feat: 设备操作组件新增;删除文件,上传文件

master
李小林 9 months ago
parent 3e8ec67400
commit 0516fe9bdc
  1. 4
      src/api/file/index.ts
  2. 4
      src/api/file/types.ts
  3. 38
      src/api/operate-type/index.ts
  4. 21
      src/api/operate-type/types.ts
  5. 13
      src/router/index.ts
  6. 233
      src/views/resources/operate-type/components/AddOperateType.vue
  7. 135
      src/views/resources/operate-type/components/AddOperateTypeFile.vue
  8. 160
      src/views/resources/operate-type/index.vue
  9. 1
      src/views/resources/service/components/AddPluginFile.vue
  10. 4
      src/views/resources/tr069/components/AddTr069File.vue

@ -1,6 +1,6 @@
import request from "@/utils/request";
import { AxiosPromise } from "axios";
import { Tr069XmlFileForm } from "@/api/file/types";
import { BaseFileForm, Tr069XmlFileForm } from "@/api/file/types";
/**
*
@ -31,7 +31,7 @@ export function uploadApi(
});
}
export function addTr069FileRecord(data: Tr069XmlFileForm) {
export function addFileRecord(data: BaseFileForm): AxiosPromise<number> {
return request({
url: "/api/file_list/v1/add",
method: "POST",

@ -17,8 +17,7 @@ export interface VendorProfile {
fileUrl?: string;
}
export interface Tr069XmlFileForm {
export interface BaseFileForm {
fileName?: string;
fileDesc?: string;
@ -27,3 +26,4 @@ export interface Tr069XmlFileForm {
fileUrl?: string;
}
export interface Tr069XmlFileForm extends BaseFileForm {}

@ -0,0 +1,38 @@
import { AxiosPromise } from "axios";
import {
DevOperateTypeForm,
OperateTypePageResult,
} from "@/api/operate-type/types";
import request from "@/utils/request";
export function operateTypePage(
data: PageQuery
): AxiosPromise<OperateTypePageResult> {
return request({
url: "/api/operate/v1/page",
method: "POST",
data,
});
}
export function AddOperateType(
data: DevOperateTypeForm
): AxiosPromise<OperateTypePageResult> {
return request({
url: "/api/operate/v1/add",
method: "POST",
data,
});
}
export function deleteOperateTypeFile(fileId?: number) {
return request({
url: `/api/operate/v1/delete-operate-file/${fileId}`,
method: "DELETE",
});
}
export function editOperateTypeFile(fileId?: number, operateName?: string) {
return request({
url: `/api/operate/v1/edit-operate-file/${fileId}/${operateName}`,
method: "PUT",
});
}

@ -0,0 +1,21 @@
import { BaseFileForm } from "@/api/file/types";
export interface DevOperateTypeVO {
operateName?: string;
fileName?: string;
remark?: string;
fileId?: number;
fileCreateTime?: string;
userName?: string;
}
export type OperateTypePageResult = PageResult<DevOperateTypeVO[]>;
export interface DevOperateTypeForm {
operateName?: string;
displayName?: string;
remark?: string;
fileId?: number;
}
export interface OperateFileForm extends BaseFileForm {
fileId?: number;
}

@ -182,6 +182,19 @@ export const constantRoutes: RouteRecordRaw[] = [
title: "新增客户",
},
},
{
path: "/resources/dev-operate-type-add",
name: "AddOperateType",
component: () =>
import(
"@/views/resources/operate-type/components/AddOperateType.vue"
),
meta: {
hidden: true,
keepAlive: true,
title: "新增操作组件",
},
},
],
},
];

@ -0,0 +1,233 @@
<template>
<div class="app-container">
<el-card shadow="never">
<template #header>
<div style="display: flex; justify-content: flex-end">
<el-button type="primary" @click="submit">保存</el-button>
</div>
</template>
<el-form
:model="formData"
v-loading="loading"
ref="addOperateFormRef"
:rules="rules"
>
<el-descriptions title="新增操作组件表单" :column="2" border>
<el-descriptions-item
label="操作名称"
label-align="left"
align="center"
label-class-name="my-label"
class-name="my-content"
width="150px"
>
<el-form-item style="margin-bottom: 0" prop="operateName">
<el-input
v-model="formData.operateName"
placeholder="请填写操作名称"
/>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item
label="操作显示名称"
label-align="left"
align="center"
label-class-name="my-label"
class-name="my-content"
width="150px"
>
<el-form-item style="margin-bottom: 0" prop="displayName">
<el-input
v-model="formData.displayName"
placeholder="请填写操作显示名称"
/>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item
label="描述信息"
label-align="left"
align="center"
label-class-name="my-label"
class-name="my-content"
width="150px"
>
<el-form-item style="margin-bottom: 0" prop="remark">
<el-input
type="textarea"
v-model="formData.remark"
placeholder="请填写描述信息"
/>
</el-form-item>
</el-descriptions-item>
</el-descriptions>
</el-form>
<el-form
:model="fileForm"
ref="addFileFormRef"
v-loading="loading"
style="margin-top: 10px"
:rules="fileRules"
>
<el-descriptions title="文件信息表单" :column="2" border>
<el-descriptions-item
label="操作名称"
label-align="left"
align="center"
label-class-name="my-label"
class-name="my-content"
width="150px"
>
<el-form-item style="margin-bottom: 0" prop="fileName">
<el-input
v-model="fileForm.fileName"
placeholder="请填写文件名称"
/>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item
label="操作显示名称"
label-align="left"
align="center"
label-class-name="my-label"
class-name="my-content"
width="150px"
>
<el-form-item style="margin-bottom: 0" prop="fileDesc">
<el-input
type="textarea"
:rows="1"
v-model="fileForm.fileDesc"
placeholder="请填写文件描述信息"
/>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item
label="文件上传"
label-align="left"
align="center"
label-class-name="my-label"
class-name="my-content"
width="150px"
>
<el-upload
drag
action="#"
:limit="1"
:auto-upload="false"
v-model:file-list="fileList"
>
<el-icon class="el-icon--upload">
<upload-filled />
</el-icon>
<div class="el-upload__text">拖拽上传 <em>点击上传</em></div>
</el-upload>
</el-descriptions-item>
</el-descriptions>
</el-form>
</el-card>
</div>
</template>
<script setup lang="ts">
import { DevOperateTypeForm, OperateFileForm } from "@/api/operate-type/types";
import { UploadFilled } from "@element-plus/icons-vue";
import { FormInstance, FormRules, UploadUserFile } from "element-plus";
import { addFileRecord, uploadApi } from "@/api/file";
import { AddOperateType } from "@/api/operate-type";
const formData = ref<DevOperateTypeForm>({});
const fileForm = ref<OperateFileForm>({
fileType: "7",
});
const loading = ref<boolean>(false);
const addOperateFormRef = ref<FormInstance>();
const addFileFormRef = ref<FormInstance>();
const fileList = ref<UploadUserFile[]>([]);
const rules = reactive<FormRules<DevOperateTypeForm>>({
operateName: [
{ required: true, message: "请填写组件操作名称", trigger: "blur" },
],
displayName: [
{ required: true, message: "请填写组件显示名称", trigger: "blur" },
],
});
const fileRules = reactive<FormRules<OperateFileForm>>({
fileName: [{ required: true, message: "请填写文件名称", trigger: "blur" }],
});
const validOperateFormFlag = ref<boolean>(false);
const validFileFormFlag = ref<boolean>(false);
const validOperateForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
await formEl.validate((valid, fields) => {
if (valid) {
validOperateFormFlag.value = true;
}
});
};
const validFileForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
await formEl.validate((valid, fields) => {
if (valid) {
validFileFormFlag.value = true;
}
});
};
const uploadFile = async () => {
const file = fileList.value[0].raw;
const dotIndex: any = file?.name.lastIndexOf(".");
if (dotIndex === -1) {
ElMessage.error("文件没有后缀,无法上传");
return;
}
const fileName = fileForm.value.fileName;
const fileType = fileForm.value.fileType;
fileForm.value.fileName = fileName + "." + file?.name.substring(dotIndex + 1);
loading.value = true;
await uploadApi(file, fileName, fileType).then(({ data }) => {
fileForm.value.fileUrl = data;
submitFileRecord();
});
};
const submitFileRecord = () => {
addFileRecord(fileForm.value).then(({ data }) => {
formData.value.fileId = data;
submitFormData();
});
};
const submitFormData = () => {
AddOperateType(formData.value)
.then(() => {
ElMessage({
message: "操作成功",
type: "success",
duration: 1000,
});
})
.finally(() => {
loading.value = false;
});
};
const submit = async () => {
if (fileList.value.length != 1) {
ElMessage({
message: "请正确上传文件",
type: "error",
duration: 1000,
});
return;
}
await Promise.all([
validOperateForm(addOperateFormRef.value),
validFileForm(addFileFormRef.value),
]);
if (validFileFormFlag.value && validOperateFormFlag.value) {
await uploadFile();
}
};
</script>
<style scoped>
:deep(.my-label) {
background: var(--el-color-white) !important;
}
</style>

@ -0,0 +1,135 @@
<template>
<el-dialog
class="com-dialog"
v-model="operateTypeFlag"
align-center
title="新增设备操作组件文件"
>
<el-form
ref="addOperateFileFormRef"
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"
>
<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(addOperateFileFormRef)"
>保存</el-button
>
<el-button @click="operateTypeFlag = false">取消</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { UploadFilled } from "@element-plus/icons-vue";
import { FormInstance, FormRules, UploadUserFile } from "element-plus";
import { addFileRecord, uploadApi } from "@/api/file";
import { OperateFileForm } from "@/api/operate-type/types";
import { editOperateTypeFile } from "@/api/operate-type";
const loading = ref<boolean>(false);
const operateTypeFlag = ref<boolean>(false);
const addOperateFileFormRef = ref();
const fileList = ref<UploadUserFile[]>([]);
const formData = ref<OperateFileForm>({});
const operateName = ref<string>("");
const open = (operateName_?: string) => {
resetForm(addOperateFileFormRef.value);
fileList.value = [];
formData.value = {
fileType: "7",
};
if (operateName_ != null) {
operateName.value = operateName_;
}
operateTypeFlag.value = true;
};
defineExpose({ open });
const rules = reactive<FormRules<OperateFileForm>>({
fileName: [{ required: true, message: "请填写文件名称", trigger: "blur" }],
});
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.resetFields();
};
const emit = defineEmits(["success"]);
const submitFileRecord = () => {
addFileRecord(formData.value).then(({ data }) => {
formData.value.fileId = data;
updateOperate();
});
};
const updateOperate = () => {
editOperateTypeFile(formData.value.fileId, operateName.value)
.then(() => {
ElMessage({
message: "操作成功",
duration: 1000,
type: "success",
onClose: () => {
emit("success");
operateTypeFlag.value = false;
},
});
})
.finally(() => {
loading.value = false;
});
};
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);
loading.value = true;
uploadApi(file, fileName, fileType)
.then(({ data }) => {
formData.value.fileUrl = data;
submitFileRecord();
})
.finally(() => {
loading.value = false;
});
}
});
};
</script>
<style scoped></style>

@ -0,0 +1,160 @@
<template>
<div class="app-container">
<el-card shadow="never">
<template #header>
<div style="display: flex; justify-content: flex-end">
<el-button type="primary" :icon="Refresh" @click="getData"
>刷新
</el-button>
<el-button type="primary" :icon="Plus" @click="skipAddOperateType"
>新增
</el-button>
<el-button type="danger" :icon="Delete">删除</el-button>
</div>
</template>
<div class="any-table">
<el-table :data="tableData" v-loading="loading" max-height="450">
<el-table-column
label="组件操作名称"
prop="operateName"
align="center"
width="300"
show-overflow-tooltip
/>
<el-table-column
label="组件包名称"
width="300"
prop="fileName"
align="center"
show-overflow-tooltip
>
<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="组件上传时间"
prop="fileCreateTime"
align="center"
/>
<el-table-column label="组件操作者" prop="userName" align="center" />
<el-table-column label="组件描述" prop="remark" align="center" />
<el-table-column label="操作" align="center">
<template #default="scope">
<div v-if="scope.row.fileId != undefined">
<el-popconfirm
width="200"
confirm-button-text="确认"
cancel-button-text="取消"
:icon="InfoFilled"
icon-color="#626AEF"
@confirm="handleDeleteFile(scope.row.fileId)"
title="确认删除该文件吗?"
>
<template #reference>
<el-button type="danger" :icon="Delete" link
>删除文件
</el-button>
</template>
</el-popconfirm>
</div>
<div v-else>
<el-button
@click="openOperateFile(scope.row.operateName)"
type="primary"
:icon="Upload"
link
>上传文件</el-button
>
</div>
</template>
</el-table-column>
</el-table>
<pagination
v-if="total > 0"
v-model:total="total"
v-model:page="queryForm.pageNum"
v-model:limit="queryForm.pageSize"
@pagination="getData"
/>
</div>
</el-card>
<add-operate-type-file ref="operateTypeFileRef" @success="getData" />
</div>
</template>
<script setup lang="ts">
import { DevOperateTypeVO } from "@/api/operate-type/types";
import { deleteOperateTypeFile, operateTypePage } from "@/api/operate-type";
import {
Delete,
InfoFilled,
Plus,
Refresh,
Upload,
} from "@element-plus/icons-vue";
import { downloadFileApi } from "@/api/file";
import { downloadHook } from "@/utils";
import AddOperateTypeFile from "@/views/resources/operate-type/components/AddOperateTypeFile.vue";
defineOptions({
name: "OperateType",
inheritAttrs: false,
});
const tableData = ref<DevOperateTypeVO[]>([]);
const total = ref<number>(0);
const loading = ref<boolean>(false);
const queryForm = ref<PageQuery>({
pageNum: 1,
pageSize: 10,
});
const operateTypeFileRef = ref();
const router = useRouter();
const getData = () => {
loading.value = true;
operateTypePage(queryForm.value)
.then(({ data }) => {
tableData.value = data.list;
total.value = data.total;
})
.finally(() => {
loading.value = false;
});
};
const skipAddOperateType = () => {
router.push({
path: `/resources/dev-operate-type-add`,
});
};
const handleDownload = (fileId: number) => {
downloadFileApi(fileId).then((res) => {
downloadHook(res);
});
};
const handleDeleteFile = (fileId?: number) => {
loading.value = true;
deleteOperateTypeFile(fileId).then(() => {
ElMessage({
message: "操作成功",
type: "success",
duration: 1000,
onClose: () => {
getData();
},
});
});
};
const openOperateFile = (operateName?: string) => {
operateTypeFileRef.value.open(operateName);
};
onMounted(() => {
getData();
});
</script>
<style scoped></style>

@ -62,6 +62,7 @@ const formData = ref<BusinessFile>({
const businessForm = ref<BusinessForm>({});
const open = (servId_: number) => {
businessForm.value.servId = servId_;
formData.value = { fileType: "4" };
resetForm(addPluginFileRef.value);
fileList.value = [];
pluginFileFlag.value = true;

@ -48,7 +48,7 @@
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";
import { addFileRecord, uploadApi } from "@/api/file";
const loading = ref<boolean>(false);
const tr069XmlFlag = ref<boolean>(false);
@ -97,7 +97,7 @@ const handleUpload = async (formEl: FormInstance | undefined) => {
uploadApi(file, fileName, fileType)
.then(({ data }) => {
formData.value.fileUrl = data;
addTr069FileRecord(formData.value).then(() => {
addFileRecord(formData.value).then(() => {
tr069XmlFlag.value = false;
});
})

Loading…
Cancel
Save