commit
129798102e
1
qieziBackend/.gitignore
vendored
1
qieziBackend/.gitignore
vendored
@ -31,3 +31,4 @@ build/
|
|||||||
|
|
||||||
### VS Code ###
|
### VS Code ###
|
||||||
.vscode/
|
.vscode/
|
||||||
|
/src/main/resources/application-local.yml
|
||||||
|
@ -73,6 +73,13 @@
|
|||||||
<artifactId>hutool-all</artifactId>
|
<artifactId>hutool-all</artifactId>
|
||||||
<version>5.7.21</version>
|
<version>5.7.21</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>easyexcel</artifactId>
|
||||||
|
<version>3.1.3</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -2,6 +2,7 @@ package com.fanxb.backend.controller;
|
|||||||
|
|
||||||
import com.fanxb.backend.entity.ResultObject;
|
import com.fanxb.backend.entity.ResultObject;
|
||||||
import com.fanxb.backend.entity.dto.ApplicationSignDto;
|
import com.fanxb.backend.entity.dto.ApplicationSignDto;
|
||||||
|
import com.fanxb.backend.entity.vo.ApplicationSignVo;
|
||||||
import com.fanxb.backend.service.ApplicationService;
|
import com.fanxb.backend.service.ApplicationService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
@ -49,4 +50,28 @@ public class ApplicationController {
|
|||||||
, @NotBlank(message = "key不能为空") String key, @NotBlank(message = "path不能为空") String path, @RequestParam(defaultValue = "false") boolean notAdd) throws IOException {
|
, @NotBlank(message = "key不能为空") String key, @NotBlank(message = "path不能为空") String path, @RequestParam(defaultValue = "false") boolean notAdd) throws IOException {
|
||||||
applicationService.visit(request, response, callBack, key, path, notAdd);
|
applicationService.visit(request, response, callBack, key, path, notAdd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查key,secret是否存在
|
||||||
|
*
|
||||||
|
* @author fanxb
|
||||||
|
* date 2022/2/16 15:24
|
||||||
|
*/
|
||||||
|
@PostMapping("/check")
|
||||||
|
public ResultObject check(@Validated @RequestBody ApplicationSignVo body) {
|
||||||
|
return ResultObject.success(applicationService.check(body));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载统计数据
|
||||||
|
*
|
||||||
|
* @return com.fanxb.backend.entity.ResultObject
|
||||||
|
* @author fanxb
|
||||||
|
* date 2022-11-25 15:26
|
||||||
|
*/
|
||||||
|
@GetMapping("/download")
|
||||||
|
public void download(String key, String secret, HttpServletResponse response) throws Exception {
|
||||||
|
applicationService.download(key, secret, response);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import com.fanxb.backend.entity.po.DetailPagePo;
|
|||||||
import com.fanxb.backend.entity.po.HostPo;
|
import com.fanxb.backend.entity.po.HostPo;
|
||||||
import org.apache.ibatis.annotations.*;
|
import org.apache.ibatis.annotations.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author fanxb
|
* @author fanxb
|
||||||
* @date 2022/2/15 16:37
|
* @date 2022/2/15 16:37
|
||||||
@ -45,4 +47,15 @@ public interface DetailPageDao {
|
|||||||
*/
|
*/
|
||||||
@Update("update detail_page set uv=uv+#{uvIncrement},pv=pv+1 where id=#{id}")
|
@Update("update detail_page set uv=uv+#{uvIncrement},pv=pv+1 where id=#{id}")
|
||||||
void updateUvPv(@Param("id") int id, @Param("uvIncrement") int uvIncrement);
|
void updateUvPv(@Param("id") int id, @Param("uvIncrement") int uvIncrement);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据hostId查询数据
|
||||||
|
*
|
||||||
|
* @param hostId hostId
|
||||||
|
* @return java.util.List<com.fanxb.backend.entity.po.DetailPagePo>
|
||||||
|
* @author fanxb
|
||||||
|
* date 2022-11-25 15:47
|
||||||
|
*/
|
||||||
|
@Select("select * from detail_page where hostId=#{hostId}")
|
||||||
|
List<DetailPagePo> selectByHostId(int hostId);
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,18 @@ public interface HostDao {
|
|||||||
@Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "id")
|
@Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "id")
|
||||||
void insertOne(HostPo host);
|
void insertOne(HostPo host);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查key,secret是否存在
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @param secret secret
|
||||||
|
* @return boolean
|
||||||
|
* @author fanxb
|
||||||
|
* date 2022-11-24 23:06
|
||||||
|
*/
|
||||||
|
@Select("select * from host where `key`=#{key} and secret=#{secret} limit 1")
|
||||||
|
HostPo selectByKeyAndSecret(@Param("key") String key, @Param("secret") String secret);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据key获取id
|
* 根据key获取id
|
||||||
*
|
*
|
||||||
|
@ -3,6 +3,8 @@ package com.fanxb.backend.dao;
|
|||||||
import com.fanxb.backend.entity.po.HostDayPo;
|
import com.fanxb.backend.entity.po.HostDayPo;
|
||||||
import org.apache.ibatis.annotations.*;
|
import org.apache.ibatis.annotations.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author fanxb
|
* @author fanxb
|
||||||
*/
|
*/
|
||||||
@ -38,4 +40,15 @@ public interface HostDayDao {
|
|||||||
*/
|
*/
|
||||||
@Update("update host_day set uv=uv+#{uvIncrement},pv=pv+#{pvIncrement} where id=#{id}")
|
@Update("update host_day set uv=uv+#{uvIncrement},pv=pv+#{pvIncrement} where id=#{id}")
|
||||||
void updatePvUv(@Param("id") int id, @Param("pvIncrement") int pvIncrement, @Param("uvIncrement") int uvIncrement);
|
void updatePvUv(@Param("id") int id, @Param("pvIncrement") int pvIncrement, @Param("uvIncrement") int uvIncrement);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据hostId查询
|
||||||
|
*
|
||||||
|
* @param hostId hostId
|
||||||
|
* @return java.util.List<com.fanxb.backend.entity.po.HostDayPo>
|
||||||
|
* @author fanxb
|
||||||
|
* date 2022-11-25 15:41
|
||||||
|
*/
|
||||||
|
@Select("select * from host_day where hostId=#{hostId}")
|
||||||
|
List<HostDayPo> selectByHostId(int hostId);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.fanxb.backend.entity.bo;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
|
import com.fanxb.backend.entity.po.DetailPagePo;
|
||||||
|
import com.fanxb.backend.entity.po.HostDayPo;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class ReportDetailPageBo {
|
||||||
|
@ExcelProperty(value = "页面路径")
|
||||||
|
private String path;
|
||||||
|
@ExcelProperty(value = "PV")
|
||||||
|
private long pv;
|
||||||
|
@ExcelProperty(value = "UV")
|
||||||
|
private long uv;
|
||||||
|
|
||||||
|
public ReportDetailPageBo(DetailPagePo po) {
|
||||||
|
BeanUtil.copyProperties(po, this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package com.fanxb.backend.entity.bo;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
|
import com.fanxb.backend.entity.po.HostPo;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class ReportHostBo {
|
||||||
|
@ExcelProperty(value = "站点名称")
|
||||||
|
private String name;
|
||||||
|
@ExcelProperty(value = "站点地址")
|
||||||
|
private String host;
|
||||||
|
@ExcelProperty(value = "PV")
|
||||||
|
private Integer pv;
|
||||||
|
@ExcelProperty(value = "UV")
|
||||||
|
private Integer uv;
|
||||||
|
|
||||||
|
public ReportHostBo(HostPo hostPo) {
|
||||||
|
BeanUtil.copyProperties(hostPo, this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.fanxb.backend.entity.bo;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
|
import com.fanxb.backend.entity.po.HostDayPo;
|
||||||
|
import com.fanxb.backend.entity.po.HostPo;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class ReportHostDayBo {
|
||||||
|
@ExcelProperty(value = "日期")
|
||||||
|
private String date;
|
||||||
|
@ExcelProperty(value = "PV")
|
||||||
|
private long pv;
|
||||||
|
@ExcelProperty(value = "UV")
|
||||||
|
private long uv;
|
||||||
|
|
||||||
|
public ReportHostDayBo(HostDayPo po) {
|
||||||
|
String temp = String.valueOf(po.getDayNum());
|
||||||
|
this.date = temp.substring(0, 4) + "-" + temp.substring(4, 6) + "-" + temp.substring(6);
|
||||||
|
this.pv = po.getPv();
|
||||||
|
this.uv = po.getUv();
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,8 @@ import lombok.AllArgsConstructor;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应用注册vo
|
* 应用注册vo
|
||||||
*
|
*
|
||||||
@ -14,6 +16,8 @@ import lombok.NoArgsConstructor;
|
|||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class ApplicationSignVo {
|
public class ApplicationSignVo {
|
||||||
|
@NotBlank(message = "key不能为空")
|
||||||
private String key;
|
private String key;
|
||||||
|
@NotBlank(message = "secret不能为空")
|
||||||
private String secret;
|
private String secret;
|
||||||
}
|
}
|
||||||
|
@ -38,4 +38,25 @@ public interface ApplicationService {
|
|||||||
* date 2022/2/16 10:20
|
* date 2022/2/16 10:20
|
||||||
*/
|
*/
|
||||||
void visit(HttpServletRequest request, HttpServletResponse response, String callBack, String key, String path, boolean notAdd) throws IOException;
|
void visit(HttpServletRequest request, HttpServletResponse response, String callBack, String key, String path, boolean notAdd) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查key,secret是否存在
|
||||||
|
*
|
||||||
|
* @param body body
|
||||||
|
* @return boolean
|
||||||
|
* @author fanxb
|
||||||
|
* date 2022-11-24 23:05
|
||||||
|
*/
|
||||||
|
boolean check(ApplicationSignVo body);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载站点数据
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @param secret secret
|
||||||
|
* @param response response
|
||||||
|
* @author fanxb
|
||||||
|
* date 2022-11-25 15:27
|
||||||
|
*/
|
||||||
|
void download(String key, String secret, HttpServletResponse response) throws Exception;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ package com.fanxb.backend.service.impl;
|
|||||||
|
|
||||||
import cn.hutool.core.util.IdUtil;
|
import cn.hutool.core.util.IdUtil;
|
||||||
import cn.hutool.http.Header;
|
import cn.hutool.http.Header;
|
||||||
|
import com.alibaba.excel.EasyExcel;
|
||||||
|
import com.alibaba.excel.ExcelWriter;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.fanxb.backend.constants.CommonConstant;
|
import com.fanxb.backend.constants.CommonConstant;
|
||||||
import com.fanxb.backend.constants.RedisConstant;
|
import com.fanxb.backend.constants.RedisConstant;
|
||||||
@ -9,6 +11,9 @@ import com.fanxb.backend.dao.DetailPageDao;
|
|||||||
import com.fanxb.backend.dao.DetailPageDayDao;
|
import com.fanxb.backend.dao.DetailPageDayDao;
|
||||||
import com.fanxb.backend.dao.HostDao;
|
import com.fanxb.backend.dao.HostDao;
|
||||||
import com.fanxb.backend.dao.HostDayDao;
|
import com.fanxb.backend.dao.HostDayDao;
|
||||||
|
import com.fanxb.backend.entity.bo.ReportDetailPageBo;
|
||||||
|
import com.fanxb.backend.entity.bo.ReportHostBo;
|
||||||
|
import com.fanxb.backend.entity.bo.ReportHostDayBo;
|
||||||
import com.fanxb.backend.entity.dto.ApplicationSignDto;
|
import com.fanxb.backend.entity.dto.ApplicationSignDto;
|
||||||
import com.fanxb.backend.entity.exception.CustomBaseException;
|
import com.fanxb.backend.entity.exception.CustomBaseException;
|
||||||
import com.fanxb.backend.entity.po.DetailPageDayPo;
|
import com.fanxb.backend.entity.po.DetailPageDayPo;
|
||||||
@ -28,13 +33,17 @@ import org.springframework.stereotype.Service;
|
|||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应用管理
|
* 应用管理
|
||||||
@ -75,6 +84,12 @@ public class ApplicationServiceImpl implements ApplicationService {
|
|||||||
return new ApplicationSignVo(po.getKey(), po.getSecret());
|
return new ApplicationSignVo(po.getKey(), po.getSecret());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean check(ApplicationSignVo body) {
|
||||||
|
HostPo po = hostDao.selectByKeyAndSecret(body.getKey(), body.getSecret());
|
||||||
|
return po != null;
|
||||||
|
}
|
||||||
|
|
||||||
private static Pattern PATTERN = Pattern.compile("googlebot|bingbot|yandex|baiduspider|360Spider|Sogou Spider|Bytespider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest\\/0\\.|pinterestbot|slackbot|vkShare|W3C_Validator|whatsapp");
|
private static Pattern PATTERN = Pattern.compile("googlebot|bingbot|yandex|baiduspider|360Spider|Sogou Spider|Bytespider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest\\/0\\.|pinterestbot|slackbot|vkShare|W3C_Validator|whatsapp");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -201,4 +216,23 @@ public class ApplicationServiceImpl implements ApplicationService {
|
|||||||
return hostId;
|
return hostId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void download(String key, String secret, HttpServletResponse response) throws Exception {
|
||||||
|
HostPo po = hostDao.selectByKeyAndSecret(key, secret);
|
||||||
|
if (po == null) {
|
||||||
|
throw new CustomBaseException("key,secret不存在");
|
||||||
|
}
|
||||||
|
List<ReportHostBo> hostList = Collections.singletonList(new ReportHostBo(po));
|
||||||
|
List<ReportHostDayBo> hostDayList = hostDayDao.selectByHostId(po.getId()).stream().map(ReportHostDayBo::new).collect(Collectors.toList());
|
||||||
|
List<ReportDetailPageBo> detailPageList = detailPageDao.selectByHostId(po.getId()).stream().map(ReportDetailPageBo::new).collect(Collectors.toList());
|
||||||
|
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||||
|
response.setCharacterEncoding("utf-8");
|
||||||
|
String fileName = URLEncoder.encode(po.getName() + "-站点导出数据", StandardCharsets.UTF_8).replaceAll("\\+", "%20");
|
||||||
|
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
|
||||||
|
ExcelWriter writer = EasyExcel.write(response.getOutputStream()).build();
|
||||||
|
writer.write(hostList, EasyExcel.writerSheet(0, "站点数据").head(ReportHostBo.class).build());
|
||||||
|
writer.write(hostDayList, EasyExcel.writerSheet(1, "站点日数据").head(ReportHostDayBo.class).build());
|
||||||
|
writer.write(detailPageList, EasyExcel.writerSheet(2, "页面数据").head(ReportDetailPageBo.class).build());
|
||||||
|
writer.finish();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 4.2 KiB |
BIN
qiezi_front/public/ico.png
Normal file
BIN
qiezi_front/public/ico.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 332 KiB |
@ -1,11 +1,11 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="">
|
<html lang="zh">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
||||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
|
<link rel="icon" href="<%= BASE_URL %>ico.png" />
|
||||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
<title>茄子统计</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>
|
<noscript>
|
||||||
@ -15,9 +15,10 @@
|
|||||||
>
|
>
|
||||||
</noscript>
|
</noscript>
|
||||||
|
|
||||||
<div id="app"></div>
|
<div id="app" style="padding-top: 20vh"></div>
|
||||||
|
|
||||||
<!-- 页面PV -->
|
<!-- 页面PV -->
|
||||||
|
<div style="position: fixed; width: 100%; bottom: 0">
|
||||||
<div style="text-align: center">
|
<div style="text-align: center">
|
||||||
<div id="qieziStatisticHtmlPost" style="display: none">当前页面访问次数:<span id="qieziStatisticHtmlPostPv"></span>次 </div>
|
<div id="qieziStatisticHtmlPost" style="display: none">当前页面访问次数:<span id="qieziStatisticHtmlPostPv"></span>次 </div>
|
||||||
</div>
|
</div>
|
||||||
@ -26,6 +27,7 @@
|
|||||||
<div id="qieziStatisticHtmlHostPv" style="display: none">总访问次数:<span id="qieziStatisticHtmlHostPvValue"></span>次 </div>
|
<div id="qieziStatisticHtmlHostPv" style="display: none">总访问次数:<span id="qieziStatisticHtmlHostPvValue"></span>次 </div>
|
||||||
<div id="qieziStatisticHtmlHostUv" style="display: none"> 总访客数:<span id="qieziStatisticHtmlHostUvValue"></span>人</div>
|
<div id="qieziStatisticHtmlHostUv" style="display: none"> 总访客数:<span id="qieziStatisticHtmlHostUvValue"></span>人</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<script>
|
<script>
|
||||||
//设置实际部署的host和key
|
//设置实际部署的host和key
|
||||||
//window.qieziStatisticHost = "http://localhost:8080";
|
//window.qieziStatisticHost = "http://localhost:8080";
|
||||||
|
BIN
qiezi_front/public/indexResource/ico.png
Normal file
BIN
qiezi_front/public/indexResource/ico.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 332 KiB |
@ -4,15 +4,21 @@
|
|||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/ico.png" />
|
||||||
<title>茄子统计</title>
|
<title>茄子统计</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="app">
|
<div class="app">
|
||||||
免费UV,PV统计,也可直接使用,也可进行私有部署后使用。<br />
|
<div class="desc">
|
||||||
使用文档见:<a href="https://github.com/FleyX/qieziStatistics">开始使用</a>
|
个人站点UV、PV统计,支持页面显示,常用于个人博客展示阅读数。比如我的个人博客:<a href="https://blog.fleyx.com/">FleyX's Blog</a><br />
|
||||||
|
支持开箱即用,只需几行代码即可为您的站点加上统计数据。<br />
|
||||||
|
代码完全开源于<a href="https://github.com/FleyX/qieziStatistics">github</a>,因此也支持自行独立部署使用。<br />
|
||||||
|
支持站点数据excel导出,方便切换统计工具。<br />
|
||||||
|
<a href="/manage">开始使用吧</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 页面PV -->
|
<!-- 页面PV -->
|
||||||
|
<div style="position: fixed; bottom: 0; width: 100%">
|
||||||
<div style="text-align: center">
|
<div style="text-align: center">
|
||||||
<div id="qieziStatisticHtmlPost" style="display: none">当前页面访问次数:<span id="qieziStatisticHtmlPostPv"></span>次 </div>
|
<div id="qieziStatisticHtmlPost" style="display: none">当前页面访问次数:<span id="qieziStatisticHtmlPostPv"></span>次 </div>
|
||||||
</div>
|
</div>
|
||||||
@ -21,6 +27,7 @@
|
|||||||
<div id="qieziStatisticHtmlHostPv" style="display: none">总访问次数:<span id="qieziStatisticHtmlHostPvValue"></span>次 </div>
|
<div id="qieziStatisticHtmlHostPv" style="display: none">总访问次数:<span id="qieziStatisticHtmlHostPvValue"></span>次 </div>
|
||||||
<div id="qieziStatisticHtmlHostUv" style="display: none"> 总访客数:<span id="qieziStatisticHtmlHostUvValue"></span>人</div>
|
<div id="qieziStatisticHtmlHostUv" style="display: none"> 总访客数:<span id="qieziStatisticHtmlHostUvValue"></span>人</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<script>
|
<script>
|
||||||
//设置实际部署的host和key
|
//设置实际部署的host和key
|
||||||
//window.qieziStatisticHost = "http://localhost:8080";
|
//window.qieziStatisticHost = "http://localhost:8080";
|
||||||
@ -31,8 +38,13 @@
|
|||||||
.app {
|
.app {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
margin-top: 20vh;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
.desc {
|
||||||
|
font-size: 1.2em;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<router-view />
|
<router-view />
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted } from "@vue/runtime-core";
|
import { onMounted } from "@vue/runtime-core";
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@ -12,6 +12,11 @@ const routes = [
|
|||||||
name: "ApplicationSign",
|
name: "ApplicationSign",
|
||||||
component: () => import("../views/ApplicationSign"),
|
component: () => import("../views/ApplicationSign"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/download",
|
||||||
|
name: "DataDownload",
|
||||||
|
component: () => import("../views/download"),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="home">
|
<div class="home">
|
||||||
<router-link to="/application/sign">应用注册</router-link><br />
|
<router-link to="/application/sign">应用注册</router-link><br />
|
||||||
<router-link to="/manage">应用管理</router-link>
|
<router-link to="/download">数据下载</router-link><br />
|
||||||
|
<div style="padding-top: 1em">
|
||||||
|
<a href="https://blog.fleyx.com/blog/detail/20221125" target="_blank">使用文档</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
47
qiezi_front/src/views/download/index.vue
Normal file
47
qiezi_front/src/views/download/index.vue
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<template>
|
||||||
|
<div class="title">站点数据下载</div>
|
||||||
|
<a-form :model="form" :label-col="{ span: 4 }" :wrapper-col="{ span: 14 }" style="width: 80%; margin: 0 auto">
|
||||||
|
<a-form-item label="key">
|
||||||
|
<a-input type="text" v-model:value="form.key" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="secret">
|
||||||
|
<a-input type="text" v-model:value="form.secret" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item :wrapper-col="{ span: 14, offset: 4 }">
|
||||||
|
<a-button type="primary" @click="onSubmit">下载</a-button>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
<a id="download" :href="'/qiezi/api/application/download?key=' + form.key + '&secret=' + form.secret" download class="download-a">download</a>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, reactive } from "vue";
|
||||||
|
import { get, post } from "../../util/HttpUtil";
|
||||||
|
import { message } from "ant-design-vue";
|
||||||
|
|
||||||
|
let form = reactive({
|
||||||
|
key: "",
|
||||||
|
secret: "",
|
||||||
|
});
|
||||||
|
let keySecret = ref({});
|
||||||
|
let onSubmit = async () => {
|
||||||
|
let exist = await post("/application/check", null, form);
|
||||||
|
if (exist) {
|
||||||
|
document.getElementById("download").click();
|
||||||
|
} else {
|
||||||
|
message.error("key,secret不存在");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.title {
|
||||||
|
font-size: 2em;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 2em;
|
||||||
|
}
|
||||||
|
.download-a {
|
||||||
|
position: fixed;
|
||||||
|
left: -1000px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,18 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>应用管理</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { onMounted, ref, reactive } from "vue";
|
|
||||||
import { get, post } from "../util/HttpUtil";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="less" scoped>
|
|
||||||
.title {
|
|
||||||
font-size: 2em;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
.captchaItem {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
</style>
|
|
Loading…
x
Reference in New Issue
Block a user