Initial commit (code only without large binaries)

This commit is contained in:
robin
2026-02-15 18:58:44 +08:00
commit 35df75498f
9442 changed files with 1495866 additions and 0 deletions

View File

@@ -0,0 +1,111 @@
{$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><plan-user-selector @change="changeUserId"></plan-user-selector>
<p class="comment" v-if="userAccount != null">用户账户余额{{userAccount.total}}元。</p>
</td>
</tr>
<tr>
<td>备注名称 *</td>
<td>
<input type="text" name="name" maxlength="50" ref="focus"/>
<p class="comment">用于识别不同的套餐。</p>
</td>
</tr>
<tr>
<td>套餐 *</td>
<td>
<select class="ui dropdown auto-width" name="planId" v-model="planId" @change="changePlanId(planId)">
<option value="0">[选择套餐]</option>
<option v-for="plan in plans" :value="plan.id">{{plan.name}}</option>
</select>
<p class="comment" v-if="plan != null">
<span v-if="plan.priceType == 'period'">按时间周期付费,{{plan.monthlyPrice}}元/月,{{plan.seasonallyPrice}}元/季度,{{plan.yearlyPrice}}元/年。</span>
<span v-if="plan.priceType == 'traffic'">按流量付费。</span>
</p>
</td>
</tr>
<!-- 按时间周期计费 -->
<tbody v-if="plan != null && plan.priceType == 'period'">
<tr>
<td>周期 *</td>
<td>
<select class="ui dropdown auto-width" name="period" v-model="period">
<option value="monthly">按月</option>
<option value="seasonally">按季度</option>
<option value="yearly">按年</option>
</select>
</td>
</tr>
<tr v-if="period == 'monthly'">
<td>月数 *</td>
<td>
<div class="ui input right labeled">
<input type="text" name="countMonths" value="1" style="width: 5em" maxlength="4" v-model="countMonths"/>
<span class="ui label"></span>
</div>
</td>
</tr>
<tr v-if="period == 'seasonally'">
<td>季度数 *</td>
<td>
<div class="ui input right labeled">
<input type="text" name="countSeasons" value="1" style="width: 5em" maxlength="4" v-model="countSeasons"/>
<span class="ui label">季度</span>
</div>
</td>
</tr>
<tr v-if="period == 'yearly'">
<td>年数 *</td>
<td>
<div class="ui input right labeled">
<input type="text" name="countYears" value="1" style="width: 5em" maxlength="4" v-model="countYears"/>
<span class="ui label"></span>
</div>
</td>
</tr>
<tr>
<td>预计费用</td>
<td>
<span v-if="fee > 0">{{fee}}元</span>
<span v-else>-</span>
</td>
</tr>
</tbody>
<!-- 按流量计费 -->
<tbody v-if="plan != null && plan.priceType == 'traffic'">
<tr>
<td>结束日期</td>
<td>
<datepicker :v-name="'dayTo'" :v-bottom-left="true" :v-value="defaultDayTo"></datepicker>
</td>
</tr>
<tr>
<td>预计费用</td>
<td>月结</td>
</tr>
</tbody>
<!-- 按带宽计费 -->
<tbody v-if="plan != null && plan.priceType == 'bandwidth'">
<tr>
<td>结束日期</td>
<td>
<datepicker :v-name="'dayTo'" :v-bottom-left="true" :v-value="defaultDayTo"></datepicker>
</td>
</tr>
<tr>
<td>预计费用</td>
<td>月结</td>
</tr>
</tbody>
</table>
<submit-btn></submit-btn>
</form>

View File

@@ -0,0 +1,87 @@
Tea.context(function () {
this.planId = 0
this.plan = null
this.period = "monthly"
this.fee = 0
this.changePlanId = function (planId) {
if (planId == 0) {
this.plan = null
} else {
this.period = "monthly"
this.plan = this.plans.$find(function (k, v) {
return v.id == planId
})
if (this.plan != null) {
this.fee = this.plan.monthlyPrice
}
}
}
this.countMonths = 1
this.countSeasons = 1
this.countYears = 1
this.$delay(function () {
this.$watch("period", function (period) {
this.countMonths = 1
this.countSeasons = 1
this.countYears = 1
switch(period) {
case "monthly":
this.fee = this.countMonths * this.plan.monthlyPrice
break
case "seasonally":
this.fee = this.countSeasons * this.plan.seasonallyPrice
break
case "yearly":
this.fee = this.countYears * this.plan.yearlyPrice
break
}
})
this.$watch("countMonths", function (months) {
let count = parseInt(months)
if (isNaN(count) || count < 1) {
count = 1
}
this.fee = this.plan.monthlyPrice * count
})
this.$watch("countSeasons", function (seasons) {
let count = parseInt(seasons)
if (isNaN(count) || count < 1) {
count = 1
}
this.fee = this.plan.seasonallyPrice * count
})
this.$watch("countYears", function (years) {
let count = parseInt(years)
if (isNaN(count) || count < 1) {
count = 1
}
this.fee = this.plan.yearlyPrice * count
})
})
/**
* 用户账户
*/
this.userAccount = null
this.changeUserId = function (userId) {
if (userId == 0) {
this.userAccount = null
return
}
this.$post(".userAccount")
.params({
userId: userId
})
.success(function (resp) {
this.userAccount = resp.data.account
})
}
})

View File

@@ -0,0 +1,63 @@
{$layout}
<first-menu>
<menu-item href=".?type=available" :active="type == 'available'">有效套餐({{countAvailable}})</menu-item>
<menu-item href=".?type=expiring7" :active="type == 'expiring7'">7天内过期(<span v-if="countExpiring7 > 0" class="red">{{countExpiring7}}</span><span v-else>0</span>)</menu-item>
<menu-item href=".?type=expiring30" :active="type == 'expiring30'">30天内过期(<span v-if="countExpiring30 > 0" class="red">{{countExpiring30}}</span><span v-else>0</span>)</menu-item>
<menu-item href=".?type=expired" :active="type == 'expired'">过期套餐({{countExpired}})</menu-item>
<span class="item disabled">|</span>
<menu-item @click.prevent="createUserPlan">[新购套餐]</menu-item>
</first-menu>
<div v-if="!canUsePlans">
<div class="margin"></div>
<div class="ui message warning">尚未在 <a href="/finance/fee">[计费设置]</a> 里开启"使用套餐计费"选项,用户将无法使用套餐。</div>
</div>
<p class="comment" v-if="userPlans.length == 0">暂时还没有已购套餐。</p>
<table class="ui table selectable celled" v-if="userPlans.length > 0">
<thead>
<tr>
<th>用户</th>
<th class="three wide">套餐</th>
<th class="three wide">备注名称</th>
<th class="three wide">有效期</th>
<th class="three wide">网站</th>
<th class="two op">操作</th>
</tr>
</thead>
<tr v-for="userPlan in userPlans">
<td>
<span v-if="userPlan.user.id > 0">
<link-icon :href="'/users/user?userId=' + userPlan.user.id">{{userPlan.user.fullname}} <span class="small">({{userPlan.user.username}})</span></link-icon>
</span>
<span class="red" v-else>[已删除]</span>
</td>
<td>
<span v-if="userPlan.plan.id > 0">
<link-icon :href="'/plans/plan?planId=' + userPlan.plan.id">{{userPlan.plan.name}}</link-icon>
</span>
<span class="red" v-else>[已删除]</span>
</td>
<td>
<span v-if="userPlan.name.length > 0">{{userPlan.name}}</span>
<span v-else class="disabled">-</span>
</td>
<td>{{userPlan.dayTo}}</td>
<td>
<div v-if="userPlan.servers != null && userPlan.servers.length > 0">
<div v-for="server in userPlan.servers">
<a :href="'/servers/server/settings?serverId=' + server.id">{{server.name}}</a>
</div>
</div>
<span v-else class="disabled">尚未绑定</span>
</td>
<td>
<a href="" @click.prevent="renewUserPlan(userPlan.id)">续费</a> &nbsp;
<a href="" @click.prevent="deleteUserPlan(userPlan.id)">删除</a>
</td>
</tr>
</table>
<div class="page" v-html="page"></div>

View File

@@ -0,0 +1,19 @@
Tea.context(function () {
this.createUserPlan = function () {
teaweb.popupSuccess(".createPopup", null, "26em")
}
this.deleteUserPlan = function (userPlanId) {
teaweb.confirm("确定要删除此套餐吗?", function () {
this.$post(".delete")
.params({
userPlanId: userPlanId
})
.refresh()
})
}
this.renewUserPlan = function (userPlanId) {
teaweb.popupSuccess(".renewPopup?userPlanId=" + userPlanId, null, "26em")
}
})

View File

@@ -0,0 +1,100 @@
{$layout "layout_popup"}
<h3>续费套餐</h3>
<form class="ui form" data-tea-action="$" data-tea-success="success">
<csrf-token></csrf-token>
<input type="hidden" name="userPlanId" :value="userPlanId"/>
<table class="ui table definition selectable">
<tr>
<td class="title">用户</td>
<td>
<user-link :v-user="user"></user-link>
<p class="comment" v-if="userAccount != null">用户账户余额{{userAccount.total}}元。</p>
</td>
</tr>
<tr>
<td>套餐 *</td>
<td>
{{plan.name}}
<p class="comment" v-if="plan != null">
<span v-if="plan.priceType == 'period'">按时间周期付费,{{plan.monthlyPrice}}元/月,{{plan.seasonallyPrice}}元/季度,{{plan.yearlyPrice}}元/年。</span>
<span v-if="plan.priceType == 'traffic'">按流量付费。</span>
</p>
</td>
</tr>
<tbody v-if="plan != null && plan.priceType == 'period'">
<tr>
<td>周期 *</td>
<td>
<select class="ui dropdown auto-width" name="period" v-model="period">
<option value="monthly">按月</option>
<option value="seasonally">按季度</option>
<option value="yearly">按年</option>
</select>
</td>
</tr>
<tr v-if="period == 'monthly'">
<td>月数 *</td>
<td>
<div class="ui input right labeled">
<input type="text" name="countMonths" value="1" style="width: 5em" maxlength="4" v-model="countMonths"/>
<span class="ui label"></span>
</div>
</td>
</tr>
<tr v-if="period == 'seasonally'">
<td>季度数 *</td>
<td>
<div class="ui input right labeled">
<input type="text" name="countSeasons" value="1" style="width: 5em" maxlength="4" v-model="countSeasons"/>
<span class="ui label">季度</span>
</div>
</td>
</tr>
<tr v-if="period == 'yearly'">
<td>年数 *</td>
<td>
<div class="ui input right labeled">
<input type="text" name="countYears" value="1" style="width: 5em" maxlength="4" v-model="countYears"/>
<span class="ui label"></span>
</div>
</td>
</tr>
<tr>
<td>预计费用</td>
<td>
<span v-if="fee > 0">{{fee}}元</span>
<span v-else>-</span>
</td>
</tr>
</tbody>
<tbody v-if="plan != null && plan.priceType == 'traffic'">
<tr>
<td>结束日期</td>
<td>
<datepicker :v-name="'dayTo'" :v-bottom-left="true" :v-value="defaultDayTo"></datepicker>
</td>
</tr>
<tr>
<td>预计费用</td>
<td>月结</td>
</tr>
</tbody>
<tbody v-if="plan != null && plan.priceType == 'bandwidth'">
<tr>
<td>结束日期</td>
<td>
<datepicker :v-name="'dayTo'" :v-bottom-left="true" :v-value="defaultDayTo"></datepicker>
</td>
</tr>
<tr>
<td>预计费用</td>
<td>月结</td>
</tr>
</tbody>
</table>
<submit-btn></submit-btn>
</form>

View File

@@ -0,0 +1,50 @@
Tea.context(function () {
this.period = "monthly"
this.fee = this.plan.monthlyPrice
this.countMonths = 1
this.countSeasons = 1
this.countYears = 1
this.$delay(function () {
this.$watch("period", function (period) {
this.countMonths = 1
this.countSeasons = 1
this.countYears = 1
switch(period) {
case "monthly":
this.fee = this.countMonths * this.plan.monthlyPrice
break
case "seasonally":
this.fee = this.countSeasons * this.plan.seasonallyPrice
break
case "yearly":
this.fee = this.countYears * this.plan.yearlyPrice
break
}
})
this.$watch("countMonths", function (months) {
let count = parseInt(months)
if (isNaN(count) || count < 1) {
count = 1
}
this.fee = this.plan.monthlyPrice * count
})
this.$watch("countSeasons", function (seasons) {
let count = parseInt(seasons)
if (isNaN(count) || count < 1) {
count = 1
}
this.fee = this.plan.seasonallyPrice * count
})
this.$watch("countYears", function (years) {
let count = parseInt(years)
if (isNaN(count) || count < 1) {
count = 1
}
this.fee = this.plan.yearlyPrice * count
})
})
})