一本码簿

众里寻码千百度,那段却在github处。

数据库设计通常包括:概念设计、逻辑设计和物理设计。

概念设计

概念设计是最顶层设计,包括实体、关系和约束。通常用E-R图表示,分局部E-R图和总E-R图,局部E-R图通常表示管理的一个或几个实体之间的关系及属性,总E-R图通常表示全部实体之间的关系,若实体较多忽略实体属性。若存在几个不相关的实体集,可分开表示,通常该处不表示数据字典。

概念设计图

逻辑设计

逻辑设计是概念设计的实施,表示与数据库类型无关的数据结构、数据类型、约束等相关描述。通常选择关系型数据模型,形式为二维表。

逻辑设计图

物理设计

物理设计是与选择数据库类型相关的具体实施,包括创建表结构、索引和约束等,形式为DDL描述的sql脚本。

1
2
3
4
5
6
7
8
9
CREATE TABLE Customer (
CustNo NUMBER NOT NULL,
CustName VARCHAR2(200) NOT NULL,
Street VARCHAR2(200) NOT NULL,
City VARCHAR2(200) NOT NULL,
State CHAR(2) NOT NULL,
Zip VARCHAR2(20) NOT NULL,
PRIMARY KEY (CustNo)
) ;

在封装地图前端API时,一开始在多层次深对象中无法获取类的实例变量,一开始用prototype上的一个属性代替,但是无法满足多个地图实例启动的要求,因为prototype属性是共享的。以下有三种解决方法。

在运行时绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function SubRun(input){
this._input=input;
}
SubRun.prototype.funs=function(){
const self=this;
return{
show:function(){
// console.log(this._input);
console.log(self._input);
}
}
}
let subRun=new SubRun("sub_run_example");
subRun.funs().show();

通过闭包返回一个函数可获取运行时指向实例的this,但是方法调用时多了一个括号,稍显麻烦。

使用Apply

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function SubApply(input){
this._input=input;
SuperApply.apply(this,arguments);
}
function SuperApply(input){
const self=this;
this._input=input;
this.base= {
show:function(){
console.log("from param: "+input);
console.log("from self: "+self._input);
}
};
this.funs={
show:function(){
console.log("from funs:");
self.base.show();
}
};
}
let subApply=new SubApply("sub_apply_example");
subApply.base.show();
subApply.funs.show();

改方法可解决this对象获取的问题,但是定义多个proto属性需重复写,不优雅。

使用Classs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
class SuperClass{
constructor(input){
this._input=input;
const self=this;
this.base= {
//使用lambda的方式获取this
show:()=>{
console.log("from param: "+input);
console.log("from self: "+this._input);
}
};
this.funs={
show:function(){
console.log("from funs lambda:");
self.base.show();
}
};
}
get self(){
return this;
}
get protoPropterty(){
// const self=this;
return {
property:()=>{
this.protoMethod();
console.log(this._input);
}
}
}
protoMethod(){
console.log("from proto :"+this._input);
}
}
class SubClass extends SuperClass{
constructor(input){
super(input);
this._input=input;
this.ori={
display:()=>{
console.log("from sub call");
this.funs.show();
}
}
}
}

let subClass=new SubClass("sub_class_example");
let subClass2=new SubClass("sub_class_example2");
// subClass.base.show();
// subClass.funs.show();
subClass.protoPropterty.property();
// subClass2.protoPropterty.property();
// subClass.protoMethod();
// subClass.ori.display();

若有多个原型属性,用const self=this的方法稍显繁琐,利用lambda的特性可在多层次深对象中直接获取指向实例的this。

idea

  • Ctrl+F12Alt+7 文件结构
  • Ctrl+Shift+E 最近更改的文件
  • Ctrl+Alt+B 跳转到方法实现处
  • Ctrl+”=/-” 当前方法展开、折叠
  • Ctrl+Shift+”=/-” 全部展开、折叠
  • Shift+F8 步出
  • Alt+F9 运行至光标处
  • Alt+2 收藏

linux

  • 查看一级目录大小:du -hd 1

tumx

  • ta 打开一个窗口
  • ts 创建一个窗口
  • tl 列出窗口
  • tkss 杀死一个窗口
  • tks 杀死全部

vim

  • /search_string\c 向下查找
  • ? 向上查找
  • :%s/foo/bar/gic 全局范围%查找foo并替换为bar,全局替换g,大小写敏感i,确认 c

nginx

  • nginx -V 查看详细信息(模块)

psql

  • sudo -u psql 进入psql
  • \l 列出数据库
  • \dt 列出表
  • \d [tablename] 列出表字段

regex

  • 部分替换

原始字符串:我是程序员
正则:(.*)(([^不是]|[^是]|)程序员)(.*)
替换为:4

  • 非捕捉组

Windows(?=95|98|NT|2000)
匹配 “Windows2000” 中的 “Windows”
不匹配 “Windows3.1” 中的 “Windows”

模式必须放后面(?=Windows)95无法匹配Windows95。
有回查类型的,例如:

2000(?<=Office|Word|Excel)
匹配 “ Office2000” 中的 “2000”
不匹配 “Windows2000” 中的 “2000”

但是回查类型的在Atom和Sublime Text3均无效。

记不住的

  • 开启SVN svnserve -d -r /mnt/d/svncode/project

其他

  • 批量重命名 for i infind -name ‘yale_*’;do mv $i ${i/yale/qsh};done
  • 批量替换文本内容 sed -i "s/yale/qsh/g" `grep yale -lr .`
  • 批量替换带空格的文件内容 grep "dc.zjchey.com" -lrZ hldc | xargs -0 sed -i "s/dc.zjchey.com/qsh.haies.cn/g"
  • docker输入宿主文件docker exec -i gogs-mysql mysql -uroot -pxxfY5019 gogs < win/gogs.sql

本次项目采用Springboot+Mybatis方式,使用注解式配置,增加全局异常处理,实现前端和后台参数传递过程下划线和驼峰法的自动转换。MyBatis官方没有提供基于Gradle的MyBtis Generator插件,因此沿用Maven做Build工具。


配置

application.yml关键配置

MyBatis配置如下:

1
2
3
4
5
mybatis:
mapper-locations: "classpath:mapper/*.xml"
type-aliases-package: "com.zjchey.dataManage.entity"
configuration:
map-underscore-to-camel-case: true

map-underscore-to-camel-case: true在生产代码时将数据库中下划线命名自动转为驼峰法命名代码。

Jackson配置如下:

1
2
3
jackson:
property-naming-strategy: SNAKE_CASE
defaultPropertyInclusion: NON_EMPTY

property-naming-strategy: SNAKE_CASE用于前端以application/json方式提交的POST请求的流参数转换,实现前端和后台双向自动下划线和驼峰法命名,后端接受参数的对象需要用@RequestBody修饰。
defaultPropertyInclusion: NON_EMPTY用于@ResponseBody修饰的接口在将对象转为json返回参数时,如果对象属性为null,则在json中忽略该属性。

注解配置

  1. 使用@Configuration修饰配置的类。
  2. 使用@Bean修饰的方法相当于xml配置中的bean标签,对应方法名为xml配置中的id属性,也可在用@Bean(name = "heou.net")的形式指定id。
  3. Spring的三种装配方式分别是:基于@Component@Autowired的隐式装配、基于@Configuration的Java显示装配和基于xml配置的显式装配。
  4. 在xml配置中,可通过构造器注入、setter注入的方式装配Bean。
  5. 在运行函数的类的配置如下:
1
2
3
@SpringBootApplication(scanBasePackages = "com.*.*")
@MapperScan("com.*.*.*")
@EnableTransactionManagement

@SpringBootApplication 包括@Configuration、@EnableAutoConfiguration和@ComponentScan三个注解。

排除tomcat使用undertow

Maven:

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>

Gradle:

1
2
3
4
5
6
7
8
9
configurations {
compile.exclude module: 'spring-boot-starter-tomcat'
}

dependencies {
compile('org.springframework.boot:spring-boot-starter-web'){
exclude module: 'spring-boot-starter-tomcat'
}
}

logback日志

1
2
3
4
5
6
7
logging:
file: projectname.log
path: .
pattern: "%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n"
level:
root: info
org.springframework.web: warn

可指定类的日志输出级别。

MyBatis

MyBatis分页

内存分页

使用RowBounds

1
loggerMapper.getLogsBySortASC(new RowBounds(0,10));

Mybatis拦截器

待实现

第三方组件

PageHelper

通用mapper

通过泛型实现所有的mapper的CRUD操作,减少代码量。待实现,目前有通用Mapper4

MyBatis Generator

POM配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.7</version>
<configuration>
<overwrite>true</overwrite>
</configuration>
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.5</version>
</dependency>
</dependencies>
</plugin>

generatorConfig配置

1
2
3
4
5
<context id="context" targetRuntime="MyBatis3">

<table tableName="user" domainObjectName="UserSample"
enableSelectByPrimaryKey="false" enableUpdateByPrimaryKey="false"
enableDeleteByPrimaryKey="false" delimitIdentifiers="true"/>

targetRuntime=”MyBatis3”生产的代码包括selectByExample,delimitIdentifiers=”true”确保表名加引号,即使使用关键字(例如user)也可以正常查询。

常用功能

全局异常处理

1
2
3
4
5
6
7
8
9
10
11
@ControllerAdvice
public class GlobalExceptionHandler {
private final Logger logger=LoggerFactory.getLogger(getClass());

@ResponseBody
@ExceptionHandler(value = Exception.class)
public Result handlerGlobalException(Exception ex){
logger.error(ex.getMessage());
return new Result(ex.getMessage(),ResultType.ERROR);
}
}

若业务代码中无异常处理,可捕获controller和service中的异常。

统一返回消息格式

1.定义错误代码与错误消息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public enum ResultType {
SUCCESS(200,"接口返回正常"),
FAILURE(5000,"接口返回失败"),
PARAMS_ERROR(5100,"提交参数错误"),
PARAMS_ERROR_MISS(5101,"必填参数缺失"),
PARAMS_ERROR_INVALID(5102,"参数无效"),
PERMISSION_DENIED(6000,"权限拒绝"),
DENIED_NOT_ROLE(6100,"角色权限拒绝"),
DENIED_NOT_ADMIN(6101,"非管理员权限"),
DENIED_NOT_USER(6102,"用户权限拒绝"),
ERROR(500,"接口调用错误"),
CUSTOM(999,"定制消息");

private Integer code;
private String msg;

ResultType(Integer code, String msg){
this.code=code;
this.msg=msg;
}
......
}

2.定义返回格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Result<T> {
@JsonIgnore
private ResultType resultType;
/*错误码*/
private Integer code;
/*提示信息 */
private String msg;
/*数据内容*/
private T data;

public Result(T data) {
this.data = data;
this.setResultType(null);
}

public Result(T data, ResultType resultType) {
this.data = data;
this.setResultType(resultType);
}
......
private void setResultType(ResultType type) {
this.resultType=type==null? ResultType.SUCCESS:type;
this.code= this.resultType.getCode();
this.msg= this.resultType.getMsg();
}
}

3.定义BaseController。

工具类使用

Google Guava

apache-commons-collections

apache-commons-fileupload

高级用法

数据库读写分离

redis二级缓存

统一前后端地址

使用反向代理

处理枚举

前后端字段下划线和驼峰法自动切换

指定property-naming-strategy: SNAKE_CASE
可实现后台到前端时的lowwer_camel转under_score但是,前端到后台时,后台接受参数的对象前加@RequestBody后,以Content-Type: application/json方式发POST请求时可以实现under_score转lowwer_camel
以application/x-www-form-urlencoded发POST请求时可以实现和Get请求均不能实现。

1.通过get请求或者application/x-www-form-urlencoded提交的POST请求

此情况下,参数可通过httpserveletRequest.getParams()获取

定义argumentreslover,如下:

1
2
3
class UnderScore2CamelArgumentResolver implements HandlerMethodArgumentResolver{
....
}

2.通过application/json提交的POST请求

此情况下,参数可通过httpserveletRequest.getInputStream()获取参数json流。

参考本文的Jackson配置

问题

Generator的xml文件如何读取application.yml内的内容

未解

yml中的日志名称改为项目名称

未解

Invalid bound statement (not found)

异常的全称如下:

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):

网上大多提到的是xml的mapper无法扫描到,要在启动类配置@MapperScan(“com.*“),但本项目一开始犯了各低级的错误,application.xml的datasource.url配置成了jdbc:postgres://***,应该是jdbc:postgresql://***

注解

格式化

  1. @DateTimeFormat(pattern=”yyyy-MM-dd”)是将String转换成Date,一般前台给后台传值时用
  2. @JsonFormat(pattern=”yyyy-MM-dd”) 将Date转换成String 一般后台传值给前台时
  3. @JsonDeserialize(using = CustomJsonDateDeserializer.class)
  4. @JsonSerialize(using= DateJsonSerializer.class)

配置属性

WinGet

常用软件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
winget install --id voidtools.Everything -h;
winget install --id VideoLAN.VLC -h;
winget install --id 7zip.7zip -h;
winget install --id Microsoft.Sysinternals.Suite -h;
winget install --id Obsidian.Obsidian -h;
winget install --id Google.Chrome -h;
winget install --id Mozilla.Firefox -h;
winget install --id Tencent.WeChat -h;
winget install --id Alibaba.DingTalk -h;
winget install --id Evernote.Evernote.CN -h;
winget install --id PixPin.PixPin -h;
winget install --id LocalSend.LocalSend -h;
winget install --id Kingsoft.WPSOffice-CN -h;
winget install --id Baidu.BaiduNetdisk -h;
winget install --id Tencent.QQ -h;
winget install --id Tencent.QQMusic -h;
winget install --id Tencent.TencentVideo -h;
winget install --id Tencent.TencentMeeting -h;
winget install --id Bilibili.Bilibili -h;
winget install --id QL-Win.QuickLook -h;
winget install --id AutoHotkey.AutoHotkey -h;
winget install --id Microsoft.PowerToys -h;
winget install --id ClashVergeRev.ClashVergeRev -h;
winget install --id Microsoft.PowerShell -h;
winget install --id Microsoft.VisualStudioCode -i;

一键安装

1
2
Set-ExecutionPolicy Bypass -Scope Process -Force;
irm https://haies.cn/assets/win-install.ps1 | iex;

一键优化

1
2
Set-ExecutionPolicy Bypass -Scope Process -Force;
irm https://debloat.raphi.re/ | iex;

工作软件

1
2
3
4
5
6
7
8
9
10
11
12
13
winget install --id OSGeo.QGIS_LTR -h;
winget install --id RealVNC.VNCViewer -h;
winget install --id Rufus.Rufus -h;
winget install --id WinSCP.WinSCP -h;
winget install --id TortoiseSVN.TortoiseSVN -h;
winget install --id JurgenRathlev.innounp -h;
winget install --id DBBrowserForSQLite.DBBrowserForSQLite -h;

winget install --id Canonical.Ubuntu -h;
winget install --id PremiumSoft.NavicatPremium -h;
winget install --id JetBrains.IntelliJIDEA.Ultimate -h;
winget install --id Microsoft.VisualStudio.Community -h;

Scoop

1
2
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser;
irm https://get.scoop.sh | iex;

scoop install git-with-openssh gitignore sudo busybox nodejs-lts -g
scoop install cmder yarn maven python -g

npm

npm i -g hexo-cli
npm i -g phantomjs-prebuilt
npm i -g vue-cli webpack-cli tldr

[其他]

一键集合

1
irm https://get.activated.win | iex

环境位置

  • Everything %AppData%\Everything\Everything.ini
  • SSH %HOMEPATH%\.ssh
  • Git %HOMEPATH%\.gitconfig

准备材料清单

服务

  • ZCEY ITISPR-33_服务级别管理程序-服务目录.xls
  • ZCEY ITISPR-33_服务级别管理程序-IT服务水平协议(SLA).docx
  • ZCEY ITISPR-33_服务级别管理程序-运营级别协议OLAS.doc

项目

  • 系统开发合同/开发任务单
  • 系统需求分析
  • 系统功能设计
  • 系统测试方案
  • 系统测试报告
  • 系统验收报告或功能点验收报告
  • 用户报告

运维

  • ZCEY ITISPR-22_事件管理程序-运维事件汇总记录单.xlsx
  • ZCEY ITISPR-22_事件管理程序-重大事件处理报告单.docx

其他

  • 系统变更记录
  • 系统会议记录
  • 系统巡检记录
  • 其他ITIS文件

安全服务协议

  • 服务目录
    服务目录需根据不同的系统进行定制。
  • 服务协议
  • 运营协议
  • 服务提供方式
    如果提供技术支持,提供系统支持过程记录单。
  • 服务评价
    用户报告、用户满意度调查

开发过程控制

  • 系统合同或开发任务书
    系类型为:为甲方开发的任务、为院生产开发的任务、出售软件服务。为甲方开发的任务需要提供系统开发合同,后两者需提供开发任务书。
  • 需求分析
    分功能性需求和非功能性需求。
  • 功能设计
    功能设计需以需求为核心,一般包括概要设计和详细设计。
  • 系统测试
    包括系统测试方案,测试报告。
  • 系统验收
    系统验收报告或功能点验收报告。
  • 系统发布
    系统发布方案
  • 系统运维
    提供系统运维记录。

信息安全保证

开发环境

  • 开发环境分内网环境和外网环境,如果开发过程涉及到涉密数据,开发的调试和测试需放在内网环境。
  • 主机登录需考虑密钥和IP限制。
  • 主机需进行端口访问和IP访问策略控制,采用阿里云管理访问策略。
  • 开发主机需要安装杀毒软件或购买相应的云安全服务,如安骑士等。

代码管理

  • 使用svn 和git进行版本控制,版本控制分成果和开发分支。
  • 开发人员需提交密钥后才能提交代码,且只能提交到开发分支。
  • 项目负责人需管理分支,进行code review后将新开发的功能或者改进的代码合并到成果分支。

系统安全

  • 系统使用需进行登录,和无操作登录超时操作,用户密码需要进行加密和弱密码限制策略。
  • 系统关键参数,如坐标转换参数需进行加密,且满足一定的加密强度。

数据安全

  • 系统和系统数据库进行定时和手动备份计划。
  • 系统代码和文档需在不同主机进行备份。
  • 系统进行关键数据操作时,提供回退操作,且能回退到操作前的数据状态。

常用坐标对应的EPSG编号

cgcs2000_geo: 4490
cgcs2000_3_gk_117E: 4548
cgcs2000_3_gk_120E: 4549
cgcs2000_3_gk_123E: 4550
wgs84_geo: 4326
web_mercator_auxiliary_sphere: 3875
web_mercator(google): 3785

管理命令

数据库备份

1
2
3
alias pgbackup='thisFun(){pg_dump -U postgres -F t -ovf /var/pgbak/$1_$(date '+%Y%m%d%H%M%S').tar $1};thisFun'
alias pgbak='pg_dump -h localhost -U postgres -F t -ovf /var/pgbak/njqdb.tar njqdb'
pg_dump -h localhost -U postgres -d njqwebdb > /hdc/njqdbbak/njqweb$(date '+%Y%m%d%H%M%S').bak -v

数据库恢复

1
2
3
alias pgrecover='thisFun(){var=${1%%_*};var=${var##*/};echo $var;pg_restore -U postgres -d ${var} -cv $1};thisFun'
alias pgrec='pg_restore -h localhost -U postgres -d njqdb -cv /var/pgbak/njqdb.tar
psql -h localhost -U postgres -d databasename < C:\databasename.bak

Linux管理

  • 登录数据库 sudo psql -u postgres
  • 导出到表格
1
COPY (SELECT a.corp_name,a.area_code,a.entity_code,b.addr_type,b.addr_content,b.symbol_code,b.geo_addr FROM geo_entity_info as a left join geo_space_info as b on a.corp_id=b.corp_id) TO '/mnt/d/a.csv' WITH csv HEADER;

开启模块扩展

  • 创建数据库

    1
    2
    create database geoTemplate;
    \c geoTemplate;
  • 启用空间数据库模块

    1
    2
    3
    4
    5
    6
    7
    CREATE EXTENSION postgis;
    CREATE EXTENSION pgrouting;
    CREATE EXTENSION postgis_topology;
    CREATE EXTENSION fuzzystrmatch;
    CREATE EXTENSION postgis_tiger_geocoder;
    CREATE EXTENSION address_standardizer;
    CREATE EXTENSION "uuid-ossp";

管理SQL

创建空间索引

  • CREATE INDEX name ON table USING gist(column);
  • CREATE INDEX name ON table USING gin(column);

查询所有数据库大小

1
select pg_database.datname, pg_size_pretty(pg_database_size(pg_database.datname)) AS size from pg_database ORDER BY size DESC

查看全部表大小

1
select relname, pg_size_pretty(pg_relation_size(relid)) from pg_stat_user_tables where schemaname='public' order by pg_relation_size(relid) desc

查看全部表索引大小

1
select indexrelname, pg_size_pretty(pg_relation_size(relid)) from pg_stat_user_indexes where schemaname='public' order by pg_relation_size(relid) desc

查看数据库连接情况

1
select * from pg_stat_activity

结束数据库连接

1
SELECT pg_terminate_backend(pid)  FROM pg_stat_activity WHERE datname='njqwebdb' AND pid<>pg_backend_pid()

查询数据库中的表

1
select * from pg_tables WHERE schemaname='public'

语句耗时统计

1
select * FROM pg_stat_statements ORDER BY total_time DESC

索引缓存命中率

1
2
3
4
5
6
SELECT
sum(idx_blks_read) as idx_read,
sum(idx_blks_hit) as idx_hit,
(sum(idx_blks_hit) - sum(idx_blks_read)) / sum(idx_blks_hit) as ratio
FROM
pg_statio_user_indexes;

查看数据库物理大小

1
select pg_size_pretty(pg_database_size('postgres'));

清空带外键约束的表格

TRUNCATE njq_user_basic CASCADE

导入函数创建脚本

1
select proname,  pg_get_functiondef(proname::regproc) from pg_proc where proname LIKE 'njq_%';

日常应用

导入数据库

1
shp2pgsql -a -D -s 4326 -W utf-8 point.shp geo_point > result.sql

-s 代表指定数据的SRID为3857
-c 代表数据将新建一个表
-d 删除旧的表,重新建表并插入数据
-a 向现有表中追加数据
-p 仅创建表结构,不添加数据,这四个参数是互斥的
-W Shape文件中属性的字符集,通常Postgresql的字符集是UTF-8,有时候可能Shape数据中的字符集是其他,就可能报“Unable to convert data value to UTF-8 (iconv reports “无效或不完整的多字节字符或宽字符”). Current encoding is “UTF-8”. Try “LATIN1” (Western European)”错误,这时候指定正确的字符集即可解决方问题。

常用查询

跨表查询统计

1
2
3
4
5
6
SELECT xcz_item.code,xcz_region."name","type","count"(xcz_item.code) AS count
FROM xcz_item
LEFT JOIN xcz_region
ON xcz_item.code LIKE '330604%' AND xcz_item.code=xcz_region.code
GROUP BY xcz_item.code,"type",xcz_region."name"
ORDER BY xcz_item.code ,"type"

跨表条件统计

1
2
3
4
5
6
7
8
9
10
SELECT DISTINCT a.code,a.name,
COALESCE(count(b.*),0) AS total,
sum(CASE WHEN b.state = 4 THEN 1 ELSE 0 END) AS finished,
sum(CASE WHEN b.state <>4 OR b.state IS NULL THEN 1 ELSE 0 END) AS unfinished,
st_astext(st_centroid(a.geom)) AS position
FROM xcz_region a left join xcz_item b
ON a.code=b.code
WHERE a.need=1 AND b.type='1001'
GROUP BY a.code,a.name,a.geom
ORDER BY a.code

图形操作

  • 空间查询
1
2
SELECT count(*) FROM njq_dk WHERE st_intersects(geom,st_geomfromtext('MULTIPOLYGON(((120.92 29.37,120.93 29.37,120.93 29.38,120.92 29.37,120.92 29.37)))',4326))
SELECT count(*) FROM njq_dk WHERE st_intersects(geom,st_geomfromtext('POLYGON((120.92 29.37,120.93 29.37,120.93 29.38,120.92 29.37,120.92 29.37))',4326))
  • 创建空间索引
1
2
3
4
5
create extension pg_trgm;
update pg_opclass set opcdefault = true where opcname='gin_trgm_ops';
CREATE index on njq_dk USING gist (geom);
CREATE index on njq_dk USING gin (geom gin_trgm_ops);

  • 外包多边形
1
select ST_AsText(ST_ConvexHull(ST_Collect(geom))) FROM xcz_region
  • 外包矩形
1
select ST_AsText(st_Envelope(ST_Collect(geom))) FROM xcz_region
  • 中心点(面质心)
1
select st_astext(st_centroid(geom)) FROM xcz_region
  • 面上点(和面lable位置一致)
1
select st_astext(st_PointOnSurface(geom)) FROM xcz_region

系统环境

1.安装node.js

2.安装cnpm

1
npm i -g cnpm --registry=https://registry.npm.taobao.org

3.安装vue-cli

1
cnpm i vue-cli

4.下载代码并进入代码目录下进行模块安装

1
cnpm i

IDEA配置

  1. File->settings->plugins 安装 node 插件和 vue.js 插件,重启IDEA
  2. 配置启动项如下图:
    启动项配置

相关知识点

  1. ES6
  2. vue.js
  3. vue-router
  4. vuex
  5. element-ui

结构图

结构图

获取文件夹指定类型的文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private File[] getFilterFiles(String path, String[] suffix) {

File baseFolder = new File(path);
if(!baseFolder.isDirectory())return null;

FileFilter imageFilter = pathname -> {
String fileName = pathname.getName().toLowerCase();
for (String s : suffix) {
if (fileName.endsWith(s.toLowerCase())) return true;
}
return false;
};

return baseFolder.listFiles(imageFilter);
}

二维表转树Json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class itemType;
class itemTypeTree extetends itemType{
List<itemTypeTree> children;
}

private List<ItemTypeTree> recursionNode(List<ItemType> list, ItemType itemTree) {

if(list==null)return null;
if(itemTree==null)itemTree=new ItemTypeTree();
return getChildNode(list,itemTree).stream()
.map(item -> {
if(getChildNode(list,item).size()>0){
item.setChildren(recursionNode(list,item));
}
return item;
})
.collect(Collectors.toList());
}
private List<ItemTypeTree> getChildNode(List<ItemType> list,ItemType itemTree){
return list.stream()
.filter(item -> {
if(StringUtils.isBlank(itemTree.getTypecode())){
return StringUtils.isBlank(item.getParentcode());
}else {
return item.getParentcode().equals(itemTree.getTypecode());
}
})
.map(itemType -> {
ItemTypeTree itemTypeTree=new ItemTypeTree();
BeanUtils.copyProperties(itemType,itemTypeTree);
return itemTypeTree;
})
.collect(Collectors.toList());
}
0%