20 Commits

Author SHA1 Message Date
guanj
eb72146e0d 提交代码 2026-04-25 15:22:50 +08:00
guanj
ce78b65875 提交代码 2026-04-24 09:13:17 +08:00
guanj
747d3139cf 调整app页面图标样式 2026-04-17 08:50:07 +08:00
guanj
bac0f83f64 提交app 2026-04-13 10:12:04 +08:00
guanj
db097bc64a 调整消息推送 2026-04-03 14:48:45 +08:00
guanj
9f593bd428 1 2026-04-01 10:00:55 +08:00
guanj
966d6d342c 提交app代码 2026-04-01 10:00:04 +08:00
guanj
66cee2922d 联调app 2026-03-30 08:43:13 +08:00
guanj
00e34c168f 提交app 2026-03-17 14:00:55 +08:00
guanj
b71200cb97 修改问题 2026-01-23 15:46:43 +08:00
guanj
82f8c366c9 微调 2025-08-22 15:54:57 +08:00
guanj
1231a39e87 修改报错 2025-08-19 10:21:12 +08:00
guanj
67ea86015a 添加时间 2025-08-19 09:50:23 +08:00
guanj
127adcd524 提交 2025-08-13 20:45:10 +08:00
guanj
c387cc9589 去除高德定位 2025-08-13 10:42:31 +08:00
guanj
032eed6768 app添加状态 2025-07-18 13:29:43 +08:00
guanj
998d017f5b 状态更具用户判断显示 2025-07-15 16:31:43 +08:00
guanj
4a0aa6472f App端添加治理模块主动询问状态功能; 2025-07-08 08:45:03 +08:00
GGJ
b32cb0b11f 修改app测试问题 2024-11-06 11:19:28 +08:00
GGJ
26066db3fd 修改 测试问题 2024-11-06 09:17:49 +08:00
147 changed files with 25862 additions and 11635 deletions

View File

@@ -0,0 +1,7 @@
---
name: New prompt
description: New prompt
invokable: true
---
Please write a thorough suite of unit tests for this code, making sure to cover all relevant edge cases

View File

@@ -0,0 +1,5 @@
---
description: A description of your rule
---
请用中文回答!

27
App.vue
View File

@@ -1,9 +1,11 @@
<script> <script>
import { queryDictDataCache } from './common/api/dictionary.js' import { queryDictDataCache } from './common/api/dictionary.js'
import { getImageUrl } from '@/common/api/basic' import { getImageUrl } from '@/common/api/basic'
import { checkAppUpdate } from './common/js/update.js'
export default { export default {
onLaunch: function () { onLaunch: function () {
checkAppUpdate()
// uni.onPushMessage((res) => { // uni.onPushMessage((res) => {
// console.log("收到推送消息:",res) //监听推送消息 // console.log("收到推送消息:",res) //监听推送消息
// }) // })
@@ -22,21 +24,38 @@ export default {
uni.onPushMessage((res) => { uni.onPushMessage((res) => {
console.log('收到推送消息:', res.data.payload.path) //监听推送消息 console.log('收到推送消息:', res.data.payload.path) //监听推送消息
if (res.data.payload && res.data.payload.path) { if (res.data.payload && res.data.payload.path) {
uni.navigateTo({ uni.setStorageSync('messageParams', {
engineeringName: '',
engineeringId: '', //工程ID
projectName: '',
projectId: '', //項目ID
deviceName: '',
deviceId: '', //设备ID
lineName: '',
lineId: '', //测点ID
type: res.data.payload.path.split('type=')[1],
})
uni.switchTab({
url: res.data.payload.path, url: res.data.payload.path,
}) })
// uni.navigateTo({
// url: res.data.payload.path,
// })
} }
}) })
}, },
onHide: function () { onHide: function () {
console.log('App Hide') console.log('App Hide')
}, },
methods: {},
} }
</script> </script>
<style lang="scss"> <style lang="scss">
/*每个页面公共css */ /*每个页面公共css */
@import './common/css/base.scss'; @import './common/css/base.scss';
@import '@/static/iconfont/iconfont.css';
/deep/ uni-tabbar .uni-tabbar__badge { /deep/ uni-tabbar .uni-tabbar__badge {
width: auto; width: auto;
@@ -47,4 +66,10 @@ export default {
font-size: 20rpx; font-size: 20rpx;
padding: 0 8rpx; padding: 0 8rpx;
} }
// .uni-page-refresh__path {
// stroke: #007aff !important; /* 改成你想要的颜色,比如红色 #ff0000 */
// }
// .uni-page-refresh__icon {
// fill: #007aff !important; /* 改成你想要的颜色,比如红色 #ff0000 */
// }
</style> </style>

10
changelog.md Normal file
View File

@@ -0,0 +1,10 @@
# 更新日志
## 1.0.0 (2025-10-15)
- 初始版本发布
- 实现字母索引列表功能
- 支持按拼音首字母分组展示数据
- 集成右侧快速字母导航功能
- 添加滚动监听和高亮显示当前字母
- 支持签到状态显示和补签操作
- 优化空数据状态展示

View File

@@ -1,197 +1,242 @@
import request from '../js/request' import request from '../js/request'
import config from '../js/config'
// 获取设备
// 获取设备 export function getDeviceList(params) {
export function getDeviceList(params) { return request({
return request({ url: '/cs-device-boot/EquipmentDelivery/queryEquipmentByProject',
url: '/cs-device-boot/EquipmentDelivery/queryEquipmentByProject', method: 'post',
method: 'post', data: params,
data: params, })
}) }
}
/**
/** * 设备统计
* 设备统计 * @param {*} id 工程id
* @param {*} id 工程id * @returns
* @returns */
*/ const date = new Date()
export function getDevCount(id) { const year = date.getFullYear() // 年份 4 位
return request({ const month = (date.getMonth() + 1).toString().padStart(2, '0') // 月份自动补 0
url: '/cs-device-boot/deviceUser/devCount', const currentYearMonth = `${year}-${month}`
method: 'post', export function getDevCount(id) {
return request({
data: { id }, url: '/cs-device-boot/deviceUser/devCount',
}) method: 'post',
} data: { id: id, time: currentYearMonth },
})
// 获取直连设备模板信息 }
export function getModel(nDid) {
return request({ // 获取直连设备模板信息
url: '/access-boot/device/model', export function getModel(nDid) {
method: 'post', return request({
data: { url: '/access-boot/device/model',
nDid, method: 'post',
}, data: {
}) nDid,
} },
})
// 直连设备接入 }
export function addDevice(params) {
return request({ // 直连设备接入
url: '/access-boot/device/access', export function addDevice(params) {
method: 'post', return request({
header: { url: '/access-boot/device/access',
'Content-Type': 'application/json', method: 'post',
}, header: {
data: params, 'Content-Type': 'application/json',
}) },
} data: params,
})
// 直连设备注册 }
export function registerDevice(nDid, type) {
return request({ // 直连设备注册
url: '/access-boot/device/register', export function registerDevice(nDid, type) {
method: 'post', return request({
data: { url: '/access-boot/device/register',
nDid, method: 'post',
type, data: {
}, nDid,
}) type,
} },
})
// 查询拓扑图模板 }
export const getTopoTemplate = () => {
return request({ // 查询拓扑图模板
url: '/cs-device-boot/topologyTemplate/queryImage', export const getTopoTemplate = () => {
method: 'POST', return request({
}) url: '/cs-device-boot/topologyTemplate/queryImage',
} method: 'POST',
})
// 查询拓扑图模板监测点 }
export const queryByTopoId = (id) => {
return request({ // 查询拓扑图模板监测点
url: '/cs-device-boot/lineTemplate/queryByTopoId', export const queryByTopoId = (id) => {
method: 'POST', return request({
data: { url: '/cs-device-boot/lineTemplate/queryByTopoId',
topoId: id, method: 'POST',
}, data: {
}) topoId: id,
} },
// 查询设备拓扑图 })
export const queryTopologyDiagram = (devId) => { }
return request({ // 查询设备拓扑图
url: '/cs-device-boot/lineTopologyDiagram/queryTopologyDiagram', export const queryTopologyDiagram = (devId) => {
method: 'POST', return request({
data: { url: '/cs-device-boot/lineTopologyDiagram/queryTopologyDiagram',
devId, method: 'POST',
}, data: {
}) devId,
} },
})
// 设备扫码移交 }
export const transferDevice = (id, userId) => { // 设备扫码移交
return request({
url: '/cs-device-boot/deviceUser/transfer', export const transferDevice = (id, userId) => {
method: 'POST', return request({
data: { url: '/cs-device-boot/deviceUser/transfer',
ids: id, method: 'POST',
userId: userId || uni.getStorageSync('userInfo').userIndex, data: {
}, ids: id,
}) userId: userId || uni.getStorageSync('userInfo').userIndex,
} },
// 设备扫码分享 })
}
export const shareDevice = (id, userId) => { // 设备扫码分享
return request({
url: '/cs-device-boot/deviceUser/share', export const shareDevice = (id, userId) => {
method: 'POST', return request({
data: { url: '/cs-device-boot/deviceUser/share',
ids: id, method: 'POST',
}, data: {
}) ids: id,
} },
})
// 设备删除 }
export const deleteDevice = (id) => { // 设备删除
return request({
url: '/cs-device-boot/deviceUser/delete', export const deleteDevice = (id) => {
method: 'POST', return request({
data: { url: '/cs-device-boot/deviceUser/delete',
eid: id, method: 'POST',
}, data: {
}) eid: id,
} },
})
// 设备查询通过id获取 }
export const queryDeivceById = (id) => {
return request({ // 设备查询通过id获取
url: '/cs-device-boot/EquipmentDelivery/queryEquipmentById', export const queryDeivceById = (id) => {
method: 'POST', return request({
data: { url: '/cs-device-boot/EquipmentDelivery/queryEquipmentById',
ids: id, method: 'POST',
}, data: {
}) ids: id,
} },
})
// 字典树接口通过id }
export const queryByid = (id) => {
return request({ // 字典树接口通过id
url: '/system-boot/dictTree/queryByid', export const queryByid = (id) => {
method: 'post', return request({
data: { url: '/system-boot/dictTree/queryByid',
id, method: 'post',
}, data: {
}) id,
} },
})
//设备修改监测点信息 }
export const updateDevice = (params) => {
return request({ //设备修改监测点信息
url: '/cs-device-boot/lineTopologyDiagram/auditList', export const updateDevice = (params) => {
method: 'POST', return request({
header: { url: '/cs-device-boot/lineTopologyDiagram/auditList',
'Content-Type': 'application/json', method: 'POST',
}, header: {
data: params, 'Content-Type': 'application/json',
}) },
} data: params,
})
// 设备用户列表 }
export const queryDeviceUser = (devId) => {
return request({ // 设备用户列表
url: '/cs-device-boot/deviceUser/queryUserById', export const queryDeviceUser = (devId) => {
method: 'POST', return request({
data: { url: '/cs-device-boot/deviceUser/queryUserById',
devId, method: 'POST',
}, data: {
}) devId,
} },
})
// 取消分享 }
export const cancelShare = (params) => {
return request({ // 取消分享
url: '/cs-device-boot/deviceUser/cancelShare', export const cancelShare = (params) => {
method: 'POST', return request({
data: params, url: '/cs-device-boot/deviceUser/cancelShare',
}) method: 'POST',
} data: params,
})
// 取消调试 }
export const cancelDebug = (params) => {
return request({ // 取消调试
url: '/cs-device-boot/EquipmentDelivery/deleteTest', export const cancelDebug = (params) => {
method: 'POST', return request({
data: params, url: '/cs-device-boot/EquipmentDelivery/deleteTest',
}) method: 'POST',
} data: params,
})
// 完成调试 }
export const finishDebug = (params) => {
return request({ // 完成调试
url: '/cs-device-boot/EquipmentDelivery/testcompletion', export const finishDebug = (params) => {
method: 'POST', return request({
data: params, url: '/cs-device-boot/EquipmentDelivery/testcompletion',
}) method: 'POST',
} data: params,
})
}
// 置顶设备、工程
export const engineeringPinToTop = (params) => {
return request({
url: '/cs-device-boot/csUserPins/engineeringPinToTop',
method: 'POST',
data: params,
header: {
'Content-Type': 'application/json',
},
})
}
// 查询工程树
export const lineTree = (params) => {
return request({
url: '/cs-device-boot/csLedger/AppLineTree',
method: 'POST',
// data: {
// type: 'engineering',
// },
// header: {
// 'Content-Type': 'application/json',
// },
})
}
// 查询工程
export const queryEngineeringPage = (params) => {
return request({
url: '/cs-device-boot/engineering/queryEngineeringPage',
method: 'POST',
data: params,
header: {
'Content-Type': 'application/json',
},
})
}
// 通过ndid查询出厂设备
export const queryEquipmentByndid = (params) => {
return request({
url: '/cs-device-boot/EquipmentDelivery/queryEquipmentByndid',
method: 'POST',
data: params,
})
}

49
common/api/harmonic.js Normal file
View File

@@ -0,0 +1,49 @@
import request from '../js/request'
// apf-》获取模块状态
export function getModuleState(params) {
return request({
url: '/cs-harmonic-boot/data/getModuleState',
method: 'post',
data: params,
})
}
export function getBaseRealData(id) {
return request({
url: '/cs-harmonic-boot/realData/getBaseRealData?lineId='+id,
method: 'post',
})
}
// 查询App暂态事件总数
export function queryAppEventCounts(params) {
return request({
url: '/cs-harmonic-boot/eventUser/queryAppEventCounts',
method: 'post',
data: params,
header: {
'Content-Type': 'application/json',
},
})
}
// 查询App稳态事件总数
export function queryAppHarmonicCounts(params) {
return request({
url: '/cs-harmonic-boot/csHarmonic/queryAppHarmonicCounts',
method: 'post',
data: params,
header: {
'Content-Type': 'application/json',
},
})
}
// 查询App稳态越限监测点
export function queryAppHarmonicLine(params) {
return request({
url: '/cs-harmonic-boot/csHarmonic/queryAppHarmonicLine',
method: 'post',
data: params,
header: {
'Content-Type': 'application/json',
},
})
}

View File

@@ -1,17 +1,45 @@
import request from '../js/request'; import request from '../js/request';
import config from '../js/config'; import config from '../js/config';
/** /**
* 已读暂态 * 已读暂态
* @returns {*} * @returns {*}
*/ */
export function updateStatus(params) { export function updateStatus(params) {
return request({ return request({
url: '/cs-harmonic-boot/eventUser/updateStatus', url: '/cs-harmonic-boot/eventUser/updateStatus',
method: 'post', method: 'post',
header: { header: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
data: params, data: params,
}) })
} }
/**
* 稳态详情
* @returns {*}
*/
export function queryHarmonicDetail(params) {
return request({
url: '/cs-harmonic-boot/csHarmonic/queryHarmonicDetail',
method: 'post',
header: {
'Content-Type': 'application/json',
},
data: params,
})
}
/**
* 运行告警事件详
* @returns {*}
*/
export function queryAlarmDetail(params) {
return request({
url: '/cs-harmonic-boot/csAlarm/queryAlarmDetail',
method: 'post',
header: {
'Content-Type': 'application/json',
},
data: params,
})
}

View File

@@ -1,128 +1,128 @@
import request from '../js/request' import request from '../js/request'
import config from '../js/config' import config from '../js/config'
export function addAppProject(params, files) { export function addAppProject(params, files) {
if (files.length === 0) { if (files.length === 0) {
return request({ return request({
url: '/cs-device-boot/project/addAppProject', url: '/cs-device-boot/project/addAppProject',
method: 'post', method: 'post',
data: params, data: params,
}) })
} else { } else {
return uni.uploadFile({ return uni.uploadFile({
url: config.domain + '/cs-device-boot/project/addAppProject', //仅为示例,非真实的接口地址 url: config.domain + '/cs-device-boot/project/addAppProject', //仅为示例,非真实的接口地址
files: files, files: files,
header: { header: {
Authorization: uni.getStorageSync('access_token'), Authorization: uni.getStorageSync('access_token'),
}, },
formData: params, formData: params,
}) })
} }
} }
// 修改项目 // 修改项目
export function updateAppProject(params, files) { export function updateAppProject(params, files) {
if (files.length === 0) { if (files.length === 0) {
return request({ return request({
url: '/cs-device-boot/project/auditAppProject', url: '/cs-device-boot/project/auditAppProject',
method: 'post', method: 'post',
data: params, data: params,
}) })
} else { } else {
return uni.uploadFile({ return uni.uploadFile({
url: config.domain + '/cs-device-boot/project/auditAppProject', //仅为示例,非真实的接口地址 url: config.domain + '/cs-device-boot/project/auditAppProject', //仅为示例,非真实的接口地址
files: files, files: files,
header: { header: {
Authorization: uni.getStorageSync('access_token'), Authorization: uni.getStorageSync('access_token'),
}, },
formData: params, formData: params,
}) })
} }
} }
export function getProjectList(params) { export function getProjectList(params) {
return request({ return request({
url: '/cs-device-boot/project/queryProject', url: '/cs-device-boot/project/queryProject',
method: 'post', method: 'post',
data: params, data: params,
header: { header: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
}) })
} }
// 删除项目 // 删除项目
export function deleteProject(id) { export function deleteProject(id) {
return request({ return request({
url: '/cs-device-boot/project/auditAppProject', url: '/cs-device-boot/project/auditAppProject',
method: 'post', method: 'post',
data: { data: {
id, id,
status: 0, status: 0,
}, },
}) })
} }
// 查询拓扑图 // 查询拓扑图
export function queryTopologyDiagramPage(params) { export function queryTopologyDiagramPage(params) {
return request({ return request({
url: '/cs-device-boot/topologyDiagram/queryTopologyDiagramPage', url: '/cs-device-boot/topologyDiagram/queryTopologyDiagramPage',
method: 'post', method: 'post',
data: Object.assign( data: Object.assign(
{ {
pageNum: 1, pageNum: 1,
pageSize: 999, pageSize: 999,
projectId: '', projectId: '',
searchValue: '', searchValue: '',
}, },
params, params,
), ),
header: { header: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
}) })
} }
// 删除拓扑图 // 删除拓扑图
export function deleteAppTopologyDiagram(id) { export function deleteAppTopologyDiagram(id) {
return request({ return request({
url: '/cs-device-boot/topologyDiagram/AuditAppTopologyDiagram', url: '/cs-device-boot/topologyDiagram/AuditAppTopologyDiagram',
method: 'post', method: 'post',
data: { data: {
id, id,
status: 0, status: 0,
}, },
}) })
} }
// 删除拓扑图 // 删除拓扑图
export function checkCanDelete(id) { export function checkCanDelete(id) {
return request({ return request({
url: '/cs-device-boot/topologyDiagram/checkCanDelete', url: '/cs-device-boot/topologyDiagram/checkCanDelete',
method: 'post', method: 'post',
data: { data: {
id, id,
}, },
}) })
} }
// 新增拓扑图 // 新增拓扑图
export function addAppTopologyDiagram(params, filePath) { export function addAppTopologyDiagram(params, filePath) {
return uni.uploadFile({ return uni.uploadFile({
url: config.domain + '/cs-device-boot/topologyDiagram/addAppTopologyDiagram', //仅为示例,非真实的接口地址 url: config.domain + '/cs-device-boot/topologyDiagram/addAppTopologyDiagram', //仅为示例,非真实的接口地址
filePath, filePath,
name: 'file', name: 'file',
header: { header: {
Authorization: uni.getStorageSync('access_token'), Authorization: uni.getStorageSync('access_token'),
}, },
formData: Object.assign( formData: Object.assign(
{ {
topologyDiagramName: '', topologyDiagramName: '',
projectId: '', projectId: '',
}, },
params, params,
), ),
}) })
} }

40
common/api/report.js Normal file
View File

@@ -0,0 +1,40 @@
import request from '../js/request'
// 下载稳态报告
export function downloadHarmonicReport(data) {
return request({
url: '/cs-report-boot/csAppReport/downloadHarmonicReport',
method: 'post',
data,
header: {
'Content-Type': 'application/json',
},
})
}
// 申请暂态报告
export function applicationReport(data) {
return request({
url: '/cs-report-boot/csAppReport/applicationReport',
method: 'post',
data,
header: {
'Content-Type': 'application/json',
},
})
}
// 生成暂态报告
export function createEventReport(params) {
return request({
url: '/cs-report-boot/csAppReport/createEventReport',
method: 'post',
params,
})
}
// 下载暂态报告
export function downloadEventReport(params) {
return request({
url: '/cs-report-boot/csAppReport/downloadEventReport',
method: 'post',
params,
})
}

View File

@@ -1,238 +1,245 @@
import request from '../js/request' import request from '../js/request'
/** /**
* 发送验证码 * 发送验证码
* @param {*} params.type 0:登录 1:注册 2:修改密码 6:忘记密码 4:更换手机号第二步获取验证码 5:更换手机号第一步获取验证码 * @param {*} params.type 0:登录 1:注册 2:修改密码 6:忘记密码 4:更换手机号第二步获取验证码 5:更换手机号第一步获取验证码
* @returns * @returns
*/ */
export function apiGetYms(params) { export function apiGetYms(params) {
return request({ return request({
url: '/user-boot/appUser/authCode', url: '/user-boot/appUser/authCode',
data: { data: {
phone: params.phone, phone: params.phone,
devCode: uni.getStorageSync('devCode'), devCode: uni.getStorageSync('devCode'),
type: params.type, type: params.type,
}, },
method: 'POST', method: 'POST',
}) })
} }
/** /**
* 登录 * 登录
* @param {*} params.type 0:ysm 1:pwd * @param {*} params.type 0:ysm 1:pwd
* @returns * @returns
*/ */
export function apiLogin(params) { export function apiLogin(params) {
console.log(uni.getStorageSync('devCode')) console.log(uni.getStorageSync('devCode'))
return request({ return request({
url: '/shiningCloud/user/login', url: '/shiningCloud/user/login',
data: { data: {
phone: params.phone, phone: params.phone,
devCode: uni.getStorageSync('devCode'), devCode: uni.getStorageSync('devCode'),
key: params.key.trim(), key: params.key.trim(),
type: params.type, type: params.type,
}, },
method: 'POST', method: 'POST',
}) })
} }
/** /**
* 验证码登录 * 验证码登录
* @param {*} params.type 0:ysm 1:pwd * @param {*} params.type 0:ysm 1:pwd
* @returns * @returns
*/ */
export function apiYsmLogin(params) { export function apiYsmLogin(params) {
uni.setStorageSync('access_token', 'Basic bmpjbmFwcDpuamNucHFz') uni.setStorageSync('access_token', 'Basic bmpjbmFwcDpuamNucHFz')
return request({ return request({
url: '/pqs-auth/oauth/token', url: '/pqs-auth/oauth/token',
data: { data: {
grant_type: 'sms_code', grant_type: 'sms_code',
phone: params.phone, phone: params.phone,
smsCode: params.smsCode.trim(), smsCode: params.smsCode.trim(),
}, },
method: 'POST', method: 'POST',
}) })
} }
/** /**
* 注册 * 注册
* @param {*} params * @param {*} params
* @returns * @returns
*/ */
export function apiRegister(params) { export function apiRegister(params) {
return request({ return request({
url: '/user-boot/appUser/register', url: '/user-boot/appUser/register',
data: { data: {
phone: params.phone, phone: params.phone,
devCode: uni.getStorageSync('devCode'), devCode: uni.getStorageSync('devCode'),
code: params.code.trim(), code: params.code.trim(),
}, },
method: 'POST', method: 'POST',
}) })
} }
/** /**
* app用户注册完自动登录 * app用户注册完自动登录
* @param params * @param params
* @returns {*} * @returns {*}
*/ */
export function autoLogin(phone) { export function autoLogin(phone) {
return request({ return request({
url: '/pqs-auth/oauth/autoLogin', url: '/pqs-auth/oauth/autoLogin',
data: { data: {
phone: phone, phone: phone,
}, },
method: 'POST', method: 'POST',
}) })
} }
// 第一次登录设置密码 // 第一次登录设置密码
export function apiSetPsd(params) { export function apiSetPsd(params) {
return request({ return request({
url: '/shiningCloud/user/setPsd', url: '/shiningCloud/user/setPsd',
data: { data: {
userId: uni.getStorageSync('userInfo').userIndex, userId: uni.getStorageSync('userInfo').userIndex,
devCode: uni.getStorageSync('devCode'), devCode: uni.getStorageSync('devCode'),
password: params.password.trim(), password: params.password.trim(),
}, },
method: 'POST', method: 'POST',
}) })
} }
// 重置密码 // 重置密码
export function apiReSetPsd(params) { export function apiReSetPsd(params) {
return request({ return request({
url: '/user-boot/appUser/resetPsd', url: '/user-boot/appUser/resetPsd',
data: { data: {
phone: params.phone, phone: params.phone,
code: params.code.trim(), code: params.code.trim(),
devCode: uni.getStorageSync('devCode'), devCode: uni.getStorageSync('devCode'),
password: params.password.trim(), password: params.password.trim(),
}, },
method: 'POST', method: 'POST',
}) })
} }
// 更换手机号第一步 // 更换手机号第一步
export function apiComfirmCode(params) { export function apiComfirmCode(params) {
return request({ return request({
url: '/user-boot/appUser/confirmCode', url: '/user-boot/appUser/confirmCode',
data: { data: {
devCode: uni.getStorageSync('devCode'), devCode: uni.getStorageSync('devCode'),
phone: params.phone, phone: params.phone,
code: params.code.trim(), code: params.code.trim(),
}, },
method: 'POST', method: 'POST',
}) })
} }
// 重新绑定手机号 // 重新绑定手机号
export function apiRebindPhone(params) { export function apiRebindPhone(params) {
return request({ return request({
url: '/user-boot/appUser/rebindPhone', url: '/user-boot/appUser/rebindPhone',
data: { data: {
devCode: uni.getStorageSync('devCode'), devCode: uni.getStorageSync('devCode'),
userId: uni.getStorageSync('userInfo').userIndex, userId: uni.getStorageSync('userInfo').userIndex,
phoneNew: params.phone, phoneNew: params.phone,
code: params.code.trim(), code: params.code.trim(),
}, },
method: 'POST', method: 'POST',
}) })
} }
// 角色升级 // 角色升级
export function roleUpdate({ userId, referralCode }) { export function roleUpdate({ userId, referralCode }) {
return request({ return request({
url: '/user-boot/appRole/roleUpdate', url: '/user-boot/appRole/roleUpdate',
method: 'post', method: 'post',
data: { data: {
devCode: uni.getStorageSync('devCode'), devCode: uni.getStorageSync('devCode'),
referralCode, referralCode,
userId, userId,
}, },
}) })
} }
// 密码登录 // 密码登录
export function apiPwdLogin(params) { export function apiPwdLogin(params) {
return request({ return request({
url: '/pqs-auth/oauth/token', url: '/pqs-auth/oauth/token',
header: { header: {
Authorization: 'Basic bmpjbnRlc3Q6bmpjbnBxcw==', // 客户端信息加密摘要认证 Authorization: 'Basic bmpjbnRlc3Q6bmpjbnBxcw==', // 客户端信息加密摘要认证
}, },
params, params,
method: 'POST', method: 'POST',
}) })
} }
//登录获取公钥 //登录获取公钥
export function gongkey(data) { export function gongkey(data) {
console.log(data) console.log(data)
return request({ return request({
url: '/user-boot/user/generateSm2Key', url: '/user-boot/user/generateSm2Key',
method: 'get', method: 'get',
data: data, data: data,
}) })
} }
// 修改手机号 // 修改手机号
export function apiModifyPsd(params) { export function apiModifyPsd(params) {
return request({ return request({
url: '/user-boot/appUser/modifyPsd', url: '/user-boot/appUser/modifyPsd',
data: { data: {
devCode: uni.getStorageSync('devCode'), devCode: uni.getStorageSync('devCode'),
userId: uni.getStorageSync('userInfo').userIndex, userId: uni.getStorageSync('userInfo').userIndex,
phone: params.phone, phone: params.phone,
password: params.password.trim(), password: params.password.trim(),
code: params.code.trim(), code: params.code.trim(),
}, },
method: 'POST', method: 'POST',
}) })
} }
// 更改用户信息 // 更改用户信息
export function apiUpdateUser(params) { export function apiUpdateUser(params) {
return request({ return request({
url: '/user-boot/user/updateAppUser', url: '/user-boot/user/updateAppUser',
data: { data: {
...params, ...params,
}, },
header: { header: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
method: 'PUT', method: 'PUT',
}) })
} }
// 更改用户信息 // 更改用户信息
export function apiDeleteUser(params) { export function apiDeleteUser(params) {
return request({ return request({
url: '/user-boot/user/delete', url: '/user-boot/user/delete',
data: { data: {
id: uni.getStorageSync('userInfo').userIndex, id: uni.getStorageSync('userInfo').userIndex,
}, },
method: 'DELETE', method: 'DELETE',
}) })
} }
// 更新用户推送标识 // 更新用户推送标识
export function apiUpdatePush(params) { export function apiUpdatePush(params) {
uni.getPushClientId({ uni.getPushClientId({
success: (res) => { success: (res) => {
console.log('🚀 ~ apiUpdatePush111 ~ res:', res) console.log('🚀 ~ apiUpdatePush111 ~ res:', res)
let push_clientid = res.cid let push_clientid = res.cid
console.log(push_clientid, 'push_clientid') console.log(push_clientid, 'push_clientid')
request({ request({
url: '/user-boot/appUser/updateDevCode', url: '/user-boot/appUser/updateDevCode',
data: { data: {
devCode: push_clientid, devCode: push_clientid,
userId: uni.getStorageSync('userInfo').userIndex, userId: uni.getStorageSync('userInfo').userIndex,
}, },
method: 'POST', method: 'POST',
}) })
}, },
fail(err) { fail(err) {
console.log('🚀 ~ apiUpdatePush222 ~ res:', err) console.log('🚀 ~ apiUpdatePush222 ~ res:', err)
}, },
}) })
} }
// 获取当前版本号
export function getLastData() {
return request({
url: '/cs-system-boot/appVersion/getLastData?versionType=APP',
method: 'POST',
})
}

View File

@@ -1,287 +1,311 @@
page { page {
background: #f3f4f5; background: #f3f4f5;
} }
// mt0,mr0,mb0,ml0 --> mt100,mr100,mb100,ml100 // mt0,mr0,mb0,ml0 --> mt100,mr100,mb100,ml100
@for $i from 0 through 100 { @for $i from 0 through 100 {
.mt#{$i} { .mt#{$i} {
margin-top: #{$i}rpx; margin-top: #{$i}rpx;
} }
.mr#{$i} { .mr#{$i} {
margin-right: #{$i}rpx; margin-right: #{$i}rpx;
} }
.mb#{$i} { .mb#{$i} {
margin-bottom: #{$i}rpx; margin-bottom: #{$i}rpx;
} }
.ml#{$i} { .ml#{$i} {
margin-left: #{$i}rpx; margin-left: #{$i}rpx;
} }
.pt#{$i} { .pt#{$i} {
padding-top: #{$i}rpx; padding-top: #{$i}rpx;
} }
.pr#{$i} { .pr#{$i} {
padding-right: #{$i}rpx; padding-right: #{$i}rpx;
} }
.pb#{$i} { .pb#{$i} {
padding-bottom: #{$i}rpx; padding-bottom: #{$i}rpx;
} }
.pl#{$i} { .pl#{$i} {
padding-left: #{$i}rpx; padding-left: #{$i}rpx;
} }
} .pd#{$i} {
padding: #{$i}rpx;
.center { }
display: flex; }
align-items: center;
justify-content: center; .center {
} display: flex;
align-items: center;
.space-between { justify-content: center;
display: flex; }
justify-content: space-between;
} .space-between {
display: flex;
.hide-txt { justify-content: space-between;
overflow-x: hidden; }
white-space: nowrap;
text-overflow: ellipsis; .hide-txt {
word-break: break-all; overflow-x: hidden;
-webkit-line-clamp: 1; white-space: nowrap;
} text-overflow: ellipsis;
word-break: break-all;
.clamp-txt { -webkit-line-clamp: 1;
overflow: hidden; }
display: -webkit-box;
-webkit-box-orient: vertical; .clamp-txt {
-webkit-line-clamp: 2; overflow: hidden;
word-break: break-all; display: -webkit-box;
} -webkit-box-orient: vertical;
-webkit-line-clamp: 2;
.fixed-btn { word-break: break-all;
position: fixed; }
right: 80rpx;
bottom: 200rpx; .fixed-btn {
width: 126rpx; position: fixed;
height: 126rpx; right: 80rpx;
background: $uni-theme-white; bottom: 200rpx;
border-radius: 50%; width: 126rpx;
display: flex; height: 126rpx;
align-items: center; background: $uni-theme-white;
justify-content: center; border-radius: 50%;
box-shadow: 0 0 10rpx rgba(0, 0, 0, 0.2); display: flex;
align-items: center;
image { justify-content: center;
height: 66rpx; box-shadow: 0 0 10rpx rgba(0, 0, 0, 0.2);
width: 66rpx;
} image {
} height: 66rpx;
width: 66rpx;
.grid-card { }
border-radius: 12rpx; }
margin-bottom: 20rpx;
.grid-card {
.grid-card-title { border-radius: 12rpx;
padding: 0 0 20rpx; margin-bottom: 20rpx;
font-size: 28rpx;
color: #111; .grid-card-title {
font-weight: 700; padding: 0 0 20rpx;
} font-size: 28rpx;
color: #111;
.grid-card-content-4, font-weight: 700;
.grid-card-content-2, }
.grid-card-content-1,
.grid-card-content-3, .grid-card-content-4,
.grid-card-content-5, .grid-card-content-2,
.grid-card-content-6 { .grid-card-content-1,
display: grid; .grid-card-content-3,
border-left: 2rpx solid #ccc; .grid-card-content-5,
border-top: 2rpx solid #ccc; .grid-card-content-6 {
font-size: 24rpx; display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr; border-left: 2rpx solid #ccc;
border-top: 2rpx solid #ccc;
.item { font-size: 24rpx;
padding: 0 4rpx; grid-template-columns: 1fr 1fr 1fr 1fr;
display: flex;
align-items: center; .item {
justify-content: center; padding: 0 4rpx;
text-align: center; display: flex;
border-bottom: 2rpx solid #ccc; align-items: center;
border-right: 2rpx solid #ccc; justify-content: center;
padding: 4rpx; text-align: center;
background: $uni-theme-white; border-bottom: 2rpx solid #ccc;
} border-right: 2rpx solid #ccc;
padding: 4rpx;
.item-title { background: $uni-theme-white;
background: unset; }
padding: 8rpx 4rpx;
} .item-title {
} background: unset;
padding: 8rpx 4rpx;
.grid-card-content-1 { }
grid-template-columns: 1fr; }
}
.grid-card-content-2 { .grid-card-content-1 {
grid-template-columns: 1fr 2fr; grid-template-columns: 1fr;
} }
.grid-card-content-2 {
.grid-card-content-3 { grid-template-columns: 1fr 2fr;
grid-template-columns: 1fr 2fr 2fr; }
}
.grid-card-content-3 {
.grid-card-content-5 { grid-template-columns: 1fr 2fr 2fr;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr; }
}
.grid-card-content-5 {
.grid-card-content-6 { grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr; }
}
} .grid-card-content-6 {
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
.index { }
.header { }
margin: 0 20rpx;
display: grid; .index {
grid-gap: 20rpx; .header {
grid-template-columns: 1fr 1fr 1fr ; margin: 0 20rpx;
.header-item { display: grid;
display: flex; grid-gap: 20rpx;
flex-direction: column; grid-template-columns: 1fr 1fr 1fr;
align-items: center; .header-item {
justify-content: center; display: flex;
padding: 10rpx 10rpx 20rpx; flex-direction: column;
color: #fff; align-items: center;
font-size: 28rpx; justify-content: center;
background: $uni-theme-color; padding: 10rpx 10rpx 20rpx;
border-radius: 12rpx; color: #fff;
.header-item-value { font-size: 28rpx;
font-size: 44rpx; background: $uni-theme-color;
} border-radius: 12rpx;
.header-item-label { .header-item-value {
font-size: 24rpx; font-size: 44rpx;
} }
} .header-item-label {
} font-size: 26rpx;
} }
}
.nav { }
position: sticky; }
top: 0;
left: 0; .nav {
padding: 20rpx 20rpx 0; position: sticky;
padding-left: 0; top: 0;
display: flex; left: 0;
flex-wrap: wrap; padding: 20rpx 20rpx 0;
background: rgb(243, 244, 245); padding-left: 0;
z-index: 2; display: flex;
flex-wrap: wrap;
.nav-menu { background: rgb(243, 244, 245);
padding: 6rpx 20rpx; z-index: 2;
margin-left: 20rpx;
margin-bottom: 20rpx; .nav-menu {
font-size: 24rpx; padding: 6rpx 20rpx;
border-radius: 8rpx; margin-left: 20rpx;
background: #ebeaec; margin-bottom: 20rpx;
color: #666; font-size: 24rpx;
&-active { border-radius: 8rpx;
background: #dfe5f7; background: #ebeaec;
color: $uni-theme-color; color: #666;
} &-active {
&-btn { background: #dfe5f7;
background: $uni-theme-color; color: $uni-theme-color;
color: #fff; }
} &-btn {
} background: $uni-theme-color;
} color: #fff;
}
.btn { }
display: flex; }
align-items: center;
justify-content: center; .btn {
flex: 1; display: flex;
background: $uni-theme-color; align-items: center;
color: #fff; justify-content: center;
height: 80rpx; flex: 1;
border-radius: 12rpx; background: $uni-theme-color;
} color: #fff;
height: 80rpx;
.btn-small { border-radius: 12rpx;
display: inline-flex; }
align-items: center;
justify-content: center; .btn-small {
padding: 0 40rpx; display: inline-flex;
background: $uni-theme-color; align-items: center;
color: #fff; justify-content: center;
height: 60rpx; padding: 0 40rpx;
font-size: 24rpx; background: $uni-theme-color;
border-radius: 12rpx; color: #fff;
} height: 60rpx;
font-size: 24rpx;
.device { border-radius: 12rpx;
/deep/ .uni-card:first-of-type { }
margin-top: 0 !important;
} .device {
} /deep/ .uni-card:first-of-type {
margin-top: 0 !important;
.content { }
/deep/ .uni-forms-item:last-of-type { }
margin-bottom: 0 !important;
} .content {
position: relative; /deep/ .uni-forms-item:last-of-type {
} margin-bottom: 0 !important;
}
.status-point-success { position: relative;
display: inline-block; }
width: 16rpx;
height: 16rpx; .status-point-success {
border-radius: 50%; display: inline-block;
background: greenyellow; width: 16rpx;
overflow: hidden; height: 16rpx;
} border-radius: 50%;
background: greenyellow;
.status-point-error { overflow: hidden;
display: inline-block; }
width: 16rpx;
height: 16rpx; .status-point-error {
border-radius: 50%; display: inline-block;
background: red; width: 16rpx;
overflow: hidden; height: 16rpx;
} border-radius: 50%;
background: red;
.popup-header { overflow: hidden;
display: flex; }
align-items: center;
justify-content: space-between; .popup-header {
padding: 0 20rpx; display: flex;
height: 80rpx; align-items: center;
background: #fff; justify-content: space-between;
border-radius: 20rpx 20rpx 0 0; padding: 0 20rpx;
overflow: hidden; height: 80rpx;
border-bottom: 1px solid #eee; background: #fff;
.popup-header-title { border-radius: 20rpx 20rpx 0 0;
font-size: 32rpx; overflow: hidden;
color: #333; border-bottom: 1px solid #eee;
} .popup-header-title {
.popup-header-close { font-size: 32rpx;
font-size: 32rpx; color: #333;
color: #666; }
} .popup-header-close {
} font-size: 32rpx;
color: #666;
}
image { }
will-change: transform;//解决加载时瞬间拉伸问题
width: auto;//解决加载时瞬间拉伸问题 image {
height: auto;//解决加载时瞬间拉伸问题 will-change: transform; //解决加载时瞬间拉伸问题
image-rendering:-moz-crisp-edges; width: auto; //解决加载时瞬间拉伸问题
image-rendering:-o-crisp-edges; height: auto; //解决加载时瞬间拉伸问题
image-rendering:-webkit-optimize-contrast; image-rendering: -moz-crisp-edges;
image-rendering: crisp-edges; image-rendering: -o-crisp-edges;
-ms-interpolation-mode:nearest-neighbor; image-rendering: -webkit-optimize-contrast;
} image-rendering: crisp-edges;
-ms-interpolation-mode: nearest-neighbor;
}
.canneng-index-title {
font-size: 30rpx;
}
.boxClick:active {
// transform: scale(0.94);
// opacity: 0.8;
animation: elastic-bounce 0.5s;
}
@keyframes elastic-bounce {
0% {
transform: scale(1);
}
50% {
transform: scale(0.96);
}
100% {
transform: scale(1);
}
}

View File

@@ -1,23 +1,23 @@
const debug = false // true 是连地服务端本地false 是连接线上 const debug = true // true 是连地服务端本地false 是连接线上
const development = { const development = {
domain: 'http://192.168.1.22:10215', domain: 'http://192.168.1.103:10215',
} }
const production = { const production = {
domain: 'https://pqmcn.com:8092/api', domain: 'https://pqmcn.com:8092/api',
} }
const config = debug ? development : production const config = debug ? development : production
// #ifdef H5 // #ifdef H5
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
config.domain = '/api' config.domain = '/api'
} else { } else {
config.domain = window.location.origin config.domain = window.location.origin
} }
// #endif // #endif
config.static = config.domain + '/system-boot/file/download?filePath=' config.static = config.domain + '/system-boot/file/download?filePath='
export default config export default config

View File

@@ -1,92 +1,98 @@
export default { export default {
onPullDownRefresh() { onPullDownRefresh() {
this.store && this.store.reload() if (this.store.isListAtTop) {
}, this.store && this.store.reload()
onReachBottom() { }
if (this.store.status != 'noMore') { },
this.store.next && this.store.next() onReachBottom() {
} if (this.store.status != 'noMore') {
}, this.store.next && this.store.next()
data() { }
return { },
store: {}, data() {
} return {
}, store: {},
methods: { }
DataSource(url) { },
var me = this methods: {
return { DataSource(url) {
data: [], var me = this
status: 'noMore', return {
empty: false, data: [],
total: 0, copyData: {},
header: { status: 'noMore',
'Content-Type': 'application/json;charset=UTF-8', empty: false,
}, isListAtTop: true,
params: { total: 0,
pageNum: 1, header: {
pageSize: 20, 'Content-Type': 'application/json;charset=UTF-8',
}, },
timer: null, params: {
callBack: null, pageNum: 1,
firstCallBack: null, pageSize: 20,
loadedCallback: null, },
reload() { timer: null,
if (this.status == 'loading') return callBack: null,
this.data = [] firstCallBack: null,
this.empty = false loadedCallback: null,
this.params.pageNum = 1 reload() {
this.next() if (this.status == 'loading') return
}, this.data = []
search() { this.empty = false
// 节流搜索 this.params.pageNum = 1
clearTimeout(this.timer) this.next()
this.timer = setTimeout(() => { },
this.reload() search() {
}, 300) // 节流搜索
}, clearTimeout(this.timer)
next() { this.timer = setTimeout(() => {
this.status = 'loading' this.reload()
me.$request({ }, 300)
url: url, },
data: this.params, next() {
header: this.header, this.status = 'loading'
method: 'POST', me.$request({
debounce: false, url: url,
}).then((res) => { data: this.params,
console.warn(res) header: this.header,
let resultData = res.data?.list || res.data?.records || res.data || [] method: 'POST',
if (this.params.pageNum == 1) { debounce: false,
this.data = resultData }).then((res) => {
if (resultData.length == 0 || resultData == 0) { console.warn(res)
this.empty = true let resultData = res.data?.list || res.data?.records || res.data || []
this.status = 'noMore' this.copyData = res.data
} else if (resultData.length < this.params.pageSize) { if (this.params.pageNum == 1) {
this.status = 'noMore' this.data = resultData
} else if (res.total == resultData.length) { if (resultData.length == 0 || resultData == 0) {
this.status = 'noMore' this.empty = true
} else { this.status = 'noMore'
this.status = 'more' } else if (resultData.length < this.params.pageSize) {
} this.status = 'noMore'
} else { } else if (res.total == resultData.length) {
this.data.push(...resultData) this.status = 'noMore'
if (resultData.length < this.params.pageSize) { } else {
this.status = 'noMore' this.status = 'more'
} else { }
this.status = 'more' } else {
} this.data.push(...resultData)
} if (resultData.length < this.params.pageSize) {
if (this.params.pageNum == 1) { this.status = 'noMore'
this.firstCallBack && this.firstCallBack() } else {
} this.status = 'more'
this.loadedCallback && this.loadedCallback() }
this.params.pageNum++ }
this.total = res.total if (this.params.pageNum == 1) {
this.loading = false this.firstCallBack && this.firstCallBack()
uni.stopPullDownRefresh() }
}) this.loadedCallback && this.loadedCallback()
}, this.params.pageNum++
} this.total = res.total || res.data?.total
},
}, this.loading = false
} uni.stopPullDownRefresh()
})
},
}
},
},
}

View File

@@ -1,14 +1,14 @@
// export const MQTT_IP = '192.168.1.24:10215/mqtt'//mqtt地址端口, 使用emqx时一定要加mqtt // export const MQTT_IP = 'pqmcn.com:8085/mqtt'//mqtt地址端口, 使用emqx时一定要加mqtt
export const MQTT_IP = 'pqmcn.com:8085/mqtt'//mqtt地址端口, 使用emqx时一定要加mqtt export const MQTT_IP = '192.168.1.103:8083/mqtt'//mqtt地址端口, 使用emqx时一定要加mqtt
const MQTT_USERNAME = 't_user'//mqtt用户名 const MQTT_USERNAME = 't_user'//mqtt用户名
const MQTT_PASSWORD = 'njcnpqs'//密码 const MQTT_PASSWORD = 'njcnpqs'//密码
export const MQTT_OPTIONS = { export const MQTT_OPTIONS = {
connectTimeout: 5000, connectTimeout: 5000,
clientId: '', clientId: '',
username: MQTT_USERNAME, username: MQTT_USERNAME,
password: MQTT_PASSWORD, password: MQTT_PASSWORD,
clean: false, clean: false,
Qos: 1, Qos: 1,
} }

View File

@@ -1,92 +1,92 @@
import config from './config' import config from './config'
import Qs from 'qs' import Qs from 'qs'
let arr = [] let arr = []
export default (options = {}) => { export default (options = {}) => {
if (options.data == undefined) { if (options.data == undefined) {
options.data = {} options.data = {}
} }
options.debounce = options.debounce === undefined ? true : options.debounce options.debounce = options.debounce === undefined ? true : options.debounce
// 防止接口重复点击 // 防止接口重复点击
if (options.debounce) { if (options.debounce) {
if (arr.indexOf(options.url) === -1) { if (arr.indexOf(options.url) === -1) {
arr.push(options.url) arr.push(options.url)
} else { } else {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
reject({ reject({
code: -1, code: -1,
msg: '请勿重复提交', msg: '请勿重复提交',
data: options.url, data: options.url,
}) })
}) })
} }
} }
return new Promise((reslove, reject) => { return new Promise((reslove, reject) => {
let url = options.url.indexOf('http') === -1 ? config.domain + options.url : options.url let url = options.url.indexOf('http') === -1 ? config.domain + options.url : options.url
if (options.params) { if (options.params) {
url = url + '?' + Qs.stringify(options.params) url = url + '?' + Qs.stringify(options.params)
} }
uni.request({ uni.request({
url, url,
timeout: 1000 *10, timeout: 1000 * 60,
data: { data: {
...options.data, ...options.data,
}, },
header: { header: {
// 'Content-Type': 'application/json;charset=UTF-8', // 'Content-Type': 'application/json;charset=UTF-8',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
Authorization: uni.getStorageSync('access_token'), Authorization: uni.getStorageSync('access_token'),
...options.header, ...options.header,
}, },
method: options.method || 'GET', method: options.method || 'GET',
success: async (res) => { success: async (res) => {
console.log(res) // console.log(res)
if (arr.indexOf(options.url) > -1) { if (arr.indexOf(options.url) > -1) {
setTimeout(() => { setTimeout(() => {
arr.splice(arr.indexOf(options.url), 1) arr.splice(arr.indexOf(options.url), 1)
}, 500) }, 500)
} }
if (res.data.resultCode !== 10000 && res.data.code !== 'A0000') { if (res.data.resultCode !== 10000 && res.data.code !== 'A0000') {
errHandler(res.data) errHandler(res.data)
reject(res.data) reject(res.data)
} else { } else {
reslove(res.data) reslove(res.data)
} }
}, },
fail: (err) => { fail: (err) => {
if (arr.indexOf(options.url) > -1) { if (arr.indexOf(options.url) > -1) {
setTimeout(() => { setTimeout(() => {
arr.splice(arr.indexOf(options.url), 1) arr.splice(arr.indexOf(options.url), 1)
}, 500) }, 500)
} }
reject(err) reject(err)
uni.showToast({ uni.showToast({
icon: 'none', icon: 'none',
title: '网络异常,请稍后再试', title: '网络异常,请稍后再试',
}) })
}, },
}) })
}) })
} }
/** /**
* 错误处理 * 错误处理
* @param {Number} code 错误码 * @param {Number} code 错误码
*/ */
function errHandler(res) { function errHandler(res) {
console.log(res) console.log(res)
switch (res.code) { switch (res.code) {
case 'A0024': case 'A0024':
uni.reLaunch({ url: '/pages/user/login' }) uni.reLaunch({ url: '/pages/user/login' })
break break
case 'A0202': case 'A0202':
uni.reLaunch({ url: '/pages/user/login' }) uni.reLaunch({ url: '/pages/user/login' })
break break
default: default:
uni.showToast({ uni.showToast({
title: res.message || res.msg || '网络异常,请稍后再试', title: res.message || res.msg || '网络异常,请稍后再试',
duration: 2000, duration: 2000,
icon: 'none', icon: 'none',
}) })
break break
} }
} }

227
common/js/update.js Normal file
View File

@@ -0,0 +1,227 @@
import { getLastData } from '../api/user.js'
export const checkAppUpdate = () => {
// 开发环境跳过检查
const isDev = process.env.NODE_ENV === 'development'
// if (isDev) {
console.log('开发环境,不执行更新检查')
return
// }
// 获取当前应用信息
plus.runtime.getProperty(plus.runtime.appid, (info) => {
const currentVersion = info.version
getLastData()
.then((res) => {
// let res = {
// data: {
// versionName: 'v1.6.83',
// forceUpdate: '1',
// androidPath: 'https://app.liuyingyong.cn/build/download/3c26e400-3a33-11f1-8997-a16e76fa35b3',
// // androidPath: 'http://112.4.144.18:8040/shiningCloud/file/canneng_wulian.apk',
// iosPath: 'xxxx',
// },
// }
if (!res?.data) {
console.log('未获取到版本信息')
return
}
// 适配新的接口返回格式
const { versionName, androidPath, iosPath, forceUpdate = '1' } = res.data
// 版本相同则不需要更新
if (versionName.includes(currentVersion)) {
console.log('已是最新版本')
return
}
const isForce = forceUpdate === '1' // 字符串 '1' 表示强制更新
const iosUrl = iosPath
handleUpdate({ version: versionName, androidPath, iosUrl, isForce })
})
.catch((err) => {
console.error('获取版本接口失败', err)
})
})
}
/**
* 处理更新逻辑
*/
const handleUpdate = ({ version, androidPath, iosUrl, isForce }) => {
const isAndroid = plus.os.name === 'Android'
const isIOS = plus.os.name === 'iOS'
if (isAndroid) {
handleAndroidUpdate({ androidPath, isForce })
} else if (isIOS) {
handleIOSUpdate({ iosUrl, isForce })
} else {
console.warn('未知操作系统')
}
}
/**
* 处理安卓更新
*/
const handleAndroidUpdate = ({ androidPath, isForce }) => {
if (!androidPath?.length) {
console.error('未找到安卓安装包')
uni.showToast({
title: '更新包不存在',
icon: 'error',
})
return
}
const downloadUrl = androidPath
uni.showModal({
title: '更新提示',
content: '发现新版本,是否立即更新?',
showCancel: !isForce, // 强制更新隐藏取消按钮
confirmText: '去更新',
cancelText: '暂不更新',
success: (modalRes) => {
if (modalRes.confirm) {
downloadAndInstallApk(downloadUrl)
} else if (isForce) {
// 强制更新且用户取消,退出应用
plus.runtime.quit()
}
},
})
}
/**
* 处理iOS更新
*/
const handleIOSUpdate = ({ iosUrl, isForce }) => {
if (!iosUrl) {
console.error('未找到iOS下载链接')
uni.showToast({
title: '更新链接不存在',
icon: 'error',
})
return
}
uni.showModal({
title: '更新提示',
content: '发现新版本,请前往 App Store 更新',
showCancel: !isForce,
confirmText: '去更新',
cancelText: '暂不更新',
success: (modalRes) => {
if (modalRes.confirm) {
plus.runtime.openURL(iosUrl)
}
// 强制更新时,无论确认还是取消都退出应用
if (isForce) {
setTimeout(() => {
plus.runtime.quit()
}, 300) // 给跳转留一点时间
}
},
})
}
/**
* 下载并安装APK安卓专用
*/
const downloadAndInstallApk = (url) => {
// 显示原生进度条
let progressWaiting = plus.nativeUI.showWaiting('正在下载中,请稍等...', {
modal: true,
round: true,
close: false, // 不允许用户关闭
padlock: true, // 锁定屏幕
})
const options = {
filename: '_doc/update/canneng_wulian.apk',
timeout: 120,
}
const downloadTask = plus.downloader.createDownload(url, options, (downloadedFile, status) => {
progressWaiting.close()
if (status === 200) {
installApk(downloadedFile.filename, url)
} else {
handleDownloadError(url)
}
})
// // 更新进度
downloadTask.addEventListener('statechanged', (task) => {
if (task.state === 3 && task.totalSize > 0) {
const percent = ((task.downloadedSize / task.totalSize) * 100).toFixed(0)
console.log("🚀 ~ downloadAndInstallApk ~ percent:", percent)
// 直接更新 waiting 的标题,不会闪烁
progressWaiting.setTitle(`正在下载更新 ${percent}%`)
}
})
downloadTask.start()
}
/**
* 安装APK
*/
const installApk = (filePath, downloadUrl) => {
console.log('🚀 ~ installApk ~ filePath:', filePath)
plus.runtime.install(
filePath,
{ force: true },
() => {
// 安装成功
uni.showModal({
title: '安装成功',
content: '是否立即重启应用?',
showCancel: false,
confirmText: '立即重启',
success: () => {
plus.runtime.restart()
},
})
},
(error) => {
console.error('安装失败', error)
uni.showModal({
title: '安装失败',
content: `安装失败:${error.message}\n请检查是否已开启安装权限`,
confirmText: '重试',
cancelText: '取消',
success: (res) => {
if (res.confirm) {
downloadAndInstallApk(downloadUrl)
}
},
})
},
)
}
/**
* 处理下载错误
*/
const handleDownloadError = (downloadUrl) => {
uni.showModal({
title: '下载失败',
content: '网络异常或下载链接失效,是否重试?',
confirmText: '重试',
cancelText: '取消',
success: (res) => {
if (res.confirm) {
downloadAndInstallApk(downloadUrl)
}
},
})
}

View File

@@ -1,299 +1,362 @@
import request from './request' import request from './request'
import cache from './cacheKey.js' import cache from './cacheKey.js'
import { getImageUrl } from '@/common/api/basic' import { getImageUrl } from '@/common/api/basic'
import { apiUpdatePush } from '@/common/api/user' import { apiUpdatePush } from '@/common/api/user'
import { queryDictDataCache } from '../api/dictionary.js' import { queryDictDataCache } from '../api/dictionary.js'
import cacheKey from './cacheKey.js' import cacheKey from './cacheKey.js'
import config from '@/common/js/config' import config from '@/common/js/config'
import jsrsasign from 'jsrsasign' import jsrsasign from 'jsrsasign'
const toast = (title, duration = 1500, call, mask = false, icon = 'none') => { const toast = (title, duration = 1500, call, mask = false, icon = 'none') => {
if (Boolean(title) === false) { if (Boolean(title) === false) {
return return
} }
uni.showToast({ uni.showToast({
title, title,
duration, duration,
mask, mask,
icon, icon,
}) })
setTimeout(() => { setTimeout(() => {
call && call() call && call()
}, duration) }, duration)
} }
/** /**
* @description 格式化时间 * @description 格式化时间
* @param time * @param time
* @param cFormat * @param cFormat
* @returns {string|null} * @returns {string|null}
*/ */
function parseTime(time, cFormat) { function parseTime(time, cFormat) {
if (arguments.length === 0) { if (arguments.length === 0) {
return null return null
} }
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}' const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
let date let date
if (typeof time === 'object') { if (typeof time === 'object') {
date = time date = time
} else { } else {
if (typeof time === 'string' && /^[0-9]+$/.test(time)) { if (typeof time === 'string' && /^[0-9]+$/.test(time)) {
time = parseInt(time) time = parseInt(time)
} }
if (typeof time === 'number' && time.toString().length === 10) { if (typeof time === 'number' && time.toString().length === 10) {
time = time * 1000 time = time * 1000
} }
date = new Date(time) date = new Date(time)
} }
const formatObj = { const formatObj = {
y: date.getFullYear(), y: date.getFullYear(),
m: date.getMonth() + 1, m: date.getMonth() + 1,
d: date.getDate(), d: date.getDate(),
h: date.getHours(), h: date.getHours(),
i: date.getMinutes(), i: date.getMinutes(),
s: date.getSeconds(), s: date.getSeconds(),
a: date.getDay(), a: date.getDay(),
} }
return format.replace(/{([ymdhisa])+}/g, (result, key) => { return format.replace(/{([ymdhisa])+}/g, (result, key) => {
let value = formatObj[key] let value = formatObj[key]
if (key === 'a') { if (key === 'a') {
return ['日', '一', '二', '三', '四', '五', '六'][value] return ['日', '一', '二', '三', '四', '五', '六'][value]
} }
if (result.length > 0 && value < 10) { if (result.length > 0 && value < 10) {
value = '0' + value value = '0' + value
} }
return value || 0 return value || 0
}) })
} }
/** /**
* @description 格式化时间 * @description 格式化时间
* @param time * @param time
* @param option * @param option
* @returns {string} * @returns {string}
*/ */
function formatTime(time, option) { function formatTime(time, option) {
if (('' + time).length === 10) { if (('' + time).length === 10) {
time = parseInt(time) * 1000 time = parseInt(time) * 1000
} else { } else {
time = +time time = +time
} }
if (option) { if (option) {
return parseTime(time, option) return parseTime(time, option)
} else { } else {
const d = new Date(time) const d = new Date(time)
const now = Date.now() const now = Date.now()
const diff = (now - d) / 1000 const diff = (now - d) / 1000
if (diff < 30) { if (diff < 30) {
return '刚刚' return '刚刚'
} else if (diff < 3600) { } else if (diff < 3600) {
// less 1 hour // less 1 hour
return Math.ceil(diff / 60) + '分钟前' return Math.ceil(diff / 60) + '分钟前'
} else if (diff < 3600 * 24) { } else if (diff < 3600 * 24) {
return Math.ceil(diff / 3600) + '小时前' return Math.ceil(diff / 3600) + '小时前'
} else if (diff < 3600 * 24 * 2) { } else if (diff < 3600 * 24 * 2) {
return '1天前' return '1天前'
} }
return ( return (
d.getMonth() + 1 + '月' + d.getDate() + '日' d.getMonth() + 1 + '月' + d.getDate() + '日'
// + // +
// d.getHours() + // d.getHours() +
// '时' // '时'
// + // +
// d.getMinutes() + // d.getMinutes() +
// '分' // '分'
) )
} }
} }
// 获取当天日期(年月日)
const h5Helper = { function getToday() {
isAndroid: function () { const today = new Date()
return window.navigator.appVersion.toLowerCase().indexOf('android') != -1 const year = today.getFullYear()
}, const month = String(today.getMonth() + 1).padStart(2, '0') // 月份从0开始需+1
isIOS: function () { const day = String(today.getDate()).padStart(2, '0')
return window.navigator.appVersion.toLowerCase().indexOf('iphone') != -1 return `${year}-${month}-${day}`
}, }
isWeiXinWeb: function () { // 获取当天日期 往前推30天
var ua = window.navigator.userAgent.toLowerCase() function getBeforeDays(days = 30) {
return ua.match(/MicroMessenger/i) == 'micromessenger' const today = new Date()
}, // 计算往前推N天的时间戳1天=86400000毫秒
} const beforeDate = new Date(today.getTime() - days * 24 * 60 * 60 * 1000)
return formatDate(beforeDate)
// 验证手机号格式 }
const validatePhoneNumber = (phone) => { function formatDate(date) {
if (!phone) return false const year = date.getFullYear()
var testReg = /^1[23456789]\d{9}$/ // 月份从0开始补零到2位
return testReg.test(phone) const month = String(date.getMonth() + 1).padStart(2, '0')
} // 日期补零到2位
const day = String(date.getDate()).padStart(2, '0')
const getUserLocation = (call) => { return `${year}-${month}-${day}`
uni.getLocation({ }
type: 'wgs84',
success: function (address) { // 获取3个月前的日期
call(address) function getThreeMonthsAgo() {
}, const threeMonthsAgo = new Date()
fail: (err) => { threeMonthsAgo.setMonth(threeMonthsAgo.getMonth() - 3) // 月份减3
uni.showModal({ const year = threeMonthsAgo.getFullYear()
title: '提示', const month = String(threeMonthsAgo.getMonth() + 1).padStart(2, '0')
content: '定位失败,请打开定位权限', const day = String(threeMonthsAgo.getDate()).padStart(2, '0')
success: function (res) { return `${year}-${month}-${day}`
if (res.confirm) { }
uni.openSetting({ //获取月最后一天
success: (resSett) => { function getMonthFirstAndLastDay(monthStr) {
if (resSett.authSetting['scope.userLocation']) { // 1. 校验输入格式正则匹配YYYY-MM
uni.getLocation({ const reg = /^\d{4}-\d{2}$/
success: (address) => { if (!reg.test(monthStr)) {
call && call(address) throw new Error('输入格式错误,请传入"YYYY-MM"格式的字符串例如2026-03')
}, }
})
} // 2. 拆分年、月
}, const [year, month] = monthStr.split('-').map(Number)
})
} // 3. 生成当月第一天直接拼接01
}, const firstDay = `${year}-${String(month).padStart(2, '0')}-01`
})
}, // 4. 生成当月最后一天核心利用Date的特性下个月0号 = 当月最后一天)
}) // 注意月份是0开始的0=1月11=12月所以month+1是下一个月
} const lastDayDate = new Date(year, month, 0) // 下个月0号 = 当月最后一天
const lastDay = `${year}-${String(month).padStart(2, '0')}-${String(lastDayDate.getDate()).padStart(2, '0')}`
// 加载用户配置
var globalConfigIsLoading = false, return {
global_config = null, firstDay,
globalConfigCallbacks = [] lastDay,
/** }
* 加载用户配置 }
* @param call 加载成功后的回调
* @param need_fresh 是否及时刷新用户配置 const h5Helper = {
*/ isAndroid: function () {
const loadConfig = (call, need_fresh = false) => { return window.navigator.appVersion.toLowerCase().indexOf('android') != -1
if (call && global_config && !need_fresh) { },
call(global_config) isIOS: function () {
return return window.navigator.appVersion.toLowerCase().indexOf('iphone') != -1
} },
if (globalConfigIsLoading) { isWeiXinWeb: function () {
globalConfigCallbacks.push(call) var ua = window.navigator.userAgent.toLowerCase()
return return ua.match(/MicroMessenger/i) == 'micromessenger'
} },
globalConfigIsLoading = true }
request({
url: '/org/userResource/userMsg', // 验证手机号格式
}) const validatePhoneNumber = (phone) => {
.then((rs) => { if (!phone) return false
globalConfigIsLoading = false var testReg = /^1[23456789]\d{9}$/
global_config = rs.data return testReg.test(phone)
uni.setStorage({ }
key: 'userInfo',
data: global_config, const getUserLocation = (call) => {
}) uni.getLocation({
if (call) { type: 'wgs84',
call(global_config) success: function (address) {
} call(address)
for (var i = 0; i < globalConfigCallbacks.length; i++) { },
globalConfigCallbacks[i](global_config) fail: (err) => {
} uni.showModal({
globalConfigCallbacks = [] title: '提示',
}) content: '定位失败,请打开定位权限',
.catch((err) => { success: function (res) {
globalConfigIsLoading = false if (res.confirm) {
console.warn(err) uni.openSetting({
// uni.reLaunch({ url: '/pages/user/login' }) success: (resSett) => {
}) if (resSett.authSetting['scope.userLocation']) {
} uni.getLocation({
success: (address) => {
const prePage = () => { call && call(address)
let pages = getCurrentPages() },
let prePage = pages[pages.length - 2] })
return prePage }
} },
})
const loginSuccess = (data, jump = true) => { }
return new Promise((resolve, reject) => { },
console.log(data) })
uni.setStorageSync('access_token', data.token_type + ' ' + data.access_token) },
uni.setStorageSync('refresh_token', data.refresh_token) })
let userInfo = decodeToken(data.access_token) }
console.log(userInfo)
// let strings = data.access_token.split('.') //截取token获取载体 // 加载用户配置
// console.log(escape, atob) var globalConfigIsLoading = false,
// var userInfo = JSON.parse(decodeURIComponent(escape(atob(strings[1].replace(/-/g, '+').replace(/_/g, '/'))))) global_config = null,
userInfo.authorities = userInfo.authorities[0] globalConfigCallbacks = []
if (userInfo.headSculpture) { /**
userInfo.avatar = config.static + userInfo.headSculpture * 加载用户配置
} * @param call 加载成功后的回调
console.log(userInfo) * @param need_fresh 是否及时刷新用户配置
uni.setStorageSync(cache.userInfo, userInfo) */
apiUpdatePush() const loadConfig = (call, need_fresh = false) => {
resolve(userInfo) if (call && global_config && !need_fresh) {
if (jump) { call(global_config)
queryDictDataCache().then((res) => { return
uni.setStorageSync(cacheKey.dictData, res.data) }
}) if (globalConfigIsLoading) {
console.log('reLaunch') globalConfigCallbacks.push(call)
uni.reLaunch({ return
url: '/pages/index/index', }
fail: (err) => { globalConfigIsLoading = true
console.log(err) request({
}, url: '/org/userResource/userMsg',
}) })
} .then((rs) => {
}) globalConfigIsLoading = false
} global_config = rs.data
/** uni.setStorage({
* 只针对列表页的刷新 key: 'userInfo',
* @param {*} number data: global_config,
* @param {*} time })
*/ if (call) {
const refreshPrePage = (number = 1, time = 1500) => { call(global_config)
let pages = getCurrentPages() }
let prePage = pages[pages.length - number - 1] for (var i = 0; i < globalConfigCallbacks.length; i++) {
if (prePage && time) { globalConfigCallbacks[i](global_config)
prePage.$vm.store?.reload() }
setTimeout(() => { globalConfigCallbacks = []
uni.navigateBack({ })
delta: number, .catch((err) => {
}) globalConfigIsLoading = false
}, time) console.warn(err)
} // uni.reLaunch({ url: '/pages/user/login' })
} })
}
const decodeToken = (token) => {
let obj = null const prePage = () => {
if (token !== '') { let pages = getCurrentPages()
const payload = jsrsasign.KJUR.jws.JWS.parse(token) let prePage = pages[pages.length - 2]
if (payload.hasOwnProperty('payloadObj')) { return prePage
obj = payload.payloadObj }
}
} const loginSuccess = (data, jump = true) => {
return obj return new Promise((resolve, reject) => {
} console.log(data)
uni.setStorageSync('access_token', data.token_type + ' ' + data.access_token)
const getDictData = (key) => { uni.setStorageSync('refresh_token', data.refresh_token)
return new Promise((resolve, reject) => { let userInfo = decodeToken(data.access_token)
let dictData = uni.getStorageSync(cacheKey.dictData) console.log(userInfo)
if (dictData) { // let strings = data.access_token.split('.') //截取token获取载体
resolve(dictData.filter((item) => item.code === key)[0]?.children || []) // console.log(escape, atob)
} else { // var userInfo = JSON.parse(decodeURIComponent(escape(atob(strings[1].replace(/-/g, '+').replace(/_/g, '/')))))
// 查询字典 userInfo.authorities = userInfo.authorities[0]
queryDictDataCache().then((res) => { if (userInfo.headSculpture) {
uni.setStorageSync(cacheKey.dictData, res.data) userInfo.avatar = config.static + userInfo.headSculpture
resolve(res.data.filter((item) => item.code === key)[0]?.children || []) }
}).catch(err=>{ console.log(userInfo)
reject(err) uni.setStorageSync(cache.userInfo, userInfo)
}) apiUpdatePush()
} resolve(userInfo)
}) if (jump) {
} queryDictDataCache().then((res) => {
uni.setStorageSync(cacheKey.dictData, res.data)
export default { })
validatePhoneNumber, console.log('reLaunch')
toast, uni.reLaunch({
formatTime, url: '/pages/index/index',
parseTime, fail: (err) => {
h5Helper, console.log(err)
getUserLocation, },
loadConfig, })
prePage, }
loginSuccess, })
refreshPrePage, }
getDictData, /**
} * 只针对列表页的刷新
* @param {*} number
* @param {*} time
*/
const refreshPrePage = (number = 1, time = 1500) => {
let pages = getCurrentPages()
let prePage = pages[pages.length - number - 1]
if (prePage && time) {
prePage.$vm.store?.reload()
setTimeout(() => {
uni.navigateBack({
delta: number,
})
}, time)
}
}
const decodeToken = (token) => {
let obj = null
if (token !== '') {
const payload = jsrsasign.KJUR.jws.JWS.parse(token)
if (payload.hasOwnProperty('payloadObj')) {
obj = payload.payloadObj
}
}
return obj
}
const getDictData = (key) => {
return new Promise((resolve, reject) => {
let dictData = uni.getStorageSync(cacheKey.dictData)
if (dictData) {
resolve(dictData.filter((item) => item.code === key)[0]?.children || [])
} else {
// 查询字典
queryDictDataCache()
.then((res) => {
uni.setStorageSync(cacheKey.dictData, res.data)
resolve(res.data.filter((item) => item.code === key)[0]?.children || [])
})
.catch((err) => {
reject(err)
})
}
})
}
export default {
validatePhoneNumber,
toast,
formatTime,
parseTime,
h5Helper,
getUserLocation,
loadConfig,
prePage,
loginSuccess,
refreshPrePage,
getDictData,
getToday,
getBeforeDays,
getThreeMonthsAgo,
getMonthFirstAndLastDay,
}

View File

@@ -1,80 +1,264 @@
<template> <template>
<uni-card <uni-card
:title="device.equipmentName" :title="device.equipmentName"
:sub-title="device.mac" :sub-title="device.mac"
:extra="device.isPrimaryUser == 1 ? '主设备' : '分享设备'" :extra="device.isPrimaryUser == 1 ? '主设备' : '分享设备'"
padding="0" padding="0"
@click="jump(device)" @click="jump(device)"
:thumbnail="deviceIcon(device.runStatus)" class="boxClick"
> :thumbnail="deviceIcon(device.runStatus)"
<template v-slot:title> >
<slot name="title"></slot> <template v-slot:title>
</template> <!-- 卡片标题 -->
<view class="device-body"> <view class="uni-card__header" @click="jump(device)">
<view class="device-body-item"> <view class="uni-card__header-box">
<text>工程名称</text> <view class="uni-card__header-avatar">
<text>{{ device.engineeringName }}</text> <view class="event-icon">
</view> <!-- 动态图标根据类型切换 -->
<view class="device-body-item mt6"> <!-- <uni-icons
<text>项目名称</text> custom-prefix="iconfont"
<text>{{ device.projectName }}</text> :type="
</view> device.devType == 'Direct_Connected_Device'
<view class="device-body-item mt6" v-if="device.process == 2 || device.process == 3"> ? 'icon-zaixianjianceshebei'
<text>调试阶段</text> : 'icon-shebei1'
<text>{{ device.process == 2 ? '功能调试' : '出厂调试' }}</text> "
</view> :color="device.runStatus == 1 ? '#ff3b30' : '#10B981'"
</view> :size="device.devType == 'Direct_Connected_Device' ? '35' : '40'"
</uni-card> ></uni-icons> -->
</template> <Cn-icon-device
<script> :devType="device.devType"
export default { :runStatus="device.runStatus"
data() { :alarmStatus="device.isAlarm ? 1 : 0"
return {} ></Cn-icon-device>
}, </view>
props: { </view>
device: { <view class="uni-card__header-content">
type: Object, <text class="uni-card__header-content-title uni-ellipsis">
default: () => {}, {{ device.equipmentName }}
}, </text>
}, <text class="uni-card__header-content-subtitle uni-ellipsis">
methods: { {{ device.mac }}
deviceIcon(e) { </text>
let str = '' <view class="tagBox">
switch (e) { <text class="event-tag" :class="device.runStatus == 1 ? 'lx-tag' : 'zx-tag'">{{
case 1: device.runStatus == 1 ? '离线' : '在线'
str = '/static/device_bad.png' }}</text>
break <text
case 2: class="event-tag"
str = '/static/device_success.png' :class="device.devType == 'Direct_Connected_Device' ? 'zl-tag' : 'jc-tag'"
break >
default: {{ device.devType == 'Direct_Connected_Device' ? '治理设备' : '监测设备' }}
str = '/static/device_success.png' </text>
break <text class="event-tag" :class="device.isPrimaryUser == 1 ? 'z-tag' : 'fx-tag'">{{
} device.isPrimaryUser == 1 ? '主设备' : '分享设备'
return str }}</text></view
}, >
jump() { </view>
console.log(12321,this.device); </view>
uni.navigateTo({ <view class="uni-card__header-extra" style="position: relative" @click.stop>
url: <text class="uni-card__header-extra-text"></text>
'/pages/device/APF/detail?id=' + <slot name="title"></slot>
this.device.equipmentId + </view>
'&isPrimaryUser=' + </view>
this.device.isPrimaryUser + <!-- <slot name="title"></slot> -->
'&process=' + </template>
this.device.process + '&ndid=' + this.device.ndid, <view class="device-body">
}) <view class="device-body-item">
}, <text>工程名称</text>
}, <text>{{ device.engineeringName }}</text>
} </view>
</script> <view class="device-body-item mt6">
<style lang="scss"> <text>项目名称</text>
.device-body { <text>{{ device.projectName }}</text>
padding: 20rpx; </view>
<view class="device-body-item mt6" v-if="device.process == 2 || device.process == 3">
.device-body-item { <text>调试阶段</text>
display: flex; <text>{{ device.process == 2 ? '功能调试' : '出厂调试' }}</text>
justify-content: space-between; </view>
} </view>
} <view class="pinToTop" v-if="device.isTop == 1"> 置顶 </view>
</style> </uni-card>
</template>
<script>
export default {
data() {
return {}
},
props: {
device: {
type: Object,
default: () => {},
},
},
methods: {
deviceIcon(e) {
let str = ''
switch (e) {
case 1:
str = '/static/device_bad.png'
break
case 2:
str = '/static/device_success.png'
break
default:
str = '/static/device_success.png'
break
}
return str
},
jump() {
if (this.device.devType == 'Direct_Connected_Device') {
uni.navigateTo({
url:
'/pages/device/APF/detail?id=' +
this.device.equipmentId +
'&isPrimaryUser=' +
this.device.isPrimaryUser +
'&process=' +
this.device.process +
'&ndid=' +
this.device.ndid +
'&device=' +
JSON.stringify(this.device),
})
} else {
if (this.device.lineList.length == 0) {
return this.$util.toast('暂无监测点!')
}
uni.navigateTo({
url: '/pages/device/realTime/index?device=' + JSON.stringify(this.device),
})
}
},
getColor(status, type) {
if (status == 1) {
return '#ff3b3020'
} else {
return '#10b98120' //type == 'Direct_Connected_Device' ? '#10b98120' : ''
}
},
},
}
</script>
<style lang="scss">
.device-body {
padding: 10rpx 20rpx 20rpx;
.device-body-item {
display: flex;
justify-content: space-between;
font-size: 28rpx;
color: #666666;
line-height: 1.2;
}
}
.uni-card {
/deep/ .uni-card__header-box {
display: flex;
flex: 1;
flex-direction: row;
align-items: center;
overflow: hidden;
}
/deep/ .uni-card__header {
display: flex;
border-bottom: 2rpx #ebeef5 solid;
flex-direction: row;
align-items: center;
padding: 20rpx 20rpx 10rpx 0;
overflow: hidden;
}
}
.uni-card .uni-card__header .uni-card__header-content .uni-card__header-content-title {
font-size: 30rpx;
color: #3a3a3a;
font-weight: 700;
}
.uni-card .uni-card__header .uni-card__header-content .uni-card__header-content-subtitle {
font-size: 24rpx;
// margin-top: 5px;
color: #666666;
}
.uni-card .uni-card__header .uni-card__header-avatar .uni-card__header-avatar-image {
width: 40px;
height: 40px;
overflow: hidden;
border-radius: 5px;
margin-right: 10px;
}
.uni-card .uni-card__header .uni-card__header-content {
display: flex;
flex-direction: column;
justify-content: center;
flex: 1;
overflow: hidden;
}
.tagBox {
display: flex;
gap: 15rpx;
}
.event-icon {
position: relative;
width: 100rpx;
height: 100rpx;
border-radius: 12rpx;
display: flex;
justify-content: center;
align-items: center;
margin-right: 20rpx;
}
.event-tag {
font-size: 22rpx;
padding: 2rpx 10rpx;
border-radius: 8rpx;
margin-top: 5rpx;
// height: 38rpx;
}
// 在线
.zx-tag {
background-color: #10b98120;
color: #10b981;
}
.lx-tag {
background-color: #ff3b3020;
color: #ff3b30;
}
.z-tag {
background-color: #2563eb20;
color: #2563eb;
}
.fx-tag {
background-color: #90939920;
color: #909399;
}
.zl-tag {
// background-color: #007aff20;
// color: #007aff;
background-color: #007aff20;
color: #007aff;
}
.jc-tag {
background-color: #007aff20;
color: #007aff;
}
.pinToTop {
background-color: $uni-theme-color;
width: 100rpx;
height: 60rpx;
line-height: 90rpx;
text-align: center;
color: #fff;
font-size: 20rpx;
position: absolute;
top: 0rpx;
right: 0rpx;
position: absolute;
top: 0;
right: 0;
/* 核心:旋转成斜三角效果 */
transform: rotate(45deg) translate(50rpx, -10rpx);
transform-origin: top right;
}
</style>

View File

@@ -0,0 +1,346 @@
<template>
<view class="nav choose">
<view class="nav-menu nav-menu1" @click="selectEngineering" v-if="showQianTree">
<view class="nav-text">
{{
select.engineeringName || select.projectName || select.deviceName || select.lineName
? [select.engineeringName, select.projectName, select.deviceName, select.lineName]
.filter((item) => item && item !== '')
.join('>')
: '全部工程'
}}
</view>
<uni-icons type="bottom" size="14"></uni-icons>
</view>
<!-- 弹框组件 -->
<Cn-qianTree
ref="qiantree"
:selectParent="true"
:multiple="false"
:range="list"
:foldAll="true"
:singleChoice="singleChoice"
@confirm="treeConfirm"
@cancel="treeCancel"
></Cn-qianTree>
<picker
mode="date"
:value="select.date"
:start="startDate"
fields="month"
:end="endDate"
@change="bindDateChange"
v-if="showDatetime"
>
<view class="nav-menu nav-menu1"
><view class="nav-text">
{{ select.date }}
</view>
<uni-icons type="bottom" size="14"></uni-icons>
</view>
</picker>
<!-- <uni-datetime-picker v-if="!showDatetime" v-model="select.range" type="daterange" :end="endDate">
<view class="nav-menu"
>{{ select.range[0] + '至' + select.range[1] }}
<uni-icons type="bottom" size="14"></uni-icons>
</view>
</uni-datetime-picker> -->
<picker
mode="date"
:value="select.range"
fields="year"
:end="endDate.slice(0, -6)"
@change="yearChange"
v-if="!showDatetime"
>
<view class="nav-menu nav-menu1"
><view class="nav-text">
{{ select.range }}
</view>
<uni-icons type="bottom" size="14"></uni-icons>
</view>
</picker>
<slot />
</view>
</template>
<script>
import { lineTree } from '@/common/api/device'
export default {
components: {},
props: {
level: { type: Number, default: 3 },
showDatetime: { type: Boolean, default: true },
singleChoice: { type: Boolean, default: false },
showQianTree: { type: Boolean, default: true },
},
data() {
const currentDate = this.getDate({
format: true,
})
const rangeDate = this.getDate({
format: true,
}).slice(0, -3)
console.log('🚀 ~ rangeDate:', rangeDate)
return {
select: {
engineeringName: '',
engineeringId: '', //工程ID
projectName: '',
projectId: '', //項目ID
deviceName: '',
deviceId: '', //设备ID
lineName: '',
lineId: '', //测点ID
date: currentDate,
range: rangeDate,
},
list: [],
}
},
created() {},
onShow() {},
mounted() {},
methods: {
getTree() {
this.clear()
lineTree().then((res) => {
let list = {}
if (this.singleChoice) {
let result = this.findFirstLevel(res.data)
console.log('🚀 ~ result:', result)
this.select.engineeringName = result.parents[0].name
this.select.engineeringId = result.parents[0].id //工程ID
this.select.projectName = result.parents[1].name
this.select.projectId = result.parents[1].id //項目ID
this.select.deviceName = result.parents[2].name
this.select.deviceId = result.parents[2].id //设备ID
this.select.lineName = result.node.name
this.select.lineId = result.node.id //测点ID
} else {
list = {
id: '',
pid: '0',
pids: '0',
name: '全部工程',
path: null,
provinceId: null,
cityId: null,
area: null,
remark: null,
sort: 0,
level: 0,
comFlag: null,
type: null,
lineType: null,
conType: null,
process: null,
isTop: 0,
children: [],
ndid: null,
}
}
this.list = this.filterTreeByLevel(this.singleChoice ? res.data : [list, ...res.data])
// this.findFirstLevel( this.list)
})
},
// 递归过滤函数去除level > 2的节点
filterTreeByLevel(tree) {
// 遍历每一个节点
return tree.map((node) => {
// 复制当前节点(避免修改原数据)
const newNode = { ...node }
// 如果当前节点有子节点并且当前节点的level <= 2因为level=2的节点的子节点是level=3需要过滤
if (newNode.children && newNode.children.length > 0) {
// 递归过滤子节点只保留子节点中level <= 2的
newNode.children = this.filterTreeByLevel(
newNode.children.filter((child) => child.level <= this.level),
)
}
return newNode
})
},
getDate(type) {
const date = new Date()
let year = date.getFullYear()
let month = date.getMonth() + 1
let day = date.getDate()
if (type === 'start') {
year = year - 10
} else if (type === 'end') {
year = year
}
month = month > 9 ? month : '0' + month
day = day > 9 ? day : '0' + day
return this.showDatetime ? `${year}-${month}` : `${year}-${month}-${day}`
},
bindDateChange(e) {
this.select.date = e.detail.value
},
yearChange(e) {
this.select.range = e.detail.value
},
selectEngineering() {
this.$refs.qiantree._show()
},
// 确定回调事件
treeConfirm(e) {
this.clear()
this.setSelect(e[0].rank, e[0].name, e[0].id)
e[0].parents.forEach((item) => {
this.setSelect(item.rank, item.name, item.id)
})
},
// 清空
clear() {
this.select.engineeringName = ''
this.select.engineeringId = '' //工程ID
this.select.projectName = ''
this.select.projectId = '' //項目ID
this.select.deviceName = ''
this.select.deviceId = '' //设备ID
this.select.lineName = ''
this.select.lineId = '' //测点ID
},
setSelect(rank, name, id) {
switch (rank) {
case 0:
this.select.engineeringId = id
this.select.engineeringName = name
break
case 1:
this.select.projectId = id
this.select.projectName = name
break
case 2:
this.select.deviceId = id
this.select.deviceName = name
break
case 3:
this.select.lineId = id
this.select.lineName = name
break
}
},
external(params) {
this.getTree()
// this.select.engineeringId = id
// this.select.engineeringName = name
this.select.engineeringName = params.engineeringName
this.select.engineeringId = params.engineeringId //工程ID
this.select.projectName = params.projectName
this.select.projectId = params.projectId //項目ID
this.select.deviceName = params.deviceName
this.select.deviceId = params.deviceId //设备ID
this.select.lineName = params.lineName
this.select.lineId = params.lineId //测点ID
},
// 取消回调事件
treeCancel(e) {
console.log(e)
},
findFirstLevel(list, parents = []) {
for (const item of list) {
// 当前就是 level=3
if (item.level === 3) {
return {
node: item, // 第一个 level=3
parents: parents, // 它的所有上级
}
}
// 递归子节点
if (item.children && item.children.length) {
const res = this.findFirstLevel(item.children, [...parents, item])
if (res) return res // 找到直接返回,不再循环
}
}
return null
},
},
computed: {
startDate() {
return this.getDate('start')
},
endDate() {
return this.getDate('end')
},
},
watch: {
select: {
handler(val, oldVal) {
if (this.loading) return
this.$emit('select', val)
},
deep: true,
immediate: true,
},
level: {
handler(val, oldVal) {
this.getTree()
},
deep: true,
immediate: true,
},
// showDatetime: {
// handler(val, oldVal) {
// if (val == false) {
// console.log("🚀 ~ this.select.range:", this.select.range)
// }
// },
// deep: true,
// },
},
}
</script>
<style lang="scss" scoped>
/deep/ .uni-date-editor {
width: 360rpx;
}
.nav-menu {
display: flex;
align-items: center;
}
// .nav-menu1 {
// max-width: calc(100vw - 150px);
// overflow: hidden !important;
// -webkit-line-clamp: 1;
// display: -webkit-box;
// -webkit-box-orient: vertical;
// text-overflow: ellipsis;
// word-break: break-all;
// white-space: nowrap;
// }
.nav-menu1 {
display: flex;
align-items: center;
max-width: calc(100vw - 150px);
}
/* 文字容器:单行溢出省略 */
.nav-text {
flex: 1;
overflow: hidden;
white-space: nowrap; /* 强制不换行 */
text-overflow: ellipsis;
// -webkit-line-clamp: 1;
// display: -webkit-box;
// -webkit-box-orient: vertical;
// text-overflow: ellipsis;
// word-break: break-all;
// white-space: nowrap;
line-height: 1;
}
</style>

View File

@@ -0,0 +1,130 @@
<template>
<view v-html="svgHtml" class="svg-container"></view>
</template>
<script>
export default {
props: {
// 父组件传递的参数
devType: {
type: String,
default: 'Direct_Connected_Device',
},
runStatus: {
type: [String, Number],
},
alarmStatus: {
type: [String, Number],
},
},
data() {
return {
// 动态颜色
powerColor: '#10b981',
// alarmStatus==1?'#f59e0b':'#10b981': '#f59e0b', //告警
// commColor: '#10B981', //在线离线
// 动态数据
}
},
computed: {
svgHtml() {
if (this.devType == 'Direct_Connected_Device') {
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
<!-- 设备主体 - 治理设备主题色(绿色) -->
<rect x="2" y="2" width="96" height="96" rx="6" ry="6" fill="#007aff30" stroke="#007aff" stroke-width="2"/>
<!-- 屏幕区域 -->
<rect x="6" y="6" width="88" height="52" rx="3" ry="3" fill="#FFFFFF" stroke="#007aff" stroke-width="1.5"/>
<!-- 屏幕标题栏 - 调整高度以容纳14px文字 -->
<rect x="10" y="9" width="80" height="14" rx="2" ry="2" fill="#007aff30" stroke="#CCC" stroke-width="0.8"/>
<text x="50" y="20" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#007aff" text-anchor="middle">治理设备</text>
<!-- 下降趋势折线(从高到低,拉满宽度) -->
<polyline points="14,28 22,34 30,32 38,40 46,38 54,46 62,44 70,50 78,48 86,52"
fill="none" stroke="#007aff" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/>
<!-- 趋势填充区域(完全覆盖屏幕下方) -->
<polygon points="14,28 22,34 30,32 38,40 46,38 54,46 62,44 70,50 78,48 86,52 86,54 14,54"
fill="#007aff15"/>
<!-- 数据节点圆点(增强数据感) -->
<circle cx="14" cy="28" r="1.5" fill="#007aff"/>
<circle cx="30" cy="32" r="1.5" fill="#007aff"/>
<circle cx="46" cy="38" r="1.5" fill="#007aff"/>
<circle cx="62" cy="44" r="1.5" fill="#007aff"/>
<circle cx="78" cy="48" r="1.5" fill="#007aff"/>
<circle cx="86" cy="52" r="1.5" fill="#007aff"/>
<!-- 下降箭头(增强趋势指向) -->
<polygon points="88,48 86,52 84,48" fill="#007aff" opacity="0.7"/>
<!-- 指示灯区域分隔线 -->
<line x1="6" y1="62" x2="94" y2="62" stroke="#999" stroke-width="1" stroke-dasharray="2,2"/>
<!-- 告警指示灯 -->
<circle cx="28" cy="70" r="6" fill="${this.alarmStatus==1?'#f59e0b':'#10b981'}" stroke="${this.alarmStatus==1?'#f59e0b':'#10b981'}" stroke-width="1"/>
<text x="28" y="92" font-family="Arial, sans-serif" font-size="13" font-weight="bold" fill="#007aff" text-anchor="middle">告警</text>
<!-- 通讯指示灯 -->
<circle cx="70" cy="70" r="6" fill="${this.runStatus == 1 ? '#ff3b30' : '#10b981'}" stroke="${this.runStatus == 1 ? '#ff3b30' : '#10b981'}" stroke-width="1"/>
<text x="70" y="92" font-family="Arial, sans-serif" font-size="13" font-weight="bold" fill="#007aff" text-anchor="middle">通讯</text>
</svg>`
} else {
return `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
<style>
text { font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif; }
</style>
<!-- 设备主体 -->
<rect x="2" y="2" width="96" height="96" rx="6" ry="6" fill="#007aff30" stroke="#007aff" stroke-width="2"/>
<!-- 屏幕区域 -->
<rect x="6" y="6" width="88" height="52" rx="3" ry="3" fill="#FFFFFF" stroke="#007aff" stroke-width="1.5"/>
<!-- 屏幕标题栏 - 调整高度 -->
<rect x="10" y="9" width="80" height="14" rx="2" ry="2" fill="#007aff30" stroke="#CCC" stroke-width="0.8"/>
<text x="50" y="20" font-size="13" font-weight="bold" fill="#007aff" text-anchor="middle">监测设备</text>
<!-- 左侧电压数据 - 调整Y位置 -->
<text x="10" y="34" font-size="7" fill="#007aff">Ua: 220.5V</text>
<text x="10" y="43" font-size="7" fill="#007aff">Ub: 219.8V</text>
<text x="10" y="52" font-size="7" fill="#007aff">Uc: 220.1V</text>
<!-- 竖向分隔线 -->
<line x1="52" y1="26" x2="52" y2="55" stroke="#CCC" stroke-width="0.8" stroke-dasharray="1.5,1.5"/>
<!-- 右侧电流数据 -->
<text x="58" y="34" font-size="7" fill="#007aff">Ia: 125.3A</text>
<text x="58" y="43" font-size="7" fill="#007aff">Ib: 124.7A</text>
<text x="58" y="52" font-size="7" fill="#007aff">Ic: 125.1A</text>
<!-- 指示灯区域分隔线 -->
<line x1="6" y1="62" x2="94" y2="62" stroke="#999" stroke-width="1" stroke-dasharray="2,2"/>
<!-- 告警指示灯 -->
<circle cx="28" cy="70" r="6" fill="${this.alarmStatus==1?'#f59e0b':'#10b981'}" stroke="${this.alarmStatus==1?'#f59e0b':'#10b981'}" stroke-width="1"/>
<text x="28" y="92" font-size="13" font-weight="bold" fill="#007aff" text-anchor="middle">告警</text>
<!-- 通讯指示灯 -->
<circle cx="70" cy="70" r="6" fill="${this.runStatus == 1 ? '#ff3b30' : '#10b981'}" stroke="${this.runStatus == 1 ? '#ff3b30' : '#10b981'}" stroke-width="1"/>
<text x="70" y="92" font-size="13" font-weight="bold" fill="#007aff" text-anchor="middle">通讯</text>
</svg>
`
}
},
},
methods: {},
}
</script>
<style scoped>
.svg-container {
width: 100rpx;
display: flex;
justify-content: center;
align-items: center;
}
</style>

View File

@@ -0,0 +1,41 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
<!-- 设备主体 -->
<rect x="2" y="2" width="96" height="96" rx="6" ry="6" fill="#E8E8E8" stroke="#333" stroke-width="2"/>
<!-- 屏幕区域 -->
<rect x="6" y="6" width="88" height="52" rx="3" ry="3" fill="#FFFFFF" stroke="#333" stroke-width="1.5"/>
<!-- 屏幕标题栏(代替品牌标识) -->
<rect x="10" y="9" width="80" height="10" rx="2" ry="2" fill="#F0F0F0" stroke="#CCC" stroke-width="0.8"/>
<text x="50" y="17" font-family="Arial, sans-serif" font-size="7" font-weight="bold" fill="#333" text-anchor="middle">电能质量监测</text>
<!-- 屏幕内容 - 左侧参数 -->
<text x="10" y="28" font-family="Arial, sans-serif" font-size="6" fill="#000">Ua:220.5V</text>
<text x="10" y="36" font-family="Arial, sans-serif" font-size="6" fill="#000">Ub:219.8V</text>
<text x="10" y="44" font-family="Arial, sans-serif" font-size="6" fill="#000">Uc:220.1V</text>
<text x="10" y="52" font-family="Arial, sans-serif" font-size="6" fill="#000">Hz:50.02</text>
<!-- 垂直分隔线 -->
<line x1="52" y1="22" x2="52" y2="55" stroke="#CCC" stroke-width="0.8" stroke-dasharray="1.5,1.5"/>
<!-- 右侧参数 -->
<text x="58" y="28" font-family="Arial, sans-serif" font-size="6" fill="#000">Ia:125.3A</text>
<text x="58" y="36" font-family="Arial, sans-serif" font-size="6" fill="#000">Ib:124.7A</text>
<text x="58" y="44" font-family="Arial, sans-serif" font-size="6" fill="#000">Ic:125.1A</text>
<text x="58" y="52" font-family="Arial, sans-serif" font-size="6" fill="#000">PF:0.98</text>
<!-- 指示灯区域分隔线 -->
<line x1="6" y1="62" x2="94" y2="62" stroke="#999" stroke-width="1" stroke-dasharray="2,2"/>
<!-- 电源灯 -->
<circle cx="20" cy="76" r="5" fill="#10b981" stroke="#10b981" stroke-width="1"/>
<text x="20" y="90" font-family="Arial, sans-serif" font-size="8" font-weight="bold" fill="#333" text-anchor="middle">电源</text>
<!-- 运行灯 -->
<circle cx="50" cy="76" r="5" fill="#999999" stroke="#333" stroke-width="1"/>
<text x="50" y="90" font-family="Arial, sans-serif" font-size="8" font-weight="bold" fill="#333" text-anchor="middle">运行</text>
<!-- 通讯灯(原通信灯,已改名) -->
<circle cx="80" cy="76" r="5" fill="#999999" stroke="#333" stroke-width="1"/>
<text x="80" y="90" font-family="Arial, sans-serif" font-size="8" font-weight="bold" fill="#333" text-anchor="middle">通讯</text>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -0,0 +1,146 @@
<template>
<view v-html="svgHtml" class="svg-container"></view>
</template>
<script>
export default {
props: {
// 父组件传递的参数
name: {
type: String,
default: '',
},
},
data() {
return {}
},
computed: {
svgHtml() {
if (this.name == '电压暂降') {
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
<path d="M8,50 L15,50 L18,38 L21,28 L24,38 L27,50 L30,62 L33,72 L36,62 L39,50 L42,38 L45,28 L48,38 L51,50 L54,56 L56,54 L58,55 L60,54 L63,56 L66,60 L68,62 L70,60 L72,56 L75,54 L77,52 L79,54 L81,56 L84,50 L87,38 L90,28 L93,38 L96,50" fill="none" stroke="#2563eb" stroke-width="4"/>
</svg>`
} else if (this.name == '电压暂升') {
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
<path d="M8,50 L15,50 L18,38 L21,28 L24,38 L27,50 L30,62 L33,72 L36,62 L39,50 L42,38 L45,28 L48,38 L51,50 L54,43 L56,34 L58,26 L60,34 L63,43 L66,54 L68,60 L70,54 L72,43 L75,34 L77,26 L79,34 L81,43 L84,50 L87,38 L90,28 L93,38 L96,50" fill="none" stroke="#e6a23c" stroke-width="4"/>
</svg>`
} else if (this.name == '电压中断') {
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
<path d="M8,50 L15,50 L18,38 L21,28 L24,38 L27,50 L30,62 L33,72 L36,62 L39,50 L42,38 L45,28 L48,38 L51,50 L54,50 L57,50 L60,50 L63,50 L66,50 L69,50 L72,50 L75,50 L78,50 L81,50 L84,50 L87,38 L90,28 L93,38 L96,50" fill="none" stroke="#6b7280" stroke-width="4"/>
</svg>`
} else if (this.name == '瞬态') {
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
<path d="M8,50 L15,50 L18,38 L21,28 L24,38 L27,50 L30,62 L33,72 L36,62 L39,50 L42,38 L45,28 L48,38 L51,50 L53,50 L55,50 L57,20 L59,50 L61,50 L63,50 L66,60 L68,62 L70,60 L72,56 L75,54 L77,52 L79,54 L81,56 L84,50 L87,38 L90,28 L93,38 L96,50" fill="none" stroke="#8b5cf6" stroke-width="4"/>
</svg>`
} else if (this.name == '未知') {
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
<path d="M8,50 L15,50 L18,38 L21,28 L24,38 L27,50 L30,62 L33,72 L36,62 L39,50 L42,38 L45,28 L48,38 L51,50 L54,56 L56,54 L58,55 L60,54 L63,56 L66,60 L68,62 L70,60 L72,56 L75,54 L77,52 L79,54 L81,56 L84,50 L87,38 L90,28 L93,38 L96,50" fill="none" stroke="#6b7280" stroke-width="4"/>
<text x="50" y="82" text-anchor="middle" font-size="18" fill="#6b7280" font-family="Arial, sans-serif" font-weight="bold">?</text>
</svg>`
} else if (this.name == '稳态越限') {
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
<!-- Limit line -->
<line x1="5" y1="40" x2="95" y2="40" stroke="#e6a23c" stroke-width="2" stroke-dasharray="4,4"/>
<polyline points="
5,65 12,65 15,59 18,53 21,59 24,65
27,71 30,77 33,71 36,65
39,59 42,53 45,59 48,65
" fill="none" stroke="#376cf3" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<polyline points="
51,40 54,20 57,40
" fill="none" stroke="#e6a23c" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<polyline points="
60,65 63,71 66,77 69,71 72,65
75,59 78,53 81,59 84,65
87,71 90,77 93,71 95,65
" fill="none" stroke="#376cf3" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<line x1="48" y1="65" x2="51" y2="40" stroke="#376cf3" stroke-width="4" stroke-linecap="round"/>
<line x1="57" y1="40" x2="60" y2="65" stroke="#376cf3" stroke-width="4" stroke-linecap="round"/>
<circle cx="54" cy="18" r="2" fill="#e6a23c"/>
<defs>
<marker id="arrowRed" markerWidth="6" markerHeight="5" refX="5" refY="2.5" orient="auto">
<polygon points="0,0 6,2.5 0,5" fill="#e6a23c"/>
</marker>
</defs>
</svg>`
} else if (this.name == '运行告警') {
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="40" height="40">
<path d="M78.43 4H20.06C9.48 4 1.16 12.33 1.16 22.9v38.37c0 10.57 8.32 18.9 18.9 18.9h26.49v7.27H25.77v7.41h47.96v-7.41H53.96v-7.27h26.47c10.58 0 18.9-8.33 18.9-18.9V22.9c0-10.57-8.32-18.9-18.9-18.9z m11.49 57.27c0 6.33-5.14 11.49-11.49 11.49H20.06c-6.34 0-11.49-5.15-11.49-11.49V22.9c0-6.33 5.14-11.49 11.49-11.49h59.37c6.34 0 11.49 5.15 11.49 11.49v38.37z" fill="#007aff"/>
<line x1="50" y1="28" x2="50" y2="50" stroke="#007aff" stroke-width="6" stroke-linecap="round"/>
<circle cx="50" cy="62" r="4" fill="#007aff"/>
</svg>`
} else if (this.name == '治理设备') {
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="38" height="38">
<rect x="0" y="0" width="100" height="100" rx="8" ry="8" fill="#007aff30" stroke="#007aff" stroke-width="2"/>
<rect x="8" y="8" width="84" height="84" rx="4" ry="4" fill="#FFFFFF" stroke="#007aff" stroke-width="1.5"/>
<rect x="10" y="12" width="80" height="16" rx="2" ry="2" fill="#007aff30" stroke="#CCC" stroke-width="0.8"/>
<text x="50" y="24" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#007aff" text-anchor="middle">治理设备</text>
<polyline points="14,45 22,51 30,49 38,57 46,55 54,63 62,61 70,67 78,65 86,69"
fill="none" stroke="#007aff" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
<polygon points="14,45 22,51 30,49 38,57 46,55 54,63 62,61 70,67 78,65 86,69 86,80 14,80"
fill="#007aff15"/>
<circle cx="14" cy="45" r="2" fill="#007aff"/>
<circle cx="30" cy="49" r="2" fill="#007aff"/>
<circle cx="46" cy="55" r="2" fill="#007aff"/>
<circle cx="62" cy="61" r="2" fill="#007aff"/>
<circle cx="78" cy="65" r="2" fill="#007aff"/>
<circle cx="86" cy="69" r="2" fill="#007aff"/>
<polygon points="88,65 86,70 84,65" fill="#007aff" opacity="0.7"/>
</svg>`
} else if (this.name == '监测设备') {
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="38" height="38">
<style>
text { font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif; }
</style>
<rect x="0" y="0" width="100" height="100" rx="6" ry="6" fill="#007aff30" stroke="#007aff" stroke-width="2"/>
<rect x="8" y="8" width="84" height="84" rx="3" ry="3" fill="#FFFFFF" stroke="#007aff" stroke-width="1.5"/>
<rect x="10" y="12" width="80" height="16" rx="2" ry="2" fill="#007aff30" stroke="#CCC" stroke-width="0.8"/>
<text x="50" y="24" font-size="14" font-weight="bold" fill="#007aff" text-anchor="middle">监测设备</text>
<text x="16" y="45" font-size="7" fill="#007aff">Ua: 220.5V</text>
<text x="16" y="55" font-size="7" fill="#007aff">Ub: 219.8V</text>
<text x="16" y="65" font-size="7" fill="#007aff">Uc: 220.1V</text>
<line x1="48" y1="38" x2="48" y2="78" stroke="#CCC" stroke-width="0.8" stroke-dasharray="2,2"/>
<text x="54" y="45" font-size="7" fill="#007aff">Ia: 125.3A</text>
<text x="54" y="55" font-size="7" fill="#007aff">Ib: 124.7A</text>
<text x="54" y="65" font-size="7" fill="#007aff">Ic: 125.1A</text>
</svg>`
} else if (this.name == '报告') {
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="47" height="47">
<path d="M12,12 L78,12 L88,22 L88,88 L12,88 Z" fill="none" stroke="#007aff" stroke-width="4" stroke-linejoin="round"/>
<path d="M78,12 L78,22 L88,22" fill="none" stroke="#007aff" stroke-width="4" stroke-linejoin="round"/>
<polyline points="20,50 26,50 28,46 30,42 32,46 34,50 36,54 38,58 40,54 42,50 44,46 46,42 48,46 50,50 56,50" fill="none" stroke="#007aff" stroke-width="4" stroke-linecap="round"/>
<line x1="20" y1="68" x2="52" y2="68" stroke="#007aff" stroke-width="4" opacity="0.4" stroke-linecap="round"/>
<line x1="20" y1="76" x2="42" y2="76" stroke="#007aff" stroke-width="4" opacity="0.4" stroke-linecap="round"/>
<circle cx="70" cy="68" r="9" fill="none" stroke="#007aff" stroke-width="4"/>
<line x1="76" y1="74" x2="86" y2="84" stroke="#007aff" stroke-width="4" stroke-linecap="round"/>
</svg>`
}
},
},
methods: {},
}
</script>
<style scoped>
.svg-container {
width: 100rpx;
display: flex;
justify-content: center;
align-items: center;
}
</style>

View File

@@ -0,0 +1,41 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
<!-- 设备主体 -->
<rect x="2" y="2" width="96" height="96" rx="6" ry="6" fill="#E8E8E8" stroke="#333" stroke-width="2"/>
<!-- 屏幕区域 -->
<rect x="6" y="6" width="88" height="52" rx="3" ry="3" fill="#FFFFFF" stroke="#333" stroke-width="1.5"/>
<!-- 屏幕标题栏(代替品牌标识) -->
<rect x="10" y="9" width="80" height="10" rx="2" ry="2" fill="#F0F0F0" stroke="#CCC" stroke-width="0.8"/>
<text x="50" y="17" font-family="Arial, sans-serif" font-size="7" font-weight="bold" fill="#333" text-anchor="middle">电能质量监测</text>
<!-- 屏幕内容 - 左侧参数 -->
<text x="10" y="28" font-family="Arial, sans-serif" font-size="6" fill="#000">Ua:220.5V</text>
<text x="10" y="36" font-family="Arial, sans-serif" font-size="6" fill="#000">Ub:219.8V</text>
<text x="10" y="44" font-family="Arial, sans-serif" font-size="6" fill="#000">Uc:220.1V</text>
<text x="10" y="52" font-family="Arial, sans-serif" font-size="6" fill="#000">Hz:50.02</text>
<!-- 垂直分隔线 -->
<line x1="52" y1="22" x2="52" y2="55" stroke="#CCC" stroke-width="0.8" stroke-dasharray="1.5,1.5"/>
<!-- 右侧参数 -->
<text x="58" y="28" font-family="Arial, sans-serif" font-size="6" fill="#000">Ia:125.3A</text>
<text x="58" y="36" font-family="Arial, sans-serif" font-size="6" fill="#000">Ib:124.7A</text>
<text x="58" y="44" font-family="Arial, sans-serif" font-size="6" fill="#000">Ic:125.1A</text>
<text x="58" y="52" font-family="Arial, sans-serif" font-size="6" fill="#000">PF:0.98</text>
<!-- 指示灯区域分隔线 -->
<line x1="6" y1="62" x2="94" y2="62" stroke="#999" stroke-width="1" stroke-dasharray="2,2"/>
<!-- 电源灯 -->
<circle cx="20" cy="76" r="5" fill="#10b981" stroke="#10b981" stroke-width="1"/>
<text x="20" y="90" font-family="Arial, sans-serif" font-size="8" font-weight="bold" fill="#333" text-anchor="middle">电源</text>
<!-- 运行灯 -->
<circle cx="50" cy="76" r="5" fill="#999999" stroke="#333" stroke-width="1"/>
<text x="50" y="90" font-family="Arial, sans-serif" font-size="8" font-weight="bold" fill="#333" text-anchor="middle">运行</text>
<!-- 通讯灯(原通信灯,已改名) -->
<circle cx="80" cy="76" r="5" fill="#999999" stroke="#333" stroke-width="1"/>
<text x="80" y="90" font-family="Arial, sans-serif" font-size="8" font-weight="bold" fill="#333" text-anchor="middle">通讯</text>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -1,63 +1,63 @@
<template> <template>
<view class="Cn-page" :class="{ 'no-padding': noPadding }"> <view class="Cn-page" :class="{ 'no-padding': noPadding }">
<template v-if="showLoginMsk && !login"> <template v-if="showLoginMsk && !login">
<navigator url="/pages/user/login" hover-class="none" class="page-login-btn">登录</navigator> <navigator url="/pages/user/login" hover-class="none" class="page-login-btn">登录</navigator>
</template> </template>
<template v-else> <template v-else>
<zero-loading v-if="loading" mask></zero-loading> <zero-loading v-if="loading" mask></zero-loading>
<slot name="body" v-if="beforeRender|| !loading "></slot> <slot name="body" v-if="beforeRender|| !loading "></slot>
</template> </template>
</view> </view>
</template> </template>
<script> <script>
export default { export default {
name: 'Cn-page', name: 'Cn-page',
props: { props: {
loading: { loading: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
beforeRender: { beforeRender: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
showLoginMsk: Boolean, showLoginMsk: Boolean,
noPadding: Boolean, noPadding: Boolean,
}, },
data() { data() {
return { return {
login: false, login: false,
} }
}, },
created() { created() {
this.login = uni.getStorageSync('Authorization') this.login = uni.getStorageSync('Authorization')
}, },
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.Cn-page { .Cn-page {
box-sizing: border-box; box-sizing: border-box;
padding-bottom: calc(30rpx + env(safe-area-inset-bottom)); padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
} }
.no-padding { .no-padding {
padding-bottom: 0; padding-bottom: 0;
} }
.page-login-btn { .page-login-btn {
position: fixed; position: fixed;
top: 50%; top: 50%;
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
height: 80rpx; height: 80rpx;
width: 200rpx; width: 200rpx;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
background: #449dff; background: #449dff;
color: #fff; color: #fff;
border-radius: 4rpx; border-radius: 4rpx;
} }
</style> </style>

View File

@@ -0,0 +1,550 @@
<template xlang="wxml">
<view class="tki-tree">
<view class="tki-tree-mask" :class="{ show: showTree }" @tap="_cancel"></view>
<view class="tki-tree-cnt" :class="{ show: showTree }">
<view class="tki-tree-bar">
<view class="tki-tree-bar-cancel" :style="{ color: cancelColor }" hover-class="hover-c" @tap="_cancel"
>取消</view
>
<view class="tki-tree-bar-title" :style="{ color: titleColor }">{{ title }}</view>
<view
class="tki-tree-bar-confirm"
:style="{ color: confirmColor }"
hover-class="hover-c"
@tap="_confirm"
>确定</view
>
</view>
<view class="tki-tree-bar1">
<uni-search-bar
class="uni-input"
radius="5"
placeholder="请输入关键字搜索"
clearButton="none"
@input="input"
/>
<!-- <uni-search-bar
v-model="searchValue"
clearButton="none"
bgColor="#fff"
placeholder="请输入关键词"
@input="input"
></uni-search-bar> -->
</view>
<view class="tki-tree-view">
<scroll-view class="tki-tree-view-sc" :scroll-y="true">
<block v-for="(item, index) in treeList" :key="index">
<view
class="tki-tree-item"
:style="[
{
paddingLeft: item.rank * 15 + 'px',
zIndex: item.rank * -1 + 50,
},
]"
:class="{
border: border === true,
show: item.show,
last: item.lastRank,
showchild: item.showChild,
open: item.open,
}"
>
<view class="tki-tree-label" @tap.stop="_treeItemTap(item, index)">
<image
class="tki-tree-icon"
:src="item.lastRank ? lastIcon : item.showChild ? currentIcon : defaultIcon"
></image>
{{ item.name }}
</view>
<view
class="tki-tree-check"
@tap.stop="_treeItemSelect(item, index)"
v-if="selectParent ? true : item.lastRank"
>
<view
class="tki-tree-check-yes"
v-if="item.checked && (singleChoice ? item.rank == 3 : true)"
:class="{ radio: !multiple }"
:style="{ 'border-color': confirmColor }"
>
<view
class="tki-tree-check-yes-b"
:style="{ 'background-color': confirmColor }"
></view>
</view>
<view
class="tki-tree-check-no"
v-if="!item.checked && (singleChoice ? item.rank == 3 : true)"
:class="{ radio: !multiple }"
:style="{ 'border-color': confirmColor }"
></view>
</view>
</view>
</block>
</scroll-view>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'tki-tree',
props: {
lazy: {
type: Boolean,
default: false,
},
range: {
type: Array,
default: function () {
return []
},
},
idKey: {
type: String,
default: 'id',
},
singleChoice: { type: Boolean, default: false },
rangeKey: {
type: String,
default: 'name',
},
title: {
type: String,
default: '',
},
multiple: {
// 是否可以多选
type: Boolean,
default: false,
// default: true
},
selectParent: {
//是否可以选父级
type: Boolean,
default: false,
},
foldAll: {
//折叠时关闭所有已经打开的子集,再次打开时需要一级一级打开
type: Boolean,
default: false,
},
confirmColor: {
// 确定按钮颜色
type: String,
default: '#376cf3', // #07bb07
},
cancelColor: {
// 取消按钮颜色
type: String,
default: '', // #757575
},
titleColor: {
// 标题颜色
type: String,
default: '', // #757575
},
currentIcon: {
// 展开时候的ic
type: String,
default:
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFEAAABRCAYAAACqj0o2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MEQ0QTM0MzQ1Q0RBMTFFOUE0MjY4NzI1Njc1RjI1ODIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MEQ0QTM0MzU1Q0RBMTFFOUE0MjY4NzI1Njc1RjI1ODIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowRDRBMzQzMjVDREExMUU5QTQyNjg3MjU2NzVGMjU4MiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowRDRBMzQzMzVDREExMUU5QTQyNjg3MjU2NzVGMjU4MiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PidwepsAAAK0SURBVHja7JxbTsJAFIYHww7ciStgCeoGvGxAiOsgURegoL5720AXYLiIr0aJviq3Zx3PhIEnKG3ndtr+f3KixrSUj/ZjzjClIqUUiFm2gAAQAREQEUAEREAERAQQAREQAREBREAEREBEEqa67h9RFDWllDv0awWYlqlQHmu1WjMRRMoV1QFttA12y3xRtdNczq8EsE4/f8FumX2q77ROvNXk8UGMEKdUz6tYJHljaZAbuyUH+UR1to5BEohTuqwPCeS4pAA/qY6o/kyHOAMCeRK3owJnj+rH1jjxhqpVsstaebCz6TmnHWyXyY+xHjSBWBY/bvSgadtXBj9u9KCN3rnIfkzkQVsTEEX0Y2IP2oKo/HhMICcFAThUcwVZNGU6FdbX/XURzkbVF4+ybGhjPrFdgP66QdXNurGtSdk6Xdb9nAJ8oDo3OQlsQZzkdPw41ONBo6vI5scDefRjZg+6gpg3Pxp50CXEvPjR2IOuIXL3oxUPuobI3Y9WPOgDIlc/WvOgL4iL/vqFCcD7LH0xB4hj7cfQ/fWH9qCT+FhG0tN+DBk1PzjOM0SVllixcsBT1AvYc/kAPhc0hRg/3uvxoCgKRN9+dOrBUBB9+9GpB0NC9OVH5x4MDdG1H714kANEV3705kEOEBf9dcPi/lQnsuvLg1wgSu3Ha0v7Uh4MMgUXeuG71H407a+VBy9CPQkOdw+MtB+nGbd/D+FBbhBNxo9SjwcngJjNj0E9yBFiFj8G9SBXiGn8GNyDnCEm8SMLD3KHGOdHNh7kDjHOj2w8mAeIi/5arX+c6b/fxHz9oADEdGdjR/fXCw/OOB5oVfCOgnepz8IB14PMw03jCmTE+QBx5z0gAmKSqK9OUF+hcAeIhu/QYr4Qie8rjW83hhMBERARQAREQAREBBABERCLnH8BBgA+TQI7U4t53AAAAABJRU5ErkJggg==',
},
defaultIcon: {
// 折叠时候的ic
type: String,
default:
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFEAAABRCAYAAACqj0o2AAACE0lEQVR4Xu3c200DMRCF4XEltJAOkEugA+ggpUAHoQMqiFMCdEAJUMEiS4mEELlIO7bPOeN9i6K1rG/952myyea1WiCtXmEuYBPR4RBMxInoIOCwhOtJLKVszWyXc/5y2BvNEq6I+/3+kFK6M7OHnPM7jcLKjbZAvD/uaZtzflm5P4rbWyJWgDcze1LPuzVihfxUz7sH4ilJ2bx7Isrm3RtRMu8RiHJ5j0SUyXs0okTeCIj0eSMh0uaNhkiZNyIiXd7IiDR5oyNS5M2ACJ83EyJs3myIkHkzIsLlzYwIkzc7IkTeCojD81ZCHJa3GuKQvBURu+etjNgtb3XELnlHQGyedyTEZnlHQ2ySd0RE97wjI7rlHR3RJe+JeIrbLOecD6ePpZQ6W1kn2epo4MUrPOKyLN8ppYq1+y1VStncOjIdGnFZlo+U0uOtWOeOY2TE12Ouq//pEA7xXL7XfvcufR8K0Svfv6CREN3yDYfYIt9QiK3yjYTYLF95xB75SiP2ylcZsVu+cogj8pVCHJWvEuKwfOkREfKlRkTJlxkRJl86RMR8qRBR82VChM0XHpEhX2hElnyREWnyhUNkzBcKkTVfJETafIcjKuQ7FFEl35GIMvl2R1TMtyuiar49EWXzbY5oZpv/hibXTF2h3+s60FRKeT6+3TjMS3nrA3ZFRD8xrfY3ER1kJ+JEdBBwWGKeRAfEH1wS5WFZSDB/AAAAAElFTkSuQmCC',
},
lastIcon: {
// 没有子集的ic
type: String,
default: '',
},
border: {
// 是否有分割线
type: Boolean,
default: false,
},
},
data() {
return {
showTree: false,
treeList: [],
selectIndex: -1,
returnedItem: [], //定义一个空数组
pids: [],
ancestorsIds: [],
childNums: [],
dataTree: [],
inputTimer: null, // 节流定时器标识
searchValue: '',
}
},
computed: {},
methods: {
_show() {
this.showTree = true
if (this.searchValue != '') {
this.searchValue = ''
this.input('')
}
},
_hide() {
this.showTree = false
},
_cancel() {
this._hide()
this.$emit('cancel', '')
},
_confirm() {
// 处理所选数据
let rt = [],
obj = {}
this.treeList.forEach((v, i) => {
if (this.treeList[i].checked) {
// rt.push(this.treeList[i].id)
rt.push(this.treeList[i])
}
})
this._hide()
console.log('🚀 ~ rt:', rt)
if (rt.length == 0) return
if (this.singleChoice) {
if (rt[0].rank != 3) return
}
this.$emit('confirm', rt)
},
//扁平化树结构
_renderTreeList(list = [], rank = 0, parentId = [], parents = []) {
list.forEach((item) => {
this.treeList.push({
id: item[this.idKey],
name: item[this.rangeKey],
source: item,
parentId, // 父级id数组
parents, // 父级id数组
rank, // 层级
showChild: false, //子级是否显示
open: false, //是否打开
show: rank === 0, // 自身是否显示
hideArr: [],
orChecked: item.checked ? item.checked : false,
checked: item.checked ? item.checked : false,
childNum: 0,
})
if (Array.isArray(item.children) && item.children.length > 0) {
let parentid = [...parentId],
parentArr = [...parents]
delete parentArr.children
parentid.push(item[this.idKey])
parentArr.push({
[this.idKey]: item[this.idKey],
[this.rangeKey]: item[this.rangeKey],
rank: rank,
})
// lazy
if (!this.lazy) {
this._renderTreeList(item.children, rank + 1, parentid, parentArr)
}
} else {
this.treeList[this.treeList.length - 1].lastRank = true
}
})
},
// 处理默认选择
_defaultSelect() {
this.treeList.forEach((v, i) => {
if (v.checked) {
this.treeList.forEach((v2, i2) => {
if (v.parentId.toString().indexOf(v2.parentId.toString()) >= 0) {
v2.show = true
if (v.parentId.includes(v2.id)) {
v2.showChild = true
v2.open = true
}
}
})
}
})
},
getOwn(id, arr) {
//利用foreach循环遍历
arr.forEach((item) => {
//判断递归结束条件
if (item[this.idKey] == id) {
// 存储数据到空数组
this.returnedItem = item
} else if (item.children != null) //判断chlidren是否有数据
{
//递归调用
this.getOwn(id, item.children)
}
})
return this.returnedItem
},
setShow(id, arr, isShow) {
arr.forEach((item, index) => {
if (item.parentId.includes(id)) {
this.treeList[index].showChild = isShow
this.treeList[index].show = isShow
} else if (item.children !== undefined) {
this.setShow(id, item.children, isShow)
}
})
},
// 点击
_treeItemTap(item, index) {
// console.log(item)
if (item.lastRank === true) {
//点击最后一级时触发事件
this.treeList[index].checked = !this.treeList[index].checked
this._fixMultiple(index)
return
}
let id = item.id
item.showChild = !item.showChild
// qingqian
if (item.showChild) {
// const range = this.range
const range = this.dataTree
const parentIdArr = item.parentId
// 找到当前元素
const own = this.getOwn(id, range)
const checkedChildren = own.children
// 子元素插入的索引位置
const nextIndex = this.treeList.findIndex((itemT) => itemT.id === item.id)
console.log(checkedChildren)
if (checkedChildren === undefined || checkedChildren.length < 1) {
return
}
// 子节点数量
this.treeList[index].childNum = checkedChildren.length
const newRank = item.rank + 1
checkedChildren.forEach((itemC) => {
const childObj = {
id: itemC[this.idKey],
name: itemC[this.rangeKey],
source: {},
parentId: [item.id], // 父级id数组
parents: [item], // 父级id数组
rank: newRank, // 层级
showChild: false, //子级是否显示
open: false, //是否打开
show: 1, // 自身是否显示
hideArr: [],
orChecked: this.treeList[index].checked,
checked: this.treeList[index].checked,
}
if (!this.treeList.some((itemT) => itemT.id === itemC[this.idKey])) {
this.treeList.splice(nextIndex + 1, 0, childObj)
}
})
}
// 展开/隐藏子级/孙级
let list = this.treeList
item.open = item.showChild ? true : !item.open
list.forEach((childItem, i) => {
if (item.showChild === false) {
//隐藏所有子级
if (!childItem.parentId.includes(id)) {
return
}
//TODO: 修改
if (!this.foldAll) {
if (childItem.lastRank !== true && !childItem.open) {
childItem.showChild = false
this.setShow(childItem.id, this.treeList, false)
}
// 为隐藏的内容添加一个标记
if (childItem.show) {
childItem.hideArr[item.rank] = id
}
} else {
if (childItem.lastRank !== true) {
childItem.showChild = false
// 继续隐藏子级的的子级
this.setShow(childItem.id, this.treeList, false)
}
}
if (childItem.children !== undefined) {
childItem.children.forEach((childItem1, i1) => {
if (!childItem1.parentId.includes(childItem.id)) {
return
}
childItem.children[i1].showChild = false
childItem.children[i1].show = false
})
}
childItem.show = false
} else {
// 打开子集
if (childItem.parentId[childItem.parentId.length - 1] === id) {
childItem.show = true
}
// 打开被隐藏的子集
if (childItem.parentId.includes(id) && !this.foldAll) {
// console.log(childItem.hideArr)
if (childItem.hideArr[item.rank] === id) {
childItem.show = true
if (childItem.open && childItem.showChild) {
childItem.showChild = true
} else {
childItem.showChild = false
}
childItem.hideArr[item.rank] = null
}
}
}
})
},
// 通过父id处理子级
syncChecked(trees, pid, checked) {
trees.forEach((item, index) => {
if (item.parentId.includes(pid)) {
this.treeList[index].checked = checked
this.syncChecked(trees, item.id, checked)
} else if (item.children !== undefined) {
this.syncChecked(item.children, pid, checked)
}
})
},
// 获取父级往上所有层级的id 并同步状态
setAncestors(pids, checked) {
this.treeList.forEach((item, index) => {
if (pids.includes(item.id)) {
if (checked && this.childNums[item.id] !== undefined && item.childNum === this.childNums[item.id]) {
// 子级全部选中, 父级才选中
this.treeList[index].checked = true
} else {
this.treeList[index].checked = false
}
this.setAncestors(item.parentId, checked)
}
})
},
_treeItemSelect(item, index) {
if (item.rank != 3) {
if (this.singleChoice) return
}
// if(this.singleChoice)
this.treeList[index].checked = !this.treeList[index].checked
// 选父级, 子级自动全选
this.syncChecked(this.treeList, item.id, this.treeList[index].checked)
if (item.rank > 0) {
item.parentId.forEach((pid, indexP) => {
const parent = this.treeList.filter((i) => i.id === pid)
const childNum = parent.length > 0 ? parent[0].childNum : 0
if (this.childNums[pid] === undefined) {
this.childNums[pid] = 1
} else if (this.childNums[pid] < childNum) {
this.childNums[pid]++
}
})
//子级选择/选满/取消选择, 父级往上同步状态
this.setAncestors(item.parentId, this.treeList[index].checked)
}
this._fixMultiple(index)
},
// 处理单选多选
_fixMultiple(index) {
if (!this.multiple) {
// 如果是单选
this.treeList.forEach((v, i) => {
if (i != index) {
this.treeList[i].checked = false
} else {
this.treeList[i].checked = true
}
})
}
},
// 重置数据
_reTreeList() {
this.treeList.forEach((v, i) => {
this.treeList[i].checked = v.orChecked
})
},
_initTree(range = this.range) {
this.treeList = []
this.dataTree = JSON.parse(JSON.stringify(range))
this._renderTreeList(range)
this.$nextTick(() => {
this._defaultSelect(range)
})
},
// 筛选
input(val) {
// 清除上一次的定时器,避免频繁执行
if (this.inputTimer) {
clearTimeout(this.inputTimer)
}
// 设置新的定时器,指定延迟后执行过滤逻辑
this.inputTimer = setTimeout(() => {
const keyword = val
// 执行树形过滤和初始化
this._initTree(this.filterNodes(this.range, keyword))
// 清空定时器标识
clearTimeout(this.inputTimer)
this.inputTimer = null
}, 500)
// this._initTree(this.filterNodes(this.range, val.detail.value))
},
filterNodes(node, query) {
const keyword = query.trim() // 获取搜索关键字并转换为小写
const nodes = node
// 使用递归函数过滤树形数据
const filteredNodes = []
for (const node of nodes) {
if (node.name.includes(keyword)) {
// 如果节点的标签包含关键字,将其添加到结果中
filteredNodes.push(node)
} else if (node.children && node.children.length > 0) {
// 如果节点有子节点,则递归过滤子节点
const filteredChildren = this.filterNodes(node.children, keyword)
if (filteredChildren.length > 0) {
// 如果子节点中有匹配的结果,则添加父节点
const clonedNode = { ...node, children: filteredChildren }
filteredNodes.push(clonedNode)
}
}
}
return filteredNodes
},
},
watch: {
range(list) {
this._initTree(list)
},
multiple() {
if (this.range.length) {
this._reTreeList()
}
},
selectParent() {
if (this.range.length) {
this._reTreeList()
}
},
},
mounted() {
this._initTree()
},
}
</script>
<style lang="scss" scoped>
@import './style.css';
/deep/ .uni-searchbar__box {
justify-content: left !important;
}
</style>

View File

@@ -0,0 +1,195 @@
.tki-tree-mask {
position: fixed;
top: 0rpx;
right: 0rpx;
bottom: 0rpx;
left: 0rpx;
z-index: 9998;
background-color: rgba(0, 0, 0, 0.6);
opacity: 0;
transition: all 0.3s ease;
visibility: hidden;
}
.tki-tree-mask.show {
visibility: visible;
opacity: 1;
}
.tki-tree-cnt {
position: fixed;
top: 0rpx;
right: 0rpx;
bottom: 0rpx;
left: 0rpx;
z-index: 9999;
top: 40%;
transition: all 0.3s ease;
transform: translateY(100%);
}
.tki-tree-cnt.show {
transform: translateY(0);
}
.tki-tree-bar {
background-color: #fff;
height: 72rpx;
padding-left: 20rpx;
padding-right: 20rpx;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
border-bottom-width: 1rpx !important;
border-bottom-style: solid;
border-bottom-color: #f5f5f5;
font-size: 32rpx;
color: #757575;
line-height: 1;
}
.tki-tree-bar1 {
background-color: #fff;
}
.tki-tree-bar-confirm {
color: #07bb07;
}
.tki-tree-view {
position: absolute;
top: 0rpx;
right: 0rpx;
bottom: 0rpx;
left: 0rpx;
top: 160rpx;
background-color: #fff;
padding-top: 20rpx;
padding-right: 20rpx;
padding-bottom: 20rpx;
padding-left: 20rpx;
}
.tki-tree-view-sc {
height: 100%;
overflow: hidden;
}
.tki-tree-item {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 26rpx;
/* color: #757575; */
line-height: 1;
height: 0;
opacity: 0;
transition: 0.2s;
position: relative;
overflow: hidden;
}
.tki-tree-item.show {
height: 80rpx;
opacity: 1;
}
.tki-tree-item.showchild:before {
transform: rotate(90deg);
}
.tki-tree-item.last:before {
opacity: 0;
}
.tki-tree-icon {
width: 26rpx;
height: 26rpx;
margin-right: 8rpx;
}
.tki-tree-label {
flex: 1;
display: flex;
align-items: center;
height: 100%;
line-height: 1.2;
}
.tki-tree-check {
width: 40px;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
}
.tki-tree-check-yes,
.tki-tree-check-no {
width: 20px;
height: 20px;
border-top-left-radius: 20%;
border-top-right-radius: 20%;
border-bottom-right-radius: 20%;
border-bottom-left-radius: 20%;
border-top-width: 1rpx;
border-left-width: 1rpx;
border-bottom-width: 1rpx;
border-right-width: 1rpx;
border-style: solid;
border-color: #07bb07;
display: flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
}
.tki-tree-check-yes-b {
width: 12px;
height: 12px;
border-top-left-radius: 20%;
border-top-right-radius: 20%;
border-bottom-right-radius: 20%;
border-bottom-left-radius: 20%;
background-color: #07bb07;
}
.tki-tree-check .radio {
border-top-left-radius: 50%;
border-top-right-radius: 50%;
border-bottom-right-radius: 50%;
border-bottom-left-radius: 50%;
}
.tki-tree-check .radio .tki-tree-check-yes-b {
border-top-left-radius: 50%;
border-top-right-radius: 50%;
border-bottom-right-radius: 50%;
border-bottom-left-radius: 50%;
}
.hover-c {
opacity: 0.6;
}
.search {
position: absolute;
left: 35rpx;
}
/* 基础输入框样式 */
.uni-input {
width: 95%;
height: 60rpx;
line-height: 60rpx;
border-radius: 20rpx;
/* font-size: 32rpx;
color: #333;
background: #f5f5f5;
width: 100%;
padding: 0 24rpx 0 60rpx;
box-sizing: border-box;
border: none; */
}
/* 聚焦态样式 */
.uni-input:focus {
background: #fff;
border: 2rpx solid #007aff;
}
/* 占位符样式 */
.uni-input::placeholder {
color: #999;
font-size: 28rpx;
}
/* 兼容微信小程序 */
.uni-input::-webkit-input-placeholder {
color: #999;
font-size: 28rpx;
}

View File

@@ -0,0 +1,177 @@
<template>
<view class="content">
<picker
mode="multiSelector"
@change="bindPickerChange"
@columnchange="handleColumnChange"
:value="multiIndex"
:range="onlyYear ? yearsArray : multiArray"
>
<view class="time-season">
<text>
<text v-if="showMonth">{{ year + '-' + season }} </text>
<text v-else-if="year">{{ year + (year ? '' : '') + (onlyYear ? '' : season) }} </text>
<text v-else class="prompt">请选择时间 </text>
</text>
</view>
</picker>
</view>
</template>
<script>
export default {
props: {
yearsMin: {
type: Number,
default: 5,
},
yearsMax: {
type: Number,
default: 0,
},
onlyYear: {
type: Boolean,
default: false,
},
showMonth: {
type: Boolean,
default: false,
},
},
data() {
const now = new Date()
this.currentYear = now.getFullYear() // 保存当前年份
this.currentMonth = now.getMonth() + 1 // 保存当前月份1-12
this.currentSeason = Math.ceil(this.currentMonth / 3) // 保存当前季度1-4
const yearArr = this.handleYear()
const seasonArr = ['一季度', '二季度', '三季度', '四季度']
const monthArr = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12']
return {
multiArray: [yearArr, this.showMonth ? monthArr : seasonArr],
multiIndex: [this.handleYear(true), 0],
yearsArray: [yearArr],
year: '',
season: '',
// 原始完整的时间数组(用于恢复)
fullMonthArr: [...monthArr],
fullSeasonArr: [...seasonArr]
}
},
created() {
const now = new Date()
this.year = now.getFullYear().toString()
const month = now.getMonth() + 1
// 初始化时就过滤当前年份的时间范围
this.updateTimeRange(this.currentYear)
if (this.showMonth) {
this.multiIndex = [5, month - 1]
this.season = month < 10 ? `0${month}` : `${month}`
} else {
let key = 0
if (month >= 1 && month <= 3) {
key = 0
this.season = '一季度'
} else if (month >= 4 && month <= 6) {
key = 1
this.season = '二季度'
} else if (month >= 7 && month <= 9) {
key = 2
this.season = '三季度'
} else {
key = 3
this.season = '四季度'
}
this.multiIndex = [5, key]
}
this.$emit('timeSeasonC', {
year: this.year,
season: this.season,
})
},
methods: {
// 处理年份
handleYear(nowYearIndex) {
let optionsArray = []
let years = new Date().getFullYear()
for (let i = years - this.yearsMin; i <= years + this.yearsMax; i++) {
optionsArray.push(i)
}
if (nowYearIndex) {
return optionsArray.indexOf(years)
}
return optionsArray
},
// 列变化事件:切换年份时动态调整时间范围
handleColumnChange(e) {
// 只有切换第一列(年份列)时才处理
if (e.detail.column === 0) {
const selectedYear = this.multiArray[0][e.detail.value]
// 更新时间范围(月份/季度)
this.updateTimeRange(selectedYear)
// 修正索引:如果当前选中的时间超出新范围,重置为最后一个选项
const timeLength = this.multiArray[1].length
if (this.multiIndex[1] >= timeLength) {
this.multiIndex[1] = timeLength - 1
}
}
},
// 核心:根据选中年份更新时间范围
updateTimeRange(selectedYear) {
if (this.onlyYear) return // 只选年份时无需处理
if (selectedYear === this.currentYear) {
// 当前年份:只显示到当前月/当前季度
if (this.showMonth) {
// 过滤月份只保留1到当前月
this.multiArray[1] = this.fullMonthArr.slice(0, this.currentMonth)
} else {
// 过滤季度只保留1到当前季度
this.multiArray[1] = this.fullSeasonArr.slice(0, this.currentSeason)
}
} else {
// 非当前年份:恢复完整的时间数组
this.multiArray[1] = this.showMonth ? [...this.fullMonthArr] : [...this.fullSeasonArr]
}
},
// 确认选择时间
bindPickerChange: function (e) {
this.multiIndex = e.detail.value
this.year = this.multiArray[0][this.multiIndex[0]]
if (this.onlyYear) {
this.$emit('timeSeasonC', { year: this.year })
} else {
this.season = this.multiArray[1][this.multiIndex[1]]
this.$emit('timeSeasonC', {
year: this.year,
season: this.season,
})
}
},
},
}
</script>
<style>
.content {
width: 100%;
height: 62rpx !important;
box-sizing: border-box;
background-color: #fff;
padding: 10rpx 20rpx;
line-height: 38rpx;
border: 1px solid #e5e5e5;
border-radius: 10rpx;
}
.time-season {
font-size: 28rpx;
}
.prompt {
font-size: 24rpx;
color: grey;
}
</style>

File diff suppressed because one or more lines are too long

44
main.js
View File

@@ -1,21 +1,23 @@
import App from './App' import App from './App'
import util from './common/js/util' import util from './common/js/util'
import request from './common/js/request' import request from './common/js/request'
import config from './common/js/config' import config from './common/js/config'
import cacheKey from './common/js/cacheKey' import cacheKey from './common/js/cacheKey'
import Vue from 'vue' import Vue from 'vue'
import share from "@/common/js/share.js"; import share from '@/common/js/share.js'
import uView from 'uview-ui'
Vue.config.productionTip = false Vue.config.productionTip = false
Vue.prototype.$request = request Vue.prototype.$request = request
Vue.prototype.$util = util Vue.prototype.$util = util
Vue.prototype.$config = config Vue.prototype.$config = config
Vue.prototype.$cacheKey = cacheKey Vue.prototype.$cacheKey = cacheKey
Vue.mixin(share); Vue.mixin(share)
App.mpType = 'app' Vue.use(uView)
const app = new Vue({ uni.$u.config.unit = 'rpx'
...App App.mpType = 'app'
}) const app = new Vue({
app.$mount() ...App,
})
app.$mount()

View File

@@ -2,9 +2,10 @@
"name" : "灿能物联", "name" : "灿能物联",
"appid" : "__UNI__88BC25B", "appid" : "__UNI__88BC25B",
"description" : "", "description" : "",
"versionName" : "1.6.1", "versionName" : "1.6.82",
"versionCode" : 161, "versionCode" : 170,
"transformPx" : false, "transformPx" : false,
"sassImplementationName" : "node-sass",
/* 5+App */ /* 5+App */
"app-plus" : { "app-plus" : {
"safearea" : { "safearea" : {
@@ -24,7 +25,6 @@
}, },
/* */ /* */
"modules" : { "modules" : {
"Maps" : {},
"Barcode" : {}, "Barcode" : {},
"Camera" : {}, "Camera" : {},
"Push" : {} "Push" : {}
@@ -70,12 +70,7 @@
/* SDK */ /* SDK */
"sdkConfigs" : { "sdkConfigs" : {
"ad" : {}, "ad" : {},
"maps" : { "maps" : {},
"amap" : {
"appkey_ios" : "73262624599d79ee4ad8bba2ab4a0958",
"appkey_android" : "c93dd87e087f3686a9d4463ce5ebcbe1"
}
},
"push" : { "push" : {
"unipush" : { "unipush" : {
"version" : "2", "version" : "2",
@@ -143,8 +138,8 @@
"proxy" : { "proxy" : {
"/api" : { "/api" : {
"https" : true, "https" : true,
"target" : "https://pqmcn.com:8092/api", // "target" : "https://pqmcn.com:8092/api",
// "target" : "http://192.168.1.22:10215", "target" : "http://192.168.1.103:10215",
"changOrigin" : true, "changOrigin" : true,
"pathRewrite" : { "pathRewrite" : {
"/api" : "" "/api" : ""
@@ -155,6 +150,12 @@
}, },
"router" : { "router" : {
"base" : "" "base" : ""
},
"unipush" : {
"enable" : false
},
"sdkConfigs" : {
"maps" : {}
} }
}, },
"mp-toutiao" : { "mp-toutiao" : {

1874
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +1,31 @@
{ {
"id": "yk-authpup", "id": "yk-authpup",
"name": "解决软件在运行时,未见向用户告知权限申请的目的,华为等上架被拒问题", "name": "解决软件在运行时,未见向用户告知权限申请的目的,华为等上架被拒问题",
"displayName": "解决软件在运行时,未见向用户告知权限申请的目的,华为等上架被拒问题", "displayName": "解决软件在运行时,未见向用户告知权限申请的目的,华为等上架被拒问题",
"version": "1.0.5", "version": "1.0.5",
"description": "解决软件在运行时,未见向用户告知权限申请的目的,华为等上架被拒问题", "description": "解决软件在运行时,未见向用户告知权限申请的目的,华为等上架被拒问题",
"keywords": [ "keywords": [
"uniapp", "uniapp",
"华为上架", "华为上架",
"权限", "权限",
"权限申请", "权限申请",
"权限判断" "权限判断"
], ],
"dcloudext": { "dcloudext": {
"category": [ "category": [
"前端组件", "前端组件",
"通用组件" "通用组件"
] ]
} },
} "dependencies": {
"crypto-js": "^4.2.0",
"echarts": "^5.6.0",
"html2canvas": "^1.4.1",
"image-tool": "^1.0.2",
"image-tools": "^1.4.0",
"jsrsasign": "^11.1.0",
"mqtt": "^3.0.0",
"pinyin-pro": "^3.28.1",
"uview-ui": "^2.0.38"
}
}

View File

@@ -4,6 +4,7 @@
{ {
"path": "pages/index/index", "path": "pages/index/index",
"style": { "style": {
"enablePullDownRefresh": true, // 开启下拉刷新
"navigationStyle": "custom", "navigationStyle": "custom",
"pullToRefresh": { "pullToRefresh": {
"support":true, "support":true,
@@ -13,11 +14,47 @@
} }
}, },
{ {
"path": "pages/index/message", "path": "pages/index/message1",
"style": { "style": {
"navigationBarTitleText": "消息" "navigationBarTitleText": "消息",
"enablePullDownRefresh": true, // 开启下拉刷新
"pullToRefresh": {
"support":true,
"style": "circle",
"color":"#007aff"
},
"app-plus": {
"bounce": "none",
//关闭窗口回弹效果
"titleNView": {
// 窗口的标题
"titleAlign": "center",
"padding-right": "20rpx",
"buttons": [
{
"text": "一键已读",
"fontSize": "28rpx",
"select": false,
"width": "auto"
}
]
}
}
} }
}, },
{
"path": "pages/index/report",
"style": {
"navigationBarTitleText": "报表",
"enablePullDownRefresh": true, // 开启下拉刷新
"pullToRefresh": {
"support":true,
"style": "circle",
"color":"#007aff"
}
}
},
{ {
"path": "pages/index/mine", "path": "pages/index/mine",
"style": { "style": {
@@ -130,7 +167,19 @@
"path": "pages/device/APF/detail", "path": "pages/device/APF/detail",
"style": { "style": {
"navigationBarTitleText": "APF 设备名称 + 型号", "navigationBarTitleText": "APF 设备名称 + 型号",
"enablePullDownRefresh": true "enablePullDownRefresh": true,
"pullToRefresh": {
"support":true,
"style": "circle",
"color":"#007aff"
}
}
},
{
"path": "pages/device/realTime/index",
"style": {
"navigationBarTitleText": "实时数据"
// "enablePullDownRefresh": true
} }
}, },
{ {
@@ -221,12 +270,36 @@
} }
} }
}, },
{
"path": "pages/message1/comp/preview",
"style": {
"navigationBarTitleText": "预览"
}
},
{ {
"path": "pages/message/messageDetail", "path": "pages/message/messageDetail",
"style": { "style": {
"navigationBarTitleText": "暂态事件详情" "navigationBarTitleText": "暂态事件详情"
} }
}, },
{
"path": "pages/message1/comp/transientDetails",
"style": {
"navigationBarTitleText": "暂态事件详情"
}
},
{
"path": "pages/message1/comp/steadyStateDetails",
"style": {
"navigationBarTitleText": "稳态事件详情"
}
},
{
"path": "pages/message1/comp/alarmDetails",
"style": {
"navigationBarTitleText": "运行告警详情"
}
},
{ {
"path": "pages/device/transfer", "path": "pages/device/transfer",
"style": { "style": {
@@ -353,6 +426,12 @@
"navigationBarTitleText": "服务内容配置" "navigationBarTitleText": "服务内容配置"
} }
}, },
{
"path": "pages/mine/transientSetting",
"style": {
"navigationBarTitleText": "暂态事件配置"
}
},
{ {
"path": "pages/user/erweima", "path": "pages/user/erweima",
"style": { "style": {
@@ -441,10 +520,16 @@
"text": "首页" "text": "首页"
}, },
{ {
"pagePath": "pages/index/message", "pagePath": "pages/index/message1",
"iconPath": "static/notice.png", "iconPath": "static/notice.png",
"selectedIconPath": "static/notice2.png", "selectedIconPath": "static/notice2.png",
"text": "消息" "text": "消息"
},
{
"pagePath": "pages/index/report",
"iconPath": "static/reportIco.png",
"selectedIconPath": "static/reportIco1.png",
"text": "报表"
}, },
{ {
"pagePath": "pages/index/mine", "pagePath": "pages/index/mine",
@@ -468,7 +553,8 @@
"easycom": { "easycom": {
"autoscan": true, "autoscan": true,
"custom": { "custom": {
"^rc-(.*)": "@/components/Cn-$1/Cn-$1.vue" "^rc-(.*)": "@/components/Cn-$1/Cn-$1.vue",
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
} }
}, },
"condition": { "condition": {

View File

@@ -1,62 +1,76 @@
<template> <template>
<Cn-page :loading="loading"> <Cn-page :loading="loading">
<view slot="body"> <view slot="body">
<view class="about"> <view class="about">
<view class="about-title">{{ deviceInfo.name }}</view> <view class="about-title">{{ deviceInfo.name }}</view>
<view class="about-text">设备类型{{ deviceInfo.devTypeName }}</view> <view class="about-text">设备类型{{ deviceInfo.devTypeName }}</view>
<view class="about-text">设备型号{{ deviceInfo.devModelName }}</view> <view class="about-text">设备型号{{ deviceInfo.devModelName }}</view>
<view class="about-text" <view class="about-text">设备接入方式{{ deviceInfo.devAccessMethod }}</view>
>设备接入方式{{ deviceInfo.devAccessMethod === 'cloud' ? 'CLD' : 'MQTT' }}</view <!-- <view class="about-text">设备注册时间永久使用</view> -->
> <view class="about-text">程序版本{{ deviceInfo.programVersionName }}</view>
<!-- <view class="about-text">设备注册时间永久使用</view> --> <view class="about-text">网络设备ID{{ deviceInfo.ndid }}</view>
<view class="about-text">程序版本{{ deviceInfo.programVersionName }}</view> </view>
<view class="about-text">网络设备ID{{ deviceInfo.ndid }}</view> </view>
</view> </Cn-page>
</view> </template>
</Cn-page> <script>
</template> import { queryDeivceById } from '@/common/api/device'
<script> import { queryByCode, queryCsDictTree, queryByid, queryEdDataPage } from '@/common/api/dictionary'
import { queryDeivceById } from '@/common/api/device' export default {
import { queryByCode, queryCsDictTree, queryByid, queryEdDataPage } from '@/common/api/dictionary' data() {
export default { return {
data() { loading: true,
return { deviceInfo: {},
loading: true, }
deviceInfo: {}, },
} methods: {},
}, onLoad(options) {
methods: {}, queryDeivceById(options.id).then((res) => {
onLoad(options) { this.deviceInfo = res.data[0]
queryDeivceById(options.id).then((res) => { if (this.deviceInfo.devAccessMethod == 'MQTT') {
console.log(res) queryByCode('Device_Type').then((res) => {
this.deviceInfo = res.data[0] Promise.all([queryCsDictTree(res.data.id), queryByid(res.data.id), queryEdDataPage()]).then(
queryByCode('Device_Type').then((res) => { (resp) => {
Promise.all([queryCsDictTree(res.data.id), queryByid(res.data.id), queryEdDataPage()]).then((resp) => { this.deviceInfo.devTypeName = resp[0].data.find(
console.log(resp) (item) => item.id === this.deviceInfo.devType,
this.deviceInfo.devTypeName = resp[0].data.find((item) => item.id === this.deviceInfo.devType)?.name )?.name
this.deviceInfo.devModelName = resp[1].data.find( this.deviceInfo.devModelName = resp[1].data.find(
(item) => item.id === this.deviceInfo.devModel, (item) => item.id === this.deviceInfo.devModel,
)?.name )?.name
this.loading = false this.loading = false
}) },
}) )
}) })
}, } else {
} queryByCode('DEV_CLD').then((res) => {
</script> this.deviceInfo.devTypeName = res.data.name
<style lang="scss"> Promise.all([queryCsDictTree(res.data.id), queryByid(res.data.id), queryEdDataPage()]).then(
.about { (resp) => {
padding: 34rpx; this.deviceInfo.devModelName = resp[1].data.find(
.about-title { (item) => item.id === this.deviceInfo.devModel,
font-size: 34rpx; )?.name
font-weight: bold; this.loading = false
color: #333333; },
margin-bottom: 34rpx; )
} })
.about-text { }
font-size: 28rpx; })
color: #666666; },
margin-bottom: 34rpx; }
} </script>
} <style lang="scss">
</style> .about {
padding: 34rpx;
.about-title {
font-size: 34rpx;
font-weight: bold;
color: #333333;
margin-bottom: 34rpx;
}
.about-text {
font-size: 28rpx;
color: #666666;
margin-bottom: 34rpx;
}
}
</style>

View File

@@ -1,92 +1,164 @@
<template> <template>
<view class="basic"> <view>
<view class="grid-card"> <uni-load-more status="loading" v-if="IOData.length == 0"></uni-load-more>
<view class="grid-card-title">温度</view> <view class="basic" v-else>
<view class="grid-card-content-4"> <view class="grid-card">
<template v-for="item in renderData"> <view class="grid-card-title">温度</view>
<view class="item item-title" <view class="grid-card-content-4">
>{{ item[0].clDid }} <template v-for="item in renderData">
<template v-if="item[0].clDid"> (°C)</template> <view class="item item-title"
</view> >{{ item[0].clDid }}
<view class="item item-title" <template v-if="item[0].clDid"> (°C)</template>
>{{ item[1].clDid }} </view>
<template v-if="item[1].clDid"> (°C)</template> <view class="item item-title"
</view> >{{ item[1].clDid }}
<view class="item item-title" <template v-if="item[1].clDid"> (°C)</template>
>{{ item[2].clDid }} </view>
<template v-if="item[2].clDid"> (°C)</template> <view class="item item-title"
</view> >{{ item[2].clDid }}
<view class="item item-title" <template v-if="item[2].clDid"> (°C)</template>
>{{ item[3].clDid }} </view>
<template v-if="item[3].clDid"> (°C)</template> <view class="item item-title"
</view> >{{ item[3].clDid }}
<view class="item">{{ item[0].clDid ? Math.round(item[0].value) || '-' : '' }}</view> <template v-if="item[3].clDid"> (°C)</template>
<view class="item">{{ item[1].clDid ? Math.round(item[1].value) || '-' : '' }}</view> </view>
<view class="item">{{ item[2].clDid ? Math.round(item[2].value) || '-' : '' }}</view> <view class="item">{{ item[0].clDid ? Math.round(item[0].value) || '-' : '' }}</view>
<view class="item">{{ item[3].clDid ? Math.round(item[3].value) || '-' : '' }}</view> <view class="item">{{ item[1].clDid ? Math.round(item[1].value) || '-' : '' }}</view>
</template> <view class="item">{{ item[2].clDid ? Math.round(item[2].value) || '-' : '' }}</view>
</view> <view class="item">{{ item[3].clDid ? Math.round(item[3].value) || '-' : '' }}</view>
</view> </template>
<!-- <view class="grid-card">--> </view>
<!-- <view class="grid-card-title">干接点</view>--> </view>
<!-- <view class="grid-card-content-4">--> <!-- 运维管理员工程用户 可看 -->
<!-- <view class="item item-title">干接点1</view>--> <view
<!-- <view class="item item-title">干接点2</view>--> class="grid-card"
<!-- <view class="item item-title"></view>--> v-if="userInfo.authorities == 'operation_manager' || userInfo.authorities == 'engineering_user'"
<!-- <view class="item item-title"></view>--> >
<!-- <view class="item">正常</view>--> <view class="grid-card-title">状态</view>
<!-- <view class="item">正常</view>--> <view class="grid-card-content-4">
<!-- <view class="item"></view>--> <template v-for="(item, index) in moduleData">
<!-- <view class="item"></view>--> <view class="item item-title"
<!-- </view>--> >{{ item[0].moduleName }}
<!-- </view>--> <template v-if="item[0].moduleName"></template>
</view> </view>
</template> <view class="item item-title"
<script> >{{ item[1].moduleName }}
export default { <template v-if="item[1].moduleName"></template>
data() { </view>
return {} <view class="item item-title"
}, >{{ item[2].moduleName }}
props: { <template v-if="item[2].moduleName"></template>
IOData: { </view>
type: Array, <view class="item item-title"
default: () => { >{{ item[3].moduleName }}
return [] <template v-if="item[3].moduleName"></template>
}, </view>
}, <!-- <uni-tag :text="item[0].moduleState" :type=" item[0].moduleState=='离线'?'error' : 'success'" /> -->
}, <view class="item">{{ item[0].moduleState }}</view>
computed: { <view class="item">{{ item[1].moduleState }}</view>
renderData() { <view class="item">{{ item[2].moduleState }}</view>
let arr = [] <view class="item">{{ item[3].moduleState }}</view>
// 把IOData转换成每4个一组的二维数组 </template>
for (let i = 0; i < this.IOData.length; i += 4) { </view>
this.IOData.slice(i, i + 4).forEach((item) => { </view>
<!-- <view class="grid-card">-->
if (Number.isInteger(item.value) || item.value =='') { <!-- <view class="grid-card-title">干接点</view>-->
<!-- <view class="grid-card-content-4">-->
}else { <!-- <view class="item item-title">干接点1</view>-->
item.value = (item.value-0).toFixed(2) <!-- <view class="item item-title">干接点2</view>-->
} <!-- <view class="item item-title"></view>-->
}) <!-- <view class="item item-title"></view>-->
arr.push(this.IOData.slice(i, i + 4)) <!-- <view class="item">正常</view>-->
} <!-- <view class="item">正常</view>-->
// 把每组的长度补齐到4 <!-- <view class="item"></view>-->
arr.forEach((item) => { <!-- <view class="item"></view>-->
if (item.length < 4) { <!-- </view>-->
let length = 4 - item.length <!-- </view>-->
for (let i = 0; i < length; i++) { </view>
item.push({}) </view>
} </template>
} <script>
}) import { getModuleState } from '@/common/api/harmonic.js'
console.warn(arr) export default {
return arr props: {
}, IOData: {
}, type: Array,
methods: {}, default: () => {
} return []
</script> },
<style lang="scss"> },
.basic { ndid: {
} type: String,
</style> },
},
data() {
return {
list: [],
userInfo: {},
flag: false,
}
},
computed: {
renderData() {
let arr = []
// 把IOData转换成每4个一组的二维数组
for (let i = 0; i < this.IOData.length; i += 4) {
this.IOData.slice(i, i + 4).forEach((item) => {
if (Number.isInteger(item.value) || item.value == '') {
} else {
item.value = (item.value - 0).toFixed(2)
}
})
arr.push(this.IOData.slice(i, i + 4))
}
// 把每组的长度补齐到4
arr.forEach((item) => {
if (item.length < 4) {
let length = 4 - item.length
for (let i = 0; i < length; i++) {
item.push({})
}
}
})
console.warn(arr)
return arr
},
moduleData() {
let arr = []
// 把IOData转换成每4个一组的二维数组
for (let i = 0; i < this.list.length; i += 4) {
arr.push(this.list.slice(i, i + 4))
}
// 把每组的长度补齐到4
arr.forEach((item) => {
if (item.length < 4) {
let length = 4 - item.length
for (let i = 0; i < length; i++) {
item.push({})
}
}
})
console.warn(arr)
return arr
},
},
methods: {
info() {
getModuleState({
id: this.ndid,
}).then((res) => {
this.list = res.data
})
},
},
mounted() {
this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo)
this.info()
},
}
</script>
<style lang="scss">
.basic {
}
</style>

View File

@@ -1,171 +1,184 @@
<template> <template>
<view class="basic"> <view>
<view class="grid-card"> <uni-load-more status="loading" v-if="basicData.length == 0"></uni-load-more>
<view class="grid-card-title">电网电流</view> <view class="basic" v-else>
<view class="grid-card-content-3"> <view class="grid-card">
<view class="item item-title">名称</view> <view class="grid-card-title">电网电流</view>
<view class="item item-title">有效值(A)</view> <view class="grid-card-content-3">
<view class="item item-title">畸变率(%)</view> <view class="item item-title">名称</view>
<template v-for="(item, index) in renderData.电网电流"> <view class="item item-title">有效值(A)</view>
<view class="item">{{ item.phase }}</view> <view class="item item-title">畸变率(%)</view>
<view class="item">{{ <template v-for="(item, index) in renderData.电网电流">
item['Apf_RmsI_Sys(A)'] > 0 ? item['Apf_RmsI_Sys(A)'].toFixed(2) : item['Apf_RmsI_Sys(A)'] <view class="item">{{ item.phase }}</view>
}}</view> <view class="item">{{
<view class="item">{{ item['Apf_RmsI_Sys(A)'] > 0 ? item['Apf_RmsI_Sys(A)'].toFixed(2) : item['Apf_RmsI_Sys(A)']
item['Apf_ThdA_Sys(%)'] > 0 ? item['Apf_ThdA_Sys(%)'].toFixed(2) : item['Apf_ThdA_Sys(%)'] }}</view>
}}</view> <view class="item">{{
</template> item['Apf_ThdA_Sys(%)'] > 0 ? item['Apf_ThdA_Sys(%)'].toFixed(2) : item['Apf_ThdA_Sys(%)']
</view> }}</view>
</view> </template>
<view class="grid-card"> </view>
<view class="grid-card-title">电网电压</view> </view>
<view class="grid-card-content-4"> <view class="grid-card">
<view class="item item-title">名称</view> <view class="grid-card-title">电网电压</view>
<view class="item item-title">电压(V)</view> <view class="grid-card-content-4">
<view class="item item-title">频率(Hz)</view> <view class="item item-title">名称</view>
<view class="item item-title">畸变率(%)</view> <view class="item item-title">电压(V)</view>
<template v-for="(item, index) in renderData.电网电压"> <view class="item item-title">频率(Hz)</view>
<view class="item">{{ item.phase }}</view> <view class="item item-title">畸变率(%)</view>
<view class="item">{{ <template v-for="(item, index) in renderData.电网电压">
item['Apf_PhV_Sys(V)'] > 0 ? item['Apf_PhV_Sys(V)'].toFixed(2) : item['Apf_PhV_Sys(V)'] <view class="item">{{ item.phase }}</view>
}}</view> <view class="item">{{
<view class="item">{{ item['Apf_PhV_Sys(V)'] > 0 ? item['Apf_PhV_Sys(V)'].toFixed(2) : item['Apf_PhV_Sys(V)']
item['Apf_Freq(Hz)'] > 0 ? item['Apf_Freq(Hz)'].toFixed(2) : item['Apf_Freq(Hz)'] }}</view>
}}</view> <view class="item">{{
<view class="item">{{ item['Apf_Freq(Hz)'] > 0 ? item['Apf_Freq(Hz)'].toFixed(2) : item['Apf_Freq(Hz)']
item['Apf_ThdU_Sys(%)'] > 0 ? item['Apf_ThdU_Sys(%)'].toFixed(2) : item['Apf_ThdU_Sys(%)'] }}</view>
}}</view> <view class="item">{{
</template> item['Apf_ThdU_Sys(%)'] > 0 ? item['Apf_ThdU_Sys(%)'].toFixed(2) : item['Apf_ThdU_Sys(%)']
</view> }}</view>
</view> </template>
<view class="grid-card"> </view>
<view class="grid-card-title">负载电流</view> </view>
<view class="grid-card-content-3"> <view class="grid-card">
<view class="item item-title">名称</view> <view class="grid-card-title">负载电流</view>
<view class="item item-title">有效值(A)</view> <view class="grid-card-content-3">
<view class="item item-title">畸变率(%)</view> <view class="item item-title">名称</view>
<template v-for="(item, index) in renderData.负载电流"> <view class="item item-title">有效值(A)</view>
<view class="item">{{ item.phase }}</view> <view class="item item-title">畸变率(%)</view>
<view class="item">{{ <template v-for="(item, index) in renderData.负载电流">
item['Apf_RmsI_Load(A)'] > 0 ? item['Apf_RmsI_Load(A)'].toFixed(2) : item['Apf_RmsI_Load(A)'] <view class="item">{{ item.phase }}</view>
}}</view> <view class="item">{{
<view class="item">{{ item['Apf_RmsI_Load(A)'] > 0
item['Apf_ThdA_Load(%)'] > 0 ? item['Apf_ThdA_Load(%)'].toFixed(2) : item['Apf_ThdA_Load(%)'] ? item['Apf_RmsI_Load(A)'].toFixed(2)
}}</view> : item['Apf_RmsI_Load(A)']
</template> }}</view>
</view> <view class="item">{{
</view> item['Apf_ThdA_Load(%)'] > 0
<view class="grid-card"> ? item['Apf_ThdA_Load(%)'].toFixed(2)
<view class="grid-card-title">补偿电流</view> : item['Apf_ThdA_Load(%)']
<view class="grid-card-content-3"> }}</view>
<view class="item item-title">名称</view> </template>
<view class="item item-title">有效值(A)</view> </view>
<view class="item item-title">负载率(%)</view> </view>
<template v-for="(item, index) in renderData.补偿电流"> <view class="grid-card">
<view class="item">{{ item.phase }}</view> <view class="grid-card-title">补偿电流</view>
<view class="item">{{ <view class="grid-card-content-3">
item['Apf_RmsI_TolOut(A)'] > 0 <view class="item item-title">名称</view>
? item['Apf_RmsI_TolOut(A)'].toFixed(2) <view class="item item-title">有效值(A)</view>
: item['Apf_RmsI_TolOut(A)'] <view class="item item-title">负载率(%)</view>
}}</view> <template v-for="(item, index) in renderData.补偿电流">
<view class="item">{{ <view class="item">{{ item.phase }}</view>
item['load_Rate'] > 0 ? item['load_Rate'].toFixed(2) : item['load_Rate'] <view class="item">{{
}}</view> item['Apf_RmsI_TolOut(A)'] == 3.1415926
</template> ? '-'
</view> : item['Apf_RmsI_TolOut(A)'] > 0
</view> ? item['Apf_RmsI_TolOut(A)'].toFixed(2)
</view> : item['Apf_RmsI_TolOut(A)']
</template> }}</view>
<script> <view class="item">{{
export default { item['load_Rate'] == 3.1415926
data() { ? '-'
return { : item['load_Rate'] > 0
renderData: { ? item['load_Rate'].toFixed(2)
电网电流: [], : item['load_Rate']
电网电压: [], }}</view>
负载电流: [], </template>
补偿电流: [], </view>
未知: [], </view>
}, </view>
} </view>
}, </template>
props: { <script>
basicData: { export default {
type: Array, data() {
default: () => { return {
return [] renderData: {
}, 电网电流: [],
}, 电网电压: [],
}, 负载电流: [],
watch: { 补偿电流: [],
basicData: { 未知: [],
handler: function (newVal, oldVal) { },
newVal.forEach((item) => { }
if (item.phase === 'avg') { },
return props: {
} basicData: {
let key = '' type: Array,
switch (item.statisticalName) { default: () => {
case 'Apf_RmsI_Sys(A)': return []
key = '电网电流' },
break },
case 'Apf_ThdA_Sys(%)': },
key = '电网电流' watch: {
break basicData: {
case 'Apf_PhV_Sys(V)': handler: function (newVal, oldVal) {
key = '电网电压' newVal.forEach((item) => {
break if (item.phase === 'avg') {
case 'Apf_Freq(Hz)': return
key = '电网电压' }
break let key = ''
case 'Apf_ThdU_Sys(%)': switch (item.statisticalName) {
key = '电网电压' case 'Apf_RmsI_Sys(A)':
break key = '电网电流'
case 'Apf_RmsI_Load(A)': break
key = '负载电流' case 'Apf_ThdA_Sys(%)':
break key = '电网电流'
case 'Apf_ThdA_Load(%)': break
key = '负载电流' case 'Apf_PhV_Sys(V)':
break key = '电网电压'
case 'Apf_RmsI_TolOut(A)': break
key = '补偿电流' case 'Apf_Freq(Hz)':
break key = '电网电压'
case 'Apf_PhV_Sys(V)': break
key = '补偿电流' case 'Apf_ThdU_Sys(%)':
break key = '电网电压'
case 'Apf_PhV_Sys(V)': break
key = '补偿电流' case 'Apf_RmsI_Load(A)':
break key = '负载电流'
case 'load_Rate': break
key = '补偿电流' case 'Apf_ThdA_Load(%)':
break key = '负载电流'
default: break
key = '未知' case 'Apf_RmsI_TolOut(A)':
break key = '补偿电流'
} break
case 'Apf_PhV_Sys(V)':
let index = this.renderData[key].findIndex((item2) => { key = '补偿电流'
return item2.phase === item.phase break
}) case 'Apf_PhV_Sys(V)':
if (index > -1) { key = '补偿电流'
this.renderData[key][index][item.statisticalName] = item.statisticalData // break
} else { case 'load_Rate':
this.renderData[key].push({ key = '补偿电流'
phase: item.phase, break
[item.statisticalName]: item.statisticalData, //, default:
}) key = '未知'
} break
}) }
console.log(this.renderData)
}, let index = this.renderData[key].findIndex((item2) => {
deep: true, return item2.phase === item.phase
immediate: true, })
}, if (index > -1) {
}, this.renderData[key][index][item.statisticalName] = item.statisticalData //
methods: {}, } else {
} this.renderData[key].push({
</script> phase: item.phase,
<style lang="scss"> [item.statisticalName]: item.statisticalData, //,
.basic { })
} }
</style> })
console.log(this.renderData)
},
deep: true,
immediate: true,
},
},
methods: {},
}
</script>
<style lang="scss">
.basic {
}
</style>

View File

@@ -1,120 +1,135 @@
<template> <template>
<view class="basic"> <view>
<view class="grid-card"> <uni-load-more status="loading" v-if="basicData.length == 0"></uni-load-more>
<view class="grid-card-title">电网侧</view> <view class="basic" v-else>
<view class="grid-card-content-5"> <view class="grid-card">
<view class="item item-title">名称</view> <view class="grid-card-title">电网侧</view>
<view class="item item-title">有功功率(kw)</view> <view class="grid-card-content-5">
<view class="item item-title">无功功率(kVar)</view> <view class="item item-title">名称</view>
<view class="item item-title">视在功率(kVA)</view> <view class="item item-title">有功功率(kW)</view>
<view class="item item-title">功率因数</view> <view class="item item-title">无功功率(kVar)</view>
<template v-for="(item, index) in renderData.电网侧"> <view class="item item-title">视在功率(kVA)</view>
<view class="item">{{ item.phase }}</view> <view class="item item-title">功率因数</view>
<view class="item">{{ item['Apf_P_Sys(W)']=='-'? '-':(item['Apf_P_Sys(W)'] / 1000).toFixed(2) }}</view> <template v-for="(item, index) in renderData.电网侧">
<view class="item">{{item['Apf_Q_Sys(Var)']=='-'? '-':(item['Apf_Q_Sys(Var)'] / 1000).toFixed(2) }}</view> <view class="item">{{ item.phase }}</view>
<view class="item">{{ item['Apf_S_Sys(VA)']=='-'?'-' :(item['Apf_S_Sys(VA)'] / 1000).toFixed(2) }}</view> <view class="item"
<view class="item">{{ item['Apf_PF_Sys(null)'] || '-' }}</view> >{{ item['Apf_P_Sys(W)'] == '-' ? '-' : (item['Apf_P_Sys(W)'] / 1000).toFixed(2) }}
</template> </view>
</view> <view class="item"
</view> >{{ item['Apf_Q_Sys(Var)'] == '-' ? '-' : (item['Apf_Q_Sys(Var)'] / 1000).toFixed(2) }}
<view class="grid-card"> </view>
<view class="grid-card-title">负载侧</view> <view class="item"
<view class="grid-card-content-5"> >{{ item['Apf_S_Sys(VA)'] == '-' ? '-' : (item['Apf_S_Sys(VA)'] / 1000).toFixed(2) }}
<view class="item item-title">名称</view> </view>
<view class="item item-title">有功功率(kw)</view> <view class="item">{{ item['Apf_PF_Sys(null)'] || '-' }}</view>
<view class="item item-title">无功功率(kVar)</view> </template>
<view class="item item-title">视在功率(kVA)</view> </view>
<view class="item item-title">功率因数</view> </view>
<template v-for="(item, index) in renderData.负载侧"> <view class="grid-card">
<view class="item">{{ item.phase }}</view> <view class="grid-card-title">负载侧</view>
<view class="item">{{ item['Apf_P_Load(W)']=='-'?'-': (item['Apf_P_Load(W)'] / 1000).toFixed(2) }}</view> <view class="grid-card-content-5">
<view class="item">{{ item['Apf_Q_Load(Var)']=='-'? '-':(item['Apf_Q_Load(Var)'] / 1000).toFixed(2) }}</view> <view class="item item-title">名称</view>
<view class="item">{{ item['Apf_S_Load(VA)']=='-'? '-':(item['Apf_S_Load(VA)'] / 1000).toFixed(2) }}</view> <view class="item item-title">有功功率(kW)</view>
<view class="item">{{ item['Apf_PF_Load(null)'] || '-' }}</view> <view class="item item-title">无功功率(kVar)</view>
</template> <view class="item item-title">视在功率(kVA)</view>
</view> <view class="item item-title">功率因数</view>
</view> <template v-for="(item, index) in renderData.负载侧">
</view> <view class="item">{{ item.phase }}</view>
</template> <view class="item"
<script> >{{ item['Apf_P_Load(W)'] == '-' ? '-' : (item['Apf_P_Load(W)'] / 1000).toFixed(2) }}
export default { </view>
data() { <view class="item">{{
return { item['Apf_Q_Load(Var)'] == '-' ? '-' : (item['Apf_Q_Load(Var)'] / 1000).toFixed(2)
renderData: { }}</view>
电网侧: [], <view class="item"
负载侧: [], >{{ item['Apf_S_Load(VA)'] == '-' ? '-' : (item['Apf_S_Load(VA)'] / 1000).toFixed(2) }}
未知: [], </view>
}, <view class="item">{{ item['Apf_PF_Load(null)'] || '-' }}</view>
} </template>
}, </view>
props: { </view>
basicData: { </view>
type: Array, </view>
default: () => { </template>
return [] <script>
}, export default {
}, data() {
}, return {
watch: { renderData: {
basicData: { 电网侧: [],
handler: function (newVal, oldVal) { 负载侧: [],
newVal.forEach((item) => { 未知: [],
if (item.phase === 'avg') { },
return }
} },
let key = '' props: {
switch (item.statisticalName) { basicData: {
case 'Apf_P_Sys(W)': type: Array,
key = '电网侧' default: () => {
break return []
case 'Apf_Q_Sys(Var)': },
key = '电网侧' },
break },
case 'Apf_S_Sys(VA)': watch: {
key = '电网侧' basicData: {
break handler: function (newVal, oldVal) {
case 'Apf_PF_Sys(null)': newVal.forEach((item) => {
key = '电网侧' if (item.phase === 'avg') {
break return
case 'Apf_P_Load(W)': }
key = '负载侧' let key = ''
break switch (item.statisticalName) {
case 'Apf_Q_Load(Var)': case 'Apf_P_Sys(W)':
key = '负载侧' key = '电网侧'
break break
case 'Apf_S_Load(VA)': case 'Apf_Q_Sys(Var)':
key = '负载侧' key = '电网侧'
break break
case 'Apf_PF_Load(null)': case 'Apf_S_Sys(VA)':
key = '负载侧' key = '电网侧'
break break
default: case 'Apf_PF_Sys(null)':
key = '未知' key = '电网侧'
break break
} case 'Apf_P_Load(W)':
key = '负载侧'
let index = this.renderData[key].findIndex((item2) => { break
return item2.phase === item.phase case 'Apf_Q_Load(Var)':
}) key = '负载侧'
if (index > -1) { break
this.renderData[key][index][item.statisticalName] = item.statisticalData || '-' case 'Apf_S_Load(VA)':
} else { key = '负载侧'
this.renderData[key].push({ break
phase: item.phase, case 'Apf_PF_Load(null)':
[item.statisticalName]: item.statisticalData || '-', key = '负载侧'
}) break
} default:
}) key = '未知'
console.log(this.renderData) break
}, }
deep: true,
immediate: true, let index = this.renderData[key].findIndex((item2) => {
}, return item2.phase === item.phase
}, })
methods: {}, if (index > -1) {
} this.renderData[key][index][item.statisticalName] = item.statisticalData || '-'
</script> } else {
<style lang="scss"> this.renderData[key].push({
.basic { phase: item.phase,
} [item.statisticalName]: item.statisticalData || '-',
</style> })
}
})
console.log(this.renderData)
},
deep: true,
immediate: true,
},
},
methods: {},
}
</script>
<style lang="scss">
.basic {
}
</style>

View File

@@ -1,374 +1,385 @@
<template> <template>
<view> <view>
<div class="header-form"> <uni-load-more status="loading" v-if="basicData.length == 0"></uni-load-more>
<uni-data-select
v-model="parity" <view v-else>
:localdata="parityOption" <div class="header-form">
@change="initEcharts" <uni-data-select
style="flex: 1" v-model="parity"
:clear="false" :localdata="parityOption"
></uni-data-select> @change="initEcharts"
<!-- <uni-data-checkbox v-model="dataRadio" :localdata="dataOptions" @change="initEcharts"></uni-data-checkbox> --> style="flex: 1"
<uni-data-select :clear="false"
v-model="dataRadio" ></uni-data-select>
:localdata="dataOptions" <!-- <uni-data-checkbox v-model="dataRadio" :localdata="dataOptions" @change="initEcharts"></uni-data-checkbox> -->
@change="initEcharts" <uni-data-select
style="flex: 2; margin-left: 20rpx" v-model="dataRadio"
:clear="false" :localdata="dataOptions"
></uni-data-select> @change="initEcharts"
</div> style="flex: 2; margin-left: 20rpx"
<view class="charts-box"> :clear="false"
<!-- <view class="data-time">{{ time }}</view> --> ></uni-data-select>
<!-- <qiun-data-charts type="bar" :ontouch="true" :opts="opts" :chartData="chartData" /> --> </div>
<view style="width: 100%; height: 100%"><l-echart ref="chartRef" @finished="init"></l-echart></view> <view class="charts-box">
</view> <!-- <view class="data-time">{{ time }}</view> -->
</view> <!-- <qiun-data-charts type="bar" :ontouch="true" :opts="opts" :chartData="chartData" /> -->
</template> <view style="width: 100%; height: 100%"><l-echart ref="chartRef" @finished="init"></l-echart></view>
</view>
<script> </view>
import * as echarts from '@/uni_modules/lime-echart/static/echarts.min' </view>
export default { </template>
props: {
basicData: { <script>
type: Array, import * as echarts from '@/uni_modules/lime-echart/static/echarts.min'
default: () => [], export default {
}, props: {
dataTime: { basicData: {
type: [String, Number], type: Array,
default: '', default: () => [],
}, },
}, dataTime: {
data() { type: [String, Number],
return { default: '',
parityOption: [ },
{ },
text: '奇次', data() {
value: 2, return {
}, parityOption: [
{ {
text: '次', text: '次',
value: 1, value: 2,
}, },
], {
parity: 2, text: '偶次',
time: '', value: 1,
dataOptions: [], },
dataRadio: 0, ],
renderData: { parity: 2,
电网侧: { time: '',
Apf_HarmI: {}, dataOptions: [],
Apf_HarmUR: {}, dataRadio: 0,
}, renderData: {
负载: { 电网: {
Apf_HarmI: {}, Apf_HarmI: {},
Apf_HarmUR: {}, Apf_HarmUR: {},
}, },
}, 负载侧: {
chartData: {}, Apf_HarmI: {},
//您可以通过修改 config-ucharts.js 文件中下标为 ['column'] 的节点来配置全局默认参数,如都是默认参数,此处可以不传 opts 。实际应用过程中 opts 只需传入与全局默认参数中不一致的【某一个属性】即可实现同类型的图表显示不同的样式,达到页面简洁的需求。 Apf_HarmUR: {},
option: { },
tooltip: { },
trigger: 'axis', chartData: {},
axisPointer: { //您可以通过修改 config-ucharts.js 文件中下标为 ['column'] 的节点来配置全局默认参数,如都是默认参数,此处可以不传 opts 。实际应用过程中 opts 只需传入与全局默认参数中不一致的【某一个属性】即可实现同类型的图表显示不同的样式,达到页面简洁的需求。
type: 'shadow', option: {
}, tooltip: {
confine: true, trigger: 'axis',
}, axisPointer: {
color: [ type: 'shadow',
'#1890FF', },
'#91CB74', confine: true,
'#FAC858', },
'#EE6666', color: [
'#73C0DE', '#1890FF',
'#3CA272', '#91CB74',
'#FC8452', '#FAC858',
'#9A60B4', '#EE6666',
'#ea7ccc', '#73C0DE',
], '#3CA272',
legend: { '#FC8452',
data: ['电网侧', '负载侧'], '#9A60B4',
left: 0, '#ea7ccc',
}, ],
grid: { legend: {
left: 10, data: ['电网侧', '负载侧'],
right: 10, left: 0,
bottom: 15, },
top: 30, grid: {
containLabel: true, left: 10,
}, right: 10,
xAxis: [ bottom: 15,
{ top: 30,
type: 'value', containLabel: true,
},
axisLine: { xAxis: [
show: true, {
}, type: 'value',
minInterval: 0.5,
position: 'top', // 设置 x 轴在顶部 axisLine: {
}, show: true,
], },
yAxis: [ minInterval: 0.5,
{ position: 'top', // 设置 x 轴在顶部
type: 'category', },
axisTick: { show: false }, ],
data: [], yAxis: [
splitLine: { show: true }, {
axisLine: { type: 'category',
lineStyle: { axisTick: { show: false },
color: '#999999', data: [],
}, splitLine: { show: true },
}, axisLine: {
axisLabel: { lineStyle: {
color: '#666666', color: '#999999',
}, },
}, },
], axisLabel: {
series: [ color: '#666666',
{ },
name: '电网侧', },
type: 'bar', ],
label: { series: [
normal: { {
color: '#666', name: '电网侧',
show: true, type: 'bar',
position: 'right', label: {
fontSize: '8px', normal: {
color: '#666',
}, show: true,
}, position: 'right',
barGap: '10%', fontSize: '8px',
data: [], },
}, },
{ barGap: '10%',
name: '负载侧', data: [],
type: 'bar', },
barCateGoryGap:20, {
label: { name: '负载侧',
normal: { type: 'bar',
color: '#666', barCateGoryGap: 20,
show: true, label: {
position: 'right', normal: {
fontSize: '8px', color: '#666',
}, show: true,
}, position: 'right',
fontSize: '8px',
data: [], },
}, },
],
}, data: [],
opts: { },
// enableScroll: true, ],
dataLabel: false, },
color: [ opts: {
'#1890FF', // enableScroll: true,
'#91CB74', dataLabel: false,
'#FAC858', color: [
'#EE6666', '#1890FF',
'#73C0DE', '#91CB74',
'#3CA272', '#FAC858',
'#FC8452', '#EE6666',
'#9A60B4', '#73C0DE',
'#ea7ccc', '#3CA272',
], '#FC8452',
padding: [0, 20, 0, 0], '#9A60B4',
legend: { '#ea7ccc',
position: 'top', ],
float: 'left', padding: [0, 20, 0, 0],
}, legend: {
xAxis: { position: 'top',
// disableGrid: true, float: 'left',
boundaryGap: 'justify', },
itemCount: 8, xAxis: {
// scrollShow: true, // disableGrid: true,
data: [ boundaryGap: 'justify',
{ itemCount: 8,
min: 0, // scrollShow: true,
}, data: [
], {
min: 0, min: 0,
// max: 10, },
],
position: 'top', min: 0,
formatter: (value, index, opts) => { // max: 10,
console.log(123, value, index, opts)
}, position: 'top',
}, formatter: (value, index, opts) => {
yAxis: {}, console.log(123, value, index, opts)
extra: { },
bar: { },
type: 'group', yAxis: {},
width: 30, extra: {
meterBorde: 1, bar: {
meterFillColor: '#FFFFFF', type: 'group',
activeBgColor: '#000000', width: 30,
activeBgOpacity: 0.08, meterBorde: 1,
barBorderCircle: true, meterFillColor: '#FFFFFF',
seriesGap: 2, activeBgColor: '#000000',
categoryGap: 6, activeBgOpacity: 0.08,
}, barBorderCircle: true,
}, seriesGap: 2,
}, categoryGap: 6,
} },
}, },
watch: { },
basicData: { }
handler(newVal, oldVal) { },
console.log(this.basicData) watch: {
let basicData = JSON.parse(JSON.stringify(this.basicData)) basicData: {
// this.dataRadio = 0 handler(newVal, oldVal) {
this.renderData = { console.log(this.basicData)
电网侧: { let basicData = JSON.parse(JSON.stringify(this.basicData))
Apf_HarmI: {}, // this.dataRadio = 0
Apf_HarmUR: {}, this.renderData = {
}, 电网侧: {
负载侧: { Apf_HarmI: {},
Apf_HarmI: {}, Apf_HarmUR: {},
Apf_HarmUR: {}, },
}, 负载侧: {
} Apf_HarmI: {},
let arr = [ Apf_HarmUR: {},
{ },
name: '电网侧', }
key: 'Apf_HarmI_Sys', let arr = [
}, {
{ name: '电网侧',
name: '电网侧', key: 'Apf_HarmI_Sys',
key: 'Apf_HarmUR_Sys', },
}, {
{ name: '电网侧',
name: '负载侧', key: 'Apf_HarmUR_Sys',
key: 'Apf_HarmI_Load', },
}, {
{ name: '负载侧',
name: '负载侧', key: 'Apf_HarmI_Load',
key: 'Apf_HarmUR_Load', },
}, {
] name: '负载侧',
basicData.forEach((item) => { key: 'Apf_HarmUR_Load',
let have = arr.find((item2) => { },
return item.statisticalName.indexOf(item2.key) > -1 ]
}) basicData.forEach((item) => {
if (!have) return let have = arr.find((item2) => {
let name1 = have['name'] return item.statisticalName.indexOf(item2.key) > -1
let name2 = have.key.split('_')[0] + '_' + have.key.split('_')[1] })
if (this.renderData[name1][name2][item.phase]) { if (!have) return
this.renderData[name1][name2][item.phase][item.statisticalName] = item.statisticalData || 0 let name1 = have['name']
} else { let name2 = have.key.split('_')[0] + '_' + have.key.split('_')[1]
this.renderData[name1][name2][item.phase] = { if (this.renderData[name1][name2][item.phase]) {
[item.statisticalName]: item.statisticalData || 0, this.renderData[name1][name2][item.phase][item.statisticalName] = item.statisticalData || 0
} } else {
} this.renderData[name1][name2][item.phase] = {
}) [item.statisticalName]: item.statisticalData || 0,
console.log(this.renderData) }
let dataOptions = [] }
let type = [ })
{ console.log(this.renderData)
name: '谐波电流幅值序列', let dataOptions = []
key: 'Apf_HarmI', let type = [
}, {
{ name: '谐波电流幅值',
name: '谐波电压含有率序列', key: 'Apf_HarmI',
key: 'Apf_HarmUR', },
}, {
] name: '谐波电压含有率',
Object.keys(this.renderData['电网侧']['Apf_HarmI']).forEach((item, index) => { key: 'Apf_HarmUR',
type.forEach((item2) => { },
dataOptions.push({ ]
text: item + '相' + item2.name, Object.keys(this.renderData['电网侧']['Apf_HarmI']).forEach((item, index) => {
pointer: item2.key + '_' + item, type.forEach((item2) => {
value: dataOptions.length, dataOptions.push({
}) text: item + '相' + item2.name,
}) pointer: item2.key + '_' + item,
}) value: dataOptions.length,
this.dataOptions = dataOptions })
console.log(dataOptions) })
this.initEcharts() })
this.dataOptions = dataOptions
this.time = this.$util.parseTime(this.dataTime - 8 * 60 * 60) console.log(dataOptions)
}, this.initEcharts()
deep: true,
immediate: true, this.time = this.$util.parseTime(this.dataTime - 8 * 60 * 60)
}, },
}, deep: true,
methods: { immediate: true,
async init() { },
// chart 图表实例不能存在data里 },
const chart = await this.$refs.chartRef.init(echarts) methods: {
chart.setOption(this.option) async init() {
}, // chart 图表实例不能存在data里
initEcharts() { const chart = await this.$refs.chartRef.init(echarts)
setTimeout(() => { chart.setOption(this.option)
let obj = JSON.parse( },
JSON.stringify( initEcharts() {
this.renderData['电网侧']['Apf_HarmI'][Object.keys(this.renderData['电网侧']['Apf_HarmI'])[0]], setTimeout(() => {
), if (
) this.renderData['电网侧']['Apf_HarmI'][Object.keys(this.renderData['电网侧']['Apf_HarmI'])[0]] ==
let key = this.dataOptions[this.dataRadio].pointer.split('_') undefined
console.log(key) )
let name1 = key[0] + '_' + key[1] return
let name2 = key[2] let obj = JSON.parse(
this.chartData = { JSON.stringify(
categories: Object.keys(obj) this.renderData['电网侧']['Apf_HarmI'][Object.keys(this.renderData['电网侧']['Apf_HarmI'])[0]],
.map((item) => { ),
// Apf_HarmI_Sys_36(A) 匹配36 )
return Number(item.match(/\d+/)[0]) let key = this.dataOptions[this.dataRadio].pointer.split('_')
}) console.log(key)
.filter((item) => { let name1 = key[0] + '_' + key[1]
return item % 2 === this.parity - 1 let name2 = key[2]
}), this.chartData = {
series: [ categories: Object.keys(obj)
{ .map((item) => {
name: '电网侧', // Apf_HarmI_Sys_36(A) 匹配36
data: Object.values(this.renderData['电网侧'][name1][name2]).filter((item, index) => { return Number(item.match(/\d+/)[0])
return index % 2 === this.parity - 1 })
}), .filter((item) => {
}, return item % 2 === this.parity - 1
{ }),
name: '负载侧', series: [
data: Object.values(this.renderData['负载侧'][name1][name2]).filter((item, index) => { {
return index % 2 === this.parity - 1 name: '电网侧',
}), data: Object.values(this.renderData['电网侧'][name1][name2]).filter((item, index) => {
}, return index % 2 === this.parity - 1
], }),
} },
// /传值到echart {
this.option.yAxis[0].data = Object.keys(obj) name: '负载侧',
.map((item) => { data: Object.values(this.renderData['负载侧'][name1][name2]).filter((item, index) => {
// Apf_HarmI_Sys_36(A) 匹配36 return index % 2 === this.parity - 1
return Number(item.match(/\d+/)[0]) }),
}) },
.filter((item) => { ],
return item % 2 === this.parity - 1 }
}).reverse() // /传值到echart
this.option.series[0].data = Object.values(this.renderData['电网侧'][name1][name2]).filter( this.option.yAxis[0].data = Object.keys(obj)
(item, index) => { .map((item) => {
return index % 2 === this.parity - 1 // Apf_HarmI_Sys_36(A) 匹配36
}, return Number(item.match(/\d+/)[0])
).reverse().map(item=>item.toFixed(2)) })
this.option.series[1].data = Object.values(this.renderData['负载侧'][name1][name2]).filter( .filter((item) => {
(item, index) => { return item % 2 === this.parity - 1
return index % 2 === this.parity - 1 })
}, .reverse()
).reverse().map(item=>item.toFixed(2)) this.option.series[0].data = Object.values(this.renderData['电网侧'][name1][name2])
this.init() .filter((item, index) => {
}, 100) return index % 2 === this.parity - 1
}, })
}, .reverse()
} .map((item) => item.toFixed(2))
</script> this.option.series[1].data = Object.values(this.renderData['负载侧'][name1][name2])
.filter((item, index) => {
<style lang="scss"> return index % 2 === this.parity - 1
.charts-box { })
margin-top: 20rpx; .reverse()
height: 100vh; .map((item) => item.toFixed(2))
.data-time { this.init()
position: absolute; }, 100)
right: 20rpx; },
margin-top: 18rpx; },
font-size: 24rpx; }
} </script>
}
.header-form { <style lang="scss">
display: flex; .charts-box {
} margin-top: 20rpx;
</style> height: 100vh;
.data-time {
position: absolute;
right: 20rpx;
margin-top: 18rpx;
font-size: 24rpx;
}
}
.header-form {
display: flex;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -1,230 +1,228 @@
<template> <template>
<Cn-page :loading="loading"> <Cn-page :loading="loading">
<view class="content" slot="body"> <view class="content" slot="body">
<view class="content-item" v-for="(item, index) in store.data" :key="index" @click="jump(item)"> <view class="content-item" v-for="(item, index) in store.data" :key="index" @click="jump(item)">
<view class="content-item-header"> <view class="content-item-header">
<uni-badge class="uni-badge-left-margin" :is-dot="true" :text="item.status == '1' ? 0 : 1" <uni-badge
absolute="rightTop" size="small" style="margin-top: 30rpx;"> class="uni-badge-left-margin"
<view class="content-item-header-icon"> :is-dot="true"
<image mode="aspectFill" :src="staticIcon" style="height: 60rpx; width: 60rpx"></image> :text="item.status == '1' ? 0 : 1"
</view> absolute="rightTop"
</uni-badge> size="small"
<view class="content-item-header-right"> style="margin-top: 30rpx"
<view class="content-item-header-right-title">{{ item.equipmentName }}</view> >
<!-- <view class="content-item-header-right-des">{{ item.engineeringName }} {{ item.projectName }}</view> --> <view class="content-item-header-icon">
<view class="content-item-header-right-des">工程名称{{ item.engineeringName }}</view> <!-- <image mode="aspectFill" :src="staticIcon" style="height: 60rpx; width: 60rpx"></image> -->
<view class="content-item-header-right-des">项目名称{{ item.projectName }}</view> <Cn-icon-transient :name="`运行告警`" />
<view class="content-item-header-right-des">监测点名称{{ item.lineName }}</view> </view>
<view class="content-item-header-right-des">暂态事件类型{{ item.showName.slice(0, -4) }}</view> </uni-badge>
<!-- <view class="content-item-header-right-des">{{ item.subTitle }}</view> --> <view class="content-item-header-right">
</view> <view class="content-item-header-right-title">{{ item.equipmentName }}</view>
<view class="ml10" v-if="type === '0' || item.status != '1'">🔍</view>
</view> <view class="content-item-header-right-des">工程名称{{ item.engineeringName }}</view>
<view class="content-item-footer">{{ item.subTitle }}</view> <view class="content-item-header-right-des">项目名称{{ item.projectName }}</view>
</view>
<!-- <uni-card </view>
:title="item.equipmentName" <view class="ml10" v-if="type === '0' || item.status != '1'">
:extra="item.status == '1' ? '' : '未读'" <uni-icons type="search" size="25" color="#376cf3"></uni-icons
:sub-title="item.subTitle" ></view>
thumbnail="https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png" </view>
@click="jump(item)" <view class="content-item-footer">{{ item.subTitle }}</view>
v-for="(item, index) in store.data" </view>
:key="index"
> <Cn-empty v-if="store.empty" style="padding-top: 400rpx"></Cn-empty>
<view class="term-list-bottom"> <uni-load-more
<view class="term-list-bottom-item" v-for="(item2, textIndex) in item.dataSet" :key="textIndex"> v-if="store.status == 'loading' || (store.data && store.data.length > 0)"
{{ item2.showName + ':' + (item2.value == 3.1415926 ? '-' : item2.value) + (item2.unit || '') }} :status="store.status"
</view> ></uni-load-more>
</view> </view>
</uni-card> --> </Cn-page>
<Cn-empty v-if="store.empty" style="padding-top: 400rpx"></Cn-empty> </template>
<uni-load-more v-if="store.status == 'loading' || (store.data && store.data.length > 0)"
:status="store.status"></uni-load-more> <script>
</view> import list from '@/common/js/list'
</Cn-page> import { updateStatus } from '@/common/api/message'
</template>
export default {
<script> mixins: [list],
import list from '@/common/js/list' data() {
import { updateStatus } from '@/common/api/message' return {
loading: true,
export default { type: '',
mixins: [list], staticIcon: '',
data() { }
return { },
loading: true, onLoad(o) {
type: '', this.type = '3'
staticIcon: '', this.devId = o.id
} switch (this.type) {
}, case '0':
onLoad(o) { uni.setNavigationBarTitle({ title: '暂态事件' })
this.type = '3' this.staticIcon = '/static/zantai2.png'
this.devId = o.id break
switch (this.type) { case '1':
case '0': uni.setNavigationBarTitle({ title: '稳态事件' })
uni.setNavigationBarTitle({ title: '暂态事件' }) this.staticIcon = '/static/steady2.png'
this.staticIcon = '/static/zantai2.png' break
break case '2':
case '1': uni.setNavigationBarTitle({ title: '运行事件' })
uni.setNavigationBarTitle({ title: '稳态事件' }) this.staticIcon = '/static/run2.png'
this.staticIcon = '/static/steady2.png' break
break case '3':
case '2': uni.setNavigationBarTitle({ title: '设备告警' })
uni.setNavigationBarTitle({ title: '运行事件' }) this.staticIcon = '/static/device_bad2.png'
this.staticIcon = '/static/run2.png' break
break }
case '3': this.init()
uni.setNavigationBarTitle({ title: '设备告警' }) },
this.staticIcon = '/static/device_bad2.png' onNavigationBarButtonTap(e) {
break uni.showModal({
} title: '提示',
this.init() content: '确定要全部标记为已读吗?',
}, success: (res) => {
onNavigationBarButtonTap(e) { if (res.confirm) {
uni.showModal({ updateStatus({
title: '提示', type: this.type,
content: '确定要全部标记为已读吗?', eventIds: [],
success: (res) => { }).then(() => {
if (res.confirm) { this.loading = true
updateStatus({ this.store.reload()
type: this.type, })
eventIds: [], }
}).then(() => { },
this.loading = true })
this.store.reload() },
}) methods: {
} async init() {
}, let dictData = await this.$util.getDictData('app_event')
}) console.log(dictData)
}, this.store = this.DataSource('/cs-harmonic-boot/eventUser/queryEventpage')
methods: { this.store.params.type = this.type
async init() { this.store.params.deviceId = this.deviceId
let dictData = await this.$util.getDictData('app_event') this.store.params.startTime = this.$util.getBeforeDays()
console.log(dictData) this.store.params.endTime = this.$util.getToday()
this.store = this.DataSource('/cs-harmonic-boot/eventUser/queryEventpage') this.store.loadedCallback = () => {
this.store.params.type = this.type this.store.data.forEach((item) => {
this.store.params.deviceId = this.deviceId if (this.type === '3') {
this.store.loadedCallback = () => { item.showName = '告警,告警码:' + (item.code || '-')
this.store.data.forEach((item) => { }
if (this.type === '3') { if (this.type !== '0') {
item.showName = '告警,告警码:' + item.code item.subTitle = `${item.startTime}发生${item.showName}`
} } else {
if (this.type !== '0') { item.subTitle =
item.subTitle = `${item.startTime}` `发生时间:${item.startTime}` +
} else { item.dataSet
item.subTitle = .map((item2) => {
`${item.startTime}` + return (
item.dataSet item2.showName +
.map((item2) => { '' +
return ( (item2.value == 3.1415926 ? '-' : item2.value) +
item2.showName + (item2.unit || '')
'' + )
(item2.value == 3.1415926 ? '-' : item2.value) + })
(item2.unit || '') .join('')
) }
}) })
.join('') this.loading = false
} }
}) this.store.reload()
this.loading = false },
} jump(item) {
this.store.reload() // if (this.type === '0') {
}, let str = JSON.stringify(item).replace(/%/g, '百分比')
jump(item) { uni.navigateTo({ url: '/pages/message/messageDetail?detail=' + encodeURIComponent(str) })
if (this.type === '0') { // } else {
let str = JSON.stringify(item).replace(/%/g, '百分比') // if (item.status != '1') {
uni.navigateTo({ url: '/pages/message/messageDetail?detail=' + encodeURIComponent(str) }) // item.status = '1'
} else { // updateStatus({
if (item.status != '1') { // eventIds: [item.id],
item.status = '1' // })
updateStatus({ // }
eventIds: [item.id], // }
}) },
} },
} }
}, </script>
},
} <style lang="scss">
</script> .content {
.content-item {
<style lang="scss"> margin: 20rpx;
.content { padding: 20rpx 20rpx;
.content-item { box-shadow: rgba(0, 0, 0, 0.08) 0px 0px 6rpx 2rpx;
margin: 20rpx; border-radius: 8rpx;
padding: 20rpx 20rpx; border: 1px solid #ebeef5;
box-shadow: rgba(0, 0, 0, 0.08) 0px 0px 6rpx 2rpx; background: #fff;
border-radius: 8rpx;
border: 1px solid #ebeef5; .content-item-header {
background: #fff; display: flex;
padding: 20rpx 0;
.content-item-header { border-bottom: 1px solid #ebeef5;
display: flex;
padding: 20rpx 0; .content-item-header-icon {
border-bottom: 1px solid #ebeef5; display: flex;
align-items: center;
.content-item-header-icon { justify-content: center;
display: flex; width: 110rpx;
align-items: center; height: 110rpx;
justify-content: center; border-radius: 8rpx;
width: 100rpx; // background: $uni-theme-color;
height: 100rpx; background-color: #376cf320;
border-radius: 8rpx; }
background: $uni-theme-color;
} .content-item-header-right {
flex: 1;
.content-item-header-right { display: flex;
flex: 1; flex-direction: column;
display: flex; justify-content: space-between;
flex-direction: column; // height: 140rpx;
justify-content: space-between; margin-left: 20rpx;
// height: 140rpx;
margin-left: 20rpx; .content-item-header-right-title {
font-size: 28rpx;
.content-item-header-right-title { font-weight: bold;
font-size: 28rpx; color: #111;
font-weight: bold; }
color: #111;
} .content-item-header-right-des {
font-size: 24rpx;
.content-item-header-right-des { color: #999;
font-size: 24rpx; }
color: #999; }
} }
}
} .content-item-footer {
margin-top: 20rpx;
.content-item-footer { font-size: 24rpx;
margin-top: 20rpx; color: #999;
font-size: 24rpx; }
color: #999; }
}
} // padding-top: 20rpx;
}
// padding-top: 20rpx;
} .term-list-bottom {
.term-list-bottom-item {
.term-list-bottom { font-size: 28rpx;
.term-list-bottom-item { margin-bottom: 10rpx;
font-size: 28rpx; display: flex;
margin-bottom: 10rpx; justify-content: space-between;
display: flex; // view:first-of-type{
justify-content: space-between; // color: #111;
// view:first-of-type{ // }
// color: #111; }
// }
} .term-list-bottom-item:last-of-type {
margin-bottom: 0;
.term-list-bottom-item:last-of-type { }
margin-bottom: 0; }
}
} /deep/ .uni-list-item {
background-color: $uni-theme-white !important;
/deep/ .uni-list-item { }
background-color: $uni-theme-white !important;
} /deep/ .uni-card__header-extra-text {
color: #dd524d !important;
/deep/ .uni-card__header-extra-text { font-size: 20rpx;
color: #dd524d !important; }
font-size: 20rpx; </style>
}
</style>

View File

@@ -59,7 +59,7 @@
</template> </template>
<script> <script>
export default { export default {
data () { data() {
return { return {
} }
}, },

View File

@@ -60,7 +60,7 @@
</template> </template>
<script> <script>
export default { export default {
data () { data() {
return { return {
} }
}, },

View File

@@ -83,7 +83,7 @@
</template> </template>
<script> <script>
export default { export default {
data () { data() {
return { return {
} }
}, },

View File

@@ -1,286 +1,292 @@
<template> <template>
<Cn-page :loading="loading" noPadding> <Cn-page :loading="loading" noPadding>
<view slot="body"> <view slot="body">
<view class="detail"> <view class="detail">
<view class="detail-header"> <view class="detail-header">
<view class="header"> <view class="header">
<image <image
src="http://localhost:8088/api/system-boot/file/download?filePath=topology/1aca98ceb22a1fc33b81d9101275ef1.png" src="http://localhost:8088/api/system-boot/file/download?filePath=topology/1aca98ceb22a1fc33b81d9101275ef1.png"
mode="widthFix" style="width: 100%" /> mode="widthFix" style="width: 100%" />
</view> </view>
<!-- <view class="des"> <!-- <view class="des">
<text>设备基础信息</text> <text>设备基础信息</text>
<text class="ml10">设备状态</text> <text class="ml10">设备状态</text>
</view> --> </view> -->
<view class="nav"> <view class="nav">
<view class="nav-menu" :class="{ 'nav-menu-active': navMenuActive == index }" <view class="nav-menu" :class="{ 'nav-menu-active': navMenuActive == index }"
v-for="(item, index) in navMenuList" :key="index" @click="navMenuClick(index)">{{ item.text v-for="(item, index) in navMenuList" :key="index" @click="navMenuClick(index)">{{ item.text
}} }}
</view> </view>
</view> </view>
</view> </view>
<view class="content"> <view class="content">
<DianWang v-if="navMenuActive == 0"></DianWang> <DianWang v-if="navMenuActive == 0"></DianWang>
<NiBian v-else-if="navMenuActive == 1"></NiBian> <NiBian v-else-if="navMenuActive == 1"></NiBian>
<ShuChu v-else-if="navMenuActive == 2"></ShuChu> <ShuChu v-else-if="navMenuActive == 2"></ShuChu>
<GanJieDian v-else-if="navMenuActive == 3"></GanJieDian> <GanJieDian v-else-if="navMenuActive == 3"></GanJieDian>
<ZhuangTaiLiang v-else-if="navMenuActive == 4"> </ZhuangTaiLiang> <ZhuangTaiLiang v-else-if="navMenuActive == 4"> </ZhuangTaiLiang>
<QiTa v-else-if="navMenuActive == 5"></QiTa> <QiTa v-else-if="navMenuActive == 5"></QiTa>
<view style="height: 20rpx"></view> <view style="height: 20rpx"></view>
</view> </view>
<!-- <uni-fab <!-- <uni-fab
ref="fab" ref="fab"
direction="vertical" direction="vertical"
horizontal="right" horizontal="right"
vertical="bottom" vertical="bottom"
:content="content" :content="content"
@trigger="trigger" @trigger="trigger"
/> --> /> -->
<hover-menu :btnList="content" @trigger='trigger'></hover-menu> <hover-menu :btnList="content" @trigger='trigger'></hover-menu>
</view> </view>
</view> </view>
</Cn-page> </Cn-page>
</template> </template>
<script> <script>
import DianWang from './comp/dianWang.vue' import DianWang from './comp/dianWang.vue'
import NiBian from './comp/niBian.vue' import NiBian from './comp/niBian.vue'
import ShuChu from './comp/shuChu.vue' import ShuChu from './comp/shuChu.vue'
import GanJieDian from './comp/ganJieDian.vue' import GanJieDian from './comp/ganJieDian.vue'
import ZhuangTaiLiang from './comp/zhuangTaiLiang.vue' import ZhuangTaiLiang from './comp/zhuangTaiLiang.vue'
import QiTa from './comp/qiTa.vue' import QiTa from './comp/qiTa.vue'
import { manualAccess } from '@/common/api/accessBoot' import { manualAccess } from '@/common/api/accessBoot'
import hoverMenu from '@/hover-menu/components/hover-menu/hover-menu.vue'; import hoverMenu from '@/hover-menu/components/hover-menu/hover-menu.vue';
export default { export default {
components: { components: {
DianWang, DianWang,
NiBian, NiBian,
ShuChu, ShuChu,
GanJieDian, GanJieDian,
ZhuangTaiLiang, ZhuangTaiLiang,
QiTa, QiTa,
hoverMenu hoverMenu
}, },
data() { data() {
return { return {
loading: false, loading: false,
navMenuActive: 0, navMenuActive: 0,
navHeight: 0, navHeight: 0,
pageOptions: {}, pageOptions: {},
navMenuList: [ navMenuList: [
{ {
text: '电网数据', text: '电网数据',
}, },
{ {
text: '逆变数据', text: '逆变数据',
}, },
{ {
text: '输出数据', text: '输出数据',
}, },
{ {
text: '干接点', text: '干接点',
}, },
{ {
text: '状态量', text: '状态量',
}, },
{ {
text: '其他', text: '其他',
}, },
], ],
content: [ content: [
{ {
iconPath: '/static/report.png', iconPath: '/static/tongji.png',
text: '告警', text: '事件',
}, },
{ // {
iconPath: '/static/record.png', // iconPath: '/static/record.png',
text: '记录', // text: '记录',
}, // },
{ {
iconPath: '/static/about.png', iconPath: '/static/about.png',
text: '关于', text: '关于',
}, },
{ // {
iconPath: '/static/access.png', // iconPath: '/static/access.png',
text: '接入', // text: '接入',
}, // },
], ],
} }
}, },
methods: { methods: {
trigger(e) { trigger(e) {
console.log(e) console.log(e)
if (e.text === '分享') { if (e.text === '分享') {
this.$refs.share.open() this.$refs.share.open()
} else if (e.text === '删除') { } else if (e.text === '删除') {
uni.showModal({ uni.showModal({
title: '提示', title: '提示',
content: '确定删除该设备吗?', content: '确定删除该设备吗?',
success: function (res) { success: function (res) {
if (res.confirm) { if (res.confirm) {
console.log('用户点击确定') console.log('用户点击确定')
} else if (res.cancel) { } else if (res.cancel) {
console.log('用户点击取消') console.log('用户点击取消')
} }
}, },
}) })
} else if (e.text === '下载') { } else if (e.text === '下载') {
this.$util.toast('下载成功') this.$util.toast('下载成功')
} else if (e.text === '记录') { } else if (e.text === '记录') {
uni.navigateTo({ url: '/pages/device/DVR/record' }) uni.navigateTo({ url: '/pages/device/DVR/record' })
} else if (e.text === '告警') { } else if (e.text === '事件') {
uni.navigateTo({ url: '/pages/device/DVR/report' }) uni.navigateTo({ url: '/pages/device/DVR/report' })
} else if (e.text === '关于') { } else if (e.text === '关于') {
uni.navigateTo({ url: '/pages/device/DVR/about' }) uni.navigateTo({ url: '/pages/device/DVR/about' })
} else if (e.text === '移交') { } else if (e.text === '移交') {
uni.navigateTo({ url: '/pages/device/transfer' }) uni.navigateTo({ url: '/pages/device/transfer' })
} else if (e.text === '反馈') { } else if (e.text === '反馈') {
uni.navigateTo({ url: '/pages/device/feedback' }) uni.navigateTo({ url: '/pages/device/feedback' })
} else if (e.text === '用户') { } else if (e.text === '用户') {
uni.navigateTo({ url: '/pages/device/user' }) uni.navigateTo({ url: '/pages/device/user' })
} else if (e.text === '接入') { } else if (e.text === '接入') {
manualAccess({ nDid: this.pageOptions.ndid }).then((res) => { manualAccess({ nDid: this.pageOptions.ndid }).then((res) => {
this.$util.toast(res.message) this.$util.toast(res.message)
}) })
} }
// this.$refs.fab.close() // this.$refs.fab.close()
}, },
navMenuClick(idx) { navMenuClick(idx) {
this.navMenuActive = idx this.navMenuActive = idx
uni.pageScrollTo({ scrollTop: 0, duration: 0 }) uni.pageScrollTo({ scrollTop: 0, duration: 0 })
}, },
init() { init() {
let userInfo = uni.getStorageSync(this.$cacheKey.userInfo) let userInfo = uni.getStorageSync(this.$cacheKey.userInfo)
console.log(userInfo.authorities) console.log(userInfo.authorities)
switch (userInfo.authorities) { switch (userInfo.authorities) {
case 1: case 1:
this.content.splice( this.content.splice(
0, 0,
0, 0,
{ {
iconPath: '/static/version.png', iconPath: '/static/version.png',
text: '版本', text: '版本',
}, },
{ {
iconPath: '/static/template.png', iconPath: '/static/template.png',
text: '模版', text: '模版',
}, },
) )
break break
case 3: case 3:
this.content.splice(1, 0, { this.content.splice(1, 0, {
iconPath: '/static/transfer.png', iconPath: '/static/transfer.png',
text: '移交', text: '移交',
}) })
break break
case 4: case 4:
this.content.splice( this.content.splice(
0, 0,
0, 0,
{ {
iconPath: '/static/subordinate.png', iconPath: '/static/subordinate.png',
text: '用户', text: '用户',
}, },
{ {
iconPath: '/static/delate.png', iconPath: '/static/delate.png',
text: '删除', text: '删除',
}, },
) )
break break
case 5: case 5:
this.content.push({ this.content.push({
iconPath: '/static/feedback.png', iconPath: '/static/feedback.png',
text: '反馈', text: '反馈',
}) })
break break
default: default:
break break
} }
setTimeout(() => { if (this.userInfo.authorities === 'operation_manager') {
// 获取nav高度 this.content.push({
uni.createSelectorQuery() iconPath: '/static/access.png',
.select('.nav') text: '接入',
.boundingClientRect((rect) => { })
this.navHeight = rect.height }
}) setTimeout(() => {
.exec() // 获取nav高度
}, 1000) uni.createSelectorQuery()
}, .select('.nav')
}, .boundingClientRect((rect) => {
onLoad(options) { this.navHeight = rect.height
this.pageOptions = options })
this.init() .exec()
}, }, 1000)
} },
</script> },
<style lang="scss"> onLoad(options) {
.detail { this.pageOptions = options
this.init()
// background: $uni-theme-white; },
.header {} }
</script>
.des { <style lang="scss">
padding: 20rpx 20rpx 0; .detail {
font-size: 28rpx;
color: #999; // background: $uni-theme-white;
} .header {}
// .nav { .des {
// position: sticky; padding: 20rpx 20rpx 0;
// top: 0; font-size: 28rpx;
// left: 0; color: #999;
// padding-top: 20rpx; }
// display: flex;
// flex-wrap: wrap; // .nav {
// background: rgb(243, 244, 245); // position: sticky;
// top: 0;
// .nav-menu { // left: 0;
// padding: 10rpx 20rpx; // padding-top: 20rpx;
// margin-left: 20rpx; // display: flex;
// margin-bottom: 20rpx; // flex-wrap: wrap;
// font-size: 28rpx; // background: rgb(243, 244, 245);
// border-radius: 8rpx;
// background: $uni-theme-white; // .nav-menu {
// padding: 10rpx 20rpx;
// &-active { // margin-left: 20rpx;
// background: $uni-theme-color; // margin-bottom: 20rpx;
// color: #fff; // font-size: 28rpx;
// } // border-radius: 8rpx;
// } // background: $uni-theme-white;
// } // &-active {
// background: $uni-theme-color;
.content { // color: #fff;
box-sizing: border-box; // }
padding: 0 20rpx; // }
}
// }
.detail-header {
position: sticky; .content {
top: 0; box-sizing: border-box;
left: 0; padding: 0 20rpx;
z-index: 2; }
background: #f3f4f5;
} .detail-header {
} position: sticky;
top: 0;
/deep/ .uni-fab__circle--rightBottom { left: 0;
right: 8px !important; z-index: 2;
bottom: 8px !important; background: #f3f4f5;
} }
}
/deep/ .uni-fab--rightBottom {
right: 8px !important; /deep/ .uni-fab__circle--rightBottom {
bottom: 8px !important; right: 8px !important;
} bottom: 8px !important;
}
/deep/ .uni-fab__circle {
width: 50px; /deep/ .uni-fab--rightBottom {
height: 54px; right: 8px !important;
} bottom: 8px !important;
}
/deep/ .uni-fab__content--flexDirectionEnd {
width: 50px !important; /deep/ .uni-fab__circle {
// height: 50px !important; width: 50px;
} height: 54px;
</style> }
/deep/ .uni-fab__content--flexDirectionEnd {
width: 50px !important;
// height: 50px !important;
}
</style>

View File

@@ -284,17 +284,17 @@ export default {
}) })
}) })
}, },
chooseLocation() { // chooseLocation() {
uni.chooseLocation({ // uni.chooseLocation({
success: function (res) { // success: function (res) {
this.address = res.name // this.address = res.name
console.log('位置名称:' + res.name) // console.log('位置名称:' + res.name)
console.log('详细地址:' + res.address) // console.log('详细地址:' + res.address)
console.log('纬度:' + res.latitude) // console.log('纬度:' + res.latitude)
console.log('经度:' + res.longitude) // console.log('经度:' + res.longitude)
}, // },
}) // })
}, // },
chooseGplot() { chooseGplot() {
this.$refs.gplot.open() this.$refs.gplot.open()
}, },

View File

@@ -1,379 +1,477 @@
<template> <template>
<Cn-page :loading="loading"> <Cn-page :loading="loading">
<template slot="body"> <template slot="body">
<view class="device"> <view class="device">
<view class="nav" :style="{ top: navTabHeight + 'px' }"> <view class="nav" :style="{ top: navTabHeight + 'px' }">
<view <view class="nav-menu" @click="selectEngineering"
class="nav-menu" >{{
:class="{ 'nav-menu-active': select.engineeringName }" select.engineeringName
@click="selectEngineering" ? select.engineeringName.length > 6
>{{ select.engineeringName || '全部工程' }} ? select.engineeringName.substring(0, 6) + '...'
<uni-icons : select.engineeringName
type="bottom" : '全部工程'
size="14" }}
:color="select.engineeringName ? '#376cf3' : '#666'" <uni-icons type="bottom" size="14"></uni-icons>
></uni-icons> </view>
</view> <picker
<picker @change="projectNameChange"
@change="projectNameChange" @cancel="select.selectProject = false"
@cancel="select.selectProject = false" :value="select.projectNameIndex"
:value="select.projectNameIndex" :range="filterProjectList"
:range="filterProjectList" range-key="text"
range-key="text" v-if="select.engineeringId"
v-if="select.engineeringId" >
> <view class="nav-menu" @click="select.selectProject = true">
<view {{
class="nav-menu" select.projectName
:class="{ 'nav-menu-active': select.projectName }" ? select.projectName.length > 6
@click="select.selectProject = true" ? select.projectName.substring(0, 6) + '...'
> : select.projectName
{{ : '全部项目'
select.projectName }}
? select.projectName.length > 6 <uni-icons type="top" size="14" v-if="select.selectProject"></uni-icons>
? select.projectName.substring(0, 6) + '...' <uni-icons type="bottom" size="14" v-else></uni-icons>
: select.projectName </view>
: '全部项目' </picker>
}} <picker
<uni-icons @change="runStatusChange"
type="top"
size="14" :value="select.runStatusIndex"
:color="select.projectName ? '#376cf3' : '#666'" :range="projectType"
v-if="select.selectProject" range-key="text"
></uni-icons> >
<uni-icons <view class="nav-menu" >
type="bottom" {{
size="14" select.runStatusName
:color="select.projectName ? '#376cf3' : '#666'" ? select.runStatusName.length > 12
v-else ? select.runStatusName.substring(0, 12) + '...'
></uni-icons> : select.runStatusName
</view> : '全部状态'
</picker> }}
<picker <uni-icons type="top" size="14" v-if="select.runStatusSelect"></uni-icons>
@change="runStatusChange" <uni-icons type="bottom" size="14" v-else></uni-icons>
@cancel="select.runStatusSelect = false" </view>
:value="select.runStatusIndex" </picker>
:range="projectType" </view>
range-key="text"
> <view class="nav" style="padding: 0 10px !important">
<view <view style="flex: 1"></view>
class="nav-menu" <template v-if="transfer || share">
:class="{ 'nav-menu-active': select.runStatusName }" <view class="nav-menu nav-menu-btn" @click="cancel">取消</view>
@click="select.runStatusSelect = true" <view class="nav-menu nav-menu-btn" @click="submit">确定</view>
> </template>
{{ <template v-else-if="store.data.length">
select.runStatusName <view
? select.runStatusName.length > 4 class="nav-menu nav-menu-btn"
? select.runStatusName.substring(0, 4) + '...' @click="selectDevice('transfer')"
: select.runStatusName v-if="
: '全部状态' userInfo.authorities === 'app_vip_user' || userInfo.authorities === 'engineering_user'
}} "
<uni-icons >移交
type="top" </view>
size="14" <view
:color="select.runStatusName ? '#376cf3' : '#666'" class="nav-menu nav-menu-btn"
v-if="select.runStatusSelect" @click="selectDevice('share')"
></uni-icons> v-if="userInfo.authorities === 'app_vip_user'"
<uni-icons >分享
type="bottom" </view>
size="14" </template>
:color="select.runStatusName ? '#376cf3' : '#666'" </view>
v-else
></uni-icons> <view class="content device" :style="{ minHeight: minHeight }">
</view> <uni-swipe-action>
</picker> <uni-swipe-action-item
<view style="flex: 1"></view> v-for="(item, index) in store.data"
<!-- <picker @change="runStatusChange" :value="select.projectTypeIndex" :range="projectType" range-key="text"> :threshold="0"
<view class="nav-menu" :class="{ 'nav-menu-active': select.projectType }" :right-options="item.isTop == 0 ? options1 : options12"
>{{ select.projectType || '类型' }} @click="bindClick($event, item)"
</view> >
</picker> --> <Cn-device-card :device="item" :key="index">
</view> <template v-slot:title>
<view class="content device" :style="{ minHeight: minHeight }"> <!-- 卡片标题 -->
<Cn-device-card v-for="(item, index) in store.data" :device="item" :key="index"> </Cn-device-card>
<uni-load-more <switch
v-if="store.status == 'loading' || (store.data && store.data.length > 0)" v-if="transfer || share"
:status="store.status" :checked="checkList.indexOf(item.equipmentId) > -1"
></uni-load-more> style="transform: scale(0.8); position: relative; left: 20rpx"
<Cn-empty v-else></Cn-empty> @change="switchChange(item)"
</view> />
</view> <view class="star-icon" v-else>
</template> <!-- <uni-icons type="search" size="25" color="#376cf3"></uni-icons> -->
</Cn-page> 🔍
</template> </view>
<script> </template>
import { getProjectList } from '@/common/api/project' </Cn-device-card>
import { queryDictData } from '@/common/api/dictionary' </uni-swipe-action-item>
import list from '@/common/js/list' </uni-swipe-action>
<uni-load-more
export default { v-if="store.status == 'loading' || (store.data && store.data.length > 0)"
mixins: [list], :status="store.status"
data() { ></uni-load-more>
return { <Cn-empty v-else></Cn-empty>
loading: true, </view>
transfer: false, </view>
share: false, </template>
checkList: [], </Cn-page>
select: { </template>
projectName: '', <script>
projectNameIndex: 0, import { getProjectList } from '@/common/api/project'
projectSelect: false, import { queryDictData } from '@/common/api/dictionary'
engineeringName: '', import list from '@/common/js/list'
engineeringId: '', import { engineeringPinToTop } from '@/common/api/device'
runStatusName: '', export default {
runStatusIndex: 0, mixins: [list],
runStatusSelect: false, data() {
}, return {
minHeight: 0, loading: true,
navTabHeight: 0, transfer: false,
engineeringList: [], share: false,
projectList: [], checkList: [],
projectType: [ select: {
{ projectName: '',
text: '全部', projectNameIndex: 0,
value: '', projectSelect: false,
}, engineeringName: '',
{ engineeringId: '',
text: '离线', runStatusName: '',
value: 1, runStatusIndex: 0,
}, runStatusSelect: false,
{ },
text: '在线', userInfo: {},
value: 2, minHeight: 0,
}, navTabHeight: 0,
], engineeringList: [],
pageOptions: {}, projectList: [],
} projectType: [
}, {
watch: { text: '全部',
select: { value: '',
handler(val, oldVal) { },
if (this.loading) return {
this.store.params.projectId = text: '离线',
val.projectNameIndex === 0 ? '' : this.filterProjectList[val.projectNameIndex].value value: 1,
this.store.params.runStatus = val.runStatusIndex === 0 ? '' : this.projectType[val.runStatusIndex].value },
this.store.params.engineerId = val.engineeringId || '' {
this.store.reload() text: '在线',
}, value: 2,
deep: true, },
}, ],
}, pageOptions: {},
computed: { options1: [
filterProjectList() { {
return this.projectList.filter( text: '置顶',
(item) => item.engineeringId === this.select.engineeringId || item.value === '-1', style: {
) backgroundColor: '#376cf3',
}, },
}, },
onLoad(options) { ],
let engineering = uni.getStorageSync('engineering') options12: [
this.pageOptions = options {
switch (options.type) { text: '取消',
case 'onLineDevs': style: {
this.select.runStatusIndex = 2 backgroundColor: '#ccc',
this.select.runStatusName = '在线' },
break },
case 'offLineDevs': ],
this.select.runStatusIndex = 1 }
this.select.runStatusName = '离线' },
break watch: {
case 'currentOnLineDevs': select: {
this.select.runStatusIndex = 2 handler(val, oldVal) {
this.select.engineeringName = engineering.name if (this.loading) return
this.select.engineeringId = engineering.id this.store.params.projectId =
this.select.runStatusName = '在线' val.projectNameIndex === 0 ? '' : this.filterProjectList[val.projectNameIndex].value
break this.store.params.runStatus = val.runStatusIndex === 0 ? '' : this.projectType[val.runStatusIndex].value
case 'currentOffLineDevs': this.store.params.engineerId = val.engineeringId || ''
this.select.runStatusIndex = 1 this.store.reload()
this.select.engineeringName = engineering.name },
this.select.engineeringId = engineering.id deep: true,
this.select.runStatusName = '离线' },
break },
case 'allEngineering': computed: {
this.select.engineeringName = '' filterProjectList() {
this.select.engineeringId = '' return this.projectList.filter(
break (item) => item.engineeringId === this.select.engineeringId || item.value === '-1',
case 'nowEngineering': )
this.select.engineeringName = engineering.name },
this.select.engineeringId = engineering.id },
break created() {
default: this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo)
break },
} onLoad(options) {
this.init() let engineering = uni.getStorageSync('engineering')
}, this.pageOptions = options
onShow() { switch (options.type) {
let engineering = uni.getStorageSync('onceSelectEngineering') case 'onLineDevs':
if (engineering) { this.select.runStatusIndex = 2
uni.removeStorageSync('onceSelectEngineering') this.select.runStatusName = '在线'
this.select.engineeringId = engineering.id break
this.select.engineeringName = engineering.name case 'offLineDevs':
this.select.projectNameIndex = 0 this.select.runStatusIndex = 1
} this.select.runStatusName = '离线'
}, break
methods: { case 'currentOnLineDevs':
selectEngineering() { this.select.runStatusIndex = 2
uni.navigateTo({ this.select.engineeringName = engineering.name
url: '/pages/home/selectEngineering?from=once', this.select.engineeringId = engineering.id
}) this.select.runStatusName = '在线'
}, break
deviceIcon(e) { case 'currentOffLineDevs':
let str = '' this.select.runStatusIndex = 1
switch (e) { this.select.engineeringName = engineering.name
case 1: this.select.engineeringId = engineering.id
str = '/static/device_bad.png' this.select.runStatusName = '离线'
break break
case 2: case 'allEngineering':
str = '/static/device.png' this.select.engineeringName = ''
break this.select.engineeringId = ''
default: break
str = '/static/device.png' case 'nowEngineering':
break this.select.engineeringName = engineering.name
} this.select.engineeringId = engineering.id
return str break
}, default:
switchChange(e) { break
console.log(e) }
let index = this.checkList.indexOf(e.equipmentId) this.init()
if (index > -1) { },
this.checkList.splice(index, 1) onShow() {
} else { let engineering = uni.getStorageSync('onceSelectEngineering')
this.checkList.push(e.equipmentId) if (engineering) {
} uni.removeStorageSync('onceSelectEngineering')
}, this.select.engineeringId = engineering.id
cancel() { this.select.engineeringName = engineering.name
this.transfer = false this.select.projectNameIndex = 0
this.share = false this.select.projectName = ''
this.checkList = [] this.getProjectList()
}, }
submit() { this.store && this.store.reload()
console.log(this.checkList) },
if (this.checkList.length === 0) { methods: {
this.$util.toast('请选择设备') bindClick(e, item) {
return engineeringPinToTop({
} targetId: item.equipmentId,
if (this.transfer) { targetType: 1,
uni.navigateTo({ url: '/pages/device/transfer?id=' + this.checkList.join(',') }) userId: uni.getStorageSync(this.$cacheKey.userInfo).userIndex,
} else if (this.share) { }).then((res) => {
uni.navigateTo({ url: '/pages/device/share?id=' + this.checkList.join(',') }) if (res.code == 'A0000') {
} this.$util.toast('操作成功!')
this.cancel() this.store.search()
}, } else {
async init() { this.$util.toast(res.message)
console.warn('init') }
this.getEngineeringList() })
this.getProjectList() },
this.getDeviceList() selectEngineering() {
}, uni.navigateTo({
getDeviceList() { url: '/pages/home/selectEngineering?from=once',
this.store = this.DataSource('/cs-device-boot/EquipmentDelivery/queryEquipmentByProject') })
this.store.params.engineerId = this.select.engineeringId },
this.store.params.runStatus = deviceIcon(e) {
this.select.runStatusIndex === 0 ? '' : this.projectType[this.select.runStatusIndex].value let str = ''
this.store.params.pageSize = 50 switch (e) {
this.store.firstCallBack = (res) => { case 1:
this.loading = false str = '/static/device_bad.png'
uni.createSelectorQuery() break
.select('.uni-navbar') case 2:
.boundingClientRect((rect1) => { str = '/static/device.png'
if (!rect1) return break
this.navTabHeight = rect1.height default:
uni.createSelectorQuery() str = '/static/device.png'
.select('.nav') break
.boundingClientRect((rect2) => { }
if (!rect2) return return str
// #ifdef H5 },
this.minHeight = 'calc(100vh - ' + (this.navTabHeight + rect2.height + 50) + 'px)' switchChange(e) {
// #endif console.log(e)
// #ifdef APP-PLUS let index = this.checkList.indexOf(e.equipmentId)
this.minHeight = 'calc(100vh - ' + (this.navTabHeight + rect2.height) + 'px)' if (index > -1) {
console.log(this.minHeight) this.checkList.splice(index, 1)
// #endif } else {
}) this.checkList.push(e.equipmentId)
.exec() }
}) },
.exec() cancel() {
} this.transfer = false
this.store.reload() this.share = false
}, this.checkList = []
getProjectList() { },
this.projectList = uni.getStorageSync('projectList') submit() {
}, console.log(this.checkList)
getEngineeringList() { if (this.checkList.length === 0) {
this.engineeringList = uni.getStorageSync('engineeringList') this.$util.toast('请选择设备')
}, return
queryDictData() { }
queryDictData('项目类型').then((res) => { if (this.transfer) {
this.projectType = [ uni.navigateTo({ url: '/pages/device/transfer?id=' + this.checkList.join(',') })
{ } else if (this.share) {
text: '全部类型', uni.navigateTo({ url: '/pages/device/share?id=' + this.checkList.join(',') })
value: '', }
}, this.cancel()
...res.data.map((item) => { },
return { async init() {
text: item.anotherName, console.warn('init')
value: item.id, this.getEngineeringList()
} this.getProjectList()
}), this.getDeviceList()
] },
}) getDeviceList() {
}, this.store = this.DataSource('/cs-device-boot/EquipmentDelivery/queryEquipmentByProject')
submitFeedBack() { this.store.params.engineerId = this.select.engineeringId
uni.navigateTo({ url: '/pages/home/feedback' }) this.store.params.runStatus =
}, this.select.runStatusIndex === 0 ? '' : this.projectType[this.select.runStatusIndex].value
runStatusChange(e) { this.store.params.pageSize = 50
this.select.runStatusSelect = false this.store.firstCallBack = (res) => {
this.select.runStatusIndex = e.detail.value this.loading = false
if (e.detail.value === 0) { uni.createSelectorQuery()
this.select.runStatusName = '' .select('.uni-navbar')
return .boundingClientRect((rect1) => {
} if (!rect1) return
this.select.runStatusName = this.projectType[e.detail.value].text this.navTabHeight = rect1.height
}, uni.createSelectorQuery()
projectNameChange(e) { .select('.nav')
this.select.selectProject = false .boundingClientRect((rect2) => {
console.log(e) if (!rect2) return
this.select.projectNameIndex = e.detail.value // #ifdef H5
if (e.detail.value === 0) { this.minHeight = 'calc(100vh - ' + (this.navTabHeight + rect2.height + 50) + 'px)'
this.select.projectName = '' // #endif
return // #ifdef APP-PLUS
} this.minHeight = 'calc(100vh - ' + (this.navTabHeight + rect2.height) + 'px)'
this.select.projectName = this.projectList[e.detail.value].text console.log(this.minHeight)
}, // #endif
registerDevice() { })
uni.showModal({ .exec()
title: '提示', })
content: '请选择设备类型', .exec()
confirmText: '直连设备', }
cancelText: '网关接入', this.store.reload()
cancelColor: '#007aff', },
success: ({ confirm, cancel }) => {
if (confirm) { getProjectList() {
uni.navigateTo({ getProjectList({
url: '/pages/device/new', pageNum: 1,
}) pageSize: 9999,
} else if (cancel) { engineeringId: this.select.engineeringId,
uni.navigateTo({ }).then((res) => {
url: '/pages/gateway/list', console.log(res)
}) let arr = [
} {
}, text: '全部项目',
}) value: '-1',
}, },
registerGateway() { ...res.data.records.map((item) => {
uni.navigateTo({ return {
url: '/pages/gateway/new', text: item.name,
}) value: item.id,
}, ...item,
navMenuClick(index) { }
this.navMenuActive = index }),
}, ]
jump(item) { this.projectList = arr
console.log(12321,item); uni.setStorageSync('projectList', arr)
uni.navigateTo({ })
url: '/pages/device/APF/detail?id=' + item.equipmentId + '&isPrimaryUser=' + item.isPrimaryUser + '&ndid=' + item.ndid, },
}) getEngineeringList() {
}, this.engineeringList = uni.getStorageSync('engineeringList')
}, },
} queryDictData() {
</script> queryDictData('项目类型').then((res) => {
<style lang="scss"></style> this.projectType = [
{
text: '全部类型',
value: '',
},
...res.data.map((item) => {
return {
text: item.anotherName,
value: item.id,
}
}),
]
})
},
submitFeedBack() {
uni.navigateTo({ url: '/pages/home/feedback' })
},
runStatusChange(e) {
this.select.runStatusSelect = false
this.select.runStatusIndex = e.detail.value
if (e.detail.value === 0) {
this.select.runStatusName = ''
return
}
this.select.runStatusName = this.projectType[e.detail.value].text
},
projectNameChange(e) {
this.select.selectProject = false
console.log(e)
this.select.projectNameIndex = e.detail.value
if (e.detail.value === 0) {
this.select.projectName = ''
return
}
this.select.projectName = this.projectList[e.detail.value].text
},
registerDevice() {
uni.showModal({
title: '提示',
content: '请选择设备类型',
confirmText: '直连设备',
cancelText: '网关接入',
cancelColor: '#007aff',
success: ({ confirm, cancel }) => {
if (confirm) {
uni.navigateTo({
url: '/pages/device/new',
})
} else if (cancel) {
uni.navigateTo({
url: '/pages/gateway/list',
})
}
},
})
},
registerGateway() {
uni.navigateTo({
url: '/pages/gateway/new',
})
},
navMenuClick(index) {
this.navMenuActive = index
},
jump(item) {
console.log(12321, item)
uni.navigateTo({
url:
'/pages/device/APF/detail?id=' +
item.equipmentId +
'&isPrimaryUser=' +
item.isPrimaryUser +
'&ndid=' +
item.ndid,
})
},
selectDevice(type) {
if (this.store.data.findIndex((item) => item.isPrimaryUser === '1') === -1) {
this.$util.toast('没有可操作的设备')
} else {
this[type] = true
}
},
switchChange(e) {
let index = this.checkList.indexOf(e.equipmentId)
if (index > -1) {
this.checkList.splice(index, 1)
} else {
this.checkList.push(e.equipmentId)
}
},
},
}
</script>
<style lang="scss">
/deep/ .button-group--right {
padding: 0 0 20rpx;
}
</style>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,273 +1,273 @@
<template> <template>
<Cn-page :loading="loading" noPadding> <Cn-page :loading="loading" noPadding>
<view slot="body"> <view slot="body">
<view class="detail"> <view class="detail">
<view class="header"> <view class="header">
<view class="header-title" <view class="header-title"
>{{ engineering.name }} >{{ engineering.name }}
<!-- <view class="header-title-extra">用能</view> --> <!-- <view class="header-title-extra">用能</view> -->
</view> </view>
<view class="header-des-mini mb10" <view class="header-des-mini mb10"
>{{ engineering.provinceName + engineering.cityName }} {{ engineering.createTime }}</view >{{ engineering.provinceName + engineering.cityName }} {{ engineering.createTime }}</view
> >
<view class="header-des">工程描述{{ engineering.description }} </view> <view class="header-des">工程描述{{ engineering.description }} </view>
</view> </view>
<view class="nav"> <view class="nav">
<view <view
class="nav-menu" class="nav-menu"
:class="{ 'nav-menu-active': navMenuActive == index }" :class="{ 'nav-menu-active': navMenuActive == index }"
v-for="(item, index) in navMenuList" v-for="(item, index) in navMenuList"
:key="index" :key="index"
@click="navMenuClick(index)" @click="navMenuClick(index)"
>{{ item.text }} >{{ item.text }}
</view> </view>
</view> </view>
<view class="content" :style="{ minHeight: 'calc(100vh - ' + navHeight + 'px)' }"> <view class="content" :style="{ minHeight: 'calc(100vh - ' + navHeight + 'px)' }">
<view v-show="navMenuActive == 0"> <view v-show="navMenuActive == 0">
<uni-card <uni-card
:title="item.name" :title="item.name"
extra="🔍" extra="🔍"
@click="jumpProject(item)" @click="jumpProject(item)"
v-for="(item, index) in store.data" v-for="(item, index) in store.data"
:key="index" :key="index"
> >
<view class="term-list-bottom"> <view class="term-list-bottom">
<view class="term-list-bottom-item"> <view class="term-list-bottom-item">
<view>设备个数</view> <view>设备个数</view>
<view>{{ item.devNum }}</view> <view>{{ item.devNum }}</view>
</view> </view>
<view class="term-list-bottom-item"> <view class="term-list-bottom-item">
<view>创建时间</view> <view>创建时间</view>
<view>{{ item.createTime }}</view> <view>{{ item.createTime }}</view>
</view> </view>
</view> </view>
</uni-card> </uni-card>
<Cn-empty v-if="store.empty"></Cn-empty> <Cn-empty v-if="store.empty"></Cn-empty>
<uni-load-more <uni-load-more
v-if="store.status == 'loading' || (store.data && store.data.length > 0)" v-if="store.status == 'loading' || (store.data && store.data.length > 0)"
:status="store.status" :status="store.status"
></uni-load-more> ></uni-load-more>
</view> </view>
<view style="padding: 0 20rpx" v-show="navMenuActive == 2"> <view style="padding: 0 20rpx" v-show="navMenuActive == 2">
<image <image
class="gplot gplot-box" class="gplot gplot-box"
mode="aspectFill" mode="aspectFill"
src="/static/test2.pic.png" src="/static/test2.pic.png"
v-for="(item, key) in 3" v-for="(item, key) in 3"
:key="key" :key="key"
/> />
</view> </view>
</view> </view>
<uni-fab <uni-fab
ref="fab" ref="fab"
direction="vertical" direction="vertical"
horizontal="right" horizontal="right"
vertical="bottom" vertical="bottom"
:content="content" :content="content"
@trigger="trigger" @trigger="trigger"
v-if="content.length" v-if="content.length"
/> />
<uni-popup ref="share" type="share" background-color="#fff"> <uni-popup ref="share" type="share" background-color="#fff">
<uni-popup-share title="分享到"></uni-popup-share> <uni-popup-share title="分享到"></uni-popup-share>
</uni-popup> </uni-popup>
</view> </view>
</view> </view>
</Cn-page> </Cn-page>
</template> </template>
<script> <script>
import list from '../../common/js/list' import list from '../../common/js/list'
import { deleteEngineering } from '../../common/api/engineering' import { deleteEngineering } from '../../common/api/engineering'
export default { export default {
mixins: [list], mixins: [list],
data() { data() {
return { return {
loading: false, loading: false,
engineering: '', engineering: '',
navMenuList: [ navMenuList: [
{ {
text: '项目', text: '项目',
}, },
// { // {
// text: '拓扑图', // text: '拓扑图',
// }, // },
], ],
content: [ content: [
// { // {
// iconPath: '/static/share.png', // iconPath: '/static/share.png',
// text: '编辑', // text: '编辑',
// }, // },
// { // {
// iconPath: '/static/delate.png', // iconPath: '/static/delate.png',
// text: '删除', // text: '删除',
// }, // },
], ],
navHeight: 0, navHeight: 0,
navMenuActive: 0, navMenuActive: 0,
} }
}, },
methods: { methods: {
trigger(e) { trigger(e) {
console.log(this.$refs) console.log(this.$refs)
if (e.item.text == '移交') { if (e.item.text == '移交') {
uni.navigateTo({ uni.navigateTo({
url: '/pages/gc/transfer', url: '/pages/gc/transfer',
}) })
} else if (e.item.text == '分享') { } else if (e.item.text == '分享') {
this.$refs.share.open() this.$refs.share.open()
} else if (e.item.text == '编辑') { } else if (e.item.text == '编辑') {
uni.navigateTo({ uni.navigateTo({
url: '/pages/engineering/new?engineering=' + encodeURIComponent(JSON.stringify(this.engineering)), url: '/pages/engineering/new?engineering=' + encodeURIComponent(JSON.stringify(this.engineering)),
}) })
} else if (e.item.text == '删除') { } else if (e.item.text == '删除') {
uni.showModal({ uni.showModal({
title: '提示', title: '提示',
content: '删除工程后不可恢复,是否继续?', content: '删除工程后不可恢复,是否继续?',
success: (res) => { success: (res) => {
if (res.confirm) { if (res.confirm) {
deleteEngineering(this.engineering.id).then((res) => { deleteEngineering(this.engineering.id).then((res) => {
this.$util.toast('删除成功') this.$util.toast('删除成功')
this.$util.refreshPrePage() this.$util.refreshPrePage()
}) })
} else if (res.cancel) { } else if (res.cancel) {
console.log('用户点击取消') console.log('用户点击取消')
} }
}, },
}) })
} }
}, },
navMenuClick(index) { navMenuClick(index) {
this.navMenuActive = index this.navMenuActive = index
}, },
goUserDetail() { goUserDetail() {
uni.navigateTo({ uni.navigateTo({
url: '/pages/mine/userDetail', url: '/pages/mine/userDetail',
}) })
}, },
del() { del() {
console.log('del') console.log('del')
uni.showModal({ uni.showModal({
title: '提示', title: '提示',
content: '确定要移除该成员吗?', content: '确定要移除该成员吗?',
success: function (res) { success: function (res) {
if (res.confirm) { if (res.confirm) {
console.log('用户点击确定') console.log('用户点击确定')
} else if (res.cancel) { } else if (res.cancel) {
console.log('用户点击取消') console.log('用户点击取消')
} }
}, },
}) })
}, },
goDevice() { goDevice() {
uni.navigateTo({ uni.navigateTo({
url: '/pages/device/APF/detail', url: '/pages/device/APF/detail',
}) })
}, },
jumpProject(item) { jumpProject(item) {
uni.navigateTo({ uni.navigateTo({
url: '/pages/project/detail?project=' + encodeURIComponent(JSON.stringify(item)), url: '/pages/project/detail?project=' + encodeURIComponent(JSON.stringify(item)),
}) })
}, },
init() { init() {
this.store = this.DataSource('/cs-device-boot/project/queryProject') this.store = this.DataSource('/cs-device-boot/project/queryProject')
this.store.params.engineeringId = this.engineering.id this.store.params.engineeringId = this.engineering.id
this.store.reload() this.store.reload()
}, },
}, },
onLoad(option) { onLoad(option) {
this.engineering = JSON.parse(decodeURIComponent(option.engineering)) this.engineering = JSON.parse(decodeURIComponent(option.engineering))
let userInfo = uni.getStorageSync('userInfo') let userInfo = uni.getStorageSync('userInfo')
if (userInfo.authorities == 'engineering_user' || userInfo.authorities == 'app_vip_user') { if (userInfo.authorities == 'engineering_user' || userInfo.authorities == 'app_vip_user') {
this.content.push( this.content.push(
{ {
iconPath: '/static/share.png', iconPath: '/static/share.png',
text: '编辑', text: '编辑',
}, },
{ {
iconPath: '/static/delate.png', iconPath: '/static/delate.png',
text: '删除', text: '删除',
}, },
) )
} }
setTimeout(() => { setTimeout(() => {
// 获取nav高度 // 获取nav高度
uni.createSelectorQuery() uni.createSelectorQuery()
.select('.nav') .select('.nav')
.boundingClientRect((rect) => { .boundingClientRect((rect) => {
this.navHeight = rect.height this.navHeight = rect.height
}) })
.exec() .exec()
}, 1000) }, 1000)
this.init() this.init()
// uni.setNavigationBarTitle({ title: this.engineering }) // uni.setNavigationBarTitle({ title: this.engineering })
}, },
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.detail { .detail {
.content { .content {
box-sizing: border-box; box-sizing: border-box;
padding-bottom: 20rpx; padding-bottom: 20rpx;
} }
.header { .header {
padding: 20rpx 20rpx 0; padding: 20rpx 20rpx 0;
.header-title { .header-title {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
font-size: 40rpx; font-size: 40rpx;
margin-bottom: 10rpx; margin-bottom: 10rpx;
.header-title-extra { .header-title-extra {
font-size: 24rpx; font-size: 24rpx;
color: #666; color: #666;
padding-right: 10rpx; padding-right: 10rpx;
} }
} }
.header-des { .header-des {
font-size: 28rpx; font-size: 28rpx;
color: #666; color: #666;
} }
.header-des-mini { .header-des-mini {
font-size: 24rpx; font-size: 24rpx;
color: #999; color: #999;
} }
} }
.footer-btn { .footer-btn {
padding: 0 20rpx; padding: 0 20rpx;
height: 50rpx; height: 50rpx;
background-color: #007aff; background-color: #007aff;
font-size: 24rpx; font-size: 24rpx;
color: #fff; color: #fff;
text-align: center; text-align: center;
line-height: 50rpx; line-height: 50rpx;
border-radius: 10rpx; border-radius: 10rpx;
} }
} }
.gplot { .gplot {
position: relative; position: relative;
width: 100%; width: 100%;
border: 8rpx solid #ccc; border: 8rpx solid #ccc;
} }
.term-list-bottom { .term-list-bottom {
.term-list-bottom-item { .term-list-bottom-item {
font-size: 28rpx; font-size: 28rpx;
margin-bottom: 20rpx; margin-bottom: 20rpx;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
// view:first-of-type{ // view:first-of-type{
// color: #111; // color: #111;
// } // }
} }
.term-list-bottom-item:last-of-type { .term-list-bottom-item:last-of-type {
margin-bottom: 0; margin-bottom: 0;
} }
} }
</style> </style>

View File

@@ -1,188 +1,244 @@
<template> <template>
<view :loading="loading"> <view :loading="loading">
<!-- <uni-nav-bar left-icon="left" right-icon="cart" title="标题" /> --> <!-- <uni-nav-bar left-icon="left" right-icon="cart" title="标题" /> -->
<uni-nav-bar <uni-nav-bar dark :fixed="true" status-bar left-icon="left" :rightIcon="userInfo.authorities === 'app_vip_user' || userInfo.authorities === 'engineering_user'
dark ? 'plusempty'
:fixed="true" : ''
status-bar " background-color="#fff" color="#111" title="工程管理" @clickLeft="back" @clickRight="add" />
left-icon="left" <uni-search-bar v-model="store.params.name" clearButton="none" bgColor="#fff" placeholder="请输入关键词"
:rightIcon=" @input="store.search()"></uni-search-bar>
userInfo.authorities === 'app_vip_user' || userInfo.authorities === 'engineering_user' <view class="message">
? 'plusempty'
: ''
" <uni-swipe-action>
background-color="#fff" <uni-swipe-action-item v-for="(item, index) in store.data"
color="#111" :style="{ marginTop: index === 0 ? '0' : '' }" :key="index" :threshold="0"
title="工程管理" :right-options="item.isTop == 0 ? options1 : options12" @click="bindClick($event, item)">
@clickLeft="back" <uni-card class="boxClick" :title="item.name" extra="🔍" @click="jump(item)">
@clickRight="add" <view class="term-list-bottom">
/> <view class="term-list-bottom-item">
<uni-search-bar <view>区域</view>
v-model="store.params.name" <view>{{ item.provinceName + item.cityName }}</view>
clearButton="none" </view>
bgColor="#fff" <view class="term-list-bottom-item">
placeholder="请输入关键词" <view>创建时间</view>
@input="store.search()" <view>{{ item.createTime }}</view>
></uni-search-bar> </view>
<view class="message"> </view>
<uni-card <view class="pinToTop" v-if="item.isTop == 1"> 置顶 </view>
:title="item.name" </uni-card>
extra="🔍" </uni-swipe-action-item>
@click="jump(item)" </uni-swipe-action>
v-for="(item, index) in store.data"
:style="{ marginTop: index === 0 ? '0' : '' }"
:key="index"
>
<view class="term-list-bottom"> <Cn-empty v-if="store.empty" style="padding-top: 400rpx"></Cn-empty>
<view class="term-list-bottom-item"> <uni-load-more v-if="store.status == 'loading' || (store.data && store.data.length > 0)"
<view>区域</view> :status="store.status"></uni-load-more>
<view>{{ item.provinceName + item.cityName }}</view> </view>
</view> </view>
<view class="term-list-bottom-item"> </template>
<view>创建时间</view>
<view>{{ item.createTime }}</view> <script>
</view> import list from '../../common/js/list'
</view> import { engineeringPinToTop } from '@/common/api/device'
</uni-card>
<Cn-empty v-if="store.empty" style="padding-top: 400rpx"></Cn-empty> export default {
<uni-load-more mixins: [list],
v-if="store.status == 'loading' || (store.data && store.data.length > 0)" data() {
:status="store.status" return {
></uni-load-more> loading: true,
</view> userInfo: {},
</view> options1: [
</template> {
text: '置顶',
<script> style: {
import list from '../../common/js/list' backgroundColor: '#376cf3',
},
export default { },
mixins: [list], ],
data() { options12: [
return { {
loading: true, text: '取消',
userInfo: {}, style: {
} backgroundColor: '#ccc',
}, },
methods: { },
init() { ],
this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo) }
this.store = this.DataSource('/cs-device-boot/engineering/queryEngineeringPage') },
this.store.params.name = '' methods: {
this.store.reload() bindClick(e, item) {
this.store.firstCallBack = (res) => { engineeringPinToTop({
let engineering = uni.getStorageSync('engineering') targetId: item.id,
if (!engineering) { targetType: 2,
uni.setStorageSync('engineering', this.store.data[0]) userId: uni.getStorageSync(this.$cacheKey.userInfo).userIndex,
} else { }).then((res) => {
this.store.data.forEach((item) => { if (res.code == 'A0000') {
if (item.id == engineering.id) { this.$util.toast('操作成功!')
uni.setStorageSync('engineering', item) this.store.search()
} } else {
}) this.$util.toast(res.message)
} }
} })
}, },
back() { init() {
uni.navigateBack() this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo)
}, this.store = this.DataSource('/cs-device-boot/engineering/queryEngineeringPage')
add() { this.store.params.name = ''
if (this.userInfo.authorities === 'app_vip_user' || this.userInfo.authorities === 'engineering_user') { this.store.reload()
uni.navigateTo({ this.store.firstCallBack = (res) => {
url: `/pages/engineering/new`, let engineering = uni.getStorageSync('engineering')
}) if (!engineering) {
} uni.setStorageSync('engineering', this.store.data[0])
}, } else {
upgrade(code) { this.store.data.forEach((item) => {
console.log(code) if (item.id == engineering.id) {
uni.showToast({ uni.setStorageSync('engineering', item)
title: '升级成功', }
icon: 'none', })
}) }
}, }
jump(engineering) { },
uni.navigateTo({ back() {
url: `/pages/engineering/detail?engineering=${encodeURIComponent(JSON.stringify(engineering))}`, uni.navigateBack()
}) },
}, add() {
}, if (this.userInfo.authorities === 'app_vip_user' || this.userInfo.authorities === 'engineering_user') {
uni.navigateTo({
onLoad() { url: `/pages/engineering/new`,
this.init() })
}, }
} },
</script> upgrade(code) {
console.log(code)
<style lang="scss"> uni.showToast({
.message { title: '升级成功',
.message-header { icon: 'none',
padding: 200rpx 34rpx 34rpx; })
display: flex; },
align-items: center; jump(engineering) {
background: $uni-theme-white; uni.navigateTo({
margin-bottom: 20rpx; url: `/pages/engineering/detail?engineering=${encodeURIComponent(JSON.stringify(engineering))}`,
box-shadow: 0 4rpx 8rpx #e7e7e74c; })
},
.message-header-head { },
margin-right: 30rpx;
height: 128rpx; onLoad() {
width: 128rpx; this.init()
border-radius: $uni-theme-radius; },
overflow: hidden; }
} </script>
.message-header-name { <style lang="scss">
margin-right: 30rpx; .message {
flex: 1; .message-header {
font-size: 36rpx; padding: 200rpx 34rpx 34rpx;
color: #111; display: flex;
font-weight: 700; align-items: center;
background: $uni-theme-white;
.tag { margin-bottom: 20rpx;
margin-top: 10rpx; box-shadow: 0 4rpx 8rpx #e7e7e74c;
font-size: 24rpx;
color: #aaa; .message-header-head {
} margin-right: 30rpx;
} height: 128rpx;
} width: 128rpx;
border-radius: $uni-theme-radius;
.message-nav { overflow: hidden;
padding: 34rpx; }
display: flex;
align-items: center; .message-header-name {
background: $uni-theme-white; margin-right: 30rpx;
border-bottom: 1rpx solid #e8e8e8; flex: 1;
font-size: 36rpx;
&-icon { color: #111;
margin-right: 30rpx; font-weight: 700;
height: 44rpx;
width: 44rpx; .tag {
border-radius: $uni-theme-radius; margin-top: 10rpx;
overflow: hidden; font-size: 24rpx;
} color: #aaa;
}
&-label { }
margin-right: 30rpx; }
flex: 1;
font-size: 28rpx; .message-nav {
color: #111; padding: 34rpx;
} display: flex;
} align-items: center;
} background: $uni-theme-white;
border-bottom: 1rpx solid #e8e8e8;
.term-list-bottom {
.term-list-bottom-item { &-icon {
font-size: 28rpx; margin-right: 30rpx;
margin-bottom: 20rpx; height: 44rpx;
display: flex; width: 44rpx;
justify-content: space-between; border-radius: $uni-theme-radius;
// view:first-of-type{ overflow: hidden;
// color: #111; }
// }
} &-label {
margin-right: 30rpx;
.term-list-bottom-item:last-of-type { flex: 1;
margin-bottom: 0; font-size: 28rpx;
} color: #111;
} }
</style> }
}
.term-list-bottom {
.term-list-bottom-item {
font-size: 28rpx;
// margin-bottom: 20rpx;
display: flex;
justify-content: space-between;
// view:first-of-type{
// color: #111;
// }
}
.term-list-bottom-item:last-of-type {
margin-bottom: 0;
}
}
/deep/ .uni-card--border {
margin: 0 10px !important;
padding-bottom: 10px;
}
/deep/ .uni-swipe {
margin-bottom: 10px;
}
.pinToTop {
background-color: $uni-theme-color;
width: 100rpx;
height: 60rpx;
line-height: 90rpx;
text-align: center;
color: #fff;
font-size: 20rpx;
position: absolute;
top: 0rpx;
right: 0rpx;
position: absolute;
top: 0;
right: 0;
/* 核心:旋转成斜三角效果 */
transform: rotate(45deg) translate(50rpx, -10rpx);
transform-origin: top right;
}
/deep/ .uni-card__content {
padding: 5px 10px 10px !important;
}
/deep/ .uni-card__header-content-title {
font-weight: 700;
}
</style>

View File

@@ -93,17 +93,17 @@ export default {
select(e) { select(e) {
console.log(e) console.log(e)
}, },
chooseLocation() { // chooseLocation() {
uni.chooseLocation({ // uni.chooseLocation({
success: function (res) { // success: function (res) {
this.address = res.name // this.address = res.name
console.log('位置名称:' + res.name) // console.log('位置名称:' + res.name)
console.log('详细地址:' + res.address) // console.log('详细地址:' + res.address)
console.log('纬度:' + res.latitude) // console.log('纬度:' + res.latitude)
console.log('经度:' + res.longitude) // console.log('经度:' + res.longitude)
}, // },
}) // })
}, // },
async submit() { async submit() {
console.log(this.formData) console.log(this.formData)
if (!this.formData.name) { if (!this.formData.name) {

View File

@@ -1,224 +1,225 @@
<template> <template>
<view :loading="loading"> <view :loading="loading">
<uni-search-bar v-model="keyWord" bgColor="#fff" placeholder="请输入关键词"></uni-search-bar> <uni-search-bar v-model="keyWord" bgColor="#fff" placeholder="请输入关键词"></uni-search-bar>
<view class="message"> <view class="message">
<!-- <uni-card <!-- <uni-card
:title="item.engineerName" :title="item.engineerName"
:extra="item.mac" :extra="item.mac"
@click="jump(item)" @click="jump(item)"
v-for="(item, index) in list" v-for="(item, index) in list"
:key="index" :key="index"
> >
<view class="term-list-bottom"> <view class="term-list-bottom">
<view class="term-list-bottom-item"> <view class="term-list-bottom-item">
<view>区域</view> <view>区域</view>
<view>{{ item.provinceName + item.cityName }}</view> <view>{{ item.provinceName + item.cityName }}</view>
</view> </view>
<view class="term-list-bottom-item"> <view class="term-list-bottom-item">
<view>创建时间</view> <view>创建时间</view>
<view>{{ item.createTime }}</view> <view>{{ item.createTime }}</view>
</view> </view>
</view> </view>
</uni-card> --> </uni-card> -->
<uni-list> <uni-list>
<uni-list-item @click="jump(item)" v-for="(item, index) in filterList" :key="index"> <uni-list-item @click="jump(item)" v-for="(item, index) in filterList" :key="index">
<template v-slot:header> <template v-slot:header>
<view class="slot-box"> <view class="slot-box">
<view class="slot-box-left hide-txt mr20">{{ item.engineerName }}</view> <view class="slot-box-left hide-txt mr20">{{ item.engineerName }}</view>
<switch <switch
:checked="selectList.indexOf(item.engineerId) > -1" :checked="selectList.indexOf(item.engineerId) > -1"
style="transform: scale(0.8)" style="transform: scale(0.8)"
@change="switchChange(item)" @change="switchChange(item)"
/> />
</view> </view>
</template> </template>
</uni-list-item> </uni-list-item>
</uni-list> </uni-list>
<uni-load-more v-if="list && list.length > 0" status="nomore"></uni-load-more> <uni-load-more v-if="list && list.length > 0" status="nomore"></uni-load-more>
<Cn-empty v-else style="padding-top: 300rpx"></Cn-empty> <Cn-empty v-else style="padding-top: 300rpx"></Cn-empty>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import list from '../../common/js/list' import list from '../../common/js/list'
import {queryAllEnginner, csMarketDataAdd, queryEngineering} from '@/common/api/engineering' import { queryAllEnginner, csMarketDataAdd, queryEngineering } from '@/common/api/engineering'
export default { export default {
data() { data() {
return { return {
loading: true, loading: true,
userInfo: {}, userInfo: {},
list: [], list: [],
selectList: [], selectList: [],
keyWord: '', keyWord: '',
} }
}, },
computed: { computed: {
filterList() { filterList() {
return this.list.filter((item) => { return this.list.filter((item) => {
return item.engineerName.indexOf(this.keyWord) > -1 return item.engineerName.indexOf(this.keyWord) > -1
}) })
}, },
}, },
methods: { methods: {
switchChange(e) { switchChange(e) {
console.log(e) console.log(e)
let index = this.selectList.indexOf(e.engineerId) let index = this.selectList.indexOf(e.engineerId)
if (index > -1) { if (index > -1) {
this.selectList.splice(index, 1) this.selectList.splice(index, 1)
} else { } else {
this.selectList.push(e.engineerId) this.selectList.push(e.engineerId)
} }
},
csMarketDataAdd({ init() {
engineerIds: this.selectList, this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo)
}).then((res) => { queryAllEnginner().then((res) => {
console.log(res) this.list = res.data
}) console.log(this.list)
}, this.selectList = res.data.filter((item) => item.isSelect === '1').map((item) => item.engineerId)
init() { console.log(this.selectList)
this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo) this.loading = false
queryAllEnginner().then((res) => { })
this.list = res.data },
console.log(this.list) back() {
this.selectList = res.data.filter((item) => item.isSelect === '1').map((item) => item.engineerId) uni.navigateBack()
console.log(this.selectList) },
this.loading = false add() {
}) uni.navigateTo({
}, url: `/pages/engineering/new`,
back() { })
uni.navigateBack() },
}, upgrade(code) {
add() { console.log(code)
uni.navigateTo({ uni.showToast({
url: `/pages/engineering/new`, title: '升级成功',
}) icon: 'none',
}, })
upgrade(code) { },
console.log(code) jump(engineering) {
uni.showToast({ uni.navigateTo({
title: '升级成功', url: `/pages/engineering/detail?engineering=${encodeURIComponent(JSON.stringify(engineering))}`,
icon: 'none', })
}) },
}, },
jump(engineering) { onUnload() {
uni.navigateTo({ csMarketDataAdd({
url: `/pages/engineering/detail?engineering=${encodeURIComponent(JSON.stringify(engineering))}`, engineerIds: this.selectList,
}) }).then((res) => {
}, console.log(res)
}, })
onBackPress() { },
console.log('onBackPress') onBackPress() {
let engineering = uni.getStorageSync('engineering') console.log('onBackPress')
queryEngineering().then(res => { let engineering = uni.getStorageSync('engineering')
if (res.data.length === 0) { queryEngineering().then((res) => {
uni.removeStorage({ if (res.data.length === 0) {
key: this.$cacheKey.engineering, uni.removeStorage({
}) key: this.$cacheKey.engineering,
} else if (engineering && !res.data.some(item => item.id = engineering.id)) { })
uni.removeStorage({ } else if (engineering && !res.data.some((item) => (item.id = engineering.id))) {
key: this.$cacheKey.engineering, uni.removeStorage({
}) key: this.$cacheKey.engineering,
} else { })
uni.setStorage({ } else {
key: this.$cacheKey.engineering, uni.setStorage({
data: res.data[0], key: this.$cacheKey.engineering,
}) data: res.data[0],
} })
}) }
}, })
onLoad() { },
this.init() onLoad() {
}, this.init()
} },
</script> }
</script>
<style lang="scss">
.message { <style lang="scss">
/deep/ .slot-box { .message {
width: 100%; /deep/ .slot-box {
display: flex; width: 100%;
align-items: center; display: flex;
align-items: center;
&-left {
flex: 1; &-left {
margin-right: 20rpx; flex: 1;
} margin-right: 20rpx;
} }
}
/deep/ .uni-list-item__content {
padding-right: 0; /deep/ .uni-list-item__content {
} padding-right: 0;
}
.message-header {
padding: 200rpx 34rpx 34rpx; .message-header {
display: flex; padding: 200rpx 34rpx 34rpx;
align-items: center; display: flex;
background: $uni-theme-white; align-items: center;
margin-bottom: 20rpx; background: $uni-theme-white;
box-shadow: 0 4rpx 8rpx #e7e7e74c; margin-bottom: 20rpx;
box-shadow: 0 4rpx 8rpx #e7e7e74c;
.message-header-head {
margin-right: 30rpx; .message-header-head {
height: 128rpx; margin-right: 30rpx;
width: 128rpx; height: 128rpx;
border-radius: $uni-theme-radius; width: 128rpx;
overflow: hidden; border-radius: $uni-theme-radius;
} overflow: hidden;
}
.message-header-name {
margin-right: 30rpx; .message-header-name {
flex: 1; margin-right: 30rpx;
font-size: 36rpx; flex: 1;
color: #111; font-size: 36rpx;
font-weight: 700; color: #111;
font-weight: 700;
.tag {
margin-top: 10rpx; .tag {
font-size: 24rpx; margin-top: 10rpx;
color: #aaa; font-size: 24rpx;
} color: #aaa;
} }
} }
}
.message-nav {
padding: 34rpx; .message-nav {
display: flex; padding: 34rpx;
align-items: center; display: flex;
background: $uni-theme-white; align-items: center;
border-bottom: 1rpx solid #e8e8e8; background: $uni-theme-white;
border-bottom: 1rpx solid #e8e8e8;
&-icon {
margin-right: 30rpx; &-icon {
height: 44rpx; margin-right: 30rpx;
width: 44rpx; height: 44rpx;
border-radius: $uni-theme-radius; width: 44rpx;
overflow: hidden; border-radius: $uni-theme-radius;
} overflow: hidden;
}
&-label {
margin-right: 30rpx; &-label {
flex: 1; margin-right: 30rpx;
font-size: 28rpx; flex: 1;
color: #111; font-size: 28rpx;
} color: #111;
} }
} }
}
.term-list-bottom {
.term-list-bottom-item { .term-list-bottom {
font-size: 28rpx; .term-list-bottom-item {
margin-bottom: 20rpx; font-size: 28rpx;
display: flex; margin-bottom: 20rpx;
justify-content: space-between; display: flex;
// view:first-of-type{ justify-content: space-between;
// color: #111; // view:first-of-type{
// } // color: #111;
} // }
}
.term-list-bottom-item:last-of-type {
margin-bottom: 0; .term-list-bottom-item:last-of-type {
} margin-bottom: 0;
} }
</style> }
</style>

View File

@@ -1,113 +1,113 @@
<template> <template>
<Cn-page :loading='loading' noPadding> <Cn-page :loading='loading' noPadding>
<view slot='body'> <view slot='body'>
<view class='detail device'> <view class='detail device'>
<view class="header"> <view class="header">
<image src="/static/test2.pic.png" mode="widthFix" style="width: 100%;" /> <image src="/static/test2.pic.png" mode="widthFix" style="width: 100%;" />
</view> </view>
<view class="title">基本信息</view> <view class="title">基本信息</view>
<view class="des"> <view class="des">
<text>名称监测网关</text> <text>名称监测网关</text>
<text class="ml20">项目XXX项目1</text> <text class="ml20">项目XXX项目1</text>
</view> </view>
<view class="des"> <view class="des">
<text>设备型号PQS-882</text> <text>设备型号PQS-882</text>
<text class="ml20">版本号v1.0.0</text> <text class="ml20">版本号v1.0.0</text>
</view> </view>
<view class="title mb20 m340">设备列表 <view class="title mb20 m340">设备列表
<view class="footer-btn" v-if="userInfo.authorities != '2' && userInfo.authorities != '5'" @click="newDevice">注册设备 <view class="footer-btn" v-if="userInfo.authorities != '2' && userInfo.authorities != '5'" @click="newDevice">注册设备
</view> </view>
</view> </view>
<uni-card :title="'设备' + item" :sub-title="'XXX项目1'" extra="用能" v-for="item in 2" :key="item" <uni-card :title="'设备' + item" :sub-title="'XXX项目1'" extra="用能" v-for="item in 2" :key="item"
@click="goDevice" padding="0" thumbnail="/static/device.png"> @click="goDevice" padding="0" thumbnail="/static/device.png">
</uni-card> </uni-card>
<uni-load-more status="nomore"></uni-load-more> <uni-load-more status="nomore"></uni-load-more>
<view style="height:20rpx"></view> <view style="height:20rpx"></view>
</view> </view>
</view> </view>
</Cn-page> </Cn-page>
</template> </template>
<script> <script>
export default { export default {
data () { data () {
return { return {
loading: false, loading: false,
userInfo: {}, userInfo: {},
deviceList: [ deviceList: [
{ {
name: '设备1', name: '设备1',
des: '设备描述1', des: '设备描述1',
type: 'APF', type: 'APF',
project: '监测', project: '监测',
}, },
{ {
name: '设备2', name: '设备2',
des: '设备描述2', des: '设备描述2',
type: 'DVR', type: 'DVR',
project: '监测' project: '监测'
}, },
] ]
} }
}, },
methods: { methods: {
newDevice () { newDevice () {
uni.navigateTo({ uni.navigateTo({
url: '/pages/gateway/newDevice' url: '/pages/gateway/newDevice'
}) })
}, },
goDevice (item) { goDevice (item) {
uni.navigateTo({ uni.navigateTo({
url: `/pages/device/${item.type}/detail` url: `/pages/device/${item.type}/detail`
}) })
} }
}, },
onLoad (options) { onLoad (options) {
this.userInfo = uni.getStorageSync('userInfo') this.userInfo = uni.getStorageSync('userInfo')
}, },
} }
</script> </script>
<style lang='scss'> <style lang='scss'>
.detail { .detail {
// background: $uni-theme-white; // background: $uni-theme-white;
.header { .header {
position: relative; position: relative;
} }
.title { .title {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
padding: 20rpx 20rpx 0; padding: 20rpx 20rpx 0;
font-size: 36rpx; font-size: 36rpx;
color: #111; color: #111;
font-weight: 700; font-weight: 700;
.footer-btn { .footer-btn {
padding: 0 20rpx; padding: 0 20rpx;
height: 50rpx; height: 50rpx;
background-color: #007aff; background-color: #007aff;
font-size: 24rpx; font-size: 24rpx;
color: #fff; color: #fff;
text-align: center; text-align: center;
line-height: 50rpx; line-height: 50rpx;
border-radius: 10rpx; border-radius: 10rpx;
} }
} }
.des { .des {
padding: 20rpx 20rpx 0; padding: 20rpx 20rpx 0;
font-size: 28rpx; font-size: 28rpx;
color: #333; color: #333;
} }
.content { .content {
box-sizing: border-box; box-sizing: border-box;
} }
} }
</style> </style>

View File

@@ -26,8 +26,8 @@
<view style="display:flex;"> <view style="display:flex;">
<uni-easyinput :clearable="false" type="textarea" autoHeight v-model="formData.address" <uni-easyinput :clearable="false" type="textarea" autoHeight v-model="formData.address"
placeholder="请输入位置信息" /> placeholder="请输入位置信息" />
<uni-icons type="location" color="#007aff" size="26" class="ml20" <!-- <uni-icons type="location" color="#007aff" size="26" class="ml20"
@click="chooseLocation"></uni-icons> @click="chooseLocation"></uni-icons> -->
</view> </view>
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="拓扑图"> <uni-forms-item label="拓扑图">
@@ -97,17 +97,17 @@ export default {
register () { register () {
this.type = 2 this.type = 2
}, },
chooseLocation () { // chooseLocation () {
uni.chooseLocation({ // uni.chooseLocation({
success: function (res) { // success: function (res) {
this.address = res.name // this.address = res.name
console.log('位置名称:' + res.name); // console.log('位置名称:' + res.name);
console.log('详细地址:' + res.address); // console.log('详细地址:' + res.address);
console.log('纬度:' + res.latitude); // console.log('纬度:' + res.latitude);
console.log('经度:' + res.longitude); // console.log('经度:' + res.longitude);
} // }
}); // });
}, // },
submit () { submit () {
this.$util.toast('提交成功') this.$util.toast('提交成功')
setTimeout(() => { setTimeout(() => {

View File

@@ -1,97 +1,160 @@
<template> <template>
<Cn-page :loading="loading"> <Cn-page :loading="loading">
<view slot="body"> <view slot="body">
<view class="select-enineering"> <view class="select-enineering">
<uni-indexed-list <view class="all" @click="all">全部工程</view>
:options="engineeringListFilter" <uni-indexed-list
:showSelect="false" :style="{ top: showAll ? '110rpx' : '0' }"
@click="confirm" :options="engineeringListFilter"
></uni-indexed-list> :showSelect="false"
</view> @click="confirm"
</view> >
</Cn-page> </uni-indexed-list>
</template> </view>
<script> </view>
import { pinyin } from 'pinyin-pro' </Cn-page>
import { queryEngineering } from '@/common/api/engineering' </template>
<script>
export default { import { pinyin } from 'pinyin-pro'
data() { import { queryEngineering } from '@/common/api/engineering'
return {
loading: false, export default {
engineeringList: [], props: {},
options: {}, data() {
} return {
}, loading: false,
computed: { engineeringList: [],
engineeringListFilter() { options: {},
let result = [] showAll: true,
this.engineeringList.forEach((item) => { }
let arr = pinyin(item.name[0], { toneType: 'none', type: 'array' }) },
let letter = arr[0][0].toUpperCase() computed: {
console.log(letter) engineeringListFilter() {
let index = result.findIndex((item) => item.letter === letter) let result = []
if (index === -1) { this.engineeringList.forEach((item) => {
result.push({ let arr = pinyin(item.name[0], { toneType: 'none', type: 'array' })
letter, let letter = arr[0][0].toUpperCase()
data: [item.name], // console.log(letter)
}) let index = result.findIndex((item) => item.letter === letter)
} else { if (index === -1) {
result[index].data.push(item.name) result.push({
} letter,
}) data: [item.name],
return result })
}, } else {
}, result[index].data.push(item.name)
onLoad(options) { }
this.options = options })
this.engineeringList = uni.getStorageSync('engineeringList') return result
this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo) },
if (!(this.userInfo.authorities === 'app_vip_user' || this.userInfo.authorities === 'engineering_user')) { },
// 修改buttons onLoad(options) {
// #ifdef APP-PLUS this.options = options
var webView = this.$mp.page.$getAppWebview() this.showAll = this.options.showAll ? true : false
// 修改buttons this.engineeringList = uni.getStorageSync('engineeringList')
webView.setTitleNViewButtonStyle(0, { this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo)
width: '0', if (!(this.userInfo.authorities === 'app_vip_user' || this.userInfo.authorities === 'engineering_user')) {
}) // 修改buttons
// #endif // #ifdef APP-PLUS
} var webView = this.$mp.page.$getAppWebview()
}, // 修改buttons
onShow() { webView.setTitleNViewButtonStyle(0, {
queryEngineering().then((res) => { width: '0',
this.engineeringList = res.data })
}) // #endif
}, }
onNavigationBarButtonTap(e) { },
if (this.userInfo.authorities === 'app_vip_user' || this.userInfo.authorities === 'engineering_user') { onShow() {
uni.navigateTo({ queryEngineering().then((res) => {
url: `/pages/engineering/new`, this.engineeringList = this.sortByFirstLetter(res.data)
}) })
} else { },
uni.showToast({ onNavigationBarButtonTap(e) {
title: '暂无权限', if (this.userInfo.authorities === 'app_vip_user' || this.userInfo.authorities === 'engineering_user') {
icon: 'none', uni.navigateTo({
}) url: `/pages/engineering/new`,
} })
}, } else {
methods: { uni.showToast({
confirm(e) { title: '暂无权限',
console.log(e) icon: 'none',
let engineering = this.engineeringList.find((item) => item.name === e.item.name) })
if (this.options.from === 'once') { }
// 创建项目的时候选择工程 用完即删 },
uni.setStorageSync('onceSelectEngineering', engineering) methods: {
} else { // 处理函数
uni.setStorageSync('engineering', engineering) sortByFirstLetter(data) {
} // 1. 添加首字母字段
uni.navigateBack() const withLetter = data.map((item) => {
}, let letter = '#'
}, const firstChar = item.name?.charAt(0) || ''
}
</script> if (/[A-Za-z]/.test(firstChar)) {
<style lang="scss"> letter = firstChar.toUpperCase()
.index { } else if (/[0-9]/.test(firstChar)) {
padding: 34rpx; letter = '#'
} } else {
</style> const py = pinyin(firstChar, { pattern: 'first', toneType: 'none' })
letter = py ? py.toUpperCase() : '#'
}
return { ...item, letter }
})
// 2. 排序
return withLetter.sort((a, b) => {
if (a.letter === '#') return 1
if (b.letter === '#') return -1
return a.letter.localeCompare(b.letter)
})
},
all() {
uni.setStorageSync('onceSelectEngineering', {
createBy: '',
createTime: '',
updateBy: '',
updateTime: '',
id: '',
name: '',
userId: null,
province: '',
provinceName: '',
city: '',
cityName: '',
description: '',
status: '1',
})
uni.navigateBack()
},
confirm(e) {
console.log(e)
let engineering = this.engineeringList.find((item) => item.name === e.item.name)
if (this.options.from === 'once') {
// 创建项目的时候选择工程 用完即删
uni.setStorageSync('onceSelectEngineering', engineering)
} else {
uni.setStorageSync('engineering', engineering)
}
uni.navigateBack()
},
},
}
</script>
<style lang="scss">
.index {
padding: 34rpx;
}
.all {
padding-left: 30rpx;
display: flex;
align-items: center;
cursor: pointer;
height: 50px;
border-bottom-style: solid;
border-bottom-width: 1px;
border-bottom-color: #dedede;
background-color: #ffffff;
}
</style>

View File

@@ -0,0 +1,144 @@
<template>
<Cn-page :loading="loading">
<view slot="body">
<view class="select-enineering">
<view class="all" @click="all">全部工程</view>
<uni-indexed-list
:style="{ top: showAll ? '110rpx' : '0' }"
:options="engineeringListFilter"
:showSelect="false"
@click="confirm"
>
</uni-indexed-list>
</view>
</view>
</Cn-page>
</template>
<script>
import { pinyin } from 'pinyin-pro'
import { queryEngineering } from '@/common/api/engineering'
export default {
props: {},
data() {
return {
loading: false,
engineeringList: [],
options: {},
showAll: true,
}
},
computed: {
engineeringListFilter() {
let result = []
this.engineeringList.forEach((item) => {
let arr = pinyin(item.name[0], { toneType: 'none', type: 'array' })
let letter = arr[0][0].toUpperCase()
// console.log(letter)
let index = result.findIndex((item) => item.letter === letter)
if (index === -1) {
result.push({
letter,
data: [item.name],
})
} else {
result[index].data.push(item.name)
}
})
return result
},
},
onLoad(options) {
this.options = options
this.showAll = this.options.showAll ? true : false
this.engineeringList = uni.getStorageSync('engineeringList')
this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo)
if (!(this.userInfo.authorities === 'app_vip_user' || this.userInfo.authorities === 'engineering_user')) {
// 修改buttons
// #ifdef APP-PLUS
var webView = this.$mp.page.$getAppWebview()
// 修改buttons
webView.setTitleNViewButtonStyle(0, {
width: '0',
})
// #endif
}
},
onShow() {
queryEngineering().then((res) => {
this.engineeringList = res.data.sort((a, b) => {
const nameA = a.name
const nameB = b.name
const isANumber = /^\d/.test(nameA)
const isBNumber = /^\d/.test(nameB)
if (isANumber !== isBNumber) {
return isANumber ? 1 : -1
}
return nameA.localeCompare(nameB, 'zh', { sensitivity: 'accent' })
})
})
},
onNavigationBarButtonTap(e) {
if (this.userInfo.authorities === 'app_vip_user' || this.userInfo.authorities === 'engineering_user') {
uni.navigateTo({
url: `/pages/engineering/new`,
})
} else {
uni.showToast({
title: '暂无权限',
icon: 'none',
})
}
},
methods: {
all() {
uni.setStorageSync('onceSelectEngineering', {
createBy: '',
createTime: '',
updateBy: '',
updateTime: '',
id: '',
name: '',
userId: null,
province: '',
provinceName: '',
city: '',
cityName: '',
description: '',
status: '1',
})
uni.navigateBack()
},
confirm(e) {
console.log(e)
let engineering = this.engineeringList.find((item) => item.name === e.item.name)
if (this.options.from === 'once') {
// 创建项目的时候选择工程 用完即删
uni.setStorageSync('onceSelectEngineering', engineering)
} else {
uni.setStorageSync('engineering', engineering)
}
uni.navigateBack()
},
},
}
</script>
<style lang="scss">
.index {
padding: 34rpx;
}
.all {
padding-left: 30rpx;
display: flex;
align-items: center;
cursor: pointer;
height: 50px;
border-bottom-style: solid;
border-bottom-width: 1px;
border-bottom-color: #dedede;
background-color: #ffffff;
}
</style>

370
pages/index/comp/apply.vue Normal file
View File

@@ -0,0 +1,370 @@
<template>
<view>
<view class="filterCriteria">
<!-- 筛选条件 -->
<Cn-filterCriteria @select="select" :singleChoice="true" :showDatetime="true"> </Cn-filterCriteria>
<!-- <view class="choose1">
<view class="nav-menu nav-menu-btn" @click="selectDevice">申请报告 </view>
</view> -->
</view>
<view class="smallLabel mt20">
<view class="boxCenter">
<view>
<checkbox-group @change="changeBox" class="boxCenter"
><checkbox value="true" :checked="checkedAll" />全选 
</checkbox-group></view
>
已选择 {{ checkedTotal }} 条事件
</view>
<view class="nav-menu nav-menu-btn" @click="selectDevice">申请报告 </view>
<!-- <view style="width: 180rpx">
<picker @change="bindPickerChange" :value="sort" :range="array">
<view class="uni-input"
>{{ array[sort] }}排序
<uni-icons custom-prefix="iconfont" type="icon-paixu1" size="10" color="#2563EB"></uni-icons>
</view>
</picker>
</view> -->
</view>
<!-- 卡片 -->
<scroll-view
scroll-y="true"
@scrolltolower="scrolltolower"
class="event-list"
:style="{ height: 'calc(100vh - ' + (navHeight + height) + 'px)', overflow: 'auto' }"
>
<!-- 循环渲染事件项 -->
<uni-card
class="event-item"
:class="judgment(item.showName).type"
v-for="(item, index) in store.data"
:key="index"
@click="clackCard(item)"
>
<!-- 头部图标 + 信息 + 操作 -->
<view class="event-header">
<view class="event-icon">
<!-- 动态图标根据类型切换 -->
<!-- <uni-icons
:custom-prefix="judgment(item.showName) == 'interrupt' ? 'custom-icon' : 'iconfont'"
:type="judgment(item.showName).icon"
:color="judgment(item.showName).color"
:size="judgment(item.showName).size"
></uni-icons> -->
<Cn-icon-transient :name="item.showName" />
</view>
<view class="event-info">
<view class="event-title">
<text class="event-id">{{ item.lineName }}</text>
<text class="event-tag" :class="`${judgment(item.showName).type}-tag`">{{
item.showName
}}</text>
</view>
<view class="event-desc">
<text>工程名称{{ item.engineeringName }}</text>
<text>项目名称{{ item.projectName }}</text>
<text>设备名称{{ item.equipmentName }}</text>
</view>
</view>
<view class="event-action" @click="handleWrapperClick(item, !item.wavePath)">
<!-- 选择 -->
<checkbox-group @change="changeChild($event, item)"
><checkbox value="true" :disabled="!item.wavePath" :checked="item.checked" />
</checkbox-group>
</view>
</view>
<!-- 详情区域 -->
<view class="event-detail">
<text>
{{ item.startTime ? '发生时间:' + item.startTime : '' }}
{{
item.evtParamVVaDepth != null && item.evtParamVVaDepth !== ''
? ',幅值:' + item.evtParamVVaDepth + '%'
: ''
}}
{{
item.evtParamTm != null && item.evtParamTm !== ''
? ',持续时间:' + item.evtParamTm + 's'
: ''
}}
{{
item.evtParamPhase != null && item.evtParamPhase !== ''
? ',相别:' + item.evtParamPhase
: ''
}}
</text>
</view>
</uni-card>
<uni-load-more
v-if="store.status == 'loading' || (store.data && store.data.length > 0)"
:status="store.status"
></uni-load-more>
<Cn-empty v-else style="top: 20%"></Cn-empty>
</scroll-view>
</view>
</template>
<script>
import list from '@/common/js/list'
import { applicationReport } from '@/common/api/report.js'
export default {
components: {},
props: {
navHeight: {
type: Number,
default: 0,
},
},
mixins: [list],
data() {
return {
selectValue: {},
height: 0,
checkedAll: false,
checkedTotal: 0,
sort: 0,
array: ['发生时间', '暂降深度', '持续时间'],
}
},
mounted() {},
methods: {
setHeight() {
uni.createSelectorQuery()
.select('.filterCriteria')
.boundingClientRect((rect) => {
//
// #ifdef H5
this.height = rect?.height + 170 || 0
// #endif
// #ifdef APP-PLUS
this.height = rect?.height + 110 || 0
// #endif
})
.exec()
},
async select(val) {
this.selectValue = val
await this.init()
setTimeout(() => {
this.setHeight()
}, 200)
},
init() {
this.store = this.DataSource('/cs-harmonic-boot/eventUser/queryEventpage')
this.store.params.type = 0
// this.store.params.pageSize = 10000
this.store.params.sortField = this.sort
this.store.params.engineeringid = this.selectValue.engineeringId
this.store.params.projectId = this.selectValue.projectId
this.store.params.deviceId = this.selectValue.deviceId
this.store.params.lineId = this.selectValue.lineId
this.store.params.target = ['Evt_Sys_DipStr']
this.store.params.startTime = this.$util.getMonthFirstAndLastDay(this.selectValue.date).firstDay
this.store.params.endTime = this.$util.getMonthFirstAndLastDay(this.selectValue.date).lastDay
// this.store.params.startTime = this.selectValue.range[0]
// this.store.params.endTime = this.selectValue.range[1]
this.store.loadedCallback = () => {
this.checkedTotal = 0
this.store.data = this.store.data.map((item) => {
item.checked = false
return item
})
}
this.store.reload()
},
// 全选
changeBox(e) {
this.checkedAll = !this.checkedAll
if (e.target.value.length > 0) {
let total = 0
this.store.data = this.store.data.map((item) => {
if (item.wavePath != null) {
item.checked = true
total += 1
} else {
item.checked = false
}
return item
})
this.checkedTotal = total
} else {
this.store.data = this.store.data.map((item) => {
item.checked = false
return item
})
this.checkedTotal = 0
}
},
changeChild(e, item) {
item.checked = !item.checked
this.checkedAll = this.store.data.every((item) => item.checked === true)
this.checkedTotal = this.store.data.filter((item) => item.checked === true).length
},
handleWrapperClick(e, flag) {
if (flag) {
return uni.showToast({
title: '当前事件没有波形,不支持生成报告!',
icon: 'none',
})
}
},
// 点击卡片
clackCard() {},
// 切换排序
bindPickerChange(e) {
this.sort = e.detail.value
this.init()
},
judgment(val, key) {
switch (val) {
case '电压暂降':
return {
type: 'sag',
icon: 'icon-a-svg4',
color: '#2563eb',
size: '25',
}
case '电压暂升':
return {
type: 'swell',
icon: 'icon-a-svg5',
color: '#e6a23c',
size: '25',
}
case '电压中断':
return {
type: 'interrupt',
icon: 'icon-zhongduan2',
color: '#6b7280',
size: '35',
}
case '瞬态':
return {
type: 'transient',
icon: 'icon-shuntaishijian',
color: '#8b5cf6',
size: '40',
}
case '未知':
return {
type: 'unknown',
icon: 'icon-wenhao',
color: '#6b7280',
size: '45',
}
}
},
// 申请
selectDevice() {
if (this.checkedTotal == 0) {
return uni.showToast({
title: '请选择事件!',
icon: 'none',
})
} else {
uni.showLoading({
title: '申请中,请稍等...',
mask: true,
})
let list = this.store.data.filter((item) => item.checked === true)
applicationReport({
list: list.map((item) => item.id),
lineId: list[0].lineId,
startTime: this.$util.getMonthFirstAndLastDay(this.selectValue.date).firstDay,
endTime: this.$util.getMonthFirstAndLastDay(this.selectValue.date).lastDay,
}).then((res) => {
this.checkedAll = false
this.store.reload()
uni.showToast({
icon: 'success',
mask: true,
title: '申请报告,成功!',
})
})
}
},
isAllLineIdSame(data) {
// 获取第一个元素的lineId作为基准
const baseLineId = data[0].lineId
// 遍历数组检查每个元素的lineId是否和基准一致
for (let item of data) {
// 兼容元素可能没有lineId的情况
if (!item || item.lineId !== baseLineId) {
return false
}
}
return true
},
// 下拉
refresherrefresh() {
this.triggered = true
uni.startPullDownRefresh()
setTimeout(() => {
this.triggered = false
}, 500)
},
// 上拉
scrolltolower() {
if (this.store.status != 'noMore') {
this.store.next && this.store.next()
}
},
},
computed: {},
watch: {},
}
</script>
<style lang="scss" scoped>
@import '@/pages/message1/index.scss';
.filterCriteria {
.nav {
background-color: #fff;
}
.choose1 {
background-color: #fff;
padding: 0 20rpx;
display: flex;
justify-content: flex-end;
/deep/ .uni-checkbox-input {
width: 30rpx;
height: 30rpx;
}
font-size: 26rpx;
}
}
.nav-menu {
height: 40rpx;
padding: 6rpx 20rpx;
// margin-left: 20rpx;
// margin-bottom: 20rpx;
line-height: 40rpx;
font-size: 24rpx;
border-radius: 8rpx;
background: #ebeaec;
color: #666;
&-active {
background: #dfe5f7;
color: $uni-theme-color;
}
&-btn {
background: $uni-theme-color;
color: #fff;
}
}
/deep/.uni-card__content {
padding: 20rpx !important;
}
.smallLabel {
justify-content: space-between;
font-size: 26rpx !important;
}
.boxCenter {
display: flex !important;
align-items: center !important;
}
</style>

View File

@@ -60,37 +60,31 @@
</picker> --> </picker> -->
</view> </view>
<view class="content device" :style="{ minHeight: minHeight }"> <view class="content device" :style="{ minHeight: minHeight }">
<Cn-device-card v-for="(item, index) in deviceListFilter" :device="item" :key="index"> <uni-swipe-action>
<template v-slot:title v-if="transfer || share"> <uni-swipe-action-item
<!-- 卡片标题 --> v-for="(item, index) in deviceListFilter"
<view class="uni-card__header"> :threshold="0"
<view class="uni-card__header-box"> :right-options="item.isTop == 0 ? options1 : options12"
<view class="uni-card__header-avatar"> @click="bindClick($event, item)"
<image >
class="uni-card__header-avatar-image" <Cn-device-card :device="item" :key="index">
:src="deviceIcon(item.runStatus)" <template v-slot:title>
mode="aspectFit" <!-- 卡片标题 -->
/>
</view>
<view class="uni-card__header-content">
<text class="uni-card__header-content-title uni-ellipsis">
{{ item.equipmentName }}
</text>
<text class="uni-card__header-content-subtitle uni-ellipsis">
{{ item.mac }}
</text>
</view>
</view>
<view class="uni-card__header-extra" style="position: relative">
<switch <switch
v-if="transfer || share"
:checked="checkList.indexOf(item.equipmentId) > -1" :checked="checkList.indexOf(item.equipmentId) > -1"
style="transform: scale(0.8); position: relative; left: 20rpx" style="transform: scale(0.8); position: relative; left: 20rpx"
@change="switchChange(item)" @change="switchChange(item)"
/> />
</view> <view class="star-icon" v-else>
</view> <!-- <uni-icons type="search" size="25" color="#376cf3"></uni-icons> -->
</template> 🔍
</Cn-device-card> </view>
</template>
</Cn-device-card>
</uni-swipe-action-item>
</uni-swipe-action>
<uni-load-more <uni-load-more
v-if="store.status == 'loading' || deviceListFilter.length > 0" v-if="store.status == 'loading' || deviceListFilter.length > 0"
:status="store.status" :status="store.status"
@@ -102,7 +96,7 @@
<script> <script>
import { getProjectList } from '@/common/api/project' import { getProjectList } from '@/common/api/project'
import { queryDictData } from '@/common/api/dictionary' import { queryDictData } from '@/common/api/dictionary'
import { engineeringPinToTop } from '@/common/api/device'
export default { export default {
props: { props: {
store: { store: {
@@ -129,11 +123,26 @@ export default {
projectType: [], projectType: [],
userInfo: {}, userInfo: {},
selectProject: false, selectProject: false,
options1: [
{
text: '置顶',
style: {
backgroundColor: '#376cf3',
},
},
],
options12: [
{
text: '取消',
style: {
backgroundColor: '#ccc',
},
},
],
} }
}, },
computed: { computed: {
deviceListFilter() { deviceListFilter() {
let arr = this.store.data.filter((item) => { let arr = this.store.data.filter((item) => {
if (this.select.projectName && this.select.projectType) { if (this.select.projectName && this.select.projectType) {
return item.project === this.select.projectName && item.type === this.select.projectType return item.project === this.select.projectName && item.type === this.select.projectType
@@ -145,9 +154,8 @@ export default {
return true return true
} }
}) })
if (this.transfer || this.share) { if (this.transfer || this.share) {
return arr.filter((item) => { return arr.filter((item) => {
return item.isPrimaryUser === '1' //&& item.process == 4 return item.isPrimaryUser === '1' //&& item.process == 4
}) })
@@ -161,6 +169,21 @@ export default {
}, },
mounted() {}, mounted() {},
methods: { methods: {
bindClick(e, item) {
engineeringPinToTop({
targetId: item.equipmentId,
targetType: 1,
userId: uni.getStorageSync(this.$cacheKey.userInfo).userIndex,
}).then((res) => {
if (res.code == 'A0000') {
this.$util.toast('操作成功!')
this.store.search()
} else {
this.$util.toast(res.message)
}
})
},
selectDevice(type) { selectDevice(type) {
if (this.deviceListFilter.findIndex((item) => item.isPrimaryUser === '1') === -1) { if (this.deviceListFilter.findIndex((item) => item.isPrimaryUser === '1') === -1) {
this.$util.toast('没有可操作的设备') this.$util.toast('没有可操作的设备')
@@ -184,7 +207,6 @@ export default {
return str return str
}, },
switchChange(e) { switchChange(e) {
console.log(e)
let index = this.checkList.indexOf(e.equipmentId) let index = this.checkList.indexOf(e.equipmentId)
if (index > -1) { if (index > -1) {
this.checkList.splice(index, 1) this.checkList.splice(index, 1)
@@ -333,18 +355,28 @@ export default {
this.navMenuActive = index this.navMenuActive = index
}, },
jump(item) { jump(item) {
uni.navigateTo({ uni.navigateTo({
url: '/pages/device/APF/detail?id=' + item.equipmentId + '&isPrimaryUser=' + item.isPrimaryUser+ '&ndid=' + item.ndid, url:
'/pages/device/APF/detail?id=' +
item.equipmentId +
'&isPrimaryUser=' +
item.isPrimaryUser +
'&ndid=' +
item.ndid,
}) })
}, },
}, },
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.index-device{ .index-device {
.nav-menu { .nav-menu {
} }
} }
/deep/ .button-group--right {
padding: 0 0 20rpx;
}
.star-icon {
font-size: 40rpx;
}
</style> </style>

View File

@@ -0,0 +1,285 @@
<template>
<view class="index-device">
<view class="nav" :style="{ top: navTabHeight + 'px' }"> </view>
<view class="content device project-list" :style="{ minHeight: minHeight }">
<uni-swipe-action>
<uni-swipe-action-item
v-for="(item, index) in store.data"
:threshold="0"
:right-options="item.isTop == 0 ? options1 : options12"
@click="bindClick($event, item)"
>
<uni-card :key="index">
<view class="card-header">
<view class="project-icon">
<uni-icons
custom-prefix="iconfont"
type="icon-gongcheng"
color="#2563eb"
size="45"
></uni-icons>
</view>
<view class="project-info">
<view class="project-name">{{ item.engineeringName }}</view>
<view class="project-stats">
<view class="stat-item boxClick" @click="jump('nowEngineering', item)">
<text class="stat-value blue">{{ item.devTotal }}</text>
<text class="stat-label">设备总数</text>
</view>
<view class="stat-item boxClick" @click="jump('currentOnLineDevs', item)">
<text class="stat-value green">{{ item.onlineDevTotal }}</text>
<text class="stat-label">在线设备</text>
</view>
<view class="stat-item boxClick" @click="jump('currentOffLineDevs', item)">
<text class="stat-value red">{{ item.offlineDevTotal }}</text>
<text class="stat-label">离线设备</text>
</view>
<view class="stat-item boxClick" @click="jump('event', item)">
<text class="stat-value red">{{ item.alarmTotal }}</text>
<text class="stat-label">事件数量</text>
</view>
</view>
</view>
</view>
<view class="pinToTop" v-if="item.isTop == 1"> 置顶 </view>
</uni-card>
</uni-swipe-action-item>
</uni-swipe-action>
<uni-load-more
v-if="store.status == 'loading' || deviceListFilter.length > 0"
:status="store.status"
></uni-load-more>
<Cn-empty v-else></Cn-empty>
</view>
</view>
</template>
<script>
import { engineeringPinToTop } from '@/common/api/device'
export default {
props: {
store: {
type: Object,
default: {},
},
},
data() {
return {
loading: false,
minHeight: 0,
navTabHeight: 0,
userInfo: {},
options1: [
{
text: '置顶',
style: {
backgroundColor: '#376cf3',
},
},
],
options12: [
{
text: '取消',
style: {
backgroundColor: '#ccc',
},
},
],
}
},
computed: {
deviceListFilter() {
let arr = this.store.data
return arr
},
},
created() {
this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo)
},
mounted() {
console.log(12333, this.store)
},
methods: {
bindClick(e, item) {
engineeringPinToTop({
targetId: item.engineeringId,
targetType: 2,
userId: uni.getStorageSync(this.$cacheKey.userInfo).userIndex,
}).then((res) => {
if (res.code == 'A0000') {
this.$util.toast('操作成功!')
this.store.search()
} else {
this.$util.toast(res.message)
}
})
},
getDeviceList() {
this.store.params.pageSize = 50
this.store.firstCallBack = (res) => {
uni.createSelectorQuery()
.select('.uni-navbar')
.boundingClientRect((rect1) => {
if (!rect1) return
this.navTabHeight = rect1.height
uni.createSelectorQuery()
.select('.nav')
.boundingClientRect((rect2) => {
if (!rect2) return
// #ifdef H5
this.minHeight = 'calc(100vh - ' + (this.navTabHeight + rect2.height + 50) + 'px)'
// #endif
// #ifdef APP-PLUS
this.minHeight = 'calc(100vh - ' + (this.navTabHeight + rect2.height) + 'px)'
console.log(this.minHeight)
// #endif
})
.exec()
})
.exec()
}
this.store.reload()
},
async init() {
console.warn('init')
this.getDeviceList()
},
jump(type, item) {
if (type == 'event') {
// 存储参数
uni.setStorageSync('messageParams', {
engineeringName: this.device.engineeringName,
engineeringId: this.device.engineeringId, //工程ID
projectName: '',
projectId: '', //項目ID
deviceName: '',
deviceId: '', //设备ID
lineName: '',
lineId: '', //测点ID
type: '',
})
uni.switchTab({
url: '/pages/index/message1',
})
} else {
uni.setStorageSync('engineering', { name: item.engineeringName, id: item.engineeringId })
uni.navigateTo({
url: '/pages/device/list?type=' + type,
})
}
},
},
}
</script>
<style lang="scss" scoped>
.index-device {
/* 列表容器 */
// .project-card {
// background-color: #ffffff;
// border-radius: 16rpx;
// margin-bottom: 16rpx;
// padding: 24rpx;
// box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
// }
.card-header {
display: flex;
align-items: center;
}
.project-icon {
width: 110rpx;
height: 110rpx;
border-radius: 12rpx;
display: flex;
justify-content: center;
align-items: center;
margin-right: 20rpx;
background-color: #2563eb20;
}
.project-info {
flex: 1;
line-height: 36rpx;
}
.project-name {
font-size: 28rpx;
font-weight: 700;
color: #333333;
margin-bottom: 20rpx;
}
.project-stats {
display: flex;
// justify-content: space-between;
}
.stat-item {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
border-right: 2rpx solid #ccc;
&:last-child {
border-right: none;
}
}
.stat-value {
font-size: 36rpx;
font-weight: 700;
}
.stat-label {
font-size: 26rpx;
margin-top: 5rpx;
// color: #666666;
}
.blue {
color: #007aff;
}
.green {
color: #34c759;
}
.red {
color: #ff3b30;
}
.icon-star {
color: #cccccc;
}
}
/deep/ .uni-card {
padding: 0 !important;
}
/deep/ .button-group--right {
padding: 0 0 20rpx;
}
.pinToTop {
background-color: $uni-theme-color;
width: 100rpx;
height: 60rpx;
line-height: 90rpx;
text-align: center;
color: #fff;
font-size: 20rpx;
position: absolute;
top: 0rpx;
right: 0rpx;
position: absolute;
top: 0;
right: 0;
/* 核心:旋转成斜三角效果 */
transform: rotate(45deg) translate(50rpx, -10rpx);
transform-origin: top right;
}
</style>

View File

@@ -1,24 +1,36 @@
<template> <template>
<view class="index-zhuyonghu"> <view class="index-zhuyonghu">
<template v-if="devCount.engineeringListLength > 1"> <template v-if="devCount.engineeringListLength > 0">
<view class="canneng-index-title mb20">所有工程设备统计</view> <view class="canneng-index-title mb20">所有工程设备统计</view>
<view class="header"> <view class="header">
<view class="header-item" @click="jump('allEngineering')"> <view class="header-item boxClick" @click="jump('allEngineering')">
<view class="header-item-value">{{ devCount.onLineDevCount + devCount.offLineDevCount || 0 }}</view> <view class="header-item-value">{{ devCount.onLineDevCount + devCount.offLineDevCount || 0 }}</view>
<view class="header-item-label">设备总数</view> <view class="header-item-label">设备总数</view>
</view> </view>
<view class="header-item" @click="jump('onLineDevs')"> <view class="header-item boxClick" @click="jump('onLineDevs')">
<view class="header-item-value">{{ devCount.onLineDevCount || 0 }}</view> <view class="header-item-value">{{ devCount.onLineDevCount || 0 }}</view>
<view class="header-item-label">在线设备</view> <view class="header-item-label">在线设备</view>
</view> </view>
<view class="header-item" @click="jump('offLineDevs')"> <view class="header-item boxClick" @click="jump('offLineDevs')">
<view class="header-item-value">{{ devCount.offLineDevCount || 0 }}</view> <view class="header-item-value">{{ devCount.offLineDevCount || 0 }}</view>
<view class="header-item-label">离线设备</view> <view class="header-item-label">离线设备</view>
</view> </view>
</view> <view class="header-item boxClick" @click="jumpMessage(0)">
<view class="mt20"></view> <view class="header-item-value">{{ devCount.eventCount || 0 }}</view>
</template> <view class="header-item-label">暂态事件数</view>
<view class="canneng-index-title mb20">当前工程设备统计</view> </view>
<view class="header-item boxClick" @click="jumpMessage(1)">
<view class="header-item-value">{{ devCount.harmonicCount || 0 }}</view>
<view class="header-item-label">稳态事件数</view>
</view>
<view class="header-item boxClick" @click="eningerNum">
<view class="header-item-value">{{ devCount.eningerCount || 0 }}</view>
<view class="header-item-label">工程个数</view>
</view>
</view>
<!-- <view class="mt20"></view> -->
</template>
<!-- <view class="canneng-index-title mb20">当前工程设备统计</view>
<view class="header"> <view class="header">
<view class="header-item" @click="jump('nowEngineering')"> <view class="header-item" @click="jump('nowEngineering')">
<view class="header-item-value" <view class="header-item-value"
@@ -34,135 +46,163 @@
<view class="header-item-value">{{ devCount.currentOffLineDevCount || 0 }}</view> <view class="header-item-value">{{ devCount.currentOffLineDevCount || 0 }}</view>
<view class="header-item-label">离线设备</view> <view class="header-item-label">离线设备</view>
</view> </view>
</view> </view> -->
<view class="canneng-index-title mt20">常用功能</view> <view class="canneng-index-title mt20">常用功能</view>
<view style="padding: 20rpx 20rpx 0"> <view style="padding: 20rpx 20rpx 0">
<Cn-grid title="" :auto-fill="false"> <Cn-grid title="" :auto-fill="false">
<Cn-grid-item src="/static/device2.png" text="设备注册" @click="registerDevice(4)"></Cn-grid-item> <Cn-grid-item
<Cn-grid-item class="boxClick"
src="/static/device2.png" src="/static/device2.png"
text="功能调试" text="设备注册"
@click="registerDevice(2)" @click="registerDevice(4)"
v-if="config.feature" ></Cn-grid-item>
></Cn-grid-item> <!-- <Cn-grid-item
<Cn-grid-item src="/static/device2.png"
src="/static/device2.png" text="功能调试"
text="出厂调试" @click="registerDevice(2)"
@click="registerDevice(3)" v-if="config.feature"
v-if="config.factory" ></Cn-grid-item>
></Cn-grid-item> <Cn-grid-item
<Cn-grid-item background="#fff" v-if="!config.feature"></Cn-grid-item> src="/static/device2.png"
<Cn-grid-item background="#fff" v-if="!config.factory"></Cn-grid-item> text="出厂调试"
<Cn-grid-item background="#fff"></Cn-grid-item> @click="registerDevice(3)"
<!-- <Cn-grid-item src="/static/gateway2.png" text="网关注册" @click="registerGateway"></Cn-grid-item> --> v-if="config.factory"
<!-- <Cn-grid-item src="/static/feedback2.png" text="问题反馈" @click="submitFeedBack"></Cn-grid-item>--> ></Cn-grid-item> -->
</Cn-grid> <!-- <Cn-grid-item background="#fff" v-if="!config.feature"></Cn-grid-item>
</view> <Cn-grid-item background="#fff" v-if="!config.factory"></Cn-grid-item> -->
<uni-popup ref="popup" type="dialog" @maskClick="maskClick"> <Cn-grid-item background="#fff"></Cn-grid-item>
<uni-popup-dialog <Cn-grid-item background="#fff"></Cn-grid-item>
mode="base" <Cn-grid-item background="#fff"></Cn-grid-item>
type="info" <!-- <Cn-grid-item src="/static/gateway2.png" text="网关注册" @click="registerGateway"></Cn-grid-item> -->
content="请选择设备类型" <!-- <Cn-grid-item src="/static/feedback2.png" text="问题反馈" @click="submitFeedBack"></Cn-grid-item>-->
:duration="0" </Cn-grid>
confirmText="直连设备" </view>
cancelText="网关接入" <uni-popup ref="popup" type="dialog" @maskClick="maskClick">
cancelColor="#007aff" <uni-popup-dialog
@close="close" mode="base"
@confirm="confirm" type="info"
></uni-popup-dialog> content="请选择设备类型"
</uni-popup> :duration="0"
</view> confirmText="直连设备"
cancelText="网关接入"
cancelColor="#007aff"
@close="close"
@confirm="confirm"
></uni-popup-dialog>
</uni-popup>
</view>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
loading: true, loading: true,
config: { config: {
feature: true, feature: true,
factory: true, factory: true,
}, },
type: 0, type: 0,
} }
}, },
props: { props: {
devCount: { devCount: {
type: Object, type: Object,
default: {}, default: {},
}, },
}, },
created() { created() {
this.init() this.init()
}, },
methods: { methods: {
init() { init() {
console.log('工程init') console.log('工程init')
let serverConfig = uni.getStorageSync(this.$cacheKey.serverConfig) let serverConfig = uni.getStorageSync(this.$cacheKey.serverConfig)
serverConfig && (this.config = serverConfig) serverConfig && (this.config = serverConfig)
}, },
submitFeedBack() { submitFeedBack() {
uni.navigateTo({ url: '/pages/home/feedback' }) uni.navigateTo({ url: '/pages/home/feedback' })
}, },
registerDevice(type) { registerDevice(type) {
this.type = type this.type = type
this.$refs.popup.open() this.$refs.popup.open()
// uni.showModal({ // uni.showModal({
// title: '提示', // title: '提示',
// content: '请选择设备类型', // content: '请选择设备类型',
// confirmText: '直连设备', // confirmText: '直连设备',
// cancelText: '网关接入', // cancelText: '网关接入',
// cancelColor: '#007aff', // cancelColor: '#007aff',
// success: ({ confirm, cancel }) => { // success: ({ confirm, cancel }) => {
// if (confirm) { // if (confirm) {
// if (this.devCount.engineeringListLength > 0) { // if (this.devCount.engineeringListLength > 0) {
// uni.navigateTo({ // uni.navigateTo({
// url: '/pages/device/new?type=' + type, // url: '/pages/device/new?type=' + type,
// }) // })
// } else { // } else {
// uni.navigateTo({ // uni.navigateTo({
// url: '/pages/engineering/new?from=index&type=' + type, // url: '/pages/engineering/new?from=index&type=' + type,
// }) // })
// } // }
// } else if (cancel) { // } else if (cancel) {
// // uni.navigateTo({ // // uni.navigateTo({
// // url: '/pages/gateway/list', // // url: '/pages/gateway/list',
// // }) // // })
// this.$util.toast('功能正在开发,敬请期待') // this.$util.toast('功能正在开发,敬请期待')
// } // }
// }, // },
// }) // })
}, },
maskClick() { maskClick() {
this.$refs.popup.close() this.$refs.popup.close()
}, },
close() { close() {
this.$util.toast('功能正在开发,敬请期待') this.$util.toast('功能正在开发,敬请期待')
this.$refs.popup.close() this.$refs.popup.close()
}, },
confirm(value) { confirm(value) {
if (this.devCount.engineeringListLength > 0) { // if (this.devCount.engineeringListLength > 0) {
uni.navigateTo({ uni.navigateTo({
url: '/pages/device/new?type=' + this.type, url: '/pages/device/new?type=' + this.type,
}) })
} else { // } else {
uni.navigateTo({ // uni.navigateTo({
url: '/pages/engineering/new?from=index&type=' + this.type, // url: '/pages/engineering/new?from=index&type=' + this.type,
}) // })
} // }
this.$refs.popup.close() this.$refs.popup.close()
}, },
registerGateway() { registerGateway() {
uni.navigateTo({ uni.navigateTo({
url: '/pages/gateway/new', url: '/pages/gateway/new',
}) })
}, },
jump(type) { jump(type) {
uni.navigateTo({ uni.navigateTo({
url: '/pages/device/list?type=' + type, url: '/pages/device/list?type=' + type,
}) })
}, },
}, jumpMessage(type) {
uni.setStorageSync('messageParams', {
engineeringName: '',
engineeringId: '', //工程ID
projectName: '',
projectId: '', //項目ID
deviceName: '',
deviceId: '', //设备ID
lineName: '',
lineId: '', //测点ID
type: type,
})
uni.switchTab({
url: '/pages/index/message1',
})
},
eningerNum() {
uni.navigateTo({
url: '/pages/engineering/list',
})
},
},
} }
</script> </script>
<style lang="scss"></style> <style lang="scss"></style>

View File

@@ -1,72 +1,71 @@
<template> <template>
<view class="index-zhuyonghu"> <view class="index-zhuyonghu">
<template v-if="devCount.engineeringListLength > 1"> <template v-if="devCount.engineeringListLength > 1">
<view class="canneng-index-title mb20">所有工程设备统计</view> <view class="canneng-index-title mb20">所有工程设备统计</view>
<view class="header"> <view class="header">
<view class="header-item" @click="jump('allEngineering')"> <view class="header-item boxClick" @click="jump('allEngineering')">
<view class="header-item-value">{{ devCount.onLineDevCount + devCount.offLineDevCount || 0 }}</view> <view class="header-item-value">{{ devCount.onLineDevCount + devCount.offLineDevCount || 0 }}</view>
<view class="header-item-label">设备总数</view> <view class="header-item-label">设备总数</view>
</view> </view>
<view class="header-item" @click="jump('onLineDevs')"> <view class="header-item boxClick" @click="jump('onLineDevs')">
<view class="header-item-value">{{ devCount.onLineDevCount || 0 }}</view> <view class="header-item-value">{{ devCount.onLineDevCount || 0 }}</view>
<view class="header-item-label">在线设备</view> <view class="header-item-label">在线设备</view>
</view> </view>
<view class="header-item" @click="jump('offLineDevs')"> <view class="header-item boxClick" @click="jump('offLineDevs')">
<view class="header-item-value">{{ devCount.offLineDevCount || 0 }}</view> <view class="header-item-value">{{ devCount.offLineDevCount || 0 }}</view>
<view class="header-item-label">离线设备</view> <view class="header-item-label">离线设备</view>
</view> </view>
</view> </view>
<view class="mt20"></view> <view class="mt20"></view>
</template> </template>
<view class="canneng-index-title mb20">当前工程设备统计</view> <view class="canneng-index-title mb20">当前工程设备统计</view>
<view class="header"> <view class="header">
<view class="header-item" @click="jump('nowEngineering')"> <view class="header-item boxClick" @click="jump('nowEngineering')">
<view class="header-item-value">{{ <view class="header-item-value">{{
devCount.currentOnLineDevCount + devCount.currentOffLineDevCount || 0 devCount.currentOnLineDevCount + devCount.currentOffLineDevCount || 0
}}</view> }}</view>
<view class="header-item-label">设备总数</view> <view class="header-item-label">设备总数</view>
</view> </view>
<view class="header-item" @click="jump('currentOnLineDevs')"> <view class="header-item boxClick" @click="jump('currentOnLineDevs')">
<view class="header-item-value">{{ devCount.currentOnLineDevCount || 0 }}</view> <view class="header-item-value">{{ devCount.currentOnLineDevCount || 0 }}</view>
<view class="header-item-label">在线设备</view> <view class="header-item-label">在线设备</view>
</view> </view>
<view class="header-item" @click="jump('currentOffLineDevs')"> <view class="header-item boxClick" @click="jump('currentOffLineDevs')">
<view class="header-item-value">{{ devCount.currentOffLineDevCount || 0 }}</view> <view class="header-item-value">{{ devCount.currentOffLineDevCount || 0 }}</view>
<view class="header-item-label">离线设备</view> <view class="header-item-label">离线设备</view>
</view> </view>
</view> </view>
<view style="padding: 20rpx 20rpx 0"> <!-- <view style="padding: 20rpx 20rpx 0">
<Cn-grid title=""> <Cn-grid title="">
<Cn-grid-item src="/static/device2.png" text="设备注册" @click="registerDevice"></Cn-grid-item> <Cn-grid-item src="/static/device2.png" text="设备注册" @click="registerDevice"></Cn-grid-item>
<!-- <Cn-grid-item src="/static/gateway2.png" text="网关注册" @click="registerGateway"></Cn-grid-item> --> <Cn-grid-item src="/static/feedback2.png" text="问题反馈" @click="submitFeedBack"></Cn-grid-item>
<Cn-grid-item src="/static/feedback2.png" text="问题反馈" @click="submitFeedBack"></Cn-grid-item> </Cn-grid>
</Cn-grid> </view> -->
</view>
</view>
</view> </template>
</template> <script>
<script> export default {
export default { props: {
props: { devCount: {
devCount: { type: Object,
type: Object, default: {},
default: {}, },
}, },
}, methods: {
methods: { jump(type) {
jump(type) { uni.navigateTo({
uni.navigateTo({ url:
url: '/pages/device/list?type=' + type
'/pages/device/list?type=' + type })
}) },
}, submitFeedBack() {
submitFeedBack() { uni.navigateTo({url: '/pages/home/feedback'})
uni.navigateTo({url: '/pages/home/feedback'}) },
}, registerDevice() {
registerDevice() { this.$util.toast('此功能仅对正式用户开放')
this.$util.toast('此功能仅对正式用户开放') },
}, },
}, }
} </script>
</script> <style lang="scss"></style>
<style lang="scss"></style>

View File

@@ -1,122 +1,135 @@
<template> <template>
<view class="index-zhuanzhi"> <view class="index-zhuanzhi">
<template v-if="devCount.engineeringListLength > 1"> <template v-if="devCount.engineeringListLength > 1">
<view class="canneng-index-title mb20">所有工程设备统计</view> <view class="canneng-index-title mb20">所有工程设备统计</view>
<view class="header"> <view class="header">
<view class="header-item" @click="jump('allEngineering')"> <view class="header-item boxClick" @click="jump('allEngineering')">
<view class="header-item-value">{{ devCount.onLineDevCount + devCount.offLineDevCount || 0 }}</view> <view class="header-item-value">{{ devCount.onLineDevCount + devCount.offLineDevCount || 0 }}</view>
<view class="header-item-label">设备总数</view> <view class="header-item-label">设备总数</view>
</view> </view>
<view class="header-item" @click="jump('onLineDevs')"> <view class="header-item boxClick" @click="jump('onLineDevs')">
<view class="header-item-value">{{ devCount.onLineDevCount || 0 }}</view> <view class="header-item-value">{{ devCount.onLineDevCount || 0 }}</view>
<view class="header-item-label">在线设备</view> <view class="header-item-label">在线设备</view>
</view> </view>
<view class="header-item" @click="jump('offLineDevs')"> <view class="header-item boxClick" @click="jump('offLineDevs')">
<view class="header-item-value">{{ devCount.offLineDevCount || 0 }}</view> <view class="header-item-value">{{ devCount.offLineDevCount || 0 }}</view>
<view class="header-item-label">离线设备</view> <view class="header-item-label">离线设备</view>
</view> </view>
<view class="header-item" @click="jumpMessage"> <view class="header-item boxClick" @click="jumpMessage(2, false)">
<view class="header-item-value">{{ devCount.alarmCount || 0 }}</view> <view class="header-item-value">{{ devCount.alarmCount || 0 }}</view>
<view class="header-item-label">告警数量</view> <view class="header-item-label">告警数量</view>
</view> </view>
<view class="header-item" @click="jumpMessage"> <view class="header-item boxClick" @click="jumpMessage(0, false)">
<view class="header-item-value">{{ <view class="header-item-value">{{
devCount.eventCount + devCount.runCount + devCount.harmonicCount || 0 devCount.eventCount + devCount.runCount + devCount.harmonicCount || 0
}}</view> }}</view>
<view class="header-item-label">事件数量</view> <view class="header-item-label">事件数量</view>
</view> </view>
<view class="header-item" @click="eningerNum"> <view class="header-item boxClick" @click="eningerNum">
<view class="header-item-value">{{ devCount.eningerCount || 0 }}</view> <view class="header-item-value">{{ devCount.eningerCount || 0 }}</view>
<view class="header-item-label">工程个数</view> <view class="header-item-label">工程个数</view>
</view> </view>
</view> </view>
<view class="mt20"></view> <view class="mt20"></view>
</template> </template>
<view class="canneng-index-title mb20">当前工程设备统计</view> <view class="canneng-index-title mb20">当前工程设备统计</view>
<view class="header"> <view class="header">
<view class="header-item" @click="jump('nowEngineering')"> <view class="header-item boxClick" @click="jump('nowEngineering')">
<view class="header-item-value">{{ <view class="header-item-value">{{
devCount.currentOnLineDevCount + devCount.currentOffLineDevCount || 0 devCount.currentOnLineDevCount + devCount.currentOffLineDevCount || 0
}}</view> }}</view>
<view class="header-item-label">设备总数</view> <view class="header-item-label">设备总数</view>
</view> </view>
<view class="header-item" @click="jump('currentOnLineDevs')"> <view class="header-item boxClick" @click="jump('currentOnLineDevs')">
<view class="header-item-value">{{ devCount.currentOnLineDevCount || 0 }}</view> <view class="header-item-value">{{ devCount.currentOnLineDevCount || 0 }}</view>
<view class="header-item-label">在线设备</view> <view class="header-item-label">在线设备</view>
</view> </view>
<view class="header-item" @click="jump('currentOffLineDevs')"> <view class="header-item boxClick" @click="jump('currentOffLineDevs')">
<view class="header-item-value">{{ devCount.currentOffLineDevCount || 0 }}</view> <view class="header-item-value">{{ devCount.currentOffLineDevCount || 0 }}</view>
<view class="header-item-label">离线设备</view> <view class="header-item-label">离线设备</view>
</view> </view>
<view class="header-item" @click="jumpMessage"> <view class="header-item boxClick" @click="jumpMessage(2, true)">
<view class="header-item-value">{{ devCount.currentAlarmCount || 0 }}</view> <view class="header-item-value">{{ devCount.currentAlarmCount || 0 }}</view>
<view class="header-item-label">告警数量</view> <view class="header-item-label">告警数量</view>
</view> </view>
<view class="header-item" @click="jumpMessage"> <view class="header-item boxClick" @click="jumpMessage(0, true)">
<view class="header-item-value">{{ <view class="header-item-value">{{
devCount.currentEventCount + devCount.currentRunCount + devCount.currentHarmonicCount || 0 devCount.currentEventCount + devCount.currentRunCount + devCount.currentHarmonicCount || 0
}}</view> }}</view>
<view class="header-item-label">事件数量</view> <view class="header-item-label">事件数量</view>
</view> </view>
<view class="header-item" @click="projectNum(true)"> <view class="header-item boxClick" @click="projectNum(true)">
<view class="header-item-value">{{ devCount.currentProjectCount || 0 }}</view> <view class="header-item-value">{{ devCount.currentProjectCount || 0 }}</view>
<view class="header-item-label">项目个数</view> <view class="header-item-label">项目个数</view>
</view> </view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
loading: false, loading: false,
} }
}, },
props: { props: {
devCount: { devCount: {
type: Object, type: Object,
default: {}, default: {},
}, },
}, },
methods: { methods: {
jumpMessage(){ jumpMessage(type, flag) {
uni.switchTab({ uni.setStorageSync('messageParams', {
url: '/pages/index/message', // name: flag ? uni.getStorageSync('engineering').name : '',
}) // id: flag ? uni.getStorageSync('engineering').id : '',
}, engineeringName: flag ? uni.getStorageSync('engineering').name : '',
eningerNum(){ engineeringId: flag ? uni.getStorageSync('engineering').id : '', //工程ID
uni.navigateTo({ projectName: '',
url: '/pages/engineering/list', projectId: '', //項目ID
}) deviceName: '',
}, deviceId: '', //设备ID
projectWarning() { lineName: '',
uni.navigateTo({ lineId: '', //测点ID
url: '/pages/zhuanzhi/warning', type: type,
}) })
}, uni.switchTab({
projectNum() { url: '/pages/index/message1',
console.log(now) })
if (now) { },
let engineering = uni.getStorageSync('engineering') eningerNum() {
uni.navigateTo({ uni.navigateTo({
url: '/pages/project/list?engineeringName=' + engineering.name + '&engineeringId=' + engineering.id, url: '/pages/engineering/list',
}) })
} else { },
uni.navigateTo({ projectWarning() {
url: '/pages/project/list', uni.navigateTo({
}) url: '/pages/zhuanzhi/warning',
} })
}, },
jump(type) { projectNum(now) {
uni.navigateTo({ console.log(now)
url: '/pages/device/list?type=' + type, if (now) {
}) let engineering = uni.getStorageSync('engineering')
}, uni.navigateTo({
}, url: '/pages/project/list?engineeringName=' + engineering.name + '&engineeringId=' + engineering.id,
created() {}, })
} } else {
</script> uni.navigateTo({
<style lang="scss"> url: '/pages/project/list',
.index-zhuanzhi { })
} }
</style> },
jump(type) {
uni.navigateTo({
url: '/pages/device/list?type=' + type,
})
},
},
created() {},
}
</script>
<style lang="scss">
.index-zhuanzhi {
}
</style>

View File

@@ -1,143 +1,174 @@
<template> <template>
<view class="index-zhuyonghu"> <view class="index-zhuyonghu">
<template v-if="devCount.engineeringListLength > 1"> <template v-if="devCount.engineeringListLength > 1">
<view class="canneng-index-title mb20">所有工程设备统计</view> <view class="canneng-index-title mb20">所有工程设备统计</view>
<view class="header"> <view class="header">
<view class="header-item" @click="jump('allEngineering')"> <view class="header-item boxClick" @click="jump('allEngineering')">
<view class="header-item-value">{{ devCount.onLineDevCount + devCount.offLineDevCount || 0 }}</view> <view class="header-item-value">{{ devCount.onLineDevCount + devCount.offLineDevCount || 0 }}</view>
<view class="header-item-label">设备总数</view> <view class="header-item-label">设备总数</view>
</view> </view>
<view class="header-item" @click="jump('onLineDevs')"> <view class="header-item boxClick" @click="jump('onLineDevs')">
<view class="header-item-value">{{ devCount.onLineDevCount || 0 }}</view> <view class="header-item-value">{{ devCount.onLineDevCount || 0 }}</view>
<view class="header-item-label">在线设备</view> <view class="header-item-label">在线设备</view>
</view> </view>
<view class="header-item" @click="jump('offLineDevs')"> <view class="header-item boxClick" @click="jump('offLineDevs')">
<view class="header-item-value">{{ devCount.offLineDevCount || 0 }}</view> <view class="header-item-value">{{ devCount.offLineDevCount || 0 }}</view>
<view class="header-item-label">离线设备</view> <view class="header-item-label">离线设备</view>
</view> </view>
</view> </view>
<view class="mt20"></view> <view class="mt20"></view>
</template> </template>
<view class="canneng-index-title mb20">当前工程设备统计</view> <view class="canneng-index-title mb20">当前工程设备统计</view>
<view class="header"> <view class="header">
<view class="header-item" @click="jump('nowEngineering')"> <view class="header-item boxClick" @click="jump('nowEngineering')">
<view class="header-item-value" <view class="header-item-value"
>{{ devCount.currentOnLineDevCount + devCount.currentOffLineDevCount || 0 }} >{{ devCount.currentOnLineDevCount + devCount.currentOffLineDevCount || 0 }}
</view> </view>
<view class="header-item-label">设备总数</view> <view class="header-item-label">设备总数</view>
</view> </view>
<view class="header-item" @click="jump('currentOnLineDevs')"> <view class="header-item boxClick" @click="jump('currentOnLineDevs')">
<view class="header-item-value">{{ devCount.currentOnLineDevCount || 0 }}</view> <view class="header-item-value">{{ devCount.currentOnLineDevCount || 0 }}</view>
<view class="header-item-label">在线设备</view> <view class="header-item-label">在线设备</view>
</view> </view>
<view class="header-item" @click="jump('currentOffLineDevs')"> <view class="header-item boxClick" @click="jump('currentOffLineDevs')">
<view class="header-item-value">{{ devCount.currentOffLineDevCount || 0 }}</view> <view class="header-item-value">{{ devCount.currentOffLineDevCount || 0 }}</view>
<view class="header-item-label">离线设备</view> <view class="header-item-label">离线设备</view>
</view> </view>
</view> <view class="header-item boxClick" @click="jumpMessage('0')">
<view class="canneng-index-title mt20">常用功能</view> <view class="header-item-value">{{ devCount.currentEventCount || 0 }}</view>
<view style="padding: 20rpx 20rpx 0"> <view class="header-item-label">暂态事件数</view>
<Cn-grid title=""> </view>
<Cn-grid-item src="/static/device2.png" text="设备注册" @click="registerDevice"></Cn-grid-item> <view class="header-item boxClick" @click="jumpMessage('1')">
<!-- <Cn-grid-item src="/static/gateway2.png" text="网关注册" @click="registerGateway"></Cn-grid-item> --> <view class="header-item-value">{{ devCount.currentHarmonicCount || 0 }}</view>
<Cn-grid-item src="/static/feedback2.png" text="问题反馈" @click="submitFeedBack"></Cn-grid-item> <view class="header-item-label">稳态事件数</view>
</Cn-grid> </view>
</view> </view>
<uni-popup ref="popup" type="dialog" @maskClick='maskClick'> <view class="canneng-index-title mt20">常用功能</view>
<uni-popup-dialog <view style="padding: 20rpx 20rpx 0">
mode="base" <Cn-grid title="">
type="info" <Cn-grid-item
content="请选择设备类型" src="/static/device2.png"
:duration="0" class="boxClick"
confirmText="直连设备" text="设备注册"
cancelText="网关接入" @click="registerDevice"
cancelColor= '#007aff' ></Cn-grid-item>
@close="close" <!-- <Cn-grid-item src="/static/gateway2.png" text="网关注册" @click="registerGateway"></Cn-grid-item> -->
@confirm="confirm" <Cn-grid-item
></uni-popup-dialog> src="/static/feedback2.png"
class="boxClick"
</uni-popup> text="问题反馈"
</view> @click="submitFeedBack"
></Cn-grid-item>
</Cn-grid>
</view>
<uni-popup ref="popup" type="dialog" @maskClick="maskClick">
<uni-popup-dialog
mode="base"
type="info"
content="请选择设备类型"
:duration="0"
confirmText="直连设备"
cancelText="网关接入"
cancelColor="#007aff"
@close="close"
@confirm="confirm"
></uni-popup-dialog>
</uni-popup>
</view>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
loading: false, loading: false,
} }
}, },
props: { props: {
devCount: { devCount: {
type: Object, type: Object,
default: {}, default: {},
}, },
}, },
methods: { methods: {
submitFeedBack() { submitFeedBack() {
uni.navigateTo({ url: '/pages/home/feedback' }) uni.navigateTo({ url: '/pages/home/feedback' })
}, },
registerDevice() { registerDevice() {
this.$refs.popup.open() this.$refs.popup.open()
// uni.showModal({ // uni.showModal({
// title: '提示', // title: '提示',
// content: '请选择设备类型', // content: '请选择设备类型',
// confirmText: '直连设备', // confirmText: '直连设备',
// cancelText: '网关接入', // cancelText: '网关接入',
// cancelColor: '#007aff', // cancelColor: '#007aff',
// success: ({confirm, cancel}) => { // success: ({confirm, cancel}) => {
// if (confirm) { // if (confirm) {
// if (this.devCount.engineeringListLength > 0) { // if (this.devCount.engineeringListLength > 0) {
// uni.navigateTo({ // uni.navigateTo({
// url: '/pages/device/new?type=4', // url: '/pages/device/new?type=4',
// }) // })
// } else { // } else {
// uni.navigateTo({ // uni.navigateTo({
// url: '/pages/engineering/new?from=index' // url: '/pages/engineering/new?from=index'
// }) // })
// } // }
// } else if (cancel) { // } else if (cancel) {
// // uni.navigateTo({ // // uni.navigateTo({
// // url: '/pages/gateway/list', // // url: '/pages/gateway/list',
// // }) // // })
// this.$util.toast('功能正在开发,敬请期待') // this.$util.toast('功能正在开发,敬请期待')
// } // }
// }, // },
// }) // })
}, },
maskClick(){ maskClick() {
this.$refs.popup.close() this.$refs.popup.close()
}, },
close() { close() {
this.$util.toast('功能正在开发,敬请期待') this.$util.toast('功能正在开发,敬请期待')
this.$refs.popup.close() this.$refs.popup.close()
}, },
confirm(value) { confirm(value) {
// if (this.devCount.engineeringListLength > 0) {
if (this.devCount.engineeringListLength > 0) { uni.navigateTo({
uni.navigateTo({ url: '/pages/device/new?type=4',
url: '/pages/device/new?type=4', })
}) // } else {
} else { // uni.navigateTo({
uni.navigateTo({ // url: '/pages/engineering/new?from=index',
url: '/pages/engineering/new?from=index' // })
}) // }
}
this.$refs.popup.close()
},
this.$refs.popup.close() registerGateway() {
}, uni.navigateTo({
registerGateway() { url: '/pages/gateway/new',
uni.navigateTo({ })
url: '/pages/gateway/new', },
}) jump(type) {
}, uni.navigateTo({
jump(type) { url: '/pages/device/list?type=' + type,
uni.navigateTo({ })
url: '/pages/device/list?type=' + type, },
}) jumpMessage(type) {
}, uni.setStorageSync('messageParams', {
}, engineeringName: '',
engineeringId: '', //工程ID
projectName: '',
projectId: '', //項目ID
deviceName: '',
deviceId: '', //设备ID
lineName: '',
lineId: '', //测点ID
type: type,
})
uni.switchTab({
url: '/pages/index/message1',
})
},
},
} }
</script> </script>
<style lang="scss"></style> <style lang="scss"></style>

View File

@@ -1,122 +1,131 @@
<template> <template>
<view class="index-zhuanzhi"> <view class="index-zhuanzhi">
<template v-if="devCount.engineeringListLength > 1"> <template v-if="devCount.engineeringListLength > 1">
<view class="canneng-index-title mb20">所有工程设备统计</view> <view class="canneng-index-title mb20">所有工程设备统计</view>
<view class="header"> <view class="header">
<view class="header-item" @click="jump('allEngineering')"> <view class="header-item boxClick" @click="jump('allEngineering')">
<view class="header-item-value">{{ devCount.onLineDevCount + devCount.offLineDevCount || 0 }}</view> <view class="header-item-value">{{ devCount.onLineDevCount + devCount.offLineDevCount || 0 }}</view>
<view class="header-item-label">设备总数</view> <view class="header-item-label">设备总数</view>
</view> </view>
<view class="header-item" @click="jump('onLineDevs')"> <view class="header-item boxClick" @click="jump('onLineDevs')">
<view class="header-item-value">{{ devCount.onLineDevCount || 0 }}</view> <view class="header-item-value">{{ devCount.onLineDevCount || 0 }}</view>
<view class="header-item-label">在线设备</view> <view class="header-item-label">在线设备</view>
</view> </view>
<view class="header-item" @click="jump('offLineDevs')"> <view class="header-item boxClick" @click="jump('offLineDevs')">
<view class="header-item-value">{{ devCount.offLineDevCount || 0 }}</view> <view class="header-item-value">{{ devCount.offLineDevCount || 0 }}</view>
<view class="header-item-label">离线设备</view> <view class="header-item-label">离线设备</view>
</view> </view>
<view class="header-item" @click="jumpMessage"> <view class="header-item boxClick" @click="jumpMessage(0, false)">
<view class="header-item-value">{{ devCount.alarmCount || 0 }}</view> <view class="header-item-value">{{ devCount.eventCount || 0 }}</view>
<view class="header-item-label">告警数量</view> <view class="header-item-label">暂态事件数</view>
</view> </view>
<view class="header-item" @click="jumpMessage"> <view class="header-item boxClick" @click="jumpMessage(1, false)">
<view class="header-item-value">{{ <view class="header-item-value">{{ devCount.harmonicCount || 0 }}</view>
devCount.eventCount + devCount.runCount + devCount.harmonicCount || 0 <view class="header-item-label">稳态事件数</view>
}}</view> </view>
<view class="header-item-label">事件数量</view> <view class="header-item boxClick" @click="eningerNum">
</view> <view class="header-item-value">{{ devCount.eningerCount || 0 }}</view>
<view class="header-item" @click="eningerNum"> <view class="header-item-label">工程个数</view>
<view class="header-item-value">{{ devCount.eningerCount || 0 }}</view> </view>
<view class="header-item-label">工程个数</view> </view>
</view> <view class="mt20"></view>
</view> </template>
<view class="mt20"></view> <view class="canneng-index-title mb20">当前工程设备统计</view>
</template> <view class="header">
<view class="canneng-index-title mb20">当前工程设备统计</view> <view class="header-item boxClick" @click="jump('nowEngineering')">
<view class="header"> <view class="header-item-value"
<view class="header-item" @click="jump('nowEngineering')"> >{{ devCount.currentOnLineDevCount + devCount.currentOffLineDevCount || 0 }}
<view class="header-item-value" </view>
>{{ devCount.currentOnLineDevCount + devCount.currentOffLineDevCount || 0 }} <view class="header-item-label">设备总数</view>
</view> </view>
<view class="header-item-label">设备总数</view> <view class="header-item boxClick" @click="jump('currentOnLineDevs')">
</view> <view class="header-item-value">{{ devCount.currentOnLineDevCount || 0 }}</view>
<view class="header-item" @click="jump('currentOnLineDevs')"> <view class="header-item-label">在线设备</view>
<view class="header-item-value">{{ devCount.currentOnLineDevCount || 0 }}</view> </view>
<view class="header-item-label">在线设备</view> <view class="header-item boxClick" @click="jump('currentOffLineDevs')">
</view> <view class="header-item-value">{{ devCount.currentOffLineDevCount || 0 }}</view>
<view class="header-item" @click="jump('currentOffLineDevs')"> <view class="header-item-label">离线设备</view>
<view class="header-item-value">{{ devCount.currentOffLineDevCount || 0 }}</view> </view>
<view class="header-item-label">离线设备</view> <view class="header-item boxClick" @click="jumpMessage(0, true)">
</view> <view class="header-item-value">{{ devCount.currentEventCount || 0 }}</view>
<view class="header-item" @click="jumpMessage"> <view class="header-item-label">暂态事件数</view>
<view class="header-item-value">{{ devCount.currentAlarmCount || 0 }}</view> </view>
<view class="header-item-label">告警数量</view> <view class="header-item boxClick" @click="jumpMessage(1, true)">
</view> <view class="header-item-value">{{ devCount.currentHarmonicCount || 0 }}</view>
<view class="header-item" @click="jumpMessage"> <view class="header-item-label">稳态事件数</view>
<view class="header-item-value">{{ </view>
devCount.currentEventCount + devCount.currentRunCount + devCount.currentHarmonicCount || 0 <view class="header-item boxClick" @click="projectNum(true)">
}}</view> <view class="header-item-value">{{ devCount.currentProjectCount || 0 }}</view>
<view class="header-item-label">事件数量</view> <view class="header-item-label">项目个数</view>
</view> </view>
<view class="header-item" @click="projectNum(true)"> </view>
<view class="header-item-value">{{ devCount.currentProjectCount || 0 }}</view> </view>
<view class="header-item-label">项目个数</view> </template>
</view> <script>
</view> export default {
</view> data() {
</template> return {
<script> loading: false,
export default { }
data() { },
return { props: {
loading: false, devCount: {
} type: Object,
}, default: {},
props: { },
devCount: { },
type: Object, methods: {
default: {}, projectWarning() {
}, uni.navigateTo({
}, url: '/pages/zhuanzhi/warning',
methods: { })
projectWarning() { },
uni.navigateTo({ eningerNum() {
url: '/pages/zhuanzhi/warning', uni.navigateTo({
}) url: '/pages/engineering/list',
}, })
eningerNum() { },
uni.navigateTo({ jumpMessage(type, flag) {
url: '/pages/engineering/list', uni.setStorageSync('messageParams', {
}) // name: flag ? uni.getStorageSync('engineering').name : '',
}, // id: flag ? uni.getStorageSync('engineering').id : '',
jumpMessage(){ engineeringName: flag ? uni.getStorageSync('engineering').name : '',
uni.switchTab({ engineeringId: flag ? uni.getStorageSync('engineering').id : '', //工程ID
url: '/pages/index/message', projectName: '',
}) projectId: '', //項目ID
}, deviceName: '',
projectNum(now) { deviceId: '', //设备ID
console.log(now) lineName: '',
if (now) { lineId: '', //测点ID
let engineering = uni.getStorageSync('engineering') type: type,
uni.navigateTo({ })
url: '/pages/project/list?engineeringName=' + engineering.name + '&engineeringId=' + engineering.id, uni.switchTab({
}) url: '/pages/index/message1',
} else { })
uni.navigateTo({ },
url: '/pages/project/list', projectNum(now) {
}) console.log(now)
} if (now) {
}, let engineering = uni.getStorageSync('engineering')
jump(type) { uni.navigateTo({
uni.navigateTo({ url: '/pages/project/list?engineeringName=' + engineering.name + '&engineeringId=' + engineering.id,
url: '/pages/device/list?type=' + type, })
}) } else {
}, uni.navigateTo({
}, url: '/pages/project/list',
created() {}, })
} }
</script> },
<style lang="scss"> jump(type) {
.index-zhuanzhi { uni.navigateTo({
} url: '/pages/device/list?type=' + type,
</style> })
},
},
created() {},
}
</script>
<style lang="scss">
.index-zhuanzhi {
}
</style>

View File

@@ -0,0 +1,346 @@
<template>
<view class="dateReport">
<!-- {{ height }} -->
<view class="pd20">
<uni-segmented-control
:current="curSub"
class="subsection"
active-color="#376cf3"
:values="subsectionList"
@clickItem="sectionChange"
/>
</view>
<view class="filterCriteria">
<!-- 筛选条件 -->
<Cn-filterCriteria @select="select" :singleChoice="true" :showDatetime="curSub == 0"> </Cn-filterCriteria>
</view>
<!-- 卡片 -->
<scroll-view
scroll-y="true"
@refresherrefresh="refresherrefresh"
:refresher-triggered="triggered"
refresher-enabled="true"
class="event-list mt20"
:style="{ height: 'calc(100vh - ' + (navHeight + height) + 'px)', overflow: 'auto' }"
>
<!-- 循环渲染事件项 -->
<uni-card class="event-item" :class="item.type" v-for="(item, index) in store.data" :key="index">
<!-- 头部图标 + 信息 + 操作 -->
<view class="event-header">
<view class="event-icon">
<!-- 动态图标根据类型切换 -->
<!-- <uni-icons
custom-prefix="iconfont"
type="icon-kouanjiancedian"
size="40"
color="#E6A23C"
></uni-icons> -->
<Cn-icon-transient :name="`报告`" />
<view class="badge1" v-if="item.isRead == 0"> </view>
</view>
<view class="event-info">
<view class="event-title">
<text class="event-id">{{ item.lineName }}</text>
<!-- <view class="event-tags"
>{{ selectValue.report == 0 ? item.startTime : item.startTime + '至' + item.endTime }}
</view> -->
</view>
<view class="event-desc">
<text
>统计时间{{
curSub == 0 ? item.startTime : item.startTime + ' 至 ' + item.endTime
}}</text
>
</view>
</view>
<view class="event-action" v-if="curSub == 0 ? monthFlag : item.endTime != thisMonth01">
<view class="iconText boxClick" @click="download(item)"
><uni-icons type="arrow-down" color="#fff" size="16"></uni-icons>
</view>
</view>
</view>
<!-- 详情区域 -->
<view class="event-detail textBox" @touchmove.stop>
<text v-if="curSub == 0 ? monthFlag : item.endTime != thisMonth01">{{
item.overLimitDesc == '' ? '该监测点暂无指标越限' : item.overLimitDesc
}}</text>
<text v-else>数据未生成暂不支持下载</text>
</view>
<!-- <view class="downloadReport" @click="download">
<uni-icons type="download" size="16" color="#376cf3"></uni-icons>下载报告
</view> -->
</uni-card>
<uni-load-more
v-if="store.status == 'loading' || (store.data && store.data.length > 0)"
:status="store.status"
></uni-load-more>
<Cn-empty v-else style="top: 20%"></Cn-empty>
</scroll-view>
</view>
</template>
<script>
import list from '@/common/js/list'
import { downloadHarmonicReport } from '@/common/api/report.js'
export default {
components: {},
props: {
indexList: {
type: Array,
default: () => [],
},
total: {
type: Number,
default: 0,
},
navHeight: {
type: Number,
default: 0,
},
},
mixins: [list],
data() {
return {
status: 'noMore',
curSub: 0,
subsectionList: ['周报', '月报'],
thisSelectValue: {},
triggered: true,
height: 0,
thisMonth01: '',
monthFlag: true,
}
},
created() {},
mounted() {
this.thisMonth01 = this.$util.getToday().slice(0, -3) + '-01'
this.monthFlag = this.$util.getToday() != this.$util.getToday().slice(0, -3) + '-01'
// this.setHeight()
},
methods: {
setHeight() {
uni.createSelectorQuery()
.select('.filterCriteria')
.boundingClientRect((rect) => {
//
// #ifdef H5
this.height = rect?.height + 140 || 0
// #endif
// #ifdef APP-PLUS
this.height = rect?.height + 75 || 0
// #endif
})
.exec()
},
sectionChange(index) {
this.curSub = index.currentIndex
this.init()
},
init() {
if (this.selectValue.lineId == '') return
this.store = this.DataSource('/cs-report-boot/csAppReport/reportList')
// this.store.params.pageSize = 10000
this.store.params.timeType = this.curSub //this.selectValue.report
this.store.params.engineerId = this.selectValue.engineeringId
this.store.params.projectId = this.selectValue.projectId
this.store.params.devId = this.selectValue.deviceId
this.store.params.lineId = this.selectValue.lineId
if (this.curSub == 0) {
this.store.params.time = this.selectValue.date
} else {
this.store.params.time = this.selectValue.range + '-01'
}
// this.store.params.startTime = this.selectValue.range[0]
// this.store.params.endTime = this.selectValue.range[1]
this.store.loadedCallback = () => {}
this.store.reload()
},
select(value) {
this.selectValue = value
setTimeout(() => {
this.setHeight()
}, 200)
this.init()
},
// 下载
download(item) {
uni.showLoading({
title: '下载中,请稍等...',
mask: true,
})
downloadHarmonicReport({
devId: this.selectValue.deviceId,
endTime: item.endTime,
engineerId: this.selectValue.engineeringId,
lineId: this.selectValue.lineId,
list: [],
projectId: this.selectValue.projectId,
startTime: item.startTime,
time: '',
timeType: this.selectValue.report,
})
.then((res) => {
// 下载文件资源到本地
uni.downloadFile({
url: res.data, // 后端返回的线上文件路径
success: function (res) {
if (res.statusCode === 200) {
// 文件到本地
uni.saveFile({
tempFilePath: res.tempFilePath, //临时路径
success: function (data) {
var savedFilePath = data.savedFilePath
// 在app端执行
// #ifdef APP-PLUS
let osname = plus.os.name
// 如果是安卓的话弹出提示
uni.showToast({
icon: 'success',
mask: true,
title: '下载成功!',
duration: 1000,
})
// #endif
//ios手机直接打开文件手动存储文件到手机Android手机从根目录创建文件夹保存文件并改名
setTimeout(() => {
//打开文档查看
uni.openDocument({
filePath: data.savedFilePath,
success: function (ress) {
console.log('成功打开文件')
},
fail() {
console.log('打开文件失败')
},
})
}, 500)
},
})
console.log('下载成功')
} else {
uni.showToast({
icon: 'none',
mask: true,
title: '下载失败!',
duration: 1000,
})
}
},
fail: function (res) {},
})
})
.catch((err) => {
uni.showToast({
icon: 'none',
mask: true,
title: err.message,
duration: 1000,
})
})
},
// 下拉
refresherrefresh() {
this.triggered = true
uni.startPullDownRefresh()
setTimeout(() => {
this.triggered = false
}, 500)
},
},
computed: {},
watch: {},
}
</script>
<style lang="scss" scoped>
@import '@/pages/message1/index.scss';
.event-title {
justify-content: space-between;
}
.event-tags {
display: flex;
font-size: 27rpx !important ;
line-height: 50rpx;
}
.event-detail {
// font-size: 25rpx !important;
// display: grid;
// grid-template-columns: 1fr 1fr;
}
.downloadReport {
width: 100%;
background: #376cf320;
height: 60rpx;
line-height: 60rpx;
color: #376cf3;
font-weight: 600;
border-radius: 15rpx;
margin-top: 10rpx;
display: flex;
justify-content: center;
}
.filterCriteria {
.nav {
background-color: #fff;
}
.choose1 {
background-color: #fff;
padding: 0 20rpx;
display: flex;
justify-content: space-between;
/deep/ .uni-checkbox-input {
width: 30rpx;
height: 30rpx;
}
font-size: 26rpx;
}
}
/deep/ .uni-scroll-view-refresher {
display: none;
}
.iconText {
width: 45rpx;
height: 45rpx;
border-radius: 50%;
background-color: $uni-theme-color;
text-align: center;
line-height: 40rpx;
}
.segmented-control {
flex: 1;
margin-right: 24rpx;
height: 60rpx;
}
/* 列表容器 */
.event-list {
/* 头部:图标 + 信息 + 操作 */
.event-header {
display: flex;
align-items: center;
margin-bottom: 10rpx;
}
/* 图标区域(按类型区分背景色) */
.event-icon {
background-color: #376cf320;
}
.event-tags {
font-size: 24rpx;
}
}
.textBox {
// @touchmove.stop
max-height: 110rpx;
overflow-y: auto;
}
</style>

View File

@@ -0,0 +1,385 @@
<template>
<view class="dateReport">
<view class="pd20">
<uni-segmented-control :current="curSub" class="subsection" active-color="#376cf3" :values="subsectionList"
@clickItem="sectionChange" />
</view>
<!-- 申请报告 -->
<view v-show="curSub == 0">
<!-- apply -->
<Apply ref="applyRef" :navHeight="navHeight" />
</view>
<!-- 申请记录 -->
<view v-if="curSub == 1">
<view class="filterCriteria">
<!-- 筛选条件 -->
<Cn-filterCriteria @select="select" :showQianTree="false"> </Cn-filterCriteria>
</view>
<scroll-view scroll-y="true" @refresherrefresh="refresherrefresh" @scrolltolower="scrolltolower"
:refresher-triggered="triggered" refresher-enabled="true" class="record event-list mt20"
:style="{ height: 'calc(100vh - ' + (navHeight + height) + 'px)', overflow: 'auto' }">
<uni-card class="event-item" :class="item.type" v-for="(item, index) in store.data" :key="index">
<!-- 头部图标 + 信息 + 操作 -->
<view class="event-header">
<view class="event-icon">
<!-- :style="{ backgroundColor: item.isComplete == 1 ? '#10b98120' : '#FF000020' }" -->
<!-- 动态图标根据类型切换 -->
<!-- <uni-icons
custom-prefix="iconfont"
type="icon-baogaoguanli"
size="40"
:color="item.isComplete == 1 ? '#10b981' : '#FF0000'"
></uni-icons> -->
<Cn-icon-transient :name="`报告`" />
</view>
<view class="event-info">
<view class="event-title">
<text class="event-id">{{ item.lineName }}</text>
</view>
<view class="event-desc">
<text>工程名称{{ item.engineeringName }}</text>
<text>项目名称{{ item.projectName }}</text>
<text>设备名称{{ item.deviceName }}</text>
<!-- <text>申请时间{{ item.time }}</text>
<text>事件数{{ item.eventNums }}</text> -->
</view>
</view>
<view class="event-action">
<view class="iconText boxClick" v-if="item.isComplete == 1" @click="download(item)">
<uni-icons type="arrow-down" color="#fff" size="16"></uni-icons>
</view>
<view class="nav-menu nav-menu-btn boxClick"
v-else-if="userInfo.authorities === 'operation_manager'" @click="generate(item)">生成报告
</view>
</view>
</view>
<!-- 详情区域 -->
<view class="event-detail">
<!-- <view class="device-body"> -->
<view class="device-body-item">
<text>申请人</text>
<text>{{ item.applyUser }}</text>
</view>
<view class="device-body-item">
<text>报告状态</text>
<text :style="{ color: item.isComplete == 1 ? '#10b981' : '#FF0000' }">{{
item.isComplete == 1 ? '已完成' : '未完成'
}}</text>
</view>
<view class="device-body-item">
<text>申请时间</text>
<text>{{ item.time }}</text>
</view>
<view class="device-body-item">
<text>暂降事件</text>
<text>{{ item.eventNums }}</text>
</view>
<!-- <view class="device-body-item">
<text>申请时间</text>
<text>{{ item.time }}</text>
</view> -->
</view>
<!-- </view> -->
</uni-card>
<uni-load-more v-if="store.status == 'loading' || (store.data && store.data.length > 0)"
:status="store.status"></uni-load-more>
<Cn-empty v-else style="top: 30%"></Cn-empty>
</scroll-view>
</view>
</view>
</template>
<script>
import Apply from './apply.vue'
import list from '@/common/js/list'
import { createEventReport, downloadEventReport } from '@/common/api/report.js'
export default {
components: { Apply },
props: {
indexList: {
type: Array,
default: () => [],
},
total: {
type: Number,
default: 0,
},
// status: {
// type: String,
// default: 'more',
// },
navHeight: {
type: Number,
default: 0,
},
},
mixins: [list],
data() {
return {
value: ['0'],
content: 123,
curSub: 0,
subsectionList: ['申请报告', '申请记录'],
form: {
type: 0,
lindId: '',
},
triggered: true,
userInfo: {},
height: 0,
selectValue: {},
}
},
created() { },
mounted() {
this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo)
},
computed: {},
methods: {
setHeight() {
uni.createSelectorQuery()
.select('.filterCriteria')
.boundingClientRect((rect) => {
//
// #ifdef H5
this.height = rect?.height + 180 || 0
// #endif
// #ifdef APP-PLUS
this.height = rect?.height + 110 || 0
// #endif
})
.exec()
},
init() {
this.store = this.DataSource('/cs-report-boot/csAppReport/getApplicationReport')
this.store.params.startTime = this.$util.getMonthFirstAndLastDay(this.selectValue.date).firstDay
this.store.params.endTime = this.$util.getMonthFirstAndLastDay(this.selectValue.date).lastDay
this.store.loadedCallback = () => {
this.setHeight()
}
this.store.reload()
},
async select(val) {
this.selectValue = val
await this.init()
},
sectionChange(index) {
this.curSub = index.currentIndex
},
// 生成报告
generate(item) {
uni.showLoading({
title: '生成中,请稍等...',
mask: true,
})
createEventReport({
id: item.eventId,
}).then((res) => {
uni.showToast({
icon: 'success',
mask: true,
title: '生成事件报告成功!',
duration: 1000,
})
this.store.reload()
})
},
// 下载报告
download(item) {
uni.showLoading({
title: '下载中,请稍等...',
mask: true,
})
downloadEventReport({
id: item.eventId,
})
.then((res) => {
// 下载文件资源到本地
uni.downloadFile({
url: res.data, // 后端返回的线上文件路径
success: function (res) {
if (res.statusCode === 200) {
// 文件到本地
uni.saveFile({
tempFilePath: res.tempFilePath, //临时路径
success: function (data) {
var savedFilePath = data.savedFilePath
// 在app端执行
// #ifdef APP-PLUS
let osname = plus.os.name
// 如果是安卓的话弹出提示
uni.showToast({
icon: 'success',
mask: true,
title: '下载成功!',
duration: 1000,
})
// #endif
//ios手机直接打开文件手动存储文件到手机Android手机从根目录创建文件夹保存文件并改名
setTimeout(() => {
//打开文档查看
uni.openDocument({
filePath: data.savedFilePath,
success: function (ress) {
console.log('成功打开文件')
},
fail() {
console.log('打开文件失败')
},
})
}, 500)
},
})
console.log('下载成功')
} else {
uni.showToast({
icon: 'none',
mask: true,
title: '下载失败!',
duration: 1000,
})
}
},
fail: function (res) { },
})
})
.catch((err) => {
uni.showToast({
icon: 'none',
mask: true,
title: err.message,
duration: 1000,
})
})
},
// 刷新
reload() {
switch (this.curSub) {
case 0:
this.$refs.applyRef.store.reload()
break
case 1:
this.store && this.store.reload()
break
}
},
// 下拉
refresherrefresh() {
this.triggered = true
uni.startPullDownRefresh()
setTimeout(() => {
this.triggered = false
}, 500)
},
// 上拉
scrolltolower() {
if (this.store.status != 'noMore') {
this.store.next && this.store.next()
}
},
},
watch: {},
}
</script>
<style lang="scss" scoped>
@import '@/pages/message1/index.scss';
.event-detail {
display: grid;
grid-template-columns: 1.6fr 1fr;
}
// /deep/ .record {
// .uni-card__content {
// padding: 55rpx 20rpx 20rpx !important;
// }
// }
.filterCriteria {
.nav {
background-color: #fff;
}
.choose1 {
background-color: #fff;
padding: 0 20rpx;
display: flex;
justify-content: space-between;
/deep/ .uni-checkbox-input {
width: 30rpx;
height: 30rpx;
}
font-size: 26rpx;
}
}
// .device-body {
// padding: 10rpx 20rpx 20rpx;
.device-body-item {
display: flex;
// justify-content: space-between;
font-size: 28rpx;
color: #666666;
line-height: 1.5;
}
// }
.iconText {
display: flex;
width: 45rpx;
height: 45rpx;
border-radius: 50%;
background-color: $uni-theme-color;
justify-content: center;
align-items: center;
}
.nav-menu {
height: 40rpx;
padding: 6rpx 20rpx;
font-size: 24rpx;
border-radius: 8rpx;
line-height: 40rpx;
background: #ebeaec;
color: #666;
&-active {
background: #dfe5f7;
color: $uni-theme-color;
}
&-btn {
background: $uni-theme-color;
color: #fff;
}
}
.event-list {
/* 图标区域(按类型区分背景色) */
.event-icon {
background-color: #376cf320;
}
}
.segmented-control {
flex: 1;
margin-right: 24rpx;
height: 60rpx;
}
/deep/ .uni-scroll-view-refresher {
display: none;
}
</style>

View File

@@ -16,23 +16,38 @@
</template> </template>
<template slot="right"> <template slot="right">
<text class="hide-txt mr5" style="font-size: 28rpx" <text class="hide-txt mr5" style="font-size: 28rpx"
>{{ select.engineeringName || emptyEngineeringName }} >{{
userInfo.authorities === 'engineering_user'
? '创建工程'
: select.engineeringName || emptyEngineeringName
}}
</text> </text>
<uni-icons type="bottom" size="16" color="#111" v-if="select.engineeringName"></uni-icons> <uni-icons
type="bottom"
size="16"
color="#111"
v-if="select.engineeringName && userInfo.authorities != 'engineering_user'"
></uni-icons>
</template> </template>
</uni-nav-bar> </uni-nav-bar>
<view class="index"> <view class="index">
<!-- 运维 --> <!-- 运维 -->
<YunWei :devCount="devCount" v-if="userInfo.authorities === 'operation_manager'" /> <YunWei :devCount="devCount" v-if="userInfo.authorities === 'operation_manager'" />
<!-- 专职 --> <!-- 营销 -->
<ZhuanZhi :devCount="devCount" v-if="userInfo.authorities === 'market_user'" /> <ZhuanZhi :devCount="devCount" v-if="userInfo.authorities === 'market_user'" />
<!-- 工程 --> <!-- 工程 -->
<GongCheng ref="gongCheng" :devCount="devCount" v-if="userInfo.authorities === 'engineering_user'" /> <GongCheng ref="gongCheng" :devCount="devCount" v-if="userInfo.authorities === 'engineering_user'" />
<!-- 主用户 --> <!-- 正式 -->
<ZhuYongHu :devCount="devCount" v-if="userInfo.authorities === 'app_vip_user'" /> <ZhuYongHu :devCount="devCount" v-if="userInfo.authorities === 'app_vip_user'" />
<!-- 游客 --> <!-- 游客 -->
<YouKe :devCount="devCount" v-if="userInfo.authorities === 'tourist'"></YouKe> <YouKe :devCount="devCount" v-if="userInfo.authorities === 'tourist'"></YouKe>
<template v-show="engineeringList.length"> <!-- 工程列表 -->
<template v-show="engineeringList.length" v-if="userInfo.authorities === 'engineering_user'">
<view class="canneng-index-title mt20">工程列表</view>
<Engineering ref="engineering" :store="store" @refresh="store.search()" />
</template>
<!-- 设备列表 -->
<template v-else v-show="engineeringList.length">
<view class="canneng-index-title mt20">设备列表</view> <view class="canneng-index-title mt20">设备列表</view>
<Device ref="device" :store="store" /> <Device ref="device" :store="store" />
</template> </template>
@@ -47,6 +62,7 @@ import ZhuYongHu from './comp/indexZhuYongHu.vue'
import ZhuanZhi from './comp/indexZhuanZhi.vue' import ZhuanZhi from './comp/indexZhuanZhi.vue'
import YouKe from './comp/indexYouKe.vue' import YouKe from './comp/indexYouKe.vue'
import Device from './comp/device.vue' import Device from './comp/device.vue'
import Engineering from './comp/engineering.vue'
import list from '../../common/js/list' import list from '../../common/js/list'
import { getDevCount } from '../../common/api/device.js' import { getDevCount } from '../../common/api/device.js'
import { queryEngineering } from '@/common/api/engineering.js' import { queryEngineering } from '@/common/api/engineering.js'
@@ -60,6 +76,7 @@ export default {
ZhuanZhi, ZhuanZhi,
YouKe, YouKe,
Device, Device,
Engineering,
}, },
data() { data() {
return { return {
@@ -88,7 +105,11 @@ export default {
}, },
methods: { methods: {
selectEngineering() { selectEngineering() {
if (this.select.engineeringName) { if (this.userInfo.authorities === 'engineering_user') {
uni.navigateTo({
url: '/pages/engineering/new',
})
} else if (this.select.engineeringName) {
uni.navigateTo({ uni.navigateTo({
url: '/pages/home/selectEngineering', url: '/pages/home/selectEngineering',
}) })
@@ -140,6 +161,7 @@ export default {
console.log(this.$refs.device, 'this.$refs.device') console.log(this.$refs.device, 'this.$refs.device')
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.device && this.$refs.device.init() this.$refs.device && this.$refs.device.init()
this.$refs.engineering && this.$refs.engineering.init()
}) })
} }
this.$refs.gongCheng?.init() this.$refs.gongCheng?.init()
@@ -154,10 +176,10 @@ export default {
// console.log(`12312`,res) // console.log(`12312`,res)
// Object.assign(this.devCount, res.data) // Object.assign(this.devCount, res.data)
this.devCount = res.data this.devCount = res.data
this.devCount.currentOffLineDevs.forEach((item) => { this.devCount.currentOffLineDevs?.forEach((item) => {
item.runStatus = 1 item.runStatus = 1
}) })
this.devCount.offLineDevs.forEach((item) => { this.devCount.offLineDevs?.forEach((item) => {
item.runStatus = 1 item.runStatus = 1
}) })
this.devCount.engineeringListLength = this.engineeringList.length this.devCount.engineeringListLength = this.engineeringList.length
@@ -165,17 +187,24 @@ export default {
key: this.$cacheKey.messageCount, key: this.$cacheKey.messageCount,
data: this.devCount, data: this.devCount,
}) })
// let messagePage =
// this.devCount.runCount +
// this.devCount.eventCount +
// this.devCount.alarmCount +
// this.devCount.harmonicCount
let messagePage = let messagePage =
this.devCount.runCount +
this.devCount.eventCount + this.devCount.eventCount +
this.devCount.alarmCount + this.devCount.harmonicCount +
this.devCount.harmonicCount (uni.getStorageSync(this.$cacheKey.userInfo).authorities == 'operation_manager'
? this.devCount.alarmCount + this.devCount.runCount
: 0)
// console.log('🚀 ~ messagePage:', messagePage)
let minePage = this.devCount.feedBackCount let minePage = this.devCount.feedBackCount
if (messagePage) { if (messagePage) {
uni.setTabBarBadge({ uni.setTabBarBadge({
index: 1, index: 1,
text:messagePage ? (messagePage > 99 ? '99+' : messagePage + '') : '', text: messagePage ? (messagePage > 99 ? '99+' : messagePage + '') : '',
}) })
} else { } else {
uni.removeTabBarBadge({ uni.removeTabBarBadge({
@@ -197,8 +226,10 @@ export default {
// #endif // #endif
}) })
}, },
// 动态配置导航栏按钮
}, },
onLoad() { onLoad() {
// 页面加载时,动态配置导航栏按钮
if (!uni.getStorageSync(this.$cacheKey.access_token)) { if (!uni.getStorageSync(this.$cacheKey.access_token)) {
uni.reLaunch({ uni.reLaunch({
url: '/pages/user/login', url: '/pages/user/login',
@@ -216,7 +247,11 @@ export default {
}, 1000) }, 1000)
} }
this.timer = setInterval(this.getDevCount, 1000 * 60) // 定时请求 this.timer = setInterval(this.getDevCount, 1000 * 60) // 定时请求
this.store = this.DataSource('/cs-device-boot/EquipmentDelivery/queryEquipmentByProject')
this.store =
uni.getStorageSync(this.$cacheKey.userInfo).authorities === 'engineering_user'
? this.DataSource('/cs-harmonic-boot/homePage/getEngineeringHomePage')
: this.DataSource('/cs-device-boot/EquipmentDelivery/queryEquipmentByProject')
// #ifdef APP-PLUS // #ifdef APP-PLUS
setTimeout(() => { setTimeout(() => {
// 获取nav高度 // 获取nav高度
@@ -243,6 +278,22 @@ export default {
this.init() this.init()
} }
}, },
mounted() {
uni.setTabBarItem({
index: 2,
visible: true,
})
if (uni.getStorageSync(this.$cacheKey.userInfo).authorities === 'tourist') {
uni.setTabBarItem({
index: 2,
visible: false,
})
uni.showToast({
title: '已同步设备历史数据',
icon: 'none',
})
}
},
} }
</script> </script>
<style lang="scss"> <style lang="scss">
@@ -256,7 +307,6 @@ export default {
.canneng-index-title { .canneng-index-title {
padding: 0 20rpx; padding: 0 20rpx;
font-size: 28rpx;
font-weight: 500; font-weight: 500;
} }

324
pages/index/message1.vue Normal file
View File

@@ -0,0 +1,324 @@
<template>
<Cn-page :loading="loading" class="messageBox" style="padding-top: 10px">
<view slot="body" class="message">
<view class="tabsBox">
<uni-segmented-control
:current="current"
:values="items"
style-type="text"
active-color="#376cf3"
@clickItem="onClickItem"
/>
<!-- 角标 -->
<view class="badge-container">
<span v-for="(item, index) in items" :key="index" class="badge">
<uni-badge :text="badgeCounts[index] > 99 ? '99+' : badgeCounts[index]" />
<!-- {{ badgeCounts[index] > 99 ? '99+' : badgeCounts[index] }} -->
</span>
</view>
<!-- 筛选条件 -->
<Cn-filterCriteria
ref="cnFilterCriteria"
:level="current === 0 ? 3 : current === 1 ? 3 : 2"
@select="select"
>
</Cn-filterCriteria>
</view>
<view class="content">
<Transient
ref="TransientRef"
v-if="current === 0"
:navHeight="navHeight"
:selectValue="selectValue"
@getDevCount="getDevCount"
/>
<SteadyState
ref="SteadyStateRef"
v-if="current === 1"
:navHeight="navHeight"
:selectValue="selectValue"
@getDevCount="getDevCount"
/>
<Alarm
ref="AlarmRef"
v-if="current === 2"
:navHeight="navHeight"
:selectValue="selectValue"
@getDevCount="getDevCount"
/>
<Run
ref="RunRef"
v-if="current === 3"
:navHeight="navHeight"
:selectValue="selectValue"
@getDevCount="getDevCount"
/>
</view>
</view>
</Cn-page>
</template>
<script>
import Transient from '@/pages/message1/transient.vue'
import SteadyState from '@/pages/message1/steadyState.vue'
import Alarm from '@/pages/message1/alarm.vue'
import Run from '@/pages/message1/run.vue'
import { getDevCount } from '../../common/api/device.js'
import { updateStatus } from '@/common/api/message'
export default {
components: { Transient, SteadyState, Alarm, Run },
props: {},
data() {
return {
items: ['暂态事件', '稳态事件'], //'运行告警', '运行事件'
badgeCounts: [0, 0, 0, 0],
current: 0,
colorIndex: 0,
item: '',
loading: false,
width: 0,
navHeight: 0,
selectValue: {},
devCount: [],
// 筛选数据
}
},
onLoad() {},
mounted() {
this.setHeight()
},
onPullDownRefresh() {
this.refresh()
},
onNavigationBarButtonTap(e) {
uni.showModal({
title: '提示',
content: '确定要全部标记为已读吗?',
success: (res) => {
if (res.confirm) {
updateStatus({
// '暂态事件', 0
// '稳态事件', 1
// '运行告警', 3
// '运行事件' 2
type: this.current == 2 ? 3 : this.current == 3 ? 2 : this.current,
eventIds: [],
}).then(() => {
this.refresh()
this.getDevCount()
})
}
},
})
},
onShow() {
if (uni.getStorageSync(this.$cacheKey.userInfo).authorities === 'operation_manager') {
this.items = ['暂态事件', '稳态事件', '运行告警', '运行事件']
}
const params = uni.getStorageSync('messageParams')
this.getDevCount()
this.$nextTick(() => {
if (params.type !== '') {
this.current = params.type - 0
}
if (params.engineeringName != '') {
this.$refs.cnFilterCriteria && this.$refs.cnFilterCriteria.external(params)
}
// this.refresh()
this.$refs.TransientRef && this.$refs.TransientRef.getConfig()
})
},
// 页面销毁
onHide() {
uni.setStorageSync('messageParams', {
engineeringName: '',
engineeringId: '', //工程ID
projectName: '',
projectId: '', //項目ID
deviceName: '',
deviceId: '', //设备ID
lineName: '',
lineId: '', //测点ID
type: '',
})
},
methods: {
setHeight() {
uni.createSelectorQuery()
.select('.tabsBox')
.boundingClientRect((rect) => {
this.width = rect.width
//
// #ifdef H5
this.navHeight = rect.height + 75
// #endif
// #ifdef APP-PLUS
this.navHeight = rect.height + 20
// #endif
})
.exec()
},
refresh() {
switch (this.current) {
case 0:
this.$refs.TransientRef.store.reload()
break
case 1:
this.$refs.SteadyStateRef.store.reload()
break
case 2:
this.$refs.AlarmRef.store.reload()
break
case 3:
this.$refs.RunRef.store.reload()
break
}
},
onClickItem(e) {
if (this.current !== e.currentIndex) {
this.current = e.currentIndex
}
},
select(value) {
this.selectValue = value
setTimeout(() => {
this.setHeight()
}, 100)
},
// 设置角标
getDevCount() {
if (uni.getStorageSync('projectList')[1] != undefined) {
getDevCount(uni.getStorageSync('projectList')[1].engineeringId).then((res) => {
this.devCount = res.data
this.badgeCounts = [
this.devCount.eventCount,
this.devCount.harmonicCount,
this.devCount.alarmCount,
this.devCount.runCount,
]
uni.setStorage({
key: this.$cacheKey.messageCount,
data: this.devCount,
})
let messagePage =
this.devCount.eventCount +
this.devCount.harmonicCount +
(uni.getStorageSync(this.$cacheKey.userInfo).authorities == 'operation_manager'
? this.devCount.alarmCount + this.devCount.runCount
: 0)
let minePage = this.devCount.feedBackCount
if (messagePage) {
uni.setTabBarBadge({
index: 1,
text: messagePage ? (messagePage > 99 ? '99+' : messagePage + '') : '',
})
} else {
uni.removeTabBarBadge({
index: 1,
})
}
if (minePage) {
uni.setTabBarBadge({
index: 2,
text: minePage + '',
})
} else {
uni.removeTabBarBadge({
index: 2,
})
}
// #ifdef APP-PLUS
plus.runtime.setBadgeNumber(messagePage + minePage)
// #endif
})
}
},
// 根据索引动态计算右侧偏移位置,使徽章对准每个标签的右上角
getBadgeRightPosition(index) {
if (this.items == 4) {
return (index + 1) * (this.width / 4) + 'px'
} else {
return (index + 0) * (this.width / 2) + 'px'
}
},
},
computed: {},
}
</script>
<style lang="scss">
.messageBox {
overflow: hidden;
/deep/.tabsBox {
position: relative;
background-color: #fff;
.segmented-control {
// height: 40px;
background-color: #fff;
border-bottom: 1px solid #cccccc70;
.segmented-control__item {
align-items: baseline;
margin-top: 5px;
}
}
.segmented-control__text {
font-size: 30rpx !important;
color: rgb(96, 98, 102);
}
.segmented-control__item--text {
font-weight: bold;
padding: 0 0 5rpx;
}
.choose {
// padding: 20rpx;
// display: flex;
// justify-content: space-between;
// align-items: center;
background: #fff;
}
}
.subsection {
width: 90%;
margin: 20rpx auto;
}
.badge-container {
position: absolute;
top: -10rpx; /* 徽章向上偏移,与控件重叠 */
display: flex;
justify-content: space-around;
right: 0;
width: 100%;
height: 0;
pointer-events: none; /* 确保徽章不干扰点击事件 */
}
/deep/ .uni-badge--error {
background-color: #ff3b30;
}
.badge {
flex: 1;
// position: absolute;
// min-width: 18px;
// height: 16px;
// padding: 0 4px;
// background-color: #ff3b30; /* 红色徽章 */
// color: white;
// font-size: 22rpx;
// line-height: 16px;
// text-align: center;
// border-radius: 9px;
//
text-align: center;
// transform: translateX(-110%); /* 使徽章中心对齐右上角 */
.uni-badge--x {
left: 70rpx;
}
}
}
</style>

View File

@@ -1,382 +1,381 @@
<template> <template>
<view :loading="loading"> <view :loading="loading">
<view class="mine"> <view class="mine">
<view class="mine-header" @click="jump('basic')"> <view class="mine-header" @click="jump('basic')">
<image mode="aspectFill" class="mine-header-head" :src="userInfo.avatar" v-if="userInfo.avatar" /> <image mode="aspectFill" class="mine-header-head" :src="userInfo.avatar" v-if="userInfo.avatar" />
<image mode="aspectFill" class="mine-header-head" src="/static/head.png" v-else /> <image mode="aspectFill" class="mine-header-head" src="/static/head.png" v-else />
<view class="mine-header-name hide-txt"> <view class="mine-header-name hide-txt">
<view>{{ userInfo.nickname }}</view> <view>{{ userInfo.nickname }}</view>
<view></view> <view></view>
<view class="tag">{{ roleName }}</view> <view class="tag">{{ roleName }}</view>
</view> </view>
<image <image
src="/static/erweima.png" src="/static/erweima.png"
style="height: 50rpx; width: 50rpx; border-radius: 12rpx" style="height: 50rpx; width: 50rpx; border-radius: 12rpx"
mode="scaleToFill" mode="scaleToFill"
/> />
<uni-icons type="forward" color="#aaa" size="16"></uni-icons> <uni-icons type="forward" color="#aaa" size="16"></uni-icons>
</view> </view>
<view class="mine-nav" v-if="userInfo.authorities === 'tourist'" @click="jump('upgrade')"> <view class="mine-nav" v-if="userInfo.authorities === 'tourist'" @click="jump('upgrade')">
<image mode="aspectFill" class="mine-nav-icon" src="/static/server.png" /> <image mode="aspectFill" class="mine-nav-icon" src="/static/server.png" />
<view class="mine-nav-label">角色升级</view> <view class="mine-nav-label">角色升级</view>
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
</view> </view>
<!-- <view class="mine-nav" @click="jump('audit')" v-if="userInfo.authorities === 'app_vip_user'"> <!-- <view class="mine-nav" @click="jump('audit')" v-if="userInfo.authorities === 'app_vip_user'">
<image mode="aspectFill" class="mine-nav-icon" src="/static/server.png" /> <image mode="aspectFill" class="mine-nav-icon" src="/static/server.png" />
<view class="mine-nav-label">角色审核</view> <view class="mine-nav-label">角色审核</view>
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
</view> --> </view> -->
<!-- <view class="mine-nav" @click="jump('user')" v-if="userInfo.authorities === 'app_vip_user'"> <!-- <view class="mine-nav" @click="jump('user')" v-if="userInfo.authorities === 'app_vip_user'">
<image mode="aspectFill" class="mine-nav-icon" src="/static/subordinate.png" /> <image mode="aspectFill" class="mine-nav-icon" src="/static/subordinate.png" />
<view class="mine-nav-label">分享用户列表</view> <view class="mine-nav-label">分享用户列表</view>
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
</view> --> </view> -->
<view <view
class="mine-nav" class="mine-nav"
@click="jump('scan')" @click="jump('scan')"
v-if="userInfo.authorities === 'app_vip_user' || userInfo.authorities === 'engineering_user'" v-if="userInfo.authorities === 'app_vip_user' || userInfo.authorities === 'engineering_user'"
> >
<image mode="aspectFill" class="mine-nav-icon" src="/static/scan.png" /> <image mode="aspectFill" class="mine-nav-icon" src="/static/scan.png" />
<view class="mine-nav-label">扫一扫</view> <view class="mine-nav-label">扫一扫</view>
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
</view> </view>
<view class="mine-nav" @click="jump('engineering')"> <view class="mine-nav" @click="jump('engineering')" v-if="userInfo.authorities !== 'tourist'">
<image mode="aspectFill" class="mine-nav-icon" src="/static/gongcheng.png" /> <image mode="aspectFill" class="mine-nav-icon" src="/static/gongcheng.png" />
<view class="mine-nav-label">工程管理</view> <view class="mine-nav-label">工程管理</view>
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
</view> </view>
<view class="mine-nav" @click="jump('project')"> <view class="mine-nav" @click="jump('project')" v-if="userInfo.authorities !== 'tourist'">
<image mode="aspectFill" class="mine-nav-icon" src="/static/project.png" /> <image mode="aspectFill" class="mine-nav-icon" src="/static/project.png" />
<view class="mine-nav-label">项目管理</view> <view class="mine-nav-label">项目管理</view>
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
</view> </view>
<view class="mine-nav" @click="jump('feedback')"> <view class="mine-nav" @click="jump('feedback')" v-if="userInfo.authorities !== 'tourist'">
<image mode="aspectFill" class="mine-nav-icon" src="/static/feedback.png" /> <image mode="aspectFill" class="mine-nav-icon" src="/static/feedback.png" />
<view class="mine-nav-label">反馈列表</view> <view class="mine-nav-label">反馈列表</view>
<uni-badge :text="messageCount.feedBackCount"></uni-badge> <uni-badge :text="messageCount.feedBackCount"></uni-badge>
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
</view> </view>
<!-- <view <!-- <view
class="mine-nav" class="mine-nav"
@click="jump('gateway')" @click="jump('gateway')"
style="border-bottom: none; box-shadow: 0 4rpx 8rpx #e7e7e74c" style="border-bottom: none; box-shadow: 0 4rpx 8rpx #e7e7e74c"
> >
<image mode="aspectFill" class="mine-nav-icon" src="/static/gateway.png" /> <image mode="aspectFill" class="mine-nav-icon" src="/static/gateway.png" />
<view class="mine-nav-label">网关列表</view> <view class="mine-nav-label">网关列表</view>
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
</view> --> </view> -->
<view class="mine-nav" @click="jump('setupMessage')"> <view class="mine-nav" @click="jump('setupMessage')" v-if="userInfo.authorities !== 'tourist'">
<image mode="aspectFill" class="mine-nav-icon" src="/static/message4.png" /> <image mode="aspectFill" class="mine-nav-icon" src="/static/message4.png" />
<view class="mine-nav-label">推送通知</view> <view class="mine-nav-label">推送通知</view>
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
</view> </view>
<view <view
class="mine-nav" class="mine-nav"
@click="jump('engineering/setting')" @click="jump('engineering/setting')"
v-if="userInfo.authorities === 'engineering_user'" v-if="userInfo.authorities === 'engineering_user' || userInfo.authorities !== 'tourist'"
> >
<image mode="aspectFill" class="mine-nav-icon" src="/static/like.png" /> <image mode="aspectFill" class="mine-nav-icon" src="/static/like.png" />
<view class="mine-nav-label">关注工程配置</view> <view class="mine-nav-label">关注工程配置</view>
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
</view> </view>
<view class="mine-nav" @click="jump('serverSetting')" v-if="userInfo.authorities === 'engineering_user'"> <view class="mine-nav" @click="jump('transientSetting')" v-if="userInfo.authorities !== 'tourist'">
<image mode="aspectFill" class="mine-nav-icon" src="/static/server2.png" /> <!-- 调试内容配置 serverSetting-->
<view class="mine-nav-label">调试内容配置</view> <image mode="aspectFill" class="mine-nav-icon" src="/static/tongji.png" />
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <view class="mine-nav-label">暂态统计配置</view>
</view> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
<view class="mine-nav" @click="jump('setup')" style="border-bottom: none"> </view>
<image mode="aspectFill" class="mine-nav-icon" src="/static/setup.png" /> <view class="mine-nav" @click="jump('setup')" style="border-bottom: none">
<view class="mine-nav-label">设置</view> <image mode="aspectFill" class="mine-nav-icon" src="/static/setup.png" />
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <view class="mine-nav-label">设置</view>
</view> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
<uni-popup ref="inputDialog" type="dialog"> </view>
<uni-popup-dialog <uni-popup ref="inputDialog" type="dialog">
ref="inputClose" <uni-popup-dialog
mode="input" ref="inputClose"
title="角色升级" mode="input"
placeholder="请输入六位邀请码" title="角色升级"
@confirm="upgrade" placeholder="请输入六位邀请码"
></uni-popup-dialog> @confirm="upgrade"
</uni-popup> ></uni-popup-dialog>
</view> </uni-popup>
</view>
<uni-popup ref="alertDialog" type="dialog">
<uni-popup-dialog <uni-popup ref="alertDialog" type="dialog">
style="width: 90%; margin: 5%" <uni-popup-dialog
type="info" style="width: 90%; margin: 5%"
cancelText="禁止" type="info"
confirmText="允许" cancelText="禁止"
title="权限说明" confirmText="允许"
content='是否允许"灿能物联"使用相机?' title="权限说明"
@confirm="handleScon('camera')" content='是否允许"灿能物联"使用相机?'
@close="dialogClose" @confirm="handleScon('camera')"
></uni-popup-dialog> @close="dialogClose"
</uni-popup> ></uni-popup-dialog>
<uni-popup ref="message" type="message"> </uni-popup>
<uni-popup-message type="info" :duration="0" style="width: 90%; margin: 5%"> <uni-popup ref="message" type="message">
<view style="color: #909399; font-style: 16px">相机权限使用说明:</view> <uni-popup-message type="info" :duration="0" style="width: 90%; margin: 5%">
<view style="color: #6c6c6c; margin-top: 3rpx; "> 用于相机扫描二维码!</view> <view style="color: #909399; font-style: 16px">相机权限使用说明:</view>
</uni-popup-message> <view style="color: #6c6c6c; margin-top: 3rpx"> 用于相机扫描二维码!</view>
</uni-popup> </uni-popup-message>
<yk-authpup ref="authpup" type="top" @changeAuth="changeAuth" permissionID="CAMERA"></yk-authpup> </uni-popup>
<yk-authpup ref="authpup" type="top" @changeAuth="changeAuth" permissionID="CAMERA"></yk-authpup>
</view> </view>
</template> </template>
<script> <script>
import { roleUpdate, autoLogin } from '@/common/api/user' import { roleUpdate, autoLogin } from '@/common/api/user'
import { transferDevice, shareDevice } from '@/common/api/device' import { transferDevice, shareDevice } from '@/common/api/device'
import ykAuthpup from "@/components/yk-authpup/yk-authpup"; import ykAuthpup from '@/components/yk-authpup/yk-authpup'
export default { export default {
components: { components: {
ykAuthpup ykAuthpup,
}, },
data() { data() {
return { return {
loading: true, loading: true,
userInfo: {}, userInfo: {},
messageCount: {}, messageCount: {},
timer: null, timer: null,
} }
}, },
computed: { computed: {
roleName() { roleName() {
let roleName = '' let roleName = ''
switch (this.userInfo.authorities) { switch (this.userInfo.authorities) {
case 'tourist': case 'tourist':
roleName = '游客' roleName = '游客'
break break
case 'engineering_user': case 'engineering_user':
roleName = '工程用户' roleName = '工程用户'
break break
case 'app_vip_user': case 'app_vip_user':
roleName = '正式用户' roleName = '正式用户'
break break
case 'market_user': case 'market_user':
roleName = '营销用户' roleName = '营销用户'
break break
case 'operation_manager': case 'operation_manager':
roleName = '运维管理员' roleName = '运维管理员'
break break
} }
return roleName return roleName
}, },
}, },
onLoad(options) { onLoad(options) {
this.init() this.init()
}, },
methods: { methods: {
init() {}, init() {},
upgrade(code) { upgrade(code) {
console.log(code) console.log(code)
roleUpdate({ roleUpdate({
referralCode: code, referralCode: code,
userId: this.userInfo.userIndex, userId: this.userInfo.userIndex,
}).then((res) => { }).then((res) => {
uni.showToast({ uni.showToast({
title: '升级成功', title: '升级成功',
icon: 'none', icon: 'none',
}) })
uni.removeStorageSync('access_token') uni.removeStorageSync('access_token')
// 直接登录 // 直接登录
autoLogin(this.userInfo.user_name).then((res) => { autoLogin(this.userInfo.user_name).then((res) => {
this.$util.loginSuccess(res.data).then((userInfo) => { this.$util.loginSuccess(res.data).then((userInfo) => {
this.userInfo = userInfo this.userInfo = userInfo
}) })
}) })
}) })
}, },
changeAuth(){ changeAuth() {
//这里是权限通过后执行自己的代码逻辑 //这里是权限通过后执行自己的代码逻辑
console.log('权限已授权,可执行自己的代码逻辑了'); console.log('权限已授权,可执行自己的代码逻辑了')
// this.handleScon() // this.handleScon()
this.handleScon() this.handleScon()
}, },
jump(type) { jump(type) {
switch (type) { switch (type) {
case 'scan': case 'scan':
if ( if (
plus.os.name == 'Android' plus.os.name == 'Android'
// && plus.navigator.checkPermission('android.permission.CAMERA') === 'undetermined' // && plus.navigator.checkPermission('android.permission.CAMERA') === 'undetermined'
) { ) {
//未授权 //未授权
// this.$refs.alertDialog.open('bottom') // this.$refs.alertDialog.open('bottom')
this.$refs['authpup'].open() this.$refs['authpup'].open()
// this.$refs.message.open() // this.$refs.message.open()
} else {
} else { console.log(2)
console.log(2) this.handleScon()
this.handleScon() }
}
break
case 'login':
break uni.navigateTo({
case 'login': url: `/pages/user/login`,
uni.navigateTo({ })
url: `/pages/user/login`, break
}) case 'gateway':
break uni.navigateTo({
case 'gateway': url: `/pages/gateway/list`,
uni.navigateTo({ })
url: `/pages/gateway/list`, break
}) case 'upgrade':
break this.$refs.inputDialog.open()
case 'upgrade': break
this.$refs.inputDialog.open() case 'basic':
break uni.navigateTo({
case 'basic': url: `/pages/user/basic`,
uni.navigateTo({ })
url: `/pages/user/basic`, break
}) case 'project':
break uni.navigateTo({
case 'project': url: `/pages/project/list`,
uni.navigateTo({ })
url: `/pages/project/list`, break
}) case 'engineering':
break uni.navigateTo({
case 'engineering': url: `/pages/engineering/list`,
uni.navigateTo({ })
url: `/pages/engineering/list`, break
}) case 'engineering/setting':
break uni.navigateTo({
case 'engineering/setting': url: `/pages/engineering/setting`,
uni.navigateTo({ })
url: `/pages/engineering/setting`, break
}) case 'feedback':
break uni.navigateTo({
case 'feedback': url: `/pages/message/feedback`,
uni.navigateTo({ })
url: `/pages/message/feedback`, break
}) default:
break uni.navigateTo({
default: url: `/pages/mine/${type}`,
uni.navigateTo({ })
url: `/pages/mine/${type}`, break
}) }
break },
} handleScon() {
}, this.$refs.message.close()
handleScon(){ uni.scanCode({
this.$refs.message.close() onlyFromCamera: true,
uni.scanCode({ success: (res) => {
onlyFromCamera:true, console.log('条码类型:' + res.scanType)
success: (res) => { console.log('条码内容:' + res.result)
console.log('条码类型:' + res.scanType) let content = JSON.parse(res.result)
console.log('条码内容:' + res.result) switch (content.type) {
let content = JSON.parse(res.result) case 'transferDevice':
switch (content.type) { this.transferDevice(content.id.split(','))
case 'transferDevice': break
this.transferDevice(content.id.split(',')) case 'shareDevice':
break this.shareDevice(content.id.split(','))
case 'shareDevice': break
this.shareDevice(content.id.split(',')) default:
break this.$util.toast('无效二维码')
default: break
this.$util.toast('无效二维码') }
break },
} })
}, },
}) dialogClose() {
}, this.$refs.message.close()
dialogClose(){this.$refs.message.close()}, },
transferDevice(id) { transferDevice(id) {
transferDevice(id).then((res) => { transferDevice(id).then((res) => {
uni.navigateTo({ url: '/pages/mine/result?type=transferDevice&id=' + id }) uni.navigateTo({ url: '/pages/mine/result?type=transferDevice&id=' + id })
}) })
}, },
shareDevice(id) { shareDevice(id) {
shareDevice(id).then((res) => { shareDevice(id).then((res) => {
uni.navigateTo({ url: '/pages/mine/result?type=shareDevice&id=' + id }) uni.navigateTo({ url: '/pages/mine/result?type=shareDevice&id=' + id })
}) })
}, },
}, },
onShow() { onShow() {
this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo) this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo)
this.loading = false this.loading = false
this.messageCount = uni.getStorageSync(this.$cacheKey.messageCount) || {} this.messageCount = uni.getStorageSync(this.$cacheKey.messageCount) || {}
this.timer = setInterval(() => { this.timer = setInterval(() => {
this.messageCount = uni.getStorageSync(this.$cacheKey.messageCount) || {} this.messageCount = uni.getStorageSync(this.$cacheKey.messageCount) || {}
}, 1000) // 定时请求 }, 1000) // 定时请求
}, },
onHide() { onHide() {
clearInterval(this.timer) clearInterval(this.timer)
}, },
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.mine { .mine {
.mine-header { .mine-header {
padding: 200rpx 34rpx 34rpx; padding: 200rpx 34rpx 34rpx;
display: flex; display: flex;
align-items: center; align-items: center;
background: $uni-theme-white; background: $uni-theme-white;
margin-bottom: 20rpx; margin-bottom: 20rpx;
box-shadow: 0 4rpx 8rpx #e7e7e74c; box-shadow: 0 4rpx 8rpx #e7e7e74c;
.mine-header-head { .mine-header-head {
margin-right: 30rpx; margin-right: 30rpx;
height: 128rpx; height: 128rpx;
width: 128rpx; width: 128rpx;
border-radius: $uni-theme-radius; border-radius: $uni-theme-radius;
overflow: hidden; overflow: hidden;
} }
.mine-header-name { .mine-header-name {
margin-right: 30rpx; margin-right: 30rpx;
flex: 1; flex: 1;
font-size: 36rpx; font-size: 36rpx;
color: #111; color: #111;
font-weight: 700; font-weight: 700;
.tag { .tag {
display: flex; display: flex;
align-items: center; align-items: center;
margin-top: 10rpx; margin-top: 10rpx;
font-size: 24rpx; font-size: 24rpx;
color: #aaa; color: #aaa;
.engineering-button { .engineering-button {
margin-left: 10rpx; margin-left: 10rpx;
font-size: 24rpx; font-size: 24rpx;
padding: 5rpx 12rpx; padding: 5rpx 12rpx;
color: #fff; color: #fff;
font-weight: 400; font-weight: 400;
border-radius: 16rpx; border-radius: 16rpx;
background: $uni-theme-color; background: $uni-theme-color;
} }
} }
} }
} }
.mine-nav { .mine-nav {
padding: 34rpx; padding: 34rpx;
display: flex; display: flex;
align-items: center; align-items: center;
background: $uni-theme-white; background: $uni-theme-white;
border-bottom: 1rpx solid #e8e8e8; border-bottom: 1rpx solid #e8e8e8;
&-icon { &-icon {
margin-right: 30rpx; margin-right: 30rpx;
height: 44rpx; height: 44rpx;
width: 44rpx; width: 44rpx;
border-radius: $uni-theme-radius; border-radius: $uni-theme-radius;
overflow: hidden; overflow: hidden;
} }
&-label { &-label {
margin-right: 30rpx; margin-right: 30rpx;
flex: 1; flex: 1;
font-size: 28rpx; font-size: 28rpx;
color: #111; color: #111;
} }
} }
} }
/deep/ .uni-popup-message__box { /deep/ .uni-popup-message__box {
border-radius: 10rpx !important; border-radius: 10rpx !important;
background-color: #fff; background-color: #fff;
} }
</style> </style>
</style>

154
pages/index/report.vue Normal file
View File

@@ -0,0 +1,154 @@
<template>
<view :loading="loading" class="report" style="padding-top: 10px">
<view class="navReport">
<view class="tabsBox">
<uni-segmented-control
:current="curTabs"
:values="items"
style-type="text"
active-color="#376cf3"
@clickItem="onClickItem"
/>
</view>
</view>
<!-- 稳态报表 -->
<SteadyState
v-if="curTabs == 0"
ref="SteadyStateRef"
:indexList="indexList"
:total="total"
:status="status"
:navHeight="navHeight"
@scrolltolower="scrolltolower"
/>
<!-- 暂态报表 -->
<Transient
v-if="curTabs == 1"
ref="TransientRef"
:indexList="indexList"
:total="total"
:status="status"
:navHeight="navHeight"
@scrolltolower="scrolltolower"
/>
</view>
</template>
<script>
import SteadyState from './comp/steadyState.vue'
import Transient from './comp/transient.vue'
export default {
components: {
SteadyState,
Transient,
},
props: {},
data() {
return {
curTabs: 0,
total: 6,
loading: false,
items: ['稳态报表', '暂降报告'],
status: 'more', //more加载前 loading加载中 noMore加载后
navHeight: 0,
indexList: [],
}
},
created() {},
onPullDownRefresh() {
this.refresh()
},
mounted() {
uni.createSelectorQuery()
.select('.navReport')
.boundingClientRect((rect) => {
//
this.navHeight = rect.height
// // #ifdef H5
// // #endif
// // #ifdef APP-PLUS
// this.navHeight = rect.height
// // #endif
})
.exec()
},
methods: {
onClickItem(e) {
if (this.curTabs !== e.currentIndex) {
this.curTabs = e.currentIndex
}
},
scrolltolower() {
if (this.total != this.indexList.length) {
this.status = 'loading'
this.info()
} else {
this.status = 'noMore'
}
},
info() {
setTimeout(() => {
this.status = 'more'
}, 1000)
},
refresh() {
switch (this.curTabs) {
case 0:
this.$refs.SteadyStateRef.store.reload()
break
case 1:
this.$refs.TransientRef.reload()
break
}
},
},
computed: {},
watch: {},
}
</script>
<style lang="scss">
.report {
overflow: hidden;
/deep/ .u-tabs__wrapper__nav {
background: #fff;
}
/deep/ .u-tabs__wrapper__nav__item {
flex: 1;
}
/deep/ .u-tabs__wrapper__nav__line {
left: 80rpx;
}
/deep/ .u-u-subsection {
width: 80% !important;
}
/deep/.tabsBox {
.segmented-control {
// height: 40px;
background-color: #fff;
border-bottom: 1px solid #cccccc70;
.segmented-control__item {
align-items: baseline;
margin-top: 5px;
}
}
.segmented-control__text {
font-size: 30rpx !important;
color: rgb(96, 98, 102);
}
.segmented-control__item--text {
font-weight: bold;
padding: 0 0 5rpx;
}
}
}
</style>

View File

@@ -1,147 +1,147 @@
<template> <template>
<Cn-page :loading='loading'> <Cn-page :loading='loading'>
<view slot='body'> <view slot='body'>
<view class='detail'> <view class='detail'>
<view class="detail-content "> <view class="detail-content ">
<view class="detail-content-title mb20">{{ pageData.title }}</view> <view class="detail-content-title mb20">{{ pageData.title }}</view>
<view> {{ pageData.createTime }}</view> <view> {{ pageData.createTime }}</view>
<view class="mt10 mb10">{{ pageData.description }}</view> <view class="mt10 mb10">{{ pageData.description }}</view>
<uni-file-picker readonly v-model="imageValue" mode="grid"/> <uni-file-picker readonly v-model="imageValue" mode="grid"/>
</view> </view>
<view class="detail-content " style="margin-bottom:0"> <view class="detail-content " style="margin-bottom:0">
<view class="detail-content-title "> <view class="detail-content-title ">
<view class="title">进度</view> <view class="title">进度</view>
<!-- <template v-if="pageData.status === '1'">--> <!-- <template v-if="pageData.status === '1'">-->
<!-- <view class="title-btn mr10" @click="updateFeedBackStatus('2')">解决</view>--> <!-- <view class="title-btn mr10" @click="updateFeedBackStatus('2')">解决</view>-->
<!-- <view class="title-btn mr10" @click="updateFeedBackStatus('0')">关闭</view>--> <!-- <view class="title-btn mr10" @click="updateFeedBackStatus('0')">关闭</view>-->
<!-- </template>--> <!-- </template>-->
<!-- <template v-if="pageData.status === '2'">--> <!-- <template v-if="pageData.status === '2'">-->
<!-- <view class="title-btn mr10" @click="updateFeedBackStatus('0')">关闭</view>--> <!-- <view class="title-btn mr10" @click="updateFeedBackStatus('0')">关闭</view>-->
<!-- </template>--> <!-- </template>-->
<!-- <view class="title-btn" @click="open">回复</view>--> <!-- <view class="title-btn" @click="open">回复</view>-->
</view> </view>
</view> </view>
<uni-list> <uni-list>
<uni-list-item :title="item.userName" :note="item.chatContent" :rightText="item.createTime" <uni-list-item :title="item.userName" :note="item.chatContent" :rightText="item.createTime"
v-for="(item, index) in pageData.csFeedbackChatPOList" :key="index"/> v-for="(item, index) in pageData.csFeedbackChatPOList" :key="index"/>
<Cn-empty <Cn-empty
v-if="pageData.csFeedbackChatPOList && pageData.csFeedbackChatPOList.length == 0"></Cn-empty> v-if="pageData.csFeedbackChatPOList && pageData.csFeedbackChatPOList.length == 0"></Cn-empty>
</uni-list> </uni-list>
<!-- 输入框示例 --> <!-- 输入框示例 -->
<uni-popup ref="inputDialog" type="dialog"> <uni-popup ref="inputDialog" type="dialog">
<uni-popup-dialog ref="inputClose" type="info" mode="input" title="输入内容" <uni-popup-dialog ref="inputClose" type="info" mode="input" title="输入内容"
value="对话框预置提示内容!" value="对话框预置提示内容!"
placeholder="请输入内容" @confirm="dialogInputConfirm"> placeholder="请输入内容" @confirm="dialogInputConfirm">
<uni-easyinput type="textarea" :maxlength="250" autoHeight v-model="chatContent" <uni-easyinput type="textarea" :maxlength="250" autoHeight v-model="chatContent"
placeholder="请输入内容"></uni-easyinput> placeholder="请输入内容"></uni-easyinput>
</uni-popup-dialog> </uni-popup-dialog>
</uni-popup> </uni-popup>
</view> </view>
</view> </view>
</Cn-page> </Cn-page>
</template> </template>
<script> <script>
import {queryFeedBackDetail, AddFeedbackChat, updateChatStatus, updateFeedBackStatus} from '../../common/api/feedback' import {queryFeedBackDetail, AddFeedbackChat, updateChatStatus, updateFeedBackStatus} from '../../common/api/feedback'
export default { export default {
data() { data() {
return { return {
loading: false, loading: false,
chatContent: "", chatContent: "",
imageValue: [ imageValue: [
{ {
"name": "file.png", "name": "file.png",
"extname": "png", "extname": "png",
"url": "/static/logo.png", "url": "/static/logo.png",
} }
], ],
pageData: {}, pageData: {},
pageOption: {} pageOption: {}
} }
}, },
onLoad(o) { onLoad(o) {
this.pageOption = o this.pageOption = o
this.init() this.init()
updateChatStatus({ updateChatStatus({
id: o.id, id: o.id,
}) })
}, },
methods: { methods: {
updateFeedBackStatus(status) { updateFeedBackStatus(status) {
updateFeedBackStatus({ updateFeedBackStatus({
id: this.pageOption.id, id: this.pageOption.id,
status: status status: status
}).then(res => { }).then(res => {
this.init() this.init()
}) })
}, },
init() { init() {
this.loading = true this.loading = true
queryFeedBackDetail(this.pageOption.id).then(res => { queryFeedBackDetail(this.pageOption.id).then(res => {
// 反转数组 // 反转数组
res.data.csFeedbackChatPOList.reverse() res.data.csFeedbackChatPOList.reverse()
this.pageData = res.data this.pageData = res.data
this.imageValue = res.data.imageUrls.map(item => { this.imageValue = res.data.imageUrls.map(item => {
return { return {
"name": item, "name": item,
"extname": item.split('.')[1], "extname": item.split('.')[1],
"url": this.$config.static + item, "url": this.$config.static + item,
} }
}) })
this.loading = false this.loading = false
console.log(res); console.log(res);
}) })
}, },
dialogInputConfirm() { dialogInputConfirm() {
AddFeedbackChat({chatContent: this.chatContent, id: this.pageOption.id}).then(res => { AddFeedbackChat({chatContent: this.chatContent, id: this.pageOption.id}).then(res => {
console.log(res); console.log(res);
this.$util.toast('回复成功') this.$util.toast('回复成功')
this.init() this.init()
this.chatContent = '' this.chatContent = ''
}) })
}, },
open() { open() {
this.$refs.inputDialog.open() this.$refs.inputDialog.open()
}, },
over() { over() {
}, },
close() { close() {
}, },
} }
} }
</script> </script>
<style lang='scss'> <style lang='scss'>
.detail { .detail {
padding: 0 0 20rpx; padding: 0 0 20rpx;
.detail-content { .detail-content {
padding: 20rpx 30rpx; padding: 20rpx 30rpx;
background: #fff; background: #fff;
margin-bottom: 20rpx; margin-bottom: 20rpx;
font-size: 26rpx; font-size: 26rpx;
.detail-content-title { .detail-content-title {
font-size: 32rpx; font-size: 28rpx;
color: #111; color: #111;
font-weight: 700; font-weight: 700;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
.title { .title {
flex: 1; flex: 1;
} }
.title-btn { .title-btn {
padding: 0 20rpx; padding: 0 20rpx;
height: 50rpx; height: 50rpx;
background-color: #007aff; background-color: #007aff;
font-size: 24rpx; font-size: 24rpx;
color: #fff; color: #fff;
text-align: center; text-align: center;
line-height: 50rpx; line-height: 50rpx;
border-radius: 10rpx; border-radius: 10rpx;
} }
} }
} }
} }
</style> </style>

View File

@@ -1,237 +1,251 @@
<template> <template>
<Cn-page :loading="loading"> <Cn-page :loading="loading">
<view class="content" slot="body"> <view class="content" slot="body">
<view class="content-item" v-for="(item, index) in store.data" :key="index" @click="jump(item)"> <view class="content-item" v-for="(item, index) in store.data" :key="index" @click="jump(item)">
<view class="content-item-header"> <view class="content-item-header">
<uni-badge class="uni-badge-left-margin" :is-dot="true" :text="item.status == '1' ? 0 : 1" <uni-badge
absolute="rightTop" size="small" :style="type == '0' ? `margin-top: 30rpx;` : ''"> class="uni-badge-left-margin"
<view class="content-item-header-icon"> :is-dot="true"
<image mode="aspectFill" :src="staticIcon" style="height: 60rpx; width: 60rpx"></image> :text="item.status == '1' ? 0 : 1"
</view> absolute="rightTop"
</uni-badge> size="small"
<view class="content-item-header-right"> :style="type == '0' ? `margin-top: 30rpx;` : ''"
<view class="content-item-header-right-title">{{ item.equipmentName }}</view> >
<!-- <view class="content-item-header-right-des">{{ item.engineeringName }} {{ item.projectName }}</view> --> <view class="content-item-header-icon">
<view class="content-item-header-right-des">工程名称{{ item.engineeringName }}</view> <image mode="aspectFill" :src="staticIcon" style="height: 60rpx; width: 60rpx"></image>
<view class="content-item-header-right-des">项目名称{{ item.projectName }}</view> </view>
<view class="content-item-header-right-des" v-if="type == '0' || type == '1'">监测点名称{{ </uni-badge>
item.lineName }}</view> <view class="content-item-header-right">
<view class="content-item-header-right-des" v-if="type == '0'">暂态事件类型{{ item.showName.slice(0, <view class="content-item-header-right-title">{{ item.equipmentName }}</view>
-4) }}</view> <!-- <view class="content-item-header-right-des">{{ item.engineeringName }} {{ item.projectName }}</view> -->
<!-- <view class="content-item-header-right-des">{{ item.subTitle }}</view> --> <view class="content-item-header-right-des">工程名称{{ item.engineeringName }}</view>
</view> <view class="content-item-header-right-des">项目名称{{ item.projectName }}</view>
<view class="ml10" v-if="type === '0' || item.status != '1'">🔍</view> <view class="content-item-header-right-des" v-if="type == '0' || type == '1'"
</view> >监测点名称{{ item.lineName }}</view
<view class="content-item-footer">{{ item.subTitle }}</view> >
</view> <view class="content-item-header-right-des" v-if="type == '0'"
<!-- <uni-card >暂态类型{{ item.showName }}</view
:title="item.equipmentName" >
:extra="item.status == '1' ? '' : '未读'" <!-- <view class="content-item-header-right-des">{{ item.subTitle }}</view> -->
:sub-title="item.subTitle" </view>
thumbnail="https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png" <view class="ml10" v-if="type === '0' || item.status != '1'">
@click="jump(item)" <!-- <uni-icons type="search" size="25" color="#376cf3"></uni-icons> -->
v-for="(item, index) in store.data" 🔍
:key="index" </view>
> </view>
<view class="term-list-bottom"> <view class="content-item-footer">{{ item.subTitle }}</view>
<view class="term-list-bottom-item" v-for="(item2, textIndex) in item.dataSet" :key="textIndex"> </view>
{{ item2.showName + ':' + (item2.value == 3.1415926 ? '-' : item2.value) + (item2.unit || '') }} <!-- <uni-card
</view> :title="item.equipmentName"
</view> :extra="item.status == '1' ? '' : '未读'"
</uni-card> --> :sub-title="item.subTitle"
<Cn-empty v-if="store.empty" style="padding-top: 400rpx"></Cn-empty> thumbnail="https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png"
<uni-load-more v-if="store.status == 'loading' || (store.data && store.data.length > 0)" @click="jump(item)"
:status="store.status"></uni-load-more> v-for="(item, index) in store.data"
</view> :key="index"
</Cn-page> >
</template> <view class="term-list-bottom">
<view class="term-list-bottom-item" v-for="(item2, textIndex) in item.dataSet" :key="textIndex">
<script> {{ item2.showName + ':' + (item2.value == 3.1415926 ? '-' : item2.value) + (item2.unit || '') }}
import list from '@/common/js/list' </view>
import { updateStatus } from '@/common/api/message' </view>
</uni-card> -->
export default { <Cn-empty v-if="store.empty" style="padding-top: 400rpx"></Cn-empty>
mixins: [list], <uni-load-more
data() { v-if="store.status == 'loading' || (store.data && store.data.length > 0)"
return { :status="store.status"
loading: true, ></uni-load-more>
type: '', </view>
staticIcon: '', </Cn-page>
} </template>
},
onLoad(o) { <script>
this.type = o.type import list from '@/common/js/list'
switch (o.type) { import { updateStatus } from '@/common/api/message'
case '0':
uni.setNavigationBarTitle({ title: '暂态事件' }) export default {
this.staticIcon = '/static/zantai2.png' mixins: [list],
break data() {
case '1': return {
uni.setNavigationBarTitle({ title: '稳态事件' }) loading: true,
this.staticIcon = '/static/steady2.png' type: '',
break staticIcon: '',
case '2': }
uni.setNavigationBarTitle({ title: '运行事件' }) },
this.staticIcon = '/static/run2.png' onLoad(o) {
break this.type = o.type
case '3': switch (o.type) {
uni.setNavigationBarTitle({ title: '设备告警' }) case '0':
this.staticIcon = '/static/device_bad2.png' uni.setNavigationBarTitle({ title: '暂态事件' })
break this.staticIcon = '/static/zantai2.png'
} break
this.init() case '1':
}, uni.setNavigationBarTitle({ title: '稳态事件' })
// onShow() { this.init()}, this.staticIcon = '/static/steady2.png'
onNavigationBarButtonTap(e) { break
uni.showModal({ case '2':
title: '提示', uni.setNavigationBarTitle({ title: '运行事件' })
content: '确定要全部标记为已读吗?', this.staticIcon = '/static/run2.png'
success: (res) => { break
if (res.confirm) { case '3':
updateStatus({ uni.setNavigationBarTitle({ title: '设备告警' })
type: this.type, this.staticIcon = '/static/device_bad2.png'
eventIds: [], break
}).then(() => { }
this.loading = true this.init()
this.store.reload() },
}) // onShow() { this.init()},
} onNavigationBarButtonTap(e) {
}, uni.showModal({
}) title: '提示',
}, content: '确定要全部标记为已读吗?',
methods: { success: (res) => {
async init() { if (res.confirm) {
let dictData = await this.$util.getDictData('app_event') updateStatus({
console.log(dictData) type: this.type,
this.store = this.DataSource('/cs-harmonic-boot/eventUser/queryEventpage') eventIds: [],
this.store.params.type = this.type }).then(() => {
this.store.loadedCallback = () => { this.loading = true
console.log(111, this.store.data) this.store.reload()
})
this.store.data.forEach((item) => { }
if (this.type === '3') { },
item.showName = '告警,告警码:' + item.code })
} },
if (this.type !== '0') { methods: {
item.subTitle = `${item.startTime}发生${item.showName}` async init() {
} else { let dictData = await this.$util.getDictData('app_event')
item.subTitle = console.log(dictData)
`${item.startTime}` + this.store = this.DataSource('/cs-harmonic-boot/eventUser/queryEventpage')
item.dataSet this.store.params.type = this.type
.map((item2) => { this.store.params.startTime = this.$util.getBeforeDays()
return ( this.store.params.endTime = this.$util.getToday()
item2.showName + this.store.loadedCallback = () => {
'' + console.log(111, this.store.data)
(item2.value == 3.1415926 ? '-' : item2.value) +
(item2.unit || '') this.store.data.forEach((item) => {
) if (this.type === '3') {
}) item.showName = '告警,告警码:' + (item.code || '-')
.join('') }
} if (this.type !== '0') {
}) item.subTitle = `${item.startTime}发生${item.showName}`
} else {
this.loading = false item.subTitle =
} `发生时间:${item.startTime}` +
this.store.reload() item.dataSet
}, .map((item2) => {
jump(item) { return (
if (this.type === '0') { item2.showName +
'' +
let str = JSON.stringify(item).replace(/%/g, '百分比') (item2.value == 3.1415926 ? '-' : item2.value) +
item.status = '1' (item2.unit || '')
)
uni.navigateTo({ url: '/pages/message/messageDetail?detail=' + encodeURIComponent(str) }) })
} else { .join('')
if (item.status != '1') { }
item.status = '1' })
updateStatus({
eventIds: [item.id], this.loading = false
}) }
} this.store.reload()
} },
}, jump(item) {
}, if (this.type === '0') {
} let str = JSON.stringify(item).replace(/%/g, '百分比')
</script> item.status = '1'
<style lang="scss"> uni.navigateTo({ url: '/pages/message/messageDetail?detail=' + encodeURIComponent(str) })
.content { } else {
.content-item { if (item.status != '1') {
margin: 20rpx; item.status = '1'
padding: 20rpx 20rpx; updateStatus({
box-shadow: rgba(0, 0, 0, 0.08) 0px 0px 6rpx 2rpx; eventIds: [item.id],
border-radius: 8rpx; })
border: 1px solid #ebeef5; }
background: #fff; }
},
.content-item-header { },
display: flex; }
padding: 20rpx 0; </script>
border-bottom: 1px solid #ebeef5;
<style lang="scss">
.content-item-header-icon { .content {
display: flex; .content-item {
align-items: center; margin: 20rpx;
justify-content: center; padding: 20rpx 20rpx;
width: 100rpx; box-shadow: rgba(0, 0, 0, 0.08) 0px 0px 6rpx 2rpx;
height: 100rpx; border-radius: 8rpx;
border-radius: 8rpx; border: 1px solid #ebeef5;
background: $uni-theme-color; background: #fff;
}
.content-item-header {
.content-item-header-right { display: flex;
flex: 1; padding: 20rpx 0;
display: flex; border-bottom: 1px solid #ebeef5;
flex-direction: column;
justify-content: space-between; .content-item-header-icon {
// height: 140rpx; display: flex;
margin-left: 20rpx; align-items: center;
justify-content: center;
.content-item-header-right-title { width: 100rpx;
font-size: 28rpx; height: 100rpx;
font-weight: bold; border-radius: 8rpx;
color: #111; background: $uni-theme-color;
} }
.content-item-header-right-des { .content-item-header-right {
font-size: 24rpx; flex: 1;
color: #999; display: flex;
} flex-direction: column;
} justify-content: space-between;
} // height: 140rpx;
margin-left: 20rpx;
.content-item-footer {
margin-top: 20rpx; .content-item-header-right-title {
font-size: 24rpx; font-size: 28rpx;
color: #999; font-weight: bold;
} color: #111;
} }
// padding-top: 20rpx; .content-item-header-right-des {
} font-size: 24rpx;
color: #999;
.term-list-bottom { }
.term-list-bottom-item { }
font-size: 28rpx; }
margin-bottom: 10rpx;
display: flex; .content-item-footer {
justify-content: space-between; margin-top: 20rpx;
// view:first-of-type{ font-size: 24rpx;
// color: #111; color: #999;
// } }
} }
.term-list-bottom-item:last-of-type { // padding-top: 20rpx;
margin-bottom: 0; }
}
} .term-list-bottom {
.term-list-bottom-item {
/deep/ .uni-list-item { font-size: 28rpx;
background-color: $uni-theme-white !important; margin-bottom: 10rpx;
} display: flex;
justify-content: space-between;
/deep/ .uni-card__header-extra-text { // view:first-of-type{
color: #dd524d !important; // color: #111;
font-size: 20rpx; // }
} }
</style>
.term-list-bottom-item:last-of-type {
margin-bottom: 0;
}
}
/deep/ .uni-list-item {
background-color: $uni-theme-white !important;
}
/deep/ .uni-card__header-extra-text {
color: #dd524d !important;
font-size: 20rpx;
}
</style>

View File

@@ -1,91 +1,91 @@
<template> <template>
<Cn-page :loading="loading"> <Cn-page :loading="loading">
<view class="detail" slot="body"> <view class="detail" slot="body">
<view class="detail-content" style="font-size: 32rpx"> <view class="detail-content" style="font-size: 32rpx">
<!-- <view class="detail-content-title mb20">发生时间</view> --> <!-- <view class="detail-content-title mb20">发生时间</view> -->
<view>{{ detail.startTime }}</view> <view>{{ detail.startTime }}</view>
</view> </view>
<view class="detail-content"> <view class="detail-content">
<view class="detail-content-title mb20">基础信息</view> <view class="detail-content-title mb20">基础信息</view>
<view class="mb5"> 设备名称{{ detail.equipmentName }}</view> <view class="mb5"> 设备名称{{ detail.equipmentName }}</view>
<view class="mb5"> 项目名称{{ detail.projectName }} </view> <view class="mb5"> 项目名称{{ detail.projectName }} </view>
<view class="mb5"> 工程名称{{ detail.engineeringName }} </view> <view class="mb5"> 工程名称{{ detail.engineeringName }} </view>
<view class="mb5"> 事件名称{{ detail.showName }}</view> <view class="mb5"> 事件名称{{ detail.showName }}</view>
<view class="mb5" v-for="(item, textIndex) in detail.dataSet" :key="textIndex"> <view class="mb5" v-for="(item, textIndex) in detail.dataSet" :key="textIndex">
{{ item.showName + ':' + (item.value == 3.1415926 ? '-' : item.value) + (item.unit || '') }} {{ item.showName + '' + (item.value == 3.1415926 ? '-' : item.value) + (item.unit || '') }}
</view> </view>
</view> </view>
<view class="detail-content"> <view class="detail-content">
<view class="detail-content-title mb20">瞬时波形图</view> <view class="detail-content-title mb20">瞬时波形图</view>
<image <image
style="width: 100%" style="width: 100%"
:src="detail.instantPics" :src="detail.instantPics"
mode="widthFix" mode="widthFix"
v-if="detail.instantPics" v-if="detail.instantPics"
@click="previewImage(detail.instantPics)" @click="previewImage(detail.instantPics)"
/> />
<text v-else>暂无</text> <text v-else>暂无</text>
</view> </view>
<view class="detail-content"> <view class="detail-content">
<view class="detail-content-title mb20">RMS波形图</view> <view class="detail-content-title mb20">RMS波形图</view>
<image <image
style="width: 100%" style="width: 100%"
:src="detail.rmsPics" :src="detail.rmsPics"
mode="widthFix" mode="widthFix"
v-if="detail.rmsPics" v-if="detail.rmsPics"
@click="previewImage(detail.rmsPics)" @click="previewImage(detail.rmsPics)"
/> />
<text v-else>暂无</text> <text v-else>暂无</text>
</view> </view>
</view> </view>
</Cn-page> </Cn-page>
</template> </template>
<script> <script>
import { updateStatus } from '@/common/api/message' import { updateStatus } from '@/common/api/message'
export default { export default {
data() { data() {
return { return {
loading: true, loading: true,
detail: {}, detail: {},
} }
}, },
onLoad(options) { onLoad(options) {
console.log(options.detail) console.log(options.detail)
this.detail = JSON.parse(decodeURIComponent(options.detail).replace(/百分比/g, '%')) this.detail = JSON.parse(decodeURIComponent(options.detail).replace(/百分比/g, '%'))
this.detail.rmsPics && (this.detail.rmsPics = this.$config.static + this.detail.rmsPics) this.detail.rmsPics && (this.detail.rmsPics = this.$config.static + this.detail.rmsPics)
this.detail.instantPics && (this.detail.instantPics = this.$config.static + this.detail.instantPics) this.detail.instantPics && (this.detail.instantPics = this.$config.static + this.detail.instantPics)
this.loading = false this.loading = false
if (this.detail.status != 1) { if (this.detail.status != 1) {
updateStatus({ updateStatus({
eventIds: [this.detail.id], eventIds: [this.detail.id],
}) })
} }
}, },
methods: { methods: {
previewImage(url) { previewImage(url) {
uni.previewImage({ uni.previewImage({
urls: [url], urls: [url],
}) })
}, },
}, },
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.detail { .detail {
padding: 20rpx 0; padding: 20rpx 0;
.detail-content { .detail-content {
padding: 20rpx; padding: 20rpx;
background: #fff; background: #fff;
margin-bottom: 20rpx; margin-bottom: 20rpx;
font-size: 26rpx; font-size: 26rpx;
.detail-content-title { .detail-content-title {
font-size: 32rpx; font-size: 28rpx;
color: #111; color: #111;
font-weight: 700; font-weight: 700;
} }
} }
} }
</style> </style>

166
pages/message1/alarm.vue Normal file
View File

@@ -0,0 +1,166 @@
<template>
<view style="position: relative">
<!-- 运行告警 -->
<!-- 卡片 -->
<scroll-view
scroll-y="true"
@refresherrefresh="refresherrefresh"
@scrolltolower="scrolltolower"
:refresher-triggered="triggered"
refresher-enabled="true"
class="event-list"
:style="{ height: 'calc(100vh - ' + (navHeight + 10) + 'px)', overflow: 'auto' }"
>
<!-- 循环渲染事件项 -->
<uni-card
class="event-item boxClick"
:class="item.type"
v-for="(item, index) in this.store.data"
:key="index"
@click="jump(item)"
>
<!-- 头部图标 + 信息 + 操作 -->
<view class="event-header">
<view class="event-icon">
<!-- 动态图标根据类型切换 -->
<!-- <uni-icons
custom-prefix="iconfont"
type="icon-terminal-box-fill"
size="30"
color="#376cf3"
></uni-icons> -->
<Cn-icon-transient :name="`运行告警`" />
<view class="badge1" v-if="item.isRead == 0"> </view>
</view>
<view class="event-info">
<view class="event-title">
<text class="event-id">{{ item.date }}</text>
</view>
<view class="event-desc">
<text>告警终端{{ item.warnNums }}</text>
<text>通讯中断{{ item.interruptCounts }}</text>
<text>终端告警{{ item.warnCounts}}</text>
</view>
</view>
<view class="event-action">
<!-- <uni-icons type="search" size="25" color="#376cf3"></uni-icons> -->
🔍
</view>
</view>
<!-- <view class="event-detail">
<text> 告警终端{{ item.warnNums }} </text>
</view> -->
</uni-card>
<uni-load-more
v-if="store.status == 'loading' || (store.data && store.data.length > 0)"
:status="store.status"
></uni-load-more>
<Cn-empty v-else style="top: 20%"></Cn-empty>
</scroll-view>
</view>
</template>
<script>
import list from '@/common/js/list'
export default {
components: {},
props: {
navHeight: {
type: Number,
default: 0,
},
selectValue: {
type: Object,
// default: () => {},
},
},
mixins: [list],
data() {
return {
triggered: true,
status: 'noMore', //more加载前 loading加载中 noMore加载后
}
},
mounted() {},
methods: {
init() {
this.store = this.DataSource('/cs-harmonic-boot/csAlarm/queryAlarmList')
// this.store.params.pageSize = 10000
this.store.params.engineerId = this.selectValue.engineeringId
this.store.params.projectId = this.selectValue.projectId
this.store.params.devId = this.selectValue.deviceId
this.store.params.lineId = this.selectValue.lineId
this.store.params.time = this.selectValue.date
this.store.loadedCallback = () => {
this.loading = false
}
this.store.reload()
},
jump(item) {
let str = JSON.stringify(item).replace(/%/g, '百分比')
item.status = '1'
uni.navigateTo({ url: '/pages/message1/comp/alarmDetails?detail=' + encodeURIComponent(str) })
},
// 下拉
refresherrefresh() {
this.triggered = true
uni.startPullDownRefresh()
setTimeout(() => {
this.triggered = false
}, 500)
},
// 上拉
scrolltolower() {
if (this.store.status != 'noMore') {
this.store.next && this.store.next()
}
},
},
computed: {},
watch: {
selectValue: {
handler(val, oldVal) {
if (Object.keys(val).length === 0) return
this.init()
},
deep: true,
immediate: true,
},
},
}
</script>
<style lang="scss" scoped>
@import './index.scss';
/* 列表容器 */
.event-list {
margin-top: 20rpx;
/* 头部:图标 + 信息 + 操作 */
// .event-header {
// margin-bottom: 0rpx;
// }
// .event-title {
// margin-bottom: 0rpx;
// }
/* 图标区域(按类型区分背景色) */
.event-icon {
// width: 80rpx;
// height: 80rpx;
background-color: #376cf320;
}
/* 信息区域 */
.event-info {
flex: 1;
}
}
/deep/ .uni-scroll-view-refresher {
display: none;
}
</style>

249
pages/message1/comp/F47.vue Normal file
View File

@@ -0,0 +1,249 @@
<template>
<!-- ITIC -->
<view>
<l-echart v-if="status != 'loading'" ref="echartRef" @finished="initChart"></l-echart>
<uni-load-more v-else :status="status"></uni-load-more>
</view>
</template>
<script>
const echarts = require('../../../uni_modules/lime-echart/static/echarts.min')
export default {
components: {},
props: {
store: {
type: [Object],
},
},
data() {
return {
option: {
backgroundColor: '#fff',
grid: {
left: '10px',
right: '40rpx',
bottom: '40rpx',
top: '10px',
containLabel: true,
},
legend: {
data: ['分割线', '可容忍事件', '不可容忍事件'],
right: '10px',
bottom: '10px',
textStyle: {
fontSize: 10,
},
itemWidth: 10,
itemHeight: 10,
itemGap: 8,
padding: [5, 5, 5, 10],
},
yAxis: {
type: 'log',
min: '0.001',
max: '1000',
name: 's',
inverse: true,
axisLabel: {
rotate: -90,
},
splitLine: { show: false },
},
xAxis: {
type: 'value',
splitNumber: 10,
minInterval: 20,
position: 'top',
rotate: 90,
max: 140,
axisLabel: {
rotate: -90,
},
name: '%',
},
series: [
{
name: '分割线',
type: 'line',
data: [
[0, 0.05],
[50, 0.05],
[50, 0.2],
[70, 0.2],
[70, 0.5],
[80, 0.5],
[80, 10],
[80, 1000],
],
showSymbol: false,
tooltips: {
show: false,
},
color: '#DAA520',
},
{
name: '可容忍事件',
type: 'scatter',
symbol: 'circle',
// data: this.pointF,
data: [],
color: 'green',
},
{
name: '不可容忍事件',
type: 'scatter',
symbol: 'circle',
// data: this.pointFun,
data: [],
color: 'red',
},
],
},
status: 'loading',
echartRef: null,
pointF: [],
pointFun: [],
data: [],
maxXAxis: 140,
}
},
mounted() {
// this.initChart()
// console.log('🚀 ~ props.data:', this.props.data)
},
methods: {
init() {},
async initChart() {
if (!this.$refs.echartRef) return
try {
this.echartRef = await this.$refs.echartRef.init(echarts)
this.bindChartClickEvent()
this.echartRef.setOption(this.option, true)
} catch (error) {
console.error('图表初始化失败:', error)
}
},
gongfunction() {
var standF = 0
var unstandF = 0
this.pointF = []
this.pointFun = []
var total = 0
let dataList = [0]
total = this.data.length
if (total == 0) {
} else {
for (var i = 0; i < this.data.length; i++) {
var point = []
var xx = this.data[i].evtParamTm.replace(/s/g, '')
var yy = this.data[i].evtParamVVaDepth.replace(/%/g, '')
var time = this.data[i].startTime.replace('T', ' ')
dataList.push(yy)
point = [yy, xx, time, this.data[i]]
if (xx < 0.05) {
standF++
this.pointF.push({
value: point,
itemStyle: { normal: { color: 'green' } },
})
} else if (xx < 0.2) {
if (yy > 50) {
standF++
this.pointF.push({
value: point,
itemStyle: { normal: { color: 'green' } },
})
} else {
unstandF++
this.pointFun.push({
value: point,
itemStyle: { normal: { color: 'red' } },
})
}
} else if (xx < 0.5) {
if (yy > 70) {
standF++
this.pointF.push({
value: point,
itemStyle: { normal: { color: 'green' } },
})
} else {
unstandF++
this.pointFun.push({
value: point,
itemStyle: { normal: { color: 'red' } },
})
}
} else {
if (yy > 80) {
standF++
this.pointF.push({
value: point,
itemStyle: { normal: { color: 'green' } },
})
} else {
unstandF++
this.pointFun.push({
value: point,
itemStyle: { normal: { color: 'red' } },
})
}
}
}
}
this.option.xAxis.max = Math.max(
140,
Math.ceil(
Math.max(
...dataList
.filter((item) => {
return item !== '-' && !isNaN(Number(item))
})
.map((item) => Number(item)),
) / 10,
) * 10,
) //this.maxXAxis
this.option.series[1].data = this.pointF
this.option.series[2].data = this.pointFun
if (this.echartRef) {
this.echartRef.setOption(this.option, true)
} else {
this.initChart()
}
},
bindChartClickEvent() {
if (!this.echartRef) return
this.echartRef.on('click', (params) => {
// 点击查看详情
let item = params.value[3]
let str = JSON.stringify(item).replace(/%/g, '百分比')
uni.navigateTo({ url: '/pages/message1/comp/transientDetails?detail=' + encodeURIComponent(str) })
})
},
},
computed: {},
watch: {
store: {
handler(val, oldVal) {
this.status = val.status
this.data = (val.data || [])
this.gongfunction()
},
deep: true,
immediate: true,
},
},
}
</script>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,241 @@
<template>
<!-- ITIC -->
<view>
<l-echart v-if="status != 'loading'" ref="echartRef" @finished="initChart"></l-echart>
<uni-load-more v-else :status="status"></uni-load-more>
</view>
</template>
<script>
const echarts = require('../../../uni_modules/lime-echart/static/echarts.min')
export default {
components: {},
props: {
store: {
type: [Object],
},
},
data() {
return {
option: {
backgroundColor: '#fff',
grid: {
left: '10px',
right: '40rpx',
bottom: '40rpx',
top: '10px',
containLabel: true,
},
legend: {
data: ['上限', '下限', '可容忍事件', '不可容忍事件'],
right: '10px',
bottom: '10px',
textStyle: {
fontSize: 10,
},
itemWidth: 10,
itemHeight: 10,
itemGap: 8,
padding: [5, 5, 5, 10],
},
color: ['#FF8C00', '#00BFFF', 'green', 'red'],
yAxis: {
type: 'log',
min: '0.001',
max: '1000',
name: 's',
inverse: true,
axisLabel: {
rotate: -90,
},
splitLine: { show: false },
},
xAxis: {
type: 'value',
splitNumber: 10,
minInterval: 3,
position: 'top',
rotate: 90,
axisLabel: {
rotate: 90,
},
name: '%',
},
series: [
{
name: '上限',
type: 'line',
data: [
[200, 0.001],
[140, 0.003],
[120, 0.003],
[120, 0.5],
[110, 0.5],
[110, 10],
[110, 1000],
],
showSymbol: false,
tooltips: {
show: false,
},
color: '#FF8C00',
},
{
name: '下限',
type: 'line',
data: [
[0, 0.02],
[70, 0.02],
[70, 0.5],
[80, 0.5],
[80, 10],
[90, 10],
[90, 1000],
],
showSymbol: false,
tooltips: {
show: false,
},
color: '#00BFFF',
},
{
name: '可容忍事件',
type: 'scatter',
symbol: 'circle',
// data: this.pointI,
data: [],
color: 'green',
},
{
name: '不可容忍事件',
type: 'scatter',
symbol: 'circle',
// data: this.pointIun,
data: [],
color: 'red',
},
],
},
status: 'loading',
echartRef: null,
pointI: [],
pointIun: [],
data: [],
}
},
mounted() {
// this.initChart()
// console.log('🚀 ~ props.data:', this.props.data)
},
methods: {
init() {},
async initChart() {
if (!this.$refs.echartRef) return
try {
this.echartRef = await this.$refs.echartRef.init(echarts)
this.bindChartClickEvent()
this.echartRef.setOption(this.option, true)
} catch (error) {
console.error('图表初始化失败:', error)
}
},
gongfunction() {
// 初始化计数与数据数组
let normalCount = 0
let abnormalCount = 0
this.normalPoints = []
this.abnormalPoints = []
if (!this.data || this.data.length === 0) {
this.updateChartOption()
return
}
// 缓存长度,遍历数据
const len = this.data.length
for (let i = 0; i < len; i++) {
const item = this.data[i]
// 建议确认正则意图,/s/g 仅移除字母 s若去空格应为 /\s/g
const xx = parseFloat(item.evtParamTm.replace(/s/g, ''))
const yy = parseFloat(item.evtParamVVaDepth.replace(/%/g, ''))
const time = item.startTime.replace('T', ' ')
const pointData = [yy, xx, time, item]
const isNormal = this.checkPointStatus(xx, yy)
const pointObj = {
value: pointData,
itemStyle: { normal: { color: isNormal ? 'green' : 'red' } },
}
if (isNormal) {
normalCount++
this.normalPoints.push(pointObj)
} else {
abnormalCount++
this.abnormalPoints.push(pointObj)
}
}
this.updateChartOption()
},
// 提取判断逻辑为独立方法
checkPointStatus(xx, yy) {
if (xx <= 0.003) {
const line = 230 - 30000 * xx
return yy <= line
} else if (xx <= 0.02) {
return yy <= 120
} else if (xx <= 0.5) {
return yy > 70 && yy < 120
} else if (xx <= 10) {
return yy > 80 && yy < 110
} else {
return yy > 90 && yy < 110
}
},
updateChartOption() {
// 建议避免硬编码 series 索引,可通过 seriesName 查找
this.option.series[2].data = this.normalPoints
this.option.series[3].data = this.abnormalPoints
if (this.echartRef) {
this.echartRef.setOption(this.option, true)
} else {
this.initChart()
}
},
bindChartClickEvent() {
if (!this.echartRef) return
this.echartRef.on('click', (params) => {
console.log('🚀 ~ params:', params.value[3])
// 点击查看详情
let item = params.value[3]
let str = JSON.stringify(item).replace(/%/g, '百分比')
uni.navigateTo({ url: '/pages/message1/comp/transientDetails?detail=' + encodeURIComponent(str) })
})
},
},
computed: {},
watch: {
store: {
handler(val, oldVal) {
this.status = val.status
this.data = (val.data || [])
this.gongfunction()
},
deep: true,
immediate: true,
},
},
}
</script>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,189 @@
<template>
<Cn-page :loading="loading">
<view class="detail" slot="body">
<view class="detail-content" style="font-size: 32rpx">
<!-- <view class="detail-content-title mb20">发生时间</view> -->
<view>{{ detail.date }}</view>
</view>
<view class="detail-content" style="padding: 0px">
<view class="detail-content-title pb20 pt20 pl20">终端告警列表</view>
</view>
<view class="event-list">
<uni-card class="event-item" :class="item.type" v-for="(item, index) in list" :key="index">
<!-- 头部图标 + 信息 + 操作 -->
<view class="event-header">
<view
class="event-icon"
:class="item.devType == 'Direct_Connected_Device' ? 'zl-bgc' : 'jc-bgc'"
>
<!-- 动态图标根据类型切换 -->
<!-- <uni-icons
custom-prefix="iconfont"
type="icon-terminal-box-fill"
size="35"
color="#FF0000"
></uni-icons> -->
<!-- <Cn-icon-transient :name="`运行告警`" /> -->
<Cn-icon-transient
:name="item.devType == 'Direct_Connected_Device' ? '治理设备' : '监测设备'"
/>
<view class="badge1" v-if="item.status == 0"> </view>
</view>
<view class="event-info">
<view class="event-title">
<text class="event-id">{{ item.devName }}</text>
<text
class="event-tag"
:class="item.devType == 'Direct_Connected_Device' ? 'zl-tag' : 'jc-tag'"
>{{ item.devType == 'Direct_Connected_Device' ? '治理设备' : '监测设备' }}</text
>
</view>
<view class="event-desc">
<text>工程名称{{ item.engineeringName }}</text>
<text>项目名称{{ item.projectName }}</text>
<!-- <text>事件时间{{ item.startTime }}</text> -->
</view>
</view>
</view>
<!-- 详情区域 -->
<view class="event-detail">
<view v-if="item.interruptCounts">
通讯中断 {{ item.interruptCounts }} 详情如下
<view class="textBox">
<view
v-for="date in String(item.interruptDetails || '').split('')"
class="textBox mb5"
>{{ date }}</view
></view
>
</view>
<view v-if="item.warnCounts">
终端告警 {{ item.warnCounts }} 详情如下
<view class="textBox">
<view v-for="val in item.warnDetails" class="textBox mb5">
{{ val.warnEventTime + '发生' + val.warnEventDesc }}
</view></view
>
</view>
</view>
</uni-card>
</view>
</view>
</Cn-page>
</template>
<script>
import { updateStatus, queryAlarmDetail } from '@/common/api/message'
export default {
data() {
return {
loading: true,
detail: {},
limit: '',
collapseValue: '0',
list: [],
}
},
onLoad(options) {
this.loading = true
this.detail = JSON.parse(decodeURIComponent(options.detail).replace(/百分比/g, '%'))
this.init()
if (this.detail.isRead != 1) {
updateStatus({
eventIds: [this.detail.eventId],
})
}
},
methods: {
init() {
queryAlarmDetail({
devList: this.detail.devIds,
time: this.detail.date,
})
.then((res) => {
this.list = res.data
this.loading = false
})
.catch(() => {
this.loading = false
})
},
},
}
</script>
<style lang="scss" scoped>
@import '../index.scss';
.detail {
padding: 20rpx 0;
.detail-content {
padding: 20rpx;
background: #fff;
margin-bottom: 20rpx;
font-size: 28rpx;
.detail-content-title {
font-size: 30rpx;
color: #111;
font-weight: 700;
}
}
.collapseTop {
padding: 10rpx 0;
margin-left: 15px;
.name {
font-size: 28rpx;
font-weight: 700;
color: #333333;
}
}
.frequency {
display: flex;
font-size: 28rpx;
// color: #666666;
}
}
.textBox {
// border-bottom: 1px solid #eee;
font-size: 28rpx;
color: #666666;
text-indent: 2em;
}
.event-list {
// background: #fff;
padding-bottom: 10rpx;
// .event-icon {
// background-color: #376cf320;
// }
.zl-bgc {
background-color: #376cf320;
}
.jc-bgc {
background-color: #376cf320;
}
.zl-tag {
background-color: #007aff20;
color: #007aff;
}
.jc-tag {
background-color: #007aff20;
color: #007aff;
}
}
/deep/ .uni-collapse-item__title-box {
padding: 0 15px 0 0;
height: 56rpx;
line-height: 56rpx;
font-size: 26rpx !important;
color: #666666;
span {
font-size: 26rpx !important;
}
}
.textBox {
max-height: 120rpx;
overflow-y: auto;
}
</style>

View File

@@ -0,0 +1,431 @@
<template>
<view class="preview-container">
<!-- 右上角按钮组 -->
<view class="btn-group">
<!-- 缩小按钮 -->
<!-- <view class="btn zoom-out-btn" @click="zoomOut">
<text class="btn-icon"></text>
</view> -->
<!-- 放大按钮 -->
<!-- <view class="btn zoom-in-btn" @click="zoomIn">
<text class="btn-icon">+</text>
</view> -->
<!-- 下载按钮 -->
<view class="btn download-btn" @click="downloadImage">
<text class="btn-icon"></text>
</view>
</view>
<!-- 图片预览区域使用movable-area和movable-view实现缩放移动 -->
<movable-area class="movable-area" :style="{ width: '100vw', height: '100vh' }">
<movable-view
class="movable-view"
direction="all"
:scale="true"
:scale-min="0.2"
:scale-max="0.5"
:scale-value="scaleValue"
@touchstart="onTouchStart"
@touchend="onTouchEnd"
:x="x"
:y="y"
:animation="true"
:animation-duration="300"
:style="{
width: rotatedWidth + 'px',
height: rotatedHeight + 'px',
}"
>
<view
class="image-wrapper"
:style="{
width: imgWidth + 'px',
height: imgHeight + 'px',
transform: 'rotate(90deg)',
transformOrigin: 'center center',
}"
>
<image
:src="imageUrl"
class="preview-img"
mode="aspectFill"
:style="{
width: imgWidth + 'px',
height: imgHeight + 'px',
}"
@load="onImageLoad"
></image>
</view>
</movable-view>
</movable-area>
</view>
</template>
<script>
export default {
onLoad(options) {
this.imageUrl = decodeURIComponent(options.url) // 接收传递的图片URL需要解码
},
data() {
return {
imageUrl: '',
// 缩放相关 - 默认0.5
scaleValue: 0.2,
x: 0,
y: 0,
// 图片原始尺寸
imgWidth: 0,
imgHeight: 0,
// 旋转后的尺寸(交换宽高)
rotatedWidth: 0,
rotatedHeight: 0,
// 提示显示控制
showScaleTip: false,
tipTimer: null,
// 屏幕尺寸
windowWidth: 0,
windowHeight: 0,
// 缩放步长
zoomStep: 0.1,
// 动画控制
isTouching: false,
animationTimer: null
}
},
mounted() {
// 获取屏幕尺寸
const systemInfo = uni.getSystemInfoSync()
this.windowWidth = systemInfo.windowWidth
this.windowHeight = systemInfo.windowHeight
},
methods: {
// 图片加载完成后获取尺寸
onImageLoad(e) {
const { width, height } = e.detail
// 保存原始尺寸
this.imgWidth = width
this.imgHeight = height
// 旋转90度后宽度和高度互换
this.rotatedWidth = height // 旋转后宽度 = 原高度
this.rotatedHeight = width // 旋转后高度 = 原宽度
// 计算初始位置居中考虑0.5缩放)
this.resetPosition()
},
// 重置位置到中心(考虑当前缩放比例)
resetPosition() {
// 计算居中的偏移量,考虑缩放比例
const displayWidth = this.rotatedWidth * this.scaleValue
const displayHeight = this.rotatedHeight * this.scaleValue
this.x = (this.windowWidth - displayWidth) / 2
this.y = (this.windowHeight - displayHeight) / 2
},
// 触摸开始
onTouchStart() {
this.isTouching = true
},
// 触摸结束
onTouchEnd() {
this.isTouching = false
},
// 缩放事件处理
onScale(e) {
this.scaleValue = e.detail.scale
// 显示缩放提示
this.showScaleTip = true
if (this.tipTimer) {
clearTimeout(this.tipTimer)
}
this.tipTimer = setTimeout(() => {
this.showScaleTip = false
}, 1500)
},
// 放大
zoomIn() {
// 计算新的缩放值,不超过最大值
const newScale = Math.min(this.scaleValue + this.zoomStep, 0.5)
this.setScaleWithAnimation(newScale)
},
// 缩小
zoomOut() {
// 计算新的缩放值,不低于最小值
const newScale = Math.max(this.scaleValue - this.zoomStep, 0.2)
this.setScaleWithAnimation(newScale)
},
// 带动画的设置缩放值
setScaleWithAnimation(newScale) {
// 保存旧的缩放值用于动画
const oldScale = this.scaleValue
// 计算缩放中心点(屏幕中心)
const centerX = this.windowWidth / 2
const centerY = this.windowHeight / 2
// 计算当前图片中心点
const oldDisplayWidth = this.rotatedWidth * oldScale
const oldDisplayHeight = this.rotatedHeight * oldScale
const oldCenterX = this.x + oldDisplayWidth / 2
const oldCenterY = this.y + oldDisplayHeight / 2
// 计算偏移量,使缩放后图片中心保持在屏幕中心
const newDisplayWidth = this.rotatedWidth * newScale
const newDisplayHeight = this.rotatedHeight * newScale
const newX = centerX - newDisplayWidth / 2
const newY = centerY - newDisplayHeight / 2
// 更新缩放值和位置
this.scaleValue = newScale
this.x = newX
this.y = newY
// 显示缩放提示
this.showScaleTip = true
if (this.tipTimer) {
clearTimeout(this.tipTimer)
}
this.tipTimer = setTimeout(() => {
this.showScaleTip = false
}, 1500)
console.log('缩放:', {oldScale, newScale, x: this.x, y: this.y})
},
// 下载图片
downloadImage() {
uni.showLoading({
title: '下载中,请稍等...',
mask: true,
})
// 先获取图片信息(如果是网络图片需要先下载)
uni.downloadFile({
url: this.imageUrl,
success: (res) => {
if (res.statusCode === 200) {
// 保存图片到相册
uni.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: () => {
uni.hideLoading()
uni.showToast({
title: '保存成功',
icon: 'success',
})
},
fail: (err) => {
uni.hideLoading()
console.error('保存失败', err)
// 处理用户拒绝权限的情况
if (err.errMsg.includes('auth deny')) {
uni.showModal({
title: '提示',
content: '需要您授权保存图片到相册',
success: (res) => {
if (res.confirm) {
uni.openSetting({
success: (settingRes) => {
console.log('打开设置页面', settingRes)
},
})
}
},
})
} else {
uni.showToast({
title: '保存失败',
icon: 'none',
})
}
},
})
} else {
uni.hideLoading()
uni.showToast({
title: '下载失败',
icon: 'none',
})
}
},
fail: (err) => {
uni.hideLoading()
console.error('下载失败', err)
uni.showToast({
title: '下载失败',
icon: 'none',
})
},
})
},
},
// 页面返回前清理定时器
onUnload() {
if (this.tipTimer) {
clearTimeout(this.tipTimer)
}
if (this.animationTimer) {
cancelAnimationFrame(this.animationTimer)
}
},
}
</script>
<style lang="scss" scoped>
.preview-container {
position: relative;
width: 100vw;
height: 100vh;
background: #000;
overflow: hidden;
}
.movable-area {
width: 100vw;
height: 100vh;
background: #000;
}
.movable-view {
display: flex;
align-items: center;
justify-content: center;
// 添加硬件加速
transform: translateZ(0);
will-change: transform;
}
.image-wrapper {
display: flex;
align-items: center;
justify-content: center;
// 添加硬件加速
transform: translateZ(0) rotate(90deg);
will-change: transform;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
transition: transform 0.3s cubic-bezier(0.25, 0.1, 0.25, 1);
}
.preview-img {
display: block;
// 添加硬件加速
transform: translateZ(0);
will-change: transform;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
}
// 按钮组
.btn-group {
position: fixed;
top: 30rpx;
right: 30rpx;
display: flex;
flex-direction: row;
gap: 20rpx;
z-index: 1000;
}
// 通用按钮样式
.btn {
width: 70rpx;
height: 70rpx;
background: rgba(0, 0, 0, 0.5);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
// 按钮不参与动画
transform: translateZ(0);
transition: background-color 0.2s ease;
&:active {
background: rgba(0, 0, 0, 0.8);
transform: scale(0.95);
}
.btn-icon {
color: #fff;
font-size: 40rpx;
line-height: 1;
font-weight: bold;
}
}
// 缩小按钮
.zoom-out-btn {
.btn-icon {
font-size: 50rpx;
}
}
// 放大按钮
.zoom-in-btn {
.btn-icon {
font-size: 40rpx;
}
}
// 下载按钮
.download-btn {
.btn-icon {
font-size: 35rpx;
}
}
// 缩放提示
.scale-tip {
position: fixed;
bottom: 100rpx;
left: 50%;
transform: translateX(-50%) translateZ(0);
background: rgba(0, 0, 0, 0.6);
color: #fff;
padding: 10rpx 30rpx;
border-radius: 40rpx;
font-size: 28rpx;
z-index: 1000;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
animation: fadeInOut 1.5s ease;
// 提示不参与动画
will-change: opacity;
}
@keyframes fadeInOut {
0% {
opacity: 0;
}
15% {
opacity: 1;
}
85% {
opacity: 1;
}
100% {
opacity: 0;
}
}
</style>

View File

@@ -0,0 +1,159 @@
<template>
<Cn-page :loading="loading">
<view class="detail" slot="body">
<view class="detail-content" style="font-size: 32rpx">
<!-- <view class="detail-content-title mb20">发生时间</view> -->
<view>{{ detail.statisticsDate }}</view>
</view>
<view class="detail-content">
<view class="detail-content-title mb20">基础信息</view>
<view class="mb5"> 工程名称{{ detail.engineeringName }} </view>
<view class="mb5"> 项目名称{{ detail.projectName }} </view>
<view class="mb5"> 设备名称{{ detail.devName }} </view>
<view class="mb5"> 监测点名称{{ detail.lineName }}</view>
<view class="mb5" style="display: flex">
越限详情
<view style="flex: 1" class="details">{{ detail.overLimitDesc }}</view></view
>
</view>
<view class="detail-content">
<view class="detail-content-title mb20"
>指标越限详情<text class="prompt">仅显示最严重的10组数据</text></view
>
<uni-collapse accordion v-model="collapseValue">
<uni-collapse-item :title="item.targetName" v-for="item in list">
<view class="data-table">
<view class="table-header">
<text>时间</text>
<text>数据类型</text>
<text v-if="!item.harmDetailList[0].hasT">A相</text>
<text v-if="!item.harmDetailList[0].hasT">B相</text>
<text v-if="!item.harmDetailList[0].hasT">C相</text>
<text v-if="item.harmDetailList[0].hasT">总相</text>
<text>限值</text>
</view>
<view class="table-row" v-for="value in item.harmDetailList">
<text>{{ value.statisticsTime }}</text>
<text>{{ value.valueType }}</text>
<text v-if="!value.hasT">{{ value.dataA }}</text>
<text v-if="!value.hasT">{{ value.dataB }}</text>
<text v-if="!value.hasT">{{ value.dataC }}</text>
<text v-if="value.hasT">{{ value.dataT }}</text>
<text>{{ value.overLimitData }}</text>
</view>
</view>
</uni-collapse-item>
</uni-collapse>
</view>
</view>
</Cn-page>
</template>
<script>
import { updateStatus, queryHarmonicDetail } from '@/common/api/message'
export default {
data() {
return {
loading: true,
detail: {},
list: [],
collapseValue: '0',
}
},
onLoad(options) {
// console.log(options.detail)
this.detail = JSON.parse(decodeURIComponent(options.detail).replace(/百分比/g, '%'))
this.init()
if (this.detail.isRead != 1) {
updateStatus({
eventIds: [this.detail.eventId],
})
}
},
methods: {
init() {
queryHarmonicDetail({
lineId: this.detail.lineId,
time: this.detail.statisticsDate,
})
.then((res) => {
this.list = res.data
this.loading = false
})
.catch(() => {
this.loading = false
})
// }
},
},
}
</script>
<style lang="scss">
.detail {
padding: 20rpx 0;
.detail-content {
padding: 20rpx;
background: #fff;
margin-bottom: 20rpx;
font-size: 28rpx;
.detail-content-title {
font-size: 30rpx;
color: #111;
font-weight: 700;
}
}
.limit {
display: flex;
align-items: center;
justify-content: end;
width: 450rpx;
margin-left: auto;
}
.prompt {
font-size: 24rpx;
color: #111;
font-weight: 500;
}
}
.data-table {
margin-top: 20rpx;
background-color: #fff;
overflow: hidden;
.table-header,
.table-row {
display: flex;
justify-content: space-between;
padding: 20rpx 0rpx;
border-bottom: 1rpx solid #eee;
text {
width: 100rpx;
text-align: center;
font-size: 28rpx;
// color: #333;
&:nth-child(1) {
flex: 1;
}
&:nth-child(2) {
flex: 1;
}
}
}
.table-header {
padding: 0rpx;
padding-bottom: 10rpx;
}
}
/deep/ .uni-collapse-item__title-text {
font-weight: 700;
span {
font-size: 28rpx;
}
}
.details {
max-height: 70px;
overflow-y: auto;
}
</style>

View File

@@ -0,0 +1,99 @@
<template>
<Cn-page :loading="loading">
<view class="detail" slot="body">
<view class="detail-content" style="font-size: 32rpx">
<!-- <view class="detail-content-title mb20">发生时间</view> -->
<view>{{ detail.startTime }}</view>
</view>
<view class="detail-content">
<view class="detail-content-title mb20">基础信息</view>
<view class="mb5"> 工程名称{{ detail.engineeringName }} </view>
<view class="mb5"> 项目名称{{ detail.projectName }} </view>
<view class="mb5"> 设备名称{{ detail.equipmentName }}</view>
<view class="mb5"> 监测点名称{{ detail.lineName }}</view>
<view class="mb5"> 暂态类型{{ detail.showName }}</view>
<view class="mb5" v-if="detail.evtParamTm"> 持续时间{{ detail.evtParamTm }}s</view>
<view class="mb5" v-if="detail.evtParamVVaDepth"> 幅值{{ detail.evtParamVVaDepth }}%</view>
<view class="mb5" v-if="detail.evtParamPhase"> 相别{{ detail.evtParamPhase }}</view>
<!-- <view class="mb5" v-for="(item, textIndex) in detail.dataSet" :key="textIndex">
{{ item.showName + '' + (item.value == 3.1415926 ? '-' : item.value) + (item.unit || '') }}
</view> -->
</view>
<view class="detail-content">
<view class="detail-content-title mb20">瞬时波形图</view>
<image
style="width: 100%"
:src="detail.instantPics"
mode="widthFix"
v-if="detail.instantPics"
@click="previewImage(detail.instantPics)"
/>
<text v-else>暂无</text>
</view>
<view class="detail-content">
<view class="detail-content-title mb20">RMS波形图</view>
<image
style="width: 100%"
:src="detail.rmsPics"
mode="widthFix"
v-if="detail.rmsPics"
@click="previewImage(detail.rmsPics)"
/>
<text v-else>暂无</text>
</view>
</view>
</Cn-page>
</template>
<script>
import { updateStatus } from '@/common/api/message'
export default {
data() {
return {
loading: true,
detail: {},
}
},
onLoad(options) {
// console.log(options.detail)
this.detail = JSON.parse(decodeURIComponent(options.detail).replace(/百分比/g, '%'))
this.detail.rmsPics && (this.detail.rmsPics = this.$config.static + this.detail.rmsPics)
this.detail.instantPics && (this.detail.instantPics = this.$config.static + this.detail.instantPics)
this.loading = false
if (this.detail.status != 1) {
updateStatus({
eventIds: [this.detail.id],
})
}
},
methods: {
previewImage(url) {
// uni.previewImage({
// urls: [url],
// })
uni.navigateTo({
url: `/pages/message1/comp/preview?url=${encodeURIComponent(url)}`,
})
},
},
}
</script>
<style lang="scss">
.detail {
padding: 20rpx 0;
.detail-content {
padding: 20rpx;
background: #fff;
margin-bottom: 20rpx;
font-size: 28rpx;
.detail-content-title {
font-size: 30rpx;
color: #111;
font-weight: 700;
}
}
}
</style>

198
pages/message1/index.scss Normal file
View File

@@ -0,0 +1,198 @@
/* 整体容器:横向排列,间距均匀 */
.statistics {
display: flex;
gap: 20rpx; /* 盒子之间的间距 */
/* 通用盒子样式 */
.box {
flex: 1; /* 四个盒子等分宽度 */
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 130rpx;
background-color: #ffffff;
border-radius: 16rpx;
}
/* 第一个盒子的特殊样式(蓝色背景) */
.box:first-child {
flex: 1.7;
}
.boxClick1 {
background-color: $uni-theme-color;
color: #ffffff;
}
/* 数字样式 */
.num {
font-size: 38rpx;
font-weight: 600;
line-height: 1.2;
margin-bottom: 8rpx;
}
/* 标签文字样式 */
.label {
font-size: 24rpx;
color: inherit; /* 继承父元素颜色,适配蓝色背景 */
}
}
/* 列表容器 */
.event-list {
background-color: #f5f7fa;
box-sizing: border-box;
/* 通用项样式 */
/deep/ .uni-card:first-of-type {
margin-top: 0 !important;
}
/deep/ .uni-card {
padding: 0 !important;
}
/* 头部:图标 + 信息 + 操作 */
.event-header {
display: flex;
align-items: center;
margin-bottom: 10rpx;
}
/* 图标区域(按类型区分背景色) */
.event-icon {
position: relative;
width: 110rpx;
height: 110rpx;
border-radius: 12rpx;
display: flex;
justify-content: center;
align-items: center;
margin-right: 20rpx;
}
.badge1 {
position: absolute;
top: -10rpx;
right: -10rpx;
width: 20rpx;
height: 20rpx;
background-color: #ff3b30; /* 红色徽章 */
border-radius: 20rpx;
}
/* 电压暂降 - 蓝色系 */
.sag .event-icon {
background-color: #2563eb20;
}
/* 电压暂升 - 橙色系 */
.swell .event-icon {
background-color: #e6a23c20;
}
.interrupt .event-icon {
background-color: #00000020;
}
.transient .event-icon {
background-color: #8b5cf620;
}
.unknown .event-icon {
background-color: #6b728020;
}
.event-icon image {
width: 48rpx;
height: 48rpx;
}
/* 信息区域 */
.event-info {
flex: 1;
}
.event-title {
display: flex;
align-items: center;
margin-bottom: 5rpx;
flex-wrap: wrap; /* 适配小屏,防止文字溢出 */
}
.event-id {
font-size: 30rpx;
font-weight: 700;
color: #333333;
margin-right: 16rpx;
}
/* 标签样式(按类型区分) */
.event-tag {
font-size: 20rpx;
padding: 0rpx 10rpx;
border-radius: 8rpx;
color: #ffffff;
height: 34rpx;
line-height: 38rpx;
}
.sag-tag {
background-color: #2563eb20;
color: #2563eb;
}
.swell-tag {
background-color: #e6a23c20;
color: #e6a23c;
}
.interrupt-tag {
background-color: #6b728020;
color: #6b7280;
}
.transient-tag {
background-color: #8b5cf620;
color: #8b5cf6;
}
.unknown-tag {
background-color: #6b728020;
color: #6b7280;
}
/* 描述文本 */
.event-desc {
display: flex;
flex-direction: column;
gap: 8rpx;
}
.event-desc text {
font-size: 28rpx;
color: #666666;
line-height: 1.2;
}
/* 操作按钮 */
.event-action {
display: flex;
justify-content: center;
align-items: center;
color: #999999;
font-size: 40rpx;
/* 点击反馈 */
touch-action: manipulation;
}
.event-action:active {
color: #376cf3;
transform: scale(0.95);
}
/* 详情文本 */
.event-detail {
font-size: 28rpx;
color: #666666;
line-height: 1.5;
padding-top: 10rpx;
border-top: 1rpx solid #f0f0f0;
word-wrap: break-word; /* 自动换行,防止长文本溢出 */
}
}
.smallLabel {
padding: 0 20rpx 20rpx 20rpx;
display: flex;
align-items: center;
justify-content: flex-end;
.segmented-control {
flex: 1;
margin-right: 20rpx;
height: 58rpx;
}
.uni-input {
font-size: 24rpx;
color: #2563eb;
margin-right: 10rpx;
}
}

158
pages/message1/run.vue Normal file
View File

@@ -0,0 +1,158 @@
<template>
<view style="position: relative">
<!-- 运行事件 -->
<!-- 卡片 -->
<scroll-view scroll-y="true" @refresherrefresh="refresherrefresh" @scrolltolower="scrolltolower"
:refresher-triggered="triggered" refresher-enabled="true" class="event-list"
:style="{ height: 'calc(100vh - ' + (navHeight + 10) + 'px)', overflow: 'auto' }">
<!-- 循环渲染事件项 -->
<uni-card class="event-item " :class="item.type" v-for="(item, index) in store.data" :key="index"
@click="jump(item)">
<!-- 头部图标 + 信息 + 操作 -->
<view class="event-header">
<view class="event-icon" :class="item.devType == 'Direct_Connected_Device' ? 'zl-bgc' : 'jc-bgc'">
<!-- 动态图标根据类型切换 -->
<!-- <uni-icons custom-prefix="iconfont" type="icon-shebei3" size="35" color="#376cf3"></uni-icons> -->
<Cn-icon-transient :name="item.devType == 'Direct_Connected_Device' ? '治理设备' : '监测设备'" />
<view class="badge1" v-if="item.status == 0"> </view>
</view>
<view class="event-info">
<view class="event-title">
<text class="event-id">{{ item.equipmentName }}</text>
<text class="event-tag"
:class="item.devType == 'Direct_Connected_Device' ? 'zl-tag' : 'jc-tag'">{{ item.devType
== 'Direct_Connected_Device' ? '治理设备' : '监测设备' }}</text>
</view>
<view class="event-desc">
<text>工程名称{{ item.engineeringName }}</text>
<text>项目名称{{ item.projectName }}</text>
<text>事件时间{{ item.startTime }}</text>
</view>
</view>
</view>
<!-- 详情区域 -->
<view class="event-detail">
<text> {{ item.showName }} </text>
</view>
</uni-card>
<uni-load-more v-if="store.status == 'loading' || (store.data && store.data.length > 0)"
:status="store.status"></uni-load-more>
<Cn-empty v-else style="top: 20%"></Cn-empty>
</scroll-view>
</view>
</template>
<script>
import list from '@/common/js/list'
import { updateStatus } from '@/common/api/message'
export default {
components: {},
props: {
navHeight: {
type: Number,
default: 0,
},
selectValue: {
type: Object,
// default: () => {},
},
},
mixins: [list],
data() {
return {
triggered: true,
}
},
mounted() { },
methods: {
// 查詢
init() {
this.store = this.DataSource('/cs-harmonic-boot/eventUser/queryEventpage')
this.store.params.type = 2
// this.store.params.pageSize = 10000
this.store.params.sortField = this.sort
this.store.params.engineeringid = this.selectValue.engineeringId
this.store.params.projectId = this.selectValue.projectId
this.store.params.deviceId = this.selectValue.deviceId
this.store.params.lineId = this.selectValue.lineId
this.store.params.startTime = this.$util.getMonthFirstAndLastDay(this.selectValue.date).firstDay
this.store.params.endTime = this.$util.getMonthFirstAndLastDay(this.selectValue.date).lastDay
this.store.loadedCallback = () => {
this.loading = false
}
this.store.reload()
},
jump(item) {
if (item.status != '1') {
item.status = '1'
updateStatus({
eventIds: [item.id],
})
this.$emit('getDevCount')
}
},
// 下拉
refresherrefresh() {
this.triggered = true
uni.startPullDownRefresh()
setTimeout(() => {
this.triggered = false
}, 500)
},
// 上拉
scrolltolower() {
if (this.store.status != 'noMore') {
this.store.next && this.store.next()
}
},
},
computed: {},
watch: {
selectValue: {
handler(val, oldVal) {
if (Object.keys(val).length === 0) return
this.init()
},
deep: true,
immediate: true,
},
},
}
</script>
<style lang="scss" scoped>
@import './index.scss';
/* 列表容器 */
.event-list {
margin-top: 20rpx;
/* 头部:图标 + 信息 + 操作 */
/* 图标区域(按类型区分背景色) */
.zl-bgc {
background-color: #376cf320;
}
.jc-bgc {
background-color: #376cf320;
}
.zl-tag {
background-color: #007aff20;
color: #007aff;
}
.jc-tag {
background-color: #007aff20;
color: #007aff;
}
}
/deep/ .uni-scroll-view-refresher {
display: none;
}
</style>

View File

@@ -0,0 +1,375 @@
<template>
<view style="position: relative">
<!-- 稳态 -->
<view class="transientBox">
<view class="statistics pd20">
<view
class="box"
:class="{ boxClick: item.label == filterValue }"
v-for="item in list"
@click="
filterValue = item.label
init()
"
>
<text class="num">{{ item.value }}</text>
<text class="label">{{ item.label }}</text>
</view>
</view>
</view>
<!-- 稳态数量 -->
<scroll-view
v-if="filterValue == '稳态数量'"
scroll-y="true"
@refresherrefresh="refresherrefresh"
@scrolltolower="scrolltolower"
:refresher-triggered="triggered"
refresher-enabled="true"
class="event-list"
:style="{ height: 'calc(100vh - ' + (navHeight + height) + 'px)', overflow: 'auto' }"
>
<!-- 循环渲染事件项 -->
<uni-card
class="event-item boxClick"
:class="item.type"
v-for="(item, index) in store.data"
:key="index"
@click="jump(item)"
>
<!-- 头部图标 + 信息 + 操作 -->
<view class="event-header">
<view class="event-icon">
<!-- 动态图标根据类型切换 -->
<!-- <uni-icons
custom-prefix="iconfont"
type="icon-kouanjiancedian"
size="40"
color="#E6A23C"
></uni-icons> -->
<Cn-icon-transient :name="`稳态越限`" />
<view class="badge1" v-if="item.isRead == 0"> </view>
</view>
<view class="event-info">
<view class="event-title">
<text class="event-id">{{ item.lineName }}</text>
</view>
<view class="event-desc">
<text>工程名称{{ item.engineeringName }}</text>
<text>项目名称{{ item.projectName }}</text>
<text>设备名称{{ item.devName }}</text>
<!-- <text>统计日期{{ item.statisticsDate }}</text> -->
</view>
</view>
<view class="event-action">
<!-- <uni-icons type="search" size="25" color="#376cf3"></uni-icons> -->
🔍
</view>
</view>
<!-- 详情区域 -->
<view class="event-detail textBox" @touchmove.stop>
<text>{{ item.statisticsDate }}发生 {{ item.overLimitDesc }} </text>
</view>
</uni-card>
<uni-load-more
v-if="store.status == 'loading' || (store.data && store.data.length > 0)"
:status="store.status"
></uni-load-more>
<Cn-empty v-else style="top: 20%"></Cn-empty>
</scroll-view>
<!-- 越限天数 -->
<view v-if="filterValue == '越限天数'">
<uni-calendar
:insert="true"
:lunar="false"
:date="startData"
:selected="selected"
:start-date="startData"
:end-date="endData"
/>
</view>
<!-- 越限测点数 -->
<scroll-view
v-if="filterValue == '越限测点数'"
scroll-y="true"
@refresherrefresh="refresherrefresh"
@scrolltolower="scrolltolower"
:refresher-triggered="triggered"
refresher-enabled="true"
class="event-list"
:style="{ height: 'calc(100vh - ' + (navHeight + height) + 'px)', overflow: 'auto' }"
>
<!-- 循环渲染事件项 -->
<uni-card class="event-item" :class="item.type" v-for="(item, index) in store.data" :key="index">
<!-- 头部图标 + 信息 + 操作 -->
<view class="event-header">
<view class="event-icon">
<!-- 动态图标根据类型切换 -->
<!-- <uni-icons
custom-prefix="iconfont"
type="icon-kouanjiancedian"
size="40"
color="#E6A23C"
></uni-icons> -->
<Cn-icon-transient :name="`稳态越限`" />
</view>
<view class="event-info">
<view class="event-title">
<text class="event-id">{{ item.lineName }}</text>
</view>
<view class="event-desc">
<text>工程名称{{ item.engineeringName }}</text>
<text>项目名称{{ item.projectName }}</text>
<text>设备名称{{ item.devName }}</text>
<!-- <text>统计日期{{ item.statisticsDate }}</text> -->
</view>
</view>
</view>
<!-- 详情区域 -->
<view class="event-detail">
<uni-calendar
:insert="true"
:lunar="false"
:date="startData"
:selected="item.timeList.map((date) => ({ date, info: '' }))"
:start-date="startData"
:end-date="endData"
/>
</view>
</uni-card>
<uni-load-more
v-if="store.status == 'loading' || (store.data && store.data.length > 0)"
:status="store.status"
></uni-load-more>
<Cn-empty v-else style="top: 20%"></Cn-empty>
</scroll-view>
</view>
</template>
<script>
import list from '@/common/js/list'
import { queryAppHarmonicCounts, queryAppHarmonicLine } from '../../common/api/harmonic.js'
export default {
components: {},
props: {
navHeight: {
type: Number,
default: 0,
},
selectValue: {
type: Object,
// default: () => {},
},
},
mixins: [list],
data() {
return {
height: 0,
filterValue: '稳态数量',
list: [
{ value: 0, label: '稳态数量' },
{ value: 0, label: '越限天数' },
{ value: 0, label: '越限测点数' },
],
startData: '',
endData: '',
selected: [
// { date: '2026-04-10', info: '' },
// { date: '2026-04-11', info: '' },
// { date: '2026-04-12', info: '' },
],
triggered: true,
status: 'noMore', //more加载前 loading加载中 noMore加载后
}
},
mounted() {
uni.createSelectorQuery()
.select('.transientBox')
.boundingClientRect((rect) => {
//
// #ifdef H5
this.height = rect.height
// #endif
// #ifdef APP-PLUS
this.height = rect.height
// #endif
})
.exec()
},
methods: {
// "devId": "",
// "engineerId": "",
// "lineId": "",
// "projectId": "",
// "time": ""
// 查詢
init() {
if (this.filterValue == '越限测点数') {
this.store = this.DataSource('/cs-harmonic-boot/csHarmonic/queryAppHarmonicLine')
} else {
this.store = this.DataSource('/cs-harmonic-boot/csHarmonic/queryHarmonicList')
}
// this.store.params.pageSize = 10000
this.store.params.engineerId = this.selectValue.engineeringId
this.store.params.projectId = this.selectValue.projectId
this.store.params.devId = this.selectValue.deviceId
this.store.params.lineId = this.selectValue.lineId
this.store.params.time = this.selectValue.date
this.store.loadedCallback = () => {
this.loading = false
this.startData = this.$util.getMonthFirstAndLastDay(this.selectValue.date).firstDay
this.endData = this.$util.getMonthFirstAndLastDay(this.selectValue.date).lastDay
// 查询越限日期
queryAppHarmonicCounts(this.store.params).then((res) => {
this.list[0].value = res.data.harmonicNums
this.list[1].value = res.data.overDays
this.list[2].value = res.data.overLineNums
this.selected = res.data.overDaysList.map((date) => ({ date, info: '' }))
})
}
this.store.reload()
},
jump(item) {
let str = JSON.stringify(item).replace(/%/g, '百分比')
item.status = '1'
uni.navigateTo({ url: '/pages/message1/comp/steadyStateDetails?detail=' + encodeURIComponent(str) })
},
// 下拉
refresherrefresh() {
this.triggered = true
uni.startPullDownRefresh()
setTimeout(() => {
this.triggered = false
}, 500)
},
// 上拉
scrolltolower() {
if (this.store.status != 'noMore') {
this.store.next && this.store.next()
}
},
},
computed: {},
watch: {
selectValue: {
handler(val, oldVal) {
if (Object.keys(val).length === 0) return
this.init()
},
deep: true,
immediate: true,
},
},
}
</script>
<style lang="scss" scoped>
@import './index.scss';
.box:first-child {
flex: 1.3 !important;
}
/* 列表容器 */
.event-list {
/* 头部:图标 + 信息 + 操作 */
.event-header {
display: flex;
align-items: center;
margin-bottom: 10rpx;
}
/* 图标区域(按类型区分背景色) */
.event-icon {
background-color: #376cf320;
}
.event-tags {
font-size: 24rpx;
}
}
/deep/ .uni-scroll-view-refresher {
display: none;
}
.textBox {
max-height: 110rpx;
overflow-y: auto;
// overflow: hidden;
/* 下面是溢出显示省略号关键样式 */
// display: -webkit-box;
// -webkit-line-clamp: 3; /* 控制最多显示几行,你可以改 2/3/4 */
// -webkit-box-orient: vertical;
// text-overflow: ellipsis;
// word-break: break-all;
}
/deep/ .uni-calendar-item--checked {
background-color: #ffffff00;
color: #000000e6;
opacity: 1;
}
/deep/ .uni-calendar-item--isDay {
background-color: #ffffff00;
color: #000000e6;
opacity: 1;
.uni-calendar-item__weeks-lunar-text {
background-color: #ffffff00;
color: #000000e6;
opacity: 1;
}
}
/deep/ .uni-calendar-item__weeks-box-text {
z-index: 1;
}
/deep/ .uni-calendar-item--isDay-text {
color: #333 !important; /* 改成你想要的颜色 */
}
/deep/ .uni-calendar-item__weeks-box-circle {
position: absolute;
top: 7px;
right: 6px;
width: 39px;
height: 39px;
border-radius: 50%;
z-index: 0;
background-color: #e6a23c;
}
/* 核心:选中圆圈下的 子元素(日期数字) */
/deep/ .uni-calendar-item__weeks-box-circle + .uni-calendar-item__weeks-box-text {
color: #fff !important; /* 改成你想要的颜色 */
}
/deep/ .uni-calendar__backtoday,
/deep/ .uni-calendar__header-btn-box {
display: none;
}
/deep/ .uni-calendar-item__weeks-lunar-text {
display: none;
}
/deep/ .uni-calendar__header {
pointer-events: none !important;
}
.event-detail {
/deep/ .uni-calendar__header {
display: none !important;
}
/deep/ .uni-calendar__weeks-day {
height: 35px;
}
/deep/ .uni-calendar-item__weeks-box-item {
height: 40px;
}
/deep/ .uni-calendar-item__weeks-box-circle {
position: absolute;
top: 3px;
right: 8px;
width: 35px;
height: 35px;
}
}
</style>

View File

@@ -0,0 +1,333 @@
<template>
<view style="position: relative">
<!-- 暂态 -->
<view class="transientBox">
<view class="statistics pd20">
<view
class="box boxClick"
:class="{ boxClick1: filterValue == index }"
v-for="(item, index) in dataList"
@click="
filterValue = index
init()
"
>
<!-- <text class="num">{{ item.value }}</text> -->
<text class="num">{{ item.value }}</text>
<text class="label">{{ item.label }}</text>
</view>
</view>
<view class="smallLabel">
<uni-segmented-control
:current="curSub"
active-color="#376cf3"
:values="subsectionList"
@clickItem="sectionChange"
v-if="subsectionList.length > 1"
/>
<view style="width: 180rpx">
<picker @change="bindPickerChange" :value="sort" :range="array" v-if="curSub == 0">
<view class="uni-input"
>{{ array[sort] }}排序
<uni-icons
custom-prefix="iconfont"
type="icon-paixu1"
size="10"
color="#2563EB"
></uni-icons>
</view>
</picker>
</view>
</view>
</view>
<!-- 卡片 -->
<scroll-view
scroll-y="true"
@refresherrefresh="refresherrefresh"
@scrolltolower="scrolltolower"
:refresher-triggered="triggered"
refresher-enabled="true"
class="event-list"
v-if="curSub == 0"
:style="{ height: 'calc(100vh - ' + (navHeight + height) + 'px)', overflow: 'auto' }"
>
<!-- 循环渲染事件项 -->
<uni-card
class="event-item boxClick"
:class="judgment(item.showName).type"
v-for="(item, index) in store.data || []"
:key="index"
@click="jump(item)"
>
<!-- 头部图标 + 信息 + 操作 -->
<view class="event-header">
<view class="event-icon">
<!-- 动态图标根据类型切换 -->
<!-- <uni-icons
:custom-prefix="'iconfont'"
:type="judgment(item.showName).icon"
:color="judgment(item.showName).color"
:size="judgment(item.showName).size"
></uni-icons> -->
<Cn-icon-transient :name="item.showName" />
<!-- 0未读 1已读 -->
<view class="badge1" v-if="item.status == 0"> </view>
</view>
<view class="event-info">
<view class="event-title">
<text class="event-id">{{ item.lineName }}</text>
<text class="event-tag" :class="`${judgment(item.showName).type}-tag`">{{
item.showName
}}</text>
</view>
<view class="event-desc">
<text>工程名称{{ item.engineeringName }}</text>
<text>项目名称{{ item.projectName }}</text>
<text>设备名称{{ item.equipmentName }}</text>
</view>
</view>
<view class="event-action">
<!-- <uni-icons type="search" size="25" color="#376cf3"></uni-icons> -->
🔍
</view>
</view>
<!-- 详情区域 -->
<view class="event-detail">
<text>
{{ item.startTime ? '发生时间:' + item.startTime : '' }}
{{
item.evtParamVVaDepth != null && item.evtParamVVaDepth !== ''
? ',幅值:' + item.evtParamVVaDepth + '%'
: ''
}}
{{
item.evtParamTm != null && item.evtParamTm !== ''
? ',持续时间:' + item.evtParamTm + 's'
: ''
}}
{{
item.evtParamPhase != null && item.evtParamPhase !== ''
? ',相别:' + item.evtParamPhase
: ''
}}
</text>
</view>
</uni-card>
<uni-load-more
v-if="store.status == 'loading' || (store.data && store.data.length > 0)"
:status="store.status"
></uni-load-more>
<Cn-empty v-else style="top: 20%"></Cn-empty>
</scroll-view>
<!-- ITIC 列表 -->
<ITIC
v-if="subsectionList[curSub] == 'ITIC'"
:store="store"
:style="{ height: 'calc(100vh - ' + (navHeight + height) + 'px)', overflow: 'auto' }"
></ITIC>
<!-- F47 列表 -->
<F47
v-if="subsectionList[curSub] == 'F47'"
:store="store"
:style="{ height: 'calc(100vh - ' + (navHeight + height) + 'px)', overflow: 'auto' }"
></F47>
</view>
</template>
<script>
import list from '@/common/js/list'
import { queryUserPushConfig } from '@/common/api/mine'
import ITIC from './comp/ITIC.vue'
import F47 from './comp/F47.vue'
import { queryAppEventCounts } from '../../common/api/harmonic.js'
export default {
components: { ITIC, F47 },
props: {
navHeight: {
type: Number,
default: 0,
},
selectValue: {
type: Object,
// default: () => {},
},
},
mixins: [list],
data() {
return {
height: 0,
filterValue: 0,
dataList: [
{ value: 0, label: '暂态数量', key: '' },
{ value: 0, label: '暂降', key: '电压暂降' },
{ value: 0, label: '中断', key: '电压中断' },
{ value: 0, label: '暂升', key: '电压暂升' },
],
curSub: 0,
subsectionList: [], //'列表', 'ITIC', 'F47'
status: 'noMore', //more加载前 loading加载中 noMore加载后
sort: 0,
triggered: true,
// config: {},
array: ['发生时间', '暂降深度', '持续时间'],
}
},
mounted() {
this.getConfig()
},
methods: {
getHeight() {
uni.createSelectorQuery()
.select('.transientBox')
.boundingClientRect((rect) => {
//
// #ifdef H5
this.height = rect?.height || 0
// #endif
// #ifdef APP-PLUS
this.height = rect?.height || 0
// #endif
})
.exec()
},
// 查詢
init() {
this.store = this.DataSource('/cs-harmonic-boot/eventUser/queryEventpage')
this.store.params.type = 0
// this.store.params.pageSize = 10000
this.store.params.sortField = this.sort
this.store.params.engineeringid = this.selectValue.engineeringId
this.store.params.projectId = this.selectValue.projectId
this.store.params.deviceId = this.selectValue.deviceId
this.store.params.lineId = this.selectValue.lineId
this.store.params.target =
this.filterValue == 0
? []
: this.filterValue == 1
? ['Evt_Sys_DipStr']
: this.filterValue == 2
? ['Evt_Sys_IntrStr']
: ['Evt_Sys_SwlStr']
this.store.params.startTime = this.$util.getMonthFirstAndLastDay(this.selectValue.date).firstDay
this.store.params.endTime = this.$util.getMonthFirstAndLastDay(this.selectValue.date).lastDay
this.store.loadedCallback = () => {
this.getHeight()
this.loading = false
queryAppEventCounts(this.store.params).then((res) => {
this.dataList[0].value = res.data.allNum
this.dataList[1].value = res.data.eventDown
this.dataList[2].value = res.data.eventOff
this.dataList[3].value = res.data.eventUp
})
}
this.store.reload()
},
getConfig() {
queryUserPushConfig().then((res) => {
// this.config = res.data
let list = [
'列表',
res.data.iticFunction == 1 ? 'ITIC' : '',
res.data.f47Function == 1 ? 'F47' : '',
].filter((item) => item)
this.curSub = !list[this.curSub] ? 0 : this.curSub
this.subsectionList = JSON.parse(JSON.stringify(list))
})
},
judgment(val, key) {
switch (val) {
case '电压暂降':
return {
type: 'sag',
icon: 'icon-a-svg4',
color: '#2563eb',
size: '25',
}
case '电压暂升':
return {
type: 'swell',
icon: 'icon-a-svg5',
color: '#e6a23c',
size: '25',
}
case '电压中断':
return {
type: 'interrupt',
icon: 'icon-zhongduan2',
color: '#6b7280',
size: '35',
}
case '瞬态':
return {
type: 'transient',
icon: 'icon-shuntaishijian',
color: '#8b5cf6',
size: '40',
}
case '未知':
return {
type: 'unknown',
icon: 'icon-wenhao',
color: '#6b7280',
size: '45',
}
}
},
// 点击查看详情
jump(item) {
let str = JSON.stringify(item).replace(/%/g, '百分比')
item.status = '1'
uni.navigateTo({ url: '/pages/message1/comp/transientDetails?detail=' + encodeURIComponent(str) })
},
// 切换排序
bindPickerChange(e) {
this.sort = e.detail.value
this.init()
},
sectionChange(e) {
this.curSub = e.currentIndex
},
// 下拉
refresherrefresh() {
this.triggered = true
uni.startPullDownRefresh()
setTimeout(() => {
this.triggered = false
}, 500)
},
// 上拉
scrolltolower() {
if (this.store.status != 'noMore') {
this.store.next && this.store.next()
}
},
},
onShow() {
this.curSub = 0
},
computed: {},
watch: {
selectValue: {
handler(val, oldVal) {
if (Object.keys(val).length === 0) return
this.init()
},
deep: true,
immediate: true,
},
},
}
</script>
<style lang="scss" scoped>
@import './index.scss';
/deep/ .uni-scroll-view-refresher {
display: none;
}
</style>

View File

@@ -1,50 +1,50 @@
<template> <template>
<Cn-page :loading="loading"> <Cn-page :loading="loading">
<view slot="body"> <view slot="body">
<view class="about"> <view class="about">
<image src="/static/logo.png" class="logo"></image> <image src="/static/logo.png" class="logo"></image>
<view class="name">灿能物联</view> <view class="name">灿能物联</view>
<view class="version">Version 1.6.1</view> <view class="version">Version 1.6.7</view>
</view> </view>
</view> </view>
</Cn-page> </Cn-page>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
loading: false, loading: false,
} }
}, },
methods: {}, methods: {},
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.about { .about {
box-sizing: border-box; box-sizing: border-box;
padding: 34rpx; padding: 34rpx;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
overflow: hidden; overflow: hidden;
.logo { .logo {
margin-top: 200rpx; margin-top: 200rpx;
height: 120rpx; height: 120rpx;
width: 120rpx; width: 120rpx;
} }
.name { .name {
margin-top: 80rpx; margin-top: 80rpx;
font-size: 40rpx; font-size: 40rpx;
font-weight: 700; font-weight: 700;
color: #333; color: #333;
} }
.version { .version {
margin-top: 20rpx; margin-top: 20rpx;
font-size: 38rpx; font-size: 38rpx;
color: #333; color: #333;
} }
} }
</style> </style>

View File

@@ -1,123 +1,123 @@
<template> <template>
<Cn-page :loading="loading"> <Cn-page :loading="loading">
<view class="mine" slot="body"> <view class="mine" slot="body">
<view class="mine-nav" style="margin-top: 20rpx"> <view class="mine-nav" style="margin-top: 20rpx">
<view class="mine-nav-label">功能调试</view> <view class="mine-nav-label">功能调试</view>
<switch <switch
style="transform: scale(0.8)" style="transform: scale(0.8)"
color="#376cf3" color="#376cf3"
@change="change('feature')" @change="change('feature')"
:checked="config.feature" :checked="config.feature"
/> />
</view> </view>
<view class="mine-nav" style="border-bottom: none"> <view class="mine-nav" style="border-bottom: none">
<view class="mine-nav-label">出厂调试</view> <view class="mine-nav-label">出厂调试</view>
<switch <switch
style="transform: scale(0.8)" style="transform: scale(0.8)"
color="#376cf3" color="#376cf3"
@change="change('factory')" @change="change('factory')"
:checked="config.factory" :checked="config.factory"
/> />
</view> </view>
</view> </view>
</Cn-page> </Cn-page>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
loading: true, loading: true,
config: { config: {
feature: true, feature: true,
factory: true, factory: true,
}, },
} }
}, },
methods: { methods: {
init() { init() {
let serverConfig = uni.getStorageSync(this.$cacheKey.serverConfig) let serverConfig = uni.getStorageSync(this.$cacheKey.serverConfig)
serverConfig && (this.config = serverConfig) serverConfig && (this.config = serverConfig)
this.loading = false this.loading = false
}, },
change(type) { change(type) {
this.config[type] = !this.config[type] this.config[type] = !this.config[type]
let str = '' let str = ''
switch (type) { switch (type) {
case 'feature': case 'feature':
str = '功能调试' str = '功能调试'
break break
case 'factory': case 'factory':
str = '出厂调试' str = '出厂调试'
break break
} }
this.$util.toast(`${str}首页入口${this.config[type] ? '开启' : '关闭'}`, 2500) this.$util.toast(`${str}首页入口${this.config[type] ? '开启' : '关闭'}`, 2500)
uni.setStorage({ uni.setStorage({
key: this.$cacheKey.serverConfig, key: this.$cacheKey.serverConfig,
data: this.config, data: this.config,
}) })
}, },
}, },
onLoad() { onLoad() {
this.init() this.init()
}, },
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.mine { .mine {
.title { .title {
padding: 0 20rpx; padding: 0 20rpx;
font-size: 28rpx; font-size: 28rpx;
font-weight: 500; font-weight: 500;
} }
.mine-header { .mine-header {
padding: 200rpx 34rpx 34rpx; padding: 200rpx 34rpx 34rpx;
display: flex; display: flex;
align-items: center; align-items: center;
background: $uni-theme-white; background: $uni-theme-white;
margin-bottom: 20rpx; margin-bottom: 20rpx;
box-shadow: 0 4rpx 8rpx #e7e7e74c; box-shadow: 0 4rpx 8rpx #e7e7e74c;
.mine-header-head { .mine-header-head {
margin-right: 30rpx; margin-right: 30rpx;
height: 128rpx; height: 128rpx;
width: 128rpx; width: 128rpx;
border-radius: $uni-theme-radius; border-radius: $uni-theme-radius;
overflow: hidden; overflow: hidden;
} }
.mine-header-name { .mine-header-name {
margin-right: 30rpx; margin-right: 30rpx;
flex: 1; flex: 1;
font-size: 36rpx; font-size: 36rpx;
color: #111; color: #111;
font-weight: 700; font-weight: 700;
} }
} }
.mine-nav { .mine-nav {
padding: 34rpx; padding: 34rpx;
display: flex; display: flex;
align-items: center; align-items: center;
background: $uni-theme-white; background: $uni-theme-white;
border-bottom: 1rpx solid #e8e8e8; border-bottom: 1rpx solid #e8e8e8;
&-icon { &-icon {
margin-right: 30rpx; margin-right: 30rpx;
height: 44rpx; height: 44rpx;
width: 44rpx; width: 44rpx;
border-radius: $uni-theme-radius; border-radius: $uni-theme-radius;
overflow: hidden; overflow: hidden;
} }
&-label { &-label {
margin-right: 30rpx; margin-right: 30rpx;
flex: 1; flex: 1;
font-size: 28rpx; font-size: 28rpx;
color: #111; color: #111;
} }
} }
} }
</style> </style>

View File

@@ -1,174 +1,183 @@
<template> <template>
<view :loading="loading"> <view :loading="loading">
<view class="mine"> <view class="mine">
<view class="mine-nav" @click="jump('changePhone')" style="box-shadow: 0 4rpx 8rpx #e7e7e74c"> <view class="mine-nav" @click="jump('changePhone')" style="box-shadow: 0 4rpx 8rpx #e7e7e74c">
<view class="mine-nav-label">更换手机号</view> <view class="mine-nav-label">更换手机号</view>
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
</view> </view>
<view class="mine-nav" @click="jump('changePwd')"> <view class="mine-nav" @click="jump('changePwd')">
<view class="mine-nav-label">修改密码</view> <view class="mine-nav-label">修改密码</view>
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
</view> </view>
<view class="mine-nav" @click="jump('deleteUser')" style="border-bottom: none"> <view class="mine-nav" @click="jump('deleteUser')" style="border-bottom: none">
<view class="mine-nav-label">账号注销</view> <view class="mine-nav-label">账号注销</view>
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
</view> </view>
<!-- <view class="mine-nav" @click="jump('setupMessage')" style="margin-top:20rpx;border-bottom: none; "> <!-- <view class="mine-nav" @click="jump('setupMessage')" style="margin-top:20rpx;border-bottom: none; ">
<view class="mine-nav-label">消息配置</view> <view class="mine-nav-label">消息配置</view>
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
</view> --> </view> -->
<view class="mine-nav" @click="jump('agreement')" style="margin-top: 20rpx"> <view class="mine-nav" @click="jump('agreement')" style="margin-top: 20rpx">
<view class="mine-nav-label">用户协议</view> <view class="mine-nav-label">用户协议</view>
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
</view> </view>
<view class="mine-nav" @click="jump('policy')"> <view class="mine-nav" @click="jump('policy')">
<view class="mine-nav-label">隐私政策</view> <view class="mine-nav-label">隐私政策</view>
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
</view> </view>
<view class="mine-nav" @click="jump('system')"> <view class="mine-nav" @click="jump('system')">
<view class="mine-nav-label">系统介绍</view> <view class="mine-nav-label">系统介绍</view>
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
</view> </view>
<view class="mine-nav" @click="jump('book')"> <view class="mine-nav" @click="jump('book')">
<view class="mine-nav-label">使用手册</view> <view class="mine-nav-label">使用手册</view>
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
</view> </view>
<!-- <view class="mine-nav" @click="jump('database')"> <!-- <view class="mine-nav" @click="jump('database')">
<view class="mine-nav-label">资料库</view> <view class="mine-nav-label">资料库</view>
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
</view> --> </view> -->
<view class="mine-nav" @click="jump('company')"> <view class="mine-nav" @click="jump('company')">
<view class="mine-nav-label">公司介绍</view> <view class="mine-nav-label">公司介绍</view>
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
</view> </view>
<!-- <view class="mine-nav" @click="jump('feedback')"> <!-- <view class="mine-nav" @click="jump('feedback')">
<view class="mine-nav-label">意见反馈</view> <view class="mine-nav-label">意见反馈</view>
<uni-icons type="forward" color="#aaa" size="20"></uni-icons> <uni-icons type="forward" color="#aaa" size="20"></uni-icons>
</view> --> </view> -->
<!-- @click="jump('about')" --> <!-- @click="jump('about')" -->
<view class="mine-nav" style="border-bottom: none"> <view class="mine-nav" style="border-bottom: none">
<view class="mine-nav-label">版本信息</view> <view class="mine-nav-label">版本信息</view>
<view style="color: #828282;font-size: 14rpx;">当前版本V1.6.2</view> <view style="color: #828282; font-size: 14rpx">当前版本V{{ version }}</view>
<!-- <uni-icons type="forward" color="#aaa" size="20"></uni-icons> --> <!-- <uni-icons type="forward" color="#aaa" size="20"></uni-icons> -->
</view> </view>
<view class="mine-nav" @click="jump('layout')" style="margin-top: 20rpx; border-bottom: none"> <view class="mine-nav" @click="jump('layout')" style="margin-top: 20rpx; border-bottom: none">
<view class="mine-nav-label" style="text-align: center">退出登录</view> <view class="mine-nav-label" style="text-align: center">退出登录</view>
</view> </view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import { queryPersonSet } from '@/common/api/mine.js' import { queryPersonSet } from '@/common/api/mine.js'
export default { export default {
data() { data() {
return { return {
loading: false, loading: false,
} version: '1.0.0',
}, }
methods: { },
async init() {}, methods: {
jump(type) { async init() {
switch (type) { const isDev = process.env.NODE_ENV === 'development'
case 'changePwd': if (isDev) {
uni.navigateTo({ return console.log('开发环境,不执行更新检查')
url: `/pages/user/changePwd`, }
}) plus.runtime.getProperty(plus.runtime.appid, (info) => {
break this.version = info.version // 当前本地版本号
case 'changePhone': })
uni.navigateTo({ },
url: `/pages/user/changePhone`, jump(type) {
}) switch (type) {
break case 'changePwd':
case 'book': uni.navigateTo({
uni.openDocument({ url: `/pages/user/changePwd`,
filePath: '/static/user_manual.docx', })
success: function (res) { break
console.log('打开文档成功') case 'changePhone':
}, uni.navigateTo({
}) url: `/pages/user/changePhone`,
break })
case 'layout': break
uni.showModal({ case 'book':
title: '提示', uni.openDocument({
content: '是否确认退出登录?', filePath: '/static/user_manual.docx',
success: (res) => { success: function (res) {
if (res.confirm) { console.log('打开文档成功')
uni.removeStorageSync(this.$cacheKey.messageCount) },
// #ifdef APP-PLUS })
plus.runtime.setBadgeNumber(0) break
// #endif case 'layout':
uni.reLaunch({ uni.showModal({
url: `/pages/user/login`, title: '提示',
}) content: '是否确认退出登录?',
} success: (res) => {
}, if (res.confirm) {
}) uni.removeStorageSync(this.$cacheKey.messageCount)
break // #ifdef APP-PLUS
default: plus.runtime.setBadgeNumber(0)
uni.navigateTo({ // #endif
url: `/pages/mine/${type}`, uni.reLaunch({
}) url: `/pages/user/login`,
break })
} }
}, },
}, })
onLoad() { break
this.init() default:
}, uni.navigateTo({
} url: `/pages/mine/${type}`,
</script> })
break
<style lang="scss"> }
.mine { },
padding-top: 20rpx; },
onLoad() {
.mine-header { this.init()
padding: 200rpx 34rpx 34rpx; },
display: flex; }
align-items: center; </script>
background: $uni-theme-white;
margin-bottom: 20rpx; <style lang="scss">
box-shadow: 0 4rpx 8rpx #e7e7e74c; .mine {
padding-top: 20rpx;
.mine-header-head {
margin-right: 30rpx; .mine-header {
height: 128rpx; padding: 200rpx 34rpx 34rpx;
width: 128rpx; display: flex;
border-radius: $uni-theme-radius; align-items: center;
overflow: hidden; background: $uni-theme-white;
} margin-bottom: 20rpx;
box-shadow: 0 4rpx 8rpx #e7e7e74c;
.mine-header-name {
margin-right: 30rpx; .mine-header-head {
flex: 1; margin-right: 30rpx;
font-size: 36rpx; height: 128rpx;
color: #111; width: 128rpx;
font-weight: 700; border-radius: $uni-theme-radius;
} overflow: hidden;
} }
.mine-nav { .mine-header-name {
padding: 34rpx; margin-right: 30rpx;
display: flex; flex: 1;
align-items: center; font-size: 36rpx;
background: $uni-theme-white; color: #111;
border-bottom: 1rpx solid #e8e8e8; font-weight: 700;
}
&-icon { }
margin-right: 30rpx;
height: 44rpx; .mine-nav {
width: 44rpx; padding: 34rpx;
border-radius: $uni-theme-radius; display: flex;
overflow: hidden; align-items: center;
} background: $uni-theme-white;
border-bottom: 1rpx solid #e8e8e8;
&-label {
margin-right: 30rpx; &-icon {
flex: 1; margin-right: 30rpx;
font-size: 28rpx; height: 44rpx;
color: #111; width: 44rpx;
} border-radius: $uni-theme-radius;
} overflow: hidden;
} }
</style>
&-label {
margin-right: 30rpx;
flex: 1;
font-size: 28rpx;
color: #111;
}
}
}
</style>

View File

@@ -1,147 +1,170 @@
<template> <template>
<Cn-page :loading="loading"> <Cn-page :loading="loading">
<view class="mine" slot="body"> <view class="mine" slot="body">
<view class="mine-nav" style="margin-top: 20rpx"> <view class="mine-nav mt20" style="border-bottom: none">
<view class="mine-nav-label">运行事件</view> <view class="mine-nav-label">暂态事件</view>
<switch style="transform: scale(0.8)" color="#376cf3" @change="change('runInfo')" :checked="config.runInfo === 1"/> <switch
</view> style="transform: scale(0.8)"
<view class="mine-nav" style="border-bottom: none"> color="#376cf3"
<view class="mine-nav-label">暂态事件</view> @change="change('eventInfo')"
<switch style="transform: scale(0.8)" color="#376cf3" @change="change('eventInfo')" :checked="config.eventInfo === 1"/> :checked="config.eventInfo === 1"
</view> />
<view class="mine-nav" style="border-bottom: none"> </view>
<view class="mine-nav-label">稳态事件</view> <view class="mine-nav" style="border-bottom: none">
<switch style="transform: scale(0.8)" color="#376cf3" @change="change('harmonicInfo')" :checked="config.harmonicInfo === 1"/> <view class="mine-nav-label">稳态事件</view>
</view> <switch
<view class="mine-nav" style="border-bottom: none"> style="transform: scale(0.8)"
<view class="mine-nav-label">设备告警</view> color="#376cf3"
<switch style="transform: scale(0.8)" color="#376cf3" @change="change('alarmInfo')" :checked="config.alarmInfo === 1"/> @change="change('harmonicInfo')"
</view> :checked="config.harmonicInfo === 1"
</view> />
</Cn-page> </view>
</template> <view class="mine-nav" style="border-bottom: none">
<view class="mine-nav-label">运行告警</view>
<script> <switch
import {queryUserPushConfig, updatePushConfig} from '@/common/api/mine' style="transform: scale(0.8)"
color="#376cf3"
export default { @change="change('alarmInfo')"
data() { :checked="config.alarmInfo === 1"
return { />
loading: true, </view>
config: {}, <view class="mine-nav" >
} <view class="mine-nav-label">运行事件</view>
}, <switch
methods: { style="transform: scale(0.8)"
init() { color="#376cf3"
queryUserPushConfig().then(res => { @change="change('runInfo')"
console.log(123123,res); :checked="config.runInfo === 1"
this.config = res.data />
console.log(this.config) </view>
</view>
this.loading = false </Cn-page>
}) </template>
},
change(type) { <script>
this.config[type] = this.config[type] === 1 ? 0 : 1 import { queryUserPushConfig, updatePushConfig } from '@/common/api/mine'
updatePushConfig(this.config).then(res => {
let str = '' export default {
switch (type){ data() {
case 'runInfo': return {
str = '运行事件' loading: true,
break config: {},
case 'eventInfo': }
str = '暂态事件' },
break methods: {
case 'harmonicInfo': init() {
str = '稳态事件' queryUserPushConfig().then((res) => {
break this.config = res.data
case 'alarmInfo':
str = '设备告警' this.loading = false
break })
} },
this.$util.toast(`${str}推送${this.config[type] === 1 ? '开启' : '关闭'}成功`) change(type) {
}) this.config[type] = this.config[type] === 1 ? 0 : 1
}, // updatePushConfig(this.config).then((res) => {
jump(type) { // let str = ''
switch (type) { // switch (type) {
case 'changePwd': // case 'runInfo':
uni.navigateTo({ // str = '运行事件'
url: `/pages/user/changePwd`, // break
}) // case 'eventInfo':
break // str = '暂态事件'
case 'changePhone': // break
uni.navigateTo({ // case 'harmonicInfo':
url: `/pages/user/changePhone`, // str = '稳态事件'
}) // break
break // case 'alarmInfo':
default: // str = '设备告警'
uni.navigateTo({ // break
url: `/pages/mine/${type}`, // }
}) // this.$util.toast(`${str}推送${this.config[type] === 1 ? '开启' : '关闭'}成功`)
break // })
} },
}, jump(type) {
}, switch (type) {
onLoad() { case 'changePwd':
this.init() uni.navigateTo({
}, url: `/pages/user/changePwd`,
} })
</script> break
case 'changePhone':
<style lang="scss"> uni.navigateTo({
.mine { url: `/pages/user/changePhone`,
.title { })
padding: 0 20rpx; break
font-size: 28rpx; default:
font-weight: 500; uni.navigateTo({
} url: `/pages/mine/${type}`,
})
.mine-header { break
padding: 200rpx 34rpx 34rpx; }
display: flex; },
align-items: center; onUnload() {
background: $uni-theme-white; updatePushConfig(this.config).then((res) => {
margin-bottom: 20rpx; // this.$util.toast(`配置修改成功!`)
box-shadow: 0 4rpx 8rpx #e7e7e74c; })
},
.mine-header-head { },
margin-right: 30rpx; onLoad() {
height: 128rpx; this.init()
width: 128rpx; },
border-radius: $uni-theme-radius; }
overflow: hidden; </script>
}
<style lang="scss">
.mine-header-name { .mine {
margin-right: 30rpx; .title {
flex: 1; padding: 0 20rpx;
font-size: 36rpx; font-size: 28rpx;
color: #111; font-weight: 500;
font-weight: 700; }
}
} .mine-header {
padding: 200rpx 34rpx 34rpx;
.mine-nav { display: flex;
padding: 34rpx; align-items: center;
display: flex; background: $uni-theme-white;
align-items: center; margin-bottom: 20rpx;
background: $uni-theme-white; box-shadow: 0 4rpx 8rpx #e7e7e74c;
border-bottom: 1rpx solid #e8e8e8;
.mine-header-head {
&-icon { margin-right: 30rpx;
margin-right: 30rpx; height: 128rpx;
height: 44rpx; width: 128rpx;
width: 44rpx; border-radius: $uni-theme-radius;
border-radius: $uni-theme-radius; overflow: hidden;
overflow: hidden; }
}
.mine-header-name {
&-label { margin-right: 30rpx;
margin-right: 30rpx; flex: 1;
flex: 1; font-size: 36rpx;
font-size: 28rpx; color: #111;
color: #111; font-weight: 700;
} }
} }
}
</style> .mine-nav {
padding: 34rpx;
display: flex;
align-items: center;
background: $uni-theme-white;
border-bottom: 1rpx solid #e8e8e8;
&-icon {
margin-right: 30rpx;
height: 44rpx;
width: 44rpx;
border-radius: $uni-theme-radius;
overflow: hidden;
}
&-label {
margin-right: 30rpx;
flex: 1;
font-size: 28rpx;
color: #111;
}
}
}
</style>

View File

@@ -0,0 +1,129 @@
<template>
<Cn-page :loading="loading">
<view class="mine" slot="body">
<view class="mine-nav" style="margin-top: 20rpx">
<view class="mine-nav-label">ITIC</view>
<switch
style="transform: scale(0.8)"
color="#376cf3"
@change="change('iticFunction')"
:checked="config.iticFunction === 1"
/>
</view>
<view class="mine-nav" style="border-bottom: none">
<view class="mine-nav-label">F47</view>
<switch
style="transform: scale(0.8)"
color="#376cf3"
@change="change('f47Function')"
:checked="config.f47Function === 1"
/>
</view>
</view>
</Cn-page>
</template>
<script>
import { queryUserPushConfig, updatePushConfig } from '@/common/api/mine'
export default {
data() {
return {
loading: true,
config: {},
}
},
onLoad() {
this.init()
},
methods: {
init() {
queryUserPushConfig().then((res) => {
this.config = res.data
this.loading = false
})
},
change(type) {
this.config[type] = this.config[type] === 1 ? 0 : 1
// updatePushConfig(this.config).then((res) => {
// let str = ''
// switch (type) {
// case 'iticFunction':
// str = 'ITIC'
// break
// case 'f47Function':
// str = 'F47'
// break
// }
// this.$util.toast(`${str}配置${this.config[type] === 1 ? '开启' : '关闭'}成功`)
// })
},
},
onLoad() {
this.init()
},
onUnload() {
updatePushConfig(this.config).then((res) => {
// this.$util.toast(`配置修改成功!`)
})
},
}
</script>
<style lang="scss">
.mine {
.title {
padding: 0 20rpx;
font-size: 28rpx;
font-weight: 500;
}
.mine-header {
padding: 200rpx 34rpx 34rpx;
display: flex;
align-items: center;
background: $uni-theme-white;
margin-bottom: 20rpx;
box-shadow: 0 4rpx 8rpx #e7e7e74c;
.mine-header-head {
margin-right: 30rpx;
height: 128rpx;
width: 128rpx;
border-radius: $uni-theme-radius;
overflow: hidden;
}
.mine-header-name {
margin-right: 30rpx;
flex: 1;
font-size: 36rpx;
color: #111;
font-weight: 700;
}
}
.mine-nav {
padding: 34rpx;
display: flex;
align-items: center;
background: $uni-theme-white;
border-bottom: 1rpx solid #e8e8e8;
&-icon {
margin-right: 30rpx;
height: 44rpx;
width: 44rpx;
border-radius: $uni-theme-radius;
overflow: hidden;
}
&-label {
margin-right: 30rpx;
flex: 1;
font-size: 28rpx;
color: #111;
}
}
}
</style>

View File

@@ -1,183 +1,166 @@
<template> <template>
<view :loading="loading"> <view :loading="loading">
<!-- <uni-nav-bar left-icon="left" right-icon="cart" title="标题" /> --> <!-- <uni-nav-bar left-icon="left" right-icon="cart" title="标题" /> -->
<uni-nav-bar <uni-nav-bar dark :fixed="true" status-bar left-icon="left" :rightIcon="userInfo.authorities === 'app_vip_user' || userInfo.authorities === 'engineering_user'
dark ? 'plusempty'
:fixed="true" : ''
status-bar " background-color="#fff" color="#111" title="项目管理" @clickLeft="back" @clickRight="add" />
left-icon="left" <uni-search-bar v-model="store.params.searchValue" clearButton="none" bgColor="#fff" placeholder="请输入关键词"
:rightIcon=" @input="store.search()"></uni-search-bar>
userInfo.authorities === 'app_vip_user' || userInfo.authorities === 'engineering_user' <view class="message">
? 'plusempty' <uni-card class="boxClick" :title="item.name" @click="jump(item)" extra="🔍"
: '' v-for="(item, index) in store.data" :key="index" :style="{ marginTop: index === 0 ? '0' : '' }">
" <view class="term-list-bottom">
background-color="#fff" <view class="term-list-bottom-item">
color="#111" <view>设备个数</view>
title="项目管理" <view>{{ item.devNum }}</view>
@clickLeft="back" </view>
@clickRight="add" <view class="term-list-bottom-item">
/> <view>所属工程</view>
<uni-search-bar <view>{{ item.engineeringName }}</view>
v-model="store.params.searchValue" </view>
clearButton="none" </view>
bgColor="#fff" </uni-card>
placeholder="请输入关键词" <Cn-empty v-if="store.empty" style="padding-top: 400rpx"></Cn-empty>
@input="store.search()" <uni-load-more v-if="store.status == 'loading' || (store.data && store.data.length > 0)"
></uni-search-bar> :status="store.status"></uni-load-more>
<view class="message"> </view>
<uni-card </view>
:title="item.name" </template>
@click="jump(item)"
extra="🔍" <script>
v-for="(item, index) in store.data" import list from '../../common/js/list'
:key="index"
:style="{ marginTop: index === 0 ? '0' : '' }" export default {
> mixins: [list],
<view class="term-list-bottom"> data() {
<view class="term-list-bottom-item"> return {
<view>设备个数</view> loading: false,
<view>{{ item.devNum }}</view> userInfo: {},
</view> }
<view class="term-list-bottom-item"> },
<view>所属工程</view> methods: {
<view>{{ item.engineeringName }}</view> init(engineeringId) {
</view> this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo)
</view> this.store = this.DataSource('/cs-device-boot/project/queryProject')
</uni-card> this.store.params.searchValue = ''
<Cn-empty v-if="store.empty" style="padding-top: 400rpx"></Cn-empty> this.store.params.engineeringId = engineeringId || ''
<uni-load-more this.store.reload()
v-if="store.status == 'loading' || (store.data && store.data.length > 0)" },
:status="store.status" back() {
></uni-load-more> uni.navigateBack()
</view> },
</view> add() {
</template> if (this.userInfo.authorities === 'app_vip_user' || this.userInfo.authorities === 'engineering_user') {
if (!uni.getStorageSync('engineering')) {
<script> return uni.showToast({
import list from '../../common/js/list' title: '请先创建一个工程',
icon: 'none',
export default { })
mixins: [list], }
data() { uni.navigateTo({
return { url: `/pages/project/new`,
loading: false, })
userInfo: {}, }
} },
}, upgrade(code) {
methods: { console.log(code)
init(engineeringId) { uni.showToast({
this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo) title: '升级成功',
this.store = this.DataSource('/cs-device-boot/project/queryProject') icon: 'none',
this.store.params.searchValue = '' })
this.store.params.engineeringId = engineeringId || '' },
this.store.reload() jump(project) {
}, console.log(project)
back() { uni.navigateTo({
uni.navigateBack() url: `/pages/project/detail?project=${encodeURIComponent(JSON.stringify(project))}`,
}, })
add() { },
if (this.userInfo.authorities === 'app_vip_user' || this.userInfo.authorities === 'engineering_user') { },
if (!uni.getStorageSync('engineering')) { onLoad({ engineeringId }) {
return uni.showToast({ this.init(engineeringId)
title: '请先创建一个工程', },
icon: 'none', }
}) </script>
}
uni.navigateTo({ <style lang="scss">
url: `/pages/project/new`, .message {
}) .message-header {
} padding: 200rpx 34rpx 34rpx;
}, display: flex;
upgrade(code) { align-items: center;
console.log(code) background: $uni-theme-white;
uni.showToast({ margin-bottom: 20rpx;
title: '升级成功', box-shadow: 0 4rpx 8rpx #e7e7e74c;
icon: 'none',
}) .message-header-head {
}, margin-right: 30rpx;
jump(project) { height: 128rpx;
console.log(project) width: 128rpx;
uni.navigateTo({ border-radius: $uni-theme-radius;
url: `/pages/project/detail?project=${encodeURIComponent(JSON.stringify(project))}`, overflow: hidden;
}) }
},
}, .message-header-name {
onLoad({ engineeringId }) { margin-right: 30rpx;
this.init(engineeringId) flex: 1;
}, font-size: 36rpx;
} color: #111;
</script> font-weight: 700;
<style lang="scss"> .tag {
.message { margin-top: 10rpx;
.message-header { font-size: 24rpx;
padding: 200rpx 34rpx 34rpx; color: #aaa;
display: flex; }
align-items: center; }
background: $uni-theme-white; }
margin-bottom: 20rpx;
box-shadow: 0 4rpx 8rpx #e7e7e74c; .message-nav {
padding: 34rpx;
.message-header-head { display: flex;
margin-right: 30rpx; align-items: center;
height: 128rpx; background: $uni-theme-white;
width: 128rpx; border-bottom: 1rpx solid #e8e8e8;
border-radius: $uni-theme-radius;
overflow: hidden; &-icon {
} margin-right: 30rpx;
height: 44rpx;
.message-header-name { width: 44rpx;
margin-right: 30rpx; border-radius: $uni-theme-radius;
flex: 1; overflow: hidden;
font-size: 36rpx; }
color: #111;
font-weight: 700; &-label {
margin-right: 30rpx;
.tag { flex: 1;
margin-top: 10rpx; font-size: 28rpx;
font-size: 24rpx; color: #111;
color: #aaa; }
} }
} }
}
.term-list-bottom {
.message-nav { .term-list-bottom-item {
padding: 34rpx; font-size: 28rpx;
display: flex; // margin-bottom: 20rpx;
align-items: center; display: flex;
background: $uni-theme-white; justify-content: space-between;
border-bottom: 1rpx solid #e8e8e8; // view:first-of-type{
// color: #111;
&-icon { // }
margin-right: 30rpx; }
height: 44rpx;
width: 44rpx; .term-list-bottom-item:last-of-type {
border-radius: $uni-theme-radius; margin-bottom: 0;
overflow: hidden; }
} }
&-label { /deep/ .uni-card__content {
margin-right: 30rpx; padding: 5px 10px 10px !important;
flex: 1; }
font-size: 28rpx;
color: #111; /deep/ .uni-card__header-content-title {
} font-weight: 700;
} }
} </style>
.term-list-bottom {
.term-list-bottom-item {
font-size: 28rpx;
margin-bottom: 20rpx;
display: flex;
justify-content: space-between;
// view:first-of-type{
// color: #111;
// }
}
.term-list-bottom-item:last-of-type {
margin-bottom: 0;
}
}
</style>

View File

@@ -24,13 +24,13 @@
v-model="formData.area" v-model="formData.area"
placeholder="请输入区域信息" placeholder="请输入区域信息"
/> />
<uni-icons <!-- <uni-icons
type="location" type="location"
color="#007aff" color="#007aff"
size="26" size="26"
class="ml20" class="ml20"
@click="chooseLocation" @click="chooseLocation"
></uni-icons> ></uni-icons> -->
</view> </view>
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="描述"> <uni-forms-item label="描述">
@@ -241,19 +241,19 @@ export default {
this.formData.files.push(...e.tempFiles) this.formData.files.push(...e.tempFiles)
console.log(this.formData.files) console.log(this.formData.files)
}, },
chooseLocation() { // chooseLocation() {
uni.chooseLocation({ // uni.chooseLocation({
success: (res) => { // success: (res) => {
this.formData.area = res.name // this.formData.area = res.name
this.formData.lat = res.latitudeame // this.formData.lat = res.latitudeame
this.formData.lng = res.longitude // this.formData.lng = res.longitude
console.log('位置名称:' + res.name) // console.log('位置名称:' + res.name)
console.log('详细地址:' + res.address) // console.log('详细地址:' + res.address)
console.log('纬度:' + res.latitude) // console.log('纬度:' + res.latitude)
console.log('经度:' + res.longitude) // console.log('经度:' + res.longitude)
}, // },
}) // })
}, // },
async submit() { async submit() {
console.log(this.formData) console.log(this.formData)
if (!this.formData.name) { if (!this.formData.name) {

View File

@@ -1,249 +1,250 @@
<template> <template>
<Cn-page :loading="loading"> <Cn-page :loading="loading">
<view slot="body"> <view slot="body">
<view class="index"> <view class="index">
<template v-if="step == 1"> <template v-if="step == 1">
<uni-forms ref="form" :rules="rules" :modelValue="formData"> <uni-forms ref="form" :rules="rules" :modelValue="formData">
<uni-forms-item name="phone"> <uni-forms-item name="phone">
<uni-easyinput <uni-easyinput
disabled disabled
type="text" type="text"
maxlength="11" maxlength="11"
v-model="formData.phoneShow" v-model="formData.phoneShow"
placeholder="请输入手机号" placeholder="请输入手机号"
/> />
</uni-forms-item> </uni-forms-item>
<uni-forms-item name="code"> <uni-forms-item name="code">
<view class="login-box-input"> <view class="login-box-input">
<uni-easyinput type="text" v-model="formData.code" placeholder="请输入验证码" maxlength="6" /> <uni-easyinput type="text" v-model="formData.code" placeholder="请输入验证码" maxlength="6" />
<view <view
class="ml40" class="ml40"
style=" style="
margin-left: 40rpx; margin-left: 40rpx;
font-size: 28rpx; font-size: 28rpx;
color: #666; color: #666;
width: 200rpx; width: 200rpx;
text-align: center; text-align: center;
" "
v-if="waitTime > 0" v-if="waitTime > 0"
>{{ waitTime + 's后重新获取' }}</view >{{ waitTime + 's后重新获取' }}</view
> >
<button class="login-box-input-btn" v-else @click="getCode(5)" size="mini"> <button class="login-box-input-btn" v-else @click="getCode(5)" size="mini">
获取验证码 获取验证码
</button> </button>
</view> </view>
</uni-forms-item> </uni-forms-item>
</uni-forms> </uni-forms>
<button type="default" class="submit-btn" @click="firstSubmit">下一步</button> <button type="default" class="submit-btn" @click="firstSubmit">下一步</button>
</template> </template>
<template v-else> <template v-else>
<uni-forms ref="form" :rules="rules" :modelValue="formData"> <uni-forms ref="form" :rules="rules" :modelValue="formData">
<uni-forms-item name="phone"> <uni-forms-item name="phone">
<uni-easyinput <uni-easyinput
maxlength="11" maxlength="11"
type="number" type="number"
v-model="formData.phone2" v-model="formData.phone2"
placeholder="请输入新手机号" placeholder="请输入新手机号"
/> />
</uni-forms-item> </uni-forms-item>
<uni-forms-item name="code"> <uni-forms-item name="code">
<view class="login-box-input"> <view class="login-box-input">
<uni-easyinput type="text" v-model="formData.code2" placeholder="请输入验证码" maxlength="6" /> <uni-easyinput type="text" v-model="formData.code2" placeholder="请输入验证码" maxlength="6" />
<view <view
class="ml40" class="ml40"
style=" style="
margin-left: 40rpx; margin-left: 40rpx;
font-size: 28rpx; font-size: 28rpx;
color: #666; color: #666;
width: 200rpx; width: 200rpx;
text-align: center; text-align: center;
" "
v-if="waitTime > 0" v-if="waitTime > 0"
>{{ waitTime + 's后重新获取' }}</view >{{ waitTime + 's后重新获取' }}</view
> >
<button class="login-box-input-btn" v-else @click="getCode(4)" size="mini"> <button class="login-box-input-btn" v-else @click="getCode(4)" size="mini">
获取验证码 获取验证码
</button> </button>
</view> </view>
</uni-forms-item> </uni-forms-item>
</uni-forms> </uni-forms>
<button type="default" class="submit-btn" @click="secondSubmit">提交</button> <button type="default" class="submit-btn" @click="secondSubmit">提交</button>
</template> </template>
</view> </view>
</view> </view>
</Cn-page> </Cn-page>
</template> </template>
<script> <script>
import { apiGetYms, apiComfirmCode, apiRebindPhone } from '@/common/api/user' import { apiGetYms, apiComfirmCode, apiRebindPhone } from '@/common/api/user'
export default { export default {
name: 'jiaban', name: 'jiaban',
data() { data() {
return { return {
step: 1, step: 1,
loading: false, loading: false,
waitTime: 0, waitTime: 0,
// 表单数据 // 表单数据
formData: { formData: {
phone: '', phone: '',
phoneShow: '', phoneShow: '',
code: '', code: '',
phone2: '', phone2: '',
code2: '', code2: '',
}, },
rules: { rules: {
phone: { phone: {
rules: [ rules: [
{ {
required: true, required: true,
errorMessage: '请填写手机号', errorMessage: '请填写手机号',
}, },
], ],
}, },
code: { code: {
rules: [ rules: [
{ {
required: true, required: true,
errorMessage: '请填写验证码', errorMessage: '请填写验证码',
}, },
], ],
}, },
phone2: { phone2: {
rules: [ rules: [
{ {
required: true, required: true,
errorMessage: '请填写新手机号', errorMessage: '请填写新手机号',
}, },
], ],
}, },
code2: { code2: {
rules: [ rules: [
{ {
required: true, required: true,
errorMessage: '请填写验证码', errorMessage: '请填写验证码',
}, },
], ],
}, },
}, },
} }
}, },
onLoad() { onLoad() {
this.init() this.init()
}, },
methods: { methods: {
getCode(type) { getCode(type) {
if (!this.formData.phone) { if (!this.formData.phone) {
return this.$util.toast('请输入手机号!') return this.$util.toast('请输入手机号!')
} }
uni.showLoading({ uni.showLoading({
title: '请稍等', title: '请稍等...',
}) mask: true,
apiGetYms({ })
phone: type == 5 ? this.formData.phone : this.formData.phone2, apiGetYms({
type, phone: type == 5 ? this.formData.phone : this.formData.phone2,
}) type,
.then((res) => { })
uni.hideLoading() .then((res) => {
console.log(res) uni.hideLoading()
this.waitTime = 60 console.log(res)
this.inter = setInterval(() => { this.waitTime = 60
if (this.waitTime == 0) { this.inter = setInterval(() => {
clearInterval(this.inter) if (this.waitTime == 0) {
} else { clearInterval(this.inter)
this.waitTime-- } else {
} this.waitTime--
}, 1000) }
}) }, 1000)
.catch((err) => { })
uni.hideLoading() .catch((err) => {
console.log(err) uni.hideLoading()
}) console.log(err)
}, })
init() { },
// 手机号中间四位隐藏 init() {
this.formData.phone = uni.getStorageSync('userInfo').user_name // 手机号中间四位隐藏
this.formData.phoneShow = this.formData.phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2') this.formData.phone = uni.getStorageSync('userInfo').user_name
}, this.formData.phoneShow = this.formData.phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
firstSubmit() { },
apiComfirmCode({ firstSubmit() {
phone: this.formData.phone, apiComfirmCode({
code: this.formData.code, phone: this.formData.phone,
}) code: this.formData.code,
.then((res) => { })
this.step = 2 .then((res) => {
clearInterval(this.inter) this.step = 2
this.waitTime = 0 clearInterval(this.inter)
}) this.waitTime = 0
.catch((err) => { })
console.log(err) .catch((err) => {
}) console.log(err)
}, })
secondSubmit() { },
apiRebindPhone({ secondSubmit() {
phone: this.formData.phone2, apiRebindPhone({
code: this.formData.code2, phone: this.formData.phone2,
}) code: this.formData.code2,
.then((res) => { })
this.$util.toast('绑定成功') .then((res) => {
uni.clearStorageSync() this.$util.toast('绑定成功')
setTimeout(() => { uni.clearStorageSync()
uni.redirectTo({ setTimeout(() => {
url: '/pages/user/login', uni.redirectTo({
}) url: '/pages/user/login',
}, 1500) })
}) }, 1500)
.catch((err) => { })
console.log(err) .catch((err) => {
}) console.log(err)
}, })
}, },
} },
</script> }
<style lang="scss"> </script>
.index { <style lang="scss">
padding: 20rpx; .index {
padding: 20rpx;
.submit-btn {
background: $uni-theme-color; .submit-btn {
color: #fff; background: $uni-theme-color;
} color: #fff;
}
.login-box-tips {
margin-top: 60rpx; .login-box-tips {
display: flex; margin-top: 60rpx;
justify-content: center; display: flex;
font-size: 20rpx; justify-content: center;
} font-size: 20rpx;
}
.login-box-input {
display: flex; .login-box-input {
align-items: center; display: flex;
border-bottom: 1rpx solid #f0f0f0; align-items: center;
border-bottom: 1rpx solid #f0f0f0;
.login-box-input-icon {
width: 40rpx; .login-box-input-icon {
margin-right: 40rpx; width: 40rpx;
} margin-right: 40rpx;
}
.login-box-input-main {
font-size: 28rpx; .login-box-input-main {
flex: 1; font-size: 28rpx;
height: 100rpx; flex: 1;
line-height: 100rpx; height: 100rpx;
} line-height: 100rpx;
}
.login-box-input-btn {
padding:0 40rpx; .login-box-input-btn {
margin-left: 40rpx; padding:0 40rpx;
background: $uni-theme-color; margin-left: 40rpx;
color: #fff; background: $uni-theme-color;
} color: #fff;
}
.login-box-input-img {
margin-left: 40rpx; .login-box-input-img {
background: skyblue; margin-left: 40rpx;
height: 80rpx; background: skyblue;
width: 200rpx; height: 80rpx;
} width: 200rpx;
} }
} }
</style> }
</style>

View File

@@ -1,242 +1,243 @@
<template> <template>
<Cn-page :loading="loading"> <Cn-page :loading="loading">
<view slot="body"> <view slot="body">
<view class="index"> <view class="index">
<uni-forms ref="form" :modelValue="formData" :rules="rules"> <uni-forms ref="form" :modelValue="formData" :rules="rules">
<uni-forms-item name="phone"> <uni-forms-item name="phone">
<uni-easyinput <uni-easyinput
maxlength="11" maxlength="11"
disabled disabled
type="text" type="text"
v-model="formData.showPhone" v-model="formData.showPhone"
placeholder="请输入手机号" placeholder="请输入手机号"
/> />
</uni-forms-item> </uni-forms-item>
<uni-forms-item name="code"> <uni-forms-item name="code">
<view class="login-box-input"> <view class="login-box-input">
<uni-easyinput type="number" v-model="formData.code" placeholder="请输入手机验证码" /> <uni-easyinput type="number" v-model="formData.code" placeholder="请输入手机验证码" />
<view <view
class="ml40" class="ml40"
style=" style="
margin-left: 40rpx; margin-left: 40rpx;
font-size: 28rpx; font-size: 28rpx;
color: #666; color: #666;
width: 200rpx; width: 200rpx;
text-align: center; text-align: center;
" "
v-if="waitTime > 0" v-if="waitTime > 0"
>{{ waitTime + 's后重新获取' }}</view >{{ waitTime + 's后重新获取' }}</view
> >
<button class="login-box-input-btn" v-else @click="getCode" size="mini">获取验证码</button> <button class="login-box-input-btn" v-else @click="getCode" size="mini">获取验证码</button>
</view> </view>
</uni-forms-item> </uni-forms-item>
<uni-forms-item name="password"> <uni-forms-item name="password">
<uni-easyinput type="password" v-model="formData.password" placeholder="请输入新的登录密码" /> <uni-easyinput type="password" v-model="formData.password" placeholder="请输入新的登录密码" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item name="password2"> <uni-forms-item name="password2">
<uni-easyinput type="password" v-model="formData.password2" placeholder="请再次确认密码" /> <uni-easyinput type="password" v-model="formData.password2" placeholder="请再次确认密码" />
</uni-forms-item> </uni-forms-item>
</uni-forms> </uni-forms>
<button type="default" class="submit-btn" @click="submit">提交</button> <button type="default" class="submit-btn" @click="submit">提交</button>
<view class="login-box-tips"> <view class="login-box-tips">
<view style="color: #999">说明密码需要长度为8-16</view> <view style="color: #999">说明密码需要长度为8-16</view>
</view> </view>
</view> </view>
</view> </view>
</Cn-page> </Cn-page>
</template> </template>
<script> <script>
import { apiGetYms, apiModifyPsd, gongkey } from '@/common/api/user' import { apiGetYms, apiModifyPsd, gongkey } from '@/common/api/user'
import { sm2, encrypt } from '@/common/js/sm2.js' import { sm2, encrypt } from '@/common/js/sm2.js'
import { sm3Digest } from '@/common/js/sm3.js' import { sm3Digest } from '@/common/js/sm3.js'
export default { export default {
name: 'ChangePWd', name: 'ChangePWd',
data() { data() {
return { return {
loading: false, loading: false,
waitTime: 0, waitTime: 0,
// 表单数据 // 表单数据
formData: { formData: {
showPhone: '', showPhone: '',
phone: '', phone: '',
code: '', code: '',
password: '', password: '',
password2: '', password2: '',
}, },
rules: { rules: {
phone: { phone: {
rules: [ rules: [
{ {
required: true, required: true,
errorMessage: '请填写手机号', errorMessage: '请填写手机号',
}, },
], ],
}, },
code: { code: {
rules: [ rules: [
{ {
required: true, required: true,
errorMessage: '请填写验证码', errorMessage: '请填写验证码',
}, },
], ],
}, },
password: { password: {
rules: [ rules: [
{ {
required: true, required: true,
errorMessage: '请填写新密码', errorMessage: '请填写新密码',
}, },
], ],
}, },
password2: { password2: {
rules: [ rules: [
{ {
required: true, required: true,
errorMessage: '请填写确认密码', errorMessage: '请填写确认密码',
}, },
], ],
}, },
}, },
} }
}, },
onLoad() { onLoad() {
// 手机号中间四位隐藏 // 手机号中间四位隐藏
this.formData.phone = uni.getStorageSync('userInfo').user_name this.formData.phone = uni.getStorageSync('userInfo').user_name
this.formData.showPhone = this.formData.phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2') this.formData.showPhone = this.formData.phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
}, },
methods: { methods: {
getCode() { getCode() {
uni.showLoading({ uni.showLoading({
title: '请稍等', title: '请稍等...',
}) mask: true,
apiGetYms({ })
phone: this.formData.phone, apiGetYms({
type: 2, phone: this.formData.phone,
}) type: 2,
.then((res) => { })
uni.hideLoading() .then((res) => {
console.log(res) uni.hideLoading()
this.waitTime = 60 console.log(res)
this.inter = setInterval(() => { this.waitTime = 60
if (this.waitTime == 0) { this.inter = setInterval(() => {
clearInterval(this.inter) if (this.waitTime == 0) {
} else { clearInterval(this.inter)
this.waitTime-- } else {
} this.waitTime--
}, 1000) }
}) }, 1000)
.catch((err) => { })
uni.hideLoading() .catch((err) => {
console.log(err) uni.hideLoading()
}) console.log(err)
}, })
submit() { },
this.$refs.form.validate((valid) => { submit() {
console.log(valid) this.$refs.form.validate((valid) => {
if (!valid) { console.log(valid)
if (this.formData.password != this.formData.password2) { if (!valid) {
uni.showToast({ if (this.formData.password != this.formData.password2) {
title: '两次密码不一致', uni.showToast({
icon: 'none', title: '两次密码不一致',
}) icon: 'none',
} else { })
// 密码需要长度为8-16 } else {
if (this.formData.password.length < 8 || this.formData.password.length > 16) { // 密码需要长度为8-16
uni.showToast({ if (this.formData.password.length < 8 || this.formData.password.length > 16) {
title: '密码需要长度为8-16', uni.showToast({
icon: 'none', title: '密码需要长度为8-16',
}) icon: 'none',
return })
} return
}
let loginName = encrypt(this.formData.phone)
gongkey({ loginName }).then((response) => { let loginName = encrypt(this.formData.phone)
let publicKey = response.data gongkey({ loginName }).then((response) => {
let sm3Pwd = sm3Digest(this.formData.password) let publicKey = response.data
let jiamipassword = sm2(sm3Pwd + '|' + this.formData.password, publicKey, 0) let sm3Pwd = sm3Digest(this.formData.password)
// apiPwdLogin({ let jiamipassword = sm2(sm3Pwd + '|' + this.formData.password, publicKey, 0)
// username: loginName, // apiPwdLogin({
// password: jiamipassword, // username: loginName,
// imageCode: '', // password: jiamipassword,
// grant_type: 'captcha', // imageCode: '',
// verifyCode: 0, // grant_type: 'captcha',
// }).then((res) => { // verifyCode: 0,
// this.$util.loginSuccess(res.data) // }).then((res) => {
// }) // this.$util.loginSuccess(res.data)
apiModifyPsd({ // })
phone: this.formData.phone, apiModifyPsd({
code: this.formData.code, phone: this.formData.phone,
password: jiamipassword, code: this.formData.code,
}) password: jiamipassword,
.then((res) => { })
console.log(res) .then((res) => {
uni.showToast({ console.log(res)
title: '修改成功', uni.showToast({
icon: 'none', title: '修改成功',
}) icon: 'none',
setTimeout(() => { })
uni.navigateBack({ setTimeout(() => {
delta: 1, uni.navigateBack({
}) delta: 1,
}, 1000) })
}) }, 1000)
.catch((err) => { })
console.log(err) .catch((err) => {
}) console.log(err)
}) })
} })
} }
}) }
}, })
}, },
} },
</script> }
<style lang="scss"> </script>
.index { <style lang="scss">
padding: 20rpx; .index {
padding: 20rpx;
.submit-btn {
background: $uni-theme-color; .submit-btn {
color: #fff; background: $uni-theme-color;
} color: #fff;
}
.login-box-tips {
margin-top: 60rpx; .login-box-tips {
display: flex; margin-top: 60rpx;
justify-content: center; display: flex;
font-size: 20rpx; justify-content: center;
} font-size: 20rpx;
}
.login-box-input {
display: flex; .login-box-input {
align-items: center; display: flex;
border-bottom: 1rpx solid #f0f0f0; align-items: center;
border-bottom: 1rpx solid #f0f0f0;
.login-box-input-icon {
width: 40rpx; .login-box-input-icon {
margin-right: 40rpx; width: 40rpx;
} margin-right: 40rpx;
}
.login-box-input-main {
font-size: 28rpx; .login-box-input-main {
flex: 1; font-size: 28rpx;
height: 100rpx; flex: 1;
line-height: 100rpx; height: 100rpx;
} line-height: 100rpx;
}
.login-box-input-btn {
padding:0 40rpx; .login-box-input-btn {
margin-left: 40rpx; padding: 0 40rpx;
background: $uni-theme-color; margin-left: 40rpx;
color: #fff; background: $uni-theme-color;
} color: #fff;
}
.login-box-input-img {
margin-left: 40rpx; .login-box-input-img {
background: skyblue; margin-left: 40rpx;
height: 80rpx; background: skyblue;
width: 200rpx; height: 80rpx;
} width: 200rpx;
} }
} }
</style> }
</style>

View File

@@ -114,7 +114,8 @@ export default {
return this.$util.toast('请输入手机号!') return this.$util.toast('请输入手机号!')
} }
uni.showLoading({ uni.showLoading({
title: '请稍等', title: '请稍等...',
mask: true,
}) })
apiGetYms({ apiGetYms({
phone: this.formData.phone, phone: this.formData.phone,

View File

@@ -1,147 +1,148 @@
<template> <template>
<view> <view>
<Cn-page :loading="loading"> <Cn-page :loading="loading">
<view slot="body"> <view slot="body">
<view class="head"> <view class="head">
<image class="head-img" :src="userInfo.avatar" v-if="userInfo.avatar"></image> <image class="head-img" :src="userInfo.avatar" v-if="userInfo.avatar"></image>
<image class="head-img" src="/static/head.png" v-else></image> <image class="head-img" src="/static/head.png" v-else></image>
<view class="head-setup"> <view class="head-setup">
<view class="head-setup-item" @click="take('album')">从相册选一张</view> <view class="head-setup-item" @click="take('album')">从相册选一张</view>
<view class="head-setup-item" @click="take('camera')">拍一张照片</view> <view class="head-setup-item" @click="take('camera')">拍一张照片</view>
</view> </view>
</view> </view>
</view> </view>
</Cn-page> </Cn-page>
<uni-popup ref="alertDialog" type="dialog"> <uni-popup ref="alertDialog" type="dialog">
<uni-popup-dialog <uni-popup-dialog
style="width: 90%; margin: 5%" style="width: 90%; margin: 5%"
cancelText="禁止" cancelText="禁止"
confirmText="允许" confirmText="允许"
title="权限说明" title="权限说明"
content='是否允许"灿能物联"使用相机?' content='是否允许"灿能物联"使用相机?'
@confirm="handleScon('camera')" @confirm="handleScon('camera')"
@close="dialogClose" @close="dialogClose"
></uni-popup-dialog> ></uni-popup-dialog>
</uni-popup> </uni-popup>
<uni-popup ref="message" type="message"> <uni-popup ref="message" type="message">
<uni-popup-message type="info" :duration="0" style="width: 90%; margin: 5%"> <uni-popup-message type="info" :duration="0" style="width: 90%; margin: 5%">
<view style="color: #909399; font-style: 16px">相机权限使用说明:</view> <view style="color: #909399; font-style: 16px">相机权限使用说明:</view>
<view style="color: #6c6c6c; margin-top: 3rpx"> 用于拍照上传头像!</view> <view style="color: #6c6c6c; margin-top: 3rpx"> 用于拍照上传头像!</view>
</uni-popup-message> </uni-popup-message>
</uni-popup> </uni-popup>
<yk-authpup ref="authpup" type="top" @changeAuth="changeAuth" permissionID="CAMERA"></yk-authpup> <yk-authpup ref="authpup" type="top" @changeAuth="changeAuth" permissionID="CAMERA"></yk-authpup>
<yk-authpup <yk-authpup
ref="authpup1" ref="authpup1"
type="top" type="top"
@changeAuth="changeAuth" @changeAuth="changeAuth"
permissionID="WRITE_EXTERNAL_STORAGE" permissionID="WRITE_EXTERNAL_STORAGE"
></yk-authpup> ></yk-authpup>
</view> </view>
</template> </template>
<script> <script>
import { uploadImage, getImageUrl } from '@/common/api/basic' import { uploadImage, getImageUrl } from '@/common/api/basic'
import { apiUpdateUser } from '@/common/api/user' import { apiUpdateUser } from '@/common/api/user'
import ykAuthpup from '@/components/yk-authpup/yk-authpup' import ykAuthpup from '@/components/yk-authpup/yk-authpup'
export default { export default {
components: { components: {
ykAuthpup, ykAuthpup,
}, },
data() { data() {
return { return {
loading: false, loading: false,
userInfo: {}, userInfo: {},
type: '', type: '',
} }
}, },
methods: { methods: {
take(type) { take(type) {
this.type = type this.type = type
if (type == 'camera') { if (type == 'camera') {
if (plus.os.name == 'Android') { if (plus.os.name == 'Android') {
this.$refs['authpup'].open() this.$refs['authpup'].open()
//未授权 //未授权
// this.$refs.message.open() // this.$refs.message.open()
// this.$refs.alertDialog.open('bottom') // this.$refs.alertDialog.open('bottom')
} else { } else {
this.handleScon(type) this.handleScon(type)
} }
} else { } else {
if (plus.os.name == 'Android') { if (plus.os.name == 'Android') {
this.$refs['authpup1'].open() this.$refs['authpup1'].open()
//未授权 //未授权
// this.$refs.message.open() // this.$refs.message.open()
// this.$refs.alertDialog.open('bottom') // this.$refs.alertDialog.open('bottom')
} else { } else {
this.handleScon(type) this.handleScon(type)
} }
// this.handleScon(type)、 // this.handleScon(type)、
} }
}, },
changeAuth() { changeAuth() {
//这里是权限通过后执行自己的代码逻辑 //这里是权限通过后执行自己的代码逻辑
console.log('权限已授权,可执行自己的代码逻辑了') console.log('权限已授权,可执行自己的代码逻辑了')
// this.handleScon() // this.handleScon()
this.handleScon(this.type) this.handleScon(this.type)
}, },
handleScon(type) { handleScon(type) {
this.$refs.message.close() this.$refs.message.close()
uni.chooseImage({ uni.chooseImage({
count: 1, count: 1,
sizeType: ['original', 'compressed'], sizeType: ['original', 'compressed'],
sourceType: [type], sourceType: [type],
success: (res) => { success: (res) => {
uploadImage(res.tempFilePaths[0]).then((res) => { uploadImage(res.tempFilePaths[0]).then((res) => {
console.log(res) console.log(res)
let result = JSON.parse(res[1].data) console.log("🚀 ~ res:", res)
apiUpdateUser({ let result = JSON.parse(res[1].data)
headSculpture: result.data.minFileUrl, apiUpdateUser({
}).then((res) => { headSculpture: result.data.minFileUrl,
console.log(res) }).then((res) => {
this.userInfo.headSculpture = result.data.minFileUrl console.log(res)
this.userInfo.avatar = this.$config.static + result.data.minFileUrl this.userInfo.headSculpture = result.data.minFileUrl
uni.setStorageSync(this.$cacheKey.userInfo, this.userInfo) this.userInfo.avatar = this.$config.static + result.data.minFileUrl
this.$forceUpdate() uni.setStorageSync(this.$cacheKey.userInfo, this.userInfo)
}) this.$forceUpdate()
}) })
}, })
}) },
}, })
dialogClose() { },
this.$refs.message.close() dialogClose() {
}, this.$refs.message.close()
}, },
},
onLoad(options) {
this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo) onLoad(options) {
}, this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo)
} },
</script> }
<style lang="scss"> </script>
.head { <style lang="scss">
.head-img { .head {
height: 750rpx; .head-img {
width: 750rpx; height: 750rpx;
} width: 750rpx;
}
.head-setup {
position: fixed; .head-setup {
bottom: 0; position: fixed;
left: 0; bottom: 0;
width: 750rpx; left: 0;
padding-bottom: 60rpx; width: 750rpx;
background-color: #fff; padding-bottom: 60rpx;
background-color: #fff;
.head-setup-item {
height: 100rpx; .head-setup-item {
line-height: 100rpx; height: 100rpx;
text-align: center; line-height: 100rpx;
border-top: 1rpx solid #e8e8e8; text-align: center;
} border-top: 1rpx solid #e8e8e8;
} }
} }
/deep/ .uni-popup-message__box { }
border-radius: 10rpx !important; /deep/ .uni-popup-message__box {
background-color: #fff; border-radius: 10rpx !important;
} background-color: #fff;
</style> }
</style>

View File

@@ -121,7 +121,8 @@ export default {
return this.$util.toast('请输入手机号!') return this.$util.toast('请输入手机号!')
} }
uni.showLoading({ uni.showLoading({
title: '请稍等', title: '请稍等...',
mask: true,
}) })
apiGetYms({ apiGetYms({
phone: this.phone, phone: this.phone,

View File

@@ -135,7 +135,8 @@ export default {
return this.$util.toast('请输入手机号!') return this.$util.toast('请输入手机号!')
} }
uni.showLoading({ uni.showLoading({
title: '请稍等', title: '请稍等...',
mask: true,
}) })
apiGetYms({ apiGetYms({
phone: this.formData.phone, phone: this.formData.phone,

View File

@@ -1,57 +1,57 @@
<template> <template>
<Cn-page :loading='loading'> <Cn-page :loading='loading'>
<view slot='body'> <view slot='body'>
<view class='index'> <view class='index'>
<view class="content device" :style="{ minHeight: minHeight }"> <view class="content device" :style="{ minHeight: minHeight }">
<uni-card :title="item.name" :sub-title="item.project" :extra="item.type" padding="0" <uni-card :title="item.name" :sub-title="item.project" :extra="item.type" padding="0"
v-for="(item, index) in deviceList" :key="index" thumbnail="/static/device.png"> v-for="(item, index) in deviceList" :key="index" thumbnail="/static/device.png">
<!-- <text>{{ item.project }} {{ item.type }}</text> --> <!-- <text>{{ item.project }} {{ item.type }}</text> -->
</uni-card> </uni-card>
<uni-load-more status="nomore"></uni-load-more> <!-- <uni-load-more status="nomore"></uni-load-more> -->
</view> </view>
</view> </view>
</view> </view>
</Cn-page> </Cn-page>
</template> </template>
<script> <script>
export default { export default {
data () { data () {
return { return {
loading: false, loading: false,
deviceList: [ deviceList: [
{ {
name: '设备APF-1', name: '设备APF-1',
des: '设备描述1', des: '设备描述1',
type: '监测', type: '监测',
project: 'XXX项目1', project: 'XXX项目1',
}, },
{ {
name: '设备APF-2', name: '设备APF-2',
des: '设备描述1', des: '设备描述1',
type: '监测', type: '监测',
project: 'XXX项目1', project: 'XXX项目1',
}, },
{ {
name: '设备APF-3', name: '设备APF-3',
des: '设备描述2', des: '设备描述2',
type: '用能', type: '用能',
project: 'XXX项目2' project: 'XXX项目2'
}, },
{ {
name: '设备DVR-1', name: '设备DVR-1',
des: '设备描述3', des: '设备描述3',
type: '监测', type: '监测',
project: 'XXX项目3' project: 'XXX项目3'
} }
] ]
} }
}, },
methods: { methods: {
} }
} }
</script> </script>
<style lang='scss'> <style lang='scss'>
.index { .index {
padding: 20rpx 0; padding: 20rpx 0;
} }
</style> </style>

380
pnpm-lock.yaml generated
View File

@@ -6,92 +6,32 @@ settings:
dependencies: dependencies:
crypto-js: crypto-js:
specifier: ^4.1.1 specifier: ^4.2.0
version: 4.1.1 version: 4.2.0
echarts:
specifier: ^5.6.0
version: 5.6.0
html2canvas: html2canvas:
specifier: ^1.4.1 specifier: ^1.4.1
version: 1.4.1 version: 1.4.1
image-tool:
specifier: ^1.0.2
version: 1.0.2
image-tools: image-tools:
specifier: ^1.4.0 specifier: ^1.4.0
version: 1.4.0 version: 1.4.0
jsrsasign: jsrsasign:
specifier: ^10.8.6 specifier: ^11.1.0
version: 10.8.6 version: 11.1.0
mqtt: mqtt:
specifier: 3.0.0 specifier: ^3.0.0
version: 3.0.0 version: 3.0.0
pinyin-pro: pinyin-pro:
specifier: ^3.13.2 specifier: ^3.26.0
version: 3.13.2 version: 3.26.0
qs:
specifier: ^6.11.2
version: 6.11.2
vconsole:
specifier: ^3.15.1
version: 3.15.1
devDependencies:
'@types/html5plus':
specifier: ^1.0.2
version: 1.0.2
'@types/uni-app':
specifier: ^1.4.4
version: 1.4.4
packages: packages:
/@babel/helper-string-parser@7.22.5:
resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==}
engines: {node: '>=6.9.0'}
dev: true
/@babel/helper-validator-identifier@7.22.5:
resolution: {integrity: sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==}
engines: {node: '>=6.9.0'}
dev: true
/@babel/parser@7.22.5:
resolution: {integrity: sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==}
engines: {node: '>=6.0.0'}
hasBin: true
dependencies:
'@babel/types': 7.22.5
dev: true
/@babel/runtime@7.22.6:
resolution: {integrity: sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==}
engines: {node: '>=6.9.0'}
dependencies:
regenerator-runtime: 0.13.11
dev: false
/@babel/types@7.22.5:
resolution: {integrity: sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/helper-string-parser': 7.22.5
'@babel/helper-validator-identifier': 7.22.5
to-fast-properties: 2.0.0
dev: true
/@types/html5plus@1.0.2:
resolution: {integrity: sha512-OklP5lrmLq8/6TUOLgWc0LndUVvAiTWX5dnyoCFhIUtFW9opWsnCtG/UxPgeuC28Rv2XNbFfft/hEEI39P/4Ag==}
dev: true
/@types/uni-app@1.4.4:
resolution: {integrity: sha512-ZTXnrCTblZyoLIoKbTv1Whz1nxrTcM7vg0qGXzDpXP8m9MqdjKt48N3FffQT1IsJWNkxbvJ1Eg5UHDaq+k+oBQ==}
dependencies:
vue: 2.7.14
dev: true
/@vue/compiler-sfc@2.7.14:
resolution: {integrity: sha512-aNmNHyLPsw+sVvlQFQ2/8sjNuLtK54TC6cuKnVzAY93ks4ZBrvwQSnkkIh7bsbNhum5hJBS00wSDipQ937f5DA==}
dependencies:
'@babel/parser': 7.22.5
postcss: 8.4.24
source-map: 0.6.1
dev: true
/async-limiter@1.0.1: /async-limiter@1.0.1:
resolution: {integrity: sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==} resolution: {integrity: sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==}
dev: false dev: false
@@ -114,11 +54,11 @@ packages:
dependencies: dependencies:
buffer: 5.7.1 buffer: 5.7.1
inherits: 2.0.4 inherits: 2.0.4
readable-stream: 3.6.1 readable-stream: 3.6.2
dev: false dev: false
/brace-expansion@1.1.11: /brace-expansion@1.1.12:
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
dependencies: dependencies:
balanced-match: 1.0.2 balanced-match: 1.0.2
concat-map: 0.0.1 concat-map: 0.0.1
@@ -135,13 +75,6 @@ packages:
ieee754: 1.2.1 ieee754: 1.2.1
dev: false dev: false
/call-bind@1.0.2:
resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==}
dependencies:
function-bind: 1.1.1
get-intrinsic: 1.2.1
dev: false
/callback-stream@1.1.0: /callback-stream@1.1.0:
resolution: {integrity: sha512-sAZ9kODla+mGACBZ1IpTCAisKoGnv6PykW7fPk1LrM+mMepE18Yz0515yoVcrZy7dQsTUp3uZLQ/9Sx1RnLoHw==} resolution: {integrity: sha512-sAZ9kODla+mGACBZ1IpTCAisKoGnv6PykW7fPk1LrM+mMepE18Yz0515yoVcrZy7dQsTUp3uZLQ/9Sx1RnLoHw==}
dependencies: dependencies:
@@ -170,22 +103,12 @@ packages:
typedarray: 0.0.6 typedarray: 0.0.6
dev: false dev: false
/copy-text-to-clipboard@3.2.0:
resolution: {integrity: sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q==}
engines: {node: '>=12'}
dev: false
/core-js@3.31.1:
resolution: {integrity: sha512-2sKLtfq1eFST7l7v62zaqXacPc7uG8ZAya8ogijLhTtaKNcpzpB4TMoTw2Si+8GYKRwFPMMtUT0263QFWFfqyQ==}
requiresBuild: true
dev: false
/core-util-is@1.0.3: /core-util-is@1.0.3:
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
dev: false dev: false
/crypto-js@4.1.1: /crypto-js@4.2.0:
resolution: {integrity: sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==} resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==}
dev: false dev: false
/css-line-break@2.1.0: /css-line-break@2.1.0:
@@ -194,19 +117,16 @@ packages:
utrie: 1.0.2 utrie: 1.0.2
dev: false dev: false
/csstype@3.1.2: /d@1.0.2:
resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==}
dev: true engines: {node: '>=0.12'}
/d@1.0.1:
resolution: {integrity: sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==}
dependencies: dependencies:
es5-ext: 0.10.62 es5-ext: 0.10.64
type: 1.2.0 type: 2.7.3
dev: false dev: false
/debug@4.3.4: /debug@4.4.1:
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==}
engines: {node: '>=6.0'} engines: {node: '>=6.0'}
peerDependencies: peerDependencies:
supports-color: '*' supports-color: '*'
@@ -214,59 +134,67 @@ packages:
supports-color: supports-color:
optional: true optional: true
dependencies: dependencies:
ms: 2.1.2 ms: 2.1.3
dev: false dev: false
/duplexify@3.7.1: /duplexify@3.7.1:
resolution: {integrity: sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==} resolution: {integrity: sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==}
dependencies: dependencies:
end-of-stream: 1.4.4 end-of-stream: 1.4.5
inherits: 2.0.4 inherits: 2.0.4
readable-stream: 2.3.8 readable-stream: 2.3.8
stream-shift: 1.0.1 stream-shift: 1.0.3
dev: false dev: false
/duplexify@4.1.2: /duplexify@4.1.3:
resolution: {integrity: sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==} resolution: {integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==}
dependencies: dependencies:
end-of-stream: 1.4.4 end-of-stream: 1.4.5
inherits: 2.0.4 inherits: 2.0.4
readable-stream: 3.6.1 readable-stream: 3.6.2
stream-shift: 1.0.1 stream-shift: 1.0.3
dev: false dev: false
/end-of-stream@1.4.4: /echarts@5.6.0:
resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} resolution: {integrity: sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==}
dependencies:
tslib: 2.3.0
zrender: 5.6.1
dev: false
/end-of-stream@1.4.5:
resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==}
dependencies: dependencies:
once: 1.4.0 once: 1.4.0
dev: false dev: false
/es5-ext@0.10.62: /es5-ext@0.10.64:
resolution: {integrity: sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==} resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==}
engines: {node: '>=0.10'} engines: {node: '>=0.10'}
requiresBuild: true requiresBuild: true
dependencies: dependencies:
es6-iterator: 2.0.3 es6-iterator: 2.0.3
es6-symbol: 3.1.3 es6-symbol: 3.1.4
esniff: 2.0.1
next-tick: 1.1.0 next-tick: 1.1.0
dev: false dev: false
/es6-iterator@2.0.3: /es6-iterator@2.0.3:
resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==}
dependencies: dependencies:
d: 1.0.1 d: 1.0.2
es5-ext: 0.10.62 es5-ext: 0.10.64
es6-symbol: 3.1.3 es6-symbol: 3.1.4
dev: false dev: false
/es6-map@0.1.5: /es6-map@0.1.5:
resolution: {integrity: sha512-mz3UqCh0uPCIqsw1SSAkB/p0rOzF/M0V++vyN7JqlPtSW/VsYgQBvVvqMLmfBuyMzTpLnNqi6JmcSizs4jy19A==} resolution: {integrity: sha512-mz3UqCh0uPCIqsw1SSAkB/p0rOzF/M0V++vyN7JqlPtSW/VsYgQBvVvqMLmfBuyMzTpLnNqi6JmcSizs4jy19A==}
dependencies: dependencies:
d: 1.0.1 d: 1.0.2
es5-ext: 0.10.62 es5-ext: 0.10.64
es6-iterator: 2.0.3 es6-iterator: 2.0.3
es6-set: 0.1.6 es6-set: 0.1.6
es6-symbol: 3.1.3 es6-symbol: 3.1.4
event-emitter: 0.3.5 event-emitter: 0.3.5
dev: false dev: false
@@ -274,32 +202,47 @@ packages:
resolution: {integrity: sha512-TE3LgGLDIBX332jq3ypv6bcOpkLO0AslAQo7p2VqX/1N46YNsvIWgvjojjSEnWEGWMhr1qUbYeTSir5J6mFHOw==} resolution: {integrity: sha512-TE3LgGLDIBX332jq3ypv6bcOpkLO0AslAQo7p2VqX/1N46YNsvIWgvjojjSEnWEGWMhr1qUbYeTSir5J6mFHOw==}
engines: {node: '>=0.12'} engines: {node: '>=0.12'}
dependencies: dependencies:
d: 1.0.1 d: 1.0.2
es5-ext: 0.10.62 es5-ext: 0.10.64
es6-iterator: 2.0.3 es6-iterator: 2.0.3
es6-symbol: 3.1.3 es6-symbol: 3.1.4
event-emitter: 0.3.5 event-emitter: 0.3.5
type: 2.7.2 type: 2.7.3
dev: false dev: false
/es6-symbol@3.1.3: /es6-symbol@3.1.4:
resolution: {integrity: sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==} resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==}
engines: {node: '>=0.12'}
dependencies: dependencies:
d: 1.0.1 d: 1.0.2
ext: 1.7.0 ext: 1.7.0
dev: false dev: false
/esniff@2.0.1:
resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==}
engines: {node: '>=0.10'}
dependencies:
d: 1.0.2
es5-ext: 0.10.64
event-emitter: 0.3.5
type: 2.7.3
dev: false
/event-emitter@0.3.5: /event-emitter@0.3.5:
resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==}
dependencies: dependencies:
d: 1.0.1 d: 1.0.2
es5-ext: 0.10.62 es5-ext: 0.10.64
dev: false
/exif-js@2.3.0:
resolution: {integrity: sha512-1Og9pAzG2FZRVlaavH8bB8BTeHcjMdJhKmeQITkX+uLRCD0xPtKAdZ2clZmQdJ56p9adXtJ8+jwrGp/4505lYg==}
dev: false dev: false
/ext@1.7.0: /ext@1.7.0:
resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==}
dependencies: dependencies:
type: 2.7.2 type: 2.7.3
dev: false dev: false
/extend@3.0.2: /extend@3.0.2:
@@ -310,19 +253,6 @@ packages:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
dev: false dev: false
/function-bind@1.1.1:
resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
dev: false
/get-intrinsic@1.2.1:
resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==}
dependencies:
function-bind: 1.1.1
has: 1.0.3
has-proto: 1.0.1
has-symbols: 1.0.3
dev: false
/glob-parent@3.1.0: /glob-parent@3.1.0:
resolution: {integrity: sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==} resolution: {integrity: sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==}
dependencies: dependencies:
@@ -348,6 +278,7 @@ packages:
/glob@7.2.3: /glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
deprecated: Glob versions prior to v9 are no longer supported
dependencies: dependencies:
fs.realpath: 1.0.0 fs.realpath: 1.0.0
inflight: 1.0.6 inflight: 1.0.6
@@ -357,23 +288,6 @@ packages:
path-is-absolute: 1.0.1 path-is-absolute: 1.0.1
dev: false dev: false
/has-proto@1.0.1:
resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==}
engines: {node: '>= 0.4'}
dev: false
/has-symbols@1.0.3:
resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
engines: {node: '>= 0.4'}
dev: false
/has@1.0.3:
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
engines: {node: '>= 0.4.0'}
dependencies:
function-bind: 1.1.1
dev: false
/help-me@1.1.0: /help-me@1.1.0:
resolution: {integrity: sha512-P/IZ8yOMne3SCTHbVY429NZ67B/2bVQlcYGZh2iPPbdLrEQ/qY5aGChn0YTDmt7Sb4IKRI51fypItav+lNl76w==} resolution: {integrity: sha512-P/IZ8yOMne3SCTHbVY429NZ67B/2bVQlcYGZh2iPPbdLrEQ/qY5aGChn0YTDmt7Sb4IKRI51fypItav+lNl76w==}
dependencies: dependencies:
@@ -395,12 +309,19 @@ packages:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
dev: false dev: false
/image-tool@1.0.2:
resolution: {integrity: sha512-D7fATR4b2rBPKaCsY7yajL9pVIha+vBTb5BqzqFXMRGIOVxxUOf4CEVrBt8LmGgcwp4Wa/JNLoaXNMDViOo8tg==}
dependencies:
exif-js: 2.3.0
dev: false
/image-tools@1.4.0: /image-tools@1.4.0:
resolution: {integrity: sha512-TKtvJ6iUwM0mfaD4keMnk1ENHFC470QEjBfA3IlvKdEOufzvWbjbaoNcoyYq6HlViF8+d5tOS1ooE6j7CHf1lQ==} resolution: {integrity: sha512-TKtvJ6iUwM0mfaD4keMnk1ENHFC470QEjBfA3IlvKdEOufzvWbjbaoNcoyYq6HlViF8+d5tOS1ooE6j7CHf1lQ==}
dev: false dev: false
/inflight@1.0.6: /inflight@1.0.6:
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
dependencies: dependencies:
once: 1.4.0 once: 1.4.0
wrappy: 1.0.2 wrappy: 1.0.2
@@ -462,8 +383,8 @@ packages:
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
dev: false dev: false
/jsrsasign@10.8.6: /jsrsasign@11.1.0:
resolution: {integrity: sha512-bQmbVtsfbgaKBTWCKiDCPlUPbdlRIK/FzSwT3BzIgZl/cU6TqXu6pZJsCI/dJVrZ9Gir5GC4woqw9shH/v7MBw==} resolution: {integrity: sha512-Ov74K9GihaK9/9WncTe1mPmvrO7Py665TUfUKvraXBpu+xcTWitrtuOwcjf4KMU9maPaYn0OuaWy0HOzy/GBXg==}
dev: false dev: false
/leven@2.1.0: /leven@2.1.0:
@@ -474,7 +395,7 @@ packages:
/minimatch@3.1.2: /minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
dependencies: dependencies:
brace-expansion: 1.1.11 brace-expansion: 1.1.12
dev: false dev: false
/minimist@1.2.8: /minimist@1.2.8:
@@ -485,7 +406,7 @@ packages:
resolution: {integrity: sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==} resolution: {integrity: sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==}
dependencies: dependencies:
bl: 4.1.0 bl: 4.1.0
debug: 4.3.4 debug: 4.4.1
process-nextick-args: 2.0.1 process-nextick-args: 2.0.1
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@@ -499,14 +420,14 @@ packages:
base64-js: 1.5.1 base64-js: 1.5.1
commist: 1.1.0 commist: 1.1.0
concat-stream: 1.6.2 concat-stream: 1.6.2
duplexify: 4.1.2 duplexify: 4.1.3
end-of-stream: 1.4.4 end-of-stream: 1.4.5
es6-map: 0.1.5 es6-map: 0.1.5
help-me: 1.1.0 help-me: 1.1.0
inherits: 2.0.4 inherits: 2.0.4
minimist: 1.2.8 minimist: 1.2.8
mqtt-packet: 6.10.0 mqtt-packet: 6.10.0
pump: 3.0.0 pump: 3.0.3
readable-stream: 2.3.8 readable-stream: 2.3.8
reinterval: 1.1.0 reinterval: 1.1.0
split2: 3.2.2 split2: 3.2.2
@@ -518,28 +439,14 @@ packages:
- utf-8-validate - utf-8-validate
dev: false dev: false
/ms@2.1.2: /ms@2.1.3:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
dev: false dev: false
/mutation-observer@1.0.3:
resolution: {integrity: sha512-M/O/4rF2h776hV7qGMZUH3utZLO/jK7p8rnNgGkjKUw8zCGjRQPxB8z6+5l8+VjRUQ3dNYu4vjqXYLr+U8ZVNA==}
dev: false
/nanoid@3.3.6:
resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
dev: true
/next-tick@1.1.0: /next-tick@1.1.0:
resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==}
dev: false dev: false
/object-inspect@1.12.3:
resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==}
dev: false
/once@1.4.0: /once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
dependencies: dependencies:
@@ -561,23 +468,10 @@ packages:
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
dev: false dev: false
/picocolors@1.0.0: /pinyin-pro@3.26.0:
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} resolution: {integrity: sha512-HcBZZb0pvm0/JkPhZHWA5Hqp2cWHXrrW/WrV+OtaYYM+kf35ffvZppIUuGmyuQ7gDr1JDJKMkbEE+GN0wfMoGg==}
dev: true
/pinyin-pro@3.13.2:
resolution: {integrity: sha512-DKz04M0PkrongGyJW7GU+iNB2jInwLcP1p5+w0gu0hz2PtF8q+GTC1GDW731wyhm+q7PGoyMuY3sLONLTqi6mg==}
dev: false dev: false
/postcss@8.4.24:
resolution: {integrity: sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==}
engines: {node: ^10 || ^12 || >=14}
dependencies:
nanoid: 3.3.6
picocolors: 1.0.0
source-map-js: 1.0.2
dev: true
/process-nextick-args@2.0.1: /process-nextick-args@2.0.1:
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
dev: false dev: false
@@ -585,14 +479,14 @@ packages:
/pump@2.0.1: /pump@2.0.1:
resolution: {integrity: sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==} resolution: {integrity: sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==}
dependencies: dependencies:
end-of-stream: 1.4.4 end-of-stream: 1.4.5
once: 1.4.0 once: 1.4.0
dev: false dev: false
/pump@3.0.0: /pump@3.0.3:
resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==}
dependencies: dependencies:
end-of-stream: 1.4.4 end-of-stream: 1.4.5
once: 1.4.0 once: 1.4.0
dev: false dev: false
@@ -604,13 +498,6 @@ packages:
pump: 2.0.1 pump: 2.0.1
dev: false dev: false
/qs@6.11.2:
resolution: {integrity: sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==}
engines: {node: '>=0.6'}
dependencies:
side-channel: 1.0.4
dev: false
/readable-stream@2.3.8: /readable-stream@2.3.8:
resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
dependencies: dependencies:
@@ -623,8 +510,8 @@ packages:
util-deprecate: 1.0.2 util-deprecate: 1.0.2
dev: false dev: false
/readable-stream@3.6.1: /readable-stream@3.6.2:
resolution: {integrity: sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ==} resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
dependencies: dependencies:
inherits: 2.0.4 inherits: 2.0.4
@@ -632,10 +519,6 @@ packages:
util-deprecate: 1.0.2 util-deprecate: 1.0.2
dev: false dev: false
/regenerator-runtime@0.13.11:
resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==}
dev: false
/reinterval@1.1.0: /reinterval@1.1.0:
resolution: {integrity: sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==} resolution: {integrity: sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==}
dev: false dev: false
@@ -652,32 +535,14 @@ packages:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
dev: false dev: false
/side-channel@1.0.4:
resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
dependencies:
call-bind: 1.0.2
get-intrinsic: 1.2.1
object-inspect: 1.12.3
dev: false
/source-map-js@1.0.2:
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
engines: {node: '>=0.10.0'}
dev: true
/source-map@0.6.1:
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
engines: {node: '>=0.10.0'}
dev: true
/split2@3.2.2: /split2@3.2.2:
resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==}
dependencies: dependencies:
readable-stream: 3.6.1 readable-stream: 3.6.2
dev: false dev: false
/stream-shift@1.0.1: /stream-shift@1.0.3:
resolution: {integrity: sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==} resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==}
dev: false dev: false
/string_decoder@1.1.1: /string_decoder@1.1.1:
@@ -720,17 +585,12 @@ packages:
is-negated-glob: 1.0.0 is-negated-glob: 1.0.0
dev: false dev: false
/to-fast-properties@2.0.0: /tslib@2.3.0:
resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==}
engines: {node: '>=4'}
dev: true
/type@1.2.0:
resolution: {integrity: sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==}
dev: false dev: false
/type@2.7.2: /type@2.7.3:
resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==} resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==}
dev: false dev: false
/typedarray@0.0.6: /typedarray@0.0.6:
@@ -763,22 +623,6 @@ packages:
base64-arraybuffer: 1.0.2 base64-arraybuffer: 1.0.2
dev: false dev: false
/vconsole@3.15.1:
resolution: {integrity: sha512-KH8XLdrq9T5YHJO/ixrjivHfmF2PC2CdVoK6RWZB4yftMykYIaXY1mxZYAic70vADM54kpMQF+dYmvl5NRNy1g==}
dependencies:
'@babel/runtime': 7.22.6
copy-text-to-clipboard: 3.2.0
core-js: 3.31.1
mutation-observer: 1.0.3
dev: false
/vue@2.7.14:
resolution: {integrity: sha512-b2qkFyOM0kwqWFuQmgd4o+uHGU7T+2z3T+WQp8UBjADfEv2n4FEMffzBmCKNP0IGzOEEfYjvtcC62xaSKeQDrQ==}
dependencies:
'@vue/compiler-sfc': 2.7.14
csstype: 3.1.2
dev: true
/websocket-stream@5.5.2: /websocket-stream@5.5.2:
resolution: {integrity: sha512-8z49MKIHbGk3C4HtuHWDtYX8mYej1wWabjthC/RupM9ngeukU4IWoM46dgth1UOS/T4/IqgEdCDJuMe2039OQQ==} resolution: {integrity: sha512-8z49MKIHbGk3C4HtuHWDtYX8mYej1wWabjthC/RupM9ngeukU4IWoM46dgth1UOS/T4/IqgEdCDJuMe2039OQQ==}
dependencies: dependencies:
@@ -817,3 +661,9 @@ packages:
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
engines: {node: '>=0.4'} engines: {node: '>=0.4'}
dev: false dev: false
/zrender@5.6.1:
resolution: {integrity: sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==}
dependencies:
tslib: 2.3.0
dev: false

2
readme
View File

@@ -9,7 +9,7 @@
njcnyw njcnyw
1.工程用户 1899999999 1.工程用户 18000001234 12345678
2.营销用户 1888888888 2.营销用户 1888888888
3.正式用户 187777777777 3.正式用户 187777777777
4.运维管理元 18666666666 4.运维管理元 18666666666

Some files were not shown because too many files have changed in this diff Show More