From 82dd7be4c03a8f4009378d4337f03d7f8b0cb98c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=98=89=E7=A5=A5=20=E8=A9=B9?= Date: Thu, 16 May 2024 17:15:09 +0800 Subject: [PATCH] finished 1 --- Controllers/ApiController.cs | 749 ++++++++++++++++-- Journeys_WantHome.csproj | 1 + Models/DbTableClass.cs | 124 +++ Models/youtubeUpdateClass.cs | 2 +- Views/Home/Dashboard.cshtml | 65 +- Views/Home/KolList.cshtml | 2 +- Views/Home/ProjectList.cshtml | 6 +- wwwroot/assets/javascript/custom/dashboard.js | 521 +++++++++++- .../igKol_20240516_CSTI980X1H99GYLZ.jpg | Bin 0 -> 13297 bytes 9 files changed, 1416 insertions(+), 54 deletions(-) create mode 100644 wwwroot/images/instagram/igKol_20240516_CSTI980X1H99GYLZ.jpg diff --git a/Controllers/ApiController.cs b/Controllers/ApiController.cs index 4bb35f6..8dde8cd 100644 --- a/Controllers/ApiController.cs +++ b/Controllers/ApiController.cs @@ -17,7 +17,6 @@ using System.Net.Http; using System.Net.Http.Headers; using Dapper.Contrib.Extensions; using System.IO; - using System.IO.Compression; using System.Threading; using System.Dynamic; @@ -39,6 +38,13 @@ using System.Diagnostics.Eventing.Reader; using static Journeys_WantHome.Controllers.AuthApiController; using SixLabors.ImageSharp.Memory; using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Bcpg.OpenPgp; +using NPOI.OpenXmlFormats.Dml.Chart; +using System.Collections; +using System.Formats.Asn1; +using Org.BouncyCastle.Ocsp; +using System.Drawing; +using System.Drawing.Imaging; namespace Journeys_WantHome.Controllers @@ -48,7 +54,7 @@ namespace Journeys_WantHome.Controllers public class ApiController : ControllerBase { private readonly IHttpContextAccessor _httpContextAccessor; - + DbConn dbConn = new DbConn(); SqlConnection conn = new SqlConnection(GlobalClass.appsettings("ConnectionStrings:SQLConnectionString")); SqlConnection elabConn = new SqlConnection(GlobalClass.appsettings("ConnectionStrings:ElabConnectionString")); @@ -59,6 +65,602 @@ namespace Journeys_WantHome.Controllers this._httpContextAccessor = httpContextAccessor; } + [Route("instagramData")] + public ActionResult InstagramPostData(IFormCollection obj) { + igDataResult ret = new igDataResult(); + + authToken token = new authToken(this._httpContextAccessor); + if (token.user_isLogin == false) + { + HttpContext.Response.Cookies.Delete("token_key"); + ret.ret = "no"; + ret.err_code = "99999"; + ret.message = "非登入狀態!"; + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); + } + + string method = obj["method"].ToString(); + string instagram_uid = obj["instagram_uid"].ToString(); + + if (method == "post") + { + ret.list = conn.Query("select * from instagramDetail where instagramDetail_type='post' and instagram_uid = @instagram_uid", new { instagram_uid = instagram_uid }).ToList(); + } + else { + ret.list = conn.Query("select * from instagramDetail where instagramDetail_type='reels' and instagram_uid = @instagram_uid", new { instagram_uid = instagram_uid }).ToList(); + } + + ret.ret = "yes"; + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); + } + + [Route("instagramList")] + public ActionResult InstagramList(IFormCollection obj) { + igRankListResult ret = new igRankListResult(); + + authToken token = new authToken(this._httpContextAccessor); + if (token.user_isLogin == false) + { + HttpContext.Response.Cookies.Delete("token_key"); + ret.ret = "no"; + ret.err_code = "99999"; + ret.message = "非登入狀態!"; + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); + } + + ret.list = conn.Query("select top 15 * from instagramKolView where instagram_revoke = 'N' order by instagram_fansNum desc ").ToList(); + ret.ret = "yes"; + + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); + } + + [Route("igUpdateData")] + public ActionResult IgUpdateData(IFormCollection obj) { + normalResult ret = new normalResult(); + + string json_data = obj["json_data"].ToString(); + //json_data = json_data.Replace("\uFEFF", "").Replace("False","false"); + if (json_data == "") { + ret.ret = "no"; + ret.err_code = "0001"; + ret.message = "json_data沒有資料"; + + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); + } + + dynamic igObject; + + try { + igObject = JsonConvert.DeserializeObject(json_data); + } catch (Exception e) + { + updateLog successLog = new updateLog(); + successLog.updateLog_text = "此Instagram 資料更新失敗 " + e.Message; + successLog.updateLog_kolMedia_uid = ""; + successLog.updateLog_kolMedia_accountName = ""; + successLog.updateLog_kolMedia_displayName = ""; + successLog.updateLog_kol_uid = ""; + successLog.updateLog_type = "Instagram"; + successLog.updateLog_result = "failed"; + successLog.updateLog_uid = ""; + + conn.Insert(successLog); + + ret.ret = "no"; + ret.err_code = "0002"; + ret.message = "json parse error : " + e.Message; + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); + } + + string kolMedia_uid = igObject.kolMedia_uid; + string kol_uid = igObject.kol_uid; + + kolMedia objMedia = conn.QueryFirstOrDefault("select * from kolMedia where kolMedia_uid = @kolMedia_uid", new { kolMedia_uid = kolMedia_uid }); + + if (objMedia == null) + { + updateLog successLog = new updateLog(); + successLog.updateLog_text = "此Instagram (" + kolMedia_uid + ") 資料更新失敗,無此kolMedia_uid資料"; + successLog.updateLog_kolMedia_uid = kolMedia_uid; + successLog.updateLog_kolMedia_accountName = ""; + successLog.updateLog_kolMedia_displayName = "kol_uid = " + kol_uid; + successLog.updateLog_kol_uid = kol_uid; + successLog.updateLog_type = "Instagram"; + successLog.updateLog_result = "failed"; + successLog.updateLog_uid = ""; + + conn.Insert(successLog); + + ret.ret = "no"; + ret.err_code = "0001"; + ret.message = "無此kolMedia_uid資料! // " + json_data; + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); + } + + conn.Execute("insert into schedule (schedule_type, schedule_log) values ('Instagram', '開始執行igUpdateData,執行對象kolMedia_uid=" + kolMedia_uid + "')", new { kolMedia_uid = kolMedia_uid }); + + try + { + objMedia.kolMedia_fansNum = (int)igObject.fans_count; + string pic_url = igObject.ig_pic; + instagram igClass = new instagram(); + List igList = new List(); + + string kolIgFileName = "igKol_" + DateTime.Now.ToString("yyyyMMdd") + "_" + GlobalClass.CreateRandomCode(16) + ".jpg"; + //string newFileName = "uid_" + GlobalClass.CreateRandomCode(16) + Path.GetExtension(originFileName); + string fullPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/images/instagram/" + kolIgFileName); + + WebRequest wreq = WebRequest.Create(pic_url); + + HttpWebResponse wresp = (HttpWebResponse)wreq.GetResponse(); + Stream s = wresp.GetResponseStream(); + System.Drawing.Image img; + img = System.Drawing.Image.FromStream(s); + img.Save(fullPath, ImageFormat.Jpeg); + MemoryStream ms = new MemoryStream(); + img.Save(ms, ImageFormat.Jpeg); + img.Dispose(); + + + + igClass.instagram_uid = "ig_" + GlobalClass.CreateRandomCode(16); + igClass.instagram_name = igObject.ig_fullname; + igClass.kolMedia_uid = kolMedia_uid; + igClass.kol_uid = kol_uid; + igClass.instagram_pic = kolIgFileName; + igClass.instagram_fansNum = (int)igObject.fans_count; + igClass.instagram_followNum = (int)igObject.following_count; + + int postLikeNum = 0; + int postCommentNum = 0; + int reelViewCount = 0; + + foreach (var igObj in igObject.posts) { + + string postIgFileName = "igPost_" + kol_uid + "_" + DateTime.Now.ToString("yyyyMMdd") + "_" + GlobalClass.CreateRandomCode(16) + ".jpg"; + //string newFileName = "uid_" + GlobalClass.CreateRandomCode(16) + Path.GetExtension(originFileName); + string postfullPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/images/instagram/" + postIgFileName); + string post_img_url = igObj.url; + WebRequest iwreq = WebRequest.Create(post_img_url); + + HttpWebResponse iwresp = (HttpWebResponse)iwreq.GetResponse(); + Stream s1 = iwresp.GetResponseStream(); + System.Drawing.Image img1; + img1 = System.Drawing.Image.FromStream(s1); + img1.Save(postfullPath, ImageFormat.Jpeg); + MemoryStream ms1 = new MemoryStream(); + img1.Save(ms1, ImageFormat.Jpeg); + img1.Dispose(); + + postLikeNum += (int)igObj.likes; + postCommentNum += (int)igObj.comments; + + instagramDetail newIg = new instagramDetail(); + newIg.instagram_uid = igClass.instagram_uid; + newIg.instagramDetail_type = "post"; + newIg.instagramDetail_title = igObj.title; + newIg.instagramDetail_photo = postIgFileName; + newIg.instagramDetail_shortcode = igObj.shortcode; + newIg.instagramDetail_date = igObj.date; + newIg.instagramDetail_likeNum = (int)igObj.likes; + newIg.instagramDetail_commentNum = (int)igObj.comments; + + if ((Boolean)igObj.is_pinned) + { + newIg.instagramDetail_ispinned = "Y"; + } + else + { + newIg.instagramDetail_ispinned = "N"; + } + + igList.Add(newIg); + } + + int reelsCount = 0; + foreach (var igObj in igObject.reels) + { + string postIgFileName = "igReels_" + kol_uid + "_" + DateTime.Now.ToString("yyyyMMdd") + "_" + GlobalClass.CreateRandomCode(16) + ".jpg"; + //string newFileName = "uid_" + GlobalClass.CreateRandomCode(16) + Path.GetExtension(originFileName); + string postfullPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/images/instagram/" + postIgFileName); + string post_img_url = igObj.url; + WebRequest iwreq = WebRequest.Create(post_img_url); + + HttpWebResponse iwresp = (HttpWebResponse)iwreq.GetResponse(); + Stream s1 = iwresp.GetResponseStream(); + System.Drawing.Image img1; + img1 = System.Drawing.Image.FromStream(s1); + img1.Save(postfullPath, ImageFormat.Jpeg); + MemoryStream ms1 = new MemoryStream(); + img1.Save(ms1, ImageFormat.Jpeg); + img1.Dispose(); + + + reelViewCount += (int)igObj.video_view_count; + reelsCount++; + + instagramDetail newIg = new instagramDetail(); + newIg.instagram_uid = igClass.instagram_uid; + newIg.instagramDetail_type = "reels"; + newIg.instagramDetail_title = igObj.title; + newIg.instagramDetail_photo = postIgFileName; + newIg.instagramDetail_shortcode = igObj.shortcode; + newIg.instagramDetail_date = igObj.date; + newIg.instagramDetail_likeNum = (int)igObj.likes; + newIg.instagramDetail_commentNum = (int)igObj.comments; + newIg.instagramDetail_viewNum = (int)igObj.video_view_count; + + if ((Boolean)igObj.is_pinned) + { + newIg.instagramDetail_ispinned = "Y"; + } + else + { + newIg.instagramDetail_ispinned = "N"; + } + + igList.Add(newIg); + } + + if (postLikeNum < 0) + { + igClass.instagram_postActive = -1; + } + else { + igClass.instagram_postActive = (double)(postLikeNum + postCommentNum) / (double)igClass.instagram_fansNum; + } + + if (reelsCount > 0) + { + igClass.instagram_reelsActive = (double)reelViewCount / (double)reelsCount; + } + else { + igClass.instagram_reelsActive = -1; + } + + igClass.instagram_revoke = "N"; + + conn.Execute("update instagram set instagram_revoke = 'Y' where kol_uid = @kol_uid and kolMedia_uid = @kolMedia_uid", new { kol_uid = kol_uid, kolMedia_uid = kolMedia_uid }); + + + conn.Update(objMedia); + conn.Insert(igList); + conn.Insert(igClass); + + conn.Execute("insert into schedule (schedule_type, schedule_log) values ('Instagram', '執行完成,執行對象kolMedia_uid=" + kolMedia_uid + "')"); + + updateLog successLog = new updateLog(); + successLog.updateLog_text = "此Instagram (" + igClass.instagram_name + ") 資料更新成功"; + successLog.updateLog_kolMedia_uid = kolMedia_uid; + successLog.updateLog_kolMedia_accountName = ""; + successLog.updateLog_kolMedia_displayName = igClass.instagram_name; + successLog.updateLog_kol_uid = kol_uid; + successLog.updateLog_type = "Instagram"; + successLog.updateLog_result = "success"; + successLog.updateLog_uid = ""; + + conn.Insert(successLog); + + ret.ret = "yes"; + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); + } + catch (Exception ex) { + + updateLog successLog = new updateLog(); + successLog.updateLog_text = "此Instagram (" + kolMedia_uid + ") 資料更新失敗 " + ex.Message; + successLog.updateLog_kolMedia_uid = kolMedia_uid; + successLog.updateLog_kolMedia_accountName = ""; + successLog.updateLog_kolMedia_displayName = "kol_uid = " + kol_uid; + successLog.updateLog_kol_uid = kol_uid; + successLog.updateLog_type = "Instagram"; + successLog.updateLog_result = "failed"; + successLog.updateLog_uid = ""; + + conn.Insert(successLog); + + ret.ret = "no"; + ret.err_code = "0003"; + ret.message = "資料更新錯誤 : " + ex.Message; + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); + } + + + + ret.ret = "yes"; + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); + } + + [Route("igUpdateList")] + public ActionResult IgUpdateList(IFormCollection obj) + { + fbUpdateListResult ret = new fbUpdateListResult(); + + //撈出FB頻道清單 + List kolMedias = conn.Query("select A.* from kolMedia A, kol B where A.kol_uid = B.kol_uid and A.option_uid = 'media' and A.optionItem_uid = 'media002' order by A.kolMedia_sn desc ").ToList(); + + foreach (kolMedia media in kolMedias) + { + string overDate = DateTime.Now.AddDays(int.Parse(GlobalClass.appsettings("UpdateByDay")) * -1).ToString("yyyy/MM/dd HH:mm:ss"); + + updateLog objLog = conn.QueryFirstOrDefault("select * from updateLog where updateLog_type = 'Instagram' and updateLog_result = 'success' and updateLog_kol_uid = @kol_uid and updateLog_kolMedia_uid = @kolMedia_uid and updateLog_updateTime >= @overDate ", new { kol_uid = media.kol_uid, kolMedia_uid = media.kolMedia_uid, overDate = overDate }); + + if (objLog == null) + { + fbClass objNew = new fbClass(); + objNew.kolMedia_accountName = media.kolMedia_accountName; + objNew.kolMedia_uid = media.kolMedia_uid; + objNew.kolMedia_url = media.kolMedia_url; + objNew.kol_uid = media.kol_uid; + objNew.optionItem_uid = media.optionItem_uid; + ret.list.Add(objNew); + } + + } + + conn.Execute("insert into schedule (schedule_type, schedule_log) values ('Instagram', 'Server撈取清單')"); + + + ret.ret = "yes"; + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); + } + + [Route("facebookData")] + public ActionResult FacebookData(IFormCollection obj) + { + facebookDataResult ret = new facebookDataResult(); + authToken token = new authToken(this._httpContextAccessor); + if (token.user_isLogin == false) + { + HttpContext.Response.Cookies.Delete("token_key"); + ret.ret = "no"; + ret.err_code = "99999"; + ret.message = "非登入狀態!"; + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); + } + + string facebook_uid = obj["facebook_uid"].ToString(); + + ret.list = conn.Query("select * from facebookDetail where facebook_uid = @facebook_uid", new { facebook_uid = facebook_uid }).ToList(); + ret.ret = "yes"; + + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); + } + + [Route("facebookList")] + public ActionResult FacebookList() { + fbRankListResult ret = new fbRankListResult(); + + authToken token = new authToken(this._httpContextAccessor); + if (token.user_isLogin == false) + { + HttpContext.Response.Cookies.Delete("token_key"); + ret.ret = "no"; + ret.err_code = "99999"; + ret.message = "非登入狀態!"; + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); + } + + ret.list = conn.Query("select top 15 * from facebookKolView where facebook_revoke = 'N' order by facebook_fansNum desc ").ToList(); + ret.ret = "yes"; + + ret.ret = "yes"; + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); + } + + [HttpGet] + [Route("fbUpdateData")] + public ActionResult FbUpdateData(string kol_uid, string kolMedia_uid, string fb_title, string fans_num, string json_data) { + normalResult ret = new normalResult(); + + kolMedia objMedia = conn.QueryFirstOrDefault("select * from kolMedia where kolMedia_uid = @kolMedia_uid", new { kolMedia_uid = kolMedia_uid }); + + if (objMedia == null) + { + ret.ret = "no"; + ret.err_code = "0001"; + ret.message = "無此kolMedia_uid資料!"; + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); + } + + conn.Execute("insert into schedule (schedule_type, schedule_log) values ('Facebook', '開始執行fbUpdateData,執行對象kolMedia_uid=" + kolMedia_uid + "')", new { kolMedia_uid = kolMedia_uid }); + + try + { + int intFansNum = 0; + + fans_num = fans_num.Replace(",", "").Trim(); + + if (fans_num.IndexOf("萬") >= 0) + { + fans_num = fans_num.Replace("萬", ""); + + double fans_numf = double.Parse(fans_num); + + fans_num = (fans_numf * 10000).ToString(); + } + + + + try + { + intFansNum = int.Parse(fans_num); + } + catch (Exception ex) + { + conn.Execute("insert into schedule (schedule_type, schedule_log) values ('Facebook', '執行fbUpdateData facebookArray Json化發生錯誤,執行對象kolMedia_uid=" + kolMedia_uid + ", 錯誤訊息:" + ex.Message.Replace("'", "").Replace("\"", "") + "')", new { kolMedia_uid = kolMedia_uid, msg = ex.Message }); + + + updateLog failedLog = new updateLog(); + failedLog.updateLog_text = "此Facebook (" + fb_title + ") 資料更新失敗 (" + ex.Message + ")"; + failedLog.updateLog_kolMedia_uid = kolMedia_uid; + failedLog.updateLog_kolMedia_accountName = ""; + failedLog.updateLog_kolMedia_displayName = fb_title; + failedLog.updateLog_kol_uid = kol_uid; + failedLog.updateLog_type = "Facebook"; + failedLog.updateLog_result = "failed"; + failedLog.updateLog_uid = ""; + + conn.Insert(failedLog); + + ret.ret = "no"; + ret.err_code = "0002"; + ret.message = ex.Message; + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); + } + + dynamic facebookArray; + + try + { + facebookArray = JsonConvert.DeserializeObject(json_data); + } + catch (Exception ex) + { + conn.Execute("insert into schedule (schedule_type, schedule_log) values ('Facebook', '執行fbUpdateData facebookArray Json化發生錯誤,執行對象kolMedia_uid=" + kolMedia_uid + ", 錯誤訊息:" + ex.Message.Replace("'", "").Replace("\"", "") + "')", new { kolMedia_uid = kolMedia_uid, msg = ex.Message }); + + updateLog failedLog = new updateLog(); + failedLog.updateLog_text = "此Facebook (" + fb_title + ") 資料更新失敗 (" + ex.Message + ")"; + failedLog.updateLog_kolMedia_uid = kolMedia_uid; + failedLog.updateLog_kolMedia_accountName = ""; + failedLog.updateLog_kolMedia_displayName = fb_title; + failedLog.updateLog_kol_uid = kol_uid; + failedLog.updateLog_type = "Facebook"; + failedLog.updateLog_result = "failed"; + failedLog.updateLog_uid = ""; + + conn.Insert(failedLog); + + ret.ret = "no"; + ret.err_code = "0003"; + ret.message = "json_data error : " + ex.Message; + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); + } + + objMedia.kolMedia_fansNum = intFansNum; + + int totalLikeNum = 0; + int totalMsgNum = 0; + int totalShareNum = 0; + int totalCount = 0; + List fbList = new List(); + facebook fb = new facebook(); + fb.facebook_uid = "fb_" + GlobalClass.CreateRandomCode(24); + fb.facebook_fansNum = intFansNum; + fb.facebook_name = fb_title; + fb.kol_uid = kol_uid; + fb.kolMedia_uid = kolMedia_uid; + + foreach (var fbObj in facebookArray) + { + string like_num = fbObj.like_num; + string msg_num = fbObj.like_num; + string share_num = fbObj.share_num; + like_num = like_num.Replace(",", ""); + msg_num = msg_num.Replace(",", ""); + share_num = share_num.Replace(",", ""); + + totalLikeNum += int.Parse(like_num); + totalMsgNum += int.Parse(msg_num); + totalShareNum += int.Parse(share_num); + totalCount += totalLikeNum + totalMsgNum + totalShareNum; + + facebookDetail item = new facebookDetail(); + item.facebook_uid = fb.facebook_uid; + item.facebookDetail_publishedAt = (string)fbObj.fb_date; + item.facebookDetail_likeCount = int.Parse(like_num); + item.facebookDetail_msgCount = int.Parse(msg_num); + item.facebookDetail_shareCount = int.Parse(share_num); + + fbList.Add(item); + } + + double actionNum = (double)totalCount / (double)intFansNum; + fb.facebook_active = actionNum; + fb.facebook_5_likesNum = totalLikeNum; + fb.facebook_5_msgNum = totalMsgNum; + fb.facebook_5_shareNum = totalShareNum; + fb.facebook_revoke = "N"; + + conn.Execute("update facebook set facebook_revoke = 'Y' where kol_uid = @kol_uid and kolMedia_uid = @kolMedia_uid", new { kol_uid = kol_uid, kolMedia_uid = kolMedia_uid }); + + + conn.Update(objMedia); + conn.Insert(fbList); + conn.Insert(fb); + + conn.Execute("insert into schedule (schedule_type, schedule_log) values ('Facebook', '執行完成,執行對象kolMedia_uid=@kolMedia_uid')", new { kolMedia_uid = kolMedia_uid }); + + updateLog successLog = new updateLog(); + successLog.updateLog_text = "此Facebook (" + fb_title + ") 資料更新成功"; + successLog.updateLog_kolMedia_uid = kolMedia_uid; + successLog.updateLog_kolMedia_accountName = ""; + successLog.updateLog_kolMedia_displayName = fb_title; + successLog.updateLog_kol_uid = kol_uid; + successLog.updateLog_type = "Facebook"; + successLog.updateLog_result = "success"; + successLog.updateLog_uid = ""; + + conn.Insert(successLog); + + ret.ret = "yes"; + } + catch (Exception ex) { + conn.Execute("insert into schedule (schedule_type, schedule_log) values ('Facebook', '執行fbUpdateData facebookArray Json化發生錯誤,執行對象kolMedia_uid=" + kolMedia_uid + ", 錯誤訊息:" + ex.Message.Replace("'", "").Replace("\"", "") + "')", new { kolMedia_uid = kolMedia_uid, msg = ex.Message }); + + updateLog failedLog = new updateLog(); + failedLog.updateLog_text = "此Facebook (" + fb_title + ") 資料更新失敗 (" + ex.Message + ")"; + failedLog.updateLog_kolMedia_uid = kolMedia_uid; + failedLog.updateLog_kolMedia_accountName = ""; + failedLog.updateLog_kolMedia_displayName = fb_title; + failedLog.updateLog_kol_uid = kol_uid; + failedLog.updateLog_type = "Facebook"; + failedLog.updateLog_result = "failed"; + failedLog.updateLog_uid = ""; + + conn.Insert(failedLog); + + ret.ret = "no"; + ret.err_code = "0003"; + ret.message = "json_data error : " + ex.Message; + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); + } + + + + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); + } + + [Route("fbUpdateList")] + public ActionResult FbUpdateList(IFormCollection obj) { + fbUpdateListResult ret = new fbUpdateListResult(); + + //撈出FB頻道清單 + List kolMedias = conn.Query("select A.* from kolMedia A, kol B where A.kol_uid = B.kol_uid and A.option_uid = 'media' and A.optionItem_uid = 'media001' ").ToList(); + + foreach (kolMedia media in kolMedias) { + string overDate = DateTime.Now.AddDays(int.Parse(GlobalClass.appsettings("UpdateByDay")) * -1).ToString("yyyy/MM/dd HH:mm:ss"); + + updateLog objLog = conn.QueryFirstOrDefault("select * from updateLog where updateLog_type = 'Facebook' and updateLog_result = 'success' and updateLog_kol_uid = @kol_uid and updateLog_kolMedia_uid = @kolMedia_uid and updateLog_updateTime >= @overDate ", new { kol_uid = media.kol_uid, kolMedia_uid = media.kolMedia_uid, overDate = overDate }); + + if (objLog == null) { + fbClass objNew = new fbClass(); + objNew.kolMedia_accountName = media.kolMedia_accountName; + objNew.kolMedia_uid = media.kolMedia_uid; + objNew.kolMedia_url = media.kolMedia_url; + objNew.kol_uid = media.kol_uid; + objNew.optionItem_uid = media.optionItem_uid; + ret.list.Add(objNew); + } + + } + + conn.Execute("insert into schedule (schedule_type, schedule_log) values ('Facebook', 'Server撈取清單')"); + + + ret.ret = "yes"; + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); + } + [Route("youtubeData")] public ActionResult YoutubeData(IFormCollection obj) { youtubeDataResult ret = new youtubeDataResult(); @@ -137,7 +739,7 @@ namespace Journeys_WantHome.Controllers string project_uid = obj["project_uid"].ToString(); - project objProj = conn.QueryFirstOrDefault("select * from project where project_uid = @project_uid", new { project_uid = project_uid}); + project objProj = conn.QueryFirstOrDefault("select * from project where project_uid = @project_uid", new { project_uid = project_uid }); if (objProj != null) { @@ -148,7 +750,7 @@ namespace Journeys_WantHome.Controllers ret.ret = "no"; ret.err_code = "00001"; ret.message = "無此project_uid資料!"; - + } return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); } @@ -170,7 +772,7 @@ namespace Journeys_WantHome.Controllers List kolProjectViews = conn.Query("select * from kolProjectView where project_uid = @project_uid order by kol_uid, optionItem_order", new { project_uid = project_uid }).ToList(); - foreach (kolProjectView objView in kolProjectViews) + foreach (kolProjectView objView in kolProjectViews) { ret.detail.Add(new kolProjectViewDetail(objView)); } @@ -235,7 +837,7 @@ namespace Journeys_WantHome.Controllers ret.datas.Add(objItem); } - + ret.ret = "yes"; return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); } @@ -285,7 +887,7 @@ namespace Journeys_WantHome.Controllers conn.Execute("delete kolProjectImage where kolProject_uid = @kolProject_uid", new { kolProject_uid = kolProject_uid }); conn.Execute("delete kolProjectFile where kolProject_uid = @kolProject_uid", new { kolProject_uid = kolProject_uid }); conn.Execute("delete kolProject where kolProject_uid = @kolProject_uid", new { kolProject_uid = kolProject_uid }); - + ret.ret = "yes"; return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); @@ -424,7 +1026,7 @@ namespace Journeys_WantHome.Controllers dynamic kolProjectFileJsonObj; - try { + try { kolProjectFileJsonObj = JsonConvert.DeserializeObject(kolProjectFileArrayJson); } catch (Exception ex) @@ -434,7 +1036,7 @@ namespace Journeys_WantHome.Controllers ret.message = "kolProjectFile json error" + ex.Message; return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); } - + List kolProjectFiles = new List(); foreach (dynamic item in kolProjectFileJsonObj) @@ -543,7 +1145,7 @@ namespace Journeys_WantHome.Controllers kolCooperateTypes.Add(kct); } - foreach (string evaluate in kolProjectEvaluateArr) + foreach (string evaluate in kolProjectEvaluateArr) { if (evaluate != "") { kolProjectEvaluate kpe = new kolProjectEvaluate(); @@ -553,7 +1155,7 @@ namespace Journeys_WantHome.Controllers kpe.kolProjectEvaluate_text = evaluate; kolProjectEvaluates.Add(kpe); - } + } } dynamic kolProjectFileJsonObj; @@ -601,7 +1203,7 @@ namespace Journeys_WantHome.Controllers List kolProjectPrices = new List(); - foreach (dynamic item in kolProjectPriceJsonObj) { + foreach (dynamic item in kolProjectPriceJsonObj) { kolProjectPrice kpp = new kolProjectPrice(); kpp.kolProjectPrice_uid = "kpp_" + GlobalClass.CreateRandomCode(16); kpp.kolProject_uid = kolProject_uid; @@ -633,7 +1235,7 @@ namespace Journeys_WantHome.Controllers List kolProjectLinks = new List(); - foreach (dynamic item in kolProjectLinkJsonObj) { + foreach (dynamic item in kolProjectLinkJsonObj) { kolProjectLink kpl = new kolProjectLink(); kpl.kolProjectLink_uid = "kpl_" + GlobalClass.CreateRandomCode(16); kpl.kolProject_uid = kolProject_uid; @@ -660,7 +1262,7 @@ namespace Journeys_WantHome.Controllers List kolProjectImages = new List(); - foreach (dynamic item in kolProjectImageJsonObj) { + foreach (dynamic item in kolProjectImageJsonObj) { kolProjectImage kpi = new kolProjectImage(); kpi.kolProjectImage_uid = "kpi_" + GlobalClass.CreateRandomCode(16); kpi.kolProjectImage_photo = item.kolProjectImage_photo; @@ -678,7 +1280,7 @@ namespace Journeys_WantHome.Controllers conn.Insert(kolProjectLinks); conn.Insert(kolProjectImages); conn.Insert(kolProjectFiles); - + ret.data.kolProject = kp; ret.data.kolProjectEvaluates = kolProjectEvaluates; @@ -752,7 +1354,7 @@ namespace Journeys_WantHome.Controllers objFile.file_mimeType = file.ContentType; objFile.file_createdate = DateTime.Now; - + try { @@ -974,7 +1576,7 @@ namespace Journeys_WantHome.Controllers string quotation_serial = obj["quotation_serial"].ToString(); - files fil = prmConn.QueryFirstOrDefault("select * from files where file_target_uid = @quotation_serial and file_del = 'N'", new { quotation_serial = quotation_serial}); + files fil = prmConn.QueryFirstOrDefault("select * from files where file_target_uid = @quotation_serial and file_del = 'N'", new { quotation_serial = quotation_serial }); if (fil == null) { @@ -1004,7 +1606,7 @@ namespace Journeys_WantHome.Controllers if (token.user_isLogin == false) { HttpContext.Response.Cookies.Delete("token_key"); - + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); } @@ -1029,7 +1631,7 @@ namespace Journeys_WantHome.Controllers return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); } - [Route("projectAddEditDelGet")] + [Route("projectAddEditDelGet")] public ActionResult ProjectAddEditDelGet(IFormCollection obj) { projectResult ret = new projectResult(); @@ -1138,7 +1740,7 @@ namespace Journeys_WantHome.Controllers } project newProj = new project(); - + newProj.project_uid = project_uid; newProj.project_name = project_name; newProj.project_isPrm = project_isPrm; @@ -1159,7 +1761,7 @@ namespace Journeys_WantHome.Controllers } [Route("projectList")] - public ActionResult ProjectList(IFormCollection obj) { + public ActionResult ProjectList(IFormCollection obj) { projectListResult ret = new projectListResult(); authToken token = new authToken(this._httpContextAccessor); @@ -1229,10 +1831,10 @@ namespace Journeys_WantHome.Controllers //ret.projectList = projects; } - + ret.ret = "yes"; - + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); } @@ -1448,7 +2050,7 @@ namespace Journeys_WantHome.Controllers string kol_uid = obj["kol_uid"].ToString(); if (method == "del") { - conn.Execute("delete kol where kol_uid = @kol_uid", new { kol_uid = kol_uid}); + conn.Execute("delete kol where kol_uid = @kol_uid", new { kol_uid = kol_uid }); conn.Execute("delete kolMakeup where kol_uid = @kol_uid", new { kol_uid = kol_uid }); conn.Execute("delete kolStyle where kol_uid = @kol_uid", new { kol_uid = kol_uid }); conn.Execute("delete kolFansType where kol_uid = @kol_uid", new { kol_uid = kol_uid }); @@ -1527,7 +2129,7 @@ namespace Journeys_WantHome.Controllers return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); } - kol newKol = conn.QueryFirstOrDefault("select * from kol where kol_uid = @kol_uid", new { kol_uid = kol_uid}); + kol newKol = conn.QueryFirstOrDefault("select * from kol where kol_uid = @kol_uid", new { kol_uid = kol_uid }); //newKol.kol_uid = kol_uid; newKol.kol_name = kol_name; @@ -1607,8 +2209,8 @@ namespace Journeys_WantHome.Controllers foreach (string tag in kolTagArr) { tags tagData = conn.QueryFirstOrDefault("select * from tags where tag_uid = @tag_uid", new { tag_uid = tag }); - if (tagData != null) { - kolTag newKolTag = new kolTag(); + if (tagData != null) { + kolTag newKolTag = new kolTag(); newKolTag.kolTag_uid = "kt_" + GlobalClass.CreateRandomCode(12); newKolTag.kol_uid = kol_uid; newKolTag.tag_uid = tag; @@ -1648,7 +2250,7 @@ namespace Journeys_WantHome.Controllers medias.Add(mediaObj); } - conn.Execute("delete kolMakeup where kol_uid = @kol_uid", new { kol_uid = kol_uid}); + conn.Execute("delete kolMakeup where kol_uid = @kol_uid", new { kol_uid = kol_uid }); conn.Execute("delete kolStyle where kol_uid = @kol_uid", new { kol_uid = kol_uid }); conn.Execute("delete kolFansType where kol_uid = @kol_uid", new { kol_uid = kol_uid }); conn.Execute("delete kolMedia where kol_uid = @kol_uid", new { kol_uid = kol_uid }); @@ -1681,7 +2283,7 @@ namespace Journeys_WantHome.Controllers if (method == "add") { string err_msg = ""; - + if (kol_name == "") { err_msg = "請輸入KOL頻道名稱!\n"; } @@ -1700,7 +2302,7 @@ namespace Journeys_WantHome.Controllers kol newKol = new kol(); kol_uid = "kol_" + GlobalClass.CreateRandomCode(12); - + newKol.kol_uid = kol_uid; newKol.kol_name = kol_name; newKol.kol_descript = kol_descript; @@ -1748,18 +2350,18 @@ namespace Journeys_WantHome.Controllers { kolStyle styleObj = new kolStyle(); styleObj.kolStyle_uid = "ks_" + GlobalClass.CreateRandomCode(12); - styleObj.kol_uid= kol_uid; + styleObj.kol_uid = kol_uid; styleObj.option_uid = item.option_uid; - styleObj.optionItem_uid= item.optionItem_uid; + styleObj.optionItem_uid = item.optionItem_uid; kolStyles.Add(styleObj); } - + } string[] kolFansTypeArr = kolFansTypeStr.Split(","); List kolFansTypes = new List(); - foreach(string fansType in kolFansTypeArr) + foreach (string fansType in kolFansTypeArr) { optionItem item = conn.QueryFirstOrDefault("select * from optionItem where optionItem_ishide = 'N' and optionItem_uid = @optionItem_uid", new { optionItem_uid = fansType }); @@ -1792,7 +2394,7 @@ namespace Journeys_WantHome.Controllers dynamic mediaJsonObj; - try { + try { mediaJsonObj = JsonConvert.DeserializeObject(mediaArrayJson); } catch (Exception ex) { @@ -1838,16 +2440,16 @@ namespace Journeys_WantHome.Controllers ret.message = ex.Message; return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); } - - + + ret.ret = "yes"; return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); } - + return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); } @@ -1877,11 +2479,11 @@ namespace Journeys_WantHome.Controllers string originFileName = file.FileName; - string newFileName = "avatar_" + GlobalClass.CreateRandomCode(8) + Path.GetExtension(originFileName); + string newFileName = "avatar_" + GlobalClass.CreateRandomCode(8) + Path.GetExtension(originFileName); string fullPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/images/avatar/" + newFileName); try { - using (var stream = new FileStream(fullPath, FileMode.Create)) { + using (var stream = new FileStream(fullPath, FileMode.Create)) { file.CopyTo(stream); } @@ -1895,17 +2497,17 @@ namespace Journeys_WantHome.Controllers newFile.thumbnailUrl = "/images/avatar/" + newFileName; newFile.deleteUrl = "/images/avatar/" + newFileName; - + files.Add(newFile); fileResult obj = new fileResult(); obj.files = files; - - - + + + return Content(JsonConvert.SerializeObject(obj), "application/json;charset=utf-8"); } @@ -1943,7 +2545,7 @@ namespace Journeys_WantHome.Controllers return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); } - + string option_uid = obj["option_uid"].ToString(); @@ -1960,7 +2562,55 @@ namespace Journeys_WantHome.Controllers return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8"); } - + + } + + public class igDataResult { + public string ret { get; set; } = "no"; + public string err_code { get; set; } = "0000"; + public string message { get; set; } = ""; + + public List list = new List(); + } + + public class igRankListResult { + public string ret { get; set; } = "no"; + public string err_code { get; set; } = "0000"; + public string message { get; set; } = ""; + + public List list { get; set; } = new List(); + } + + public class facebookDataResult { + public string ret { get; set; } = "no"; + public string err_code { get; set; } = "0000"; + public string message { get; set; } = ""; + public List list = new List(); + } + public class fbRankListResult { + public string ret { get; set; } = "no"; + public string err_code { get; set; } = "0000"; + public string message { get; set; } = ""; + + public List list { get; set; } = new List(); + } + + public class fbUpdateListResult { + public string ret { get; set; } = "no"; + public string err_code { get; set; } = "0000"; + public string message { get; set; } = ""; + + public List list { get; set; } = new List(); + } + + public class fbClass + { + public string kol_uid { get; set; } = ""; + public string kolMedia_uid { get; set; } = ""; + public string optionItem_uid { get; set; } = ""; + public string kolMedia_url { get; set; } = ""; + public string kolMedia_accountName { get; set; } = ""; + } public class youtubeDataResult @@ -2097,4 +2747,11 @@ namespace Journeys_WantHome.Controllers public long size { get; set; } = 0; public string error { get; set; } = ""; } + + public class normalResult { + public string ret { get; set; } = ""; + public string err_code { get; set; } = ""; + public string message { get; set; } = ""; + } } + diff --git a/Journeys_WantHome.csproj b/Journeys_WantHome.csproj index bcef7d6..0682de2 100644 --- a/Journeys_WantHome.csproj +++ b/Journeys_WantHome.csproj @@ -43,6 +43,7 @@ + diff --git a/Models/DbTableClass.cs b/Models/DbTableClass.cs index c68ff55..f5be718 100644 --- a/Models/DbTableClass.cs +++ b/Models/DbTableClass.cs @@ -8,6 +8,130 @@ using Newtonsoft.Json.Linq; public class DbTableClass { + [Table("instagramKolView")] + public class instagramKolView + { + [JsonIgnore] + [Key] + public int instagram_sn { get; set; } + public string instagram_uid { get; set; } + public string kol_uid { get; set; } + public string kolMedia_uid { get; set; } + public string instagram_name { get; set; } + public string instagram_pic { get; set; } + public string instagram_revoke { get; set; } + public int instagram_fansNum { get; set; } + public int instagram_followNum { get; set; } + public double instagram_postActive { get; set; } + public double instagram_reelsActive { get; set; } + public DateTime instagram_updatedate { get; set; } + public string kolMedia_url { get; set; } + public string kol_photo { get; set; } + + } + + + + [Table("instagramDetail")] + public class instagramDetail + { + [JsonIgnore] + [Key] + public int instagramDetail_sn { get; set; } + public string instagram_uid { get; set; } = ""; + public string instagramDetail_type { get; set; } = ""; + public string instagramDetail_title { get; set; } = ""; + public string instagramDetail_photo { get; set; } = ""; + public string instagramDetail_shortcode { get; set; } = ""; + public string instagramDetail_date { get; set; } = ""; + public int instagramDetail_viewNum { get; set; } = 0; + public int instagramDetail_likeNum { get; set; } = 0; + public int instagramDetail_commentNum { get; set; } = 0; + public string instagramDetail_ispinned { get; set; } = "N"; + public DateTime instagramDetail_createdate { get; set; } = DateTime.Now; + } + + + + [Table("instagram")] + public class instagram + { + [JsonIgnore] + [Key] + public int instagram_sn { get; set; } + public string instagram_uid { get; set; } = ""; + public string kol_uid { get; set; } = ""; + public string kolMedia_uid { get; set; } = ""; + public string instagram_name { get; set; } = ""; + public string instagram_pic { get; set; } = ""; + public string instagram_revoke { get; set; } = "N"; + public int instagram_fansNum { get; set; } = 0; + public int instagram_followNum { get; set; } = 0; + public double instagram_postActive { get; set; } = 0.0; + public double instagram_reelsActive { get; set; } = 0.0; + public DateTime instagram_updatedate { get; set; } = DateTime.Now; + } + + + [Table("facebookKolView")] + public class facebookKolView + { + [JsonIgnore] + [Key] + public int facebook_sn { get; set; } + public string facebook_uid { get; set; } = ""; + public string kol_uid { get; set; } = ""; + public string kolMedia_uid { get; set; } = ""; + public string facebook_name { get; set; } = ""; + public string facebook_revoke { get; set; } = "N"; + public int facebook_fansNum { get; set; } = 0; + public int facebook_5_likesNum { get; set; } = 0; + public int facebook_5_msgNum { get; set; } = 0; + public int facebook_5_shareNum { get; set; } = 0; + public double facebook_active { get; set; } = 0.0; + public DateTime facebook_updatedate { get; set; } = DateTime.Now; + public string kol_name { get; set; } = ""; + public string kol_photo { get; set; } = ""; + public string kolMedia_url { get; set; } = ""; + } + + + + [Table("facebookDetail")] + public class facebookDetail + { + [JsonIgnore] + [Key] + public int facebookDetail_sn { get; set; } + public string facebook_uid { get; set; } = ""; + public string facebookDetail_publishedAt { get; set; } = ""; + public int facebookDetail_likeCount { get; set; } = 0; + public int facebookDetail_msgCount { get; set; } = 0; + public int facebookDetail_shareCount { get; set; } = 0; + public DateTime facebookDetail_createdate { get; set; } =DateTime.Now; + } + + [Table("facebook")] + public class facebook + { + [JsonIgnore] + [Key] + public int facebook_sn { get; set; } + public string facebook_uid { get; set; } = ""; + public string kol_uid { get; set; } = ""; + public string kolMedia_uid { get; set; } = ""; + public string facebook_name { get; set; } = ""; + public string facebook_revoke { get; set; } = "N"; + public int facebook_fansNum { get; set; } = 0; + public int facebook_5_likesNum { get; set; } = 0; + public int facebook_5_msgNum { get; set; } = 0; + public int facebook_5_shareNum { get; set; } = 0; + public double facebook_active { get; set; } = 0.0; + public DateTime facebook_updatedate { get; set; } = DateTime.Now; + } + + + [Table("youtubeDetail")] public class youtubeDetail { diff --git a/Models/youtubeUpdateClass.cs b/Models/youtubeUpdateClass.cs index 397aae9..76c3fed 100644 --- a/Models/youtubeUpdateClass.cs +++ b/Models/youtubeUpdateClass.cs @@ -29,7 +29,7 @@ public class youtubeUpdateClass : IHostedService, IDisposable { _timer = new Timer(DoWork, null, TimeSpan.Zero, - TimeSpan.FromSeconds(5 * 60)); + TimeSpan.FromSeconds(15 * 60)); return Task.CompletedTask; } diff --git a/Views/Home/Dashboard.cshtml b/Views/Home/Dashboard.cshtml index cebb543..5a0cd08 100644 --- a/Views/Home/Dashboard.cshtml +++ b/Views/Home/Dashboard.cshtml @@ -46,6 +46,9 @@
+ +
+
@@ -80,4 +83,64 @@ - \ No newline at end of file + + +
+ +
+ +
+ +
diff --git a/Views/Home/KolList.cshtml b/Views/Home/KolList.cshtml index 6104de1..53fd2a7 100644 --- a/Views/Home/KolList.cshtml +++ b/Views/Home/KolList.cshtml @@ -338,7 +338,7 @@
- +
diff --git a/Views/Home/ProjectList.cshtml b/Views/Home/ProjectList.cshtml index d9494cf..03d053a 100644 --- a/Views/Home/ProjectList.cshtml +++ b/Views/Home/ProjectList.cshtml @@ -106,13 +106,13 @@
- +
- +
- +
diff --git a/wwwroot/assets/javascript/custom/dashboard.js b/wwwroot/assets/javascript/custom/dashboard.js index 019eda1..69b0cac 100644 --- a/wwwroot/assets/javascript/custom/dashboard.js +++ b/wwwroot/assets/javascript/custom/dashboard.js @@ -2,8 +2,217 @@ $(document).ready(function () { loadYoutubeCard(); + loadFacebookCard(); + loadInstagramCard(); }); +function loadInstagramCard() { + $.ajax({ + url: "/Api/instagramList", + type: "post", + data: null, + success: function (data, textStatus, jqXHR) { + if (data.ret == "yes") { + var obj = data.list; + $('#card_group2').append(instagramCardHtml(obj)); + + + + + } else { + alert(data.message); + + if (data.err_code == "99999") { + location.href = "/Root/Login"; + } + } + }, + error: function (jqXHR, textStatus, errorThrown) { + alert('網路或伺服器發生錯誤,請稍後重試!'); + } + }); +} + +function instagramCardHtml(objItem) { + var html = ""; + html += ""; + html += "
"; + html += " "; + html += "
"; + html += " "; + html += "
"; + html += " "; + html += "
"; + html += " Instagram 排行 "; + html += "
"; + html += "
"; + html += "
"; + html += "
"; + html += " "; + html += "
"; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + + $.each(objItem, function (index, item) { + html += instagramSubHtml(item); + }); + + html += " "; + html += "
名稱 粉絲數 貼文互動數(近6) Reels預估觀看數 更新日期
"; + html += "
"; + html += " "; + html += "
"; + html += "
"; + html += "
"; + html += "
"; + + return html; +} + +function instagramSubHtml(item) { + var html = ""; + + var decimal = item.instagram_postActive; + var postPercent = (decimal * 100).toFixed(2) + "%"; + + var avgView = item.instagram_reelsActive.toFixed(0); + + var publishdate = new Date(item.instagram_updatedate); + + html += " "; + html += " "; + html += " "; + html += "  "; + html += " " + item.instagram_name + ""; + html += " "; + html += " " + AppendComma(item.instagram_fansNum) + " "; + html += " " + postPercent + " "; + html += " " + AppendComma(avgView) + " "; + html += " " + formatDate(publishdate, 'yyyy/MM/dd HH:mm:ss') + " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + + return html; +} + +function loadFacebookCard() { + $.ajax({ + url: "/Api/facebookList", + type: "post", + data: null, + success: function (data, textStatus, jqXHR) { + if (data.ret == "yes") { + var obj = data.list; + $('#card_group').append(facebookCardHtml(obj)); + + + + + } else { + alert(data.message); + + if (data.err_code == "99999") { + location.href = "/Root/Login"; + } + } + }, + error: function (jqXHR, textStatus, errorThrown) { + alert('網路或伺服器發生錯誤,請稍後重試!'); + } + }); +} + +function facebookCardHtml(objItem) { + var html = ""; + html += ""; + html += "
"; + html += " "; + html += "
"; + html += " "; + html += "
"; + html += " "; + html += "
"; + html += " Facebook 排行 "; + html += "
"; + html += "
"; + html += "
"; + html += "
"; + html += " "; + html += "
"; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + + $.each(objItem, function (index, item) { + html += facebookSubHtml(item); + }); + + html += " "; + html += "
名稱 追蹤者數 互動數(近5) 資料更新日期
"; + html += "
"; + html += " "; + html += "
"; + html += "
"; + html += "
"; + html += "
"; + + return html; +} + +function facebookSubHtml(item) { + var html = ""; + + var decimal = item.facebook_active; + var percent = (decimal * 100).toFixed(2) + "%"; + var publishdate = new Date(item.facebook_updatedate); + + html += " "; + html += " "; + html += " "; + html += "  "; + html += " " + item.facebook_name + ""; + html += " "; + html += " " + AppendComma(item.facebook_fansNum) + " "; + html += " " + percent + " "; + html += " " + formatDate(publishdate, 'yyyy/MM/dd HH:mm:ss') + " "; + html += " "; + html += " "; + html += " "; + html += " "; + + return html; +} + + function loadYoutubeCard() { $.ajax({ url: "/Api/youtubeList", @@ -54,9 +263,10 @@ function youtubeCardHtml(objItem) { html += " "; html += " "; html += " 頻道名稱 "; - html += " 帳號 "; + html += " 訂閱數 "; html += " 平均觀看數(近5) "; + html += " 資料更新日期 "; html += " "; html += " "; html += " "; @@ -89,9 +299,10 @@ function youtubeSubHtml(item) { html += "  "; html += " " + item.youtube_name + ""; html += " "; - html += " " + item.youtube_account + " "; + html += " " + AppendComma(item.youtube_subscriberCount) + " "; html += " " + AppendComma(item.youtube_avgViewCount) + " "; + html += " " + (new Date(item.youtube_updateTime)).format("yyyy/MM/dd hh:mm:ss") + " "; html += " "; html += " "; html += " "; @@ -100,6 +311,312 @@ function youtubeSubHtml(item) { return html; } +function instagramBtnClick(obj) { + var dataUid = obj.getAttribute('data-uid'); + var dataType = obj.getAttribute('data-method'); + + if (dataType == 'post') { + var trList = $("#instagramPost_layout").find(".masonry-item"); + $.each(trList, function (index, item) { + $(item).remove(); + }); + + var formData = { + instagram_uid: dataUid, + method: 'post' + } + + $.ajax({ + url: "/Api/instagramData", + type: "post", + data: formData, + success: function (data, textStatus, jqXHR) { + if (data.ret == "yes") { + var obj = data.list; + + var html = ""; + + $.each(obj, function (index, item) { + html += instagramPostModalHtml(item); + }); + + $('#instagramPost_layout').append(html); + + $('#InstagramPostModal').modal('toggle'); + + + } else { + alert(data.message); + + if (data.err_code == "99999") { + location.href = "/Root/Login"; + } + } + }, + error: function (jqXHR, textStatus, errorThrown) { + alert('網路或伺服器發生錯誤,請稍後重試!'); + } + }); + } + + if (dataType == 'reels') { + var trList = $("#instagramPost_layout").find(".masonry-item"); + $.each(trList, function (index, item) { + $(item).remove(); + }); + + var formData = { + instagram_uid: dataUid, + method: 'reels' + } + + $.ajax({ + url: "/Api/instagramData", + type: "reels", + data: formData, + success: function (data, textStatus, jqXHR) { + if (data.ret == "yes") { + var obj = data.list; + + var html = ""; + + $.each(obj, function (index, item) { + html += instagramReelsModalHtml(item); + }); + + $('#instagramPost_layout').append(html); + + $('#InstagramPostModal').modal('toggle'); + + + } else { + alert(data.message); + + if (data.err_code == "99999") { + location.href = "/Root/Login"; + } + } + }, + error: function (jqXHR, textStatus, errorThrown) { + alert('網路或伺服器發生錯誤,請稍後重試!'); + } + }); + } +} + +function instagramReelsModalHtml(obj) { + + + + var html = ""; + html += ""; + html += "
"; + html += " "; + html += "
"; + html += " "; + html += " "; + html += " "; + html += "
"; + html += " "; + html += "
"; + html += " "; + html += "
"; + html += "
"; + html += " " + obj.instagramDetail_title + ""; + html += "
"; + html += "
" + obj.instagramDetail_date + "
"; + html += "
"; + html += " "; + html += "
"; + html += " "; + html += "
"; + + html += " "; + html += "
"; + html += " "; + html += "
"; + html += "
" + AppendComma(obj.instagramDetail_viewNum) + "
"; + html += "

觀看數

"; + html += "
"; + html += "
"; + html += " "; + html += "
"; + html += " "; + html += "
"; + html += "
" + AppendComma(obj.instagramDetail_commentNum) + "
"; + html += "

留言數

"; + html += "
"; + html += "
"; + html += "
"; + html += "
"; + html += "
"; + html += "
"; + + return html; +} + +function instagramPostModalHtml(obj) { + + + + var html = ""; + html += ""; + html += "
"; + html += " "; + html += "
"; + html += " "; + html += " "; + html += " "; + html += "
"; + html += " "; + html += "
"; + html += " "; + html += "
"; + html += "
"; + html += " " + obj.instagramDetail_title + ""; + html += "
"; + html += "
" + obj.instagramDetail_date + "
"; + html += "
"; + html += " "; + html += "
"; + html += " "; + html += "
"; + + html += " "; + html += "
"; + html += " "; + html += "
"; + html += "
" + AppendComma(obj.instagramDetail_likeNum) + "
"; + html += "

喜歡數

"; + html += "
"; + html += "
"; + html += " "; + html += "
"; + html += " "; + html += "
"; + html += "
" + AppendComma(obj.instagramDetail_commentNum) + "
"; + html += "

留言數

"; + html += "
"; + html += "
"; + html += "
"; + html += "
"; + html += "
"; + html += "
"; + + return html; +} +function facebookBtnClick(obj) { + var dataUid = obj.getAttribute('data-uid'); + + + var trList = $("#facebook_layout").find(".masonry-item"); + $.each(trList, function (index, item) { + $(item).remove(); + }); + + var formData = { + facebook_uid: dataUid + } + + $.ajax({ + url: "/Api/facebookData", + type: "post", + data: formData, + success: function (data, textStatus, jqXHR) { + if (data.ret == "yes") { + var obj = data.list; + + var html = ""; + + $.each(obj, function (index, item) { + html += facebookModalHtml(item); + }); + + $('#facebook_layout').append(html); + + $('#FacebookModal').modal('toggle'); + + + } else { + alert(data.message); + + if (data.err_code == "99999") { + location.href = "/Root/Login"; + } + } + }, + error: function (jqXHR, textStatus, errorThrown) { + alert('網路或伺服器發生錯誤,請稍後重試!'); + } + }); +} + +function facebookModalHtml(obj) { + + //var publishdate = new Date(obj.youtubeDetail_publishedAt); + + var html = ""; + html += ""; + html += "
"; + html += " "; + html += "
"; + //html += " "; + //html += " "; + //html += " "; + html += "
"; + html += " "; + html += "
"; + html += " "; + html += "
"; + // html += "
"; + //html += " " + obj.youtubeDetail_title + ""; + //html += "
"; + //html += "
" + obj.+ "
"; + html += "
"; + html += " "; + html += "
"; + html += " "; + html += "
"; + html += " "; + html += "
"; + html += " "; + html += "
"; + html += " " + obj.facebookDetail_publishedAt + " "; + html += "

貼文發布時間

"; + + html += "
"; + html += "
"; + html += " "; + html += "
"; + html += " "; + html += "
"; + html += "
" + AppendComma(obj.facebookDetail_likeCount) + "
"; + html += "

按讚數

"; + html += "
"; + html += "
"; + html += " "; + html += "
"; + html += " "; + html += "
"; + html += "
" + AppendComma(obj.facebookDetail_msgCount) + "
"; + html += "

留言數

"; + html += "
"; + html += "
"; + html += " "; + html += "
"; + html += " "; + html += "
"; + html += "
" + AppendComma(obj.facebookDetail_shareCount) + "
"; + html += "

分享數

"; + html += "
"; + html += "
"; + html += "
"; + html += "
"; + html += "
"; + html += "
"; + + return html; +} function youtubeBtnClick(obj) { var dataUid = obj.getAttribute('data-uid'); diff --git a/wwwroot/images/instagram/igKol_20240516_CSTI980X1H99GYLZ.jpg b/wwwroot/images/instagram/igKol_20240516_CSTI980X1H99GYLZ.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f1432df78ebbec291700385d0f5463b8fb2de15a GIT binary patch literal 13297 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 literal 0 HcmV?d00001