29 Commits

Author SHA1 Message Date
caozehui
27b593ba01 微调 2026-06-02 11:21:55 +08:00
caozehui
8c7b164166 微调 2026-06-02 09:25:17 +08:00
caozehui
bdc45b8890 微调 2026-06-01 18:37:31 +08:00
caozehui
2705bedc71 微调 2026-06-01 14:12:47 +08:00
caozehui
ae970d048c 微调 2026-06-01 11:34:39 +08:00
caozehui
29f57c80ef 数据库调整 2026-06-01 11:25:37 +08:00
caozehui
80072bf7e0 资源管理前后端 2026-06-01 11:20:11 +08:00
caozehui
8d377dfed7 微调 2026-06-01 11:09:32 +08:00
caozehui
633b6ffd29 自动播放视频 2026-06-01 11:07:47 +08:00
caozehui
cf3141198b 微调 2026-06-01 09:26:01 +08:00
caozehui
c05d329614 补充观看教学视频路由跳转功能,检测页面微调 2026-05-29 10:39:12 +08:00
caozehui
ee08263e4a 检测计划统计弹窗下拉框内容调整 2026-05-29 09:58:24 +08:00
19ea08d5e0 feat(detection): 添加检测锁机制防止多用户同时操作
- 新增 detectionLock store 管理检测锁状态
- 实现检测锁相关的弹窗提示功能
- 添加 DETECTION_BUSY 错误码处理多人竞争逻辑
- 在 websocket 中集成检测锁超时处理
- 修改程序源控制接口以同步锁状态
- 更新项目标题和图标配置
- 添加 docs 目录到忽略列表
2026-05-28 20:44:53 +08:00
caozehui
f9809197e8 微调 2026-05-28 16:33:07 +08:00
caozehui
0090a922c6 资源管理页面微调 2026-05-28 14:37:40 +08:00
caozehui
0b26de20b9 资源管理 2026-05-28 13:26:35 +08:00
caozehui
1202f64bfc 检测计划统计功能 2026-05-28 08:44:15 +08:00
caozehui
ce1738daf0 微调 2026-05-27 11:20:12 +08:00
caozehui
a41d824ca3 归档 2026-05-26 15:45:08 +08:00
caozehui
ac5a8450e8 微调 2026-05-26 14:23:59 +08:00
caozehui
01e817a5d6 微调 2026-05-26 13:45:23 +08:00
caozehui
01bf07fc42 检测计划统计功能 2026-05-26 09:22:38 +08:00
caozehui
633e914c9a Revert "下拉多选报告模版"
This reverts commit 37e69e7bda.
2026-05-25 18:38:46 +08:00
caozehui
37e69e7bda 下拉多选报告模版 2026-05-25 14:25:57 +08:00
caozehui
19fb90432a 归档 2026-05-25 09:51:42 +08:00
caozehui
4a3c81a792 归档 2026-05-25 09:50:16 +08:00
caozehui
12d3073241 统一sourceId 2026-05-13 09:47:10 +08:00
caozehui
72838462ad 微调 2026-04-22 10:02:21 +08:00
caozehui
327addf625 微调 2026-04-22 09:58:03 +08:00
132 changed files with 2016 additions and 2712 deletions

1
.gitignore vendored
View File

@@ -9,3 +9,4 @@ public/electron/
pnpm-lock.yaml
CLAUDE.md
/public/dist/
/docs/

View File

@@ -33,9 +33,9 @@ mybatis-plus:
#驼峰命名
map-underscore-to-camel-case: true
#配置sql日志输出
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#关闭日志输出
# log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl
log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl
global-config:
db-config:
#指定主键生成策略
@@ -55,30 +55,32 @@ webSocket:
#源参数下发,暂态数据默认值
Dip:
#暂态前时间s
fPreTime: 2f
# 暂态前时间s
# fPreTime: 2f
#写入时间s
fRampIn: 0.001f
#写出时间s
fRampOut: 0.001f
#暂态后时间s
fAfterTime: 3f
# 暂态后时间s
# fAfterTime: 3f
Flicker:
waveFluType: CPM
waveType: SQU
fDutyCycle: 50f
#Flicker:
# waveFluType: CPM
# waveType: SQU
# fDutyCycle: 50f
log:
homeDir: {{APP_DATA_PATH}}\logs
commonLevel: info
#log:
# homeDir: D:\logs
# commonLevel: info
report:
template: {{APP_DATA_PATH}}\template
reportDir: {{APP_DATA_PATH}}\report
# template: D:\template
# reportDir: D:\report
dateFormat: yyyy年MM月dd日
data:
homeDir: {{APP_DATA_PATH}}\data
#data:
# homeDir: D:\data
#resource:
# videoDir: ${data.homeDir}\resources\videos
qr:
cloud: http://pqmcc.com:18082/api/file
dev:

View File

@@ -1 +1 @@
11900
116212

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -11,3 +11,8 @@
.\binlog.000033
.\binlog.000034
.\binlog.000035
.\binlog.000036
.\binlog.000037
.\binlog.000038
.\binlog.000039
.\binlog.000040

View File

@@ -42,7 +42,7 @@ function createTray() {
tray = new Tray(iconPath);
}
tray.setToolTip('变频器暂降耐受实验平台');
tray.setToolTip('NPQS-9100自动检测平台');
console.log('[Tray] Tray created successfully');
// 创建托盘菜单

View File

@@ -1,5 +1,5 @@
# title
VITE_GLOB_APP_TITLE=变频器暂降耐受实验平台
VITE_GLOB_APP_TITLE=NPQS-9100自动检测平台
# 本地运行端口号
VITE_PORT=18091

View File

@@ -23,5 +23,6 @@ VITE_PROXY=[["/api","http://127.0.0.1:18092/"]]
#VITE_PROXY=[["/api","http://192.168.1.124:18092/"]]
#VITE_PROXY=[["/api","http://192.168.2.125:18092/"]]
# VITE_PROXY=[["/api","http://192.168.1.138:8080/"]]张文
VITE_IS_SHOW_RAW_DATA=true
# 开启激活验证
VITE_ACTIVATE_OPEN=false
VITE_ACTIVATE_OPEN=false

View File

@@ -24,5 +24,6 @@ VITE_PWA=true
# 线上环境接口地址
#VITE_API_URL="/api" # 打包时用
VITE_API_URL="http://127.0.0.1:18092/"
VITE_IS_SHOW_RAW_DATA=true
# 开启激活验证
VITE_ACTIVATE_OPEN=false
VITE_ACTIVATE_OPEN=false

View File

@@ -4,7 +4,8 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, maximum-scale=1.0, minimum-scale=1.0" />
<title></title>
<link rel="icon" type="image/x-icon" href="/favicon.ico">
<title>NPQS-9100</title>
<!-- 优化vue渲染未完成之前先加一个css动画 -->
<style>
#loadingPage {

BIN
frontend/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -0,0 +1,15 @@
import http from '@/api'
import type { DetectionLockHolder } from '@/stores/modules/detectionLock'
/**
* 查询当前检测锁持有状态
* - data 为 null → 锁空闲
* - data 非 null → 锁被某账号持有
*
* 本接口只读,不抢锁、不会返回 DETECTION_BUSY
*/
export const getCurrentLock = () => {
return http.get<DetectionLockHolder | null>('/detection/lock/current', undefined, {
loading: false
})
}

View File

@@ -1,6 +1,7 @@
import type { controlSource } from '@/api/device/interface/controlSource'
import http from '@/api'
import { useDetectionLockStore } from '@/stores/modules/detectionLock'
/**
* @name 程控源管理模块
@@ -17,8 +18,11 @@ export const startSimulateTest = (params: controlSource.ResControl) => {
}
//停止
export const closeSimulateTest = (params: controlSource.ResControl) => {
return http.post(`/prepare/closeSimulateTest`,params,{loading:false})
export const closeSimulateTest = async (params: controlSource.ResControl) => {
const result = await http.post(`/prepare/closeSimulateTest`,params,{loading:false})
// 主动终止 → 释放本地持锁标记
useDetectionLockStore().clearHolder()
return result
}

View File

@@ -1,10 +1,6 @@
import type {Device} from '@/api/device/interface/device'
import http from '@/api'
export const getPqDevListAll = () => {
return http.get<Device.ResPqDev[]>(`/pqDev/listAll`)
}
/**
* @name 被检设备管理模块
*/

View File

@@ -1,52 +0,0 @@
import type {FreqConverter} from '@/api/device/interface/freqConverter'
import http from '@/api'
/**
* @name 变频器管理模块
*/
//获取设备类型
export const getFreqConverterList = (params: FreqConverter.ReqFreqConverterParams) => {
return http.post(`/freqConverter/list`, params)
}
//添加设备类型
export const addFreqConverter = (params: FreqConverter.ResFreqConverter) => {
return http.post(`/freqConverter/add`, params)
}
//编辑设备类型
export const updateFreqConverter = (params: FreqConverter.ResFreqConverter) => {
return http.post(`/freqConverter/update`, params)
}
//删除设备类型
export const deleteFreqConverter = (params: string[]) => {
return http.post(`/freqConverter/delete`, params)
}
export const getFreqConverterResult = (params: { converterId?: string }) => {
return http.get(`/freqConverter/result?converterId=${params.converterId || ''}`)
}
export const startFreqConverterDetect = (params: {
converterId?: string;
monitorId?: string;
userId?: string | null;
reset?: boolean;
}) => {
return http.get(`/prepare/startFreqConverter`, params, {loading: false})
}
export const stopFreqConverterDetect = (params: {
userId?: string | null;
}) => {
return http.get(`/prepare/stopFreqConverter`, params, {loading: false})
}
export const getFreqConverterSCurve = (params: FreqConverter.ReqFreqConverterSCurveParams) => {
return http.get(`/freqConverter/scurve?converterId=${params.converterId || ''}`)
}

View File

@@ -1,51 +0,0 @@
import type {ReqPage, ResPage} from '@/api/interface'
// 变频器模块
export namespace FreqConverter {
/**
* 变频器数据表格分页查询参数
*/
export interface ReqFreqConverterParams extends ReqPage {
name?: string; // 名称
}
/**
* 变频器新增、修改、根据id查询返回的对象
*/
export interface ResFreqConverter {
id?: string; //变频器ID
name: string;//变频器名称
portName: string; //串口名称
slaveAddress: number; //从机地址
baudRate: number; //波特率
parity: string; //奇偶校验类型
dataBits: number; //数据位
stopBits: number; //停止位
timeoutMs: number; //超时时间(毫秒)
suffix?: number; //数据表后缀
state?: number;
testStatus?: number; //测试状态 0未测试 1测试完成
createBy?: string | null; //创建用户
createTime?: string | null; //创建时间
updateBy?: string | null; //更新用户
updateTime?: string | null; //更新时间
}
/**
* 变频器表格查询分页返回的对象;
*/
export interface ResFreqConverterPage extends ResPage<ResFreqConverter> {
}
export interface ReqFreqConverterSCurveParams {
converterId?: string;
}
export interface ResTolerantPoint {
durationMs?: number | null;
residualVoltage?: number | null;
tolerant?: number | null;
}
}

View File

@@ -2,43 +2,44 @@ import type { ReqPage, ResPage } from '@/api/interface'
// 检测源模块
export namespace TestSource {
/**
* 检测脚本表格分页查询参数
*/
export interface ReqTestSourceParams extends ReqPage{
id: string; // 装置序号id 必填
name: string;
pattern: string;
}
/**
* 检测源表格分页查询参数
*/
export interface ReqTestSourceParams extends ReqPage {
id: string
name: string
pattern: string
}
// 检测源接口
export interface ResTestSource {
id: string; //检测源ID
name?: string; //检测源名称(检测源类型 + 设备类型 + 数字自动生成)
pattern: string;//检测源模式(字典表Code字段数字、模拟、比对)
type: string; //检测源类型(字典表Code字段标准源、高精度设备)
devType: string;//检测源设备类型(字典表Code字段)
parameter?: string;//源参数JSON字符串
state:number;//
createBy?: string;
createTime?: string;
updateBy?: string;
updateTime?: string;
id: string
name?: string
pattern: string
type: string
devType: string
maxVoltage?: number
maxCurrent?: number
parameter?: string
state: number
createBy?: string
createTime?: string
updateBy?: string
updateTime?: string
}
/* 检测脚本查询分页返回的对象;
*/
export interface ResTestSourcePage extends ResPage<ResTestSource> {
}
export interface ParameterType{
id:string;
type:string;
desc:string;
value:string|null;
sort:number;
pId:string;
children?:ParameterType[];
/*
* 检测源查询分页返回的对象
*/
export interface ResTestSourcePage extends ResPage<ResTestSource> {}
export interface ParameterType {
id: string
type: string
desc: string
value: string | null
sort: number
pId: string
children?: ParameterType[]
}
}
}

View File

@@ -12,6 +12,12 @@ import { type ResultData } from '@/api/interface'
import { ResultEnum } from '@/enums/httpEnum'
import { checkStatus } from './helper/checkStatus'
import { useUserStore } from '@/stores/modules/user'
import { useDetectionLockStore, type DetectionLockHolder } from '@/stores/modules/detectionLock'
import {
showForceReleasedDialog,
showLockBusyDialog,
showLockNotStartedToast
} from '@/utils/detectionLockDialog'
import router from '@/routers'
import { refreshToken } from '@/api/user/login'
import { EventSourcePolyfill } from 'event-source-polyfill'
@@ -107,6 +113,32 @@ class RequestHttp {
}
return Promise.reject(data)
}
// 单用户检测互斥:命中 DETECTION_BUSY 时根据 data 和本地持锁状态分发到 4 种文案
if (data.code === ResultEnum.DETECTION_BUSY) {
const lockStore = useDetectionLockStore()
const holder = (data.data ?? null) as DetectionLockHolder | null
const currentUserId = userStore.userInfo?.id
const localDetecting = lockStore.iAmHolder
if (!localDetecting && holder) {
// S1:他人持锁
showLockBusyDialog(holder)
} else if (!localDetecting && !holder) {
// S2:未开始检测就调中间接口
showLockNotStartedToast()
} else if (localDetecting && holder && holder.holderUserId !== currentUserId) {
// S4-a:被强释 + 别人接手
showForceReleasedDialog(holder)
lockStore.clearHolder()
} else if (localDetecting && !holder) {
// S4-b:被强释,无人接手
showForceReleasedDialog(null)
lockStore.clearHolder()
}
// 阻断默认错误提示,不再走下面的 ElMessage.error
return Promise.reject(data)
}
// 全局错误信息拦截(防止下载文件的时候返回数据流,没有 code 直接报错)
if (data.code && data.code !== ResultEnum.SUCCESS) {
if (data.message.includes('&')) {

View File

@@ -69,5 +69,37 @@ export namespace Plan {
maxTime: number;
}
export interface PlanStatisticsItem {
itemId: string;
itemName: string;
unqualifiedCount: number;
}
export interface PlanStatisticsOption {
id: string;
name: string;
}
export interface PlanStatistics {
planId: string;
planName: string;
totalCheckCount: number;
checkedDeviceCount: number;
uncheckedDeviceCount: number;
firstQualifiedDeviceCount: number;
secondQualifiedDeviceCount: number;
thirdOrMoreQualifiedDeviceCount: number;
qualifiedDeviceCount: number;
unqualifiedDeviceCount: number;
unqualifiedItemCount: number;
firstPassRate: number;
secondPassRate: number;
thirdOrMorePassRate: number;
unqualifiedRate: number;
itemDistributions: PlanStatisticsItem[];
manufacturerOptions: PlanStatisticsOption[];
devTypeOptions: PlanStatisticsOption[];
}
}
}

View File

@@ -94,6 +94,10 @@ export const staticsAnalyse = (params: { id: string[] }) => {
return http.download('/adPlan/analyse', params)
}
export const getPlanStatistics = (params: { planId: string; manufacturer?: string; devType?: string }) => {
return http.post<Plan.PlanStatistics>(`/adPlan/statistics`, params)
}
//根据计划id分页查询被检设
export const getDevListByPlanId = (params: any) => {
return http.post(`/adPlan/listDevByPlanId`, params)
@@ -159,4 +163,4 @@ export const importAndMergePlanCheckData = (params: Plan.ResPlan) => {
return http.upload(`/adPlan/importAndMergePlanCheckData`, params, {
timeout: 60000 * 20
})
}
}

View File

@@ -0,0 +1,18 @@
import http from '@/api'
import type { ResourceManage } from '@/api/resourceManage/interface'
export const getResourceManageList = (params: ResourceManage.ReqResourceManageParams) => {
return http.post<ResourceManage.ResResourceManagePage>('/resourceManage/list', params)
}
export const addResourceManage = (params: FormData) => {
return http.upload('/resourceManage/add', params)
}
export const updateResourceManage = (params: ResourceManage.ReqUpdateResourceManage) => {
return http.post('/resourceManage/update', params)
}
export const getResourceManagePlayUrl = (id: string) => {
return http.get<ResourceManage.PlayVO>(`/resourceManage/play?id=${id}`)
}

View File

@@ -0,0 +1,34 @@
import type { ReqPage, ResPage } from '@/api/interface'
export namespace ResourceManage {
export interface ReqResourceManageParams extends ReqPage {
name?: string
fileName?: string
}
export interface ResResourceManage {
id: string
name: string
fileName: string
fileSize: number
relativePath: string
remark: string
state: number
createBy?: string | null
createTime?: string | null
updateBy?: string | null
updateTime?: string | null
}
export interface ResResourceManagePage extends ResPage<ResResourceManage> {}
export interface ReqUpdateResourceManage {
id: string
name: string
remark: string
}
export interface PlayVO {
url: string
}
}

View File

@@ -1,8 +1,12 @@
import http from '@/api'
import { useDetectionLockStore } from '@/stores/modules/detectionLock'
export const startPreTest = (params) => {
return http.post(`/prepare/startPreTest`, params, {loading: false})
export const startPreTest = async (params) => {
const result = await http.post(`/prepare/startPreTest`, params, {loading: false})
// 抢锁成功 → 标记本地为持锁者
useDetectionLockStore().setAsHolder()
return result
}
export const closePreTest = (params) => {
@@ -37,8 +41,11 @@ export const resumeTest = (params) => {
* 比对式通道配对
* @param params
*/
export const contrastTest = (params: any) => {
return http.post(`/prepare/startContrastTest`,params)
export const contrastTest = async (params: any) => {
const result = await http.post(`/prepare/startContrastTest`, params)
// 抢锁成功 → 标记本地为持锁者
useDetectionLockStore().setAsHolder()
return result
}
export const exportAlignData= () => {

View File

@@ -0,0 +1,9 @@
import http from '@/api'
export const startSntpService = () => {
return http.post('/sntp/start', {})
}
export const stopSntpService = () => {
return http.post('/sntp/stop', {})
}

View File

@@ -130,7 +130,6 @@ const initChart = () => {
chart.resize()
}, 0)
}
const getChartInstance = () => chart
const handlerBar = (options: any) => {
if (Array.isArray(options.series)) {
options.series.forEach((item: any) => {
@@ -254,7 +253,7 @@ onMounted(() => {
initChart()
resizeObserver.observe(chartRef.value!)
})
defineExpose({ initChart, getChartInstance })
defineExpose({ initChart })
onBeforeUnmount(() => {
resizeObserver.unobserve(chartRef.value!)
chart?.dispose()

View File

@@ -1,7 +1,7 @@
// ? 全局默认配置项
// 首页地址(默认)
export const HOME_URL: string = "/machine/freqConverter";
export const HOME_URL: string = "/home/index";
// export const HOME_URL: string = "/machine/controlSource";

View File

@@ -6,6 +6,7 @@ export enum ResultEnum {
ERROR = 500,
ACCESSTOKEN_EXPIRED = "A0024",
OVERDUE = "A0025",
DETECTION_BUSY = "A020042",
TIMEOUT = 30000,
TYPE = "success"
}

View File

@@ -26,7 +26,6 @@
</template>
<script lang="ts" setup>
import { computed } from 'vue'
import { HOME_URL } from '@/config'
import { useAuthStore } from '@/stores/modules/auth'
import { useModeStore } from '@/stores/modules/mode' // 引入模式 store
import { useTabsStore } from '@/stores/modules/tabs'
@@ -75,8 +74,8 @@ const handelOpen = async (item: string, key: string) => {
await initDynamicRouter()
// 只有当目标路径与当前路径不同时才跳转
if (router.currentRoute.value.path !== HOME_URL) {
await router.push({ path: HOME_URL })
if (router.currentRoute.value.path !== '/home/index') {
await router.push({ path: '/home/index' })
} else {
// 如果已在目标页面,手动触发组件更新
window.location.reload() // 或者采用其他方式刷新数据

View File

@@ -70,7 +70,7 @@
<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'
@@ -132,7 +132,7 @@ const changeScene = async (value: string) => {
//模式切换
const changeMode = async () => {
authStore.changeModel()
await router.push(HOME_URL)
await router.push('/home/index')
}
</script>

View File

@@ -29,7 +29,6 @@ import { useRoute, useRouter } from 'vue-router'
import { useGlobalStore } from '@/stores/modules/global'
import { useTabsStore } from '@/stores/modules/tabs'
import { useAuthStore } from '@/stores/modules/auth'
import { HOME_URL } from '@/config'
import { TabPaneName, TabsPaneContext } from 'element-plus'
import MoreButton from './components/MoreButton.vue'
@@ -74,13 +73,13 @@ watch(
// 初始化需要固定的 tabs
const initTabs = () => {
authStore.flatMenuListGet.forEach(item => {
if (item.path === HOME_URL && !item.meta.isHide && !item.meta.isFull) {
if (item.meta.isAffix && !item.meta.isHide && !item.meta.isFull) {
const tabsParams = {
icon: item.meta.icon,
title: item.meta.title,
path: item.path,
name: item.name,
close: false,
close: !item.meta.isAffix,
isKeepAlive: item.meta.isKeepAlive,
unshift: true
}

View File

@@ -19,3 +19,6 @@ export const DICT_STORE_KEY = "cn-dictData";
export const CHECK_STORE_KEY = "cn-check";
// pinia中detectionLock store的key
export const DETECTION_LOCK_STORE_KEY = "cn-detectionLock";

View File

@@ -3,7 +3,6 @@ import { type AuthState } from '@/stores/interface'
import { getAuthButtonListApi, getAuthMenuListApi } from '@/api/user/login'
import { getAllBreadcrumbList, getFlatMenuList, getShowMenuList } from '@/utils'
import { AUTH_STORE_KEY } from '@/stores/constant'
import { HOME_URL } from '@/config'
import { useModeStore } from '@/stores/modules/mode'
import { getLicense } from '@/api/activate'
import type { Activate } from '@/api/activate/interface'
@@ -53,7 +52,7 @@ export const useAuthStore = defineStore(AUTH_STORE_KEY, {
? filterMenuByExcludedNames(menuData, ['testSource', 'testScript', 'controlSource'])
: filterMenuByExcludedNames(menuData, ['standardDevice'])
this.authMenuList = normalizeHomeAffix(filteredMenu)
this.authMenuList = filteredMenu
},
// Set RouteName
async setRouteName(name: string) {
@@ -113,22 +112,3 @@ function filterMenuByExcludedNames(menuList: any[], excludedNames: string[]): an
return !excludedNames.includes(menu.name)
})
}
function normalizeHomeAffix(menuList: any[]): any[] {
return menuList.map(menu => {
const nextMenu = { ...menu }
if (nextMenu.meta) {
nextMenu.meta = {
...nextMenu.meta,
isAffix: nextMenu.path === HOME_URL
}
}
if (Array.isArray(nextMenu.children) && nextMenu.children.length > 0) {
nextMenu.children = normalizeHomeAffix(nextMenu.children)
}
return nextMenu
})
}

View File

@@ -0,0 +1,33 @@
import { defineStore } from 'pinia'
import { DETECTION_LOCK_STORE_KEY } from '@/stores/constant'
export interface DetectionLockHolder {
holderUserId: string
holderUserName: string
acquireTime: string
expireAt: string
}
export const useDetectionLockStore = defineStore(DETECTION_LOCK_STORE_KEY, {
state: () => ({
iAmHolder: false,
holder: null as DetectionLockHolder | null
}),
actions: {
setAsHolder(holder?: Partial<DetectionLockHolder> | null) {
this.iAmHolder = true
if (holder) {
this.holder = {
holderUserId: holder.holderUserId ?? '',
holderUserName: holder.holderUserName ?? '',
acquireTime: holder.acquireTime ?? '',
expireAt: holder.expireAt ?? ''
}
}
},
clearHolder() {
this.iAmHolder = false
this.holder = null
}
}
})

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