ZhenHongpeng
昨天 3c1436878578d9df4d8358b181492dacc4a713f9
本地开发https
已修改5个文件
已添加2个文件
463 ■■■■ 文件已修改
package.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/uav/dock.js 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/uav/server.js 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/device/airport/index.vue 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/device/servers/index.vue 310 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vite.config.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vite/plugins/index.js 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json
@@ -17,6 +17,7 @@
  },
  "dependencies": {
    "@element-plus/icons-vue": "2.3.1",
    "@vitejs/plugin-basic-ssl": "^2.1.0",
    "@vueup/vue-quill": "1.2.0",
    "@vueuse/core": "13.3.0",
    "axios": "1.9.0",
src/api/uav/dock.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,11 @@
import request from '@/utils/request'
import { parseStrEmpty } from "@/utils/ruoyi";
// æŸ¥è¯¢æœºåœºåˆ—表
export function listDock(query) {
  return request({
    url: '/dock/device/list',
    method: 'get',
    params: query
  })
}
src/api/uav/server.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,45 @@
import request from '@/utils/request'
import { parseStrEmpty } from "@/utils/ruoyi";
// æŸ¥è¯¢æœåŠ¡å™¨åˆ—è¡¨
export function listServer(query) {
  return request({
    url: '/uav/server/list',
    method: 'get',
    params: query
  })
}
// æŸ¥è¯¢æœåŠ¡å™¨è¯¦ç»†
export function getServer(id) {
  return request({
    url: '/uav/server/' + parseStrEmpty(id),
    method: 'get'
  })
}
// æ–°å¢žæœåС噍
export function addServer(data) {
  return request({
    url: '/uav/server',
    method: 'post',
    data: data
  })
}
// ä¿®æ”¹æœåС噍
export function updateServer(data) {
  return request({
    url: '/uav/server',
    method: 'put',
    data: data
  })
}
// åˆ é™¤æœåС噍
export function delServer(userId) {
  return request({
    url: '/uav/server/' + userId,
    method: 'delete'
  })
}
src/views/device/airport/index.vue
@@ -69,16 +69,16 @@
              <el-table-column
                label="设备型号"
                align="center"
                key="deviceType"
                prop="deviceType"
                v-if="columns.ip.visible"
                key="deviceName"
                prop="deviceName"
                v-if="columns.deviceName.visible"
              />
              <el-table-column
                label="设备SN"
                align="center"
                key="deviceSN"
                prop="deviceSN"
                v-if="columns.ip.visible"
                key="deviceSn"
                prop="deviceSn"
                v-if="columns.deviceSn.visible"
                :show-overflow-tooltip="true"
              />
              <el-table-column
@@ -86,7 +86,7 @@
                align="center"
                key="deviceName"
                prop="deviceName"
                v-if="columns.port.visible"
                v-if="columns.deviceName.visible"
                :show-overflow-tooltip="true"
              />
@@ -123,13 +123,8 @@
import { getToken } from "@/utils/auth";
import useAppStore from "@/store/modules/app";
import {
  fetchCameraList,
  delCamera,
  getCameraDetail,
  updateCamera,
  addCamera,
  fetchChannelList,
} from "@/api/device/camera";
  listDock,
} from "@/api/uav/dock";
import { deptTreeSelect } from "@/api/system/user";
import { Splitpanes, Pane } from "splitpanes";
import "splitpanes/dist/splitpanes.css";
@@ -161,14 +156,9 @@
const airPortList = ref([]);
// åˆ—显隐信息
const columns = ref({
  name: { label: "相机名称", visible: true },
  ip: { label: "IP地址", visible: true },
  port: { label: "端口", visible: true },
  factory: { label: "厂商", visible: true },
  type: { label: "类型", visible: true },
  chanNum: { label: "通道数", visible: true },
  chanNum: { label: "通道数", visible: true },
  state: { label: "状态", visible: true },
  deviceName: { label: "设备名称", visible: true },
  deviceSn: { label: "设备SN", visible: true },
  state: { label: "设备状态", visible: true },
});
const data = reactive({
@@ -200,37 +190,35 @@
function getList() {
  loading.value = true;
  airPortList.value = [
    {
      deviceType: "Dock",
      deviceSN: "8888888",
      deviceName: "机场名称",
      deviceState: "设备空闲中",
      joinTime: "2025-12-01 12:00:00",
      id: 1,
      children: [
        {
          id: 2,
          deviceType: "M30T",
          deviceSN: "9999",
          deviceName: "飞行器名称",
          deviceState: "舱内关机",
          joinTime: "",
        },
      ],
    },
  ];
  // airPortList.value = [
  //   {
  //     deviceType: "Dock",
  //     deviceSn: "8888888",
  //     deviceName: "机场名称",
  //     deviceState: "设备空闲中",
  //     joinTime: "2025-12-01 12:00:00",
  //     id: 1,
  //     children: [
  //       {
  //         id: 2,
  //         deviceType: "M30T",
  //         deviceSn: "9999",
  //         deviceName: "飞行器名称",
  //         deviceState: "舱内关机",
  //         joinTime: "",
  //       },
  //     ],
  //   },
  // ];
  // loading.value = false;
  loading.value = false;
  total.value = 1;
  // fetchCameraList(proxy.addDateRange(queryParams.value, dateRange.value)).then(
  //   (res) => {
  //     loading.value = false;
  //     serverList.value = res.rows;
  //     total.value = res.total;
  //   }
  // );
  listDock(queryParams.value).then(
    (res) => {
      loading.value = false;
      airPortList.value = res.data;
      total.value = res.total;
    }
  );
}
/** æŸ¥è¯¢éƒ¨é—¨ä¸‹æ‹‰æ ‘结构 */
src/views/device/servers/index.vue
@@ -42,29 +42,14 @@
              v-show="showSearch"
              label-width="68px"
            >
              <el-form-item label="名称" prop="userName">
              <el-form-item label="名称" prop="serverName">
                <el-input
                  v-model="queryParams.userName"
                  v-model="queryParams.serverName"
                  placeholder="请输入名称"
                  clearable
                  style="width: 240px"
                  @keyup.enter="handleQuery"
                />
              </el-form-item>
              <el-form-item label="操作系统" prop="os">
                <el-select
                  v-model="queryParams.status"
                  placeholder="操作系统"
                  clearable
                  style="width: 240px"
                >
                  <el-option
                    v-for="dict in sys_os_type"
                    :key="dict.value"
                    :label="dict.label"
                    :value="dict.value"
                  />
                </el-select>
              </el-form-item>
              <el-form-item label="状态" prop="status">
                <el-select
@@ -72,6 +57,7 @@
                  placeholder="服务器状态"
                  clearable
                  style="width: 240px"
                  @change="handleQuery"
                >
                  <el-option
                    v-for="dict in sys_servers_status"
@@ -138,38 +124,39 @@
              <el-table-column
                label="ID"
                align="center"
                key="userId"
                prop="userId"
                v-if="columns.userId.visible"
                key="id"
                prop="id"
                v-if="columns.id.visible"
              />
              <el-table-column
                label="名称"
                align="center"
                key="userId"
                prop="userId"
                v-if="columns.userId.visible"
                key="serverName"
                prop="serverName"
                v-if="columns.serverName.visible"
              />
              <el-table-column
                label="IP地址"
                align="center"
                key="userName"
                prop="userName"
                v-if="columns.userName.visible"
                key="host"
                prop="host"
                v-if="columns.host.visible"
              />
              <el-table-column
                label="HTTP端口"
                align="center"
                key="userName"
                prop="userName"
                v-if="columns.userName.visible"
                key="httpPort"
                prop="httpPort"
                v-if="columns.httpPort.visible"
              />
              <el-table-column
                label="TCP端口"
                align="center"
                key="userName"
                prop="userName"
                v-if="columns.userName.visible"
                key="tcpPort"
                prop="tcpPort"
                v-if="columns.tcpPort.visible"
              />
              <!-- todo çŠ¶æ€æ²¡æœ‰ -->
              <el-table-column
                label="状态"
                align="center"
@@ -188,11 +175,6 @@
                  >
                </template>
              </el-table-column>
              <el-table-column prop="status" label="操作系统">
                <template #default="scope">
                  <dict-tag :options="sys_os_type" :value="scope.row.status" />
                </template>
              </el-table-column>
              <el-table-column
                label="部门"
                align="center"
@@ -200,18 +182,11 @@
                prop="dept.deptName"
                v-if="columns.deptName.visible"
                :show-overflow-tooltip="true"
              />
              <!-- <el-table-column
                label="运行时间"
                align="center"
                prop="createTime"
                v-if="columns.createTime.visible"
                width="160"
              >
                <template #default="scope">
                  <span>{{ parseTime(scope.row.createTime) }}</span>
                  {{ computedDeptName(scope.row.deptId) }}
                </template>
              </el-table-column> -->
              </el-table-column>
              <el-table-column
                label="操作"
                align="center"
@@ -275,53 +250,36 @@
              ref="userRef"
              label-width="120px"
            >
              <el-form-item label="ID" prop="nickName">
              <!-- <el-form-item label="ID" prop="id">
                <el-input v-model="form.id" placeholder="请输入服务器ID" />
              </el-form-item> -->
              <el-form-item label="服务器名称" prop="serverName">
                <el-input
                  v-model="form.nickName"
                  placeholder="请输入服务器ID"
                  maxlength="30"
                />
              </el-form-item>
              <el-form-item label="服务器名称" prop="nickName">
                <el-input
                  v-model="form.nickName"
                  v-model="form.serverName"
                  placeholder="请输入服务器名称"
                  maxlength="30"
                />
              </el-form-item>
              <el-form-item label="IP地址" prop="nickName">
              <el-form-item label="IP地址" prop="host">
                <el-input
                  v-model="form.nickName"
                  v-model="form.host"
                  placeholder="例如: 192.168.1.100"
                  maxlength="30"
                />
              </el-form-item>
              <el-form-item label="HTTP端口" prop="nickName">
              <el-form-item label="HTTP端口" prop="httpPort">
                <el-input
                  type="Number"
                  v-model="form.nickName"
                  v-model="form.httpPort"
                  placeholder="请输入HTTP端口"
                  maxlength="30"
                />
              </el-form-item>
              <el-form-item label="TCP端口" prop="nickName">
              <el-form-item label="TCP端口" prop="tcpPort">
                <el-input
                  type="Number"
                  v-model="form.nickName"
                  v-model="form.tcpPort"
                  placeholder="请输入TCP端口"
                  maxlength="30"
                />
              </el-form-item>
              <!-- <el-form-item label="服务器类型" prop="nickName">
                <el-select v-model="form.sex" placeholder="请选择">
                  <el-option
                    v-for="dict in sys_servers_type"
                    :key="dict.value"
                    :label="dict.label"
                    :value="dict.value"
                  ></el-option>
                </el-select>
              </el-form-item> -->
              <el-form-item label="经度" prop="longitude">
                <el-input
                  type="password"
@@ -338,7 +296,7 @@
                  maxlength="30"
                />
              </el-form-item>
              <el-form-item label="高程" prop="location">
              <el-form-item label="高程" prop="altitude">
                <el-input
                  type="password"
                  v-model="form.altitude"
@@ -357,20 +315,18 @@
                  check-strictly
                />
              </el-form-item>
                <el-form-item label="密钥ID" prop="location">
              <el-form-item label="密钥ID" prop="accessKeyId">
                <el-input
                  type="password"
                  v-model="form.altitude"
                  placeholder=""
                  maxlength="30"
                  v-model="form.accessKeyId"
                  placeholder="请输入密钥ID"
                />
              </el-form-item>
                <el-form-item label="访问密钥" prop="location">
              <el-form-item label="访问密钥" prop="accessKeySecret">
                <el-input
                  type="password"
                  v-model="form.altitude"
                  placeholder=""
                  maxlength="30"
                  v-model="form.accessKeySecret"
                  placeholder="请输入访问密钥"
                />
              </el-form-item>
            </el-form>
@@ -396,11 +352,7 @@
      </template>
    </el-dialog>
    <el-dialog
      title="飞行器列表"
      v-model="aircraftOpen"
      append-to-body
    >
    <el-dialog title="飞行器列表" v-model="aircraftOpen" append-to-body>
      <el-table :data="aircraftListData">
        <el-table-column prop="name" label="通道名称"> </el-table-column>
        <el-table-column prop="chanNo" label="通道号"> </el-table-column>
@@ -430,15 +382,13 @@
import { getToken } from "@/utils/auth";
import useAppStore from "@/store/modules/app";
import {
  changeUserStatus,
  listUser,
  resetUserPwd,
  delUser,
  getUser,
  updateUser,
  addUser,
  deptTreeSelect,
} from "@/api/system/user";
  listServer,
  delServer,
  getServer,
  updateServer,
  addServer,
} from "@/api/uav/server";
import { deptTreeSelect } from "@/api/system/user";
import { Splitpanes, Pane } from "splitpanes";
import "splitpanes/dist/splitpanes.css";
import * as Cesium from "cesium";
@@ -465,20 +415,18 @@
const multiple = ref(true);
const total = ref(0);
const title = ref("");
const dateRange = ref([]);
const deptName = ref("");
const deptOptions = ref(undefined);
const enabledDeptOptions = ref(undefined);
const roleOptions = ref([]);
// åˆ—显隐信息
const columns = ref({
  userId: { label: "服务器编号", visible: true },
  userName: { label: "服务器名称", visible: true },
  nickName: { label: "服务器昵称", visible: true },
  id: { label: "服务器编号", visible: true },
  serverName: { label: "服务器名称", visible: true },
  host: { label: "IP地址", visible: true },
  httpPort: { label: "HTTP端口", visible: true },
  tcpPort: { label: "TCP端口", visible: true },
  deptName: { label: "部门", visible: true },
  phonenumber: { label: "手机号码", visible: true },
  status: { label: "状态", visible: true },
  createTime: { label: "创建时间", visible: true },
});
const data = reactive({
@@ -486,57 +434,30 @@
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    userName: undefined,
    phonenumber: undefined,
    serverName: undefined,
    status: undefined,
    deptId: undefined,
  },
  rules: {
    userName: [
      { required: true, message: "服务器名称不能为空", trigger: "blur" },
      {
        min: 2,
        max: 20,
        message: "服务器名称长度必须介于 2 å’Œ 20 ä¹‹é—´",
        trigger: "blur",
      },
    id: [{ required: true, message: "请输入服务器ID", trigger: "blur" }],
    serverName: [
      { required: true, message: "请输入服务器名称", trigger: "blur" },
    ],
    nickName: [
      { required: true, message: "服务器昵称不能为空", trigger: "blur" },
    ],
    password: [
      { required: true, message: "服务器密码不能为空", trigger: "blur" },
      {
        min: 5,
        max: 20,
        message: "服务器密码长度必须介于 5 å’Œ 20 ä¹‹é—´",
        trigger: "blur",
      },
      {
        pattern: /^[^<>"'|\\]+$/,
        message: "不能包含非法字符:< > \" ' \\\ |",
        trigger: "blur",
      },
    ],
    email: [
      {
        type: "email",
        message: "请输入正确的邮箱地址",
        trigger: ["blur", "change"],
      },
    ],
    phonenumber: [
      {
        pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
        message: "请输入正确的手机号码",
        trigger: "blur",
      },
    host: [{ required: true, message: "请输入IP地址", trigger: "blur" }],
    httpPort: [{ required: true, message: "请输入HTTP端口", trigger: "blur" }],
    tcpPort: [{ required: true, message: "请输入TCP端口", trigger: "blur" }],
    longitude: [{ required: true, message: "请选择相机位置", trigger: "blur" }],
    latitude: [{ required: true, message: "请选择相机位置", trigger: "blur" }],
    altitude: [{ required: true, message: "请选择相机位置", trigger: "blur" }],
    deptId: [{ required: true, message: "请选择所属部门", trigger: "blur" }],
    accessKeyId: [{ required: true, message: "请输入密钥ID", trigger: "blur" }],
    accessKeySecret: [
      { required: true, message: "请输入访问密钥", trigger: "blur" },
    ],
  },
});
const { queryParams, form, rules } = toRefs(data);
const aircraftData = reactive({
  aircraftQueryParams: {
@@ -563,16 +484,62 @@
  proxy.$refs["deptTreeRef"].filter(val);
});
function findNodeByIdRecursive(tree, targetId) {
  for (const node of tree) {
    if (node.id === targetId) {
      return node;
    }
    // å¦‚果有子节点,递归查找
    if (node.children && node.children.length > 0) {
      const found = findNodeByIdRecursive(node.children, targetId);
      if (found) {
        return found;
      }
    }
  }
  // æœªæ‰¾åˆ°è¿”回null
  return null;
}
function computedDeptName(deptId) {
  const result1 = findNodeByIdRecursive(deptOptions.value, deptId);
  return result1.label;
}
/** æŸ¥è¯¢æœåŠ¡å™¨åˆ—è¡¨ */
function getList() {
  loading.value = true;
  listUser(proxy.addDateRange(queryParams.value, dateRange.value)).then(
    (res) => {
      loading.value = false;
      serverList.value = res.rows;
      total.value = res.total;
    }
  );
  listServer(queryParams.value).then((res) => {
    loading.value = false;
    res.rows.forEach((row) => {
      row.ardDroneInfoList = [
        {
          ardServerInfo: {},
          boxName: "",
          boxSn: "",
          boxVersion: "",
          createBy: "",
          createTime: "",
          deptId: 0,
          id: "",
          lastTaskId: 0,
          onLine: 0,
          params: {},
          remark: "",
          serverInfoId: "",
          startTime: "",
          updateBy: "",
          updateTime: "",
          userId: 0,
          videoPort: 0,
          videoServer: "",
        },
      ];
    });
    serverList.value = res.rows;
    total.value = res.total;
  });
}
/** æŸ¥è¯¢éƒ¨é—¨ä¸‹æ‹‰æ ‘结构 */
@@ -612,7 +579,6 @@
/** é‡ç½®æŒ‰é’®æ“ä½œ */
function resetQuery() {
  dateRange.value = [];
  proxy.resetForm("queryRef");
  queryParams.value.deptId = undefined;
  proxy.$refs.deptTreeRef.setCurrentKey(null);
@@ -625,7 +591,7 @@
  proxy.$modal
    .confirm('是否确认删除服务器编号为"' + userIds + '"的数据项?')
    .then(function () {
      return delUser(userIds);
      return delServer(userIds);
    })
    .then(() => {
      getList();
@@ -633,7 +599,6 @@
    })
    .catch(() => {});
}
/** é€‰æ‹©æ¡æ•°  */
function handleSelectionChange(selection) {
@@ -644,20 +609,7 @@
/** é‡ç½®æ“ä½œè¡¨å• */
function reset() {
  form.value = {
    userId: undefined,
    deptId: undefined,
    userName: undefined,
    nickName: undefined,
    password: undefined,
    phonenumber: undefined,
    email: undefined,
    sex: undefined,
    status: "0",
    remark: undefined,
    postIds: [],
    roleIds: [],
  };
  form.value = {};
  proxy.resetForm("userRef");
}
@@ -684,24 +636,20 @@
/** ä¿®æ”¹æŒ‰é’®æ“ä½œ */
function handleUpdate(row) {
  reset();
  const userId = row.userId || ids.value;
  getUser(userId).then((response) => {
  const id = row.id || ids.value;
  getServer(id).then((response) => {
    form.value = response.data;
    roleOptions.value = response.roles;
    form.value.postIds = response.postIds;
    form.value.roleIds = response.roleIds;
    open.value = true;
    title.value = "修改服务器";
    form.password = "";
    nextTick(() => {
      useCesium.initCesium(cesiumRef);
      initCesiumClickEvent();
      useCesium.cesium.addPoint(
        new Cesium.Cartesian3.fromDegrees(
          126.66115696371807,
          45.736627033013534,
          200
          form.value.longitude,
          form.value.latitude,
          form.value.altitude
        ),
        {
          text: "位置",
@@ -716,14 +664,14 @@
function submitForm() {
  proxy.$refs["userRef"].validate((valid) => {
    if (valid) {
      if (form.value.userId != undefined) {
        updateUser(form.value).then((response) => {
      if (form.value.id != undefined) {
        updateServer(form.value).then((response) => {
          proxy.$modal.msgSuccess("修改成功");
          open.value = false;
          getList();
        });
      } else {
        addUser(form.value).then((response) => {
        addServer(form.value).then((response) => {
          proxy.$modal.msgSuccess("新增成功");
          open.value = false;
          getList();
vite.config.js
@@ -45,6 +45,7 @@
      port: 80,
      host: true,
      open: true,
      // https: true,
      proxy: {
        // https://cn.vitejs.dev/config/#server-proxy
        '/dev-api': {
vite/plugins/index.js
@@ -5,12 +5,13 @@
import createCompression from './compression'
import createSetupExtend from './setup-extend'
import cesium from 'vite-plugin-cesium'
import basicSsl from '@vitejs/plugin-basic-ssl'
export default function createVitePlugins(viteEnv, isBuild = false) {
    const vitePlugins = [vue(), cesium()]
    vitePlugins.push(createAutoImport())
    vitePlugins.push(createSetupExtend())
    vitePlugins.push(createSvgIcon(isBuild))
    vitePlugins.push(basicSsl())
    isBuild && vitePlugins.push(...createCompression(viteEnv))
    return vitePlugins
}