Преглед на файлове

设备管理部分提交

luogang преди 9 месеца
родител
ревизия
cfc405d74f

+ 2 - 2
.env.development

@@ -1,5 +1,5 @@
 # 页面标题
-VITE_APP_TITLE = RuoYi-Vue-Plus多租户管理系统
+VITE_APP_TITLE = 机电运维平台
 
 # 开发环境配置
 VITE_APP_ENV = 'development'
@@ -16,7 +16,7 @@ VITE_APP_MONITOR_ADMIN = 'http://localhost:9090/admin/applications'
 # SnailJob 控制台地址
 VITE_APP_SNAILJOB_ADMIN = 'http://localhost:8800/snail-job'
 
-VITE_APP_PORT = 80
+VITE_APP_PORT = 8001
 
 # 接口加密功能开关(如需关闭 后端也必须对应关闭)
 VITE_APP_ENCRYPT = true

+ 2 - 2
.env.production

@@ -1,5 +1,5 @@
 # 页面标题
-VITE_APP_TITLE = RuoYi-Vue-Plus多租户管理系统
+VITE_APP_TITLE = 机电运维平台
 
 # 生产环境配置
 VITE_APP_ENV = 'production'
@@ -19,7 +19,7 @@ VITE_APP_BASE_API = '/prod-api'
 # 是否在打包时开启压缩,支持 gzip 和 brotli
 VITE_BUILD_COMPRESS = gzip
 
-VITE_APP_PORT = 80
+VITE_APP_PORT = 8001
 
 # 接口加密功能开关(如需关闭 后端也必须对应关闭)
 VITE_APP_ENCRYPT = true

+ 1 - 0
.eslintignore

@@ -15,3 +15,4 @@ dist
 prettier.config.js
 src/assets
 tailwind.config.js
+index.html

+ 1 - 1
.prettierignore

@@ -6,4 +6,4 @@
 **/*.svg
 **/*.sh
 
-/public/*
+/public/*

+ 1 - 1
.prettierrc

@@ -1,6 +1,6 @@
 {
   "printWidth": 150,
-  "tabWidth": 2,
+  "tabWidth": 4,
   "useTabs": false,
   "semi": true,
   "singleQuote": true,

+ 1 - 1
index.html

@@ -6,7 +6,7 @@
     <meta name="renderer" content="webkit" />
     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
     <link rel="icon" href="/favicon.ico" />
-    <title>RuoYi-Vue-Plus多租户管理系统</title>
+    <title>机电运维平台</title>
     <!--[if lt IE 11
       ]><script>
         window.location.href = '/html/ie.html';

BIN
public/favicon.ico


+ 149 - 0
src/api/deviceManage/deviceType/index.ts

@@ -0,0 +1,149 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+
+/**
+ * 查询设备类型信息列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listDeviceType = (query) => {
+  return request({
+    url: '/jdyw/deviceType/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询设备类型信息详细
+ * @param id
+ */
+export const getDeviceType = (id) => {
+  return request({
+    url: '/jdyw/deviceType/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增设备类型信息
+ * @param data
+ */
+export const addDeviceType = (data) => {
+  return request({
+    url: '/jdyw/deviceType',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改设备类型信息
+ * @param data
+ */
+export const updateDeviceType = (data) => {
+  return request({
+    url: '/jdyw/deviceType',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除设备类型信息
+ * @param id
+ */
+export const delDeviceType = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/jdyw/deviceType/' + id,
+    method: 'delete'
+  });
+};
+
+/**
+ * 设备分项系统信息
+ * @param query
+ * @returns {*}
+ */
+
+export const getDeviceSystemTree = (query) => {
+  return request({
+    url: '/jdyw/deviceSystem/list',
+    method: 'get',
+    params: query
+  });
+};
+/**
+ * 新增设备分项系统信息
+ * @param query
+ * @returns {*}
+ */
+
+export const addDeviceSystem = (data) => {
+  return request({
+    url: '/jdyw/deviceSystem',
+    method: 'post',
+    data
+  });
+};
+/**
+ * 修改设备分项系统信息
+ * @param query
+ * @returns {*}
+ */
+
+export const editDeviceSystem = (data) => {
+  return request({
+    url: '/jdyw/deviceSystem',
+    method: 'put',
+    data
+  });
+};
+/**
+ * 删除设备分项系统信息
+ * @param query
+ * @returns {*}
+ */
+
+export const delDeviceSystem = (id) => {
+  return request({
+    url: `/jdyw/deviceSystem/${id}`,
+    method: 'delete'
+  });
+};
+/**
+ * 物模型获取
+ * @returns {*}
+ */
+
+export const getModels = (id) => {
+  return request({
+    url: `/jdyw/models/${id}`,
+    method: 'get'
+  });
+};
+/**
+ * 物模型新增
+ * @returns {*}
+ */
+
+export const addModels = (data) => {
+  return request({
+    url: `/jdyw/models`,
+    method: 'post',
+    data
+  });
+};
+/**
+ * 物模型修改
+ * @returns {*}
+ */
+
+export const editModels = (data) => {
+  return request({
+    url: `/jdyw/models`,
+    method: 'put',
+    data
+  });
+};

BIN
src/assets/logo/logo.png


+ 1 - 1
src/layout/components/Sidebar/Logo.vue

@@ -34,7 +34,7 @@ defineProps({
   }
 });
 
-const title = ref('RuoYi-Vue-Plus');
+const title = ref('机电运维平台');
 const settingsStore = useSettingsStore();
 const sideTheme = computed(() => settingsStore.sideTheme);
 </script>

+ 1 - 1
src/utils/request.ts

@@ -40,7 +40,7 @@ service.interceptors.request.use(
     // 是否需要防止数据重复提交
     const isRepeatSubmit = config.headers?.repeatSubmit === false;
     // 是否需要加密
-    const isEncrypt = config.headers?.isEncrypt === 'true';
+    const isEncrypt = config.headers?.isEncrypt === 'false';
 
     if (getToken() && !isToken) {
       config.headers['Authorization'] = 'Bearer ' + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改

+ 5 - 0
src/views/deviceMaintain/faultRepair/index.vue

@@ -0,0 +1,5 @@
+<template>
+  <div class=""></div>
+</template>
+<script setup lang="ts"></script>
+<style lang="scss" scoped></style>

+ 5 - 0
src/views/deviceMaintain/faultType/index.vue

@@ -0,0 +1,5 @@
+<template>
+  <div class=""></div>
+</template>
+<script setup lang="ts"></script>
+<style lang="scss" scoped></style>

+ 5 - 0
src/views/deviceMaintain/innerWorkorder/index.vue

@@ -0,0 +1,5 @@
+<template>
+  <div class=""></div>
+</template>
+<script setup lang="ts"></script>
+<style lang="scss" scoped></style>

+ 5 - 0
src/views/deviceMaintain/outerWorkorder/index.vue

@@ -0,0 +1,5 @@
+<template>
+  <div class=""></div>
+</template>
+<script setup lang="ts"></script>
+<style lang="scss" scoped></style>

+ 5 - 0
src/views/deviceManage/archives/index.vue

@@ -0,0 +1,5 @@
+<template>
+  <div class=""></div>
+</template>
+<script setup lang="ts"></script>
+<style lang="scss" scoped></style>

+ 692 - 0
src/views/deviceManage/deviceType/index.vue

@@ -0,0 +1,692 @@
+<template>
+  <div class="p-2">
+    <el-row :gutter="10">
+      <el-col :span="5">
+        <el-card>
+          <template #header>
+            <div class="card-header">
+              <span>分项系统</span>
+              <el-icon color="#409EFF" @click="addSystem">
+                <Plus />
+              </el-icon>
+            </div>
+          </template>
+          <div>
+            <el-input v-model="filterText" style="width: 200px" placeholder="请输入关键字" />
+            <el-tree
+              ref="treeRef"
+              style="max-width: 600px; margin-top: 5px"
+              class="filter-tree"
+              :props="defaultProps"
+              :data="treeData"
+              node-key="id"
+              default-expand-all
+              highlight-current
+              :expand-on-click-node="false"
+              :filter-node-method="filterNode"
+              @node-click="handleNodeClick"
+            >
+              <template #default="{ node, data }">
+                <div class="custom-tree-node">
+                  <span>{{ node.label }}</span>
+                  <el-popover placement="bottom" :popper-style="{ 'width': '70px', 'min-width': '70px' }" trigger="click">
+                    <div class="node-operateBtns">
+                      <div @click="addSystem(data)">新增</div>
+                      <div @click="editSystem(node, data)">编辑</div>
+                      <div @click="delSystem(node, data)">删除</div>
+                    </div>
+                    <template #reference>
+                      <el-icon>
+                        <Setting />
+                      </el-icon>
+                    </template>
+                  </el-popover>
+                </div>
+              </template>
+            </el-tree>
+          </div>
+        </el-card>
+      </el-col>
+      <el-col :span="19">
+        <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
+          <div v-show="showSearch" class="mb-[10px]">
+            <el-card shadow="hover">
+              <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="100px">
+                <el-form-item label="设备类型名称" prop="name">
+                  <el-input v-model="queryParams.name" placeholder="请输入设备类型名称" clearable @keyup.enter="handleQuery" />
+                </el-form-item>
+                <el-form-item>
+                  <el-button type="primary" icon="Search" @click="handleQuery"> 搜索 </el-button>
+                  <el-button icon="Refresh" @click="resetQuery"> 重置 </el-button>
+                </el-form-item>
+              </el-form>
+            </el-card>
+          </div>
+        </transition>
+
+        <el-card shadow="never">
+          <template #header>
+            <el-row :gutter="10" class="mb8">
+              <el-col :span="1.5">
+                <el-button v-hasPermi="['jdyw:deviceType:add']" type="primary" plain icon="Plus" @click="handleAdd"> 新增 </el-button>
+              </el-col>
+              <el-col :span="1.5">
+                <el-button v-hasPermi="['jdyw:deviceType:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate">
+                  修改
+                </el-button>
+              </el-col>
+              <el-col :span="1.5">
+                <el-button v-hasPermi="['jdyw:deviceType:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete">
+                  删除
+                </el-button>
+              </el-col>
+              <right-toolbar v-model:showSearch="showSearch" @query-table="getList" />
+            </el-row>
+          </template>
+
+          <el-table v-loading="loading" :data="deviceTypeList" @selection-change="handleSelectionChange">
+            <el-table-column type="selection" width="55" align="center" />
+            <el-table-column label="设备类型名称" align="center" prop="name" />
+            <el-table-column label="设备等级" align="center" prop="deviceLevel" />
+            <el-table-column label="分项系统" align="center" show-overflow-tooltip prop="systemId">
+              <template #default="scope">
+                {{ findNameWithParents(treeData, scope.row.systemId, '') }}
+              </template>
+            </el-table-column>
+            <el-table-column label="备注" align="center" prop="remark" />
+            <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+              <template #default="scope">
+                <el-button v-hasPermi="['jdyw:deviceType:edit']" size="small" link type="primary" @click="handleUpdate(scope.row)">修改</el-button>
+                <el-button v-hasPermi="['jdyw:deviceType:edit']" size="small" link type="primary" @click="handleModel(scope.row)">物模型</el-button>
+                <el-button v-hasPermi="['jdyw:deviceType:remove']" size="small" link type="danger" @click="handleDelete(scope.row)">删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+          <pagination
+            v-show="total > 0"
+            v-model:page="queryParams.pageNum"
+            v-model:limit="queryParams.pageSize"
+            :total="total"
+            @pagination="getList"
+          />
+        </el-card>
+      </el-col>
+    </el-row>
+
+    <!-- 添加或修改设备类型信息对话框 -->
+    <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body>
+      <el-form ref="deviceTypeFormRef" :model="form" :rules="rules" label-width="110px">
+        <el-form-item label="设备类型名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入设备类型名称" />
+        </el-form-item>
+        <el-form-item label="设备等级" prop="deviceLevel">
+          <el-select v-model="form.deviceLevel" placeholder="请选择设备等级">
+            <el-option v-for="dict in device_level" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="分项系统" prop="systemId">
+          <el-tree-select
+            v-model="form.systemId"
+            :props="defaultProps"
+            node-key="id"
+            :data="treeData"
+            default-expand-all
+            :check-strictly="true"
+            :render-after-expand="false"
+          />
+        </el-form-item>
+        <el-form-item label="备注" prop="remark">
+          <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button :loading="buttonLoading" type="primary" @click="submitForm"> 确 定 </el-button>
+          <el-button @click="cancel"> 取 消 </el-button>
+        </div>
+      </template>
+    </el-dialog>
+    <el-dialog v-model="systemDialog.visible" :title="systemDialog.title" width="500px" append-to-body>
+      <el-form ref="deviceSystemFormRef" :model="systemForm" label-width="120px">
+        <el-form-item label="上级分项系统" prop="parentName" required>
+          <el-input v-model="systemForm.parentName" disabled placeholder="请选择上级分项系统" />
+        </el-form-item>
+        <el-form-item label="系统名称" prop="name" required :rules="[{ required: true, message: '请输入系统名称' }]">
+          <el-input v-model="systemForm.name" placeholder="请输入系统名称" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button :loading="buttonLoading" type="primary" @click="submitSystemForm"> 确 定 </el-button>
+          <el-button @click="systemDialog.visible = false"> 取 消 </el-button>
+        </div>
+      </template>
+    </el-dialog>
+    <el-drawer v-model="rightDrawer" size="70%" class="customDrawer">
+      <template #header>
+        <div class="drawer-title">
+          <div class="title-name">物模型</div>
+          <el-descriptions style="margin-top: 10px" direction="vertical" title="" :column="4" border>
+            <el-descriptions-item label="设备名称">{{ curRow.name }}</el-descriptions-item>
+            <el-descriptions-item label="分项系统">{{ findNameWithParents(treeData, curRow.systemId, '') }}</el-descriptions-item>
+            <el-descriptions-item label="设备等级">{{ curRow.deviceLevel }}</el-descriptions-item>
+          </el-descriptions>
+        </div>
+      </template>
+      <el-tabs v-model="activeName" class="demo-tabs">
+        <el-tab-pane label="属性定义" name="dataPoints">
+          <el-button size="small" type="primary" @click="addModel">新增</el-button>
+          <el-table :data="modelData.dataPoints" style="margin-top: 10px">
+            <el-table-column label="属性" align="center" prop="name" />
+            <el-table-column label="属性值" align="center" prop="value" />
+            <el-table-column label="单位" align="center" prop="unit" />
+            <el-table-column label="描述" align="center" prop="remark" />
+            <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+              <template #default="scope">
+                <el-button size="small" link type="primary" @click="editModel(scope.$index)">修改</el-button>
+                <el-button size="small" link type="danger" @click="delModel(scope.$index)">删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-tab-pane>
+        <el-tab-pane label="能力定义" name="controlFuncs">
+          <el-button size="small" type="primary" @click="addModel">新增</el-button>
+          <el-table :data="modelData.controlFuncs" style="margin-top: 10px">
+            <el-table-column label="能力名称" align="center" prop="name" />
+            <el-table-column label="下发参数" align="center" prop="value" />
+            <el-table-column label="描述" align="center" prop="remark" />
+            <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+              <template #default="scope">
+                <el-button size="small" link type="primary" @click="editModel(scope.$index)">修改</el-button>
+                <el-button size="small" link type="danger" @click="delModel(scope.$index)">删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-tab-pane>
+        <el-tab-pane label="事件定义" name="events">
+          <el-button size="small" type="primary" @click="addModel">新增</el-button>
+          <el-table :data="modelData.events" style="margin-top: 10px">
+            <el-table-column label="事件名称" align="center" prop="name" />
+            <el-table-column label="事件类型" align="center" prop="type" />
+            <el-table-column label="事件代码" align="center" prop="code" />
+            <el-table-column label="外部事件代码" align="center" prop="outerCode" />
+            <el-table-column label="描述" align="center" prop="remark" />
+            <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+              <template #default="scope">
+                <el-button size="small" link type="primary" @click="editModel(scope.$index)">修改</el-button>
+                <el-button size="small" link type="danger" @click="delModel(scope.$index)">删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-tab-pane>
+      </el-tabs>
+    </el-drawer>
+    <el-dialog v-model="modelDialog.visible" :title="modelDialog.title" width="500px" append-to-body>
+      <el-form v-if="activeName == 'dataPoints'" ref="modelFormRef" :model="modelData.dataPointsForm" label-width="120px">
+        <el-form-item label="属性名称" prop="name" :rules="[{ required: true, message: '请输入属性名称' }]">
+          <el-input v-model="modelData.dataPointsForm.name" placeholder="请输入属性名称" />
+        </el-form-item>
+        <el-form-item label="属性值" prop="value" :rules="[{ required: true, message: '请输入属性值' }]">
+          <el-input v-model="modelData.dataPointsForm.value" placeholder="请输入属性值" />
+        </el-form-item>
+        <el-form-item label="单位" prop="unit" :rules="[{ required: true, message: '请输入单位' }]">
+          <el-input v-model="modelData.dataPointsForm.unit" placeholder="请输入单位" />
+        </el-form-item>
+        <el-form-item label="描述" prop="remark">
+          <el-input v-model="modelData.dataPointsForm.remark" placeholder="请输入描述" />
+        </el-form-item>
+      </el-form>
+      <el-form v-else-if="activeName == 'controlFuncs'" ref="modelFormRef" :model="modelData.controlFuncsForm" label-width="120px">
+        <el-form-item label="能力名称" prop="name" :rules="[{ required: true, message: '请输入能力名称' }]">
+          <el-input v-model="modelData.controlFuncsForm.name" placeholder="请输入能力名称" />
+        </el-form-item>
+        <el-form-item label="下发参数" prop="value" :rules="[{ required: true, message: '请输入下发参数' }]">
+          <el-input v-model="modelData.controlFuncsForm.value" placeholder="请输入下发参数" />
+        </el-form-item>
+        <el-form-item label="描述" prop="remark">
+          <el-input v-model="modelData.controlFuncsForm.unit" placeholder="请输入描述" />
+        </el-form-item>
+      </el-form>
+      <el-form v-else-if="activeName == 'events'" ref="modelFormRef" :model="modelData.eventsForm" label-width="120px">
+        <el-form-item label="事件名称" prop="name" :rules="[{ required: true, message: '请输入事件名称' }]">
+          <el-input v-model="modelData.eventsForm.name" placeholder="请输入事件名称" />
+        </el-form-item>
+        <el-form-item label="事件类型" prop="type" :rules="[{ required: true, message: '请输入事件类型' }]">
+          <el-input v-model="modelData.eventsForm.type" placeholder="请输入事件类型" />
+        </el-form-item>
+        <el-form-item label="事件代码" prop="code" :rules="[{ required: true, message: '请输入事件代码' }]">
+          <el-input v-model="modelData.eventsForm.code" placeholder="请输入事件代码" />
+        </el-form-item>
+        <el-form-item label="外部事件代码" prop="outerCode" :rules="[{ required: true, message: '请输入外部事件代码' }]">
+          <el-input v-model="modelData.eventsForm.outerCode" placeholder="请输入外部事件代码" />
+        </el-form-item>
+        <el-form-item label="描述" prop="remark">
+          <el-input v-model="modelData.eventsForm.remark" placeholder="请输入描述" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button :loading="buttonLoading" type="primary" @click="submitModelForm"> 确 定 </el-button>
+          <el-button @click="modelDialog.visible = false"> 取 消 </el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup name="DeviceType" lang="ts">
+import {
+  listDeviceType,
+  getDeviceType,
+  delDeviceType,
+  addDeviceType,
+  updateDeviceType,
+  getDeviceSystemTree,
+  addDeviceSystem,
+  editDeviceSystem,
+  delDeviceSystem,
+  addModels,
+  editModels,
+  getModels
+} from '@/api/deviceManage/deviceType';
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+
+const deviceTypeList = ref([]);
+const buttonLoading = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref<Array<string | number>>([]);
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const queryFormRef = ref<ElFormInstance>();
+const deviceTypeFormRef = ref<ElFormInstance>();
+const deviceSystemFormRef = ref<ElFormInstance>();
+const modelFormRef = ref<ElFormInstance>();
+const filterText = ref('');
+const treeRef = ref<ElTreeInstance>();
+const filterNode = (value: string, data) => {
+  if (!value) return true;
+  return data.name.includes(value);
+};
+watch(filterText, (val) => {
+  treeRef.value!.filter(val);
+});
+const defaultProps = {
+  children: 'children',
+  label: 'name'
+};
+const treeData = ref([]);
+const dialog = reactive<DialogOption>({
+  visible: false,
+  title: ''
+});
+const systemDialog = reactive<DialogOption>({
+  visible: false,
+  title: ''
+});
+const { device_level } = toRefs<any>(proxy?.useDict('device_level'));
+const rightDrawer = ref(false);
+const curRow = ref<any>({});
+const activeName = ref('dataPoints');
+const systemForm = reactive({
+  id: '',
+  name: '',
+  parentId: 0,
+  parentName: ''
+});
+
+const modelData = reactive<any>({
+  id: '',
+  name: '',
+  dataPoints: [],
+  controlFuncs: [],
+  events: [],
+  dataPointsForm: {
+    name: '',
+    value: '',
+    unit: '',
+    remark: ''
+  },
+  controlFuncsForm: {
+    name: '',
+    value: '',
+    remark: ''
+  },
+  eventsForm: {
+    name: '',
+    type: '',
+    code: '',
+    outerCode: '',
+    remark: ''
+  }
+});
+const editIndex = ref(null);
+const modelDialog = reactive<DialogOption>({
+  visible: false,
+  title: ''
+});
+const initFormData = {
+  id: undefined,
+  name: undefined,
+  deviceLevel: undefined,
+  systemId: null,
+  modeId: undefined,
+  remark: undefined,
+  ext1: undefined,
+  ext2: undefined
+};
+const formData = reactive({
+  form: { ...initFormData },
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10,
+    name: undefined,
+    systemId: undefined,
+    params: {}
+  },
+  rules: {
+    name: [{ required: true, message: '设备类型名称不能为空', trigger: 'blur' }],
+    deviceLevel: [{ required: true, message: '设备等级不能为空', trigger: 'change' }],
+    systemId: [{ required: true, message: '分项系统不能为空', trigger: 'change' }]
+  }
+});
+
+const { queryParams, form, rules } = toRefs(formData);
+
+/** 查询设备类型信息列表 */
+const getList = async () => {
+  loading.value = true;
+  const res = await listDeviceType(queryParams.value);
+  deviceTypeList.value = res.rows;
+  total.value = res.total;
+  loading.value = false;
+};
+
+/** 取消按钮 */
+const cancel = () => {
+  reset();
+  dialog.visible = false;
+};
+
+/** 表单重置 */
+const reset = () => {
+  form.value = { ...initFormData };
+  deviceTypeFormRef.value?.resetFields();
+};
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.value.pageNum = 1;
+  getList();
+};
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value?.resetFields();
+  handleQuery();
+};
+
+/** 多选框选中数据 */
+const handleSelectionChange = (selection) => {
+  ids.value = selection.map((item) => item.id);
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+};
+
+/** 新增按钮操作 */
+const handleAdd = () => {
+  reset();
+  dialog.visible = true;
+  dialog.title = '新增设备类型信息';
+};
+
+/** 修改按钮操作 */
+const handleUpdate = async (row) => {
+  reset();
+  const _id = row?.id || ids.value[0];
+  const res = await getDeviceType(_id);
+  Object.assign(form.value, res.data);
+  dialog.visible = true;
+  dialog.title = '修改设备类型信息';
+};
+
+/** 提交按钮 */
+const submitForm = () => {
+  deviceTypeFormRef.value?.validate(async (valid: boolean) => {
+    if (valid) {
+      buttonLoading.value = true;
+      if (form.value.id) {
+        await updateDeviceType(form.value).finally(() => (buttonLoading.value = false));
+      } else {
+        await addDeviceType(form.value).finally(() => (buttonLoading.value = false));
+      }
+      proxy?.$modal.msgSuccess('操作成功');
+      dialog.visible = false;
+      await getList();
+    }
+  });
+};
+
+/** 删除按钮操作 */
+const handleDelete = async (row) => {
+  const _ids = row?.id || ids.value;
+  await proxy?.$modal.confirm('是否确认删除设备类型信息编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
+  await delDeviceType(_ids);
+  proxy?.$modal.msgSuccess('删除成功');
+  await getList();
+};
+
+const getTreeData = async () => {
+  getDeviceSystemTree({}).then(({ code, rows }) => {
+    if (code === 200) {
+      treeData.value = convertToTree(rows);
+      if (treeData.value.length === 0) {
+        treeData.value = [];
+      }
+    }
+  });
+};
+const convertToTree = (list) => {
+  let map = new Map();
+  let root = [];
+  for (let item of list) {
+    map.set(item.id, { ...item });
+  }
+  for (let item of list) {
+    if (item.parentId !== 0) {
+      let parent = map.get(item.parentId);
+      if (!parent.children) {
+        parent.children = [];
+      }
+      parent.children.push(map.get(item.id));
+    } else {
+      root.push(map.get(item.id));
+    }
+  }
+  return root;
+};
+const findNameWithParents = (data, idToFind, parentName = '') => {
+  for (let item of data) {
+    let fullName = parentName ? `${parentName}/${item.name}` : item.name;
+    if (item.id === idToFind) {
+      return fullName;
+    }
+    if (item.children && Array.isArray(item.children)) {
+      let result = findNameWithParents(item.children, idToFind, fullName);
+      if (result) {
+        return result;
+      }
+    }
+  }
+  return null; // 如果没有找到对应的 ID,则返回 null
+};
+const addSystem = (data) => {
+  systemDialog.visible = true;
+  systemDialog.title = '新增分项系统';
+  deviceSystemFormRef.value?.resetFields();
+  Object.keys(systemForm).forEach((key) => {
+    systemForm[key] = '';
+  });
+  if (data.name) {
+    systemForm.parentName = data.name;
+    systemForm.parentId = data.id;
+  } else {
+    systemForm.parentName = '根节点';
+    systemForm.parentId = 0;
+  }
+};
+const editSystem = (node, data) => {
+  systemDialog.visible = true;
+  systemDialog.title = '修改分项系统';
+  deviceSystemFormRef.value?.resetFields();
+  Object.keys(systemForm).forEach((key) => {
+    systemForm[key] = data[key];
+  });
+  if (data.parentId === 0) {
+    systemForm.parentName = '根节点';
+  } else {
+    systemForm.parentName = node.parent.data.name;
+  }
+};
+const delSystem = async (node, data) => {
+  if (node.childNodes.length) return proxy?.$modal.msgWarning('存在子节点,请先删除子节点');
+  await delDeviceSystem(data.id);
+  proxy?.$modal.msgSuccess('删除成功');
+  await getTreeData();
+};
+const handleNodeClick = (data, node) => {
+  queryParams.value.systemId = data.id;
+  handleQuery();
+};
+const submitSystemForm = () => {
+  deviceSystemFormRef.value?.validate(async (valid: boolean) => {
+    if (valid) {
+      buttonLoading.value = true;
+      if (systemForm.id) {
+        await editDeviceSystem(systemForm).finally(() => (buttonLoading.value = false));
+      } else {
+        await addDeviceSystem(systemForm).finally(() => (buttonLoading.value = false));
+      }
+      proxy?.$modal.msgSuccess('操作成功');
+      systemDialog.visible = false;
+      await getTreeData();
+    }
+  });
+};
+const handleModel = (row) => {
+  rightDrawer.value = true;
+  curRow.value = row;
+  if (row.modeId) {
+    getModels(row.modeId).then(({ code, data }) => {
+      if (code === 200) {
+        modelData.id = data.id;
+        modelData.name = data.name;
+        modelData.dataPoints = JSON.parse(data.dataPoints || '[]');
+        modelData.controlFuncs = JSON.parse(data.controlFuncs || '[]');
+        modelData.events = JSON.parse(data.events || '[]');
+      }
+    });
+  }
+};
+const addModel = () => {
+  modelDialog.visible = true;
+  modelDialog.title = activeName.value === 'dataPoints' ? '新增属性' : activeName.value === 'controlFuncs' ? '新增能力' : '新增事件';
+  editIndex.value = null;
+  modelFormRef.value?.resetFields();
+  Object.keys(modelData[`${activeName.value}Form`]).forEach((key) => {
+    modelData[`${activeName.value}Form`][key] = '';
+  });
+};
+const editModel = (index) => {
+  modelDialog.visible = true;
+  modelDialog.title = activeName.value === 'dataPoints' ? '修改属性' : activeName.value === 'controlFuncs' ? '修改能力' : '修改事件';
+  editIndex.value = index;
+  modelFormRef.value?.resetFields();
+  Object.assign(modelData[`${activeName.value}Form`], modelData[`${activeName.value}`][index]);
+};
+const delModel = async (index) => {
+  modelData[activeName.value].splice(index, 1);
+  const params = {};
+  params[activeName.value] = JSON.stringify(modelData[activeName.value]);
+  await editModels({ id: modelData.id, ...params });
+  proxy?.$modal.msgSuccess('删除成功');
+};
+const submitModelForm = () => {
+  modelFormRef.value?.validate(async (valid: boolean) => {
+    if (valid) {
+      if (editIndex.value !== null) {
+        modelData[activeName.value].splice(editIndex.value, 1, modelData[`${activeName.value}Form`]);
+      } else {
+        modelData[activeName.value].push(modelData[`${activeName.value}Form`]);
+      }
+      const params = { name: `${curRow.value.name}物模型` };
+      params[activeName.value] = JSON.stringify(modelData[activeName.value]);
+      buttonLoading.value = true;
+      if (modelData.id) {
+        await editModels({ id: modelData.id, ...params });
+        proxy?.$modal.msgSuccess('修改成功');
+      } else {
+        await addModels(params).then(({ code, data }) => {
+          if (code === 200) {
+            updateDeviceType({ id: curRow.value.id, modeId: data.id });
+          }
+        });
+        proxy?.$modal.msgSuccess('新增成功');
+      }
+      modelDialog.visible = false;
+      buttonLoading.value = false;
+    }
+  });
+};
+onMounted(() => {
+  getList();
+  getTreeData();
+});
+</script>
+<style lang="scss" scoped>
+.card-header {
+  display: flex;
+  justify-content: space-between;
+
+  .el-icon {
+    cursor: pointer;
+  }
+}
+
+.custom-tree-node {
+  flex: 1;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding-right: 5px;
+}
+
+.node-operateBtns {
+  div {
+    margin-top: 3px;
+    text-align: center;
+    cursor: pointer;
+
+    &:hover {
+      color: #409eff;
+    }
+  }
+}
+</style>
+<style lang="scss">
+.customDrawer {
+  .el-drawer__header {
+    align-items: flex-start !important;
+    margin-bottom: 10px;
+    .drawer-title {
+      .title-name {
+        color: #000;
+      }
+    }
+  }
+  .el-drawer__body {
+    padding-top: 0;
+  }
+}
+</style>

+ 5 - 0
src/views/deviceManage/modeling/index.vue

@@ -0,0 +1,5 @@
+<template>
+  <div class=""></div>
+</template>
+<script setup lang="ts"></script>
+<style lang="scss" scoped></style>

+ 345 - 0
src/views/deviceManage/versionManage/index.vue

@@ -0,0 +1,345 @@
+<template>
+  <div class="p-2">
+    <el-row :gutter="10">
+      <el-col :span="5">
+        <el-card>
+          <template #header>
+            <div class="card-header">分项系统</div>
+          </template>
+          <div>
+            <el-input v-model="filterText" style="width: 200px" placeholder="请输入关键字" />
+            <el-tree
+              ref="treeRef"
+              style="max-width: 600px; margin-top: 5px"
+              class="filter-tree"
+              :props="defaultProps"
+              :data="treeData"
+              node-key="id"
+              default-expand-all
+              highlight-current
+              :expand-on-click-node="false"
+              :filter-node-method="filterNode"
+              @node-click="handleNodeClick"
+            />
+          </div>
+        </el-card>
+      </el-col>
+      <el-col :span="19">
+        <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
+          <div v-show="showSearch" class="mb-[10px]">
+            <el-card shadow="hover">
+              <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="100px">
+                <el-form-item label="设备类型名称" prop="name">
+                  <el-input v-model="queryParams.name" placeholder="请输入名称" clearable @keyup.enter="handleQuery" />
+                </el-form-item>
+                <el-form-item label="品牌" prop="name">
+                  <el-input v-model="queryParams.name" placeholder="请输入品牌" clearable @keyup.enter="handleQuery" />
+                </el-form-item>
+                <el-form-item label="型号" prop="name">
+                  <el-input v-model="queryParams.name" placeholder="请输入型号" clearable @keyup.enter="handleQuery" />
+                </el-form-item>
+                <el-form-item>
+                  <el-button type="primary" icon="Search" @click="handleQuery"> 搜索 </el-button>
+                  <el-button icon="Refresh" @click="resetQuery"> 重置 </el-button>
+                </el-form-item>
+              </el-form>
+            </el-card>
+          </div>
+        </transition>
+
+        <el-card shadow="never">
+          <template #header>
+            <el-row :gutter="10" class="mb8">
+              <el-col :span="1.5">
+                <el-button v-hasPermi="['jdyw:deviceType:add']" type="primary" plain icon="Plus" @click="handleAdd"> 新增 </el-button>
+              </el-col>
+              <el-col :span="1.5">
+                <el-button v-hasPermi="['jdyw:deviceType:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate">
+                  修改
+                </el-button>
+              </el-col>
+              <el-col :span="1.5">
+                <el-button v-hasPermi="['jdyw:deviceType:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete">
+                  删除
+                </el-button>
+              </el-col>
+              <right-toolbar v-model:showSearch="showSearch" @query-table="getList" />
+            </el-row>
+          </template>
+
+          <el-table v-loading="loading" :data="deviceTypeList" @selection-change="handleSelectionChange">
+            <el-table-column type="selection" width="55" align="center" />
+            <el-table-column label="设备名称" align="center" prop="name" />
+            <el-table-column label="品牌" align="center" prop="deviceLevel" />
+            <el-table-column label="型号" align="center" prop="deviceLevel" />
+            <el-table-column label="供应商" align="center" prop="deviceLevel" />
+            <el-table-column label="联系人" align="center" prop="deviceLevel" />
+            <el-table-column label="联系方式" align="center" prop="deviceLevel" />
+            <el-table-column label="备注" align="center" prop="remark" />
+            <el-table-column label="创建时间" align="center" prop="remark" />
+            <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+              <template #default="scope">
+                <el-button v-hasPermi="['jdyw:deviceType:edit']" size="small" link type="primary" @click="handleUpdate(scope.row)">修改</el-button>
+                <el-button v-hasPermi="['jdyw:deviceType:remove']" size="small" link type="danger" @click="handleDelete(scope.row)">删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+          <pagination
+            v-show="total > 0"
+            v-model:page="queryParams.pageNum"
+            v-model:limit="queryParams.pageSize"
+            :total="total"
+            @pagination="getList"
+          />
+        </el-card>
+      </el-col>
+    </el-row>
+
+    <!-- 添加或修改设备类型信息对话框 -->
+    <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body>
+      <el-form ref="deviceTypeFormRef" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="设备名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入设备名称" />
+        </el-form-item>
+        <el-form-item label="设备等级" prop="deviceLevel">
+          <el-select v-model="form.deviceLevel" placeholder="请选择设备等级">
+            <el-option v-for="dict in device_level" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="分项系统" prop="systemId">
+          <el-tree-select
+            v-model="form.systemId"
+            :props="defaultProps"
+            node-key="id"
+            :data="treeData"
+            default-expand-all
+            :check-strictly="true"
+            :render-after-expand="false"
+          />
+        </el-form-item>
+        <el-form-item label="备注" prop="remark">
+          <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button :loading="buttonLoading" type="primary" @click="submitForm"> 确 定 </el-button>
+          <el-button @click="cancel"> 取 消 </el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup name="VersionManage" lang="ts">
+import {
+  listDeviceType,
+  getDeviceType,
+  delDeviceType,
+  addDeviceType,
+  updateDeviceType,
+  getDeviceSystemTree,
+  addDeviceSystem,
+  editDeviceSystem,
+  delDeviceSystem,
+  addModels,
+  editModels,
+  getModels
+} from '@/api/deviceManage/deviceType';
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+
+const deviceTypeList = ref([]);
+const buttonLoading = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref<Array<string | number>>([]);
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const queryFormRef = ref<ElFormInstance>();
+const deviceTypeFormRef = ref<ElFormInstance>();
+const filterText = ref('');
+const treeRef = ref<ElTreeInstance>();
+const filterNode = (value: string, data) => {
+  if (!value) return true;
+  return data.name.includes(value);
+};
+watch(filterText, (val) => {
+  treeRef.value!.filter(val);
+});
+const defaultProps = {
+  children: 'children',
+  label: 'name'
+};
+const treeData = ref([]);
+const dialog = reactive<DialogOption>({
+  visible: false,
+  title: ''
+});
+const { device_level } = toRefs<any>(proxy?.useDict('device_level'));
+
+const initFormData = {
+  id: undefined,
+  name: undefined,
+  deviceLevel: undefined,
+  systemId: null,
+  modeId: undefined,
+  remark: undefined,
+  ext1: undefined,
+  ext2: undefined
+};
+const formData = reactive({
+  form: { ...initFormData },
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10,
+    name: undefined,
+    systemId: undefined,
+    params: {}
+  },
+  rules: {
+    name: [{ required: true, message: '设备名称不能为空', trigger: 'blur' }],
+    deviceLevel: [{ required: true, message: '设备等级不能为空', trigger: 'change' }],
+    systemId: [{ required: true, message: '分项系统不能为空', trigger: 'change' }]
+  }
+});
+
+const { queryParams, form, rules } = toRefs(formData);
+
+/** 查询设备类型信息列表 */
+const getList = async () => {
+  loading.value = true;
+  const res = await listDeviceType(queryParams.value);
+  deviceTypeList.value = res.rows;
+  total.value = res.total;
+  loading.value = false;
+};
+
+/** 取消按钮 */
+const cancel = () => {
+  reset();
+  dialog.visible = false;
+};
+
+/** 表单重置 */
+const reset = () => {
+  form.value = { ...initFormData };
+  deviceTypeFormRef.value?.resetFields();
+};
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.value.pageNum = 1;
+  getList();
+};
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value?.resetFields();
+  handleQuery();
+};
+
+/** 多选框选中数据 */
+const handleSelectionChange = (selection) => {
+  ids.value = selection.map((item) => item.id);
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+};
+
+/** 新增按钮操作 */
+const handleAdd = () => {
+  reset();
+  dialog.visible = true;
+  dialog.title = '新增品牌型号';
+};
+
+/** 修改按钮操作 */
+const handleUpdate = async (row) => {
+  reset();
+  const _id = row?.id || ids.value[0];
+  const res = await getDeviceType(_id);
+  Object.assign(form.value, res.data);
+  dialog.visible = true;
+  dialog.title = '修改品牌型号';
+};
+
+/** 提交按钮 */
+const submitForm = () => {
+  deviceTypeFormRef.value?.validate(async (valid: boolean) => {
+    if (valid) {
+      buttonLoading.value = true;
+      if (form.value.id) {
+        await updateDeviceType(form.value).finally(() => (buttonLoading.value = false));
+      } else {
+        await addDeviceType(form.value).finally(() => (buttonLoading.value = false));
+      }
+      proxy?.$modal.msgSuccess('操作成功');
+      dialog.visible = false;
+      await getList();
+    }
+  });
+};
+
+/** 删除按钮操作 */
+const handleDelete = async (row) => {
+  const _ids = row?.id || ids.value;
+  await proxy?.$modal.confirm('是否确认删除设备类型信息编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
+  await delDeviceType(_ids);
+  proxy?.$modal.msgSuccess('删除成功');
+  await getList();
+};
+
+const getTreeData = async () => {
+  getDeviceSystemTree({}).then(({ code, rows }) => {
+    if (code === 200) {
+      treeData.value = convertToTree(rows);
+      if (treeData.value.length === 0) {
+        treeData.value = [];
+      }
+    }
+  });
+};
+const convertToTree = (list) => {
+  let map = new Map();
+  let root = [];
+  for (let item of list) {
+    map.set(item.id, { ...item });
+  }
+  for (let item of list) {
+    if (item.parentId !== 0) {
+      let parent = map.get(item.parentId);
+      if (!parent.children) {
+        parent.children = [];
+      }
+      parent.children.push(map.get(item.id));
+    } else {
+      root.push(map.get(item.id));
+    }
+  }
+  return root;
+};
+const findNameWithParents = (data, idToFind, parentName = '') => {
+  for (let item of data) {
+    let fullName = parentName ? `${parentName}/${item.name}` : item.name;
+    if (item.id === idToFind) {
+      return fullName;
+    }
+    if (item.children && Array.isArray(item.children)) {
+      let result = findNameWithParents(item.children, idToFind, fullName);
+      if (result) {
+        return result;
+      }
+    }
+  }
+  return null; // 如果没有找到对应的 ID,则返回 null
+};
+const handleNodeClick = (data, node) => {
+  queryParams.value.systemId = data.id;
+  handleQuery();
+};
+onMounted(() => {
+  getList();
+  getTreeData();
+});
+</script>
+<style lang="scss" scoped></style>

+ 1 - 90
src/views/index.vue

@@ -1,95 +1,6 @@
 <template>
   <div class="app-container home">
-    <el-row :gutter="20">
-      <el-col :sm="24" :lg="12" style="padding-left: 20px">
-        <h2>RuoYi-Vue-Plus多租户管理系统</h2>
-        <p>
-          RuoYi-Vue-Plus 是基于 RuoYi-Vue 针对 分布式集群 场景升级(不兼容原框架)
-          <br />
-          * 前端开发框架 Vue3、TS、Element Plus<br />
-          * 后端开发框架 Spring Boot<br />
-          * 容器框架 Undertow 基于 Netty 的高性能容器<br />
-          * 权限认证框架 Sa-Token 支持多终端认证系统<br />
-          * 关系数据库 MySQL 适配 8.X 最低 5.7<br />
-          * 缓存数据库 Redis 适配 6.X 最低 4.X<br />
-          * 数据库框架 Mybatis-Plus 快速 CRUD 增加开发效率<br />
-          * 数据库框架 p6spy 更强劲的 SQL 分析<br />
-          * 多数据源框架 dynamic-datasource 支持主从与多种类数据库异构<br />
-          * 序列化框架 Jackson 统一使用 jackson 高效可靠<br />
-          * Redis客户端 Redisson 性能强劲、API丰富<br />
-          * 分布式限流 Redisson 全局、请求IP、集群ID 多种限流<br />
-          * 分布式锁 Lock4j 注解锁、工具锁 多种多样<br />
-          * 分布式幂等 Lock4j 基于分布式锁实现<br />
-          * 分布式链路追踪 SkyWalking 支持链路追踪、网格分析、度量聚合、可视化<br />
-          * 分布式任务调度 SnailJob 高性能 高可靠 易扩展<br />
-          * 文件存储 Minio 本地存储<br />
-          * 文件存储 七牛、阿里、腾讯 云存储<br />
-          * 监控框架 SpringBoot-Admin 全方位服务监控<br />
-          * 校验框架 Validation 增强接口安全性 严谨性<br />
-          * Excel框架 Alibaba EasyExcel 性能优异 扩展性强<br />
-          * 文档框架 SpringDoc、javadoc 无注解零入侵基于java注释<br />
-          * 工具类框架 Hutool、Lombok 减少代码冗余 增加安全性<br />
-          * 代码生成器 适配MP、SpringDoc规范化代码 一键生成前后端代码<br />
-          * 部署方式 Docker 容器编排 一键部署业务集群<br />
-          * 国际化 SpringMessage Spring标准国际化方案<br />
-        </p>
-        <p><b>当前版本:</b> <span>v5.2.2</span></p>
-        <p>
-          <el-tag type="danger">&yen;免费开源</el-tag>
-        </p>
-        <p>
-          <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://gitee.com/dromara/RuoYi-Vue-Plus')">访问码云</el-button>
-          <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://github.com/dromara/RuoYi-Vue-Plus')">访问GitHub</el-button>
-          <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://plus-doc.dromara.org/#/ruoyi-vue-plus/changlog')"
-            >更新日志</el-button
-          >
-        </p>
-      </el-col>
-
-      <el-col :sm="24" :lg="12" style="padding-left: 20px">
-        <h2>RuoYi-Cloud-Plus多租户微服务管理系统</h2>
-        <p>
-          RuoYi-Cloud-Plus 微服务通用权限管理系统 重写 RuoYi-Cloud 全方位升级(不兼容原框架)
-          <br />
-          * 前端开发框架 Vue3、TS、Element UI<br />
-          * 后端开发框架 Spring Boot<br />
-          * 微服务开发框架 Spring Cloud、Spring Cloud Alibaba<br />
-          * 容器框架 Undertow 基于 XNIO 的高性能容器<br />
-          * 权限认证框架 Sa-Token、Jwt 支持多终端认证系统<br />
-          * 关系数据库 MySQL 适配 8.X 最低 5.7<br />
-          * 关系数据库 Oracle 适配 11g 12c<br />
-          * 关系数据库 PostgreSQL 适配 13 14<br />
-          * 关系数据库 SQLServer 适配 2017 2019<br />
-          * 缓存数据库 Redis 适配 6.X 最低 5.X<br />
-          * 分布式注册中心 Alibaba Nacos 采用2.X 基于GRPC通信高性能<br />
-          * 分布式配置中心 Alibaba Nacos 采用2.X 基于GRPC通信高性能<br />
-          * 服务网关 Spring Cloud Gateway 响应式高性能网关<br />
-          * 负载均衡 Spring Cloud Loadbalancer 负载均衡处理<br />
-          * RPC远程调用 Apache Dubbo 原生态使用体验、高性能<br />
-          * 分布式限流熔断 Alibaba Sentinel 无侵入、高扩展<br />
-          * 分布式事务 Alibaba Seata 无侵入、高扩展 支持 四种模式<br />
-          * 分布式消息队列 Apache Kafka 高性能高速度<br />
-          * 分布式消息队列 Apache RocketMQ 高可用功能多样<br />
-          * 分布式消息队列 RabbitMQ 支持各种扩展插件功能多样性<br />
-          * 分布式搜索引擎 ElasticSearch 业界知名<br />
-          * 分布式链路追踪 Apache SkyWalking 链路追踪、网格分析、度量聚合、可视化<br />
-          * 分布式日志中心 ELK 业界成熟解决方案<br />
-          * 分布式监控 Prometheus、Grafana 全方位性能监控<br />
-          * 其余与 Vue 版本一致<br />
-        </p>
-        <p><b>当前版本:</b> <span>v2.2.1</span></p>
-        <p>
-          <el-tag type="danger">&yen;免费开源</el-tag>
-        </p>
-        <p>
-          <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://gitee.com/dromara/RuoYi-Cloud-Plus')">访问码云</el-button>
-          <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://github.com/dromara/RuoYi-Cloud-Plus')">访问GitHub</el-button>
-          <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://plus-doc.dromara.org/#/ruoyi-cloud-plus/changlog')"
-            >更新日志</el-button
-          >
-        </p>
-      </el-col>
-    </el-row>
+    首页
     <el-divider />
   </div>
 </template>

+ 4 - 4
src/views/login.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="login">
     <el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form">
-      <h3 class="title">RuoYi-Vue-Plus多租户管理系统</h3>
+      <h3 class="title">机电运维平台</h3>
       <el-form-item v-if="tenantEnabled" prop="tenantId">
         <el-select v-model="loginForm.tenantId" filterable placeholder="请选择/输入公司名称" style="width: 100%">
           <el-option v-for="item in tenantList" :key="item.tenantId" :label="item.companyName" :value="item.tenantId"></el-option>
@@ -27,7 +27,7 @@
         </div>
       </el-form-item>
       <el-checkbox v-model="loginForm.rememberMe" style="margin: 0 0 25px 0">记住密码</el-checkbox>
-      <el-form-item style="float: right">
+      <!-- <el-form-item style="float: right">
         <el-button circle title="微信登录" @click="doSocialLogin('wechat')">
           <svg-icon icon-class="wechat" />
         </el-button>
@@ -43,7 +43,7 @@
         <el-button circle title="Github登录" @click="doSocialLogin('github')">
           <svg-icon icon-class="github" />
         </el-button>
-      </el-form-item>
+      </el-form-item> -->
       <el-form-item style="width: 100%">
         <el-button :loading="loading" size="large" type="primary" style="width: 100%" @click.prevent="handleLogin">
           <span v-if="!loading">登 录</span>
@@ -56,7 +56,7 @@
     </el-form>
     <!--  底部  -->
     <div class="el-login-footer">
-      <span>Copyright © 2018-2024 疯狂的狮子Li All Rights Reserved.</span>
+      <!-- <span>Copyright © 2018-2024 疯狂的狮子Li All Rights Reserved.</span> -->
     </div>
   </div>
 </template>

+ 1 - 1
vite.config.ts

@@ -25,7 +25,7 @@ export default defineConfig(({ mode, command }: ConfigEnv): UserConfig => {
       open: true,
       proxy: {
         [env.VITE_APP_BASE_API]: {
-          target: 'http://localhost:8080',
+          target: 'http://jdyw.xt.wenhq.top:8083/',
           changeOrigin: true,
           ws: true,
           rewrite: (path) => path.replace(new RegExp('^' + env.VITE_APP_BASE_API), '')