Browse Source

feat:新增首页内容

confidence
杜贤金 3 years ago
parent
commit
357f824e89
  1. 14
      src/api/communication/flowpool.js
  2. 74
      src/api/wel/administrator.js
  3. 50
      src/api/wel/buser.js
  4. 132
      src/views/communicationmanage/flowpool/flowpool.vue
  5. 71
      src/views/communicationmanage/targetflowpool/targetflowpool.vue
  6. 708
      src/views/wel/component/Administrator.vue
  7. 524
      src/views/wel/component/Buser.vue
  8. 683
      src/views/wel/component/clientside.vue
  9. 14
      src/views/wel/index.vue

14
src/api/communication/flowpool.js

@ -47,3 +47,17 @@ export const update = (row) => {
}) })
} }
//同步流量池
export const syncFlowPool = () => {
return request({
url: '/api/iot-sim/flowpool/syncFlowPool',
method: 'get',
})
}
//同步流量池使用量
export const syncFlowPoolUsage = () => {
return request({
url: '/api/iot-sim/flowpool/syncFlowPoolUsage',
method: 'get',
})
}

74
src/api/wel/administrator.js

@ -1,4 +1,5 @@
import request from '@/router/axios'; import request from '@/router/axios';
// ----- 卡状态start
//卡总数 //卡总数
export const cardTotal = () => { export const cardTotal = () => {
return request({ return request({
@ -21,3 +22,76 @@ export const cardStatus = () => {
method: 'get', method: 'get',
}) })
} }
// ----- 卡状态end
// ----- 元流量池监控start
export const getFlowPool = () => {
return request({
url: '/api/iot-sim/home/getFlowPool',
method: 'get',
})
}
// ----- 元流量池监控end
// -----设备接入总数start
export const getDeviceNum = () => {
return request({
url: '/api/iot-sim/home/getDeviceNum',
method: 'get',
})
}
// ----- 设备接入总数end
// -----日使用排名、月使用排名start
export const getUsage = (type) => {
return request({
url: '/api/iot-sim/home/getUsage',
method: 'get',
params: {
type
}
})
}
// ----- 日使用排名、月使用排名end
// -----日收款、月收款start
export const getMoney = (type) => {
return request({
url: '/api/iot-sim/home/getMoney',
method: 'get',
params: {
type
}
})
}
// ----- 日收款、月收款排名end
// -----:佣金申请数量 结算佣金数量start 1:佣金申请数量 2:结算佣金数量
export const getWithdrawal = (type) => {
return request({
url: '/api/iot-sim/home/getWithdrawal',
method: 'get',
params: {
type
}
})
}
// ----- 佣金申请数量 结算佣金数量end
// -----:echars使用量 start
export const getMonthUsage = () => {
return request({
url: '/api/iot-sim/home/getMonthUsage',
method: 'get',
})
}
// ----- echars使用量 end
// -----本月订单 本日订单 1:今天 5:本月
export const getOrderNum = (type) => {
return request({
url: '/api/iot-sim/home/getOrderNum',
method: 'get',
params: {
type
}
})
}
// ----- 本月订单 本日订单end

50
src/api/wel/buser.js

@ -0,0 +1,50 @@
import request from '@/router/axios';
//运营商卡数量
export const getOperatorCardNum = () => {
return request({
url: '/api/iot-sim/home/getOperatorCardNum',
method: 'get',
})
}
//卡状态
export const cardStatus = () => {
return request({
url: '/api/iot-sim/home/getSimStatus',
method: 'get',
})
}
// ----- 流量池监控start
export const getFlowPool = () => {
return request({
url: '/api/iot-sim/home/getPoolMonitoring',
method: 'get',
})
}
// -----:echars使用量 start
export const getTotalUsage = () => {
return request({
url: '/api/iot-sim/home/getTotalUsage',
method: 'get',
})
}
// -----日使用排名、月使用排名start
export const getUsage = (type) => {
return request({
url: '/api/iot-sim/home/getUsage',
method: 'get',
params: {
type
}
})
}
// ----- 日使用排名、月使用排名end
//剩余量
export const getCardSurplus = () => {
return request({
url: '/api/iot-sim/home/getCardSurplus',
method: 'get',
})
}

132
src/views/communicationmanage/flowpool/flowpool.vue

@ -19,19 +19,23 @@
@refresh-change="refreshChange" @refresh-change="refreshChange"
@on-load="onLoad" @on-load="onLoad"
> >
<template slot-scope="{ disabled, size, value }" slot="activationNumForm"> <template slot="menuLeft">
<el-input <el-button
:disabled="disabled" size="small"
:size="size" type="primary"
v-model="value == -1 ? '-' : value" icon="el-icon-refresh-right"
></el-input> @click="handlesyncFlowPool"
>同步流量池
</el-button>
</template> </template>
<template slot-scope="{ disabled, size, value }" slot="accountForm"> <template slot="menuLeft">
<el-input <el-button
:disabled="disabled" size="small"
:size="size" type="primary"
v-model="value == '' ? '-' : value" icon="el-icon-refresh-right"
></el-input> @click="handlesyncFlowPoolUsage"
>同步流量池使用量
</el-button>
</template> </template>
</avue-crud> </avue-crud>
</basic-container> </basic-container>
@ -44,6 +48,8 @@ import {
add, add,
remove, remove,
update, update,
syncFlowPool,
syncFlowPoolUsage,
} from "@/api/communication/flowpool"; } from "@/api/communication/flowpool";
import { mapGetters } from "vuex"; import { mapGetters } from "vuex";
@ -82,7 +88,7 @@ export default {
prop: "channelId", prop: "channelId",
type: "select", type: "select",
span: 12, span: 12,
width: 100,
search: true, search: true,
dataType: "String", dataType: "String",
dicUrl: "/api/iot-sim/channel/fillData", dicUrl: "/api/iot-sim/channel/fillData",
@ -98,6 +104,22 @@ export default {
}, },
], ],
}, },
{
label: "接口类型",
type: "select",
dicUrl: "/api/iot-system/dict/dictionary?code=interface_type",
props: {
label: "dictValue",
value: "dictKey",
},
span: 12,
dataType: "number",
prop: "interfaceType",
search: true,
rules: [
{ required: true, message: "请选择接口类型", trigger: "change" },
],
},
{ {
label: "流量池编号", label: "流量池编号",
prop: "code", prop: "code",
@ -129,11 +151,37 @@ export default {
], ],
}, },
{ {
label: "流量池总量", label: "流量池总量(M)",
prop: "total", prop: "total",
span: 12, span: 12,
addDisplay: false,
editDisplay: false,
searchLabelWidth: 90, searchLabelWidth: 90,
width: 115,
search: false,
hide: false,
type: "number",
rules: [
{
required: true,
message: "请输入流量池总量",
trigger: "blur",
},
{
pattern: /^\d+(\.\d+)?$/,
message: "请输入正确的流量池总量",
trigger: "blur",
},
],
},
{
label: "流量池使用量(M)",
prop: "usageM",
span: 12,
addDisplay: false,
editDisplay: false,
searchLabelWidth: 90,
width: 115,
search: false, search: false,
hide: false, hide: false,
type: "number", type: "number",
@ -154,7 +202,6 @@ export default {
label: "提醒阈值", label: "提醒阈值",
prop: "remindRatio", prop: "remindRatio",
span: 12, span: 12,
searchLabelWidth: 90, searchLabelWidth: 90,
search: false, search: false,
hide: false, hide: false,
@ -243,39 +290,52 @@ export default {
label: "已激活数量", label: "已激活数量",
prop: "activationNum", prop: "activationNum",
span: 12, span: 12,
search: false, search: false,
hide: true,
addDisplay: false, addDisplay: false,
editDisplay: false, editDisplay: false,
formslot: true, viewDisplay: true,
rules: [ rules: [
{ {
required: true, required: true,
message: "请输入已激活数量", message: "请输入已激活数量",
trigger: "blur", trigger: "blur",
}, },
],
},
{
label: "未激活数量",
prop: "unactivatedNum",
span: 12,
search: false,
addDisplay: false,
editDisplay: false,
viewDisplay: true,
rules: [
{ {
pattern: /^\d+?$/, required: true,
message: "请输入正确的已激活数量", message: "请输入激活数量",
trigger: "blur", trigger: "blur",
}, },
], ],
}, },
{ {
label: "管理员名称", label: "超量是否停机所有流量卡",
prop: "account", prop: "isStopAll",
type: "select",
dicUrl: "/api/iot-system/dict/dictionary?code=yes_no",
props: {
label: "dictValue",
value: "dictKey",
},
dataType: "number",
span: 12, span: 12,
search: false, search: false,
addDisplay: false,
editDisplay: false,
hide: true, hide: true,
formslot: true,
rules: [ rules: [
{ {
required: true, required: true,
message: "请输入管理员账号", message: "请选择是否停机所有流量卡",
trigger: "blur", trigger: "change",
}, },
], ],
}, },
@ -387,6 +447,22 @@ export default {
this.loading = false; this.loading = false;
}); });
}, },
//
handlesyncFlowPool() {
syncFlowPool().then((res) => {
if (res.data.code == 200) {
this.onLoad(this.page, this.query);
}
});
},
//使
handlesyncFlowPoolUsage() {
syncFlowPoolUsage().then((res) => {
if (res.data.code == 200) {
this.onLoad(this.page, this.query);
}
});
},
}, },
}; };
</script> </script>

71
src/views/communicationmanage/targetflowpool/targetflowpool.vue

@ -19,20 +19,6 @@
@refresh-change="refreshChange" @refresh-change="refreshChange"
@on-load="onLoad" @on-load="onLoad"
> >
<template slot-scope="{ disabled, size, value }" slot="activationNumForm">
<el-input
:disabled="disabled"
:size="size"
v-model="value == -1 ? '-' : value"
></el-input>
</template>
<template slot-scope="{ disabled, size, value }" slot="accountForm">
<el-input
:disabled="disabled"
:size="size"
v-model="value == '' ? '-' : value"
></el-input>
</template>
</avue-crud> </avue-crud>
</basic-container> </basic-container>
</template> </template>
@ -102,13 +88,13 @@ export default {
label: "目标流量池编号", label: "目标流量池编号",
prop: "code", prop: "code",
span: 12, span: 12,
width: 105,
searchLabelWidth: 90, searchLabelWidth: 90,
search: false, search: false,
rules: [ rules: [
{ {
required: true, required: true,
message: "请输入设备序列号", message: "请输入目标流量池编号",
trigger: "blur", trigger: "blur",
}, },
], ],
@ -117,7 +103,7 @@ export default {
label: "目标流量池名称", label: "目标流量池名称",
prop: "name", prop: "name",
span: 12, span: 12,
width: 105,
searchLabelWidth: 130, searchLabelWidth: 130,
search: true, search: true,
rules: [ rules: [
@ -129,11 +115,37 @@ export default {
], ],
}, },
{ {
label: "目标流量池总量", label: "流量池总量(M)",
prop: "total", prop: "total",
span: 12, span: 12,
searchLabelWidth: 90,
search: false,
addDisplay: false,
editDisplay: false,
hide: false,
type: "number",
rules: [
{
required: true,
message: "请输入流量池总量",
trigger: "blur",
},
{
pattern: /^\d+(\.\d+)?$/,
message: "请输入正确的流量池总量",
trigger: "blur",
},
],
},
{
label: "流量池使用量(M)",
prop: "usageM",
span: 12,
addDisplay: false,
editDisplay: false,
searchLabelWidth: 90, searchLabelWidth: 90,
width: 115,
search: false, search: false,
hide: false, hide: false,
type: "number", type: "number",
@ -154,7 +166,6 @@ export default {
label: "提醒阈值", label: "提醒阈值",
prop: "remindRatio", prop: "remindRatio",
span: 12, span: 12,
searchLabelWidth: 90, searchLabelWidth: 90,
search: false, search: false,
hide: false, hide: false,
@ -206,7 +217,6 @@ export default {
}, },
dataType: "number", dataType: "number",
prop: "type", prop: "type",
searchLabelWidth: 140, searchLabelWidth: 140,
search: false, search: false,
rules: [ rules: [
@ -222,7 +232,6 @@ export default {
label: "单卡最大使用量(M)", label: "单卡最大使用量(M)",
prop: "maxUsage", prop: "maxUsage",
span: 12, span: 12,
search: false, search: false,
hide: true, hide: true,
type: "number", type: "number",
@ -239,43 +248,35 @@ export default {
}, },
], ],
}, },
{ {
label: "已激活数量", label: "已激活数量",
prop: "activationNum", prop: "activationNum",
span: 12, span: 12,
search: false, search: false,
hide: true,
addDisplay: false, addDisplay: false,
editDisplay: false, editDisplay: false,
formslot: true, viewDisplay: true,
rules: [ rules: [
{ {
required: true, required: true,
message: "请输入已激活数量", message: "请输入已激活数量",
trigger: "blur", trigger: "blur",
}, },
{
pattern: /^\d+?$/,
message: "请输入正确的已激活数量",
trigger: "blur",
},
], ],
}, },
{ {
label: "管理员名称", label: "未激活数量",
prop: "account", prop: "unactivatedNum",
span: 12, span: 12,
search: false, search: false,
addDisplay: false, addDisplay: false,
editDisplay: false, editDisplay: false,
viewDisplay: false, viewDisplay: true,
hide: true,
formslot: true,
rules: [ rules: [
{ {
required: true, required: true,
message: "请输入管理员账号", message: "请输入未激活数量",
trigger: "blur", trigger: "blur",
}, },
], ],

708
src/views/wel/component/Administrator.vue

@ -1,27 +1,699 @@
<template> <template>
<div class="app-container"> <basic-container>
<div class="dashboard-container"> <div class="app-container">
<div class="dashboard-text">欢迎访问物联网平台</div> <div class="cardTotal">
<div> <el-card class="box-card">
<img src="@/assets/shouye.png" alt class="dashboard-img" /> <div slot="header" class="clearfix">
<el-select
v-model="cardtype"
placeholder="请选择"
size="small"
@change="handleCardType"
>
<el-option
v-for="(item, index) in cardType"
:key="index"
:label="item"
:value="item"
>
</el-option>
</el-select>
</div>
<div id="cardTotalmain" style="width: 100%; height: 165px"></div>
</el-card>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>元流量池监控</span>
</div>
<div
class="foolbox"
v-for="(item, index) in foolmonitoring"
:key="index"
>
<div class="top">
<div class="name">{{ item.name }}</div>
<div class="G">{{ item.totalM }}M</div>
</div>
<div class="progress">
<el-progress
:text-inside="true"
:stroke-width="18"
:percentage="item.ratio"
:status="Number(item.ratio) > 80 ? 'warning' : ''"
></el-progress>
</div>
</div>
</el-card>
<el-card class="box-card"> </el-card>
</div>
<div class="statistics">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>设备接入总数</span>
</div>
<div class="device">{{ getDeviceNumsObj }}</div>
</el-card>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>会员总数</span>
</div>
<div class="water">
<div>
<div class="number">0</div>
<div class="water-name">企业</div>
</div>
<div>
<div class="number">0</div>
<div class="water-name">个人</div>
</div>
</div>
</el-card>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>销售情况</span>
</div>
<div class="water">
<div>
<div class="number">0</div>
<div class="water-name">累计销售</div>
</div>
<div>
<div class="number">0</div>
<div class="water-name">本年销售</div>
</div>
<div>
<div class="number">0</div>
<div class="water-name">本月销售</div>
</div>
</div>
</el-card>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>佣金总计</span>
</div>
<div class="water">
<div>
<div class="number">0</div>
<div class="water-name">已支付</div>
</div>
<div>
<div class="number">0</div>
<div class="water-name">未支付</div>
</div>
</div>
</el-card>
</div>
<div class="tabs">
<el-card class="box-card">
<div class="tabs-box">
<div class="useTypeBox">
<div
v-for="(item, index) in useType"
:key="index"
:class="useIndex == index ? 'useType color' : 'useType nocolor'"
@click="handleTabs(index)"
>
{{ item.name }}
</div>
</div>
</div>
<!-- 总使用量 -->
<div class="totaluse" v-show="useIndex == 0">
<div class="left">
<div id="useEchars" style="width: 100%; height: 300px"></div>
</div>
<div class="right">
<div
class="show-box"
v-for="(item, index) in totaluseoptions"
:key="index"
>
<div class="show">
<div>
<div class="title">{{ item.name }}</div>
<div class="content">{{ item.money }}</div>
</div>
</div>
</div>
</div>
</div>
<!-- 销售排行 -->
<div class="rank" v-show="useIndex != 0">
<div class="rank-box">
<div
class="rankList"
v-for="(item, index) in rankListArr"
:key="index"
>
<div class="left">
<div class="index">{{ index + 1 }}</div>
</div>
<div class="right">
<div class="phone">{{ item.iccid }}</div>
<div class="num">{{ item.usage }}(M)</div>
</div>
</div>
</div>
</div>
</el-card>
</div> </div>
</div> </div>
</div> </basic-container>
</template> </template>
<script>
import * as echarts from "echarts";
import {
cardTotal,
operatorCard,
cardStatus,
getFlowPool,
getDeviceNum,
getUsage,
getMoney,
getWithdrawal,
getMonthUsage,
getOrderNum,
} from "@/api/wel/administrator";
export default {
data() {
return {
cardtype: "卡总数",
cardType: ["卡总数", "运营商卡数量", "出库卡状态"],
cardData: [],
month: [],
usage: [],
useIndex: 0,
useType: [
{
name: "总使用量",
},
{
name: "销售排名",
},
{
name: "月使用排名",
},
{
name: "日使用排名",
},
],
//
foolmonitoring: [],
//
getDeviceNumsObj: 0,
//echars
totaluseoptions: [
{
name: "本日收款",
money: "0",
},
{
name: "本月收款",
money: "0",
},
{
name: "本日订单数量",
money: "0",
},
{
name: "本月订单数量",
money: "0",
},
{
name: "佣金提现申请",
money: "0",
},
{
name: "结算佣金数",
money: "0",
},
],
//使使
rankListArr: [],
};
},
created() {
this.cardTotals();
this.getFlowPools(); //
this.getDeviceNums(); //
this.getMoneys();
this.getMoneyss();
this.getWithdrawals();
this.getWithdrawalss();
this.getMonthUsages();
this.getOrderNums();
this.getOrderNumss();
},
mounted() {},
methods: {
//
handleCardType(e) {
if (e == "卡总数") {
this.cardTotals();
} else if (e == "运营商卡数量") {
this.operatorCards();
} else if (e == "出库卡状态") {
this.cardStatuss();
}
},
//
cardTotals() {
cardTotal().then((res) => {
if (res.data.code == 200) {
(this.cardData = [
{
name: "出库数量",
value: res.data.data.deliver,
},
{
name: "未出库数量",
value: res.data.data.notDeliver,
},
]),
this.cardTotal();
}
});
},
<style scoped> //
.dashboard-container { operatorCards() {
width: 100%; operatorCard().then((res) => {
text-align: center; if (res.data.code == 200) {
this.cardData = [
{
name: "山东省移动",
value: res.data.data.shanDongShengYiDong,
},
{
name: "山东省电信",
value: res.data.data.shanDongShengDianXin,
},
{
name: "华为电信",
value: res.data.data.huaWeiDianXin,
},
{
name: "济南历城移动",
value: res.data.data.jiNanLiChengYiDong,
},
{
name: "北京移动",
value: res.data.data.beiJingYiDong,
},
{
name: "济南天桥移动",
value: res.data.data.jiNanTianQiaoYiDong,
},
];
this.cardTotal();
}
});
},
//
cardStatuss() {
cardStatus().then((res) => {
console.log(res, 3);
if (res.data.code == 200) {
this.cardData = [
{
name: "已激活",
value: res.data.data.inUse,
},
{
name: "未激活",
value: res.data.data.unused,
},
{
name: "停机",
value: res.data.data.shutdown,
},
{
name: "其他",
value: res.data.data.other,
},
];
this.cardTotal();
}
});
},
//
cardTotal() {
let chartDom = document.getElementById("cardTotalmain");
let myChart = echarts.init(chartDom);
let option;
option = {
tooltip: {
trigger: "item",
},
legend: {
type: "scroll",
orient: "vertical",
right: 0,
},
series: [
{
type: "pie",
radius: ["60%", "90%"],
center: ["40%", "50%"],
avoidLabelOverlap: false,
label: {
show: false,
position: "left",
},
labelLine: {
show: false,
},
data: this.cardData,
},
],
};
option && myChart.setOption(option);
},
//
getFlowPools() {
getFlowPool().then((res) => {
if (res.data.code == 200) {
this.foolmonitoring = res.data.data;
}
});
},
//
getDeviceNums() {
getDeviceNum().then((res) => {
if (res.data.code == 200) {
this.getDeviceNumsObj = res.data.data;
}
});
},
//使echars
useEchars() {
let chartDoms = document.getElementById("useEchars");
let myCharts = echarts.init(chartDoms);
let options;
options = {
xAxis: {
name: "月",
type: "category",
boundaryGap: false,
data: this.month,
},
yAxis: {
type: "value",
name: "M",
},
series: [
{
data: this.usage,
type: "line",
areaStyle: {},
},
],
tooltip: {
trigger: "axis",
axisPointer: {
type: "cross",
label: {
backgroundColor: "#6a7985",
},
},
},
};
options && myCharts.setOption(options);
},
//
handleTabs(index) {
this.useIndex = index;
if (index == 2) {
this.getUsages(2);
} else if (index == 3) {
this.getUsages(1);
}
},
//使使 type 2:1
getUsages(type) {
getUsage(type).then((res) => {
if (res.data.code == 200) {
this.rankListArr = res.data.data;
}
});
},
// type 2:1
getMoneys() {
getMoney(1).then((res) => {
if (res.data.code == 200) {
this.totaluseoptions[0].money = res.data.data;
}
});
},
getMoneyss() {
getMoney(2).then((res) => {
if (res.data.code == 200) {
this.totaluseoptions[1].money = res.data.data;
}
});
},
//
getOrderNums() {
getOrderNum(1).then((res) => {
if (res.data.code == 200) {
this.totaluseoptions[2].money = res.data.data.total;
}
});
},
getOrderNumss() {
getOrderNum(5).then((res) => {
if (res.data.code == 200) {
this.totaluseoptions[3].money = res.data.data.total;
}
});
},
//
getWithdrawals() {
getWithdrawal(1).then((res) => {
if (res.data.code == 200) {
this.totaluseoptions[4].money = res.data.data;
}
});
},
getWithdrawalss() {
getWithdrawal(2).then((res) => {
if (res.data.code == 200) {
this.totaluseoptions[5].money = res.data.data;
}
});
},
//使
getMonthUsages() {
getMonthUsage().then((res) => {
let month = [];
let usage = [];
if (res.data.code == 200) {
res.data.data.forEach((element) => {
month.push(element.month);
usage.push(element.usage);
});
this.month = month;
this.usage = usage;
this.useEchars();
}
});
},
},
};
</script>
<style scoped lang="scss">
.cardTotal {
display: flex;
justify-content: space-between;
.box-card {
width: 32%;
height: 250px;
overflow: auto;
.foolbox {
margin-top: 2px;
.top {
display: flex;
justify-content: space-between;
.name {
font-size: 13px;
color: #666;
font-weight: bold;
}
}
.roundtop {
display: flex;
justify-content: space-around;
}
.round {
display: flex;
justify-content: center;
}
.progress {
margin-top: 1px;
}
}
}
} }
.dashboard-text { .clearfix {
color: #333; font-size: 17px;
font-size: 25px; font-weight: bold;
margin-top: 15%; color: #666;
} }
.dashboard-img { //
margin-top: 40px; .statistics {
width: 25%; display: flex;
height: 25%; justify-content: space-between;
margin-top: 12px;
.box-card {
width: 24%;
.device {
font-size: 34px;
display: flex;
justify-content: center;
align-items: center;
height: 90px;
font-weight: bold;
color: rgb(66, 125, 169);
}
.water {
height: 90px;
display: flex;
justify-content: space-around;
align-items: center;
text-align: center;
.number {
font-size: 19px;
font-weight: bold;
color: rgb(66, 125, 169);
}
.water-name {
margin-top: 9px;
font-size: 16px;
font-weight: 500;
color: rgb(66, 125, 169);
}
}
}
}
//
.tabs {
margin-top: 10px;
width: 100%;
.tabs-box {
.useTypeBox {
width: 50%;
margin: 0 auto;
display: flex;
justify-content: space-around;
.useType {
cursor: pointer;
padding-bottom: 13px;
}
.color {
border-bottom: 2px solid blueviolet;
color: "blueviolet";
}
.nocolor {
border-bottom: 2px solid white;
}
}
}
.totaluse {
display: flex;
.left {
flex: 4;
}
.right {
flex: 2;
margin-top: 20px;
display: flex;
justify-content: space-around;
flex-wrap: wrap;
.show-box {
width: 46%;
height: 80px;
background: #427da9;
border-radius: 14px;
display: flex;
justify-content: center;
align-items: center;
.show {
width: 92%;
height: 70px;
background: #427da9;
border-radius: 14px;
border: 1px solid white;
color: white;
display: flex;
justify-content: center;
align-items: center;
.title {
font-size: 14px;
}
.content {
font-size: 18px;
text-align: center;
}
}
}
}
}
.rank {
width: 100%;
height: 300px;
margin: 0 auto;
.rank-box {
width: 90%;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.rankList {
display: flex;
width: 50%;
margin-top: 15px;
.left {
width: 13%;
height: 40px;
background: #427da9;
.index {
color: white;
text-align: center;
font-size: 16px;
line-height: 40px;
font-weight: bold;
}
}
.right {
width: 80%;
height: 40px;
background: #f2f2f2;
display: flex;
align-items: center;
justify-content: space-around;
color: #427da9;
font-weight: 700;
.phone {
width: 60%;
}
.num {
width: 20%;
}
}
}
}
}
} }
</style> </style>

524
src/views/wel/component/Buser.vue

@ -0,0 +1,524 @@
<template>
<basic-container>
<div class="app-container">
<div class="cardTotal">
<el-card class="box-card">
<div slot="header" class="clearfix">
<el-select
v-model="cardtype"
placeholder="请选择"
size="small"
@change="handleCardType"
>
<el-option
v-for="(item, index) in cardType"
:key="index"
:label="item"
:value="item"
>
</el-option>
</el-select>
</div>
<div id="cardTotalmain" style="width: 100%; height: 165px"></div>
</el-card>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>流量池监控</span>
</div>
<div
class="foolbox"
v-for="(item, index) in foolmonitoring"
:key="index"
>
<div class="top">
<div class="name">{{ item.name }}</div>
<div class="G">{{ item.totalM }}M</div>
</div>
<div class="progress">
<el-progress
:text-inside="true"
:stroke-width="18"
:percentage="item.ratio"
:status="Number(item.ratio) > 80 ? 'warning' : ''"
></el-progress>
</div>
</div>
</el-card>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>流量剩余量</span>
</div>
<div class="foolbox">
<div class="top">
<el-table :data="residueListArr" style="width: 100%">
<el-table-column prop="iccid" label="ICCID"> </el-table-column>
<el-table-column prop="surplus" label="剩余量(M)" align="right">
</el-table-column>
</el-table>
</div>
</div>
</el-card>
</div>
<div class="tabs">
<el-card class="box-card">
<div class="tabs-box">
<div class="useTypeBox">
<div
v-for="(item, index) in useType"
:key="index"
:class="useIndex == index ? 'useType color' : 'useType nocolor'"
@click="handleTabs(index)"
>
{{ item.name }}
</div>
</div>
</div>
<!-- 总使用量 -->
<div class="totaluse" v-show="useIndex == 0">
<div class="left">
<div id="useEchars" style="width: 100%; height: 300px"></div>
</div>
</div>
<!-- 销售排行 -->
<div class="rank" v-show="useIndex != 0">
<div class="rank-box">
<div
class="rankList"
v-for="(item, index) in rankListArr"
:key="index"
>
<div class="left">
<div class="index">{{ index + 1 }}</div>
</div>
<div class="right">
<div class="phone">{{ item.iccid }}</div>
<div class="num">{{ item.usage }}(M)</div>
</div>
</div>
</div>
</div>
</el-card>
</div>
</div>
</basic-container>
</template>
<script>
import * as echarts from "echarts";
import {
getOperatorCardNum,
cardStatus,
getFlowPool,
getTotalUsage,
getUsage,
getCardSurplus,
} from "@/api/wel/buser";
export default {
data() {
return {
cardtype: "运营商卡数量",
cardType: ["运营商卡数量", "出库卡状态"],
cardData: [],
month: [],
usage: [],
useIndex: 0,
useType: [
{
name: "总使用量",
},
{
name: "月使用排名",
},
{
name: "日使用排名",
},
],
//
foolmonitoring: [],
//
residueListArr: [],
//
//使使
rankListArr: [],
};
},
created() {
this.operatorCards();
this.getFlowPools(); //
this.getTotalUsages(); //使
this.getCardSurpluss(); //
},
mounted() {},
methods: {
//
handleCardType(e) {
if (e == "运营商卡数量") {
this.operatorCards();
} else if (e == "出库卡状态") {
this.cardStatuss();
}
},
//
operatorCards() {
getOperatorCardNum().then((res) => {
if (res.data.code == 200) {
this.cardData = [
{
name: "中国移动",
value: res.data.data.mobile,
},
{
name: "中国联通",
value: res.data.data.unicom,
},
{
name: "中国电信",
value: res.data.data.telecom,
},
];
this.cardTotal();
}
});
},
//
cardStatuss() {
cardStatus().then((res) => {
if (res.data.code == 200) {
this.cardData = [
{
name: "已激活",
value: res.data.data.inUse,
},
{
name: "未激活",
value: res.data.data.unused,
},
{
name: "停机",
value: res.data.data.shutdown,
},
{
name: "其他",
value: res.data.data.other,
},
];
this.cardTotal();
}
});
},
//
cardTotal() {
let chartDom = document.getElementById("cardTotalmain");
let myChart = echarts.init(chartDom);
let option;
option = {
tooltip: {
trigger: "item",
},
legend: {
type: "scroll",
orient: "vertical",
right: 0,
},
series: [
{
type: "pie",
radius: ["60%", "90%"],
center: ["40%", "50%"],
avoidLabelOverlap: false,
label: {
show: false,
position: "left",
},
labelLine: {
show: false,
},
data: this.cardData,
},
],
};
option && myChart.setOption(option);
},
//
getFlowPools() {
getFlowPool().then((res) => {
if (res.data.code == 200) {
this.foolmonitoring = res.data.data;
}
});
},
//
getCardSurpluss() {
getCardSurplus().then((res) => {
if (res.data.code == 200) {
this.residueListArr = res.data.data;
}
});
},
//使echars
useEchars() {
let chartDoms = document.getElementById("useEchars");
let myCharts = echarts.init(chartDoms);
let options;
options = {
xAxis: {
name: "月",
type: "category",
boundaryGap: false,
data: this.month,
},
yAxis: {
type: "value",
name: "M",
},
series: [
{
data: this.usage,
type: "line",
areaStyle: {},
},
],
tooltip: {
trigger: "axis",
axisPointer: {
type: "cross",
label: {
backgroundColor: "#6a7985",
},
},
},
};
options && myCharts.setOption(options);
},
//
handleTabs(index) {
this.useIndex = index;
if (index == 1) {
this.getUsages(2);
} else if (index == 2) {
this.getUsages(1);
}
},
//使使 type 2:1
getUsages(type) {
getUsage(type).then((res) => {
if (res.data.code == 200) {
this.rankListArr = res.data.data;
}
});
},
//使
getTotalUsages() {
getTotalUsage().then((res) => {
let month = [];
let usage = [];
if (res.data.code == 200) {
res.data.data.forEach((element) => {
month.push(element.month);
usage.push(element.usage);
});
this.month = month;
this.usage = usage;
this.useEchars();
}
});
},
},
};
</script>
<style scoped lang="scss">
.cardTotal {
display: flex;
justify-content: space-between;
.box-card {
width: 32%;
height: 250px;
overflow: auto;
.foolbox {
.top {
display: flex;
justify-content: space-between;
.name {
font-size: 13px;
color: #666;
font-weight: bold;
}
}
.roundtop {
display: flex;
justify-content: space-around;
}
.round {
display: flex;
justify-content: center;
}
.progress {
margin-top: 1px;
}
}
}
}
.clearfix {
font-size: 17px;
font-weight: bold;
color: #666;
}
//
.statistics {
display: flex;
justify-content: space-between;
margin-top: 12px;
.box-card {
width: 24%;
.device {
font-size: 34px;
display: flex;
justify-content: center;
align-items: center;
height: 90px;
font-weight: bold;
color: rgb(66, 125, 169);
}
.water {
height: 90px;
display: flex;
justify-content: space-around;
align-items: center;
text-align: center;
.number {
font-size: 19px;
font-weight: bold;
color: rgb(66, 125, 169);
}
.water-name {
margin-top: 9px;
font-size: 16px;
font-weight: 500;
color: rgb(66, 125, 169);
}
}
}
}
//
.tabs {
margin-top: 10px;
width: 100%;
.tabs-box {
.useTypeBox {
width: 50%;
margin: 0 auto;
display: flex;
justify-content: space-around;
.useType {
cursor: pointer;
padding-bottom: 13px;
}
.color {
border-bottom: 2px solid blueviolet;
color: "blueviolet";
}
.nocolor {
border-bottom: 2px solid white;
}
}
}
.totaluse {
display: flex;
.left {
flex: 4;
}
.right {
flex: 2;
margin-top: 20px;
display: flex;
justify-content: space-around;
flex-wrap: wrap;
.show-box {
width: 46%;
height: 80px;
background: #427da9;
border-radius: 14px;
display: flex;
justify-content: center;
align-items: center;
.show {
width: 92%;
height: 70px;
background: #427da9;
border-radius: 14px;
border: 1px solid white;
color: white;
display: flex;
justify-content: center;
align-items: center;
.title {
font-size: 14px;
}
.content {
font-size: 18px;
text-align: center;
}
}
}
}
}
.rank {
width: 100%;
height: 300px;
margin: 0 auto;
.rank-box {
width: 90%;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.rankList {
display: flex;
width: 50%;
margin-top: 15px;
.left {
width: 13%;
height: 40px;
background: #427da9;
.index {
color: white;
text-align: center;
font-size: 16px;
line-height: 40px;
font-weight: bold;
}
}
.right {
width: 80%;
height: 40px;
background: #f2f2f2;
display: flex;
align-items: center;
justify-content: space-around;
color: #427da9;
font-weight: 700;
.phone {
width: 60%;
}
.num {
width: 20%;
}
}
}
}
}
}
</style>

683
src/views/wel/component/clientside.vue

@ -1,368 +1,409 @@
<template> <template>
<div> <basic-container>
<div class="infos"> <div class="container">
<el-card> <div class="top">
<div class="title"> <el-card class="Turnover">
<span class="icon el-icon-tickets"></span> <div slot="header" class="clearfix">
客户信息 <span>交易额</span>
</div>
<div class="content">
<div>
客户名称 <span>{{ form.tenantName }}</span>
</div>
<div>
联系人 <span>{{ form.linkman }}</span>
</div> </div>
<div> <div class="money">9999</div>
联系电话 <span>{{ form.contactNumber }}</span> <div class="timeChange">
</div> <div
</div> :class="timeIndex == index ? 'timebox' : 'timebox nocolor'"
</el-card> v-for="(item, index) in time"
<el-card> :key="index"
<div class="title"> @click="handleTime(index)"
<span class="icon el-icon-star-off"></span>
金额
</div>
<div class="content">
<div>
账户额度
<span>{{ printFn(form.balance / 10000) }} <span>()</span> </span>
</div>
<div>
授信余额
<span
>{{ printFn(form.creditBalance / 10000) }}<span>()</span></span
> >
{{ item }}
</div>
</div> </div>
<div> </el-card>
授信额度 <div class="message">
<span <div class="message-box">
>{{ printFn(form.creditAmount / 10000) }}<span>()</span></span <el-card class="card">
> <div slot="header" class="clearfix">
</div> <span>客服消息</span>
</div> </div>
</el-card> <div class="content">
<el-card> <div class="left">
<div class="title"> <i class="icon el-icon-service"></i>
<span class="icon el-icon-coin"></span> </div>
Open API <div class="right">
</div> <div class="num">99</div>
<div class="content"> <div class="status">+2.3% <span>同比昨日</span></div>
<div> </div>
AppID <span>{{ form.tenantId }}</span> </div>
</div> </el-card>
<div class="secret"> <el-card class="card">
AppSecret <div slot="header" class="clearfix">
<span> ****** </span> <span>待发货</span>
<a class="reset" @click="handAppSecret">查看</a> </div>
</div> <div class="content">
<div> <div class="left" style="background-color: #ff8b89">
生成时间 <span>{{ form.apiSecretTime }}</span> <i class="icon el-icon-truck"></i>
</div>
<div class="right">
<div class="num">99</div>
<div class="status">+2.3% <span>同比昨日</span></div>
</div>
</div>
</el-card>
<el-card class="card">
<div slot="header" class="clearfix">
<span>历史订单</span>
</div>
<div class="content">
<div class="left" style="background-color: #42d6bd">
<i class="icon el-icon-truck"></i>
</div>
<div class="right">
<div class="num">99</div>
<div class="status">+2.3% <span>同比昨日</span></div>
</div>
</div>
</el-card>
</div> </div>
</div> <div class="order">
</el-card> <el-card class="ordercards">
<el-card> <div class="left">
<div class="title"> <div class="title">动态订单</div>
<span class="icon el-icon-user"></span> <div class="lines"></div>
白名单 <vue-seamless-scroll
</div> :data="listData"
<div class="content"> :class-option="optionHover"
<div style="display:flex"> class="orderShow"
<div> IP </div> >
<div style=" word-wrap:break-word; word-break:break-all;margin-left: 10px;">{{ form.ipWhiteLists }}</div> <div
class="content"
v-for="(item, index) in listData"
:key="index"
>
{{ item.content }}
</div>
</vue-seamless-scroll>
</div>
</el-card>
</div> </div>
</div> </div>
</el-card> </div>
</div> <div class="bottom">
<el-card class="data">
<!-- 显示密钥 --> <div id="dataChars"></div>
<el-dialog </el-card>
title="客户密钥" <el-card class="sales">
:visible.sync="secret" <div class="title">商品销量</div>
width="30%" <div>
:before-close="closeSecret" <el-table :data="tableData" stripe style="width: 100%">
append-to-body <el-table-column prop="date" label="排名"> </el-table-column>
> <el-table-column prop="name" label="商品名称"> </el-table-column>
<div class="descriptions"> <el-table-column
<div prop="address"
class="item-body" label="销量"
:style="{ width: width ? width : '100%' }" sortable
:key="label" align="right"
v-for="{ label, value, width, render } in seArr"
>
<div class="label">{{ label }}</div>
<div class="value">
<div ref="code">{{ value }}</div>
<div style="padding-left: 15px">
<el-button
class="tag-read"
type="text"
:data-clipboard-text="value"
@click="copy"
>复制</el-button
> >
</div> </el-table-column>
<Render v-if="render" :render="render" /> </el-table>
</div> </div>
</div> </el-card>
</div> </div>
<span slot="footer" class="dialog-footer"> </div>
<el-button type="primary" @click="secret = false"> </el-button> </basic-container>
</span>
</el-dialog>
</div>
</template> </template>
<script> <script>
import { mapGetters } from "vuex"; import * as echarts from "echarts";
import { getdetail } from "@/api/dashboard/index.js";
import Render from "@/components/Render/index.vue";
import Clipboard from "clipboard";
import * as math from "mathjs";
export default { export default {
components: {
Render,
},
data() { data() {
return { return {
form: { time: ["本月", "本日"],
tenantName: "", timeIndex: 0,
createTime: "", listData: [
creditBalance: 0, {
creditAmount: 0, content:
apiSecretTime: "", "2022-06-01 16:01:01用户123343434提交了一份19.9G流量套餐的商品购买",
balance: "", },
tenantId: "", {
apiSecret: "", content:
linkman: "", "2022-06-01 16:01:01用户123343434提交了一份19.9G流量套餐的商品购买",
contactNumber: "", },
ipWhiteLists: "",
},
secret: false, //
};
},
computed: {
...mapGetters(["userInfo"]),
//
seArr() {
return [
{ {
label: "App ID", content:
value: this.form.tenantId, "2022-06-01 16:01:01用户123343434提交了一份19.9G流量套餐的商品购买",
}, },
{ {
label: "AppSecret", content:
value: this.form.apiSecret, "2022-06-01 16:01:01用户123343434提交了一份19.9G流量套餐的商品购买",
}, },
]; {
content:
"2022-06-01 16:01:01用户123343434提交了一份19.9G流量套餐的商品购买",
},
{
content:
"2022-06-01 16:01:01用户123343434提交了一份19.9G流量套餐的商品购买",
},
],
tableData: [
{
date: "2016-05-02",
name: "王小虎",
address: 11,
},
{
date: "2016-05-04",
name: "王小虎",
address: 23,
},
{
date: "2016-05-01",
name: "王小虎",
address: 134,
},
{
date: "2016-05-03",
name: "王小虎",
address: 44,
},
],
};
},
computed: {
optionHover() {
return {
step: 0.5, //
limitMoveNum: 1, // this.dataList.length
hoverStop: true, // stop
direction: 1, // 0 1 2 3
openWatch: true, // dom
singleHeight: 0, // (0) direction => 0/1
singleWidth: 0, // (0) direction => 2/3
waitTime: 1000, // (1000ms)
};
}, },
}, },
created() { mounted() {
this.detail(this.userInfo.tenant_id); this.dataEchars();
}, },
methods: { methods: {
// dataEchars() {
detail(id) { var chartDom = document.getElementById("dataChars");
getdetail(id).then((res) => { var myChart = echarts.init(chartDom);
if (res.data.code == 200) { var option;
this.form = res.data.data; option = {
} title: {
}); text: "实时数据",
}, },
// tooltip: {
handAppSecret() { trigger: "axis",
this.secret = true; axisPointer: {
}, type: "cross",
// label: {
copy() { backgroundColor: "#6a7985",
var clipboard = new Clipboard(".tag-read"); },
clipboard.on("success", (e) => { },
this.$message.success("复制成功"); },
clipboard.destroy(); legend: {
}); data: ["套餐销售数量", "机器销售数量"],
clipboard.on("error", (e) => { },
// toolbox: {
console.log("该浏览器不支持自动复制"); feature: {
// a6e49f3ead9daa1f1a09e9d9ddb79b31 saveAsImage: {},
clipboard.destroy(); },
}); },
grid: {
left: "3%",
right: "4%",
bottom: "3%",
containLabel: true,
},
xAxis: [
{
type: "category",
boundaryGap: false,
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
},
],
yAxis: [
{
type: "value",
},
],
series: [
{
name: "套餐销售数量",
type: "line",
stack: "Total",
areaStyle: {},
emphasis: {
focus: "series",
},
data: [120, 132, 101, 134, 90, 230, 210],
},
{
name: "机器销售数量",
type: "line",
stack: "Total",
areaStyle: {},
emphasis: {
focus: "series",
},
data: [220, 182, 191, 234, 290, 330, 310],
},
],
};
option && myChart.setOption(option);
}, },
printFn(value) { handleTime(index) {
const precision = 14; this.timeIndex = index;
return Number(math.format(value, precision));
}, },
}, },
}; };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.infos { .container {
width: 100%; .clearfix {
display: flex; font-size: 17px;
flex-wrap: wrap; font-weight: bold;
.el-card { color: #333;
width: 30%; }
.top {
display: flex; display: flex;
margin-left: 2%; height: 230px;
margin-top: 15px; justify-content: space-between;
.content { .Turnover {
color: #555555; width: 20%;
font-size: 14px; height: 100%;
line-height: 3;
span {
margin-left: 10px;
}
.reset {
cursor: pointer;
margin: 0 20px;
color: blueviolet;
}
.ki-bar:first-child { .money {
margin-top: 20px; color: #427da9;
} font-size: 32px;
.ki-bar {
margin-top: 30px; margin-top: 30px;
text-align: center;
font-weight: bolder;
} }
.timeChange {
.secret { margin-top: 40px;
display: flex; display: flex;
align-items: center;
span { justify-content: center;
width: 0; font-size: 14px;
flex: 1; margin-top: 50px;
overflow: hidden; .timebox {
white-space: nowrap; text-align: center;
text-overflow: ellipsis; line-height: 25px;
background: #025fa7;
width: 60px;
height: 25px;
border-radius: 20px;
color: white;
}
.nocolor {
background: white;
color: #333;
} }
} }
} }
} .message {
} width: 78%;
height: 100%;
.title { .message-box {
color: #000c17; width: 100%;
font-weight: bold; height: 50%;
display: flex; display: flex;
align-items: center; justify-content: space-between;
padding-bottom: 20px; .card {
.icon { height: 100%;
margin-right: 10px; width: 32%;
} .content {
} display: flex;
.hide { align-items: center;
visibility: hidden; .left {
} width: 40px;
.bar-title { height: 40px;
color: #555555; background: #449add;
font-size: 14px; border-radius: 7px;
display: flex; text-align: center;
align-items: baseline; line-height: 40px;
.icon {
.label { font-size: 23px;
font-size: 16px; color: white;
font-weight: bold; }
margin-right: 20px; }
} .right {
margin-left: 20px;
span { .num {
font-size: 14px; font-size: 22px;
font-weight: normal; font-weight: bold;
} color: #427da9;
} }
.status {
.tips { font-size: 16px;
color: #cccccc; }
margin-left: 10px; }
} }
}
.el-date-editor { }
margin-left: auto; .order {
} margin-top: 1%;
width: 100%;
.device { height: 46%;
margin-top: 20px;
display: flex;
.el-card:first-child {
flex: 1;
margin-right: 20px;
}
.el-card:last-child {
flex: 2;
padding-right: 20px;
}
.ki-bar,
.line-chart {
margin-top: 25px;
}
.not-active {
margin-top: 30px;
span { .ordercards {
font-size: 14px; height: 100%;
margin-left: 10px; width: 100%;
overflow: hidden;
.left {
display: flex;
height: 50%;
.title {
width: 45px;
height: 45px;
font-size: 19px;
color: #333;
font-weight: bold;
text-align: center;
}
.lines {
width: 2px;
height: 60px;
background: #025fa7;
margin-left: 40px;
}
.orderShow {
margin-left: 40px;
.content {
font-size: 14px;
padding-bottom: 20px;
color: #333;
}
}
}
}
}
} }
} }
} .bottom {
margin-top: 20px;
.message {
margin-top: 20px;
display: flex;
.title {
margin-bottom: 30px;
}
.el-card {
flex: 1;
}
.el-card:first-child {
margin-right: 20px;
}
.month {
font-size: 14px;
margin-top: 15px;
}
}
.descriptions {
display: flex;
flex-wrap: wrap;
border-left: 1px solid #ecedee;
border-top: 1px solid #ecedee;
.item-body {
display: flex; display: flex;
flex-wrap: wrap; height: 420px;
.label { justify-content: space-between;
color: #73777a; .data {
width: 80px; width: 68%;
background-color: #fbfbfc; #dataChars {
display: flex; width: 100%;
align-items: center; height: 400px;
} }
.value {
color: #373d41;
width: 0;
flex: 1;
display: flex;
align-items: center;
} }
.label, .sales {
.value { width: 30%;
font-size: 12px; .title {
padding: 8px; color: #333;
display: flex; font-weight: bold;
align-items: center; font-size: 17px;
border-right: 1px solid #ecedee; }
border-bottom: 1px solid #ecedee;
} }
} }
} }

14
src/views/wel/index.vue

@ -1,27 +1,29 @@
<template> <template>
<!-- <div class="app-container"> -->
<!-- <Clinent v-if="userInfo.tenant_id != '000000'" /> -->
<!-- <Administrator v-else /> -->
<!-- <Clinent></Clinent> -->
<!-- </div> -->
<div class="app-container"> <div class="app-container">
<Buser v-if="userInfo.tenant_id != '000000'" />
<Administrator v-else />
<!-- <Buser v-else /> -->
</div>
<!-- <div class="app-container">
<div class="dashboard-container"> <div class="dashboard-container">
<div class="dashboard-text">欢迎访问物联网管理后台</div> <div class="dashboard-text">欢迎访问物联网管理后台</div>
<div> <div>
<img src="@/assets/shouye.png" alt class="dashboard-img" /> <img src="@/assets/shouye.png" alt class="dashboard-img" />
</div> </div>
</div> </div>
</div> </div> -->
</template> </template>
<script> <script>
import { mapGetters } from "vuex"; import { mapGetters } from "vuex";
import Clinent from "./component/clientside.vue"; import Clinent from "./component/clientside.vue";
import Administrator from "./component/Administrator.vue"; import Administrator from "./component/Administrator.vue";
import Buser from "./component/Buser.vue";
export default { export default {
components: { components: {
Clinent, Clinent,
Administrator, Administrator,
Buser,
}, },
data() { data() {
return {}; return {};

Loading…
Cancel
Save