mirror of
https://github.com/TeaOSLab/EdgeAdmin.git
synced 2025-11-09 16:50:26 +08:00
增加套餐相关代码
This commit is contained in:
@@ -19,6 +19,7 @@ const (
|
|||||||
AdminModuleCodeAdmin AdminModuleCode = "admin" // 系统用户
|
AdminModuleCodeAdmin AdminModuleCode = "admin" // 系统用户
|
||||||
AdminModuleCodeUser AdminModuleCode = "user" // 平台用户
|
AdminModuleCodeUser AdminModuleCode = "user" // 平台用户
|
||||||
AdminModuleCodeFinance AdminModuleCode = "finance" // 财务
|
AdminModuleCodeFinance AdminModuleCode = "finance" // 财务
|
||||||
|
AdminModuleCodePlan AdminModuleCode = "plan" // 套餐
|
||||||
AdminModuleCodeLog AdminModuleCode = "log" // 日志
|
AdminModuleCodeLog AdminModuleCode = "log" // 日志
|
||||||
AdminModuleCodeSetting AdminModuleCode = "setting" // 设置
|
AdminModuleCodeSetting AdminModuleCode = "setting" // 设置
|
||||||
AdminModuleCodeCommon AdminModuleCode = "common" // 只要登录就可以访问的模块
|
AdminModuleCodeCommon AdminModuleCode = "common" // 只要登录就可以访问的模块
|
||||||
@@ -203,6 +204,11 @@ func AllModuleMaps() []maps.Map {
|
|||||||
"code": AdminModuleCodeFinance,
|
"code": AdminModuleCodeFinance,
|
||||||
"url": "/finance",
|
"url": "/finance",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "套餐管理",
|
||||||
|
"code": AdminModuleCodePlan,
|
||||||
|
"url": "/plans",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "日志审计",
|
"name": "日志审计",
|
||||||
"code": AdminModuleCodeLog,
|
"code": AdminModuleCodeLog,
|
||||||
|
|||||||
@@ -464,6 +464,14 @@ func (this *RPCClient) ServerStatBoardChartRPC() pb.ServerStatBoardChartServiceC
|
|||||||
return pb.NewServerStatBoardChartServiceClient(this.pickConn())
|
return pb.NewServerStatBoardChartServiceClient(this.pickConn())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *RPCClient) PlanRPC() pb.PlanServiceClient {
|
||||||
|
return pb.NewPlanServiceClient(this.pickConn())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RPCClient) UserPlanRPC() pb.UserPlanServiceClient {
|
||||||
|
return pb.NewUserPlanServiceClient(this.pickConn())
|
||||||
|
}
|
||||||
|
|
||||||
// Context 构造Admin上下文
|
// Context 构造Admin上下文
|
||||||
func (this *RPCClient) Context(adminId int64) context.Context {
|
func (this *RPCClient) Context(adminId int64) context.Context {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ type ParentAction struct {
|
|||||||
actions.ActionObject
|
actions.ActionObject
|
||||||
|
|
||||||
rpcClient *rpc.RPCClient
|
rpcClient *rpc.RPCClient
|
||||||
|
|
||||||
|
ctx context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parent 可以调用自身的一个简便方法
|
// Parent 可以调用自身的一个简便方法
|
||||||
@@ -117,6 +119,10 @@ func (this *ParentAction) RPC() *rpc.RPCClient {
|
|||||||
|
|
||||||
// AdminContext 获取Context
|
// AdminContext 获取Context
|
||||||
func (this *ParentAction) AdminContext() context.Context {
|
func (this *ParentAction) AdminContext() context.Context {
|
||||||
|
if this.ctx != nil {
|
||||||
|
return this.ctx
|
||||||
|
}
|
||||||
|
|
||||||
if this.rpcClient == nil {
|
if this.rpcClient == nil {
|
||||||
rpcClient, err := rpc.SharedRPC()
|
rpcClient, err := rpc.SharedRPC()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -125,7 +131,8 @@ func (this *ParentAction) AdminContext() context.Context {
|
|||||||
}
|
}
|
||||||
this.rpcClient = rpcClient
|
this.rpcClient = rpcClient
|
||||||
}
|
}
|
||||||
return this.rpcClient.Context(this.AdminId())
|
this.ctx = this.rpcClient.Context(this.AdminId())
|
||||||
|
return this.ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
// ViewData 视图里可以使用的数据
|
// ViewData 视图里可以使用的数据
|
||||||
|
|||||||
@@ -374,6 +374,21 @@ func (this *userMustAuth) modules(actionPtr actions.ActionWrapper, adminId int64
|
|||||||
"icon": "yen sign",
|
"icon": "yen sign",
|
||||||
"isOn": teaconst.IsPlus,
|
"isOn": teaconst.IsPlus,
|
||||||
},
|
},
|
||||||
|
/**{
|
||||||
|
"code": "plans",
|
||||||
|
"module": configloaders.AdminModuleCodePlan,
|
||||||
|
"name": "套餐管理",
|
||||||
|
"icon": "puzzle piece",
|
||||||
|
"isOn": teaconst.IsPlus,
|
||||||
|
"subItems": []maps.Map{
|
||||||
|
{
|
||||||
|
"name": "已购套餐",
|
||||||
|
"url": "/plans/userPlans",
|
||||||
|
"code": "userPlans",
|
||||||
|
"isOn": teaconst.IsPlus,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},**/
|
||||||
{
|
{
|
||||||
"code": "admins",
|
"code": "admins",
|
||||||
"module": configloaders.AdminModuleCodeAdmin,
|
"module": configloaders.AdminModuleCodeAdmin,
|
||||||
|
|||||||
34
web/public/js/components/common/datepicker.js
Normal file
34
web/public/js/components/common/datepicker.js
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
Vue.component("datepicker", {
|
||||||
|
props: ["v-name", "v-value", "v-bottom-left"],
|
||||||
|
mounted: function () {
|
||||||
|
let that = this
|
||||||
|
teaweb.datepicker(this.$refs.dayInput, function (v) {
|
||||||
|
that.day = v
|
||||||
|
that.change()
|
||||||
|
}, !!this.vBottomLeft)
|
||||||
|
},
|
||||||
|
data: function () {
|
||||||
|
let name = this.vName
|
||||||
|
if (name == null) {
|
||||||
|
name = "day"
|
||||||
|
}
|
||||||
|
|
||||||
|
let day = this.vValue
|
||||||
|
if (day == null) {
|
||||||
|
day = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: name,
|
||||||
|
day: day
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
change: function () {
|
||||||
|
this.$emit("change", this.day)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: `<div style="display: inline-block">
|
||||||
|
<input type="text" :name="name" v-model="day" placeholder="YYYY-MM-DD" style="width:8.6em" maxlength="10" @input="change" ref="dayInput" autocomplete="off"/>
|
||||||
|
</div>`
|
||||||
|
})
|
||||||
166
web/public/js/components/plans/plan-price-config-box.js
Normal file
166
web/public/js/components/plans/plan-price-config-box.js
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
// 套餐价格配置
|
||||||
|
Vue.component("plan-price-config-box", {
|
||||||
|
props: ["v-price-type", "v-monthly-price", "v-seasonally-price", "v-yearly-price", "v-bandwidth-price"],
|
||||||
|
data: function () {
|
||||||
|
let priceType = this.vPriceType
|
||||||
|
if (priceType == null) {
|
||||||
|
priceType = "period"
|
||||||
|
}
|
||||||
|
|
||||||
|
let monthlyPriceNumber = 0
|
||||||
|
let monthlyPrice = this.vMonthlyPrice
|
||||||
|
if (monthlyPrice == null || monthlyPrice <= 0) {
|
||||||
|
monthlyPrice = ""
|
||||||
|
} else {
|
||||||
|
monthlyPrice = monthlyPrice.toString()
|
||||||
|
monthlyPriceNumber = parseFloat(monthlyPrice)
|
||||||
|
if (isNaN(monthlyPriceNumber)) {
|
||||||
|
monthlyPriceNumber = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let seasonallyPriceNumber = 0
|
||||||
|
let seasonallyPrice = this.vSeasonallyPrice
|
||||||
|
if (seasonallyPrice == null || seasonallyPrice <= 0) {
|
||||||
|
seasonallyPrice = ""
|
||||||
|
} else {
|
||||||
|
seasonallyPrice = seasonallyPrice.toString()
|
||||||
|
seasonallyPriceNumber = parseFloat(seasonallyPrice)
|
||||||
|
if (isNaN(seasonallyPriceNumber)) {
|
||||||
|
seasonallyPriceNumber = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let yearlyPriceNumber = 0
|
||||||
|
let yearlyPrice = this.vYearlyPrice
|
||||||
|
if (yearlyPrice == null || yearlyPrice <= 0) {
|
||||||
|
yearlyPrice = ""
|
||||||
|
} else {
|
||||||
|
yearlyPrice = yearlyPrice.toString()
|
||||||
|
yearlyPriceNumber = parseFloat(yearlyPrice)
|
||||||
|
if (isNaN(yearlyPriceNumber)) {
|
||||||
|
yearlyPriceNumber = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let bandwidthPrice = this.vBandwidthPrice
|
||||||
|
let bandwidthPriceBaseNumber = 0
|
||||||
|
if (bandwidthPrice != null) {
|
||||||
|
bandwidthPriceBaseNumber = bandwidthPrice.base
|
||||||
|
} else {
|
||||||
|
bandwidthPrice = {
|
||||||
|
base: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let bandwidthPriceBase = ""
|
||||||
|
if (bandwidthPriceBaseNumber > 0) {
|
||||||
|
bandwidthPriceBase = bandwidthPriceBaseNumber.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
priceType: priceType,
|
||||||
|
monthlyPrice: monthlyPrice,
|
||||||
|
seasonallyPrice: seasonallyPrice,
|
||||||
|
yearlyPrice: yearlyPrice,
|
||||||
|
|
||||||
|
monthlyPriceNumber: monthlyPriceNumber,
|
||||||
|
seasonallyPriceNumber: seasonallyPriceNumber,
|
||||||
|
yearlyPriceNumber: yearlyPriceNumber,
|
||||||
|
|
||||||
|
bandwidthPriceBase: bandwidthPriceBase,
|
||||||
|
bandwidthPrice: bandwidthPrice
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
monthlyPrice: function (v) {
|
||||||
|
let price = parseFloat(v)
|
||||||
|
if (isNaN(price)) {
|
||||||
|
price = 0
|
||||||
|
}
|
||||||
|
this.monthlyPriceNumber = price
|
||||||
|
},
|
||||||
|
seasonallyPrice: function (v) {
|
||||||
|
let price = parseFloat(v)
|
||||||
|
if (isNaN(price)) {
|
||||||
|
price = 0
|
||||||
|
}
|
||||||
|
this.seasonallyPriceNumber = price
|
||||||
|
},
|
||||||
|
yearlyPrice: function (v) {
|
||||||
|
let price = parseFloat(v)
|
||||||
|
if (isNaN(price)) {
|
||||||
|
price = 0
|
||||||
|
}
|
||||||
|
this.yearlyPriceNumber = price
|
||||||
|
},
|
||||||
|
bandwidthPriceBase: function (v) {
|
||||||
|
let price = parseFloat(v)
|
||||||
|
if (isNaN(price)) {
|
||||||
|
price = 0
|
||||||
|
}
|
||||||
|
this.bandwidthPrice.base = price
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: `<div>
|
||||||
|
<input type="hidden" name="priceType" :value="priceType"/>
|
||||||
|
<input type="hidden" name="monthlyPrice" :value="monthlyPriceNumber"/>
|
||||||
|
<input type="hidden" name="seasonallyPrice" :value="seasonallyPriceNumber"/>
|
||||||
|
<input type="hidden" name="yearlyPrice" :value="yearlyPriceNumber"/>
|
||||||
|
<input type="hidden" name="bandwidthPriceJSON" :value="JSON.stringify(bandwidthPrice)"/>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<radio :v-value="'period'" :value="priceType" v-model="priceType"> 按时间周期</radio>
|
||||||
|
<radio :v-value="'bandwidth'" :value="priceType" v-model="priceType"> 按带宽用量</radio>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 按时间周期 -->
|
||||||
|
<div v-show="priceType == 'period'">
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
<table class="ui table">
|
||||||
|
<tr>
|
||||||
|
<td class="title">月度价格</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui input right labeled">
|
||||||
|
<input type="text" style="width: 7em" maxlength="10" v-model="monthlyPrice"/>
|
||||||
|
<span class="ui label">元</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="title">季度价格</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui input right labeled">
|
||||||
|
<input type="text" style="width: 7em" maxlength="10" v-model="seasonallyPrice"/>
|
||||||
|
<span class="ui label">元</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="title">年度价格</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui input right labeled">
|
||||||
|
<input type="text" style="width: 7em" maxlength="10" v-model="yearlyPrice"/>
|
||||||
|
<span class="ui label">元</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 按带宽 -->
|
||||||
|
<div v-show="priceType =='bandwidth'">
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
<table class="ui table">
|
||||||
|
<tr>
|
||||||
|
<td class="title">基础带宽费用</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui input right labeled">
|
||||||
|
<input type="text" v-model="bandwidthPriceBase" maxlength="10" style="width: 7em"/>
|
||||||
|
<span class="ui label">元/GB</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>`
|
||||||
|
})
|
||||||
18
web/public/js/components/plans/plan-price-view.js
Normal file
18
web/public/js/components/plans/plan-price-view.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
Vue.component("plan-price-view", {
|
||||||
|
props: ["v-plan"],
|
||||||
|
data: function () {
|
||||||
|
return {
|
||||||
|
plan: this.vPlan
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: `<div>
|
||||||
|
<span v-if="plan.priceType == 'period'">
|
||||||
|
<span v-if="plan.monthlyPrice > 0">月度:¥{{plan.monthlyPrice}}元<br/></span>
|
||||||
|
<span v-if="plan.seasonallyPrice > 0">季度:¥{{plan.seasonallyPrice}}元<br/></span>
|
||||||
|
<span v-if="plan.yearlyPrice > 0">年度:¥{{plan.yearlyPrice}}元</span>
|
||||||
|
</span>
|
||||||
|
<span v-if="plan.priceType == 'bandwidth'">
|
||||||
|
基础价格:¥{{plan.bandwidthPrice.base}}元/GB
|
||||||
|
</span>
|
||||||
|
</div>`
|
||||||
|
})
|
||||||
28
web/public/js/components/plans/plan-user-selector.js
Normal file
28
web/public/js/components/plans/plan-user-selector.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
Vue.component("plan-user-selector", {
|
||||||
|
mounted: function () {
|
||||||
|
let that = this
|
||||||
|
|
||||||
|
Tea.action("/plans/users/options")
|
||||||
|
.post()
|
||||||
|
.success(function (resp) {
|
||||||
|
that.users = resp.data.users
|
||||||
|
})
|
||||||
|
},
|
||||||
|
props: ["v-user-id"],
|
||||||
|
data: function () {
|
||||||
|
let userId = this.vUserId
|
||||||
|
if (userId == null) {
|
||||||
|
userId = 0
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
users: [],
|
||||||
|
userId: userId
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: `<div>
|
||||||
|
<select class="ui dropdown auto-width" name="userId" v-model="userId">
|
||||||
|
<option value="0">[选择用户]</option>
|
||||||
|
<option v-for="user in users" :value="user.id">{{user.fullname}} ({{user.username}})</option>
|
||||||
|
</select>
|
||||||
|
</div>`
|
||||||
|
})
|
||||||
16
web/public/js/components/server/bandwidth-limit-view.js
Normal file
16
web/public/js/components/server/bandwidth-limit-view.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// 显示带宽限制说明
|
||||||
|
Vue.component("bandwidth-limit-view", {
|
||||||
|
props: ["v-bandwidth-limit"],
|
||||||
|
data: function () {
|
||||||
|
return {
|
||||||
|
config: this.vBandwidthLimit
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: `<div>
|
||||||
|
<div v-if="config.isOn">
|
||||||
|
<span v-if="config.dailySize != null && config.dailySize.count > 0">日带宽限制:{{config.dailySize.count}}{{config.dailySize.unit.toUpperCase()}}<br/></span>
|
||||||
|
<span v-if="config.monthlySize != null && config.monthlySize.count > 0">月带宽限制:{{config.monthlySize.count}}{{config.monthlySize.unit.toUpperCase()}}<br/></span>
|
||||||
|
</div>
|
||||||
|
<span v-else class="disabled">没有限制。</span>
|
||||||
|
</div>`
|
||||||
|
})
|
||||||
@@ -69,13 +69,13 @@ window.teaweb = {
|
|||||||
}
|
}
|
||||||
document.head.append(element)
|
document.head.append(element)
|
||||||
},
|
},
|
||||||
datepicker: function (element, callback) {
|
datepicker: function (element, callback, bottomLeft) {
|
||||||
// 加载
|
// 加载
|
||||||
if (typeof Pikaday == "undefined") {
|
if (typeof Pikaday == "undefined") {
|
||||||
let that = this
|
let that = this
|
||||||
this.loadJS("/js/moment.min.js", function () {
|
this.loadJS("/js/moment.min.js", function () {
|
||||||
that.loadJS("/js/pikaday.js", function () {
|
that.loadJS("/js/pikaday.js", function () {
|
||||||
that.datepicker(element, callback)
|
that.datepicker(element, callback, bottomLeft)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
this.loadCSS("/js/pikaday.css")
|
this.loadCSS("/js/pikaday.css")
|
||||||
@@ -89,8 +89,8 @@ window.teaweb = {
|
|||||||
if (typeof (element) == "string") {
|
if (typeof (element) == "string") {
|
||||||
element = document.getElementById(element);
|
element = document.getElementById(element);
|
||||||
}
|
}
|
||||||
var year = new Date().getFullYear();
|
let year = new Date().getFullYear();
|
||||||
var picker = new Pikaday({
|
let picker = new Pikaday({
|
||||||
field: element,
|
field: element,
|
||||||
firstDay: 1,
|
firstDay: 1,
|
||||||
minDate: new Date(year - 1, 0, 1),
|
minDate: new Date(year - 1, 0, 1),
|
||||||
@@ -109,8 +109,9 @@ window.teaweb = {
|
|||||||
if (typeof (callback) == "function") {
|
if (typeof (callback) == "function") {
|
||||||
callback.call(Tea.Vue, picker.toString());
|
callback.call(Tea.Vue, picker.toString());
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
});
|
reposition: !bottomLeft
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
formatBytes: function (bytes) {
|
formatBytes: function (bytes) {
|
||||||
@@ -256,6 +257,21 @@ window.teaweb = {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
popupSuccess: function (url, width, height) {
|
||||||
|
let options = {}
|
||||||
|
if (width != null) {
|
||||||
|
options["width"] = width
|
||||||
|
}
|
||||||
|
if (height != null) {
|
||||||
|
options["height"] = height
|
||||||
|
}
|
||||||
|
options["callback"] = function () {
|
||||||
|
teaweb.success("保存成功", function () {
|
||||||
|
teaweb.reload()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.popup(url, options)
|
||||||
|
},
|
||||||
popupFinish: function () {
|
popupFinish: function () {
|
||||||
if (window.POPUP_CALLBACK != null) {
|
if (window.POPUP_CALLBACK != null) {
|
||||||
window.POPUP_CALLBACK.apply(window, arguments);
|
window.POPUP_CALLBACK.apply(window, arguments);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<menu-item :href="'/servers/certs/acme?type=available&keyword=' + keyword" :active="type == 'available'">有效证书({{countAvailable}})</menu-item>
|
<menu-item :href="'/servers/certs/acme?type=available&keyword=' + keyword" :active="type == 'available'">有效证书({{countAvailable}})</menu-item>
|
||||||
<menu-item :href="'/servers/certs/acme?type=expired&keyword=' + keyword" :active="type == 'expired'">过期证书<span :class="{red: countExpired > 0}">({{countExpired}})</span></menu-item>
|
<menu-item :href="'/servers/certs/acme?type=expired&keyword=' + keyword" :active="type == 'expired'">过期证书<span :class="{red: countExpired > 0}">({{countExpired}})</span></menu-item>
|
||||||
<menu-item :href="'/servers/certs/acme?type=7days&keyword=' + keyword" :active="type == '7days'">7天内过期<span :class="{red: count7Days > 0}">({{count7Days}})</span></menu-item>
|
<menu-item :href="'/servers/certs/acme?type=7days&keyword=' + keyword" :active="type == '7days'">7天内过期<span :class="{red: count7Days > 0}">({{count7Days}})</span></menu-item>
|
||||||
<menu-item :href="'/servers/certs/acme?type=30days&keyword=' + keyword" :active="type == '30days'">30天过期({{count30Days}})</menu-item>
|
<menu-item :href="'/servers/certs/acme?type=30days&keyword=' + keyword" :active="type == '30days'">30天内过期({{count30Days}})</menu-item>
|
||||||
<div class="item right">
|
<div class="item right">
|
||||||
<form class="ui form">
|
<form class="ui form">
|
||||||
<div class="ui fields inline">
|
<div class="ui fields inline">
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
<menu-item :href="'/servers/certs?type=available&keyword=' + keyword" :active="type == 'available'">有效证书({{countAvailable}})</menu-item>
|
<menu-item :href="'/servers/certs?type=available&keyword=' + keyword" :active="type == 'available'">有效证书({{countAvailable}})</menu-item>
|
||||||
<menu-item :href="'/servers/certs?type=expired&keyword=' + keyword" :active="type == 'expired'">过期证书<span :class="{red: countExpired > 0}">({{countExpired}})</span></menu-item>
|
<menu-item :href="'/servers/certs?type=expired&keyword=' + keyword" :active="type == 'expired'">过期证书<span :class="{red: countExpired > 0}">({{countExpired}})</span></menu-item>
|
||||||
<menu-item :href="'/servers/certs?type=7days&keyword=' + keyword" :active="type == '7days'">7天内过期<span :class="{red: count7Days > 0}">({{count7Days}})</span></menu-item>
|
<menu-item :href="'/servers/certs?type=7days&keyword=' + keyword" :active="type == '7days'">7天内过期<span :class="{red: count7Days > 0}">({{count7Days}})</span></menu-item>
|
||||||
<menu-item :href="'/servers/certs?type=30days&keyword=' + keyword" :active="type == '30days'">30天过期({{count30Days}})</menu-item>
|
<menu-item :href="'/servers/certs?type=30days&keyword=' + keyword" :active="type == '30days'">30天内过期({{count30Days}})</menu-item>
|
||||||
<span class="item">|</span>
|
<span class="item disabled">|</span>
|
||||||
<a href="" class="item" @click.prevent="uploadCert">[上传证书]</a>
|
<a href="" class="item" @click.prevent="uploadCert">[上传证书]</a>
|
||||||
</second-menu>
|
</second-menu>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user