This commit is contained in:
shimu
2024-05-21 11:34:38 +08:00
commit 1c0e4b1bf0
70 changed files with 2077 additions and 0 deletions

32
iot/package.xml Normal file
View File

@@ -0,0 +1,32 @@
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>customAssembly</id>
<!-- dir -->
<formats>
<format>dir</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>/lib</outputDirectory>
<scope>runtime</scope>
<excludes>
<exclude>${project.groupId}:${project.artifactId}</exclude>
</excludes>
</dependencySet>
<dependencySet>
<outputDirectory>/</outputDirectory>
<includes>
<include>${project.groupId}:${project.artifactId}</include>
</includes>
</dependencySet>
</dependencySets>
</assembly>

117
iot/pom.xml Normal file
View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>iot</artifactId>
<packaging>jar</packaging>
<name>iot</name>
<groupId>com.zeto</groupId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<com.zeto>3.0.0</com.zeto>
</properties>
<dependencies>
<dependency>
<groupId>com.zeto</groupId>
<artifactId>core</artifactId>
<version>${com.zeto}</version>
</dependency>
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos_api</artifactId>
<version>5.6.211</version>
</dependency>
<dependency>
<groupId>me.zhyd.oauth</groupId>
<artifactId>JustAuth</artifactId>
<version>1.16.5</version>
</dependency>
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos-sts_api</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java</artifactId>
<version>3.1.640</version>
</dependency>
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos-sts_api</artifactId>
<version>3.1.1</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>package.xml</descriptor>
</descriptors>
<outputDirectory>${project.build.directory}/dist/</outputDirectory>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.zeto.${project.name}.Application</mainClass>
</transformer>
</transformers>
<finalName>${project.name}</finalName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,13 @@
package com.zeto.cms;
import com.zeto.Zen;
public class Application {
public static void main(String[] args) {
int listenPort = 7097;
String appName = "iot";
// ZenEnvironment.setMulti(true);
Zen.start(args, appName, listenPort, Application.class);
}
}

View File

@@ -0,0 +1,24 @@
package com.zeto.cms.controller;
import com.zeto.ZenData;
import com.zeto.ZenEngine;
import com.zeto.ZenResult;
import com.zeto.annotation.AccessRole;
import com.zeto.domain.ZenUserTag;
import com.zeto.kit.DateKit;
import lombok.extern.slf4j.Slf4j;
import org.noear.solon.annotation.Inject;
@Slf4j
@AccessRole(ZenUserTag.ADMIN)
public class Activity {
@Inject
private ZenEngine zenEngine;
public ZenResult content(ZenData context) {
ZenResult result = zenEngine.execute("get/activityOutput", context);
return result.put("now", DateKit.now() * 1000).setMessage(null);
}
}

View File

@@ -0,0 +1,5 @@
package com.zeto.cms.helper.login;
// 钉钉登录
public class DingLogin {
}

View File

@@ -0,0 +1,5 @@
package com.zeto.cms.helper.login;
// 企业微信登录
public class WeCom {
}

View File

@@ -0,0 +1,15 @@
package com.zeto.cms.helper.upload;
import java.util.Map;
public interface IUploader {
void put(String path, String content, String contentType);
void remove(String path);
String get(String path);
void refresh(String path);
Map<String, Object> token(String fileName, String target);
}

View File

@@ -0,0 +1,63 @@
package com.zeto.cms.helper.upload;
import com.zeto.ZenEnvironment;
import com.zeto.cms.helper.upload.cos.CosUploader;
import com.zeto.kit.ConfigKit;
import java.util.HashMap;
import java.util.Map;
public class Uploader {
private static IUploader uploader = null;
private static final Map<String, String> contentTypeMap = new HashMap<String, String>() {{
put("js", "application/javascript;charset=utf-8");
put("css", "text/css;charset=utf-8");
put("json", "application/json;charset=utf-8");
put("gif", "image/gif");
put("png", "image/png");
put("jpg", "image/jpeg");
put("woff", "application/font-woff");
put("woff2", "application/font-woff2");
put("otf", "application/x-font-opentype");
put("ttf", "application/x-font-ttf");
put("svg", "image/svg+xml");
put("eot", "application/vnd.ms-fontobject");
}};
private static IUploader i() {
if (Uploader.uploader == null) {
String type = ZenEnvironment.get("cloudType");
if (type.equals("qcloud")) Uploader.uploader = new CosUploader();
}
return Uploader.uploader;
}
public static void put(String path, String content) {
int extIndex = path.lastIndexOf(".");
if (extIndex < 0) return;
String ext = path.substring(extIndex + 1);
if (!Uploader.contentTypeMap.containsKey(ext)) return;
Uploader.i().put(path, content, Uploader.contentTypeMap.get(ext));
Uploader.refresh(path);
}
public static String get(String path) {
return Uploader.i().get(path);
}
public static void remove(String path) {
Uploader.i().remove(path);
Uploader.refresh(path);
}
public static void refresh(String path) {
// 非线上环境无需刷CDN
if (!ZenEnvironment.isOnline()) return;
String webpath = ZenEnvironment.get("cdnHost") + path;
Uploader.i().refresh(webpath);
}
public static Map<String, Object> token(String fileName, String target) {
return Uploader.i().token(fileName, target);
}
}

View File

@@ -0,0 +1,155 @@
package com.zeto.cms.helper.upload.cos;
import com.google.common.base.Strings;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.model.COSObject;
import com.qcloud.cos.model.COSObjectInputStream;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.region.Region;
import com.qcloud.cos.utils.IOUtils;
import com.qcloud.cos.utils.StringUtils;
import com.tencent.cloud.CosStsClient;
import com.tencent.cloud.Response;
import com.zeto.ZenEnvironment;
import com.zeto.cms.helper.upload.IUploader;
import com.zeto.kit.StringKit;
import lombok.extern.slf4j.Slf4j;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
@Slf4j
public class CosUploader implements IUploader {
private final String publicBucket;
private final COSClient cosClient;
private final String defaultType = "public";
public CosUploader() {
String secretId = ZenEnvironment.get("bucketAK");
String secretKey = ZenEnvironment.get("bucketSK");
String region = ZenEnvironment.get("bucketRegion");
publicBucket = ZenEnvironment.get("bucketPublic");
// 初始化用户身份信息(secretId, secretKey)
COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
// 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
ClientConfig clientConfig = new ClientConfig(new Region(region));
// 生成cos客户端
this.cosClient = new COSClient(cred, clientConfig);
}
@Override
public void remove(String path) {
}
@Override
public void put(String path, String content, String contentType) {
if (Strings.isNullOrEmpty(content) || Strings.isNullOrEmpty(path)) return;
byte[] contentByteArray = content.getBytes(StringUtils.UTF8);
InputStream contentInput = new ByteArrayInputStream(contentByteArray);
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(contentType);
metadata.setContentLength(contentByteArray.length);
PutObjectRequest putObjectRequest = new PutObjectRequest(publicBucket, path, contentInput, metadata);
cosClient.putObject(putObjectRequest);
}
@Override
public String get(String path) {
COSObjectInputStream cosObjectInput = null;
try {
COSObject cosObject = cosClient.getObject(publicBucket, path);
cosObjectInput = cosObject.getObjectContent();
} catch (CosClientException e) {
CosUploader.log.error("uploader", e);
}
// 这里是直接读取,按实际情况来处理
byte[] bytes = null;
try {
bytes = IOUtils.toByteArray(cosObjectInput);
} catch (IOException e) {
CosUploader.log.error("uploader", e);
} finally {
// 用完流之后一定要调用 close()
try {
cosObjectInput.close();
} catch (IOException e) {
CosUploader.log.error("uploader", e);
}
}
return new String(bytes);
}
// 刷新CDN
@Override
public void refresh(String path) {
}
@Override
public Map<String, Object> token(String fileName, String target) {
String secretId = ZenEnvironment.get("bucketAK");
String secretKey = ZenEnvironment.get("bucketSK");
String region = ZenEnvironment.get("bucketRegion");
String domain = ZenEnvironment.get("bucketDomain");
String filepath = this.getPath(fileName);
TreeMap<String, Object> config = new TreeMap<>();
// 替换为您的云 api 密钥 SecretId
config.put("secretId", secretId);
// 替换为您的云 api 密钥 SecretKey
config.put("secretKey", secretKey);
String bucket = defaultType.equals(target) ? publicBucket : ZenEnvironment.get("bucketPrivate");
// 临时密钥有效时长,单位是秒,默认 1800 秒,目前主账号最长 2 小时(即 7200 秒),子账号最长 36 小时(即 129600
int timeout = 1800;
config.put("durationSeconds", timeout);
config.put("bucket", bucket);
// 换成 publicBucket 所在地区
config.put("region", region);
String allowPrefix = filepath.substring(0, 18) + "*";
config.put("allowPrefixes", new String[]{allowPrefix});
String[] allowActions = new String[]{
"name/cos:PutObject",
"name/cos:PostObject"
};
config.put("allowActions", allowActions);
Map<String, Object> result = new HashMap<>();
try {
Response response = CosStsClient.getCredential(config);
// 腾讯云
result.put("type", "cos");
result.put("startTime", response.startTime);
result.put("expiredTime", response.expiredTime);
// 地域地址https://cloud.tencent.com/document/product/436/6224
result.put("pathname", filepath);
result.put("bucket", bucket);
result.put("region", region);
result.put("url", domain + filepath);
result.put("secretId", response.credentials.tmpSecretId);
result.put("secretKey", response.credentials.tmpSecretKey);
result.put("sessionToken", response.credentials.sessionToken);
} catch (IOException e) {
throw new RuntimeException(e);
}
return result;
}
private String getPath(String fileName) {
String ext = StringKit.fileExt(fileName);
String fileId = StringKit.objectId();
return "f01/" + ext + "/" + fileId.substring(0, 2) + "/" + fileId.substring(2) + "." + ext;
}
}

View File

@@ -0,0 +1,4 @@
package com.zeto.cms.helper.upload.oss;
public class OssUploader {
}

View File

@@ -0,0 +1,57 @@
package com.zeto.cms.hooks;
import com.zeto.IZenHook;
import com.zeto.ZenData;
import com.zeto.ZenEngine;
import com.zeto.ZenResult;
import com.zeto.annotation.ZenHook;
import com.zeto.cms.helper.upload.Uploader;
import com.zeto.cms.hooks.domain.PageComponentDO;
import com.zeto.cms.hooks.domain.PageDO;
import com.zeto.driver.JsonKit;
import com.zeto.kit.StringKit;
import org.noear.solon.annotation.Inject;
@ZenHook("patch/activityStatus")
public class ActivityStatusHook implements IZenHook {
private final static String online = "2";
private final static String offline = "3";
@Inject
private ZenEngine zenEngine;
@Override
public ZenResult before(ZenData context) {
String status = context.get("status");
ZenResult result = zenEngine.execute("get/activity", context);
String pathStr = StringKit.objectId();
String path = "/" + pathStr.substring(0, 2) + "/" + pathStr.substring(2);
// 页面上线
if (ActivityStatusHook.online.equals(status)) {
PageDO pageDO = result.get("content", PageDO.class);
Object pageData = result.getObject("data");
pageDO.setData(pageData);
StringBuilder jsResult = new StringBuilder();
for (PageComponentDO componentDO : pageDO.getComponents()) {
String jsSource = "/" + componentDO.getLib() + "/" + componentDO.getName() + ".js";
jsResult.append(Uploader.get(jsSource)).append(";");
}
String pageDataStr = JsonKit.stringify(pageDO);
// 推送数据与js资源
Uploader.put("/jsz" + path + ".json", pageDataStr);
Uploader.put("/jsz" + path + ".js", jsResult.toString());
context.put("output", path);
}
return ZenResult.success();
}
@Override
public void after(ZenData context, ZenResult result) {
String id = context.getId();
String status = context.get("status");
// 页面上线
if (ActivityStatusHook.offline.equals(status)) {
//todo: 完成cdn下线
}
}
}

View File

@@ -0,0 +1,21 @@
package com.zeto.cms.hooks;
import com.zeto.IZenHook;
import com.zeto.ZenData;
import com.zeto.ZenResult;
import com.zeto.annotation.ZenHook;
import com.zeto.cms.helper.upload.Uploader;
import java.util.Map;
@ZenHook("zetoUploadHook")
public class ZetoUploadHook implements IZenHook {
@Override
public ZenResult before(ZenData context) {
IZenHook.super.before(context);
String fileName = context.get("filename");
String target = context.get("target");
Map<String, Object> data = Uploader.token(fileName, target);
return ZenResult.success().setData(data);
}
}

View File

@@ -0,0 +1,13 @@
package com.zeto.cms.hooks.domain;
import lombok.Data;
import java.util.Map;
@Data
public class PageComponentDO {
private String name;
private String id;
private String lib;
private Map<String, String> meta;
}

View File

@@ -0,0 +1,13 @@
package com.zeto.cms.hooks.domain;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
public class PageDO {
private List<PageComponentDO> components;
private int counter;
private Object data;
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
[{"columns":[{"defaultValue":"","describe":"编号","length":24,"name":"id","required":false,"type":2},{"defaultValue":"","describe":"文章标题","length":200,"name":"title","required":false,"type":2},{"defaultValue":"","describe":"文章分类","length":24,"name":"category_id","required":false,"type":2},{"code":"articleType","defaultValue":"","describe":"文章类型","length":1,"name":"type","required":false,"type":1},{"defaultValue":"","describe":"文章内容","length":0,"name":"content","required":false,"type":10},{"defaultValue":"","describe":"是否支持评论","length":0,"name":"commentable","required":false,"type":1},{"defaultValue":"","describe":"创建时间","length":0,"name":"create_gmt","required":false,"type":6},{"defaultValue":"","describe":"更新时间","length":0,"name":"update_gmt","required":false,"type":6},{"defaultValue":"","describe":"图片列表","length":0,"name":"pictures","required":false,"type":12},{"defaultValue":"","describe":"创建者","length":24,"name":"uid","required":false,"type":2},{"defaultValue":"","describe":"创建者","length":50,"name":"author","required":false,"type":2},{"defaultValue":"","describe":"来源","length":200,"name":"from","required":false,"type":2}],"indices":[],"name":"article"},{"columns":[{"defaultValue":"","describe":"编号","length":24,"name":"id","required":false,"type":2},{"defaultValue":"","describe":"分类标题","length":20,"name":"title","required":false,"type":2},{"defaultValue":"","describe":"分类描述","length":200,"name":"describe","required":false,"type":2},{"defaultValue":"","describe":"父级id","length":24,"name":"parent_id","required":false,"type":2},{"defaultValue":"","describe":"创建时间","length":0,"name":"create_gmt","required":false,"type":6},{"defaultValue":"","describe":"更新时间","length":0,"name":"update_gmt","required":false,"type":6}],"indices":[],"name":"category"},{"columns":[{"defaultValue":"","describe":"编号","length":24,"name":"id","required":false,"type":2},{"defaultValue":"","describe":"页面标题","length":50,"name":"title","required":false,"type":2},{"defaultValue":"","describe":"页面路径","length":50,"name":"path","required":false,"type":2},{"code":"pageType","defaultValue":"","describe":"页面类型","length":1,"name":"type","required":false,"type":1},{"defaultValue":"","describe":"所属站点","length":24,"name":"site_id","required":false,"type":2},{"defaultValue":"","describe":"描述内容","length":0,"name":"content","required":false,"type":12},{"code":"pageStatus","defaultValue":"","describe":"页面状态","length":1,"name":"status","required":false,"type":1},{"defaultValue":"","describe":"创建时间","length":0,"name":"create_gmt","required":false,"type":6},{"defaultValue":"","describe":"更新时间","length":0,"name":"update_gmt","required":false,"type":6},{"defaultValue":"","describe":"页面数据","length":0,"name":"data","required":false,"type":12},{"defaultValue":"","describe":"js path输出ID","length":200,"name":"output","required":false,"type":2}],"indices":[],"name":"activity"},{"columns":[{"defaultValue":"","describe":"站点名称","length":50,"name":"title","required":false,"type":2},{"defaultValue":"","describe":"描述信息","length":300,"name":"describe","required":false,"type":2},{"defaultValue":"","describe":"站点域名","length":50,"name":"domain","required":false,"type":2},{"defaultValue":"","describe":"备案信息","length":200,"name":"record","required":false,"type":2},{"defaultValue":"","describe":"编号","length":24,"name":"id","required":false,"type":2},{"defaultValue":"","describe":"创建时间","length":0,"name":"create_gmt","required":false,"type":6},{"defaultValue":"","describe":"更新时间","length":0,"name":"update_gmt","required":false,"type":6}],"indices":[{"columns":["domain"],"index":"Unique"}],"name":"site"},{"columns":[{"defaultValue":"","describe":"页面标题","length":50,"name":"title","required":false,"type":2},{"defaultValue":"","describe":"页面路径","length":50,"name":"path","required":false,"type":2},{"defaultValue":"","describe":"平台类型","length":0,"name":"type","required":false,"type":1},{"defaultValue":"","describe":"所属站点","length":24,"name":"site_id","required":false,"type":2},{"defaultValue":"","describe":"网站内容","length":0,"name":"content","required":false,"type":4},{"code":"pageStatus","defaultValue":"","describe":"状态","length":0,"name":"status","required":false,"type":1},{"defaultValue":"","describe":"模版ID","length":24,"name":"template_id","required":false,"type":2},{"defaultValue":"","describe":"编号","length":24,"name":"id","required":false,"type":2},{"defaultValue":"","describe":"创建时间","length":0,"name":"create_gmt","required":false,"type":6},{"defaultValue":"","describe":"更新时间","length":0,"name":"update_gmt","required":false,"type":6}],"indices":[{"columns":["path"],"index":"Unique"}],"name":"page"}]

View File

@@ -0,0 +1,93 @@
{
"columns": [
{
"defaultValue": "",
"describe": "编号",
"length": 24,
"name": "id",
"required": false,
"type": 2
},
{
"defaultValue": "",
"describe": "昵称",
"length": 50,
"name": "nick",
"required": false,
"type": 2
},
{
"defaultValue": "",
"describe": "登录名",
"length": 24,
"name": "username",
"required": false,
"type": 2
},
{
"defaultValue": "",
"describe": "联系电话",
"length": 1,
"name": "mobile",
"required": false,
"type": 2
},
{
"defaultValue": "",
"describe": "账号密码",
"length": 200,
"name": "pwd",
"required": false,
"type": 2
},
{
"defaultValue": "",
"describe": "三方唯一ID",
"length": 50,
"name": "union_id",
"required": false,
"type": 2
},
{
"defaultValue": "",
"describe": "基础标签",
"length": 0,
"name": "tag",
"required": false,
"type": 1
},
{
"defaultValue": "",
"describe": "用户邮箱",
"length": 50,
"name": "email",
"required": false,
"type": 2
},{
"defaultValue": "",
"describe": "动态密钥",
"length": 200,
"name": "ukey",
"required": false,
"type": 2
},
{
"defaultValue": "",
"describe": "创建时间",
"length": 0,
"name": "create_gmt",
"required": false,
"type": 6
},
{
"defaultValue": "",
"describe": "更新时间",
"length": 0,
"name": "update_gmt",
"required": false,
"type": 6
}
],
"indices": [],
"name": "user"
}

View File

@@ -0,0 +1 @@
v2.0.0-20240102