bugfix
This commit is contained in:
31
src/api/config.js
Normal file
31
src/api/config.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// 省列表
|
||||||
|
import request from "@/utils/request";
|
||||||
|
|
||||||
|
export function provinceList() {
|
||||||
|
return request({
|
||||||
|
url: "/system/region/allProvince",
|
||||||
|
method: "get",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 市列表
|
||||||
|
export function cityList(provinceCode) {
|
||||||
|
return request({
|
||||||
|
url: "/system/region/allCity",
|
||||||
|
method: "get",
|
||||||
|
params: {
|
||||||
|
provinceCode,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 县区列表
|
||||||
|
export function districtList(cityCode) {
|
||||||
|
return request({
|
||||||
|
url: "/system/region/allArea",
|
||||||
|
method: "get",
|
||||||
|
params: {
|
||||||
|
cityCode,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
202
src/components/CityOptions/index.vue
Normal file
202
src/components/CityOptions/index.vue
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
<template>
|
||||||
|
<el-form
|
||||||
|
ref="formRef"
|
||||||
|
:label-width="`${labelWidth}px`"
|
||||||
|
:model="modelValue"
|
||||||
|
:rules="rules"
|
||||||
|
>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="所在地:" required>
|
||||||
|
<el-row justify="space-between" type="flex">
|
||||||
|
<el-col :span="7">
|
||||||
|
<el-form-item prop="provinceCode">
|
||||||
|
<el-select
|
||||||
|
v-model="modelValue.provinceCode"
|
||||||
|
:disabled="provinceSelectList.length === 0"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
placeholder="请选择"
|
||||||
|
@change="provinceChanged"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in provinceSelectList"
|
||||||
|
:key="item.provinceCode"
|
||||||
|
:label="item.provinceName"
|
||||||
|
:value="item.provinceCode"
|
||||||
|
>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="7">
|
||||||
|
<el-form-item prop="cityCode">
|
||||||
|
<el-select
|
||||||
|
v-model="modelValue.cityCode"
|
||||||
|
:disabled="citySelectList.length === 0"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
placeholder="请选择"
|
||||||
|
@change="cityChanged"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in citySelectList"
|
||||||
|
:key="item.cityCode"
|
||||||
|
:label="item.cityName"
|
||||||
|
:value="item.cityCode"
|
||||||
|
>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="7">
|
||||||
|
<el-form-item prop="areaCode">
|
||||||
|
<el-select
|
||||||
|
v-model="modelValue.areaCode"
|
||||||
|
:disabled="districtSelectList.length === 0"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
placeholder="请选择"
|
||||||
|
@change="areaChanged"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in districtSelectList"
|
||||||
|
:key="item.areaCode"
|
||||||
|
:label="item.areaName"
|
||||||
|
:value="item.areaCode"
|
||||||
|
>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
<script name="CityOptions" setup>
|
||||||
|
import { cityList, districtList, provinceList } from "@/api/config";
|
||||||
|
|
||||||
|
import { reactive, ref, toRefs, watch } from "vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: Object,
|
||||||
|
labelWidth: {
|
||||||
|
type: Number,
|
||||||
|
default: 120
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const { modelValue, labelWidth } = toRefs(props);
|
||||||
|
const formRef = ref(null);
|
||||||
|
const provinceSelectList = ref([]); // 省
|
||||||
|
const citySelectList = ref([]); // 市
|
||||||
|
const districtSelectList = ref([]); // 区\
|
||||||
|
const data = reactive({
|
||||||
|
rules: {
|
||||||
|
provinceCode: [
|
||||||
|
{ required: true, message: "请选择", trigger: ["change", "blue"] }
|
||||||
|
],
|
||||||
|
cityCode: [{ required: true, message: "请选择", trigger: ["change", "blue"] }],
|
||||||
|
areaCode: [
|
||||||
|
{ required: true, message: "请选择", trigger: ["change", "blue"] }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const { rules } = toRefs(data);
|
||||||
|
// 获取 省列表
|
||||||
|
const getProvinceList = async () => {
|
||||||
|
const resp = await provinceList();
|
||||||
|
provinceSelectList.value = resp.data.map((el) => {
|
||||||
|
return { ...el, provinceCode: el.provinceCode.toString() };
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 获取市列表
|
||||||
|
const getCityListByProvinceId = async (provinceId) => {
|
||||||
|
const { data } = await cityList(provinceId);
|
||||||
|
citySelectList.value = data.map((el) => {
|
||||||
|
return {
|
||||||
|
...el,
|
||||||
|
cityCode: el.cityCode.toString()
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 根据市id获取县区列表
|
||||||
|
const getAreaListByCityId = async (cityId) => {
|
||||||
|
const { data } = await districtList(cityId);
|
||||||
|
districtSelectList.value = data.map((el) => {
|
||||||
|
return {
|
||||||
|
...el,
|
||||||
|
areaCode: el.areaCode.toString()
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 当省改变时
|
||||||
|
const provinceChanged = (val) => {
|
||||||
|
if (val) {
|
||||||
|
modelValue.value.provinceName = provinceSelectList.value.find(el => el.provinceCode === val)?.provinceName;
|
||||||
|
} else {
|
||||||
|
modelValue.value.provinceName = undefined;
|
||||||
|
}
|
||||||
|
// 清除市县代码列表
|
||||||
|
modelValue.value.cityCode = undefined;
|
||||||
|
modelValue.value.areaCode = undefined;
|
||||||
|
// 清除市县列表
|
||||||
|
citySelectList.value = [];
|
||||||
|
districtSelectList.value = [];
|
||||||
|
};
|
||||||
|
// 当市改变时
|
||||||
|
const cityChanged = (val) => {
|
||||||
|
if (val) {
|
||||||
|
modelValue.value.cityName = citySelectList.value.find(el => el.cityCode === val)?.cityName;
|
||||||
|
} else {
|
||||||
|
modelValue.value.cityName = undefined;
|
||||||
|
}
|
||||||
|
// 清除县区代码列表
|
||||||
|
modelValue.value.areaCode = undefined;
|
||||||
|
districtSelectList.value = [];
|
||||||
|
};
|
||||||
|
const areaChanged = (val) => {
|
||||||
|
if (val) {
|
||||||
|
modelValue.value.areaName = districtSelectList.value.find(el => el.areaCode === val)?.areaName;
|
||||||
|
} else {
|
||||||
|
modelValue.value.areaName = undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const validateForm = async () => {
|
||||||
|
try {
|
||||||
|
return await formRef.value.validate();
|
||||||
|
} catch (error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => modelValue.value.provinceCode,
|
||||||
|
(val) => {
|
||||||
|
console.log("changed province");
|
||||||
|
val && getCityListByProvinceId(val);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => modelValue.value.cityCode,
|
||||||
|
(val) => {
|
||||||
|
console.log("changed city");
|
||||||
|
val && getAreaListByCityId(val);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
getProvinceList();
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
validateForm
|
||||||
|
});
|
||||||
|
</script>
|
@ -187,7 +187,7 @@ onMounted(async () => {
|
|||||||
left: 0;
|
left: 0;
|
||||||
top: 10px;
|
top: 10px;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
z-index: 202333;
|
z-index: 120;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -57,6 +57,10 @@ export const constantRoutes = [
|
|||||||
component: () => import("@/views/sign_in_with.vue"),
|
component: () => import("@/views/sign_in_with.vue"),
|
||||||
hidden: true,
|
hidden: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/test",
|
||||||
|
component: () => import("@/views/test/index.vue"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/:pathMatch(.*)*",
|
path: "/:pathMatch(.*)*",
|
||||||
component: () => import("@/views/error/404"),
|
component: () => import("@/views/error/404"),
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
<el-input
|
<el-input
|
||||||
v-model="form.serialNumber"
|
v-model="form.serialNumber"
|
||||||
:disabled="!!route.query.id"
|
:disabled="!!route.query.id"
|
||||||
|
maxlength="15"
|
||||||
placeholder="请输入设备编号"
|
placeholder="请输入设备编号"
|
||||||
>
|
>
|
||||||
<template #append>
|
<template #append>
|
||||||
@ -35,10 +36,13 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="产品" prop="productId">
|
<el-form-item label="产品" prop="productId">
|
||||||
<!-- <el-input v-model="form.productId" placeholder="请输入产品ID" />-->
|
<!-- <el-input v-model="form.productId" placeholder="请输入产品ID" />-->
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
<el-select
|
<el-select
|
||||||
v-model="form.productId"
|
v-model="form.productId"
|
||||||
:remote-method="getProductOptions"
|
:remote-method="getProductOptions"
|
||||||
clearable
|
clearable
|
||||||
|
disabled
|
||||||
filterable
|
filterable
|
||||||
placeholder="请选择产品"
|
placeholder="请选择产品"
|
||||||
remote
|
remote
|
||||||
@ -51,18 +55,26 @@
|
|||||||
:value="item.productId"
|
:value="item.productId"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="产品编号">
|
||||||
|
<el-input v-model="form.productSn" disabled></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="MQTT账号" prop="mqttAccount">
|
<el-form-item label="MQTT账号" prop="mqttAccount">
|
||||||
<el-input v-model="form.mqttAccount" disabled></el-input>
|
<el-input v-model="form.mqttAccount" disabled></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<!-- <el-col :span="12">-->
|
||||||
<el-form-item label="MQTT密码" prop="mqttPassword">
|
<!-- <el-form-item label="MQTT密码" prop="mqttPassword">-->
|
||||||
<el-input v-model="form.mqttPassword" disabled></el-input>
|
<!-- <el-input v-model="form.mqttPassword" disabled></el-input>-->
|
||||||
</el-form-item>
|
<!-- </el-form-item>-->
|
||||||
</el-col>
|
<!-- </el-col>-->
|
||||||
</el-row>
|
</el-row>
|
||||||
<!-- <el-form-item label="定位方式" prop="locationWay">-->
|
<!-- <el-form-item label="定位方式" prop="locationWay">-->
|
||||||
<!-- <el-select-->
|
<!-- <el-select-->
|
||||||
@ -74,20 +86,21 @@
|
|||||||
<!-- <el-option :value="3" label="自定义" />-->
|
<!-- <el-option :value="3" label="自定义" />-->
|
||||||
<!-- </el-select>-->
|
<!-- </el-select>-->
|
||||||
<!-- </el-form-item>-->
|
<!-- </el-form-item>-->
|
||||||
|
<CityOptions ref="cityRef" v-model="form" :label-width="140" />
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="设备经度" prop="longitude">
|
<el-form-item label="设备经度" prop="longitude">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="form.longitude"
|
v-model="form.longitude"
|
||||||
|
disabled
|
||||||
placeholder="请输入设备经度"
|
placeholder="请输入设备经度"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="设备纬度" prop="latitude">
|
<el-form-item label="设备纬度" prop="latitude">
|
||||||
<el-input
|
<el-input v-model="form.latitude"
|
||||||
v-model="form.latitude"
|
disabled
|
||||||
placeholder="请输入设备纬度"
|
placeholder="请输入设备纬度"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -156,7 +169,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onActivated, onMounted, reactive, ref, toRefs } from "vue";
|
import { onMounted, reactive, ref, toRefs } from "vue";
|
||||||
import { listProduct } from "@/api/product/product";
|
import { listProduct } from "@/api/product/product";
|
||||||
import OperatingStatus from "@/views/iot/device/detail-panes/OperatingStatus.vue";
|
import OperatingStatus from "@/views/iot/device/detail-panes/OperatingStatus.vue";
|
||||||
import { addDevice, getDevice, updateDevice } from "@/api/iot/device";
|
import { addDevice, getDevice, updateDevice } from "@/api/iot/device";
|
||||||
@ -167,6 +180,7 @@ import UpgradeLog from "@/views/firmware/log/index.vue";
|
|||||||
import MapSelect from "@/components/MapSelect/index.vue";
|
import MapSelect from "@/components/MapSelect/index.vue";
|
||||||
import { generateRandomString } from "@/utils";
|
import { generateRandomString } from "@/utils";
|
||||||
import { listModel } from "@/api/thingsmodel/model";
|
import { listModel } from "@/api/thingsmodel/model";
|
||||||
|
import CityOptions from "@/components/CityOptions";
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
@ -176,15 +190,17 @@ const data = reactive({
|
|||||||
form: {},
|
form: {},
|
||||||
rules: {
|
rules: {
|
||||||
deviceName: [
|
deviceName: [
|
||||||
{ required: true, message: "设备名称不能为空", trigger: "blur" },
|
{ required: true, message: "设备名称不能为空", trigger: "blur" }
|
||||||
],
|
],
|
||||||
serialNumber: [
|
serialNumber: [
|
||||||
{ required: true, message: "设备编号不能为空", trigger: "blur" },
|
{ required: true, message: "设备编号不能为空", trigger: "blur" },
|
||||||
|
{ pattern: /^[a-zA-Z0-9]+$/, message: "只能包含字母和数字", trigger: "blur" }
|
||||||
],
|
],
|
||||||
productId: [{ required: true, message: "产品ID不能为空", trigger: "blur" }],
|
productId: [{ required: true, message: "产品ID不能为空", trigger: "blur" }]
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
const { form, rules } = toRefs(data);
|
const { form, rules } = toRefs(data);
|
||||||
|
const cityRef = ref();
|
||||||
|
|
||||||
// 表单重置
|
// 表单重置
|
||||||
function reset() {
|
function reset() {
|
||||||
@ -210,7 +226,7 @@ function reset() {
|
|||||||
imgUrl: null,
|
imgUrl: null,
|
||||||
createBy: null,
|
createBy: null,
|
||||||
createTime: null,
|
createTime: null,
|
||||||
remark: null,
|
remark: null
|
||||||
};
|
};
|
||||||
if (deviceRef.value) {
|
if (deviceRef.value) {
|
||||||
deviceRef.value.resetFields();
|
deviceRef.value.resetFields();
|
||||||
@ -219,8 +235,9 @@ function reset() {
|
|||||||
|
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
function submitForm() {
|
function submitForm() {
|
||||||
deviceRef.value.validate((valid) => {
|
deviceRef.value.validate(async (valid) => {
|
||||||
if (valid) {
|
const cityValid = await cityRef.value.validateForm();
|
||||||
|
if (valid && cityValid) {
|
||||||
if (form.value.deviceId != null) {
|
if (form.value.deviceId != null) {
|
||||||
updateDevice(form.value).then((response) => {
|
updateDevice(form.value).then((response) => {
|
||||||
ElMessage.success("修改成功");
|
ElMessage.success("修改成功");
|
||||||
@ -239,7 +256,7 @@ function getProductOptions(keyword) {
|
|||||||
listProduct({
|
listProduct({
|
||||||
productName: keyword,
|
productName: keyword,
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 20,
|
pageSize: 20
|
||||||
}).then((resp) => {
|
}).then((resp) => {
|
||||||
productOptions.value = resp.rows;
|
productOptions.value = resp.rows;
|
||||||
});
|
});
|
||||||
@ -261,14 +278,26 @@ const modelList = ref([]);
|
|||||||
const getThingsModel = () => {
|
const getThingsModel = () => {
|
||||||
if (form.value.productId) {
|
if (form.value.productId) {
|
||||||
listModel({
|
listModel({
|
||||||
productId: form.value.productId,
|
productId: form.value.productId
|
||||||
}).then((resp) => {
|
}).then((resp) => {
|
||||||
modelList.value = resp.rows ?? [];
|
modelList.value = resp.rows ?? [];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// watch(() => form.value.productId, (val) => {
|
||||||
|
// if (val) {
|
||||||
|
// form.value.productSn = productOptions.value.find(el => el.productId === val)?.productSn ?? undefined;
|
||||||
|
// } else {
|
||||||
|
// form.value.productSn = undefined;
|
||||||
|
// }
|
||||||
|
// }, {
|
||||||
|
// // immediate: true
|
||||||
|
// });
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
getProductOptions();
|
||||||
await getDeviceDetail();
|
await getDeviceDetail();
|
||||||
getThingsModel();
|
getThingsModel();
|
||||||
// AMap.value = await loadMap(["AMap.PlaceSearch"]);
|
// AMap.value = await loadMap(["AMap.PlaceSearch"]);
|
||||||
@ -285,7 +314,7 @@ onMounted(async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
getProductOptions();
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -214,32 +214,25 @@
|
|||||||
>
|
>
|
||||||
<el-table-column align="center" type="selection" width="55" />
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
<!-- <el-table-column align="center" label="设备ID" prop="deviceId" />-->
|
<!-- <el-table-column align="center" label="设备ID" prop="deviceId" />-->
|
||||||
<el-table-column align="center" label="设备名称" prop="deviceName" />
|
<el-table-column align="center" label="设备名称" prop="deviceName" show-overflow-tooltip/>
|
||||||
<el-table-column align="center" label="设备编号" prop="serialNumber" />
|
<el-table-column align="center" label="设备编号" prop="serialNumber" />
|
||||||
<el-table-column align="center" label="产品" prop="productName" />
|
<el-table-column align="center" label="产品" prop="productName" />
|
||||||
<!-- <el-table-column align="center" label="用户" prop="userName" />-->
|
<!-- <el-table-column align="center" label="用户" prop="userName" />-->
|
||||||
<!-- <el-table-column align="center" label="租户" prop="tenantName" />-->
|
<!-- <el-table-column align="center" label="租户" prop="tenantName" />-->
|
||||||
<!-- <el-table-column align="center" label="固件版本" prop="firmwareVersion" />-->
|
<!-- <el-table-column align="center" label="固件版本" prop="firmwareVersion" />-->
|
||||||
<el-table-column align="center" label="设备状态" prop="status">
|
|
||||||
<template #default="{ row }">
|
<el-table-column align="center" label="产品编码" prop="productSn" />
|
||||||
<dict-tag
|
|
||||||
:options="deviceStatusMap"
|
|
||||||
:value="[row.status]"
|
|
||||||
effect="dark"
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<!-- <el-table-column align="center" label="信号强度" prop="rssi" />-->
|
<!-- <el-table-column align="center" label="信号强度" prop="rssi" />-->
|
||||||
<el-table-column align="center" label="是否启用设备影子" prop="isShadow">
|
<!-- <el-table-column align="center" label="是否启用设备影子" prop="isShadow">-->
|
||||||
<template #default="{ row }">
|
<!-- <template #default="{ row }">-->
|
||||||
<dict-tag
|
<!-- <dict-tag-->
|
||||||
:options="isShadowDict"
|
<!-- :options="isShadowDict"-->
|
||||||
:value="[row.isShadow]"
|
<!-- :value="[row.isShadow]"-->
|
||||||
size="small"
|
<!-- size="small"-->
|
||||||
/>
|
<!-- />-->
|
||||||
</template>
|
<!-- </template>-->
|
||||||
</el-table-column>
|
<!-- </el-table-column>-->
|
||||||
<!-- <el-table-column align="center" label="定位方式" prop="locationWay">-->
|
<!-- <el-table-column align="center" label="定位方式" prop="locationWay">-->
|
||||||
<!-- <template #default="{ row }">-->
|
<!-- <template #default="{ row }">-->
|
||||||
<!-- {{ locationWayMap.find((el) => el.value === row.locationWay)?.label }}-->
|
<!-- {{ locationWayMap.find((el) => el.value === row.locationWay)?.label }}-->
|
||||||
@ -250,11 +243,11 @@
|
|||||||
label="MQTT账号"
|
label="MQTT账号"
|
||||||
prop="mqttAccount"
|
prop="mqttAccount"
|
||||||
></el-table-column>
|
></el-table-column>
|
||||||
<el-table-column
|
<!-- <el-table-column-->
|
||||||
align="center"
|
<!-- align="center"-->
|
||||||
label="MQTT密码"
|
<!-- label="MQTT密码"-->
|
||||||
prop="mqttPassword"
|
<!-- prop="mqttPassword"-->
|
||||||
></el-table-column>
|
<!-- ></el-table-column>-->
|
||||||
<!-- <el-table-column align="center" label="物模型值" prop="thingsModelValue" />-->
|
<!-- <el-table-column align="center" label="物模型值" prop="thingsModelValue" />-->
|
||||||
<!-- <el-table-column align="center" label="设备所在地址" prop="networkAddress" />-->
|
<!-- <el-table-column align="center" label="设备所在地址" prop="networkAddress" />-->
|
||||||
<!-- <el-table-column align="center" label="设备入网IP" prop="networkIp" />-->
|
<!-- <el-table-column align="center" label="设备入网IP" prop="networkIp" />-->
|
||||||
@ -279,7 +272,16 @@
|
|||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column align="center" label="设备状态" prop="status">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<dict-tag
|
||||||
|
:options="deviceStatusMap"
|
||||||
|
:value="[row.status]"
|
||||||
|
effect="dark"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
align="center"
|
align="center"
|
||||||
class-name="small-padding fixed-width"
|
class-name="small-padding fixed-width"
|
||||||
@ -334,7 +336,7 @@
|
|||||||
label-width="140px"
|
label-width="140px"
|
||||||
>
|
>
|
||||||
<el-form-item label="设备编号" prop="serialNumber">
|
<el-form-item label="设备编号" prop="serialNumber">
|
||||||
<el-input v-model="form.serialNumber" placeholder="请输入设备编号">
|
<el-input v-model="form.serialNumber" maxlength="15" placeholder="请输入设备编号">
|
||||||
<template #append>
|
<template #append>
|
||||||
<el-button @click="geneDeivceSn">自动生成</el-button>
|
<el-button @click="geneDeivceSn">自动生成</el-button>
|
||||||
</template>
|
</template>
|
||||||
@ -400,18 +402,19 @@
|
|||||||
<!-- </el-col>-->
|
<!-- </el-col>-->
|
||||||
<el-col :span="12"></el-col>
|
<el-col :span="12"></el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="20">
|
<CityOptions ref="cityRef" v-model="form" :label-width="140" />
|
||||||
<el-col :span="12">
|
<!-- <el-row :gutter="20">-->
|
||||||
<el-form-item label="设备经度" prop="longitude">
|
<!-- <el-col :span="12">-->
|
||||||
<el-input v-model="form.longitude" placeholder="请输入设备经度" />
|
<!-- <el-form-item label="设备经度" prop="longitude">-->
|
||||||
</el-form-item>
|
<!-- <el-input v-model="form.longitude" placeholder="请输入设备经度" />-->
|
||||||
</el-col>
|
<!-- </el-form-item>-->
|
||||||
<el-col :span="12">
|
<!-- </el-col>-->
|
||||||
<el-form-item label="设备纬度" prop="latitude">
|
<!-- <el-col :span="12">-->
|
||||||
<el-input v-model="form.latitude" placeholder="请输入设备纬度" />
|
<!-- <el-form-item label="设备纬度" prop="latitude">-->
|
||||||
</el-form-item>
|
<!-- <el-input v-model="form.latitude" placeholder="请输入设备纬度" />-->
|
||||||
</el-col>
|
<!-- </el-form-item>-->
|
||||||
</el-row>
|
<!-- </el-col>-->
|
||||||
|
<!-- </el-row>-->
|
||||||
<el-form-item label="设备所在地址" prop="networkAddress">
|
<el-form-item label="设备所在地址" prop="networkAddress">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="form.networkAddress"
|
v-model="form.networkAddress"
|
||||||
@ -480,29 +483,17 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script name="Device" setup>
|
<script name="Device" setup>
|
||||||
import {
|
import { addDevice, delDevice, getDevice, listDevice, updateDevice } from "@/api/iot/device";
|
||||||
addDevice,
|
|
||||||
delDevice,
|
|
||||||
getDevice,
|
|
||||||
listDevice,
|
|
||||||
updateDevice,
|
|
||||||
} from "@/api/iot/device";
|
|
||||||
import { listProduct } from "@/api/product/product";
|
import { listProduct } from "@/api/product/product";
|
||||||
import { deviceStatusMap, isShadowDict } from "@/constant/dict";
|
import { deviceStatusMap } from "@/constant/dict";
|
||||||
import UserTreeSelect from "@/components/UserTreeSelect/index.vue";
|
import UserTreeSelect from "@/components/UserTreeSelect/index.vue";
|
||||||
import {
|
import { getCurrentInstance, reactive, ref, shallowRef, toRefs, watch, watchEffect } from "vue";
|
||||||
getCurrentInstance,
|
|
||||||
reactive,
|
|
||||||
ref,
|
|
||||||
shallowRef,
|
|
||||||
toRefs,
|
|
||||||
watchEffect,
|
|
||||||
} from "vue";
|
|
||||||
import DictTag from "@/components/DictTag/index.vue";
|
import DictTag from "@/components/DictTag/index.vue";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import { loadMap } from "@/utils/amap";
|
import { loadMap } from "@/utils/amap";
|
||||||
import MapSelect from "@/components/MapSelect/index.vue";
|
import MapSelect from "@/components/MapSelect/index.vue";
|
||||||
import { generateRandomString } from "@/utils";
|
import { generateRandomString } from "@/utils";
|
||||||
|
import CityOptions from "@/components/CityOptions";
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { proxy } = getCurrentInstance();
|
const { proxy } = getCurrentInstance();
|
||||||
@ -510,10 +501,10 @@ const { proxy } = getCurrentInstance();
|
|||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
productId: {
|
productId: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: null,
|
default: null
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
|
const cityRef = ref();
|
||||||
const deviceList = ref([]);
|
const deviceList = ref([]);
|
||||||
const open = ref(false);
|
const open = ref(false);
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
@ -548,17 +539,18 @@ const data = reactive({
|
|||||||
latitude: null,
|
latitude: null,
|
||||||
activeTime: null,
|
activeTime: null,
|
||||||
summary: null,
|
summary: null,
|
||||||
imgUrl: null,
|
imgUrl: null
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
deviceName: [
|
deviceName: [
|
||||||
{ required: true, message: "设备名称不能为空", trigger: "blur" },
|
{ required: true, message: "设备名称不能为空", trigger: "blur" }
|
||||||
],
|
],
|
||||||
serialNumber: [
|
serialNumber: [
|
||||||
{ required: true, message: "设备编号不能为空", trigger: "blur" },
|
{ required: true, message: "设备编号不能为空", trigger: "blur" },
|
||||||
|
{ pattern: /^[a-zA-Z0-9]+$/, message: "只能包含字母和数字", trigger: "blur" }
|
||||||
],
|
],
|
||||||
productId: [{ required: true, message: "产品ID不能为空", trigger: "blur" }],
|
productId: [{ required: true, message: "产品ID不能为空", trigger: "blur" }]
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const { queryParams, form, rules } = toRefs(data);
|
const { queryParams, form, rules } = toRefs(data);
|
||||||
@ -608,7 +600,7 @@ function reset() {
|
|||||||
imgUrl: null,
|
imgUrl: null,
|
||||||
createBy: null,
|
createBy: null,
|
||||||
createTime: null,
|
createTime: null,
|
||||||
remark: null,
|
remark: null
|
||||||
};
|
};
|
||||||
proxy.resetForm("deviceRef");
|
proxy.resetForm("deviceRef");
|
||||||
}
|
}
|
||||||
@ -619,6 +611,16 @@ function handleQuery() {
|
|||||||
getList();
|
getList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
watch(() => form.value.productId, (val) => {
|
||||||
|
if (val) {
|
||||||
|
form.value.productSn = productOptions.value.find(el => el.productId === val)?.productSn ?? undefined;
|
||||||
|
} else {
|
||||||
|
form.value.productSn = undefined;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
immediate: true
|
||||||
|
});
|
||||||
const geneDeivceSn = () => {
|
const geneDeivceSn = () => {
|
||||||
form.value.serialNumber = generateRandomString(11);
|
form.value.serialNumber = generateRandomString(11);
|
||||||
};
|
};
|
||||||
@ -645,7 +647,7 @@ async function handleAdd() {
|
|||||||
if (!AMap.value) AMap.value = await loadMap([]);
|
if (!AMap.value) AMap.value = await loadMap([]);
|
||||||
if (!map.value)
|
if (!map.value)
|
||||||
map.value = new AMap.value.Map("map-container", {
|
map.value = new AMap.value.Map("map-container", {
|
||||||
zoom: 11,
|
zoom: 11
|
||||||
});
|
});
|
||||||
map.value.on("click", handleMapClick);
|
map.value.on("click", handleMapClick);
|
||||||
}
|
}
|
||||||
@ -667,8 +669,9 @@ function handleDetail(row) {
|
|||||||
|
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
function submitForm() {
|
function submitForm() {
|
||||||
proxy.$refs["deviceRef"].validate((valid) => {
|
proxy.$refs["deviceRef"].validate(async (valid) => {
|
||||||
if (valid) {
|
const cityValid = await cityRef.value.validateForm();
|
||||||
|
if (valid && cityValid) {
|
||||||
if (form.value.deviceId != null) {
|
if (form.value.deviceId != null) {
|
||||||
updateDevice(form.value).then((response) => {
|
updateDevice(form.value).then((response) => {
|
||||||
proxy.$modal.msgSuccess("修改成功");
|
proxy.$modal.msgSuccess("修改成功");
|
||||||
@ -677,7 +680,7 @@ function submitForm() {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
form.value.mqttAccount = form.value.serialNumber;
|
form.value.mqttAccount = form.value.serialNumber;
|
||||||
form.value.mqttPassword = generateRandomString(11);
|
// form.value.mqttPassword = generateRandomString(11);
|
||||||
addDevice(form.value).then((response) => {
|
addDevice(form.value).then((response) => {
|
||||||
proxy.$modal.msgSuccess("新增成功");
|
proxy.$modal.msgSuccess("新增成功");
|
||||||
open.value = false;
|
open.value = false;
|
||||||
@ -692,7 +695,7 @@ function submitForm() {
|
|||||||
function handleDelete(row) {
|
function handleDelete(row) {
|
||||||
const _deviceIds = row.deviceId || ids.value;
|
const _deviceIds = row.deviceId || ids.value;
|
||||||
proxy.$modal
|
proxy.$modal
|
||||||
.confirm('是否确认删除设备编号为"' + _deviceIds + '"的数据项?')
|
.confirm("是否确认删除设备编号为\"" + _deviceIds + "\"的数据项?")
|
||||||
.then(function() {
|
.then(function() {
|
||||||
return delDevice(_deviceIds);
|
return delDevice(_deviceIds);
|
||||||
})
|
})
|
||||||
@ -700,7 +703,8 @@ function handleDelete(row) {
|
|||||||
getList();
|
getList();
|
||||||
proxy.$modal.msgSuccess("删除成功");
|
proxy.$modal.msgSuccess("删除成功");
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
@ -708,7 +712,7 @@ function handleExport() {
|
|||||||
proxy.download(
|
proxy.download(
|
||||||
"iot/device/export",
|
"iot/device/export",
|
||||||
{
|
{
|
||||||
...queryParams.value,
|
...queryParams.value
|
||||||
},
|
},
|
||||||
`device_${new Date().getTime()}.xlsx`
|
`device_${new Date().getTime()}.xlsx`
|
||||||
);
|
);
|
||||||
@ -718,7 +722,7 @@ function getProductOptions(keyword) {
|
|||||||
listProduct({
|
listProduct({
|
||||||
productName: keyword,
|
productName: keyword,
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 20,
|
pageSize: 20
|
||||||
}).then((resp) => {
|
}).then((resp) => {
|
||||||
productOptions.value = resp.rows;
|
productOptions.value = resp.rows;
|
||||||
});
|
});
|
||||||
@ -738,7 +742,7 @@ const handleMapClick = (event) => {
|
|||||||
form.value.latitude = lnglat.lat;
|
form.value.latitude = lnglat.lat;
|
||||||
form.value.longitude = lnglat.lng;
|
form.value.longitude = lnglat.lng;
|
||||||
const marker = new AMap.value.Marker({
|
const marker = new AMap.value.Marker({
|
||||||
position: lnglat,
|
position: lnglat
|
||||||
});
|
});
|
||||||
map.value.add(marker);
|
map.value.add(marker);
|
||||||
};
|
};
|
||||||
|
@ -236,7 +236,7 @@ function reset() {
|
|||||||
categoryId: null,
|
categoryId: null,
|
||||||
tenantId: null,
|
tenantId: null,
|
||||||
mqttAccount: null,
|
mqttAccount: null,
|
||||||
mqttPassword: null,
|
// mqttPassword: null,
|
||||||
mqttSecret: null,
|
mqttSecret: null,
|
||||||
status: null,
|
status: null,
|
||||||
thingsModelsJson: null,
|
thingsModelsJson: null,
|
||||||
|
@ -282,9 +282,9 @@
|
|||||||
<el-form-item label="mqtt账号" prop="mqttAccount">
|
<el-form-item label="mqtt账号" prop="mqttAccount">
|
||||||
<el-input v-model="form.mqttAccount" placeholder="请输入mqtt账号" />
|
<el-input v-model="form.mqttAccount" placeholder="请输入mqtt账号" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="mqtt密码" prop="mqttPassword">
|
<!-- <el-form-item label="mqtt密码" prop="mqttPassword">-->
|
||||||
<el-input v-model="form.mqttPassword" placeholder="请输入mqtt密码" />
|
<!-- <el-input v-model="form.mqttPassword" placeholder="请输入mqtt密码" />-->
|
||||||
</el-form-item>
|
<!-- </el-form-item>-->
|
||||||
<el-form-item label="产品秘钥" prop="mqttSecret">
|
<el-form-item label="产品秘钥" prop="mqttSecret">
|
||||||
<el-input v-model="form.mqttSecret" placeholder="请输入产品秘钥" />
|
<el-input v-model="form.mqttSecret" placeholder="请输入产品秘钥" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -353,7 +353,7 @@ const data = reactive({
|
|||||||
categoryId: null,
|
categoryId: null,
|
||||||
tenantId: null,
|
tenantId: null,
|
||||||
mqttAccount: null,
|
mqttAccount: null,
|
||||||
mqttPassword: null,
|
// mqttPassword: null,
|
||||||
mqttSecret: null,
|
mqttSecret: null,
|
||||||
status: null,
|
status: null,
|
||||||
thingsModelsJson: null,
|
thingsModelsJson: null,
|
||||||
@ -414,7 +414,7 @@ function reset() {
|
|||||||
categoryId: null,
|
categoryId: null,
|
||||||
tenantId: null,
|
tenantId: null,
|
||||||
mqttAccount: null,
|
mqttAccount: null,
|
||||||
mqttPassword: null,
|
// mqttPassword: null,
|
||||||
mqttSecret: null,
|
mqttSecret: null,
|
||||||
status: null,
|
status: null,
|
||||||
thingsModelsJson: null,
|
thingsModelsJson: null,
|
||||||
|
73
src/views/test/index.vue
Normal file
73
src/views/test/index.vue
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
const showSelectProvinceDialog = ref(true);
|
||||||
|
const selectedProvinceList = ref([]);
|
||||||
|
const provinceList = ref([
|
||||||
|
{ code: "11", name: "北京市" },
|
||||||
|
{ code: "12", name: "天津市" },
|
||||||
|
{ code: "13", name: "河北省" },
|
||||||
|
{ code: "14", name: "山西省" },
|
||||||
|
{ code: "15", name: "内蒙古自治区" },
|
||||||
|
{ code: "21", name: "辽宁省" },
|
||||||
|
{ code: "22", name: "吉林省" },
|
||||||
|
{ code: "23", name: "黑龙江省" },
|
||||||
|
{ code: "31", name: "上海市" },
|
||||||
|
{ code: "32", name: "江苏省" },
|
||||||
|
{ code: "33", name: "浙江省" },
|
||||||
|
{ code: "34", name: "安徽省" },
|
||||||
|
{ code: "35", name: "福建省" },
|
||||||
|
{ code: "36", name: "江西省" },
|
||||||
|
{ code: "37", name: "山东省" },
|
||||||
|
{ code: "41", name: "河南省" },
|
||||||
|
{ code: "42", name: "湖北省" },
|
||||||
|
{ code: "43", name: "湖南省" },
|
||||||
|
{ code: "44", name: "广东省" },
|
||||||
|
{ code: "45", name: "广西壮族自治区" },
|
||||||
|
{ code: "46", name: "海南省" },
|
||||||
|
{ code: "50", name: "重庆市" },
|
||||||
|
{ code: "51", name: "四川省" },
|
||||||
|
{ code: "52", name: "贵州省" },
|
||||||
|
{ code: "53", name: "云南省" },
|
||||||
|
{ code: "54", name: "西藏自治区" },
|
||||||
|
{ code: "61", name: "陕西省" },
|
||||||
|
{ code: "62", name: "甘肃省" },
|
||||||
|
{ code: "63", name: "青海省" },
|
||||||
|
{ code: "64", name: "宁夏回族自治区" },
|
||||||
|
{ code: "65", name: "新疆维吾尔自治区" },
|
||||||
|
{ code: "71", name: "台湾省" },
|
||||||
|
{ code: "81", name: "香港特别行政区" },
|
||||||
|
{ code: "82", name: "澳门特别行政区" }
|
||||||
|
]);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-dialog v-model="showSelectProvinceDialog" title="选择省份">
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
|
||||||
|
<el-tag v-for="item in selectedProvinceList" :key="item"
|
||||||
|
closable style="margin-left: 12px;margin-bottom: 8px" @close="selectedProvinceList=selectedProvinceList.filter(el=>el!==item)">
|
||||||
|
{{ provinceList.find(el => el.code === item)?.name ?? "" }}
|
||||||
|
</el-tag>
|
||||||
|
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-table :data="provinceList.filter(el=>!selectedProvinceList.includes(el.code))" max-height="420"
|
||||||
|
style="min-height: 420px">
|
||||||
|
<el-table-column label="编号" prop="code" />
|
||||||
|
<el-table-column label="名称" prop="name" />
|
||||||
|
<el-table-column>
|
||||||
|
<template #default="{row}">
|
||||||
|
<el-button icon="plus" type="primary" @click="selectedProvinceList.push(row.code)">添加省份</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
@ -31,7 +31,8 @@ export default defineConfig(({ mode, command }) => {
|
|||||||
proxy: {
|
proxy: {
|
||||||
// https://cn.vitejs.dev/config/#server-proxy
|
// https://cn.vitejs.dev/config/#server-proxy
|
||||||
"/dev-api": {
|
"/dev-api": {
|
||||||
target: "http://117.72.16.89/api",
|
target: "http://192.168.1.201:1616",
|
||||||
|
// target: "http://117.72.16.89/api",
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: (p) => p.replace(/^\/dev-api/, ""),
|
rewrite: (p) => p.replace(/^\/dev-api/, ""),
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user