model field

This commit is contained in:
2023-03-20 10:40:18 +08:00
parent 6f93d0b8de
commit 6a387d2c34
6 changed files with 196 additions and 49 deletions

View File

@ -8,20 +8,11 @@ export const deviceTypeMap = new Map([
[2, "网关子设备"], [2, "网关子设备"],
[3, "网关子设备"], [3, "网关子设备"],
]); ]);
export const vertificateMethodOptions = [ export const vertificateMethodOptions = new Map([
{ [1, "简单认证"],
label: "简单认证", [2, "加密认证"],
value: 1, [3, "简单+加密"],
}, ]);
{
label: "加密认证",
value: 2,
},
{
label: "简单+加密",
value: 3,
},
];
export const isTopMap = new Map([ export const isTopMap = new Map([
[0, "是"], [0, "是"],
@ -33,7 +24,18 @@ export const isMonitor = new Map([
[1, "否"], [1, "否"],
]); ]);
export const productStatusMap = [[1, ""]]; export const productStatusMap = [
{
label: "未发布",
value: 1,
tag: "info",
},
{
label: "已发布",
value: 2,
tag: "success",
},
];
export const firmwareLatestTypeOptions = [ export const firmwareLatestTypeOptions = [
{ {

View File

@ -79,8 +79,8 @@
<!-- </el-form-item>--> <!-- </el-form-item>-->
<el-form-item> <el-form-item>
<el-button icon="Search" type="primary" @click="handleQuery" <el-button icon="Search" type="primary" @click="handleQuery"
>搜索</el-button >搜索
> </el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button> <el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -234,6 +234,7 @@
<el-form-item label="产品" prop="productId"> <el-form-item label="产品" prop="productId">
<el-select <el-select
v-model="form.productId" v-model="form.productId"
:disabled="productId"
:remote-method="getProductOptions" :remote-method="getProductOptions"
filterable filterable
placeholder="请选择产品" placeholder="请选择产品"
@ -415,6 +416,9 @@ function handleSelectionChange(selection) {
/** 新增按钮操作 */ /** 新增按钮操作 */
function handleAdd() { function handleAdd() {
reset(); reset();
if (productId.value) {
form.value.productId = productId.value;
}
open.value = true; open.value = true;
title.value = "添加产品固件"; title.value = "添加产品固件";
} }

View File

@ -51,7 +51,7 @@
<!-- {{ isMonitor.get(row.isMonitor) ?? "未知" }}--> <!-- {{ isMonitor.get(row.isMonitor) ?? "未知" }}-->
<!-- </template>--> <!-- </template>-->
<!-- </el-table-column>--> <!-- </el-table-column>-->
<el-table-column align="center" label="物模型类别" prop="isMonitor"> <el-table-column align="center" label="物模型类别" prop="type">
<template #default="{ row }"> <template #default="{ row }">
<el-tag v-if="row.type === 3" size="small">事件</el-tag> <el-tag v-if="row.type === 3" size="small">事件</el-tag>
<el-tag v-else-if="row.type === 2" size="small">功能</el-tag> <el-tag v-else-if="row.type === 2" size="small">功能</el-tag>
@ -59,6 +59,38 @@
<el-tag v-else size="small">未知</el-tag> <el-tag v-else size="small">未知</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" label="数据类型" prop="datatype">
<template #default="{ row }">
<el-tag v-if="row.datatype === 'integer'" size="small">整数</el-tag>
<el-tag v-else-if="row.datatype === 'decimal'" size="small"
>小数</el-tag
>
<el-tag v-else-if="row.datatype === 'bool'" size="small">布尔</el-tag>
<el-tag v-else-if="row.datatype === 'enum'" size="small">枚举</el-tag>
<el-tag v-else-if="row.datatype === 'string'" size="small"
>字符串</el-tag
>
<el-tag v-else-if="row.datatype === 'array'" size="small"
>数组</el-tag
>
<el-tag v-else size="small">未知</el-tag>
</template>
</el-table-column>
<el-table-column align="center" label="是否只读" prop="isReadonly">
<template #default="{ row }">
<el-tag
:type="
row.isReadonly === 0
? 'success'
: row.isReadonly === 1
? 'warning'
: ''
"
>
{{ row.isReadonly === 0 ? "否" : row.isReadonly === 1 ? "是" : "" }}
</el-tag>
</template>
</el-table-column>
<el-table-column <el-table-column
align="left" align="left"
class-name="specsColor" class-name="specsColor"
@ -117,6 +149,17 @@
<el-radio-button :label="3">事件</el-radio-button> <el-radio-button :label="3">事件</el-radio-button>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="是否只读" prop="isReadonly">
<el-switch
v-model="form.isReadonly"
:active-value="1"
:inactive-value="0"
active-color="#13ce66"
active-text=""
inactive-text=""
>
</el-switch>
</el-form-item>
<!-- <el-form-item v-show="form.type !== 3" label="首页显示" prop="isTop">--> <!-- <el-form-item v-show="form.type !== 3" label="首页显示" prop="isTop">-->
<!-- <el-switch v-model="form.isTop" :active-value="1" :inactive-value="0" active-color="#13ce66" active-text=""--> <!-- <el-switch v-model="form.isTop" :active-value="1" :inactive-value="0" active-color="#13ce66" active-text=""-->
<!-- inactive-text="">--> <!-- inactive-text="">-->
@ -142,25 +185,25 @@
<el-option key="decimal" label="小数" value="decimal"></el-option> <el-option key="decimal" label="小数" value="decimal"></el-option>
<el-option <el-option
key="bool" key="bool"
:disabled="form.isMonitor === 1" :disabled="form.type === 1"
label="布尔" label="布尔"
value="bool" value="bool"
></el-option> ></el-option>
<el-option <el-option
key="enum" key="enum"
:disabled="form.isMonitor === 1" :disabled="form.type === 1"
label="枚举" label="枚举"
value="enum" value="enum"
></el-option> ></el-option>
<el-option <el-option
key="string" key="string"
:disabled="form.isMonitor === 1" :disabled="form.type === 1"
label="字符串" label="字符串"
value="string" value="string"
></el-option> ></el-option>
<el-option <el-option
key="array" key="array"
:disabled="form.isMonitor === 1" :disabled="form.type === 1"
label="数组" label="数组"
value="array" value="array"
></el-option> ></el-option>
@ -197,6 +240,7 @@
<el-form-item label="步长"> <el-form-item label="步长">
<el-input <el-input
v-model="form.specs.step" v-model="form.specs.step"
oninput="value=value.replace(/[^\d]/g,'')"
placeholder="请输入步长例如1" placeholder="请输入步长例如1"
style="width: 385px" style="width: 385px"
type="number" type="number"
@ -409,6 +453,9 @@ watch(modelJson, (value) => {
type: 3, type: 3,
})), })),
]; ];
modelList.value = modelList.value.sort(
(a, b) => b.createTime - a.createTime
);
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} }
@ -429,6 +476,7 @@ const reset = () => {
isSys: null, isSys: null,
isTop: null, isTop: null,
isMonitor: null, isMonitor: null,
isReadonly: 0,
delFlag: null, delFlag: null,
createBy: null, createBy: null,
createTime: null, createTime: null,
@ -490,8 +538,15 @@ const handleDelete = (row) => {
}; };
// 类型改变 // 类型改变
const typeChange = (label) => { const typeChange = (label) => {
if (label === 2 || label === 3) { // if (label === 2 || label === 3) {
form.value.isMonitor = 0; // form.value.isMonitor = 0;
// }
if (
label === 1 &&
form.value.datatype !== "integer" &&
form.value.datatype !== "decimal"
) {
form.value.datatype = "integer";
} }
}; };
const dataTypeChange = () => {}; const dataTypeChange = () => {};
@ -528,6 +583,7 @@ const submitForm = () => {
form.value.specs = formatThingsSpecs(); form.value.specs = formatThingsSpecs();
form.value.productId = product.value.productId; form.value.productId = product.value.productId;
form.value.productName = product.value.productName; form.value.productName = product.value.productName;
form.value.updateTime = Date.now();
const _modelJson = JSON.parse(modelJson.value); const _modelJson = JSON.parse(modelJson.value);
const modelType = modelTypeMap.get(form.value.type); const modelType = modelTypeMap.get(form.value.type);
_modelJson[modelType].forEach((el, index) => { _modelJson[modelType].forEach((el, index) => {
@ -558,6 +614,7 @@ const submitForm = () => {
// 格式化specs // 格式化specs
form.value.modelId = uuidv4(); form.value.modelId = uuidv4();
form.value.specs = formatThingsSpecs(); form.value.specs = formatThingsSpecs();
form.value.createTime = Date.now();
form.value.productId = product.value.productId; form.value.productId = product.value.productId;
form.value.productName = product.value.productName; form.value.productName = product.value.productName;
// if (form.value.type === 2) { // if (form.value.type === 2) {

View File

@ -103,10 +103,10 @@
placeholder="请选择认证方式" placeholder="请选择认证方式"
> >
<el-option <el-option
v-for="item in vertificateMethodOptions" v-for="[value, key] in vertificateMethodOptions"
:key="item.value" :key="value"
:label="item.label" :label="key"
:value="item.value" :value="value"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
@ -139,7 +139,7 @@
/> />
</el-tab-pane> </el-tab-pane>
<el-tab-pane :disabled="!form.productId" label="固件管理"> <el-tab-pane :disabled="!form.productId" label="固件管理">
<firmware :product-id="form.productId" /> <firmware v-if="form.productId" :product-id="form.productId" />
</el-tab-pane> </el-tab-pane>
<el-tab-pane :disabled="!form.productId" label="设备授权"></el-tab-pane> <el-tab-pane :disabled="!form.productId" label="设备授权"></el-tab-pane>
<el-tab-pane :disabled="!form.productId" label="告警配置"></el-tab-pane> <el-tab-pane :disabled="!form.productId" label="告警配置"></el-tab-pane>
@ -173,6 +173,10 @@ const checkProductSnUnique = debounce((rule, value, callback) => {
isProductSnUnique.value = undefined; isProductSnUnique.value = undefined;
return; return;
} }
if (value === oriSn.value) {
callback();
return;
}
checkProductSn(value) checkProductSn(value)
.then((response) => { .then((response) => {
const isUnique = response.data; const isUnique = response.data;
@ -241,6 +245,7 @@ function reset() {
} }
// , // ,
const oriSn = ref(""); // sn
const getData = () => { const getData = () => {
reset(); reset();
const _productId = route.query.productId; const _productId = route.query.productId;
@ -249,6 +254,7 @@ const getData = () => {
tab.updatePage(tabObj); tab.updatePage(tabObj);
getProduct(_productId).then((response) => { getProduct(_productId).then((response) => {
form.value = response.data; form.value = response.data;
oriSn.value = response.data.productSn;
}); });
} else { } else {
const tabObj = Object.assign({}, route, { title: "新增产品" }); const tabObj = Object.assign({}, route, { title: "新增产品" });

View File

@ -24,12 +24,18 @@
@keyup.enter="handleQuery" @keyup.enter="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="产品分类ID" prop="categoryId"> <el-form-item label="产品分类" prop="categoryId">
<el-input <el-tree-select
v-model="queryParams.categoryId" v-model="queryParams.categoryId"
clearable :data="categoryOptions"
placeholder="请输入产品分类ID" :props="{
@keyup.enter="handleQuery" value: 'categoryId',
label: 'name',
children: 'children',
}"
check-strictly
placeholder="请选择产品分类"
value-key="categoryId"
/> />
</el-form-item> </el-form-item>
<!-- <el-form-item label="租户ID" prop="tenantId">--> <!-- <el-form-item label="租户ID" prop="tenantId">-->
@ -146,20 +152,53 @@
<el-table-column align="center" label="产品ID" prop="productId" /> <el-table-column align="center" label="产品ID" prop="productId" />
<el-table-column align="center" label="产品编码SN" prop="productSn" /> <el-table-column align="center" label="产品编码SN" prop="productSn" />
<el-table-column align="center" label="产品名称" prop="productName" /> <el-table-column align="center" label="产品名称" prop="productName" />
<el-table-column align="center" label="产品分类ID" prop="categoryId" /> <el-table-column align="center" label="产品分类ID" prop="categoryId">
<el-table-column align="center" label="租户ID" prop="tenantId" /> <template #default="{ row }">
{{ findNode(categoryOptions, row.categoryId)?.name }}
</template>
</el-table-column>
<el-table-column align="center" label="租户" prop="tenantName">
<template #default="{ row }">
{{
tenantOptions.find((el) => el.tenantId === row.tenantId)
?.tenantName ?? "未知"
}}
</template>
</el-table-column>
<el-table-column align="center" label="mqtt账号" prop="mqttAccount" /> <el-table-column align="center" label="mqtt账号" prop="mqttAccount" />
<el-table-column align="center" label="mqtt密码" prop="mqttPassword" /> <el-table-column align="center" label="mqtt密码" prop="mqttPassword" />
<el-table-column align="center" label="产品秘钥" prop="mqttSecret" /> <el-table-column align="center" label="产品秘钥" prop="mqttSecret" />
<el-table-column align="center" label="状态" prop="status" /> <el-table-column align="center" label="状态" prop="status">
<template #default="{ row }">
<el-tag
:type="
productStatusMap.find((el) => el.value === row.status)?.tag ??
'info'
"
>
{{
productStatusMap.find((el) => el.value === row.status)?.label ??
"未知"
}}
</el-tag>
</template>
</el-table-column>
<!-- <el-table-column align="center" label="物模型JSON" prop="thingsModelsJson" />--> <!-- <el-table-column align="center" label="物模型JSON" prop="thingsModelsJson" />-->
<el-table-column align="center" label="设备类型" prop="deviceType" /> <el-table-column align="center" label="设备类型" prop="deviceType">
<el-table-column <template #default="{ row }">
align="center" {{ deviceTypeMap.get(row.deviceType) ?? "未知" }}
label="认证方式" </template>
prop="vertificateMethod" </el-table-column>
/> <el-table-column align="center" label="认证方式" prop="vertificateMethod">
<el-table-column align="center" label="图片地址" prop="imgUrl" /> <template #default="{ row }">
{{ vertificateMethodOptions.get(row.vertificateMethod) ?? "未知" }}
</template>
</el-table-column>
<el-table-column align="center" label="产品图片" prop="imgUrl">
<template #default="{ row }">
<el-image :src="`/dev-api/${row.imgUrl}`"></el-image>
</template>
</el-table-column>
<el-table-column align="center" label="备注" prop="remark" /> <el-table-column align="center" label="备注" prop="remark" />
<el-table-column <el-table-column
align="center" align="center"
@ -225,9 +264,9 @@
placeholder="请输入认证方式" placeholder="请输入认证方式"
/> />
</el-form-item> </el-form-item>
<el-form-item label="图片地址" prop="imgUrl"> <!-- <el-form-item label="图片地址" prop="imgUrl">-->
<el-input v-model="form.imgUrl" placeholder="请输入图片地址" /> <!-- <el-input v-model="`${baseUrl}/${form.imgUrl}`" placeholder="请输入图片地址" />-->
</el-form-item> <!-- </el-form-item>-->
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
<el-input <el-input
v-model="form.remark" v-model="form.remark"
@ -254,8 +293,17 @@ import {
updateProduct, updateProduct,
} from "@/api/product/product"; } from "@/api/product/product";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import {
deviceTypeMap,
productStatusMap,
vertificateMethodOptions,
} from "../../../constant/dict";
import { listTenant } from "@/api/system/tenant";
import { ref } from "vue";
import { listCategory } from "@/api/product/category";
const router = useRouter(); const router = useRouter();
const baseUrl = import.meta.env.VITE_APP_BASE_API;
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const productList = ref([]); const productList = ref([]);
const open = ref(false); const open = ref(false);
@ -266,7 +314,8 @@ const single = ref(true);
const multiple = ref(true); const multiple = ref(true);
const total = ref(0); const total = ref(0);
const title = ref(""); const title = ref("");
const tenantOptions = ref([]);
const categoryOptions = ref([]); // 产品分类树形选择
const data = reactive({ const data = reactive({
form: {}, form: {},
queryParams: { queryParams: {
@ -308,6 +357,21 @@ function getList() {
}); });
} }
// 递归查找树形结构中的某个节点
function findNode(tree, categoryId) {
let result = null;
for (let node of tree) {
if (node.categoryId === categoryId) {
result = node;
break;
} else if (node.children && node.children.length > 0) {
result = findNode(node.children, categoryId);
if (result) break;
}
}
return result;
}
// 取消按钮 // 取消按钮
function cancel() { function cancel() {
open.value = false; open.value = false;
@ -430,7 +494,22 @@ function handleExport() {
); );
} }
const getTenantOptions = async (keyword) => {
const response = await listTenant({
pageNum: 1,
pageSize: 20,
tenantName: keyword,
});
tenantOptions.value = response.rows;
};
const getCategoryList = async () => {
const response = await listCategory();
categoryOptions.value = response.data;
};
getList(); getList();
getCategoryList();
getTenantOptions();
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.card-item { .card-item {

View File

@ -76,7 +76,6 @@
:maxlength="6" :maxlength="6"
auto-complete="off" auto-complete="off"
class="sms-code-input" class="sms-code-input"
oninput="value=value.replace(/[^\d]/g,'')"
placeholder="请输入短信验证码" placeholder="请输入短信验证码"
size="large" size="large"
@keyup.enter="handleRegister" @keyup.enter="handleRegister"