新增 SIM 卡前端页面
This commit is contained in:
parent
43a1d36f18
commit
aa0ef8625d
@ -0,0 +1,213 @@
|
|||||||
|
package com.imdroid.beidou.controller;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONArray;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.imdroid.beidou.common.Role;
|
||||||
|
import com.imdroid.beidou.service.CommonExcelService;
|
||||||
|
import com.imdroid.secapi.dto.*;
|
||||||
|
import org.apache.http.HttpEntity;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClients;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class SimCardController extends BasicController {
|
||||||
|
// TODO:这里的常量应该写入 application.properties
|
||||||
|
private static final String BASE_URL = "http://120.78.169.220:8089";
|
||||||
|
private static final String USERNAME = "gzyzdz";
|
||||||
|
private static final String KEY = "632629d1269a202c9d49a574623e4e4c";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SimCardsMapper simCardsMapper;
|
||||||
|
|
||||||
|
@RequestMapping("/page/sim_status")
|
||||||
|
public String simStatus(Model m, HttpSession session) {
|
||||||
|
initModel(m, session);
|
||||||
|
|
||||||
|
return "/page/sim_status";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/sim/list")
|
||||||
|
@ResponseBody
|
||||||
|
public JSONObject list(HttpSession session,
|
||||||
|
int page,
|
||||||
|
int limit,
|
||||||
|
String searchType,
|
||||||
|
String searchContent,
|
||||||
|
Integer status) {
|
||||||
|
Page<SimCard> pageable = new Page<>(page, limit);
|
||||||
|
|
||||||
|
QueryWrapper<SimCard> queryWrapper = new QueryWrapper<>();
|
||||||
|
|
||||||
|
|
||||||
|
if (!StringUtils.isEmpty(searchContent)) {
|
||||||
|
switch(searchType) {
|
||||||
|
case "deviceId":
|
||||||
|
queryWrapper.like("deviceid", searchContent.trim());
|
||||||
|
break;
|
||||||
|
case "iccid":
|
||||||
|
queryWrapper.like("iccid", searchContent.trim());
|
||||||
|
break;
|
||||||
|
case "simNumber":
|
||||||
|
queryWrapper.like("msisdn", searchContent.trim());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (status != null) {
|
||||||
|
queryWrapper.eq("status", status);
|
||||||
|
}
|
||||||
|
|
||||||
|
queryWrapper.orderByDesc("updatetime");
|
||||||
|
IPage<SimCard> cs = simCardsMapper.selectPage(pageable, queryWrapper);
|
||||||
|
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
jsonObject.put("code", 0);
|
||||||
|
jsonObject.put("msg", "");
|
||||||
|
jsonObject.put("count", cs.getTotal());
|
||||||
|
jsonObject.put("data", cs.getRecords());
|
||||||
|
System.out.println(jsonObject.toString());
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/page/sim_traffic_query")
|
||||||
|
public String simTrafficQuery(Model m, HttpSession session) {
|
||||||
|
initModel(m, session);
|
||||||
|
|
||||||
|
return "/page/sim_traffic_query";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 代理转发
|
||||||
|
@RequestMapping("/api/proxy/sim/query")
|
||||||
|
@ResponseBody
|
||||||
|
public JSONObject proxySimQuery(
|
||||||
|
@RequestParam String type,
|
||||||
|
@RequestParam String content
|
||||||
|
){
|
||||||
|
CloseableHttpClient httpClient = null;
|
||||||
|
CloseableHttpResponse response = null;
|
||||||
|
try {
|
||||||
|
Map<String, String> params = new HashMap<>();
|
||||||
|
params.put("username", USERNAME);
|
||||||
|
params.put("key", KEY);
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case "iccid":
|
||||||
|
params.put("card", content);
|
||||||
|
break;
|
||||||
|
case "deviceId":
|
||||||
|
if (content.trim().isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("设备ID不能为空");
|
||||||
|
}
|
||||||
|
SimCard simCard = simCardsMapper.queryByDeviceId(content.trim());
|
||||||
|
if (simCard == null) {
|
||||||
|
throw new IllegalArgumentException("未找到该设备ID对应的SIM卡信息");
|
||||||
|
}
|
||||||
|
params.put("card", simCard.getIccid());
|
||||||
|
break;
|
||||||
|
case "simNumber":
|
||||||
|
params.put("card", content);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("无效的查询类型: " + type);
|
||||||
|
}
|
||||||
|
|
||||||
|
params.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
|
||||||
|
|
||||||
|
String signature = calculateSignature(params);
|
||||||
|
if (signature == null) {
|
||||||
|
throw new Exception("签名计算失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder urlBuilder = new StringBuilder(BASE_URL);
|
||||||
|
urlBuilder.append("/api/Service/QueryCard?");
|
||||||
|
urlBuilder.append("username=").append(USERNAME);
|
||||||
|
urlBuilder.append("&key=").append(KEY);
|
||||||
|
urlBuilder.append("&card=").append(params.get("card"));
|
||||||
|
urlBuilder.append("×tamp=").append(params.get("timestamp"));
|
||||||
|
urlBuilder.append("&signature=").append(signature);
|
||||||
|
|
||||||
|
httpClient = HttpClients.createDefault();
|
||||||
|
HttpGet httpGet = new HttpGet(urlBuilder.toString());
|
||||||
|
|
||||||
|
// System.out.println("Sending request: " + urlBuilder.toString());
|
||||||
|
response = httpClient.execute(httpGet);
|
||||||
|
HttpEntity entity = response.getEntity();
|
||||||
|
|
||||||
|
|
||||||
|
String result = EntityUtils.toString(entity);
|
||||||
|
// System.out.println("Received response: " + result);
|
||||||
|
|
||||||
|
return JSONObject.parseObject(result);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
// System.out.println("Query failed: " + e.getMessage());
|
||||||
|
JSONObject errorResponse = new JSONObject();
|
||||||
|
errorResponse.put("Status", 0);
|
||||||
|
errorResponse.put("Message", "查询失败: " + e.getMessage());
|
||||||
|
return errorResponse;
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (response != null) {
|
||||||
|
response.close();
|
||||||
|
}
|
||||||
|
if (httpClient != null) {
|
||||||
|
httpClient.close();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String calculateSignature(Map<String, String> params) {
|
||||||
|
try {
|
||||||
|
List<String> paramList = new ArrayList<>();
|
||||||
|
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||||
|
paramList.add(entry.getKey() + "=" + entry.getValue());
|
||||||
|
}
|
||||||
|
Collections.sort(paramList);
|
||||||
|
|
||||||
|
String paramString = String.join("&", paramList);
|
||||||
|
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||||
|
byte[] digest = md.digest(paramString.getBytes());
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (byte b : digest) {
|
||||||
|
sb.append(String.format("%02x", b));
|
||||||
|
}
|
||||||
|
String signature = sb.toString();
|
||||||
|
// System.out.println("Signature: " + signature);
|
||||||
|
return signature;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
//System.out.println("Signature: " + e.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -111,6 +111,26 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"title": "SIM卡管理",
|
||||||
|
"href": "",
|
||||||
|
"icon": "fa fa-signal",
|
||||||
|
"target": "_self",
|
||||||
|
"child": [
|
||||||
|
{
|
||||||
|
"title": "总览",
|
||||||
|
"href": "page/sim_status",
|
||||||
|
"icon": "fa fa-minus",
|
||||||
|
"target": "_self"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "卡信息查询",
|
||||||
|
"href": "page/sim_traffic_query",
|
||||||
|
"icon": "fa fa-minus",
|
||||||
|
"target": "_self"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"title": "数据推送",
|
"title": "数据推送",
|
||||||
"href": "",
|
"href": "",
|
||||||
|
|||||||
@ -93,6 +93,26 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"title": "SIM卡管理",
|
||||||
|
"href": "",
|
||||||
|
"icon": "fa fa-signal",
|
||||||
|
"target": "_self",
|
||||||
|
"child": [
|
||||||
|
{
|
||||||
|
"title": "总览",
|
||||||
|
"href": "page/sim_status",
|
||||||
|
"icon": "fa fa-minus",
|
||||||
|
"target": "_self"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "卡信息查询",
|
||||||
|
"href": "page/sim_traffic_query",
|
||||||
|
"icon": "fa fa-minus",
|
||||||
|
"target": "_self"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"title": "数据推送",
|
"title": "数据推送",
|
||||||
"href": "",
|
"href": "",
|
||||||
|
|||||||
278
sec-beidou/src/main/resources/templates/page/sim_status.html
Normal file
278
sec-beidou/src/main/resources/templates/page/sim_status.html
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>SIM卡信息查询</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="../lib/layui-v2.6.3/css/layui.css" media="all">
|
||||||
|
<link rel="stylesheet" href="../css/public.css" media="all">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="layuimini-container">
|
||||||
|
<div class="layuimini-main">
|
||||||
|
<fieldset class="table-search-fieldset">
|
||||||
|
<legend>搜索信息</legend>
|
||||||
|
<div style="margin: 10px 10px 10px 10px">
|
||||||
|
<form class="layui-form layui-form-pane" action="" id="searchForm">
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<div class="layui-inline">
|
||||||
|
<label class="layui-form-label">查询类型</label>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<select name="searchType" lay-verify="required">
|
||||||
|
<option value="deviceId">设备号</option>
|
||||||
|
<option value="iccid">ICCID</option>
|
||||||
|
<option value="simNumber">SIM卡号</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-inline">
|
||||||
|
<label class="layui-form-label">搜索内容</label>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<input type="text" name="searchContent" id="searchInput" autocomplete="off" class="layui-input">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-inline">
|
||||||
|
<label class="layui-form-label">状态</label>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<select name="status">
|
||||||
|
<option value="">全部</option>
|
||||||
|
<option value="1">待激活</option>
|
||||||
|
<option value="2">已激活</option>
|
||||||
|
<option value="3">停机</option>
|
||||||
|
<option value="4">注销</option>
|
||||||
|
<option value="5">库存</option>
|
||||||
|
<option value="6">可测试</option>
|
||||||
|
<option value="7">失效</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<div class="layui-inline">
|
||||||
|
<button type="submit" class="layui-btn layui-btn-primary" lay-submit lay-filter="searchSubmit"><i class="layui-icon"></i> 搜 索</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<div class="layui-tab layui-tab-card" lay-filter="data-tab">
|
||||||
|
<ul class="layui-tab-title">
|
||||||
|
<li class="layui-this">数据表格</li>
|
||||||
|
<li>流量图表</li>
|
||||||
|
</ul>
|
||||||
|
<div class="layui-tab-content">
|
||||||
|
<div class="layui-tab-item layui-show">
|
||||||
|
<table class="layui-hide" id="simTable" lay-filter="simTableFilter"></table>
|
||||||
|
</div>
|
||||||
|
<div class="layui-tab-item">
|
||||||
|
<div id="trafficChart" style="min-height:300px;padding: 10px"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="../js/lay-module/echarts/echartsTheme.js" charset="utf-8"></script>
|
||||||
|
<script src="../js/lay-module/echarts/echarts.js" charset="utf-8"></script>
|
||||||
|
<script src="../lib/layui-v2.6.3/layui.js" charset="utf-8"></script>
|
||||||
|
<script type="text/html" id="statusTpl">
|
||||||
|
{{# if(d.status === 1){ }}
|
||||||
|
<span class="layui-badge layui-bg-orange">待激活</span>
|
||||||
|
{{# } else if(d.status === 2){ }}
|
||||||
|
<span class="layui-badge layui-bg-green">已激活</span>
|
||||||
|
{{# } else if(d.status === 3){ }}
|
||||||
|
<span class="layui-badge layui-bg-red">停机</span>
|
||||||
|
{{# } else if(d.status === 4){ }}
|
||||||
|
<span class="layui-badge layui-bg-black">注销</span>
|
||||||
|
{{# } else if(d.status === 5){ }}
|
||||||
|
<span class="layui-badge layui-bg-blue">库存</span>
|
||||||
|
{{# } else if(d.status === 6){ }}
|
||||||
|
<span class="layui-badge layui-bg-cyan">可测试</span>
|
||||||
|
{{# } else if(d.status === 7){ }}
|
||||||
|
<span class="layui-badge">失效</span>
|
||||||
|
{{# } }}
|
||||||
|
</script>
|
||||||
|
<script th:inline="javascript">
|
||||||
|
|
||||||
|
layui.use(['form', 'table','layer','element'], function () {
|
||||||
|
var table = layui.table
|
||||||
|
,form = layui.form
|
||||||
|
,layer = layui.layer
|
||||||
|
,element = layui.element;
|
||||||
|
|
||||||
|
var flowChart;
|
||||||
|
function initEcharts() {
|
||||||
|
if (!flowChart) {
|
||||||
|
flowChart = echarts.init(document.getElementById('trafficChart'), 'theme');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function updateFlowChart(simData) {
|
||||||
|
initEcharts();
|
||||||
|
|
||||||
|
var used = parseFloat(simData.used) || 0;
|
||||||
|
var remaining = parseFloat(simData.remaining) || 0;
|
||||||
|
var total = parseFloat(simData.total) || (used + remaining);
|
||||||
|
|
||||||
|
var option = {
|
||||||
|
title: {
|
||||||
|
text: 'SIM卡流量使用情况',
|
||||||
|
left: 'center',
|
||||||
|
top: 20,
|
||||||
|
textStyle: {
|
||||||
|
fontSize: 16
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
formatter: '{a} <br/>{b}: {c}MB ({d}%)'
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
orient: 'horizontal', // 改为水平布局
|
||||||
|
bottom: 20, // 放在底部
|
||||||
|
left: 'center', // 居中对齐
|
||||||
|
itemWidth: 25,
|
||||||
|
itemHeight: 14
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '流量使用情况',
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['40%', '60%'], // 调整饼图大小
|
||||||
|
center: ['50%', '50%'], // 居中显示
|
||||||
|
avoidLabelOverlap: false,
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'outside', // 标签位置改为外部
|
||||||
|
formatter: function(params) {
|
||||||
|
return params.name + '\n' +
|
||||||
|
params.value + 'MB\n' +
|
||||||
|
params.percent + '%';
|
||||||
|
},
|
||||||
|
fontSize: 14,
|
||||||
|
lineHeight: 20
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: true,
|
||||||
|
length: 15,
|
||||||
|
length2: 10
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
value: used,
|
||||||
|
name: '已使用流量',
|
||||||
|
itemStyle: { color: '#FF5722' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: remaining,
|
||||||
|
name: '剩余流量',
|
||||||
|
itemStyle: { color: '#009688' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
document.getElementById('trafficChart').style.height = '400px';
|
||||||
|
|
||||||
|
flowChart.setOption(option);
|
||||||
|
flowChart.resize(); // 重新调整大小
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var data_cols = [
|
||||||
|
{field: 'deviceid', title: '设备号'},
|
||||||
|
{field: 'iccid', title: 'ICCID'},
|
||||||
|
{field: 'msisdn', title: 'SIM 卡号'},
|
||||||
|
{field: 'updatetime', title: '更新时间'},
|
||||||
|
{field: 'status', title: '状态',templet: '#statusTpl'},
|
||||||
|
{field: 'remaining', title: '剩余流量(MB)'},
|
||||||
|
{field: 'used', title: '已使用流量(MB)'},
|
||||||
|
{field: 'total', title: '总流量(MB)'}
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
form.render();
|
||||||
|
table.render({
|
||||||
|
elem: '#simTable',
|
||||||
|
url: '/sim/list',
|
||||||
|
toolbar: '#toolbarDemo', //开启头部工具栏
|
||||||
|
defaultToolbar: ['filter'],
|
||||||
|
cols: [
|
||||||
|
data_cols
|
||||||
|
],
|
||||||
|
limits: [20, 50, 100, 200, 300],
|
||||||
|
limit: 20,
|
||||||
|
page: true,
|
||||||
|
skin: 'line',
|
||||||
|
done: function(res) {
|
||||||
|
if(res.code !== 0) {
|
||||||
|
layer.msg(res.msg || '查询失败', {icon: 2});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
form.verify({
|
||||||
|
searchContent: function(value, item) {
|
||||||
|
var type = $('select[name="searchType"]').val();
|
||||||
|
if(!value) {
|
||||||
|
return '请输入搜索内容';
|
||||||
|
}
|
||||||
|
if(type === 'iccid' && !/^\d{19,20}$/.test(value)) {
|
||||||
|
return 'ICCID必须是19-20位数字';
|
||||||
|
}
|
||||||
|
if(type === 'simNumber' && !/^\d{11,13}$/.test(value)) {
|
||||||
|
return 'SIM卡号必须是11-13位数字';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
form.on('submit(searchSubmit)', function(data){
|
||||||
|
var loadIndex = layer.load(1);
|
||||||
|
table.reload('simTable', {
|
||||||
|
page: {
|
||||||
|
curr: 1
|
||||||
|
}
|
||||||
|
,where: {
|
||||||
|
searchType: data.field.searchType,
|
||||||
|
searchContent: data.field.searchContent,
|
||||||
|
status: data.field.status
|
||||||
|
}
|
||||||
|
,done: function(res) {
|
||||||
|
layer.close(loadIndex);
|
||||||
|
if(res.code !== 0) {
|
||||||
|
layer.msg(res.msg || '查询失败', {icon: 2});
|
||||||
|
} else if(res.count === 0) {
|
||||||
|
layer.msg('未找到符合条件的数据', {icon: 0});
|
||||||
|
}else if(res.count === 1) {
|
||||||
|
// 当查询结果只有一条数据时,使用该数据绘制饼图
|
||||||
|
updateFlowChart(res.data[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
//监听Tab切换,重新resize图表,否则显示不出来
|
||||||
|
element.on('tab(data-tab)', function(data){
|
||||||
|
if(data.index === 1 && flowChart) {
|
||||||
|
flowChart.resize();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听窗口大小变化
|
||||||
|
window.addEventListener('resize', function() {
|
||||||
|
if (flowChart) {
|
||||||
|
flowChart.resize();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -0,0 +1,290 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>SIM卡信息查询</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="../lib/layui-v2.6.3/css/layui.css" media="all">
|
||||||
|
<link rel="stylesheet" href="../css/public.css" media="all">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="layuimini-container">
|
||||||
|
<div class="layuimini-main">
|
||||||
|
<fieldset class="table-search-fieldset">
|
||||||
|
<legend>SIM卡相关信息聚合查询</legend>
|
||||||
|
<div style="margin: 10px 10px 10px 10px">
|
||||||
|
<form class="layui-form layui-form-pane" action="" id="searchForm">
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">搜索类型</label>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<select id="searchType" name="searchType" lay-search="" lay-filter="searchType">
|
||||||
|
<option value="iccid">ICCID</option>
|
||||||
|
<option value="deviceId">设备ID</option>
|
||||||
|
<option value="simNumber">SIM卡号</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<label class="layui-form-label">搜索内容</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<input type="text" id="searchInput" name="searchContent" autocomplete="off" placeholder="搜索内容" lay-verify="required" class="layui-input">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<div class="layui-inline">
|
||||||
|
<button type="button" class="layui-btn" onclick="searchSIM()" lay-submit lay-filter="searchSubmit"><i class="layui-icon"></i>搜索</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<div id="resultContainer" class="result-container layui-hide">
|
||||||
|
<div class="layui-card">
|
||||||
|
<div class="layui-card-body" id="resultContent">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="../lib/layui-v2.6.3/layui.js" charset="utf-8"></script>
|
||||||
|
<script>
|
||||||
|
layui.use(['form', 'layer', 'element'], function(){
|
||||||
|
var form = layui.form;
|
||||||
|
var layer = layui.layer;
|
||||||
|
var element = layui.element;
|
||||||
|
|
||||||
|
form.render();
|
||||||
|
form.on('submit(searchSubmit)', function(data){
|
||||||
|
searchSIM();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function searchSIM() {
|
||||||
|
const searchInput = document.getElementById('searchInput');
|
||||||
|
const searchContent = searchInput.value.trim();
|
||||||
|
const searchType = document.querySelector('select[name="searchType"]').value;
|
||||||
|
|
||||||
|
if (!searchContent) {
|
||||||
|
layer.msg('请输入搜索内容');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (searchType === 'iccid' && !/^\d{19,20}$/.test(searchContent)) {
|
||||||
|
layer.msg('ICCID必须是19-20位数字');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (searchType === 'simNumber' && !/^\d{11,13}$/.test(searchContent)) {
|
||||||
|
layer.msg('SIM卡号必须是11-13位数字');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const loadingIndex = layer.load(1, {
|
||||||
|
shade: [0.1, '#fff']
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch(`/api/proxy/sim/query?type=${searchType}&content=${searchContent}`)
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Network response was not ok');
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(result => {
|
||||||
|
layer.close(loadingIndex);
|
||||||
|
console.log('API Response:', result);
|
||||||
|
|
||||||
|
if (result.Status === 1 && result.Data) {
|
||||||
|
displayResult(result.Data);
|
||||||
|
} else {
|
||||||
|
layer.msg(result.Message || '查询失败');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
layer.close(loadingIndex);
|
||||||
|
console.error('Error:', error);
|
||||||
|
layer.msg('请求处理失败:' + error.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayResult(data) {
|
||||||
|
const resultContainer = document.getElementById('resultContainer');
|
||||||
|
const resultContent = document.getElementById('resultContent');
|
||||||
|
|
||||||
|
if (!resultContainer || !resultContent) {
|
||||||
|
console.error('Result container elements not found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resultContainer.classList.remove('layui-hide');
|
||||||
|
|
||||||
|
// 格式化状态和其他信息
|
||||||
|
const statusText = getStatusText(data.status);
|
||||||
|
const statusClass = getStatusClass(data.status);
|
||||||
|
const operatorText = getOperatorText(data.operatortype);
|
||||||
|
|
||||||
|
// 格式化流量数据
|
||||||
|
const gprsInfo = {
|
||||||
|
total: parseFloat(data.gprs?.total) || 0,
|
||||||
|
used: parseFloat(data.gprs?.used) || 0,
|
||||||
|
left: parseFloat(data.gprs?.left) || 0
|
||||||
|
};
|
||||||
|
|
||||||
|
const usagePercentage = calculateUsagePercentage(gprsInfo);
|
||||||
|
|
||||||
|
resultContent.innerHTML = `
|
||||||
|
<table class="layui-table">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td width="120">运营商</td>
|
||||||
|
<td>${operatorText}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>ICCID</td>
|
||||||
|
<td>${data.iccid || '-'}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>SIM卡号</td>
|
||||||
|
<td>${data.msisdn || '-'}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>IMSI</td>
|
||||||
|
<td>${data.imsi || '-'}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>套餐信息</td>
|
||||||
|
<td>
|
||||||
|
ID: ${data.packageid || '-'}<br>
|
||||||
|
名称: ${data.packagename || '-'}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>时间信息</td>
|
||||||
|
<td>
|
||||||
|
激活时间: ${data.activetime || '-'}<br>
|
||||||
|
有效期: ${data.starttime || '-'} 至 ${data.stoptime || '-'}<br>
|
||||||
|
沉默期结束: ${data.silentdate || '-'}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>状态</td>
|
||||||
|
<td><span class="layui-badge ${statusClass}">${statusText}</span></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>APN信息</td>
|
||||||
|
<td>
|
||||||
|
${data.apn ? `
|
||||||
|
<div>ID: ${data.apn.apnid || '-'}</div>
|
||||||
|
<div>状态: ${data.apn.status === '01' ?
|
||||||
|
'<span class="layui-badge layui-bg-green">在线</span>' :
|
||||||
|
'<span class="layui-badge layui-bg-gray">离线</span>'}</div>
|
||||||
|
<div>IP: ${data.apn.ip || '-'}</div>
|
||||||
|
<div>网络: ${getNetworkText(data.apn.rat)}</div>
|
||||||
|
<div>设备状态: ${data.apn.onoffstatus === '1' ?
|
||||||
|
'<span class="layui-badge layui-bg-green">开机</span>' :
|
||||||
|
'<span class="layui-badge layui-bg-gray">关机</span>'}</div>
|
||||||
|
` : '-'}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>GPRS流量</td>
|
||||||
|
<td>
|
||||||
|
<div class="layui-row">
|
||||||
|
<div class="layui-col-md4">总流量: ${formatFlowSize(gprsInfo.total)} MB</div>
|
||||||
|
<div class="layui-col-md4">已用: ${formatFlowSize(gprsInfo.used)} MB</div>
|
||||||
|
<div class="layui-col-md4">剩余: ${formatFlowSize(gprsInfo.left)} MB</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-progress layui-progress-big" style="margin-top: 10px;">
|
||||||
|
<div class="layui-progress-bar ${getProgressBarColor(gprsInfo)}"
|
||||||
|
style="width: ${usagePercentage}%">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
`;
|
||||||
|
|
||||||
|
// 重新渲染进度条
|
||||||
|
layui.element.render('progress');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStatusText(status) {
|
||||||
|
const statusMap = {
|
||||||
|
1: '待激活',
|
||||||
|
2: '已激活',
|
||||||
|
3: '停机',
|
||||||
|
4: '注销',
|
||||||
|
5: '库存',
|
||||||
|
6: '可测试',
|
||||||
|
7: '失效'
|
||||||
|
};
|
||||||
|
return statusMap[status] || '未知状态';
|
||||||
|
}
|
||||||
|
function getOperatorText(type) {
|
||||||
|
const operatorMap = {
|
||||||
|
1: '中国移动',
|
||||||
|
2: '中国联通',
|
||||||
|
3: '中国电信'
|
||||||
|
};
|
||||||
|
return operatorMap[type] || '未知运营商';
|
||||||
|
}
|
||||||
|
function getNetworkText(rat) {
|
||||||
|
const networkMap = {
|
||||||
|
'1': '3G',
|
||||||
|
'2': '2G',
|
||||||
|
'6': '4G',
|
||||||
|
'8': 'NB'
|
||||||
|
};
|
||||||
|
return networkMap[rat] || '未知网络';
|
||||||
|
}
|
||||||
|
function getStatusClass(status) {
|
||||||
|
const classMap = {
|
||||||
|
1: 'layui-bg-orange', // 待激活
|
||||||
|
2: 'layui-bg-green', // 已激活
|
||||||
|
3: 'layui-bg-red', // 停机
|
||||||
|
4: 'layui-bg-gray', // 注销
|
||||||
|
5: 'layui-bg-blue', // 库存
|
||||||
|
6: 'layui-bg-cyan', // 可测试
|
||||||
|
7: 'layui-bg-black' // 失效
|
||||||
|
};
|
||||||
|
return classMap[status] || 'layui-bg-gray';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getProgressBarColor(gprsInfo) {
|
||||||
|
const percentage = calculateUsagePercentage(gprsInfo);
|
||||||
|
if (percentage >= 90) return 'layui-bg-red';
|
||||||
|
if (percentage >= 70) return 'layui-bg-orange';
|
||||||
|
return 'layui-bg-green';
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateUsagePercentage(gprsInfo) {
|
||||||
|
// 确保所有值都是数字,并且total不为0
|
||||||
|
const total = parseFloat(gprsInfo.total) || 0;
|
||||||
|
const used = parseFloat(gprsInfo.used) || 0;
|
||||||
|
|
||||||
|
if (total <= 0) return 0;
|
||||||
|
|
||||||
|
const percentage = (used / total) * 100;
|
||||||
|
return Math.min(100, Math.round(percentage));
|
||||||
|
}
|
||||||
|
function formatFlowSize(size) {
|
||||||
|
if (typeof size !== 'number' || isNaN(size)) return '0.00';
|
||||||
|
return size.toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按回车键触发查询
|
||||||
|
document.getElementById('searchInput').addEventListener('keypress', function(e) {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
e.preventDefault();
|
||||||
|
searchSIM();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
x
Reference in New Issue
Block a user