feat: 监控端
This commit is contained in:
parent
6838d454b0
commit
d4b629cc25
|
|
@ -1,2 +1,3 @@
|
|||
# 开发环境 — 留空,走 vite.config.ts 中的 proxy
|
||||
VITE_API_BASE=
|
||||
VITE_ENTRY_OPTIONS=ops,monitor
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
# 生产环境
|
||||
VITE_API_BASE=https://api.baoshi56.com
|
||||
VITE_ENTRY_OPTIONS=ops,monitor
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
# 测试环境(SIT)
|
||||
VITE_API_BASE=https://sit-api.baoshi56.com
|
||||
VITE_API_BASE=https://api.baoshi56.com
|
||||
VITE_ENTRY_OPTIONS=monitor
|
||||
|
|
|
|||
|
|
@ -13362,4 +13362,11 @@ node_modules/vue-tsc/LICENSE
|
|||
node_modules/vue-tsc/package.json
|
||||
node_modules/vue-tsc/README.md
|
||||
node_modules/vue-tsc/bin/vue-tsc.js
|
||||
/dist/*
|
||||
/dist/*
|
||||
/node_modules/fsevents/fsevents.d.ts
|
||||
/node_modules/fsevents/fsevents.js
|
||||
/node_modules/fsevents/fsevents.node
|
||||
/node_modules/fsevents/LICENSE
|
||||
/node_modules/fsevents/package.json
|
||||
/node_modules/fsevents/README.md
|
||||
/node_modules/*
|
||||
|
|
|
|||
|
|
@ -11,12 +11,12 @@
|
|||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"vue": "^3.5.13",
|
||||
"vue-router": "^4.5.0",
|
||||
"pinia": "^2.3.0",
|
||||
"@element-plus/icons-vue": "^2.3.1",
|
||||
"axios": "^1.7.9",
|
||||
"element-plus": "^2.9.1",
|
||||
"@element-plus/icons-vue": "^2.3.1"
|
||||
"pinia": "^2.3.0",
|
||||
"vue": "^3.5.13",
|
||||
"vue-router": "^4.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ export interface ChainQueryParams {
|
|||
type?: string
|
||||
businessNo?: string
|
||||
sourceContainer?: string
|
||||
targetCode?: string
|
||||
startTime?: string
|
||||
endTime?: string
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
active-text-color="#ffffff"
|
||||
class="aside-menu"
|
||||
>
|
||||
<el-menu-item index="/dashboard">
|
||||
<el-menu-item v-if="!isMonitorMode" index="/dashboard">
|
||||
<el-icon><Monitor /></el-icon>
|
||||
<template #title>首页</template>
|
||||
</el-menu-item>
|
||||
|
|
@ -25,13 +25,13 @@
|
|||
</el-menu-item>
|
||||
<el-menu-item index="/elevator">
|
||||
<el-icon><SetUp /></el-icon>
|
||||
<template #title>提升机管理</template>
|
||||
<template #title>提升机查看</template>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/vendor/load">
|
||||
<el-menu-item v-if="!isMonitorMode" index="/vendor/load">
|
||||
<el-icon><DataLine /></el-icon>
|
||||
<template #title>厂商负载</template>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/generate">
|
||||
<el-menu-item v-if="!isMonitorMode" index="/generate">
|
||||
<el-icon><Plus /></el-icon>
|
||||
<template #title>任务生成</template>
|
||||
</el-menu-item>
|
||||
|
|
@ -191,7 +191,14 @@ function refreshCurrentTab() {
|
|||
refreshKeys.value[route.path] = (refreshKeys.value[route.path] ?? 0) + 1
|
||||
}
|
||||
|
||||
const keepAliveNames = ['DashboardView', 'TaskChainList', 'TaskChainDetail', 'ElevatorList', 'VendorLoadView', 'TaskGenerateView']
|
||||
const userStore = useUserStore()
|
||||
const isMonitorMode = computed(() => userStore.isMonitorMode())
|
||||
const keepAliveNames = computed(() => {
|
||||
if (isMonitorMode.value) {
|
||||
return ['TaskChainList', 'TaskChainDetail', 'ElevatorList']
|
||||
}
|
||||
return ['DashboardView', 'TaskChainList', 'TaskChainDetail', 'ElevatorList', 'VendorLoadView', 'TaskGenerateView']
|
||||
})
|
||||
|
||||
// 必须在 watch 之前恢复,否则 watch 的 immediate 会先执行并覆盖 storage
|
||||
const activePath = tabsStore.restoreFromStorage()
|
||||
|
|
@ -304,16 +311,15 @@ onMounted(() => {
|
|||
onUnmounted(() => {
|
||||
document.removeEventListener('click', hideTabMenu)
|
||||
})
|
||||
const userStore = useUserStore()
|
||||
const isCollapse = ref(false)
|
||||
|
||||
const tabs = [
|
||||
{ path: '/dashboard', label: '首页', icon: Monitor },
|
||||
const tabs = computed(() => [
|
||||
...(!isMonitorMode.value ? [{ path: '/dashboard', label: '首页', icon: Monitor }] : []),
|
||||
{ path: '/task/chain', label: '任务链', icon: List },
|
||||
{ path: '/elevator', label: '提升机', icon: SetUp },
|
||||
{ path: '/vendor/load', label: '厂商负载', icon: DataLine },
|
||||
{ path: '/generate', label: '生成', icon: Plus },
|
||||
]
|
||||
...(!isMonitorMode.value ? [{ path: '/vendor/load', label: '厂商负载', icon: DataLine }] : []),
|
||||
...(!isMonitorMode.value ? [{ path: '/generate', label: '生成', icon: Plus }] : []),
|
||||
])
|
||||
|
||||
const activeMenu = computed(() => {
|
||||
const path = route.path
|
||||
|
|
|
|||
|
|
@ -1,4 +1,12 @@
|
|||
import { createRouter, createWebHashHistory } from 'vue-router'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
|
||||
const monitorBlockedPaths = ['/dashboard', '/vendor/load', '/generate']
|
||||
|
||||
function getHomePath() {
|
||||
const userStore = useUserStore()
|
||||
return userStore.isMonitorMode() ? '/task/chain' : '/dashboard'
|
||||
}
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
|
|
@ -12,7 +20,7 @@ const router = createRouter({
|
|||
{
|
||||
path: '/',
|
||||
component: () => import('@/layouts/AdminLayout.vue'),
|
||||
redirect: '/dashboard',
|
||||
redirect: () => getHomePath(),
|
||||
children: [
|
||||
{
|
||||
path: 'dashboard',
|
||||
|
|
@ -56,11 +64,14 @@ const router = createRouter({
|
|||
})
|
||||
|
||||
router.beforeEach((to, _from, next) => {
|
||||
const userStore = useUserStore()
|
||||
const token = localStorage.getItem('token')
|
||||
if (!to.meta.public && !token) {
|
||||
next('/login')
|
||||
} else if (to.path === '/login' && token) {
|
||||
next('/')
|
||||
next(getHomePath())
|
||||
} else if (!to.meta.public && userStore.isMonitorMode() && monitorBlockedPaths.includes(to.path)) {
|
||||
next('/task/chain')
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ import { ref } from 'vue'
|
|||
import { login as loginApi } from '@/api/auth'
|
||||
import router from '@/router'
|
||||
|
||||
export type EntryMode = 'ops' | 'monitor'
|
||||
|
||||
export interface UserInfo {
|
||||
id: number
|
||||
name: string
|
||||
|
|
@ -12,6 +14,7 @@ export interface UserInfo {
|
|||
export const useUserStore = defineStore('user', () => {
|
||||
const token = ref(localStorage.getItem('token') || '')
|
||||
const user = ref<UserInfo | null>(parseStoredUser())
|
||||
const entryMode = ref<EntryMode>(parseStoredEntryMode())
|
||||
|
||||
function parseStoredUser(): UserInfo | null {
|
||||
try {
|
||||
|
|
@ -22,6 +25,11 @@ export const useUserStore = defineStore('user', () => {
|
|||
}
|
||||
}
|
||||
|
||||
function parseStoredEntryMode(): EntryMode {
|
||||
const stored = localStorage.getItem('entryMode')
|
||||
return stored === 'monitor' ? 'monitor' : 'ops'
|
||||
}
|
||||
|
||||
async function login(username: string, password: string) {
|
||||
const res = await loginApi(username, password)
|
||||
const data = res.data
|
||||
|
|
@ -35,6 +43,15 @@ export const useUserStore = defineStore('user', () => {
|
|||
localStorage.setItem('user', JSON.stringify(user.value))
|
||||
}
|
||||
|
||||
function setEntryMode(mode: EntryMode) {
|
||||
entryMode.value = mode
|
||||
localStorage.setItem('entryMode', mode)
|
||||
}
|
||||
|
||||
function isMonitorMode(): boolean {
|
||||
return entryMode.value === 'monitor'
|
||||
}
|
||||
|
||||
function logout() {
|
||||
token.value = ''
|
||||
user.value = null
|
||||
|
|
@ -47,5 +64,5 @@ export const useUserStore = defineStore('user', () => {
|
|||
return !!token.value
|
||||
}
|
||||
|
||||
return { token, user, login, logout, isLoggedIn }
|
||||
return { token, user, entryMode, login, logout, isLoggedIn, setEntryMode, isMonitorMode }
|
||||
})
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<el-card shadow="hover">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>提升机管理</span>
|
||||
<span>提升机查看</span>
|
||||
<el-button type="primary" size="small" :loading="refreshing" @click="loadData">
|
||||
刷新
|
||||
</el-button>
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
{{ elevator.enable ? '已启用' : '已禁用' }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div class="elevator-actions">
|
||||
<div v-if="!isMonitorMode" class="elevator-actions">
|
||||
<el-button
|
||||
v-if="elevator.enable"
|
||||
type="warning" size="small" plain
|
||||
|
|
@ -120,7 +120,7 @@
|
|||
<!-- ========== 移动端 ========== -->
|
||||
<template v-else>
|
||||
<div class="m-elevator-header">
|
||||
<span class="m-elevator-title">提升机管理</span>
|
||||
<span class="m-elevator-title">提升机查看</span>
|
||||
<el-button type="primary" size="small" round :loading="refreshing" @click="loadData">刷新</el-button>
|
||||
</div>
|
||||
|
||||
|
|
@ -198,7 +198,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="m-elevator-card-actions">
|
||||
<div v-if="!isMonitorMode" class="m-elevator-card-actions">
|
||||
<el-button
|
||||
v-if="elevator.enable"
|
||||
type="warning" size="small" plain round
|
||||
|
|
@ -231,11 +231,14 @@ import {
|
|||
type ElevatorVO,
|
||||
} from '@/api/elevator'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useDevice } from '@/composables/useDevice'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
|
||||
const { isMobile } = useDevice()
|
||||
const userStore = useUserStore()
|
||||
const isMonitorMode = computed(() => userStore.isMonitorMode())
|
||||
const router = useRouter()
|
||||
const elevators = ref<ElevatorVO[]>([])
|
||||
const refreshing = ref(false)
|
||||
|
|
|
|||
|
|
@ -30,6 +30,20 @@
|
|||
:prefix-icon="Lock"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<div class="entry-mode-wrap">
|
||||
<span class="entry-mode-label">进入端口</span>
|
||||
<el-radio-group v-model="entryMode">
|
||||
<el-radio-button
|
||||
v-for="item in availableEntryModes"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
|
|
@ -66,9 +80,10 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import type { EntryMode } from '@/stores/user'
|
||||
import { Lock, User } from '@element-plus/icons-vue'
|
||||
import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { computed, reactive, ref, watchEffect } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
|
|
@ -88,6 +103,23 @@ const rules: FormRules = {
|
|||
|
||||
const tokenDialogVisible = ref(false)
|
||||
const manualToken = ref('')
|
||||
const allEntryModes: Array<{ value: EntryMode; label: string }> = [
|
||||
{ value: 'ops', label: '运维端' },
|
||||
{ value: 'monitor', label: '监控端' },
|
||||
]
|
||||
const envEntryModes = (import.meta.env.VITE_ENTRY_OPTIONS as string | undefined) || 'ops,monitor'
|
||||
const parsedEntryModes = envEntryModes.split(',').map((item) => item.trim()).filter((item) => item === 'ops' || item === 'monitor') as EntryMode[]
|
||||
const availableEntryModes = computed(() => {
|
||||
const modeSet = new Set(parsedEntryModes.length ? parsedEntryModes : ['ops', 'monitor'])
|
||||
return allEntryModes.filter((item) => modeSet.has(item.value))
|
||||
})
|
||||
const entryMode = ref<EntryMode>(userStore.entryMode)
|
||||
|
||||
watchEffect(() => {
|
||||
if (!availableEntryModes.value.some((item) => item.value === entryMode.value)) {
|
||||
entryMode.value = availableEntryModes.value[0]?.value ?? 'ops'
|
||||
}
|
||||
})
|
||||
|
||||
function handleSetToken() {
|
||||
const token = manualToken.value.trim()
|
||||
|
|
@ -95,6 +127,7 @@ function handleSetToken() {
|
|||
ElMessage.warning('Token 不能为空')
|
||||
return
|
||||
}
|
||||
userStore.setEntryMode(entryMode.value)
|
||||
localStorage.setItem('token', token)
|
||||
tokenDialogVisible.value = false
|
||||
ElMessage.success('Token 已设置')
|
||||
|
|
@ -107,6 +140,7 @@ async function handleLogin() {
|
|||
|
||||
loading.value = true
|
||||
try {
|
||||
userStore.setEntryMode(entryMode.value)
|
||||
await userStore.login(form.username, form.password)
|
||||
ElMessage.success('登录成功')
|
||||
router.push('/')
|
||||
|
|
@ -179,4 +213,15 @@ async function handleLogin() {
|
|||
width: 100%;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.entry-mode-wrap {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.entry-mode-label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
{{ chainStatusMap[chain.status] || chain.status }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div class="card-header-actions">
|
||||
<div v-if="!isMonitorMode" class="card-header-actions">
|
||||
<el-button
|
||||
v-if="canCancel(chain.status)"
|
||||
type="danger" size="small" :loading="canceling"
|
||||
|
|
@ -94,14 +94,14 @@
|
|||
{{ taskStatusMap[task.status] || task.status }}
|
||||
</el-tag>
|
||||
<el-button
|
||||
v-if="canMockCallback(task)"
|
||||
v-if="!isMonitorMode && canMockCallback(task)"
|
||||
text type="success" size="small"
|
||||
@click="openMockCallback(task)"
|
||||
>模拟回调</el-button>
|
||||
<el-button text type="danger" size="small" @click="handleDeleteTask(task)">
|
||||
<el-button v-if="!isMonitorMode" text type="danger" size="small" @click="handleDeleteTask(task)">
|
||||
删除
|
||||
</el-button>
|
||||
<el-dropdown trigger="click" @command="(cmd: string) => handleForceStatus(task, cmd)">
|
||||
<el-dropdown v-if="!isMonitorMode" trigger="click" @command="(cmd: string) => handleForceStatus(task, cmd)">
|
||||
<el-button text type="primary" size="small">变更状态</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
|
|
@ -172,7 +172,7 @@
|
|||
<span class="m-chain-type">{{ typeMap[chain.type] || chain.type }}</span>
|
||||
</div>
|
||||
<div class="m-chain-code-mobile">{{ chain.code }}</div>
|
||||
<div class="m-status-actions">
|
||||
<div v-if="!isMonitorMode" class="m-status-actions">
|
||||
<el-button
|
||||
v-if="canCancel(chain.status)"
|
||||
type="danger" size="small" round :loading="canceling"
|
||||
|
|
@ -282,7 +282,7 @@
|
|||
<el-tag size="small" type="info">{{ task.type }}</el-tag>
|
||||
<el-tag size="small" type="info">{{ task.vendor }}</el-tag>
|
||||
</div>
|
||||
<el-icon class="m-task-more" @click="openTaskActions(task)"><MoreFilled /></el-icon>
|
||||
<el-icon v-if="!isMonitorMode" class="m-task-more" @click="openTaskActions(task)"><MoreFilled /></el-icon>
|
||||
</div>
|
||||
<div class="m-task-code">{{ task.code }}</div>
|
||||
|
||||
|
|
@ -320,6 +320,7 @@
|
|||
|
||||
<!-- 移动端子任务操作面板 -->
|
||||
<el-drawer
|
||||
v-if="!isMonitorMode"
|
||||
v-model="taskActionDrawerVisible"
|
||||
direction="btt"
|
||||
size="auto"
|
||||
|
|
@ -351,6 +352,7 @@
|
|||
|
||||
<!-- 移动端变更状态选择 -->
|
||||
<el-drawer
|
||||
v-if="!isMonitorMode"
|
||||
v-model="statusPickerVisible"
|
||||
direction="btt"
|
||||
size="auto"
|
||||
|
|
@ -442,11 +444,12 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: 'TaskChainDetail' })
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { ArrowLeft, MoreFilled, VideoPlay, Switch, Delete } from '@element-plus/icons-vue'
|
||||
import { useDevice } from '@/composables/useDevice'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { chainStatusMap, getChainStatusTag } from '@/constants/chainStatus'
|
||||
import { taskStatusMap, getTaskStatusTag } from '@/constants/taskStatus'
|
||||
import {
|
||||
|
|
@ -456,6 +459,8 @@ import {
|
|||
} from '@/api/task'
|
||||
|
||||
const { isMobile } = useDevice()
|
||||
const userStore = useUserStore()
|
||||
const isMonitorMode = computed(() => userStore.isMonitorMode())
|
||||
const route = useRoute()
|
||||
const loading = ref(false)
|
||||
const executing = ref(false)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@
|
|||
<el-form-item label="源容器">
|
||||
<el-input v-model="query.sourceContainer" placeholder="请输入" clearable style="width: 150px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="目标编码">
|
||||
<el-input v-model="query.targetCode" placeholder="请输入" clearable style="width: 150px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间">
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
|
|
@ -46,7 +49,7 @@
|
|||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>任务链列表</span>
|
||||
<div>
|
||||
<div v-if="!isMonitorMode">
|
||||
<el-button type="success" size="small" @click="handleScan">手动扫描执行</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -97,7 +100,7 @@
|
|||
<template #default="{ row }">
|
||||
<el-button text type="primary" size="small" @click="goDetail(row.code)">详情</el-button>
|
||||
<el-button
|
||||
v-if="row.status === 'CREATED' || row.status === 'READY'"
|
||||
v-if="!isMonitorMode && (row.status === 'CREATED' || row.status === 'READY')"
|
||||
text type="warning" size="small"
|
||||
@click="handleExecute(row)"
|
||||
>
|
||||
|
|
@ -139,7 +142,7 @@
|
|||
</div>
|
||||
|
||||
<!-- 手动扫描执行 -->
|
||||
<el-button type="success" size="small" class="m-scan-btn" @click="handleScan">
|
||||
<el-button v-if="!isMonitorMode" type="success" size="small" class="m-scan-btn" @click="handleScan">
|
||||
手动扫描执行
|
||||
</el-button>
|
||||
|
||||
|
|
@ -201,7 +204,7 @@
|
|||
<span class="m-chain-time">{{ row.createTime }}</span>
|
||||
<div class="m-chain-actions" @click.stop>
|
||||
<el-button
|
||||
v-if="row.status === 'CREATED' || row.status === 'READY'"
|
||||
v-if="!isMonitorMode && (row.status === 'CREATED' || row.status === 'READY')"
|
||||
type="warning"
|
||||
size="small"
|
||||
@click="handleExecute(row)"
|
||||
|
|
@ -261,6 +264,9 @@
|
|||
<el-form-item label="源容器">
|
||||
<el-input v-model="query.sourceContainer" placeholder="请输入" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="目标编码">
|
||||
<el-input v-model="query.targetCode" placeholder="请输入" clearable />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="m-drawer-footer">
|
||||
<el-button @click="handleReset">重置</el-button>
|
||||
|
|
@ -280,8 +286,11 @@ import { computed, nextTick, onMounted, onUnmounted, reactive, ref } from 'vue'
|
|||
import { useRouter } from 'vue-router'
|
||||
import { useDevice } from '@/composables/useDevice'
|
||||
import { chainStatusMap, getChainStatusTag } from '@/constants/chainStatus'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
|
||||
const { isMobile } = useDevice()
|
||||
const userStore = useUserStore()
|
||||
const isMonitorMode = computed(() => userStore.isMonitorMode())
|
||||
const router = useRouter()
|
||||
const tableRef = ref<TableInstance>()
|
||||
const loading = ref(false)
|
||||
|
|
@ -350,6 +359,7 @@ const query = reactive({
|
|||
type: '',
|
||||
businessNo: '',
|
||||
sourceContainer: '',
|
||||
targetCode: '',
|
||||
})
|
||||
|
||||
const activeFilterCount = computed(() => {
|
||||
|
|
@ -357,6 +367,7 @@ const activeFilterCount = computed(() => {
|
|||
if (query.type) n++
|
||||
if (query.businessNo) n++
|
||||
if (query.sourceContainer) n++
|
||||
if (query.targetCode) n++
|
||||
if (dateRange.value?.length) n++
|
||||
return n
|
||||
})
|
||||
|
|
@ -424,6 +435,7 @@ function handleReset() {
|
|||
query.type = ''
|
||||
query.businessNo = ''
|
||||
query.sourceContainer = ''
|
||||
query.targetCode = ''
|
||||
dateRange.value = []
|
||||
handleSearch()
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue