wangxinping 2 months ago
parent
commit
8146cd8a0c
  1. 104
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/UsersController.java
  2. 2
      ruoyi-admin/src/main/resources/application-druid.yml
  3. 82
      ruoyi-system/src/main/java/com/ruoyi/system/domain/Users.java
  4. 61
      ruoyi-system/src/main/java/com/ruoyi/system/mapper/UsersMapper.java
  5. 61
      ruoyi-system/src/main/java/com/ruoyi/system/service/IUsersService.java
  6. 93
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UsersServiceImpl.java
  7. 66
      ruoyi-system/src/main/resources/mapper/system/UsersMapper.xml
  8. BIN
      ruoyi-ui/node_modules.zip
  9. 139
      ruoyi-ui/src/views/childRoom/LeftMenu.vue
  10. 723
      ruoyi-ui/src/views/childRoom/RightPanel.vue
  11. 2
      ruoyi-ui/vue.config.js

104
ruoyi-admin/src/main/java/com/ruoyi/web/controller/UsersController.java

@ -0,0 +1,104 @@
package com.ruoyi.web.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.Users;
import com.ruoyi.system.service.IUsersService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* 系统用户Controller
*
* @author ruoyi
* @date 2026-01-14
*/
@RestController
@RequestMapping("/system/users")
public class UsersController extends BaseController
{
@Autowired
private IUsersService usersService;
/**
* 查询系统用户列表
*/
@PreAuthorize("@ss.hasPermi('system:users:list')")
@GetMapping("/list")
public TableDataInfo list(Users users)
{
startPage();
List<Users> list = usersService.selectUsersList(users);
return getDataTable(list);
}
/**
* 导出系统用户列表
*/
@PreAuthorize("@ss.hasPermi('system:users:export')")
@Log(title = "系统用户", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, Users users)
{
List<Users> list = usersService.selectUsersList(users);
ExcelUtil<Users> util = new ExcelUtil<Users>(Users.class);
util.exportExcel(response, list, "系统用户数据");
}
/**
* 获取系统用户详细信息
*/
@PreAuthorize("@ss.hasPermi('system:users:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(usersService.selectUsersById(id));
}
/**
* 新增系统用户
*/
@PreAuthorize("@ss.hasPermi('system:users:add')")
@Log(title = "系统用户", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody Users users)
{
return toAjax(usersService.insertUsers(users));
}
/**
* 修改系统用户
*/
@PreAuthorize("@ss.hasPermi('system:users:edit')")
@Log(title = "系统用户", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody Users users)
{
return toAjax(usersService.updateUsers(users));
}
/**
* 删除系统用户
*/
@PreAuthorize("@ss.hasPermi('system:users:remove')")
@Log(title = "系统用户", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(usersService.deleteUsersByIds(ids));
}
}

2
ruoyi-admin/src/main/resources/application-druid.yml

@ -8,7 +8,7 @@ spring:
master:
url: jdbc:mysql://localhost:3306/ry?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 123456
password: A20040303ctw!
# 从库数据源
slave:
# 从数据源开关/默认关闭

82
ruoyi-system/src/main/java/com/ruoyi/system/domain/Users.java

@ -0,0 +1,82 @@
package com.ruoyi.system.domain;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* 系统用户对象 users
*
* @author ruoyi
* @date 2026-01-14
*/
public class Users extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 登录账号 */
@Excel(name = "登录账号")
private String username;
/** 密码 (建议存哈希值) */
@Excel(name = "密码 (建议存哈希值)")
private String password;
/** 权限等级: 1=管理员(L1), 2=房主(L2), 3=操作员(L3) */
@Excel(name = "权限等级: 1=管理员(L1), 2=房主(L2), 3=操作员(L3)")
private Long role;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setUsername(String username)
{
this.username = username;
}
public String getUsername()
{
return username;
}
public void setPassword(String password)
{
this.password = password;
}
public String getPassword()
{
return password;
}
public void setRole(Long role)
{
this.role = role;
}
public Long getRole()
{
return role;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("username", getUsername())
.append("password", getPassword())
.append("role", getRole())
.toString();
}
}

61
ruoyi-system/src/main/java/com/ruoyi/system/mapper/UsersMapper.java

@ -0,0 +1,61 @@
package com.ruoyi.system.mapper;
import java.util.List;
import com.ruoyi.system.domain.Users;
/**
* 系统用户Mapper接口
*
* @author ruoyi
* @date 2026-01-14
*/
public interface UsersMapper
{
/**
* 查询系统用户
*
* @param id 系统用户主键
* @return 系统用户
*/
public Users selectUsersById(Long id);
/**
* 查询系统用户列表
*
* @param users 系统用户
* @return 系统用户集合
*/
public List<Users> selectUsersList(Users users);
/**
* 新增系统用户
*
* @param users 系统用户
* @return 结果
*/
public int insertUsers(Users users);
/**
* 修改系统用户
*
* @param users 系统用户
* @return 结果
*/
public int updateUsers(Users users);
/**
* 删除系统用户
*
* @param id 系统用户主键
* @return 结果
*/
public int deleteUsersById(Long id);
/**
* 批量删除系统用户
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteUsersByIds(Long[] ids);
}

61
ruoyi-system/src/main/java/com/ruoyi/system/service/IUsersService.java

@ -0,0 +1,61 @@
package com.ruoyi.system.service;
import java.util.List;
import com.ruoyi.system.domain.Users;
/**
* 系统用户Service接口
*
* @author ruoyi
* @date 2026-01-14
*/
public interface IUsersService
{
/**
* 查询系统用户
*
* @param id 系统用户主键
* @return 系统用户
*/
public Users selectUsersById(Long id);
/**
* 查询系统用户列表
*
* @param users 系统用户
* @return 系统用户集合
*/
public List<Users> selectUsersList(Users users);
/**
* 新增系统用户
*
* @param users 系统用户
* @return 结果
*/
public int insertUsers(Users users);
/**
* 修改系统用户
*
* @param users 系统用户
* @return 结果
*/
public int updateUsers(Users users);
/**
* 批量删除系统用户
*
* @param ids 需要删除的系统用户主键集合
* @return 结果
*/
public int deleteUsersByIds(Long[] ids);
/**
* 删除系统用户信息
*
* @param id 系统用户主键
* @return 结果
*/
public int deleteUsersById(Long id);
}

93
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UsersServiceImpl.java

@ -0,0 +1,93 @@
package com.ruoyi.system.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.UsersMapper;
import com.ruoyi.system.domain.Users;
import com.ruoyi.system.service.IUsersService;
/**
* 系统用户Service业务层处理
*
* @author ruoyi
* @date 2026-01-14
*/
@Service
public class UsersServiceImpl implements IUsersService
{
@Autowired
private UsersMapper usersMapper;
/**
* 查询系统用户
*
* @param id 系统用户主键
* @return 系统用户
*/
@Override
public Users selectUsersById(Long id)
{
return usersMapper.selectUsersById(id);
}
/**
* 查询系统用户列表
*
* @param users 系统用户
* @return 系统用户
*/
@Override
public List<Users> selectUsersList(Users users)
{
return usersMapper.selectUsersList(users);
}
/**
* 新增系统用户
*
* @param users 系统用户
* @return 结果
*/
@Override
public int insertUsers(Users users)
{
return usersMapper.insertUsers(users);
}
/**
* 修改系统用户
*
* @param users 系统用户
* @return 结果
*/
@Override
public int updateUsers(Users users)
{
return usersMapper.updateUsers(users);
}
/**
* 批量删除系统用户
*
* @param ids 需要删除的系统用户主键
* @return 结果
*/
@Override
public int deleteUsersByIds(Long[] ids)
{
return usersMapper.deleteUsersByIds(ids);
}
/**
* 删除系统用户信息
*
* @param id 系统用户主键
* @return 结果
*/
@Override
public int deleteUsersById(Long id)
{
return usersMapper.deleteUsersById(id);
}
}

66
ruoyi-system/src/main/resources/mapper/system/UsersMapper.xml

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.system.mapper.UsersMapper">
<resultMap type="Users" id="UsersResult">
<result property="id" column="id" />
<result property="username" column="username" />
<result property="password" column="password" />
<result property="role" column="role" />
</resultMap>
<sql id="selectUsersVo">
select id, username, password, role from users
</sql>
<select id="selectUsersList" parameterType="Users" resultMap="UsersResult">
<include refid="selectUsersVo"/>
<where>
<if test="username != null and username != ''"> and username like concat('%', #{username}, '%')</if>
<if test="password != null and password != ''"> and password = #{password}</if>
<if test="role != null "> and role = #{role}</if>
</where>
</select>
<select id="selectUsersById" parameterType="Long" resultMap="UsersResult">
<include refid="selectUsersVo"/>
where id = #{id}
</select>
<insert id="insertUsers" parameterType="Users" useGeneratedKeys="true" keyProperty="id">
insert into users
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="username != null and username != ''">username,</if>
<if test="password != null and password != ''">password,</if>
<if test="role != null">role,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="username != null and username != ''">#{username},</if>
<if test="password != null and password != ''">#{password},</if>
<if test="role != null">#{role},</if>
</trim>
</insert>
<update id="updateUsers" parameterType="Users">
update users
<trim prefix="SET" suffixOverrides=",">
<if test="username != null and username != ''">username = #{username},</if>
<if test="password != null and password != ''">password = #{password},</if>
<if test="role != null">role = #{role},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteUsersById" parameterType="Long">
delete from users where id = #{id}
</delete>
<delete id="deleteUsersByIds" parameterType="String">
delete from users where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

BIN
ruoyi-ui/node_modules.zip

Binary file not shown.

139
ruoyi-ui/src/views/childRoom/LeftMenu.vue

@ -1,139 +0,0 @@
<template>
<div
class="floating-left-menu"
:class="{ 'hidden': isHidden }"
@mouseenter="showTooltip = true"
@mouseleave="showTooltip = false"
>
<!-- 隐藏按钮>箭头 -->
<div class="hide-btn" @click="handleHide" title="隐藏菜单">
<i class="el-icon-arrow-left"></i>
</div>
<!-- 一级菜单 -->
<div class="menu-icons">
<div
v-for="item in menuItems"
:key="item.id"
class="menu-item"
:class="{ active: activeMenu === item.id }"
@click="handleSelectMenu(item)"
:title="item.name"
>
<i :class="item.icon"></i>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'LeftMenu',
props: {
isHidden: {
type: Boolean,
default: false
},
menuItems: {
type: Array,
default: () => []
},
activeMenu: {
type: String,
default: ''
}
},
methods: {
handleHide() {
this.$emit('hide')
},
handleSelectMenu(item) {
this.$emit('select', item)
}
}
}
</script>
<style scoped>
/* 左侧菜单栏 - 蓝色主题 。*/
.floating-left-menu {
position: absolute;
top: 70px;
left: 20px;
width: 40px;
background: rgba(255, 255, 255, 0.3);
backdrop-filter: blur(10px);
border: 1px solid rgba(0, 138, 255, 0.1);
border-radius: 8px;
z-index: 90;
box-shadow: 0 4px 12px rgba(0, 138, 255, 0.2);
padding: 15px 5px;
transition: all 0.3s ease;
overflow: hidden;
opacity: 1;
transform: translateX(0);
}
.floating-left-menu.hidden {
opacity: 0;
transform: translateX(-100%);
pointer-events: none;
}
.hide-btn {
position: absolute;
top: 15px;
left: 50%;
transform: translateX(-50%);
width: 24px;
height: 24px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
color: #008aff;
font-size: 16px;
transition: all 0.3s;
background: rgba(255, 255, 255, 0.5);
border-radius: 4px;
z-index: 10;
}
.menu-icons {
display: flex;
flex-direction: column;
gap: 10px;
margin-top: 30px;
}
.menu-item {
display: flex;
justify-content: center;
align-items: center;
height: 40px;
cursor: pointer;
color: #555;
font-size: 20px;
position: relative;
transition: all 0.3s;
border-radius: 4px;
padding: 0 5px;
background: rgba(255, 255, 255, 0.8);
backdrop-filter: blur(5px);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.menu-item:hover {
background: rgba(0, 138, 255, 0.1);
color: #008aff;
transform: translateY(-2px);
box-shadow: 0 4px 10px rgba(0, 138, 255, 0.2);
}
.menu-item.active {
background: rgba(0, 138, 255, 0.15);
color: #008aff;
box-shadow: 0 2px 8px rgba(0, 138, 255, 0.3);
}
</style>

723
ruoyi-ui/src/views/childRoom/RightPanel.vue

@ -1,723 +0,0 @@
<template>
<div>
<!-- 右侧外部隐藏按钮 -->
<div
class="right-external-hide-btn"
:class="{ hidden: isHidden }"
@click="handleHide"
title="隐藏右侧面板"
>
<i class="el-icon-arrow-right"></i>
</div>
<!-- 右侧实体列表浮动- 蓝色主题 -->
<div
class="floating-right-panel blue-theme"
:class="{ 'hidden': isHidden }"
>
<!-- 方案内容 -->
<div v-if="activeTab === 'plan'" class="tab-content plan-content">
<div class="section">
<div class="section-title">航线列表</div>
<div class="route-list">
<div
v-for="route in routes"
:key="route.id"
class="route-item"
:class="{ selected: selectedRouteId === route.id }"
@click="handleSelectRoute(route)"
>
<i class="el-icon-map-location"></i>
<div class="route-info">
<div class="route-name">{{ route.name }}</div>
<div class="route-meta">{{ route.points }}个航点</div>
</div>
<el-tag
v-if="route.conflict"
size="mini"
type="danger"
class="conflict-tag"
>
冲突
</el-tag>
<div class="route-actions">
<i class="el-icon-edit" title="编辑" @click.stop="handleOpenRouteDialog(route)"></i>
</div>
</div>
</div>
</div>
<div v-if="selectedRouteDetails" class="section">
<div class="section-title">航点列表</div>
<div class="waypoint-list">
<div
v-for="point in selectedRouteDetails.waypoints"
:key="point.name"
class="waypoint-item"
@click="handleOpenWaypointDialog(point)"
>
<i class="el-icon-location"></i>
<div class="waypoint-info">
<div class="waypoint-name">{{ point.name }}</div>
<div class="waypoint-meta">高度: {{ point.altitude }}m | 速度: {{ point.speed }}</div>
</div>
<div class="waypoint-actions">
<i class="el-icon-edit" title="编辑" @click.stop="handleOpenWaypointDialog(point)"></i>
<i class="el-icon-delete" title="删除"></i>
</div>
</div>
</div>
</div>
<div class="action-buttons">
<el-button type="primary" size="mini" icon="el-icon-circle-plus" class="blue-btn" @click="handleAddWaypoint">
添加航点
</el-button>
<el-button size="mini" class="blue-btn" @click="handleCancelRoute">
取消
</el-button>
</div>
</div>
<!-- 冲突内容 -->
<div v-if="activeTab === 'conflict'" class="tab-content conflict-content">
<div v-if="conflicts.length > 0" class="conflict-list">
<div
v-for="conflict in conflicts"
:key="conflict.id"
class="conflict-item"
>
<div class="conflict-header">
<i class="el-icon-warning" style="color: #f56c6c;"></i>
<span class="conflict-title">{{ conflict.title }}</span>
<el-tag size="mini" type="danger">严重</el-tag>
</div>
<div class="conflict-details">
<div class="detail-item">
<span class="label">涉及航线</span>
<span class="value">{{ conflict.routes.join('、') }}</span>
</div>
<div class="detail-item">
<span class="label">冲突时间</span>
<span class="value">{{ conflict.time }}</span>
</div>
<div class="detail-item">
<span class="label">冲突位置</span>
<span class="value">{{ conflict.position }}</span>
</div>
</div>
<div class="conflict-actions">
<el-button type="text" size="mini" class="blue-text-btn" @click="handleViewConflict(conflict)">
查看详情
</el-button>
<el-button type="text" size="mini" class="blue-text-btn" @click="handleResolveConflict(conflict)">
解决冲突
</el-button>
</div>
</div>
</div>
<div v-else class="no-conflict">
<i class="el-icon-success" style="color: #67c23a; font-size: 24px;"></i>
<p>暂无冲突</p>
<el-button size="mini" class="blue-btn" @click="handleRunConflictCheck">
重新检测
</el-button>
</div>
</div>
<!-- 平台内容 -->
<div v-if="activeTab === 'platform'" class="tab-content platform-content">
<div class="platform-categories">
<el-tabs v-model="activePlatformTab" type="card" size="mini" class="blue-tabs">
<el-tab-pane label="空中" name="air">
<div class="platform-list">
<div
v-for="platform in airPlatforms"
:key="platform.id"
class="platform-item"
@click="handleOpenPlatformDialog(platform)"
>
<div class="platform-icon" :style="{ color: platform.color }">
<i :class="platform.icon"></i>
</div>
<div class="platform-info">
<div class="platform-name">{{ platform.name }}</div>
<div class="platform-type">{{ platform.type }}</div>
</div>
<div class="platform-status">
<span class="status-dot" :class="platform.status"></span>
</div>
</div>
</div>
</el-tab-pane>
<el-tab-pane label="海上" name="sea">
<div class="platform-list">
<div
v-for="platform in seaPlatforms"
:key="platform.id"
class="platform-item"
@click="handleOpenPlatformDialog(platform)"
>
<div class="platform-icon" :style="{ color: platform.color }">
<i :class="platform.icon"></i>
</div>
<div class="platform-info">
<div class="platform-name">{{ platform.name }}</div>
<div class="platform-type">{{ platform.type }}</div>
</div>
<div class="platform-status">
<span class="status-dot" :class="platform.status"></span>
</div>
</div>
</div>
</el-tab-pane>
<el-tab-pane label="地面" name="ground">
<div class="platform-list">
<div
v-for="platform in groundPlatforms"
:key="platform.id"
class="platform-item"
@click="handleOpenPlatformDialog(platform)"
>
<div class="platform-icon" :style="{ color: platform.color }">
<i :class="platform.icon"></i>
</div>
<div class="platform-info">
<div class="platform-name">{{ platform.name }}</div>
<div class="platform-type">{{ platform.type }}</div>
</div>
<div class="platform-status">
<span class="status-dot" :class="platform.status"></span>
</div>
</div>
</div>
</el-tab-pane>
</el-tabs>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'RightPanel',
props: {
isHidden: {
type: Boolean,
default: false
},
activeTab: {
type: String,
default: 'plan'
},
routes: {
type: Array,
default: () => []
},
selectedRouteId: {
type: [String, Number],
default: null
},
selectedRouteDetails: {
type: Object,
default: null
},
conflicts: {
type: Array,
default: () => []
},
conflictCount: {
type: Number,
default: 0
},
airPlatforms: {
type: Array,
default: () => []
},
seaPlatforms: {
type: Array,
default: () => []
},
groundPlatforms: {
type: Array,
default: () => []
}
},
data() {
return {
activePlatformTab: 'air'
}
},
methods: {
handleHide() {
this.$emit('hide')
},
handleSelectRoute(route) {
this.$emit('select-route', route)
},
handleOpenRouteDialog(route) {
this.$emit('open-route-dialog', route)
},
handleOpenWaypointDialog(point) {
this.$emit('open-waypoint-dialog', point)
},
handleAddWaypoint() {
this.$emit('add-waypoint')
},
handleCancelRoute() {
this.$emit('cancel-route')
},
handleViewConflict(conflict) {
this.$emit('view-conflict', conflict)
},
handleResolveConflict(conflict) {
this.$emit('resolve-conflict', conflict)
},
handleRunConflictCheck() {
this.$emit('run-conflict-check')
},
handleOpenPlatformDialog(platform) {
this.$emit('open-platform-dialog', platform)
}
}
}
</script>
<style scoped>
/* 右侧外部隐藏按钮 */
.right-external-hide-btn {
position: absolute;
top: 80px;
right: 20px;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
color: #008aff;
font-size: 18px;
background: rgba(255, 255, 255, 0.5);
border-radius: 50%;
z-index: 85;
box-shadow: 0 2px 8px rgba(0, 138, 255, 0.3);
transition: all 0.3s;
backdrop-filter: blur(5px);
}
.right-external-hide-btn:hover {
color: #0066cc;
background: rgba(0, 138, 255, 0.2);
transform: scale(1.1);
}
.right-external-hide-btn.hidden {
opacity: 0;
transform: translateX(100%);
pointer-events: none;
}
/* 右侧浮动面板 - 蓝色主题 */
.floating-right-panel {
position: absolute;
top: 70px;
right: 20px;
width: 300px;
border-radius: 0 8px 8px 8px;
z-index: 90;
color: #333;
overflow: hidden;
box-shadow: 0 4px 20px rgba(0, 138, 255, 0.2);
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(15px);
transition: all 0.3s ease;
opacity: 1;
transform: translateX(0);
}
.floating-right-panel.hidden {
opacity: 0;
transform: translateX(100%);
pointer-events: none;
}
.tab-content {
padding: 15px;
max-height: 500px;
overflow-y: auto;
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
}
.section {
margin-bottom: 20px;
}
.section-title {
font-size: 14px;
font-weight: 600;
color: #008aff;
margin-bottom: 10px;
padding-bottom: 8px;
border-bottom: 2px solid rgba(0, 138, 255, 0.2);
}
.route-list {
display: flex;
flex-direction: column;
gap: 8px;
}
.route-item {
display: flex;
align-items: center;
gap: 10px;
padding: 10px;
background: rgba(255, 255, 255, 0.8);
border-radius: 6px;
cursor: pointer;
transition: all 0.3s;
border: 1px solid rgba(0, 138, 255, 0.1);
position: relative;
}
.route-item:hover {
background: rgba(0, 138, 255, 0.1);
transform: translateX(-2px);
box-shadow: 0 2px 8px rgba(0, 138, 255, 0.15);
}
.route-item.selected {
background: rgba(0, 138, 255, 0.15);
border-color: rgba(0, 138, 255, 0.3);
box-shadow: 0 2px 10px rgba(0, 138, 255, 0.25);
}
.route-info {
flex: 1;
}
.route-name {
font-size: 14px;
font-weight: 500;
color: #333;
}
.route-meta {
font-size: 12px;
color: #999;
}
.route-actions {
display: flex;
gap: 8px;
}
.route-actions i {
cursor: pointer;
color: #008aff;
font-size: 14px;
padding: 4px;
border-radius: 4px;
transition: all 0.2s;
}
.route-actions i:hover {
background: rgba(0, 138, 255, 0.1);
transform: scale(1.2);
}
.waypoint-list {
display: flex;
flex-direction: column;
gap: 8px;
}
.waypoint-item {
display: flex;
align-items: center;
gap: 10px;
padding: 10px;
background: rgba(255, 255, 255, 0.8);
border-radius: 6px;
cursor: pointer;
transition: all 0.3s;
border: 1px solid rgba(0, 138, 255, 0.1);
}
.waypoint-item:hover {
background: rgba(0, 138, 255, 0.1);
transform: translateX(-2px);
box-shadow: 0 2px 8px rgba(0, 138, 255, 0.15);
}
.waypoint-info {
flex: 1;
}
.waypoint-name {
font-size: 14px;
font-weight: 500;
color: #333;
}
.waypoint-meta {
font-size: 12px;
color: #999;
}
.waypoint-actions {
display: flex;
gap: 8px;
}
.waypoint-actions i {
cursor: pointer;
color: #008aff;
font-size: 14px;
padding: 4px;
border-radius: 4px;
transition: all 0.2s;
}
.waypoint-actions i:hover {
background: rgba(0, 138, 255, 0.1);
transform: scale(1.2);
}
.action-buttons {
display: flex;
gap: 10px;
padding: 10px 0;
}
.conflict-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.conflict-item {
background: rgba(255, 255, 255, 0.8);
border-radius: 6px;
padding: 12px;
border: 1px solid rgba(245, 108, 108, 0.2);
transition: all 0.3s;
}
.conflict-item:hover {
background: rgba(245, 108, 108, 0.1);
box-shadow: 0 2px 8px rgba(245, 108, 108, 0.15);
}
.conflict-header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 10px;
}
.conflict-title {
flex: 1;
font-weight: 600;
color: #f56c6c;
}
.conflict-details {
display: flex;
flex-direction: column;
gap: 8px;
margin-bottom: 10px;
}
.detail-item {
display: flex;
gap: 8px;
font-size: 13px;
}
.detail-item .label {
color: #999;
min-width: 70px;
}
.detail-item .value {
color: #333;
font-weight: 500;
}
.conflict-actions {
display: flex;
gap: 10px;
}
.no-conflict {
display: flex;
flex-direction: column;
align-items: center;
gap: 15px;
padding: 40px 20px;
color: #999;
}
.platform-categories {
height: 100%;
}
.platform-list {
display: flex;
flex-direction: column;
gap: 10px;
max-height: 450px;
overflow-y: auto;
}
.platform-item {
display: flex;
align-items: center;
gap: 12px;
padding: 12px;
background: rgba(255, 255, 255, 0.8);
border-radius: 6px;
cursor: pointer;
transition: all 0.3s;
border: 1px solid rgba(0, 138, 255, 0.1);
}
.platform-item:hover {
background: rgba(0, 138, 255, 0.1);
transform: translateX(-2px);
box-shadow: 0 2px 8px rgba(0, 138, 255, 0.15);
}
.platform-icon {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
background: rgba(255, 255, 255, 0.9);
border-radius: 50%;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
}
.platform-info {
flex: 1;
}
.platform-name {
font-size: 14px;
font-weight: 500;
color: #333;
}
.platform-type {
font-size: 12px;
color: #999;
}
.platform-status {
display: flex;
align-items: center;
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
display: inline-block;
}
.status-dot.online {
background: #67c23a;
box-shadow: 0 0 6px rgba(103, 194, 58, 0.6);
}
.status-dot.offline {
background: #999;
}
.status-dot.operating {
background: #008aff;
animation: pulse 2s infinite;
box-shadow: 0 0 10px rgba(0, 138, 255, 0.8);
}
@keyframes pulse {
0%, 100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
.blue-btn {
background: rgba(0, 138, 255, 0.1);
color: #008aff;
border: 1px solid rgba(0, 138, 255, 0.3);
}
.blue-btn:hover {
background: rgba(0, 138, 255, 0.2);
border-color: rgba(0, 138, 255, 0.5);
}
.blue-text-btn {
color: #008aff;
}
.blue-text-btn:hover {
color: #0066cc;
}
.blue-badge {
background: rgba(245, 108, 108, 0.1);
color: #f56c6c;
border: 1px solid rgba(245, 108, 108, 0.3);
}
.blue-tabs >>> .el-tabs__item {
color: #666;
transition: all 0.3s;
}
.blue-tabs >>> .el-tabs__item:hover {
color: #008aff;
}
.blue-tabs >>> .el-tabs__item.is-active {
color: #008aff;
font-weight: 600;
}
.blue-tabs >>> .el-tabs__active-bar {
background-color: #008aff;
box-shadow: 0 0 6px rgba(0, 138, 255, 0.5);
}
.blue-tabs >>> .el-tabs__nav-wrap::after {
background-color: rgba(0, 138, 255, 0.3);
}
.blue-success {
color: #67c23a;
}
.blue-warning {
color: #e6a23c;
}
</style>

2
ruoyi-ui/vue.config.js

@ -10,7 +10,7 @@ const CompressionPlugin = require('compression-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const name = process.env.VUE_APP_TITLE || '若依管理系统' // 网页标题
const baseUrl = 'http://127.0.0.1:8080' // 后端接口
const baseUrl = 'http://192.168.50.30:8080' // 后端接口
const port = process.env.port || process.env.npm_config_port || 80 // 端口
// 定义 Cesium 源码路径

Loading…
Cancel
Save