feat: 故障管理-基本信息

master
李小林 7 months ago
parent 78fb8d2a78
commit 542e863193
  1. 20
      src/api/fault/index.ts
  2. 41
      src/api/fault/types.ts
  3. 12
      src/layout/components/NavBar/components/NavbarRight.vue
  4. 6
      src/views/dashboard/index.vue
  5. 252
      src/views/family/operate/fault-management/components/basicInfoQuery.vue
  6. 242
      src/views/family/operate/fault-management/index.vue
  7. 6
      src/views/family/operate/ipv6CollectingConfig/index.vue
  8. 4
      src/views/personal/index.vue

@ -0,0 +1,20 @@
import request from "@/utils/request";
import { FaultBasicInfoVO, FaultQuery, FaultQueryVO } from "@/api/fault/types";
import { AxiosPromise } from "axios";
export function faultQueryList(data: FaultQuery): AxiosPromise<FaultQueryVO[]> {
return request({
url: "/api/fault/v1/query",
method: "POST",
data,
});
}
export function faultBasicInfoQuery(
data: FaultQuery
): AxiosPromise<FaultBasicInfoVO> {
return request({
url: "/api/fault/v1/basic_info",
method: "POST",
data,
});
}

@ -0,0 +1,41 @@
export interface FaultQueryVO {
devId?: number;
devSno?: string;
devPppoe?: string;
devVendorOui?: string;
devAdNo?: string;
}
export interface FaultQuery {
label: string;
value: string;
ping: string[];
}
export interface FaultBasicInfoVO {
devId?: number;
devPppoe?: string;
devVendorName?: string;
devTypeName?: string;
devHardVer?: string;
userSnNo?: string;
customType?: string;
devIp?: string;
devStatus?: string;
devAccessType?: string;
devSno?: string;
softVer?: string;
}

@ -20,10 +20,7 @@
<!-- 用户头像 --> <!-- 用户头像 -->
<el-dropdown class="setting-item" trigger="click"> <el-dropdown class="setting-item" trigger="click">
<div class="flex-center h100% p10px"> <div class="flex-center h100% p10px">
<img <img :src="avatarUrl" class="rounded-full mr-10px w24px w24px" />
:src="userStore.user.avatar + '?imageView2/1/w/80/h/80'"
class="rounded-full mr-10px w24px w24px"
/>
<span>{{ userStore.user.username }}</span> <span>{{ userStore.user.username }}</span>
</div> </div>
<template #dropdown> <template #dropdown>
@ -65,7 +62,9 @@ const router = useRouter();
const device = computed(() => appStore.device); const device = computed(() => appStore.device);
const { isFullscreen, toggle } = useFullscreen(); const { isFullscreen, toggle } = useFullscreen();
const avatarUrl = ref(
new URL(`../../../../assets/images/avatar.png`, import.meta.url).href
);
/** /**
* 注销 * 注销
*/ */
@ -89,6 +88,9 @@ function logout() {
const skipPersonal = () => { const skipPersonal = () => {
router.push(`/resources/personal-center`); router.push(`/resources/personal-center`);
}; };
onMounted(()=>{
console.log(avatarUrl.value);
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.setting-item { .setting-item {

@ -6,7 +6,7 @@
<div class="flex h-full items-center"> <div class="flex h-full items-center">
<img <img
class="w-20 h-20 mr-5 rounded-full" class="w-20 h-20 mr-5 rounded-full"
:src="userStore.user.avatar + '?imageView2/1/w/80/h/80'" :src="avatarUrl"
/> />
<div> <div>
<p>{{ greetings }}</p> <p>{{ greetings }}</p>
@ -48,7 +48,9 @@ const greetings = computed(() => {
return "偷偷向银河要了一把碎星,只等你闭上眼睛撒入你的梦中,晚安🌛!"; return "偷偷向银河要了一把碎星,只等你闭上眼睛撒入你的梦中,晚安🌛!";
} }
}); });
const avatarUrl = ref(
new URL(`../../assets/images/avatar.png`, import.meta.url).href
);
const duration = 5000; const duration = 5000;
</script> </script>

@ -0,0 +1,252 @@
<template>
<el-scrollbar height="450" v-loading="loading">
<el-descriptions :column="3" border>
<template #title>
<div style="display: flex; align-items: center">
<el-icon size="15"> <Grid /> </el-icon>&nbsp;<span
style="font-weight: 700; font-size: 14px; line-height: 16px"
>用户信息</span
>
</div>
</template>
<el-descriptions-item
label="宽带账号"
label-align="center"
align="left"
label-class-name="my-label"
class-name="my-content"
width="150px"
>
{{ vo.devPppoe }}
</el-descriptions-item>
<el-descriptions-item
label="公客/商客"
label-align="center"
align="left"
label-class-name="my-label"
class-name="my-content"
width="150px"
>
{{ vo.customType }}
</el-descriptions-item>
<el-descriptions-item
label=" 逻辑ID"
label-align="center"
align="left"
label-class-name="my-label"
class-name="my-content"
width="150px"
>
{{ vo.userSnNo }}
</el-descriptions-item>
</el-descriptions>
<el-descriptions :column="3" border class="mt-3">
<template #title>
<div style="display: flex; align-items: center">
<el-icon size="15"> <Grid /> </el-icon>&nbsp;<span
style="font-weight: 700; font-size: 14px; line-height: 16px"
>终端信息</span
>
</div>
</template>
<el-descriptions-item
label="终端厂家"
label-align="center"
align="left"
label-class-name="my-label"
class-name="my-content"
width="150px"
>
{{ vo.devVendorName }} </el-descriptions-item
>>
<el-descriptions-item
label="终端型号"
label-align="center"
align="left"
label-class-name="my-label"
class-name="my-content"
width="150px"
>
{{ vo.devTypeName }}
</el-descriptions-item>
<el-descriptions-item
label=" 终端序列号"
label-align="center"
align="left"
label-class-name="my-label"
class-name="my-content"
width="150px"
>
{{ vo.devSno }}
</el-descriptions-item>
<el-descriptions-item
label=" 终端注册状态"
label-align="center"
align="left"
label-class-name="my-label"
class-name="my-content"
width="150px"
>
{{ vo.devStatus }}
</el-descriptions-item>
<el-descriptions-item
label=" 终端硬件版本"
label-align="center"
align="left"
label-class-name="my-label"
class-name="my-content"
width="150px"
>
{{ vo.devHardVer }}
</el-descriptions-item>
<el-descriptions-item
label=" 软件版本"
label-align="center"
align="left"
label-class-name="my-label"
class-name="my-content"
width="150px"
>
{{ vo.softVer }}
</el-descriptions-item>
<el-descriptions-item
label=" 网管IP"
label-align="center"
align="left"
label-class-name="my-label"
class-name="my-content"
width="150px"
>
{{ vo.devIp }}
</el-descriptions-item>
<el-descriptions-item
label=" 设备网络接口"
label-align="center"
align="left"
label-class-name="my-label"
class-name="my-content"
width="150px"
>
{{ vo.devAccessType }}
</el-descriptions-item>
</el-descriptions>
<div class="tags-container mt-2">
<div
@click="changTab(1)"
:class="'tags-item ' + (isActive(1) ? 'active' : '')"
>
有线无法上网
</div>
<div
@click="changTab(2)"
:class="'tags-item ' + (isActive(2) ? 'active' : '')"
class="tags-item"
>
上网速度慢
</div>
<div
@click="changTab(3)"
:class="'tags-item ' + (isActive(3) ? 'active' : '')"
class="tags-item"
>
用户异常掉线
</div>
</div>
<div>
<div v-show="currentTab === 1">
<el-card shadow="never">
<template #header>
<div class="flex justify-between">
<div style="display: flex; align-items: center">
<el-icon size="15"> <Grid /> </el-icon>&nbsp;<span
style="font-weight: 700; font-size: 14px; line-height: 16px"
>有线无法上网</span
>
</div>
<div>
<el-button type="primary">开始诊断</el-button>
</div>
</div>
</template>
<el-empty description="暂无任何信息" />
</el-card>
</div>
<div v-show="currentTab === 2">上网速度慢</div>
<div v-show="currentTab === 3">用户异常掉线</div>
</div>
</el-scrollbar>
</template>
<script setup lang="ts">
import { Grid } from "@element-plus/icons-vue";
import { faultBasicInfoQuery } from "@/api/fault";
import { FaultBasicInfoVO, FaultQuery, FaultQueryVO } from "@/api/fault/types";
const loading = ref<boolean>(false);
const currentTab = ref<number>(1);
function isActive(tab: number) {
return currentTab.value === tab;
}
const changTab = (tab: number) => {
currentTab.value = tab;
};
const vo = ref<FaultBasicInfoVO>({});
const getBasicInfo = (queryVO: FaultQueryVO) => {
loading.value = true;
let searchForm: FaultQuery = {
label: "devSno",
value: queryVO.devSno,
};
faultBasicInfoQuery(searchForm)
.then(({ data }) => {
vo.value = data;
})
.finally(() => {
loading.value = false;
});
};
defineExpose({ getBasicInfo });
</script>
<style scoped>
.tags-container {
width: 100%;
height: 50px;
color: #68758e;
background-color: var(--el-bg-color);
border: 1px solid var(--el-border-color-light);
box-shadow: 0 1px 1px var(--el-box-shadow-light);
.tags-item {
display: inline-block;
padding: 3px 8px;
margin: 8px 0 0 5px;
font-size: 14px;
line-height: 25px;
min-width: 100px;
cursor: pointer;
text-align: center;
background-color: #fff;
border: 1px solid var(--el-border-color-light);
border-radius: 6px;
&:hover {
color: var(--el-color-primary);
}
&:first-of-type {
margin-left: 5px;
}
&:last-of-type {
margin-right: 15px;
}
&.active {
color: var(--el-color-primary);
}
}
}
</style>

@ -0,0 +1,242 @@
<template>
<div class="app-container">
<el-card shadow="never">
<el-row>
<el-col
:span="24"
style="display: flex; justify-content: center; align-items: center"
>
<div class="w-160">
<el-input
style="position: relative"
v-model="searchForm.value"
@focus="flag = true"
placeholder="ITMS3.0 搜索"
/>
<div class="dropdown" v-if="flag" v-loading="loading">
<div class="close" @click="flag = false">
<el-icon size="18"><Close /></el-icon>
</div>
<el-scrollbar max-height="200">
<div>
<ul>
<li v-if="faultOptions.length === 0">暂无数据</li>
<li
v-for="(item, index) in faultOptions"
@click="loadBasicInfo(item)"
:key="index"
>
设备标识:{{ item.devVendorOui }}-{{
item.devSno
}}
宽带账号: {{ item.devPppoe }} AD编号: {{ item.devAdNo }}
</li>
</ul>
</div>
</el-scrollbar>
</div>
</div>
<div class="ml-3">
<el-button type="primary" @click="getData">搜索</el-button>
</div>
</el-col>
</el-row>
<el-row>
<el-col
class="mt-4"
:span="24"
style="display: flex; justify-content: center; align-items: center"
>
<div>
<el-radio-group v-model="searchForm.label">
<el-radio value="devSno">设备序列号</el-radio>
<el-radio value="adNo">AD编号</el-radio>
<el-radio value="pppoeAccount">上网账号</el-radio>
<el-radio value="identificationNumber">身份证号</el-radio>
<el-radio value="phoneNumber">电话号码</el-radio>
</el-radio-group>
</div>
<div class="ml-5">
<el-checkbox-group v-model="searchForm.ping" class="mr-2">
<el-checkbox label="PING" value="ping" />
</el-checkbox-group>
</div>
</el-col>
</el-row>
<div class="w-full">
<div class="tags-container">
<div
@click="changTab(0)"
:class="'tags-item ' + (isActive(0) ? 'active' : '')"
>
基本信息查询
</div>
<div
@click="changTab(1)"
:class="'tags-item ' + (isActive(1) ? 'active' : '')"
>
业务终端状态
</div>
<div
@click="changTab(2)"
:class="'tags-item ' + (isActive(2) ? 'active' : '')"
>
故障诊断应用
</div>
<div
@click="changTab(3)"
:class="'tags-item ' + (isActive(3) ? 'active' : '')"
>
高级查询
</div>
<div
@click="changTab(4)"
:class="'tags-item ' + (isActive(4) ? 'active' : '')"
>
健康库
</div>
<div
@click="changTab(5)"
:class="'tags-item ' + (isActive(5) ? 'active' : '')"
>
专家库
</div>
</div>
</div>
<div class="w-full mt-3">
<div v-show="currentTab === 0">
<basic-info-query ref="basicInfoQueryRef" />
</div>
<div v-show="currentTab === 1">业务终端状态</div>
<div v-show="currentTab === 2">故障诊断应用</div>
<div v-show="currentTab === 3">高级查询</div>
<div v-show="currentTab === 4">健康库</div>
<div v-show="currentTab === 5">专家库</div>
</div>
</el-card>
</div>
</template>
<script setup lang="ts">
import BasicInfoQuery from "@/views/family/operate/fault-management/components/basicInfoQuery.vue";
import { FaultQuery, FaultQueryVO } from "@/api/fault/types";
import { faultQueryList } from "@/api/fault";
import { Close } from "@element-plus/icons-vue";
defineOptions({
name: "FaultManagement",
inheritAttrs: false,
});
const loading = ref<string>();
const searchForm = ref<FaultQuery>({
label: "devSno",
value: "",
ping: [],
});
const basicInfoQueryRef = ref();
const flag = ref<boolean>(false);
const faultOptions = ref<FaultQueryVO[]>([]);
const currentTab = ref<number>(0);
function isActive(tab: number) {
return currentTab.value === tab;
}
const changTab = (tab: number) => {
currentTab.value = tab;
};
const getData = () => {
loading.value = true;
faultQueryList(searchForm.value)
.then(({ data }) => {
faultOptions.value = data;
})
.finally(() => {
loading.value = false;
});
};
const loadBasicInfo = (vo: FaultQueryVO) => {
flag.value = false;
basicInfoQueryRef.value.getBasicInfo(vo);
};
</script>
<style scoped>
:deep(.el-card__body) {
padding: 5px;
}
.tags-container {
width: 100%;
height: 50px;
color: #68758e;
background-color: var(--el-bg-color);
border: 1px solid var(--el-border-color-light);
box-shadow: 0 1px 1px var(--el-box-shadow-light);
.tags-item {
display: inline-block;
padding: 3px 8px;
margin: 8px 0 0 5px;
font-size: 14px;
line-height: 25px;
min-width: 100px;
cursor: pointer;
text-align: center;
background-color: #fff;
border: 1px solid var(--el-border-color-light);
border-radius: 6px;
&:hover {
color: var(--el-color-primary);
}
&:first-of-type {
margin-left: 5px;
}
&:last-of-type {
margin-right: 15px;
}
&.active {
color: var(--el-color-primary);
}
}
}
:deep(.my-label) {
width: 60px !important;
background: var(--el-color-white) !important;
}
.dropdown {
border: 1px solid #ccc;
width: inherit;
background-color: var(--el-color-white);
position: absolute;
z-index: 999;
overflow-y: auto;
line-height: 32px;
font-size: 14px;
text-align: center;
color: var(--el-input-text-color, var(--el-text-color-regular));
}
.dropdown .close {
height: 20px;
position: absolute;
top: -3px;
z-index: 999;
cursor: pointer;
right: 0;
}
.dropdown ul {
list-style: none;
padding: 0;
margin: 0;
}
.dropdown li {
padding: 5px;
cursor: pointer;
}
.dropdown li:hover {
background-color: var(--el-color-info-light-9);
}
</style>

@ -290,13 +290,13 @@ const loadTypeNameOption = () => {
}); });
}; };
const updateIpv6ConfigParam = (param: string) => { const updateIpv6ConfigParam = (param: string) => {
let param2 = ""; let param2: string | undefined = "";
switch (param) { switch (param) {
case "areaId": case "areaId":
param2 = area.value; param2 = <string>area.value?.toString();
break; break;
case "subAreaId": case "subAreaId":
param2 = subarea.value; param2 = <string>subarea.value?.toString();
break; break;
case "routeId": case "routeId":
param2 = rgMode.value; param2 = rgMode.value;

@ -65,9 +65,9 @@
</div> </div>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="确认新密码密码" prop="lastPwd"> <el-form-item label="确认新密码" prop="lastPwd">
<el-input <el-input
placeholder="请输入新密码密码" placeholder="请输入新密码"
v-model="formData.lastPwd" v-model="formData.lastPwd"
type="password" type="password"
show-password show-password

Loading…
Cancel
Save