工区管理

dev_xd
lj7788 2025-12-26 17:55:14 +08:00
parent b987300ae9
commit c663cced1b
28 changed files with 7791 additions and 115 deletions

File diff suppressed because one or more lines are too long

View File

@ -21,7 +21,7 @@ spring:
# 配置中心地址 # 配置中心地址
server-addr: @discovery.server-addr@ server-addr: @discovery.server-addr@
# 工作空间配置 # 工作空间配置
# namespace: a113aa27-4d61-46e0-81d6-9cede0457f0d namespace: a113aa27-4d61-46e0-81d6-9cede0457f0d
# 配置文件格式 # 配置文件格式
file-extension: yml file-extension: yml
# 共享配置 # 共享配置

View File

@ -65,6 +65,10 @@ public class ProVideoMonitor extends BaseEntity
@Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()") @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
private Long isDel; private Long isDel;
/** 工区ID */
@Excel(name = "工区ID")
private Long workAreaId;
/** $column.columnComment */ /** $column.columnComment */
@Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()") @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
private Date upadteTime; private Date upadteTime;
@ -72,6 +76,10 @@ public class ProVideoMonitor extends BaseEntity
private String projectName; private String projectName;
private String workAreaName;
private String workAreaAncestors;
public String getCompName() { public String getCompName() {
return compName; return compName;
} }
@ -196,6 +204,33 @@ public class ProVideoMonitor extends BaseEntity
{ {
return isDel; return isDel;
} }
public void setWorkAreaId(Long workAreaId)
{
this.workAreaId = workAreaId;
}
public Long getWorkAreaId()
{
return workAreaId;
}
public void setWorkAreaName(String workAreaName) {
this.workAreaName = workAreaName;
}
public String getWorkAreaName() {
return workAreaName;
}
public void setWorkAreaAncestors(String workAreaAncestors) {
this.workAreaAncestors = workAreaAncestors;
}
public String getWorkAreaAncestors() {
return workAreaAncestors;
}
public void setUpadteTime(Date upadteTime) public void setUpadteTime(Date upadteTime)
{ {
this.upadteTime = upadteTime; this.upadteTime = upadteTime;
@ -222,6 +257,9 @@ public class ProVideoMonitor extends BaseEntity
.append("remark", getRemark()) .append("remark", getRemark())
.append("state", getState()) .append("state", getState())
.append("isDel", getIsDel()) .append("isDel", getIsDel())
.append("workAreaId", getWorkAreaId())
.append("workAreaName", getWorkAreaName())
.append("workAreaAncestors", getWorkAreaAncestors())
.append("createBy", getCreateBy()) .append("createBy", getCreateBy())
.append("createTime", getCreateTime()) .append("createTime", getCreateTime())
.append("updateBy", getUpdateBy()) .append("updateBy", getUpdateBy())

View File

@ -0,0 +1,182 @@
package com.yanzhu.system.domain;
import com.yanzhu.common.core.annotation.Excel;
import com.yanzhu.common.core.web.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import java.util.ArrayList;
import java.util.List;
/**
* sys_work_area
*
* @author yanzhu
* @date 2025-12-25
*/
public class SysWorkArea extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** $column.columnComment */
private Long id;
/** 公司主键 */
@Excel(name = "公司主键")
private Long comId;
/** 项目ID */
@Excel(name = "项目ID")
private Long projectId;
/** 父ID */
@Excel(name = "父ID")
private Long parentId;
/** 祖级列表 */
@Excel(name = "祖级列表")
private String ancestors;
/** 工区名称 */
@Excel(name = "工区名称")
private String title;
/** 防护等级 */
@Excel(name = "防护等级")
private String level;
/** 排序 */
@Excel(name = "排序")
private Long orderNum;
/** 状态 */
@Excel(name = "状态")
private Long state;
/** 删除标志0代表存在 1代表删除 */
private String delFlag;
/** 子工区 */
private List<SysWorkArea> children = new ArrayList<>();
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setComId(Long comId)
{
this.comId = comId;
}
public Long getComId()
{
return comId;
}
public void setProjectId(Long projectId)
{
this.projectId = projectId;
}
public Long getProjectId()
{
return projectId;
}
public void setParentId(Long parentId)
{
this.parentId = parentId;
}
public Long getParentId()
{
return parentId;
}
public void setAncestors(String ancestors)
{
this.ancestors = ancestors;
}
public String getAncestors()
{
return ancestors;
}
public void setTitle(String title)
{
this.title = title;
}
public String getTitle()
{
return title;
}
public void setLevel(String level)
{
this.level = level;
}
public String getLevel()
{
return level;
}
public void setOrderNum(Long orderNum)
{
this.orderNum = orderNum;
}
public Long getOrderNum()
{
return orderNum;
}
public void setState(Long state)
{
this.state = state;
}
public Long getState()
{
return state;
}
public void setDelFlag(String delFlag)
{
this.delFlag = delFlag;
}
public String getDelFlag()
{
return delFlag;
}
public List<SysWorkArea> getChildren() {
return children;
}
public void setChildren(List<SysWorkArea> children) {
this.children = children != null ? children : new ArrayList<>();
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("comId", getComId())
.append("projectId", getProjectId())
.append("parentId", getParentId())
.append("ancestors", getAncestors())
.append("title", getTitle())
.append("level", getLevel())
.append("orderNum", getOrderNum())
.append("state", getState())
.append("remark", getRemark())
.append("delFlag", getDelFlag())
.append("children", getChildren())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.toString();
}
}

View File

@ -7,6 +7,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import com.yanzhu.system.api.domain.SysDept; import com.yanzhu.system.api.domain.SysDept;
import com.yanzhu.system.domain.SysArea; import com.yanzhu.system.domain.SysArea;
import com.yanzhu.system.domain.SysMenu; import com.yanzhu.system.domain.SysMenu;
import com.yanzhu.system.domain.SysWorkArea;
/** /**
* Treeselect * Treeselect
@ -66,6 +67,14 @@ public class TreeSelect implements Serializable
this.data=area; this.data=area;
} }
public TreeSelect(SysWorkArea workArea)
{
this.id = workArea.getId();
this.label = workArea.getTitle();
this.children = workArea.getChildren() != null ? workArea.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList()) : null;
this.data=workArea;
}
public Long getId() public Long getId()
{ {
return id; return id;

View File

@ -0,0 +1,95 @@
package com.yanzhu.system.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.yanzhu.system.domain.SysWorkArea;
/**
*
*
* @author yanzhu
*/
public interface SysWorkAreaMapper
{
/**
*
*
* @param id
* @return
*/
public SysWorkArea selectSysWorkAreaById(Long id);
/**
*
*
* @param sysWorkArea
* @return
*/
public List<SysWorkArea> selectSysWorkAreaList(SysWorkArea sysWorkArea);
/**
*
*
* @param sysWorkArea
* @return
*/
public int insertSysWorkArea(SysWorkArea sysWorkArea);
/**
*
*
* @param sysWorkArea
* @return
*/
public int updateSysWorkArea(SysWorkArea sysWorkArea);
/**
*
*
* @param id
* @return
*/
public int deleteSysWorkAreaById(Long id);
/**
*
*
* @param ids
* @return
*/
public int deleteSysWorkAreaByIds(Long[] ids);
/**
* ID
*
* @param id ID
* @return
*/
public List<SysWorkArea> selectChildrenWorkAreaById(Long id);
/**
*
*
* @param workAreas
* @return
*/
public int updateWorkAreaChildren(@Param("workAreas") List<SysWorkArea> workAreas);
/**
*
*
* @param workAreaId ID
* @param state
* @return
*/
public int updateSubWorkAreaStateByAncestors(@Param("workAreaId") Long workAreaId, @Param("state") Long state);
/**
* ID
*
* @param comId ID
* @return
*/
public List<SysWorkArea> selectSysWorkAreaListByComId(@Param("comId") Long comId);
}

View File

@ -18,21 +18,25 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="remark" column="remark" /> <result property="remark" column="remark" />
<result property="state" column="state" /> <result property="state" column="state" />
<result property="isDel" column="is_del" /> <result property="isDel" column="is_del" />
<result property="workAreaId" column="work_area_id" />
<result property="createBy" column="create_by" /> <result property="createBy" column="create_by" />
<result property="createTime" column="create_time" /> <result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" /> <result property="updateBy" column="update_by" />
<result property="upadteTime" column="upadte_time" /> <result property="upadteTime" column="upadte_time" />
<result property="compName" column="comp_name"/> <result property="compName" column="comp_name"/>
<result property="projectName" column="project_name"/> <result property="projectName" column="project_name"/>
<result property="workAreaName" column="work_area_name"/>
<result property="workAreaAncestors" column="work_area_ancestors"/>
</resultMap> </resultMap>
<sql id="selectProVideoMonitorVo"> <sql id="selectProVideoMonitorVo">
select pv.id, pv.com_id, pv.project_id, pv.monitor_name, pv.monitor_type, pv.url, pv.appkey, pv.secret, select pv.id, pv.com_id, pv.project_id, pv.monitor_name, pv.monitor_type, pv.url, pv.appkey, pv.secret,
pv.manufacturer, pv.key_point, pv.remark, pv.state, pv.is_del, pv.create_by, pv.create_time, pv.manufacturer, pv.key_point, pv.remark, pv.state, pv.is_del, pv.work_area_id, pv.create_by, pv.create_time,
pv.update_by, pv.upadte_time,dp.`dept_name` comp_name,pi.`project_name` pv.update_by, pv.upadte_time,dp.`dept_name` comp_name,pi.`project_name`, wa.`title` work_area_name, wa.ancestors work_area_ancestors
from pro_video_monitor pv from pro_video_monitor pv
LEFT JOIN sys_dept dp ON pv.com_id=dp.dept_id LEFT JOIN sys_dept dp ON pv.com_id=dp.dept_id
LEFT JOIN pro_project_info pi ON pv.project_id=pi.id LEFT JOIN pro_project_info pi ON pv.project_id=pi.id
LEFT JOIN sys_work_area wa ON pv.work_area_id=wa.id
</sql> </sql>
<select id="selectProVideoMonitorList" parameterType="ProVideoMonitor" resultMap="ProVideoMonitorResult"> <select id="selectProVideoMonitorList" parameterType="ProVideoMonitor" resultMap="ProVideoMonitorResult">
@ -40,6 +44,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<where> <where>
<if test="comId != null "> and pv.com_id = #{comId}</if> <if test="comId != null "> and pv.com_id = #{comId}</if>
<if test="projectId != null "> and pv.project_id = #{projectId}</if> <if test="projectId != null "> and pv.project_id = #{projectId}</if>
<if test="workAreaId != null "> and pv.work_area_id = #{workAreaId} </if>
<if test="workAreaAncestors != null "> and (pv.work_area_id = #{workAreaAncestors} or FIND_IN_SET(#{workAreaAncestors}, wa.ancestors) > 0)</if>
<if test="monitorName != null and monitorName != ''"> and pv.monitor_name like concat('%', #{monitorName}, '%')</if> <if test="monitorName != null and monitorName != ''"> and pv.monitor_name like concat('%', #{monitorName}, '%')</if>
<if test="monitorType != null and monitorType != ''"> and pv.monitor_type = #{monitorType}</if> <if test="monitorType != null and monitorType != ''"> and pv.monitor_type = #{monitorType}</if>
<if test="url != null and url != ''"> and pv.url = #{url}</if> <if test="url != null and url != ''"> and pv.url = #{url}</if>
@ -73,6 +79,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="remark != null">remark,</if> <if test="remark != null">remark,</if>
<if test="state != null">state,</if> <if test="state != null">state,</if>
<if test="isDel != null">is_del,</if> <if test="isDel != null">is_del,</if>
<if test="workAreaId != null">work_area_id,</if>
<if test="createBy != null">create_by,</if> <if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if> <if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if> <if test="updateBy != null">update_by,</if>
@ -91,6 +98,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="remark != null">#{remark},</if> <if test="remark != null">#{remark},</if>
<if test="state != null">#{state},</if> <if test="state != null">#{state},</if>
<if test="isDel != null">#{isDel},</if> <if test="isDel != null">#{isDel},</if>
<if test="workAreaId != null">#{workAreaId},</if>
<if test="createBy != null">#{createBy},</if> <if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if> <if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if> <if test="updateBy != null">#{updateBy},</if>
@ -113,6 +121,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="remark != null">remark = #{remark},</if> <if test="remark != null">remark = #{remark},</if>
<if test="state != null">state = #{state},</if> <if test="state != null">state = #{state},</if>
<if test="isDel != null">is_del = #{isDel},</if> <if test="isDel != null">is_del = #{isDel},</if>
<if test="workAreaId != null">work_area_id = #{workAreaId},</if>
<if test="createBy != null">create_by = #{createBy},</if> <if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if> <if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if> <if test="updateBy != null">update_by = #{updateBy},</if>

View File

@ -0,0 +1,144 @@
<?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.yanzhu.system.mapper.SysWorkAreaMapper">
<resultMap type="SysWorkArea" id="SysWorkAreaResult">
<result property="id" column="id" />
<result property="comId" column="com_id" />
<result property="projectId" column="project_id" />
<result property="parentId" column="parent_id" />
<result property="ancestors" column="ancestors" />
<result property="title" column="title" />
<result property="level" column="level" />
<result property="orderNum" column="order_num" />
<result property="state" column="state" />
<result property="remark" column="remark" />
<result property="delFlag" column="del_flag" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
</resultMap>
<sql id="selectSysWorkAreaVo">
select id, com_id, project_id, parent_id, ancestors, title, level, order_num, state, remark, del_flag, create_by, create_time, update_by, update_time from sys_work_area
</sql>
<select id="selectSysWorkAreaList" parameterType="SysWorkArea" resultMap="SysWorkAreaResult">
<include refid="selectSysWorkAreaVo"/>
<where>
<if test="comId != null "> and com_id = #{comId}</if>
<if test="projectId != null "> and project_id = #{projectId}</if>
<if test="parentId != null "> and parent_id = #{parentId}</if>
<if test="ancestors != null and ancestors != ''"> and FIND_IN_SET(#{ancestors}, ancestors) > 0</if>
<if test="title != null and title != ''"> and title = #{title}</if>
<if test="level != null and level != ''"> and level = #{level}</if>
<if test="orderNum != null "> and order_num = #{orderNum}</if>
<if test="state != null "> and state = #{state}</if>
and del_flag = '0'
</where>
</select>
<select id="selectSysWorkAreaById" parameterType="Long" resultMap="SysWorkAreaResult">
<include refid="selectSysWorkAreaVo"/>
where id = #{id} and del_flag = '0'
</select>
<insert id="insertSysWorkArea" parameterType="SysWorkArea">
insert into sys_work_area
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="comId != null">com_id,</if>
<if test="projectId != null">project_id,</if>
<if test="parentId != null">parent_id,</if>
<if test="ancestors != null">ancestors,</if>
<if test="title != null">title,</if>
<if test="level != null">level,</if>
<if test="orderNum != null">order_num,</if>
<if test="state != null">state,</if>
<if test="remark != null">remark,</if>
del_flag,
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="comId != null">#{comId},</if>
<if test="projectId != null">#{projectId},</if>
<if test="parentId != null">#{parentId},</if>
<if test="ancestors != null">#{ancestors},</if>
<if test="title != null">#{title},</if>
<if test="level != null">#{level},</if>
<if test="orderNum != null">#{orderNum},</if>
<if test="state != null">#{state},</if>
<if test="remark != null">#{remark},</if>
'0',
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
</trim>
<selectKey keyProperty="id" resultType="long" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
</insert>
<update id="updateSysWorkArea" parameterType="SysWorkArea">
update sys_work_area
<trim prefix="SET" suffixOverrides=",">
<if test="comId != null">com_id = #{comId},</if>
<if test="projectId != null">project_id = #{projectId},</if>
<if test="parentId != null">parent_id = #{parentId},</if>
<if test="ancestors != null">ancestors = #{ancestors},</if>
<if test="title != null">title = #{title},</if>
<if test="level != null">level = #{level},</if>
<if test="orderNum != null">order_num = #{orderNum},</if>
<if test="state != null">state = #{state},</if>
<if test="remark != null">remark = #{remark},</if>
<if test="delFlag != null">del_flag = #{delFlag},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
</trim>
where id = #{id}
</update>
<update id="deleteSysWorkAreaById" parameterType="Long">
update sys_work_area set del_flag = '1' where id = #{id}
</update>
<update id="deleteSysWorkAreaByIds" parameterType="String">
update sys_work_area set del_flag = '1' where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</update>
<select id="selectChildrenWorkAreaById" parameterType="long" resultMap="SysWorkAreaResult">
<include refid="selectSysWorkAreaVo"/>
WHERE parent_id = #{id} and del_flag = '0'
</select>
<update id="updateWorkAreaChildren" parameterType="java.util.List">
<foreach collection="workAreas" item="item" separator=";">
UPDATE sys_work_area SET ancestors = #{item.ancestors}
WHERE id = #{item.id}
</foreach>
</update>
<update id="updateSubWorkAreaStateByAncestors" parameterType="map">
UPDATE sys_work_area
SET state = #{state}
WHERE FIND_IN_SET(#{workAreaId}, ancestors) > 0
AND del_flag = '0'
</update>
<select id="selectSysWorkAreaListByComId" parameterType="long" resultMap="SysWorkAreaResult">
<include refid="selectSysWorkAreaVo"/>
WHERE com_id = #{comId} and del_flag = '0'
ORDER BY parent_id, order_num
</select>
</mapper>

View File

@ -20,6 +20,8 @@ spring:
config: config:
# 配置中心地址 # 配置中心地址
server-addr: @discovery.server-addr@ server-addr: @discovery.server-addr@
# 工作空间配置
namespace: a113aa27-4d61-46e0-81d6-9cede0457f0d
# 配置文件格式 # 配置文件格式
file-extension: yml file-extension: yml
# 共享配置 # 共享配置

View File

@ -17,9 +17,12 @@ spring:
server-addr: @discovery.server-addr@ server-addr: @discovery.server-addr@
# 服务分组 # 服务分组
# group: lijun # group: lijun
config: config:
# 配置中心地址 # 配置中心地址
server-addr: @discovery.server-addr@ server-addr: @discovery.server-addr@
# 工作空间配置
namespace: a113aa27-4d61-46e0-81d6-9cede0457f0d
# 配置文件格式 # 配置文件格式
file-extension: yml file-extension: yml
# 共享配置 # 共享配置

View File

@ -16,10 +16,13 @@ spring:
# 服务注册地址 # 服务注册地址
server-addr: @discovery.server-addr@ server-addr: @discovery.server-addr@
# 服务分组 # 服务分组
group: JiangYuQi #group: JiangYuQi
config: config:
# 配置中心地址 # 配置中心地址
server-addr: @discovery.server-addr@ server-addr: @discovery.server-addr@
# 工作空间配置
namespace: a113aa27-4d61-46e0-81d6-9cede0457f0d
# 配置文件格式 # 配置文件格式
file-extension: yml file-extension: yml
# 共享配置 # 共享配置

View File

@ -20,13 +20,13 @@ spring:
discovery: discovery:
# 服务注册地址 # 服务注册地址
server-addr: @discovery.server-addr@ server-addr: @discovery.server-addr@
# 工作空间配置
# namespace: a113aa27-4d61-46e0-81d6-9cede0457f0d
# 服务分组 # 服务分组
group: JiangYuQi #group: JiangYuQi
config: config:
# 配置中心地址 # 配置中心地址
server-addr: @discovery.server-addr@ server-addr: @discovery.server-addr@
# 工作空间配置
namespace: a113aa27-4d61-46e0-81d6-9cede0457f0d
# 配置文件格式 # 配置文件格式
file-extension: yml file-extension: yml
# 共享配置 # 共享配置

View File

@ -0,0 +1,142 @@
package com.yanzhu.system.controller;
import java.util.List;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import com.yanzhu.common.core.utils.poi.ExcelUtil;
import com.yanzhu.common.core.web.controller.BaseController;
import com.yanzhu.common.core.web.domain.AjaxResult;
import com.yanzhu.common.core.web.page.TableDataInfo;
import com.yanzhu.common.log.annotation.Log;
import com.yanzhu.common.log.enums.BusinessType;
import com.yanzhu.common.security.annotation.RequiresPermissions;
import com.yanzhu.common.security.utils.SecurityUtils;
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.yanzhu.system.domain.SysWorkArea;
import com.yanzhu.system.service.ISysWorkAreaService;
import com.yanzhu.system.domain.vo.TreeSelect;
/**
* Controller
*
* @author yanzhu
* @date 2025-12-25
*/
@RestController
@RequestMapping("/workAarea")
public class SysWorkAreaController extends BaseController
{
@Autowired
private ISysWorkAreaService sysWorkAreaService;
/**
*
*/
@RequiresPermissions("system:workAarea:list")
@GetMapping("/list")
public TableDataInfo list(SysWorkArea sysWorkArea)
{
startPage();
List<SysWorkArea> list = sysWorkAreaService.selectSysWorkAreaList(sysWorkArea);
return getDataTable(list);
}
/**
*
*/
@RequiresPermissions("system:workAarea:export")
@Log(title = "工区管理", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, SysWorkArea sysWorkArea)
{
List<SysWorkArea> list = sysWorkAreaService.selectSysWorkAreaList(sysWorkArea);
ExcelUtil<SysWorkArea> util = new ExcelUtil<SysWorkArea>(SysWorkArea.class);
util.exportExcel(response, list, "工区管理数据");
}
/**
*
*/
@RequiresPermissions("system:workAarea:query")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(sysWorkAreaService.selectSysWorkAreaById(id));
}
/**
*
*/
@RequiresPermissions("system:workAarea:add")
@Log(title = "工区管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SysWorkArea sysWorkArea)
{
return toAjax(sysWorkAreaService.insertSysWorkArea(sysWorkArea));
}
/**
*
*/
@RequiresPermissions("system:workAarea:edit")
@Log(title = "工区管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody SysWorkArea sysWorkArea)
{
return toAjax(sysWorkAreaService.updateSysWorkArea(sysWorkArea));
}
/**
*
*/
@RequiresPermissions("system:workAarea:remove")
@Log(title = "工区管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(sysWorkAreaService.deleteSysWorkAreaByIds(ids));
}
/**
*
*/
@RequiresPermissions("system:workAarea:list")
@GetMapping("/workAreaTree")
public AjaxResult workAreaTree(Long projectId){
// 创建查询条件对象
SysWorkArea query = new SysWorkArea();
// 获取当前用户的公司ID
Long comId = SecurityUtils.getLoginUser().getSysUser().getComId();
query.setComId(comId);
// 如果传入了项目ID则设置项目ID查询条件
if (projectId != null) {
query.setProjectId(projectId);
// 使用通用的查询方法,会根据条件进行过滤
List<SysWorkArea> workAreas = sysWorkAreaService.selectSysWorkAreaList(query);
// 构建树形结构
List<TreeSelect> treeList = sysWorkAreaService.buildWorkAreaTreeSelect(workAreas);
return success(treeList);
} else {
// 如果没有传入项目ID则保持原逻辑查询该公司下的所有工区
List<SysWorkArea> workAreas = sysWorkAreaService.selectSysWorkAreaListByComId(comId);
// 构建树形结构
List<TreeSelect> treeList = sysWorkAreaService.buildWorkAreaTreeSelect(workAreas);
return success(treeList);
}
}
}

View File

@ -0,0 +1,86 @@
package com.yanzhu.system.service;
import java.util.List;
import com.yanzhu.system.domain.SysWorkArea;
import com.yanzhu.system.domain.vo.TreeSelect;
/**
* Service
*
* @author yanzhu
* @date 2025-12-25
*/
public interface ISysWorkAreaService
{
/**
*
*
* @param id
* @return
*/
public SysWorkArea selectSysWorkAreaById(Long id);
/**
*
*
* @param sysWorkArea
* @return
*/
public List<SysWorkArea> selectSysWorkAreaList(SysWorkArea sysWorkArea);
/**
*
*
* @param sysWorkArea
* @return
*/
public int insertSysWorkArea(SysWorkArea sysWorkArea);
/**
*
*
* @param sysWorkArea
* @return
*/
public int updateSysWorkArea(SysWorkArea sysWorkArea);
/**
*
*
* @param ids
* @return
*/
public int deleteSysWorkAreaByIds(Long[] ids);
/**
*
*
* @param id
* @return
*/
public int deleteSysWorkAreaById(Long id);
/**
* ID
*
* @param comId ID
* @return
*/
public List<SysWorkArea> selectSysWorkAreaListByComId(Long comId);
/**
*
*
* @param workAreas
* @return
*/
public List<SysWorkArea> buildWorkAreaTree(List<SysWorkArea> workAreas);
/**
*
*
* @param workAreas
* @return
*/
public List<TreeSelect> buildWorkAreaTreeSelect(List<SysWorkArea> workAreas);
}

View File

@ -0,0 +1,328 @@
package com.yanzhu.system.service.impl;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import com.yanzhu.common.core.utils.StringUtils;
import com.yanzhu.common.core.context.SecurityContextHolder;
import com.yanzhu.common.core.utils.DateUtils;
import com.yanzhu.common.core.utils.StringUtils;
import com.yanzhu.system.domain.vo.TreeSelect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.yanzhu.system.mapper.SysWorkAreaMapper;
import com.yanzhu.system.domain.SysWorkArea;
import com.yanzhu.system.service.ISysWorkAreaService;
/**
* Service
*
* @author yanzhu
* @date 2025-12-25
*/
@Service
public class SysWorkAreaServiceImpl implements ISysWorkAreaService
{
@Autowired
private SysWorkAreaMapper sysWorkAreaMapper;
/**
*
*
* @param id
* @return
*/
@Override
public SysWorkArea selectSysWorkAreaById(Long id)
{
return sysWorkAreaMapper.selectSysWorkAreaById(id);
}
/**
*
*
* @param sysWorkArea
* @return
*/
@Override
public List<SysWorkArea> selectSysWorkAreaList(SysWorkArea sysWorkArea)
{
return sysWorkAreaMapper.selectSysWorkAreaList(sysWorkArea);
}
/**
*
*
* @param sysWorkArea
* @return
*/
@Override
public int insertSysWorkArea(SysWorkArea sysWorkArea)
{
// 如果不是根节点,需要构建祖先路径
if (sysWorkArea.getParentId() != null && sysWorkArea.getParentId() > 0) {
SysWorkArea parentWorkArea = sysWorkAreaMapper.selectSysWorkAreaById(sysWorkArea.getParentId());
if (parentWorkArea != null) {
// 构建祖先路径:父节点的祖先路径 + 父节点ID
String ancestors = parentWorkArea.getAncestors() + "," + parentWorkArea.getId();
sysWorkArea.setAncestors(ancestors);
}
} else {
// 根节点的祖先路径就是自己
sysWorkArea.setAncestors("0");
}
sysWorkArea.setCreateBy(SecurityContextHolder.getUserName());
sysWorkArea.setCreateTime(DateUtils.getNowDate());
return sysWorkAreaMapper.insertSysWorkArea(sysWorkArea);
}
/**
*
*
* @param sysWorkArea
* @return
*/
@Override
public int updateSysWorkArea(SysWorkArea sysWorkArea)
{
// 获取当前工区信息
SysWorkArea oldWorkArea = sysWorkAreaMapper.selectSysWorkAreaById(sysWorkArea.getId());
if (oldWorkArea == null) {
return 0;
}
// 如果父节点发生了变化
if (!Objects.equals(oldWorkArea.getParentId(), sysWorkArea.getParentId())) {
// 获取新的父节点信息
SysWorkArea newParentWorkArea = sysWorkAreaMapper.selectSysWorkAreaById(sysWorkArea.getParentId());
if (newParentWorkArea != null) {
// 构建新的祖先路径
String newAncestors = newParentWorkArea.getAncestors() + "," + newParentWorkArea.getId();
sysWorkArea.setAncestors(newAncestors);
// 更新所有子节点的祖先路径
updateSubWorkAreaAncestors(sysWorkArea.getId(), newAncestors, oldWorkArea.getAncestors());
}
} else {
// 父节点未变化,保持原有祖先路径
sysWorkArea.setAncestors(oldWorkArea.getAncestors());
}
// 如果状态发生变化,需要同时更新所有子工区的状态
if (!Objects.equals(oldWorkArea.getState(), sysWorkArea.getState())) {
updateSubWorkAreaState(sysWorkArea.getId(), sysWorkArea.getState());
}
sysWorkArea.setUpdateBy(SecurityContextHolder.getUserName());
sysWorkArea.setUpdateTime(DateUtils.getNowDate());
return sysWorkAreaMapper.updateSysWorkArea(sysWorkArea);
}
/**
*
*
* @param workAreaId ID
* @param state
*/
private void updateSubWorkAreaState(Long workAreaId, Long state) {
// 通过ancestors字段一次性更新所有子工区的状态
// 更新所有ancestors包含当前工区ID的工区状态
sysWorkAreaMapper.updateSubWorkAreaStateByAncestors(workAreaId, state);
}
/**
*
*
* @param workAreaId ID
* @param newAncestors
* @param oldAncestors
*/
private void updateSubWorkAreaAncestors(Long workAreaId, String newAncestors, String oldAncestors)
{
List<SysWorkArea> children = sysWorkAreaMapper.selectChildrenWorkAreaById(workAreaId);
for (SysWorkArea child : children)
{
// 保存原始祖先路径,用于递归调用
String originalAncestors = child.getAncestors();
String updatedAncestors = originalAncestors.replaceFirst(oldAncestors, newAncestors);
child.setAncestors(updatedAncestors);
// 递归更新子节点的子节点
// 传递更新后的祖先路径作为新的newAncestors原始祖先路径作为旧的oldAncestors
updateSubWorkAreaAncestors(child.getId(), updatedAncestors, originalAncestors);
}
if (children.size() > 0)
{
sysWorkAreaMapper.updateWorkAreaChildren(children);
}
}
/**
*
*
* @param ids
* @return
*/
@Override
public int deleteSysWorkAreaByIds(Long[] ids)
{
// 检查是否有工区被使用
for (Long id : ids) {
if (checkWorkAreaUsed(id)) {
throw new RuntimeException("工区ID为 " + id + " 的工区正在被使用,无法删除");
}
// 检查是否存在未被删除的子工区
if (hasChildrenWorkArea(id)) {
throw new RuntimeException("工区ID为 " + id + " 的工区存在子工区,无法删除");
}
}
return sysWorkAreaMapper.deleteSysWorkAreaByIds(ids);
}
/**
*
*
* @param id
* @return
*/
@Override
public int deleteSysWorkAreaById(Long id)
{
// 检查工区是否被使用
if (checkWorkAreaUsed(id)) {
throw new RuntimeException("工区ID为 " + id + " 的工区正在被使用,无法删除");
}
// 检查是否存在未被删除的子工区
if (hasChildrenWorkArea(id)) {
throw new RuntimeException("工区ID为 " + id + " 的工区存在子工区,无法删除");
}
return sysWorkAreaMapper.deleteSysWorkAreaById(id);
}
@Override
public List<SysWorkArea> selectSysWorkAreaListByComId(Long comId)
{
return sysWorkAreaMapper.selectSysWorkAreaListByComId(comId);
}
/**
*
*
* @param workAreas
* @return
*/
@Override
public List<SysWorkArea> buildWorkAreaTree(List<SysWorkArea> workAreas)
{
List<SysWorkArea> returnList = new ArrayList<SysWorkArea>();
List<Long> tempList = workAreas.stream().map(SysWorkArea::getId).collect(Collectors.toList());
for (SysWorkArea workArea : workAreas)
{
// 如果是顶级节点, 遍历该父节点的所有子节点
if (!tempList.contains(workArea.getParentId()))
{
recursionFn(workAreas, workArea);
returnList.add(workArea);
}
}
if (returnList.isEmpty())
{
returnList = workAreas;
}
return returnList;
}
/**
*
*
* @param workAreas
* @return
*/
@Override
public List<TreeSelect> buildWorkAreaTreeSelect(List<SysWorkArea> workAreas)
{
List<SysWorkArea> workAreaTrees = buildWorkAreaTree(workAreas);
return workAreaTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
}
/**
*
*
* @param list
* @param t
*/
private void recursionFn(List<SysWorkArea> list, SysWorkArea t)
{
// 得到子节点列表
List<SysWorkArea> childList = getChildList(list, t);
t.setChildren(childList != null ? childList : new ArrayList<>());
for (SysWorkArea tChild : childList)
{
if (hasChild(list, tChild))
{
recursionFn(list, tChild);
}
}
}
/**
*
*/
private List<SysWorkArea> getChildList(List<SysWorkArea> list, SysWorkArea t)
{
List<SysWorkArea> tlist = new ArrayList<SysWorkArea>();
Iterator<SysWorkArea> it = list.iterator();
while (it.hasNext())
{
SysWorkArea n = (SysWorkArea) it.next();
if (n.getParentId().longValue() == t.getId().longValue())
{
tlist.add(n);
}
}
return tlist;
}
/**
*
*/
private boolean hasChild(List<SysWorkArea> list, SysWorkArea t)
{
return getChildList(list, t).size() > 0;
}
/**
*
*
* @param id ID
* @return true-false-
*/
private boolean hasChildrenWorkArea(Long id) {
SysWorkArea sysWorkArea = new SysWorkArea();
sysWorkArea.setParentId(id);
List<SysWorkArea> children = sysWorkAreaMapper.selectSysWorkAreaList(sysWorkArea);
return !children.isEmpty();
}
/**
* 使
*
* @param id ID
* @return true-使false-使
*/
private boolean checkWorkAreaUsed(Long id) {
// TODO: 实现工区使用情况检查逻辑
// 例如:检查是否有用户、设备、项目等关联到该工区
// 目前暂时返回false表示未被使用
return false;
}
}

View File

@ -20,6 +20,8 @@ spring:
config: config:
# 配置中心地址 # 配置中心地址
server-addr: @discovery.server-addr@ server-addr: @discovery.server-addr@
# 工作空间配置
namespace: a113aa27-4d61-46e0-81d6-9cede0457f0d
# 配置文件格式 # 配置文件格式
file-extension: yml file-extension: yml
# 共享配置 # 共享配置

View File

@ -113,4 +113,7 @@ a {
.svg-icon{ .svg-icon{
outline: none; outline: none;
} }
.hidden{
display: none;
}
</style> </style>

View File

@ -0,0 +1,51 @@
import request from '@/utils/request'
// 查询工区管理列表
export function listWorkAarea(query) {
return request({
url: '/system/workAarea/list',
method: 'get',
params: query
})
}
// 查询工区管理详细
export function getWorkAarea(id) {
return request({
url: '/system/workAarea/' + id,
method: 'get'
})
}
// 新增工区管理
export function addWorkAarea(data) {
return request({
url: '/system/workAarea',
method: 'post',
data: data
})
}
// 修改工区管理
export function updateWorkAarea(data) {
return request({
url: '/system/workAarea',
method: 'put',
data: data
})
}
// 删除工区管理
export function delWorkAarea(id) {
return request({
url: '/system/workAarea/' + id,
method: 'delete'
})
}
export function workAreaTree(projectId) {
return request({
url: '/system/workAarea/workAreaTree?projectId=' + projectId,
method: 'get'
})
}

View File

@ -0,0 +1,151 @@
// Tailwind CSS
/* Spacing */
.p-y-0 { padding-top: 0; padding-bottom: 0; }
.p-x-0 { padding-left: 0; padding-right: 0; }
.p-0 { padding: 0; }
.m-y-0 { margin-top: 0; margin-bottom: 0; }
.m-x-0 { margin-left: 0; margin-right: 0; }
.m-0 { margin: 0; }
.p-y-1 { padding-top: 1rem; padding-bottom: 1rem; }
.p-x-1 { padding-left: 1rem; padding-right: 1rem; }
.p-1 { padding: 1rem; }
.m-y-1 { margin-top: 1rem; margin-bottom: 1rem; }
.m-x-1 { margin-left: 1rem; margin-right: 1rem; }
.p-y-2 { padding-top: 2rem; padding-bottom: 2rem; }
.p-x-2 { padding-left: 2rem; padding-right: 2rem; }
.p-2 { padding: 2rem; }
.m-y-2 { margin-top: 2rem; margin-bottom: 2rem; }
.m-x-2 { margin-left: 2rem; margin-right: 2rem; }
.p-y-3 { padding-top: 3rem; padding-bottom: 3rem; }
.p-x-3 { padding-left: 3rem; padding-right: 3rem; }
.p-3 { padding: 3rem; }
.m-y-3 { margin-top: 3rem; margin-bottom: 3rem; }
.m-x-3 { margin-left: 3rem; margin-right: 3rem; }
.mt-1 { margin-top: 1rem; }
.mb-1 { margin-bottom: 1rem; }
.mb-2 { margin-bottom: 2rem; }
.mb-3 { margin-bottom: 3rem; }
.mt-2 { margin-top: 2rem; }
.mt-3 { margin-top: 3rem; }
.ml-1 { margin-left: 1rem; }
.ml-2 { margin-left: 2rem; }
.ml-3 { margin-left: 3rem; }
.mr-1 { margin-right: 1rem; }
.mr-2 { margin-right: 2rem; }
.mr-3 { margin-right: 3rem; }
.pl-1 { padding-left: 1rem; }
.pl-2 { padding-left: 2rem; }
.pl-3 { padding-left: 3rem; }
.pr-1 { padding-right: 1rem; }
.pr-2 { padding-right: 2rem; }
.pr-3 { padding-right: 3rem; }
.p-y-auto { padding-top: auto; padding-bottom: auto; }
.p-x-auto { padding-left: auto; padding-right: auto; }
.pt-1 { padding-top: 1rem; }
.pt-2 { padding-top: 2rem; }
.pt-3 { padding-top: 3rem; }
.pb-1 { padding-bottom: 1rem; }
.pb-2 { padding-bottom: 2rem; }
.pb-3 { padding-bottom: 3rem; }
/* Flexbox */
.flex { display: flex; }
.inline-flex { display: inline-flex; }
.flex-row { flex-direction: row; }
.flex-col { flex-direction: column; }
.flex-wrap { flex-wrap: wrap; }
.items-center { align-items: center; }
.justify-center { justify-content: center; }
.justify-between { justify-content: space-between; }
.justify-start { justify-content: flex-start; }
.justify-end { justify-content: flex-end; }
/* Width */
.w-full { width: 100%; }
.w-1\/2 { width: 50%; }
.w-1\/3 { width: 33.333333%; }
.w-2\/3 { width: 66.666667%; }
.w-1\/4 { width: 25%; }
.w-3\/4 { width: 75%; }
.w-1\/5 { width: 20%; }
.w-4\/5 { width: 80%; }
.w-1\/6 { width: 16.666667%; }
.w-5\/6 { width: 83.333333%; }
/* Height */
.h-full { height: 100%; }
.h-screen { height: 100vh; }
/* Text Alignment */
.text-left { text-align: left; }
.text-center { text-align: center; }
.text-right { text-align: right; }
/* Text Colors */
.text-white { color: #fff; }
.text-black { color: #000; }
.text-gray { color: #6b7280; }
.text-gray-dark { color: #374151; }
.text-blue { color: #3b82f6; }
.text-green { color: #10b981; }
.text-red { color: #ef4444; }
.text-yellow { color: #f59e0b; }
/* Background Colors */
.bg-white { background-color: #fff; }
.bg-black { background-color: #000; }
.bg-gray { background-color: #6b7280; }
.bg-gray-light { background-color: #f3f4f6; }
.bg-blue { background-color: #3b82f6; }
.bg-green { background-color: #10b981; }
.bg-red { background-color: #ef4444; }
.bg-yellow { background-color: #f59e0b; }
/* Border */
.border { border: 1px solid #e5e7eb; }
.border-t { border-top: 1px solid #e5e7eb; }
.border-b { border-bottom: 1px solid #e5e7eb; }
.border-l { border-left: 1px solid #e5e7eb; }
.border-r { border-right: 1px solid #e5e7eb; }
.border-gray { border-color: #e5e7eb; }
.rounded { border-radius: 0.25rem; }
.rounded-md { border-radius: 0.375rem; }
.rounded-lg { border-radius: 0.5rem; }
.rounded-full { border-radius: 9999px; }
/* Display */
.block { display: block; }
.inline-block { display: inline-block; }
.hidden { display: none; }
/* Position */
.relative { position: relative; }
.absolute { position: absolute; }
/* Font */
.font-normal { font-weight: 400; }
.font-medium { font-weight: 500; }
.font-semibold { font-weight: 600; }
.font-bold { font-weight: 700; }
.text-sm { font-size: 0.875rem; }
.text-base { font-size: 1rem; }
.text-lg { font-size: 1.125rem; }
.text-xl { font-size: 1.25rem; }
.text-2xl { font-size: 1.5rem; }
/* Other Utilities */
.overflow-hidden { overflow: hidden; }
.overflow-auto { overflow: auto; }
.overflow-scroll { overflow: scroll; }
.cursor-pointer { cursor: pointer; }
.select-none { user-select: none; }
.dlg-hide-form-hidden-scroll{
.el-dialog__body{
overflow: hidden !important;
.el-form{
overflow: hidden !important;
}
}
}

View File

@ -15,6 +15,10 @@
</div> </div>
</div> </div>
<div id="index-map" style="width: 100%; height: 600px"></div> <div id="index-map" style="width: 100%; height: 600px"></div>
<!-- 添加加载提示 -->
<div v-if="mapLoading" class="map-loading">
地图加载中...
</div>
</el-dialog> </el-dialog>
</template> </template>
<script setup> <script setup>
@ -25,11 +29,14 @@ const title = ref("");
const map = ref(""); const map = ref("");
const point = ref(""); const point = ref("");
const cityInfo = ref(""); const cityInfo = ref("");
const mapLoading = ref(false); //
const data = reactive({ const data = reactive({
txtAarea: "", txtAarea: "",
}); });
const emit = defineEmits(["docom"]); const emit = defineEmits(["docom"]);
// API
const BAIDU_MAP_AK = "0WF4D7OmWBQ0CGIdVXS8rmpk";
function doOk() { function doOk() {
emit("docom", point.value, cityInfo.value); emit("docom", point.value, cityInfo.value);
@ -41,15 +48,109 @@ function getAddress() {
return addr; return addr;
} }
// API
function loadBaiduMapAPI() {
return new Promise((resolve, reject) => {
console.log("开始加载百度地图API...");
//
if (typeof BMapGL !== 'undefined') {
console.log("BMapGL已存在直接使用");
resolve();
return;
}
//
if (window.baiduMapLoading) {
console.log("百度地图API正在加载中...");
//
window.baiduMapCallbacks = window.baiduMapCallbacks || [];
window.baiduMapCallbacks.push(() => {
console.log("百度地图API加载完成通过回调");
resolve();
});
return;
}
//
window.baiduMapLoading = true;
window.baiduMapCallbacks = [];
// script
const script = document.createElement('script');
script.type = 'text/javascript';
// 使WebGLAPIs=1
script.src = `https://api.map.baidu.com/api?v=1.0&type=webgl&ak=${BAIDU_MAP_AK}&callback=onBaiduMapLoaded`;
script.onload = () => {
console.log("百度地图API脚本加载成功");
};
script.onerror = () => {
console.error("百度地图API脚本加载失败");
window.baiduMapLoading = false;
reject(new Error('百度地图API脚本加载失败'));
};
//
window.onBaiduMapLoaded = function() {
console.log("百度地图API加载完成回调");
// BMapGL
if (typeof BMapGL !== 'undefined') {
console.log("BMapGL已定义API加载成功");
window.baiduMapLoading = false;
//
window.baiduMapCallbacks.forEach(callback => callback());
window.baiduMapCallbacks = [];
resolve();
} else {
console.error("BMapGL仍未定义API加载可能存在问题");
window.baiduMapLoading = false;
reject(new Error('百度地图API加载完成但BMapGL未定义'));
}
};
//
document.head.appendChild(script);
console.log("百度地图API脚本已添加到页面");
});
}
function showDlg(opt) { function showDlg(opt) {
title.value = opt?.title || "选择地址"; title.value = opt?.title || "选择地址";
show.value = true; show.value = true;
setTimeout(() => { mapLoading.value = true; //
initMap(opt);
}, 400); //
console.log("尝试加载百度地图API...");
// API
loadBaiduMapAPI()
.then(() => {
console.log("百度地图API已就绪开始初始化地图...");
initMap(opt);
})
.catch(error => {
console.error("百度地图API加载失败:", error);
mapLoading.value = false;
// AK
if (error.message.includes('AK')) {
proxy.$modal.msgError("地图加载失败: API密钥无效或配额已用完");
} else {
proxy.$modal.msgError("地图加载失败: " + error.message);
}
});
} }
function currentPoint() { function currentPoint() {
// BMapGL
if (typeof BMapGL === 'undefined') {
console.error("BMapGL未定义无法获取当前位置");
proxy.$modal.msgError("地图服务未加载完成,请稍后重试");
return;
}
let geolocation = new BMapGL.Geolocation(); let geolocation = new BMapGL.Geolocation();
geolocation.enableSDKLocation(); geolocation.enableSDKLocation();
geolocation.getCurrentPosition((e) => { geolocation.getCurrentPosition((e) => {
@ -62,6 +163,11 @@ function currentPoint() {
} }
function mapClick(e) { function mapClick(e) {
// BMapGL
if (typeof BMapGL === 'undefined') {
return;
}
point.value = e.latlng; point.value = e.latlng;
let myGeo = new BMapGL.Geocoder({ extensions_town: true }); let myGeo = new BMapGL.Geocoder({ extensions_town: true });
myGeo.getLocation(e.latlng, (r) => { myGeo.getLocation(e.latlng, (r) => {
@ -84,42 +190,68 @@ function mapClick(e) {
} }
function initMap(opt) { function initMap(opt) {
let imap = new BMapGL.Map("index-map"); // BMapGL
if (typeof BMapGL === 'undefined') {
console.error("BMapGL未定义无法初始化地图");
proxy.$modal.msgError("地图服务未加载完成,请稍后重试");
mapLoading.value = false;
return;
}
map.value = imap; console.log("开始初始化地图...");
let point = new BMapGL.Point(116.404, 39.915);
//
map.value.centerAndZoom(point, 15);
map.value.setDefaultCursor("crosshair"); //
map.value.enableScrollWheelZoom(); //
// //
const container = document.getElementById("index-map");
if (container) {
container.innerHTML = "";
}
// try {
let initMarker = new BMapGL.Marker(point); let imap = new BMapGL.Map("index-map");
//
map.value.addOverlay(initMarker);
//
// map.value = imap;
map.value.addControl(new BMapGL.NavigationControl()); let point = new BMapGL.Point(116.404, 39.915);
// //
map.value.addEventListener("click", mapClick); map.value.centerAndZoom(point, 15);
var myGeo = new BMapGL.Geocoder(); map.value.setDefaultCursor("crosshair"); //
if (opt && opt.address) { map.value.enableScrollWheelZoom(); //
let myGeo = new BMapGL.Geocoder();
myGeo.getPoint(opt.address, function (pt) { //
if (pt) { //
map.value.centerAndZoom(pt, 16); let initMarker = new BMapGL.Marker(point);
mapClick({ latlng: pt }); //
} else { map.value.addOverlay(initMarker);
currentPoint(); //
}
}); //
} else { map.value.addControl(new BMapGL.NavigationControl());
currentPoint(); //
map.value.addEventListener("click", mapClick);
if (opt && opt.address) {
let myGeo = new BMapGL.Geocoder();
myGeo.getPoint(opt.address, function (pt) {
if (pt) {
map.value.centerAndZoom(pt, 16);
mapClick({ latlng: pt });
} else {
currentPoint();
}
});
} else {
currentPoint();
}
//
mapLoading.value = false;
console.log("地图初始化完成");
} catch (error) {
console.error("地图初始化过程中发生错误:", error);
mapLoading.value = false;
proxy.$modal.msgError("地图初始化失败: " + error.message);
} }
} }
function initMapData(opt) { function initMapData(opt) {
if (opt.latitude && opt.longitude) { if (opt.latitude && opt.longitude) {
point.value = {}; point.value = {};
@ -138,7 +270,14 @@ defineExpose({
showDlg, showDlg,
initMapData, initMapData,
}); });
function search() { function search() {
// BMapGL
if (typeof BMapGL === 'undefined') {
proxy.$modal.msgError("地图服务未加载完成,请稍后重试");
return;
}
if (!data.txtAarea) { if (!data.txtAarea) {
proxy.$modal.msgError("请输入要搜索的地址"); proxy.$modal.msgError("请输入要搜索的地址");
return; return;
@ -174,6 +313,22 @@ function search() {
color: #51b5ff; color: #51b5ff;
line-height: 24px; line-height: 24px;
} }
//
.map-loading {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.8);
display: flex;
justify-content: center;
align-items: center;
font-size: 16px;
color: #666;
z-index: 1000;
}
} }
} }
</style> </style>

View File

@ -6,6 +6,7 @@ import ElementPlus from "element-plus";
import locale from "element-plus/es/locale/lang/zh-cn"; import locale from "element-plus/es/locale/lang/zh-cn";
import "element-plus/theme-chalk/index.css"; import "element-plus/theme-chalk/index.css";
import "@/assets/styles/index.scss"; // global css import "@/assets/styles/index.scss"; // global css
import "@/assets/styles/tailwind.scss";
import App from "./App"; import App from "./App";
import store from "./store"; import store from "./store";

View File

@ -1,36 +1,13 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form v-if="false" :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px"> <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px"
<el-form-item label="${comment}" prop="comId"> v-if="data.workAreaOptions && data.workAreaOptions.length > 0">
<el-input v-model="queryParams.comId" placeholder="请输入${comment}" clearable @keyup.enter="handleQuery" /> <el-form-item label="工区" prop="workAreaAncestors">
</el-form-item> <el-tree-select v-model="queryParams.workAreaAncestors" :data="data.workAreaOptions"
<el-form-item label="${comment}" prop="projectId"> :props="{ value: 'id', label: 'title', children: 'children' }" value-key="id" placeholder="请选择工区"
<el-input v-model="queryParams.projectId" placeholder="请输入${comment}" clearable @keyup.enter="handleQuery" /> clearable style="width: 240px" check-strictly />
</el-form-item>
<el-form-item label="监控名称" prop="monitorName">
<el-input v-model="queryParams.monitorName" placeholder="请输入监控名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="AppKey" prop="appkey">
<el-input v-model="queryParams.appkey" placeholder="请输入AppKey" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="Secret" prop="secret">
<el-input v-model="queryParams.secret" placeholder="请输入Secret" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="设备厂商" prop="manufacturer">
<el-input v-model="queryParams.manufacturer" placeholder="请输入设备厂商" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="是否关键点" prop="keyPoint">
<el-input v-model="queryParams.keyPoint" placeholder="请输入是否关键点" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="${comment}" prop="state">
<el-input v-model="queryParams.state" placeholder="请输入${comment}" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="${comment}" prop="isDel">
<el-input v-model="queryParams.isDel" placeholder="请输入${comment}" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="${comment}" prop="upadteTime">
<el-date-picker clearable v-model="queryParams.upadteTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择${comment}"></el-date-picker>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery"></el-button> <el-button type="primary" icon="Search" @click="handleQuery"></el-button>
<el-button icon="Refresh" @click="resetQuery"></el-button> <el-button icon="Refresh" @click="resetQuery"></el-button>
@ -39,7 +16,8 @@
<el-row :gutter="10" class="mb8"> <el-row :gutter="10" class="mb8">
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['manage:videoMonitor:add']"></el-button> <el-button type="primary" plain icon="Plus" @click="handleAdd"
v-hasPermi="['manage:videoMonitor:add']">新增</el-button>
</el-col> </el-col>
<!-- <!--
<el-col :span="1.5"> <el-col :span="1.5">
@ -61,22 +39,28 @@
<el-table v-loading="loading" :data="videoMonitorList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" :data="videoMonitorList" @selection-change="handleSelectionChange">
<el-table-column label="监控名称" align="center" prop="monitorName" /> <el-table-column label="监控名称" align="center" prop="monitorName" />
<el-table-column label="项目名称" align="center" prop="projectName" /> <el-table-column label="项目名称" align="center" prop="projectName" />
<el-table-column label="工区" align="center" prop="workAreaName"
v-if="data.workAreaOptions && data.workAreaOptions.length > 0" />
<el-table-column label="链接" align="center" prop="url" /> <el-table-column label="链接" align="center" prop="url" />
<el-table-column label="萤石云AppKey" align="center" prop="appkey" /> <el-table-column label="萤石云AppKey" align="center" prop="appkey" />
<el-table-column label="萤石云Secret" align="center" prop="secret" /> <el-table-column label="萤石云Secret" align="center" prop="secret" />
<el-table-column label="设备厂商" align="center" prop="manufacturer" /> <el-table-column label="设备厂商" align="center" prop="manufacturer" />
<el-table-column label="是否重点" align="center" prop="keyPoint"> <el-table-column label="是否重点" align="center" prop="keyPoint">
<template #default="scope">{{scope.row.keyPoint==1?'是':'否' }}</template> <template #default="scope">{{ scope.row.keyPoint == 1 ? '是' : '否' }}</template>
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="160px"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="160px">
<template #default="scope"> <template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['manage:videoMonitor:edit']"></el-button> <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['manage:videoMonitor:remove']"></el-button> v-hasPermi="['manage:videoMonitor:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
v-hasPermi="['manage:videoMonitor:remove']">删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" @pagination="getList" />
<!-- 添加或修改延迟摄影管理对话框 --> <!-- 添加或修改延迟摄影管理对话框 -->
<el-dialog :title="title" v-model="open" width="500px" append-to-body> <el-dialog :title="title" v-model="open" width="500px" append-to-body>
@ -115,7 +99,8 @@
<el-input v-model="form.isDel" placeholder="请输入${comment}" /> <el-input v-model="form.isDel" placeholder="请输入${comment}" />
</el-form-item> </el-form-item>
<el-form-item label="${comment}" prop="upadteTime"> <el-form-item label="${comment}" prop="upadteTime">
<el-date-picker clearable v-model="form.upadteTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择${comment}"></el-date-picker> <el-date-picker clearable v-model="form.upadteTime" type="date" value-format="YYYY-MM-DD"
placeholder="请选择${comment}"></el-date-picker>
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
@ -131,6 +116,7 @@
<script setup name="VideoMonitor"> <script setup name="VideoMonitor">
import { listVideoMonitor, getVideoMonitor, delVideoMonitor, addVideoMonitor, updateVideoMonitor } from '@/api/manage/videoMonitor' import { listVideoMonitor, getVideoMonitor, delVideoMonitor, addVideoMonitor, updateVideoMonitor } from '@/api/manage/videoMonitor'
import { workAreaTree } from '@/api/system/workAarea'
import useUserStore from '@/store/modules/user' import useUserStore from '@/store/modules/user'
import videoMonitorDrawer from './videoMonitorDrawer.vue' import videoMonitorDrawer from './videoMonitorDrawer.vue'
const { proxy } = getCurrentInstance() const { proxy } = getCurrentInstance()
@ -151,8 +137,9 @@ const data = reactive({
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
comId: null, workAreaAncestors: '',
projectId: null, comId: userStore.currentComId,
projectId: userStore.currentPrjId,
monitorName: null, monitorName: null,
monitorType: null, monitorType: null,
url: null, url: null,
@ -165,14 +152,72 @@ const data = reactive({
upadteTime: null, upadteTime: null,
}, },
rules: {}, rules: {},
//
workAreaOptions: [],
}) })
const { queryParams, form, rules } = toRefs(data) const { queryParams, form, rules } = toRefs(data)
/** 查询工区树结构 */
function getWorkAreaTree() {
workAreaTree(userStore.currentPrjId).then(response => {
// el-tree-select
data.workAreaOptions = transformTreeData(response.data);
});
}
/** 转换树形数据格式 */
function transformTreeData(apiData) {
if (!apiData || !Array.isArray(apiData)) {
return [];
}
return apiData.map(item => {
// item.datachildren
const transformedItem = {
id: item.id,
title: item.label, // 使label
ancestors: item.data?.ancestors, // dataancestors
//
...item.data
};
// children使
transformedItem.children = item.children ? transformTreeData(item.children) : [];
return transformedItem;
});
}
/** 查找树节点 */
function findTreeNode(nodes, id) {
for (let node of nodes) {
if (node.id === id) {
return node;
}
if (node.children && node.children.length > 0) {
const found = findTreeNode(node.children, id);
if (found) return found;
}
}
return null;
}
/** 查询延迟摄影管理列表 */ /** 查询延迟摄影管理列表 */
function getList() { function getList() {
loading.value = true loading.value = true
queryParams.value.projectId = userStore.currentPrjId queryParams.value.projectId = userStore.currentPrjId
// workAreaAncestors
if (queryParams.value.comId) {
// queryParamsworkAreaAncestors
// ancestors
const selectedNode = findTreeNode(data.workAreaOptions, queryParams.value.comId);
if (selectedNode && selectedNode.ancestors) {
queryParams.value.workAreaAncestors = selectedNode.ancestors;
}
} else {
delete queryParams.value.workAreaAncestors; //
}
listVideoMonitor(queryParams.value).then((response) => { listVideoMonitor(queryParams.value).then((response) => {
videoMonitorList.value = response.rows videoMonitorList.value = response.rows
total.value = response.total total.value = response.total
@ -290,7 +335,7 @@ function handleDelete(row) {
getList() getList()
proxy.$modal.msgSuccess('删除成功') proxy.$modal.msgSuccess('删除成功')
}) })
.catch(() => {}) .catch(() => { })
} }
/** 导出按钮操作 */ /** 导出按钮操作 */
@ -304,5 +349,8 @@ function handleExport() {
) )
} }
//
getWorkAreaTree();
//
getList() getList()
</script> </script>

View File

@ -9,7 +9,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-row v-if="data.selPrjId" class="video-main" :class="!data.currentPrjId?'show-prjs':''"> <el-row v-if="data.selPrjId" class="video-main" :class="!data.currentPrjId ? 'show-prjs' : ''">
<el-col :span="4" class="video-name-list"> <el-col :span="4" class="video-name-list">
<div class="video-title command" @click="showAllVideo"></div> <div class="video-title command" @click="showAllVideo"></div>
<div class="video-list"> <div class="video-list">
@ -19,7 +19,7 @@
</div> </div>
</div> </div>
</el-col> </el-col>
<el-col :span="20" :key="data.elKey" style="height: 100%;"> <el-col :span="20" :key="data.elKey" style="height: 100%;padding-left: 4px;">
<template v-if="data.showMode == 'sigle'"> <template v-if="data.showMode == 'sigle'">
<iframe v-if="data.selVideo" frameborder="0" :src="data.selVideo.iframeSrc" <iframe v-if="data.selVideo" frameborder="0" :src="data.selVideo.iframeSrc"
style="width:100%;height:100%;" id="ysOpenDevice" allowfullscreen> style="width:100%;height:100%;" id="ysOpenDevice" allowfullscreen>
@ -33,11 +33,13 @@
:class="data.showSize != data.mode1 ? 'is-active' : ''" icon-class="9screen" /> :class="data.showSize != data.mode1 ? 'is-active' : ''" icon-class="9screen" />
</div> </div>
<div class="all-list" :class="data.showSize == data.mode1 ? 'mode1' : 'mode2'"> <div class="all-list" :class="data.showSize == data.mode1 ? 'mode1' : 'mode2'">
<div class="all-item command" v-for="it in data.showList" :key="it.id" > <div class="all-item command" v-for="it in data.showList" :key="it.id">
<iframe frameborder="0" :src="it.iframeSrc" style="width:100%;height:calc(100% - 30px);" <iframe frameborder="0" :src="it.iframeSrc" style="width:100%;height:calc(100% - 30px);"
id="ysOpenDevice" allowfullscreen> id="ysOpenDevice" allowfullscreen>
</iframe> </iframe>
<div class="command" @click="doSelectItem(it)" style="text-align: center;height: 30px; line-height: 30px;">{{ it.monitorName }}</div> <div class="command" @click="doSelectItem(it)"
style="text-align: center;height: 30px; line-height: 30px;">
{{ it.monitorName }}</div>
</div> </div>
</div> </div>
<div class="all-pager"> <div class="all-pager">
@ -57,11 +59,12 @@ import {
getYsToken getYsToken
} from "@/api/manage/videoMonitor"; } from "@/api/manage/videoMonitor";
import useUserStore from '@/store/modules/user' import useUserStore from '@/store/modules/user'
import { workAreaTree } from '@/api/system/workAarea'
const userStore = useUserStore() const userStore = useUserStore()
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const data = reactive({ const data = reactive({
mode1:4, mode1: 4,
mode2:9, mode2: 9,
prjInfo: null, prjInfo: null,
projects: [], projects: [],
selPrjId: '', selPrjId: '',
@ -75,6 +78,7 @@ const data = reactive({
showSize: 4, showSize: 4,
showIndex: 1, showIndex: 1,
showList: [], showList: [],
workAreaOptions: [],
}) })
function loadVideo(it) { function loadVideo(it) {
getYsToken(it.id).then(d => { getYsToken(it.id).then(d => {
@ -83,6 +87,15 @@ function loadVideo(it) {
}) })
} }
/** 查询工区树结构 */
function getWorkAreaTree() {
workAreaTree(userStore.currentPrjId).then(response => {
// el-tree-select
data.workAreaOptions = response.data || [];
});
}
function changeSize(n) { function changeSize(n) {
data.showSize = n; data.showSize = n;
data.showIndex = 1; data.showIndex = 1;
@ -93,7 +106,7 @@ function doSelectItem(it) {
return; return;
} }
data.showMode = "sigle"; data.showMode = "sigle";
if(data.selVideo){ if (data.selVideo) {
data.selVideo.active = false; data.selVideo.active = false;
} }
data.selVideo = it; data.selVideo = it;
@ -101,7 +114,7 @@ function doSelectItem(it) {
loadVideo(data.selVideo); loadVideo(data.selVideo);
} }
function showAllVideo() { function showAllVideo() {
if(data.selVideo){ if (data.selVideo) {
data.selVideo.active = false; data.selVideo.active = false;
} }
data.selVideo = null; data.selVideo = null;
@ -169,12 +182,15 @@ getProjectList();
position: absolute; position: absolute;
width: 100%; width: 100%;
padding: 12px; padding: 12px;
.video-main{
.video-main {
height: 100%; height: 100%;
&.show-prjs{
&.show-prjs {
height: calc(100% - 40px); height: calc(100% - 40px);
} }
} }
.video-name-list { .video-name-list {
height: 100%; height: 100%;
background: #fff; background: #fff;
@ -228,22 +244,22 @@ getProjectList();
} }
.all-list { .all-list {
display:grid; display: grid;
grid-gap: 10px; grid-gap: 10px;
height: calc(100% - 80px); height: calc(100% - 80px);
&.mode1{
&.mode1 {
grid-template-columns: 50% 50%; grid-template-columns: 50% 50%;
grid-template-rows: 50% 50%; grid-template-rows: 50% 50%;
.all-item{
} .all-item {}
} }
&.mode2{
&.mode2 {
grid-template-columns: 33% 33% 33%; grid-template-columns: 33% 33% 33%;
grid-template-rows: 33% 33% 33%; grid-template-rows: 33% 33% 33%;
.all-item{
} .all-item {}
} }

View File

@ -1,9 +1,12 @@
<template> <template>
<el-drawer class="video-monitor-drawer" v-if="data.isOpen" v-model="data.isOpen" direction="rtl" size="50%" style="padding-left: 20px" :title="data.title"> <el-drawer class="video-monitor-drawer" v-if="data.isOpen" v-model="data.isOpen" direction="rtl" size="50%"
style="padding-left: 20px" :title="data.title">
<el-form ref="videoMonitorRef" :model="form" :rules="rules" label-width="120px"> <el-form ref="videoMonitorRef" :model="form" :rules="rules" label-width="120px">
<el-form-item label="项目名称" prop="projectId"> <el-form-item label="项目名称" prop="projectId">
<el-select :disabled="data.currentPrjId != ''||data.type=='edit'" v-model="form.projectId" placeholder="请选择项目" clearable style="width:300px;"> <el-select :disabled="data.currentPrjId != '' || data.type == 'edit'" v-model="form.projectId"
<el-option v-for="prj in data.projects" :key="prj.id" :label="prj.projectName" :value="prj.id"></el-option> placeholder="请选择项目" clearable style="width:300px;">
<el-option v-for="prj in data.projects" :key="prj.id" :label="prj.projectName"
:value="prj.id"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="监控名称" prop="monitorName"> <el-form-item label="监控名称" prop="monitorName">
@ -32,6 +35,11 @@
<el-option label="否" value="0"></el-option> <el-option label="否" value="0"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="工区" prop="workAreaId">
<el-tree-select v-model="form.workAreaId" :data="data.workAreaOptions"
:props="{ value: 'id', label: 'title', children: 'children' }" value-key="id" placeholder="请选择工区"
clearable style="width:300px;" />
</el-form-item>
</el-form> </el-form>
<div style="text-align: center;"> <div style="text-align: center;">
<el-button type="primary" @click="doSave"></el-button> <el-button type="primary" @click="doSave"></el-button>
@ -43,6 +51,7 @@
<script setup> <script setup>
import { listVideoMonitor, getVideoMonitor, delVideoMonitor, addVideoMonitor, updateVideoMonitor } from '@/api/manage/videoMonitor' import { listVideoMonitor, getVideoMonitor, delVideoMonitor, addVideoMonitor, updateVideoMonitor } from '@/api/manage/videoMonitor'
import { findMyProjectList } from '@/api/publics' import { findMyProjectList } from '@/api/publics'
import { workAreaTree } from '@/api/system/workAarea'
import useUserStore from '@/store/modules/user' import useUserStore from '@/store/modules/user'
const $emit = defineEmits('success') const $emit = defineEmits('success')
const userStore = useUserStore() const userStore = useUserStore()
@ -54,7 +63,7 @@ const rules = reactive({
monitorType: [{ required: true, trigger: ['blur', 'change'], message: '请选择监控类型' }], monitorType: [{ required: true, trigger: ['blur', 'change'], message: '请选择监控类型' }],
url: [{ required: true, trigger: ['blur', 'change'], message: '请输入监控链接' }], url: [{ required: true, trigger: ['blur', 'change'], message: '请输入监控链接' }],
appkey: [{ required: true, trigger: ['blur', 'change'], message: '请输入萤石云AppKey' }], appkey: [{ required: true, trigger: ['blur', 'change'], message: '请输入萤石云AppKey' }],
secret: [{ required: true, trigger: ['blur', 'change'], message: '请输入萤石云Secret' }], secret: [{ required: true, trigger: ['blur', 'change'], message: '请输入萤石云Secret' }]
}) })
const data = reactive({ const data = reactive({
isOpen: false, isOpen: false,
@ -64,6 +73,7 @@ const data = reactive({
currentPrjId: '', currentPrjId: '',
editRow: null, editRow: null,
comId: '', comId: '',
workAreaOptions: [],
}) })
function showDrawer(opt) { function showDrawer(opt) {
@ -101,6 +111,37 @@ function getSelectProject() {
return objs.length > 0 ? objs[0] : { id: data.currentPrjId, comId: userStore.currentComId } return objs.length > 0 ? objs[0] : { id: data.currentPrjId, comId: userStore.currentComId }
} }
/** 转换树形数据格式 */
function transformTreeData(apiData) {
if (!apiData || !Array.isArray(apiData)) {
return [];
}
return apiData.map(item => {
// item.datachildren
const transformedItem = {
id: item.id,
title: item.label, // 使label
ancestors: item.data?.ancestors, // dataancestors
//
...item.data
};
// children使
transformedItem.children = item.children ? transformTreeData(item.children) : [];
return transformedItem;
});
}
/** 查询工区树结构 */
function getWorkAreaTree() {
workAreaTree(userStore.currentPrjId).then(response => {
// el-tree-select
data.workAreaOptions = transformTreeData(response.data);
});
}
function doSave() { function doSave() {
proxy.$refs['videoMonitorRef'].validate((valid) => { proxy.$refs['videoMonitorRef'].validate((valid) => {
if (valid) { if (valid) {
@ -127,6 +168,7 @@ function doCancel() {
data.isOpen = false data.isOpen = false
} }
getProjectList() getProjectList()
getWorkAreaTree()
defineExpose({ defineExpose({
showDrawer, showDrawer,
}) })

View File

@ -0,0 +1,155 @@
<template>
<el-dialog :title="title" v-model="dialogVisible" width="500px" append-to-body class="dlg-hide-form-hidden-scroll">
<el-form ref="workAareaRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="父区域" v-if="data.row && data.row.parentId!=0">
{{ data.row.fullPath }}
</el-form-item>
<el-form-item label="工区名称" prop="title">
<el-input v-model="form.title" placeholder="请输入工区名称" />
</el-form-item>
<el-form-item :label="data.row && data.row.parentId!=0?'区域编号':'防护等级'" prop="level">
<el-input v-model="form.level" placeholder="请输入防护等级" />
</el-form-item>
<el-form-item label="排序" prop="orderNum">
<el-input v-model="form.orderNum" placeholder="请输入排序" />
</el-form-item>
<el-form-item label="状态" prop="state">
<el-switch v-model="form.state" :active-value="1" :inactive-value="0" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref, reactive, toRefs, nextTick } from 'vue';
import { ElMessage } from 'element-plus';
import { addWorkAarea, updateWorkAarea } from '@/api/system/workAarea';
import useUserStore from "@/store/modules/user";
const emit = defineEmits(['confirm', 'cancel']);
const dialogVisible = ref(false);
const workAareaRef = ref();
const title = ref('');
const action = ref(''); // 'add' or 'edit'
const userStore = useUserStore();
const data = reactive({
isAdd:true,
row:null,
form: {
id: null,
comId: userStore.currentComId,
projectId: userStore.currentPrjId,
parentId: 0,
ancestors: null,
title: null,
level: null,
orderNum: 1,
state: 1,
remark: null,
delFlag: 0
},
rules: {
title: [
{ required: true, message: "工区名称不能为空", trigger: "blur" }
]
}
});
const { form, rules } = toRefs(data);
/** 表单重置 */
function reset(row) {
form.value = {
id: null,
comId: userStore.currentComId,
projectId: userStore.currentPrjId,
parentId: row?.id||0,
ancestors: row?.ancestors || null,
title: '',
level: '',
orderNum: 1,
state: 1,
remark: '',
delFlag: 0
};
nextTick(() => {
if (workAareaRef.value) {
workAareaRef.value.clearValidate();
}
});
}
/** 打开对话框 */
function openDialog(row = null,mode='add') {
data.isAdd = mode === 'add';
data.row = row;
reset(row);
if (!data.isAdd) {
//
title.value = "修改工区管理";
action.value = 'edit';
// rowform
Object.assign(form.value, JSON.parse(JSON.stringify(row)));
} else {
//
title.value = "添加工区管理";
action.value = 'add';
}
dialogVisible.value = true;
}
/** 关闭对话框 */
function closeDialog() {
dialogVisible.value = false;
}
/** 提交表单 */
async function submitForm() {
if (workAareaRef.value) {
const valid = await workAareaRef.value.validate().catch(() => false);
if (valid) {
try {
let response;
if (action.value === 'edit') {
//
response = await updateWorkAarea(form.value);
ElMessage.success("修改成功");
} else {
//
response = await addWorkAarea(form.value);
ElMessage.success("新增成功");
}
dialogVisible.value = false;
emit('confirm', { action: action.value, data: response });
} catch (error) {
const actionText = action.value === 'edit' ? '修改' : '新增';
ElMessage.error(`${actionText}失败: ${error.message || '未知错误'}`);
}
}
}
}
/** 取消 */
function cancel() {
dialogVisible.value = false;
emit('cancel');
}
// 使
defineExpose({
openDialog,
closeDialog
});
</script>
<style scoped>
.dialog-footer {
text-align: right;
}
</style>

View File

@ -0,0 +1,220 @@
<template>
<div class="work-area-main app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="工区名称" prop="title">
<el-input v-model="queryParams.title" 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-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd"
v-hasPermi="['system:workAarea:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"
v-hasPermi="['system:workAarea:remove']">删除</el-button>
</el-col>
</el-row>
<el-table v-loading="loading" :data="workAareaList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="工区名称" align="center" prop="title" />
<el-table-column label="防护等级" align="center" prop="level" />
<el-table-column label="排序" align="center" prop="orderNum" />
<el-table-column label="状态" align="center" prop="state" />
<el-table-column label="创建时间" align="center" prop="createTime" />
<el-table-column label="创建人" align="center" prop="createBy" />
<el-table-column label="操作" align="center" width="240">
<template #default="scope">
<el-button link type="primary" @click="handleAddChild(scope.row)"
v-hasPermi="['system:workAarea:query']">子区域</el-button>
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
v-hasPermi="['system:workAarea:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
v-hasPermi="['system:workAarea:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<workAreaDrawer ref="workAreaDrawerRef" />
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" @pagination="getList" />
<WorkAreaDialog ref="workAreaDialogRef" @confirm="onDialogConfirm" @cancel="onDialogCancel" />
</div>
</template>
<script setup name="WorkAarea">
import { listWorkAarea, getWorkAarea, delWorkAarea, addWorkAarea, updateWorkAarea } from "@/api/system/workAarea";
import WorkAreaDialog from './WorkAreaDialog.vue';
import useUserStore from "@/store/modules/user";
import workAreaDrawer from "./workAreaDrawer.vue";
const { proxy } = getCurrentInstance();
const userStore = useUserStore();
const workAareaList = ref([]);
const open = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const title = ref("");
const workAreaDialogRef = ref();
const workAreaDrawerRef = ref(null);
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
comId: userStore.currentComId,
projectId: userStore.currentPrjId,
parentId: 0,
ancestors: null,
title: null,
level: null,
orderNum: null,
state: null,
},
rules: {
title: [
{ required: true, message: "工区名称不能为空", trigger: "blur" }
]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询工区管理列表 */
function getList() {
loading.value = true;
listWorkAarea(queryParams.value).then(response => {
workAareaList.value = response.rows;
total.value = response.total;
loading.value = false;
});
}
function handleAddChild(row) {
workAreaDrawerRef.value.showDrawer(row);
}
//
function cancel() {
open.value = false;
reset();
}
//
function reset() {
form.value = {
id: null,
comId: userStore.currentComId,
projectId: userStore.currentPrjId,
parentId: null,
ancestors: null,
title: null,
level: null,
orderNum: 1,
state: 1,
remark: null,
delFlag: 0
};
proxy.resetForm("workAareaRef");
}
/** 对话框确认事件 */
function onDialogConfirm({ action, data }) {
proxy.$modal.msgSuccess(action === 'add' ? "新增成功" : "修改成功");
getList();
}
/** 对话框取消事件 */
function onDialogCancel() {
//
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef");
handleQuery();
}
//
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
}
/** 新增按钮操作 */
function handleAdd() {
if (workAreaDialogRef.value) {
workAreaDialogRef.value.openDialog(null,'add');
}
}
/** 修改按钮操作 */
function handleUpdate(row) {
if (workAreaDialogRef.value) {
workAreaDialogRef.value.openDialog(row,'edit');
}
}
/** 提交按钮 */
function submitForm() {
proxy.$refs["workAareaRef"].validate(valid => {
if (valid) {
if (form.value.id != null) {
updateWorkAarea(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功");
open.value = false;
getList();
});
} else {
addWorkAarea(form.value).then(response => {
proxy.$modal.msgSuccess("新增成功");
open.value = false;
getList();
});
}
}
});
}
/** 删除按钮操作 */
function handleDelete(row) {
const _ids = row.id || ids.value;
proxy.$modal.confirm('是否确认删除工区管理编号为"' + _ids + '"的数据项?').then(function () {
return delWorkAarea(_ids);
}).then(() => {
getList();
proxy.$modal.msgSuccess("删除成功");
}).catch(() => { });
}
/** 导出按钮操作 */
function handleExport() {
proxy.download('system/workAarea/export', {
...queryParams.value
}, `workAarea_${new Date().getTime()}.xlsx`)
}
getList();
</script>

View File

@ -0,0 +1,180 @@
<template>
<el-drawer v-model="open" :title="title" size="60%" class="p-y-0 area-worker-drawer">
<div class="p-y-1">
<el-button type="success" class="mb-1" @click="handleAddRoot"></el-button>
<el-table v-loading="loading" :data="workAreaList" row-key="id"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }">
<el-table-column label="工区名称" prop="title" width="200" />
<el-table-column label="区域编号" prop="level" width="200" />
<el-table-column label="操作" width="280" fixed="right">
<template #default="{ row }">
<el-button link type="primary" icon="Plus" @click="handleAddChild(row)"
v-hasPermi="['system:workAarea:add']">增加子区域</el-button>
<el-button link type="primary" icon="Edit" @click="handleUpdate(row)"
v-hasPermi="['system:workAarea:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(row)"
v-hasPermi="['system:workAarea:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<WorkAreaDialog ref="workAreaDialogRef" @confirm="onDialogConfirm" @cancel="onDialogCancel" />
</el-drawer>
</template>
<script>
import { listWorkAarea, delWorkAarea } from '@/api/system/workAarea';
import WorkAreaDialog from './WorkAreaDialog.vue';
export default {
name: "WorkAreaDrawer",
components: {
WorkAreaDialog
},
data() {
return {
open: false,
loading: true,
title: '',
workAreaList: [],
row: null
};
},
methods: {
/** 查询工区管理列表 */
getList() {
this.loading = true;
let queryParams = {
ancestors: this.row.id,
projectId: this.row.projectId,
comId: this.row.comId,
pageNum: 1,
pageSize: 10000
};
listWorkAarea(queryParams).then(response => {
this.workAreaList = this.buildTree(response.rows);
this.loading = false;
});
},
/** 构建树形结构 */
buildTree(data) {
const map = {};
const roots = [];
let rootPath = `/${this.row.title}/`
// fullPath
for (let i = 0; i < data.length; i++) {
map[data[i].id] = {
...data[i],
children: [],
fullPath: data[i].title || data[i].name || ''
};
}
//
for (let i = 0; i < data.length; i++) {
let node = map[data[i].id];
if (data[i].parentId && map[data[i].parentId]) {
//
// fullPath
node.fullPath = rootPath + map[data[i].parentId].fullPath + ' / ' + (data[i].title || data[i].name || '');
map[data[i].parentId].children.push(node);
} else {
//
node.fullPath = rootPath + node.fullPath;
roots.push(node);
}
}
return roots;
},
/** 新增根区域 */
handleAddRoot() {
if (this.$refs.workAreaDialogRef) {
//
this.$refs.workAreaDialogRef.openDialog({
...this.row,
comId: this.row.comId,
projectId: this.row.projectId,
parentId: this.row.id,
ancestors: this.row.ancestors ? this.row.ancestors + ',' + this.row.id : this.row.id.toString(),
}, 'add');
}
},
/** 新增子区域 */
handleAddChild(row) {
if (this.$refs.workAreaDialogRef) {
this.$refs.workAreaDialogRef.openDialog({
...row,
fullPath: row.fullPath,
comId: row.comId,
projectId: row.projectId,
parentId: row.id,
ancestors: row.ancestors ? row.ancestors + ',' + row.id : row.id.toString()
});
}
},
/** 修改 */
handleUpdate(row) {
if (this.$refs.workAreaDialogRef) {
this.$refs.workAreaDialogRef.openDialog(row, 'edit');
}
},
/** 删除 */
handleDelete(row) {
this.$modal.confirm('是否确认删除工区管理编号为"' + row.id + '"的数据项?')
.then(() => {
return delWorkAarea(row.id);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => { });
},
/** 打开抽屉 */
showDrawer(row = null) {
if (row) {
row.fullPath = '/' + row.title
}
this.row = row;
this.title = row.title;
this.open = true;
this.getList();
},
/** 关闭抽屉 */
closeDrawer() {
this.open = false;
},
/** 对话框确认事件 */
onDialogConfirm({ action, data }) {
this.$modal.msgSuccess(action === 'add' ? "新增成功" : "修改成功");
this.getList();
},
/** 对话框取消事件 */
onDialogCancel() {
//
}
}
}
</script>
<style lang="scss">
.area-worker-drawer {
.el-drawer__header {
margin-bottom: 0px;
}
.el-drawer__body {
padding-top: 0px;
padding-bottom: 0px;
}
}
</style>

View File

@ -39,8 +39,8 @@ export default defineConfig(({ mode, command }) => {
}, },
// https://cn.vitejs.dev/config/#server-proxy // https://cn.vitejs.dev/config/#server-proxy
"/dev-api": { "/dev-api": {
//target: "http://localhost:8080", target: "http://localhost:8080",
target: "http://62.234.3.186", //target: "http://62.234.3.186",
changeOrigin: true, changeOrigin: true,
rewrite: (p) => p.replace(/^\/dev-api/, ""), rewrite: (p) => p.replace(/^\/dev-api/, ""),
}, },