From 223ce7dcb236cad6679275d8941e1a909f8a1efc Mon Sep 17 00:00:00 2001
From: lty <876263681@qq.com>
Date: 星期三, 21 一月 2026 10:12:30 +0800
Subject: [PATCH] #库区分配

---
 src/main/java/com/zy/asrs/mapper/AreaMapper.java               |   12 
 src/main/java/com/zy/asrs/service/impl/LocMastServiceImpl.java |   13 
 src/main/webapp/views/report/viewLocMap.html                   |   45 +
 src/main/java/com/zy/asrs/controller/LocMastController.java    |   12 
 src/main/webapp/static/js/report/locMap.js                     |  323 ++++++++++++++
 src/main/java/com/zy/asrs/entity/ViewLocMapDto.java            |   10 
 src/main/java/com/zy/asrs/entity/Area.java                     |  103 ++++
 src/main/webapp/static/js/mat/mat.js                           |   52 ++
 src/main/webapp/views/mat/mat.html                             |   44 +
 src/main/resources/mapper/AreaMapper.xml                       |   18 
 src/main/webapp/static/js/area/area.js                         |  252 +++++++++++
 src/main/java/com/zy/common/CodeBuilder.java                   |    4 
 src/main/java/com/zy/asrs/controller/AreaController.java       |  128 +++++
 src/main/java/com/zy/asrs/mapper/ReportQueryMapper.java        |    6 
 src/main/java/com/zy/asrs/service/AreaService.java             |    8 
 src/main/java/area.sql                                         |   18 
 src/main/webapp/views/area/area.html                           |  134 ++++++
 src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java    |   41 +
 src/main/resources/mapper/MatMapper.xml                        |    1 
 src/main/java/com/zy/asrs/entity/Mat.java                      |   24 +
 src/main/resources/license2.lic                                |    0 
 src/main/java/com/zy/asrs/service/LocMastService.java          |    2 
 src/main/resources/license.lic                                 |    0 
 src/main/java/com/zy/asrs/service/impl/AreaServiceImpl.java    |   12 
 24 files changed, 1,220 insertions(+), 42 deletions(-)

diff --git a/src/main/java/area.sql b/src/main/java/area.sql
new file mode 100644
index 0000000..ef2236d
--- /dev/null
+++ b/src/main/java/area.sql
@@ -0,0 +1,18 @@
+-- save area record
+-- mysql
+insert into `sys_resource` ( `code`, `name`, `resource_id`, `level`, `sort`, `status`) values ( 'area/area.html', 'area绠$悊', null , '2', null , '1');
+
+insert into `sys_resource` ( `code`, `name`, `resource_id`, `level`, `sort`, `status`) values ( 'area#view', '鏌ヨ', '', '3', '0', '1');
+insert into `sys_resource` ( `code`, `name`, `resource_id`, `level`, `sort`, `status`) values ( 'area#btn-add', '鏂板', '', '3', '1', '1');
+insert into `sys_resource` ( `code`, `name`, `resource_id`, `level`, `sort`, `status`) values ( 'area#btn-edit', '缂栬緫', '', '3', '2', '1');
+insert into `sys_resource` ( `code`, `name`, `resource_id`, `level`, `sort`, `status`) values ( 'area#btn-delete', '鍒犻櫎', '', '3', '3', '1');
+insert into `sys_resource` ( `code`, `name`, `resource_id`, `level`, `sort`, `status`) values ( 'area#btn-export', '瀵煎嚭', '', '3', '4', '1');
+
+-- sqlserver
+insert [dbo].[sys_resource] ( [code], [name], [resource_id], [level], [sort], [status]) values ( N'area/area.html', N'area绠$悊', null, '2', null, '1');
+
+insert [dbo].[sys_resource] ( [code], [name], [resource_id], [level], [sort], [status]) values ( N'area#view', N'鏌ヨ', '', '3', '0', '1');
+insert [dbo].[sys_resource] ( [code], [name], [resource_id], [level], [sort], [status]) values ( N'area#btn-add', N'鏂板', '', '3', '1', '1');
+insert [dbo].[sys_resource] ( [code], [name], [resource_id], [level], [sort], [status]) values ( N'area#btn-edit', N'缂栬緫', '', '3', '2', '1');
+insert [dbo].[sys_resource] ( [code], [name], [resource_id], [level], [sort], [status]) values ( N'area#btn-delete', N'鍒犻櫎', '', '3', '3', '1');
+insert [dbo].[sys_resource] ( [code], [name], [resource_id], [level], [sort], [status]) values ( N'area#btn-export', N'瀵煎嚭', '', '3', '4', '1');
diff --git a/src/main/java/com/zy/asrs/controller/AreaController.java b/src/main/java/com/zy/asrs/controller/AreaController.java
new file mode 100644
index 0000000..e476522
--- /dev/null
+++ b/src/main/java/com/zy/asrs/controller/AreaController.java
@@ -0,0 +1,128 @@
+package com.zy.asrs.controller;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.baomidou.mybatisplus.mapper.Wrapper;
+import com.baomidou.mybatisplus.plugins.Page;
+import com.core.common.DateUtils;
+import com.zy.asrs.entity.Area;
+import com.zy.asrs.service.AreaService;
+import com.core.annotations.ManagerAuth;
+import com.core.common.BaseRes;
+import com.core.common.Cools;
+import com.core.common.R;
+import com.zy.common.web.BaseController;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.*;
+
+@RestController
+public class AreaController extends BaseController {
+
+    @Autowired
+    private AreaService areaService;
+
+    @RequestMapping(value = "/area/{id}/auth")
+    @ManagerAuth
+    public R get(@PathVariable("id") String id) {
+        return R.ok(areaService.selectById(String.valueOf(id)));
+    }
+
+    @RequestMapping(value = "/area/list/auth")
+    @ManagerAuth
+    public R list(@RequestParam(defaultValue = "1")Integer curr,
+                  @RequestParam(defaultValue = "10")Integer limit,
+                  @RequestParam(required = false)String orderByField,
+                  @RequestParam(required = false)String orderByType,
+                  @RequestParam(required = false)String condition,
+                  @RequestParam Map<String, Object> param){
+        EntityWrapper<Area> wrapper = new EntityWrapper<>();
+        excludeTrash(param);
+        param.remove("page");
+        param.remove("limit");
+        param.remove("curr");
+        convert(param, wrapper);
+        allLike(Area.class, param.keySet(), wrapper, condition);
+        if (!Cools.isEmpty(orderByField)){wrapper.orderBy(humpToLine(orderByField), "asc".equals(orderByType));}
+        return R.ok(areaService.selectPage(new Page<>(curr, limit), wrapper));
+    }
+
+    private <T> void convert(Map<String, Object> map, EntityWrapper<T> wrapper){
+        for (Map.Entry<String, Object> entry : map.entrySet()){
+            String val = String.valueOf(entry.getValue());
+            if (val.contains(RANGE_TIME_LINK)){
+                String[] dates = val.split(RANGE_TIME_LINK);
+                wrapper.ge(entry.getKey(), DateUtils.convert(dates[0]));
+                wrapper.le(entry.getKey(), DateUtils.convert(dates[1]));
+            } else {
+                wrapper.like(entry.getKey(), val);
+            }
+        }
+    }
+
+    @RequestMapping(value = "/area/add/auth")
+    @ManagerAuth
+    public R add(Area area) {
+        areaService.insert(area);
+        return R.ok();
+    }
+
+	@RequestMapping(value = "/area/update/auth")
+	@ManagerAuth
+    public R update(Area area){
+        if (Cools.isEmpty(area) || null==area.getId()){
+            return R.error();
+        }
+        areaService.updateById(area);
+        return R.ok();
+    }
+
+    @RequestMapping(value = "/area/delete/auth")
+    @ManagerAuth
+    public R delete(@RequestParam(value="ids[]") Long[] ids){
+         for (Long id : ids){
+            areaService.deleteById(id);
+        }
+        return R.ok();
+    }
+
+    @RequestMapping(value = "/area/export/auth")
+    @ManagerAuth
+    public R export(@RequestBody JSONObject param){
+        EntityWrapper<Area> wrapper = new EntityWrapper<>();
+        List<String> fields = JSONObject.parseArray(param.getJSONArray("fields").toJSONString(), String.class);
+        Map<String, Object> map = excludeTrash(param.getJSONObject("area"));
+        convert(map, wrapper);
+        List<Area> list = areaService.selectList(wrapper);
+        return R.ok(exportSupport(list, fields));
+    }
+
+    @RequestMapping(value = "/areaQuery/auth")
+    @ManagerAuth
+    public R query(String condition) {
+        EntityWrapper<Area> wrapper = new EntityWrapper<>();
+        wrapper.like("id", condition);
+        Page<Area> page = areaService.selectPage(new Page<>(0, 10), wrapper);
+        List<Map<String, Object>> result = new ArrayList<>();
+        for (Area area : page.getRecords()){
+            Map<String, Object> map = new HashMap<>();
+            map.put("id", area.getId());
+            map.put("value", area.getId());
+            result.add(map);
+        }
+        return R.ok(result);
+    }
+
+    @RequestMapping(value = "/area/check/column/auth")
+    @ManagerAuth
+    public R query(@RequestBody JSONObject param) {
+        Wrapper<Area> wrapper = new EntityWrapper<Area>().eq(humpToLine(String.valueOf(param.get("key"))), param.get("val"));
+        if (null != areaService.selectOne(wrapper)){
+            return R.parse(BaseRes.REPEAT).add(getComment(Area.class, String.valueOf(param.get("key"))));
+        }
+        return R.ok();
+    }
+
+}
diff --git a/src/main/java/com/zy/asrs/controller/LocMastController.java b/src/main/java/com/zy/asrs/controller/LocMastController.java
index 98dacdb..666be26 100644
--- a/src/main/java/com/zy/asrs/controller/LocMastController.java
+++ b/src/main/java/com/zy/asrs/controller/LocMastController.java
@@ -177,6 +177,18 @@
         return R.ok();
     }
 
+    @PostMapping(value = "/locMast/batchUpdateArea/auth")
+    @ManagerAuth
+    public R batchUpdateArea(@RequestBody JSONObject param) {
+        List<String> locNos = param.getJSONArray("locNos").toJavaList(String.class);
+        Integer areaId = param.getInteger("areaId");
+        if (Cools.isEmpty(locNos) || areaId == null) {
+            return R.error("鍙傛暟閿欒");
+        }
+        locMastService.batchUpdateArea(locNos, areaId.shortValue());
+        return R.ok();
+    }
+
     @RequestMapping(value = "/locMast/init/auth")
     @ManagerAuth(memo = "鍒濆鍖栧簱浣�")
 //    @Transactional
diff --git a/src/main/java/com/zy/asrs/entity/Area.java b/src/main/java/com/zy/asrs/entity/Area.java
new file mode 100644
index 0000000..424a648
--- /dev/null
+++ b/src/main/java/com/zy/asrs/entity/Area.java
@@ -0,0 +1,103 @@
+package com.zy.asrs.entity;
+
+import com.baomidou.mybatisplus.annotations.TableId;
+import com.baomidou.mybatisplus.enums.IdType;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.core.common.Cools;import com.baomidou.mybatisplus.annotations.TableField;
+
+import com.core.common.SpringUtils;
+import com.zy.asrs.service.AreaService;
+import com.zy.asrs.service.TagService;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import com.baomidou.mybatisplus.annotations.TableName;
+import java.io.Serializable;
+
+@Data
+@TableName("man_area")
+public class Area implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * ID
+     */
+    @ApiModelProperty(value= "ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty(value= "")
+    @TableField("tag_id")
+    private Long tagId;
+
+    /**
+     * 搴撳尯id
+     */
+    @ApiModelProperty(value= "搴撳尯id")
+    @TableField("area_id")
+    private String areaId;
+
+    /**
+     * 搴撳尯鍚嶇О
+     */
+    @ApiModelProperty(value= "搴撳尯鍚嶇О")
+    @TableField("area_name")
+    private String areaName;
+
+    /**
+     * 搴撳尯澶囨敞
+     */
+    @ApiModelProperty(value= "搴撳尯澶囨敞")
+    private String memo;
+
+    /**
+     * 澶囩敤瀛楁
+     */
+    @ApiModelProperty(value= "澶囩敤瀛楁")
+    private String backup1;
+
+    /**
+     * 澶囩敤瀛楁2
+     */
+    @ApiModelProperty(value= "澶囩敤瀛楁2")
+    private String backup2;
+
+    /**
+     * 澶囩敤瀛楁3
+     */
+    @ApiModelProperty(value= "澶囩敤瀛楁3")
+    private String backup3;
+
+    public Area() {}
+
+    public Area(Long id,Long tagId,String areaId,String areaName,String memo,String backup1,String backup2,String backup3) {
+        this.id = id;
+        this.tagId = tagId;
+        this.areaId = areaId;
+        this.areaName = areaName;
+        this.memo = memo;
+        this.backup1 = backup1;
+        this.backup2 = backup2;
+        this.backup3 = backup3;
+    }
+    public String getAreaId$(){
+        AreaService service = SpringUtils.getBean(AreaService.class);
+        Area area = service.selectOne(new EntityWrapper<Area>().eq("area_id",areaId));
+        if (!Cools.isEmpty(area)){
+            return String.valueOf(area.getAreaName());
+        }
+        return null;
+    }
+//    Area area = new Area(
+//            null,    // ID[闈炵┖]
+//            null,    // [闈炵┖]
+//            null,    // 搴撳尯id[闈炵┖]
+//            null,    // 搴撳尯鍚嶇О
+//            null,    // 搴撳尯澶囨敞
+//            null,    // 澶囩敤瀛楁
+//            null,    // 澶囩敤瀛楁2
+//            null    // 澶囩敤瀛楁3
+//    );
+
+
+}
diff --git a/src/main/java/com/zy/asrs/entity/Mat.java b/src/main/java/com/zy/asrs/entity/Mat.java
index bee0346..3501573 100644
--- a/src/main/java/com/zy/asrs/entity/Mat.java
+++ b/src/main/java/com/zy/asrs/entity/Mat.java
@@ -5,8 +5,10 @@
 import com.baomidou.mybatisplus.annotations.TableId;
 import com.baomidou.mybatisplus.annotations.TableName;
 import com.baomidou.mybatisplus.enums.IdType;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
 import com.core.common.Cools;
 import com.core.common.SpringUtils;
+import com.zy.asrs.service.AreaService;
 import com.zy.asrs.service.TagService;
 import com.zy.common.utils.Synchro;
 import com.zy.system.entity.User;
@@ -325,9 +327,16 @@
     @TableField("store_max_date")
     private Integer storeMaxDate;
 
+    /**
+     * 搴撳尯id
+     */
+    @ApiModelProperty(value= "搴撳尯id")
+    @TableField("area_id")
+    private String areaId;
+
     public Mat() {}
 
-    public Mat(String uuid,Long tagId,String matnr,String maktx,String name,String specs,String model,String color,String brand,String unit,Double price,String sku,Double units,String barcode,String origin,String manu,String manuDate,String itemNum,Double safeQty,Double weight,Double length,Double volume,String threeCode,String supp,String suppCode,Integer beBatch,String deadTime,Integer deadWarn,Integer source,Integer inspect,Integer danger,Integer status,Long createBy,Date createTime,Long updateBy,Date updateTime,String memo) {
+    public Mat(String uuid,Long tagId,String matnr,String maktx,String name,String specs,String model,String color,String brand,String unit,Double price,String sku,Double units,String barcode,String origin,String manu,String manuDate,String itemNum,Double safeQty,Double weight,Double length,Double volume,String threeCode,String supp,String suppCode,Integer beBatch,String deadTime,Integer deadWarn,Integer source,Integer inspect,Integer danger,Integer status,Long createBy,Date createTime,Long updateBy,Date updateTime,String memo,String areaId) {
         this.uuid = uuid;
         this.tagId = tagId;
         this.matnr = matnr;
@@ -365,6 +374,7 @@
         this.updateBy = updateBy;
         this.updateTime = updateTime;
         this.memo = memo;
+        this.areaId = areaId;
     }
 
 //    Mat mat = new Mat(
@@ -416,6 +426,18 @@
         return null;
     }
 
+    public String getAreaId$(){
+        if (Cools.isEmpty(this.areaId)){
+            return null;
+        }
+        AreaService service = SpringUtils.getBean(AreaService.class);
+        Area area = service.selectOne(new EntityWrapper<Area>().eq("area_id", this.areaId));
+        if (!Cools.isEmpty(area)){
+            return String.valueOf(area.getAreaName());
+        }
+        return null;
+    }
+
     public String getBeBatch$(){
         if (null == this.beBatch){ return null; }
         switch (this.beBatch){
diff --git a/src/main/java/com/zy/asrs/entity/ViewLocMapDto.java b/src/main/java/com/zy/asrs/entity/ViewLocMapDto.java
index 31adb7e..1113b3b 100644
--- a/src/main/java/com/zy/asrs/entity/ViewLocMapDto.java
+++ b/src/main/java/com/zy/asrs/entity/ViewLocMapDto.java
@@ -17,6 +17,7 @@
     private String color = "#666";
     private Integer row1;
     private Integer lev1;
+    private Short locType2;
 
     public ViewLocMapDto() {
     }
@@ -25,6 +26,14 @@
         this.locNo = locNo;
         this.bay1 = bay1;
         this.locSts = locSts;
+    }
+
+    public Short getLocType2() {
+        return locType2;
+    }
+
+    public void setLocType2(Short locType2) {
+        this.locType2 = locType2;
     }
 
     public String getLocNo() {
@@ -112,4 +121,5 @@
     public void setColor(String color) {
         this.color = color;
     }
+
 }
diff --git a/src/main/java/com/zy/asrs/mapper/AreaMapper.java b/src/main/java/com/zy/asrs/mapper/AreaMapper.java
new file mode 100644
index 0000000..86dcb4b
--- /dev/null
+++ b/src/main/java/com/zy/asrs/mapper/AreaMapper.java
@@ -0,0 +1,12 @@
+package com.zy.asrs.mapper;
+
+import com.zy.asrs.entity.Area;
+import com.baomidou.mybatisplus.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.springframework.stereotype.Repository;
+
+@Mapper
+@Repository
+public interface AreaMapper extends BaseMapper<Area> {
+
+}
diff --git a/src/main/java/com/zy/asrs/mapper/ReportQueryMapper.java b/src/main/java/com/zy/asrs/mapper/ReportQueryMapper.java
index 56fdfbf..0eaa2a2 100644
--- a/src/main/java/com/zy/asrs/mapper/ReportQueryMapper.java
+++ b/src/main/java/com/zy/asrs/mapper/ReportQueryMapper.java
@@ -34,20 +34,20 @@
 	@Select("select distinct lev1 from asr_loc_mast where row1=#{row1} order by lev1 desc")
 	public List<String> getViewLocLevCount(@Param("row1") int row1);
 //
-	@Select("select loc_no as locNo, bay1,loc_sts as locSts from asr_loc_mast where row1=#{row1} and lev1=#{lev1} order by bay1")
+	@Select("select loc_no as locNo, bay1,loc_sts as locSts, loc_type2 as locType2 from asr_loc_mast where row1=#{row1} and lev1=#{lev1} order by bay1")
 	public List<ViewLocMapDto> getViewLocBays(@Param("row1") int row1, @Param("lev1") int lev1);
 
 	// 搴撲綅Map
 	@Select("select distinct bay1 from asr_loc_mast where row1=#{row1} order by bay1")
 	public List<String> getViewLocBayCount(@Param("row1") int row1);
-	@Select("select lev1,loc_sts as locSts from asr_loc_mast where row1=#{row1} and bay1=#{bay1} order by bay1")
+	@Select("select lev1,loc_sts as locSts, loc_type2 as locType2 from asr_loc_mast where row1=#{row1} and bay1=#{bay1} order by bay1")
 	public List<ViewLocMapDto> getViewLocLevs(@Param("row1") int row1, @Param("bay1") int bay1);
 	@Select("SELECT DISTINCT row1 FROM asr_loc_mast ORDER BY row1 ASC")
 	List<Integer> getAllRows();
 	@Select("SELECT DISTINCT bay1 FROM asr_loc_mast ORDER BY bay1 ASC")
 	List<String> getAllBays();
 
-	@Select("SELECT row1,lev1,bay1,loc_no as locNo,loc_sts as locSts FROM asr_loc_mast WHERE lev1 = #{layer} ORDER BY row1 ASC, bay1 ASC")
+	@Select("SELECT row1,lev1,bay1,loc_no as locNo,loc_sts as locSts, loc_type2 as locType2 FROM asr_loc_mast WHERE lev1 = #{layer} ORDER BY row1 ASC, bay1 ASC")
 	List<ViewLocMapDto> getLocMapByLayer(@Param("layer") Integer layer);
 	//鍒嗛〉鏌ヨ绔欑偣鍏ュ嚭搴撴鏁扮粺璁�
 	public List<ViewInOutBean> queryViewInOutList(ViewInOutBean viewInOut);
diff --git a/src/main/java/com/zy/asrs/service/AreaService.java b/src/main/java/com/zy/asrs/service/AreaService.java
new file mode 100644
index 0000000..77449c3
--- /dev/null
+++ b/src/main/java/com/zy/asrs/service/AreaService.java
@@ -0,0 +1,8 @@
+package com.zy.asrs.service;
+
+import com.zy.asrs.entity.Area;
+import com.baomidou.mybatisplus.service.IService;
+
+public interface AreaService extends IService<Area> {
+
+}
diff --git a/src/main/java/com/zy/asrs/service/LocMastService.java b/src/main/java/com/zy/asrs/service/LocMastService.java
index c2e41b9..7aa93d5 100644
--- a/src/main/java/com/zy/asrs/service/LocMastService.java
+++ b/src/main/java/com/zy/asrs/service/LocMastService.java
@@ -66,5 +66,7 @@
      */
     List<LocMast> queryFreeLocMast2(Short locType1, Integer rowBeg, Integer rowEnd, Integer bayBeg, Integer bayEnd, Integer levBeg, Integer levEnd);
 
+    void batchUpdateArea(List<String> locNos, Short areaId);
+
     List<Integer> getLevList();
 }
diff --git a/src/main/java/com/zy/asrs/service/impl/AreaServiceImpl.java b/src/main/java/com/zy/asrs/service/impl/AreaServiceImpl.java
new file mode 100644
index 0000000..b31b803
--- /dev/null
+++ b/src/main/java/com/zy/asrs/service/impl/AreaServiceImpl.java
@@ -0,0 +1,12 @@
+package com.zy.asrs.service.impl;
+
+import com.zy.asrs.mapper.AreaMapper;
+import com.zy.asrs.entity.Area;
+import com.zy.asrs.service.AreaService;
+import com.baomidou.mybatisplus.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+@Service("areaService")
+public class AreaServiceImpl extends ServiceImpl<AreaMapper, Area> implements AreaService {
+
+}
diff --git a/src/main/java/com/zy/asrs/service/impl/LocMastServiceImpl.java b/src/main/java/com/zy/asrs/service/impl/LocMastServiceImpl.java
index 08468a5..1ba611f 100644
--- a/src/main/java/com/zy/asrs/service/impl/LocMastServiceImpl.java
+++ b/src/main/java/com/zy/asrs/service/impl/LocMastServiceImpl.java
@@ -156,6 +156,19 @@
     }
 
     @Override
+    public void batchUpdateArea(List<String> locNos, Short areaId) {
+        if (Cools.isEmpty(locNos)) return;
+        java.util.List<LocMast> list = new java.util.ArrayList<>();
+        for (String locNo : locNos) {
+            LocMast loc = new LocMast();
+            loc.setLocNo(locNo);
+            loc.setLocType2(areaId);
+            list.add(loc);
+        }
+        this.updateBatchById(list);
+    }
+
+    @Override
     public List<Integer> getLevList() {
         return this.baseMapper.getLevList();
     }
diff --git a/src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java b/src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java
index eba6e34..c25a96d 100644
--- a/src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java
+++ b/src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java
@@ -273,8 +273,10 @@
     /**
      * 妫�鏌ユ甯稿簱浣嶅墠鏂规槸鍚﹀牭濉烇紙娣卞簱浣嶈鍒欙細鍓嶆柟鎺掓槸鍚︽湁璐ф垨鍏ュ簱浠诲姟锛�
      *
-     * 鍙灞炰簬鍑哄簱鍒嗙粍瑙勫垯鍐呯殑搴撲綅杩涜妫�鏌�
-     * 濡傛灉搴撲綅涓嶅湪鍒嗙粍瑙勫垯鍐咃紝鍒欒涓轰笉闇�瑕佷弗鏍兼鏌ワ紙杩斿洖 false锛屼笉瑙﹀彂琛ラ綈锛�
+     * 鍒ゆ柇渚濇嵁锛�
+     * 1. 鍙鏌ュ睘浜庡嚭搴撳垎缁勮鍒欏唴鐨勫簱浣嶏紙閫氳繃鍒嗙粍鐨� rowList 纭畾鑼冨洿锛�
+     * 2. 鍓嶆柟 = 鍒嗙粍涓储寮曞ぇ浜庡綋鍓嶅簱浣嶇殑鎺掞紙鍋囪鍒嗙粍 rowList 宸叉寜鍑哄簱椤哄簭鎺掑垪锛屽ぇ绱㈠紩 = 鍓嶆柟鏇存繁锛�
+     * 3. 鍫靛鏉′欢锛氬墠鏂规湁璐э紙F鐘舵�侊級鎴栨湁鍏ュ簱浠诲姟
      *
      * @param normalMasts 闇�瑕佹鏌ョ殑姝e父搴撲綅鍒楄〃锛堝凡閫氳繃 isInNormalRule 杩囨护锛�
      * @return true = 鍓嶆柟鏈夊牭濉烇紙闇�瑕佽ˉ榻愶級锛宖alse = 鍓嶆柟娓呯┖鎴栨棤闇�妫�鏌�
@@ -283,11 +285,25 @@
         if (normalMasts == null || normalMasts.isEmpty()) {
             return false;
         }
-        // 鑾峰彇鍑哄簱鍒嗙粍閰嶇疆锛堢敤浜庣‘璁よ鍒欒寖鍥达級
+
+        // 鑾峰彇鍑哄簱鍒嗙粍閰嶇疆
         List<LocGroupOrder> locGroupAscOrder = slaveProperties.getLocGroupAscOrder();
         if (locGroupAscOrder == null || locGroupAscOrder.isEmpty()) {
             return false; // 鏃犻厤缃椂榛樿涓嶆鏌�
         }
+
+        // 鍋囪鎵�鏈� normalMasts 鍦ㄥ悓涓�涓垎缁勶紙甯歌鎯呭喌锛岃嫢澶氬垎缁勫彲寰幆澶勭悊锛�
+        LocMast representative = normalMasts.get(0);
+        LocGroupOrder group = locGroupAscOrder.stream()
+                .filter(g -> g.getRowList() != null && g.getRowList().contains(representative.getRow1()))
+                .findFirst()
+                .orElse(null);
+
+        if (group == null || group.getRowList() == null || group.getRowList().isEmpty()) {
+            return false; // 涓嶅湪浠讳綍鍒嗙粍锛屼笉妫�鏌�
+        }
+
+        List<Integer> fullRows = group.getRowList(); // 鍒嗙粍鍐呮墍鏈夋帓鍙峰垪琛紙鎸夊嚭搴撻『搴忔帓鍒楋級
 
         // 閬嶅巻姣忎釜姝e父搴撲綅
         for (LocMast lm : normalMasts) {
@@ -299,10 +315,17 @@
                 continue;
             }
 
-            // 娣卞簱浣嶆鏌ユ柟鍚戯細鍋囪 row 瓒婂ぇ瓒婃繁锛堝墠鏂规槸鏇村ぇ row 鐨勪綅缃級
-            // 浣犲彲浠ユ牴鎹疄闄呭嚭搴撴柟鍚戣皟鏁村惊鐜潯浠讹紙渚嬪浠庡皬 row 鍒板ぇ row 鎴栧弽涔嬶級
-            for (int row = currentRow + 1; row <= 5; row++) { // 鍋囪娣卞簱浣嶈寖鍥村埌 5 鎺掞紝鍙皟鏁�
-                LocMast front = getLocMastByRow(row, bay1, lev1);
+            // 鍦ㄥ垎缁� rowList 涓壘鍒板綋鍓嶆帓鐨勭储寮�
+            int currentIndex = fullRows.indexOf(currentRow);
+            if (currentIndex < 0) {
+                continue; // 褰撳墠鎺掍笉鍦ㄥ垎缁勫唴锛岃烦杩�
+            }
+
+            // 鍓嶆柟 = 鍒嗙粍涓储寮曟洿澶х殑浣嶇疆锛堝亣璁惧垎缁� rowList 浠庡墠鍒板悗鎺掑垪锛屽ぇ绱㈠紩 = 鏇存繁锛�
+            // 濡傛灉浣犵殑鍒嗙粍鍒楄〃鏄�掑簭鐨勶紙浠庡悗鍒板墠锛夛紝鍒欓渶鏀逛负 currentIndex - 1 鍒� 0
+            for (int i = currentIndex + 1; i < fullRows.size(); i++) {
+                Integer frontRow = fullRows.get(i);
+                LocMast front = getLocMastByRow(frontRow, bay1, lev1);
                 if (front == null) {
                     continue;
                 }
@@ -312,12 +335,12 @@
                     return true;
                 }
 
-                // 鏈夊叆搴撲换鍔� 鈫� 鍫靛
                 WrkMast frontTask = wrkMastService.selectOne(
                         new EntityWrapper<WrkMast>()
                                 .eq("source_loc_no", front.getLocNo())
-                                .eq("io_type", 100) // 鍋囪 100 涓哄叆搴撶被鍨嬶紝鍙皟鏁�
+                                .in("loc_sts", Arrays.asList("S", "Q")) // 鏀寔 loc_sts 涓� S 鎴� Q
                 );
+
                 if (frontTask != null) {
                     return true;
                 }
diff --git a/src/main/java/com/zy/common/CodeBuilder.java b/src/main/java/com/zy/common/CodeBuilder.java
index 8b6805a..fae63f4 100644
--- a/src/main/java/com/zy/common/CodeBuilder.java
+++ b/src/main/java/com/zy/common/CodeBuilder.java
@@ -17,10 +17,10 @@
 //        generator.table="sys_host";
         // sqlserver
         generator.sqlOsType = SqlOsType.SQL_SERVER;
-        generator.url="192.168.4.15:1433;databasename=source";
+        generator.url="localhost:1433;databasename=arydasrs";
         generator.username="sa";
         generator.password="sa@123";
-        generator.table="asr_wrk_mast_four_war_vehicle_log";
+        generator.table="man_area";
         generator.packagePath="com.zy.asrs";
         generator.build();
     }
diff --git a/src/main/resources/license.lic b/src/main/resources/license.lic
index 5b2a1f1..66b3cbb 100644
--- a/src/main/resources/license.lic
+++ b/src/main/resources/license.lic
Binary files differ
diff --git a/src/main/resources/license2.lic b/src/main/resources/license2.lic
new file mode 100644
index 0000000..5b2a1f1
--- /dev/null
+++ b/src/main/resources/license2.lic
Binary files differ
diff --git a/src/main/resources/mapper/AreaMapper.xml b/src/main/resources/mapper/AreaMapper.xml
new file mode 100644
index 0000000..26eb35f
--- /dev/null
+++ b/src/main/resources/mapper/AreaMapper.xml
@@ -0,0 +1,18 @@
+<?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.zy.asrs.mapper.AreaMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.zy.asrs.entity.Area">
+        <result column="id" property="id" />
+        <result column="tag_id" property="tagId" />
+        <result column="area_id" property="areaId" />
+        <result column="area_name" property="areaName" />
+        <result column="memo" property="memo" />
+        <result column="backup1" property="backup1" />
+        <result column="backup2" property="backup2" />
+        <result column="backup3" property="backup3" />
+
+    </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/MatMapper.xml b/src/main/resources/mapper/MatMapper.xml
index b7157a6..efa94b7 100644
--- a/src/main/resources/mapper/MatMapper.xml
+++ b/src/main/resources/mapper/MatMapper.xml
@@ -44,6 +44,7 @@
         <result column="memo" property="memo" />
 
         <result column="stock" property="stock" />
+        <result column="area_id" property="areaId"/>
     </resultMap>
 
     <select id="listByPage" resultMap="BaseResultMap">
diff --git a/src/main/webapp/static/js/area/area.js b/src/main/webapp/static/js/area/area.js
new file mode 100644
index 0000000..d513630
--- /dev/null
+++ b/src/main/webapp/static/js/area/area.js
@@ -0,0 +1,252 @@
+var pageCurr;
+layui.config({
+    base: baseUrl + "/static/layui/lay/modules/"
+}).use(['table','laydate', 'form', 'admin'], function(){
+    var table = layui.table;
+    var $ = layui.jquery;
+    var layer = layui.layer;
+    var layDate = layui.laydate;
+    var form = layui.form;
+    var admin = layui.admin;
+
+    // 鏁版嵁娓叉煋
+    tableIns = table.render({
+        elem: '#area',
+        headers: {token: localStorage.getItem('token')},
+        url: baseUrl+'/area/list/auth',
+        page: true,
+        limit: 15,
+        limits: [15, 30, 50, 100, 200, 500],
+        toolbar: '#toolbar',
+        cellMinWidth: 50,
+        height: 'full-120',
+        cols: [[
+            {type: 'checkbox'}
+            // ,{field: 'id', align: 'center',title: 'ID'}
+            // ,{field: 'tagId', align: 'center',title: ''}
+            ,{field: 'areaId', align: 'center',title: '搴撳尯缂栧彿'}
+            ,{field: 'areaName', align: 'center',title: '搴撳尯鍚嶇О'}
+            ,{field: 'memo', align: 'center',title: '搴撳尯澶囨敞'}
+            // ,{field: 'backup1', align: 'center',title: '澶囩敤瀛楁'}
+            // ,{field: 'backup2', align: 'center',title: '澶囩敤瀛楁2'}
+            // ,{field: 'backup3', align: 'center',title: '澶囩敤瀛楁3'}
+
+            ,{fixed: 'right', title:'鎿嶄綔', align: 'center', toolbar: '#operate', width:120}
+        ]],
+        request: {
+            pageName: 'curr',
+            pageSize: 'limit'
+        },
+        parseData: function (res) {
+            return {
+                'code': res.code,
+                'msg': res.msg,
+                'count': res.data.total,
+                'data': res.data.records
+            }
+        },
+        response: {
+            statusCode: 200
+        },
+        done: function(res, curr, count) {
+            if (res.code === 403) {
+                top.location.href = baseUrl+"/";
+            }
+            pageCurr=curr;
+            limit();
+        }
+    });
+
+    // 鐩戝惉鎺掑簭浜嬩欢
+    table.on('sort(area)', function (obj) {
+        var searchData = {};
+        $.each($('#search-box [name]').serializeArray(), function() {
+            searchData[this.name] = this.value;
+        });
+        searchData['orderByField'] = obj.field;
+        searchData['orderByType'] = obj.type;
+        tableIns.reload({
+            where: searchData,
+            page: {curr: 1}
+        });
+    });
+
+    // 鐩戝惉澶村伐鍏锋爮浜嬩欢
+    table.on('toolbar(area)', function (obj) {
+        var checkStatus = table.checkStatus(obj.config.id).data;
+        switch(obj.event) {
+            case 'addData':
+                showEditModel();
+                break;
+            case 'deleteData':
+               if (checkStatus.length === 0) {
+                   layer.msg('璇烽�夋嫨瑕佸垹闄ょ殑鏁版嵁', {icon: 2});
+                   return;
+               }
+               del(checkStatus.map(function (d) {
+                   return d.id;
+               }));
+               break;
+            case 'exportData':
+                admin.confirm('纭畾瀵煎嚭Excel鍚�', {shadeClose: true}, function(){
+                    var titles=[];
+                    var fields=[];
+                    obj.config.cols[0].map(function (col) {
+                        if (col.type === 'normal' && col.hide === false && col.toolbar == null) {
+                            titles.push(col.title);
+                            fields.push(col.field);
+                        }
+                    });
+                    var exportData = {};
+                    $.each($('#search-box [name]').serializeArray(), function() {
+                        exportData[this.name] = this.value;
+                    });
+                    var param = {
+                        'area': exportData,
+                        'fields': fields
+                    };
+                    $.ajax({
+                        url: baseUrl+"/area/export/auth",
+                        headers: {'token': localStorage.getItem('token')},
+                        data: JSON.stringify(param),
+                        dataType:'json',
+                        contentType:'application/json;charset=UTF-8',
+                        method: 'POST',
+                        success: function (res) {
+                            layer.closeAll();
+                            if (res.code === 200) {
+                                table.exportFile(titles,res.data,'xls');
+                            } else if (res.code === 403) {
+                                top.location.href = baseUrl+"/";
+                            } else {
+                                layer.msg(res.msg, {icon: 2})
+                            }
+                        }
+                    });
+                });
+                break;
+        }
+    });
+
+    // 鐩戝惉琛屽伐鍏蜂簨浠�
+    table.on('tool(area)', function(obj){
+        var data = obj.data;
+        switch (obj.event) {
+            case 'edit':
+                showEditModel(data);
+                break;
+            case "del":
+                del([data.id]);
+                break;
+        }
+    });
+
+    /* 寮圭獥 - 鏂板銆佷慨鏀� */
+    function showEditModel(mData) {
+        admin.open({
+            type: 1,
+            area: '600px',
+            title: (mData ? '淇敼' : '娣诲姞') + '璁㈠崟鐘舵��',
+            content: $('#editDialog').html(),
+            success: function (layero, dIndex) {
+                layDateRender(mData);
+                form.val('detail', mData);
+                form.on('submit(editSubmit)', function (data) {
+                    var loadIndex = layer.load(2);
+                    $.ajax({
+                        url: baseUrl+"/area/"+(mData?'update':'add')+"/auth",
+                        headers: {'token': localStorage.getItem('token')},
+                        data: data.field,
+                        method: 'POST',
+                        success: function (res) {
+                            layer.close(loadIndex);
+                            if (res.code === 200){
+                                layer.close(dIndex);
+                                layer.msg(res.msg, {icon: 1});
+                                tableReload();
+                            } else if (res.code === 403){
+                                top.location.href = baseUrl+"/";
+                            }else {
+                                layer.msg(res.msg, {icon: 2});
+                            }
+                        }
+                    })
+                    return false;
+                });
+                $(layero).children('.layui-layer-content').css('overflow', 'visible');
+                layui.form.render('select');
+            }
+        });
+    }
+
+    /* 鍒犻櫎 */
+    function del(ids) {
+        layer.confirm('纭畾瑕佸垹闄ら�変腑鏁版嵁鍚楋紵', {
+            skin: 'layui-layer-admin',
+            shade: .1
+        }, function (i) {
+            layer.close(i);
+            var loadIndex = layer.load(2);
+            $.ajax({
+                url: baseUrl+"/area/delete/auth",
+                headers: {'token': localStorage.getItem('token')},
+                data: {ids: ids},
+                method: 'POST',
+                success: function (res) {
+                    layer.close(loadIndex);
+                    if (res.code === 200){
+                        layer.msg(res.msg, {icon: 1});
+                        tableReload();
+                    } else if (res.code === 403){
+                        top.location.href = baseUrl+"/";
+                    } else {
+                        layer.msg(res.msg, {icon: 2});
+                    }
+                }
+            })
+        });
+    }
+
+    // 鎼滅储
+    form.on('submit(search)', function (data) {
+        pageCurr = 1;
+        tableReload(false);
+    });
+
+    // 閲嶇疆
+    form.on('submit(reset)', function (data) {
+        pageCurr = 1;
+        clearFormVal($('#search-box'));
+        tableReload(false);
+    });
+
+    // 鏃堕棿閫夋嫨鍣�
+    function layDateRender(data) {
+        setTimeout(function () {
+            layDate.render({
+                elem: '.layui-laydate-range'
+                ,type: 'datetime'
+                ,range: true
+            });
+
+        }, 300);
+    }
+    layDateRender();
+
+});
+
+// 鍏抽棴鍔ㄤ綔
+$(document).on('click','#data-detail-close', function () {
+    parent.layer.closeAll();
+});
+
+function tableReload(child) {
+    var searchData = {};
+    $.each($('#search-box [name]').serializeArray(), function() {
+        searchData[this.name] = this.value;
+    });
+    tableIns.reload({
+        where: searchData,
+        page: {curr: pageCurr}
+     });
+}
diff --git a/src/main/webapp/static/js/mat/mat.js b/src/main/webapp/static/js/mat/mat.js
index 2805440..addc55e 100644
--- a/src/main/webapp/static/js/mat/mat.js
+++ b/src/main/webapp/static/js/mat/mat.js
@@ -8,6 +8,8 @@
         ,{field: 'store_max', align: 'center',title: '搴撳瓨涓婇檺'}
         ,{field: 'store_min', align: 'center',title: '搴撳瓨涓嬮檺'}
         ,{field: 'store_max_date', align: 'center',title: '搴撻緞涓婇檺(澶�)'}
+        ,{field: 'areaId$', align: 'center',title: '鍖哄煙', templet: '#areaTpl'}
+
     ];
     cols.push.apply(cols, matCols);
     cols.push(
@@ -29,6 +31,31 @@
     admin = layui.admin;
     var treeTable = layui.treeTable;
     var xmSelect = layui.xmSelect;
+
+    // 鍖哄煙鏁版嵁
+    var areaData = [];
+    
+    // 鍔犺浇鍖哄煙鏁版嵁
+    $.ajax({
+        url: baseUrl+'/area/list/auth',
+        headers: {token: localStorage.getItem('token')},
+        method: 'GET',
+        async: false,
+        success: function (res) {
+            if (res.code === 200 && res.data && res.data.records) {
+                // 杩囨护鎺夌┖鍊�
+                areaData = res.data.records.filter(function(item) {
+                    return item != null && item.areaId != null;
+                });
+                console.log('鍖哄煙鏁版嵁鍔犺浇鎴愬姛:', areaData);
+            } else {
+                console.error('鍖哄煙鏁版嵁鍔犺浇澶辫触:', res);
+            }
+        },
+        error: function(err) {
+            console.error('鍖哄煙鏁版嵁璇锋眰澶辫触:', err);
+        }
+    });
 
     // 鍟嗗搧鍒嗙被鏁版嵁
     var insTb = treeTable.render({
@@ -253,13 +280,14 @@
                 // 鏂板鑷姩鐢熸垚鍟嗗搧缂栧彿
                 if (!mData) {
                     http.get(baseUrl + "/mat/auto/matnr/auth", null, function (res) {
-                        $('#matnr').val(res.data);
+                        $(layero).find('#matnr').val(res.data);
                     })
                 }
                 // 琛ㄥ崟鎻愪氦浜嬩欢
                 form.on('submit(editSubmit)', function (data) {
                     console.log(data)
                     data.field.tagId = insXmSel.getValue('valueStr');
+                    data.field.areaId = areaXmSel.getValue('valueStr');
                     if (isEmpty(data.field.tagId)) {
                         layer.msg('鍒嗙被涓嶈兘涓虹┖', {icon: 2});
                         return false;
@@ -287,7 +315,7 @@
                 });
                 // 娓叉煋涓嬫媺鏍�
                 var insXmSel = xmSelect.render({
-                    el: '#tagSel',
+                    el: $(layero).find('#tagSel')[0],
                     height: '250px',
                     data: insTb.options.data,
                     initValue: mData ? [mData.tagId] : [],
@@ -305,6 +333,26 @@
                         expandedKeys: true
                     }
                 });
+                // 娓叉煋鍖哄煙涓嬫媺閫夋嫨
+                console.log('鍑嗗娓叉煋鍖哄煙閫夋嫨鍣紝鏁版嵁:', areaData);
+                console.log('褰撳墠鍟嗗搧鏁版嵁:', mData);
+                var areaXmSel = xmSelect.render({
+                    el: $(layero).find('#areaSel')[0],
+                    height: '250px',
+                    data: areaData.length > 0 ? areaData : [],
+                    initValue: mData && mData.areaId ? [mData.areaId] : [],
+                    model: {label: {type: 'text'}},
+                    prop: {
+                        name: 'areaName',
+                        value: 'areaId'
+                    },
+                    radio: true,
+                    clickClose: true,
+                    on: function(data) {
+                        console.log('鍖哄煙閫夋嫨鍣ㄤ簨浠�:', data);
+                    }
+                });
+                console.log('鍖哄煙閫夋嫨鍣ㄦ覆鏌撳畬鎴�');
                 // 寮圭獥涓嶅嚭鐜版粴鍔ㄦ潯
                 $(layero).children('.layui-layer-content').css('overflow', 'visible');
                 layui.form.render('select');
diff --git a/src/main/webapp/static/js/report/locMap.js b/src/main/webapp/static/js/report/locMap.js
index 205cd7d..58b6171 100644
--- a/src/main/webapp/static/js/report/locMap.js
+++ b/src/main/webapp/static/js/report/locMap.js
@@ -2,11 +2,102 @@
     var $ = layui.jquery;
     var layer = layui.layer;
     var form = layui.form;
+    var areaMap = {};
+
+    // Handlebars helper for area color
+    Handlebars.registerHelper('getAreaColor', function(areaId) {
+        if (areaId && areaMap[areaId] && areaMap[areaId].color) {
+            return areaMap[areaId].color;
+        }
+        return 'transparent';
+    });
 
     // 鍒濆鍔犺浇
+    loadAreas();             // 鍔犺浇搴撳尯棰滆壊淇℃伅
     loadRowsOptions();       // 鍔犺浇銆屾帓銆嶉�夐」锛堝缁堥渶瑕侊級
     loadLayersOptions();     // 鍔犺浇銆屽眰銆嶉�夐」锛堟彁鍓嶅噯澶囷級
     getLocTable('byRow', 1); // 榛樿鎸夋帓 + 绗�1鎺�
+
+    // 鍔犺浇搴撳尯淇℃伅骞舵樉绀哄浘渚�
+    function loadAreas() {
+        $.ajax({
+            url: baseUrl + '/area/list/auth?page=1&limit=1000',
+            headers: {'token': localStorage.getItem('token')},
+            async: false,
+            success: function(res) {
+                if (res.code === 200) {
+                    areaMap = {};
+                    var legendHtml = '<div class="area-legend-item" style="cursor:default;font-weight:bold;">搴撳尯鍥句緥:</div>';
+                    // 榛樿棰滆壊鍒楄〃锛岀敤浜庤嚜鍔ㄥ垎閰�
+                    var defaultColors = ['#FF5733', '#33FF57', '#3357FF', '#FF33A1', '#A133FF', '#33FFF5', '#FFD700', '#FF8C00'];
+                    var colorIndex = 0;
+
+                    res.data.records.forEach(function(area) {
+                        var color = area.backup1;
+                        // 澧炲己棰滆壊鏍¢獙锛氬鏋滀负绌恒�乶ull瀛楃涓叉垨闀垮害杩囩煭锛屽垯瑙嗕负鏃犳晥
+                        if (!color || color === 'null' || color.trim().length < 3) {
+                            color = defaultColors[colorIndex % defaultColors.length];
+                            colorIndex++;
+                        }
+                        areaMap[area.id] = {name: area.areaName, color: color, fullArea: area};
+                        legendHtml += '<div class="area-legend-item" onclick="editAreaColor(\'' + area.id + '\')"><span class="area-color-box" style="background-color:' + color + '"></span>' + area.areaName + '</div>';
+                    });
+                    $('#areaLegend').html(legendHtml).show();
+                }
+            }
+        });
+    }
+
+    // 缂栬緫搴撳尯棰滆壊
+    window.editAreaColor = function(areaId) {
+        if (!areaId || !areaMap[areaId]) return;
+        var areaData = areaMap[areaId];
+        
+        var contentHtml = '<div style="padding: 20px;"><form class="layui-form">' +
+            '<div class="layui-form-item">' +
+            '<label class="layui-form-label" style="width: auto; padding-left: 0;">搴撳尯鍚嶇О:</label>' +
+            '<div class="layui-input-inline" style="line-height: 45px;">' + areaData.name + '</div>' +
+            '</div>' +
+            '<div class="layui-form-item">' +
+            '<label class="layui-form-label" style="width: auto; padding-left: 0;">閫夋嫨棰滆壊</label>' +
+            '<div class="layui-input-inline"><input type="color" id="singleAreaColorPicker" value="' + (areaData.color || '#cccccc') + '" style="height: 38px; width: 100%;"></div>' +
+            '</div>' +
+            '</form></div>';
+
+        layer.open({
+            type: 1,
+            title: '淇敼搴撳尯棰滆壊',
+            area: ['350px', '250px'],
+            content: contentHtml,
+            btn: ['淇濆瓨', '鍙栨秷'],
+            yes: function(index) {
+                var newColor = $('#singleAreaColorPicker').val();
+                if (newColor !== areaData.color) {
+                    $.ajax({
+                        url: baseUrl + '/area/update/auth',
+                        method: 'POST',
+                        headers: {'token': localStorage.getItem('token')},
+                        data: { id: areaId, backup1: newColor },
+                        success: function(res) {
+                            if (res.code === 200) {
+                                layer.msg('棰滆壊宸叉洿鏂�');
+                                layer.close(index);
+                                loadAreas(); // 鍒锋柊鍥句緥鍜岀紦瀛�
+                                // 鍒锋柊鍦板浘浠ュ簲鐢ㄦ柊棰滆壊
+                                var mode = $('#viewMode').val();
+                                if (mode === 'byRow') getLocTable('byRow', $('#rowSelect').val());
+                                else getLocTable('byLayer', $('#layerSelect').val());
+                            } else {
+                                layer.msg(res.msg || '鏇存柊澶辫触');
+                            }
+                        }
+                    });
+                } else {
+                    layer.close(index);
+                }
+            }
+        });
+    };
 
     // 鍔犺浇鎵�鏈夊彲鐢ㄦ帓
     function loadRowsOptions() {
@@ -31,13 +122,13 @@
     // 鍔犺浇鎵�鏈夊彲鐢ㄥ眰锛堥渶瑕佸悗绔敮鎸佹柊鎺ュ彛锛�
     function loadLayersOptions() {
         $.ajax({
-            url: baseUrl + "/report/viewLocMapList/layers.action",  // 鈫� 闇�瑕佹柊澧炴帴鍙�
+            url: baseUrl + "/report/viewLocMapList/layers.action",  
             headers: {'token': localStorage.getItem('token')},
             method: 'POST',
             async: false,
             success: function (res) {
                 if (res.code === 200) {
-                    var tpl = $("#locMastRowTemplate").html(); // 澶嶇敤妯℃澘
+                    var tpl = $("#locMastRowTemplate").html(); 
                     var template = Handlebars.compile(tpl);
                     $('#layerSelect').append(template(res));
                     form.render('select');
@@ -106,4 +197,232 @@
             getLocTable('byLayer', data.value);
         }
     });
+
+    // --- 妗嗛�夊姛鑳� ---
+    var isSelectionMode = false;
+    var isDragging = false;
+    var startX, startY;
+    var $selectionBox = $('#selectionBox');
+    var $container = $('#locMapContain');
+
+    $('#btnSelectMode').click(function () {
+        isSelectionMode = !isSelectionMode;
+        if (isSelectionMode) {
+            $(this).text('鍏抽棴妗嗛��').addClass('layui-btn-danger').removeClass('layui-btn-normal');
+            // 绂佺敤鍘熸湁鐐瑰嚮浜嬩欢锛岄槻姝㈠啿绐� (閫氳繃 CSS pointer-events 鎴栫Щ闄� onclick)
+            // 杩欓噷閫夋嫨绉婚櫎 onclick 灞炴��
+            $('.a-loc').each(function(){
+                $(this).attr('data-onclick', $(this).attr('onclick')).removeAttr('onclick');
+            });
+            layer.msg('宸插紑鍚閫夋ā寮忥紝璇峰湪搴撲綅鍥句笂鎷栨嫿閫夋嫨');
+        } else {
+            $(this).text('寮�鍚閫�').addClass('layui-btn-normal').removeClass('layui-btn-danger');
+            $('.loc-selected').removeClass('loc-selected');
+            $('#btnAssignZone').hide();
+            // 鎭㈠鐐瑰嚮浜嬩欢
+            $('.a-loc').each(function(){
+                if($(this).attr('data-onclick')) {
+                    $(this).attr('onclick', $(this).attr('data-onclick'));
+                }
+            });
+        }
+    });
+
+    $container.on('mousedown', function (e) {
+        if (!isSelectionMode) return;
+        // 濡傛灉鐐瑰湪婊氬姩鏉′笂锛屽彲鑳戒篃浼氳Е鍙戯紝绠�鍗曞垽鏂洰鏍囨槸鍚︽槸 container 鎴� table
+        if(e.target.tagName !== 'TD' && e.target.id !== 'locMapContain' && e.target.tagName !== 'TABLE' && e.target.tagName !== 'TBODY' && e.target.tagName !== 'TR') return;
+
+        isDragging = true;
+        var offset = $container.offset();
+        // 鐩稿浜� container 鍐呭鐨勫潗鏍� (鍖呭惈婊氬姩)
+        startX = e.pageX - offset.left + $container.scrollLeft();
+        startY = e.pageY - offset.top + $container.scrollTop();
+        
+        $selectionBox.css({
+            left: startX,
+            top: startY,
+            width: 0,
+            height: 0,
+            display: 'block'
+        });
+        
+        // 闃绘榛樿鏂囨湰閫夋嫨
+        e.preventDefault();
+    });
+
+    $container.on('mousemove', function (e) {
+        if (!isSelectionMode || !isDragging) return;
+        var offset = $container.offset();
+        var currentX = e.pageX - offset.left + $container.scrollLeft();
+        var currentY = e.pageY - offset.top + $container.scrollTop();
+
+        var width = Math.abs(currentX - startX);
+        var height = Math.abs(currentY - startY);
+        var left = Math.min(currentX, startX);
+        var top = Math.min(currentY, startY);
+
+        $selectionBox.css({
+            width: width,
+            height: height,
+            left: left,
+            top: top
+        });
+    });
+
+    $(document).on('mouseup', function (e) {
+        if (!isSelectionMode || !isDragging) return;
+        isDragging = false;
+        $selectionBox.hide();
+
+        // 璁$畻妗嗛�夊尯鍩� (鐩稿浜庤鍙o紝鐢ㄤ簬 getBoundingClientRect 姣旇緝)
+        // 鎴栬�呴兘杞崲涓虹浉瀵逛簬 container 鐨勫潗鏍�
+        // 杩欓噷浣跨敤鐩稿浜� container 鐨勫潗鏍囨瘮杈冩洿绋冲Ε
+        
+        var boxLeft = parseFloat($selectionBox.css('left'));
+        var boxTop = parseFloat($selectionBox.css('top'));
+        var boxWidth = parseFloat($selectionBox.css('width'));
+        var boxHeight = parseFloat($selectionBox.css('height'));
+        var boxRight = boxLeft + boxWidth;
+        var boxBottom = boxTop + boxHeight;
+
+        // 鑾峰彇 container 鐨� offset
+        var containerOffset = $container.offset();
+
+        $('.a-loc').each(function () {
+            var $el = $(this);
+            var elOffset = $el.offset();
+            // 杞崲涓虹浉瀵逛簬 container 鐨勫潗鏍� (鍔犱笂 scroll)
+            var elLeft = elOffset.left - containerOffset.left + $container.scrollLeft();
+            var elTop = elOffset.top - containerOffset.top + $container.scrollTop();
+            var elWidth = $el.outerWidth();
+            var elHeight = $el.outerHeight();
+            var elRight = elLeft + elWidth;
+            var elBottom = elTop + elHeight;
+
+            // 纰版挒妫�娴�
+            if (!(elLeft > boxRight || elRight < boxLeft || elTop > boxBottom || elBottom < boxTop)) {
+                $el.toggleClass('loc-selected');
+            }
+        });
+
+        if ($('.loc-selected').length > 0) {
+            $('#btnAssignZone').show().text('鍒嗛厤搴撳尯 (' + $('.loc-selected').length + ')');
+        } else {
+            $('#btnAssignZone').hide();
+        }
+    });
+
+    // --- 鍒嗛厤搴撳尯 ---
+    $('#btnAssignZone').click(function () {
+        var selectedLocs = [];
+        $('.loc-selected').each(function () {
+            selectedLocs.push($(this).attr('title')); // title has locNo
+        });
+
+        if (selectedLocs.length === 0) return;
+
+        // 鑾峰彇搴撳尯鍒楄〃
+        $.ajax({
+            url: baseUrl + '/area/list/auth?page=1&limit=1000',
+            headers: {'token': localStorage.getItem('token')},
+            success: function(listRes) {
+                if (listRes.code === 200) {
+                        var optionsHtml = '<option value="">璇烽�夋嫨搴撳尯</option>';
+                        var areas = listRes.data.records;
+                        areas.forEach(function(area) {
+                            optionsHtml += '<option value="' + area.id + '">' + area.areaName + ' (' + area.areaId + ')</option>';
+                        });
+                        
+                        var contentHtml = '<div style="padding: 20px;"><form class="layui-form">' +
+                            '<div class="layui-form-item"><select id="selectArea" lay-filter="selectArea">' + optionsHtml + '</select></div>' +
+                            '<div class="layui-form-item">' +
+                            '<label class="layui-form-label" style="width: auto; padding-left: 0;">搴撳尯棰滆壊</label>' +
+                            '<div class="layui-input-inline"><input type="color" id="areaColorPicker" value="#cccccc" style="height: 38px; width: 100%;"></div>' +
+                            '</div>' +
+                            '</form></div>';
+
+                        layer.open({
+                            type: 1,
+                            title: '鍒嗛厤搴撳尯鍙婇鑹�',
+                            area: ['400px', '350px'],
+                            content: contentHtml,
+                            btn: ['纭畾', '鍙栨秷'],
+                            success: function(layero, index) {
+                                form.render('select');
+                                form.on('select(selectArea)', function(data){
+                                    var areaId = data.value;
+                                    if(areaId && areaMap[areaId]) {
+                                        $('#areaColorPicker').val(areaMap[areaId].color || '#cccccc');
+                                    }
+                                });
+                            },
+                            yes: function(index) {
+                                var areaId = $('#selectArea').val();
+                                var newColor = $('#areaColorPicker').val();
+
+                                if (!areaId) {
+                                    layer.msg('璇烽�夋嫨搴撳尯');
+                                    return;
+                                }
+
+                                // 1. 鏇存柊搴撳尯棰滆壊 (濡傛灉鏈夊彉鍖�)
+                                if (areaMap[areaId] && areaMap[areaId].color !== newColor) {
+                                    $.ajax({
+                                        url: baseUrl + '/area/update/auth',
+                                        method: 'POST',
+                                        headers: {'token': localStorage.getItem('token')},
+                                        data: { id: areaId, backup1: newColor },
+                                        async: false, // 鍚屾鏇存柊浠ョ‘淇濆埛鏂版椂棰滆壊姝g‘
+                                        success: function() {
+                                            loadAreas(); // 鍒锋柊鍥句緥鍜岀紦瀛�
+                                        }
+                                    });
+                                }
+                                
+                                // 2. 鎵归噺鏇存柊搴撲綅
+                                $.ajax({
+                                    url: baseUrl + '/locMast/batchUpdateArea/auth',
+                                    method: 'POST',
+                                    headers: {'token': localStorage.getItem('token')},
+                                    contentType: 'application/json',
+                                    data: JSON.stringify({
+                                        locNos: selectedLocs,
+                                        areaId: parseInt(areaId)
+                                    }),
+                                    success: function(updRes) {
+                                        if (updRes.code === 200) {
+                                            layer.msg('鍒嗛厤鎴愬姛');
+                                            layer.close(index);
+                                            // 鍒锋柊
+                                            var mode = $('#viewMode').val();
+                                            if (mode === 'byRow') getLocTable('byRow', $('#rowSelect').val());
+                                            else getLocTable('byLayer', $('#layerSelect').val());
+                                            
+                                            // 閲嶇疆鐘舵��
+                                            $('.loc-selected').removeClass('loc-selected');
+                                            $('#btnAssignZone').hide();
+                                            // 淇濇寔妗嗛�夋ā寮�
+                                            if(isSelectionMode) {
+                                                // 閲嶆柊绉婚櫎onclick
+                                                setTimeout(function(){
+                                                    $('.a-loc').each(function(){
+                                                        $(this).attr('data-onclick', $(this).attr('onclick')).removeAttr('onclick');
+                                                    });
+                                                }, 500); // 绠�鍗曞欢鏃剁瓑寰呮覆鏌�
+                                            }
+                                        } else {
+                                            layer.msg(updRes.msg || '鎿嶄綔澶辫触');
+                                        }
+                                    }
+                                });
+                            }
+                        });
+                } else {
+                    layer.msg(listRes.msg || '鏃犳硶鑾峰彇搴撳尯鍒楄〃');
+                }
+            }
+        });
+    });
+
 });
\ No newline at end of file
diff --git a/src/main/webapp/views/area/area.html b/src/main/webapp/views/area/area.html
new file mode 100644
index 0000000..f440745
--- /dev/null
+++ b/src/main/webapp/views/area/area.html
@@ -0,0 +1,134 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title></title>
+    <meta name="renderer" content="webkit">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+    <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all">
+    <link rel="stylesheet" href="../../static/css/admin.css?v=318" media="all">
+    <link rel="stylesheet" href="../../static/css/cool.css" media="all">
+</head>
+<body>
+
+<div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-card-body">
+            <div class="layui-form toolbar" id="search-box">
+                <div class="layui-form-item">
+                    <div class="layui-inline">
+                        <div class="layui-input-inline">
+                            <input class="layui-input" type="text" name="id" placeholder="缂栧彿" autocomplete="off">
+                        </div>
+                    </div>
+                     <div class="layui-inline" style="width: 300px">
+                        <div class="layui-input-inline">
+                            <input class="layui-input layui-laydate-range" name="create_time" type="text" placeholder="璧峰鏃堕棿 - 缁堟鏃堕棿" autocomplete="off" style="width: 300px">
+                        </div>
+                    </div>
+                    <div class="layui-inline">
+                        <div class="layui-input-inline">
+                            <input class="layui-input" type="text" name="condition" placeholder="璇疯緭鍏�" autocomplete="off">
+                        </div>
+                    </div>
+                    <div class="layui-inline">&emsp;
+                        <button class="layui-btn icon-btn" lay-filter="search" lay-submit>
+                            <i class="layui-icon">&#xe615;</i>鎼滅储
+                        </button>
+                        <button class="layui-btn icon-btn" lay-filter="reset" lay-submit>
+                            <i class="layui-icon">&#xe666;</i>閲嶇疆
+                        </button>
+                    </div>
+                </div>
+            </div>
+            <table class="layui-hide" id="area" lay-filter="area"></table>
+        </div>
+    </div>
+</div>
+
+<script type="text/html" id="toolbar">
+    <div class="layui-btn-container">
+        <button class="layui-btn layui-btn-sm" id="btn-add" lay-event="addData">鏂板</button>
+        <button class="layui-btn layui-btn-sm layui-btn-danger" id="btn-delete" lay-event="deleteData">鍒犻櫎</button>
+        <button class="layui-btn layui-btn-primary layui-btn-sm" id="btn-export" lay-event="exportData" style="float: right">瀵煎嚭</button>
+    </div>
+</script>
+
+<script type="text/html" id="operate">
+    <a class="layui-btn layui-btn-primary layui-btn-xs btn-edit" lay-event="edit">淇敼</a>
+    <a class="layui-btn layui-btn-danger layui-btn-xs btn-edit" lay-event="del">鍒犻櫎</a>
+</script>
+
+<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
+<script type="text/javascript" src="../../static/layui/layui.js" charset="utf-8"></script>
+<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
+<script type="text/javascript" src="../../static/js/cool.js" charset="utf-8"></script>
+<script type="text/javascript" src="../../static/js/area/area.js" charset="utf-8"></script>
+</body>
+<!-- 琛ㄥ崟寮圭獥 -->
+<script type="text/html" id="editDialog">
+    <form id="detail" lay-filter="detail" class="layui-form admin-form model-form">
+        <input name="id" type="hidden">
+        <div class="layui-row">
+            <div class="layui-col-md12">
+<!--                <div class="layui-form-item">-->
+<!--                    <label class="layui-form-label layui-form-required">ID: </label>-->
+<!--                    <div class="layui-input-block">-->
+<!--                        <input class="layui-input" name="id" placeholder="璇疯緭鍏D" lay-vertype="tips" lay-verify="required">-->
+<!--                    </div>-->
+<!--                </div>-->
+<!--                <div class="layui-form-item">-->
+<!--                    <label class="layui-form-label layui-form-required">: </label>-->
+<!--                    <div class="layui-input-block">-->
+<!--                        <input class="layui-input" name="tagId" placeholder="璇疯緭鍏�" lay-vertype="tips" lay-verify="required">-->
+<!--                    </div>-->
+<!--                </div>-->
+                <div class="layui-form-item">
+                    <label class="layui-form-label layui-form-required">搴撳尯缂栧彿: </label>
+                    <div class="layui-input-block">
+                        <input class="layui-input" name="areaId" placeholder="璇疯緭鍏ュ簱鍖篿d" lay-vertype="tips" lay-verify="required">
+                    </div>
+                </div>
+                <div class="layui-form-item">
+                    <label class="layui-form-label">搴撳尯鍚嶇О: </label>
+                    <div class="layui-input-block">
+                        <input class="layui-input" name="areaName" placeholder="璇疯緭鍏ュ簱鍖哄悕绉�">
+                    </div>
+                </div>
+                <div class="layui-form-item">
+                    <label class="layui-form-label">搴撳尯澶囨敞: </label>
+                    <div class="layui-input-block">
+                        <input class="layui-input" name="memo" placeholder="璇疯緭鍏ュ簱鍖哄娉�">
+                    </div>
+                </div>
+<!--                <div class="layui-form-item">-->
+<!--                    <label class="layui-form-label">澶囩敤瀛楁-1: </label>-->
+<!--                    <div class="layui-input-block">-->
+<!--                        <input class="layui-input" name="backup1" placeholder="璇疯緭鍏ュ鐢ㄥ瓧娈�">-->
+<!--                    </div>-->
+<!--                </div>-->
+<!--                <div class="layui-form-item">-->
+<!--                    <label class="layui-form-label">澶囩敤瀛楁-2: </label>-->
+<!--                    <div class="layui-input-block">-->
+<!--                        <input class="layui-input" name="backup2" placeholder="璇疯緭鍏ュ鐢ㄥ瓧娈�2">-->
+<!--                    </div>-->
+<!--                </div>-->
+<!--                <div class="layui-form-item">-->
+<!--                    <label class="layui-form-label">澶囩敤瀛楁-3: </label>-->
+<!--                    <div class="layui-input-block">-->
+<!--                        <input class="layui-input" name="backup3" placeholder="璇疯緭鍏ュ鐢ㄥ瓧娈�3">-->
+<!--                    </div>-->
+<!--                </div>-->
+
+             </div>
+        </div>
+        <hr class="layui-bg-gray">
+        <div class="layui-form-item text-right">
+            <button class="layui-btn" lay-filter="editSubmit" lay-submit="">淇濆瓨</button>
+            <button class="layui-btn layui-btn-primary" type="button" ew-event="closeDialog">鍙栨秷</button>
+        </div>
+    </form>
+</script>
+</html>
+
diff --git a/src/main/webapp/views/mat/mat.html b/src/main/webapp/views/mat/mat.html
index 9577145..5b82fdd 100644
--- a/src/main/webapp/views/mat/mat.html
+++ b/src/main/webapp/views/mat/mat.html
@@ -123,6 +123,10 @@
     <span name="tagId" class="layui-badge layui-badge-gray">{{d.tagId$}}</span>
 </script>
 
+<script type="text/html" id="areaTpl">
+    <span name="areaId" class="layui-badge layui-badge-blue">{{d.areaId$}}</span>
+</script>
+
 <script type="text/html" id="toolbar">
     <div class="layui-btn-container">
         <button class="layui-btn layui-btn-sm" id="btn-print-batch" lay-event="btnPrintBatch">鎵归噺鎵撳嵃</button>
@@ -198,12 +202,12 @@
                     </div>
                 </div>
 
-                <div class="layui-form-item">
-                    <label class="layui-form-label">閰嶇疆</label>
-                    <div class="layui-input-block">
-                        <input name="specs" placeholder="璇疯緭鍏ラ厤缃�" class="layui-input">
-                    </div>
-                </div>
+<!--                <div class="layui-form-item">-->
+<!--                    <label class="layui-form-label">閰嶇疆</label>-->
+<!--                    <div class="layui-input-block">-->
+<!--                        <input name="specs" placeholder="璇疯緭鍏ラ厤缃�" class="layui-input">-->
+<!--                    </div>-->
+<!--                </div>-->
 
                 <div class="layui-form-item">
                     <label class="layui-form-label">鍗曠鍑�閲�</label>
@@ -213,15 +217,21 @@
                 </div>
 
                 <div class="layui-form-item">
-                    <label class="layui-form-label">鍗曠浣撶Н</label>
+                    <label class="layui-form-label">鍗曠姣涢噸</label>
                     <div class="layui-input-block">
-                        <input name="volume" placeholder="璇疯緭鍏ュ崟绠变綋绉�" class="layui-input">
+                        <input name="length" placeholder="璇疯緭鍏ュ崟绠辨瘺閲�" class="layui-input">
                     </div>
                 </div>
 
             </div>
 
             <div class="layui-col-md6">
+                <div class="layui-form-item">
+                    <label class="layui-form-label">鍖哄煙</label>
+                    <div class="layui-input-block">
+                        <div id="areaSel" class="ew-xmselect-tree"></div>
+                    </div>
+                </div>
                 <div class="layui-form-item">
                     <label class="layui-form-label layui-form-required">鍟嗗搧缂栧彿</label>
                     <div class="layui-input-block">
@@ -243,19 +253,13 @@
                     </div>
                 </div>
 
-                <div class="layui-form-item">
-                    <label class="layui-form-label">鍗曠姣涢噸</label>
-                    <div class="layui-input-block">
-                        <input name="length" placeholder="璇疯緭鍏ュ崟绠辨瘺閲�" class="layui-input">
-                    </div>
-                </div>
 
-                <div class="layui-form-item">
-                    <label class="layui-form-label">鍗曠浣撶Н</label>
-                    <div class="layui-input-block">
-                        <input name="threeCode" placeholder="璇疯緭鍏ョ瀛愬昂瀵�" class="layui-input">
-                    </div>
-                </div>
+<!--                <div class="layui-form-item">-->
+<!--                    <label class="layui-form-label">鍗曠浣撶Н</label>-->
+<!--                    <div class="layui-input-block">-->
+<!--                        <input name="threeCode" placeholder="璇疯緭鍏ョ瀛愬昂瀵�" class="layui-input">-->
+<!--                    </div>-->
+<!--                </div>-->
 
             </div>
         </div>
diff --git a/src/main/webapp/views/report/viewLocMap.html b/src/main/webapp/views/report/viewLocMap.html
index 34bcfcb..053aa99 100644
--- a/src/main/webapp/views/report/viewLocMap.html
+++ b/src/main/webapp/views/report/viewLocMap.html
@@ -13,7 +13,8 @@
         #locMapContain {
             overflow-x: auto;
             width:100%;
-            height:700px
+            height:700px;
+            position: relative;
         }
         .a-loc {
             cursor: pointer;
@@ -50,7 +51,32 @@
         .layui-table td:hover {
             opacity: 0.5;
         }
-</style>
+        .loc-selected {
+            border: 2px solid red !important;
+            box-shadow: 0 0 5px red;
+        }
+        #selectionBox {
+            position: absolute;
+            border: 1px dashed #009688;
+            background-color: rgba(0, 150, 136, 0.2);
+            display: none;
+            z-index: 1000;
+            pointer-events: none;
+        }
+        .area-legend-item {
+            display: inline-flex;
+            align-items: center;
+            margin-right: 15px;
+            font-size: 14px;
+            cursor: pointer;
+            padding: 2px 5px;
+            border-radius: 4px;
+            transition: background-color 0.2s;
+        }
+        .area-legend-item:hover {
+            background-color: #f0f0f0;
+        }
+    </style>
 </head>
 <body>
 <!-- 鎼滅储鏍� -->
@@ -82,9 +108,18 @@
             </select>
         </div>
     </div>
+
+    <div class="layui-inline" style="margin-left: 20px;">
+        <button class="layui-btn layui-btn-normal" id="btnSelectMode">寮�鍚閫�</button>
+        <button class="layui-btn layui-btn-warm" id="btnAssignZone" style="display:none;">鍒嗛厤搴撳尯</button>
+    </div>
+</div>
+<div id="areaLegend" style="padding: 5px 15px; background: #fff; border-bottom: 1px solid #eee; display:none;">
+    <!-- Legend items will be injected here -->
 </div>
 <div id="locMapContain">
     <table class="layui-table" id="locMap" lay-filter="locMap"></table>
+    <div id="selectionBox"></div>
 </div>
 <!-- 琛ㄦ牸 -->
 
@@ -102,7 +137,11 @@
         {{#each body}}
         <tr>
             {{#each loc}}
-                <td class="a-loc" title="{{locNo}}" onclick="locDetl(this)" style="background-color:{{bgc}};color:{{color}}">{{locSts}}</td>
+                <td class="a-loc" title="{{locNo}}" onclick="locDetl(this)" 
+                    style="background-color:{{bgc}};color:{{color}};position:relative;{{#if locType2}}box-shadow:inset 0 0 0 4px {{getAreaColor locType2}}{{/if}}">
+                    {{locSts}}
+                    {{#if locType2}}<div style="position:absolute;top:0;right:0;width:0;height:0;border-top:10px solid {{getAreaColor locType2}};border-left:10px solid transparent;"></div>{{/if}}
+                </td>
             {{/each}}
         </tr>
         {{/each}}

--
Gitblit v1.9.1