feat: 添加部分修改
This commit is contained in:
parent
54c60ab607
commit
3916aa0bab
@ -16,7 +16,7 @@ services.AddSwaggerGen();
|
||||
services.AddHangfire(configuration =>
|
||||
{
|
||||
configuration.UseConsole();
|
||||
configuration.UseRedisStorage("172.16.127.100:34188,defaultDatabase=15,connectTimeout=100000,syncTimeout=100000,connectRetry=50", new RedisStorageOptions { Db = 10 });
|
||||
configuration.UseRedisStorage("192.168.1.148:6379,defaultDatabase=15,connectTimeout=100000,syncTimeout=100000,connectRetry=50", new RedisStorageOptions { Db = 15 });
|
||||
});
|
||||
services.AddHangfireServer(option =>
|
||||
{
|
||||
|
||||
16
RedisDemo/Controller/TestController.cs
Normal file
16
RedisDemo/Controller/TestController.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace RedisDemo.Controller
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class TestController : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
public async Task<string> Test(string str) {
|
||||
Console.WriteLine($"这是参数:{str}");
|
||||
return "这是回参";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8,7 +8,7 @@
|
||||
"applicationUrl": "http://localhost:5030;http://0.0.0.0:5030;",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||
"Redis:Connection": "172.16.127.100:34188,defaultDatabase=14,connectTimeout=100000,syncTimeout=100000,connectRetry=50"
|
||||
"Redis:Connection": "192.168.1.148:6379,Password=abc-123,defaultDatabase=14,connectTimeout=100000,syncTimeout=100000,connectRetry=50"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
485
SelfUseUtil/AMap.cs
Normal file
485
SelfUseUtil/AMap.cs
Normal file
@ -0,0 +1,485 @@
|
||||
using NewLife.Data;
|
||||
using NewLife.Map.Models;
|
||||
using NewLife.Map;
|
||||
using NewLife;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using NewLife.Serialization;
|
||||
using SelfUseUtil.Model;
|
||||
|
||||
namespace SelfUseUtil
|
||||
{
|
||||
public class AMap : Map, IMap
|
||||
{
|
||||
private readonly string[] _KeyWords = new string[4] { "TOO_FREQUENT", "LIMIT", "NOMATCH", "RECYCLED" };
|
||||
|
||||
//
|
||||
// 摘要:
|
||||
// 高德地图
|
||||
public AMap()
|
||||
{
|
||||
base.Server = "http://restapi.amap.com";
|
||||
base.KeyName = "key";
|
||||
}
|
||||
|
||||
//
|
||||
// 摘要:
|
||||
// 远程调用
|
||||
//
|
||||
// 参数:
|
||||
// url:
|
||||
// 目标Url
|
||||
//
|
||||
// result:
|
||||
// 结果字段
|
||||
protected override async Task<T> InvokeAsync<T>(string url, string? result)
|
||||
{
|
||||
IDictionary<string, object> dictionary = await base.InvokeAsync<IDictionary<string, object>>(url, result);
|
||||
if (dictionary == null || dictionary.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (dictionary["status"].ToInt() != 1)
|
||||
{
|
||||
string text = dictionary["info"]?.ToString() ?? "";
|
||||
if (!base.LastKey.IsNullOrEmpty() && IsValidKey(text))
|
||||
{
|
||||
RemoveKey(base.LastKey, DateTime.Now.AddHours(1.0));
|
||||
}
|
||||
|
||||
if (base.ThrowException)
|
||||
{
|
||||
throw new Exception(text);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (result.IsNullOrEmpty())
|
||||
{
|
||||
return (T)dictionary;
|
||||
}
|
||||
|
||||
// 👉 把 dictionary[result] 转为 JSON 再反序列化
|
||||
var json = Newtonsoft.Json.JsonConvert.SerializeObject(dictionary[result]);
|
||||
return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(json);
|
||||
}
|
||||
|
||||
//
|
||||
// 摘要:
|
||||
// 查询地址的经纬度坐标
|
||||
//
|
||||
// 参数:
|
||||
// address:
|
||||
//
|
||||
// city:
|
||||
//
|
||||
// coordtype:
|
||||
protected async Task<IDictionary<string, object>?> GetGeocoderAsync(string address, string? city = null, string? coordtype = null)
|
||||
{
|
||||
if (address.IsNullOrEmpty())
|
||||
{
|
||||
throw new ArgumentNullException("address");
|
||||
}
|
||||
|
||||
address = HttpUtility.UrlEncode(address);
|
||||
city = HttpUtility.UrlEncode(city);
|
||||
string url = "http://restapi.amap.com/v3/geocode/geo?address=" + address + "&city=" + city + "&output=json";
|
||||
return (await InvokeAsync<IList<object>>(url, "geocodes"))?.FirstOrDefault() as IDictionary<string, object>;
|
||||
}
|
||||
|
||||
//
|
||||
// 摘要:
|
||||
// 查询地址获取坐标
|
||||
//
|
||||
// 参数:
|
||||
// address:
|
||||
// 地址
|
||||
//
|
||||
// city:
|
||||
// 城市
|
||||
//
|
||||
// coordtype:
|
||||
//
|
||||
// formatAddress:
|
||||
// 是否格式化地址。高德地图默认已经格式化地址
|
||||
public async Task<GeoAddress?> GetGeoAsync(string address, string? city = null, string? coordtype = null, bool formatAddress = false)
|
||||
{
|
||||
IDictionary<string, object> rs = await GetGeocoderAsync(address, city);
|
||||
if (rs == null || rs.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
GeoAddress geo = new GeoAddress
|
||||
{
|
||||
Location = new GeoPoint(rs["location"] as string)
|
||||
};
|
||||
rs.Remove("location");
|
||||
new JsonReader().ToObject(rs, null, geo);
|
||||
geo.Code = rs["adcode"].ToInt();
|
||||
if (rs["township"] is IList<object> list && list.Count > 0)
|
||||
{
|
||||
geo.Township = list[0]?.ToString() ?? "";
|
||||
}
|
||||
|
||||
if (rs["number"] is IList<object> list2 && list2.Count > 0)
|
||||
{
|
||||
geo.StreetNumber = list2[0]?.ToString() ?? "";
|
||||
}
|
||||
|
||||
if (formatAddress)
|
||||
{
|
||||
GeoAddress geoAddress = await GetReverseGeoAsync(geo.Location, "gcj02");
|
||||
if (geoAddress != null)
|
||||
{
|
||||
geo = geoAddress;
|
||||
if (geo.Level.IsNullOrEmpty())
|
||||
{
|
||||
geo.Level = rs["level"]?.ToString() ?? "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string text = rs["formatted_address"]?.ToString() ?? "";
|
||||
if (!text.IsNullOrEmpty() && (geo.Address.IsNullOrEmpty() || geo.Address.Length < text.Length))
|
||||
{
|
||||
geo.Address = text;
|
||||
}
|
||||
|
||||
TrimAddress(geo);
|
||||
return geo;
|
||||
}
|
||||
|
||||
private static void TrimAddress(GeoAddress geo)
|
||||
{
|
||||
if (!geo.Address.IsNullOrEmpty())
|
||||
{
|
||||
geo.Address = geo.Address.Replace("|", null);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 摘要:
|
||||
// 根据坐标获取地址
|
||||
//
|
||||
// 参数:
|
||||
// point:
|
||||
//
|
||||
// coordtype:
|
||||
//
|
||||
// 言论:
|
||||
// http://lbs.amap.com/api/webservice/guide/api/georegeo/#regeo
|
||||
protected async Task<IDictionary<string, object>> GetReverseGeocoderAsync(GeoPoint point, string? coordtype)
|
||||
{
|
||||
if (point.Longitude < 0.1 || point.Latitude < 0.1)
|
||||
{
|
||||
throw new ArgumentNullException("point");
|
||||
}
|
||||
|
||||
string url = $"http://restapi.amap.com/v3/geocode/regeo?location={point.Longitude},{point.Latitude}&extensions=base&output=json";
|
||||
return await InvokeAsync<IDictionary<string, object>>(url, "regeocode");
|
||||
}
|
||||
|
||||
//
|
||||
// 摘要:
|
||||
// 根据坐标获取地址
|
||||
//
|
||||
// 参数:
|
||||
// point:
|
||||
//
|
||||
// coordtype:
|
||||
// 坐标系
|
||||
public async Task<GeoAddress?> GetReverseGeoAsync(GeoPoint point, string? coordtype)
|
||||
{
|
||||
IDictionary<string, object> dictionary = await GetReverseGeocoderAsync(point, coordtype);
|
||||
if (dictionary == null || dictionary.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
GeoAddress geoAddress = new GeoAddress
|
||||
{
|
||||
Address = (dictionary["formatted_address"]?.ToString() ?? ""),
|
||||
Location = point
|
||||
};
|
||||
if (dictionary["addressComponent"] is IDictionary<string, object> dictionary2)
|
||||
{
|
||||
new JsonReader().ToObject(dictionary2, null, geoAddress);
|
||||
if (dictionary2.TryGetValue("city", out var value) && !(value is string))
|
||||
{
|
||||
geoAddress.City = null;
|
||||
}
|
||||
|
||||
if (dictionary2.TryGetValue("streetNumber", out value) && !(value is string))
|
||||
{
|
||||
geoAddress.StreetNumber = null;
|
||||
}
|
||||
|
||||
geoAddress.Code = dictionary2["adcode"].ToInt();
|
||||
geoAddress.Township = null;
|
||||
geoAddress.Towncode = 0;
|
||||
string text = "";
|
||||
if (dictionary2["township"] is string township)
|
||||
{
|
||||
geoAddress.Township = township;
|
||||
}
|
||||
|
||||
if (dictionary2["towncode"] is string text2)
|
||||
{
|
||||
text = text2;
|
||||
}
|
||||
|
||||
if (!text.IsNullOrEmpty() && text.Length > 9)
|
||||
{
|
||||
text = text.TrimEnd("000");
|
||||
}
|
||||
|
||||
geoAddress.Towncode = text.ToInt();
|
||||
if (dictionary2["streetNumber"] is IDictionary<string, object> dictionary3 && dictionary3.Count > 0)
|
||||
{
|
||||
if (dictionary3["street"] is IList<object> list && list.Count > 0)
|
||||
{
|
||||
geoAddress.Street = list[0]?.ToString() ?? "";
|
||||
}
|
||||
else
|
||||
{
|
||||
geoAddress.Street = dictionary3["street"]?.ToString() ?? "";
|
||||
}
|
||||
|
||||
if (dictionary3["number"] is IList<object> list2 && list2.Count > 0)
|
||||
{
|
||||
geoAddress.StreetNumber = list2[0]?.ToString() ?? "";
|
||||
}
|
||||
else
|
||||
{
|
||||
geoAddress.StreetNumber = dictionary3["number"]?.ToString() ?? "";
|
||||
}
|
||||
|
||||
if (geoAddress.Title.IsNullOrEmpty())
|
||||
{
|
||||
if (!dictionary3.TryGetValue("direction", out var value2))
|
||||
{
|
||||
value2 = "";
|
||||
}
|
||||
|
||||
if (dictionary3.TryGetValue("distance", out var value3))
|
||||
{
|
||||
value3 = Math.Round(value3.ToDouble(), 0) + "米";
|
||||
}
|
||||
|
||||
geoAddress.Title = $"{geoAddress.Province}{geoAddress.City}{geoAddress.District}{geoAddress.Township}{geoAddress.Street}{geoAddress.StreetNumber}{value2}{value3}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
geoAddress.Location = point;
|
||||
TrimAddress(geoAddress);
|
||||
return geoAddress;
|
||||
}
|
||||
|
||||
//
|
||||
// 摘要:
|
||||
// 计算距离和驾车时间
|
||||
//
|
||||
// 参数:
|
||||
// origin:
|
||||
//
|
||||
// destination:
|
||||
//
|
||||
// coordtype:
|
||||
//
|
||||
// type:
|
||||
// 路径计算的方式和方法
|
||||
//
|
||||
// 言论:
|
||||
// http://lbs.amap.com/api/webservice/guide/api/direction type: 0:直线距离 1:驾车导航距离(仅支持国内坐标)。
|
||||
// 必须指出,当为1时会考虑路况,故在不同时间请求返回结果可能不同。 此策略和driving接口的 strategy = 4策略一致 2:公交规划距离(仅支持同城坐标)
|
||||
// 3:步行规划距离(仅支持5km之间的距离) distance 路径距离,单位:米 duration 预计行驶时间,单位:秒
|
||||
public async Task<Driving?> GetDistanceAsync(GeoPoint origin, GeoPoint destination, string? coordtype, int type = 1)
|
||||
{
|
||||
if (origin == null || (origin.Longitude < 1.0 && origin.Latitude < 1.0))
|
||||
{
|
||||
throw new ArgumentNullException("origin");
|
||||
}
|
||||
|
||||
if (destination == null || (destination.Longitude < 1.0 && destination.Latitude < 1.0))
|
||||
{
|
||||
throw new ArgumentNullException("destination");
|
||||
}
|
||||
|
||||
if (type <= 0)
|
||||
{
|
||||
type = 1;
|
||||
}
|
||||
|
||||
string url = $"http://restapi.amap.com/v3/distance?origins={origin.Longitude},{origin.Latitude}&destination={destination.Longitude},{destination.Latitude}&type={type}&output=json";
|
||||
IList<object> list = await InvokeAsync<IList<object>>(url, "results");
|
||||
if (list == null || list.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!(list.FirstOrDefault() is IDictionary<string, object> dictionary))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Driving
|
||||
{
|
||||
Distance = dictionary["distance"].ToInt(),
|
||||
Duration = dictionary["duration"].ToInt()
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// 摘要:
|
||||
// 计算距离和驾车时间
|
||||
//
|
||||
// 参数:
|
||||
// origin:
|
||||
//
|
||||
// destination:
|
||||
//
|
||||
// coordtype:
|
||||
//
|
||||
// type:
|
||||
// 路径计算的方式和方法
|
||||
//
|
||||
// 言论:
|
||||
// http://lbs.amap.com/api/webservice/guide/api/direction type: 0:直线距离 1:驾车导航距离(仅支持国内坐标)。
|
||||
// 必须指出,当为1时会考虑路况,故在不同时间请求返回结果可能不同。 此策略和driving接口的 strategy = 4策略一致 2:公交规划距离(仅支持同城坐标)
|
||||
// 3:步行规划距离(仅支持5km之间的距离) distance 路径距离,单位:米 duration 预计行驶时间,单位:秒
|
||||
public async Task<DrivingEx?> GetDistanceExAsync(GeoPoint origin, GeoPoint destination, string? coordtype, int type = 1)
|
||||
{
|
||||
if (origin == null || (origin.Longitude < 1.0 && origin.Latitude < 1.0))
|
||||
{
|
||||
throw new ArgumentNullException("origin");
|
||||
}
|
||||
|
||||
if (destination == null || (destination.Longitude < 1.0 && destination.Latitude < 1.0))
|
||||
{
|
||||
throw new ArgumentNullException("destination");
|
||||
}
|
||||
|
||||
if (type <= 0)
|
||||
{
|
||||
type = 1;
|
||||
}
|
||||
|
||||
string url = $"https://restapi.amap.com/v5/direction/driving?origin={origin.Longitude},{origin.Latitude}&destination={destination.Longitude},{destination.Latitude}&key=c7591c54f7443323b41ec4c0f315acf5&output=json&show_fields=cost,polyline";
|
||||
var route = await InvokeAsync<Route>(url, "route");
|
||||
var list = route.paths;
|
||||
if (route.paths == null || route.paths.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new DrivingEx
|
||||
{
|
||||
Distance = route.paths[0].distance.ToInt(),
|
||||
Duration = route.paths[0].cost.duration.ToInt(),
|
||||
Steps = route.paths[0].steps
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// 摘要:
|
||||
// 行政区划
|
||||
//
|
||||
// 参数:
|
||||
// keywords:
|
||||
// 查询关键字
|
||||
//
|
||||
// subdistrict:
|
||||
// 设置显示下级行政区级数
|
||||
//
|
||||
// code:
|
||||
// 按照指定行政区划进行过滤,填入后则只返回该省/直辖市信息
|
||||
//
|
||||
// 言论:
|
||||
// http://lbs.amap.com/api/webservice/guide/api/district
|
||||
public async Task<IList<GeoArea>> GetAreaAsync(string keywords, int subdistrict = 1, int code = 0)
|
||||
{
|
||||
if (keywords.IsNullOrEmpty())
|
||||
{
|
||||
throw new ArgumentNullException("keywords");
|
||||
}
|
||||
|
||||
keywords = HttpUtility.UrlEncode(keywords);
|
||||
string url = $"http://restapi.amap.com/v3/config/district?keywords={keywords}&subdistrict={subdistrict}&filter={code}&extensions=base&output=json";
|
||||
IList<object> list = await InvokeAsync<IList<object>>(url, "districts");
|
||||
if (list == null || list.Count == 0)
|
||||
{
|
||||
return new List<GeoArea>();
|
||||
}
|
||||
|
||||
if (!(list.FirstOrDefault() is IDictionary<string, object> geo))
|
||||
{
|
||||
return new List<GeoArea>();
|
||||
}
|
||||
|
||||
return GetArea(geo, 0);
|
||||
}
|
||||
|
||||
private IList<GeoArea> GetArea(IDictionary<string, object> geo, int parentCode)
|
||||
{
|
||||
if (geo == null || geo.Count == 0)
|
||||
{
|
||||
return new List<GeoArea>();
|
||||
}
|
||||
|
||||
List<GeoArea> list = new List<GeoArea>();
|
||||
GeoArea geoArea = new GeoArea();
|
||||
new JsonReader().ToObject(geo, null, geoArea);
|
||||
geoArea.Code = geo["adcode"].ToInt();
|
||||
if (parentCode > 0)
|
||||
{
|
||||
geoArea.ParentCode = parentCode;
|
||||
}
|
||||
|
||||
list.Add(geoArea);
|
||||
if (geo["districts"] is IList<object> list2 && list2.Count > 0)
|
||||
{
|
||||
foreach (object item in list2)
|
||||
{
|
||||
if (item is IDictionary<string, object> geo2)
|
||||
{
|
||||
IList<GeoArea> area = GetArea(geo2, geoArea.Code);
|
||||
if (area != null && area.Count > 0)
|
||||
{
|
||||
list.AddRange(area);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
//
|
||||
// 摘要:
|
||||
// 是否无效Key。可能禁用或超出限制
|
||||
//
|
||||
// 参数:
|
||||
// result:
|
||||
protected override bool IsValidKey(string result)
|
||||
{
|
||||
if (result.IsNullOrEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_KeyWords.Any(result.Contains))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.IsValidKey(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
542
SelfUseUtil/BaiduMap.cs
Normal file
542
SelfUseUtil/BaiduMap.cs
Normal file
@ -0,0 +1,542 @@
|
||||
using NewLife.Data;
|
||||
using NewLife.Map.Models;
|
||||
using NewLife.Map;
|
||||
using NewLife;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using NewLife.Serialization;
|
||||
|
||||
namespace SelfUseUtil
|
||||
{
|
||||
//
|
||||
// 摘要:
|
||||
// 百度地图
|
||||
//
|
||||
// 言论:
|
||||
// 参考手册 https://lbsyun.baidu.com/index.php?title=webapi
|
||||
[DisplayName("百度地图")]
|
||||
public class BaiduMap : Map, IMap
|
||||
{
|
||||
private static readonly List<string> _coordTypes = new List<string> { "", "wgs84ll", "sougou", "gcj02ll", "gcj02mc", "bd09ll", "bd09mc", "amap", "gps" };
|
||||
|
||||
//
|
||||
// 摘要:
|
||||
// 高德地图
|
||||
public BaiduMap()
|
||||
{
|
||||
base.Server = "https://api.map.baidu.com";
|
||||
base.KeyName = "ak";
|
||||
}
|
||||
|
||||
//
|
||||
// 摘要:
|
||||
// 远程调用
|
||||
//
|
||||
// 参数:
|
||||
// url:
|
||||
// 目标Url
|
||||
//
|
||||
// result:
|
||||
// 结果字段
|
||||
protected override async Task<T> InvokeAsync<T>(string url, string? result)
|
||||
{
|
||||
IDictionary<string, object> dictionary = await base.InvokeAsync<IDictionary<string, object>>(url, result);
|
||||
if (dictionary == null || dictionary.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int num = dictionary["status"].ToInt();
|
||||
if (num != 0)
|
||||
{
|
||||
string text = (dictionary["msg"] ?? dictionary["message"])?.ToString() ?? "";
|
||||
if (num >= 200 || IsValidKey(text))
|
||||
{
|
||||
RemoveKey(base.LastKey, DateTime.Now.AddHours(1.0));
|
||||
}
|
||||
|
||||
if (base.ThrowException)
|
||||
{
|
||||
throw new Exception(text);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (result.IsNullOrEmpty())
|
||||
{
|
||||
return (T)dictionary;
|
||||
}
|
||||
|
||||
return (T)dictionary[result];
|
||||
}
|
||||
|
||||
//
|
||||
// 摘要:
|
||||
// 查询地址的经纬度坐标
|
||||
//
|
||||
// 参数:
|
||||
// address:
|
||||
//
|
||||
// city:
|
||||
//
|
||||
// coordtype:
|
||||
//
|
||||
// 言论:
|
||||
// 参考手册 https://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding
|
||||
protected async Task<IDictionary<string, object>> GetGeocoderAsync(string address, string? city = null, string? coordtype = null)
|
||||
{
|
||||
if (address.IsNullOrEmpty())
|
||||
{
|
||||
throw new ArgumentNullException("address");
|
||||
}
|
||||
|
||||
address = HttpUtility.UrlEncode(address);
|
||||
city = HttpUtility.UrlEncode(city);
|
||||
string url = "/geocoding/v3/?address=" + address + "&city=" + city + "&ret_coordtype=" + coordtype + "&extension_analys_level=1&output=json";
|
||||
return await InvokeAsync<IDictionary<string, object>>(url, "result");
|
||||
}
|
||||
|
||||
//
|
||||
// 摘要:
|
||||
// 查询地址获取坐标
|
||||
//
|
||||
// 参数:
|
||||
// address:
|
||||
// 地址
|
||||
//
|
||||
// city:
|
||||
// 城市
|
||||
//
|
||||
// coordtype:
|
||||
//
|
||||
// formatAddress:
|
||||
// 是否格式化地址
|
||||
public async Task<GeoAddress?> GetGeoAsync(string address, string? city = null, string? coordtype = null, bool formatAddress = false)
|
||||
{
|
||||
IDictionary<string, object> rs = await GetGeocoderAsync(address, city, coordtype);
|
||||
if (rs == null || rs.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!(rs["location"] is IDictionary<string, object> dictionary) || dictionary.Count < 2)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
GeoAddress geo = new GeoAddress
|
||||
{
|
||||
Location = new GeoPoint(dictionary["lng"], dictionary["lat"])
|
||||
};
|
||||
if (formatAddress)
|
||||
{
|
||||
GeoAddress geoAddress = await GetReverseGeoAsync(geo.Location, coordtype);
|
||||
if (geoAddress != null)
|
||||
{
|
||||
geo = geoAddress;
|
||||
}
|
||||
}
|
||||
|
||||
geo.Precise = rs["precise"].ToBoolean();
|
||||
geo.Confidence = rs["confidence"].ToInt();
|
||||
geo.Comprehension = rs["comprehension"].ToInt();
|
||||
geo.Level = rs["level"]?.ToString() ?? "";
|
||||
return geo;
|
||||
}
|
||||
|
||||
//
|
||||
// 摘要:
|
||||
// 根据坐标获取地址
|
||||
//
|
||||
// 参数:
|
||||
// point:
|
||||
//
|
||||
// coordtype:
|
||||
// 坐标系
|
||||
//
|
||||
// 言论:
|
||||
// 参考手册 https://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding-abroad
|
||||
protected async Task<IDictionary<string, object>> GetReverseGeocoderAsync(GeoPoint point, string? coordtype)
|
||||
{
|
||||
if (point == null || point.Longitude == 0.0 || point.Latitude == 0.0)
|
||||
{
|
||||
throw new ArgumentNullException("point");
|
||||
}
|
||||
|
||||
string url = $"/reverse_geocoding/v3/?location={point.Latitude},{point.Longitude}&extensions_poi=1&extensions_town=true&coordtype={coordtype}&output=json";
|
||||
return await InvokeAsync<IDictionary<string, object>>(url, "result");
|
||||
}
|
||||
|
||||
//
|
||||
// 摘要:
|
||||
// 根据坐标获取地址
|
||||
//
|
||||
// 参数:
|
||||
// point:
|
||||
//
|
||||
// coordtype:
|
||||
public async Task<GeoAddress?> GetReverseGeoAsync(GeoPoint point, string? coordtype)
|
||||
{
|
||||
IDictionary<string, object> dictionary = await GetReverseGeocoderAsync(point, coordtype);
|
||||
if (dictionary == null || dictionary.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
GeoAddress geoAddress = new GeoAddress
|
||||
{
|
||||
Address = (dictionary["formatted_address"]?.ToString() ?? ""),
|
||||
Confidence = dictionary["confidence"].ToInt()
|
||||
};
|
||||
if (dictionary["location"] is IDictionary<string, object> dictionary2 && dictionary2.Count >= 2)
|
||||
{
|
||||
geoAddress.Location = new GeoPoint(dictionary2["lng"], dictionary2["lat"]);
|
||||
}
|
||||
|
||||
if (dictionary["addressComponent"] is IDictionary<string, object> dictionary3)
|
||||
{
|
||||
new JsonReader().ToObject(dictionary3, null, geoAddress);
|
||||
geoAddress.Code = dictionary3["adcode"].ToInt();
|
||||
geoAddress.Township = dictionary3["town"]?.ToString() ?? "";
|
||||
geoAddress.Towncode = dictionary3["town_code"].ToInt();
|
||||
geoAddress.StreetNumber = dictionary3["street_number"]?.ToString() ?? "";
|
||||
}
|
||||
|
||||
if (dictionary.TryGetValue("sematic_description", out var value) && value is string text && !text.IsNullOrEmpty())
|
||||
{
|
||||
geoAddress.Title = text;
|
||||
}
|
||||
|
||||
return geoAddress;
|
||||
}
|
||||
|
||||
//
|
||||
// 摘要:
|
||||
// 计算距离和驾车时间
|
||||
//
|
||||
// 参数:
|
||||
// origin:
|
||||
//
|
||||
// destination:
|
||||
//
|
||||
// coordtype:
|
||||
//
|
||||
// type:
|
||||
// 路径计算的方式和方法
|
||||
//
|
||||
// 言论:
|
||||
// https://lbsyun.baidu.com/index.php?title=webapi/route-matrix-api-v2
|
||||
public async Task<Driving?> GetDistanceAsync(GeoPoint origin, GeoPoint destination, string? coordtype, int type = 13)
|
||||
{
|
||||
if (origin == null || (origin.Longitude < 1.0 && origin.Latitude < 1.0))
|
||||
{
|
||||
throw new ArgumentNullException("origin");
|
||||
}
|
||||
|
||||
if (destination == null || (destination.Longitude < 1.0 && destination.Latitude < 1.0))
|
||||
{
|
||||
throw new ArgumentNullException("destination");
|
||||
}
|
||||
|
||||
if (type <= 0)
|
||||
{
|
||||
type = 13;
|
||||
}
|
||||
|
||||
string text = coordtype;
|
||||
if (!text.IsNullOrEmpty() && text.Length > 6)
|
||||
{
|
||||
text = text.TrimEnd("ll");
|
||||
}
|
||||
|
||||
string url = $"/routematrix/v2/driving?origins={origin.Latitude},{origin.Longitude}&destinations={destination.Latitude},{destination.Longitude}&tactics={type}&coord_type={text}&output=json";
|
||||
IList<object> list = await InvokeAsync<IList<object>>(url, "result");
|
||||
if (list == null || list.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!(list.FirstOrDefault() is IDictionary<string, object> dictionary))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
IDictionary<string, object> dictionary2 = dictionary["distance"] as IDictionary<string, object>;
|
||||
IDictionary<string, object> dictionary3 = dictionary["duration"] as IDictionary<string, object>;
|
||||
return new Driving
|
||||
{
|
||||
Distance = (dictionary2?["value"].ToInt() ?? 0),
|
||||
Duration = (dictionary3?["value"].ToInt() ?? 0)
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// 摘要:
|
||||
// 计算距离和驾车时间
|
||||
//
|
||||
// 参数:
|
||||
// origin:
|
||||
//
|
||||
// destination:
|
||||
//
|
||||
// coordtype:
|
||||
//
|
||||
// type:
|
||||
// 路径计算的方式和方法
|
||||
//
|
||||
// 言论:
|
||||
// https://lbsyun.baidu.com/index.php?title=webapi/route-matrix-api-v2
|
||||
public async Task<Driving?> GetDistanceExAsync(GeoPoint origin, GeoPoint destination, string stratCity, string endCity, string? coordtype, int type = 13)
|
||||
{
|
||||
if (origin == null || (origin.Longitude < 1.0 && origin.Latitude < 1.0))
|
||||
{
|
||||
throw new ArgumentNullException("origin");
|
||||
}
|
||||
|
||||
if (destination == null || (destination.Longitude < 1.0 && destination.Latitude < 1.0))
|
||||
{
|
||||
throw new ArgumentNullException("destination");
|
||||
}
|
||||
|
||||
if (type <= 0)
|
||||
{
|
||||
type = 13;
|
||||
}
|
||||
|
||||
string text = coordtype;
|
||||
if (!text.IsNullOrEmpty() && text.Length > 6)
|
||||
{
|
||||
text = text.TrimEnd("ll");
|
||||
}
|
||||
string url = $"/direction/v2/driving?origin={origin}&destination={destination}&ak={base.AppKey}&origin_region={stratCity}&destination_region={endCity}&coord_type={text}&output=json";
|
||||
IList<object> list = await InvokeAsync<IList<object>>(url, "result");
|
||||
if (list == null || list.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!(list.FirstOrDefault() is IDictionary<string, object> dictionary))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
IDictionary<string, object> dictionary2 = dictionary["distance"] as IDictionary<string, object>;
|
||||
IDictionary<string, object> dictionary3 = dictionary["duration"] as IDictionary<string, object>;
|
||||
return new Driving
|
||||
{
|
||||
Distance = (dictionary2?["value"].ToInt() ?? 0),
|
||||
Duration = (dictionary3?["value"].ToInt() ?? 0)
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// 摘要:
|
||||
// 行政区划区域检索
|
||||
//
|
||||
// 参数:
|
||||
// query:
|
||||
//
|
||||
// tag:
|
||||
//
|
||||
// region:
|
||||
//
|
||||
// coordtype:
|
||||
//
|
||||
// formatAddress:
|
||||
//
|
||||
// 言论:
|
||||
// https://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-placeapi
|
||||
public async Task<GeoAddress?> PlaceSearchAsync(string query, string tag, string region, string? coordtype = null, bool formatAddress = true)
|
||||
{
|
||||
query = HttpUtility.UrlEncode(query);
|
||||
tag = HttpUtility.UrlEncode(tag);
|
||||
region = HttpUtility.UrlEncode(region);
|
||||
string url = "/place/v2/search?output=json&query=" + query + "&tag=" + tag + "®ion=" + region + "&city_limit=true&ret_coordtype=" + coordtype;
|
||||
IList<object> list = await InvokeAsync<IList<object>>(url, "results");
|
||||
if (list == null || list.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
object obj = list.FirstOrDefault();
|
||||
IDictionary<string, object> rs = obj as IDictionary<string, object>;
|
||||
if (rs == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
GeoAddress geo = new GeoAddress();
|
||||
if (rs["location"] is IDictionary<string, object> dictionary && dictionary.Count >= 2)
|
||||
{
|
||||
geo.Location = new GeoPoint(dictionary["lng"], dictionary["lat"]);
|
||||
if (formatAddress && geo.Location != null)
|
||||
{
|
||||
GeoAddress geoAddress = await GetReverseGeoAsync(geo.Location, coordtype);
|
||||
if (geoAddress != null)
|
||||
{
|
||||
geo = geoAddress;
|
||||
}
|
||||
}
|
||||
|
||||
geo.Name = rs["name"]?.ToString() ?? "";
|
||||
string text = rs["address"]?.ToString() ?? "";
|
||||
if (!text.IsNullOrEmpty())
|
||||
{
|
||||
geo.Address = text;
|
||||
}
|
||||
|
||||
return geo;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
//
|
||||
// 摘要:
|
||||
// IP定位
|
||||
//
|
||||
// 参数:
|
||||
// ip:
|
||||
//
|
||||
// coordtype:
|
||||
//
|
||||
// 言论:
|
||||
// https://lbsyun.baidu.com/index.php?title=webapi/ip-api
|
||||
public async Task<IDictionary<string, object?>?> IpLocationAsync(string ip, string coordtype)
|
||||
{
|
||||
string url = "/location/ip?ip=" + ip + "&coor=" + coordtype;
|
||||
IDictionary<string, object> dictionary = await InvokeAsync<IDictionary<string, object>>(url, null);
|
||||
if (dictionary == null || dictionary.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!(dictionary["content"] is IDictionary<string, object> dictionary2))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (dictionary.TryGetValue("address", out var value))
|
||||
{
|
||||
dictionary2["full_address"] = value;
|
||||
}
|
||||
|
||||
if (dictionary2.TryGetValue("address_detail", out var value2))
|
||||
{
|
||||
if (value2 != null)
|
||||
{
|
||||
dictionary2.Merge(value2);
|
||||
}
|
||||
|
||||
dictionary2.Remove("address_detail");
|
||||
}
|
||||
|
||||
if (dictionary2.TryGetValue("point", out var value3))
|
||||
{
|
||||
if (value3 != null)
|
||||
{
|
||||
dictionary2.Merge(value3);
|
||||
}
|
||||
|
||||
dictionary2.Remove("point");
|
||||
}
|
||||
|
||||
return dictionary2;
|
||||
}
|
||||
|
||||
//
|
||||
// 摘要:
|
||||
// 坐标转换
|
||||
//
|
||||
// 参数:
|
||||
// points:
|
||||
// 需转换的源坐标
|
||||
//
|
||||
// from:
|
||||
// 源坐标类型。wgs84ll/gcj02/bd09ll
|
||||
//
|
||||
// to:
|
||||
// 目标坐标类型。gcj02/bd09ll
|
||||
//
|
||||
// 言论:
|
||||
// https://lbsyun.baidu.com/index.php?title=webapi/guide/changeposition
|
||||
public override async Task<IList<GeoPoint>> ConvertAsync(IList<GeoPoint> points, string from, string to)
|
||||
{
|
||||
if (points == null || points.Count == 0)
|
||||
{
|
||||
throw new ArgumentNullException("points");
|
||||
}
|
||||
|
||||
if (from.IsNullOrEmpty())
|
||||
{
|
||||
throw new ArgumentNullException("from");
|
||||
}
|
||||
|
||||
if (to.IsNullOrEmpty())
|
||||
{
|
||||
throw new ArgumentNullException("to");
|
||||
}
|
||||
|
||||
//if (!from.EndsWithIgnoreCase("ll", "mc"))
|
||||
//{
|
||||
// from += "ll";
|
||||
//}
|
||||
|
||||
//if (!to.EndsWithIgnoreCase("ll", "mc"))
|
||||
//{
|
||||
// to += "ll";
|
||||
//}
|
||||
|
||||
if (from.EqualIgnoreCase(to))
|
||||
{
|
||||
return points;
|
||||
}
|
||||
|
||||
int num = 0;
|
||||
int num2 = 0;
|
||||
for (int i = 0; i < _coordTypes.Count; i++)
|
||||
{
|
||||
if (_coordTypes[i].EqualIgnoreCase(from))
|
||||
{
|
||||
num = i;
|
||||
}
|
||||
|
||||
if (_coordTypes[i].EqualIgnoreCase(to))
|
||||
{
|
||||
num2 = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (num == 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("from");
|
||||
}
|
||||
|
||||
if (num2 == 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("to");
|
||||
}
|
||||
|
||||
string url = string.Format("/geoconv/v2/?coords={0}&from={1}&to={2}&output=json", points.Join(";", (GeoPoint e) => $"{e.Longitude},{e.Latitude}"), num, num2);
|
||||
List<GeoPoint> list = new List<GeoPoint>();
|
||||
IList<object> list2 = await InvokeAsync<IList<object>>(url, "result");
|
||||
if (list2 == null || list2.Count == 0)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
|
||||
foreach (IDictionary<string, object> item in list2.Cast<IDictionary<string, object>>())
|
||||
{
|
||||
list.Add(new GeoPoint(item["x"], item["y"]));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SelfUseUtil.Helper
|
||||
@ -11,27 +12,10 @@ namespace SelfUseUtil.Helper
|
||||
/// <summary>
|
||||
/// 取小数,向下取整不四舍五入
|
||||
/// </summary>
|
||||
/// <param name="d"></param>
|
||||
/// <param name="n"></param>
|
||||
/// <returns></returns>
|
||||
public static decimal CutDecimalWithN(decimal d, int n = 0)
|
||||
{
|
||||
string strDecimal = d.ToString();
|
||||
int index = strDecimal.IndexOf(".");
|
||||
if (index == -1 || strDecimal.Length < index + n + 1)
|
||||
{
|
||||
strDecimal = string.Format("{0:F" + n + "}", d);
|
||||
}
|
||||
else
|
||||
{
|
||||
int length = index;
|
||||
if (n != 0)
|
||||
{
|
||||
length = index + n + 1;
|
||||
}
|
||||
strDecimal = strDecimal.Substring(0, length);
|
||||
}
|
||||
return decimal.Parse(strDecimal);
|
||||
decimal factor = (decimal)Math.Pow(10, n);
|
||||
return Math.Floor(d * factor) / factor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SelfUseUtil.Helper
|
||||
@ -74,6 +75,85 @@ namespace SelfUseUtil.Helper
|
||||
{
|
||||
return (long)(value.ToUniversalTime().Subtract(new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc))).TotalSeconds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将输入字符串所有非数字字符替换为 -
|
||||
/// </summary>
|
||||
public static string NormalizeDate(string input)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
return string.Empty;
|
||||
|
||||
input = Regex.Replace(input.Trim(), @"\D+", "-");
|
||||
return input.Trim('-');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断日期精度
|
||||
/// </summary>
|
||||
public static DatePrecision GetDatePrecision(string input)
|
||||
{
|
||||
input = NormalizeDate(input);
|
||||
|
||||
return input.Length switch
|
||||
{
|
||||
4 => DatePrecision.Year,
|
||||
6 => DatePrecision.Month,
|
||||
8 => DatePrecision.Day,
|
||||
_ => input.Count(c => c == '-') switch
|
||||
{
|
||||
1 => DatePrecision.Month,
|
||||
2 => DatePrecision.Day,
|
||||
_ => DatePrecision.Invalid
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串转换为 DateTime,支持选择起始时间或结束时间,精确到毫秒
|
||||
/// </summary>
|
||||
public static DateTime? ParseToDateTime(string input, bool endTime = false)
|
||||
{
|
||||
input = NormalizeDate(input);
|
||||
var precision = GetDatePrecision(input);
|
||||
if (precision == DatePrecision.Invalid)
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
// 统一处理紧凑格式(无 -)
|
||||
if (precision == DatePrecision.Month && Regex.IsMatch(input, @"^\d{6}$"))
|
||||
input = $"{input.Substring(0, 4)}-{input.Substring(4, 2)}";
|
||||
if (precision == DatePrecision.Day && Regex.IsMatch(input, @"^\d{8}$"))
|
||||
input = $"{input.Substring(0, 4)}-{input.Substring(4, 2)}-{input.Substring(6, 2)}";
|
||||
|
||||
// 拆分年月日
|
||||
string[] parts = input.Split('-');
|
||||
int year = int.Parse(parts[0]);
|
||||
int month = parts.Length > 1 ? int.Parse(parts[1]) : 1;
|
||||
int day = parts.Length > 2 ? int.Parse(parts[2]) : 1;
|
||||
|
||||
switch (precision)
|
||||
{
|
||||
case DatePrecision.Year:
|
||||
return endTime
|
||||
? new DateTime(year, 12, 31, 23, 59, 59, 999)
|
||||
: new DateTime(year, 1, 1, 0, 0, 0, 0);
|
||||
case DatePrecision.Month:
|
||||
if (endTime)
|
||||
day = DateTime.DaysInMonth(year, month);
|
||||
return new DateTime(year, month, day, endTime ? 23 : 0, endTime ? 59 : 0, endTime ? 59 : 0, endTime ? 999 : 0);
|
||||
case DatePrecision.Day:
|
||||
return new DateTime(year, month, day, endTime ? 23 : 0, endTime ? 59 : 0, endTime ? 59 : 0, endTime ? 999 : 0);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
@ -97,4 +177,12 @@ namespace SelfUseUtil.Helper
|
||||
return obj.ToJson().ToObject<DateDto>();
|
||||
}
|
||||
}
|
||||
|
||||
public enum DatePrecision
|
||||
{
|
||||
Year,
|
||||
Month,
|
||||
Day,
|
||||
Invalid
|
||||
}
|
||||
}
|
||||
|
||||
55
SelfUseUtil/Model/DrivingEx.cs
Normal file
55
SelfUseUtil/Model/DrivingEx.cs
Normal file
@ -0,0 +1,55 @@
|
||||
using NewLife.Map.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SelfUseUtil.Model
|
||||
{
|
||||
public class DrivingEx : Driving
|
||||
{
|
||||
/// <summary>路线步骤</summary>
|
||||
public IList<Step> Steps { get; set; } = new List<Step>();
|
||||
}
|
||||
|
||||
public class Step
|
||||
{
|
||||
public string instruction { get; set; }
|
||||
public string orientation { get; set; }
|
||||
public string road_name { get; set; }
|
||||
public string step_distance { get; set; }
|
||||
public Cost cost { get; set; }
|
||||
public string polyline { get; set; }
|
||||
}
|
||||
|
||||
public class Path
|
||||
{
|
||||
public string distance { get; set; }
|
||||
public string restriction { get; set; }
|
||||
public List<Step> steps { get; set; }
|
||||
public Cost cost { get; set; }
|
||||
}
|
||||
|
||||
public class Route
|
||||
{
|
||||
public string origin { get; set; }
|
||||
public string destination { get; set; }
|
||||
public string taxi_cost { get; set; }
|
||||
public List<Path> paths { get; set; }
|
||||
}
|
||||
|
||||
public class Root
|
||||
{
|
||||
public Route route { get; set; }
|
||||
}
|
||||
|
||||
public class Cost
|
||||
{
|
||||
public string duration { get; set; }
|
||||
public string tolls { get; set; }
|
||||
public string toll_distance { get; set; }
|
||||
public string toll_road { get; set; }
|
||||
public string traffic_lights { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,46 +1,102 @@
|
||||
using ScottPlot;
|
||||
//using ScottPlot;
|
||||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
using DocumentFormat.OpenXml.Wordprocessing;
|
||||
using hyjiacan.py4n;
|
||||
using NewLife;
|
||||
using NewLife.Data;
|
||||
using NewLife.Map;
|
||||
using Newtonsoft.Json;
|
||||
using SelfUseUtil;
|
||||
using SelfUseUtil.Demo;
|
||||
using SelfUseUtil.Helper;
|
||||
using System.Drawing;
|
||||
using System.IO.Packaging;
|
||||
using System.Management;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Text.RegularExpressions;
|
||||
using AMap = SelfUseUtil.AMap;
|
||||
using BaiduMap = SelfUseUtil.BaiduMap;
|
||||
|
||||
|
||||
// 创建 ScottPlot 图表对象
|
||||
var plt = new Plot();
|
||||
//// 创建 ScottPlot 图表对象
|
||||
//var plt = new Plot();
|
||||
|
||||
|
||||
// 添加一些示例数据
|
||||
double[] x = { 1, 2, 3, 4, 5 };
|
||||
double[] y1 = { 10, 20, 15, 30, 25 };
|
||||
double[] y2 = { 15, 25, 20, 35, 30 };
|
||||
double[] y3 = { 30, 30, 30, 30, 30 };
|
||||
//// 添加一些示例数据
|
||||
//double[] x = { 1, 2, 3, 4, 5 };
|
||||
//double[] y1 = { 10, 20, 15, 30, 25 };
|
||||
//double[] y2 = { 15, 25, 20, 35, 30 };
|
||||
//double[] y3 = { 30, 30, 30, 30, 30 };
|
||||
|
||||
var bar1 = plt.PlotFill(x, y3, baseline: 20, label: "国家线", fillColor: Color.FromArgb(20, 255, 0, 0));
|
||||
//var bar1 = plt.PlotFill(x, y3, baseline: 20, label: "国家线", fillColor: Color.FromArgb(20, 255, 0, 0));
|
||||
|
||||
// 添加折线图
|
||||
var line1 = plt.PlotScatter(x, y1, markerSize: 10, label: "线条1", lineStyle: LineStyle.Solid, color: Color.Blue);
|
||||
var line2 = plt.PlotScatter(x, y2, markerSize: 10, label: "线条2", lineStyle: LineStyle.Solid, color: Color.Orange);
|
||||
//// 添加折线图
|
||||
//var line1 = plt.PlotScatter(x, y1, markerSize: 10, label: "线条1", lineStyle: LineStyle.Solid, color: Color.Blue);
|
||||
//var line2 = plt.PlotScatter(x, y2, markerSize: 10, label: "线条2", lineStyle: LineStyle.Solid, color: Color.Orange);
|
||||
|
||||
|
||||
// 设置图表标题
|
||||
plt.Title("折线图示例");
|
||||
//// 设置图表标题
|
||||
//plt.Title("折线图示例");
|
||||
|
||||
// 设置中文横轴标签
|
||||
plt.XTicks(x, new[] { "一", "二", "三", "四", "五" });
|
||||
//// 设置中文横轴标签
|
||||
//plt.XTicks(x, new[] { "一", "二", "三", "四", "五" });
|
||||
|
||||
// 显示图例
|
||||
plt.Legend();
|
||||
|
||||
// 保存为图片文件
|
||||
string imagePath = $"{ConstData.DesktopPath}/LinePlot.png";
|
||||
plt.SaveFig(imagePath);
|
||||
|
||||
Console.WriteLine($"折线图已保存到 {imagePath}");
|
||||
//// 显示图例
|
||||
//plt.Legend();
|
||||
|
||||
//// 保存为图片文件
|
||||
//string imagePath = $"{ConstData.DesktopPath}/LinePlot.png";
|
||||
//plt.SaveFig(imagePath);
|
||||
|
||||
//Console.WriteLine($"折线图已保存到 {imagePath}");
|
||||
|
||||
var start = new GeoPoint(115.636961, 33.140093);
|
||||
var end = new GeoPoint(115.885212, 32.911371);
|
||||
var codeType = "bd09ll";
|
||||
|
||||
//Console.WriteLine("----- 高德地图 -----");
|
||||
//var gaode = new AMap { AppKey = "c7591c54f7443323b41ec4c0f315acf5" };
|
||||
|
||||
////请求地址:https://restapi.amap.com/v5/direction/driving?origin=115.636961,33.140093&destination=115.885212,32.911371&key=c7591c54f7443323b41ec4c0f315acf5&output=json&show_fields=cost,polyline
|
||||
//var gaodeData = await gaode.GetDistanceExAsync(start, end, codeType);
|
||||
//Console.WriteLine($"公里: {gaodeData?.Distance / 1000d}km 时间:{gaodeData?.Duration / 60d}m");
|
||||
|
||||
|
||||
//Console.WriteLine("----- 百度地图 -----");
|
||||
//var baidu = new BaiduMap { AppKey = "VkKeY0zh7hxCkA788etU4Fxv6q25EuEw" };
|
||||
|
||||
//var data = await baidu.ConvertAsync(new[] { start, end }, "amap", codeType);
|
||||
//start = data[0];
|
||||
//end = data[1];
|
||||
|
||||
//var startAddr = await baidu.GetReverseGeoAsync(start, codeType);
|
||||
//Console.WriteLine(startAddr?.City);
|
||||
//var endAddr = await baidu.GetReverseGeoAsync(end, codeType);
|
||||
//Console.WriteLine(endAddr?.City);
|
||||
|
||||
////请求地址:https://api.map.baidu.com/direction/v2/driving?origin=33.146014,115.643602&destination=32.917289,115.891866&ak=VkKeY0zh7hxCkA788etU4Fxv6q25EuEw
|
||||
//var baiduData = await baidu.GetDistanceExAsync(start, end, startAddr?.City, endAddr?.City, codeType);
|
||||
//Console.WriteLine($"公里: {baiduData?.Distance / 1000d}km 时间:{baiduData?.Duration / 60d}m");
|
||||
|
||||
//Console.WriteLine("----- 腾讯地图 -----");
|
||||
//var tencent = new TencentMap { AppKey = "TS5BZ-4RSCW-NVGRZ-YOTG4-UR645-K6FKD" };
|
||||
|
||||
////请求地址:https://api.map.baidu.com/direction/v2/driving?origin=115.643602,33.146014&destination=115.891866,32.917289&ak=VkKeY0zh7hxCkA788etU4Fxv6q25EuEw&origin_region=阜阳&destination_region=阜阳
|
||||
//var tencentData = await tencent.GetDistanceExAsync(start, end, codeType);
|
||||
//Console.WriteLine($"公里: {tencentData?.Distance / 1000d}km 时间:{tencentData?.Duration / 60d}m");
|
||||
|
||||
//Console.WriteLine("----- 天地图 -----");
|
||||
//var tiandi = new TianDiMap { AppKey = "TS5BZ-4RSCW-NVGRZ-YOTG4-UR645-K6FKD" };
|
||||
|
||||
////请求地址:https://api.map.baidu.com/direction/v2/driving?origin=115.643602,33.146014&destination=115.891866,32.917289&ak=VkKeY0zh7hxCkA788etU4Fxv6q25EuEw&origin_region=阜阳&destination_region=阜阳
|
||||
//var tiandiData = await tiandi.GetDistanceExAsync(start, end, codeType);
|
||||
//Console.WriteLine($"公里: {tiandiData?.Distance / 1000d}km 时间:{tiandiData?.Duration / 60d}m");
|
||||
|
||||
|
||||
string[] tests = { "2025", "202510", "20251013", "2025-10", "2025-10-13", "2025.10", "2025.10.13", "2025/10", "2025/10/13", "2025 10", "2025 10 13" };
|
||||
|
||||
foreach (var input in tests)
|
||||
{
|
||||
Console.WriteLine($"{input} → {DateHelper.ParseToDateTime(input, true)}");
|
||||
}
|
||||
|
||||
|
||||
@ -19,17 +19,21 @@
|
||||
<PackageReference Include="DocX" Version="2.5.0" />
|
||||
<PackageReference Include="FluentFTP" Version="47.1.0" />
|
||||
<PackageReference Include="FreeSql.Provider.ClickHouse" Version="3.2.809" />
|
||||
<PackageReference Include="hyjiacan.pinyin4net" Version="4.1.1" />
|
||||
<PackageReference Include="Irony" Version="1.2.0" />
|
||||
<PackageReference Include="Microsoft.SqlServer.Management.SqlParser" Version="170.9.0" />
|
||||
<PackageReference Include="Microsoft.SqlServer.TransactSql.ScriptDom" Version="161.8901.0" />
|
||||
<PackageReference Include="MiniSqlParser" Version="1.0.8" />
|
||||
<PackageReference Include="NewLife.Map" Version="2.6.2025.601" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NPinyinPro" Version="0.3.3" />
|
||||
<PackageReference Include="NPOI" Version="2.6.0" />
|
||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||
<PackageReference Include="ScottPlot" Version="4.1.67" />
|
||||
<PackageReference Include="System.Data.Odbc" Version="8.0.0" />
|
||||
<PackageReference Include="System.Data.SqlClient" Version="4.8.5" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
|
||||
<PackageReference Include="System.Management" Version="9.0.8" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user