|
@@ -0,0 +1,351 @@
|
|
|
+<template>
|
|
|
+ <div class="app-container">
|
|
|
+ <el-form :model="data.form" :rules="data.rules" ref="form" label-width="auto" :disabled="disabled">
|
|
|
+ <el-form-item label="设备型号:" prop="clientType">
|
|
|
+ <el-input v-model="data.form.clientType" placeholder="请输入设备型号" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="设备名称:" prop="name">
|
|
|
+ <el-input v-model="data.form.name" placeholder="请输入设备名称" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item v-if="data.form.id" label="旧版蓝牙名称:">
|
|
|
+ <el-input v-model="data.form.bluetoothName" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="蓝牙名称:" prop="bluetoothNames">
|
|
|
+ <el-tag v-for="(item, index) in data.form.bluetoothNames" :key="item" :closable="!disabled" size="large"
|
|
|
+ :disable-transition="false" @close="handleClose(index)" style="margin-right: 10px;">{{ item }}</el-tag>
|
|
|
+ <el-input v-if="inputVisible" v-model="bluetoothName" ref="saveTagInput" @input="handleInput"
|
|
|
+ @keyup.enter.native="handleInputConfirm" @blur="handleInputConfirm" style="width: 100px" />
|
|
|
+ <el-button v-else @click="showInput">+ 新增</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="制造商:" prop="manufacturer">
|
|
|
+ <el-select v-model="data.form.manufacturer" placeholder="请选择设备制造商" clearable>
|
|
|
+ <el-option v-for="item in data.manuOptions" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="设备分类:" prop="categoryId">
|
|
|
+ <el-select v-model="data.form.categoryId" placeholder="请选择设备分类">
|
|
|
+ <el-option v-for="item in deviceClassOptions" :key="item.id" :label="item.name" :value="item.id" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="设备类型:" prop="deviceType">
|
|
|
+ <el-select v-model="data.form.deviceType" placeholder="请选择设备类型">
|
|
|
+ <el-option v-for="item in deviceTypeOptions" :key="item.value" :value="item.value" :label="item.label" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="是否热门:" prop="isHot">
|
|
|
+ <el-select v-model="data.form.isHot" placeholder="请选择是否热门">
|
|
|
+ <el-option v-for="item in hotOptions" :key="item.value" :label="item.label" :value="Number(item.value)" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="在线图片:" prop="img">
|
|
|
+ <CustomUpload listType="picture-card" :src="data.form.img" @upload="handleUploadImg($event, 'online')"
|
|
|
+ :disabled="disabled" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="离线图片:" prop="offlineImg" style="float:right">
|
|
|
+ <CustomUpload listType="picture-card" :src="data.form.offlineImg"
|
|
|
+ @upload="handleUploadImg($event, 'offline')" :disabled="disabled" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <!-- 子表单 -->
|
|
|
+ <el-button v-if="disabled === false && data.form.typeList.length < 4" type="primary" icon="Plus" style="margin-bottom: 20px;"
|
|
|
+ @click="getAdd">新增</el-button>
|
|
|
+ <div class="sub-form" v-for="(item, index) in data.form.typeList" :key="item.id">
|
|
|
+ <el-form-item label="设备模式:" :prop="`typeList.${index}.type`"
|
|
|
+ :rules="{ required: true, message: '请选择设备模式', trigger: 'change' }">
|
|
|
+ <el-select v-model="item.type" placeholder="请选择设备模式" @change="getTypeChange(item)">
|
|
|
+ <el-option v-for="item in data.devModeOptions" :key="item.value" :label="item.label"
|
|
|
+ :value="Number(item.value)" :disabled="item.disabled" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item v-if="item.type !== 3" label="功能权限:" :prop="`typeList.${index}.functionList`"
|
|
|
+ :rules="{ type: 'array', required: true, message: '请选择功能权限', trigger: 'change' }">
|
|
|
+ <el-select v-model="item.functionList" placeholder="请选择功能权限" multiple>
|
|
|
+ <el-option v-for="item in deviceFunOptions" :key="item.id" :label="item.name" :value="item.id" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item v-if="item.type == 2" label="芯片方案:" :prop="`typeList.${index}.is5g`"
|
|
|
+ :rules="{ required: true, message: '请选择芯片方案', trigger: 'change' }">
|
|
|
+ <el-select v-model="item.is5g" placeholder="请选择芯片方案">
|
|
|
+ <el-option v-for="item in planOptions" :key="item.value" :value="item.value" :label="item.label" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item v-if="item.type == 2" label="连接方式:" :prop="`typeList.${index}.connectType`"
|
|
|
+ :rules="{ required: true, message: '请选择连接方式', trigger: 'change' }">
|
|
|
+ <el-select v-model="item.connectType" placeholder="请选择连接方式">
|
|
|
+ <el-option v-for="item in connectTypeOptions" :key="item.value" :label="item.label"
|
|
|
+ :value="Number(item.value)" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item :label="item.type === 1 || item.type === 3 ? '连接引导图:' : '开机引导图:'"
|
|
|
+ :prop="`typeList.${index}.icon1`" :rules="{ required: true, message: '请上传引导图片', trigger: 'change' }">
|
|
|
+ <CustomUpload listType="picture-card" :src="item.icon1" @upload="handleUploadIcon($event, index, 'icon1')"
|
|
|
+ :disabled="disabled" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="配对键引导图:" :prop="`typeList.${index}.icon2`" style="float:right"
|
|
|
+ :rules="{ required: true, message: '请上传配对键引导图', trigger: 'change' }">
|
|
|
+ <CustomUpload listType="picture-card" :src="item.icon2" @upload="handleUploadIcon($event, index, 'icon2')"
|
|
|
+ :disabled="disabled" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-form-item v-if="item.type === 1 || item.type === 3" label="引导页内容:"
|
|
|
+ :prop="`typeList.${index}.guidePageContent`"
|
|
|
+ :rules="{ required: true, message: '请输入引导页内容', trigger: 'blur' }">
|
|
|
+ <Editor v-model="item.guidePageContent" :min-height="250" :readOnly="disabled" />
|
|
|
+ </el-form-item>
|
|
|
+ <!-- 删除按钮 -->
|
|
|
+ <el-link class="el-icon-close" icon="Close" v-if="data.form.typeList.length > 1" :underline="false"
|
|
|
+ @click="getDelete(item.type, index)" />
|
|
|
+ </div>
|
|
|
+ </el-form>
|
|
|
+ <div>
|
|
|
+ <el-button @click="getCancel">取消</el-button>
|
|
|
+ <el-button v-if="disabled === false" type="primary" @click="getSubmit">提交</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { create, detail, edit } from "@/api/device/list";
|
|
|
+import { useDeviceClass, useDeviceType, useHot, useDeviceFun } from '../hooks/index'
|
|
|
+const { deviceClassOptions } = useDeviceClass()
|
|
|
+const { deviceTypeOptions } = useDeviceType()
|
|
|
+const { hotOptions } = useHot()
|
|
|
+const { deviceFunOptions } = useDeviceFun()
|
|
|
+
|
|
|
+const { proxy } = getCurrentInstance();
|
|
|
+
|
|
|
+const data = reactive({
|
|
|
+ // 表单
|
|
|
+ form: {
|
|
|
+ typeList: [{
|
|
|
+ functionList: [],
|
|
|
+ }],
|
|
|
+ bluetoothNames: []
|
|
|
+ },
|
|
|
+ // 表单验证
|
|
|
+ rules: {
|
|
|
+ clientType: [{ required: true, message: "请输入设备型号", trigger: "blur" }],
|
|
|
+ name: [{ required: true, message: "请输入设备名称", trigger: "blur" }],
|
|
|
+ bluetoothNames: [{ type: 'array', required: true, message: '请输入蓝牙名称', trigger: 'blur' }],
|
|
|
+ isHot: [{ required: true, message: "是否热门", trigger: "change" }],
|
|
|
+ categoryId: [{ required: true, message: "请选择设备分类", trigger: "change" }],
|
|
|
+ deviceType: [{ required: true, message: "请选择设备类型", trigger: 'change' }],
|
|
|
+ img: [{ required: true, message: "请上传在线图片", trigger: "change" }],
|
|
|
+ offlineImg: [{ required: true, message: "请上传离线图片", trigger: "change" }],
|
|
|
+ },
|
|
|
+ // 设备连接
|
|
|
+ connectTypeOptions: [{
|
|
|
+ value: 2,
|
|
|
+ label: 'UPnP'
|
|
|
+ }, {
|
|
|
+ value: 3,
|
|
|
+ label: 'MQTT'
|
|
|
+ }],
|
|
|
+ // 制造商
|
|
|
+ manuOptions: [{
|
|
|
+ value: 'ShanJing',
|
|
|
+ label: 'ShanJing'
|
|
|
+ }, {
|
|
|
+ value: 'JieLi',
|
|
|
+ label: 'JieLi'
|
|
|
+ }, {
|
|
|
+ value: 'LingXin',
|
|
|
+ label: 'LingXin'
|
|
|
+ }, {
|
|
|
+ value: 'QiXinWei',
|
|
|
+ label: 'QiXinWei'
|
|
|
+ }],
|
|
|
+ // 芯片方案
|
|
|
+ planOptions: [{
|
|
|
+ value: 1,
|
|
|
+ label: '兼容5GHZ频段芯片方案'
|
|
|
+ }, {
|
|
|
+ value: 0,
|
|
|
+ label: '不兼容5GHZ频段芯片方案'
|
|
|
+ }],
|
|
|
+ // 设备模式
|
|
|
+ devModeOptions: [{
|
|
|
+ value: 1,
|
|
|
+ label: '蓝牙',
|
|
|
+ disabled: false
|
|
|
+ }, {
|
|
|
+ value: 2,
|
|
|
+ label: 'WIFI',
|
|
|
+ disabled: false
|
|
|
+ }, {
|
|
|
+ value: 3,
|
|
|
+ label: '传统蓝牙',
|
|
|
+ disabled: false
|
|
|
+ }, {
|
|
|
+ value: 4,
|
|
|
+ label: '4G',
|
|
|
+ disabled: false
|
|
|
+ }]
|
|
|
+})
|
|
|
+
|
|
|
+// 显示蓝牙输入框
|
|
|
+const inputVisible = ref(false)
|
|
|
+// 蓝牙名称
|
|
|
+const bluetoothName = ref('')
|
|
|
+// 只读
|
|
|
+const disabled = ref(Boolean(proxy.$route.query.boolean))
|
|
|
+
|
|
|
+// 详情
|
|
|
+const getList = () => {
|
|
|
+ if (proxy.$route.query.id) {
|
|
|
+ detail({
|
|
|
+ id: proxy.$route.query.id,
|
|
|
+ }).then(res => {
|
|
|
+ if (res.code === 0) {
|
|
|
+ data.form = res.data;
|
|
|
+ data.form.typeList.map((i) => {
|
|
|
+ data.devModeOptions[i.type - 1].disabled = true;
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+getList()
|
|
|
+
|
|
|
+// 删除蓝牙名称
|
|
|
+const handleClose = (index) => {
|
|
|
+ data.form.bluetoothNames.splice(index, 1)
|
|
|
+}
|
|
|
+
|
|
|
+// 显示输入框
|
|
|
+const showInput = () => {
|
|
|
+ inputVisible.value = true
|
|
|
+ nextTick(() => {
|
|
|
+ proxy.$refs.saveTagInput.$refs.input.focus()
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+// 禁止输入逗号
|
|
|
+const handleInput = (e) => {
|
|
|
+ bluetoothName.value = e.replace(/[,,]/g, "")
|
|
|
+}
|
|
|
+
|
|
|
+// 保存蓝牙名称
|
|
|
+const handleInputConfirm = () => {
|
|
|
+ let inputValue = bluetoothName.value
|
|
|
+ if (inputValue) {
|
|
|
+ data.form.bluetoothNames.push(inputValue)
|
|
|
+ }
|
|
|
+ inputVisible.value = false
|
|
|
+ bluetoothName.value = ''
|
|
|
+}
|
|
|
+
|
|
|
+// 上传设备图片
|
|
|
+const handleUploadImg = (e, key) => {
|
|
|
+ key === "online"
|
|
|
+ ? (data.form.img = e.file)
|
|
|
+ : (data.form.offlineImg = e.file);
|
|
|
+}
|
|
|
+
|
|
|
+// 上传设备图标
|
|
|
+const handleUploadIcon = (e, index, obj) => {
|
|
|
+ data.form.typeList[index][obj] = e.file;
|
|
|
+}
|
|
|
+
|
|
|
+// 选中一个设备类型就从数组中去掉
|
|
|
+const getTypeChange = (i) => {
|
|
|
+ for (let key in data.devModeOptions) {
|
|
|
+ data.devModeOptions[key].disabled = false
|
|
|
+ }
|
|
|
+ // 选中的设备模式禁止再选
|
|
|
+ data.form.typeList.map(item => {
|
|
|
+ if (item.type) {
|
|
|
+ let index = data.devModeOptions.findIndex(j => j.value == item.type)
|
|
|
+ data.devModeOptions[index].disabled = true
|
|
|
+ }
|
|
|
+ })
|
|
|
+ // 除了设备模式都为空
|
|
|
+ Object.keys(i).map(e => {
|
|
|
+ if (!['type', 'icon1', 'icon2'].includes(e)) {
|
|
|
+ i[e] = e === 'functionList' ? [] : null
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+// 新增子表单
|
|
|
+const getAdd = () => {
|
|
|
+ data.form.typeList.push({
|
|
|
+ type: null,
|
|
|
+ functionList: [],
|
|
|
+ connectType: null,
|
|
|
+ icon1: '',
|
|
|
+ icon2: '',
|
|
|
+ guidePageContent: ''
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+// 删除子表单
|
|
|
+const getDelete = (type, index) => {
|
|
|
+ data.form.typeList.splice(index, 1);
|
|
|
+ if (type) {
|
|
|
+ data.devModeOptions.find(i => i.value == type).disabled = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 取消
|
|
|
+const getCancel = () => {
|
|
|
+ proxy.$tab.closeOpenPage("/device/deviceList");
|
|
|
+}
|
|
|
+
|
|
|
+// 提交
|
|
|
+const getSubmit = () => {
|
|
|
+ proxy.$refs.form.validate((valid) => {
|
|
|
+ if (valid) {
|
|
|
+ if (proxy.$route.query.id) {
|
|
|
+ // 编辑
|
|
|
+ edit(data.form).then((res) => {
|
|
|
+ if (res.code === 0) {
|
|
|
+ proxy.$modal.msgSuccess("修改成功!");
|
|
|
+ getCancel();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 新建
|
|
|
+ create(data.form).then((res) => {
|
|
|
+ if (res.code === 0) {
|
|
|
+ proxy.$modal.msgSuccess("提交成功!");
|
|
|
+ getCancel();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.el-form {
|
|
|
+ width: 580px;
|
|
|
+}
|
|
|
+
|
|
|
+.sub-form {
|
|
|
+ position: relative;
|
|
|
+ border: 1px solid #e8e8e8;
|
|
|
+ padding: 25px 25px 0 0;
|
|
|
+ margin-bottom: 20px;
|
|
|
+
|
|
|
+ .el-icon-close {
|
|
|
+ position: absolute;
|
|
|
+ top: 5px;
|
|
|
+ right: 5px;
|
|
|
+ color: #c0c4cc;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|