新增tr069

master
李小林 10 months ago
parent 20f28f2a55
commit 6e2f8da03f
  1. 26
      src/api/device-type-ver/index.ts
  2. 9
      src/api/device-type-ver/types.ts
  3. 50
      src/api/device-type/index.ts
  4. 9
      src/api/file/index.ts
  5. 11
      src/api/file/types.ts
  6. 45
      src/api/tr069/index.ts
  7. 26
      src/api/tr069/types.ts
  8. 1
      src/assets/icons/document_tree.svg
  9. 4
      src/components/Table/TableBar.vue
  10. 7
      src/router/index.ts
  11. 93
      src/views/resources/device-type/components/AddDevTypeVersion.vue
  12. 4
      src/views/resources/device-type/components/AddDomianTree.vue
  13. 20
      src/views/resources/device-type/components/AddFile.vue
  14. 48
      src/views/resources/device-type/components/DeviceTypeToVer.vue
  15. 76
      src/views/resources/device-type/components/DeviceTypeVersionEdit.vue
  16. 113
      src/views/resources/device-type/index.vue
  17. 112
      src/views/resources/tr069/components/AddTr069File.vue
  18. 198
      src/views/resources/tr069/components/Tr069Tree.vue
  19. 115
      src/views/resources/tr069/index.vue

@ -1,8 +1,8 @@
import { import {
DeviceTypeToVerPageResult, DeviceTypeToVerPageResult,
DeviceTypeToVerQuery, DeviceTypeToVerQuery,
DeviceTypeVerForm, DeviceTypeVerForm, DevVerServicePageResult,
GroupNamePageResult, GroupNamePageResult
} from "@/api/device-type-ver/types"; } from "@/api/device-type-ver/types";
import request from "@/utils/request"; import request from "@/utils/request";
import { AxiosPromise } from "axios"; import { AxiosPromise } from "axios";
@ -121,4 +121,24 @@ export function editVerDomain(typeAndVerId: number, data: number[]) {
method: "POST", method: "POST",
data, data,
}); });
}; }
export function pageService(
data: PageQuery,
typeAndVerId: number
): AxiosPromise<DevVerServicePageResult> {
return request({
url: `/api/device-type-ver/v1/page-service/${typeAndVerId}`,
method: "GET",
params: {
pageNum: data.pageNum,
pageSize: data.pageSize,
},
});
}
export function addTypeVer(devTypeId: number, data: DeviceTypeVerForm) {
return request({
url: `/api/device-type-ver/v1/add-type-ver/${devTypeId}`,
method: "POST",
data,
});
}

@ -32,3 +32,12 @@ export interface DeviceTypeVerForm {
} }
export type GroupNamePageResult = PageResult<string[]>; export type GroupNamePageResult = PageResult<string[]>;
export interface DeviceServiceVO {
servId?: number;
servName?: string;
servVerName?: string;
servDisplayName?: string;
servDesc?: string;
}
export type DevVerServicePageResult = PageResult<DeviceServiceVO[]>;

@ -22,3 +22,53 @@ export function findDevTypeById(devTypeId: number): AxiosPromise<DeviceTypeVO> {
method: "GET", method: "GET",
}); });
} }
export function getVendorNameOption(): AxiosPromise<OptionType[]> {
return request({
url: `/api/dev-type/v1/vendor-name-option`,
method: "GET",
});
}
export function getVendorOuiOption(
vendorName?: string
): AxiosPromise<OptionType[]> {
return request({
url: `/api/dev-type/v1/vendor-oui-option/`,
method: "GET",
params: {
vendorName,
},
});
}
export function getTypeNameOption(
vendorOui?: string
): AxiosPromise<OptionType[]> {
return request({
url: `/api/dev-type/v1/type-name-option/`,
method: "GET",
params: {
vendorOui,
},
});
}
export function getHardVerOption(
typeName?: string
): AxiosPromise<OptionType[]> {
return request({
url: `/api/dev-type/v1/hard-ver-option/`,
method: "GET",
params: {
typeName: typeName,
},
});
}
export function deleteDevTypeByIds(ids: number[]) {
return request({
url: `/api/dev-type/v1/deletes/`,
method: "POST",
data: ids,
});
}

@ -1,5 +1,6 @@
import request from "@/utils/request"; import request from "@/utils/request";
import { AxiosPromise } from "axios"; import { AxiosPromise } from "axios";
import { Tr069XmlFileForm } from "@/api/file/types";
/** /**
* *
@ -29,3 +30,11 @@ export function uploadApi(
}, },
}); });
} }
export function addTr069FileRecord(data: Tr069XmlFileForm) {
return request({
url: "/api/file_list/v1/add",
method: "POST",
data,
});
}

@ -7,9 +7,18 @@ export interface FileInfo {
} }
export interface VendorProfile { export interface VendorProfile {
typeAndVerId?: number;
typeAndVerId?:number; fileName?: string;
fileDesc?: string;
fileType?: string;
fileUrl?: string;
}
export interface Tr069XmlFileForm {
fileName?: string; fileName?: string;
fileDesc?: string; fileDesc?: string;

@ -0,0 +1,45 @@
import request from "@/utils/request";
import { AxiosPromise } from "axios";
import { Tr069VerForm, Tr069VerPageResult, Tr069Xml } from "@/api/tr069/types";
export function getTr069Page(
data: PageQuery
): AxiosPromise<Tr069VerPageResult> {
return request({
url: "/api/tr069/v1/page",
method: "POST",
data,
});
}
export function getTr069XmlTree(fileId?: number): AxiosPromise<Tr069Xml> {
return request({
url: `/api/tr069/v1/tree/${fileId}`,
method: "get",
});
}
export function getTr069XmlOption(): AxiosPromise<OptionType[]> {
return request({
url: `/api/tr069/v1/tr069-model/option`,
method: "get",
});
}
export function getTr069Form(tr069VerId: number): AxiosPromise<Tr069VerForm> {
return request({
url: `/api/tr069/v1/${tr069VerId}`,
method: "get",
});
}
export function editTr069(data: Tr069VerForm) {
return request({
url: `/api/tr069/v1/edit`,
method: "POST",
data,
});
}
export function addTr069(data: Tr069VerForm){
return request({
url: `/api/tr069/v1/add`,
method: "POST",
data,
});
}

@ -0,0 +1,26 @@
export interface Tr069VerVO {
tr069VerId?: number;
tr069VerName?: string;
tr069VerDesc?: string;
fileName?: string;
fileId?: number;
}
export type Tr069VerPageResult = PageResult<Tr069VerVO[]>;
export interface Tr069VerForm {
tr069VerId?: number;
tr069VerName?: string;
tr069VerDesc?: string;
fileId?: number;
}
export interface Tr069Xml {
tagName?: string;
read?: string;
write?: string;
type?: string;
children?: Array<Tr069Xml>;
}

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1715668787167" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6119" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M807.64 733.83H691.45V618.64h101.87c2.42 0 4.84-0.13 7.24-0.4 8.77-0.96 17.03-4.6 24.1-9.89l33.89-32.66v107.23c0 28.12-22.79 50.91-50.91 50.91z" fill="#00c3ee" p-id="6120"></path><path d="M663.34 733.83c-2.98 13.27-14.79 23.21-28.96 23.21h-410.7c-14.17 0-25.98-9.94-28.96-23.21h-28.87v86.12c0 32.4 26.26 58.66 58.66 58.66h408.3c32.4 0 58.66-26.26 58.66-58.66v-86.12h-28.13z" fill="#00c3ee" p-id="6121"></path><path d="M806.27 737.83h-24.06c-2.21 0-4-1.79-4-4s1.79-4 4-4h24.06c25.48 0 46.21-24.36 46.21-54.31V173.31c0-29.95-20.73-54.31-46.21-54.31H440.81c-20.13 0-37.81 15.13-43.99 37.64-0.58 2.13-2.78 3.38-4.92 2.8-2.13-0.58-3.38-2.79-2.8-4.92 7.15-26.04 27.92-43.53 51.71-43.53h365.46c29.89 0 54.21 27.95 54.21 62.31v502.21c0 34.37-24.32 62.32-54.21 62.32z" fill="#00c3ee" p-id="6122"></path><path d="M633.08 882.61H224.21c-34.39 0-62.37-27.98-62.37-62.37V506.19c0-2.21 1.79-4 4-4s4 1.79 4 4v314.05c0 29.98 24.39 54.37 54.37 54.37h408.88c29.98 0 54.37-24.39 54.37-54.37V429.56H553.41c-19.28 0-31.09-4.43-38.31-14.36-6.4-8.81-9.02-21.49-9.02-43.78V245.73H224.21c-29.98 0-54.37 24.39-54.37 54.37v38.65c0 2.21-1.79 4-4 4s-4-1.79-4-4V300.1c0-34.39 27.98-62.37 62.37-62.37h285.88c1.06 0 2.08 0.42 2.83 1.17s1.17 1.77 1.17 2.83v129.69c0 39.36 8.45 50.14 39.33 50.14h138.04c2.21 0 4 1.79 4 4v394.68c-0.01 34.39-27.98 62.37-62.38 62.37z" fill="#00c3ee" p-id="6123"></path><path d="M165.84 429.7c-2.21 0-4-1.79-4-4v-3.66c0-2.21 1.79-4 4-4s4 1.79 4 4v3.66c0 2.21-1.8 4-4 4zM691.45 429.56c-1.03 0-2.06-0.4-2.85-1.19L507.24 244.54a4.008 4.008 0 0 1 0.04-5.66 4.008 4.008 0 0 1 5.66 0.04L694.3 422.75a4.008 4.008 0 0 1-0.04 5.66c-0.78 0.77-1.79 1.15-2.81 1.15z" fill="#00c3ee" p-id="6124"></path></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

@ -46,7 +46,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { Operation, Refresh, Search } from "@element-plus/icons-vue"; import { Operation, Refresh, Search } from "@element-plus/icons-vue";
const emit = defineEmits([ "changeColumns"]); const emit = defineEmits(["changeColumns", "loadRefresh"]);
const props = defineProps({ const props = defineProps({
showTop: { showTop: {
@ -74,7 +74,7 @@ const columnChange = ref<boolean>(false);
// //
function refresh() { function refresh() {
console.log(); emit("loadRefresh");
} }
const buttonRef = ref(); const buttonRef = ref();
const popoverRef = ref(); const popoverRef = ref();

@ -80,6 +80,13 @@ export const constantRoutes: RouteRecordRaw[] = [
), ),
meta: { hidden: true, keepAlive: true, title: "设备类型软件编辑" }, meta: { hidden: true, keepAlive: true, title: "设备类型软件编辑" },
}, },
{
path: "/resources/tr069-tree/:tr069VerId/:fileId",
name: "Tr069Tree",
component: () =>
import("@/views/resources/tr069/components/Tr069Tree.vue"),
meta: { hidden: true, keepAlive: true, title: "TR069参数树" },
},
], ],
}, },
]; ];

@ -0,0 +1,93 @@
<template>
<el-dialog
class="com-dialog"
v-model="addDevTypeVerFlag"
title="新增设备类型软件版本信息"
>
<el-form
ref="addDevTypeVerFormRef"
:rules="rules"
:model="formData"
v-loading="loading"
label-position="top"
>
<el-form-item label="设备类型软件版本名称" prop="softVer">
<el-input v-model="formData.softVer" />
</el-form-item>
<el-form-item label="TR069协议版本" prop="specVer">
<el-input v-model="formData.specVer" />
</el-form-item>
<el-form-item label="适用流程" prop="provisionFlag">
<dictionary
type-code="provision_flag"
v-model="formData.provisionFlag"
/>
</el-form-item>
<el-form-item label="设备类型软件版本描述" prop="provisionFlag">
<el-input v-model="formData.devTypeVerDesc" type="textarea" />
</el-form-item>
</el-form>
<template #footer>
<el-button type="primary" @click="submitForm(addDevTypeVerFormRef)"
>确认</el-button
>
<el-button>取消</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { DeviceTypeVerForm } from "@/api/device-type-ver/types";
import { FormInstance, FormRules } from "element-plus";
import { addTypeVer } from "@/api/device-type-ver";
const addDevTypeVerFlag = ref<boolean>(false);
const loading = ref<boolean>(false);
const devTypeId = ref<number>(0);
const open = (devTypeId_: number) => {
resetForm(addDevTypeVerFormRef.value);
devTypeId.value = devTypeId_;
formData.value = { provisionFlag: "0" };
addDevTypeVerFlag.value = true;
};
defineExpose({ open });
const formData = ref<DeviceTypeVerForm>({
provisionFlag: "0",
});
const addDevTypeVerFormRef = ref<FormInstance>();
const rules = reactive<FormRules<DeviceTypeVerForm>>({
softVer: [
{ required: true, message: "请输入设备类型软件版本名称", trigger: "blur" },
],
specVer: [
{ required: true, message: "请输入TR069协议版本", trigger: "blur" },
],
});
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.resetFields();
};
const emit = defineEmits(["success"]);
const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
await formEl.validate((valid, fields) => {
if (valid) {
loading.value = true;
addTypeVer(devTypeId.value, formData.value)
.then(() => {
emit("success");
addDevTypeVerFlag.value = false;
})
.finally(() => {
loading.value = false;
});
}
});
};
</script>
<style scoped></style>

@ -14,7 +14,7 @@
</div> </div>
<template #footer> <template #footer>
<el-button type="primary" @click="submit">确定</el-button> <el-button type="primary" @click="submit">确定</el-button>
<el-button>取消</el-button> <el-button @click="openDomainTreeFlag = false">取消</el-button>
</template> </template>
</el-dialog> </el-dialog>
</template> </template>
@ -27,7 +27,7 @@ import { editVerDomain, listVerDomain } from "@/api/device-type-ver";
const loading = ref<boolean>(false); const loading = ref<boolean>(false);
const openDomainTreeFlag = ref<boolean>(false); const openDomainTreeFlag = ref<boolean>(false);
const typeAndVerId = ref<number>(0); const typeAndVerId = ref<number>(0);
const openDomainTree = (typeAndVerId_?: number) => { const openDomainTree = (typeAndVerId_: number) => {
openDomainTreeFlag.value = true; openDomainTreeFlag.value = true;
typeAndVerId.value = typeAndVerId_; typeAndVerId.value = typeAndVerId_;
loadResource(); loadResource();

@ -3,7 +3,7 @@
class="com-dialog" class="com-dialog"
v-model="vendorProfileFlag" v-model="vendorProfileFlag"
align-center align-center
title="新增厂商配置文件信息" :title="title"
> >
<el-form <el-form
ref="addVendorProfileRef" ref="addVendorProfileRef"
@ -13,12 +13,12 @@
> >
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
<el-form-item label="厂商配置文件名称" prop="fileName"> <el-form-item label="文件名称" prop="fileName">
<el-input v-model="formData.fileName" /> <el-input v-model="formData.fileName" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="厂商配置文件描述信息"> <el-form-item label="文件描述信息">
<el-input v-model="formData.fileDesc" type="textarea" :rows="1" /> <el-input v-model="formData.fileDesc" type="textarea" :rows="1" />
</el-form-item> </el-form-item>
</el-col> </el-col>
@ -38,7 +38,7 @@
<el-button type="primary" @click="handleUpload(addVendorProfileRef)" <el-button type="primary" @click="handleUpload(addVendorProfileRef)"
>保存</el-button >保存</el-button
> >
<el-button>取消</el-button> <el-button @click="vendorProfileFlag = false">取消</el-button>
</template> </template>
</el-dialog> </el-dialog>
</template> </template>
@ -54,15 +54,17 @@ const loading = ref<boolean>(false);
const vendorProfileFlag = ref<boolean>(false); const vendorProfileFlag = ref<boolean>(false);
const addVendorProfileRef = ref(); const addVendorProfileRef = ref();
const fileList = ref<UploadUserFile[]>([]); const fileList = ref<UploadUserFile[]>([]);
const formData = ref<VendorProfile>({ const formData = ref<VendorProfile>({});
fileType: "1", const title = ref<string>("");
}); const open = (typeAndVerId?: number, fileType_?: string, title_?: string) => {
const open = (typeAndVerId?: number) => {
resetForm(addVendorProfileRef.value); resetForm(addVendorProfileRef.value);
fileList.value = []; fileList.value = [];
formData.value = { formData.value = {
fileType: "1", fileType: fileType_,
}; };
if (title_ != null) {
title.value = title_;
}
vendorProfileFlag.value = true; vendorProfileFlag.value = true;
formData.value.typeAndVerId = typeAndVerId; formData.value.typeAndVerId = typeAndVerId;
}; };

@ -55,6 +55,17 @@
</el-descriptions-item> </el-descriptions-item>
</el-descriptions> </el-descriptions>
</div> </div>
<div class="mt-4">
<div style="display: flex; justify-content: space-between">
<div style="font-weight: 700">设备类型对应的设备软件版本列表</div>
<div>
<el-button type="primary" @click="openAddTypeVer">
<i-ep-plus />
增加设备类型软件版本
</el-button>
</div>
</div>
</div>
<div class="any-table mt" v-loading="loading"> <div class="any-table mt" v-loading="loading">
<el-table <el-table
:data="tableData" :data="tableData"
@ -69,7 +80,7 @@
@click="redirect(scope.row.typeAndVerId)" @click="redirect(scope.row.typeAndVerId)"
link link
> >
{{scope.row.softVer}} {{ scope.row.softVer }}
</el-button> </el-button>
</template> </template>
</el-table-column> </el-table-column>
@ -82,7 +93,13 @@
@click="handleDownload(scope.row.fileId)" @click="handleDownload(scope.row.fileId)"
>{{ scope.row.fileName }} >{{ scope.row.fileName }}
</el-button> </el-button>
<el-button type="danger" link v-else>上传文件</el-button> <el-button
type="danger"
@click="openAddVerFile(scope.row.typeAndVerId)"
link
v-else
>上传文件</el-button
>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@ -147,11 +164,13 @@
</el-table-column> </el-table-column>
<el-table-column label="操作" width="200" align="center"> <el-table-column label="操作" width="200" align="center">
<template #default="scope"> <template #default="scope">
<el-tooltip content="该类型其它OUI软件情况" placement="top"> <!-- <el-tooltip content="该类型其它OUI软件情况" placement="top">-->
<el-button type="primary" link> <!-- <el-button type="primary" link>-->
<el-icon size="16px"><View /></el-icon> <!-- <el-icon size="16px">-->
</el-button> <!-- <View />-->
</el-tooltip> <!-- </el-icon>-->
<!-- </el-button>-->
<!-- </el-tooltip>-->
<el-tooltip content="复制软件版本" placement="top"> <el-tooltip content="复制软件版本" placement="top">
<el-button <el-button
type="primary" type="primary"
@ -196,6 +215,11 @@
/> />
</div> </div>
</el-card> </el-card>
<add-file ref="addTypeVerFileRef" @success="loadDeviceTypeToVerPage" />
<add-dev-type-version
ref="addDevTypeVerRef"
@success="loadDeviceTypeToVerPage"
/>
</div> </div>
</template> </template>
@ -217,6 +241,8 @@ import { findDevTypeById } from "@/api/device-type";
import { downloadFileApi } from "@/api/file"; import { downloadFileApi } from "@/api/file";
import { downloadHook } from "@/utils"; import { downloadHook } from "@/utils";
import { DocumentCopy, InfoFilled, View } from "@element-plus/icons-vue"; import { DocumentCopy, InfoFilled, View } from "@element-plus/icons-vue";
import AddDevTypeVersion from "@/views/resources/device-type/components/AddDevTypeVersion.vue";
import AddFile from "@/views/resources/device-type/components/AddFile.vue";
const loading = ref<boolean>(false); const loading = ref<boolean>(false);
const voLoading = ref<boolean>(false); const voLoading = ref<boolean>(false);
@ -329,6 +355,14 @@ const redirect = (typeAndVerId: number) => {
path: `/resources/device_type_version_edit/${devTypeId}/${typeAndVerId}`, path: `/resources/device_type_version_edit/${devTypeId}/${typeAndVerId}`,
}); });
}; };
const addDevTypeVerRef = ref();
const openAddTypeVer = () => {
addDevTypeVerRef.value.open(devTypeId);
};
const addTypeVerFileRef = ref();
const openAddVerFile = (typeAndVerId?: number) => {
addTypeVerFileRef.value.open(typeAndVerId, "0", "新增设备软件版本文件");
};
onMounted(() => { onMounted(() => {
loadDevTypeById(); loadDevTypeById();
loadDeviceTypeToVerPage(); loadDeviceTypeToVerPage();

@ -1,7 +1,7 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-card shadow="never"> <el-card shadow="never">
<el-scrollbar height="550px"> <el-scrollbar height="570px">
<el-form <el-form
:model="formData" :model="formData"
ref="typeVerFormRef" ref="typeVerFormRef"
@ -496,32 +496,72 @@
/> />
</div> </div>
</div> </div>
<div class="mt-4">
<div style="display: flex; justify-content: space-between">
<div style="font-weight: 700">
设备类型及设备软件版本支持的业务信息列表
</div>
</div>
<div class="any-table mt-4">
<el-table :data="serviceList" v-loading="loadingService">
<el-table-column
label="业务名称"
prop="servName"
align="center"
/>
<el-table-column
label="业务版本"
prop="servVerName"
align="center"
/>
<el-table-column
label="业务显示名称"
prop="servDisplayName"
align="center"
/>
<el-table-column
label="业务描述"
prop="servDesc"
align="center"
/>
</el-table>
<pagination
v-if="totalService > 0"
v-model:total="totalService"
v-model:page="serviceQuery.pageNum"
v-model:limit="serviceQuery.pageSize"
@pagination="loadService"
/>
</div>
</div>
</el-scrollbar> </el-scrollbar>
</el-card> </el-card>
<add-vendor-profile <add-file ref="vendorProfileRef" @success="loadVendorProfileList" />
ref="vendorProfileRef"
@success="loadVendorProfileList"
/>
<add-domian-tree ref="domainTreeRef" @success="loadDomainPage" /> <add-domian-tree ref="domainTreeRef" @success="loadDomainPage" />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { DeviceTypeVerForm } from "@/api/device-type-ver/types"; import {
DeviceServiceVO,
DeviceTypeVerForm,
} from "@/api/device-type-ver/types";
import { import {
deleteVendorProfile, deleteVendorProfile,
editDevTypeVerForm, editDevTypeVerForm,
findDevTypeVerEditForm, findDevTypeVerEditForm,
listVendorProfile, listVendorProfile,
pageService,
pageSysDomain, pageSysDomain,
} from "@/api/device-type-ver"; } from "@/api/device-type-ver";
import { EditPen, InfoFilled } from "@element-plus/icons-vue"; import { EditPen, InfoFilled } from "@element-plus/icons-vue";
import { FormInstance, FormRules } from "element-plus"; import { FormInstance, FormRules } from "element-plus";
import { editCapabilityForm, getCapabilityForm } from "@/api/type-ver-ext"; import { editCapabilityForm, getCapabilityForm } from "@/api/type-ver-ext";
import { CapabilityForm } from "@/api/type-ver-ext/types"; import { CapabilityForm } from "@/api/type-ver-ext/types";
import AddVendorProfile from "@/views/resources/device-type/components/AddVendorProfile.vue"; import AddVendorProfile from "@/views/resources/device-type/components/AddFile.vue";
import { FileListVO } from "@/api/file-list/types"; import { FileListVO } from "@/api/file-list/types";
import AddDomianTree from "@/views/resources/device-type/components/AddDomianTree.vue"; import AddDomianTree from "@/views/resources/device-type/components/AddDomianTree.vue";
import AddFile from "@/views/resources/device-type/components/AddFile.vue";
const loading = ref<boolean>(false); const loading = ref<boolean>(false);
const route = useRoute(); const route = useRoute();
@ -606,7 +646,7 @@ const loadFormData = async () => {
}; };
const vendorProfileRef = ref(); const vendorProfileRef = ref();
const openVendorProfile = () => { const openVendorProfile = () => {
vendorProfileRef.value.open(typeAndVerId); vendorProfileRef.value.open(typeAndVerId, "1", "新增厂商配置文件信息");
}; };
const loadVendorProfileList = async () => { const loadVendorProfileList = async () => {
@ -652,11 +692,31 @@ const loadDomainPage = async () => {
const openDomainTree = () => { const openDomainTree = () => {
domainTreeRef.value.openDomainTree(typeAndVerId); domainTreeRef.value.openDomainTree(typeAndVerId);
}; };
//service
const loadingService = ref<boolean>(false);
const totalService = ref<number>(0);
const serviceList = ref<DeviceServiceVO[]>([]);
const serviceQuery = ref<PageQuery>({
pageNum: 1,
pageSize: 10,
});
const loadService = async () => {
loadingService.value = true;
await pageService(serviceQuery.value, typeAndVerId)
.then(({ data }) => {
serviceList.value = data.list;
totalService.value = data.total;
})
.finally(() => {
loadingService.value = false;
});
};
onMounted(() => { onMounted(() => {
loadFormData(); loadFormData();
loadCapabilityForm(); loadCapabilityForm();
loadVendorProfileList(); loadVendorProfileList();
loadDomainPage(); loadDomainPage();
loadService();
}); });
</script> </script>

@ -69,14 +69,20 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
<el-card> <el-card shadow="never">
<template #header> <template #header>
<div class="table-head-parent"> <div class="table-head-parent">
<div> <div>
<el-button type="primary" plain><i-ep-plus />新增</el-button> <el-button type="primary" plain><i-ep-plus />新增</el-button>
<el-button type="danger" plain><i-ep-delete />删除</el-button> <el-button type="danger" plain @click="handleDeletes"
><i-ep-delete />删除</el-button
>
</div> </div>
<table-bar :columns="columns" @change-columns="changeColumns" /> <table-bar
:columns="columns"
@load-refresh="loadDeviceTypePage"
@change-columns="changeColumns"
/>
</div> </div>
</template> </template>
<div class="any-table"> <div class="any-table">
@ -86,7 +92,9 @@
v-loading="loading" v-loading="loading"
highlight-current-row highlight-current-row
style="width: 100%" style="width: 100%"
@selection-change="handleSelectionChange"
> >
<el-table-column type="selection" width="55" />
<el-table-column <el-table-column
fixed fixed
label="设备供应商" label="设备供应商"
@ -96,7 +104,12 @@
v-if="columns[0].show" v-if="columns[0].show"
> >
<template #default="scope"> <template #default="scope">
<el-button type="primary" link @click="redirect(scope.row.devTypeId)">{{ scope.row.devVendorName }}</el-button> <el-button
type="primary"
link
@click="redirect(scope.row.devTypeId)"
>{{ scope.row.devVendorName }}</el-button
>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@ -134,7 +147,7 @@
v-if="columns[5].show" v-if="columns[5].show"
/> />
<el-table-column <el-table-column
label="TR069数据模型版本" label="TR069模型版本"
prop="tr069VerName" prop="tr069VerName"
align="center" align="center"
v-if="columns[6].show" v-if="columns[6].show"
@ -160,7 +173,14 @@
<script setup lang="ts"> <script setup lang="ts">
import { DeviceTypePageVO, DeviceTypeQuery } from "@/api/device-type/types"; import { DeviceTypePageVO, DeviceTypeQuery } from "@/api/device-type/types";
import { getDeviceTypePage } from "@/api/device-type"; import {
deleteDevTypeByIds,
getDeviceTypePage,
getHardVerOption,
getTypeNameOption,
getVendorNameOption,
getVendorOuiOption,
} from "@/api/device-type";
defineOptions({ defineOptions({
name: "DeviceType", name: "DeviceType",
inheritAttrs: false, inheritAttrs: false,
@ -181,6 +201,10 @@ const changeColumns = (newColumns: TableColumns[]) => {
}; };
const total = ref<number>(0); const total = ref<number>(0);
const searchForm = ref<DeviceTypeQuery>({ const searchForm = ref<DeviceTypeQuery>({
devTypeName: "",
devVendorOui: "",
devHardVer: "",
devVendorName: "",
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
}); });
@ -189,7 +213,78 @@ const vendorOuiOption = ref<OptionType[]>([]);
const typeNameOption = ref<OptionType[]>([]); const typeNameOption = ref<OptionType[]>([]);
const hardVerOption = ref<OptionType[]>([]); const hardVerOption = ref<OptionType[]>([]);
const tableData = ref<DeviceTypePageVO[]>([]); const tableData = ref<DeviceTypePageVO[]>([]);
const multipleSelection = ref<DeviceTypePageVO[]>([]);
const handleSelectionChange = (val: DeviceTypePageVO[]) => {
multipleSelection.value = val;
};
const handleDeletes = () => {
if (multipleSelection.value.length === 0) {
ElMessage.error("请至少选择一条记录来删除");
return;
}
ElMessageBox.confirm("该操作将永久删除该数据,是否继续?", "Warning", {
confirmButtonText: "确认",
cancelButtonText: "取消",
type: "warning",
}).then(() => {
let ids: number[] = [];
multipleSelection.value.forEach((obj) => {
ids.push(<number>obj.devTypeId);
});
deleteDevTypeByIds(ids).then(() => {
ElMessage.success("操作成功");
loadDeviceTypePage();
});
});
};
watch(
() => searchForm.value.devVendorName,
() => {
if (searchForm.value.devVendorName === undefined) {
return;
}
loadVendorOuiOption();
}
);
watch(
() => searchForm.value.devVendorOui,
() => {
if (searchForm.value.devVendorOui === undefined) {
return;
}
loadTypeNameOption();
}
);
watch(
() => searchForm.value.devTypeName,
() => {
if (searchForm.value.devTypeName === undefined) {
return;
}
loadHardVerOption();
}
);
const loadVendorNameOption = async () => {
await getVendorNameOption().then(({ data }) => {
vendorNameOption.value = data;
});
};
const loadVendorOuiOption = async () => {
await getVendorOuiOption(searchForm.value.devVendorName).then(({ data }) => {
vendorOuiOption.value = data;
});
};
const loadTypeNameOption = async () => {
await getTypeNameOption(searchForm.value.devVendorOui).then(({ data }) => {
typeNameOption.value = data;
});
};
const loadHardVerOption = async () => {
await getHardVerOption(searchForm.value.devTypeName).then(({ data }) => {
hardVerOption.value = data;
});
};
const loadDeviceTypePage = () => { const loadDeviceTypePage = () => {
loading.value = true; loading.value = true;
getDeviceTypePage(searchForm.value) getDeviceTypePage(searchForm.value)
@ -207,6 +302,12 @@ const redirect = (devTypeId: number) => {
path: `/resources/device_type_to_ver/${devTypeId}`, path: `/resources/device_type_to_ver/${devTypeId}`,
}); });
}; };
onMounted(() => {
loadVendorNameOption();
loadVendorOuiOption();
loadTypeNameOption();
loadHardVerOption();
});
</script> </script>
<style scoped></style> <style scoped></style>

@ -0,0 +1,112 @@
<template>
<el-dialog
class="com-dialog"
v-model="tr069XmlFlag"
align-center
:title="title"
>
<el-form
ref="addVendorProfileRef"
v-loading="loading"
:rules="rules"
:model="formData"
>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="文件名称" prop="fileName">
<el-input v-model="formData.fileName" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="文件描述信息">
<el-input v-model="formData.fileDesc" type="textarea" :rows="1" />
</el-form-item>
</el-col>
</el-row>
<el-upload
drag
action="#"
:limit="1"
:auto-upload="false"
v-model:file-list="fileList"
accept=".xml"
>
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">拖拽上传 <em>点击上传</em></div>
</el-upload>
</el-form>
<template #footer>
<el-button type="primary" @click="handleUpload(addVendorProfileRef)"
>保存</el-button
>
<el-button @click="tr069XmlFlag = false">取消</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { UploadFilled } from "@element-plus/icons-vue";
import { Tr069XmlFileForm, VendorProfile } from "@/api/file/types";
import { FormInstance, FormRules, UploadUserFile } from "element-plus";
import { addTr069FileRecord, uploadApi } from "@/api/file";
const loading = ref<boolean>(false);
const tr069XmlFlag = ref<boolean>(false);
const addVendorProfileRef = ref();
const fileList = ref<UploadUserFile[]>([]);
const formData = ref<Tr069XmlFileForm>({});
const title = ref<string>("");
const open = (fileType_?: string, title_?: string) => {
resetForm(addVendorProfileRef.value);
fileList.value = [];
formData.value = {
fileType: fileType_,
};
if (title_ != null) {
title.value = title_;
}
tr069XmlFlag.value = true;
};
defineExpose({ open });
const rules = reactive<FormRules<VendorProfile>>({
fileName: [{ required: true, message: "请填写文件名称", trigger: "blur" }],
});
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.resetFields();
};
const handleUpload = async (formEl: FormInstance | undefined) => {
if (fileList.value.length === 0) {
ElMessage.error("请选择文件上传");
return;
}
if (!formEl) return;
await formEl.validate((valid, fields) => {
if (valid) {
loading.value = true;
const file = fileList.value[0].raw;
const dotIndex: any = file?.name.lastIndexOf(".");
if (dotIndex === -1) {
ElMessage.error("文件没有后缀,无法上传");
return;
}
const fileName = formData.value.fileName;
const fileType = formData.value.fileType;
formData.value.fileName =
fileName + "." + file?.name.substring(dotIndex + 1);
uploadApi(file, fileName, fileType)
.then(({ data }) => {
formData.value.fileUrl = data;
addTr069FileRecord(formData.value).then(() => {
tr069XmlFlag.value = false;
});
})
.finally(() => {
loading.value = false;
});
}
});
};
</script>
<style scoped></style>

@ -0,0 +1,198 @@
<template>
<div class="app-container">
<el-card shadow="never">
<el-form
:model="formData"
:rules="rules"
v-loading="loadingForm"
ref="tr069FormRef"
>
<el-descriptions title="TR-069参数树模型" :column="2" border>
<template #extra>
<el-button type="primary" @click="submitForm(tr069FormRef)"
><el-icon><EditPen /></el-icon></el-button
>
</template>
<el-descriptions-item
label="TR-069数据模型版本"
label-align="left"
align="center"
label-class-name="my-label"
class-name="my-content"
width="150px"
>
<el-form-item style="margin-bottom: 0" prop="fileId">
<el-select v-model="formData.fileId">
<el-option
v-for="item in tr069FileOption"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item
label="TR-069数据模型版本名称"
label-align="left"
align="center"
label-class-name="my-label"
class-name="my-content"
width="150px"
>
<el-form-item prop="tr069VerName" style="margin-bottom: 0">
<el-input v-model="formData.tr069VerName" />
</el-form-item>
</el-descriptions-item>
<el-descriptions-item
label="TR-069描述"
label-align="left"
align="center"
label-class-name="my-label"
class-name="my-content"
width="150px"
>
<el-form-item prop="tr069VerDesc" style="margin-bottom: 0">
<el-input type="textarea" v-model="formData.tr069VerDesc" />
</el-form-item>
</el-descriptions-item>
</el-descriptions>
</el-form>
<div class="tree">
<el-scrollbar max-height="300">
<el-tree
ref="folderTreeRef"
v-loading="treeLoading"
:highlight-current="true"
:data="treeList"
:props="{ children: 'children', label: 'tagName', disabled: '' }"
:expand-on-click-node="false"
default-expand-all
>
<template #default="{ node }">
<div class="custom-tree-node">
<span>
<span>
<svg-icon class="mr-5px" icon-class="folder" />
</span>
<span>{{ node.label }}</span>
</span>
</div>
</template>
</el-tree>
</el-scrollbar>
</div>
</el-card>
</div>
</template>
<script setup lang="ts">
import { Tr069VerForm, Tr069Xml } from "@/api/tr069/types";
import { EditPen } from "@element-plus/icons-vue";
import {
addTr069,
editTr069,
getTr069Form,
getTr069XmlOption,
getTr069XmlTree
} from "@/api/tr069";
import { FormInstance, FormRules } from "element-plus";
const route = useRoute();
let tr069VerId: number = parseInt(<string>route.params?.tr069VerId);
let fileId: number = parseInt(<string>route.params?.fileId);
const formData = ref<Tr069VerForm>({});
const treeLoading = ref<boolean>(false);
const treeList = ref<Tr069Xml[]>([]);
const tr069FormRef = ref<FormInstance>();
const rules = reactive<FormRules<Tr069VerForm>>({
fileId: [{ required: true, message: "请选择tr069文件", trigger: "blur" }],
tr069VerName: [
{ required: true, message: "请输入tr069名称", trigger: "blur" },
],
});
const loadTr069Xml = async () => {
treeLoading.value = true;
treeList.value = [];
await getTr069XmlTree(formData.value.fileId)
.then(({ data }) => {
treeList.value.push(data);
})
.finally(() => {
treeLoading.value = false;
});
};
const tr069FileOption = ref<OptionType[]>([]);
const loadTr069FileOption = async () => {
await getTr069XmlOption().then(({ data }) => {
tr069FileOption.value = data;
});
};
const loadingForm = ref<boolean>(false);
const loadTr069FormData = async () => {
loadingForm.value = true;
await getTr069Form(tr069VerId)
.then(({ data }) => {
formData.value = data;
})
.finally(() => {
loadingForm.value = false;
});
};
const handleEdit = () => {
loadingForm.value = true;
editTr069(formData.value)
.then(() => {
ElMessage.success("操作成功");
})
.finally(() => {
loadingForm.value = false;
});
};
const handleAdd = () => {
loadingForm.value = true;
addTr069(formData.value)
.then(() => {
ElMessage.success("操作成功");
})
.finally(() => {
loadingForm.value = false;
});
};
const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
await formEl.validate((valid, fields) => {
if (valid) {
if (tr069VerId !== -999) {
handleEdit();
} else {
handleAdd();
}
}
});
};
watch(
() => formData.value.fileId,
() => {
loadTr069Xml();
}
);
onMounted(() => {
loadTr069FileOption();
if (tr069VerId !== -999) {
formData.value.fileId = fileId;
loadTr069FormData();
}
});
</script>
<style scoped lang="scss">
:deep(.my-label) {
background: var(--el-color-white) !important;
}
.tree {
margin-top: 10px;
border: 1px solid var(--el-border-color-dark);
}
</style>

@ -0,0 +1,115 @@
<template>
<div class="app-container">
<el-card shadow="never">
<template #header>
<div style="display: flex; justify-content: flex-end">
<div>
<el-button type="primary" plain @click="goto(-999, -999)"
><i-ep-plus />新增</el-button
>
<el-button type="primary" @click="openTr069FileForm" plain
><i-ep-plus />导入TR069文件</el-button
>
<el-button @click="loadTr069Page" plain><i-ep-refresh /></el-button>
<el-button type="danger" plain><i-ep-delete />删除</el-button>
</div>
</div>
</template>
<div class="any-table">
<el-table :data="tableData" v-loading="loading">
<el-table-column
label="TR-069数据模型版本名称"
align="center"
prop="tr069VerName"
>
<template #default="scope">
<el-button
type="primary"
@click="goto(scope.row.tr069VerId, scope.row.fileId)"
link
>{{ scope.row.tr069VerName }}</el-button
>
</template>
</el-table-column>
<el-table-column
label="TR-069数据模型版本文件名称"
align="center"
prop="fileName"
>
<template #default="scope">
<el-button
type="primary"
link
@click="handleDownload(scope.row.fileId)"
>{{ scope.row.fileName }}
</el-button>
</template>
</el-table-column>
<el-table-column
label="TR-069数据模型版本描述"
align="center"
prop="tr069VerDesc"
/>
</el-table>
<pagination
v-if="total > 0"
v-model:total="total"
v-model:page="query.pageNum"
v-model:limit="query.pageSize"
@pagination="loadTr069Page"
/>
</div>
</el-card>
<add-tr069-file ref="addTr069FileRef" />
</div>
</template>
<script setup lang="ts">
import { Tr069VerVO } from "@/api/tr069/types";
import { getTr069Page } from "@/api/tr069";
import { downloadFileApi } from "@/api/file";
import { downloadHook } from "@/utils";
import AddTr069File from "@/views/resources/tr069/components/AddTr069File.vue";
defineOptions({
name: "Tr069",
inheritAttrs: false,
});
const loading = ref<boolean>(false);
const tableData = ref<Tr069VerVO[]>([]);
const query = ref<PageQuery>({
pageNum: 1,
pageSize: 10,
});
const total = ref<number>(0);
const loadTr069Page = () => {
loading.value = true;
getTr069Page(query.value)
.then(({ data }) => {
total.value = data.total;
tableData.value = data.list;
})
.finally(() => {
loading.value = false;
});
};
const handleDownload = (fileId: number) => {
downloadFileApi(fileId).then((res) => {
downloadHook(res);
});
};
const router = useRouter();
const goto = (tr069VerId?: number, fileId?: number) => {
router.push({
path: `/resources/tr069-tree/${tr069VerId}/${fileId}`,
});
};
const addTr069FileRef = ref();
const openTr069FileForm = () => {
addTr069FileRef.value.open("3", "新增TR-069数据模型文件");
};
onMounted(() => {
loadTr069Page();
});
</script>
<style scoped></style>
Loading…
Cancel
Save