From 1f9454af3356f628c25c3e2e492869163731da56 Mon Sep 17 00:00:00 2001
From: puzhibing <393733352@qq.com>
Date: 星期五, 09 十月 2026 10:47:24 +0800
Subject: [PATCH] 修改bug
---
ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tSite/tSite_add.html | 7
ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/GaoDeMapUtil.java | 64 +
ManagementFBTravel/guns-admin/src/main/resources/application.yml | 2
ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/home.html | 9
ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TGaodeAccountServiceImpl.java | 28 +
ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tSite/tSite_edit.html | 7
ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/GDKeyMapper.java | 31 +
ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/GDMapElectricFenceUtil.java | 136 +++-
ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/GDKeyManager.java | 349 ++++++++++++
ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/general/TGaodeAccountController.java | 164 ++++++
ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/GDMapGeocodingUtil.java | 43 +
ManagementFBTravel/guns-admin/src/main/webapp/static/modular/system/tGaodeAccount/tGaodeAccount.js | 257 +++++++++
ManagementFBTravel/guns-admin/src/main/webapp/static/modular/system/tGaodeAccount/tGaodeAccount_info.js | 133 ++++
ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/TGaodeAccountMapper.java | 28 +
ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tGaodeAccount/tGaodeAccount.html | 58 ++
ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tGaodeAccount/tGaodeAccount_add.html | 32 +
ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tGaodeAccount/tGaodeAccount_edit.html | 32 +
ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/TGaodeAccountMapper.xml | 41 +
ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TGaodeAccount.java | 153 +++++
ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/ITGaodeAccountService.java | 24
20 files changed, 1,535 insertions(+), 63 deletions(-)
diff --git a/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/general/TGaodeAccountController.java b/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/general/TGaodeAccountController.java
new file mode 100644
index 0000000..17039a0
--- /dev/null
+++ b/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/general/TGaodeAccountController.java
@@ -0,0 +1,164 @@
+package com.stylefeng.guns.modular.system.controller.general;
+
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.baomidou.mybatisplus.plugins.Page;
+import com.stylefeng.guns.core.base.controller.BaseController;
+import com.stylefeng.guns.core.base.tips.ErrorTip;
+import com.stylefeng.guns.core.common.constant.factory.PageFactory;
+import com.stylefeng.guns.core.log.LogObjectHolder;
+import com.stylefeng.guns.core.shiro.ShiroKit;
+import com.stylefeng.guns.core.util.SinataUtil;
+import com.stylefeng.guns.modular.system.model.TGaodeAccount;
+import com.stylefeng.guns.modular.system.service.ITGaodeAccountService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * 高德地图账号控制器
+ *
+ * @author stylefeng
+ * @Date 2026-09-21
+ */
+@Controller
+@RequestMapping("/tGaodeAccount")
+public class TGaodeAccountController extends BaseController {
+
+ private String PREFIX = "/system/tGaodeAccount/";
+
+ @Autowired
+ private ITGaodeAccountService tGaodeAccountService;
+
+ /**
+ * 跳转到高德地图账号首页
+ */
+ @RequestMapping("")
+ public String index() {
+ return PREFIX + "tGaodeAccount.html";
+ }
+
+ /**
+ * 跳转到添加高德地图账号
+ */
+ @RequestMapping("/tGaodeAccount_add")
+ public String tGaodeAccountAdd() {
+ return PREFIX + "tGaodeAccount_add.html";
+ }
+
+ /**
+ * 跳转到修改高德地图账号
+ */
+ @RequestMapping("/tGaodeAccount_update/{tGaodeAccountId}")
+ public String tGaodeAccountUpdate(@PathVariable Integer tGaodeAccountId, Model model) {
+ TGaodeAccount tGaodeAccount = tGaodeAccountService.selectById(tGaodeAccountId);
+ model.addAttribute("item", tGaodeAccount);
+ LogObjectHolder.me().set(tGaodeAccount);
+ return PREFIX + "tGaodeAccount_edit.html";
+ }
+
+ /**
+ * 获取高德地图账号列表
+ */
+ @RequestMapping(value = "/list")
+ @ResponseBody
+ public Object list(String gdKey, Integer useStatus, Integer status) {
+ Page<Map<String, Object>> page = new PageFactory<Map<String, Object>>().defaultPage();
+ page.setRecords(tGaodeAccountService.getAccountList(page, gdKey, useStatus, status));
+ return super.packForBT(page);
+ }
+
+ /**
+ * 新增高德地图账号
+ */
+ @RequestMapping(value = "/add")
+ @ResponseBody
+ public Object add(TGaodeAccount tGaodeAccount) {
+ if (SinataUtil.isEmpty(tGaodeAccount.getGdKey())) {
+ return new ErrorTip(500, "高德key不能为空");
+ }
+ //校验高德key是否重复
+ TGaodeAccount exist = tGaodeAccountService.selectOne(new EntityWrapper<TGaodeAccount>()
+ .eq("gdKey", tGaodeAccount.getGdKey())
+ .eq("delFlag", 0));
+ if (SinataUtil.isNotEmpty(exist)) {
+ return new ErrorTip(500, "该高德key已存在,请勿重复添加");
+ }
+ if (SinataUtil.isEmpty(tGaodeAccount.getUseStatus())) {
+ tGaodeAccount.setUseStatus(1);
+ }
+ if (SinataUtil.isEmpty(tGaodeAccount.getStatus())) {
+ tGaodeAccount.setStatus(1);
+ }
+ tGaodeAccount.setDelFlag(0);
+ tGaodeAccount.setInsertTime(new Date());
+ tGaodeAccount.setInsertUser(ShiroKit.getUser().getId());
+ tGaodeAccountService.insert(tGaodeAccount);
+ return SUCCESS_TIP;
+ }
+
+ /**
+ * 删除高德地图账号(逻辑删除)
+ */
+ @RequestMapping(value = "/delete")
+ @ResponseBody
+ public Object delete(@RequestParam Integer tGaodeAccountId) {
+ TGaodeAccount tGaodeAccount = tGaodeAccountService.selectById(tGaodeAccountId);
+ if (SinataUtil.isNotEmpty(tGaodeAccount)) {
+ tGaodeAccount.setDelFlag(1);
+ tGaodeAccount.setUpdateTime(new Date());
+ tGaodeAccount.setUpdateUser(ShiroKit.getUser().getId());
+ tGaodeAccountService.updateById(tGaodeAccount);
+ }
+ return SUCCESS_TIP;
+ }
+
+ /**
+ * 修改高德地图账号
+ */
+ @RequestMapping(value = "/update")
+ @ResponseBody
+ public Object update(TGaodeAccount tGaodeAccount) {
+ if (SinataUtil.isEmpty(tGaodeAccount.getGdKey())) {
+ return new ErrorTip(500, "高德key不能为空");
+ }
+ //校验高德key是否重复(排除自身)
+ TGaodeAccount exist = tGaodeAccountService.selectOne(new EntityWrapper<TGaodeAccount>()
+ .eq("gdKey", tGaodeAccount.getGdKey())
+ .eq("delFlag", 0)
+ .ne("id", tGaodeAccount.getId()));
+ if (SinataUtil.isNotEmpty(exist)) {
+ return new ErrorTip(500, "该高德key已存在,请勿重复添加");
+ }
+ tGaodeAccount.setUpdateTime(new Date());
+ tGaodeAccount.setUpdateUser(ShiroKit.getUser().getId());
+ tGaodeAccountService.updateById(tGaodeAccount);
+ return SUCCESS_TIP;
+ }
+
+ /**
+ * 操作高德地图账号(启用/禁用)
+ */
+ @RequestMapping(value = "/opt")
+ @ResponseBody
+ public Object opt(@RequestParam Integer tGaodeAccountId, @RequestParam Integer optType) {
+ TGaodeAccount tGaodeAccount = tGaodeAccountService.selectById(tGaodeAccountId);
+ if (SinataUtil.isNotEmpty(tGaodeAccount)) {
+ if (1 == optType.intValue()) { //启用
+ tGaodeAccount.setStatus(1);
+ } else if (2 == optType.intValue()) { //禁用
+ tGaodeAccount.setStatus(2);
+ }
+ tGaodeAccount.setUpdateTime(new Date());
+ tGaodeAccount.setUpdateUser(ShiroKit.getUser().getId());
+ tGaodeAccountService.updateById(tGaodeAccount);
+ }
+ return SUCCESS_TIP;
+ }
+}
diff --git a/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/GDKeyMapper.java b/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/GDKeyMapper.java
new file mode 100644
index 0000000..1fec0f6
--- /dev/null
+++ b/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/GDKeyMapper.java
@@ -0,0 +1,31 @@
+package com.stylefeng.guns.modular.system.dao;
+
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+
+import java.util.List;
+
+/**
+ * 高德地图key管理 Mapper(注解方式,无需XML)
+ */
+public interface GDKeyMapper {
+
+ /**
+ * 查询可用key(启用、未删除、未用完)
+ */
+ @Select("SELECT gdKey FROM t_gaode_account WHERE status = 1 AND delFlag = 0 AND useStatus <> 3")
+ List<String> selectAvailableKeys();
+
+ /**
+ * 查询已用完的key(用于每日凌晨重置校验)
+ */
+ @Select("SELECT gdKey FROM t_gaode_account WHERE status = 1 AND delFlag = 0 AND useStatus = 3")
+ List<String> selectExhaustedKeys();
+
+ /**
+ * 更新key的使用状态
+ */
+ @Update("UPDATE t_gaode_account SET useStatus = #{useStatus} WHERE gdKey = #{gdKey} AND delFlag = 0")
+ int updateUseStatus(@Param("gdKey") String gdKey, @Param("useStatus") Integer useStatus);
+}
diff --git a/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/TGaodeAccountMapper.java b/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/TGaodeAccountMapper.java
new file mode 100644
index 0000000..c1fa78e
--- /dev/null
+++ b/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/TGaodeAccountMapper.java
@@ -0,0 +1,28 @@
+package com.stylefeng.guns.modular.system.dao;
+
+import com.baomidou.mybatisplus.mapper.BaseMapper;
+import com.baomidou.mybatisplus.plugins.Page;
+import com.stylefeng.guns.modular.system.model.TGaodeAccount;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ * 高德地图账号 Mapper 接口
+ * </p>
+ *
+ * @author stylefeng
+ * @since 2026-09-21
+ */
+public interface TGaodeAccountMapper extends BaseMapper<TGaodeAccount> {
+
+ /**
+ * 根据条件查询高德地图账号列表
+ */
+ List<Map<String, Object>> getAccountList(Page<Map<String, Object>> page,
+ @Param("gdKey") String gdKey,
+ @Param("useStatus") Integer useStatus,
+ @Param("status") Integer status);
+}
diff --git a/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/TGaodeAccountMapper.xml b/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/TGaodeAccountMapper.xml
new file mode 100644
index 0000000..88ada9e
--- /dev/null
+++ b/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/TGaodeAccountMapper.xml
@@ -0,0 +1,41 @@
+<?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.stylefeng.guns.modular.system.dao.TGaodeAccountMapper">
+
+ <!-- 通用查询映射结果 -->
+ <resultMap id="BaseResultMap" type="com.stylefeng.guns.modular.system.model.TGaodeAccount">
+ <id column="id" property="id" />
+ <result column="gdKey" property="gdKey" />
+ <result column="useStatus" property="useStatus" />
+ <result column="status" property="status" />
+ <result column="delFlag" property="delFlag" />
+ <result column="insertTime" property="insertTime" />
+ <result column="insertUser" property="insertUser" />
+ <result column="updateTime" property="updateTime" />
+ <result column="updateUser" property="updateUser" />
+ </resultMap>
+
+ <!-- 通用查询结果列 -->
+ <sql id="Base_Column_List">
+ id, gdKey, useStatus, status, delFlag, insertTime, insertUser, updateTime, updateUser
+ </sql>
+
+ <!--根据条件查询高德地图账号列表-->
+ <select id="getAccountList" resultType="map" parameterType="com.baomidou.mybatisplus.plugins.Page">
+ SELECT * FROM t_gaode_account
+ <where>
+ delFlag = 0
+ <if test="gdKey != null and gdKey != ''">
+ and gdKey LIKE CONCAT('%',#{gdKey},'%')
+ </if>
+ <if test="useStatus != null and useStatus != ''">
+ and useStatus = #{useStatus}
+ </if>
+ <if test="status != null and status != ''">
+ and status = #{status}
+ </if>
+ </where>
+ order by id desc
+ </select>
+
+</mapper>
diff --git a/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TGaodeAccount.java b/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TGaodeAccount.java
new file mode 100644
index 0000000..a93086b
--- /dev/null
+++ b/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TGaodeAccount.java
@@ -0,0 +1,153 @@
+package com.stylefeng.guns.modular.system.model;
+
+import com.baomidou.mybatisplus.enums.IdType;
+import java.util.Date;
+import com.baomidou.mybatisplus.annotations.TableId;
+import com.baomidou.mybatisplus.activerecord.Model;
+import com.baomidou.mybatisplus.annotations.TableName;
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 高德地图账号
+ * </p>
+ *
+ * @author stylefeng
+ * @since 2026-09-21
+ */
+@TableName("t_gaode_account")
+public class TGaodeAccount extends Model<TGaodeAccount> {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键id
+ */
+ @TableId(value = "id", type = IdType.AUTO)
+ private Integer id;
+ /**
+ * 高德的key
+ */
+ private String gdKey;
+ /**
+ * 使用状态 1=未使用 2=使用中 3=已用完
+ */
+ private Integer useStatus;
+ /**
+ * 状态 1=启用 2=禁用
+ */
+ private Integer status;
+ /**
+ * 删除状态 0=未删除 1=已删除
+ */
+ private Integer delFlag;
+ /**
+ * 添加时间
+ */
+ private Date insertTime;
+ /**
+ * 添加人
+ */
+ private Integer insertUser;
+ /**
+ * 修改时间
+ */
+ private Date updateTime;
+ /**
+ * 修改人
+ */
+ private Integer updateUser;
+
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getGdKey() {
+ return gdKey;
+ }
+
+ public void setGdKey(String gdKey) {
+ this.gdKey = gdKey;
+ }
+
+ public Integer getUseStatus() {
+ return useStatus;
+ }
+
+ public void setUseStatus(Integer useStatus) {
+ this.useStatus = useStatus;
+ }
+
+ public Integer getStatus() {
+ return status;
+ }
+
+ public void setStatus(Integer status) {
+ this.status = status;
+ }
+
+ public Integer getDelFlag() {
+ return delFlag;
+ }
+
+ public void setDelFlag(Integer delFlag) {
+ this.delFlag = delFlag;
+ }
+
+ public Date getInsertTime() {
+ return insertTime;
+ }
+
+ public void setInsertTime(Date insertTime) {
+ this.insertTime = insertTime;
+ }
+
+ public Integer getInsertUser() {
+ return insertUser;
+ }
+
+ public void setInsertUser(Integer insertUser) {
+ this.insertUser = insertUser;
+ }
+
+ public Date getUpdateTime() {
+ return updateTime;
+ }
+
+ public void setUpdateTime(Date updateTime) {
+ this.updateTime = updateTime;
+ }
+
+ public Integer getUpdateUser() {
+ return updateUser;
+ }
+
+ public void setUpdateUser(Integer updateUser) {
+ this.updateUser = updateUser;
+ }
+
+ @Override
+ protected Serializable pkVal() {
+ return this.id;
+ }
+
+ @Override
+ public String toString() {
+ return "TGaodeAccount{" +
+ "id=" + id +
+ ", gdKey=" + gdKey +
+ ", useStatus=" + useStatus +
+ ", status=" + status +
+ ", delFlag=" + delFlag +
+ ", insertTime=" + insertTime +
+ ", insertUser=" + insertUser +
+ ", updateTime=" + updateTime +
+ ", updateUser=" + updateUser +
+ "}";
+ }
+}
diff --git a/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/ITGaodeAccountService.java b/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/ITGaodeAccountService.java
new file mode 100644
index 0000000..b2b61a2
--- /dev/null
+++ b/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/ITGaodeAccountService.java
@@ -0,0 +1,24 @@
+package com.stylefeng.guns.modular.system.service;
+
+import com.baomidou.mybatisplus.plugins.Page;
+import com.baomidou.mybatisplus.service.IService;
+import com.stylefeng.guns.modular.system.model.TGaodeAccount;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ * 高德地图账号 服务类
+ * </p>
+ *
+ * @author stylefeng
+ * @since 2026-09-21
+ */
+public interface ITGaodeAccountService extends IService<TGaodeAccount> {
+
+ /**
+ * 根据条件查询高德地图账号列表
+ */
+ List<Map<String, Object>> getAccountList(Page<Map<String, Object>> page, String gdKey, Integer useStatus, Integer status);
+}
diff --git a/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TGaodeAccountServiceImpl.java b/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TGaodeAccountServiceImpl.java
new file mode 100644
index 0000000..4041178
--- /dev/null
+++ b/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TGaodeAccountServiceImpl.java
@@ -0,0 +1,28 @@
+package com.stylefeng.guns.modular.system.service.impl;
+
+import com.baomidou.mybatisplus.plugins.Page;
+import com.baomidou.mybatisplus.service.impl.ServiceImpl;
+import com.stylefeng.guns.modular.system.dao.TGaodeAccountMapper;
+import com.stylefeng.guns.modular.system.model.TGaodeAccount;
+import com.stylefeng.guns.modular.system.service.ITGaodeAccountService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ * 高德地图账号 服务实现类
+ * </p>
+ *
+ * @author stylefeng
+ * @since 2026-09-21
+ */
+@Service
+public class TGaodeAccountServiceImpl extends ServiceImpl<TGaodeAccountMapper, TGaodeAccount> implements ITGaodeAccountService {
+
+ @Override
+ public List<Map<String, Object>> getAccountList(Page<Map<String, Object>> page, String gdKey, Integer useStatus, Integer status) {
+ return this.baseMapper.getAccountList(page, gdKey, useStatus, status);
+ }
+}
diff --git a/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/GDKeyManager.java b/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/GDKeyManager.java
new file mode 100644
index 0000000..f42b2ca
--- /dev/null
+++ b/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/GDKeyManager.java
@@ -0,0 +1,349 @@
+package com.stylefeng.guns.modular.system.util;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.stylefeng.guns.modular.system.dao.GDKeyMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestTemplate;
+
+import javax.annotation.PostConstruct;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * 高德地图key管理器
+ * <p>
+ * 功能:
+ * 1. key池管理:从 t_gaode_account 表加载可用key(启用、未删除、未用完),轮询获取;
+ * 表为空或全部用尽时降级使用兜底key(原硬编码key)。
+ * 2. 自动切换:调用方检测到key"次数用完"后调用 reportExhausted 上报,
+ * 管理器将key移出内存池并置库表 useStatus=3(已用完)。
+ * 3. 每日凌晨重置校验:每天 00:00 将 useStatus=3 的key重置为未使用并放回池,
+ * 随后调用高德最轻量接口校验配额是否真正恢复;未恢复的key重新标记已用完,
+ * 进入延迟重试队列,每30分钟校验一次直到恢复额度。
+ * 4. 兜底key:当天用完仅内存禁用,次日凌晨自动恢复;不写库(表内无对应记录)。
+ */
+@Component
+public class GDKeyManager {
+
+ private static final Logger logger = LoggerFactory.getLogger(GDKeyManager.class);
+
+ /**
+ * 兜底key(原硬编码key):管理端/用户端
+ */
+ public static final String FALLBACK_KEY = "39b31fa22955efa8fce9eed487241db9";
+
+ /**
+ * 配额校验接口:最轻量的通用Web服务接口,每次仅消耗1次配额
+ */
+ private static final String VERIFY_URL = "https://restapi.amap.com/v3/geocode/geo?output=JSON&address=%E5%8C%97%E4%BA%AC%E5%B8%82&key=";
+
+ @Autowired
+ private GDKeyMapper gdKeyMapper;
+
+ @Autowired
+ private RestTemplate restTemplate;
+
+ /**
+ * 内存可用key池(refreshPool整体替换,保证getKey不会看到clear/addAll中间态)
+ */
+ private volatile List<String> availableKeys = new CopyOnWriteArrayList<>();
+
+ /**
+ * 轮询下标
+ */
+ private final AtomicInteger index = new AtomicInteger(0);
+
+ /**
+ * 延迟校验队列:key -> 已重试次数(每日凌晨校验未恢复的key)
+ */
+ private final ConcurrentHashMap<String, Integer> pendingVerifyKeys = new ConcurrentHashMap<>();
+
+ /**
+ * 兜底key当日是否已用完
+ */
+ private volatile boolean fallbackExhausted = false;
+
+ /**
+ * 已标记"使用中"(useStatus=2)的key集合,避免热路径每次取用都写库
+ */
+ private final Set<String> inUseKeys = ConcurrentHashMap.newKeySet();
+
+ @PostConstruct
+ public void init() {
+ refreshPool();
+ }
+
+ /**
+ * 刷新可用key池
+ */
+ public synchronized void refreshPool() {
+ try {
+ List<String> keys = gdKeyMapper.selectAvailableKeys();
+ List<String> newPool = new CopyOnWriteArrayList<>();
+ if (keys != null) {
+ newPool.addAll(keys);
+ }
+ // 整体替换,避免clear/addAll中间态导致getKey短暂看到空池误降级兜底key
+ availableKeys = newPool;
+ logger.info("[GDKeyManager] 高德key池刷新完成,可用key数:{}", newPool.size());
+ } catch (Exception e) {
+ // 表不存在(用户端/司机端未建表时)等异常:降级使用兜底key,不影响系统运行
+ logger.warn("[GDKeyManager] 加载高德key失败(t_gaode_account表可能不存在),降级使用兜底key", e);
+ availableKeys = new CopyOnWriteArrayList<>();
+ }
+ }
+
+ /**
+ * 获取一个可用key:池非空轮询池内key;池空使用兜底key(当日未用完时)
+ */
+ public String getKey() {
+ List<String> pool = availableKeys;
+ if (!pool.isEmpty()) {
+ String key = pickFromPool(pool);
+ markInUse(key);
+ return key;
+ }
+ if (!fallbackExhausted) {
+ return FALLBACK_KEY;
+ }
+ // 兜底key当日也已用完:尝试刷新池(可能有新录入的key)
+ refreshPool();
+ pool = availableKeys;
+ if (!pool.isEmpty()) {
+ String key = pickFromPool(pool);
+ markInUse(key);
+ return key;
+ }
+ return FALLBACK_KEY;
+ }
+
+ /**
+ * 从内存池轮询取一个key(使用调用方传入的池快照,避免与定时刷新交叉导致越界)
+ */
+ private String pickFromPool(List<String> pool) {
+ int i = Math.abs(index.getAndIncrement() % pool.size());
+ return pool.get(i);
+ }
+
+ /**
+ * 将表内key标记为"使用中"(useStatus=2):
+ * 仅key首次被取用时写库一次;兜底key不写库;写库失败不影响取key流程。
+ */
+ private void markInUse(String key) {
+ if (key == null || FALLBACK_KEY.equals(key) || inUseKeys.contains(key)) {
+ return;
+ }
+ try {
+ gdKeyMapper.updateUseStatus(key, 2);
+ inUseKeys.add(key);
+ logger.info("[GDKeyManager] 高德key[{}]开始使用,已标记为使用中", key);
+ } catch (Exception e) {
+ // 表不存在等异常:本次不标记,下次取用再尝试,不影响业务
+ logger.warn("[GDKeyManager] 标记高德key[{}]使用中失败(表可能不存在),不影响使用", key);
+ }
+ }
+
+ /**
+ * 定时刷新key池:每5分钟一次,让管理后台新录入的key及时生效
+ */
+ @Scheduled(fixedDelay = 5 * 60 * 1000, initialDelay = 60 * 1000)
+ public void scheduledRefreshPool() {
+ refreshPool();
+ }
+
+ /**
+ * 上报某个key次数用完:
+ * 表内key -> 移出内存池 + 置库表 useStatus=3;
+ * 兜底key -> 仅内存当日禁用(不写库),次日凌晨自动恢复。
+ */
+ public void reportExhausted(String usedKey) {
+ if (usedKey == null || usedKey.isEmpty()) {
+ return;
+ }
+ availableKeys.remove(usedKey);
+ inUseKeys.remove(usedKey);
+ if (FALLBACK_KEY.equals(usedKey)) {
+ fallbackExhausted = true;
+ logger.warn("[GDKeyManager] 兜底key次数已用完,今日禁用,次日凌晨自动恢复");
+ return;
+ }
+ try {
+ gdKeyMapper.updateUseStatus(usedKey, 3);
+ logger.warn("[GDKeyManager] 高德key[{}]次数用完,已标记为已用完并移出key池", usedKey);
+ } catch (Exception e) {
+ logger.warn("[GDKeyManager] 更新高德key[{}]使用状态失败(表可能不存在),仅内存剔除", usedKey);
+ }
+ }
+
+ /**
+ * 判断Web服务API响应是否为"次数用完/不可用"(依据infocode)
+ */
+ public static boolean isWebKeyExhausted(JSONObject resp) {
+ if (resp == null) {
+ return false;
+ }
+ String infocode = resp.getString("infocode");
+ if (infocode == null || infocode.isEmpty()) {
+ return false;
+ }
+ switch (infocode) {
+ case "10001": // key不正确或过期
+ case "10003": // 超过每日配额
+ case "10004": // 访问过于频繁
+ case "10005": // 超出每秒访问量限制
+ case "10010": // 权限不足
+ case "10012": // 服务未开放/权限不足
+ case "10019": // 使用配额已用尽
+ case "10020": // 并发超限
+ case "10044": // 签名错误/未开通
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * 判断猎鹰API响应是否为"次数用完"(依据errcode/errmsg)
+ */
+ public static boolean isFalconExhausted(JSONObject resp) {
+ if (resp == null) {
+ return false;
+ }
+ int errcode = resp.getIntValue("errcode");
+ if (errcode == 10000) {
+ return false;
+ }
+ if (errcode == 20001) {
+ return true; // 权限不足
+ }
+ String errmsg = resp.getString("errmsg");
+ if (errmsg == null) {
+ return false;
+ }
+ return errmsg.contains("配额") || errmsg.contains("上限") || errmsg.contains("次数")
+ || errmsg.contains("用完") || errmsg.contains("超限")
+ || errmsg.contains("quota") || errmsg.contains("limit");
+ }
+
+ // ==================== 每日凌晨重置 + API校验恢复额度 ====================
+
+ /**
+ * 每日凌晨 00:00 自动执行:
+ * 1. 将 useStatus=3(已用完)的key重置为未使用并放回内存池;
+ * 2. 调用高德API校验配额是否真正恢复;
+ * 3. 未恢复的key重新标记已用完,进入延迟重试队列,直到恢复额度。
+ */
+ @Scheduled(cron = "0 0 0 * * ?")
+ public void dailyResetAndVerify() {
+ logger.info("[GDKeyManager] 开始每日高德key配额重置校验");
+ // 兜底key当日禁用标记次日自动恢复
+ fallbackExhausted = false;
+ List<String> exhaustedKeys;
+ try {
+ exhaustedKeys = gdKeyMapper.selectExhaustedKeys();
+ } catch (Exception e) {
+ logger.warn("[GDKeyManager] 查询已用完key失败(表可能不存在),跳过重置校验", e);
+ return;
+ }
+ if (exhaustedKeys == null || exhaustedKeys.isEmpty()) {
+ logger.info("[GDKeyManager] 无已用完的key,跳过重置校验");
+ return;
+ }
+ for (String gdKey : exhaustedKeys) {
+ // 1. 先重置为未使用
+ try {
+ gdKeyMapper.updateUseStatus(gdKey, 1);
+ } catch (Exception e) {
+ logger.warn("[GDKeyManager] 重置key[{}]使用状态失败", gdKey, e);
+ }
+ // 2. 调用API校验是否真正恢复额度
+ boolean recovered = verifyQuota(gdKey);
+ if (recovered) {
+ if (!availableKeys.contains(gdKey)) {
+ availableKeys.add(gdKey);
+ }
+ pendingVerifyKeys.remove(gdKey);
+ logger.info("[GDKeyManager] 高德key[{}]配额已恢复,重新加入key池", gdKey);
+ } else {
+ // 未恢复:重新标记已用完,进入延迟重试队列
+ try {
+ gdKeyMapper.updateUseStatus(gdKey, 3);
+ } catch (Exception e) {
+ logger.warn("[GDKeyManager] 回写key[{}]已用完状态失败", gdKey, e);
+ }
+ availableKeys.remove(gdKey);
+ pendingVerifyKeys.put(gdKey, 0);
+ logger.warn("[GDKeyManager] 高德key[{}]配额尚未恢复,进入延迟重试队列", gdKey);
+ }
+ }
+ }
+
+ /**
+ * 延迟重试任务:每30分钟校验一次待恢复的key,直到恢复额度为止
+ */
+ @Scheduled(fixedDelay = 30 * 60 * 1000, initialDelay = 30 * 60 * 1000)
+ public void retryPendingKeys() {
+ if (pendingVerifyKeys.isEmpty()) {
+ return;
+ }
+ for (String gdKey : new ArrayList<>(pendingVerifyKeys.keySet())) {
+ boolean recovered = verifyQuota(gdKey);
+ if (recovered) {
+ try {
+ gdKeyMapper.updateUseStatus(gdKey, 1);
+ } catch (Exception e) {
+ logger.warn("[GDKeyManager] 恢复key[{}]使用状态失败", gdKey, e);
+ }
+ if (!availableKeys.contains(gdKey)) {
+ availableKeys.add(gdKey);
+ }
+ pendingVerifyKeys.remove(gdKey);
+ logger.info("[GDKeyManager] 高德key[{}]延迟校验通过,配额已恢复,重新加入key池", gdKey);
+ } else {
+ int count = pendingVerifyKeys.merge(gdKey, 1, Integer::sum);
+ logger.warn("[GDKeyManager] 高德key[{}]配额仍未恢复(已校验{}次),继续等待", gdKey, count);
+ }
+ }
+ }
+
+ /**
+ * 调用高德最轻量接口校验配额是否恢复
+ *
+ * @return true=已恢复(或无法判断,保守放行);false=明确未恢复(配额类错误)
+ */
+ private boolean verifyQuota(String gdKey) {
+ try {
+ String resp = restTemplate.getForObject(VERIFY_URL + gdKey, String.class);
+ JSONObject json = JSON.parseObject(resp);
+ String status = json.getString("status");
+ String infocode = json.getString("infocode");
+ if ("1".equals(status) && "10000".equals(infocode)) {
+ return true;
+ }
+ // 权限类错误:该key未开通Web服务校验权限(如猎鹰专用key),无法判断配额,按已恢复处理
+ if ("10044".equals(infocode) || "10012".equals(infocode)
+ || "10002".equals(infocode) || "10010".equals(infocode)) {
+ logger.info("[GDKeyManager] 高德key[{}]无Web服务校验权限(infocode={}),按已恢复处理", gdKey, infocode);
+ return true;
+ }
+ // 配额类错误:明确未恢复
+ if ("10001".equals(infocode) || "10003".equals(infocode) || "10019".equals(infocode)) {
+ return false;
+ }
+ // 其他错误(限流/网络等):保守放行,真实调用失败时会被自动切换机制再次标记
+ return true;
+ } catch (Exception e) {
+ logger.warn("[GDKeyManager] 校验key[{}]配额异常,按已恢复处理", gdKey, e);
+ return true;
+ }
+ }
+}
diff --git a/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/GDMapElectricFenceUtil.java b/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/GDMapElectricFenceUtil.java
index 8f17281..04e4121 100644
--- a/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/GDMapElectricFenceUtil.java
+++ b/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/GDMapElectricFenceUtil.java
@@ -34,9 +34,98 @@
@Autowired
private IGDInterfaceService gdInterfaceService;
- private String key = "ca723c3c8a78962a7751129ae035dc9d";
+ @Autowired
+ private GDKeyManager gdKeyManager;
private JSONArray jsonArray = new JSONArray();
+
+ /**
+ * 执行GET请求:key次数用完时自动切换可用key重试
+ */
+ private String doGetWithRetry(String baseUrl) {
+ String lastResp = null;
+ int maxAttempts = 5;
+ for (int i = 0; i < maxAttempts; i++) {
+ String key = gdKeyManager.getKey();
+ String url = baseUrl + (baseUrl.contains("?") ? "&" : "?") + "key=" + key;
+ String resp = restTemplate.getForObject(url, String.class);
+ lastResp = resp;
+ JSONObject jsonObject;
+ try {
+ jsonObject = JSON.parseObject(resp);
+ } catch (Exception e) {
+ return resp;
+ }
+ if (GDKeyManager.isWebKeyExhausted(jsonObject)) {
+ gdKeyManager.reportExhausted(key);
+ continue;
+ }
+ return resp;
+ }
+ return lastResp;
+ }
+
+ /**
+ * 执行POST请求(JSON体):key次数用完时自动切换可用key重试
+ */
+ private String doPostJsonWithRetry(String baseUrl, String jsonBody) {
+ String lastResp = null;
+ int maxAttempts = 5;
+ HttpHeaders headers = new HttpHeaders();
+ MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
+ headers.setContentType(type);
+ headers.add("Accept", MediaType.APPLICATION_JSON.toString());
+ for (int i = 0; i < maxAttempts; i++) {
+ String key = gdKeyManager.getKey();
+ String url = baseUrl + (baseUrl.contains("?") ? "&" : "?") + "key=" + key;
+ HttpEntity<String> formEntity = new HttpEntity<>(jsonBody, headers);
+ String resp = restTemplate.postForObject(url, formEntity, String.class);
+ lastResp = resp;
+ JSONObject jsonObject;
+ try {
+ jsonObject = JSON.parseObject(resp);
+ } catch (Exception e) {
+ return resp;
+ }
+ if (GDKeyManager.isWebKeyExhausted(jsonObject)) {
+ gdKeyManager.reportExhausted(key);
+ continue;
+ }
+ return resp;
+ }
+ return lastResp;
+ }
+
+ /**
+ * 执行PATCH请求(JSON体):key次数用完时自动切换可用key重试
+ */
+ private String doPatchJsonWithRetry(String baseUrl, String jsonBody) {
+ String lastResp = null;
+ int maxAttempts = 5;
+ HttpHeaders headers = new HttpHeaders();
+ MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
+ headers.setContentType(type);
+ headers.add("Accept", MediaType.APPLICATION_JSON.toString());
+ for (int i = 0; i < maxAttempts; i++) {
+ String key = gdKeyManager.getKey();
+ String url = baseUrl + (baseUrl.contains("?") ? "&" : "?") + "key=" + key;
+ HttpEntity<String> formEntity = new HttpEntity<>(jsonBody, headers);
+ String resp = restTemplate.patchForObject(url, formEntity, String.class);
+ lastResp = resp;
+ JSONObject jsonObject;
+ try {
+ jsonObject = JSON.parseObject(resp);
+ } catch (Exception e) {
+ return resp;
+ }
+ if (GDKeyManager.isWebKeyExhausted(jsonObject)) {
+ gdKeyManager.reportExhausted(key);
+ continue;
+ }
+ return resp;
+ }
+ return lastResp;
+ }
@Bean
@@ -82,14 +171,7 @@
json.put("alert_condition", "enter;leave");
json.put("desc", id);
- HttpHeaders headers = new HttpHeaders();
- MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
- headers.setContentType(type);
- headers.add("Accept", MediaType.APPLICATION_JSON.toString());
- HttpEntity<String> formEntity = new HttpEntity<>(json.toString(), headers);
-
- String url = "https://restapi.amap.com/v4/geofence/meta?key=" + key;
- String js = restTemplate.postForObject(url, formEntity, String.class);
+ String js = doPostJsonWithRetry("https://restapi.amap.com/v4/geofence/meta", json.toString());
JSONObject jsonObject = JSON.parseObject(js);
JSONObject data = jsonObject.getJSONObject("data");
String status = data.getString("status");
@@ -132,8 +214,8 @@
* @return
*/
public String findElectricFenc(String gid){
- String url = "https://restapi.amap.com/v4/geofence/meta?key=" + key + "&gid=" + gid;
- String forObject = restTemplate.getForObject(url, String.class);
+ String url = "https://restapi.amap.com/v4/geofence/meta?gid=" + gid;
+ String forObject = doGetWithRetry(url);
JSONObject jsonObject = JSON.parseObject(forObject);
JSONObject data = jsonObject.getJSONObject("data");
JSONArray rs_list = data.getJSONArray("rs_list");
@@ -149,8 +231,8 @@
* 查询以创建的所有电子围栏
*/
public String findElectricFenc(String center, String radius, String points){
- String url = "https://restapi.amap.com/v4/geofence/meta?key=" + key;
- String forObject = restTemplate.getForObject(url, String.class);
+ String url = "https://restapi.amap.com/v4/geofence/meta";
+ String forObject = doGetWithRetry(url);
JSONObject jsonObject = JSON.parseObject(forObject);
JSONObject data = jsonObject.getJSONObject("data");
@@ -186,8 +268,8 @@
if(page == 1){
jsonArray = new JSONArray();
}
- String url = "https://restapi.amap.com/v4/geofence/meta?key=" + key + "&page_no=" + page + "&page_size=" + 30;
- String forObject = restTemplate.getForObject(url, String.class);
+ String url = "https://restapi.amap.com/v4/geofence/meta?page_no=" + page + "&page_size=" + 30;
+ String forObject = doGetWithRetry(url);
JSONObject jsonObject = JSON.parseObject(forObject);
JSONObject data = jsonObject.getJSONObject("data");
JSONArray rs_list = data.getJSONArray("rs_list");
@@ -275,14 +357,8 @@
json.put("alert_condition", "enter;leave");
json.put("desc", id + "围栏更新描述");
- HttpHeaders headers = new HttpHeaders();
- MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
- headers.setContentType(type);
- headers.add("Accept", MediaType.APPLICATION_JSON.toString());
- HttpEntity<String> formEntity = new HttpEntity<>(json.toString(), headers);
-
- String url = "https://restapi.amap.com/v4/geofence/meta?key=" + key + "&gid=" + gid;
- String s = restTemplate.patchForObject(url, formEntity, String.class);
+ String url = "https://restapi.amap.com/v4/geofence/meta?gid=" + gid;
+ String s = doPatchJsonWithRetry(url, json.toString());
System.out.println(s);
gdInterfaceService.saveData("https://restapi.amap.com/v4/geofence/meta", "更新电子围栏");
@@ -304,8 +380,8 @@
diu = "B78F99DD-2496-4A43-843B-172CDA2D9798";
}
locations = locations + "," + (new Date().getTime() / 1000);
- String url = "https://restapi.amap.com/v4/geofence/status?key=" + key + "&diu=" + diu + "&locations=" + locations;
- String forObject = restTemplate.getForObject(url, String.class);
+ String url = "https://restapi.amap.com/v4/geofence/status?diu=" + diu + "&locations=" + locations;
+ String forObject = doGetWithRetry(url);
JSONObject jsonObject = JSON.parseObject(forObject);
List<String> ids = new ArrayList<>();
JSONObject data = jsonObject.getJSONObject("data");
@@ -334,7 +410,7 @@
* @return
*/
public boolean deleteElectricFenc(String gid){
- restTemplate.delete("https://restapi.amap.com/v4/geofence/meta?key={1}&gid={2}", key, gid);
+ restTemplate.delete("https://restapi.amap.com/v4/geofence/meta?key={1}&gid={2}", gdKeyManager.getKey(), gid);
System.out.println("删除:" );
gdInterfaceService.saveData("https://restapi.amap.com/v4/geofence/meta", "删除电子围栏");
@@ -351,9 +427,9 @@
* @return
*/
public Map<String, String> getDistance(String origins, String destination, Integer type){
- String url = "https://restapi.amap.com/v3/distance?key=" + key + "&origins=" + origins + "&destination=" + destination +
+ String url = "https://restapi.amap.com/v3/distance?origins=" + origins + "&destination=" + destination +
"&type=" + type;
- String forObject = restTemplate.getForObject(url, String.class);
+ String forObject = doGetWithRetry(url);
JSONObject jsonObject = JSON.parseObject(forObject);
String status = jsonObject.getString("status");
@@ -381,9 +457,9 @@
* @return
*/
public Map<String, String> getDriving(String origins, String destination, String waypoints){
- String url = "https://restapi.amap.com/v3/direction/driving?key=" + key + "&origin=" + origins + "&destination=" + destination +
+ String url = "https://restapi.amap.com/v3/direction/driving?origin=" + origins + "&destination=" + destination +
"&waypoints=" + waypoints + "&extensions=base&strategy=0";
- String forObject = restTemplate.getForObject(url, String.class);
+ String forObject = doGetWithRetry(url);
JSONObject jsonObject = JSON.parseObject(forObject);
String status = jsonObject.getString("status");
diff --git a/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/GDMapGeocodingUtil.java b/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/GDMapGeocodingUtil.java
index 5845ae2..33e97e5 100644
--- a/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/GDMapGeocodingUtil.java
+++ b/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/GDMapGeocodingUtil.java
@@ -20,13 +20,40 @@
@Component
public class GDMapGeocodingUtil {
- private String key = "ca723c3c8a78962a7751129ae035dc9d";
-
@Autowired
private RestTemplate restTemplate;
@Autowired
private IGDInterfaceService gdInterfaceService;
+
+ @Autowired
+ private GDKeyManager gdKeyManager;
+
+ /**
+ * 执行GET请求:key次数用完时自动切换可用key重试
+ */
+ private String doGetWithRetry(String baseUrl) {
+ String lastResp = null;
+ int maxAttempts = 5;
+ for (int i = 0; i < maxAttempts; i++) {
+ String key = gdKeyManager.getKey();
+ String url = baseUrl + (baseUrl.contains("?") ? "&" : "?") + "key=" + key;
+ String resp = restTemplate.getForObject(url, String.class);
+ lastResp = resp;
+ JSONObject jsonObject;
+ try {
+ jsonObject = JSON.parseObject(resp);
+ } catch (Exception e) {
+ return resp;
+ }
+ if (GDKeyManager.isWebKeyExhausted(jsonObject)) {
+ gdKeyManager.reportExhausted(key);
+ continue;
+ }
+ return resp;
+ }
+ return lastResp;
+ }
/**
@@ -55,9 +82,9 @@
return map;
}
- String url = "https://restapi.amap.com/v3/geocode/geo?key=" + key + "&output=JSON";
+ String url = "https://restapi.amap.com/v3/geocode/geo?output=JSON";
url += "&address=" + province + (ToolUtil.isNotEmpty(city) ? city : "") + (ToolUtil.isNotEmpty(county) ? county : "") + (ToolUtil.isNotEmpty(address) ? address : "");
- String forObject = restTemplate.getForObject(url, String.class);
+ String forObject = doGetWithRetry(url);
JSONObject jsonObject = JSON.parseObject(forObject);
String status = jsonObject.getString("status");
List<String> list = new ArrayList<>();
@@ -80,8 +107,8 @@
public Map<String, Object> geocoding(String address){
Map<String, Object> map = new HashMap<>();
- String url = "https://restapi.amap.com/v3/geocode/geo?key=" + key + "&output=JSON&address=" + address;
- String forObject = restTemplate.getForObject(url, String.class);
+ String url = "https://restapi.amap.com/v3/geocode/geo?output=JSON&address=" + address;
+ String forObject = doGetWithRetry(url);
JSONObject jsonObject = JSON.parseObject(forObject);
String status = jsonObject.getString("status");
List<String> list = new ArrayList<>();
@@ -110,8 +137,8 @@
* @throws Exception
*/
public Map<String, String> geocode(String lon, String lan) throws Exception{
- String url = "https://restapi.amap.com/v3/geocode/regeo?key=" + key + "&location=" + lon + "," + lan;
- String forObject = restTemplate.getForObject(url, String.class);
+ String url = "https://restapi.amap.com/v3/geocode/regeo?location=" + lon + "," + lan;
+ String forObject = doGetWithRetry(url);
JSONObject jsonObject = JSON.parseObject(forObject);
Map<String, String> map = new HashMap<>();
diff --git a/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/GaoDeMapUtil.java b/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/GaoDeMapUtil.java
index 89d066f..ed6452f 100644
--- a/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/GaoDeMapUtil.java
+++ b/ManagementFBTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/GaoDeMapUtil.java
@@ -1,6 +1,8 @@
package com.stylefeng.guns.modular.system.util;
+import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
+import com.stylefeng.guns.core.util.SpringContextHolder;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
@@ -25,35 +27,57 @@
}
/**
+ * 获取GDKeyManager(非Spring环境下返回null,如main测试)
+ */
+ private static GDKeyManager getKeyManager() {
+ try {
+ return SpringContextHolder.getBean(GDKeyManager.class);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
* 根据地址查询经纬度
+ * key次数用完时自动切换可用key重试
*
* @param address
* @return
*/
public static JSONObject getLngAndLat(String address) {
JSONObject positionObj = new JSONObject();
+ GDKeyManager keyManager = getKeyManager();
- try {
- // 拼接请求高德的url
- String url = "http://restapi.amap.com/v3/geocode/geo?address=" + address + "&output=JSON&key=" + "ca723c3c8a78962a7751129ae035dc9d";
- // 请求高德接口
- String result = sendHttpGet(url);
- JSONObject resultJOSN = JSONObject.parseObject(result);
- System.out.println("高德接口返回原始数据:");
- System.out.println(resultJOSN);
- JSONArray geocodesArray = resultJOSN.getJSONArray("geocodes");
- if (geocodesArray.size() > 0) {
- String position = geocodesArray.getJSONObject(0).getString("location");
- String[] lngAndLat = position.split(",");
- String longitude = lngAndLat[0];
- String latitude = lngAndLat[1];
- positionObj.put("longitude", longitude);
- positionObj.put("latitude", latitude);
+ int maxAttempts = 5;
+ for (int i = 0; i < maxAttempts; i++) {
+ String key = keyManager != null ? keyManager.getKey() : GDKeyManager.FALLBACK_KEY;
+ try {
+ // 拼接请求高德的url
+ String url = "http://restapi.amap.com/v3/geocode/geo?address=" + address + "&output=JSON&key=" + key;
+ // 请求高德接口
+ String result = sendHttpGet(url);
+ JSONObject resultJOSN = JSON.parseObject(result);
+ System.out.println("高德接口返回原始数据:");
+ System.out.println(resultJOSN);
+ if (GDKeyManager.isWebKeyExhausted(resultJOSN)) {
+ if (keyManager != null) {
+ keyManager.reportExhausted(key);
+ }
+ continue;
+ }
+ JSONArray geocodesArray = resultJOSN.getJSONArray("geocodes");
+ if (geocodesArray != null && geocodesArray.size() > 0) {
+ String position = geocodesArray.getJSONObject(0).getString("location");
+ String[] lngAndLat = position.split(",");
+ String longitude = lngAndLat[0];
+ String latitude = lngAndLat[1];
+ positionObj.put("longitude", longitude);
+ positionObj.put("latitude", latitude);
+ }
+ break;
+ } catch (Exception e) {
+ e.printStackTrace();
}
- geocodesArray.getJSONObject(0).getString("location");
-
- } catch (Exception e) {
- e.printStackTrace();
}
return positionObj;
}
diff --git a/ManagementFBTravel/guns-admin/src/main/resources/application.yml b/ManagementFBTravel/guns-admin/src/main/resources/application.yml
index 6dbfd74..6d4f4b9 100644
--- a/ManagementFBTravel/guns-admin/src/main/resources/application.yml
+++ b/ManagementFBTravel/guns-admin/src/main/resources/application.yml
@@ -66,7 +66,7 @@
#spring:
# datasource:
-# url: jdbc:mysql://127.0.0.1:3306/fbtravel?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=GMT%2B8
+# url: jdbc:mysql://192.168.110.80:3306/fbtravel?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=GMT%2B8
# username: root
# password: 123456
# db-name: oktravel #用来搜集数据库的所有表
diff --git a/ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/home.html b/ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/home.html
index 56b8fbd..1441148 100644
--- a/ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/home.html
+++ b/ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/home.html
@@ -256,8 +256,13 @@
</div>
</div>
</div>
-<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=c59c0ec8058a8305009eb315584e07d1"></script>
-<script src="https://webapi.amap.com/maps?v=1.4.15&key=c59c0ec8058a8305009eb315584e07d1&plugin=AMap.MouseTool"></script>
+<script type="text/javascript">
+ window._AMapSecurityConfig = {
+ securityJsCode: "f4241876b072db561dc69b2857032738",
+ };
+</script>
+<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=fb70a54f977723c9cac44bc903936746"></script>
+<script src="https://webapi.amap.com/maps?v=1.4.15&key=fb70a54f977723c9cac44bc903936746&plugin=AMap.MouseTool"></script>
<script type="text/javascript" src='https://a.amap.com/jsapi_demos/static/citys.js'></script>
<script src="${ctxPath}/static/home.js"></script>
<script src="${ctxPath}/static/js/jquery.sparkline 2.1.2.js"></script>
diff --git a/ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tGaodeAccount/tGaodeAccount.html b/ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tGaodeAccount/tGaodeAccount.html
new file mode 100644
index 0000000..37065c8
--- /dev/null
+++ b/ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tGaodeAccount/tGaodeAccount.html
@@ -0,0 +1,58 @@
+@layout("/common/_container.html"){
+<div class="row">
+ <div class="col-sm-12">
+ <div class="ibox float-e-margins">
+ <div class="ibox-title">
+ <h5>高德地图账号管理</h5>
+ </div>
+ <div class="ibox-content">
+ <div class="row row-lg">
+ <div class="col-sm-12">
+ <div class="row">
+ <div class="col-sm-3">
+ <#NameCon id="gdKey" name="高德key" />
+ </div>
+ <div class="col-sm-3">
+ <#SelectCon id="useStatus" name="使用状态" >
+ <option value="">全部</option>
+ <option value="1">未使用</option>
+ <option value="2">使用中</option>
+ <option value="3">已用完</option>
+ </#SelectCon>
+ </div>
+ <div class="col-sm-3">
+ <#SelectCon id="status" name="状态" >
+ <option value="">全部</option>
+ <option value="1">启用</option>
+ <option value="2">禁用</option>
+ </#SelectCon>
+ </div>
+ <div class="col-sm-3">
+ <#button name="搜索" icon="fa-search" clickFun="TGaodeAccount.search()"/>
+ <#button name="重置" icon="fa-trash" clickFun="TGaodeAccount.resetSearch()" space="true"/>
+ </div>
+ </div>
+ <div class="hidden-xs" id="TGaodeAccountTableToolbar" role="group">
+ @if(shiro.hasPermission("/tGaodeAccount/add")){
+ <#button name="添加" icon="fa-plus" clickFun="TGaodeAccount.openAddTGaodeAccount()"/>
+ @}
+ @if(shiro.hasPermission("/tGaodeAccount/update")){
+ <#button name="编辑" icon="fa-edit" clickFun="TGaodeAccount.openTGaodeAccountDetail()" space="true"/>
+ @}
+ @if(shiro.hasPermission("/tGaodeAccount/delete")){
+ <#button name="删除" icon="fa-remove" clickFun="TGaodeAccount.delete()" space="true"/>
+ @}
+ @if(shiro.hasPermission("/tGaodeAccount/opt")){
+ <#button name="启用" icon="fa-check-circle" clickFun="TGaodeAccount.enable()" space="true"/>
+ <#button name="禁用" icon="fa-ban" clickFun="TGaodeAccount.disable()" space="true"/>
+ @}
+ </div>
+ <#table id="TGaodeAccountTable"/>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+<script src="${ctxPath}/static/modular/system/tGaodeAccount/tGaodeAccount.js"></script>
+@}
diff --git a/ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tGaodeAccount/tGaodeAccount_add.html b/ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tGaodeAccount/tGaodeAccount_add.html
new file mode 100644
index 0000000..02ec2a4
--- /dev/null
+++ b/ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tGaodeAccount/tGaodeAccount_add.html
@@ -0,0 +1,32 @@
+@layout("/common/_container.html"){
+<div class="ibox float-e-margins">
+ <div class="ibox-content">
+ <div class="form-horizontal" id="gaodeAccountInfoForm">
+
+ <div class="row">
+ <div class="col-sm-10">
+ <#input id="gdKey" name="高德key"/>
+ <#select id="useStatus" name="使用状态:">
+ <option value="1" selected="selected">未使用</option>
+ <option value="2">使用中</option>
+ <option value="3">已用完</option>
+ </#select>
+ <#select id="status" name="状态:">
+ <option value="1" selected="selected">启用</option>
+ <option value="2">禁用</option>
+ </#select>
+ </div>
+ </div>
+
+ <div class="row btn-group-m-t">
+ <div class="col-sm-10 col-sm-offset-5">
+ <#button btnCss="info" name="提交" id="ensure" icon="fa-check" clickFun="TGaodeAccountInfoDlg.addSubmit()"/>
+ <#button btnCss="danger" name="取消" id="cancel" icon="fa-eraser" clickFun="TGaodeAccountInfoDlg.close()"/>
+ </div>
+ </div>
+ </div>
+
+ </div>
+</div>
+<script src="${ctxPath}/static/modular/system/tGaodeAccount/tGaodeAccount_info.js"></script>
+@}
diff --git a/ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tGaodeAccount/tGaodeAccount_edit.html b/ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tGaodeAccount/tGaodeAccount_edit.html
new file mode 100644
index 0000000..7af42a3
--- /dev/null
+++ b/ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tGaodeAccount/tGaodeAccount_edit.html
@@ -0,0 +1,32 @@
+@layout("/common/_container.html"){
+<div class="ibox float-e-margins">
+ <div class="ibox-content">
+ <div class="form-horizontal" id="gaodeAccountInfoForm">
+ <input type="hidden" id="id" name="id" value="${item.id}">
+ <div class="row">
+ <div class="col-sm-10">
+ <#input id="gdKey" name="高德key" value="${item.gdKey}"/>
+ <#select id="useStatus" name="使用状态:">
+ <option value="1" ${1 == item.useStatus ? 'selected=selected' : ''}>未使用</option>
+ <option value="2" ${2 == item.useStatus ? 'selected=selected' : ''}>使用中</option>
+ <option value="3" ${3 == item.useStatus ? 'selected=selected' : ''}>已用完</option>
+ </#select>
+ <#select id="status" name="状态:">
+ <option value="1" ${1 == item.status ? 'selected=selected' : ''}>启用</option>
+ <option value="2" ${2 == item.status ? 'selected=selected' : ''}>禁用</option>
+ </#select>
+ </div>
+ </div>
+
+ <div class="row btn-group-m-t">
+ <div class="col-sm-10 col-sm-offset-5">
+ <#button btnCss="info" name="提交" id="ensure" icon="fa-check" clickFun="TGaodeAccountInfoDlg.editSubmit()"/>
+ <#button btnCss="danger" name="取消" id="cancel" icon="fa-eraser" clickFun="TGaodeAccountInfoDlg.close()"/>
+ </div>
+ </div>
+ </div>
+
+ </div>
+</div>
+<script src="${ctxPath}/static/modular/system/tGaodeAccount/tGaodeAccount_info.js"></script>
+@}
diff --git a/ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tSite/tSite_add.html b/ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tSite/tSite_add.html
index 284514e..447d2e8 100644
--- a/ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tSite/tSite_add.html
+++ b/ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tSite/tSite_add.html
@@ -164,7 +164,12 @@
</div>
</div>
-<script src="https://webapi.amap.com/maps?v=1.4.15&key=c59c0ec8058a8305009eb315584e07d1&plugin=AMap.MouseTool,AMap.DistrictSearch,AMap.PolyEditor,AMap.RectangleEditor,AMap.CircleEditor"></script>
+<script type="text/javascript">
+ window._AMapSecurityConfig = {
+ securityJsCode: "f4241876b072db561dc69b2857032738",
+ };
+</script>
+<script src="https://webapi.amap.com/maps?v=1.4.15&key=fb70a54f977723c9cac44bc903936746&plugin=AMap.MouseTool,AMap.DistrictSearch,AMap.PolyEditor,AMap.RectangleEditor,AMap.CircleEditor"></script>
<script src="${ctxPath}/static/modular/system/tSite/electricFence.js"></script>
<script src="${ctxPath}/static/modular/system/tSite/tSite_info.js"></script>
@}
diff --git a/ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tSite/tSite_edit.html b/ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tSite/tSite_edit.html
index 319a285..19a2b2f 100644
--- a/ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tSite/tSite_edit.html
+++ b/ManagementFBTravel/guns-admin/src/main/webapp/WEB-INF/view/system/tSite/tSite_edit.html
@@ -187,7 +187,12 @@
</div>
</div>
-<script src="https://webapi.amap.com/maps?v=1.4.15&key=c59c0ec8058a8305009eb315584e07d1&plugin=AMap.MouseTool,AMap.DistrictSearch,AMap.PolyEditor,AMap.RectangleEditor,AMap.CircleEditor"></script>
+<script type="text/javascript">
+ window._AMapSecurityConfig = {
+ securityJsCode: "f4241876b072db561dc69b2857032738",
+ };
+</script>
+<script src="https://webapi.amap.com/maps?v=1.4.15&key=fb70a54f977723c9cac44bc903936746&plugin=AMap.MouseTool,AMap.DistrictSearch,AMap.PolyEditor,AMap.RectangleEditor,AMap.CircleEditor"></script>
<script src="${ctxPath}/static/modular/system/tSite/electricFence.js"></script>
<script src="${ctxPath}/static/modular/system/tSite/tSite_info.js"></script>
@}
diff --git a/ManagementFBTravel/guns-admin/src/main/webapp/static/modular/system/tGaodeAccount/tGaodeAccount.js b/ManagementFBTravel/guns-admin/src/main/webapp/static/modular/system/tGaodeAccount/tGaodeAccount.js
new file mode 100644
index 0000000..3bdc6d2
--- /dev/null
+++ b/ManagementFBTravel/guns-admin/src/main/webapp/static/modular/system/tGaodeAccount/tGaodeAccount.js
@@ -0,0 +1,257 @@
+/**
+ * 高德地图账号管理初始化
+ */
+var TGaodeAccount = {
+ id: "TGaodeAccountTable", //表格id
+ seItem: null, //选中的条目
+ table: null,
+ layerIndex: -1
+};
+
+/**
+ * 初始化表格的列
+ */
+TGaodeAccount.initColumn = function () {
+ return [
+ {field: 'selectItem', radio: true},
+ {title: '主键ID', field: 'id', visible: false, align: 'center', valign: 'middle'},
+ {title: '高德key', field: 'gdKey', visible: true, align: 'center', valign: 'middle',width:'20%',
+ formatter: function (value, row) {
+ var btn = "";
+ if(row.gdKey != '' && row.gdKey != null) {
+ btn = ['<p class="toolTip" style="overflow:hidden;white-space:nowrap;text-overflow:ellipsis;" title="' + row.gdKey + '" onfocus="TUser.tooltip()">' + row.gdKey + '</p>']
+ }
+ return btn;
+ }
+ },
+ {title: '使用状态', field: 'useStatus', visible: true, align: 'center', valign: 'middle',
+ formatter: function (value, row) {
+ var btn = "";
+ if(row.useStatus != '' && row.useStatus != null) {
+ if (row.useStatus == 1){
+ btn = ['<p class="toolTip" style="overflow:hidden;white-space:nowrap;text-overflow:ellipsis;" title="未使用" onfocus="TUser.tooltip()">未使用</p>']
+ } else if (row.useStatus == 2){
+ btn = ['<p class="toolTip" style="overflow:hidden;white-space:nowrap;text-overflow:ellipsis;color: #0d8ddb;" title="使用中" onfocus="TUser.tooltip()">使用中</p>']
+ } else if (row.useStatus == 3){
+ btn = ['<p class="toolTip" style="overflow:hidden;white-space:nowrap;text-overflow:ellipsis;color: red;" title="已用完" onfocus="TUser.tooltip()">已用完</p>']
+ }
+ }
+ return btn;
+ }
+ },
+ {title: '状态', field: 'status', visible: true, align: 'center', valign: 'middle',
+ formatter: function (value, row) {
+ var btn = "";
+ if(row.status != '' && row.status != null) {
+ if (row.status == 1){
+ btn = ['<p class="toolTip" style="overflow:hidden;white-space:nowrap;text-overflow:ellipsis;color: #0d8ddb;" title="启用" onfocus="TUser.tooltip()">启用</p>']
+ } else if (row.status == 2){
+ btn = ['<p class="toolTip" style="overflow:hidden;white-space:nowrap;text-overflow:ellipsis;color: red;" title="禁用" onfocus="TUser.tooltip()">禁用</p>']
+ }
+ }
+ return btn;
+ }
+ },
+ {title: '删除状态', field: 'delFlag', visible: true, align: 'center', valign: 'middle',
+ formatter: function (value, row) {
+ var btn = "";
+ if(row.delFlag != '' && row.delFlag != null) {
+ if (row.delFlag == 0){
+ btn = ['<p class="toolTip" style="overflow:hidden;white-space:nowrap;text-overflow:ellipsis;" title="未删除" onfocus="TUser.tooltip()">未删除</p>']
+ } else if (row.delFlag == 1){
+ btn = ['<p class="toolTip" style="overflow:hidden;white-space:nowrap;text-overflow:ellipsis;color: red;" title="已删除" onfocus="TUser.tooltip()">已删除</p>']
+ }
+ }
+ return btn;
+ }
+ },
+ {title: '添加时间', field: 'insertTime', visible: true, align: 'center', valign: 'middle',width:'12%',
+ formatter: function (value, row) {
+ var btn = "";
+ if(row.insertTime != '' && row.insertTime != null) {
+ var time = row.insertTime.replace(" ",'<br>');
+ btn = ['<p class="toolTip" style="overflow:hidden;white-space:nowrap;text-overflow:ellipsis;" title="' + row.insertTime + '" onfocus="TUser.tooltip()">' + time + '</p>']
+ }
+ return btn;
+ }
+ }
+ ];
+};
+
+/**
+ * 检查是否选中
+ */
+TGaodeAccount.check = function () {
+ var selected = $('#' + this.id).bootstrapTable('getSelections');
+ if(selected.length == 0){
+ Feng.info("请先选中表格中的某一记录!");
+ return false;
+ }else{
+ TGaodeAccount.seItem = selected[0];
+ return true;
+ }
+};
+
+/**
+ * 点击添加高德地图账号
+ */
+TGaodeAccount.openAddTGaodeAccount = function () {
+ var index = layer.open({
+ type: 2,
+ title: '添加高德地图账号',
+ area: ['100%', '100%'], //宽高
+ fix: false, //不固定
+ maxmin: true,
+ content: Feng.ctxPath + '/tGaodeAccount/tGaodeAccount_add'
+ });
+ this.layerIndex = index;
+};
+
+/**
+ * 打开编辑高德地图账号
+ */
+TGaodeAccount.openTGaodeAccountDetail = function () {
+ if (this.check()) {
+ var index = layer.open({
+ type: 2,
+ title: '编辑高德地图账号',
+ area: ['100%', '100%'], //宽高
+ fix: false, //不固定
+ maxmin: true,
+ content: Feng.ctxPath + '/tGaodeAccount/tGaodeAccount_update/' + TGaodeAccount.seItem.id
+ });
+ this.layerIndex = index;
+ }
+};
+
+/**
+ * 删除高德地图账号
+ */
+TGaodeAccount.delete = function () {
+ if (this.check()) {
+ var gdKey = TGaodeAccount.seItem.gdKey;
+ if (gdKey == "" || gdKey == null || gdKey == undefined) {
+ gdKey = "该记录";
+ } else {
+ gdKey = "【" + gdKey + "】";
+ }
+ swal({
+ title: "您是否确认删除" + gdKey + "?",
+ text: "请谨慎操作,删除后不可恢复!",
+ type: "warning",
+ showCancelButton: true,
+ confirmButtonColor: "#DD6B55",
+ confirmButtonText: "删除",
+ closeOnConfirm: false
+ }, function () {
+ var ajax = new $ax(Feng.ctxPath + "/tGaodeAccount/delete", function (data) {
+ swal("删除成功", "您已经成功删除了" + gdKey + "。", "success");
+ TGaodeAccount.table.refresh();
+ }, function (data) {
+ swal("删除失败", data.responseJSON.message + "!", "warning");
+ });
+ ajax.set("tGaodeAccountId",TGaodeAccount.seItem.id);
+ ajax.start();
+ });
+ }
+};
+
+/**
+ * 启用
+ */
+TGaodeAccount.enable = function(){
+ if (this.check()) {
+ var gdKey = TGaodeAccount.seItem.gdKey;
+ if (gdKey == "" || gdKey == null || gdKey == undefined) {
+ gdKey = "该记录";
+ } else {
+ gdKey = "【" + gdKey + "】";
+ }
+ if (TGaodeAccount.seItem.status == 1) {
+ swal("启用失败", "【启用】状态下无需执行此操作", "warning");
+ return;
+ } else {
+ swal({
+ title: "您是否确认启用" + gdKey + "?",
+ text: "请谨慎操作!",
+ type: "warning",
+ showCancelButton: true,
+ confirmButtonColor: "#DD6B55",
+ confirmButtonText: "启用",
+ closeOnConfirm: false
+ }, function () {
+ var ajax = new $ax(Feng.ctxPath + "/tGaodeAccount/opt", function (data) {
+ swal("启用成功", "您已经成功启用了" + gdKey + "。", "success");
+ TGaodeAccount.table.refresh();
+ }, function (data) {
+ swal("启用失败", data.responseJSON.message + "!", "warning");
+ });
+ ajax.set("tGaodeAccountId", TGaodeAccount.seItem.id);
+ ajax.set("optType", 1);
+ ajax.start();
+ });
+ }
+ }
+}
+
+/**
+ * 禁用
+ */
+TGaodeAccount.disable = function(){
+ if (this.check()) {
+ var gdKey = TGaodeAccount.seItem.gdKey;
+ if (gdKey == "" || gdKey == null || gdKey == undefined) {
+ gdKey = "该记录";
+ } else {
+ gdKey = "【" + gdKey + "】";
+ }
+ if (TGaodeAccount.seItem.status == 2) {
+ swal("禁用失败", "【禁用】状态下无需执行此操作", "warning");
+ return;
+ } else {
+ swal({
+ title: "您是否确认禁用" + gdKey + "?",
+ text: "请谨慎操作!",
+ type: "warning",
+ showCancelButton: true,
+ confirmButtonColor: "#DD6B55",
+ confirmButtonText: "禁用",
+ closeOnConfirm: false
+ }, function () {
+ var ajax = new $ax(Feng.ctxPath + "/tGaodeAccount/opt", function (data) {
+ swal("禁用成功", "您已经成功禁用了" + gdKey + "。", "success");
+ TGaodeAccount.table.refresh();
+ }, function (data) {
+ swal("禁用失败", data.responseJSON.message + "!", "warning");
+ });
+ ajax.set("tGaodeAccountId", TGaodeAccount.seItem.id);
+ ajax.set("optType", 2);
+ ajax.start();
+ });
+ }
+ }
+}
+
+/**
+ * 查询高德地图账号列表
+ */
+TGaodeAccount.search = function () {
+ var queryData = {};
+ queryData['gdKey'] = $("#gdKey").val();
+ queryData['useStatus'] = $("#useStatus").val();
+ queryData['status'] = $("#status").val();
+ TGaodeAccount.table.refresh({query: queryData});
+};
+TGaodeAccount.resetSearch = function () {
+ $("#gdKey").val("");
+ $("#useStatus").val("");
+ $("#status").val("");
+ TGaodeAccount.search();
+};
+
+$(function () {
+ var defaultColunms = TGaodeAccount.initColumn();
+ var table = new BSTable(TGaodeAccount.id, "/tGaodeAccount/list", defaultColunms);
+ table.setPaginationType("server");
+ TGaodeAccount.table = table.init();
+});
diff --git a/ManagementFBTravel/guns-admin/src/main/webapp/static/modular/system/tGaodeAccount/tGaodeAccount_info.js b/ManagementFBTravel/guns-admin/src/main/webapp/static/modular/system/tGaodeAccount/tGaodeAccount_info.js
new file mode 100644
index 0000000..c69e5b4
--- /dev/null
+++ b/ManagementFBTravel/guns-admin/src/main/webapp/static/modular/system/tGaodeAccount/tGaodeAccount_info.js
@@ -0,0 +1,133 @@
+/**
+ * 初始化高德地图账号详情对话框
+ */
+var TGaodeAccountInfoDlg = {
+ gaodeAccountInfoData : {},
+ validateFields: {
+ gdKey: {
+ validators: {
+ notEmpty: {
+ message: '高德key不能为空'
+ }
+ }
+ },
+ useStatus: {
+ validators: {
+ notEmpty: {
+ message: '请先选择使用状态'
+ }
+ }
+ },
+ status: {
+ validators: {
+ notEmpty: {
+ message: '请先选择状态'
+ }
+ }
+ },
+ }
+};
+
+/**
+ * 验证数据是否为空
+ */
+TGaodeAccountInfoDlg.validate = function () {
+ $('#gaodeAccountInfoForm').data("bootstrapValidator").resetForm();
+ $('#gaodeAccountInfoForm').bootstrapValidator('validate');
+ return $("#gaodeAccountInfoForm").data('bootstrapValidator').isValid();
+};
+
+
+/**
+ * 清除数据
+ */
+TGaodeAccountInfoDlg.clearData = function() {
+ this.gaodeAccountInfoData = {};
+}
+
+/**
+ * 设置对话框中的数据
+ *
+ * @param key 数据的名称
+ * @param val 数据的具体值
+ */
+TGaodeAccountInfoDlg.set = function(key, val) {
+ this.gaodeAccountInfoData[key] = (typeof val == "undefined") ? $("#" + key).val() : val;
+ return this;
+}
+
+/**
+ * 设置对话框中的数据
+ *
+ * @param key 数据的名称
+ * @param val 数据的具体值
+ */
+TGaodeAccountInfoDlg.get = function(key) {
+ return $("#" + key).val();
+}
+
+/**
+ * 关闭此对话框
+ */
+TGaodeAccountInfoDlg.close = function() {
+ parent.layer.close(window.parent.TGaodeAccount.layerIndex);
+}
+
+/**
+ * 收集数据
+ */
+TGaodeAccountInfoDlg.collectData = function() {
+ this
+ .set('id')
+ .set('gdKey')
+ .set('useStatus')
+ .set('status');
+}
+
+/**
+ * 提交添加
+ */
+TGaodeAccountInfoDlg.addSubmit = function() {
+
+ this.clearData();
+ this.collectData();
+ if(!this.validate()){
+ return ;
+ }
+ //提交信息
+ var ajax = new $ax(Feng.ctxPath + "/tGaodeAccount/add", function(data){
+ Feng.success("添加成功!");
+ window.parent.TGaodeAccount.table.refresh();
+ TGaodeAccountInfoDlg.close();
+ },function(data){
+ Feng.error("添加失败!" + data.responseJSON.message + "!");
+ });
+ ajax.set(this.gaodeAccountInfoData);
+ ajax.start();
+}
+
+/**
+ * 提交修改
+ */
+TGaodeAccountInfoDlg.editSubmit = function() {
+
+ this.clearData();
+ this.collectData();
+ if(!this.validate()){
+ return ;
+ }
+ //提交信息
+ var ajax = new $ax(Feng.ctxPath + "/tGaodeAccount/update", function(data){
+ Feng.success("修改成功!");
+ window.parent.TGaodeAccount.table.refresh();
+ TGaodeAccountInfoDlg.close();
+ },function(data){
+ Feng.error("修改失败!" + data.responseJSON.message + "!");
+ });
+ ajax.set(this.gaodeAccountInfoData);
+ ajax.start();
+}
+
+$(function() {
+ Feng.initValidator("gaodeAccountInfoForm", TGaodeAccountInfoDlg.validateFields);
+});
--
Gitblit v1.7.1