mirror of
https://gitee.com/shuto-github/intranet_app_manager.git
synced 2026-05-09 00:00:03 +08:00
新增钉钉机器人支持
This commit is contained in:
@@ -11,6 +11,7 @@ import org.yzr.model.App;
|
||||
import org.yzr.model.Package;
|
||||
import org.yzr.service.AppService;
|
||||
import org.yzr.service.PackageService;
|
||||
import org.yzr.utils.DingdingUtils;
|
||||
import org.yzr.utils.PathManager;
|
||||
import org.yzr.utils.ipa.PlistGenerator;
|
||||
import org.yzr.vo.AppViewModel;
|
||||
@@ -94,6 +95,8 @@ public class PackageController {
|
||||
app = this.appService.save(app);
|
||||
// URL
|
||||
String codeURL = this.pathManager.getBaseURL(false) + "p/code/" + app.getCurrentPackage().getId();
|
||||
// 发送钉钉消息
|
||||
DingdingUtils.sendMarkdown(app, pathManager);
|
||||
map.put("code", codeURL);
|
||||
map.put("success", true);
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -1,38 +1,27 @@
|
||||
package org.yzr.controller;
|
||||
|
||||
|
||||
import net.glxn.qrgen.javase.QRCode;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.yzr.model.App;
|
||||
import org.yzr.model.Package;
|
||||
import org.yzr.service.AppService;
|
||||
import org.yzr.service.PackageService;
|
||||
import org.yzr.utils.PathManager;
|
||||
import org.yzr.utils.ipa.PlistGenerator;
|
||||
import org.yzr.vo.AppViewModel;
|
||||
import org.yzr.vo.PackageViewModel;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.yzr.model.WebHook;
|
||||
import org.yzr.service.WebHookService;
|
||||
import org.yzr.vo.WebHookViewModel;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Controller
|
||||
public class WebHookController {
|
||||
@Resource
|
||||
private AppService appService;
|
||||
@Resource
|
||||
private PackageService packageService;
|
||||
@Resource
|
||||
private PathManager pathManager;
|
||||
private WebHookService webHookService;
|
||||
|
||||
/**
|
||||
* 添加webHook
|
||||
@@ -44,6 +33,12 @@ public class WebHookController {
|
||||
@ResponseBody
|
||||
public Map<String, Object> add(WebHookViewModel viewModel, HttpServletRequest request) {
|
||||
Map<String , Object> result = new HashMap<>();
|
||||
WebHook webHook = this.webHookService.save(viewModel);
|
||||
if (webHook != null) {
|
||||
result.put("success", true);
|
||||
} else {
|
||||
result.put("success", false);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -57,6 +52,12 @@ public class WebHookController {
|
||||
@ResponseBody
|
||||
public Map<String, Object> delete(WebHookViewModel viewModel, HttpServletRequest request) {
|
||||
Map<String , Object> result = new HashMap<>();
|
||||
try {
|
||||
this.webHookService.deleteById(viewModel.getId());
|
||||
result.put("success", true);
|
||||
} catch (Exception e) {
|
||||
result.put("success", false);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -70,7 +71,38 @@ public class WebHookController {
|
||||
@ResponseBody
|
||||
public Map<String, Object> update(WebHookViewModel viewModel, HttpServletRequest request) {
|
||||
Map<String , Object> result = new HashMap<>();
|
||||
try {
|
||||
this.webHookService.update(viewModel);
|
||||
result.put("success", true);
|
||||
} catch (Exception e) {
|
||||
result.put("success", false);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取 webHook 列表
|
||||
* @param id
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/webHook/find/{id}")
|
||||
@ResponseBody
|
||||
public List<WebHookViewModel> findById(@PathVariable("id") String id, HttpServletRequest request) {
|
||||
List<WebHookViewModel> viewModels = new ArrayList<>();
|
||||
try {
|
||||
List<WebHook> webHookList = this.webHookService.findByAppId(id);
|
||||
for (WebHook webHook :
|
||||
webHookList) {
|
||||
WebHookViewModel viewModel = new WebHookViewModel();
|
||||
BeanUtils.copyProperties(webHook, viewModel);
|
||||
viewModels.add(viewModel);
|
||||
}
|
||||
} catch (BeansException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return viewModels;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,6 +30,12 @@ public class AppService {
|
||||
public App save(App app) {
|
||||
App app1 = this.appDao.save(app);
|
||||
app1.getCurrentPackage();
|
||||
try {
|
||||
// 触发级联查询
|
||||
app1.getWebHookList().forEach(webHook -> {});
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return app1;
|
||||
}
|
||||
|
||||
@@ -71,6 +77,7 @@ public class AppService {
|
||||
app.setName(aPackage.getName());
|
||||
// 触发级联查询
|
||||
app.getPackageList().forEach(p->{});
|
||||
app.getWebHookList().forEach(webHook -> {});
|
||||
}
|
||||
if (app.getPackageList() == null) {
|
||||
app.setPackageList(new ArrayList<>());
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.yzr.dao.AppDao;
|
||||
import org.yzr.dao.PackageDao;
|
||||
import org.yzr.model.App;
|
||||
import org.yzr.model.Package;
|
||||
import org.yzr.utils.ImageUtils;
|
||||
import org.yzr.utils.PathManager;
|
||||
import org.yzr.utils.ipa.PlistGenerator;
|
||||
import org.yzr.utils.parser.ParserClient;
|
||||
@@ -38,8 +39,9 @@ public class PackageService {
|
||||
String tempIconPath = PathManager.getTempIconPath(aPackage);
|
||||
String iconPath = packagePath + File.separator + "icon.png";
|
||||
String sourcePath = packagePath + File.separator + fileName;
|
||||
|
||||
// 拷贝图标
|
||||
FileUtils.copyFile(new File(tempIconPath), new File(iconPath));
|
||||
ImageUtils.resize(tempIconPath, iconPath, 192, 192);
|
||||
// 源文件
|
||||
FileUtils.copyFile(new File(filePath), new File(sourcePath));
|
||||
|
||||
|
||||
@@ -1,22 +1,38 @@
|
||||
package org.yzr.service;
|
||||
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.yzr.dao.AppDao;
|
||||
import org.yzr.dao.WebHookDao;
|
||||
import org.yzr.model.App;
|
||||
import org.yzr.model.WebHook;
|
||||
import org.yzr.vo.WebHookViewModel;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.transaction.Transactional;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class WebHookService {
|
||||
|
||||
@Resource
|
||||
private WebHookDao webHookDao;
|
||||
@Resource
|
||||
private AppDao appDao;
|
||||
|
||||
@Transactional
|
||||
public WebHook save(WebHook webHook) {
|
||||
return this.webHookDao.save(webHook);
|
||||
public WebHook save(WebHookViewModel viewModel) {
|
||||
App app = appDao.findById(viewModel.getAppId()).get();
|
||||
if (app != null) {
|
||||
WebHook webHook = new WebHook();
|
||||
BeanUtils.copyProperties(viewModel, webHook);
|
||||
webHook.setApp(app);
|
||||
webHook.setType(WebHook.WEB_HOOK_TYPE_DING_DING);
|
||||
return webHookDao.save(webHook);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -33,4 +49,28 @@ public class WebHookService {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<WebHook> findByAppId(String appId) {
|
||||
App app = appDao.findById(appId).get();
|
||||
if (app != null) {
|
||||
List<WebHook> webHookList = app.getWebHookList();
|
||||
List<WebHook> webHooks = new ArrayList<>();
|
||||
for (WebHook webHook :
|
||||
webHookList) {
|
||||
webHooks.add(webHook);
|
||||
}
|
||||
return webHooks;
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public void update(WebHookViewModel viewModel) {
|
||||
WebHook webHook = webHookDao.findById(viewModel.getId()).get();
|
||||
if (webHook != null) {
|
||||
webHook.setName(viewModel.getName());
|
||||
webHook.setUrl(viewModel.getUrl());
|
||||
webHookDao.save(webHook);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,10 @@ package org.yzr.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import okhttp3.*;
|
||||
import org.springframework.http.converter.json.GsonBuilderUtils;
|
||||
import org.yzr.model.App;
|
||||
import org.yzr.model.WebHook;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class DingdingUtils {
|
||||
@@ -18,7 +17,7 @@ public class DingdingUtils {
|
||||
* @param webhook 钉钉自定义机器人webhook
|
||||
* @return
|
||||
*/
|
||||
public static boolean sendToDingding(String jsonString, String webhook) {
|
||||
private static boolean sendToDingding(String jsonString, String webhook) {
|
||||
try{
|
||||
String type = "application/json; charset=utf-8";
|
||||
RequestBody body = RequestBody.create(MediaType.parse(type), jsonString);
|
||||
@@ -38,14 +37,33 @@ public class DingdingUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean sendMarkdown() {
|
||||
public static void sendMarkdown(App app, PathManager pathManager) {
|
||||
if (app.getWebHookList() == null || app.getWebHookList().size() < 1) {
|
||||
return;
|
||||
}
|
||||
Map<String, Object> markdown = new HashMap<>();
|
||||
markdown.put("title", "时代的火车向前开");
|
||||
markdown.put("text", "[ticket(Android)更新](https://www.baidu.com) \n\n  \n\n 链接:[https://fir.im/cq7f](https://fir.im/cq7f) \n\n 版本: 1.0 (Build: 1)");
|
||||
markdown.put("title", app.getName());
|
||||
String url = pathManager.getBaseURL(false) + "s/" + app.getShortCode();
|
||||
String platform = "iOS";
|
||||
if (app.getPlatform().equalsIgnoreCase("android")) {
|
||||
platform = "Android";
|
||||
}
|
||||
|
||||
String appInfo = String.format("[%s(%s)更新](%s)", app.getName(), platform, url);
|
||||
// 将图片转为 base64, 内网 ip 钉钉无法访问,直接给图片数据
|
||||
String iconPath = PathManager.getFullPath(app.getCurrentPackage()) + "icon.png";
|
||||
String icon = "data:image/png;base64," + ImageUtils.convertImageToBase64(iconPath);
|
||||
String pathInfo = String.format("", app.getName(), icon);
|
||||
String otherInfo = String.format("链接:[%s](%s) \n\n 版本:%s (Build: %s)", url, url, app.getCurrentPackage().getVersion(), app.getCurrentPackage().getBuildVersion());
|
||||
String text = appInfo + " \n\n " + pathInfo + " \n\n " + otherInfo;
|
||||
markdown.put("text", text);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("msgtype", "markdown");
|
||||
jsonObject.put("markdown", markdown);
|
||||
|
||||
return sendToDingding(jsonObject.toJSONString(), "https://oapi.dingtalk.com/robot/send?access_token=a2030da1a934473cc8f950d342888321387ed65f92bcf16a6bf4c048903e5a0e");
|
||||
String json = jsonObject.toJSONString();
|
||||
for (WebHook webHook :
|
||||
app.getWebHookList()) {
|
||||
sendToDingding(json, webHook.getUrl());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package org.yzr.utils;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import org.springframework.util.Base64Utils;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
public class ImageUtils {
|
||||
|
||||
/**
|
||||
* 将图片转换为 Base64
|
||||
* @param filePath
|
||||
* @return
|
||||
*/
|
||||
public static String convertImageToBase64(String filePath) {
|
||||
InputStream in = null;
|
||||
byte[] data = null;
|
||||
//读取图片字节数组
|
||||
try {
|
||||
in = new FileInputStream(filePath);
|
||||
data = new byte[in.available()];
|
||||
in.read(data);
|
||||
in.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
//对字节数组Base64编码
|
||||
return Base64Utils.encodeToString(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置图片大小
|
||||
* @param soureFilePath
|
||||
* @param targetFilePath
|
||||
* @param height
|
||||
* @param width
|
||||
*/
|
||||
public static void resize(String soureFilePath, String targetFilePath, int width, int height) {
|
||||
try {
|
||||
File input = new File(soureFilePath);
|
||||
File output = new File(targetFilePath);
|
||||
output.mkdirs();
|
||||
BufferedImage image = ImageIO.read(input);
|
||||
Image tmp = image.getScaledInstance(width, height, Image.SCALE_SMOOTH);
|
||||
BufferedImage resized = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D g2d = resized.createGraphics();
|
||||
g2d.drawImage(tmp, 0, 0, null);
|
||||
g2d.dispose();
|
||||
ImageIO.write(resized, "png", output);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,8 +22,16 @@ public class APKParser implements PackageParser {
|
||||
aPackage.setSize(file.length());
|
||||
ApkMeta meta = apkFile.getApkMeta();
|
||||
aPackage.setName(meta.getName());
|
||||
aPackage.setVersion(meta.getPlatformBuildVersionName());
|
||||
aPackage.setBuildVersion(meta.getPlatformBuildVersionCode());
|
||||
String version = meta.getVersionName();
|
||||
String buildVersion = meta.getVersionCode() + "";
|
||||
if (version.length() < 1) {
|
||||
version = meta.getPlatformBuildVersionName();
|
||||
}
|
||||
if (buildVersion.length() < 1) {
|
||||
buildVersion = meta.getPlatformBuildVersionCode();
|
||||
}
|
||||
aPackage.setVersion(version);
|
||||
aPackage.setBuildVersion(buildVersion);
|
||||
aPackage.setBundleID(meta.getPackageName());
|
||||
aPackage.setMinVersion(meta.getMinSdkVersion());
|
||||
aPackage.setPlatform("android");
|
||||
|
||||
@@ -4,6 +4,7 @@ import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class WebHookViewModel {
|
||||
private String id;
|
||||
|
||||
private String appId;
|
||||
|
||||
|
||||
@@ -41,4 +41,4 @@ server.ssl.key-alias=1
|
||||
server.port=443
|
||||
server.http.port=80
|
||||
config.debug=debug
|
||||
server.domain=127.0.0.1
|
||||
server.domain=192.168.199.169
|
||||
+1
-6
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,205 @@
|
||||
/**
|
||||
* 获取 webHook 列表
|
||||
*/
|
||||
function getWebHooks() {
|
||||
var appId =$("#appId").val();
|
||||
var url = "/webHook/find/" + appId;
|
||||
$.post(url, function(result){
|
||||
$(".configrations").children(".config-name").remove();
|
||||
var content="";
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
content += '<a onclick="editWebHook(this)" class="config-name ng-binding ng-scope"';
|
||||
content += 'data="'+ result[i].id +'" data-url="' + result[i].url + '" ';
|
||||
content += 'data-name="'+ result[i].name;
|
||||
content += '">#'+ result[i].name +'</a>';
|
||||
}
|
||||
$(".configrations").append(content);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑 webHook
|
||||
* @param e
|
||||
*/
|
||||
function editWebHook(e) {
|
||||
var id = $("#webHookId").val();
|
||||
if (id.length > 0) {
|
||||
resetForm();
|
||||
} else {
|
||||
var name = $(e).attr("data-name");
|
||||
var url = $(e).attr("data-url");
|
||||
var id = $(e).attr("data");
|
||||
$("#webHookId").val(id);
|
||||
$("#ding-ding-web-hook-name").val(name);
|
||||
$("#ding-ding-web-hook-url").val(url);
|
||||
|
||||
$("#webhook-form-view").removeClass("ng-hide");
|
||||
$("#webHookAdd").removeClass("ng-hide");
|
||||
$("#webHookUpdate").removeClass("ng-hide");
|
||||
$("#webHookRemove").removeClass("ng-hide");
|
||||
$("#webHookCancel").removeClass("ng-hide");
|
||||
|
||||
$("#webHookAdd").addClass("ng-hide");
|
||||
$("#webHookCancel").addClass("ng-hide");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造数据
|
||||
* @returns {{appId: (*|jQuery|string|undefined), name: (*|jQuery|string|undefined), id: (*|jQuery|string|undefined), url: (*|jQuery|string|undefined)}}
|
||||
*/
|
||||
function buildData() {
|
||||
var name = $("#ding-ding-web-hook-name").val();
|
||||
var url = $("#ding-ding-web-hook-url").val();
|
||||
var appId = $("#appId").val();
|
||||
var id = $("#webHookId").val();
|
||||
var data ={
|
||||
name:name,
|
||||
url:url,
|
||||
appId:appId,
|
||||
id:id
|
||||
};
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置 webHook 表单
|
||||
*/
|
||||
function resetForm() {
|
||||
$("#ding-ding-web-hook-name").val('');
|
||||
$("#ding-ding-web-hook-url").val('');
|
||||
$("#webHookId").val('');
|
||||
|
||||
$("#webHookAdd").addClass("ng-hide");
|
||||
$("#webHookUpdate").addClass("ng-hide");
|
||||
$("#webHookRemove").addClass("ng-hide");
|
||||
$("#webHookCancel").addClass("ng-hide");
|
||||
|
||||
$("#webHookAdd").removeClass("ng-hide");
|
||||
$("#webHookCancel").removeClass("ng-hide");
|
||||
$("#webhook-form-view").addClass("ng-hide");
|
||||
|
||||
$("#webHookUpdate").attr("disabled", "disabled");
|
||||
$("#webHookAdd").attr("disabled", "disabled");
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加 webHook
|
||||
*/
|
||||
function add() {
|
||||
postWithURL("/webHook/add")
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新 webHook
|
||||
*/
|
||||
function update() {
|
||||
postWithURL("/webHook/update")
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除 webHook
|
||||
*/
|
||||
function remove() {
|
||||
postWithURL("/webHook/delete")
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送请求
|
||||
*/
|
||||
function postWithURL(url) {
|
||||
var data = buildData();
|
||||
resetForm();
|
||||
$.post(url, data, function(result){
|
||||
getWebHooks();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换面板时样式清除
|
||||
*/
|
||||
function removeAllPanelClass() {
|
||||
$("#info-container").removeClass("app-info");
|
||||
$("#info-container").removeClass("app-integration");
|
||||
$("#info-container").removeClass("app-activities");
|
||||
$("#info-panel").removeClass("apps-app-integration")
|
||||
$("#info-panel").removeClass("apps-app-info");
|
||||
$("#info-panel").removeClass("apps-app-activities");
|
||||
$("#app-activity-panel").removeClass("ng-hide");
|
||||
$("#app-info-panel").removeClass("ng-hide");
|
||||
$("#app-integration-panel").removeClass("ng-hide");
|
||||
}
|
||||
|
||||
$(function () {
|
||||
getWebHooks();
|
||||
|
||||
$(".download-action").click(function () {
|
||||
window.open($(this).val())
|
||||
});
|
||||
|
||||
$(".preview").click(function () {
|
||||
window.open($(this).val())
|
||||
});
|
||||
|
||||
$(".app-delete").click(function () {
|
||||
var url = "/p/delete/" + $(this).attr("data");
|
||||
$.post(url, data, function(result){
|
||||
window.location.href = window.location.href
|
||||
window.location.reload
|
||||
});
|
||||
})
|
||||
$("#js-app-short-copy-trigger").click(function () {
|
||||
new ClipboardJS('#js-app-short-copy-trigger', {
|
||||
text: function (trigger) {
|
||||
return trigger.getAttribute('value');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("#app-activity-icon").click(function () {
|
||||
removeAllPanelClass();
|
||||
$("#info-container").addClass("app-activities");
|
||||
$("#info-panel").addClass("apps-app-activities");
|
||||
$("#app-info-panel").addClass("ng-hide");
|
||||
$("#app-integration-panel").addClass("ng-hide");
|
||||
});
|
||||
$("#app-info-icon").click(function () {
|
||||
removeAllPanelClass();
|
||||
$("#info-container").addClass("app-info");
|
||||
$("#info-panel").addClass("apps-app-info");
|
||||
$("#app-activity-panel").addClass("ng-hide");
|
||||
$("#app-integration-panel").addClass("ng-hide");
|
||||
});
|
||||
$("#app-integration-icon").click(function () {
|
||||
removeAllPanelClass();
|
||||
$("#info-container").addClass("app-integration");
|
||||
$("#info-panel").addClass("apps-app-integration");
|
||||
$("#app-activity-panel").addClass("ng-hide");
|
||||
$("#app-info-panel").addClass("ng-hide");
|
||||
});
|
||||
|
||||
$("#delete-app").click(function () {
|
||||
var url = "/app/delete/" + $(this).attr("data");
|
||||
$.post(url, function(result){
|
||||
window.location.href = "/apps"
|
||||
});
|
||||
});
|
||||
|
||||
$("#ding-ding-web-hook-name, #ding-ding-web-hook-url").bind("input propertychange",function(event){
|
||||
var name = $("#ding-ding-web-hook-name").val();
|
||||
var url = $("#ding-ding-web-hook-url").val();
|
||||
if (name.length > 0 && url.length > 0) {
|
||||
$("#webHookAdd").removeAttr("disabled");
|
||||
$("#webHookUpdate").removeAttr("disabled");
|
||||
}
|
||||
});
|
||||
|
||||
$("#webHookCancel").click(function () {
|
||||
resetForm();
|
||||
});
|
||||
|
||||
$(".add-config").click(function () {
|
||||
resetForm();
|
||||
$("#webhook-form-view").removeClass("ng-hide");
|
||||
});
|
||||
});
|
||||
@@ -1,168 +1,222 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Stict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta http-equiv="x-ua-compatible" content="IE=edge">
|
||||
<meta name="renderer" content="webkit">
|
||||
|
||||
<title class="ng-binding">[[${package.name}]] - 应用动态</title>
|
||||
<link rel="icon" type="image/x-icon" th:href="@{/images/favicon.ico}" />
|
||||
<link rel="icon" type="image/x-icon" th:href="@{/images/favicon.ico}"/>
|
||||
<link rel="stylesheet" th:href="@{/css/bootstrap.css}">
|
||||
<link rel="stylesheet" th:href="@{/css/index.css}">
|
||||
<script type="text/javascript" th:src="@{/js/jquery-1.11.0.min.js}"></script>
|
||||
<script type="text/javascript" th:src="@{/js/clipboard.min.js}"></script>
|
||||
</head>
|
||||
|
||||
<body class="ng-scope">
|
||||
<nav class="navbar navbar-transparent fade-out navbar-black">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="/apps"><i class="icon-logo"></i> </a>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse navbar-ex1-collapse ng-scope">
|
||||
<div class="dropdown">
|
||||
<div></div>
|
||||
<nav class="navbar navbar-transparent fade-out navbar-black">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="/apps"><i class="icon-logo"></i></a>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse navbar-ex1-collapse ng-scope">
|
||||
<div class="dropdown">
|
||||
<div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="menu-toggle fade-out"><i class="icon-menu"></i></div>
|
||||
<div class="navbar-wrapper ng-scope">
|
||||
<div ng-controller="NavbarController" class="ng-scope">
|
||||
<div class="navbar-header-wrap">
|
||||
<div class="middle-wrapper">
|
||||
<nav>
|
||||
<h1 class="navbar-title logo">
|
||||
<i class="icon-logo"></i>
|
||||
</h1>
|
||||
<i class="icon-angle-right"></i>
|
||||
<div class="navbar-title primary-title">
|
||||
<a class="ng-binding" href="/apps">我的应用</a>
|
||||
</div>
|
||||
<i class="icon-angle-right"></i>
|
||||
<div class="navbar-title secondary-title ng-binding"
|
||||
style="">[[${package.name}]]</div>
|
||||
</nav>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="menu-toggle fade-out">
|
||||
<i class="icon-menu"></i>
|
||||
</div>
|
||||
<div class="navbar-wrapper ng-scope">
|
||||
<div ng-controller="NavbarController" class="ng-scope">
|
||||
<div class="navbar-header-wrap">
|
||||
<div class="middle-wrapper">
|
||||
<nav>
|
||||
<h1 class="navbar-title logo">
|
||||
<i class="icon-logo"></i>
|
||||
</h1>
|
||||
<i class="icon-angle-right"></i>
|
||||
<div class="navbar-title primary-title">
|
||||
<a class="ng-binding" href="/apps">我的应用</a>
|
||||
</div>
|
||||
<i class="icon-angle-right"></i>
|
||||
<div class="navbar-title secondary-title ng-binding" style="">
|
||||
[[${package.name}]]
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ngInclude: '/templates_manage/upload_modal.html' --><section data-ui-view="" class="ng-scope" style="">
|
||||
<div id="info-container" class="page-app app-activities">
|
||||
<div class="banner has-devices">
|
||||
<div class="middle-wrapper clearfix">
|
||||
<div id="app-activity-icon" class="pull-left icon-container appicon">
|
||||
<img th:src="'/' + ${package.icon}" width="100" height="100" class="change_icon ng-isolate-scope"/>
|
||||
</div>
|
||||
<div class="badges">
|
||||
<span tooltip-top="" tooltip="复制到剪贴板" id="js-app-short-copy-trigger" class="short tooltip-top ng-binding ng-isolate-scope" th:value="${package.installPath}" copy-trigger="">[[${package.installPath}]]</span>
|
||||
<span class="apptype ng-binding" th:if="${#strings.containsIgnoreCase(package.platform,'ios')}">iOS</span>
|
||||
<span class="apptype ng-binding" th:if="${#strings.containsIgnoreCase(package.platform,'android')}">Android</span>
|
||||
<span class="bundleid ng-binding">BundleID<b class="ng-binding"> [[${package.bundleID}]]</b></span>
|
||||
<span class="version ng-scope" th:if="${#strings.containsIgnoreCase(package.platform,'ios')}">iOS [[${package.minVersion}]] 或者高版本</span>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<a class="download ng-binding" th:href="${package.installPath}" target="_blank">
|
||||
<i class="icon-eye"></i> 预览
|
||||
</a>
|
||||
</div>
|
||||
<div class="tabs-container">
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a id="app-info-icon" class="ng-binding"><i class="icon-file"></i> 基本信息</a></li>
|
||||
<li>
|
||||
<a id="app-integration-icon" class="ng-binding"><i class="icon-box"></i> 集成</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- ngInclude: '/templates_manage/upload_modal.html' -->
|
||||
<section data-ui-view="" class="ng-scope" style="">
|
||||
<div class="page-app app-activities">
|
||||
<div class="banner has-devices">
|
||||
<div class="middle-wrapper clearfix">
|
||||
<div class="pull-left icon-container appicon">
|
||||
<img th:src="'/' + ${package.icon}" width="100" height="100" class="change_icon ng-isolate-scope"/>
|
||||
</div>
|
||||
<div class="badges">
|
||||
<span tooltip-top="" tooltip="复制到剪贴板" id="js-app-short-copy-trigger"
|
||||
class="short tooltip-top ng-binding ng-isolate-scope" th:value="${package.installPath}"
|
||||
copy-trigger="">[[${package.installPath}]]</span>
|
||||
<span class="apptype ng-binding" th:if="${#strings.containsIgnoreCase(package.platform,'ios')}">iOS</span>
|
||||
<span class="apptype ng-binding" th:if="${#strings.containsIgnoreCase(package.platform,'android')}">Android</span>
|
||||
<span class="bundleid ng-binding">BundleID<b class="ng-binding"> [[${package.bundleID}]]</b></span>
|
||||
<span class="version ng-scope" th:if="${#strings.containsIgnoreCase(package.platform,'ios')}" >iOS [[${package.minVersion}]] 或者高版本</span>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<a class="download ng-binding"th:href="${package.installPath}" target="_blank">
|
||||
<i class="icon-eye"></i>
|
||||
预览
|
||||
</a>
|
||||
</div>
|
||||
<div class="tabs-container">
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a class="ng-binding"><i class="icon-file"></i> 基本信息</a></li>
|
||||
<li>
|
||||
<a class="ng-binding"><i class="icon-device"></i> 设备列表</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- uiView: -->
|
||||
<div data-ui-view="" class="ng-scope">
|
||||
<div class="page-app-activities page-tabcontent ng-scope">
|
||||
<!-- ngIf: !activitiesReady -->
|
||||
<div class="middle-wrapper" ng-show="activitiesReady">
|
||||
<ul class="list-unstyled time-line">
|
||||
<li>
|
||||
<span class="dot"></span>
|
||||
<span class="filter ng-binding">版本更新</span>
|
||||
<span class="filter version-rollback ng-scope"></span>
|
||||
</li>
|
||||
<li>
|
||||
<div class="market-app-info">
|
||||
</div>
|
||||
</li>
|
||||
<li th:each="app,appStat : ${apps}">
|
||||
<div>
|
||||
<div class="directive-view-release">
|
||||
<i class="icon-upload-cloud2"></i>
|
||||
<b class="ng-binding">[[${app.version}]] (Build [[${app.buildVersion}]])</b>
|
||||
<div class="release-metainfo ng-hide">
|
||||
<small>
|
||||
<i class="icon-calendar"></i>
|
||||
<span class="ng-binding">[[${app.displayTime}]]</span>
|
||||
</small>
|
||||
</div>
|
||||
<div class="release-metainfo">
|
||||
<small>
|
||||
<i class="icon-calendar"></i>
|
||||
<span class="ng-binding">[[${app.displayTime}]]</span></small> ·
|
||||
<small class="ng-scope">[[${app.type}]]</small>
|
||||
<i class="ng-hide"> · </i>
|
||||
<small class="ng-binding ng-hide"></small>
|
||||
</div>
|
||||
<div class="release-actions">
|
||||
<button class="tooltip-top download-action" tooltip="下载原文件" th:value="${app.downloadURL}">
|
||||
<i class="icon-cloud-download"></i>
|
||||
<span class="ng-binding">[[${app.displaySize}]]</span>
|
||||
</button>
|
||||
<button class="preview" th:value="${app.previewURL}">
|
||||
<i class="icon-eye"></i>
|
||||
<span class="ng-binding">预览</span>
|
||||
</button>
|
||||
<button class="ng-scope app-delete" th:data="${app.id}" th:if="${appStat.index > 0}">
|
||||
<i class="icon-trash"></i>
|
||||
<span class="ng-binding">删除</span>
|
||||
</button>
|
||||
</div>
|
||||
<!-- uiView: -->
|
||||
<div data-ui-view="" class="ng-scope">
|
||||
<div id="info-panel" class="page-app-activities page-tabcontent apps-app-info ng-scope">
|
||||
<!-- ngIf: !activitiesReady -->
|
||||
<div class="middle-wrapper" ng-show="activitiesReady">
|
||||
<!-- 更新面板-->
|
||||
<ul id="app-activity-panel" class="list-unstyled time-line">
|
||||
<li>
|
||||
<span class="dot"></span>
|
||||
<span class="filter ng-binding">版本更新</span>
|
||||
<span class="filter version-rollback ng-scope"></span>
|
||||
</li>
|
||||
<li>
|
||||
<div class="market-app-info">
|
||||
</div>
|
||||
</li>
|
||||
<li th:each="app,appStat : ${apps}">
|
||||
<div>
|
||||
<div class="directive-view-release">
|
||||
<i class="icon-upload-cloud2"></i>
|
||||
<b class="ng-binding">[[${app.version}]] (Build [[${app.buildVersion}]])</b>
|
||||
<div class="release-metainfo ng-hide">
|
||||
<small>
|
||||
<i class="icon-calendar"></i>
|
||||
<span class="ng-binding">[[${app.displayTime}]]</span>
|
||||
</small>
|
||||
</div>
|
||||
<div class="release-metainfo">
|
||||
<small>
|
||||
<i class="icon-calendar"></i>
|
||||
<span class="ng-binding">[[${app.displayTime}]]</span></small> ·
|
||||
<small class="ng-scope">[[${app.type}]]</small>
|
||||
<i class="ng-hide"> · </i>
|
||||
<small class="ng-binding ng-hide"></small>
|
||||
</div>
|
||||
<div class="release-actions">
|
||||
<button class="tooltip-top download-action" tooltip="下载原文件" th:value="${app.downloadURL}">
|
||||
<i class="icon-cloud-download"></i>
|
||||
<span class="ng-binding">[[${app.displaySize}]]</span>
|
||||
</button>
|
||||
<button class="preview" th:value="${app.previewURL}">
|
||||
<i class="icon-eye"></i>
|
||||
<span class="ng-binding">预览</span>
|
||||
</button>
|
||||
<button class="ng-scope app-delete" th:data="${app.id}" th:if="${appStat.index> 0}">
|
||||
<i class="icon-trash"></i>
|
||||
<span class="ng-binding">删除</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="more ng-hide" ng-show="currentApp.releases.current_page < currentApp.releases.total_pages">
|
||||
<button ng-click="moreRelease()" class="ng-binding">显示更多版本</button></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li class="more ng-hide" ng-show="currentApp.releases.current_page < currentApp.releases.total_pages">
|
||||
<button ng-click="moreRelease()" class="ng-binding">显示更多版本</button></li>
|
||||
</ul>
|
||||
<!--信息面板-->
|
||||
<div id="app-info-panel" class="app-info-form ng-pristine ng-valid ng-valid-required ng-valid-pattern ng-hide">
|
||||
<div class="field app-id">
|
||||
<div class="left-label ng-binding">
|
||||
应用 ID
|
||||
</div>
|
||||
<div class="value">
|
||||
<input ng-model="currentApp.id" th:value="${package.id}" readonly="readonly" class="ng-pristine ng-untouched ng-valid">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field app-name">
|
||||
<div class="left-label ng-binding">
|
||||
应用名称
|
||||
</div>
|
||||
<div class="value">
|
||||
<input ng-model="currentApp.id" th:value="${package.name}" readonly="readonly" class="ng-pristine ng-untouched ng-valid"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field app-short">
|
||||
<div class="left-label ng-binding">
|
||||
短链接
|
||||
</div>
|
||||
<div class="value">
|
||||
<input ng-model="currentApp.id" th:value="${package.installPath}" readonly="readonly" class="ng-pristine ng-untouched ng-valid">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field app-id">
|
||||
<div class="left-label">
|
||||
应用图标
|
||||
</div>
|
||||
<div class="icon_select unploadIcon appicon" style="width: 100px; cursor: pointer">
|
||||
<img width="100" height="100" id="icon_img" style="border-radius: 17%" class="change_icon ng-isolate-scope" th:src="'/' + ${package.icon}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field app-deletion">
|
||||
<div class="left-label ng-binding">
|
||||
删除应用
|
||||
</div>
|
||||
<div class="value">
|
||||
<button id="delete-app" th:data="${package.id}" class="btn btn-danger btn-circle require-confirm">
|
||||
<span class="ng-scope">删除</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--集成面板-->
|
||||
<div id="app-integration-panel" class="providers ng-hide">
|
||||
<h2 class="ng-scope">消息推送</h2>
|
||||
<div class="item item-webhook ng-scope">
|
||||
<div class="logo pull-left Dingtalk">
|
||||
<img alt="Dingtalk" src="/images/ding_ding.png">
|
||||
</div>
|
||||
<div class="content">
|
||||
<p class="desc ng-binding">
|
||||
钉钉,是阿里巴巴集团专为企业打造的一个专业通讯、协同办公平台, 帮助企业降低沟通与管理成本,提升办公效率,让数千万企业提前进入到云和移动办公时代。
|
||||
</p>
|
||||
<div class="configrations">
|
||||
<a class="add-config">
|
||||
<i class="icon-plus"></i>
|
||||
</a>
|
||||
</div>
|
||||
<webhook-form-view id="webhook-form-view" class="ng-pristine ng-untouched ng-valid ng-isolate-scope ng-hide">
|
||||
<div id="webhookForm" class="ng-pristine ng-invalid ng-invalid-required ng-valid-url">
|
||||
<input class="ng-hide" th:value="${package.id}" name="appId" id="appId"/>
|
||||
<input class="ng-hide" name="id" id="webHookId"/>
|
||||
<input id="ding-ding-web-hook-name" class="config-name form-control ng-pristine ng-untouched ng-invalid ng-invalid-required" placeholder="配置名称" name="name" required=""/>
|
||||
<input id="ding-ding-web-hook-url" class="config-url form-control ng-pristine ng-untouched ng-invalid ng-invalid-required ng-valid-url" placeholder="Webhook url" type="url" name="url" required=""/>
|
||||
<button class="btn btn-lemon ng-binding ng-hide" disabled="disabled" onclick="update()" id="webHookUpdate">保存</button>
|
||||
<button class="btn btn-lemon ng-binding" disabled="disabled" onclick="add()" id="webHookAdd">添加</button>
|
||||
<button class="btn btn-link ng-hide" onclick="remove()" id="webHookRemove">
|
||||
<i class="icon-trash"></i>
|
||||
</button>
|
||||
<button class="btn btn-link ng-binding" id="webHookCancel">取消</button>
|
||||
<p class="url-invalid-tips ng-scope ng-hide">
|
||||
请输入正确的 URL 地址
|
||||
</p>
|
||||
</div>
|
||||
</webhook-form-view>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<script type="application/javascript">
|
||||
$(".download-action").click(function(){
|
||||
window.open($(this).val())
|
||||
})
|
||||
|
||||
$(".preview").click(function () {
|
||||
window.open($(this).val())
|
||||
})
|
||||
|
||||
|
||||
$(".app-delete").click(function () {
|
||||
var url = "/p/delete/" + $(this).attr("data");
|
||||
$.ajax({url:url,success:function(result){
|
||||
window.location.href=window.location.href
|
||||
window.location.reload
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
$("#js-app-short-copy-trigger").click(function(){
|
||||
new ClipboardJS('#js-app-short-copy-trigger', {
|
||||
text: function(trigger) {
|
||||
return trigger.getAttribute('value');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
</section>
|
||||
<script type="text/javascript" th:src="@{/js/list.js}"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user