3 Commits

Author SHA1 Message Date
guanj
40899e6d55 修改测试问题 2026-07-02 09:55:30 +08:00
guanj
1d73755a43 修改测试问题 2026-06-29 11:01:44 +08:00
guanj
f008bcb4b8 优化强制更新功能 2026-06-18 16:34:25 +08:00
69 changed files with 4936 additions and 4416 deletions

View File

@@ -1,11 +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) //监听推送消息
// }) // })
@@ -72,4 +72,5 @@ export default {
// .uni-page-refresh__icon { // .uni-page-refresh__icon {
// fill: #007aff !important; /* 改成你想要的颜色,比如红色 #ff0000 */ // fill: #007aff !important; /* 改成你想要的颜色,比如红色 #ff0000 */
// } // }
</style> </style>

View File

@@ -2,14 +2,14 @@
"version" : "2", "version" : "2",
"prompt" : "template", "prompt" : "template",
"title" : "服务协议和隐私政策", "title" : "服务协议和隐私政策",
"message" : "  请你务必审慎阅读、充分理解“服务协议”和“隐私政策”各条款,包括但不限于:为了更好的向你提供服务,我们需要收集你的设备标识、操作日志等信息用于分析、优化应用性能。<br/>  你可阅读<a href=\"https://pqmcn.com:8092/#/agreement\">《服务协议》</a>和<a href=\"https://pqmcn.com:8092/#/policy\">《隐私政策》</a>了解详细信息。如果你同意,请点击下面按钮开始接受我们的服务。", "message" : "  请你务必审慎阅读、充分理解“服务协议”和“隐私政策”各条款,包括但不限于:为了更好的向你提供服务,我们需要收集你的设备标识、操作日志等信息用于分析、优化应用性能。<br/>  你可阅读<a href=\"http://www.pqmcc.com:27707/#/agreement\">《服务协议》</a>和<a href=\"http://www.pqmcc.com:27707/#/policy\">《隐私政策》</a>了解详细信息。如果你同意,请点击下面按钮开始接受我们的服务。",
"buttonAccept" : "同意并接受", "buttonAccept" : "同意并接受",
"buttonRefuse" : "暂不同意", "buttonRefuse" : "暂不同意",
"hrefLoader" : "system|default", "hrefLoader" : "system|default",
"backToExit" : "false", "backToExit" : "false",
"second" : { "second" : {
"title" : "确认提示", "title" : "确认提示",
"message" : "  进入应用前,你需先同意<a href=\"https://pqmcn.com:8092/#/agreement\">《用户协议》</a>和<a href=\"https://pqmcn.com:8092/#/policy\">《隐私政策》</a>,否则将退出应用。", "message" : "  进入应用前,你需先同意<a href=\"http://www.pqmcc.com:27707/#/agreement\">《用户协议》</a>和<a href=\"http://www.pqmcc.com:27707/#/policy\">《隐私政策》</a>,否则将退出应用。",
"buttonAccept" : "同意并继续", "buttonAccept" : "同意并继续",
"buttonRefuse" : "退出应用" "buttonRefuse" : "退出应用"
}, },

View File

@@ -11,6 +11,7 @@ export function addFeedBack(params) {
console.log(files.length); console.log(files.length);
let data = JSON.parse(JSON.stringify(params)); let data = JSON.parse(JSON.stringify(params));
delete data.files delete data.files
console.log("🚀 ~ addFeedBack ~ files.length:", files.length)
if (files.length) { if (files.length) {
return uni.uploadFile({ return uni.uploadFile({
url: config.domain + '/cs-system-boot/feedback/addFeedBack', //仅为示例,非真实的接口地址 url: config.domain + '/cs-system-boot/feedback/addFeedBack', //仅为示例,非真实的接口地址

View File

@@ -242,4 +242,4 @@ export function getLastData() {
url: '/cs-system-boot/appVersion/getLastData?versionType=APP', url: '/cs-system-boot/appVersion/getLastData?versionType=APP',
method: 'POST', method: 'POST',
}) })
} }

View File

@@ -1,11 +1,12 @@
const debug = true // true 是连地服务端本地false 是连接线上 const debug = false // true 是连地服务端本地false 是连接线上
const development = { const development = {
domain: 'http://192.168.2.126:10215', // domain: 'http://192.168.1.103:10215',
domain: 'http://192.168.1.102:27707/api',
} }
const production = { const production = {
domain: 'https://pqmcn.com:8092/api', domain: 'http://www.pqmcc.com:27707/api',
} }
const config = debug ? development : production const config = debug ? development : production

View File

@@ -1,5 +1,6 @@
// 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:38083/mqtt'//mqtt地址端口, 使用emqx时一定要加mqtt // export const MQTT_IP = '192.168.1.103:38083/mqtt'//mqtt地址端口, 使用emqx时一定要加mqtt
// export const MQTT_IP = '192.168.1.103:38083/mqtt'//mqtt地址端口, 使用emqx时一定要加mqtt
const MQTT_USERNAME = 't_user'//mqtt用户名 const MQTT_USERNAME = 't_user'//mqtt用户名
const MQTT_PASSWORD = 'njcnpqs'//密码 const MQTT_PASSWORD = 'njcnpqs'//密码

View File

@@ -83,7 +83,10 @@ function errHandler(res) {
break break
default: default:
uni.showToast({ uni.showToast({
title: res.message || res.msg || '网络异常,请稍后再试', title:
res.message.substring(res.message.indexOf(',') + 1) ||
res.msg.substring(msg.indexOf(',') + 1) ||
'网络异常,请稍后再试',
duration: 2000, duration: 2000,
icon: 'none', icon: 'none',
}) })

View File

@@ -1,52 +1,102 @@
import { getLastData } from '../api/user.js' import { getLastData } from '../api/user.js'
/** 规范化版本号,如 v1.6.83 → [1, 6, 83] */
const normalizeVersion = (version) => {
if (!version) return []
return String(version)
.replace(/^v/i, '')
.split('.')
.map((part) => parseInt(part, 10) || 0)
}
/**
* 比较版本号
* @returns 1 远端较新需更新 | 0 相同 | -1 本地较新
*/
const compareVersion = (remote, local) => {
const remoteParts = normalizeVersion(remote)
const localParts = normalizeVersion(local)
const len = Math.max(remoteParts.length, localParts.length)
for (let i = 0; i < len; i++) {
const rv = remoteParts[i] || 0
const lv = localParts[i] || 0
if (rv > lv) return 1
if (rv < lv) return -1
}
return 0
}
/** 自定义调试基座 / HBuilder 标准基座,不走线上更新 */
const isCustomDebugBase = (appName = '') => {
return /自定义基座|custom debug|HBuilder|DCloud/i.test(appName)
}
export const checkAppUpdate = () => { export const checkAppUpdate = () => {
// #ifndef APP-PLUS
// return
// #endif
// 开发环境跳过检查 // 开发环境跳过检查
const isDev = process.env.NODE_ENV === 'development' const isDev = process.env.NODE_ENV === 'development'
// if (isDev) { if (isDev) {
console.log('开发环境,不执行更新检查') console.log('开发环境,不执行更新检查')
return return
// } }
// 自定义基座调试,跳过更新检查
// try {
// const { appName } = uni.getSystemInfoSync()
// if (isCustomDebugBase(appName)) {
// console.log('自定义基座调试中,不执行更新检查')
// return
// }
// } catch (e) {}
// 获取当前应用信息 // 获取当前应用信息
plus.runtime.getProperty(plus.runtime.appid, (info) => { plus.runtime.getProperty(plus.runtime.appid, (info) => {
// if (isCustomDebugBase(info?.name)) {
// console.log('自定义基座调试中,不执行更新检查')
// return
// }
const currentVersion = info.version const currentVersion = info.version
getLastData() getLastData()
.then((res) => { .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
}
// let res = { // 适配新的接口返回格式,默认强制更新
// data: { const { versionName, androidPath, iosPath, forceUpdate = '1' } = res.data
// versionName: 'v1.6.83', console.log('🚀 ~ checkAppUpdate ~ versionName, currentVersion:', versionName, currentVersion)
// 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 (compareVersion(versionName, currentVersion) <= 0) {
console.log('已是最新版本')
return
}
// 版本相同则不需要更新 const isForce = forceUpdate !== '0' // 默认强制更新,'0' 为可选更新
if (versionName.includes(currentVersion)) {
console.log('已是最新版本')
return
}
const isForce = forceUpdate === '1' // 字符串 '1' 表示强制更新 const iosUrl = iosPath
const iosUrl = iosPath handleUpdate({ version: versionName, androidPath, iosUrl, isForce })
})
handleUpdate({ version: versionName, androidPath, iosUrl, isForce }) .catch((err) => {
}) console.error('获取版本接口失败', err)
.catch((err) => { })
console.error('获取版本接口失败', err)
})
}) })
} }
@@ -58,9 +108,9 @@ const handleUpdate = ({ version, androidPath, iosUrl, isForce }) => {
const isIOS = plus.os.name === 'iOS' const isIOS = plus.os.name === 'iOS'
if (isAndroid) { if (isAndroid) {
handleAndroidUpdate({ androidPath, isForce }) handleAndroidUpdate({ version, androidPath, isForce })
} else if (isIOS) { } else if (isIOS) {
handleIOSUpdate({ iosUrl, isForce }) handleIOSUpdate({ version, iosUrl, isForce })
} else { } else {
console.warn('未知操作系统') console.warn('未知操作系统')
} }
@@ -69,7 +119,7 @@ const handleUpdate = ({ version, androidPath, iosUrl, isForce }) => {
/** /**
* 处理安卓更新 * 处理安卓更新
*/ */
const handleAndroidUpdate = ({ androidPath, isForce }) => { const handleAndroidUpdate = ({ version, androidPath, isForce }) => {
if (!androidPath?.length) { if (!androidPath?.length) {
console.error('未找到安卓安装包') console.error('未找到安卓安装包')
uni.showToast({ uni.showToast({
@@ -80,18 +130,18 @@ const handleAndroidUpdate = ({ androidPath, isForce }) => {
} }
const downloadUrl = androidPath const downloadUrl = androidPath
const content = isForce ? `发现新版本 ${version},请立即更新后继续使用` : `发现新版本 ${version},是否立即更新?`
uni.showModal({ uni.showModal({
title: '更新提示', title: '更新提示',
content: '发现新版本,是否立即更新?', content,
showCancel: !isForce, // 强制更新隐藏取消按钮 showCancel: false,
confirmText: '去更新', confirmText: '去更新',
cancelText: '暂不更新',
success: (modalRes) => { success: (modalRes) => {
if (modalRes.confirm) { if (modalRes.confirm) {
downloadAndInstallApk(downloadUrl) downloadAndInstallApk(downloadUrl)
} else if (isForce) { } else if (isForce) {
// 强制更新用户取消,退出应用 // 强制更新用户按返回键关闭弹窗时退出
plus.runtime.quit() plus.runtime.quit()
} }
}, },
@@ -101,7 +151,7 @@ const handleAndroidUpdate = ({ androidPath, isForce }) => {
/** /**
* 处理iOS更新 * 处理iOS更新
*/ */
const handleIOSUpdate = ({ iosUrl, isForce }) => { const handleIOSUpdate = ({ version, iosUrl, isForce }) => {
if (!iosUrl) { if (!iosUrl) {
console.error('未找到iOS下载链接') console.error('未找到iOS下载链接')
uni.showToast({ uni.showToast({
@@ -111,22 +161,23 @@ const handleIOSUpdate = ({ iosUrl, isForce }) => {
return return
} }
const content = isForce
? `发现新版本 ${version},请前往 App Store 更新后继续使用`
: `发现新版本 ${version},请前往 App Store 更新`
uni.showModal({ uni.showModal({
title: '更新提示', title: '更新提示',
content: '发现新版本,请前往 App Store 更新', content,
showCancel: !isForce, showCancel: false,
confirmText: '去更新', confirmText: '去更新',
cancelText: '暂不更新',
success: (modalRes) => { success: (modalRes) => {
if (modalRes.confirm) { if (modalRes.confirm) {
plus.runtime.openURL(iosUrl) plus.runtime.openURL(iosUrl)
}
// 强制更新时,无论确认还是取消都退出应用
if (isForce) {
setTimeout(() => { setTimeout(() => {
plus.runtime.quit() plus.runtime.quit()
}, 300) // 给跳转留一点时间 }, 300)
} else if (isForce) {
// 强制更新且用户取消,退出应用
} }
}, },
}) })
@@ -143,14 +194,22 @@ const downloadAndInstallApk = (url) => {
close: false, // 不允许用户关闭 close: false, // 不允许用户关闭
padlock: true, // 锁定屏幕 padlock: true, // 锁定屏幕
}) })
let progressClosed = false
const closeProgress = () => {
if (progressClosed) return
progressClosed = true
progressWaiting.close()
}
const options = { const options = {
filename: '_doc/update/canneng_wulian.apk', filename: '_doc/update/canneng_wulian.apk',
timeout: 120, timeout: 300,
} }
console.log('🚀 ~ downloadAndInstallApk ~ url:', url)
const downloadTask = plus.downloader.createDownload(url, options, (downloadedFile, status) => { const downloadTask = plus.downloader.createDownload(url, options, (downloadedFile, status) => {
progressWaiting.close() closeProgress()
if (status === 200) { if (status === 200) {
installApk(downloadedFile.filename, url) installApk(downloadedFile.filename, url)
@@ -161,11 +220,12 @@ const downloadAndInstallApk = (url) => {
// // 更新进度 // // 更新进度
downloadTask.addEventListener('statechanged', (task) => { downloadTask.addEventListener('statechanged', (task) => {
if (progressClosed) return
if (task.state === 3 && task.totalSize > 0) { if (task.state === 3 && task.totalSize > 0) {
const percent = ((task.downloadedSize / task.totalSize) * 100).toFixed(0) const percent = ((task.downloadedSize / task.totalSize) * 100).toFixed(0)
console.log("🚀 ~ downloadAndInstallApk ~ percent:", percent) console.log('🚀 ~ downloadAndInstallApk ~ percent:', percent)
// 直接更新 waiting 的标题,不会闪烁 // 直接更新 waiting 的标题,不会闪烁
progressWaiting.setTitle(`正在下载更新 ${percent}%`) progressWaiting.setTitle(`正在下载更新...`)
} }
}) })
@@ -197,11 +257,13 @@ const installApk = (filePath, downloadUrl) => {
uni.showModal({ uni.showModal({
title: '安装失败', title: '安装失败',
content: `安装失败:${error.message}\n请检查是否已开启安装权限`, content: `安装失败:${error.message}\n请检查是否已开启安装权限`,
showCancel: false,
confirmText: '重试', confirmText: '重试',
cancelText: '取消',
success: (res) => { success: (res) => {
if (res.confirm) { if (res.confirm) {
downloadAndInstallApk(downloadUrl) downloadAndInstallApk(downloadUrl)
} else {
plus.runtime.quit()
} }
}, },
}) })
@@ -216,11 +278,13 @@ const handleDownloadError = (downloadUrl) => {
uni.showModal({ uni.showModal({
title: '下载失败', title: '下载失败',
content: '网络异常或下载链接失效,是否重试?', content: '网络异常或下载链接失效,是否重试?',
showCancel: false,
confirmText: '重试', confirmText: '重试',
cancelText: '取消',
success: (res) => { success: (res) => {
if (res.confirm) { if (res.confirm) {
downloadAndInstallApk(downloadUrl) downloadAndInstallApk(downloadUrl)
} else {
plus.runtime.quit()
} }
}, },
}) })

View File

@@ -183,35 +183,6 @@ const validatePhoneNumber = (phone) => {
return testReg.test(phone) return testReg.test(phone)
} }
const getUserLocation = (call) => {
uni.getLocation({
type: 'wgs84',
success: function (address) {
call(address)
},
fail: (err) => {
uni.showModal({
title: '提示',
content: '定位失败,请打开定位权限',
success: function (res) {
if (res.confirm) {
uni.openSetting({
success: (resSett) => {
if (resSett.authSetting['scope.userLocation']) {
uni.getLocation({
success: (address) => {
call && call(address)
},
})
}
},
})
}
},
})
},
})
}
// 加载用户配置 // 加载用户配置
var globalConfigIsLoading = false, var globalConfigIsLoading = false,
@@ -349,7 +320,6 @@ export default {
formatTime, formatTime,
parseTime, parseTime,
h5Helper, h5Helper,
getUserLocation,
loadConfig, loadConfig,
prePage, prePage,
loginSuccess, loginSuccess,

View File

@@ -16,15 +16,15 @@ export default {
}, },
computed: { computed: {
svgHtml() { svgHtml() {
if (this.name == '电压暂降') { if (this.name == '暂降') {
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100"> 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"/> <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>` </svg>`
} else if (this.name == '电压暂升') { } else if (this.name == '暂升') {
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100"> 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"/> <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>` </svg>`
} else if (this.name == '电压中断') { } else if (this.name == '中断') {
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100"> 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"/> <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>` </svg>`

View File

@@ -12,7 +12,7 @@
:style="{ color: confirmColor }" :style="{ color: confirmColor }"
hover-class="hover-c" hover-class="hover-c"
@tap="_confirm" @tap="_confirm"
>确定</view >完成</view
> >
</view> </view>
<view class="tki-tree-bar1"> <view class="tki-tree-bar1">

View File

@@ -1,201 +1,222 @@
<template> <template>
<view> <view>
<!-- 遮罩 --> <!-- 遮罩 -->
<view class="mask" v-if="show" @tap="show = false" @touchmove.stop.prevent></view> <view class="mask" v-if="show" @tap="show = false" @touchmove.stop.prevent></view>
<!-- 按钮 --> <!-- 按钮 -->
<view class="major-box" :class="{ show: show }"> <view class="major-box" :class="{ show: show }">
<view <view class="click-btn" v-if="!show" @tap="show = !show" draggable="true">
class="click-btn"
v-if="!show" <!-- <view>&lt;&nbsp;</view> -->
@tap="show = !show" <uni-icons type="left" size="26" color="#645555"></uni-icons>
draggable="true" </view>
<view class="nav-box" v-if="show" style="max-width: 320px;">
> <view class="click-btn click-btn-right" @tap="show = !show" draggable="true">
<!-- @touchstart="touchstart"
@touchmove.stop.prevent="touchmove" --> <!-- <view>&gt;&nbsp;</view> -->
<view>&lt;&nbsp;</view> <uni-icons type="right" size="26" color="#645555"></uni-icons>
</view> </view>
<view class="nav-box" v-if="show" style="max-width: 320px;"> <view class="nav-box-list">
<view class="nav-btn" v-for="(btn, index) in btnList" :key="index" @tap="clickBtn(btn)"> <view class="nav-btn" v-for="(btn, index) in btnList" :key="index" @tap="clickBtn(btn)">
<view class="nav-icon"> <view class="nav-icon">
<image class="icon" :src="btn.iconPath"></image> <image class="icon" :src="btn.iconPath"></image>
</view> </view>
<view class="nav-text">{{ btn.text }}</view> <view class="nav-text">{{ btn.text }}</view>
</view> </view>
</view> </view>
</view> </view>
</view> </view>
</template> </view>
</template>
<script>
export default { <script>
props: { export default {
btnList: { props: {
btnList: {
default: {},
}, default: {},
}, },
data() { },
return { data() {
show: false, // 是否显示 return {
deviationTop: 0, // 偏移量 show: false, // 是否显示
windowHeight: uni.getSystemInfoSync().windowHeight, // 视图高度 deviationTop: 0, // 偏移量
// btnList: [ windowHeight: uni.getSystemInfoSync().windowHeight, // 视图高度
// // 所有按钮 // btnList1: [
// { // // 所有按钮
// text: '首页', // {
// icon: '/static/report.png', // text: '首页',
// type: 1, // icon: '/static/report.png',
// }, // type: 1,
// { // },
// text: '列表', // {
// icon: '../../static/icon-add.png', // text: '列表',
// type: 2, // icon: '../../static/icon-add.png',
// }, // type: 2,
// { // },
// text: '列表详情', // {
// icon: '../../static/icon-visit.png', // text: '列表详情',
// type: 3, // icon: '../../static/icon-visit.png',
// }, // type: 3,
// { // },
// text: '列表详情', // {
// icon: '../../static/icon-visit.png', // text: '列表详情',
// type: 3, // icon: '../../static/icon-visit.png',
// }, // type: 3,
// { // },
// text: '列表详情', // {
// icon: '../../static/icon-visit.png', // text: '列表详情',
// type: 3, // icon: '../../static/icon-visit.png',
// }, // type: 3,
// { // },
// text: '列表详情', // {
// icon: '../../static/icon-visit.png', // text: '列表详情',
// type: 3, // icon: '../../static/icon-visit.png',
// }, // type: 3,
// { // },
// text: '列表详情', // {
// icon: '../../static/icon-visit.png', // text: '列表详情',
// type: 3, // icon: '../../static/icon-visit.png',
// }, // type: 3,
// ], // },
} // ],
}, }
methods: { },
// 点击按钮 methods: {
clickBtn: function (type) { // 点击按钮
// console.log(`123`, type) clickBtn: function (type) {
this.$emit('trigger',type) // console.log(`123`, type)
}, this.$emit('trigger', type)
// 拖动开始,记录一下偏移量 },
touchstart: function (e) { // 拖动开始,记录一下偏移量
var touch = e.touches[0] || e.changedTouches[0] touchstart: function (e) {
this.deviationTop = touch.clientY - this.top var touch = e.touches[0] || e.changedTouches[0]
// console.log(this.deviationTop); this.deviationTop = touch.clientY - this.top
}, // console.log(this.deviationTop);
// 上下拖动时 },
touchmove: function (e) { // 上下拖动时
var touch = e.touches[0] || e.changedTouches[0] touchmove: function (e) {
var top = touch.clientY var touch = e.touches[0] || e.changedTouches[0]
top = top - this.deviationTop var top = touch.clientY
if (top < 0) { top = top - this.deviationTop
top = 0 if (top < 0) {
} top = 0
if (top > this.windowHeight - 40) { }
top = this.windowHeight - 40 if (top > this.windowHeight - 40) {
} top = this.windowHeight - 40
this.top = top }
return false this.top = top
}, return false
}, },
} },
</script> }
</script>
<style>
/* 遮罩 */ <style>
.mask { /* 遮罩 */
position: fixed; .mask {
width: 100%; position: fixed;
height: 100%; width: 100%;
top: 0; height: 100%;
left: 0; top: 0;
z-index: 99; left: 0;
/* background: rgba(248, 248, 248, 0.8); */ z-index: 99;
} /* background: rgba(248, 248, 248, 0.8); */
}
/* 总盒子 */
.major-box { /* 总盒子 */
border: 1px 0 solid; .major-box {
z-index: 100; border: 1px 0 solid;
position: fixed; z-index: 100;
bottom: 5%; position: fixed;
right: 0; bottom: 5%;
transition: left 0.5s; right: 0;
overflow: hidden; transition: left 0.5s;
} overflow: hidden;
}
.click-btn,
.nav-box { .click-btn,
float: left; .nav-box {
} float: left;
}
/* 按钮样式 */
.nav-box { /* 按钮样式 */
background-color: #fff; .nav-box {
border-radius: 0 0 0 5px; background-color: #fff;
} border-radius: 0 0 0 5px;
padding: 5px 0;
.click-btn { }
width: 20px;
height: 40px; .click-btn {
background-color: #999; display: flex;
color: #fff; align-items: center;
opacity: 0.8; justify-content: center;
text-align: center; width: 30px;
border-radius: 50px 0 0 50px; min-height: 40px;
padding: 6px 0; height: 100%;
} background-color: #d8d7d7;
color: #fff;
.click-btn uni-view { opacity: 0.8;
line-height: 40px; text-align: center;
font-size: 12px; border-radius: 50px 0 0 50px;
} padding: 6px 0;
font-weight: 700;
.click-btn view {
padding-left: 8px; }
}
.click-btn uni-view {
/* 按钮盒子 */ line-height: 40px;
.nav-box { font-size: 15px;
display: flex; }
flex-wrap: wrap;
text-align: center; .click-btn view {
padding-left: 20px; padding-left: 8px;
/* justify-content: center; */ }
background-color: #d8d7d7;
color: #000; .click-btn-right {
font-size: 12rpx; background-color: #d8d7d7;
/* opacity: 0.8; */ margin-left: 5px;
text-align: center;
border-radius: 50px 0 0 50px; }
/* border-width: 0px; */ /* 按钮盒子 */
.nav-box {
} display: flex;
.nav-btn { text-align: center;
/* flex: 1; */ align-items: center;
border: 0px #000 solid;
min-width: 63px; background-color: #d8d7d7;
padding: 5px 0 5px 0; color: #000;
} font-size: 12rpx;
text-align: center;
.icon { border-radius: 50px 0 0 50px;
margin: 0 auto; }
width: 20px; .nav-box-list{
height: 20px; display: flex;
} flex-wrap: wrap;
text-align: center;
.nav-text { align-items: center;
font-size: 12px; gap: 8px 0;
} background-color: #d8d7d7;
</style> color: #000;
font-size: 12rpx;
text-align: center;
}
.nav-btn {
/* flex: 1; */
border: 0px #000 solid;
min-width: 55px;
}
.icon {
margin: 0 auto;
width: 20px;
height: 20px;
}
.nav-text {
font-size: 12px;
}
</style>

View File

@@ -2,8 +2,8 @@
"name" : "灿能物联", "name" : "灿能物联",
"appid" : "__UNI__88BC25B", "appid" : "__UNI__88BC25B",
"description" : "", "description" : "",
"versionName" : "1.6.82", "versionName" : "2.0.1",
"versionCode" : 170, "versionCode" : 176,
"transformPx" : false, "transformPx" : false,
"sassImplementationName" : "node-sass", "sassImplementationName" : "node-sass",
/* 5+App */ /* 5+App */
@@ -46,6 +46,7 @@
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>", "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>", "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.INTERNET\"/>", "<uses-permission android:name=\"android.permission.INTERNET\"/>",
"<uses-permission android:name=\"android.permission.REQUEST_INSTALL_PACKAGES\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>", "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>", "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>", "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
@@ -124,7 +125,10 @@
"setting" : { "setting" : {
"urlCheck" : false "urlCheck" : false
}, },
"usingComponents" : true "usingComponents" : true,
"unipush" : {
"enable" : false
}
}, },
"mp-alipay" : { "mp-alipay" : {
"usingComponents" : true "usingComponents" : true
@@ -138,8 +142,9 @@
"proxy" : { "proxy" : {
"/api" : { "/api" : {
"https" : true, "https" : true,
// "target" : "https://pqmcn.com:8092/api", "target" : "http://www.pqmcc.com:27707/api",
"target" : "http://192.168.2.126:10215", // "target" : "http://192.168.1.102:27707/api",
// "target" : "http://192.168.1.103:10215",
"changOrigin" : true, "changOrigin" : true,
"pathRewrite" : { "pathRewrite" : {
"/api" : "" "/api" : ""
@@ -152,7 +157,7 @@
"base" : "" "base" : ""
}, },
"unipush" : { "unipush" : {
"enable" : false "enable" : true
}, },
"sdkConfigs" : { "sdkConfigs" : {
"maps" : {} "maps" : {}

View File

@@ -118,14 +118,14 @@
{ {
"path": "pages/mine/setupMessage", "path": "pages/mine/setupMessage",
"style": { "style": {
"navigationBarTitleText": "个性化推荐" "navigationBarTitleText": "推送通知配置"
} }
}, },
{ {
"path": "pages/index/comp/monitoringPoint", "path": "pages/index/comp/monitoringPoint",
"style": { "style": {
"navigationBarTitleText": "监测点电能质量信息", "navigationBarTitleText": "关键指标概览",
"enablePullDownRefresh": true, "enablePullDownRefresh": true,
"pullToRefresh": { "pullToRefresh": {
"support":true, "support":true,
@@ -234,13 +234,13 @@
{ {
"path": "pages/device/APF/about", "path": "pages/device/APF/about",
"style": { "style": {
"navigationBarTitleText": "关于" "navigationBarTitleText": "详情"
} }
}, },
{ {
"path": "pages/device/DVR/about", "path": "pages/device/DVR/about",
"style": { "style": {
"navigationBarTitleText": "关于" "navigationBarTitleText": "详情"
} }
}, },
{ {
@@ -446,12 +446,7 @@
"navigationBarTitleText": "服务内容配置" "navigationBarTitleText": "服务内容配置"
} }
}, },
{
"path": "pages/mine/transientSetting",
"style": {
"navigationBarTitleText": "暂态事件配置"
}
},
{ {
"path": "pages/user/erweima", "path": "pages/user/erweima",
"style": { "style": {

View File

@@ -1,86 +1,70 @@
<template> <template>
<view> <view>
<uni-load-more status="loading" v-if="IOData.length == 0"></uni-load-more> <uni-load-more status="loading" v-if="IOData.length == 0"></uni-load-more>
<view class="basic" v-else> <view class="basic mt10" v-else>
<view class="grid-card"> <view class="params-wrap">
<text> <view class="section-title-row">
<view class="grid-card-title grid-card-title-with-icon"></view>温度 <view class="section-title">
</text> <view class="grid-card-title-with-icon"></view>
<view class="grid-card-content-4"> <text>温度</text>
<template v-for="item in renderData"> </view>
<view class="item item-title">{{ item[0].clDid }} </view>
<template v-if="item[0].clDid"> (°C)</template> <view class="params-section">
<view
v-for="(rowItems, rowIdx) in chunkedChildren(temperatureCards)"
:key="'temp-' + rowIdx"
class="double-row"
>
<view v-for="(child, childIdx) in rowItems" :key="childIdx" class="param-group">
<view class="param-title">
<text>{{ child.name }}</text>
</view>
<view class="param-value-wrap">
<text class="param-value">{{ child.value }}</text>
</view>
</view> </view>
<view class="item item-title">{{ item[1].clDid }} </view>
<template v-if="item[1].clDid"> (°C)</template>
</view>
<view class="item item-title">{{ item[2].clDid }}
<template v-if="item[2].clDid"> (°C)</template>
</view>
<view class="item item-title">{{ item[3].clDid }}
<template v-if="item[3].clDid"> (°C)</template>
</view>
<view class="item">{{ item[0].clDid ? Math.round(item[0].value) || '-' : '' }}</view>
<view class="item">{{ item[1].clDid ? Math.round(item[1].value) || '-' : '' }}</view>
<view class="item">{{ item[2].clDid ? Math.round(item[2].value) || '-' : '' }}</view>
<view class="item">{{ item[3].clDid ? Math.round(item[3].value) || '-' : '' }}</view>
</template>
</view> </view>
</view> </view>
<!-- 运维管理员工程用户 可看 -->
<view class="grid-card" <view class="params-wrap" v-if="showModuleSection">
v-if="(userInfo.authorities == 'operation_manager' || userInfo.authorities == 'engineering_user') && moduleData.length > 0"> <view class="section-title-row">
<view class="grid-card-title"> <view class="section-title">
<view class="grid-card-title-with-icon"></view>
<text><view class="grid-card-title-with-icon"></view>状态</text> <text>状态</text>
</view>
</view> </view>
<view class="grid-card-content-4"> <view class="params-section">
<template v-for="(item, index) in moduleData"> <view
<view class="item item-title">{{ item[0].moduleName }} v-for="(rowItems, rowIdx) in chunkedChildren(moduleCards)"
<template v-if="item[0].moduleName"></template> :key="'module-' + rowIdx"
class="double-row"
>
<view v-for="(child, childIdx) in rowItems" :key="childIdx" class="param-group">
<view class="param-title">
<text>{{ child.name }}</text>
</view>
<view class="param-value-wrap">
<text
class="param-value"
:class="{ 'param-value--offline': child.value === '离线' }"
>{{ child.value }}</text>
</view>
</view> </view>
<view class="item item-title">{{ item[1].moduleName }} </view>
<template v-if="item[1].moduleName"></template>
</view>
<view class="item item-title">{{ item[2].moduleName }}
<template v-if="item[2].moduleName"></template>
</view>
<view class="item item-title">{{ item[3].moduleName }}
<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>
<view class="item">{{ item[1].moduleState }}</view>
<view class="item">{{ item[2].moduleState }}</view>
<view class="item">{{ item[3].moduleState }}</view>
</template>
</view> </view>
</view> </view>
<!-- <view class="grid-card">-->
<!-- <view class="grid-card-title">干接点</view>-->
<!-- <view class="grid-card-content-4">-->
<!-- <view class="item item-title">干接点1</view>-->
<!-- <view class="item item-title">干接点2</view>-->
<!-- <view class="item item-title"></view>-->
<!-- <view class="item item-title"></view>-->
<!-- <view class="item">正常</view>-->
<!-- <view class="item">正常</view>-->
<!-- <view class="item"></view>-->
<!-- <view class="item"></view>-->
<!-- </view>-->
<!-- </view>-->
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import { getModuleState } from '@/common/api/harmonic.js' import { getModuleState } from '@/common/api/harmonic.js'
export default { export default {
props: { props: {
IOData: { IOData: {
type: Array, type: Array,
default: () => { default: () => [],
return []
},
}, },
ndid: { ndid: {
type: String, type: String,
@@ -90,87 +74,174 @@ export default {
return { return {
list: [], list: [],
userInfo: {}, userInfo: {},
flag: false,
} }
}, },
computed: { computed: {
renderData() { renderData() {
let arr = [] const arr = []
const data = this.IOData || []
// 把IOData转换成每4个一组的二维数组 for (let i = 0; i < data.length; i += 4) {
for (let i = 0; i < this.IOData.length; i += 4) { const group = data.slice(i, i + 4).map((item) => {
this.IOData.slice(i, i + 4).forEach((item) => { const next = { ...item }
if (Number.isInteger(item.value) || item.value == '') { if (!Number.isInteger(next.value) && next.value !== '') {
} else { next.value = (next.value - 0).toFixed(2)
item.value = (item.value - 0).toFixed(2)
} }
return next
}) })
arr.push(this.IOData.slice(i, i + 4)) while (group.length < 4) {
} group.push({})
// 把每组的长度补齐到4
arr.forEach((item) => {
if (item.length < 4) {
let length = 4 - item.length
for (let i = 0; i < length; i++) {
item.push({})
}
} }
}) arr.push(group)
}
return arr return arr
}, },
moduleData() { moduleData() {
let arr = [] const arr = []
// 把IOData转换成每4个一组的二维数组
for (let i = 0; i < this.list.length; i += 4) { for (let i = 0; i < this.list.length; i += 4) {
arr.push(this.list.slice(i, i + 4)) const group = this.list.slice(i, i + 4)
} while (group.length < 4) {
// 把每组的长度补齐到4 group.push({})
arr.forEach((item) => {
if (item.length < 4) {
let length = 4 - item.length
for (let i = 0; i < length; i++) {
item.push({})
}
} }
}) arr.push(group)
console.warn(arr) }
return arr return arr
}, },
temperatureCards() {
const cards = []
this.renderData.forEach((row) => {
row.forEach((item) => {
if (!item.clDid) return
cards.push({
name: `${item.clDid} (°C)`,
value: Math.round(item.value) ,
})
})
})
return cards
},
moduleCards() {
const cards = []
this.moduleData.forEach((row) => {
row.forEach((item) => {
if (!item.moduleName) return
cards.push({
name: item.moduleName,
value: item.moduleState ,
})
})
})
return cards
},
showModuleSection() {
return (
(this.userInfo.authorities === 'operation_manager' ||
this.userInfo.authorities === 'engineering_user') &&
this.moduleCards.length > 0
)
},
},
mounted() {
this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo)
this.info()
}, },
methods: { methods: {
info() { info() {
getModuleState({ getModuleState({
id: this.ndid, id: this.ndid,
}).then((res) => { }).then((res) => {
this.list = res.data this.list = res.data || []
}) })
}, },
}, chunkedChildren(children) {
mounted() { const result = []
this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo) for (let i = 0; i < children.length; i += 2) {
result.push(children.slice(i, i + 2))
this.info() }
return result
},
}, },
} }
</script> </script>
<style lang="scss"> <style lang="scss" scoped>
.basic { .basic {
.params-wrap {
margin-bottom: 20rpx;
background-color: #fff;
border-radius: 10rpx;
overflow: hidden;
}
.section-title-row {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 12rpx;
padding: 20rpx 20rpx 0;
}
.section-title {
display: flex;
align-items: center;
font-size: 30rpx;
font-weight: 600;
color: #333;
}
.grid-card-title-with-icon { .grid-card-title-with-icon {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
position: relative; position: relative;
padding-left: 20rpx; width: 8rpx;
height: 28rpx;
margin-right: 12rpx;
background: $uni-theme-color;
border-radius: 3rpx;
}
&::before { .params-section {
content: ''; padding: 16rpx 16rpx 20rpx;
position: absolute; }
left: 0;
top: 50%; .double-row {
transform: translateY(-50%); display: grid;
width: 8rpx; grid-template-columns: repeat(2, 1fr);
height: 28rpx; gap: 16rpx;
background: $uni-theme-color; margin-bottom: 16rpx;
border-radius: 3rpx;
&:last-child {
margin-bottom: 0;
}
}
.param-group {
min-width: 0;
background: #f3f3f3;
border-radius: 16rpx;
padding: 16rpx 8rpx 12rpx;
}
.param-title {
font-size: 26rpx;
color: #666666;
margin-bottom: 8rpx;
padding-left: 4rpx;
}
.param-value-wrap {
display: flex;
justify-content: center;
align-items: center;
padding: 4rpx;
}
.param-value {
font-size: 28rpx;
font-weight: 700;
color: #333;
&--offline {
color: #ff3b30;
} }
} }
} }

View File

@@ -1,115 +1,105 @@
<template> <template>
<view> <view>
<uni-load-more status="loading" <uni-load-more status="loading" v-if="!isDataReady"></uni-load-more>
v-if="renderData.电网电流.length == 0 || renderData.电网电压.length == 0 || renderData.负载电流.length == 0 || renderData.补偿电流.length == 0"></uni-load-more> <view class="basic mt10" v-else>
<view class="basic" v-else> <view class="params-wrap" v-for="(section, ind) in sections" :key="section.title">
<view class="grid-card"> <view class="section-title-row">
<view class="section-title">
<text> <view class="grid-card-title-with-icon"></view>
<view class="grid-card-title grid-card-title-with-icon"></view>电网电流 <text>{{ section.title }}</text>
</text> </view>
<view class="legend-row" v-if="ind == 0">
<view class="grid-card-content-3"> <view class="legend-item" v-for="phase in phaseColors" :key="phase.name">
<view class="item item-title">名称</view> <view class="legend-dot" :style="{ background: phase.color }" />
<view class="item item-title">有效值(A)</view> <text class="legend-text">{{ phase.name }}</text>
<view class="item item-title">畸变率(%)</view> </view>
<template v-for="(item, index) in renderData.电网电流"> </view>
<view class="item">{{ item.phase }}</view>
<view class="item">{{
item['Apf_RmsI_Sys(A)'] > 0 ? item['Apf_RmsI_Sys(A)'].toFixed(2) : item['Apf_RmsI_Sys(A)']
}}</view>
<view class="item">{{
item['Apf_ThdA_Sys(%)'] > 0 ? item['Apf_ThdA_Sys(%)'].toFixed(2) : item['Apf_ThdA_Sys(%)']
}}</view>
</template>
</view> </view>
</view> <view class="params-section">
<view class="grid-card"> <view v-for="(rowItems, rowIdx) in chunkedChildren(getSectionCards(section))" :key="rowIdx"
class="double-row">
<text> <view v-for="(child, childIdx) in rowItems" :key="childIdx" class="param-group">
<view class="grid-card-title grid-card-title-with-icon"></view>电网电压 <view class="param-title">
</text> <text>{{ child.name }}</text>
</view>
<view class="grid-card-content-4"> <view class="phase-vertical">
<view class="item item-title">名称</view> <view class="phase-item-vertical">
<view class="item item-title">电压(V)</view> <text class="phase-value-vertical" :style="{ color: phaseColors[0].color }">{{
<view class="item item-title">频率(Hz)</view> child.A
<view class="item item-title">畸变率(%)</view> }}</text>
<template v-for="(item, index) in renderData.电网电压"> </view>
<view class="item">{{ item.phase }}</view> <view class="phase-divider" />
<view class="item">{{ <view class="phase-item-vertical">
item['Apf_PhV_Sys(V)'] > 0 ? item['Apf_PhV_Sys(V)'].toFixed(2) : item['Apf_PhV_Sys(V)'] <text class="phase-value-vertical" :style="{ color: phaseColors[1].color }">{{
}}</view> child.B
<view class="item">{{ }}</text>
item['Apf_Freq(Hz)'] > 0 ? item['Apf_Freq(Hz)'].toFixed(2) : item['Apf_Freq(Hz)'] </view>
}}</view> <view class="phase-divider" />
<view class="item">{{ <view class="phase-item-vertical">
item['Apf_ThdU_Sys(%)'] > 0 ? item['Apf_ThdU_Sys(%)'].toFixed(2) : item['Apf_ThdU_Sys(%)'] <text class="phase-value-vertical" :style="{ color: phaseColors[2].color }">{{
}}</view> child.C
</template> }}</text>
</view> </view>
</view> </view>
<view class="grid-card"> </view>
</view>
<text>
<view class="grid-card-title grid-card-title-with-icon"></view>负载电流
</text>
<view class="grid-card-content-3">
<view class="item item-title">名称</view>
<view class="item item-title">有效值(A)</view>
<view class="item item-title">畸变率(%)</view>
<template v-for="(item, index) in renderData.负载电流">
<view class="item">{{ item.phase }}</view>
<view class="item">{{
item['Apf_RmsI_Load(A)'] > 0
? item['Apf_RmsI_Load(A)'].toFixed(2)
: item['Apf_RmsI_Load(A)']
}}</view>
<view class="item">{{
item['Apf_ThdA_Load(%)'] > 0
? item['Apf_ThdA_Load(%)'].toFixed(2)
: item['Apf_ThdA_Load(%)']
}}</view>
</template>
</view>
</view>
<view class="grid-card">
<text>
<view class="grid-card-title grid-card-title-with-icon"></view>补偿电流
</text>
<view class="grid-card-content-3">
<view class="item item-title">名称</view>
<view class="item item-title">有效值(A)</view>
<view class="item item-title">负载率(%)</view>
<template v-for="(item, index) in renderData.补偿电流">
<view class="item">{{ item.phase }}</view>
<view class="item">{{
item['Apf_RmsI_TolOut(A)'] == 3.1415926
? '-'
: item['Apf_RmsI_TolOut(A)'] > 0
? item['Apf_RmsI_TolOut(A)'].toFixed(2)
: item['Apf_RmsI_TolOut(A)']
}}</view>
<view class="item">{{
item['load_Rate'] == 3.1415926
? '-'
: item['load_Rate'] > 0
? item['load_Rate'].toFixed(2)
: item['load_Rate']
}}</view>
</template>
</view> </view>
</view> </view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
const SECTIONS = [
{
title: '电网电流',
dataKey: '电网电流',
metrics: [
{ label: '有效值(A)', field: 'Apf_RmsI_Sys(A)' },
{ label: '畸变率(%)', field: 'Apf_ThdA_Sys(%)' },
],
},
{
title: '电网电压',
dataKey: '电网电压',
metrics: [
{ label: '电压(V)', field: 'Apf_PhV_Sys(V)' },
{ label: '频率(Hz)', field: 'Apf_Freq(Hz)' },
{ label: '畸变率(%)', field: 'Apf_ThdU_Sys(%)' },
],
},
{
title: '负载电流',
dataKey: '负载电流',
metrics: [
{ label: '有效值(A)', field: 'Apf_RmsI_Load(A)' },
{ label: '畸变率(%)', field: 'Apf_ThdA_Load(%)' },
],
},
{
title: '补偿电流',
dataKey: '补偿电流',
metrics: [
{ label: '有效值(A)', field: 'Apf_RmsI_TolOut(A)' },
{ label: '负载率(%)', field: 'load_Rate' },
],
},
]
export default { export default {
props: {
basicData: {
type: Array,
default: () => [],
},
},
data() { data() {
return { return {
sections: SECTIONS,
phaseColors: [
{ name: 'A相', color: '#DAA520' },
{ name: 'B相', color: '#2E8B57' },
{ name: 'C相', color: '#D54941' },
],
renderData: { renderData: {
电网电流: [], 电网电流: [],
电网电压: [], 电网电压: [],
@@ -119,101 +109,209 @@ export default {
}, },
} }
}, },
props: { computed: {
basicData: { isDataReady() {
type: Array, return (
default: () => { this.renderData.电网电流.length > 0 &&
return [] this.renderData.电网电压.length > 0 &&
}, this.renderData.负载电流.length > 0 &&
this.renderData.补偿电流.length > 0
)
}, },
}, },
watch: { watch: {
basicData: { basicData: {
handler: function (newVal, oldVal) { handler(newVal) {
newVal.forEach((item) => { this.renderData = {
if (item.phase === 'avg') { 电网电流: [],
return 电网电压: [],
} 负载电流: [],
let key = '' 补偿电流: [],
switch (item.statisticalName) { 未知: [],
case 'Apf_RmsI_Sys(A)': }
key = '电网电流' ; (newVal || []).forEach((item) => {
break if (item.phase === 'avg') {
case 'Apf_ThdA_Sys(%)': return
key = '电网电流' }
break const key = this.getDataKey(item.statisticalName)
case 'Apf_PhV_Sys(V)': const index = this.renderData[key].findIndex((item2) => item2.phase === item.phase)
key = '电网电压' if (index > -1) {
break this.renderData[key][index][item.statisticalName] = item.statisticalData
case 'Apf_Freq(Hz)': } else {
key = '电网电压' this.renderData[key].push({
break phase: item.phase,
case 'Apf_ThdU_Sys(%)': [item.statisticalName]: item.statisticalData,
key = '电网电压' })
break }
case 'Apf_RmsI_Load(A)':
key = '负载电流'
break
case 'Apf_ThdA_Load(%)':
key = '负载电流'
break
case 'Apf_RmsI_TolOut(A)':
key = '补偿电流'
break
case 'Apf_PhV_Sys(V)':
key = '补偿电流'
break
case 'Apf_PhV_Sys(V)':
key = '补偿电流'
break
case 'load_Rate':
key = '补偿电流'
break
default:
key = '未知'
break
}
let index = this.renderData[key].findIndex((item2) => {
return item2.phase === item.phase
}) })
if (index > -1) {
this.renderData[key][index][item.statisticalName] = item.statisticalData //
} else {
this.renderData[key].push({
phase: item.phase,
[item.statisticalName]: item.statisticalData, //,
})
}
})
console.log(this.renderData)
}, },
deep: true, deep: true,
immediate: true, immediate: true,
}, },
}, },
methods: {}, methods: {
getDataKey(statisticalName) {
switch (statisticalName) {
case 'Apf_RmsI_Sys(A)':
case 'Apf_ThdA_Sys(%)':
return '电网电流'
case 'Apf_PhV_Sys(V)':
case 'Apf_Freq(Hz)':
case 'Apf_ThdU_Sys(%)':
return '电网电压'
case 'Apf_RmsI_Load(A)':
case 'Apf_ThdA_Load(%)':
return '负载电流'
case 'Apf_RmsI_TolOut(A)':
case 'load_Rate':
return '补偿电流'
default:
return '未知'
}
},
getSectionCards(section) {
const list = this.renderData[section.dataKey] || []
return section.metrics.map((metric) => ({
name: metric.label,
A: this.getPhaseValue(list, metric.field, 'A'),
B: this.getPhaseValue(list, metric.field, 'B'),
C: this.getPhaseValue(list, metric.field, 'C'),
}))
},
getPhaseValue(list, field, phase) {
const item = list.find(
(row) => String(row.phase || '').toUpperCase() === phase,
)
return this.formatValue(item[field])
},
formatValue(value) {
if (value == 3.1415926) return '-'
if (value === undefined || value === null || value === '') return '-'
const num = Number(value)
if (Number.isNaN(num)) return value
return num > 0 ? num.toFixed(2) : num
},
chunkedChildren(children) {
const result = []
for (let i = 0; i < children.length; i += 2) {
result.push(children.slice(i, i + 2))
}
return result
},
},
} }
</script> </script>
<style lang="scss"> <style lang="scss" scoped>
.basic { .basic {
.params-wrap {
margin-bottom: 20rpx;
background-color: #fff;
border-radius: 10rpx;
overflow: hidden;
}
.section-title-row {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 12rpx;
padding: 20rpx 20rpx 0;
}
.section-title {
display: flex;
align-items: center;
font-size: 30rpx;
font-weight: 600;
color: #333;
}
.grid-card-title-with-icon { .grid-card-title-with-icon {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
position: relative; position: relative;
padding-left: 20rpx; width: 8rpx;
height: 28rpx;
margin-right: 12rpx;
background: $uni-theme-color;
border-radius: 3rpx;
}
&::before { .legend-row {
content: ''; display: flex;
position: absolute; gap: 20rpx;
left: 0; align-items: center;
top: 50%; }
transform: translateY(-50%);
width: 8rpx; .legend-item {
height: 28rpx; display: flex;
background: $uni-theme-color; align-items: center;
border-radius: 3rpx; gap: 8rpx;
}
.legend-dot {
width: 16rpx;
height: 16rpx;
border-radius: 50%;
}
.legend-text {
font-size: 24rpx;
color: #666666;
}
.params-section {
padding: 16rpx 16rpx 20rpx;
}
.double-row {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16rpx;
margin-bottom: 16rpx;
&:last-child {
margin-bottom: 0;
} }
} }
.param-group {
min-width: 0;
background: #f3f3f3;
border-radius: 16rpx;
padding: 16rpx 8rpx 12rpx;
}
.param-title {
font-size: 26rpx;
color: #666666;
margin-bottom: 8rpx;
padding-left: 4rpx;
}
.phase-vertical {
display: flex;
align-items: stretch;
}
.phase-item-vertical {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
padding: 4rpx;
}
.phase-value-vertical {
font-size: 26rpx;
font-weight: 700;
}
.phase-divider {
width: 1px;
background: #d2d2d2;
margin: 8rpx 0;
}
} }
</style> </style>

View File

@@ -1,119 +1,119 @@
<template> <template>
<view> <view>
<uni-data-checkbox multiple v-model="checkbox" :localdata="hobby"></uni-data-checkbox> <uni-data-checkbox multiple v-model="checkbox" :localdata="hobby"></uni-data-checkbox>
<view class="charts-box"> <view class="charts-box">
<qiun-data-charts ontouch onzoom type="line" :opts="opts" :chartData="chartData" /> <qiun-data-charts ontouch onzoom type="line" :opts="opts" :chartData="chartData" />
</view> </view>
</view> </view>
</template> </template>
<script> <script>
export default { export default {
data () { data () {
return { return {
checkbox: [0, 1, 2], checkbox: [0, 1, 2],
hobby: [{ hobby: [{
text: '电网电压1', text: '电网电压1',
value: 0 value: 0
}, { }, {
text: '电网电压2', text: '电网电压2',
value: 1 value: 1
}, { }, {
text: '电网电压3', text: '电网电压3',
value: 2 value: 2
}, { }, {
text: '电网电压3', text: '电网电压3',
value: 4 value: 4
}], }],
chartData: {}, chartData: {},
//您可以通过修改 config-ucharts.js 文件中下标为 ['line'] 的节点来配置全局默认参数,如都是默认参数,此处可以不传 opts 。实际应用过程中 opts 只需传入与全局默认参数中不一致的【某一个属性】即可实现同类型的图表显示不同的样式,达到页面简洁的需求。 //您可以通过修改 config-ucharts.js 文件中下标为 ['line'] 的节点来配置全局默认参数,如都是默认参数,此处可以不传 opts 。实际应用过程中 opts 只需传入与全局默认参数中不一致的【某一个属性】即可实现同类型的图表显示不同的样式,达到页面简洁的需求。
opts: { opts: {
color: ["#1890FF", "#91CB74", "#FAC858", "#EE6666", "#73C0DE", "#3CA272", "#FC8452", "#9A60B4", "#ea7ccc"], color: ["#1890FF", "#91CB74", "#FAC858", "#EE6666", "#73C0DE", "#3CA272", "#FC8452", "#9A60B4", "#ea7ccc"],
padding: [15, 15, 0, 0], padding: [15, 15, 0, 0],
dataLabel: false, dataLabel: false,
dataPointShape: false, dataPointShape: false,
enableScroll: true, enableScroll: true,
legend: {}, legend: {},
xAxis: { xAxis: {
disableGrid: true, disableGrid: true,
itemCount: 10240, itemCount: 10240,
}, },
yAxis: { yAxis: {
gridType: "dash", gridType: "dash",
dashLength: 2, dashLength: 2,
data: [ data: [
{ {
min: -100, min: -100,
max: 100 max: 100
} }
] ]
}, },
// extra: { // extra: {
// line: { // line: {
// type: "curve", // type: "curve",
// width: 2, // width: 2,
// activeType: "hollow", // activeType: "hollow",
// linearType: "custom" // linearType: "custom"
// } // }
// } // }
}, },
testDataA: [], testDataA: [],
testDataB: [], testDataB: [],
testDataC: [], testDataC: [],
testCategories: [] testCategories: []
}; };
}, },
mounted () { mounted () {
this.getServerData(); this.getServerData();
}, },
methods: { methods: {
touchmove (e) { touchmove (e) {
console.log(e) console.log(e)
}, },
getServerData () { getServerData () {
//模拟从服务器获取数据时的延时 //模拟从服务器获取数据时的延时
setTimeout(() => { setTimeout(() => {
this.testDataA = [80, 60, 95, 50, 95] this.testDataA = [80, 60, 95, 50, 95]
this.testDataB = [95, 50, 50, 95, 50] this.testDataB = [95, 50, 50, 95, 50]
this.testDataC = [50, 60, 40, 50, 60] this.testDataC = [50, 60, 40, 50, 60]
this.testCategories = ["0", "90", "180", "270", "360"] this.testCategories = ["0", "90", "180", "270", "360"]
for (let index = 0; index < 9; index++) { for (let index = 0; index < 9; index++) {
this.testDataA.push(...this.testDataA) this.testDataA.push(...this.testDataA)
this.testDataB.push(...this.testDataB) this.testDataB.push(...this.testDataB)
this.testDataC.push(...this.testDataC) this.testDataC.push(...this.testDataC)
this.testCategories.push(...this.testCategories) this.testCategories.push(...this.testCategories)
} }
//模拟服务器返回数据,如果数据格式和标准格式不同,需自行按下面的格式拼接 //模拟服务器返回数据,如果数据格式和标准格式不同,需自行按下面的格式拼接
let res = { let res = {
categories: this.testCategories, categories: this.testCategories,
series: [ series: [
{ {
name: "成交量A", name: "成交量A",
data: this.testDataA data: this.testDataA
}, },
// { // {
// name: "成交量B", // name: "成交量B",
// data: this.testDataB // data: this.testDataB
// }, // },
// { // {
// name: "成交量C", // name: "成交量C",
// data: this.testDataC // data: this.testDataC
// } // }
] ]
}; };
this.chartData = JSON.parse(JSON.stringify(res)); this.chartData = JSON.parse(JSON.stringify(res));
}, 500); }, 500);
}, },
} }
}; };
</script> </script>
<style scoped> <style scoped>
/* 请根据实际需求修改父元素尺寸,组件自动识别宽高 */ /* 请根据实际需求修改父元素尺寸,组件自动识别宽高 */
.charts-box { .charts-box {
margin-top: 20rpx; margin-top: 20rpx;
width: 100%; width: 100%;
height: 300px; height: 300px;
} }
</style> </style>

View File

@@ -1,64 +1,92 @@
<template> <template>
<view> <view>
<uni-load-more status="loading" v-if="renderData.电网侧.length == 0 || renderData.负载侧.length == 0"></uni-load-more> <uni-load-more status="loading" v-if="!isDataReady"></uni-load-more>
<view class="basic" v-else> <view class="basic mt10" v-else>
<view class="grid-card"> <view class="params-wrap" v-for="(section, ind) in sections" :key="section.title">
<text> <view class="section-title-row">
<view class="grid-card-title grid-card-title-with-icon"></view>电网侧 <view class="section-title">
</text> <view class="grid-card-title-with-icon"></view>
<view class="grid-card-content-5"> <text>{{ section.title }}</text>
<view class="item item-title">名称</view> </view>
<view class="item item-title">有功功率(kW)</view> <view class="legend-row" v-if="ind == 0">
<view class="item item-title">无功功率(kVar)</view> <view class="legend-item" v-for="phase in phaseColors" :key="phase.name">
<view class="item item-title">视在功率(kVA)</view> <view class="legend-dot" :style="{ background: phase.color }" />
<view class="item item-title">功率因数</view> <text class="legend-text">{{ phase.name }}</text>
<template v-for="(item, index) in renderData.电网侧">
<view class="item">{{ item.phase }}</view>
<view class="item">{{ item['Apf_P_Sys(W)'] == '-' ? '-' : (item['Apf_P_Sys(W)'] /
1000).toFixed(2) }}
</view> </view>
<view class="item">{{ item['Apf_Q_Sys(Var)'] == '-' ? '-' : (item['Apf_Q_Sys(Var)'] / </view>
1000).toFixed(2) }}
</view>
<view class="item">{{ item['Apf_S_Sys(VA)'] == '-' ? '-' : (item['Apf_S_Sys(VA)'] /
1000).toFixed(2) }}
</view>
<view class="item">{{ item['Apf_PF_Sys(null)'] || '-' }}</view>
</template>
</view> </view>
</view> <view class="params-section">
<view class="grid-card"> <view v-for="(rowItems, rowIdx) in chunkedChildren(getSectionCards(section))" :key="rowIdx"
<text> class="double-row">
<view class="grid-card-title grid-card-title-with-icon"></view>负载侧 <view v-for="(child, childIdx) in rowItems" :key="childIdx" class="param-group">
</text> <view class="param-title">
<view class="grid-card-content-5"> <text>{{ child.name }}</text>
<view class="item item-title">名称</view> </view>
<view class="item item-title">有功功率(kW)</view> <view class="phase-vertical">
<view class="item item-title">无功功率(kVar)</view> <view class="phase-item-vertical">
<view class="item item-title">视在功率(kVA)</view> <text class="phase-value-vertical" :style="{ color: phaseColors[0].color }">{{
<view class="item item-title">功率因数</view> child.A
<template v-for="(item, index) in renderData.负载侧"> }}</text>
<view class="item">{{ item.phase }}</view> </view>
<view class="item">{{ item['Apf_P_Load(W)'] == '-' ? '-' : (item['Apf_P_Load(W)'] / <view class="phase-divider" />
1000).toFixed(2) }} <view class="phase-item-vertical">
<text class="phase-value-vertical" :style="{ color: phaseColors[1].color }">{{
child.B
}}</text>
</view>
<view class="phase-divider" />
<view class="phase-item-vertical">
<text class="phase-value-vertical" :style="{ color: phaseColors[2].color }">{{
child.C
}}</text>
</view>
</view>
</view> </view>
<view class="item">{{ </view>
item['Apf_Q_Load(Var)'] == '-' ? '-' : (item['Apf_Q_Load(Var)'] / 1000).toFixed(2)
}}</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> </view>
</view> </view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
const SECTIONS = [
{
title: '电网侧',
dataKey: '电网侧',
metrics: [
{ label: '有功功率(kW)', field: 'Apf_P_Sys(W)', divide: 1000 },
{ label: '无功功率(kVar)', field: 'Apf_Q_Sys(Var)', divide: 1000 },
{ label: '视在功率(kVA)', field: 'Apf_S_Sys(VA)', divide: 1000 },
{ label: '功率因数', field: 'Apf_PF_Sys(null)' },
],
},
{
title: '负载侧',
dataKey: '负载侧',
metrics: [
{ label: '有功功率(kW)', field: 'Apf_P_Load(W)', divide: 1000 },
{ label: '无功功率(kVar)', field: 'Apf_Q_Load(Var)', divide: 1000 },
{ label: '视在功率(kVA)', field: 'Apf_S_Load(VA)', divide: 1000 },
{ label: '功率因数', field: 'Apf_PF_Load(null)' },
],
},
]
export default { export default {
props: {
basicData: {
type: Array,
default: () => [],
},
},
data() { data() {
return { return {
sections: SECTIONS,
phaseColors: [
{ name: 'A相', color: '#DAA520' },
{ name: 'B相', color: '#2E8B57' },
{ name: 'C相', color: '#D54941' },
],
renderData: { renderData: {
电网侧: [], 电网侧: [],
负载侧: [], 负载侧: [],
@@ -66,92 +94,210 @@ export default {
}, },
} }
}, },
props: { computed: {
basicData: { isDataReady() {
type: Array, return this.renderData.电网侧.length > 0 && this.renderData.负载侧.length > 0
default: () => {
return []
},
}, },
}, },
watch: { watch: {
basicData: { basicData: {
handler: function (newVal, oldVal) { handler(newVal) {
newVal.forEach((item) => { this.renderData = {
if (item.phase === 'avg') { 电网侧: [],
return 负载侧: [],
} 未知: [],
let key = '' }
switch (item.statisticalName) { ; (newVal || []).forEach((item) => {
case 'Apf_P_Sys(W)': if (item.phase === 'avg') {
key = '电网侧' return
break }
case 'Apf_Q_Sys(Var)': const key = this.getDataKey(item.statisticalName)
key = '电网侧' const index = this.renderData[key].findIndex((item2) => item2.phase === item.phase)
break if (index > -1) {
case 'Apf_S_Sys(VA)': this.renderData[key][index][item.statisticalName] = this.normalizeStatisticalData(
key = '电网侧' item.statisticalData,
break )
case 'Apf_PF_Sys(null)': } else {
key = '电网侧' this.renderData[key].push({
break phase: item.phase,
case 'Apf_P_Load(W)': [item.statisticalName]: this.normalizeStatisticalData(item.statisticalData),
key = '负载侧' })
break }
case 'Apf_Q_Load(Var)':
key = '负载侧'
break
case 'Apf_S_Load(VA)':
key = '负载侧'
break
case 'Apf_PF_Load(null)':
key = '负载侧'
break
default:
key = '未知'
break
}
let index = this.renderData[key].findIndex((item2) => {
return item2.phase === item.phase
}) })
if (index > -1) {
this.renderData[key][index][item.statisticalName] = item.statisticalData || '-'
} else {
this.renderData[key].push({
phase: item.phase,
[item.statisticalName]: item.statisticalData || '-',
})
}
})
console.log(this.renderData)
}, },
deep: true, deep: true,
immediate: true, immediate: true,
}, },
}, },
methods: {}, methods: {
getDataKey(statisticalName) {
switch (statisticalName) {
case 'Apf_P_Sys(W)':
case 'Apf_Q_Sys(Var)':
case 'Apf_S_Sys(VA)':
case 'Apf_PF_Sys(null)':
return '电网侧'
case 'Apf_P_Load(W)':
case 'Apf_Q_Load(Var)':
case 'Apf_S_Load(VA)':
case 'Apf_PF_Load(null)':
return '负载侧'
default:
return '未知'
}
},
getSectionCards(section) {
const list = this.renderData[section.dataKey] || []
return section.metrics.map((metric) => ({
name: metric.label,
A: this.getPhaseValue(list, metric, 'A'),
B: this.getPhaseValue(list, metric, 'B'),
C: this.getPhaseValue(list, metric, 'C'),
}))
},
getPhaseValue(list, metric, phase = 'A') {
const item = list.find((row) => String(row.phase || '').toUpperCase() === phase)
return item ? this.formatValue(item[metric.field], metric.divide) : '-'
},
normalizeStatisticalData(value) {
if (value == 3.1415926 || value === null || value === '') {
return '-'
}
return value
},
formatValue(value, divide) {
if (value == 3.1415926 || value === null || value === '' || value === '-') {
return '-'
}
const num = Number(value)
if (Number.isNaN(num)) return value
if (divide) {
// return (num / divide).toFixed(2)
return num != 0 ? (num / divide).toFixed(2) : num.toFixed(2)
}
return num.toFixed(2)
},
chunkedChildren(children) {
const result = []
for (let i = 0; i < children.length; i += 2) {
result.push(children.slice(i, i + 2))
}
return result
},
},
} }
</script> </script>
<style lang="scss"> <style lang="scss" scoped>
.basic { .basic {
.params-wrap {
margin-bottom: 20rpx;
background-color: #fff;
border-radius: 10rpx;
overflow: hidden;
}
.section-title-row {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 12rpx;
padding: 20rpx 20rpx 0;
}
.section-title {
display: flex;
align-items: center;
font-size: 30rpx;
font-weight: 600;
color: #333;
}
.grid-card-title-with-icon { .grid-card-title-with-icon {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
position: relative; position: relative;
padding-left: 20rpx; width: 8rpx;
height: 28rpx;
margin-right: 12rpx;
background: $uni-theme-color;
border-radius: 3rpx;
}
&::before { .legend-row {
content: ''; display: flex;
position: absolute; gap: 20rpx;
left: 0; align-items: center;
top: 50%; }
transform: translateY(-50%);
width: 8rpx; .legend-item {
height: 28rpx; display: flex;
background: $uni-theme-color; align-items: center;
border-radius: 3rpx; gap: 8rpx;
}
.legend-dot {
width: 16rpx;
height: 16rpx;
border-radius: 50%;
}
.legend-text {
font-size: 24rpx;
color: #666666;
}
.params-section {
padding: 16rpx 16rpx 20rpx;
}
.double-row {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16rpx;
margin-bottom: 16rpx;
&:last-child {
margin-bottom: 0;
} }
} }
.param-group {
min-width: 0;
background: #f3f3f3;
border-radius: 16rpx;
padding: 16rpx 8rpx 12rpx;
}
.param-title {
font-size: 26rpx;
color: #666666;
margin-bottom: 8rpx;
padding-left: 4rpx;
}
.phase-vertical {
display: flex;
align-items: stretch;
}
.phase-item-vertical {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
padding: 4rpx;
}
.phase-value-vertical {
font-size: 26rpx;
font-weight: 700;
}
.phase-divider {
width: 1px;
background: #d2d2d2;
margin: 8rpx 0;
}
} }
</style> </style>

View File

@@ -1,24 +1,14 @@
<template> <template>
<view> <view >
<uni-load-more status="loading" v-if="basicData.length == 0"></uni-load-more> <uni-load-more status="loading" v-if="loading"></uni-load-more>
<view v-else> <view v-else class="xieBo">
<div class="header-form"> <div class="header-form">
<uni-data-select <uni-data-select v-model="parity" :localdata="parityOption" @change="initEcharts" style="flex: 1"
v-model="parity" :clear="false"></uni-data-select>
:localdata="parityOption"
@change="initEcharts"
style="flex: 1"
:clear="false"
></uni-data-select>
<!-- <uni-data-checkbox v-model="dataRadio" :localdata="dataOptions" @change="initEcharts"></uni-data-checkbox> --> <!-- <uni-data-checkbox v-model="dataRadio" :localdata="dataOptions" @change="initEcharts"></uni-data-checkbox> -->
<uni-data-select <uni-data-select v-model="dataRadio" :localdata="dataOptions" @change="initEcharts"
v-model="dataRadio" style="flex: 2; margin-left: 20rpx" :clear="false"></uni-data-select>
:localdata="dataOptions"
@change="initEcharts"
style="flex: 2; margin-left: 20rpx"
:clear="false"
></uni-data-select>
</div> </div>
<view class="charts-box"> <view class="charts-box">
<!-- <view class="data-time">{{ time }}</view> --> <!-- <view class="data-time">{{ time }}</view> -->
@@ -54,6 +44,7 @@ export default {
value: 1, value: 1,
}, },
], ],
loading: true,
parity: 2, parity: 2,
time: '', time: '',
dataOptions: [], dataOptions: [],
@@ -216,7 +207,6 @@ export default {
watch: { watch: {
basicData: { basicData: {
handler(newVal, oldVal) { handler(newVal, oldVal) {
console.log(this.basicData)
let basicData = JSON.parse(JSON.stringify(this.basicData)) let basicData = JSON.parse(JSON.stringify(this.basicData))
// this.dataRadio = 0 // this.dataRadio = 0
this.renderData = { this.renderData = {
@@ -284,9 +274,9 @@ export default {
}) })
}) })
this.dataOptions = dataOptions this.dataOptions = dataOptions
console.log(dataOptions)
this.initEcharts() this.initEcharts()
this.loading = false
this.time = this.$util.parseTime(this.dataTime - 8 * 60 * 60) this.time = this.$util.parseTime(this.dataTime - 8 * 60 * 60)
}, },
deep: true, deep: true,
@@ -365,13 +355,29 @@ export default {
}, 100) }, 100)
}, },
}, },
mounted() {
this.loading = true
setTimeout(() => {
this.loading = false
}, 5000)
},
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.xieBo {
margin-top: 10rpx;
background-color: #fff;
padding: 20rpx;
border-radius: 10rpx;
}
.charts-box { .charts-box {
margin-top: 20rpx; margin-top: 20rpx;
height: 100vh; height: 100vh;
.data-time { .data-time {
position: absolute; position: absolute;
right: 20rpx; right: 20rpx;
@@ -379,6 +385,7 @@ export default {
font-size: 24rpx; font-size: 24rpx;
} }
} }
.header-form { .header-form {
display: flex; display: flex;
} }

View File

@@ -25,8 +25,8 @@
<template v-for="(item, index) in IOData"> <template v-for="(item, index) in IOData">
<view class="item">{{ item.clDid }}</view> <view class="item">{{ item.clDid }}</view>
<view class="item" style="font-weight: 700"> <view class="item" style="font-weight: 700">
{{ Math.floor(item.value) || '-' }} {{ Math.floor(item.value) }}
<view v-if="item.value"> °C</view> <view> °C</view>
</view> </view>
</template> </template>
<template v-for="(item, index) in 3 - (IOData.length % 3)"> <template v-for="(item, index) in 3 - (IOData.length % 3)">
@@ -170,7 +170,7 @@ export default {
// }, // },
{ {
iconPath: '/static/about.png', iconPath: '/static/about.png',
text: '关于', text: '详情',
}, },
// { // {
// iconPath: '/static/access.png', // iconPath: '/static/access.png',
@@ -235,7 +235,7 @@ export default {
uni.switchTab({ uni.switchTab({
url: '/pages/index/message1', url: '/pages/index/message1',
}) })
} else if (e.text === '关于') { } else if (e.text === '详情') {
uni.navigateTo({ url: '/pages/device/APF/about?id=' + this.devId }) uni.navigateTo({ url: '/pages/device/APF/about?id=' + this.devId })
} else if (e.text === '移交') { } else if (e.text === '移交') {
uni.navigateTo({ url: '/pages/device/transfer?id=' + this.devId }) uni.navigateTo({ url: '/pages/device/transfer?id=' + this.devId })
@@ -673,8 +673,9 @@ export default {
.header { .header {
position: relative; position: relative;
width: 375px; width: 100vw;
margin: 0 auto; display: flex;
justify-content: center;
overflow: hidden; overflow: hidden;
image { image {
@@ -691,7 +692,7 @@ export default {
z-index: 2; z-index: 2;
text-align: center; text-align: center;
color: #111; color: #111;
width: 150rpx; width: 180rpx;
font-size: 16rpx; font-size: 16rpx;
opacity: 0.8; opacity: 0.8;

View File

@@ -98,7 +98,7 @@ export default {
// }, // },
{ {
iconPath: '/static/about.png', iconPath: '/static/about.png',
text: '关于', text: '详情',
}, },
// { // {
// iconPath: '/static/access.png', // iconPath: '/static/access.png',
@@ -130,7 +130,7 @@ export default {
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' })

View File

@@ -95,7 +95,7 @@
@change="positionChange" :clear="false" disabled></uni-data-select> @change="positionChange" :clear="false" disabled></uni-data-select>
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="别名"> <uni-forms-item label="别名">
<uni-easyinput :clearable="false" type="text" v-model="point.alias" <uni-easyinput :clearable="false" maxlength="24" type="text" v-model="point.alias"
@change="aliasChange" placeholder="别名(非必填)" /> @change="aliasChange" placeholder="别名(非必填)" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="绑定指标"> <uni-forms-item label="绑定指标">

View File

@@ -492,6 +492,6 @@ export default {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
box-shadow: 0 4rpx 16rpx rgba(55, 108, 243, 0.35); box-shadow: 0 4rpx 16rpx rgba(55, 108, 243, 0.35);
z-index: 99; z-index: 1;
} }
</style> </style>

View File

@@ -107,7 +107,7 @@
@change="positionChange" disabled :clear="false"></uni-data-select> @change="positionChange" disabled :clear="false"></uni-data-select>
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="别名"> <uni-forms-item label="别名">
<uni-easyinput :clearable="false" type="text" v-model="point.alias" <uni-easyinput :clearable="false" maxlength="24" type="text" v-model="point.alias"
@change="aliasChange" placeholder="别名(非必填)" /> @change="aliasChange" placeholder="别名(非必填)" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="绑定指标"> <uni-forms-item label="绑定指标">
@@ -369,7 +369,7 @@ export default {
}, },
changeAuth() { changeAuth() {
uni.scanCode({ uni.scanCode({
onlyFromCamera: true, onlyFromCamera: false,
success: (res) => { success: (res) => {
console.log('条码类型:' + res.scanType) console.log('条码类型:' + res.scanType)
console.log('条码内容:' + res.result) console.log('条码内容:' + res.result)
@@ -664,4 +664,19 @@ export default {
left: -9999px; left: -9999px;
width: 375px; width: 375px;
} }
</style>
/deep/ .uni-select__input-text {
width: 170px !important;
}
/deep/ .uni-select__selector-item {
uni-text {
white-space: nowrap !important;
/* 强制不换行 */
overflow: hidden !important;
/* 溢出内容隐藏 */
text-overflow: ellipsis !important;
/* 溢出部分显示省略号 */
}
}
</style>

View File

@@ -21,7 +21,10 @@
所属工程<view>{{ device.engineeringName }}</view> 所属工程<view>{{ device.engineeringName }}</view>
</view> </view>
<view class="info-item"> <view class="info-item">
所属项目<view>{{ device.equipmentName }}</view> 所属项目<view>{{ device.projectName }}</view>
</view>
<view class="info-item">
所属设备<view>{{ device.equipmentName }}</view>
</view> </view>
<view class="info-item status"> <view class="info-item status">
@@ -42,7 +45,7 @@
{{ disabled ? `刷新(${countdown}s)` : '刷新' }} {{ disabled ? `刷新(${countdown}s)` : '刷新' }}
</button> </button>
</view> </view>
<!-- 仪表盘 --> <!-- 仪表盘 -->
<view> <view>
<view class="chartBox"> <view class="chartBox">
@@ -87,9 +90,14 @@
</view> </view>
<!-- 底部指标数据 --> <!-- 底部指标数据 -->
<view class="params-wrap"> <view class="params-wrap ">
<view class="legend-row mt10">
<view class="params-section"> <view class="legend-item" v-for="phase in phaseColors" :key="phase.name">
<view class="legend-dot" :style="{ background: phase.color }" />
<text class="legend-text">{{ phase.name }}</text>
</view>
</view>
<view class="params-section mb40">
<view v-for="(rowItems, rowIdx) in chunkedChildren(realTimeData)" :key="rowIdx" <view v-for="(rowItems, rowIdx) in chunkedChildren(realTimeData)" :key="rowIdx"
class="double-row"> class="double-row">
<view v-for="(child, childIdx) in rowItems" :key="childIdx" class="param-group"> <view v-for="(child, childIdx) in rowItems" :key="childIdx" class="param-group">
@@ -135,7 +143,11 @@ export default {
data() { data() {
return { return {
loading: true, loading: true,
phaseColors: [
{ name: 'A相', color: '#DAA520' },
{ name: 'B相', color: '#2E8B57' },
{ name: 'C相', color: '#D54941' },
],
deviceInfo: {}, deviceInfo: {},
// 使用上面定义的图表配置项 // 使用上面定义的图表配置项
option: {}, option: {},
@@ -145,7 +157,7 @@ export default {
echartsDataV2: {}, echartsDataV2: {},
echartsDataV3: {}, echartsDataV3: {},
echartsDataA1: {}, echartsDataA1: {},
echartsDataA2: {}, echartsDataA2: {},
echartsDataA3: {}, echartsDataA3: {},
// 图表实例,用于后续操作 // 图表实例,用于后续操作
echart0: null, echart0: null,
@@ -173,8 +185,8 @@ export default {
{ name: '电压总谐波畸变率(%)', A: '-', B: '-', C: '-' }, { name: '电压总谐波畸变率(%)', A: '-', B: '-', C: '-' },
], ],
phaseColors: [ phaseColors: [
{ name: 'A相', color: '#F1B22E' }, { name: 'A相', color: '#DAA520' },
{ name: 'B相', color: '#2BA471' }, { name: 'B相', color: '#2E8B57' },
{ name: 'C相', color: '#D54941' }, { name: 'C相', color: '#D54941' },
], ],
disabled: false, disabled: false,
@@ -190,7 +202,7 @@ export default {
}, },
{ {
iconPath: '/static/about.png', iconPath: '/static/about.png',
text: '关于', text: '详情',
}, },
], ],
device: {}, device: {},
@@ -969,7 +981,7 @@ export default {
url: '/pages/index/message1', url: '/pages/index/message1',
}) })
// uni.navigateTo({ url: '/pages/device/APF/report?id=' + this.device.equipmentId }) // uni.navigateTo({ url: '/pages/device/APF/report?id=' + this.device.equipmentId })
} else if (e.text === '关于') { } else if (e.text === '详情') {
uni.navigateTo({ url: '/pages/device/APF/about?id=' + this.device.equipmentId }) uni.navigateTo({ url: '/pages/device/APF/about?id=' + this.device.equipmentId })
} else if (e.text === '移交') { } else if (e.text === '移交') {
uni.navigateTo({ url: '/pages/device/transfer?id=' + this.device.equipmentId }) uni.navigateTo({ url: '/pages/device/transfer?id=' + this.device.equipmentId })
@@ -1114,7 +1126,7 @@ export default {
} }
.phase-value-vertical { .phase-value-vertical {
font-size: 28rpx; font-size: 26rpx;
font-weight: 700; font-weight: 700;
} }
@@ -1191,4 +1203,29 @@ export default {
height: 45rpx; height: 45rpx;
line-height: 45rpx; line-height: 45rpx;
} }
.legend-row {
display: flex;
gap: 20rpx;
align-items: center;
justify-content: end;
padding: 16rpx 20rpx;
}
.legend-item {
display: flex;
align-items: center;
gap: 8rpx;
}
.legend-dot {
width: 16rpx;
height: 16rpx;
border-radius: 50%;
}
.legend-text {
font-size: 24rpx;
color: #666666;
}
</style> </style>

View File

@@ -1,157 +1,142 @@
<template> <template>
<view> <view>
<Cn-page :loading="loading" beforeRender> <Cn-page :loading="loading" beforeRender>
<view slot="body"> <view slot="body">
<view class="transfer"> <view class="transfer">
<!-- <div class="transfer-img" ref="qrCodeUrl" /> --> <!-- <div class="transfer-img" ref="qrCodeUrl" /> -->
<!-- <uqrcode ref="uqrcode" canvas-id="qrcode" :value="content" :options="{ margin: 10 }"></uqrcode> --> <!-- <uqrcode ref="uqrcode" canvas-id="qrcode" :value="content" :options="{ margin: 10 }"></uqrcode> -->
<uqrcode <uqrcode ref="uqrcode" canvas-id="qrcode" :value="content" size="200" @complete="complete"
ref="uqrcode" :loading="false"></uqrcode>
canvas-id="qrcode" <view style="height: 200rpx"></view>
:value="content" <view class="transfer-text">请让接收人员扫码接收</view>
size="200" <view class="transfer-btn">
@complete="complete" <button class="transfer-btn-item" style="background-color: #fff; color: #111" @click="back">
:loading="false" 返回
></uqrcode> </button>
<view style="height: 200rpx"></view> <button class="transfer-btn-item ml20" @click="scan">扫一扫</button>
<view class="transfer-text">请让接收人员扫码接收</view> </view>
<view class="transfer-btn"> </view>
<button class="transfer-btn-item" style="background-color: #fff; color: #111" @click="back"> </view>
返回 </Cn-page>
</button> <uni-popup ref="alertDialog" type="dialog">
<button class="transfer-btn-item ml20" @click="scan">扫一扫</button> <uni-popup-dialog style="width: 90%; margin: 5%" type="info" cancelText="禁止" confirmText="允许" title="权限说明"
</view> content='是否允许"灿能物联"使用相机?' @confirm="handleScon('camera')" @close="dialogClose"></uni-popup-dialog>
</view> </uni-popup>
</view> <uni-popup ref="message" type="message">
</Cn-page> <uni-popup-message type="info" :duration="0" style="width: 90%; margin: 5%">
<uni-popup ref="alertDialog" type="dialog"> <view style="color: #909399; font-style: 16px">相机权限使用说明:</view>
<uni-popup-dialog <view style="color: #6c6c6c; margin-top: 3rpx; "> 用于相机扫描二维码!</view>
style="width: 90%; margin: 5%" </uni-popup-message>
type="info" </uni-popup>
cancelText="禁止" </view>
confirmText="允许" </template>
title="权限说明" <script>
content='是否允许"灿能物联"使用相机?' // import QRCode from 'qrcodejs2'
@confirm="handleScon('camera')" // import UQRCode from '@/uni_modules/Sansnn-uQRCode/js_sdk/uqrcode/uqrcode.js';
@close="dialogClose"
></uni-popup-dialog> import { transferDevice } from '@/common/api/device'
</uni-popup>
<uni-popup ref="message" type="message"> export default {
<uni-popup-message type="info" :duration="0" style="width: 90%; margin: 5%"> data() {
<view style="color: #909399; font-style: 16px">相机权限使用说明:</view> return {
<view style="color: #6c6c6c; margin-top: 3rpx; "> 用于相机扫描二维码!</view> loading: true,
</uni-popup-message> content: '',
</uni-popup> options: {},
</view> }
</template> },
<script> methods: {
// import QRCode from 'qrcodejs2' complete() {
// import UQRCode from '@/uni_modules/Sansnn-uQRCode/js_sdk/uqrcode/uqrcode.js'; this.loading = false
},
import { transferDevice } from '@/common/api/device' back() {
uni.navigateBack({ delta: 1 })
export default { },
data() { home() {
return { uni.navigateBack({ delta: 1 })
loading: true, },
content: '', transferDevice(userId) {
options: {}, transferDevice(this.options.id, userId).then((res) => {
} uni.showToast({
}, title: '移交成功',
methods: { icon: 'none',
complete() { })
this.loading = false uni.navigateBack()
}, })
back() { },
uni.navigateBack({ delta: 1 }) scan() {
}, if (
home() { plus.os.name == 'Android' &&
uni.navigateBack({ delta: 1 }) plus.navigator.checkPermission('android.permission.CAMERA') === 'undetermined'
}, ) {
transferDevice(userId) { //未授权
transferDevice(this.options.id, userId).then((res) => { this.$refs.message.open()
uni.showToast({ this.$refs.alertDialog.open('bottom')
title: '移交成功', } else {
icon: 'none', this.handleScon()
}) }
uni.navigateBack() },
}) handleScon() {
}, this.$refs.message.close()
scan() { uni.scanCode({
if ( // onlyFromCamera:false,
plus.os.name == 'Android' && success: (res) => {
plus.navigator.checkPermission('android.permission.CAMERA') === 'undetermined' console.log(res)
) { let data = JSON.parse(res.result)
//未授权 if (data.type === 'userId') {
this.$refs.message.open() this.transferDevice(data.id)
this.$refs.alertDialog.open('bottom') } else {
} else { uni.showToast({
this.handleScon() title: '请扫描正确的二维码',
} icon: 'none',
}, })
handleScon() { }
this.$refs.message.close() },
uni.scanCode({ })
onlyFromCamera:true, },
success: (res) => { dialogClose() { this.$refs.message.close() },
console.log(res) },
let data = JSON.parse(res.result) onLoad(options) {
if (data.type === 'userId') { this.options = options
this.transferDevice(data.id) this.content = JSON.stringify({
} else { type: 'transferDevice',
uni.showToast({ id: options.id,
title: '请扫描正确的二维码', })
icon: 'none', },
}) }
} </script>
}, <style lang="scss">
}) .transfer {
}, padding: 200rpx 34rpx 0;
dialogClose() {this.$refs.message.close()}, display: flex;
}, flex-direction: column;
onLoad(options) { align-items: center;
this.options = options
this.content = JSON.stringify({ .transfer-img {}
type: 'transferDevice',
id: options.id, .transfer-text {
}) font-size: 28rpx;
}, color: #999999;
} margin-top: 30rpx;
</script> }
<style lang="scss">
.transfer { .transfer-btn {
padding: 200rpx 34rpx 0; display: flex;
display: flex; flex-direction: row;
flex-direction: column; justify-content: space-between;
align-items: center; margin-top: 100rpx;
width: 100%;
.transfer-img {
} .transfer-btn-item {
flex: 1;
.transfer-text { height: 80rpx;
font-size: 28rpx; border-radius: 12rpx;
color: #999999; background-color: $uni-theme-color;
margin-top: 30rpx; font-size: 28rpx;
} color: #fff;
display: flex;
.transfer-btn { justify-content: center;
display: flex; align-items: center;
flex-direction: row; }
justify-content: space-between; }
margin-top: 100rpx; }
width: 100%; </style>
.transfer-btn-item {
flex: 1;
height: 80rpx;
border-radius: 12rpx;
background-color: $uni-theme-color;
font-size: 28rpx;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
}
}
}
</style>

View File

@@ -10,35 +10,32 @@
<view class="message"> <view class="message">
<uni-swipe-action>
<uni-swipe-action-item v-for="(item, index) in store.data" <view v-for="(item, index) in store.data" :key="index" style="margin: 0px 7px 7px;">
:style="{ marginTop: index === 0 ? '0' : '' }" :key="index" :threshold="0" <!-- extra="🔍" -->
:right-options="item.isTop == 0 ? options1 : options12" @click="bindClick($event, item)"> <uni-card class="boxClick" :title="item.name" @click="jump(item)">
<!-- extra="🔍" --> <view class="term-list-bottom">
<uni-card class="boxClick" :title="item.name" @click="jump(item)"> <view class="term-list-bottom-item">
<view class="term-list-bottom"> <view>区域</view>
<view class="term-list-bottom-item"> <view>{{ item.provinceName + item.cityName }}</view>
<view>区域</view>
<view>{{ item.provinceName + item.cityName }}</view>
</view>
<view class="term-list-bottom-item">
<view>创建时间</view>
<view>{{ item.createTime }}</view>
</view>
</view> </view>
<view class="pinToTop" v-if="item.isTop == 1"> 置顶 </view> <view class="term-list-bottom-item">
</uni-card> <view>创建时间</view>
</uni-swipe-action-item> <view>{{ item.createTime }}</view>
</uni-swipe-action> </view>
</view>
</uni-card>
</view>
<Cn-empty v-if="store.empty" style="padding-top: 400rpx"></Cn-empty> <Cn-empty v-if="store.empty" style="padding-top: 400rpx"></Cn-empty>
<uni-load-more v-if="store.status == 'loading' || (store.data && store.data.length > 0)" <uni-load-more v-if="store.status == 'loading' || (store.data && store.data.length > 0)"
:status="store.status"></uni-load-more> :status="store.status"></uni-load-more>
</view>
</view> </view>
</view>
</template> </template>
<script> <script>

View File

@@ -1,182 +1,182 @@
<template> <template>
<Cn-page :loading="loading"> <Cn-page :loading="loading">
<view slot="body"> <view slot="body">
<view class="new"> <view class="new">
<view class="content"> <view class="content">
<page-meta :page-style="'overflow:'+(show?'hidden':'visible')"></page-meta> <page-meta :page-style="'overflow:'+(show?'hidden':'visible')"></page-meta>
<uni-forms :label-width="80"> <uni-forms :label-width="80">
<uni-forms-item label="工程名称"> <uni-forms-item label="工程名称">
<uni-easyinput type="text" v-model="formData.name" placeholder="请输入工程名称"/> <uni-easyinput type="text" v-model="formData.name" maxlength="50" placeholder="请输入工程名称"/>
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="位置"> <uni-forms-item label="位置">
<!-- <view style="display:flex;"> <!-- <view style="display:flex;">
<uni-easyinput :clearable="false" type="textarea" autoHeight v-model="formData.area" <uni-easyinput :clearable="false" type="textarea" autoHeight v-model="formData.area"
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-data-picker :localdata="localdata" @change="areaChange" v-model="value" <uni-data-picker :localdata="localdata" @change="areaChange" v-model="value"
@popupopened="show=true" @popupclosed="show=false"> @popupopened="show=true" @popupclosed="show=false">
</uni-data-picker> </uni-data-picker>
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="描述"> <uni-forms-item label="描述">
<uni-easyinput <uni-easyinput
type="textarea" type="textarea"
autoHeight autoHeight
maxlength="999" maxlength="999"
v-model="formData.description" v-model="formData.description"
placeholder="请输入工程描述" placeholder="请输入工程描述"
/> />
</uni-forms-item> </uni-forms-item>
</uni-forms> </uni-forms>
</view> </view>
<view class="btn-wrap"> <view class="btn-wrap">
<view class="btn-wrap-item" @click="submit"> 提交</view> <view class="btn-wrap-item" @click="submit"> 提交</view>
</view> </view>
</view> </view>
</view> </view>
</Cn-page> </Cn-page>
</template> </template>
<script> <script>
import {addEngineering, auditEngineering} from '../../common/api/engineering' import {addEngineering, auditEngineering} from '../../common/api/engineering'
import area from '../../common/js/area.json' import area from '../../common/js/area.json'
export default { export default {
data() { data() {
return { return {
localdata: area, localdata: area,
loading: false, loading: false,
value: '', value: '',
formData: { formData: {
city: '', city: '',
description: '', description: '',
name: '', name: '',
province: '', province: '',
}, },
engineering: {}, engineering: {},
show: false, show: false,
options: {} options: {}
} }
}, },
onLoad(options) { onLoad(options) {
this.options = options this.options = options
if (options.engineering) { if (options.engineering) {
this.engineering = JSON.parse(decodeURIComponent(options.engineering)) this.engineering = JSON.parse(decodeURIComponent(options.engineering))
console.log(this.engineering) console.log(this.engineering)
for (let key in this.formData) { for (let key in this.formData) {
if (this.engineering[key]) { if (this.engineering[key]) {
this.formData[key] = this.engineering[key] this.formData[key] = this.engineering[key]
} }
} }
this.value = this.engineering.city this.value = this.engineering.city
this.formData.id = this.engineering.id this.formData.id = this.engineering.id
uni.setNavigationBarTitle({title: '工程编辑'}) uni.setNavigationBarTitle({title: '工程编辑'})
} }
if (options.from === 'index') { if (options.from === 'index') {
this.$util.toast('请先创建一个工程') this.$util.toast('请先创建一个工程')
} }
// console.log(area); // console.log(area);
console.log(this.$util.prePage()) console.log(this.$util.prePage())
}, },
methods: { methods: {
toJSON() { toJSON() {
}, },
areaChange(e) { areaChange(e) {
if (e.detail.value.length) { if (e.detail.value.length) {
this.formData.province = e.detail.value[0].value this.formData.province = e.detail.value[0].value
this.formData.city = e.detail.value[1].value this.formData.city = e.detail.value[1].value
} else { } else {
this.formData.province = '' this.formData.province = ''
this.formData.city = '' this.formData.city = ''
} }
}, },
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) {
this.$util.toast('请输入工程名称') this.$util.toast('请输入工程名称')
return return
} }
if (!this.formData.province) { if (!this.formData.province) {
this.$util.toast('请选择区域信息') this.$util.toast('请选择区域信息')
return return
} }
if (!this.formData.description) { if (!this.formData.description) {
this.$util.toast('请输入工程描述') this.$util.toast('请输入工程描述')
return return
} }
if (this.formData.id) { if (this.formData.id) {
await auditEngineering(this.formData) await auditEngineering(this.formData)
this.$util.toast('工程修改成功') this.$util.toast('工程修改成功')
this.$util.refreshPrePage(2) this.$util.refreshPrePage(2)
} else { } else {
let res = await addEngineering(this.formData) let res = await addEngineering(this.formData)
this.$util.toast('工程创建成功') this.$util.toast('工程创建成功')
if (this.options.from === 'index') { if (this.options.from === 'index') {
uni.setStorageSync('engineering', res.data) uni.setStorageSync('engineering', res.data)
uni.redirectTo({ uni.redirectTo({
url: '/pages/device/new?type=' + this.options.type, url: '/pages/device/new?type=' + this.options.type,
}) })
return return
} else { } else {
this.$util.refreshPrePage() this.$util.refreshPrePage()
} }
} }
}, },
}, },
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.new { .new {
padding: 34rpx; padding: 34rpx;
.content { .content {
.content-des { .content-des {
font-size: 28rpx; font-size: 28rpx;
color: #666; color: #666;
margin-bottom: 20rpx; margin-bottom: 20rpx;
} }
margin-bottom: 20rpx; margin-bottom: 20rpx;
padding: 34rpx; padding: 34rpx;
background: $uni-theme-white; background: $uni-theme-white;
border-radius: 12rpx; border-radius: 12rpx;
} }
.btn-wrap { .btn-wrap {
margin-top: 40rpx; margin-top: 40rpx;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
.btn-wrap-item { .btn-wrap-item {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex: 1; flex: 1;
background: $uni-theme-color; background: $uni-theme-color;
color: #fff; color: #fff;
height: 80rpx; height: 80rpx;
border-radius: 12rpx; border-radius: 12rpx;
} }
} }
} }
/deep/ .uni-drawer__content { /deep/ .uni-drawer__content {
width: 100vw !important; width: 100vw !important;
} }
</style> </style>

View File

@@ -25,11 +25,8 @@
<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" style="transform: scale(0.8)"
:checked="selectList.indexOf(item.engineerId) > -1" @change="switchChange(item)" />
style="transform: scale(0.8)"
@change="switchChange(item)"
/>
</view> </view>
</template> </template>
</uni-list-item> </uni-list-item>
@@ -74,8 +71,9 @@ export default {
init() { init() {
this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo) this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo)
queryAllEnginner().then((res) => { queryAllEnginner().then((res) => {
this.list = res.data this.list = (res.data || []).slice().sort((a, b) =>
console.log(this.list) (a.engineerName || '').localeCompare(b.engineerName || '', 'zh', { sensitivity: 'accent' }),
)
this.selectList = res.data.filter((item) => item.isSelect === '1').map((item) => item.engineerId) this.selectList = res.data.filter((item) => item.isSelect === '1').map((item) => item.engineerId)
console.log(this.selectList) console.log(this.selectList)
this.loading = false this.loading = false

View File

@@ -1,219 +1,219 @@
<template> <template>
<view class='new'> <view class='new'>
<template v-if="type == 1"> <template v-if="type == 1">
<view class="content"> <view class="content">
<uni-forms> <uni-forms>
<uni-forms-item label="网关识别码"> <uni-forms-item label="网关识别码">
<view style="display:flex"> <view style="display:flex">
<uni-easyinput type="number" v-model="code" placeholder="请输入网关识别码" /> <uni-easyinput type="number" v-model="code" placeholder="请输入网关识别码" />
<!-- <uni-icons type="camera" color="#007aff" size="26" class="ml20" <!-- <uni-icons type="camera" color="#007aff" size="26" class="ml20"
@click="scanCode"></uni-icons> --> @click="scanCode"></uni-icons> -->
</view> </view>
</uni-forms-item> </uni-forms-item>
</uni-forms> </uni-forms>
</view> </view>
<view class="btn-wrap"> <view class="btn-wrap">
<view class="btn-wrap-item" @click="register"> 发起注册 </view> <view class="btn-wrap-item" @click="register"> 发起注册 </view>
</view> </view>
</template> </template>
<template v-else> <template v-else>
<view class="content"> <view class="content">
<uni-forms> <uni-forms>
<uni-forms-item label="项目"> <uni-forms-item label="项目">
<uni-data-select v-model="formData.project" :localdata="projectRange"></uni-data-select> <uni-data-select v-model="formData.project" :localdata="projectRange"></uni-data-select>
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="位置"> <uni-forms-item label="位置">
<view style="display:flex;"> <view style="display:flex;">
<uni-easyinput :clearable="false" type="textarea" autoHeight v-model="formData.address" <uni-easyinput :clearable="false" maxlength="250" 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="拓扑图">
<view style="display:flex;"> <view style="display:flex;">
<view style="flex:1"> <view style="flex:1">
<image class="gplot" src="/static/test2.pic.png" mode="aspectFill" /> <image class="gplot" src="/static/test2.pic.png" mode="aspectFill" />
</view> </view>
<uni-icons type="image" color="#007aff" size="26" class="ml20" <uni-icons type="image" color="#007aff" size="26" class="ml20"
@click="chooseGplot"></uni-icons> @click="chooseGplot"></uni-icons>
</view> </view>
</uni-forms-item> </uni-forms-item>
</uni-forms> </uni-forms>
</view> </view>
<view class="btn-wrap"> <view class="btn-wrap">
<view class="btn-wrap-item" @click="submit"> 提交 </view> <view class="btn-wrap-item" @click="submit"> 提交 </view>
</view> </view>
</template> </template>
<uni-drawer ref="gplot" mode="right" :mask-click="false"> <uni-drawer ref="gplot" mode="right" :mask-click="false">
<scroll-view style="height: 100%;" scroll-y="true"> <scroll-view style="height: 100%;" scroll-y="true">
<view class="content"> <view class="content">
<image class="gplot gplot-box" mode="aspectFill" :class="{ 'gplot-active': key == activeGplot }" <image class="gplot gplot-box" mode="aspectFill" :class="{ 'gplot-active': key == activeGplot }"
src="/static/test2.pic.png" @click="activeGplot = key" v-for="(item, key) in 3" :key="key" /> src="/static/test2.pic.png" @click="activeGplot = key" v-for="(item, key) in 3" :key="key" />
<view class="btn-wrap"> <view class="btn-wrap">
<view class="btn-wrap-item" @click="closeDrawer"> 取消 </view> <view class="btn-wrap-item" @click="closeDrawer"> 取消 </view>
<view class="btn-wrap-item ml20" @click="closeDrawer"> 确定 </view> <view class="btn-wrap-item ml20" @click="closeDrawer"> 确定 </view>
</view> </view>
</view> </view>
</scroll-view> </scroll-view>
</uni-drawer> </uni-drawer>
</view> </view>
</template> </template>
<script> <script>
export default { export default {
data () { data () {
return { return {
loading: false, loading: false,
code: '', code: '',
type: 1, type: 1,
formData: { formData: {
address: '', address: '',
project:"" project:""
}, },
projectRange: [ projectRange: [
{ value: 1, text: "监测", point: 1 }, { value: 1, text: "监测", point: 1 },
{ value: 2, text: "治理", point: 2 }, { value: 2, text: "治理", point: 2 },
{ value: 3, text: "用能", point: 1 }, { value: 3, text: "用能", point: 1 },
], ],
activeGplot: 1, activeGplot: 1,
} }
}, },
methods: { methods: {
chooseGplot () { chooseGplot () {
this.$refs.gplot.open() this.$refs.gplot.open()
}, },
closeDrawer () { closeDrawer () {
this.$refs.gplot.close() this.$refs.gplot.close()
}, },
scanCode () { scanCode () {
uni.scanCode({ uni.scanCode({
success: function (res) { success: function (res) {
console.log('条码类型:' + res.scanType); console.log('条码类型:' + res.scanType);
console.log('条码内容:' + res.result); console.log('条码内容:' + res.result);
} }
}); });
}, },
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(() => {
uni.navigateBack({ delta: 1 }) uni.navigateBack({ delta: 1 })
}, 1500); }, 1500);
}, },
} }
} }
</script> </script>
<style lang='scss'> <style lang='scss'>
.new { .new {
padding: 34rpx; padding: 34rpx;
.new-btn { .new-btn {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
margin: 80rpx auto 0; margin: 80rpx auto 0;
width: 320rpx; width: 320rpx;
background: $uni-theme-color; background: $uni-theme-color;
color: #fff; color: #fff;
height: 80rpx; height: 80rpx;
border-radius: 12rpx; border-radius: 12rpx;
} }
.content { .content {
.content-des { .content-des {
font-size: 28rpx; font-size: 28rpx;
color: #666; color: #666;
margin-bottom: 20rpx; margin-bottom: 20rpx;
} }
margin-bottom: 20rpx; margin-bottom: 20rpx;
padding: 34rpx; padding: 34rpx;
background: $uni-theme-white; background: $uni-theme-white;
border-radius: 12rpx; border-radius: 12rpx;
} }
.gplot { .gplot {
position: relative; position: relative;
width: 100%; width: 100%;
height: 188rpx; height: 188rpx;
} }
.gplot-box { .gplot-box {
height: 280rpx; height: 280rpx;
margin: 0 auto; margin: 0 auto;
} }
.gplot-active::after { .gplot-active::after {
content: ''; content: '';
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
box-sizing: border-box; box-sizing: border-box;
border: 8rpx solid $uni-theme-color; border: 8rpx solid $uni-theme-color;
// background: rgba(3, 3, 3, .5); // background: rgba(3, 3, 3, .5);
} }
.btn-wrap { .btn-wrap {
margin-top: 40rpx; margin-top: 40rpx;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
.btn-wrap-item { .btn-wrap-item {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex: 1; flex: 1;
background: $uni-theme-color; background: $uni-theme-color;
color: #fff; color: #fff;
height: 80rpx; height: 80rpx;
border-radius: 12rpx; border-radius: 12rpx;
} }
} }
} }
.map-pin-box { .map-pin-box {
position: relative; position: relative;
width: 375px; width: 375px;
margin: 0 auto; margin: 0 auto;
.map-pin-box-area { .map-pin-box-area {
position: absolute; position: absolute;
width: 100%; width: 100%;
height: 100%; height: 100%;
top: 0; top: 0;
left: 0; left: 0;
} }
.point { .point {
height: 100rpx; height: 100rpx;
width: 100rpx; width: 100rpx;
image { image {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
} }
} }
/deep/ .uni-drawer__content { /deep/ .uni-drawer__content {
width: 100vw !important; width: 100vw !important;
} }
</style> </style>

View File

@@ -1,403 +1,403 @@
<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" v-for="(item, index) in deviceList" :key="index"> <view class="content" v-for="(item, index) in deviceList" :key="index">
<uni-forms :label-width="80"> <uni-forms :label-width="80">
<uni-forms-item label="型号"> <uni-forms-item label="型号">
<uni-data-select v-model="item.type" :localdata="range" <uni-data-select v-model="item.type" :localdata="range"
@change="typeChange(item)"></uni-data-select> @change="typeChange(item)"></uni-data-select>
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="MAC地址"> <uni-forms-item label="MAC地址">
<uni-easyinput type="text" v-model="item.address" placeholder="请输入设备MAC地址" /> <uni-easyinput type="text" v-model="item.address" placeholder="请输入设备MAC地址" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="拓扑图"> <uni-forms-item label="拓扑图">
<view style="display:flex;"> <view style="display:flex;">
<view style="flex:1"> <view style="flex:1">
<image class="gplot" src="/static/test2.pic.png" mode="aspectFill" /> <image class="gplot" src="/static/test2.pic.png" mode="aspectFill" />
</view> </view>
<uni-icons type="image" color="#007aff" size="26" class="ml20" <uni-icons type="image" color="#007aff" size="26" class="ml20"
@click="chooseGplot(item)"></uni-icons> @click="chooseGplot(item)"></uni-icons>
</view> </view>
</uni-forms-item> </uni-forms-item>
<!-- <uni-forms-item label="监测点" v-if="item.pointList.length"> <!-- <uni-forms-item label="监测点" v-if="item.pointList.length">
<view class="point-item" v-for="(item2, index2) in item.pointList" :key="index2" <view class="point-item" v-for="(item2, index2) in item.pointList" :key="index2"
@click="editPoint(item, index2)"> @click="editPoint(item, index2)">
<view style="flex:1" v-if="item2.pointName">{{ item2.pointName }}</view> <view style="flex:1" v-if="item2.pointName">{{ item2.pointName }}</view>
<view style="flex:1;color:#999" v-else>请选择监测点</view> <view style="flex:1;color:#999" v-else>请选择监测点</view>
<uni-icons type="compose" color="#007aff" size="26" class="ml20"></uni-icons> <uni-icons type="compose" color="#007aff" size="26" class="ml20"></uni-icons>
</view> </view>
</uni-forms-item> --> </uni-forms-item> -->
</uni-forms> </uni-forms>
</view> </view>
<view class="btn-wrap"> <view class="btn-wrap">
<view class="btn-wrap-item" @click="addDevice"> 添加 </view> <view class="btn-wrap-item" @click="addDevice"> 添加 </view>
<view class="btn-wrap-item ml20" @click="submit"> 提交 </view> <view class="btn-wrap-item ml20" @click="submit"> 提交 </view>
</view> </view>
<uni-drawer ref="gplot" mode="right" :mask-click="false"> <uni-drawer ref="gplot" mode="right" :mask-click="false">
<scroll-view style="height: 100%;" scroll-y="true"> <scroll-view style="height: 100%;" scroll-y="true">
<view class="content"> <view class="content">
<image class="gplot gplot-box" mode="aspectFill" :class="{ 'gplot-active': key == activeGplot }" <image class="gplot gplot-box" mode="aspectFill" :class="{ 'gplot-active': key == activeGplot }"
src="/static/test2.pic.png" @click="activeGplot = key" v-for="(item, key) in 3" src="/static/test2.pic.png" @click="activeGplot = key" v-for="(item, key) in 3"
:key="key" /> :key="key" />
<view class="btn-wrap"> <view class="btn-wrap">
<view class="btn-wrap-item" @click="closeDrawer"> 取消 </view> <view class="btn-wrap-item" @click="closeDrawer"> 取消 </view>
<view class="btn-wrap-item ml20" @click="confirmGplot"> 确定 </view> <view class="btn-wrap-item ml20" @click="confirmGplot"> 确定 </view>
</view> </view>
</view> </view>
</scroll-view> </scroll-view>
</uni-drawer> </uni-drawer>
<uni-drawer ref="point" mode="right" :mask-click="false"> <uni-drawer ref="point" mode="right" :mask-click="false">
<scroll-view style="height: 100%;" scroll-y="true"> <scroll-view style="height: 100%;" scroll-y="true">
<view style="background:#fff"> <view style="background:#fff">
<view class="map-pin-box"> <view class="map-pin-box">
<image class="gplot" mode="widthFix" src="/static/test2.pic.png" /> <image class="gplot" mode="widthFix" src="/static/test2.pic.png" />
<movable-area class="map-pin-box-area"> <movable-area class="map-pin-box-area">
<movable-view :x="point.x" :y="point.y" direction="all" @change="dragPoint"> <movable-view :x="point.x" :y="point.y" direction="all" @change="dragPoint">
<view class="point center"> <view class="point center">
<image src="/static/point.png" mode="scaleToFill" /> <image src="/static/point.png" mode="scaleToFill" />
<!-- <uni-icons type="map-pin" color="#007aff" size="26" class="ml20"></uni-icons> --> <!-- <uni-icons type="map-pin" color="#007aff" size="26" class="ml20"></uni-icons> -->
</view> </view>
</movable-view> </movable-view>
</movable-area> </movable-area>
</view> </view>
</view> </view>
<view class="content"> <view class="content">
<view class="content-des">请拖动图中的蓝色定位图标选择监测点位置(左上角)</view> <view class="content-des">请拖动图中的蓝色定位图标选择监测点位置(左上角)</view>
<uni-forms> <uni-forms>
<uni-easyinput type="text" v-model="pointName" placeholder="请输入设监测点名称" /> <uni-easyinput type="text" v-model="pointName" maxlength="24" placeholder="请输入设监测点名称" />
</uni-forms> </uni-forms>
<view class="btn-wrap"> <view class="btn-wrap">
<view class="btn-wrap-item" @click="closeDrawer"> 取消 </view> <view class="btn-wrap-item" @click="closeDrawer"> 取消 </view>
<view class="btn-wrap-item ml20" @click="savePoint"> 确定 </view> <view class="btn-wrap-item ml20" @click="savePoint"> 确定 </view>
</view> </view>
</view> </view>
</scroll-view> </scroll-view>
</uni-drawer> </uni-drawer>
</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: [
{ {
type: '', type: '',
address: '', address: '',
pointList: [], pointList: [],
gplot: 1, gplot: 1,
} }
], ],
range: [ range: [
{ value: 1, text: "POS-882AX", point: 1 }, { value: 1, text: "POS-882AX", point: 1 },
{ value: 2, text: "NPOS-681", point: 2 }, { value: 2, text: "NPOS-681", point: 2 },
{ value: 3, text: "NPOS-681", point: 1 }, { value: 3, text: "NPOS-681", point: 1 },
{ value: 4, text: "POV-500", point: 2 }, { value: 4, text: "POV-500", point: 2 },
{ value: 5, text: "PQV-300", point: 1 }, { value: 5, text: "PQV-300", point: 1 },
{ value: 6, text: "NPOS-571W", point: 3 }, { value: 6, text: "NPOS-571W", point: 3 },
{ value: 7, text: "NPQS-572W", point: 3 }, { value: 7, text: "NPQS-572W", point: 3 },
{ value: 8, text: "POS-882B6", point: 2 }, { value: 8, text: "POS-882B6", point: 2 },
{ value: 9, text: "PQS-882B5", point: 1 }, { value: 9, text: "PQS-882B5", point: 1 },
{ value: 10, text: "POS-882B4", point: 2 }, { value: 10, text: "POS-882B4", point: 2 },
{ value: 11, text: "PQS-882B2", point: 1 }, { value: 11, text: "PQS-882B2", point: 1 },
{ value: 12, text: "POS-882A", point: 2 }, { value: 12, text: "POS-882A", point: 2 },
{ value: 13, text: "POS-883A", point: 1 }, { value: 13, text: "POS-883A", point: 1 },
{ value: 14, text: "NPOS-581", point: 2 }, { value: 14, text: "NPOS-581", point: 2 },
{ value: 15, text: "PQS-681", point: 1 }, { value: 15, text: "PQS-681", point: 1 },
{ value: 16, text: "POS-8825", point: 3 }, { value: 16, text: "POS-8825", point: 3 },
{ value: 17, text: "PQS-782", point: 1 }, { value: 17, text: "PQS-782", point: 1 },
{ value: 18, text: "POS-880X", point: 3 }, { value: 18, text: "POS-880X", point: 3 },
{ value: 19, text: "NPQS-580", point: 1 }, { value: 19, text: "NPQS-580", point: 1 },
{ value: 20, text: "NPOS-572", point: 2 }, { value: 20, text: "NPOS-572", point: 2 },
], ],
point: { point: {
x: 170, x: 170,
y: 100, y: 100,
}, },
pointName: '', pointName: '',
activeGplot: 1, activeGplot: 1,
nowDevice: {}, nowDevice: {},
nowDeviceEditIndex: -1, nowDeviceEditIndex: -1,
} }
}, },
methods: { methods: {
typeChange (item) { typeChange (item) {
console.log(item.type); console.log(item.type);
setTimeout(() => { setTimeout(() => {
if (!item.type) return if (!item.type) return
let rangeIndex = this.range.findIndex((v) => v.value == item.type) let rangeIndex = this.range.findIndex((v) => v.value == item.type)
item.pointList = [] item.pointList = []
for (let index = 0; index < this.range[rangeIndex].point; index++) { for (let index = 0; index < this.range[rangeIndex].point; index++) {
item.pointList.push({ item.pointList.push({
name: '', name: '',
x: 170, x: 170,
y: 100, y: 100,
}) })
} }
}, 100); }, 100);
}, },
addDevice () { addDevice () {
console.log(this.formData); console.log(this.formData);
this.deviceList.push({ this.deviceList.push({
type: '', type: '',
address: '', address: '',
pointList: [], pointList: [],
gplot: 1, gplot: 1,
}) })
}, },
chooseGplot (item) { chooseGplot (item) {
this.activeGplot = item.gplot this.activeGplot = item.gplot
this.nowDevice = item this.nowDevice = item
this.$refs.gplot.open() this.$refs.gplot.open()
}, },
confirmGplot () { confirmGplot () {
this.nowDevice.gplot = this.activeGplot this.nowDevice.gplot = this.activeGplot
this.$refs.gplot.close() this.$refs.gplot.close()
}, },
closeDrawer () { closeDrawer () {
this.pointName = '' this.pointName = ''
this.point = { this.point = {
x: 170, x: 170,
y: 100, y: 100,
} }
this.$refs.gplot.close() this.$refs.gplot.close()
this.$refs.point.close() this.$refs.point.close()
}, },
// 添加新的监测点 // 添加新的监测点
addNewPoint (item) { addNewPoint (item) {
this.nowDevice = item this.nowDevice = item
this.$refs.point.open() this.$refs.point.open()
}, },
// 保存监测点 // 保存监测点
savePoint () { savePoint () {
if (!this.pointName) { if (!this.pointName) {
this.$util.toast('请输入监测点名称') this.$util.toast('请输入监测点名称')
return return
} }
if (this.nowDeviceEditIndex > -1) { if (this.nowDeviceEditIndex > -1) {
let arr = this.nowDevice.pointList.filter((item, index) => { let arr = this.nowDevice.pointList.filter((item, index) => {
if (index == this.nowDeviceEditIndex) { if (index == this.nowDeviceEditIndex) {
return false return false
} }
return item.pointName == this.pointName return item.pointName == this.pointName
}) })
if (arr.length > 0) { if (arr.length > 0) {
this.$util.toast('监测点名称已存在') this.$util.toast('监测点名称已存在')
return return
} }
this.nowDevice.pointList[this.nowDeviceEditIndex] = { this.nowDevice.pointList[this.nowDeviceEditIndex] = {
x: this.point.x, x: this.point.x,
y: this.point.y, y: this.point.y,
pointName: this.pointName, pointName: this.pointName,
} }
this.nowDeviceEditIndex = -1 this.nowDeviceEditIndex = -1
} else { } else {
let arr = this.nowDevice.pointList.filter((item, index) => { let arr = this.nowDevice.pointList.filter((item, index) => {
if (index == this.nowDeviceEditIndex) { if (index == this.nowDeviceEditIndex) {
return false return false
} }
return item.pointName == this.pointName return item.pointName == this.pointName
}) })
if (arr.length > 0) { if (arr.length > 0) {
this.$util.toast('监测点名称已存在') this.$util.toast('监测点名称已存在')
return return
} }
this.nowDevice.pointList.push({ this.nowDevice.pointList.push({
x: this.point.x, x: this.point.x,
y: this.point.y, y: this.point.y,
pointName: this.pointName, pointName: this.pointName,
}) })
} }
console.log(this.pointList); console.log(this.pointList);
this.closeDrawer() this.closeDrawer()
}, },
// 删除一个监测点 // 删除一个监测点
deletePoint (item, index) { deletePoint (item, index) {
console.log(item, index); console.log(item, index);
item.pointList.splice(index, 1) item.pointList.splice(index, 1)
}, },
// 编辑监测点 // 编辑监测点
editPoint (item, index) { editPoint (item, index) {
this.nowDeviceEditIndex = index this.nowDeviceEditIndex = index
this.nowDevice = item this.nowDevice = item
this.point.x = item.pointList[index].x this.point.x = item.pointList[index].x
this.point.y = item.pointList[index].y this.point.y = item.pointList[index].y
this.pointName = item.pointList[index].pointName this.pointName = item.pointList[index].pointName
this.$refs.point.open() this.$refs.point.open()
}, },
dragPoint (e) { dragPoint (e) {
console.log(e) console.log(e)
this.point.x = e.detail.x this.point.x = e.detail.x
this.point.y = e.detail.y this.point.y = e.detail.y
}, },
submit () { submit () {
this.$util.toast('提交成功') this.$util.toast('提交成功')
setTimeout(() => { setTimeout(() => {
uni.navigateBack({ delta: 1 }) uni.navigateBack({ delta: 1 })
}, 1500); }, 1500);
}, },
} }
} }
</script> </script>
<style lang='scss'> <style lang='scss'>
.index { .index {
padding: 20rpx; padding: 20rpx;
.content { .content {
margin-bottom: 20rpx; margin-bottom: 20rpx;
padding: 34rpx; padding: 34rpx;
background: $uni-theme-white; background: $uni-theme-white;
border-radius: 12rpx; border-radius: 12rpx;
} }
.btn-wrap { .btn-wrap {
margin-top: 40rpx; margin-top: 40rpx;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
.btn-wrap-item { .btn-wrap-item {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex: 1; flex: 1;
background: $uni-theme-color; background: $uni-theme-color;
color: #fff; color: #fff;
height: 80rpx; height: 80rpx;
border-radius: 12rpx; border-radius: 12rpx;
} }
} }
} }
.index { .index {
padding: 20rpx; padding: 20rpx;
.new-btn { .new-btn {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
margin: 80rpx auto 0; margin: 80rpx auto 0;
width: 320rpx; width: 320rpx;
background: $uni-theme-color; background: $uni-theme-color;
color: #fff; color: #fff;
height: 80rpx; height: 80rpx;
border-radius: 12rpx; border-radius: 12rpx;
} }
.content { .content {
.content-des { .content-des {
font-size: 28rpx; font-size: 28rpx;
color: #666; color: #666;
margin-bottom: 20rpx; margin-bottom: 20rpx;
} }
margin-bottom: 20rpx; margin-bottom: 20rpx;
padding: 34rpx; padding: 34rpx;
background: $uni-theme-white; background: $uni-theme-white;
border-radius: 12rpx; border-radius: 12rpx;
} }
.gplot { .gplot {
position: relative; position: relative;
width: 100%; width: 100%;
height: 188rpx; height: 188rpx;
} }
.gplot-box { .gplot-box {
height: 280rpx; height: 280rpx;
margin: 0 auto; margin: 0 auto;
} }
.gplot-active::after { .gplot-active::after {
content: ''; content: '';
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
box-sizing: border-box; box-sizing: border-box;
border: 8rpx solid $uni-theme-color; border: 8rpx solid $uni-theme-color;
// background: rgba(3, 3, 3, .5); // background: rgba(3, 3, 3, .5);
} }
.btn-wrap { .btn-wrap {
margin-top: 40rpx; margin-top: 40rpx;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
.btn-wrap-item { .btn-wrap-item {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex: 1; flex: 1;
background: $uni-theme-color; background: $uni-theme-color;
color: #fff; color: #fff;
height: 80rpx; height: 80rpx;
border-radius: 12rpx; border-radius: 12rpx;
} }
} }
} }
.map-pin-box { .map-pin-box {
position: relative; position: relative;
width: 375px; width: 375px;
margin: 0 auto; margin: 0 auto;
.map-pin-box-area { .map-pin-box-area {
position: absolute; position: absolute;
width: 100%; width: 100%;
height: 100%; height: 100%;
top: 0; top: 0;
left: 0; left: 0;
} }
.point { .point {
height: 100rpx; height: 100rpx;
width: 100rpx; width: 100rpx;
image { image {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
} }
} }
/deep/ .uni-drawer__content { /deep/ .uni-drawer__content {
width: 100vw !important; width: 100vw !important;
} }
.add-point { .add-point {
height: 72rpx; height: 72rpx;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
border: 2rpx solid #ccc; border: 2rpx solid #ccc;
border-radius: 12rpx; border-radius: 12rpx;
font-size: 28rpx; font-size: 28rpx;
border-color: rgb(229, 229, 229); border-color: rgb(229, 229, 229);
background-color: rgb(255, 255, 255); background-color: rgb(255, 255, 255);
color: #999; color: #999;
} }
.point-item { .point-item {
height: 72rpx; height: 72rpx;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
border-top: 2rpx solid #e5e5e5; border-top: 2rpx solid #e5e5e5;
border-color: rgb(229, 229, 229); border-color: rgb(229, 229, 229);
} }
.point-item:first-of-type { .point-item:first-of-type {
border-top: none; border-top: none;
} }
</style> </style>

View File

@@ -8,10 +8,10 @@
<uni-data-select v-model="item.type" :localdata="range"></uni-data-select> <uni-data-select v-model="item.type" :localdata="range"></uni-data-select>
</uni-forms-item> --> </uni-forms-item> -->
<uni-forms-item label="标题"> <uni-forms-item label="标题">
<uni-easyinput type="text" v-model="formData.title" placeholder="请输入问题简要"/> <uni-easyinput type="text" v-model="formData.title" maxlength="32" placeholder="请输入问题简要"/>
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="描述"> <uni-forms-item label="描述">
<uni-easyinput type="textarea" v-model="formData.description" placeholder="请输入详细描述"/> <uni-easyinput type="textarea" v-model="formData.description" maxlength="999" placeholder="请输入详细描述"/>
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="图片"> <uni-forms-item label="图片">
<uni-file-picker :auto-upload="false" @select="fileChange" @delete="delImg"> <uni-file-picker :auto-upload="false" @select="fileChange" @delete="delImg">
@@ -23,9 +23,9 @@
<view class="btn-wrap"> <view class="btn-wrap">
<view class="btn-wrap-item " @click="submit"> 提交</view> <view class="btn-wrap-item " @click="submit"> 提交</view>
</view> </view>
<navigator url="/pages/home/service" hover-class="none" class="fixed-btn"> <!-- <navigator url="/pages/home/service" hover-class="none" class="fixed-btn">
<image src="/static/service.png" style="height:66rpx;width:66rpx"/> <image src="/static/service.png" style="height:66rpx;width:66rpx"/>
</navigator> </navigator> -->
</view> </view>
</view> </view>
</Cn-page> </Cn-page>
@@ -83,6 +83,7 @@ export default {
}) })
return return
} }
console.log("🚀 ~ this.formData:", this.formData)
addFeedBack(this.formData).then(res => { addFeedBack(this.formData).then(res => {
console.log(res) console.log(res)
console.log(this.formData.files.length) console.log(this.formData.files.length)

View File

@@ -9,11 +9,11 @@
</view> </view>
<view class="smallLabel mt20"> <view class="smallLabel mt20">
<view class="boxCenter"> <view class="boxCenter">
<view> <!-- <view>
<checkbox-group @change="changeBox" class="boxCenter" <checkbox-group @change="changeBox" class="boxCenter"
><checkbox value="true" :checked="checkedAll" />全选  ><checkbox value="true" :checked="checkedAll" />全选 
</checkbox-group></view </checkbox-group></view
> > -->
已选择 {{ checkedTotal }} 条事件 已选择 {{ checkedTotal }} 条事件
</view> </view>
<view class="nav-menu nav-menu-btn" @click="selectDevice">申请报告 </view> <view class="nav-menu nav-menu-btn" @click="selectDevice">申请报告 </view>
@@ -127,7 +127,7 @@ export default {
checkedAll: false, checkedAll: false,
checkedTotal: 0, checkedTotal: 0,
sort: 0, sort: 0,
array: ['发生时间', '暂降深度', '持续时间'], array: ['发生时间', '暂降幅值', '持续时间'],
} }
}, },
mounted() {}, mounted() {},
@@ -222,21 +222,21 @@ export default {
}, },
judgment(val, key) { judgment(val, key) {
switch (val) { switch (val) {
case '电压暂降': case '暂降':
return { return {
type: 'sag', type: 'sag',
icon: 'icon-a-svg4', icon: 'icon-a-svg4',
color: '#2563eb', color: '#2563eb',
size: '25', size: '25',
} }
case '电压暂升': case '暂升':
return { return {
type: 'swell', type: 'swell',
icon: 'icon-a-svg5', icon: 'icon-a-svg5',
color: '#e6a23c', color: '#e6a23c',
size: '25', size: '25',
} }
case '电压中断': case '中断':
return { return {
type: 'interrupt', type: 'interrupt',
icon: 'icon-zhongduan2', icon: 'icon-zhongduan2',

View File

@@ -39,7 +39,7 @@
</view> </view>
</picker> --> </picker> -->
</view> </view>
<view class="content device" > <view class="content device">
<uni-swipe-action> <uni-swipe-action>
<uni-swipe-action-item v-for="(item, index) in deviceListFilter" :threshold="0" <uni-swipe-action-item v-for="(item, index) in deviceListFilter" :threshold="0"
:right-options="item.isTop == 0 ? options1 : options12" @click="bindClick($event, item)"> :right-options="item.isTop == 0 ? options1 : options12" @click="bindClick($event, item)">
@@ -245,6 +245,8 @@ export default {
engineeringId: this.store.params.engineerId, engineeringId: this.store.params.engineerId,
}).then((res) => { }).then((res) => {
console.log(res) console.log(res)
this.select.projectName = ''
this.select.projectNameIndex = 0
let arr = [ let arr = [
{ {
text: '全部项目', text: '全部项目',
@@ -259,6 +261,7 @@ export default {
}), }),
] ]
this.projectList = arr this.projectList = arr
uni.setStorageSync('projectList', arr) uni.setStorageSync('projectList', arr)
}) })
}, },

View File

@@ -1,7 +1,7 @@
<template> <template>
<view class="index-zhuyonghu"> <view class="index-zhuyonghu">
<template v-if="devCount.engineeringListLength > 0"> <template v-if="devCount.engineeringListLength > 0">
<view class="canneng-index-title mb20 canneng-index-title-with-icon"> <view class="canneng-index-title mb20 ml20 canneng-index-title-with-icon">
<uni-icons custom-prefix="iconfont" type="icon-gongcheng" size="18" color="#376cf3" /> <uni-icons custom-prefix="iconfont" type="icon-gongcheng" size="18" color="#376cf3" />
<text>所有工程设备统计</text> <text>所有工程设备统计</text>
</view> </view>
@@ -33,7 +33,7 @@
</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 ml20">当前工程设备统计</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"
@@ -50,7 +50,7 @@
<view class="header-item-label">离线设备</view> <view class="header-item-label">离线设备</view>
</view> </view>
</view> --> </view> -->
<view class="canneng-index-title mt20 canneng-index-title-with-icon"> <view class="canneng-index-title mt20 ml20 canneng-index-title-with-icon">
<uni-icons type="settings" size="18" color="#376cf3" /> <uni-icons type="settings" size="18" color="#376cf3" />
<text>常用功能</text> <text>常用功能</text>
</view> </view>

View File

@@ -1,7 +1,7 @@
<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 canneng-index-title-with-icon"> <view class="canneng-index-title mb20 ml20 canneng-index-title-with-icon">
<uni-icons custom-prefix="iconfont" type="icon-gongcheng" size="18" color="#376cf3" /> <uni-icons custom-prefix="iconfont" type="icon-gongcheng" size="18" color="#376cf3" />
<text>所有工程设备统计</text> <text>所有工程设备统计</text>
</view> </view>
@@ -21,7 +21,7 @@
</view> </view>
<view class="mt20"></view> <view class="mt20"></view>
</template> </template>
<view class="canneng-index-title mb20 canneng-index-title-with-icon"> <view class="canneng-index-title mb20 ml20 canneng-index-title-with-icon">
<uni-icons custom-prefix="iconfont" type="icon-zaixianjianceshebei" size="18" color="#376cf3" /> <uni-icons custom-prefix="iconfont" type="icon-zaixianjianceshebei" size="18" color="#376cf3" />
<text>当前工程设备统计</text> <text>当前工程设备统计</text>
</view> </view>

View File

@@ -1,7 +1,7 @@
<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 canneng-index-title-with-icon"> <view class="canneng-index-title mb20 ml20 canneng-index-title-with-icon">
<uni-icons custom-prefix="iconfont" type="icon-gongcheng" size="18" color="#376cf3" /> <uni-icons custom-prefix="iconfont" type="icon-gongcheng" size="18" color="#376cf3" />
<text>所有工程设备统计</text> <text>所有工程设备统计</text>
</view> </view>
@@ -35,7 +35,7 @@
</view> </view>
<view class="mt20"></view> <view class="mt20"></view>
</template> </template>
<view class="canneng-index-title mb20 canneng-index-title-with-icon"> <view class="canneng-index-title mb20 ml20 canneng-index-title-with-icon">
<uni-icons custom-prefix="iconfont" type="icon-zaixianjianceshebei" size="18" color="#376cf3" /> <uni-icons custom-prefix="iconfont" type="icon-zaixianjianceshebei" size="18" color="#376cf3" />
<text>当前工程设备统计</text> <text>当前工程设备统计</text>
</view> </view>

View File

@@ -1,7 +1,7 @@
<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 canneng-index-title-with-icon"> <view class="canneng-index-title mb20 ml20 canneng-index-title-with-icon">
<uni-icons custom-prefix="iconfont" type="icon-gongcheng" size="18" color="#376cf3" /> <uni-icons custom-prefix="iconfont" type="icon-gongcheng" size="18" color="#376cf3" />
<text>所有工程设备统计</text> <text>所有工程设备统计</text>
</view> </view>
@@ -21,7 +21,7 @@
</view> </view>
<view class="mt20"></view> <view class="mt20"></view>
</template> </template>
<view class="canneng-index-title mb20 canneng-index-title-with-icon"> <view class="canneng-index-title mb20 ml20 canneng-index-title-with-icon">
<uni-icons custom-prefix="iconfont" type="icon-zaixianjianceshebei" size="18" color="#376cf3" /> <uni-icons custom-prefix="iconfont" type="icon-zaixianjianceshebei" size="18" color="#376cf3" />
<text>当前工程设备统计</text> <text>当前工程设备统计</text>
</view> </view>
@@ -49,7 +49,7 @@
<view class="header-item-label">稳态事件数</view> <view class="header-item-label">稳态事件数</view>
</view> </view>
</view> </view>
<view class="canneng-index-title mt20 canneng-index-title-with-icon"> <view class="canneng-index-title mt20 ml20 canneng-index-title-with-icon">
<uni-icons type="settings" size="18" color="#376cf3" /> <uni-icons type="settings" size="18" color="#376cf3" />
<text>常用功能</text> <text>常用功能</text>
</view> </view>

View File

@@ -1,7 +1,7 @@
<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 canneng-index-title-with-icon"> <view class="canneng-index-title mb20 ml20 canneng-index-title-with-icon">
<uni-icons custom-prefix="iconfont" type="icon-gongcheng" size="18" color="#376cf3" /> <uni-icons custom-prefix="iconfont" type="icon-gongcheng" size="18" color="#376cf3" />
<text>所有工程设备统计</text> <text>所有工程设备统计</text>
</view> </view>
@@ -33,7 +33,7 @@
</view> </view>
<view class="mt20"></view> <view class="mt20"></view>
</template> </template>
<view class="canneng-index-title mb20 canneng-index-title-with-icon"> <view class="canneng-index-title mb20 ml20 canneng-index-title-with-icon">
<uni-icons custom-prefix="iconfont" type="icon-zaixianjianceshebei" size="18" color="#376cf3" /> <uni-icons custom-prefix="iconfont" type="icon-zaixianjianceshebei" size="18" color="#376cf3" />
<text>当前工程设备统计</text> <text>当前工程设备统计</text>
</view> </view>

File diff suppressed because it is too large Load Diff

View File

@@ -41,7 +41,7 @@
<view class="event-desc"> <view class="event-desc">
<text>统计时间{{ <text>统计时间{{
curSub == 0 ? item.startTime : item.startTime + ' 至 ' + item.endTime curSub == 0 ? item.startTime : item.startTime + ' 至 ' + item.endTime
}}</text> }}</text>
</view> </view>
</view> </view>
<view class="event-action" v-if="!showNotGenerated(item)"> <view class="event-action" v-if="!showNotGenerated(item)">
@@ -54,7 +54,7 @@
<view class="event-detail textBox" @touchmove.stop> <view class="event-detail textBox" @touchmove.stop>
<text v-if="!showNotGenerated(item)">{{ <text v-if="!showNotGenerated(item)">{{
item.overLimitDesc == '' ? '该监测点暂无指标越限' : item.overLimitDesc item.overLimitDesc == '' ? '该监测点暂无指标越限' : item.overLimitDesc
}}</text> }}</text>
<text v-else>数据未生成暂不支持下载</text> <text v-else>数据未生成暂不支持下载</text>
</view> </view>
<!-- <view class="downloadReport" @click="download"> <!-- <view class="downloadReport" @click="download">
@@ -180,46 +180,14 @@ export default {
timeType: this.selectValue.report, timeType: this.selectValue.report,
}) })
.then((res) => { .then((res) => {
// 下载文件资源到本地 const match = this.$config.static + res.data.match(/excelreport([^?]*)/)[1]
uni.downloadFile({ uni.downloadFile({
url: res.data, // 后端返回的线上文件路径 url: match,
success: function (res) { success: (downloadRes) => {
if (res.statusCode === 200) { if (downloadRes.statusCode === 200) {
// 文件到本地 this.openReportFile(downloadRes.tempFilePath)
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 { } else {
uni.hideLoading()
uni.showToast({ uni.showToast({
icon: 'none', icon: 'none',
mask: true, mask: true,
@@ -228,10 +196,19 @@ export default {
}) })
} }
}, },
fail: function (res) { }, fail: () => {
uni.hideLoading()
uni.showToast({
icon: 'none',
mask: true,
title: '下载失败!',
duration: 1000,
})
},
}) })
}) })
.catch((err) => { .catch((err) => {
uni.hideLoading()
uni.showToast({ uni.showToast({
icon: 'none', icon: 'none',
mask: true, mask: true,
@@ -240,6 +217,72 @@ export default {
}) })
}) })
}, },
openReportFile(tempFilePath) {
const previewFile = (filePath) => {
uni.hideLoading()
uni.openDocument({
filePath,
fileType: 'xlsx',
showMenu: true,
success: () => {
console.log('成功打开文件')
},
fail: (err) => {
console.log('打开文件失败', err)
uni.showToast({
icon: 'none',
title: '预览失败',
})
},
})
}
// #ifdef APP-PLUS
// iOS 需保留 xlsx 后缀saveFile 随机路径会导致 openDocument 失败
if (plus.os.name === 'iOS') {
const fileName = `harmonic_report_${Date.now()}.xlsx`
plus.io.resolveLocalFileSystemURL(
tempFilePath,
(entry) => {
plus.io.resolveLocalFileSystemURL(
'_doc/',
(docEntry) => {
entry.copyTo(
docEntry,
fileName,
(newEntry) => previewFile(newEntry.fullPath),
() => previewFile(tempFilePath)
)
},
() => previewFile(tempFilePath)
)
},
() => previewFile(tempFilePath)
)
return
}
// #endif
uni.saveFile({
tempFilePath,
success: (data) => {
uni.showToast({
icon: 'success',
mask: true,
title: '下载成功!',
duration: 1000,
})
setTimeout(() => previewFile(data.savedFilePath), 500)
},
fail: () => {
uni.hideLoading()
uni.showToast({
icon: 'none',
title: '保存失败!',
})
},
})
},
// 下拉 // 下拉
refresherrefresh() { refresherrefresh() {
this.triggered = true this.triggered = true
@@ -384,6 +427,10 @@ export default {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
box-shadow: 0 4rpx 16rpx rgba(55, 108, 243, 0.35); box-shadow: 0 4rpx 16rpx rgba(55, 108, 243, 0.35);
z-index: 99; z-index: 1;
}
/deep/ .segmented-control__text {
line-height: 60rpx !important;
} }
</style> </style>

View File

@@ -1,307 +1,315 @@
<template> <template>
<view class="target-info-page"> <view class="target-info-page">
<scroll-view class="target-info-scroll" scroll-y :show-scrollbar="false"> <scroll-view class="target-info-scroll" scroll-y :show-scrollbar="false">
<view class="monitor-card card"> <view class="monitor-card card">
<view class="card-header"> <view class="card-header">
<view class="event-icon"> <view class="event-icon">
<Cn-icon-transient name="监测点" /> <Cn-icon-transient name="监测点" />
</view> </view>
<view class="card-header-info"> <view class="card-header-info">
<text class="point-name ellipsis">{{ pointInfo.pointName || '-' }}</text> <view class="point-name-row">
<view class="meta-row"> <text class="point-name ellipsis">{{ pointInfo.pointName || '-' }}</text>
<text v-if="pointInfo.engineeringName" class="meta-item ellipsis"> <text class="event-tag ml10" :class="pointInfo.runStatus == 0 ? 'zx-tag' : 'lx-tag'">
工程{{ pointInfo.engineeringName }} {{ pointInfo.runStatus == 0 ? '在线' : '离线' }}
</text> </text>
<text class="meta-item ellipsis">项目{{ pointInfo.projectName || '-' }}</text> </view>
<text class="meta-item ellipsis">设备{{ pointInfo.deviceName || '-' }}</text> <view class="meta-row">
</view> <text v-if="pointInfo.engineeringName" class="meta-item ellipsis">
<text class="meta-time ellipsis">最新数据时间{{ pointInfo.dataTime || '-' }}</text> 工程{{ pointInfo.engineeringName }}
</view> </text>
</view> <text class="meta-item ellipsis">项目{{ pointInfo.projectName || '-' }}</text>
<text class="meta-item ellipsis">设备{{ pointInfo.deviceName || '-' }}</text>
<view class="legend-row"> </view>
<view class="legend-item" v-for="phase in phaseColors" :key="phase.name"> <text class="meta-time ellipsis">最新数据时间{{ pointInfo.dataTime || '-' }}</text>
<view class="legend-dot" :style="{ background: phase.color }" /> </view>
<text class="legend-text">{{ phase.name }}</text> </view>
</view>
</view> <view class="legend-row">
<view class="legend-item" v-for="phase in phaseColors" :key="phase.name">
<view v-if="moreChildren.length" class="params-section"> <view class="legend-dot" :style="{ background: phase.color }" />
<view <text class="legend-text">{{ phase.name }}</text>
v-for="(rowItems, rowIdx) in chunkedChildren(moreChildren)" </view>
:key="rowIdx" </view>
class="double-row"
> <view v-if="moreChildren.length" class="params-section">
<view v-for="(child, childIdx) in rowItems" :key="child.targetId || childIdx" class="param-group"> <view v-for="(rowItems, rowIdx) in chunkedChildren(moreChildren)" :key="rowIdx" class="double-row">
<view class="param-title"> <view v-for="(child, childIdx) in rowItems" :key="child.targetId || childIdx"
<text>{{ child.name }}{{ child.unit ? ` (${child.unit})` : '' }}</text> class="param-group">
</view> <view class="param-title">
<view v-if="hasTPhaseData(child)" class="phase-single"> <text>{{ child.name }}{{ child.unit ? ` (${child.unit})` : '' }}</text>
<text class="phase-value-vertical phase-value-vertical--neutral">{{ child.T }}</text> </view>
</view> <view v-if="hasTPhaseData(child)" class="phase-single">
<view v-else class="phase-vertical"> <text class="phase-value-vertical phase-value-vertical--neutral">{{ child.T }}</text>
<view class="phase-item-vertical"> </view>
<text class="phase-value-vertical" :style="{ color: phaseColors[0].color }">{{ child.A }}</text> <view v-else class="phase-vertical">
</view> <view class="phase-item-vertical">
<view class="phase-divider" /> <text class="phase-value-vertical" :style="{ color: phaseColors[0].color }">{{
<view class="phase-item-vertical"> child.A }}</text>
<text class="phase-value-vertical" :style="{ color: phaseColors[1].color }">{{ child.B }}</text> </view>
</view> <view class="phase-divider" />
<view class="phase-divider" /> <view class="phase-item-vertical">
<view class="phase-item-vertical"> <text class="phase-value-vertical" :style="{ color: phaseColors[1].color }">{{
<text class="phase-value-vertical" :style="{ color: phaseColors[2].color }">{{ child.C }}</text> child.B }}</text>
</view> </view>
</view> <view class="phase-divider" />
</view> <view class="phase-item-vertical">
</view> <text class="phase-value-vertical" :style="{ color: phaseColors[2].color }">{{
</view> child.C }}</text>
<view v-else class="empty-wrap"> </view>
<Cn-empty msg="暂无更多指标" :paddingTop="120"></Cn-empty> </view>
</view> </view>
</view> </view>
</scroll-view> </view>
</view> <view v-else class="empty-wrap">
</template> <Cn-empty msg="暂无指标数据" :paddingTop="120"></Cn-empty>
</view>
<script> </view>
export default { </scroll-view>
data() { </view>
return { </template>
pointInfo: {},
phaseColors: [ <script>
{ name: 'A相', color: '#F1B22E' }, export default {
{ name: 'B相', color: '#2BA471' }, data() {
{ name: 'C相', color: '#D54941' }, return {
], pointInfo: {},
} phaseColors: [
}, { name: 'A相', color: '#DAA520' },
computed: { { name: 'B相', color: '#2E8B57' },
moreChildren() { { name: 'C相', color: '#D54941' },
const children = this.pointInfo.children || [] ],
const selected = this.getSelectedIndicators() }
return children.filter( },
(child) => !selected.some((name) => this.matchIndicator(child.name, name)), computed: {
) moreChildren() {
}, return this.pointInfo.children || []
}, },
onLoad() { },
const point = uni.getStorageSync('monitorPointDetail') onLoad() {
if (point) { const point = uni.getStorageSync('monitorPointDetail')
this.pointInfo = { if (point) {
...point, this.pointInfo = { ...point }
selectedIndicators: this.getSelectedIndicatorsFromStorage(point.selectedIndicators), if (point.pointName) {
} uni.setNavigationBarTitle({ title: point.pointName })
if (point.pointName) { }
uni.setNavigationBarTitle({ title: point.pointName }) }
} },
} onUnload() {
}, uni.removeStorageSync('monitorPointDetail')
onUnload() { },
uni.removeStorageSync('monitorPointDetail') methods: {
}, hasTPhaseData(child) {
methods: { return child.T !== undefined && child.T !== null && child.T !== '-'
getSelectedIndicatorsFromStorage(fallback = []) { },
const cached = uni.getStorageSync(this.$cacheKey.monitorSelectedIndicators) chunkedChildren(children) {
if (Array.isArray(cached) && cached.length) { const result = []
return cached for (let i = 0; i < children.length; i += 2) {
} result.push(children.slice(i, i + 2))
return Array.isArray(fallback) ? fallback : [] }
}, return result
getSelectedIndicators() { },
return this.getSelectedIndicatorsFromStorage(this.pointInfo.selectedIndicators) },
}, }
matchIndicator(name, selected) { </script>
if (!name || !selected) return false
const base = (name || '').replace(/\(.*\)/, '').trim() <style lang="scss" scoped>
const selectedBase = (selected || '').replace(/\(.*\)/, '').trim() .target-info-page {
return base === selectedBase min-height: 100vh;
}, background: #f7f8fa;
hasTPhaseData(child) { }
return child.T !== undefined && child.T !== null && child.T !== '-'
}, .target-info-scroll {
chunkedChildren(children) { height: 100vh;
const result = [] box-sizing: border-box;
for (let i = 0; i < children.length; i += 2) { padding: 20rpx 0 40rpx;
result.push(children.slice(i, i + 2)) }
}
return result .card {
}, background: #ffffff;
}, border-radius: 10px;
} box-shadow: rgba(0, 0, 0, 0.08) 0px 0px 1px 1px;
</script> margin: 0 10px;
overflow: hidden;
<style lang="scss" scoped> }
.target-info-page {
min-height: 100vh; .monitor-card {
background: #f7f8fa; border: 1rpx solid #eef2f6;
} }
.target-info-scroll { .card-header {
height: 100vh; padding: 20rpx 20rpx 12rpx;
box-sizing: border-box; display: flex;
padding: 20rpx 0 40rpx; align-items: center;
} border-bottom: 1rpx solid #eef2f6;
}
.card {
background: #ffffff; .event-icon {
border-radius: 10px; width: 90rpx;
box-shadow: rgba(0, 0, 0, 0.08) 0px 0px 1px 1px; height: 90rpx;
margin: 0 10px; border-radius: 16rpx;
overflow: hidden; display: flex;
} justify-content: center;
align-items: center;
.monitor-card { margin-right: 20rpx;
border: 1rpx solid #eef2f6; background-color: #376cf320;
} flex-shrink: 0;
}
.card-header {
padding: 20rpx 20rpx 12rpx; .card-header-info {
display: flex; flex: 1;
align-items: center; min-width: 0;
border-bottom: 1rpx solid #eef2f6; }
}
.point-name-row {
.event-icon { display: flex;
width: 90rpx; align-items: center;
height: 90rpx; gap: 12rpx;
border-radius: 16rpx; margin-bottom: 8rpx;
display: flex; min-width: 0;
justify-content: center; }
align-items: center;
margin-right: 20rpx; .point-name {
background-color: #376cf320; // flex: 1;
flex-shrink: 0; min-width: 0;
} font-size: 30rpx;
font-weight: 700;
.card-header-info { color: #333333;
flex: 1; }
min-width: 0;
} .meta-row {
display: grid;
.point-name { grid-template-columns: 1fr ;
display: block; gap: 6rpx 12rpx;
font-size: 30rpx; }
font-weight: 700;
color: #333333; .meta-item {
margin-bottom: 8rpx; font-size: 24rpx;
} color: #666666;
line-height: 1.2;
.meta-row { }
display: grid;
grid-template-columns: 1fr 1fr; .meta-time {
gap: 6rpx 12rpx; display: block;
} margin-top: 8rpx;
font-size: 24rpx;
.meta-item { color: #666666;
font-size: 24rpx; line-height: 1.2;
color: #666666; }
line-height: 1.2;
} .legend-row {
display: flex;
.meta-time { gap: 20rpx;
display: block; align-items: center;
margin-top: 8rpx; justify-content: end;
font-size: 24rpx; padding: 16rpx 20rpx;
color: #666666; }
line-height: 1.2;
} .legend-item {
display: flex;
.legend-row { align-items: center;
display: flex; gap: 8rpx;
gap: 20rpx; }
align-items: center;
padding: 16rpx 20rpx; .legend-dot {
} width: 16rpx;
height: 16rpx;
.legend-item { border-radius: 50%;
display: flex; }
align-items: center;
gap: 8rpx; .legend-text {
} font-size: 24rpx;
color: #666666;
.legend-dot { }
width: 16rpx;
height: 16rpx; .params-section {
border-radius: 50%; padding: 0 16rpx 20rpx;
} }
.legend-text { .empty-wrap {
font-size: 24rpx; position: relative;
color: #666666; min-height: 320rpx;
} }
.params-section { .double-row {
padding: 0 16rpx 20rpx; display: grid;
} grid-template-columns: repeat(2, 1fr);
gap: 16rpx;
.empty-wrap { margin-bottom: 16rpx;
position: relative;
min-height: 320rpx; &:last-child {
} margin-bottom: 0;
}
.double-row { }
display: grid;
grid-template-columns: repeat(2, 1fr); .param-group {
gap: 16rpx; min-width: 0;
margin-bottom: 16rpx; background: #f3f3f3;
border-radius: 16rpx;
&:last-child { padding: 16rpx 8rpx 12rpx;
margin-bottom: 0; }
}
} .param-title {
font-size: 24rpx;
.param-group { color: #666666;
min-width: 0; margin-bottom: 8rpx;
background: #f3f3f3; padding-left: 4rpx;
border-radius: 16rpx; }
padding: 16rpx 8rpx 12rpx;
} .phase-vertical {
display: flex;
.param-title { align-items: stretch;
font-size: 24rpx; }
color: #666666;
margin-bottom: 8rpx; .phase-single {
padding-left: 4rpx; display: flex;
} justify-content: center;
align-items: center;
.phase-vertical { padding: 4rpx;
display: flex; }
align-items: stretch;
} .phase-item-vertical {
flex: 1;
.phase-single { display: flex;
display: flex; justify-content: center;
justify-content: center; align-items: center;
align-items: center; padding: 4rpx;
padding: 4rpx; }
}
.phase-value-vertical {
.phase-item-vertical { font-size: 26rpx;
flex: 1; font-weight: 700;
display: flex;
justify-content: center; &--neutral {
align-items: center; color: #333333;
padding: 4rpx; }
} }
.phase-value-vertical { .phase-divider {
font-size: 28rpx; width: 1px;
font-weight: 700; background: #d2d2d2;
margin: 8rpx 0;
&--neutral { }
color: #333333;
} .ellipsis {
} overflow: hidden;
text-overflow: ellipsis;
.phase-divider { white-space: nowrap;
width: 1px; }
background: #d2d2d2;
margin: 8rpx 0; .event-tag {
} flex-shrink: 0;
font-size: 22rpx;
.ellipsis { padding: 2rpx 10rpx;
overflow: hidden; border-radius: 8rpx;
text-overflow: ellipsis; }
white-space: nowrap;
} .zx-tag {
</style> background-color: #10b98120;
color: #10b981;
}
.lx-tag {
background-color: #ff3b3020;
color: #ff3b30;
}
</style>

View File

@@ -18,8 +18,8 @@
<Cn-filterCriteria @select="select" :showQianTree="false"> </Cn-filterCriteria> <Cn-filterCriteria @select="select" :showQianTree="false"> </Cn-filterCriteria>
</view> </view>
<scroll-view scroll-y="true" @scroll="onScroll" :scroll-top="scrollTop" scroll-with-animation <scroll-view scroll-y="true" @scroll="onScroll" :scroll-top="scrollTop" scroll-with-animation
@refresherrefresh="refresherrefresh" @scrolltolower="scrolltolower" @refresherrefresh="refresherrefresh" @scrolltolower="scrolltolower" :refresher-triggered="triggered"
:refresher-triggered="triggered" refresher-enabled="true" class="record event-list mt20" refresher-enabled="true" class="record event-list mt20"
:style="{ height: 'calc(100vh - ' + (navHeight + height) + 'px)', overflow: 'auto' }"> :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"> <uni-card class="event-item" :class="item.type" v-for="(item, index) in store.data" :key="index">
<!-- 头部图标 + 信息 + 操作 --> <!-- 头部图标 + 信息 + 操作 -->
@@ -67,7 +67,7 @@
<text>报告状态</text> <text>报告状态</text>
<text :style="{ color: item.isComplete == 1 ? '#10b981' : '#FF0000' }">{{ <text :style="{ color: item.isComplete == 1 ? '#10b981' : '#FF0000' }">{{
item.isComplete == 1 ? '已完成' : '未完成' item.isComplete == 1 ? '已完成' : '未完成'
}}</text> }}</text>
</view> </view>
<view class="device-body-item"> <view class="device-body-item">
<text>申请时间</text> <text>申请时间</text>
@@ -192,10 +192,17 @@ export default {
uni.showToast({ uni.showToast({
icon: 'success', icon: 'success',
mask: true, mask: true,
title: '生成事件报告成功!', title: '生成报告成功!',
duration: 1000, duration: 1000,
}) })
this.store.reload() this.store.reload()
}).catch((err) => {
uni.showToast({
icon: 'none',
mask: true,
title: err.message,
duration: 1000,
})
}) })
}, },
// 下载报告 // 下载报告
@@ -208,46 +215,26 @@ export default {
id: item.eventId, id: item.eventId,
}) })
.then((res) => { .then((res) => {
// 下载文件资源到本地 const pathMatch = res.data.match(/excelreport([^?]*)/)
if (!pathMatch) {
uni.hideLoading()
uni.showToast({
icon: 'none',
mask: true,
title: '文件地址无效',
duration: 1000,
})
return
}
const fileMeta = this.getReportFileMeta(pathMatch[1])
const match = this.$config.static + pathMatch[1]
uni.downloadFile({ uni.downloadFile({
url: res.data, // 后端返回的线上文件路径 url: match,
success: function (res) { success: (downloadRes) => {
if (res.statusCode === 200) { if (downloadRes.statusCode === 200) {
// 文件到本地 this.openReportFile(downloadRes.tempFilePath, fileMeta)
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 { } else {
uni.hideLoading()
uni.showToast({ uni.showToast({
icon: 'none', icon: 'none',
mask: true, mask: true,
@@ -256,10 +243,19 @@ export default {
}) })
} }
}, },
fail: function (res) { }, fail: () => {
uni.hideLoading()
uni.showToast({
icon: 'none',
mask: true,
title: '下载失败!',
duration: 1000,
})
},
}) })
}) })
.catch((err) => { .catch((err) => {
uni.hideLoading()
uni.showToast({ uni.showToast({
icon: 'none', icon: 'none',
mask: true, mask: true,
@@ -268,6 +264,79 @@ export default {
}) })
}) })
}, },
getReportFileMeta(filePath) {
const lower = (filePath || '').toLowerCase()
if (lower.endsWith('.doc')) {
return { fileType: 'doc', ext: 'doc' }
}
return { fileType: 'docx', ext: 'docx' }
},
openReportFile(tempFilePath, fileMeta) {
const previewFile = (filePath) => {
uni.hideLoading()
uni.openDocument({
filePath,
fileType: fileMeta.fileType,
showMenu: true,
success: () => {
console.log('成功打开文件')
},
fail: (err) => {
console.log('打开文件失败', err)
uni.showToast({
icon: 'none',
title: '预览失败',
})
},
})
}
// #ifdef APP-PLUS
// iOS 需保留 doc/docx 后缀saveFile 随机路径会导致 openDocument 失败
if (plus.os.name === 'iOS') {
const fileName = `event_report_${Date.now()}.${fileMeta.ext}`
plus.io.resolveLocalFileSystemURL(
tempFilePath,
(entry) => {
plus.io.resolveLocalFileSystemURL(
'_doc/',
(docEntry) => {
entry.copyTo(
docEntry,
fileName,
(newEntry) => previewFile(newEntry.fullPath),
() => previewFile(tempFilePath)
)
},
() => previewFile(tempFilePath)
)
},
() => previewFile(tempFilePath)
)
return
}
// #endif
uni.saveFile({
tempFilePath,
success: (data) => {
uni.showToast({
icon: 'success',
mask: true,
title: '下载成功!',
duration: 1000,
})
setTimeout(() => previewFile(data.savedFilePath), 500)
},
fail: () => {
uni.hideLoading()
uni.showToast({
icon: 'none',
title: '保存失败!',
})
},
})
},
// 刷新 // 刷新
reload() { reload() {
switch (this.curSub) { switch (this.curSub) {
@@ -350,9 +419,9 @@ export default {
font-size: 26rpx; font-size: 26rpx;
color: #666666; color: #666666;
line-height: 1.5; line-height: 1.5;
} }
// } // }
@@ -416,6 +485,10 @@ export default {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
box-shadow: 0 4rpx 16rpx rgba(55, 108, 243, 0.35); box-shadow: 0 4rpx 16rpx rgba(55, 108, 243, 0.35);
z-index: 99; z-index: 1;
}
/deep/ .segmented-control__text {
line-height: 60rpx !important;
} }
</style> </style>

View File

@@ -72,6 +72,7 @@ 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'
import { checkAppUpdate } from '@/common/js/update.js'
export default { export default {
mixins: [list], mixins: [list],
@@ -252,6 +253,11 @@ export default {
this.showBackTop = e.scrollTop > 200 this.showBackTop = e.scrollTop > 200
}, },
onLoad() { onLoad() {
// #ifdef APP-PLUS
checkAppUpdate()
// #endif
// 页面加载时,动态配置导航栏按钮 // 页面加载时,动态配置导航栏按钮
if (!uni.getStorageSync(this.$cacheKey.access_token)) { if (!uni.getStorageSync(this.$cacheKey.access_token)) {
uni.reLaunch({ uni.reLaunch({
@@ -289,6 +295,8 @@ export default {
// #endif // #endif
}, },
onShow() { onShow() {
this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo) this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo)
let access_token = uni.getStorageSync(this.$cacheKey.access_token) let access_token = uni.getStorageSync(this.$cacheKey.access_token)
@@ -319,7 +327,7 @@ export default {
}, },
} }
</script> </script>
<style lang="scss"> <style lang="scss" scoped>
.popup-content { .popup-content {
background: #fff; background: #fff;
} }
@@ -355,7 +363,7 @@ export default {
padding: 4rpx 20rpx; padding: 4rpx 20rpx;
// margin-left: 20rpx; // margin-left: 20rpx;
// margin-bottom: 20rpx; // margin-bottom: 20rpx;
line-height: 38rpx; line-height: 40rpx;
font-size: 24rpx; font-size: 24rpx;
border-radius: 8rpx; border-radius: 8rpx;
background: #ebeaec; background: #ebeaec;
@@ -386,6 +394,6 @@ export default {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
box-shadow: 0 4rpx 16rpx rgba(55, 108, 243, 0.35); box-shadow: 0 4rpx 16rpx rgba(55, 108, 243, 0.35);
z-index: 99; z-index: 1;
} }
</style> </style>

View File

@@ -61,7 +61,7 @@ export default {
selectValue: {}, selectValue: {},
devCount: [], devCount: [],
sortIndex: 0, sortIndex: 0,
sortOptions: ['发生时间', '暂降深度', '持续时间'], sortOptions: ['发生时间', '暂降幅值', '持续时间'],
} }
}, },
onLoad() { }, onLoad() { },
@@ -101,7 +101,7 @@ export default {
this.getDevCount() this.getDevCount()
this.$nextTick(() => { this.$nextTick(() => {
if (params.type !== '') { if (params.type !== '') {
this.current = params.type - 0 this.current = (params.type - 0)||0
} }
if (params.engineeringName != '') { if (params.engineeringName != '') {
this.$refs.cnFilterCriteria && this.$refs.cnFilterCriteria.external(params) this.$refs.cnFilterCriteria && this.$refs.cnFilterCriteria.external(params)
@@ -343,4 +343,5 @@ export default {
// white-space: nowrap; // white-space: nowrap;
line-height: 1; line-height: 1;
} }
</style> </style>

View File

@@ -82,11 +82,7 @@
<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('transientSetting')" v-if="userInfo.authorities !== 'tourist'">
<image mode="aspectFill" class="mine-nav-icon" src="/static/tongji.png" />
<view class="mine-nav-label">暂态统计配置</view>
<uni-icons type="forward" color="#aaa" size="20"></uni-icons>
</view> -->
<view class="mine-nav" @click="jump('setup')" style="border-bottom: none"> <view class="mine-nav" @click="jump('setup')" style="border-bottom: none">
<image mode="aspectFill" class="mine-nav-icon" src="/static/setup.png" /> <image mode="aspectFill" class="mine-nav-icon" src="/static/setup.png" />
<view class="mine-nav-label">设置</view> <view class="mine-nav-label">设置</view>
@@ -259,7 +255,7 @@ export default {
handleScon() { handleScon() {
this.$refs.message.close() this.$refs.message.close()
uni.scanCode({ uni.scanCode({
onlyFromCamera: true, // onlyFromCamera: false,
success: (res) => { success: (res) => {
console.log('条码类型:' + res.scanType) console.log('条码类型:' + res.scanType)
console.log('条码内容:' + res.result) console.log('条码内容:' + res.result)

View File

@@ -6,34 +6,33 @@
<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')" v-if="userInfo.authorities === 'app_vip_user'">关闭</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')" v-if="userInfo.authorities === 'app_vip_user'">关闭</view>
<!-- </template>--> </template>
<!-- <view class="title-btn" @click="open">回复</view>--> <view class="title-btn" @click="open" v-if="pageData.status != '0'">回复</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" clearable
<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>
@@ -41,7 +40,7 @@
</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() {
@@ -55,11 +54,13 @@ export default {
"url": "/static/logo.png", "url": "/static/logo.png",
} }
], ],
userInfo: {},
pageData: {}, pageData: {},
pageOption: {} pageOption: {}
} }
}, },
onLoad(o) { onLoad(o) {
this.userInfo = uni.getStorageSync(this.$cacheKey.userInfo)
this.pageOption = o this.pageOption = o
this.init() this.init()
updateChatStatus({ updateChatStatus({
@@ -93,7 +94,7 @@ export default {
}) })
}, },
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()
@@ -101,7 +102,9 @@ export default {
}) })
}, },
open() { open() {
this.chatContent = ''
this.$refs.inputDialog.open() this.$refs.inputDialog.open()
}, },
over() { over() {
}, },

View File

@@ -190,6 +190,6 @@ export default {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
box-shadow: 0 4rpx 16rpx rgba(55, 108, 243, 0.35); box-shadow: 0 4rpx 16rpx rgba(55, 108, 243, 0.35);
z-index: 99; z-index: 1;
} }
</style> </style>

View File

@@ -1,286 +1,286 @@
<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.date }}</view> <view>{{ detail.date }}</view>
</view> </view>
<view class="detail-content" style="padding-top: 0px;padding-bottom: 0px"> <view class="detail-content" style="padding-top: 0px;padding-bottom: 0px">
<view class="detail-content-title pb20 pt20 pl20">终端告警列表</view> <view class="detail-content-title pb20 pt20 pl20">终端告警列表</view>
</view> </view>
<view class="event-list"> <view class="event-list">
<uni-card class="event-item" :class="item.type" v-for="(item, index) in list" :key="index"> <uni-card class="event-item" :class="item.type" v-for="(item, index) in list" :key="index">
<!-- 头部图标 + 信息 + 操作 --> <!-- 头部图标 + 信息 + 操作 -->
<view class="event-header"> <view class="event-header">
<view class="event-icon" <view class="event-icon"
:class="item.devType == 'Direct_Connected_Device' ? 'zl-bgc' : 'jc-bgc'"> :class="item.devType == 'Direct_Connected_Device' ? 'zl-bgc' : 'jc-bgc'">
<Cn-icon-transient :name="item.devType == 'Direct_Connected_Device' ? '治理设备' : '监测设备'" /> <Cn-icon-transient :name="item.devType == 'Direct_Connected_Device' ? '治理设备' : '监测设备'" />
<view class="badge1" v-if="item.status == 0"> </view> <view class="badge1" v-if="item.status == 0"> </view>
</view> </view>
<view class="event-info"> <view class="event-info">
<view class="event-title"> <view class="event-title">
<text class="event-id">{{ item.devName }}</text> <text class="event-id">{{ item.devName }}</text>
<text class="event-tag" <text class="event-tag"
:class="item.devType == 'Direct_Connected_Device' ? 'zl-tag' : 'jc-tag'">{{ :class="item.devType == 'Direct_Connected_Device' ? 'zl-tag' : 'jc-tag'">{{
item.devType == 'Direct_Connected_Device' ? '治理设备' : '监测设备' }}</text> item.devType == 'Direct_Connected_Device' ? '治理设备' : '监测设备' }}</text>
</view> </view>
<view class="event-desc"> <view class="event-desc">
<text>工程{{ item.engineeringName }}</text> <text>工程{{ item.engineeringName }}</text>
<text>项目{{ item.projectName }}</text> <text>项目{{ item.projectName }}</text>
<!-- <text v-if="item.dataDetails.onlineRate.isAbnormal">在线率{{ <!-- <text v-if="item.dataDetails.onlineRate.isAbnormal">在线率{{
item.dataDetails.onlineRate.value }}% 限值{{ item.dataDetails.onlineRate.threshold item.dataDetails.onlineRate.value }}% 限值{{ item.dataDetails.onlineRate.threshold
}}% </text> --> }}% </text> -->
<!-- <text>事件时间{{ item.startTime }}</text> --> <!-- <text>事件时间{{ item.startTime }}</text> -->
</view> </view>
</view> </view>
</view> </view>
<!-- 详情区域 --> <!-- 详情区域 -->
<view class="event-detail"> <view class="event-detail">
<view v-if="item.dataDetails.onlineRate.isAbnormal"> <view v-if="item.dataDetails.onlineRate.isAbnormal">
<text>在线率 <text>在线率
<text class="integrity-value">{{ item.dataDetails.onlineRate.value }}%</text>  <text class="integrity-value">{{ item.dataDetails.onlineRate.value }}%</text> 
</text> </text>
</view> </view>
<view v-if="hasIntegrityAbnormal(item)" class="mt10"> <view v-if="hasIntegrityAbnormal(item)" class="mt10">
数据完整性 数据完整性
<view class="integrity-grid"> <view class="integrity-grid">
<view <view
v-for="(rowItems, rowIdx) in chunkedPoints(getAbnormalPoints(item))" v-for="(rowItems, rowIdx) in chunkedPoints(getAbnormalPoints(item))"
:key="rowIdx" :key="rowIdx"
class="grid-row"> class="grid-row">
<view <view
v-for="(point, pIdx) in rowItems" v-for="(point, pIdx) in rowItems"
:key="pIdx" :key="pIdx"
class="param-group"> class="param-group">
<view class="param-title"> <view class="param-title">
<text>{{ point.monitorName }}</text> <text>{{ point.monitorName }}</text>
</view> </view>
<view class="integrity-value-row"> <view class="integrity-value-row">
<text class="integrity-value">{{ point.value }}%</text> <text class="integrity-value">{{ point.value }}%</text>
</view> </view>
</view> </view>
</view> </view>
</view> </view>
</view> </view>
<view v-if="item.warnCounts" class="mt10 "> <view v-if="item.warnCounts" class="mt10 ">
终端告警 {{ item.warnCounts }} 详情如下 终端告警 {{ item.warnCounts }} 详情如下
<view class="textBox mt10"> <view class="textBox mt10">
<view v-for="val in item.warnDetails" class="textBox mb5" style=" font-size: 26rpx;"> <view v-for="val in item.warnDetails" class="textBox mb5" style=" font-size: 26rpx;">
{{ val.warnEventTime + '发生' + val.warnEventDesc }} {{ val.warnEventTime + '发生' + val.warnEventDesc }}
</view> </view>
</view> </view>
</view> </view>
</view> </view>
</uni-card> </uni-card>
</view> </view>
</view> </view>
</Cn-page> </Cn-page>
</template> </template>
<script> <script>
import { updateStatus, queryAlarmDetail } from '@/common/api/message' import { updateStatus, queryAlarmDetail } from '@/common/api/message'
export default { export default {
data() { data() {
return { return {
loading: true, loading: true,
detail: {}, detail: {},
limit: '', limit: '',
collapseValue: '0', collapseValue: '0',
list: [], list: [],
} }
}, },
onLoad(options) { onLoad(options) {
this.loading = true this.loading = true
this.detail = JSON.parse(decodeURIComponent(options.detail).replace(/百分比/g, '%')) this.detail = JSON.parse(decodeURIComponent(options.detail).replace(/百分比/g, '%'))
this.init() this.init()
if (this.detail.isRead != 1) { if (this.detail.isRead != 1) {
updateStatus({ updateStatus({
eventIds: [this.detail.eventId], eventIds: [this.detail.eventId],
}) })
} }
}, },
methods: { methods: {
hasIntegrityAbnormal(item) { hasIntegrityAbnormal(item) {
const points = item?.dataDetails?.integrity?.monitorPoints const points = item?.dataDetails?.integrity?.monitorPoints
if (!Array.isArray(points) || !points.length) return false if (!Array.isArray(points) || !points.length) return false
return points.some((p) => p.isAbnormal === true) return points.some((p) => p.isAbnormal === true)
}, },
getAbnormalPoints(item) { getAbnormalPoints(item) {
return item?.dataDetails?.integrity?.monitorPoints?.filter((p) => p.isAbnormal === true) || [] return item?.dataDetails?.integrity?.monitorPoints?.filter((p) => p.isAbnormal === true) || []
}, },
chunkedPoints(points) { chunkedPoints(points) {
const result = [] const result = []
for (let i = 0; i < points.length; i += 3) { for (let i = 0; i < points.length; i += 3) {
result.push(points.slice(i, i + 3)) result.push(points.slice(i, i + 3))
} }
return result return result
}, },
init() { init() {
queryAlarmDetail({ queryAlarmDetail({
devList: this.detail.devIds, devList: this.detail.devIds,
time: this.detail.date, time: this.detail.date,
}) })
.then((res) => { .then((res) => {
this.list = res.data this.list = res.data
this.loading = false this.loading = false
}) })
.catch(() => { .catch(() => {
this.loading = false this.loading = false
}) })
}, },
}, },
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import '../index.scss'; @import '../index.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: 28rpx; font-size: 28rpx;
.detail-content-title { .detail-content-title {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
position: relative; position: relative;
padding-left: 20rpx; padding-left: 20rpx;
font-size: 30rpx; font-size: 30rpx;
color: #111; color: #111;
font-weight: 700; font-weight: 700;
&::before { &::before {
content: ''; content: '';
position: absolute; position: absolute;
left: 0; left: 0;
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
width: 8rpx; width: 8rpx;
height: 28rpx; height: 28rpx;
background: $uni-theme-color; background: $uni-theme-color;
border-radius: 3rpx; border-radius: 3rpx;
} }
} }
} }
.collapseTop { .collapseTop {
padding: 10rpx 0; padding: 10rpx 0;
margin-left: 15px; margin-left: 15px;
.name { .name {
font-size: 28rpx; font-size: 28rpx;
font-weight: 700; font-weight: 700;
color: #333333; color: #333333;
} }
} }
.frequency { .frequency {
display: flex; display: flex;
font-size: 28rpx; font-size: 28rpx;
// color: #666666; // color: #666666;
} }
} }
.textBox { .textBox {
// border-bottom: 1px solid #eee; // border-bottom: 1px solid #eee;
font-size: 28rpx; font-size: 28rpx;
color: #666666; color: #666666;
text-indent: 2em; text-indent: 2em;
} }
.event-list { .event-list {
// background: #fff; // background: #fff;
padding-bottom: 10rpx; padding-bottom: 10rpx;
// .event-icon { // .event-icon {
// background-color: #376cf320; // background-color: #376cf320;
// } // }
.zl-bgc { .zl-bgc {
background-color: #376cf320; background-color: #376cf320;
} }
.jc-bgc { .jc-bgc {
background-color: #376cf320; background-color: #376cf320;
} }
.zl-tag { .zl-tag {
background-color: #007aff20; background-color: #007aff20;
color: #007aff; color: #007aff;
} }
.jc-tag { .jc-tag {
background-color: #007aff20; background-color: #007aff20;
color: #007aff; color: #007aff;
} }
} }
/deep/ .uni-collapse-item__title-box { /deep/ .uni-collapse-item__title-box {
padding: 0 15px 0 0; padding: 0 15px 0 0;
height: 56rpx; height: 56rpx;
line-height: 56rpx; line-height: 56rpx;
font-size: 26rpx !important; font-size: 26rpx !important;
color: #666666; color: #666666;
span { span {
font-size: 26rpx !important; font-size: 26rpx !important;
} }
} }
.textBox { .textBox {
max-height: 150rpx; max-height: 150rpx;
overflow-y: auto; overflow-y: auto;
} }
.integrity-grid { .integrity-grid {
margin-top: 16rpx; margin-top: 16rpx;
} }
.grid-row { .grid-row {
display: grid; display: grid;
grid-template-columns: repeat(3, 1fr); grid-template-columns: repeat(3, 1fr);
gap: 16rpx; gap: 16rpx;
margin-bottom: 16rpx; margin-bottom: 16rpx;
&:last-child { &:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
} }
.param-group { .param-group {
min-width: 0; min-width: 0;
background: #f3f3f3; background: #f3f3f3;
border-radius: 16rpx; border-radius: 16rpx;
padding: 16rpx 8rpx 12rpx; padding: 16rpx 8rpx 12rpx;
text-align: center; text-align: center;
} }
.param-title { .param-title {
font-size: 24rpx; font-size: 24rpx;
color: #666666; color: #666666;
// margin-bottom: 8rpx; // margin-bottom: 8rpx;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }
.integrity-value-row { .integrity-value-row {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
padding: 2rpx; padding: 2rpx;
} }
.integrity-value { .integrity-value {
font-size: 26rpx; font-size: 26rpx;
font-weight: 700; font-weight: 700;
color: #333333; color: #333333;
} }
</style> </style>

View File

@@ -28,7 +28,7 @@
<text v-if="!item.harmDetailList[0].hasT">A相</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">B相</text>
<text v-if="!item.harmDetailList[0].hasT">C相</text> <text v-if="!item.harmDetailList[0].hasT">C相</text>
<text v-if="item.harmDetailList[0].hasT"></text> <text v-if="item.harmDetailList[0].hasT"></text>
<text>限值</text> <text>限值</text>
</view> </view>
<view class="table-row" v-for="value in item.harmDetailList"> <view class="table-row" v-for="value in item.harmDetailList">

View File

@@ -4,17 +4,21 @@
<view class="detail-content" style="font-size: 32rpx"> <view class="detail-content" style="font-size: 32rpx">
<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.engineeringName }} </view> <view class="mb5"> 工程{{ detail.engineeringName }} </view>
<view class="mb5"> 项目{{ detail.projectName }} </view> <view class="mb5"> 项目{{ detail.projectName }} </view>
<view class="mb5"> 设备{{ detail.equipmentName }}</view> <view class="mb5"> 设备{{ detail.equipmentName }}</view>
<view class="mb5"> 监测点{{ detail.lineName }}</view> <view class="mb5"> 监测点{{ detail.lineName }}</view>
<view class="mb5"> 暂态类型{{ detail.showName }}</view> <view class="mb5"> 暂态类型{{ detail.showName }}</view>
<view class="mb5" v-if="detail.evtParamPhase"> 相别{{ detail.evtParamPhase }}</view>
<view class="mb5" v-if="detail.evtParamTm"> 持续时间{{ detail.evtParamTm }}s</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.evtParamVVaDepth"> 幅值{{ detail.evtParamVVaDepth }}%</view>
<view class="mb5" v-if="detail.evtParamPhase"> 相别{{ detail.evtParamPhase }}</view> <view class="mb5"> 落点区域{{ detail.landPoint != null && detail.landPoint !== '' ? detail.landPoint :
<view class="mb5" > 落点区域{{ detail.landPoint != null && detail.landPoint !== '' ? detail.landPoint : '未知' }}</view> '未知'
}}</view>
</view> </view>
<view class="detail-tabs"> <view class="detail-tabs">
<uni-segmented-control :current="detailTab" active-color="#376cf3" :values="['波形图', 'ITIC', 'F47']" <uni-segmented-control :current="detailTab" active-color="#376cf3" :values="['波形图', 'ITIC', 'F47']"
@@ -60,6 +64,7 @@ import F47 from './F47.vue'
import waveform from './waveform.vue' import waveform from './waveform.vue'
import { analyseWave } from '@/common/api/harmonic.js'; import { analyseWave } from '@/common/api/harmonic.js';
export default { export default {
components: { ITIC, F47, waveform }, components: { ITIC, F47, waveform },
data() { data() {
@@ -190,25 +195,9 @@ export default {
font-size: 28rpx; font-size: 28rpx;
.detail-content-title { .detail-content-title {
display: inline-flex;
align-items: center;
position: relative;
padding-left: 20rpx;
font-size: 30rpx; font-size: 30rpx;
color: #111; color: #111;
font-weight: 700; font-weight: 700;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 8rpx;
height: 28rpx;
background: $uni-theme-color;
border-radius: 3rpx;
}
} }
} }
@@ -233,4 +222,23 @@ export default {
margin-right: 24rpx; margin-right: 24rpx;
height: 60rpx; height: 60rpx;
} }
/deep/ .segmented-control__text {
line-height: 60rpx !important;
}
.detail-content-info {
display: grid;
grid-template-columns: 1fr 1fr;
}
// .detail-content-info {
// display: grid;
// grid-template-columns: 1fr 1fr;
// }
.detail-content-info {
display: grid;
grid-template-columns: 1fr 1fr;
}
</style> </style>

View File

@@ -76,11 +76,11 @@
border-radius: 20rpx; border-radius: 20rpx;
} }
/* 电压暂降 - 蓝色系 */ /* 暂降 - 蓝色系 */
.sag .event-icon { .sag .event-icon {
background-color: #2563eb20; background-color: #2563eb20;
} }
/* 电压暂升 - 橙色系 */ /* 暂升 - 橙色系 */
.swell .event-icon { .swell .event-icon {
background-color: #e6a23c20; background-color: #e6a23c20;
} }

View File

@@ -186,7 +186,7 @@ export default {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
box-shadow: 0 4rpx 16rpx rgba(55, 108, 243, 0.35); box-shadow: 0 4rpx 16rpx rgba(55, 108, 243, 0.35);
z-index: 99; z-index: 1;
} }
</style> </style>

View File

@@ -337,7 +337,7 @@ export default {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
box-shadow: 0 4rpx 16rpx rgba(55, 108, 243, 0.35); box-shadow: 0 4rpx 16rpx rgba(55, 108, 243, 0.35);
z-index: 99; z-index: 1;
} }
.textBox { .textBox {
@@ -371,17 +371,23 @@ export default {
} }
/deep/ .uni-calendar-item__weeks-box-text { /deep/ .uni-calendar-item__weeks-box-text {
position: relative;
z-index: 1; z-index: 1;
line-height: 1;
} }
/deep/ .uni-calendar-item--isDay-text { /deep/ .uni-calendar-item__weeks-box-item {
color: #333 !important; /* 改成你想要的颜色 */ display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
} }
/deep/ .uni-calendar-item__weeks-box-circle { /deep/ .uni-calendar-item__weeks-box-circle {
position: absolute; position: absolute;
top: 7px; top: 50%;
right: 6px; left: 50%;
transform: translate(-50%, -50%);
width: 39px; width: 39px;
height: 39px; height: 39px;
border-radius: 50%; border-radius: 50%;
@@ -389,9 +395,13 @@ export default {
background-color: #e6a23c; background-color: #e6a23c;
} }
/* 核心:选中圆圈下的 子元素(日期数字 */ /* 选中圆圈下的日期数字 */
/deep/ .uni-calendar-item__weeks-box-circle + .uni-calendar-item__weeks-box-text { /deep/ .uni-calendar-item__weeks-box-circle + .uni-calendar-item__weeks-box-text {
color: #fff !important; /* 改成你想要的颜色 */ color: #fff !important;
}
/deep/ .uni-calendar-item--isDay-text {
color: #333 !important;
} }
/deep/ .uni-calendar__backtoday, /deep/ .uni-calendar__backtoday,
@@ -421,9 +431,9 @@ export default {
} }
/deep/ .uni-calendar-item__weeks-box-circle { /deep/ .uni-calendar-item__weeks-box-circle {
position: absolute; top: 50%;
top: 3px; left: 50%;
right: 8px; transform: translate(-50%, -50%);
width: 35px; width: 35px;
height: 35px; height: 35px;
} }

View File

@@ -59,8 +59,8 @@
<text> <text>
{{ item.startTime ? '发生时间:' + item.startTime : '' }} {{ item.startTime ? '发生时间:' + item.startTime : '' }}
{{ {{
item.evtParamVVaDepth != null && item.evtParamVVaDepth !== '' item.evtParamPhase != null && item.evtParamPhase !== ''
? '幅值' + item.evtParamVVaDepth + '%' ? '相别' + item.evtParamPhase
: '' : ''
}} }}
{{ {{
@@ -69,10 +69,12 @@
: '' : ''
}} }}
{{ {{
item.evtParamPhase != null && item.evtParamPhase !== '' item.evtParamVVaDepth != null && item.evtParamVVaDepth !== ''
? '相别' + item.evtParamPhase ? '幅值' + item.evtParamVVaDepth + '%'
: '' : ''
}} {{ }}
{{
item.landPoint != null && item.landPoint !== '' item.landPoint != null && item.landPoint !== ''
? ',落点区域:' + item.landPoint ? ',落点区域:' + item.landPoint
: ',落点区域:未知' : ',落点区域:未知'
@@ -115,9 +117,9 @@ export default {
filterValue: 0, filterValue: 0,
dataList: [ dataList: [
{ value: 0, label: '暂态数量', key: '' }, { value: 0, label: '暂态数量', key: '' },
{ value: 0, label: '暂降', key: '电压暂降' }, { value: 0, label: '暂降', key: '暂降' },
{ value: 0, label: '中断', key: '电压中断' }, { value: 0, label: '中断', key: '中断' },
{ value: 0, label: '暂升', key: '电压暂升' }, { value: 0, label: '暂升', key: '暂升' },
], ],
status: 'noMore', //more加载前 loading加载中 noMore加载后 status: 'noMore', //more加载前 loading加载中 noMore加载后
sort: 0, sort: 0,
@@ -177,21 +179,21 @@ export default {
}, },
judgment(val, key) { judgment(val, key) {
switch (val) { switch (val) {
case '电压暂降': case '暂降':
return { return {
type: 'sag', type: 'sag',
icon: 'icon-a-svg4', icon: 'icon-a-svg4',
color: '#2563eb', color: '#2563eb',
size: '25', size: '25',
} }
case '电压暂升': case '暂升':
return { return {
type: 'swell', type: 'swell',
icon: 'icon-a-svg5', icon: 'icon-a-svg5',
color: '#e6a23c', color: '#e6a23c',
size: '25', size: '25',
} }
case '电压中断': case '中断':
return { return {
type: 'interrupt', type: 'interrupt',
icon: 'icon-zhongduan2', icon: 'icon-zhongduan2',
@@ -287,6 +289,6 @@ export default {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
box-shadow: 0 4rpx 16rpx rgba(55, 108, 243, 0.35); box-shadow: 0 4rpx 16rpx rgba(55, 108, 243, 0.35);
z-index: 99; z-index: 1;
} }
</style> </style>

View File

@@ -1,85 +1,85 @@
<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" v-for="(item, index) in formData" :key="index"> <view class="content" v-for="(item, index) in formData" :key="index">
<uni-forms> <uni-forms>
<uni-forms-item label="类型"> <uni-forms-item label="类型">
<uni-data-select v-model="item.type" :localdata="range"></uni-data-select> <uni-data-select v-model="item.type" :localdata="range"></uni-data-select>
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="区域"> <uni-forms-item label="区域">
<uni-easyinput type="textarea" v-model="item.title" placeholder="请输入问题简要" /> <uni-easyinput type="textarea" v-model="item.title" placeholder="请输入区域" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="描述"> <uni-forms-item label="描述">
<uni-easyinput type="textarea" v-model="item.des" placeholder="请输入详细描述" /> <uni-easyinput type="textarea" v-model="item.des" placeholder="请输入详细描述" />
</uni-forms-item> </uni-forms-item>
</uni-forms> </uni-forms>
</view> </view>
<view class="btn-wrap"> <view class="btn-wrap">
<view class="btn-wrap-item " @click="submit"> 提交 </view> <view class="btn-wrap-item " @click="submit"> 提交 </view>
</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,
formData: [ formData: [
{ {
title: '', title: '',
des: '', des: '',
} }
], ],
range: [ range: [
{ value: 0, text: "需求" }, { value: 0, text: "需求" },
{ value: 1, text: "缺陷" }, { value: 1, text: "缺陷" },
], ],
} }
}, },
methods: { methods: {
add () { add () {
this.formData.push({ this.formData.push({
type: '', type: '',
address: '', address: '',
}) })
}, },
submit () { submit () {
console.log(this.formData) console.log(this.formData)
uni.navigateBack({ delta: 1 }) uni.navigateBack({ delta: 1 })
}, },
} }
} }
</script> </script>
<style lang='scss'> <style lang='scss'>
.index { .index {
padding: 20rpx; padding: 20rpx;
.content { .content {
margin-bottom: 20rpx; margin-bottom: 20rpx;
padding: 34rpx; padding: 34rpx;
background: $uni-theme-white; background: $uni-theme-white;
border-radius: 12rpx; border-radius: 12rpx;
} }
.btn-wrap { .btn-wrap {
margin-top: 40rpx; margin-top: 40rpx;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
.btn-wrap-item { .btn-wrap-item {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex: 1; flex: 1;
background: $uni-theme-color; background: $uni-theme-color;
color: #fff; color: #fff;
height: 80rpx; height: 80rpx;
border-radius: 12rpx; border-radius: 12rpx;
} }
} }
} }
</style> </style>

View File

@@ -48,7 +48,7 @@
<!-- @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">当前版本V{{ version }}</view> <view style="color: #828282; font-size: 24rpx">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 File

@@ -1,41 +1,25 @@
<template> <template>
<Cn-page :loading="loading"> <Cn-page>
<view class="mine" slot="body"> <view class="mine" slot="body">
<view class="mine-nav mt20" style="border-bottom: none"> <view class="mine-nav mt20" style="border-bottom: none">
<view class="mine-nav-label">暂态事件</view> <view class="mine-nav-label">暂态事件</view>
<switch <switch style="transform: scale(0.8)" color="#376cf3" @change="change('eventInfo')"
style="transform: scale(0.8)" :checked="config.eventInfo === 1" />
color="#376cf3"
@change="change('eventInfo')"
:checked="config.eventInfo === 1"
/>
</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)" color="#376cf3" @change="change('harmonicInfo')"
style="transform: scale(0.8)" :checked="config.harmonicInfo === 1" />
color="#376cf3"
@change="change('harmonicInfo')"
:checked="config.harmonicInfo === 1"
/>
</view> </view>
<view class="mine-nav" style="border-bottom: none"> <view class="mine-nav" style="border-bottom: none" v-if="flag">
<view class="mine-nav-label">运行告警</view> <view class="mine-nav-label">运行告警</view>
<switch <switch style="transform: scale(0.8)" color="#376cf3" @change="change('alarmInfo')"
style="transform: scale(0.8)" :checked="config.alarmInfo === 1" />
color="#376cf3"
@change="change('alarmInfo')"
:checked="config.alarmInfo === 1"
/>
</view> </view>
<view class="mine-nav" > <view class="mine-nav" v-if="flag">
<view class="mine-nav-label">运行事件</view> <view class="mine-nav-label">运行事件</view>
<switch <switch style="transform: scale(0.8)" color="#376cf3" @change="change('runInfo')"
style="transform: scale(0.8)" :checked="config.runInfo === 1" />
color="#376cf3"
@change="change('runInfo')"
:checked="config.runInfo === 1"
/>
</view> </view>
</view> </view>
</Cn-page> </Cn-page>
@@ -49,6 +33,7 @@ export default {
return { return {
loading: true, loading: true,
config: {}, config: {},
flag: false,
} }
}, },
methods: { methods: {
@@ -100,12 +85,18 @@ export default {
} }
}, },
onUnload() { onUnload() {
updatePushConfig(this.config).then((res) => { if (this.config.eventInfo != undefined) {
// this.$util.toast(`配置修改成功!`) updatePushConfig(this.config).then((res) => {
}) // this.$util.toast(`配置修改成功!`)
})
}
}, },
}, },
onLoad() { onLoad() {
if (uni.getStorageSync(this.$cacheKey.userInfo).authorities === 'operation_manager') {
this.flag = true
}
this.init() this.init()
}, },
} }

View File

@@ -1,129 +0,0 @@
<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,77 +1,77 @@
<template> <template>
<Cn-page :loading="loading"> <Cn-page :loading="loading">
<view slot="body"> <view slot="body">
<view class="index"> <view class="index">
<uni-card <uni-card
title="设备信息" title="设备信息"
sub-title="副标题" sub-title="副标题"
v-for="item in 3" v-for="item in 3"
:key="item" :key="item"
thumbnail="/static/real_time_data.png" thumbnail="/static/real_time_data.png"
> >
<view class="footer"> <view class="footer">
<text>设备基础信息 </text> <text>设备基础信息 </text>
<view class="footer-btn" @click="del">移除</view> <view class="footer-btn" @click="del">移除</view>
</view> </view>
</uni-card> </uni-card>
<uni-load-more status="nomore"></uni-load-more> <uni-load-more status="nomore"></uni-load-more>
</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: {
del() { 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('用户点击取消')
} }
}, },
}) })
}, },
newDevice() { newDevice() {
uni.scanCode({ uni.scanCode({
onlyFromCamera: true, onlyFromCamera: false,
success: function (res) { success: function (res) {
console.log('条码类型:' + res.scanType) console.log('条码类型:' + res.scanType)
console.log('条码内容:' + res.result) console.log('条码内容:' + res.result)
uni.navigateTo({ uni.navigateTo({
url: '/pages/gateway/newDevice', url: '/pages/gateway/newDevice',
}) })
}, },
}) })
}, },
}, },
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.index { .index {
.footer { .footer {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
.footer-btn { .footer-btn {
padding: 0 20rpx; padding: 0 20rpx;
height: 50rpx; height: 50rpx;
background-color: #e47470; background-color: #e47470;
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,464 +1,444 @@
<template> <template>
<Cn-page :loading="loading"> <Cn-page :loading="loading">
<view slot="body"> <view slot="body">
<view class="new" :class="{'project-new':!this.options.project}"> <view class="new" :class="{ 'project-new': !this.options.project }">
<view class="content"> <view class="content">
<uni-forms :label-width="80"> <uni-forms :label-width="80">
<uni-forms-item label="工程名称" @click.native.stop.prevent="selectEngineering"> <uni-forms-item label="工程名称">
<uni-easyinput <view class="engineering-select" @click="selectEngineering">
v-model="formData.engineeringName" <uni-easyinput
placeholder="请选择工程" v-model="formData.engineeringName"
:clearable="false" disabled
:disabled="true" maxlength="50"
/> placeholder="请选择工程"
</uni-forms-item> :clearable="false"
<uni-forms-item label="项目名称"> />
<uni-easyinput v-model="formData.name" placeholder="请输入项目名称"/> </view>
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="区域"> <uni-forms-item label="项目名称">
<view style="display: flex"> <uni-easyinput v-model="formData.name" maxlength="50" placeholder="请输入项目名称" />
<uni-easyinput </uni-forms-item>
:clearable="false" <uni-forms-item label="区域">
type="textarea" <view style="display: flex">
autoHeight <uni-easyinput :clearable="false" type="textarea" maxlength="250" autoHeight
v-model="formData.area" v-model="formData.area" placeholder="请输入区域信息" />
placeholder="请输入区域信息" <!-- <uni-icons
/> type="location"
<!-- <uni-icons color="#007aff"
type="location" size="26"
color="#007aff" class="ml20"
size="26" @click="chooseLocation"
class="ml20" ></uni-icons> -->
@click="chooseLocation" </view>
></uni-icons> --> </uni-forms-item>
</view> <uni-forms-item label="描述">
</uni-forms-item> <uni-easyinput type="textarea" autoHeight maxlength="999" v-model="formData.description"
<uni-forms-item label="描述"> placeholder="请输入项目描述" />
<uni-easyinput </uni-forms-item>
type="textarea" <view class="temp-choose">
autoHeight <view class="temp-choose-title">从模版库选择拓扑图</view>
maxlength="999" <view class="temp-choose-content">
v-model="formData.description" <view class="temp-choose-content-item" v-for="(item, index) in formData.tempFiles">
placeholder="请输入项目描述" <image class="temp-choose-content-item-img" :src="item.filePath"
/> mode="aspectFill" />
</uni-forms-item> <view class="temp-choose-content-item-close" @click="deleteImg(index)">
<view class="temp-choose"> <uni-icons style="font-size: 18px" type="closeempty" color="#fff" size="20" />
<view class="temp-choose-title">从模版库选择拓扑图</view> </view>
<view class="temp-choose-content"> </view>
<view class="temp-choose-content-item" v-for="(item, index) in formData.tempFiles"> <view class="temp-choose-content-item" @click="openTemp">
<image <uni-icons type="plusempty" size="70" color="#f1f1f1"></uni-icons>
class="temp-choose-content-item-img" </view>
:src="item.filePath" </view>
mode="aspectFill" </view>
/> <uni-file-picker v-model="formData.files" title="从本地上传拓扑图" :sourceType="['album']"
<view class="temp-choose-content-item-close" @click="deleteImg(index)"> :before-remove="beforeRemove" @select="select"></uni-file-picker>
<uni-icons style="font-size: 18px" type="closeempty" color="#fff" size="20"/> </uni-forms>
</view> </view>
</view> <view class="btn-wrap">
<view class="temp-choose-content-item" @click="openTemp"> <view class="btn-wrap-item" @click="submit"> 提交</view>
<uni-icons type="plusempty" size="70" color="#f1f1f1"></uni-icons> </view>
</view> <uni-popup ref="showTemp" type="bottom" :mask-click="false">
</view> <view class="popup-header">
</view> <view class="popup-header-title">模版库</view>
<uni-file-picker <view class="popup-header-close" @click="closeTemp">
v-model="formData.files" <uni-icons type="closeempty" color="#111" size="20" />
title="从本地上传拓扑图" </view>
:sourceType="['album']" </view>
:before-remove="beforeRemove" <view class="temp-list">
@select="select" <view class="temp-list-item" :class="{
></uni-file-picker> 'temp-list-item-active': formData.tempFiles.some(
</uni-forms> (item2) => item2.id === item.id || item2.topoId === item.id,
</view> ),
<view class="btn-wrap"> }" v-for="(item, index) in tempList" @click="chooseTempItem(item)">
<view class="btn-wrap-item" @click="submit"> 提交</view> <image class="temp-list-item-img" :src="item.filePath" mode="aspectFill" />
</view> <view class="temp-list-item-name">{{ item.name }}</view>
<uni-popup ref="showTemp" type="bottom" :mask-click="false"> </view>
<view class="popup-header"> </view>
<view class="popup-header-title">模版库</view> </uni-popup>
<view class="popup-header-close" @click="closeTemp"> </view>
<uni-icons type="closeempty" color="#111" size="20"/> </view>
</view> </Cn-page>
</view> </template>
<view class="temp-list"> <script>
<view import { pinyin } from 'pinyin-pro'
class="temp-list-item" import { addAppProject, updateAppProject, checkCanDelete } from '../../common/api/project'
:class="{ import { getTopoTemplate } from '../../common/api/device'
'temp-list-item-active': formData.tempFiles.some( import { queryEngineering } from '@/common/api/engineering.js'
(item2) => item2.id === item.id || item2.topoId === item.id,
), export default {
}" data() {
v-for="(item, index) in tempList" return {
@click="chooseTempItem(item)" loading: false,
> formData: {
<image class="temp-list-item-img" :src="item.filePath" mode="aspectFill"/> engineeringId: '',
<view class="temp-list-item-name">{{ item.name }}</view> engineeringName: '',
</view> area: '',
</view> files: [],
</uni-popup> tempFiles: [],
</view> topoIds: [],
</view> description: '',
</Cn-page> name: '',
</template> lat: '',
<script> lng: '',
import {pinyin} from 'pinyin-pro' },
import {addAppProject, updateAppProject, checkCanDelete} from '../../common/api/project' tempList: [],
import {getTopoTemplate} from '../../common/api/device' project: null,
import {queryEngineering} from '@/common/api/engineering.js' options: {}
}
export default { },
data() { onShow() {
return { if (!this.options.project) {
loading: false, let engineering = uni.getStorageSync('onceSelectEngineering')
formData: { if (engineering) {
engineeringId: '', uni.removeStorageSync('onceSelectEngineering')
engineeringName: '', this.formData.engineeringId = engineering.id
area: '', this.formData.engineeringName = engineering.name
files: [], }
tempFiles: [], }
topoIds: [], },
description: '', onLoad(options) {
name: '', this.options = options
lat: '', if (options.project) {
lng: '', uni.setNavigationBarTitle({
}, title: '编辑项目',
tempList: [], })
project: null, this.project = JSON.parse(decodeURIComponent(options.project))
options: {} console.log(this.project)
} for (let key in this.formData) {
}, if (this.project[key]) {
onShow() { this.formData[key] = this.project[key]
if (!this.options.project) { }
let engineering = uni.getStorageSync('onceSelectEngineering') }
if (engineering) { } else {
uni.removeStorageSync('onceSelectEngineering') let engineering = uni.getStorageSync('engineering')
this.formData.engineeringId = engineering.id this.formData.engineeringId = engineering.id
this.formData.engineeringName = engineering.name this.formData.engineeringName = engineering.name
} }
}
}, getTopoTemplate().then((res) => {
onLoad(options) { console.log(res)
this.options = options this.tempList = res.data.map((item) => {
if (options.project) { return {
uni.setNavigationBarTitle({ ...item,
title: '编辑项目', filePath: this.$config.static + item.filePath
}) }
this.project = JSON.parse(decodeURIComponent(options.project)) })
console.log(this.project) if (this.project) {
for (let key in this.formData) { this.project.topologyDiagramPaths.forEach((item) => {
if (this.project[key]) { if (this.tempList.some((item2) => item2.id === item.topoId)) {
this.formData[key] = this.project[key] this.formData.tempFiles.push(item)
} } else {
} this.formData.files.push({
} else { url: item.filePath,
let engineering = uni.getStorageSync('engineering') extname: item.name.split('.')[1],
this.formData.engineeringId = engineering.id name: item.name,
this.formData.engineeringName = engineering.name ...item,
} })
uni.getLocation({ }
type: 'wgs84', })
success: function (res) { }
console.log(res) })
console.log('当前位置的经度:' + res.longitude) },
console.log('当前位置的纬度:' + res.latitude) methods: {
}, selectEngineering() {
}) console.log(123)
getTopoTemplate().then((res) => { if (this.options.project) return this.$util.toast('项目已经创建,不能修改工程')
console.log(res) uni.navigateTo({
this.tempList = res.data.map((item) => { url: '/pages/home/selectEngineering?from=once',
return { })
...item, },
filePath:this.$config.static + item.filePath beforeRemove(e) {
} console.log(e)
}) if (!e.tempFile.id) {
if (this.project) { return true
this.project.topologyDiagramPaths.forEach((item) => { }
if (this.tempList.some((item2) => item2.id === item.topoId)) { return new Promise((resolve, reject) => {
this.formData.tempFiles.push(item) checkCanDelete(e.tempFile.id).then((res) => {
} else { console.log(res)
this.formData.files.push({ if (res.data) {
url: item.filePath, resolve(true)
extname: item.name.split('.')[1], } else {
name: item.name, reject()
...item, }
}) })
} })
}) },
} async deleteImg(index) {
}) await this.beforeRemove({
}, tempFile: this.formData.tempFiles[index],
methods: { })
selectEngineering() { this.formData.tempFiles.splice(index, 1)
console.log(123) },
if (this.options.project) return this.$util.toast('项目已经创建,不能修改工程') async chooseTempItem(item) {
uni.navigateTo({ console.log(item)
url: '/pages/home/selectEngineering?from=once', console.log(this.formData.tempFiles)
}) // 编辑的时候如果已经存在就要验证topoId
}, let index = this.formData.tempFiles.findIndex((item2) => item2.id === item.id || item2.topoId === item.id)
beforeRemove(e) { if (index > -1) {
console.log(e) await this.beforeRemove({
if (!e.tempFile.id) { tempFile: this.formData.tempFiles[index],
return true })
} this.formData.tempFiles.splice(index, 1)
return new Promise((resolve, reject) => { } else {
checkCanDelete(e.tempFile.id).then((res) => { this.formData.tempFiles.push(item)
console.log(res) }
if (res.data) { },
resolve(true) closeTemp() {
} else { this.$refs.showTemp.close()
reject() },
} openTemp() {
}) this.$refs.showTemp.open()
}) },
}, select(e) {
async deleteImg(index) { console.log(e)
await this.beforeRemove({ this.formData.files.push(...e.tempFiles)
tempFile: this.formData.tempFiles[index], console.log(this.formData.files)
}) },
this.formData.tempFiles.splice(index, 1) // chooseLocation() {
}, // uni.chooseLocation({
async chooseTempItem(item) { // success: (res) => {
console.log(item) // this.formData.area = res.name
console.log(this.formData.tempFiles) // this.formData.lat = res.latitudeame
// 编辑的时候如果已经存在就要验证topoId // this.formData.lng = res.longitude
let index = this.formData.tempFiles.findIndex((item2) => item2.id === item.id || item2.topoId === item.id) // console.log('位置名称:' + res.name)
if (index > -1) { // console.log('详细地址:' + res.address)
await this.beforeRemove({ // console.log('纬度:' + res.latitude)
tempFile: this.formData.tempFiles[index], // console.log('经度:' + res.longitude)
}) // },
this.formData.tempFiles.splice(index, 1) // })
} else { // },
this.formData.tempFiles.push(item) async submit() {
} console.log(this.formData)
}, if (!this.formData.name) {
closeTemp() { this.$util.toast('请输入项目名称')
this.$refs.showTemp.close() return
}, }
openTemp() { if (!this.formData.area) {
this.$refs.showTemp.open() this.$util.toast('请输入区域信息')
}, return
select(e) { }
console.log(e) if (!this.formData.description) {
this.formData.files.push(...e.tempFiles) this.$util.toast('请输入项目描述')
console.log(this.formData.files) return
}, }
// chooseLocation() { if (!this.formData.files.length && !this.formData.tempFiles.length) {
// uni.chooseLocation({ this.$util.toast('请至少选择一张拓扑图')
// success: (res) => { return
// this.formData.area = res.name }
// this.formData.lat = res.latitudeame let arr = []
// this.formData.lng = res.longitude for (let i = 0; i < this.formData.files.length; i++) {
// console.log('位置名称:' + res.name) let item = this.formData.files[i]
// console.log('详细地址:' + res.address) console.log(item)
// console.log('纬度:' + res.latitude) arr.push({
// console.log('经度:' + res.longitude) ...item,
// }, name: 'files',
// }) uri: item.url,
// }, })
async submit() { }
console.log(this.formData) console.log(arr)
if (!this.formData.name) { this.formData.topoIds = this.formData.tempFiles.map((item) => (item.id))
this.$util.toast('请输入项目名称') let data = JSON.parse(JSON.stringify(this.formData))
return let res = {}
} console.warn(data, arr)
if (!this.formData.area) { if (this.project) {
this.$util.toast('请输入区域信息') data.id = this.project.id
return data.newTopoIds = data.files.filter(item => item.id).map((item) => item.id)
} data.newTopoIds.push(...data.tempFiles.filter(item => item.id && item.topoId).map((item) => item.id))
if (!this.formData.description) { data.topoIds = data.tempFiles.filter(item => item.id && !item.topoId).map((item) => item.id)
this.$util.toast('请输入项目描述') delete data.tempFiles
return delete data.files
} arr = arr.filter(item => !item.id)
if (!this.formData.files.length && !this.formData.tempFiles.length) { res = await updateAppProject(data, arr)
this.$util.toast('请至少选择一张拓扑图') } else {
return delete data.tempFiles
} delete data.files
let arr = [] res = await addAppProject(data, arr)
for (let i = 0; i < this.formData.files.length; i++) { }
let item = this.formData.files[i] let result = {}
console.log(item) if (res.code === 'A0000') {
arr.push({ result = res
...item, } else {
name: 'files', console.warn(res)
uri: item.url, if (res.length === 1) {
}) this.$util.toast(res[0].message)
} return
console.log(arr) }
this.formData.topoIds = this.formData.tempFiles.map((item) => (item.id)) result = JSON.parse(res[1].data)
let data = JSON.parse(JSON.stringify(this.formData)) }
let res = {} if (result.code === 'A0000') {
console.warn(data, arr) if (this.project) {
if (this.project) { this.$util.toast('项目修改成功')
data.id = this.project.id this.$util.refreshPrePage(2)
data.newTopoIds = data.files.filter(item => item.id).map((item) => item.id) } else {
data.newTopoIds.push(...data.tempFiles.filter(item => item.id && item.topoId).map((item) => item.id)) if (this.options.from === 'newDevice') {
data.topoIds = data.tempFiles.filter(item => item.id && !item.topoId).map((item) => item.id) uni.navigateBack()
delete data.tempFiles } else {
delete data.files this.$util.toast('项目创建成功')
arr = arr.filter(item => !item.id) this.$util.refreshPrePage()
res = await updateAppProject(data, arr) }
} else { }
delete data.tempFiles } else {
delete data.files this.$util.toast(result.message)
res = await addAppProject(data, arr) }
} },
let result = {} },
if (res.code === 'A0000') { }
result = res </script>
} else { <style lang="scss" scoped>
console.warn(res) .project-new /deep/ .is-disabled {
if (res.length === 1) { background: #fff !important;
this.$util.toast(res[0].message) color: #111;
return }
}
result = JSON.parse(res[1].data) .engineering-select {
} width: 100%;
if (result.code === 'A0000') {
if (this.project) { /deep/ .uni-easyinput,
this.$util.toast('项目修改成功') /deep/ .uni-easyinput__content {
this.$util.refreshPrePage(2) pointer-events: none;
} else { }
if (this.options.from === 'newDevice') { }
uni.navigateBack()
} else { .new {
this.$util.toast('项目创建成功') padding: 34rpx;
this.$util.refreshPrePage()
} .project-new {}
}
} else { .content {
this.$util.toast(result.message) .content-des {
} font-size: 28rpx;
}, color: #666;
}, margin-bottom: 20rpx;
} }
</script>
<style lang="scss" scoped> margin-bottom: 20rpx;
.project-new /deep/ .is-disabled { padding: 34rpx;
background: #fff !important; background: $uni-theme-white;
color: #111; border-radius: 12rpx;
} }
.new { .btn-wrap {
padding: 34rpx; margin-top: 40rpx;
display: flex;
.project-new { align-items: center;
justify-content: space-between;
}
.btn-wrap-item {
.content { display: flex;
.content-des { align-items: center;
font-size: 28rpx; justify-content: center;
color: #666; flex: 1;
margin-bottom: 20rpx; background: $uni-theme-color;
} color: #fff;
height: 80rpx;
margin-bottom: 20rpx; border-radius: 12rpx;
padding: 34rpx; }
background: $uni-theme-white; }
border-radius: 12rpx;
} .temp-choose {
margin-bottom: 44rpx;
.btn-wrap {
margin-top: 40rpx; .temp-choose-title {
display: flex; font-size: 14px;
align-items: center; color: #333;
justify-content: space-between; }
.btn-wrap-item { .temp-choose-content {
display: flex; margin-top: 20rpx;
align-items: center; display: grid;
justify-content: center; grid-template-columns: repeat(3, 198rpx);
flex: 1; grid-gap: 10rpx;
background: $uni-theme-color;
color: #fff; .temp-choose-content-item {
height: 80rpx; box-sizing: border-box;
border-radius: 12rpx; border: 1px #eee solid;
} position: relative;
} display: flex;
align-items: center;
.temp-choose { justify-content: center;
margin-bottom: 44rpx; height: 198rpx;
.temp-choose-title { .temp-choose-content-item-img {
font-size: 14px; height: 100%;
color: #333; width: 100%;
} background: skyblue;
display: block;
.temp-choose-content { }
margin-top: 20rpx;
display: grid; .temp-choose-content-item-close {
grid-template-columns: repeat(3, 198rpx); display: flex;
grid-gap: 10rpx; align-items: center;
justify-content: center;
.temp-choose-content-item { position: absolute;
box-sizing: border-box; top: 3px;
border: 1px #eee solid; right: 3px;
position: relative; border-radius: 50%;
display: flex; background-color: rgba(0, 0, 0, 0.5);
align-items: center; z-index: 2;
justify-content: center; height: 52rpx;
height: 198rpx; width: 52rpx;
font-size: 24rpx;
.temp-choose-content-item-img { color: #666;
height: 100%; }
width: 100%; }
background: skyblue; }
display: block; }
}
.temp-list {
.temp-choose-content-item-close { box-sizing: border-box;
display: flex; width: 750rpx;
align-items: center; height: 80vh;
justify-content: center; padding: 20rpx;
position: absolute; overflow-y: scroll;
top: 3px; background: #fff;
right: 3px;
border-radius: 50%; .temp-list-item {
background-color: rgba(0, 0, 0, 0.5); margin-bottom: 10rpx;
z-index: 2; position: relative;
height: 52rpx; box-sizing: border-box;
width: 52rpx; border: 4px solid #f1f1f1;
font-size: 24rpx;
color: #666; .temp-list-item-img {
} height: 280rpx;
} width: 100%;
} }
}
.temp-list-item-name {
.temp-list { position: absolute;
box-sizing: border-box; right: 0;
width: 750rpx; top: 0;
height: 80vh; background: #fff;
padding: 20rpx; padding: 4rpx 8rpx;
overflow-y: scroll; }
background: #fff;
&-active {
.temp-list-item { border: 4rpx solid $uni-theme-color;
margin-bottom: 10rpx; }
position: relative; }
box-sizing: border-box; }
border: 4px solid #f1f1f1; }
.temp-list-item-img { /deep/ .uni-drawer__content {
height: 280rpx; width: 100vw !important;
width: 100%; }
} </style>
.temp-list-item-name {
position: absolute;
right: 0;
top: 0;
background: #fff;
padding: 4rpx 8rpx;
}
&-active {
border: 4rpx solid $uni-theme-color;
}
}
}
}
/deep/ .uni-drawer__content {
width: 100vw !important;
}
</style>

View File

@@ -3,7 +3,7 @@
<view slot="body"> <view slot="body">
<view class="change-name"> <view class="change-name">
<view class="content"> <view class="content">
<uni-easyinput type="text" v-model="name" placeholder="请输入昵称" /> <uni-easyinput type="text" maxlength="24" v-model="name" placeholder="请输入昵称" />
</view> </view>
<view class="btn-wrap"> <view class="btn-wrap">
<view class="btn-wrap-item" @click="submit"> 提交 </view> <view class="btn-wrap-item" @click="submit"> 提交 </view>

View File

@@ -4,33 +4,18 @@
<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 type="number" maxlength="11" v-model="formData.phone" placeholder="请输入手机号" />
type="number"
maxlength="11"
v-model="formData.phone"
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 <uni-easyinput type="text" v-model="formData.code" placeholder="请输入验证码" maxlength="6" />
type="text" <view class="ml40" style="
v-model="formData.code"
placeholder="请输入验证码"
maxlength="6"
/>
<view
class="ml40"
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">{{ waitTime + 's后重新获取' }}</view>
v-if="waitTime > 0"
>{{ 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>
@@ -41,7 +26,8 @@
<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" :loading="loadingButton" :disabled="loadingButton"
@click="submit">提交</button>
<view class="login-box-tips"> <view class="login-box-tips">
<view style="color: #999">说明密码长度为6-18</view> <view style="color: #999">说明密码长度为6-18</view>
</view> </view>
@@ -71,6 +57,7 @@ export default {
password: '', password: '',
password2: '', password2: '',
}, },
loadingButton: false,
rules: { rules: {
phone: { phone: {
rules: [ rules: [
@@ -107,7 +94,7 @@ export default {
}, },
} }
}, },
onLoad() {}, onLoad() { },
methods: { methods: {
getCode() { getCode() {
if (!this.formData.phone) { if (!this.formData.phone) {
@@ -151,6 +138,7 @@ export default {
}) })
return return
} }
this.loadingButton = true
let loginName = encrypt(this.formData.phone) let loginName = encrypt(this.formData.phone)
gongkey({ loginName }).then((response) => { gongkey({ loginName }).then((response) => {
let publicKey = response.data let publicKey = response.data
@@ -169,9 +157,13 @@ export default {
}, 1000) }, 1000)
}) })
.catch((err) => { .catch((err) => {
uni.hideLoading()
console.log(err) console.log(err)
}) })
.finally(() => {
this.loadingButton = false
})
}).finally(() => {
this.loadingButton = false
}) })
}) })
}, },

View File

@@ -5,32 +5,18 @@
<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 type="number" v-model="formData.phone" maxlength="11" placeholder="请输入手机号" />
type="number"
v-model="formData.phone"
maxlength="11"
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 <uni-easyinput type="text" v-model="formData.code" placeholder="请输入验证码" maxlength="6" />
type="text" <view class="ml40" style="
v-model="formData.code"
placeholder="请输入验证码"
maxlength="6"
/>
<view
class="ml40"
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">{{ waitTime + 's后重新获取' }}
v-if="waitTime > 0"
>{{ waitTime + 's后重新获取' }}
</view> </view>
<button class="login-box-input-btn" v-else @click="getCode" size="mini"> <button class="login-box-input-btn" v-else @click="getCode" size="mini">
获取验证码 获取验证码
@@ -38,16 +24,13 @@
</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" :loading="loadingButton" :disabled="loadingButton"
@click="firstSubmit">注册</button>
<view class="login-box-tips"> <view class="login-box-tips">
<view style="color: #999" <view style="color: #999">
><checkbox <checkbox style="transform: scale(0.7)" :checked="checkbox" @click="checkbox = !checkbox" />
style="transform: scale(0.7)" 我已阅读并同意
:checked="checkbox" </view>
@click="checkbox = !checkbox"
/>
我已阅读并同意</view
>
<navigator url="/pages/mine/agreement" hover-class="none">用户协议</navigator> <navigator url="/pages/mine/agreement" hover-class="none">用户协议</navigator>
<navigator url="/pages/mine/policy" hover-class="none">隐私政策</navigator> <navigator url="/pages/mine/policy" hover-class="none">隐私政策</navigator>
</view> </view>
@@ -61,7 +44,8 @@
<uni-easyinput type="text" v-model="formData.password2" placeholder="请再次确认密码" /> <uni-easyinput type="text" v-model="formData.password2" placeholder="请再次确认密码" />
</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" :loading="loadingButton" :disabled="loadingButton"
@click="secondSubmit">提交</button>
<view class="login-box-tips"> <view class="login-box-tips">
<view style="color: #999">说明密码长度为6-18</view> <view style="color: #999">说明密码长度为6-18</view>
</view> </view>
@@ -82,6 +66,7 @@ export default {
loading: false, loading: false,
waitTime: 0, waitTime: 0,
inter: null, inter: null,
loadingButton: false,
// 表单数据 // 表单数据
formData: { formData: {
phone: '', phone: '',
@@ -125,7 +110,7 @@ export default {
}, },
} }
}, },
onLoad() {}, onLoad() { },
methods: { methods: {
getCode() { getCode() {
if (!this.checkbox) { if (!this.checkbox) {
@@ -163,7 +148,9 @@ export default {
if (!this.checkbox) { if (!this.checkbox) {
return this.$util.toast('请先阅读并同意用户协议和隐私政策!') return this.$util.toast('请先阅读并同意用户协议和隐私政策!')
} }
this.$refs.form.validate().then((valid, errors) => { this.$refs.form.validate().then((valid, errors) => {
this.loadingButton = true
apiRegister({ apiRegister({
phone: this.formData.phone, phone: this.formData.phone,
code: this.formData.code, code: this.formData.code,
@@ -176,11 +163,14 @@ export default {
autoLogin(this.formData.phone).then((res) => { autoLogin(this.formData.phone).then((res) => {
this.$util.loginSuccess(res.data) this.$util.loginSuccess(res.data)
}) })
}).finally(() => {
this.loadingButton = false
}) })
}) })
}, },
secondSubmit() { secondSubmit() {
this.$refs.form.validate().then((valid, errors) => { this.$refs.form.validate().then((valid, errors) => {
this.loadingButton = true
console.log(this.formData.password.length) console.log(this.formData.password.length)
if (this.formData.password.length < 6 || this.formData.password.length > 18) { if (this.formData.password.length < 6 || this.formData.password.length > 18) {
return this.$util.toast('密码长度为6-18位') return this.$util.toast('密码长度为6-18位')
@@ -197,6 +187,8 @@ export default {
uni.reLaunch({ uni.reLaunch({
url: '/pages/user/login', url: '/pages/user/login',
}) })
}).finally(() => {
this.loadingButton = false
}) })
}) })
}, },

Binary file not shown.

BIN
static/user_manual1.docx Normal file

Binary file not shown.

View File

@@ -221,4 +221,4 @@ function chooseAndUploadFile(opts = {
export { export {
chooseAndUploadFile, chooseAndUploadFile,
uploadCloudFiles uploadCloudFiles
}; };

View File

@@ -35,7 +35,7 @@
@delFile="delFile" @delFile="delFile"
> >
<slot><button type="primary" size="mini">选择文件</button></slot> <slot><button type="primary" size="mini">选择文件</button></slot>
</upload-file> </upload-file>
</view> </view>
</template> </template>
@@ -354,7 +354,7 @@ export default {
icon: 'none', icon: 'none',
}) })
return return
} }
this.chooseFiles(type) this.chooseFiles(type)
}, },
@@ -363,13 +363,13 @@ export default {
* 选择文件并上传 * 选择文件并上传
*/ */
chooseFiles(type) { chooseFiles(type) {
const _extname = get_extname(this.fileExtname) const _extname = get_extname(this.fileExtname)
// 获取后缀 // 获取后缀
uniCloud uniCloud
.chooseAndUploadFile({ .chooseAndUploadFile({
type: this.fileMediatype, type: this.fileMediatype,
compressed: false, compressed: false,
sourceType: [type],//type? :this.sourceType , sourceType: [type],//type? :this.sourceType ,
sizeType: this.sizeType, sizeType: this.sizeType,
// TODO 如果为空video 有问题 // TODO 如果为空video 有问题
@@ -380,12 +380,13 @@ export default {
this.setProgress(progressEvent, progressEvent.index) this.setProgress(progressEvent, progressEvent.index)
}, },
}) })
.then((result) => { .then((result) => {
console.log('选择失败', result) if (this.autoUpload && !this.noSpace) {
this.setSuccessAndError(result.tempFiles) this.setSuccessAndError(result.tempFiles)
}
}) })
.catch((err) => { .catch((err) => {
console.log('选择失败', err) console.log('选择文件失败', err)
}) })
}, },

View File

@@ -1,109 +1,109 @@
/** /**
* 获取文件名和后缀 * 获取文件名和后缀
* @param {String} name * @param {String} name
*/ */
export const get_file_ext = (name) => { export const get_file_ext = (name) => {
const last_len = name.lastIndexOf('.') const last_len = name.lastIndexOf('.')
const len = name.length const len = name.length
return { return {
name: name.substring(0, last_len), name: name.substring(0, last_len),
ext: name.substring(last_len + 1, len) ext: name.substring(last_len + 1, len)
} }
} }
/** /**
* 获取扩展名 * 获取扩展名
* @param {Array} fileExtname * @param {Array} fileExtname
*/ */
export const get_extname = (fileExtname) => { export const get_extname = (fileExtname) => {
if (!Array.isArray(fileExtname)) { if (!Array.isArray(fileExtname)) {
let extname = fileExtname.replace(/(\[|\])/g, '') let extname = fileExtname.replace(/(\[|\])/g, '')
return extname.split(',') return extname.split(',')
} else { } else {
return fileExtname return fileExtname
} }
return [] return []
} }
/** /**
* 获取文件和检测是否可选 * 获取文件和检测是否可选
*/ */
export const get_files_and_is_max = (res, _extname) => { export const get_files_and_is_max = (res, _extname) => {
let filePaths = [] let filePaths = []
let files = [] let files = []
if(!_extname || _extname.length === 0){ if(!_extname || _extname.length === 0){
return { return {
filePaths, filePaths,
files files
} }
} }
res.tempFiles.forEach(v => { res.tempFiles.forEach(v => {
let fileFullName = get_file_ext(v.name) let fileFullName = get_file_ext(v.name)
const extname = fileFullName.ext.toLowerCase() const extname = fileFullName.ext.toLowerCase()
if (_extname.indexOf(extname) !== -1) { if (_extname.indexOf(extname) !== -1) {
files.push(v) files.push(v)
filePaths.push(v.path) filePaths.push(v.path)
} }
}) })
if (files.length !== res.tempFiles.length) { if (files.length !== res.tempFiles.length) {
uni.showToast({ uni.showToast({
title: `当前选择了${res.tempFiles.length}个文件 ${res.tempFiles.length - files.length} 个文件格式不正确`, title: `当前选择了${res.tempFiles.length}个文件 ${res.tempFiles.length - files.length} 个文件格式不正确`,
icon: 'none', icon: 'none',
duration: 5000 duration: 5000
}) })
} }
return { return {
filePaths, filePaths,
files files
} }
} }
/** /**
* 获取图片信息 * 获取图片信息
* @param {Object} filepath * @param {Object} filepath
*/ */
export const get_file_info = (filepath) => { export const get_file_info = (filepath) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
uni.getImageInfo({ uni.getImageInfo({
src: filepath, src: filepath,
success(res) { success(res) {
resolve(res) resolve(res)
}, },
fail(err) { fail(err) {
reject(err) reject(err)
} }
}) })
}) })
} }
/** /**
* 获取封装数据 * 获取封装数据
*/ */
export const get_file_data = async (files, type = 'image') => { export const get_file_data = async (files, type = 'image') => {
// 最终需要上传数据库的数据 // 最终需要上传数据库的数据
let fileFullName = get_file_ext(files.name) let fileFullName = get_file_ext(files.name)
const extname = fileFullName.ext.toLowerCase() const extname = fileFullName.ext.toLowerCase()
let filedata = { let filedata = {
name: files.name, name: files.name,
uuid: files.uuid, uuid: files.uuid,
extname: extname || '', extname: extname || '',
cloudPath: files.cloudPath, cloudPath: files.cloudPath,
fileType: files.fileType, fileType: files.fileType,
url: files.path || files.path, url: files.path || files.path,
size: files.size, //单位是字节 size: files.size, //单位是字节
image: {}, image: {},
path: files.path, path: files.path,
video: {} video: {}
} }
if (type === 'image') { if (type === 'image') {
const imageinfo = await get_file_info(files.path) const imageinfo = await get_file_info(files.path)
delete filedata.video delete filedata.video
filedata.image.width = imageinfo.width filedata.image.width = imageinfo.width
filedata.image.height = imageinfo.height filedata.image.height = imageinfo.height
filedata.image.location = imageinfo.path filedata.image.location = imageinfo.path
} else { } else {
delete filedata.image delete filedata.image
} }
return filedata return filedata
} }