Kaynağa Gözat

优化插件监控页面,增加字段的校验,插件图标的上传,复显等

yanglzh 2 yıl önce
ebeveyn
işleme
bfb6501d5f

+ 1 - 1
src/api/system/index.ts

@@ -143,7 +143,7 @@ export default {
   },
   plugin: {
     getList: (params: object) => get('/system/plugins/list', params),
-    del: (ids: object) => del('/system/plugins/set', {ids}),
+    del: (ids: object) => del('/system/plugins/del', {ids}),
     changeStatus: (data: object) => post('/system/plugins/set', data),
     edit: (data: any) => put('/system/plugins/edit', data),
     addPluginFile: (formatDate: FormData) => post('/system/plugins/add', formatDate),

+ 54 - 33
src/components/upload/index.vue

@@ -1,7 +1,19 @@
 <template>
 	<div class="upload">
-		<el-upload v-model:file-list="fileList" :class="{ hide: fileList.length >= limit }" :accept="accept" list-type="picture-card" :limit="limit" :multiple="multiple" :headers="headers" :before-upload="beforeAvatarUpload" :action="uploadUrl"
-			:on-success="updateImg" :on-preview="handlePictureCardPreview" :on-remove="updateImg">
+		<el-upload
+			v-model:file-list="fileList"
+			:class="{ hide: fileList.length >= limit }"
+			:accept="accept"
+			list-type="picture-card"
+			:limit="limit"
+			:multiple="multiple"
+			:headers="headers"
+			:before-upload="beforeAvatarUpload"
+			:action="uploadUrl"
+			:on-success="updateImg"
+			:on-preview="handlePictureCardPreview"
+			:on-remove="updateImg"
+		>
 			<el-icon>
 				<ele-Plus />
 			</el-icon>
@@ -21,29 +33,32 @@
 
 		<!-- 上传多张图片,imgs属性可以恢复表单图片多图显示 需增加limit属性,设定图片最多张数 -->
 		<!-- <uploadVue :imgs="['https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png']" @set-imgs="youImgs=$event" :limit="2"></uploadVue> -->
-
 	</div>
 </template>
 
 <script lang="ts" setup>
-import { ref, PropType, watch } from 'vue';
-import { ElMessage } from 'element-plus';
-import type { UploadProps } from 'element-plus';
+import { ref, PropType, watch } from 'vue'
+import { ElMessage } from 'element-plus'
+import type { UploadProps } from 'element-plus'
 import getOrigin from '/@/utils/origin'
 
-const uploadUrl: string = getOrigin(import.meta.env.VITE_API_URL + '/common/singleImg');
+const uploadUrl: string = getOrigin(import.meta.env.VITE_API_URL + '/common/singleImg')
 
 const headers = {
 	Authorization: 'Bearer ' + localStorage.token,
-};
+}
 
-const emit = defineEmits(['setImg', 'setImgs']);
+const emit = defineEmits(['setImg', 'setImgs'])
 
 const props = defineProps({
 	multiple: {
 		type: Boolean,
 		default: false,
 	},
+	widthHost: {
+		type: Boolean,
+		default: true,
+	},
 	accept: {
 		type: String,
 		default: '.jpg,.png,.jpeg,.gif',
@@ -60,71 +75,77 @@ const props = defineProps({
 		type: String,
 		default: '',
 	},
-});
+})
 
 const fileList = ref<any[]>([
 	// {
 	// 	name: '',
 	// 	url: '',
 	// },
-]);
+])
 
 const updateImg = () => {
 	const list = fileList.value.map((item) => {
 		if (item.response) {
-			return getOrigin(import.meta.env.VITE_SERVER_URL + '/' + item.response?.data?.path);
+			return getOrigin(import.meta.env.VITE_SERVER_URL + '/' + item.response?.data?.path)
 			// return item.response?.data?.path;
 		} else {
-			return item.url;
+			return item.url
 		}
-	});
+	})
 
 	if (props.limit === 1) {
-		emit('setImg', list[0]);
+		const img = list[0]
+		emit('setImg', props.widthHost ? img : img.replace(getOrigin(import.meta.env.VITE_SERVER_URL + '/'), ''))
 	} else {
-		emit('setImgs', list);
+		emit('setImgs', list)
 	}
-};
+}
 
 // 如果传入图片输入,设置图片显示
 watch(
 	() => props.imgs,
 	(imgs) => {
 		if (imgs.length) {
-			fileList.value = imgs.map((url) => ({ name: url, url }));
-			updateImg();
+			fileList.value = imgs.map((url) => ({ name: url, url }))
+			updateImg()
+		} else {
+			fileList.value = []
 		}
 	},
 	{ immediate: true }
-);
+)
 
 // 传入单独图片,设置图片显示
 watch(
 	() => props.img,
 	(img) => {
 		if (img) {
-			fileList.value = [{ name: img, url: img }];
-			updateImg();
+			const theImg = props.widthHost ? img : getOrigin(import.meta.env.VITE_SERVER_URL + '/' + img)
+			fileList.value = [{ name: theImg, url: theImg }]
+			updateImg()
+		} else {
+			fileList.value = []
 		}
 	},
 	{ immediate: true }
-);
+)
 
-const dialogImageUrl = ref('');
-const dialogVisible = ref(false);
+const dialogImageUrl = ref('')
+const dialogVisible = ref(false)
 
 const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
-	dialogImageUrl.value = uploadFile.url!;
-	dialogVisible.value = true;
-};
+	dialogImageUrl.value = uploadFile.url!
+	dialogVisible.value = true
+}
 
 const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
 	if (rawFile.size / 1024 / 1024 > 2) {
-		ElMessage.error('图片不能超过2MB!');
-		return false;
+		ElMessage.error('图片不能超过2MB!')
+		return false
 	}
-	return true;
-};
+	return true
+}
 </script>
 
 <style scoped>
@@ -138,4 +159,4 @@ const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
 	display: block;
 	margin: 0 auto;
 }
-</style>
+</style>

+ 75 - 92
src/views/iot/certificate/component/editParams.vue

@@ -1,54 +1,38 @@
 <template>
-	<el-dialog @close="state.ruleForm= {}" :title="state.ruleForm.id ? '编辑证书' : '新增证书'" v-model="state.dialogVisible" width="60%">
+	<el-dialog @close="state.ruleForm = {}" :title="state.ruleForm.id ? '编辑证书' : '新增证书'" v-model="state.dialogVisible" width="60%">
 		<!-- <el-tabs v-model="state.activeName" @tab-click="onTabClick"> -->
-			<!-- <el-tab-pane label="基本信息" name="1"> -->
-				<el-form :rules="state.rules" ref="ruleForm" :model="state.ruleForm" label-width="120px">
-					<el-form-item label="证书标准" prop="standard">
-						<el-select v-model="state.ruleForm.standard" placeholder="请选择证书标准">
-							<el-option
-								v-for="dict in network_certificate"
-								:key="dict.value"
-								:label="dict.label"
-								:value="dict.value">
-							</el-option>
-						</el-select>
-					</el-form-item>
-					<el-form-item label="证书名称" prop="name">
-						<el-input size="default" v-model="state.ruleForm.name"></el-input>
-					</el-form-item>
-					<el-form-item label="证书文件" prop="fileContent">
-						<el-input disabled v-if="state.ruleForm.fileContent" size="default" v-model="state.ruleForm.fileContent"></el-input>
-						<uploadFile @update="updateFile" url="/common/singleFile"></uploadFile>
-					</el-form-item>
-					<el-form-item label="证书公钥" prop="publicKeyContent">
-						<el-input size="default" disabled type="textarea" :rows="6" v-model="state.ruleForm.publicKeyContent"></el-input>
-						<el-upload  
-							class="upload-demo"
-							action=""              
-							accept=".txt"
-							:on-change="beforePublicUpload"
-							:auto-upload="false">
-							<el-button size="small" type="primary">上传</el-button>             
-						</el-upload>
-					</el-form-item>
-					<el-form-item label="证书私钥" prop="privateKeyContent">
-						<el-input size="default" disabled type="textarea" :rows="6" v-model="state.ruleForm.privateKeyContent"></el-input>
-						<el-upload  
-							class="upload-demo"
-							action=""              
-							accept=".txt"
-							:on-change="beforePrivateUpload"
-							:auto-upload="false">
-							<el-button size="small" type="primary">上传</el-button>             
-						</el-upload>
-					</el-form-item>
-					<el-form-item label="说明">
-						<el-input size="default" type="textarea" :rows="6" v-model="state.ruleForm.description"></el-input>
-					</el-form-item>
-					
-				</el-form>
-			<!-- </el-tab-pane> -->
-			<!-- <el-tab-pane label="字段信息" name="2">
+		<!-- <el-tab-pane label="基本信息" name="1"> -->
+		<el-form :rules="state.rules" ref="ruleForm" :model="state.ruleForm" label-width="120px">
+			<el-form-item label="证书标准" prop="standard">
+				<el-select v-model="state.ruleForm.standard" placeholder="请选择证书标准">
+					<el-option v-for="dict in network_certificate" :key="dict.value" :label="dict.label" :value="dict.value"> </el-option>
+				</el-select>
+			</el-form-item>
+			<el-form-item label="证书名称" prop="name">
+				<el-input size="default" v-model="state.ruleForm.name"></el-input>
+			</el-form-item>
+			<el-form-item label="证书文件" prop="fileContent">
+				<el-input disabled v-if="state.ruleForm.fileContent" size="default" v-model="state.ruleForm.fileContent"></el-input>
+				<uploadFile @update="updateFile" url="/common/singleFile"></uploadFile>
+			</el-form-item>
+			<el-form-item label="证书公钥" prop="publicKeyContent">
+				<el-input size="default" disabled type="textarea" :rows="6" v-model="state.ruleForm.publicKeyContent"></el-input>
+				<el-upload class="upload-demo" action="" accept=".txt" :on-change="beforePublicUpload" :auto-upload="false">
+					<el-button size="small" type="primary">上传</el-button>
+				</el-upload>
+			</el-form-item>
+			<el-form-item label="证书私钥" prop="privateKeyContent">
+				<el-input size="default" disabled type="textarea" :rows="6" v-model="state.ruleForm.privateKeyContent"></el-input>
+				<el-upload class="upload-demo" action="" accept=".txt" :on-change="beforePrivateUpload" :auto-upload="false">
+					<el-button size="small" type="primary">上传</el-button>
+				</el-upload>
+			</el-form-item>
+			<el-form-item label="说明">
+				<el-input size="default" type="textarea" :rows="6" v-model="state.ruleForm.description"></el-input>
+			</el-form-item>
+		</el-form>
+		<!-- </el-tab-pane> -->
+		<!-- <el-tab-pane label="字段信息" name="2">
 				<el-table :data="state.columns" style="width: 100%">
 					<el-table-column label="字段描述" align="center" width="150" fixed="left">
 						<template #default="{ row }">
@@ -190,15 +174,15 @@
 </template>
 
 <script lang="ts" setup>
-import { reactive, ref, unref, getCurrentInstance } from 'vue';
+import { reactive, ref, unref, getCurrentInstance } from 'vue'
 import { genFileId, FormRules, FormInstance } from 'element-plus'
-import uploadFile from '/@/components/upload/uploadFile.vue';
+import uploadFile from '/@/components/upload/uploadFile.vue'
 import type { UploadInstance, UploadProps, UploadRawFile } from 'element-plus'
 
-import api from '/@/api/certificateManagement';
-import { ElMessage } from 'element-plus';
+import api from '/@/api/certificateManagement'
+import { ElMessage } from 'element-plus'
 
-const emit = defineEmits(['update']);
+const emit = defineEmits(['update'])
 
 const ruleForm = ref<FormInstance>()
 
@@ -213,7 +197,7 @@ const state = reactive({
 		standard: [{ required: true, message: '证书标准不能为空', trigger: 'blur' }],
 		fileContent: [{ required: true, message: '证书文件不能为空', trigger: 'blur' }],
 		publicKeyContent: [{ required: true, message: '证书公钥不能为空', trigger: 'blur' }],
-		privateKeyContent: [{ required: true, message: '证书私钥不能为空', trigger: 'blur' }]
+		privateKeyContent: [{ required: true, message: '证书私钥不能为空', trigger: 'blur' }],
 	},
 	columns: [
 		{
@@ -420,77 +404,76 @@ const state = reactive({
 			linkLabelName: '',
 		},
 	],
-});
-const { proxy } = getCurrentInstance() as any;
-const { network_certificate } = proxy.useDict('network_certificate');
+})
+const { proxy } = getCurrentInstance() as any
+const { network_certificate } = proxy.useDict('network_certificate')
 console.log(network_certificate)
 // 打开弹窗
 const openDialog = (row: any) => {
 	if (row) {
-		state.ruleForm = row;
+		state.ruleForm = row
 	}
-	state.dialogVisible = true;
-};
+	state.dialogVisible = true
+}
 
 // 关闭弹窗
 const closeDialog = () => {
-	state.dialogVisible = false;
-};
+	state.dialogVisible = false
+}
 // 取消
 const onCancel = () => {
-	closeDialog();
-};
+	closeDialog()
+}
 
-const submitData =  async (formEl: any | undefined) => {
+const submitData = async (formEl: any | undefined) => {
 	if (!formEl) return
-		await formEl.validate((valid: any, fields: any) => {
+	await formEl.validate((valid: any, fields: any) => {
 		if (valid) {
 			console.log('submit!')
-			if(state.ruleForm.id) {
+			if (state.ruleForm.id) {
 				// 编辑
 				api.certificateManagement.edit(state.ruleForm).then((res: any) => {
-					ElMessage.success('证书编辑成功');
+					ElMessage.success('证书编辑成功')
 					console.log(res)
 					state.dialogVisible = false
 					emit('update')
 					state.ruleForm = {}
-				});
-			}else {
+				})
+			} else {
 				// 新增
 				api.certificateManagement.add(state.ruleForm).then((res: any) => {
-					ElMessage.success('证书添加成功');
+					ElMessage.success('证书添加成功')
 					console.log(res)
 					state.dialogVisible = false
 					emit('update')
 					state.ruleForm = {}
-				});
+				})
 			}
-
 		} else {
 			console.log('error submit!', fields)
 		}
 	})
 }
 
-const beforePublicUpload = (response:any, file:any, fileList:any) => {
-	let reader=new FileReader();
-	reader.readAsText(file[file.length-1].raw,'UTF-8')//读取,转换字符编码
-	reader.onload=function(e:any){
-		let val = e.target.result;//获取数据
-		let rtulist = val.split("\r\n")
-		console.log('rtulist:>> ', rtulist);
-		state.ruleForm.publicKeyContent = rtulist[0];
+const beforePublicUpload = (response: any, file: any, fileList: any) => {
+	let reader = new FileReader()
+	reader.readAsText(file[file.length - 1].raw, 'UTF-8') //读取,转换字符编码
+	reader.onload = function (e: any) {
+		let val = e.target.result //获取数据
+		let rtulist = val.split('\r\n')
+		console.log('rtulist:>> ', rtulist)
+		state.ruleForm.publicKeyContent = rtulist[0]
 	}
 }
 
-const beforePrivateUpload = (response:any, file:any, fileList:any) => {
-	let reader=new FileReader();
-	reader.readAsText(file[file.length-1].raw,'UTF-8')//读取,转换字符编码
-	reader.onload=function(e:any){
-		let val = e.target.result;//获取数据
-		let rtulist = val.split("\r\n")
-		console.log('rtulist:>> ', rtulist);
-		state.ruleForm.privateKeyContent = rtulist[0];
+const beforePrivateUpload = (response: any, file: any, fileList: any) => {
+	let reader = new FileReader()
+	reader.readAsText(file[file.length - 1].raw, 'UTF-8') //读取,转换字符编码
+	reader.onload = function (e: any) {
+		let val = e.target.result //获取数据
+		let rtulist = val.split('\r\n')
+		console.log('rtulist:>> ', rtulist)
+		state.ruleForm.privateKeyContent = rtulist[0]
 	}
 }
 const updateFile = (url: string) => {
@@ -498,7 +481,7 @@ const updateFile = (url: string) => {
 	state.ruleForm.fileContent = url
 }
 
-defineExpose({ openDialog });
+defineExpose({ openDialog })
 </script>
 
 <style scoped lang="scss">
@@ -510,4 +493,4 @@ defineExpose({ openDialog });
 :deep(.el-upload-list) {
 	display: none;
 }
-</style>
+</style>

+ 222 - 233
src/views/iot/device/product/component/editPro.vue

@@ -1,29 +1,34 @@
 <template>
-  <div class="system-edit-dic-container">
-    <el-dialog :title="(ruleForm.id !== 0 ? '修改' : '添加') + '产品'" v-model="isShowDialog" width="769px">
-      <el-form :model="ruleForm" ref="formRef" :rules="rules" size="default" label-width="90px">
-        <el-form-item label="产品标识" prop="key">
-          <el-input v-model="ruleForm.key" placeholder="请输入产品标识" :disabled="ruleForm.id" />
-        </el-form-item>
-        <el-form-item label="产品名称" prop="name">
-          <el-input v-model="ruleForm.name" placeholder="请输入产品名称" />
-        </el-form-item>
-        <el-form-item label="产品图片" prop="imageUrl">
-
-          <uploadVue :img="imageUrl" @set-img="handleAvatarSuccess"></uploadVue>
-
-        </el-form-item>
-
-        <el-form-item label="产品分类" prop="categoryId">
-          <el-cascader :options="cateData" :props="{ checkStrictly: true, emitPath: false, value: 'id', label: 'name' }" placeholder="请选择分类" clearable class="w100" v-model="ruleForm.categoryId">
-            <template #default="{ node, data }">
-              <span>{{ data.name }}</span>
-              <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
-            </template>
-          </el-cascader>
-        </el-form-item>
-
-        <!-- <el-form-item label="所属部门" prop="deptId">
+	<div class="system-edit-dic-container">
+		<el-dialog :title="(ruleForm.id !== 0 ? '修改' : '添加') + '产品'" v-model="isShowDialog" width="769px">
+			<el-form :model="ruleForm" ref="formRef" :rules="rules" size="default" label-width="90px">
+				<el-form-item label="产品标识" prop="key">
+					<el-input v-model="ruleForm.key" placeholder="请输入产品标识" :disabled="ruleForm.id" />
+				</el-form-item>
+				<el-form-item label="产品名称" prop="name">
+					<el-input v-model="ruleForm.name" placeholder="请输入产品名称" />
+				</el-form-item>
+				<el-form-item label="产品图片" prop="imageUrl">
+					<uploadVue :img="imageUrl" @set-img="handleAvatarSuccess"></uploadVue>
+				</el-form-item>
+
+				<el-form-item label="产品分类" prop="categoryId">
+					<el-cascader
+						:options="cateData"
+						:props="{ checkStrictly: true, emitPath: false, value: 'id', label: 'name' }"
+						placeholder="请选择分类"
+						clearable
+						class="w100"
+						v-model="ruleForm.categoryId"
+					>
+						<template #default="{ node, data }">
+							<span>{{ data.name }}</span>
+							<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
+						</template>
+					</el-cascader>
+				</el-form-item>
+
+				<!-- <el-form-item label="所属部门" prop="deptId">
           <el-cascader :options="deptData" :props="{ checkStrictly: true, emitPath: false, value: 'deptId', label: 'deptName' }" placeholder="请选择所属部门" clearable class="w100" v-model="ruleForm.deptId">
             <template #default="{ node, data }">
               <span>{{ data.deptName }}</span>
@@ -32,239 +37,223 @@
           </el-cascader>
         </el-form-item> -->
 
-
-        <el-form-item label="消息协议" prop="messageProtocol">
-          <el-select v-model="ruleForm.messageProtocol" placeholder="请选择消息协议">
-            <el-option v-for="dict in network_protocols" :key="dict.value" :label="dict.label" :value="dict.value">
-            </el-option>
-          </el-select>
-        </el-form-item>
-
-        <el-form-item label="传输协议" prop="transportProtocol">
-          <el-select v-model="ruleForm.transportProtocol" placeholder="请选择传输协议">
-            <el-option v-for="dict in network_server_type" :key="dict.value" :label="dict.label" :value="dict.value">
-            </el-option>
-          </el-select>
-        </el-form-item>
-
-
-        <el-form-item label="设备类型" prop="deviceType">
-          <el-radio-group v-model="ruleForm.deviceType">
-            <el-radio label="设备">设备</el-radio>
-
-            <el-radio label="网关">网关</el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label="产品描述	" prop="desc">
-          <el-input v-model="ruleForm.desc" type="textarea" placeholder="请输入产品描述"></el-input>
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <span class="dialog-footer">
-          <el-button @click="onCancel" size="default">取 消</el-button>
-          <el-button type="primary" @click="onSubmit" size="default">{{ ruleForm.id !== 0 ? '修 改' : '添 加' }}</el-button>
-        </span>
-      </template>
-    </el-dialog>
-  </div>
+				<el-form-item label="消息协议" prop="messageProtocol">
+					<el-select v-model="ruleForm.messageProtocol" placeholder="请选择消息协议">
+						<el-option v-for="dict in network_protocols" :key="dict.value" :label="dict.label" :value="dict.value"> </el-option>
+					</el-select>
+				</el-form-item>
+
+				<el-form-item label="传输协议" prop="transportProtocol">
+					<el-select v-model="ruleForm.transportProtocol" placeholder="请选择传输协议">
+						<el-option v-for="dict in network_server_type" :key="dict.value" :label="dict.label" :value="dict.value"> </el-option>
+					</el-select>
+				</el-form-item>
+
+				<el-form-item label="设备类型" prop="deviceType">
+					<el-radio-group v-model="ruleForm.deviceType">
+						<el-radio label="设备">设备</el-radio>
+
+						<el-radio label="网关">网关</el-radio>
+					</el-radio-group>
+				</el-form-item>
+				<el-form-item label="产品描述	" prop="desc">
+					<el-input v-model="ruleForm.desc" type="textarea" placeholder="请输入产品描述"></el-input>
+				</el-form-item>
+			</el-form>
+			<template #footer>
+				<span class="dialog-footer">
+					<el-button @click="onCancel" size="default">取 消</el-button>
+					<el-button type="primary" @click="onSubmit" size="default">{{ ruleForm.id !== 0 ? '修 改' : '添 加' }}</el-button>
+				</span>
+			</template>
+		</el-dialog>
+	</div>
 </template>
 
 <script lang="ts">
-import { reactive, toRefs, defineComponent, ref, unref, getCurrentInstance } from 'vue';
-import api from '/@/api/device';
-import uploadVue from '/@/components/upload/index.vue';
-import { ElMessage, UploadProps } from "element-plus";
+import { reactive, toRefs, defineComponent, ref, unref, getCurrentInstance } from 'vue'
+import api from '/@/api/device'
+import uploadVue from '/@/components/upload/index.vue'
+import { ElMessage, UploadProps } from 'element-plus'
 import getOrigin from '/@/utils/origin'
 
 interface RuleFormState {
-  id: number;
-  name: string;
-  dictType: string;
-  status: number;
-  desc: string;
+	id: number
+	name: string
+	dictType: string
+	status: number
+	desc: string
 }
 interface DicState {
-  isShowDialog: boolean;
-  ruleForm: RuleFormState;
-  cateData: RuleFormState[];
-  deptData: RuleFormState[];
-  messageData: RuleFormState[];
-  tranData: RuleFormState[];
-  rules: {}
+	isShowDialog: boolean
+	ruleForm: RuleFormState
+	cateData: RuleFormState[]
+	deptData: RuleFormState[]
+	messageData: RuleFormState[]
+	tranData: RuleFormState[]
+	rules: {}
 }
 
 export default defineComponent({
-  name: 'deviceEditPro',
-  components: { uploadVue },
-  setup(prop, { emit }) {
-    const formRef = ref<HTMLElement | null>(null);
-    const baseURL: string | undefined | boolean = getOrigin(import.meta.env.VITE_API_URL)
-
-    const { proxy } = getCurrentInstance() as any;
-    const { network_server_type, network_protocols } = proxy.useDict('network_server_type', 'network_protocols');
-
-    const state = reactive<DicState>({
-      isShowDialog: false,
-      cateData: [], // 分类数据
-      deptData: [], // 
-      messageData: [], // 
-      tranData: [], // 
-      imageUrl: "", // 
-      singleImg: baseURL + "/product/icon/upload",
-
-      ruleForm: {
-        id: 0,
-        name: '',
-        categoryId: '',
-        // deptId: '',
-        messageProtocol: '',
-        transportProtocol: '',
-        deviceType: '设备',
-        status: 1,
-        desc: ''
-      },
-      rules: {
-        name: [
-          { required: true, message: "产品名称不能为空", trigger: "blur" }
-        ],
-        key: [
-          { required: true, message: "产品标识不能为空", trigger: "blur" }
-        ],
-        parentId: [{ required: true, message: '产品分类不能为空', trigger: 'blur' }],
-        // deptId: [{ required: true, message: '所属部门不能为空', trigger: 'blur' }],
-        messageProtocol: [{ required: true, message: '消息协议不能为空', trigger: 'blur' }],
-        transportProtocol: [{ required: true, message: '传输协议不能为空', trigger: 'blur' }],
-        deviceType: [{ required: true, message: '设备类型不能为空', trigger: 'blur' }],
-      }
-    });
-
-
-
-
-    const handleAvatarSuccess: UploadProps['onSuccess'] = (
-      response) => {
-
-      console.log(response);
-
-      state.imageUrl = response
-      state.ruleForm.icon = response
-    }
-
-
-    // 打开弹窗
-    const openDialog = (row: RuleFormState | null) => {
-      resetForm();
-      api.category.getList({ status: 1 }).then((res: any) => {
-        state.cateData = res.category || [];
-      });
-      api.dept.getList({ status: -1 }).then((res: any) => {
-        state.deptData = res || [];
-      });
-      // api.product.message_protocol_list({ status: -1 }).then((res: any) => {
-      //   state.messageData = res.data || [];
-      // });
-      // api.product.trunsport_protocol_list({ status: -1 }).then((res: any) => {
-      //   state.tranData = res.data || [];
-      // });
-      if (row) {
-        // api.dict.getType(row.dictId).then((res:any)=>{
-        //   state.ruleForm = res.data.dictType
-        // }
-
-
-        state.imageUrl = row.icon
-
-        state.ruleForm = row;
-      }
-      state.isShowDialog = true;
-    };
-    const resetForm = () => {
-      state.ruleForm = {
-        id: 0,
-        name: '',
-        dictType: '',
-        deviceType: '设备',
-        status: 1,
-        desc: ''
-      }
-    };
-    // 关闭弹窗
-    const closeDialog = () => {
-      state.isShowDialog = false;
-    };
-    // 取消
-    const onCancel = () => {
-      closeDialog();
-    };
-    // 新增
-    const onSubmit = () => {
-      const formWrap = unref(formRef) as any;
-      if (!formWrap) return;
-      formWrap.validate((valid: boolean) => {
-        if (valid) {
-          if (state.ruleForm.id !== 0) {
-            //修改
-            api.product.edit(state.ruleForm).then(() => {
-              ElMessage.success('产品类型修改成功');
-              closeDialog(); // 关闭弹窗
-              emit('typeList')
-            })
-          } else {
-            //添加
-            console.log(state.ruleForm);
-            api.product.add(state.ruleForm).then(() => {
-              ElMessage.success('产品类型添加成功');
-              closeDialog(); // 关闭弹窗
-              emit('typeList')
-            })
-          }
-        }
-      });
-    };
-
-
-    return {
-      openDialog,
-      handleAvatarSuccess,
-      closeDialog,
-      onCancel,
-      onSubmit,
-      network_server_type,
-      network_protocols,
-      formRef,
-      ...toRefs(state),
-    };
-  },
-});
+	name: 'deviceEditPro',
+	components: { uploadVue },
+	setup(prop, { emit }) {
+		const formRef = ref<HTMLElement | null>(null)
+		const baseURL: string | undefined | boolean = getOrigin(import.meta.env.VITE_API_URL)
+
+		const { proxy } = getCurrentInstance() as any
+		const { network_server_type, network_protocols } = proxy.useDict('network_server_type', 'network_protocols')
+
+		const state = reactive<DicState>({
+			isShowDialog: false,
+			cateData: [], // 分类数据
+			deptData: [], //
+			messageData: [], //
+			tranData: [], //
+			imageUrl: '', //
+			singleImg: baseURL + '/product/icon/upload',
+
+			ruleForm: {
+				id: 0,
+				name: '',
+				categoryId: '',
+				// deptId: '',
+				messageProtocol: '',
+				transportProtocol: '',
+				deviceType: '设备',
+				status: 1,
+				desc: '',
+			},
+			rules: {
+				name: [{ required: true, message: '产品名称不能为空', trigger: 'blur' }],
+				key: [{ required: true, message: '产品标识不能为空', trigger: 'blur' }],
+				parentId: [{ required: true, message: '产品分类不能为空', trigger: 'blur' }],
+				// deptId: [{ required: true, message: '所属部门不能为空', trigger: 'blur' }],
+				messageProtocol: [{ required: true, message: '消息协议不能为空', trigger: 'blur' }],
+				transportProtocol: [{ required: true, message: '传输协议不能为空', trigger: 'blur' }],
+				deviceType: [{ required: true, message: '设备类型不能为空', trigger: 'blur' }],
+			},
+		})
+
+		const handleAvatarSuccess: UploadProps['onSuccess'] = (response) => {
+			console.log(response)
+
+			state.imageUrl = response
+			state.ruleForm.icon = response
+		}
+
+		// 打开弹窗
+		const openDialog = (row: RuleFormState | null) => {
+			resetForm()
+			api.category.getList({ status: 1 }).then((res: any) => {
+				state.cateData = res.category || []
+			})
+			api.dept.getList({ status: -1 }).then((res: any) => {
+				state.deptData = res || []
+			})
+			// api.product.message_protocol_list({ status: -1 }).then((res: any) => {
+			//   state.messageData = res.data || [];
+			// });
+			// api.product.trunsport_protocol_list({ status: -1 }).then((res: any) => {
+			//   state.tranData = res.data || [];
+			// });
+			if (row) {
+				// api.dict.getType(row.dictId).then((res:any)=>{
+				//   state.ruleForm = res.data.dictType
+				// }
+
+				state.imageUrl = row.icon
+
+				state.ruleForm = row
+			}
+			state.isShowDialog = true
+		}
+		const resetForm = () => {
+			state.ruleForm = {
+				id: 0,
+				name: '',
+				dictType: '',
+				deviceType: '设备',
+				status: 1,
+				desc: '',
+			}
+		}
+		// 关闭弹窗
+		const closeDialog = () => {
+			state.isShowDialog = false
+		}
+		// 取消
+		const onCancel = () => {
+			closeDialog()
+		}
+		// 新增
+		const onSubmit = () => {
+			const formWrap = unref(formRef) as any
+			if (!formWrap) return
+			formWrap.validate((valid: boolean) => {
+				if (valid) {
+					if (state.ruleForm.id !== 0) {
+						//修改
+						api.product.edit(state.ruleForm).then(() => {
+							ElMessage.success('产品类型修改成功')
+							closeDialog() // 关闭弹窗
+							emit('typeList')
+						})
+					} else {
+						//添加
+						console.log(state.ruleForm)
+						api.product.add(state.ruleForm).then(() => {
+							ElMessage.success('产品类型添加成功')
+							closeDialog() // 关闭弹窗
+							emit('typeList')
+						})
+					}
+				}
+			})
+		}
+
+		return {
+			openDialog,
+			handleAvatarSuccess,
+			closeDialog,
+			onCancel,
+			onSubmit,
+			network_server_type,
+			network_protocols,
+			formRef,
+			...toRefs(state),
+		}
+	},
+})
 </script>
 
 <style scoped>
 .avatar-uploader .avatar {
-  width: 178px;
-  height: 178px;
-  display: block;
+	width: 178px;
+	height: 178px;
+	display: block;
 }
 </style>
 
 <style>
 .avatar-uploader .el-upload {
-  border: 1px dashed var(--el-border-color);
-  border-radius: 6px;
-  cursor: pointer;
-  position: relative;
-  overflow: hidden;
-  transition: var(--el-transition-duration-fast);
+	border: 1px dashed var(--el-border-color);
+	border-radius: 6px;
+	cursor: pointer;
+	position: relative;
+	overflow: hidden;
+	transition: var(--el-transition-duration-fast);
 }
 
 .avatar-uploader .el-upload:hover {
-  border-color: var(--el-color-primary);
+	border-color: var(--el-color-primary);
 }
 
 .el-icon.avatar-uploader-icon {
-  font-size: 28px;
-  color: #8c939d;
-  width: 178px;
-  height: 178px;
-  text-align: center;
+	font-size: 28px;
+	color: #8c939d;
+	width: 178px;
+	height: 178px;
+	text-align: center;
 }
 </style>

+ 119 - 119
src/views/personal/index.vue

@@ -1,109 +1,109 @@
 <template>
-  <div class="personal">
-    <el-row>
-      <!-- 个人信息 -->
-      <el-col :xs="24" :sm="24">
-        <el-card shadow="hover" header="个人信息" v-loading="!info.userName">
-          <div class="personal-user">
-            <div class="personal-user-left">
-              <img v-if="isEditStatus && info.avatar" style="width:140px;height:140px" :src="info.avatar" />
-			  <uploadVue v-else @set-img="setImg">
-                <img  style="width:140px;height:140px" :src="info.avatar" />
-				<div class="tips">点击上方照片,即可更改头像</div>
-              </uploadVue>
-            </div>
-            <div class="personal-user-right">
-              <el-row>
-                <el-col :span="24" class="personal-title mb18">{{ currentTime }},{{info.userName}},生活变的再糟糕,也不妨碍我变得更好! </el-col>
-                <!-- 昵称 -->
-				<el-col :xs="24" :sm="24" class="personal-item mb6">
-                  <div class="personal-item-label">昵称:</div>
-                  <div v-if="isEditStatus" class="personal-item-value">{{info.userNickname}}</div>
-				  <el-input v-else class="personal-item-value personal-item-value-edit" v-model="info.userNickname"></el-input>
-                </el-col>
-				<!-- 性别 -->
-                <el-col :xs="24" :sm="24" class="personal-item mb6">
-                  <div class="personal-item-label">性别:</div>
-                  <div v-if="isEditStatus" class="personal-item-value">{{info.sex=='1'?'男':'女'}}</div>
-					<!-- 0:保密,1:男,2:女 -->
-					<el-radio-group v-else v-model="info.sex">
-						<el-radio :label="0">保密</el-radio>
-						<el-radio :label="1">男</el-radio>
-						<el-radio :label="2">女</el-radio>
-					</el-radio-group>
-                </el-col>
-				<!-- 生日 -->
-				<el-col :xs="24" :sm="24" class="personal-item mb6">
-                  <div class="personal-item-label">生日:</div>
-                  <div v-if="isEditStatus" class="personal-item-value">{{info.birthday}}</div>
-				  <el-date-picker
-				    v-else
-				    @change="dateChange"
-					v-model="info.birthday"
-					type="date"
-					placeholder="请选择出生日期"
-					format="YYYY/MM/DD"
-                    value-format="YYYY-MM-DD"
-				  />
-                </el-col>
-				<!-- 登录密码 -->
-				<el-col v-if="!isEditStatus" :xs="24" :sm="24" class="personal-item mb6">
-                  <div class="personal-item-label">登录密码:</div>
-				  <el-input class="personal-item-value personal-item-value-edit" v-model="info.userPassword"></el-input>
-                </el-col>
-				<!-- 手机号 -->
-				<el-col :xs="24" :sm="24" class="personal-item mb6">
-                  <div class="personal-item-label">手机号:</div>
-                  <div v-if="isEditStatus" class="personal-item-value">{{info.mobile}}</div>
-				  <el-input v-else class="personal-item-value personal-item-value-edit" v-model="info.mobile"></el-input>
-                </el-col>
-				<!-- 邮箱 -->
-				<el-col :xs="24" :sm="24" class="personal-item mb6">
-                  <div class="personal-item-label">邮箱:</div>
-                  <div v-if="isEditStatus" class="personal-item-value">{{info.userEmail}}</div>
-				  <el-input v-else class="personal-item-value personal-item-value-edit" v-model="info.userEmail"></el-input>
-                </el-col>
-				<!-- 联系地址 -->
-				<el-col :xs="24" :sm="24" class="personal-item mb6">
-                  <div class="personal-item-label">联系地址:</div>
-                  <div v-if="isEditStatus" class="personal-item-value">{{info.address}}</div>
-				  <el-input v-else class="personal-item-value personal-item-value-edit" v-model="info.address"></el-input>
-                </el-col>
-				<!-- 简介 -->
-				<el-col :xs="24" :sm="24" class="personal-item mb6">
-                  <div class="personal-item-label">简介:</div>
-                  <div v-if="isEditStatus" class="personal-item-value">{{info.describe}}</div>
-				  <el-input v-else class="personal-item-value personal-item-value-edit" v-model="info.describe"></el-input>
-                </el-col>
-                <el-col :xs="24" :sm="24" class="personal-item mb6">
-                  <div class="personal-item-label">登录IP:</div>
-                  <div class="personal-item-value">{{info.lastLoginIp}}</div>
-                </el-col>
-                <el-col :xs="24" :sm="24" class="personal-item mb6">
-                  <div class="personal-item-label">登录时间:</div>
-                  <div class="personal-item-value">{{info.lastLoginTime}}</div>
-                </el-col>
-              </el-row>
-            </div>
-          </div>
-		  <div class="edit-btn">
-	 	    <el-button type="primary" @click="handleChange">{{isEditStatus?'修改':'保存'}}</el-button>
-		  </div>
-        </el-card>
-      </el-col>
-    </el-row>
-  </div>
+	<div class="personal">
+		<el-row>
+			<!-- 个人信息 -->
+			<el-col :xs="24" :sm="24">
+				<el-card shadow="hover" header="个人信息" v-loading="!info.userName">
+					<div class="personal-user">
+						<div class="personal-user-left">
+							<img v-if="isEditStatus && info.avatar" style="width: 140px; height: 140px" :src="info.avatar" />
+							<uploadVue v-else @set-img="setImg">
+								<img style="width: 140px; height: 140px" :src="info.avatar" />
+								<div class="tips">点击上方照片,即可更改头像</div>
+							</uploadVue>
+						</div>
+						<div class="personal-user-right">
+							<el-row>
+								<el-col :span="24" class="personal-title mb18">{{ currentTime }},{{ info.userName }},生活变的再糟糕,也不妨碍我变得更好! </el-col>
+								<!-- 昵称 -->
+								<el-col :xs="24" :sm="24" class="personal-item mb6">
+									<div class="personal-item-label">昵称:</div>
+									<div v-if="isEditStatus" class="personal-item-value">{{ info.userNickname }}</div>
+									<el-input v-else class="personal-item-value personal-item-value-edit" v-model="info.userNickname"></el-input>
+								</el-col>
+								<!-- 性别 -->
+								<el-col :xs="24" :sm="24" class="personal-item mb6">
+									<div class="personal-item-label">性别:</div>
+									<div v-if="isEditStatus" class="personal-item-value">{{ info.sex == '1' ? '男' : '女' }}</div>
+									<!-- 0:保密,1:男,2:女 -->
+									<el-radio-group v-else v-model="info.sex">
+										<el-radio :label="0">保密</el-radio>
+										<el-radio :label="1">男</el-radio>
+										<el-radio :label="2">女</el-radio>
+									</el-radio-group>
+								</el-col>
+								<!-- 生日 -->
+								<el-col :xs="24" :sm="24" class="personal-item mb6">
+									<div class="personal-item-label">生日:</div>
+									<div v-if="isEditStatus" class="personal-item-value">{{ info.birthday }}</div>
+									<el-date-picker
+										v-else
+										@change="dateChange"
+										v-model="info.birthday"
+										type="date"
+										placeholder="请选择出生日期"
+										format="YYYY/MM/DD"
+										value-format="YYYY-MM-DD"
+									/>
+								</el-col>
+								<!-- 登录密码 -->
+								<el-col v-if="!isEditStatus" :xs="24" :sm="24" class="personal-item mb6">
+									<div class="personal-item-label">登录密码:</div>
+									<el-input class="personal-item-value personal-item-value-edit" v-model="info.userPassword"></el-input>
+								</el-col>
+								<!-- 手机号 -->
+								<el-col :xs="24" :sm="24" class="personal-item mb6">
+									<div class="personal-item-label">手机号:</div>
+									<div v-if="isEditStatus" class="personal-item-value">{{ info.mobile }}</div>
+									<el-input v-else class="personal-item-value personal-item-value-edit" v-model="info.mobile"></el-input>
+								</el-col>
+								<!-- 邮箱 -->
+								<el-col :xs="24" :sm="24" class="personal-item mb6">
+									<div class="personal-item-label">邮箱:</div>
+									<div v-if="isEditStatus" class="personal-item-value">{{ info.userEmail }}</div>
+									<el-input v-else class="personal-item-value personal-item-value-edit" v-model="info.userEmail"></el-input>
+								</el-col>
+								<!-- 联系地址 -->
+								<el-col :xs="24" :sm="24" class="personal-item mb6">
+									<div class="personal-item-label">联系地址:</div>
+									<div v-if="isEditStatus" class="personal-item-value">{{ info.address }}</div>
+									<el-input v-else class="personal-item-value personal-item-value-edit" v-model="info.address"></el-input>
+								</el-col>
+								<!-- 简介 -->
+								<el-col :xs="24" :sm="24" class="personal-item mb6">
+									<div class="personal-item-label">简介:</div>
+									<div v-if="isEditStatus" class="personal-item-value">{{ info.describe }}</div>
+									<el-input v-else class="personal-item-value personal-item-value-edit" v-model="info.describe"></el-input>
+								</el-col>
+								<el-col :xs="24" :sm="24" class="personal-item mb6">
+									<div class="personal-item-label">登录IP:</div>
+									<div class="personal-item-value">{{ info.lastLoginIp }}</div>
+								</el-col>
+								<el-col :xs="24" :sm="24" class="personal-item mb6">
+									<div class="personal-item-label">登录时间:</div>
+									<div class="personal-item-value">{{ info.lastLoginTime }}</div>
+								</el-col>
+							</el-row>
+						</div>
+					</div>
+					<div class="edit-btn">
+						<el-button type="primary" @click="handleChange">{{ isEditStatus ? '修改' : '保存' }}</el-button>
+					</div>
+				</el-card>
+			</el-col>
+		</el-row>
+	</div>
 </template>
 
 <script lang="ts" setup>
-import { ref, computed } from 'vue';
-import { formatAxis } from '/@/utils/formatTime';
-import { ElMessage } from 'element-plus';
-import api from '/@/api/system';
-import uploadVue from '/@/components/upload-wrapper/index.vue';
+import { ref, computed } from 'vue'
+import { formatAxis } from '/@/utils/formatTime'
+import { ElMessage } from 'element-plus'
+import api from '/@/api/system'
+import uploadVue from '/@/components/upload-wrapper/index.vue'
 
 const info = ref<any>({})
-const isEditStatus = ref<Boolean>(true);
+const isEditStatus = ref<Boolean>(true)
 
 // api.login.currentUser().then((res: any) => {
 //   info.value = res.Info
@@ -112,31 +112,31 @@ const isEditStatus = ref<Boolean>(true);
 // 			// 	});
 // });
 api.user.detail(localStorage.userId).then((user: any) => {
-	info.value = user;
-});
+	info.value = user
+})
 
 // 当前时间提示语
 const currentTime = computed(() => {
-  return formatAxis(new Date());
-});
+	return formatAxis(new Date())
+})
 
 const setImg = (img: string) => {
-  api.user.setAvatar(info.value.id, img).then((res: any) => {
-    ElMessage.success('更新成功')
-    info.value.avatar = img
-  })
+	api.user.setAvatar(info.value.id, img).then((res: any) => {
+		ElMessage.success('更新成功')
+		info.value.avatar = img
+	})
 }
 
 /**
  * 修改/保存 状态切换
  */
 const handleChange = () => {
-	if(isEditStatus.value) {
+	if (isEditStatus.value) {
 		// 展示修改按钮
-		isEditStatus.value = false;
-	}else {
+		isEditStatus.value = false
+	} else {
 		// 提交修改表单
-		submitData();
+		submitData()
 	}
 }
 
@@ -144,8 +144,8 @@ const handleChange = () => {
  * 提交修改表单
  */
 // 地址事例值:四川省成都市青羊区东城根南街68号院
-const submitData =  () => {
-	const { id, mobile, userNickname, birthday, userPassword, userEmail, sex, avatar, address, describe } = info.value;
+const submitData = () => {
+	const { id, mobile, userNickname, birthday, userPassword, userEmail, sex, avatar, address, describe } = info.value
 	let params = {
 		id,
 		mobile,
@@ -156,19 +156,19 @@ const submitData =  () => {
 		sex,
 		avatar,
 		address,
-		describe
+		describe,
 	}
 	api.user.editUserInfo(params).then((res: any) => {
 		ElMessage.success('更新成功')
-		isEditStatus.value = true;
+		isEditStatus.value = true
 	})
 }
 
 /**
  * 选择生日
  */
-const dateChange = (e:any) => {
-  info.value.birthday = e;
+const dateChange = (e: any) => {
+	info.value.birthday = e
 }
 </script>
 
@@ -188,7 +188,7 @@ const dateChange = (e:any) => {
 					color: #ccc;
 				}
 			}
-			
+
 			.personal-user-left-upload {
 				img {
 					width: 100%;

+ 14 - 5
src/views/system/monitor/plugin/edit.vue

@@ -4,13 +4,13 @@
 			<el-form-item label="通信方式" prop="types">
 				<el-input v-model="formData.types" placeholder="输入接口名称" />
 			</el-form-item>
-			<el-form-item label="功能类型" prop="handleType" required>
+			<el-form-item label="功能类型" prop="handleType">
 				<el-input v-model="formData.handleType" placeholder="输入功能类型" />
 			</el-form-item>
-			<el-form-item label="名称" prop="name" required>
+			<el-form-item label="名称" prop="name">
 				<el-input v-model="formData.name" placeholder="输入名称" />
 			</el-form-item>
-			<el-form-item label="标题" prop="title" required>
+			<el-form-item label="标题" prop="title">
 				<el-input v-model="formData.title" placeholder="输入标题" />
 			</el-form-item>
 			<el-form-item label="说明" prop="description">
@@ -23,7 +23,8 @@
 				<el-input v-model="formData.author" placeholder="输入作者" />
 			</el-form-item>
 			<el-form-item label="插件图标" prop="icon">
-				<el-input v-model="formData.icon" placeholder="输入插件图标" />
+				<!-- <el-input v-model="formData.icon" placeholder="输入插件图标" /> -->
+				<uploadVue :width-host="false" :img="formData.icon" @set-img="formData.icon = $event"></uploadVue>
 			</el-form-item>
 			<el-form-item label="插件网址" prop="link">
 				<el-input v-model="formData.link" placeholder="输入插件网址" />
@@ -58,6 +59,7 @@ import { ref, reactive, nextTick } from 'vue'
 import api from '/@/api/system'
 import { ruleRequired } from '/@/utils/validator'
 import { ElMessage } from 'element-plus'
+import uploadVue from '/@/components/upload/index.vue'
 
 const emit = defineEmits(['getList'])
 
@@ -88,7 +90,14 @@ const formData = reactive({
 
 const ruleForm = {
 	types: [ruleRequired('通信方式不能为空')],
-	menuIds: [ruleRequired('关联页面不能为空', 'change')],
+	handleType: [ruleRequired('功能类型不能为空')],
+	name: [ruleRequired('名称不能为空')],
+	title: [ruleRequired('标题不能为空')],
+	version: [ruleRequired('版本不能为空')],
+	author: [ruleRequired('作者不能为空')],
+	icon: [ruleRequired('插件图标不能为空')],
+	command: [ruleRequired('运行指令不能为空')],
+	args: [ruleRequired('指令参数不能为空')],
 }
 
 const onSubmit = async () => {