diff --git a/internal/configloaders/admin_module.go b/internal/configloaders/admin_module.go index f9de9abb..a562d552 100644 --- a/internal/configloaders/admin_module.go +++ b/internal/configloaders/admin_module.go @@ -10,14 +10,15 @@ import ( type AdminModuleCode = string const ( - AdminModuleCodeServer AdminModuleCode = "server" - AdminModuleCodeNode AdminModuleCode = "node" - AdminModuleCodeDNS AdminModuleCode = "dns" - AdminModuleCodeAdmin AdminModuleCode = "admin" // 系统用户 - AdminModuleCodeUser AdminModuleCode = "user" // 平台用户 - AdminModuleCodeLog AdminModuleCode = "log" - AdminModuleCodeSetting AdminModuleCode = "setting" - AdminModuleCodeCommon AdminModuleCode = "common" // 只要登录就可以访问的模块 + AdminModuleCodeServer AdminModuleCode = "server" // 网站 + AdminModuleCodeNode AdminModuleCode = "node" // 节点 + AdminModuleCodeDNS AdminModuleCode = "dns" // DNS + AdminModuleCodeAdmin AdminModuleCode = "admin" // 系统用户 + AdminModuleCodeUser AdminModuleCode = "user" // 平台用户 + AdminModuleCodeFinance AdminModuleCode = "finance" // 财务 + AdminModuleCodeLog AdminModuleCode = "log" // 日志 + AdminModuleCodeSetting AdminModuleCode = "setting" // 设置 + AdminModuleCodeCommon AdminModuleCode = "common" // 只要登录就可以访问的模块 ) var sharedAdminModuleMapping = map[int64]*AdminModuleList{} // adminId => AdminModuleList @@ -116,7 +117,6 @@ func FindFirstAdminModule(adminId int64) (module AdminModuleCode, ok bool) { return } - // 查找某个管理员名称 func FindAdminFullname(adminId int64) string { locker.Lock() @@ -157,6 +157,11 @@ func AllModuleMaps() []maps.Map { "code": AdminModuleCodeAdmin, "url": "/admins", }, + { + "name": "财务管理", + "code": AdminModuleCodeFinance, + "url": "/finance", + }, { "name": "日志审计", "code": AdminModuleCodeLog, diff --git a/internal/rpc/rpc_client.go b/internal/rpc/rpc_client.go index eb7ef065..8d234bb1 100644 --- a/internal/rpc/rpc_client.go +++ b/internal/rpc/rpc_client.go @@ -236,6 +236,10 @@ func (this *RPCClient) UserRPC() pb.UserServiceClient { return pb.NewUserServiceClient(this.pickConn()) } +func (this *RPCClient) UserBillRPC() pb.UserBillServiceClient { + return pb.NewUserBillServiceClient(this.pickConn()) +} + // 构造Admin上下文 func (this *RPCClient) Context(adminId int64) context.Context { ctx := context.Background() diff --git a/internal/web/actions/default/finance/bills/generate.go b/internal/web/actions/default/finance/bills/generate.go new file mode 100644 index 00000000..32b0f6f6 --- /dev/null +++ b/internal/web/actions/default/finance/bills/generate.go @@ -0,0 +1,38 @@ +package bills + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/actions" + timeutil "github.com/iwind/TeaGo/utils/time" + "time" +) + +type GenerateAction struct { + actionutils.ParentAction +} + +func (this *GenerateAction) Init() { + this.Nav("", "", "generate") +} + +func (this *GenerateAction) RunGet(params struct{}) { + this.Data["month"] = timeutil.Format("Ym", time.Now().AddDate(0, -1, 0)) + + this.Show() +} + +func (this *GenerateAction) RunPost(params struct { + Month string + + Must *actions.Must +}) { + defer this.CreateLogInfo("手动生成上个月(" + params.Month + ")账单") + + _, err := this.RPC().UserBillRPC().GenerateAllUserBills(this.AdminContext(), &pb.GenerateAllUserBillsRequest{Month: params.Month}) + if err != nil { + this.ErrorPage(err) + return + } + this.Success() +} diff --git a/internal/web/actions/default/finance/bills/index.go b/internal/web/actions/default/finance/bills/index.go new file mode 100644 index 00000000..4eb3e21f --- /dev/null +++ b/internal/web/actions/default/finance/bills/index.go @@ -0,0 +1,65 @@ +package bills + +import ( + "fmt" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/maps" +) + +type IndexAction struct { + actionutils.ParentAction +} + +func (this *IndexAction) Init() { + this.Nav("", "", "index") +} + +func (this *IndexAction) RunGet(params struct { + PaidFlag int32 `default:"-1"` + UserId int64 + Month string +}) { + countResp, err := this.RPC().UserBillRPC().CountAllUserBills(this.AdminContext(), &pb.CountAllUserBillsRequest{}) + if err != nil { + this.ErrorPage(err) + return + } + + page := this.NewPage(countResp.Count) + this.Data["page"] = page.AsHTML() + + billsResp, err := this.RPC().UserBillRPC().ListUserBills(this.AdminContext(), &pb.ListUserBillsRequest{ + PaidFlag: params.PaidFlag, + UserId: params.UserId, + Month: params.Month, + Offset: page.Offset, + Size: page.Size, + }) + if err != nil { + this.ErrorPage(err) + return + } + billMaps := []maps.Map{} + for _, bill := range billsResp.UserBills { + var userMap maps.Map = nil + if bill.User != nil { + userMap = maps.Map{ + "id": bill.User.Id, + "fullname": bill.User.Fullname, + } + } + billMaps = append(billMaps, maps.Map{ + "id": bill.Id, + "isPaid": bill.IsPaid, + "month": bill.Month, + "amount": fmt.Sprintf("%.2f", bill.Amount), + "typeName": bill.TypeName, + "user": userMap, + "description": bill.Description, + }) + } + this.Data["bills"] = billMaps + + this.Show() +} diff --git a/internal/web/actions/default/finance/bills/init.go b/internal/web/actions/default/finance/bills/init.go new file mode 100644 index 00000000..9ca6f057 --- /dev/null +++ b/internal/web/actions/default/finance/bills/init.go @@ -0,0 +1,22 @@ +package bills + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/configloaders" + "github.com/TeaOSLab/EdgeAdmin/internal/web/helpers" + "github.com/iwind/TeaGo" +) + +func init() { + TeaGo.BeforeStart(func(server *TeaGo.Server) { + server. + Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeFinance)). + Data("teaMenu", "finance"). + + // 财务管理 + Prefix("/finance/bills"). + Get("", new(IndexAction)). + GetPost("/generate", new(GenerateAction)). + + EndAll() + }) +} diff --git a/internal/web/actions/default/finance/index.go b/internal/web/actions/default/finance/index.go new file mode 100644 index 00000000..d68cafae --- /dev/null +++ b/internal/web/actions/default/finance/index.go @@ -0,0 +1,18 @@ +package finance + +import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + +type IndexAction struct { + actionutils.ParentAction +} + +func (this *IndexAction) Init() { + this.Nav("", "", "") +} + +func (this *IndexAction) RunGet(params struct{}) { + // TODO 暂时先跳转到账单页,将来做成Dashboard + this.RedirectURL("/finance/bills") + + this.Show() +} diff --git a/internal/web/actions/default/finance/init.go b/internal/web/actions/default/finance/init.go new file mode 100644 index 00000000..791b0a3a --- /dev/null +++ b/internal/web/actions/default/finance/init.go @@ -0,0 +1,20 @@ +package finance + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/configloaders" + "github.com/TeaOSLab/EdgeAdmin/internal/web/helpers" + "github.com/iwind/TeaGo" +) + +func init() { + TeaGo.BeforeStart(func(server *TeaGo.Server) { + server. + Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeFinance)). + + // 财务管理 + Prefix("/finance"). + Get("", new(IndexAction)). + + EndAll() + }) +} diff --git a/internal/web/helpers/user_must_auth.go b/internal/web/helpers/user_must_auth.go index 143d8b88..a7ae8503 100644 --- a/internal/web/helpers/user_must_auth.go +++ b/internal/web/helpers/user_must_auth.go @@ -203,6 +203,12 @@ func (this *userMustAuth) modules(adminId int64) []maps.Map { "name": "平台用户", "icon": "users", }, + { + "code": "finance", + "module": configloaders.AdminModuleCodeFinance, + "name": "财务管理", + "icon": "yen sign", + }, { "code": "admins", "module": configloaders.AdminModuleCodeAdmin, diff --git a/internal/web/import.go b/internal/web/import.go index 46d96209..af0dc8e4 100644 --- a/internal/web/import.go +++ b/internal/web/import.go @@ -16,6 +16,8 @@ import ( _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dashboard" _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/db" _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns" + _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/finance" + _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/finance/bills" _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/index" _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/log" _ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/logout" diff --git a/web/views/@default/finance/bills/@menu.html b/web/views/@default/finance/bills/@menu.html new file mode 100644 index 00000000..3496ecd7 --- /dev/null +++ b/web/views/@default/finance/bills/@menu.html @@ -0,0 +1,4 @@ + + 账单 + 生成账单 + \ No newline at end of file diff --git a/web/views/@default/finance/bills/generate.html b/web/views/@default/finance/bills/generate.html new file mode 100644 index 00000000..8d5798b7 --- /dev/null +++ b/web/views/@default/finance/bills/generate.html @@ -0,0 +1,8 @@ +{$layout} +{$template "menu"} + +
+
+ +

多次点击不会重复生成同样的账单。

+
diff --git a/web/views/@default/finance/bills/generate.js b/web/views/@default/finance/bills/generate.js new file mode 100644 index 00000000..2838ed71 --- /dev/null +++ b/web/views/@default/finance/bills/generate.js @@ -0,0 +1,16 @@ +Tea.context(function () { + this.generateBills = function () { + let that = this + teaweb.confirm("确定要生成上个月的账单吗?", function () { + that.$post(".generate") + .params({ + month: that.month + }) + .success(function () { + teaweb.success("生成成功", function () { + window.location = "/finance/bills" + }) + }) + }) + } +}) \ No newline at end of file diff --git a/web/views/@default/finance/bills/index.html b/web/views/@default/finance/bills/index.html new file mode 100644 index 00000000..1b998d76 --- /dev/null +++ b/web/views/@default/finance/bills/index.html @@ -0,0 +1,30 @@ +{$layout} +{$template "menu"} + +

暂时还没有账单。

+ + + + + + + + + + + + + + + + + + + + +
用户月份项目金额描述已支付
{{bill.user.fullname}}{{bill.month}}{{bill.typeName}}¥{{bill.amount}}元{{bill.description}} + Y + N +
+ +
\ No newline at end of file