detail.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. <template>
  2. <div class="app-container">
  3. <el-form :model="data.form" :rules="data.rules" ref="form" label-width="auto" :disabled="disabled">
  4. <el-form-item label="设备型号:" prop="clientType">
  5. <el-input v-model="data.form.clientType" placeholder="请输入设备型号" />
  6. </el-form-item>
  7. <el-form-item label="设备名称:" prop="name">
  8. <el-input v-model="data.form.name" placeholder="请输入设备名称" />
  9. </el-form-item>
  10. <el-form-item v-if="data.form.id" label="旧版蓝牙名称:">
  11. <el-input v-model="data.form.bluetoothName" disabled />
  12. </el-form-item>
  13. <el-form-item label="蓝牙名称:" prop="bluetoothNames">
  14. <el-tag v-for="(item, index) in data.form.bluetoothNames" :key="item" :closable="!disabled" size="large"
  15. :disable-transition="false" @close="handleClose(index)" style="margin-right: 10px;">{{ item }}</el-tag>
  16. <el-input v-if="inputVisible" v-model="bluetoothName" ref="saveTagInput" @input="handleInput"
  17. @keyup.enter.native="handleInputConfirm" @blur="handleInputConfirm" style="width: 100px" />
  18. <el-button v-else @click="showInput">+ 新增</el-button>
  19. </el-form-item>
  20. <el-form-item label="制造商:" prop="manufacturer">
  21. <el-select v-model="data.form.manufacturer" placeholder="请选择设备制造商" clearable>
  22. <el-option v-for="item in data.manuOptions" :key="item.value" :label="item.label" :value="item.value" />
  23. </el-select>
  24. </el-form-item>
  25. <el-form-item label="设备分类:" prop="categoryId">
  26. <el-select v-model="data.form.categoryId" placeholder="请选择设备分类">
  27. <el-option v-for="item in deviceClassOptions" :key="item.id" :label="item.name" :value="item.id" />
  28. </el-select>
  29. </el-form-item>
  30. <el-form-item label="设备类型:" prop="deviceType">
  31. <el-select v-model="data.form.deviceType" placeholder="请选择设备类型">
  32. <el-option v-for="item in deviceTypeOptions" :key="item.value" :value="item.value" :label="item.label" />
  33. </el-select>
  34. </el-form-item>
  35. <el-form-item label="是否热门:" prop="isHot">
  36. <el-select v-model="data.form.isHot" placeholder="请选择是否热门">
  37. <el-option v-for="item in hotOptions" :key="item.value" :label="item.label" :value="Number(item.value)" />
  38. </el-select>
  39. </el-form-item>
  40. <el-row>
  41. <el-col :span="12">
  42. <el-form-item label="在线图片:" prop="img">
  43. <CustomUpload listType="picture-card" :src="data.form.img" @upload="handleUploadImg($event, 'online')"
  44. :disabled="disabled" />
  45. </el-form-item>
  46. </el-col>
  47. <el-col :span="12">
  48. <el-form-item label="离线图片:" prop="offlineImg" style="float:right">
  49. <CustomUpload listType="picture-card" :src="data.form.offlineImg"
  50. @upload="handleUploadImg($event, 'offline')" :disabled="disabled" />
  51. </el-form-item>
  52. </el-col>
  53. </el-row>
  54. <!-- 子表单 -->
  55. <el-button v-if="disabled === false && data.form.typeList.length < 4" type="primary" icon="Plus" style="margin-bottom: 20px;"
  56. @click="getAdd">新增</el-button>
  57. <div class="sub-form" v-for="(item, index) in data.form.typeList" :key="item.id">
  58. <el-form-item label="设备模式:" :prop="`typeList.${index}.type`"
  59. :rules="{ required: true, message: '请选择设备模式', trigger: 'change' }">
  60. <el-select v-model="item.type" placeholder="请选择设备模式" @change="getTypeChange(item)">
  61. <el-option v-for="item in data.devModeOptions" :key="item.value" :label="item.label"
  62. :value="Number(item.value)" :disabled="item.disabled" />
  63. </el-select>
  64. </el-form-item>
  65. <el-form-item v-if="item.type !== 3" label="功能权限:" :prop="`typeList.${index}.functionList`"
  66. :rules="{ type: 'array', required: true, message: '请选择功能权限', trigger: 'change' }">
  67. <el-select v-model="item.functionList" placeholder="请选择功能权限" multiple>
  68. <el-option v-for="item in deviceFunOptions" :key="item.id" :label="item.name" :value="item.id" />
  69. </el-select>
  70. </el-form-item>
  71. <el-form-item v-if="item.type == 2" label="芯片方案:" :prop="`typeList.${index}.is5g`"
  72. :rules="{ required: true, message: '请选择芯片方案', trigger: 'change' }">
  73. <el-select v-model="item.is5g" placeholder="请选择芯片方案">
  74. <el-option v-for="item in data.planOptions" :key="item.value" :value="item.value" :label="item.label" />
  75. </el-select>
  76. </el-form-item>
  77. <el-form-item v-if="item.type == 2" label="连接方式:" :prop="`typeList.${index}.connectType`"
  78. :rules="{ required: true, message: '请选择连接方式', trigger: 'change' }">
  79. <el-select v-model="item.connectType" placeholder="请选择连接方式">
  80. <el-option v-for="item in data.connectTypeOptions" :key="item.value" :label="item.label"
  81. :value="Number(item.value)" />
  82. </el-select>
  83. </el-form-item>
  84. <el-row>
  85. <el-col :span="12">
  86. <el-form-item :label="item.type === 1 || item.type === 3 ? '连接引导图:' : '开机引导图:'"
  87. :prop="`typeList.${index}.icon1`" :rules="{ required: true, message: '请上传引导图片', trigger: 'change' }">
  88. <CustomUpload listType="picture-card" :src="item.icon1" @upload="handleUploadIcon($event, index, 'icon1')"
  89. :disabled="disabled" />
  90. </el-form-item>
  91. </el-col>
  92. <el-col :span="12">
  93. <el-form-item label="配对键引导图:" :prop="`typeList.${index}.icon2`" style="float:right"
  94. :rules="{ required: true, message: '请上传配对键引导图', trigger: 'change' }">
  95. <CustomUpload listType="picture-card" :src="item.icon2" @upload="handleUploadIcon($event, index, 'icon2')"
  96. :disabled="disabled" />
  97. </el-form-item>
  98. </el-col>
  99. </el-row>
  100. <el-form-item v-if="item.type === 1 || item.type === 3" label="引导页内容:"
  101. :prop="`typeList.${index}.guidePageContent`"
  102. :rules="{ required: true, message: '请输入引导页内容', trigger: 'blur' }">
  103. <Editor v-model="item.guidePageContent" :min-height="250" :readOnly="disabled" />
  104. </el-form-item>
  105. <!-- 删除按钮 -->
  106. <el-link class="el-icon-close" icon="Close" v-if="data.form.typeList.length > 1" :underline="false" :disabled="disabled"
  107. @click="getDelete(item.type, index)" />
  108. </div>
  109. </el-form>
  110. <div>
  111. <el-button @click="getCancel">取消</el-button>
  112. <el-button v-if="disabled === false" type="primary" @click="getSubmit">提交</el-button>
  113. </div>
  114. </div>
  115. </template>
  116. <script setup>
  117. import { create, detail, edit } from "@/api/device/list";
  118. import { useDeviceClass, useDeviceType, useHot, useDeviceFun } from '../hooks/index'
  119. const { deviceClassOptions } = useDeviceClass()
  120. const { deviceTypeOptions } = useDeviceType()
  121. const { hotOptions } = useHot()
  122. const { deviceFunOptions } = useDeviceFun()
  123. const { proxy } = getCurrentInstance();
  124. const data = reactive({
  125. // 表单
  126. form: {
  127. typeList: [{
  128. functionList: [],
  129. }],
  130. bluetoothNames: []
  131. },
  132. // 表单验证
  133. rules: {
  134. clientType: [{ required: true, message: "请输入设备型号", trigger: "blur" }],
  135. name: [{ required: true, message: "请输入设备名称", trigger: "blur" }],
  136. bluetoothNames: [{ type: 'array', required: true, message: '请输入蓝牙名称', trigger: 'blur' }],
  137. isHot: [{ required: true, message: "是否热门", trigger: "change" }],
  138. categoryId: [{ required: true, message: "请选择设备分类", trigger: "change" }],
  139. deviceType: [{ required: true, message: "请选择设备类型", trigger: 'change' }],
  140. img: [{ required: true, message: "请上传在线图片", trigger: "change" }],
  141. offlineImg: [{ required: true, message: "请上传离线图片", trigger: "change" }],
  142. },
  143. // 设备连接
  144. connectTypeOptions: [{
  145. value: 2,
  146. label: 'UPnP'
  147. }, {
  148. value: 3,
  149. label: 'MQTT'
  150. }],
  151. // 制造商
  152. manuOptions: [{
  153. value: 'ShanJing',
  154. label: 'ShanJing'
  155. }, {
  156. value: 'JieLi',
  157. label: 'JieLi'
  158. }, {
  159. value: 'LingXin',
  160. label: 'LingXin'
  161. }, {
  162. value: 'QiXinWei',
  163. label: 'QiXinWei'
  164. }],
  165. // 芯片方案
  166. planOptions: [{
  167. value: 1,
  168. label: '兼容5GHZ频段芯片方案'
  169. }, {
  170. value: 0,
  171. label: '不兼容5GHZ频段芯片方案'
  172. }],
  173. // 设备模式
  174. devModeOptions: [{
  175. value: 1,
  176. label: '蓝牙',
  177. disabled: false
  178. }, {
  179. value: 2,
  180. label: 'WIFI',
  181. disabled: false
  182. }, {
  183. value: 3,
  184. label: '传统蓝牙',
  185. disabled: false
  186. }, {
  187. value: 4,
  188. label: '4G',
  189. disabled: false
  190. }]
  191. })
  192. // 显示蓝牙输入框
  193. const inputVisible = ref(false)
  194. // 蓝牙名称
  195. const bluetoothName = ref('')
  196. // 只读
  197. const disabled = ref(Boolean(proxy.$route.query.boolean))
  198. // 详情
  199. const getList = () => {
  200. if (proxy.$route.query.id) {
  201. detail({
  202. id: proxy.$route.query.id,
  203. }).then(res => {
  204. if (res.code === 0) {
  205. data.form = res.data;
  206. data.form.typeList.map((i) => {
  207. data.devModeOptions[i.type - 1].disabled = true;
  208. })
  209. }
  210. })
  211. }
  212. }
  213. getList()
  214. // 删除蓝牙名称
  215. const handleClose = (index) => {
  216. data.form.bluetoothNames.splice(index, 1)
  217. }
  218. // 显示输入框
  219. const showInput = () => {
  220. inputVisible.value = true
  221. nextTick(() => {
  222. proxy.$refs.saveTagInput.$refs.input.focus()
  223. })
  224. }
  225. // 禁止输入逗号
  226. const handleInput = (e) => {
  227. bluetoothName.value = e.replace(/[,,]/g, "")
  228. }
  229. // 保存蓝牙名称
  230. const handleInputConfirm = () => {
  231. let inputValue = bluetoothName.value
  232. if (inputValue) {
  233. data.form.bluetoothNames.push(inputValue)
  234. }
  235. inputVisible.value = false
  236. bluetoothName.value = ''
  237. }
  238. // 上传设备图片
  239. const handleUploadImg = (e, key) => {
  240. key === "online"
  241. ? (data.form.img = e.file)
  242. : (data.form.offlineImg = e.file);
  243. }
  244. // 上传设备图标
  245. const handleUploadIcon = (e, index, obj) => {
  246. data.form.typeList[index][obj] = e.file;
  247. }
  248. // 选中一个设备类型就从数组中去掉
  249. const getTypeChange = (i) => {
  250. for (let key in data.devModeOptions) {
  251. data.devModeOptions[key].disabled = false
  252. }
  253. // 选中的设备模式禁止再选
  254. data.form.typeList.map(item => {
  255. if (item.type) {
  256. let index = data.devModeOptions.findIndex(j => j.value == item.type)
  257. data.devModeOptions[index].disabled = true
  258. }
  259. })
  260. // 除了设备模式都为空
  261. Object.keys(i).map(e => {
  262. if (!['type', 'icon1', 'icon2'].includes(e)) {
  263. i[e] = e === 'functionList' ? [] : null
  264. }
  265. })
  266. }
  267. // 新增子表单
  268. const getAdd = () => {
  269. data.form.typeList.push({
  270. type: null,
  271. functionList: [],
  272. connectType: null,
  273. icon1: '',
  274. icon2: '',
  275. guidePageContent: ''
  276. });
  277. }
  278. // 删除子表单
  279. const getDelete = (type, index) => {
  280. data.form.typeList.splice(index, 1);
  281. if (type) {
  282. data.devModeOptions.find(i => i.value == type).disabled = false
  283. }
  284. }
  285. // 取消
  286. const getCancel = () => {
  287. proxy.$tab.closeOpenPage("/device/deviceList");
  288. }
  289. // 提交
  290. const getSubmit = () => {
  291. proxy.$refs.form.validate((valid) => {
  292. if (valid) {
  293. if (proxy.$route.query.id) {
  294. // 编辑
  295. edit(data.form).then((res) => {
  296. if (res.code === 0) {
  297. proxy.$modal.msgSuccess("修改成功!");
  298. getCancel();
  299. }
  300. });
  301. } else {
  302. // 新建
  303. create(data.form).then((res) => {
  304. if (res.code === 0) {
  305. proxy.$modal.msgSuccess("提交成功!");
  306. getCancel();
  307. }
  308. });
  309. }
  310. } else {
  311. return false;
  312. }
  313. });
  314. }
  315. </script>
  316. <style lang="scss" scoped>
  317. .el-form {
  318. width: 580px;
  319. }
  320. .sub-form {
  321. position: relative;
  322. border: 1px solid #e8e8e8;
  323. padding: 25px 25px 0 0;
  324. margin-bottom: 20px;
  325. .el-icon-close {
  326. position: absolute;
  327. top: 5px;
  328. right: 5px;
  329. color: #c0c4cc;
  330. }
  331. }
  332. </style>