已完成:

  • 后台的管理功能:

这里用的组件是 element-UI  ====> NavMenu

◆首先是排版 :

 <div class="manage-page fillcontain">
<el-row style="height: 100%;">
<el-col :span="width" style="height: 100%;background-color: #324057;overflow-y:scroll">
<el-menu :default-active="defaultPath" ref='homeMenu' :default-openeds='arr' style="min-height: 100%;" text-color="#ffffff" unique-opened router @select='selectRouter' @close='closeMenu'>
<el-submenu index="">
<template slot="title">
<i class="el-icon-star-on"></i>
<span>实时管理</span>
<span class="red-dots dot-little" v-show="applyNum>0 || btext.bool || storageSpace"></span>
</template>
<el-submenu index="1-1">
<template slot="title">
<i class="el-icon-bell"></i>
<span>实时</span>
</template>
<el-menu-item index="/realTimeStatus">实时状况</el-menu-item>
<el-menu-item index="/baseData">基础数据</el-menu-item>
<el-menu-item index="/GPURealTime">GPU实时统计</el-menu-item>
</el-submenu>
<el-submenu index="1-2" v-if="is_administrator">
<template slot="title">
<i class="el-icon-time"></i>
<span>主机部署</span>
</template>
<el-menu-item index="/hostScan">主机扫描</el-menu-item>
</el-submenu>
<el-submenu index="1-3">
<template slot="title">
<i class="el-icon-plus"></i>
<span>设备管理</span>
<span class="red-dots dot-little" v-show="btext.bool || storageSpace"></span>
</template>
<el-menu-item index="/deviceList">设备列表</el-menu-item>
<el-menu-item index="/hostList">主机列表
<span class="red-dots " v-show="btext.bool">{{btext.num}}</span>
</el-menu-item>
<el-menu-item index="/modelList">模板列表</el-menu-item>
<el-menu-item index="/spaceList">存储空间列表
<span class="red-dots" v-show="storageSpace>0">{{storageSpace}}</span>
</el-menu-item>
<el-menu-item index="/priceList">价格列表</el-menu-item>
<el-menu-item index="/networkAgent">网络代理列表</el-menu-item>
</el-submenu>
<el-submenu index="1-4">
<template slot="title">
<i class="el-icon-goods"></i>
<span>市场管理</span>
<span class="red-dots dot-little" v-show="workerOrderApply>0"></span>
</template>
<el-menu-item index="/serviceList">服务列表</el-menu-item>
<el-menu-item index="/workOrderList">工单列表
<span class="red-dots" v-show="workerOrderApply>0">{{workerOrderApply}}</span>
</el-menu-item>
<el-menu-item index="/createWorkOrder">创建工单</el-menu-item>
<el-menu-item index="/AISoundCode">AI 源码列表</el-menu-item>
</el-submenu>
<el-submenu index="1-5">
<template slot="title">
<i class="el-icon-printer"></i>
<span>财务管理</span>
<span class="red-dots dot-little" v-show="billingApply>0"></span>
</template>
<el-menu-item index="/invoiceProcessing">发票管理
<span class="red-dots" v-show="billingApply>0">{{billingApply}}</span>
</el-menu-item>
<el-menu-item index="/rechargeInfo">收入管理</el-menu-item>
<el-menu-item index="/expenditure">支出管理</el-menu-item>
<el-menu-item index="/systemPresented">系统赠送</el-menu-item>
</el-submenu>
<el-submenu index="1-6">
<template slot="title">
<i class="el-icon-user-solid"></i>
<span>用户管理</span>
</template>
<el-menu-item index="/userInfo">用户列表</el-menu-item>
<el-menu-item index="/wxUserList">微信用户列表</el-menu-item>
</el-submenu>
<el-submenu index="1-7">
<template slot="title">
<i class="el-icon-share"></i>
<span>推广管理</span>
<span class="red-dots dot-little" v-show="(ambassadorApply>0 || withdrawApply>0)"></span>
</template>
<el-menu-item index="/recommendApply">推广申请
<span class="red-dots" v-show="ambassadorApply>0">{{ambassadorApply}}</span>
</el-menu-item>
<el-menu-item index="/withdrawApply">提现申请
<span class="red-dots" v-show="withdrawApply>0">{{withdrawApply}}</span>
</el-menu-item>
<el-menu-item index="/recommendList">推广信息列表</el-menu-item>
</el-submenu>
<el-submenu index="1-8">
<template slot="title">
<i class="el-icon-edit"></i>
<span>活动管理</span>
</template>
<el-menu-item index="/discountList">折扣列表</el-menu-item>
<el-menu-item index="/activityList">活动列表</el-menu-item>
</el-submenu>
<el-submenu index="1-9">
<template slot="title">
<i class="el-icon-news"></i>
<span>公告管理</span>
</template>
<el-menu-item index="/notice">公告列表</el-menu-item>
</el-submenu>
<el-submenu index="1-10" v-if="is_administrator">
<template slot="title">
<i class="el-icon-setting"></i>
<span>权限管理</span>
</template>
<el-menu-item index="/userRole">角色列表</el-menu-item>
<el-menu-item index="/permission">权限列表</el-menu-item>
<el-menu-item index="/role">角色管理</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="">
<template slot="title">
<i class="el-icon-document"></i>
<span>统计分析</span>
</template>
<el-submenu index="2-1">
<template slot="title">
<i class="el-icon-document"></i>
<span>设备使用情况</span>
</template>
<el-menu-item index="/equipData">GPU 租用总量总计</el-menu-item>
<el-menu-item index="/GPUAvailability">GPU 利用率统计</el-menu-item>
<el-menu-item index="/GPUUsed">GPU 使用分时统计</el-menu-item>
<el-menu-item index="/GPURent">GPU 租用采样统计</el-menu-item>
<el-menu-item index="/GPUUtilizationHeap">GPU 利用率堆积图</el-menu-item>
<el-menu-item index="/GPURentBenefit">GPU 租用效益统计</el-menu-item>
<!-- <el-menu-item index="/occupancyAnalysis">租用量分析</el-menu-item>
<el-menu-item index="/rentalFeeAnalysis">租赁费分析</el-menu-item> -->
<!-- <el-menu-item index="/rentalBenefitAnalysis">租用效益分析</el-menu-item> -->
</el-submenu>
<el-submenu index="2-2">
<template slot="title">
<i class="el-icon-document"></i>
<span>用户基本情况</span>
</template>
<el-menu-item index="/userGrow">用户增长统计</el-menu-item>
<el-menu-item index="/userRegister">用户注册时间分布</el-menu-item>
<el-menu-item index="/userInformat">用户活跃量统计</el-menu-item>
<el-menu-item index="/useTime">使用时长统计</el-menu-item>
<el-menu-item index="/userAttribute">用户属性统计</el-menu-item>
<el-menu-item index="/visitor">用户排行榜</el-menu-item>
<el-menu-item index="/visitStatistics">网站访问统计</el-menu-item>
</el-submenu>
<el-submenu index="2-7">
<template slot="title">
<i class="el-icon-pie-chart"></i>
<span>用户分布统计</span>
</template>
<el-menu-item index="/provinceStatistics">省份人数分布</el-menu-item>
<el-menu-item index="/cityStatistics">城市人数分布</el-menu-item>
<el-menu-item index="/schoolStatistics">学校人数分布</el-menu-item>
</el-submenu>
<el-submenu index="2-3">
<template slot="title">
<i class="el-icon-document"></i>
<span>用户 GPU 利用率</span>
</template>
<el-menu-item index="/rankingList">用户 GPU 利用率排行榜</el-menu-item>
</el-submenu>
<el-submenu index="2-4">
<template slot="title">
<i class="el-icon-document"></i>
<span>用户消费情况</span>
</template>
<el-menu-item index="/userExpense">消费类型统计</el-menu-item>
<el-menu-item index="/mainframeLease">主机租赁统计</el-menu-item>
<el-menu-item index="/incrementService">增值服务统计</el-menu-item>
<el-menu-item index="/ticketsUsed">消费券使用记录</el-menu-item>
<el-menu-item index="/codeList">AI 源码用户购买列表</el-menu-item>
</el-submenu>
<el-submenu index="2-5">
<template slot="title">
<i class="el-icon-document"></i>
<span>用户充值情况</span>
</template>
<el-menu-item index="/userRecharge">用户充值额统计</el-menu-item>
<el-menu-item index="/userRechargeType">用户充值渠道统计</el-menu-item>
</el-submenu>
<el-submenu index="2-6">
<template slot="title">
<i class="el-icon-document"></i>
<span>公司收支分析</span>
</template>
<el-menu-item index="/comparative">收支对比</el-menu-item>
<el-menu-item index="/income">收入统计</el-menu-item>
<el-menu-item index="/expenditureTow">支出统计</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index=''>
<template slot="title">
<i class="el-icon-s-promotion"></i>
<span>直达</span>
</template>
<!-- <el-menu-item index="/nonstop">快捷方式设置</el-menu-item> -->
<el-menu-item v-for='(item,index) in urlList' :index="`3-${index}`" :route="{path:item.nav_url,query:{copy:1}}" :key="index">{{item.nav_name}}</el-menu-item>
</el-submenu>
</el-menu>
</el-col>
<el-col :span="(24-width)" style="height: 100%">
<head-top v-on:changeMenu='openAMenu'></head-top>
<div class="content">
<keep-alive>
<router-view></router-view>
</keep-alive>
<div class="scrollbar"></div>
</div>
</el-col>
</el-row>
</div>

排版

◆消息提示:

小红点样式

.red-dots {
display: inline-block;
color: white;
vertical-align: middle;
margin-left: 5px;
margin-top: -2px;
width: 22px;
height: 22px;
line-height: 22px;
text-align: center;
border-radius: 15px;
font-size: 10px;
background-color: rgb(, , );
}

如何实现小红点的判断:

 <template slot="title">
<i class="el-icon-plus"></i>
<span>设备管理</span>
<span class="red-dots dot-little" v-show="btext.bool || storageSpace"></span>
</template>

路由跳转

 <el-menu-item index="/userExpense">消费类型统计</el-menu-item>
<el-menu-item index="/mainframeLease">主机租赁统计</el-menu-item>
<el-menu-item index="/incrementService">增值服务统计</el-menu-item>
<el-menu-item index="/ticketsUsed">消费券使用记录</el-menu-item>
<el-menu-item index="/codeList">AI 源码用户购买列表</el-menu-item>

路由跳转

  • 顶部导航栏功能的实现(后台)

排版代码:

 <template>
<div class="header-container">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/manage' }">首页</el-breadcrumb-item>
<el-breadcrumb-item v-for="item in $route.meta" :key="item.index">
<span :class="{'is-link':item.index!==undefined}" @click="openMenu(item.index)">{{item.name}}</span>
</el-breadcrumb-item>
</el-breadcrumb>
<div class="userInfo-box">
<template v-if="canAdd!==null">
<el-button class="addNonstop" size="small" type="primary" @click="setShortcut('post')" v-if="canAdd===1">添加直达</el-button>
<el-button class="addNonstop" size="small" type="warning" @click="setShortcut('delete')" v-if="canAdd===0">取消直达</el-button>
</template>
<img src='../assets/default.jpg' class="avator">
<ul class="userInfo">
<li>{{username}}</li>
<li>|</li>
<li @click="loginOut">退出</li>
</ul>
</div>
</div>
</template>

排版代码

子组件向父组件传路由值

 <el-breadcrumb-item v-for="item in $route.meta" :key="item.index">
<span :class="{'is-link':item.index!==undefined}" @click="openMenu(item.index)">{{item.name}}</span>
</el-breadcrumb-item>
 openMenu(index){
if(index){
this.$emit('changeMenu',index); //$emit 绑定一个自定义事件event,当这个这个语句被执行到的时候,就会将参数arg传递给父组件,父组件通过@event监听并接收参数
}
}

父组件获取路由值

 <head-top v-on:changeMenu='openTheMenu'></head-top>
//打开指定菜单
openTheMenu(index) {
this.$refs["homeMenu"].open(index);
}
  • 订单查询功能(后台)

整个页面:

 <script>
import Utils from "@/utils/utils";
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('financial')
export default {
data() {
return {
showPagination: false,
pickerBeginDateBefore: {
disabledDate: time => {
if (this.end_date) {
return (
time.getTime() > this.end_date || time.getTime() > Date.now()
);
}
}
},
pickerBeginDateAfter: {
disabledDate: time => {
if (this.begin_date) {
return (
time.getTime() < this.begin_date || time.getTime() > Date.now()
);
}
}
},
origin_list: [
"全部",
"后台-淘宝-易学智能",
"后台-淘宝-GPU远程租用",
"平台-支付宝",
"后台-淘宝充值",
"后台-银行公账-深圳兴导",
'后台-银行公账-湖南兴导',
"后台-淘宝-国科机房",
'平台-微信'
],
time_list: [
{ name: "本日", val: "today" },
{ name: "本周", val: "this_week" },
{ name: "本月", val: "this_month" },
{ name: "上月", val: "last_month" },
{ name: "日期范围", val: "date_range" }
],
add_list: [{
name:"全部",
id:0
},{
name:"充值",
id:1
},{
name:"快递费",
id:5
},{
name:"增值服务",
id:6
}],
origin: 0,
add_type: 0,
time_type: "today",
begin_date: new Date(2018,10,15),
end_date: new Date(),
total_data: {
total: 0
},
table_loading: false,
page_size: 20,
order_by: null,
order: null,
input:null,
order_number:null
};
},
watch: {
$route(to, from) {
if (to.path === "/rechargeInfo" && from.path !== "/userDetails") {
this.total_data = {};
this.origin=0;
this.add_type=0;
this.time_type="today";
this.begin_date=new Date(2018,10,15);
this.end_date=new Date();
this.showPagination = false;
this.order = null;
this.order_by = null;
this.search(1);
}
}
},
created() {
this.search(1);
},
methods: {
...mapActions(["rechargeListAPI", "downloadRechargeAPI"]),
//分页
changePage(value) {
this.search(value);
this.$refs['pageTwo'].internalCurrentPage = this.$refs['pageOne'].internalCurrentPage;//绑定页数
},
changePageTwo(value){
this.search(value);
this.$refs['pageOne'].internalCurrentPage = this.$refs['pageTwo'].internalCurrentPage;
},
//排序
sortMethod(){
this.order_by = 'add_time';
this.order = this.order === 'desc'? 'asc': 'desc';
this.showPagination=false;
this.search(1);
},
//进入用户详情
searchOne(id) {
this.$router.push({ path: "userDetails?id=" + id, replace: true });
},
//查询充值明细
search(page) {
if (!Utils.checkToken(this)) return;
if(this.time_type==='date_range'&&(!this.begin_date||!this.end_date)){
return this.$message.error('请选择时间!');
}
this.table_loading = true;
this.rechargeListAPI({
origin: this.origin,
time_type: this.time_type,
add_type: this.add_type,
begin_date: Utils.formatDate(this.begin_date, "yyyy-MM-dd"),
end_date: Utils.formatDate(this.end_date, "yyyy-MM-dd"),
page: page,
page_size: this.page_size,
order_by: this.order_by,
order: this.order,
order_number:this.order_number
}).then(
({body}) => {
this.total_data = body;
this.table_loading = false;
this.showPagination = true;
},
err => {
this.table_loading = false;
this.showPagination = true;
this.$message.error(err.msg);
}
);
},
//下载明细单
download(page) {
if (!Utils.checkToken(this)) return;
const loading = this.$loading();
this.downloadRechargeAPI({
origin: this.origin,
time_type: this.time_type,
add_type: this.add_type,
begin_date: Utils.formatDate(this.begin_date, "yyyy-MM-dd"),
end_date: Utils.formatDate(this.end_date, "yyyy-MM-dd"),
order: this.order,
order_by: this.order_by,
}).then(
res => {
loading.close();
const blob = res.data;
const fileName = decodeURI(res.headers.map["content-disposition"][0].split(";")[1].split("=")[1]) || '易学智能-充值明细单.xlsx';
if ("download" in document.createElement("a")) {
// 非IE下载
const elink = document.createElement("a");
elink.download = fileName;
elink.style.display = "none";
elink.href = URL.createObjectURL(blob);
document.body.appendChild(elink);
elink.click();
URL.revokeObjectURL(elink.href); // 释放URL 对象
document.body.removeChild(elink);
} else {
// IE10+下载
navigator.msSaveBlob(blob, fileName);
}
},
err => {
loading.close();
this.$message.error(err.msg);
}
);
},
//订单号获得焦点事件 //zcg
focus(){
this.time_type ='date_range'
this.search(1);
},
//订单号change事件
changeInput(value){
this.order_number =value
this.search(1);
}
}
};
</script>
<template>
<div>
<p class="title title-primary">充值明细查询</p>
<el-form label-width="100px" label-position="left">
<el-form-item label="来源:">
<el-radio-group v-model="origin" @change="showPagination=false,search(1)">
<el-radio v-for='(item,index) in origin_list' :key="index" :label="index">{{item}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="充值类型:">
<el-radio-group v-model="add_type" @change="showPagination=false,search(1)">
<el-radio v-for='(item,index) in add_list' :key="index" :label="item.id">{{item.name}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="时间类型:">
<el-radio-group v-model="time_type" @change="showPagination=false,search(1)">
<el-radio v-for='(item,index) in time_list' :key="index" :label="item.val">{{item.name}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="起始日期:" v-show="time_type==='date_range'">
<el-date-picker v-model="begin_date" type="date" placeholder="开始时间" format="yyyy-MM-dd" :picker-options="pickerBeginDateBefore">
</el-date-picker>
<el-date-picker v-model="end_date" type="date" placeholder="结束时间" format="yyyy-MM-dd" :picker-options="pickerBeginDateAfter">
</el-date-picker>
<el-button type="primary" @click="showPagination=false,search(1)">查询记录</el-button>
</el-form-item>
<el-form-item label="订单号:" class="nav-btns nav-input">
<el-input placeholder="输入订单号" clearable v-model="input" @focus="focus" @input="changeInput"></el-input>
</el-form-item>
<el-form-item>
<el-button type="warning" @click="download">全部下载</el-button>
</el-form-item>
</el-form>
<el-pagination ref='pageOne' v-if="showPagination" :page-size="page_size" background layout="total,prev, pager, next" :total='total_data.total' @current-change="changePage"></el-pagination>
<el-table :data="total_data.data" v-loading="table_loading">
<el-table-column label="序号" type="index" width="100px">
</el-table-column>
<el-table-column label="用户名" prop="user_name">
<template slot-scope="scope">
<span @click="searchOne(scope.row.uid)" class="font-jump">{{scope.row.user_name}}</span>
</template>
</el-table-column>
<el-table-column label="充值时间" prop="add_time">
<template slot="header" slot-scope="scope">
<span @click="sortMethod('add_time')">充值时间
<i class="el-icon-sort" v-if="order_by!='add_time'"></i>
<template v-else>
<i class="el-icon-sort-down" v-if="order =='desc'"></i>
<i class="el-icon-sort-up" v-else></i>
</template>
</span>
</template>
</el-table-column>
<el-table-column label="订单号">
<template slot-scope="scope">
<p>{{scope.row.order_number?scope.row.order_number:'无'}}</p>
</template>
</el-table-column>
<el-table-column label="来源" prop="origin">
</el-table-column>
<el-table-column label="备注">
<template slot-scope="scope">
<p>{{scope.row.comment?scope.row.comment:'无'}}</p>
</template>
</el-table-column>
<el-table-column label="充值金额(元)" prop="receipt_amount">
</el-table-column>
<el-table-column label="操作人" prop="admin_username">
</el-table-column>
</el-table>
<el-pagination ref='pageTwo' v-if="showPagination" :page-size="page_size" background layout="total,prev, pager, next" :total='total_data.total' @current-change="changePageTwo"></el-pagination>
</div>
</template>

整个查询页面

排版:

  <el-form-item  label="订单号:" class="nav-btns nav-input">
<el-input placeholder="输入订单号" clearable v-model="input" @focus="focus" @input="changeInput"></el-input>
</el-form-item>
<el-form-item>
<el-button type="warning" @click="download">全部下载</el-button>
</el-form-item

功能的实现:

 1 focus(){
2 this.time_type ='date_range'
3 this.search(1);
4 },
5 //订单号change事件
6 changeInput(value){
7 this.order_number =value
8 this.search(1);
9 }
10 }

查询时间:

 search(page) {
if (!Utils.checkToken(this)) return;
if(this.time_type==='date_range'&&(!this.begin_date||!this.end_date)){
return this.$message.error('请选择时间!');
}
this.table_loading = true;
this.rechargeListAPI({
origin: this.origin,
time_type: this.time_type,
add_type: this.add_type,
begin_date: Utils.formatDate(this.begin_date, "yyyy-MM-dd"),
end_date: Utils.formatDate(this.end_date, "yyyy-MM-dd"),
page: page,
page_size: this.page_size,
order_by: this.order_by,
order: this.order,
order_number:this.order_number
}).then(
({body}) => {
this.total_data = body;
this.table_loading = false;
this.showPagination = true;
},
err => {
this.table_loading = false;
this.showPagination = true;
this.$message.error(err.msg);
}
);
},

下载明细文件:

 download(page) {
if (!Utils.checkToken(this)) return;
const loading = this.$loading();
this.downloadRechargeAPI({
origin: this.origin,
time_type: this.time_type,
add_type: this.add_type,
begin_date: Utils.formatDate(this.begin_date, "yyyy-MM-dd"),
end_date: Utils.formatDate(this.end_date, "yyyy-MM-dd"),
order: this.order,
order_by: this.order_by,
}).then(
res => {
loading.close();
const blob = res.data;
const fileName = decodeURI(res.headers.map["content-disposition"][0].split(";")[1].split("=")[1]) || '易学智能-充值明细单.xlsx';
if ("download" in document.createElement("a")) {
// 非IE下载
const elink = document.createElement("a");
elink.download = fileName;
elink.style.display = "none";
elink.href = URL.createObjectURL(blob);
document.body.appendChild(elink);
elink.click();
URL.revokeObjectURL(elink.href); // 释放URL 对象
document.body.removeChild(elink);
} else {
// IE10+下载
navigator.msSaveBlob(blob, fileName);
}
},
err => {
loading.close();
this.$message.error(err.msg);
}
);
},
 const state = {
billingList:{},
billingOrders:{}
} const actions = {
/* 发票管理 */
//开票待处理、已开票、已拒绝列表
async billingInfoAPI({dispatch,commit},query) {
return await dispatch('callingInterface',{
request_method:'get',
API_url:'gpu_admin/finance/bill/apply_list',
query:{
params:query
},
callback:({body})=>{
commit('setState',{
childName:'financial',
name:'billingList',
val:body
},{root:true})
}
},{root:true})
},
//开票相关订单信息
async billingOrdersInfoAPI({dispatch,commit},query) {
return await dispatch('callingInterface',{
request_method:'get',
API_url:'gpu_admin/finance/bill/order_list',
query:{
params:query
},
callback:({body})=>{
commit('setState',{
childName:'financial',
name:'billingOrders',
val:body
},{root:true})
}
},{root:true})
},
//开票完成信息提交
async billingCompleteAPI({dispatch},query) {
return await dispatch('callingInterface',{
request_method:'post',
API_url:'gpu_admin/finance/bill/dealt',
query:query
},{root:true})
},
//发票数据总计
async billingAmountAPI({dispatch}) {
return await dispatch('callingInterface',{
request_method:'get',
API_url:'gpu_admin/finance/billinfo'
},{root:true})
}, /* 充值明细 */
//充值明细记录
async rechargeListAPI({dispatch},query) {
return await dispatch('callingInterface',{
request_method:'get',
API_url:'gpu_admin/finance/recharge_list',
query:{
params:query
}
},{root:true})
},
//下载充值明细
async downloadRechargeAPI({dispatch},query) {
return await dispatch('callingInterface',{
request_method:'get',
API_url:'gpu_admin/finance/recharge_list_excel',
query:{
headers:{'Content-Type':'application/ms-excel'},
responseType:'blob',
params:query,
}
},{root:true})
}, /* 系统赠送 */
//系统赠送明细记录
async presentedListAPI({dispatch},query) {
return await dispatch('callingInterface',{
request_method:'get',
API_url:'gpu_admin/finance/syspresented_list',
query:{
params:query
}
},{root:true})
},
//下载系统赠送明细
async downloadPresentedAPI({dispatch},query) {
return await dispatch('callingInterface',{
request_method:'get',
API_url:'gpu_admin/finance/syspresented_list_excel',
query:{
headers:{'Content-Type':'application/ms-excel'},
responseType:'blob',
params:query
}
},{root:true})
},
//支出信息
async expenditureAPI({dispatch},query) {
return await dispatch('callingInterface',{
request_method:'get',
API_url:'gpu_admin/and_payments/expenditure',
query:{
params:query
},
flag : true
},{root:true})
},
//添加支出
async expenditureAddAPI({dispatch},query) {
return await dispatch('callingInterface',{
request_method:'post',
API_url:'gpu_admin/and_payments/expenditure',
query:query
},{root:true})
},
//用户名列表
async usernamelistAPI({dispatch},query) {
return await dispatch('callingInterface',{
request_method:'get',
API_url:'gpu_admin/usernamelist',
query:{
params:query
}
},{root:true})
},
//用户充值记录
async add_money_logAPI({dispatch},query) {
return await dispatch('callingInterface',{
request_method:'get',
API_url:'gpu_admin/and_payments/add_money_log',
query:{
params:query
}
},{root:true})
}, //财务管理 //收入信息 -充值信息
async incomeAPI({dispatch},query) {
return await dispatch('callingInterface',{
request_method:'get',
API_url:'gpu_admin/finance/income',
query:{
params:query
}
},{root:true})
}, //收入信息 -充值信息
async incomegraphAPI({dispatch},query) {
return await dispatch('callingInterface',{
request_method:'get',
API_url:'gpu_admin/finance/incomegraph',
query:{
params:query
}
},{root:true})
}, //收入每日/周/月信息
async incomedetailAPI({dispatch},query) {
return await dispatch('callingInterface',{
request_method:'get',
API_url:'gpu_admin/finance/incomedetail',
query:{
params:query
}
},{root:true})
}, } export default{
namespaced:true,
state,
actions
}

财政接口代码

调用接口JS代码:

 callingInterface({},{request_method,API_url,query,flag,callback}){
//请求地址+API
const url = localhost + API_url;
//是否开启emulateJSON
const is_flag = flag!==undefined ? flag : false;
//回调函数,处理提交mutaion修改state的操作
const callMethod = callback!==undefined ? callback : (()=>{});
console.log('请求传入参数query:', query) return new Promise((resolve, reject) => {
Vue.http[request_method](url, query ,{
emulateJSON: is_flag
}).then(res => {
resolve(res);
callMethod(res);
console.log('请求成功:', res);
}, err => {
console.log('请求失败:', err)
reject(err.body)
})
})
},

点击按钮查询不同的数据(利用v-model的双向绑定原理和v-on:change事件)

 <el-form-item label="来源:">
<el-radio-group v-model="origin" @change="showPagination=false,search(1)">
<el-radio v-for='(item,index) in origin_list' :key="index" :label="index">{{item}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="充值类型:">
<el-radio-group v-model="add_type" @change="showPagination=false,search(1)">
<el-radio v-for='(item,index) in add_list' :key="index" :label="item.id">{{item.name}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="时间类型:">
<el-radio-group v-model="time_type" @change="showPagination=false,search(1)">
<el-radio v-for='(item,index) in time_list' :key="index" :label="item.val">{{item.name}}</el-radio>
</el-radio-group>
</el-form-item>

 根据路由传值完成不同的详情页面:

在其他页面传值后跳转到详情页面

点击用户名 触发事件:

<el-table-column label="用户名">
<template slot-scope="scope">
<span @click="searchOne(scope.row.uid)" class="font-jump">{{scope.row.username}}</span> //点击触发查询事件
</template>
</el-table-column>

查询事件:

searchOne(id) {
this.$router.push({path:'userDetails?id='+id,replace:true});//路由就变成了详情页并且带id
}

详情页面的获取信息功能:

 getUserDetails(){
this.uid = this.$route.query.id;// 根据路由ID的不同,返回不同的数据
this.getUserInfo();
this.getExtraInfo();
this.getExpenseInfo();
},

getUserInfo:

  getUserInfo() {
if (!Utils.checkToken(this)) return;
this.pageLoading = true;
this.userInfoDetailsAPI({//通过API接口获取数据
uid: this.uid
}).then(
({body}) => {
this.pageLoading = false;
this.sendData = Object.assign(this.sendData,{user_name:body.user_name,balance:body.balance})
this.userInfo = body;
},
err => {
this.pageLoading = false;
this.$message.error(err.msg);
}
);
}

监听:

 watch: {
$route(to, from) {
if (to.path === "/userDetails") {
this.showPagination = false;
this.record_type= 'expenseRecord';
this.record_son_type= ;
this.pageInfo={
page:,
page_size:
};
this.date= [Utils.formatDate(new Date("2018/11/15"), "yyyy-MM-dd"), Utils.formatDate(new Date(), "yyyy-MM-dd")];
this.userInfo = {}
this.extraInfo = {}
this.expenseInfo = {}
this.sendData = {}
this.getUserDetails();
}
}

生命周期钩子函数:

 created() {
this.getUserDetails();
},
  • 点击显示订单详情

利用饿了么组件(不同之处:利用计算属性来获得数据)

 <el-dialog title="订单信息" :visible.sync="openOrderInfo" width="1000px" center :close-on-click-modal='false'>
<el-table :data="billingOrders.data" border>
<el-table-column label="序号" type="index" width="100px">
</el-table-column>
<el-table-column label="可开票金额(元)" prop="available_bill">
</el-table-column>
<el-table-column label="实收金额(元)" prop="receipt_amount">
</el-table-column>
<el-table-column label="充值来源" prop="origin">
</el-table-column>
<el-table-column label="订单号" prop="order_number">
</el-table-column>
<el-table-column label="订单类型" prop="order_type">
</el-table-column>
<el-table-column label="充值时间" prop="add_time">
</el-table-column>
</el-table>
</el-dialog>

数据获取(使用了命名空间):

  import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('financial') computed:{
...mapState(['billingList','billingOrders'])
}

命名空间获取billingOrders值:(命名空间:将模块的空间名称字符串作为第一个参数传递给上述函数,这样所有绑定都会自动将该模块作为上下文。)

命名空间: 默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。

 async billingOrdersInfoAPI({dispatch,commit},query) {
return await dispatch('callingInterface',{
request_method:'get',
API_url:'gpu_admin/finance/bill/order_list',
query:{
params:query
},
callback:({body})=>{
commit('setState',{//到setstate去设置state的值
childName:'financial',//字符串,为了setState可以[""]
name:'billingOrders',//字符串,为了setState可以[""]
val:body
},{root:true})
}
},{root:true})
},

提交到setState:(mutations.js文件)

 const mutations = {
//设置state的值
setState(state,{name,val,childName}){
if(childName!==undefined){
state[childName][name] = val
}else{
state[name] = val
}
}
} export default{
mutations
}

如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。例如:

billingOrders来源:(接口获取)

 async billingOrdersInfoAPI({dispatch,commit},query) {
return await dispatch('callingInterface',{
request_method:'get',
API_url:'gpu_admin/finance/bill/order_list',
query:{
params:query
},
callback:({body})=>{
commit('setState',{
childName:'financial',
name:'billingOrders',//回调函数
val:body
},{root:true})
}
},{root:true})
},

命名来源:(Store下的index.js文件):

 import Vue from 'vue'
import Vuex from 'vuex' import fooActions from './actions'
import fooMutations from './mutations'
import login from './modules/login'
import realTimeData from './modules/real_time_data'
import deploy from './modules/deploy'
import device from './modules/device'
import financial from './modules/financial'
import userInfo from './modules/user_info'
import recommend from './modules/recommend'
import activity from './modules/activity'
import userLimit from './modules/user_limit'
import recharge from './modules/recharge'
import statistics from './modules/statistics'
import equipUsageInfo from './modules/equip_usage_info'
import userExpenseData from './modules/user_expense_data'
import market from './modules/market'
import GPUUseRatio from './modules/GPU_use_ratio'
import expenses from "./modules/expenses"
import userDistribution from "./modules/user_distribution"
// import createLogger from '../../../src/plugins/logger' Vue.use(Vuex)
const debug = process.env.NODE_ENV !== 'production' const state = {
applyData:{},
urlList:[]
} export default new Vuex.Store({
state:state,
actions:fooActions.actions,
mutations:fooMutations.mutations,
modules:{
login,
realTimeData,
deploy,
device,
financial,
userInfo,
recommend,
activity,
userLimit,
recharge,
statistics,
equipUsageInfo,
userExpenseData,
market,
GPUUseRatio,
expenses,
userDistribution
},
strict: debug,
// plugins: debug ? [createLogger()] : []
})

Store文件夹下的index.js文件

若需要在全局命名空间内分发 action 或提交 mutation,将 { root: true } 作为第三参数传给 dispatch 或 commit 即可。

{root:true}    =====> 若需要在全局命名空间内分发 action 或提交 mutation,将 { root: true } 作为第三参数传给 dispatch 或 commit 即可。  

未用命名空间:

 import { mapActions,mapState } from "vuex"
computed: {
...mapState({
deploy_status:state=>state.deploy.deploy_status,
status_color:state=>state.deploy.status_color
}), methods: {
...mapActions({
deployListAPI:'deploy/deployListAPI',
deployServerAPI:'deploy/deployServerAPI'
}),

回调接口;

 callingInterface({},{request_method,API_url,query,flag,callback}){
//请求地址+API
const url = localhost + API_url;
//是否开启emulateJSON
const is_flag = flag!==undefined ? flag : false;
//回调函数,处理提交mutaion修改state的操作
const callMethod = callback!==undefined ? callback : (()=>{});
console.log('请求传入参数query:', query) return new Promise((resolve, reject) => {
Vue.http[request_method](url, query ,{
emulateJSON: is_flag
}).then(res => {
resolve(res);
callMethod(res); //如果传了callback,就有意义,如果没传callback 就是(){} 空函数,执行了也没效果
console.log('请求成功:', res);
}, err => {
console.log('请求失败:', err)
reject(err.body)
})
})
}
  • 画图:  =====>见另一篇博文 Echarts配置
  • 点击按钮触发申请处理表

模板代码:

 <el-table-column label="操作" v-if="status==='apply'" key="t2" width="">
<template slot-scope="scope"> // scope 是v-bind绑定数据(:data)后的固定写法

           <el-button @click="openForm(scope.row)" type="primary" size="small">处理</el-button>
</template>
</el-table-column>

点击事件代码:

 //打开处理申请的弹框
openForm(row){
this.formData = Object.assign({
order:null//目标
},{
id:row.e_id,
clearing:row.e_money,
})
this.openUpdate = true;
},

点击后:

模板代码:

 <el-dialog title="申请处理" :visible.sync="openUpdate" width="400px" center @closed='clearData' :close-on-click-modal='false'>
        //model ====> 表单数据对象
<el-form :model="formData" :rules="deal_rules" ref='dealForm' label-width="100px" v-if="formData!==null">
<el-form-item label="提现订单号" prop="order">
<el-input v-model="formData.order"></el-input>
</el-form-item>
<el-form-item label="提现金额" prop="clearing">
<el-input v-model="formData.clearing"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="openUpdate = false">取 消</el-button>
<el-button type="primary" @click="submitData('dealForm')">确 定</el-button>
</span>
</el-dialog>

提交申请:

submitData(name){
if(!Utils.checkToken(this))return;
this.$refs[name].validate(valid=>{
if(valid){
let loading = this.$loading();
this.withdrawHandleAPI({
id:this.formData.id,
clearing:this.formData.clearing,
order:this.formData.order,
}).then(({body})=>{
loading.close();
this.openUpdate = false;
if(body.code===){
this.$message.success(body.msg)
this.getApplyInfo(this.page);
}else{
this.$message.error(body.msg)
}
},err=>{
loading.close();
this.$message.error(err.msg)
})
}
})
}
  • 权限:

  • 切换角色类型:

 <el-radio-group v-model="record_type">
<el-radio-button :label="item" v-for="(item,index) in role_list" :key='index'></el-radio-button>
</el-radio-group>

监听双向绑定额数据:

 watch:{
//切换角色类型
record_type(newVal,oldVal){
this.showPagination = false;
this.getUserRoleList();
}
}

监听数据这里不是函数,而是一个固定写法,第一个参数是new值,第二个参数是old值(而且这里不用this)

  • 直达功能

添加直达

模板代码:

 <template v-if="canAdd!==null">
<el-button class="addNonstop" size="small" type="primary" @click="setShortcut('post')" v-if="canAdd===1">添加直达</el-button>
<el-button class="addNonstop" size="small" type="warning" @click="setShortcut('delete')" v-if="canAdd===0">取消直达</el-button>
</template>

直达功能代码:

 setShortcut(method){
if(!Utils.checkToken(this))return;
const name = this.$route.meta[].name? this.$route.meta[].name: this.$route.meta[].name;
let query;
if(method==='delete'){
query = {
method:method,
data:{
body:{
nav_name:name,
nav_url:this.$route.path
}
}
}
}else{
query = {
method:method,
data:{
nav_name:name,
nav_url:this.$route.path
}
}
}
this.updateShortcutAPI(query).then(
res => {
this.$message.success(res.body.msg);
this.shortcutListAPI()
},
err => {
this.$message.error(err.msg);
}
);
}

直达功能

$route为当前router跳转对象里面可以获取name、path、query、params等

$router为VueRouter实例,想要导航到不同URL,则使用$router.push方法

  • 点击曲线获得数据
       const This = this;
let mChart_line1 = This.$echarts.init(document.getElementById("mChart_line"));
mChart_line1.getZr().off("click"); // ZRender 一个轻量级的Canvas类库
mChart_line1.getZr().on("click", params => {
const pointInPixel = [params.offsetX, params.offsetY];
if (mChart_line1.containPixel({ seriesIndex: [] }, pointInPixel)) {
//判断给定的点是否在指定的坐标系或者系列上
let xIndex = mChart_line1.convertFromPixel({ seriesIndex: }, [
//转换像素坐标值到逻辑坐标系上的点
params.offsetX,
params.offsetY
])[]; /*事件处理代码书写位置*/
This.day =
This.date_type === "month"
? This.total_data.date[xIndex] + "-01"
: This.total_data.date[xIndex];
This.showPagination = false;
this.getData()
}
});
  • 两种查询方式调同一个方法里面的接口: (一个传值,一个不传值) //即使是不同的地方点击事件,里面的参数也会保存。
 getInvoiceList(page){
if(!Utils.checkToken(this))return;
if (this.begin_date === null || this.end_date === null) {
this.$message.error("请选择时间!");
return;
}
this.table_loading = true;
this.billingInfoAPI({
begin_date: Utils.formatDate(this.begin_date, "yyyy-MM-dd"),
end_date: Utils.formatDate(this.end_date, "yyyy-MM-dd"),
status: this.status,
page: page,
page_size: this.page_size,
keyword:this.keyword
}).then(res=>{
this.table_loading = false;
this.showPagination = true;
},err=>{
this.table_loading = false;
this.showPagination = true;
this.$message.error(err.msg);
})
},

传值的

  invoiceQuery() {
this.showPagination = false;
this.getInvoiceList();
}

不传值的

遍历数据的三种写法:

1.v-for

 <el-form-item label="来源:">
<el-radio-group v-model="origin" @change="showPagination=false,search(1)">
<el-radio v-for='(item,index) in origin_list' :key="index" :label="index">{{item}}</el-radio>
</el-radio-group>
</el-form-item>

2.element 模板  利用v-bind绑定数据, 然后传个prop属性作为值。

 <el-table border :data="userData" v-loading='tableLoadingOne'>
<el-table-column label="用户总数" prop="user_total_num"></el-table-column>
<el-table-column label="总充值次数" prop="add_money_num"></el-table-column>
<el-table-column label="充值总额(元)" prop="add_money_total"></el-table-column>
<el-table-column label="总使用次数" prop="rent_num"></el-table-column>
<el-table-column label="消费总额(易学币)" prop="cunsumption_money_total"></el-table-column>
</el-table>
  • 2-1  如果需要对获取的值做个判断,可以在这个里面嵌套个 <template slot-scope = 'scope'> </template>  再用插值表达式判断

3.element表单组件,利用v-bind:model绑定数据,然后利用v-model双向绑定机制输出。

 <el-form :model="editData" ref="editForm" :rules="rules" v-if="editData!==null" class="recharge-form" label-width="100px">
<el-form-item label="策略编号" prop="policy_reference">
<el-select v-model="editData.policy_reference" placeholder="请选择策略" :disabled="editTitle==='修改折扣'">
  <el-option v-for="(item,index) in idList" :key="index" :label="item" :value="item"></el-option>
   </el-select>
          </el-form-item>
</el-form>
 
  • 通过JS适配移动端WEB页面
 function adaptation() {//通过JS适配移动端
(function(doc, win) {
var docEl = doc.documentElement,
recalc = function() {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
//&&!navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)
if (clientWidth >= ) {
docEl.style.fontSize = '100px';
} else {
docEl.style.fontSize = * (clientWidth / ) + 'px';
}
};
// if (!doc.addEventListener) return;
// doc.addEventListener('DOMContentLoaded', recalc, false);
recalc();
})(document, window);
}

待完成 :

  • 聊天室(前台)
  • 直播 (前台)
  • 支付功能(前台)

【原创】Vue项目中各种功能的实现的更多相关文章

  1. 在vue项目中使用codemirror插件实现代码编辑器功能(代码高亮显示及自动提示

    在vue项目中使用codemirror插件实现代码编辑器功能(代码高亮显示及自动提示) 1.使用npm安装依赖 npm install --save codemirror; 2.在页面中放入如下代码 ...

  2. Vue项目中添加锁屏功能

    0. 直接上 预览链接 Vue项目中添加锁屏功能 1. 实现思路 ( 1 ) 设置锁屏密码 ( 2 ) 密码存localStorage (本项目已经封装h5的sessionStorage和localS ...

  3. 浅谈 Axios 在 Vue 项目中的使用

    介绍 Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中. 特性 它主要有如下特性: 浏览器端发起XMLHttpRequests请求 Node端发起http ...

  4. scss/less语法以及在vue项目中的使用(转载)

    1.scss与less都是css的预处理器,首先我们的明白为什么要用scss与less,因为css只是一种标记语言,其中并没有函数变量之类的,所以当写复杂的样式时必然存在局限性,不灵活,而scss与l ...

  5. 转:如何在Vue项目中使用vw实现移动端适配

    https://www.w3cplus.com/mobile/vw-layout-in-vue.html 有关于移动端的适配布局一直以来都是众说纷纭,对应的解决方案也是有很多种.在<使用Flex ...

  6. 在Vue项目中使用vw实现移动端适配

    有关于移动端的适配布局一直以来都是众说纷纭,对应的解决方案也是有很多种.在<使用Flexible实现手淘H5页面的终端适配>提出了Flexible的布局方案,随着viewport单位越来越 ...

  7. 如何在Vue项目中使用vw实现移动端适配(转)

    有关于移动端的适配布局一直以来都是众说纷纭,对应的解决方案也是有很多种.在<使用Flexible实现手淘H5页面的终端适配>提出了Flexible的布局方案,随着viewport单位越来越 ...

  8. vue 项目中命名方法

    命名 命名的方法通常有以下几类: 命名法说明 1).camel命名法,形如thisIsAnApple 2).pascal命名法,形如ThisIsAnApple 3).下划线命名法,形如this_is_ ...

  9. Vue项目中使用vw实现移动端适配

    我们在vue移动端项目中的适配一般都采用rem,但是rem也不是能兼容所有的终端. 随着viewport单位越来越受到众多浏览器的支持,下面将简单介绍怎么实现vw的兼容问题,用vw代替rem 当我们采 ...

随机推荐

  1. MyBatis 的基本要素—SQL 映射文件

    MyBatis 真正的强大在于映射语句,相对于它强大的功能,SQL 映射文件的配置却是相当简单.对比 SQL 映射配置和 JDBC 代码,发现使用 SQL 映射文件配置可减少 50% 以上的代码,并且 ...

  2. 洛谷 2048 BZOJ 2006 [NOI2010]超级钢琴

    [题解] 贪心题.设五元组(mx,pos,l,r1,r2)表示最大值为mx,取得最大值的区间右端点为pos,区间左端点为l,区间右端点的可选区间为[r1,r2]. 每次从堆里拎出最大值,然后把这个区间 ...

  3. The Falling Leaves(建树方法)

    uva 699 紫书P159 Each year, fall in the North Central region is accompanied by the brilliant colors of ...

  4. Python基础(四) 基础拾遗、数据类型进阶

    一.基础拾遗 (一).变量作用域 外层变量,可以被内层变量直接调用:内层变量,无法被外层变量使用.这种说法在其它语言中适用,在python中除了栈以外,正常的变量作用域,只要执行声明并在内存中存在,该 ...

  5. JUnit基本用法

    JUnit的一些注意事项: 测试方法必须使用@Test修饰 测试方法必须使用public void进行修饰,不能带参数 一般使用单元测试会新建一个test目录存放测试代码,在生产部署的时候只需要将te ...

  6. at24c02系列和at24c256系列的比较

    编号的含义: at24c02系列包括的有: 128(1K),256(2K),512(4K),1024(8K),2048(16K)字节(B) at24c256系列包括的有: 16384(128K),32 ...

  7. tomcat配置虚拟目录实现无项目名访问项目,域名直接访问

    1.tomcat下新建文件夹名为 myapp,把编译后的项目放入该文件夹,不是war包. 2.conf/Catalina/localhost目录下,新建一个ROOT.xml文件,写入类似于如下内容 & ...

  8. MYSQL常用的字符串函数

    #字符串函数 #返回字符串的字符数量,对于此例而言,结果为5SELECT CHAR_LENGTH('计算机编程'); #合并字符串,对于此例而言,结果为‘我喜欢计算机’SELECT CONCAT('我 ...

  9. endWith is not a function

    解决方法,增加String的扩展 String.prototype.endWith = function(suffix) { return this.indexOf(suffix, this.leng ...

  10. JAVA包装类的缓存范围

    JAVA包装类的缓存范围 前两天面试遇到两个关于JAVA源码的问题,记录下来提醒自己. 1.写出下面的输出结果 System.out.println(Integer.valueOf("100 ...