diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f26bda4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +HELP.md +target/ +.DS_ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/** +!**/src/test/** + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +*.mvn +/logger/ +!**/logger/** +*mvnw* +*/logger/* + + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ + +### VS Code ### +.vscode/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..fb07f4d --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,57 @@ +stages: + # 构建 + - build + - webhook + +build: + image: maven:3.6.3-openjdk-8 + stage: build + only: + - main + - develop + before_script: + - echo ' + '$PWD'.m2 + + + nexus + nexus_public + 9SZ4KXFvGt9N7kRU + + + ' > $HOME/.m2/settings.xml + + artifacts: + name: stock-market.war + expire_in: 1 day + paths: + - ./target/stock-market.war + script: + - echo ">>>>>>Start Building<<<<<<" + - pwd + - java -version + - mvn -v + - mvn clean install -Dmaven.test.skip=true + - ls + #- apt-get install -y curl + #- curl --max-time 20 http://43.128.20.12:11113/api/webhook/justpull?project=api\&setenv_file=alpha.sh\&publish_env=alpha + - echo ">>>>>>Finish Building<<<<<<" +webhook: + stage: webhook + #tags: + # - gz + only: + - main + - develop + script: + - echo ">>>>>>Start Deploy<<<<<<" + - ls + - apt-get update + - apt-get install -y curl + - curl --max-time 30 http://43.139.146.165:11113/api/webhook/justpull?project=market\&setenv_file=alpha.sh\&publish_env=alpha\&shell=deploy-alpha.sh + - echo ">>>>>>Start Deploy Finish<<<<<<" + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..24199f9 --- /dev/null +++ b/pom.xml @@ -0,0 +1,256 @@ + + 4.0.0 + war + + cn.qutaojing + qutaojing-micro-pom + 0.0.1-SNAPSHOT + + + + registry.cn-hangzhou.aliyuncs.com + 1.8 + 1.8 + MMdd-HHmm + + cn.stock + market + 股票行情 + 股票行情 + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + cn.qutaojing + qutaojing-common + 0.0.2-SNAPSHOT + + + com.squareup.okhttp3 + okhttp + + + + + + com.alibaba + druid-spring-boot-starter + 1.1.9 + + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + + mysql + mysql-connector-java + + + + com.google.zxing + core + 3.4.0 + + + + + io.netty + netty-all + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + com.github.pagehelper + pagehelper + 4.1.0 + + + + io.springfox + springfox-swagger2 + 2.7.0 + + + io.springfox + springfox-swagger-ui + 2.7.0 + + + + com.alibaba + easyexcel + 2.2.6 + + + com.github.xiaoymin + swagger-bootstrap-ui + 1.9.6 + + + + + com.xuxueli + xxl-job-core + 2.2.0 + + + + com.aliyun.oss + aliyun-sdk-oss + 2.5.0 + + + + com.aliyun + dysmsapi20170525 + 2.0.9 + + + com.squareup.okhttp3 + okhttp + + + + + + com.squareup.okhttp3 + okhttp + + + + + joda-time + joda-time + 2.3 + + + + com.belerweb + pinyin4j + 2.5.1 + + + + com.tencentcloudapi + tencentcloud-sdk-java + 3.1.322 + + + + com.aliyun + cloudauth20200618 + 1.0.5 + + + + com.aliyun + cloudauth20190307 + 1.0.7 + + + + + org.jsoup + jsoup + 1.15.2 + + + + + stock-market + + + org.apache.maven.plugins + maven-war-plugin + 3.3.1 + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + + + com.mysema.maven + apt-maven-plugin + 1.1.3 + + + + process + + + src/main/generated + com.querydsl.apt.jpa.JPAAnnotationProcessor + + + + + + + + + + nexus + https://nexus.duofu88.com/repository/maven-public/ + + true + + + true + + + + + \ No newline at end of file diff --git a/src/main/generated/cn/stock/market/infrastructure/db/po/QCityPO.java b/src/main/generated/cn/stock/market/infrastructure/db/po/QCityPO.java new file mode 100644 index 0000000..b3f51fc --- /dev/null +++ b/src/main/generated/cn/stock/market/infrastructure/db/po/QCityPO.java @@ -0,0 +1,57 @@ +package cn.stock.market.infrastructure.db.po; + +import static com.querydsl.core.types.PathMetadataFactory.*; + +import com.querydsl.core.types.dsl.*; + +import com.querydsl.core.types.PathMetadata; +import javax.annotation.Generated; +import com.querydsl.core.types.Path; + + +/** + * QCityPO is a Querydsl query type for CityPO + */ +@Generated("com.querydsl.codegen.EntitySerializer") +public class QCityPO extends EntityPathBase { + + private static final long serialVersionUID = -1922934307L; + + public static final QCityPO cityPO = new QCityPO("cityPO"); + + public final StringPath cityCode = createString("cityCode"); + + public final NumberPath id = createNumber("id", Integer.class); + + public final StringPath latitude = createString("latitude"); + + public final StringPath levelType = createString("levelType"); + + public final StringPath longitude = createString("longitude"); + + public final StringPath name = createString("name"); + + public final StringPath parentId = createString("parentId"); + + public final StringPath path = createString("path"); + + public final StringPath remark = createString("remark"); + + public final StringPath shortName = createString("shortName"); + + public final StringPath zipCode = createString("zipCode"); + + public QCityPO(String variable) { + super(CityPO.class, forVariable(variable)); + } + + public QCityPO(Path path) { + super(path.getType(), path.getMetadata()); + } + + public QCityPO(PathMetadata metadata) { + super(CityPO.class, metadata); + } + +} + diff --git a/src/main/generated/cn/stock/market/infrastructure/db/po/QCounter.java b/src/main/generated/cn/stock/market/infrastructure/db/po/QCounter.java new file mode 100644 index 0000000..b4e09d0 --- /dev/null +++ b/src/main/generated/cn/stock/market/infrastructure/db/po/QCounter.java @@ -0,0 +1,47 @@ +package cn.stock.market.infrastructure.db.po; + +import static com.querydsl.core.types.PathMetadataFactory.*; + +import com.querydsl.core.types.dsl.*; + +import com.querydsl.core.types.PathMetadata; +import javax.annotation.Generated; +import com.querydsl.core.types.Path; + + +/** + * QCounter is a Querydsl query type for Counter + */ +@Generated("com.querydsl.codegen.EntitySerializer") +public class QCounter extends EntityPathBase { + + private static final long serialVersionUID = 690984745L; + + public static final QCounter counter = new QCounter("counter"); + + public final NumberPath count = createNumber("count", Long.class); + + public final DateTimePath createTime = createDateTime("createTime", java.util.Date.class); + + public final StringPath fkId = createString("fkId"); + + public final StringPath k = createString("k"); + + public final StringPath type = createString("type"); + + public final DateTimePath updateTime = createDateTime("updateTime", java.util.Date.class); + + public QCounter(String variable) { + super(Counter.class, forVariable(variable)); + } + + public QCounter(Path path) { + super(path.getType(), path.getMetadata()); + } + + public QCounter(PathMetadata metadata) { + super(Counter.class, metadata); + } + +} + diff --git a/src/main/generated/cn/stock/market/infrastructure/db/po/QDic.java b/src/main/generated/cn/stock/market/infrastructure/db/po/QDic.java new file mode 100644 index 0000000..1657c83 --- /dev/null +++ b/src/main/generated/cn/stock/market/infrastructure/db/po/QDic.java @@ -0,0 +1,41 @@ +package cn.stock.market.infrastructure.db.po; + +import static com.querydsl.core.types.PathMetadataFactory.*; + +import com.querydsl.core.types.dsl.*; + +import com.querydsl.core.types.PathMetadata; +import javax.annotation.Generated; +import com.querydsl.core.types.Path; + + +/** + * QDic is a Querydsl query type for Dic + */ +@Generated("com.querydsl.codegen.EntitySerializer") +public class QDic extends EntityPathBase { + + private static final long serialVersionUID = -1801755605L; + + public static final QDic dic = new QDic("dic"); + + public final DateTimePath createTime = createDateTime("createTime", java.util.Date.class); + + public final StringPath k = createString("k"); + + public final StringPath val = createString("val"); + + public QDic(String variable) { + super(Dic.class, forVariable(variable)); + } + + public QDic(Path path) { + super(path.getType(), path.getMetadata()); + } + + public QDic(PathMetadata metadata) { + super(Dic.class, metadata); + } + +} + diff --git a/src/main/generated/cn/stock/market/infrastructure/db/po/QJsonInfoPO.java b/src/main/generated/cn/stock/market/infrastructure/db/po/QJsonInfoPO.java new file mode 100644 index 0000000..266e8cd --- /dev/null +++ b/src/main/generated/cn/stock/market/infrastructure/db/po/QJsonInfoPO.java @@ -0,0 +1,45 @@ +package cn.stock.market.infrastructure.db.po; + +import static com.querydsl.core.types.PathMetadataFactory.*; + +import com.querydsl.core.types.dsl.*; + +import com.querydsl.core.types.PathMetadata; +import javax.annotation.Generated; +import com.querydsl.core.types.Path; + + +/** + * QJsonInfoPO is a Querydsl query type for JsonInfoPO + */ +@Generated("com.querydsl.codegen.EntitySerializer") +public class QJsonInfoPO extends EntityPathBase { + + private static final long serialVersionUID = 537860584L; + + public static final QJsonInfoPO jsonInfoPO = new QJsonInfoPO("jsonInfoPO"); + + public final DateTimePath createAt = createDateTime("createAt", java.util.Date.class); + + public final StringPath ext = createString("ext"); + + public final NumberPath id = createNumber("id", Integer.class); + + public final StringPath type = createString("type"); + + public final DateTimePath updateAt = createDateTime("updateAt", java.util.Date.class); + + public QJsonInfoPO(String variable) { + super(JsonInfoPO.class, forVariable(variable)); + } + + public QJsonInfoPO(Path path) { + super(path.getType(), path.getMetadata()); + } + + public QJsonInfoPO(PathMetadata metadata) { + super(JsonInfoPO.class, metadata); + } + +} + diff --git a/src/main/generated/cn/stock/market/infrastructure/db/po/QRealtimePO.java b/src/main/generated/cn/stock/market/infrastructure/db/po/QRealtimePO.java new file mode 100644 index 0000000..fa06b13 --- /dev/null +++ b/src/main/generated/cn/stock/market/infrastructure/db/po/QRealtimePO.java @@ -0,0 +1,51 @@ +package cn.stock.market.infrastructure.db.po; + +import static com.querydsl.core.types.PathMetadataFactory.*; + +import com.querydsl.core.types.dsl.*; + +import com.querydsl.core.types.PathMetadata; +import javax.annotation.Generated; +import com.querydsl.core.types.Path; + + +/** + * QRealtimePO is a Querydsl query type for RealtimePO + */ +@Generated("com.querydsl.codegen.EntitySerializer") +public class QRealtimePO extends EntityPathBase { + + private static final long serialVersionUID = -677602211L; + + public static final QRealtimePO realtimePO = new QRealtimePO("realtimePO"); + + public final NumberPath amounts = createNumber("amounts", Integer.class); + + public final NumberPath averagePrice = createNumber("averagePrice", Double.class); + + public final NumberPath id = createNumber("id", Integer.class); + + public final NumberPath price = createNumber("price", Double.class); + + public final NumberPath rates = createNumber("rates", Double.class); + + public final StringPath stockCode = createString("stockCode"); + + public final StringPath time = createString("time"); + + public final NumberPath volumes = createNumber("volumes", Integer.class); + + public QRealtimePO(String variable) { + super(RealtimePO.class, forVariable(variable)); + } + + public QRealtimePO(Path path) { + super(path.getType(), path.getMetadata()); + } + + public QRealtimePO(PathMetadata metadata) { + super(RealtimePO.class, metadata); + } + +} + diff --git a/src/main/generated/cn/stock/market/infrastructure/db/po/QSiteArticlePO.java b/src/main/generated/cn/stock/market/infrastructure/db/po/QSiteArticlePO.java new file mode 100644 index 0000000..323dc56 --- /dev/null +++ b/src/main/generated/cn/stock/market/infrastructure/db/po/QSiteArticlePO.java @@ -0,0 +1,61 @@ +package cn.stock.market.infrastructure.db.po; + +import static com.querydsl.core.types.PathMetadataFactory.*; + +import com.querydsl.core.types.dsl.*; + +import com.querydsl.core.types.PathMetadata; +import javax.annotation.Generated; +import com.querydsl.core.types.Path; + + +/** + * QSiteArticlePO is a Querydsl query type for SiteArticlePO + */ +@Generated("com.querydsl.codegen.EntitySerializer") +public class QSiteArticlePO extends EntityPathBase { + + private static final long serialVersionUID = -38085285L; + + public static final QSiteArticlePO siteArticlePO = new QSiteArticlePO("siteArticlePO"); + + public final DateTimePath addTime = createDateTime("addTime", java.util.Date.class); + + public final StringPath artCnt = createString("artCnt"); + + public final StringPath artImg = createString("artImg"); + + public final StringPath artSummary = createString("artSummary"); + + public final StringPath artTitle = createString("artTitle"); + + public final StringPath artType = createString("artType"); + + public final StringPath author = createString("author"); + + public final NumberPath hitTimes = createNumber("hitTimes", Integer.class); + + public final NumberPath id = createNumber("id", Integer.class); + + public final NumberPath isShow = createNumber("isShow", Integer.class); + + public final StringPath sourceId = createString("sourceId"); + + public final StringPath spiderUrl = createString("spiderUrl"); + + public final NumberPath views = createNumber("views", Integer.class); + + public QSiteArticlePO(String variable) { + super(SiteArticlePO.class, forVariable(variable)); + } + + public QSiteArticlePO(Path path) { + super(path.getType(), path.getMetadata()); + } + + public QSiteArticlePO(PathMetadata metadata) { + super(SiteArticlePO.class, metadata); + } + +} + diff --git a/src/main/generated/cn/stock/market/infrastructure/db/po/QSiteNewsPO.java b/src/main/generated/cn/stock/market/infrastructure/db/po/QSiteNewsPO.java new file mode 100644 index 0000000..9d6eb24 --- /dev/null +++ b/src/main/generated/cn/stock/market/infrastructure/db/po/QSiteNewsPO.java @@ -0,0 +1,61 @@ +package cn.stock.market.infrastructure.db.po; + +import static com.querydsl.core.types.PathMetadataFactory.*; + +import com.querydsl.core.types.dsl.*; + +import com.querydsl.core.types.PathMetadata; +import javax.annotation.Generated; +import com.querydsl.core.types.Path; + + +/** + * QSiteNewsPO is a Querydsl query type for SiteNewsPO + */ +@Generated("com.querydsl.codegen.EntitySerializer") +public class QSiteNewsPO extends EntityPathBase { + + private static final long serialVersionUID = 525777388L; + + public static final QSiteNewsPO siteNewsPO = new QSiteNewsPO("siteNewsPO"); + + public final DateTimePath addTime = createDateTime("addTime", java.util.Date.class); + + public final StringPath content = createString("content"); + + public final StringPath description = createString("description"); + + public final NumberPath id = createNumber("id", Integer.class); + + public final StringPath imgurl = createString("imgurl"); + + public final DateTimePath showTime = createDateTime("showTime", java.util.Date.class); + + public final StringPath sourceId = createString("sourceId"); + + public final StringPath sourceName = createString("sourceName"); + + public final NumberPath status = createNumber("status", Integer.class); + + public final StringPath title = createString("title"); + + public final NumberPath type = createNumber("type", Integer.class); + + public final DateTimePath updateTime = createDateTime("updateTime", java.util.Date.class); + + public final NumberPath views = createNumber("views", Integer.class); + + public QSiteNewsPO(String variable) { + super(SiteNewsPO.class, forVariable(variable)); + } + + public QSiteNewsPO(Path path) { + super(path.getType(), path.getMetadata()); + } + + public QSiteNewsPO(PathMetadata metadata) { + super(SiteNewsPO.class, metadata); + } + +} + diff --git a/src/main/generated/cn/stock/market/infrastructure/db/po/QSysLogPO.java b/src/main/generated/cn/stock/market/infrastructure/db/po/QSysLogPO.java new file mode 100644 index 0000000..742df59 --- /dev/null +++ b/src/main/generated/cn/stock/market/infrastructure/db/po/QSysLogPO.java @@ -0,0 +1,63 @@ +package cn.stock.market.infrastructure.db.po; + +import static com.querydsl.core.types.PathMetadataFactory.*; + +import com.querydsl.core.types.dsl.*; + +import com.querydsl.core.types.PathMetadata; +import javax.annotation.Generated; +import com.querydsl.core.types.Path; + + +/** + * QSysLogPO is a Querydsl query type for SysLogPO + */ +@Generated("com.querydsl.codegen.EntitySerializer") +public class QSysLogPO extends EntityPathBase { + + private static final long serialVersionUID = -2037818903L; + + public static final QSysLogPO sysLogPO = new QSysLogPO("sysLogPO"); + + public final StringPath actionType = createString("actionType"); + + public final StringPath content = createString("content"); + + public final DateTimePath createAt = createDateTime("createAt", java.util.Date.class); + + public final StringPath ext = createString("ext"); + + public final NumberPath id = createNumber("id", Integer.class); + + public final StringPath module = createString("module"); + + public final StringPath operatorId = createString("operatorId"); + + public final StringPath operatorName = createString("operatorName"); + + public final StringPath operatorPhone = createString("operatorPhone"); + + public final StringPath roleType = createString("roleType"); + + public final NumberPath storeId = createNumber("storeId", Integer.class); + + public final StringPath title = createString("title"); + + public final StringPath uniqueId = createString("uniqueId"); + + public final DateTimePath updateAt = createDateTime("updateAt", java.util.Date.class); + + public QSysLogPO(String variable) { + super(SysLogPO.class, forVariable(variable)); + } + + public QSysLogPO(Path path) { + super(path.getType(), path.getMetadata()); + } + + public QSysLogPO(PathMetadata metadata) { + super(SysLogPO.class, metadata); + } + +} + diff --git a/src/main/generated/cn/stock/market/infrastructure/stockdb/po/QSiteSettingPO.java b/src/main/generated/cn/stock/market/infrastructure/stockdb/po/QSiteSettingPO.java new file mode 100644 index 0000000..c9e4d71 --- /dev/null +++ b/src/main/generated/cn/stock/market/infrastructure/stockdb/po/QSiteSettingPO.java @@ -0,0 +1,39 @@ +package cn.stock.market.infrastructure.stockdb.po; + +import static com.querydsl.core.types.PathMetadataFactory.*; + +import com.querydsl.core.types.dsl.*; + +import com.querydsl.core.types.PathMetadata; +import javax.annotation.Generated; +import com.querydsl.core.types.Path; + + +/** + * QSiteSettingPO is a Querydsl query type for SiteSettingPO + */ +@Generated("com.querydsl.codegen.EntitySerializer") +public class QSiteSettingPO extends EntityPathBase { + + private static final long serialVersionUID = -51441337L; + + public static final QSiteSettingPO siteSettingPO = new QSiteSettingPO("siteSettingPO"); + + public final NumberPath id = createNumber("id", Integer.class); + + public final StringPath marketServerList = createString("marketServerList"); + + public QSiteSettingPO(String variable) { + super(SiteSettingPO.class, forVariable(variable)); + } + + public QSiteSettingPO(Path path) { + super(path.getType(), path.getMetadata()); + } + + public QSiteSettingPO(PathMetadata metadata) { + super(SiteSettingPO.class, metadata); + } + +} + diff --git a/src/main/generated/cn/stock/market/infrastructure/stockdb/po/QStockPO.java b/src/main/generated/cn/stock/market/infrastructure/stockdb/po/QStockPO.java new file mode 100644 index 0000000..5dd97b5 --- /dev/null +++ b/src/main/generated/cn/stock/market/infrastructure/stockdb/po/QStockPO.java @@ -0,0 +1,61 @@ +package cn.stock.market.infrastructure.stockdb.po; + +import static com.querydsl.core.types.PathMetadataFactory.*; + +import com.querydsl.core.types.dsl.*; + +import com.querydsl.core.types.PathMetadata; +import javax.annotation.Generated; +import com.querydsl.core.types.Path; + + +/** + * QStockPO is a Querydsl query type for StockPO + */ +@Generated("com.querydsl.codegen.EntitySerializer") +public class QStockPO extends EntityPathBase { + + private static final long serialVersionUID = -1246401708L; + + public static final QStockPO stockPO = new QStockPO("stockPO"); + + public final DateTimePath addTime = createDateTime("addTime", java.util.Date.class); + + public final NumberPath id = createNumber("id", Integer.class); + + public final NumberPath increaseRatio = createNumber("increaseRatio", java.math.BigDecimal.class); + + public final NumberPath isLock = createNumber("isLock", Integer.class); + + public final NumberPath isShow = createNumber("isShow", Integer.class); + + public final NumberPath spreadRate = createNumber("spreadRate", java.math.BigDecimal.class); + + public final StringPath stockCode = createString("stockCode"); + + public final StringPath stockGid = createString("stockGid"); + + public final StringPath stockName = createString("stockName"); + + public final StringPath stockPlate = createString("stockPlate"); + + public final StringPath stockSpell = createString("stockSpell"); + + public final NumberPath stockState = createNumber("stockState", Integer.class); + + public final StringPath stockType = createString("stockType"); + + public QStockPO(String variable) { + super(StockPO.class, forVariable(variable)); + } + + public QStockPO(Path path) { + super(path.getType(), path.getMetadata()); + } + + public QStockPO(PathMetadata metadata) { + super(StockPO.class, metadata); + } + +} + diff --git a/src/main/java/cn/stock/market/StockMarketLaunch.java b/src/main/java/cn/stock/market/StockMarketLaunch.java new file mode 100644 index 0000000..446cab2 --- /dev/null +++ b/src/main/java/cn/stock/market/StockMarketLaunch.java @@ -0,0 +1,72 @@ +package cn.stock.market; + +import org.apache.commons.lang.StringUtils; +import org.slf4j.MDC; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration; +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; +import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.core.env.Environment; + +import com.alibaba.fastjson.JSON; + +import cn.hutool.http.HttpGlobalConfig; +import cn.qutaojing.common.utils.MdcUtil; +import cn.stock.market.domain.basic.entity.SiteSetting; +import cn.stock.market.domain.basic.repository.SiteSettingRepository; +import lombok.extern.slf4j.Slf4j; + +@SpringBootApplication(exclude = { + MongoAutoConfiguration.class, MongoDataAutoConfiguration.class, + RedisAutoConfiguration.class, +// RedissonAutoConfiguration.class, RedisAutoConfiguration.class +}) +@Slf4j +@ComponentScan(basePackages = { "cn.stock" }) +public class StockMarketLaunch implements CommandLineRunner { + + public static void main(String[] args) { + HttpGlobalConfig.setTimeout(45000); + SpringApplication.run(StockMarketLaunch.class, args); + } + + @Autowired + private Environment env; + @Override + public void run(String... args) throws Exception { + MDC.put(MdcUtil.TRACE_ID, MdcUtil.getTraceId()); + log.info("StockMarketLaunch RUNNING...."); + + String marketDomain = env.getProperty("market.domain"); + if(StringUtils.isNotBlank(marketDomain)) { + log.info("发现marketDomain: {}", marketDomain); + SiteSetting siteSetting = SiteSettingRepository.of().get(); + if(siteSetting == null) { + log.info("找不到siteSetting信息, 无法设置"); + } else { + log.info("设置前: {}", JSON.toJSONString(siteSetting)); + boolean flag = siteSetting.checkAndAddIfNoExists(marketDomain); + if(! flag) { + SiteSettingRepository.of().saveAndFlush(siteSetting); + log.info("已经设置: {}....", JSON.toJSONString(siteSetting)); + } else { + log.info("包含, 跳过...."); + } + } + } + } + +// @Bean +// public TomcatServletWebServerFactory tomcatServletWebServerFactory() { +// TomcatServletWebServerFactory tomcatServletWebServerFactory = new TomcatServletWebServerFactory(); +// tomcatServletWebServerFactory.addConnectorCustomizers((Connector connector) -> { +// connector.setProperty("relaxedPathChars", "\"{\\}^`{|}[|]"); +// connector.setProperty("relaxedQueryChars", "\"{\\}^`{|}[|]"); +// }); +// return tomcatServletWebServerFactory; +// } +} \ No newline at end of file diff --git a/src/main/java/cn/stock/market/StockMarketServletInitializer.java b/src/main/java/cn/stock/market/StockMarketServletInitializer.java new file mode 100644 index 0000000..ff94185 --- /dev/null +++ b/src/main/java/cn/stock/market/StockMarketServletInitializer.java @@ -0,0 +1,11 @@ +package cn.stock.market; + +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +public class StockMarketServletInitializer extends SpringBootServletInitializer { + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { + return builder.sources(StockMarketLaunch.class); + } +} diff --git a/src/main/java/cn/stock/market/application/CommonApis.java b/src/main/java/cn/stock/market/application/CommonApis.java new file mode 100644 index 0000000..b20ffee --- /dev/null +++ b/src/main/java/cn/stock/market/application/CommonApis.java @@ -0,0 +1,78 @@ +package cn.stock.market.application; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeSet; +import java.util.function.Function; +import java.util.stream.Collector; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.ag.utils.CollectionUtils; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.constant.StockSource; +import cn.stock.market.domain.basic.entity.Stock; +import cn.stock.market.domain.basic.repository.StockRepository; +import cn.stock.market.dto.model.StockCode; +import cn.stock.market.dto.model.StockDetail; +import cn.stock.market.dto.model.StockVO; +import cn.stock.market.infrastructure.api.AStockApis; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class CommonApis { + + public StockDetail aStockDetail(String code) { + return AStockApis.qq(code); + } + + public StockVO stockDetail(StockCode code) { + Map map = stockDetailMap(Lists.newArrayList(code)); + return map.get(code.getCode()); + } + + public List aStockDetail(List code) { + return AStockApis.qq(code); + } + + public Map stockDetailMap(List code) { + Function> func = (source) -> { + return code.stream() + .filter(val -> val != null && source == val.getSource()) + .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(StockCode::getCode))), ArrayList::new)); + }; + + List aList = func.apply(StockSource.A); +// List hkList = func.apply(StockSource.HK); +// List usList = func.apply(StockSource.US); + + Map map = Maps.newHashMap(); + Collector> collectorMap = Collectors.toMap(StockVO::getCode, Function.identity(), (u,v) -> { return v;}, HashMap::new); + + Map stockMap = StockRepository.of().cacheCodeMap(); + + if(CollectionUtils.isNotEmpty(aList)) { + Map m = aStockDetail(Lists.transform(aList, val -> val.getCode())) + .stream() + .map(val -> StockVO.from(val, stockMap.get(val.getCode()))) + .collect(collectorMap); + + map.putAll(m); + } + + return map; + } + + public static CommonApis of() { + return SpringUtils.getBean(CommonApis.class); + } +} diff --git a/src/main/java/cn/stock/market/application/Counters.java b/src/main/java/cn/stock/market/application/Counters.java new file mode 100644 index 0000000..d4fb86e --- /dev/null +++ b/src/main/java/cn/stock/market/application/Counters.java @@ -0,0 +1,198 @@ +//package cn.stock.market.application; +// +//import java.util.Date; +//import java.util.List; +//import java.util.Map; +//import java.util.concurrent.TimeUnit; +//import java.util.stream.Collectors; +// +//import org.apache.commons.lang.StringUtils; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.data.redis.core.RedisTemplate; +//import org.springframework.stereotype.Service; +//import org.springframework.transaction.annotation.Transactional; +// +//import com.ag.utils.CollectionUtils; +//import com.ag.utils.NumberUtils; +//import com.google.common.base.Joiner; +//import com.google.common.collect.Maps; +//import com.querydsl.core.types.dsl.CaseBuilder; +//import com.querydsl.core.types.dsl.CaseBuilder.Cases; +//import com.querydsl.core.types.dsl.NumberExpression; +//import com.querydsl.jpa.impl.JPAUpdateClause; +// +//import cn.qutaojing.common.utils.DslUtils; +//import cn.qutaojing.common.utils.SpringUtils; +//import cn.stock.market.infrastructure.db.po.Counter; +//import cn.stock.market.infrastructure.db.repo.CounterRepo; +//import cn.stock.market.infrastructure.db.po.QCounter; +//import lombok.extern.slf4j.Slf4j; +// +///** +// * 计数器 +// * +// * @author xlfd +// * @email xlfd@gmail.com +// * @version 1.0 +// * @created Apr 22, 2021 4:21:07 PM +// */ +//@Service +//@SuppressWarnings("rawtypes") +//@Slf4j +//public class Counters { +// public static final String TYPE_USER = "USER"; +// public static final String TYPE_SYS = "SYS"; +// +// /** +// * 用户购买商品 +// */ +// public static final String USER_BUY_GOODS_COUNT_TMP = "USER_BUY_GOODS_COUNT_%s_%s"; +// public static final String USER_EVERYDAY_BUY_GOODS_COUNT_TMP = "USER_EVERYDAY_BUY_GOODS_COUNT_%s_%s_%s"; +// public static final String USER_STORE_BUY_COUNT_TMP = "USER_STORE_BUY_COUNT_%s_%s_%s"; +// +// static final long EXPIRE_SEC = 60 * 60 * 24; // 默认一天 +// @Autowired RedisTemplate redisTemplate; +// @Autowired CounterRepo repo; +// +// String COUNTER_OPERCOUNT_MAP = "counter::opercount::map"; +// String COUNTER_MAP_PRE = "counter::count::"; +// +// @SuppressWarnings("unchecked") +// public long getCount(String k) { +// Object obj = redisTemplate.opsForValue().get(key(k)); +// if(obj != null) { +// if(obj instanceof Number) { +// return ((Number) obj).longValue(); +// } else { +// log.error("获取的到值{}非数字类型, 删除", obj); +// redisTemplate.delete(key(k)); +// } +// } +// +// Counter counter = repo.findById(k).orElse(null); +// if(counter != null) { +// redisTemplate.opsForValue().set(key(k), counter.getCount(), EXPIRE_SEC, TimeUnit.SECONDS); +// return counter.getCount(); +// } +// +// return 0; +// } +// +// String key(String k) { +// return COUNTER_MAP_PRE + k; +// } +// +// /** +// * 返回add后的值 +// * @return +// */ +// @SuppressWarnings("unchecked") +// public long add(String k, long delta, String type, String fkId) { +// String key = key(k); +// if (redisTemplate.hasKey(key)) { +// Long increment = redisTemplate.opsForValue().increment(key, delta); +// +// if(redisTemplate.opsForHash().hasKey(COUNTER_OPERCOUNT_MAP, key)) { +// redisTemplate.opsForHash().increment(COUNTER_OPERCOUNT_MAP, key, 1); +// } else { +// redisTemplate.opsForHash().putIfAbsent(COUNTER_OPERCOUNT_MAP, key, 1); +// } +// return increment == null ? 0 : increment.longValue(); +// } +// +// Counter counter = repo.findById(k).orElse(null); +// if(counter != null) { +// counter.setCount(counter.getCount() + delta); +// } else { +// counter = Counter.builder() +// .k(k) +// .count(delta) +// .type(type) +// .fkId(fkId) +// .build(); +// } +// repo.save(counter); +// redisTemplate.opsForValue().set(key, counter.getCount(), EXPIRE_SEC, TimeUnit.SECONDS); +// return counter.getCount(); +// } +// +// @SuppressWarnings("unchecked") +// public List getStockOperList() { +// Map map = redisTemplate.opsForHash().entries(COUNTER_OPERCOUNT_MAP); +// return +// map.entrySet() +// .stream() +// .filter(entry -> { +// return ((int) entry.getValue()) > 0; +// }).map(entry -> entry.getKey()) +// .map(String::valueOf) +// .collect(Collectors.toList()); +// } +// +// /** +// * 库存从redis回写到DB +// */ +// @SuppressWarnings({ "unchecked"}) +// @Transactional +// public long writebackToDB() { +// List list = getStockOperList(); +// if(CollectionUtils.isEmpty(list)) { +// return 0; +// } +// +// log.info("准备回写库存到DB, size:{}, {}", list.size(), Joiner.on(",").join(list)); +// Map map = Maps.newConcurrentMap(); +// +// List valueList = redisTemplate.opsForValue().multiGet(list); +// for (int i = 0; i < list.size(); i++) { +// String keyWithPre = list.get(i); +// Object value = valueList.get(i); +// if(value == null || ! (value instanceof Number)) { +// log.warn("{}-无效", keyWithPre, value); +// continue; +// } +// +// Long count = ((Number) valueList.get(i)).longValue(); +// if(NumberUtils.isNotValidWithoutZero(count)) { +// log.warn("{}-无效值", keyWithPre, count); +// continue; +// } +// +// String k = StringUtils.replace(keyWithPre, COUNTER_MAP_PRE, ""); +// if(StringUtils.isBlank(k)) { +// log.warn("{}-key-{}无效值", keyWithPre, k); +// continue; +// } +// +// map.put(k, count); +// } +// +// if(CollectionUtils.isNotEmpty(map)) { +// QCounter q = QCounter.counter; +// +// Cases> cases = null; +// for (Map.Entry entry : map.entrySet()) { +// if(cases == null) { +// cases = new CaseBuilder().when(q.k.eq(entry.getKey())).then(entry.getValue()); +// } else { +// cases = cases.when(q.k.eq(entry.getKey())).then(entry.getValue()); +// } +// } +// +// JPAUpdateClause updateClause = DslUtils.update(q) +// .set(q.count, cases.otherwise(-1L)) +// .set(q.updateTime, new Date()) +// .where(q.k.in(map.keySet())); +// +// long row = updateClause.execute(); +// log.info("返回行数:{}, 执行SQL: {}", row, updateClause); +// } +// +// redisTemplate.delete(COUNTER_OPERCOUNT_MAP); +// return list.size(); +// } +// +// public static Counters of() { +// return SpringUtils.getBean(Counters.class); +// } +//} diff --git a/src/main/java/cn/stock/market/application/Dics.java b/src/main/java/cn/stock/market/application/Dics.java new file mode 100644 index 0000000..6af5d0a --- /dev/null +++ b/src/main/java/cn/stock/market/application/Dics.java @@ -0,0 +1,264 @@ +package cn.stock.market.application; + +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.lang.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.ag.utils.CollectionUtils; +import com.ag.utils.JsonUtils; +import com.ag.utils.Jsons; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.util.TypeUtils; +import com.google.common.base.Joiner; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.infrastructure.db.po.Dic; +import cn.stock.market.infrastructure.db.po.QDic; +import cn.stock.market.infrastructure.db.repo.DicRepo; +import lombok.extern.slf4j.Slf4j; + +/** + * title: Dics.java + * + * @author xlfd + * @version 1.0 + * @email xlfd@gmail.com + * @created Oct 15, 2020 11:00:46 AM + */ +@Slf4j +@Service +public class Dics { + @Autowired + DicRepo repository; + final static String SPLIT = "."; //分隔符 + + LoadingCache> keyCahce = CacheBuilder.newBuilder() + .maximumSize(20000) + .expireAfterWrite(60, TimeUnit.SECONDS) + .build(CacheLoader.from((prefix) -> { + return Optional.ofNullable(findByPrefix(prefix)); + })); + + public void refreshCache(String key) { + try { + keyCahce.refresh(key); + } catch(Exception e) { + log.warn("refreshCache error: {}", e.getLocalizedMessage()); + } + } + + @SuppressWarnings("unchecked") + public T getFromCache(String prefix) { + try { + return (T) keyCahce.get(prefix).orElse(null); + } catch (ExecutionException e) { + e.printStackTrace(); + } + return null; + } + + @SuppressWarnings("unchecked") + public T getFromCache(String prefix, Class clazz) { + Object o = getFromCache(prefix); + if(o != null && clazz == null) { + return (T) o; + } + return Jsons.typeCast(o, clazz); + } + + @SuppressWarnings("unchecked") + public T getFromCache(String prefix, T defalutValue) { + Object o = getFromCache(prefix); + if (o == null) { + return defalutValue; + } + + return (T) Jsons.typeCast(o, defalutValue.getClass()); +// return (T) TypeUtils.cast(o, defalutValue.getClass(), ParserConfig.getGlobalInstance()); + } + + public static String pack(Object... strings) { + return Joiner.on(SPLIT).skipNulls().join(strings); + } + + public static Dics of() { + return SpringUtils.getBean(Dics.class); + } + + /** + * 降map的每键值对记录刷到DB中, 每组记录为一列 + * + * @param prefix 键的前缀 + * @param map + * @return + */ + public List save(final String prefix, Object obj) { + JSONObject map = JsonUtils.formObject(obj); + return save(prefix, map); + } + + /** + * 降map的每组记录刷到DB中, 每组记录为一列 + * + * @param prefix 键的前缀 + * @param map + * @return + */ + public List save(final String prefix, Map map) { + Map m = Maps.newHashMap(); + map.keySet().stream().forEach(k -> { + m.put(prefix + SPLIT + k, map.get(k)); + }); + return save(m); + } + + public Dic saveOne(final String key, Object value) { + Map m = Maps.newHashMap(); + m.put(key, value); + return save(m).get(0); + } + + public List save(Map map) { + List list = Lists.newArrayList(); + map.forEach((k, v) -> { + Dic dic = Dic.builder() + .k(k) + .val(String.valueOf(v)) + .build(); + list.add(dic); + }); + + repository.saveAll(list); + return list; + } + + static String[] split(String str) { + return StringUtils.split(str, SPLIT); + } + + /** + * 根据前缀查询到列表, 然后每列的k-val对应的 class.v=val封装成对象返回 + * 适用于 key -> Object + * + * @param prefix 前缀 + * @param clazz + * @return + */ + public T findByPrefix(String prefix, Class clazz) { + Object o = findByPrefix(prefix); + return TypeUtils.cast(o, clazz, ParserConfig.getGlobalInstance()); +// return JsonUtils.convert(JsonUtils.formObject(o), clazz); + } + + /** + * 根据前缀查询到列表 + * 根据传入的prefix返回对应的保存数据库的结构 + * 1, prefix -> Object + * 2, prefix -> Map K可以是String也可以是Map + * + * @param prefix 前缀 + * @return + */ + public T findByPrefix(String prefix) { + return findByPrefix(prefix, Comparator.comparing(Dic::getCreateTime)); + } + + @SuppressWarnings("unchecked") + public T findByPrefix(String prefix, Comparator comparator) { + List list = repository.findAll(QDic.dic.k.like(prefix + "%")); + list.sort(comparator); + Map map = list.stream().collect(HashMap::new, (m, v) -> m.put(v.getK(), v.getVal()), HashMap::putAll); + Map structureMap = buildStructureMap(map); + return (T) getParameter(structureMap, split(prefix)); + } + + @SuppressWarnings("rawtypes") + static Object getParameter(Map map, String... settings) { + if (settings == null || settings.length < 1) + return null; + if (settings.length == 1) { + settings = StringUtils.split(settings[0], "."); + } + + if (settings.length == 1) + return map.get(settings[0]); + Map tempMap = (Map) map.get(settings[0]); + for (int i = 1; i < settings.length - 1; i++) { + + if (tempMap == null) { + return null; + } + tempMap = (Map) tempMap.get(settings[i]); + if (tempMap == null) { + return null; + } + } + + if (tempMap == null) { + return null; + } + return tempMap.get(settings[settings.length - 1]); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + static Map buildStructureMap(Map assembleMap) { + Map map = Maps.newLinkedHashMap(); + if (CollectionUtils.isEmpty(assembleMap)) { + return map; + } + for (Map.Entry set : assembleMap.entrySet()) { + String variable = set.getKey(); + String value = set.getValue(); + if (StringUtils.isBlank(variable)) { + continue; + } + + String[] keys = StringUtils.split(variable, '.'); + Map supMap = null; + Map subMap = null; + Object obj = null; + int len = keys.length - 1; + if (len < 1) { // only root node + map.put(variable, value); + continue; + } + + supMap = (Map) map.get(keys[0]); + if (supMap == null) { // new root node + supMap = new LinkedHashMap(); + map.put(keys[0], supMap); + } + + for (int i = 1; i < len; i++) { + String key = keys[i]; + obj = supMap.get(key); + + if (obj != null && obj instanceof Map) { + supMap = (Map) obj; + } else { + subMap = Maps.newLinkedHashMap(); + supMap.put(key, subMap); + supMap = subMap; + } + } + supMap.put(keys[len], value); + } + + return map; + } +} diff --git a/src/main/java/cn/stock/market/application/assembler/CityAssembler.java b/src/main/java/cn/stock/market/application/assembler/CityAssembler.java new file mode 100644 index 0000000..4902981 --- /dev/null +++ b/src/main/java/cn/stock/market/application/assembler/CityAssembler.java @@ -0,0 +1,28 @@ +package cn.stock.market.application.assembler; + +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +import cn.qutaojing.common.utils.Beans; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.City; +import cn.stock.market.dto.CityDTO; + +/** + * CityAssembler + * + * @author xlfd + * @email xlfd@gmail.com + * @created 2021/06/16 + */ +@Component +@Lazy +public class CityAssembler { + public CityDTO toDTO(City entity) { + return Beans.mapper(entity, CityDTO.class); + } + + public static CityAssembler of() { + return SpringUtils.getBean(CityAssembler.class); + } +} diff --git a/src/main/java/cn/stock/market/application/assembler/JsonInfoAssembler.java b/src/main/java/cn/stock/market/application/assembler/JsonInfoAssembler.java new file mode 100644 index 0000000..e832d00 --- /dev/null +++ b/src/main/java/cn/stock/market/application/assembler/JsonInfoAssembler.java @@ -0,0 +1,36 @@ +package cn.stock.market.application.assembler; + +import cn.qutaojing.common.utils.Beans; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.JsonInfo; +import cn.stock.market.dto.JsonInfoDTO; + +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +/** + * JsonInfoAssembler + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2022/08/16 + */ +@Component +@Lazy +public class JsonInfoAssembler { + public JsonInfoDTO toDTO(JsonInfo e) { + JsonInfoDTO dto = Beans.mapper(e, JsonInfoDTO.class); + if(dto == null) return dto; + fill(e, dto); + return dto; + } + + protected void fill(JsonInfo e, JsonInfoDTO dto) { + if(dto == null) return; + return; + } + + public static JsonInfoAssembler of() { + return SpringUtils.getBean(JsonInfoAssembler.class); + } +} diff --git a/src/main/java/cn/stock/market/application/assembler/RealtimeAssembler.java b/src/main/java/cn/stock/market/application/assembler/RealtimeAssembler.java new file mode 100644 index 0000000..26d2890 --- /dev/null +++ b/src/main/java/cn/stock/market/application/assembler/RealtimeAssembler.java @@ -0,0 +1,35 @@ +package cn.stock.market.application.assembler; + +import cn.qutaojing.common.utils.Beans; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.Realtime; +import cn.stock.market.dto.RealtimeDTO; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +/** + * RealtimeAssembler + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Component +@Lazy +public class RealtimeAssembler { + public RealtimeDTO toDTO(Realtime e) { + RealtimeDTO dto = Beans.mapper(e, RealtimeDTO.class); + if(dto == null) return dto; + fill(e, dto); + return dto; + } + + protected void fill(Realtime e, RealtimeDTO dto) { + if(dto == null) return; + return; + } + + public static RealtimeAssembler of() { + return SpringUtils.getBean(RealtimeAssembler.class); + } +} diff --git a/src/main/java/cn/stock/market/application/assembler/SiteArticleAssembler.java b/src/main/java/cn/stock/market/application/assembler/SiteArticleAssembler.java new file mode 100644 index 0000000..44aa5ca --- /dev/null +++ b/src/main/java/cn/stock/market/application/assembler/SiteArticleAssembler.java @@ -0,0 +1,35 @@ +package cn.stock.market.application.assembler; + +import cn.qutaojing.common.utils.Beans; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.SiteArticle; +import cn.stock.market.dto.SiteArticleDTO; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +/** + * SiteArticleAssembler + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Component +@Lazy +public class SiteArticleAssembler { + public SiteArticleDTO toDTO(SiteArticle e) { + SiteArticleDTO dto = Beans.mapper(e, SiteArticleDTO.class); + if(dto == null) return dto; + fill(e, dto); + return dto; + } + + protected void fill(SiteArticle e, SiteArticleDTO dto) { + if(dto == null) return; + return; + } + + public static SiteArticleAssembler of() { + return SpringUtils.getBean(SiteArticleAssembler.class); + } +} diff --git a/src/main/java/cn/stock/market/application/assembler/SiteNewsAssembler.java b/src/main/java/cn/stock/market/application/assembler/SiteNewsAssembler.java new file mode 100644 index 0000000..016ba8f --- /dev/null +++ b/src/main/java/cn/stock/market/application/assembler/SiteNewsAssembler.java @@ -0,0 +1,35 @@ +package cn.stock.market.application.assembler; + +import cn.qutaojing.common.utils.Beans; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.SiteNews; +import cn.stock.market.dto.SiteNewsDTO; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +/** + * SiteNewsAssembler + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/19 + */ +@Component +@Lazy +public class SiteNewsAssembler { + public SiteNewsDTO toDTO(SiteNews e) { + SiteNewsDTO dto = Beans.mapper(e, SiteNewsDTO.class); + if(dto == null) return dto; + fill(e, dto); + return dto; + } + + protected void fill(SiteNews e, SiteNewsDTO dto) { + if(dto == null) return; + return; + } + + public static SiteNewsAssembler of() { + return SpringUtils.getBean(SiteNewsAssembler.class); + } +} diff --git a/src/main/java/cn/stock/market/application/assembler/StockAssembler.java b/src/main/java/cn/stock/market/application/assembler/StockAssembler.java new file mode 100644 index 0000000..942bb30 --- /dev/null +++ b/src/main/java/cn/stock/market/application/assembler/StockAssembler.java @@ -0,0 +1,35 @@ +package cn.stock.market.application.assembler; + +import cn.qutaojing.common.utils.Beans; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.Stock; +import cn.stock.market.dto.StockDTO; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +/** + * StockAssembler + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Component +@Lazy +public class StockAssembler { + public StockDTO toDTO(Stock e) { + StockDTO dto = Beans.mapper(e, StockDTO.class); + if(dto == null) return dto; + fill(e, dto); + return dto; + } + + protected void fill(Stock e, StockDTO dto) { + if(dto == null) return; + return; + } + + public static StockAssembler of() { + return SpringUtils.getBean(StockAssembler.class); + } +} diff --git a/src/main/java/cn/stock/market/application/assembler/SysLogAssembler.java b/src/main/java/cn/stock/market/application/assembler/SysLogAssembler.java new file mode 100644 index 0000000..0aab634 --- /dev/null +++ b/src/main/java/cn/stock/market/application/assembler/SysLogAssembler.java @@ -0,0 +1,28 @@ +package cn.stock.market.application.assembler; + +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +import cn.qutaojing.common.utils.Beans; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.SysLog; +import cn.stock.market.dto.SysLogDTO; + +/** + * SysLogAssembler + * + * @author xlfd + * @email xlfd@gmail.com + * @created 2021/06/18 + */ +@Component +@Lazy +public class SysLogAssembler { + public SysLogDTO toDTO(SysLog entity) { + return Beans.mapper(entity, SysLogDTO.class); + } + + public static SysLogAssembler of() { + return SpringUtils.getBean(SysLogAssembler.class); + } +} diff --git a/src/main/java/cn/stock/market/constant/AccountActionEnum.java b/src/main/java/cn/stock/market/constant/AccountActionEnum.java new file mode 100644 index 0000000..dbba967 --- /dev/null +++ b/src/main/java/cn/stock/market/constant/AccountActionEnum.java @@ -0,0 +1,66 @@ +package cn.stock.market.constant; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:31 AM + */ +public enum AccountActionEnum { + SETTLEMENT("SETTLEMENT", "INCOME", "结算"), + COMMISSION_SETTLEMENT("COMMISSION_SETTLEMENT","INCOME", "佣金结算"), + FLOATING_SETTLEMENT("FLOATING_SETTLEMENT","INCOME", "浮动费结算"), + DELIVERY_SETTLEMENT("DELIVERY_SETTLEMENT", "INCOME", "配送费结算"), + WITHDRAWAL("WITHDRAWAL", "WITHDRAWAL", "提现"), + + ORDER("ORDER", "INCOME", "订单"), + RECHARGE("RECHARGE", "RECHARGE", "充值"), + BAIL_RECHARGE("BAIL_RECHARGE", "BAIL_RECHARGE", "保证金充值"), + TRUST_BUY("TRUST_BUY", "TRUST_BUY", "买入冻结金额"), + TRUST_SELL("TRUST_SELL", "TRUST_SELL", "委托卖出"), + TRUST_SELL_ATTACH_BAIL("TRUST_SELL_ATTACH_BAIL", "TRUST_SELL_ATTACH_BAIL", "委托卖出附带保证金"), +// TRUST_BUY_UNDO("TRUST_BUY_UNDO", "TRUST_BUY_UNDO", "委托买入撤销"), + TRANSFER_OUT("TRANSFER_OUT", "TRANSFER_OUT", "兑换转出"), + TRANSFER_IN("TRANSFER_IN", "TRANSFER_IN", "兑换转入"), + + PRE_TRADING_DAY("PRE_TRADING_DAY", "PRE_TRADING_DAY", "融资利息费"), + IPO_SUBSCRIBE("IPO_SUBSCRIBE", "IPO_SUBSCRIBE", "申购"), + ; + + String code; + String type; + String remark; + AccountActionEnum(String code, String type, String remark) { + this.code = code; + this.remark = remark; + this.type = type; + } + + public String code() { + return code; + } + + public String type() { + return type; + } + + public String remark() { + return remark; + } + + public static AccountActionEnum of(String code) { + AccountActionEnum[] values = AccountActionEnum.values(); + for (AccountActionEnum e : values) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } + + public static String remark(String code) { + AccountActionEnum of = of(code); + return of == null? "" : of.remark; + } +} diff --git a/src/main/java/cn/stock/market/constant/AccountLogType.java b/src/main/java/cn/stock/market/constant/AccountLogType.java new file mode 100644 index 0000000..88b6766 --- /dev/null +++ b/src/main/java/cn/stock/market/constant/AccountLogType.java @@ -0,0 +1,46 @@ +package cn.stock.market.constant; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:31 AM + */ +public enum AccountLogType { + SUBTRACT("SUBTRACT", "扣除"), + ADD("ADD", "新增"), + LOCK("LOCK", "冻结"), + LOCK_SUBTRACT("LOCK_SUBTRACT", "扣除冻结"), + LOCK_CANCEL("LOCK_CANCEL", "取消冻结"), + + WILL_INCOME("WILL_INCOME", "即将收入"), + WILL_INCOME_REFUND("WILL_INCOME_REFUND", "即将收入_退款"), + WILL_INCOME_SUCCESS("WILL_INCOME_SUCCESS", "即将收入_进账"), + ; + + String code; + String remark; + AccountLogType(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static AccountLogType of(String code) { + AccountLogType[] values = AccountLogType.values(); + for (AccountLogType e : values) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/AccountType.java b/src/main/java/cn/stock/market/constant/AccountType.java new file mode 100644 index 0000000..4171e95 --- /dev/null +++ b/src/main/java/cn/stock/market/constant/AccountType.java @@ -0,0 +1,67 @@ +package cn.stock.market.constant; + +/** + * 资金类型 + * + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:31 AM + */ +public enum AccountType { + STOCK_LOAN("STOCK_LOAN", "融资融券", "300010", false), + + STOCK("STOCK", "证券", "10", true), + FUND("FUND", "基金", "11", true), + + CHANGE("CHANGE", "钱包账户", "3000", true), + ; + + String code; + String remark; + String prefix; + boolean withdrawFlag; +// Currency currency; + AccountType(String code, /**Currency currency,**/ String remark, String prefix, boolean withdrawFlag) { + this.code = code; + this.remark = remark; + this.prefix = prefix; + this.withdrawFlag = withdrawFlag; +// this.currency = currency; + } + +// public Currency currency() { +// return currency; +// } + public String code() { + return code; + } + + public String prefix() { + return prefix; + } + + public boolean withdrawFlag() { + return withdrawFlag; + } + + public String remark() { + return remark; + } + + public static AccountType of(String code) { + AccountType[] values = AccountType.values(); + for (AccountType e : values) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } + + public static String remark(String code) { + AccountType of = of(code); + return of == null ? "" : of.remark; + } +} diff --git a/src/main/java/cn/stock/market/constant/AppVersionType.java b/src/main/java/cn/stock/market/constant/AppVersionType.java new file mode 100644 index 0000000..1cc3d84 --- /dev/null +++ b/src/main/java/cn/stock/market/constant/AppVersionType.java @@ -0,0 +1,47 @@ +package cn.stock.market.constant; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:31 AM + */ +public enum AppVersionType { + USER_APP_ANDROID("user_app_android", "用户APP安卓端"), + USER_APP_IOS("user_app_ios", "用户APP苹果端"), +// SHOP_APP_ANDROID("shop_app_android", "商家APP安卓端"), +// SHOP_APP_IOS("shop_app_ios", "商家APPIOS"), + + ; + + String code; + String remark; + AppVersionType(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static String remark(String code) { + AppVersionType of = of(code); + return of == null ? "" : of.remark; + } + + public static AppVersionType of(String code) { + AppVersionType[] values = AppVersionType.values(); + for (AppVersionType e : values) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/AppVersionUpdateTag.java b/src/main/java/cn/stock/market/constant/AppVersionUpdateTag.java new file mode 100644 index 0000000..5435069 --- /dev/null +++ b/src/main/java/cn/stock/market/constant/AppVersionUpdateTag.java @@ -0,0 +1,46 @@ +package cn.stock.market.constant; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:31 AM + */ +public enum AppVersionUpdateTag { + LATEST("latest", "最新版本,无需更新"), + AUDIT("audit", "审核版本"), + UPDATE_CHOOSE("choose_update", "选择更新"), + UPDATE_MUST("must_update", "强制更新"); + ; + + String code; + String remark; + AppVersionUpdateTag(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static String remark(String code) { + AppVersionUpdateTag of = of(code); + return of == null ? "" : of.remark; + } + + public static AppVersionUpdateTag of(String code) { + AppVersionUpdateTag[] values = AppVersionUpdateTag.values(); + for (AppVersionUpdateTag e : values) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/BannerType.java b/src/main/java/cn/stock/market/constant/BannerType.java new file mode 100644 index 0000000..50f2d6b --- /dev/null +++ b/src/main/java/cn/stock/market/constant/BannerType.java @@ -0,0 +1,45 @@ +package cn.stock.market.constant; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:31 AM + */ +public enum BannerType { + INDEX("INDEX", "首页"), + INDEX_TOP4("INDEX_TOP4", "首页_4宫格"), + ACTI("ACTI", "活动中心"), + ; + + String code; + String remark; + BannerType(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static String remark(String code) { + BannerType of = of(code); + return of == null ? "" : of.remark; + } + + public static BannerType of(String code) { + BannerType[] values = BannerType.values(); + for (BannerType e : values) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/BillOrderAction.java b/src/main/java/cn/stock/market/constant/BillOrderAction.java new file mode 100644 index 0000000..2773960 --- /dev/null +++ b/src/main/java/cn/stock/market/constant/BillOrderAction.java @@ -0,0 +1,45 @@ +package cn.stock.market.constant; + +/** + * 动作产生1/n个BillOrderEvent + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:14 AM + */ +public enum BillOrderAction { + CREATE("CREATE", "创建"), + REVOKE("REVOKE", "撤单"), + REFUND("REFUND", "退款"), + DILIVERY_CANCEL("DILIVERY_CANCEL", "骑手订单取消"), + DILIVERY_CREATE("DILIVERY_CREATE", "骑手订单创建"), + DILIVERY_ADD_TIP("DILIVERY_ADD_TIP", "加小费"), + ; + + String code; + String remark; + + BillOrderAction(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static BillOrderAction of(String code) { + BillOrderAction[] enums = BillOrderAction.values(); + for (BillOrderAction e : enums) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/BillOrderEvent.java b/src/main/java/cn/stock/market/constant/BillOrderEvent.java new file mode 100644 index 0000000..46f240a --- /dev/null +++ b/src/main/java/cn/stock/market/constant/BillOrderEvent.java @@ -0,0 +1,55 @@ +package cn.stock.market.constant; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:14 AM + */ +public enum BillOrderEvent { + CREATE("CREATE", "创建"), + USER_DELIVERY_FEE_TRANSFER("USER_DELIVERY_FEE_TRANSFER", "用户配送费转移"), + DELIVERY_FEE_CREATE("DELIVERY_CREATE", "配送费创建"), + DELIVERY_FEE_CANCEL("DELIVERY_CANCEL", "配送费取消"), + DELIVERY_CUSTOM_FEE_CANCEL("DELIVERY_CANCEL", "配送增值费取消"), + DELIVERY_TIP_FEE_CANCEL("DELIVERY_TIP_FEE_CANCEL", "小费取消"), + DELIVERY_TIP_FEE_ADD("DELIVERY_TIP_FEE_ADD", "小费增加"), + DELIVERY_DEDIT_ADD("DELIVERY_DEDIT_ADD", "违约金增加"), + + FLOATING_REDUCE("FLOATING_REDUCE", "浮动费扣除"), + POUNDAGE_REDUCE("POUNDAGE_REDUCE", "交易费扣除"), + GOODS_REFUND("GOODS_REFUND", "商品退款"), + COMMISSION_REDUCE("COMMISSION_REDUCE", "佣金扣除"), + MERCHANT_COMMISSION_REDUCE("MERCHANT_COMMISSION_REDUCE", "商户佣金扣除"), + PACKINGFEE_REDUCE("PACKINGFEE_REDUCE", "打包费扣除"), + COUPONS_RETURN("COUPONS_RETURN", "优惠券返还"), + GOODS_ERROR_REDUCE("GOODS_ERROR_REDUCE", "商品误差扣除"), + ; + + String code; + String remark; + + BillOrderEvent(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static BillOrderEvent of(String code) { + BillOrderEvent[] enums = BillOrderEvent.values(); + for (BillOrderEvent e : enums) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/BillType.java b/src/main/java/cn/stock/market/constant/BillType.java new file mode 100644 index 0000000..808acd8 --- /dev/null +++ b/src/main/java/cn/stock/market/constant/BillType.java @@ -0,0 +1,39 @@ +package cn.stock.market.constant; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:14 AM + */ +public enum BillType { + ORDER("ORDER", "订单类"), + ; + + String code; + String remark; + + BillType(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static BillType of(String code) { + BillType[] enums = BillType.values(); + for (BillType e : enums) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/CalcToValueType.java b/src/main/java/cn/stock/market/constant/CalcToValueType.java new file mode 100644 index 0000000..b3bfc30 --- /dev/null +++ b/src/main/java/cn/stock/market/constant/CalcToValueType.java @@ -0,0 +1,47 @@ +package cn.stock.market.constant; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:14 AM + * + * @deprecated 参考 cn.stock.trade.application.processor.trade.calc.ITaxCalc + */ +@Deprecated +public enum CalcToValueType { + FIXED("FIXED", "固定"), + PERCENT("PERCENT", "百分比"),; + + String code; + String remark; + + CalcToValueType(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static String remark(String code) { + CalcToValueType of = of(code); + return of == null ? "" : of.remark; + } + + public static CalcToValueType of(String code) { + CalcToValueType[] enums = CalcToValueType.values(); + for (CalcToValueType e : enums) { + if (e.code.equalsIgnoreCase(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/CapitalDirection.java b/src/main/java/cn/stock/market/constant/CapitalDirection.java new file mode 100644 index 0000000..85daffd --- /dev/null +++ b/src/main/java/cn/stock/market/constant/CapitalDirection.java @@ -0,0 +1,42 @@ +package cn.stock.market.constant; + +/** + * 资金方向 + * + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:31 AM + */ +public enum CapitalDirection { + IN("IN", "收"), + OUT("OUT", "支"), + ; + + String code; + String remark; + + CapitalDirection(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static CapitalDirection of(String code) { + CapitalDirection[] values = CapitalDirection.values(); + for (CapitalDirection e : values) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/CapitalGroup.java b/src/main/java/cn/stock/market/constant/CapitalGroup.java new file mode 100644 index 0000000..e70cacd --- /dev/null +++ b/src/main/java/cn/stock/market/constant/CapitalGroup.java @@ -0,0 +1,41 @@ +package cn.stock.market.constant; + +/** + * 资金组 + * + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:31 AM + */ +public enum CapitalGroup { + OTHER("OTHER", "其他"), + USER("USER", "用户"), + ; + + String code; + String remark; + CapitalGroup(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static CapitalGroup of(String code) { + CapitalGroup[] values = CapitalGroup.values(); + for (CapitalGroup e : values) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/CapitalType.java b/src/main/java/cn/stock/market/constant/CapitalType.java new file mode 100644 index 0000000..3050c0c --- /dev/null +++ b/src/main/java/cn/stock/market/constant/CapitalType.java @@ -0,0 +1,64 @@ +package cn.stock.market.constant; + +/** + * 资金类型 + * + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:31 AM + */ +public enum CapitalType { + /** + * 订单支付成功 + */ +// DELIVERY_FEE("DELIVERY_FEE", CapitalGroup.OTHER, "配送费"), +// COMMISSION("COMMISSION", CapitalGroup.OTHER, "佣金"), +// MERCHANT_COMMISSION("MERCHANT_COMMISSION", CapitalGroup.OTHER, "商家佣金"), +// TIP("TIP", CapitalGroup.OTHER, "小费"), +// DEDIT("DEDIT", CapitalGroup.OTHER, "违约金"), +// PACKING_FEE("PACKING_FEE", CapitalGroup.OTHER, "打包费"), +// GOODS("GOODS", CapitalGroup.OTHER, "商品"), +// FULL_REDUCTION("FULL_REDUCTION", CapitalGroup.OTHER, "满减"), +// COUPONS("COUPONS", CapitalGroup.OTHER, "优惠券"), +// FLOATING_FEE("FLOATING_FEE", CapitalGroup.OTHER, "浮动费"), +// DELIVERY_CUSTOM_FEE("DELIVERY_CUSTOM_FEE", CapitalGroup.OTHER, "配送增值费"), +// GOODS_ERROR("GOODS_ERROR", CapitalGroup.OTHER, "商品误差值"), +// POUNDAGE("POUNDAGE", CapitalGroup.OTHER, "手续费"), //默认平台承担, 可以配置成商家承担 + CASH("CASH", CapitalGroup.OTHER, "现金"), + LOAN("LOAN", CapitalGroup.OTHER,"融资"), + + ; + + String code; + String remark; + CapitalGroup group; + CapitalType(String code, CapitalGroup group, String remark) { + this.code = code; + this.remark = remark; + this.group = group; + } + + public CapitalGroup group() { + return group; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static CapitalType of(String code) { + CapitalType[] values = CapitalType.values(); + for (CapitalType e : values) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/ClickAction.java b/src/main/java/cn/stock/market/constant/ClickAction.java new file mode 100644 index 0000000..1bbba0c --- /dev/null +++ b/src/main/java/cn/stock/market/constant/ClickAction.java @@ -0,0 +1,52 @@ +package cn.stock.market.constant; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:31 AM + */ +public enum ClickAction { + WEB("WEB", "网页"), + APP_PAGE("APP_PAGE", "App页面"), + OPEN_OR_POSITION("OPEN_OR_POSITION", "开户/持仓"), + GOODS_DETAIL("GOODS_DETAIL", "商品详情"), + FRONT_CLASSIFY("FRONT_CLASSIFY", "前端分类"), + SUBJECT("SUBJECT", "专题"), + ORDER_DETAIL("ORDER_DETAIL", "订单详情"), + LOGIN("LOGIN", "登录"), + EXCLUSIVE_LIST("EXCLUSIVE_LIST", "独家列表"), + WITHDRAWAL_INDEX("WITHDRAWAL_INDEX", "提现首页"), + ; + + String code; + String remark; + ClickAction(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static String remark(String code) { + ClickAction of = of(code); + return of == null ? "" : of.remark; + } + + public static ClickAction of(String code) { + ClickAction[] values = ClickAction.values(); + for (ClickAction e : values) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/DeliveryTimeType.java b/src/main/java/cn/stock/market/constant/DeliveryTimeType.java new file mode 100644 index 0000000..b34c1f9 --- /dev/null +++ b/src/main/java/cn/stock/market/constant/DeliveryTimeType.java @@ -0,0 +1,43 @@ +package cn.stock.market.constant; + +import com.ag.utils.NumberUtils; + +/** + * 送达时间类型 + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:14 AM + */ +public enum DeliveryTimeType { + NOW(1, "立即送达"), + SUBSCRIBE(2, "预约时间"), + ; + + int status; + String remark; + + DeliveryTimeType(int status, String remark) { + this.status = status; + this.remark = remark; + } + + public int status() { + return status; + } + + public String remark() { + return remark; + } + + public static DeliveryTimeType of(Integer s) { + DeliveryTimeType[] enums = DeliveryTimeType.values(); + for (DeliveryTimeType e : enums) { + if (NumberUtils.equals(e.status, s)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/JsonInfoType.java b/src/main/java/cn/stock/market/constant/JsonInfoType.java new file mode 100644 index 0000000..f6cd61d --- /dev/null +++ b/src/main/java/cn/stock/market/constant/JsonInfoType.java @@ -0,0 +1,39 @@ +package cn.stock.market.constant; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:14 AM + */ +public enum JsonInfoType { + PARTNER("PARTNER", "合伙人"), + ; + + String code; + String remark; + + JsonInfoType(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static JsonInfoType of(String code) { + JsonInfoType[] enums = JsonInfoType.values(); + for (JsonInfoType e : enums) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/OrderAfterSaleBizStatus.java b/src/main/java/cn/stock/market/constant/OrderAfterSaleBizStatus.java new file mode 100644 index 0000000..f109d96 --- /dev/null +++ b/src/main/java/cn/stock/market/constant/OrderAfterSaleBizStatus.java @@ -0,0 +1,56 @@ +package cn.stock.market.constant; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:14 AM + */ +public enum OrderAfterSaleBizStatus { + CREATED("CREATED", "已申请", OrderAfterSaleStatus.CREATED), + PASSED("PASSED", "已同意", OrderAfterSaleStatus.PASSED), + USER_SENDED("USER_SENDED", "用户已发货", OrderAfterSaleStatus.USER_SENDED), + MERCHANT_CONFIRMED("MERCHANT_CONFIRMED", "商家收货", OrderAfterSaleStatus.MERCHANT_CONFIRMED), + MERCHANT_SENDED("MERCHANT_SENDED", "商家已发货", OrderAfterSaleStatus.MERCHANT_SENDED), + USER_CONFIRMED("USER_CONFIRMED", "用户已收货", OrderAfterSaleStatus.USER_CONFIRMED), + REJECTED("REJECTED", "拒绝", OrderAfterSaleStatus.REJECTED), + ; + + String code; + String remark; + OrderAfterSaleStatus os; + + OrderAfterSaleBizStatus(String code, String remark, OrderAfterSaleStatus os) { + this.code = code; + this.remark = remark; + this.os = os; + } + + public String code() { + return code; + } + + public OrderAfterSaleStatus os() { + return os; + } + + public String remark() { + return remark; + } + + public static String remark(String code) { + OrderAfterSaleBizStatus of = of(code); + return of == null ? "" : of.remark; + } + + public static OrderAfterSaleBizStatus of(String code) { + OrderAfterSaleBizStatus[] enums = OrderAfterSaleBizStatus.values(); + for (OrderAfterSaleBizStatus e : enums) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/OrderAfterSaleNode.java b/src/main/java/cn/stock/market/constant/OrderAfterSaleNode.java new file mode 100644 index 0000000..bdc6e50 --- /dev/null +++ b/src/main/java/cn/stock/market/constant/OrderAfterSaleNode.java @@ -0,0 +1,67 @@ +package cn.stock.market.constant; + +import java.util.List; + +import com.google.common.collect.Lists; + +import cn.qutaojing.common.constant.RoleEnum; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:14 AM + */ +public enum OrderAfterSaleNode { + CREATED("CREATED", "用户申请", RoleEnum.USER, Lists.newArrayList(OrderAfterSaleBizStatus.CREATED)), + SYS_AUDIT("SYS_AUDIT", "平台审核", RoleEnum.SYS, Lists.newArrayList(OrderAfterSaleBizStatus.PASSED, OrderAfterSaleBizStatus.REJECTED)), + USER_SENDED("USER_SENDED", "用户已发货", RoleEnum.USER, Lists.newArrayList(OrderAfterSaleBizStatus.USER_SENDED)), + MERCHANT_CONFIRMED("MERCHANT_CONFIRMED", "商家收货", RoleEnum.SHOP, Lists.newArrayList(OrderAfterSaleBizStatus.MERCHANT_CONFIRMED)), + MERCHANT_SENDED("MERCHANT_SENDED", "商家已发货", RoleEnum.SHOP, Lists.newArrayList(OrderAfterSaleBizStatus.MERCHANT_SENDED)), + USER_CONFIRMED("USER_CONFIRMED", "用户已收货", RoleEnum.USER, Lists.newArrayList(OrderAfterSaleBizStatus.USER_CONFIRMED)), + ; + + String code; + String remark; + RoleEnum role; + List statusList; + OrderAfterSaleNode(String code, String remark, RoleEnum role, List statusList) { + + this.code = code; + this.remark = remark; + this.role = role; + this.statusList = statusList; + } + + public List statusList() { + return statusList; + } + + public String code() { + return code; + } + + public RoleEnum role() { + return role; + } + + public String remark() { + return remark; + } + + public static String remark(String code) { + OrderAfterSaleNode of = of(code); + return of == null? "" : of.remark; + } + + public static OrderAfterSaleNode of(String code) { + OrderAfterSaleNode[] enums = OrderAfterSaleNode.values(); + for (OrderAfterSaleNode e : enums) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/OrderAfterSaleStatus.java b/src/main/java/cn/stock/market/constant/OrderAfterSaleStatus.java new file mode 100644 index 0000000..e8581e5 --- /dev/null +++ b/src/main/java/cn/stock/market/constant/OrderAfterSaleStatus.java @@ -0,0 +1,53 @@ +package cn.stock.market.constant; + +import com.ag.utils.NumberUtils; + +/** + * + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:14 AM + */ +public enum OrderAfterSaleStatus { + CREATED(0, "已创建"), + PASSED(4, "已同意"), + USER_SENDED(10, "用户已发货"), + MERCHANT_CONFIRMED(20, "商家收货"), + MERCHANT_SENDED(30, "商家已发货"), + USER_CONFIRMED(40, "用户已收货"), + REJECTED(-4, "拒绝"), + ; + + int status; + String remark; + + OrderAfterSaleStatus(int status, String remark) { + this.status = status; + this.remark = remark; + } + + public int status() { + return status; + } + + public String remark() { + return remark; + } + + public static String remark(Integer v) { + OrderAfterSaleStatus of = of(v); + return of == null ? "" : of.remark; + } + + public static OrderAfterSaleStatus of(Integer s) { + OrderAfterSaleStatus[] enums = OrderAfterSaleStatus.values(); + for (OrderAfterSaleStatus e : enums) { + if(NumberUtils.equals(e.status, s)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/OrderAfterSaleType.java b/src/main/java/cn/stock/market/constant/OrderAfterSaleType.java new file mode 100644 index 0000000..0451bac --- /dev/null +++ b/src/main/java/cn/stock/market/constant/OrderAfterSaleType.java @@ -0,0 +1,47 @@ +package cn.stock.market.constant; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:14 AM + */ +public enum OrderAfterSaleType { + DIRECTLY("DIRECTLY", "直接退款"), + REFUND_GOODS_MONEY("REFUND_GOODS_MONEY", "退货/退款"), + EXCHANGE_GOODS("EXCHANGE_GOODS", "换货"), + RECHARGE_GOODS("RECHARGE_GOODS", "补货"), + ; + + String code; + String remark; + + OrderAfterSaleType(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static String remark(String code) { + OrderAfterSaleType of = of(code); + return of == null? "" : of.remark; + } + + public static OrderAfterSaleType of(String code) { + OrderAfterSaleType[] enums = OrderAfterSaleType.values(); + for (OrderAfterSaleType e : enums) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/OrderBizStatus.java b/src/main/java/cn/stock/market/constant/OrderBizStatus.java new file mode 100644 index 0000000..fa6f198 --- /dev/null +++ b/src/main/java/cn/stock/market/constant/OrderBizStatus.java @@ -0,0 +1,78 @@ +package cn.stock.market.constant; + +import java.util.List; +import java.util.Map; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:14 AM + */ +public enum OrderBizStatus { + CREATED("CREATED", "已创建", OrderStatus.CREATED), + PAYED("PAYED", "已支付", OrderStatus.PAYED), + SENDED("SENDED", "已发货", OrderStatus.SENDED), + CONFIRMED("CONFIRMED", "已收货", OrderStatus.CONFIRMED), + REFUNDED("REFUNDED", "已退款", OrderStatus.REFUNDED), + CANCELED("CANCELED", "已撤销", OrderStatus.CANCELED), ; + + String code; + String remark; + OrderStatus os; + + public static List NORMAL_PROGESS_LIST = Lists.newArrayList(CREATED, PAYED, SENDED, CONFIRMED); + public static Map NORMAL_PROGESS_MAP = normalProgessMap(); + + public static Map normalProgessMap() { + Map m = Maps.newHashMap(); + for(int i = 0; i < NORMAL_PROGESS_LIST.size(); i++) { + OrderBizStatus ob = NORMAL_PROGESS_LIST.get(i); + m.put(ob, i); + } + + return ImmutableMap.copyOf(m); + } + + public static int toIndex(OrderBizStatus ob) { + return NORMAL_PROGESS_MAP.getOrDefault(ob, -1); + } + + OrderBizStatus(String code, String remark, OrderStatus os) { + this.code = code; + this.remark = remark; + this.os = os; + } + + public String code() { + return code; + } + + public OrderStatus os() { + return os; + } + + public String remark() { + return remark; + } + + public static String remark(String code) { + OrderBizStatus of = of(code); + return of == null ? "" : of.remark; + } + + public static OrderBizStatus of(String code) { + OrderBizStatus[] enums = OrderBizStatus.values(); + for (OrderBizStatus e : enums) { + if(e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/OrderModel.java b/src/main/java/cn/stock/market/constant/OrderModel.java new file mode 100644 index 0000000..cbdfdb9 --- /dev/null +++ b/src/main/java/cn/stock/market/constant/OrderModel.java @@ -0,0 +1,45 @@ +package cn.stock.market.constant; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:14 AM + */ +public enum OrderModel { + GRAP("GRAP", "抢单模式"), + GATHER("GATHER", "集散模式"), + ; + + String code; + String remark; + + OrderModel(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static String remark(String code) { + OrderModel of = of(code); + return of == null ? "" : of.remark; + } + + public static OrderModel of(String code) { + OrderModel[] enums = OrderModel.values(); + for (OrderModel e : enums) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/OrderOperButtonEnum.java b/src/main/java/cn/stock/market/constant/OrderOperButtonEnum.java new file mode 100644 index 0000000..41dd61e --- /dev/null +++ b/src/main/java/cn/stock/market/constant/OrderOperButtonEnum.java @@ -0,0 +1,72 @@ +package cn.stock.market.constant; + +/** + * + * title: OrderOperButtonEnum.java + * + * 订单操作按钮 + * + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Mar 24, 2021 2:54:38 PM + */ +public enum OrderOperButtonEnum { + CAN_CANCEL("CAN_CANCEL", "取消订单"), + CAN_CONTACT_MERCHANT("CAN_CONTACT_MERCHANT", "联系商家"), + CAN_PAY("CAN_PAY", "立即支付"), + CAN_MODIFY("CAN_MODIFY", "修改订单信息"), + CAN_REFUND("CAN_REFUND", "可以退款 (支付成功后的取消订单)"), + + CAN_CONFIRM("CAN_CONFIRM", "确认收货"), + CAN_SHOW_EXP_INFO("CAN_SHOW_EXP_INFO", "快递查询"), + +// BROWSE_OTHER("BROWSE_OTHER", "逛逛别家"), +// CAN_REORDER("CAN_REORDER", "再来一单"), +// CAN_APPLY_REFUND("CAN_APPLY_REFUND", "申请退款"), +// CAN_CONTACT_DELIVERYER("CAN_CONTACT_DELIVERYER", "联系骑手"), +// CAN_COMMENT("CAN_COMMENT", "去评价"), +// CAN_APPEAL("CAN_APPEAL", "去申诉"), + + CAN_APPEAL_DETAIL("CAN_APPEAL_DETAIL", "申诉详情"), + CAN_REFUND_DETAIL("CAN_REFUND_DETAIL", "退款详情"), + + //商家 +// CAN_MERCHANT_CONFIRM("CAN_MERCHANT_CONFIRM", "商户接单"), +// CAN_MERCHANT_CANCEL("CAN_MERCHANT_CANCEL", "商户取消"), +// CAN_MERCHANT_REFUND("CAN_MERCHANT_REFUND", "商家退款"), +// CAN_MERCHANT_AGREE_APPLY_REFUND("CAN_MERCHANT_AGREE_APPLY_REFUND", "商家同意退款申请"), +// CAN_MERCHANT_REFUSE_APPLY_REFUND("CAN_MERCHANT_REFUSE_APPLY_REFUND", "商家拒绝退款申请"), +// CAN_MERCHANT_CONTACT_DELIVERYER("CAN_MERCHANT_CONTACT_DELIVERYER", "商家联系骑手"), +// CAN_MERCHANT_DO_FETCH("CAN_MERCHANT_DO_FETCH", "商家取餐"), +// CAN_MERCHANT_DO_ARRIVED_CUSTOMER("CAN_MERCHANT_DO_ARRIVED_CUSTOMER", "商家送达"), +// CAN_SWITCH_MERCHANT_DELIVERY_PLATFORM("CAN_SWITCH_MERCHANT_DELIVERY_PLATFORM", "切换商家自配送"), +// CAN_DELIVERY_ADDTIP("CAN_DELIVERY_ADDTIP", "加小费"), +// CAN_DELIVERY_REORDER("CAN_DELIVERY_REORDER", "重发配送"), +// CAN_DELIVERY_CANCEL_AND_REORDER("CAN_DELIVERY_CANCEL_AND_REORDER", "配送取消重发骑手单"), + + CAN_MERCHANT_SEND("CAN_MERCHANT_SEND", "商户发货"), + CAN_TIP_SEND("CAN_TIP_SEND", "提醒发货"), + ; + String code; + String remark; + + OrderOperButtonEnum(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + @Override + public String toString() { + return code; + } + +} diff --git a/src/main/java/cn/stock/market/constant/OrderStatus.java b/src/main/java/cn/stock/market/constant/OrderStatus.java new file mode 100644 index 0000000..fb1c998 --- /dev/null +++ b/src/main/java/cn/stock/market/constant/OrderStatus.java @@ -0,0 +1,52 @@ +package cn.stock.market.constant; + +import com.ag.utils.NumberUtils; + +/** + * + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:14 AM + */ +public enum OrderStatus { + CREATED(0, "已创建"), + PAYED(4, "已支付"), + SENDED(10, "已发货"), + CONFIRMED(20, "已收货"), + CANCELED(-5, "已撤销"), + REFUNDED(-4, "已退款"), + ; + + int status; + String remark; + + OrderStatus(int status, String remark) { + this.status = status; + this.remark = remark; + } + + public int status() { + return status; + } + + public String remark() { + return remark; + } + + public static String remark(Integer v) { + OrderStatus of = of(v); + return of == null ? "" : of.remark; + } + + public static OrderStatus of(Integer s) { + OrderStatus[] enums = OrderStatus.values(); + for (OrderStatus e : enums) { + if(NumberUtils.equals(e.status, s)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/OrderType.java b/src/main/java/cn/stock/market/constant/OrderType.java new file mode 100644 index 0000000..777a769 --- /dev/null +++ b/src/main/java/cn/stock/market/constant/OrderType.java @@ -0,0 +1,39 @@ +package cn.stock.market.constant; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:14 AM + */ +public enum OrderType { + CUSTOM_PULL("CUSTOM_PULL", "主动拉取"), + ; + + String code; + String remark; + + OrderType(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static OrderType of(String code) { + OrderType[] enums = OrderType.values(); + for (OrderType e : enums) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/RechargeType.java b/src/main/java/cn/stock/market/constant/RechargeType.java new file mode 100644 index 0000000..10a2196 --- /dev/null +++ b/src/main/java/cn/stock/market/constant/RechargeType.java @@ -0,0 +1,49 @@ +package cn.stock.market.constant; + +/** + * 资金类型 + * + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:31 AM + */ +public enum RechargeType { + /** + * 线下转账 + */ + OFFLINE("OFFLINE", "线下转账"), + ALIPAY_WAP("ALIPAY_WAP", "支付宝WAP"), + ; + + String code; + String remark; + RechargeType(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static String remark(String code) { + RechargeType of = of(code); + return of == null ? "" : of.remark; + } + + public static RechargeType of(String code) { + RechargeType[] values = RechargeType.values(); + for (RechargeType e : values) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/SMSChannelType.java b/src/main/java/cn/stock/market/constant/SMSChannelType.java new file mode 100644 index 0000000..6841326 --- /dev/null +++ b/src/main/java/cn/stock/market/constant/SMSChannelType.java @@ -0,0 +1,48 @@ +package cn.stock.market.constant; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:14 AM + */ +public enum SMSChannelType { + RIDER_LOGIN("RIDER_LOGIN", "骑手端登录"), + SORTER_LOGIN("SORTER_LOGIN", "分拣员登录"), + SHOP_LOGIN("SHOP_LOGIN", "商家登录"), + SHOP_REGIST("SHOP_REGIST", "商家注册"), + USER_LOGIN("USER_LOGIN", "用户登录"), + USER_REGIST("USER_REGIST", "用户注册"), + USER_REMOVE("USER_REMOVE", "用户注销"), + FORGET_PWD_SMS("FORGET_PWD_SMS", "忘记密码"), + FORGET_PAYPWD_SMS("FORGET_PAYPWD_SMS", "忘记支付密码"), + WTHDRAWAL("WTHDRAWAL", "提现验证码"), + ; + + String code; + String remark; + + SMSChannelType(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static SMSChannelType of(String code) { + SMSChannelType[] enums = SMSChannelType.values(); + for (SMSChannelType e : enums) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/SettlementStatus.java b/src/main/java/cn/stock/market/constant/SettlementStatus.java new file mode 100644 index 0000000..c63c6de --- /dev/null +++ b/src/main/java/cn/stock/market/constant/SettlementStatus.java @@ -0,0 +1,35 @@ +package cn.stock.market.constant; +import com.ag.utils.NumberUtils; + +public enum SettlementStatus { + SETTLEMENTED(4, "已结算"), + UNSETTLEMENT(0, "未结算"), + CLOSE(-4, "已关闭"); + + Integer v; + String remark; + + SettlementStatus(Integer v,String remark) { + this.remark = remark; + this.v = v; + } + + public Integer v() { + return v; + } + + public String remark() { + return remark; + } + + public static SettlementStatus of(Integer value) { + SettlementStatus[] values = SettlementStatus.values(); + for (SettlementStatus e : values) { + if(NumberUtils.equals(e.v, value)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/SettlementType.java b/src/main/java/cn/stock/market/constant/SettlementType.java new file mode 100644 index 0000000..f8d8880 --- /dev/null +++ b/src/main/java/cn/stock/market/constant/SettlementType.java @@ -0,0 +1,39 @@ +package cn.stock.market.constant; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:31 AM + */ +public enum SettlementType { + TO_ACCOUNT("TO_ACCOUNT", "结算到账户"), + TO_DIV("TO_DIV", "分账"),; + + String code; + String remark; + + SettlementType(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static SettlementType of(String code) { + SettlementType[] values = SettlementType.values(); + for (SettlementType e : values) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/StockSource.java b/src/main/java/cn/stock/market/constant/StockSource.java new file mode 100644 index 0000000..34638de --- /dev/null +++ b/src/main/java/cn/stock/market/constant/StockSource.java @@ -0,0 +1,59 @@ +package cn.stock.market.constant; + +import com.ag.exception.SysTipsException; + +import cn.qutaojing.common.constant.Currency; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:31 AM + */ +public enum StockSource { + A("A", "A股"), HK("HK", "港股"), US("US", "美股"),; + + String code; + String remark; + + StockSource(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static String remark(String code) { + StockSource of = of(code); + return of == null ? "" : of.remark; + } + + public static StockSource of(String code) { + StockSource[] values = StockSource.values(); + for (StockSource e : values) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } + + public Currency currency() { + if (this == A) { + return Currency.CNY; + } else if (this == HK) { + return Currency.HKD; + } else if (this == US) { + return Currency.USD; + } + + throw new SysTipsException("无法转换到对应币种."); + } +} diff --git a/src/main/java/cn/stock/market/constant/SysModule.java b/src/main/java/cn/stock/market/constant/SysModule.java new file mode 100644 index 0000000..43daf4b --- /dev/null +++ b/src/main/java/cn/stock/market/constant/SysModule.java @@ -0,0 +1,43 @@ +package cn.stock.market.constant; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:31 AM + */ +public enum SysModule { + ADMIN("ADMIN", "后台"), + ; + + String code; + String remark; + SysModule(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static String remark(String code) { + SysModule of = of(code); + return of == null ? "" : of.remark; + } + + public static SysModule of(String code) { + SysModule[] values = SysModule.values(); + for (SysModule e : values) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/ThirdAuthType.java b/src/main/java/cn/stock/market/constant/ThirdAuthType.java new file mode 100644 index 0000000..85f554a --- /dev/null +++ b/src/main/java/cn/stock/market/constant/ThirdAuthType.java @@ -0,0 +1,41 @@ +package cn.stock.market.constant; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:14 AM + */ +public enum ThirdAuthType { + MINIAPP("MINIAPP", "小程序"), + WX("WX", "微信"), + + ; + + String code; + String remark; + + ThirdAuthType(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static ThirdAuthType of(String code) { + ThirdAuthType[] enums = ThirdAuthType.values(); + for (ThirdAuthType e : enums) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/TrustDealType.java b/src/main/java/cn/stock/market/constant/TrustDealType.java new file mode 100644 index 0000000..1510e47 --- /dev/null +++ b/src/main/java/cn/stock/market/constant/TrustDealType.java @@ -0,0 +1,40 @@ +package cn.stock.market.constant; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:14 AM + */ +public enum TrustDealType { + MARKET_ORDER("MARKET_ORDER", "市价单"), + LIMIT_ORDER("LIMIT_ORDER", "限价单"), + ; + + String code; + String remark; + + TrustDealType(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static TrustDealType of(String code) { + TrustDealType[] enums = TrustDealType.values(); + for (TrustDealType e : enums) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/constant/TrustType.java b/src/main/java/cn/stock/market/constant/TrustType.java new file mode 100644 index 0000000..b0f5fd2 --- /dev/null +++ b/src/main/java/cn/stock/market/constant/TrustType.java @@ -0,0 +1,43 @@ +package cn.stock.market.constant; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 13, 2021 11:53:31 AM + */ +public enum TrustType { + SELL("SELL", "证券卖出"), BUY("BUY", "证券买入"),; + + String code; + String remark; + + TrustType(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static String remark(String code) { + TrustType of = of(code); + return of == null ? "" : of.remark; + } + + public static TrustType of(String code) { + TrustType[] values = TrustType.values(); + for (TrustType e : values) { + if (e.code.equals(code)) { + return e; + } + } + + return null; + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/convert/CityConvert.java b/src/main/java/cn/stock/market/domain/basic/convert/CityConvert.java new file mode 100644 index 0000000..7ea49cd --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/convert/CityConvert.java @@ -0,0 +1,24 @@ +package cn.stock.market.domain.basic.convert; + +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +import cn.qutaojing.common.domain.convert.SimpleEntityPOConvert; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.City; +import cn.stock.market.infrastructure.db.po.CityPO; + +/** + * CityConvert + * + * @author xlfd + * @email xlfd@gmail.com + * @created 2021/06/16 + */ +@Component +@Lazy +public class CityConvert extends SimpleEntityPOConvert { + public static CityConvert of() { + return SpringUtils.getBean(CityConvert.class); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/convert/JsonInfoConvert.java b/src/main/java/cn/stock/market/domain/basic/convert/JsonInfoConvert.java new file mode 100644 index 0000000..80e49d1 --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/convert/JsonInfoConvert.java @@ -0,0 +1,24 @@ +package cn.stock.market.domain.basic.convert; + +import cn.qutaojing.common.domain.convert.SimpleEntityPOConvert; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.JsonInfo; +import cn.stock.market.infrastructure.db.po.JsonInfoPO; + +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +/** + * JsonInfoConvert + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2022/08/16 + */ +@Component +@Lazy +public class JsonInfoConvert extends SimpleEntityPOConvert { + public static JsonInfoConvert of() { + return SpringUtils.getBean(JsonInfoConvert.class); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/convert/RealtimeConvert.java b/src/main/java/cn/stock/market/domain/basic/convert/RealtimeConvert.java new file mode 100644 index 0000000..9000d48 --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/convert/RealtimeConvert.java @@ -0,0 +1,23 @@ +package cn.stock.market.domain.basic.convert; + +import cn.qutaojing.common.domain.convert.SimpleEntityPOConvert; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.Realtime; +import cn.stock.market.infrastructure.db.po.RealtimePO; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +/** + * RealtimeConvert + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Component +@Lazy +public class RealtimeConvert extends SimpleEntityPOConvert { + public static RealtimeConvert of() { + return SpringUtils.getBean(RealtimeConvert.class); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/convert/SiteArticleConvert.java b/src/main/java/cn/stock/market/domain/basic/convert/SiteArticleConvert.java new file mode 100644 index 0000000..dae7dbe --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/convert/SiteArticleConvert.java @@ -0,0 +1,23 @@ +package cn.stock.market.domain.basic.convert; + +import cn.qutaojing.common.domain.convert.SimpleEntityPOConvert; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.SiteArticle; +import cn.stock.market.infrastructure.db.po.SiteArticlePO; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +/** + * SiteArticleConvert + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Component +@Lazy +public class SiteArticleConvert extends SimpleEntityPOConvert { + public static SiteArticleConvert of() { + return SpringUtils.getBean(SiteArticleConvert.class); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/convert/SiteNewsConvert.java b/src/main/java/cn/stock/market/domain/basic/convert/SiteNewsConvert.java new file mode 100644 index 0000000..016be69 --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/convert/SiteNewsConvert.java @@ -0,0 +1,23 @@ +package cn.stock.market.domain.basic.convert; + +import cn.qutaojing.common.domain.convert.SimpleEntityPOConvert; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.SiteNews; +import cn.stock.market.infrastructure.db.po.SiteNewsPO; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +/** + * SiteNewsConvert + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/19 + */ +@Component +@Lazy +public class SiteNewsConvert extends SimpleEntityPOConvert { + public static SiteNewsConvert of() { + return SpringUtils.getBean(SiteNewsConvert.class); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/convert/SiteSettingConvert.java b/src/main/java/cn/stock/market/domain/basic/convert/SiteSettingConvert.java new file mode 100644 index 0000000..60ac1f2 --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/convert/SiteSettingConvert.java @@ -0,0 +1,24 @@ +package cn.stock.market.domain.basic.convert; + +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +import cn.qutaojing.common.domain.convert.SimpleEntityPOConvert; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.SiteSetting; +import cn.stock.market.infrastructure.stockdb.po.SiteSettingPO; + +/** + * StockConvert + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Component +@Lazy +public class SiteSettingConvert extends SimpleEntityPOConvert { + public static SiteSettingConvert of() { + return SpringUtils.getBean(SiteSettingConvert.class); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/convert/StockConvert.java b/src/main/java/cn/stock/market/domain/basic/convert/StockConvert.java new file mode 100644 index 0000000..d2978de --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/convert/StockConvert.java @@ -0,0 +1,24 @@ +package cn.stock.market.domain.basic.convert; + +import cn.qutaojing.common.domain.convert.SimpleEntityPOConvert; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.Stock; +import cn.stock.market.infrastructure.stockdb.po.StockPO; + +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +/** + * StockConvert + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Component +@Lazy +public class StockConvert extends SimpleEntityPOConvert { + public static StockConvert of() { + return SpringUtils.getBean(StockConvert.class); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/convert/SysLogConvert.java b/src/main/java/cn/stock/market/domain/basic/convert/SysLogConvert.java new file mode 100644 index 0000000..930d6d5 --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/convert/SysLogConvert.java @@ -0,0 +1,24 @@ +package cn.stock.market.domain.basic.convert; + +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +import cn.qutaojing.common.domain.convert.SimpleEntityPOConvert; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.SysLog; +import cn.stock.market.infrastructure.db.po.SysLogPO; + +/** + * SysLogConvert + * + * @author xlfd + * @email xlfd@gmail.com + * @created 2021/06/18 + */ +@Component +@Lazy +public class SysLogConvert extends SimpleEntityPOConvert { + public static SysLogConvert of() { + return SpringUtils.getBean(SysLogConvert.class); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/entity/City.java b/src/main/java/cn/stock/market/domain/basic/entity/City.java new file mode 100644 index 0000000..69e1e8b --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/entity/City.java @@ -0,0 +1,50 @@ +package cn.stock.market.domain.basic.entity; + +import java.util.List; + +import com.ag.utils.JsonUtils; +import com.ag.utils.JsonUtils.IListToTreeWrapper; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; + +import cn.stock.market.infrastructure.db.po.CityPO; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * CityEntity + * + * @author xlfd + * @email xlfd@gmail.com + * @created 2021/06/16 + */ +@Data +@NoArgsConstructor +@SuperBuilder +@EqualsAndHashCode(callSuper = false) +public class City extends CityPO { + public static JSONArray tree(List list, int level) { + return JsonUtils.listToTree(list, new IListToTreeWrapper() { + @Override + public Object getParentValue(City t) { + return t.getParentId(); + } + + @Override + public Object getPkValue(City t) { + return String.valueOf(t.getId()); + } + + @Override + public JSONObject doConvertJson(City t) { + JSONObject json = new JSONObject(true); + json.put("id", t.getId()); + json.put("name", t.getName()); + json.put("path", t.getPath()); + return json; + } + }, level); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/entity/JsonInfo.java b/src/main/java/cn/stock/market/domain/basic/entity/JsonInfo.java new file mode 100644 index 0000000..9453403 --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/entity/JsonInfo.java @@ -0,0 +1,28 @@ +package cn.stock.market.domain.basic.entity; + +import cn.qutaojing.common.utils.Beans; +import cn.stock.market.dto.command.JsonInfoCreateCommand; +import cn.stock.market.infrastructure.db.po.JsonInfoPO; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * JsonInfo + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2022/08/16 + */ +@Data +@NoArgsConstructor +@SuperBuilder +@EqualsAndHashCode( + callSuper = false +) +public class JsonInfo extends JsonInfoPO { + public void update(JsonInfoCreateCommand cmd) { + Beans.copyPropertiesIgnoreNull(cmd, this); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/entity/Realtime.java b/src/main/java/cn/stock/market/domain/basic/entity/Realtime.java new file mode 100644 index 0000000..1011068 --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/entity/Realtime.java @@ -0,0 +1,28 @@ +package cn.stock.market.domain.basic.entity; + +import cn.qutaojing.common.utils.Beans; +import cn.stock.market.dto.command.RealtimeCreateCommand; +import cn.stock.market.infrastructure.db.po.RealtimePO; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * Realtime + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Data +@NoArgsConstructor +@SuperBuilder +@EqualsAndHashCode( + callSuper = false +) +public class Realtime extends RealtimePO { + public void update(RealtimeCreateCommand cmd) { + Beans.copyPropertiesIgnoreNull(cmd, this); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/entity/SiteArticle.java b/src/main/java/cn/stock/market/domain/basic/entity/SiteArticle.java new file mode 100644 index 0000000..d7bc1e6 --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/entity/SiteArticle.java @@ -0,0 +1,26 @@ +package cn.stock.market.domain.basic.entity; + +import cn.qutaojing.common.utils.Beans; +import cn.stock.market.dto.command.SiteArticleCreateCommand; +import cn.stock.market.infrastructure.db.po.SiteArticlePO; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * SiteArticle + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Data +@NoArgsConstructor +@SuperBuilder +@EqualsAndHashCode(callSuper = false) +public class SiteArticle extends SiteArticlePO { + public void update(SiteArticleCreateCommand cmd) { + Beans.copyPropertiesIgnoreNull(cmd, this); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/entity/SiteNews.java b/src/main/java/cn/stock/market/domain/basic/entity/SiteNews.java new file mode 100644 index 0000000..29ce9c9 --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/entity/SiteNews.java @@ -0,0 +1,28 @@ +package cn.stock.market.domain.basic.entity; + +import cn.qutaojing.common.utils.Beans; +import cn.stock.market.dto.command.SiteNewsCreateCommand; +import cn.stock.market.infrastructure.db.po.SiteNewsPO; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * SiteNews + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/19 + */ +@Data +@NoArgsConstructor +@SuperBuilder +@EqualsAndHashCode( + callSuper = false +) +public class SiteNews extends SiteNewsPO { + public void update(SiteNewsCreateCommand cmd) { + Beans.copyPropertiesIgnoreNull(cmd, this); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/entity/SiteSetting.java b/src/main/java/cn/stock/market/domain/basic/entity/SiteSetting.java new file mode 100644 index 0000000..b9f0d99 --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/entity/SiteSetting.java @@ -0,0 +1,51 @@ +package cn.stock.market.domain.basic.entity; + +import java.util.List; + +import org.apache.commons.lang.StringUtils; + +import com.ag.utils.Jsons; +import com.alibaba.fastjson.JSON; +import com.google.common.collect.Lists; + +import cn.qutaojing.common.utils.Beans; +import cn.stock.market.dto.command.StockCreateCommand; +import cn.stock.market.infrastructure.stockdb.po.SiteSettingPO; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * Stock + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Data +@NoArgsConstructor +@SuperBuilder +@EqualsAndHashCode(callSuper = false) +public class SiteSetting extends SiteSettingPO { + + public void update(StockCreateCommand cmd) { + Beans.copyPropertiesIgnoreNull(cmd, this); + } + + public boolean checkAndAddIfNoExists(String marketDomain) { + List list = Jsons.toListAnyway(getMarketServerList(), String.class); + + boolean contain = list.stream() + .filter(val -> StringUtils.startsWith(val, marketDomain)) + .count() > 0; + + if(! contain) { //改成覆盖 + list = Lists.newArrayList(); + list.add(marketDomain); + setMarketServerList(JSON.toJSONString(list)); + } + + return contain; + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/entity/Stock.java b/src/main/java/cn/stock/market/domain/basic/entity/Stock.java new file mode 100644 index 0000000..6c4cfa2 --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/entity/Stock.java @@ -0,0 +1,28 @@ +package cn.stock.market.domain.basic.entity; + +import cn.qutaojing.common.utils.Beans; +import cn.stock.market.dto.command.StockCreateCommand; +import cn.stock.market.infrastructure.stockdb.po.StockPO; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * Stock + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Data +@NoArgsConstructor +@SuperBuilder +@EqualsAndHashCode( + callSuper = false +) +public class Stock extends StockPO { + public void update(StockCreateCommand cmd) { + Beans.copyPropertiesIgnoreNull(cmd, this); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/entity/SysLog.java b/src/main/java/cn/stock/market/domain/basic/entity/SysLog.java new file mode 100644 index 0000000..dc52a5d --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/entity/SysLog.java @@ -0,0 +1,23 @@ +package cn.stock.market.domain.basic.entity; + +import cn.stock.market.infrastructure.db.po.SysLogPO; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * SysLogEntity + * + * @author xlfd + * @email xlfd@gmail.com + * @created 2021/06/18 + */ +@Data +@NoArgsConstructor +@SuperBuilder +@EqualsAndHashCode( + callSuper = false +) +public class SysLog extends SysLogPO { +} diff --git a/src/main/java/cn/stock/market/domain/basic/event/DomainEvent.java b/src/main/java/cn/stock/market/domain/basic/event/DomainEvent.java new file mode 100644 index 0000000..9ceed84 --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/event/DomainEvent.java @@ -0,0 +1,25 @@ +package cn.stock.market.domain.basic.event; + +import java.util.Date; +import java.util.UUID; + +import lombok.Data; +import lombok.experimental.SuperBuilder; + +@SuperBuilder +@Data +public class DomainEvent { + String id; + Date createAt; + + public DomainEvent() { + init(); + } + + @SuppressWarnings("unchecked") + public T init() { + this.id = String.valueOf(UUID.randomUUID()); + this.createAt = new Date(); + return (T) this; + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/factory/CityFactory.java b/src/main/java/cn/stock/market/domain/basic/factory/CityFactory.java new file mode 100644 index 0000000..259f693 --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/factory/CityFactory.java @@ -0,0 +1,20 @@ +package cn.stock.market.domain.basic.factory; + +import cn.qutaojing.common.utils.SpringUtils; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +/** + * CityFactory + * + * @author xlfd + * @email xlfd@gmail.com + * @created 2021/06/16 + */ +@Component +@Lazy +public class CityFactory { + public static CityFactory of() { + return SpringUtils.getBean(CityFactory.class); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/factory/JsonInfoFactory.java b/src/main/java/cn/stock/market/domain/basic/factory/JsonInfoFactory.java new file mode 100644 index 0000000..52e9374 --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/factory/JsonInfoFactory.java @@ -0,0 +1,29 @@ +package cn.stock.market.domain.basic.factory; + +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.JsonInfo; +import cn.stock.market.dto.command.JsonInfoCreateCommand; + +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +/** + * JsonInfoFactory + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2022/08/16 + */ +@Component +@Lazy +public class JsonInfoFactory { + public static JsonInfoFactory of() { + return SpringUtils.getBean(JsonInfoFactory.class); + } + + public JsonInfo from(JsonInfoCreateCommand cmd) { + JsonInfo e = JsonInfo.builder().build(); + e.update(cmd); + return e; + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/factory/LogBuilder.java b/src/main/java/cn/stock/market/domain/basic/factory/LogBuilder.java new file mode 100644 index 0000000..f73d843 --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/factory/LogBuilder.java @@ -0,0 +1,195 @@ +package cn.stock.market.domain.basic.factory; + +import org.apache.commons.lang.StringUtils; + +import com.alibaba.fastjson.JSONObject; + +import cn.qutaojing.common.OperInfo; +import cn.qutaojing.common.constant.RoleEnum; +import cn.stock.market.domain.basic.entity.SysLog; +import cn.stock.market.domain.basic.service.SysLogService; +import lombok.Data; + +@Data +public class LogBuilder { + public static LogBuilder builder() { + return new LogBuilder(); + } + + public static enum ActionTypeEnum { + INERT("INSERT", "新增"), + UPDATE("UPDATE", "更新"), + DELETE("DELETE", "删除"), + ENABLE("ENABLE", "启用"), + DISABLE("DISABLE", "禁用"), + RECORD("RECORD", "记录"), + ; + + String code; + String remark; + + ActionTypeEnum(String code, String remark) { + this.code = code; + this.remark = remark; + } + } + + public static enum ModuleEnum { + UNKNOWN("UNKNOWN", "未知"), + SYS_ROLE("SYS_ROLE", "系统角色"), + + ADMIN_LOGIN("ADMIN_LOGIN", "后台登录"), + DEVICE_MAINTAINER_LOGIN("DEVICE_MAINTAINER_LOGIN", "设备维护员登录"), + RIDER_LOGIN("RIDER_LOGIN", "骑手登录"), + ADMIN_LOGIN_RESET_PWD("ADMIN_LOGIN_RESET_PWD", "后台重置密码"), + ADMIN_LOGIN_CHANGE_PWD("ADMIN_LOGIN_CHANGE_PWD", "后台修改密码"), + SYS_MENU("SYS_MENU", "系统菜单"), + COUPONS_ALERT_STLYE("COUPONS_ALERT_STLYE", "优惠券弹窗"), + OTO_SALE_DEVILERY_FEE("OTO_SALE_DEVILERY_FEE", "运费补贴"), + SALE_STORE_FULL_REDUCTION("SALE_STORE_FULL_REDUCTION", "店铺满减"), + ; + + String code; + String remark; + + ModuleEnum(String code, String remark) { + this.code = code; + this.remark = remark; + } + + public String code() { + return code; + } + + public String remark() { + return remark; + } + + public static ModuleEnum of(String code) { + ModuleEnum[] values = ModuleEnum.values(); + for (ModuleEnum e : values) { + if(e.code.equalsIgnoreCase(code)) { + return e; + } + } + + return UNKNOWN; + } + } + ModuleEnum moduleEnum; + ActionTypeEnum actionTypeEnum; + RoleEnum re; + Integer storeId; + String operatorId; + String operatorName; + String operatorPhone; + String uniqueId; + String title; + String content; + JSONObject ext = new JSONObject(); + + public LogBuilder actionEnable(Object o) { + this.actionTypeEnum = ActionTypeEnum.ENABLE; + this.ext.put("obj", o); + return this; + } + public LogBuilder actionDisable(Object o) { + this.actionTypeEnum = ActionTypeEnum.DISABLE; + this.ext.put("obj", o); + return this; + } + + public LogBuilder actionInsert(Object o) { + this.actionTypeEnum = ActionTypeEnum.INERT; + this.ext.put("obj", o); + return this; + } + + public LogBuilder actionDelete(Object o) { + this.actionTypeEnum = ActionTypeEnum.DELETE; + this.ext.put("obj", o); + return this; + } + + public LogBuilder actionRecord(Object o) { + this.actionTypeEnum = ActionTypeEnum.RECORD; + this.ext.put("obj", o); + return this; + } + + public LogBuilder actionUpdate(Object pre, Object after) { + this.actionTypeEnum = ActionTypeEnum.UPDATE; + this.ext.put("pre", pre); + this.ext.put("after", after); + return this; + } + + public LogBuilder title(String title) { + this.title = title; + return this; + } + + public LogBuilder content(String content) { + this.content = content; + return this; + } + + public LogBuilder module(ModuleEnum moduleEnum) { + this.moduleEnum = moduleEnum; + return this; + } + + public LogBuilder operator(OperInfo operInfo) { + this.re = operInfo.getRe(); + return operator(operInfo.getOperatorId(), operInfo.getOperatorName(), operInfo.getOperatorPhone()); + } + + public LogBuilder operator(String operatorName, Object operatorId, String operatorPhone) { + this.operatorName = operatorName; + this.operatorId = String.valueOf(operatorId); + return this; + } + + public LogBuilder re(RoleEnum re) { + this.re = re; + return this; + } + + public LogBuilder uniqueId(Object uniqueId) { + this.uniqueId = String.valueOf(uniqueId); + return this; + } + + public LogBuilder storeId(Integer storeId) { + this.storeId = storeId; + return this; + } + + public void save() { + SysLogService.of().log(this); + } + + public SysLog build() { + String title = this.title; + if(StringUtils.isBlank(title)) { + title = actionTypeEnum.remark + moduleEnum.remark; + } + + return SysLog.builder() + .storeId(storeId) + .actionType(actionTypeEnum.code) + .content(content) + .ext(ext.toJSONString()) + .module(moduleEnum.code) + .operatorId(operatorId) + .operatorName(operatorName) + .roleType(re.code()) + .title(title) + .uniqueId(uniqueId) + .build(); + } + + public static LogBuilder of() { + return new LogBuilder(); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/factory/RealtimeFactory.java b/src/main/java/cn/stock/market/domain/basic/factory/RealtimeFactory.java new file mode 100644 index 0000000..1b4330e --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/factory/RealtimeFactory.java @@ -0,0 +1,28 @@ +package cn.stock.market.domain.basic.factory; + +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.Realtime; +import cn.stock.market.dto.command.RealtimeCreateCommand; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +/** + * RealtimeFactory + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Component +@Lazy +public class RealtimeFactory { + public static RealtimeFactory of() { + return SpringUtils.getBean(RealtimeFactory.class); + } + + public Realtime from(RealtimeCreateCommand cmd) { + Realtime e = Realtime.builder().build(); + e.update(cmd); + return e; + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/factory/SiteArticleFactory.java b/src/main/java/cn/stock/market/domain/basic/factory/SiteArticleFactory.java new file mode 100644 index 0000000..c76729f --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/factory/SiteArticleFactory.java @@ -0,0 +1,43 @@ +package cn.stock.market.domain.basic.factory; + +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.SiteArticle; +import cn.stock.market.dto.command.SiteArticleCreateCommand; + +import java.util.Date; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +import com.ag.exception.SysTipsException; + +/** + * SiteArticleFactory + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Component +@Lazy +public class SiteArticleFactory { + public static SiteArticleFactory of() { + return SpringUtils.getBean(SiteArticleFactory.class); + } + + public SiteArticle from(SiteArticleCreateCommand cmd) { + if (StringUtils.isBlank(cmd.getArtTitle()) || + StringUtils.isBlank(cmd.getArtType()) || + StringUtils.isBlank(cmd.getArtCnt()) || cmd + .getIsShow() == null) { + throw new SysTipsException("标题正文类型必填"); + } + + cmd.setAddTime(new Date()); + + SiteArticle e = SiteArticle.builder().build(); + e.update(cmd); + return e; + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/factory/SiteNewsFactory.java b/src/main/java/cn/stock/market/domain/basic/factory/SiteNewsFactory.java new file mode 100644 index 0000000..aa2ef24 --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/factory/SiteNewsFactory.java @@ -0,0 +1,28 @@ +package cn.stock.market.domain.basic.factory; + +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.SiteNews; +import cn.stock.market.dto.command.SiteNewsCreateCommand; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +/** + * SiteNewsFactory + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/19 + */ +@Component +@Lazy +public class SiteNewsFactory { + public static SiteNewsFactory of() { + return SpringUtils.getBean(SiteNewsFactory.class); + } + + public SiteNews from(SiteNewsCreateCommand cmd) { + SiteNews e = SiteNews.builder().build(); + e.update(cmd); + return e; + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/factory/StockFactory.java b/src/main/java/cn/stock/market/domain/basic/factory/StockFactory.java new file mode 100644 index 0000000..9bd9b19 --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/factory/StockFactory.java @@ -0,0 +1,28 @@ +package cn.stock.market.domain.basic.factory; + +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.Stock; +import cn.stock.market.dto.command.StockCreateCommand; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +/** + * StockFactory + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Component +@Lazy +public class StockFactory { + public static StockFactory of() { + return SpringUtils.getBean(StockFactory.class); + } + + public Stock from(StockCreateCommand cmd) { + Stock e = Stock.builder().build(); + e.update(cmd); + return e; + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/factory/SysLogFactory.java b/src/main/java/cn/stock/market/domain/basic/factory/SysLogFactory.java new file mode 100644 index 0000000..9e3159c --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/factory/SysLogFactory.java @@ -0,0 +1,20 @@ +package cn.stock.market.domain.basic.factory; + +import cn.qutaojing.common.utils.SpringUtils; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +/** + * SysLogFactory + * + * @author xlfd + * @email xlfd@gmail.com + * @created 2021/06/18 + */ +@Component +@Lazy +public class SysLogFactory { + public static SysLogFactory of() { + return SpringUtils.getBean(SysLogFactory.class); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/repository/CacheRepository.java b/src/main/java/cn/stock/market/domain/basic/repository/CacheRepository.java new file mode 100644 index 0000000..cddcf1d --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/repository/CacheRepository.java @@ -0,0 +1,135 @@ +package cn.stock.market.domain.basic.repository; + +import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import cn.qutaojing.common.utils.SpringUtils; + +public interface CacheRepository { + boolean set(final String key, Object value); + + /** + * 写入缓存设置时效时间 + * + * @param key + * @param value + * @param expireTime + * @return + */ + boolean set(final String key, Object value, long expireTime); + + boolean set(final String key, Object value, long expireTime, TimeUnit timeUnit); + + /** + * 批量删除对应的value + * + * @param keys + */ + void remove(final String... keys); + + /** + * 批量删除key + * + * @param pattern + */ + void removePattern(final String pattern); + + /** + * 删除对应的value + * + * @param key + */ + void remove(final String key); + + /** + * 判断缓存中是否有对应的value + * + * @param key + * @return + */ + boolean exists(final String key); + + /** + * 读取缓存 + * + * @param key + * @return + */ + Object get(final String key); + + /** + * 哈希 添加 + * + * @param key + * @param hashKey + * @param value + */ + void hmSet(String key, Object hashKey, Object value); + + /** + * 哈希获取数据 + * + * @param key + * @param hashKey + * @return + */ + Object hmGet(String key, Object hashKey); + + /** + * 列表添加 + * + * @param k + * @param v + */ + void lPush(String k, Object v); + + /** + * 列表获取 + * + * @param k + * @param l + * @param l1 + * @return + */ + List lRange(String k, long l, long l1); + + /** + * 集合添加 + * + * @param key + * @param value + */ + void add(String key, Object value); + + /** + * 集合获取 + * + * @param key + * @return + */ + Set setMembers(String key); + + /** + * 有序集合添加 + * + * @param key + * @param value + * @param scoure + */ + void zAdd(String key, Object value, double scoure); + + /** + * 有序集合获取 + * + * @param key + * @param scoure + * @param scoure1 + * @return + */ + Set rangeByScore(String key, double scoure, double scoure1); + + public static CacheRepository of() { + return SpringUtils.getBean(CacheRepository.class); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/repository/CityRepository.java b/src/main/java/cn/stock/market/domain/basic/repository/CityRepository.java new file mode 100644 index 0000000..7af148e --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/repository/CityRepository.java @@ -0,0 +1,67 @@ +package cn.stock.market.domain.basic.repository; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +import com.google.common.base.Joiner; +import com.google.common.collect.Lists; +import com.rp.spring.jpa.GenericJpaRepository; + +import cn.qutaojing.common.domain.convert.IEntityPOConvert; +import cn.qutaojing.common.domain.respostory.LocalCacheRepository; +import cn.qutaojing.common.utils.SpringUtils; +import cn.qutaojing.common.utils.TreePathUtils; +import cn.stock.market.domain.basic.convert.CityConvert; +import cn.stock.market.domain.basic.entity.City; +import cn.stock.market.infrastructure.db.po.CityPO; +import cn.stock.market.infrastructure.db.repo.CityRepo; +import lombok.RequiredArgsConstructor; + +/** + * CityRepository + * + * @author xlfd + * @email xlfd@gmail.com + * @created 2021/06/16 + */ +@Repository +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class CityRepository extends LocalCacheRepository { + final CityRepo repo; + + final CityConvert convert; + + @Override + public GenericJpaRepository repo() { + return repo; + } + + public String names(String path) { + return Joiner.on("/").join(names(TreePathUtils.splitAsInt(path))); + } + + public String[] names(Integer[] ids) { + List list = Lists.newArrayList(); + for (Integer id : ids) { + list.add(findCacheById(id)); + } + + String[] array = list.stream().map(val -> { + if (val == null) + return ""; + return val.getName(); + }).toArray(String[]::new); + return array; + } + + @Override + public IEntityPOConvert convert() { + return convert; + } + + public static CityRepository of() { + return SpringUtils.getBean(CityRepository.class); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/repository/JsonInfoRepository.java b/src/main/java/cn/stock/market/domain/basic/repository/JsonInfoRepository.java new file mode 100644 index 0000000..5daec0a --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/repository/JsonInfoRepository.java @@ -0,0 +1,44 @@ +package cn.stock.market.domain.basic.repository; + +import cn.qutaojing.common.domain.convert.IEntityPOConvert; +import cn.qutaojing.common.domain.respostory.SimplePoConvertEntityRepository; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.convert.JsonInfoConvert; +import cn.stock.market.domain.basic.entity.JsonInfo; +import cn.stock.market.infrastructure.db.po.JsonInfoPO; +import cn.stock.market.infrastructure.db.repo.JsonInfoRepo; + +import com.rp.spring.jpa.GenericJpaRepository; +import java.lang.Integer; +import java.lang.Override; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +/** + * JsonInfoRepository + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2022/08/16 + */ +@Repository +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class JsonInfoRepository extends SimplePoConvertEntityRepository { + final JsonInfoRepo repo; + final JsonInfoConvert convert; + + @Override + public GenericJpaRepository repo() { + return repo; + } + + @Override + public IEntityPOConvert convert() { + return convert; + } + + public static JsonInfoRepository of() { + return SpringUtils.getBean(JsonInfoRepository.class); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/repository/RealtimeRepository.java b/src/main/java/cn/stock/market/domain/basic/repository/RealtimeRepository.java new file mode 100644 index 0000000..a150256 --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/repository/RealtimeRepository.java @@ -0,0 +1,46 @@ +package cn.stock.market.domain.basic.repository; + +import cn.qutaojing.common.domain.convert.IEntityPOConvert; +import cn.qutaojing.common.domain.respostory.SimplePoConvertEntityRepository; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.convert.RealtimeConvert; +import cn.stock.market.domain.basic.entity.Realtime; +import cn.stock.market.infrastructure.db.po.RealtimePO; +import cn.stock.market.infrastructure.db.repo.RealtimeRepo; +import com.rp.spring.jpa.GenericJpaRepository; +import java.lang.Integer; +import java.lang.Override; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +/** + * RealtimeRepository + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Repository +@RequiredArgsConstructor( + onConstructor = @__(@Autowired) +) +public class RealtimeRepository extends SimplePoConvertEntityRepository { + final RealtimeRepo repo; + + final RealtimeConvert convert; + + @Override + public GenericJpaRepository repo() { + return repo; + } + + @Override + public IEntityPOConvert convert() { + return convert; + } + + public static RealtimeRepository of() { + return SpringUtils.getBean(RealtimeRepository.class); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/repository/SiteArticleRepository.java b/src/main/java/cn/stock/market/domain/basic/repository/SiteArticleRepository.java new file mode 100644 index 0000000..2cfbce5 --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/repository/SiteArticleRepository.java @@ -0,0 +1,46 @@ +package cn.stock.market.domain.basic.repository; + +import cn.qutaojing.common.domain.convert.IEntityPOConvert; +import cn.qutaojing.common.domain.respostory.SimplePoConvertEntityRepository; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.convert.SiteArticleConvert; +import cn.stock.market.domain.basic.entity.SiteArticle; +import cn.stock.market.infrastructure.db.po.SiteArticlePO; +import cn.stock.market.infrastructure.db.repo.SiteArticleRepo; +import com.rp.spring.jpa.GenericJpaRepository; +import java.lang.Integer; +import java.lang.Override; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +/** + * SiteArticleRepository + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Repository +@RequiredArgsConstructor( + onConstructor = @__(@Autowired) +) +public class SiteArticleRepository extends SimplePoConvertEntityRepository { + final SiteArticleRepo repo; + + final SiteArticleConvert convert; + + @Override + public GenericJpaRepository repo() { + return repo; + } + + @Override + public IEntityPOConvert convert() { + return convert; + } + + public static SiteArticleRepository of() { + return SpringUtils.getBean(SiteArticleRepository.class); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/repository/SiteNewsRepository.java b/src/main/java/cn/stock/market/domain/basic/repository/SiteNewsRepository.java new file mode 100644 index 0000000..c8e1ad6 --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/repository/SiteNewsRepository.java @@ -0,0 +1,55 @@ +package cn.stock.market.domain.basic.repository; + +import cn.qutaojing.common.domain.convert.IEntityPOConvert; +import cn.qutaojing.common.domain.respostory.SimplePoConvertEntityRepository; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.convert.SiteNewsConvert; +import cn.stock.market.domain.basic.entity.SiteNews; +import cn.stock.market.infrastructure.db.po.QSiteNewsPO; +import cn.stock.market.infrastructure.db.po.SiteNewsPO; +import cn.stock.market.infrastructure.db.repo.SiteNewsRepo; +import com.rp.spring.jpa.GenericJpaRepository; +import java.lang.Integer; +import java.lang.Override; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +/** + * SiteNewsRepository + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/19 + */ +@Repository +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class SiteNewsRepository extends SimplePoConvertEntityRepository { + final SiteNewsRepo repo; + final SiteNewsConvert convert; + static final QSiteNewsPO q = QSiteNewsPO.siteNewsPO; + + public long getNewsBySourceIdCount(String newsId) { + return count(q.sourceId.eq(newsId)); + } + @Override + public GenericJpaRepository repo() { + return repo; + } + + @Override + public IEntityPOConvert convert() { + return convert; + } + + public static SiteNewsRepository of() { + return SpringUtils.getBean(SiteNewsRepository.class); + } + + public long updateViews(Integer id) { + return getJPAQueryFactory() + .update(q) + .set(q.views, q.views.add(1)) + .where(q.id.eq(id)).execute(); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/repository/SiteSettingRepository.java b/src/main/java/cn/stock/market/domain/basic/repository/SiteSettingRepository.java new file mode 100644 index 0000000..fa455d8 --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/repository/SiteSettingRepository.java @@ -0,0 +1,50 @@ +package cn.stock.market.domain.basic.repository; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +import com.rp.spring.jpa.GenericJpaRepository; + +import cn.qutaojing.common.domain.convert.IEntityPOConvert; +import cn.qutaojing.common.domain.respostory.LocalCacheRepository; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.convert.SiteSettingConvert; +import cn.stock.market.domain.basic.entity.SiteSetting; +import cn.stock.market.infrastructure.stockdb.po.SiteSettingPO; +import cn.stock.market.infrastructure.stockdb.repo.SiteSettingRepo; +import lombok.RequiredArgsConstructor; + +/** + * StockRepository + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Repository +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class SiteSettingRepository extends LocalCacheRepository { + final SiteSettingRepo repo; + final SiteSettingConvert convert; + + public static SiteSettingRepository of() { + return SpringUtils.getBean(SiteSettingRepository.class); + } + + public SiteSetting get() { + return findAll() + .stream() + .findAny() + .orElse(null); + } + + @Override + public GenericJpaRepository repo() { + return repo; + } + + @Override + public IEntityPOConvert convert() { + return convert; + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/repository/StockRepository.java b/src/main/java/cn/stock/market/domain/basic/repository/StockRepository.java new file mode 100644 index 0000000..6eb589e --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/repository/StockRepository.java @@ -0,0 +1,143 @@ +package cn.stock.market.domain.basic.repository; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Repository; + +import com.google.common.cache.CacheBuilder; +import com.rp.spring.jpa.GenericJpaRepository; + +import cn.qutaojing.common.domain.convert.IEntityPOConvert; +import cn.qutaojing.common.domain.respostory.LocalCacheBean; +import cn.qutaojing.common.domain.respostory.LocalCacheRepository; +import cn.qutaojing.common.jpa.ConditionBuilder; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.convert.StockConvert; +import cn.stock.market.domain.basic.entity.Stock; +import cn.stock.market.infrastructure.stockdb.po.QStockPO; +import cn.stock.market.infrastructure.stockdb.po.StockPO; +import cn.stock.market.infrastructure.stockdb.repo.StockRepo; +import lombok.RequiredArgsConstructor; + +/** + * StockRepository + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Repository +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class StockRepository extends LocalCacheRepository { + final StockRepo repo; + final StockConvert convert; + final static QStockPO q = QStockPO.stockPO; + + @Override + protected LocalCacheBean buildLocalCache() { + /** + * 缓存10分钟 + */ + return new LocalCacheBean<>(repo(), val -> repo().findAll(), CacheBuilder.newBuilder().maximumSize(2000000).expireAfterWrite(10 * 60, TimeUnit.SECONDS)); + } + + public Map cacheCodeMap() { + Map map = cacheList() + .stream().collect(Collectors.toMap(Stock::getStockCode, val -> val, (u, v) -> u)); + + return map; + } + + public Map cacheNameMap() { + Map map = cacheList() + .stream().collect(Collectors.toMap(Stock::getStockName, val -> val, (u, v) -> u)); + + return map; + } + public Page listByAdmin(Integer showState, Integer lockState, String code, String name, String stockPlate, + String stockType, Pageable pageable) { + ConditionBuilder builder = ConditionBuilder.builder(); + if(showState != null) { + builder.and(q.isShow.eq(showState)); + } + if(lockState != null) { + builder.and(q.isLock.eq(lockState)); + } + + if(StringUtils.isNotBlank(code)) { + builder.and(q.stockCode.like("%" + code + "%")); + } + + if(StringUtils.isNotBlank(name)) { + builder.and(q.stockName.like("%" + name + "%")); + } + + if(StringUtils.isNotBlank(stockPlate)) { + builder.and(q.stockPlate.eq(stockPlate)); + } + if(StringUtils.isNotBlank(stockType)) { + builder.and(q.stockType.eq(stockType)); + } + + return findAll(builder.build(), pageable); + } + + public Page findStockListByKeyWords(String keyWords, String stockPlate,String stockType, Integer isShow, Pageable pageable) { + ConditionBuilder builder = ConditionBuilder.builder(); + if(isShow != null) { + builder.and(q.isShow.eq(isShow)); + } + + if(StringUtils.isNotBlank(keyWords)) { + builder.and(q.stockCode.like("%" + keyWords + "%").or(q.stockSpell.like("%" + keyWords + "%"))); + } + + if(StringUtils.isNotBlank(stockPlate)) { + builder.and(q.stockPlate.isNull().or(q.stockPlate.eq("").or(q.stockPlate.eq("科创").or(q.stockPlate.eq("创业"))))); + } + + if(StringUtils.isNotBlank(stockType)) { + builder.and(q.stockType.eq(stockType)); + } + + return findAll(builder.build(), pageable); + } + + public List findStockCode(String stockType, Integer start, Integer count) { + List list = getJPAQueryFactory() + .select(q) + .where(q.stockType.eq(stockType)) + .fetch(); + + return transform(list); + } + + public Stock findStockByCode(String code) { + return findOneIfMutil(q.stockCode.eq(code)); + } + + public Stock findStockByName(String name) { + return findOneIfMutil(q.stockName.eq(name)); + } + + @Override + public GenericJpaRepository repo() { + return repo; + } + + @Override + public IEntityPOConvert convert() { + return convert; + } + + public static StockRepository of() { + return SpringUtils.getBean(StockRepository.class); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/repository/SysLogRepository.java b/src/main/java/cn/stock/market/domain/basic/repository/SysLogRepository.java new file mode 100644 index 0000000..30b56cd --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/repository/SysLogRepository.java @@ -0,0 +1,41 @@ +package cn.stock.market.domain.basic.repository; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +import com.rp.spring.jpa.GenericJpaRepository; + +import cn.qutaojing.common.domain.convert.IEntityPOConvert; +import cn.qutaojing.common.domain.respostory.SimplePoConvertEntityRepository; +import cn.stock.market.domain.basic.convert.SysLogConvert; +import cn.stock.market.domain.basic.entity.SysLog; +import cn.stock.market.infrastructure.db.po.SysLogPO; +import cn.stock.market.infrastructure.db.repo.SysLogRepo; +import lombok.RequiredArgsConstructor; + +/** + * SysLogRepository + * + * @author xlfd + * @email xlfd@gmail.com + * @created 2021/06/18 + */ +@Repository +@RequiredArgsConstructor( + onConstructor = @__(@Autowired) +) +public class SysLogRepository extends SimplePoConvertEntityRepository { + final SysLogRepo repo; + + final SysLogConvert convert; + + @Override + public GenericJpaRepository repo() { + return repo; + } + + @Override + public IEntityPOConvert convert() { + return convert; + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/service/CityService.java b/src/main/java/cn/stock/market/domain/basic/service/CityService.java new file mode 100644 index 0000000..f48c94c --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/service/CityService.java @@ -0,0 +1,36 @@ +package cn.stock.market.domain.basic.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.City; +import cn.stock.market.domain.basic.factory.CityFactory; +import cn.stock.market.domain.basic.repository.CityRepository; +import lombok.RequiredArgsConstructor; + +/** + * CityService + * + * @author xlfd + * @email xlfd@gmail.com + * @created 2021/06/16 + */ +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class CityService { + final CityRepository repository; + final CityFactory factory; + + public City findById(Integer id) { + return repository.findCacheById(id); + } + + public CityRepository repository() { + return repository; + } + + public static CityService of() { + return SpringUtils.getBean(CityService.class); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/service/JsonInfoService.java b/src/main/java/cn/stock/market/domain/basic/service/JsonInfoService.java new file mode 100644 index 0000000..4465c4b --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/service/JsonInfoService.java @@ -0,0 +1,40 @@ +package cn.stock.market.domain.basic.service; + +import cn.qutaojing.common.enhance.validator.ValidationFacade; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.JsonInfo; +import cn.stock.market.domain.basic.factory.JsonInfoFactory; +import cn.stock.market.domain.basic.repository.JsonInfoRepository; +import cn.stock.market.dto.command.JsonInfoCreateCommand; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * JsonInfoService + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2022/08/16 + */ +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class JsonInfoService { + final JsonInfoRepository repository; + final JsonInfoFactory factory; + + public JsonInfo create(JsonInfoCreateCommand cmd) { + ValidationFacade.of().validate(cmd); + JsonInfo from = factory.from(cmd); + repository.save(from); + return from; + } + + public JsonInfoRepository repository() { + return repository; + } + + public static JsonInfoService of() { + return SpringUtils.getBean(JsonInfoService.class); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/service/RealtimeService.java b/src/main/java/cn/stock/market/domain/basic/service/RealtimeService.java new file mode 100644 index 0000000..8a35d8c --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/service/RealtimeService.java @@ -0,0 +1,74 @@ +package cn.stock.market.domain.basic.service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.Realtime; +import cn.stock.market.domain.basic.factory.RealtimeFactory; +import cn.stock.market.domain.basic.repository.RealtimeRepository; +import cn.stock.market.infrastructure.db.po.QRealtimePO; +import cn.stock.market.utils.Utils; +import lombok.RequiredArgsConstructor; + +/** + * RealtimeService + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class RealtimeService { + final RealtimeRepository repository; + final RealtimeFactory factory; + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public Map findStock(String stockCode) { + List list = repository.findAll(QRealtimePO.realtimePO.stockCode.eq(Utils.jys(stockCode))); + Map map = new HashMap<>(); + List price = new ArrayList(); + List averagePrice = new ArrayList(); + List rates = new ArrayList(); + List time = new ArrayList(); + List volumes = new ArrayList(); + List amounts = new ArrayList(); + map.put("stockCode", stockCode); + map.put("size", Integer.valueOf(list.size())); + for (Realtime realTime : list) { + double p = realTime.getPrice(); + price.add(Double.valueOf(p)); + /*double avg = realTime.getAveragePrice(); + averagePrice.add(Double.valueOf(avg));*/ + double r = realTime.getRates(); + rates.add(Double.valueOf(r)); + String t = realTime.getTime(); + time.add(t); + int v = realTime.getVolumes(); + volumes.add(Integer.valueOf(v)); + int a = realTime.getAmounts(); + amounts.add(Integer.valueOf(a)); + } + map.put("time", time); + map.put("volumes", volumes); + map.put("price", price); + map.put("averagePrice", averagePrice); + map.put("rates", rates); + map.put("amounts", amounts); + return map; + } + + public RealtimeRepository repository() { + return repository; + } + + public static RealtimeService of() { + return SpringUtils.getBean(RealtimeService.class); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/service/SiteArticleService.java b/src/main/java/cn/stock/market/domain/basic/service/SiteArticleService.java new file mode 100644 index 0000000..b18752d --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/service/SiteArticleService.java @@ -0,0 +1,176 @@ +package cn.stock.market.domain.basic.service; + +import java.util.Date; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.stereotype.Service; + +import cn.qutaojing.common.PageParam; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.SiteArticle; +import cn.stock.market.domain.basic.factory.SiteArticleFactory; +import cn.stock.market.domain.basic.repository.SiteArticleRepository; +import cn.stock.market.dto.command.SiteArticleCreateCommand; +import cn.stock.market.dto.query.SiteArticleQuery; +import cn.stock.market.infrastructure.db.po.QSiteArticlePO; +import cn.stock.market.utils.DateTimeUtil; +import cn.stock.market.utils.HttpRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.sf.json.JSONObject; + +/** + * SiteArticleService + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Slf4j +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class SiteArticleService { + final SiteArticleRepository repository; + final SiteArticleFactory factory; + + public Page listByAdmin(String artTitle, String artType, int pageNum, int pageSize) { + SiteArticleQuery query = new SiteArticleQuery(); + query.setArtTitle(artTitle); + query.setArtType(artType); + return repository.findAll(query.where(), PageParam.of(pageNum, pageSize)); + } + + + public SiteArticle add(SiteArticleCreateCommand cmd) { + SiteArticle siteArticle = factory.from(cmd); + repository.saveAndFlush(siteArticle); + return siteArticle; + } + +// public ServerResponse update(SiteArticle siteArticle) { +// if (siteArticle.getId() == null) { +// return ServerResponse.createByErrorMsg("修改id必传"); +// } +// int updateCount = this.siteArticleMapper.updateByPrimaryKeySelective(siteArticle); +// if (updateCount > 0) { +// return ServerResponse.createBySuccessMsg("修改成功"); +// } +// return ServerResponse.createByErrorMsg("修改失败"); +// } + + public Page list(String artTitle, String artType, int pageNum, int pageSize) { + //is_show + SiteArticleQuery query = new SiteArticleQuery(); + query.setIsShow(0); + query.setArtTitle(artTitle); + query.setArtType(artType); + return repository.findAll(query.where(), PageParam.of(pageNum, pageSize)); + } + + /*top最新公告*/ + public List getTopArtList(int pageSize){ + SiteArticleQuery query = new SiteArticleQuery(); + query.setIsShow(0); + + return repository.findAll(query.where(), pageSize, QSiteArticlePO.siteArticlePO.id.desc()); + } + + public long getArtBySourceIdCount(String newsId) { + return repository.count(QSiteArticlePO.siteArticlePO.sourceId.eq(newsId)); + } + + /*公告-抓取*/ + public int grabArticle() { + int ret = 0; + try { + Date date = DateTimeUtil.addDay(new Date(),2); + String time = DateTimeUtil.dateToStr(date,"yyyy-MM-dd HH:mm:ss"); + String smap = DateTimeUtil.dateToStamp(time); + String url = "http://eminfo.eastmoney.com/pc_news/Notice/GetNoticeList?uid=&columnType=002&securityType=100&pageNumber=1&pageSize=50&startTime=1589904000000&endTime="+ smap +"&securityCodeMarket=&searchType=001&searchCondition=&fundIdList=&isfund="; + String newlist = HttpRequest.doGrabGet(url); + JSONObject data = JSONObject.fromObject(newlist); + JSONObject json = JSONObject.fromObject(data.get("data")); + if(json != null && json.getJSONArray("items") != null && json.getJSONArray("items").size() > 0){ + for (int i = 0; i < json.getJSONArray("items").size(); i++){ + JSONObject model = JSONObject.fromObject(json.getJSONArray("items").getString(i)); + String newsId = model.getString("infoCode"); + + //新闻不存在则添加 + if(getArtBySourceIdCount(newsId) == 0){ + //获取新闻详情 + String newdata = HttpRequest.doGrabGet("https://np-cnotice-pc.eastmoney.com/api/content/ann/rich?client_source=pc&page_index=1&is_rich=1&req_trace=&art_code="+ newsId); + + JSONObject jsonnew = JSONObject.fromObject(newdata); + if(jsonnew != null && jsonnew.get("data") != null){ + JSONObject news = JSONObject.fromObject(jsonnew.get("data")); + SiteArticle siteArticle = new SiteArticle(); + siteArticle.setSourceId(newsId); + siteArticle.setAuthor(news.getString("short_name")); + siteArticle.setArtTitle(news.getString("notice_title")); + siteArticle.setAddTime(DateTimeUtil.getCurrentDate()); + siteArticle.setArtSummary(news.getString("notice_title")); + String content = news.getString("notice_content"); + siteArticle.setIsShow(0); + siteArticle.setViews(10); + siteArticle.setArtType(news.getString("short_name")); + if(!content.contains("{") && !content.contains("}")){ + siteArticle.setArtCnt(content); + try { + repository.saveAndFlush(siteArticle); + } catch(Exception e) { + log.warn("siteArticleMapper insert error: {}", e.getLocalizedMessage()); + } + ret++; + } else if (content.contains("{") && content.contains("pages")){ + JSONObject pagelist = JSONObject.fromObject(news.get("notice_content")); + String contStr = ""; + if(pagelist != null && pagelist.getJSONArray("pages") != null && pagelist.getJSONArray("pages").size() > 0){ + for (int k=0;k 0){ + for (int r=0;r getList(int pageNum, int pageSize, Integer type, String sort, String keyword, HttpServletRequest request){ + SiteNewsQuery query = new SiteNewsQuery(); + query.setStatus(1); + query.setType(type); + query.setOrderSpecifier(sort); + query.setKeyword(keyword); + Page page = repository.findAll(query.where(), PageParam.of(pageNum, pageSize), query.orderSpecifier()); + + return ServerResponse.createBySuccess(Utils.toPageHelperInfo(page)); + } + + /*新闻资讯-查询详情*/ + public ServerResponse getDetail(int id) { + return ServerResponse.createBySuccess(repository.find(id)); + } + + /*新闻资讯-修改新闻浏览量*/ + public ServerResponse updateViews(Integer id) { + return ServerResponse.createBySuccess(repository.updateViews(id)); + } + + /*新闻资讯-top最新新闻资讯*/ + public ServerResponse getTopNewsList(int pageSize){ + SiteNewsQuery query = new SiteNewsQuery(); + query.setStatus(1); + + List list = repository.findAll(query.where(), pageSize, query.orderSpecifier()); + + PageInfo pageInfo = new PageInfo(); + pageInfo.setList(list); + return ServerResponse.createBySuccess(pageInfo); + } + + /*新闻资讯-抓取*/ + public int grabNews() { + int ret = 0; + //新闻类型:1、财经要闻,2、经济数据,3、全球股市,4、7*24全球,5、商品资讯,6、上市公司,7、全球央行 + ret = addNews(1, PropertiesUtil.getProperty("news.main.url") + "/pc_news/FastNews/GetImportantNewsList"); + log.info("财经要闻-抓取条数:" + ret); + + ret = addNews(2, PropertiesUtil.getProperty("news.main.url") + "/pc_news/FastNews/GetInfoList?code=125&pageNumber=1&pagesize=20&condition=&r="); + log.info("经济数据-抓取条数:" + ret); + + ret = addNews(3, PropertiesUtil.getProperty("news.main.url") + "/pc_news/FastNews/GetInfoList?code=105&pageNumber=1&pagesize=20&condition=&r="); + log.info("全球股市-抓取条数:" + ret); + + ret = addNews(4, PropertiesUtil.getProperty("news.main.url") + "/pc_news/FastNews/GetInfoList?code=100&pageNumber=1&pagesize=20&condition=&r="); + log.info("7*24全球-抓取条数:" + ret); + + ret = addNews(5, PropertiesUtil.getProperty("news.main.url") + "/pc_news/FastNews/GetInfoList?code=106&pageNumber=1&pagesize=20&condition=&r="); + log.info("商品资讯-抓取条数:" + ret); + + ret = addNews(6, PropertiesUtil.getProperty("news.main.url") + "/pc_news/FastNews/GetInfoList?code=103&pageNumber=1&pagesize=20&condition=&r="); + log.info("上市公司-抓取条数:" + ret); + + ret = addNews(7, PropertiesUtil.getProperty("news.main.url") + "/pc_news/FastNews/GetInfoList?code=118&pageNumber=1&pagesize=20&condition=&r="); + log.info("全球央行-抓取条数:" + ret); + + return ret; + } + + /* + *抓取新闻专用 + * type:新闻类型:1、财经要闻,2、经济数据,3、全球股市,4、7*24全球,5、商品资讯,6、上市公司,7、全球央行 + * */ + private int addNews(Integer type, String url){ + int k = 0; + try { + String newlist = HttpRequest.doGrabGet(url); + JSONObject json = JSONObject.fromObject(newlist); + if(json != null && json.getJSONArray("items") != null && json.getJSONArray("items").size() > 0){ + for (int i = 0; i < json.getJSONArray("items").size(); i++){ + JSONObject model = JSONObject.fromObject(json.getJSONArray("items").getString(i)); + String newsId = model.getString("code"); + String imgUrl = null; + if(model.has("imgUrl")){ + imgUrl = model.getString("imgUrl"); + } + //新闻不存在则添加 + if(repository.getNewsBySourceIdCount(newsId) == 0){ + //获取新闻详情 + String newdata = HttpRequest.doGrabGet(PropertiesUtil.getProperty("news.main.url") + "/PC_News/Detail/GetDetailContent?id="+ newsId +"&type=1"); + newdata = newdata.substring(1,newdata.length()-1).replace("\\\\\\\"","\""); + newdata = newdata.replace("\\\"","\""); + newdata = StringUtils.UnicodeToCN(newdata); + newdata = StringUtils.delHTMLTag(newdata); + + JSONObject jsonnew = JSONObject.fromObject(newdata); + if(jsonnew != null && jsonnew.get("data") != null){ + JSONObject news = JSONObject.fromObject(jsonnew.get("data")); + SiteNews siteNews = new SiteNews(); + siteNews.setSourceId(newsId); + siteNews.setSourceName(news.getString("source")); + siteNews.setTitle(news.getString("title")); + String showTime = news.getString("showTime"); + siteNews.setShowTime(DateTimeUtil.strToDate(showTime)); + siteNews.setImgurl(imgUrl); + siteNews.setDescription(news.getString("description")); + siteNews.setContent(news.getString("content")); + siteNews.setStatus(1); + siteNews.setType(type); + try { + repository.saveAndFlush(siteNews); + } catch(Exception e) { + log.warn("siteNewsMapper insert error: {}", e.getLocalizedMessage()); + } + k++; + } + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return k; + } + + public SiteNewsRepository repository() { + return repository; + } + + public static SiteNewsService of() { + return SpringUtils.getBean(SiteNewsService.class); + } +} diff --git a/src/main/java/cn/stock/market/domain/basic/service/StockService.java b/src/main/java/cn/stock/market/domain/basic/service/StockService.java new file mode 100644 index 0000000..3e66650 --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/service/StockService.java @@ -0,0 +1,628 @@ +package cn.stock.market.domain.basic.service; + +import java.math.BigDecimal; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Objects; + +import javax.persistence.EntityExistsException; +import javax.servlet.http.HttpServletRequest; + +import cn.stock.market.dto.model.HKStockNewInfo; +import cn.stock.market.infrastructure.api.sina.vo.HotSearchVO; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import org.apache.commons.lang3.StringUtils; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.select.Elements; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import com.ag.exception.EntityNotFoundException; +import com.ag.exception.SysTipsException; +import com.github.pagehelper.PageInfo; +import com.google.common.collect.Lists; + +import cn.qutaojing.common.PageParam; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.Stock; +import cn.stock.market.domain.basic.factory.StockFactory; +import cn.stock.market.domain.basic.repository.StockRepository; +import cn.stock.market.dto.model.StockAdminListVO; +import cn.stock.market.dto.model.StockListVO; +import cn.stock.market.dto.model.StockVO; +import cn.stock.market.infrastructure.api.qq.QqStockApi; +import cn.stock.market.infrastructure.api.sina.SinaStockApi; +import cn.stock.market.infrastructure.api.sina.vo.MarketVO; +import cn.stock.market.infrastructure.api.sina.vo.MarketVOResult; +import cn.stock.market.infrastructure.api.sina.vo.k.MinDataVO; +import cn.stock.market.infrastructure.api.sina.vo.k.echarts.EchartsDataVO; +import cn.stock.market.infrastructure.stockdb.po.QStockPO; +import cn.stock.market.utils.GetPyByChinese; +import cn.stock.market.utils.HttpClientRequest; +import cn.stock.market.utils.PropertiesUtil; +import cn.stock.market.utils.ServerResponse; +import cn.stock.market.utils.Utils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.client.RestTemplate; + +/** + * StockService + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Slf4j +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class StockService { + final StockRepository repository; + final StockFactory factory; + final RestTemplate restTemplate; + + public ServerResponse getMarket() { + String market_url = "https://hq.sinajs.cn/rn=1520407404627&list=s_sh000001,s_sz399001,s_sz399006,s_sz399300,s_sz399005,s_sz399673,s_sz399106,s_sz399004,s_sz399100"; + String result = null; + try { + result = HttpClientRequest.doGet(market_url); + } catch (Exception e) { + log.error("e = {}", e); + } + String[] marketArray = result.split(";"); + List marketVOS = Lists.newArrayList(); + for (int i = 0; i < marketArray.length; i++) { + String hqstr = marketArray[i]; + try { + if (StringUtils.isNotBlank(hqstr)) { + hqstr = hqstr.substring(hqstr.indexOf("\"") + 1, hqstr.lastIndexOf("\"")); + MarketVO marketVO = new MarketVO(); + String[] sh01_arr = hqstr.split(","); + marketVO.setName(sh01_arr[0]); + marketVO.setNowPrice(sh01_arr[1]); + marketVO.setIncrease(sh01_arr[2]); + marketVO.setIncreaseRate(sh01_arr[3]); + marketVOS.add(marketVO); + } + } catch (Exception e) { + log.error("str = {} , e = {}", hqstr, e); + } + } + MarketVOResult marketVOResult = new MarketVOResult(); + marketVOResult.setMarket(marketVOS); + return ServerResponse.createBySuccess(marketVOResult); + } + + public ServerResponse getHotSearch() { + String market_url = "https://finance.sina.com.cn/hq/analysis/pc_hot_search.js"; + String result = null; + try { + result = HttpClientRequest.doGet(market_url); + } catch (Exception e) { + log.error("e = {}", e); + } + JSONArray json = JSONArray.parseArray(result.replace("var hot_a_stock=", "")); + List hotSearchVOS = Lists.newArrayList(); + for (int i = 0; i < json.size(); i++) { + JSONObject hot = json.getJSONObject(i); + HotSearchVO hotSearchVO = new HotSearchVO(); + hotSearchVO.setSymbol(hot.getString("symbol")); + hotSearchVO.setWeight(hot.getInteger("weight")); + Stock stock = repository.cacheCodeMap().get(hotSearchVO.getSymbol().substring(2)); + if (Objects.isNull(stock)) { + continue; + } + hotSearchVO.setCode(stock.getStockCode()); + hotSearchVO.setName(stock.getStockName()); + hotSearchVOS.add(hotSearchVO); + } + return ServerResponse.createBySuccess(hotSearchVOS); + } + + + public ServerResponse getNorthIn() { + String market_url = "https://datacenter-web.eastmoney.com/api/data/v1/get?callback=jQuery112305686722141887519_1700033208129&reportName=RPT_MUTUAL_QUOTA&columns=TRADE_DATE,MUTUAL_TYPE,BOARD_TYPE,MUTUAL_TYPE_NAME,FUNDS_DIRECTION,INDEX_CODE,INDEX_NAME,BOARD_CODE"eColumns=status~07~BOARD_CODE,dayNetAmtIn~07~BOARD_CODE,dayAmtRemain~07~BOARD_CODE,dayAmtThreshold~07~BOARD_CODE,f104~07~BOARD_CODE,f105~07~BOARD_CODE,f106~07~BOARD_CODE,f3~03~INDEX_CODE~INDEX_f3,netBuyAmt~07~BOARD_CODE"eType=0&pageNumber=1&pageSize=200&sortTypes=1&sortColumns=MUTUAL_TYPE&source=WEB&client=WEB&_="+System.currentTimeMillis(); + String result = null; + try { + result = HttpClientRequest.doGet(market_url); + } catch (Exception e) { + log.error("e = {}", e); + } + result = result.replace("jQuery112305686722141887519_1700033208129(",""); + result = result.substring(0,result.length()-2); + JSONObject json = JSONObject.parseObject(result); + Integer code = json.getInteger("code"); + if (code == 0) { + BigDecimal ret = BigDecimal.ZERO; + JSONArray dataAry = json.getJSONObject("result").getJSONArray("data"); + for (int i = 0; i < dataAry.size(); i++) { + JSONObject data = dataAry.getJSONObject(i); + String fundsDirection = data.getString("FUNDS_DIRECTION"); + if ("北向".equals(fundsDirection)){ + ret = ret.add(data.getBigDecimal("netBuyAmt")); + } + } + return ServerResponse.createBySuccess(ret); + } + return ServerResponse.createByErrorMsg("查不到数据"); + } + + public ServerResponse getMainIn() { + String url = "https://push2his.eastmoney.com/api/qt/stock/fflow/daykline/get?cb=jQuery1123044920609862794136_1700037243016&lmt=0&klt=101&fields1=f1,f2,f3,f7&fields2=f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61,f62,f63,f64,f65&ut=b2884a393a59ad64002292a3e90d46a5&secid=1.000001&secid2=0.399001&_="+System.currentTimeMillis(); + String result = null; + try { + result = HttpClientRequest.doGet(url); + } catch (Exception e) { + log.error("e = {}", e); + } + result = result.replace("jQuery1123044920609862794136_1700037243016(",""); + result = result.substring(0,result.length()-2); + JSONObject json = JSONObject.parseObject(result); + JSONObject data = json.getJSONObject("data"); + if (Objects.nonNull(data)){ + JSONArray klines = data.getJSONArray("klines"); + if (Objects.nonNull(klines) && !klines.isEmpty()){ + String last = klines.getString(klines.size()-1); + String[] arry = last.split(","); + return ServerResponse.createBySuccess(arry[1]); + } + } + return ServerResponse.createByErrorMsg("查不到数据"); + } + + public ServerResponse getMarketByStockGid(String stockGid) { + String market_url = "https://qt.gtimg.cn/?q=marketStat,stockcode,usDJI,r_hkHSI"; + + String result = null; + try { + market_url = market_url.replace("stockcode", stockGid); + //SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + //System.out.print("指数请求开始,时间:"+sdf.format(new Date())+",market_url:"+market_url + "\n"); + + result = HttpClientRequest.doGet(market_url); + //System.out.print("指数请求结束,时间:"+sdf.format(new Date())+",result:"+result + "\n"); + } catch (Exception e) { + log.error("获取 大盘指数 出错 e = {}", e); + } + MarketVO marketVO = null; + if (!StringUtils.contains(result, "=")) { + log.info("将使用行情模块兜底: {}", stockGid); + try { + result = HttpClientRequest.doGet(market_url); + marketVO = JSONObject.parseObject(result, MarketVO.class); + log.info("兜底返回信息: {}", result); + } catch (Exception e2) { + log.info("将使用行情{}模块兜底错误...", stockGid, e2); + } + return ServerResponse.createBySuccess(marketVO); + } + + try { + if (StringUtils.isNotBlank(result)) { + result = result.substring(result.indexOf("\"") + 1, result.lastIndexOf("\"")); + + marketVO = new MarketVO(); + if (result.contains(";")) { + String[] indexAry = result.split(";"); + if (indexAry.length > 1) { + String[] sh01_arr = indexAry[1].split("~"); + marketVO.setName(sh01_arr[1]); + marketVO.setMaxHigh(sh01_arr[33]); + marketVO.setMinLow(sh01_arr[34]); + marketVO.setNowPrice(sh01_arr[3]); + marketVO.setOpenPrice(sh01_arr[5]); + marketVO.setClosePrice(sh01_arr[4]); + marketVO.setIncrease(sh01_arr[31]); + marketVO.setIncreaseRate(sh01_arr[32]); + + String[] turnAry = sh01_arr[35].split("/"); + marketVO.setTurnOver(turnAry[1]); + marketVO.setTurnNum(turnAry[2]); + } + + } + } + } catch (Exception e) { + log.error("转换大盘指数出错 str = {} , e = {}", result, e); + } + + return ServerResponse.createBySuccess(marketVO); + } + + public ServerResponse getStock(int pageNum, int pageSize, String keyWords, String stockPlate, String stockType, + HttpServletRequest request) { + Page page = repository.findStockListByKeyWords(keyWords, stockPlate, stockType, 0, PageParam.of(pageNum, pageSize)); + List stockListVOS = Lists.newArrayList(); + if (page.getContent().size() > 0) + for (Stock stock : page.getContent()) { + StockListVO stockListVO = SinaStockApi + .assembleStockListVO(SinaStockApi.getSinaStock(stock.getStockGid())); + stockListVO.setCode(stock.getStockCode()); + stockListVO.setSpell(stock.getStockSpell()); + stockListVO.setGid(stock.getStockGid()); +// BigDecimal day3Rate = (BigDecimal) selectRateByDaysAndStockCode(stock.getStockCode(), 3).getData(); + BigDecimal day3Rate = BigDecimal.ZERO; + stockListVO.setDay3Rate(day3Rate); + stockListVO.setStock_plate(stock.getStockPlate()); + stockListVO.setStock_type(stock.getStockType()); + // 是否添加自选 //TODO: +// if (user == null) { + stockListVO.setIsOption("0"); +// } else { +// stockListVO.setIsOption(iStockOptionService.isMyOption(user.getId(), stock.getStockCode())); +// } + stockListVOS.add(stockListVO); + } + + com.github.pagehelper.PageInfo pageInfo = Utils.toPageHelperInfo(page); + pageInfo.setList(stockListVOS); + return ServerResponse.createBySuccess(pageInfo); + } + + public ServerResponse getSingleStock(String code) { + if (StringUtils.isBlank(code)) + return ServerResponse.createByErrorMsg(""); + Stock stock = new Stock(); + Integer depositAmt = 0; + // 期货 +// if (code.contains("hf")) { +// StockFutures futmodel = stockFuturesMapper.selectFuturesByCode(code.replace("hf_", "")); +// stock.setStockGid(futmodel.getFuturesGid()); +// stock.setStockCode(futmodel.getFuturesCode()); +// stock.setStockName(futmodel.getFuturesName()); +// stock.setAddTime(futmodel.getAddTime()); +// stock.setId(futmodel.getId()); +// stock.setStockSpell("0"); +// depositAmt = futmodel.getDepositAmt(); +// } else if (code.contains("sh") || code.contains("sz")) { // 指数 +// StockIndex model = stockIndexMapper.selectIndexByCode(code.replace("sh", "").replace("sz", "")); +// stock.setStockGid(model.getIndexGid()); +// stock.setStockCode(model.getIndexCode()); +// stock.setStockName(model.getIndexName()); +// stock.setAddTime(model.getAddTime()); +// stock.setId(model.getId()); +// stock.setStockSpell("0"); +// depositAmt = model.getDepositAmt(); +// } else {// 股票 +// } + stock = repository.findStockByCode(code); + + if (stock == null) + return ServerResponse.createByErrorMsg(""); + String gid = stock.getStockGid(); + String sinaResult = SinaStockApi.getSinaStock(gid); + StockVO stockVO = new StockVO(); + if (code.contains("hf")) { + stockVO = SinaStockApi.assembleStockFuturesVO(sinaResult); + } else { + stockVO = SinaStockApi.assembleStockVO(sinaResult); + } + + stockVO.setDepositAmt(depositAmt); + stockVO.setId(stock.getId().intValue()); + stockVO.setCode(stock.getStockCode()); + stockVO.setSpell(stock.getStockSpell()); + stockVO.setGid(stock.getStockGid()); + stockVO.setMinImg(PropertiesUtil.getProperty("sina.single.stock.min.url") + stock.getStockGid() + ".jpg"); + stockVO.setDayImg(PropertiesUtil.getProperty("sina.single.stock.day.url") + stock.getStockGid() + ".jpg"); + stockVO.setWeekImg(PropertiesUtil.getProperty("sina.single.stock.week.url") + stock.getStockGid() + ".jpg"); + stockVO.setMonthImg(PropertiesUtil.getProperty("sina.single.stock.month.url") + stock.getStockGid() + ".jpg"); + return ServerResponse.createBySuccess(stockVO); + } + + public ServerResponse getMinK(String code, Integer time, Integer ma, Integer size) { + if (StringUtils.isBlank(code) || time == null || ma == null || size == null) + return ServerResponse.createByErrorMsg(""); + Stock stock = repository.findStockByCode(code); + if (stock == null) + return ServerResponse.createByErrorMsg(""); + return SinaStockApi.getStockMinK(stock, time.intValue(), ma.intValue(), size.intValue()); + } + + public ServerResponse getKLine(String code) { + return SinaStockApi.getKLine(code); + } + + public ServerResponse getMinK_Echarts(String code, Integer time, Integer ma, Integer size) { + if (StringUtils.isBlank(code) || time == null || ma == null || size == null) + return ServerResponse.createByErrorMsg(""); + Stock stock = repository.findStockByCode(code); + if (stock == null) + return ServerResponse.createByErrorMsg(""); + ServerResponse serverResponse = SinaStockApi.getStockMinK(stock, time.intValue(), ma.intValue(), + size.intValue()); + MinDataVO minDataVO = (MinDataVO) serverResponse.getData(); + EchartsDataVO echartsDataVO = SinaStockApi.assembleEchartsDataVO(minDataVO); + return ServerResponse.createBySuccess(echartsDataVO); + } + + /* 指数分时-k线 */ + public ServerResponse getIndexMinK_Echarts(String code, Integer time, Integer size) { + if (StringUtils.isBlank(code) || time == null) + return ServerResponse.createByErrorMsg(""); + + ServerResponse serverResponse = QqStockApi.getIndexMinK(code, time.intValue(), size.intValue()); + MinDataVO minDataVO = (MinDataVO) serverResponse.getData(); + EchartsDataVO echartsDataVO = SinaStockApi.assembleEchartsDataVO(minDataVO); + return ServerResponse.createBySuccess(echartsDataVO); + } + + /* 股票日线-K线 */ + public ServerResponse getDayK_Echarts(String code) { + return kEcharts(code, "day"); + } + + ServerResponse kEcharts(String code, String type) { + if (StringUtils.isBlank(code)) + return ServerResponse.createByErrorMsg(""); + Stock stock = repository.findStockByCode(code); + if (stock == null) + return ServerResponse.createByErrorMsg(""); + ServerResponse serverResponse = null; + if (stock.getStockType().equals("bj")) { + serverResponse = QqStockApi.getBjsStockMonthK(stock, type); + } else { + serverResponse = QqStockApi.getGpStockMonthK(stock, type); + } + MinDataVO minDataVO = (MinDataVO) serverResponse.getData(); + EchartsDataVO echartsDataVO = SinaStockApi.assembleEchartsDataVO(minDataVO); + return ServerResponse.createBySuccess(echartsDataVO); + } + + /* 股票周线-K线 */ + public ServerResponse getWeekK_Echarts(String code) { + return kEcharts(code, "week"); + } + + /* 股票月线-K线 */ + public ServerResponse getMonthK_Echarts(String code) { + return kEcharts(code, "month"); + } + + public StockRepository repository() { + return repository; + } + + + public ServerResponse listByAdmin(Integer showState, Integer lockState, String code, String name, + String stockPlate, String stockType, int pageNum, int pageSize, HttpServletRequest request) { + Page page = this.repository.listByAdmin(showState, lockState, code, name, stockPlate, stockType, PageParam.of(pageNum, pageSize)); + List stockAdminListVOS = Lists.newArrayList(); + for (Stock stock : page.getContent()) { + StockAdminListVO stockAdminListVO = assembleStockAdminListVO(stock); + stockAdminListVOS.add(stockAdminListVO); + } + PageInfo pageInfo = Utils.toPageHelperInfo(page); + pageInfo.setList(stockAdminListVOS); + return ServerResponse.createBySuccess(pageInfo); + } + + private StockAdminListVO assembleStockAdminListVO(Stock stock) { + StockAdminListVO stockAdminListVO = new StockAdminListVO(); + stockAdminListVO.setId(stock.getId()); + stockAdminListVO.setStockName(stock.getStockName()); + stockAdminListVO.setStockCode(stock.getStockCode()); + stockAdminListVO.setStockSpell(stock.getStockSpell()); + stockAdminListVO.setStockType(stock.getStockType()); + stockAdminListVO.setStockGid(stock.getStockGid()); + stockAdminListVO.setStockPlate(stock.getStockPlate()); + stockAdminListVO.setIsLock(stock.getIsLock()); + stockAdminListVO.setIsShow(stock.getIsShow()); + stockAdminListVO.setAddTime(stock.getAddTime()); + StockListVO stockListVO = SinaStockApi.assembleStockListVO(SinaStockApi.getSinaStock(stock.getStockGid())); + stockAdminListVO.setNowPrice(stockListVO.getNowPrice()); + stockAdminListVO.setHcrate(stockListVO.getHcrate()); + stockAdminListVO.setSpreadRate(stock.getSpreadRate()); +// ServerResponse serverResponse = selectRateByDaysAndStockCode(stock.getStockCode(), 3); + BigDecimal day3Rate = new BigDecimal("0"); +// if (serverResponse.isSuccess()) +// day3Rate = (BigDecimal) serverResponse.getData(); + stockAdminListVO.setDay3Rate(day3Rate); + return stockAdminListVO; + } + + public void updateLock(Integer stockId) { + Stock stock = this.repository.find(stockId); + if (stock == null) { + throw new EntityNotFoundException(); + } + if (stock.getIsLock().intValue() == 1) { + stock.setIsLock(Integer.valueOf(0)); + } else { + stock.setIsLock(Integer.valueOf(1)); + } + this.repository.saveAndFlush(stock); + } + + public void updateShow(Integer stockId) { + Stock stock = this.repository.find(stockId); + if (stock == null) { + throw new EntityNotFoundException(); + } + if (stock.getIsShow().intValue() == 0) { + stock.setIsShow(Integer.valueOf(1)); + } else { + stock.setIsShow(Integer.valueOf(0)); + } + this.repository.saveAndFlush(stock); + } + + public void addStock(String stockName, String stockCode, String stockType, String stockPlate, + Integer isLock, Integer isShow) { + if (StringUtils.isBlank(stockName) || StringUtils.isBlank(stockCode) || StringUtils.isBlank(stockType) + || isLock == null || isShow == null) + throw new SysTipsException("参数非法"); + Stock cstock = repository.findStockByCode(stockCode); + if (cstock != null) { + throw new EntityExistsException(); + } + Stock nstock = repository.findStockByName(stockName); + if (nstock != null) + throw new EntityExistsException(); + Stock stock = new Stock(); + stock.setStockName(stockName); + stock.setStockCode(stockCode); + stock.setStockSpell(GetPyByChinese.converterToFirstSpell(stockName)); + stock.setStockType(stockType); + stock.setStockGid(stockType + stockCode); + stock.setIsLock(isLock); + stock.setIsShow(isShow); + stock.setAddTime(new Date()); + if (stockPlate != null) + stock.setStockPlate(stockPlate); + + if (stockPlate != null && StringUtils.isNotEmpty(stockPlate) && stockCode.startsWith("300")) + stock.setStockPlate("创业"); + else if (stockPlate != null && StringUtils.isNotEmpty(stockPlate) && stockCode.startsWith("688")) + stock.setStockPlate("科创"); + else + stock.setStockPlate(null); + + this.repository.saveAndFlush(stock); + } + + public long CountStockNum() { + return this.repository.count(); + } + + public long CountShowNum(Integer showState) { + return this.repository.count(QStockPO.stockPO.isShow.eq(showState)); + } + + public long CountUnLockNum(Integer lockState) { + return this.repository.count(QStockPO.stockPO.isLock.eq(lockState)); + } + + public List findStockList() { + return this.repository.findAll(); + } + + public void updateStock(Stock model) { + if (StringUtils.isBlank(model.getId().toString()) || StringUtils.isBlank(model.getStockName())) + throw new SysTipsException("参数非法"); + + Stock stock = this.repository.find(model.getId()); + if (stock == null) + throw new EntityNotFoundException(); + + stock.setStockName(model.getStockName()); + if (model.getSpreadRate() != null) + stock.setSpreadRate(model.getSpreadRate()); + + repository.saveAndFlush(stock); + + } + + public void deleteByPrimaryKey(Integer id) { + repository.deleteById(id); + } + + public static StockService of() { + return SpringUtils.getBean(StockService.class); + } + + /* 指数日线-K线 */ + public ServerResponse getIndexDayK(String code) { + return getIndexK(code, "day"); + } + + /* 指数周线-K线 */ + public ServerResponse getIndexWeekK(String code) { + return getIndexK(code, "week"); + } + + /* 指数月线-K线 */ + public ServerResponse getIndexMonthK(String code) { + return getIndexK(code, "month"); + } + + /* 指数月线-K线 */ + public ServerResponse getIndexK(String code, String type) { + if (StringUtils.isBlank(code)) + return ServerResponse.createByErrorMsg(""); + + ServerResponse serverResponse = QqStockApi.getQqIndexDayK(code, type); + MinDataVO minDataVO = (MinDataVO) serverResponse.getData(); + EchartsDataVO echartsDataVO = SinaStockApi.assembleEchartsDataVO(minDataVO); + return ServerResponse.createBySuccess(echartsDataVO); + } + + + public ServerResponse getNewStock() { + String sina_result = ""; + + try { + List stockNewInfos = new ArrayList<>(); + sina_result = HttpClientRequest.doGet("https://datacenter-web.eastmoney.com/api/data/v1/get?sortColumns=APPLY_DATE%2CSECURITY_CODE&sortTypes=-1%2C-1&pageSize=10&pageNumber=1&reportName=RPTA_APP_IPOAPPLY&columns=SECURITY_CODE%2CSECURITY_NAME%2CTRADE_MARKET_CODE%2CAPPLY_CODE%2CTRADE_MARKET%2CMARKET_TYPE%2CORG_TYPE%2CISSUE_NUM%2CONLINE_ISSUE_NUM%2COFFLINE_PLACING_NUM%2CTOP_APPLY_MARKETCAP%2CPREDICT_ONFUND_UPPER%2CONLINE_APPLY_UPPER%2CPREDICT_ONAPPLY_UPPER%2CISSUE_PRICE%2CLATELY_PRICE%2CCLOSE_PRICE%2CAPPLY_DATE%2CBALLOT_NUM_DATE%2CBALLOT_PAY_DATE%2CLISTING_DATE%2CAFTER_ISSUE_PE%2CONLINE_ISSUE_LWR%2CINITIAL_MULTIPLE%2CINDUSTRY_PE_NEW%2COFFLINE_EP_OBJECT%2CCONTINUOUS_1WORD_NUM%2CTOTAL_CHANGE%2CPROFIT%2CLIMIT_UP_PRICE%2CINFO_CODE%2COPEN_PRICE%2CLD_OPEN_PREMIUM%2CLD_CLOSE_CHANGE%2CTURNOVERRATE%2CLD_HIGH_CHANG%2CLD_AVERAGE_PRICE%2COPEN_DATE%2COPEN_AVERAGE_PRICE%2CPREDICT_PE%2CPREDICT_ISSUE_PRICE2%2CPREDICT_ISSUE_PRICE%2CPREDICT_ISSUE_PRICE1%2CPREDICT_ISSUE_PE%2CPREDICT_PE_THREE%2CONLINE_APPLY_PRICE%2CMAIN_BUSINESS%2CPAGE_PREDICT_PRICE1%2CPAGE_PREDICT_PRICE2%2CPAGE_PREDICT_PRICE3%2CPAGE_PREDICT_PE1%2CPAGE_PREDICT_PE2%2CPAGE_PREDICT_PE3%2CSELECT_LISTING_DATE%2CIS_BEIJING%2CINDUSTRY_PE_RATIO%2CIS_REGISTRATION"eColumns=f2~01~SECURITY_CODE~NEWEST_PRICE"eType=0"); + com.alibaba.fastjson.JSONObject json = com.alibaba.fastjson.JSONObject.parseObject(sina_result); + com.alibaba.fastjson.JSONArray jsonArray = json.getJSONObject("result").getJSONArray("data"); + + for (Object o : jsonArray) { + com.alibaba.fastjson.JSONObject jsonObject = (com.alibaba.fastjson.JSONObject) o; + HKStockNewInfo info = new HKStockNewInfo(); + info.setSymbol(jsonObject.getString("SECURITY_CODE")); + info.setName(jsonObject.getString("SECURITY_NAME")); + info.setLotWinRate(jsonObject.getString("ONLINE_ISSUE_LWR")); + info.setPrice(jsonObject.getString("ISSUE_PRICE")); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + if (new Date(jsonObject.getLong("APPLY_DATE")).before(new Date())) { + break; + } + String formattedDate = sdf.format(new Date(jsonObject.getLong("APPLY_DATE"))); + info.setApplyBeginDate(formattedDate); + info.setType(3); + //判断深沪类型 + if (jsonObject.getString("TRADE_MARKET").contains("深证")) { + info.setType(1); + } + if (jsonObject.getString("TRADE_MARKET").contains("上海")) { + info.setType(2); + } + stockNewInfos.add(info); + } + return ServerResponse.createBySuccess(stockNewInfos); + + } catch (Exception e) { + log.error("获取出错,错误信息 = {}", e); + } + return null; + } + + public ServerResponse getNewStockList() { + try { + JSONObject jsonParam = new JSONObject(); + jsonParam.put("Czxt", "HUAWEI BNE-AL00 12"); + jsonParam.put("Sblx", "RNandroid"); + jsonParam.put("Sjhm", "LIP:NA;MAC:NA;IMEI:NA;RMPN:NA;UMPN:NA;ICCID:NA;OSV:12;IMSI:NA"); + jsonParam.put("Type", "QueryIpoToBeListed"); + jsonParam.put("User_id_lx", "Z"); + jsonParam.put("User_id", "666666666666"); + jsonParam.put("emtoken", "EMRNV1"); + jsonParam.put("svrid", "em-secutrade-service"); + jsonParam.put("gw_reqtimestamp", System.currentTimeMillis()); + jsonParam.put("startIndex", 1); + jsonParam.put("pageSize", 20); + jsonParam.put("Kzzbz", "0"); + jsonParam.put("Version", "10.12.1"); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + HttpEntity requestEntity = new HttpEntity<>(jsonParam.toString(), headers); + ResponseEntity response = restTemplate.postForEntity("https://nhtradegateway.18.cn/api/NewStk/QueryIpoToBeListed", requestEntity, String.class); + com.alibaba.fastjson.JSONArray data = JSON.parseObject(response.getBody()).getJSONArray("Data"); + return ServerResponse.createBySuccess(data); + } catch (Exception e) { + e.printStackTrace(); + } + return ServerResponse.createByErrorMsg("请求失败"); + } +} \ No newline at end of file diff --git a/src/main/java/cn/stock/market/domain/basic/service/SysLogService.java b/src/main/java/cn/stock/market/domain/basic/service/SysLogService.java new file mode 100644 index 0000000..8df372f --- /dev/null +++ b/src/main/java/cn/stock/market/domain/basic/service/SysLogService.java @@ -0,0 +1,36 @@ +package cn.stock.market.domain.basic.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.factory.LogBuilder; +import cn.stock.market.domain.basic.factory.SysLogFactory; +import cn.stock.market.domain.basic.repository.SysLogRepository; +import lombok.RequiredArgsConstructor; + +/** + * SysLogService + * + * @author xlfd + * @email xlfd@gmail.com + * @created 2021/06/18 + */ +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class SysLogService { + final SysLogRepository repository; + final SysLogFactory factory; + + public SysLogRepository repository() { + return repository; + } + + public static SysLogService of() { + return SpringUtils.getBean(SysLogService.class); + } + + public void log(LogBuilder builder) { + repository.save(builder.build()); + } +} diff --git a/src/main/java/cn/stock/market/dto/CityDTO.java b/src/main/java/cn/stock/market/dto/CityDTO.java new file mode 100644 index 0000000..9e15f3b --- /dev/null +++ b/src/main/java/cn/stock/market/dto/CityDTO.java @@ -0,0 +1,23 @@ +package cn.stock.market.dto; + +import cn.stock.market.infrastructure.db.po.CityPO; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * CityDTO + * + * @author xlfd + * @email xlfd@gmail.com + * @created 2021/06/16 + */ +@Data +@NoArgsConstructor +@SuperBuilder +@EqualsAndHashCode(callSuper = false) +@ApiModel +public class CityDTO extends CityPO { +} diff --git a/src/main/java/cn/stock/market/dto/JsonInfoDTO.java b/src/main/java/cn/stock/market/dto/JsonInfoDTO.java new file mode 100644 index 0000000..69e4517 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/JsonInfoDTO.java @@ -0,0 +1,50 @@ +package cn.stock.market.dto; + +import java.util.Date; + +import com.ag.utils.DateUtils; +import com.ag.utils.StringConvertJSONObjectSerializer; +import com.alibaba.fastjson.annotation.JSONField; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import cn.qutaojing.common.utils.fastjson.DateJsonSerializer; +import cn.qutaojing.common.utils.jackson.String2JsonObjSerializer; +import cn.stock.market.infrastructure.db.po.JsonInfoPO; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * JsonInfoDTO + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2022/08/16 + */ +@Data +@NoArgsConstructor +@SuperBuilder +@EqualsAndHashCode(callSuper = false) +public class JsonInfoDTO extends JsonInfoPO { + @JsonSerialize(using = DateJsonSerializer.class) + @JSONField(format = DateUtils.YYYY_MM_DD_HH_MM_SS) + @Override + public Date getUpdateAt() { + return super.getUpdateAt(); + } + + @JsonSerialize(using = DateJsonSerializer.class) + @JSONField(format = DateUtils.YYYY_MM_DD_HH_MM_SS) + @Override + public Date getCreateAt() { + return super.getCreateAt(); + } + + @JsonSerialize(using = String2JsonObjSerializer.class) + @JSONField(serializeUsing = StringConvertJSONObjectSerializer.class) + @Override + public String getExt() { + return super.getExt(); + } +} diff --git a/src/main/java/cn/stock/market/dto/RealtimeDTO.java b/src/main/java/cn/stock/market/dto/RealtimeDTO.java new file mode 100644 index 0000000..0194f51 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/RealtimeDTO.java @@ -0,0 +1,23 @@ +package cn.stock.market.dto; + +import cn.stock.market.infrastructure.db.po.RealtimePO; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * RealtimeDTO + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Data +@NoArgsConstructor +@SuperBuilder +@EqualsAndHashCode( + callSuper = false +) +public class RealtimeDTO extends RealtimePO { +} diff --git a/src/main/java/cn/stock/market/dto/SiteArticleDTO.java b/src/main/java/cn/stock/market/dto/SiteArticleDTO.java new file mode 100644 index 0000000..3e4ef1f --- /dev/null +++ b/src/main/java/cn/stock/market/dto/SiteArticleDTO.java @@ -0,0 +1,23 @@ +package cn.stock.market.dto; + +import cn.stock.market.infrastructure.db.po.SiteArticlePO; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * SiteArticleDTO + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Data +@NoArgsConstructor +@SuperBuilder +@EqualsAndHashCode( + callSuper = false +) +public class SiteArticleDTO extends SiteArticlePO { +} diff --git a/src/main/java/cn/stock/market/dto/SiteNewsDTO.java b/src/main/java/cn/stock/market/dto/SiteNewsDTO.java new file mode 100644 index 0000000..c8fffe6 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/SiteNewsDTO.java @@ -0,0 +1,23 @@ +package cn.stock.market.dto; + +import cn.stock.market.infrastructure.db.po.SiteNewsPO; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * SiteNewsDTO + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/19 + */ +@Data +@NoArgsConstructor +@SuperBuilder +@EqualsAndHashCode( + callSuper = false +) +public class SiteNewsDTO extends SiteNewsPO { +} diff --git a/src/main/java/cn/stock/market/dto/StockDTO.java b/src/main/java/cn/stock/market/dto/StockDTO.java new file mode 100644 index 0000000..8dc74a6 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/StockDTO.java @@ -0,0 +1,23 @@ +package cn.stock.market.dto; + +import cn.stock.market.infrastructure.stockdb.po.StockPO; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * StockDTO + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Data +@NoArgsConstructor +@SuperBuilder +@EqualsAndHashCode( + callSuper = false +) +public class StockDTO extends StockPO { +} diff --git a/src/main/java/cn/stock/market/dto/SysLogDTO.java b/src/main/java/cn/stock/market/dto/SysLogDTO.java new file mode 100644 index 0000000..0c6eb4b --- /dev/null +++ b/src/main/java/cn/stock/market/dto/SysLogDTO.java @@ -0,0 +1,23 @@ +package cn.stock.market.dto; + +import cn.stock.market.infrastructure.db.po.SysLogPO; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * CityDTO + * + * @author xlfd + * @email xlfd@gmail.com + * @created 2021/06/16 + */ +@Data +@NoArgsConstructor +@SuperBuilder +@EqualsAndHashCode(callSuper = false) +@ApiModel +public class SysLogDTO extends SysLogPO { +} diff --git a/src/main/java/cn/stock/market/dto/command/JsonInfoCreateCommand.java b/src/main/java/cn/stock/market/dto/command/JsonInfoCreateCommand.java new file mode 100644 index 0000000..a95e9fb --- /dev/null +++ b/src/main/java/cn/stock/market/dto/command/JsonInfoCreateCommand.java @@ -0,0 +1,20 @@ +package cn.stock.market.dto.command; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * JsonInfoCreateCommand + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2022/08/16 + */ +@Data +@SuperBuilder +@NoArgsConstructor +public class JsonInfoCreateCommand { + String type; + String ext; +} diff --git a/src/main/java/cn/stock/market/dto/command/JsonInfoModifyCommand.java b/src/main/java/cn/stock/market/dto/command/JsonInfoModifyCommand.java new file mode 100644 index 0000000..4a221af --- /dev/null +++ b/src/main/java/cn/stock/market/dto/command/JsonInfoModifyCommand.java @@ -0,0 +1,24 @@ +package cn.stock.market.dto.command; + +import java.lang.Integer; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * JsonInfoModifyCommand + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2022/08/16 + */ +@Data +@SuperBuilder +@NoArgsConstructor +@EqualsAndHashCode( + callSuper = false +) +public class JsonInfoModifyCommand extends JsonInfoCreateCommand { + Integer id; +} diff --git a/src/main/java/cn/stock/market/dto/command/RealtimeCreateCommand.java b/src/main/java/cn/stock/market/dto/command/RealtimeCreateCommand.java new file mode 100644 index 0000000..f7fa72f --- /dev/null +++ b/src/main/java/cn/stock/market/dto/command/RealtimeCreateCommand.java @@ -0,0 +1,38 @@ +package cn.stock.market.dto.command; + +import java.lang.Double; +import java.lang.Integer; +import java.lang.String; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * RealtimeCreateCommand + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Data +@SuperBuilder +@NoArgsConstructor +public class RealtimeCreateCommand { + Integer id; + + String time; + + Integer volumes; + + Double price; + + Double rates; + + Integer amounts; + + String stockCode; + + /** + * 均价 */ + Double averagePrice; +} diff --git a/src/main/java/cn/stock/market/dto/command/RealtimeModifyCommand.java b/src/main/java/cn/stock/market/dto/command/RealtimeModifyCommand.java new file mode 100644 index 0000000..089ca1a --- /dev/null +++ b/src/main/java/cn/stock/market/dto/command/RealtimeModifyCommand.java @@ -0,0 +1,24 @@ +package cn.stock.market.dto.command; + +import java.lang.Integer; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * RealtimeModifyCommand + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Data +@SuperBuilder +@NoArgsConstructor +@EqualsAndHashCode( + callSuper = false +) +public class RealtimeModifyCommand extends RealtimeCreateCommand { + Integer id; +} diff --git a/src/main/java/cn/stock/market/dto/command/SiteArticleCreateCommand.java b/src/main/java/cn/stock/market/dto/command/SiteArticleCreateCommand.java new file mode 100644 index 0000000..24c6152 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/command/SiteArticleCreateCommand.java @@ -0,0 +1,50 @@ +package cn.stock.market.dto.command; + +import java.lang.Integer; +import java.lang.String; +import java.util.Date; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * SiteArticleCreateCommand + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Data +@SuperBuilder +@NoArgsConstructor +public class SiteArticleCreateCommand { + Integer id; + + String artTitle; + + String artType; + + String artImg; + + String author; + + Integer hitTimes; + + Integer isShow; + + Date addTime; + + String artSummary; + + String artCnt; + + String spiderUrl; + + /** + * 来源id */ + String sourceId; + + /** + * 浏览量 */ + Integer views; +} diff --git a/src/main/java/cn/stock/market/dto/command/SiteArticleModifyCommand.java b/src/main/java/cn/stock/market/dto/command/SiteArticleModifyCommand.java new file mode 100644 index 0000000..1f38410 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/command/SiteArticleModifyCommand.java @@ -0,0 +1,24 @@ +package cn.stock.market.dto.command; + +import java.lang.Integer; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * SiteArticleModifyCommand + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Data +@SuperBuilder +@NoArgsConstructor +@EqualsAndHashCode( + callSuper = false +) +public class SiteArticleModifyCommand extends SiteArticleCreateCommand { + Integer id; +} diff --git a/src/main/java/cn/stock/market/dto/command/SiteNewsCreateCommand.java b/src/main/java/cn/stock/market/dto/command/SiteNewsCreateCommand.java new file mode 100644 index 0000000..bdb0204 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/command/SiteNewsCreateCommand.java @@ -0,0 +1,68 @@ +package cn.stock.market.dto.command; + +import java.lang.Integer; +import java.lang.String; +import java.util.Date; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * SiteNewsCreateCommand + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/19 + */ +@Data +@SuperBuilder +@NoArgsConstructor +public class SiteNewsCreateCommand { + /** + * 新闻主键id */ + Integer id; + + /** + * 新闻类型:1、财经要闻,2、经济数据,3、全球股市,4、7*24全球,5、商品资讯,6、上市公司,7、全球央行 */ + Integer type; + + /** + * 新闻标题 */ + String title; + + /** + * 来源id */ + String sourceId; + + /** + * 来源名称 */ + String sourceName; + + /** + * 浏览量 */ + Integer views; + + /** + * 状态:1、启用,0、停用 */ + Integer status; + + /** + * 显示时间 */ + Date showTime; + + /** + * 添加时间 */ + Date addTime; + + /** + * 图片地址 */ + String imgurl; + + /** + * 描述 */ + String description; + + /** + * 新闻内容 */ + String content; +} diff --git a/src/main/java/cn/stock/market/dto/command/SiteNewsModifyCommand.java b/src/main/java/cn/stock/market/dto/command/SiteNewsModifyCommand.java new file mode 100644 index 0000000..f3ce64b --- /dev/null +++ b/src/main/java/cn/stock/market/dto/command/SiteNewsModifyCommand.java @@ -0,0 +1,24 @@ +package cn.stock.market.dto.command; + +import java.lang.Integer; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * SiteNewsModifyCommand + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/19 + */ +@Data +@SuperBuilder +@NoArgsConstructor +@EqualsAndHashCode( + callSuper = false +) +public class SiteNewsModifyCommand extends SiteNewsCreateCommand { + Integer id; +} diff --git a/src/main/java/cn/stock/market/dto/command/StockCreateCommand.java b/src/main/java/cn/stock/market/dto/command/StockCreateCommand.java new file mode 100644 index 0000000..4275b97 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/command/StockCreateCommand.java @@ -0,0 +1,49 @@ +package cn.stock.market.dto.command; + +import java.lang.Integer; +import java.lang.String; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * StockCreateCommand + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Data +@SuperBuilder +@NoArgsConstructor +public class StockCreateCommand { + Integer id; + + String stockName; + + String stockCode; + + String stockSpell; + + String stockType; + + String stockGid; + + String stockPlate; + + Integer isLock; + + Integer isShow; + + Date addTime; + + /** + * 点差费率 */ + BigDecimal spreadRate; + + /** + * 涨幅比例 */ + BigDecimal increaseRatio; +} diff --git a/src/main/java/cn/stock/market/dto/command/StockModifyCommand.java b/src/main/java/cn/stock/market/dto/command/StockModifyCommand.java new file mode 100644 index 0000000..7ef21ec --- /dev/null +++ b/src/main/java/cn/stock/market/dto/command/StockModifyCommand.java @@ -0,0 +1,24 @@ +package cn.stock.market.dto.command; + +import java.lang.Integer; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * StockModifyCommand + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@Data +@SuperBuilder +@NoArgsConstructor +@EqualsAndHashCode( + callSuper = false +) +public class StockModifyCommand extends StockCreateCommand { + Integer id; +} diff --git a/src/main/java/cn/stock/market/dto/model/AboutUs.java b/src/main/java/cn/stock/market/dto/model/AboutUs.java new file mode 100644 index 0000000..5c2bacb --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/AboutUs.java @@ -0,0 +1,14 @@ +package cn.stock.market.dto.model; + +import lombok.Data; + +@Data +public class AboutUs { + String icon; + String name; + String url; + String phone; + String mp; + String copyright; + String copyrightUrl; +} diff --git a/src/main/java/cn/stock/market/dto/model/AddressThumb.java b/src/main/java/cn/stock/market/dto/model/AddressThumb.java new file mode 100644 index 0000000..a526f0d --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/AddressThumb.java @@ -0,0 +1,14 @@ +package cn.stock.market.dto.model; + +import lombok.Data; + +@Data +public class AddressThumb { + String role; + String name; + String contactPhone; + String viewPhone; + String cityPath; + String cityPathText; + String address; +} diff --git a/src/main/java/cn/stock/market/dto/model/Bank.java b/src/main/java/cn/stock/market/dto/model/Bank.java new file mode 100644 index 0000000..87838a7 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/Bank.java @@ -0,0 +1,28 @@ +package cn.stock.market.dto.model; + +import com.ag.utils.Jsons; + +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@SuperBuilder +@EqualsAndHashCode(callSuper = false) +@NoArgsConstructor +@ApiModel +public class Bank { + String currency; + String bankCode; + String bankName; + String bankIcon; + String remark; + + public static void main(String[] args) { + String s = "{\"bankCode\":\"ccb\",\"bankIcon\":\"https://stock-prod.oss-cn-hangzhou.aliyuncs.com/bankIcon/ac02108bde1a640ffedb5117793762db.png\",\"bankName\":\"建设银行\",\"remark\":\"银行监管账户\"}"; + Bank bean = Jsons.toBean(s, Bank.class); + System.out.println(bean); + } +} diff --git a/src/main/java/cn/stock/market/dto/model/CapitalIncrement.java b/src/main/java/cn/stock/market/dto/model/CapitalIncrement.java new file mode 100644 index 0000000..30a83c3 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/CapitalIncrement.java @@ -0,0 +1,116 @@ +package cn.stock.market.dto.model; + +import java.math.BigDecimal; + +import com.alibaba.fastjson.JSONObject; + +import cn.stock.market.constant.BillOrderEvent; +import cn.stock.market.constant.CapitalType; +import lombok.Getter; + +/** + * 资金增加描述 + * + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Sep 18, 2021 1:10:27 PM + */ +@Getter +public class CapitalIncrement { + BillOrderEvent event; + CapitalType capitalType; + BigDecimal originalAmount; + BigDecimal tradeAmount; + BigDecimal amount; + BigDecimal refundAmount; + BigDecimal sysAmount; + BigDecimal supplierAmount; + BigDecimal customerAmount; + + public JSONObject json() { + JSONObject json = new JSONObject(); + if(originalAmount != null) { + json.put("originalAmount", originalAmount); + } + if(tradeAmount != null) { + json.put("tradeAmount", tradeAmount); + } + if(amount != null) { + json.put("amount", amount); + } + if(refundAmount != null) { + json.put("refundAmount", refundAmount); + } + if(sysAmount != null) { + json.put("sysAmount", sysAmount); + } + if(supplierAmount != null) { + json.put("supplierAmount", supplierAmount); + } + if(customerAmount != null) { + json.put("customerAmount", customerAmount); + } + return json; + } + + public static IncrementBuilder builder() { + return new IncrementBuilder(); + } + + public final static class IncrementBuilder { + CapitalIncrement incr = null; + public IncrementBuilder() { + incr = new CapitalIncrement(); + } + + public IncrementBuilder originalAmount(BigDecimal originalAmount) { + incr.originalAmount = originalAmount; + return this; + } + + public IncrementBuilder tradeAmount(BigDecimal tradeAmount) { + incr.tradeAmount = tradeAmount; + return this; + } + + public IncrementBuilder amount(BigDecimal amount) { + incr.amount = amount; + return this; + } + + public IncrementBuilder refundAmount(BigDecimal refundAmount) { + incr.refundAmount = refundAmount; + return this; + } + + public IncrementBuilder sysAmount(BigDecimal sysAmount) { + incr.sysAmount = sysAmount; + return this; + } + + public IncrementBuilder supplierAmount(BigDecimal supplierAmount) { + incr.supplierAmount = supplierAmount; + return this; + } + + public IncrementBuilder customerAmount(BigDecimal customerAmount) { + incr.customerAmount = customerAmount; + return this; + } + + public IncrementBuilder capitalType(CapitalType capitalType) { + incr.capitalType = capitalType; + return this; + } + + public IncrementBuilder event(BillOrderEvent event) { + incr.event = event; + return this; + } + + public CapitalIncrement build() { + return incr; + } + } +} diff --git a/src/main/java/cn/stock/market/dto/model/ClickActionInfo.java b/src/main/java/cn/stock/market/dto/model/ClickActionInfo.java new file mode 100644 index 0000000..91a8cc7 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/ClickActionInfo.java @@ -0,0 +1,44 @@ +package cn.stock.market.dto.model; + +import cn.stock.market.constant.ClickAction; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@SuperBuilder +@EqualsAndHashCode(callSuper = false) +@NoArgsConstructor +@ApiModel +public class ClickActionInfo { + ClickAction action; + String actionTarget; + String actionText; + String expend; + + public static ClickActionInfo of(ClickAction action, Integer id) { + return of(action, String.valueOf(id)); + } + + public static ClickActionInfo of(ClickAction action, String actionTarget) { + return of(action, actionTarget, null); + } + + public static ClickActionInfo of(ClickAction action, String actionTarget, String expend) { + return ClickActionInfo.builder() + .action(action) + .expend(expend) + .actionText(action.remark()) + .actionTarget(actionTarget) + .build(); + } + + public void fillExpend() { + if(action == ClickAction.GOODS_DETAIL) { + } else if(action == ClickAction.SUBJECT) { + } else if(action == ClickAction.FRONT_CLASSIFY) { + } + } +} diff --git a/src/main/java/cn/stock/market/dto/model/CurrencyRatio.java b/src/main/java/cn/stock/market/dto/model/CurrencyRatio.java new file mode 100644 index 0000000..aae5c5d --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/CurrencyRatio.java @@ -0,0 +1,26 @@ +package cn.stock.market.dto.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * + * 币种比例 + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jul 27, 2021 1:51:16 PM + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class CurrencyRatio { + Double cny; + + public static CurrencyRatio allCny() { + return new CurrencyRatio(1.0D); + } +} diff --git a/src/main/java/cn/stock/market/dto/model/ExchangeInfoDTO.java b/src/main/java/cn/stock/market/dto/model/ExchangeInfoDTO.java new file mode 100644 index 0000000..c59783a --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/ExchangeInfoDTO.java @@ -0,0 +1,37 @@ +package cn.stock.market.dto.model; + +import java.math.BigDecimal; + +import cn.qutaojing.common.constant.Currency; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * + * title: ExchangerRate.java + * 汇率 + * + * @author rplees + * @email xlfd@gmail.com + * @version 1.0 + * @created Aug 12, 2022 10:52:32 AM + */ +@Data +@SuperBuilder +@EqualsAndHashCode(callSuper = false) +@NoArgsConstructor +@ApiModel +public class ExchangeInfoDTO { + @ApiModelProperty("兑出币种") + Currency from; + @ApiModelProperty("兑入币种") + Currency to; + @ApiModelProperty("汇率(1 from币种 = ${rate} to币种)") + BigDecimal rate; + @ApiModelProperty("可兑金额") + BigDecimal fromBalance; +} diff --git a/src/main/java/cn/stock/market/dto/model/ExchangeRate.java b/src/main/java/cn/stock/market/dto/model/ExchangeRate.java new file mode 100644 index 0000000..f539886 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/ExchangeRate.java @@ -0,0 +1,75 @@ +package cn.stock.market.dto.model; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Map; + +import com.ag.exception.SysTipsException; + +import cn.qutaojing.common.constant.Currency; +import cn.qutaojing.common.utils.BigDecimals; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * + * title: ExchangerRate.java + * 汇率 + * + * @author rplees + * @email xlfd@gmail.com + * @version 1.0 + * @created Aug 12, 2022 10:52:32 AM + */ +@Data +@SuperBuilder +@EqualsAndHashCode(callSuper = false) +@NoArgsConstructor +@ApiModel +public class ExchangeRate { + @ApiModelProperty("当前币种") + Currency base; + @ApiModelProperty("与不同币种的汇率信息") + Map rates; + + public BigDecimal toCurrency(Currency from, Currency to) { + if(base != from && base != to) { + throw new SysTipsException("不能计算汇率比"); + } + + if(! rates.containsKey(to)) { + throw new SysTipsException("没有该币种[" + to.remark() + "]信息, 无法兑换"); + } + + if(base == from) { + return rates.get(to); + } else { + return BigDecimals.divide(1, rates.get(from)).setScale(4, RoundingMode.HALF_UP); + } + } + +// public BigDecimal toCurrencyValue(Currency to, BigDecimal value) { +// BigDecimal currency = toCurrency(to); +// return BigDecimals.multiplys(value, currency); +// } +// +// public BigDecimal toCurrencyValue(String to, BigDecimal value) { +// BigDecimal currency = toCurrency(Currency.of(to)); +// return BigDecimals.multiplys(value, currency); +// } + + public BigDecimal toCurrencyValue(Currency from, Currency to, BigDecimal value) { + BigDecimal currency = toCurrency(from, to); + return BigDecimals.multiplys(value, currency).setScale(2, RoundingMode.HALF_UP); + } + + public BigDecimal toCurrencyValue(String from, String to, BigDecimal value) { + Currency fromCurrency = Currency.of(from); + Currency toCurrency = Currency.of(to); + return toCurrencyValue(fromCurrency, toCurrency, value); + } +} diff --git a/src/main/java/cn/stock/market/dto/model/HKStockNewInfo.java b/src/main/java/cn/stock/market/dto/model/HKStockNewInfo.java new file mode 100644 index 0000000..fe6564c --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/HKStockNewInfo.java @@ -0,0 +1,26 @@ +package cn.stock.market.dto.model; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +@Data +@ApiModel("香港新股信息") +public class HKStockNewInfo { + @ApiModelProperty("股票代码") + private String symbol; + @ApiModelProperty("股票名称") + private String name; + @ApiModelProperty("上市时间") + private String applyBeginDate; + @ApiModelProperty("中签率") + private String lotWinRate; + @ApiModelProperty("价格") + private String price; + @ApiModelProperty("类型(1深 2沪 3北)") + private Integer type; + + +} \ No newline at end of file diff --git a/src/main/java/cn/stock/market/dto/model/IStockPrice.java b/src/main/java/cn/stock/market/dto/model/IStockPrice.java new file mode 100644 index 0000000..64bd65e --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/IStockPrice.java @@ -0,0 +1,31 @@ +package cn.stock.market.dto.model; + +import java.math.BigDecimal; +import java.util.List; + +import com.ag.utils.vo.KVContainer; +import com.google.common.collect.Lists; + +public interface IStockPrice { + default BigDecimal yesterdayPrice() { + return BigDecimal.ZERO; + } + + BigDecimal price(); + + default List> sell() { + return Lists.newArrayList(); + } + + default List> buy() { + return Lists.newArrayList(); + } + + default BigDecimal priceRange() { + return BigDecimal.ZERO; + } + + default BigDecimal priceRate() { + return BigDecimal.ZERO; + } +} diff --git a/src/main/java/cn/stock/market/dto/model/IdentityAuthInfo.java b/src/main/java/cn/stock/market/dto/model/IdentityAuthInfo.java new file mode 100644 index 0000000..b7db790 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/IdentityAuthInfo.java @@ -0,0 +1,25 @@ +package cn.stock.market.dto.model; + +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@SuperBuilder +@EqualsAndHashCode(callSuper = false) +@NoArgsConstructor +@ApiModel +public class IdentityAuthInfo { + String name; + String idcard; + String address; + String birth; + String nation; + String gender; + String authority; + + String fortUrl; + String backUrl; +} diff --git a/src/main/java/cn/stock/market/dto/model/InvitationActi.java b/src/main/java/cn/stock/market/dto/model/InvitationActi.java new file mode 100644 index 0000000..8032345 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/InvitationActi.java @@ -0,0 +1,159 @@ +package cn.stock.market.dto.model; + +import java.util.Comparator; +import java.util.List; + +import com.ag.utils.CollectionUtils; +import com.ag.utils.SysConstant.BooleanEnum; +import com.alibaba.fastjson.JSON; +import com.google.common.collect.Lists; + +import cn.stock.market.application.Dics; +import cn.stock.market.dto.model.InvitationActi.RulePrize; +import cn.stock.market.dto.model.InvitationActi.UserInvitationInfo; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * + * 邀请赚现金活动 + * @author rplees + * @email rplees.i.ly@gmail.com + * @version 1.0 + * @created Oct 20, 2022 11:35:47 AM + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InvitationActi { + String name; + Integer status; + List rulePrizeList; + + public boolean open() { + return BooleanEnum.isOn(status); + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class RulePrize { + Integer step; + Long needInvitationCount; + String stockCode; + String stockName; + Integer stockCount; + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class UserInvitationInfo { + Long invitationCount; + List rulePrizeList; + + public Integer preStep() { + if(CollectionUtils.isEmpty(rulePrizeList)) { + return 0; + } + + return rulePrizeList.get(rulePrizeList.size() - 1).step; + } + } + + public RulePrize hit(UserInvitationInfo userInvitationInfo) { + List alreadyStep = Lists.transform(userInvitationInfo.rulePrizeList, RulePrize::getStep); + + RulePrize rulePrize = rulePrizeList.stream() + .filter(val -> ! alreadyStep.contains(val.getStep())) + .sorted(Comparator.comparing(RulePrize::getNeedInvitationCount).reversed()) + .filter(val -> val.needInvitationCount <= userInvitationInfo.getInvitationCount()) + .findFirst().orElse(null); + + return rulePrize; + } + + public static InvitationActi invitationActi() { + return InvitationActi.builder() + .name("邀请送股票活动") + .status(1) + .rulePrizeList(Lists.newArrayList( + RulePrize.builder() + .step(1) + .needInvitationCount(3L) + .stockCount(1) + .stockCode("01810") + .stockName("小米集团-W") + .build(), + + RulePrize.builder() + .step(2) + .needInvitationCount(8L) + .stockCount(3) + .stockCode("01810") + .stockName("小米集团-W") + .build(), + + RulePrize.builder() + .step(3) + .needInvitationCount(15L) + .stockCount(4) + .stockCode("01810") + .stockName("小米集团-W") + .build() + )) + .build(); + } + + public static void main(String[] args) { + UserInvitationInfo userInvitationInfo = UserInvitationInfo.builder() + .invitationCount(2L) + .rulePrizeList(Lists.newArrayList()) + .build(); + RulePrize prize = invitationActi().hit(userInvitationInfo); + System.out.println(JSON.toJSONString(prize)); + + userInvitationInfo.setInvitationCount(6L); + prize = invitationActi().hit(userInvitationInfo); + System.out.println(JSON.toJSONString(prize)); + + userInvitationInfo.setInvitationCount(10L); + prize = invitationActi().hit(userInvitationInfo); + System.out.println(JSON.toJSONString(prize)); + + userInvitationInfo.setInvitationCount(15L); + prize = invitationActi().hit(userInvitationInfo); + System.out.println(JSON.toJSONString(prize)); + + userInvitationInfo.setRulePrizeList(Lists.newArrayList( + RulePrize.builder() + .step(1) + .needInvitationCount(3L) + .stockCount(1) + .stockCode("01810") + .build(), + + RulePrize.builder() + .step(2) + .needInvitationCount(8L) + .stockCount(3) + .stockCode("01810") + .build(), + + RulePrize.builder() + .step(3) + .needInvitationCount(15L) + .stockCount(4) + .stockCode("01810") + .build() + )); + + prize = invitationActi().hit(userInvitationInfo); + System.out.println(JSON.toJSONString(prize)); + } +} diff --git a/src/main/java/cn/stock/market/dto/model/LogisticsInfo.java b/src/main/java/cn/stock/market/dto/model/LogisticsInfo.java new file mode 100644 index 0000000..c1a823a --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/LogisticsInfo.java @@ -0,0 +1,41 @@ +package cn.stock.market.dto.model; + +import org.apache.commons.lang3.StringUtils; + +import com.ag.exception.SysTipsException; + +import cn.stock.market.application.Dics; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@SuperBuilder +@EqualsAndHashCode(callSuper = false) +@NoArgsConstructor +@ApiModel +public class LogisticsInfo { + String logisticsCode; + String logistics; + + String receiverPhone; + String senderPhone; + String no; + + public static LogisticsInfo from(String logisticsCode, String no) { + String logistics = Dics.of().getFromCache("logistics." + logisticsCode, null); + if(StringUtils.isBlank(logistics)) { + throw new SysTipsException("找不到该物流信息"); + } + + LogisticsInfo logisticsInfo = LogisticsInfo.builder() + .logistics(logistics) + .logisticsCode(logisticsCode) + .no(no) + .build(); + + return logisticsInfo; + } +} diff --git a/src/main/java/cn/stock/market/dto/model/StockAdminListVO.java b/src/main/java/cn/stock/market/dto/model/StockAdminListVO.java new file mode 100644 index 0000000..735d583 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/StockAdminListVO.java @@ -0,0 +1,215 @@ +package cn.stock.market.dto.model; + +import java.math.BigDecimal; +import java.util.Date; + +public class StockAdminListVO { + private Integer id; + private String stockName; + private String stockCode; + private String stockSpell; + private String stockType; + private String stockGid; + + public void setId(Integer id) { + this.id = id; + } + + private String stockPlate; + private Integer isLock; + private Integer isShow; + private Date addTime; + private String nowPrice; + private BigDecimal hcrate; + private BigDecimal day3Rate; + /*点差费率*/ + private BigDecimal spreadRate; + + public void setStockName(String stockName) { + this.stockName = stockName; + } + + public void setStockCode(String stockCode) { + this.stockCode = stockCode; + } + + public void setStockSpell(String stockSpell) { + this.stockSpell = stockSpell; + } + + public void setStockType(String stockType) { + this.stockType = stockType; + } + + public void setStockGid(String stockGid) { + this.stockGid = stockGid; + } + + public void setStockPlate(String stockPlate) { + this.stockPlate = stockPlate; + } + + public void setIsLock(Integer isLock) { + this.isLock = isLock; + } + + public void setIsShow(Integer isShow) { + this.isShow = isShow; + } + + public void setAddTime(Date addTime) { + this.addTime = addTime; + } + + public void setNowPrice(String nowPrice) { + this.nowPrice = nowPrice; + } + + public void setHcrate(BigDecimal hcrate) { + this.hcrate = hcrate; + } + + public void setDay3Rate(BigDecimal day3Rate) { + this.day3Rate = day3Rate; + } + + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof StockAdminListVO)) return false; + StockAdminListVO other = (StockAdminListVO) o; + if (!other.canEqual(this)) return false; + Object this$id = getId(), other$id = other.getId(); + if ((this$id == null) ? (other$id != null) : !this$id.equals(other$id)) return false; + Object this$stockName = getStockName(), other$stockName = other.getStockName(); + if ((this$stockName == null) ? (other$stockName != null) : !this$stockName.equals(other$stockName)) + return false; + Object this$stockCode = getStockCode(), other$stockCode = other.getStockCode(); + if ((this$stockCode == null) ? (other$stockCode != null) : !this$stockCode.equals(other$stockCode)) + return false; + Object this$stockSpell = getStockSpell(), other$stockSpell = other.getStockSpell(); + if ((this$stockSpell == null) ? (other$stockSpell != null) : !this$stockSpell.equals(other$stockSpell)) + return false; + Object this$stockType = getStockType(), other$stockType = other.getStockType(); + if ((this$stockType == null) ? (other$stockType != null) : !this$stockType.equals(other$stockType)) + return false; + Object this$stockGid = getStockGid(), other$stockGid = other.getStockGid(); + if ((this$stockGid == null) ? (other$stockGid != null) : !this$stockGid.equals(other$stockGid)) return false; + Object this$stockPlate = getStockPlate(), other$stockPlate = other.getStockPlate(); + if ((this$stockPlate == null) ? (other$stockPlate != null) : !this$stockPlate.equals(other$stockPlate)) + return false; + Object this$isLock = getIsLock(), other$isLock = other.getIsLock(); + if ((this$isLock == null) ? (other$isLock != null) : !this$isLock.equals(other$isLock)) return false; + Object this$isShow = getIsShow(), other$isShow = other.getIsShow(); + if ((this$isShow == null) ? (other$isShow != null) : !this$isShow.equals(other$isShow)) return false; + Object this$addTime = getAddTime(), other$addTime = other.getAddTime(); + if ((this$addTime == null) ? (other$addTime != null) : !this$addTime.equals(other$addTime)) return false; + Object this$nowPrice = getNowPrice(), other$nowPrice = other.getNowPrice(); + if ((this$nowPrice == null) ? (other$nowPrice != null) : !this$nowPrice.equals(other$nowPrice)) return false; + Object this$hcrate = getHcrate(), other$hcrate = other.getHcrate(); + if ((this$hcrate == null) ? (other$hcrate != null) : !this$hcrate.equals(other$hcrate)) return false; + Object this$day3Rate = getDay3Rate(), other$day3Rate = other.getDay3Rate(); + return !((this$day3Rate == null) ? (other$day3Rate != null) : !this$day3Rate.equals(other$day3Rate)); + } + + protected boolean canEqual(Object other) { + return other instanceof StockAdminListVO; + } + + public int hashCode() { + int PRIME = 59; + int result = 1; + Object $id = getId(); + result = result * 59 + (($id == null) ? 43 : $id.hashCode()); + Object $stockName = getStockName(); + result = result * 59 + (($stockName == null) ? 43 : $stockName.hashCode()); + Object $stockCode = getStockCode(); + result = result * 59 + (($stockCode == null) ? 43 : $stockCode.hashCode()); + Object $stockSpell = getStockSpell(); + result = result * 59 + (($stockSpell == null) ? 43 : $stockSpell.hashCode()); + Object $stockType = getStockType(); + result = result * 59 + (($stockType == null) ? 43 : $stockType.hashCode()); + Object $stockGid = getStockGid(); + result = result * 59 + (($stockGid == null) ? 43 : $stockGid.hashCode()); + Object $stockPlate = getStockPlate(); + result = result * 59 + (($stockPlate == null) ? 43 : $stockPlate.hashCode()); + Object $isLock = getIsLock(); + result = result * 59 + (($isLock == null) ? 43 : $isLock.hashCode()); + Object $isShow = getIsShow(); + result = result * 59 + (($isShow == null) ? 43 : $isShow.hashCode()); + Object $addTime = getAddTime(); + result = result * 59 + (($addTime == null) ? 43 : $addTime.hashCode()); + Object $nowPrice = getNowPrice(); + result = result * 59 + (($nowPrice == null) ? 43 : $nowPrice.hashCode()); + Object $hcrate = getHcrate(); + result = result * 59 + (($hcrate == null) ? 43 : $hcrate.hashCode()); + Object $day3Rate = getDay3Rate(); + return result * 59 + (($day3Rate == null) ? 43 : $day3Rate.hashCode()); + } + + public String toString() { + return "StockAdminListVO(id=" + getId() + ", stockName=" + getStockName() + ", stockCode=" + getStockCode() + ", stockSpell=" + getStockSpell() + ", stockType=" + getStockType() + ", stockGid=" + getStockGid() + ", stockPlate=" + getStockPlate() + ", isLock=" + getIsLock() + ", isShow=" + getIsShow() + ", addTime=" + getAddTime() + ", nowPrice=" + getNowPrice() + ", hcrate=" + getHcrate() + ", day3Rate=" + getDay3Rate() + getHcrate() + ", spreadRate=" + getSpreadRate()+ ")"; + } + + + public Integer getId() { + return this.id; + } + + public String getStockName() { + return this.stockName; + } + + public String getStockCode() { + return this.stockCode; + } + + public String getStockSpell() { + return this.stockSpell; + } + + public String getStockType() { + return this.stockType; + } + + public String getStockGid() { + return this.stockGid; + } + + public String getStockPlate() { + return this.stockPlate; + } + + public Integer getIsLock() { + return this.isLock; + } + + public Integer getIsShow() { + return this.isShow; + } + + public Date getAddTime() { + return this.addTime; + } + + + public String getNowPrice() { + return this.nowPrice; + } + + public BigDecimal getHcrate() { + return this.hcrate; + } + + + public BigDecimal getDay3Rate() { + return this.day3Rate; + } + + public BigDecimal getSpreadRate() { + return spreadRate; + } + + public void setSpreadRate(BigDecimal spreadRate) { + this.spreadRate = spreadRate; + } +} diff --git a/src/main/java/cn/stock/market/dto/model/StockCode.java b/src/main/java/cn/stock/market/dto/model/StockCode.java new file mode 100644 index 0000000..9da5156 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/StockCode.java @@ -0,0 +1,30 @@ +package cn.stock.market.dto.model; + +import cn.stock.market.constant.StockSource; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@SuperBuilder +@EqualsAndHashCode(callSuper = false) +@NoArgsConstructor +@ApiModel +public class StockCode { + String code; + StockSource source; + + public static StockCode a(String code) { + return of(code, StockSource.A); + } + + public static StockCode of(String code, String source) { + return of(code, StockSource.of(source)); + } + + public static StockCode of(String code, StockSource source) { + return StockCode.builder().code(code).source(source).build(); + } +} diff --git a/src/main/java/cn/stock/market/dto/model/StockDetail.java b/src/main/java/cn/stock/market/dto/model/StockDetail.java new file mode 100644 index 0000000..3c77a6c --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/StockDetail.java @@ -0,0 +1,171 @@ +package cn.stock.market.dto.model; + +import java.math.BigDecimal; +import java.util.List; + +import com.ag.utils.vo.KVContainer; +import com.google.common.collect.Lists; + +import cn.qutaojing.common.utils.BigDecimals; +import cn.stock.market.constant.StockSource; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@SuperBuilder +@EqualsAndHashCode(callSuper = false) +@NoArgsConstructor +@ApiModel +public class StockDetail implements IStockPrice { + String code; + String name; + @ApiModelProperty("昨收") + BigDecimal yesterdayPrice; + @ApiModelProperty("开盘价") + BigDecimal openPrice; + @ApiModelProperty("当前价格") + BigDecimal currentPrice; + + @ApiModelProperty("买一") + BigDecimal buyOnePrice; + @ApiModelProperty("买二") + BigDecimal buyTwoPrice; + @ApiModelProperty("买三") + BigDecimal buyThreePrice; + @ApiModelProperty("买四") + BigDecimal buyFourPrice; + @ApiModelProperty("买五") + BigDecimal buyFivePrice; + + @ApiModelProperty("买一量(手)") + BigDecimal buyOneAmount; + @ApiModelProperty("买二量(手)") + BigDecimal buyTwoAmount; + @ApiModelProperty("买三量(手)") + BigDecimal buyThreeAmount; + @ApiModelProperty("买四量(手)") + BigDecimal buyFourAmount; + @ApiModelProperty("买五量(手)") + BigDecimal buyFiveAmount; + + @ApiModelProperty("卖一") + BigDecimal sellOnePrice; + @ApiModelProperty("卖二") + BigDecimal sellTwoPrice; + @ApiModelProperty("卖三") + BigDecimal sellThreePrice; + @ApiModelProperty("卖四") + BigDecimal sellFourPrice; + @ApiModelProperty("卖五") + BigDecimal sellFivePrice; + + @ApiModelProperty("卖一量(手)") + BigDecimal sellOneAmount; + @ApiModelProperty("卖二量(手)") + BigDecimal sellTwoAmount; + @ApiModelProperty("卖三量(手)") + BigDecimal sellThreeAmount; + @ApiModelProperty("卖四量(手)") + BigDecimal sellFourAmount; + @ApiModelProperty("卖五量(手)") + BigDecimal sellFiveAmount; + + @ApiModelProperty("41: 最高") + BigDecimal highest; + @ApiModelProperty("42: 最低") + BigDecimal lowest; + @ApiModelProperty("36: 成交量(手)") + BigDecimal volume; + @ApiModelProperty("37: 成交额(万)") + BigDecimal turnover; + String time; + + @ApiModelProperty("换手率") + BigDecimal turnoverRate; + @ApiModelProperty("39: 市盈率") + BigDecimal peRatio; + @ApiModelProperty("流通市值") + BigDecimal circulationMarketValue; + @ApiModelProperty("总市值") + BigDecimal totalMarketValue; + @ApiModelProperty("市净率") + BigDecimal pbRatio; + @ApiModelProperty("43: 振幅") + BigDecimal amplitude; + String jys; + + @ApiModelProperty("47: 涨停价") + String hardenPrice; + @ApiModelProperty("48: 跌停价") + String dropPrice; + + @ApiModelProperty("涨跌额") + BigDecimal priceRange; + @ApiModelProperty("涨跌比") + BigDecimal priceRate; + + public StockInfo thumb() { + return StockInfo.builder() + .buy(buy()) + .code(code) + .jsy(jys) + .name(name) + .price(currentPrice) + .priceRange(priceRange) + .priceRate(priceRate) + .sell(sell()) + .source(StockSource.A) + .yesterdayPrice(yesterdayPrice) + .build(); + } + + BigDecimal unitConversion(BigDecimal decimal) { + return BigDecimals.multiplys(decimal, 100); + } + + @Override + public List> sell() { + List> pList = Lists.newArrayList( + KVContainer.from(getSellOnePrice(), unitConversion(getSellOneAmount())), + KVContainer.from(getSellTwoPrice(), unitConversion(getSellTwoAmount())), + KVContainer.from(getSellThreePrice(), unitConversion(getSellThreeAmount())), + KVContainer.from(getSellFourPrice(), unitConversion(getSellFourAmount())), + KVContainer.from(getSellFivePrice(), unitConversion(getSellFiveAmount()))); + return pList; + } + + @Override + public List> buy() { + List> pList = Lists.newArrayList( + KVContainer.from(getBuyOnePrice(), unitConversion(getBuyOneAmount())), + KVContainer.from(getBuyTwoPrice(), unitConversion(getBuyTwoAmount())), + KVContainer.from(getBuyThreePrice(), unitConversion(getBuyThreeAmount())), + KVContainer.from(getBuyFourPrice(), unitConversion(getBuyFourAmount())), + KVContainer.from(getBuyFivePrice(), unitConversion(getBuyFiveAmount()))); + return pList; + } + + @Override + public BigDecimal price() { + return currentPrice; + } + + @Override + public BigDecimal yesterdayPrice() { + return yesterdayPrice; + } + + @Override + public BigDecimal priceRange() { + return priceRange; + } + + @Override + public BigDecimal priceRate() { + return priceRate; + } +} diff --git a/src/main/java/cn/stock/market/dto/model/StockDetailThumb.java b/src/main/java/cn/stock/market/dto/model/StockDetailThumb.java new file mode 100644 index 0000000..c0782f8 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/StockDetailThumb.java @@ -0,0 +1,38 @@ +package cn.stock.market.dto.model; + +import java.math.BigDecimal; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@SuperBuilder +@EqualsAndHashCode(callSuper = false) +@NoArgsConstructor +@ApiModel +public class StockDetailThumb { + String code; + String name; + @ApiModelProperty("昨收") + BigDecimal yesterdayPrice; + @ApiModelProperty("开盘价") + BigDecimal openPrice; + @ApiModelProperty("当前价格") + BigDecimal currentPrice; + + BigDecimal highest; + BigDecimal lowest; + BigDecimal volume; + BigDecimal turnover; + String time; + String jys; + + @ApiModelProperty("涨跌额") + BigDecimal priceRange; + @ApiModelProperty("涨跌比") + BigDecimal priceRate; +} diff --git a/src/main/java/cn/stock/market/dto/model/StockInfo.java b/src/main/java/cn/stock/market/dto/model/StockInfo.java new file mode 100644 index 0000000..eb4941e --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/StockInfo.java @@ -0,0 +1,56 @@ +package cn.stock.market.dto.model; + +import java.math.BigDecimal; +import java.util.List; + +import com.ag.utils.vo.KVContainer; + +import cn.stock.market.constant.StockSource; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@SuperBuilder +@EqualsAndHashCode(callSuper = false) +@NoArgsConstructor +@ApiModel +public class StockInfo implements IStockPrice { + BigDecimal yesterdayPrice; + BigDecimal price; + BigDecimal priceRange; + BigDecimal priceRate; + List> sell; + List> buy; + + String code; + String name; + StockSource source; + String jsy; + @Override + public BigDecimal yesterdayPrice() { + return yesterdayPrice; + } + @Override + public BigDecimal price() { + return price; + } + @Override + public List> sell() { + return sell; + } + @Override + public List> buy() { + return buy; + } + @Override + public BigDecimal priceRange() { + return priceRange; + } + @Override + public BigDecimal priceRate() { + return priceRate; + } +} diff --git a/src/main/java/cn/stock/market/dto/model/StockListVO.java b/src/main/java/cn/stock/market/dto/model/StockListVO.java new file mode 100644 index 0000000..27b67f1 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/StockListVO.java @@ -0,0 +1,258 @@ +package cn.stock.market.dto.model; + + +import java.math.BigDecimal; + + +public class StockListVO { + + private String name; + + private String code; + + private String spell; + + private String gid; + + private String nowPrice; + + private BigDecimal hcrate; + + private String today_max; + + public void setName(String name) { + this.name = name; + } + + private String today_min; + private String business_balance; + private String business_amount; + private String preclose_px; + private String open_px; + private BigDecimal day3Rate; + private String stock_type; + private String stock_plate; + /*是否添加自选:1、添加自选,0、未添加自选*/ + private String isOption; + + public void setCode(String code) { + this.code = code; + } + + public void setSpell(String spell) { + this.spell = spell; + } + + public void setGid(String gid) { + this.gid = gid; + } + + public void setNowPrice(String nowPrice) { + this.nowPrice = nowPrice; + } + + public void setHcrate(BigDecimal hcrate) { + this.hcrate = hcrate; + } + + public void setToday_max(String today_max) { + this.today_max = today_max; + } + + public void setToday_min(String today_min) { + this.today_min = today_min; + } + + public void setBusiness_balance(String business_balance) { + this.business_balance = business_balance; + } + + public void setBusiness_amount(String business_amount) { + this.business_amount = business_amount; + } + + public void setPreclose_px(String preclose_px) { + this.preclose_px = preclose_px; + } + + public void setOpen_px(String open_px) { + this.open_px = open_px; + } + + public void setDay3Rate(BigDecimal day3Rate) { + this.day3Rate = day3Rate; + } + + public void setStock_type(String stock_type) { + this.stock_type = stock_type; + } + + public void setStock_plate(String stock_plate) { + this.stock_plate = stock_plate; + } + + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof StockListVO)) return false; + StockListVO other = (StockListVO) o; + if (!other.canEqual(this)) return false; + Object this$name = getName(), other$name = other.getName(); + if ((this$name == null) ? (other$name != null) : !this$name.equals(other$name)) return false; + Object this$code = getCode(), other$code = other.getCode(); + if ((this$code == null) ? (other$code != null) : !this$code.equals(other$code)) return false; + Object this$spell = getSpell(), other$spell = other.getSpell(); + if ((this$spell == null) ? (other$spell != null) : !this$spell.equals(other$spell)) return false; + Object this$gid = getGid(), other$gid = other.getGid(); + if ((this$gid == null) ? (other$gid != null) : !this$gid.equals(other$gid)) return false; + Object this$nowPrice = getNowPrice(), other$nowPrice = other.getNowPrice(); + if ((this$nowPrice == null) ? (other$nowPrice != null) : !this$nowPrice.equals(other$nowPrice)) return false; + Object this$hcrate = getHcrate(), other$hcrate = other.getHcrate(); + if ((this$hcrate == null) ? (other$hcrate != null) : !this$hcrate.equals(other$hcrate)) return false; + Object this$today_max = getToday_max(), other$today_max = other.getToday_max(); + if ((this$today_max == null) ? (other$today_max != null) : !this$today_max.equals(other$today_max)) + return false; + Object this$today_min = getToday_min(), other$today_min = other.getToday_min(); + if ((this$today_min == null) ? (other$today_min != null) : !this$today_min.equals(other$today_min)) + return false; + Object this$business_balance = getBusiness_balance(), other$business_balance = other.getBusiness_balance(); + if ((this$business_balance == null) ? (other$business_balance != null) : !this$business_balance.equals(other$business_balance)) + return false; + Object this$business_amount = getBusiness_amount(), other$business_amount = other.getBusiness_amount(); + if ((this$business_amount == null) ? (other$business_amount != null) : !this$business_amount.equals(other$business_amount)) + return false; + Object this$preclose_px = getPreclose_px(), other$preclose_px = other.getPreclose_px(); + if ((this$preclose_px == null) ? (other$preclose_px != null) : !this$preclose_px.equals(other$preclose_px)) + return false; + Object this$open_px = getOpen_px(), other$open_px = other.getOpen_px(); + if ((this$open_px == null) ? (other$open_px != null) : !this$open_px.equals(other$open_px)) return false; + Object this$day3Rate = getDay3Rate(), other$day3Rate = other.getDay3Rate(); + if ((this$day3Rate == null) ? (other$day3Rate != null) : !this$day3Rate.equals(other$day3Rate)) return false; + Object this$stock_type = getStock_type(), other$stock_type = other.getStock_type(); + if ((this$stock_type == null) ? (other$stock_type != null) : !this$stock_type.equals(other$stock_type)) + return false; + Object this$stock_plate = getStock_plate(), other$stock_plate = other.getStock_plate(); + return !((this$stock_plate == null) ? (other$stock_plate != null) : !this$stock_plate.equals(other$stock_plate)); + } + + protected boolean canEqual(Object other) { + return other instanceof StockListVO; + } + + public int hashCode() { + int PRIME = 59; + int result = 1; + Object $name = getName(); + result = result * 59 + (($name == null) ? 43 : $name.hashCode()); + Object $code = getCode(); + result = result * 59 + (($code == null) ? 43 : $code.hashCode()); + Object $spell = getSpell(); + result = result * 59 + (($spell == null) ? 43 : $spell.hashCode()); + Object $gid = getGid(); + result = result * 59 + (($gid == null) ? 43 : $gid.hashCode()); + Object $nowPrice = getNowPrice(); + result = result * 59 + (($nowPrice == null) ? 43 : $nowPrice.hashCode()); + Object $hcrate = getHcrate(); + result = result * 59 + (($hcrate == null) ? 43 : $hcrate.hashCode()); + Object $today_max = getToday_max(); + result = result * 59 + (($today_max == null) ? 43 : $today_max.hashCode()); + Object $today_min = getToday_min(); + result = result * 59 + (($today_min == null) ? 43 : $today_min.hashCode()); + Object $business_balance = getBusiness_balance(); + result = result * 59 + (($business_balance == null) ? 43 : $business_balance.hashCode()); + Object $business_amount = getBusiness_amount(); + result = result * 59 + (($business_amount == null) ? 43 : $business_amount.hashCode()); + Object $preclose_px = getPreclose_px(); + result = result * 59 + (($preclose_px == null) ? 43 : $preclose_px.hashCode()); + Object $open_px = getOpen_px(); + result = result * 59 + (($open_px == null) ? 43 : $open_px.hashCode()); + Object $day3Rate = getDay3Rate(); + result = result * 59 + (($day3Rate == null) ? 43 : $day3Rate.hashCode()); + Object $stock_type = getStock_type(); + result = result * 59 + (($stock_type == null) ? 43 : $stock_type.hashCode()); + Object $stock_plate = getStock_plate(); + return result * 59 + (($stock_plate == null) ? 43 : $stock_plate.hashCode()); + } + + public String toString() { + return "StockListVO(name=" + getName() + ", code=" + getCode() + ", spell=" + getSpell() + ", gid=" + getGid() + ", nowPrice=" + getNowPrice() + ", hcrate=" + getHcrate() + ", today_max=" + getToday_max() + ", today_min=" + getToday_min() + ", business_balance=" + getBusiness_balance() + ", business_amount=" + getBusiness_amount() + ", preclose_px=" + getPreclose_px() + ", open_px=" + getOpen_px() + ", day3Rate=" + getDay3Rate() + ", stock_type=" + getStock_type() + ", stock_plate=" + getStock_plate() + ")"; + } + + + public String getName() { + return this.name; + } + + public String getCode() { + return this.code; + } + + public String getSpell() { + return this.spell; + } + + public String getGid() { + return this.gid; + } + + + public String getNowPrice() { + return this.nowPrice; + } + + + public BigDecimal getHcrate() { + return this.hcrate; + } + + + public String getToday_max() { + return this.today_max; + } + + + public String getToday_min() { + return this.today_min; + } + + + public String getBusiness_balance() { + return this.business_balance; + } + + + public String getBusiness_amount() { + return this.business_amount; + } + + + public String getPreclose_px() { + return this.preclose_px; + } + + + public String getOpen_px() { + return this.open_px; + } + + + public BigDecimal getDay3Rate() { + return this.day3Rate; + } + + + public String getStock_type() { + return this.stock_type; + } + + public String getStock_plate() { + return this.stock_plate; + } + + public String getIsOption() { + return isOption; + } + + public void setIsOption(String isOption) { + this.isOption = isOption; + } +} diff --git a/src/main/java/cn/stock/market/dto/model/StockPrice.java b/src/main/java/cn/stock/market/dto/model/StockPrice.java new file mode 100644 index 0000000..69bafd2 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/StockPrice.java @@ -0,0 +1,23 @@ +package cn.stock.market.dto.model; + +import java.math.BigDecimal; + +public class StockPrice implements IStockPrice { + BigDecimal price; + + @Override + public BigDecimal price() { + return price; + } + + @Override + public BigDecimal yesterdayPrice() { + return price; + } + + public static StockPrice of(BigDecimal price) { + StockPrice p = new StockPrice(); + p.price = price; + return p; + } +} diff --git a/src/main/java/cn/stock/market/dto/model/StockThumb.java b/src/main/java/cn/stock/market/dto/model/StockThumb.java new file mode 100644 index 0000000..af5bcc1 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/StockThumb.java @@ -0,0 +1,34 @@ +package cn.stock.market.dto.model; + +import com.alibaba.fastjson.JSONObject; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class StockThumb { + Integer id; + String source; + /** + * 股票名称 + */ + String name; + /** + * 股票代码 + */ + String code; + /** + * 股票简拼 + */ + String pinyin; + String jys; + + String market; + + JSONObject ext; +} diff --git a/src/main/java/cn/stock/market/dto/model/StockVO.java b/src/main/java/cn/stock/market/dto/model/StockVO.java new file mode 100644 index 0000000..45e088d --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/StockVO.java @@ -0,0 +1,605 @@ + +package cn.stock.market.dto.model; + +import java.math.BigDecimal; + +import cn.stock.market.domain.basic.entity.Stock; +import cn.stock.market.utils.Utils; + +public class StockVO { + private int id; + private String name; + private String code; + private String spell; + private String gid; + private String nowPrice; + private BigDecimal hcrate; + private String today_max; + private String today_min; + + private String business_balance; + + private String business_amount; + + private String preclose_px; + + private String open_px; + + private String buy1; + + private String buy2; + + private String buy3; + + private String buy4; + + private String buy5; + + + public void setId(int id) { + this.id = id; + } + + private String sell1; + private String sell2; + private String sell3; + private String sell4; + private String sell5; + private String buy1_num; + private String buy2_num; + private String buy3_num; + private String buy4_num; + private String buy5_num; + private String sell1_num; + private String sell2_num; + private String sell3_num; + private String sell4_num; + private String sell5_num; + private String minImg; + private String dayImg; + private String weekImg; + private String monthImg; + + private Integer depositAmt; + + public static StockVO from(StockDetail detail, Stock stock) { + StockVO vo = new StockVO(); + if(stock != null) { + vo.setId(stock.getId()); + vo.setCode(stock.getStockCode()); + vo.setSpell(stock.getStockSpell()); + vo.setGid(stock.getStockGid()); + } + + vo.setName(detail.getName()); + vo.setCode(detail.getCode()); +// vo.setGid(Utils.fenxi(detail.getCode())); + vo.setNowPrice(String.valueOf(detail.getCurrentPrice())); + vo.setHcrate(detail.getPriceRate().setScale(2)); + vo.setToday_max(String.valueOf(detail.getHighest())); + vo.setToday_min(String.valueOf(detail.getLowest())); + + vo.setBuy1(String.valueOf(detail.getBuyOnePrice())); + vo.setBuy2(String.valueOf(detail.getBuyTwoPrice())); + vo.setBuy3(String.valueOf(detail.getBuyThreePrice())); + vo.setBuy4(String.valueOf(detail.getBuyFourPrice())); + vo.setBuy5(String.valueOf(detail.getBuyFivePrice())); + + vo.setSell1(String.valueOf(detail.getSellOnePrice())); + vo.setSell2(String.valueOf(detail.getSellTwoPrice())); + vo.setSell3(String.valueOf(detail.getSellThreePrice())); + vo.setSell4(String.valueOf(detail.getSellFourPrice())); + vo.setSell5(String.valueOf(detail.getSellFivePrice())); + + vo.setBuy1_num(String.valueOf(detail.getBuyOneAmount())); + vo.setBuy2_num(String.valueOf(detail.getBuyTwoAmount())); + vo.setBuy3_num(String.valueOf(detail.getBuyThreeAmount())); + vo.setBuy4_num(String.valueOf(detail.getBuyFourAmount())); + vo.setBuy5_num(String.valueOf(detail.getBuyFiveAmount())); + + vo.setSell1_num(String.valueOf(detail.getSellOneAmount())); + vo.setSell2_num(String.valueOf(detail.getSellTwoAmount())); + vo.setSell3_num(String.valueOf(detail.getSellThreeAmount())); + vo.setSell4_num(String.valueOf(detail.getSellFourAmount())); + vo.setSell5_num(String.valueOf(detail.getSellFiveAmount())); + + vo.setOpen_px(String.valueOf(detail.getOpenPrice())); + vo.setPreclose_px(String.valueOf(detail.getYesterdayPrice())); + vo.setBusiness_balance(String.valueOf(detail.getTurnover())); + vo.setBusiness_amount(String.valueOf(detail.getVolume())); + + return vo; + } + + public void setName(String name) { + this.name = name; + } + + public void setCode(String code) { + this.code = code; + } + + public void setSpell(String spell) { + this.spell = spell; + } + + public void setGid(String gid) { + this.gid = gid; + } + + public void setNowPrice(String nowPrice) { + this.nowPrice = nowPrice; + } + + public void setHcrate(BigDecimal hcrate) { + this.hcrate = hcrate; + } + + public void setToday_max(String today_max) { + this.today_max = today_max; + } + + public void setToday_min(String today_min) { + this.today_min = today_min; + } + + public void setBusiness_balance(String business_balance) { + this.business_balance = business_balance; + } + + public void setBusiness_amount(String business_amount) { + this.business_amount = business_amount; + } + + public void setPreclose_px(String preclose_px) { + this.preclose_px = preclose_px; + } + + public void setOpen_px(String open_px) { + this.open_px = open_px; + } + + public void setBuy1(String buy1) { + this.buy1 = buy1; + } + + public void setBuy2(String buy2) { + this.buy2 = buy2; + } + + public void setBuy3(String buy3) { + this.buy3 = buy3; + } + + public void setBuy4(String buy4) { + this.buy4 = buy4; + } + + public void setBuy5(String buy5) { + this.buy5 = buy5; + } + + public void setSell1(String sell1) { + this.sell1 = sell1; + } + + public void setSell2(String sell2) { + this.sell2 = sell2; + } + + public void setSell3(String sell3) { + this.sell3 = sell3; + } + + public void setSell4(String sell4) { + this.sell4 = sell4; + } + + public void setSell5(String sell5) { + this.sell5 = sell5; + } + + public void setBuy1_num(String buy1_num) { + this.buy1_num = buy1_num; + } + + public void setBuy2_num(String buy2_num) { + this.buy2_num = buy2_num; + } + + public void setBuy3_num(String buy3_num) { + this.buy3_num = buy3_num; + } + + public void setBuy4_num(String buy4_num) { + this.buy4_num = buy4_num; + } + + public void setBuy5_num(String buy5_num) { + this.buy5_num = buy5_num; + } + + public void setSell1_num(String sell1_num) { + this.sell1_num = sell1_num; + } + + public void setSell2_num(String sell2_num) { + this.sell2_num = sell2_num; + } + + public void setSell3_num(String sell3_num) { + this.sell3_num = sell3_num; + } + + public void setSell4_num(String sell4_num) { + this.sell4_num = sell4_num; + } + + public void setSell5_num(String sell5_num) { + this.sell5_num = sell5_num; + } + + public void setMinImg(String minImg) { + this.minImg = minImg; + } + + public void setDayImg(String dayImg) { + this.dayImg = dayImg; + } + + public void setWeekImg(String weekImg) { + this.weekImg = weekImg; + } + + public void setMonthImg(String monthImg) { + this.monthImg = monthImg; + } + + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof StockVO)) return false; + StockVO other = (StockVO) o; + if (!other.canEqual(this)) return false; + if (getId() != other.getId()) return false; + Object this$name = getName(), other$name = other.getName(); + if ((this$name == null) ? (other$name != null) : !this$name.equals(other$name)) return false; + Object this$code = getCode(), other$code = other.getCode(); + if ((this$code == null) ? (other$code != null) : !this$code.equals(other$code)) return false; + Object this$spell = getSpell(), other$spell = other.getSpell(); + if ((this$spell == null) ? (other$spell != null) : !this$spell.equals(other$spell)) return false; + Object this$gid = getGid(), other$gid = other.getGid(); + if ((this$gid == null) ? (other$gid != null) : !this$gid.equals(other$gid)) return false; + Object this$nowPrice = getNowPrice(), other$nowPrice = other.getNowPrice(); + if ((this$nowPrice == null) ? (other$nowPrice != null) : !this$nowPrice.equals(other$nowPrice)) return false; + Object this$hcrate = getHcrate(), other$hcrate = other.getHcrate(); + if ((this$hcrate == null) ? (other$hcrate != null) : !this$hcrate.equals(other$hcrate)) return false; + Object this$today_max = getToday_max(), other$today_max = other.getToday_max(); + if ((this$today_max == null) ? (other$today_max != null) : !this$today_max.equals(other$today_max)) + return false; + Object this$today_min = getToday_min(), other$today_min = other.getToday_min(); + if ((this$today_min == null) ? (other$today_min != null) : !this$today_min.equals(other$today_min)) + return false; + Object this$business_balance = getBusiness_balance(), other$business_balance = other.getBusiness_balance(); + if ((this$business_balance == null) ? (other$business_balance != null) : !this$business_balance.equals(other$business_balance)) + return false; + Object this$business_amount = getBusiness_amount(), other$business_amount = other.getBusiness_amount(); + if ((this$business_amount == null) ? (other$business_amount != null) : !this$business_amount.equals(other$business_amount)) + return false; + Object this$preclose_px = getPreclose_px(), other$preclose_px = other.getPreclose_px(); + if ((this$preclose_px == null) ? (other$preclose_px != null) : !this$preclose_px.equals(other$preclose_px)) + return false; + Object this$open_px = getOpen_px(), other$open_px = other.getOpen_px(); + if ((this$open_px == null) ? (other$open_px != null) : !this$open_px.equals(other$open_px)) return false; + Object this$buy1 = getBuy1(), other$buy1 = other.getBuy1(); + if ((this$buy1 == null) ? (other$buy1 != null) : !this$buy1.equals(other$buy1)) return false; + Object this$buy2 = getBuy2(), other$buy2 = other.getBuy2(); + if ((this$buy2 == null) ? (other$buy2 != null) : !this$buy2.equals(other$buy2)) return false; + Object this$buy3 = getBuy3(), other$buy3 = other.getBuy3(); + if ((this$buy3 == null) ? (other$buy3 != null) : !this$buy3.equals(other$buy3)) return false; + Object this$buy4 = getBuy4(), other$buy4 = other.getBuy4(); + if ((this$buy4 == null) ? (other$buy4 != null) : !this$buy4.equals(other$buy4)) return false; + Object this$buy5 = getBuy5(), other$buy5 = other.getBuy5(); + if ((this$buy5 == null) ? (other$buy5 != null) : !this$buy5.equals(other$buy5)) return false; + Object this$sell1 = getSell1(), other$sell1 = other.getSell1(); + if ((this$sell1 == null) ? (other$sell1 != null) : !this$sell1.equals(other$sell1)) return false; + Object this$sell2 = getSell2(), other$sell2 = other.getSell2(); + if ((this$sell2 == null) ? (other$sell2 != null) : !this$sell2.equals(other$sell2)) return false; + Object this$sell3 = getSell3(), other$sell3 = other.getSell3(); + if ((this$sell3 == null) ? (other$sell3 != null) : !this$sell3.equals(other$sell3)) return false; + Object this$sell4 = getSell4(), other$sell4 = other.getSell4(); + if ((this$sell4 == null) ? (other$sell4 != null) : !this$sell4.equals(other$sell4)) return false; + Object this$sell5 = getSell5(), other$sell5 = other.getSell5(); + if ((this$sell5 == null) ? (other$sell5 != null) : !this$sell5.equals(other$sell5)) return false; + Object this$buy1_num = getBuy1_num(), other$buy1_num = other.getBuy1_num(); + if ((this$buy1_num == null) ? (other$buy1_num != null) : !this$buy1_num.equals(other$buy1_num)) return false; + Object this$buy2_num = getBuy2_num(), other$buy2_num = other.getBuy2_num(); + if ((this$buy2_num == null) ? (other$buy2_num != null) : !this$buy2_num.equals(other$buy2_num)) return false; + Object this$buy3_num = getBuy3_num(), other$buy3_num = other.getBuy3_num(); + if ((this$buy3_num == null) ? (other$buy3_num != null) : !this$buy3_num.equals(other$buy3_num)) return false; + Object this$buy4_num = getBuy4_num(), other$buy4_num = other.getBuy4_num(); + if ((this$buy4_num == null) ? (other$buy4_num != null) : !this$buy4_num.equals(other$buy4_num)) return false; + Object this$buy5_num = getBuy5_num(), other$buy5_num = other.getBuy5_num(); + if ((this$buy5_num == null) ? (other$buy5_num != null) : !this$buy5_num.equals(other$buy5_num)) return false; + Object this$sell1_num = getSell1_num(), other$sell1_num = other.getSell1_num(); + if ((this$sell1_num == null) ? (other$sell1_num != null) : !this$sell1_num.equals(other$sell1_num)) + return false; + Object this$sell2_num = getSell2_num(), other$sell2_num = other.getSell2_num(); + if ((this$sell2_num == null) ? (other$sell2_num != null) : !this$sell2_num.equals(other$sell2_num)) + return false; + Object this$sell3_num = getSell3_num(), other$sell3_num = other.getSell3_num(); + if ((this$sell3_num == null) ? (other$sell3_num != null) : !this$sell3_num.equals(other$sell3_num)) + return false; + Object this$sell4_num = getSell4_num(), other$sell4_num = other.getSell4_num(); + if ((this$sell4_num == null) ? (other$sell4_num != null) : !this$sell4_num.equals(other$sell4_num)) + return false; + Object this$sell5_num = getSell5_num(), other$sell5_num = other.getSell5_num(); + if ((this$sell5_num == null) ? (other$sell5_num != null) : !this$sell5_num.equals(other$sell5_num)) + return false; + Object this$minImg = getMinImg(), other$minImg = other.getMinImg(); + if ((this$minImg == null) ? (other$minImg != null) : !this$minImg.equals(other$minImg)) return false; + Object this$dayImg = getDayImg(), other$dayImg = other.getDayImg(); + if ((this$dayImg == null) ? (other$dayImg != null) : !this$dayImg.equals(other$dayImg)) return false; + Object this$weekImg = getWeekImg(), other$weekImg = other.getWeekImg(); + if ((this$weekImg == null) ? (other$weekImg != null) : !this$weekImg.equals(other$weekImg)) return false; + Object this$monthImg = getMonthImg(), other$monthImg = other.getMonthImg(); + return !((this$monthImg == null) ? (other$monthImg != null) : !this$monthImg.equals(other$monthImg)); + } + + protected boolean canEqual(Object other) { + return other instanceof StockVO; + } + + public int hashCode() { + int PRIME = 59; + int result = 1; + result = result * 59 + getId(); + Object $name = getName(); + result = result * 59 + (($name == null) ? 43 : $name.hashCode()); + Object $code = getCode(); + result = result * 59 + (($code == null) ? 43 : $code.hashCode()); + Object $spell = getSpell(); + result = result * 59 + (($spell == null) ? 43 : $spell.hashCode()); + Object $gid = getGid(); + result = result * 59 + (($gid == null) ? 43 : $gid.hashCode()); + Object $nowPrice = getNowPrice(); + result = result * 59 + (($nowPrice == null) ? 43 : $nowPrice.hashCode()); + Object $hcrate = getHcrate(); + result = result * 59 + (($hcrate == null) ? 43 : $hcrate.hashCode()); + Object $today_max = getToday_max(); + result = result * 59 + (($today_max == null) ? 43 : $today_max.hashCode()); + Object $today_min = getToday_min(); + result = result * 59 + (($today_min == null) ? 43 : $today_min.hashCode()); + Object $business_balance = getBusiness_balance(); + result = result * 59 + (($business_balance == null) ? 43 : $business_balance.hashCode()); + Object $business_amount = getBusiness_amount(); + result = result * 59 + (($business_amount == null) ? 43 : $business_amount.hashCode()); + Object $preclose_px = getPreclose_px(); + result = result * 59 + (($preclose_px == null) ? 43 : $preclose_px.hashCode()); + Object $open_px = getOpen_px(); + result = result * 59 + (($open_px == null) ? 43 : $open_px.hashCode()); + Object $buy1 = getBuy1(); + result = result * 59 + (($buy1 == null) ? 43 : $buy1.hashCode()); + Object $buy2 = getBuy2(); + result = result * 59 + (($buy2 == null) ? 43 : $buy2.hashCode()); + Object $buy3 = getBuy3(); + result = result * 59 + (($buy3 == null) ? 43 : $buy3.hashCode()); + Object $buy4 = getBuy4(); + result = result * 59 + (($buy4 == null) ? 43 : $buy4.hashCode()); + Object $buy5 = getBuy5(); + result = result * 59 + (($buy5 == null) ? 43 : $buy5.hashCode()); + Object $sell1 = getSell1(); + result = result * 59 + (($sell1 == null) ? 43 : $sell1.hashCode()); + Object $sell2 = getSell2(); + result = result * 59 + (($sell2 == null) ? 43 : $sell2.hashCode()); + Object $sell3 = getSell3(); + result = result * 59 + (($sell3 == null) ? 43 : $sell3.hashCode()); + Object $sell4 = getSell4(); + result = result * 59 + (($sell4 == null) ? 43 : $sell4.hashCode()); + Object $sell5 = getSell5(); + result = result * 59 + (($sell5 == null) ? 43 : $sell5.hashCode()); + Object $buy1_num = getBuy1_num(); + result = result * 59 + (($buy1_num == null) ? 43 : $buy1_num.hashCode()); + Object $buy2_num = getBuy2_num(); + result = result * 59 + (($buy2_num == null) ? 43 : $buy2_num.hashCode()); + Object $buy3_num = getBuy3_num(); + result = result * 59 + (($buy3_num == null) ? 43 : $buy3_num.hashCode()); + Object $buy4_num = getBuy4_num(); + result = result * 59 + (($buy4_num == null) ? 43 : $buy4_num.hashCode()); + Object $buy5_num = getBuy5_num(); + result = result * 59 + (($buy5_num == null) ? 43 : $buy5_num.hashCode()); + Object $sell1_num = getSell1_num(); + result = result * 59 + (($sell1_num == null) ? 43 : $sell1_num.hashCode()); + Object $sell2_num = getSell2_num(); + result = result * 59 + (($sell2_num == null) ? 43 : $sell2_num.hashCode()); + Object $sell3_num = getSell3_num(); + result = result * 59 + (($sell3_num == null) ? 43 : $sell3_num.hashCode()); + Object $sell4_num = getSell4_num(); + result = result * 59 + (($sell4_num == null) ? 43 : $sell4_num.hashCode()); + Object $sell5_num = getSell5_num(); + result = result * 59 + (($sell5_num == null) ? 43 : $sell5_num.hashCode()); + Object $minImg = getMinImg(); + result = result * 59 + (($minImg == null) ? 43 : $minImg.hashCode()); + Object $dayImg = getDayImg(); + result = result * 59 + (($dayImg == null) ? 43 : $dayImg.hashCode()); + Object $weekImg = getWeekImg(); + result = result * 59 + (($weekImg == null) ? 43 : $weekImg.hashCode()); + Object $monthImg = getMonthImg(); + return result * 59 + (($monthImg == null) ? 43 : $monthImg.hashCode()); + } + + public String toString() { + return "StockVO(id=" + getId() + ", name=" + getName() + ", code=" + getCode() + ", spell=" + getSpell() + ", gid=" + getGid() + ", nowPrice=" + getNowPrice() + ", hcrate=" + getHcrate() + ", today_max=" + getToday_max() + ", today_min=" + getToday_min() + ", business_balance=" + getBusiness_balance() + ", business_amount=" + getBusiness_amount() + ", preclose_px=" + getPreclose_px() + ", open_px=" + getOpen_px() + ", buy1=" + getBuy1() + ", buy2=" + getBuy2() + ", buy3=" + getBuy3() + ", buy4=" + getBuy4() + ", buy5=" + getBuy5() + ", sell1=" + getSell1() + ", sell2=" + getSell2() + ", sell3=" + getSell3() + ", sell4=" + getSell4() + ", sell5=" + getSell5() + ", buy1_num=" + getBuy1_num() + ", buy2_num=" + getBuy2_num() + ", buy3_num=" + getBuy3_num() + ", buy4_num=" + getBuy4_num() + ", buy5_num=" + getBuy5_num() + ", sell1_num=" + getSell1_num() + ", sell2_num=" + getSell2_num() + ", sell3_num=" + getSell3_num() + ", sell4_num=" + getSell4_num() + ", sell5_num=" + getSell5_num() + ", minImg=" + getMinImg() + ", dayImg=" + getDayImg() + ", weekImg=" + getWeekImg() + ", monthImg=" + getMonthImg()+ ", depositAmt=" + getDepositAmt() + ")"; + } + + + public int getId() { + return this.id; + } + + + public String getName() { + return this.name; + } + + public String getCode() { + return this.code; + } + + public String getSpell() { + return this.spell; + } + + public String getGid() { + return this.gid; + } + + + public String getNowPrice() { + return this.nowPrice; + } + + + public BigDecimal getHcrate() { + return this.hcrate; + } + + + public String getToday_max() { + return this.today_max; + } + + + public String getToday_min() { + return this.today_min; + } + + + public String getBusiness_balance() { + return this.business_balance; + } + + + public String getBusiness_amount() { + return this.business_amount; + } + + + public String getPreclose_px() { + return this.preclose_px; + } + + + public String getOpen_px() { + return this.open_px; + } + + + public String getBuy1() { + return this.buy1; + } + + public String getBuy2() { + return this.buy2; + } + + public String getBuy3() { + return this.buy3; + } + + public String getBuy4() { + return this.buy4; + } + + public String getBuy5() { + return this.buy5; + } + + + public String getSell1() { + return this.sell1; + } + + public String getSell2() { + return this.sell2; + } + + public String getSell3() { + return this.sell3; + } + + public String getSell4() { + return this.sell4; + } + + public String getSell5() { + return this.sell5; + } + + + public String getBuy1_num() { + return this.buy1_num; + } + + public String getBuy2_num() { + return this.buy2_num; + } + + public String getBuy3_num() { + return this.buy3_num; + } + + public String getBuy4_num() { + return this.buy4_num; + } + + public String getBuy5_num() { + return this.buy5_num; + } + + + public String getSell1_num() { + return this.sell1_num; + } + + public String getSell2_num() { + return this.sell2_num; + } + + public String getSell3_num() { + return this.sell3_num; + } + + public String getSell4_num() { + return this.sell4_num; + } + + public String getSell5_num() { + return this.sell5_num; + } + + + public String getMinImg() { + return this.minImg; + } + + public String getDayImg() { + return this.dayImg; + } + + public String getWeekImg() { + return this.weekImg; + } + + public String getMonthImg() { + return this.monthImg; + } + + public Integer getDepositAmt() { + return depositAmt; + } + + public void setDepositAmt(Integer depositAmt) { + this.depositAmt = depositAmt; + } +} + diff --git a/src/main/java/cn/stock/market/dto/model/Tax.java b/src/main/java/cn/stock/market/dto/model/Tax.java new file mode 100644 index 0000000..9a9cb56 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/Tax.java @@ -0,0 +1,188 @@ +package cn.stock.market.dto.model; + +import java.lang.reflect.Field; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.List; + +import com.ag.utils.CollectionUtils; +import com.google.common.collect.Lists; + +import cn.qutaojing.common.utils.BigDecimals; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@ApiModel("交易收费") +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class Tax { + @ApiModelProperty("平台汇总") + public BigDecimal platformSum; + @ApiModelProperty("三方汇总") + public BigDecimal thirtySum; + @ApiModelProperty("总汇总") + public BigDecimal totalSum; + + /** + * 印花税 + */ + @ApiModelProperty("印花税") + public BigDecimal stampTax; + /** + * 佣金 + */ + @ApiModelProperty("交易佣金") + public BigDecimal commission; + + @ApiModelProperty("平台费") + public BigDecimal platformTax; + + @ApiModelProperty("產品處理費") + public BigDecimal productHandlerTax; + @ApiModelProperty("證券管理費") + public BigDecimal securitiesManageTax; + @ApiModelProperty("交易活動費") + public BigDecimal tradeActiTax; + @ApiModelProperty("證監會費(僅賣單時收取) ") + public BigDecimal securitiesTax; + + @ApiModelProperty("结算费") + public BigDecimal settlementTax; + @ApiModelProperty("交易费") + public BigDecimal tradeTax; + @ApiModelProperty("交易征費") + public BigDecimal tradeTranTax; + @ApiModelProperty("交易所费用") + public BigDecimal jysTax; + @ApiModelProperty("財匯局交易征費") + public BigDecimal chjTradeTranTax; + + public void sum() { + platformSum = BigDecimals.add(commission, platformTax); + thirtySum = BigDecimals.add(stampTax, productHandlerTax, securitiesManageTax, tradeActiTax, securitiesTax, settlementTax, tradeTax, tradeTranTax, jysTax, chjTradeTranTax); + totalSum = BigDecimals.add(platformSum, thirtySum); + } + + public static Tax subtract(Tax source, Tax ... t) { + Tax tax = new Tax(); + Field[] fields = Tax.class.getFields(); + for (Field field : fields) { +// Class type = field.getType(); +// if(! type.isInstance(BigDecimal.class)) { +// continue; +// } + field.setAccessible(true); + + BigDecimal sourceValue = BigDecimal.ZERO; + try { + sourceValue = (BigDecimal) field.get(source); + } catch (IllegalArgumentException | IllegalAccessException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + if(sourceValue == null) { + continue; + } + + List l = Lists.newArrayList(); + for (Tax _t : t) { + if(_t == null) { + continue; + } + try { + l.add((BigDecimal) field.get(_t)); + } catch (IllegalArgumentException | IllegalAccessException e) { + e.printStackTrace(); + } + } + + try { + field.set(tax, BigDecimals.lSubtract(sourceValue, l)); + } catch (IllegalArgumentException | IllegalAccessException e) { + e.printStackTrace(); + } + } + + tax.sum(); + return tax; + } + + public static Tax multiply(Tax source, BigDecimal percent) { + Tax tax = new Tax(); + Field[] fields = Tax.class.getFields(); + for (Field field : fields) { +// Class type = field.getType(); +// if(! type.isInstance(BigDecimal.class)) { +// continue; +// } + field.setAccessible(true); + + BigDecimal sourceValue = BigDecimal.ZERO; + try { + sourceValue = (BigDecimal) field.get(source); + } catch (IllegalArgumentException | IllegalAccessException e) { + e.printStackTrace(); + } + + if(sourceValue == null) { + continue; + } + + try { + field.set(tax, BigDecimals.multiplys(sourceValue, percent).setScale(2, RoundingMode.DOWN)); + } catch (IllegalArgumentException | IllegalAccessException e) { + e.printStackTrace(); + } + } + + tax.sum(); + return tax; + } + + public static Tax add(Tax ... t) { + Tax tax = new Tax(); + Field[] fields = Tax.class.getFields(); + for (Field field : fields) { +// Class type = field.getType(); +// if(! type.isInstance(BigDecimal.class)) { +// continue; +// } + field.setAccessible(true); + + List l = Lists.newArrayList(); + for (Tax _t : t) { + if(_t == null) { + continue; + } + + try { + l.add((BigDecimal) field.get(_t)); + } catch (IllegalArgumentException | IllegalAccessException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + if(CollectionUtils.isEmpty(l)) { + continue; + } + + try { + field.set(tax, BigDecimals.lAdd(l).setScale(2, RoundingMode.DOWN)); + } catch (IllegalArgumentException | IllegalAccessException e) { + e.printStackTrace(); + } + } + + tax.sum(); + return tax; + } + +} diff --git a/src/main/java/cn/stock/market/dto/model/TradeAccThumb.java b/src/main/java/cn/stock/market/dto/model/TradeAccThumb.java new file mode 100644 index 0000000..0633621 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/TradeAccThumb.java @@ -0,0 +1,22 @@ +package cn.stock.market.dto.model; + +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@SuperBuilder +@EqualsAndHashCode(callSuper = false) +@NoArgsConstructor +@ApiModel +public class TradeAccThumb { + Integer id; + Integer destId; + String role; + String destName; + String destPhone; + String type; + Integer fakeFlag; +} diff --git a/src/main/java/cn/stock/market/dto/model/TradeSetting.java b/src/main/java/cn/stock/market/dto/model/TradeSetting.java new file mode 100644 index 0000000..b0a9574 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/TradeSetting.java @@ -0,0 +1,121 @@ +package cn.stock.market.dto.model; + +import java.math.BigDecimal; + +import com.ag.utils.StringConvertJSONObjectSerializer; +import com.alibaba.fastjson.annotation.JSONField; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import cn.qutaojing.common.utils.BigDecimals; +import cn.qutaojing.common.utils.jackson.String2JsonObjSerializer; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel("交易配置") +public class TradeSetting { + BigDecimal lostWarn; + BigDecimal lostClose; + BigDecimal preTradingDayCost; + @ApiModelProperty("兑换手续费") + BigDecimal exchange; + @ApiModelProperty("配置的杠杆倍数") + Integer multiple; + + /** + * 印花税 + */ + + @JsonSerialize(using = String2JsonObjSerializer.class) + @JSONField(serializeUsing = StringConvertJSONObjectSerializer.class) + @ApiModelProperty("印花税") + String stampTax; + /** + * 佣金 + */ + @JsonSerialize(using = String2JsonObjSerializer.class) + @JSONField(serializeUsing = StringConvertJSONObjectSerializer.class) + @ApiModelProperty("交易佣金") + String commission; + + @ApiModelProperty("平台费") + @JsonSerialize(using = String2JsonObjSerializer.class) + @JSONField(serializeUsing = StringConvertJSONObjectSerializer.class) + String platformTax; + + @ApiModelProperty("產品處理費") + @JsonSerialize(using = String2JsonObjSerializer.class) + @JSONField(serializeUsing = StringConvertJSONObjectSerializer.class) + String productHandlerTax; + + @ApiModelProperty("證券管理費") + @JsonSerialize(using = String2JsonObjSerializer.class) + @JSONField(serializeUsing = StringConvertJSONObjectSerializer.class) + String securitiesManageTax; + + @ApiModelProperty("交易活動費") + @JsonSerialize(using = String2JsonObjSerializer.class) + @JSONField(serializeUsing = StringConvertJSONObjectSerializer.class) + String tradeActiTax; + + @JsonSerialize(using = String2JsonObjSerializer.class) + @JSONField(serializeUsing = StringConvertJSONObjectSerializer.class) + @ApiModelProperty("證監會費(僅賣單時收取) ") + String securitiesTax; + + @JsonSerialize(using = String2JsonObjSerializer.class) + @JSONField(serializeUsing = StringConvertJSONObjectSerializer.class) + @ApiModelProperty("结算费") + String settlementTax; + + @JsonSerialize(using = String2JsonObjSerializer.class) + @JSONField(serializeUsing = StringConvertJSONObjectSerializer.class) + @ApiModelProperty("交易费") + String tradeTax; + + @JsonSerialize(using = String2JsonObjSerializer.class) + @JSONField(serializeUsing = StringConvertJSONObjectSerializer.class) + @ApiModelProperty("交易征費") + String tradeTranTax; + + @JsonSerialize(using = String2JsonObjSerializer.class) + @JSONField(serializeUsing = StringConvertJSONObjectSerializer.class) + @ApiModelProperty("交易所费用") + String jysTax; + + @JsonSerialize(using = String2JsonObjSerializer.class) + @JSONField(serializeUsing = StringConvertJSONObjectSerializer.class) + @ApiModelProperty("財匯局交易征費") + String chjTradeTranTax; + +// @Deprecated +// @ApiModelProperty("佣金比率") +// BigDecimal commission; +// @Deprecated +// @ApiModelProperty("印花税") +// BigDecimal stampTax; +// @Deprecated +// @ApiModelProperty("结算费") +// BigDecimal settlementTax; +// @Deprecated +// @ApiModelProperty("交易征费") +// BigDecimal tradeTax; +// @Deprecated +// @ApiModelProperty("交易所费用") +// BigDecimal jysTax; + + public void check() { + if(lostWarn == null) lostWarn = BigDecimals.p(0.6); + if(lostClose == null) lostClose = BigDecimals.p(0.3); + if(preTradingDayCost == null) preTradingDayCost = BigDecimals.p(0.0015); + if(multiple == null) multiple = 5; + if(exchange == null) exchange = BigDecimals.p(0.01); + +// if(stampTax == null) stampTax = BigDecimals.p(0.001); +// if(commission == null) commission = BigDecimals.p(0.0008); +// if(settlementTax == null) settlementTax = BigDecimals.p(0); +// if(tradeTax == null) tradeTax = BigDecimals.p(0); +// if(jysTax == null) jysTax = BigDecimals.p(0); + } +} diff --git a/src/main/java/cn/stock/market/dto/model/UserProtocol.java b/src/main/java/cn/stock/market/dto/model/UserProtocol.java new file mode 100644 index 0000000..61658d8 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/UserProtocol.java @@ -0,0 +1,34 @@ +package cn.stock.market.dto.model; + +import javax.validation.constraints.NotNull; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * UserBankCreateCommand + * + * @author xlfd + * @email xlfd@gmail.com + * @created 2022/04/14 + */ +@Data +@SuperBuilder +@NoArgsConstructor +public class UserProtocol { + /** + * 名称 + */ + @NotNull + String mianzexieyi; + + @NotNull + String xinpofengxiangaozhishu; + + /** + * 所属银行 + */ + @NotNull + String xinpoweituoxieyi; +} diff --git a/src/main/java/cn/stock/market/dto/model/UserThumb.java b/src/main/java/cn/stock/market/dto/model/UserThumb.java new file mode 100644 index 0000000..fc9c874 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/model/UserThumb.java @@ -0,0 +1,22 @@ +package cn.stock.market.dto.model; + +import cn.qutaojing.common.DestInfo; +import cn.qutaojing.common.constant.RoleEnum; +import lombok.Data; + +@Data +public class UserThumb { + Integer id; + String phoneNo; + String nickName; + String headPortrait; + + public DestInfo destInfo() { + return DestInfo.builder() + .id(String.valueOf(this.getId())) + .name(this.getNickName()) + .phone(this.getPhoneNo()) + .re(RoleEnum.USER) + .build(); + } +} diff --git a/src/main/java/cn/stock/market/dto/query/SiteArticleQuery.java b/src/main/java/cn/stock/market/dto/query/SiteArticleQuery.java new file mode 100644 index 0000000..f1b6b47 --- /dev/null +++ b/src/main/java/cn/stock/market/dto/query/SiteArticleQuery.java @@ -0,0 +1,50 @@ +package cn.stock.market.dto.query; + +import org.apache.commons.lang3.StringUtils; + +import com.querydsl.core.types.dsl.BooleanExpression; + +import cn.qutaojing.common.jpa.ConditionBuilder; +import cn.stock.market.infrastructure.db.po.QSiteArticlePO; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @Author: Radish + * @Date: 2021-08-16 14:26 + * @Version: 1.0 + */ +@Data +@NoArgsConstructor +@SuperBuilder +@EqualsAndHashCode(callSuper = false) +@ApiModel("文章聚合条件") +public class SiteArticleQuery { + + String artTitle; + String artType; + Integer isShow; + + + public BooleanExpression where() { + QSiteArticlePO q = QSiteArticlePO.siteArticlePO; + ConditionBuilder builder = ConditionBuilder.builder(); + if (StringUtils.isNotBlank(artTitle)) { + builder.and(q.artTitle.like("%" + artTitle + "%")); + } + + if (StringUtils.isNotBlank(artType)) { + builder.and(q.artType.like("%" + artType + "%")); + } + + if (isShow != null) { + builder.and(q.isShow.eq(isShow)); + } + + return builder.build(); + } + +} diff --git a/src/main/java/cn/stock/market/dto/query/SiteNewsQuery.java b/src/main/java/cn/stock/market/dto/query/SiteNewsQuery.java new file mode 100644 index 0000000..f8b72ff --- /dev/null +++ b/src/main/java/cn/stock/market/dto/query/SiteNewsQuery.java @@ -0,0 +1,67 @@ +package cn.stock.market.dto.query; + +import org.apache.commons.lang3.StringUtils; + +import com.querydsl.core.types.OrderSpecifier; +import com.querydsl.core.types.dsl.BooleanExpression; + +import cn.qutaojing.common.jpa.ConditionBuilder; +import cn.stock.market.infrastructure.db.po.QSiteNewsPO; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * @Author: Radish + * @Date: 2021-08-16 14:26 + * @Version: 1.0 + */ +@Data +@NoArgsConstructor +@SuperBuilder +@EqualsAndHashCode(callSuper = false) +@ApiModel("新闻聚合条件") +public class SiteNewsQuery { + static QSiteNewsPO q = QSiteNewsPO.siteNewsPO; + Integer status; + Integer type; + String keyword; + + String orderSpecifier; + + public OrderSpecifier orderSpecifier() { + if ("idAsc".equals(orderSpecifier)) { + return q.id.asc(); + } else if ("time1".equals(orderSpecifier)) { + return q.showTime.desc(); + } else if ("time0".equals(orderSpecifier)) { + return q.showTime.asc(); + } else if ("views1".equals(orderSpecifier)) { + return q.views.desc(); + } else if ("views0".equals(orderSpecifier)) { + return q.views.asc(); + } + + return q.showTime.desc(); + } + + public BooleanExpression where() { + ConditionBuilder builder = ConditionBuilder.builder(); + if (StringUtils.isNotBlank(keyword)) { + builder.and(q.title.like("%" + keyword + "%").or(q.sourceName.like("%" + keyword + "%"))); + } + + if (status != null) { + builder.and(q.status.eq(status)); + } + + if (type != null) { + builder.and(q.type.eq(type)); + } + + return builder.build(); + } + +} diff --git a/src/main/java/cn/stock/market/exception/Code.java b/src/main/java/cn/stock/market/exception/Code.java new file mode 100644 index 0000000..b4779d0 --- /dev/null +++ b/src/main/java/cn/stock/market/exception/Code.java @@ -0,0 +1,167 @@ +package cn.stock.market.exception; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jul 14, 2021 1:35:00 PM + */ +public class Code { + + + //1. 系统级代码9开头 + //2. 店铺代码100开头 + //3. App用户端300开头 + /** + * 未登录 + */ + public static final Integer NO_LOGIN = 999; + + + /** + * 验证码错误 + **/ + public static final int SMS_CODE_ERROR = 996; + + /** + * token已过期或无效 + */ + public static final int TOKEN_ILLEGAL_EXCEPTION = 995; + /** + * 实体已存在 + */ + public static final int ENTITY_EXIST_EXCEPTION = 994; + /** + * 实体没找到 + **/ + public static final int ENTITY_NOT_FOUND = 993; + + public static final int FIELD_NULL = 997; + + /** + * 无效非法的参数 + */ + public static final int INVAILD_PARAM_EXCEPTION = 992; + /** + * 订单状态非法 + */ + public static final int ORDER_INVAILD_STATUS_EXCEPTION = 991; + + /** + * 鲸豆余额不足 + **/ + public static final int JD_NOTSUFFICIENTFUNDS = 970; + + /** + * 系统提示 + **/ + public static final int SYS_TIP = 988; + + /** + * 账号被锁定 + **/ + public static final int ACCOUNT_LOCK = 980; + /** + * 账号不存在 + **/ + public static final int ACCOUNT_NOT_FOUND = 981; + /** + * 密码错误 + **/ + public static final int PASSWORD_ERROR = 982; + + + /** + * 无权限 + **/ + public static final int NOT_PERMISSION = 990; + + /** + * 库存不足 + */ + public static final int STOCK_NOT_ENOUGH = 991; + + + /** + * 店铺已存在(一个营业执照一个店) + **/ + public static final int STORE_EXIST = 101; + + + /** + * 店铺状态不正常 + **/ + public static final int STORE_STAUTS_NOT_NORMAL = 102; + + /** + * 店铺未注册 + **/ + public static final int STORE_NOT_OPEN = 112; + + /** + * 线下支付扫码异常 + **/ + public static final int OFFLINESTORERISK = 103; + + /** + * 子账号过多 + */ + public static final int SUB_ACCOUNT_TOO_MUCH = 104; + + public static final int SUB_ACCOUNT_EXCEPTION = 105; + + /*** + * 店铺不存在 + */ + public static final int STORE_NOT_EXIST = 106; + + /** + * 没有传递地理位置信息 + **/ + public static final int NOT_LOCATION_PARAMTER = 300; + + /** + * 购买上限 + */ + public static final int BUY_LIMIT = 301; + + + /** + * 一级分类不能设置标签 + */ + public static final int CATEGORY_L1_CAN_NOT_SET_TAG = 103; + + /** + * 索引 700开始 + */ + + public static final int ES_INDEX_EXISTS = 700; + + public static final int ES_EXCEPTION = 701; + + /** + * 桌台存在未支付的订单 + */ + public static final int STORE_ROOM_EXISTS_UNPAY_ORDER = 702; + + /** + * 已经全额退款 + */ + public static final int ALLREADY_REFUNDED_ALL = 710; + + /*** + * 钱包提现异常 + */ + public static final int WITHDRAW_SERVER_EXCEPTION = 720; + + /*** + * 抢单异常 + */ + public static final int ABNORMAL_RUSH_ORDERS = 730; + + /*** + * 学校园区异常 + */ + public static final int SCHOOL_CAMPUS_IS_ABNORMAL = 740; + +} diff --git a/src/main/java/cn/stock/market/exception/SMSException.java b/src/main/java/cn/stock/market/exception/SMSException.java new file mode 100644 index 0000000..91ec74e --- /dev/null +++ b/src/main/java/cn/stock/market/exception/SMSException.java @@ -0,0 +1,23 @@ +package cn.stock.market.exception; + +import com.ag.exception.CodeException; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jul 14, 2021 1:34:51 PM + */ +public class SMSException extends CodeException { + + /** 描述 */ + private static final long serialVersionUID = 1L; + + public SMSException() { + super(Code.SMS_CODE_ERROR, "验证码错误"); + } + + public SMSException(String msg) { + super(Code.SMS_CODE_ERROR, msg); + } +} diff --git a/src/main/java/cn/stock/market/infrastructure/api/AStockApis.java b/src/main/java/cn/stock/market/infrastructure/api/AStockApis.java new file mode 100644 index 0000000..4275918 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/api/AStockApis.java @@ -0,0 +1,215 @@ +package cn.stock.market.infrastructure.api; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; + +import com.ag.exception.SysTipsException; +import com.ag.utils.CollectionUtils; +import com.ag.utils.DateUtils; +import com.ag.utils.Jsons; +import com.ag.utils.NumberUtils; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.google.common.base.Joiner; +import com.google.common.collect.Lists; + +import cn.hutool.http.HttpUtil; +import cn.qutaojing.common.utils.BigDecimals; +import cn.stock.market.dto.model.StockDetail; +import cn.stock.market.utils.Utils; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class AStockApis { + public static final String gugdata_appkey = "K5LZKV8KAYM4"; + public static final String ig507_licence = "4CEF3CDC-3A2E-76AB-9BF1-BE856F3D4468"; + public List stockRealTime(String appKey) { + //+ "&symbol=600031,sh000001" + String body = HttpUtil.get("https://api.gugudata.com/stock/cn/realtime?appkey=" + appKey); + JSONObject json = Jsons.toJSON(body); + Integer status = Jsons.getByPath(json, "DataStatus.StatusCode", -1); + if(NumberUtils.equals(status, 100)) { + return Lists.newArrayList(Lists.transform(json.getJSONArray("Data"), val -> { + return Jsons.toBean((JSONObject) val, StockRealTime.class); + })); + } + + throw new SysTipsException("同步失败:" + Jsons.getByPath(json, "DataStatus.StatusDescription", null)); + } + + public List gplist(String ig507_licence) { + String body = HttpUtil.get("https://ig507.com/data/base/gplist?licence=" + ig507_licence); + return Jsons.toList(body, JSONObject.class); + } + + public List sinalist(int page) { + String body = HttpUtil.get("https://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQNodeData?page="+page+"&num=40&sort=symbol&asc=1&node=hs_bjs&symbol=&_s_r_a=page"); + return Jsons.toList(body, JSONObject.class); + } + + /** + * 历史分时交易 + * @param level 支持5分钟、15分钟、30分钟、60分钟、日周月年级别(包括前后复权),对应的值分别是 5、15、30、60、Day、Day_qfq(日线前复权)、Day_hfq(日线后复权)、Week、Week_qfq(周线前复权)、Week_hfq(周线后复权)、Month、Month_qfq(月线前复权)、Month_hfq(月线后复权)、Year、Year_qfq(年线前复权)、Year_hfq(年线后复权) + * @return + */ + public List stockHistoryTrade(String stockCode, String level, String ig507Licence) { + String url = String.format("https://ig507.com/data/time/history/trade/%s/%s?licence=%s", stockCode, level, ig507Licence); + String body = HttpUtil.get(url); + return Jsons.toList(body, JSONObject.class); + } + + public static List sinahy() { + String body = HttpUtil.get("https://vip.stock.finance.sina.com.cn/q/view/newSinaHy.php"); + String replace = StringUtils.replace(body, "var S_Finance_bankuai_sinaindustry = ", ""); + JSONObject json = Jsons.toJSON(replace); + List list = Lists.newArrayList(); + for(String k : json.keySet()) { + String[] split = StringUtils.split(json.getString(k), ","); + list.add(new JSONArray(Lists.transform(Arrays.asList(split), val -> (Object) val))) ; + } + + return list; + } + + public static JSONArray stock_top10() { + String body = HttpUtil.get("https://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQNodeData?page=1&num=100&sort=changepercent&asc=0&node=hs_a&symbol=&_s_r_a=setlen"); + return JSON.parseArray(body); + } + + public static JSONArray stock_bot10() { + String body = HttpUtil.get("https://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQNodeData?page=1&num=100&sort=changepercent&asc=1&node=hs_a&symbol=&_s_r_a=setlen"); + return JSON.parseArray(body); + } + + public static StockDetail qq(String code) { + List list = qq(Lists.newArrayList(code)); + return CollectionUtils.isNotEmpty(list) ? list.get(0) : null; + } + + public static List qq(List codeList) { + List list = Lists.newArrayList(); + if(CollectionUtils.isEmpty(codeList)) { + return list; + } + + String url = "https://qt.gtimg.cn/q=" + Joiner.on(",").join(Lists.transform(codeList, val -> Utils.fenxi(val))); + log.info(url); + String body = HttpUtil.createGet(url) + .header("Referer", "https://qt.gtimg.cn") + .execute().body(); + String[] split = StringUtils.split(body, ";"); + for (String string : split) { + if(StringUtils.contains(string, "v_pv_none_match")) { + continue; + } + String content = StringUtils.replaceEach(string, new String[] { "\r\n", "\r", "\n" }, new String[] { "", "", "" }); + if(StringUtils.isBlank(content)) { + continue; + } + StockDetail stockDetail = _qqParse(content); + list.add(stockDetail); + } + return list; + } + + public static StockDetail _qqParse(String str) { + //v_sh000300="1~沪深300~000300~4186.98~4191.57~4162.37~61230818~30615409~30615409~0.00~0~0.00~0~0.00~0~0.00~0~0.00~0~0.00~0~0.00~0~0.00~0~0.00~0~0.00~0~~20220415105430~-4.59~-0.11~4193.20~4152.97~4186.98/61230818/110353453060~61230818~11035345~0.22~12.30~~4193.20~4152.97~0.96~363899.25~470787.62~0.00~-1~-1~1.26~0~4175.77~~~~~~11035345.3060~0.0000~0~ ~ZS~-15.25~-1.03~~~~5378.48~3942.86~-1.58~0.74~-13.59~~~-8.92~-17.82~~" + + /** + * 0: 未知 1: 名字 2: 代码 3: 当前价格 4: 昨收 5: 今开 6: 成交量(手)7: 外盘 8: 内盘 9: 买一 10: 买一量(手)11-18: 买二 买五 19: 卖一 20: 卖一量 21-28: 卖二 卖五 + * 29: 最近逐笔成交 30: 时间 31: 涨跌 32: 涨跌% 33: 最高 34: 最低 35: 价格/成交量(手)/成交额 36: 成交量(手)37: 成交额(万)38: 换手率 39: 市盈率 40: + * 41: 最高 42: 最低 43: 振幅 44: 流通市值 45: 总市值 46: 市净率 47: 涨停价 48: 跌停价 + */ + String[] split = StringUtils.split(str, "="); + String var = split[0]; + String content = StringUtils.substring(split[1], 1, split[1].length() - 1); + String jys = StringUtils.substring(var, 2, 4); +// String[] fields = StringUtils.split(content, "~"); + String[] fields = content.split("~"); + + StockDetail detail = StockDetail.builder() + .name(fields[1]) + .code(fields[2]) + .currentPrice(BigDecimals.p(fields[3])) //3: 当前价格 + .yesterdayPrice(BigDecimals.p(fields[4])) //4: 昨收 + .openPrice(BigDecimals.p(fields[5])) //5: 今开 + + .buyOnePrice(BigDecimals.p(fields[9])) + .buyTwoPrice(BigDecimals.p(fields[11])) + .buyThreePrice(BigDecimals.p(fields[13])) + .buyFourPrice(BigDecimals.p(fields[15])) + .buyFivePrice(BigDecimals.p(fields[17])) + + .buyOneAmount(BigDecimals.p(fields[10])) + .buyTwoAmount(BigDecimals.p(fields[12])) + .buyThreeAmount(BigDecimals.p(fields[14])) + .buyFourAmount(BigDecimals.p(fields[16])) + .buyFiveAmount(BigDecimals.p(fields[18])) + + .sellOnePrice(BigDecimals.p(fields[19])) + .sellTwoPrice(BigDecimals.p(fields[21])) + .sellThreePrice(BigDecimals.p(fields[23])) + .sellFourPrice(BigDecimals.p(fields[25])) + .sellFivePrice(BigDecimals.p(fields[27])) + + .sellOneAmount(BigDecimals.p(fields[20])) + .sellTwoAmount(BigDecimals.p(fields[22])) + .sellThreeAmount(BigDecimals.p(fields[24])) + .sellFourAmount(BigDecimals.p(fields[26])) + .sellFiveAmount(BigDecimals.p(fields[28])) + + .highest(BigDecimals.p(fields[41])) //41: 最高 + .lowest(BigDecimals.p(fields[42])) //42: 最低 + .volume(BigDecimals.p(fields[36])) //36: 成交量(手) + .turnover(BigDecimals.p(fields[37], BigDecimal.ZERO)) //37: 成交额(万) + .time(DateUtils.format(new Date(), "HH:mm:ss")) + .turnoverRate(BigDecimals.p(fields[38], BigDecimal.ZERO)) //38: 换手率 + .peRatio(BigDecimals.p(fields[39], BigDecimal.ZERO)) //39: 市盈率 + .circulationMarketValue(BigDecimals.p(fields[44], BigDecimal.ZERO)) //44: 流通市值 + .totalMarketValue(BigDecimals.p(fields[45], BigDecimal.ZERO)) //45: 总市值 + .pbRatio(BigDecimals.p(fields[46], BigDecimal.ZERO)) //46: 市净率 + .amplitude(BigDecimals.p(fields[43], BigDecimal.ZERO)) //43: 振幅 + .hardenPrice(fields[47]) //47: 涨停价 + .dropPrice(fields[48]) //48: 跌停价 + .jys(StringUtils.upperCase(jys)) + .build(); + + BigDecimal priceRange = BigDecimals.subtract(detail.getCurrentPrice(), detail.getYesterdayPrice()).setScale(2, RoundingMode.HALF_UP); + BigDecimal priceRate = BigDecimal.ZERO; + if(BigDecimals.neZero(detail.getYesterdayPrice())) { + priceRate = BigDecimals.multiplys(BigDecimals.divide(priceRange, detail.getYesterdayPrice()), 100).setScale(2, RoundingMode.HALF_UP); + } + detail.setPriceRange(priceRange); //涨幅 + detail.setPriceRate(priceRate); //涨幅百分比 + return detail; + } + + public static void main(String[] args) { +// List list = new AStockApis().stockRealTime(gugdata_appkey); +// for (CNStockRealTime stockRealTime : list) { +// System.out.println(JSON.toJSONString(stockRealTime)); +// } +// +// System.out.println(1); + + List sinahy = sinahy(); + System.out.println(sinahy); + + JSONArray stock_top10 = stock_top10(); + System.out.println(stock_top10); + + JSONArray stock_bot10 = stock_bot10(); + System.out.println(stock_bot10); + + StockDetail qq = qq("sh000300"); + System.out.println(qq); + StockDetail qq2 = qq("sh000001"); + System.out.println(qq2); + } +} diff --git a/src/main/java/cn/stock/market/infrastructure/api/AliApis.java b/src/main/java/cn/stock/market/infrastructure/api/AliApis.java new file mode 100644 index 0000000..446b460 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/api/AliApis.java @@ -0,0 +1,267 @@ +package cn.stock.market.infrastructure.api; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpResponse; +import org.apache.http.util.EntityUtils; + +import com.ag.exception.SysTipsException; +import com.ag.utils.Jsons; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.aliyun.cloudauth20200618.Client; +import com.aliyun.cloudauth20200618.models.DescribeSmartVerifyRequest; +import com.aliyun.cloudauth20200618.models.DescribeSmartVerifyResponse; +import com.aliyun.cloudauth20200618.models.InitSmartVerifyRequest; +import com.aliyun.cloudauth20200618.models.InitSmartVerifyResponse; +import com.aliyun.dysmsapi20170525.models.SendSmsRequest; +import com.aliyun.dysmsapi20170525.models.SendSmsResponse; +import com.aliyun.tea.TeaException; +import com.aliyun.tea.TeaUnretryableException; +import com.aliyun.teautil.models.RuntimeOptions; + +import cn.hutool.core.lang.UUID; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.dto.model.LogisticsInfo; +import cn.stock.market.web.config.Config; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class AliApis { + public String accessKeyId = ""; + public String accessKeySecret = ""; + public String appCode = ""; + + public static final String SMS_VERIFY_CODE = "SMS_246440038"; + public static final String SMS_WARN = "SMS_248035836"; +// public static final String SMS_CLOSE = "SMS_239314374"; + public static final String SMS_SIGN_NAME = "维来世通"; + public static final String SMS_OPEN = "SMS_244600492"; + public static final String SMS_WITHDRAWAL = "SMS_244485100"; + + public static final long SCENE_SFZ_PLUS = 3730001L; + public static final long SCENE_SFZ = 3739001L; + public static final long SCENE = 3729001L; +// public static final String SMS_VERIFY_CODE = "SMS_238300825"; +// public static final String SMS_WARN = "SMS_239319587"; +// public static final String SMS_CLOSE = "SMS_239314374"; +// public static final String SMS_SIGN_NAME = "兴珀证券"; +// public static final String SMS_OPEN = "SMS_239314375"; +// public static final String SMS_WITHDRAWAL = "SMS_239324551"; + + public AliApis(String accessKeyId, String accessKeySecret, String appCode) { + this.accessKeyId = accessKeyId; + this.accessKeySecret = accessKeySecret; + this.appCode = appCode; + } + + public static AliApis ofNew() { + return new AliApis("LTAI5tJi2z8cegG8fTW7BSQu", "fnCI9LUcqLuH7D6nkhvSHQMob1JSm8", ""); + } + + public static AliApis of() { + Config config = SpringUtils.getBean(Config.class); +// return new AliApis("LTAI5tCQRp7t158TVyoF2Yhe", "glyzOno773Cv7HeWDliveu2H5gX486", "75ef2615da614eaaa71e2e2058fc53b0"); + return new AliApis(config.getAliyunAccessKeyId(), config.getAliyunAccessKeySecret(), config.getAliyunAppCode()); + } + +// public static AliApis of_weilaizjhk() { +// //AccessKey ID LTAI5tJi2z8cegG8fTW7BSQu +// //AccessKey Secret fnCI9LUcqLuH7D6nkhvSHQMob1JSm8 +// return new AliApis("LTAI5tJi2z8cegG8fTW7BSQu", "fnCI9LUcqLuH7D6nkhvSHQMob1JSm8", ""); +// } + + /** + * { + "code": "10000", + "message": "成功", + "data": { + "state": "1" 验证结果:state: "1"为核验一致;state: "2"为核验不一致;state:"3"为异常情况 + }, + "seqNo": "4XU29Z4D1704061618" + } + { + "code": "10001", + "message": "参数传入有误", + "data": null, + "seqNo": "4XU29Z4D1704061618" + } + */ + public void checkCommunicationPersonal(String acc_no, String idcard, String mobile, String name) { + JSONObject json = communicationPersonal(acc_no, idcard, mobile, name); + if(json == null) { + throw new SysTipsException("调用异常~~~"); + } + + if("10000".equals(json.get("code"))) { + String state = Jsons.getByPath(json, "data.state", ""); + if("1".equals(state)) { + return; + } + String content = ""; + if("2".equals(state)) { + content = "核验不一致"; + } else { + content = "核验异常情况"; + } + + throw new SysTipsException(content); + } + + throw new SysTipsException(json.getString("message")); + } + + public JSONObject communicationPersonal(String acc_no, String idcard, String mobile, String name) { + String host = "http://yhkys.market.alicloudapi.com"; + String path = "/communication/personal/1887"; + String method = "POST"; + Map headers = new HashMap(); + //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105 + headers.put("Authorization", "APPCODE " + appCode); + //根据API的要求,定义相对应的Content-Type + headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); + Map querys = new HashMap(); + Map bodys = new HashMap(); + bodys.put("acc_no", acc_no); + bodys.put("idcard", idcard); + bodys.put("mobile", mobile); + bodys.put("name", name); + + try { + HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys); + System.out.println(response.toString()); + String content = EntityUtils.toString(response.getEntity()); + return Jsons.toJSON(content); + } catch (Exception e) { + e.printStackTrace(); + throw new SysTipsException("查询失败:" + e.getLocalizedMessage()); + } + } + + /** + * 使用AK&SK初始化账号Client + * @param accessKeyId + * @param accessKeySecret + * @return Client + * @throws Exception + */ + public static com.aliyun.dysmsapi20170525.Client createClient(String accessKeyId, String accessKeySecret) throws Exception { + com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config() + // 您的AccessKey ID + .setAccessKeyId(accessKeyId) + // 您的AccessKey Secret + .setAccessKeySecret(accessKeySecret); + // 访问的域名 + config.endpoint = "dysmsapi.aliyuncs.com"; + return new com.aliyun.dysmsapi20170525.Client(config); + } + + public JSONObject sendSms(String phone, String signName, String templateCode, JSONObject param) { + if(param == null) param = new JSONObject(); + try { + com.aliyun.dysmsapi20170525.Client client = createClient(accessKeyId, accessKeySecret); + SendSmsRequest sendSmsRequest = new SendSmsRequest() + .setSignName(signName) + .setTemplateCode(templateCode) + .setPhoneNumbers(phone) + .setTemplateParam(JSON.toJSONString(param)); + // 复制代码运行请自行打印 API 的返回值 + SendSmsResponse response = client.sendSms(sendSmsRequest); + return Jsons.toJSON(response.getBody()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static boolean checSendSucc(JSONObject json) { + //{"code":"OK","requestId":"62418BAE-7500-59F6-A899-BF4BD48A7FE7","bizId":"141614847682398177^0","message":"OK"} + return json != null && StringUtils.equals("OK", json.getString("code")); + } + + public JSONObject showapiExpInfo(LogisticsInfo info) { + String host = "https://ali-deliver.showapi.com"; + String path = "/showapi_expInfo"; + String method = "GET"; + Map headers = new HashMap(); + //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105 + headers.put("Authorization", "APPCODE " + appCode); + Map querys = new HashMap(); + querys.put("com", info.getLogisticsCode()); + querys.put("nu", info.getNo()); + querys.put("receiverPhone", info.getReceiverPhone()); + querys.put("senderPhone", info.getSenderPhone()); + + try { + /** + * 重要提示如下: + * HttpUtils请从 + * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java + * 下载 + * + * 相应的依赖请参照 + * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml + */ + HttpResponse response = HttpUtils.doGet(host, path, method, headers, querys); +// String content = response.toString(); + String content = EntityUtils.toString(response.getEntity()); + log.info(content); + return Jsons.toJSON(content); + } catch (Exception e) { + e.printStackTrace(); + throw new SysTipsException("查询失败:" + e.getLocalizedMessage()); + } + } + + public JSONObject fetchCom(String nu) { + String host = "https://ali-deliver.showapi.com"; + String path = "/fetchCom"; + String method = "GET"; + Map headers = new HashMap(); + // 最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105 + headers.put("Authorization", "APPCODE " + appCode); + Map querys = new HashMap(); + querys.put("nu", nu); + + try { + /** + * 重要提示如下: HttpUtils请从 + * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java + * 下载 + * + * 相应的依赖请参照 + * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml + */ + HttpResponse response = HttpUtils.doGet(host, path, method, headers, querys); + String content = EntityUtils.toString(response.getEntity()); + log.info(content); + return Jsons.toJSON(content); + } catch (Exception e) { + e.printStackTrace(); + + throw new SysTipsException("查询失败:" + e.getLocalizedMessage()); + } + } + + public static void main(String[] args) throws Exception { +// AliApis apis = new AliApis("LTAI5tCQRp7t158TVyoF2Yhe", "glyzOno773Cv7HeWDliveu2H5gX486", "75ef2615da614eaaa71e2e2058fc53b0"); +// AliApis.of().checkCommunicationPersonal("6214835710237742", "362526198911135012", "15390891113", "李荣平"); +// LogisticsInfo info = LogisticsInfo.builder() +// .logisticsCode("ems") +// .no("9975682576513") +// .build(); +// AliApis.of().showapiExpInfo(info); + +// JSONObject json = new JSONObject(); +// json.put("code", "1234"); +// JSONObject j = apis.sendSms("15390891113", SMS_SIGN_NAME, SMS_WARN, json); +// System.out.println(j); + +// DescribeSmartVerifyResponse response = DescribeSmartVerify.describeSmart("shs3db1931cf84eda693e2c8746279d0"); +// System.out.println(JSON.toJSONString(response)); + + } +} diff --git a/src/main/java/cn/stock/market/infrastructure/api/AliAsyncApis.java b/src/main/java/cn/stock/market/infrastructure/api/AliAsyncApis.java new file mode 100644 index 0000000..c7bad17 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/api/AliAsyncApis.java @@ -0,0 +1,23 @@ +package cn.stock.market.infrastructure.api; + +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.stereotype.Component; + +import com.alibaba.fastjson.JSONObject; + +import cn.qutaojing.common.utils.SpringUtils; + +@Deprecated +@Component +@EnableAsync +public class AliAsyncApis { +// @Async +// public void sendSmsSync(String phone, String signName, String templateCode, JSONObject param) { +// AliApis.of().sendSms(phone, signName, templateCode, param); +// } +// +// public static AliAsyncApis of() { +// return SpringUtils.getBean(AliAsyncApis.class); +// } +} diff --git a/src/main/java/cn/stock/market/infrastructure/api/CApis.java b/src/main/java/cn/stock/market/infrastructure/api/CApis.java new file mode 100644 index 0000000..4ba350e --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/api/CApis.java @@ -0,0 +1,52 @@ +package cn.stock.market.infrastructure.api; + +import java.math.BigDecimal; +import java.util.Map; + +import com.ag.exception.SysTipsException; +import com.ag.utils.Jsons; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.google.common.collect.Maps; + +import cn.hutool.http.HttpUtil; +import cn.qutaojing.common.constant.Currency; +import cn.qutaojing.common.utils.BigDecimals; +import cn.stock.market.dto.model.ExchangeRate; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CApis { + + public CApis() { + } + + public ExchangeRate exchangeRate(Currency currency) { + String text = HttpUtil.get("https://api.exchangerate-api.com/v4/latest/" + currency.code()); + JSONObject json = Jsons.toJSON(text); + if(! json.containsKey("rates")) { + throw new SysTipsException(json.getString("error_type")); + } + + Map map = Maps.newHashMap(); + json.getJSONObject("rates").forEach((k, v) -> { + Currency of = Currency.of(k); + if(of != null) { + map.put(of, BigDecimals.p(v)); + } + }); + ExchangeRate rate = new ExchangeRate(); + rate.setBase(currency); + rate.setRates(map); + return rate; + } + + public static CApis of() { + return new CApis(); + } + + public static void main(String[] args) { + ExchangeRate exchangerRate = of().exchangeRate(Currency.CNY); + System.out.println(JSON.toJSONString(exchangerRate)); + } +} diff --git a/src/main/java/cn/stock/market/infrastructure/api/DescribeFaceVerify.java b/src/main/java/cn/stock/market/infrastructure/api/DescribeFaceVerify.java new file mode 100644 index 0000000..f4778a6 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/api/DescribeFaceVerify.java @@ -0,0 +1,105 @@ +package cn.stock.market.infrastructure.api; + +import java.util.Arrays; +import java.util.List; + +import com.aliyun.cloudauth20190307.Client; +import com.aliyun.cloudauth20190307.models.DescribeFaceVerifyRequest; +import com.aliyun.cloudauth20190307.models.DescribeFaceVerifyResponse; +import com.aliyun.tea.TeaException; +import com.aliyun.tea.TeaUnretryableException; +import com.aliyun.tearpc.models.Config; +import com.aliyun.teautil.models.RuntimeOptions; + +public class DescribeFaceVerify { +// +// public static DescribeFaceVerifyResponse main(String certifyId) throws Exception { +// +// // 通过以下代码创建API请求并设置参数。 +// DescribeFaceVerifyRequest request = new DescribeFaceVerifyRequest(); +// // 请输入场景ID+L。 +// request.setSceneId(AliApis.SMART_SCENEID); +// +// request.setCertifyId(certifyId); +// +// // 推荐,支持服务路由。 +// DescribeFaceVerifyResponse response = describeFaceVerifyAutoRoute(request); +// +// // 不支持服务自动路由。 +// //DescribeFaceVerifyResponse response = describeFaceVerify("cloudauth.cn-shanghai.aliyuncs.com", request); +// +// System.out.println(response.getRequestId()); +// System.out.println(response.getCode()); +// System.out.println(response.getMessage()); +// System.out.println( +// response.getResultObject() == null ? null : response.getResultObject().getPassed()); +// System.out.println( +// response.getResultObject() == null ? null : response.getResultObject().getSubCode()); +// System.out.println( +// response.getResultObject() == null ? null +// : response.getResultObject().getIdentityInfo()); +// System.out.println( +// response.getResultObject() == null ? null +// : response.getResultObject().getDeviceToken()); +// System.out.println( +// response.getResultObject() == null ? null +// : response.getResultObject().getMaterialInfo()); +// +// return response; +// } +// +// private static DescribeFaceVerifyResponse describeFaceVerifyAutoRoute(DescribeFaceVerifyRequest request) { +// // 第一个为主区域Endpoint,第二个为备区域Endpoint。 +// List endpoints = Arrays.asList("cloudauth.cn-shanghai.aliyuncs.com", +// "cloudauth.cn-beijing.aliyuncs.com"); +// DescribeFaceVerifyResponse lastResponse = null; +// for (String endpoint : endpoints) { +// try { +// DescribeFaceVerifyResponse response = describeFaceVerify(endpoint, request); +// lastResponse = response; +// +// // 服务端错误,切换到下个区域调用。 +// if (response != null && "500".equals(response.getCode())) { +// continue; +// } +// +// return response; +// } catch (Exception e) { +// // 网络异常,切换到下个区域调用。 +// if (e.getCause() instanceof TeaException) { +// TeaException teaException = ((TeaException)e.getCause()); +// if (teaException.getData() != null && "ServiceUnavailable".equals( +// teaException.getData().get("Code"))) { +// continue; +// } +// } +// +// if (e.getCause() instanceof TeaUnretryableException) { +// continue; +// } +// } +// } +// +// return lastResponse; +// } +// +// private static DescribeFaceVerifyResponse describeFaceVerify(String endpoint, DescribeFaceVerifyRequest request) +// throws Exception { +// Config config = new Config(); +// config.setAccessKeyId(AliApis.ofNew().accessKeyId); +// config.setAccessKeySecret(AliApis.ofNew().accessKeySecret); +// config.setEndpoint(endpoint); +// // 设置http代理。 +// //config.setHttpProxy("http://xx.xx.xx.xx:xxxx"); +// // 设置https代理。 +// //config.setHttpsProxy("http://xx.xx.xx.xx:xxxx"); +// Client client = new Client(config); +// +// // 创建RuntimeObject实例并设置运行参数。 +// RuntimeOptions runtime = new RuntimeOptions(); +// runtime.readTimeout = 10000; +// runtime.connectTimeout = 10000; +// +// return client.describeFaceVerify(request, runtime); +// } +} diff --git a/src/main/java/cn/stock/market/infrastructure/api/DescribeSmartVerify.java b/src/main/java/cn/stock/market/infrastructure/api/DescribeSmartVerify.java new file mode 100644 index 0000000..b4818a1 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/api/DescribeSmartVerify.java @@ -0,0 +1,103 @@ +package cn.stock.market.infrastructure.api; + +import java.util.Arrays; +import java.util.List; + +import com.alibaba.fastjson.JSON; +import com.aliyun.cloudauth20200618.Client; +import com.aliyun.cloudauth20200618.models.DescribeSmartVerifyRequest; +import com.aliyun.cloudauth20200618.models.DescribeSmartVerifyResponse; +import com.aliyun.tea.TeaException; +import com.aliyun.tea.TeaUnretryableException; +import com.aliyun.tearpc.models.Config; +import com.aliyun.teautil.models.RuntimeOptions; + +public class DescribeSmartVerify { + public static DescribeSmartVerifyResponse describeSmart(long scene, String certifyId) throws Exception { + + // 通过以下代码创建API请求并设置参数。 + DescribeSmartVerifyRequest request = new DescribeSmartVerifyRequest(); + // 请输入场景ID+L。 + request.setSceneId(scene); + + request.setCertifyId(certifyId); + + // 推荐,支持服务路由。 + //DescribeSmartVerifyResponse response = describeSmartVerifyAutoRoute(request); + + // 不支持服务自动路由。 + DescribeSmartVerifyResponse response = describeSmartVerify("cloudauth.cn-shanghai.aliyuncs.com", request); + + System.out.println(response.getRequestId()); + System.out.println(response.getCode()); + System.out.println(response.getMessage()); + System.out.println( + response.getResultObject() == null ? null : response.getResultObject().getPassed()); + System.out.println( + response.getResultObject() == null ? null : response.getResultObject().getSubCode()); + System.out.println(response.getResultObject() == null ? null + : response.getResultObject().getMaterialInfo()); + + return response; + } + + private static DescribeSmartVerifyResponse describeSmartVerifyAutoRoute(DescribeSmartVerifyRequest request) { + // 第一个为主区域Endpoint,第二个为备区域Endpoint。 + List endpoints = Arrays.asList("cloudauth.cn-shanghai.aliyuncs.com", + "cloudauth.cn-beijing.aliyuncs.com"); + DescribeSmartVerifyResponse lastResponse = null; + for (String endpoint : endpoints) { + try { + DescribeSmartVerifyResponse response = describeSmartVerify(endpoint, request); + lastResponse = response; + + // 服务端错误,切换到下个区域调用。 + if ("500".equals(response.getCode())) { + continue; + } + + return response; + } catch (Exception e) { + // 网络异常,切换到下个区域调用。 + if (e.getCause() instanceof TeaException) { + TeaException teaException = ((TeaException)e.getCause()); + if (teaException.getData() != null && "ServiceUnavailable".equals( + teaException.getData().get("Code"))) { + continue; + } + } + + if (e.getCause() instanceof TeaUnretryableException) { + continue; + } + } + } + + return lastResponse; + } + + private static DescribeSmartVerifyResponse describeSmartVerify(String endpoint, DescribeSmartVerifyRequest request) + throws Exception { + Config config = new Config(); + config.setAccessKeyId(AliApis.ofNew().accessKeyId); + config.setAccessKeySecret(AliApis.ofNew().accessKeySecret); + config.setEndpoint(endpoint); + // 设置HTTP代理。 + //config.setHttpProxy(""); + // 设置HTTPS代理。 + //config.setHttpsProxy(""); + Client client = new Client(config); + + // 创建RuntimeObject实例并设置运行参数。 + RuntimeOptions runtime = new RuntimeOptions(); + runtime.readTimeout = 10000; + runtime.connectTimeout = 10000; + + return client.describeSmartVerify(request, runtime); + } + + public static void main(String[] args) throws Exception { + DescribeSmartVerifyResponse response = DescribeSmartVerify.describeSmart(AliApis.SCENE_SFZ_PLUS, "shs0cd820014eaef132f218f0dfc9d8c"); + System.out.println(JSON.toJSONString(response)); + } +} diff --git a/src/main/java/cn/stock/market/infrastructure/api/EastmoneyApi.java b/src/main/java/cn/stock/market/infrastructure/api/EastmoneyApi.java new file mode 100644 index 0000000..b7c203c --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/api/EastmoneyApi.java @@ -0,0 +1,120 @@ +package cn.stock.market.infrastructure.api; + +import java.text.MessageFormat; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; + +import com.ag.exception.SysTipsException; +import com.ag.utils.DateUtils; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.google.common.collect.Lists; + +import cn.hutool.http.HttpGlobalConfig; +import cn.hutool.http.HttpUtil; +import cn.qutaojing.common.PageInfo; +import cn.qutaojing.common.PageParam; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class EastmoneyApi { + public static List gethotgubalist() { + String reponse = HttpUtil.createGet("http://quote.eastmoney.com/newapi/gethotgubalist") + .header("Referer", "http://quote.eastmoney.com") + .execute().body(); + + return Lists.transform(JSON.parseArray(reponse), item -> (JSONObject) item); + } + + /** + * 新股日历 + * @param pageNum + * @param pageSize + * @return + */ + public static PageInfo ipoApplyDate(int pageNum, int pageSize) { + String url = MessageFormat.format("https://datacenter-web.eastmoney.com/api/data/v1/get?sortColumns=APPLY_DATE%2CSECURITY_CODE&sortTypes=-1%2C-1&pageSize={0}&pageNumber={1}&reportName=RPTA_APP_IPOAPPLY&columns=SECURITY_CODE%2CSECURITY_NAME%2CTRADE_MARKET_CODE%2CAPPLY_CODE%2CTRADE_MARKET%2CMARKET_TYPE%2CORG_TYPE%2CISSUE_NUM%2CONLINE_ISSUE_NUM%2COFFLINE_PLACING_NUM%2CTOP_APPLY_MARKETCAP%2CPREDICT_ONFUND_UPPER%2CONLINE_APPLY_UPPER%2CPREDICT_ONAPPLY_UPPER%2CISSUE_PRICE%2CLATELY_PRICE%2CCLOSE_PRICE%2CAPPLY_DATE%2CBALLOT_NUM_DATE%2CBALLOT_PAY_DATE%2CLISTING_DATE%2CAFTER_ISSUE_PE%2CONLINE_ISSUE_LWR%2CINITIAL_MULTIPLE%2CINDUSTRY_PE_NEW%2COFFLINE_EP_OBJECT%2CCONTINUOUS_1WORD_NUM%2CTOTAL_CHANGE%2CPROFIT%2CLIMIT_UP_PRICE%2CINFO_CODE%2COPEN_PRICE%2CLD_OPEN_PREMIUM%2CLD_CLOSE_CHANGE%2CTURNOVERRATE%2CLD_HIGH_CHANG%2CLD_AVERAGE_PRICE%2COPEN_DATE%2COPEN_AVERAGE_PRICE%2CPREDICT_PE%2CPREDICT_ISSUE_PRICE2%2CPREDICT_ISSUE_PRICE%2CPREDICT_ISSUE_PRICE1%2CPREDICT_ISSUE_PE%2CPREDICT_PE_THREE%2CONLINE_APPLY_PRICE%2CMAIN_BUSINESS%2CPAGE_PREDICT_PRICE1%2CPAGE_PREDICT_PRICE2%2CPAGE_PREDICT_PRICE3%2CPAGE_PREDICT_PE1%2CPAGE_PREDICT_PE2%2CPAGE_PREDICT_PE3%2CSELECT_LISTING_DATE%2CIS_BEIJING%2CINDUSTRY_PE_RATIO%2CINDUSTRY_PE%2CIS_REGISTRATION"eColumns=f2~01~SECURITY_CODE~NEWEST_PRICE"eType=0&filter=(APPLY_DATE%3E%27{2}%27)&source=WEB&client=WEB", pageSize, pageNum, DateUtils.format(DateUtils.dayAdd(-1), DateUtils.YYYY_MM_DD)); + String reponse = null; + try { + reponse = HttpUtil.createGet(url) + .header("Referer", "https://datacenter-web.eastmoney.com") + .execute().body(); + + JSONObject json = JSON.parseObject(reponse); + if(json.getIntValue("code") == 0) { + JSONObject result = json.getJSONObject("result"); + Integer count = result.getInteger("count"); + JSONArray data = result.getJSONArray("data"); + List list = Lists.transform(data, item -> (JSONObject) item) + .stream() +// .filter(j -> ! StringUtils.startsWith(j.getString("APPLY_CODE"), "8")) + .collect(Collectors.toList()); + + return PageInfo.with(list, new PageParam(pageNum, pageSize), count); + } else { + return PageInfo.with(Lists.newArrayList(), new PageParam(pageNum, pageSize)); + } + } catch (Exception e) { + log.error("获取新股日历出错url:{},reponse: {}, 错误信息 = {}", url, reponse, e); + // 获取股票行情出错 + throw new SysTipsException("tips.msg.185"); + } + } + + /** + * 沪深300 + * @return + */ + public static List a300List() { + String url = "http://push2.eastmoney.com/api/qt/clist/get?np=1&fltt=1&invt=2&fs=b%3ABK0500%2Bf%3A!50&fields=f14%2Cf12%2Cf13%2Cf1%2Cf2%2Cf4%2Cf3%2Cf152&fid=f3&pn=1&pz=15&po=1&ut=fa5fd1943c7b386f172d6893dbfba10b&wbp2u=%7C0%7C0%7C0%7Cweb&_=" + System.currentTimeMillis(); + return _qtListGet(url); + } + + /** + * 沪深指数 + * {total, diff: []} + * @return + */ + public static List aIndexList() { + int pageNum = 1; + int pageSize = 20; + String url = String.format("http://21.push2.eastmoney.com/api/qt/clist/get?pn=%s&pz=%s&po=1&np=1&ut=bd1d9ddb04089700cf9c27f6f7426281&fltt=2&invt=2&wbp2u=|0|0|0|web&fid=&fs=b:MK0010&fields=f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18,f20,f21,f23,f24,f25,f26,f22,f11,f62,f128,f136,f115,f152&_=" + System.currentTimeMillis(), pageNum, pageSize); + return _qtListGet(url); + } + + public static List _qtListGet(String url) { + String reponse = null; + try { + reponse = HttpUtil.createGet(url) + .header("Referer", "http://21.push2.eastmoney.com") + .execute().body(); + log.info("url:{}", url); + log.info(reponse); + JSONObject json = JSON.parseObject(reponse); + JSONObject data = json.getJSONObject("data"); + if(data == null) { + return Lists.newArrayList(); + } + + return Lists.transform(data.getJSONArray("diff"), item -> { + JSONObject j = (JSONObject) item; + return j; + }); + } catch (Exception e) { + log.error("获取股票行情出错url:{},reponse: {}, 错误信息 = {}", url, reponse, e); + // 获取股票行情出错 + throw new SysTipsException("tips.msg.185"); + } + } + + public static void main(String[] args) { + PageInfo ipoApplyDate = ipoApplyDate(1, 300); + System.out.println(JSON.toJSONString(ipoApplyDate)); + + List gethotgubalist = gethotgubalist(); + System.out.println(JSON.toJSONString(gethotgubalist)); + } +} diff --git a/src/main/java/cn/stock/market/infrastructure/api/FutunnNewsApis.java b/src/main/java/cn/stock/market/infrastructure/api/FutunnNewsApis.java new file mode 100644 index 0000000..b575650 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/api/FutunnNewsApis.java @@ -0,0 +1,33 @@ +package cn.stock.market.infrastructure.api; + +import com.ag.exception.SysTipsException; +import com.ag.utils.Jsons; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; + +import cn.hutool.http.HttpUtil; + +public class FutunnNewsApis { + public JSONArray market_list(String news_id) { + String url = String.format("https://news.futunn.com/client/market-list?news_id=%s&lang=zh-cn", news_id); + String body = HttpUtil.get(url); + JSONObject json = Jsons.toJSON(body); + if(json == null) { + throw new SysTipsException("访问异常"); + } + + if(json.getIntValue("code") != 0) { + throw new SysTipsException(json.getString("message")); + } + + return json.getJSONObject("data").getJSONArray("list"); + } + + public static FutunnNewsApis of() { + return new FutunnNewsApis(); + } + + public static void main(String[] args) { + System.out.println(of().market_list(null)); + } +} diff --git a/src/main/java/cn/stock/market/infrastructure/api/HttpUtils.java b/src/main/java/cn/stock/market/infrastructure/api/HttpUtils.java new file mode 100644 index 0000000..0133f3e --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/api/HttpUtils.java @@ -0,0 +1,313 @@ +package cn.stock.market.infrastructure.api; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.apache.commons.lang.StringUtils; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.conn.ClientConnectionManager; +import org.apache.http.conn.scheme.Scheme; +import org.apache.http.conn.scheme.SchemeRegistry; +import org.apache.http.conn.ssl.SSLSocketFactory; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicNameValuePair; + +@SuppressWarnings("deprecation") +public class HttpUtils { + + /** + * get + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @return + * @throws Exception + */ + public static HttpResponse doGet(String host, String path, String method, + Map headers, + Map querys) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpGet request = new HttpGet(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + return httpClient.execute(request); + } + + /** + * post form + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param bodys + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, + Map headers, + Map querys, + Map bodys) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (bodys != null) { + List nameValuePairList = new ArrayList(); + + for (String key : bodys.keySet()) { + nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key))); + } + UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8"); + formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8"); + request.setEntity(formEntity); + } + + return httpClient.execute(request); + } + + /** + * Post String + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, + Map headers, + Map querys, + String body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (StringUtils.isNotBlank(body)) { + request.setEntity(new StringEntity(body, "utf-8")); + } + + return httpClient.execute(request); + } + + /** + * Post stream + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, + Map headers, + Map querys, + byte[] body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (body != null) { + request.setEntity(new ByteArrayEntity(body)); + } + + return httpClient.execute(request); + } + + /** + * Put String + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPut(String host, String path, String method, + Map headers, + Map querys, + String body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPut request = new HttpPut(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (StringUtils.isNotBlank(body)) { + request.setEntity(new StringEntity(body, "utf-8")); + } + + return httpClient.execute(request); + } + + /** + * Put stream + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPut(String host, String path, String method, + Map headers, + Map querys, + byte[] body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPut request = new HttpPut(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (body != null) { + request.setEntity(new ByteArrayEntity(body)); + } + + return httpClient.execute(request); + } + + /** + * Delete + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @return + * @throws Exception + */ + public static HttpResponse doDelete(String host, String path, String method, + Map headers, + Map querys) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpDelete request = new HttpDelete(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + return httpClient.execute(request); + } + + private static String buildUrl(String host, String path, Map querys) throws UnsupportedEncodingException { + StringBuilder sbUrl = new StringBuilder(); + sbUrl.append(host); + if (!StringUtils.isBlank(path)) { + sbUrl.append(path); + } + if (null != querys) { + StringBuilder sbQuery = new StringBuilder(); + for (Map.Entry query : querys.entrySet()) { + if (0 < sbQuery.length()) { + sbQuery.append("&"); + } + if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) { + sbQuery.append(query.getValue()); + } + if (!StringUtils.isBlank(query.getKey())) { + sbQuery.append(query.getKey()); + if (!StringUtils.isBlank(query.getValue())) { + sbQuery.append("="); + sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8")); + } + } + } + if (0 < sbQuery.length()) { + sbUrl.append("?").append(sbQuery); + } + } + + return sbUrl.toString(); + } + + private static HttpClient wrapClient(String host) { + HttpClient httpClient = new DefaultHttpClient(); + if (host.startsWith("https://")) { + sslClient(httpClient); + } + + return httpClient; + } + + private static void sslClient(HttpClient httpClient) { + try { + SSLContext ctx = SSLContext.getInstance("TLS"); + X509TrustManager tm = new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } + public void checkClientTrusted(X509Certificate[] xcs, String str) { + + } + public void checkServerTrusted(X509Certificate[] xcs, String str) { + + } + }; + ctx.init(null, new TrustManager[] { tm }, null); + SSLSocketFactory ssf = new SSLSocketFactory(ctx); + ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + ClientConnectionManager ccm = httpClient.getConnectionManager(); + SchemeRegistry registry = ccm.getSchemeRegistry(); + registry.register(new Scheme("https", 443, ssf)); + } catch (KeyManagementException ex) { + throw new RuntimeException(ex); + } catch (NoSuchAlgorithmException ex) { + throw new RuntimeException(ex); + } + } +} \ No newline at end of file diff --git a/src/main/java/cn/stock/market/infrastructure/api/InitFaceVerify.java b/src/main/java/cn/stock/market/infrastructure/api/InitFaceVerify.java new file mode 100644 index 0000000..df668df --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/api/InitFaceVerify.java @@ -0,0 +1,122 @@ +package cn.stock.market.infrastructure.api; + +import java.util.Arrays; +import java.util.List; + +import com.aliyun.cloudauth20190307.Client; +import com.aliyun.cloudauth20190307.models.*; +import com.aliyun.tea.TeaException; +import com.aliyun.tea.TeaUnretryableException; +import com.aliyun.tearpc.models.Config; +import com.aliyun.teautil.models.RuntimeOptions; + +import cn.hutool.core.lang.UUID; + +public class InitFaceVerify { +// +// public static InitFaceVerifyResponse faceVerify(String phoneNo, String metaInfo, String certifyId) throws Exception { +// +// InitFaceVerifyRequest request = new InitFaceVerifyRequest(); +// // 请输入场景ID+L。 +// request.setSceneId(AliApis.SMART_SCENEID); +// // 设置商户请求的唯一标识。 +// request.setOuterOrderNo(UUID.fastUUID().toString()); +// // 认证方案。 +// request.setProductCode("PV_FV"); +// request.setUserId("12345xxxx"); +// // 模式。 +// request.setModel("LIVENESS"); +// request.setCertType("IDENTITY_CARD"); +// //request.setCertName("张三"); +// //request.setCertNo("xxxx"); +// // MetaInfo环境参数。 +// request.setMetaInfo(metaInfo); +// //request.setMobile("130xxxxxxxx"); +// //request.setIp("114.xxx.xxx.xxx"); +// +// // 请在以下四种方式中选择其一。 +// // 1.照片Base64编码。 +// // 2.照片OSS bucket名和文件名。 +// // 3.照片OSS的URL地址。 +// // 4.已经实人认证通过的CertifyId。 +// +// // 方式一:照片Base64。 +//// request.setFaceContrastPicture("人脸照片Base64编码"); +// // 方式二:照片OSS bucket名和文件名。 +// //request.setOssBucketName("cn-shanghai-aliyun-cloudauth-xxxxx"); +// //request.setOssObjectName("verify/xxxxx/xxxxxx.jpeg"); +// // 方式三:照片OSS的URL地址,公网可访问。 +// //request.setFaceContrastPictureUrl("https://cn-shanghai-aliyun-cloudauth-xxxxxx.oss-cn-shanghai.aliyuncs.com/verify/xxxxx/xxxxx.jpeg") +// // 方式四:已经实人认证通过的CertifyId。 +// request.setCertifyId(certifyId); +// +// // 推荐,支持服务路由。 +// InitFaceVerifyResponse response = initFaceVerifyAutoRoute(request); +// +// // 不支持服务自动路由。 +// //InitFaceVerifyResponse response = initFaceVerify("cloudauth.cn-shanghai.aliyuncs.com", request); +// +// System.out.println(response.getRequestId()); +// System.out.println(response.getCode()); +// System.out.println(response.getMessage()); +// System.out.println(response.getResultObject() == null ? null +// : response.getResultObject().getCertifyId()); +// +// return response; +// } +// +// private static InitFaceVerifyResponse initFaceVerifyAutoRoute(InitFaceVerifyRequest request) { +// // 第一个为主区域Endpoint,第二个为备区域Endpoint。 +// List endpoints = Arrays.asList("cloudauth.cn-shanghai.aliyuncs.com", +// "cloudauth.cn-beijing.aliyuncs.com"); +// InitFaceVerifyResponse lastResponse = null; +// for (String endpoint : endpoints) { +// try { +// InitFaceVerifyResponse response = initFaceVerify(endpoint, request); +// lastResponse = response; +// +// // 服务端错误,切换到下个区域调用。 +// if (response != null && "500".equals(response.getCode())) { +// continue; +// } +// +// return response; +// } catch (Exception e) { +// // 网络异常,切换到下个区域调用。 +// if (e.getCause() instanceof TeaException) { +// TeaException teaException = ((TeaException)e.getCause()); +// if (teaException.getData() != null && "ServiceUnavailable".equals( +// teaException.getData().get("Code"))) { +// continue; +// } +// } +// +// if (e.getCause() instanceof TeaUnretryableException) { +// continue; +// } +// } +// } +// +// return lastResponse; +// } +// +// private static InitFaceVerifyResponse initFaceVerify(String endpoint, InitFaceVerifyRequest request) +// throws Exception { +// Config config = new Config(); +// config.setAccessKeyId(AliApis.ofNew().accessKeyId); +// config.setAccessKeySecret(AliApis.ofNew().accessKeySecret); +// config.setEndpoint(endpoint); +// // 设置http代理。 +// //config.setHttpProxy("http://xx.xx.xx.xx:xxxx"); +// // 设置https代理。 +// //config.setHttpsProxy("https://xx.xx.xx.xx:xxxx"); +// Client client = new Client(config); +// +// // 创建RuntimeObject实例并设置运行参数。 +// RuntimeOptions runtime = new RuntimeOptions(); +// runtime.readTimeout = 10000; +// runtime.connectTimeout = 10000; +// +// return client.initFaceVerify(request, runtime); +// } +} \ No newline at end of file diff --git a/src/main/java/cn/stock/market/infrastructure/api/InitSmartVerify.java b/src/main/java/cn/stock/market/infrastructure/api/InitSmartVerify.java new file mode 100644 index 0000000..49fbaf6 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/api/InitSmartVerify.java @@ -0,0 +1,196 @@ +package cn.stock.market.infrastructure.api; + +import java.util.Arrays; +import java.util.List; + +import com.alibaba.fastjson.JSON; +import com.aliyun.cloudauth20200618.Client; +import com.aliyun.cloudauth20200618.models.InitSmartVerifyRequest; +import com.aliyun.cloudauth20200618.models.InitSmartVerifyResponse; +import com.aliyun.tea.TeaException; +import com.aliyun.tea.TeaUnretryableException; +import com.aliyun.tearpc.models.Config; +import com.aliyun.teautil.models.RuntimeOptions; + +import cn.hutool.core.lang.UUID; + +public class InitSmartVerify { + + public static InitSmartVerifyResponse idCardOcrPlus(String phoneNo, String metaInfo) throws Exception { + + // 通过以下代码创建API请求并设置参数。 + InitSmartVerifyRequest request = new InitSmartVerifyRequest(); + // 请输入场景ID+L。 + request.setSceneId(AliApis.SCENE_SFZ_PLUS); + request.setOuterOrderNo(UUID.fastUUID().toString()); + // 卡证核身类型,固定值。 + request.setMode("MARKET_SAFE"); + request.setOcr("T"); + // 证件类型,固定值。 + request.setCertType("IDENTITY_CARD"); + //request.setCertName("张三"); + //request.setCertNo("xxxx"); + // MetaInfo环境参数,需要通过客户端SDK获取。 + request.setMetaInfo(metaInfo); + request.setMobile(phoneNo); + //request.setIp("114.xxx.xxx.xxx"); + //request.setUserId("12345xxxx"); + //request.setCallbackUrl("https://www.aliyundoc.com"); + //request.setCallbackToken("xxxxxxx"); + + // 推荐,支持服务路由。 + InitSmartVerifyResponse response = initSmartVerifyAutoRoute(request); + + // 不支持服务自动路由。 + //InitSmartVerifyResponse response = initSmartVerify("cloudauth.cn-shanghai.aliyuncs.com", request); + + System.out.println(response.getRequestId()); + System.out.println(response.getCode()); + System.out.println(response.getMessage()); + System.out.println(response.getResultObject() == null ? null + : response.getResultObject().getCertifyId()); + + return response; + } + + public static InitSmartVerifyResponse idCardOcr(String phoneNo, String metaInfo) throws Exception { + // 通过以下代码创建API请求并设置参数。 + InitSmartVerifyRequest request = new InitSmartVerifyRequest(); + // 请输入场景ID+L。 + request.setSceneId(AliApis.SCENE_SFZ); + + request.setOuterOrderNo(UUID.fastUUID().toString()); + // 卡证核身类型,固定值。 + request.setMode("OCR"); + // 证件类型,固定值。 + request.setCertType("IDENTITY_CARD"); + // MetaInfo环境参数,需要通过客户端SDK获取。 + request.setMetaInfo(metaInfo); + request.setMobile(phoneNo); +// request.setIp("114.xxx.xxx.xxx"); +// request.setUserId(phoneNo); +// request.setCallbackUrl("https://www.aliyundoc.com"); +// request.setCallbackToken("xxxxx"); + + // 推荐,支持服务路由。 + InitSmartVerifyResponse response = initSmartVerifyAutoRoute(request); + + // 不支持服务自动路由。 + //InitSmartVerifyResponse response = initSmartVerify("cloudauth.cn-shanghai.aliyuncs.com", request); + + System.out.println(response.getRequestId()); + System.out.println(response.getCode()); + System.out.println(response.getMessage()); + System.out.println(response.getResultObject() == null ? null + : response.getResultObject().getCertifyId()); + + return response; + } + + public static InitSmartVerifyResponse initSmart(String phoneNo, String metaInfo, String idCardCertifyId, String facePictureUrl) throws Exception { + + // 通过以下代码创建API请求并设置参数。 + InitSmartVerifyRequest request = new InitSmartVerifyRequest(); + // 请输入场景ID+L。 + request.setSceneId(AliApis.SCENE); + request.setOuterOrderNo(UUID.fastUUID().toString()); + // 卡证核身类型,固定值。 + request.setMode("LOGIN_SAFE"); + // 证件类型,固定值。 + request.setCertType("IDENTITY_CARD"); + // request.setCertName("<张三>"); + // request.setCertNo(""); + // MetaInfo环境参数,需要通过客户端SDK获取。 + request.setMetaInfo(metaInfo); + request.setMobile(phoneNo); + //request.setIp("<114.xxx.xxx.xxx>"); + //request.setUserId("<12345xxxx>"); + //request.setCallbackUrl(""); + //request.setCallbackToken(""); + + // 请在以下四种方式中选择其一。 + // 1.人脸图片的Base64编码。 + // 2.已授权OSS空间的Bucket名和已授权OSS空间的文件名。 + // 3.人脸图片的HTTPS或HTTP地址。 + // 4.已通过智能核身得到的CertifyId,认证时的图片作为比对图片。 + + // 方式一:人脸图片的Base64编码。 + // request.setFacePictureBase64(""); + // 方式二:已授权OSS空间的Bucket名和已授权OSS空间的文件名。 + // request.setOssBucketName(""); + // request.setOssObjectName(""); + // 方式三:人脸图片的HTTPS或HTTP地址。 +// request.setFacePictureUrl(facePictureUrl); + // 方式四:已通过智能核身得到的CertifyId,认证时的图片作为比对图片。 + request.setCertifyId(idCardCertifyId); + + // 推荐,支持服务路由。 + InitSmartVerifyResponse response = initSmartVerifyAutoRoute(request); + + // 不支持服务自动路由。 + //InitSmartVerifyResponse response = initSmartVerify("cloudauth.cn-shanghai.aliyuncs.com", request); + System.out.println(JSON.toJSONString(request)); + System.out.println(response.getRequestId()); + System.out.println(response.getCode()); + System.out.println(response.getMessage()); + System.out.println(response.getResultObject() == null ? null + : response.getResultObject().getCertifyId()); + + return response; + } + + private static InitSmartVerifyResponse initSmartVerifyAutoRoute(InitSmartVerifyRequest request) { + // 第一个为主区域Endpoint,第二个为备区域Endpoint。 + List endpoints = Arrays.asList("cloudauth.cn-shanghai.aliyuncs.com", + "cloudauth.cn-beijing.aliyuncs.com"); + InitSmartVerifyResponse lastResponse = null; + for (String endpoint : endpoints) { + try { + InitSmartVerifyResponse response = initSmartVerify(endpoint, request); + lastResponse = response; + + // 服务端错误,切换到下个区域调用。 + if (response != null && "500".equals(response.getCode())) { + continue; + } + + return response; + } catch (Exception e) { + // 网络异常,切换到下个区域调用。 + if (e.getCause() instanceof TeaException) { + TeaException teaException = ((TeaException)e.getCause()); + if (teaException.getData() != null && "ServiceUnavailable".equals( + teaException.getData().get("Code"))) { + continue; + } + } + + if (e.getCause() instanceof TeaUnretryableException) { + continue; + } + } + } + + return lastResponse; + } + + private static InitSmartVerifyResponse initSmartVerify(String endpoint, InitSmartVerifyRequest request) + throws Exception { + Config config = new Config(); + config.setAccessKeyId(AliApis.ofNew().accessKeyId); + config.setAccessKeySecret(AliApis.ofNew().accessKeySecret); + config.setEndpoint(endpoint); + // 设置http代理。 + //config.setHttpProxy("http://xx.xx.xx.xx:xxxx"); + // 设置https代理。 + //config.setHttpsProxy("https://xx.xx.xx.xx:xxxx"); + Client client = new Client(config); + + // 创建RuntimeObject实例并设置运行参数。 + RuntimeOptions runtime = new RuntimeOptions(); + runtime.readTimeout = 10000; + runtime.connectTimeout = 10000; + + return client.initSmartVerify(request, runtime); + } +} diff --git a/src/main/java/cn/stock/market/infrastructure/api/JuheApis.java b/src/main/java/cn/stock/market/infrastructure/api/JuheApis.java new file mode 100644 index 0000000..2978d25 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/api/JuheApis.java @@ -0,0 +1,228 @@ +package cn.stock.market.infrastructure.api; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLEncoder; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; + +public class JuheApis { + //接口请求地址 + public static final String URL = "http://v.juhe.cn/sms/send?mobile=%s&tpl_id=%s&tpl_value=%s&key=%s"; + //申请接口的请求key + // TODO: 您需要改为自己的请求key + public static final String KEY = "33d215cc0c5a92e7e2d063c13300cd79"; + //此次发送短信需要使用的短信模板 + //3010模板对应的发送内容为:【聚合数据1】您的验证码是#code#.你还剩余次数#total#,如非本人操作,请忽略本短信 + //其中#code#是短信模板中的变量,用于开发者动态生成验证码 + //在运行代码的时候您需要改为自己拥有的模板 + // TODO: 您需要改为自己的模板id + + + public static final int SMS_RECHARGE = 249103; + public static final int SMS_WITHDRAWAL = 249105; + public static final int SMS_OPEN = 249104; + public static final int SMS_VERIFY_CODE = 249100; + public static final int SMS_WARN = 250126; + public static final int SMS_POSITION_ADD = 250318; + + public static void main(String[] args) { + //用于接收短信的手机号码,你需要修改此处 + // TODO: 改为自己手机号测试看看 + String mobile = "15390891113"; + //短信模板中的您自定义的变量 + // TODO: 改为您模板中的需要的变量 + String variable = "#code#=12345&#total#=100"; +// send(mobile,SMS_VERIFY_CODE, variable); + + send(mobile,SMS_WARN, variable); + } + + /** + * 打印请求结果 + * + * @param mobile 手机号 + * @param variable 模板变量 + */ + public static JSONObject send(String mobile, int code, String variable) { + if(variable == null) { + variable = ""; + } + //发送http请求的url + String url = null; + try { + url = String.format(URL, mobile, code, URLEncoder.encode(variable, "utf-8"), KEY); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + String response = doGet(url); + System.out.println(response); + JSONObject jsonObject = JSON.parseObject(response); + int error_code = jsonObject.getIntValue("error_code"); + if (error_code == 0) { + System.out.println("调用接口成功"); + JSONObject result = jsonObject.getJSONObject("result"); + String sid = result.getString("sid"); + int fee = result.getIntValue("fee"); + System.out.println("本次发送的唯一标示:" + sid); + System.out.println("本次发送消耗的次数:" + fee); + }else{ + System.out.println("调用接口失败:"+ jsonObject.getString("reason")); + } + + return jsonObject; + } + + /** + * get方式的http请求 + * + * @param httpUrl 请求地址 + * @return 返回结果 + */ + public static String doGet(String httpUrl) { + HttpURLConnection connection = null; + InputStream inputStream = null; + BufferedReader bufferedReader = null; + String result = null;// 返回结果字符串 + try { + // 创建远程url连接对象 + URL url = new URL(httpUrl); + // 通过远程url连接对象打开一个连接,强转成httpURLConnection类 + connection = (HttpURLConnection) url.openConnection(); + // 设置连接方式:get + connection.setRequestMethod("GET"); + // 设置连接主机服务器的超时时间:15000毫秒 + connection.setConnectTimeout(15000); + // 设置读取远程返回的数据时间:60000毫秒 + connection.setReadTimeout(60000); + // 发送请求 + connection.connect(); + // 通过connection连接,获取输入流 + if (connection.getResponseCode() == 200) { + inputStream = connection.getInputStream(); + // 封装输入流,并指定字符集 + bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); + // 存放数据 + StringBuilder sbf = new StringBuilder(); + String temp; + while ((temp = bufferedReader.readLine()) != null) { + sbf.append(temp); + sbf.append(System.getProperty("line.separator")); + } + result = sbf.toString(); + } + } catch (MalformedURLException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + // 关闭资源 + if (null != bufferedReader) { + try { + bufferedReader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (null != inputStream) { + try { + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (connection != null) { + connection.disconnect();// 关闭远程连接 + } + } + return result; + } + + + /** + * post方式的http请求 + * + * @param httpUrl 请求地址 + * @param param 请求参数 + * @return 返回结果 + */ + public static String doPost(String httpUrl, String param) { + HttpURLConnection connection = null; + InputStream inputStream = null; + OutputStream outputStream = null; + BufferedReader bufferedReader = null; + String result = null; + try { + URL url = new URL(httpUrl); + // 通过远程url连接对象打开连接 + connection = (HttpURLConnection) url.openConnection(); + // 设置连接请求方式 + connection.setRequestMethod("POST"); + // 设置连接主机服务器超时时间:15000毫秒 + connection.setConnectTimeout(15000); + // 设置读取主机服务器返回数据超时时间:60000毫秒 + connection.setReadTimeout(60000); + // 默认值为:false,当向远程服务器传送数据/写数据时,需要设置为true + connection.setDoOutput(true); + // 设置传入参数的格式:请求参数应该是 name1=value1&name2=value2 的形式。 + connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + // 通过连接对象获取一个输出流 + outputStream = connection.getOutputStream(); + // 通过输出流对象将参数写出去/传输出去,它是通过字节数组写出的 + outputStream.write(param.getBytes()); + // 通过连接对象获取一个输入流,向远程读取 + if (connection.getResponseCode() == 200) { + inputStream = connection.getInputStream(); + // 对输入流对象进行包装:charset根据工作项目组的要求来设置 + bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); + StringBuilder sbf = new StringBuilder(); + String temp; + // 循环遍历一行一行读取数据 + while ((temp = bufferedReader.readLine()) != null) { + sbf.append(temp); + sbf.append(System.getProperty("line.separator")); + } + result = sbf.toString(); + } + } catch (MalformedURLException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + // 关闭资源 + if (null != bufferedReader) { + try { + bufferedReader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (null != outputStream) { + try { + outputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (null != inputStream) { + try { + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (connection != null) { + connection.disconnect(); + } + } + return result; + } +} diff --git a/src/main/java/cn/stock/market/infrastructure/api/StockRealTime.java b/src/main/java/cn/stock/market/infrastructure/api/StockRealTime.java new file mode 100644 index 0000000..c5adfa1 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/api/StockRealTime.java @@ -0,0 +1,39 @@ +package cn.stock.market.infrastructure.api; + +import lombok.Data; + +@Data +public class StockRealTime { +// @JSONField(name = "Symbol") + String symbol; //A 股股票代码 +// @JSONField(name = "StockName") + String stockName; //股票名称 +// @JSONField(name = "Latest") + Double latest; //最新价,单位:元 +// @JSONField(name = "ChangePercent") + Double changePercent; //涨跌幅,单位:% +// @JSONField(name = "ChangeAmount") + Double changeAmount; //涨跌额,单位:元 +// @JSONField(name = "TradingVolume") + Double tradingVolume; //成交量,单位:手 +// @JSONField(name = "TradingAmount") + Double tradingAmount; //成交额,单位:元 +// @JSONField(name = "Swing") + Double swing; //振幅,单位:% +// @JSONField(name = "High") + Double high; //最高,单位:元 +// @JSONField(name = "Low") + Double low; //最低,单位:元 +// @JSONField(name = "Open") + Double open; //今日开盘价,单位:元 +// @JSONField(name = "PreClose") + Double preClose; //昨收价,单位:元 +// @JSONField(name = "QuantityRatio") + Double quantityRatio; //量比 +// @JSONField(name = "TurnoverRate") + Double turnoverRate; //换手率,单位:% +// @JSONField(name = "PERatioDynamic") + Double peRatioDynamic; //市盈率-动态 +// @JSONField(name = "PBRatio") + Double pbRatio; //市净率 +} diff --git a/src/main/java/cn/stock/market/infrastructure/api/TxApis.java b/src/main/java/cn/stock/market/infrastructure/api/TxApis.java new file mode 100644 index 0000000..3ed7dc8 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/api/TxApis.java @@ -0,0 +1,102 @@ +package cn.stock.market.infrastructure.api; + +import com.ag.exception.SysTipsException; +import com.ag.utils.Jsons; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.tencentcloudapi.common.Credential; +import com.tencentcloudapi.common.exception.TencentCloudSDKException; +import com.tencentcloudapi.common.profile.ClientProfile; +import com.tencentcloudapi.common.profile.HttpProfile; +import com.tencentcloudapi.faceid.v20180301.FaceidClient; +import com.tencentcloudapi.faceid.v20180301.models.DetectAuthRequest; +import com.tencentcloudapi.faceid.v20180301.models.DetectAuthResponse; +import com.tencentcloudapi.faceid.v20180301.models.GetDetectInfoRequest; +import com.tencentcloudapi.faceid.v20180301.models.GetDetectInfoResponse; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class TxApis { + public String accessKeyId = ""; + public String accessKeySecret = ""; + public static String ruleId = "1"; + + public TxApis(String accessKeyId, String accessKeySecret) { + this.accessKeyId = accessKeyId; + this.accessKeySecret = accessKeySecret; + } + + /** + * https://cloud.tencent.com/document/product/1007/31816 + * @param ruleId + * @return + */ + public DetectAuthResponse detectAuth(String ruleId) { + // 实例化一个认证对象,入参需要传入腾讯云账户secretId,secretKey,此处还需注意密钥对的保密 + // 密钥可前往https://console.cloud.tencent.com/cam/capi网站进行获取 + Credential cred = new Credential(accessKeyId, accessKeySecret); + // 实例化一个http选项,可选的,没有特殊需求可以跳过 + HttpProfile httpProfile = new HttpProfile(); + httpProfile.setEndpoint("faceid.tencentcloudapi.com"); + // 实例化一个client选项,可选的,没有特殊需求可以跳过 + ClientProfile clientProfile = new ClientProfile(); + clientProfile.setHttpProfile(httpProfile); + // 实例化要请求产品的client对象,clientProfile是可选的 + FaceidClient client = new FaceidClient(cred, "", clientProfile); + // 实例化一个请求对象,每个接口都会对应一个request对象 + DetectAuthRequest req = new DetectAuthRequest(); + req.setRuleId(ruleId); + try { + // 返回的resp是一个DetectAuthResponse的实例,与请求对象对应 + DetectAuthResponse resp = client.DetectAuth(req); + + return resp; + } catch (TencentCloudSDKException e) { + throw new SysTipsException(e.toString()); + } + } + + public GetDetectInfoResponse getDetectInfo(String ruleId, String bizToken) { + // 实例化一个认证对象,入参需要传入腾讯云账户secretId,secretKey,此处还需注意密钥对的保密 + // 密钥可前往https://console.cloud.tencent.com/cam/capi网站进行获取 + Credential cred = new Credential(accessKeyId, accessKeySecret); + // 实例化一个http选项,可选的,没有特殊需求可以跳过 + HttpProfile httpProfile = new HttpProfile(); + httpProfile.setEndpoint("faceid.tencentcloudapi.com"); + // 实例化一个client选项,可选的,没有特殊需求可以跳过 + ClientProfile clientProfile = new ClientProfile(); + clientProfile.setHttpProfile(httpProfile); + // 实例化要请求产品的client对象,clientProfile是可选的 + FaceidClient client = new FaceidClient(cred, "", clientProfile); + // 实例化一个请求对象,每个接口都会对应一个request对象 + GetDetectInfoRequest req = new GetDetectInfoRequest(); + req.setBizToken(bizToken); + req.setRuleId(ruleId); + + try { + // 返回的resp是一个GetDetectInfoResponse的实例,与请求对象对应 + GetDetectInfoResponse resp = client.GetDetectInfo(req); + return resp; + } catch (TencentCloudSDKException e) { + throw new SysTipsException(e.toString()); + } + } + + public static TxApis of() { +// return new TxApis("AKIDmOmvpUu51h9LI0TggS5TcV9YjfQyGJ7g", "MVSBfutd8NOAi03qSpxpSqzsWw72iBPN"); + return new TxApis("AKIDswxo3GIG42oeNyslUzIOIwMYbefbfYGn", "l0CAxVqxoQ0d5ZJvLYYM2Wp0znOvKVVT"); + } + + public static void main(String[] args) { + TxApis apis = of(); + DetectAuthResponse detectAuth = apis.detectAuth(ruleId); + System.out.println(JSON.toJSONString(detectAuth)); + +// String bizToken = "97404E85-2E9A-4E2D-9853-A912561CD2B0"; +// GetDetectInfoResponse response = TxApis.of().getDetectInfo(TxApis.ruleId, bizToken); +// JSONObject text = Jsons.getByPath(response.getDetectInfo(), "Text", JSONObject.class); +// +// System.out.println(text); + } +} diff --git a/src/main/java/cn/stock/market/infrastructure/api/qq/QqStockApi.java b/src/main/java/cn/stock/market/infrastructure/api/qq/QqStockApi.java new file mode 100644 index 0000000..3b9e1e2 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/api/qq/QqStockApi.java @@ -0,0 +1,399 @@ +package cn.stock.market.infrastructure.api.qq; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import cn.hutool.core.lang.TypeReference; +import com.ag.utils.JsonUtils; +import com.ag.utils.Jsons; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.ag.utils.NumberUtils; + +import cn.hutool.http.HttpUtil; +import cn.qutaojing.common.utils.BigDecimals; +import cn.stock.market.domain.basic.entity.Stock; +import cn.stock.market.infrastructure.api.sina.SinaStockApi; +import cn.stock.market.infrastructure.api.sina.vo.SinaStockMinData; +import cn.stock.market.infrastructure.api.sina.vo.k.MinDataVO; +import cn.stock.market.utils.HttpClientRequest; +import cn.stock.market.utils.PropertiesUtil; +import cn.stock.market.utils.ServerResponse; +import net.sf.json.JSONArray; +import net.sf.json.JSONObject; + +public class QqStockApi { + private static final Logger log = LoggerFactory.getLogger(SinaStockApi.class); + + public static ServerResponse getGpStockDayK(Stock stock) { + String minUrl = PropertiesUtil.getProperty("qq.k.min.url"); + minUrl = minUrl.replace("code",stock.getStockGid()); + + String hqstr = ""; + try { + hqstr = HttpClientRequest.doGet(minUrl); + } catch (Exception e) { + log.error("获取股票K线分时图出错,错误信息 = {}", e); + } + + log.info(" qq-code = {} ", stock.getStockGid()); + if (StringUtils.isBlank(hqstr)) { + return ServerResponse.createByErrorMsg("没有查询到行情数据"); + } + String qqstr = hqstr.split("=")[1].replace("\";","").replace("\\n\\",",").replace("\n","").replace("\"",""); + String[] liststr = qqstr.split(","); + List list = new ArrayList<>(); + for (int i = 1; isize){ + list = list.subList((list.size()-size-1),list.size()); + } + MinDataVO minDataVO = new MinDataVO(); + minDataVO.setStockName(stock.getStockName()); + minDataVO.setStockCode(stock.getStockCode()); + minDataVO.setGid(stock.getStockGid()); + minDataVO.setData(list); + return ServerResponse.createBySuccess(minDataVO); + } + +// public static ServerResponse getQqStockDayK(StockFutures stock) { +// String minUrl = PropertiesUtil.getProperty("sina.futures.day.min.url"); +// minUrl = minUrl.replace("{code}",stock.getFuturesCode()); +// SimpleDateFormat df = new SimpleDateFormat("yyyy_MM_dd");//设置日期格式 +// minUrl = minUrl.replace("{date}",df.format(new Date())); +// +// +// String hqstr = ""; +// try { +// hqstr = HttpClientRequest.doGet(minUrl); +// } catch (Exception e) { +// log.error("获取股票K线分时图出错,错误信息 = {}", e); +// } +// +// log.info(" 期货日线-code = {} ", stock.getFuturesGid()); +// if (StringUtils.isBlank(hqstr)) { +// return ServerResponse.createByErrorMsg("没有查询到行情数据"); +// } +// hqstr = hqstr.split("\\(")[1].replace(");",""); +// hqstr = hqstr.replaceAll("date","day"); +// hqstr = hqstr.replaceAll("\"\"", "\""); +// +// List list = (List) JsonUtil.string2Obj(hqstr, new TypeReference>(){}); +// int size = Integer.valueOf(PropertiesUtil.getProperty("sina.futures.day.min.max.size")); +// if(list.size()>size){ +// list = list.subList((list.size()-size-1),list.size()); +// } +// +// MinDataVO minDataVO = new MinDataVO(); +// minDataVO.setStockName(stock.getFuturesName()); +// minDataVO.setStockCode(stock.getFuturesCode()); +// minDataVO.setGid(stock.getFuturesGid()); +// minDataVO.setData(list); +// return ServerResponse.createBySuccess(minDataVO); +// } +// + /*指数日线*/ + public static ServerResponse getQqIndexDayK(String stock, String type) { + String minUrl = PropertiesUtil.getProperty("sina.index.day.min.url"); + minUrl = minUrl.replace("{code}",stock); + minUrl = minUrl.replace("day",type); + SimpleDateFormat df = new SimpleDateFormat("yyyy_MM_dd");//设置日期格式 + minUrl = minUrl.replace("{date}",df.format(new Date())); + + + String hqstr = ""; + try { + hqstr = HttpClientRequest.doGet(minUrl); + } catch (Exception e) { + log.error("获取股票K线分时图出错,错误信息 = {}", e); + } + + log.info(" 指数日线-code = {} ", stock); + if (StringUtils.isBlank(hqstr)) { + return ServerResponse.createByErrorMsg("没有查询到行情数据"); + } + hqstr = hqstr.split(":\\[\\[")[1]; + hqstr = hqstr.split("]]")[0].replace("],[",";"); + String[] liststr = hqstr.split(";"); + List list = new ArrayList<>(); + for (int i = 1; i getIndexMinK(String stock, int time, int size) { + String minUrl = PropertiesUtil.getProperty("sina.index.k.min.url").replace("{code}", stock).replace("{time}",String.valueOf(time)); + String stamp = String.valueOf(new Date().getTime());// new Date()为获取当前系统时间 + minUrl = minUrl.replace("{stamp}",stamp); + + String hqstr = ""; + try { + hqstr = HttpClientRequest.doGet(minUrl); + } catch (Exception e) { + log.error("获取股票K线分时图出错,错误信息 = {}", e); + } + + log.info("期货分时 - time = {} ", time); + + hqstr = hqstr.split("\\[")[1].replace("]);",""); + + if (StringUtils.isBlank(hqstr)) { + return ServerResponse.createByErrorMsg("没有查询到行情数据"); + } + + MinDataVO minDataVO = new MinDataVO(); +// minDataVO.setStockName(stock.getIndexName()); + minDataVO.setStockCode(stock); +// minDataVO.setGid(stock.getIndexGid()); + + hqstr = hqstr.replaceAll("\"\"", "\""); + hqstr = "[" + hqstr + "]"; + + List list = Jsons.toList(hqstr,SinaStockMinData.class); + if(list.size()>size){ + list = list.subList((list.size()-size-1),list.size()); + } + minDataVO.setData(list); + return ServerResponse.createBySuccess(minDataVO); + } + + /** + * 使用java正则表达式去掉多余的.与0 + * @param s + * @return + */ + public static String subZeroAndDot(String s){ + BigDecimal value = new BigDecimal(s); + BigDecimal noZeros = value.stripTrailingZeros(); + String result = noZeros.toPlainString(); + return result; + } + + private static String filterCode(String str) { + return str.replace("\"",""); + } + + /*股票月线、周线 + * type:month=月,week=周, day=天 + * */ + public static ServerResponse getGpStockMonthK(Stock stock,String type) { + String minUrl = PropertiesUtil.getProperty("qq.month.min.url"); + minUrl = minUrl.replace("sz300750",stock.getStockGid()); + minUrl = minUrl.replace("month",type); + + String hqstr = ""; + try { + hqstr = HttpClientRequest.doGet(minUrl); +// hqstr = hqstr.replace("qfqday","day"); + } catch (Exception e) { + log.error("获取股票K线分时图出错,错误信息 = {}", e); + } + + log.info("{} type:{}, 返回信息:{}", stock.getStockCode(), type, hqstr); + + String typeKey = ""; + /** + * 备用Key + */ + String typeKeyBak = ""; + if("day".equalsIgnoreCase(type)) { + typeKey = "qfqday"; + typeKeyBak = "day"; + } else if("week".equalsIgnoreCase(type)) { + typeKeyBak = "week"; + typeKey = "qfqweek"; + } else if("month".equalsIgnoreCase(type)) { + typeKeyBak = "month"; + typeKey = "qfqmonth"; + } + + log.info(" qq-code = {} ", stock.getStockGid()); + if (StringUtils.isBlank(hqstr)) { + return ServerResponse.createByErrorMsg("没有查询到行情数据"); + } + //String qqstr = hqstr.split("=")[1]; + JSONObject json = JSONObject.fromObject(hqstr); + JSONObject data = json.getJSONObject("data"); + JSONObject listjson = data.getJSONObject(stock.getStockGid()); + + JSONArray jsonArray = null; + if(listjson.has(typeKey)) { + jsonArray = listjson.getJSONArray(typeKey); + } else { + jsonArray = listjson.getJSONArray(typeKeyBak); + } + + List list = new ArrayList<>(); + for (int i = 0; i50){ +// list = list.subList((list.size()-50),list.size()); +// } + + MinDataVO minDataVO = new MinDataVO(); + minDataVO.setStockName(stock.getStockName()); + minDataVO.setStockCode(stock.getStockCode()); + minDataVO.setGid(stock.getStockGid()); + minDataVO.setData(list); + return ServerResponse.createBySuccess(minDataVO); + } + + /*股票月线、周线 + * type:month=月,week=周, day=天 + * */ + public static ServerResponse getBjsStockMonthK(Stock stock,String type) { + String minUrl = PropertiesUtil.getProperty("eastmoney.month.url"); + minUrl = minUrl.replace("0.833429","0."+stock.getStockCode()); + minUrl = minUrl.replace("_=1699356882499","_"+System.currentTimeMillis()); + String klt = "101"; + if ("week".equals(type)){ + klt = "102"; + } else if ("month".equals(type)) { + klt = "103"; + } + minUrl = minUrl.replace("klt=102","klt="+klt); + + String hqstr = ""; + try { + hqstr = HttpClientRequest.doGet(minUrl); + } catch (Exception e) { + log.error("获取股票K线分时图出错,错误信息 = {}", e); + } + + log.info("{} type:{}, 返回信息:{}", stock.getStockCode(), type, hqstr); + hqstr = hqstr.replace("jQuery3510019847947565290847_1699356882415(",""); + hqstr = hqstr.substring(0,hqstr.length()-2); + JSONObject json = JSONObject.fromObject(hqstr); + JSONObject data = json.getJSONObject("data"); + JSONArray jsonArray = data.getJSONArray("klines"); + + List list = new ArrayList<>(); + for (int i = 0; i getHQNodeData(int asc, int pageNum, int pageSize) { + String url = String.format("https://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQNodeData?page=%s&num=%s&sort=changepercent&asc=%s&node=hs_a&symbol=&_s_r_a=setlen", pageNum, pageSize, asc); + String reponse = ""; + try { + reponse = get(url); + JSONArray array = JSON.parseArray(reponse); + //过滤bj开头 + return Lists.transform(array, item -> (JSONObject) item) + .stream() +// .filter(j -> ! StringUtils.startsWith(j.getString("symbol"), "bj")) + .collect(Collectors.toList()) + ; + } catch (Exception e) { + log.error("获取股票行情出错,错误信息 = {}", e); + } + + return Lists.newArrayList(); + } + + public static String getRawSinaStock(String stockGid) { + String sina_url = PropertiesUtil.getProperty("sina.single.stock.url"); + String sina_result = ""; + try { + sina_result = get(sina_url + stockGid); + } catch (Exception e) { + log.error("获取股票行情出错,错误信息 = {}", e); + } + + return sina_result; + } + + public static String getSinaStock(String stockGid) { + String sina_result = getRawSinaStock(stockGid); + + if(! StringUtils.contains(sina_result, "=")) { + log.error("{}获取行情失败: {}", stockGid, sina_result); + throw new SysTipsException("获取行情失败:" + stockGid); + } + return sina_result.substring(sina_result.indexOf("=") + 2); + } + + + public static StockListVO assembleStockListVO(String sinaResult) { + StockListVO stockListVO = new StockListVO(); + + String[] hqarr = sinaResult.split(","); + + if (hqarr.length > 1) { + + stockListVO.setName(hqarr[0]); + + stockListVO.setNowPrice(hqarr[3]); + + BigDecimal chang_rate = new BigDecimal("0"); + if ((new BigDecimal(hqarr[2])).compareTo(new BigDecimal("0")) != 0 && new BigDecimal(hqarr[3]).compareTo(new BigDecimal("0")) != 0) { + + chang_rate = (new BigDecimal(hqarr[3])).subtract(new BigDecimal(hqarr[2])); + + chang_rate = chang_rate.multiply(new BigDecimal("100")).divide(new BigDecimal(hqarr[2]), 2, RoundingMode.HALF_UP); + } + stockListVO.setHcrate(chang_rate); + + stockListVO.setToday_max(hqarr[4]); + + stockListVO.setToday_min(hqarr[5]); + + stockListVO.setBusiness_amount(hqarr[8]); + + stockListVO.setBusiness_balance(hqarr[9]); + + stockListVO.setPreclose_px(hqarr[2]); + + stockListVO.setOpen_px(hqarr[1]); + } + + return stockListVO; + } + + public static StockVO assembleStockVO(String sinaResult, Stock stock) { + if(stock == null) { + return null; + } + StockVO stockVO = SinaStockApi.assembleStockVO(SinaStockApi.getSinaStock(stock.getStockGid())); + stockVO.setId(stock.getId().intValue()); + stockVO.setCode(stock.getStockCode()); + stockVO.setSpell(stock.getStockSpell()); + stockVO.setGid(stock.getStockGid()); + return stockVO; + } + public static StockVO assembleStockVO(String sinaResult) { + StockVO stockVO = new StockVO(); + + String[] hqarr = sinaResult.split(","); + + stockVO.setName(hqarr[0]); + + stockVO.setNowPrice(hqarr[3]); + + BigDecimal chang_rate = new BigDecimal("0"); + if ((new BigDecimal(hqarr[2])).compareTo(new BigDecimal("0")) != 0 && new BigDecimal(hqarr[3]).compareTo(new BigDecimal("0")) != 0) { + + chang_rate = (new BigDecimal(hqarr[3])).subtract(new BigDecimal(hqarr[2])); + + chang_rate = chang_rate.multiply(new BigDecimal("100")).divide(new BigDecimal(hqarr[2]), 2, RoundingMode.HALF_UP); + } + stockVO.setHcrate(chang_rate); + + stockVO.setToday_max(hqarr[4]); + + stockVO.setToday_min(hqarr[5]); + + stockVO.setBusiness_amount(hqarr[8]); + + stockVO.setBusiness_balance(hqarr[9]); + + stockVO.setPreclose_px(hqarr[2]); + + stockVO.setOpen_px(hqarr[1]); + + stockVO.setBuy1(hqarr[6]); + stockVO.setBuy2(hqarr[13]); + stockVO.setBuy3(hqarr[15]); + stockVO.setBuy4(hqarr[17]); + stockVO.setBuy5(hqarr[19]); + + stockVO.setSell1(hqarr[7]); + stockVO.setSell2(hqarr[23]); + stockVO.setSell3(hqarr[25]); + stockVO.setSell4(hqarr[27]); + stockVO.setSell5(hqarr[29]); + + stockVO.setBuy1_num(hqarr[10]); + stockVO.setBuy2_num(hqarr[12]); + stockVO.setBuy3_num(hqarr[14]); + stockVO.setBuy4_num(hqarr[16]); + stockVO.setBuy5_num(hqarr[18]); + + stockVO.setSell1_num(hqarr[20]); + stockVO.setSell2_num(hqarr[22]); + stockVO.setSell3_num(hqarr[24]); + stockVO.setSell4_num(hqarr[26]); + stockVO.setSell5_num(hqarr[28]); + + return stockVO; + } + + /*期货详情转换*/ + public static StockVO assembleStockFuturesVO(String sinaResult) { + StockVO stockVO = new StockVO(); + + String[] hqarr = sinaResult.split(","); + //伦敦金格式不正确,特殊处理 + if(hqarr.length<=14){ + String sinaResulttemp = sinaResult.replace("\"",",1\""); + hqarr = sinaResulttemp.split(","); + } + stockVO.setName(hqarr[13]); + + stockVO.setNowPrice(hqarr[0]); + + BigDecimal rates = new BigDecimal("0"); + BigDecimal b1 = new BigDecimal(hqarr[3].toString()); + BigDecimal b2 = new BigDecimal(hqarr[2].toString()); + BigDecimal b3 = b1.subtract(b2); + String s = hqarr[14].toString(); + int index = s.indexOf("\""); + String substring = s.substring(0, index); + rates = b3.multiply(new BigDecimal("100")).divide(b1,2,BigDecimal.ROUND_HALF_UP); + stockVO.setHcrate(rates); + + stockVO.setToday_max(hqarr[7]); + + stockVO.setToday_min(hqarr[8]); + + stockVO.setBusiness_amount(substring); + + stockVO.setBusiness_balance(hqarr[9]); + + stockVO.setPreclose_px(hqarr[11]); + + stockVO.setOpen_px(hqarr[10]); + + stockVO.setBuy1(hqarr[2]); + stockVO.setBuy2("0"); + stockVO.setBuy3("0"); + stockVO.setBuy4("0"); + stockVO.setBuy5("0"); + + stockVO.setSell1(hqarr[3]); + stockVO.setSell2("0"); + stockVO.setSell3("0"); + stockVO.setSell4("0"); + stockVO.setSell5("0"); + + stockVO.setBuy1_num(hqarr[10]); + stockVO.setBuy2_num("0"); + stockVO.setBuy3_num("0"); + stockVO.setBuy4_num("0"); + stockVO.setBuy5_num("0"); + + stockVO.setSell1_num(hqarr[11]); + stockVO.setSell2_num("0"); + stockVO.setSell3_num("0"); + stockVO.setSell4_num("0"); + stockVO.setSell5_num("0"); + + return stockVO; + } + + + public static ServerResponse getStockMinK(Stock stock, int time, int ma, int size) { + int maxSize = Integer.parseInt(PropertiesUtil.getProperty("sina.k.min.max.size")); + if (size > maxSize) { + size = maxSize; + } + + String minUrl = PropertiesUtil.getProperty("sina.k.min.url"); + minUrl = minUrl + "?symbol=" + stock.getStockGid() + "&scale=" + time + "&ma=" + ma + "&datalen=" + size; + + String hqstr = ""; + try { + hqstr = get(minUrl); + } catch (Exception e) { + log.error("获取股票K线分时图出错,错误信息 = {}", e); + } + + log.info(" time = {} ma = {} size = {}", new Object[]{Integer.valueOf(time), Integer.valueOf(ma), Integer.valueOf(size)}); + + + hqstr = hqstr.replace("day", "\"day\"").replace("open", "\"open\"").replace("high", "\"high\"").replace("low", "\"low\"").replace("close", "\"close\""); + + if (ma == 5) { + + hqstr = hqstr.replace("ma_volume5", "\"ma_volume\"").replace(",volume", ",\"volume\"").replace("ma_price5", "\"ma_price\""); + } else if (ma == 10) { + + + hqstr = hqstr.replace("ma_volume10", "\"ma_volume\"").replace(",volume", ",\"volume\"").replace("ma_price10", "\"ma_price\""); + } else if (ma == 15) { + + hqstr = hqstr.replace("ma_volume15", "\"ma_volume\"").replace(",volume", ",\"volume\"").replace("ma_price15", "\"ma_price\""); + } else { + return ServerResponse.createByErrorMsg("ma 取值 5,10,15"); + } + + + if (StringUtils.isBlank(hqstr)) { + return ServerResponse.createByErrorMsg("没有查询到行情数据"); + } + + MinDataVO minDataVO = new MinDataVO(); + minDataVO.setStockName(stock.getStockName()); + minDataVO.setStockCode(stock.getStockCode()); + minDataVO.setGid(stock.getStockGid()); + + hqstr = hqstr.replaceAll("\"\"", "\""); + + List list = Jsons.toList(hqstr, SinaStockMinData.class); + log.info("需要查询的行情size为: {}", Integer.valueOf(size)); + + minDataVO.setData(list); + + return ServerResponse.createBySuccess(minDataVO); + } + + + public static ServerResponse getKLine(String code) { + String url = null; + switch (code) { + case "399006": + //创业板分时接口 + url = "http://push2delay.eastmoney.com/api/qt/stock/trends2/get?secid=0.399006&fields1=f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13&fields2=f51,f52,f53,f54,f55,f56,f57,f58&ut=e1e6871893c6386c5ff6967026016627&iscr=0&cb=cb_1688350355026_68094768&isqhquote=&cb_1688350355026_68094768=cb_1688350355026_68094768"; + break; + case "399001": + //深证指数分时接口 + url = "http://push2.eastmoney.com/api/qt/stock/trends2/get?secid=0.399001&fields1=f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13&fields2=f51,f52,f53,f54,f55,f56,f57,f58&ut=e1e6871893c6386c5ff6967026016627&iscr=0&cb=cb_1688350355026_56868727&isqhquote=&cb_1688350355026_56868727=cb_1688350355026_56868727"; + break; + case "000001": + //上证指数分时接口 + url = "http://push2.eastmoney.com/api/qt/stock/trends2/get?secid=1.000001&fields1=f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13&fields2=f51,f52,f53,f54,f55,f56,f57,f58&ut=e1e6871893c6386c5ff6967026016627&iscr=0&cb=cb_1688350355023_98652553&isqhquote=&cb_1688350355023_98652553=cb_1688350355023_98652553"; + break; + default: + //不支持 + return ServerResponse.createByErrorMsg("不支持的股票代码"); + } + String reponse = get(url); + //cb_1688350355023_98652553({ json )} 转换为json + reponse = reponse.substring(reponse.indexOf("(") + 1, reponse.lastIndexOf(")")); + return ServerResponse.createBySuccess(JSONObject.parseObject(reponse)); + } + + public static EchartsDataVO assembleEchartsDataVO(MinDataVO minDataVO) { + EchartsDataVO echartsDataVO = new EchartsDataVO(); + echartsDataVO.setStockName(minDataVO.getStockName()); + echartsDataVO.setStockCode(minDataVO.getStockCode()); + + List minDataList = minDataVO.getData(); + + + double[][] values = (double[][]) null; + Object[][] volumes = (Object[][]) null; + String[] date = null; + + if (minDataList.size() > 0) { + + values = new double[minDataList.size()][5]; + + volumes = new Object[minDataList.size()][3]; + + date = new String[minDataList.size()]; + + for (int i = 0; i < minDataList.size(); i++) { + SinaStockMinData sinaStockMinData = (SinaStockMinData) minDataList.get(i); + + for (int j = 0; j < values[i].length; j++) { + values[i][0] = Double.valueOf(sinaStockMinData.getOpen()).doubleValue(); + values[i][1] = Double.valueOf(sinaStockMinData.getClose()).doubleValue(); + values[i][2] = Double.valueOf(sinaStockMinData.getLow()).doubleValue(); + values[i][3] = Double.valueOf(sinaStockMinData.getHigh()).doubleValue(); + values[i][4] = Double.valueOf(sinaStockMinData.getVolume()).doubleValue(); + } + for (int k = 0; k < volumes[i].length; k++) { + volumes[i][0] = Integer.valueOf(i); + volumes[i][1] = Double.valueOf(sinaStockMinData.getVolume()); + + if ((new BigDecimal(sinaStockMinData.getClose())) + .compareTo(new BigDecimal(sinaStockMinData.getOpen())) == 1) { + volumes[i][2] = Integer.valueOf(1); + } else { + volumes[i][2] = Integer.valueOf(-1); + } + } + + date[i] = sinaStockMinData.getDay(); + } + } + + echartsDataVO.setValues(values); + echartsDataVO.setVolumes(volumes); + echartsDataVO.setDate(date); + + return echartsDataVO; + } + + /*股票日线*/ + public static ServerResponse getStockDayK(Stock stock, int time, int ma, int size) { + int maxSize = Integer.parseInt(PropertiesUtil.getProperty("sina.k.min.max.size")); + if (size > maxSize) { + size = maxSize; + } + + String minUrl = PropertiesUtil.getProperty("sina.k.min.url"); + minUrl = minUrl + "?symbol=" + stock.getStockGid() + "&scale=" + time + "&ma=" + ma + "&datalen=" + size; + + String hqstr = ""; + try { + hqstr = get(minUrl); + } catch (Exception e) { + log.error("获取股票K线分时图出错,错误信息 = {}", e); + } + + log.info(" time = {} ma = {} size = {}", new Object[]{Integer.valueOf(time), Integer.valueOf(ma), Integer.valueOf(size)}); + + + hqstr = hqstr.replace("day", "\"day\"").replace("open", "\"open\"").replace("high", "\"high\"").replace("low", "\"low\"").replace("close", "\"close\""); + + if (ma == 5) { + + hqstr = hqstr.replace("ma_volume5", "\"ma_volume\"").replace(",volume", ",\"volume\"").replace("ma_price5", "\"ma_price\""); + } else if (ma == 10) { + + + hqstr = hqstr.replace("ma_volume10", "\"ma_volume\"").replace(",volume", ",\"volume\"").replace("ma_price10", "\"ma_price\""); + } else if (ma == 15) { + + hqstr = hqstr.replace("ma_volume15", "\"ma_volume\"").replace(",volume", ",\"volume\"").replace("ma_price15", "\"ma_price\""); + } else { + return ServerResponse.createByErrorMsg("ma 取值 5,10,15"); + } + + + if (StringUtils.isBlank(hqstr)) { + return ServerResponse.createByErrorMsg("没有查询到行情数据"); + } + + MinDataVO minDataVO = new MinDataVO(); + minDataVO.setStockName(stock.getStockName()); + minDataVO.setStockCode(stock.getStockCode()); + minDataVO.setGid(stock.getStockGid()); + + hqstr = hqstr.replaceAll("\"\"", "\""); + + List list = Jsons.toList(hqstr, SinaStockMinData.class); + log.info("需要查询的行情size为: {}", Integer.valueOf(size)); + + minDataVO.setData(list); + + return ServerResponse.createBySuccess(minDataVO); + } + + + public static void main(String[] args) throws IOException { +// List list = Lists.newArrayList(); +// list.add(Integer.valueOf(1)); +// list.add(Integer.valueOf(2)); +// list.add(Integer.valueOf(3)); +// System.out.println(list.size()); +// +// String[][] values = new String[list.size()][5]; +// +// System.out.println("[]" + values.length); +// System.out.println("[][]" + values[1].length); +// +// System.out.println(getSinaStock("sh601318")); +// +// String sss = "[\n{\n\"day\": \"2019-03-05 14:50:00\",\n\"open\": \"13.020\",\n\"high\": \"13.040\",\n\"low\": \"13.000\",\n\"close\": \"13.040\",\n\"volume\": \"2611513\",\n\"ma_price5\": 13.01,\n\"ma_volume5\": 3216535\n},\n{\n\"day\": \"2019-03-05 14:55:00\",\n\"open\": \"13.040\",\n\"high\": \"13.040\",\n\"low\": \"13.010\",\n\"close\": \"13.030\",\n\"volume\": \"2296000\",\n\"ma_price5\": 13.016,\n\"ma_volume5\": 3044839\n}\n]"; +// +// sss = sss.substring(1, sss.length() - 1); +// +// sss = "{" + sss + "}"; +// String sinaStock = getSinaStock("s_sh600090"); +// System.out.println(sinaStock); + +// Request request = new Request.Builder() +// .url("https://hq.sinajs.cn/list=s_sh600090") +// .build(); + +// Response response = new OkHttpClient().newCall(request).execute(); +// System.out.println(response.body().string()); +// System.out.println(get("https://hq.sinajs.cn/list=s_sh600090")); +// System.out.println(get2("https://hq.sinajs.cn/list=s_sh600090")); +// System.out.println(get("https://toolkit-server.rplees.com/info")); +// System.out.println(get2("https://toolkit-server.rplees.com/info")); +// String uuu = "http://hq.sinajs.cn/list=s_sh600090"; + String body = HttpUtil + .createGet("http://hq.sinajs.cn/list=s_sh600090") + .header("Referer", "http://finance.sina.com.cn") + .execute() + .body(); + System.out.println(body); +//// +// OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象 +// Request request = new Request.Builder() +// .url("http://hq.sinajs.cn/list=s_sh600090")//请求接口。如果需要传参拼接到接口后面。 +// .addHeader("Referer", "http://finance.sina.com.cn") +// .build();//创建Request 对象 +// +// String string = client.newCall(request).execute().body().string(); +// +// System.out.println(string); + } + + +} + diff --git a/src/main/java/cn/stock/market/infrastructure/api/sina/vo/HotSearchVO.java b/src/main/java/cn/stock/market/infrastructure/api/sina/vo/HotSearchVO.java new file mode 100644 index 0000000..69ac0c2 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/api/sina/vo/HotSearchVO.java @@ -0,0 +1,63 @@ +package cn.stock.market.infrastructure.api.sina.vo; + + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel("热搜股票信息") +public class HotSearchVO { + + @ApiModelProperty("股票名称") + private String name; + + @ApiModelProperty("股票简码") + private String code; + + @ApiModelProperty("股票代码") + private String symbol; + + @ApiModelProperty("权重") + private Integer weight; + + public HotSearchVO() { + } + + public HotSearchVO(String name, String code,String symbol,Integer weight) { + this.name = name; + this.code = code; + this.symbol = symbol; + this.weight = weight; + } + + public String getSymbol() { + return symbol; + } + + public void setSymbol(String symbol) { + this.symbol = symbol; + } + + public Integer getWeight() { + return weight; + } + + public void setWeight(Integer weight) { + this.weight = weight; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } +} diff --git a/src/main/java/cn/stock/market/infrastructure/api/sina/vo/MarketVO.java b/src/main/java/cn/stock/market/infrastructure/api/sina/vo/MarketVO.java new file mode 100644 index 0000000..259c17f --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/api/sina/vo/MarketVO.java @@ -0,0 +1,176 @@ +package cn.stock.market.infrastructure.api.sina.vo; + + +public class MarketVO { + + private String name; + + private String nowPrice; + + private String increaseRate; + + private String increase; + + private String maxHigh; + + private String minLow; + + private String openPrice; + + private String closePrice; + + private String turnOver; + + private String turnNum; + + public void setName(String name) { + this.name = name; + } + + public void setNowPrice(String nowPrice) { + this.nowPrice = nowPrice; + } + + public void setIncreaseRate(String increaseRate) { + this.increaseRate = increaseRate; + } + + public void setIncrease(String increase) { + this.increase = increase; + } + + public void setMaxHigh(String maxHigh) { + this.maxHigh = maxHigh; + } + + public void setMinLow(String minLow) { + this.minLow = minLow; + } + + public void setOpenPrice(String openPrice) { + this.openPrice = openPrice; + } + + public void setClosePrice(String closePrice) { + this.closePrice = closePrice; + } + + public void setTurnOver(String turnOver) { + this.turnOver = turnOver; + } + + public void setTurnNum(String turnNum) { + this.turnNum = turnNum; + } + + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof MarketVO)) return false; + MarketVO other = (MarketVO) o; + if (!other.canEqual(this)) return false; + Object this$name = getName(), other$name = other.getName(); + if ((this$name == null) ? (other$name != null) : !this$name.equals(other$name)) return false; + Object this$nowPrice = getNowPrice(), other$nowPrice = other.getNowPrice(); + if ((this$nowPrice == null) ? (other$nowPrice != null) : !this$nowPrice.equals(other$nowPrice)) return false; + Object this$increaseRate = getIncreaseRate(), other$increaseRate = other.getIncreaseRate(); + if ((this$increaseRate == null) ? (other$increaseRate != null) : !this$increaseRate.equals(other$increaseRate)) + return false; + Object this$maxHigh= getMaxHigh(), other$maxHigh = other.getMaxHigh(); + if ((this$maxHigh == null) ? (other$maxHigh != null) : !this$maxHigh.equals(other$maxHigh)) + return false; + Object this$minLow = getMinLow(), other$minLow = other.getMinLow(); + if ((this$minLow == null) ? (other$minLow != null) : !this$minLow.equals(other$minLow)) + return false; + Object this$openPrice = getOpenPrice(), other$openPrice = other.getOpenPrice(); + if ((this$openPrice == null) ? (other$openPrice != null) : !this$openPrice.equals(other$openPrice)) + return false; + Object this$closePrice = getClosePrice(), other$closePrice = other.getClosePrice(); + if ((this$closePrice == null) ? (other$closePrice != null) : !this$closePrice.equals(other$closePrice)) + return false; + Object this$turnOver = getTurnOver(), other$turnOver = other.getTurnOver(); + if ((this$turnOver == null) ? (other$turnOver != null) : !this$turnOver.equals(other$turnOver)) + return false; + Object this$turnNum = getTurnNum(), other$turnNum= other.getTurnNum(); + if ((this$turnNum == null) ? (other$turnNum != null) : !this$turnNum.equals(other$turnNum)) + return false; + Object this$increase = getIncrease(), other$increase = other.getIncrease(); + return !((this$increase == null) ? (other$increase != null) : !this$increase.equals(other$increase)); + } + + protected boolean canEqual(Object other) { + return other instanceof MarketVO; + } + + public int hashCode() { + int PRIME = 59; + int result = 1; + Object $name = getName(); + result = result * 59 + (($name == null) ? 43 : $name.hashCode()); + Object $nowPrice = getNowPrice(); + result = result * 59 + (($nowPrice == null) ? 43 : $nowPrice.hashCode()); + Object $increaseRate = getIncreaseRate(); + result = result * 59 + (($increaseRate == null) ? 43 : $increaseRate.hashCode()); + Object $maxHigh = getMaxHigh(); + result = result * 59 + (($maxHigh == null) ? 43 : $maxHigh.hashCode()); + Object $minLow = getMinLow(); + result = result * 59 + (($minLow == null) ? 43 : $minLow.hashCode()); + Object $openPrice = getOpenPrice(); + result = result * 59 + (($openPrice == null) ? 43 : $openPrice.hashCode()); + Object $closePrice = getClosePrice(); + result = result * 59 + (($closePrice == null) ? 43 : $closePrice.hashCode()); + Object $turnOver = getTurnOver(); + result = result * 59 + (($turnOver == null) ? 43 : $turnOver.hashCode()); + Object $turnNum = getTurnNum(); + result = result * 59 + (($turnNum == null) ? 43 : $turnNum.hashCode()); + Object $increase = getIncrease(); + return result * 59 + (($increase == null) ? 43 : $increase.hashCode()); + } + + public String toString() { + return "MarketVO(name=" + getName() + ", nowPrice=" + getNowPrice() + ", increaseRate=" + getIncreaseRate() + ", increase=" + getIncrease() + ", maxHigh=" + getMaxHigh() +", minLow=" + getMinLow() +", openPrice=" + getOpenPrice() +", closePrice=" + getClosePrice() +", turnOver=" + getTurnOver() +", turnNum=" + getTurnNum() +")"; + } + + + public String getName() { + return this.name; + } + + + public String getNowPrice() { + return this.nowPrice; + } + + + public String getIncreaseRate() { + return this.increaseRate; + } + + + public String getIncrease() { + return this.increase; + } + + public String getMaxHigh() { + return this.maxHigh; + } + + public String getMinLow() { + return this.minLow; + } + + public String getOpenPrice() { + return this.openPrice; + } + + public String getClosePrice() { + return this.closePrice; + } + + public String getTurnOver() { + return this.turnOver; + } + + public String getTurnNum() { + return this.turnNum; + } +} diff --git a/src/main/java/cn/stock/market/infrastructure/api/sina/vo/MarketVOResult.java b/src/main/java/cn/stock/market/infrastructure/api/sina/vo/MarketVOResult.java new file mode 100644 index 0000000..cc4a1b8 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/api/sina/vo/MarketVOResult.java @@ -0,0 +1,46 @@ +package cn.stock.market.infrastructure.api.sina.vo; + + +import java.util.List; + + +public class MarketVOResult { + + List market; + + + public String toString() { + return "MarketVOResult(market=" + getMarket() + ")"; + } + + public int hashCode() { + int PRIME = 59; + int result = 1; + Object $market = getMarket(); + return result * 59 + (($market == null) ? 43 : $market.hashCode()); + } + + protected boolean canEqual(Object other) { + return other instanceof MarketVOResult; + } + + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof MarketVOResult)) return false; + MarketVOResult other = (MarketVOResult) o; + if (!other.canEqual(this)) return false; + Object this$market = getMarket(), other$market = other.getMarket(); + return !((this$market == null) ? (other$market != null) : !this$market.equals(other$market)); + } + + public void setMarket(List market) { + this.market = market; + } + + + public List getMarket() { + return this.market; + } + +} + diff --git a/src/main/java/cn/stock/market/infrastructure/api/sina/vo/SinaStockMinData.java b/src/main/java/cn/stock/market/infrastructure/api/sina/vo/SinaStockMinData.java new file mode 100644 index 0000000..7eee638 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/api/sina/vo/SinaStockMinData.java @@ -0,0 +1,127 @@ +package cn.stock.market.infrastructure.api.sina.vo; + +public class SinaStockMinData { + private String day; + private String open; + private String high; + private String low; + private String close; + private String volume; + private double ma_price; + private String ma_volume; + + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof SinaStockMinData)) return false; + SinaStockMinData other = (SinaStockMinData) o; + if (!other.canEqual(this)) return false; + Object this$day = getDay(), other$day = other.getDay(); + if ((this$day == null) ? (other$day != null) : !this$day.equals(other$day)) return false; + Object this$open = getOpen(), other$open = other.getOpen(); + if ((this$open == null) ? (other$open != null) : !this$open.equals(other$open)) return false; + Object this$high = getHigh(), other$high = other.getHigh(); + if ((this$high == null) ? (other$high != null) : !this$high.equals(other$high)) return false; + Object this$low = getLow(), other$low = other.getLow(); + if ((this$low == null) ? (other$low != null) : !this$low.equals(other$low)) return false; + Object this$close = getClose(), other$close = other.getClose(); + if ((this$close == null) ? (other$close != null) : !this$close.equals(other$close)) return false; + Object this$volume = getVolume(), other$volume = other.getVolume(); + return ((this$volume == null) ? (other$volume != null) : !this$volume.equals(other$volume)) ? false : ((Double.compare(getMa_price(), other.getMa_price()) != 0) ? false : (!(getMa_volume() != other.getMa_volume()))); + } + + protected boolean canEqual(Object other) { + return other instanceof SinaStockMinData; + } + + public int hashCode() { + int PRIME = 59; + int result = 1; + Object $day = getDay(); + result = result * 59 + (($day == null) ? 43 : $day.hashCode()); + Object $open = getOpen(); + result = result * 59 + (($open == null) ? 43 : $open.hashCode()); + Object $high = getHigh(); + result = result * 59 + (($high == null) ? 43 : $high.hashCode()); + Object $low = getLow(); + result = result * 59 + (($low == null) ? 43 : $low.hashCode()); + Object $close = getClose(); + result = result * 59 + (($close == null) ? 43 : $close.hashCode()); + Object $volume = getVolume(); + result = result * 59 + (($volume == null) ? 43 : $volume.hashCode()); + long $ma_price = Double.doubleToLongBits(getMa_price()); + result = result * 59 + (int) ($ma_price >>> 32 ^ $ma_price); + Object $ma_volume = getMa_volume(); + return result * 59 + (($ma_volume == null) ? 43 : $volume.hashCode()); + //return result * 59 + getMa_volume(); + } + + public String toString() { + return "SinaStockMinData(day=" + getDay() + ", open=" + getOpen() + ", high=" + getHigh() + ", low=" + getLow() + ", close=" + getClose() + ", volume=" + getVolume() + ", ma_price=" + getMa_price() + ", ma_volume=" + getMa_volume() + ")"; + } + + public String getDay() { + return this.day; + } + + public void setDay(String day) { + this.day = day; + } + + public String getOpen() { + return this.open; + } + + public void setOpen(String open) { + this.open = open; + } + + public String getHigh() { + return this.high; + } + + public void setHigh(String high) { + this.high = high; + } + + public String getLow() { + return this.low; + } + + public void setLow(String low) { + this.low = low; + } + + public String getClose() { + return this.close; + } + + public void setClose(String close) { + this.close = close; + } + + public String getVolume() { + return this.volume; + } + + public void setVolume(String volume) { + this.volume = volume; + } + + public double getMa_price() { + return this.ma_price; + } + + public void setMa_price(double ma_price) { + this.ma_price = ma_price; + } + + public String getMa_volume() { + return this.ma_volume; + } + + public void setMa_volume(String ma_volume) { + this.ma_volume = ma_volume; + } +} + + diff --git a/src/main/java/cn/stock/market/infrastructure/api/sina/vo/k/MinDataVO.java b/src/main/java/cn/stock/market/infrastructure/api/sina/vo/k/MinDataVO.java new file mode 100644 index 0000000..26aaf2d --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/api/sina/vo/k/MinDataVO.java @@ -0,0 +1,95 @@ +package cn.stock.market.infrastructure.api.sina.vo.k; + + +import java.util.List; + +import cn.stock.market.infrastructure.api.sina.vo.SinaStockMinData; + + +public class MinDataVO { + + private String stockName; + + private String stockCode; + + private String gid; + + private List data; + + + public void setStockName(String stockName) { + this.stockName = stockName; + } + + public void setStockCode(String stockCode) { + this.stockCode = stockCode; + } + + public void setGid(String gid) { + this.gid = gid; + } + + public void setData(List data) { + this.data = data; + } + + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof MinDataVO)) return false; + MinDataVO other = (MinDataVO) o; + if (!other.canEqual(this)) return false; + Object this$stockName = getStockName(), other$stockName = other.getStockName(); + if ((this$stockName == null) ? (other$stockName != null) : !this$stockName.equals(other$stockName)) + return false; + Object this$stockCode = getStockCode(), other$stockCode = other.getStockCode(); + if ((this$stockCode == null) ? (other$stockCode != null) : !this$stockCode.equals(other$stockCode)) + return false; + Object this$gid = getGid(), other$gid = other.getGid(); + if ((this$gid == null) ? (other$gid != null) : !this$gid.equals(other$gid)) return false; + Object this$data = getData(), other$data = other.getData(); + return !((this$data == null) ? (other$data != null) : !this$data.equals(other$data)); + } + + protected boolean canEqual(Object other) { + return other instanceof MinDataVO; + } + + public int hashCode() { + int PRIME = 59; + int result = 1; + Object $stockName = getStockName(); + result = result * 59 + (($stockName == null) ? 43 : $stockName.hashCode()); + Object $stockCode = getStockCode(); + result = result * 59 + (($stockCode == null) ? 43 : $stockCode.hashCode()); + Object $gid = getGid(); + result = result * 59 + (($gid == null) ? 43 : $gid.hashCode()); + Object $data = getData(); + return result * 59 + (($data == null) ? 43 : $data.hashCode()); + } + + public String toString() { + return "MinDataVO(stockName=" + getStockName() + ", stockCode=" + getStockCode() + ", gid=" + getGid() + ", data=" + getData() + ")"; + } + + + public String getStockName() { + return this.stockName; + } + + + public String getStockCode() { + return this.stockCode; + } + + + public String getGid() { + return this.gid; + } + + + public List getData() { + return this.data; + } + +} + diff --git a/src/main/java/cn/stock/market/infrastructure/api/sina/vo/k/echarts/EchartsDataVO.java b/src/main/java/cn/stock/market/infrastructure/api/sina/vo/k/echarts/EchartsDataVO.java new file mode 100644 index 0000000..ad22a52 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/api/sina/vo/k/echarts/EchartsDataVO.java @@ -0,0 +1,87 @@ +package cn.stock.market.infrastructure.api.sina.vo.k.echarts; + +import java.util.Arrays; + +public class EchartsDataVO { + private String stockName; + private String stockCode; + private double[][] values; + private Object[][] volumes; + private String[] date; + + public void setStockName(String stockName) { + this.stockName = stockName; + } + + public void setStockCode(String stockCode) { + this.stockCode = stockCode; + } + + public void setValues(double[][] values) { + this.values = values; + } + + public void setVolumes(Object[][] volumes) { + this.volumes = volumes; + } + + public void setDate(String[] date) { + this.date = date; + } + + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof EchartsDataVO)) return false; + EchartsDataVO other = (EchartsDataVO) o; + if (!other.canEqual(this)) return false; + Object this$stockName = getStockName(), other$stockName = other.getStockName(); + if ((this$stockName == null) ? (other$stockName != null) : !this$stockName.equals(other$stockName)) + return false; + Object this$stockCode = getStockCode(), other$stockCode = other.getStockCode(); + return ((this$stockCode == null) ? (other$stockCode != null) : !this$stockCode.equals(other$stockCode)) ? false : (!Arrays.deepEquals(getValues(), other.getValues()) ? false : (!Arrays.deepEquals(getVolumes(), other.getVolumes()) ? false : (!!Arrays.deepEquals(getDate(), other.getDate())))); + } + + protected boolean canEqual(Object other) { + return other instanceof EchartsDataVO; + } + + public int hashCode() { + int PRIME = 59; + int result = 1; + Object $stockName = getStockName(); + result = result * 59 + (($stockName == null) ? 43 : $stockName.hashCode()); + Object $stockCode = getStockCode(); + result = result * 59 + (($stockCode == null) ? 43 : $stockCode.hashCode()); + result = result * 59 + Arrays.deepHashCode(getValues()); + result = result * 59 + Arrays.deepHashCode(getVolumes()); + return result * 59 + Arrays.deepHashCode(getDate()); + } + + public String toString() { + return "EchartsDataVO(stockName=" + getStockName() + ", stockCode=" + getStockCode() + ", values=" + Arrays.deepToString(getValues()) + ", volumes=" + Arrays.deepToString(getVolumes()) + ", date=" + Arrays.deepToString(getDate()) + ")"; + } + + + public String getStockName() { + return this.stockName; + } + + + public String getStockCode() { + return this.stockCode; + } + + + public double[][] getValues() { + return this.values; + } + + public Object[][] getVolumes() { + return this.volumes; + } + + public String[] getDate() { + return this.date; + } +} + diff --git a/src/main/java/cn/stock/market/infrastructure/db/DataSourceContextHolder.java b/src/main/java/cn/stock/market/infrastructure/db/DataSourceContextHolder.java new file mode 100644 index 0000000..91ddbf1 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/db/DataSourceContextHolder.java @@ -0,0 +1,21 @@ +package cn.stock.market.infrastructure.db; + +public class DataSourceContextHolder { + + private static final ThreadLocal holder = new ThreadLocal<>(); + + public static void setDataSource(String type) { + holder.set(type); + } + + public static String getDataSource() { + String lookUpKey = holder.get(); +// return lookUpKey == null ? DatasourceConfig.STOCK_MARKET : lookUpKey; + return lookUpKey; + } + + public static void clear() { + holder.remove(); + } + +} diff --git a/src/main/java/cn/stock/market/infrastructure/db/DynamicDataSourceRouter.java b/src/main/java/cn/stock/market/infrastructure/db/DynamicDataSourceRouter.java new file mode 100644 index 0000000..5196d82 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/db/DynamicDataSourceRouter.java @@ -0,0 +1,9 @@ +package cn.stock.market.infrastructure.db; +import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; + +public class DynamicDataSourceRouter extends AbstractRoutingDataSource { + @Override + protected Object determineCurrentLookupKey() { + return DataSourceContextHolder.getDataSource(); + } +} diff --git a/src/main/java/cn/stock/market/infrastructure/db/config/JpaConfig.java b/src/main/java/cn/stock/market/infrastructure/db/config/JpaConfig.java new file mode 100644 index 0000000..6703bf6 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/db/config/JpaConfig.java @@ -0,0 +1,70 @@ +package cn.stock.market.infrastructure.db.config; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.web.config.EnableSpringDataWebSupport; + +import com.alibaba.druid.support.http.StatViewServlet; +import com.rp.spring.jpa.FreemarkerSqlTemplates; + +/** + * + * title: JpaConfig.java jpa通用配置 + * + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 26, 2018 3:57:59 PM + */ +@Configuration +@EnableSpringDataWebSupport +public class JpaConfig { + + @Bean + @ConditionalOnMissingBean + public FreemarkerSqlTemplates freemarkerSqlTemplates() { + FreemarkerSqlTemplates templates = new FreemarkerSqlTemplates(); + templates.setTemplateBasePackage(""); + templates.setSuffix(".sftl"); + return templates; + } + + /** + * 配置监控服务器 + * @return 返回监控注册的servlet对象 + * @author SimpleWu + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Bean + public ServletRegistrationBean statViewServlet() { + ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*"); + // 添加IP白名单 +// servletRegistrationBean.addInitParameter("allow", "127.0.0.1"); + // 添加IP黑名单,当白名单和黑名单重复时,黑名单优先级更高 +// servletRegistrationBean.addInitParameter("deny", "127.0.0.1"); + // 添加控制台管理用户 +// servletRegistrationBean.addInitParameter(ResourceServlet.PARAM_NAME_USERNAME, "admin"); +// servletRegistrationBean.addInitParameter(ResourceServlet.PARAM_NAME_PASSWORD, "admin"); + // 是否能够重置数据 + servletRegistrationBean.addInitParameter("resetEnable", "false"); + return servletRegistrationBean; + } + + /** + * 配置服务过滤器 + * + * @return 返回过滤器配置对象 + */ +// @Bean +// public FilterRegistrationBean statFilter() { +// FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter()); +// // 添加过滤规则 +// filterRegistrationBean.addUrlPatterns("/*"); +// // 忽略过滤格式 +// filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*,"); +// return filterRegistrationBean; +// } + +} \ No newline at end of file diff --git a/src/main/java/cn/stock/market/infrastructure/db/config/MarketDatasourceConfig.java b/src/main/java/cn/stock/market/infrastructure/db/config/MarketDatasourceConfig.java new file mode 100644 index 0000000..c6eda87 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/db/config/MarketDatasourceConfig.java @@ -0,0 +1,87 @@ +package cn.stock.market.infrastructure.db.config; + +import java.util.Map; + +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings; +import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.core.env.Environment; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.transaction.PlatformTransactionManager; + +import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; +import com.rp.spring.jpa.GenericJpaRepositoryFactoryBean; +import com.rp.spring.jpa.GenericJpaRepositoryImpl; + +/** + * + * title: PlatformDatasourceConfig.java + * 平台数据源设置 + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @version 1.0 + * @created Jan 26, 2018 3:57:47 PM + */ +@Configuration +@ComponentScan({ "cn.stock.**.db.po", "com.stock.**.db.repo","cn.qutaojing.**.po", "cn.qutaojing.**.repo" }) +@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactory", +transactionManagerRef = "transactionManager", +repositoryBaseClass = GenericJpaRepositoryImpl.class, +repositoryFactoryBeanClass = GenericJpaRepositoryFactoryBean.class, +basePackages = { + "cn.qutaojing.ipay.infrastructure.db.po", "cn.qutaojing.ipay.infrastructure.db.repo", + "cn.stock.trade.infrastructure.db.po", "cn.stock.trade.infrastructure.db.repo", + "cn.stock.market.infrastructure.db.po", "cn.stock.market.infrastructure.db.repo"}) +public class MarketDatasourceConfig { + @Autowired HibernateProperties hibernateProperties; + + @Primary + @Bean(name = "marketDataSource") + @ConfigurationProperties(prefix="spring.datasource.stock-market") + public DataSource stockMarketDataSource() { + return DruidDataSourceBuilder.create().build(); + } + + @Primary + @Bean(name = "marketJpaProperties") + @ConfigurationProperties(prefix = "spring.jpa") + public JpaProperties jpaProperties() { + return new JpaProperties(); + } + + @Primary + @Bean(name = {"marketEntityManagerFactory", "entityManagerFactory"}) + public LocalContainerEntityManagerFactoryBean entityManagerFactory( + EntityManagerFactoryBuilder builder, + @Qualifier("marketJpaProperties") JpaProperties jpaProperties, + @Qualifier("marketDataSource") DataSource dataSource, Environment env) { + Map properties = hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings()); + + return builder + .dataSource(dataSource) + .properties(properties) + .packages( "cn.stock.**.po","cn.qutaojing.**.po") + .persistenceUnit("market") + .build(); + } + + @Primary + @Bean(name = {"marketTransactionManager", "transactionManager"}) + public PlatformTransactionManager transactionManager(@Qualifier("marketEntityManagerFactory") EntityManagerFactory entityManagerFactory) { + return new JpaTransactionManager(entityManagerFactory); + } +} diff --git a/src/main/java/cn/stock/market/infrastructure/db/po/CityPO.java b/src/main/java/cn/stock/market/infrastructure/db/po/CityPO.java new file mode 100644 index 0000000..ffe000a --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/db/po/CityPO.java @@ -0,0 +1,86 @@ +package cn.stock.market.infrastructure.db.po; + +import java.lang.Integer; +import java.lang.String; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; + +/** + * CityPO + * + * @author xlfd + * @email xlfd@gmail.com + * @created 2021/06/16 + */ +@SuperBuilder +@Data +@NoArgsConstructor +@AllArgsConstructor +@Entity +@DynamicInsert +@DynamicUpdate +@Table(name = "city") +public class CityPO { + /** + * 主键ID + */ + @Id + Integer id; + + /** + * 父级ID + */ + String parentId; + + /** + * 名称 + */ + String name; + + /** + * 城市路径 + */ + String path; + + /** + * 短名 + */ + String shortName; + + /** + * 1省2市3区/县 + */ + String levelType; + + /** + * 城市代码 + */ + String cityCode; + + /** + * 邮编 + */ + String zipCode; + + /** + * 经度 + */ + String longitude; + + /** + * 纬度 + */ + String latitude; + + /** + * 备注 + */ + String remark; +} diff --git a/src/main/java/cn/stock/market/infrastructure/db/po/Counter.java b/src/main/java/cn/stock/market/infrastructure/db/po/Counter.java new file mode 100644 index 0000000..7529fd2 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/db/po/Counter.java @@ -0,0 +1,48 @@ +package cn.stock.market.infrastructure.db.po; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; +import org.hibernate.annotations.UpdateTimestamp; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * + * 计数器 + * + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Oct 15, 2020 10:37:50 AM + */ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@Entity +@DynamicInsert +@DynamicUpdate +@Table(name = "counter") +public class Counter { + @Id + String k; + String type; + String fkId; + Long count; + @CreationTimestamp + @Column(updatable = false) + Date createTime; + @UpdateTimestamp + Date updateTime; +} diff --git a/src/main/java/cn/stock/market/infrastructure/db/po/Dic.java b/src/main/java/cn/stock/market/infrastructure/db/po/Dic.java new file mode 100644 index 0000000..db0d145 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/db/po/Dic.java @@ -0,0 +1,43 @@ +package cn.stock.market.infrastructure.db.po; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * + * title: DictionarySetting.java 动态键值对表 + * + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Oct 15, 2020 10:37:50 AM + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Entity +@DynamicInsert +@DynamicUpdate +@Table(name = "dic") +public class Dic { + @Id + String k; + String val; + @CreationTimestamp + @Column(updatable = false) + Date createTime; +} diff --git a/src/main/java/cn/stock/market/infrastructure/db/po/JsonInfoPO.java b/src/main/java/cn/stock/market/infrastructure/db/po/JsonInfoPO.java new file mode 100644 index 0000000..b1f0ffb --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/db/po/JsonInfoPO.java @@ -0,0 +1,58 @@ +package cn.stock.market.infrastructure.db.po; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; +import org.hibernate.annotations.UpdateTimestamp; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * JsonInfoPO + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2022/08/16 + */ +@SuperBuilder +@Data +@NoArgsConstructor +@AllArgsConstructor +@Entity +@DynamicInsert +@DynamicUpdate +@Table( + name = "json_info" +) +public class JsonInfoPO { + @Id + @GeneratedValue( + strategy = GenerationType.IDENTITY + ) + Integer id; + + String type; + + String ext; + + @CreationTimestamp + @Column( + updatable = false + ) + Date createAt; + + @UpdateTimestamp + Date updateAt; +} diff --git a/src/main/java/cn/stock/market/infrastructure/db/po/RealtimePO.java b/src/main/java/cn/stock/market/infrastructure/db/po/RealtimePO.java new file mode 100644 index 0000000..e428c0d --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/db/po/RealtimePO.java @@ -0,0 +1,54 @@ +package cn.stock.market.infrastructure.db.po; + +import java.lang.Double; +import java.lang.Integer; +import java.lang.String; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; + +/** + * RealtimePO + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@SuperBuilder +@Data +@NoArgsConstructor +@AllArgsConstructor +@Entity +@DynamicInsert +@DynamicUpdate +@Table(name = "realtime") +public class RealtimePO { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + Integer id; + + String time; + + Integer volumes; + + Double price; + + Double rates; + + Integer amounts; + + String stockCode; + + /** + * 均价 + */ + Double averagePrice; +} diff --git a/src/main/java/cn/stock/market/infrastructure/db/po/SiteArticlePO.java b/src/main/java/cn/stock/market/infrastructure/db/po/SiteArticlePO.java new file mode 100644 index 0000000..4f6abe9 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/db/po/SiteArticlePO.java @@ -0,0 +1,81 @@ +package cn.stock.market.infrastructure.db.po; + +import java.lang.Integer; +import java.lang.String; +import java.util.Date; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; + +/** + * SiteArticlePO + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@SuperBuilder +@Data +@NoArgsConstructor +@AllArgsConstructor +@Entity +@DynamicInsert +@DynamicUpdate +@Table(name = "site_article") +public class SiteArticlePO { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + Integer id; + + @ApiModelProperty("公告标题") + String artTitle; + + @ApiModelProperty("公告类型") + String artType; + + @ApiModelProperty("公告图片") + String artImg; + + @ApiModelProperty("公告作者") + String author; + + @ApiModelProperty("点击次数") + Integer hitTimes; + + @ApiModelProperty("是否展示") + Integer isShow; + + @ApiModelProperty("增加时间") + Date addTime; + + @ApiModelProperty("") + String artSummary; + + @ApiModelProperty("") + String artCnt; + + @ApiModelProperty("") + String spiderUrl; + + /** + * 来源id + */ + @ApiModelProperty("来源id") + String sourceId; + + /** + * 浏览量 + */ + @ApiModelProperty("浏览量") + Integer views; +} diff --git a/src/main/java/cn/stock/market/infrastructure/db/po/SiteNewsPO.java b/src/main/java/cn/stock/market/infrastructure/db/po/SiteNewsPO.java new file mode 100644 index 0000000..b60794f --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/db/po/SiteNewsPO.java @@ -0,0 +1,105 @@ +package cn.stock.market.infrastructure.db.po; + +import java.util.Date; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +import io.swagger.annotations.ApiModelProperty; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; +import org.hibernate.annotations.UpdateTimestamp; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * SiteNewsPO + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/19 + */ +@SuperBuilder +@Data +@NoArgsConstructor +@AllArgsConstructor +@Entity +@DynamicInsert +@DynamicUpdate +@Table( + name = "site_news" +) +public class SiteNewsPO { + /** + * 新闻主键id */ + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + Integer id; + + /** + * 新闻类型:1、财经要闻,2、经济数据,3、全球股市,4、7*24全球,5、商品资讯,6、上市公司,7、全球央行 */ + @ApiModelProperty("闻类型:1、财经要闻,2、经济数据,3、全球股市,4、7*24全球,5、商品资讯,6、上市公司,7、全球央行") + Integer type; + + /** + * 新闻标题 */ + @ApiModelProperty("新闻标题") + String title; + + /** + * 来源id */ + @ApiModelProperty("来源id") + String sourceId; + + /** + * 来源名称 */ + @ApiModelProperty("来源名称") + String sourceName; + + /** + * 浏览量 */ + @ApiModelProperty("浏览量") + Integer views; + + /** + * 状态:1、启用,0、停用 */ + @ApiModelProperty("状态:1、启用,0、停用 ") + Integer status; + + /** + * 显示时间 */ + @ApiModelProperty("显示时间") + Date showTime; + + /** + * 添加时间 */ + @ApiModelProperty("添加时间") + Date addTime; + + /** + * 修改时间 */ + @ApiModelProperty("修改时间") + @UpdateTimestamp + Date updateTime; + + /** + * 图片地址 */ + @ApiModelProperty("图片地址") + String imgurl; + + /** + * 描述 */ + @ApiModelProperty("描述") + String description; + + /** + * 新闻内容 */ + @ApiModelProperty("新闻内容") + String content; +} diff --git a/src/main/java/cn/stock/market/infrastructure/db/po/SysLogPO.java b/src/main/java/cn/stock/market/infrastructure/db/po/SysLogPO.java new file mode 100644 index 0000000..6003e70 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/db/po/SysLogPO.java @@ -0,0 +1,93 @@ +package cn.stock.market.infrastructure.db.po; + +import java.lang.Integer; +import java.lang.String; +import java.util.Date; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; +import org.hibernate.annotations.UpdateTimestamp; + +/** + * SysLogPO + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2021/06/18 + */ +@SuperBuilder +@Data +@NoArgsConstructor +@AllArgsConstructor +@Entity +@DynamicInsert +@DynamicUpdate +@Table(name = "sys_log") +public class SysLogPO { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + Integer id; + + /** + * 模块 + */ + String module; + + /** + * 动作类型 + */ + String actionType; + + /** + * 操作角色 + */ + String roleType; + + Integer storeId; + + String operatorId; + + String operatorName; + + String operatorPhone; + + String uniqueId; + + /** + * 标题 + */ + String title; + + /** + * 内容 + */ + String content; + + /** + * 扩展 + */ + String ext; + + /** + * 创建时间 + */ + @CreationTimestamp + @Column(updatable = false) + Date createAt; + + /** + * 更新时间 + */ + @UpdateTimestamp + Date updateAt; +} diff --git a/src/main/java/cn/stock/market/infrastructure/db/repo/CityRepo.java b/src/main/java/cn/stock/market/infrastructure/db/repo/CityRepo.java new file mode 100644 index 0000000..4b1308a --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/db/repo/CityRepo.java @@ -0,0 +1,15 @@ +package cn.stock.market.infrastructure.db.repo; + +import com.rp.spring.jpa.GenericJpaRepository; + +import cn.stock.market.infrastructure.db.po.CityPO; + +/** + * CityRepo + * + * @author xlfd + * @email xlfd@gmail.com + * @created 2021/06/16 + */ +public interface CityRepo extends GenericJpaRepository { +} diff --git a/src/main/java/cn/stock/market/infrastructure/db/repo/CounterRepo.java b/src/main/java/cn/stock/market/infrastructure/db/repo/CounterRepo.java new file mode 100644 index 0000000..0dd7ae0 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/db/repo/CounterRepo.java @@ -0,0 +1,15 @@ +package cn.stock.market.infrastructure.db.repo; + +import com.rp.spring.jpa.GenericJpaRepository; + +import cn.stock.market.infrastructure.db.po.Counter; + +/** + * + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Oct 15, 2020 10:46:45 AM + */ +public interface CounterRepo extends GenericJpaRepository { +} diff --git a/src/main/java/cn/stock/market/infrastructure/db/repo/DicRepo.java b/src/main/java/cn/stock/market/infrastructure/db/repo/DicRepo.java new file mode 100644 index 0000000..98b5d8e --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/db/repo/DicRepo.java @@ -0,0 +1,15 @@ +package cn.stock.market.infrastructure.db.repo; + +import com.rp.spring.jpa.GenericJpaRepository; + +import cn.stock.market.infrastructure.db.po.Dic; + +/** + * + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Oct 15, 2020 10:46:45 AM + */ +public interface DicRepo extends GenericJpaRepository { +} diff --git a/src/main/java/cn/stock/market/infrastructure/db/repo/JsonInfoRepo.java b/src/main/java/cn/stock/market/infrastructure/db/repo/JsonInfoRepo.java new file mode 100644 index 0000000..a760fbb --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/db/repo/JsonInfoRepo.java @@ -0,0 +1,17 @@ +package cn.stock.market.infrastructure.db.repo; + +import com.rp.spring.jpa.GenericJpaRepository; + +import cn.stock.market.infrastructure.db.po.JsonInfoPO; + +import java.lang.Integer; + +/** + * JsonInfoRepo + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2022/08/16 + */ +public interface JsonInfoRepo extends GenericJpaRepository { +} diff --git a/src/main/java/cn/stock/market/infrastructure/db/repo/RealtimeRepo.java b/src/main/java/cn/stock/market/infrastructure/db/repo/RealtimeRepo.java new file mode 100644 index 0000000..968be00 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/db/repo/RealtimeRepo.java @@ -0,0 +1,27 @@ +package cn.stock.market.infrastructure.db.repo; + +import org.springframework.data.jpa.repository.Modifying; + +import com.rp.spring.jpa.GenericJpaRepository; +import com.rp.spring.jpa.TemplateQuery; + +import cn.stock.market.infrastructure.db.po.RealtimePO; + +/** + * RealtimeRepo + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +public interface RealtimeRepo extends GenericJpaRepository { + /*删除股票*/ + @Modifying + @TemplateQuery + void deleteStockCode(); + + /*删除期货*/ + @Modifying + @TemplateQuery + void deleteStockFuturesCode(); +} diff --git a/src/main/java/cn/stock/market/infrastructure/db/repo/SiteArticleRepo.java b/src/main/java/cn/stock/market/infrastructure/db/repo/SiteArticleRepo.java new file mode 100644 index 0000000..9e7c341 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/db/repo/SiteArticleRepo.java @@ -0,0 +1,15 @@ +package cn.stock.market.infrastructure.db.repo; + +import cn.stock.market.infrastructure.db.po.SiteArticlePO; +import com.rp.spring.jpa.GenericJpaRepository; +import java.lang.Integer; + +/** + * SiteArticleRepo + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +public interface SiteArticleRepo extends GenericJpaRepository { +} diff --git a/src/main/java/cn/stock/market/infrastructure/db/repo/SiteNewsRepo.java b/src/main/java/cn/stock/market/infrastructure/db/repo/SiteNewsRepo.java new file mode 100644 index 0000000..52f5d91 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/db/repo/SiteNewsRepo.java @@ -0,0 +1,15 @@ +package cn.stock.market.infrastructure.db.repo; + +import cn.stock.market.infrastructure.db.po.SiteNewsPO; +import com.rp.spring.jpa.GenericJpaRepository; +import java.lang.Integer; + +/** + * SiteNewsRepo + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/19 + */ +public interface SiteNewsRepo extends GenericJpaRepository { +} diff --git a/src/main/java/cn/stock/market/infrastructure/db/repo/SysLogRepo.java b/src/main/java/cn/stock/market/infrastructure/db/repo/SysLogRepo.java new file mode 100644 index 0000000..b73e600 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/db/repo/SysLogRepo.java @@ -0,0 +1,15 @@ +package cn.stock.market.infrastructure.db.repo; + +import com.rp.spring.jpa.GenericJpaRepository; + +import cn.stock.market.infrastructure.db.po.SysLogPO; + +/** + * SysLogRepo + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2021/06/18 + */ +public interface SysLogRepo extends GenericJpaRepository { +} diff --git a/src/main/java/cn/stock/market/infrastructure/job/JobBoot.java b/src/main/java/cn/stock/market/infrastructure/job/JobBoot.java new file mode 100644 index 0000000..d9de463 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/job/JobBoot.java @@ -0,0 +1,67 @@ +package cn.stock.market.infrastructure.job; + +import java.util.concurrent.TimeUnit; + +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import com.google.common.base.Stopwatch; + +import cn.qutaojing.common.utils.MdcUtil; +import cn.stock.market.domain.basic.service.SiteArticleService; +import cn.stock.market.domain.basic.service.SiteNewsService; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class JobBoot { + /** + * cronExpression表达式定义:  + 字段   允许值   允许的特殊字符 + 秒   0-59   , - * / + 分   0-59   , - * / + 小时   0-23   , - * / + 日期   1-31   , - * ? / L W C + 月份   1-12 或者 JAN-DEC   , - * / + 星期   1-7 或者 SUN-SAT   , - * ? / L C # + 年(可选)   留空, 1970-2099   , - * / + + https://blog.csdn.net/ClementAD/article/details/42042111 + */ +// @Scheduled(cron="0 0/1 * * * ? ") + @Scheduled(cron="0/30 * * * * ? ") + public void batchStockTrust() { + MdcUtil.setTraceIdIfAbsent(); +// Stopwatch stopwatch = Stopwatch.createStarted(); +// log.info("batchStockTrust执行, 受影响数{}, 耗时:{}毫秒", count, stopwatch.elapsed(TimeUnit.MILLISECONDS)); + } + + @Scheduled(cron="0/30 * * * * ? ") + public void batchStockPosition() { + MdcUtil.setTraceIdIfAbsent(); +// Stopwatch stopwatch = Stopwatch.createStarted(); +// log.info("batchStockPosition执行, 受影响数{}, 耗时:{}毫秒", count, stopwatch.elapsed(TimeUnit.MILLISECONDS)); + } + + /* + * 新闻资讯抓取 + * */ + @Scheduled(cron = "0 0/30 9-20 * * ?") + public void artInfoTask() { + MdcUtil.setTraceIdIfAbsent(); + Stopwatch stopwatch = Stopwatch.createStarted(); + int count = SiteArticleService.of().grabArticle(); + log.info("artInfoTask执行, 受影响数{}, 耗时:{}毫秒", count, stopwatch.elapsed(TimeUnit.MILLISECONDS)); + } + + /* + * 新闻资讯抓取 + * */ + @Scheduled(cron = "0 0/30 9-20 * * ?") + public void newsInfoTask() { + MdcUtil.setTraceIdIfAbsent(); + Stopwatch stopwatch = Stopwatch.createStarted(); + int count = SiteNewsService.of().grabNews(); + log.info("newsInfoTask执行, 受影响数{}, 耗时:{}毫秒", count, stopwatch.elapsed(TimeUnit.MILLISECONDS)); + } +} diff --git a/src/main/java/cn/stock/market/infrastructure/job/RealTimeTask.java b/src/main/java/cn/stock/market/infrastructure/job/RealTimeTask.java new file mode 100644 index 0000000..3108955 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/job/RealTimeTask.java @@ -0,0 +1,32 @@ +package cn.stock.market.infrastructure.job; + +import javax.annotation.Resource; + +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import cn.stock.market.infrastructure.db.repo.RealtimeRepo; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class RealTimeTask { + @Resource RealtimeRepo repo; + + /*每天9点定时删除股票k线数据*/ + @Transactional + @Scheduled(cron = "0 00 9 * * MON-FRI") + public void deleteStockCode() { + log.info("每天9点定时删除股票k线数据"); + repo.deleteStockCode(); + } + + /*每天0点定时删除期货k线数据*/ + @Transactional + @Scheduled(cron = "0 00 0 * * MON-FRI") + public void deleteStockFuturesCode() { + log.info("每天0点定时删除期货k线数据"); + repo.deleteStockFuturesCode(); + } +} diff --git a/src/main/java/cn/stock/market/infrastructure/job/StockTask.java b/src/main/java/cn/stock/market/infrastructure/job/StockTask.java new file mode 100644 index 0000000..2f7e947 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/job/StockTask.java @@ -0,0 +1,342 @@ +package cn.stock.market.infrastructure.job; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import javax.annotation.PostConstruct; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import com.ag.utils.CollectionUtils; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.google.common.base.Stopwatch; +import com.google.common.collect.Lists; + +import cn.qutaojing.common.PageInfo; +import cn.qutaojing.common.utils.MdcUtil; +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.domain.basic.entity.Realtime; +import cn.stock.market.domain.basic.entity.Stock; +import cn.stock.market.domain.basic.repository.RealtimeRepository; +import cn.stock.market.domain.basic.repository.StockRepository; +import cn.stock.market.domain.basic.service.SiteArticleService; +import cn.stock.market.infrastructure.api.AStockApis; +import cn.stock.market.infrastructure.api.EastmoneyApi; +import cn.stock.market.infrastructure.api.sina.SinaStockApi; +import cn.stock.market.utils.Utils; +import cn.stock.market.web.config.Config; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class StockTask { + @Autowired RealtimeRepository realtimeRepository; + @Autowired StockRepository stockRepository; + ThreadPoolExecutor pool; + + @PostConstruct + public void initPool() { + this.pool = new ThreadPoolExecutor(50, 70, 20L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(240)); + this.pool.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy()); + } + + /*股票走势图定时任务-15*/ + // @Scheduled(cron = "0 0/1 9-15 * * ?") + public void z1() { +// if(! Utils.isTradeTime()) { +// return; +// } +// +// MdcUtil.setTraceIdIfAbsent(); +// Stopwatch stopwatch = Stopwatch.createStarted(); +// int count = SiteArticleService.of().grabArticle(); +// +// List list = stockRepository.findAll(); +// log.info("stockCodeSizes: {}", list.size()); +// +// List> partition = Lists.partition(list, 200); +// for (List itemList : partition) { +// List realtimeList = Lists.newArrayList(); +// for (Stock stock : itemList) { +// String stockGid = stock.getStockGid(); +// String sinaStock = SinaStockApi.getSinaStock("s_" + stockGid); +// +// try { +// String[] split = sinaStock.split(","); +// Double averagePrice = 0.0; +// +// Realtime realTime = new Realtime(); +// realTime.setPrice(Double.parseDouble(split[1].toString())); +// realTime.setRates(Double.parseDouble(split[3].toString())); +// SimpleDateFormat sdf = new SimpleDateFormat("HH:mm"); +// String time = sdf.format(new Date()); +// realTime.setTime(time); +// realTime.setVolumes(Integer.parseInt(split[4].toString())); +// String s = split[5].toString(); +// int index = s.indexOf("\""); +// String substring = s.substring(0, index); +// int amounts = Integer.parseInt(substring); +// realTime.setAmounts(amounts); +// realTime.setStockCode(stockGid); +// realTime.setAveragePrice(averagePrice); +// +// realtimeList.add(realTime); +// } catch(Exception e) { +// log.error("解析出错, stockGid:{}, result: {}", stockGid, sinaStock); +// } +// } +// +// this.pool.submit(() -> { +// realtimeRepository.saveAll(realtimeList); +// }); +// } +// +// log.info("z1执行, 受影响数{}, 耗时:{}毫秒", count, stopwatch.elapsed(TimeUnit.MILLISECONDS)); + } + + /*同步股票列表*/ + @Scheduled(cron = "0 0 6 * * ?") + public void syncAFutureStockList() { + PageInfo info = EastmoneyApi.ipoApplyDate(1, 300); + Map stockMap = StockRepository.of().cacheCodeMap(); + Stopwatch stopwatch = Stopwatch.createStarted(); + List list = Lists.newArrayList(); + for(JSONObject json : info.getItems()) { + String code = json.getString("SECURITY_CODE"); + String name = json.getString("SECURITY_NAME"); + String jys = Utils.jys(code); + if (stockMap.containsKey(code)) { + log.info("已经存在 {} 信息, 跳过", code); + continue; + } + + if(! Utils.isShOrSzOrBJ(code)) { + log.info("{} 非 sh 或者 sz 或者 bj , 跳过", code); + continue; + } + + Stock stock = new Stock(); + + stock.setStockName(name); + stock.setStockCode(code); + stock.setIsLock(0); + stock.setIsShow(0); + stock.setAddTime(new Date()); + stock.setStockState(0); + + stock.setStockSpell(Utils.converterToFirstSpell(name)); + stock.setStockGid(jys + code); + stock.setStockType(jys); + list.add(stock); + } + if(CollectionUtils.isNotEmpty(list)) { + StockRepository.of().saveAll(list); + } + int count = list.size(); + log.info("syncAFutureStockList执行, 受影响数{}, 耗时:{}毫秒", count, stopwatch.elapsed(TimeUnit.MILLISECONDS)); + } + + /*同步股票列表*/ + @Scheduled(cron = "0 0 6 * * ?") + public void syncAStockList() { + MdcUtil.setTraceIdIfAbsent(); + Config config = SpringUtils.getBean(Config.class); + List gplist = new AStockApis().gplist(config.getIg507Licence()); + + Stopwatch stopwatch = Stopwatch.createStarted(); + log.info("syncAStockList返回信息: {}", JSON.toJSONString(gplist)); + Map stockMap = StockRepository.of().cacheCodeMap(); + List list = Lists.newArrayList(); + for (JSONObject t : gplist) { + String code = t.getString("dm"); + String mc = t.getString("mc"); + String jys = t.getString("jys"); + + if (stockMap.containsKey(code)) { + Stock stock = stockMap.get(code); + if(! StringUtils.equals(mc, stock.getStockName())) { + stock.setStockName(mc); + log.info("已经存在 {} 信息, 名称不一样, 订正: {}", code, JSON.toJSONString(stock)); + list.add(stock); + } else { + log.info("已经存在 {} 信息, 跳过", code); + } + + continue; + } + + if(! Utils.isShOrSzOrBjByJys(jys)) { + log.info("{} 非 sh 或者 sz , 跳过", code); + continue; + } + + Stock stock = new Stock(); + + stock.setStockName(mc); + stock.setStockCode(code); + stock.setIsLock(0); + stock.setIsShow(0); + stock.setAddTime(new Date()); + stock.setStockState(0); + + stock.setStockSpell(Utils.converterToFirstSpell(mc)); + stock.setStockGid(jys + code); + stock.setStockType(jys); + list.add(stock); + } + + if(CollectionUtils.isNotEmpty(list)) { + StockRepository.of().saveAll(list); + } + int count = list.size(); + log.info("syncAStockList执行, 受影响数{}, 耗时:{}毫秒", count, stopwatch.elapsed(TimeUnit.MILLISECONDS)); + } + + /*同步股票列表*/ + @Scheduled(cron = "0 5 6 * * ?") + public void syncBjsStockList() { + MdcUtil.setTraceIdIfAbsent(); + boolean flag = true; + int count = 0; + Stopwatch stopwatch = Stopwatch.createStarted(); + int page = 1; + do { + List gplist = new AStockApis().sinalist(page); + if (gplist.isEmpty()){ + flag = false; + continue; + } + page++; + log.info("syncAStockList返回信息: {}", JSON.toJSONString(gplist)); + Map stockMap = StockRepository.of().cacheCodeMap(); + List list = Lists.newArrayList(); + for (JSONObject t : gplist) { + String code = t.getString("code"); + String mc = t.getString("name"); + String jys = t.getString("symbol"); + + if (stockMap.containsKey(code)) { + Stock stock = stockMap.get(code); + if(! StringUtils.equals(mc, stock.getStockName())) { + stock.setStockName(mc); + log.info("已经存在 {} 信息, 名称不一样, 订正: {}", code, JSON.toJSONString(stock)); + list.add(stock); + } else { + log.info("已经存在 {} 信息, 跳过", code); + } + + continue; + } + + Stock stock = new Stock(); + + stock.setStockName(mc); + stock.setStockCode(code); + stock.setIsLock(0); + stock.setIsShow(0); + stock.setAddTime(new Date()); + stock.setStockState(0); + + stock.setStockSpell(Utils.converterToFirstSpell(mc)); + stock.setStockGid(jys); + stock.setStockType("bj"); + list.add(stock); + } + count+=list.size(); + if(CollectionUtils.isNotEmpty(list)) { + StockRepository.of().saveAll(list); + } + }while(flag); + log.info("syncBjsStockList执行, 受影响数{}, 耗时:{}毫秒", count, stopwatch.elapsed(TimeUnit.MILLISECONDS)); + } +// @Scheduled(cron = "0 0 6 * * ?") +// public void syncAStockList() { +// MdcUtil.setTraceIdIfAbsent(); +// int count = 0; +// +// Stopwatch stopwatch = Stopwatch.createStarted(); +// String url = "http://api.waditu.com"; +// Map param = new HashMap<>(); +// param.put("api_name","stock_basic"); +// param.put("token","c30c5266b67ce2e0b93e12ddb18926150b777331e22568b07cabcca3"); +// param.put("fields",""); +// +// String data = HttpUtil.createPost(url) +// .body(JSON.toJSONString(param)) +// .header("Content-Type", "application/json") +// .execute() +// .body() +// ; +// +// JSONObject json = Jsons.toJSONAnyway(data); +// log.info("syncAStockList返回信息: {}", data); +// if(NumberUtils.ne(json.getInteger("code"), 0)) { +// log.info("返回错误码"); +// } else { +// Map stockMap = StockRepository.of().cacheCodeMap(); +// JSONArray items = json.getJSONObject("data").getJSONArray("items"); +// List list = Lists.newArrayList(); +// for (Object t : items) { +// List arr = (List) t; +// String code = arr.get(1); +// if (stockMap.containsKey(code)) { +// log.info("已经存在 {} 信息, 跳过", code); +// continue; +// } +// +// Stock stock = new Stock(); +// +// stock.setStockName(arr.get(2)); +// stock.setStockCode(arr.get(1)); +// stock.setStockName(arr.get(2)); +// stock.setIsLock(0); +// stock.setIsShow(0); +// stock.setAddTime(new Date()); +// stock.setStockState(0); +// +// stock.setStockSpell(Utils.converterToFirstSpell(arr.get(2))); +// if ("主板".equals(arr.get(5)) || "创业板".equals(arr.get(5))) { +// String strings = arr.get(0).substring(7, 9); +// if ("SH".equals(strings)) { +// stock.setStockGid("sh" + arr.get(1)); +// stock.setStockType("sh"); +// stock.setStockPlate("沪市"); +// } else if ("SZ".equals(strings)) { +// stock.setStockGid("sz" + arr.get(1)); +// stock.setStockType("sz"); +// stock.setStockPlate("深市"); +// } +// } else if ("创业板".equals(arr.get(5))) { +// stock.setStockGid("sz" + arr.get(1)); +// stock.setStockType("sz"); +// stock.setStockPlate("创业板"); +// } else if ("科创板".equals(arr.get(5))) { +// stock.setStockGid("sh" + arr.get(1)); +// stock.setStockType("sh"); +// stock.setStockPlate("科创板"); +// } else { +// log.info("无法识别{} 信息, 跳过", code); +// continue; +// } +// +// if(StringUtils.isNotBlank(stock.getStockType())) { +// list.add(stock); +// } +// } +// +// StockRepository.of().saveAll(list); +// count = list.size(); +// } +// +// log.info("syncAStockList执行, 受影响数{}, 耗时:{}毫秒", count, stopwatch.elapsed(TimeUnit.MILLISECONDS)); +// } +} diff --git a/src/main/java/cn/stock/market/infrastructure/oss/AliyunCloudStorageService.java b/src/main/java/cn/stock/market/infrastructure/oss/AliyunCloudStorageService.java new file mode 100644 index 0000000..55c62dc --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/oss/AliyunCloudStorageService.java @@ -0,0 +1,129 @@ +/* + * + * * Copyright (C) 2018 Wanghaobin<463540703@qq.com> + * + * * AG-Enterprise 企业版源码 + * * 郑重声明: + * * 如果你从其他途径获取到,请告知老A传播人,奖励1000。 + * * 老A将追究授予人和传播人的法律责任! + * + * * This program is free software; you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation; either version 2 of the License, or + * * (at your option) any later version. + * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * + * * You should have received a copy of the GNU General Public License along + * * with this program; if not, write to the Free Software Foundation, Inc., + * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +package cn.stock.market.infrastructure.oss; + + + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import org.apache.commons.lang3.StringUtils; + +import com.aliyun.oss.OSSClient; +import com.aliyun.oss.model.ObjectMetadata; + +/** + * 阿里云存储 + * @author ace + */ +public class AliyunCloudStorageService extends CloudStorageService { + + private OSSClient client; + + public AliyunCloudStorageService(CloudStorageConfig config) { + this.config = config; + + //初始化 + init(); + } + + private void init(){ + client = new OSSClient(config.getAliyunEndPoint(), config.getAliyunAccessKeyId(), + config.getAliyunAccessKeySecret()); + } + + @Override + public String upload(byte[] data, String path) { + return upload(new ByteArrayInputStream(data), path); + } + + @Override + public String upload(InputStream inputStream, String path) { + try { + + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setContentDisposition("inline"); + metadata.setContentType(getContType(path)); + client.putObject(config.getAliyunBucketName(), path, inputStream,metadata); + + } catch (Exception e){ + throw new RuntimeException("上传文件失败,请检查配置信息. " + e.getLocalizedMessage()); + } + + return config.getAliyunDomain() + "/" + path; + } + + + //通过文件名判断并获取OSS服务文件上传时文件的contentType 默认设置jpg格式 + public String getContType(String path) { + int lastIndexOf = StringUtils.lastIndexOf(path, "."); + if(lastIndexOf < 0) { + return "image/jpeg"; + } + String typeName = path.substring(lastIndexOf); + if(StringUtils.isBlank(typeName)){ + return "image/jpeg"; + } + if (typeName.equalsIgnoreCase(".jpeg") || + typeName.equalsIgnoreCase(".jpg") || + typeName.equalsIgnoreCase(".png")) { + return "image/jpeg"; + } + if (typeName.equalsIgnoreCase(".gif")) { + return "image/gif"; + } + if (typeName.equalsIgnoreCase(".svg")) { + return "image/svg"; + } + if (typeName.equalsIgnoreCase(".bmp")) { + return "application/x-bmp"; + } + if (typeName.equalsIgnoreCase(".tif")) { + return "image/tiff"; + } + if (typeName.equalsIgnoreCase(".pcx")) { + return "image/pcx"; + } + if (typeName.equalsIgnoreCase(".tga")) { + return "image/tga"; + } + if(typeName.equalsIgnoreCase(".mp4")){ + return "video/mpeg4"; + } + return "image/jpeg"; + } + + + @Override + public String uploadSuffix(byte[] data, String suffix) { + return upload(data, getPath(config.getAliyunPrefix(), suffix)); + } + + @Override + public String uploadSuffix(InputStream inputStream, String suffix) { + return upload(inputStream, getPath(config.getAliyunPrefix(), suffix)); + } +} diff --git a/src/main/java/cn/stock/market/infrastructure/oss/CloudStorageConfig.java b/src/main/java/cn/stock/market/infrastructure/oss/CloudStorageConfig.java new file mode 100644 index 0000000..35796f0 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/oss/CloudStorageConfig.java @@ -0,0 +1,137 @@ +/* + * + * * Copyright (C) 2018 Wanghaobin<463540703@qq.com> + * + * * AG-Enterprise 企业版源码 + * * 郑重声明: + * * 如果你从其他途径获取到,请告知老A传播人,奖励1000。 + * * 老A将追究授予人和传播人的法律责任! + * + * * This program is free software; you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation; either version 2 of the License, or + * * (at your option) any later version. + * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * + * * You should have received a copy of the GNU General Public License along + * * with this program; if not, write to the Free Software Foundation, Inc., + * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +package cn.stock.market.infrastructure.oss; + +import java.io.Serializable; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * 云存储配置信息 + */ +@Configuration +@ConfigurationProperties(prefix = "oss") +public class CloudStorageConfig implements Serializable { + private static final long serialVersionUID = 1L; + + //类型 1:七牛 2:阿里云 3:腾讯云 + private Integer type; + +// //七牛绑定的域名 +// private String qiniuDomain; +// //七牛路径前缀 +// private String qiniuPrefix; +// //七牛ACCESS_KEY +// private String qiniuAccessKey; +// //七牛SECRET_KEY +// private String qiniuSecretKey; +// //七牛存储空间名 +// private String qiniuBucketName; + + //阿里云绑定的域名 + private String aliyunDomain; + //阿里云路径前缀 + private String aliyunPrefix; + //阿里云EndPoint + private String aliyunEndPoint; + //阿里云AccessKeyId + private String aliyunAccessKeyId; + //阿里云AccessKeySecret + private String aliyunAccessKeySecret; + //阿里云BucketName + private String aliyunBucketName; + + //腾讯云绑定的域名 +// private String qcloudDomain; +// //腾讯云路径前缀 +// private String qcloudPrefix; +// //腾讯云AppId +// private Integer qcloudAppId; +// //腾讯云SecretId +// private String qcloudSecretId; +// //腾讯云SecretKey +// private String qcloudSecretKey; +// //腾讯云BucketName +// private String qcloudBucketName; +// //腾讯云COS所属地区 +// private String qcloudRegion; + + public Integer getType() { + return type; + } + + public void setType(Integer type) { + this.type = type; + } + + public String getAliyunDomain() { + return aliyunDomain; + } + + public void setAliyunDomain(String aliyunDomain) { + this.aliyunDomain = aliyunDomain; + } + + public String getAliyunPrefix() { + return aliyunPrefix; + } + + public void setAliyunPrefix(String aliyunPrefix) { + this.aliyunPrefix = aliyunPrefix; + } + + public String getAliyunEndPoint() { + return aliyunEndPoint; + } + + public void setAliyunEndPoint(String aliyunEndPoint) { + this.aliyunEndPoint = aliyunEndPoint; + } + + public String getAliyunAccessKeyId() { + return aliyunAccessKeyId; + } + + public void setAliyunAccessKeyId(String aliyunAccessKeyId) { + this.aliyunAccessKeyId = aliyunAccessKeyId; + } + + public String getAliyunAccessKeySecret() { + return aliyunAccessKeySecret; + } + + public void setAliyunAccessKeySecret(String aliyunAccessKeySecret) { + this.aliyunAccessKeySecret = aliyunAccessKeySecret; + } + + public String getAliyunBucketName() { + return aliyunBucketName; + } + + public void setAliyunBucketName(String aliyunBucketName) { + this.aliyunBucketName = aliyunBucketName; + } +} diff --git a/src/main/java/cn/stock/market/infrastructure/oss/CloudStorageService.java b/src/main/java/cn/stock/market/infrastructure/oss/CloudStorageService.java new file mode 100644 index 0000000..d7de629 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/oss/CloudStorageService.java @@ -0,0 +1,95 @@ +/* + * + * * Copyright (C) 2018 Wanghaobin<463540703@qq.com> + * + * * AG-Enterprise 企业版源码 + * * 郑重声明: + * * 如果你从其他途径获取到,请告知老A传播人,奖励1000。 + * * 老A将追究授予人和传播人的法律责任! + * + * * This program is free software; you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation; either version 2 of the License, or + * * (at your option) any later version. + * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * + * * You should have received a copy of the GNU General Public License along + * * with this program; if not, write to the Free Software Foundation, Inc., + * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +package cn.stock.market.infrastructure.oss; + +import java.io.InputStream; +import java.util.UUID; + +import org.apache.commons.lang.StringUtils; + +import com.ag.utils.DateUtils; +import com.ag.utils.FileUtils; + +/** + * 云存储(支持七牛、阿里云、腾讯云、又拍云) + * + */ +public abstract class CloudStorageService { + + /** 云存储配置信息 */ + CloudStorageConfig config; + + /** + * 文件路径 + * @param rootPath 前缀 + * @param suffix 后缀 + * @return 返回上传路径 + */ + public String getPath(String rootPath, String suffix) { + // 生成uuid + String path = DateUtils.nowDate("yyyyMMdd") + "/" + UUID.randomUUID().toString().replaceAll("-", ""); + // 文件路径 + if (StringUtils.isNotBlank(rootPath)) { + path = FileUtils.splicePaths(rootPath, path); + } + + return path + "." +suffix; + } + + /** + * 文件上传 + * @param data 文件字节数组 + * @param path 文件路径,包含文件名 + * @return 返回http地址 + */ + public abstract String upload(byte[] data, String path); + + /** + * 文件上传 + * @param data 文件字节数组 + * @param suffix 后缀 + * @return 返回http地址 + */ + public abstract String uploadSuffix(byte[] data, String suffix); + + /** + * 文件上传 + * @param inputStream 字节流 + * @param path 文件路径,包含文件名 + * @return 返回http地址 + */ + public abstract String upload(InputStream inputStream, String path); + + /** + * 文件上传 + * @param inputStream 字节流 + * @param suffix 后缀 + * @return 返回http地址 + */ + public abstract String uploadSuffix(InputStream inputStream, String suffix); + + +} diff --git a/src/main/java/cn/stock/market/infrastructure/oss/OSSConstant.java b/src/main/java/cn/stock/market/infrastructure/oss/OSSConstant.java new file mode 100644 index 0000000..6250e85 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/oss/OSSConstant.java @@ -0,0 +1,37 @@ +/* + * + * * Copyright (C) 2018 Wanghaobin<463540703@qq.com> + * + * * AG-Enterprise 企业版源码 + * * 郑重声明: + * * 如果你从其他途径获取到,请告知老A传播人,奖励1000。 + * * 老A将追究授予人和传播人的法律责任! + * + * * This program is free software; you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation; either version 2 of the License, or + * * (at your option) any later version. + * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * + * * You should have received a copy of the GNU General Public License along + * * with this program; if not, write to the Free Software Foundation, Inc., + * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +package cn.stock.market.infrastructure.oss; + +/** + * @author ace + * @create 2018/3/4. + */ +public class OSSConstant { + //类型 1:七牛 2:阿里云 3:腾讯云 + public final static Integer TYPE_QINIU = 1; + public final static Integer TYPE_ALIYUN = 2; + public final static Integer TYPE_QCLOUD = 3; +} diff --git a/src/main/java/cn/stock/market/infrastructure/oss/OSSFactory.java b/src/main/java/cn/stock/market/infrastructure/oss/OSSFactory.java new file mode 100644 index 0000000..8f45fd2 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/oss/OSSFactory.java @@ -0,0 +1,54 @@ +/* + * + * * Copyright (C) 2018 Wanghaobin<463540703@qq.com> + * + * * AG-Enterprise 企业版源码 + * * 郑重声明: + * * 如果你从其他途径获取到,请告知老A传播人,奖励1000。 + * * 老A将追究授予人和传播人的法律责任! + * + * * This program is free software; you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation; either version 2 of the License, or + * * (at your option) any later version. + * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * + * * You should have received a copy of the GNU General Public License along + * * with this program; if not, write to the Free Software Foundation, Inc., + * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +package cn.stock.market.infrastructure.oss; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * 文件上传Factory + * + * @author ace + */ +@Component +public class OSSFactory { + + @Autowired + private CloudStorageConfig config; + + public CloudStorageService build() { + if (config.getType().equals(OSSConstant.TYPE_QINIU)) { +// return new QiniuCloudStorageService(config); + } else if (config.getType().equals(OSSConstant.TYPE_ALIYUN)) { + return new AliyunCloudStorageService(config); + } else if (config.getType().equals(OSSConstant.TYPE_QCLOUD)) { +// return new QcloudCloudStorageService(config); + } + return null; + } + + +} diff --git a/src/main/java/cn/stock/market/infrastructure/redis/SingleDistributedLockTemplate.java b/src/main/java/cn/stock/market/infrastructure/redis/SingleDistributedLockTemplate.java new file mode 100644 index 0000000..8469160 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/redis/SingleDistributedLockTemplate.java @@ -0,0 +1,87 @@ +//package cn.stock.market.infrastructure.redis; +// +//import java.time.LocalDateTime; +//import java.time.format.DateTimeFormatter; +//import java.util.Map; +//import java.util.Map.Entry; +//import java.util.concurrent.TimeUnit; +// +//import org.redisson.api.RLock; +//import org.redisson.api.RedissonClient; +// +//import com.google.common.base.Stopwatch; +//import com.google.common.collect.Maps; +// +//import cn.qutaojing.common.aop.distributedlock.DistributedLockCallback; +//import cn.qutaojing.common.aop.distributedlock.DistributedLockInfo; +//import cn.qutaojing.common.aop.distributedlock.DistributedLockTemplate; +//import lombok.extern.slf4j.Slf4j; +// +///** +// * +// * title: SingleDistributedLockTemplate.java +// * +// * @author xlfd +// * @email xlfd@gmail.com +// * @version 1.0 +// * @created Sep 1, 2020 5:03:20 PM +// */ +//@Slf4j +//public class SingleDistributedLockTemplate implements DistributedLockTemplate { +// private RedissonClient redisson; +// DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS"); +// +// public SingleDistributedLockTemplate() { +// } +// +// public SingleDistributedLockTemplate(RedissonClient redisson) { +// this.redisson = redisson; +// } +// +// @Override +// public T lock(DistributedLockCallback callback, DistributedLockInfo... lockInfoList) throws Throwable { +// Stopwatch stopwatch = Stopwatch.createStarted(); +// Map lockMap = Maps.newConcurrentMap(); +// +// for (DistributedLockInfo info : lockInfoList) { +// RLock lock = getLock(info.getLockName(), info.getFairLock()); +// lockMap.put(lock, info); +// } +// +// try { +// for (Entry entry : lockMap.entrySet()) { +// RLock lock = entry.getKey(); +// DistributedLockInfo info = entry.getValue(); +// log.info("{}-准备获取{}分布式锁:{}", dateTimeFormatter.format(LocalDateTime.now()), info.getMessage(), info.getLockName()); +// lock.lock(info.getLeaseTime(), info.getTimeUnit()); +// log.info("{}-{}分布式锁:{}获取成功, 耗时:{} ms", dateTimeFormatter.format(LocalDateTime.now()), info.getMessage(), info.getLockName(), stopwatch.elapsed(TimeUnit.MILLISECONDS)); +// } +// +// return callback.process(); +// } finally { +// for (Entry entry : lockMap.entrySet()) { +// RLock lock = entry.getKey(); +// DistributedLockInfo info = entry.getValue(); +// if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) { +// lock.unlock(); +// log.info("{}-{}分布式锁:{}释放成功, 耗时:{} ms", dateTimeFormatter.format(LocalDateTime.now()), info.getMessage(), info.getLockName(), stopwatch.elapsed(TimeUnit.MILLISECONDS)); +// } +// } +// +// } +// } +// +// private RLock getLock(String lockName, boolean fairLock) { +// RLock lock; +// if (fairLock) { +// lock = redisson.getFairLock(lockName); +// } else { +// lock = redisson.getLock(lockName); +// } +// return lock; +// } +// +// public void setRedisson(RedissonClient redisson) { +// this.redisson = redisson; +// } +//} diff --git a/src/main/java/cn/stock/market/infrastructure/redis/config/RedisConfig.java b/src/main/java/cn/stock/market/infrastructure/redis/config/RedisConfig.java new file mode 100644 index 0000000..2bab268 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/redis/config/RedisConfig.java @@ -0,0 +1,70 @@ +//package cn.stock.market.infrastructure.redis.config; +// +//import java.time.Duration; +// +//import org.redisson.api.RedissonClient; +//import org.springframework.cache.CacheManager; +//import org.springframework.cache.annotation.EnableCaching; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.data.redis.cache.RedisCacheConfiguration; +//import org.springframework.data.redis.cache.RedisCacheManager; +//import org.springframework.data.redis.connection.RedisConnectionFactory; +//import org.springframework.data.redis.core.RedisTemplate; +//import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +//import org.springframework.data.redis.serializer.RedisSerializationContext; +//import org.springframework.data.redis.serializer.StringRedisSerializer; +// +//import cn.qutaojing.common.aop.distributedlock.DistributedLockTemplate; +//import cn.stock.market.infrastructure.redis.SingleDistributedLockTemplate; +// +///** +// * +// * @author xlfd +// * @email xlfd@gmail.com +// * @version 1.0 +// * @created Jun 3, 2021 4:56:28 PM +// */ +//@Configuration +//@EnableCaching +//public class RedisConfig { +// +// @Bean +// public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { +// RedisTemplate redisTemplate = new RedisTemplate<>(); +// redisTemplate.setConnectionFactory(redisConnectionFactory); +// redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class)); +// redisTemplate.setKeySerializer(new StringRedisSerializer()); +// +// redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class)); +// redisTemplate.setHashKeySerializer(new StringRedisSerializer()); +// +// return redisTemplate; +// } +// +// @Bean +// public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) { +// // 配置序列化 +// RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig(); +// config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())); +// config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new Jackson2JsonRedisSerializer<>(Object.class))); +// +// // 设置缓存的默认过期时间 ,30分钟 +// config.entryTtl(Duration.ofMinutes(30)); +// // 不缓存空值 +// config.disableCachingNullValues(); +// RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(config) +// .build(); +// return cacheManager; +// } +// +// /** +// * 分布式锁实现 +// * @param redissonClient +// * @return +// */ +// @Bean +// public DistributedLockTemplate distributedLockTemplate(RedissonClient redissonClient) { +// return new SingleDistributedLockTemplate(redissonClient); +// } +//} diff --git a/src/main/java/cn/stock/market/infrastructure/stockdb/config/StockDatasourceConfig.java b/src/main/java/cn/stock/market/infrastructure/stockdb/config/StockDatasourceConfig.java new file mode 100644 index 0000000..3176577 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/stockdb/config/StockDatasourceConfig.java @@ -0,0 +1,77 @@ +package cn.stock.market.infrastructure.stockdb.config; + +import java.util.Map; + +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings; +import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.transaction.PlatformTransactionManager; + +import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; +import com.rp.spring.jpa.GenericJpaRepositoryFactoryBean; +import com.rp.spring.jpa.GenericJpaRepositoryImpl; + +/** + * + * title: ErpDatasourceConfig.java + * ERP 数据源设置 + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @version 1.0 + * @created Jan 5, 2018 11:44:49 AM + */ +@Configuration +@ComponentScan({ "cn.stock.market.infrastructure.stockdb.po", "cn.stock.market.infrastructure.stockdb.repo"}) +@EnableJpaRepositories( + repositoryBaseClass = GenericJpaRepositoryImpl.class, + repositoryFactoryBeanClass = GenericJpaRepositoryFactoryBean.class, + entityManagerFactoryRef = "stockEntityManagerFactory", + transactionManagerRef = "stockTransactionManager", + basePackages = { "cn.stock.market.infrastructure.stockdb.po", "cn.stock.market.infrastructure.stockdb.repo"}) +public class StockDatasourceConfig { + @Autowired HibernateProperties hibernateProperties; + @Bean(name = "stockDataSource") + @ConfigurationProperties(prefix="spring.datasource.stock") + public DataSource dataSource() { + return DruidDataSourceBuilder.create().build(); + } + + @Bean(name = "stockJpaProperties") + @ConfigurationProperties(prefix = "spring.jpa") + public JpaProperties jpaProperties() { + return new JpaProperties(); + } + + @Bean(name = "stockEntityManagerFactory") + public LocalContainerEntityManagerFactoryBean entityManagerFactory( + EntityManagerFactoryBuilder builder, + @Qualifier("stockJpaProperties") JpaProperties jpaProperties, + @Qualifier("stockDataSource") DataSource dataSource) { + Map properties = hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings()); + return builder + .dataSource(dataSource) + .properties(properties) + .packages("cn.stock.market.infrastructure.stockdb.po") + .persistenceUnit("stock") + .build(); + } + + @Bean(name = "stockTransactionManager") + public PlatformTransactionManager transactionManager(@Qualifier("stockEntityManagerFactory") EntityManagerFactory entityManagerFactory) { + return new JpaTransactionManager(entityManagerFactory); + } +} diff --git a/src/main/java/cn/stock/market/infrastructure/stockdb/po/SiteSettingPO.java b/src/main/java/cn/stock/market/infrastructure/stockdb/po/SiteSettingPO.java new file mode 100644 index 0000000..8f26340 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/stockdb/po/SiteSettingPO.java @@ -0,0 +1,38 @@ +package cn.stock.market.infrastructure.stockdb.po; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * StockPO + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@SuperBuilder +@Data +@NoArgsConstructor +@AllArgsConstructor +@Entity +@DynamicInsert +@DynamicUpdate +@Table(name = "site_setting") +public class SiteSettingPO { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + Integer id; + + String marketServerList; +} diff --git a/src/main/java/cn/stock/market/infrastructure/stockdb/po/StockPO.java b/src/main/java/cn/stock/market/infrastructure/stockdb/po/StockPO.java new file mode 100644 index 0000000..40b07b0 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/stockdb/po/StockPO.java @@ -0,0 +1,68 @@ +package cn.stock.market.infrastructure.stockdb.po; + +import java.lang.Integer; +import java.lang.String; +import java.math.BigDecimal; +import java.util.Date; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; + +/** + * StockPO + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +@SuperBuilder +@Data +@NoArgsConstructor +@AllArgsConstructor +@Entity +@DynamicInsert +@DynamicUpdate +@Table(name = "stock") +public class StockPO { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + Integer id; + + String stockName; + + String stockCode; + + String stockSpell; + + String stockType; + + String stockGid; + + String stockPlate; + + Integer isLock; + + Integer isShow; + + Date addTime; + + /** + * 点差费率 + */ + BigDecimal spreadRate; + + /** + * 涨幅比例 + */ + BigDecimal increaseRatio; + + Integer stockState; +} diff --git a/src/main/java/cn/stock/market/infrastructure/stockdb/repo/SiteSettingRepo.java b/src/main/java/cn/stock/market/infrastructure/stockdb/repo/SiteSettingRepo.java new file mode 100644 index 0000000..b238935 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/stockdb/repo/SiteSettingRepo.java @@ -0,0 +1,15 @@ +package cn.stock.market.infrastructure.stockdb.repo; + +import com.rp.spring.jpa.GenericJpaRepository; + +import cn.stock.market.infrastructure.stockdb.po.SiteSettingPO; + +/** + * StockRepo + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +public interface SiteSettingRepo extends GenericJpaRepository { +} diff --git a/src/main/java/cn/stock/market/infrastructure/stockdb/repo/StockRepo.java b/src/main/java/cn/stock/market/infrastructure/stockdb/repo/StockRepo.java new file mode 100644 index 0000000..0d1a734 --- /dev/null +++ b/src/main/java/cn/stock/market/infrastructure/stockdb/repo/StockRepo.java @@ -0,0 +1,17 @@ +package cn.stock.market.infrastructure.stockdb.repo; + +import com.rp.spring.jpa.GenericJpaRepository; + +import cn.stock.market.infrastructure.stockdb.po.StockPO; + +import java.lang.Integer; + +/** + * StockRepo + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @created 2023/06/17 + */ +public interface StockRepo extends GenericJpaRepository { +} diff --git a/src/main/java/cn/stock/market/utils/Cons.java b/src/main/java/cn/stock/market/utils/Cons.java new file mode 100644 index 0000000..4b33404 --- /dev/null +++ b/src/main/java/cn/stock/market/utils/Cons.java @@ -0,0 +1,22 @@ +package cn.stock.market.utils; + +public final class Cons { + public class QPlantForm { + public static final String USER_APP = "user_app"; + public static final String SHOP_APP = "shop_app"; + public static final String SHOP_WEB = "shop_web"; + } + + /** + * 设备类型 + */ + public class QDeviceType { + + public static final String IOS = "ios"; + public static final String ANDROID = "android"; + public static final String WEB_PC = "web_pc"; + + // 后续扩展 微信公众号、小程序、支付宝 + } + +} diff --git a/src/main/java/cn/stock/market/utils/DateTimeUtil.java b/src/main/java/cn/stock/market/utils/DateTimeUtil.java new file mode 100644 index 0000000..914ecf1 --- /dev/null +++ b/src/main/java/cn/stock/market/utils/DateTimeUtil.java @@ -0,0 +1,192 @@ +package cn.stock.market.utils; + + +import java.sql.Timestamp; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Calendar; +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class DateTimeUtil { + private static final Logger log = LoggerFactory.getLogger(DateTimeUtil.class); + + + public static final String STANDARD_FORMAT = "yyyy-MM-dd HH:mm:ss"; + + + public static final String YMD_FORMAT = "yyyy-MM-dd"; + + + public static final String HM_FORMAT = "HH:mm"; + + + public static Date getCurrentDate() { + return new Date(); + } + + + public static Date strToDate(String dateTimeStr, String formatStr) { + DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(formatStr); + DateTime dateTime = dateTimeFormatter.parseDateTime(dateTimeStr); + return dateTime.toDate(); + } + + + public static String dateToStr(Date date, String formatStr) { + if (date == null) { + return ""; + } + DateTime dateTime = new DateTime(date); + return dateTime.toString(formatStr); + } + + public static Date strToDate(String dateTimeStr) { + DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"); + DateTime dateTime = dateTimeFormatter.parseDateTime(dateTimeStr); + return dateTime.toDate(); + } + + /* + * 将时间转换为时间戳 + */ + public static String dateToStamp(String time){ + String stamp = ""; + if (!"".equals(time)) {//时间不为空 + try { + String res; + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + Date date = simpleDateFormat.parse(time); + long ts = date.getTime(); + res = String.valueOf(ts); + return res; + } catch (Exception e) { + System.out.println("参数为空!"); + } + }else { //时间为空 + long current_time = System.currentTimeMillis(); //获取当前时间 + stamp = String.valueOf(current_time/1000); + } + return stamp; + } + + + /* + * 将时间戳转换为时间 + */ + public static String stampToDate(String s){ + String res; + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + long lt = new Long(s); + Date date = new Date(lt); + res = simpleDateFormat.format(date); + return res; + } + + /*获取当前时间戳*/ + public static String getStampNow() { + Long startTs = System.currentTimeMillis(); // 当前时间戳 + return startTs.toString(); + } + + + public static Timestamp searchStrToTimestamp(String dateTimeStr) { + return Timestamp.valueOf(dateTimeStr); + } + + + public static String dateToStr(Date date) { + if (date == null) { + return ""; + } + DateTime dateTime = new DateTime(date); + return dateTime.toString("yyyy-MM-dd HH:mm:ss"); + } + + + public static Date longToDate(Long time) { + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + String d = format.format(time); + + Date date = null; + try { + date = format.parse(d); + } catch (Exception e) { + log.error("datetime utils longToDate error"); + } + return date; + } + + + public static Date doEndTime(Date begintime, int month) { + Long begintimelong = Long.valueOf(begintime.getTime() / 1000L); + log.info("计算时间 传入时间 = {} , 时间戳 = {}", dateToStr(begintime), begintimelong); + + Long endtimelong = Long.valueOf(begintimelong.longValue() + (2592000 * month)); + Date endtimedate = longToDate(Long.valueOf(endtimelong.longValue() * 1000L)); + + log.info("endtime 时间戳 = {},时间 = {} , 格式化时间={}", new Object[]{endtimelong, endtimedate, + dateToStr(endtimedate)}); + + return endtimedate; + } + + + public static String getCurrentTimeMiao() { + return String.valueOf(System.currentTimeMillis() / 1000L); + } + + + public static Date parseToDateByMinute(int minuteTimes) { + Date nowDate = new Date(); + Long nowtimes = Long.valueOf(nowDate.getTime() / 1000L); + + Long beginTimesLong = Long.valueOf(nowtimes.longValue() - (minuteTimes * 60)); + return longToDate(Long.valueOf(beginTimesLong.longValue() * 1000L)); + } + + + public static boolean isCanSell(Date buyDate, int maxMinutes) { + Long buyDateTimes = Long.valueOf(buyDate.getTime() / 1000L); + + buyDateTimes = Long.valueOf(buyDateTimes.longValue() + (maxMinutes * 60)); + + Long nowDateTimes = Long.valueOf((new Date()).getTime() / 1000L); + + if (nowDateTimes.longValue() > buyDateTimes.longValue()) { + return true; + } + return false; + } + + /*日期年月日是否相同*/ + public static boolean sameDate(Date d1, Date d2) { + SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd"); + //fmt.setTimeZone(new TimeZone()); // 如果需要设置时间区域,可以在这里设置 + return fmt.format(d1).equals(fmt.format(d2)); + } + + /** + * 【参考】https://www.cnblogs.com/zhaoKeju-bokeyuan/p/12125711.html + * 基于指定日期增加天数 + * @param date + * @param num 整数往后推,负数往前移 + * @return + */ + public static Date addDay(Date date,int num) { + Calendar cal = Calendar.getInstance(); + cal.setTime(date); + cal.add(Calendar.DATE, num); + return cal.getTime(); + } + + + public static void main(String[] args) { + parseToDateByMinute(10); + } +} diff --git a/src/main/java/cn/stock/market/utils/ExTrans.java b/src/main/java/cn/stock/market/utils/ExTrans.java new file mode 100644 index 0000000..a635eb9 --- /dev/null +++ b/src/main/java/cn/stock/market/utils/ExTrans.java @@ -0,0 +1,69 @@ +package cn.stock.market.utils; + +import java.util.function.Consumer; + +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.transaction.TransactionDefinition; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.DefaultTransactionDefinition; + +import cn.qutaojing.common.utils.SpringUtils; + +/** + * + * title: TranUtils.java + * + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Aug 27, 2020 2:40:02 PM + */ +public class ExTrans { + static JpaTransactionManager transactionManager; + static ExTrans tranUtils; + + public static ExTrans of() { + if(tranUtils == null) { + tranUtils = new ExTrans(); + } + + return tranUtils; + } + + JpaTransactionManager getJpaTransactionManager() { + if(transactionManager == null) { + transactionManager = SpringUtils.getBean("transactionManager"); + } + return transactionManager; + } + + public TransactionStatus requiresNew() { + DefaultTransactionDefinition def = new DefaultTransactionDefinition(); + def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); + TransactionStatus status = getJpaTransactionManager().getTransaction(def); + return status; + } + + public void commit(TransactionStatus status) { + if(! status.isCompleted()) { + getJpaTransactionManager().commit(status); + } + } + + public void rollback(TransactionStatus status) { + if(! status.isCompleted()) { + getJpaTransactionManager().rollback(status); + } + } + + public void exec(Consumer c) { + TransactionStatus status = requiresNew(); + try { + c.accept(status); + commit(status); + } catch(Exception e) { + rollback(status); + throw e; + } + } +} diff --git a/src/main/java/cn/stock/market/utils/ExceptionHandler.java b/src/main/java/cn/stock/market/utils/ExceptionHandler.java new file mode 100644 index 0000000..ee2c95c --- /dev/null +++ b/src/main/java/cn/stock/market/utils/ExceptionHandler.java @@ -0,0 +1,182 @@ +package cn.stock.market.utils; + +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.dao.DataAccessException; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.InvalidDataAccessApiUsageException; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.multipart.MultipartException; +import org.springframework.web.multipart.support.MissingServletRequestPartException; +import org.springframework.web.servlet.HandlerExceptionResolver; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.util.ContentCachingRequestWrapper; + +import com.ag.exception.CodeException; +import com.ag.exception.CommonCode; +import com.ag.utils.CollectionUtils; +import com.ag.utils.RequestUtils; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.support.spring.FastJsonJsonView; +import com.google.common.collect.Lists; + +import cn.qutaojing.common.constant.ExceptionHttpStatus; +import cn.qutaojing.common.constant.Loggers; +import cn.qutaojing.common.utils.R; + +/** + * + * title: ExceptionHandler.java 异常句柄 + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @version 1.0 + * @created 2015年9月16日 下午3:40:35 + */ +public class ExceptionHandler implements HandlerExceptionResolver { + HttpStatus httpStatus; + public ExceptionHandler(HttpStatus httpStatus) { + this.httpStatus = httpStatus; + } + + private Object prettyString(String s) { + try { + return JSON.parse(s); + } catch(Exception ex) { + } + + return s; + } + + private ModelAndView mv(Object handler, Map map) { + map.put("status", map.get("code")); + map.remove("code"); + if(handler instanceof HandlerMethod) { + HandlerMethod handlerMethod = (HandlerMethod) handler; + boolean isResponseBody = handlerMethod.getMethod().isAnnotationPresent(ResponseBody.class) + || handlerMethod.getBeanType().isAnnotationPresent(RestController.class); + + if(isResponseBody) { + return new ModelAndView(new FastJsonJsonView(), map); + } else { + return new ModelAndView("exception", map); + } + } + return new ModelAndView(new FastJsonJsonView(), map); + } + + public static CodeException getCodeException(Exception ex) { + Throwable throwable = ex; + + while(throwable != null) { + if(throwable instanceof CodeException) { + return (CodeException) throwable; + } + + throwable = throwable.getCause(); + } + + return null; + } + + @Override + public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, + Exception ex) { + Map map = new HashMap(); + boolean printStackTrace = true; + CodeException ce = getCodeException(ex); + + if (ce != null) {// 自定义异常 + map = ce.toMap(); + printStackTrace = false; + } else if(ex instanceof MissingServletRequestPartException) { + map = R.error(-1,"请上传图片"); + } else if (ex instanceof SQLException || ex instanceof DataAccessException) { + if(ex instanceof InvalidDataAccessApiUsageException) { + InvalidDataAccessApiUsageException idaau = ((InvalidDataAccessApiUsageException) ex); + if(idaau.getCause() != null && idaau.getCause() instanceof IllegalArgumentException) { + map = R.error(-1, idaau.getCause().getLocalizedMessage()); + printStackTrace = false; + } else { + map = R.error(CommonCode.SQL_EXCEPTION, "哎呀,服务器出错啦!"); + } + } else if(ex instanceof DataIntegrityViolationException) {//违法了唯一约束 + printStackTrace = true; + map = R.error(CommonCode.SQL_EXCEPTION, "请稍后重试"); + } else { + map = R.error(CommonCode.SQL_EXCEPTION, "哎呀,服务器出错啦!"); + } + } else if (ex instanceof MultipartException) { + map = R.error(CommonCode.FILE_UPLOAD_ERROR, "文件上传失败,切换网络试试!"); + } else if (ex instanceof NullPointerException) { + map = R.error(CommonCode.NULL_POINT_ERROR, ",服务器出错啦!请稍后重试"); + } else if (ex instanceof ArrayIndexOutOfBoundsException) { + map = R.error(CommonCode.ARRAY_INDEXOUTOF_BOUNDS, "哎呀,服务器出错啦!请稍后重试"); + } else { + map = R.error(-1, ex.getLocalizedMessage()); + } + + // entry.value 不能为null + List nullKeyValueList = Lists.newArrayList(); + for(Map.Entry e : map.entrySet()) { + if(e.getValue() == null) { + nullKeyValueList.add(e.getKey()); + } + } + + if(CollectionUtils.isNotEmpty(nullKeyValueList)) { + for (String nukkKey : nullKeyValueList) { + map.put(nukkKey, "null"); + } + } + + //logger + Object p = null; + if("POST".equalsIgnoreCase(request.getMethod())) {//POST + if(request instanceof ContentCachingRequestWrapper) { + ContentCachingRequestWrapper requestWrapper = (ContentCachingRequestWrapper) request; + p = prettyString(new String(requestWrapper.getContentAsByteArray())); + } else { + p = RequestUtils.getPostParm(request); + } + } else { + p = JSON.toJSON(request.getParameterMap()); + } + + String message = String.format("请求地址:%s>>>%s<<<,参数:%s, 异常信息:%s,请求头:%s", request.getRequestURI(), request.getMethod(), p, ex.toString(), JSON.toJSONString(RequestUtils.getRequestHeaders(request))); + Loggers.EXCEPTION.error(message, printStackTrace ? ex : null); + + //httpstatus + HttpStatus httpStatus = this.httpStatus; + if(handler instanceof HandlerMethod) { + HandlerMethod handlerMethod = (HandlerMethod) handler; + boolean hasAnno = handlerMethod.getMethod().isAnnotationPresent(ExceptionHttpStatus.class) + || handlerMethod.getBeanType().isAnnotationPresent(ExceptionHttpStatus.class); + + if(hasAnno) { + ExceptionHttpStatus annotation = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), ExceptionHttpStatus.class); + if(annotation == null) { + annotation = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), ExceptionHttpStatus.class); + } + + if(annotation != null) { + httpStatus = annotation.status(); + response.setStatus(httpStatus.value()); + } + } + } + + //view + return mv(handler, map); + } +} diff --git a/src/main/java/cn/stock/market/utils/Exports.java b/src/main/java/cn/stock/market/utils/Exports.java new file mode 100644 index 0000000..42ca799 --- /dev/null +++ b/src/main/java/cn/stock/market/utils/Exports.java @@ -0,0 +1,74 @@ +package cn.stock.market.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URLEncoder; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletResponse; + +import org.springframework.http.MediaType; + +import com.ag.utils.CollectionUtils; +import com.ag.utils.DateUtils; +import com.ag.utils.Jsons; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.alibaba.excel.write.metadata.fill.FillWrapper; +import com.alibaba.fastjson.JSONObject; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jul 1, 2021 11:26:24 AM + */ +public final class Exports { + + static void one(JSONObject root, String key, Object value) { + if(value instanceof JSONObject) { + for(Map.Entry entry : ((JSONObject) value).entrySet()) { + String newKey = key + "_" + entry.getKey(); + one(root, newKey, entry.getValue()); + } + } else { + root.put(key, value); + } + } + + public static void export(String title, String tmpl, List l, HttpServletResponse response) throws IOException { + export(title, tmpl, l, null, response); + } + + public static void export(String title, String tmpl, List l, Function> func, HttpServletResponse response) throws IOException { + List list = l.stream().map(val -> { + JSONObject json = Jsons.toJSON(val); + if(func != null) { + Map map = func.apply(val); + if(CollectionUtils.isNotEmpty(map)) { + for(Map.Entry entry : map.entrySet()) { + one(json, entry.getKey(), Jsons.toJSON(entry.getValue())); + } + } + } + return json; + }).collect(Collectors.toList()); + + String fileName = String.format("%s导出%s.xlsx", title, DateUtils.format("yyyyMMddHH", new Date())); + + response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); + response.setCharacterEncoding("UTF-8"); + response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); + + InputStream templateInputStream = Exports.class.getResourceAsStream(tmpl); + ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(templateInputStream).build(); + WriteSheet writeSheet = EasyExcel.writerSheet().build(); + excelWriter.fill(new FillWrapper("list", list), writeSheet); + excelWriter.finish(); + } +} diff --git a/src/main/java/cn/stock/market/utils/GetPyByChinese.java b/src/main/java/cn/stock/market/utils/GetPyByChinese.java new file mode 100644 index 0000000..d3e5d3e --- /dev/null +++ b/src/main/java/cn/stock/market/utils/GetPyByChinese.java @@ -0,0 +1,109 @@ +package cn.stock.market.utils; + +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import net.sourceforge.pinyin4j.PinyinHelper; +import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType; +import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat; +import net.sourceforge.pinyin4j.format.HanyuPinyinToneType; +import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination; + +public class GetPyByChinese { + public static void main(String[] args) { + System.out.println(converterToFirstSpell("长沙市长")); + System.out.println(converterToFirstSpell("平安银行")); + System.out.println(converterToFirstSpell("老板电器")); + } + + public static String converterToFirstSpell(String chines) { + StringBuffer pinyinName = new StringBuffer(); + char[] nameChar = chines.toCharArray(); + HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat(); + defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); + defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); + for (int i = 0; i < nameChar.length; i++) { + if (nameChar[i] > '€') { + try { + String[] strs = PinyinHelper.toHanyuPinyinStringArray(nameChar[i], defaultFormat); + if (strs != null) { + for (int j = 0; j < strs.length; j++) { + pinyinName.append(strs[j].charAt(0)); + if (j != strs.length - 1) { + pinyinName.append(","); + } + } + } + } catch (BadHanyuPinyinOutputFormatCombination e) { + e.printStackTrace(); + } + } else { + pinyinName.append(nameChar[i]); + } + pinyinName.append(" "); + } + + return parseTheChineseByObject(discountTheChinese(pinyinName.toString())); + } + + + private static List> discountTheChinese(String theStr) { + List> mapList = new ArrayList>(); + Map onlyOne = null; + String[] firsts = theStr.split(" "); + for (String str : firsts) { + onlyOne = new Hashtable(); + String[] china = str.split(","); + for (String s : china) { + Integer count = onlyOne.get(s); + if (count == null) { + onlyOne.put(s, new Integer(1)); + } else { + onlyOne.remove(s); + Integer integer1=count,integer2=count=Integer.valueOf(count.intValue() + 1); + onlyOne.put(s, count); + } + } + mapList.add(onlyOne); + } + return mapList; + } + + + private static String parseTheChineseByObject(List> list) { + Map first = null; + for (int i = 0; i < list.size(); i++) { + Map temp = new Hashtable<>(); + if (first != null) { + for (String s : first.keySet()) { + for (Object s1 : ((Map)list.get(i)).keySet()) { + String str = s + s1; + temp.put(str, Integer.valueOf(1)); + } + } + if (temp != null && temp.size() > 0) { + first.clear(); + } + } else { + for (Object s : ((Map)list.get(i)).keySet()) { + String str = (String) s; + temp.put(str, Integer.valueOf(1)); + } + } + if (temp != null && temp.size() > 0) { + first = temp; + } + } + String returnStr = ""; + if (first != null) { + for (String str : first.keySet()) { + returnStr = returnStr + str + ","; + } + } + if (returnStr.length() > 0) { + returnStr = returnStr.substring(0, returnStr.length() - 1); + } + return returnStr; + } +} diff --git a/src/main/java/cn/stock/market/utils/HttpClientRequest.java b/src/main/java/cn/stock/market/utils/HttpClientRequest.java new file mode 100644 index 0000000..5655eb9 --- /dev/null +++ b/src/main/java/cn/stock/market/utils/HttpClientRequest.java @@ -0,0 +1,190 @@ +package cn.stock.market.utils; + + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.github.pagehelper.StringUtil; +import org.apache.http.HttpEntity; +import org.apache.http.NameValuePair; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.cookie.Cookie; +import org.apache.http.impl.client.BasicCookieStore; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; + + +public class HttpClientRequest { + public static String doGet(String url) { + CloseableHttpClient httpClient = null; + CloseableHttpResponse response = null; + String result = ""; + + try { + httpClient = HttpClients.createDefault(); + + HttpGet httpGet = new HttpGet(url); + + httpGet.setHeader("Authorization", "Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0"); + httpGet.setHeader("Referer", "https://finance.sina.com.cn"); + + + RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000).setConnectionRequestTimeout(35000).setSocketTimeout(60000).build(); + + httpGet.setConfig(requestConfig); + + response = httpClient.execute(httpGet); + + HttpEntity entity = response.getEntity(); + + result = EntityUtils.toString(entity); + } catch (ClientProtocolException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + + if (null != response) { + try { + response.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (null != httpClient) { + try { + httpClient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return result; + } + /** + * 获取cooike + * @param url + * @return + */ + public static List getCookie(String url) { + CloseableHttpClient httpClient = null; + CloseableHttpResponse response = null; + String result = ""; + List cookieList=null; + try { + + + HttpGet httpGet = new HttpGet(url); + + BasicCookieStore store= new BasicCookieStore(); + httpClient = HttpClients.custom().setDefaultCookieStore(store).build(); + RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000).setConnectionRequestTimeout(35000).setSocketTimeout(60000).build(); + + httpGet.setConfig(requestConfig); + + response = httpClient.execute(httpGet); + cookieList= store.getCookies(); + System.out.println(cookieList); + HttpEntity entity = response.getEntity(); + + result = EntityUtils.toString(entity); + } catch (ClientProtocolException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + + if (null != response) { + try { + response.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (null != httpClient) { + try { + httpClient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return cookieList; + } + + public static String doPost(String url, Map paramMap) { + CloseableHttpClient httpClient = null; + CloseableHttpResponse httpResponse = null; + String result = ""; + + httpClient = HttpClients.createDefault(); + + HttpPost httpPost = new HttpPost(url); + + + RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000).setConnectionRequestTimeout(35000).setSocketTimeout(60000).build(); + + httpPost.setConfig(requestConfig); + + httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded"); + + if (null != paramMap && paramMap.size() > 0) { + List nvps = new ArrayList(); + + Set> entrySet = paramMap.entrySet(); + + Iterator> iterator = entrySet.iterator(); + while (iterator.hasNext()) { + Map.Entry mapEntry = (Map.Entry) iterator.next(); + nvps.add(new BasicNameValuePair((String) mapEntry.getKey(), mapEntry.getValue().toString())); + } + + + try { + httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8")); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + + try { + httpResponse = httpClient.execute(httpPost); + + HttpEntity entity = httpResponse.getEntity(); + result = EntityUtils.toString(entity); + } catch (ClientProtocolException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + + if (null != httpResponse) { + try { + httpResponse.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (null != httpClient) { + try { + httpClient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return result; + } +} diff --git a/src/main/java/cn/stock/market/utils/HttpRequest.java b/src/main/java/cn/stock/market/utils/HttpRequest.java new file mode 100644 index 0000000..a2f1770 --- /dev/null +++ b/src/main/java/cn/stock/market/utils/HttpRequest.java @@ -0,0 +1,160 @@ +package cn.stock.market.utils; + + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class HttpRequest { + private static final Logger log = LoggerFactory.getLogger(HttpRequest.class); + + + public static String doGet(String url, String params) throws Exception { + URL localURL = new URL(url + params); + URLConnection connection = localURL.openConnection(); + HttpURLConnection httpURLConnection = (HttpURLConnection) connection; + httpURLConnection.setRequestProperty("Accept-Charset", "utf-8"); + httpURLConnection.setRequestProperty("Content-Type", "application/text"); + InputStream inputStream = null; + InputStreamReader inputStreamReader = null; + BufferedReader reader = null; + StringBuffer resultBuffer = new StringBuffer(); + String tempLine = null; + + if (httpURLConnection.getResponseCode() >= 300) { + throw new Exception("HTTP Request is not success, Response code is " + httpURLConnection + + .getResponseCode()); + } + try { + inputStream = httpURLConnection.getInputStream(); + inputStreamReader = new InputStreamReader(inputStream); + reader = new BufferedReader(inputStreamReader); + + while ((tempLine = reader.readLine()) != null) { + resultBuffer.append(tempLine); + } + } finally { + if (reader != null) { + reader.close(); + } + if (inputStreamReader != null) { + inputStreamReader.close(); + } + if (inputStream != null) { + inputStream.close(); + } + } + return resultBuffer.toString(); + } + + /* + *抓数据专用, + *signature:授权码 + * timestamp:时间戳 + * url + */ + public static String doGrabGet(String url) throws Exception { + // Request URL: http://gateway.jinyi999.cn/rjhy-news/api/1/tcy/news/hotlist?columnCodes=cjyw&appCode=tcy&showPermission=0&limit=20&hasContent=0&pageNo=1 + URL localURL = new URL(url); + URLConnection connection = localURL.openConnection(); + HttpURLConnection httpURLConnection = (HttpURLConnection) connection; + httpURLConnection.setRequestProperty("Accept-Charset", "utf-8"); + /*httpURLConnection.setRequestProperty("Access-Control-Allow-Credentials", "true"); + httpURLConnection.setRequestProperty("Access-Control-Allow-Headers", "X-Requested-With, accept, origin, content-type, signature, timestamp, appcode, whiteList"); + httpURLConnection.setRequestProperty("Content-Encoding", "gzip"); + httpURLConnection.setRequestProperty("Content-Language", "zh-CN"); + httpURLConnection.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); + //httpURLConnection.setRequestProperty("Accept", "application/json, text/plain"); + httpURLConnection.setRequestProperty("Origin", "http://static.sinagp.com"); + httpURLConnection.setRequestProperty("signature", signature); + httpURLConnection.setRequestProperty("timestamp", timestamp);*/ + InputStream inputStream = null; + InputStreamReader inputStreamReader = null; + BufferedReader reader = null; + StringBuffer resultBuffer = new StringBuffer(); + String tempLine = null; + + if (httpURLConnection.getResponseCode() >= 300) { + throw new Exception("HTTP Request is not success, Response code is " + httpURLConnection + + .getResponseCode()); + } + try { + inputStream = httpURLConnection.getInputStream(); + inputStreamReader = new InputStreamReader(inputStream); + //reader = new BufferedReader(inputStreamReader); + reader = new BufferedReader(new InputStreamReader(connection.getInputStream(),"UTF-8")); + + while ((tempLine = reader.readLine()) != null) { + resultBuffer.append(tempLine); + } + } finally { + if (reader != null) { + reader.close(); + } + if (inputStreamReader != null) { + inputStreamReader.close(); + } + if (inputStream != null) { + inputStream.close(); + } + } + return resultBuffer.toString(); + } + + + public static String doPost(String url, Map params) throws Exception { + HttpPost httpPost = new HttpPost(url); + + DefaultHttpClient defaultHttpClient = new DefaultHttpClient(); + List nvps = new ArrayList(); + if (params != null) { + BasicNameValuePair bnvp = null; + for (Map.Entry p : params.entrySet()) { + bnvp = new BasicNameValuePair((String) p.getKey(), (String) p.getValue()); + } + } + httpPost.setEntity(new UrlEncodedFormEntity(nvps)); + HttpResponse response = defaultHttpClient.execute(httpPost); + HttpEntity respEntity = response.getEntity(); + String text = EntityUtils.toString(respEntity, "UTF-8"); + + defaultHttpClient.getConnectionManager().shutdown(); + + return text; + } + + + public static void main(String[] args) { + String url = ""; + String ips = "183.32.208.138"; + + String getret = ""; + try { + getret = doGet(url, ips); + } catch (Exception e) { + e.printStackTrace(); + } + log.info("get ret : " + getret); + } + + +} diff --git a/src/main/java/cn/stock/market/utils/Messages.java b/src/main/java/cn/stock/market/utils/Messages.java new file mode 100644 index 0000000..2a10168 --- /dev/null +++ b/src/main/java/cn/stock/market/utils/Messages.java @@ -0,0 +1,37 @@ +package cn.stock.market.utils; + +import com.alibaba.fastjson.JSONObject; + +import cn.stock.market.infrastructure.api.JuheApis; + +public class Messages { + public static boolean succ(JSONObject json) { + return json.getIntValue("error_code") == 0; + } + + public static JSONObject warn(String phone) { + return JuheApis.send(phone, JuheApis.SMS_WARN, null); + } + + public static JSONObject positionAdd(String phone) { + return JuheApis.send(phone, JuheApis.SMS_POSITION_ADD, null); + } + + public static JSONObject sendCode(String phone, String code) { + JSONObject json = new JSONObject(); + json.put("error_code", 0); + json.put("tips", "FAKE"); + return json; +// return JuheApis.send(phone, JuheApis.SMS_VERIFY_CODE, "#code#=" + code); + } + + public static void recharge(String phone) { + JuheApis.send(phone, JuheApis.SMS_RECHARGE, null); + } + public static void open(String phone) { + JuheApis.send(phone, JuheApis.SMS_OPEN, null); + } + public static void withdrawal(String phone) { + JuheApis.send(phone, JuheApis.SMS_WITHDRAWAL, null); + } +} diff --git a/src/main/java/cn/stock/market/utils/PropertiesUtil.java b/src/main/java/cn/stock/market/utils/PropertiesUtil.java new file mode 100644 index 0000000..287a66a --- /dev/null +++ b/src/main/java/cn/stock/market/utils/PropertiesUtil.java @@ -0,0 +1,45 @@ +package cn.stock.market.utils; + + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.stock.market.web.config.Env; + + +public class PropertiesUtil { + private static Logger logger = LoggerFactory.getLogger(PropertiesUtil.class); + +// private static Properties props; +// +// static { +// String fileName = "stock2guo.properties"; +// props = new Properties(); +// try { +// props.load(new InputStreamReader(PropertiesUtil.class.getClassLoader().getResourceAsStream(fileName), "UTF-8")); +// } catch (IOException e) { +// logger.error("配置文件读取异常", e); +// } +// } + + public static String getProperty(String key) { + return getProperty(key, null); + } + + + public static String getProperty(String key, String defaultValue) { + Env env = Env.of(); + if(env == null) { + logger.warn("找配置信息 key: {} 时环境未初始化完成! ", env); + return defaultValue; + } + + String value = env.environment().getProperty(key.trim()); + if (StringUtils.isBlank(value)) { + value = defaultValue; + } + return StringUtils.trim(value); + } +} + diff --git a/src/main/java/cn/stock/market/utils/QRImpl.java b/src/main/java/cn/stock/market/utils/QRImpl.java new file mode 100644 index 0000000..cf5abf8 --- /dev/null +++ b/src/main/java/cn/stock/market/utils/QRImpl.java @@ -0,0 +1,26 @@ +package cn.stock.market.utils; + +import java.awt.Font; +import java.io.InputStream; + +import cn.stock.market.utils.UserQRs.IQR; + +public class QRImpl implements IQR { + + @Override + public Font font() { + throw new UnsupportedClassVersionError(); + } + + @Override + public InputStream bg() { + InputStream inputStream = UserQRs.class.getResourceAsStream("/static/user_qrcode_picture_tmpl.jpg"); + return inputStream; + } + + @Override + public InputStream qrbg() { + throw new UnsupportedClassVersionError(); + } + +} diff --git a/src/main/java/cn/stock/market/utils/RedisGeoUtils.java b/src/main/java/cn/stock/market/utils/RedisGeoUtils.java new file mode 100644 index 0000000..9c7b2ae --- /dev/null +++ b/src/main/java/cn/stock/market/utils/RedisGeoUtils.java @@ -0,0 +1,118 @@ +//package cn.stock.market.utils; +// +//import java.util.List; +// +//import org.springframework.data.geo.Circle; +//import org.springframework.data.geo.Distance; +//import org.springframework.data.geo.GeoResults; +//import org.springframework.data.geo.Metric; +//import org.springframework.data.geo.Point; +//import org.springframework.data.redis.connection.RedisGeoCommands; +//import org.springframework.data.redis.core.RedisTemplate; +// +//import com.ag.utils.CollectionUtils; +// +//import cn.qutaojing.common.utils.SpringUtils; +// +///** +// * +// * title: RedisGeoUtils.java +// * +// * @author xlfd +// * @email xlfd@gmail.com +// * @version 1.0 +// * @created Jul 1, 2021 11:26:34 AM +// */ +//@SuppressWarnings({"deprecation", "unchecked", "rawtypes"}) +//public class RedisGeoUtils { +// public static RedisTemplate redisTemplate() { +// return SpringUtils.getBean(RedisTemplate.class); +// } +// +// /** +// * 添加经纬度信息,时间复杂度为O(log(N)) +// * redis 命令:geoadd cityGeo 116.405285 39.904989 "北京" +// * @param k +// * @param point +// * @param m +// */ +// public static Long addGeoPoin(Object k, Point point, Object m) { +// Long addedNum = redisTemplate().opsForGeo().geoAdd(k, point, m); +// return addedNum; +// } +// +// public static Point geoGet(Object k, Object m) { +// List points = geoGet(k, new Object[] { m }); +// +// return CollectionUtils.isNotEmpty(points) ? points.get(0) : null; +// } +// +// /** +// * 查找指定key的经纬度信息,可以指定多个key,批量返回 +// * redis命令:geopos cityGeo 北京 +// * @param k +// * @param m +// */ +// public static List geoGet(Object k, Object... m) { +// List points = redisTemplate().opsForGeo().geoPos(k, m); +// return points; +// } +// +// /** +// * 返回两个地方的距离,可以指定单位,比如米m,千米km,英里mi,英尺ft +// * redis命令:geodist cityGeo 北京 上海 +// * @param k +// * @param mk1 +// * @param mk2 +// * @param metric +// * @return +// */ +// public static Distance geoDist(Object k, Object mk1, Object mk2, Metric metric) { +// Distance distance = redisTemplate().opsForGeo().geoDist(k, mk1, mk2, metric); +// return distance; +// } +// +// /** +// * 根据给定的经纬度,返回半径不超过指定距离的元素,时间复杂度为O(N+log(M)),N为指定半径范围内的元素个数,M为要返回的个数 +// * redis命令:georadius cityGeo 116.405285 39.904989 100 km WITHDIST WITHCOORD ASC COUNT 5 +// * @param k +// * @param circle +// * @param args +// */ +// public static GeoResults> nearByXY(Object k, Circle circle, RedisGeoCommands.GeoRadiusCommandArgs args) { +// //longitude,latitude +// //Circle circle = new Circle(116.405285, 39.904989, Metrics.KILOMETERS.getMultiplier()); +// //RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates().sortAscending().limit(5); +// +// GeoResults> results = redisTemplate().opsForGeo().geoRadius(k, circle, args); +// return results; +// } +// +// /** +// * 根据指定的地点查询半径在指定范围内的位置,时间复杂度为O(log(N)+M),N为指定半径范围内的元素个数,M为要返回的个数 +// * redis命令:georadiusbymember cityGeo 北京 100 km WITHDIST WITHCOORD ASC COUNT 5 +// * @param k +// * @param mk +// * @param distance +// * @param args +// * @return +// */ +// public static GeoResults nearByPlace(Object k, Object mk, Distance distance, RedisGeoCommands.GeoRadiusCommandArgs args) { +//// Distance distance = new Distance(5, Metrics.KILOMETERS); +//// RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates().sortAscending().limit(5); +// GeoResults> results = redisTemplate().opsForGeo().geoRadiusByMember(k, mk, distance, args); +// return results; +// } +// +// /** +// * 返回的是geohash值,查找一个位置的时间复杂度为O(log(N)) +// * redis命令:geohash cityGeo 北京 +// * @param k +// * @param mks +// * @return +// */ +// public static List geoHash(Object k, Object... mks) { +// List results = redisTemplate().opsForGeo().geoHash(k, mks); +// return results; +// } +//} diff --git a/src/main/java/cn/stock/market/utils/RequestCacheUtils.java b/src/main/java/cn/stock/market/utils/RequestCacheUtils.java new file mode 100644 index 0000000..2d3b35f --- /dev/null +++ b/src/main/java/cn/stock/market/utils/RequestCacheUtils.java @@ -0,0 +1,91 @@ +package cn.stock.market.utils; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.LongAdder; +import java.util.function.Function; +import java.util.stream.Collectors; + +import com.alibaba.fastjson.JSON; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.collect.Maps; + +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class RequestCacheUtils { + static Map>> map = Maps.newConcurrentMap(); + public static List stat() { + return map + .entrySet() + .stream() + .map(entry -> entry.getKey() + "-" + entry.getValue().stats()) + .collect(Collectors.toList()); + } + + public static Cache> cache(String key) { + if(! map.containsKey(key)) { + log.info("创建缓存: {}", key); + Cache> cache = CacheBuilder.newBuilder() + .maximumSize(1000) + .expireAfterWrite(500,TimeUnit.MILLISECONDS) + .weakValues() + .recordStats() + .build( +// new CacheLoader() { +// @Override +// public Object load(String key) throws Exception { +// return func.apply(key); +// } +// } + ); + map.put(key, cache); + } + + return map.get(key); + } + + @SuppressWarnings("unchecked") + @SneakyThrows + public static ServerResponse cache(String module, String key, Function> func) { + Cache> cache = cache(module); + AtomicBoolean bool = new AtomicBoolean(true); + ServerResponse response = (ServerResponse) cache.get(key, () -> { + bool.set(false); + return func.apply(key); + }); + + if(bool.get()) { + log.info("命中缓存 module: {}, key: {}, 时间戳: {}", module, key, System.currentTimeMillis()); + } + + return response; + } + + public static void main(String[] args) throws InterruptedException { + ServerResponse response = null; + Function> func = (string) -> { + System.out.println("LLLLL" + string); + return ServerResponse.createBySuccess("TTTT"); + }; + response = cache("_test_", "_TEST_KEY", func); + System.out.println(JSON.toJSONString(response)); + + response = cache("_test_", "_TEST_KEY", func); + System.out.println(JSON.toJSONString(response)); + + response = cache("_test_", "_TEST_KEY", func); + System.out.println(JSON.toJSONString(response)); + response = cache("_test_", "_TEST_KEY_2", func); + System.out.println(JSON.toJSONString(response)); + + Thread.sleep(500); + + response = cache("_test_", "_TEST_KEY", func); + System.out.println(JSON.toJSONString(response)); + } +} diff --git a/src/main/java/cn/stock/market/utils/Requests.java b/src/main/java/cn/stock/market/utils/Requests.java new file mode 100644 index 0000000..5dca374 --- /dev/null +++ b/src/main/java/cn/stock/market/utils/Requests.java @@ -0,0 +1,43 @@ +package cn.stock.market.utils; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.StringUtils; + +import com.ag.utils.CollectionUtils; + +import cn.stock.market.utils.Cons.QDeviceType; + +public class Requests { + + /** + * 获取设备类型 ,与前端约定 + * + * @param qUserAgent + * @return + */ + public static String getDeviceType(String qUserAgent) { + + if (StringUtils.isBlank(qUserAgent)) { + return QDeviceType.ANDROID; + } + if (qUserAgent.contains("-")) { + String[] _userAgent = qUserAgent.split("-"); + if (CollectionUtils.isNotEmpty(_userAgent)) { + return _userAgent[0]; + + } + } + return ""; + } + + public static String getDeviceTypeFromUserAgent(HttpServletRequest request) { + String deviceType = request.getHeader("DeviceType"); + if (StringUtils.isBlank(deviceType)) { + deviceType = request.getHeader("User-Agent"); + } + + return getDeviceType(deviceType); + } + +} diff --git a/src/main/java/cn/stock/market/utils/ResponseCode.java b/src/main/java/cn/stock/market/utils/ResponseCode.java new file mode 100644 index 0000000..48d6b8b --- /dev/null +++ b/src/main/java/cn/stock/market/utils/ResponseCode.java @@ -0,0 +1,24 @@ +package cn.stock.market.utils; + + +public enum ResponseCode { + SUCCESS(0, "SUCCESS"), + ERROR(1, "ERROR"), + NEED_LOGIN(10, "NEED_LOGIN"), + ILLEGAL_ARGUMENT(2, "ILLEGAL_ARGUMENT"); + private int code; + private String msg; + + ResponseCode(int code, String msg) { + this.code = code; + this.msg = msg; + } + + public int getCode() { + return this.code; + } + + public String getMsg() { + return this.msg; + } +} diff --git a/src/main/java/cn/stock/market/utils/ServerResponse.java b/src/main/java/cn/stock/market/utils/ServerResponse.java new file mode 100644 index 0000000..7ebaadc --- /dev/null +++ b/src/main/java/cn/stock/market/utils/ServerResponse.java @@ -0,0 +1,86 @@ +package cn.stock.market.utils; + +import java.io.Serializable; + +import com.alibaba.fastjson.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +public class ServerResponse extends Object implements Serializable { + private int status; + private String msg; + private T data; + + private ServerResponse(int status) { + this.status = status; + } + + private ServerResponse(int status, T data) { + this.status = status; + this.data = data; + } + + private ServerResponse(int status, String msg) { + this.status = status; + this.msg = msg; + } + + private ServerResponse(int status, String msg, T data) { + this.status = status; + this.msg = msg; + this.data = data; + } + + public static void main(String[] args) { + ServerResponse serverResponse = new ServerResponse(1, new Object()); + ServerResponse serverResponse1 = new ServerResponse(1, "abc"); + System.out.print("ServerResponse"); + } + + @JsonIgnore + @JSONField(serialize = false) + public boolean isSuccess() { + return (this.status == ResponseCode.SUCCESS.getCode()); + } + + public int getStatus() { + return this.status; + } + + public T getData() { + return (T) this.data; + } + + public String getMsg() { + return this.msg; + } + + public static ServerResponse createBySuccess() { + return new ServerResponse(ResponseCode.SUCCESS.getCode()); + } + + public static ServerResponse createBySuccessMsg(String msg) { + return new ServerResponse(ResponseCode.SUCCESS.getCode(), msg); + } + + public static ServerResponse createBySuccess(T data) { + return new ServerResponse(ResponseCode.SUCCESS.getCode(), data); + } + + public static ServerResponse createBySuccess(String msg, T data) { + return new ServerResponse(ResponseCode.SUCCESS.getCode(), msg, data); + } + + public static ServerResponse createByError() { + return new ServerResponse(ResponseCode.ERROR.getCode(), ResponseCode.ERROR.getMsg()); + } + + public static ServerResponse createByErrorMsg(String errormsg) { + return new ServerResponse(ResponseCode.ERROR.getCode(), errormsg); + } + + public static ServerResponse createByErrorCodeMsg(int errorcode, String errormsg) { + return new ServerResponse(errorcode, errormsg); + } +} \ No newline at end of file diff --git a/src/main/java/cn/stock/market/utils/StringUtils.java b/src/main/java/cn/stock/market/utils/StringUtils.java new file mode 100644 index 0000000..c1e3ec4 --- /dev/null +++ b/src/main/java/cn/stock/market/utils/StringUtils.java @@ -0,0 +1,81 @@ +package cn.stock.market.utils; + +import java.io.UnsupportedEncodingException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class StringUtils { + /** + * unicode编码转换为汉字 + * @param unicodeStr 待转化的编码 + * @return 返回转化后的汉子 + */ + public static String UnicodeToCN(String unicodeStr) { + Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))"); + Matcher matcher = pattern.matcher(unicodeStr); + char ch; + while (matcher.find()) { + //group + String group = matcher.group(2); + //ch:'李四' + ch = (char) Integer.parseInt(group, 16); + //group1 + String group1 = matcher.group(1); + unicodeStr = unicodeStr.replace(group1, ch + ""); + } + + return unicodeStr.replace("\\", "").trim(); + } + + /** + * 汉字转化为Unicode编码 + * @param CN 待转化的中文 + * @return 返回转化之后的unicode编码 + */ + public static String CNToUnicode(String CN) { + + try { + StringBuffer out = new StringBuffer(""); + //直接获取字符串的unicode二进制 + byte[] bytes = CN.getBytes("unicode"); + //然后将其byte转换成对应的16进制表示即可 + for (int i = 0; i < bytes.length - 1; i += 2) { + out.append("\\u"); + String str = Integer.toHexString(bytes[i + 1] & 0xff); + for (int j = str.length(); j < 2; j++) { + out.append("0"); + } + String str1 = Integer.toHexString(bytes[i] & 0xff); + out.append(str1); + out.append(str); + } + return out.toString(); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + return null; + } + } + + public static String delHTMLTag(String htmlStr){ + String regEx_script="]*?>[\\s\\S]*?<\\/script>"; //定义script的正则表达式 + String regEx_style="]*?>[\\s\\S]*?<\\/style>"; //定义style的正则表达式 + String regEx_html="<[^>]+>"; //定义HTML标签的正则表达式 + + Pattern p_script=Pattern.compile(regEx_script,Pattern.CASE_INSENSITIVE); + Matcher m_script=p_script.matcher(htmlStr); + htmlStr=m_script.replaceAll(""); //过滤script标签 + + Pattern p_style=Pattern.compile(regEx_style,Pattern.CASE_INSENSITIVE); + Matcher m_style=p_style.matcher(htmlStr); + htmlStr=m_style.replaceAll(""); //过滤style标签 + + Pattern p_html=Pattern.compile(regEx_html,Pattern.CASE_INSENSITIVE); + Matcher m_html=p_html.matcher(htmlStr); + htmlStr=m_html.replaceAll(""); //过滤html标签 + + return htmlStr.trim(); //返回文本字符串 + } + + + +} diff --git a/src/main/java/cn/stock/market/utils/UserQRs.java b/src/main/java/cn/stock/market/utils/UserQRs.java new file mode 100644 index 0000000..21b0726 --- /dev/null +++ b/src/main/java/cn/stock/market/utils/UserQRs.java @@ -0,0 +1,198 @@ +package cn.stock.market.utils; + +import java.awt.AlphaComposite; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.Transparency; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.WritableRaster; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.HashMap; +import java.util.Map; + +import javax.imageio.ImageIO; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.EncodeHintType; +import com.google.zxing.MultiFormatWriter; +import com.google.zxing.WriterException; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; + +public class UserQRs { + public interface IQR { + Font font(); + InputStream bg(); + InputStream qrbg(); + } + + public static void main(String[] args) throws IOException, WriterException { + String shopQr = "https://oto.qutaojing.cn/qr/mini-1112"; +// String shopImage = "https://f.qutaojing.cn/resources/20211111/2f10670a18f34e8780a2519a93419b7f.png"; + +// byte[] logo = FileUtils.readFileToByteArray(new File("/Users/rplees/Desktop/logo.png")); + byte[] logo = null; + + byte[] gen = gen(shopQr, logo, new QRImpl()); + + ByteArrayInputStream in = new ByteArrayInputStream(gen); + BufferedImage image = ImageIO.read(in); + + OutputStream os = new FileOutputStream("/Users/rplees/Desktop/ttt.png"); + ImageIO.write(image, "png", os); + os.close(); + } + + public static BufferedImage qr(String shopQr, byte[] logo) throws WriterException, IOException { + int width = 110; // 图像宽度 + int height = 110; // 图像高度 + Map hints = new HashMap<>(); + // 内容编码格式 + hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); + // 指定纠错等级 + hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); + // 设置二维码边的空度,非负数 + hints.put(EncodeHintType.MARGIN, 1); + + BitMatrix bitMatrix = new MultiFormatWriter().encode(shopQr, BarcodeFormat.QR_CODE, width, height, hints); + BufferedImage bi = toBufferedImage(bitMatrix); +// +// Graphics g = bi.getGraphics(); + +// int w = 152; +// int h = 152; +// BufferedImage logoBI = ImageIO.read(new ByteArrayInputStream(logo)); +// logoBI = resize(logoBI, Math.min(logoBI.getWidth(), logoBI.getHeight())); +// logoBI = radius(logoBI, new Double((0.3 * logoBI.getHeight())).intValue(), 0, 0); +// g.drawImage(logoBI, (bi.getWidth() - w) / 2, (bi.getHeight() - h) / 2, w, h, null); + return bi; + } + + /** + * 图片设置圆角 + * + * @param srcImage + * @param radius + * @param border + * @param padding + * @return + * @throws IOException + */ + @SuppressWarnings("all") + public static BufferedImage radius(BufferedImage srcImage, int radius, int border, int padding) + throws IOException { + int width = srcImage.getWidth(); + int height = srcImage.getHeight(); + + int canvasWidth = width + padding * 2; + int canvasHeight = height + padding * 2; + + BufferedImage image = new BufferedImage(srcImage.getWidth(), srcImage.getHeight(), BufferedImage.TYPE_INT_ARGB); + + Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, srcImage.getWidth(), srcImage.getHeight()); + + Graphics2D g2 = image.createGraphics(); + image = g2.getDeviceConfiguration() + .createCompatibleImage(srcImage.getWidth(), srcImage.getHeight(), Transparency.TRANSLUCENT); + g2 = image.createGraphics(); + g2.setComposite(AlphaComposite.Clear); + g2.fill(new Rectangle(image.getWidth(), image.getHeight())); + g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, 1.0f)); + g2.setClip(shape); + // 使用 setRenderingHint 设置抗锯齿 + g2 = image.createGraphics(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.fillRoundRect(0, 0, srcImage.getWidth(), srcImage.getHeight(), radius, radius); + g2.setComposite(AlphaComposite.SrcIn); + g2.drawImage(srcImage, 0, 0, srcImage.getWidth(), srcImage.getHeight(), null); + + if (border != 0) { + // gs.setColor(Color.GRAY); + g2.setColor(Color.GRAY); + g2.setStroke(new BasicStroke(border)); + g2.drawRoundRect(padding, padding, canvasWidth * padding, canvasHeight * padding, radius, radius); + } + g2.dispose(); + + return image; + + } + + /** + * BitMatrix 2 BufferedImage + * + * @param matrix + * @return + */ + private static BufferedImage toBufferedImage(BitMatrix matrix) { + int width = matrix.getWidth(); + int height = matrix.getHeight(); + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + image.setRGB(x, y, matrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF); + } + } + return image; + } + + public static byte[] gen(String qrContent, byte[] logo, IQR iqr) throws IOException, WriterException { + + InputStream inputStream = iqr.bg(); + BufferedImage image = ImageIO.read(inputStream); + Graphics graphics = image.getGraphics(); + + BufferedImage qr = qr(qrContent, logo); + graphics.drawImage(qr, 377, 450, 180, 180, null); + + byte[] bs = bufferedImageToByte(image); + graphics.dispose(); + return bs; + } + + public static byte[] bufferedImageToByte(BufferedImage image) throws IOException { + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + ImageIO.write(image, "png", bout); + bout.close(); + return bout.toByteArray(); + } + + public static BufferedImage resize(BufferedImage source, int targetW) { + int type = source.getType(); + BufferedImage target = null; + int width = source.getWidth(); + int height = source.getHeight(); + + double sx = (double) targetW / width; + int targetH = new Double(height * sx).intValue(); + double sy = (double) targetH / height; + if (type == BufferedImage.TYPE_CUSTOM) { + ColorModel cm = source.getColorModel(); + WritableRaster raster = cm.createCompatibleWritableRaster(targetW, + targetH); + boolean alphaPremultiplied = cm.isAlphaPremultiplied(); + target = new BufferedImage(cm, raster, alphaPremultiplied, null); + } else { + target = new BufferedImage(targetW, targetH, type); + } + Graphics2D g = target.createGraphics(); + // smoother than exlax: + g.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY); + g.drawRenderedImage(source, AffineTransform.getScaleInstance(sx, sy)); + g.dispose(); + return target; + } +} diff --git a/src/main/java/cn/stock/market/utils/Utils.java b/src/main/java/cn/stock/market/utils/Utils.java new file mode 100644 index 0000000..6a68794 --- /dev/null +++ b/src/main/java/cn/stock/market/utils/Utils.java @@ -0,0 +1,406 @@ +package cn.stock.market.utils; + +import java.net.URI; +import java.net.URISyntaxException; +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.Date; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.data.domain.Page; + +import com.ag.utils.DateUtils; +import com.ag.utils.NumberUtils; +import com.ag.utils.SysConstant.BooleanEnum; +import com.ag.utils.vo.KVObj; +import com.github.pagehelper.PageInfo; +import com.google.common.base.Joiner; +import com.google.common.collect.Lists; + +import cn.hutool.core.net.url.UrlBuilder; +import cn.qutaojing.common.constant.Currency; +import cn.stock.market.application.Dics; +import cn.stock.market.constant.StockSource; +import cn.stock.market.infrastructure.api.AliApis; +import lombok.extern.slf4j.Slf4j; +import net.sourceforge.pinyin4j.PinyinHelper; +import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType; +import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat; +import net.sourceforge.pinyin4j.format.HanyuPinyinToneType; +import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jul 1, 2021 11:26:24 AM + */ +@Slf4j +public final class Utils { + public static void throwing(KVObj kvObj) { + com.ag.utils.Utils.throwing(kvObj); + } + + public static String urlWithOutQUeryParameter(String url) { + if (StringUtils.isBlank(url)) { + return url; + } + + try { + URI uri = new URI(url); + UrlBuilder urlBuilder = UrlBuilder.of(uri.getScheme(), uri.getHost(), uri.getPort(), uri.getPath(), null, + null, null); + return urlBuilder.build(); + } catch (URISyntaxException e) { + log.error("{} 解析错误", url, e); + } + + return null; + } + + public static void checkCommunicationPersonal(String acc_no, String idcard, String mobile, String name) { + Integer flag = Dics.of().getFromCache("enable.checkCommunicationPersonal", 1); + if (BooleanEnum.isOff(flag)) { + return; + } + + AliApis.of().checkCommunicationPersonal(acc_no, idcard, mobile, name); + } + + public static Integer day() { + return NumberUtils.parseInt(DateUtils.format(DateUtils.YYYYMMDD, new Date())); + } + + public static String fenxi(String code) { + return jys(code) + code; + } + + public static boolean isShOrSzOrBJ(String code) { + String jys = jys(code); + return isShOrSzOrBjByJys(jys); + } + + public static boolean isShOrSzOrBjByJys(String jxs) { + return "sh".equals(jxs) || "sz".equals(jxs) || "bj".equals(jxs); + } + + public static String jys(String code) { + if (StringUtils.startsWith(code, "600") || StringUtils.startsWith(code, "601") + || StringUtils.startsWith(code, "603")) { + return "sh"; + } + if (StringUtils.startsWith(code, "000")) { + return "sz"; + } + + char charAt = StringUtils.substring(code, 0, 1).charAt(0); + + String prefix = ""; + switch (charAt) { + case '0': + case '1': + case '2': + case '3': + prefix = "sz"; + break; + case '5': + case '6': + case '9': + prefix = "sh"; + break; + + case '4': + case '8': + prefix = "bj"; + break; + default: + break; + } + + return prefix; + } + +// public static TradeSetting tradeSetting() { +// TradeSetting setting = Dics.of().getFromCache("trade", TradeSetting.class); +// if(setting == null) { +// setting = new TradeSetting(); +// } +// setting.check(); +// return setting; +// } +// +// public static BigDecimal lostWarn() { +// Double d = Dics.of().getFromCache("trade.lostWarn", 0.4); +// return BigDecimals.p(d); +// } +// +// public static BigDecimal lostClose() { +// Double d = Dics.of().getFromCache("trade.lostClose", 0.2); +// return BigDecimals.p(d); +// } +// +// public static BigDecimal preTradingDayCost() { +// Double d = Dics.of().getFromCache("trade.preTradingDayCost", 100D); +// return BigDecimals.p(d); +// } +// +// public static BigDecimal commission() { +// Double d = Dics.of().getFromCache("trade.commission", 0.0004); +// return BigDecimals.p(d); +// } +// +// public static BigDecimal stampTax() { +// Double d = Dics.of().getFromCache("trade.stampTax", 0.001); +// return BigDecimals.p(d); +// } + +// public static BigDecimal stampTaxCalc(BigDecimal volume) { +// return BigDecimals.multiplys(volume, Utils.tradeSetting().getStampTax()).setScale(2, RoundingMode.HALF_UP); +// } +// +// public static BigDecimal preTradingDayCalc(BigDecimal volume) { +// return BigDecimals.multiplys(volume, Utils.tradeSetting().getPreTradingDayCost()).setScale(2, RoundingMode.HALF_UP); +// } +// +// public static BigDecimal commissionCalc(BigDecimal volume) { +// return BigDecimals.multiplys(volume, Utils.tradeSetting().getCommission()).setScale(2, RoundingMode.HALF_UP); +// } +// + public static ExTrans t() { + return ExTrans.of(); + } + + public static String getFirstLetter(String string) { + if (StringUtils.isBlank(string)) + return string; + + List l = Lists.newArrayList(); + for (int i = 0; i < string.length(); i++) { + String[] array = PinyinHelper.toHanyuPinyinStringArray(string.charAt(i)); + if (array == null) { + l.add(string.charAt(i)); + } else { + l.add(array[0].toUpperCase().charAt(0)); + } + } + return Joiner.on("").join(l); + } + +// public static String pinyin(String string) { +// if(StringUtils.isBlank(string)) +// return string; +//// PinyinUtil.getPinyin(string) +// List l = Lists.newArrayList(); +// for(int i = 0; i < string.length(); i++) { +// String[] array = PinyinHelper.toHanyuPinyinStringArray(string.charAt(i)); +// if(array == null) { +// l.add(string); +// } else { +// l.add(array[0]); +// } +// } +// return Joiner.on("").join(l); +// } + + public static StockSource toSource(Currency c) { + if (c == Currency.CNY) { + return StockSource.A; + } else if (c == Currency.HKD) { + return StockSource.HK; + } else if (c == Currency.USD) { + return StockSource.US; + } + + return null; + } + + /** + * + * @param v1 格式 1.0.9 + * @param v2 + * @return + */ + public static boolean highVersion(String v1, String v2) { + int v1Int = NumberUtils.parseInt(StringUtils.replace(v1, ".", "")); + int v2Int = NumberUtils.parseInt(StringUtils.replace(v2, ".", "")); + + return v1Int > v2Int; + } + +// public static BigDecimal multiple() { +// return Dics.of().getFromCache("trade.multiple", BigDecimal.valueOf(4)); +// } + + final static List OPEN_TIME = Lists.newArrayList( + new LocalTime[] { LocalTime.of(9, 30), LocalTime.of(11, 30) }, + new LocalTime[] { LocalTime.of(13, 00), LocalTime.of(15, 00) }); + + public static boolean isTradeTime() { + if (!inTradeDay()) { + return false; + } + + LocalTime localTime = LocalTime.now(); + for (LocalTime[] lt : OPEN_TIME) { + if (localTime.isAfter(lt[0]) && localTime.isBefore(lt[1])) { + return true; + } + } + + return false; + } + + public static boolean inTradeDay() { + LocalDate localDate = LocalDate.now(); + DayOfWeek week = localDate.getDayOfWeek(); + if (week == DayOfWeek.SATURDAY || week == DayOfWeek.SUNDAY) { // 周末 + return false; + } + + if (isHoliday(localDate)) { + return false; + } + + return true; + } + + public static boolean isHoliday(LocalDate localDate) { + return false; + +// String format = localDate.format(DateTimeFormatter.ofPattern("MMdd")); +// String cacheKey = "holiday_" + format; +// Object object = CacheRepository.of().get(cacheKey); +// if(object != null) { +// return true; +// } +// +// String holiday = Dics.of().getFromCache("legal_holiday", String.class); +// JSONObject json = Jsons.toJSONAnyway(holiday); +// JSONArray array = json.getJSONArray(String.valueOf(localDate.getYear())); +// if(array == null) { +// log.warn("legal_holiday的{}年未配置", localDate.getYear()); +// return false; +// } +// +// for(Object o : array) { +// if(StringUtils.equals(String.valueOf(o), format)) { +// CacheRepository.of().set(cacheKey, 1, 24, TimeUnit.HOURS); +// return true; +// } +// } +// +// return false; + } + + public static PageInfo toPageHelperInfo(Page page) { + PageInfo pageInfo = new PageInfo<>(); + pageInfo.setList(page.getContent()); + pageInfo.setPageSize(page.getSize()); + pageInfo.setTotal(page.getTotalElements()); + pageInfo.setPageNum(page.getTotalPages()); + return pageInfo; + } + + public static String converterToFirstSpell(String chines) { + StringBuffer pinyinName = new StringBuffer(); + char[] nameChar = chines.toCharArray(); + HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat(); + defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); + defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); + for (int i = 0; i < nameChar.length; i++) { + if (nameChar[i] > '€') { + try { + String[] strs = PinyinHelper.toHanyuPinyinStringArray(nameChar[i], defaultFormat); + if (strs != null) { + for (int j = 0; j < strs.length; j++) { + pinyinName.append(strs[j].charAt(0)); + if (j != strs.length - 1) { + pinyinName.append(","); + } + } + } + } catch (BadHanyuPinyinOutputFormatCombination e) { + e.printStackTrace(); + } + } else { + pinyinName.append(nameChar[i]); + } + pinyinName.append(" "); + } + + return parseTheChineseByObject(discountTheChinese(pinyinName.toString())); + } + + private static List> discountTheChinese(String theStr) { + List> mapList = new ArrayList>(); + Map onlyOne = null; + String[] firsts = theStr.split(" "); + for (String str : firsts) { + onlyOne = new Hashtable(); + String[] china = str.split(","); + for (String s : china) { + Integer count = onlyOne.get(s); + if (count == null) { + onlyOne.put(s, new Integer(1)); + } else { + onlyOne.remove(s); + Integer integer1 = count, integer2 = count = Integer.valueOf(count.intValue() + 1); + onlyOne.put(s, count); + } + } + mapList.add(onlyOne); + } + return mapList; + } + + private static String parseTheChineseByObject(List> list) { + Map first = null; + for (int i = 0; i < list.size(); i++) { + Map temp = new Hashtable<>(); + if (first != null) { + for (String s : first.keySet()) { + for (Object s1 : ((Map) list.get(i)).keySet()) { + String str = s + s1; + temp.put(str, Integer.valueOf(1)); + } + } + if (temp != null && temp.size() > 0) { + first.clear(); + } + } else { + for (Object s : ((Map) list.get(i)).keySet()) { + String str = (String) s; + temp.put(str, Integer.valueOf(1)); + } + } + if (temp != null && temp.size() > 0) { + first = temp; + } + } + String returnStr = ""; + if (first != null) { + for (String str : first.keySet()) { + returnStr = returnStr + str + ","; + } + } + if (returnStr.length() > 0) { + returnStr = returnStr.substring(0, returnStr.length() - 1); + } + return returnStr; + } + + public static void main(String[] args) { + System.out.println(getFirstLetter("0L神鼎ds飞#@#丹砂")); + System.out.println(getFirstLetter("0L神鼎ds飞#@#丹砂")); + System.out.println(highVersion("1.0.8", "1.0.9")); + System.out.println(highVersion("1.0.9", "1.0.10")); + System.out.println(highVersion("1.0.10", "1.0.11")); + System.out.println(highVersion("1.0.10", "1.0.9")); + + } +} diff --git a/src/main/java/cn/stock/market/utils/pushtext/IPushText.java b/src/main/java/cn/stock/market/utils/pushtext/IPushText.java new file mode 100644 index 0000000..c7e0415 --- /dev/null +++ b/src/main/java/cn/stock/market/utils/pushtext/IPushText.java @@ -0,0 +1,20 @@ +package cn.stock.market.utils.pushtext; + +import com.ag.text.DicText; + +import cn.qutaojing.common.constant.RoleEnum; +import cn.stock.market.dto.model.ClickActionInfo; + +public abstract class IPushText implements DicText { + public abstract RoleEnum role(); + public abstract Integer targetId(); + public abstract ClickActionInfo clickActionInfo(); + public abstract String event(); + public boolean pushFlag() { + return true; + } + + public boolean smsFlag() { + return true; + } +} diff --git a/src/main/java/cn/stock/market/utils/pushtext/PushTexts.java b/src/main/java/cn/stock/market/utils/pushtext/PushTexts.java new file mode 100644 index 0000000..35fc432 --- /dev/null +++ b/src/main/java/cn/stock/market/utils/pushtext/PushTexts.java @@ -0,0 +1,46 @@ +package cn.stock.market.utils.pushtext; + +import cn.qutaojing.common.constant.RoleEnum; +import cn.stock.market.constant.ClickAction; +import cn.stock.market.dto.model.ClickActionInfo; +import cn.stock.market.dto.model.UserThumb; + +public final class PushTexts { + //~=================user==================== + public static IPushText userAuditPass(UserThumb user) { + return from(RoleEnum.USER, user.getId(), "用户审核通过", "审核通知", "恭喜您,您的账号已审核通过", ClickActionInfo.of(ClickAction.LOGIN, user.getId())); + } + + public static IPushText userAuditReject(UserThumb user) { + return from(RoleEnum.USER, user.getId(),"用户审核不通过", "审核通知", "非常抱歉,您的账号审核不通过!", ClickActionInfo.of(ClickAction.LOGIN, user.getId())); + } + + public static IPushText from(RoleEnum role, Integer targetId, String event, String title, String content, ClickActionInfo info) { + return new IPushText() { + @Override + public String title() { + return title; + } + @Override + public String content() { + return content; + } + @Override + public String event() { + return event; + } + @Override + public ClickActionInfo clickActionInfo() { + return info; + } + @Override + public RoleEnum role() { + return role; + } + @Override + public Integer targetId() { + return targetId; + } + }; + } +} diff --git a/src/main/java/cn/stock/market/web/ArticleApiController.java b/src/main/java/cn/stock/market/web/ArticleApiController.java new file mode 100644 index 0000000..81a1f35 --- /dev/null +++ b/src/main/java/cn/stock/market/web/ArticleApiController.java @@ -0,0 +1,67 @@ +package cn.stock.market.web; + +import java.util.List; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import cn.qutaojing.common.PageInfo; +import cn.stock.market.domain.basic.entity.SiteArticle; +import cn.stock.market.domain.basic.service.SiteArticleService; +import cn.stock.market.utils.ServerResponse; + +@Controller +@RequestMapping({"/api/market/art/", "/api/hq/art/"}) +@Api(tags = "公告信息") +public class ArticleApiController extends BaseController { + + @Autowired + SiteArticleService siteArticleService; + + //查询企业公告信息 + @ApiOperation(value = "查询企业公告信息",httpMethod = "GET") + @RequestMapping(value = {"list.do"},method = RequestMethod.GET) + @ResponseBody + @ApiImplicitParams({ + @ApiImplicitParam(value = "公告标题", name = "artTitle", dataType = "String"), + @ApiImplicitParam(value = "公告类型", name = "artType", dataType = "String") + }) + public ServerResponse> list(@RequestParam(value = "artTitle", required = false) String artTitle, + @RequestParam(value = "artType", required = false) String artType, + @RequestParam(value = "pageNum", defaultValue = "1") int pageNum, + @RequestParam(value = "pageSize", defaultValue = "12") int pageSize) { + Page page = siteArticleService.list(artTitle, artType, pageNum, pageSize); + return ServerResponse.createBySuccess(PageInfo.with(page)); + } + + //查询指定企业公告信息 + @ApiOperation(value = "查询指定企业公告信息",httpMethod = "GET") + @RequestMapping(value = {"detail.do"},method = RequestMethod.GET) + @ResponseBody + @ApiImplicitParams({ + @ApiImplicitParam(value = "公告id", name = "artId", dataType = "Integer") + }) + public ServerResponse detail(Integer artId) { + SiteArticle article = siteArticleService.repository().find(artId); + return ServerResponse.createBySuccess(article); + } + + //top最新公告 + @ApiOperation(value = "top最新公告",httpMethod = "GET") + @RequestMapping(value = {"getTopArt.do"},method = RequestMethod.GET) + @ResponseBody + public ServerResponse> getTopArtList(@RequestParam(value = "pageSize", defaultValue = "15") int pageSize) { + List list = siteArticleService.getTopArtList(pageSize); + return ServerResponse.createBySuccess(list); + } + +} diff --git a/src/main/java/cn/stock/market/web/BaseController.java b/src/main/java/cn/stock/market/web/BaseController.java new file mode 100644 index 0000000..eb0a039 --- /dev/null +++ b/src/main/java/cn/stock/market/web/BaseController.java @@ -0,0 +1,24 @@ +package cn.stock.market.web; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.ag.exception.VisitLimitException; +import com.ag.utils.AgAssert; + +import cn.stock.market.web.openapi.model.AuthOpenApiModel; + +/** + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jun 18, 2021 11:17:43 AM + */ +public class BaseController { + protected final Logger log = LoggerFactory.getLogger(this.getClass().getSimpleName()); + + + public void checkSimpleCredentials(AuthOpenApiModel model) { + AgAssert.isTrue("simpleCredentials".equals(model.getSimpleCredentials()), VisitLimitException.class); + } +} diff --git a/src/main/java/cn/stock/market/web/InfoController.java b/src/main/java/cn/stock/market/web/InfoController.java new file mode 100644 index 0000000..e4db529 --- /dev/null +++ b/src/main/java/cn/stock/market/web/InfoController.java @@ -0,0 +1,67 @@ +package cn.stock.market.web; + +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.google.common.collect.Maps; + +import cn.qutaojing.common.web.response.SuccessView; +import cn.stock.market.utils.PropertiesUtil; +import springfox.documentation.annotations.ApiIgnore; + +/** + * + * title: InfoController.java + * description + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @version 1.0 + * @created Dec 4, 2018 10:22:44 PM + */ +@RestController +@RequestMapping("/api/hq/") +@ApiIgnore +public class InfoController { + @Value("${spring.application.name}") + String name; + @Value("${server.port}") + Integer port; + + @Value("${spring.datasource.stock-market.url}") + String stockMarketDbUrl; + + @RequestMapping(value="test.do") + public Map test(@RequestParam(required = false) String key) { + Map map = Maps.newHashMap(); + map.put("stockMarketDbUrl", stockMarketDbUrl); + if(StringUtils.isNotBlank(key)) { + map.put("key", PropertiesUtil.getProperty(key)); + } + + return map; + } + + @RequestMapping(value="info") + public Map info(@RequestParam(required = false) String key) { + Map map = Maps.newHashMap(); + map.put("name", name); + map.put("port", port); + map.put("redisIp", PropertiesUtil.getProperty("redis1.ip")); + if(StringUtils.isNotBlank(key)) { + map.put("key", PropertiesUtil.getProperty(key)); + } + return map; + } + + @RequestMapping(value="sleep") + public SuccessView sleep(@RequestParam(defaultValue = "3") Integer sleep) throws InterruptedException { + Thread.sleep(sleep * 1000); + return SuccessView.create(); + } +} diff --git a/src/main/java/cn/stock/market/web/SiteNewsController.java b/src/main/java/cn/stock/market/web/SiteNewsController.java new file mode 100644 index 0000000..5589ad6 --- /dev/null +++ b/src/main/java/cn/stock/market/web/SiteNewsController.java @@ -0,0 +1,70 @@ +package cn.stock.market.web; + +import javax.servlet.http.HttpServletRequest; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import cn.stock.market.domain.basic.service.SiteNewsService; +import cn.stock.market.utils.ServerResponse; + +@Controller +@RequestMapping({"/api/market/news/", "/api/hq/news/"}) +@Api(tags="新闻资讯") +public class SiteNewsController { + private static final Logger log = LoggerFactory.getLogger(SiteNewsController.class); + @Autowired + SiteNewsService iSiteNewsService; + + //新闻资讯-列表查询 + @RequestMapping({"getNewsList.do"}) + @ResponseBody + @ApiOperation(value = "列表查询",httpMethod = "GET") + @ApiImplicitParams({ + @ApiImplicitParam(name="type",value = "类型"), + @ApiImplicitParam(name="sort",value = "排序"), + @ApiImplicitParam(name="keyword",value = "搜索关键字"), + }) + public ServerResponse getNewsList(@RequestParam(value = "pageNum", defaultValue = "1") int pageNum, + @RequestParam(value = "pageSize", defaultValue = "15") int pageSize, + @RequestParam(value = "type", defaultValue = "0") Integer type, + @RequestParam(value = "sort", defaultValue = "time1") String sort, + @RequestParam(value = "keyword", required = false) String keyword, HttpServletRequest request) { + return this.iSiteNewsService.getList(pageNum, pageSize, type, sort, keyword, request); + } + + //新闻资讯-详情 + @RequestMapping({"getDetail.do"}) + @ResponseBody + @ApiOperation(value = "详情",httpMethod = "GET") + @ApiImplicitParam(name="id",value = "详情id") + public ServerResponse getDetail(int id) { + return this.iSiteNewsService.getDetail(id); + } + + //新闻资讯-修改新闻浏览量 + @RequestMapping({"updateViews.do"}) + @ResponseBody + @ApiOperation(value = "修改新闻浏览量",httpMethod = "GET") + @ApiImplicitParam(name="id",value = "详情id") + public ServerResponse updateViews(Integer id) { + return this.iSiteNewsService.updateViews(id); + } + + //新闻资讯-列表查询 + @RequestMapping({"getTopNews.do"}) + @ResponseBody + @ApiOperation(value = "新闻资讯-列表查询",httpMethod = "GET") + public ServerResponse getTopNewsList(@RequestParam(value = "pageSize", defaultValue = "15") int pageSize) { + return this.iSiteNewsService.getTopNewsList(pageSize); + } +} \ No newline at end of file diff --git a/src/main/java/cn/stock/market/web/StockApiController.java b/src/main/java/cn/stock/market/web/StockApiController.java new file mode 100644 index 0000000..e818963 --- /dev/null +++ b/src/main/java/cn/stock/market/web/StockApiController.java @@ -0,0 +1,602 @@ +package cn.stock.market.web; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletRequest; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.ag.utils.DateUtils; +import com.ag.utils.Jsons; +import com.alibaba.fastjson.JSONObject; +import com.google.common.base.Joiner; +import com.google.common.cache.Cache; +import com.google.common.collect.Lists; + +import cn.qutaojing.common.PageInfo; +import cn.qutaojing.common.utils.BigDecimals; +import cn.stock.market.application.CommonApis; +import cn.stock.market.domain.basic.entity.SiteArticle; +import cn.stock.market.domain.basic.entity.Stock; +import cn.stock.market.domain.basic.service.RealtimeService; +import cn.stock.market.domain.basic.service.SiteArticleService; +import cn.stock.market.domain.basic.service.StockService; +import cn.stock.market.dto.model.StockCode; +import cn.stock.market.dto.model.StockVO; +import cn.stock.market.infrastructure.api.EastmoneyApi; +import cn.stock.market.infrastructure.api.qq.QqStockApi; +import cn.stock.market.infrastructure.api.sina.SinaStockApi; +import cn.stock.market.utils.RequestCacheUtils; +import cn.stock.market.utils.ServerResponse; +import springfox.documentation.annotations.ApiIgnore; + +@Controller +@Api(value = "/StockApiController", tags = "股票行情") +@RequestMapping({"/api/market/stock/", "/api/hq/stock/"}) +public class StockApiController { + private static final Logger log = LoggerFactory.getLogger(StockApiController.class); + + @Autowired + SiteArticleService siteArticleService; + @Autowired + RealtimeService realTimeService; + + @Autowired + StockService stockService; + + @RequestMapping({"getRawSinaStock.do"}) + @ResponseBody + @ApiIgnore + public ServerResponse getRawSinaStock(String stockGid) { + return RequestCacheUtils.cache("getRawSinaStock.do", stockGid, (string) -> { + String sina = SinaStockApi.getRawSinaStock(stockGid); + return ServerResponse.createBySuccess(sina); + }); + } + + //查询 股票指数、大盘指数信息 + @RequestMapping({"getMarket.do"}) + @ApiOperation(value = "查询股票指数", httpMethod = "GET") + @ResponseBody + public ServerResponse getMarket() { + return RequestCacheUtils.cache("getMarket.do", "_UNI_", (string) -> { + return this.stockService.getMarket(); + }); + } + + //查询 热门股票 + @RequestMapping({"getHotSearch.do"}) + @ApiOperation(value = "查询热门股票", httpMethod = "GET") + @ResponseBody + public ServerResponse getHotSearch() { + return RequestCacheUtils.cache("getHotSearch.do", "_HOT_", (string) -> { + return this.stockService.getHotSearch(); + }); + } + + //查询北向净流入 + @RequestMapping({"getNorthIn.do"}) + @ApiOperation(value = "查询北向净流入", httpMethod = "GET") + @ResponseBody + public ServerResponse getNorthIn() { + return this.stockService.getNorthIn(); + } + + // 查询主力净流入 + @RequestMapping({"getMainIn.do"}) + @ApiOperation(value = "查询主力净流入", httpMethod = "GET") + @ResponseBody + public ServerResponse getMainIn() { + return this.stockService.getMainIn(); + } + + //查询 新股上市信息 + @RequestMapping({"getNewStock.do"}) + @ApiOperation(value = "查询新股", httpMethod = "GET") + @ResponseBody + public ServerResponse getNewStock() { + return this.stockService.getNewStock(); + } + + //根据股票id查询 股票指数、大盘指数信息 + @RequestMapping({"getMarketByStockGid.do"}) + @ApiOperation(value = "根据股票id查询 股票指数、大盘指数信息", httpMethod = "GET") + @ResponseBody + public ServerResponse getMarketByStockGid(@RequestParam("stockGid") String stockGid) { + return RequestCacheUtils.cache("getMarketByStockGid.do", stockGid, (string) -> { + return this.stockService.getMarketByStockGid(stockGid); + }); + } + + //查询官网PC端交易 所有股票信息及指定股票信息 +// @RequestMapping({"getStock.do"}) +// @ResponseBody +// public ServerResponse getStock(@RequestParam(value = "pageNum", defaultValue = "1") int pageNum, @RequestParam(value = "pageSize", defaultValue = "10") int pageSize, @RequestParam(value = "stockPlate", required = false) String stockPlate, @RequestParam(value = "stockType", required = false) String stockType, @RequestParam(value = "keyWords", required = false) String keyWords, HttpServletRequest request) { +// return this.stockService.getStock(pageNum, pageSize, keyWords, stockPlate, stockType, request); +// } + + //通过股票代码查询股票信息 + @RequestMapping({"getSingleStock.do"}) + @ApiOperation(value = "通过股票代码查询股票信息", httpMethod = "GET") + @ResponseBody + @ApiImplicitParams({ + @ApiImplicitParam(name = "code",value = "股票对应代码(symbol)",dataType ="String",required = true), + }) + public ServerResponse getSingleStock(@RequestParam("code") String code) { + return RequestCacheUtils.cache("getSingleStock.do", code, (string) -> { + return this.stockService.getSingleStock(code); + }); + } + + @RequestMapping({"getMinK.do"}) + @ApiOperation(value = "查询股票分线", httpMethod = "GET") + @ResponseBody + @ApiImplicitParams({ + @ApiImplicitParam(name = "code",value = "股票对应代码(symbol)",dataType ="String",required = true), + @ApiImplicitParam(name = "time",value = "时间间隔",dataType ="Integer",required = true), + }) + public ServerResponse getMinK(@RequestParam("code") String code, @RequestParam("time") Integer time, @RequestParam("ma") Integer ma, @RequestParam("size") Integer size) { + String key = Joiner.on("_").skipNulls().join(code, time, ma, size); + return RequestCacheUtils.cache("getMinK.do", key, (string) -> { + return this.stockService.getMinK(code, time, ma, size); + }); + + } + + @RequestMapping({"getKLine.do"}) + @ApiOperation(value = "查询股票K线", httpMethod = "GET") + @ResponseBody + @ApiImplicitParams({ + @ApiImplicitParam(name = "code",value = "股票对应代码(symbol)",dataType ="String",required = true), + }) + public ServerResponse getKLine(@RequestParam("code") String code) { + return RequestCacheUtils.cache("getKLine.do", code, (string) -> { + return this.stockService.getKLine(code); + }); + } + + /*查询股票日线*/ + @RequestMapping({"getDayK.do"}) + @ApiOperation(value = "查询股票日线", httpMethod = "GET") + @ResponseBody + @ApiImplicitParams({ + @ApiImplicitParam(name = "code",value = "股票对应代码(symbol)",dataType ="String",required = true), + }) + public ServerResponse getDayK(@RequestParam("code") String code) { + return RequestCacheUtils.cache("getDayK.do", code, (string) -> { + return this.stockService.getDayK_Echarts(code); + }); + } + + /*查询股票周线*/ + @RequestMapping({"getWeekK.do"}) + @ApiOperation(value = "查询股票周线", httpMethod = "GET") + @ResponseBody + @ApiImplicitParams({ + @ApiImplicitParam(name = "code",value = "股票对应代码(symbol)",dataType ="String",required = true), + }) + public ServerResponse getWeekK(@RequestParam("code") String code) { + return RequestCacheUtils.cache("getWeekK.do", code, (string) -> { + return this.stockService.getWeekK_Echarts(code); + }); + } + + /*查询股票月线*/ + @RequestMapping({"getMonthK.do"}) + @ApiOperation(value = "查询股票月线", httpMethod = "GET") + @ResponseBody + @ApiImplicitParams({ + @ApiImplicitParam(name = "code",value = "股票对应代码(symbol)",dataType ="String",required = true), + }) + public ServerResponse getMonthK(@RequestParam("code") String code) { + return RequestCacheUtils.cache("getMonthK.do", code, (string) -> { + return this.stockService.getMonthK_Echarts(code); + }); + } + + //查询股票历史数据数据 + @RequestMapping({"getMinK_Echarts.do"}) + @ApiOperation(value = "查询股票历史数据数据", httpMethod = "GET") + @ResponseBody + @ApiImplicitParams({ + @ApiImplicitParam(name = "code",value = "股票对应代码(symbol)",dataType ="String",required = true), + }) + public ServerResponse getMinK_Echarts(@RequestParam("code") String code, @RequestParam("time") Integer time, @RequestParam("size") Integer size) { + String key = Joiner.on("_").skipNulls().join(code, time, size); + return RequestCacheUtils.cache("getMinK_Echarts.do", key, (string) -> { + return this.stockService.getMinK_Echarts(code, time, 15, size); + }); + } + +// /*期货分时-k线*/ +// @RequestMapping({"getFuturesMinK_Echarts.do"}) +// @ResponseBody +// public ServerResponse getFuturesMinK_Echarts(@RequestParam("code") String code, @RequestParam("time") Integer time, @RequestParam("size") Integer size) { +// return this.iStockService.getFuturesMinK_Echarts(code, time, size); +// } + + /*指数分时-k线*/ + @RequestMapping({"getIndexMinK_Echarts.do"}) + @ApiOperation(value = "查询指数分时-k线", httpMethod = "GET") + @ResponseBody + @ApiImplicitParams({ + @ApiImplicitParam(name = "code",value = "股票对应代码(symbol)",dataType ="String",required = true), + @ApiImplicitParam(name = "time",value = "时间间隔",dataType ="String",required = true), + }) + public ServerResponse getIndexMinK_Echarts(@RequestParam("code") String code, @RequestParam("time") Integer time, @RequestParam("size") Integer size) { + String key = Joiner.on("_").skipNulls().join(code, time, size); + return RequestCacheUtils.cache("getIndexMinK_Echarts.do", key, (string) -> { + return this.stockService.getIndexMinK_Echarts(code, time, size); + }); + } + +// /*查询期货日线*/ +// @RequestMapping({"getFuturesDayK.do"}) +// @ResponseBody +// public ServerResponse getFuturesDayK(@RequestParam("code") String code) { +// return this.iStockService.getFuturesDayK(code); +// } + + /*指数日线*/ + @RequestMapping({"getIndexDayK.do"}) + @ApiOperation(value = "查询指数日线", httpMethod = "GET") + @ResponseBody + @ApiImplicitParams({ + @ApiImplicitParam(name = "code",value = "股票对应代码(symbol)",dataType ="String",required = true), + }) + public ServerResponse getIndexDayK(@RequestParam("code") String code) { + return RequestCacheUtils.cache("getIndexDayK.do", code, (string) -> { + return this.stockService.getIndexDayK(code); + }); + } + + + + /*指数日线*/ + @RequestMapping({"getIndexWeekK.do"}) + @ApiOperation(value = "查询指数周线", httpMethod = "GET") + @ResponseBody + @ApiImplicitParams({ + @ApiImplicitParam(name = "code",value = "股票对应代码(symbol)",dataType ="String",required = true), + }) + public ServerResponse getIndexWeekK(@RequestParam("code") String code) { + return RequestCacheUtils.cache("getIndexWeekK.do", code, (string) -> { + return this.stockService.getIndexWeekK(code); + }); + } + + /*指数日线*/ + @RequestMapping({"getIndexMonthK.do"}) + @ApiOperation(value = "查询指数月线", httpMethod = "GET") + @ResponseBody + @ApiImplicitParams({ + @ApiImplicitParam(name = "code",value = "股票对应代码(symbol)",dataType ="String",required = true), + }) + public ServerResponse getIndexMonthK(@RequestParam("code") String code) { + return RequestCacheUtils.cache("getIndexMonthK.do", code, (string) -> { + return this.stockService.getIndexMonthK(code); + }); + } + + /*跌幅榜单*/ + @RequestMapping({"getChangePercentDrop.do"}) + @ApiOperation(value = "查询跌幅榜单", httpMethod = "GET") + @ResponseBody + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum",value = "分页页数",dataType ="int",required = true), + @ApiImplicitParam(name = "pageSize",value = "每页数量",dataType ="int",required = true), + }) + public ServerResponse> getChangePercentDrop(@RequestParam(defaultValue = "1") int pageNum, @RequestParam(defaultValue = "10") int pageSize) { + String key = Joiner.on("_").skipNulls().join(pageNum, pageSize); + + return RequestCacheUtils.cache("getChangePercentDrop.do", key, (string) -> { + List list = SinaStockApi.getHQNodeData(1, pageNum, pageSize); + Map stockMap = this.stockService.repository().cacheCodeMap(); + return ServerResponse.createBySuccess(list + .stream() + .filter(val -> { + String code = val.getString("code"); + return stockMap.containsKey(code); + }) + .collect(Collectors.toList())); + }); + + } + + /*涨幅榜单*/ + @RequestMapping({"getChangePercentRise.do"}) + @ApiOperation(value = "查询涨幅榜单", httpMethod = "GET") + @ResponseBody + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum",value = "分页页数",dataType ="int",required = true), + @ApiImplicitParam(name = "pageSize",value = "每页数量",dataType ="int",required = true), + }) + public ServerResponse> getChangePercentRise(@RequestParam(defaultValue = "1") int pageNum, @RequestParam(defaultValue = "10") int pageSize) { + String key = Joiner.on("_").skipNulls().join(pageNum, pageSize); + + return RequestCacheUtils.cache("getChangePercentRise.do", key, (string) -> { + List list = SinaStockApi.getHQNodeData(0, pageNum, pageSize); + Map stockMap = this.stockService.repository().cacheCodeMap(); + return ServerResponse.createBySuccess(list + .stream() + .filter(val -> { + String code = val.getString("code"); + return stockMap.containsKey(code); + }) + .collect(Collectors.toList())); + }); + } + + /*新股日历*/ + @RequestMapping({"getIpoApplyDate.do"}) + @ApiOperation(value = "查询新股日历", httpMethod = "GET") + @ResponseBody + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum",value = "分页页数",dataType ="int",required = true), + @ApiImplicitParam(name = "pageSize",value = "每页数量",dataType ="int",required = true), + }) + public ServerResponse getIpoApplyDate(@RequestParam(defaultValue = "1") int pageNum, @RequestParam(defaultValue = "10") int pageSize) { + String key = Joiner.on("_").skipNulls().join(pageNum, pageSize); + + return RequestCacheUtils.cache("getIpoApplyDate.do", key, (string) -> { + PageInfo pageInfo = EastmoneyApi.ipoApplyDate(pageNum, pageSize); + return ServerResponse.createBySuccess(pageInfo); + }); + + } + + /*新股日历_今日申购_即将发布*/ + @RequestMapping({"getIpoApplyDateAndClassify.do"}) + @ApiOperation(value = "查询新股日历_今日申购_即将发布", httpMethod = "GET") + @ResponseBody + public ServerResponse getIpoApplyDateAndClassify() { + String key = "_UNI_"; + + return RequestCacheUtils.cache("getIpoApplyDateAndClassify.do", key, (string) -> { + PageInfo pageInfo = EastmoneyApi.ipoApplyDate(1, 50); + String nowDate = DateUtils.nowDate(DateUtils.YYYY_MM_DD); + + List todayList = pageInfo.getItems() + .stream() + .filter(val -> { + return StringUtils.startsWith(val.getString("APPLY_DATE"), nowDate); + }) + .collect(Collectors.toList()); + + List futureList = pageInfo.getItems() + .stream() + .filter(val -> { + return ! StringUtils.startsWith(val.getString("APPLY_DATE"), nowDate); + }) + .sorted(Comparator.comparing(val -> val.getString("APPLY_DATE"))) + .collect(Collectors.toList()); + + JSONObject json = new JSONObject(); + json.put("todayList", todayList); + json.put("futureList", futureList); + return ServerResponse.createBySuccess(json); + }); + + } + + /*沪深300*/ + @RequestMapping({"a300List.do"}) + @ApiOperation(value = "查询沪深300", httpMethod = "GET") + @ResponseBody + public ServerResponse a300List() { + String key = "_UNI_"; + + return RequestCacheUtils.cache("a300List.do", key, (string) -> { + Map stockMap = this.stockService.repository().cacheCodeMap(); + List list = EastmoneyApi.a300List(); + Map stockDetailMap = CommonApis.of().stockDetailMap(Lists.transform(list, val -> StockCode.a(val.getString("f12")))); + List retList = EastmoneyApi.a300List().stream() + .map(val -> { + String code = val.getString("f12"); + Stock stock = stockMap.get(code); + if(stock == null) { + log.warn("stock无code:{} 数据.", code); + return null; + } + + return stockDetailMap.get(code); + }) + .filter(val -> val != null) + .collect(Collectors.toList()); + return ServerResponse.createBySuccess(retList); + }); + } + + /*沪深指数*/ + @RequestMapping({"aIndexList.do"}) + @ApiOperation(value = "查询沪深指数", httpMethod = "GET") + @ResponseBody + public ServerResponse aIndexList() { + String key = "_UNI_"; + + return RequestCacheUtils.cache("aIndexList.do", key, (string) -> { + List list = EastmoneyApi.aIndexList(); +// Map stockDetailMap = CommonApis.of().stockDetailMap(Lists.transform(list, val -> StockCode.a(val.getString("f12")))); + + List retList = list.stream() + .map(val -> { + String code = val.getString("f12"); +// Stock stock = stockMap.get(code); +// if(stock == null) { +// log.warn("stock无code:{} 数据.", code); +// return null; +// } + + JSONObject json = new JSONObject(); + json.put("name", val.getString("f14")); + json.put("code", code); + json.put("gid", code); + json.put("hcrate", val.get("f3")); + json.put("nowPrice", val.get("f2")); + + return json; +// return stockDetailMap.get(code); + }) + .filter(val -> val != null) + .collect(Collectors.toList()); + return ServerResponse.createBySuccess(retList); + }); + + } + + /*热门股票*/ + @RequestMapping({"gethotgubalist.do"}) + @ApiOperation(value = "查询热门股票", httpMethod = "GET") + @ResponseBody + public ServerResponse gethotgubalist() { + String key = "_UNI_"; + + return RequestCacheUtils.cache("gethotgubalist.do", key, (string) -> { + Map stockMap = this.stockService.repository().cacheCodeMap(); + List list = EastmoneyApi.gethotgubalist(); + Map stockDetailMap = CommonApis.of().stockDetailMap(Lists.transform(list, val -> StockCode.a(val.getString("guba_code")))); + + List retList = list + .stream() + .map(val -> { + String code = val.getString("guba_code"); + Stock stock = stockMap.get(code); + if(stock == null) { + return null; + } + StockVO stockVO = stockDetailMap.get(code); + if(stockVO == null) { + return null; + } + val.put("hcrate", stockVO.getHcrate()); + val.put("hcPrice", BigDecimals.multiplys(stockVO.getNowPrice(), stockVO.getHcrate())); + val.put("nowPrice",stockVO.getNowPrice()); + return val; + }) + .filter(val -> val != null) + .collect(Collectors.toList()); + + return ServerResponse.createBySuccess(retList); + }); + } + + /*上涨下跌家数统计*/ + @RequestMapping({"bkqtRank.do"}) + @ApiOperation(value = "上涨下跌家数统计", httpMethod = "GET") + @ResponseBody + public ServerResponse bkqtRank() { + String key = "_UNI_"; + + return RequestCacheUtils.cache("bkqtRank.do", key, (string) -> { + JSONObject json = QqStockApi.bkqtRank(); + return ServerResponse.createBySuccess(json); + }); + } + + /*新股日历_最新公告*/ + @RequestMapping({"getIpoApplyDateAndTopArt.do"}) + @ApiOperation(value = "新股日历_最新公告", httpMethod = "GET") + @ResponseBody + public ServerResponse getIpoApplyDateAndTopArt() { + String key = "_UNI_"; + + return RequestCacheUtils.cache("getIpoApplyDateAndTopArt.do", key, (string) -> { + PageInfo pageInfo = EastmoneyApi.ipoApplyDate(1, 50); + String nowDate = DateUtils.nowDate(DateUtils.YYYY_MM_DD); + List todayList = pageInfo.getItems() + .stream() + .filter(val -> { + return StringUtils.startsWith(val.getString("APPLY_DATE"), nowDate); + }) + .limit(2) + .collect(Collectors.toList()); + + JSONObject json = new JSONObject(); + json.put("ipoApplyDateList", todayList); + + List topArtList = siteArticleService.getTopArtList(20); + final Map stockNameMap = this.stockService.repository().cacheNameMap(); + + List codeList = Lists.transform(topArtList, val -> { + Stock s = stockNameMap.get(val.getAuthor()); + if(s == null) { + return null; + } + + return StockCode.a(s.getStockCode()); + }); + + Map stockDetailMap = CommonApis.of().stockDetailMap(codeList); + final List stockNameList = new ArrayList<>(); + com.github.pagehelper.PageInfo artListPageInfo = new com.github.pagehelper.PageInfo<>(topArtList); + List list = artListPageInfo.getList().stream() + .filter(val -> stockNameMap.containsKey(((SiteArticle) val).getAuthor()) && !stockNameList.contains(((SiteArticle) val).getAuthor())) + .limit(2) + .map(val -> { + String name = ((SiteArticle) val).getAuthor(); + Stock stockByCode = stockNameMap.get(name); + stockNameList.add(name); + JSONObject j = Jsons.toJSON(val); + if (stockByCode != null) { + StockVO stockVO = stockDetailMap.get(stockByCode.getStockCode()); + if(stockVO != null) { + j.put("hcrate", stockVO.getHcrate()); + j.put("nowPrice", stockVO.getNowPrice()); + } + } + + return j; + }) + .collect(Collectors.toList()); + artListPageInfo.setList(list); + + json.put("artList", artListPageInfo); + + return ServerResponse.createBySuccess(json); + }); + } + + /** + * 分时线 + * 描述 + * @param stockCode + * @return + */ + @RequestMapping({"/realTime/findStock.do"}) + @ApiOperation(value = "分时线", httpMethod = "GET") + @ResponseBody + @ApiImplicitParams({ + @ApiImplicitParam(name = "stockCode",value = "股票对应代码(symbol)",dataType ="String",required = true), + }) + public ServerResponse findStock(@RequestParam(value = "stockCode", required = false) String stockCode) { + return RequestCacheUtils.cache("/realTime/findStock.do", stockCode, (string) -> { + Map findStock = this.realTimeService.findStock(stockCode); + return ServerResponse.createBySuccess(findStock); + }); + } + + @ApiOperation(value = "新股待上市接口",httpMethod = "GET", response = ServerResponse.class) + @RequestMapping({"getNewStockList.do"}) + @ResponseBody + public + ServerResponse getNewStockList() { + + return this.stockService.getNewStockList(); + } +} \ No newline at end of file diff --git a/src/main/java/cn/stock/market/web/TTLHolder.java b/src/main/java/cn/stock/market/web/TTLHolder.java new file mode 100644 index 0000000..a104f43 --- /dev/null +++ b/src/main/java/cn/stock/market/web/TTLHolder.java @@ -0,0 +1,13 @@ +package cn.stock.market.web; + +/** + * ThreadLocal 多线程会造成内存泄漏 请使用 + * https://github.com/alibaba/transmittable-thread-local + * + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jun 3, 2021 4:23:35 PM + */ +public class TTLHolder { +} diff --git a/src/main/java/cn/stock/market/web/ToolController.java b/src/main/java/cn/stock/market/web/ToolController.java new file mode 100644 index 0000000..59f7490 --- /dev/null +++ b/src/main/java/cn/stock/market/web/ToolController.java @@ -0,0 +1,56 @@ +package cn.stock.market.web; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import cn.qutaojing.common.utils.SpringUtils; +import cn.stock.market.infrastructure.job.RealTimeTask; +import cn.stock.market.infrastructure.job.StockTask; +import cn.stock.market.utils.RequestCacheUtils; +import cn.stock.market.utils.ServerResponse; +import springfox.documentation.annotations.ApiIgnore; + +@Controller +@RequestMapping({"/api/hq/tool/", "/api/market/tool/"}) +@ApiIgnore +public class ToolController { + + @RequestMapping({"/syncAStockList.do"}) + @ResponseBody + public ServerResponse syncAStockList() { + StockTask stockTask = SpringUtils.getBean(StockTask.class); + stockTask.syncAStockList(); + return ServerResponse.createBySuccess("已经执行"); + } + + @RequestMapping({"/syncBjsStockList.do"}) + @ResponseBody + public ServerResponse syncBjsStockList() { + StockTask stockTask = SpringUtils.getBean(StockTask.class); + stockTask.syncBjsStockList(); + return ServerResponse.createBySuccess("已经执行"); + } + + @RequestMapping({"/syncAFutureStockList.do"}) + @ResponseBody + public ServerResponse syncAFutureStockList() { + StockTask stockTask = SpringUtils.getBean(StockTask.class); + stockTask.syncAFutureStockList(); + return ServerResponse.createBySuccess("已经执行"); + } + + @RequestMapping({"/cache/stat.do"}) + @ResponseBody + public ServerResponse cache_stat() { + return ServerResponse.createBySuccess(RequestCacheUtils.stat()); + } + + @RequestMapping({"/deleteStockCode.do"}) + @ResponseBody + public ServerResponse deleteStockCode() { + RealTimeTask task = SpringUtils.getBean(RealTimeTask.class); + task.deleteStockCode(); + return ServerResponse.createBySuccess("已经执行"); + } +} \ No newline at end of file diff --git a/src/main/java/cn/stock/market/web/config/Config.java b/src/main/java/cn/stock/market/web/config/Config.java new file mode 100644 index 0000000..7349203 --- /dev/null +++ b/src/main/java/cn/stock/market/web/config/Config.java @@ -0,0 +1,42 @@ +/* + * + * * Copyright (C) 2018 Wanghaobin<463540703@qq.com> + * + * * AG-Enterprise 企业版源码 + * * 郑重声明: + * * 如果你从其他途径获取到,请告知老A传播人,奖励1000。 + * * 老A将追究授予人和传播人的法律责任! + * + * * This program is free software; you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation; either version 2 of the License, or + * * (at your option) any later version. + * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * + * * You should have received a copy of the GNU General Public License along + * * with this program; if not, write to the Free Software Foundation, Inc., + * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +package cn.stock.market.web.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import lombok.Data; + +@Data +@Configuration +@ConfigurationProperties() +public class Config { + String ig507Licence; + String gugudataAppKey; + String aliyunAccessKeyId; + String aliyunAccessKeySecret; + String aliyunAppCode; +} diff --git a/src/main/java/cn/stock/market/web/config/ControlSchedulingConfiguration.java b/src/main/java/cn/stock/market/web/config/ControlSchedulingConfiguration.java new file mode 100644 index 0000000..bb1bb33 --- /dev/null +++ b/src/main/java/cn/stock/market/web/config/ControlSchedulingConfiguration.java @@ -0,0 +1,12 @@ +package cn.stock.market.web.config; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; + +@Configuration +@EnableScheduling +@ConditionalOnProperty(prefix = "enable", name = "scheduled", havingValue = "true") +public class ControlSchedulingConfiguration { + +} diff --git a/src/main/java/cn/stock/market/web/config/Env.java b/src/main/java/cn/stock/market/web/config/Env.java new file mode 100644 index 0000000..610e967 --- /dev/null +++ b/src/main/java/cn/stock/market/web/config/Env.java @@ -0,0 +1,53 @@ +package cn.stock.market.web.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.context.annotation.PropertySources; +import org.springframework.core.env.Environment; + +import cn.qutaojing.common.utils.SpringUtils; + +/** + * 环境变量 + * + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jun 2, 2020 10:00:59 AM + */ +@Configuration +@PropertySources({ + @PropertySource("classpath:stock2guo.properties"), +}) +public class Env { + @Autowired + Environment environment; + + static Env env; + + public static Env of() { + if (env == null) { + env = SpringUtils.getBean(Env.class); + } + + return env; + } + + public String domain() { + return environment.getProperty("domain"); + } + + public String springProfilesActive() { + return environment.getProperty("spring.profiles.active"); + } + + public boolean isProd() { + return "prod".equals(springProfilesActive()); + } + + public Environment environment() { + return environment; + } +} \ No newline at end of file diff --git a/src/main/java/cn/stock/market/web/config/RestTemplateConfig.java b/src/main/java/cn/stock/market/web/config/RestTemplateConfig.java new file mode 100644 index 0000000..66f4bef --- /dev/null +++ b/src/main/java/cn/stock/market/web/config/RestTemplateConfig.java @@ -0,0 +1,23 @@ +package cn.stock.market.web.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class RestTemplateConfig { + @Bean + public RestTemplate restTemplate(ClientHttpRequestFactory factory) { + return new RestTemplate(factory); + } + + @Bean + public ClientHttpRequestFactory simpleClientHttpRequestFactory() { + SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); + factory.setReadTimeout(5000);// ms + factory.setConnectTimeout(15000);// ms + return factory; + } +} diff --git a/src/main/java/cn/stock/market/web/config/Swagger2Config.java b/src/main/java/cn/stock/market/web/config/Swagger2Config.java new file mode 100644 index 0000000..5766e7b --- /dev/null +++ b/src/main/java/cn/stock/market/web/config/Swagger2Config.java @@ -0,0 +1,135 @@ +package cn.stock.market.web.config; + +import static com.google.common.base.Predicates.not; +import static com.google.common.collect.Lists.newArrayList; + +import java.util.List; +import java.util.Set; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; + +import com.ag.utils.AnnotationUtils; +import com.fasterxml.classmate.TypeResolver; +import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI; +import com.github.xiaoymin.swaggerbootstrapui.model.SpringAddtionalModel; + +import cn.stock.market.web.interceptor.AppInterceptor; +import io.swagger.annotations.ApiModel; +import springfox.documentation.annotations.ApiIgnore; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiKey; +import springfox.documentation.service.AuthorizationScope; +import springfox.documentation.service.SecurityReference; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spi.service.contexts.SecurityContext; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** + * + * title: Swagger2Config.java + * Swagger2 的Api注解的配置 + * + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jan 26, 2018 3:55:02 PM + */ +@Configuration +@EnableSwagger2 +@EnableSwaggerBootstrapUI +@ConditionalOnProperty(name = "enabled", prefix = "swagger", havingValue = "true", matchIfMissing = true) +public class Swagger2Config { + @Autowired + private TypeResolver typeResolver; + + SpringAddtionalModel springAddtionalModel = null; + public synchronized SpringAddtionalModel springAddtionalModel() { + if(springAddtionalModel == null) { + SpringAddtionalModel springAddtionalModel = new SpringAddtionalModel(); + Set> classSets = AnnotationUtils.getClazzFromAnnotation("cn.stock.trade.dto", ApiModel.class); + Set> classSetModels = AnnotationUtils.getClazzFromAnnotation("cn.stock.trade.model", ApiModel.class); + + classSets.addAll(classSetModels); + int a = 0; + for (Class clazz : classSets) { + if (a == 0) { + springAddtionalModel.setFirst(typeResolver.resolve(clazz)); + } else { + springAddtionalModel.add(typeResolver.resolve(clazz)); + } + + a++; + } + + this.springAddtionalModel = springAddtionalModel; + } + + return springAddtionalModel; + } + + @Bean + @Order(value = 4) + public Docket createAppApi() { +// Parameter headerTokenParameter = new ParameterBuilder().name(AppInterceptor.TOKEN_KEY) +// .description("appToken") +// .modelRef(new ModelRef("string")).parameterType("query") +// .required(false) +// .defaultValue("") +// .build(); + + SpringAddtionalModel springAddtionalModel = springAddtionalModel(); + + Docket docket = new Docket(DocumentationType.SWAGGER_2).apiInfo(commonApiInfoBuilder().title("鑫宝 - App Api RESTful APIs").build()) + .groupName("前端 -app -api") + .select() + .apis(not(RequestHandlerSelectors.withClassAnnotation(ApiIgnore.class))) + .paths(PathSelectors.ant("/api/app/**")) + .build() + .additionalModels(springAddtionalModel.getFirst(), springAddtionalModel.getRemaining()) + .ignoredParameterTypes(ApiIgnore.class) + +// .securitySchemes(newArrayList(apiKey(AppInterceptor.TOKEN_KEY))) +// .securityContexts(newArrayList(SecurityContext.builder().securityReferences(defaultAuth(AppInterceptor.TOKEN_KEY)).forPaths(PathSelectors.regex("/anyPath.*")).build())) +// .globalOperationParameters(newArrayList( +// headerTokenParameter +// )) + ; + return docket; + } + + @Bean + @Order(value = 5) + public Docket createCommonApi() { + return new Docket(DocumentationType.SWAGGER_2) + .groupName("后端 -api") + .select() + .apis(RequestHandlerSelectors.basePackage("cn.stock.market.web")) + .paths(PathSelectors.any()) + .build(); + } + + private ApiKey apiKey(String key) { + return new ApiKey(key, key, "header"); + } + + List defaultAuth(String key) { + AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); + AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; + authorizationScopes[0] = authorizationScope; + return newArrayList(new SecurityReference(key, authorizationScopes)); + } + + public ApiInfoBuilder commonApiInfoBuilder() { + return new ApiInfoBuilder() + .description("鑫宝 接口文档") + .termsOfServiceUrl("http://www.xxxx.cn/") + .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0").version("v1.0"); + } +} diff --git a/src/main/java/cn/stock/market/web/config/WebAppConfigurer.java b/src/main/java/cn/stock/market/web/config/WebAppConfigurer.java new file mode 100644 index 0000000..9cb90a8 --- /dev/null +++ b/src/main/java/cn/stock/market/web/config/WebAppConfigurer.java @@ -0,0 +1,57 @@ +package cn.stock.market.web.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpStatus; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; + +import cn.qutaojing.common.config.WebAppBaseConfigurer; +import cn.qutaojing.common.web.HttpTraceLogFilter; +import cn.stock.market.utils.ExceptionHandler; +import cn.stock.market.web.interceptor.AppInterceptor; +import cn.stock.market.web.interceptor.GlobalInterceptor; + +/** + * title: WebAppConfigurer.java + * + * @author xlfd + * @version 1.0 + * @email xlfd@gmail.com + * @created Jan 26, 2018 3:56:53 PM + */ +@Configuration +public class WebAppConfigurer extends WebAppBaseConfigurer { + @Autowired AppInterceptor appInterceptor; + @Autowired GlobalInterceptor globalInterceptor; + + protected String[] swaggerPath = new String[] { + "/error**", + "/v2/api-docs**", + "/swagger-resources**", + "/swagger-resources/**", "/configuration/**" + }; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + super.addInterceptors(registry); + registry.addInterceptor(globalInterceptor) + .addPathPatterns("/api/**") + .excludePathPatterns(swaggerPath); + + registry.addInterceptor(appInterceptor) + .addPathPatterns("/api/**") + .excludePathPatterns(swaggerPath); + + } + + @Bean + public HttpTraceLogFilter httpTraceLogFilter() { + return new HttpTraceLogFilter(); + } + + @Bean + public ExceptionHandler exceptionHandler() { + return new ExceptionHandler(HttpStatus.OK); + } +} diff --git a/src/main/java/cn/stock/market/web/config/swagger2/CustomizeModelAttributeParameterExpander.java b/src/main/java/cn/stock/market/web/config/swagger2/CustomizeModelAttributeParameterExpander.java new file mode 100644 index 0000000..0126575 --- /dev/null +++ b/src/main/java/cn/stock/market/web/config/swagger2/CustomizeModelAttributeParameterExpander.java @@ -0,0 +1,289 @@ +package cn.stock.market.web.config.swagger2; + +import static com.google.common.base.Objects.equal; +import static com.google.common.base.Predicates.and; +import static com.google.common.base.Predicates.not; +import static com.google.common.base.Predicates.or; +import static com.google.common.base.Strings.isNullOrEmpty; +import static com.google.common.collect.FluentIterable.from; +import static com.google.common.collect.Lists.newArrayList; +import static com.google.common.collect.Sets.newHashSet; +import static springfox.documentation.schema.Collections.collectionElementType; +import static springfox.documentation.schema.Collections.isContainerType; +import static springfox.documentation.schema.Types.typeNameFor; + +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Component; + +import com.fasterxml.classmate.ResolvedType; +import com.fasterxml.classmate.members.ResolvedField; +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.collect.FluentIterable; + +import io.swagger.annotations.ApiModelProperty; +import springfox.documentation.builders.ParameterBuilder; +import springfox.documentation.schema.Maps; +import springfox.documentation.schema.Types; +import springfox.documentation.schema.property.field.FieldProvider; +import springfox.documentation.service.Parameter; +import springfox.documentation.spi.schema.AlternateTypeProvider; +import springfox.documentation.spi.service.contexts.DocumentationContext; +import springfox.documentation.spi.service.contexts.ParameterExpansionContext; +import springfox.documentation.spring.web.plugins.DocumentationPluginsManager; +import springfox.documentation.spring.web.readers.parameter.ExpansionContext; +import springfox.documentation.spring.web.readers.parameter.ModelAttributeField; +import springfox.documentation.spring.web.readers.parameter.ModelAttributeParameterExpander; + +/** + * + * title: ModelAttributeParameterExpander.java + * springboot整合Swagger,解决忽略属性不生效 + * + * @author rplees + * @email rplees.i.ly@gmail.com + * @version 1.0 + * @created Dec 9, 2022 11:21:13 AM + */ +@Component +@Primary +public class CustomizeModelAttributeParameterExpander extends ModelAttributeParameterExpander { + private static final Logger LOG = LoggerFactory.getLogger(CustomizeModelAttributeParameterExpander.class); + private final FieldProvider fieldProvider; + + @Autowired + protected DocumentationPluginsManager pluginsManager; + + @Autowired + public CustomizeModelAttributeParameterExpander(FieldProvider fields) { + super(fields); + this.fieldProvider = fields; + } + + public List expand(ExpansionContext context) { + + List parameters = newArrayList(); + Set beanPropNames = getBeanPropertyNames(context.getParamType().getErasedType()); + Iterable fields = FluentIterable.from(fieldProvider.in(context.getParamType())) + .filter(onlyBeanProperties(beanPropNames)); + LOG.debug("Expanding parameter type: {}", context.getParamType()); + AlternateTypeProvider alternateTypeProvider = context.getDocumentationContext().getAlternateTypeProvider(); + + FluentIterable modelAttributes = from(fields) + .transform(toModelAttributeField(alternateTypeProvider)); + + FluentIterable expendables = modelAttributes.filter(not(simpleType())) + .filter(not(recursiveType(context))); + for (ModelAttributeField each : expendables) { + LOG.debug("Attempting to expand expandable field: {}", each.getField()); + parameters.addAll(expand(context.childContext(nestedParentName(context.getParentName(), each.getField()), + each.getFieldType(), context.getDocumentationContext()))); + } + + FluentIterable collectionTypes = modelAttributes + .filter(and(isCollection(), not(recursiveCollectionItemType(context.getParamType())))); + for (ModelAttributeField each : collectionTypes) { + LOG.debug("Attempting to expand collection/array field: {}", each.getField()); + + ResolvedType itemType = collectionElementType(each.getFieldType()); + if (Types.isBaseType(itemType) || itemType.getErasedType().isEnum()) { + parameters.add(simpleFields(context.getParentName(), context.getDocumentationContext(), each)); + } else { + parameters + .addAll(expand(context.childContext(nestedParentName(context.getParentName(), each.getField()), + itemType, context.getDocumentationContext()))); + } + } + + FluentIterable simpleFields = modelAttributes.filter(simpleType()); + for (ModelAttributeField each : simpleFields) { + parameters.add(simpleFields(context.getParentName(), context.getDocumentationContext(), each)); + } + return FluentIterable.from(parameters).filter(not(hiddenParameters())).toList(); + } + + private Predicate recursiveCollectionItemType(final ResolvedType paramType) { + return new Predicate() { + @Override + public boolean apply(ModelAttributeField input) { + return equal(collectionElementType(input.getFieldType()), paramType); + } + }; + } + + private Predicate hiddenParameters() { + return new Predicate() { + @Override + public boolean apply(Parameter input) { + return input.isHidden(); + } + }; + } + + private Parameter simpleFields(String parentName, DocumentationContext documentationContext, + ModelAttributeField each) { + LOG.debug("Attempting to expand field: {}", each); + String dataTypeName = Optional.fromNullable(typeNameFor(each.getFieldType().getErasedType())) + .or(each.getFieldType().getErasedType().getSimpleName()); + LOG.debug("Building parameter for field: {}, with type: ", each, each.getFieldType()); + ParameterExpansionContext parameterExpansionContext = new ParameterExpansionContext(dataTypeName, parentName, + each.getField(), documentationContext.getDocumentationType(), new ParameterBuilder()); + return pluginsManager.expandParameter(parameterExpansionContext); + } + + private Predicate recursiveType(final ExpansionContext context) { + return new Predicate() { + @Override + public boolean apply(ModelAttributeField input) { + return context.hasSeenType(input.getFieldType()); + } + }; + } + + private Predicate simpleType() { + return and(not(isCollection()), not(isMap()), or(belongsToJavaPackage(), isBaseType(), isEnum())); + } + + private Predicate isCollection() { + return new Predicate() { + @Override + public boolean apply(ModelAttributeField input) { + return isContainerType(input.getFieldType()); + } + }; + } + + private Predicate isMap() { + return new Predicate() { + @Override + public boolean apply(ModelAttributeField input) { + return Maps.isMapType(input.getFieldType()); + } + }; + } + + private Predicate isEnum() { + return new Predicate() { + @Override + public boolean apply(ModelAttributeField input) { + return input.getFieldType().getErasedType().isEnum(); + } + }; + } + + private Predicate belongsToJavaPackage() { + return new Predicate() { + @Override + public boolean apply(ModelAttributeField input) { + return packageName(input.getFieldType().getErasedType()).startsWith("java.lang"); + } + }; + } + + private Predicate isBaseType() { + return new Predicate() { + @Override + public boolean apply(ModelAttributeField input) { + return Types.isBaseType(input.getFieldType()) || input.getField().getType().isPrimitive(); + } + }; + } + + private Function toModelAttributeField( + final AlternateTypeProvider alternateTypeProvider) { + return new Function() { + @Override + public ModelAttributeField apply(ResolvedField input) { + return new ModelAttributeField(fieldType(alternateTypeProvider, input), input); + } + }; + } + + private Predicate onlyBeanProperties(final Set beanPropNames) { + return new Predicate() { + @Override + public boolean apply(ResolvedField input) { + return beanPropNames.contains(input.getName()); + } + }; + } + + private String nestedParentName(String parentName, ResolvedField field) { + String name = field.getName(); + ResolvedType fieldType = field.getType(); + if (isContainerType(fieldType) && !Types.isBaseType(collectionElementType(fieldType))) { + name += "[0]"; + } + + if (isNullOrEmpty(parentName)) { + return name; + } + return String.format("%s.%s", parentName, name); + } + + private ResolvedType fieldType(AlternateTypeProvider alternateTypeProvider, ResolvedField field) { + return alternateTypeProvider.alternateFor(field.getType()); + } + + private String packageName(Class type) { + return Optional.fromNullable(type.getPackage()).transform(toPackageName()).or("java"); + } + + private Function toPackageName() { + return new Function() { + @Override + public String apply(Package input) { + return input.getName(); + } + }; + } + + private Set getBeanPropertyNames(final Class clazz) { + + try { + Set beanProps = new HashSet(); + PropertyDescriptor[] propDescriptors = Introspector.getBeanInfo(clazz).getPropertyDescriptors(); + + for (PropertyDescriptor propDescriptor : propDescriptors) { + try { + Field field = clazz.getDeclaredField(propDescriptor.getName()); + if(field != null) { + field.setAccessible(true); + ApiModelProperty property = field.getAnnotation(ApiModelProperty.class); + if(property != null && property.hidden()) { + continue; + } + } + } catch (Exception e) { + } + + if (propDescriptor.getReadMethod() != null) { + beanProps.add(propDescriptor.getName()); + } + } + + return beanProps; + + } catch (Exception e) { + LOG.warn(String.format("Failed to get bean properties on (%s)", clazz), e); + } + return newHashSet(); + } + +// @VisibleForTesting +// BeanInfo getBeanInfo(Class clazz) throws IntrospectionException { +// return Introspector.getBeanInfo(clazz); +// } + +} diff --git a/src/main/java/cn/stock/market/web/interceptor/AppInterceptor.java b/src/main/java/cn/stock/market/web/interceptor/AppInterceptor.java new file mode 100644 index 0000000..236322b --- /dev/null +++ b/src/main/java/cn/stock/market/web/interceptor/AppInterceptor.java @@ -0,0 +1,39 @@ +package cn.stock.market.web.interceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +import lombok.extern.slf4j.Slf4j; + +/** + * + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Mar 3, 2018 5:31:57 PM + */ +@Configuration +@Slf4j +public class AppInterceptor implements HandlerInterceptor { + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + + return true; + } + + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, + ModelAndView modelAndView) throws Exception { + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) + throws Exception { + } +} \ No newline at end of file diff --git a/src/main/java/cn/stock/market/web/interceptor/GlobalInterceptor.java b/src/main/java/cn/stock/market/web/interceptor/GlobalInterceptor.java new file mode 100644 index 0000000..96ca551 --- /dev/null +++ b/src/main/java/cn/stock/market/web/interceptor/GlobalInterceptor.java @@ -0,0 +1,37 @@ +package cn.stock.market.web.interceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +/** + * + * title: GlobalInterceptor.java + * 全局拦截器 + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Nov 1, 2021 2:08:51 PM + */ +@Configuration +public class GlobalInterceptor implements HandlerInterceptor { + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + return true; + } + + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, + ModelAndView modelAndView) throws Exception { + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) + throws Exception { + } +} \ No newline at end of file diff --git a/src/main/java/cn/stock/market/web/interceptor/OpenApiAuthInterceptor.java b/src/main/java/cn/stock/market/web/interceptor/OpenApiAuthInterceptor.java new file mode 100644 index 0000000..816a76a --- /dev/null +++ b/src/main/java/cn/stock/market/web/interceptor/OpenApiAuthInterceptor.java @@ -0,0 +1,32 @@ +package cn.stock.market.web.interceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +/** + * + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Mar 3, 2018 5:31:57 PM + */ +public class OpenApiAuthInterceptor implements HandlerInterceptor { + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + return true; + } + + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, + ModelAndView modelAndView) throws Exception { + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) + throws Exception { + } +} \ No newline at end of file diff --git a/src/main/java/cn/stock/market/web/interceptor/RedisTokenVerifyer.java b/src/main/java/cn/stock/market/web/interceptor/RedisTokenVerifyer.java new file mode 100644 index 0000000..01ce227 --- /dev/null +++ b/src/main/java/cn/stock/market/web/interceptor/RedisTokenVerifyer.java @@ -0,0 +1,82 @@ +//package cn.stock.market.web.interceptor; +// +//import java.util.Calendar; +//import java.util.Date; +//import java.util.List; +// +//import org.apache.commons.lang3.StringUtils; +//import org.springframework.data.redis.core.ListOperations; +//import org.springframework.data.redis.core.RedisTemplate; +// +//import com.ag.utils.CollectionUtils; +// +//import cn.qutaojing.common.utils.JwtUtils; +//import io.jsonwebtoken.Claims; +//import io.jsonwebtoken.Jws; +// +///** +// * 维护token列表 +// * +// * @author xlfd +// * @email xlfd@gmail.com +// * @version 1.0 +// * @created Jun 16, 2021 2:37:24 PM +// */ +//@SuppressWarnings({ "rawtypes", "unchecked" }) +//public class RedisTokenVerifyer { +// RedisTemplate redisTemplate; +// String redisKey; +// String secret; +// +// public RedisTokenVerifyer(RedisTemplate redisTemplate, String secret, String redisKey) { +// this.redisTemplate = redisTemplate; +// this.secret = secret; +// this.redisKey = redisKey; +// } +// +// public boolean verify(String token) { +// List list = redisTemplate.opsForList().range(redisKey, 0, -1); +// if (CollectionUtils.isEmpty(list)) { +// return false; +// } +// +// for (Object o : list) { +// String t = String.valueOf(o); +// +// try { +// Jws jws = JwtUtils.parse(t, secret); +// Date expiration = jws.getBody().getExpiration(); +// if(expiration != null && expiration.before(Calendar.getInstance().getTime())) { +// redisTemplate.opsForList().remove(redisKey, 0, t); +// continue; +// } +// } catch(Exception e) { +// } +// +// if (StringUtils.equals(token, t)) { +// return true; +// } +// } +// +// return false; +// } +// +// public void expireAt(Date date) { +// redisTemplate.expireAt(redisKey, date); +// } +// +// public void login(String token, Date expireAt) { +// redisTemplate.opsForList().leftPush(redisKey, token); +// expireAt(expireAt); +// } +// +// public void logout(String token) { +// redisTemplate.opsForList().remove(redisKey, 0, token); +// } +// +// public void clear() { +// ListOperations listOperations = redisTemplate.opsForList(); +// listOperations.trim(redisKey, 0, 0); +// listOperations.leftPop(redisKey); +// } +//} diff --git a/src/main/java/cn/stock/market/web/openapi/OpenApiParam.java b/src/main/java/cn/stock/market/web/openapi/OpenApiParam.java new file mode 100644 index 0000000..d0477b5 --- /dev/null +++ b/src/main/java/cn/stock/market/web/openapi/OpenApiParam.java @@ -0,0 +1,21 @@ +package cn.stock.market.web.openapi; + +import lombok.Data; + +/** + * open-api 公用入参 + * + * @author xlfd + * @email xlfd@gmail.com + * @version 1.0 + * @created Jun 16, 2021 1:54:51 PM + */ +@Data +public class OpenApiParam { + String appId; + String teamToken; + String version; + String timestamp; + String nonce; + String sign; +} diff --git a/src/main/java/cn/stock/market/web/openapi/impl/StockOpenApi.java b/src/main/java/cn/stock/market/web/openapi/impl/StockOpenApi.java new file mode 100644 index 0000000..30bdca4 --- /dev/null +++ b/src/main/java/cn/stock/market/web/openapi/impl/StockOpenApi.java @@ -0,0 +1,36 @@ +package cn.stock.market.web.openapi.impl; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.ag.utils.param.ParamUtils; + +import cn.stock.market.application.CommonApis; +import cn.stock.market.dto.model.StockCode; +import cn.stock.market.dto.model.StockVO; +import cn.stock.market.utils.ServerResponse; +import springfox.documentation.annotations.ApiIgnore; + +@Controller +@RequestMapping({"/api/market/openapi/stock"}) +@ApiIgnore +public class StockOpenApi { + + @RequestMapping({"hq"}) + @ResponseBody + public ServerResponse getNewsList(@RequestParam(value = "codeList") String codeList) { + ParamUtils.verify("股票代码集", codeList, ParamUtils.STRING_NOT_EMPTY_VERIFY_AND_CONVERT_VALUE); + + List list = Stream.of(StringUtils.split(codeList, ",")).map(val -> StockCode.a(val)).collect(Collectors.toList()); + Map map = CommonApis.of().stockDetailMap(list); + return ServerResponse.createBySuccess(map); + } +} \ No newline at end of file diff --git a/src/main/java/cn/stock/market/web/openapi/model/AuthOpenApiModel.java b/src/main/java/cn/stock/market/web/openapi/model/AuthOpenApiModel.java new file mode 100644 index 0000000..24d3029 --- /dev/null +++ b/src/main/java/cn/stock/market/web/openapi/model/AuthOpenApiModel.java @@ -0,0 +1,17 @@ +package cn.stock.market.web.openapi.model; + +import javax.validation.constraints.NotBlank; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@NoArgsConstructor +@SuperBuilder +@EqualsAndHashCode(callSuper = false) +public class AuthOpenApiModel { + @NotBlank(message = "凭证不能为空") + String simpleCredentials; +} diff --git a/src/main/resources/application-alpha.yml b/src/main/resources/application-alpha.yml new file mode 100644 index 0000000..df962c3 --- /dev/null +++ b/src/main/resources/application-alpha.yml @@ -0,0 +1,6 @@ +# 对外的公网域名 +domain: http://18.163.41.97:8108 +spring: + profiles: + include: base,base-alpha + active: alpha \ No newline at end of file diff --git a/src/main/resources/application-base-alpha.yml b/src/main/resources/application-base-alpha.yml new file mode 100644 index 0000000..221f131 --- /dev/null +++ b/src/main/resources/application-base-alpha.yml @@ -0,0 +1,61 @@ +spring: + jpa: + show-sql: true + # Redis配置 + redis: + host: 43.128.20.124 + password: ruTZ9J3gaDhknJ + port: 36379 + database: 1 + lettuce: + pool: + max-active: 8 + min-idle: 0 + max-idle: 8 + max-wait: 10000ms + timeout: 5000 + datasource: + stock-market: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://124.156.133.209:33306/stock-market?useUnicode=true&characterEncoding=utf-8 + username: root + password: 33BsUUcnXRYgwt + maxActive: 500 + testWhileIdle: true + validationQuery: SELECT 1 + timeBetweenEvictionRunsMillis: 6000 + type: com.alibaba.druid.pool.DruidDataSource + stock: + driver-class-name: com.mysql.cj.jdbc.Driver + #url: jdbc:mysql://129.226.172.67:3306/vip_huananyong_c?useUnicode=true&characterEncoding=utf-8&useSSL=true&verifyServerCertificate=true&requireSSL=true&clientCertificateKeyStoreUrl=classpath:keystoremysql&clientCertificateKeyStorePassword=abs1234567890&trustCertificateKeyStoreUrl=classpath:truststoremysql&trustCertificateKeyStorePassword=abs1234567890 + url: jdbc:mysql://124.156.133.209:33306/vip_huananyong_c?useUnicode=true&characterEncoding=utf-8&useSSL=true + username: root + password: 33BsUUcnXRYgwt + maxActive: 500 + testWhileIdle: true + validationQuery: SELECT 1 + timeBetweenEvictionRunsMillis: 6000 + type: com.alibaba.druid.pool.DruidDataSource + +ig507Licence: 4CEF3CDC-3A2E-76AB-9BF1-BE856F3D4468 +gugudataAppKey: K5LZKV8KAYM4 +aliyunAccessKeyId: LTAI5tJi2z8cegG8fTW7BSQu +aliyunAccessKeySecret: fnCI9LUcqLuH7D6nkhvSHQMob1JSm8 +aliyunAppCode: 75ef2615da614eaaa71e2e2058fc53b0 +# 具体看类:CloudStorageConfig +oss: + type: 2 # 类型 1:七牛 2:阿里云 3:腾讯云 + aliyunDomain: https://weilaishitong-dev.oss-cn-hangzhou.aliyuncs.com + aliyunPrefix: oss + aliyunEndPoint: oss-cn-hangzhou.aliyuncs.com + aliyunAccessKeyId: LTAI5tJi2z8cegG8fTW7BSQu + aliyunAccessKeySecret: fnCI9LUcqLuH7D6nkhvSHQMob1JSm8 + aliyunBucketName: weilaishitong-dev +enable: + scheduled: true +news: + url: https://api.tushare.pro + apiName: news + src: eastmoney + token: f86299eb129c44545eb8ff53d64902353225652efe63cc4dc95f8936 + fields: content,channels diff --git a/src/main/resources/application-base-prod.yml b/src/main/resources/application-base-prod.yml new file mode 100644 index 0000000..114de02 --- /dev/null +++ b/src/main/resources/application-base-prod.yml @@ -0,0 +1,71 @@ +spring: + jpa: + show-sql: true + # Redis配置 + redis: + host: 185.239.86.14 + #host: 18.163.5.172 + #host: localhost + password: Xinbao_2022@_redis + port: 6379 + database: 1 + lettuce: + pool: + max-active: 8 + min-idle: 0 + max-idle: 8 + max-wait: 10000ms + timeout: 5000 + datasource: + stock: + driver-class-name: com.mysql.cj.jdbc.Driver + #url: jdbc:mysql://rm-bp1i3596u188q0h44yo.mysql.rds.aliyuncs.com/stock?characterEncoding=utf8 + #url: jdbc:mysql://47.111.88.100:3306/stock?characterEncoding=utf8 + #username: root + #password: Xinbao_2022@_mysql + #url: jdbc:mysql://database-1.cctgahkfdii5.ap-east-1.rds.amazonaws.com:3306/stock?characterEncoding=utf8 + #password: Aa112211 + #url: jdbc:mysql://database-1.c8sr1gchvg02.ap-southeast-1.rds.amazonaws.com:3306/stock?characterEncoding=utf8 + #url: jdbc:mysql://database-1.cthrcoipwwsn.ap-east-1.rds.amazonaws.com:3306/stock?characterEncoding=utf8 + #username: admin + #password: Xinbao_2022!_mysql + #url: jdbc:mysql://18.163.5.172:3306/stock?characterEncoding=utf8 + url: jdbc:mysql://185.239.86.14:3306/stock?characterEncoding=utf8 + username: root + password: Xinbao_2022_mysql + maxActive: 1200 + maxWait: 60000 + testWhileIdle: true + testOnBorrow: false + validationQuery: SELECT 1 + #timeBetweenEvictionRunsMillis: 6000 + type: com.alibaba.druid.pool.DruidDataSource + +ig507Licence: 4CEF3CDC-3A2E-76AB-9BF1-BE856F3D4468 +gugudataAppKey: K5LZKV8KAYM4 +aliyunAccessKeyId: LTAI5tCQRp7t158TVyoF2Yhe +aliyunAccessKeySecret: glyzOno773Cv7HeWDliveu2H5gX486 +aliyunAppCode: 75ef2615da614eaaa71e2e2058fc53b0 +# 具体看类:CloudStorageConfig +oss: + type: 2 # 类型 1:七牛 2:阿里云 3:腾讯云 + aliyunDomain: https://weilaishitong.oss-cn-hangzhou.aliyuncs.com + aliyunPrefix: oss + aliyunEndPoint: oss-cn-hangzhou.aliyuncs.com + aliyunAccessKeyId: LTAI5tJi2z8cegG8fTW7BSQu + aliyunAccessKeySecret: fnCI9LUcqLuH7D6nkhvSHQMob1JSm8 + aliyunBucketName: weilaishitong +enable: + scheduled: true +news: + url: https://api.tushare.pro + apiName: news + src: eastmoney + token: f86299eb129c44545eb8ff53d64902353225652efe63cc4dc95f8936 + fields: content,channels +swagger: + production: false + basic: + enable: true + username: admin + password: 123321 diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml new file mode 100644 index 0000000..548d024 --- /dev/null +++ b/src/main/resources/application-dev.yml @@ -0,0 +1,6 @@ +# 对外的公网域名 +domain: http://stock.ngrok.rplees.com +spring: + profiles: + include: base,base-alpha + active: dev diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml new file mode 100644 index 0000000..1ebaf37 --- /dev/null +++ b/src/main/resources/application-prod.yml @@ -0,0 +1,6 @@ +# 对外的公网域名 +domain: https://api.xinpozj.top +spring: + profiles: + include: base,base-prod + active: prod \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..40c3db4 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,7 @@ +server: + port: 8188 +spring: + application: + name: stock-market + profiles: + active: dev \ No newline at end of file diff --git a/src/main/resources/bootstrap.yml b/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..2f93e46 --- /dev/null +++ b/src/main/resources/bootstrap.yml @@ -0,0 +1,39 @@ +server: + compression: + enabled: true + mime-types: application/json,application/xml,text/html,text/xml,text/plain + min-response-size: 2048 +spring: + resources: + static-locations: classpath:/templates/,classpath:/static/ + jpa: + database: mysql + database-platform: cn.qutaojing.common.jpa.CustomMysqlDialect + generate-ddl: false + hibernate: + # 将hibernate的统计打开来看看到底是不是被缓存了 + generate_statistics: true + order_inserts: true + order_updates: true + jdbc: + batch_size: 200 + batch_versioned_data: true + ddl-auto: none + use-new-id-generator-mappings: false + naming: + physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy + # 所有属性参考 https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html + servlet: + multipart: + max-file-size: 20MB + max-request-size: 20MB + +opentracing: + jaeger: + enabled: false + +logging: + level: + org.springframework.data.mongodb.core.MongoTemplate: DEBUG + #org.springframework.orm.jpa: DEBUG + #org.springframework.transaction: DEBUG \ No newline at end of file diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..0bbda05 --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + ${MAIN_FILE} + + ${FILE_LOG_PATTERN} + + + + ${MAIN_FILE}.%d{yyyy-MM-dd}.%i.log + ${LOG_FILE_MAX_SIZE:-200MB} + ${LOG_FILE_MAX_HISTORY:-3} + + + + + ${EXCEPTION_FILE} + + ${FILE_LOG_PATTERN} + + + + ${EXCEPTION_FILE}.%d{yyyy-MM-dd}.%i.log + ${LOG_FILE_MAX_SIZE:-200MB} + ${LOG_FILE_MAX_HISTORY:-3} + true + + + + + ${TIMEOUT_FILE} + + ${FILE_LOG_PATTERN} + + + + ${TIMEOUT_FILE}.%d{yyyy-MM-dd}.%i.log + ${LOG_FILE_MAX_SIZE:-200MB} + ${LOG_FILE_MAX_HISTORY:-3} + true + + + + + ${VISIT_FILE} + + ${FILE_LOG_PATTERN} + + + + ${VISIT_FILE}.%d{yyyy-MM-dd}.%i.log + ${LOG_FILE_MAX_SIZE:-200MB} + ${LOG_FILE_MAX_HISTORY:-3} + true + + + + + ${RECORD_FILE} + + ${FILE_LOG_PATTERN} + + + + ${RECORD_FILE}.%d{yyyy-MM-dd}.%i.log + ${LOG_FILE_MAX_SIZE:-200MB} + ${LOG_FILE_MAX_HISTORY:-3} + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/sqls/RealtimePO.sftl b/src/main/resources/sqls/RealtimePO.sftl new file mode 100644 index 0000000..9ff5b22 --- /dev/null +++ b/src/main/resources/sqls/RealtimePO.sftl @@ -0,0 +1,5 @@ +--deleteStockCode +DELETE FROM realtime WHERE locate('hf_',`stock_code`)=0 + +--deleteStockFuturesCode +DELETE FROM realtime WHERE locate('hf_',`stock_code`)=1 \ No newline at end of file diff --git a/src/main/resources/stock2guo.properties b/src/main/resources/stock2guo.properties new file mode 100644 index 0000000..fa90f5a --- /dev/null +++ b/src/main/resources/stock2guo.properties @@ -0,0 +1,115 @@ +ftp.server.ip=127.0.0.1 +ftp.user=ftp_vipyingyrt_cn +ftp.pass=ftp_vipyingyrt_cn +ftp.server.http.prefix=http://ftp.vipyingyrt.cn/ + +# redis config start +redis1.ip=129.226.172.67 +redis1.port=6379 +redis1.pwd=nango +redis.max.total=20 +redis.max.idle=10 +redis.min.idle=2 +redis.test.borrow=true +redis.test.return=true +# redis config end + +#cookie config start +user.cookie.name=USER_TOKEN +agent.cookie.name=AGENT_TOKEN +admin.cookie.name=ADMIN_TOKEN + +agent.key.prefix=SR +admin.super.name=18916320007 + +admin.auth.email.subject=\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00a9\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00b8\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00bf\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00a9\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00b9\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0084\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00a6\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0098\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0093\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00a8\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u009e\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u008d - \u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00a6\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0094\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00af\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00a4\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00bb\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0098\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00a9\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0080\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u009a\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00a7\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u009f\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00a5\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00a9\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00ae\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00a4\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00bb\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00b6 +admin.auth.email=navihold800@163.com +admin.auth.email.pwd=XY118318asd +#cookie config end + +# close order task config start +close.order.task.time.hour=2 +lock.timeout=50000 +# close order task config start + +#aliyun sms config +sms.aliyun.accessKeyId=LTAI4FqEYw8va2Bgak2fd9pL +sms.aliyun.accessKeySecret=WpOZQCHHwuJ9U9oo4yU73RiJY4CuLK + +#juhe api +juhe.stock.key=e27571e4f5f2f07440bf4996d01d5770 +juhe.ip.key=1b87ed225d34571b1ab8666f8f1a018b +#juhe api end + +#site setting +site.email.auth.url=/api/admin/authCharge.do +site.pc.reg.url=/home/#/register?code= +site.m.reg.url=/wap/#/register?code= + +#pc.refresh.time=3000 + +#sina.market.url=https://hq.sinajs.cn/rn=1520407404627&list=s_sh000001,s_sz399001,s_sz399006,s_sz399300,s_sz399005,s_sz399673 +sina.market.url=https://hq.sinajs.cn/rn=1520407404627&list=s_sh000001,s_sz399001,s_sz399006,s_sz399300,s_sz399005,s_sz399673,s_sz399106,s_sz399004,s_sz399100 +sina.single.market.url=https://hq.sinajs.cn/rn=1520407404627&list=s_ +sina.single.stock.url=https://hq.sinajs.cn/list= + +sina.single.stock.min.url=http://image.sinajs.cn/newchart/min/n/ +sina.single.stock.day.url=http://image.sinajs.cn/newchart/daily/n/ +sina.single.stock.week.url=http://image.sinajs.cn/newchart/weekly/n/ +sina.single.stock.month.url=http://image.sinajs.cn/newchart/monthly/n/ + +sina.single.futures.url=https://hq.sinajs.cn/list= + +sina.single.exchange.url=https://hq.sinajs.cn/list= + + +sina.k.min.url=http://money.finance.sina.com.cn/quotes_service/api/json_v2.php/CN_MarketData.getKLineData +sina.k.min.max.size=50 + +sina.futures.k.min.url=https://gu.sina.cn/ft/api/jsonp.php/var%20_XAU_{time}_{stamp}=/GlobalService.getMink?symbol={code}&type={time} +sina.futures.k.min.max.size=50 + +sina.futures.day.min.url=https://stock2.finance.sina.com.cn/futures/api/jsonp.php/var%20_{code}{date}=/GlobalFuturesService.getGlobalFuturesDailyKLine?symbol={code}&_={date}&source=web +sina.futures.day.min.max.size=50 + +sina.index.k.min.url=https://quotes.sina.cn/cn/api/jsonp_v2.php/var%20_{code}_{time}_{stamp}=/CN_MarketDataService.getKLineData?symbol={code}&scale={time}&ma=no&datalen=1023 +sina.index.k.min.max.size=50 + +sina.index.day.min.url=http://web.ifzq.gtimg.cn/appstock/app/fqkline/get?_var=kline_dayqfq¶m={code},day,,,320,qfq&r=0.8531244563261586 +sina.index.day.min.max.size=50 + +qq.k.min.url=http://data.gtimg.cn/flashdata/hushen/daily/20/code.js?visitDstTime=1 +qq.k.min.max.size=50 + +qq.month.min.url=http://web.ifzq.gtimg.cn/appstock/app/fqkline/get?param=sz300750,month,,,320,qfq + +eastmoney.month.url=https://push2his.eastmoney.com/api/qt/stock/kline/get?cb=jQuery3510019847947565290847_1699356882415&secid=0.833429&ut=fa5fd1943c7b386f172d6893dbfba10b&fields1=f1,f2,f3,f4,f5,f6&fields2=f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61&klt=102&fqt=1&beg=0&end=20500101&smplmt=460&lmt=1000000&_=1699356882499 + +juhe1.pay.callbackurl=http://xx.com +juhe1.pay.notifyurl=http://xx.com + + +fly.pay.merchantid=SLPNXG +fly.pay.token=0a17a92f45816a88431fa326b3b61baf + +cmc.pay.key=0a17a92f45816a88431fa326b3b61baf +cmc.pay.uid=74021809 +cmc.pay.return_url=https://www.bldzb666888.com/homes/#/rechargelist +cmc.pay.notify_url=https://www.bldzb666888.com/api/pay/juhenewpayNotify.do +cmc.pay.url=http://pay.phu889.com/api.php/webRequest/tradePay + + + +fly.pay.serverbackurl=http://www.honghoo.top/api/pay/flyNotify.do +fly.pay.callbackurl=http://www.honghoo.top/wap/#/user + +fly.pay.payurl=https://zf.flyotcpay.com/payment/ + +wj.sms.uid=\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00a4\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00b8\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0080\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00a6\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u009c\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0083\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0083\u00c3\u0082\u00c2\u0082\u00c3\u0083\u00c2\u0082\u00c3\u0082\u00c2\u00ac001 +wj.sms.key=d41d8cd98f00b204e980 +wj.sms.coding=utf8 + +website.domain.url=http://www.huijuwang888.com +website.token=0DC8F78384C7AAFF3192A9C60A473FEE7F89C62888689616B98A06910E86B510 + +news.main.url=http://eminfo.eastmoney.com diff --git a/src/main/resources/xxl-job.properties b/src/main/resources/xxl-job.properties new file mode 100644 index 0000000..b93532a --- /dev/null +++ b/src/main/resources/xxl-job.properties @@ -0,0 +1,18 @@ +### xxl-job admin address list, such as "http://address" or "http://address01,http://address02" +xxl.job.admin.addresses=http://xxl-job.useeus.net/xxl-job-admin + +### xxl-job, access token +xxl.job.accessToken=1TQaDaaCsAs + +### prod end override xxl.job.executor.appname and xxl.job.executor.address +### xxl-job executor appname +xxl.job.executor.appname=stock-dev +### xxl-job executor registry-address: default use address to registry , otherwise use ip:port if address is null +xxl.job.executor.address=http://xxjob.ngrok.rplees.com +### xxl-job executor server-info +xxl.job.executor.ip= +xxl.job.executor.port=8198 +### xxl-job executor log-path +#xxl.job.executor.logpath=logger/xxl-job/jobhandler +### xxl-job executor log-retention-days +xxl.job.executor.logretentiondays=1 diff --git a/src/test/java/cn/stock/trade/test/StockTest.java b/src/test/java/cn/stock/trade/test/StockTest.java new file mode 100644 index 0000000..d7529a5 --- /dev/null +++ b/src/test/java/cn/stock/trade/test/StockTest.java @@ -0,0 +1,29 @@ +package cn.stock.trade.test; + +import java.util.HashMap; +import java.util.Map; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; + +import cn.hutool.http.HttpUtil; +import cn.stock.market.utils.Messages; + +public class StockTest { + public static void main(String[] args) { + String url = "http://api.waditu.com"; + Map param = new HashMap<>(); + param.put("api_name","stock_basic"); + param.put("token","c30c5266b67ce2e0b93e12ddb18926150b777331e22568b07cabcca3"); + param.put("fields",""); + + String body = HttpUtil.createPost(url) + .body(JSON.toJSONString(param)) + .header("Content-Type", "application/json") + .execute() + .body() + ; + + System.out.println(body); + } +}