管理端全部功能跑通

This commit is contained in:
robin
2026-02-27 10:35:22 +08:00
parent 4d275c921d
commit 150799f41d
263 changed files with 22664 additions and 4053 deletions

View File

@@ -1,4 +1,4 @@
<first-menu>
<menu-item href="/httpdns/apps" code="index">应用列表</menu-item>
<a href="" class="item" @click.prevent="createApp()">[添加应用]</a>
</first-menu>
<a href="/httpdns/apps/create" class="item">[添加应用]</a>
</first-menu>

View File

@@ -1,8 +1,7 @@
{$layout "layout_popup"}
{$layout}
{$template "menu"}
<h3>添加应用</h3>
<form method="post" class="ui form" data-tea-action="$">
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
<csrf-token></csrf-token>
<table class="ui table definition selectable">
<tr>
@@ -35,13 +34,10 @@
<tr>
<td>所属用户</td>
<td>
<select class="ui dropdown" name="userId">
<option value="0">[平台自用 / 不指定]</option>
<option v-for="user in users" :value="user.id">{{user.name}} ({{user.username}})</option>
</select>
<p class="comment">可分配给指定租户用户;留空表示平台管理员自用。</p>
<user-selector></user-selector>
<p class="comment">可以选择当前应用所属的平台用户。</p>
</td>
</tr>
</table>
<submit-btn></submit-btn>
</form>
</form>

Binary file not shown.

View File

@@ -10,7 +10,12 @@
teaweb.popup("/httpdns/apps/customRecords/createPopup?appId=" + this.app.id + "&domainId=" + this.domain.id, {
width: "42em",
height: "33em",
title: "新增自定义解析规则"
title: "新增自定义解析规则",
callback: function () {
teaweb.success("保存成功", function () {
teaweb.reload();
});
}
});
};
@@ -21,7 +26,12 @@
teaweb.popup("/httpdns/apps/customRecords/createPopup?appId=" + this.app.id + "&domainId=" + this.domain.id + "&recordId=" + recordId, {
width: "42em",
height: "33em",
title: "编辑自定义解析规则"
title: "编辑自定义解析规则",
callback: function () {
teaweb.success("保存成功", function () {
teaweb.reload();
});
}
});
};

View File

@@ -1,4 +1,4 @@
{$layout "layout_popup"}
{$layout "layout_popup"}
<style>
.httpdns-inline-actions {
@@ -37,7 +37,7 @@
<h3 v-if="isEditing">编辑自定义解析规则</h3>
<h3 v-else>新增自定义解析规则</h3>
<form method="post" class="ui form" data-tea-action="$">
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
<csrf-token></csrf-token>
<input type="hidden" name="appId" :value="app.id" />
<input type="hidden" name="domainId" :value="domain.id" />
@@ -55,7 +55,7 @@
<td class="title">规则名称 *</td>
<td>
<input type="text" name="ruleName" maxlength="50" v-model="record.ruleName" ref="focus" />
<p class="comment">例如:上海电信灰度-v2</p>
<p class="comment">例如:上海电信灰度-v2</p>
</td>
</tr>
<tr>
@@ -105,7 +105,7 @@
<div style="margin-bottom: 0.5em;">
<div class="ui checkbox" style="margin-bottom: 0.5em;">
<input type="checkbox" name="weightEnabled" value="1" v-model="record.weightEnabled" />
<label>启权重调度设置</label>
<label>权重调度设置</label>
</div>
</div>
@@ -157,4 +157,4 @@
</table>
<submit-btn></submit-btn>
</form>
</form>

View File

@@ -1,4 +1,4 @@
Tea.context(function () {
Tea.context(function () {
var vm = this;
if (typeof vm.record == "undefined" || vm.record == null) {

View File

@@ -0,0 +1,36 @@
# Android SDK
## 初始化
```java
new InitConfig.Builder()
.setContext(context)
.setPrimaryServiceHost("httpdns-a.example.com")
.setBackupServiceHost("httpdns-b.example.com")
.setServicePort(443)
.setSecretKey("your-sign-secret")
.setEnableHttps(true)
.buildFor("app1f1ndpo9");
```
## 解析
```java
HTTPDNSResult result = httpDnsService.getHttpDnsResultForHostSyncNonBlocking(
"api.business.com",
RequestIpType.auto,
null,
null
);
```
## 官方业务适配器
```java
HttpDnsHttpAdapter adapter = HttpDns.buildHttpClientAdapter(httpDnsService);
HttpDnsAdapterResponse resp = adapter.execute(
new HttpDnsAdapterRequest("GET", "https://api.business.com/v1/ping")
);
```
固定策略IP 直连 + 空 SNI + Host=真实域名,不回退到带 SNI。

View File

@@ -0,0 +1,35 @@
# Flutter SDK
## 初始化
```dart
await AliyunHttpdns.init(
appId: 'app1f1ndpo9',
primaryServiceHost: 'httpdns-a.example.com',
backupServiceHost: 'httpdns-b.example.com',
servicePort: 443,
secretKey: 'your-sign-secret',
);
await AliyunHttpdns.build();
```
## 解析
```dart
final result = await AliyunHttpdns.resolveHostSyncNonBlocking(
'api.business.com',
ipType: 'both',
);
```
## 官方业务适配器
```dart
final adapter = AliyunHttpdns.createHttpAdapter();
final resp = await adapter.request(
Uri.parse('https://api.business.com/v1/ping'),
method: 'GET',
);
```
固定策略IP 直连 + 空 SNI + Host=真实域名,不回退到带 SNI。

View File

@@ -0,0 +1,31 @@
# iOS SDK
## 初始化
```objc
HttpdnsEdgeService *service = [[HttpdnsEdgeService alloc]
initWithAppId:@"app1f1ndpo9"
primaryServiceHost:@"httpdns-a.example.com"
backupServiceHost:@"httpdns-b.example.com"
servicePort:443
signSecret:@"your-sign-secret"];
```
## 解析
```objc
[service resolveHost:@"api.business.com" queryType:@"A" completion:^(HttpdnsEdgeResolveResult * _Nullable result, NSError * _Nullable error) {
// result.ipv4s / result.ipv6s
}];
```
## 官方业务适配器
```objc
NSURL *url = [NSURL URLWithString:@"https://api.business.com/v1/ping"];
[service requestURL:url method:@"GET" headers:nil body:nil completion:^(NSData * _Nullable data, NSHTTPURLResponse * _Nullable response, NSError * _Nullable error) {
// handle
}];
```
固定策略IP 直连 + 空 SNI + Host=真实域名,不回退到带 SNI。

View File

@@ -36,7 +36,12 @@
teaweb.popup("/httpdns/apps/domains/createPopup?appId=" + this.app.id, {
height: "24em",
width: "46em",
title: "添加域名"
title: "添加域名",
callback: function () {
teaweb.success("保存成功", function () {
teaweb.reload();
});
}
});
};

View File

@@ -2,8 +2,9 @@
<h3>添加域名</h3>
<form method="post" class="ui form" data-tea-action="$">
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
<csrf-token></csrf-token>
<input type="hidden" name="appId" :value="app.id" />
<table class="ui table definition selectable">
<tr>
<td class="title">域名 *</td>

View File

@@ -54,7 +54,7 @@
<code>{{app.appId}}</code>
<copy-icon :text="app.appId"></copy-icon>
</td>
<td><a :href="'/httpdns/apps/domains?appId=' + app.id">{{app.domainCount}}</a></td>
<td class="center"><a :href="'/httpdns/apps/domains?appId=' + app.id">{{app.domainCount}}</a></td>
<td class="center">
<label-on :v-is-on="app.isOn"></label-on>
</td>

View File

@@ -4,10 +4,6 @@ Tea.context(function () {
}
this.createApp = function () {
teaweb.popup("/httpdns/apps/createPopup", {
height: "26em",
width: "48em",
title: "添加应用"
});
window.location = "/httpdns/apps/create";
};
});

View File

@@ -34,6 +34,12 @@
<div class="item"><strong>SDK 集成</strong></div>
</second-menu>
<div style="margin-top: 1em; text-align: right">
<a class="ui button tiny blue" :href="'/httpdns/apps/sdk/upload?appId=' + app.id">
<i class="icon upload"></i> 上传 SDK/文档
</a>
</div>
<div class="ui three stackable cards httpdns-sdk-cards">
<div class="card">
<div class="content">
@@ -43,8 +49,8 @@
</div>
<div class="extra content">
<div class="httpdns-sdk-actions">
<a class="ui button compact mini basic" href="javascript:;"><i class="icon download"></i> 下载 SDK</a>
<a class="ui button compact mini basic" href="javascript:;"><i class="icon book"></i> 集成文档</a>
<a class="ui button compact mini basic" href="/httpdns/apps/sdk/download?platform=android"><i class="icon download"></i> 下载 SDK</a>
<a class="ui button compact mini basic" href="/httpdns/apps/sdk/doc?platform=android"><i class="icon book"></i> 下载文档</a>
</div>
</div>
</div>
@@ -57,8 +63,8 @@
</div>
<div class="extra content">
<div class="httpdns-sdk-actions">
<a class="ui button compact mini basic" href="javascript:;"><i class="icon download"></i> 下载 SDK</a>
<a class="ui button compact mini basic" href="javascript:;"><i class="icon book"></i> 集成文档</a>
<a class="ui button compact mini basic" href="/httpdns/apps/sdk/download?platform=ios"><i class="icon download"></i> 下载 SDK</a>
<a class="ui button compact mini basic" href="/httpdns/apps/sdk/doc?platform=ios"><i class="icon book"></i> 下载文档</a>
</div>
</div>
</div>
@@ -71,8 +77,8 @@
</div>
<div class="extra content">
<div class="httpdns-sdk-actions">
<a class="ui button compact mini basic" href="javascript:;"><i class="icon download"></i> 下载 SDK</a>
<a class="ui button compact mini basic" href="javascript:;"><i class="icon book"></i> 集成文档</a>
<a class="ui button compact mini basic" href="/httpdns/apps/sdk/download?platform=flutter"><i class="icon download"></i> 下载 SDK</a>
<a class="ui button compact mini basic" href="/httpdns/apps/sdk/doc?platform=flutter"><i class="icon book"></i> 下载文档</a>
</div>
</div>
</div>

View File

@@ -0,0 +1,93 @@
{$layout}
<second-menu>
<a class="item" :href="'/httpdns/apps/domains?appId=' + app.id">{{app.name}}</a>
<span class="item disabled" style="padding-left: 0; padding-right: 0">&raquo;</span>
<a class="item" :href="'/httpdns/apps/sdk?appId=' + app.id">SDK 集成</a>
<span class="item disabled" style="padding-left: 0; padding-right: 0">&raquo;</span>
<div class="item"><strong>上传 SDK</strong></div>
</second-menu>
<form method="post"
enctype="multipart/form-data"
class="ui form"
data-tea-action="$"
data-tea-timeout="300"
data-tea-before="beforeUpload"
data-tea-done="doneUpload"
data-tea-success="successUpload">
<csrf-token></csrf-token>
<input type="hidden" name="appId" :value="app.id"/>
<table class="ui table selectable definition">
<tr>
<td class="title">平台 *</td>
<td>
<select name="platform" class="ui dropdown auto-width" v-model="platform">
<option value="android">Android</option>
<option value="ios">iOS</option>
<option value="flutter">Flutter</option>
</select>
</td>
</tr>
<tr>
<td class="title">版本号 *</td>
<td>
<input type="text" name="version" v-model="version" maxlength="32"/>
<p class="comment">默认 `1.0.0`。同平台上传会覆盖“最新版本”下载内容。</p>
</td>
</tr>
<tr>
<td class="title">SDK 包</td>
<td>
<input type="file" name="sdkFile" accept=".zip"/>
<p class="comment">支持 zip 包,例如 `httpdns-sdk-android.zip`。</p>
</td>
</tr>
<tr>
<td class="title">集成文档</td>
<td>
<input type="file" name="docFile" accept=".md,text/markdown"/>
<p class="comment">支持 Markdown 文件(`.md`)。</p>
</td>
</tr>
</table>
<div v-if="isUploading" class="ui message blue">
正在上传,请稍候...
</div>
<submit-btn v-show="!isUploading">上传并生效</submit-btn>
<button v-if="isUploading" class="ui button disabled" type="button">上传中...</button>
<a class="ui button" :href="'/httpdns/apps/sdk?appId=' + app.id">返回</a>
</form>
<h4 style="margin-top: 1.5em">已上传文件</h4>
<table class="ui table selectable celled" v-if="uploadedFiles.length > 0">
<thead>
<tr>
<th>平台</th>
<th>类型</th>
<th>版本</th>
<th>文件名</th>
<th>大小</th>
<th>更新时间</th>
<th class="one wide">操作</th>
</tr>
</thead>
<tbody>
<tr v-for="file in uploadedFiles">
<td>{{file.platform}}</td>
<td>{{file.fileType}}</td>
<td>{{file.version}}</td>
<td>{{file.name}}</td>
<td>{{file.sizeText}}</td>
<td>{{file.updatedAt}}</td>
<td><a href="" @click.prevent="deleteUploadedFile(file.name)">删除</a></td>
</tr>
</tbody>
</table>
<div class="ui message" v-else>
暂无上传记录。
</div>

View File

@@ -0,0 +1,39 @@
Tea.context(function () {
this.platform = "android";
this.version = this.defaultVersion || "1.0.0";
this.isUploading = false;
if (!Array.isArray(this.uploadedFiles)) {
this.uploadedFiles = [];
}
this.beforeUpload = function () {
this.isUploading = true;
};
this.doneUpload = function () {
this.isUploading = false;
};
this.successUpload = function () {
teaweb.success("上传成功", function () {
window.location = "/httpdns/apps/sdk?appId=" + this.app.id;
}.bind(this));
};
this.deleteUploadedFile = function (filename) {
let that = this;
teaweb.confirm("确定要删除文件 " + filename + " 吗?", function () {
that.$post("/httpdns/apps/sdk/upload/delete")
.params({
appId: that.app.id,
filename: filename
})
.success(function () {
teaweb.success("删除成功", function () {
window.location.reload();
});
});
});
};
});