7 Commits

Author SHA1 Message Date
caozehui
4189eea278 默认模式为模拟式 2026-05-11 20:37:44 +08:00
caozehui
d3fef49af2 微调 2026-05-11 20:17:11 +08:00
caozehui
12d40a5c6e 打包 2026-05-09 09:53:10 +08:00
caozehui
6748490c3f 隐藏非必要的页面 2026-05-09 08:43:33 +08:00
caozehui
2c19fc43de 微调 2026-05-08 13:16:19 +08:00
caozehui
2ba5ebaddb Merge remote-tracking branch 'origin/hainan' into hainan
# Conflicts:
#	frontend/src/views/machine/freqConverter/components/freqConverterDipChart.vue
2026-05-08 11:36:53 +08:00
caozehui
448687115c 实施测试特性曲线与结果展示特性曲线不一致问题 2026-05-08 11:32:45 +08:00
82 changed files with 155 additions and 180 deletions

View File

@@ -115,4 +115,10 @@ activate:
private-key: "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCcUyYhVqczGxblL+o/xZzF/8nf+LjrfUE/dS1aRHM7uMDD0cgCArhjtfneFePrMxt+Z7W8yNBzSarub8qsfhaVNikV7Es7oaeTygfjQXTi2n4AFkir3fM07J08RpWhl5M8f8uWTCuvFUYAw00gq55typqmnbkmJa2VIUy/iQf+cMCP7abz4/jNhUzUR3qA7TV4oMRgTdIEDUp63YF8dOC+JH8XxYrCVeHXV6fLCwmesdMzl0lB2VTEKMfLbXhOmF5g7P9y/16VCcN8UBuZlbyYfn+GAxJOSbeHi5HshOKfoSuD7Jz+3WQZpNavOWjIFExKIU38/CvnJCOP7XBCqpSTAgMBAAECggEAYeWokWRE3TpvwiOZnUpR/aVMdVi75a3ROL5XIpqPV61B+t/bU3cEpl0GF9C5pUeiRi0IoStZb3mI9D1KPW/REKyUWkhabQO1gFYbTnRlkNOn6MILzKX4cwJjDaZeeo4EBPU7N+qHyOOXrU6hdH5FfxhMdV983ajm5eeuupxER1C2kAcIklTeVpTX6EKOgZb5LBp5ssOVm2P42pOauvcRozRcvZmqnErXmukv0H4l3EVNt4rHpTn9riHUC63e8JfiYzVaF6zuNUxv6nHEft0/SRMw11XSTnNfDzcKqgjz6ksFBS/6eQQYKESk+ONC53HUuYHFAknkwsPupDCT2W8FIQKBgQDLHT/xCU3nxGr4vFKBDNaO2D5oK20ECbBO4oDvLWWmQG7f+6TsMy8PgVdMnoL4RfqGlwFAKEpS6KVFHnBVqnNEhcdy9uCI7x7Xx8UnyUtxj1EDTm76uta9Ki9OrlqB6tImDM9+Ya3vGktW37ht4WOx2OsJRhG1dbf6RLwFlH7DWwKBgQDFBxvi5I1BR6hg6Tj7xd2SqOT2Y+BED3xuSYENhWbmMhLJDResaB7mjztbxlYaY2mOE0holWm2uDmVFFhMh4jYXik4hYH8nmDzq9mDpZCZ9pyjYqnAP8THoAa8EbgrUWB8A6BPH4iL3KbMnBfBKY0pIr2xrvnjQjNBAgta7KDRKQKBgCe6oe4wxrdF2TKsC2tIqpMoQxS3Icy/ZGgZr+SYuaBKTCWtoDW/UT40K3JGMxIDBhzbXphBCUCsVt9tM8Xd4EwP6tJW7dZ7B0pnve2pVwNwaAVAiz6p2yUHIle+jN+Koe5lZRSwYIg7WW81tWpwwsJfzqFyvjYDP6hJV4mz4ROvAoGAaRcdnKvjXApomShMqJ4lTPChD3q+SA8qg3jZSOj6tZXHx00gb2kp8jg7pPvpOTIFPy6x1Ha9aCRjMk0ju84fA6lVuzwa1S907wOehUVuF3Eeo1cgy9Y3k3KbpPyeixxgpkUY4JslLdSHc2NemD0dee951qhJyRmqVOZOQDUuoeECgYEAqBw2cAFk3vM97WY06TSldGA8ajVHx3BYRjj+zl62NTQthy8fw3tqxb3c5e8toOmZWKjZvDhg2TRLhsDDQWEYg3LZG87REqVIjgEPcpjNLidjygGX8n3JF2o0O5I/EMvl0s/+LVQONfduOBvhwDqr8QNisbLsyneiAq7umewMolo="
public-key: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnFMmIVanMxsW5S/qP8Wcxf/J3/i4631BP3UtWkRzO7jAw9HIAgK4Y7X53hXj6zMbfme1vMjQc0mq7m/KrH4WlTYpFexLO6Gnk8oH40F04tp+ABZIq93zNOydPEaVoZeTPH/LlkwrrxVGAMNNIKuebcqapp25JiWtlSFMv4kH/nDAj+2m8+P4zYVM1Ed6gO01eKDEYE3SBA1Ket2BfHTgviR/F8WKwlXh11enywsJnrHTM5dJQdlUxCjHy214TpheYOz/cv9elQnDfFAbmZW8mH5/hgMSTkm3h4uR7ITin6Erg+yc/t1kGaTWrzloyBRMSiFN/Pwr5yQjj+1wQqqUkwIDAQAB"
freq-converter:
schedule-period: 200 #定时器运行间隔
tolerant: 1 #耐受状态
dt: 200 #延迟时间ms
direction: 0 #0为横向1为纵向
allow-error-duration: 6 #暂态持续时间允许最大误差ms
allow-error-residual-voltage: 2.0 #暂态幅值允许最多误差%

View File

@@ -1 +1 @@
11900
42428

Binary file not shown.

View File

@@ -1,13 +1,3 @@
.\binlog.000023
.\binlog.000024
.\binlog.000025
.\binlog.000026
.\binlog.000027
.\binlog.000028
.\binlog.000029
.\binlog.000030
.\binlog.000031
.\binlog.000032
.\binlog.000033
.\binlog.000034
.\binlog.000035
.\binlog.000036

View File

@@ -1,28 +1,28 @@
<template>
<div class="footer flx-align-center pl10">
<el-dropdown>
<div class="change_mode">
{{ title }}
<el-icon class="el-icon--right change_mode_down"><arrow-down /></el-icon>
<el-icon class="el-icon--right change_mode_up"><arrow-up /></el-icon>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
v-for="item in modeList"
:key="item.key"
:disabled="!item.activated"
@click="handelOpen(item.code, item.key)"
>
{{ item.name }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<p style="margin: 0">
<a href="http://www.shining-electric.com/" target="_blank">2024 © 南京灿能电力自动化股份有限公司</a>
</p>
</div>
<div class="footer flx-align-center pl10">
<el-dropdown>
<div class="change_mode">
{{ title }}
<el-icon class="el-icon--right change_mode_down"><arrow-down /></el-icon>
<el-icon class="el-icon--right change_mode_up"><arrow-up /></el-icon>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
v-for="item in modeList"
:key="item.key"
:disabled="!item.activated"
@click="handelOpen(item.code, item.key)"
>
{{ item.name }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<p style="margin: 0">
<a href="http://www.shining-electric.com/" target="_blank">2024 © 南京灿能电力自动化股份有限公司</a>
</p>
</div>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
@@ -39,97 +39,97 @@ const modeStore = useModeStore()
const tabsStore = useTabsStore()
const title = computed(() => {
return modeStore.currentMode === '' ? '选择模块' : modeStore.currentMode + '模块'
return modeStore.currentMode === '' ? '选择模块' : modeStore.currentMode + '模块'
})
const activateInfo = authStore.activateInfo
const isActivateOpen = import.meta.env.VITE_ACTIVATE_OPEN
const modeList = [
{
name: '模拟式模块',
code: '模拟式',
key: 'simulate',
activated: isActivateOpen === 'true' ? activateInfo.simulate.permanently === 1 : true
},
{
name: '数字式模块',
code: '数字式',
key: 'digital',
activated: isActivateOpen === 'true' ? activateInfo.digital.permanently === 1 : true
},
{
name: '比对式模块',
code: '比对式',
key: 'contrast',
activated: isActivateOpen === 'true' ? activateInfo.contrast.permanently === 1 : true
}
{
name: '模拟式模块',
code: '模拟式',
key: 'simulate',
activated: isActivateOpen === 'true' ? activateInfo.simulate.permanently === 1 : true
},
{
name: '数字式模块',
code: '数字式',
key: 'digital',
activated: isActivateOpen === 'true' ? activateInfo.digital.permanently === 1 : true
},
{
name: '比对式模块',
code: '比对式',
key: 'contrast',
activated: isActivateOpen === 'true' ? activateInfo.contrast.permanently === 1 : true
}
]
const handelOpen = async (item: string, key: string) => {
if (isActivateOpen === 'true' && activateInfo[key].permanently !== 1) {
ElMessage.warning(`${item}模块未激活`)
return
}
await authStore.setShowMenu()
modeStore.setCurrentMode(item) // 将模式code存入 store
// 强制刷新页面
await tabsStore.closeMultipleTab()
await initDynamicRouter()
if (isActivateOpen === 'true' && activateInfo[key].permanently !== 1) {
ElMessage.warning(`${item}模块未激活`)
return
}
await authStore.setShowMenu()
modeStore.setCurrentMode(item) // 将模式code存入 store
// 强制刷新页面
await tabsStore.closeMultipleTab()
await initDynamicRouter()
// 只有当目标路径与当前路径不同时才跳转
if (router.currentRoute.value.path !== HOME_URL) {
await router.push({ path: HOME_URL })
} else {
// 如果已在目标页面,手动触发组件更新
window.location.reload() // 或者采用其他方式刷新数据
}
// 只有当目标路径与当前路径不同时才跳转
if (router.currentRoute.value.path !== HOME_URL) {
await router.push({ path: HOME_URL })
} else {
// 如果已在目标页面,手动触发组件更新
window.location.reload() // 或者采用其他方式刷新数据
}
}
</script>
<style scoped lang="scss">
@use './index.scss';
.footer {
position: relative;
background-color: var(--el-color-primary);
// .el-button:hover {
// background-color: var(--el-color-primary) !important;
// border: none !important;
// outline: none !important;
// }
.change_mode {
color: #fff;
display: flex;
align-items: center;
justify-content: flex-start;
height: 100%;
width: auto;
font-size: 14px;
.change_mode_down {
display: block;
}
.change_mode_up {
display: none;
}
position: relative;
background-color: var(--el-color-primary);
// .el-button:hover {
// background-color: var(--el-color-primary) !important;
// border: none !important;
// outline: none !important;
// }
.change_mode {
color: #fff;
display: flex;
align-items: center;
justify-content: flex-start;
height: 100%;
width: auto;
font-size: 14px;
.change_mode_down {
display: block;
}
.change_mode:hover {
.change_mode_down {
display: none;
}
.change_mode_up {
display: block;
}
.change_mode_up {
display: none;
}
.el-dropdown {
z-index: 1001;
}
.change_mode:hover {
.change_mode_down {
display: none;
}
p {
position: absolute;
width: 100%;
height: 100%;
text-align: right;
line-height: 40px;
a {
color: #fff;
margin-right: 25px; // 增加右边距
}
.change_mode_up {
display: block;
}
}
.el-dropdown {
z-index: 1001;
}
p {
position: absolute;
width: 100%;
height: 100%;
text-align: right;
line-height: 40px;
a {
color: #fff;
margin-right: 25px; // 增加右边距
}
}
}
</style>

View File

@@ -22,14 +22,6 @@
<el-icon><Edit /></el-icon>
{{ t('header.changePassword') }}
</el-dropdown-item>
<el-dropdown-item @click="changeMode" v-if="authStore.showMenuFlag">
<el-icon><Switch /></el-icon>
{{ t('header.changeMode') }}
</el-dropdown-item>
<el-dropdown-item @click="openDialog('versionRegisterRef')">
<el-icon><SetUp /></el-icon>
{{ t('header.versionRegister') }}
</el-dropdown-item>
<el-dropdown trigger="hover" placement="left-start" v-if="userStore.userInfo.loginName == 'root'">
<div class="custom-dropdown-trigger">
<el-icon><Tools /></el-icon>
@@ -62,24 +54,20 @@
<InfoDialog ref="infoRef"></InfoDialog>
<!-- passwordDialog -->
<PasswordDialog ref="passwordRef"></PasswordDialog>
<!-- versionRegisterDialog -->
<VersionDialog ref="versionRegisterRef"></VersionDialog>
<!-- ThemeDialog -->
<ThemeDialog ref="themeRef"></ThemeDialog>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
import { HOME_URL, LOGIN_URL } from '@/config'
import { LOGIN_URL } from '@/config'
import { useRouter } from 'vue-router'
import { useUserStore } from '@/stores/modules/user'
import { ElMessage, ElMessageBox } from 'element-plus'
import InfoDialog from './InfoDialog.vue'
import PasswordDialog from './PasswordDialog.vue'
import ThemeDialog from './ThemeDialog.vue'
import VersionDialog from '@/views/system/versionRegister/index.vue'
import { Avatar, Sunny, Switch, Tools } from '@element-plus/icons-vue'
import { useAuthStore } from '@/stores/modules/auth'
import { Avatar, Sunny, Tools } from '@element-plus/icons-vue'
import { useDictStore } from '@/stores/modules/dict'
import { useAppSceneStore } from '@/stores/modules/mode'
import { useI18n } from 'vue-i18n'
@@ -90,7 +78,6 @@ const dictStore = useDictStore()
const username = computed(() => userStore.userInfo.name)
const router = useRouter()
const authStore = useAuthStore()
// 初始化 i18n
const { t } = useI18n() // 使用 t 方法替代 $t
@@ -111,12 +98,10 @@ const logout = () => {
// 打开修改密码和个人信息弹窗
const infoRef = ref<InstanceType<typeof InfoDialog> | null>(null)
const passwordRef = ref<InstanceType<typeof PasswordDialog> | null>(null)
const versionRegisterRef = ref<InstanceType<typeof VersionDialog> | null>(null)
const themeRef = ref<InstanceType<typeof ThemeDialog> | null>(null)
const openDialog = (ref: string) => {
if (ref == 'infoRef') infoRef.value?.openDialog()
if (ref == 'passwordRef') passwordRef.value?.openDialog()
if (ref == 'versionRegisterRef') versionRegisterRef.value?.openDialog()
if (ref == 'themeRef') themeRef.value?.openDialog()
}
@@ -130,10 +115,6 @@ const changeScene = async (value: string) => {
}
//模式切换
const changeMode = async () => {
authStore.changeModel()
await router.push(HOME_URL)
}
</script>
<style scoped lang="scss">

View File

@@ -1,9 +1,11 @@
// src/stores/modules/mode.ts
import { defineStore } from 'pinia'
export const DEFAULT_MODE = '模拟式'
export const useModeStore = defineStore('mode', {
state: () => ({
currentMode: localStorage.getItem('currentMode') || ('' as string)
currentMode: localStorage.getItem('currentMode') || DEFAULT_MODE
}),
actions: {
setCurrentMode(modeName: string) {

View File

@@ -4,7 +4,7 @@ import piniaPersistConfig from '@/stores/helper/persist'
import { USER_STORE_KEY } from '@/stores/constant'
import { logoutApi } from '@/api/user/login'
import { useAuthStore } from '@/stores/modules/auth'
import { useAppSceneStore, useModeStore } from '@/stores/modules/mode'
import { DEFAULT_MODE, useAppSceneStore, useModeStore } from '@/stores/modules/mode'
import { useDictStore } from '@/stores/modules/dict'
export const useUserStore = defineStore(USER_STORE_KEY, {
@@ -48,7 +48,7 @@ export const useUserStore = defineStore(USER_STORE_KEY, {
this.setUserInfo({ id: '', name: '', loginName: '' })
this.setIsRefreshToken(false)
dictStore.setDictData([])
modeStore.setCurrentMode('')
modeStore.setCurrentMode(DEFAULT_MODE)
appSceneStore.setCurrentMode('')
await authStore.resetAuthStore()
}

View File

@@ -82,7 +82,6 @@ const CHARACTERISTIC_POINT_COLOR = '#ff4d4f'
const chartPoints = ref<ChartPoint[]>([])
const characteristicCurveData = ref<CharacteristicCurvePoint[]>([])
const drawnCharacteristicCurveData = ref<CharacteristicCurvePoint[]>([])
const characteristicCurveVisible = ref(false)
const chartRef = ref<any>(null)
@@ -127,8 +126,8 @@ const sortedChartPoints = computed(() => {
const sortedCharacteristicCurveData = computed(() => {
return [...characteristicCurveData.value].sort((a, b) => {
// 保留1位小数
let aResidualVoltage = Math.floor(a.residualVoltage * 10) / 10
let bResidualVoltage = Math.floor(b.residualVoltage * 10) / 10
let aResidualVoltage = Math.floor(a.residualVoltage)
let bResidualVoltage = Math.floor(b.residualVoltage)
if (aResidualVoltage != bResidualVoltage) {
return a.residualVoltage - b.residualVoltage;
} else {
@@ -152,35 +151,12 @@ const sortedCharacteristicCurveData = computed(() => {
})
})
const sortedDrawnCharacteristicCurveData = computed(() => {
return [...drawnCharacteristicCurveData.value].sort((a, b) => {
if (a.timeMs !== null && b.timeMs !== null && a.timeMs !== b.timeMs) {
return a.timeMs - b.timeMs
}
if (a.timeMs !== null && b.timeMs === null) {
return -1
}
if (a.timeMs === null && b.timeMs !== null) {
return 1
}
if (a.duration !== b.duration) {
return a.duration - b.duration
}
return a.residualVoltage - b.residualVoltage
})
})
const solidCharacteristicCurveSeriesData = computed(() => {
if (!characteristicCurveVisible.value) {
return [] as Array<[number, number, string]>
}
const curveSource = props.autoDrawCurve ? sortedCharacteristicCurveData.value : sortedDrawnCharacteristicCurveData.value
return curveSource.map(item => [item.duration, item.residualVoltage, '特性曲线'])
return sortedCharacteristicCurveData.value.map(item => [item.duration, item.residualVoltage, '特性曲线'])
})
const characteristicCurvePointSeriesData = computed(() => {
@@ -517,13 +493,11 @@ const updateCharacteristicCurveVisibility = () => {
const drawCharacteristicCurve = () => {
if (!sortedCharacteristicCurveData.value.length) {
drawnCharacteristicCurveData.value = []
characteristicCurveVisible.value = false
ElMessage.warning('暂无特性曲线点')
return
}
drawnCharacteristicCurveData.value = [...sortedCharacteristicCurveData.value]
characteristicCurveVisible.value = true
}
@@ -738,12 +712,11 @@ const chartOptions = computed(() => {
})
watch(
() => props.autoDrawCurve,
newValue => {
characteristicCurveVisible.value = newValue ? characteristicCurveData.value.length > 0 : false
drawnCharacteristicCurveData.value = newValue ? [...characteristicCurveData.value] : []
},
{immediate: true}
() => props.autoDrawCurve,
newValue => {
characteristicCurveVisible.value = newValue ? characteristicCurveData.value.length > 0 : false
},
{ immediate: true }
)
watch(
@@ -788,13 +761,12 @@ watch(
)
watch(
() => props.selectedMapping,
() => {
chartPoints.value = []
characteristicCurveData.value = []
drawnCharacteristicCurveData.value = []
characteristicCurveVisible.value = false
}
() => props.selectedMapping,
() => {
chartPoints.value = []
characteristicCurveData.value = []
characteristicCurveVisible.value = false
}
)
</script>

View File

@@ -123,6 +123,30 @@ const normalizeFormalRealPayload = (payload: any) => {
}
}
const extractResultArray = (payload: any) => {
if (Array.isArray(payload)) {
return payload
}
if (Array.isArray(payload?.data)) {
return payload.data
}
if (Array.isArray(payload?.data?.records)) {
return payload.data.records
}
if (Array.isArray(payload?.records)) {
return payload.records
}
if (Array.isArray(payload?.list)) {
return payload.list
}
return [] as any[]
}
const handleSocketMessage = (payload: any) => {
const requestId = `${payload?.requestId ?? ''}`
const normalizedRequestId = requestId.trim().toLowerCase()
@@ -289,7 +313,7 @@ const handleStart = async () => {
const historyResult = await getFreqConverterResult({
converterId: mapping.freqConverterId
})
historyResultData.value = historyResult?.data ?? historyResult
historyResultData.value = extractResultArray(historyResult?.data ?? historyResult)
} else {
historyResultData.value = null
}