Merge pull request '设备类型添加图片' (#27) from liubiao/dyf-vue-ui:main into main

Reviewed-on: #27
This commit is contained in:
dyf
2026-01-12 11:20:17 +08:00
6 changed files with 1316 additions and 65 deletions

View File

@ -6,8 +6,8 @@ VITE_APP_ENV = 'development'
# 开发环境 # 开发环境
# VITE_APP_BASE_API = 'http://139.224.253.23:8000' # VITE_APP_BASE_API = 'http://139.224.253.23:8000'
VITE_APP_BASE_API = 'https://www.cnxhyc.com/jq' # VITE_APP_BASE_API = 'https://www.cnxhyc.com/jq'
#VITE_APP_BASE_API = 'http://192.168.110.56:8000' VITE_APP_BASE_API = 'http://192.168.110.57:8000'
#代永飞接口 #代永飞接口
# VITE_APP_BASE_API = 'http://457102h2d6.qicp.vip:24689' # VITE_APP_BASE_API = 'http://457102h2d6.qicp.vip:24689'

View File

@ -8,7 +8,7 @@ VITE_APP_ENV = 'https://www.cnxhyc.com'
# VITE_APP_ENV = 'https://fuyuanshen.com/backend-fys' # VITE_APP_ENV = 'https://fuyuanshen.com/backend-fys'
# 应用访问路径 晶全1 # 应用访问路径 晶全1
VITE_APP_CONTEXT_PATH = '/jingquan/' VITE_APP_CONTEXT_PATH = '/'
# 高德地图Key # 高德地图Key
VITE_AMAP_KEY='84a12a692ae378effdf741e16d584cd3' VITE_AMAP_KEY='84a12a692ae378effdf741e16d584cd3'
@ -23,7 +23,7 @@ VITE_APP_MONITOR_ADMIN = '/admin/applications'
VITE_APP_SNAILJOB_ADMIN = '/snail-job' VITE_APP_SNAILJOB_ADMIN = '/snail-job'
# 生产环境 晶全3 代理访问 # 生产环境 晶全3 代理访问
VITE_APP_BASE_API = '/jq' VITE_APP_BASE_API = 'https://www.cnxhyc.com/jq'
# 生产环境 富源晟3 # 生产环境 富源晟3
#VITE_APP_BASE_API = '/backend-fys' #VITE_APP_BASE_API = '/backend-fys'

View File

@ -6,7 +6,12 @@
<meta name="renderer" content="webkit" /> <meta name="renderer" content="webkit" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" /> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/favicon.ico" />
<script src="https://webapi.amap.com/maps?v=2.0&key=90bc158992feb8ccd0145e168cab1307&plugin=AMap.CircleEditor"></script> <script type="text/javascript">
window._AMapSecurityConfig = {
securityJsCode: "4239900f4fb7b2569df651ac814a28de",
};
</script>
<script src="https://webapi.amap.com/maps?v=2.0&key=78c36a1e251a95f1a21a9e5ea7a1331c&plugin=AMap.CircleEditor"></script>
<title>物联网管理平台</title> <title>物联网管理平台</title>
<!--[if lt IE 11 <!--[if lt IE 11
]><script> ]><script>

View File

@ -17,7 +17,10 @@ export const addDeviceType = (data: any): AxiosPromise<deviceTypeVO[]> => {
return request({ return request({
url: '/api/deviceType/add', url: '/api/deviceType/add',
method: 'post', method: 'post',
data: data data: data,
headers:{
'Content-Type':'application/x-www-form-urlencoded;charset=UTF-8'
}
}); });
}; };
@ -26,6 +29,9 @@ export const updateDeviceType = (data: any): AxiosPromise<deviceTypeVO[]> => {
return request({ return request({
url: '/api/deviceType/update', url: '/api/deviceType/update',
method: 'put', method: 'put',
headers:{
'Content-Type':'application/x-www-form-urlencoded;charset=UTF-8'
},
data data
}) })
} }
@ -34,6 +40,7 @@ export const deleteDeviceType = (ids: any): AxiosPromise<deviceTypeVO[]> => {
return request({ return request({
url: '/api/deviceType/delete', url: '/api/deviceType/delete',
method: 'delete', method: 'delete',
data: ids data: ids
}) })
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,6 @@
<template> <template>
<div class="p-2"> <div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
:leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]"> <div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true"> <el-form ref="queryFormRef" :model="queryParams" :inline="true">
@ -24,14 +23,10 @@
<el-button type="primary" plain icon="Plus" @click="handleAdd()">新增</el-button> <el-button type="primary" plain icon="Plus" @click="handleAdd()">新增</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="success" plain :disabled="single" icon="Edit" @click="handleUpdate()"> <el-button type="success" plain :disabled="single" icon="Edit" @click="handleUpdate()"> 修改 </el-button>
修改
</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="danger" plain :disabled="multiple" icon="Delete" @click="handleDelete()"> <el-button type="danger" plain :disabled="multiple" icon="Delete" @click="handleDelete()"> 删除 </el-button>
删除
</el-button>
</el-col> </el-col>
<right-toolbar v-model:show-search="showSearch" :search="true" @query-table="getList"></right-toolbar> <right-toolbar v-model:show-search="showSearch" :search="true" @query-table="getList"></right-toolbar>
</el-row> </el-row>
@ -42,8 +37,7 @@
<el-table-column label="型号名称" align="center" prop="typeName" /> <el-table-column label="型号名称" align="center" prop="typeName" />
<el-table-column label="类型code" align="center" prop="appModelDictionary"> <el-table-column label="类型code" align="center" prop="appModelDictionary">
<template #default="scope"> <template #default="scope">
{{appmodelDictionaryOptions.find(item => item.dictValue === String(scope.row.appModelDictionary))?.dictLabel {{ appmodelDictionaryOptions.find((item) => item.dictValue === String(scope.row.appModelDictionary))?.dictLabel }}
}}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="是否支持蓝牙" align="center" prop="isSupportBle"> <el-table-column label="是否支持蓝牙" align="center" prop="isSupportBle">
@ -81,14 +75,11 @@
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
:total="total" @pagination="getList" />
</el-card> </el-card>
<!-- 添加或修改用户配置对话框 --> <!-- 添加或修改用户配置对话框 -->
<el-dialog ref="formDialogRef" v-model="dialog.visible" :title="dialog.title" width="30%" append-to-body <el-dialog ref="formDialogRef" v-model="dialog.visible" :title="dialog.title" width="30%" append-to-body @close="closeDialog">
@close="closeDialog">
<el-form ref="userFormRef" :model="form" :rules="rules" label-width="120px"> <el-form ref="userFormRef" :model="form" :rules="rules" label-width="120px">
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
@ -101,14 +92,12 @@
<el-col :span="24"> <el-col :span="24">
<el-form-item label="路由跳转" prop="appModelDictionary"> <el-form-item label="路由跳转" prop="appModelDictionary">
<el-select v-model="form.appModelDictionary" placeholder="请选择" @change="handlePcRouteChange"> <el-select v-model="form.appModelDictionary" placeholder="请选择" @change="handlePcRouteChange">
<el-option v-for="item in appmodelDictionaryOptions" :key="item.dictCode" :label="item.dictLabel" <el-option v-for="item in appmodelDictionaryOptions" :key="item.dictCode" :label="item.dictLabel" :value="item.dictValue" />
:value="item.dictValue" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="pc路由跳转" prop="pcModelDictionary" style="display: none;"> <el-form-item label="pc路由跳转" prop="pcModelDictionary" style="display: none">
<el-select v-model="form.pcModelDictionary" placeholder="请选择"> <el-select v-model="form.pcModelDictionary" placeholder="请选择">
<el-option v-for="item in pcmodelDictionaryOptions" :key="item.dictCode" :label="item.dictLabel" <el-option v-for="item in pcmodelDictionaryOptions" :key="item.dictCode" :label="item.dictLabel" :value="item.dictValue" />
:value="item.dictValue" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
@ -147,6 +136,22 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row>
<el-col :span="24">
<el-form-item label="设备图片" prop="devicePic">
<input type="file" id="fileTypeImg" accept="image/*" style="display: none" />
<div class="devicePic typeImgContent" v-if="form.devicePic">
<img class="img" :src="form.devicePic" />
<div class="mask center" @click.stop="DropImg(form)">
<el-icon class="avatar-uploader-icon"><Delete /></el-icon>
</div>
</div>
<div class="devicePic typeImgAdd center" v-else @click.stop="AddImg(form)">
<el-icon class="avatar-uploader-icon"><Plus /></el-icon>
</div>
</el-form-item>
</el-col>
</el-row>
</el-form> </el-form>
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
@ -164,7 +169,23 @@ import { deviceTypeQuery } from '@/api/equipmentManagement/deviceType/types';
import { getDicts } from '@/api/system/dict/data'; import { getDicts } from '@/api/system/dict/data';
import { to } from 'await-to-js'; import { to } from 'await-to-js';
import { ComponentInternalInstance, getCurrentInstance, onMounted, reactive, ref, toRefs } from 'vue'; import { ComponentInternalInstance, getCurrentInstance, onMounted, reactive, ref, toRefs } from 'vue';
import { ElDialog, ElForm, ElFormItem, ElInput, ElRow, ElCol, ElButton, ElCard, ElSelect, ElOption, ElDatePicker, ElTable, ElTableColumn, ElTooltip, ElSwitch } from 'element-plus'; import {
ElDialog,
ElForm,
ElFormItem,
ElInput,
ElRow,
ElCol,
ElButton,
ElCard,
ElSelect,
ElOption,
ElDatePicker,
ElTable,
ElTableColumn,
ElTooltip,
ElSwitch
} from 'element-plus';
interface deviceTypeVO { interface deviceTypeVO {
id: string | number; id: string | number;
typeName: string; typeName: string;
@ -176,9 +197,9 @@ interface deviceTypeVO {
communicationMode: number; communicationMode: number;
createTime: string; createTime: string;
createByName: string; createByName: string;
devicePic: string;
} }
interface DeviceTypeForm extends deviceTypeVO { interface DeviceTypeForm extends deviceTypeVO {}
}
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const deviceTypeList = ref<deviceTypeVO[]>(); const deviceTypeList = ref<deviceTypeVO[]>();
const loading = ref(true); const loading = ref(true);
@ -190,9 +211,11 @@ const total = ref(0);
const queryFormRef = ref<InstanceType<typeof ElForm>>(); const queryFormRef = ref<InstanceType<typeof ElForm>>();
const userFormRef = ref<InstanceType<typeof ElForm>>(); const userFormRef = ref<InstanceType<typeof ElForm>>();
const formDialogRef = ref<InstanceType<typeof ElDialog>>(); const formDialogRef = ref<InstanceType<typeof ElDialog>>();
const loadingIng = ref(false) const loadingIng = ref(false);
const appmodelDictionaryOptions = ref<any[]>([]); const appmodelDictionaryOptions = ref<any[]>([]);
const pcmodelDictionaryOptions = ref<any[]>([]); const pcmodelDictionaryOptions = ref<any[]>([]);
var fileC = null;
var uploadFile=false;
const dialog = reactive<DialogOption>({ const dialog = reactive<DialogOption>({
visible: false, visible: false,
title: '' title: ''
@ -207,7 +230,7 @@ const initFormData: DeviceTypeForm = {
communicationMode: 0, communicationMode: 0,
id: '', id: '',
createTime: '', createTime: '',
createByName: '', createByName: ''
}; };
const initData = { const initData = {
@ -215,28 +238,20 @@ const initData = {
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
typeName: '', typeName: ''
}, },
rules: { rules: {
typeName: [ typeName: [{ required: true, message: '请输入设备类型名称', trigger: 'blur' }],
{ required: true, message: '请输入设备类型名称', trigger: 'blur' }, appModelDictionary: [{ required: true, message: '请选择类型code', trigger: 'blur' }],
], locateMode: [{ required: true, message: '请选择定位方式', trigger: 'blur' }],
appModelDictionary: [ communicationMode: [{ required: true, message: '请选择通讯方式', trigger: 'blur' }]
{ required: true, message: '请选择类型code', trigger: 'blur' },
],
locateMode: [
{ required: true, message: '请选择定位方式', trigger: 'blur' },
],
communicationMode: [
{ required: true, message: '请选择通讯方式', trigger: 'blur' },
],
} }
}; };
const data = reactive<{ const data = reactive<{
form: DeviceTypeForm, form: DeviceTypeForm;
queryParams: deviceTypeQuery, queryParams: deviceTypeQuery;
rules: any rules: any;
}>(initData); }>(initData);
const { queryParams, form, rules } = toRefs(data); const { queryParams, form, rules } = toRefs(data);
@ -252,11 +267,11 @@ const getList = async () => {
const getDict = async () => { const getDict = async () => {
const res = await getDicts('app_model_dictionary'); const res = await getDicts('app_model_dictionary');
appmodelDictionaryOptions.value = res.data; appmodelDictionaryOptions.value = res.data;
} };
const pcgetDict = async () => { const pcgetDict = async () => {
const res = await getDicts('pc_model_dictionary'); const res = await getDicts('pc_model_dictionary');
pcmodelDictionaryOptions.value = res.data; pcmodelDictionaryOptions.value = res.data;
} };
/** 搜索按钮操作 */ /** 搜索按钮操作 */
const handleQuery = () => { const handleQuery = () => {
queryParams.value.pageNum = 1; queryParams.value.pageNum = 1;
@ -270,13 +285,9 @@ const resetQuery = () => {
}; };
// PC路由变化时同步对应APP路由 // PC路由变化时同步对应APP路由
const handlePcRouteChange = (pcDictValue: string) => { const handlePcRouteChange = (pcDictValue: string) => {
const selectedPcItem = appmodelDictionaryOptions.value.find( const selectedPcItem = appmodelDictionaryOptions.value.find((item) => item.dictValue === pcDictValue);
item => item.dictValue === pcDictValue
);
if (!selectedPcItem) return; if (!selectedPcItem) return;
const matchedAppItem = pcmodelDictionaryOptions.value.find( const matchedAppItem = pcmodelDictionaryOptions.value.find((item) => item.dictLabel === selectedPcItem.dictLabel);
item => item.dictLabel === selectedPcItem.dictLabel
);
if (matchedAppItem) { if (matchedAppItem) {
form.value.pcModelDictionary = matchedAppItem.dictValue; form.value.pcModelDictionary = matchedAppItem.dictValue;
} else { } else {
@ -287,13 +298,15 @@ const handlePcRouteChange = (pcDictValue: string) => {
/** 删除按钮操作 */ /** 删除按钮操作 */
const handleDelete = async (row?: deviceTypeVO) => { const handleDelete = async (row?: deviceTypeVO) => {
const deviceTypeIds = row ? [row.id] : ids.value.map(item => item.id); const deviceTypeIds = row ? [row.id] : ids.value.map((item) => item.id);
const typeNames = row ? row.typeName : ids.value.map(item => item.typeName).join(','); const typeNames = row ? row.typeName : ids.value.map((item) => item.typeName).join(',');
const [err] = await to(proxy?.$modal.confirm('是否确认删除"' + typeNames + '"的数据项?', '系统提示', { const [err] = await to(
confirmButtonText: '确定', proxy?.$modal.confirm('是否确认删除"' + typeNames + '"的数据项?', '系统提示', {
cancelButtonText: '取消', confirmButtonText: '确定',
type: 'warning' cancelButtonText: '取消',
}) as any); type: 'warning'
}) as any
);
if (!err) { if (!err) {
await api.deleteDeviceType(deviceTypeIds); await api.deleteDeviceType(deviceTypeIds);
await getList(); await getList();
@ -350,7 +363,7 @@ const submitForm = () => {
if (valid) { if (valid) {
loadingIng.value = true; loadingIng.value = true;
try { try {
const payload = { let payload = {
...form.value, ...form.value,
appModelDictionary: form.value.appModelDictionary, appModelDictionary: form.value.appModelDictionary,
pcModelDictionary: form.value.pcModelDictionary, pcModelDictionary: form.value.pcModelDictionary,
@ -358,7 +371,27 @@ const submitForm = () => {
locateMode: Number(form.value.locateMode), locateMode: Number(form.value.locateMode),
communicationMode: Number(form.value.communicationMode) communicationMode: Number(form.value.communicationMode)
}; };
form.value.id ? await api.updateDeviceType(payload) : await api.addDeviceType(payload);
let formData = new FormData();
let keys=Object.keys(payload);
keys.forEach(key=>{
if(key!=='devicePic'){
if(payload[key]!==null && payload[key]!==undefined){
formData.append(key,payload[key]);
}
}
});
if(uploadFile && fileC && fileC.files.length){
formData.append('file',fileC.files[0]);
}
//如果要上传文件就用formData,不上传使用payload
form.value.id ? await api.updateDeviceType(formData) : await api.addDeviceType(formData);
proxy?.$modal.msgSuccess('操作成功'); proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false; dialog.visible = false;
await getList(); await getList();
@ -369,6 +402,25 @@ const submitForm = () => {
}); });
}; };
//删除图片
function DropImg(item) {
ElMessageBox.confirm('删除后不可恢复,您确认要删除吗?', '提醒', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
form.value.devicePic = null;
})
.catch(() => {});
}
//选择图片
function AddImg(item) {
uploadFile=false;
initControl();
fileC.click();
}
/** /**
* 关闭用户弹窗 * 关闭用户弹窗
*/ */
@ -386,9 +438,106 @@ const resetForm = () => {
form.value.id = ''; form.value.id = '';
}; };
function initControl() {
if (fileC) {
fileC.value="";
return;
}
fileC = document.getElementById('fileTypeImg');
fileC.addEventListener('change', function () {
if (this.files.length) {
let file = this.files[0];
if (file.type.indexOf('image/') === 0) {
let reader = new FileReader();
reader.onload = function (e) {
uploadFile=true;
form.value.devicePic = e.target.result;
};
reader.onerror = function () {
console.log('读取文件失败!');
};
reader.readAsDataURL(file);
} else {
// form.value.devicePic = null;
}
} else {
// form.value.devicePic = null;
}
});
}
onMounted(() => { onMounted(() => {
getList(); // 初始化列表数据 getList(); // 初始化列表数据
getDict(); getDict();
pcgetDict() //pc跳转 pcgetDict(); //pc跳转
}); });
</script> </script>
<style>
.devicePic {
width: 120px;
height: 120px;
border-radius: 6px;
box-sizing: border-box;
overflow: hidden;
}
.typeImgContent {
background-color: #ffffff;
border: 1px solid rgb(220, 223, 230);
position: relative;
}
.typeImgContent .img {
width: 100%;
height: 100%;
object-fit: contain;
position: absolute;
top: 0px;
left: 0px;
z-index: 0;
padding: 10px;
}
.center {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
align-items: center;
justify-content: center;
}
.typeImgAdd {
background-color: #fafafa;
border: 1px dashed rgb(205, 208, 214);
font-size: 30px;
cursor: pointer;
}
.mask {
background-color: #1c1c1c80;
position: absolute;
top: 0px;
left: 0px;
z-index: 1;
width: 0px;
height: 0px;
cursor: pointer;
overflow: hidden;
color: #ff0000;
font-size: 25px;
}
.typeImgContent:hover .mask {
width: 100%;
height: 100%;
}
</style>