fix: 🐛 ip归属地查询接口地址更新 (#168)

Co-authored-by: tk <fiyne1a@dingtalk.com>
This commit is contained in:
nsnail 2024-08-02 09:26:37 +08:00 committed by GitHub
parent e00c30c961
commit 4733adede5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 60 additions and 63 deletions

View File

@ -30,6 +30,18 @@ public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicReposit
set => Rpo.DbContextOptions.EnableCascadeSave = value;
}
/// <summary>
/// 导出实体
/// </summary>
protected async Task<IActionResult> ExportAsync<TQuery, TExport>( //
Func<QueryReq<TQuery>, ISelectGrouping<TEntity, TEntity>> selector, QueryReq<TQuery> query, string fileName
, Expression<Func<ISelectGroupingAggregate<TEntity, TEntity>, object>> listExp)
where TQuery : DataAbstraction, new()
{
var list = await selector(query).Take(Numbers.MAX_LIMIT_EXPORT).ToListAsync(listExp).ConfigureAwait(false);
return await GetExportFileStreamAsync<TExport>(fileName, list).ConfigureAwait(false);
}
/// <summary>
/// 导出实体
/// </summary>
@ -48,26 +60,7 @@ public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicReposit
? await select.ToListAsync().ConfigureAwait(false)
: await select.ToListAsync(listExp).ConfigureAwait(false);
var listTyped = list.Adapt<List<TExport>>();
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
var csv = new CsvWriter(writer, CultureInfo.InvariantCulture);
csv.WriteHeader<TExport>();
await csv.NextRecordAsync().ConfigureAwait(false);
foreach (var item in listTyped) {
csv.WriteRecord(item);
await csv.NextRecordAsync().ConfigureAwait(false);
}
await csv.FlushAsync().ConfigureAwait(false);
_ = stream.Seek(0, SeekOrigin.Begin);
App.HttpContext.Response.Headers.ContentDisposition
= new ContentDispositionHeaderValue(Chars.FLG_HTTP_HEADER_VALUE_ATTACHMENT) {
FileNameStar = $"{fileName}_{DateTime.Now:yyyy.MM.dd-HH.mm.ss}.csv"
}.ToString();
return new FileStreamResult(stream, Chars.FLG_HTTP_HEADER_VALUE_APPLICATION_OCTET_STREAM);
return await GetExportFileStreamAsync<TExport>(fileName, list).ConfigureAwait(false);
}
/// <summary>
@ -117,6 +110,31 @@ public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicReposit
}
#endif
private static async Task<IActionResult> GetExportFileStreamAsync<TExport>(string fileName, object list)
{
var listTyped = list.Adapt<List<TExport>>();
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
var csv = new CsvWriter(writer, CultureInfo.InvariantCulture);
csv.WriteHeader<TExport>();
await csv.NextRecordAsync().ConfigureAwait(false);
foreach (var item in listTyped) {
csv.WriteRecord(item);
await csv.NextRecordAsync().ConfigureAwait(false);
}
await csv.FlushAsync().ConfigureAwait(false);
_ = stream.Seek(0, SeekOrigin.Begin);
App.HttpContext.Response.Headers.ContentDisposition
= new ContentDispositionHeaderValue(Chars.FLG_HTTP_HEADER_VALUE_ATTACHMENT) {
FileNameStar = $"{fileName}_{DateTime.Now:yyyy.MM.dd-HH.mm.ss}.csv"
}.ToString();
return new FileStreamResult(stream, Chars.FLG_HTTP_HEADER_VALUE_APPLICATION_OCTET_STREAM);
}
private IUpdate<TEntity> BuildUpdate( //
TEntity entity //
, IEnumerable<string> includeFields //

View File

@ -19,6 +19,8 @@ public record CreateLoginLogReq : Sys_LoginLog, IRegister
{
var body = s.Detail.ResponseBody.ToObject<RestfulInfo<LoginRsp>>();
ContextUserToken userToken = null;
// ReSharper disable once InvertIf
if (body.Data?.AccessToken != null) {
try {
userToken = ContextUserToken.Create(body.Data.AccessToken);

View File

@ -10,7 +10,7 @@
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"ace-builds": "^1.35.2",
"ace-builds": "^1.35.4",
"aieditor": "^1.0.13",
"axios": "^1.7.2",
"clipboard": "^2.0.11",
@ -18,7 +18,7 @@
"cropperjs": "^1.6.2",
"crypto-js": "^4.2.0",
"echarts": "^5.5.1",
"element-plus": "^2.7.7",
"element-plus": "^2.7.8",
"json-bigint": "^1.0.0",
"json5-to-table": "^0.1.8",
"markdown-it": "^14.1.0",
@ -28,7 +28,7 @@
"qrcodejs2": "^0.0.2",
"sortablejs": "^1.15.2",
"vkbeautify": "^0.99.3",
"vue": "^3.4.31",
"vue": "^3.4.34",
"vue-i18n": "^9.13.1",
"vue-router": "^4.4.0",
"vue3-ace-editor": "^2.2.4",
@ -37,12 +37,12 @@
"vuex": "^4.1.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.0.5",
"@vitejs/plugin-vue": "^5.1.1",
"prettier": "^3.3.3",
"prettier-plugin-organize-attributes": "^1.0.0",
"sass": "^1.77.8",
"terser": "^5.31.3",
"vite": "^5.3.4"
"vite": "^5.3.5"
},
"browserslist": [
"> 1%",

View File

@ -1,30 +0,0 @@
<template>
<p>{{ ip ?? '-' }}</p>
<p style="overflow: hidden">{{ region ?? '-' }}</p>
</template>
<script>
import http from '@/utils/request'
export default {
emits: [],
props: ['ip'],
data() {
return {
region: null,
}
},
mounted() {},
created() {
if (this.ip) {
this.region = '...'
http.get(`http://ip.line92.xyz/?ip=${this.ip}`).then((x) => {
this.region = x.region
})
}
},
components: {},
computed: {},
methods: {},
}
</script>
<style scoped></style>

View File

@ -2,7 +2,7 @@
<form @keyup.enter="search" @submit.prevent="search" class="right-panel-search">
<el-date-picker
v-if="hasDate"
v-model="form.dy.createdTime"
v-model="form.dy[this.dateField]"
:end-placeholder="$t('结束日期')"
:format="dateFormat"
:range-separator="$t('至')"
@ -83,6 +83,7 @@ import vkbeautify from 'vkbeautify/index'
export default {
emits: ['search', 'reset'],
props: {
dateField: { type: String, default: 'createdTime' },
hasDate: { type: Boolean, default: true },
dateType: { type: String, default: 'daterange' },
dateFormat: { type: String, default: 'YYYY-MM-DD' },
@ -114,8 +115,8 @@ export default {
text: this.$t('后退一日'),
value: () => {
try {
const start = new Date(new Date(this.form.dy.createdTime[0]) - 3600 * 1000 * 24)
const end = new Date(new Date(this.form.dy.createdTime[1]) - 3600 * 1000 * 24)
const start = new Date(new Date(this.form.dy[this.dateField][0]) - 3600 * 1000 * 24)
const end = new Date(new Date(this.form.dy[this.dateField][1]) - 3600 * 1000 * 24)
return [start, end]
} catch {}
},
@ -356,8 +357,8 @@ export default {
text: this.$t('后退一时'),
value: () => {
try {
const start = new Date(new Date(this.form.dy.createdTime[0]) - 3600 * 1000)
const end = new Date(new Date(this.form.dy.createdTime[1]) - 3600 * 1000)
const start = new Date(new Date(this.form.dy[this.dateField][0]) - 3600 * 1000)
const end = new Date(new Date(this.form.dy[this.dateField][1]) - 3600 * 1000)
return [start, end]
} catch {}
},

View File

@ -24,7 +24,12 @@
</div>
<div class="sc-statistic-content">
<span v-if="prefix" class="sc-statistic-content-prefix">{{ prefix }}</span>
<span class="sc-statistic-content-value">{{ cmtValue }}</span>
<span class="sc-statistic-content-value">
<slot v-if="$slots.content" name="content"></slot>
<template v-else>
{{ cmtValue }}
</template>
</span>
<span v-if="suffix" class="sc-statistic-content-suffix">{{ suffix }}</span>
</div>
<div v-if="description || $slots.default" class="sc-statistic-description">

View File

@ -15,6 +15,7 @@
label: 'name',
}"
@node-click="click"
default-expand-all
node-key="id"
ref="dic">
<template #default="{ _, data }">

View File

@ -121,7 +121,7 @@ export default {
this.apis = []
const ips = data.data.rows?.map((x) => x.createdClientIp) ?? []
const res = await Promise.all([
ips && ips.length > 0 ? http.get(`http://ip.line92.xyz/?ip=${ips.join('&ip=')}`) : new Promise((x) => x({ data: [] })),
ips && ips.length > 0 ? http.get(`https://ip.tools92.top/?ip=${ips.join('&ip=')}`) : new Promise((x) => x({ data: [] })),
])
this.ips = res[0]
},

View File

@ -239,7 +239,7 @@ export default {
})
: new Promise((x) => x({ data: [] })),
ips && ips.length > 0 ? http.get(`http://ip.line92.xyz/?ip=${ips.join('&ip=')}`) : new Promise((x) => x({ data: [] })),
ips && ips.length > 0 ? http.get(`https://ip.tools92.top/?ip=${ips.join('&ip=')}`) : new Promise((x) => x({ data: [] })),
])
this.owners = res[0].data
this.apis = res[1].data