This commit is contained in:
unknown
2026-02-04 20:27:13 +08:00
commit 3b042d1dad
9410 changed files with 1488147 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
<first-menu>
<menu-item href="/finance/bills" code="index">账单</menu-item>
</first-menu>

View File

@@ -0,0 +1,142 @@
{$layout}
{$template "menu"}
<table class="ui table selectable definition">
<tr>
<td class="title">账单编号</td>
<td>{{bill.code}}</td>
</tr>
<tr>
<td>结算周期</td>
<td>{{bill.pricePeriodName}}</td>
</tr>
<tr>
<td>月份</td>
<td>{{bill.month}}</td>
</tr>
<tr v-if="bill.pricePeriod == 'daily'">
<td>日期</td>
<td>
<span v-if="bill.pricePeriod == 'daily'">
<span v-if="bill.dayFrom == bill.dayTo">{{bill.dayFrom}}</span>
<span v-else>{{bill.dayFrom}} - {{bill.dayTo}}</span>
</span>
</td>
</tr>
<tr>
<td>项目</td>
<td>{{bill.typeName}}</td>
</tr>
<tr>
<td>金额</td>
<td>¥{{bill.amount}}元
<span v-if="!bill.canPay" class="small grey">&nbsp;(预估)</span>
</td>
</tr>
<tr>
<td>描述</td>
<td>{{bill.description}}</td>
</tr>
<tr>
<td>是否已支付</td>
<td>
<span class="green" v-if="bill.isPaid">Y</span>
<span v-else class="disabled">N</span>
</td>
</tr>
<tr>
<td>操作</td>
<td>
<span v-if="bill.isPaid" class="disabled" title="已支付,无需重复支付">已支付</span>
<span v-else>
<a href="" v-if="bill.canPay" @click.prevent="payBill(bill.id)">支付</a>
<span v-else class="disabled"></span>
</span>
</td>
</tr>
</table>
<div v-if="serverBills.length > 0">
<h4>网站/套餐子账单</h4>
<table class="ui table selectable">
<thead>
<tr>
<th>网站</th>
<th>套餐</th>
<th>流量</th>
<th>带宽</th>
<th>费用</th>
<th>更新时间</th>
</tr>
</thead>
<tr v-for="serverBill in serverBills">
<td>
<span v-if="serverBill.server != null && serverBill.server.id > 0">{{serverBill.server.name}}</span>
<span v-else class="disabled">-</span>
</td>
<td>
<span v-if="serverBill.plan.id > 0">
{{serverBill.plan.name}}
<span class="small grey" v-if="serverBill.plan.priceType == 'traffic'">(按流量计费)</span>
<span class="small grey" v-if="serverBill.plan.priceType == 'bandwidth'">(按带宽计费)</span>
</span>
<span v-else>默认
<span v-if="serverBill.priceType == 'traffic'" class="small grey">(按流量计费)</span>
<span v-if="serverBill.priceType == 'bandwidth'" class="small grey">(按带宽计费)</span>
<span v-if="serverBill.priceType.length == 0" class="small grey">(按区域流量计费)</span>
</span>
</td>
<td>{{serverBill.traffic}}</td>
<td>{{serverBill.bandwidthPercentileSize}}<span class="grey small">{{serverBill.bandwidthPercentile}}th</span></td>
<td>{{serverBill.amount}}元</td>
<td>{{serverBill.createdTime}}</td>
</tr>
</table>
<div v-html="page"></div>
</div>
<div v-if="trafficBills.length > 0">
<h4>流量子账单</h4>
<table class="ui table selectable celled">
<thead>
<tr>
<th>区域</th>
<th>计费方式</th>
<th>计费带宽</th>
<th>带宽百分位</th>
<th>计费流量</th>
<th>流量包使用</th>
<th>单位价格</th>
<th>总价格</th>
</tr>
</thead>
<tr v-for="trafficBill in trafficBills">
<td>
<span v-if="trafficBill.region.id > 0">{{trafficBill.region.name}}</span>
<span v-else class="disabled">[未分区]</span>
</td>
<td>{{trafficBill.priceTypeName}}</td>
<td>
<span v-if="trafficBill.priceType == 'bandwidth'">{{trafficBill.bandwidthMB}}</span>
<span v-else class="disabled">-</span>
</td>
<td>
<span v-if="trafficBill.priceType == 'bandwidth'">{{trafficBill.bandwidthPercentile}}th</span>
<span v-else class="disabled">-</span>
</td>
<td>
<span v-if="trafficBill.priceType == 'traffic'">{{trafficBill.trafficGB}}</span>
<span v-else class="disabled">-</span>
</td>
<td>
<span v-if="trafficBill.priceType == 'traffic' && trafficBill.trafficPackageGB != '0B'">{{trafficBill.trafficPackageGB}}</span>
<span v-else class="disabled">-</span>
</td>
<td>
<span v-if="trafficBill.priceType == 'bandwidth'">{{trafficBill.pricePerUnit}}元/Mbps</span>
<span v-if="trafficBill.priceType == 'traffic'">{{trafficBill.pricePerUnit}}元/GiB</span>
</td>
<td>{{trafficBill.amount}}元</td>
</tr>
</table>
</div>

View File

@@ -0,0 +1,15 @@
Tea.context(function () {
this.payBill = function (billId) {
teaweb.confirm("确定要支付此账单吗? ", function () {
this.$post(".pay")
.params({
billId: billId
})
.success(function () {
teaweb.success("支付成功", function () {
teaweb.reload()
})
})
})
}
})

View File

@@ -0,0 +1,68 @@
{$layout}
<div v-if="bills.length > 0" style="margin-top: 1em">
<p>未支付账单总额:{{unpaidAmount}}元,账号总余额为:{{accountTotal}}元。<a href="/finance/charge"><span class="red" v-if="unpaidAmount > accountTotal">您的余额已不足以支付账单,请及时充值。</span></a></p>
<div class="margin"></div>
</div>
<form class="ui form" method="get" action="/finance/bills">
<div class="ui fields inline">
<div class="ui field">
<select class="ui dropdown selectable" name="paidFlag" v-model="paidFlag">
<option value="-1">[支付状态]</option>
<option value="0">未支付</option>
<option value="1">已支付</option>
</select>
</div>
<div class="ui field">
<button class="ui button" type="submit">搜索</button>
</div>
</div>
</form>
<p class="comment" v-if="bills.length == 0">暂时还没有账单。</p>
<table class="ui table selectable celled" v-if="bills.length > 0">
<thead>
<tr>
<th>账单编号</th>
<th style="width: 6em">结算周期</th>
<th style="width: 6em">月份</th>
<th style="width: 8em">日期</th>
<th style="width: 8em">项目</th>
<th style="width: 8em">金额</th>
<th style="width: 6em">已支付</th>
<th class="one op">操作</th>
</tr>
</thead>
<tr v-for="bill in bills">
<td>
<a :href="'/finance/bills/bill?code=' + bill.code">{{bill.code}}</a>
<div v-if="bill.isOverdue">
<span class="ui red basic small">逾期</span>
</div>
</td>
<td>{{bill.pricePeriodName}}</td>
<td>{{bill.month}}</td>
<td>
<span v-if="bill.pricePeriod == 'daily'">
<span v-if="bill.dayFrom == bill.dayTo">{{bill.dayFrom}}</span>
<span v-else>{{bill.dayFrom}} - {{bill.dayTo}}</span>
</span>
</td>
<td>{{bill.typeName}}</td>
<td><span :class="{disabled: bill.amount == 0}">¥{{bill.amount}}元</span>
<span class="grey small" v-if="!bill.canPay"><br/>预估</span>
</td>
<td>
<span class="green" v-if="bill.isPaid">Y</span>
<span v-else class="disabled">N</span>
</td>
<td>
<a href="" v-if="!bill.isPaid && bill.canPay" @click.prevent="payBill(bill.id)">支付</a>
<span v-if="bill.isPaid" class="disabled" title="已支付,无需重复支付">支付</span>
</td>
</tr>
</table>
<div class="page" v-html="page"></div>

View File

@@ -0,0 +1,15 @@
Tea.context(function () {
this.payBill = function (billId) {
teaweb.confirm("确定要支付此账单吗? ", function () {
this.$post(".pay")
.params({
billId: billId
})
.success(function () {
teaweb.success("支付成功", function () {
teaweb.reload()
})
})
})
}
})

View File

@@ -0,0 +1,37 @@
{$layout}
<div class="margin"></div>
<div v-if="!config.enablePay">
<div class="ui message" v-if="config.disablePageHTML.length == 0">暂不提供在线充值功能,请联系管理员充值。</div>
<div v-if="config.disablePageHTML.length > 0" v-html="config.disablePageHTML"></div>
</div>
<div v-if="config.enablePay">
<form class="ui form" data-tea-action="$" data-tea-success="success">
<csrf-token></csrf-token>
<table class="ui table definition">
<tr>
<td class="title">充值金额 *</td>
<td>
<div class="ui left labeled input">
<span class="ui label"></span>
<input type="text" name="amount" maxlength="10" style="width: 10em" ref="focus"/>
</div>
</td>
</tr>
<tr>
<td>选择支付方式 *</td>
<td>
<div class="methods-box">
<div class="method-box" :class="{active: methodCode == method.code}" v-for="method in methods" @click.event="selectMethod(method)">
<radio name="methodCode" :value="method.code" :v-value="method.code" v-model="methodCode">{{method.name}}</radio>
<p class="comment">{{method.description}}</p>
</div>
</div>
</td>
</tr>
</table>
<submit-btn>下一步 &raquo;</submit-btn>
</form>
</div>

View File

@@ -0,0 +1,14 @@
Tea.context(function () {
this.methodCode = 0
if (this.methods.length > 0) {
this.methodCode = this.methods[0].code
}
this.selectMethod = function (method) {
this.methodCode = method.code
}
this.success = function (resp) {
window.location = "/finance/pay?code=" + resp.data.code + "&from=" + this.currentURL
}
})

View File

@@ -0,0 +1,53 @@
{$layout}
<h3>账户余额</h3>
<table class="ui table selectable definition">
<tr>
<td class="title">余额</td>
<td>{{account.total}}元</td>
</tr>
<tr v-if="account.totalFrozen > 0">
<td>冻结</td>
<td>{{account.totalFrozen}}元 &nbsp; <tip-icon content="冻结后不能使用的余额"></tip-icon></td>
</tr>
</table>
<h3>最近收支明细<a href="/finance/logs" v-if="logs.length > 0"><span class="small grey">更多...</span></a></h3>
<p class="comment" v-if="logs.length == 0">暂时还没有操作日志。</p>
<table class="ui table selectable celled" v-if="logs.length > 0">
<thead>
<tr>
<th class="two wide">操作类型</th>
<th class="two wide">操作金额</th>
<th class="two wide">冻结金额</th>
<th class="two wide">剩余余额</th>
<th class="two wide">剩余冻结余额</th>
<th class="four wide">时间</th>
</tr>
</thead>
<tbody v-for="log in logs">
<tr>
<td>
<span v-if="log.event != null">{{log.event.name}}</span>
<span v-else class="disabled">其他</span>
</td>
<td>
<span v-if="log.delta != 0" :class="{red: log.delta < 0, green: log.delta > 0}">{{log.delta}}元</span>
<span v-else class="disabled">0</span>
</td>
<td>
<span v-if="log.deltaFrozen != 0">{{log.deltaFrozen}}元</span>
<span v-else class="disabled">0</span>
</td>
<td>{{log.total}}元</td>
<td><span :class="{disabled: log.totalFrozen == 0}">{{log.totalFrozen}}元</span></td>
<td>{{log.createdTime}}</td>
</tr>
<tr v-if="log.description.length > 0">
<td colspan="10">
<span class="grey">描述:<keyword :v-word="keyword">{{log.description}}</keyword></span>
</td>
</tr>
</tbody>
</table>

View File

@@ -0,0 +1,62 @@
{$layout}
<form class="ui form" action="/finance/logs">
<div class="ui fields inline">
<div class="ui field">
<input type="text" placeholder="描述" name="keyword" v-model="keyword"/>
</div>
<div class="ui field">
<select class="ui dropdown" name="eventType" v-model="eventType">
<option value="">[所有类型]</option>
<option v-for="event in events" :value="event.code">{{event.name}}</option>
</select>
</div>
<div class="ui field">
<button class="ui button" type="submit">搜索</button>
&nbsp;
<a href="/finance/logs" v-if="keyword.length > 0 || eventType.length > 0">[清除条件]</a>
</div>
</div>
</form>
<p class="comment" v-if="logs.length == 0">暂时还没有操作日志。</p>
<table class="ui table selectable celled" v-if="logs.length > 0">
<thead>
<tr>
<th class="two wide">操作类型</th>
<th class="two wide">操作金额</th>
<th class="two wide">冻结金额</th>
<th class="two wide">剩余余额</th>
<th class="two wide">剩余冻结余额</th>
<th class="three wide">时间</th>
</tr>
</thead>
<tbody v-for="log in logs">
<tr>
<td>
<span v-if="log.event != null">{{log.event.name}}</span>
<span v-else class="disabled">其他</span>
</td>
<td>
<span v-if="log.delta != 0" :class="{red: log.delta < 0, green: log.delta > 0}">{{log.deltaFormatted}}元</span>
<span v-else class="disabled">0</span>
</td>
<td>
<span v-if="log.deltaFrozen != 0">{{log.deltaFrozen}}元</span>
<span v-else class="disabled">0</span>
</td>
<td>{{log.totalFormatted}}元</td>
<td><span :class="{disabled: log.totalFrozen == 0}">{{log.totalFrozen}}元</span></td>
<td>{{log.createdTime}}</td>
</tr>
<tr v-if="log.description.length > 0">
<td colspan="10">
<span class="grey">描述:<keyword :v-word="keyword">{{log.description}}</keyword></span>
</td>
</tr>
</tbody>
</table>
<div class="page" v-html="page"></div>

View File

@@ -0,0 +1,37 @@
.pay-box {
position: relative;
}
.pay-box .pay-mask {
position: fixed;
z-index: 10;
background: rgba(0, 0, 0, 0.8);
top: 0;
left: 0;
right: 0;
bottom: 0;
text-align: center;
}
.pay-box .pay-mask .inner-box {
position: absolute;
top: 50%;
left: 50%;
margin-top: -2em;
margin-left: -2em;
}
.pay-box .pay-mask .inner-box .qrcode-box {
padding: 1em 0;
}
.pay-box .pay-mask .inner-box .qrcode-box .qrcode-title-box {
color: white;
margin-bottom: 1em;
}
.pay-box .pay-mask .inner-box .qrcode-box img {
width: 16em;
}
.pay-box .pay-mask .inner-box.qrcode {
margin-top: -15em;
}
.pay-box .pay-mask .cancel {
margin-top: 1em;
}
/*# sourceMappingURL=index.css.map */

View File

@@ -0,0 +1 @@
{"version":3,"sources":["index.less"],"names":[],"mappings":"AAAA;EACC,kBAAA;;AADD,QAGC;EACC,eAAA;EACA,WAAA;EACA,8BAAA;EACA,MAAA;EACA,OAAA;EACA,QAAA;EACA,SAAA;EACA,kBAAA;;AAXF,QAGC,UAUC;EACC,kBAAA;EACA,QAAA;EACA,SAAA;EACA,gBAAA;EACA,iBAAA;;AAlBH,QAGC,UAUC,WAOC;EACC,cAAA;;AArBJ,QAGC,UAUC,WAOC,YAGC;EACC,YAAA;EACA,kBAAA;;AAzBL,QAGC,UAUC,WAOC,YAQC;EACC,WAAA;;AA7BL,QAGC,UA+BC,WAAU;EACT,iBAAA;;AAnCH,QAGC,UAmCC;EACC,eAAA","file":"index.css"}

View File

@@ -0,0 +1,63 @@
{$layout}
<div class="margin"></div>
<div class="pay-box">
<form class="ui form">
<table class="ui table definition selectable">
<tr>
<td class="title">订单号</td>
<td>{{order.code}}</td>
</tr>
<tr>
<td>订单金额</td>
<td>
¥{{order.amount}}
</td>
</tr>
<tr>
<td>订单类型</td>
<td>
{{order.typeName}}
</td>
</tr>
<tr>
<td>支付方式</td>
<td>{{order.method.name}}</td>
</tr>
<tr>
<td>订单状态</td>
<td>
<span v-if="order.isExpired" class="red">已过期</span>
<span :class="{green: order.status == 'finished'}" v-else>{{order.statusName}}</span>
</td>
</tr>
</table>
<!-- URL支付 -->
<a :href="order.payURL" target="_blank" class="ui button primary" type="button" v-if="order.canPay && order.urlQRCodeKey.length == 0" @click="goPay">去支付 &raquo;</a>
<!-- QRCode支付 -->
<a href="" class="ui button primary" type="button" v-if="order.canPay && order.urlQRCodeKey.length > 0" @click.prevent="goPay">去支付 &raquo;</a>
<span class="red" v-if="order.isExpired">订单已过期,无需支付</span>
&nbsp; &nbsp; &nbsp; &nbsp; <a :href="fromURL" v-if="fromURL.length > 0" class="grey">[上一步]</a>
</form>
<div class="pay-mask" v-if="isPaying">
<div class="inner-box" :class="{qrcode: order.urlQRCodeKey.length > 0}">
<div class="qrcode-box" v-if="order.urlQRCodeKey.length > 0">
<div class="qrcode-title-box">
<span v-if="order.qrcodeTitle.length > 0">{{order.qrcodeTitle}}</span>
<span v-else>请扫描以下二维码完成支付:</span>
</div>
<img :src="'/qrcode?key=' + order.urlQRCodeKey"/>
</div>
<div>
<a :href="returnURL" class="ui button primary large">我已完成支付</a>
</div>
<div class="cancel">
<a href="" @click.prevent="cancel">暂不支付</a>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,22 @@
Tea.context(function () {
this.isPaying = false
if (this.returnURL.length == 0) {
this.returnURL = "/finance"
}
// 自动刷新页面
this.$delay(function () {
if (!this.isPaying) {
window.location.reload()
}
}, 600 * 1000)
this.goPay = function () {
this.isPaying = true
}
this.cancel = function () {
this.isPaying = false
}
})

View File

@@ -0,0 +1,43 @@
.pay-box {
position: relative;
.pay-mask {
position: fixed;
z-index: 10;
background: rgba(0, 0, 0, 0.8);
top: 0;
left: 0;
right: 0;
bottom: 0;
text-align: center;
.inner-box {
position: absolute;
top: 50%;
left: 50%;
margin-top: -2em;
margin-left: -2em;
.qrcode-box {
padding: 1em 0;
.qrcode-title-box {
color: white;
margin-bottom: 1em;
}
img {
width: 16em;
}
}
}
.inner-box.qrcode {
margin-top: -15em;
}
.cancel {
margin-top: 1em;
}
}
}