mirror of
https://github.com/TeaOSLab/EdgeAdmin.git
synced 2025-11-13 11:53:34 +08:00
[区域]可以设置区域-价格项目之间的价格
This commit is contained in:
@@ -75,6 +75,10 @@ func (this *RPCClient) NodeRegionRPC() pb.NodeRegionServiceClient {
|
|||||||
return pb.NewNodeRegionServiceClient(this.pickConn())
|
return pb.NewNodeRegionServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *RPCClient) NodePriceItemRPC() pb.NodePriceItemServiceClient {
|
||||||
|
return pb.NewNodePriceItemServiceClient(this.pickConn())
|
||||||
|
}
|
||||||
|
|
||||||
func (this *RPCClient) NodeIPAddressRPC() pb.NodeIPAddressServiceClient {
|
func (this *RPCClient) NodeIPAddressRPC() pb.NodeIPAddressServiceClient {
|
||||||
return pb.NewNodeIPAddressServiceClient(this.pickConn())
|
return pb.NewNodeIPAddressServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ type IndexAction struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *IndexAction) Init() {
|
func (this *IndexAction) Init() {
|
||||||
this.Nav("", "", "")
|
this.Nav("", "", "region")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *IndexAction) RunGet(params struct{}) {
|
func (this *IndexAction) RunGet(params struct{}) {
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ func init() {
|
|||||||
Post("/delete", new(DeleteAction)).
|
Post("/delete", new(DeleteAction)).
|
||||||
Post("/sort", new(SortAction)).
|
Post("/sort", new(SortAction)).
|
||||||
GetPost("/selectPopup", new(SelectPopupAction)).
|
GetPost("/selectPopup", new(SelectPopupAction)).
|
||||||
|
GetPost("/prices", new(PricesAction)).
|
||||||
|
GetPost("/updatePricePopup", new(UpdatePricePopupAction)).
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package items
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/regions/regionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreatePopupAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CreatePopupAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CreatePopupAction) RunGet(params struct{}) {
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *CreatePopupAction) RunPost(params struct {
|
||||||
|
Name string
|
||||||
|
BitsFrom int64
|
||||||
|
BitsTo int64
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
CSRF *actionutils.CSRF
|
||||||
|
}) {
|
||||||
|
params.Must.
|
||||||
|
Field("name", params.Name).
|
||||||
|
Require("请输入名称").
|
||||||
|
Field("bitsFrom", params.BitsFrom).
|
||||||
|
Gte(0, "请输入不小于0的整数").
|
||||||
|
Field("bitsTo", params.BitsTo).
|
||||||
|
Gte(0, "请输入不小于0的整数")
|
||||||
|
|
||||||
|
createResp, err := this.RPC().NodePriceItemRPC().CreateNodePriceItem(this.AdminContext(), &pb.CreateNodePriceItemRequest{
|
||||||
|
Name: params.Name,
|
||||||
|
Type: regionutils.PriceTypeTraffic,
|
||||||
|
BitsFrom: params.BitsFrom * 1000 * 1000,
|
||||||
|
BitsTo: params.BitsTo * 1000 * 1000,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer this.CreateLogInfo("创建流量价格项目", createResp.NodePriceItemId)
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package items
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DeleteAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *DeleteAction) RunPost(params struct {
|
||||||
|
ItemId int64
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("删除流量价格项目 %d", params.ItemId)
|
||||||
|
|
||||||
|
_, err := this.RPC().NodePriceItemRPC().DeleteNodePriceItem(this.AdminContext(), &pb.DeleteNodePriceItemRequest{NodePriceItemId: params.ItemId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
21
internal/web/actions/default/clusters/regions/items/init.go
Normal file
21
internal/web/actions/default/clusters/regions/items/init.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package items
|
||||||
|
|
||||||
|
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.AdminModuleCodeNode)).
|
||||||
|
Data("teaMenu", "clusters").
|
||||||
|
Data("teaSubMenu", "region").
|
||||||
|
Prefix("/clusters/regions/items").
|
||||||
|
GetPost("/createPopup", new(CreatePopupAction)).
|
||||||
|
GetPost("/updatePopup", new(UpdatePopupAction)).
|
||||||
|
Post("/delete", new(DeleteAction)).
|
||||||
|
EndAll()
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
package items
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UpdatePopupAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdatePopupAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdatePopupAction) RunGet(params struct {
|
||||||
|
ItemId int64
|
||||||
|
}) {
|
||||||
|
itemResp, err := this.RPC().NodePriceItemRPC().FindEnabledNodePriceItem(this.AdminContext(), &pb.FindEnabledNodePriceItemRequest{NodePriceItemId: params.ItemId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
item := itemResp.NodePriceItem
|
||||||
|
if item == nil {
|
||||||
|
this.NotFound("nodePriceItem", params.ItemId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["item"] = maps.Map{
|
||||||
|
"id": item.Id,
|
||||||
|
"name": item.Name,
|
||||||
|
"bitsFrom": item.BitsFrom,
|
||||||
|
"bitsTo": item.BitsTo,
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdatePopupAction) RunPost(params struct {
|
||||||
|
ItemId int64
|
||||||
|
Name string
|
||||||
|
BitsFrom int64
|
||||||
|
BitsTo int64
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
CSRF *actionutils.CSRF
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("修改流量价格项目", params.ItemId)
|
||||||
|
|
||||||
|
params.Must.
|
||||||
|
Field("name", params.Name).
|
||||||
|
Require("请输入名称").
|
||||||
|
Field("bitsFrom", params.BitsFrom).
|
||||||
|
Gte(0, "请输入不小于0的整数").
|
||||||
|
Field("bitsTo", params.BitsTo).
|
||||||
|
Gte(0, "请输入不小于0的整数")
|
||||||
|
|
||||||
|
_, err := this.RPC().NodePriceItemRPC().UpdateNodePriceItem(this.AdminContext(), &pb.UpdateNodePriceItemRequest{
|
||||||
|
NodePriceItemId: params.ItemId,
|
||||||
|
Name: params.Name,
|
||||||
|
BitsFrom: params.BitsFrom * 1000 * 1000,
|
||||||
|
BitsTo: params.BitsTo * 1000 * 1000,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
84
internal/web/actions/default/clusters/regions/prices.go
Normal file
84
internal/web/actions/default/clusters/regions/prices.go
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
package regions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/regions/regionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PricesAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *PricesAction) Init() {
|
||||||
|
this.Nav("", "", "price")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *PricesAction) RunGet(params struct{}) {
|
||||||
|
// 所有价格项目
|
||||||
|
itemsResp, err := this.RPC().NodePriceItemRPC().FindAllEnabledAndOnNodePriceItems(this.AdminContext(), &pb.FindAllEnabledAndOnNodePriceItemsRequest{Type: regionutils.PriceTypeTraffic})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
itemMaps := []maps.Map{}
|
||||||
|
for _, item := range itemsResp.NodePriceItems {
|
||||||
|
|
||||||
|
itemMaps = append(itemMaps, maps.Map{
|
||||||
|
"id": item.Id,
|
||||||
|
"name": item.Name,
|
||||||
|
"bitsFromString": this.formatBits(item.BitsFrom),
|
||||||
|
"bitsToString": this.formatBits(item.BitsTo),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["items"] = itemMaps
|
||||||
|
|
||||||
|
// 所有区域
|
||||||
|
regionsResp, err := this.RPC().NodeRegionRPC().FindAllEnabledNodeRegions(this.AdminContext(), &pb.FindAllEnabledNodeRegionsRequest{})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
regionMaps := []maps.Map{}
|
||||||
|
for _, region := range regionsResp.NodeRegions {
|
||||||
|
pricesMap := map[string]float32{}
|
||||||
|
if len(region.PricesJSON) > 0 {
|
||||||
|
err = json.Unmarshal(region.PricesJSON, &pricesMap)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
regionMaps = append(regionMaps, maps.Map{
|
||||||
|
"id": region.Id,
|
||||||
|
"isOn": region.IsOn,
|
||||||
|
"name": region.Name,
|
||||||
|
"prices": pricesMap,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["regions"] = regionMaps
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *PricesAction) formatBits(bits int64) string {
|
||||||
|
sizeHuman := ""
|
||||||
|
if bits < 1000 {
|
||||||
|
sizeHuman = numberutils.FormatInt64(bits) + "BPS"
|
||||||
|
} else if bits < 1_000_000 {
|
||||||
|
sizeHuman = fmt.Sprintf("%.2fKBPS", float64(bits)/1000)
|
||||||
|
} else if bits < 1_000_000_000 {
|
||||||
|
sizeHuman = fmt.Sprintf("%.2fMBPS", float64(bits)/1000/1000)
|
||||||
|
} else if bits < 1_000_000_000_000 {
|
||||||
|
sizeHuman = fmt.Sprintf("%.2fGBPS", float64(bits)/1000/1000/1000)
|
||||||
|
} else if bits < 1_000_000_000_000_000 {
|
||||||
|
sizeHuman = fmt.Sprintf("%.2fTBPS", float64(bits)/1000/1000/1000/1000)
|
||||||
|
} else {
|
||||||
|
sizeHuman = fmt.Sprintf("%.2fPTBPS", float64(bits)/1000/1000/1000/1000/1000)
|
||||||
|
}
|
||||||
|
return sizeHuman
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package regionutils
|
||||||
|
|
||||||
|
const (
|
||||||
|
PriceTypeTraffic = "traffic"
|
||||||
|
)
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
package regions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/actions"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UpdatePricePopupAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdatePricePopupAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdatePricePopupAction) RunGet(params struct {
|
||||||
|
RegionId int64
|
||||||
|
ItemId int64
|
||||||
|
}) {
|
||||||
|
// 区域
|
||||||
|
regionResp, err := this.RPC().NodeRegionRPC().FindEnabledNodeRegion(this.AdminContext(), &pb.FindEnabledNodeRegionRequest{NodeRegionId: params.RegionId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
region := regionResp.NodeRegion
|
||||||
|
if region == nil {
|
||||||
|
this.NotFound("nodeRegion", params.RegionId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Data["region"] = maps.Map{
|
||||||
|
"id": region.Id,
|
||||||
|
"isOn": region.IsOn,
|
||||||
|
"name": region.Name,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 当前价格
|
||||||
|
pricesMap := map[string]float32{}
|
||||||
|
if len(region.PricesJSON) > 0 {
|
||||||
|
err = json.Unmarshal(region.PricesJSON, &pricesMap)
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.Data["price"] = pricesMap[numberutils.FormatInt64(params.ItemId)]
|
||||||
|
|
||||||
|
// 价格项
|
||||||
|
itemResp, err := this.RPC().NodePriceItemRPC().FindEnabledNodePriceItem(this.AdminContext(), &pb.FindEnabledNodePriceItemRequest{NodePriceItemId: params.ItemId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
item := itemResp.NodePriceItem
|
||||||
|
if item == nil {
|
||||||
|
this.NotFound("nodePriceItem", params.ItemId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["item"] = maps.Map{
|
||||||
|
"id": item.Id,
|
||||||
|
"name": item.Name,
|
||||||
|
"bitsFrom": item.BitsFrom,
|
||||||
|
"bitsTo": item.BitsTo,
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UpdatePricePopupAction) RunPost(params struct {
|
||||||
|
RegionId int64
|
||||||
|
ItemId int64
|
||||||
|
Price float32
|
||||||
|
|
||||||
|
Must *actions.Must
|
||||||
|
CSRF *actionutils.CSRF
|
||||||
|
}) {
|
||||||
|
defer this.CreateLogInfo("修改区域 %d-价格项 %d 的价格", params.RegionId, params.ItemId)
|
||||||
|
|
||||||
|
_, err := this.RPC().NodeRegionRPC().UpdateNodeRegionPrice(this.AdminContext(), &pb.UpdateNodeRegionPriceRequest{
|
||||||
|
NodeRegionId: params.RegionId,
|
||||||
|
NodeItemId: params.ItemId,
|
||||||
|
Price: params.Price,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.Success()
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings"
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings"
|
||||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/grants"
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/grants"
|
||||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/regions"
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/regions"
|
||||||
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/regions/items"
|
||||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/csrf"
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/csrf"
|
||||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dashboard"
|
_ "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/db"
|
||||||
|
|||||||
6
web/views/@default/clusters/regions/@menu.html
Normal file
6
web/views/@default/clusters/regions/@menu.html
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<first-menu>
|
||||||
|
<menu-item href="/clusters/regions" code="region">区域</menu-item>
|
||||||
|
<menu-item href="/clusters/regions/prices" code="price">价格</menu-item>
|
||||||
|
<span class="item">|</span>
|
||||||
|
<menu-item><tip-icon content="可以设置节点所属区域,从而利用区域设置进行不同的价格设定。"></tip-icon></menu-item>
|
||||||
|
</first-menu>
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
{$layout}
|
{$layout}
|
||||||
|
{$template "menu"}
|
||||||
|
|
||||||
<first-menu>
|
<second-menu>
|
||||||
<menu-item @click.prevent="createRegion()">创建</menu-item>
|
<menu-item @click.prevent="createRegion()">创建</menu-item>
|
||||||
<span class="item">|</span>
|
</second-menu>
|
||||||
<menu-item><tip-icon content="可以设置节点所属区域,从而利用区域设置进行不同的价格设定。"></tip-icon></menu-item>
|
|
||||||
</first-menu>
|
|
||||||
|
|
||||||
<p class="comment" v-if="regions.length == 0">暂时还没有区域。</p>
|
<p class="comment" v-if="regions.length == 0">暂时还没有区域。</p>
|
||||||
|
|
||||||
<table class="ui table selectable" v-if="regions.length > 0" style="width: 35em" id="sortable-table">
|
<table class="ui table selectable" v-if="regions.length > 0" id="sortable-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width:3em"></th>
|
<th style="width:3em"></th>
|
||||||
|
|||||||
36
web/views/@default/clusters/regions/items/createPopup.html
Normal file
36
web/views/@default/clusters/regions/items/createPopup.html
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
{$layout "layout_popup"}
|
||||||
|
|
||||||
|
<h3>添加价格项</h3>
|
||||||
|
|
||||||
|
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||||
|
<csrf-token></csrf-token>
|
||||||
|
<table class="ui table definition selectable">
|
||||||
|
<tr>
|
||||||
|
<td class="title">名称 *</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="name" maxlength="100" ref="focus"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>最低流量 *</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui input right labeled">
|
||||||
|
<input type="text" name="bitsFrom" maxlength="16" style="width:10em" v-model="bitsFrom" autocomplete="off"/>
|
||||||
|
<span class="ui label">MBPS</span>
|
||||||
|
</div>
|
||||||
|
<p class="comment">采用1000进制<span v-if="bitsFromMB.length > 0">,相当于{{bitsFromMB}}</span>。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>最高流量 *</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui input right labeled">
|
||||||
|
<input type="text" name="bitsTo" maxlength="16" style="width:10em" v-model="bitsTo" autocomplete="off"/>
|
||||||
|
<span class="ui label">MBPS</span>
|
||||||
|
</div>
|
||||||
|
<p class="comment">采用1000进制<span v-if="bitsToMB.length > 0">,相当于{{bitsToMB}}</span>。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<submit-btn></submit-btn>
|
||||||
|
</form>
|
||||||
42
web/views/@default/clusters/regions/items/createPopup.js
Normal file
42
web/views/@default/clusters/regions/items/createPopup.js
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
Tea.context(function () {
|
||||||
|
this.bitsFrom = 0
|
||||||
|
this.bitsFromMB = ""
|
||||||
|
|
||||||
|
this.bitsTo = 0
|
||||||
|
this.bitsToMB = ""
|
||||||
|
|
||||||
|
this.$delay(function () {
|
||||||
|
let that = this
|
||||||
|
this.$watch("bitsFrom", function (v) {
|
||||||
|
this.bitsFromMB = that.formatBits(v)
|
||||||
|
})
|
||||||
|
this.$watch("bitsTo", function (v) {
|
||||||
|
this.bitsToMB = that.formatBits(v)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
this.formatBits = function (bits) {
|
||||||
|
bits = parseInt(bits)
|
||||||
|
if (isNaN(bits)) {
|
||||||
|
bits = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bits < 1000) {
|
||||||
|
return bits + "MB"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bits < 1000 * 1000) {
|
||||||
|
return (bits / 1000) + "GB"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bits < 1000 * 1000 * 1000) {
|
||||||
|
return (bits / 1000 / 1000) + "TB"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bits < 1000 * 1000 * 1000 * 1000) {
|
||||||
|
return (bits / 1000 / 1000 / 1000) + "PB"
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
})
|
||||||
37
web/views/@default/clusters/regions/items/updatePopup.html
Normal file
37
web/views/@default/clusters/regions/items/updatePopup.html
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{$layout "layout_popup"}
|
||||||
|
|
||||||
|
<h3>修改价格项</h3>
|
||||||
|
|
||||||
|
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||||
|
<csrf-token></csrf-token>
|
||||||
|
<input type="hidden" name="itemId" :value="item.id"/>
|
||||||
|
<table class="ui table definition selectable">
|
||||||
|
<tr>
|
||||||
|
<td class="title">名称 *</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="name" maxlength="100" ref="focus" v-model="item.name"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>最低流量 *</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui input right labeled">
|
||||||
|
<input type="text" name="bitsFrom" maxlength="16" style="width:10em" v-model="bitsFrom" autocomplete="off"/>
|
||||||
|
<span class="ui label">MBPS</span>
|
||||||
|
</div>
|
||||||
|
<p class="comment">采用1000进制<span v-if="bitsFromMB.length > 0">,相当于{{bitsFromMB}}</span>。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>最高流量 *</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui input right labeled">
|
||||||
|
<input type="text" name="bitsTo" maxlength="16" style="width:10em" v-model="bitsTo" autocomplete="off"/>
|
||||||
|
<span class="ui label">MBPS</span>
|
||||||
|
</div>
|
||||||
|
<p class="comment">采用1000进制<span v-if="bitsToMB.length > 0">,相当于{{bitsToMB}}</span>。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<submit-btn></submit-btn>
|
||||||
|
</form>
|
||||||
45
web/views/@default/clusters/regions/items/updatePopup.js
Normal file
45
web/views/@default/clusters/regions/items/updatePopup.js
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
Tea.context(function () {
|
||||||
|
this.bitsFrom = this.item.bitsFrom / 1000 / 1000
|
||||||
|
this.bitsFromMB = ""
|
||||||
|
|
||||||
|
this.bitsTo = this.item.bitsTo / 1000 / 1000
|
||||||
|
this.bitsToMB = ""
|
||||||
|
|
||||||
|
this.$delay(function () {
|
||||||
|
let that = this
|
||||||
|
this.$watch("bitsFrom", function (v) {
|
||||||
|
this.bitsFromMB = that.formatBits(v)
|
||||||
|
})
|
||||||
|
this.$watch("bitsTo", function (v) {
|
||||||
|
this.bitsToMB = that.formatBits(v)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.bitsFromMB = that.formatBits(this.bitsFrom)
|
||||||
|
this.bitsToMB = that.formatBits(this.bitsTo)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.formatBits = function (bits) {
|
||||||
|
bits = parseInt(bits)
|
||||||
|
if (isNaN(bits)) {
|
||||||
|
bits = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bits < 1000) {
|
||||||
|
return bits + "MB"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bits < 1000 * 1000) {
|
||||||
|
return (bits / 1000) + "GB"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bits < 1000 * 1000 * 1000) {
|
||||||
|
return (bits / 1000 / 1000) + "TB"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bits < 1000 * 1000 * 1000 * 1000) {
|
||||||
|
return (bits / 1000 / 1000 / 1000) + "PB"
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
})
|
||||||
15
web/views/@default/clusters/regions/prices.css
Normal file
15
web/views/@default/clusters/regions/prices.css
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
th span {
|
||||||
|
font-size: 0.9em;
|
||||||
|
font-weight: normal;
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
|
th a {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
td a {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
td:hover a {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
/*# sourceMappingURL=prices.css.map */
|
||||||
1
web/views/@default/clusters/regions/prices.css.map
Normal file
1
web/views/@default/clusters/regions/prices.css.map
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["prices.less"],"names":[],"mappings":"AAAA,EACC;EACC,gBAAA;EACA,mBAAA;EACA,WAAA;;AAJF,EAOC;EACC,mBAAA;;AAIF,EACC;EACC,aAAA;;AAIF,EAAE,MACD;EACC,eAAA","file":"prices.css"}
|
||||||
31
web/views/@default/clusters/regions/prices.html
Normal file
31
web/views/@default/clusters/regions/prices.html
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{$layout}
|
||||||
|
{$template "menu"}
|
||||||
|
|
||||||
|
<p class="comment" v-if="regions.length == 0">暂时还没有区域。</p>
|
||||||
|
|
||||||
|
<table class="ui table selectable">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width:7em">区域\范围</th>
|
||||||
|
<th v-for="item in items">
|
||||||
|
{{item.name}}
|
||||||
|
<a href="" title="修改" @click.prevent="updateItem(item.id)"><i class="icon pencil small"></i></a>
|
||||||
|
<a href="" title="删除" @click.prevent="deleteItem(item.id)"><i class="icon remove small"></i></a>
|
||||||
|
<br/>
|
||||||
|
<span>{{item.bitsFromString}}-{{item.bitsToString}}</span>
|
||||||
|
</th>
|
||||||
|
<th class="width10">
|
||||||
|
<a href="" @click.prevent="createItem">[+添加价格项]</a>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tr v-for="region in regions">
|
||||||
|
<td>{{region.name}}</td>
|
||||||
|
<td v-for="item in items">
|
||||||
|
<span v-if="region.prices[item.id.toString()] != null">¥{{region.prices[item.id.toString()]}}元/GB </span>
|
||||||
|
|
||||||
|
<a href="" title="修改单位价格" @click.prevent="updatePrice(region.id, item.id)">[设置]</a>
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
42
web/views/@default/clusters/regions/prices.js
Normal file
42
web/views/@default/clusters/regions/prices.js
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
Tea.context(function () {
|
||||||
|
this.createItem = function () {
|
||||||
|
teaweb.popup(Tea.url(".items.createPopup"), {
|
||||||
|
callback: function () {
|
||||||
|
teaweb.success("保存成功", function () {
|
||||||
|
teaweb.reload()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateItem = function (itemId) {
|
||||||
|
teaweb.popup(Tea.url(".items.updatePopup", {itemId: itemId}), {
|
||||||
|
callback: function () {
|
||||||
|
teaweb.success("保存成功", function () {
|
||||||
|
teaweb.reload()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.deleteItem = function (itemId) {
|
||||||
|
let that = this
|
||||||
|
teaweb.confirm("确定要删除此价格项吗?", function () {
|
||||||
|
that.$post(".items.delete")
|
||||||
|
.params({
|
||||||
|
itemId: itemId
|
||||||
|
})
|
||||||
|
.refresh()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updatePrice = function (regionId, itemId) {
|
||||||
|
teaweb.popup(Tea.url(".updatePricePopup", {regionId: regionId, itemId: itemId}), {
|
||||||
|
callback: function () {
|
||||||
|
teaweb.success("保存成功", function () {
|
||||||
|
teaweb.reload()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
23
web/views/@default/clusters/regions/prices.less
Normal file
23
web/views/@default/clusters/regions/prices.less
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
th {
|
||||||
|
span {
|
||||||
|
font-size: 0.9em;
|
||||||
|
font-weight: normal;
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
a {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
td:hover {
|
||||||
|
a {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
}
|
||||||
30
web/views/@default/clusters/regions/updatePricePopup.html
Normal file
30
web/views/@default/clusters/regions/updatePricePopup.html
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{$layout "layout_popup"}
|
||||||
|
|
||||||
|
<h3>修改价格</h3>
|
||||||
|
<form class="ui form" method="post" data-tea-action="$" data-tea-success="success">
|
||||||
|
<csrf-token></csrf-token>
|
||||||
|
<input type="hidden" name="regionId" :value="region.id"/>
|
||||||
|
<input type="hidden" name="itemId" :value="item.id"/>
|
||||||
|
|
||||||
|
<table class="ui table definition selectable">
|
||||||
|
<tr>
|
||||||
|
<td class="title">区域</td>
|
||||||
|
<td>{{region.name}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>价格项</td>
|
||||||
|
<td>{{item.name}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="title">单位价格 *</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui input right labeled">
|
||||||
|
<input type="text" name="price" maxlength="10" style="width:6em" ref="focus" v-model="price"/>
|
||||||
|
<span class="ui label">元/GB</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<submit-btn></submit-btn>
|
||||||
|
</form>
|
||||||
Reference in New Issue
Block a user