add(订单、支付):添加了订单,支付模块,并完善了一些功能 #8
@ -351,7 +351,10 @@ export default {
|
|||||||
this.$emit("dataDelete", id);
|
this.$emit("dataDelete", id);
|
||||||
},
|
},
|
||||||
handleSearch() {},
|
handleSearch() {},
|
||||||
handleAddUser() {},
|
handleAddUser() {
|
||||||
|
this.$emit("dataAdd");
|
||||||
|
}
|
||||||
|
,
|
||||||
handleBatchDelete() {},
|
handleBatchDelete() {},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|||||||
396
src/components/OrderDataTable.vue
Normal file
396
src/components/OrderDataTable.vue
Normal file
@ -0,0 +1,396 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title text-center card-header">{{ title }}</h5>
|
||||||
|
<div id="zero-conf_wrapper" class="dataTables_wrapper dt-bootstrap4">
|
||||||
|
<div class="row align-items-center">
|
||||||
|
<div class="col-sm-12 col-md-6 d-flex align-items-center">
|
||||||
|
<div class="dataTables_length" id="zero-conf_length">
|
||||||
|
<label class="d-flex align-items-center" style="white-space: nowrap">
|
||||||
|
展示
|
||||||
|
<select
|
||||||
|
name="zero-conf_length"
|
||||||
|
aria-controls="zero-conf"
|
||||||
|
class="custom-select custom-select-sm form-control form-control-sm mx-2"
|
||||||
|
v-model="pageSize"
|
||||||
|
>
|
||||||
|
<option value="10">10</option>
|
||||||
|
<option value="25">25</option>
|
||||||
|
<option value="50">50</option>
|
||||||
|
<option value="100">100</option>
|
||||||
|
</select>
|
||||||
|
条数据
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="ms-3">
|
||||||
|
<label class="d-flex align-items-center" style="white-space: nowrap">
|
||||||
|
搜索:
|
||||||
|
<input
|
||||||
|
type="search"
|
||||||
|
class="form-control form-control-sm ms-2"
|
||||||
|
placeholder="请输入关键字"
|
||||||
|
aria-controls="zero-conf"
|
||||||
|
/>
|
||||||
|
<button class="btn btn-sm btn-secondary ms-2" @click="handleSearch">
|
||||||
|
搜索
|
||||||
|
</button>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-12 col-md-6 text-center">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<table
|
||||||
|
id="zero-conf"
|
||||||
|
class="display dataTable"
|
||||||
|
style="width: 100%"
|
||||||
|
role="grid"
|
||||||
|
aria-describedby="zero-conf_info"
|
||||||
|
>
|
||||||
|
<thead>
|
||||||
|
<tr role="row">
|
||||||
|
<th
|
||||||
|
class="sorting_asc"
|
||||||
|
tabindex="0"
|
||||||
|
aria-controls="zero-conf"
|
||||||
|
rowspan="1"
|
||||||
|
colspan="1"
|
||||||
|
aria-sort="ascending"
|
||||||
|
aria-label="Name: activate to sort column descending"
|
||||||
|
style="width: 85.5469px"
|
||||||
|
v-for="(item, index) in headers"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
|
{{ item.text }}
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr
|
||||||
|
role="row"
|
||||||
|
v-for="(item, rowIndex) in rows"
|
||||||
|
:key="rowIndex"
|
||||||
|
:class="rowIndex % 2 ? 'even' : 'odd'"
|
||||||
|
>
|
||||||
|
<td v-for="(header, colIndex) in headers" :key="colIndex">
|
||||||
|
<div v-if="header.type == null">
|
||||||
|
<span>{{ item[header.value] ? item[header.value] : '空' }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="header.type == 'bool'">
|
||||||
|
<span
|
||||||
|
:class="[
|
||||||
|
'badge',
|
||||||
|
item[header.value] ? 'bg-danger' : 'bg-success',
|
||||||
|
]"
|
||||||
|
>{{ item[header.value] ? "禁用" : "正常" }}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div v-if="header.type == 'arrObj'">
|
||||||
|
<span
|
||||||
|
class="badge bg-info"
|
||||||
|
v-for="(objItem, objIndex) in item[header.value]"
|
||||||
|
:key="objIndex"
|
||||||
|
>
|
||||||
|
{{ objItem[header.child] }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="header.type == 'money'">
|
||||||
|
<span>{{ item[header.value].toFixed(2) }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="header.type == 'datetime'">
|
||||||
|
<span>{{ formatDateTime(item[header.value]) }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="header.type == 'method'">
|
||||||
|
<span
|
||||||
|
:class="[
|
||||||
|
'badge',
|
||||||
|
'bg-warning',
|
||||||
|
]"
|
||||||
|
>{{ callMethod[item[header.value]] }}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div v-if="header.type == 'find'">
|
||||||
|
<span class="badge bg-info">
|
||||||
|
{{ header.findValue.find(x => x.id == item[header.value]).name }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="header.type == 'orderStatus'">
|
||||||
|
<span class="badge bg-info" v-if="item[header.value] == 0">
|
||||||
|
待支付
|
||||||
|
</span>
|
||||||
|
<span class="badge bg-success" v-if="item[header.value] == 1">
|
||||||
|
已支付
|
||||||
|
</span>
|
||||||
|
<span class="badge bg-warning" v-if="item[header.value] == 2">
|
||||||
|
已取消
|
||||||
|
</span>
|
||||||
|
<span class="badge bg-danger" v-if="item[header.value] == 3">
|
||||||
|
失败
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="header.type == 'orderType'">
|
||||||
|
<span class="badge bg-primary" v-if="item[header.value] == 0">
|
||||||
|
充值
|
||||||
|
</span>
|
||||||
|
<span class="badge bg-success" v-if="item[header.value] == 1">
|
||||||
|
购买
|
||||||
|
</span>
|
||||||
|
<span class="badge bg-info" v-if="item[header.value] == 2">
|
||||||
|
退款
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<th
|
||||||
|
rowspan="1"
|
||||||
|
colspan="1"
|
||||||
|
v-for="(header, index) in headers"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
|
{{ header.value }}
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12 col-md-5">
|
||||||
|
<div
|
||||||
|
class="dataTables_info"
|
||||||
|
id="zero-conf_info"
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
>
|
||||||
|
正在展示 {{ currentPageIndex * pageSize - (pageSize - 1) }} 到
|
||||||
|
{{ currentPageIndex * pageSize }} 条数据 总计 {{ dataCount }} 条
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-12 col-md-7">
|
||||||
|
<div
|
||||||
|
class="dataTables_paginate paging_simple_numbers"
|
||||||
|
id="zero-conf_paginate"
|
||||||
|
>
|
||||||
|
<ul class="pagination">
|
||||||
|
<li
|
||||||
|
:class="[
|
||||||
|
'paginate_button',
|
||||||
|
'page-item',
|
||||||
|
'previous',
|
||||||
|
currentPageIndex == 1 ? 'disabled' : '',
|
||||||
|
]"
|
||||||
|
id="zero-conf_previous"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
aria-controls="zero-conf"
|
||||||
|
data-dt-idx="0"
|
||||||
|
tabindex="0"
|
||||||
|
class="page-link"
|
||||||
|
@click.prevent="previousPage"
|
||||||
|
>上一页</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
:class="[
|
||||||
|
'paginate_button',
|
||||||
|
'page-item',
|
||||||
|
item.index == currentPageIndex ? 'active' : '',
|
||||||
|
]"
|
||||||
|
v-for="(item, index) in pageBtn"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
aria-controls="zero-conf"
|
||||||
|
:data-dt-idx="item.index"
|
||||||
|
tabindex="0"
|
||||||
|
class="page-link"
|
||||||
|
@click.prevent="currentPageIndex = item.index"
|
||||||
|
>{{ item.text }}</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
:class="[
|
||||||
|
'paginate_button',
|
||||||
|
'page-item',
|
||||||
|
'next',
|
||||||
|
currentPageIndex == pageCount ? 'disabled' : '',
|
||||||
|
]"
|
||||||
|
id="zero-conf_next"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
aria-controls="zero-conf"
|
||||||
|
data-dt-idx="7"
|
||||||
|
tabindex="0"
|
||||||
|
class="page-link"
|
||||||
|
@click.prevent="nextPage"
|
||||||
|
>下一页</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "OrderDataTable",
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: "标题",
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
// 表头数组 [{ text: '名字', value: 'name'}, ...]
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
rows: {
|
||||||
|
// 数据数组 [{ name: '佐藤爱理', position: '会计', office: '东京', age: 33, startDate: '2008/11/28', salary: '162,700 元' }, ...]
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
dataCount: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
//当前页索引
|
||||||
|
currentPageIndex: 1,
|
||||||
|
//单页大小
|
||||||
|
pageSize: 10,
|
||||||
|
//总页数
|
||||||
|
pageCount: 0,
|
||||||
|
//分页按钮数据,[{text:'1',index:1},.....]
|
||||||
|
pageBtn: [],
|
||||||
|
//调用方法
|
||||||
|
callMethod:['GET','POST']
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {},
|
||||||
|
methods: {
|
||||||
|
//下一页
|
||||||
|
nextPage() {
|
||||||
|
if (this.currentPageIndex < this.pageCount) this.currentPageIndex++;
|
||||||
|
},
|
||||||
|
//上一页
|
||||||
|
previousPage() {
|
||||||
|
if (this.currentPageIndex > 1) {
|
||||||
|
this.currentPageIndex--;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
changePage(pageIndex) {
|
||||||
|
this.currentPageIndex == pageIndex;
|
||||||
|
},
|
||||||
|
//更新总页数
|
||||||
|
updatePageCount(newPageSize) {
|
||||||
|
this.pageCount = Math.floor(this.dataCount / newPageSize);
|
||||||
|
this.pageCount += this.dataCount % newPageSize == 0 ? 0 : 1;
|
||||||
|
},
|
||||||
|
//更新分页按钮数据
|
||||||
|
updatePageBtn(newPageIndex) {
|
||||||
|
this.pageBtn = [];
|
||||||
|
//初始化首页
|
||||||
|
this.pageBtn.push({ text: "1", index: 1 });
|
||||||
|
//总页数小于8时显示全部页码
|
||||||
|
if (this.pageCount <= 8) {
|
||||||
|
for (let i = 2; i < this.pageCount; i++) {
|
||||||
|
this.pageBtn.push({ text: `${i}`, index: i });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//当前页左侧显示2格页码,当显示最小页码距离首页中间间隔大于1时隐藏间隔页面
|
||||||
|
if (newPageIndex - 2 > 3) {
|
||||||
|
this.pageBtn.push({ text: "...", index: newPageIndex });
|
||||||
|
}
|
||||||
|
//渲染当前页码左右各两格页码
|
||||||
|
const numleft = newPageIndex - 2 < 2 ? newPageIndex - 2 : 2;
|
||||||
|
const numright =
|
||||||
|
newPageIndex + 2 < this.pageCount ? 2 : this.pageCount - newPageIndex - 1;
|
||||||
|
for (let i = newPageIndex - numleft; i <= newPageIndex + numright; i++) {
|
||||||
|
this.pageBtn.push({ text: `${i}`, index: i });
|
||||||
|
}
|
||||||
|
//当前页右侧显示2格页码,当显示最大页码距离尾页中间间隔大于1时隐藏间隔页面
|
||||||
|
if (newPageIndex + 2 < this.pageCount - 2) {
|
||||||
|
this.pageBtn.push({ text: "...", index: newPageIndex });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//渲染尾页
|
||||||
|
this.pageBtn.push({ text: `${this.pageCount}`, index: this.pageCount });
|
||||||
|
},
|
||||||
|
formatDateTime(str) {
|
||||||
|
if (!str) return "-";
|
||||||
|
|
||||||
|
const date = new Date(str);
|
||||||
|
if (isNaN(date)) return "-"; // 防止 Safari 报 Invalid Date
|
||||||
|
|
||||||
|
const pad = (n) => n.toString().padStart(2, "0");
|
||||||
|
|
||||||
|
const Y = date.getFullYear();
|
||||||
|
const M = pad(date.getMonth() + 1);
|
||||||
|
const D = pad(date.getDate());
|
||||||
|
const h = pad(date.getHours());
|
||||||
|
const m = pad(date.getMinutes());
|
||||||
|
const s = pad(date.getSeconds());
|
||||||
|
|
||||||
|
return `${Y}-${M}-${D} ${h}:${m}:${s}`;
|
||||||
|
},
|
||||||
|
modify(id) {
|
||||||
|
this.$emit("dataModify", id);
|
||||||
|
},
|
||||||
|
deleteData(id) {
|
||||||
|
this.$emit("dataDelete", id);
|
||||||
|
},
|
||||||
|
handleSearch() {},
|
||||||
|
handleAddUser() {
|
||||||
|
this.$emit("dataAdd");
|
||||||
|
}
|
||||||
|
,
|
||||||
|
handleBatchDelete() {},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
//监听分页大小变化
|
||||||
|
pageSize: {
|
||||||
|
handler(newVal) {
|
||||||
|
this.updatePageCount(newVal);
|
||||||
|
//单页显示数据量改变时重置当前索引,防止数据以及控件异常
|
||||||
|
this.currentPageIndex = 1;
|
||||||
|
this.$emit("pageChanged", { pageIndex: this.currentPageIndex, pageSize: newVal });
|
||||||
|
this.updatePageBtn(this.currentPageIndex);
|
||||||
|
},
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
|
//监听页索引,用于切换数据
|
||||||
|
currentPageIndex: {
|
||||||
|
handler(newVal) {
|
||||||
|
this.$emit("pageChanged", { pageIndex: newVal, pageSize: this.pageSize });
|
||||||
|
this.updatePageBtn(newVal);
|
||||||
|
},
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 可自定义样式 */
|
||||||
|
.card-title {
|
||||||
|
font-size: 1.8rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
123
src/components/PackageFormModal.vue
Normal file
123
src/components/PackageFormModal.vue
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
<template>
|
||||||
|
<div v-if="visible" class="modal fade show" id="exampleModalCenter" tabindex="-1"
|
||||||
|
aria-labelledby="exampleModalLabel" style="display: block; padding-right: 15px;" _mstvisible="0"
|
||||||
|
aria-modal="true" role="dialog">
|
||||||
|
<div class="modal-dialog modal-dialog-centered" _mstvisible="1">
|
||||||
|
<div class="modal-content" _mstvisible="2">
|
||||||
|
<div class="modal-header" _mstvisible="3">
|
||||||
|
<h5 class="modal-title" id="exampleModalCenterTitle" _msttexthash="13222534" _msthash="147"
|
||||||
|
_mstvisible="4">{{ title }}</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="关闭"
|
||||||
|
_mstaria-label="59709" _msthash="148" _mstvisible="4" @click="cancel"></button>
|
||||||
|
</div>
|
||||||
|
<div class="formcontent">
|
||||||
|
<form>
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label for="inputName3" class="col-sm-2 col-form-label">套餐名称</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input type="text" v-model="form.name" class="form-control" id="inputName3">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label for="inpuCallLimit3" class="col-sm-2 col-form-label">月调用次数</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input type="text" v-model="form.callLimit" class="form-control" id="inputCallLimit3">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label for="inputPrice3" class="col-sm-2 col-form-label">价格</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input type="text" v-model="form.price" class="form-control" id="inputPrice3" v-money>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label for="inputOneMinuteLimit3" class="col-sm-2 col-form-label">调用频率限制</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input type="text" v-model="form.oneMinuteLimit" class="form-control"
|
||||||
|
id="inputOneMinuteLimit3">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer" _mstvisible="3">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" _msttexthash="5889065"
|
||||||
|
_msthash="150" _mstvisible="4" @click="cancel">关闭</button>
|
||||||
|
<button type="button" class="btn btn-primary" _msttexthash="10744773" _msthash="151" _mstvisible="4"
|
||||||
|
@click="submit">保存更改</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'PackageFormModal',
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
formType: {
|
||||||
|
type: String,
|
||||||
|
default: 'edit'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
visible: false,
|
||||||
|
packageId: -2,
|
||||||
|
packageList: [],
|
||||||
|
form: {
|
||||||
|
name: '',
|
||||||
|
callLimit: 0,
|
||||||
|
price: '0',
|
||||||
|
oneMinuteLimit: 0
|
||||||
|
},
|
||||||
|
resolve: null
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
open(packageId = null, packageInfo = null) {
|
||||||
|
this.resetForm();
|
||||||
|
this.visible = true;
|
||||||
|
if (packageInfo != null) {
|
||||||
|
this.packageId = packageId;
|
||||||
|
this.form.name = packageInfo.name;
|
||||||
|
this.form.callLimit = packageInfo.callLimit;
|
||||||
|
this.form.price = packageInfo.price.toString();
|
||||||
|
this.form.oneMinuteLimit = packageInfo.oneMinuteLimit;
|
||||||
|
}
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
this.resolve = resolve;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
submit() {
|
||||||
|
this.visible = false;
|
||||||
|
this.resolve && this.resolve(this.form);
|
||||||
|
},
|
||||||
|
cancel() {
|
||||||
|
this.visible = false;
|
||||||
|
this.resolve && this.resolve(null);
|
||||||
|
},
|
||||||
|
resetForm() {
|
||||||
|
this.form = {
|
||||||
|
name: '',
|
||||||
|
callLimit: 0,
|
||||||
|
price: '0',
|
||||||
|
oneMinuteLimit: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.modal {
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.formcontent {
|
||||||
|
padding: 0 30px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -45,6 +45,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'UserFormModal',
|
name: 'UserFormModal',
|
||||||
props:{
|
props:{
|
||||||
@ -63,26 +64,29 @@ export default {
|
|||||||
form: {
|
form: {
|
||||||
userName: '',
|
userName: '',
|
||||||
email: '',
|
email: '',
|
||||||
balance: '',
|
balance: '0',
|
||||||
password: ''
|
password: ''
|
||||||
},
|
},
|
||||||
resolve: null
|
resolve: null
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
open(userId,userInfo = null) {
|
open(userId = null,userInfo = null) {
|
||||||
this.resetForm();
|
this.resetForm();
|
||||||
this.visible = true;
|
this.visible = true;
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
|
if(userInfo != null){
|
||||||
this.form.email = userInfo.email;
|
this.form.email = userInfo.email;
|
||||||
this.form.userName = userInfo.userName;
|
this.form.userName = userInfo.userName;
|
||||||
this.form.balance = userInfo.balance;
|
this.form.balance = userInfo.balance;
|
||||||
|
}
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
this.resolve = resolve;
|
this.resolve = resolve;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
submit() {
|
submit() {
|
||||||
this.visible = false;
|
this.visible = false;
|
||||||
|
this.form.balance = Number(this.form.balance)
|
||||||
this.resolve && this.resolve(this.form);
|
this.resolve && this.resolve(this.form);
|
||||||
},
|
},
|
||||||
cancel() {
|
cancel() {
|
||||||
@ -93,7 +97,7 @@ export default {
|
|||||||
this.form = {
|
this.form = {
|
||||||
userName: '',
|
userName: '',
|
||||||
email: '',
|
email: '',
|
||||||
balance: '',
|
balance: '0',
|
||||||
password: ''
|
password: ''
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,6 +29,9 @@ const getUserInfoById = async (id) => await request.get(`/api/Admin/UserInfo?use
|
|||||||
//更新用户信息
|
//更新用户信息
|
||||||
const updateUserInfo = async (id,param) => await request.post(`/api/Admin/UpdateUser?userId=${id}`,param)
|
const updateUserInfo = async (id,param) => await request.post(`/api/Admin/UpdateUser?userId=${id}`,param)
|
||||||
|
|
||||||
|
//添加用户
|
||||||
|
const addUser =async (param) => await request.post('/api/admin/adduser',param)
|
||||||
|
|
||||||
//获取api列表
|
//获取api列表
|
||||||
const getApiList = async (pageIndex,pageSize,desc) => await request.get(`/api/apis/ApiList?pageIndex=${pageIndex}&pageSize=${pageSize}&desc=${desc}`)
|
const getApiList = async (pageIndex,pageSize,desc) => await request.get(`/api/apis/ApiList?pageIndex=${pageIndex}&pageSize=${pageSize}&desc=${desc}`)
|
||||||
|
|
||||||
@ -44,9 +47,50 @@ const updateApiInfo = async (id,param) => await request.post(`/api/Apis/UpdateAp
|
|||||||
//获取套餐列表
|
//获取套餐列表
|
||||||
const getPackageList = async (pageIndex,pageSize,desc) => await request.get(`/api/Package/GetPackageList?pageIndex=${pageIndex}&pageSize=${pageSize}&desc=${desc}`)
|
const getPackageList = async (pageIndex,pageSize,desc) => await request.get(`/api/Package/GetPackageList?pageIndex=${pageIndex}&pageSize=${pageSize}&desc=${desc}`)
|
||||||
|
|
||||||
|
|
||||||
|
//删除套餐
|
||||||
|
const deletePackageById = async (id) => await request.delete(`/api/Package/DeletePackage?packageId=${id}`)
|
||||||
|
|
||||||
|
//更新套餐信息
|
||||||
|
const updatePackage = async (id,param) => await request.post(`/api/Package/UpdatePackage?packageId=${id}`,param)
|
||||||
|
|
||||||
|
//添加套餐
|
||||||
|
const addPackage = async (param) => await request.post("/api/Package/AddPackage",param)
|
||||||
|
|
||||||
|
//获取套餐信息
|
||||||
|
const getPackageInfoById = async (id) => await request.get(`/api/Package/GetPackageInfo?packageId=${id}`)
|
||||||
|
|
||||||
//更新系统配置
|
//更新系统配置
|
||||||
const updateSystemConfig = async (configName,configBody) => await request.post('/api/SystemConfig/UpdateSystemConfig',{configName:configName,configBody:configBody})
|
const updateSystemConfig = async (configName,configBody) => await request.post('/api/SystemConfig/UpdateSystemConfig',{configName:configName,configBody:configBody})
|
||||||
|
|
||||||
|
//创建支付
|
||||||
|
const createPayment = async (PaymentType,Amount,ReturnUrl) => await request.post('/api/pay/createpayment',{PaymentType:PaymentType,Amount:Amount,ReturnUrl:ReturnUrl});
|
||||||
|
//支付通知
|
||||||
|
const payNotice = async (pid, trade_no, out_trade_no, type, name, money, trade_status, sign, sign_type) => {
|
||||||
|
|
||||||
|
const query = new URLSearchParams({
|
||||||
|
pid,
|
||||||
|
trade_no,
|
||||||
|
out_trade_no,
|
||||||
|
type,
|
||||||
|
name,
|
||||||
|
money,
|
||||||
|
trade_status,
|
||||||
|
sign,
|
||||||
|
sign_type
|
||||||
|
}).toString();
|
||||||
|
|
||||||
|
return await request.get(`/api/pay/notice?${query}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
//获取用户套餐列表
|
||||||
|
const getUserPackagesAdmin = async (pageIndex,pageSize,desc) => await request.get(`/api/Package/GetUserPackageListAdmin?pageIndex=${pageIndex}&pageSize=${pageSize}&desc=${desc}`);
|
||||||
|
|
||||||
|
//获取订单列表
|
||||||
|
const getOrderList = async (pageIndex,pageSize,desc) => await request.get(`/api/ordergetorders?pageIndex=${pageIndex}&pageSize=${pageSize}&desc=${desc}`);
|
||||||
|
|
||||||
|
//获取个人订单列表
|
||||||
|
const getMyOrderList = async (pageIndex,pageSize,desc) => await request.get(`/api/ordergetmyorders?pageIndex=${pageIndex}&pageSize=${pageSize}&desc=${desc}`);
|
||||||
export default {
|
export default {
|
||||||
login,
|
login,
|
||||||
register,
|
register,
|
||||||
@ -63,5 +107,15 @@ export default {
|
|||||||
getApiInfoById,
|
getApiInfoById,
|
||||||
updateApiInfo,
|
updateApiInfo,
|
||||||
getPackageList,
|
getPackageList,
|
||||||
updateSystemConfig
|
updateSystemConfig,
|
||||||
|
payNotice,
|
||||||
|
createPayment,
|
||||||
|
addUser,
|
||||||
|
getUserPackagesAdmin,
|
||||||
|
deletePackageById,
|
||||||
|
updatePackage,
|
||||||
|
addPackage,
|
||||||
|
getPackageInfoById,
|
||||||
|
getOrderList,
|
||||||
|
getMyOrderList
|
||||||
}
|
}
|
||||||
@ -30,6 +30,11 @@ const routes = [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/paynotice',
|
||||||
|
name: 'paynotice',
|
||||||
|
component: () => import('@/views/PayNotice.vue')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/layout',
|
path: '/layout',
|
||||||
component: () => import('@/views/layout/Home.vue'),
|
component: () => import('@/views/layout/Home.vue'),
|
||||||
@ -112,17 +117,6 @@ const routes = [
|
|||||||
isHome: false
|
isHome: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: 'records',
|
|
||||||
component: () => import('@/views/layout/Records.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '消费记录',
|
|
||||||
icon: 'archive',
|
|
||||||
showInMenu: true,
|
|
||||||
showInUser: true,
|
|
||||||
isHome: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: 'system',
|
path: 'system',
|
||||||
component: () => import('@/views/layout/SystemConfig.vue'),
|
component: () => import('@/views/layout/SystemConfig.vue'),
|
||||||
|
|||||||
36
src/views/PayNotice.vue
Normal file
36
src/views/PayNotice.vue
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<template>
|
||||||
|
<div class="pay-redirect">
|
||||||
|
<h2>正在处理支付结果,请稍候...</h2>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'PayRedirect',
|
||||||
|
data(){
|
||||||
|
return {
|
||||||
|
text:'正在处理支付结果,请稍候...'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
|
||||||
|
const query = this.$route.query;
|
||||||
|
// 校验必要字段
|
||||||
|
if (!query || !query.out_trade_no || !query.trade_status) {
|
||||||
|
alert('参数不完整,无法确认支付结果');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$api.payNotice(query.pid,query.trade_no,query.out_trade_no,query.type,query.name,query.money,query.trade_status,query.sign,query.sign_type)
|
||||||
|
.then(res => {
|
||||||
|
console.log('通知后端成功', res.data);
|
||||||
|
this.$router.push('/layout/balance');
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error('通知后端失败', err);
|
||||||
|
this.text = '支付失败'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@ -11,7 +11,7 @@
|
|||||||
<div class="balance-box">
|
<div class="balance-box">
|
||||||
<h5 class="balance-text">
|
<h5 class="balance-text">
|
||||||
<i class="fas fa-wallet balance-icon"></i>
|
<i class="fas fa-wallet balance-icon"></i>
|
||||||
剩余余额:<span class="balance-amount">{{ balance }}</span>
|
剩余余额:<span class="balance-amount">{{ userInfo.balance }}</span>
|
||||||
</h5>
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -36,14 +36,14 @@
|
|||||||
<!-- 单选按钮 1 -->
|
<!-- 单选按钮 1 -->
|
||||||
<div
|
<div
|
||||||
class="col-6 d-flex justify-content-center mb-3 option-box"
|
class="col-6 d-flex justify-content-center mb-3 option-box"
|
||||||
:class="{ 'selected-box': selectedpay === 'alipay' }"
|
:class="{ 'selected-box': selectedpay === 0 }"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
id="option1"
|
id="option1"
|
||||||
name="options"
|
name="options"
|
||||||
class="hidden-radio"
|
class="hidden-radio"
|
||||||
value="alipay"
|
:value="0"
|
||||||
v-model="selectedpay"
|
v-model="selectedpay"
|
||||||
/>
|
/>
|
||||||
<label for="option1" class="label-style">
|
<label for="option1" class="label-style">
|
||||||
@ -53,14 +53,14 @@
|
|||||||
<!-- 单选按钮 2 -->
|
<!-- 单选按钮 2 -->
|
||||||
<div
|
<div
|
||||||
class="col-6 d-flex justify-content-center mb-3 option-box"
|
class="col-6 d-flex justify-content-center mb-3 option-box"
|
||||||
:class="{ 'selected-box': selectedpay === 'wechat' }"
|
:class="{ 'selected-box': selectedpay === 1 }"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
id="option2"
|
id="option2"
|
||||||
name="options"
|
name="options"
|
||||||
class="hidden-radio"
|
class="hidden-radio"
|
||||||
value="wechat"
|
:value="1"
|
||||||
v-model="selectedpay"
|
v-model="selectedpay"
|
||||||
/>
|
/>
|
||||||
<label for="option2" class="label-style">
|
<label for="option2" class="label-style">
|
||||||
@ -80,53 +80,68 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapState } from "vuex";
|
|
||||||
export default {
|
export default {
|
||||||
name: "Balance",
|
name: "Balance",
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
userInfo:{
|
||||||
|
balance:0
|
||||||
|
},
|
||||||
rechargeAmount: 0,
|
rechargeAmount: 0,
|
||||||
selectedpay: "",
|
selectedpay: 0,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState("userinfo", {
|
|
||||||
balance: (state) => (state.user ? state.user.balance : 0),
|
|
||||||
}),
|
|
||||||
formattedRechargeAmount: {
|
formattedRechargeAmount: {
|
||||||
get() {
|
get() {
|
||||||
return this.rechargeAmount === 0 ? "" : this.rechargeAmount;
|
if (typeof this.rechargeAmount !== 'number') return '0.00';
|
||||||
|
return this.rechargeAmount
|
||||||
|
.toFixed(2)
|
||||||
|
.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||||
},
|
},
|
||||||
set(value) {
|
set(val) {
|
||||||
this.rechargeAmount = value === "" ? 0 : Number(value);
|
// 去除千分位并转换为数字
|
||||||
},
|
const num = parseFloat(val.replace(/,/g, ''));
|
||||||
},
|
if (!isNaN(num)) {
|
||||||
},
|
this.rechargeAmount = num;
|
||||||
created() {
|
}
|
||||||
this.$store.dispatch("userinfo/fetchUserInfo");
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
deposit() {
|
async getUserInfo(){
|
||||||
if (this.rechargeAmount <= 0) {
|
try{
|
||||||
this.$alert("充值金额必须大于0", "danger");
|
const res = await this.$api.getUserInfo();
|
||||||
return;
|
if(res.code != 1000){
|
||||||
|
this.$alert('加载失败','danger')
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if (!this.selectedpay) {
|
this.userInfo = res.data
|
||||||
this.$alert("请选择充值方式", "danger");
|
}catch(e){
|
||||||
return;
|
this.$alert('加载失败','danger')
|
||||||
|
console.error(e)
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
console.log(`Depositing ${this.rechargeAmount} using ${this.selectedpay}`);
|
|
||||||
this.$alert("充值成功", "success");
|
|
||||||
} catch (error) {
|
|
||||||
console.error("充值失败:", error);
|
|
||||||
this.$alert("充值失败,请稍后再试", "danger");
|
|
||||||
}
|
|
||||||
this.rechargeAmount = 0;
|
|
||||||
this.selectedpay = "";
|
|
||||||
},
|
},
|
||||||
|
async deposit(){
|
||||||
|
const returnUrl = `${window.location.protocol}//${window.location.host}/paynotice`;
|
||||||
|
try{
|
||||||
|
const res = await this.$api.createPayment(this.selectedpay,this.rechargeAmount,returnUrl);
|
||||||
|
if(!res.success){
|
||||||
|
this.$alert('跳转支付失败','danger')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
window.location.href = res.payUrl
|
||||||
|
}catch(e){
|
||||||
|
this.$alert('跳转支付失败','danger')
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
async created(){
|
||||||
|
await this.getUserInfo()
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@ -186,6 +186,7 @@ export default {
|
|||||||
auth.clear()
|
auth.clear()
|
||||||
this.$alert('登录状态失效,请重新登录...','info')
|
this.$alert('登录状态失效,请重新登录...','info')
|
||||||
this.$router.push('/auth/login')
|
this.$router.push('/auth/login')
|
||||||
|
|
||||||
}
|
}
|
||||||
},watch:{
|
},watch:{
|
||||||
isAdmin:{
|
isAdmin:{
|
||||||
|
|||||||
@ -0,0 +1,59 @@
|
|||||||
|
<template>
|
||||||
|
<div class="main-wrapper">
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col" v-if="isLoaded">
|
||||||
|
<order-data-table title="订单管理" :headers="tableHeaders" :rows="tableData" :data-count="dataCount"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import OrderDataTable from '@/components/OrderDataTable.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
OrderDataTable
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dataCount: 0,
|
||||||
|
isLoaded: false,
|
||||||
|
tableHeaders: [
|
||||||
|
{ text: "编号", value: "id", width: "155px" },
|
||||||
|
{ text: "用户", value: "userId", width: "214px" },
|
||||||
|
{ text: "订单号", value: "orderNumber", width: "48px" },
|
||||||
|
{ text: "商户订单号", value: "thirdPartyOrderId", width: "82px" },
|
||||||
|
{ text: "金额", value: "amount", width: "103px", type: "money"},
|
||||||
|
{ text: "订单类型", value: "orderType", width: "103px",type:"orderType"},
|
||||||
|
{ text: "订单状态", value: "status", width: "103px",type:"orderStatus"},
|
||||||
|
{ text: "创建时间", value: "createdAt", width: "103px",type:"datetime"},
|
||||||
|
],
|
||||||
|
tableData: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async loadOrderList(pageIndex = 1, pageSize = 10, desc = false) {
|
||||||
|
try {
|
||||||
|
const res = await this.$api.getOrderList(pageIndex, pageSize, desc)
|
||||||
|
if (res.code == '1000') {
|
||||||
|
this.tableData = res.data
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.$alert('订单列表数据加载失败!', 'danger')
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async pageChangedHandle(newval) {
|
||||||
|
await this.loadUserList(newval.pageIndex, newval.pageSize, false)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async mounted() {
|
||||||
|
await this.loadOrderList()
|
||||||
|
this.dataCount = 100
|
||||||
|
this.isLoaded = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@ -0,0 +1,115 @@
|
|||||||
|
<template>
|
||||||
|
<div class="main-wrapper">
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col" v-if="isLoaded">
|
||||||
|
<DataTable title="套餐管理" :headers="tableHeaders" :rows="tableData" :data-count="dataCount"
|
||||||
|
@pageChanged="pageChangedHandle" @dataDelete="deleteHandle" @dataModify="modifyHandle" @dataAdd="addHandle"
|
||||||
|
/>
|
||||||
|
<package-form-modal title="修改套餐" ref="userModal" />
|
||||||
|
<package-form-modal title="添加套餐" formType="add" ref="addUserModal" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import DataTable from '@/components/DataTable.vue';
|
||||||
|
import PackageFormModal from '../../components/PackageFormModal.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
DataTable,
|
||||||
|
PackageFormModal
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dataCount: 0,
|
||||||
|
isLoaded: false,
|
||||||
|
tableHeaders: [
|
||||||
|
{ text: "编号", value: "id", width: "155px" },
|
||||||
|
{ text: "套餐名", value: "name", width: "214px" },
|
||||||
|
{ text: "套餐月限额", value: "callLimit", width: "48px" },
|
||||||
|
{ text: "价格", value: "price", width: "29px", type: "money" },
|
||||||
|
{ text: "限速", value: "oneMinuteLimit", width: "82px" },
|
||||||
|
],
|
||||||
|
tableData: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async loadPackageList(pageIndex = 1, pageSize = 10, desc = false) {
|
||||||
|
try {
|
||||||
|
const res = await this.$api.getPackageList(pageIndex, pageSize, desc)
|
||||||
|
if (res.code == '1000') {
|
||||||
|
this.tableData = res.data
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.$alert('套餐列表数据加载失败!', 'danger')
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async pageChangedHandle(newval) {
|
||||||
|
await this.loadPackageList(newval.pageIndex, newval.pageSize, false)
|
||||||
|
},
|
||||||
|
async deleteHandle(id) {
|
||||||
|
const confirmRes = await this.$confirm('删除', '是否删除套餐?')
|
||||||
|
if (!confirmRes) return;
|
||||||
|
try {
|
||||||
|
const res = await this.$api.deletePackage(id)
|
||||||
|
if (res.code != 1000) {
|
||||||
|
this.$alert(res.message, 'danger')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$alert('删除成功', 'success')
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
this.$alert(e, 'danger')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async modifyHandle(id) {
|
||||||
|
try {
|
||||||
|
//加载用户信息到新窗口
|
||||||
|
const packageInfoRes = await this.$api.getPackageInfoById(id)
|
||||||
|
if(packageInfoRes.code != 1000){
|
||||||
|
this.$alert(packageInfoRes.message,'danger')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//拉起修改弹窗
|
||||||
|
const res = await this.$refs.userModal.open(id,packageInfoRes.data)
|
||||||
|
//弹窗返回为null表示用户关闭了窗口,不执行操作
|
||||||
|
if(res == null) return
|
||||||
|
const modifyRes = await this.$api.updatePackage(id,res)
|
||||||
|
if(modifyRes.code != 1000){
|
||||||
|
this.$alert(modifyRes.message, 'danger')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$alert('修改成功', 'success')
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
this.$alert(e, 'danger')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async addHandle(){
|
||||||
|
//拉起添加弹窗
|
||||||
|
const res = await this.$refs.addUserModal.open()
|
||||||
|
if(res == null) return
|
||||||
|
try{
|
||||||
|
const modifyRes = await this.$api.addPackage(res)
|
||||||
|
if(modifyRes.code != 1000){
|
||||||
|
this.$alert(modifyRes.message, 'danger')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$alert('添加成功', 'success')
|
||||||
|
|
||||||
|
}catch (e) {
|
||||||
|
this.$alert(e, 'danger')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async mounted() {
|
||||||
|
await this.loadPackageList()
|
||||||
|
this.dataCount = 10
|
||||||
|
this.isLoaded = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@ -4,8 +4,10 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col" v-if="isLoaded">
|
<div class="col" v-if="isLoaded">
|
||||||
<DataTable title="用户管理" :headers="tableHeaders" :rows="tableData" :data-count="dataCount"
|
<DataTable title="用户管理" :headers="tableHeaders" :rows="tableData" :data-count="dataCount"
|
||||||
@pageChanged="pageChangedHandle" @dataDelete="deleteHandle" @dataModify="modifyHandle" />
|
@pageChanged="pageChangedHandle" @dataDelete="deleteHandle" @dataModify="modifyHandle" @dataAdd="addHandle"
|
||||||
|
/>
|
||||||
<user-form-modal title="修改用户" ref="userModal" />
|
<user-form-modal title="修改用户" ref="userModal" />
|
||||||
|
<user-form-modal title="添加用户" formType="add" ref="addUserModal" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -88,6 +90,22 @@ export default {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.$alert(e, 'danger')
|
this.$alert(e, 'danger')
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
async addHandle(){
|
||||||
|
//拉起添加弹窗
|
||||||
|
const res = await this.$refs.addUserModal.open()
|
||||||
|
if(res == null) return
|
||||||
|
try{
|
||||||
|
const modifyRes = await this.$api.addUser(res)
|
||||||
|
if(modifyRes.code != 1000){
|
||||||
|
this.$alert(modifyRes.message, 'danger')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$alert('添加成功', 'success')
|
||||||
|
|
||||||
|
}catch (e) {
|
||||||
|
this.$alert(e, 'danger')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user