diff --git a/service/common/consts.go b/agent/common/consts.go similarity index 100% rename from service/common/consts.go rename to agent/common/consts.go diff --git a/service/common/mq_config.go b/agent/common/mq_config.go similarity index 100% rename from service/common/mq_config.go rename to agent/common/mq_config.go diff --git a/service/common/pay_way_code.go b/agent/common/pay_way_code.go similarity index 100% rename from service/common/pay_way_code.go rename to agent/common/pay_way_code.go diff --git a/service/common/supplier.go b/agent/common/supplier.go similarity index 100% rename from service/common/supplier.go rename to agent/common/supplier.go diff --git a/agent/conf/app.conf b/agent/conf/app.conf new file mode 100644 index 0000000..6128daf --- /dev/null +++ b/agent/conf/app.conf @@ -0,0 +1,19 @@ +appname = agent +httpport = 12308 +#runmode = pro +runmode = dev + +#日志配置 +[logs] +# 0 ~ 7, 日志级别 +#level =7 +level =7 +#日志保存路径 +filepath= ../../logs/agent.log +#需要显示的日志信息 +#separate="["emergency", "alert", "critical", "error", "warning", "notice", "info", "debug"]" +separate="["emergency","alert","critical","error","warning","notice","info","debug"]" +#日志保存最大天数 +maxdays=10 + +sessionon = true \ No newline at end of file diff --git a/service/conf/config.go b/agent/conf/config.go similarity index 70% rename from service/conf/config.go rename to agent/conf/config.go index 48d02b0..8e330d3 100644 --- a/service/conf/config.go +++ b/agent/conf/config.go @@ -10,9 +10,9 @@ package conf const ( - DB_HOST = "rm-z7fchopj.mysql.rds.aliyuncs.com" + DB_HOST = "localhost" DB_PORT = "3306" - DB_USER = "dongfeng" - DB_PASSWORD = "UekR24BwfKx&^E5bcq43f" - DB_BASE = "dongfeng" + DB_USER = "root" + DB_PASSWORD = "Kyb^15273031604" + DB_BASE = "juhe_pay" ) diff --git a/agent/controllers/account_history.go b/agent/controllers/account_history.go new file mode 100644 index 0000000..7eaa8b0 --- /dev/null +++ b/agent/controllers/account_history.go @@ -0,0 +1,88 @@ +/*************************************************** + ** @Desc : This file for 账户变动 + ** @Time : 19.12.10 10:42 + ** @Author : Joker + ** @File : account_history + ** @Last Modified by : Joker + ** @Last Modified time: 19.12.10 10:42 + ** @Software: GoLand +****************************************************/ +package controllers + +import ( + "agent/models" + "agent/sys/enum" + "strconv" + "strings" +) + +type History struct { + KeepSession +} + +// 账户资产变动列表 +func (c *History) ShowHistoryListUI() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + ranMd5 := encrypt.EncodeMd5([]byte(pubMethod.RandomString(46))) + c.Ctx.SetCookie(enum.UserCookie, ranMd5, enum.CookieExpireTime) + c.Ctx.SetSecureCookie(ranMd5, enum.UserCookie, ranMd5, enum.CookieExpireTime) + c.SetSession(enum.UserCookie, ranMd5) + + c.Data["payType"] = enum.GetHistoryStatus() + c.Data["userName"] = u.AgentName + c.TplName = "history_record.html" +} + +func (c *History) HistoryQueryAndListPage() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + // 分页参数 + page, _ := strconv.Atoi(c.GetString("page")) + limit, _ := strconv.Atoi(c.GetString("limit")) + if limit == 0 { + limit = 15 + } + + // 查询参数 + in := make(map[string]string) + start := strings.TrimSpace(c.GetString("start")) + end := strings.TrimSpace(c.GetString("end")) + status := strings.TrimSpace(c.GetString("status")) + + in["type"] = status + in["account_uid"] = u.AgentUid + + if start != "" { + in["create_time__gte"] = start + } + if end != "" { + in["create_time__lte"] = end + } + + // 计算分页数 + count := models.GetAccountHistoryLenByMap(in) + totalPage := count / limit // 计算总页数 + if count%limit != 0 { // 不满一页的数据按一页计算 + totalPage++ + } + + // 数据获取 + var list []models.AccountHistoryInfo + if page <= totalPage { + list = models.GetAccountHistoryByMap(in, limit, (page-1)*limit) + } + + // 数据回显 + out := make(map[string]interface{}) + out["limit"] = limit // 分页数据 + out["page"] = page + out["totalPage"] = totalPage + out["root"] = list // 显示数据 + + c.Data["json"] = out + c.ServeJSON() + c.StopRun() +} diff --git a/agent/controllers/deal_excel.go b/agent/controllers/deal_excel.go new file mode 100644 index 0000000..9a0cef6 --- /dev/null +++ b/agent/controllers/deal_excel.go @@ -0,0 +1,435 @@ +/*************************************************** + ** @Desc : This file for 处理Excel文件 + ** @Time : 19.12.6 16:25 + ** @Author : Joker + ** @File : deal_excel + ** @Last Modified by : Joker + ** @Last Modified time: 19.12.6 16:25 + ** @Software: GoLand +****************************************************/ +package controllers + +import ( + "agent/models" + "agent/sys/enum" + "agent/utils" + "fmt" + "github.com/beego/beego/v2/core/logs" + "github.com/tealeg/xlsx" + "os" + "strings" + "time" +) + +type DealExcel struct { + KeepSession +} + +// 下载模板 +func (c *DealExcel) DownloadExcelModel() { + ranMd5 := encrypt.EncodeMd5([]byte(pubMethod.RandomString(46))) + c.Ctx.SetCookie(enum.UserCookie, ranMd5, enum.CookieExpireTime) + c.Ctx.SetSecureCookie(ranMd5, enum.UserCookie, ranMd5, enum.CookieExpireTime) + c.SetSession(enum.UserCookie, ranMd5) + + c.Ctx.Output.Download(enum.ExcelModelPath, enum.ExcelModelName) +} + +// 导出订单记录 +func (c *DealExcel) MakeOrderExcel() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + // 查询参数 + in := make(map[string]string) + merchantName := strings.TrimSpace(c.GetString("merchantName")) + start := strings.TrimSpace(c.GetString("start")) + end := strings.TrimSpace(c.GetString("end")) + payType := strings.TrimSpace(c.GetString("pay_type")) + status := strings.TrimSpace(c.GetString("status")) + + in["merchant_name__icontains"] = merchantName + in["pay_type_code"] = payType + in["status"] = status + in["agent_uid"] = u.AgentUid + + if start != "" { + in["update_time__gte"] = start + } + if end != "" { + in["update_time__lte"] = end + } + + var ( + msg = enum.FailedString + flag = enum.FailedFlag + fileName = "trade_order-" + pubMethod.GetNowTimeV2() + pubMethod.RandomString(6) + ".xlsx" + + file *xlsx.File + sheet *xlsx.Sheet + row *xlsx.Row + cell *xlsx.Cell + err error + ) + + // 数据获取 + list := models.GetOrderProfitByMap(in, -1, 0) + if len(list) <= 0 { + msg = "没有检索到数据!" + goto stopRun + } + + // 写入记录 + file = xlsx.NewFile() + sheet, err = file.AddSheet("订单记录") + if err != nil { + utils.LogError(fmt.Sprintf("代理商户:%s 导出订单记录,发生错误:%v", u.AgentName, err)) + msg = enum.FailedToAdmin + goto stopRun + } + + // 第一行 + row = sheet.AddRow() + row.SetHeightCM(1) + cell = row.AddCell() + cell.Value = "平台订单号" + cell = row.AddCell() + cell.Value = "商户订单号" + cell = row.AddCell() + cell.Value = "支付方式" + cell = row.AddCell() + cell.Value = "订单金额" + cell = row.AddCell() + cell.Value = "收入金额" + cell = row.AddCell() + cell.Value = "平台手续费" + cell = row.AddCell() + cell.Value = "代理商手续费" + cell = row.AddCell() + cell.Value = "状 态" + cell = row.AddCell() + cell.Value = "成功支付时间" + for _, v := range list { + addRow := sheet.AddRow() + addCell := addRow.AddCell() + addCell.Value = v.BankOrderId + addCell = addRow.AddCell() + addCell.Value = v.MerchantOrderId + addCell = addRow.AddCell() + addCell.Value = v.PayProductName + addCell = addRow.AddCell() + addCell.Value = fmt.Sprintf("%f", v.OrderAmount) + + var ( + st = "" + t string + ) + switch v.Status { + case "failed": + st = "交易失败" + case "wait": + st = "等待支付" + case "success": + st = "交易成功" + t = v.UpdateTime + } + + addCell = addRow.AddCell() + addCell.Value = fmt.Sprintf("%f", v.UserInAmount) + addCell = addRow.AddCell() + addCell.Value = fmt.Sprintf("%f", v.PlatformProfit) + addCell = addRow.AddCell() + addCell.Value = fmt.Sprintf("%f", v.AgentProfit) + addCell = addRow.AddCell() + addCell.Value = st + addCell = addRow.AddCell() + addCell.Value = t + } + + err = file.Save(enum.ExcelDownloadPath + fileName) + if err != nil { + utils.LogError(fmt.Sprintf("代理商户:%s 导出订单记录,保存文件发生错误:%v", u.AgentName, err)) + msg = enum.FailedToAdmin + goto stopRun + } + + flag = enum.SuccessFlag + msg = fileName + +stopRun: + c.Data["json"] = pubMethod.JsonFormat(flag, "", msg, "") + c.ServeJSON() + c.StopRun() +} + +// 下载excel +func (c *DealExcel) DownloadRecordExcel() { + fileName := c.GetString(":params") + file := enum.ExcelDownloadPath + fileName + + defer func() { + if r := recover(); r != nil { + logs.Error(fmt.Sprintf("%s此文件不存在", file)) + time.Sleep(3 * time.Second) + } + }() + // 删除临时文件 + go func() { + tk := time.NewTicker(5 * time.Minute) + select { + case <-tk.C: + _ = os.Remove(file) + tk.Stop() + } + }() + + c.Ctx.Output.Download(file, fileName) +} + +// 导出投诉记录 +func (c *DealExcel) MakeComplaintExcel() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + // 查询参数 + in := make(map[string]string) + merchantName := strings.TrimSpace(c.GetString("merchantName")) + start := strings.TrimSpace(c.GetString("start")) + end := strings.TrimSpace(c.GetString("end")) + payType := strings.TrimSpace(c.GetString("pay_type")) + status := strings.TrimSpace(c.GetString("status")) + + in["pay_type_code"] = payType + in["merchant_name__icontains"] = merchantName + if strings.Compare("YES", status) == 0 { + in["freeze"] = enum.YES + } else { + in["refund"] = enum.YES + } + in["agent_uid"] = u.AgentUid + + if start != "" { + in["update_time__gte"] = start + } + if end != "" { + in["update_time__lte"] = end + } + + var ( + msg = enum.FailedString + flag = enum.FailedFlag + fileName = "complaint_order-" + pubMethod.GetNowTimeV2() + pubMethod.RandomString(6) + ".xlsx" + + file *xlsx.File + sheet *xlsx.Sheet + row *xlsx.Row + cell *xlsx.Cell + err error + ) + + // 数据获取 + list := models.GetOrderByMap(in, -1, 0) + if len(list) <= 0 { + msg = "没有检索到数据!" + goto stopRun + } + + // 写入记录 + file = xlsx.NewFile() + sheet, err = file.AddSheet("投诉记录") + if err != nil { + utils.LogError(fmt.Sprintf("代理商户:%s 导出投诉记录,发生错误:%v", u.AgentName, err)) + msg = enum.FailedToAdmin + goto stopRun + } + + // 第一行 + row = sheet.AddRow() + row.SetHeightCM(1) + cell = row.AddCell() + cell.Value = "平台流水号" + cell = row.AddCell() + cell.Value = "商户订单号" + cell = row.AddCell() + cell.Value = "支付方式" + cell = row.AddCell() + cell.Value = "订单金额" + cell = row.AddCell() + cell.Value = "状 态" + cell = row.AddCell() + cell.Value = "冻结时间" + for _, v := range list { + addRow := sheet.AddRow() + addCell := addRow.AddCell() + addCell.Value = v.BankOrderId + addCell = addRow.AddCell() + addCell.Value = v.MerchantOrderId + addCell = addRow.AddCell() + addCell.Value = v.PayProductName + addCell = addRow.AddCell() + addCell.Value = fmt.Sprintf("%f", v.OrderAmount) + + var st = "" + switch v.Freeze { + case "yes": + st = "已冻结" + case "no": + st = "已退款" + } + + addCell = addRow.AddCell() + addCell.Value = st + addCell = addRow.AddCell() + addCell.Value = v.UpdateTime + } + + err = file.Save(enum.ExcelDownloadPath + fileName) + if err != nil { + utils.LogError(fmt.Sprintf("代理商户:%s 导出投诉记录,保存文件发生错误:%v", u.AgentName, err)) + msg = enum.FailedToAdmin + goto stopRun + } + + flag = enum.SuccessFlag + msg = fileName + +stopRun: + c.Data["json"] = pubMethod.JsonFormat(flag, "", msg, "") + c.ServeJSON() + c.StopRun() +} + +// 导出提现记录 +func (c *DealExcel) MakeWithdrawExcel() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + // 查询参数 + in := make(map[string]string) + start := strings.TrimSpace(c.GetString("start")) + end := strings.TrimSpace(c.GetString("end")) + status := strings.TrimSpace(c.GetString("status")) + + in["status"] = status + in["merchant_uid"] = u.AgentUid + + if start != "" { + in["update_time__gte"] = start + } + if end != "" { + in["update_time__lte"] = end + } + + var ( + msg = enum.FailedString + flag = enum.FailedFlag + fileName = "withdraw_order-" + pubMethod.GetNowTimeV2() + pubMethod.RandomString(6) + ".xlsx" + + file *xlsx.File + sheet *xlsx.Sheet + row *xlsx.Row + cell *xlsx.Cell + err error + ) + + // 数据获取 + list := models.GetPayForByMap(in, -1, 0) + if len(list) <= 0 { + msg = "没有检索到数据!" + goto stopRun + } + + // 写入记录 + file = xlsx.NewFile() + sheet, err = file.AddSheet("提现记录") + if err != nil { + utils.LogError(fmt.Sprintf("代理商户:%s 导出提现记录,发生错误:%v", u.AgentName, err)) + msg = enum.FailedToAdmin + goto stopRun + } + + // 第一行 + row = sheet.AddRow() + row.SetHeightCM(1) + cell = row.AddCell() + cell.Value = "平台订单号" + cell = row.AddCell() + cell.Value = "商户订单号" + cell = row.AddCell() + cell.Value = "结算金额" + cell = row.AddCell() + cell.Value = "手续费" + cell = row.AddCell() + cell.Value = "银行名称" + cell = row.AddCell() + cell.Value = "开户名" + cell = row.AddCell() + cell.Value = "开户账户" + cell = row.AddCell() + cell.Value = "状 态" + cell = row.AddCell() + cell.Value = "创建时间" + cell = row.AddCell() + cell.Value = "打款时间" + cell = row.AddCell() + cell.Value = "备注" + for _, v := range list { + addRow := sheet.AddRow() + addCell := addRow.AddCell() + addCell.Value = v.BankOrderId + addCell = addRow.AddCell() + addCell.Value = v.MerchantOrderId + addCell = addRow.AddCell() + addCell.Value = fmt.Sprintf("%f", v.PayforTotalAmount) + addCell = addRow.AddCell() + addCell.Value = fmt.Sprintf("%f", v.PayforFee) + addCell = addRow.AddCell() + addCell.Value = v.BankName + addCell = addRow.AddCell() + addCell.Value = v.BankAccountName + addCell = addRow.AddCell() + addCell.Value = v.BankAccountNo + + var ( + st = "" + t string + ) + switch v.Status { + case "payfor_confirm": + st = "等待审核" + case "payfor_solving": + st = "系统处理中" + case "payfor_banking": + st = "银行处理中" + case "success": + st = "代付成功" + t = v.UpdateTime + case "failed": + st = "代付失败" + } + + addCell = addRow.AddCell() + addCell.Value = st + addCell = addRow.AddCell() + addCell.Value = v.CreateTime + addCell = addRow.AddCell() + addCell.Value = t + addCell = addRow.AddCell() + addCell.Value = v.Remark + } + + err = file.Save(enum.ExcelDownloadPath + fileName) + if err != nil { + utils.LogError(fmt.Sprintf("代理商户:%s 导出提现记录,保存文件发生错误:%v", u.AgentName, err)) + msg = enum.FailedToAdmin + goto stopRun + } + + flag = enum.SuccessFlag + msg = fileName + +stopRun: + c.Data["json"] = pubMethod.JsonFormat(flag, "", msg, "") + c.ServeJSON() + c.StopRun() +} diff --git a/agent/controllers/index.go b/agent/controllers/index.go new file mode 100644 index 0000000..b0db675 --- /dev/null +++ b/agent/controllers/index.go @@ -0,0 +1,158 @@ +/*************************************************** + ** @Desc : This file for 首页 + ** @Time : 19.11.30 11:49 + ** @Author : Joker + ** @File : index + ** @Last Modified by : Joker + ** @Last Modified time: 19.11.30 11:49 + ** @Software: GoLand +****************************************************/ +package controllers + +import ( + "agent/models" + "agent/sys/enum" + "fmt" +) + +type Index struct { + KeepSession +} + +// 首页 +func (c *Index) ShowUI() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + c.Data["userName"] = u.AgentName + c.TplName = "index.html" +} + +// 加载用户账户金额信息 +func (c *Index) LoadUserAccountInfo() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + ac := models.GetAccountByUid(u.AgentUid) + + info := make(map[string]interface{}) + // 账户余额 + info["balanceAmt"] = pubMethod.FormatFloat64ToString(ac.Balance) + + // 可用余额 + info["settAmount"] = pubMethod.FormatFloat64ToString(ac.WaitAmount) + + // 冻结金额 + info["freezeAmt"] = pubMethod.FormatFloat64ToString(ac.FreezeAmount) + + // 押款金额 + info["amountFrozen"] = pubMethod.FormatFloat64ToString(ac.LoanAmount) + + c.Data["json"] = info + c.ServeJSON() + c.StopRun() +} + +// 加载总订单信息 +func (c *Index) LoadCountOrder() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + md := models.GetMerchantDeployByUid(u.AgentUid) + + type orderInPayWay struct { + PayWayName string // 支付方式名 + OrderCount int // 订单数 + SucOrderCount int // 成功订单数 + SucRate string // 成功率 + } + + ways := make([]orderInPayWay, len(md)) + + for k, v := range md { + in := make(map[string]string) + in["agent_uid"] = u.AgentUid + + ways[k].PayWayName = models.GetRoadInfoByRoadUid(v.SingleRoadUid).ProductName + + in["road_uid"] = v.SingleRoadUid + ways[k].OrderCount = models.GetOrderLenByMap(in) + + in["status"] = enum.SUCCESS + ways[k].SucOrderCount = models.GetOrderLenByMap(in) + + if ways[k].OrderCount == 0 { + ways[k].SucRate = "0" + continue + } + ways[k].SucRate = fmt.Sprintf("%0.4f", float64(ways[k].SucOrderCount)/float64(ways[k].OrderCount)) + } + + c.Data["json"] = ways + c.ServeJSON() + c.StopRun() +} + +// 加载总订单数 +func (c *Index) LoadOrderCount() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + out := make(map[string]interface{}) + + in := make(map[string]string) + in["agent_uid"] = u.AgentUid + out["orders"] = models.GetOrderLenByMap(in) + + in["status"] = enum.SUCCESS + out["suc_orders"] = models.GetOrderLenByMap(in) + + if out["orders"].(int) == 0 { + out["suc_rate"] = 0 + } else { + out["suc_rate"] = fmt.Sprintf("%0.4f", float64(out["suc_orders"].(int))/float64(out["orders"].(int))) + } + + c.Data["json"] = out + c.ServeJSON() + c.StopRun() +} + +// 加载用户支付配置 +func (c *Index) LoadUserPayWayUI() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + c.Data["userName"] = u.AgentName + c.TplName = "pay_way.html" +} + +func (c *Index) LoadUserPayWay() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + md := models.GetMerchantDeployByUid(u.AgentUid) + + type payConfig struct { + No string // 通道编号 + Name string // 产品名 + PlatRate float64 // 通道费率 + AgentRate float64 // 通道费率 + } + + ways := make([]payConfig, len(md)) + + for k, v := range md { + road := models.GetRoadInfoByRoadUid(v.SingleRoadUid) + ways[k].No = road.RoadUid + + ways[k].Name = road.ProductName + + ways[k].PlatRate = road.BasicFee + v.SingleRoadPlatformRate + v.SingleRoadAgentRate + ways[k].AgentRate = v.SingleRoadAgentRate + } + + c.Data["json"] = ways + c.ServeJSON() + c.StopRun() +} diff --git a/agent/controllers/keep_session.go b/agent/controllers/keep_session.go new file mode 100644 index 0000000..7705f7d --- /dev/null +++ b/agent/controllers/keep_session.go @@ -0,0 +1,51 @@ +/*************************************************** + ** @Desc : This file for 保持会话 + ** @Time : 19.11.29 13:55 + ** @Author : Joker + ** @File : keep_session + ** @Last Modified by : Joker + ** @Last Modified time: 19.11.29 13:55 + ** @Software: GoLand +****************************************************/ +package controllers + +import ( + "agent/sys/enum" + "github.com/beego/beego/v2/server/web" +) + +type KeepSession struct { + web.Controller +} + +// 生成随机md5值,客户端和服务端各保存一份 +// 客户端每次请求都将重写md5值 +// 若用户在30分钟内没有操作行为或连续操作时间超过3小时,则自动退出 +func (c *KeepSession) Prepare() { + // 以免session值不是string类型而panic + defer func() { + if err := recover(); err != nil { + c.DelSession(enum.UserSession) + c.Ctx.Redirect(302, "/") + } + }() + + us := c.GetSession(enum.UserSession) + uc := c.GetSession(enum.UserCookie) + if us == nil || uc == nil { + c.DelSession(enum.UserSession) + c.Ctx.Redirect(302, "/") + } + + if uc.(string) == "" { + c.DelSession(enum.UserSession) + c.Ctx.Redirect(302, "/") + } + + _, b := c.Ctx.GetSecureCookie(uc.(string), enum.UserCookie) + //utils.LogNotice(fmt.Sprintf("客户端cookie:%s,服务端cookie:%s", cookie, uc.(string))) + if !b { + c.DelSession(enum.UserSession) + c.Ctx.Redirect(302, "/") + } +} diff --git a/agent/controllers/login.go b/agent/controllers/login.go new file mode 100644 index 0000000..039f8a9 --- /dev/null +++ b/agent/controllers/login.go @@ -0,0 +1,156 @@ +/*************************************************** + ** @Desc : This file for 用户登录 + ** @Time : 19.11.29 13:52 + ** @Author : Joker + ** @File : login + ** @Last Modified by : Joker + ** @Last Modified time: 19.11.29 13:52 + ** @Software: GoLand +****************************************************/ +package controllers + +import ( + "agent/models" + "agent/sys" + "agent/sys/enum" + "agent/utils" + "fmt" + beego "github.com/beego/beego/v2/server/web" + "github.com/dchest/captcha" + "strconv" + "strings" +) + +var pubMethod = sys.PublicMethod{} +var encrypt = utils.Encrypt{} + +type Login struct { + beego.Controller +} + +func (c *Login) UserLogin() { + captchaCode := c.GetString("captchaCode") + captchaId := c.GetString("captchaId") + userName := strings.TrimSpace(c.GetString("userName")) + password := c.GetString("Password") + + var ( + flag = enum.FailedFlag + msg = "" + url = "/" + + pwdMd5 string + ran string + ranMd5 string + + verify bool + u models.AgentInfo + ) + + us := c.GetSession(enum.UserSession) + fmt.Println(us) + if us != nil { + url = enum.DoMainUrl + flag = enum.SuccessFlag + goto stopRun + } + + if userName == "" || password == "" { + msg = "登录账号或密码不能为空!" + goto stopRun + } + + verify = captcha.VerifyString(captchaId, captchaCode) + if !verify { + url = strconv.Itoa(enum.FailedFlag) + msg = "验证码不正确!" + goto stopRun + } + + u = models.GetAgentInfoByPhone(userName) + if u.AgentPassword == "" { + msg = "账户信息错误,请联系管理人员!" + goto stopRun + } + + if strings.Compare(enum.ACTIVE, u.Status) != 0 { + msg = "登录账号或密码错误!" + goto stopRun + } + + //验证密码 + pwdMd5 = encrypt.EncodeMd5([]byte(password)) + if strings.Compare(strings.ToUpper(pwdMd5), u.AgentPassword) != 0 { + msg = "登录账号或密码错误!" + goto stopRun + } + + c.SetSession(enum.UserSession, u) + + // 设置客户端用户信息有效保存时间 + ran = pubMethod.RandomString(46) + ranMd5 = encrypt.EncodeMd5([]byte(ran)) + c.Ctx.SetSecureCookie(ranMd5, enum.UserCookie, ranMd5, enum.CookieExpireTime) + c.SetSession(enum.UserCookie, ranMd5) + + url = enum.DoMainUrl + flag = enum.SuccessFlag + //logs.Notice(fmt.Sprintf("【%s】代理商登录成功,请求IP:%s", u.AgentName, c.Ctx.Input.IP()) + +stopRun: + c.Data["json"] = pubMethod.JsonFormat(flag, "", msg, url) + fmt.Println(c.Data["json"]) + c.ServeJSON() + //c.StopRun() +} + +func (c *Login) Index() { + capt := struct { + CaptchaId string + }{ + captcha.NewLen(4), + } + c.Data["CaptchaId"] = capt.CaptchaId + c.TplName = "login.html" +} + +// 验证输入的验证码 +func (c *Login) VerifyCaptcha() { + captchaValue := c.Ctx.Input.Param(":value") + captchaId := c.Ctx.Input.Param(":chaId") + + verify := captcha.VerifyString(captchaId, captchaValue) + if verify { + c.Data["json"] = pubMethod.JsonFormat(enum.SuccessFlag, "", "", "") + } else { + c.Data["json"] = pubMethod.JsonFormat(enum.FailedFlag, "", "验证码不匹配!", "") + } + c.ServeJSON() + c.StopRun() +} + +// 重绘验证码 +func (c *Login) FlushCaptcha() { + capt := struct { + CaptchaId string + }{ + captcha.NewLen(4), + } + c.Data["json"] = pubMethod.JsonFormat(enum.SuccessFlag, capt.CaptchaId, "验证码不匹配!", "") + c.ServeJSON() + c.StopRun() +} + +// 退出登录 +func (c *Login) LoginOut() { + c.DelSession(enum.UserSession) + + c.Data["json"] = pubMethod.JsonFormat(enum.FailedFlag, "", "", "/") + c.ServeJSON() + c.StopRun() +} + +// 对接文档 +func (c *Login) PayDoc() { + c.TplName = "api_doc/pay_doc.html" +} diff --git a/agent/controllers/multi_withdraw.go b/agent/controllers/multi_withdraw.go new file mode 100644 index 0000000..f5b7899 --- /dev/null +++ b/agent/controllers/multi_withdraw.go @@ -0,0 +1,250 @@ +/*************************************************** + ** @Desc : This file for 批量提现 + ** @Time : 19.12.6 17:07 + ** @Author : Joker + ** @File : multi_withdraw + ** @Last Modified by : Joker + ** @Last Modified time: 19.12.6 17:07 + ** @Software: GoLand +****************************************************/ +package controllers + +import ( + "agent/common" + "agent/models" + "agent/sys/enum" + "agent/utils" + "fmt" + "github.com/rs/xid" + "github.com/tealeg/xlsx" + "path" + "regexp" + "strconv" + "strings" + "time" +) + +type MultiWithdraw struct { + KeepSession +} + +func (c *MultiWithdraw) ShowMultiWithdrawUI() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + ranMd5 := encrypt.EncodeMd5([]byte(pubMethod.RandomString(46))) + c.Ctx.SetCookie(enum.UserCookie, ranMd5, enum.CookieExpireTime) + c.Ctx.SetSecureCookie(ranMd5, enum.UserCookie, ranMd5, enum.CookieExpireTime) + c.SetSession(enum.UserCookie, ranMd5) + + c.Data["userName"] = u.AgentName + c.TplName = "withdraw/multi_withdraw.html" +} + +// 申请批量提现 +func (c *Withdraw) LaunchMultiWithdraw() { + mobileCode := strings.TrimSpace(c.GetString("mobileCode")) + file, header, err := c.GetFile("file") + + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + var ( + msg = enum.FailedString + flag = enum.FailedFlag + + b bool + + url string + ) + + fileName := header.Filename + defer file.Close() + split := strings.Split(fileName, ".") + if len(split) < 2 { + msg = "请选择批量文件!" + goto stopRun + } + if strings.Compare(strings.ToLower(split[1]), "xls") != 0 && + strings.Compare(strings.ToLower(split[1]), "xlsx") != 0 { + msg = "仅支持“xls”、“xlsx”格式文件!" + goto stopRun + } + if err != nil { + msg = "请上传批量文件! " + err.Error() + goto stopRun + } + + if u.PayPassword == "" { + msg = "请设置支付密码!" + goto stopRun + } + if strings.Compare(strings.ToUpper(encrypt.EncodeMd5([]byte(mobileCode))), u.PayPassword) != 0 { + msg = "支付密码输入错误!" + goto stopRun + } + + u = models.GetAgentInfoByAgentUid(u.AgentUid) + if strings.Compare(enum.ACTIVE, u.Status) != 0 { + msg = "商户状态异常,请联系管理人员!" + goto stopRun + } + + b, msg = handleFileContent(split[0], u, c) + if b { + flag = enum.SuccessFlag + url = "/withdraw/show_list_ui" + } + +stopRun: + c.Data["json"] = pubMethod.JsonFormat(flag, "", msg, url) + c.ServeJSON() + c.StopRun() +} + +func handleFileContent(name string, u models.AgentInfo, c *Withdraw) (bool, string) { + // 重命名文件 + fileName := name + " - " + pubMethod.GetNowTimeV2() + pubMethod.RandomString(4) + ".xlsx" + + // 保存文件 + _ = c.SaveToFile("file", path.Join(enum.ExcelPath, fileName)) + + // 读取文件内容 + xlFile, err := xlsx.OpenFile(enum.ExcelPath + fileName) + if err != nil { + msg := "文件内容错误:" + err.Error() + utils.LogInfo(msg) + return false, msg + } + + // 只读取文档中第一个工作表,忽略其他工作表 + sheet := xlFile.Sheets[0] + line, err := sheet.Row(0).Cells[1].Int() + if err != nil { + msg := "请输入正确的总笔数:" + err.Error() + utils.LogInfo(msg) + return false, msg + } + if line <= 0 { + msg := "请输入正确的总笔数!" + return false, msg + } + if line > 300 { + line = 300 + } + + ac := models.GetAccountByUid(u.AgentUid) + if strings.Compare(enum.ACTIVE, ac.Status) != 0 { + msg := "账户状态异常,请联系管理人员!" + return false, msg + } + // 后台处理文件,不让用户等待 + go func() { + for k, row := range sheet.Rows { + if k == 0 || k == 1 { + continue + } + + // 数据行数不得超过指定行数 + if k == line+2 || k == 301 { + break + } + + // 出现空行,则忽略后面记录 + if row.Cells[0].String() == "" || row.Cells[4].String() == "" { + break + } + + bankAccountType := row.Cells[3].String() + ac := models.GetAccountByUid(u.AgentUid) + b, msg, code := verifyFileContent(row.Cells[0].String(), row.Cells[1].String(), row.Cells[2].String(), bankAccountType, + row.Cells[4].String(), ac) + if !b { + utils.LogInfo(fmt.Sprintf("用户:%s 批量代付中,第 %d 行记录出现错误:%s", u.AgentName, k+1, msg)) + // 账户可用余额不足,终止读取记录 + if code == 5009 { + break + } + continue + } + + if strings.Compare("对公", bankAccountType) == 0 { + bankAccountType = enum.PublicAccount + } else { + bankAccountType = enum.PrivateDebitAccount + } + + money, _ := strconv.ParseFloat(row.Cells[4].String(), 10) + payFor := models.PayforInfo{ + PayforUid: "pppp" + xid.New().String(), + MerchantUid: u.AgentUid, + MerchantName: u.AgentName, + PhoneNo: u.AgentPhone, + MerchantOrderId: xid.New().String(), + BankOrderId: "4444" + xid.New().String(), + PayforFee: common.PAYFOR_FEE, + Type: common.SELF_MERCHANT, + PayforAmount: money, + PayforTotalAmount: money + common.PAYFOR_FEE, + BankCode: "C", + BankName: row.Cells[2].String(), + IsSend: common.NO, + BankAccountName: row.Cells[0].String(), + BankAccountNo: row.Cells[1].String(), + BankAccountType: bankAccountType, + BankAccountAddress: row.Cells[2].String(), + Status: common.PAYFOR_COMFRIM, + CreateTime: pubMethod.GetNowTime(), + UpdateTime: pubMethod.GetNowTime(), + } + + models.InsertPayfor(payFor) + + time.Sleep(500 * time.Millisecond) + } + }() + + return true, "提交成功,等待审核中,请在结算信息中查询状态!" +} + +// 验证文件内容是否规范 +func verifyFileContent(accountName, cardNo, bankAccountAddress, bankAccountType, amount string, ac models.AccountInfo) (bool, string, int) { + if accountName == "" || cardNo == "" { + msg := "账户名或卡号不能为空!" + return false, msg, 5001 + } + // 账户类型 + if strings.Compare("对公", bankAccountType) == 0 { + if bankAccountAddress == "" { + msg := "收款方开户机构名称不能为空!" + return false, msg, 5002 + } + } + if amount == "" { + msg := "金额不能为空!" + return false, msg, 5003 + } + matched, _ := regexp.MatchString(enum.MoneyReg, amount) + if !matched { + msg := "请输入正确的金额!" + return false, msg, 5004 + } + f, err := strconv.ParseFloat(amount, 10) + if err != nil { + msg := "请输入正确的金额! " + err.Error() + return false, msg, 5007 + } + + if f > enum.WithdrawalMaxAmount || f < enum.WithdrawalMinAmount || f+enum.SettlementFee > ac.WaitAmount { + msg := fmt.Sprintf("单笔提现金额超出限制,提现金额:%f,账户可结算余额:%f,提现最小额:%d,最大额:%d,手续费:%d", + f, ac.WaitAmount, enum.WithdrawalMinAmount, enum.WithdrawalMaxAmount, enum.SettlementFee) + return false, msg, 5008 + } + + if f+enum.SettlementFee > ac.Balance || ac.Balance <= 0 { + msg := fmt.Sprintf("账户金额不足,提现金额:%f,账户余额:%f,手续费:%d", + f, ac.Balance, enum.SettlementFee) + return false, msg, 5009 + } + return true, "", 5000 +} diff --git a/agent/controllers/trade_record.go b/agent/controllers/trade_record.go new file mode 100644 index 0000000..cda413e --- /dev/null +++ b/agent/controllers/trade_record.go @@ -0,0 +1,173 @@ +/*************************************************** + ** @Desc : This file for 交易记录 + ** @Time : 19.12.2 16:34 + ** @Author : Joker + ** @File : trade_record + ** @Last Modified by : Joker + ** @Last Modified time: 19.12.2 16:34 + ** @Software: GoLand +****************************************************/ +package controllers + +import ( + "agent/models" + "agent/sys/enum" + "strconv" + "strings" +) + +type TradeRecord struct { + KeepSession +} + +func (c *TradeRecord) ShowUI() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + ranMd5 := encrypt.EncodeMd5([]byte(pubMethod.RandomString(46))) + c.Ctx.SetCookie(enum.UserCookie, ranMd5, enum.CookieExpireTime) + c.Ctx.SetSecureCookie(ranMd5, enum.UserCookie, ranMd5, enum.CookieExpireTime) + c.SetSession(enum.UserCookie, ranMd5) + + c.Data["payType"] = enum.GetPayType() + c.Data["status"] = enum.GetOrderStatus() + c.Data["userName"] = u.AgentName + c.TplName = "trade_record.html" +} + +// 订单记录查询分页 +func (c *TradeRecord) TradeQueryAndListPage() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + // 分页参数 + page, _ := strconv.Atoi(c.GetString("page")) + limit, _ := strconv.Atoi(c.GetString("limit")) + if limit == 0 { + limit = 15 + } + + // 查询参数 + in := make(map[string]string) + merchantNo := strings.TrimSpace(c.GetString("MerchantNo")) + merchantName := strings.TrimSpace(c.GetString("merchantName")) + start := strings.TrimSpace(c.GetString("start")) + end := strings.TrimSpace(c.GetString("end")) + payType := strings.TrimSpace(c.GetString("pay_type")) + status := strings.TrimSpace(c.GetString("status")) + + in["merchant_order_id"] = merchantNo + in["merchant_name__icontains"] = merchantName + in["pay_type_code"] = payType + in["status"] = status + in["agent_uid"] = u.AgentUid + + if start != "" { + in["update_time__gte"] = start + } + if end != "" { + in["update_time_lte"] = end + } + + // 计算分页数 + count := models.GetOrderProfitLenByMap(in) + totalPage := count / limit // 计算总页数 + if count%limit != 0 { // 不满一页的数据按一页计算 + totalPage++ + } + + // 数据获取 + var list []models.OrderProfitInfo + if page <= totalPage { + list = models.GetOrderProfitByMap(in, limit, (page-1)*limit) + } + + // 数据回显 + out := make(map[string]interface{}) + out["limit"] = limit // 分页数据 + out["page"] = page + out["totalPage"] = totalPage + out["root"] = list // 显示数据 + + c.Data["json"] = out + c.ServeJSON() + c.StopRun() +} + +func (c *TradeRecord) ShowComplaintUI() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + ranMd5 := encrypt.EncodeMd5([]byte(pubMethod.RandomString(46))) + c.Ctx.SetCookie(enum.UserCookie, ranMd5, enum.CookieExpireTime) + c.Ctx.SetSecureCookie(ranMd5, enum.UserCookie, ranMd5, enum.CookieExpireTime) + c.SetSession(enum.UserCookie, ranMd5) + + c.Data["payType"] = enum.GetPayType() + c.Data["status"] = enum.GetComOrderStatus() + c.Data["userName"] = u.AgentName + c.TplName = "complaint_record.html" +} + +// 投诉列表查询分页 +func (c *TradeRecord) ComplaintQueryAndListPage() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + // 分页参数 + page, _ := strconv.Atoi(c.GetString("page")) + limit, _ := strconv.Atoi(c.GetString("limit")) + if limit == 0 { + limit = 15 + } + + // 查询参数 + in := make(map[string]string) + merchantNo := strings.TrimSpace(c.GetString("MerchantNo")) + merchantName := strings.TrimSpace(c.GetString("merchantName")) + start := strings.TrimSpace(c.GetString("start")) + end := strings.TrimSpace(c.GetString("end")) + payType := strings.TrimSpace(c.GetString("pay_type")) + status := strings.TrimSpace(c.GetString("status")) + + in["merchant_order_id"] = merchantNo + in["merchant_name__icontains"] = merchantName + in["pay_type_code"] = payType + if strings.Compare("YES", status) == 0 { + in["freeze"] = enum.YES + } else { + in["refund"] = enum.YES + } + in["agent_uid"] = u.AgentUid + + if start != "" { + in["update_time__gte"] = start + } + if end != "" { + in["update_time__lte"] = end + } + + // 计算分页数 + count := models.GetOrderLenByMap(in) + totalPage := count / limit // 计算总页数 + if count%limit != 0 { // 不满一页的数据按一页计算 + totalPage++ + } + + // 数据获取 + var list []models.OrderInfo + if page <= totalPage { + list = models.GetOrderByMap(in, limit, (page-1)*limit) + } + + // 数据回显 + out := make(map[string]interface{}) + out["limit"] = limit // 分页数据 + out["page"] = page + out["totalPage"] = totalPage + out["root"] = list // 显示数据 + + c.Data["json"] = out + c.ServeJSON() + c.StopRun() +} diff --git a/agent/controllers/user_info.go b/agent/controllers/user_info.go new file mode 100644 index 0000000..4999efd --- /dev/null +++ b/agent/controllers/user_info.go @@ -0,0 +1,332 @@ +/*************************************************** + ** @Desc : This file for 用户信息控制 + ** @Time : 19.12.3 10:38 + ** @Author : Joker + ** @File : user_info + ** @Last Modified by : Joker + ** @Last Modified time: 19.12.3 10:38 + ** @Software: GoLand +****************************************************/ +package controllers + +import ( + "agent/models" + "agent/sys/enum" + "regexp" + "strings" +) + +type UserInfo struct { + KeepSession +} + +func (c *UserInfo) ShowModifyUserInfoUI() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + ranMd5 := encrypt.EncodeMd5([]byte(pubMethod.RandomString(46))) + c.Ctx.SetCookie(enum.UserCookie, ranMd5, enum.CookieExpireTime) + c.Ctx.SetSecureCookie(ranMd5, enum.UserCookie, ranMd5, enum.CookieExpireTime) + c.SetSession(enum.UserCookie, ranMd5) + + c.Data["userName"] = u.AgentName + c.TplName = "modify_userInfo.html" +} + +// 修改用户信息 +func (c *UserInfo) ModifyUserInfo() { + or_pwd := strings.TrimSpace(c.GetString("or_pwd")) + new_pwd := strings.TrimSpace(c.GetString("new_pwd")) + confirm_pwd := strings.TrimSpace(c.GetString("confirm_pwd")) + + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + var ( + msg = enum.FailedString + flag = enum.FailedFlag + + md bool + ud bool + pwdMd5 string + ) + + if or_pwd == "" || + new_pwd == "" || + confirm_pwd == "" { + msg = "密码不能为空!" + goto stopRun + } + + pwdMd5 = encrypt.EncodeMd5([]byte(or_pwd)) + if strings.Compare(strings.ToUpper(pwdMd5), u.AgentPassword) != 0 { + msg = "原始密码错误!" + } + + md, _ = regexp.MatchString(enum.PasswordReg, new_pwd) + if !md { + msg = "密码只能输入6-20个以字母开头、可带数字、“_”、“.”的字串!" + goto stopRun + } + + md, _ = regexp.MatchString(enum.PasswordReg, confirm_pwd) + if !md { + msg = "密码只能输入6-20个以字母开头、可带数字、“_”、“.”的字串!" + goto stopRun + } + + if strings.Compare(new_pwd, confirm_pwd) != 0 { + msg = "两次密码不匹配!" + goto stopRun + } + + u.AgentPassword = strings.ToUpper(encrypt.EncodeMd5([]byte(new_pwd))) + u.UpdateTime = pubMethod.GetNowTime() + ud = models.UpdateAgentInfo(u) + if ud { + msg = enum.SuccessString + flag = enum.SuccessFlag + + // 退出重新登录 + c.DelSession(enum.UserSession) + } + +stopRun: + c.Data["json"] = pubMethod.JsonFormat(flag, "", msg, "") + c.ServeJSON() + c.StopRun() +} + +// 验证原始密码 +func (c *UserInfo) ConfirmOriginPwd() { + ori := strings.TrimSpace(c.GetString("c")) + + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + var ( + msg = enum.FailedString + flag = enum.FailedFlag + ) + + pwdMd5 := encrypt.EncodeMd5([]byte(ori)) + if strings.Compare(strings.ToUpper(pwdMd5), u.AgentPassword) != 0 { + msg = "原始密码错误!" + } else { + flag = enum.SuccessFlag + } + + c.Data["json"] = pubMethod.JsonFormat(flag, "", msg, "") + c.ServeJSON() + c.StopRun() +} + +// 设置支付密码 +func (c *UserInfo) SetPayPassword() { + or_pwd := strings.TrimSpace(c.GetString("or_pwd")) + new_pwd := strings.TrimSpace(c.GetString("new_pwd")) + confirm_pwd := strings.TrimSpace(c.GetString("confirm_pwd")) + + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + var ( + msg = enum.FailedString + flag = enum.FailedFlag + + md bool + ud bool + pwdMd5 string + ) + + if new_pwd == "" || confirm_pwd == "" { + msg = "密码不能为空!" + goto stopRun + } + + if u.PayPassword != "" { + pwdMd5 = encrypt.EncodeMd5([]byte(or_pwd)) + if strings.Compare(strings.ToUpper(pwdMd5), u.AgentPassword) != 0 { + msg = "原始密码错误!" + } + } + + md, _ = regexp.MatchString(enum.PasswordReg, new_pwd) + if !md { + msg = "密码只能输入6-20个以字母开头、可带数字、“_”、“.”的字串!" + goto stopRun + } + + md, _ = regexp.MatchString(enum.PasswordReg, confirm_pwd) + if !md { + msg = "密码只能输入6-20个以字母开头、可带数字、“_”、“.”的字串!" + goto stopRun + } + + if strings.Compare(new_pwd, confirm_pwd) != 0 { + msg = "两次密码不匹配!" + goto stopRun + } + + u.PayPassword = strings.ToUpper(encrypt.EncodeMd5([]byte(new_pwd))) + u.UpdateTime = pubMethod.GetNowTime() + ud = models.UpdateAgentInfo(u) + if ud { + msg = enum.SuccessString + flag = enum.SuccessFlag + + // 重新写入缓存信息 + c.SetSession(enum.UserSession, u) + } + +stopRun: + c.Data["json"] = pubMethod.JsonFormat(flag, "", msg, "") + c.ServeJSON() + c.StopRun() +} + +// 验证原始支付密码 +func (c *UserInfo) ConfirmOriginPayPwd() { + ori := strings.TrimSpace(c.GetString("c")) + + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + var ( + msg = enum.FailedString + flag = enum.SuccessFlag + ) + + if u.PayPassword != "" { + pwdMd5 := encrypt.EncodeMd5([]byte(ori)) + if strings.Compare(strings.ToUpper(pwdMd5), u.AgentPassword) != 0 { + msg = "原始密码错误!" + flag = enum.FailedFlag + } + } + + c.Data["json"] = pubMethod.JsonFormat(flag, "", msg, "") + c.ServeJSON() + c.StopRun() +} + +// 展示用户信息 +func (c *UserInfo) ShowUserInfoUI() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + ranMd5 := encrypt.EncodeMd5([]byte(pubMethod.RandomString(46))) + c.Ctx.SetCookie(enum.UserCookie, ranMd5, enum.CookieExpireTime) + c.Ctx.SetSecureCookie(ranMd5, enum.UserCookie, ranMd5, enum.CookieExpireTime) + c.SetSession(enum.UserCookie, ranMd5) + + c.Data["userName"] = u.AgentName + c.TplName = "show_userInfo.html" +} + +// 代理商列表 +func (c *UserInfo) ShowMerchantUI() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + ranMd5 := encrypt.EncodeMd5([]byte(pubMethod.RandomString(46))) + c.Ctx.SetCookie(enum.UserCookie, ranMd5, enum.CookieExpireTime) + c.Ctx.SetSecureCookie(ranMd5, enum.UserCookie, ranMd5, enum.CookieExpireTime) + c.SetSession(enum.UserCookie, ranMd5) + + c.Data["payType"] = enum.GetPayType() + c.Data["status"] = enum.GetOrderStatus() + c.Data["userName"] = u.AgentName + c.TplName = "merchant.html" +} + +func (c *UserInfo) MerchantQueryAndListPage() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + mt := make(map[string]string) + mt["belong_agent_uid"] = u.AgentUid + mt["status"] = enum.ACTIVE + + // 该代理商下所有正常商户 + merchants := models.GetMerchantByParams(mt, -1, 0) + + type account struct { + UId string + MerchantName string // 商户名 + Mobile string // 手机号 + Balance float64 // 账户余额 + SettleAmount float64 // 已结算金额 + WaitAmount float64 // 待结算金额 + LoanAmount float64 // 押款金额 + FreezeAmount float64 // 账户冻结金额 + PayAmount float64 // 代付中金额 + } + + type deploy struct { + ChannelName string // 通道名 + PlatRate float64 // 平台费率 + AgentRate float64 // 代理商费率 + } + + mtd := make(map[string]string) + mtd["status"] = enum.ACTIVE + var ( + count = 0 // 计算该代理商下的商户有多少个通道 + accounts []account // 每个商户的账户信息 + ) + for _, m := range merchants { + mtd["merchant_uid"] = m.MerchantUid + lens := models.GetMerchantDeployLenByMap(mtd) + count += lens + + ac := models.GetAccountByUid(m.MerchantUid) + accounts = append(accounts, account{ + UId: m.MerchantUid, + MerchantName: m.MerchantName, + Mobile: m.LoginAccount, + Balance: ac.Balance, + SettleAmount: ac.SettleAmount, + WaitAmount: ac.WaitAmount, + LoanAmount: ac.LoanAmount, + FreezeAmount: ac.FreezeAmount, + PayAmount: ac.PayforAmount, + }) + } + + // 每个商户的通道信息 + deploys := make(map[string][]deploy) + if count != 0 { + for _, a := range accounts { + mtd["merchant_uid"] = a.UId + + mdl := models.GetMerchantDeployListByMap(mtd, -1, 0) + for _, m := range mdl { + road := models.GetRoadInfoByRoadUid(m.SingleRoadUid) + fee := road.BasicFee + m.SingleRoadPlatformRate + m.SingleRoadAgentRate + if fee < 0.00000001 { + fee = road.BasicFee + m.RollRoadPlatformRate + m.RollRoadAgentRate + } + afee := m.SingleRoadAgentRate + if afee < 0.00000001 { + afee = m.RollRoadAgentRate + } + deploys[a.UId] = append(deploys[a.UId], deploy{ + ChannelName: road.ProductName, + PlatRate: fee, + AgentRate: afee, + }) + } + } + } + + // 数据回显 + out := make(map[string]interface{}) + out["ac"] = accounts + out["dp"] = deploys + out["count"] = count + + c.Data["json"] = out + c.ServeJSON() + c.StopRun() +} diff --git a/agent/controllers/withdraw.go b/agent/controllers/withdraw.go new file mode 100644 index 0000000..81c1bae --- /dev/null +++ b/agent/controllers/withdraw.go @@ -0,0 +1,269 @@ +/*************************************************** + ** @Desc : This file for 代付申请和记录 + ** @Time : 19.12.4 10:50 + ** @Author : Joker + ** @File : withdraw + ** @Last Modified by : Joker + ** @Last Modified time: 19.12.4 10:50 + ** @Software: GoLand +****************************************************/ +package controllers + +import ( + "agent/common" + "agent/models" + "agent/sys/enum" + "agent/utils" + "fmt" + "github.com/rs/xid" + "regexp" + "strconv" + "strings" +) + +type Withdraw struct { + KeepSession +} + +func (c *Withdraw) ShowWithdrawUI() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + ranMd5 := encrypt.EncodeMd5([]byte(pubMethod.RandomString(46))) + c.Ctx.SetCookie(enum.UserCookie, ranMd5, enum.CookieExpireTime) + c.Ctx.SetSecureCookie(ranMd5, enum.UserCookie, ranMd5, enum.CookieExpireTime) + c.SetSession(enum.UserCookie, ranMd5) + + c.Data["bankInfo"] = enum.GetBankInfo() + c.Data["userName"] = u.AgentName + c.TplName = "withdraw/withdraw.html" +} + +// 获取账户提现余额 +func (c *Withdraw) UserBalance() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + ac := models.GetAccountByUid(u.AgentUid) + balance := ac.Balance + if balance < 0 { + balance = 0 + } + + out := make(map[string]interface{}) + out["fee"] = enum.SettlementFee + out["balance"] = fmt.Sprintf("%0.2f", balance) + + c.Data["json"] = out + c.ServeJSON() + c.StopRun() +} + +// 验证卡号和金额是否正确 +func verifyAccountAndMoney(bankCode, accountName, cardNo, bankAccountType, province, city, bankAccountAddress, moblieNo, amount string, ac models.AccountInfo) (b bool, msg string) { + if bankCode == "" || accountName == "" || cardNo == "" { + msg = "银行名、账户名或卡号不能为空!" + return false, msg + } + if moblieNo == "" || amount == "" { + msg = "手机号或金额不能为空!" + return false, msg + } + matched, _ := regexp.MatchString(enum.MobileReg, moblieNo) + if !matched { + msg = "请输入正确的手机号!" + return false, msg + } + matched, _ = regexp.MatchString(enum.MoneyReg, amount) + if !matched { + msg = "请输入正确的金额!" + return false, msg + } + f, err := strconv.ParseFloat(amount, 10) + if err != nil { + msg = "请输入正确的金额!" + return false, msg + } + + if strings.Compare(enum.PublicAccount, bankAccountType) == 0 { + if province == "" || city == "" || bankAccountAddress == "" { + msg = "开户行全称、所在省份或所在城市不能为空!" + return false, msg + } + } + + if f > enum.WithdrawalMaxAmount || f < enum.WithdrawalMinAmount || f+enum.SettlementFee > ac.WaitAmount { + utils.LogInfo(fmt.Sprintf("提现金额超出限制,提现金额:%f,账户可结算余额:%f,提现最小额:%d,最大额:%d,手续费:%d", + f, ac.WaitAmount, enum.WithdrawalMinAmount, enum.WithdrawalMaxAmount, enum.SettlementFee)) + msg = "提现金额超出限制!" + return false, msg + } + + if f+enum.SettlementFee > ac.Balance || ac.Balance <= 0 { + utils.LogInfo(fmt.Sprintf("账户金额不足,提现金额:%f,账户余额:%f,手续费:%d", + f, ac.Balance, enum.SettlementFee)) + msg = "账户可用金额不足!" + return false, msg + } + // 由于没有发生错误,必须把msg重置为初始值,而不是空值 + return true, enum.FailedToAdmin +} + +// 单笔提现申请 +func (c *Withdraw) LaunchSingleWithdraw() { + bankCode := strings.TrimSpace(c.GetString("bankCode")) + accountName := strings.TrimSpace(c.GetString("accountName")) + cardNo := strings.TrimSpace(c.GetString("cardNo")) + bankAccountType := strings.TrimSpace(c.GetString("bankAccountType")) + province := strings.TrimSpace(c.GetString("province")) + city := strings.TrimSpace(c.GetString("city")) + bankAccountAddress := strings.TrimSpace(c.GetString("bankAccountAddress")) + moblieNo := strings.TrimSpace(c.GetString("moblieNo")) + money := strings.TrimSpace(c.GetString("amount")) + mobileCode := strings.TrimSpace(c.GetString("smsVerifyCode")) + + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + var ( + msg = enum.FailedString + flag = enum.FailedFlag + + matched bool + + amount float64 + + ac models.AccountInfo + sett models.PayforInfo + url string + ) + + if u.PayPassword == "" { + msg = "请设置支付密码!" + goto stopRun + } + if strings.Compare(strings.ToUpper(encrypt.EncodeMd5([]byte(mobileCode))), u.PayPassword) != 0 { + msg = "支付密码输入错误!" + goto stopRun + } + + ac = models.GetAccountByUid(u.AgentUid) + matched, msg = verifyAccountAndMoney(bankCode, accountName, cardNo, bankAccountType, province, city, + bankAccountAddress, moblieNo, money, ac) + if !matched { + goto stopRun + } + + u = models.GetAgentInfoByAgentUid(u.AgentUid) + if strings.Compare(enum.ACTIVE, u.Status) != 0 { + msg = "账户状态异常,请联系管理人员!" + goto stopRun + } + + amount, _ = strconv.ParseFloat(money, 10) + sett = models.PayforInfo{ + PayforUid: "pppp" + xid.New().String(), + MerchantUid: u.AgentUid, + MerchantName: u.AgentName, + PhoneNo: u.AgentPhone, + MerchantOrderId: xid.New().String(), + BankOrderId: "4444" + xid.New().String(), + PayforFee: common.PAYFOR_FEE, + Type: common.SELF_MERCHANT, + PayforAmount: amount, + PayforTotalAmount: amount + common.PAYFOR_FEE, + BankCode: bankCode, + BankName: enum.GetBankInfo()[bankCode], + IsSend: common.NO, + BankAccountName: accountName, + BankAccountNo: cardNo, + BankAccountType: bankAccountType, + BankAccountAddress: province + city + bankAccountAddress, + Status: common.PAYFOR_COMFRIM, + CreateTime: pubMethod.GetNowTime(), + UpdateTime: pubMethod.GetNowTime(), + } + + matched = models.InsertPayfor(sett) + if matched { + flag = enum.SuccessFlag + msg = "提交成功,等待审核中,请在结算信息中查询状态!" + url = "/withdraw/show_list_ui" + } + +stopRun: + c.Data["json"] = pubMethod.JsonFormat(flag, "", msg, url) + c.ServeJSON() + c.StopRun() +} + +// 提现列表 +func (c *Withdraw) ShowListUI() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + ranMd5 := encrypt.EncodeMd5([]byte(pubMethod.RandomString(46))) + c.Ctx.SetCookie(enum.UserCookie, ranMd5, enum.CookieExpireTime) + c.Ctx.SetSecureCookie(ranMd5, enum.UserCookie, ranMd5, enum.CookieExpireTime) + c.SetSession(enum.UserCookie, ranMd5) + + c.Data["payType"] = enum.GetSettlementStatus() + c.Data["userName"] = u.AgentName + c.TplName = "withdraw/withdraw_record.html" +} + +func (c *Withdraw) WithdrawQueryAndListPage() { + us := c.GetSession(enum.UserSession) + u := us.(models.AgentInfo) + + // 分页参数 + page, _ := strconv.Atoi(c.GetString("page")) + limit, _ := strconv.Atoi(c.GetString("limit")) + if limit == 0 { + limit = 15 + } + + // 查询参数 + in := make(map[string]string) + merchantNo := strings.TrimSpace(c.GetString("MerchantNo")) + bankNo := strings.TrimSpace(c.GetString("BankNo")) + start := strings.TrimSpace(c.GetString("start")) + end := strings.TrimSpace(c.GetString("end")) + status := strings.TrimSpace(c.GetString("status")) + + in["bank_order_id"] = bankNo + in["merchant_order_id"] = merchantNo + in["status"] = status + in["merchant_uid"] = u.AgentUid + + if start != "" { + in["create_time__gte"] = start + } + if end != "" { + in["create_time__lte"] = end + } + + // 计算分页数 + count := models.GetPayForLenByMap(in) + totalPage := count / limit // 计算总页数 + if count%limit != 0 { // 不满一页的数据按一页计算 + totalPage++ + } + + // 数据获取 + var list []models.PayforInfo + if page <= totalPage { + list = models.GetPayForByMap(in, limit, (page-1)*limit) + } + + // 数据回显 + out := make(map[string]interface{}) + out["limit"] = limit // 分页数据 + out["page"] = page + out["totalPage"] = totalPage + out["root"] = list // 显示数据 + + c.Data["json"] = out + c.ServeJSON() + c.StopRun() +} diff --git a/agent/go.mod b/agent/go.mod new file mode 100644 index 0000000..f544310 --- /dev/null +++ b/agent/go.mod @@ -0,0 +1,13 @@ +module agent + +go 1.13 + +require github.com/beego/beego/v2 v2.0.1 + +require ( + github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f + github.com/go-sql-driver/mysql v1.5.0 + github.com/rs/xid v1.3.0 + github.com/smartystreets/goconvey v1.6.4 + github.com/tealeg/xlsx v1.0.5 +) diff --git a/agent/go.sum b/agent/go.sum new file mode 100644 index 0000000..6572247 --- /dev/null +++ b/agent/go.sum @@ -0,0 +1,289 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= +github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk= +github.com/astaxie/beego v1.12.3 h1:SAQkdD2ePye+v8Gn1r4X6IKZM1wd28EyUOVQ3PDSOOQ= +github.com/astaxie/beego v1.12.3/go.mod h1:p3qIm0Ryx7zeBHLljmd7omloyca1s4yu1a8kM1FkpIA= +github.com/beego/beego/v2 v2.0.1 h1:07a7Z0Ok5vbqyqh+q53sDPl9LdhKh0ZDy3gbyGrhFnE= +github.com/beego/beego/v2 v2.0.1/go.mod h1:8zyHi1FnWO1mZLwTn62aKRIZF/aIKvkCBB2JYs+eqQI= +github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ= +github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60= +github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80= +github.com/coreos/etcd v3.3.25+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U= +github.com/couchbase/gomemcached v0.0.0-20200526233749-ec430f949808/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c= +github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs= +github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f h1:q/DpyjJjZs94bziQ7YkBmIlpqbVP7yw179rnzoNVX1M= +github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f/go.mod h1:QGrK8vMWWHQYQ3QU9bw9Y9OPNfxccGzfb41qjvVeXtY= +github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/elastic/go-elasticsearch/v6 v6.8.5/go.mod h1:UwaDJsD3rWLM5rKNFzv9hgox93HoX8utj1kxD9aFUcI= +github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk= +github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-redis/redis/v7 v7.4.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg= +github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6/go.mod h1:n931TsDuKuq+uX4v1fulaMbA/7ZLLhjc85h7chZGBCQ= +github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= +github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8= +github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +github.com/peterh/liner v1.0.1-0.20171122030339-3681c2a91233/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.7.0 h1:wCi7urQOGBsYcQROHqpUUX4ct84xp40t9R9JX0FuA/U= +github.com/prometheus/client_golang v1.7.0/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4= +github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 h1:X+yvsM2yrEktyI+b2qND5gpH8YhURn0k8OCaeRnkINo= +github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg= +github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw= +github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKzU3qCuvj/tPnimWSsZZzvk9qvkvrIL5naVBPh5s= +github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= +github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= +github.com/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE= +github.com/tealeg/xlsx v1.0.5/go.mod h1:btRS8dz54TDnvKNosuAqxrM1QgN1udgk9O34bDCnORM= +github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= +github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU= +go.etcd.io/etcd v3.3.25+incompatible/go.mod h1:yaeTdrJi5lOmYerz05bd8+V7KubZs8YSFZfzsF9A6aI= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58 h1:1Bs6RVeBFtLZ8Yi1Hk07DiOqzvwLD/4hln4iahvFlag= +golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.5/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= diff --git a/agent/lastupdate.tmp b/agent/lastupdate.tmp new file mode 100644 index 0000000..d2a7bbd --- /dev/null +++ b/agent/lastupdate.tmp @@ -0,0 +1 @@ +{"/mnt/c/go-product/dongfeng/agent/controllers":1619338081249997400} \ No newline at end of file diff --git a/agent/main.go b/agent/main.go new file mode 100644 index 0000000..1953d66 --- /dev/null +++ b/agent/main.go @@ -0,0 +1,13 @@ +package main + +import ( + _ "agent/models" + _ "agent/routers" + beego "github.com/beego/beego/v2/server/web" +) + +func main() { + beego.BConfig.WebConfig.Session.SessionOn = true + beego.Run() +} + diff --git a/agent/models/account.go b/agent/models/account.go new file mode 100644 index 0000000..770c85c --- /dev/null +++ b/agent/models/account.go @@ -0,0 +1,119 @@ +/*************************************************** + ** @Desc : This file for ... + ** @Time : 2019/10/16 11:11 + ** @Author : yuebin + ** @File : account + ** @Last Modified by : yuebin + ** @Last Modified time: 2019/10/16 11:11 + ** @Software: GoLand +****************************************************/ +package models + +import ( + "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/core/logs" +) + +type AccountInfo struct { + Id int + Status string + AccountUid string + AccountName string + Balance float64 //账户总余额 + SettleAmount float64 //已经结算的金额 + LoanAmount float64 //账户押款金额 + FreezeAmount float64 //账户冻结金额 + WaitAmount float64 //待结算资金 + PayforAmount float64 //代付在途金额 + //AbleBalance float64 //账户可用金额 + UpdateTime string + CreateTime string +} + +const ACCOUNT_INFO = "account_info" + +func InsetAcount(account AccountInfo) bool { + o := orm.NewOrm() + _, err := o.Insert(&account) + if err != nil { + logs.Error("insert account fail: ", err) + return false + } + return true +} + +func GetAccountByUid(accountUid string) AccountInfo { + o := orm.NewOrm() + var account AccountInfo + _, err := o.QueryTable(ACCOUNT_INFO).Filter("account_uid", accountUid).Limit(1).All(&account) + if err != nil { + logs.Error("get account by uid fail: ", err) + } + + return account +} + +func GetAccountLenByMap(params map[string]string) int { + o := orm.NewOrm() + qs := o.QueryTable(ACCOUNT_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + cnt, err := qs.Limit(-1).OrderBy("-update_time").Count() + if err != nil { + logs.Error("get account len by map fail: ", err) + } + return int(cnt) +} + +func GetAccountByMap(params map[string]string, displayCount, offset int) []AccountInfo { + o := orm.NewOrm() + var accountList []AccountInfo + qs := o.QueryTable(ACCOUNT_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + + _, err := qs.Limit(displayCount, offset).OrderBy("-update_time").All(&accountList) + if err != nil { + logs.Error("get account by map fail: ", err) + } + return accountList +} + +func GetAllAccount() []AccountInfo { + o := orm.NewOrm() + var accountList []AccountInfo + + _, err := o.QueryTable(ACCOUNT_INFO).Limit(-1).All(&accountList) + + if err != nil { + logs.Error("get all account fail: ", err) + } + + return accountList +} + +func UpdateAccount(account AccountInfo) bool { + o := orm.NewOrm() + _, err := o.Update(&account) + if err != nil { + logs.Error("update account fail: ", err) + return false + } + return true +} + +func DeleteAccountByUid(accountUid string) bool { + o := orm.NewOrm() + _, err := o.QueryTable(ACCOUNT_INFO).Filter("account_uid", accountUid).Delete() + if err != nil { + logs.Error("delete account fail: ", err) + return false + } + return true +} diff --git a/agent/models/account_history_info.go b/agent/models/account_history_info.go new file mode 100644 index 0000000..abb630f --- /dev/null +++ b/agent/models/account_history_info.go @@ -0,0 +1,69 @@ +/*************************************************** + ** @Desc : This file for ... + ** @Time : 2019/10/19 14:56 + ** @Author : yuebin + ** @File : account_history_info + ** @Last Modified by : yuebin + ** @Last Modified time: 2019/10/19 14:56 + ** @Software: GoLand +****************************************************/ +package models + +import ( + "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/core/logs" +) + +type AccountHistoryInfo struct { + Id int + AccountUid string + AccountName string + Type string + Amount float64 + Balance float64 + UpdateTime string + CreateTime string +} + +const ACCOUNT_HISTORY_INFO = "account_history_info" + +func InsertAccountHistory(accountHistory AccountHistoryInfo) bool { + o := orm.NewOrm() + _, err := o.Insert(accountHistory) + if err != nil { + logs.Error("insert account history fail: ", err) + return false + } + return true +} + +func GetAccountHistoryLenByMap(params map[string]string) int { + o := orm.NewOrm() + qs := o.QueryTable(ACCOUNT_HISTORY_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + cnt, err := qs.Limit(-1).Count() + if err != nil { + logs.Error("get account history len by map fail: ", err) + } + return int(cnt) +} + +func GetAccountHistoryByMap(params map[string]string, displayCount, offset int) []AccountHistoryInfo { + o := orm.NewOrm() + qs := o.QueryTable(ACCOUNT_HISTORY_INFO) + var accountHistoryList []AccountHistoryInfo + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + _, err := qs.Limit(displayCount, offset).OrderBy("-update_time").All(&accountHistoryList) + if err != nil { + logs.Error("get account history by map fail: ", err) + } + return accountHistoryList +} diff --git a/agent/models/agent_info.go b/agent/models/agent_info.go new file mode 100644 index 0000000..2c43f1e --- /dev/null +++ b/agent/models/agent_info.go @@ -0,0 +1,162 @@ +/*************************************************** + ** @Desc : This file for ... + ** @Time : 2019/9/19 14:41 + ** @Author : yuebin + ** @File : agent_info + ** @Last Modified by : yuebin + ** @Last Modified time: 2019/9/19 14:41 + ** @Software: GoLand +****************************************************/ +package models + +import ( + "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/core/logs" +) + +type AgentInfo struct { + Id int + Status string + AgentName string + AgentPassword string + PayPassword string + AgentRemark string + AgentUid string + AgentPhone string + UpdateTime string + CreateTime string +} + +const AGENT_INFO = "agent_info" + +func IsEixstByAgentName(agentName string) bool { + o := orm.NewOrm() + exist := o.QueryTable(AGENT_INFO).Filter("agent_name", agentName).Exist() + + return exist +} + +func IsExistByAgentUid(uid string) bool { + o := orm.NewOrm() + exist := o.QueryTable(AGENT_INFO).Filter("agent_uid", uid).Exist() + + return exist +} + +func IsEixstByAgentPhone(agentPhone string) bool { + o := orm.NewOrm() + exist := o.QueryTable(AGENT_INFO).Filter("agent_phone", agentPhone).Exist() + return exist +} + +func InsertAgentInfo(agentInfo AgentInfo) bool { + o := orm.NewOrm() + _, err := o.Insert(&agentInfo) + if err != nil { + logs.Error("insert agent info fail: ", err) + return false + } + + return true +} + +func GetAgentInfoByAgentUid(agentUid string) AgentInfo { + o := orm.NewOrm() + var agentInfo AgentInfo + _, err := o.QueryTable(AGENT_INFO).Filter("agent_uid", agentUid).Limit(1).All(&agentInfo) + + if err != nil { + logs.Error("get agent info by agentUid fail: ", err) + } + + return agentInfo +} + +func GetAgentInfoByPhone(phone string) AgentInfo { + o := orm.NewOrm() + var agentInfo AgentInfo + _, err := o.QueryTable(AGENT_INFO).Filter("agent_phone", phone).Limit(1).All(&agentInfo) + + if err != nil { + logs.Error("get agent info by phone fail: ", err) + } + + return agentInfo +} + +func GetAgentInfoLenByMap(params map[string]string) int { + o := orm.NewOrm() + qs := o.QueryTable(AGENT_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + cnt, err := qs.Limit(-1).Count() + if err != nil { + logs.Error("get agentinfo len by map fail: ", err) + } + + return int(cnt) +} + +func GetAgentInfoByMap(params map[string]string, displayCount, offset int) []AgentInfo { + o := orm.NewOrm() + var agentInfoList []AgentInfo + + qs := o.QueryTable(AGENT_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + + _, err := qs.Limit(displayCount, offset).OrderBy("-update_time").All(&agentInfoList) + + if err != nil { + logs.Error("get agentInfo by map fail: ", err) + } + + return agentInfoList +} + +func GetAllAgentByMap(parmas map[string]string) []AgentInfo { + o := orm.NewOrm() + var agentList []AgentInfo + + qs := o.QueryTable(AGENT_INFO) + for k, v := range parmas { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + + _, err := qs.Limit(-1).All(&agentList) + if err != nil { + logs.Error("get all agent by map fail: ", err) + } + + return agentList +} + +func UpdateAgentInfo(agentInfo AgentInfo) bool { + o := orm.NewOrm() + _, err := o.Update(&agentInfo) + + if err != nil { + logs.Error("update agentinfo fail: ", err) + return false + } + + return true +} + +func DeleteAgentByAgentUid(agentUid string) bool { + o := orm.NewOrm() + _, err := o.QueryTable(AGENT_INFO).Filter("agent_uid", agentUid).Delete() + if err != nil { + logs.Error("delete agent by agent uid fail: ", err) + return false + } + return true +} diff --git a/service/models/agent_profit.go b/agent/models/agent_profit.go similarity index 100% rename from service/models/agent_profit.go rename to agent/models/agent_profit.go diff --git a/agent/models/bank_card_info.go b/agent/models/bank_card_info.go new file mode 100644 index 0000000..ff881ea --- /dev/null +++ b/agent/models/bank_card_info.go @@ -0,0 +1,106 @@ +/*************************************************** + ** @Desc : This file for ... + ** @Time : 2019/9/6 10:19 + ** @Author : yuebin + ** @File : bank_card_info + ** @Last Modified by : yuebin + ** @Last Modified time: 2019/9/6 10:19 + ** @Software: GoLand +****************************************************/ +package models + +import ( + "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/core/logs" +) + +type BankCardInfo struct { + Id int + Uid string + UserName string + BankName string + BankCode string + BankAccountType string + AccountName string + BankNo string + IdentifyCard string + CertificateNo string + PhoneNo string + BankAddress string + UpdateTime string + CreateTime string +} + +const BANK_CARD_INFO = "bank_card_info" + +func InsertBankCardInfo(bankCardInfo BankCardInfo) bool { + o := orm.NewOrm() + _, err := o.Insert(&bankCardInfo) + + if err != nil { + logs.Error("insert bank card info fail: ", err) + return false + } + return true +} + +func GetBankCardLenByMap(params map[string]string) int { + o := orm.NewOrm() + qs := o.QueryTable(BANK_CARD_INFO) + for k, v := range params { + qs = qs.Filter(k, v) + } + cnt, err := qs.Limit(-1).Count() + if err != nil { + logs.Error("get bank card len by map fail: ", err) + } + return int(cnt) +} + +func GetBankCardByMap(params map[string]string, displayCount, offset int) []BankCardInfo { + o := orm.NewOrm() + var bankCardList []BankCardInfo + qs := o.QueryTable(BANK_CARD_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + _, err := qs.Limit(displayCount, offset).OrderBy("-update_time").All(&bankCardList) + if err != nil { + logs.Error("get bank card by map fail: ", err) + } + return bankCardList +} + +func GetBankCardByUid(uid string) BankCardInfo { + o := orm.NewOrm() + var bankCardInfo BankCardInfo + _, err := o.QueryTable(bankCardInfo).Filter("uid", uid).Limit(1).All(&bankCardInfo) + if err != nil { + logs.Error("get bank card by uid fail: ", err) + } + + return bankCardInfo +} + +func DeleteBankCardByUid(uid string) bool { + o := orm.NewOrm() + _, err := o.QueryTable(BANK_CARD_INFO).Filter("uid", uid).Delete() + + if err != nil { + logs.Error("delete bank card by uid fail: ", err) + return false + } + return true +} + +func UpdateBankCard(bankCard BankCardInfo) bool { + o := orm.NewOrm() + _, err := o.Update(&bankCard) + if err != nil { + logs.Error("update bank card fail: ", err) + return false + } + return true +} diff --git a/agent/models/init.go b/agent/models/init.go new file mode 100644 index 0000000..2cf07bd --- /dev/null +++ b/agent/models/init.go @@ -0,0 +1,39 @@ +/*************************************************** + ** @Desc : This file for ... + ** @Time : 2019/8/9 13:48 + ** @Author : yuebin + ** @File : init + ** @Last Modified by : yuebin + ** @Last Modified time: 2019/8/9 13:48 + ** @Software: GoLand +****************************************************/ +package models + +import ( + "agent/conf" + "fmt" + "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/core/logs" + _ "github.com/go-sql-driver/mysql" +) + +func init() { + dbHost := conf.DB_HOST + dbUser := conf.DB_USER + dbPassword := conf.DB_PASSWORD + dbBase := conf.DB_BASE + dbPort := conf.DB_PORT + + link := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8", dbUser, dbPassword, dbHost, dbPort, dbBase) + + logs.Info("mysql init.....", link) + + orm.RegisterDriver("mysql", orm.DRMySQL) + orm.RegisterDataBase("default", "mysql", link) + orm.RegisterModel(new(UserInfo), new(MenuInfo), new(SecondMenuInfo), + new(PowerInfo), new(RoleInfo), new(BankCardInfo), new(RoadInfo), + new(RoadPoolInfo), new(AgentInfo), new(MerchantInfo), new(MerchantDeployInfo), + new(AccountInfo), new(AccountHistoryInfo), new(OrderInfo), new(OrderProfitInfo), + new(OrderSettleInfo), new(NotifyInfo), new(MerchantLoadInfo), + new(PayforInfo)) +} diff --git a/agent/models/menu_info.go b/agent/models/menu_info.go new file mode 100644 index 0000000..e974db5 --- /dev/null +++ b/agent/models/menu_info.go @@ -0,0 +1,179 @@ +/*************************************************** + ** @Desc : This file for ... + ** @Time : 2019/8/21 9:33 + ** @Author : yuebin + ** @File : menu_info + ** @Last Modified by : yuebin + ** @Last Modified time: 2019/8/21 9:33 + ** @Software: GoLand +****************************************************/ +package models + +import ( + "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/core/logs" +) + +type MenuInfo struct { + Id int + MenuOrder int + MenuUid string + FirstMenu string + SecondMenu string + Creater string + Status string + CreateTime string + UpdateTime string +} + +//实现排序的三个接口函数 +type MenuInfoSlice []MenuInfo + +func (m MenuInfoSlice) Len() int { + return len(m) +} + +func (m MenuInfoSlice) Swap(i, j int) { + m[i], m[j] = m[j], m[i] +} + +func (m MenuInfoSlice) Less(i, j int) bool { + return m[i].MenuOrder < m[j].MenuOrder //从小到大排序 +} + +const MENUINFO = "menu_info" + +func InsertMenu(menuInfo MenuInfo) bool { + o := orm.NewOrm() + _, err := o.Insert(&menuInfo) + if err != nil { + logs.Error("insert new menu info fail:", err) + return false + } + return true +} + +func FirstMenuIsExists(firstMenu string) bool { + o := orm.NewOrm() + exist := o.QueryTable(MENUINFO).Filter("first_menu", firstMenu).Exist() + return exist +} + +func FirstMenuUidIsExists(firstMenUid string) bool { + o := orm.NewOrm() + exist := o.QueryTable(MENUINFO).Filter("menu_uid", firstMenUid).Exist() + return exist +} + +func MenuOrderIsExists(menuOrder int) bool { + o := orm.NewOrm() + exist := o.QueryTable(MENUINFO).Filter("menu_order", menuOrder).Exist() + return exist +} + +func GetMenuLen() int { + o := orm.NewOrm() + cnt, err := o.QueryTable(MENUINFO).Count() + if err != nil { + logs.Error("get menu info len length fail: ", err) + } + return int(cnt) +} + +func GetMenuInfoByMenuUid(menuUid string) MenuInfo { + o := orm.NewOrm() + var menuInfo MenuInfo + _, err := o.QueryTable(MENUINFO).Filter("menu_uid", menuUid).Limit(1).All(&menuInfo) + if err != nil { + logs.Error("get menu info by menuUid fail: ", err) + } + return menuInfo +} + +func GetMenuInfosByMenuUids(menuUids []string) []MenuInfo { + menuInfoList := make([]MenuInfo, 0) + for _, v := range menuUids { + m := GetMenuInfoByMenuUid(v) + menuInfoList = append(menuInfoList, m) + } + return menuInfoList +} + +func GetMenuInfoByMenuOrder(menuOrder int) MenuInfo { + o := orm.NewOrm() + var menuInfo MenuInfo + _, err := o.QueryTable(MENUINFO).Filter("menu_order", menuOrder).Limit(1).All(&menuInfo) + if err != nil { + logs.Error("get menu info by menu order fail: ", err) + } + return menuInfo +} + +func GetMenuAll() []MenuInfo { + o := orm.NewOrm() + var menuInfoList []MenuInfo + _, err := o.QueryTable(MENUINFO).OrderBy("-update_time").All(&menuInfoList) + if err != nil { + logs.Error("get all menu list fail:", err) + } + return menuInfoList +} + +func GetMenuOffset(displayCount, offset int) []MenuInfo { + o := orm.NewOrm() + var menuInfoList []MenuInfo + _, err := o.QueryTable(MENUINFO).Limit(displayCount, offset).All(&menuInfoList) + if err != nil { + logs.Error("get menu offset fail: ", err) + } + return menuInfoList +} + +func GetMenuOffsetByMap(params map[string]string, displayCount, offset int) []MenuInfo { + o := orm.NewOrm() + var menuInfoList []MenuInfo + qs := o.QueryTable(MENUINFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + _, err := qs.Limit(displayCount, offset).OrderBy("-update_time").All(&menuInfoList) + if err != nil { + logs.Error("get menu offset by map fail: ", err) + } + return menuInfoList +} + +func GetMenuLenByMap(params map[string]string) int { + o := orm.NewOrm() + qs := o.QueryTable(MENUINFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + cnt, err := qs.Count() + if err != nil { + logs.Error("get menu len by map fail: ", err) + } + return int(cnt) +} + +func UpdateMenuInfo(menuInfo MenuInfo) { + o := orm.NewOrm() + cnt, err := o.Update(&menuInfo) + if err != nil { + logs.Error("update menu info fail: ", err) + } + logs.Info("update menu info success, num: ", cnt) +} + +func DeleteMenuInfo(menuUid string) { + o := orm.NewOrm() + cnt, err := o.QueryTable(MENUINFO).Filter("menu_uid", menuUid).Delete() + if err != nil { + logs.Error("delete menu info fail: ", err) + } + logs.Info("delete menu info num: ", cnt) +} diff --git a/agent/models/merchant_deploy_info.go b/agent/models/merchant_deploy_info.go new file mode 100644 index 0000000..e8fa6da --- /dev/null +++ b/agent/models/merchant_deploy_info.go @@ -0,0 +1,135 @@ +/*************************************************** + ** @Desc : This file for ... + ** @Time : 2019/10/7 11:52 + ** @Author : yuebin + ** @File : merchant_deploy_info + ** @Last Modified by : yuebin + ** @Last Modified time: 2019/10/7 11:52 + ** @Software: GoLand +****************************************************/ +package models + +import ( + "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/core/logs" +) + +type MerchantDeployInfo struct { + Id int + Status string + MerchantUid string + PayType string + SingleRoadUid string + SingleRoadName string + SingleRoadPlatformRate float64 + SingleRoadAgentRate float64 + RollRoadCode string + RollRoadName string + RollRoadPlatformRate float64 + RollRoadAgentRate float64 + IsLoan string + LoanRate float64 + LoanDays int + UnfreezeHour int + WaitUnfreezeAmount float64 + LoanAmount float64 + UpdateTime string + CreateTime string +} + +const MERCHANT_DEPLOY_INFO = "merchant_deploy_info" + +func InsertMerchantDeployInfo(merchantDeployInfo MerchantDeployInfo) bool { + o := orm.NewOrm() + _, err := o.Insert(&merchantDeployInfo) + if err != nil { + logs.Error("insert merchant deploy info fail: ", err) + return false + } + return true +} + +func IsExistByUidAndPayType(uid, payType string) bool { + o := orm.NewOrm() + isEixst := o.QueryTable(MERCHANT_DEPLOY_INFO).Filter("merchant_uid", uid).Filter("pay_type", payType).Exist() + return isEixst +} + +func GetMerchantDeployByUidAndPayType(uid, payType string) MerchantDeployInfo { + o := orm.NewOrm() + var merchantDeployInfo MerchantDeployInfo + _, err := o.QueryTable(MERCHANT_DEPLOY_INFO).Filter("merchant_uid", uid).Filter("pay_type", payType).Limit(1).All(&merchantDeployInfo) + if err != nil { + logs.Error("get merchant deploy by uid and paytype fail:", err) + } + return merchantDeployInfo +} + +func GetMerchantDeployByUid(uid string) (ms []MerchantDeployInfo) { + o := orm.NewOrm() + _, err := o.QueryTable(MERCHANT_DEPLOY_INFO).Filter("merchant_uid", uid).All(&ms) + if err != nil { + logs.Error("get merchant deploy by uid fail:", err) + } + return ms +} + +func GetMerchantDeployByHour(hour int) []MerchantDeployInfo { + o := orm.NewOrm() + var merchantDeployList []MerchantDeployInfo + _, err := o.QueryTable(MERCHANT_DEPLOY_INFO).Filter("unfreeze_hour", hour).Filter("status", "active").Limit(-1).All(&merchantDeployList) + if err != nil { + logs.Error("get merchant deploy list fail: ", err) + } + + return merchantDeployList +} +func DeleteMerchantDeployByUidAndPayType(uid, payType string) bool { + o := orm.NewOrm() + _, err := o.QueryTable(MERCHANT_DEPLOY_INFO).Filter("merchant_uid", uid).Filter("pay_type", payType).Delete() + if err != nil { + logs.Error("delete merchant deploy by uid and payType fail: ", err) + return false + } + return true +} + +func UpdateMerchantDeploy(merchantDeploy MerchantDeployInfo) bool { + o := orm.NewOrm() + _, err := o.Update(&merchantDeploy) + if err != nil { + logs.Error("update merchant deploy fail: ", err) + return false + } + return true +} + +func GetMerchantDeployLenByMap(params map[string]string) int { + o := orm.NewOrm() + qs := o.QueryTable(MERCHANT_DEPLOY_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + cnt, err := qs.Count() + if err != nil { + logs.Error("get merchant deploy len by map fail: ", err) + } + return int(cnt) +} + +func GetMerchantDeployListByMap(params map[string]string, displayCount, offset int) (md []MerchantDeployInfo) { + o := orm.NewOrm() + qs := o.QueryTable(MERCHANT_DEPLOY_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + _, err := qs.Limit(displayCount, offset).OrderBy("-update_time").All(&md) + if err != nil { + logs.Error("get merchant deploy list by map fail: ", err) + } + return md +} diff --git a/agent/models/merchant_info.go b/agent/models/merchant_info.go new file mode 100644 index 0000000..2877ace --- /dev/null +++ b/agent/models/merchant_info.go @@ -0,0 +1,205 @@ +/*************************************************** + ** @Desc : This file for ... + ** @Time : 2019/9/28 16:47 + ** @Author : yuebin + ** @File : merchant_info + ** @Last Modified by : yuebin + ** @Last Modified time: 2019/9/28 16:47 + ** @Software: GoLand +****************************************************/ +package models + +import ( + "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/core/logs" +) + +type MerchantInfo struct { + Id int + Status string + BelongAgentUid string + BelongAgentName string + MerchantName string + MerchantUid string + MerchantKey string + MerchantSecret string + LoginPassword string + LoginAccount string + AutoSettle string + AutoPayFor string + WhiteIps string + Remark string + SinglePayForRoadUid string + SinglePayForRoadName string + RollPayForRoadCode string + RollPayForRoadName string + PayforFee float64 + UpdateTime string + CreateTime string +} + +const MERCHANT_INFO = "merchant_info" + +func IsExistByMerchantName(merchantName string) bool { + o := orm.NewOrm() + exist := o.QueryTable(MERCHANT_INFO).Filter("merchant_name", merchantName).Exist() + + return exist +} + +func IsExistByMerchantUid(uid string) bool { + o := orm.NewOrm() + exist := o.QueryTable(MERCHANT_INFO).Filter("merchant_uid", uid).Exist() + + return exist +} + +func IsExistMerchantByAgentUid(uid string) bool { + o := orm.NewOrm() + exist := o.QueryTable(MERCHANT_INFO).Filter("belong_agent_uid", uid).Exist() + + return exist +} + +func IsExistByMerchantPhone(phone string) bool { + o := orm.NewOrm() + exist := o.QueryTable(MERCHANT_INFO).Filter("LoginAccount", phone).Exist() + + return exist +} + +func GetMerchantByPhone(phone string) (m MerchantInfo) { + o := orm.NewOrm() + _, e := o.QueryTable(MERCHANT_INFO).Filter("LoginAccount", phone).Limit(1).All(&m) + if e != nil { + logs.Error("GetMerchantByPhone merchant fail: ", e) + } + return m +} + +func InsertMerchantInfo(merchantInfo MerchantInfo) bool { + o := orm.NewOrm() + _, err := o.Insert(&merchantInfo) + if err != nil { + logs.Error("insert merchant fail: ", err) + return false + } + return true +} + +func GetMerchantLenByMap(params map[string]string) int { + o := orm.NewOrm() + qs := o.QueryTable(MERCHANT_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + cnt, err := qs.Count() + if err != nil { + logs.Error("get merchant len by map fail: ", err) + } + return int(cnt) +} + +func GetMerchantListByMap(params map[string]string, displayCount, offset int) []MerchantInfo { + o := orm.NewOrm() + qs := o.QueryTable(MERCHANT_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + var merchantList []MerchantInfo + _, err := qs.Limit(displayCount, offset).OrderBy("-update_time").All(&merchantList) + if err != nil { + logs.Error("get merchant list by map fail: ", err) + } + return merchantList +} + +func GetAllMerchant() []MerchantInfo { + o := orm.NewOrm() + var merchantList []MerchantInfo + + _, err := o.QueryTable(MERCHANT_INFO).Limit(-1).All(&merchantList) + if err != nil { + logs.Error("get all merchant fail:", err) + } + + return merchantList +} + +func GetMerchantByParams(params map[string]string, displayCount, offset int) []MerchantInfo { + o := orm.NewOrm() + var merchantList []MerchantInfo + qs := o.QueryTable(MERCHANT_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + + qs.Limit(displayCount, offset).All(&merchantList) + + return merchantList +} + +func GetMerchantLenByParams(params map[string]string) int { + o := orm.NewOrm() + qs := o.QueryTable(MERCHANT_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + + cnt, err := qs.Limit(-1).Count() + + if err != nil { + logs.Error("get merchant len by params fail: ", err) + } + return int(cnt) +} + +func GetMerchantByUid(merchantUid string) MerchantInfo { + o := orm.NewOrm() + var merchantInfo MerchantInfo + _, err := o.QueryTable(MERCHANT_INFO).Filter("merchant_uid", merchantUid).Limit(1).All(&merchantInfo) + if err != nil { + logs.Error("get merchant info fail: ", err) + } + return merchantInfo +} + +func GetMerchantByPaykey(payKey string) MerchantInfo { + o := orm.NewOrm() + var merchantInfo MerchantInfo + _, err := o.QueryTable(MERCHANT_INFO).Filter("merchant_key", payKey).Limit(1).All(&merchantInfo) + if err != nil { + logs.Error("get merchant by merchantKey fail: ", err) + } + return merchantInfo +} + +func UpdateMerchant(merchantInfo MerchantInfo) bool { + o := orm.NewOrm() + _, err := o.Update(&merchantInfo) + + if err != nil { + logs.Error("update merchant fail: ", err) + return false + } + + return true +} + +func DeleteMerchantByUid(merchantUid string) bool { + o := orm.NewOrm() + _, err := o.QueryTable(MERCHANT_INFO).Filter("merchant_uid", merchantUid).Delete() + if err != nil { + logs.Error("delete merchant fail: ", err) + return false + } + return true +} diff --git a/agent/models/merchant_load_info.go b/agent/models/merchant_load_info.go new file mode 100644 index 0000000..8277c6f --- /dev/null +++ b/agent/models/merchant_load_info.go @@ -0,0 +1,56 @@ +/*************************************************** + ** @Desc : This file for ... + ** @Time : 2019/11/22 13:07 + ** @Author : yuebin + ** @File : merchant_load_info + ** @Last Modified by : yuebin + ** @Last Modified time: 2019/11/22 13:07 + ** @Software: GoLand +****************************************************/ +package models + +import ( + "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/core/logs" +) + +type MerchantLoadInfo struct { + Id int + Status string + MerchantUid string + RoadUid string + LoadDate string + LoadAmount float64 + UpdateTime string + CreateTime string +} + +const MERCHANT_LOAD_INFO = "merchant_load_info" + +func GetMerchantLoadInfoByMap(params map[string]string) []MerchantLoadInfo { + o := orm.NewOrm() + qs := o.QueryTable(MERCHANT_LOAD_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + var merchantLoadList []MerchantLoadInfo + _, err := qs.Limit(-11).All(&merchantLoadList) + if err != nil { + logs.Error("get merchant load info fail: ", err) + } + return merchantLoadList +} + +func IsExistMerchantLoadByParams(params map[string]string) bool { + o := orm.NewOrm() + qs := o.QueryTable(MERCHANT_LOAD_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + + return qs.Exist() +} diff --git a/agent/models/notify_info.go b/agent/models/notify_info.go new file mode 100644 index 0000000..d2bab17 --- /dev/null +++ b/agent/models/notify_info.go @@ -0,0 +1,103 @@ +/*************************************************** + ** @Desc : This file for ... + ** @Time : 2019/11/20 13:13 + ** @Author : yuebin + ** @File : notify_info + ** @Last Modified by : yuebin + ** @Last Modified time: 2019/11/20 13:13 + ** @Software: GoLand +****************************************************/ +package models + +import ( + "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/core/logs" +) + +type NotifyInfo struct { + Id int + Type string //订单-order,代付-payfor + BankOrderId string + MerchantOrderId string + Status string + Times int + Url string + Response string + UpdateTime string + CreateTime string +} + +const NOTIFYINFO = "notify_info" + +func InsertNotifyInfo(notifyInfo NotifyInfo) bool { + o := orm.NewOrm() + _, err := o.Insert(¬ifyInfo) + if err != nil { + logs.Error("insert notify fail:", err) + return false + } + return true +} + +func NotifyInfoExistByBankOrderId(bankOrderId string) bool { + o := orm.NewOrm() + exist := o.QueryTable(NOTIFYINFO).Filter("bank_order_id", bankOrderId).Exist() + return exist +} + +func GetNotifyInfoByBankOrderId(bankOrderId string) NotifyInfo { + o := orm.NewOrm() + var notifyInfo NotifyInfo + _, err := o.QueryTable(NOTIFYINFO).Filter("bank_order_id", bankOrderId).All(¬ifyInfo) + if err != nil { + logs.Error("get notify info by bankOrderId fail: ", err) + } + + return notifyInfo +} + +func GetNotifyInfosNotSuccess(params map[string]interface{}) []NotifyInfo { + o := orm.NewOrm() + var notifyInfoList []NotifyInfo + qs := o.QueryTable(NOTIFYINFO) + for k, v := range params { + qs = qs.Filter(k, v) + } + qs = qs.Exclude("status", "success") + _, err := qs.Limit(-1).All(¬ifyInfoList) + + if err != nil { + logs.Error("get notifyinfos fail: ", err) + } + + return notifyInfoList +} + +func GetNotifyBankOrderIdListByParams(params map[string]string) []string { + o := orm.NewOrm() + qs := o.QueryTable(NOTIFYINFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + + var notifyList []NotifyInfo + qs.Limit(-1).All(¬ifyList) + var list []string + for _, n := range notifyList { + list = append(list, n.BankOrderId) + } + + return list +} + +func UpdateNotifyInfo(notifyInfo NotifyInfo) bool { + o := orm.NewOrm() + _, err := o.Update(¬ifyInfo) + if err != nil { + logs.Error("update notify info fail: ", err) + return false + } + return true +} diff --git a/agent/models/order_info.go b/agent/models/order_info.go new file mode 100644 index 0000000..1a82ce0 --- /dev/null +++ b/agent/models/order_info.go @@ -0,0 +1,222 @@ +/*************************************************** + ** @Desc : This file for ... + ** @Time : 2019/10/28 10:15 + ** @Author : yuebin + ** @File : order_info + ** @Last Modified by : yuebin + ** @Last Modified time: 2019/10/28 10:15 + ** @Software: GoLand +****************************************************/ +package models + +import ( + "fmt" + "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/core/logs" + "strconv" +) + +type OrderInfo struct { + Id int + ShopName string //商品名称 + OrderPeriod string //订单有效时间 + MerchantOrderId string //商户订单id + BankOrderId string //本系统订单id + BankTransId string //上游流水id + OrderAmount float64 //订单提交的金额 + ShowAmount float64 //待支付的金额 + FactAmount float64 //用户实际支付金额 + RollPoolCode string //轮询池编码 + RollPoolName string //轮询池名臣 + RoadUid string //通道标识 + RoadName string //通道名称 + PayProductName string //上游支付公司的名称 + PayProductCode string //上游支付公司的编码代号 + PayTypeCode string //支付产品编码 + PayTypeName string //支付产品名称 + OsType string //操作系统类型 + Status string //订单支付状态 + Refund string //退款状态 + RefundTime string //退款操作时间 + Freeze string //冻结状态 + FreezeTime string //冻结时间 + Unfreeze string //是否已经解冻 + UnfreezeTime string //解冻时间 + ReturnUrl string //支付完跳转地址 + NotifyUrl string //下游回调地址 + MerchantUid string //商户id + MerchantName string //商户名称 + AgentUid string //该商户所属代理 + AgentName string //该商户所属代理名称 + UpdateTime string + CreateTime string +} + +const ORDER_INFO = "order_info" + +func InsertOrder(orderInfo OrderInfo) bool { + o := orm.NewOrm() + _, err := o.Insert(&orderInfo) + if err != nil { + logs.Error("insert order info fail: ", err) + return false + } + return true +} + +func OrderNoIsEixst(orderId string) bool { + o := orm.NewOrm() + exits := o.QueryTable(ORDER_INFO).Filter("merchant_order_id", orderId).Exist() + return exits +} + +func BankOrderIdIsEixst(bankOrderId string) bool { + o := orm.NewOrm() + exists := o.QueryTable(ORDER_INFO).Filter("bank_order_id", bankOrderId).Exist() + return exists +} + +func GetOrderLenByMap(params map[string]string) int { + o := orm.NewOrm() + qs := o.QueryTable(ORDER_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + cnt, _ := qs.Limit(-1).Count() + return int(cnt) +} + +func GetOrderByMap(params map[string]string, display, offset int) []OrderInfo { + o := orm.NewOrm() + var orderInfoList []OrderInfo + qs := o.QueryTable(ORDER_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + _, err := qs.Limit(display, offset).OrderBy("-update_time").All(&orderInfoList) + if err != nil { + logs.Error("get order by map fail: ", err) + } + return orderInfoList +} + +func GetSuccessRateByMap(params map[string]string) string { + o := orm.NewOrm() + qs := o.QueryTable(ORDER_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + + successRate := "0%" + allCount, _ := qs.Limit(-1).Count() + successCount, _ := qs.Filter("status", "success").Limit(-1).Count() + if allCount == 0 { + return successRate + } + tmp := float64(successCount) / float64(allCount) * 100 + successRate = fmt.Sprintf("%.1f", tmp) + return successRate + "%" +} + +func GetAllAmountByMap(params map[string]string) float64 { + o := orm.NewOrm() + condition := "select sum(order_amount) as allAmount from order_info " + for _, v := range params { + if len(v) > 0 { + condition = condition + "where " + break + } + } + flag := false + if params["create_time__gte"] != "" { + flag = true + condition = condition + " create_time >= '" + params["create_time__gte"] + "'" + } + if params["create_time__lte"] != "" { + if flag { + condition = condition + " and " + } + condition = condition + " create_time <= '" + params["create_time__lte"] + "'" + } + if params["merchant_name__icontains"] != "" { + if flag { + condition = condition + " and " + } + condition = condition + "merchant_name like %'" + params["merchant_name__icontains"] + "'% " + } + if params["merchant_order_id"] != "" { + if flag { + condition = condition + " and " + } + condition = condition + " merchant_order_id = '" + params["merchant_order_id"] + "'" + } + if params["bank_order_id"] != "" { + if flag { + condition = condition + " and " + } + condition = condition + " bank_order_id = '" + params["bank_order_id"] + "'" + } + if params["status"] != "" { + if flag { + condition = condition + " and " + } + condition = condition + "status = '" + params["status"] + "'" + } + if params["pay_product_code"] != "" { + if flag { + condition = condition + " and " + } + condition = condition + "pay_product_code = " + params["pay_product_code"] + "'" + } + if params["pay_type_code"] != "" { + if flag { + condition = condition + " and " + } + condition = condition + "pay_type_code = " + params["pay_type_code"] + } + logs.Info("get order amount str = ", condition) + var maps []orm.Params + allAmount := 0.00 + num, err := o.Raw(condition).Values(&maps) + if err == nil && num > 0 { + allAmount, _ = strconv.ParseFloat(maps[0]["allAmount"].(string), 64) + } + return allAmount +} + +func GetOrderByBankOrderId(bankOrderId string) OrderInfo { + o := orm.NewOrm() + var orderInfo OrderInfo + _, err := o.QueryTable(ORDER_INFO).Filter("bank_order_id", bankOrderId).Limit(1).All(&orderInfo) + if err != nil { + logs.Error("get order info by bankOrderId fail: ", err) + } + return orderInfo +} + +func GetOrderByMerchantOrderId(merchantOrderId string) OrderInfo { + o := orm.NewOrm() + var orderInfo OrderInfo + _, err := o.QueryTable(ORDER_INFO).Filter("merchant_order_id", merchantOrderId).Limit(1).All(&orderInfo) + if err != nil { + logs.Error("get order by merchant_order_id: ", err.Error()) + } + return orderInfo +} + +func GetOneOrder(bankOrderId string) OrderInfo { + o := orm.NewOrm() + var orderInfo OrderInfo + _, err := o.QueryTable(ORDER_INFO).Filter("bank_order_id", bankOrderId).Limit(1).All(&orderInfo) + if err != nil { + logs.Error("get one order fail: ", err) + } + + return orderInfo +} diff --git a/agent/models/order_profit_info.go b/agent/models/order_profit_info.go new file mode 100644 index 0000000..94e8559 --- /dev/null +++ b/agent/models/order_profit_info.go @@ -0,0 +1,119 @@ +/*************************************************** + ** @Desc : This file for ... + ** @Time : 2019/10/30 11:44 + ** @Author : yuebin + ** @File : order_profit_info + ** @Last Modified by : yuebin + ** @Last Modified time: 2019/10/30 11:44 + ** @Software: GoLand +****************************************************/ +package models + +import ( + "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/core/logs" + "strings" +) + +type OrderProfitInfo struct { + Id int + MerchantName string + MerchantUid string + AgentName string + AgentUid string + PayProductCode string + PayProductName string + PayTypeCode string + PayTypeName string + Status string + MerchantOrderId string + BankOrderId string + BankTransId string + OrderAmount float64 + ShowAmount float64 + FactAmount float64 + UserInAmount float64 + SupplierRate float64 + PlatformRate float64 + AgentRate float64 + AllProfit float64 + SupplierProfit float64 + PlatformProfit float64 + AgentProfit float64 + UpdateTime string + CreateTime string +} + +const ORDER_PROFIT_INFO = "order_profit_info" + +func GetOrderProfitByBankOrderId(bankOrderId string) OrderProfitInfo { + o := orm.NewOrm() + var orderProfit OrderProfitInfo + _, err := o.QueryTable(ORDER_PROFIT_INFO).Filter("bank_order_id", bankOrderId).Limit(1).All(&orderProfit) + if err != nil { + logs.Error("GetOrderProfitByBankOrderId fail:", err) + } + return orderProfit +} + +func GetOrderProfitLenByMap(params map[string]string) int { + o := orm.NewOrm() + qs := o.QueryTable(ORDER_PROFIT_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + cnt, _ := qs.Limit(-1).Count() + return int(cnt) +} + +func GetOrderProfitByMap(params map[string]string, display, offset int) []OrderProfitInfo { + o := orm.NewOrm() + var orderProfitInfoList []OrderProfitInfo + qs := o.QueryTable(ORDER_PROFIT_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + _, err := qs.Limit(display, offset).OrderBy("-update_time").All(&orderProfitInfoList) + if err != nil { + logs.Error("get order by map fail: ", err) + } + return orderProfitInfoList +} + +func GetPlatformProfitByMap(params map[string]string) []PlatformProfit { + + o := orm.NewOrm() + + cond := "select merchant_name, agent_name, pay_product_name as supplier_name, pay_type_name, sum(fact_amount) as order_amount, count(1) as order_count, " + + "sum(platform_profit) as platform_profit, sum(agent_profit) as agent_profit from " + ORDER_PROFIT_INFO + " where status='success' " + flag := false + for k, v := range params { + if len(v) > 0 { + if flag { + cond += " and" + } + if strings.Contains(k, "create_time__gte") { + cond = cond + " create_time>='" + v + "'" + } else if strings.Contains(k, "create_time__lte") { + cond = cond + " create_time<='" + v + "'" + } else { + cond = cond + " " + k + "='" + v + "'" + } + flag = true + } + } + + cond += " group by merchant_uid, agent_uid, pay_product_code, pay_type_code" + + var platformProfitList []PlatformProfit + _, err := o.Raw(cond).QueryRows(&platformProfitList) + if err != nil { + logs.Error("get platform profit by map fail:", err) + } + + return platformProfitList +} diff --git a/agent/models/order_settle_info.go b/agent/models/order_settle_info.go new file mode 100644 index 0000000..966477d --- /dev/null +++ b/agent/models/order_settle_info.go @@ -0,0 +1,51 @@ +/*************************************************** + ** @Desc : This file for ... + ** @Time : 2019/10/30 11:41 + ** @Author : yuebin + ** @File : order_settle_info + ** @Last Modified by : yuebin + ** @Last Modified time: 2019/10/30 11:41 + ** @Software: GoLand +****************************************************/ +package models + +import ( + "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/core/logs" +) + +type OrderSettleInfo struct { + Id int + PayProductCode string + PayProductName string + PayTypeCode string + RoadUid string + PayTypeName string + MerchantUid string + MerchantName string + MerchantOrderId string + BankOrderId string + SettleAmount float64 + IsAllowSettle string + IsCompleteSettle string + UpdateTime string + CreateTime string +} + +const ORDER_SETTLE_INFO = "order_settle_info" + +func GetOrderSettleListByParams(params map[string]string) []OrderSettleInfo { + o := orm.NewOrm() + qs := o.QueryTable(ORDER_SETTLE_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + var orderSettleList []OrderSettleInfo + if _, err := qs.Limit(-1).All(&orderSettleList); err != nil { + logs.Error("get order settle list fail: ", err) + } + + return orderSettleList +} diff --git a/agent/models/payfor_info.go b/agent/models/payfor_info.go new file mode 100644 index 0000000..32f0743 --- /dev/null +++ b/agent/models/payfor_info.go @@ -0,0 +1,227 @@ +/*************************************************** + ** @Desc : This file for ... + ** @Time : 2019/11/25 14:32 + ** @Author : yuebin + ** @File : payfor_info + ** @Last Modified by : yuebin + ** @Last Modified time: 2019/11/25 14:32 + ** @Software: GoLand +****************************************************/ +package models + +import ( + "agent/common" + "agent/utils" + "context" + "errors" + "fmt" + "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/core/logs" +) + +type PayforInfo struct { + Id int + PayforUid string + MerchantUid string + MerchantName string + MerchantOrderId string + BankOrderId string + BankTransId string + RoadUid string + RoadName string + RollPoolCode string + RollPoolName string + PayforFee float64 + PayforAmount float64 + PayforTotalAmount float64 + BankCode string + BankName string + BankAccountName string + BankAccountNo string + BankAccountType string + Country string + City string + Ares string + BankAccountAddress string + PhoneNo string + GiveType string + Type string + NotifyUrl string + Status string + IsSend string + RequestTime string + ResponseTime string + ResponseContext string + Remark string + CreateTime string + UpdateTime string +} + +const PAYFORINFO = "payfor_info" + +func InsertPayfor(payFor PayforInfo) bool { + o := orm.NewOrm() + _, err := o.Insert(&payFor) + if err != nil { + logs.Error("insert payfor fail: ", err) + return false + } + return true +} + +func IsExistPayForByBankOrderId(bankOrderId string) bool { + o := orm.NewOrm() + exist := o.QueryTable(PAYFORINFO).Filter("bank_order_id", bankOrderId).Exist() + + return exist +} + +func IsExistPayForByMerchantOrderId(merchantOrderId string) bool { + o := orm.NewOrm() + exist := o.QueryTable(PAYFORINFO).Filter("merchant_order_id", merchantOrderId).Exist() + + return exist +} + +func GetPayForLenByMap(params map[string]string) int { + o := orm.NewOrm() + qs := o.QueryTable(PAYFORINFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + + cnt, err := qs.Limit(-1).Count() + + if err != nil { + logs.Error("get pay for len by map fail: ", err) + } + + return int(cnt) +} + +func GetPayForByMap(params map[string]string, displayCount, offset int) []PayforInfo { + o := orm.NewOrm() + var payForList []PayforInfo + + qs := o.QueryTable(PAYFORINFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + + _, err := qs.Limit(displayCount, offset).OrderBy("-create_time").All(&payForList) + + if err != nil { + logs.Error("get agentInfo by map fail: ", err) + } + + return payForList +} + +func GetPayForListByParams(params map[string]string) []PayforInfo { + o := orm.NewOrm() + var payForList []PayforInfo + qs := o.QueryTable(PAYFORINFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + _, err := qs.Limit(-1).All(&payForList) + if err != nil { + logs.Error("GetPayForListByParams fail:", err) + } + return payForList +} + +func GetPayForByBankOrderId(bankOrderId string) PayforInfo { + o := orm.NewOrm() + var payFor PayforInfo + _, err := o.QueryTable(PAYFORINFO).Filter("bank_order_id", bankOrderId).Limit(1).All(&payFor) + + if err != nil { + logs.Error("get pay for by bank_order_id fail: ", err) + } + + return payFor +} + +func GetPayForByMerchantOrderId(merchantOrderId string) PayforInfo { + o := orm.NewOrm() + var payFor PayforInfo + + _, err := o.QueryTable(PAYFORINFO).Filter("merchant_order_id", merchantOrderId).Limit(1).All(&payFor) + + if err != nil { + logs.Error("fail: ", err) + } + + return payFor +} + +func ForUpdatePayFor(payFor PayforInfo) bool { + o := orm.NewOrm() + + if err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error { + + var tmp PayforInfo + if err := txOrm.Raw("select * from payfor_info where bank_order_id = ? for update", payFor.BankOrderId).QueryRow(&tmp); err != nil || tmp.PayforUid == "" { + logs.Error("for update payfor select fail:", err) + return err + } + + if tmp.Status == common.PAYFOR_FAIL || tmp.Status == common.PAYFOR_SUCCESS { + return errors.New("订单已经处理") + } + + //如果是手动打款,并且是需要处理商户金额 + if payFor.Status == common.PAYFOR_SOLVING && tmp.Status == common.PAYFOR_COMFRIM && + payFor.GiveType == common.PAYFOR_HAND && payFor.Type != common.SELF_HELP { + + var account AccountInfo + if err := txOrm.Raw("select * from account_info where account_uid = ? for update", payFor.MerchantUid).QueryRow(&account); err != nil || account.AccountUid == "" { + logs.Error("for update payfor select account info,fail:", err) + return err + } + //计算该用户的可用金额 + ableAmount := account.SettleAmount - account.FreezeAmount - account.PayforAmount - account.LoanAmount + if ableAmount >= payFor.PayforAmount+payFor.PayforFee { + account.PayforAmount += payFor.PayforFee + payFor.PayforAmount + account.UpdateTime = utils.GetBasicDateTime() + if _, err := txOrm.Update(&account); err != nil { + logs.Error("for update payfor update account fail:", err) + return err + } + } else { + logs.Error(fmt.Sprintf("商户uid=%s,可用金额不够", payFor.MerchantUid)) + payFor.ResponseContext = "商户可用余额不足" + payFor.Status = common.PAYFOR_FAIL + } + } + + if _, err := txOrm.Update(&payFor); err != nil { + logs.Error("for update payfor fail: ", err) + return err + } + + return nil + }); err != nil { + return false + } + return true +} + +func UpdatePayFor(payFor PayforInfo) bool { + o := orm.NewOrm() + _, err := o.Update(&payFor) + + if err != nil { + logs.Error("update pay for fail:", err) + return false + } + + return true +} diff --git a/service/models/platform_profit.go b/agent/models/platform_profit.go similarity index 100% rename from service/models/platform_profit.go rename to agent/models/platform_profit.go diff --git a/agent/models/power_info.go b/agent/models/power_info.go new file mode 100644 index 0000000..893a686 --- /dev/null +++ b/agent/models/power_info.go @@ -0,0 +1,143 @@ +/*************************************************** + ** @Desc : This file for ... + ** @Time : 2019/8/28 17:59 + ** @Author : yuebin + ** @File : power_info + ** @Last Modified by : yuebin + ** @Last Modified time: 2019/8/28 17:59 + ** @Software: GoLand +****************************************************/ +package models + +import ( + "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/core/logs" +) + +type PowerInfo struct { + Id int + FirstMenuUid string + SecondMenuUid string + SecondMenu string + PowerId string + PowerItem string + Creater string + Status string + CreateTime string + UpdateTime string +} + +const POWER_INFO = "power_info" + +type PowerInfoSlice []PowerInfo + +func (sm PowerInfoSlice) Len() int { + return len(sm) +} + +func (sm PowerInfoSlice) Swap(i, j int) { + sm[i], sm[j] = sm[j], sm[i] +} + +func (sm PowerInfoSlice) Less(i, j int) bool { + return sm[i].SecondMenuUid < sm[j].SecondMenuUid +} + +func PowerUidExists(powerUid string) bool { + o := orm.NewOrm() + exists := o.QueryTable(POWER_INFO).Filter("power_id", powerUid).Exist() + return exists +} + +func InsertPowerInfo(powerInfo PowerInfo) bool { + o := orm.NewOrm() + _, err := o.Insert(&powerInfo) + if err != nil { + logs.Error("insert power info fail: ", err) + return false + } + return true +} + +func GetPower() []PowerInfo { + o := orm.NewOrm() + var powerInfo []PowerInfo + _, err := o.QueryTable(POWER_INFO).Limit(-1).All(&powerInfo) + + if err != nil { + logs.Error("get power fail: ", err) + } + return powerInfo +} + +func GetPowerById(powerId string) PowerInfo { + o := orm.NewOrm() + var powerInfo PowerInfo + _, err := o.QueryTable(POWER_INFO).Filter("power_id", powerId).Limit(1).All(&powerInfo) + if err != nil { + logs.Error("get power by id fail: ", err) + } + return powerInfo +} + +func GetPowerByIds(powerIds []string) []PowerInfo { + var powerInfoList []PowerInfo + for _, v := range powerIds { + m := GetPowerById(v) + powerInfoList = append(powerInfoList, m) + } + return powerInfoList +} + +func GetPowerItemLenByMap(params map[string]string) int { + o := orm.NewOrm() + qs := o.QueryTable(POWER_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + cnt, err := qs.Limit(-1).Count() + if err != nil { + logs.Error("get power item len by map fail: ", err) + } + return int(cnt) +} + +func GetPowerItemByMap(params map[string]string, displpay, offset int) []PowerInfo { + o := orm.NewOrm() + var powerItemList []PowerInfo + qs := o.QueryTable(POWER_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + + _, err := qs.Limit(displpay, offset).OrderBy("-update_time").All(&powerItemList) + if err != nil { + logs.Error("get power item by map fail: ", err) + } + return powerItemList +} + +func DeletePowerItemByPowerID(powerID string) bool { + o := orm.NewOrm() + _, err := o.QueryTable(POWER_INFO).Filter("power_id", powerID).Delete() + if err != nil { + logs.Error("delete power item by powerID fail: ", err) + return false + } + return true +} + +func DeletePowerBySecondUid(secondUid string) bool { + o := orm.NewOrm() + _, err := o.QueryTable(POWER_INFO).Filter("second_menu_uid", secondUid).Delete() + + if err != nil { + logs.Error("delete power by second menu uid fail: ", err) + return false + } + return true +} diff --git a/agent/models/road_info.go b/agent/models/road_info.go new file mode 100644 index 0000000..10c6c6c --- /dev/null +++ b/agent/models/road_info.go @@ -0,0 +1,162 @@ +/*************************************************** + ** @Desc : This file for ... + ** @Time : 2019/9/8 12:09 + ** @Author : yuebin + ** @File : road_info + ** @Last Modified by : yuebin + ** @Last Modified time: 2019/9/8 12:09 + ** @Software: GoLand +****************************************************/ +package models + +import ( + "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/core/logs" +) + +type RoadInfo struct { + Id int + Status string + RoadName string + RoadUid string + Remark string + ProductName string + ProductUid string + PayType string + BasicFee float64 + SettleFee float64 + TotalLimit float64 + TodayLimit float64 + SingleMinLimit float64 + SingleMaxLimit float64 + StarHour int + EndHour int + Params string + TodayIncome float64 + TotalIncome float64 + TodayProfit float64 + TotalProfit float64 + Balance float64 + RequestAll int + RequestSuccess int + UpdateTime string + CreateTime string +} + +const ROAD_INFO = "road_info" + +func GetRoadInfoByRoadUid(roadUid string) RoadInfo { + o := orm.NewOrm() + var roadInfo RoadInfo + _, err := o.QueryTable(ROAD_INFO).Exclude("status", "delete").Filter("road_uid", roadUid).Limit(1).All(&roadInfo) + if err != nil { + logs.Error("get road info by road uid fail: ", err) + } + return roadInfo +} + +func GetRoadInfosByRoadUids(roadUids []string) []RoadInfo { + o := orm.NewOrm() + var roadInfoList []RoadInfo + _, err := o.QueryTable(ROAD_INFO).Filter("road_uid__in", roadUids).OrderBy("update_time").All(&roadInfoList) + if err != nil { + logs.Error("get roadInfos by roadUids fail: ", err) + } + return roadInfoList +} + +func GetRoadInfoByName(roadName string) RoadInfo { + o := orm.NewOrm() + var roadInfo RoadInfo + _, err := o.QueryTable(ROAD_INFO).Exclude("status", "delete").Filter("road_name", roadName).Limit(1).All(&roadInfo) + if err != nil { + logs.Error("get road info by name fail: ", err) + } + return roadInfo +} + +func GetRoadLenByMap(params map[string]string) int { + o := orm.NewOrm() + qs := o.QueryTable(ROAD_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + cnt, err := qs.Exclude("status", "delete").Limit(-1).Count() + if err != nil { + logs.Error("get road len by map fail: ", err) + } + return int(cnt) +} + +func GetRoadInfoByMap(params map[string]string, displayCount, offset int) []RoadInfo { + o := orm.NewOrm() + var roadInfoList []RoadInfo + qs := o.QueryTable(ROAD_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + + _, err := qs.Exclude("status", "delete").Limit(displayCount, offset).OrderBy("-update_time").All(&roadInfoList) + if err != nil { + logs.Error("get road info by map fail: ", err) + } + return roadInfoList +} + +func GetAllRoad(params map[string]string) []RoadInfo { + o := orm.NewOrm() + var roadInfoList []RoadInfo + qs := o.QueryTable(ROAD_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + _, err := qs.Limit(-1).All(&roadInfoList) + if err != nil { + logs.Error("get all road fail: ", err) + } + return roadInfoList +} + +func InsertRoadInfo(roadInfo RoadInfo) bool { + o := orm.NewOrm() + _, err := o.Insert(&roadInfo) + + if err != nil { + logs.Error("insert road info fail: ", err) + return false + } + return true +} + +func RoadInfoExistByRoadUid(roadUid string) bool { + o := orm.NewOrm() + exist := o.QueryTable(ROAD_INFO).Filter("status", "active").Filter("road_uid", roadUid).Exist() + + return exist +} + +func UpdateRoadInfo(roadInfo RoadInfo) bool { + o := orm.NewOrm() + _, err := o.Update(&roadInfo) + if err != nil { + logs.Error("update road info fail: ", err) + return false + } + return true +} + +func DeleteRoadByRoadUid(roadUid string) bool { + o := orm.NewOrm() + _, err := o.QueryTable(ROAD_INFO).Filter("road_uid", roadUid).Delete() + if err != nil { + logs.Error("delete road by road uid fail: ", err) + return false + } + return true +} diff --git a/agent/models/road_pool_info.go b/agent/models/road_pool_info.go new file mode 100644 index 0000000..0fdced9 --- /dev/null +++ b/agent/models/road_pool_info.go @@ -0,0 +1,127 @@ +/*************************************************** + ** @Desc : This file for ... + ** @Time : 2019/9/9 16:35 + ** @Author : yuebin + ** @File : road_pool_info + ** @Last Modified by : yuebin + ** @Last Modified time: 2019/9/9 16:35 + ** @Software: GoLand +****************************************************/ +package models + +import ( + "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/core/logs" +) + +type RoadPoolInfo struct { + Id int + Status string + RoadPoolName string + RoadPoolCode string + RoadUidPool string + UpdateTime string + CreateTime string +} + +const ROAD_POOL_INFO = "road_pool_info" + +func InsertRoadPool(roadPool RoadPoolInfo) bool { + o := orm.NewOrm() + _, err := o.Insert(&roadPool) + if err != nil { + logs.Error("insert road pool fail: ", err) + return false + } + return true +} + +func GetRoadPoolLenByMap(params map[string]string) int { + o := orm.NewOrm() + qs := o.QueryTable(ROAD_POOL_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + cnt, err := qs.Limit(-1).Count() + if err != nil { + logs.Error("get road pool len by map fail: ", err) + } + return int(cnt) +} + +func GetRoadPoolByMap(params map[string]string, displayCount, offset int) []RoadPoolInfo { + o := orm.NewOrm() + var roadPoolList []RoadPoolInfo + qs := o.QueryTable(ROAD_POOL_INFO) + for k, v := range params { + if len(v) > 0 { + qs.Filter(k, v) + } + } + _, err := qs.Limit(displayCount, offset).OrderBy("-update_time").All(&roadPoolList) + if err != nil { + logs.Error("get road pool by map fail: ", err) + } + return roadPoolList +} + +func GetRoadPoolByRoadPoolCode(roadPoolCode string) RoadPoolInfo { + o := orm.NewOrm() + var roadPoolInfo RoadPoolInfo + _, err := o.QueryTable(ROAD_POOL_INFO).Filter("road_pool_code", roadPoolCode).Limit(1).All(&roadPoolInfo) + + if err != nil { + logs.Error("get road pool info by road pool code fail: ", err) + } + + return roadPoolInfo +} + +func GetAllRollPool(params map[string]string) []RoadPoolInfo { + o := orm.NewOrm() + var roadPoolList []RoadPoolInfo + qs := o.QueryTable(ROAD_POOL_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + _, err := qs.Limit(-1).All(&roadPoolList) + if err != nil { + logs.Error("get all roll pool fail: ", err) + } + return roadPoolList +} + +func GetRoadPoolByName(roadPoolName string) RoadPoolInfo { + o := orm.NewOrm() + var roadPoolInfo RoadPoolInfo + _, err := o.QueryTable(ROAD_POOL_INFO).Filter("road_pool_name", roadPoolName).Limit(1).All(&roadPoolInfo) + if err != nil { + logs.Error("get road pool by name fail: ", err) + } + return roadPoolInfo +} + +func DeleteRoadPoolByCode(roadPoolCode string) bool { + o := orm.NewOrm() + _, err := o.QueryTable(ROAD_POOL_INFO).Filter("road_pool_code", roadPoolCode).Delete() + if err != nil { + logs.Error("delete road pool by code fail: ", err) + return false + } + return true +} + +func UpdateRoadPool(roadPool RoadPoolInfo) bool { + o := orm.NewOrm() + _, err := o.Update(&roadPool) + + if err != nil { + logs.Error("update road pool fail: ", err) + return false + } + return true +} diff --git a/agent/models/role_info.go b/agent/models/role_info.go new file mode 100644 index 0000000..49c7c51 --- /dev/null +++ b/agent/models/role_info.go @@ -0,0 +1,123 @@ +/*************************************************** + ** @Desc : This file for ... + ** @Time : 2019/8/29 14:43 + ** @Author : yuebin + ** @File : role_info + ** @Last Modified by : yuebin + ** @Last Modified time: 2019/8/29 14:43 + ** @Software: GoLand +****************************************************/ +package models + +import ( + "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/core/logs" +) + +type RoleInfo struct { + Id int + RoleName string + RoleUid string + ShowFirstMenu string + ShowFirstUid string + ShowSecondMenu string + ShowSecondUid string + ShowPower string + ShowPowerUid string + Creater string + Status string + Remark string + CreateTime string + UpdateTime string +} + +const ROLE_INFO = "role_info" + +func GetRoleLenByMap(params map[string]string) int { + o := orm.NewOrm() + qs := o.QueryTable(ROLE_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + cnt, err := qs.Count() + if err != nil { + logs.Error("get role len by map fail: ", err) + } + return int(cnt) +} + +func GetRole() []RoleInfo { + o := orm.NewOrm() + var roleInfo []RoleInfo + _, err := o.QueryTable(ROLE_INFO).Limit(-1).OrderBy("-update_time").All(&roleInfo) + if err != nil { + logs.Error("get all role fail: ", err) + } + return roleInfo +} + +func GetRoleByMap(params map[string]string, display, offset int) []RoleInfo { + o := orm.NewOrm() + var roleInfo []RoleInfo + qs := o.QueryTable(ROLE_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + _, err := qs.Limit(display, offset).OrderBy("-update_time").All(&roleInfo) + if err != nil { + logs.Error("get role by map fail: ", err) + } + return roleInfo +} + +func GetRoleByRoleUid(roleUid string) RoleInfo { + o := orm.NewOrm() + var roleInfo RoleInfo + _, err := o.QueryTable(ROLE_INFO).Filter("role_uid", roleUid).Limit(1).All(&roleInfo) + + if err != nil { + logs.Error("get role by role uid fail: ", err) + } + return roleInfo +} + +func RoleNameExists(roleName string) bool { + o := orm.NewOrm() + exists := o.QueryTable(ROLE_INFO).Filter("role_name", roleName).Exist() + return exists +} + +func InsertRole(roleInfo RoleInfo) bool { + o := orm.NewOrm() + _, err := o.Insert(&roleInfo) + if err != nil { + logs.Error("insert role fail: ", err) + return false + } + return true +} + +func DeleteRoleByRoleUid(roleUid string) bool { + o := orm.NewOrm() + _, err := o.QueryTable(ROLE_INFO).Filter("role_uid", roleUid).Delete() + if err != nil { + logs.Error("delete role by role uid fail: ", err) + return false + } + return true +} + +func UpdateRoleInfo(roleInfo RoleInfo) bool { + o := orm.NewOrm() + _, err := o.Update(&roleInfo) + + if err != nil { + logs.Error("update role info fail: ", err) + return false + } + return true +} diff --git a/agent/models/second_menu_info.go b/agent/models/second_menu_info.go new file mode 100644 index 0000000..e1b3f87 --- /dev/null +++ b/agent/models/second_menu_info.go @@ -0,0 +1,216 @@ +/*************************************************** + ** @Desc : This file for ... + ** @Time : 2019/8/26 9:33 + ** @Author : yuebin + ** @File : second_menu_info + ** @Last Modified by : yuebin + ** @Last Modified time: 2019/8/26 9:33 + ** @Software: GoLand +****************************************************/ +package models + +import ( + "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/core/logs" +) + +const SECOND_MENU_INFO = "second_menu_info" + +type SecondMenuInfo struct { + Id int + FirstMenuOrder int + FirstMenuUid string + FirstMenu string + MenuOrder int + SecondMenuUid string + SecondMenu string + SecondRouter string + Creater string + Status string + CreateTime string + UpdateTime string +} + +type SecondMenuSlice []SecondMenuInfo + +func (sm SecondMenuSlice) Len() int { + return len(sm) +} + +func (sm SecondMenuSlice) Swap(i, j int) { + sm[i], sm[j] = sm[j], sm[i] +} + +func (sm SecondMenuSlice) Less(i, j int) bool { + if sm[i].FirstMenuOrder == sm[j].FirstMenuOrder { + return sm[i].MenuOrder < sm[j].MenuOrder + } + return sm[i].FirstMenuOrder < sm[j].FirstMenuOrder +} + +func GetSecondMenuLen() int { + o := orm.NewOrm() + cnt, err := o.QueryTable(SECOND_MENU_INFO).Count() + if err != nil { + logs.Error("get second meun len fail: ", err) + } + return int(cnt) +} + +func GetSecondMenuInfoByMenuOrder(menuOrder int, firstMenuUid string) SecondMenuInfo { + o := orm.NewOrm() + var secondMenuInfo SecondMenuInfo + _, err := o.QueryTable(SECOND_MENU_INFO).Filter("first_menu_uid", firstMenuUid).Filter("menu_order", menuOrder).Limit(1).All(&secondMenuInfo) + if err != nil { + logs.Error("get second menu info by menu order fail: ", err) + } + return secondMenuInfo +} + +func GetSecondMenuLenByFirstMenuUid(firstMenuUid string) int { + o := orm.NewOrm() + cnt, err := o.QueryTable(SECOND_MENU_INFO).Filter("first_menu_uid", firstMenuUid).Count() + if err != nil { + logs.Error("get second menu len by first menu uid fail: ", err) + } + return int(cnt) +} + +func GetSecondMenuList() []SecondMenuInfo { + o := orm.NewOrm() + var secondMenuList []SecondMenuInfo + _, err := o.QueryTable(SECOND_MENU_INFO).Limit(-1).OrderBy("-update_time").All(&secondMenuList) + if err != nil { + logs.Error("get second menu list fail: ", err) + } + return secondMenuList +} + +func GetSecondMenuInfoBySecondMenuUid(secondMenuUid string) SecondMenuInfo { + o := orm.NewOrm() + var secondMenuInfo SecondMenuInfo + _, err := o.QueryTable(SECOND_MENU_INFO).Filter("second_menu_uid", secondMenuUid).Limit(1).All(&secondMenuInfo) + if err != nil { + logs.Error("get scond menu info by second menu uid fail: ", err) + } + return secondMenuInfo +} + +func GetSecondMenuInfoBySecondMenuUids(secondMenuUids []string) []SecondMenuInfo { + secondMenuInfoList := make([]SecondMenuInfo, 0) + for _, v := range secondMenuUids { + sm := GetSecondMenuInfoBySecondMenuUid(v) + secondMenuInfoList = append(secondMenuInfoList, sm) + } + return secondMenuInfoList +} + +func GetSecondMenuListByFirstMenuUid(firstMenuUid string) []SecondMenuInfo { + o := orm.NewOrm() + var secondMenuList []SecondMenuInfo + _, err := o.QueryTable(SECOND_MENU_INFO).Filter("first_menu_uid", firstMenuUid).Limit(-1).OrderBy("-update_time").All(&secondMenuList) + if err != nil { + logs.Error("get second menu list by first menu uid fail: ", err) + } + return secondMenuList +} + +func GetSecondMenuLenByMap(params map[string]string) int { + o := orm.NewOrm() + qs := o.QueryTable(SECOND_MENU_INFO) + for k, v := range params { + qs = qs.Filter(k, v) + } + cnt, err := qs.Limit(-1).Count() + if err != nil { + logs.Error("get second menu len by map fail: ", err) + } + return int(cnt) +} + +func GetSecondMenuByMap(params map[string]string, displayCount, offset int) []SecondMenuInfo { + o := orm.NewOrm() + var secondMenuList []SecondMenuInfo + qs := o.QueryTable(SECOND_MENU_INFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + _, err := qs.Limit(displayCount, offset).OrderBy("-update_time").All(&secondMenuList) + if err != nil { + logs.Error("get second menu by map fail: ", err) + } + return secondMenuList +} +func InsertSecondMenu(secondMenuInfo SecondMenuInfo) bool { + o := orm.NewOrm() + _, err := o.Insert(&secondMenuInfo) + if err != nil { + logs.Error("insert second menu fail: ", err) + return false + } + return true +} + +func SecondMenuIsExists(seconfMenu string) bool { + o := orm.NewOrm() + exist := o.QueryTable(SECOND_MENU_INFO).Filter("second_menu", seconfMenu).Exist() + return exist +} + +func SecondMenuUidIsExists(secondMenuUid string) bool { + o := orm.NewOrm() + exist := o.QueryTable(SECOND_MENU_INFO).Filter("second_menu_uid", secondMenuUid).Exist() + return exist +} + +func SecondRouterExists(secondRouter string) bool { + o := orm.NewOrm() + exist := o.QueryTable(SECOND_MENU_INFO).Filter("second_router", secondRouter).Exist() + return exist +} + +func DeleteSecondMenuByFirstMenuUid(firstMenuUid string) bool { + o := orm.NewOrm() + num, err := o.QueryTable(SECOND_MENU_INFO).Filter("first_menu_uid", firstMenuUid).Delete() + if err != nil { + logs.Error("delete second menu by first menu uid fail: ", err) + return false + } + logs.Info("delete second menu by first menu uid success, num: ", num) + return true +} + +func DeleteSecondMenuBySecondMenuUid(secondMenuUid string) bool { + o := orm.NewOrm() + num, err := o.QueryTable(SECOND_MENU_INFO).Filter("second_menu_uid", secondMenuUid).Delete() + if err != nil { + logs.Error("delete second menu by second menu uid fail: ", err) + return false + } + logs.Info("delete second menu by second menu uid success, num: ", num) + return true +} + +func UpdateSecondMenuOrderBySecondUid(secondUid string, order int) { + o := orm.NewOrm() + _, err := o.QueryTable(SECOND_MENU_INFO).Filter("second_menu_uid", secondUid).Update(orm.Params{"menu_order": order}) + if err != nil { + logs.Error("update second menu order by second menu uid fail: ", err) + } +} + +func UpdateSecondMenu(secondMenu SecondMenuInfo) { + o := orm.NewOrm() + _, err := o.Update(&secondMenu) + if err != nil { + logs.Error("update second menu for first order fail: ", err) + } +} + +func SecondMenuExistByMenuOrder(menuOrder int) bool { + o := orm.NewOrm() + exist := o.QueryTable(SECOND_MENU_INFO).Filter("menu_order", menuOrder).Exist() + return exist +} diff --git a/agent/models/transaction.go b/agent/models/transaction.go new file mode 100644 index 0000000..a283397 --- /dev/null +++ b/agent/models/transaction.go @@ -0,0 +1,87 @@ +/*************************************************** + ** @Desc : This file for ... + ** @Time : 2019/10/19 14:17 + ** @Author : yuebin + ** @File : transaction + ** @Last Modified by : yuebin + ** @Last Modified time: 2019/10/19 14:17 + ** @Software: GoLand +****************************************************/ +package models + +import ( +) + +/*func OperatorAccount(accountUid, operatorType string, amount float64) (string, bool) { + o := orm.NewOrm() + o.Begin() + + defer func(interface{}) { + if r := recover(); r != nil { + o.Rollback() + logs.Error("operator account fail") + } + }(o) + + msg := "" + //处理事务 + accountInfo := new(AccountInfo) + if err := o.Raw("select * from account_info where account_uid = ? for update", accountUid).QueryRow(accountInfo); err != nil || accountInfo.AccountUid == "" { + logs.Error("operator account get account info for update fail: ", err) + o.Rollback() + return msg, false + } + + accountInfo.UpdateTime = utils.GetBasicDateTime() + flag := true + + switch operatorType { + case common.PLUS_AMOUNT: //处理加款操作 + accountInfo.Balance = accountInfo.Balance + amount + accountInfo.SettleAmount = accountInfo.SettleAmount + amount + case common.SUB_AMOUNT: //处理减款 + if accountInfo.Balance >= amount && accountInfo.SettleAmount >= amount { + accountInfo.Balance = accountInfo.Balance - amount + accountInfo.SettleAmount = accountInfo.SettleAmount - amount + } else { + msg = "账户余额不够减" + flag = false + } + case common.FREEZE_AMOUNT: //处理冻结款 + accountInfo.FreezeAmount = accountInfo.FreezeAmount + amount + case common.UNFREEZE_AMOUNT: //处理解冻款 + if accountInfo.FreezeAmount >= amount { + accountInfo.FreezeAmount = accountInfo.FreezeAmount - amount + } else { + msg = "账户冻结金额不够解冻款" + flag = false + } + } + if !flag { + o.Rollback() + return msg, false + } + + if _, err := o.Update(accountInfo); err != nil { + logs.Error("operator account update account fail: ", err) + o.Rollback() + return msg, false + } + //往account_history表中插入一条动账记录 + accountHistory := AccountHistoryInfo{AccountUid: accountUid, AccountName: accountInfo.AccountName, Type: operatorType, + Amount: amount, Balance: accountInfo.Balance, CreateTime: utils.GetBasicDateTime(), UpdateTime: utils.GetBasicDateTime()} + + if _, err := o.Insert(&accountHistory); err != nil { + logs.Error("operator account insert account history fail: ", err) + o.Rollback() + return msg, false + } + if err := o.Commit(); err != nil { + logs.Error("operator account commit fail: ", err) + return msg, false + } else { + logs.Info("操作账户成功") + return "", true + } +} +*/ \ No newline at end of file diff --git a/agent/models/user_info.go b/agent/models/user_info.go new file mode 100644 index 0000000..bf5235c --- /dev/null +++ b/agent/models/user_info.go @@ -0,0 +1,146 @@ +/*************************************************** + ** @Desc : This file for ... + ** @Time : 2019/8/9 14:02 + ** @Author : yuebin + ** @File : user_info + ** @Last Modified by : yuebin + ** @Last Modified time: 2019/8/9 14:02 + ** @Software: GoLand +****************************************************/ +package models + +import ( + "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/core/logs" +) + +const ( + USERINFO = "user_info" +) + +type UserInfo struct { + Id int + UserId string + Passwd string + Nick string + Remark string + Ip string + Status string + Role string + RoleName string + CreateTime string + UpdateTime string +} + +func GetUserInfoByUserID(userID string) UserInfo { + o := orm.NewOrm() + var userInfo UserInfo + err := o.QueryTable(USERINFO).Exclude("status", "delete").Filter("user_id", userID).One(&userInfo) + if err != nil { + logs.Error("get user info fail: ", err) + } + return userInfo +} + +func GetOperatorByMap(params map[string]string, displayCount, offset int) []UserInfo { + o := orm.NewOrm() + var userInfo []UserInfo + qs := o.QueryTable(USERINFO) + for k, v := range params { + if len(v) > 0 { + qs = qs.Filter(k, v) + } + } + _, err := qs.Exclude("status", "delete").Limit(displayCount, offset).OrderBy("-update_time").All(&userInfo) + + if err != nil { + logs.Error("get operator by map fail: ", err) + } + return userInfo +} + +func GetOperatorLenByMap(params map[string]string) int { + o := orm.NewOrm() + qs := o.QueryTable(USERINFO) + for k, v := range params { + qs = qs.Filter(k, v) + } + cnt, err := qs.Exclude("status", "delete").Count() + if err != nil { + logs.Error("get operator len by map fail: ", err) + } + return int(cnt) +} + +func UpdateUserInfoIP(userInfo UserInfo) { + o := orm.NewOrm() + num, err := o.QueryTable(USERINFO).Exclude("status", "delete").Filter("user_id", userInfo.UserId).Update(orm.Params{"ip": userInfo.Ip}) + if err != nil { + logs.Error("%s update user info ip fail: %v", userInfo.UserId, err) + } else { + logs.Info("%s update user info ip success, num: %d", userInfo.UserId, num) + } +} + +func UpdateUserInfoPassword(userInfo UserInfo) { + o := orm.NewOrm() + num, err := o.QueryTable(USERINFO).Exclude("status", "delete").Filter("user_id", userInfo.UserId).Update(orm.Params{"passwd": userInfo.Passwd}) + if err != nil { + logs.Error("%s update user info password fail: %v", userInfo.UserId, err) + } else { + logs.Info("%s update user info password success, update num: %d", userInfo.UserId, num) + } +} + +func UpdateUserInfo(userInfo UserInfo) { + o := orm.NewOrm() + if num, err := o.Update(&userInfo); err != nil { + logs.Error("update user info fail: ", err) + } else { + logs.Info("update user info success, num: ", num) + } +} + +func UpdateStauts(status, userId string) bool { + o := orm.NewOrm() + _, err := o.QueryTable(USERINFO).Filter("user_id", userId).Update(orm.Params{"status": status}) + + if err != nil { + logs.Error("update status fail: ", err) + return false + } + return true +} + +func UserInfoExistByUserId(userId string) bool { + o := orm.NewOrm() + exist := o.QueryTable(USERINFO).Exclude("status", "delete").Filter("user_id", userId).Exist() + return exist +} + +func NickIsExist(nick string) bool { + o := orm.NewOrm() + exist := o.QueryTable(USERINFO).Exclude("status", "delete").Filter("nick", nick).Exist() + return exist +} + +func InsertUser(userInfo UserInfo) bool { + o := orm.NewOrm() + _, err := o.Insert(&userInfo) + if err != nil { + logs.Error("insert user fail: ", err) + return false + } + return true +} + +func DeleteUserByUserId(userId string) bool { + o := orm.NewOrm() + _, err := o.QueryTable(USERINFO).Exclude("status", "delete").Filter("user_id", userId).Update(orm.Params{"status": "delete"}) + + if err != nil { + logs.Error("delete user by userId fail: ", err) + return false + } + return true +} diff --git a/agent/routers/router.go b/agent/routers/router.go new file mode 100644 index 0000000..8d2dbee --- /dev/null +++ b/agent/routers/router.go @@ -0,0 +1,57 @@ +package routers + +import ( + "agent/controllers" + beego "github.com/beego/beego/v2/server/web" + "github.com/dchest/captcha" +) + +func init() { + //生产登录验证码 + beego.Handler("/img.do/*.png", captcha.Server(130, 40)) + beego.Router("/", &controllers.Login{}, "*:Index") + beego.Router("/login.py/?:params", &controllers.Login{}, "post:UserLogin") + beego.Router("/verifyCaptcha.py/:value/:chaId", &controllers.Login{}, "get:VerifyCaptcha") + beego.Router("/flushCaptcha.py/", &controllers.Login{}, "get:FlushCaptcha") + beego.Router("/loginOut.py", &controllers.Login{}, "*:LoginOut") + beego.Router("/pay_doc.py", &controllers.Login{}, "*:PayDoc") + + beego.Router("/history/show_history_list_ui", &controllers.History{}, "*:ShowHistoryListUI") + beego.Router("/history/list_history_record/?:params", &controllers.History{}, "*:HistoryQueryAndListPage") + + beego.Router("/excel/download", &controllers.DealExcel{}, "*:DownloadExcelModel") + beego.Router("/excel/make_order_excel/?:params", &controllers.DealExcel{}, "get:MakeOrderExcel") + beego.Router("/excel/download_excel/?:params", &controllers.DealExcel{}, "get:DownloadRecordExcel") + beego.Router("/excel/make_complaint_record_excel/?:params", &controllers.DealExcel{}, "get:MakeComplaintExcel") + beego.Router("/excel/make_withdraw_record_excel/?:params", &controllers.DealExcel{}, "get:MakeWithdrawExcel") + + beego.Router("/index/ui/", &controllers.Index{}, "*:ShowUI") + beego.Router("/index/loadInfo/", &controllers.Index{}, "*:LoadUserAccountInfo") + beego.Router("/index/load_count_order", &controllers.Index{}, "*:LoadCountOrder") + beego.Router("/index/loadOrders", &controllers.Index{}, "*:LoadOrderCount") + beego.Router("/index/show_pay_way_ui", &controllers.Index{}, "*:LoadUserPayWayUI") + beego.Router("/index/pay_way", &controllers.Index{}, "*:LoadUserPayWay") + + beego.Router("/multi_withdraw/show_multi_ui", &controllers.MultiWithdraw{}, "*:ShowMultiWithdrawUI") + beego.Router("/multi_withdraw/launch_multi_withdraw/?:params", &controllers.Withdraw{}, "post:LaunchMultiWithdraw") + + beego.Router("/trade/show_ui", &controllers.TradeRecord{}, "*:ShowUI") + beego.Router("/trade/list/?:params", &controllers.TradeRecord{}, "*:TradeQueryAndListPage") + beego.Router("/trade/show_complaint_ui", &controllers.TradeRecord{}, "*:ShowComplaintUI") + beego.Router("/trade/complaint/?:params", &controllers.TradeRecord{}, "*:ComplaintQueryAndListPage") + + beego.Router("/user_info/show_modify_ui", &controllers.UserInfo{}, "*:ShowModifyUserInfoUI") + beego.Router("/user_info/modify_userInfo/?:params", &controllers.UserInfo{}, "*:ModifyUserInfo") + beego.Router("/user_info/confirm_pwd/?:params", &controllers.UserInfo{}, "*:ConfirmOriginPwd") + beego.Router("/user_info/set_pay_password/?:params", &controllers.UserInfo{}, "*:SetPayPassword") + beego.Router("/user_info/confirm_pay_pwd/?:params", &controllers.UserInfo{}, "*:ConfirmOriginPayPwd") + beego.Router("/user_info/show_ui", &controllers.UserInfo{}, "*:ShowUserInfoUI") + beego.Router("/user_info/show_merchant_ui", &controllers.UserInfo{}, "*:ShowMerchantUI") + beego.Router("//user_info/merchant_list/?:params", &controllers.UserInfo{}, "*:MerchantQueryAndListPage") + + beego.Router("/withdraw/show_ui", &controllers.Withdraw{}, "*:ShowWithdrawUI") + beego.Router("/withdraw/balance", &controllers.Withdraw{}, "*:UserBalance") + beego.Router("/withdraw/launch_single_withdraw/?:params", &controllers.Withdraw{}, "post:LaunchSingleWithdraw") + beego.Router("/withdraw/show_list_ui", &controllers.Withdraw{}, "*:ShowListUI") + beego.Router("/withdraw/list_record/?:params", &controllers.Withdraw{}, "*:WithdrawQueryAndListPage") +} diff --git a/agent/static/css/custom.css b/agent/static/css/custom.css new file mode 100644 index 0000000..a4b5576 --- /dev/null +++ b/agent/static/css/custom.css @@ -0,0 +1 @@ +/* your styles go here */ \ No newline at end of file diff --git a/agent/static/css/fontastic.css b/agent/static/css/fontastic.css new file mode 100644 index 0000000..0bc6299 --- /dev/null +++ b/agent/static/css/fontastic.css @@ -0,0 +1,121 @@ +@charset "UTF-8"; + +@font-face { + font-family: "dashboard"; + src:url("../fonts/dashboard.eot"); + src:url("../fonts/dashboard.eot?#iefix") format("embedded-opentype"), + url("../fonts/dashboard.woff") format("woff"), + url("../fonts/dashboard.ttf") format("truetype"), + url("../fonts/dashboard.svg#dashboard") format("svg"); + font-weight: normal; + font-style: normal; + +} + +[data-icon]:before { + font-family: "dashboard" !important; + content: attr(data-icon); + font-style: normal !important; + font-weight: normal !important; + font-variant: normal !important; + text-transform: none !important; + speak: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +[class^="icon-"]:before, +[class*=" icon-"]:before { + font-family: "dashboard" !important; + font-style: normal !important; + font-weight: normal !important; + font-variant: normal !important; + text-transform: none !important; + speak: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-home:before { + content: "\62"; +} +.icon-form:before { + content: "\61"; +} +.icon-list:before { + content: "\63"; +} +.icon-presentation:before { + content: "\65"; +} +.icon-bill:before { + content: "\66"; +} +.icon-check:before { + content: "\67"; +} +.icon-list-1:before { + content: "\68"; +} +.icon-padnote:before { + content: "\69"; +} +.icon-pencil-case:before { + content: "\6a"; +} +.icon-user:before { + content: "\6b"; +} +.icon-bars:before { + content: "\6c"; +} +.icon-line-chart:before { + content: "\70"; +} +.icon-flask:before { + content: "\6d"; +} +.icon-grid:before { + content: "\6e"; +} +.icon-picture:before { + content: "\6f"; +} +.icon-website:before { + content: "\71"; +} +.icon-screen:before { + content: "\72"; +} +.icon-interface-windows:before { + content: "\73"; +} +.icon-clock:before { + content: "\74"; +} +.icon-rss-feed:before { + content: "\75"; +} +.icon-mail:before { + content: "\64"; +} +.icon-ios-email-outline:before { + content: "\76"; +} +.icon-paper-airplane:before { + content: "\77"; +} +.icon-ios-email:before { + content: "\78"; +} +.icon-page:before { + content: "\41"; +} +.icon-close:before { + content: "\79"; +} +.icon-search:before { + content: "\7a"; +} diff --git a/agent/static/css/style.blue.css b/agent/static/css/style.blue.css new file mode 100644 index 0000000..3cdbe81 --- /dev/null +++ b/agent/static/css/style.blue.css @@ -0,0 +1,3496 @@ +/* +========================================================== +========================================================== + +Bootstrap 4 Admin Template + +https://bootstrapious.com/p/admin-template + +========================================================== +========================================================== +*/ +/* +* ========================================================== +* GENERAL STYLES +* ========================================================== +*/ +body { + overflow-x: hidden; +} + +a, +i, +span { + display: inline-block; + text-decoration: none; + -webkit-transition: all 0.3s; + transition: all 0.3s; +} + +a:hover, a:focus, +i:hover, +i:focus, +span:hover, +span:focus { + text-decoration: none; +} + +section { + padding: 0px 0; +} + +canvas { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.container-fluid { + padding: 0 30px; +} + +@media (max-width: 575px) { + .container-fluid { + padding: 0 15px; + } +} + +header.page-header { + padding: 20px 0; +} + +table { + font-size: 0.9em; + color: #666; +} + +.card-close { + position: absolute; + top: 15px; + right: 15px; +} + +.card-close .dropdown-toggle { + color: #999; + background: none; + border: none; +} + +.card-close .dropdown-toggle:after { + display: none; +} + +.card-close .dropdown-menu { + border: none; + min-width: auto; + font-size: 0.9em; + border-radius: 0; + -webkit-box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.1), -2px -2px 3px rgba(0, 0, 0, 0.1); + box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.1), -2px -2px 3px rgba(0, 0, 0, 0.1); +} + +.card-close .dropdown-menu a { + color: #999 !important; +} + +.card-close .dropdown-menu a:hover { + background: #2b90d9; + color: #fff !important; +} + +.card-close .dropdown-menu a i { + margin-right: 10px; + -webkit-transition: none; + transition: none; +} + +.content-inner { + position: relative; + width: calc(100% - 250px); + min-height: calc(100vh - 70px); + padding-bottom: 60px; +} + +.content-inner.active { + width: calc(100% - 90px); +} + +.page-header { + background: #fff; + padding: 20px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1); + position: relative; + z-index: 8; +} + +*[class*="icon-"] { + -webkit-transform: translateY(3px); + transform: translateY(3px); +} + +button, +input { + outline: none !important; +} + +.card { + margin-bottom: 30px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1), -1px 0 2px rgba(0, 0, 0, 0.05); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1), -1px 0 2px rgba(0, 0, 0, 0.05); +} + +.card-header { + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.05); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.05); +} + +.card-header h1, +.card-header h2, +.card-header h3, +.card-header h4, +.card-header h5, +.card-header h6 { + margin-bottom: 0; +} + +.breadcrumb-holder { + background: #fff; +} + +.breadcrumb { + background: #fff; + position: relative; + z-index: 7; + border-radius: 0; + padding: 15px 0; + margin-bottom: 0; +} + +.breadcrumb li.breadcrumb-item { + color: #aaa; + font-weight: 300; +} + +/*=== Helpers ===*/ +.text-bold { + font-weight: 700; +} + +.text-small { + font-size: 0.9rem; +} + +.text-xsmall { + font-size: 0.8rem; +} + +.bg-red { + background: #ff7676 !important; + color: #fff; +} + +.bg-red:hover { + color: #fff; +} + +.bg-blue { + background: #85b4f2 !important; + color: #fff; +} + +.bg-blue:hover { + color: #fff; +} + +.bg-yellow { + background: #eef157 !important; + color: #fff; +} + +.bg-yellow:hover { + color: #fff; +} + +.bg-green { + background: #54e69d !important; + color: #fff; +} + +.bg-green:hover { + color: #fff; +} + +.bg-orange { + background: #ffc36d !important; + color: #fff; +} + +.bg-orange:hover { + color: #fff; +} + +.bg-violet { + background: #796AEE !important; + color: #fff; +} + +.bg-violet:hover { + color: #fff; +} + +.bg-gray { + background: #ced4da !important; +} + +.bg-white { + background: #fff !important; +} + +.text-red { + color: #ff7676; +} + +.text-red:hover { + color: #ff7676; +} + +.text-yellow { + color: #eef157; +} + +.text-yellow:hover { + color: #eef157; +} + +.text-green { + color: #54e69d; +} + +.text-green:hover { + color: #54e69d; +} + +.text-orange { + color: #ffc36d; +} + +.text-orange:hover { + color: #ffc36d; +} + +.text-violet { + color: #796AEE; +} + +.text-violet:hover { + color: #796AEE; +} + +.text-blue { + color: #85b4f2; +} + +.text-blue:hover { + color: #85b4f2; +} + +.text-gray { + color: #ced4da; +} + +.text-gray:hover { + color: #ced4da; +} + +.text-uppercase { + letter-spacing: 0.2em; +} + +.lh-2 { + line-height: 2; +} + +.page { + background: #EEF5F9; +} + +.page .text-white { + color: #fff; +} + +.no-padding { + padding: 0 !important; +} + +.no-padding-bottom { + padding-bottom: 0 !important; +} + +.no-padding-top { + padding-top: 0 !important; +} + +.no-margin { + margin: 0 !important; +} + +.no-margin-bottom { + margin-bottom: 0 !important; +} + +.no-margin-top { + margin-top: 0 !important; +} + +.page { + overflow-x: hidden; +} + +.has-shadow { + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1), -1px 0 2px rgba(0, 0, 0, 0.05); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1), -1px 0 2px rgba(0, 0, 0, 0.05); +} + +.badge { + font-weight: 400; +} + +.badge-rounded { + border-radius: 50px; +} + +.list-group-item { + border-right: 0; + border-left: 0; +} + +.list-group-item:first-child, .list-group-item:last-child { + border-radius: 0; +} + +.overflow-hidden { + overflow: hidden; +} + +.tile-link { + position: absolute; + cursor: pointer; + width: 100%; + height: 100%; + left: 0; + top: 0; + z-index: 30; +} + +/* +* ========================================================== +* SIDEBAR +* ========================================================== +*/ +nav.side-navbar { + background: #fff; + min-width: 250px; + max-width: 250px; + color: #686a76; + -webkit-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1); + box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1); + z-index: 9; + /*==== Sidebar Header ====*/ + /*==== Sidebar Menu ====*/ + /*==== Shrinked Sidebar ====*/ +} + +nav.side-navbar a { + color: inherit; + position: relative; + font-size: 0.9em; +} + +nav.side-navbar a[data-toggle="collapse"]::before { + content: '\f104'; + display: inline-block; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); + font-family: 'FontAwesome'; + position: absolute; + top: 50%; + right: 20px; +} + +nav.side-navbar a[aria-expanded="true"] { + background: #EEF5F9; +} + +nav.side-navbar a[aria-expanded="true"]::before { + content: '\f107'; +} + +nav.side-navbar a i { + font-size: 1.2em; + margin-right: 10px; + -webkit-transition: none; + transition: none; +} + +nav.side-navbar .sidebar-header { + padding: 30px 15px; +} + +nav.side-navbar .avatar { + width: 55px; + height: 55px; +} + +nav.side-navbar .title { + margin-left: 10px; +} + +nav.side-navbar .title h1 { + color: #333; +} + +nav.side-navbar .title p { + font-size: 0.9em; + font-weight: 200; + margin-bottom: 0; + color: #aaa; +} + +nav.side-navbar span.heading { + text-transform: uppercase; + font-weight: 400; + margin-left: 20px; + color: #ccc; + font-size: 0.8em; +} + +nav.side-navbar ul { + padding: 15px 0; +} + +nav.side-navbar ul li { + /* submenu item active */ +} + +nav.side-navbar ul li a { + padding: 10px 15px; + text-decoration: none; + display: block; + font-weight: 300; + border-left: 4px solid transparent; +} + +nav.side-navbar ul li a:hover { + background: #2b90d9; + border-left: 4px solid #1c669c; + color: #fff; +} + +nav.side-navbar ul li li a { + padding-left: 50px; + background: #EEF5F9; +} + +nav.side-navbar ul li.active > a { + background: #2b90d9; + color: #fff; + border-left: 4px solid #1c669c; +} + +nav.side-navbar ul li.active > a:hover { + background: #2b90d9; +} + +nav.side-navbar ul li li.active > a { + background: #419bdd; +} + +nav.side-navbar ul li ul { + padding: 0; +} + +nav.side-navbar.shrinked { + min-width: 90px; + max-width: 90px; + text-align: center; +} + +nav.side-navbar.shrinked span.heading { + margin: 0; +} + +nav.side-navbar.shrinked ul li a { + padding: 15px 2px; + border: none; + font-size: 0.8em; + color: #aaa; + -webkit-transition: color 0.3s, background 0.3s; + transition: color 0.3s, background 0.3s; +} + +nav.side-navbar.shrinked ul li a[data-toggle="collapse"]::before { + content: '\f107'; + -webkit-transform: translateX(50%); + transform: translateX(50%); + position: absolute; + top: auto; + right: 50%; + bottom: 0; + left: auto; +} + +nav.side-navbar.shrinked ul li a[data-toggle="collapse"][aria-expanded="true"]::before { + content: '\f106'; +} + +nav.side-navbar.shrinked ul li a:hover { + color: #fff; + border: none; +} + +nav.side-navbar.shrinked ul li a:hover i { + color: #fff; +} + +nav.side-navbar.shrinked ul li a i { + margin-right: 0; + margin-bottom: 2px; + display: block; + font-size: 1rem; + color: #333; + -webkit-transition: color 0.3s; + transition: color 0.3s; +} + +nav.side-navbar.shrinked ul li.active > a { + color: #fff; +} + +nav.side-navbar.shrinked ul li.active > a i { + color: #fff; +} + +nav.side-navbar.shrinked .sidebar-header .title { + display: none; +} + +/* SIDEBAR MEDIAQUERIES ----------------------------------- */ +@media (max-width: 1199px) { + nav.side-navbar { + margin-left: -90px; + min-width: 90px; + max-width: 90px; + text-align: center; + overflow: hidden; + } + nav.side-navbar span.heading { + margin: 0; + } + nav.side-navbar ul li a { + padding: 15px 2px; + border: none; + font-size: 0.8em; + color: #aaa; + -webkit-transition: color 0.3s, background 0.3s; + transition: color 0.3s, background 0.3s; + } + nav.side-navbar ul li a[data-toggle="collapse"]::before { + content: '\f107'; + -webkit-transform: translateX(50%); + transform: translateX(50%); + position: absolute; + top: auto; + right: 50%; + bottom: 0; + left: auto; + } + nav.side-navbar ul li a[data-toggle="collapse"][aria-expanded="true"]::before { + content: '\f106'; + } + nav.side-navbar ul li a:hover { + color: #fff; + border: none; + } + nav.side-navbar ul li a:hover i { + color: #fff; + } + nav.side-navbar ul li a i { + margin-right: 0; + margin-bottom: 5px; + display: block; + font-size: 1.6em; + color: #333; + -webkit-transition: color 0.3s; + transition: color 0.3s; + } + nav.side-navbar ul li.active > a { + color: #fff; + } + nav.side-navbar ul li.active > a i { + color: #fff; + } + nav.side-navbar .sidebar-header .title { + display: none; + } + nav.side-navbar.shrinked { + margin-left: 0; + } + .content-inner { + width: 100%; + } + .content-inner.active { + width: calc(100% - 90px); + } +} + +/* +* ========================================================== +* MAIN NAVBAR +* ========================================================== +*/ +nav.navbar { + background: #2f333e; + padding-top: 15px; + padding-bottom: 15px; + color: #fff; + position: relative; + border-radius: 0; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.2); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.2); + z-index: 10; + padding-left: 0; + padding-right: 0; + /*==== Toggle Sidebar Btn ====*/ + /*==== Navbar Items ====*/ + /*==== Search Box ====*/ + /*==== Dropdowns ====*/ +} + +nav.navbar .badge { + width: 22px; + height: 22px; + line-height: 22px; + text-align: center; + padding: 0; + border-radius: 50%; +} + +nav.navbar .navbar-holder { + width: 100%; +} + +nav.navbar a { + color: inherit; +} + +nav.navbar .container-fluid { + width: 100%; +} + +nav.navbar .menu-btn { + margin-right: 20px; + font-size: 1.2em; + -webkit-transition: all 0.7s; + transition: all 0.7s; +} + +nav.navbar .menu-btn span { + width: 20px; + height: 2px; + background: #fff; + display: block; + margin: 4px auto 0; + -webkit-transition: all 0.3s cubic-bezier(0.81, -0.33, 0.345, 1.375); + transition: all 0.3s cubic-bezier(0.81, -0.33, 0.345, 1.375); +} + +nav.navbar .menu-btn span:nth-of-type(2) { + position: relative; + width: 35px; + -webkit-transform: rotateY(180deg); + transform: rotateY(180deg); +} + +nav.navbar .menu-btn span:nth-of-type(2)::before, nav.navbar .menu-btn span:nth-of-type(2)::after { + content: ''; + width: 6px; + height: 2px; + display: block; + background: #fff; + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + position: absolute; + top: 2px; + left: 0; + -webkit-transition: all 0.7s; + transition: all 0.7s; +} + +nav.navbar .menu-btn span:nth-of-type(2)::after { + -webkit-transform: rotate(145deg); + transform: rotate(145deg); + position: absolute; + top: -2px; + left: 0; +} + +nav.navbar .menu-btn.active span:first-of-type { + -webkit-transform: translateY(12px); + transform: translateY(12px); +} + +nav.navbar .menu-btn.active span:nth-of-type(2) { + -webkit-transform: none; + transform: none; +} + +nav.navbar .menu-btn.active span:last-of-type { + -webkit-transform: translateY(-12px); + transform: translateY(-12px); +} + +nav.navbar .nav-link { + position: relative; +} + +nav.navbar .nav-link span.badge-corner { + position: absolute; + top: 0; + right: 0; + font-weight: 400; + font-size: 0.7em; +} + +nav.navbar .nav-link.language span { + margin-left: .3rem; + vertical-align: middle; +} + +nav.navbar .nav-link.logout i { + margin-left: 10px; +} + +nav.navbar .nav-menu { + margin-bottom: 0; +} + +nav.navbar .search-box { + width: 100%; + height: 100%; + position: absolute; + top: 0; + right: 0; + padding: 0; + background: #fff; + z-index: 12; + border-radius: 0; + display: none; +} + +nav.navbar .search-box .dismiss { + position: absolute; + top: 50%; + right: 20px; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); + background: none; + border: none; + cursor: pointer; + font-size: 1.5em; + color: #999; +} + +nav.navbar .search-box form { + height: 100%; +} + +nav.navbar .search-box form input { + height: 100%; + border: none; + padding: 20px; +} + +nav.navbar .dropdown-toggle::after { + border: none !important; + content: '\f107'; + vertical-align: baseline; + font-family: 'FontAwesome'; + margin-left: .3rem; +} + +nav.navbar .dropdown-menu { + right: 0; + min-width: 250px; + left: auto; + margin-top: 15px; + margin-bottom: 0; + padding: 15px 0; + max-width: 400px; + border-radius: 0; + border: none; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1), -2px 0 2px rgba(0, 0, 0, 0.1); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1), -2px 0 2px rgba(0, 0, 0, 0.1); +} + +nav.navbar .dropdown-menu .dropdown-item { + background: #fff; + padding: 10px 20px; + font-size: 0.8rem; + color: #777; + width: 100%; +} + +nav.navbar .dropdown-menu .dropdown-item:hover { + background: #f5f5f5; +} + +nav.navbar .dropdown-menu .dropdown-item i { + width: 30px; + height: 30px; + line-height: 30px; + background: #2b90d9; + text-align: center; + color: #fff; + border-radius: 50%; + margin-right: 10px; +} + +nav.navbar .dropdown-menu .dropdown-item small { + margin-left: 40px; +} + +nav.navbar .dropdown-menu span { + position: static; + font-size: 0.9em; + color: #999; +} + +nav.navbar .dropdown-menu strong { + font-weight: 700; +} + +nav.navbar .dropdown-menu .msg-profile { + width: 45px; + height: 45px; + margin-right: 10px; +} + +nav.navbar .dropdown-menu h3 { + font-weight: 500; +} + +/* MAIN NAVBAR MEDIAQUERIES ----------------------------------- */ +@media (max-width: 1199px) { + nav.navbar { + /*==== Toggle Sidebar Btn ====*/ + } + nav.navbar .menu-btn { + margin-right: 20px; + font-size: 1.2em; + -webkit-transition: all 0.7s; + transition: all 0.7s; + } + nav.navbar .menu-btn span:first-of-type { + -webkit-transform: translateY(12px); + transform: translateY(12px); + } + nav.navbar .menu-btn span:nth-of-type(2) { + -webkit-transform: none; + transform: none; + } + nav.navbar .menu-btn span:nth-of-type(2)::before, nav.navbar .menu-btn span:nth-of-type(2)::after { + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + } + nav.navbar .menu-btn span:nth-of-type(2)::after { + -webkit-transform: rotate(145deg); + transform: rotate(145deg); + position: absolute; + top: -2px; + left: 0; + } + nav.navbar .menu-btn span:last-of-type { + -webkit-transform: translateY(-12px); + transform: translateY(-12px); + } + nav.navbar .menu-btn.active span:first-of-type { + -webkit-transform: none; + transform: none; + } + nav.navbar .menu-btn.active span:nth-of-type(2) { + -webkit-transform: rotateY(180deg); + transform: rotateY(180deg); + } + nav.navbar .menu-btn.active span:last-of-type { + -webkit-transform: none; + transform: none; + } +} + +@media (max-width: 575px) { + nav.navbar { + font-size: 14px; + } + nav.navbar .badge { + width: 19px; + height: 19px; + } + nav.navbar .nav-item > a { + font-size: 13px; + } + nav.navbar .dropdown-menu { + right: auto; + left: -50%; + -webkit-transform: translateX(-50%); + transform: translateX(-50%); + } +} + +/* +* ========================================================== +* DASHBOARD COUNTS SECTION +* ========================================================== +*/ +section.dashboard-counts .icon { + width: 40px; + height: 40px; + line-height: 40px; + text-align: center; + min-width: 40px; + max-width: 40px; + border-radius: 50%; +} + +section.dashboard-counts .title { + font-size: 1.1em; + font-weight: 300; + color: #777; + margin: 0 20px; +} + +section.dashboard-counts .progress { + margin-top: 10px; + height: 4px; +} + +section.dashboard-counts .number { + font-size: 1.8em; + font-weight: 300; +} + +section.dashboard-counts .number strong { + font-weight: 700; +} + +section.dashboard-counts .row { + padding: 30px 15px; + margin: 0; +} + +section.dashboard-counts div[class*='col-'] .item { + border-right: 1px solid #eee; + padding: 15px 0; +} + +section.dashboard-counts div[class*='col-']:last-of-type .item { + border-right: none; +} + +/* DASHBOARD COUNTS MEDIAQUERIES ------------------------ */ +@media (max-width: 1199px) { + section.dashboard-counts div[class*='col-']:nth-of-type(2) .item { + border-right: none; + } +} + +@media (max-width: 575px) { + section.dashboard-counts div[class*='col-'] .item { + border-right: none; + } +} + +/* +* ========================================================== +* DASHBOARD HEADER SECTION +* ========================================================== +*/ +.statistic { + padding: 20px 15px; + margin-bottom: 15px; +} + +.statistic:last-of-type { + margin-bottom: 0; +} + +.statistic strong { + font-size: 1.5em; + color: #333; + font-weight: 700; + line-height: 1; +} + +.statistic small { + color: #aaa; + text-transform: uppercase; +} + +.statistic .icon { + width: 40px; + height: 40px; + line-height: 40px; + text-align: center; + min-width: 40px; + max-width: 40px; + color: #fff; + border-radius: 50%; + margin-right: 15px; +} + +.chart .title { + padding: 15px 0 0 15px; +} + +.chart .title strong { + font-weight: 700; + font-size: 1.2em; +} + +.chart .title small { + color: #aaa; + text-transform: uppercase; +} + +.chart .line-chart { + width: 100%; + height: 100%; + padding: 20px 0; +} + +.chart .line-chart canvas { + width: calc(100% - 30px) !important; +} + +.chart .bar-chart { + margin-bottom: 15px; +} + +.chart .bar-chart canvas { + padding: 15px; + width: 100%; + margin: 0; +} + +/* DASHBOARD HEADER MEDIAQUERIES ------------------------*/ +@media (max-width: 991px) { + section.dashboard-header div[class*='col-'] { + margin-bottom: 20px; + } +} + +/* +* ========================================================== +* PROJECTS SECTION +* ========================================================== +*/ +.project .row { + margin: 0; + padding: 15px 0; + margin-bottom: 15px; +} + +.project div[class*='col-'] { + border-right: 1px solid #eee; +} + +.project .text h3 { + margin-bottom: 0; + color: #555; +} + +.project .text small { + color: #aaa; + font-size: 0.75em; +} + +.project .project-date span { + font-size: 0.9em; + color: #999; +} + +.project .image { + max-width: 50px; + min-width: 50px; + height: 50px; + margin-right: 15px; +} + +.project .time, +.project .comments, +.project .project-progress { + color: #999; + font-size: 0.9em; + margin-right: 20px; +} + +.project .time i, +.project .comments i, +.project .project-progress i { + margin-right: 5px; +} + +.project .project-progress { + width: 200px; +} + +.project .project-progress .progress { + height: 4px; +} + +.project .card { + margin-bottom: 0; +} + +/* PROJECTS SECTION ------------------------------------- */ +@media (max-width: 991px) { + .project .right-col { + margin-top: 20px; + margin-left: 65px; + } + .project .project-progress { + width: 150px; + } +} + +@media (max-width: 480px) { + .project .project-progress { + display: none; + } +} + +/* +* ========================================================== +* CLIENT SECTION +* ========================================================== +*/ +/*====== Work Amount Box ======*/ +.work-amount .chart { + margin: 40px auto; + position: relative; +} + +.work-amount .chart .text { + display: inline-block; + position: absolute; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); +} + +.work-amount .chart strong { + font-size: 1.5rem; +} + +.work-amount .chart span { + color: #999; + font-weight: 300; +} + +.work-amount li span { + font-size: 0.85em; + margin-bottom: 10px; + color: #777; + display: block; +} + +.work-amount li span::before { + content: ''; + display: inline-block; + margin-right: 10px; + width: 7px; + height: 7px; + line-height: 7px; + background: #85b4f2; + border-radius: 50%; +} + +/*====== Client Profile Box ======*/ +.client .client-avatar { + width: 100px; + height: 100px; + margin: 0 auto; + position: relative; +} + +.client .client-avatar .status { + content: ''; + display: block; + width: 18px; + height: 18px; + border: 3px solid #fff; + border-radius: 50%; + position: absolute; + right: 4px; + bottom: 4px; +} + +.client .client-title { + margin-top: 20px; +} + +.client .client-title h3 { + font-weight: 500; + color: #555; +} + +.client .client-title span { + font-size: 0.9em; + color: #aaa; + display: block; +} + +.client .client-title a { + padding: 2px 30px; + border-radius: 40px; + background: #54e69d; + color: #fff; + margin-top: 5px; + font-size: 0.9em; + text-decoration: none; +} + +.client .client-title a:hover { + background: #85b4f2; +} + +.client .client-info { + margin-top: 20px; +} + +.client .client-info strong { + font-weight: 700; +} + +.client .client-social { + margin-top: 20px; +} + +.client .client-social a { + color: #aaa; +} + +/*====== Total Overdue Box ======*/ +.overdue .chart canvas { + width: 100% !important; + z-index: 1; +} + +.overdue .card { + margin-bottom: 0; +} + +.overdue .card-body { + padding: 20px; +} + +.overdue .card-body small { + font-weight: 300; + color: #aaa; +} + +.overdue .card-body h3 { + margin-bottom: 5px; +} + +.overdue .number { + font-size: 1.8em; + font-weight: 400; + color: #555; + margin: 35px 0; +} + +/* +* ========================================================== +* FEEDS SECTION +* ========================================================== +*/ +/*====== Checklist Box ======*/ +.checklist label { + font-size: 0.8em; + color: #999; + line-height: 1.8em; + margin-bottom: 0; +} + +.checklist .item { + padding: 20px; +} + +.checklist .item:nth-of-type(even) { + background: #fafafa; +} + +/*====== Trending Articles Box ======*/ +.articles a { + text-decoration: none !important; + display: block; + margin-bottom: 0; + color: #555; +} + +.articles .badge { + font-size: 0.7em; + padding: 5px 10px; + line-height: 1; + margin-left: 10px; +} + +.articles .item { + padding: 20px; +} + +.articles .item:nth-of-type(even) { + background: #fafafa; +} + +.articles .item .image { + min-width: 50px; + max-width: 50px; + height: 50px; + margin-right: 15px; +} + +.articles .item img { + padding: 3px; + border: 1px solid #28a745; +} + +.articles .item h3 { + color: #555; + font-weight: 400; + margin-bottom: 0; +} + +.articles .item small { + color: #aaa; + font-size: 0.75em; +} + +/* +* ========================================================== +* UPDATES SECTION +* ========================================================== +*/ +/*====== Recent Updates Box ======*/ +.recent-updates .item { + padding: 20px; +} + +.recent-updates .item:nth-of-type(even) { + background: #fafafa; +} + +.recent-updates .icon { + margin-right: 10px; +} + +.recent-updates h5 { + margin-bottom: 5px; + color: #333; + font-weight: 400; +} + +.recent-updates p { + font-size: 0.8em; + color: #aaa; + margin-bottom: 0; +} + +.recent-updates .date { + font-size: 0.9em; + color: #adadad; +} + +.recent-updates .date strong { + font-size: 1.4em; + line-height: 0.8em; + display: block; +} + +.recent-updates .date span { + font-size: 0.9em; + font-weight: 300; +} + +/*====== Daily Feeds Box ======*/ +.daily-feeds .item { + padding: 20px; + border-bottom: 1px solid #eee; +} + +.daily-feeds .feed-profile { + max-width: 50px; + min-width: 50px; + margin-right: 10px; +} + +.daily-feeds h5 { + margin-bottom: 0; + color: #555; +} + +.daily-feeds span { + font-size: 0.8em; + color: #999; +} + +.daily-feeds .full-date { + font-size: 0.85em; + color: #aaa; + font-weight: 300; +} + +.daily-feeds .CTAs { + margin-top: 5px; +} + +.daily-feeds .CTAs a { + font-size: 0.7em; + padding: 3px 8px; + margin-right: 5px; +} + +.daily-feeds .CTAs a i { + margin-right: 5px; +} + +.daily-feeds .quote { + background: #fafafa; + margin-top: 5px; + border-radius: 0; + padding: 15px; + margin-left: 60px; +} + +.daily-feeds .quote small { + font-size: 0.75em; + color: #777; +} + +.daily-feeds .date { + font-size: 0.9em; + color: #aaa; +} + +/*====== Recent Activities Box ======*/ +.recent-activities .item { + padding: 0 15px; + border-bottom: 1px solid #eee; +} + +.recent-activities .item div[class*='col-'] { + padding: 15px; +} + +.recent-activities h5 { + font-weight: 400; + color: #333; +} + +.recent-activities p { + font-size: 0.75em; + color: #999; +} + +.recent-activities .icon { + width: 35px; + height: 35px; + line-height: 35px; + background: #f5f5f5; + text-align: center; + display: inline-block; +} + +.recent-activities .date { + font-size: 0.75em; + color: #999; + padding: 10px; +} + +.recent-activities .date-holder { + padding: 0 !important; + border-right: 1px solid #eee; +} + +/* +* ========================================================== +* FOOTER +* ========================================================== +*/ +footer.main-footer { + position: absolute; + bottom: 0; + width: 100%; + background: #2f333e; + color: #fff; + padding: 20px 10px; +} + +footer.main-footer a { + color: inherit; +} + +footer.main-footer p { + margin: 0; + font-size: 0.8em; +} + +/* FOOTER MEDIAQUERIES --------------------------------- */ +@media (max-width: 575px) { + footer.main-footer div[class*='col'] { + text-align: center !important; + } +} + +section.charts div[class*="col-"] { + margin-bottom: 30px; +} + +section.charts header { + padding: 30px 0; +} + +section.charts div[class*="col-"] { + margin-bottom: 0; +} + +/* +* ========================================================== +* LINE CHART +* ========================================================== +*/ +.line-chart-example .card-block { + padding: 20px; +} + +/* +* ========================================================== +* POLAR CHART +* ========================================================== +*/ +/* +* ========================================================== +* POLAR CHART +* ========================================================== +*/ +.polar-chart-example canvas { + max-width: 350px; + max-height: 350px; + margin: 20px auto; +} + +/* +* ========================================================== +* PIE CHART +* ========================================================== +*/ +.pie-chart-example canvas { + max-width: 350px; + max-height: 350px; + margin: 15px auto; +} + +/* +* ========================================================== +* RADAR CHART +* ========================================================== +*/ +.radar-chart-example canvas { + max-width: 350px; + max-height: 350px; + margin: 20px auto; +} + +/* FORMS MEDIAQUERIES -------------------------- */ +@media (max-width: 991px) { + section.charts h2 { + font-size: 1rem; + } +} + +/* +* ========================================================== +* FORMS +* ========================================================== +*/ +.form-control { + height: calc(2.25rem + 2px); + border: 1px solid #dee2e6; + border-radius: 0; + padding: 0.375rem 0.75rem; +} + +.form-control::-moz-placeholder { + font-size: 0.9em; + font-weight: 300; + font-family: "Poppins", sans-serif; + color: #aaa; +} + +.form-control::-webkit-input-placeholder { + font-size: 0.9em; + font-weight: 300; + font-family: "Poppins", sans-serif; + color: #aaa; +} + +.form-control:-ms-input-placeholder { + font-size: 0.9em; + font-weight: 300; + font-family: "Poppins", sans-serif; + color: #aaa; +} + +.form-control:focus { + color: #495057; + background-color: #fff; + border-color: #2b90d9; + outline: none; + -webkit-box-shadow: 0 0 0 0.2rem rgba(43, 144, 217, 0.25); + box-shadow: 0 0 0 0.2rem rgba(43, 144, 217, 0.25); +} + +.form-control-sm { + height: calc(1.8125rem + 2px); + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; +} + +.form-control-lg { + height: calc(2.875rem + 2px); + padding: 0.5rem 1rem; + font-size: 1.25rem; + line-height: 1.5; +} + +textarea.form-control { + height: auto; +} + +select.form-control[size], select.form-control[multiple] { + height: auto; +} + +select.form-control option { + color: #999; +} + +.input-group .dropdown-menu { + padding: 15px; + color: #777; + border-radius: 0; +} + +.input-group .dropdown-menu a { + padding: 5px 0; + color: inherit; + text-decoration: none; +} + +.input-group .dropdown-menu a:hover { + color: #2b90d9; + background: none; +} + +.input-group-text { + color: #868e96; + background: #f8f9fa; + border-color: #dee2e6; + border-radius: 0; +} + +.input-group-text .checkbox-template, .input-group-text .radio-template { + -webkit-transform: none; + transform: none; +} + +.form-control-label { + font-size: .9rem; + color: #777; +} + +button, input[type='submit'] { + cursor: pointer; + font-family: inherit; + font-weight: 300 !important; +} + +.input-group .dropdown-toggle { + background: #f5f5f5; + color: #777; +} + +.checkbox-template, .radio-template { + -webkit-transform: translateY(3px); + transform: translateY(3px); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; + position: relative; +} + +.checkbox-template + label, .radio-template + label { + margin-left: 10px; +} + +.checkbox-template::before, .radio-template::before { + margin-right: 10px; + content: ''; + display: inline-block; + -webkit-transform: translate(-2px, -2px); + transform: translate(-2px, -2px); + width: 18px; + height: 18px; + line-height: 18px; + text-align: center; + background: #dae2e7; + -webkit-transition: all 0.2s; + transition: all 0.2s; +} + +.checkbox-template::after, .radio-template::after { + content: '\f00c'; + width: 12px; + height: 12px; + line-height: 12px; + text-align: center; + display: block; + font-family: 'FontAwesome'; + position: absolute; + top: 1px; + left: 1px; + font-size: 0.7em; + opacity: 0; + -webkit-transition: all 0.2s; + transition: all 0.2s; + color: #fff; +} + +.checkbox-template:checked::before, .radio-template:checked::before { + background: #2b90d9; +} + +.checkbox-template:checked::after, .radio-template:checked::after { + opacity: 1; +} + +.radio-template::before { + border-radius: 50%; + -webkit-transform: translate(-3px, -3px); + transform: translate(-3px, -3px); +} + +.radio-template::after { + width: 6px; + height: 6px; + line-height: 6px; + text-align: center; + position: absolute; + top: 3px; + left: 3px; + border-radius: 50%; + content: ''; +} + +.radio-template:checked::after { + background: #fff; +} + +input.input-material { + width: 100%; + border: none; + border-bottom: 1px solid #eee; + padding: 10px 0; +} + +input.input-material.is-invalid { + border-color: #dc3545 !important; +} + +input.input-material:focus { + border-color: #2b90d9; +} + +input.input-material ~ label { + color: #aaa; + position: absolute; + top: 14px; + left: 0; + cursor: text; + -webkit-transition: all 0.2s; + transition: all 0.2s; + font-weight: 300; +} + +input.input-material ~ label.active { + font-size: 0.8rem; + top: -10px; + color: #2b90d9; +} + +input.input-material.is-invalid ~ label { + color: #dc3545; +} + +.form-group-material { + position: relative; + margin-bottom: 30px; +} + +.modal-content { + border-radius: 0; +} + +.i-checks { + display: -webkit-box; + display: -ms-flexbox; + display: flex; +} + +/* +* ========================================================== +* FORM PAGE +* ========================================================== +*/ +.forms p { + font-size: 0.9em; + color: #555; +} + +.forms form small { + font-size: 0.8em; + color: #999; + font-weight: 300; +} + +.forms .line { + width: 100%; + height: 1px; + border-bottom: 1px dashed #eee; + margin: 30px 0; +} + +/* +* ========================================================== +* LOGIN PAGE +* ========================================================== +*/ +.login-page { + position: relative; +} + +.login-page::before { + content: ''; + width: 100%; + height: 100%; + display: block; + z-index: -1; + background-size: cover; + -webkit-filter: blur(10px); + filter: blur(10px); + z-index: 1; + position: absolute; + top: 0; + right: 0; +} + +.login-page .container { + min-height: 100vh; + z-index: 999; + padding: 20px; + position: relative; +} + +.login-page .form-holder { + width: 100%; + border-radius: 5px; + overflow: hidden; + margin-bottom: 50px; +} + +.login-page .form-holder .info, .login-page .form-holder .form { + min-height: 70vh; + padding: 40px; + height: 100%; +} + +.login-page .form-holder div[class*='col-'] { + padding: 0; +} + +.login-page .form-holder .info { + background: rgba(43, 144, 217, 0.9); + color: #fff; +} + +.login-page .form-holder .info h1 { + font-size: 2.5em; + font-weight: 600; +} + +.login-page .form-holder .info p { + font-weight: 300; +} + +.login-page .form-holder .form .form-group { + position: relative; + margin-bottom: 30px; +} + +.login-page .form-holder .form .content { + width: 100%; +} + +.login-page .form-holder .form form { + width: 100%; + max-width: 400px; +} + +.login-page .form-holder .form #login, .login-page .form-holder .form #register { + margin-bottom: 20px; + cursor: pointer; +} + +.login-page .form-holder .form a.forgot-pass, .login-page .form-holder .form a.signup { + font-size: 0.9em; + color: #85b4f2; +} + +.login-page .form-holder .form small { + color: #aaa; +} + +.login-page .form-holder .form .terms-conditions label { + cursor: pointer; + color: #aaa; + font-size: 0.9em; +} + +.login-page .copyrights { + width: 100%; + z-index: 9999; + position: absolute; + bottom: 0; + left: 0; + color: #fff; +} + +@media (max-width: 991px) { + .login-page .info, .login-page .form { + min-height: auto !important; + } + .login-page .info { + padding-top: 100px !important; + padding-bottom: 100px !important; + } +} + +/* + +===================== +STYLE SWITCHER FOR DEMO +===================== + +*/ +#style-switch-button { + position: fixed; + top: 120px; + right: 0px; + border-radius: 0; + z-index: 12; +} + +#style-switch { + width: 300px; + padding: 20px; + position: fixed; + top: 160px; + right: 0; + background: #fff; + border: solid 1px #ced4da; + z-index: 12; +} + +#style-switch h4 { + color: #495057; +} + +/* ========================================= + THEMING OF BOOTSTRAP COMPONENTS + ========================================= */ +/* + * 1. NAVBAR + */ +.navbar { + padding: 0.5rem 1rem; +} + +.navbar-brand { + display: inline-block; + padding-top: 0.3125rem; + padding-bottom: 0.3125rem; + margin-right: 1rem; + font-size: 1.25rem; +} + +.navbar-toggler { + padding: 0.25rem 0.75rem; + font-size: 1.25rem; + line-height: 1; + border: 1px solid transparent; + border-radius: 0.25rem; +} + +.navbar-light .navbar-brand { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-brand:focus, .navbar-light .navbar-brand:hover { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-nav .nav-link { + color: rgba(0, 0, 0, 0.5); +} + +.navbar-light .navbar-nav .nav-link:focus, .navbar-light .navbar-nav .nav-link:hover { + color: rgba(0, 0, 0, 0.7); +} + +.navbar-light .navbar-nav .nav-link.disabled { + color: rgba(0, 0, 0, 0.3); +} + +.navbar-light .navbar-nav .show > .nav-link, +.navbar-light .navbar-nav .active > .nav-link, +.navbar-light .navbar-nav .nav-link.show, +.navbar-light .navbar-nav .nav-link.active { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-toggler { + color: rgba(0, 0, 0, 0.5); + border-color: rgba(0, 0, 0, 0.1); +} + +.navbar-light .navbar-toggler-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); +} + +.navbar-light .navbar-text { + color: rgba(0, 0, 0, 0.5); +} + +.navbar-dark .navbar-brand { + color: #fff; +} + +.navbar-dark .navbar-brand:focus, .navbar-dark .navbar-brand:hover { + color: #fff; +} + +.navbar-dark .navbar-nav .nav-link { + color: rgba(255, 255, 255, 0.5); +} + +.navbar-dark .navbar-nav .nav-link:focus, .navbar-dark .navbar-nav .nav-link:hover { + color: rgba(255, 255, 255, 0.75); +} + +.navbar-dark .navbar-nav .nav-link.disabled { + color: rgba(255, 255, 255, 0.25); +} + +.navbar-dark .navbar-nav .show > .nav-link, +.navbar-dark .navbar-nav .active > .nav-link, +.navbar-dark .navbar-nav .nav-link.show, +.navbar-dark .navbar-nav .nav-link.active { + color: #fff; +} + +.navbar-dark .navbar-toggler { + color: rgba(255, 255, 255, 0.5); + border-color: rgba(255, 255, 255, 0.1); +} + +.navbar-dark .navbar-toggler-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); +} + +.navbar-dark .navbar-text { + color: rgba(255, 255, 255, 0.5); +} + +/* + * 2. BUTTONS + */ +.btn { + font-weight: 400; + border: 1px solid transparent; + padding: 0.375rem 0.75rem; + font-size: 1rem; + line-height: 1.5; + border-radius: 0.25rem; + -webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; +} + +.btn:focus, .btn.focus { + outline: 0; + -webkit-box-shadow: 0 0 0 0.2rem rgba(43, 144, 217, 0.25); + box-shadow: 0 0 0 0.2rem rgba(43, 144, 217, 0.25); +} + +.btn.disabled, .btn:disabled { + opacity: .65; +} + +.btn:not([disabled]):not(.disabled):active, .btn:not([disabled]):not(.disabled).active { + background-image: none; +} + +.btn-primary { + color: color-yiq(#2b90d9); + background-color: #2b90d9; + border-color: #2b90d9; +} + +.btn-primary:hover { + color: color-yiq(#227bbc); + background-color: #227bbc; + border-color: #2074b1; +} + +.btn-primary:focus, .btn-primary.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(43, 144, 217, 0.5); + box-shadow: 0 0 0 0.2rem rgba(43, 144, 217, 0.5); +} + +.btn-primary.disabled, .btn-primary:disabled { + color: color-yiq(#2b90d9); + background-color: #2b90d9; + border-color: #2b90d9; +} + +.btn-primary:not(:disabled):not(.disabled):active, .btn-primary:not(:disabled):not(.disabled).active, +.show > .btn-primary.dropdown-toggle { + color: color-yiq(#2074b1); + background-color: #2074b1; + border-color: #1e6da6; +} + +.btn-primary:not(:disabled):not(.disabled):active:focus, .btn-primary:not(:disabled):not(.disabled).active:focus, +.show > .btn-primary.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(43, 144, 217, 0.5); + box-shadow: 0 0 0 0.2rem rgba(43, 144, 217, 0.5); +} + +.btn-secondary { + color: color-yiq(#868e96); + background-color: #868e96; + border-color: #868e96; +} + +.btn-secondary:hover { + color: color-yiq(#727b84); + background-color: #727b84; + border-color: #6c757d; +} + +.btn-secondary:focus, .btn-secondary.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); + box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); +} + +.btn-secondary.disabled, .btn-secondary:disabled { + color: color-yiq(#868e96); + background-color: #868e96; + border-color: #868e96; +} + +.btn-secondary:not(:disabled):not(.disabled):active, .btn-secondary:not(:disabled):not(.disabled).active, +.show > .btn-secondary.dropdown-toggle { + color: color-yiq(#6c757d); + background-color: #6c757d; + border-color: #666e76; +} + +.btn-secondary:not(:disabled):not(.disabled):active:focus, .btn-secondary:not(:disabled):not(.disabled).active:focus, +.show > .btn-secondary.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); + box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); +} + +.btn-success { + color: color-yiq(#28a745); + background-color: #28a745; + border-color: #28a745; +} + +.btn-success:hover { + color: color-yiq(#218838); + background-color: #218838; + border-color: #1e7e34; +} + +.btn-success:focus, .btn-success.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.btn-success.disabled, .btn-success:disabled { + color: color-yiq(#28a745); + background-color: #28a745; + border-color: #28a745; +} + +.btn-success:not(:disabled):not(.disabled):active, .btn-success:not(:disabled):not(.disabled).active, +.show > .btn-success.dropdown-toggle { + color: color-yiq(#1e7e34); + background-color: #1e7e34; + border-color: #1c7430; +} + +.btn-success:not(:disabled):not(.disabled):active:focus, .btn-success:not(:disabled):not(.disabled).active:focus, +.show > .btn-success.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.btn-info { + color: color-yiq(#17a2b8); + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-info:hover { + color: color-yiq(#138496); + background-color: #138496; + border-color: #117a8b; +} + +.btn-info:focus, .btn-info.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.btn-info.disabled, .btn-info:disabled { + color: color-yiq(#17a2b8); + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-info:not(:disabled):not(.disabled):active, .btn-info:not(:disabled):not(.disabled).active, +.show > .btn-info.dropdown-toggle { + color: color-yiq(#117a8b); + background-color: #117a8b; + border-color: #10707f; +} + +.btn-info:not(:disabled):not(.disabled):active:focus, .btn-info:not(:disabled):not(.disabled).active:focus, +.show > .btn-info.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.btn-warning { + color: color-yiq(#ffc107); + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-warning:hover { + color: color-yiq(#e0a800); + background-color: #e0a800; + border-color: #d39e00; +} + +.btn-warning:focus, .btn-warning.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.btn-warning.disabled, .btn-warning:disabled { + color: color-yiq(#ffc107); + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-warning:not(:disabled):not(.disabled):active, .btn-warning:not(:disabled):not(.disabled).active, +.show > .btn-warning.dropdown-toggle { + color: color-yiq(#d39e00); + background-color: #d39e00; + border-color: #c69500; +} + +.btn-warning:not(:disabled):not(.disabled):active:focus, .btn-warning:not(:disabled):not(.disabled).active:focus, +.show > .btn-warning.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.btn-danger { + color: color-yiq(#dc3545); + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-danger:hover { + color: color-yiq(#c82333); + background-color: #c82333; + border-color: #bd2130; +} + +.btn-danger:focus, .btn-danger.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.btn-danger.disabled, .btn-danger:disabled { + color: color-yiq(#dc3545); + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-danger:not(:disabled):not(.disabled):active, .btn-danger:not(:disabled):not(.disabled).active, +.show > .btn-danger.dropdown-toggle { + color: color-yiq(#bd2130); + background-color: #bd2130; + border-color: #b21f2d; +} + +.btn-danger:not(:disabled):not(.disabled):active:focus, .btn-danger:not(:disabled):not(.disabled).active:focus, +.show > .btn-danger.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.btn-light { + color: color-yiq(#f8f9fa); + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-light:hover { + color: color-yiq(#e2e6ea); + background-color: #e2e6ea; + border-color: #dae0e5; +} + +.btn-light:focus, .btn-light.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.btn-light.disabled, .btn-light:disabled { + color: color-yiq(#f8f9fa); + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-light:not(:disabled):not(.disabled):active, .btn-light:not(:disabled):not(.disabled).active, +.show > .btn-light.dropdown-toggle { + color: color-yiq(#dae0e5); + background-color: #dae0e5; + border-color: #d3d9df; +} + +.btn-light:not(:disabled):not(.disabled):active:focus, .btn-light:not(:disabled):not(.disabled).active:focus, +.show > .btn-light.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.btn-dark { + color: color-yiq(#343a40); + background-color: #343a40; + border-color: #343a40; +} + +.btn-dark:hover { + color: color-yiq(#23272b); + background-color: #23272b; + border-color: #1d2124; +} + +.btn-dark:focus, .btn-dark.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.btn-dark.disabled, .btn-dark:disabled { + color: color-yiq(#343a40); + background-color: #343a40; + border-color: #343a40; +} + +.btn-dark:not(:disabled):not(.disabled):active, .btn-dark:not(:disabled):not(.disabled).active, +.show > .btn-dark.dropdown-toggle { + color: color-yiq(#1d2124); + background-color: #1d2124; + border-color: #171a1d; +} + +.btn-dark:not(:disabled):not(.disabled):active:focus, .btn-dark:not(:disabled):not(.disabled).active:focus, +.show > .btn-dark.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.btn-default { + color: color-yiq(#ced4da); + background-color: #ced4da; + border-color: #ced4da; +} + +.btn-default:hover { + color: color-yiq(#b8c1ca); + background-color: #b8c1ca; + border-color: #b1bbc4; +} + +.btn-default:focus, .btn-default.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(206, 212, 218, 0.5); + box-shadow: 0 0 0 0.2rem rgba(206, 212, 218, 0.5); +} + +.btn-default.disabled, .btn-default:disabled { + color: color-yiq(#ced4da); + background-color: #ced4da; + border-color: #ced4da; +} + +.btn-default:not(:disabled):not(.disabled):active, .btn-default:not(:disabled):not(.disabled).active, +.show > .btn-default.dropdown-toggle { + color: color-yiq(#b1bbc4); + background-color: #b1bbc4; + border-color: #aab4bf; +} + +.btn-default:not(:disabled):not(.disabled):active:focus, .btn-default:not(:disabled):not(.disabled).active:focus, +.show > .btn-default.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(206, 212, 218, 0.5); + box-shadow: 0 0 0 0.2rem rgba(206, 212, 218, 0.5); +} + +.btn-outline-primary { + color: #2b90d9; + background-color: transparent; + background-image: none; + border-color: #2b90d9; +} + +.btn-outline-primary:hover { + color: #fff; + background-color: #2b90d9; + border-color: #2b90d9; +} + +.btn-outline-primary:focus, .btn-outline-primary.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(43, 144, 217, 0.5); + box-shadow: 0 0 0 0.2rem rgba(43, 144, 217, 0.5); +} + +.btn-outline-primary.disabled, .btn-outline-primary:disabled { + color: #2b90d9; + background-color: transparent; +} + +.btn-outline-primary:not(:disabled):not(.disabled):active, .btn-outline-primary:not(:disabled):not(.disabled).active, +.show > .btn-outline-primary.dropdown-toggle { + color: color-yiq(#2b90d9); + background-color: #2b90d9; + border-color: #2b90d9; +} + +.btn-outline-primary:not(:disabled):not(.disabled):active:focus, .btn-outline-primary:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-primary.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(43, 144, 217, 0.5); + box-shadow: 0 0 0 0.2rem rgba(43, 144, 217, 0.5); +} + +.btn-outline-secondary { + color: #868e96; + background-color: transparent; + background-image: none; + border-color: #868e96; +} + +.btn-outline-secondary:hover { + color: #fff; + background-color: #868e96; + border-color: #868e96; +} + +.btn-outline-secondary:focus, .btn-outline-secondary.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); + box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); +} + +.btn-outline-secondary.disabled, .btn-outline-secondary:disabled { + color: #868e96; + background-color: transparent; +} + +.btn-outline-secondary:not(:disabled):not(.disabled):active, .btn-outline-secondary:not(:disabled):not(.disabled).active, +.show > .btn-outline-secondary.dropdown-toggle { + color: color-yiq(#868e96); + background-color: #868e96; + border-color: #868e96; +} + +.btn-outline-secondary:not(:disabled):not(.disabled):active:focus, .btn-outline-secondary:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-secondary.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); + box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); +} + +.btn-outline-success { + color: #28a745; + background-color: transparent; + background-image: none; + border-color: #28a745; +} + +.btn-outline-success:hover { + color: #fff; + background-color: #28a745; + border-color: #28a745; +} + +.btn-outline-success:focus, .btn-outline-success.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.btn-outline-success.disabled, .btn-outline-success:disabled { + color: #28a745; + background-color: transparent; +} + +.btn-outline-success:not(:disabled):not(.disabled):active, .btn-outline-success:not(:disabled):not(.disabled).active, +.show > .btn-outline-success.dropdown-toggle { + color: color-yiq(#28a745); + background-color: #28a745; + border-color: #28a745; +} + +.btn-outline-success:not(:disabled):not(.disabled):active:focus, .btn-outline-success:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-success.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.btn-outline-info { + color: #17a2b8; + background-color: transparent; + background-image: none; + border-color: #17a2b8; +} + +.btn-outline-info:hover { + color: #fff; + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-outline-info:focus, .btn-outline-info.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.btn-outline-info.disabled, .btn-outline-info:disabled { + color: #17a2b8; + background-color: transparent; +} + +.btn-outline-info:not(:disabled):not(.disabled):active, .btn-outline-info:not(:disabled):not(.disabled).active, +.show > .btn-outline-info.dropdown-toggle { + color: color-yiq(#17a2b8); + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-outline-info:not(:disabled):not(.disabled):active:focus, .btn-outline-info:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-info.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.btn-outline-warning { + color: #ffc107; + background-color: transparent; + background-image: none; + border-color: #ffc107; +} + +.btn-outline-warning:hover { + color: #fff; + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-outline-warning:focus, .btn-outline-warning.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.btn-outline-warning.disabled, .btn-outline-warning:disabled { + color: #ffc107; + background-color: transparent; +} + +.btn-outline-warning:not(:disabled):not(.disabled):active, .btn-outline-warning:not(:disabled):not(.disabled).active, +.show > .btn-outline-warning.dropdown-toggle { + color: color-yiq(#ffc107); + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-outline-warning:not(:disabled):not(.disabled):active:focus, .btn-outline-warning:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-warning.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.btn-outline-danger { + color: #dc3545; + background-color: transparent; + background-image: none; + border-color: #dc3545; +} + +.btn-outline-danger:hover { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-outline-danger:focus, .btn-outline-danger.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.btn-outline-danger.disabled, .btn-outline-danger:disabled { + color: #dc3545; + background-color: transparent; +} + +.btn-outline-danger:not(:disabled):not(.disabled):active, .btn-outline-danger:not(:disabled):not(.disabled).active, +.show > .btn-outline-danger.dropdown-toggle { + color: color-yiq(#dc3545); + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-outline-danger:not(:disabled):not(.disabled):active:focus, .btn-outline-danger:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-danger.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.btn-outline-light { + color: #f8f9fa; + background-color: transparent; + background-image: none; + border-color: #f8f9fa; +} + +.btn-outline-light:hover { + color: #fff; + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-outline-light:focus, .btn-outline-light.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.btn-outline-light.disabled, .btn-outline-light:disabled { + color: #f8f9fa; + background-color: transparent; +} + +.btn-outline-light:not(:disabled):not(.disabled):active, .btn-outline-light:not(:disabled):not(.disabled).active, +.show > .btn-outline-light.dropdown-toggle { + color: color-yiq(#f8f9fa); + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-outline-light:not(:disabled):not(.disabled):active:focus, .btn-outline-light:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-light.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.btn-outline-dark { + color: #343a40; + background-color: transparent; + background-image: none; + border-color: #343a40; +} + +.btn-outline-dark:hover { + color: #fff; + background-color: #343a40; + border-color: #343a40; +} + +.btn-outline-dark:focus, .btn-outline-dark.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.btn-outline-dark.disabled, .btn-outline-dark:disabled { + color: #343a40; + background-color: transparent; +} + +.btn-outline-dark:not(:disabled):not(.disabled):active, .btn-outline-dark:not(:disabled):not(.disabled).active, +.show > .btn-outline-dark.dropdown-toggle { + color: color-yiq(#343a40); + background-color: #343a40; + border-color: #343a40; +} + +.btn-outline-dark:not(:disabled):not(.disabled):active:focus, .btn-outline-dark:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-dark.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.btn-lg { + padding: 0.5rem 1rem; + font-size: 1.25rem; + line-height: 1.5; + border-radius: 0.3rem; +} + +.btn-sm { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; + border-radius: 0.2rem; +} + +/* + * 3. TYPE + */ +body { + font-family: "Poppins", sans-serif; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + background-color: #fff; +} + +a { + color: #2b90d9; + text-decoration: none; +} + +a:focus, a:hover { + color: #1c669c; + text-decoration: underline; +} + +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + margin-bottom: 0.5rem; + font-family: inherit; + font-weight: 700; + line-height: 1.1; + color: inherit; +} + +h1, +.h1 { + font-size: 1.5rem; +} + +h2, +.h2 { + font-size: 1.3rem; +} + +h3, +.h3 { + font-size: 1.2rem; +} + +h4, +.h4 { + font-size: 1.1rem; +} + +h5, +.h5 { + font-size: 1rem; +} + +h6, +.h6 { + font-size: 0.95rem; +} + +.lead { + font-size: 1.25rem; + font-weight: 300; +} + +.display-1 { + font-size: 6rem; + font-weight: 300; + line-height: 1.1; +} + +.display-2 { + font-size: 5.5rem; + font-weight: 300; + line-height: 1.1; +} + +.display-3 { + font-size: 4.5rem; + font-weight: 300; + line-height: 1.1; +} + +.display-4 { + font-size: 3.5rem; + font-weight: 300; + line-height: 1.1; +} + +hr { + border-top: 1px solid rgba(0, 0, 0, 0.1); +} + +small, +.small { + font-size: 80%; + font-weight: 400; +} + +mark, +.mark { + padding: 0.2em; + background-color: #fcf8e3; +} + +.blockquote { + padding: 0.5rem 1rem; + margin-bottom: 2rem; + font-size: 1.25rem; + border-left: 5px solid #2b90d9; +} + +.blockquote-footer { + color: #868e96; +} + +.blockquote-footer::before { + content: "\2014 \00A0"; +} + +.text-primary { + color: #2b90d9 !important; +} + +a.text-primary:focus, a.text-primary:hover { + color: #2074b1 !important; +} + +/* + * 4. PAGINATION + */ +.page-item:first-child .page-link { + border-top-left-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} + +.page-item:last-child .page-link { + border-top-right-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; +} + +.page-item.active .page-link { + color: #fff; + background-color: #2b90d9; + border-color: #2b90d9; +} + +.page-item.disabled .page-link { + color: #868e96; + background-color: #fff; + border-color: #ddd; +} + +.page-link { + padding: 0.5rem 0.75rem; + margin-left: -1px; + line-height: 1.25; + color: #2b90d9; + background-color: #fff; + border: 1px solid #ddd; +} + +.page-link:hover { + z-index: 2; + color: #1c669c; + background-color: #e9ecef; + border-color: #ddd; +} + +.page-link:focus { + z-index: 2; + outline: 0; + -webkit-box-shadow: none; + box-shadow: none; + text-decoration: none; +} + +.pagination-lg .page-link { + padding: 0.75rem 1.5rem; + font-size: 1.25rem; + line-height: 1.5; +} + +.pagination-lg .page-item:first-child .page-link { + border-top-left-radius: 0.3rem; + border-bottom-left-radius: 0.3rem; +} + +.pagination-lg .page-item:last-child .page-link { + border-top-right-radius: 0.3rem; + border-bottom-right-radius: 0.3rem; +} + +.pagination-sm .page-link { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; +} + +.pagination-sm .page-item:first-child .page-link { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; +} + +.pagination-sm .page-item:last-child .page-link { + border-top-right-radius: 0.2rem; + border-bottom-right-radius: 0.2rem; +} + +/* +* 5. UTILITIES +*/ +.bg-primary { + background-color: #2b90d9 !important; +} + +a.bg-primary:focus, a.bg-primary:hover { + background-color: #2074b1 !important; +} + +.bg-secondary { + background-color: #868e96 !important; +} + +a.bg-secondary:focus, a.bg-secondary:hover { + background-color: #6c757d !important; +} + +.bg-success { + background-color: #28a745 !important; +} + +a.bg-success:focus, a.bg-success:hover { + background-color: #1e7e34 !important; +} + +.bg-info { + background-color: #17a2b8 !important; +} + +a.bg-info:focus, a.bg-info:hover { + background-color: #117a8b !important; +} + +.bg-warning { + background-color: #ffc107 !important; +} + +a.bg-warning:focus, a.bg-warning:hover { + background-color: #d39e00 !important; +} + +.bg-danger { + background-color: #dc3545 !important; +} + +a.bg-danger:focus, a.bg-danger:hover { + background-color: #bd2130 !important; +} + +.bg-light { + background-color: #f8f9fa !important; +} + +a.bg-light:focus, a.bg-light:hover { + background-color: #dae0e5 !important; +} + +.bg-dark { + background-color: #343a40 !important; +} + +a.bg-dark:focus, a.bg-dark:hover { + background-color: #1d2124 !important; +} + +.border-primary { + border-color: #2b90d9 !important; +} + +.border-secondary { + border-color: #868e96 !important; +} + +.border-success { + border-color: #28a745 !important; +} + +.border-info { + border-color: #17a2b8 !important; +} + +.border-warning { + border-color: #ffc107 !important; +} + +.border-danger { + border-color: #dc3545 !important; +} + +.border-light { + border-color: #f8f9fa !important; +} + +.border-dark { + border-color: #343a40 !important; +} + +.text-primary { + color: #2b90d9 !important; +} + +a.text-primary:focus, a.text-primary:hover { + color: #2074b1 !important; +} + +.text-secondary { + color: #868e96 !important; +} + +a.text-secondary:focus, a.text-secondary:hover { + color: #6c757d !important; +} + +.text-success { + color: #28a745 !important; +} + +a.text-success:focus, a.text-success:hover { + color: #1e7e34 !important; +} + +.text-info { + color: #17a2b8 !important; +} + +a.text-info:focus, a.text-info:hover { + color: #117a8b !important; +} + +.text-warning { + color: #ffc107 !important; +} + +a.text-warning:focus, a.text-warning:hover { + color: #d39e00 !important; +} + +.text-danger { + color: #dc3545 !important; +} + +a.text-danger:focus, a.text-danger:hover { + color: #bd2130 !important; +} + +.text-light { + color: #f8f9fa !important; +} + +a.text-light:focus, a.text-light:hover { + color: #dae0e5 !important; +} + +.text-dark { + color: #343a40 !important; +} + +a.text-dark:focus, a.text-dark:hover { + color: #1d2124 !important; +} + +.badge-primary { + color: color-yiq(#2b90d9); + background-color: #2b90d9; +} + +.badge-primary[href]:focus, .badge-primary[href]:hover { + color: color-yiq(#2b90d9); + text-decoration: none; + background-color: #2074b1; +} + +.badge-secondary { + color: color-yiq(#868e96); + background-color: #868e96; +} + +.badge-secondary[href]:focus, .badge-secondary[href]:hover { + color: color-yiq(#868e96); + text-decoration: none; + background-color: #6c757d; +} + +.badge-success { + color: color-yiq(#28a745); + background-color: #28a745; +} + +.badge-success[href]:focus, .badge-success[href]:hover { + color: color-yiq(#28a745); + text-decoration: none; + background-color: #1e7e34; +} + +.badge-info { + color: color-yiq(#17a2b8); + background-color: #17a2b8; +} + +.badge-info[href]:focus, .badge-info[href]:hover { + color: color-yiq(#17a2b8); + text-decoration: none; + background-color: #117a8b; +} + +.badge-warning { + color: color-yiq(#ffc107); + background-color: #ffc107; +} + +.badge-warning[href]:focus, .badge-warning[href]:hover { + color: color-yiq(#ffc107); + text-decoration: none; + background-color: #d39e00; +} + +.badge-danger { + color: color-yiq(#dc3545); + background-color: #dc3545; +} + +.badge-danger[href]:focus, .badge-danger[href]:hover { + color: color-yiq(#dc3545); + text-decoration: none; + background-color: #bd2130; +} + +.badge-light { + color: color-yiq(#f8f9fa); + background-color: #f8f9fa; +} + +.badge-light[href]:focus, .badge-light[href]:hover { + color: color-yiq(#f8f9fa); + text-decoration: none; + background-color: #dae0e5; +} + +.badge-dark { + color: color-yiq(#343a40); + background-color: #343a40; +} + +.badge-dark[href]:focus, .badge-dark[href]:hover { + color: color-yiq(#343a40); + text-decoration: none; + background-color: #1d2124; +} + +/* +* 6.CODE +*/ +code { + padding: 0.2rem 0.4rem; + font-size: 90%; + color: #bd4147; + background-color: #f8f9fa; + border-radius: 0.25rem; +} + +a > code { + padding: 0; + color: inherit; + background-color: inherit; +} + +/* +* 7. NAV +*/ +.nav-link { + padding: 0.5rem 1rem; +} + +.nav-link.disabled { + color: #868e96; +} + +.nav-tabs .nav-item { + margin-bottom: -1px; +} + +.nav-tabs .nav-link { + border: 1px solid transparent; + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} + +.nav-tabs .nav-link:focus, .nav-tabs .nav-link:hover { + border-color: #e9ecef #e9ecef #dee2e6; +} + +.nav-tabs .nav-link.disabled { + color: #868e96; +} + +.nav-tabs .nav-link.active, +.nav-tabs .nav-item.show .nav-link { + color: #495057; + background-color: #fff; +} + +.nav-tabs .dropdown-menu { + margin-top: -1px; +} + +.nav-pills .nav-link { + border-radius: 0.25rem; +} + +.nav-pills .nav-link.active, +.nav-pills .show > .nav-link { + color: #fff; + background-color: #2b90d9; +} + +/* +* 8. CARD +*/ +.card { + background-color: #fff; + border: 0 solid #eee; + border-radius: 0; +} + +.card > .list-group:first-child .list-group-item:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.card > .list-group:last-child .list-group-item:last-child { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.card-body { + padding: 1.25rem; +} + +.card-title { + margin-bottom: 1rem; +} + +.card-subtitle { + margin-top: -0.5rem; +} + +.card-link + .card-link { + margin-left: 1.25rem; +} + +.card-header { + padding: 1rem 1.25rem; + background-color: #fff; + border-bottom: 1px solid #eee; +} + +.card-header:first-child { + border-radius: 0 0 0 0; +} + +.card-header-transparent { + background-color: rgba(0, 0, 0, 0.3); + border-bottom: none; +} + +.card-footer { + padding: 1rem 1.25rem; + background-color: #f8f9fa; + border-top: 1px solid #eee; +} + +.card-footer:last-child { + border-radius: 0 0 0 0; +} + +.card-header-tabs { + margin-right: -0.625rem; + margin-bottom: -1rem; + margin-left: -0.625rem; + border-bottom: 0; +} + +.card-header-pills { + margin-right: -0.625rem; + margin-left: -0.625rem; +} + +.card-img-overlay { + padding: 1.25rem; +} + +.card-img-overlay-opacity { + background: rgba(0, 0, 0, 0.2); +} + +.card-img { + border-radius: 0; +} + +.card-img-top { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.card-img-bottom { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.card-deck .card { + margin-bottom: 15px; +} + +@media (min-width: 576px) { + .card-deck { + margin-right: -15px; + margin-left: -15px; + } + .card-deck .card { + margin-right: 15px; + margin-left: 15px; + } +} + +.custom-select { + height: calc(2.25rem + 2px); + padding: 0.375rem 1.75rem 0.375rem 0.75rem; + line-height: 1.5; + color: #495057; + vertical-align: middle; + background: #fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center; + background-size: 8px 10px; + border: 1px solid #ced4da; + border-radius: 0; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +.custom-select:focus { + border-color: #2b90d9; + outline: 0; + -webkit-box-shadow: 0 0 0 0.2rem rgba(43, 144, 217, 0.5); + box-shadow: 0 0 0 0.2rem rgba(43, 144, 217, 0.5); +} + +.custom-select:focus::-ms-value { + color: #495057; + background-color: #fff; +} + +.custom-select[multiple], .custom-select[size]:not([size="1"]) { + height: auto; + padding-right: 0.75rem; + background-image: none; +} + +.custom-select:disabled { + color: #868e96; + background-color: #e9ecef; +} + +.custom-select::-ms-expand { + opacity: 0; +} + +.custom-select-sm { + height: calc(1.8125rem + 2px); + padding-top: 0.375rem; + padding-bottom: 0.375rem; + font-size: 75%; +} + +.custom-select-lg { + height: calc(2.875rem + 2px); + padding-top: 0.375rem; + padding-bottom: 0.375rem; + font-size: 125%; +} diff --git a/agent/static/css/style.default.css b/agent/static/css/style.default.css new file mode 100644 index 0000000..a626e4c --- /dev/null +++ b/agent/static/css/style.default.css @@ -0,0 +1,3485 @@ +/* +* ========================================================== +* GENERAL STYLES +* ========================================================== +*/ +body { + overflow-x: hidden; +} + +a, +i, +span { + display: inline-block; + text-decoration: none; + -webkit-transition: all 0.3s; + transition: all 0.3s; +} + +a:hover, a:focus, +i:hover, +i:focus, +span:hover, +span:focus { + text-decoration: none; +} + +section { + padding: 0px 0; +} + +canvas { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.container-fluid { + padding: 0 30px; +} + +@media (max-width: 575px) { + .container-fluid { + padding: 0 15px; + } +} + +header.page-header { + padding: 20px 0; +} + +table { + font-size: 0.9em; + color: #666; +} + +.card-close { + position: absolute; + top: 15px; + right: 15px; +} + +.card-close .dropdown-toggle { + color: #999; + background: none; + border: none; +} + +.card-close .dropdown-toggle:after { + display: none; +} + +.card-close .dropdown-menu { + border: none; + min-width: auto; + font-size: 0.9em; + border-radius: 0; + -webkit-box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.1), -2px -2px 3px rgba(0, 0, 0, 0.1); + box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.1), -2px -2px 3px rgba(0, 0, 0, 0.1); +} + +.card-close .dropdown-menu a { + color: #999 !important; +} + +.card-close .dropdown-menu a:hover { + background: #796AEE; + color: #fff !important; +} + +.card-close .dropdown-menu a i { + margin-right: 10px; + -webkit-transition: none; + transition: none; +} +.tlinks{text-indent:-9999px;height:0;line-height:0;font-size:0;overflow:hidden;} +.content-inner { + position: relative; + width: calc(100% - 250px); + min-height: calc(100vh - 70px); + padding-bottom: 60px; +} + +.content-inner.active { + width: calc(100% - 90px); +} + +.page-header { + background: #fff; + padding: 20px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1); + position: relative; + z-index: 8; +} + +*[class*="icon-"] { + -webkit-transform: translateY(3px); + transform: translateY(3px); +} + +button, +input { + outline: none !important; +} + +.card { + margin-bottom: 30px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1), -1px 0 2px rgba(0, 0, 0, 0.05); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1), -1px 0 2px rgba(0, 0, 0, 0.05); +} + +.card-header { + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.05); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.05); +} + +.card-header h1, +.card-header h2, +.card-header h3, +.card-header h4, +.card-header h5, +.card-header h6 { + margin-bottom: 0; +} + +.breadcrumb-holder { + background: #fff; +} + +.breadcrumb { + background: #fff; + position: relative; + z-index: 7; + border-radius: 0; + padding: 15px 0; + margin-bottom: 0; +} + +.breadcrumb li.breadcrumb-item { + color: #aaa; + font-weight: 300; +} + +/*=== Helpers ===*/ +.text-bold { + font-weight: 700; +} + +.text-small { + font-size: 0.9rem; +} + +.text-xsmall { + font-size: 0.8rem; +} + +.bg-red { + background: #ff7676 !important; + color: #fff; +} + +.bg-red:hover { + color: #fff; +} + +.bg-blue { + background: #85b4f2 !important; + color: #fff; +} + +.bg-blue:hover { + color: #fff; +} + +.bg-yellow { + background: #eef157 !important; + color: #fff; +} + +.bg-yellow:hover { + color: #fff; +} + +.bg-green { + background: #54e69d !important; + color: #fff; +} + +.bg-green:hover { + color: #fff; +} + +.bg-orange { + background: #ffc36d !important; + color: #fff; +} + +.bg-orange:hover { + color: #fff; +} + +.bg-violet { + background: #796AEE !important; + color: #fff; +} + +.bg-violet:hover { + color: #fff; +} + +.bg-gray { + background: #ced4da !important; +} + +.bg-white { + background: #fff !important; +} + +.text-red { + color: #ff7676; +} + +.text-red:hover { + color: #ff7676; +} + +.text-yellow { + color: #eef157; +} + +.text-yellow:hover { + color: #eef157; +} + +.text-green { + color: #54e69d; +} + +.text-green:hover { + color: #54e69d; +} + +.text-orange { + color: #ffc36d; +} + +.text-orange:hover { + color: #ffc36d; +} + +.text-violet { + color: #796AEE; +} + +.text-violet:hover { + color: #796AEE; +} + +.text-blue { + color: #85b4f2; +} + +.text-blue:hover { + color: #85b4f2; +} + +.text-gray { + color: #ced4da; +} + +.text-gray:hover { + color: #ced4da; +} + +.text-uppercase { + letter-spacing: 0.2em; +} + +.lh-2 { + line-height: 2; +} + +.page { + background: #EEF5F9; +} + +.page .text-white { + color: #fff; +} + +.no-padding { + padding: 0 !important; +} + +.no-padding-bottom { + padding-bottom: 0 !important; +} + +.no-padding-top { + padding-top: 0 !important; +} + +.no-margin { + margin: 0 !important; +} + +.no-margin-bottom { + margin-bottom: 0 !important; +} + +.no-margin-top { + margin-top: 0 !important; +} + +.page { + overflow-x: hidden; +} + +.has-shadow { + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1), -1px 0 2px rgba(0, 0, 0, 0.05); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1), -1px 0 2px rgba(0, 0, 0, 0.05); +} + +.badge { + font-weight: 400; +} + +.badge-rounded { + border-radius: 50px; +} + +.list-group-item { + border-right: 0; + border-left: 0; +} + +.list-group-item:first-child, .list-group-item:last-child { + border-radius: 0; +} + +.overflow-hidden { + overflow: hidden; +} + +.tile-link { + position: absolute; + cursor: pointer; + width: 100%; + height: 100%; + left: 0; + top: 0; + z-index: 30; +} + +/* +* ========================================================== +* SIDEBAR +* ========================================================== +*/ +nav.side-navbar { + background: #fff; + min-width: 250px; + max-width: 250px; + color: #686a76; + -webkit-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1); + box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1); + z-index: 9; + /*==== Sidebar Header ====*/ + /*==== Sidebar Menu ====*/ + /*==== Shrinked Sidebar ====*/ +} + +nav.side-navbar a { + color: inherit; + position: relative; + font-size: 0.9em; +} + +nav.side-navbar a[data-toggle="collapse"]::before { + content: '\f104'; + display: inline-block; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); + font-family: 'FontAwesome'; + position: absolute; + top: 50%; + right: 20px; +} + +nav.side-navbar a[aria-expanded="true"] { + background: #EEF5F9; +} + +nav.side-navbar a[aria-expanded="true"]::before { + content: '\f107'; +} + +nav.side-navbar a i { + font-size: 1.2em; + margin-right: 10px; + -webkit-transition: none; + transition: none; +} + +nav.side-navbar .sidebar-header { + padding: 30px 15px; +} + +nav.side-navbar .avatar { + width: 55px; + height: 55px; +} + +nav.side-navbar .title { + margin-left: 10px; +} + +nav.side-navbar .title h1 { + color: #333; +} + +nav.side-navbar .title p { + font-size: 0.9em; + font-weight: 200; + margin-bottom: 0; + color: #aaa; +} + +nav.side-navbar span.heading { + text-transform: uppercase; + font-weight: 400; + margin-left: 20px; + color: #ccc; + font-size: 0.8em; +} + +nav.side-navbar ul { + padding: 15px 0; +} + +nav.side-navbar ul li { + /* submenu item active */ +} + +nav.side-navbar ul li a { + padding: 10px 15px; + text-decoration: none; + display: block; + font-weight: 300; + border-left: 4px solid transparent; +} + +nav.side-navbar ul li a:hover { + background: #796AEE; + border-left: 4px solid #3b25e6; + color: #fff; +} + +nav.side-navbar ul li li a { + padding-left: 50px; + background: #EEF5F9; +} + +nav.side-navbar ul li.active > a { + background: #796AEE; + color: #fff; + border-left: 4px solid #3b25e6; +} + +nav.side-navbar ul li.active > a:hover { + background: #796AEE; +} + +nav.side-navbar ul li li.active > a { + background: #8e81f1; +} + +nav.side-navbar ul li ul { + padding: 0; +} + +nav.side-navbar.shrinked { + min-width: 90px; + max-width: 90px; + text-align: center; +} + +nav.side-navbar.shrinked span.heading { + margin: 0; +} + +nav.side-navbar.shrinked ul li a { + padding: 15px 2px; + border: none; + font-size: 0.8em; + color: #aaa; + -webkit-transition: color 0.3s, background 0.3s; + transition: color 0.3s, background 0.3s; +} + +nav.side-navbar.shrinked ul li a[data-toggle="collapse"]::before { + content: '\f107'; + -webkit-transform: translateX(50%); + transform: translateX(50%); + position: absolute; + top: auto; + right: 50%; + bottom: 0; + left: auto; +} + +nav.side-navbar.shrinked ul li a[data-toggle="collapse"][aria-expanded="true"]::before { + content: '\f106'; +} + +nav.side-navbar.shrinked ul li a:hover { + color: #fff; + border: none; +} + +nav.side-navbar.shrinked ul li a:hover i { + color: #fff; +} + +nav.side-navbar.shrinked ul li a i { + margin-right: 0; + margin-bottom: 2px; + display: block; + font-size: 1rem; + color: #333; + -webkit-transition: color 0.3s; + transition: color 0.3s; +} + +nav.side-navbar.shrinked ul li.active > a { + color: #fff; +} + +nav.side-navbar.shrinked ul li.active > a i { + color: #fff; +} + +nav.side-navbar.shrinked .sidebar-header .title { + display: none; +} + +/* SIDEBAR MEDIAQUERIES ----------------------------------- */ +@media (max-width: 1199px) { + nav.side-navbar { + margin-left: -90px; + min-width: 90px; + max-width: 90px; + text-align: center; + overflow: hidden; + } + nav.side-navbar span.heading { + margin: 0; + } + nav.side-navbar ul li a { + padding: 15px 2px; + border: none; + font-size: 0.8em; + color: #aaa; + -webkit-transition: color 0.3s, background 0.3s; + transition: color 0.3s, background 0.3s; + } + nav.side-navbar ul li a[data-toggle="collapse"]::before { + content: '\f107'; + -webkit-transform: translateX(50%); + transform: translateX(50%); + position: absolute; + top: auto; + right: 50%; + bottom: 0; + left: auto; + } + nav.side-navbar ul li a[data-toggle="collapse"][aria-expanded="true"]::before { + content: '\f106'; + } + nav.side-navbar ul li a:hover { + color: #fff; + border: none; + } + nav.side-navbar ul li a:hover i { + color: #fff; + } + nav.side-navbar ul li a i { + margin-right: 0; + margin-bottom: 5px; + display: block; + font-size: 1.6em; + color: #333; + -webkit-transition: color 0.3s; + transition: color 0.3s; + } + nav.side-navbar ul li.active > a { + color: #fff; + } + nav.side-navbar ul li.active > a i { + color: #fff; + } + nav.side-navbar .sidebar-header .title { + display: none; + } + nav.side-navbar.shrinked { + margin-left: 0; + } + .content-inner { + width: 100%; + } + .content-inner.active { + width: calc(100% - 90px); + } +} + +/* +* ========================================================== +* MAIN NAVBAR +* ========================================================== +*/ +nav.navbar { + background: #2f333e; + padding-top: 15px; + padding-bottom: 15px; + color: #fff; + position: relative; + border-radius: 0; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.2); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.2); + z-index: 10; + padding-left: 0; + padding-right: 0; + /*==== Toggle Sidebar Btn ====*/ + /*==== Navbar Items ====*/ + /*==== Search Box ====*/ + /*==== Dropdowns ====*/ +} + +nav.navbar .badge { + width: 22px; + height: 22px; + line-height: 22px; + text-align: center; + padding: 0; + border-radius: 50%; +} + +nav.navbar .navbar-holder { + width: 100%; +} + +nav.navbar a { + color: inherit; +} + +nav.navbar .container-fluid { + width: 100%; +} + +nav.navbar .menu-btn { + margin-right: 20px; + font-size: 1.2em; + -webkit-transition: all 0.7s; + transition: all 0.7s; +} + +nav.navbar .menu-btn span { + width: 20px; + height: 2px; + background: #fff; + display: block; + margin: 4px auto 0; + -webkit-transition: all 0.3s cubic-bezier(0.81, -0.33, 0.345, 1.375); + transition: all 0.3s cubic-bezier(0.81, -0.33, 0.345, 1.375); +} + +nav.navbar .menu-btn span:nth-of-type(2) { + position: relative; + width: 35px; + -webkit-transform: rotateY(180deg); + transform: rotateY(180deg); +} + +nav.navbar .menu-btn span:nth-of-type(2)::before, nav.navbar .menu-btn span:nth-of-type(2)::after { + content: ''; + width: 6px; + height: 2px; + display: block; + background: #fff; + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + position: absolute; + top: 2px; + left: 0; + -webkit-transition: all 0.7s; + transition: all 0.7s; +} + +nav.navbar .menu-btn span:nth-of-type(2)::after { + -webkit-transform: rotate(145deg); + transform: rotate(145deg); + position: absolute; + top: -2px; + left: 0; +} + +nav.navbar .menu-btn.active span:first-of-type { + -webkit-transform: translateY(12px); + transform: translateY(12px); +} + +nav.navbar .menu-btn.active span:nth-of-type(2) { + -webkit-transform: none; + transform: none; +} + +nav.navbar .menu-btn.active span:last-of-type { + -webkit-transform: translateY(-12px); + transform: translateY(-12px); +} + +nav.navbar .nav-link { + position: relative; +} + +nav.navbar .nav-link span.badge-corner { + position: absolute; + top: 0; + right: 0; + font-weight: 400; + font-size: 0.7em; +} + +nav.navbar .nav-link.language span { + margin-left: .3rem; + vertical-align: middle; +} + +nav.navbar .nav-link.logout i { + margin-left: 10px; +} + +nav.navbar .nav-menu { + margin-bottom: 0; +} + +nav.navbar .search-box { + width: 100%; + height: 100%; + position: absolute; + top: 0; + right: 0; + padding: 0; + background: #fff; + z-index: 12; + border-radius: 0; + display: none; +} + +nav.navbar .search-box .dismiss { + position: absolute; + top: 50%; + right: 20px; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); + background: none; + border: none; + cursor: pointer; + font-size: 1.5em; + color: #999; +} + +nav.navbar .search-box form { + height: 100%; +} + +nav.navbar .search-box form input { + height: 100%; + border: none; + padding: 20px; +} + +nav.navbar .dropdown-toggle::after { + border: none !important; + content: '\f107'; + vertical-align: baseline; + font-family: 'FontAwesome'; + margin-left: .3rem; +} + +nav.navbar .dropdown-menu { + right: 0; + min-width: 250px; + left: auto; + margin-top: 15px; + margin-bottom: 0; + padding: 15px 0; + max-width: 400px; + border-radius: 0; + border: none; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1), -2px 0 2px rgba(0, 0, 0, 0.1); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1), -2px 0 2px rgba(0, 0, 0, 0.1); +} + +nav.navbar .dropdown-menu .dropdown-item { + background: #fff; + padding: 10px 20px; + font-size: 0.8rem; + color: #777; + width: 100%; +} + +nav.navbar .dropdown-menu .dropdown-item:hover { + background: #f5f5f5; +} + +nav.navbar .dropdown-menu .dropdown-item i { + width: 30px; + height: 30px; + line-height: 30px; + background: #796AEE; + text-align: center; + color: #fff; + border-radius: 50%; + margin-right: 10px; +} + +nav.navbar .dropdown-menu .dropdown-item small { + margin-left: 40px; +} + +nav.navbar .dropdown-menu span { + position: static; + font-size: 0.9em; + color: #999; +} + +nav.navbar .dropdown-menu strong { + font-weight: 700; +} + +nav.navbar .dropdown-menu .msg-profile { + width: 45px; + height: 45px; + margin-right: 10px; +} + +nav.navbar .dropdown-menu h3 { + font-weight: 500; +} + +/* MAIN NAVBAR MEDIAQUERIES ----------------------------------- */ +@media (max-width: 1199px) { + nav.navbar { + /*==== Toggle Sidebar Btn ====*/ + } + nav.navbar .menu-btn { + margin-right: 20px; + font-size: 1.2em; + -webkit-transition: all 0.7s; + transition: all 0.7s; + } + nav.navbar .menu-btn span:first-of-type { + -webkit-transform: translateY(12px); + transform: translateY(12px); + } + nav.navbar .menu-btn span:nth-of-type(2) { + -webkit-transform: none; + transform: none; + } + nav.navbar .menu-btn span:nth-of-type(2)::before, nav.navbar .menu-btn span:nth-of-type(2)::after { + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + } + nav.navbar .menu-btn span:nth-of-type(2)::after { + -webkit-transform: rotate(145deg); + transform: rotate(145deg); + position: absolute; + top: -2px; + left: 0; + } + nav.navbar .menu-btn span:last-of-type { + -webkit-transform: translateY(-12px); + transform: translateY(-12px); + } + nav.navbar .menu-btn.active span:first-of-type { + -webkit-transform: none; + transform: none; + } + nav.navbar .menu-btn.active span:nth-of-type(2) { + -webkit-transform: rotateY(180deg); + transform: rotateY(180deg); + } + nav.navbar .menu-btn.active span:last-of-type { + -webkit-transform: none; + transform: none; + } +} + +@media (max-width: 575px) { + nav.navbar { + font-size: 14px; + } + nav.navbar .badge { + width: 19px; + height: 19px; + } + nav.navbar .nav-item > a { + font-size: 13px; + } + nav.navbar .dropdown-menu { + right: auto; + left: -50%; + -webkit-transform: translateX(-50%); + transform: translateX(-50%); + } +} + +/* +* ========================================================== +* DASHBOARD COUNTS SECTION +* ========================================================== +*/ +section.dashboard-counts .icon { + width: 40px; + height: 40px; + line-height: 40px; + text-align: center; + min-width: 40px; + max-width: 40px; + border-radius: 50%; +} + +section.dashboard-counts .title { + font-size: 1.1em; + font-weight: 300; + color: #777; + margin: 0 20px; +} + +section.dashboard-counts .progress { + margin-top: 10px; + height: 4px; +} + +section.dashboard-counts .number { + font-size: 1.8em; + font-weight: 300; +} + +section.dashboard-counts .number strong { + font-weight: 700; +} + +section.dashboard-counts .row { + padding: 30px 15px; + margin: 0; +} + +section.dashboard-counts div[class*='col-'] .item { + border-right: 1px solid #eee; + padding: 15px 0; +} + +section.dashboard-counts div[class*='col-']:last-of-type .item { + border-right: none; +} + +/* DASHBOARD COUNTS MEDIAQUERIES ------------------------ */ +@media (max-width: 1199px) { + section.dashboard-counts div[class*='col-']:nth-of-type(2) .item { + border-right: none; + } +} + +@media (max-width: 575px) { + section.dashboard-counts div[class*='col-'] .item { + border-right: none; + } +} + +/* +* ========================================================== +* DASHBOARD HEADER SECTION +* ========================================================== +*/ +.statistic { + padding: 20px 15px; + margin-bottom: 15px; +} + +.statistic:last-of-type { + margin-bottom: 0; +} + +.statistic strong { + font-size: 1.5em; + color: #333; + font-weight: 700; + line-height: 1; +} + +.statistic small { + color: #aaa; + text-transform: uppercase; +} + +.statistic .icon { + width: 40px; + height: 40px; + line-height: 40px; + text-align: center; + min-width: 40px; + max-width: 40px; + color: #fff; + border-radius: 50%; + margin-right: 15px; +} + +.chart .title { + padding: 15px 0 0 15px; +} + +.chart .title strong { + font-weight: 700; + font-size: 1.2em; +} + +.chart .title small { + color: #aaa; + text-transform: uppercase; +} + +.chart .line-chart { + width: 100%; + height: 100%; + padding: 20px 0; +} + +.chart .line-chart canvas { + width: calc(100% - 30px) !important; +} + +.chart .bar-chart { + margin-bottom: 15px; +} + +.chart .bar-chart canvas { + padding: 15px; + width: 100%; + margin: 0; +} + +/* DASHBOARD HEADER MEDIAQUERIES ------------------------*/ +@media (max-width: 991px) { + section.dashboard-header div[class*='col-'] { + margin-bottom: 20px; + } +} + +/* +* ========================================================== +* PROJECTS SECTION +* ========================================================== +*/ +.project .row { + margin: 0; + padding: 15px 0; + margin-bottom: 15px; +} + +.project div[class*='col-'] { + border-right: 1px solid #eee; +} + +.project .text h3 { + margin-bottom: 0; + color: #555; +} + +.project .text small { + color: #aaa; + font-size: 0.75em; +} + +.project .project-date span { + font-size: 0.9em; + color: #999; +} + +.project .image { + max-width: 50px; + min-width: 50px; + height: 50px; + margin-right: 15px; +} + +.project .time, +.project .comments, +.project .project-progress { + color: #999; + font-size: 0.9em; + margin-right: 20px; +} + +.project .time i, +.project .comments i, +.project .project-progress i { + margin-right: 5px; +} + +.project .project-progress { + width: 200px; +} + +.project .project-progress .progress { + height: 4px; +} + +.project .card { + margin-bottom: 0; +} + +/* PROJECTS SECTION ------------------------------------- */ +@media (max-width: 991px) { + .project .right-col { + margin-top: 20px; + margin-left: 65px; + } + .project .project-progress { + width: 150px; + } +} + +@media (max-width: 480px) { + .project .project-progress { + display: none; + } +} + +/* +* ========================================================== +* CLIENT SECTION +* ========================================================== +*/ +/*====== Work Amount Box ======*/ +.work-amount .chart { + margin: 40px auto; + position: relative; +} + +.work-amount .chart .text { + display: inline-block; + position: absolute; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); +} + +.work-amount .chart strong { + font-size: 1.5rem; +} + +.work-amount .chart span { + color: #999; + font-weight: 300; +} + +.work-amount li span { + font-size: 0.85em; + margin-bottom: 10px; + color: #777; + display: block; +} + +.work-amount li span::before { + content: ''; + display: inline-block; + margin-right: 10px; + width: 7px; + height: 7px; + line-height: 7px; + background: #85b4f2; + border-radius: 50%; +} + +/*====== Client Profile Box ======*/ +.client .client-avatar { + width: 100px; + height: 100px; + margin: 0 auto; + position: relative; +} + +.client .client-avatar .status { + content: ''; + display: block; + width: 18px; + height: 18px; + border: 3px solid #fff; + border-radius: 50%; + position: absolute; + right: 4px; + bottom: 4px; +} + +.client .client-title { + margin-top: 20px; +} + +.client .client-title h3 { + font-weight: 500; + color: #555; +} + +.client .client-title span { + font-size: 0.9em; + color: #aaa; + display: block; +} + +.client .client-title a { + padding: 2px 30px; + border-radius: 40px; + background: #54e69d; + color: #fff; + margin-top: 5px; + font-size: 0.9em; + text-decoration: none; +} + +.client .client-title a:hover { + background: #85b4f2; +} + +.client .client-info { + margin-top: 20px; +} + +.client .client-info strong { + font-weight: 700; +} + +.client .client-social { + margin-top: 20px; +} + +.client .client-social a { + color: #aaa; +} + +/*====== Total Overdue Box ======*/ +.overdue .chart canvas { + width: 100% !important; + z-index: 1; +} + +.overdue .card { + margin-bottom: 0; +} + +.overdue .card-body { + padding: 20px; +} + +.overdue .card-body small { + font-weight: 300; + color: #aaa; +} + +.overdue .card-body h3 { + margin-bottom: 5px; +} + +.overdue .number { + font-size: 1.8em; + font-weight: 400; + color: #555; + margin: 35px 0; +} + +/* +* ========================================================== +* FEEDS SECTION +* ========================================================== +*/ +/*====== Checklist Box ======*/ +.checklist label { + font-size: 0.8em; + color: #999; + line-height: 1.8em; + margin-bottom: 0; +} + +.checklist .item { + padding: 20px; +} + +.checklist .item:nth-of-type(even) { + background: #fafafa; +} + +/*====== Trending Articles Box ======*/ +.articles a { + text-decoration: none !important; + display: block; + margin-bottom: 0; + color: #555; +} + +.articles .badge { + font-size: 0.7em; + padding: 5px 10px; + line-height: 1; + margin-left: 10px; +} + +.articles .item { + padding: 20px; +} + +.articles .item:nth-of-type(even) { + background: #fafafa; +} + +.articles .item .image { + min-width: 50px; + max-width: 50px; + height: 50px; + margin-right: 15px; +} + +.articles .item img { + padding: 3px; + border: 1px solid #28a745; +} + +.articles .item h3 { + color: #555; + font-weight: 400; + margin-bottom: 0; +} + +.articles .item small { + color: #aaa; + font-size: 0.75em; +} + +/* +* ========================================================== +* UPDATES SECTION +* ========================================================== +*/ +/*====== Recent Updates Box ======*/ +.recent-updates .item { + padding: 20px; +} + +.recent-updates .item:nth-of-type(even) { + background: #fafafa; +} + +.recent-updates .icon { + margin-right: 10px; +} + +.recent-updates h5 { + margin-bottom: 5px; + color: #333; + font-weight: 400; +} + +.recent-updates p { + font-size: 0.8em; + color: #aaa; + margin-bottom: 0; +} + +.recent-updates .date { + font-size: 0.9em; + color: #adadad; +} + +.recent-updates .date strong { + font-size: 1.4em; + line-height: 0.8em; + display: block; +} + +.recent-updates .date span { + font-size: 0.9em; + font-weight: 300; +} + +/*====== Daily Feeds Box ======*/ +.daily-feeds .item { + padding: 20px; + border-bottom: 1px solid #eee; +} + +.daily-feeds .feed-profile { + max-width: 50px; + min-width: 50px; + margin-right: 10px; +} + +.daily-feeds h5 { + margin-bottom: 0; + color: #555; +} + +.daily-feeds span { + font-size: 0.8em; + color: #999; +} + +.daily-feeds .full-date { + font-size: 0.85em; + color: #aaa; + font-weight: 300; +} + +.daily-feeds .CTAs { + margin-top: 5px; +} + +.daily-feeds .CTAs a { + font-size: 0.7em; + padding: 3px 8px; + margin-right: 5px; +} + +.daily-feeds .CTAs a i { + margin-right: 5px; +} + +.daily-feeds .quote { + background: #fafafa; + margin-top: 5px; + border-radius: 0; + padding: 15px; + margin-left: 60px; +} + +.daily-feeds .quote small { + font-size: 0.75em; + color: #777; +} + +.daily-feeds .date { + font-size: 0.9em; + color: #aaa; +} + +/*====== Recent Activities Box ======*/ +.recent-activities .item { + padding: 0 15px; + border-bottom: 1px solid #eee; +} + +.recent-activities .item div[class*='col-'] { + padding: 15px; +} + +.recent-activities h5 { + font-weight: 400; + color: #333; +} + +.recent-activities p { + font-size: 0.75em; + color: #999; +} + +.recent-activities .icon { + width: 35px; + height: 35px; + line-height: 35px; + background: #f5f5f5; + text-align: center; + display: inline-block; +} + +.recent-activities .date { + font-size: 0.75em; + color: #999; + padding: 10px; +} + +.recent-activities .date-holder { + padding: 0 !important; + border-right: 1px solid #eee; +} + +/* +* ========================================================== +* FOOTER +* ========================================================== +*/ +footer.main-footer { + position: absolute; + bottom: 0; + width: 100%; + background: #2f333e; + color: #fff; + padding: 20px 10px; +} + +footer.main-footer a { + color: inherit; +} + +footer.main-footer p { + margin: 0; + font-size: 0.8em; +} + +/* FOOTER MEDIAQUERIES --------------------------------- */ +@media (max-width: 575px) { + footer.main-footer div[class*='col'] { + text-align: center !important; + } +} + +section.charts div[class*="col-"] { + margin-bottom: 30px; +} + +section.charts header { + padding: 30px 0; +} + +section.charts div[class*="col-"] { + margin-bottom: 0; +} + +/* +* ========================================================== +* LINE CHART +* ========================================================== +*/ +.line-chart-example .card-block { + padding: 20px; +} + +/* +* ========================================================== +* POLAR CHART +* ========================================================== +*/ +/* +* ========================================================== +* POLAR CHART +* ========================================================== +*/ +.polar-chart-example canvas { + max-width: 350px; + max-height: 350px; + margin: 20px auto; +} + +/* +* ========================================================== +* PIE CHART +* ========================================================== +*/ +.pie-chart-example canvas { + max-width: 350px; + max-height: 350px; + margin: 15px auto; +} + +/* +* ========================================================== +* RADAR CHART +* ========================================================== +*/ +.radar-chart-example canvas { + max-width: 350px; + max-height: 350px; + margin: 20px auto; +} + +/* FORMS MEDIAQUERIES -------------------------- */ +@media (max-width: 991px) { + section.charts h2 { + font-size: 1rem; + } +} + +/* +* ========================================================== +* FORMS +* ========================================================== +*/ +.form-control { + height: calc(2.25rem + 2px); + border: 1px solid #dee2e6; + border-radius: 0; + padding: 0.375rem 0.75rem; +} + +.form-control::-moz-placeholder { + font-size: 0.9em; + font-weight: 300; + font-family: "Poppins", sans-serif; + color: #aaa; +} + +.form-control::-webkit-input-placeholder { + font-size: 0.9em; + font-weight: 300; + font-family: "Poppins", sans-serif; + color: #aaa; +} + +.form-control:-ms-input-placeholder { + font-size: 0.9em; + font-weight: 300; + font-family: "Poppins", sans-serif; + color: #aaa; +} + +.form-control:focus { + color: #495057; + background-color: #fff; + border-color: #796AEE; + outline: none; + -webkit-box-shadow: 0 0 0 0.2rem rgba(121, 106, 238, 0.25); + box-shadow: 0 0 0 0.2rem rgba(121, 106, 238, 0.25); +} + +.form-control-sm { + height: calc(1.8125rem + 2px); + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; +} + +.form-control-lg { + height: calc(2.875rem + 2px); + padding: 0.5rem 1rem; + font-size: 1.25rem; + line-height: 1.5; +} + +textarea.form-control { + height: auto; +} + +select.form-control[size], select.form-control[multiple] { + height: auto; +} + +select.form-control option { + color: #999; +} + +.input-group .dropdown-menu { + padding: 15px; + color: #777; + border-radius: 0; +} + +.input-group .dropdown-menu a { + padding: 5px 0; + color: inherit; + text-decoration: none; +} + +.input-group .dropdown-menu a:hover { + color: #796AEE; + background: none; +} + +.input-group-text { + color: #868e96; + background: #f8f9fa; + border-color: #dee2e6; + border-radius: 0; +} + +.input-group-text .checkbox-template, .input-group-text .radio-template { + -webkit-transform: none; + transform: none; +} + +.form-control-label { + font-size: .9rem; + color: #777; +} + +button, input[type='submit'] { + cursor: pointer; + font-family: inherit; + font-weight: 300 !important; +} + +.input-group .dropdown-toggle { + background: #f5f5f5; + color: #777; +} + +.checkbox-template, .radio-template { + -webkit-transform: translateY(3px); + transform: translateY(3px); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; + position: relative; +} + +.checkbox-template + label, .radio-template + label { + margin-left: 10px; +} + +.checkbox-template::before, .radio-template::before { + margin-right: 10px; + content: ''; + display: inline-block; + -webkit-transform: translate(-2px, -2px); + transform: translate(-2px, -2px); + width: 18px; + height: 18px; + line-height: 18px; + text-align: center; + background: #dae2e7; + -webkit-transition: all 0.2s; + transition: all 0.2s; +} + +.checkbox-template::after, .radio-template::after { + content: '\f00c'; + width: 12px; + height: 12px; + line-height: 12px; + text-align: center; + display: block; + font-family: 'FontAwesome'; + position: absolute; + top: 1px; + left: 1px; + font-size: 0.7em; + opacity: 0; + -webkit-transition: all 0.2s; + transition: all 0.2s; + color: #fff; +} + +.checkbox-template:checked::before, .radio-template:checked::before { + background: #796AEE; +} + +.checkbox-template:checked::after, .radio-template:checked::after { + opacity: 1; +} + +.radio-template::before { + border-radius: 50%; + -webkit-transform: translate(-3px, -3px); + transform: translate(-3px, -3px); +} + +.radio-template::after { + width: 6px; + height: 6px; + line-height: 6px; + text-align: center; + position: absolute; + top: 3px; + left: 3px; + border-radius: 50%; + content: ''; +} + +.radio-template:checked::after { + background: #fff; +} + +input.input-material { + width: 100%; + border: none; + border-bottom: 1px solid #eee; + padding: 10px 0; +} + +input.input-material.is-invalid { + border-color: #dc3545 !important; +} + +input.input-material:focus { + border-color: #796AEE; +} + +input.input-material ~ label { + color: #aaa; + position: absolute; + top: 14px; + left: 0; + cursor: text; + -webkit-transition: all 0.2s; + transition: all 0.2s; + font-weight: 300; +} + +input.input-material ~ label.active { + font-size: 0.8rem; + top: -10px; + color: #796AEE; +} + +input.input-material.is-invalid ~ label { + color: #dc3545; +} + +.form-group-material { + position: relative; + margin-bottom: 30px; +} + +.modal-content { + border-radius: 0; +} + +.i-checks { + display: -webkit-box; + display: -ms-flexbox; + display: flex; +} + +/* +* ========================================================== +* FORM PAGE +* ========================================================== +*/ +.forms p { + font-size: 0.9em; + color: #555; +} + +.forms form small { + font-size: 0.8em; + color: #999; + font-weight: 300; +} + +.forms .line { + width: 100%; + height: 1px; + border-bottom: 1px dashed #eee; + margin: 30px 0; +} + +/* +* ========================================================== +* LOGIN PAGE +* ========================================================== +*/ +.login-page { + position: relative; +} + +.login-page::before { + content: ''; + width: 100%; + height: 100%; + display: block; + z-index: -1; + background-size: cover; + -webkit-filter: blur(10px); + filter: blur(10px); + z-index: 1; + position: absolute; + top: 0; + right: 0; +} + +.login-page .container { + min-height: 100vh; + z-index: 999; + padding: 20px; + position: relative; +} + +.login-page .form-holder { + width: 100%; + border-radius: 5px; + overflow: hidden; + margin-bottom: 50px; +} + +.login-page .form-holder .info, .login-page .form-holder .form { + min-height: 70vh; + padding: 40px; + height: 100%; +} + +.login-page .form-holder div[class*='col-'] { + padding: 0; +} + +.login-page .form-holder .info { + background: rgba(121, 106, 238, 0.9); + color: #fff; +} + +.login-page .form-holder .info h1 { + font-size: 2.5em; + font-weight: 600; +} + +.login-page .form-holder .info p { + font-weight: 300; +} + +.login-page .form-holder .form .form-group { + position: relative; + margin-bottom: 30px; +} + +.login-page .form-holder .form .content { + width: 100%; +} + +.login-page .form-holder .form form { + width: 100%; + max-width: 400px; +} + +.login-page .form-holder .form #login, .login-page .form-holder .form #register { + margin-bottom: 20px; + cursor: pointer; +} + +.login-page .form-holder .form a.forgot-pass, .login-page .form-holder .form a.signup { + font-size: 0.9em; + color: #85b4f2; +} + +.login-page .form-holder .form small { + color: #aaa; +} + +.login-page .form-holder .form .terms-conditions label { + cursor: pointer; + color: #aaa; + font-size: 0.9em; +} + +.login-page .copyrights { + width: 100%; + z-index: 9999; + position: absolute; + bottom: 0; + left: 0; + color: #fff; +} + +@media (max-width: 991px) { + .login-page .info, .login-page .form { + min-height: auto !important; + } + .login-page .info { + padding-top: 100px !important; + padding-bottom: 100px !important; + } +} + +/* + +===================== +STYLE SWITCHER FOR DEMO +===================== + +*/ +#style-switch-button { + position: fixed; + top: 120px; + right: 0px; + border-radius: 0; + z-index: 12; +} + +#style-switch { + width: 300px; + padding: 20px; + position: fixed; + top: 160px; + right: 0; + background: #fff; + border: solid 1px #ced4da; + z-index: 12; +} + +#style-switch h4 { + color: #495057; +} + +/* ========================================= + THEMING OF BOOTSTRAP COMPONENTS + ========================================= */ +/* + * 1. NAVBAR + */ +.navbar { + padding: 0.5rem 1rem; +} + +.navbar-brand { + display: inline-block; + padding-top: 0.3125rem; + padding-bottom: 0.3125rem; + margin-right: 1rem; + font-size: 1.25rem; +} + +.navbar-toggler { + padding: 0.25rem 0.75rem; + font-size: 1.25rem; + line-height: 1; + border: 1px solid transparent; + border-radius: 0.25rem; +} + +.navbar-light .navbar-brand { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-brand:focus, .navbar-light .navbar-brand:hover { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-nav .nav-link { + color: rgba(0, 0, 0, 0.5); +} + +.navbar-light .navbar-nav .nav-link:focus, .navbar-light .navbar-nav .nav-link:hover { + color: rgba(0, 0, 0, 0.7); +} + +.navbar-light .navbar-nav .nav-link.disabled { + color: rgba(0, 0, 0, 0.3); +} + +.navbar-light .navbar-nav .show > .nav-link, +.navbar-light .navbar-nav .active > .nav-link, +.navbar-light .navbar-nav .nav-link.show, +.navbar-light .navbar-nav .nav-link.active { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-toggler { + color: rgba(0, 0, 0, 0.5); + border-color: rgba(0, 0, 0, 0.1); +} + +.navbar-light .navbar-toggler-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); +} + +.navbar-light .navbar-text { + color: rgba(0, 0, 0, 0.5); +} + +.navbar-dark .navbar-brand { + color: #fff; +} + +.navbar-dark .navbar-brand:focus, .navbar-dark .navbar-brand:hover { + color: #fff; +} + +.navbar-dark .navbar-nav .nav-link { + color: rgba(255, 255, 255, 0.5); +} + +.navbar-dark .navbar-nav .nav-link:focus, .navbar-dark .navbar-nav .nav-link:hover { + color: rgba(255, 255, 255, 0.75); +} + +.navbar-dark .navbar-nav .nav-link.disabled { + color: rgba(255, 255, 255, 0.25); +} + +.navbar-dark .navbar-nav .show > .nav-link, +.navbar-dark .navbar-nav .active > .nav-link, +.navbar-dark .navbar-nav .nav-link.show, +.navbar-dark .navbar-nav .nav-link.active { + color: #fff; +} + +.navbar-dark .navbar-toggler { + color: rgba(255, 255, 255, 0.5); + border-color: rgba(255, 255, 255, 0.1); +} + +.navbar-dark .navbar-toggler-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); +} + +.navbar-dark .navbar-text { + color: rgba(255, 255, 255, 0.5); +} + +/* + * 2. BUTTONS + */ +.btn { + font-weight: 400; + border: 1px solid transparent; + padding: 0.375rem 0.75rem; + font-size: 1rem; + line-height: 1.5; + border-radius: 0.25rem; + -webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; +} + +.btn:focus, .btn.focus { + outline: 0; + -webkit-box-shadow: 0 0 0 0.2rem rgba(121, 106, 238, 0.25); + box-shadow: 0 0 0 0.2rem rgba(121, 106, 238, 0.25); +} + +.btn.disabled, .btn:disabled { + opacity: .65; +} + +.btn:not([disabled]):not(.disabled):active, .btn:not([disabled]):not(.disabled).active { + background-image: none; +} + +.btn-primary { + color: color-yiq(#796AEE); + background-color: #796AEE; + border-color: #796AEE; +} + +.btn-primary:hover { + color: color-yiq(#5a48ea); + background-color: #5a48ea; + border-color: #503ce9; +} + +.btn-primary:focus, .btn-primary.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(121, 106, 238, 0.5); + box-shadow: 0 0 0 0.2rem rgba(121, 106, 238, 0.5); +} + +.btn-primary.disabled, .btn-primary:disabled { + color: color-yiq(#796AEE); + background-color: #796AEE; + border-color: #796AEE; +} + +.btn-primary:not(:disabled):not(.disabled):active, .btn-primary:not(:disabled):not(.disabled).active, +.show > .btn-primary.dropdown-toggle { + color: color-yiq(#503ce9); + background-color: #503ce9; + border-color: #4631e7; +} + +.btn-primary:not(:disabled):not(.disabled):active:focus, .btn-primary:not(:disabled):not(.disabled).active:focus, +.show > .btn-primary.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(121, 106, 238, 0.5); + box-shadow: 0 0 0 0.2rem rgba(121, 106, 238, 0.5); +} + +.btn-secondary { + color: color-yiq(#868e96); + background-color: #868e96; + border-color: #868e96; +} + +.btn-secondary:hover { + color: color-yiq(#727b84); + background-color: #727b84; + border-color: #6c757d; +} + +.btn-secondary:focus, .btn-secondary.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); + box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); +} + +.btn-secondary.disabled, .btn-secondary:disabled { + color: color-yiq(#868e96); + background-color: #868e96; + border-color: #868e96; +} + +.btn-secondary:not(:disabled):not(.disabled):active, .btn-secondary:not(:disabled):not(.disabled).active, +.show > .btn-secondary.dropdown-toggle { + color: color-yiq(#6c757d); + background-color: #6c757d; + border-color: #666e76; +} + +.btn-secondary:not(:disabled):not(.disabled):active:focus, .btn-secondary:not(:disabled):not(.disabled).active:focus, +.show > .btn-secondary.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); + box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); +} + +.btn-success { + color: color-yiq(#28a745); + background-color: #28a745; + border-color: #28a745; +} + +.btn-success:hover { + color: color-yiq(#218838); + background-color: #218838; + border-color: #1e7e34; +} + +.btn-success:focus, .btn-success.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.btn-success.disabled, .btn-success:disabled { + color: color-yiq(#28a745); + background-color: #28a745; + border-color: #28a745; +} + +.btn-success:not(:disabled):not(.disabled):active, .btn-success:not(:disabled):not(.disabled).active, +.show > .btn-success.dropdown-toggle { + color: color-yiq(#1e7e34); + background-color: #1e7e34; + border-color: #1c7430; +} + +.btn-success:not(:disabled):not(.disabled):active:focus, .btn-success:not(:disabled):not(.disabled).active:focus, +.show > .btn-success.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.btn-info { + color: color-yiq(#17a2b8); + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-info:hover { + color: color-yiq(#138496); + background-color: #138496; + border-color: #117a8b; +} + +.btn-info:focus, .btn-info.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.btn-info.disabled, .btn-info:disabled { + color: color-yiq(#17a2b8); + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-info:not(:disabled):not(.disabled):active, .btn-info:not(:disabled):not(.disabled).active, +.show > .btn-info.dropdown-toggle { + color: color-yiq(#117a8b); + background-color: #117a8b; + border-color: #10707f; +} + +.btn-info:not(:disabled):not(.disabled):active:focus, .btn-info:not(:disabled):not(.disabled).active:focus, +.show > .btn-info.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.btn-warning { + color: color-yiq(#ffc107); + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-warning:hover { + color: color-yiq(#e0a800); + background-color: #e0a800; + border-color: #d39e00; +} + +.btn-warning:focus, .btn-warning.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.btn-warning.disabled, .btn-warning:disabled { + color: color-yiq(#ffc107); + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-warning:not(:disabled):not(.disabled):active, .btn-warning:not(:disabled):not(.disabled).active, +.show > .btn-warning.dropdown-toggle { + color: color-yiq(#d39e00); + background-color: #d39e00; + border-color: #c69500; +} + +.btn-warning:not(:disabled):not(.disabled):active:focus, .btn-warning:not(:disabled):not(.disabled).active:focus, +.show > .btn-warning.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.btn-danger { + color: color-yiq(#dc3545); + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-danger:hover { + color: color-yiq(#c82333); + background-color: #c82333; + border-color: #bd2130; +} + +.btn-danger:focus, .btn-danger.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.btn-danger.disabled, .btn-danger:disabled { + color: color-yiq(#dc3545); + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-danger:not(:disabled):not(.disabled):active, .btn-danger:not(:disabled):not(.disabled).active, +.show > .btn-danger.dropdown-toggle { + color: color-yiq(#bd2130); + background-color: #bd2130; + border-color: #b21f2d; +} + +.btn-danger:not(:disabled):not(.disabled):active:focus, .btn-danger:not(:disabled):not(.disabled).active:focus, +.show > .btn-danger.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.btn-light { + color: color-yiq(#f8f9fa); + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-light:hover { + color: color-yiq(#e2e6ea); + background-color: #e2e6ea; + border-color: #dae0e5; +} + +.btn-light:focus, .btn-light.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.btn-light.disabled, .btn-light:disabled { + color: color-yiq(#f8f9fa); + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-light:not(:disabled):not(.disabled):active, .btn-light:not(:disabled):not(.disabled).active, +.show > .btn-light.dropdown-toggle { + color: color-yiq(#dae0e5); + background-color: #dae0e5; + border-color: #d3d9df; +} + +.btn-light:not(:disabled):not(.disabled):active:focus, .btn-light:not(:disabled):not(.disabled).active:focus, +.show > .btn-light.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.btn-dark { + color: color-yiq(#343a40); + background-color: #343a40; + border-color: #343a40; +} + +.btn-dark:hover { + color: color-yiq(#23272b); + background-color: #23272b; + border-color: #1d2124; +} + +.btn-dark:focus, .btn-dark.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.btn-dark.disabled, .btn-dark:disabled { + color: color-yiq(#343a40); + background-color: #343a40; + border-color: #343a40; +} + +.btn-dark:not(:disabled):not(.disabled):active, .btn-dark:not(:disabled):not(.disabled).active, +.show > .btn-dark.dropdown-toggle { + color: color-yiq(#1d2124); + background-color: #1d2124; + border-color: #171a1d; +} + +.btn-dark:not(:disabled):not(.disabled):active:focus, .btn-dark:not(:disabled):not(.disabled).active:focus, +.show > .btn-dark.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.btn-default { + color: color-yiq(#ced4da); + background-color: #ced4da; + border-color: #ced4da; +} + +.btn-default:hover { + color: color-yiq(#b8c1ca); + background-color: #b8c1ca; + border-color: #b1bbc4; +} + +.btn-default:focus, .btn-default.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(206, 212, 218, 0.5); + box-shadow: 0 0 0 0.2rem rgba(206, 212, 218, 0.5); +} + +.btn-default.disabled, .btn-default:disabled { + color: color-yiq(#ced4da); + background-color: #ced4da; + border-color: #ced4da; +} + +.btn-default:not(:disabled):not(.disabled):active, .btn-default:not(:disabled):not(.disabled).active, +.show > .btn-default.dropdown-toggle { + color: color-yiq(#b1bbc4); + background-color: #b1bbc4; + border-color: #aab4bf; +} + +.btn-default:not(:disabled):not(.disabled):active:focus, .btn-default:not(:disabled):not(.disabled).active:focus, +.show > .btn-default.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(206, 212, 218, 0.5); + box-shadow: 0 0 0 0.2rem rgba(206, 212, 218, 0.5); +} + +.btn-outline-primary { + color: #796AEE; + background-color: transparent; + background-image: none; + border-color: #796AEE; +} + +.btn-outline-primary:hover { + color: #fff; + background-color: #796AEE; + border-color: #796AEE; +} + +.btn-outline-primary:focus, .btn-outline-primary.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(121, 106, 238, 0.5); + box-shadow: 0 0 0 0.2rem rgba(121, 106, 238, 0.5); +} + +.btn-outline-primary.disabled, .btn-outline-primary:disabled { + color: #796AEE; + background-color: transparent; +} + +.btn-outline-primary:not(:disabled):not(.disabled):active, .btn-outline-primary:not(:disabled):not(.disabled).active, +.show > .btn-outline-primary.dropdown-toggle { + color: color-yiq(#796AEE); + background-color: #796AEE; + border-color: #796AEE; +} + +.btn-outline-primary:not(:disabled):not(.disabled):active:focus, .btn-outline-primary:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-primary.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(121, 106, 238, 0.5); + box-shadow: 0 0 0 0.2rem rgba(121, 106, 238, 0.5); +} + +.btn-outline-secondary { + color: #868e96; + background-color: transparent; + background-image: none; + border-color: #868e96; +} + +.btn-outline-secondary:hover { + color: #fff; + background-color: #868e96; + border-color: #868e96; +} + +.btn-outline-secondary:focus, .btn-outline-secondary.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); + box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); +} + +.btn-outline-secondary.disabled, .btn-outline-secondary:disabled { + color: #868e96; + background-color: transparent; +} + +.btn-outline-secondary:not(:disabled):not(.disabled):active, .btn-outline-secondary:not(:disabled):not(.disabled).active, +.show > .btn-outline-secondary.dropdown-toggle { + color: color-yiq(#868e96); + background-color: #868e96; + border-color: #868e96; +} + +.btn-outline-secondary:not(:disabled):not(.disabled):active:focus, .btn-outline-secondary:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-secondary.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); + box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); +} + +.btn-outline-success { + color: #28a745; + background-color: transparent; + background-image: none; + border-color: #28a745; +} + +.btn-outline-success:hover { + color: #fff; + background-color: #28a745; + border-color: #28a745; +} + +.btn-outline-success:focus, .btn-outline-success.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.btn-outline-success.disabled, .btn-outline-success:disabled { + color: #28a745; + background-color: transparent; +} + +.btn-outline-success:not(:disabled):not(.disabled):active, .btn-outline-success:not(:disabled):not(.disabled).active, +.show > .btn-outline-success.dropdown-toggle { + color: color-yiq(#28a745); + background-color: #28a745; + border-color: #28a745; +} + +.btn-outline-success:not(:disabled):not(.disabled):active:focus, .btn-outline-success:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-success.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.btn-outline-info { + color: #17a2b8; + background-color: transparent; + background-image: none; + border-color: #17a2b8; +} + +.btn-outline-info:hover { + color: #fff; + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-outline-info:focus, .btn-outline-info.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.btn-outline-info.disabled, .btn-outline-info:disabled { + color: #17a2b8; + background-color: transparent; +} + +.btn-outline-info:not(:disabled):not(.disabled):active, .btn-outline-info:not(:disabled):not(.disabled).active, +.show > .btn-outline-info.dropdown-toggle { + color: color-yiq(#17a2b8); + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-outline-info:not(:disabled):not(.disabled):active:focus, .btn-outline-info:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-info.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.btn-outline-warning { + color: #ffc107; + background-color: transparent; + background-image: none; + border-color: #ffc107; +} + +.btn-outline-warning:hover { + color: #fff; + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-outline-warning:focus, .btn-outline-warning.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.btn-outline-warning.disabled, .btn-outline-warning:disabled { + color: #ffc107; + background-color: transparent; +} + +.btn-outline-warning:not(:disabled):not(.disabled):active, .btn-outline-warning:not(:disabled):not(.disabled).active, +.show > .btn-outline-warning.dropdown-toggle { + color: color-yiq(#ffc107); + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-outline-warning:not(:disabled):not(.disabled):active:focus, .btn-outline-warning:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-warning.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.btn-outline-danger { + color: #dc3545; + background-color: transparent; + background-image: none; + border-color: #dc3545; +} + +.btn-outline-danger:hover { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-outline-danger:focus, .btn-outline-danger.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.btn-outline-danger.disabled, .btn-outline-danger:disabled { + color: #dc3545; + background-color: transparent; +} + +.btn-outline-danger:not(:disabled):not(.disabled):active, .btn-outline-danger:not(:disabled):not(.disabled).active, +.show > .btn-outline-danger.dropdown-toggle { + color: color-yiq(#dc3545); + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-outline-danger:not(:disabled):not(.disabled):active:focus, .btn-outline-danger:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-danger.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.btn-outline-light { + color: #f8f9fa; + background-color: transparent; + background-image: none; + border-color: #f8f9fa; +} + +.btn-outline-light:hover { + color: #fff; + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-outline-light:focus, .btn-outline-light.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.btn-outline-light.disabled, .btn-outline-light:disabled { + color: #f8f9fa; + background-color: transparent; +} + +.btn-outline-light:not(:disabled):not(.disabled):active, .btn-outline-light:not(:disabled):not(.disabled).active, +.show > .btn-outline-light.dropdown-toggle { + color: color-yiq(#f8f9fa); + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-outline-light:not(:disabled):not(.disabled):active:focus, .btn-outline-light:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-light.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.btn-outline-dark { + color: #343a40; + background-color: transparent; + background-image: none; + border-color: #343a40; +} + +.btn-outline-dark:hover { + color: #fff; + background-color: #343a40; + border-color: #343a40; +} + +.btn-outline-dark:focus, .btn-outline-dark.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.btn-outline-dark.disabled, .btn-outline-dark:disabled { + color: #343a40; + background-color: transparent; +} + +.btn-outline-dark:not(:disabled):not(.disabled):active, .btn-outline-dark:not(:disabled):not(.disabled).active, +.show > .btn-outline-dark.dropdown-toggle { + color: color-yiq(#343a40); + background-color: #343a40; + border-color: #343a40; +} + +.btn-outline-dark:not(:disabled):not(.disabled):active:focus, .btn-outline-dark:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-dark.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.btn-lg { + padding: 0.5rem 1rem; + font-size: 1.25rem; + line-height: 1.5; + border-radius: 0.3rem; +} + +.btn-sm { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; + border-radius: 0.2rem; +} + +/* + * 3. TYPE + */ +body { + font-family: "Poppins", sans-serif; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + background-color: #fff; +} + +a { + color: #796AEE; + text-decoration: none; +} + +a:focus, a:hover { + color: #3b25e6; + text-decoration: underline; +} + +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + margin-bottom: 0.5rem; + font-family: inherit; + font-weight: 700; + line-height: 1.1; + color: inherit; +} + +h1, +.h1 { + font-size: 1.5rem; +} + +h2, +.h2 { + font-size: 1.3rem; +} + +h3, +.h3 { + font-size: 1.2rem; +} + +h4, +.h4 { + font-size: 1.1rem; +} + +h5, +.h5 { + font-size: 1rem; +} + +h6, +.h6 { + font-size: 0.95rem; +} + +.lead { + font-size: 1.25rem; + font-weight: 300; +} + +.display-1 { + font-size: 6rem; + font-weight: 300; + line-height: 1.1; +} + +.display-2 { + font-size: 5.5rem; + font-weight: 300; + line-height: 1.1; +} + +.display-3 { + font-size: 4.5rem; + font-weight: 300; + line-height: 1.1; +} + +.display-4 { + font-size: 3.5rem; + font-weight: 300; + line-height: 1.1; +} + +hr { + border-top: 1px solid rgba(0, 0, 0, 0.1); +} + +small, +.small { + font-size: 80%; + font-weight: 400; +} + +mark, +.mark { + padding: 0.2em; + background-color: #fcf8e3; +} + +.blockquote { + padding: 0.5rem 1rem; + margin-bottom: 2rem; + font-size: 1.25rem; + border-left: 5px solid #796AEE; +} + +.blockquote-footer { + color: #868e96; +} + +.blockquote-footer::before { + content: "\2014 \00A0"; +} + +.text-primary { + color: #796AEE !important; +} + +a.text-primary:focus, a.text-primary:hover { + color: #503ce9 !important; +} + +/* + * 4. PAGINATION + */ +.page-item:first-child .page-link { + border-top-left-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} + +.page-item:last-child .page-link { + border-top-right-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; +} + +.page-item.active .page-link { + color: #fff; + background-color: #796AEE; + border-color: #796AEE; +} + +.page-item.disabled .page-link { + color: #868e96; + background-color: #fff; + border-color: #ddd; +} + +.page-link { + padding: 0.5rem 0.75rem; + margin-left: -1px; + line-height: 1.25; + color: #796AEE; + background-color: #fff; + border: 1px solid #ddd; +} + +.page-link:hover { + z-index: 2; + color: #3b25e6; + background-color: #e9ecef; + border-color: #ddd; +} + +.page-link:focus { + z-index: 2; + outline: 0; + -webkit-box-shadow: none; + box-shadow: none; + text-decoration: none; +} + +.pagination-lg .page-link { + padding: 0.75rem 1.5rem; + font-size: 1.25rem; + line-height: 1.5; +} + +.pagination-lg .page-item:first-child .page-link { + border-top-left-radius: 0.3rem; + border-bottom-left-radius: 0.3rem; +} + +.pagination-lg .page-item:last-child .page-link { + border-top-right-radius: 0.3rem; + border-bottom-right-radius: 0.3rem; +} + +.pagination-sm .page-link { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; +} + +.pagination-sm .page-item:first-child .page-link { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; +} + +.pagination-sm .page-item:last-child .page-link { + border-top-right-radius: 0.2rem; + border-bottom-right-radius: 0.2rem; +} + +/* +* 5. UTILITIES +*/ +.bg-primary { + background-color: #796AEE !important; +} + +a.bg-primary:focus, a.bg-primary:hover { + background-color: #503ce9 !important; +} + +.bg-secondary { + background-color: #868e96 !important; +} + +a.bg-secondary:focus, a.bg-secondary:hover { + background-color: #6c757d !important; +} + +.bg-success { + background-color: #28a745 !important; +} + +a.bg-success:focus, a.bg-success:hover { + background-color: #1e7e34 !important; +} + +.bg-info { + background-color: #17a2b8 !important; +} + +a.bg-info:focus, a.bg-info:hover { + background-color: #117a8b !important; +} + +.bg-warning { + background-color: #ffc107 !important; +} + +a.bg-warning:focus, a.bg-warning:hover { + background-color: #d39e00 !important; +} + +.bg-danger { + background-color: #dc3545 !important; +} + +a.bg-danger:focus, a.bg-danger:hover { + background-color: #bd2130 !important; +} + +.bg-light { + background-color: #f8f9fa !important; +} + +a.bg-light:focus, a.bg-light:hover { + background-color: #dae0e5 !important; +} + +.bg-dark { + background-color: #343a40 !important; +} + +a.bg-dark:focus, a.bg-dark:hover { + background-color: #1d2124 !important; +} + +.border-primary { + border-color: #796AEE !important; +} + +.border-secondary { + border-color: #868e96 !important; +} + +.border-success { + border-color: #28a745 !important; +} + +.border-info { + border-color: #17a2b8 !important; +} + +.border-warning { + border-color: #ffc107 !important; +} + +.border-danger { + border-color: #dc3545 !important; +} + +.border-light { + border-color: #f8f9fa !important; +} + +.border-dark { + border-color: #343a40 !important; +} + +.text-primary { + color: #796AEE !important; +} + +a.text-primary:focus, a.text-primary:hover { + color: #503ce9 !important; +} + +.text-secondary { + color: #868e96 !important; +} + +a.text-secondary:focus, a.text-secondary:hover { + color: #6c757d !important; +} + +.text-success { + color: #28a745 !important; +} + +a.text-success:focus, a.text-success:hover { + color: #1e7e34 !important; +} + +.text-info { + color: #17a2b8 !important; +} + +a.text-info:focus, a.text-info:hover { + color: #117a8b !important; +} + +.text-warning { + color: #ffc107 !important; +} + +a.text-warning:focus, a.text-warning:hover { + color: #d39e00 !important; +} + +.text-danger { + color: #dc3545 !important; +} + +a.text-danger:focus, a.text-danger:hover { + color: #bd2130 !important; +} + +.text-light { + color: #f8f9fa !important; +} + +a.text-light:focus, a.text-light:hover { + color: #dae0e5 !important; +} + +.text-dark { + color: #343a40 !important; +} + +a.text-dark:focus, a.text-dark:hover { + color: #1d2124 !important; +} + +.badge-primary { + color: color-yiq(#796AEE); + background-color: #796AEE; +} + +.badge-primary[href]:focus, .badge-primary[href]:hover { + color: color-yiq(#796AEE); + text-decoration: none; + background-color: #503ce9; +} + +.badge-secondary { + color: color-yiq(#868e96); + background-color: #868e96; +} + +.badge-secondary[href]:focus, .badge-secondary[href]:hover { + color: color-yiq(#868e96); + text-decoration: none; + background-color: #6c757d; +} + +.badge-success { + color: color-yiq(#28a745); + background-color: #28a745; +} + +.badge-success[href]:focus, .badge-success[href]:hover { + color: color-yiq(#28a745); + text-decoration: none; + background-color: #1e7e34; +} + +.badge-info { + color: color-yiq(#17a2b8); + background-color: #17a2b8; +} + +.badge-info[href]:focus, .badge-info[href]:hover { + color: color-yiq(#17a2b8); + text-decoration: none; + background-color: #117a8b; +} + +.badge-warning { + color: color-yiq(#ffc107); + background-color: #ffc107; +} + +.badge-warning[href]:focus, .badge-warning[href]:hover { + color: color-yiq(#ffc107); + text-decoration: none; + background-color: #d39e00; +} + +.badge-danger { + color: color-yiq(#dc3545); + background-color: #dc3545; +} + +.badge-danger[href]:focus, .badge-danger[href]:hover { + color: color-yiq(#dc3545); + text-decoration: none; + background-color: #bd2130; +} + +.badge-light { + color: color-yiq(#f8f9fa); + background-color: #f8f9fa; +} + +.badge-light[href]:focus, .badge-light[href]:hover { + color: color-yiq(#f8f9fa); + text-decoration: none; + background-color: #dae0e5; +} + +.badge-dark { + color: color-yiq(#343a40); + background-color: #343a40; +} + +.badge-dark[href]:focus, .badge-dark[href]:hover { + color: color-yiq(#343a40); + text-decoration: none; + background-color: #1d2124; +} + +/* +* 6.CODE +*/ +code { + padding: 0.2rem 0.4rem; + font-size: 90%; + color: #bd4147; + background-color: #f8f9fa; + border-radius: 0.25rem; +} + +a > code { + padding: 0; + color: inherit; + background-color: inherit; +} + +/* +* 7. NAV +*/ +.nav-link { + padding: 0.5rem 1rem; +} + +.nav-link.disabled { + color: #868e96; +} + +.nav-tabs .nav-item { + margin-bottom: -1px; +} + +.nav-tabs .nav-link { + border: 1px solid transparent; + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} + +.nav-tabs .nav-link:focus, .nav-tabs .nav-link:hover { + border-color: #e9ecef #e9ecef #dee2e6; +} + +.nav-tabs .nav-link.disabled { + color: #868e96; +} + +.nav-tabs .nav-link.active, +.nav-tabs .nav-item.show .nav-link { + color: #495057; + background-color: #fff; +} + +.nav-tabs .dropdown-menu { + margin-top: -1px; +} + +.nav-pills .nav-link { + border-radius: 0.25rem; +} + +.nav-pills .nav-link.active, +.nav-pills .show > .nav-link { + color: #fff; + background-color: #796AEE; +} + +/* +* 8. CARD +*/ +.card { + background-color: #fff; + border: 0 solid #eee; + border-radius: 0; +} + +.card > .list-group:first-child .list-group-item:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.card > .list-group:last-child .list-group-item:last-child { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.card-body { + padding: 1.25rem; +} + +.card-title { + margin-bottom: 1rem; +} + +.card-subtitle { + margin-top: -0.5rem; +} + +.card-link + .card-link { + margin-left: 1.25rem; +} + +.card-header { + padding: 1rem 1.25rem; + background-color: #fff; + border-bottom: 1px solid #eee; +} + +.card-header:first-child { + border-radius: 0 0 0 0; +} + +.card-header-transparent { + background-color: rgba(0, 0, 0, 0.3); + border-bottom: none; +} + +.card-footer { + padding: 1rem 1.25rem; + background-color: #f8f9fa; + border-top: 1px solid #eee; +} + +.card-footer:last-child { + border-radius: 0 0 0 0; +} + +.card-header-tabs { + margin-right: -0.625rem; + margin-bottom: -1rem; + margin-left: -0.625rem; + border-bottom: 0; +} + +.card-header-pills { + margin-right: -0.625rem; + margin-left: -0.625rem; +} + +.card-img-overlay { + padding: 1.25rem; +} + +.card-img-overlay-opacity { + background: rgba(0, 0, 0, 0.2); +} + +.card-img { + border-radius: 0; +} + +.card-img-top { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.card-img-bottom { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.card-deck .card { + margin-bottom: 15px; +} + +@media (min-width: 576px) { + .card-deck { + margin-right: -15px; + margin-left: -15px; + } + .card-deck .card { + margin-right: 15px; + margin-left: 15px; + } +} + +.custom-select { + height: calc(2.25rem + 2px); + padding: 0.375rem 1.75rem 0.375rem 0.75rem; + line-height: 1.5; + color: #495057; + vertical-align: middle; + background: #fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center; + background-size: 8px 10px; + border: 1px solid #ced4da; + border-radius: 0; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +.custom-select:focus { + border-color: #796AEE; + outline: 0; + -webkit-box-shadow: 0 0 0 0.2rem rgba(121, 106, 238, 0.5); + box-shadow: 0 0 0 0.2rem rgba(121, 106, 238, 0.5); +} + +.custom-select:focus::-ms-value { + color: #495057; + background-color: #fff; +} + +.custom-select[multiple], .custom-select[size]:not([size="1"]) { + height: auto; + padding-right: 0.75rem; + background-image: none; +} + +.custom-select:disabled { + color: #868e96; + background-color: #e9ecef; +} + +.custom-select::-ms-expand { + opacity: 0; +} + +.custom-select-sm { + height: calc(1.8125rem + 2px); + padding-top: 0.375rem; + padding-bottom: 0.375rem; + font-size: 75%; +} + +.custom-select-lg { + height: calc(2.875rem + 2px); + padding-top: 0.375rem; + padding-bottom: 0.375rem; + font-size: 125%; +} diff --git a/agent/static/css/style.font.css b/agent/static/css/style.font.css new file mode 100644 index 0000000..fa99034 --- /dev/null +++ b/agent/static/css/style.font.css @@ -0,0 +1,72 @@ +/* devanagari */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 300; + src: local('Poppins Light'), local('Poppins-Light'), url(https://fonts.gstatic.com/s/poppins/v9/pxiByp8kv8JHgFVrLDz8Z11lFc-K.woff2) format('woff2'); + unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB; +} +/* latin-ext */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 300; + src: local('Poppins Light'), local('Poppins-Light'), url(https://fonts.gstatic.com/s/poppins/v9/pxiByp8kv8JHgFVrLDz8Z1JlFc-K.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 300; + src: local('Poppins Light'), local('Poppins-Light'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* devanagari */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 400; + src: local('Poppins Regular'), local('Poppins-Regular'), url(https://fonts.gstatic.com/s/poppins/v9/pxiEyp8kv8JHgFVrJJbecmNE.woff2) format('woff2'); + unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB; +} +/* latin-ext */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 400; + src: local('Poppins Regular'), local('Poppins-Regular'), url(https://fonts.gstatic.com/s/poppins/v9/pxiEyp8kv8JHgFVrJJnecmNE.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 400; + src: local('Poppins Regular'), local('Poppins-Regular'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* devanagari */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 700; + src: local('Poppins Bold'), local('Poppins-Bold'), url(https://fonts.gstatic.com/s/poppins/v9/pxiByp8kv8JHgFVrLCz7Z11lFc-K.woff2) format('woff2'); + unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB; +} +/* latin-ext */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 700; + src: local('Poppins Bold'), local('Poppins-Bold'), url(https://fonts.gstatic.com/s/poppins/v9/pxiByp8kv8JHgFVrLCz7Z1JlFc-K.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 700; + src: local('Poppins Bold'), local('Poppins-Bold'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} diff --git a/agent/static/css/style.sea.css b/agent/static/css/style.sea.css new file mode 100644 index 0000000..70bbfdb --- /dev/null +++ b/agent/static/css/style.sea.css @@ -0,0 +1,3496 @@ +/* +========================================================== +========================================================== + +Bootstrap 4 Admin Template + +https://bootstrapious.com/p/admin-template + +========================================================== +========================================================== +*/ +/* +* ========================================================== +* GENERAL STYLES +* ========================================================== +*/ +body { + overflow-x: hidden; +} + +a, +i, +span { + display: inline-block; + text-decoration: none; + -webkit-transition: all 0.3s; + transition: all 0.3s; +} + +a:hover, a:focus, +i:hover, +i:focus, +span:hover, +span:focus { + text-decoration: none; +} + +section { + padding: 0px 0; +} + +canvas { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.container-fluid { + padding: 0 30px; +} + +@media (max-width: 575px) { + .container-fluid { + padding: 0 15px; + } +} + +header.page-header { + padding: 0px 0; +} + +table { + font-size: 0.9em; + color: #666; +} + +.card-close { + position: absolute; + top: 15px; + right: 15px; +} + +.card-close .dropdown-toggle { + color: #999; + background: none; + border: none; +} + +.card-close .dropdown-toggle:after { + display: none; +} + +.card-close .dropdown-menu { + border: none; + min-width: auto; + font-size: 0.9em; + border-radius: 0; + -webkit-box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.1), -2px -2px 3px rgba(0, 0, 0, 0.1); + box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.1), -2px -2px 3px rgba(0, 0, 0, 0.1); +} + +.card-close .dropdown-menu a { + color: #999 !important; +} + +.card-close .dropdown-menu a:hover { + background: #379392; + color: #fff !important; +} + +.card-close .dropdown-menu a i { + margin-right: 10px; + -webkit-transition: none; + transition: none; +} + +.content-inner { + position: relative; + width: calc(100% - 250px); + min-height: calc(100vh - 70px); + padding-bottom: 60px; +} + +.content-inner.active { + width: calc(100% - 90px); +} + +.page-header { + background: #fff; + padding: 20px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1); + position: relative; + z-index: 8; +} + +*[class*="icon-"] { + -webkit-transform: translateY(3px); + transform: translateY(3px); +} + +button, +input { + outline: none !important; +} + +.card { + margin-bottom: 30px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1), -1px 0 2px rgba(0, 0, 0, 0.05); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1), -1px 0 2px rgba(0, 0, 0, 0.05); +} + +.card-header { + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.05); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.05); +} + +.card-header h1, +.card-header h2, +.card-header h3, +.card-header h4, +.card-header h5, +.card-header h6 { + margin-bottom: 0; +} + +.breadcrumb-holder { + background: #fff; +} + +.breadcrumb { + background: #fff; + position: relative; + z-index: 7; + border-radius: 0; + padding: 15px 0; + margin-bottom: 0; +} + +.breadcrumb li.breadcrumb-item { + color: #aaa; + font-weight: 300; +} + +/*=== Helpers ===*/ +.text-bold { + font-weight: 700; +} + +.text-small { + font-size: 0.9rem; +} + +.text-xsmall { + font-size: 0.8rem; +} + +.bg-red { + background: #ff7676 !important; + color: #fff; +} + +.bg-red:hover { + color: #fff; +} + +.bg-blue { + background: #85b4f2 !important; + color: #fff; +} + +.bg-blue:hover { + color: #fff; +} + +.bg-yellow { + background: #eef157 !important; + color: #fff; +} + +.bg-yellow:hover { + color: #fff; +} + +.bg-green { + background: #54e69d !important; + color: #fff; +} + +.bg-green:hover { + color: #fff; +} + +.bg-orange { + background: #ffc36d !important; + color: #fff; +} + +.bg-orange:hover { + color: #fff; +} + +.bg-violet { + background: #796AEE !important; + color: #fff; +} + +.bg-violet:hover { + color: #fff; +} + +.bg-gray { + background: #ced4da !important; +} + +.bg-white { + background: #fff !important; +} + +.text-red { + color: #ff7676; +} + +.text-red:hover { + color: #ff7676; +} + +.text-yellow { + color: #eef157; +} + +.text-yellow:hover { + color: #eef157; +} + +.text-green { + color: #54e69d; +} + +.text-green:hover { + color: #54e69d; +} + +.text-orange { + color: #ffc36d; +} + +.text-orange:hover { + color: #ffc36d; +} + +.text-violet { + color: #796AEE; +} + +.text-violet:hover { + color: #796AEE; +} + +.text-blue { + color: #85b4f2; +} + +.text-blue:hover { + color: #85b4f2; +} + +.text-gray { + color: #ced4da; +} + +.text-gray:hover { + color: #ced4da; +} + +.text-uppercase { + letter-spacing: 0.2em; +} + +.lh-2 { + line-height: 2; +} + +.page { + background: #EEF5F9; +} + +.page .text-white { + color: #fff; +} + +.no-padding { + padding: 0 !important; +} + +.no-padding-bottom { + padding-bottom: 0 !important; +} + +.no-padding-top { + padding-top: 0 !important; +} + +.no-margin { + margin: 0 !important; +} + +.no-margin-bottom { + margin-bottom: 0 !important; +} + +.no-margin-top { + margin-top: 0 !important; +} + +.page { + overflow-x: hidden; +} + +.has-shadow { + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1), -1px 0 2px rgba(0, 0, 0, 0.05); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1), -1px 0 2px rgba(0, 0, 0, 0.05); +} + +.badge { + font-weight: 400; +} + +.badge-rounded { + border-radius: 50px; +} + +.list-group-item { + border-right: 0; + border-left: 0; +} + +.list-group-item:first-child, .list-group-item:last-child { + border-radius: 0; +} + +.overflow-hidden { + overflow: hidden; +} + +.tile-link { + position: absolute; + cursor: pointer; + width: 100%; + height: 100%; + left: 0; + top: 0; + z-index: 30; +} + +/* +* ========================================================== +* SIDEBAR +* ========================================================== +*/ +nav.side-navbar { + background: #fff; + min-width: 250px; + max-width: 250px; + color: #686a76; + -webkit-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1); + box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1); + z-index: 9; + /*==== Sidebar Header ====*/ + /*==== Sidebar Menu ====*/ + /*==== Shrinked Sidebar ====*/ +} + +nav.side-navbar a { + color: inherit; + position: relative; + font-size: 0.9em; +} + +nav.side-navbar a[data-toggle="collapse"]::before { + content: '\f104'; + display: inline-block; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); + font-family: 'FontAwesome'; + position: absolute; + top: 50%; + right: 20px; +} + +nav.side-navbar a[aria-expanded="true"] { + background: #EEF5F9; +} + +nav.side-navbar a[aria-expanded="true"]::before { + content: '\f107'; +} + +nav.side-navbar a i { + font-size: 1.2em; + margin-right: 10px; + -webkit-transition: none; + transition: none; +} + +nav.side-navbar .sidebar-header { + padding: 30px 15px; +} + +nav.side-navbar .avatar { + width: 55px; + height: 55px; +} + +nav.side-navbar .title { + margin-left: 10px; +} + +nav.side-navbar .title h1 { + color: #333; +} + +nav.side-navbar .title p { + font-size: 0.9em; + font-weight: 200; + margin-bottom: 0; + color: #aaa; +} + +nav.side-navbar span.heading { + text-transform: uppercase; + font-weight: 400; + margin-left: 20px; + color: #ccc; + font-size: 0.8em; +} + +nav.side-navbar ul { + padding: 15px 0; +} + +nav.side-navbar ul li { + /* submenu item active */ +} + +nav.side-navbar ul li a { + padding: 10px 15px; + text-decoration: none; + display: block; + font-weight: 300; + border-left: 4px solid transparent; +} + +nav.side-navbar ul li a:hover { + background: #379392; + border-left: 4px solid #225b5b; + color: #fff; +} + +nav.side-navbar ul li li a { + padding-left: 50px; + background: #EEF5F9; +} + +nav.side-navbar ul li.active > a { + background: #379392; + color: #fff; + border-left: 4px solid #225b5b; +} + +nav.side-navbar ul li.active > a:hover { + background: #379392; +} + +nav.side-navbar ul li li.active > a { + background: #3ea6a4; +} + +nav.side-navbar ul li ul { + padding: 0; +} + +nav.side-navbar.shrinked { + min-width: 90px; + max-width: 90px; + text-align: center; +} + +nav.side-navbar.shrinked span.heading { + margin: 0; +} + +nav.side-navbar.shrinked ul li a { + padding: 15px 2px; + border: none; + font-size: 0.8em; + color: #aaa; + -webkit-transition: color 0.3s, background 0.3s; + transition: color 0.3s, background 0.3s; +} + +nav.side-navbar.shrinked ul li a[data-toggle="collapse"]::before { + content: '\f107'; + -webkit-transform: translateX(50%); + transform: translateX(50%); + position: absolute; + top: auto; + right: 50%; + bottom: 0; + left: auto; +} + +nav.side-navbar.shrinked ul li a[data-toggle="collapse"][aria-expanded="true"]::before { + content: '\f106'; +} + +nav.side-navbar.shrinked ul li a:hover { + color: #fff; + border: none; +} + +nav.side-navbar.shrinked ul li a:hover i { + color: #fff; +} + +nav.side-navbar.shrinked ul li a i { + margin-right: 0; + margin-bottom: 2px; + display: block; + font-size: 1rem; + color: #333; + -webkit-transition: color 0.3s; + transition: color 0.3s; +} + +nav.side-navbar.shrinked ul li.active > a { + color: #fff; +} + +nav.side-navbar.shrinked ul li.active > a i { + color: #fff; +} + +nav.side-navbar.shrinked .sidebar-header .title { + display: none; +} + +/* SIDEBAR MEDIAQUERIES ----------------------------------- */ +@media (max-width: 1199px) { + nav.side-navbar { + margin-left: -90px; + min-width: 90px; + max-width: 90px; + text-align: center; + overflow: hidden; + } + nav.side-navbar span.heading { + margin: 0; + } + nav.side-navbar ul li a { + padding: 15px 2px; + border: none; + font-size: 0.8em; + color: #aaa; + -webkit-transition: color 0.3s, background 0.3s; + transition: color 0.3s, background 0.3s; + } + nav.side-navbar ul li a[data-toggle="collapse"]::before { + content: '\f107'; + -webkit-transform: translateX(50%); + transform: translateX(50%); + position: absolute; + top: auto; + right: 50%; + bottom: 0; + left: auto; + } + nav.side-navbar ul li a[data-toggle="collapse"][aria-expanded="true"]::before { + content: '\f106'; + } + nav.side-navbar ul li a:hover { + color: #fff; + border: none; + } + nav.side-navbar ul li a:hover i { + color: #fff; + } + nav.side-navbar ul li a i { + margin-right: 0; + margin-bottom: 5px; + display: block; + font-size: 1.6em; + color: #333; + -webkit-transition: color 0.3s; + transition: color 0.3s; + } + nav.side-navbar ul li.active > a { + color: #fff; + } + nav.side-navbar ul li.active > a i { + color: #fff; + } + nav.side-navbar .sidebar-header .title { + display: none; + } + nav.side-navbar.shrinked { + margin-left: 0; + } + .content-inner { + width: 100%; + } + .content-inner.active { + width: calc(100% - 90px); + } +} + +/* +* ========================================================== +* MAIN NAVBAR +* ========================================================== +*/ +nav.navbar { + background: #2f333e; + padding-top: 15px; + padding-bottom: 15px; + color: #fff; + position: relative; + border-radius: 0; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.2); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.2); + z-index: 10; + padding-left: 0; + padding-right: 0; + /*==== Toggle Sidebar Btn ====*/ + /*==== Navbar Items ====*/ + /*==== Search Box ====*/ + /*==== Dropdowns ====*/ +} + +nav.navbar .badge { + width: 22px; + height: 22px; + line-height: 22px; + text-align: center; + padding: 0; + border-radius: 50%; +} + +nav.navbar .navbar-holder { + width: 100%; +} + +nav.navbar a { + color: inherit; +} + +nav.navbar .container-fluid { + width: 100%; +} + +nav.navbar .menu-btn { + margin-right: 20px; + font-size: 1.2em; + -webkit-transition: all 0.7s; + transition: all 0.7s; +} + +nav.navbar .menu-btn span { + width: 20px; + height: 2px; + background: #fff; + display: block; + margin: 4px auto 0; + -webkit-transition: all 0.3s cubic-bezier(0.81, -0.33, 0.345, 1.375); + transition: all 0.3s cubic-bezier(0.81, -0.33, 0.345, 1.375); +} + +nav.navbar .menu-btn span:nth-of-type(2) { + position: relative; + width: 35px; + -webkit-transform: rotateY(180deg); + transform: rotateY(180deg); +} + +nav.navbar .menu-btn span:nth-of-type(2)::before, nav.navbar .menu-btn span:nth-of-type(2)::after { + content: ''; + width: 6px; + height: 2px; + display: block; + background: #fff; + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + position: absolute; + top: 2px; + left: 0; + -webkit-transition: all 0.7s; + transition: all 0.7s; +} + +nav.navbar .menu-btn span:nth-of-type(2)::after { + -webkit-transform: rotate(145deg); + transform: rotate(145deg); + position: absolute; + top: -2px; + left: 0; +} + +nav.navbar .menu-btn.active span:first-of-type { + -webkit-transform: translateY(12px); + transform: translateY(12px); +} + +nav.navbar .menu-btn.active span:nth-of-type(2) { + -webkit-transform: none; + transform: none; +} + +nav.navbar .menu-btn.active span:last-of-type { + -webkit-transform: translateY(-12px); + transform: translateY(-12px); +} + +nav.navbar .nav-link { + position: relative; +} + +nav.navbar .nav-link span.badge-corner { + position: absolute; + top: 0; + right: 0; + font-weight: 400; + font-size: 0.7em; +} + +nav.navbar .nav-link.language span { + margin-left: .3rem; + vertical-align: middle; +} + +nav.navbar .nav-link.logout i { + margin-left: 10px; +} + +nav.navbar .nav-menu { + margin-bottom: 0; +} + +nav.navbar .search-box { + width: 100%; + height: 100%; + position: absolute; + top: 0; + right: 0; + padding: 0; + background: #fff; + z-index: 12; + border-radius: 0; + display: none; +} + +nav.navbar .search-box .dismiss { + position: absolute; + top: 50%; + right: 20px; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); + background: none; + border: none; + cursor: pointer; + font-size: 1.5em; + color: #999; +} + +nav.navbar .search-box form { + height: 100%; +} + +nav.navbar .search-box form input { + height: 100%; + border: none; + padding: 20px; +} + +nav.navbar .dropdown-toggle::after { + border: none !important; + content: '\f107'; + vertical-align: baseline; + font-family: 'FontAwesome'; + margin-left: .3rem; +} + +nav.navbar .dropdown-menu { + right: 0; + min-width: 250px; + left: auto; + margin-top: 15px; + margin-bottom: 0; + padding: 15px 0; + max-width: 400px; + border-radius: 0; + border: none; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1), -2px 0 2px rgba(0, 0, 0, 0.1); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.1), -2px 0 2px rgba(0, 0, 0, 0.1); +} + +nav.navbar .dropdown-menu .dropdown-item { + background: #fff; + padding: 10px 20px; + font-size: 0.8rem; + color: #777; + width: 100%; +} + +nav.navbar .dropdown-menu .dropdown-item:hover { + background: #f5f5f5; +} + +nav.navbar .dropdown-menu .dropdown-item i { + width: 30px; + height: 30px; + line-height: 30px; + background: #379392; + text-align: center; + color: #fff; + border-radius: 50%; + margin-right: 10px; +} + +nav.navbar .dropdown-menu .dropdown-item small { + margin-left: 40px; +} + +nav.navbar .dropdown-menu span { + position: static; + font-size: 0.9em; + color: #999; +} + +nav.navbar .dropdown-menu strong { + font-weight: 700; +} + +nav.navbar .dropdown-menu .msg-profile { + width: 45px; + height: 45px; + margin-right: 10px; +} + +nav.navbar .dropdown-menu h3 { + font-weight: 500; +} + +/* MAIN NAVBAR MEDIAQUERIES ----------------------------------- */ +@media (max-width: 1199px) { + nav.navbar { + /*==== Toggle Sidebar Btn ====*/ + } + nav.navbar .menu-btn { + margin-right: 20px; + font-size: 1.2em; + -webkit-transition: all 0.7s; + transition: all 0.7s; + } + nav.navbar .menu-btn span:first-of-type { + -webkit-transform: translateY(12px); + transform: translateY(12px); + } + nav.navbar .menu-btn span:nth-of-type(2) { + -webkit-transform: none; + transform: none; + } + nav.navbar .menu-btn span:nth-of-type(2)::before, nav.navbar .menu-btn span:nth-of-type(2)::after { + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + } + nav.navbar .menu-btn span:nth-of-type(2)::after { + -webkit-transform: rotate(145deg); + transform: rotate(145deg); + position: absolute; + top: -2px; + left: 0; + } + nav.navbar .menu-btn span:last-of-type { + -webkit-transform: translateY(-12px); + transform: translateY(-12px); + } + nav.navbar .menu-btn.active span:first-of-type { + -webkit-transform: none; + transform: none; + } + nav.navbar .menu-btn.active span:nth-of-type(2) { + -webkit-transform: rotateY(180deg); + transform: rotateY(180deg); + } + nav.navbar .menu-btn.active span:last-of-type { + -webkit-transform: none; + transform: none; + } +} + +@media (max-width: 575px) { + nav.navbar { + font-size: 14px; + } + nav.navbar .badge { + width: 19px; + height: 19px; + } + nav.navbar .nav-item > a { + font-size: 13px; + } + nav.navbar .dropdown-menu { + right: auto; + left: -50%; + -webkit-transform: translateX(-50%); + transform: translateX(-50%); + } +} + +/* +* ========================================================== +* DASHBOARD COUNTS SECTION +* ========================================================== +*/ +section.dashboard-counts .icon { + width: 40px; + height: 40px; + line-height: 40px; + text-align: center; + min-width: 40px; + max-width: 40px; + border-radius: 50%; +} + +section.dashboard-counts .title { + font-size: 1.1em; + font-weight: 300; + color: #777; + margin: 0 20px; +} + +section.dashboard-counts .progress { + margin-top: 10px; + height: 4px; +} + +section.dashboard-counts .number { + font-size: 1.8em; + font-weight: 300; +} + +section.dashboard-counts .number strong { + font-weight: 700; +} + +section.dashboard-counts .row { + padding: 30px 15px; + margin: 0; +} + +section.dashboard-counts div[class*='col-'] .item { + border-right: 1px solid #eee; + padding: 15px 0; +} + +section.dashboard-counts div[class*='col-']:last-of-type .item { + border-right: none; +} + +/* DASHBOARD COUNTS MEDIAQUERIES ------------------------ */ +@media (max-width: 1199px) { + section.dashboard-counts div[class*='col-']:nth-of-type(2) .item { + border-right: none; + } +} + +@media (max-width: 575px) { + section.dashboard-counts div[class*='col-'] .item { + border-right: none; + } +} + +/* +* ========================================================== +* DASHBOARD HEADER SECTION +* ========================================================== +*/ +.statistic { + padding: 20px 15px; + margin-bottom: 15px; +} + +.statistic:last-of-type { + margin-bottom: 0; +} + +.statistic strong { + font-size: 1.5em; + color: #333; + font-weight: 700; + line-height: 1; +} + +.statistic small { + color: #aaa; + text-transform: uppercase; +} + +.statistic .icon { + width: 40px; + height: 40px; + line-height: 40px; + text-align: center; + min-width: 40px; + max-width: 40px; + color: #fff; + border-radius: 50%; + margin-right: 15px; +} + +.chart .title { + padding: 15px 0 0 15px; +} + +.chart .title strong { + font-weight: 700; + font-size: 1.2em; +} + +.chart .title small { + color: #aaa; + text-transform: uppercase; +} + +.chart .line-chart { + width: 100%; + height: 100%; + padding: 20px 0; +} + +.chart .line-chart canvas { + width: calc(100% - 30px) !important; +} + +.chart .bar-chart { + margin-bottom: 15px; +} + +.chart .bar-chart canvas { + padding: 15px; + width: 100%; + margin: 0; +} + +/* DASHBOARD HEADER MEDIAQUERIES ------------------------*/ +@media (max-width: 991px) { + section.dashboard-header div[class*='col-'] { + margin-bottom: 20px; + } +} + +/* +* ========================================================== +* PROJECTS SECTION +* ========================================================== +*/ +.project .row { + margin: 0; + padding: 15px 0; + margin-bottom: 15px; +} + +.project div[class*='col-'] { + border-right: 1px solid #eee; +} + +.project .text h3 { + margin-bottom: 0; + color: #555; +} + +.project .text small { + color: #aaa; + font-size: 0.75em; +} + +.project .project-date span { + font-size: 0.9em; + color: #999; +} + +.project .image { + max-width: 50px; + min-width: 50px; + height: 50px; + margin-right: 15px; +} + +.project .time, +.project .comments, +.project .project-progress { + color: #999; + font-size: 0.9em; + margin-right: 20px; +} + +.project .time i, +.project .comments i, +.project .project-progress i { + margin-right: 5px; +} + +.project .project-progress { + width: 200px; +} + +.project .project-progress .progress { + height: 4px; +} + +.project .card { + margin-bottom: 0; +} + +/* PROJECTS SECTION ------------------------------------- */ +@media (max-width: 991px) { + .project .right-col { + margin-top: 20px; + margin-left: 65px; + } + .project .project-progress { + width: 150px; + } +} + +@media (max-width: 480px) { + .project .project-progress { + display: none; + } +} + +/* +* ========================================================== +* CLIENT SECTION +* ========================================================== +*/ +/*====== Work Amount Box ======*/ +.work-amount .chart { + margin: 40px auto; + position: relative; +} + +.work-amount .chart .text { + display: inline-block; + position: absolute; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); +} + +.work-amount .chart strong { + font-size: 1.5rem; +} + +.work-amount .chart span { + color: #999; + font-weight: 300; +} + +.work-amount li span { + font-size: 0.85em; + margin-bottom: 10px; + color: #777; + display: block; +} + +.work-amount li span::before { + content: ''; + display: inline-block; + margin-right: 10px; + width: 7px; + height: 7px; + line-height: 7px; + background: #85b4f2; + border-radius: 50%; +} + +/*====== Client Profile Box ======*/ +.client .client-avatar { + width: 100px; + height: 100px; + margin: 0 auto; + position: relative; +} + +.client .client-avatar .status { + content: ''; + display: block; + width: 18px; + height: 18px; + border: 3px solid #fff; + border-radius: 50%; + position: absolute; + right: 4px; + bottom: 4px; +} + +.client .client-title { + margin-top: 20px; +} + +.client .client-title h3 { + font-weight: 500; + color: #555; +} + +.client .client-title span { + font-size: 0.9em; + color: #aaa; + display: block; +} + +.client .client-title a { + padding: 2px 30px; + border-radius: 40px; + background: #54e69d; + color: #fff; + margin-top: 5px; + font-size: 0.9em; + text-decoration: none; +} + +.client .client-title a:hover { + background: #85b4f2; +} + +.client .client-info { + margin-top: 20px; +} + +.client .client-info strong { + font-weight: 700; +} + +.client .client-social { + margin-top: 20px; +} + +.client .client-social a { + color: #aaa; +} + +/*====== Total Overdue Box ======*/ +.overdue .chart canvas { + width: 100% !important; + z-index: 1; +} + +.overdue .card { + margin-bottom: 0; +} + +.overdue .card-body { + padding: 20px; +} + +.overdue .card-body small { + font-weight: 300; + color: #aaa; +} + +.overdue .card-body h3 { + margin-bottom: 5px; +} + +.overdue .number { + font-size: 1.8em; + font-weight: 400; + color: #555; + margin: 35px 0; +} + +/* +* ========================================================== +* FEEDS SECTION +* ========================================================== +*/ +/*====== Checklist Box ======*/ +.checklist label { + font-size: 0.8em; + color: #999; + line-height: 1.8em; + margin-bottom: 0; +} + +.checklist .item { + padding: 20px; +} + +.checklist .item:nth-of-type(even) { + background: #fafafa; +} + +/*====== Trending Articles Box ======*/ +.articles a { + text-decoration: none !important; + display: block; + margin-bottom: 0; + color: #555; +} + +.articles .badge { + font-size: 0.7em; + padding: 5px 10px; + line-height: 1; + margin-left: 10px; +} + +.articles .item { + padding: 20px; +} + +.articles .item:nth-of-type(even) { + background: #fafafa; +} + +.articles .item .image { + min-width: 50px; + max-width: 50px; + height: 50px; + margin-right: 15px; +} + +.articles .item img { + padding: 3px; + border: 1px solid #28a745; +} + +.articles .item h3 { + color: #555; + font-weight: 400; + margin-bottom: 0; +} + +.articles .item small { + color: #aaa; + font-size: 0.75em; +} + +/* +* ========================================================== +* UPDATES SECTION +* ========================================================== +*/ +/*====== Recent Updates Box ======*/ +.recent-updates .item { + padding: 20px; +} + +.recent-updates .item:nth-of-type(even) { + background: #fafafa; +} + +.recent-updates .icon { + margin-right: 10px; +} + +.recent-updates h5 { + margin-bottom: 5px; + color: #333; + font-weight: 400; +} + +.recent-updates p { + font-size: 0.8em; + color: #aaa; + margin-bottom: 0; +} + +.recent-updates .date { + font-size: 0.9em; + color: #adadad; +} + +.recent-updates .date strong { + font-size: 1.4em; + line-height: 0.8em; + display: block; +} + +.recent-updates .date span { + font-size: 0.9em; + font-weight: 300; +} + +/*====== Daily Feeds Box ======*/ +.daily-feeds .item { + padding: 20px; + border-bottom: 1px solid #eee; +} + +.daily-feeds .feed-profile { + max-width: 50px; + min-width: 50px; + margin-right: 10px; +} + +.daily-feeds h5 { + margin-bottom: 0; + color: #555; +} + +.daily-feeds span { + font-size: 0.8em; + color: #999; +} + +.daily-feeds .full-date { + font-size: 0.85em; + color: #aaa; + font-weight: 300; +} + +.daily-feeds .CTAs { + margin-top: 5px; +} + +.daily-feeds .CTAs a { + font-size: 0.7em; + padding: 3px 8px; + margin-right: 5px; +} + +.daily-feeds .CTAs a i { + margin-right: 5px; +} + +.daily-feeds .quote { + background: #fafafa; + margin-top: 5px; + border-radius: 0; + padding: 15px; + margin-left: 60px; +} + +.daily-feeds .quote small { + font-size: 0.75em; + color: #777; +} + +.daily-feeds .date { + font-size: 0.9em; + color: #aaa; +} + +/*====== Recent Activities Box ======*/ +.recent-activities .item { + padding: 0 15px; + border-bottom: 1px solid #eee; +} + +.recent-activities .item div[class*='col-'] { + padding: 15px; +} + +.recent-activities h5 { + font-weight: 400; + color: #333; +} + +.recent-activities p { + font-size: 0.75em; + color: #999; +} + +.recent-activities .icon { + width: 35px; + height: 35px; + line-height: 35px; + background: #f5f5f5; + text-align: center; + display: inline-block; +} + +.recent-activities .date { + font-size: 0.75em; + color: #999; + padding: 10px; +} + +.recent-activities .date-holder { + padding: 0 !important; + border-right: 1px solid #eee; +} + +/* +* ========================================================== +* FOOTER +* ========================================================== +*/ +footer.main-footer { + position: absolute; + bottom: 0; + width: 100%; + background: #2f333e; + color: #fff; + padding: 20px 10px; +} + +footer.main-footer a { + color: inherit; +} + +footer.main-footer p { + margin: 0; + font-size: 0.8em; +} + +/* FOOTER MEDIAQUERIES --------------------------------- */ +@media (max-width: 575px) { + footer.main-footer div[class*='col'] { + text-align: center !important; + } +} + +section.charts div[class*="col-"] { + margin-bottom: 30px; +} + +section.charts header { + padding: 30px 0; +} + +section.charts div[class*="col-"] { + margin-bottom: 0; +} + +/* +* ========================================================== +* LINE CHART +* ========================================================== +*/ +.line-chart-example .card-block { + padding: 20px; +} + +/* +* ========================================================== +* POLAR CHART +* ========================================================== +*/ +/* +* ========================================================== +* POLAR CHART +* ========================================================== +*/ +.polar-chart-example canvas { + max-width: 350px; + max-height: 350px; + margin: 20px auto; +} + +/* +* ========================================================== +* PIE CHART +* ========================================================== +*/ +.pie-chart-example canvas { + max-width: 350px; + max-height: 350px; + margin: 15px auto; +} + +/* +* ========================================================== +* RADAR CHART +* ========================================================== +*/ +.radar-chart-example canvas { + max-width: 350px; + max-height: 350px; + margin: 20px auto; +} + +/* FORMS MEDIAQUERIES -------------------------- */ +@media (max-width: 991px) { + section.charts h2 { + font-size: 1rem; + } +} + +/* +* ========================================================== +* FORMS +* ========================================================== +*/ +.form-control { + height: calc(2.25rem + 2px); + border: 1px solid #dee2e6; + border-radius: 0; + padding: 0.375rem 0.75rem; +} + +.form-control::-moz-placeholder { + font-size: 0.9em; + font-weight: 300; + font-family: "Poppins", sans-serif; + color: #aaa; +} + +.form-control::-webkit-input-placeholder { + font-size: 0.9em; + font-weight: 300; + font-family: "Poppins", sans-serif; + color: #aaa; +} + +.form-control:-ms-input-placeholder { + font-size: 0.9em; + font-weight: 300; + font-family: "Poppins", sans-serif; + color: #aaa; +} + +.form-control:focus { + color: #495057; + background-color: #fff; + border-color: #379392; + outline: none; + -webkit-box-shadow: 0 0 0 0.2rem rgba(55, 147, 146, 0.25); + box-shadow: 0 0 0 0.2rem rgba(55, 147, 146, 0.25); +} + +.form-control-sm { + height: calc(1.8125rem + 2px); + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; +} + +.form-control-lg { + height: calc(2.875rem + 2px); + padding: 0.5rem 1rem; + font-size: 1.25rem; + line-height: 1.5; +} + +textarea.form-control { + height: auto; +} + +select.form-control[size], select.form-control[multiple] { + height: auto; +} + +select.form-control option { + color: #999; +} + +.input-group .dropdown-menu { + padding: 15px; + color: #777; + border-radius: 0; +} + +.input-group .dropdown-menu a { + padding: 5px 0; + color: inherit; + text-decoration: none; +} + +.input-group .dropdown-menu a:hover { + color: #379392; + background: none; +} + +.input-group-text { + color: #868e96; + background: #f8f9fa; + border-color: #dee2e6; + border-radius: 0; +} + +.input-group-text .checkbox-template, .input-group-text .radio-template { + -webkit-transform: none; + transform: none; +} + +.form-control-label { + font-size: .9rem; + color: #777; +} + +button, input[type='submit'] { + cursor: pointer; + font-family: inherit; + font-weight: 300 !important; +} + +.input-group .dropdown-toggle { + background: #f5f5f5; + color: #777; +} + +.checkbox-template, .radio-template { + -webkit-transform: translateY(3px); + transform: translateY(3px); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; + position: relative; +} + +.checkbox-template + label, .radio-template + label { + margin-left: 10px; +} + +.checkbox-template::before, .radio-template::before { + margin-right: 10px; + content: ''; + display: inline-block; + -webkit-transform: translate(-2px, -2px); + transform: translate(-2px, -2px); + width: 18px; + height: 18px; + line-height: 18px; + text-align: center; + background: #dae2e7; + -webkit-transition: all 0.2s; + transition: all 0.2s; +} + +.checkbox-template::after, .radio-template::after { + content: '\f00c'; + width: 12px; + height: 12px; + line-height: 12px; + text-align: center; + display: block; + font-family: 'FontAwesome'; + position: absolute; + top: 1px; + left: 1px; + font-size: 0.7em; + opacity: 0; + -webkit-transition: all 0.2s; + transition: all 0.2s; + color: #fff; +} + +.checkbox-template:checked::before, .radio-template:checked::before { + background: #379392; +} + +.checkbox-template:checked::after, .radio-template:checked::after { + opacity: 1; +} + +.radio-template::before { + border-radius: 50%; + -webkit-transform: translate(-3px, -3px); + transform: translate(-3px, -3px); +} + +.radio-template::after { + width: 6px; + height: 6px; + line-height: 6px; + text-align: center; + position: absolute; + top: 3px; + left: 3px; + border-radius: 50%; + content: ''; +} + +.radio-template:checked::after { + background: #fff; +} + +input.input-material { + width: 100%; + border: none; + border-bottom: 1px solid #eee; + padding: 10px 0; +} + +input.input-material.is-invalid { + border-color: #dc3545 !important; +} + +input.input-material:focus { + border-color: #379392; +} + +input.input-material ~ label { + color: #aaa; + position: absolute; + top: 14px; + left: 0; + cursor: text; + -webkit-transition: all 0.2s; + transition: all 0.2s; + font-weight: 300; +} + +input.input-material ~ label.active { + font-size: 0.8rem; + top: -10px; + color: #379392; +} + +input.input-material.is-invalid ~ label { + color: #dc3545; +} + +.form-group-material { + position: relative; + margin-bottom: 30px; +} + +.modal-content { + border-radius: 0; +} + +.i-checks { + display: -webkit-box; + display: -ms-flexbox; + display: flex; +} + +/* +* ========================================================== +* FORM PAGE +* ========================================================== +*/ +.forms p { + font-size: 0.9em; + color: #555; +} + +.forms form small { + font-size: 0.8em; + color: #999; + font-weight: 300; +} + +.forms .line { + width: 100%; + height: 1px; + border-bottom: 1px dashed #eee; + margin: 30px 0; +} + +/* +* ========================================================== +* LOGIN PAGE +* ========================================================== +*/ +.login-page { + position: relative; +} + +.login-page::before { + content: ''; + width: 100%; + height: 100%; + display: block; + z-index: -1; + background-size: cover; + -webkit-filter: blur(10px); + filter: blur(10px); + z-index: 1; + position: absolute; + top: 0; + right: 0; +} + +.login-page .container { + min-height: 100vh; + z-index: 999; + padding: 20px; + position: relative; +} + +.login-page .form-holder { + width: 100%; + border-radius: 5px; + overflow: hidden; + margin-bottom: 50px; +} + +.login-page .form-holder .info, .login-page .form-holder .form { + min-height: 70vh; + padding: 40px; + height: 100%; +} + +.login-page .form-holder div[class*='col-'] { + padding: 0; +} + +.login-page .form-holder .info { + background: rgba(55, 147, 146, 0.9); + color: #fff; +} + +.login-page .form-holder .info h1 { + font-size: 2.5em; + font-weight: 600; +} + +.login-page .form-holder .info p { + font-weight: 300; +} + +.login-page .form-holder .form .form-group { + position: relative; + margin-bottom: 30px; +} + +.login-page .form-holder .form .content { + width: 100%; +} + +.login-page .form-holder .form form { + width: 100%; + max-width: 400px; +} + +.login-page .form-holder .form #login, .login-page .form-holder .form #register { + margin-bottom: 20px; + cursor: pointer; +} + +.login-page .form-holder .form a.forgot-pass, .login-page .form-holder .form a.signup { + font-size: 0.9em; + color: #85b4f2; +} + +.login-page .form-holder .form small { + color: #aaa; +} + +.login-page .form-holder .form .terms-conditions label { + cursor: pointer; + color: #aaa; + font-size: 0.9em; +} + +.login-page .copyrights { + width: 100%; + z-index: 9999; + position: absolute; + bottom: 0; + left: 0; + color: #fff; +} + +@media (max-width: 991px) { + .login-page .info, .login-page .form { + min-height: auto !important; + } + .login-page .info { + padding-top: 100px !important; + padding-bottom: 100px !important; + } +} + +/* + +===================== +STYLE SWITCHER FOR DEMO +===================== + +*/ +#style-switch-button { + position: fixed; + top: 120px; + right: 0px; + border-radius: 0; + z-index: 12; +} + +#style-switch { + width: 300px; + padding: 20px; + position: fixed; + top: 160px; + right: 0; + background: #fff; + border: solid 1px #ced4da; + z-index: 12; +} + +#style-switch h4 { + color: #495057; +} + +/* ========================================= + THEMING OF BOOTSTRAP COMPONENTS + ========================================= */ +/* + * 1. NAVBAR + */ +.navbar { + padding: 0.5rem 1rem; +} + +.navbar-brand { + display: inline-block; + padding-top: 0.3125rem; + padding-bottom: 0.3125rem; + margin-right: 1rem; + font-size: 1.25rem; +} + +.navbar-toggler { + padding: 0.25rem 0.75rem; + font-size: 1.25rem; + line-height: 1; + border: 1px solid transparent; + border-radius: 0.25rem; +} + +.navbar-light .navbar-brand { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-brand:focus, .navbar-light .navbar-brand:hover { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-nav .nav-link { + color: rgba(0, 0, 0, 0.5); +} + +.navbar-light .navbar-nav .nav-link:focus, .navbar-light .navbar-nav .nav-link:hover { + color: rgba(0, 0, 0, 0.7); +} + +.navbar-light .navbar-nav .nav-link.disabled { + color: rgba(0, 0, 0, 0.3); +} + +.navbar-light .navbar-nav .show > .nav-link, +.navbar-light .navbar-nav .active > .nav-link, +.navbar-light .navbar-nav .nav-link.show, +.navbar-light .navbar-nav .nav-link.active { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-toggler { + color: rgba(0, 0, 0, 0.5); + border-color: rgba(0, 0, 0, 0.1); +} + +.navbar-light .navbar-toggler-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); +} + +.navbar-light .navbar-text { + color: rgba(0, 0, 0, 0.5); +} + +.navbar-dark .navbar-brand { + color: #fff; +} + +.navbar-dark .navbar-brand:focus, .navbar-dark .navbar-brand:hover { + color: #fff; +} + +.navbar-dark .navbar-nav .nav-link { + color: rgba(255, 255, 255, 0.5); +} + +.navbar-dark .navbar-nav .nav-link:focus, .navbar-dark .navbar-nav .nav-link:hover { + color: rgba(255, 255, 255, 0.75); +} + +.navbar-dark .navbar-nav .nav-link.disabled { + color: rgba(255, 255, 255, 0.25); +} + +.navbar-dark .navbar-nav .show > .nav-link, +.navbar-dark .navbar-nav .active > .nav-link, +.navbar-dark .navbar-nav .nav-link.show, +.navbar-dark .navbar-nav .nav-link.active { + color: #fff; +} + +.navbar-dark .navbar-toggler { + color: rgba(255, 255, 255, 0.5); + border-color: rgba(255, 255, 255, 0.1); +} + +.navbar-dark .navbar-toggler-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); +} + +.navbar-dark .navbar-text { + color: rgba(255, 255, 255, 0.5); +} + +/* + * 2. BUTTONS + */ +.btn { + font-weight: 400; + border: 1px solid transparent; + padding: 0.375rem 0.75rem; + font-size: 1rem; + line-height: 1.5; + border-radius: 0.25rem; + -webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; +} + +.btn:focus, .btn.focus { + outline: 0; + -webkit-box-shadow: 0 0 0 0.2rem rgba(55, 147, 146, 0.25); + box-shadow: 0 0 0 0.2rem rgba(55, 147, 146, 0.25); +} + +.btn.disabled, .btn:disabled { + opacity: .65; +} + +.btn:not([disabled]):not(.disabled):active, .btn:not([disabled]):not(.disabled).active { + background-image: none; +} + +.btn-primary { + color: color-yiq(#379392); + background-color: #379392; + border-color: #379392; +} + +.btn-primary:hover { + color: color-yiq(#2d7776); + background-color: #2d7776; + border-color: #296e6d; +} + +.btn-primary:focus, .btn-primary.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(55, 147, 146, 0.5); + box-shadow: 0 0 0 0.2rem rgba(55, 147, 146, 0.5); +} + +.btn-primary.disabled, .btn-primary:disabled { + color: color-yiq(#379392); + background-color: #379392; + border-color: #379392; +} + +.btn-primary:not(:disabled):not(.disabled):active, .btn-primary:not(:disabled):not(.disabled).active, +.show > .btn-primary.dropdown-toggle { + color: color-yiq(#296e6d); + background-color: #296e6d; + border-color: #266564; +} + +.btn-primary:not(:disabled):not(.disabled):active:focus, .btn-primary:not(:disabled):not(.disabled).active:focus, +.show > .btn-primary.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(55, 147, 146, 0.5); + box-shadow: 0 0 0 0.2rem rgba(55, 147, 146, 0.5); +} + +.btn-secondary { + color: color-yiq(#868e96); + background-color: #868e96; + border-color: #868e96; +} + +.btn-secondary:hover { + color: color-yiq(#727b84); + background-color: #727b84; + border-color: #6c757d; +} + +.btn-secondary:focus, .btn-secondary.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); + box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); +} + +.btn-secondary.disabled, .btn-secondary:disabled { + color: color-yiq(#868e96); + background-color: #868e96; + border-color: #868e96; +} + +.btn-secondary:not(:disabled):not(.disabled):active, .btn-secondary:not(:disabled):not(.disabled).active, +.show > .btn-secondary.dropdown-toggle { + color: color-yiq(#6c757d); + background-color: #6c757d; + border-color: #666e76; +} + +.btn-secondary:not(:disabled):not(.disabled):active:focus, .btn-secondary:not(:disabled):not(.disabled).active:focus, +.show > .btn-secondary.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); + box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); +} + +.btn-success { + color: color-yiq(#28a745); + background-color: #28a745; + border-color: #28a745; +} + +.btn-success:hover { + color: color-yiq(#218838); + background-color: #218838; + border-color: #1e7e34; +} + +.btn-success:focus, .btn-success.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.btn-success.disabled, .btn-success:disabled { + color: color-yiq(#28a745); + background-color: #28a745; + border-color: #28a745; +} + +.btn-success:not(:disabled):not(.disabled):active, .btn-success:not(:disabled):not(.disabled).active, +.show > .btn-success.dropdown-toggle { + color: color-yiq(#1e7e34); + background-color: #1e7e34; + border-color: #1c7430; +} + +.btn-success:not(:disabled):not(.disabled):active:focus, .btn-success:not(:disabled):not(.disabled).active:focus, +.show > .btn-success.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.btn-info { + color: color-yiq(#17a2b8); + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-info:hover { + color: color-yiq(#138496); + background-color: #138496; + border-color: #117a8b; +} + +.btn-info:focus, .btn-info.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.btn-info.disabled, .btn-info:disabled { + color: color-yiq(#17a2b8); + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-info:not(:disabled):not(.disabled):active, .btn-info:not(:disabled):not(.disabled).active, +.show > .btn-info.dropdown-toggle { + color: color-yiq(#117a8b); + background-color: #117a8b; + border-color: #10707f; +} + +.btn-info:not(:disabled):not(.disabled):active:focus, .btn-info:not(:disabled):not(.disabled).active:focus, +.show > .btn-info.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.btn-warning { + color: color-yiq(#ffc107); + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-warning:hover { + color: color-yiq(#e0a800); + background-color: #e0a800; + border-color: #d39e00; +} + +.btn-warning:focus, .btn-warning.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.btn-warning.disabled, .btn-warning:disabled { + color: color-yiq(#ffc107); + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-warning:not(:disabled):not(.disabled):active, .btn-warning:not(:disabled):not(.disabled).active, +.show > .btn-warning.dropdown-toggle { + color: color-yiq(#d39e00); + background-color: #d39e00; + border-color: #c69500; +} + +.btn-warning:not(:disabled):not(.disabled):active:focus, .btn-warning:not(:disabled):not(.disabled).active:focus, +.show > .btn-warning.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.btn-danger { + color: color-yiq(#dc3545); + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-danger:hover { + color: color-yiq(#c82333); + background-color: #c82333; + border-color: #bd2130; +} + +.btn-danger:focus, .btn-danger.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.btn-danger.disabled, .btn-danger:disabled { + color: color-yiq(#dc3545); + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-danger:not(:disabled):not(.disabled):active, .btn-danger:not(:disabled):not(.disabled).active, +.show > .btn-danger.dropdown-toggle { + color: color-yiq(#bd2130); + background-color: #bd2130; + border-color: #b21f2d; +} + +.btn-danger:not(:disabled):not(.disabled):active:focus, .btn-danger:not(:disabled):not(.disabled).active:focus, +.show > .btn-danger.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.btn-light { + color: color-yiq(#f8f9fa); + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-light:hover { + color: color-yiq(#e2e6ea); + background-color: #e2e6ea; + border-color: #dae0e5; +} + +.btn-light:focus, .btn-light.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.btn-light.disabled, .btn-light:disabled { + color: color-yiq(#f8f9fa); + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-light:not(:disabled):not(.disabled):active, .btn-light:not(:disabled):not(.disabled).active, +.show > .btn-light.dropdown-toggle { + color: color-yiq(#dae0e5); + background-color: #dae0e5; + border-color: #d3d9df; +} + +.btn-light:not(:disabled):not(.disabled):active:focus, .btn-light:not(:disabled):not(.disabled).active:focus, +.show > .btn-light.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.btn-dark { + color: color-yiq(#343a40); + background-color: #343a40; + border-color: #343a40; +} + +.btn-dark:hover { + color: color-yiq(#23272b); + background-color: #23272b; + border-color: #1d2124; +} + +.btn-dark:focus, .btn-dark.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.btn-dark.disabled, .btn-dark:disabled { + color: color-yiq(#343a40); + background-color: #343a40; + border-color: #343a40; +} + +.btn-dark:not(:disabled):not(.disabled):active, .btn-dark:not(:disabled):not(.disabled).active, +.show > .btn-dark.dropdown-toggle { + color: color-yiq(#1d2124); + background-color: #1d2124; + border-color: #171a1d; +} + +.btn-dark:not(:disabled):not(.disabled):active:focus, .btn-dark:not(:disabled):not(.disabled).active:focus, +.show > .btn-dark.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.btn-default { + color: color-yiq(#ced4da); + background-color: #ced4da; + border-color: #ced4da; +} + +.btn-default:hover { + color: color-yiq(#b8c1ca); + background-color: #b8c1ca; + border-color: #b1bbc4; +} + +.btn-default:focus, .btn-default.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(206, 212, 218, 0.5); + box-shadow: 0 0 0 0.2rem rgba(206, 212, 218, 0.5); +} + +.btn-default.disabled, .btn-default:disabled { + color: color-yiq(#ced4da); + background-color: #ced4da; + border-color: #ced4da; +} + +.btn-default:not(:disabled):not(.disabled):active, .btn-default:not(:disabled):not(.disabled).active, +.show > .btn-default.dropdown-toggle { + color: color-yiq(#b1bbc4); + background-color: #b1bbc4; + border-color: #aab4bf; +} + +.btn-default:not(:disabled):not(.disabled):active:focus, .btn-default:not(:disabled):not(.disabled).active:focus, +.show > .btn-default.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(206, 212, 218, 0.5); + box-shadow: 0 0 0 0.2rem rgba(206, 212, 218, 0.5); +} + +.btn-outline-primary { + color: #379392; + background-color: transparent; + background-image: none; + border-color: #379392; +} + +.btn-outline-primary:hover { + color: #fff; + background-color: #379392; + border-color: #379392; +} + +.btn-outline-primary:focus, .btn-outline-primary.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(55, 147, 146, 0.5); + box-shadow: 0 0 0 0.2rem rgba(55, 147, 146, 0.5); +} + +.btn-outline-primary.disabled, .btn-outline-primary:disabled { + color: #379392; + background-color: transparent; +} + +.btn-outline-primary:not(:disabled):not(.disabled):active, .btn-outline-primary:not(:disabled):not(.disabled).active, +.show > .btn-outline-primary.dropdown-toggle { + color: color-yiq(#379392); + background-color: #379392; + border-color: #379392; +} + +.btn-outline-primary:not(:disabled):not(.disabled):active:focus, .btn-outline-primary:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-primary.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(55, 147, 146, 0.5); + box-shadow: 0 0 0 0.2rem rgba(55, 147, 146, 0.5); +} + +.btn-outline-secondary { + color: #868e96; + background-color: transparent; + background-image: none; + border-color: #868e96; +} + +.btn-outline-secondary:hover { + color: #fff; + background-color: #868e96; + border-color: #868e96; +} + +.btn-outline-secondary:focus, .btn-outline-secondary.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); + box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); +} + +.btn-outline-secondary.disabled, .btn-outline-secondary:disabled { + color: #868e96; + background-color: transparent; +} + +.btn-outline-secondary:not(:disabled):not(.disabled):active, .btn-outline-secondary:not(:disabled):not(.disabled).active, +.show > .btn-outline-secondary.dropdown-toggle { + color: color-yiq(#868e96); + background-color: #868e96; + border-color: #868e96; +} + +.btn-outline-secondary:not(:disabled):not(.disabled):active:focus, .btn-outline-secondary:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-secondary.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); + box-shadow: 0 0 0 0.2rem rgba(134, 142, 150, 0.5); +} + +.btn-outline-success { + color: #28a745; + background-color: transparent; + background-image: none; + border-color: #28a745; +} + +.btn-outline-success:hover { + color: #fff; + background-color: #28a745; + border-color: #28a745; +} + +.btn-outline-success:focus, .btn-outline-success.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.btn-outline-success.disabled, .btn-outline-success:disabled { + color: #28a745; + background-color: transparent; +} + +.btn-outline-success:not(:disabled):not(.disabled):active, .btn-outline-success:not(:disabled):not(.disabled).active, +.show > .btn-outline-success.dropdown-toggle { + color: color-yiq(#28a745); + background-color: #28a745; + border-color: #28a745; +} + +.btn-outline-success:not(:disabled):not(.disabled):active:focus, .btn-outline-success:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-success.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.btn-outline-info { + color: #17a2b8; + background-color: transparent; + background-image: none; + border-color: #17a2b8; +} + +.btn-outline-info:hover { + color: #fff; + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-outline-info:focus, .btn-outline-info.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.btn-outline-info.disabled, .btn-outline-info:disabled { + color: #17a2b8; + background-color: transparent; +} + +.btn-outline-info:not(:disabled):not(.disabled):active, .btn-outline-info:not(:disabled):not(.disabled).active, +.show > .btn-outline-info.dropdown-toggle { + color: color-yiq(#17a2b8); + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-outline-info:not(:disabled):not(.disabled):active:focus, .btn-outline-info:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-info.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.btn-outline-warning { + color: #ffc107; + background-color: transparent; + background-image: none; + border-color: #ffc107; +} + +.btn-outline-warning:hover { + color: #fff; + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-outline-warning:focus, .btn-outline-warning.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.btn-outline-warning.disabled, .btn-outline-warning:disabled { + color: #ffc107; + background-color: transparent; +} + +.btn-outline-warning:not(:disabled):not(.disabled):active, .btn-outline-warning:not(:disabled):not(.disabled).active, +.show > .btn-outline-warning.dropdown-toggle { + color: color-yiq(#ffc107); + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-outline-warning:not(:disabled):not(.disabled):active:focus, .btn-outline-warning:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-warning.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.btn-outline-danger { + color: #dc3545; + background-color: transparent; + background-image: none; + border-color: #dc3545; +} + +.btn-outline-danger:hover { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-outline-danger:focus, .btn-outline-danger.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.btn-outline-danger.disabled, .btn-outline-danger:disabled { + color: #dc3545; + background-color: transparent; +} + +.btn-outline-danger:not(:disabled):not(.disabled):active, .btn-outline-danger:not(:disabled):not(.disabled).active, +.show > .btn-outline-danger.dropdown-toggle { + color: color-yiq(#dc3545); + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-outline-danger:not(:disabled):not(.disabled):active:focus, .btn-outline-danger:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-danger.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.btn-outline-light { + color: #f8f9fa; + background-color: transparent; + background-image: none; + border-color: #f8f9fa; +} + +.btn-outline-light:hover { + color: #fff; + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-outline-light:focus, .btn-outline-light.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.btn-outline-light.disabled, .btn-outline-light:disabled { + color: #f8f9fa; + background-color: transparent; +} + +.btn-outline-light:not(:disabled):not(.disabled):active, .btn-outline-light:not(:disabled):not(.disabled).active, +.show > .btn-outline-light.dropdown-toggle { + color: color-yiq(#f8f9fa); + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-outline-light:not(:disabled):not(.disabled):active:focus, .btn-outline-light:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-light.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.btn-outline-dark { + color: #343a40; + background-color: transparent; + background-image: none; + border-color: #343a40; +} + +.btn-outline-dark:hover { + color: #fff; + background-color: #343a40; + border-color: #343a40; +} + +.btn-outline-dark:focus, .btn-outline-dark.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.btn-outline-dark.disabled, .btn-outline-dark:disabled { + color: #343a40; + background-color: transparent; +} + +.btn-outline-dark:not(:disabled):not(.disabled):active, .btn-outline-dark:not(:disabled):not(.disabled).active, +.show > .btn-outline-dark.dropdown-toggle { + color: color-yiq(#343a40); + background-color: #343a40; + border-color: #343a40; +} + +.btn-outline-dark:not(:disabled):not(.disabled):active:focus, .btn-outline-dark:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-dark.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.btn-lg { + padding: 0.5rem 1rem; + font-size: 1.25rem; + line-height: 1.5; + border-radius: 0.3rem; +} + +.btn-sm { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; + border-radius: 0.2rem; +} + +/* + * 3. TYPE + */ +body { + font-family: "Poppins", sans-serif; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + background-color: #fff; +} + +a { + color: #379392; + text-decoration: none; +} + +a:focus, a:hover { + color: #225b5b; + text-decoration: underline; +} + +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + margin-bottom: 0.5rem; + font-family: inherit; + font-weight: 700; + line-height: 1.1; + color: inherit; +} + +h1, +.h1 { + font-size: 1.5rem; +} + +h2, +.h2 { + font-size: 1.3rem; +} + +h3, +.h3 { + font-size: 1.2rem; +} + +h4, +.h4 { + font-size: 1.1rem; +} + +h5, +.h5 { + font-size: 1rem; +} + +h6, +.h6 { + font-size: 0.95rem; +} + +.lead { + font-size: 1.25rem; + font-weight: 300; +} + +.display-1 { + font-size: 6rem; + font-weight: 300; + line-height: 1.1; +} + +.display-2 { + font-size: 5.5rem; + font-weight: 300; + line-height: 1.1; +} + +.display-3 { + font-size: 4.5rem; + font-weight: 300; + line-height: 1.1; +} + +.display-4 { + font-size: 3.5rem; + font-weight: 300; + line-height: 1.1; +} + +hr { + border-top: 1px solid rgba(0, 0, 0, 0.1); +} + +small, +.small { + font-size: 80%; + font-weight: 400; +} + +mark, +.mark { + padding: 0.2em; + background-color: #fcf8e3; +} + +.blockquote { + padding: 0.5rem 1rem; + margin-bottom: 2rem; + font-size: 1.25rem; + border-left: 5px solid #379392; +} + +.blockquote-footer { + color: #868e96; +} + +.blockquote-footer::before { + content: "\2014 \00A0"; +} + +.text-primary { + color: #379392 !important; +} + +a.text-primary:focus, a.text-primary:hover { + color: #296e6d !important; +} + +/* + * 4. PAGINATION + */ +.page-item:first-child .page-link { + border-top-left-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} + +.page-item:last-child .page-link { + border-top-right-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; +} + +.page-item.active .page-link { + color: #fff; + background-color: #379392; + border-color: #379392; +} + +.page-item.disabled .page-link { + color: #868e96; + background-color: #fff; + border-color: #ddd; +} + +.page-link { + padding: 0.5rem 0.75rem; + margin-left: -1px; + line-height: 1.25; + color: #379392; + background-color: #fff; + border: 1px solid #ddd; +} + +.page-link:hover { + z-index: 2; + color: #225b5b; + background-color: #e9ecef; + border-color: #ddd; +} + +.page-link:focus { + z-index: 2; + outline: 0; + -webkit-box-shadow: none; + box-shadow: none; + text-decoration: none; +} + +.pagination-lg .page-link { + padding: 0.75rem 1.5rem; + font-size: 1.25rem; + line-height: 1.5; +} + +.pagination-lg .page-item:first-child .page-link { + border-top-left-radius: 0.3rem; + border-bottom-left-radius: 0.3rem; +} + +.pagination-lg .page-item:last-child .page-link { + border-top-right-radius: 0.3rem; + border-bottom-right-radius: 0.3rem; +} + +.pagination-sm .page-link { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; +} + +.pagination-sm .page-item:first-child .page-link { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; +} + +.pagination-sm .page-item:last-child .page-link { + border-top-right-radius: 0.2rem; + border-bottom-right-radius: 0.2rem; +} + +/* +* 5. UTILITIES +*/ +.bg-primary { + background-color: #379392 !important; +} + +a.bg-primary:focus, a.bg-primary:hover { + background-color: #296e6d !important; +} + +.bg-secondary { + background-color: #868e96 !important; +} + +a.bg-secondary:focus, a.bg-secondary:hover { + background-color: #6c757d !important; +} + +.bg-success { + background-color: #28a745 !important; +} + +a.bg-success:focus, a.bg-success:hover { + background-color: #1e7e34 !important; +} + +.bg-info { + background-color: #17a2b8 !important; +} + +a.bg-info:focus, a.bg-info:hover { + background-color: #117a8b !important; +} + +.bg-warning { + background-color: #ffc107 !important; +} + +a.bg-warning:focus, a.bg-warning:hover { + background-color: #d39e00 !important; +} + +.bg-danger { + background-color: #dc3545 !important; +} + +a.bg-danger:focus, a.bg-danger:hover { + background-color: #bd2130 !important; +} + +.bg-light { + background-color: #f8f9fa !important; +} + +a.bg-light:focus, a.bg-light:hover { + background-color: #dae0e5 !important; +} + +.bg-dark { + background-color: #343a40 !important; +} + +a.bg-dark:focus, a.bg-dark:hover { + background-color: #1d2124 !important; +} + +.border-primary { + border-color: #379392 !important; +} + +.border-secondary { + border-color: #868e96 !important; +} + +.border-success { + border-color: #28a745 !important; +} + +.border-info { + border-color: #17a2b8 !important; +} + +.border-warning { + border-color: #ffc107 !important; +} + +.border-danger { + border-color: #dc3545 !important; +} + +.border-light { + border-color: #f8f9fa !important; +} + +.border-dark { + border-color: #343a40 !important; +} + +.text-primary { + color: #379392 !important; +} + +a.text-primary:focus, a.text-primary:hover { + color: #296e6d !important; +} + +.text-secondary { + color: #868e96 !important; +} + +a.text-secondary:focus, a.text-secondary:hover { + color: #6c757d !important; +} + +.text-success { + color: #28a745 !important; +} + +a.text-success:focus, a.text-success:hover { + color: #1e7e34 !important; +} + +.text-info { + color: #17a2b8 !important; +} + +a.text-info:focus, a.text-info:hover { + color: #117a8b !important; +} + +.text-warning { + color: #ffc107 !important; +} + +a.text-warning:focus, a.text-warning:hover { + color: #d39e00 !important; +} + +.text-danger { + color: #dc3545 !important; +} + +a.text-danger:focus, a.text-danger:hover { + color: #bd2130 !important; +} + +.text-light { + color: #f8f9fa !important; +} + +a.text-light:focus, a.text-light:hover { + color: #dae0e5 !important; +} + +.text-dark { + color: #343a40 !important; +} + +a.text-dark:focus, a.text-dark:hover { + color: #1d2124 !important; +} + +.badge-primary { + color: color-yiq(#379392); + background-color: #379392; +} + +.badge-primary[href]:focus, .badge-primary[href]:hover { + color: color-yiq(#379392); + text-decoration: none; + background-color: #296e6d; +} + +.badge-secondary { + color: color-yiq(#868e96); + background-color: #868e96; +} + +.badge-secondary[href]:focus, .badge-secondary[href]:hover { + color: color-yiq(#868e96); + text-decoration: none; + background-color: #6c757d; +} + +.badge-success { + color: color-yiq(#28a745); + background-color: #28a745; +} + +.badge-success[href]:focus, .badge-success[href]:hover { + color: color-yiq(#28a745); + text-decoration: none; + background-color: #1e7e34; +} + +.badge-info { + color: color-yiq(#17a2b8); + background-color: #17a2b8; +} + +.badge-info[href]:focus, .badge-info[href]:hover { + color: color-yiq(#17a2b8); + text-decoration: none; + background-color: #117a8b; +} + +.badge-warning { + color: color-yiq(#ffc107); + background-color: #ffc107; +} + +.badge-warning[href]:focus, .badge-warning[href]:hover { + color: color-yiq(#ffc107); + text-decoration: none; + background-color: #d39e00; +} + +.badge-danger { + color: color-yiq(#dc3545); + background-color: #dc3545; +} + +.badge-danger[href]:focus, .badge-danger[href]:hover { + color: color-yiq(#dc3545); + text-decoration: none; + background-color: #bd2130; +} + +.badge-light { + color: color-yiq(#f8f9fa); + background-color: #f8f9fa; +} + +.badge-light[href]:focus, .badge-light[href]:hover { + color: color-yiq(#f8f9fa); + text-decoration: none; + background-color: #dae0e5; +} + +.badge-dark { + color: color-yiq(#343a40); + background-color: #343a40; +} + +.badge-dark[href]:focus, .badge-dark[href]:hover { + color: color-yiq(#343a40); + text-decoration: none; + background-color: #1d2124; +} + +/* +* 6.CODE +*/ +code { + padding: 0.2rem 0.4rem; + font-size: 90%; + color: #bd4147; + background-color: #f8f9fa; + border-radius: 0.25rem; +} + +a > code { + padding: 0; + color: inherit; + background-color: inherit; +} + +/* +* 7. NAV +*/ +.nav-link { + padding: 0.5rem 1rem; +} + +.nav-link.disabled { + color: #868e96; +} + +.nav-tabs .nav-item { + margin-bottom: -1px; +} + +.nav-tabs .nav-link { + border: 1px solid transparent; + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} + +.nav-tabs .nav-link:focus, .nav-tabs .nav-link:hover { + border-color: #e9ecef #e9ecef #dee2e6; +} + +.nav-tabs .nav-link.disabled { + color: #868e96; +} + +.nav-tabs .nav-link.active, +.nav-tabs .nav-item.show .nav-link { + color: #495057; + background-color: #fff; +} + +.nav-tabs .dropdown-menu { + margin-top: -1px; +} + +.nav-pills .nav-link { + border-radius: 0.25rem; +} + +.nav-pills .nav-link.active, +.nav-pills .show > .nav-link { + color: #fff; + background-color: #379392; +} + +/* +* 8. CARD +*/ +.card { + background-color: #fff; + border: 0 solid #eee; + border-radius: 0; +} + +.card > .list-group:first-child .list-group-item:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.card > .list-group:last-child .list-group-item:last-child { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.card-body { + padding: 1.25rem; +} + +.card-title { + margin-bottom: 1rem; +} + +.card-subtitle { + margin-top: -0.5rem; +} + +.card-link + .card-link { + margin-left: 1.25rem; +} + +.card-header { + padding: 1rem 1.25rem; + background-color: #fff; + border-bottom: 1px solid #eee; +} + +.card-header:first-child { + border-radius: 0 0 0 0; +} + +.card-header-transparent { + background-color: rgba(0, 0, 0, 0.3); + border-bottom: none; +} + +.card-footer { + padding: 1rem 1.25rem; + background-color: #f8f9fa; + border-top: 1px solid #eee; +} + +.card-footer:last-child { + border-radius: 0 0 0 0; +} + +.card-header-tabs { + margin-right: -0.625rem; + margin-bottom: -1rem; + margin-left: -0.625rem; + border-bottom: 0; +} + +.card-header-pills { + margin-right: -0.625rem; + margin-left: -0.625rem; +} + +.card-img-overlay { + padding: 1.25rem; +} + +.card-img-overlay-opacity { + background: rgba(0, 0, 0, 0.2); +} + +.card-img { + border-radius: 0; +} + +.card-img-top { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.card-img-bottom { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.card-deck .card { + margin-bottom: 15px; +} + +@media (min-width: 576px) { + .card-deck { + margin-right: -15px; + margin-left: -15px; + } + .card-deck .card { + margin-right: 15px; + margin-left: 15px; + } +} + +.custom-select { + height: calc(2.25rem + 2px); + padding: 0.375rem 1.75rem 0.375rem 0.75rem; + line-height: 1.5; + color: #495057; + vertical-align: middle; + background: #fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center; + background-size: 8px 10px; + border: 1px solid #ced4da; + border-radius: 0; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +.custom-select:focus { + border-color: #379392; + outline: 0; + -webkit-box-shadow: 0 0 0 0.2rem rgba(55, 147, 146, 0.5); + box-shadow: 0 0 0 0.2rem rgba(55, 147, 146, 0.5); +} + +.custom-select:focus::-ms-value { + color: #495057; + background-color: #fff; +} + +.custom-select[multiple], .custom-select[size]:not([size="1"]) { + height: auto; + padding-right: 0.75rem; + background-image: none; +} + +.custom-select:disabled { + color: #868e96; + background-color: #e9ecef; +} + +.custom-select::-ms-expand { + opacity: 0; +} + +.custom-select-sm { + height: calc(1.8125rem + 2px); + padding-top: 0.375rem; + padding-bottom: 0.375rem; + font-size: 75%; +} + +.custom-select-lg { + height: calc(2.875rem + 2px); + padding-top: 0.375rem; + padding-bottom: 0.375rem; + font-size: 125%; +} diff --git a/agent/static/excel/batch_daifa_template.xlsx b/agent/static/excel/batch_daifa_template.xlsx new file mode 100644 index 0000000..d0d11cb Binary files /dev/null and b/agent/static/excel/batch_daifa_template.xlsx differ diff --git a/agent/static/fonts/dashboard.eot b/agent/static/fonts/dashboard.eot new file mode 100644 index 0000000..961be2d Binary files /dev/null and b/agent/static/fonts/dashboard.eot differ diff --git a/agent/static/fonts/dashboard.svg b/agent/static/fonts/dashboard.svg new file mode 100644 index 0000000..426a66c --- /dev/null +++ b/agent/static/fonts/dashboard.svg @@ -0,0 +1,37 @@ + + + diff --git a/agent/static/fonts/dashboard.ttf b/agent/static/fonts/dashboard.ttf new file mode 100644 index 0000000..9f6bb3d Binary files /dev/null and b/agent/static/fonts/dashboard.ttf differ diff --git a/agent/static/fonts/dashboard.woff b/agent/static/fonts/dashboard.woff new file mode 100644 index 0000000..9ab67b2 Binary files /dev/null and b/agent/static/fonts/dashboard.woff differ diff --git a/agent/static/icons-reference/fonts/dashboard.eot b/agent/static/icons-reference/fonts/dashboard.eot new file mode 100644 index 0000000..961be2d Binary files /dev/null and b/agent/static/icons-reference/fonts/dashboard.eot differ diff --git a/agent/static/icons-reference/fonts/dashboard.svg b/agent/static/icons-reference/fonts/dashboard.svg new file mode 100644 index 0000000..426a66c --- /dev/null +++ b/agent/static/icons-reference/fonts/dashboard.svg @@ -0,0 +1,37 @@ + + + diff --git a/agent/static/icons-reference/fonts/dashboard.ttf b/agent/static/icons-reference/fonts/dashboard.ttf new file mode 100644 index 0000000..9f6bb3d Binary files /dev/null and b/agent/static/icons-reference/fonts/dashboard.ttf differ diff --git a/agent/static/icons-reference/fonts/dashboard.woff b/agent/static/icons-reference/fonts/dashboard.woff new file mode 100644 index 0000000..9ab67b2 Binary files /dev/null and b/agent/static/icons-reference/fonts/dashboard.woff differ diff --git a/agent/static/icons-reference/icons-reference.html b/agent/static/icons-reference/icons-reference.html new file mode 100644 index 0000000..2d3e4e8 --- /dev/null +++ b/agent/static/icons-reference/icons-reference.html @@ -0,0 +1,256 @@ + + +
+ + + +This font was created withFontastic
+