├── miniprogram ├── pages │ ├── job │ │ ├── index.wxss │ │ ├── detail.json │ │ ├── index.json │ │ ├── detail.wxss │ │ └── detail.wxml │ └── my │ │ ├── my.wxss │ │ ├── about.wxss │ │ ├── favorites.wxss │ │ ├── my.json │ │ ├── about.json │ │ ├── favorites.json │ │ ├── about.js │ │ ├── about.wxml │ │ ├── favorites.wxml │ │ ├── favorites.js │ │ ├── my.wxml │ │ └── my.js ├── images │ ├── ic_my.png │ ├── ic_empty.png │ ├── ic_job.png │ ├── ic_avatar.png │ ├── ic_my_gray.png │ ├── logo_boss.png │ ├── ic_job_gray.png │ ├── logo_liepin.png │ ├── logo_zhilian.png │ └── logo_qianchengwuyou.png ├── sitemap.json ├── app.js ├── consts.js ├── app.json ├── app.wxss └── colorui │ └── animation.wxss ├── scf ├── .DS_Store ├── LBS.Amap.SDK │ ├── Models │ │ ├── SimpleModel.cs │ │ ├── Direction │ │ │ ├── IntegratedRoute.cs │ │ │ ├── Bus.cs │ │ │ ├── Gateway.cs │ │ │ ├── Stop.cs │ │ │ ├── WalkingRoute.cs │ │ │ ├── Path.cs │ │ │ ├── IntegratedResponse.cs │ │ │ ├── WalkingResponse.cs │ │ │ ├── WalkingParameter.cs │ │ │ ├── Segment.cs │ │ │ ├── Step.cs │ │ │ ├── BusLine.cs │ │ │ └── IntegratedParameter.cs │ │ ├── BaseParameter.cs │ │ ├── Suggestion.cs │ │ ├── WeatherParameter.cs │ │ ├── ReGeoCode.cs │ │ ├── IPLocationParameter.cs │ │ ├── CoordinateConvertResponse.cs │ │ ├── CoordinateConvertParameter.cs │ │ ├── TipResponse.cs │ │ ├── ReGeoResponse.cs │ │ ├── GeoResponse.cs │ │ ├── ForeCast.cs │ │ ├── Tip.cs │ │ ├── DistrictResponse.cs │ │ ├── WeatherResponse.cs │ │ ├── IPLocationResponse.cs │ │ ├── ReGeoParameter.cs │ │ ├── AddressComponent.cs │ │ ├── TipParameter.cs │ │ ├── GeoParameter.cs │ │ ├── DistrictParameter.cs │ │ ├── District.cs │ │ ├── Live.cs │ │ ├── StaticMapParameter.cs │ │ ├── Cast.cs │ │ └── GeoCode.cs │ ├── AmapOptions.cs │ ├── DependencyInjection │ │ ├── LBSAmapServiceCollectionExtensions.cs │ │ └── AmapOptionsServiceCollectionExtensions.cs │ ├── AmapUriConst.cs │ ├── Json │ │ ├── AmapStringConverter.cs │ │ └── AmapJsonConvert.cs │ ├── Extensions │ │ ├── DictionaryExtensions.cs │ │ └── ModelExtensions.cs │ ├── LBS.Amap.SDK.csproj │ └── Http │ │ └── AmapHttpClient.cs ├── XUnitTestFindJob │ ├── JobManagerTest.cs │ ├── appsettings.json │ ├── XUnitTestFindJob.csproj │ └── AmapWebApiTest.cs ├── bootstrap ├── build ├── serverless.yaml ├── README.md ├── index │ ├── index.csproj │ ├── appsettings.json │ └── Program.cs ├── stat │ ├── stat.csproj │ ├── appsettings.json │ └── Program.cs ├── Yhd.TencentCloud.SCF │ ├── Loggers │ │ └── Logger │ │ │ └── Constants │ │ │ └── LogCategories.cs │ ├── ISCFHost.cs │ ├── Executors │ │ ├── FunctionInvoker.cs │ │ ├── IFunctionInvoker.cs │ │ └── HttpFunctionInvoker.cs │ ├── Yhd.TencentCloud.SCF.csproj │ ├── Hosting │ │ ├── ISCFBuilder.cs │ │ ├── SCFBuilder.cs │ │ ├── SCFBuilderExtensions.cs │ │ ├── SCFHostService.cs │ │ ├── SCFServiceCollectionExtensions.cs │ │ └── SCFHostBuilderExtensions.cs │ ├── Protocols │ │ ├── RequestIdentity.cs │ │ ├── APIGatewayProxyResponseEvent.cs │ │ ├── APIGatewayProxyRequestEvent.cs │ │ └── ProxyRequestContext.cs │ ├── SCFContext.cs │ ├── Config │ │ ├── SCFHostOptions.cs │ │ └── AppConfigurations.cs │ └── ObjectDictionaryConverter.cs ├── Yhd.FindJob │ ├── IFindJob.cs │ ├── RecruitEnum.cs │ ├── IJobsManager.cs │ ├── Yhd.FindJob.csproj │ ├── DetailsInfo.cs │ ├── JobInfo.cs │ ├── ServiceCollectionExtensions.cs │ ├── FindJobFactory.cs │ ├── JobsManager.cs │ ├── FindJobBase.cs │ └── FindBossJob.cs ├── Yhd.FindJobStat │ ├── WxCloudOption.cs │ ├── Yhd.FindJobStat.csproj │ ├── ServiceCollectionExtensions.cs │ ├── Model.cs │ ├── WxCloudApi.cs │ ├── ApiHttpClient.cs │ └── AccessTokenManager.cs ├── appsettings.json ├── XUnitTestFindJobStat │ ├── appsettings.json │ ├── XUnitTestFindJobStat.csproj │ ├── AccessTokenManagerTest.cs │ └── WxCloudApiTest.cs └── config.json ├── blazorsite └── FindJobBlazorSite │ ├── FindJobBlazorSite │ ├── Pages │ │ ├── Pv.razor │ │ ├── Apply.razor │ │ ├── TopCity.razor │ │ ├── TopSearch.razor │ │ └── Index.razor │ ├── wwwroot │ │ ├── favicon.ico │ │ ├── css │ │ │ └── open-iconic │ │ │ │ ├── font │ │ │ │ └── fonts │ │ │ │ │ ├── open-iconic.eot │ │ │ │ │ ├── open-iconic.otf │ │ │ │ │ ├── open-iconic.ttf │ │ │ │ │ └── open-iconic.woff │ │ │ │ ├── ICON-LICENSE │ │ │ │ └── README.md │ │ ├── images │ │ │ └── spinner.svg │ │ ├── js │ │ │ └── loader.js │ │ └── index.html │ ├── App.razor │ ├── Shared │ │ ├── MainLayout.razor │ │ ├── StatTopCityChart.razor │ │ ├── StatTopSearchChart.razor │ │ ├── NavMenu.razor │ │ ├── StatPvChart.razor │ │ └── StatApplyChart.razor │ ├── _Imports.razor │ ├── Program.cs │ ├── FindJobBlazorSite.csproj │ └── Properties │ │ └── launchSettings.json │ └── FindJobBlazorSite.sln ├── cloudfunctions ├── get-stat-pv │ ├── config.json │ ├── package.json │ └── index.js ├── is-favorite │ ├── config.json │ ├── package.json │ └── index.js ├── post-stat │ ├── config.json │ ├── package.json │ └── index.js ├── user-login │ ├── config.json │ ├── package.json │ └── index.js ├── get-stat-apply │ ├── config.json │ ├── package.json │ └── index.js ├── get-stat-top-city │ ├── config.json │ ├── package.json │ └── index.js ├── save-favorite │ ├── config.json │ ├── package.json │ └── index.js ├── user-favorite │ ├── config.json │ ├── index.js │ └── package.json └── get-stat-top-search │ ├── config.json │ ├── package.json │ └── index.js ├── resources ├── funcarch.png ├── miniprog.png ├── miniprog2.png ├── miniprog3.png ├── miniprog4.png ├── miniprog5.png ├── miniprog6.png ├── softarch.png └── findjobqrcode.jpg ├── code-of-conduct.md ├── changelog.md ├── LICENSE ├── deployment.md ├── project.config.json ├── contributing.md └── README.md /miniprogram/pages/job/index.wxss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/pages/my/my.wxss: -------------------------------------------------------------------------------- 1 | /* miniprogram/pages/my/my.wxss */ -------------------------------------------------------------------------------- /miniprogram/pages/my/about.wxss: -------------------------------------------------------------------------------- 1 | /* miniprogram/pages/my/about.wxss */ -------------------------------------------------------------------------------- /miniprogram/pages/my/favorites.wxss: -------------------------------------------------------------------------------- 1 | /* miniprogram/pages/my/favorites.wxss */ -------------------------------------------------------------------------------- /scf/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/scf/.DS_Store -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/Pages/Pv.razor: -------------------------------------------------------------------------------- 1 | @page "/statpv" 2 | -------------------------------------------------------------------------------- /miniprogram/pages/my/my.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {}, 3 | "navigationBarTitleText": "" 4 | } -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/Pages/Apply.razor: -------------------------------------------------------------------------------- 1 | @page "/statapply" 2 | -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/Pages/TopCity.razor: -------------------------------------------------------------------------------- 1 | @page "/topcity" 2 | -------------------------------------------------------------------------------- /cloudfunctions/get-stat-pv/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "permissions": { 3 | "openapi": [ 4 | ] 5 | } 6 | } -------------------------------------------------------------------------------- /cloudfunctions/is-favorite/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "permissions": { 3 | "openapi": [ 4 | ] 5 | } 6 | } -------------------------------------------------------------------------------- /cloudfunctions/post-stat/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "permissions": { 3 | "openapi": [ 4 | ] 5 | } 6 | } -------------------------------------------------------------------------------- /cloudfunctions/user-login/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "permissions": { 3 | "openapi": [ 4 | ] 5 | } 6 | } -------------------------------------------------------------------------------- /miniprogram/pages/job/detail.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {}, 3 | "navigationBarTitleText": "职位详情" 4 | } -------------------------------------------------------------------------------- /miniprogram/pages/my/about.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {}, 3 | "navigationBarTitleText": "关于小程序" 4 | } -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/Pages/TopSearch.razor: -------------------------------------------------------------------------------- 1 | @page "/topsearch" 2 | -------------------------------------------------------------------------------- /cloudfunctions/get-stat-apply/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "permissions": { 3 | "openapi": [ 4 | ] 5 | } 6 | } -------------------------------------------------------------------------------- /cloudfunctions/get-stat-top-city/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "permissions": { 3 | "openapi": [ 4 | ] 5 | } 6 | } -------------------------------------------------------------------------------- /cloudfunctions/save-favorite/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "permissions": { 3 | "openapi": [ 4 | ] 5 | } 6 | } -------------------------------------------------------------------------------- /cloudfunctions/user-favorite/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "permissions": { 3 | "openapi": [ 4 | ] 5 | } 6 | } -------------------------------------------------------------------------------- /resources/funcarch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/resources/funcarch.png -------------------------------------------------------------------------------- /resources/miniprog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/resources/miniprog.png -------------------------------------------------------------------------------- /resources/miniprog2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/resources/miniprog2.png -------------------------------------------------------------------------------- /resources/miniprog3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/resources/miniprog3.png -------------------------------------------------------------------------------- /resources/miniprog4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/resources/miniprog4.png -------------------------------------------------------------------------------- /resources/miniprog5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/resources/miniprog5.png -------------------------------------------------------------------------------- /resources/miniprog6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/resources/miniprog6.png -------------------------------------------------------------------------------- /resources/softarch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/resources/softarch.png -------------------------------------------------------------------------------- /cloudfunctions/get-stat-top-search/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "permissions": { 3 | "openapi": [ 4 | ] 5 | } 6 | } -------------------------------------------------------------------------------- /miniprogram/images/ic_my.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/miniprogram/images/ic_my.png -------------------------------------------------------------------------------- /resources/findjobqrcode.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/resources/findjobqrcode.jpg -------------------------------------------------------------------------------- /miniprogram/images/ic_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/miniprogram/images/ic_empty.png -------------------------------------------------------------------------------- /miniprogram/images/ic_job.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/miniprogram/images/ic_job.png -------------------------------------------------------------------------------- /miniprogram/images/ic_avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/miniprogram/images/ic_avatar.png -------------------------------------------------------------------------------- /miniprogram/images/ic_my_gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/miniprogram/images/ic_my_gray.png -------------------------------------------------------------------------------- /miniprogram/images/logo_boss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/miniprogram/images/logo_boss.png -------------------------------------------------------------------------------- /miniprogram/images/ic_job_gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/miniprogram/images/ic_job_gray.png -------------------------------------------------------------------------------- /miniprogram/images/logo_liepin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/miniprogram/images/logo_liepin.png -------------------------------------------------------------------------------- /miniprogram/images/logo_zhilian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/miniprogram/images/logo_zhilian.png -------------------------------------------------------------------------------- /miniprogram/pages/job/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {}, 3 | "enablePullDownRefresh": true, 4 | "navigationBarTitleText": "" 5 | } -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/SimpleModel.cs: -------------------------------------------------------------------------------- 1 | namespace LBS.Amap.SDK.Models 2 | { 3 | internal class SimpleModel 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /scf/XUnitTestFindJob/JobManagerTest.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/scf/XUnitTestFindJob/JobManagerTest.cs -------------------------------------------------------------------------------- /miniprogram/pages/my/favorites.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {}, 3 | "navigationBarTitleText": "我的收藏", 4 | "enablePullDownRefresh": true 5 | } -------------------------------------------------------------------------------- /miniprogram/images/logo_qianchengwuyou.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/miniprogram/images/logo_qianchengwuyou.png -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/blazorsite/FindJobBlazorSite/FindJobBlazorSite/wwwroot/favicon.ico -------------------------------------------------------------------------------- /scf/bootstrap: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo "Start dotnet bootstrap ~~~" 3 | export DOTNET_ROOT=/opt/rt 4 | export PATH=$(pwd):/opt/rt:${PATH} 5 | dotnet ./index/bin/Release/netcoreapp3.1/index.dll 6 | 7 | -------------------------------------------------------------------------------- /miniprogram/sitemap.json: -------------------------------------------------------------------------------- 1 | { 2 | "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", 3 | "rules": [{ 4 | "action": "allow", 5 | "page": "*" 6 | }] 7 | } -------------------------------------------------------------------------------- /scf/build: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Must do this on a linux machine with dotnet sdk 3 | ls -la 4 | cd index/ 5 | dotnet build --configuration Release 6 | cd .. 7 | 8 | zip -x config.json -q -r ./dotnet-demo.zip ./* 9 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/AmapOptions.cs: -------------------------------------------------------------------------------- 1 | namespace LBS.Amap.SDK 2 | { 3 | /// 4 | /// 高的地图配置 5 | /// 6 | public class AmapOptions 7 | { 8 | public string Key { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/Direction/IntegratedRoute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace LBS.Amap.SDK.Models.Direction 6 | { 7 | class IntegratedRoute 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/wwwroot/css/open-iconic/font/fonts/open-iconic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/blazorsite/FindJobBlazorSite/FindJobBlazorSite/wwwroot/css/open-iconic/font/fonts/open-iconic.eot -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/wwwroot/css/open-iconic/font/fonts/open-iconic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/blazorsite/FindJobBlazorSite/FindJobBlazorSite/wwwroot/css/open-iconic/font/fonts/open-iconic.otf -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/blazorsite/FindJobBlazorSite/FindJobBlazorSite/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/wwwroot/css/open-iconic/font/fonts/open-iconic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnetcloudbase/findjobtclooud/HEAD/blazorsite/FindJobBlazorSite/FindJobBlazorSite/wwwroot/css/open-iconic/font/fonts/open-iconic.woff -------------------------------------------------------------------------------- /miniprogram/pages/my/about.js: -------------------------------------------------------------------------------- 1 | const jobService = require("../../jobService") 2 | Page({ 3 | onLoad: function (options) { 4 | jobService.statPreviewAbout() 5 | }, 6 | 7 | onShareAppMessage: function () { 8 | }, 9 | 10 | onShareTimeline() { 11 | } 12 | }) -------------------------------------------------------------------------------- /cloudfunctions/user-favorite/index.js: -------------------------------------------------------------------------------- 1 | const cloud = require('wx-server-sdk') 2 | cloud.init() 3 | const db = cloud.database() 4 | 5 | exports.main = async (event, context) => { 6 | return (await db.collection('favorites').where({ 7 | openId: cloud.getWXContext().OPENID 8 | }).get()).data; 9 | } -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/Direction/Bus.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace LBS.Amap.SDK.Models.Direction 5 | { 6 | public class Bus 7 | { 8 | [JsonProperty("buslines")] 9 | public ICollection BusLines { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/Pages/Index.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | 3 |

关于本站

4 |
本站为腾讯2020年8月份云开发赛事参赛作品统计网站。
5 |
6 |

7 | 小程序云开发挑战赛 8 | 参赛作品 FindJob 9 |

10 | -------------------------------------------------------------------------------- /cloudfunctions/post-stat/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "post-stat", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "wx-server-sdk": "~2.2.0" 13 | } 14 | } -------------------------------------------------------------------------------- /cloudfunctions/user-login/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "user-login", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "wx-server-sdk": "~2.2.0" 13 | } 14 | } -------------------------------------------------------------------------------- /cloudfunctions/get-stat-pv/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "get-stat-pv", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "wx-server-sdk": "~2.2.0" 13 | } 14 | } -------------------------------------------------------------------------------- /cloudfunctions/is-favorite/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "is-favorite", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "wx-server-sdk": "~2.2.0" 13 | } 14 | } -------------------------------------------------------------------------------- /cloudfunctions/save-favorite/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "save-favorite", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "wx-server-sdk": "~2.2.0" 13 | } 14 | } -------------------------------------------------------------------------------- /cloudfunctions/user-favorite/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "user-favorite", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "wx-server-sdk": "~2.2.0" 13 | } 14 | } -------------------------------------------------------------------------------- /scf/serverless.yaml: -------------------------------------------------------------------------------- 1 | component: scf 2 | name: ap-guangzhou_dotnet_demo 3 | org: app 4 | app: dotnet_demo 5 | stage: dev 6 | inputs: 7 | name: dotnet_demo 8 | src: ./ 9 | description: dotnet demo function. Dotnet模版函数 10 | handler: index.main_handler 11 | runtime: CustomRuntime 12 | namespace: default 13 | region: ap-guangzhou 14 | memorySize: 128 15 | timeout: 3 16 | -------------------------------------------------------------------------------- /cloudfunctions/get-stat-apply/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "get-stat-apply", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "wx-server-sdk": "~2.2.0" 13 | } 14 | } -------------------------------------------------------------------------------- /cloudfunctions/get-stat-top-city/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "get-stat-top-city", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "wx-server-sdk": "~2.2.0" 13 | } 14 | } -------------------------------------------------------------------------------- /cloudfunctions/get-stat-top-search/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "get-stat-top-search", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "wx-server-sdk": "~2.2.0" 13 | } 14 | } -------------------------------------------------------------------------------- /scf/README.md: -------------------------------------------------------------------------------- 1 | # API接口说明 2 | 3 | 找工作提供2个接口, 聚合查询招聘网站的岗位数据 以及查看岗位的详细信息。 4 | 5 | 1. 查询招聘网站的岗位数据 6 | - path: /api/jobs/getjobs?sources=xxxx&city=xxx&searchkey=xxxxx&pageindex=1 7 | - method: httpget 8 | - 格式: json 9 | 2. 查看岗位的详细信息 10 | - path: /api/jobs/getdetailsinfo?source=xxxx&url=xxx 11 | - method: httpget 12 | - 格式: json 13 | 14 | # 应用配置 15 | 16 | 使用Redis 用户的最新查询数据,默认缓存10分钟。 -------------------------------------------------------------------------------- /miniprogram/pages/job/detail.wxss: -------------------------------------------------------------------------------- 1 | .job-detail-container { 2 | position: relative; 3 | padding-bottom: 100rpx; 4 | } 5 | 6 | .job-base-infol { 7 | background: white; 8 | } 9 | 10 | .apply-job { 11 | position: fixed; 12 | bottom: 0; 13 | left: 0; 14 | width: 100%; 15 | box-shadow: 0 0 8px rgba(0,0,0,0.1); 16 | } 17 | 18 | .company-intro { 19 | line-height: 180%; 20 | } -------------------------------------------------------------------------------- /cloudfunctions/is-favorite/index.js: -------------------------------------------------------------------------------- 1 | const cloud = require('wx-server-sdk') 2 | cloud.init() 3 | const db = cloud.database() 4 | 5 | exports.main = async (event, context) => { 6 | const openId = cloud.getWXContext().OPENID; 7 | var favorite = await db.collection('favorites').where({ 8 | openId: openId, 9 | url: event.url 10 | }).get(); 11 | return favorite.data.length > 0; 12 | } -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/BaseParameter.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace LBS.Amap.SDK.Models 4 | { 5 | public abstract class BaseParameter 6 | { 7 | /// 8 | /// 返回数据格式类型 9 | ///
可选值:JSON,XML
10 | ///
11 | [Display(Name = "output")] 12 | public string Output { get; set; } = "JSON"; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/Direction/Gateway.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace LBS.Amap.SDK.Models.Direction 4 | { 5 | /// 6 | /// 出入口 7 | /// 8 | public class Gateway 9 | { 10 | [JsonProperty("name")] 11 | public string Name { get; set; } 12 | 13 | [JsonProperty("location")] 14 | public string Location { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /cloudfunctions/post-stat/index.js: -------------------------------------------------------------------------------- 1 | const cloud = require('wx-server-sdk') 2 | cloud.init() 3 | const db = cloud.database() 4 | 5 | exports.main = async (event, context) => { 6 | var statInfo = { 7 | date: event.date, 8 | type: event.type, 9 | page: event.page, 10 | extra: event.extra 11 | }; 12 | await db.collection('stats').add({ 13 | data: statInfo 14 | }); 15 | return true 16 | } -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/App.razor: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Sorry, there's nothing at this address.

8 |
9 |
10 |
11 | -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/Shared/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 | 6 | 7 |
8 |
9 | Github 10 |
11 | 12 |
13 | @Body 14 |
15 |
16 | -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using Microsoft.AspNetCore.Components.WebAssembly.Http 7 | @using Microsoft.JSInterop 8 | @using FindJobBlazorSite 9 | @using FindJobBlazorSite.Shared 10 | @using AntDesign.Charts 11 | -------------------------------------------------------------------------------- /miniprogram/pages/my/about.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 关于 4 | 《Find Job》是2020年8月份腾讯公司举办的云开发赛事参赛作品。 5 | 开源地址 6 | Github:https://github.com/dotnetcloudbase/findjob 7 | 8 | -------------------------------------------------------------------------------- /miniprogram/app.js: -------------------------------------------------------------------------------- 1 | App({ 2 | onLaunch: function () { 3 | if (!wx.cloud) { 4 | console.error('请使用 2.2.3 或以上的基础库以使用云能力') 5 | } else { 6 | wx.cloud.init({ 7 | // env 参数说明: 8 | // env 参数决定接下来小程序发起的云开发调用(wx.cloud.xxx)会默认请求到哪个云环境的资源 9 | // 此处请填入环境 ID, 环境 ID 可打开云控制台查看 10 | // 如不填则使用默认环境(第一个创建的环境) 11 | // env: 'my-env-id', 12 | traceUser: true, 13 | }) 14 | } 15 | this.globalData = {} 16 | } 17 | }) 18 | -------------------------------------------------------------------------------- /scf/index/index.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | PreserveNewest 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /scf/stat/stat.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | PreserveNewest 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/DependencyInjection/LBSAmapServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using LBS.Amap.SDK; 2 | using LBS.Amap.SDK.Http; 3 | 4 | namespace Microsoft.Extensions.DependencyInjection 5 | { 6 | public static class LBSAmapServiceCollectionExtensions 7 | { 8 | public static IServiceCollection AddLBSAmap(this IServiceCollection services) 9 | { 10 | services.AddHttpClient(); 11 | services.AddSingleton(); 12 | return services; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /scf/Yhd.TencentCloud.SCF/Loggers/Logger/Constants/LogCategories.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Yhd.TencentCloud.SCF.Loggers.Logger.Constants 6 | { 7 | public static class LogCategories 8 | { 9 | /// 10 | /// The category for all logs written by the function host during startup and shutdown. This 11 | /// includes indexing and configuration logs. 12 | /// 13 | public const string Startup = "Host.Startup"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/Suggestion.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace LBS.Amap.SDK.Models 4 | { 5 | /// 6 | /// 建议结果列表 7 | /// 8 | public class Suggestion 9 | { 10 | /// 11 | /// 建议关键字列表 12 | /// 13 | [JsonProperty("keywords")] 14 | public string KeyWords { get; set; } 15 | 16 | /// 17 | /// 建议城市列表 18 | /// 19 | [JsonProperty("cities")] 20 | public string Citys { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /scf/Yhd.FindJob/IFindJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | 6 | namespace Yhd.FindJob 7 | { 8 | public interface IFindJob 9 | { 10 | RecruitEnum Recruit { get; } 11 | 12 | string City { get; set; } 13 | 14 | string SearchKey { get; set; } 15 | 16 | int PageIndex { get; set; } 17 | 18 | Task> GetJobsAsync(int? minutes = null); 19 | 20 | Task GetDetailsInfo(string url); 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /scf/Yhd.FindJobStat/WxCloudOption.cs: -------------------------------------------------------------------------------- 1 | namespace Yhd.FindJobStat 2 | { 3 | /// 4 | /// 小程序云开发参数配置 5 | /// 6 | public class WxCloudOption 7 | { 8 | /// 9 | /// AppID 10 | /// 11 | public string AppID { get; set; } 12 | /// 13 | /// AppSecret 14 | /// 15 | public string AppSecret { get; set; } 16 | /// 17 | /// 环境 18 | /// 19 | public string Env { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /cloudfunctions/get-stat-top-search/index.js: -------------------------------------------------------------------------------- 1 | const cloud = require('wx-server-sdk') 2 | cloud.init() 3 | const db = cloud.database() 4 | const $ = db.command.aggregate 5 | 6 | exports.main = async () => { 7 | return (await db.collection('stats') 8 | .aggregate() 9 | .match({ 10 | type: "search" 11 | }) 12 | .group({ 13 | _id: $.toLower('$extra.keyword'), 14 | count: $.sum(1) 15 | }) 16 | .sort({ 17 | count: 1, 18 | }) 19 | .limit(10) 20 | .end()).list; 21 | } -------------------------------------------------------------------------------- /scf/Yhd.TencentCloud.SCF/ISCFHost.cs: -------------------------------------------------------------------------------- 1 | 2 | // Copyright (c) Yhd Tech. All rights reserved. 3 | // Licensed under the MIT License. See License.txt in the project root for license information.using Microsoft.Extensions.Configuration; 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | 11 | namespace Yhd.TencentCloud.SCF 12 | { 13 | public interface ISCFHost 14 | { 15 | Task StartAsync(CancellationToken cancellationToken); 16 | 17 | Task StopAsync(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/WeatherParameter.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace LBS.Amap.SDK.Models 4 | { 5 | /// 6 | /// 天气数据获取参数 7 | /// 8 | public class WeatherParameter : BaseParameter 9 | { 10 | /// 11 | /// 城市编码 12 | /// 13 | [Display(Name = "city")] 14 | public string City { get; set; } 15 | 16 | /// 17 | /// 气象类型 18 | /// 19 | [Display(Name = "extensions")] 20 | public string Extensions { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/ReGeoCode.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace LBS.Amap.SDK.Models 7 | { 8 | public class ReGeoCode 9 | { 10 | 11 | /// 12 | /// 结构化地址信息 13 | /// 14 | [JsonProperty("formatted_address")] 15 | public string FormattedAddress { get; set; } 16 | 17 | /// 18 | /// 地址信息 19 | /// 20 | [JsonProperty("addressComponent")] 21 | public AddressComponent AddressComponent { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /scf/index/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "easycaching": { 3 | "redis": { 4 | "MaxRdSecond": 120, 5 | "EnableLogging": false, 6 | "LockMs": 5000, 7 | "SleepMs": 300, 8 | "dbconfig": { 9 | "Password": null, 10 | "IsSsl": false, 11 | "SslHost": null, 12 | "ConnectionTimeout": 5000, 13 | "AllowAdmin": true, 14 | "Endpoints": [ 15 | { 16 | "Host": "10.1.0.2", 17 | "Port": 6379 18 | } 19 | ], 20 | "Database": 10 21 | } 22 | } 23 | }, 24 | "Amap": { 25 | "Key": "xxxxx" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /scf/XUnitTestFindJob/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "easycaching": { 3 | "redis": { 4 | "MaxRdSecond": 120, 5 | "EnableLogging": false, 6 | "LockMs": 5000, 7 | "SleepMs": 300, 8 | "dbconfig": { 9 | "Password": null, 10 | "IsSsl": false, 11 | "SslHost": null, 12 | "ConnectionTimeout": 5000, 13 | "AllowAdmin": true, 14 | "Endpoints": [ 15 | { 16 | "Host": "localhost", 17 | "Port": 6739 18 | } 19 | ], 20 | "Database": 10 21 | } 22 | } 23 | }, 24 | "Amap": { 25 | "Key": "xxxxxxx" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /scf/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "easycaching": { 3 | "redis": { 4 | "MaxRdSecond": 120, 5 | "EnableLogging": false, 6 | "LockMs": 5000, 7 | "SleepMs": 300, 8 | "dbconfig": { 9 | "Password": null, 10 | "IsSsl": false, 11 | "SslHost": null, 12 | "ConnectionTimeout": 5000, 13 | "AllowAdmin": true, 14 | "Endpoints": [ 15 | { 16 | "Host": "10.1.0.2", 17 | "Port": 6739 18 | } 19 | ], 20 | "Database": 10 21 | } 22 | }, 23 | "Amap": { 24 | "Key": "71822e73b7871a41f4cb386413d3db0c" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /scf/Yhd.TencentCloud.SCF/Executors/FunctionInvoker.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Yhd Tech. All rights reserved. 2 | // Licensed under the MIT License. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Yhd.TencentCloud.SCF.Executors 10 | { 11 | public class FunctionInvoker : IFunctionInvoker 12 | { 13 | public virtual async Task ProcessEvent(string responseBody, SCFContext context) 14 | { 15 | return "Event :" + responseBody + "\t Context: " + context.ToString(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /scf/Yhd.FindJob/RecruitEnum.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Yhd.FindJob 6 | { 7 | public enum RecruitEnum 8 | { 9 | /// 10 | /// 智联招聘 11 | /// 12 | ZLZhaopin = 0, 13 | /// 14 | /// 前程无忧 15 | /// 16 | QC51 = 1, 17 | /// 18 | /// 猎聘网 19 | /// 20 | Liepin = 2, 21 | /// 22 | /// BOSS 23 | /// 24 | BOSS = 3, 25 | /// 26 | /// 拉勾网 27 | /// 28 | Lagou = 4 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /cloudfunctions/get-stat-pv/index.js: -------------------------------------------------------------------------------- 1 | const cloud = require('wx-server-sdk') 2 | cloud.init() 3 | const db = cloud.database() 4 | const $ = db.command.aggregate 5 | 6 | exports.main = async () => { 7 | let curDate = new Date((+new Date()) - 30 * 24 * 3600 * 1000); 8 | return (await db.collection('stats') 9 | .aggregate() 10 | .addFields({ 11 | matched: $.and([ 12 | $.gte(['$date', curDate]), 13 | $.eq(['$type', 'preview']) 14 | ]), 15 | }) 16 | .match({ 17 | matched: !0 18 | }) 19 | .group({ 20 | _id: '$date', 21 | pv: $.sum(1) 22 | }) 23 | .sort({ 24 | _id: 1, 25 | }) 26 | .end()).list; 27 | } -------------------------------------------------------------------------------- /cloudfunctions/get-stat-apply/index.js: -------------------------------------------------------------------------------- 1 | const cloud = require('wx-server-sdk') 2 | cloud.init() 3 | const db = cloud.database() 4 | const $ = db.command.aggregate 5 | 6 | exports.main = async () => { 7 | let curDate = new Date((+new Date()) - 30 * 24 * 3600 * 1000); 8 | return (await db.collection('stats') 9 | .aggregate() 10 | .addFields({ 11 | matched: $.and([ 12 | $.gte(['$date', curDate]), 13 | $.eq(['$type', 'apply']) 14 | ]), 15 | }) 16 | .match({ 17 | matched: !0 18 | }) 19 | .group({ 20 | _id: '$date', 21 | pv: $.sum(1) 22 | }) 23 | .sort({ 24 | _id: 1, 25 | }) 26 | .end()).list; 27 | } -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/IPLocationParameter.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace LBS.Amap.SDK.Models 4 | { 5 | /// 6 | /// IP定位参数 7 | /// 8 | public class IPLocationParameter : BaseParameter 9 | { 10 | /// 11 | /// ip地址 12 | ///
需要搜索的IP地址(仅支持国内)若不填写IP,则取客户http之中的请求来进行定位
13 | ///
14 | [Display(Name = "ip")] 15 | public string IP { get; set; } 16 | 17 | /// 18 | /// 签名 19 | ///
选择数字签名认证的付费用户必填
20 | ///
21 | [Display(Name = "sig")] 22 | public string Sig { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/CoordinateConvertResponse.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace LBS.Amap.SDK.Models 4 | { 5 | public class CoordinateConvertResponse 6 | { 7 | /// 8 | /// 返回状态 9 | /// 10 | [JsonProperty("status")] 11 | public string Status { get; set; } 12 | 13 | /// 14 | /// 返回的状态信息 15 | /// 16 | [JsonProperty("info")] 17 | public string Info { get; set; } 18 | 19 | /// 20 | /// 转换之后的坐标。若有多个坐标,则用 “;”进行区分和间隔 21 | /// 22 | [JsonProperty("locations")] 23 | public string Locations { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/Direction/Stop.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace LBS.Amap.SDK.Models.Direction 4 | { 5 | /// 6 | /// 站点信息 7 | /// 8 | public class Stop 9 | { 10 | /// 11 | /// 站点名字 12 | /// 13 | [JsonProperty("name")] 14 | public string Name { get; set; } 15 | 16 | /// 17 | /// 站点id 18 | /// 19 | [JsonProperty("id")] 20 | public string Id { get; set; } 21 | 22 | /// 23 | /// 站点经纬度 24 | /// 25 | [JsonProperty("id")] 26 | public string Location { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /scf/stat/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "easycaching": { 3 | "redis": { 4 | "MaxRdSecond": 120, 5 | "EnableLogging": false, 6 | "LockMs": 5000, 7 | "SleepMs": 300, 8 | "dbconfig": { 9 | "Password": null, 10 | "IsSsl": false, 11 | "SslHost": null, 12 | "ConnectionTimeout": 5000, 13 | "AllowAdmin": true, 14 | "Endpoints": [ 15 | { 16 | "Host": "10.1.0.2", 17 | "Port": 6379 18 | } 19 | ], 20 | "Database": 11 21 | } 22 | } 23 | }, 24 | "WxCloud": { 25 | "AppID": "wx4d40eb9199e605e1", 26 | "AppSecret": "xxxxx", 27 | "Env": "findjob-dev-xxxx" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /scf/XUnitTestFindJobStat/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "easycaching": { 3 | "redis": { 4 | "MaxRdSecond": 120, 5 | "EnableLogging": false, 6 | "LockMs": 5000, 7 | "SleepMs": 300, 8 | "dbconfig": { 9 | "Password": null, 10 | "IsSsl": false, 11 | "SslHost": null, 12 | "ConnectionTimeout": 5000, 13 | "AllowAdmin": true, 14 | "Endpoints": [ 15 | { 16 | "Host": "10.1.0.2", 17 | "Port": 6379 18 | } 19 | ], 20 | "Database": 11 21 | } 22 | } 23 | }, 24 | "WxCloud": { 25 | "AppID": "wx4d40eb9199e605e1", 26 | "AppSecret": "xxxxxx", 27 | "Env": "findjob-dev-xxxx" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/AmapUriConst.cs: -------------------------------------------------------------------------------- 1 | namespace LBS.Amap.SDK 2 | { 3 | internal static class AmapUriConst 4 | { 5 | public static string ConvertCoordinate = "/v3/assistant/coordinate/convert"; 6 | public static string District = "/v3/config/district"; 7 | public static string GeoCode = "/v3/geocode/geo"; 8 | public static string ReGeoCode = "/v3/geocode/regeo"; 9 | public static string IPLocation = "/v3/ip"; 10 | public static string StaticMap = "/v3/staticmap"; 11 | public static string InputTips = "/v3/assistant/inputtips"; 12 | public static string DirectionWalking = "/v3/direction/walking"; 13 | public static string Weather = "/v3/weather/weatherInfo"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /cloudfunctions/get-stat-top-city/index.js: -------------------------------------------------------------------------------- 1 | const cloud = require('wx-server-sdk') 2 | cloud.init() 3 | const db = cloud.database() 4 | const $ = db.command.aggregate 5 | 6 | exports.main = async () => { 7 | return (await db.collection('stats') 8 | .aggregate() 9 | .match({ 10 | type: "search" 11 | }) 12 | .group({ 13 | _id: '$extra.city', 14 | count: $.sum(1) 15 | }) 16 | .project({ 17 | _id: $.cond({ 18 | if: $.eq(["$_id", ""]), 19 | then: "城市不限", 20 | else: "$_id" 21 | }), 22 | count: 1 23 | }) 24 | .sort({ 25 | count: 1, 26 | }) 27 | .limit(10) 28 | .end()).list; 29 | } -------------------------------------------------------------------------------- /scf/Yhd.TencentCloud.SCF/Executors/IFunctionInvoker.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Yhd Tech. All rights reserved. 2 | // Licensed under the MIT License. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Yhd.TencentCloud.SCF.Executors 10 | { 11 | public interface IFunctionInvoker 12 | { 13 | /// 14 | /// process event , simply return event and request id. 15 | /// 16 | /// 17 | /// 18 | /// 19 | Task ProcessEvent(string responseBody, SCFContext context); 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/Direction/WalkingRoute.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace LBS.Amap.SDK.Models.Direction 5 | { 6 | /// 7 | /// 步行路线信息 8 | /// 9 | public class WalkingRoute 10 | { 11 | /// 12 | /// 起点坐标 13 | /// 14 | [JsonProperty("origin")] 15 | public string Origin { get; set; } 16 | 17 | /// 18 | /// 终点坐标 19 | /// 20 | [JsonProperty("destination")] 21 | public string Destination { get; set; } 22 | 23 | /// 24 | /// 步行方案 25 | /// 26 | [JsonProperty("paths")] 27 | public List Paths { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/CoordinateConvertParameter.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace LBS.Amap.SDK.Models 4 | { 5 | /// 6 | /// 坐标转换请求参数 7 | /// 8 | public class CoordinateConvertParameter : BaseParameter 9 | { 10 | /// 11 | /// 坐标点 12 | /// 13 | [Display(Name = "locations")] 14 | public string Locations { get; set; } 15 | 16 | /// 17 | /// 原坐标系 18 | /// 19 | [Display(Name = "coordsys")] 20 | public string Coordsys { get; set; } 21 | 22 | /// 23 | /// 数字签名 24 | /// 25 | [Display(Name = "sig")] 26 | public string Sig { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct行为准则 2 | ## 项目名称:快速找工作 3 | 4 | 作为该项目的贡献者和维护者,为了建立一个开放而热情的社区,我们承诺尊重所有通过报告问题,发布功能请求,更新文档,提交请求或补丁以及其他活动做出积极贡献的人。 5 | 6 | 参与者不可接受的行为包括: 7 | - 使用性化语言或图像 8 | * 人身攻击 9 | + 引战或侮辱性/贬损性评论 10 | - 公开或私人骚扰 11 | * 未经明确许可,发布他人的私人信息,例如物理或电子地址 12 | + 其他侵犯其他开发者合法权益的行为 13 | - 其他不道德或不专业的行为 14 | 15 | 项目维护者有权并有责任删除,编辑或拒绝与本行为准则不符的评论,承诺,代码,Wiki编辑,问题和其他贡献,或暂时或永久禁止任何贡献者从事其他行为他们认为这是不适当的,威胁性的,冒犯性的或有害的。 16 | 通过采用本《行为准则》,项目维护者承诺将公平,一致地将这些原则应用于项目管理的各个方面。不遵守或不执行行为准则的项目维护者可能会从项目团队中永久撤职。 17 | 18 | 当个人代表项目或其社区时,本行为准则适用于项目空间和公共空间。 19 | 20 | 可以通过与 geffzhang@weyhd.com 的项目维护人员联系来举报侵权,骚扰或其他不可接受的行为,包括主题为行为准则的主题(标有“您的问题”的字段)。所有的投诉都将得到审查和调查,并将根据情况做出认为是必要和适当的回应。维护者有义务对事件的举报人保密。 21 | 22 | 本行为准则改编自 Contributor Covenant 1.3.0版,网址为 https://www.contributor-covenant.org/version/1/3/0/code-of-conduct.html 23 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/Direction/Path.cs: -------------------------------------------------------------------------------- 1 | using LBS.Amap.SDK.Json; 2 | using Newtonsoft.Json; 3 | using System.Collections.Generic; 4 | 5 | namespace LBS.Amap.SDK.Models.Direction 6 | { 7 | /// 8 | /// 步行方案 9 | /// 10 | public class Path 11 | { 12 | /// 13 | /// 起点和终点的步行距离(单位:米) 14 | /// 15 | [JsonProperty("distance")] 16 | public string Distance { get; set; } 17 | 18 | /// 19 | /// 步行时间预计(单位:秒) 20 | /// 21 | [JsonProperty("duration")] 22 | public string Duration { get; set; } 23 | 24 | /// 25 | /// 步行结果列表 26 | /// 27 | [JsonProperty("steps")] 28 | public List Steps { get; set; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/Direction/IntegratedResponse.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace LBS.Amap.SDK.Models.Direction 7 | { 8 | /// 9 | /// 公交规划响应结果 10 | /// 11 | public class IntegratedResponse 12 | { 13 | /// 14 | /// 状态 15 | /// 16 | [JsonProperty("status")] 17 | public string Status { get; set; } 18 | 19 | /// 20 | /// 状态信息 21 | /// 22 | [JsonProperty("info")] 23 | public string Info { get; set; } 24 | 25 | /// 26 | /// 公交换乘方案数目 27 | /// 28 | [JsonProperty("count")] 29 | public string Count { get; set; } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /miniprogram/consts.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | CITYS: ["地区不限", "北京市", "上海市", "深圳市", "广州市", "杭州市", "成都市", "南京市", "武汉市", "西安市", "厦门市", "长沙市", "苏州市", "天津市", "重庆市", "郑州市", "青岛市", "合肥市", "福州市", "济南市", "大连市", "珠海市", "无锡市", "佛山市", "东莞市", "宁波市", "常州市", "沈阳市", "石家庄市", "昆明市", "南昌市", "南宁市", "哈尔滨市", "海口市", "中山市", "惠州市", "贵阳市", "长春市", "太原市", "嘉兴市", "泰安市", "昆山市", "烟台市", "兰州市", "泉州市"], 3 | SITES: [{ 4 | name: "来源不限", 5 | value: "0-1-2" 6 | }, { 7 | name: "智联招聘", 8 | logo: "logo_zhilian.png", 9 | value: 0 10 | }, { 11 | name: "前程无忧", 12 | logo: "logo_qianchengwuyou.png", 13 | value: 1 14 | }, { 15 | name: "猎聘网", 16 | logo: "logo_liepin.png", 17 | value: 2 18 | }, { 19 | name: "BOOS直聘", 20 | logo: 'logo_boss.png', 21 | value: 3 22 | }] 23 | } -------------------------------------------------------------------------------- /scf/Yhd.TencentCloud.SCF/Yhd.TencentCloud.SCF.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/TipResponse.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace LBS.Amap.SDK.Models 5 | { 6 | public class TipResponse 7 | { 8 | /// 9 | /// 返回状态 10 | /// 11 | [JsonProperty("status")] 12 | public string Status { get; set; } 13 | 14 | /// 15 | /// 返回的状态信息 16 | /// 17 | [JsonProperty("info")] 18 | public string Info { get; set; } 19 | 20 | /// 21 | /// 返回结果总数目 22 | /// 23 | [JsonProperty("count")] 24 | public string Count { get; set; } 25 | 26 | /// 27 | /// 建议提示列表 28 | /// 29 | [JsonProperty("tips")] 30 | public ICollection Tips { get; set; } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /scf/Yhd.TencentCloud.SCF/Hosting/ISCFBuilder.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Yhd Tech. All rights reserved. 2 | // Licensed under the MIT License. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | using Microsoft.Extensions.Configuration; 8 | using Microsoft.Extensions.DependencyInjection; 9 | 10 | namespace Yhd.TencentCloud.SCF.Hosting 11 | { 12 | public interface ISCFBuilder 13 | { 14 | /// 15 | /// Gets the where scf services are configured. 16 | /// 17 | IServiceCollection Services { get; } 18 | 19 | /// 20 | /// Gets the where scf configurations 21 | /// 22 | IConfigurationRoot Configuration { get; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/DependencyInjection/AmapOptionsServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using LBS.Amap.SDK; 2 | using Microsoft.Extensions.Configuration; 3 | 4 | namespace Microsoft.Extensions.DependencyInjection 5 | { 6 | public static class AmapOptionsServiceCollectionExtensions 7 | { 8 | public static IServiceCollection AddAmapOptions(this IServiceCollection services, IConfiguration config, string sectionName = "Amap") 9 | { 10 | services.AddOptions().Configure(options => 11 | { 12 | var amapSection = config.GetSection(sectionName); 13 | amapSection.Bind(options); 14 | 15 | }).Validate(options => 16 | { 17 | return !string.IsNullOrWhiteSpace(options.Key); 18 | }, "Amap Key is empty"); 19 | 20 | return services; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/Direction/WalkingResponse.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace LBS.Amap.SDK.Models.Direction 4 | { 5 | /// 6 | /// 步行路径规划结果 7 | /// 8 | public class WalkingResponse 9 | { 10 | /// 11 | /// 状态 12 | /// 13 | [JsonProperty("status")] 14 | public string Status { get; set; } 15 | 16 | /// 17 | /// 状态信息 18 | /// 19 | [JsonProperty("info")] 20 | public string Info { get; set; } 21 | 22 | /// 23 | /// 结果总数目 24 | /// 25 | [JsonProperty("count")] 26 | public string Count { get; set; } 27 | 28 | /// 29 | /// 路线信息 30 | /// 31 | [JsonProperty("route")] 32 | public WalkingRoute Route { get; set; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/ReGeoResponse.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace LBS.Amap.SDK.Models 7 | { 8 | public class ReGeoResponse 9 | { 10 | /// 11 | /// 返回结果状态值 12 | /// 13 | [JsonProperty("status")] 14 | public string Status { get; set; } 15 | 16 | /// 17 | /// 返回结果数目 18 | /// 19 | [JsonProperty("infocode")] 20 | public string Infocode { get; set; } 21 | 22 | /// 23 | /// 返回状态说明 24 | /// 25 | [JsonProperty("info")] 26 | public string Info { get; set; } 27 | 28 | 29 | /// 30 | /// 地址详细信息 31 | /// 32 | [JsonProperty("regeocode")] 33 | public ReGeoCode ReGeoCode { get; set; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /scf/Yhd.TencentCloud.SCF/Hosting/SCFBuilder.cs: -------------------------------------------------------------------------------- 1 | 2 | // Copyright (c) Yhd Tech. All rights reserved. 3 | // Licensed under the MIT License. See License.txt in the project root for license information.using Microsoft.Extensions.Configuration; 4 | 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using System; 8 | 9 | namespace Yhd.TencentCloud.SCF.Hosting 10 | { 11 | internal class SCFBuilder : ISCFBuilder 12 | { 13 | public SCFBuilder(IServiceCollection services, IConfigurationRoot configuration) 14 | { 15 | Services = services ?? throw new ArgumentNullException(nameof(services)); 16 | Configuration = configuration?? throw new ArgumentNullException(nameof(configuration)); 17 | } 18 | 19 | public IServiceCollection Services { get; } 20 | 21 | 22 | public IConfigurationRoot Configuration { get; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/GeoResponse.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace LBS.Amap.SDK.Models 5 | { 6 | /// 7 | /// 地理/逆地理编码查询响应 8 | /// 9 | public class GeoResponse 10 | { 11 | /// 12 | /// 返回结果状态值 13 | /// 14 | [JsonProperty("status")] 15 | public string Status { get; set; } 16 | 17 | /// 18 | /// 返回结果数目 19 | /// 20 | [JsonProperty("count")] 21 | public string Count { get; set; } 22 | 23 | /// 24 | /// 返回状态说明 25 | /// 26 | [JsonProperty("info")] 27 | public string Info { get; set; } 28 | 29 | /// 30 | /// 地理编码信息列表 31 | /// 32 | [JsonProperty("geocodes")] 33 | public List GeoCodes { get; set; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /scf/Yhd.FindJobStat/Yhd.FindJobStat.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net.Http; 3 | using System.Collections.Generic; 4 | using System.Threading.Tasks; 5 | using System.Text; 6 | using Microsoft.AspNetCore.Components.WebAssembly.Hosting; 7 | using Microsoft.Extensions.Configuration; 8 | using Microsoft.Extensions.DependencyInjection; 9 | using Microsoft.Extensions.Logging; 10 | 11 | namespace FindJobBlazorSite 12 | { 13 | public class Program 14 | { 15 | public static async Task Main(string[] args) 16 | { 17 | var builder = WebAssemblyHostBuilder.CreateDefault(args); 18 | builder.RootComponents.Add("app"); 19 | 20 | builder.Services.AddTransient(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); 21 | builder.Services.AddSingleton(); 22 | 23 | await builder.Build().RunAsync(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Json/AmapStringConverter.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Linq; 3 | using System; 4 | 5 | namespace LBS.Amap.SDK.Json 6 | { 7 | internal class AmapStringConverter : JsonConverter 8 | { 9 | public override bool CanConvert(Type objectType) 10 | { 11 | return objectType == typeof(string); 12 | } 13 | 14 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 15 | { 16 | JToken token = JToken.Load(reader); 17 | if (token.Type == JTokenType.String) 18 | { 19 | return (string)token; 20 | } 21 | 22 | return null; 23 | } 24 | 25 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 26 | { 27 | serializer.Serialize(writer, value); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Extensions/DictionaryExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Web; 5 | 6 | namespace LBS.Amap.SDK 7 | { 8 | internal static class DictionaryExtensions 9 | { 10 | public static string ToUriParam(this IDictionary dict) 11 | { 12 | if (dict == null) 13 | throw new ArgumentNullException(nameof(dict)); 14 | 15 | if (dict.Count <= 0) 16 | return string.Empty; 17 | 18 | StringBuilder sb = new StringBuilder(); 19 | foreach (KeyValuePair kv in dict) 20 | { 21 | sb.Append(kv.Key); 22 | sb.Append("="); 23 | sb.Append(HttpUtility.UrlEncode(kv.Value)); 24 | sb.Append("&"); 25 | } 26 | 27 | return sb.Remove(sb.Length - 1, 1).ToString(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/Direction/WalkingParameter.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace LBS.Amap.SDK.Models.Direction 4 | { 5 | /// 6 | /// 路径规划参数 7 | /// 8 | public class WalkingParameter : BaseParameter 9 | { 10 | /// 11 | /// 出发点经纬度 12 | /// 13 | [Display(Name = "origin")] 14 | public string Origin { get; set; } 15 | 16 | /// 17 | /// 目的地经纬度 18 | /// 19 | [Display(Name = "destination")] 20 | public string Destination { get; set; } 21 | 22 | /// 23 | /// 数字签名 24 | /// 25 | [Display(Name = "sig")] 26 | public string Sig { get; set; } 27 | 28 | /// 29 | /// 回调函数 30 | /// 31 | [Display(Name = "callback")] 32 | public string CallBack { get; set; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/Direction/Segment.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace LBS.Amap.SDK.Models.Direction 7 | { 8 | /// 9 | /// 换乘路段列表 10 | /// 11 | public class Segment 12 | { 13 | /// 14 | /// 此路段步行导航信息 15 | /// 16 | [JsonProperty("walking")] 17 | public Path Walking { get; set; } 18 | 19 | /// 20 | /// 此路段公交导航信息 21 | /// 22 | [JsonProperty("bus")] 23 | public Bus Bus { get; set; } 24 | 25 | /// 26 | /// 地铁入口 27 | /// 28 | [JsonProperty("entrance")] 29 | public Gateway Entrance { get; set; } 30 | 31 | /// 32 | /// 地铁出口 33 | /// 34 | [JsonProperty("exit")] 35 | public Gateway Exit { get; set; } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/FindJobBlazorSite.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.1 5 | 3.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /scf/Yhd.FindJobStat/ServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | 6 | namespace Yhd.FindJobStat 7 | { 8 | public static class ServiceCollectionExtensions 9 | { 10 | public static IServiceCollection AddFindJobStat(this IServiceCollection services, IConfiguration configuration) 11 | { 12 | if (services == null) 13 | { 14 | throw new ArgumentNullException(nameof(services)); 15 | } 16 | 17 | Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); 18 | services.Configure(configuration.GetSection("WxCloud")); 19 | services.AddSingleton(); 20 | services.AddSingleton(); 21 | services.AddSingleton(); 22 | 23 | return services; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /scf/XUnitTestFindJob/XUnitTestFindJob.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | PreserveNewest 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /scf/Yhd.FindJob/IJobsManager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | 4 | namespace Yhd.FindJob 5 | { 6 | public interface IJobsManager 7 | { 8 | /// 9 | /// 获取岗位详细信息 10 | /// 11 | /// 12 | /// 13 | /// 14 | Task GetDetailsInfo(string source, string url); 15 | 16 | /// 17 | /// 获取查询岗位数据的简要信息 18 | /// 19 | /// 来源列表 20 | /// 21 | /// 22 | /// 23 | /// 24 | Task> GetJobsAsync(List sources, string city, string searchKey, int pageIndex); 25 | 26 | Task> GetJobsAsync(string source,string city, string searchKey, int pageIndex); 27 | } 28 | } -------------------------------------------------------------------------------- /cloudfunctions/save-favorite/index.js: -------------------------------------------------------------------------------- 1 | const cloud = require('wx-server-sdk') 2 | cloud.init() 3 | const db = cloud.database() 4 | 5 | exports.main = async (event, context) => { 6 | const openId = cloud.getWXContext().OPENID; 7 | var favorite = await db.collection('favorites').where({ 8 | openId: openId, 9 | url: event.url 10 | }).get(); 11 | if (favorite.data.length == 0) { 12 | var favoriteInfo = { 13 | openId: openId, 14 | source: event.source, 15 | url: event.url, 16 | jobTitle: event.jobTitle, 17 | area: event.area, 18 | salary: event.salary, 19 | jobCompany: event.jobCompany, 20 | time: event.time, 21 | logo: event.logo 22 | }; 23 | await db.collection('favorites').add({ 24 | data: favoriteInfo 25 | }); 26 | return true 27 | } 28 | await db.collection('favorites').doc(favorite.data[0]._id).remove(); 29 | return false 30 | } -------------------------------------------------------------------------------- /scf/Yhd.TencentCloud.SCF/Hosting/SCFBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | 2 | // Copyright (c) Yhd Tech. All rights reserved. 3 | // Licensed under the MIT License. See License.txt in the project root for license information.using Microsoft.Extensions.Configuration; 4 | 5 | using System; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.DependencyInjection.Extensions; 8 | using Yhd.TencentCloud.SCF.Hosting; 9 | 10 | namespace Yhd.TencentCloud.SCF 11 | { 12 | public static class SCFBuilderExtensions 13 | { 14 | /// 15 | /// Adds builtin bindings 16 | /// 17 | /// 18 | /// 19 | public static ISCFBuilder AddBuiltInBindings(this ISCFBuilder builder) 20 | { 21 | if (builder == null) 22 | { 23 | throw new ArgumentNullException(nameof(builder)); 24 | } 25 | 26 | return builder; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:65039", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", 15 | "environmentVariables": { 16 | "ASPNETCORE_ENVIRONMENT": "Development" 17 | } 18 | }, 19 | "FindJobBlazorSite": { 20 | "commandName": "Project", 21 | "launchBrowser": true, 22 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", 23 | "applicationUrl": "http://localhost:5000", 24 | "environmentVariables": { 25 | "ASPNETCORE_ENVIRONMENT": "Development" 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/LBS.Amap.SDK.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | W 6 | 7 | 8 | 9 | 10 | 11 | <_Parameter1>$(AssemblyName).Tests 12 | 13 | 14 | <_Parameter1>DynamicProxyGenAssembly2 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /scf/Yhd.TencentCloud.SCF/Protocols/RequestIdentity.cs: -------------------------------------------------------------------------------- 1 | 2 | // Copyright (c) Yhd Tech. All rights reserved. 3 | // Licensed under the MIT License. See License.txt in the project root for license information.using Microsoft.Extensions.Configuration; 4 | 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | 10 | namespace Yhd.TencentCloud.SCF.Protocols 11 | { 12 | public class RequestIdentity 13 | { 14 | 15 | public RequestIdentity() { } 16 | 17 | public string SecretId { get; set; } 18 | 19 | 20 | public override bool Equals(object obj) 21 | { 22 | if (this == obj) 23 | return true; 24 | if (obj == null || GetType() != obj.GetType()) 25 | return false; 26 | RequestIdentity that = obj as RequestIdentity; 27 | return SecretId.Equals(that.SecretId); 28 | } 29 | 30 | public override int GetHashCode() 31 | { 32 | return SecretId.GetHashCode(); 33 | } 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | ## 2020-08-17 2 | - 新建小程序项目 findjob 3 | 4 | ## 2020-08-20 5 | - 封装scf 云函数的核心逻辑 6 | - scf 函数的API网关代理函数封装 7 | - 在SCFContext 中传递配置的函数Handler名称,用于封装函数,用于指定开发规范 8 | 9 | ## 2020-08-21 10 | - 封装findjob 逻辑 11 | - 添加redis 缓存,使用EasyCaching组件 12 | - 采用线程安全的集合 13 | 14 | ## 2020-08-22 15 | - 迁入小程序基础版本,添加职位页面和我的页面,完成用户登录功能 16 | - 封装云函数 17 | - 修改redis 缓存 18 | 19 | ## 2020-08-23 20 | - 修改 scf bootstrap file 格式 21 | 22 | ## 2020-08-24 23 | - 添加经纬度转换为城市接口 24 | - 接入 /api/jobs/getjobs 接口 25 | - 完成首页列表展示 26 | - 完成城市定位功能 27 | 28 | ## 2020-08-25 29 | - 接入 /api/jobs/getdetailsinfo 接口 30 | - 完成职位详情界面,并显示数据 31 | - 完成收藏列表界面,并显示数据 32 | - 提取配置到配置文件 33 | - 更新文件 SCFServiceCollectionExtensions.cs 34 | 35 | ## 2020-08-26 36 | 37 | - 完成小程序全部功能 38 | - 优化 redis 缓存 39 | 40 | ## 2020-08-28 41 | - 新增 echart 图表 42 | 43 | ## 2020-08-31 44 | - 完善统计功能。小程序提交各种统计数据到服务器。 45 | - echart 问题,移除小程序端的统计界面 46 | 47 | ## 2020-09-06 48 | - 增加 Blazor 统计网站模板 49 | 50 | ## 2020-09-08 51 | - 增加 scf Yhd.FindJobStat 项目 52 | - 增加 scf XUnitTestFindJobStat 项目 53 | - 增加 scf stat 项目 54 | 55 | ## 2020-09-09 56 | - 完成 Blazor 运营网站 57 | -------------------------------------------------------------------------------- /scf/Yhd.FindJob/Yhd.FindJob.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /scf/Yhd.FindJob/DetailsInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Yhd.FindJob 6 | { 7 | /// 8 | /// 详情 9 | /// 10 | [Serializable] 11 | public class DetailsInfo 12 | { 13 | /// 14 | /// 学历要求 15 | /// 16 | public string Education { get; set; } 17 | 18 | /// 19 | /// 工作经验 20 | /// 21 | public string Experience { get; set; } 22 | 23 | /// 24 | /// 公司性质 25 | /// 26 | public string CompanyNature { get; set; } 27 | 28 | /// 29 | /// 公司规模 30 | /// 31 | public string CompanySize { get; set; } 32 | 33 | /// 34 | /// 详细要求 【职位描述】 35 | /// 36 | public string Requirement { get; set; } 37 | 38 | /// 39 | /// 公司介绍 40 | /// 41 | public string CompanyIntroduction { get; set; } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /scf/Yhd.FindJobStat/Model.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace Yhd.FindJobStat 4 | { 5 | /// 6 | /// 错误模型类 7 | /// 8 | public class ErrorModel 9 | { 10 | [JsonProperty("errcode")] 11 | public int ErrorCode { get; set; } 12 | 13 | [JsonProperty("errmsg")] 14 | public string ErrorMessage { get; set; } 15 | 16 | public bool HasError() 17 | { 18 | return ErrorCode > 0; 19 | } 20 | } 21 | 22 | /// 23 | /// AccessToken 模型类 24 | /// 25 | public class AccessTokenModel : ErrorModel 26 | { 27 | [JsonProperty("access_token")] 28 | public string AccessToken { get; set; } 29 | 30 | [JsonProperty("expires_in")] 31 | public int ExpiresIn { get; set; } 32 | } 33 | 34 | /// 35 | /// 微信云开发云函数调用结果模型类 36 | /// 37 | public class WxCloudInvokeCloudFunctionModel : ErrorModel 38 | { 39 | [JsonProperty("resp_data")] 40 | public string ResponseData { get; set; } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/ForeCast.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace LBS.Amap.SDK.Models 5 | { 6 | /// 7 | /// 预报天气信息数据 8 | /// 9 | public class ForeCast 10 | { 11 | /// 12 | /// 城市名称 13 | /// 14 | [JsonProperty("city")] 15 | public string City { get; set; } 16 | 17 | /// 18 | /// 城市编码 19 | /// 20 | [JsonProperty("adcode")] 21 | public string AdCode { get; set; } 22 | 23 | /// 24 | /// 省份名称 25 | /// 26 | [JsonProperty("province")] 27 | public string Province { get; set; } 28 | 29 | /// 30 | /// 预报发布时间 31 | /// 32 | [JsonProperty("reporttime")] 33 | public string ReportTime { get; set; } 34 | 35 | /// 36 | /// 预报数据集合,元素cast,按顺序为当天、第二天、第三天的预报数据 37 | /// 38 | [JsonProperty("casts")] 39 | public ICollection Casts { get; set; } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /scf/Yhd.FindJob/JobInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Yhd.FindJob 4 | { 5 | /// 6 | /// 简要信息 7 | /// 8 | [Serializable] 9 | public class JobInfo 10 | { 11 | /// 12 | /// 职位名称 13 | /// 14 | public string PositionName { get; set; } 15 | 16 | /// 17 | /// 公司名称 18 | /// 19 | public string CorporateName { get; set; } 20 | 21 | /// 22 | /// 薪水 23 | /// 24 | public string Salary { get; set; } 25 | 26 | /// 27 | /// 工作地点 28 | /// 29 | public string WorkingPlace { get; set; } 30 | 31 | /// 32 | /// 发布日期 33 | /// 34 | public string ReleaseDate { get; set; } 35 | 36 | /// 37 | /// 详情url 38 | /// 39 | public string DetailsUrl { get; set; } 40 | 41 | /// 42 | /// 岗位来源 43 | /// 44 | public string Source { get; set; } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 dotnetcloudbase 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /scf/Yhd.FindJob/ServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using EasyCaching.Core.Configurations; 2 | using EasyCaching.Redis; 3 | using LBS.Amap.SDK; 4 | using Microsoft.Extensions.Configuration; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Microsoft.Extensions.DependencyInjection.Extensions; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Text; 10 | 11 | namespace Yhd.FindJob 12 | { 13 | public static class ServiceCollectionExtensions 14 | { 15 | public static IServiceCollection AddFindJob(this IServiceCollection services, IConfiguration configuration) 16 | { 17 | if (services == null) 18 | { 19 | throw new ArgumentNullException(nameof(services)); 20 | } 21 | 22 | services.AddAmapOptions(configuration); 23 | services.AddLBSAmap(); 24 | Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); 25 | services.AddSingleton(); 26 | services.AddSingleton(); 27 | 28 | 29 | return services; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/Tip.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace LBS.Amap.SDK.Models 4 | { 5 | /// 6 | /// 提示信息 7 | /// 8 | public class Tip 9 | { 10 | /// 11 | /// 提示信息 12 | /// 13 | [JsonProperty("id")] 14 | public string Id { get; set; } 15 | 16 | /// 17 | /// tip名称 18 | /// 19 | [JsonProperty("name")] 20 | public string Name { get; set; } 21 | 22 | /// 23 | /// 所属区域 24 | /// 25 | [JsonProperty("district")] 26 | public string District { get; set; } 27 | 28 | /// 29 | /// 区域编码 30 | /// 31 | [JsonProperty("adcode")] 32 | public string AdCode { get; set; } 33 | 34 | /// 35 | /// tip中心点坐标 36 | /// 37 | [JsonProperty("location")] 38 | public string Location { get; set; } 39 | 40 | /// 41 | /// 详细地址 42 | /// 43 | [JsonProperty("address")] 44 | public string Address { get; set; } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/wwwroot/css/open-iconic/ICON-LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Waybury 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /scf/XUnitTestFindJobStat/XUnitTestFindJobStat.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | runtime; build; native; contentfiles; analyzers; buildtransitive 14 | all 15 | 16 | 17 | runtime; build; native; contentfiles; analyzers; buildtransitive 18 | all 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | PreserveNewest 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /scf/Yhd.TencentCloud.SCF/SCFContext.cs: -------------------------------------------------------------------------------- 1 | 2 | // Copyright (c) Yhd Tech. All rights reserved. 3 | // Licensed under the MIT License. See License.txt in the project root for license information.using Microsoft.Extensions.Configuration; 4 | 5 | namespace Yhd.TencentCloud.SCF 6 | { 7 | public class SCFContext 8 | { 9 | public string RequestId { get; private set; } 10 | 11 | public string Handler { get; private set; } 12 | 13 | public int TimeLimitInMs { get; private set; } 14 | 15 | public int MemoryLimitInMb { get; private set; } 16 | 17 | 18 | public SCFContext(string requestId, string handler, int timeLimitInMs, int memoryLimitInMb) 19 | { 20 | RequestId = requestId; 21 | Handler = handler; 22 | TimeLimitInMs = timeLimitInMs; 23 | MemoryLimitInMb = memoryLimitInMb; 24 | } 25 | 26 | 27 | public override string ToString() 28 | { 29 | 30 | return "{" + 31 | "RequestId='" + RequestId + '\'' + 32 | "TimeLimitInMs" + TimeLimitInMs + '\'' + 33 | "MemoryLimitInMb" + MemoryLimitInMb + '\'' + 34 | '}'; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /scf/stat/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using Microsoft.Extensions.Hosting; 3 | using System.Threading.Tasks; 4 | using Yhd.TencentCloud.SCF.Executors; 5 | using Yhd.FindJobStat; 6 | 7 | public class Stat 8 | { 9 | static async Task Main(string[] args) 10 | { 11 | var builder = new HostBuilder() 12 | .ConfigureSCF((context, scfbuilder) => 13 | { 14 | var configuration = scfbuilder.Configuration; 15 | scfbuilder.Services.AddEasyCaching(options => 16 | { 17 | options.UseInMemory(); 18 | //use redis cache that named redis 19 | options.UseRedis(configuration).WithJson(); 20 | }); 21 | scfbuilder.Services.AddSingleton(configuration); 22 | scfbuilder.Services.AddFindJobStat(configuration); 23 | scfbuilder.Services.AddTransient(); 24 | 25 | }) 26 | .UseConsoleLifetime(); 27 | 28 | 29 | var host = builder.Build(); 30 | 31 | using (host) 32 | { 33 | await host.RunAsync(); 34 | } 35 | 36 | } 37 | } -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/DistrictResponse.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace LBS.Amap.SDK.Models 5 | { 6 | /// 7 | /// 行政区域查询响应 8 | /// 9 | public class DistrictResponse 10 | { 11 | /// 12 | /// 结果状态值 13 | /// 14 | /// 值为0或1,0表示失败;1表示成功 15 | [JsonProperty("status")] 16 | public string Status { get; set; } 17 | 18 | /// 19 | /// 状态说明 20 | /// 21 | /// 返回状态说明,status为0时,info返回错误原因,否则返回“OK” 22 | [JsonProperty("info")] 23 | public string Info { get; set; } 24 | 25 | /// 26 | /// 状态码 27 | /// 28 | [JsonProperty("infocode")] 29 | public string InfoCode { get; set; } 30 | 31 | /// 32 | /// 建议结果列表 33 | /// 34 | [JsonProperty("suggestion")] 35 | public Suggestion Suggestion { get; set; } 36 | 37 | /// 38 | /// 行政区列表 39 | /// 40 | [JsonProperty("districts")] 41 | public List Districts { get; set; } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Extensions/ModelExtensions.cs: -------------------------------------------------------------------------------- 1 | using LBS.Amap.SDK.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.Reflection; 6 | 7 | namespace LBS.Amap.SDK 8 | { 9 | internal static class ModelExtensions 10 | { 11 | public static string ToUriParam(this BaseParameter obj) 12 | { 13 | if (obj == null) 14 | throw new ArgumentNullException(nameof(obj)); 15 | 16 | PropertyInfo[] propertis = obj.GetType().GetProperties(); 17 | SortedDictionary paramDict = new SortedDictionary(); 18 | foreach (var p in propertis) 19 | { 20 | var v = p.GetValue(obj, null); 21 | if (v == null) 22 | continue; 23 | 24 | paramDict.Add(GetName(p), v.ToString()); 25 | } 26 | 27 | return paramDict.ToUriParam(); 28 | } 29 | 30 | private static string GetName(PropertyInfo p) 31 | { 32 | DisplayAttribute attribute = p.GetCustomAttribute(); 33 | return attribute != null ? attribute.Name : p.Name; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30413.136 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FindJobBlazorSite", "FindJobBlazorSite\FindJobBlazorSite.csproj", "{474D72AD-D14D-4127-ABA1-CF41B3301F22}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {474D72AD-D14D-4127-ABA1-CF41B3301F22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {474D72AD-D14D-4127-ABA1-CF41B3301F22}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {474D72AD-D14D-4127-ABA1-CF41B3301F22}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {474D72AD-D14D-4127-ABA1-CF41B3301F22}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {D4A08384-3E29-4B7E-8630-255285909873} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /miniprogram/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages": [ 3 | "pages/job/index", 4 | "pages/job/detail", 5 | "pages/my/my", 6 | "pages/my/favorites", 7 | "pages/my/about" 8 | ], 9 | "window": { 10 | "backgroundColor": "#F6F6F6", 11 | "backgroundTextStyle": "light", 12 | "navigationBarBackgroundColor": "#0081ff", 13 | "navigationBarTitleText": "Find Job", 14 | "navigationBarTextStyle": "white" 15 | }, 16 | "tabBar": { 17 | "color": "#999999", 18 | "selectedColor": "#0081ff", 19 | "list": [ 20 | { 21 | "pagePath": "pages/job/index", 22 | "text": "职位", 23 | "iconPath": "images/ic_job_gray.png", 24 | "selectedIconPath": "images/ic_job.png" 25 | }, 26 | { 27 | "pagePath": "pages/my/my", 28 | "text": "我的", 29 | "iconPath": "images/ic_my_gray.png", 30 | "selectedIconPath": "images/ic_my.png" 31 | } 32 | ] 33 | }, 34 | "sitemapLocation": "sitemap.json", 35 | "style": "v2", 36 | "permission": { 37 | "scope.userLocation": { 38 | "desc": "你的位置信息将用于定位当前城市" 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/WeatherResponse.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace LBS.Amap.SDK.Models 5 | { 6 | /// 7 | /// 天气数据响应 8 | /// 9 | public class WeatherResponse 10 | { 11 | /// 12 | /// 返回状态 13 | /// 14 | [JsonProperty("status")] 15 | public string Status { get; set; } 16 | 17 | /// 18 | /// 返回结果总数目 19 | /// 20 | [JsonProperty("count")] 21 | public string Count { get; set; } 22 | 23 | /// 24 | /// 返回的状态信息 25 | /// 26 | [JsonProperty("info")] 27 | public string Info { get; set; } 28 | 29 | /// 30 | /// 返回状态说明 31 | /// 32 | [JsonProperty("infocode")] 33 | public string InfoCode { get; set; } 34 | 35 | /// 36 | /// 实况天气数据信息集合 37 | /// 38 | [JsonProperty("lives")] 39 | public ICollection Lives { get; set; } 40 | 41 | /// 42 | /// 预报天气信息数据 43 | /// 44 | [JsonProperty("forecasts")] 45 | public ICollection ForeCasts { get; set; } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /scf/index/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.Hosting; 4 | using Microsoft.Extensions.Logging; 5 | using System.Threading.Tasks; 6 | using Yhd.FindJob; 7 | using Yhd.TencentCloud.SCF.Executors; 8 | 9 | public class Index 10 | { 11 | static async Task Main(string[] args) 12 | { 13 | var builder = new HostBuilder() 14 | .ConfigureSCF((context, scfbuilder) => 15 | { 16 | var configuration = scfbuilder.Configuration; 17 | 18 | scfbuilder.Services.AddFindJob(configuration); 19 | scfbuilder.Services.AddEasyCaching(options => 20 | { 21 | options.UseInMemory(); 22 | //use redis cache that named redis 23 | options.UseRedis(configuration) 24 | .WithJson() 25 | ; 26 | }); 27 | scfbuilder.Services.AddTransient(); 28 | 29 | }) 30 | .UseConsoleLifetime(); 31 | 32 | 33 | var host = builder.Build(); 34 | 35 | using (host) 36 | { 37 | await host.RunAsync(); 38 | } 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /scf/Yhd.TencentCloud.SCF/Protocols/APIGatewayProxyResponseEvent.cs: -------------------------------------------------------------------------------- 1 | 2 | // Copyright (c) Yhd Tech. All rights reserved. 3 | // Licensed under the MIT License. See License.txt in the project root for license information.using Microsoft.Extensions.Configuration; 4 | 5 | using Newtonsoft.Json; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | 10 | namespace Yhd.TencentCloud.SCF.Protocols 11 | { 12 | 13 | /// 14 | /// Class that represents an APIGatewayProxyResponseEvent object 15 | /// 16 | public class APIGatewayProxyResponseEvent { 17 | 18 | public int StatusCode { get; set; } 19 | 20 | public Dictionary Headers { get; set; } 21 | public string Body { get; set; } 22 | public bool IsBase64Encoded { get; set; } 23 | 24 | public int ErrorCode { get; set; } 25 | 26 | public string ErrorMessage { get; set; } 27 | /** 28 | * default constructor 29 | */ 30 | public APIGatewayProxyResponseEvent() { 31 | Headers = new Dictionary(); 32 | StatusCode = 200; 33 | } 34 | 35 | public override string ToString() 36 | { 37 | return JsonConvert.SerializeObject(this); 38 | } 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /miniprogram/pages/my/favorites.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{item.jobTitle}} 6 | {{item.salary}} 7 | 8 | {{item.jobCompany}} 9 | 10 | 11 | | {{item.area}} 12 | 13 | {{item.time}} 14 | 15 | 16 | 17 | —— 长按删除收藏记录 —— 18 | 19 | 20 | 21 | 暂无收藏职位 22 | -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/wwwroot/images/spinner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /deployment.md: -------------------------------------------------------------------------------- 1 | ## 在开发者工具中新建项目 2 | 3 | 打开微信开发者工具,添加小程序项目,选择合适的文件夹,使用自己的APP ID,勾选云开发服务,新建项目。 4 | 5 | ## 下载代码 6 | 7 | 进入到项目目录中删除所有文件,使用如下命令将代码下载到本地: 8 | 9 | ```bash 10 | git clone https://github.com/dotnetcloudbase/findjobtclooud.git 11 | ``` 12 | 把findjobtclooud文件夹中文件剪切到小程序项目根目录 13 | 14 | ## 初始化云环境并修改参数 15 | 16 | 点击开发者工具的云开发,启用云服务。新建自己的云环境,复制云环境ID,然后把`app.js`和所有`cloudfunctions`文件夹下所有云函数的`index.js`中的: 17 | 18 | ```javascript 19 | cloud.init({ 20 | env: "xxxxxx" // 替换成自己的云环境ID 21 | }) 22 | ``` 23 | 24 | 其中的`env`的值替换成自己的云环境ID。 25 | 26 | ## 云数据库初始化 27 | 28 | 在《微信开发者工具》里顶部菜单里点击“云开发”,打开“云开发控制台”,切换到“数据库”界面,在左侧的集合名称面板,添加 “favorites”、“stats”、“users” 三个集合。完成云数据库初始化。 29 | 30 | ## 部署云开发云函数 31 | 32 | 右击`cloudfunctions`,选择当前云环境。 33 | 34 | 分别右击`get-stat-apply, get-stat-pv, get-stat-top-city, get-stat-top-search, is-favorite, post-stat, save-favorite, user-favorite, user-login`云函数,选择在终端打开,输入如下命令安装依赖: 35 | 36 | ```bash 37 | npm install --save tcb-router 38 | ``` 39 | 40 | ## 部署腾讯云SCF云函数 41 | 42 | SCF 云函数的部署参见[在腾讯云云函数计算上部署.NET Core 3.1](https://www.cnblogs.com/shanyou/p/scf-dotnet-customruntime.html) 43 | 44 | ## 部署Api网关 45 | 46 | 云函数通过API网关发布,具体发布文档参见[api网关和云函数](https://docs.qq.com/doc/DWHJ5VnNuWmFYcEV0?pub=1&dver=2.1.0) 47 | 48 | ## 运行小程序项目 49 | 50 | 点击编译,运行项目。 51 | 52 | ## 部署运营网站 53 | 54 | 运营网站的部署参见 [腾讯云 云开发 部署 Blazor网站](https://www.cnblogs.com/shanyou/p/13645172.html) 55 | -------------------------------------------------------------------------------- /scf/Yhd.TencentCloud.SCF/Hosting/SCFHostService.cs: -------------------------------------------------------------------------------- 1 | 2 | // Copyright (c) Yhd Tech. All rights reserved. 3 | // Licensed under the MIT License. See License.txt in the project root for license information.using Microsoft.Extensions.Configuration; 4 | 5 | using Microsoft.Extensions.Hosting; 6 | using Microsoft.Extensions.Logging; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Text; 10 | using System.Threading; 11 | using System.Threading.Tasks; 12 | 13 | namespace Yhd.TencentCloud.SCF.Hosting 14 | { 15 | public class SCFHostService : IHostedService 16 | { 17 | private readonly ILogger _logger; 18 | private readonly ISCFHost _scfHost; 19 | 20 | public SCFHostService(ISCFHost jobhost, ILogger logger) 21 | { 22 | _logger = logger ?? throw new ArgumentNullException(nameof(logger)); 23 | _scfHost = jobhost; 24 | } 25 | 26 | public Task StartAsync(CancellationToken cancellationToken) 27 | { 28 | _logger.LogInformation("Starting SCFHost"); 29 | return _scfHost.StartAsync(cancellationToken); 30 | } 31 | 32 | public Task StopAsync(CancellationToken cancellationToken) 33 | { 34 | _logger.LogInformation("Stopping SCFHost"); 35 | return _scfHost.StopAsync(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/IPLocationResponse.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace LBS.Amap.SDK.Models 4 | { 5 | /// 6 | /// IP定位接口响应 7 | /// 8 | public class IPLocationResponse 9 | { 10 | /// 11 | /// 返回结果状态值 12 | /// 13 | [JsonProperty("status")] 14 | public string Status { get; set; } 15 | 16 | /// 17 | /// 返回状态说明 18 | /// 19 | [JsonProperty("info")] 20 | public string Info { get; set; } 21 | 22 | /// 23 | /// infocode 24 | /// 25 | [JsonProperty("infocode")] 26 | public string InfoCode { get; set; } 27 | 28 | /// 29 | /// 省份名称 30 | /// 31 | [JsonProperty("province")] 32 | public string Province { get; set; } 33 | 34 | /// 35 | /// 城市名称 36 | /// 37 | [JsonProperty("city")] 38 | public string City { get; set; } 39 | 40 | /// 41 | /// 城市的adcode编码 42 | /// 43 | [JsonProperty("adcode")] 44 | public string AdCode { get; set; } 45 | 46 | /// 47 | /// 所在城市矩形区域范围 48 | /// 49 | [JsonProperty("rectangle")] 50 | public string Rectangle { get; set; } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/wwwroot/js/loader.js: -------------------------------------------------------------------------------- 1 | var startLoader = function (progressElement, textElement) { 2 | /* 3 | * Loader/splash screen 4 | * */ 5 | if (!window.XMLHttpRequest) { 6 | return; 7 | } 8 | var loading = {}; 9 | var files = []; 10 | var total = 0; 11 | var loaded = 0; 12 | var proxied = window.XMLHttpRequest.prototype.open; 13 | window.XMLHttpRequest.prototype.open = function () { 14 | var file = arguments[1]; 15 | files.push(file); 16 | total++; 17 | loading[file] = 1; 18 | this.addEventListener("load", function () { 19 | delete (loading[file]); 20 | loaded++; 21 | var progress = Math.floor(((loaded / total) * 100)); 22 | if (progressElement) { 23 | progressElement.max = total; 24 | progressElement.value = loaded; 25 | } 26 | if (textElement) { 27 | textElement.innerHTML = "Loaded " + file + ", " + progress + " %..." 28 | } 29 | if (loaded == total) { 30 | window.XMLHttpRequest.prototype.open = proxied; 31 | if (textElement) { 32 | textElement.innerHTML = "Loading 100%, opening application..."; 33 | } 34 | } 35 | }); 36 | return proxied.apply(this, [].slice.call(arguments)); 37 | }; 38 | } -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/ReGeoParameter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Text; 5 | 6 | namespace LBS.Amap.SDK.Models 7 | { 8 | public class ReGeoParameter : BaseParameter 9 | { 10 | /// 11 | /// 经纬度坐标;最多支持20个坐标点;多个点之间用"|"分割。 12 | /// 13 | [Display(Name = "location")] 14 | public string Location { get; set; } 15 | 16 | /// 17 | /// batch=true为批量查询。batch=false为单点查询 18 | /// 19 | [Display(Name = "batch")] 20 | public bool Batch { get; set; } 21 | 22 | /// 23 | /// 查询POI的半径范围。取值范围:0~3000,单位:米 24 | /// 25 | [Display(Name = "radius")] 26 | public int Radius { get; set; } 27 | 28 | 29 | /// 30 | /// 返回结果控制 31 | /// 32 | [Display(Name = "extensions")] 33 | public string Extensions { get; set; } 34 | 35 | /// 36 | /// 可选值:1,当roadlevel=1时,过滤非主干道路,仅输出主干道路数据 37 | /// 38 | [Display(Name = "roadlevel")] 39 | public int RoadLevel { get; set; } 40 | 41 | /// 42 | /// 支持传入POI TYPECODE及名称;支持传入多个POI类型,多值间用“|”分隔 43 | /// 44 | [Display(Name = "poitype")] 45 | public string Poitype { get; set; } 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/Shared/StatTopCityChart.razor: -------------------------------------------------------------------------------- 1 | @inject WxCloudApi WxCloud 2 | 3 | 4 | @if (statData == null) 5 | { 6 |

图表正在加载中...

7 | } 8 | 9 | @code { 10 | PieConfig chartConfig = new PieConfig 11 | { 12 | Height = 650, 13 | Title = new Title 14 | { 15 | Visible = true, 16 | Text = "FindJob 搜索城市 Top10 排行榜" 17 | }, 18 | Description = new Description 19 | { 20 | Visible = true, 21 | Text = "本图表统计 FindJob 搜索次数最多的城市", 22 | }, 23 | ForceFit = true, 24 | Padding = "auto", 25 | Meta = new 26 | { 27 | _id = new 28 | { 29 | Alias = "城市" 30 | }, 31 | count = new 32 | { 33 | Alias = "搜索次数" 34 | } 35 | }, 36 | AngleField = "count", 37 | ColorField = "_id", 38 | Label = new PieLabelConfig 39 | { 40 | Visible = true, 41 | Type = "inner" 42 | } 43 | }; 44 | 45 | IChartComponent chartInstance = null; 46 | IEnumerable statData = null; 47 | 48 | protected override async Task OnInitializedAsync() 49 | { 50 | statData = (await WxCloud.GetStatTopCity()).OrderByDescending(p => p.Value); 51 | await chartInstance.ChangeData(statData); 52 | } 53 | } -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/Shared/StatTopSearchChart.razor: -------------------------------------------------------------------------------- 1 | @inject WxCloudApi WxCloud 2 | 3 | 4 | @if (statData == null) 5 | { 6 |

图表正在加载中...

7 | } 8 | 9 | @code { 10 | BarConfig chartConfig = new BarConfig 11 | { 12 | Height = 650, 13 | Title = new Title 14 | { 15 | Visible = true, 16 | Text = "FindJob 搜索关键词 Top10 排行榜" 17 | }, 18 | Description = new Description 19 | { 20 | Visible = true, 21 | Text = "本图表统计 FindJob 搜索次数最多的关键词", 22 | }, 23 | ForceFit = true, 24 | Padding = "auto", 25 | XField = "count", 26 | YField = "_id", 27 | Meta = new 28 | { 29 | _id = new 30 | { 31 | Alias = "关键词" 32 | }, 33 | count = new 34 | { 35 | Alias = "搜索次数" 36 | } 37 | }, 38 | Label = new BarViewConfigLabel 39 | { 40 | Visible = true, 41 | Position = "left" 42 | } 43 | }; 44 | 45 | IChartComponent chartInstance = null; 46 | IEnumerable statData = null; 47 | 48 | protected override async Task OnInitializedAsync() 49 | { 50 | statData = (await WxCloud.GetStatTopSearch()).OrderByDescending(p => p.Value); 51 | await chartInstance.ChangeData(statData); 52 | } 53 | } -------------------------------------------------------------------------------- /scf/Yhd.FindJob/FindJobFactory.cs: -------------------------------------------------------------------------------- 1 | using EasyCaching.Core; 2 | using System; 3 | 4 | namespace Yhd.FindJob 5 | { 6 | public interface IFindJobFactory 7 | { 8 | IFindJob Get(string source); 9 | } 10 | 11 | public class FindJobFactory : IFindJobFactory 12 | { 13 | private IEasyCachingProvider _provider; 14 | 15 | public FindJobFactory(IEasyCachingProvider provider) 16 | { 17 | _provider = provider; 18 | } 19 | 20 | public IFindJob Get(string source) 21 | { 22 | IFindJob findJob = null; 23 | RecruitEnum enumRecruit = (RecruitEnum)Enum.Parse(typeof(RecruitEnum), source); 24 | switch(enumRecruit) 25 | { 26 | case RecruitEnum.BOSS: 27 | findJob = new FindBossJob(_provider); 28 | break; 29 | case RecruitEnum.Lagou: 30 | findJob = new FindLagouJob(_provider); 31 | break; 32 | case RecruitEnum.Liepin: 33 | findJob = new FindLiepinJob(_provider); 34 | break; 35 | case RecruitEnum.QC51: 36 | findJob = new FindQCJob(_provider); 37 | break; 38 | case RecruitEnum.ZLZhaopin: 39 | findJob = new FindZhaopinJob(_provider); 40 | break; 41 | } 42 | return findJob; 43 | 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/wwwroot/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | FindJob 统计 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 |
18 |

Loading...

19 |
20 | 21 |
22 | 23 | 24 | 25 |
26 | 27 |
28 | An unhandled error has occurred. 29 | Reload 30 | 🗙 31 |
32 | 33 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /scf/Yhd.TencentCloud.SCF/Config/SCFHostOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Yhd Tech. All rights reserved. 2 | // Licensed under the MIT License. See License.txt in the project root for license information. 3 | 4 | namespace Yhd.TencentCloud.SCF 5 | { 6 | /// 7 | /// Represents the configuration settings for a . 8 | /// 9 | public sealed class SCFHostOptions 10 | { 11 | /// 12 | /// Returns true if has been called on this instance. 13 | /// 14 | internal bool UsingDevelopmentSettings { get; set; } 15 | 16 | 17 | /// 18 | /// Gets or sets a value indicating whether the host should be able to start partially 19 | /// when some functions are in error. The default is false. 20 | /// 21 | /// 22 | /// Normally when a function encounters an indexing error or its listener fails to start 23 | /// the error will propagate and the host will not start. However, with this option set, 24 | /// the host will be allowed to start in "partial" mode: 25 | /// - Functions without errors will run normally 26 | /// - Functions with indexing errors will not be running 27 | /// - Functions listener startup failures will be retried in the background 28 | /// until they start. 29 | /// 30 | public bool AllowPartialHostStartup { get; set; } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /scf/XUnitTestFindJobStat/AccessTokenManagerTest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Threading.Tasks; 6 | using Xunit; 7 | using Xunit.Abstractions; 8 | using Yhd.FindJobStat; 9 | using Yhd.TencentCloud.SCF.Config; 10 | 11 | namespace XUnitTestFindJobStat 12 | { 13 | public class AccessTokenManagerTest 14 | { 15 | private readonly IServiceCollection _services; 16 | private readonly IServiceProvider _serviceProvider; 17 | private readonly IConfiguration _configRoot; 18 | 19 | public AccessTokenManagerTest() 20 | { 21 | _configRoot = AppConfigurations.Get(Environment.CurrentDirectory); 22 | _services = new ServiceCollection(); 23 | _services.AddFindJobStat(_configRoot); 24 | _services.AddEasyCaching(options => 25 | { 26 | options.UseInMemory(); 27 | }); 28 | _services.AddSingleton(_configRoot); 29 | _serviceProvider = _services.BuildServiceProvider(); 30 | System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance); 31 | } 32 | 33 | [Fact] 34 | public async Task TestGetAccessToken() 35 | { 36 | var accessTokenManager = _serviceProvider.GetService(); 37 | var token = await accessTokenManager.GetAccessToken(); 38 | Assert.NotNull(token); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/AddressComponent.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace LBS.Amap.SDK.Models 7 | { 8 | public class AddressComponent 9 | { 10 | /// 11 | /// 国家 12 | /// 13 | [JsonProperty("country")] 14 | public string Country { get; set; } 15 | 16 | /// 17 | /// 地址所在的省份名 18 | /// 19 | [JsonProperty("province")] 20 | public string Province { get; set; } 21 | 22 | /// 23 | /// 地址所在的城市名 24 | /// 25 | [JsonProperty("city")] 26 | public string City { get; set; } 27 | 28 | /// 29 | /// 城市编码 30 | /// 31 | [JsonProperty("citycode")] 32 | public string CityCode { get; set; } 33 | 34 | /// 35 | /// 地址所在的区 36 | /// 37 | [JsonProperty("district")] 38 | public string District { get; set; } 39 | 40 | /// 41 | /// Adcode 42 | /// 43 | [JsonProperty("adcode")] 44 | public string Adcode { get; set; } 45 | 46 | /// 47 | /// 街道 48 | /// 49 | [JsonProperty("township")] 50 | public string Township { get; set; } 51 | 52 | /// 53 | /// 街道编码 54 | /// 55 | [JsonProperty("towncode")] 56 | public string Towncode { get; set; } 57 | 58 | 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/TipParameter.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace LBS.Amap.SDK.Models 4 | { 5 | /// 6 | /// 输入提示请求参数 7 | /// 8 | public class TipParameter : BaseParameter 9 | { 10 | /// 11 | /// 查询关键词 12 | /// 13 | [Display(Name = "keywords")] 14 | public string Keywords { get; set; } 15 | 16 | /// 17 | /// POI分类 18 | /// 19 | [Display(Name = "type")] 20 | public string Type { get; set; } 21 | 22 | /// 23 | /// 坐标 24 | /// 25 | [Display(Name = "location")] 26 | public string Location { get; set; } 27 | 28 | /// 29 | /// 搜索城市 30 | /// 31 | [Display(Name = "city")] 32 | public string City { get; set; } 33 | 34 | /// 35 | /// 仅返回指定城市数据 36 | /// 37 | [Display(Name = "citylimit")] 38 | public bool CityLimit { get; set; } 39 | 40 | /// 41 | /// 返回的数据类型 42 | /// 43 | [Display(Name = "datatype")] 44 | public string DataType { get; set; } 45 | 46 | /// 47 | /// 数字签名 48 | /// 49 | [Display(Name = "sig")] 50 | public string Sig { get; set; } 51 | 52 | /// 53 | /// 回调函数 54 | /// 55 | [Display(Name = "callback")] 56 | public string CallBack { get; set; } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/GeoParameter.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace LBS.Amap.SDK.Models 4 | { 5 | /// 6 | /// 地理编码参数 7 | /// 8 | public class GeoParameter : BaseParameter 9 | { 10 | /// 11 | /// 结构化地址信息 12 | ///
规则遵循:国家、省份、城市、区县、城镇、乡村、街道、门牌号码、屋邨、大厦
13 | ///
如果需要解析多个地址的话,请用"|"进行间隔,并且将 batch 参数设置为 true,最多支持 10 个地址进进行"|"分割形式的请求
14 | /// 北京市朝阳区阜通东大街6号 15 | ///
16 | [Display(Name = "address")] 17 | public string Address { get; set; } 18 | 19 | /// 20 | /// 指定查询的城市 21 | ///
可选输入内容包括:指定城市的中文(如北京)、指定城市的中文全拼(beijing)、citycode(010)、adcode(110000),不支持县级市
22 | ///
当指定城市查询内容为空时,会进行全国范围内的地址转换检索
23 | ///
24 | [Display(Name = "city")] 25 | public string City { get; set; } 26 | 27 | /// 28 | /// 批量查询控制 29 | /// 30 | [Display(Name = "batch")] 31 | public bool Batch { get; set; } = false; 32 | 33 | /// 34 | /// 数字签名 35 | /// 36 | /// 37 | [Display(Name = "sig")] 38 | public string Sig { get; set; } 39 | 40 | /// 41 | /// 回调函数 42 | ///
callback 值是用户定义的函数名称,此参数只在 output 参数设置为 JSON 时有效
43 | ///
44 | [Display(Name = "callback")] 45 | public string Callback { get; set; } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /miniprogram/pages/my/favorites.js: -------------------------------------------------------------------------------- 1 | const jobService = require("../../jobService"); 2 | Page({ 3 | data: { 4 | jobList: [] 5 | }, 6 | 7 | onLoad: function (options) { 8 | this.fetchMyFavorites(); 9 | jobService.statPreviewMyFavorite() 10 | }, 11 | 12 | onPullDownRefresh: function () { 13 | this.fetchMyFavorites(); 14 | }, 15 | 16 | onDeleteFavorite(e) { 17 | var that = this; 18 | var data = e.currentTarget.dataset.data; 19 | var url = data.detailsUrl; 20 | wx.showModal({ 21 | title: '询问', 22 | content: "确认要删除这条收藏记录吗?", 23 | success: function (res) { 24 | if (res.confirm) { 25 | jobService.deleteFavorite(url, (res) => { 26 | that.fetchMyFavorites(); 27 | }); 28 | } 29 | } 30 | }) 31 | }, 32 | 33 | fetchMyFavorites() { 34 | var that = this; 35 | wx.showLoading({ 36 | title: '加载中...' 37 | }); 38 | jobService.getMyFavorites((res) => { 39 | wx.hideLoading(); 40 | wx.stopPullDownRefresh() 41 | that.setData({ 42 | jobList: res || [] 43 | }); 44 | }); 45 | }, 46 | 47 | onViewJobDetail(e) { 48 | var data = e.currentTarget.dataset.data; 49 | wx.navigateTo({ 50 | url: `/pages/job/detail?title=${data.jobTitle}&salary=${data.salary}&area=${data.area}&company=${data.jobCompany}&time=${data.time}&source=${data.source}&url=${data.url}&logo=${data.logo}`, 51 | }) 52 | } 53 | }) -------------------------------------------------------------------------------- /scf/Yhd.TencentCloud.SCF/Config/AppConfigurations.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Yhd Tech. All rights reserved. 2 | // Licensed under the MIT License. See License.txt in the project root for license information. 3 | 4 | using Microsoft.Extensions.Configuration; 5 | using System.Collections.Concurrent; 6 | 7 | namespace Yhd.TencentCloud.SCF.Config 8 | { 9 | public static class AppConfigurations 10 | { 11 | private static readonly ConcurrentDictionary ConfigurationCache; 12 | 13 | static AppConfigurations() 14 | { 15 | ConfigurationCache = new ConcurrentDictionary(); 16 | } 17 | 18 | public static IConfigurationRoot Get(string path, string environmentName = null) 19 | { 20 | var cacheKey = path + "#" + environmentName; 21 | return ConfigurationCache.GetOrAdd( 22 | cacheKey, 23 | _ => BuildConfiguration(path, environmentName) 24 | ); 25 | } 26 | 27 | private static IConfigurationRoot BuildConfiguration(string path, string environmentName = null) 28 | { 29 | var builder = new ConfigurationBuilder() 30 | .SetBasePath(path) 31 | .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true); 32 | 33 | if (!string.IsNullOrWhiteSpace(environmentName)) 34 | { 35 | builder = builder.AddJsonFile($"appsettings.{environmentName}.json", optional: true); 36 | } 37 | 38 | builder = builder.AddEnvironmentVariables(); 39 | 40 | return builder.Build(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/DistrictParameter.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace LBS.Amap.SDK.Models 4 | { 5 | /// 6 | /// 行政区域请求参数 7 | /// 8 | public class DistrictParameter : BaseParameter 9 | { 10 | /// 11 | /// 查询关键字 12 | /// 13 | [Display(Name = "keywords")] 14 | public string Keywords { get; set; } 15 | 16 | /// 17 | /// 子级行政区 18 | /// 19 | /// 20 | /// 0:不返回下级行政区 21 | /// 1:返回下一级行政区 22 | /// 2:返回下两级行政区 23 | /// 3:返回下三级行政区 24 | /// 25 | [Display(Name = "subdistrict")] 26 | public int SubDistrict { get; set; } = 1; 27 | 28 | /// 29 | /// 需要第几页数据 30 | /// 31 | [Display(Name = "page")] 32 | public int Page { get; set; } = 1; 33 | 34 | /// 35 | /// 最外层返回数据个数 36 | /// 37 | [Display(Name = "offset")] 38 | public string Offset { get; set; } 39 | 40 | /// 41 | /// 返回结果控制 42 | /// 43 | [Display(Name = "extensions")] 44 | public string Extensions { get; set; } = "base"; 45 | 46 | /// 47 | /// 按照adcode过滤 48 | /// 49 | [Display(Name = "filter")] 50 | public string Filter { get; set; } 51 | 52 | /// 53 | /// 回调函数 54 | /// 55 | [Display(Name = "callback")] 56 | public string Callback { get; set; } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /scf/Yhd.FindJobStat/WxCloudApi.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Http; 2 | using System.Threading.Tasks; 3 | using Microsoft.Extensions.Options; 4 | using Newtonsoft.Json; 5 | 6 | namespace Yhd.FindJobStat 7 | { 8 | /// 9 | /// 小程序云开发 API 10 | /// 11 | public class WxCloudApi 12 | { 13 | private WxCloudOption _wxCloudOption; 14 | private IAccessTokenManager _accessTokenManager; 15 | 16 | public WxCloudApi(IOptions options, IAccessTokenManager accessTokenManager) 17 | { 18 | _wxCloudOption = options.Value; 19 | _accessTokenManager = accessTokenManager; 20 | } 21 | 22 | /// 23 | /// 调用小程序云开发云函数 24 | /// 25 | /// 26 | /// 27 | /// 28 | public async Task InvokeCloudFunction(string functionName, string postBody = "{}") 29 | { 30 | var accessToken = await _accessTokenManager.GetAccessToken(); 31 | var api = $"https://api.weixin.qq.com/tcb/invokecloudfunction?access_token={accessToken}&env={_wxCloudOption.Env}&name={functionName}"; 32 | using (var httpClient = new HttpClient()) 33 | { 34 | var response = await httpClient.PostAsync(api, new StringContent(postBody)); 35 | response.EnsureSuccessStatusCode(); 36 | var responseText = await response.Content.ReadAsStringAsync(); 37 | return JsonConvert.DeserializeObject(responseText); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/District.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace LBS.Amap.SDK.Models 5 | { 6 | /// 7 | /// 行政区信息 8 | /// 9 | public class District 10 | { 11 | /// 12 | /// 城市编码 13 | /// 14 | [JsonProperty("citycode")] 15 | public string CityCode { get; set; } 16 | 17 | /// 18 | /// 区域编码 19 | /// 20 | [JsonProperty("adcode")] 21 | public string AdCode { get; set; } 22 | 23 | /// 24 | /// 行政区名称 25 | /// 26 | [JsonProperty("name")] 27 | public string Name { get; set; } 28 | 29 | /// 30 | /// 行政区边界坐标点 31 | /// 32 | [JsonProperty("polyline")] 33 | public string PolyLine { get; set; } 34 | 35 | /// 36 | /// 区域中心点 37 | /// 38 | [JsonProperty("center")] 39 | public string Center { get; set; } 40 | 41 | /// 42 | /// 行政区划级别 43 | /// 44 | /// 45 | /// country:国家 46 | /// province:省份(直辖市会在province和city显示) 47 | /// city:市(直辖市会在province和city显示) 48 | /// district:区县 49 | /// street:街道 50 | /// 51 | [JsonProperty("level")] 52 | public string Level { get; set; } 53 | 54 | /// 55 | /// 下级行政区列表 56 | /// 57 | [JsonProperty("districts")] 58 | public List Districts { get; set; } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /miniprogram/pages/my/my.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{userInfo.nickName}} 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 我的收藏 24 | 25 | 26 | 27 | 28 | 29 | 30 | 34 | 35 | 36 | 40 | 41 | 42 | 43 | 44 | 关于小程序 45 | 46 | 47 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/Live.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace LBS.Amap.SDK.Models 4 | { 5 | /// 6 | /// 实况天气数据 7 | /// 8 | public class Live 9 | { 10 | /// 11 | /// 省份 12 | /// 13 | [JsonProperty("province")] 14 | public string Province { get; set; } 15 | 16 | /// 17 | /// 城市 18 | /// 19 | [JsonProperty("city")] 20 | public string City { get; set; } 21 | 22 | /// 23 | /// 区域编码 24 | /// 25 | [JsonProperty("adcode")] 26 | public string AdCode { get; set; } 27 | 28 | /// 29 | /// 天气现象 30 | /// 31 | [JsonProperty("weather")] 32 | public string Weather { get; set; } 33 | 34 | /// 35 | /// 实时气温,单位:摄氏度 36 | /// 37 | [JsonProperty("temperature")] 38 | public string Temperature { get; set; } 39 | 40 | /// 41 | /// 风向描述 42 | /// 43 | [JsonProperty("winddirection")] 44 | public string WindDirection { get; set; } 45 | 46 | /// 47 | /// 风力级别,单位:级 48 | /// 49 | [JsonProperty("windpower")] 50 | public string WindPower { get; set; } 51 | 52 | /// 53 | /// 空气湿度 54 | /// 55 | [JsonProperty("humidity")] 56 | public string Humidity { get; set; } 57 | 58 | /// 59 | /// 数据发布的时间 60 | /// 61 | [JsonProperty("reporttime")] 62 | public string ReportTime { get; set; } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /scf/Yhd.TencentCloud.SCF/Executors/HttpFunctionInvoker.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | using Newtonsoft.Json; 3 | using System; 4 | // Copyright (c) Yhd Tech. All rights reserved. 5 | // Licensed under the MIT License. See License.txt in the project root for license information. 6 | 7 | using System.Collections.Generic; 8 | using System.Net.Http.Headers; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using Yhd.TencentCloud.SCF.Protocols; 12 | 13 | namespace Yhd.TencentCloud.SCF.Executors 14 | { 15 | public class HttpFunctionInvoker : FunctionInvoker 16 | { 17 | private ILogger _logger; 18 | 19 | public HttpFunctionInvoker(ILoggerFactory loggerFactory) 20 | { 21 | _logger = loggerFactory.CreateLogger(); 22 | } 23 | 24 | public override async Task ProcessEvent(string responseBody, SCFContext context) 25 | { 26 | _logger.LogInformation($"start {context.Handler }"); 27 | 28 | APIGatewayProxyRequestEvent requestEvent = JsonConvert.DeserializeObject(responseBody); 29 | 30 | var response = await Handler(context, requestEvent); 31 | 32 | return response.ToString(); 33 | } 34 | 35 | protected virtual async Task Handler(SCFContext context, APIGatewayProxyRequestEvent requestEvent) 36 | { 37 | return new APIGatewayProxyResponseEvent() { 38 | StatusCode = 200, 39 | IsBase64Encoded = false, 40 | Headers = new Dictionary(), 41 | Body = requestEvent.ToString() 42 | }; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/StaticMapParameter.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace LBS.Amap.SDK.Models 4 | { 5 | /// 6 | /// 静态地图请求参数 7 | /// 8 | public class StaticMapParameter : BaseParameter 9 | { 10 | /// 11 | /// 地图中心点 12 | /// 13 | [Display(Name = "location")] 14 | public string Location { get; set; } 15 | 16 | /// 17 | /// 地图级别 18 | /// 19 | [Display(Name = "zoom")] 20 | public int? Zoom { get; set; } 21 | 22 | /// 23 | /// 地图大小 24 | /// 25 | [Display(Name = "size")] 26 | public string Size { get; set; } 27 | 28 | /// 29 | /// 清晰度 30 | /// 31 | [Display(Name = "scale")] 32 | public int Scale { get; set; } = 1; 33 | 34 | /// 35 | /// 标注 36 | /// 37 | [Display(Name = "markers")] 38 | public string Markers { get; set; } 39 | 40 | /// 41 | /// 标签 42 | /// 43 | [Display(Name = "labels")] 44 | public string Labels { get; set; } 45 | 46 | /// 47 | /// 折线 48 | /// 49 | [Display(Name = "paths")] 50 | public string Paths { get; set; } 51 | 52 | /// 53 | /// 交通路况标识 54 | /// 55 | [Display(Name = "traffic")] 56 | public int Traffic { get; set; } = 0; 57 | 58 | /// 59 | /// 数字签名 60 | /// 61 | [Display(Name = "sig")] 62 | public string Sig { get; set; } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /scf/Yhd.TencentCloud.SCF/Hosting/SCFServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.DependencyInjection.Extensions; 4 | 5 | // Copyright (c) Yhd Tech. All rights reserved. 6 | // Licensed under the MIT License. See License.txt in the project root for license information.using Microsoft.Extensions.Configuration; 7 | 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Text; 11 | using Yhd.TencentCloud.SCF.Executors; 12 | 13 | namespace Yhd.TencentCloud.SCF.Hosting 14 | { 15 | /// 16 | /// Extension methods for setting up SCF services in a . 17 | /// 18 | internal static class SCFServiceCollectionExtensions 19 | { 20 | /// 21 | /// Adds the SCF services to the provided . 22 | /// 23 | /// 24 | /// 25 | public static ISCFBuilder AddSCF(this IServiceCollection services, Action configure,IConfigurationRoot configuration) 26 | { 27 | if (services == null) 28 | { 29 | throw new ArgumentNullException(nameof(services)); 30 | } 31 | 32 | services.Configure(configure); 33 | 34 | // Core host services 35 | services.TryAddSingleton(); 36 | services.TryAddTransient(); 37 | var builder = new SCFBuilder(services, configuration); 38 | builder.AddBuiltInBindings(); 39 | 40 | return builder; 41 | } 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/Direction/Step.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace LBS.Amap.SDK.Models.Direction 4 | { 5 | /// 6 | /// 每段步行方案 7 | /// 8 | public class Step 9 | { 10 | /// 11 | /// 路段步行方案 12 | /// 13 | [JsonProperty("instruction")] 14 | public string Instruction { get; set; } 15 | 16 | /// 17 | /// 道路名称 18 | /// 19 | [JsonProperty("road")] 20 | public string Road { get; set; } 21 | 22 | /// 23 | /// 此路段距离(单位:米) 24 | /// 25 | [JsonProperty("distance")] 26 | public string Distance { get; set; } 27 | 28 | /// 29 | /// 方向 30 | /// 31 | [JsonProperty("orientation")] 32 | public string Orientation { get; set; } 33 | 34 | /// 35 | /// 此路段预计步行时间 36 | /// 37 | [JsonProperty("duration")] 38 | public string Duration { get; set; } 39 | 40 | /// 41 | /// 此路段坐标点 42 | /// 43 | [JsonProperty("polyline")] 44 | public string Polyline { get; set; } 45 | 46 | /// 47 | /// 步行主要动作 48 | /// 49 | [JsonProperty("action")] 50 | public string Action { get; set; } 51 | 52 | /// 53 | /// 步行辅助动作 54 | /// 55 | [JsonProperty("assistant_action")] 56 | public string AssistantAction { get; set; } 57 | 58 | /// 59 | /// 这段路是否存在特殊的方式 60 | /// 61 | [JsonProperty("walk_type")] 62 | public string WalkType { get; set; } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/Cast.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace LBS.Amap.SDK.Models 4 | { 5 | public class Cast 6 | { 7 | /// 8 | /// 日期 9 | /// 10 | [JsonProperty("date")] 11 | public string Date { get; set; } 12 | 13 | /// 14 | /// 星期几 15 | /// 16 | [JsonProperty("week")] 17 | public string Week { get; set; } 18 | 19 | /// 20 | /// 白天天气现象 21 | /// 22 | [JsonProperty("dayweather")] 23 | public string DayWeather { get; set; } 24 | 25 | /// 26 | /// 晚上天气现象 27 | /// 28 | [JsonProperty("nightweather")] 29 | public string NightWeather { get; set; } 30 | 31 | /// 32 | /// 白天温度 33 | /// 34 | [JsonProperty("daytemp")] 35 | public string DayTemp { get; set; } 36 | 37 | /// 38 | /// 晚上温度 39 | /// 40 | [JsonProperty("nighttemp")] 41 | public string NightTemp { get; set; } 42 | 43 | /// 44 | /// 白天风向 45 | /// 46 | [JsonProperty("daywind")] 47 | public string DayWind { get; set; } 48 | 49 | /// 50 | /// 晚上风向 51 | /// 52 | [JsonProperty("nightwind")] 53 | public string NightWind { get; set; } 54 | 55 | /// 56 | /// 白天风力 57 | /// 58 | [JsonProperty("daypower")] 59 | public string DayPower { get; set; } 60 | 61 | /// 62 | /// 晚上风力 63 | /// 64 | [JsonProperty("nightpower")] 65 | public string NightPower { get; set; } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/Shared/NavMenu.razor: -------------------------------------------------------------------------------- 1 | 7 | 8 |
9 | 36 |
37 | 38 | @code { 39 | private bool collapseNavMenu = true; 40 | 41 | private string NavMenuCssClass => collapseNavMenu ? "collapse" : null; 42 | 43 | private void ToggleNavMenu() 44 | { 45 | collapseNavMenu = !collapseNavMenu; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /scf/Yhd.TencentCloud.SCF/Protocols/APIGatewayProxyRequestEvent.cs: -------------------------------------------------------------------------------- 1 | 2 | // Copyright (c) Yhd Tech. All rights reserved. 3 | // Licensed under the MIT License. See License.txt in the project root for license information.using Microsoft.Extensions.Configuration; 4 | 5 | using Newtonsoft.Json; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | 10 | namespace Yhd.TencentCloud.SCF.Protocols 11 | { 12 | public class APIGatewayProxyRequestEvent 13 | { 14 | public ProxyRequestContext RequestContext { get; set; } 15 | public Dictionary Headers { get; set; } 16 | public string Body { get; set; } 17 | public Dictionary PathParameters { get; set; } 18 | public Dictionary QueryStringParameters { get; set; } 19 | public Dictionary HeaderParameters { get; set; } 20 | public Dictionary StageVariables { get; set; } 21 | public string Path { get; set; } 22 | public Dictionary QueryString { get; set; } 23 | public string HttpMethod { get; set; } 24 | 25 | 26 | /** 27 | * default constructor 28 | */ 29 | public APIGatewayProxyRequestEvent() 30 | { 31 | HeaderParameters = new Dictionary(); 32 | Headers = new Dictionary(); 33 | PathParameters = new Dictionary(); 34 | QueryString = new Dictionary(); 35 | QueryStringParameters = new Dictionary(); 36 | StageVariables = new Dictionary(); 37 | } 38 | 39 | 40 | public override string ToString() 41 | { 42 | return JsonConvert.SerializeObject(this); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /miniprogram/app.wxss: -------------------------------------------------------------------------------- 1 | @import "colorui/main.wxss"; 2 | @import "colorui/icon.wxss"; 3 | 4 | .text-darkgray { 5 | color: var(--darkGray); 6 | } 7 | 8 | .bg-none { 9 | background: none 10 | } 11 | 12 | .select-area view { 13 | width: 48%; 14 | height: 70rpx; 15 | line-height: 70rpx; 16 | display: block; 17 | } 18 | 19 | .select-area view:first-child { 20 | border-right: 1px solid #ededed; 21 | } 22 | 23 | .picker-site-logo { 24 | width: 80px; 25 | height: 40px; 26 | background-size: 100%; 27 | background-repeat: no-repeat; 28 | background-position: center; 29 | margin-top: 5px; 30 | } 31 | 32 | .picker-button-area { 33 | padding-left: 20rpx; 34 | padding-right: 20rpx; 35 | } 36 | 37 | .picker-button-area button+button { 38 | margin-left: 20rpx; 39 | } 40 | 41 | .empty-view { 42 | padding: 50rpx; 43 | } 44 | 45 | .empty-view .empty-icon { 46 | width: 300rpx; 47 | height: 300rpx; 48 | margin-left: auto; 49 | margin-right: auto; 50 | } 51 | 52 | .empty-view .empty-icon { 53 | display: block; 54 | width: 300rpx; 55 | height: 300rpx; 56 | } 57 | 58 | .job-list { 59 | width: 100% !important; 60 | overflow: hidden; 61 | } 62 | 63 | .filter-container { 64 | position: relative; 65 | } 66 | 67 | .filter-container.top { 68 | position: fixed; 69 | top: 0; 70 | width: 100%; 71 | z-index: 999; 72 | } 73 | 74 | .filter-container .picker { 75 | background: white; 76 | position: absolute; 77 | width: 100%; 78 | height: 200px; 79 | top: 100rpx; 80 | z-index: 1000; 81 | border-bottom: 1px solid #dddddd; 82 | } 83 | 84 | .echart-container { 85 | position: absolute; 86 | top: 0; 87 | bottom: 0; 88 | left: 0; 89 | right: 0; 90 | 91 | display: flex; 92 | flex-direction: column; 93 | align-items: flex-start; 94 | justify-content: space-between; 95 | box-sizing: border-box; 96 | 97 | padding-top: 15px; 98 | padding-bottom: 15px; 99 | } -------------------------------------------------------------------------------- /project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "miniprogramRoot": "miniprogram/", 3 | "cloudfunctionRoot": "cloudfunctions/", 4 | "setting": { 5 | "urlCheck": false, 6 | "es6": true, 7 | "enhance": true, 8 | "postcss": true, 9 | "preloadBackgroundData": false, 10 | "minified": true, 11 | "newFeature": true, 12 | "coverView": true, 13 | "nodeModules": false, 14 | "autoAudits": false, 15 | "showShadowRootInWxmlPanel": true, 16 | "scopeDataCheck": false, 17 | "uglifyFileName": false, 18 | "checkInvalidKey": true, 19 | "checkSiteMap": false, 20 | "uploadWithSourceMap": true, 21 | "compileHotReLoad": false, 22 | "babelSetting": { 23 | "ignore": [], 24 | "disablePlugins": [], 25 | "outputPath": "" 26 | }, 27 | "useIsolateContext": true, 28 | "useCompilerModule": true, 29 | "userConfirmedUseCompilerModuleSwitch": true 30 | }, 31 | "appid": "wx4d40eb9199e605e1", 32 | "projectname": "findjob", 33 | "libVersion": "2.9.3", 34 | "simulatorType": "wechat", 35 | "simulatorPluginLibVersion": {}, 36 | "condition": { 37 | "search": { 38 | "current": -1, 39 | "list": [] 40 | }, 41 | "conversation": { 42 | "current": -1, 43 | "list": [] 44 | }, 45 | "plugin": { 46 | "current": -1, 47 | "list": [] 48 | }, 49 | "game": { 50 | "list": [] 51 | }, 52 | "gamePlugin": { 53 | "current": -1, 54 | "list": [] 55 | }, 56 | "miniprogram": { 57 | "current": 0, 58 | "list": [ 59 | { 60 | "id": -1, 61 | "name": "db guide", 62 | "pathName": "pages/databaseGuide/databaseGuide", 63 | "query": "" 64 | }, 65 | { 66 | "id": -1, 67 | "name": "pages/job/detail", 68 | "pathName": "pages/job/detail", 69 | "query": "id=1", 70 | "scene": null 71 | }, 72 | { 73 | "id": -1, 74 | "name": "pages/stat/index", 75 | "pathName": "pages/stat/index", 76 | "scene": null 77 | } 78 | ] 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Http/AmapHttpClient.cs: -------------------------------------------------------------------------------- 1 | using LBS.Amap.SDK.Json; 2 | using LBS.Amap.SDK.Models; 3 | using Microsoft.Extensions.Options; 4 | using System; 5 | using System.Net.Http; 6 | using System.Threading.Tasks; 7 | 8 | namespace LBS.Amap.SDK.Http 9 | { 10 | internal class AmapHttpClient 11 | { 12 | private readonly HttpClient _client; 13 | private readonly IOptionsMonitor _options; 14 | public AmapHttpClient(HttpClient client, IOptionsMonitor options) 15 | { 16 | client.BaseAddress = new Uri("https://restapi.amap.com/"); 17 | _client = client; 18 | _options = options; 19 | } 20 | 21 | public async Task GetAsync(string uri, BaseParameter param) 22 | { 23 | var result = await GetAsync(uri, param); 24 | if (string.IsNullOrWhiteSpace(result)) 25 | return default(T); 26 | 27 | if (param.Output == "XML") 28 | { 29 | return AmapJsonConvert.DeserializeXmlObject(result); 30 | } 31 | 32 | return AmapJsonConvert.DeserializeObject(result); 33 | } 34 | 35 | public async Task GetAsync(string uri, BaseParameter param) 36 | { 37 | if (param == null) 38 | return string.Empty; 39 | 40 | var paramStr = param.ToUriParam(); 41 | paramStr += "&key=" + _options.CurrentValue.Key; 42 | return await _client.GetStringAsync($"{uri}?{paramStr}").ConfigureAwait(false); 43 | } 44 | 45 | public async Task GetByteArrayAsync(string uri, BaseParameter param) 46 | { 47 | var paramStr = param.ToUriParam(); 48 | paramStr += "&key=" + _options.CurrentValue.Key; 49 | return await _client.GetByteArrayAsync($"{uri}?{paramStr}").ConfigureAwait(false); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /scf/Yhd.TencentCloud.SCF/Protocols/ProxyRequestContext.cs: -------------------------------------------------------------------------------- 1 | 2 | // Copyright (c) Yhd Tech. All rights reserved. 3 | // Licensed under the MIT License. See License.txt in the project root for license information.using Microsoft.Extensions.Configuration; 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | 9 | namespace Yhd.TencentCloud.SCF.Protocols 10 | { 11 | public class ProxyRequestContext 12 | { 13 | public string ServiceId { get; set; } 14 | public string Path { get; set; } 15 | public string HttpMethod { get; set; } 16 | public string RequestId { get; set; } 17 | public RequestIdentity Identity { get; set; } 18 | public string SourceIp { get; set; } 19 | public string Stage { get; set; } 20 | 21 | /** 22 | * default constructor 23 | */ 24 | public ProxyRequestContext() { } 25 | 26 | 27 | public override bool Equals(object obj) 28 | { 29 | if (this == obj) 30 | return true; 31 | if (obj == null || GetType() != obj.GetType()) 32 | return false; 33 | ProxyRequestContext that = obj as ProxyRequestContext; 34 | return ServiceId.Equals(that.ServiceId) && 35 | Path.Equals(that.Path) && 36 | HttpMethod.Equals(that.HttpMethod) && 37 | RequestId.Equals( that.RequestId) && 38 | Identity.Equals(that.Identity) && 39 | SourceIp.Equals( that.SourceIp) && 40 | Stage.Equals(that.Stage); 41 | } 42 | 43 | public override int GetHashCode() 44 | { 45 | return ServiceId.GetHashCode() ^ Path.GetHashCode() ^ HttpMethod.GetHashCode() ^ RequestId.GetHashCode() ^ Identity.GetHashCode() ^ SourceIp.GetHashCode() ^ Stage.GetHashCode(); 46 | 47 | } 48 | 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /cloudfunctions/user-login/index.js: -------------------------------------------------------------------------------- 1 | const cloud = require('wx-server-sdk') 2 | cloud.init() 3 | const db = cloud.database() 4 | 5 | exports.main = async (event, context) => { 6 | const wxContext = cloud.getWXContext() 7 | const openId = wxContext.OPENID; 8 | 9 | var user = await db.collection('users').where({ 10 | openId: openId 11 | }).get(); 12 | if (user.data.length != 0) { 13 | var userInfo = user.data[0]; 14 | var id = userInfo._id; 15 | 16 | userInfo.avatarUrl = userInfo.avatarUrl || event.userInfo.avatarUrl; 17 | userInfo.country = userInfo.country || event.userInfo.country; 18 | userInfo.province = userInfo.province || event.userInfo.province; 19 | userInfo.city = userInfo.city || event.userInfo.city; 20 | userInfo.gender = typeof (userInfo.gender) === "number" ? userInfo.gender : event.userInfo.gender; 21 | userInfo.language = userInfo.language || event.userInfo.language; 22 | userInfo.nickName = userInfo.nickName || event.userInfo.nickName; 23 | userInfo.unionId = wxContext.UNIONID || ""; 24 | 25 | delete userInfo._id; 26 | 27 | await db.collection('users').doc(id).update({ 28 | data: userInfo 29 | }); 30 | 31 | return userInfo; 32 | } else { 33 | var userInfo = event.userInfo; 34 | userInfo.avatarUrl = userInfo.avatarUrl || null; 35 | userInfo.country = userInfo.country || null; 36 | userInfo.province = userInfo.province || null; 37 | userInfo.city = userInfo.city || null; 38 | userInfo.gender = typeof (userInfo.gender) === "number" ? userInfo.gender : 0; 39 | userInfo.language = userInfo.language || "zh_CN"; 40 | userInfo.nickName = userInfo.nickName || null; 41 | userInfo.openId = wxContext.OPENID; 42 | userInfo.unionId = wxContext.UNIONID || ""; 43 | 44 | await db.collection('users').add({ 45 | data: userInfo 46 | }); 47 | return userInfo; 48 | } 49 | } -------------------------------------------------------------------------------- /miniprogram/pages/job/detail.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{jobDetail.jobTitle}} 4 | {{jobDetail.salary}} 5 | {{jobDetail.area}} | {{jobDetail.industry}} 6 | 7 | 8 | 9 | 10 | 11 | 公司简介 12 | 13 | 14 | 15 | {{jobDetail.companySize}} 16 | {{jobDetail.companyIntroduction}} 17 | 18 | 19 | 20 | 21 | 职位要求 22 | 23 | 24 | 25 | 学历:{{jobDetail.education}} 26 | 经验:{{jobDetail.experience}} 27 | {{jobDetail.requirement}} 28 | 29 | 30 | 34 | 44 | 申请职位 45 | 46 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Json/AmapJsonConvert.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Xml; 3 | 4 | namespace LBS.Amap.SDK.Json 5 | { 6 | internal static class AmapJsonConvert 7 | { 8 | public static T DeserializeObject(string json) 9 | { 10 | return JsonConvert.DeserializeObject(json, new AmapStringConverter()); 11 | } 12 | 13 | public static T DeserializeXmlObject(string xml) 14 | { 15 | if (string.IsNullOrWhiteSpace(xml)) 16 | return default(T); 17 | 18 | XmlDocument XmlDoc = new XmlDocument(); 19 | XmlDoc.LoadXml(xml); 20 | AddJsonNetRootAttribute(XmlDoc); 21 | AddJsonArrayAttributesForXPath(XmlDoc); 22 | var json = JsonConvert.SerializeXmlNode(XmlDoc); 23 | return JsonConvert.DeserializeObject>(json).Data; 24 | } 25 | 26 | class XmlResponse 27 | { 28 | [JsonProperty("response")] 29 | public T Data { get; set; } 30 | } 31 | 32 | private static void AddJsonNetRootAttribute(XmlDocument xmlD) 33 | { 34 | XmlAttribute jsonNS = xmlD.CreateAttribute("xmlns", "json", "http://www.w3.org/2000/xmlns/"); 35 | jsonNS.Value = "http://james.newtonking.com/projects/json"; 36 | xmlD.DocumentElement.SetAttributeNode(jsonNS); 37 | } 38 | 39 | private static void AddJsonArrayAttributesForXPath(XmlDocument doc) 40 | { 41 | var elements = doc.SelectNodes("//*[@type='list']"); 42 | foreach (var element in elements) 43 | { 44 | var el = element as XmlElement; 45 | if (el != null) 46 | { 47 | var jsonArray = doc.CreateAttribute("json", "Array", "http://james.newtonking.com/projects/json"); 48 | jsonArray.Value = "true"; 49 | el.SetAttributeNode(jsonArray); 50 | } 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/GeoCode.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace LBS.Amap.SDK.Models 4 | { 5 | /// 6 | /// 地理编码信息 7 | /// 8 | public class GeoCode 9 | { 10 | /// 11 | /// 结构化地址信息 12 | /// 13 | [JsonProperty("formatted_address")] 14 | public string FormattedAddress { get; set; } 15 | 16 | /// 17 | /// 国家 18 | /// 19 | [JsonProperty("country")] 20 | public string Country { get; set; } 21 | 22 | /// 23 | /// 地址所在的省份名 24 | /// 25 | [JsonProperty("province")] 26 | public string Province { get; set; } 27 | 28 | /// 29 | /// 地址所在的城市名 30 | /// 31 | [JsonProperty("city")] 32 | public string City { get; set; } 33 | 34 | /// 35 | /// 城市编码 36 | /// 37 | [JsonProperty("citycode")] 38 | public string CityCode { get; set; } 39 | 40 | /// 41 | /// 地址所在的区 42 | /// 43 | [JsonProperty("district")] 44 | public string District { get; set; } 45 | 46 | /// 47 | /// 街道 48 | /// 49 | [JsonProperty("street")] 50 | public string Street { get; set; } 51 | 52 | /// 53 | /// 门牌 54 | /// 55 | [JsonProperty("number")] 56 | public string Number { get; set; } 57 | 58 | /// 59 | /// 区域编码 60 | /// 61 | [JsonProperty("adcode")] 62 | public string AdCode { get; set; } 63 | 64 | /// 65 | /// 坐标点 66 | /// 67 | [JsonProperty("location")] 68 | public string Location { get; set; } 69 | 70 | /// 71 | /// 匹配级别 72 | /// 73 | [JsonProperty("level")] 74 | public string Level { get; set; } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/Direction/BusLine.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace LBS.Amap.SDK.Models.Direction 5 | { 6 | public class BusLine 7 | { 8 | /// 9 | /// 起乘站 10 | /// 11 | [JsonProperty("departure_stop")] 12 | public Stop DepartureStop { get; set; } 13 | 14 | /// 15 | /// 到达站 16 | /// 17 | [JsonProperty("arrival_stop")] 18 | public Stop ArrivalStop { get; set; } 19 | 20 | /// 21 | /// 公交路线名称 22 | /// 23 | [JsonProperty("name")] 24 | public string Name { get; set; } 25 | 26 | /// 27 | /// 公交路线id 28 | /// 29 | [JsonProperty("id")] 30 | public string Id { get; set; } 31 | 32 | /// 33 | /// 公交类型 34 | /// 35 | [JsonProperty("type")] 36 | public string Type { get; set; } 37 | 38 | /// 39 | /// 公交行驶距离 40 | /// 41 | [JsonProperty("distance")] 42 | public string Distance { get; set; } 43 | 44 | /// 45 | /// 此路段坐标集 46 | /// 47 | [JsonProperty("polyline")] 48 | public string PolyLine { get; set; } 49 | 50 | /// 51 | /// 首班车时间 52 | /// 53 | [JsonProperty("start_time")] 54 | public string StartTime { get; set; } 55 | 56 | /// 57 | /// 末班车时间 58 | /// 59 | [JsonProperty("end_time")] 60 | public string EndTime { get; set; } 61 | 62 | /// 63 | /// 此段途经公交站数 64 | /// 65 | [JsonProperty("via_num")] 66 | public string ViaNum { get; set; } 67 | 68 | /// 69 | /// 此段途经公交站点列表 70 | /// 71 | [JsonProperty("via_stops")] 72 | public ICollection ViaStops { get; set; } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /miniprogram/pages/my/my.js: -------------------------------------------------------------------------------- 1 | const jobService = require("../../jobService") 2 | Page({ 3 | data: { 4 | isLogin: false, 5 | userInfo: {} 6 | }, 7 | 8 | onGotUserInfo(e) { 9 | if (e.detail.errMsg == "getUserInfo:ok") { 10 | this.onUserLogin(e.detail.userInfo); 11 | } 12 | }, 13 | 14 | userLoginFunc (userInfo, sb) { 15 | wx.cloud.callFunction({ 16 | name: "user-login", 17 | data: { 18 | userInfo: userInfo 19 | }, 20 | success: res => { 21 | if (res.errMsg == "cloud.callFunction:ok") { 22 | sb && sb(res.result) 23 | } else { 24 | log.error(`API[user-login]调用失败,`, res) 25 | } 26 | }, 27 | fail: err => { 28 | log.error(`API[${consts.functions.userLogin}]调用失败,`, err) 29 | } 30 | }) 31 | }, 32 | 33 | onUserLogin(userInfo) { 34 | var that = this; 35 | that.userLoginFunc(userInfo, (loginResult) => { 36 | getApp().globalData.userInfo = loginResult; 37 | that.setData({ 38 | userInfo: loginResult, 39 | isLogin: true 40 | }) 41 | }); 42 | }, 43 | 44 | onShow: function (options) { 45 | var that = this; 46 | wx.getSetting({ 47 | success(res) { 48 | if (res.authSetting['scope.userInfo']) { 49 | wx.getUserInfo({ 50 | success: function (res) { 51 | that.onUserLogin(res.userInfo); 52 | }, 53 | fail: function () { 54 | that.setData({ 55 | userInfo: {}, 56 | isLogin: false 57 | }) 58 | } 59 | }) 60 | } 61 | } 62 | }) 63 | }, 64 | 65 | onLoad: function (options) { 66 | jobService.statPreviewMy() 67 | } 68 | }) -------------------------------------------------------------------------------- /scf/Yhd.FindJob/JobsManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Concurrent; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Linq; 7 | 8 | namespace Yhd.FindJob 9 | { 10 | public class JobsManager : IJobsManager 11 | { 12 | private IFindJobFactory findjobFactory; 13 | 14 | public JobsManager(IFindJobFactory factory) 15 | { 16 | findjobFactory = factory; 17 | } 18 | 19 | public async Task> GetJobsAsync(List sources, string city, string searchKey, int pageIndex) 20 | { 21 | var jobInfos = new List(); 22 | 23 | foreach (var x in sources) 24 | { 25 | List jobList = await GetJobsAsync(x, city, searchKey, pageIndex); 26 | jobInfos.AddRange(jobList); 27 | } 28 | return jobInfos; 29 | 30 | //return await Task.Run(() => 31 | //{ 32 | // var jobInfos = new List(); 33 | // Parallel.ForEach(sources, (async x => 34 | // { 35 | // List jobList = await GetJobsAsync(x, city, searchKey, pageIndex); 36 | // jobInfos.AddRange(jobList); 37 | // //jobList.ForEach(y => jobInfos.Add(y)); 38 | // })); 39 | // return jobInfos; 40 | //}); 41 | } 42 | 43 | public async Task> GetJobsAsync(string source,string city, string searchKey, int pageIndex) 44 | { 45 | IFindJob findJob = findjobFactory.Get(source); 46 | findJob.City = city; 47 | findJob.SearchKey = searchKey; 48 | findJob.PageIndex = pageIndex; 49 | var jobList = await findJob.GetJobsAsync(); 50 | return jobList; 51 | } 52 | 53 | public async Task GetDetailsInfo(string source, string url) 54 | { 55 | IFindJob findJob = findjobFactory.Get(source); 56 | return await findJob.GetDetailsInfo(url); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /scf/XUnitTestFindJob/AmapWebApiTest.cs: -------------------------------------------------------------------------------- 1 | using LBS.Amap.SDK; 2 | using LBS.Amap.SDK.Models; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using Xunit; 10 | 11 | namespace XUnitTestFindJob 12 | { 13 | public class AmapWebApiTest 14 | { 15 | private readonly IServiceCollection _services; 16 | private IServiceProvider _serviceProvider; 17 | private readonly IConfiguration _configRoot; 18 | 19 | IConfigurationBuilder builder; 20 | 21 | 22 | 23 | 24 | 25 | public AmapWebApiTest() 26 | { 27 | builder = new ConfigurationBuilder(); 28 | 29 | const string KEY = "71822e73b7871a41f4cb386413d3db0c"; 30 | builder.AddInMemoryCollection(new Dictionary 31 | { 32 | { "Amap:Key", KEY } 33 | }); 34 | _configRoot = builder.Build(); 35 | 36 | 37 | _services = new ServiceCollection(); 38 | _services.AddAmapOptions(_configRoot); 39 | _services.AddLBSAmap(); 40 | _services.AddSingleton(_configRoot); 41 | _serviceProvider = _services.BuildServiceProvider(); 42 | System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance); 43 | } 44 | 45 | [Fact] 46 | public async Task TestGetReGeoCode() 47 | { 48 | ReGeoParameter reGeoParameter = new ReGeoParameter() 49 | { 50 | Location = "116.481488,39.990464", 51 | Batch = false, 52 | Output = "JSON", 53 | Radius = 1000, 54 | RoadLevel = 0, 55 | Extensions = "base", 56 | Poitype = string.Empty 57 | }; 58 | 59 | IAmapWebApi jobsManager = _serviceProvider.GetService(); 60 | var jobs = await jobsManager.GetRegeoAsync(reGeoParameter); 61 | Assert.True(jobs.ReGeoCode.AddressComponent.Country == "中国"); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /scf/LBS.Amap.SDK/Models/Direction/IntegratedParameter.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace LBS.Amap.SDK.Models.Direction 4 | { 5 | /// 6 | /// 公交路径规划参数 7 | /// 8 | public class IntegratedParameter : BaseParameter 9 | { 10 | /// 11 | /// 出发点 12 | /// 13 | [Display(Name = "origin")] 14 | public string Origin { get; set; } 15 | 16 | /// 17 | /// 目的地 18 | /// 19 | [Display(Name = "destination")] 20 | public string Destination { get; set; } 21 | 22 | /// 23 | /// 城市/跨城规划时的起点城市 24 | ///
可选值:城市名称/citycode
25 | ///
26 | [Display(Name = "city")] 27 | public string City { get; set; } 28 | 29 | /// 30 | /// 跨城公交规划时的终点城市 31 | /// 32 | [Display(Name = "cityd")] 33 | public string Cityd { get; set; } 34 | 35 | /// 36 | /// 返回结果详略 37 | /// 38 | [Display(Name = "extensions")] 39 | public string Extensions { get; set; } 40 | 41 | /// 42 | /// 公交换乘策略 43 | /// 44 | [Display(Name = "strategy")] 45 | public string Strategy { get; set; } 46 | 47 | /// 48 | /// 是否计算夜班车 49 | /// 50 | [Display(Name = "nightflag")] 51 | public string NightFlag { get; set; } 52 | 53 | /// 54 | /// 出发日期 55 | /// 56 | [Display(Name = "date")] 57 | public string Date { get; set; } 58 | 59 | /// 60 | /// 出发时间 61 | /// 62 | [Display(Name = "time")] 63 | public string Time { get; set; } 64 | 65 | /// 66 | /// 数字签名 67 | /// 68 | [Display(Name = "sig")] 69 | public string Sig { get; set; } 70 | 71 | /// 72 | /// 回调函数 73 | /// 74 | [Display(Name = "callback")] 75 | public string Callback { get; set; } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /scf/Yhd.TencentCloud.SCF/ObjectDictionaryConverter.cs: -------------------------------------------------------------------------------- 1 | 2 | // Copyright (c) Yhd Tech. All rights reserved. 3 | // Licensed under the MIT License. See License.txt in the project root for license information.using Microsoft.Extensions.Configuration; 4 | 5 | using System; 6 | using System.Collections; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | 10 | namespace Yhd.TencentCloud.SCF 11 | { 12 | internal static class ObjectDictionaryConverter 13 | { 14 | public static IDictionary AsDictionary(object values) 15 | { 16 | if (values == null) 17 | { 18 | return null; 19 | } 20 | 21 | IDictionary valuesAsDictionary = values as IDictionary; 22 | 23 | if (valuesAsDictionary != null) 24 | { 25 | return valuesAsDictionary; 26 | } 27 | 28 | IDictionary valuesAsNonGenericDictionary = values as IDictionary; 29 | 30 | if (valuesAsNonGenericDictionary != null) 31 | { 32 | throw new InvalidOperationException("Argument dictionaries must implement IDictionary."); 33 | } 34 | 35 | IDictionary dictionary = new Dictionary(); 36 | 37 | foreach (PropertyHelper property in PropertyHelper.GetProperties(values)) 38 | { 39 | // Extract the property values from the property helper 40 | // The advantage here is that the property helper caches fast accessors. 41 | dictionary.Add(property.Name, property.GetValue(values)); 42 | } 43 | 44 | return dictionary; 45 | } 46 | 47 | public static string DictToString(IEnumerable> items, string format = "") 48 | { 49 | format = String.IsNullOrEmpty(format) ? "{0}='{1}' " : format; 50 | 51 | StringBuilder itemString = new StringBuilder(); 52 | foreach (var item in items) 53 | itemString.AppendFormat(format, item.Key, item.Value); 54 | 55 | return itemString.ToString(); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /scf/Yhd.FindJob/FindJobBase.cs: -------------------------------------------------------------------------------- 1 | using EasyCaching.Core; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Threading.Tasks; 5 | 6 | namespace Yhd.FindJob 7 | { 8 | public abstract class FindJobBase : IFindJob 9 | { 10 | public string RequestPath { get; set; } 11 | 12 | public RecruitEnum Recruit { get; } 13 | 14 | public string City { get; set; } 15 | 16 | public string SearchKey { get; set; } 17 | 18 | public int PageIndex { get; set; } 19 | 20 | private readonly IEasyCachingProvider _provider; 21 | 22 | 23 | public FindJobBase(RecruitEnum recruit, IEasyCachingProvider provider) 24 | { 25 | Recruit = recruit; 26 | _provider = provider ; 27 | } 28 | 29 | protected string CacheKey 30 | { 31 | get 32 | { 33 | var key = $"{RequestPath}?city={City}&key={SearchKey}&index={PageIndex}"; 34 | return key; 35 | } 36 | } 37 | 38 | public async Task> GetJobsAsync(int? minutes = null) 39 | { 40 | var cache = GetCacheObject(); 41 | 42 | if (cache != null && cache.Count > 0) 43 | return cache; 44 | 45 | var cityCode = CodesData.GetCityCode(Recruit, this.City ); 46 | 47 | var data = await GetJobsFromWeb(cityCode); 48 | 49 | var time = minutes ?? 10 ;//缓存10分钟 50 | 51 | await _provider.SetAsync(CacheKey, data, TimeSpan.FromMinutes(time)); 52 | return data; 53 | } 54 | 55 | 56 | public abstract Task> GetJobsFromWeb(string cityCode); 57 | 58 | 59 | /// 60 | /// 获取缓存对象 61 | /// 62 | /// 63 | /// 64 | /// 65 | /// 66 | public List GetCacheObject(int? minutes = null) 67 | { 68 | var cacheValue = _provider.Get>(CacheKey); 69 | return cacheValue.Value; 70 | } 71 | 72 | /// 73 | /// 获取岗位详细信息 74 | /// 75 | /// 岗位详细信息的URL 76 | /// 77 | public abstract Task GetDetailsInfo(string url); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /contributing.md: -------------------------------------------------------------------------------- 1 | # 项目贡献指南 2 | 欢迎参与 findjobtcloud 的贡献,你可以给我们提出意见、建议,报告 bug,或者贡献代码。在参与贡献之前,请阅读以下指引。 3 | 4 | ## 关于命名规范 5 | 6 | ## 咨询问题 7 | 8 | 简单的咨询,如询问如何使用、询问示例是如何实现的或其他和 Findjob 无关的技术问题,请在官方 QQ 群中询问,效率更高。 9 | 10 | ## 关于 issue 11 | Findjob 的发展,离不开社区的贡献。如果你对 FindJob 的现状有意见、建议或者发现了 bug,欢迎通过 issue 给我们提出。提 issue 之前,请阅读以下指引。 12 | 13 | - 搜索以往的 issue ,看是否已经提过,避免重复提出; 14 | - 请确认你遇到的问题,是否在最新版本已被修复; 15 | - 提出意见或建议时,请描述: 16 | - 现状 17 | - 给你带来了什么问题 18 | - 你的期望结果 19 | - 可能的实现方式(可选) 20 | - 如果是报告 bug,请提供可以复现的条件: 21 | - 平台 22 | - 系统版本 23 | - 微信客户端版本 24 | - bug 表现 25 | - 是否必现 26 | - 最好可以提供截图 27 | - 最好可以提供示例代码,推荐使用 http://codepen.io 28 | - 如果你的问题已经得到解决,请关闭你的 issue。 29 | 30 | ### Fork项目 31 | 32 | 由于此时大家并没有对当前开源项目仓库进行修改的权限,因此需要通过 fork ,将此仓库复制一份到自己的名字下,从而得到一个自己有权限提交代码的仓库。 33 | 34 | [![img](https://testerhome.com/uploads/photo/2019/f9797f26-e893-4768-8d5b-fb27b7fce0b4.png!large)](https://testerhome.com/uploads/photo/2019/f9797f26-e893-4768-8d5b-fb27b7fce0b4.png!large) 35 | 36 | Fork 完毕后,会在自己的名下得到一个和原来开源项目仓库一模一样的仓库: 37 | 38 | [![img](https://testerhome.com/uploads/photo/2019/1a586a0e-9dc9-4b6d-a140-45aa12899435.png!large) 39 | 40 | ### 开发+自测+提交代码 41 | 42 | 当完成了 Fork 操作后,可以 clone 下自己的仓库代码,并在本地基于 master 建立新的分支,进行开发、自测,并在自测通过后提交代码到自己的远程仓库。 43 | 44 | ### 提交 pull request 45 | 46 | 通过前一步骤,对应的修改代码已经放到了你自己 fork 出来的仓库里了,此时需要通过提交 pull request (后续简称 PR)来提交一个申请,把你的这部分修改代码合并到原来开源项目的仓库中。 47 | 48 | 当你的代码 push 到自己的远程仓库后,在 github 仓库首页,会见到一个自动提示,可以直接点击 【Compare & pull request】进入 PR 创建页面。 49 | 50 | [![img](https://testerhome.com/uploads/photo/2019/7a2da1e7-5ca3-4a96-a62b-e930f47ccd2a.png!large)](https://testerhome.com/uploads/photo/2019/7a2da1e7-5ca3-4a96-a62b-e930f47ccd2a.png!large) 51 | 52 | 在 PR 创建页面,完成以下5项检查,最后点击 【Create Pull Request】提交你的修改。 53 | 54 | [![img](https://testerhome.com/uploads/photo/2019/a9823009-9c12-4ff5-b747-582b641acc3d.png!large)](https://testerhome.com/uploads/photo/2019/a9823009-9c12-4ff5-b747-582b641acc3d.png!large) 55 | 56 | 提交完成后,将进入 PR 展示页面,你的 PR 将会出现在开源项目的 PR 列表中,并通知项目作者。 57 | 58 | ### 后续修改 59 | 60 | PR 提交后,作者会进行 Review ,个别项目还会自动触发一些自动化检查和测试。若这些检查没有通过,会在 PR 页面上有对应提示,此时需要再次修改代码。 61 | 62 | 修改时,不需要重新提交 PR ,只需要直接在 PR 中自己仓库的分支进行修改,push,并在修改完毕后在 PR 中添加评论说明修改已提交即可。 63 | 64 | 另外,请特别注意,任何 PR 不应该存在和原有官方仓库的代码冲突。若存在,请自行修复。 65 | 66 | ## 贡献者名单 67 | 68 | 非常感谢以下几位贡献者对findjob做出的贡献: 69 | 70 | [geffzhang](https://github.com/geffzhang) 71 | 72 | [mrhuo](https://github.com/mrhuo) 73 | 74 | ## 参与贡献 75 | 76 | 如果你有好的意见或建议,欢迎给我们提 Issues 或 Pull Requests,为提升dotnet 生态贡献力量。 77 | 详见:[CONTRIBUTING.md](CONTRIBUTING.md) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 项目名称:快速找工作findjob 2 | 3 | ## 1. 项目介绍 4 | 5 | 首先感谢官方提供了这次比赛。刚好最近看到腾讯云云函数SCF 推出Custom Runtime定制化运行功能,正在使用C#封装Custom Runtime的云函数,需要找一个场景来进行验证工作,当前微信小程序使用js 作为开发语言, 云开发的云函数也支持多种语言,但是他们都不支持C#,腾讯云 SCF Custom Runtime的云函数可以让更多的后端程序员投身全栈开发。 6 | 7 | 本次参加这次大赛的初衷是以大赛的要求来充分验证使用C#打造全场景的云原生应用开发,参加比赛的场景是使用小程序快速查找各大招聘网站的岗位,用户在小程序种输入岗位关键词和城市【支持全部城市岗位(不选城市)】,将查询条件提交给后端云函数向各大招聘网站提交查询请求,合并查询结果返回给小程序,同时将相同查询条件的请求使用Redis缓存到服务端。用户在小程序端可以保存他感兴趣的岗位,也可以在微信小程序种发起申请岗位(调用招聘网站的小程序,这一部分理论上技术可行,更多的是商务,因此目前未实现)。用户在小程序端的相关操作进行一个访问统计,用户登录和保存感兴趣岗位数据,以及用户的访问统计数据使用云开发的云函数 封装api和数据库保存数据, 同时将云开发的数据通过Custom Runtime的云函数进行封装成API 提供给 运营站点进行展示, 运营站点使用基于WebAssembly技术的前端框架blazor 进行开发,通过云开发部署到静态网站托管。 8 | 9 | 这个项目充分调用了小程序的能力,并且结合云开发的优势,同时扩展云开发的云函数,当前云开发的云函数不支持Custom Runtime,云开发的云函数也是基于腾讯云SCF封装。微信小程序可以在ios和android上运行,解决了移动App必须去兼容多端的接口,减少工作量,开发出来的小程序稳定,用完就走,方便用户使用。 云开发进一步的简化了微信小程序的开发,真正做到云原生应用开发,当前云开发不支持C#语言,本项目的主要目的就是展示使用C#语言在云开发的应用。 10 | 11 | ## 2. 各页面功能展示 12 | ![小程序首页](/resources/miniprog.png) 13 | 14 | 默认界面是职位搜索界面,输入关键词后,点击键盘上的搜索按钮。小程序将向远程 scf 云函数发起请求,返回职位列表。如下: 15 | 16 | ![职位列表](/resources/miniprog2.png) 17 | 18 | 可以看到相关职位都已经列出来,搜索框下面有两个下拉选择,分别是地区选择,和职位来源选择。不选择则返回所有地区和所有来源网站的职位信息。点击地区选择时: 19 | 20 | ![条件选择](/resources/miniprog3.png) 21 | 22 | 这里可以切换地区,选中地区确认后,则只筛选指定地区的职位信息。这里可以看到左侧有个“定位”按钮,定位时,将根据 wx.getLocation API 获取用户当前经纬度,然后调用 scf 云函数返回用户城市。达到定位效果。重置按钮,则重置筛选条件,将城市设置为不限制。 23 | 24 | ![来源列表](/resources/miniprog4.png) 25 | 26 | 来源列表里这里支持“猎聘网”、“智联招聘”、“前程无忧”、“Boos直聘”这4个来源。默认不限来源。 27 | 28 | ![详情页面](/resources/miniprog5.png) 29 | 30 | 进入详情界面,可以看到最下方有 “分享”、“收藏”、“申请职位” 三个功能按钮。 31 | 点击分享,可以分享职位信息给朋友。 32 | 收藏按钮,可以收藏在我的收藏列表里,在“我的收藏”界面里展示。 33 | 申请职位按钮可以通过跳转别的网站小程序来实现,但是因为需要商务方面的工作,所以暂时没有实现申请职位。将来有机会,这个功能会实现的。 34 | 此详情页面设置了可以分享到朋友圈,点击右上角的 ”...“ 就可以分享到朋友圈。 35 | 36 | ![详情页面](/resources/miniprog6.png) 37 | 38 | ## 3. 项目架构 39 | 40 | ### 功能架构 41 | 42 | 项目 功能上由小程序 和运营网站构成, 用户使用微信小程序快速找工具,相关的运营数据保存在云开发的云存储中,通过运营网站进行展示。 43 | 44 | ![功能架构](/resources/funcarch.png) 45 | 46 | ### 系统架构 47 | 48 | 本项目以云开发为核心,主要包括:云函数,云数据库,云存储,和HTTP API(SCF云函数)和 .NET SCF Custom Runtime 五个部分。除了云开发外,还有小程序端,运营系统,第三方服务器等部分。 49 | 50 | ![系统架构](/resources/softarch.png) 51 | 52 | ## 4. 体验 53 | 54 | 小程序体验二维码 55 | 56 | ![小程序体验二维码](/resources/findjobqrcode.jpg) 57 | 58 | 运营网站体验地址:[https://findjob-1gcto7ln453287ca-1257277642.tcloudbaseapp.com/](https://findjob-1gcto7ln453287ca-1257277642.tcloudbaseapp.com/) 59 | 60 | ## 5. 部署指南 61 | 62 | 部署参考文档 [deployment.d](deployment.md) 63 | 64 | ## 开源协议 65 | 66 | 项目基于 MIT 协议, 详细请参考 [LICENSE](LICENSE) 67 | 68 | ## 参考文档 69 | 70 | - [云开发文档](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/getting-started.html) 71 | 72 | - [Custom Runtime](https://cloud.tencent.com/document/product/583/47274) 73 | -------------------------------------------------------------------------------- /scf/Yhd.FindJobStat/ApiHttpClient.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Net.Http; 4 | using System.Text.Encodings.Web; 5 | using System.Threading.Tasks; 6 | using Newtonsoft.Json; 7 | 8 | namespace Yhd.FindJobStat 9 | { 10 | /// 11 | /// Api 接口请求工具类 12 | /// 13 | public class ApiHttpClient 14 | { 15 | /// 16 | /// 发起 Get 请求 17 | /// 18 | /// 19 | /// 20 | /// 21 | /// 22 | public Task HttpGet(string api, Dictionary data = null) 23 | { 24 | return InvokeTencentApi("GET", api, data); 25 | } 26 | 27 | /// 28 | /// 发起 Post 请求 29 | /// 30 | /// 31 | /// 32 | /// 33 | /// 34 | public Task HttpPost(string api, Dictionary data = null) 35 | { 36 | return InvokeTencentApi("POST", api, data); 37 | } 38 | 39 | /// 40 | /// 调用腾讯API 41 | /// 42 | /// 43 | /// 44 | /// 45 | /// 46 | /// 47 | private async Task InvokeTencentApi(string method, string api, Dictionary data = null) 48 | { 49 | using (var httpClient = new HttpClient()) 50 | { 51 | HttpResponseMessage response = null; 52 | switch (method.ToUpper()) 53 | { 54 | case "GET": 55 | if (data != null) 56 | { 57 | api = api + "?" + string.Join("&", data.Select(p => $"{p.Key}={UrlEncoder.Default.Encode(p.Value)}")); 58 | } 59 | response = await httpClient.GetAsync(api); 60 | break; 61 | case "POST": 62 | response = await httpClient.PostAsync(api, new FormUrlEncodedContent(data)); 63 | break; 64 | } 65 | response.EnsureSuccessStatusCode(); 66 | var responseText = await response.Content.ReadAsStringAsync(); 67 | return JsonConvert.DeserializeObject(responseText); 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/Shared/StatPvChart.razor: -------------------------------------------------------------------------------- 1 | @inject WxCloudApi WxCloud 2 | 3 | 4 | @if (statPvData == null) 5 | { 6 |

图表正在加载中...

7 | } 8 | 9 | @code { 10 | LineConfig chartConfig = new LineConfig 11 | { 12 | Height = 650, 13 | Title = new Title 14 | { 15 | Visible = true, 16 | Text = "FindJob 访问统计" 17 | }, 18 | Description = new Description 19 | { 20 | Visible = true, 21 | Text = "本图表统计30天内 FindJob 访问情况", 22 | }, 23 | ForceFit = true, 24 | Padding = "auto", 25 | XField = "_id", 26 | YField = "pv", 27 | Meta = new 28 | { 29 | _id = new 30 | { 31 | Alias = "日期" 32 | }, 33 | pv = new 34 | { 35 | Alias = "PV" 36 | } 37 | }, 38 | Label = new ColumnViewConfigLabel 39 | { 40 | Visible = true, 41 | Style = new TextStyle 42 | { 43 | FontSize = 12, 44 | FontWeight = 600, 45 | Opacity = 60, 46 | } 47 | }, 48 | Interactions = new Interaction[] 49 | { 50 | new Interaction 51 | { 52 | Type = "slider", 53 | Cfg = new 54 | { 55 | start = 0, 56 | end = 1, 57 | } 58 | } 59 | }, 60 | Smooth = true 61 | }; 62 | 63 | IChartComponent chartInstance = null; 64 | List statPvData = null; 65 | 66 | protected override async Task OnInitializedAsync() 67 | { 68 | var tempPv = (await WxCloud.GetStatPv()).ToDictionary(p => DateTime.Parse(p.Date), p => p.Value); 69 | var minDate = tempPv.Min(p => p.Key); 70 | var maxDate = tempPv.Max(p => p.Key); 71 | statPvData = new List(); 72 | while (minDate.Date <= maxDate.Date) 73 | { 74 | if (tempPv.ContainsKey(minDate)) 75 | { 76 | statPvData.Add(new StatPv() 77 | { 78 | Date = minDate.ToString("yyyy-MM-dd"), 79 | Value = tempPv[minDate] 80 | }); 81 | } 82 | else 83 | { 84 | statPvData.Add(new StatPv() 85 | { 86 | Date = minDate.ToString("yyyy-MM-dd"), 87 | Value = 0 88 | }); 89 | } 90 | minDate = minDate.AddDays(1); 91 | } 92 | await chartInstance.ChangeData(statPvData); 93 | } 94 | } -------------------------------------------------------------------------------- /scf/Yhd.TencentCloud.SCF/Hosting/SCFHostBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | 2 | // Copyright (c) Yhd Tech. All rights reserved. 3 | // Licensed under the MIT License. See License.txt in the project root for license information.using Microsoft.Extensions.Configuration; 4 | 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.DependencyInjection.Extensions; 8 | using Microsoft.Extensions.Logging; 9 | using System; 10 | using Yhd.TencentCloud.SCF; 11 | using Yhd.TencentCloud.SCF.Config; 12 | using Yhd.TencentCloud.SCF.Hosting; 13 | 14 | namespace Microsoft.Extensions.Hosting 15 | { 16 | public static class SCFHostBuilderExtensions 17 | { 18 | private static IConfigurationRoot _appConfiguration; 19 | 20 | public static IHostBuilder ConfigureSCF(this IHostBuilder builder) 21 | { 22 | return builder.ConfigureSCF(o => { }, o => { }); 23 | } 24 | 25 | public static IHostBuilder ConfigureSCF(this IHostBuilder builder, Action configure) 26 | { 27 | return builder.ConfigureSCF(configure, o => { }); 28 | } 29 | 30 | public static IHostBuilder ConfigureSCF(this IHostBuilder builder, Action configure, Action configureOptions) 31 | { 32 | return builder.ConfigureSCF((context, b) => configure(b), configureOptions); 33 | } 34 | 35 | public static IHostBuilder ConfigureSCF(this IHostBuilder builder, Action configure) 36 | { 37 | return builder.ConfigureSCF(configure, o => { }); 38 | } 39 | 40 | public static IHostBuilder ConfigureSCF(this IHostBuilder builder, Action configure, Action configureOptions) 41 | { 42 | builder.ConfigureAppConfiguration((context, config) => 43 | { 44 | var hostingEnvironment = context.HostingEnvironment; 45 | _appConfiguration = AppConfigurations.Get(hostingEnvironment.ContentRootPath, hostingEnvironment.EnvironmentName); 46 | }); 47 | 48 | builder.ConfigureLogging((context, b) => 49 | { 50 | b.SetMinimumLevel(LogLevel.Debug); 51 | b.AddConsole(); 52 | }); 53 | 54 | builder.ConfigureServices((context, services) => 55 | { 56 | ISCFBuilder scfBuilder = services.AddSCF(configureOptions, _appConfiguration); 57 | configure(context, scfBuilder); 58 | 59 | services.AddHttpClient(); 60 | services.TryAddEnumerable(ServiceDescriptor.Singleton()); 61 | }); 62 | 63 | return builder; 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/Shared/StatApplyChart.razor: -------------------------------------------------------------------------------- 1 | @inject WxCloudApi WxCloud 2 | 3 | 4 | @if (statApplyData == null) 5 | { 6 |

图表正在加载中...

7 | } 8 | 9 | @code { 10 | ColumnConfig chartConfig = new ColumnConfig 11 | { 12 | Height = 650, 13 | Title = new Title 14 | { 15 | Visible = true, 16 | Text = "FindJob 申请职位按钮点击统计" 17 | }, 18 | Description = new Description 19 | { 20 | Visible = true, 21 | Text = "本图表统计30天内 FindJob 申请职位按钮点击情况", 22 | }, 23 | ForceFit = true, 24 | Padding = "auto", 25 | XField = "_id", 26 | YField = "pv", 27 | Meta = new 28 | { 29 | _id = new 30 | { 31 | Alias = "日期" 32 | }, 33 | pv = new 34 | { 35 | Alias = "点击量" 36 | } 37 | }, 38 | Label = new ColumnViewConfigLabel 39 | { 40 | Visible = true, 41 | Position = "middle", 42 | Style = new TextStyle 43 | { 44 | FontSize = 12, 45 | FontWeight = 600, 46 | Opacity = 60, 47 | } 48 | }, 49 | Interactions = new Interaction[] 50 | { 51 | new Interaction 52 | { 53 | Type = "slider", 54 | Cfg = new 55 | { 56 | start = 0, 57 | end = 1, 58 | } 59 | } 60 | } 61 | }; 62 | 63 | IChartComponent chartInstance = null; 64 | List statApplyData = null; 65 | 66 | protected override async Task OnInitializedAsync() 67 | { 68 | var tempPv = (await WxCloud.GetStatApply()).ToDictionary(p => DateTime.Parse(p.Date), p => p.Value); 69 | var minDate = tempPv.Min(p => p.Key); 70 | var maxDate = tempPv.Max(p => p.Key); 71 | statApplyData = new List(); 72 | while (minDate.Date <= maxDate.Date) 73 | { 74 | if (tempPv.ContainsKey(minDate)) 75 | { 76 | statApplyData.Add(new StatApply() 77 | { 78 | Date = minDate.ToString("yyyy-MM-dd"), 79 | Value = tempPv[minDate] 80 | }); 81 | } 82 | else 83 | { 84 | statApplyData.Add(new StatApply() 85 | { 86 | Date = minDate.ToString("yyyy-MM-dd"), 87 | Value = 0 88 | }); 89 | } 90 | minDate = minDate.AddDays(1); 91 | } 92 | await chartInstance.ChangeData(statApplyData); 93 | } 94 | } -------------------------------------------------------------------------------- /scf/XUnitTestFindJobStat/WxCloudApiTest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Threading.Tasks; 6 | using Xunit; 7 | using Xunit.Abstractions; 8 | using Yhd.FindJobStat; 9 | using Yhd.TencentCloud.SCF.Config; 10 | 11 | namespace XUnitTestFindJobStat 12 | { 13 | public class WxCloudApiTest 14 | { 15 | private readonly IServiceCollection _services; 16 | private readonly IServiceProvider _serviceProvider; 17 | private readonly IConfiguration _configRoot; 18 | 19 | public WxCloudApiTest() 20 | { 21 | _configRoot = AppConfigurations.Get(Environment.CurrentDirectory); 22 | _services = new ServiceCollection(); 23 | _services.AddFindJobStat(_configRoot); 24 | _services.AddEasyCaching(options => 25 | { 26 | options.UseInMemory(); 27 | }); 28 | _services.AddSingleton(_configRoot); 29 | _serviceProvider = _services.BuildServiceProvider(); 30 | System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance); 31 | } 32 | 33 | [Fact] 34 | public async Task TestWxCloudApiGetStatPV() 35 | { 36 | var wxCloudApi = _serviceProvider.GetService(); 37 | var invokeResult = await wxCloudApi.InvokeCloudFunction("get-stat-pv"); 38 | Assert.Equal(0, invokeResult.ErrorCode); 39 | Assert.Equal("ok", invokeResult.ErrorMessage); 40 | Assert.NotNull(invokeResult.ResponseData); 41 | } 42 | 43 | [Fact] 44 | public async Task TestWxCloudApiGetStatApplyButton() 45 | { 46 | var wxCloudApi = _serviceProvider.GetService(); 47 | var invokeResult = await wxCloudApi.InvokeCloudFunction("get-stat-apply"); 48 | Assert.Equal(0, invokeResult.ErrorCode); 49 | Assert.Equal("ok", invokeResult.ErrorMessage); 50 | Assert.NotNull(invokeResult.ResponseData); 51 | } 52 | 53 | [Fact] 54 | public async Task TestWxCloudApiGetStatTopSearch() 55 | { 56 | var wxCloudApi = _serviceProvider.GetService(); 57 | var invokeResult = await wxCloudApi.InvokeCloudFunction("get-stat-top-search"); 58 | Assert.Equal(0, invokeResult.ErrorCode); 59 | Assert.Equal("ok", invokeResult.ErrorMessage); 60 | Assert.NotNull(invokeResult.ResponseData); 61 | } 62 | 63 | [Fact] 64 | public async Task TestWxCloudApiGetStatTopCity() 65 | { 66 | var wxCloudApi = _serviceProvider.GetService(); 67 | var invokeResult = await wxCloudApi.InvokeCloudFunction("get-stat-top-city"); 68 | Assert.Equal(0, invokeResult.ErrorCode); 69 | Assert.Equal("ok", invokeResult.ErrorMessage); 70 | Assert.NotNull(invokeResult.ResponseData); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /scf/Yhd.FindJobStat/AccessTokenManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using EasyCaching.Core; 4 | using Microsoft.Extensions.Options; 5 | 6 | namespace Yhd.FindJobStat 7 | { 8 | /// 9 | /// AccessToken 管理器接口 10 | /// 11 | public interface IAccessTokenManager 12 | { 13 | /// 14 | /// 获取 AccessToken 15 | /// 16 | /// 17 | Task GetAccessToken(); 18 | /// 19 | /// 刷新 AccessToken 20 | /// 21 | /// 22 | Task RefreshAccessToken(); 23 | } 24 | 25 | /// 26 | /// AccessToken 管理器实现 27 | /// 28 | public class AccessTokenManager : IAccessTokenManager 29 | { 30 | private IEasyCachingProvider _provider; 31 | private WxCloudOption _wxCloudOption; 32 | private ApiHttpClient _apiHttpClient; 33 | 34 | private static readonly string CacheKey = "AccessToken"; 35 | /// 36 | /// 过期时间,官方规定 AccessToken 在 7200 秒后过期,这里采用 7000 秒。 37 | /// 38 | private static readonly TimeSpan ExpireIn = TimeSpan.FromSeconds(7000); 39 | 40 | public AccessTokenManager(IEasyCachingProvider provider, IOptions options, ApiHttpClient apiHttpClient) 41 | { 42 | _provider = provider; 43 | _wxCloudOption = options.Value; 44 | _apiHttpClient = apiHttpClient; 45 | } 46 | 47 | /// 48 | /// 获取 AccessToken 49 | /// 50 | /// 51 | public async Task GetAccessToken() 52 | { 53 | var cacheToken = (await _provider.GetAsync(CacheKey)).Value; 54 | if (!string.IsNullOrEmpty(cacheToken)) 55 | { 56 | return cacheToken; 57 | } 58 | var accessTokenResponse = await GetAccessTokenFromApi(); 59 | if (accessTokenResponse.HasError()) 60 | { 61 | throw new Exception(accessTokenResponse.ErrorMessage); 62 | } 63 | var accessToken = accessTokenResponse.AccessToken; 64 | await _provider.SetAsync(CacheKey, accessToken, ExpireIn); 65 | return accessToken; 66 | } 67 | 68 | /// 69 | /// 刷新 AccessToken。清除缓存,重新获取 70 | /// 71 | /// 72 | public async Task RefreshAccessToken() 73 | { 74 | await _provider.RemoveAsync(CacheKey); 75 | return await GetAccessToken(); 76 | } 77 | 78 | /// 79 | /// 调用微信API,获取 AccessToken 80 | /// 81 | /// 82 | private async Task GetAccessTokenFromApi() 83 | { 84 | var api = $"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={_wxCloudOption.AppID}&secret={_wxCloudOption.AppSecret}"; 85 | return await _apiHttpClient.HttpGet(api); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /scf/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "serverless-cloud-function-application": { 3 | "application":{ 4 | "Chinese":{ 5 | "name": "dotnet函数示例", 6 | "description": "本示例展示如何在CustomRuntime类型函数中使用dotnet。", 7 | "attention": "无", 8 | "readme": { 9 | "file": "", 10 | "content": "" 11 | }, 12 | "license": { 13 | "file": "", 14 | "content": "公开" 15 | }, 16 | "author": { 17 | "name": "腾讯云无服务器云函数团队" 18 | } 19 | }, 20 | "English":{ 21 | "name": "dotnet_demo", 22 | "description": "This example shows how to use dotnet in CustomRuntime type function", 23 | "attention": "No", 24 | "readme": { 25 | "file": "", // readme file 26 | "content": "" //content of readme 27 | }, 28 | "license": { 29 | "file": "", // license file 30 | "content": "Open" //content of license 31 | }, 32 | "author": { 33 | "name": "Tencent Cloud Serverless Team" // author 34 | } 35 | }, 36 | "input_parameters":{ 37 | "event":"", 38 | "context":"" 39 | }, 40 | "output_parameters":{ 41 | }, 42 | "download_address":"https://github.com/tencentyun/scf-demo-repo/tree/master/CustomRuntime-dotnetDemo", //Demo's git download url. demo的git下载链接 43 | "tags":[ 44 | "CustomRuntime", "dotnet" 45 | // The tags only support English and can be multiple, we suggest you to use keywords such as runtime, trigger, environment and so on. 46 | // 标签统一为英文,可编写多个,建议使用runtime、触发器、场景等关键字,用户可以通过该关键字搜索。前台需要展示,请认真填写,不支持中文 47 | ], 48 | "version": "1.0.0" 49 | // Version number, which identifies the demo version status. 50 | // Demo will not to update to the page if the version number unmodified. 51 | //版本号,通过版本号标识 demo 升级情况,未修改版本号会导致 demo 不更新至页面 52 | }, 53 | "functions": { 54 | "name": "dotnetDemo", // Function name which only be in English. 函数名称,只支持英文 55 | "description": "dotnet demo function. dotnet模版函数", 56 | "handler":"index.main_handler", 57 | "memorySize": 128, // Running memory. 运行配置内存 58 | "timeout": 3, // Running timeout. 运行超时时间 59 | "runtime": "CustomRuntime", // Runtime which users can search demo by this keyword. 运行环境,用户可以通过该关键字搜索["Python2.7", "Python3.6", "Nodejs6.10", "Java8", "LuaCDN", "NodejsCDN", "Php5", "Php7", "Nodejs8.9", "Go1", "CustomRuntime"] 60 | "Environment":{ 61 | }, // Optional, used to define environment variables. 可选,用于定义环境变量 62 | "Events":{ 63 | }, // Optional, used define the event source that triggers this function. 可选,用于定义触发此函数的事件源 64 | "VpcConfig":{ 65 | }, // Optional, used configure cloud function's private network. 可选, 用于配置云函数访问 VPC 私有网络。 66 | "codeObject": { 67 | "codeFile": [ 68 | "build", 69 | "bootstrap" 70 | ], 71 | "CodeUri":[ // Code download url which should be same as 'download_address'. 代码下载地址,和download_address保持一致 72 | "https://github.com/tencentyun/scf-demo-repo/tree/master/CustomRuntime-dotnetDemo" 73 | ] 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /miniprogram/colorui/animation.wxss: -------------------------------------------------------------------------------- 1 | /* 2 | Animation 微动画 3 | 基于ColorUI组建库的动画模块 by 文晓港 2019年3月26日19:52:28 4 | */ 5 | 6 | /* css 滤镜 控制黑白底色gif的 */ 7 | .gif-black{ 8 | mix-blend-mode: screen; 9 | } 10 | .gif-white{ 11 | mix-blend-mode: multiply; 12 | } 13 | 14 | 15 | /* Animation css */ 16 | [class*=animation-] { 17 | animation-duration: .5s; 18 | animation-timing-function: ease-out; 19 | animation-fill-mode: both 20 | } 21 | 22 | .animation-fade { 23 | animation-name: fade; 24 | animation-duration: .8s; 25 | animation-timing-function: linear 26 | } 27 | 28 | .animation-scale-up { 29 | animation-name: scale-up 30 | } 31 | 32 | .animation-scale-down { 33 | animation-name: scale-down 34 | } 35 | 36 | .animation-slide-top { 37 | animation-name: slide-top 38 | } 39 | 40 | .animation-slide-bottom { 41 | animation-name: slide-bottom 42 | } 43 | 44 | .animation-slide-left { 45 | animation-name: slide-left 46 | } 47 | 48 | .animation-slide-right { 49 | animation-name: slide-right 50 | } 51 | 52 | .animation-shake { 53 | animation-name: shake 54 | } 55 | 56 | .animation-reverse { 57 | animation-direction: reverse 58 | } 59 | 60 | @keyframes fade { 61 | 0% { 62 | opacity: 0 63 | } 64 | 65 | 100% { 66 | opacity: 1 67 | } 68 | } 69 | 70 | @keyframes scale-up { 71 | 0% { 72 | opacity: 0; 73 | transform: scale(.2) 74 | } 75 | 76 | 100% { 77 | opacity: 1; 78 | transform: scale(1) 79 | } 80 | } 81 | 82 | @keyframes scale-down { 83 | 0% { 84 | opacity: 0; 85 | transform: scale(1.8) 86 | } 87 | 88 | 100% { 89 | opacity: 1; 90 | transform: scale(1) 91 | } 92 | } 93 | 94 | @keyframes slide-top { 95 | 0% { 96 | opacity: 0; 97 | transform: translateY(-100%) 98 | } 99 | 100 | 100% { 101 | opacity: 1; 102 | transform: translateY(0) 103 | } 104 | } 105 | 106 | @keyframes slide-bottom { 107 | 0% { 108 | opacity: 0; 109 | transform: translateY(100%) 110 | } 111 | 112 | 100% { 113 | opacity: 1; 114 | transform: translateY(0) 115 | } 116 | } 117 | 118 | @keyframes shake { 119 | 120 | 0%, 121 | 100% { 122 | transform: translateX(0) 123 | } 124 | 125 | 10% { 126 | transform: translateX(-9px) 127 | } 128 | 129 | 20% { 130 | transform: translateX(8px) 131 | } 132 | 133 | 30% { 134 | transform: translateX(-7px) 135 | } 136 | 137 | 40% { 138 | transform: translateX(6px) 139 | } 140 | 141 | 50% { 142 | transform: translateX(-5px) 143 | } 144 | 145 | 60% { 146 | transform: translateX(4px) 147 | } 148 | 149 | 70% { 150 | transform: translateX(-3px) 151 | } 152 | 153 | 80% { 154 | transform: translateX(2px) 155 | } 156 | 157 | 90% { 158 | transform: translateX(-1px) 159 | } 160 | } 161 | 162 | @keyframes slide-left { 163 | 0% { 164 | opacity: 0; 165 | transform: translateX(-100%) 166 | } 167 | 168 | 100% { 169 | opacity: 1; 170 | transform: translateX(0) 171 | } 172 | } 173 | 174 | @keyframes slide-right { 175 | 0% { 176 | opacity: 0; 177 | transform: translateX(100%) 178 | } 179 | 180 | 100% { 181 | opacity: 1; 182 | transform: translateX(0) 183 | } 184 | } -------------------------------------------------------------------------------- /blazorsite/FindJobBlazorSite/FindJobBlazorSite/wwwroot/css/open-iconic/README.md: -------------------------------------------------------------------------------- 1 | [Open Iconic v1.1.1](http://useiconic.com/open) 2 | =========== 3 | 4 | ### Open Iconic is the open source sibling of [Iconic](http://useiconic.com). It is a hyper-legible collection of 223 icons with a tiny footprint—ready to use with Bootstrap and Foundation. [View the collection](http://useiconic.com/open#icons) 5 | 6 | 7 | 8 | ## What's in Open Iconic? 9 | 10 | * 223 icons designed to be legible down to 8 pixels 11 | * Super-light SVG files - 61.8 for the entire set 12 | * SVG sprite—the modern replacement for icon fonts 13 | * Webfont (EOT, OTF, SVG, TTF, WOFF), PNG and WebP formats 14 | * Webfont stylesheets (including versions for Bootstrap and Foundation) in CSS, LESS, SCSS and Stylus formats 15 | * PNG and WebP raster images in 8px, 16px, 24px, 32px, 48px and 64px. 16 | 17 | 18 | ## Getting Started 19 | 20 | #### For code samples and everything else you need to get started with Open Iconic, check out our [Icons](http://useiconic.com/open#icons) and [Reference](http://useiconic.com/open#reference) sections. 21 | 22 | ### General Usage 23 | 24 | #### Using Open Iconic's SVGs 25 | 26 | We like SVGs and we think they're the way to display icons on the web. Since Open Iconic are just basic SVGs, we suggest you display them like you would any other image (don't forget the `alt` attribute). 27 | 28 | ``` 29 | icon name 30 | ``` 31 | 32 | #### Using Open Iconic's SVG Sprite 33 | 34 | Open Iconic also comes in a SVG sprite which allows you to display all the icons in the set with a single request. It's like an icon font, without being a hack. 35 | 36 | Adding an icon from an SVG sprite is a little different than what you're used to, but it's still a piece of cake. *Tip: To make your icons easily style able, we suggest adding a general class to the* `` *tag and a unique class name for each different icon in the* `` *tag.* 37 | 38 | ``` 39 | 40 | 41 | 42 | ``` 43 | 44 | Sizing icons only needs basic CSS. All the icons are in a square format, so just set the `` tag with equal width and height dimensions. 45 | 46 | ``` 47 | .icon { 48 | width: 16px; 49 | height: 16px; 50 | } 51 | ``` 52 | 53 | Coloring icons is even easier. All you need to do is set the `fill` rule on the `` tag. 54 | 55 | ``` 56 | .icon-account-login { 57 | fill: #f00; 58 | } 59 | ``` 60 | 61 | To learn more about SVG Sprites, read [Chris Coyier's guide](http://css-tricks.com/svg-sprites-use-better-icon-fonts/). 62 | 63 | #### Using Open Iconic's Icon Font... 64 | 65 | 66 | ##### …with Bootstrap 67 | 68 | You can find our Bootstrap stylesheets in `font/css/open-iconic-bootstrap.{css, less, scss, styl}` 69 | 70 | 71 | ``` 72 | 73 | ``` 74 | 75 | 76 | ``` 77 | 78 | ``` 79 | 80 | ##### …with Foundation 81 | 82 | You can find our Foundation stylesheets in `font/css/open-iconic-foundation.{css, less, scss, styl}` 83 | 84 | ``` 85 | 86 | ``` 87 | 88 | 89 | ``` 90 | 91 | ``` 92 | 93 | ##### …on its own 94 | 95 | You can find our default stylesheets in `font/css/open-iconic.{css, less, scss, styl}` 96 | 97 | ``` 98 | 99 | ``` 100 | 101 | ``` 102 | 103 | ``` 104 | 105 | 106 | ## License 107 | 108 | ### Icons 109 | 110 | All code (including SVG markup) is under the [MIT License](http://opensource.org/licenses/MIT). 111 | 112 | ### Fonts 113 | 114 | All fonts are under the [SIL Licensed](http://scripts.sil.org/cms/scripts/page.php?item_id=OFL_web). 115 | -------------------------------------------------------------------------------- /scf/Yhd.FindJob/FindBossJob.cs: -------------------------------------------------------------------------------- 1 | using AngleSharp.Html.Parser; 2 | using EasyCaching.Core; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Net.Http; 7 | using System.Threading.Tasks; 8 | 9 | namespace Yhd.FindJob 10 | { 11 | public class FindBossJob : FindJobBase 12 | { 13 | public FindBossJob(IEasyCachingProvider provider) : 14 | base(RecruitEnum.BOSS, provider) 15 | { 16 | RequestPath = "boss.zhaopin"; 17 | } 18 | 19 | public override async Task GetDetailsInfo(string url) 20 | { 21 | using (HttpClient http = new HttpClient()) 22 | { 23 | var htmlString = await http.GetStringAsync(url); 24 | HtmlParser htmlParser = new HtmlParser(); 25 | var detailsInfo =(await htmlParser.ParseDocumentAsync(htmlString)) 26 | .QuerySelectorAll("#main") 27 | .Where(t => t.QuerySelectorAll(".job-banner .info-primary p").FirstOrDefault() != null) 28 | .Select(t => new DetailsInfo() 29 | { 30 | Experience = t.QuerySelectorAll(".job-banner .info-primary p").FirstOrDefault().TextContent.Trim(), 31 | //Education = t.QuerySelectorAll(".terminalpage-left .terminal-ul li")[5].TextContent, 32 | CompanyNature = t.QuerySelectorAll(".job-banner .info-company p").FirstOrDefault().TextContent.Trim(), 33 | //CompanySize = t.QuerySelectorAll(".terminalpage-right .terminal-company li")[0].TextContent, 34 | Requirement = t.QuerySelectorAll(".detail-content div.text").FirstOrDefault().TextContent.Replace("职位描述:", "").Trim() 35 | //CompanyIntroduction = t.QuerySelectorAll(".tab-cont-box .tab-inner-cont")[1].TextContent, 36 | }) 37 | .FirstOrDefault(); 38 | return detailsInfo; 39 | } 40 | } 41 | 42 | public override async Task> GetJobsFromWeb(string cityCode) 43 | { 44 | List jobInfos = new List(); 45 | string url = string.Format("http://www.zhipin.com/c{0}/h_{0}/?query={1}&page={2}", cityCode, SearchKey, PageIndex); 46 | using (HttpClient http = new HttpClient()) 47 | { 48 | try 49 | { 50 | var htmlString = await http.GetStringAsync(url); 51 | HtmlParser htmlParser = new HtmlParser(); 52 | jobInfos = (await htmlParser.ParseDocumentAsync(htmlString)) 53 | .QuerySelectorAll(".job-list ul li") 54 | .Where(t => t.QuerySelectorAll(".info-primary h3").FirstOrDefault() != null) 55 | .Select(t => new JobInfo() 56 | { 57 | PositionName = t.QuerySelectorAll(".info-primary h3").FirstOrDefault().TextContent.Trim(), 58 | CorporateName = t.QuerySelectorAll(".company-text h3").FirstOrDefault().TextContent.Trim(), 59 | Salary = t.QuerySelectorAll(".info-primary h3 .red").FirstOrDefault().TextContent.Trim(), 60 | WorkingPlace = t.QuerySelectorAll(".info-primary p").FirstOrDefault().TextContent.Trim(), 61 | ReleaseDate = t.QuerySelectorAll(".job-time .time").FirstOrDefault().TextContent.Trim(), 62 | DetailsUrl = "http://www.zhipin.com" + t.QuerySelectorAll("a").FirstOrDefault().Attributes.FirstOrDefault(f => f.Name == "href").Value, 63 | Source = Enum.GetName(typeof(RecruitEnum), this.Recruit) 64 | }) 65 | .ToList(); 66 | 67 | return jobInfos; 68 | } 69 | catch (Exception ex) 70 | { 71 | Console.WriteLine(ex); 72 | return jobInfos; 73 | } 74 | } 75 | } 76 | } 77 | } 78 | --------------------------------------------------------------------------------