Merge remote-tracking branch 'origin/master'

This commit is contained in:
SjS 2025-04-29 10:46:25 +08:00
commit edd975c6b3
28 changed files with 626 additions and 171 deletions

View File

@ -43,6 +43,7 @@
"clipboard": "2.0.8",
"core-js": "3.37.1",
"decimal.js": "^10.4.3",
"driver.js": "^1.3.5",
"echarts": "5.4.0",
"element-ui": "2.15.14",
"file-saver": "2.0.5",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -152,3 +152,12 @@ export function deptTreeSelect() {
method: 'get'
})
}
// 已读导览
export function readGuide(key) {
return request({
url: '/system/user/guide',
method: 'put',
params: { key }
})
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 63 KiB

View File

@ -72,13 +72,16 @@ export default {
align-items: center;
justify-content: center;
border-radius: 50%;
overflow: hidden;
vertical-align: middle;
::v-deep .el-avatar {
display: flex;
display: inline-flex;
align-items: center;
justify-content: center;
background-color: inherit;
font-size: 16px;
vertical-align: middle;
}
}
</style>

View File

@ -0,0 +1,32 @@
<template>
<base-link :id="id" :text="text" :size="size" @click="handleClick" :permissions="['bst:area:query']"/>
</template>
<script>
import BaseLink from '@/components/BaseLink/index.vue';
export default {
name: 'AreaLink',
components: {BaseLink},
props: {
id: {
type: String,
default: null
},
text: {
type: String,
default: null,
},
size: {
type: String,
default: "small"
}
},
methods: {
handleClick() {
if (this.id != null && this.checkPermi(['bst:area:query'])) {
this.$router.push(`/view/area/${this.id}`);
}
}
}
}
</script>

View File

@ -121,6 +121,12 @@ export const constantRoutes = [
component: () => import('@/views/system/user/view/view.vue'),
name: 'UserView',
meta: { title: '用户详情' }
},
{
path: 'area/:id?',
component: () => import('@/views/bst/area/view/view.vue'),
name: 'AreaView',
meta: { title: '运营区详情' }
}
]
},

View File

@ -10,6 +10,7 @@ const getters = {
userId: state => state.user.id,
name: state => state.user.name,
nickName: state => state.user.nickName,
guides: state => state.user.guides,
introduction: state => state.user.introduction,
roles: state => state.user.roles,
permissions: state => state.user.permissions,

View File

@ -1,4 +1,5 @@
import { getInfo, login, logout } from '@/api/login';
import { readGuide } from '@/api/system/user';
import { getToken, removeToken, setToken } from '@/utils/auth';
// import { Watermark } from '@pansy/watermark';
@ -15,6 +16,7 @@ const user = {
permissions: [],
deptId: null,
userType: null,
guides: [],
},
mutations: {
@ -41,31 +43,12 @@ const user = {
},
SET_NICK_NAME: (state, nickName) => {
state.nickName = nickName;
// if (watermark) {
// watermark.destroy();
// }
// // 创建水印
// watermark = new Watermark({
// // 水印文案,支持多行
// text: nickName,
// // 水印文案样式
// font: {
// fontSize: 16,
// color: 'rgba(0, 0, 0)',
// fontFamily: 'sans-serif'
// },
// // 水印之间的间距
// gap: [300, 300],
// // 旋转角度
// rotate: -20,
// // 设置水印层级
// zIndex: 9999,
// opacity: 0.1,
// })
},
SET_USER_TYPE: (state, userType) => {
state.userType = userType;
},
SET_GUIDES: (state, guides) => {
state.guides = guides;
}
},
@ -105,6 +88,7 @@ const user = {
commit('SET_AVATAR', avatar)
commit('SET_DEPT_ID', user.deptId)
commit('SET_USER_TYPE', user.userType)
commit('SET_GUIDES', user.guides)
resolve(res)
}).catch(error => {
reject(error)
@ -134,6 +118,14 @@ const user = {
removeToken()
resolve()
})
},
// 添加导览
ADD_GUIDES({commit, state}, key) {
return new Promise((resolve, reject) => {
readGuide(key).then(() => {
commit('SET_GUIDES', [...state.guides, key])
});
});
}
}
}

161
src/utils/guide.js Normal file
View File

@ -0,0 +1,161 @@
/**
* 用户引导
*/
import store from "@/store";
import { driver } from "driver.js";
import "driver.js/dist/driver.css";
export function startGuide(guideKey) {
let guides = store.getters.guides;
if (guides == null || !guides.includes(guideKey)) {
let guide = guideSet[guideKey];
if (guide) {
guide.start();
}
}
}
const guideSet = {
MchIndex: {
start() {
const driverObj = driver({
showProgress: true,
animate: true,
nextBtnText: '下一步',
prevBtnText: '上一步',
doneBtnText: '完成',
closeBtnText: '关闭',
allowClose: false,
onDestroyed: () => {
// 导览完成后调用接口
store.dispatch("ADD_GUIDES", "MchIndex");
},
steps: [
{
popover: {
title: '欢迎使用小鹿骑行管理系统',
description: '接下来我们将带您了解系统的主要功能区域',
side: "center",
align: 'center'
}
},
{
element: '#mch-stat',
popover: {
title: '运营统计',
description: '这里显示您的运营数据统计信息,包括订单数量、金额等关键指标。',
side: "bottom",
align: 'start'
}
},
{
element: '#device-stat',
popover: {
title: '车辆统计',
description: '这里展示设备相关的统计信息,包括设备总数、在线状态等。',
side: "bottom",
align: 'start'
}
},
{
element: '#order-daily-stat',
popover: {
title: '每日流水统计',
description: '这里展示每日的订单流水统计图表,帮助您了解业务趋势。',
side: "left",
align: 'start'
}
},
{
element: '#balance-panel',
popover: {
title: '账户信息',
description: '这里显示您的账户余额、待分润金额等信息,方便您随时查看收益情况。',
side: "right",
align: 'start'
}
},
{
popover: {
title: '小程序管理',
description: `
<div>
<p>您还可以通过小鹿骑行小程序随时随地管理您的业务扫码即可体验</p>
<img src="https://api.ccttiot.com/gh_fe8a3740ae9a_1280-1745824336524.jpg" style="width: 100%; height: auto; margin: 10px auto;position:relative;" />
</div>
`,
side: "center",
align: 'center'
}
}
]
});
driverObj.drive();
}
},
AreaSub: {
start() {
const driverObj = driver({
showProgress: true,
animate: true,
nextBtnText: '下一步',
prevBtnText: '上一步',
doneBtnText: '完成',
closeBtnText: '关闭',
allowClose: false,
onDestroyed: () => {
store.dispatch("ADD_GUIDES", "AreaSub");
},
steps: [
{
popover: {
title: '子区域管理',
description: '欢迎使用子区域管理功能,这里您可以管理运营区下的子区域和电子围栏。',
side: "center",
align: 'center'
}
},
{
element: '.sub-area-list',
popover: {
title: '子区域列表',
description: '左侧显示当前运营区下的所有子区域列表,您可以在这里查看和管理子区域。',
side: "right",
align: 'start'
}
},
{
element: '.map-container',
popover: {
title: '地图操作区',
description: '右侧地图区域是您的主要操作区域,您可以在这里进行以下操作:管理子区域、修改电子围栏、查看区域详情。',
side: "left",
align: 'start'
}
},
{
element: '#add-sub',
popover: {
title: '新增子区域',
description: '点击按钮,即可开始在地图上绘制区域(停车区、禁行区、禁停区)',
side: "left",
align: 'start'
}
},
{
element: '#area-edit',
popover: {
title: '电子围栏操作',
description: '点击此处可以编辑电子围栏',
side: "left",
align: 'start'
}
}
]
});
driverObj.drive();
}
}
}

View File

@ -76,7 +76,11 @@
<dict-tag :options="dict.type.agreement_content_type" :value="row.contentType" size="mini" style="margin-left:4px"/>
</template>
</el-table-column>
<el-table-column label="运营区" align="center" prop="areaName"/>
<el-table-column label="运营区" align="center" prop="areaName">
<template slot-scope="d">
<area-link :id="d.row.areaId" :text="d.row.areaName"/>
</template>
</el-table-column>
<el-table-column label="简介" align="center" prop="brief"/>
<el-table-column label="创建时间" align="center" prop="createTime"/>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
@ -192,6 +196,7 @@ import Editor from "@/components/Editor/index.vue";
import AreaRemoteSelect from "@/components/Business/Area/AreaRemoteSelect.vue";
import UserLink from "@/components/Business/User/UserLink.vue";
import {isSysAdmin} from "@/utils/permission";
import AreaLink from '@/components/Business/Area/AreaLink.vue'
//
const defaultSort = {
@ -203,7 +208,13 @@ export default {
name: "Agreement",
mixins: [$showColumns],
dicts: ['agreement_type', 'agreement_content_type'],
components: {FormCol, Editor, AreaRemoteSelect, UserLink},
components: {FormCol, Editor, AreaRemoteSelect, UserLink, AreaLink},
props: {
query: {
type: Object,
default: () => ({})
},
},
data() {
return {
span: 24,
@ -326,6 +337,7 @@ export default {
},
},
created() {
Object.assign(this.queryParams, this.query);
this.getList();
},
methods: {

View File

@ -104,7 +104,7 @@
{{d.row[column.key]}}
</template>
<template v-else-if="column.key === 'name'">
{{d.row.name}}
<area-link :id="d.row.id" :text="d.row.name" />
<dict-tag :options="dict.type.area_status" :value="d.row.status" size="mini"/>
</template>
<template v-else-if="column.key === 'areaTimeStart'">
@ -131,6 +131,13 @@
</template>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="280">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-view"
@click="handleView(scope.row)"
v-has-permi="['bst:area:query']"
>详情</el-button>
<el-button
size="mini"
type="text"
@ -187,6 +194,7 @@ import { listArea, delArea } from "@/api/bst/area";
import { $showColumns } from '@/utils/mixins';
import AreaCustomerServiceDialog from "@/views/bst/area/components/AreaCustomerServiceDialog.vue";
import UserLink from '@/components/Business/User/UserLink.vue';
import AreaLink from '@/components/Business/Area/AreaLink.vue';
//
const defaultSort = {
prop: "createTime",
@ -199,7 +207,8 @@ export default {
dicts: ['area_status'],
components: {
AreaCustomerServiceDialog,
UserLink
UserLink,
AreaLink
},
props: {
query: {
@ -269,6 +278,9 @@ export default {
this.getList();
},
methods: {
handleView(row) {
this.$router.push({ path: `/view/area/${row.id}` });
},
handleCustomerService(row) {
this.row = row;
this.visibleCustomerService = true;

View File

@ -0,0 +1,103 @@
<template>
<div class="app-container" v-loading="loading" >
<el-card header="基础信息" class="card-box">
<el-descriptions :column="4">
<el-descriptions-item label="名称">
{{ detail.name }}
<dict-tag :options="dict.type.area_status" :value="detail.status" size="small" />
</el-descriptions-item>
<el-descriptions-item label="运营时间">
{{ detail.areaTimeStart | dv }} - {{ detail.areaTimeEnd | dv }}
</el-descriptions-item>
<el-descriptions-item label="运营商">
<user-link :id="detail.userId" :text="detail.userName" />
</el-descriptions-item>
<el-descriptions-item label="创建人">
<user-link :id="detail.createId" :text="detail.createName" />
</el-descriptions-item>
<el-descriptions-item label="创建时间">{{ detail.createTime | dv }}</el-descriptions-item>
<el-descriptions-item label="备注" :span="2">{{ detail.remark | dv }}</el-descriptions-item>
</el-descriptions>
</el-card>
<el-card v-if="detail.id" class="card-box">
<el-tabs>
<el-tab-pane label="电子围栏" lazy v-if="checkPermi(['bst:areaSub:list'])">
<area-sub :area-id="detail.id"/>
</el-tab-pane>
<el-tab-pane label="车辆列表" lazy v-if="checkPermi(['bst:device:list'])">
<device :query="{areaId: detail.id}" />
</el-tab-pane>
<el-tab-pane label="订单列表" lazy v-if="checkPermi(['bst:order:list'])">
<order :query="{areaId: detail.id}" />
</el-tab-pane>
<el-tab-pane label="加盟列表" lazy v-if="checkPermi(['bst:areaJoin:list'])">
<area-join :query="{areaId: detail.id, types: [AreaJoinType.JOIN, AreaJoinType.COOPERATE]}" />
</el-tab-pane>
<el-tab-pane label="运维列表" lazy v-if="checkPermi(['bst:areaJoin:list'])">
<area-join :query="{areaId: detail.id, types: [AreaJoinType.OPERATION]}" />
</el-tab-pane>
<el-tab-pane label="客服列表" lazy v-if="checkPermi(['bst:customerService:list'])">
<customer-service :query="{areaId: detail.id}"/>
</el-tab-pane>
<el-tab-pane label="公告协议" lazy v-if="checkPermi(['bst:agreement:list'])">
<agreement :query="{areaId: detail.id}"/>
</el-tab-pane>
<el-tab-pane label="操作日志" lazy v-if="checkPermi(['monitor:operlog:list'])">
<oper-log :query="{bizId: detail.id, bizType: LogBizType.AREA}" />
</el-tab-pane>
</el-tabs>
</el-card>
</div>
</template>
<script>
import { getArea } from '@/api/bst/area';
import UserLink from '@/components/Business/User/UserLink.vue';
import AreaSub from '@/views/bst/areaSub/index.vue';
import Device from '@/views/bst/device/index.vue';
import Order from '@/views/bst/order/index.vue';
import AreaJoin from '@/views/bst/areaJoin/index.vue';
import { AreaJoinType, LogBizType } from '@/utils/enums';
import CustomerService from '@/views/bst/customerService/index.vue';
import Agreement from '@/views/bst/agreement/index.vue';
import OperLog from '@/views/monitor/operlog/index.vue';
export default {
name: 'AreaView',
dicts: ['area_status'],
components: {
UserLink,
AreaSub,
Device,
Order,
AreaJoin,
CustomerService,
Agreement,
OperLog
},
data() {
return {
AreaJoinType,
LogBizType,
detail: {},
loading: false,
id: null,
}
},
created() {
this.id = this.$route.params.id;
this.getDetail();
},
methods: {
getDetail() {
this.loading = true;
getArea(this.id).then(res => {
this.detail = res.data;
}).finally(() => {
this.loading = false;
})
},
}
}
</script>

View File

@ -12,7 +12,7 @@
<el-select v-model="queryParams.type" placeholder="请选择类型" clearable @change="handleQuery">
<template v-for="dict in dict.type.area_join_type">
<el-option
v-if="types.includes(dict.value)"
v-if="queryParams.types.includes(dict.value)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
@ -109,6 +109,9 @@
<template v-else-if="column.key === 'createName'">
<user-link :id="d.row.createId" :text="d.row.createName" />
</template>
<template v-else-if="column.key === 'areaName'">
<area-link :id="d.row.areaId" :text="d.row.areaName" />
</template>
<template v-else>
{{d.row[column.key]}}
</template>
@ -149,7 +152,7 @@
:id="editId"
:init-data="initData"
@success="getList"
:types="types"
:types="queryParams.types"
/>
</div>
</template>
@ -160,7 +163,8 @@ import { $showColumns } from '@/utils/mixins';
import AreaJoinEditDialog from './components/AreaJoinEditDialog';
import UserLink from '@/components/Business/User/UserLink.vue';
import AreaRemoteSelect from '@/components/Business/Area/AreaRemoteSelect.vue';
import { isEmpty } from '@/utils';
import AreaLink from '@/components/Business/Area/AreaLink.vue';
//
const defaultSort = {
prop: "createTime",
@ -171,7 +175,13 @@ export default {
name: "AreaJoin",
mixins: [$showColumns],
dicts: ['area_join_type', 'area_join_permission'],
components: { AreaJoinEditDialog, UserLink, AreaRemoteSelect },
components: { AreaJoinEditDialog, UserLink, AreaRemoteSelect, AreaLink },
props: {
query: {
type: Object,
default: null
},
},
data() {
return {
//
@ -218,14 +228,18 @@ export default {
areaId: null,
userId: null,
remark: null,
createId: null
createId: null,
types: []
},
types: [], //
};
},
created() {
this.types = this.$route.query?.types?.split(',') || [];
if (!isEmpty(this.propTypes)) {
this.types = this.propTypes;
}
this.queryParams.types = this.types;
Object.assign(this.queryParams, this.query);
this.getList();
},
methods: {

View File

@ -9,8 +9,8 @@
<!-- 地图工具栏 -->
<div class="map-tools">
<el-button-group>
<el-button size="mini" type="primary" icon="el-icon-plus" @click="startBoundaryEdit(null)" v-if="enableEdit" :disabled="isEditing">子区域</el-button>
<el-button size="mini" type="warning" icon="el-icon-edit" @click="startAreaBoundaryEdit" v-if="enableEdit" :disabled="isEditing">电子围栏</el-button>
<el-button size="mini" id="add-sub" type="primary" icon="el-icon-plus" @click="startBoundaryEdit(null)" v-if="enableEdit" :disabled="isEditing">子区域</el-button>
<el-button size="mini" id="area-edit" type="warning" icon="el-icon-edit" @click="startAreaBoundaryEdit" v-if="enableEdit" :disabled="isEditing">电子围栏</el-button>
<el-button size="mini" icon="el-icon-full-screen" @click="setFitView">全局查看</el-button>
<el-button size="mini" icon="el-icon-picture" @click="toggleMapStyle">切换样式</el-button>
<el-button size="mini" icon="el-icon-document" @click="toggleLabels">{{ showLabels ? '隐藏' : '显示' }}标签</el-button>
@ -300,7 +300,6 @@ export default {
position: absolute;
top: 15px;
right: 15px;
z-index: 100;
}
.boundary-tools {

View File

@ -186,6 +186,7 @@ import { getArea, updateArea } from '@/api/bst/area';
import { AreaSubStatus, AreaSubType } from '@/utils/enums';
import AreaMap from '@/views/bst/areaSub/components/AreaMap.vue';
import AreaSubEditDialog from '@/views/bst/areaSub/components/AreaSubEditDialog.vue';
import {startGuide} from "@/utils/guide"
//
const defaultSort = {
@ -198,6 +199,12 @@ export default {
mixins: [$showColumns],
dicts: ['area_sub_type', 'area_sub_status'],
components: {FormCol, AreaMap, AreaSubEditDialog},
props: {
areaId: {
type: String,
default: null
}
},
data() {
return {
AreaSubStatus,
@ -271,9 +278,17 @@ export default {
};
},
created() {
this.queryParams.areaId = this.$route.params.areaId;
if (this.areaId) {
this.queryParams.areaId = this.areaId;
} else {
this.queryParams.areaId = this.$route.params.areaId;
}
this.getArea();
this.getList();
this.$nextTick(()=> {
startGuide("AreaSub");
});
},
methods: {
handleRowClick(row) {

View File

@ -88,6 +88,9 @@
<template v-if="column.key === 'id'">
{{d.row[column.key]}}
</template>
<template v-else-if="column.key === 'areaName'">
<area-link :id="d.row.areaId" :text="d.row.areaName"/>
</template>
<template v-else-if="column.key==='isEnabled'">
<dict-tag
:options="dict.type.customer_service_status"
@ -147,6 +150,7 @@ import { $showColumns } from '@/utils/mixins';
import FormCol from "@/components/FormCol/index.vue";
import CustomerServiceEditDialog from "@/views/bst/customerService/components/CustomerServiceEditDialog.vue";
import AreaRemoteSelect from "@/components/Business/Area/AreaRemoteSelect.vue";
import AreaLink from "@/components/Business/Area/AreaLink.vue";
//
const defaultSort = {
@ -157,7 +161,7 @@ const defaultSort = {
export default {
name: "CustomerService",
mixins: [$showColumns],
components: {AreaRemoteSelect, CustomerServiceEditDialog, FormCol},
components: {AreaRemoteSelect, CustomerServiceEditDialog, FormCol, AreaLink},
dicts:['customer_service_status'],
props: {
query: {
@ -178,7 +182,7 @@ export default {
span: 24,
//
columns: [
{key: 'id', visible: true, label: 'ID', minWidth: null, sortable: true, overflow: false, align: 'center', width: "80"},
{key: 'id', visible: false, label: 'ID', minWidth: null, sortable: true, overflow: false, align: 'center', width: "80"},
{key: 'areaName', visible: true, label: '运营区', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'name', visible: true, label: '姓名', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'contact', visible: true, label: '联系方式', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},

View File

@ -226,7 +226,8 @@
<template v-else-if="column.key === 'mchName'">
<i class="el-icon-office-building"/>
<user-link :id="d.row.mchId" :text="d.row.mchName" size="mini"/><br/>
<i class="el-icon-location"/>{{d.row.areaName | dv}}
<i class="el-icon-location"/>
<area-link :id="d.row.areaId" :text="d.row.areaName" size="mini"/>
</template>
<template v-else-if="column.key === 'lockStatus'">
<el-tooltip content="开锁:共享模块有开锁的信号输出;电门开:车子处于开锁可骑行状态" placement="top">
@ -244,9 +245,9 @@
{{d.row.remainEndurance | dv}} KM
</template>
<template v-else-if="column.key === 'vehicleNum'">
<i class="el-icon-bicycle"/>
{{d.row.vehicleNum | dv}}<br/>
<i class="el-icon-tickets"/>
{{d.row.vehicleNum | dv}}<br/>
<i class="el-icon-bicycle"/>
{{d.row.modelName | dv}}
</template>
<template v-else-if="column.key === 'music'">
@ -412,6 +413,7 @@ import DeviceSn from '@/views/bst/device/components/DeviceSn.vue';
import UserLink from '@/components/Business/User/UserLink.vue';
import DeviceLink from '@/components/Business/Device/DeviceLink.vue';
import AreaRemoteSelect from '@/components/Business/Area/AreaRemoteSelect.vue';
import AreaLink from '@/components/Business/Area/AreaLink.vue';
//
const defaultSort = {
@ -423,7 +425,7 @@ export default {
name: "Device",
mixins: [$showColumns, $device],
dicts: ['device_status', 'device_lock_status', 'device_iot_status', 'device_online_status', 'device_quality', 'device_music'],
components: {FormCol, DeviceEditDialog, BooleanTag, DeviceTransferDialog, DeviceSn, UserLink, DeviceLink, AreaRemoteSelect},
components: {FormCol, DeviceEditDialog, BooleanTag, DeviceTransferDialog, DeviceSn, UserLink, DeviceLink, AreaRemoteSelect, AreaLink},
props: {
query: {
type: Object,

View File

@ -18,14 +18,14 @@
</el-row>
<!-- 统计信息 -->
<mch-stat :stat="stat" :today-stat="todayStat" :mine-stat="mineStat" :today-mine-stat="todayMineStat" />
<mch-stat id="mch-stat" :stat="stat" :today-stat="todayStat"/>
<!-- 设备统计信息 -->
<device-stat :stat="stat"/>
<device-stat id="device-stat" :stat="stat"/>
<el-row :gutter="gutter" style="margin-top:12px">
<el-col :sm="24" :md="16">
<el-card header="每日流水统计" shadow="never">
<el-card header="每日流水统计" shadow="never" id="order-daily-stat">
<order-daily-stat ref="dailyStat" :query="areaQuery"/>
</el-card>
</el-col>
@ -39,7 +39,7 @@
<i class="el-icon-user"></i>
我的
</div>
<balance-panel v-if="userInfo" :balance="userInfo.balance" :waitBonus="userStat.bonus.waitDivideAmount" :totalWithdraw="userStat.withdraw.successAmount"/>
<balance-panel v-if="userInfo" id="balance-panel" :balance="userInfo.balance" :waitBonus="userStat.bonus.waitDivideAmount" :totalWithdraw="userStat.withdraw.successAmount"/>
<!-- 待办事项 -->
<todo-list :stat="stat"/>
@ -64,6 +64,7 @@ import { listSimpleArea } from '@/api/bst/area'
import BalancePanel from '@/views/bst/index/components/BalancePanel'
import OrderStat from '@/views/bst/index/components/OrderStat'
import { mapGetters } from 'vuex'
import {startGuide} from '@/utils/guide'
export default {
name: 'Index',
@ -99,6 +100,9 @@ export default {
created() {
this.getUserInfo();
this.getAreaList();
this.$nextTick(()=> {
startGuide("MchIndex");
});
},
methods: {
getAreaList() {

View File

@ -59,10 +59,10 @@ export default {
},
// 退
canRefundAmount() {
let payAmount = this.detail.payAmount || 0;
let payedAmount = this.detail.payedAmount || 0;
let payRefunded = this.detail.payRefunded || 0;
let payRefunding = this.detail.payRefunding || 0;
return payAmount - payRefunded - payRefunding;
return payedAmount - payRefunded - payRefunding;
}
},
methods: {

View File

@ -67,8 +67,8 @@
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable @change="handleQuery">
<el-form-item label="状态" prop="statusList">
<el-select v-model="queryParams.statusList" placeholder="请选择状态" clearable @change="handleQuery" multiple>
<el-option
v-for="dict in dict.type.order_status"
:key="dict.value"
@ -148,7 +148,7 @@
</template>
<template v-else-if="column.key === 'suitName'">
{{d.row.suitName | dv}}<br/>
<dictd-tag :options="dict.type.suit_type" :value="d.row.suitType" size="mini"/>
<dict-tag :options="dict.type.suit_type" :value="d.row.suitType" size="mini"/>
<dict-tag :options="dict.type.order_status" :value="d.row.status" size="mini" style="margin-left: 4px;"/>
<dict-tag :options="dict.type.suit_riding_rule" :value="d.row.suitRidingRule" size="mini" style="margin-left: 4px;"/>
</template>
@ -162,13 +162,24 @@
<template v-else-if="column.key === 'totalFee'">
<div>
<el-row :gutter="8">
<el-col :span="12" v-if="d.row.payedAmount" style="color: green;font-weight: bold;">实收{{d.row.payedAmount - d.row.payRefunded - d.row.payRefunding | fix2 | dv}} </el-col>
<el-col :span="12" v-if="d.row.depositFee != null">预存{{d.row.depositFee | fix2 | dv}} </el-col>
<el-col :span="12" v-if="d.row.totalFee != null">结算{{d.row.totalFee | fix2 | dv}} </el-col>
<el-col :span="12" v-if="d.row.ridingFee != null">骑行{{d.row.ridingFee | fix2 | dv}} </el-col>
<el-col :span="12" v-if="d.row.dispatchFee">调度{{d.row.dispatchFee | fix2 | dv}} </el-col>
<el-col :span="12" v-if="d.row.manageFee">管理{{d.row.manageFee | fix2 | dv}} </el-col>
<el-col :span="12" v-if="d.row.deductionFee">车损{{d.row.deductionFee | fix2 | dv}} </el-col>
<el-col :span="12" v-if="d.row.depositFee != null">预存{{d.row.depositFee | fix2 | dv}} </el-col>
<el-col :span="12" v-if="d.row.totalFee != null">
<el-popover
placement="bottom"
width="200"
trigger="hover"
>
<div>
<div>骑行费{{d.row.ridingFee | fix2 | dv}} </div>
<div>调度费{{d.row.dispatchFee | fix2 | dv}} </div>
<div>管理费{{d.row.manageFee | fix2 | dv}} </div>
<div>车损费{{d.row.deductionFee | fix2 | dv}} </div>
</div>
<div slot="reference">结算{{d.row.totalFee | fix2 | dv}} <i class="el-icon-info" /></div>
</el-popover>
</el-col>
<el-col :span="12" v-if="d.row.payedAmount" style="color: green;font-weight: bold;">实收{{d.row.payedAmount - d.row.payRefunded - d.row.payRefunding | fix2 | dv}} </el-col>
<el-col :span="24" v-if="d.row.payRefunded || d.row.payRefunding" style="color: red;">
退款{{d.row.payRefunded | fix2 | dv}}
<template v-if="d.row.payRefunding">(退款中{{d.row.payRefunding | fix2 | dv}} )</template>
@ -212,7 +223,8 @@
<user-link :id="d.row.userId" :text="d.row.userPhone" size="mini"/>
</div>
<div v-if="d.row.areaName != null">
<i class="el-icon-location"/>{{d.row.areaName | dv}}
<i class="el-icon-location"/>
<area-link :id="d.row.areaId" :text="d.row.areaName" size="mini"/>
</div>
</template>
<template v-else>
@ -283,6 +295,7 @@ import { toDescriptionFromSecond } from '@/utils/date';
import UserLink from '@/components/Business/User/UserLink.vue';
import DeviceLink from '@/components/Business/Device/DeviceLink.vue'
import OrderLink from '@/components/Business/Order/OrderLink.vue'
import AreaLink from '@/components/Business/Area/AreaLink.vue';
//
const defaultSort = {
@ -294,7 +307,7 @@ export default {
name: "Order",
mixins: [$showColumns],
dicts: ['order_status', 'suit_type', 'order_return_type', 'order_return_mode', 'suit_rental_unit', 'suit_riding_rule'],
components: {FormCol, OrderRefundDialog, OrderVerifyDialog, UserLink, DeviceLink, OrderLink},
components: {FormCol, OrderRefundDialog, OrderVerifyDialog, UserLink, DeviceLink, OrderLink, AreaLink},
props: {
query: {
type: Object,
@ -346,6 +359,7 @@ export default {
pageSize: 20,
orderByColumn: defaultSort.prop,
isAsc: defaultSort.order,
statusList: OrderStatus.valid(),
id: null,
no: null,
type: null,

View File

@ -2,6 +2,95 @@
<div class="app-container" v-loading="loading">
<el-row :gutter="10">
<el-col :span="18">
<el-card class="mb10">
<el-row :gutter="20" type="flex">
<el-col>
<el-statistic title="骑行费" :value="detail.ridingFee" :precision="2" suffix="元">
<template slot="prefix">
<i class="el-icon-bicycle" style="color: #409EFF"></i>
</template>
</el-statistic>
</el-col>
<el-col>
<el-statistic title="预存" :value="detail.depositFee" :precision="2" suffix="元">
<template slot="prefix">
<i class="el-icon-money" style="color: #67C23A"></i>
</template>
</el-statistic>
</el-col>
<el-col>
<el-popover placement="bottom" width="200" trigger="hover">
<div>
<div>骑行费{{detail.ridingFee | fix2 | dv}} </div>
<div>调度费{{detail.dispatchFee | fix2 | dv}} </div>
<div>管理费{{detail.manageFee | fix2 | dv}} </div>
<div>车损费{{detail.deductionFee | fix2 | dv}} </div>
</div>
<el-statistic slot="reference" :value="detail.totalFee" :precision="2" suffix="元">
<template slot="prefix">
<i class="el-icon-wallet" style="color: #E6A23C"></i>
</template>
<template slot="title">
结算金额
<i class="el-icon-info" style="color: #909399; margin-left: 4px; cursor: pointer"></i>
</template>
</el-statistic>
</el-popover>
</el-col>
<el-col>
<el-statistic
title="实收"
:value="detail.payedAmount - detail.payRefunded - detail.payRefunding"
:precision="2"
suffix="元"
value-style="color: #67C23A">
<template slot="prefix">
<i class="el-icon-success" style="color: #67C23A"></i>
</template>
</el-statistic>
</el-col>
<el-col>
<el-statistic
title="总退款"
:value="detail.payRefunded"
:precision="2"
suffix="元"
value-style="color: #F56C6C">
<template slot="prefix">
<i class="el-icon-refresh-left" style="color: #F56C6C"></i>
</template>
<template v-if="detail.payRefunding" slot="suffix">
<span style="color: #F56C6C; font-size: 12px">退款中{{ detail.payRefunding | fix2 | dv }} </span>
</template>
</el-statistic>
</el-col>
<el-col>
<el-statistic
title="自动退款"
:value="detail.payAutoRefund"
:precision="2"
suffix="元"
value-style="color: #F56C6C">
<template slot="prefix">
<i class="el-icon-timer" style="color: #F56C6C"></i>
</template>
</el-statistic>
</el-col>
<el-col>
<el-statistic
title="人工退款"
:value="detail.payAdminRefund"
:precision="2"
suffix="元"
value-style="color: #F56C6C">
<template slot="prefix">
<i class="el-icon-user" style="color: #F56C6C"></i>
</template>
</el-statistic>
</el-col>
</el-row>
</el-card>
<el-card>
<el-row class="mb10" type="flex" justify="end">
<el-button
@ -26,7 +115,7 @@
size="small"
plain
type="warning"
icon="el-icon-wallet"
icon="el-icon-s-check"
@click="handleVerify(detail)"
v-has-permi="['bst:order:verify']"
v-show="OrderStatus.canVerify().includes(detail.status)"
@ -34,15 +123,19 @@
</el-row>
<collapse-panel :value="true" title="基础信息">
<el-descriptions :column="4" >
<el-descriptions-item label="订单编号">{{ detail.no | dv}}</el-descriptions-item>
<el-descriptions-item label="订单编号">
{{ detail.no | dv}}
<el-link v-clipboard:copy="detail.no" v-clipboard:success="handleCopySuccess" type="primary" icon="el-icon-document"/>
</el-descriptions-item>
<el-descriptions-item label="订单状态">
<dict-tag :options="dict.type.order_status" :value="detail.status" size="small"/>
</el-descriptions-item>
<el-descriptions-item label="运营区">{{ detail.areaName | dv}}</el-descriptions-item>
<el-descriptions-item label="运营区">
<area-link :id="detail.areaId" :text="detail.areaName" />
</el-descriptions-item>
<el-descriptions-item label="创建时间">{{ detail.createTime | dv}}</el-descriptions-item>
<el-descriptions-item label="开始时间">{{ detail.startTime | dv}}</el-descriptions-item>
<el-descriptions-item label="结束时间">{{ detail.endTime | dv}}</el-descriptions-item>
<el-descriptions-item label="到期时间">{{ detail.maxTime | dv}}</el-descriptions-item>
<el-descriptions-item label="骑行时长">{{ orderDuration | dv}}</el-descriptions-item>
<el-descriptions-item label="骑行距离">{{ detail.distance / 1000 | fix2 | dv}} 公里</el-descriptions-item>
<el-descriptions-item label="结束原因" v-if="detail.endReason">{{ detail.endReason | dv }}</el-descriptions-item>
@ -50,27 +143,10 @@
</el-descriptions>
</collapse-panel>
<collapse-panel :value="true" title="费用信息">
<el-descriptions :column="4" >
<el-descriptions-item label="预存">{{ detail.depositFee | fix2 | dv }} </el-descriptions-item>
<el-descriptions-item label="结算金额" v-if="detail.totalFee != null">{{ detail.totalFee | fix2 | dv }} </el-descriptions-item>
<el-descriptions-item label="骑行费" v-if="detail.ridingFee != null">{{ detail.ridingFee | fix2 | dv }} </el-descriptions-item>
<el-descriptions-item label="调度费" v-if="detail.dispatchFee">{{ detail.dispatchFee | fix2 | dv }} </el-descriptions-item>
<el-descriptions-item label="管理费" v-if="detail.manageFee">{{ detail.manageFee | fix2 | dv }} </el-descriptions-item>
<el-descriptions-item label="车损费" v-if="detail.deductionFee">{{ detail.deductionFee | fix2 | dv }} </el-descriptions-item>
<el-descriptions-item label="退款">
{{ detail.payRefunded | fix2 | dv }}
<template v-if="detail.payRefunding">
<span style="color: red;">退款中{{ detail.payRefunding | fix2 | dv }} </span>
</template>
</el-descriptions-item>
<el-descriptions-item label="实收">{{ detail.payedAmount - detail.payRefunded - detail.payRefunding | fix2 | dv }} </el-descriptions-item>
</el-descriptions>
</collapse-panel>
<collapse-panel :value="true" title="套餐信息">
<el-descriptions :column="4" >
<el-descriptions-item label="套餐名称">
<el-descriptions-item label="套餐名称" :span="2">
{{ detail.suitName }}
<dict-tag :options="dict.type.suit_type" :value="detail.suitType" size="mini" style="margin-left: 4px;"/>
<dict-tag :options="dict.type.suit_riding_rule" :value="detail.suitRidingRule" size="mini" style="margin-left: 4px;"/>
@ -102,21 +178,6 @@
</el-descriptions-item>
</el-descriptions>
</collapse-panel>
<!-- <collapse-panel :value="true" title="归还信息">
<el-descriptions :column="4" >
<el-descriptions-item label="定位方式">
<dict-tag :options="dict.type.order_return_mode" :value="detail.returnMode" size="small"/>
</el-descriptions-item>
<el-descriptions-item label="归还类型">
<dict-tag :options="dict.type.order_return_type" :value="detail.returnType" size="small"/>
</el-descriptions-item>
<el-descriptions-item label="归还时间">{{ detail.endTime }}</el-descriptions-item>
<el-descriptions-item label="归还定位">{{ detail.returnLon | dv }}, {{ detail.returnLat | dv }}</el-descriptions-item>
<el-descriptions-item label="起始站点">{{ detail.startAreaSubName | dv }}</el-descriptions-item>
<el-descriptions-item label="归还站点">{{ detail.endAreaSubName | dv }}</el-descriptions-item>
</el-descriptions>
</collapse-panel> -->
</el-card>
</el-col>
<el-col :span="6">
@ -160,7 +221,7 @@
<el-card class="box-card" v-if="detail.id" style="margin-top: 10px;">
<el-tabs lazy>
<el-tab-pane label="车辆轨迹" v-if="checkPermi(['bst:locationLog:list'])">
<device-location :query="{orderId: detail.id, timeRange: [detail.startTime, detail.endTime == null ? detail.maxTime : detail.endTime]}" :area-id="detail.areaId" />
<device-location :query="{orderId: detail.id, timeRange: []}" :area-id="detail.areaId" />
</el-tab-pane>
<el-tab-pane label="收益信息" v-if="checkPermi(['bst:bonus:list'])">
<bonus :query="{bstId: detail.id, bstType: BonusBstType.ORDER}" />
@ -207,6 +268,7 @@ import CommandLog from '@/views/bst/commandLog/index.vue'
import DeviceLink from '@/components/Business/Device/DeviceLink.vue'
import UserLink from '@/components/Business/User/UserLink.vue'
import {getOrderDuration} from '@/views/bst/order/util'
import AreaLink from '@/components/Business/Area/AreaLink.vue'
export default {
name: 'OrderView',
@ -223,7 +285,8 @@ export default {
Operlog,
CommandLog,
DeviceLink,
UserLink
UserLink,
AreaLink
},
data() {
return {
@ -249,6 +312,9 @@ export default {
this.getDetail()
},
methods: {
handleCopySuccess() {
this.$message.success("复制成功");
},
toDescriptionFromSecond,
getDetail() {
this.loading = true
@ -284,4 +350,15 @@ export default {
},
}
}
</script>
</script>
<style scoped>
.red-text {
color: red;
}
.green-text {
color: green;
}
</style>

View File

@ -74,6 +74,7 @@
<template v-else-if="column.key === 'reason'">
<order-link v-if="PayBstType.ORDER === d.row.payBstType" :id="d.row.payBstId" :text="d.row.reason" />
<span v-else>{{d.row.reason | dv}}</span>
<dict-tag :options="dict.type.refund_type" :value="d.row.type" size="mini" style="margin-left: 4px;"/>
<dict-tag :options="dict.type.refund_status" :value="d.row.status" size="mini" style="margin-left: 4px;"/>
<dict-tag :options="dict.type.pay_bst_type" :value="d.row.payBstType" size="mini" style="margin-left: 4px;"/>
</template>
@ -119,7 +120,7 @@ const defaultSort = {
export default {
name: "Refund",
mixins: [$showColumns],
dicts: ['refund_status', 'pay_bst_type'],
dicts: ['refund_status', 'pay_bst_type', 'refund_type'],
components: {FormCol, UserLink, OrderLink},
props: {
query: {

View File

@ -172,8 +172,8 @@ export default {
.bg-box {
flex: 1;
background-image: url("../assets/images/login-background.png");
-webkit-background-image: url("../assets/images/login-background.png");
background-image: url("https://api.ccttiot.com/fd7f9ab7c2bb4ddd816282cc91079230dbfd985b1092f-I7XJ3y-1745887744159.jpg");
-webkit-background-image: url("https://api.ccttiot.com/fd7f9ab7c2bb4ddd816282cc91079230dbfd985b1092f-I7XJ3y-1745887744159.jpg");
background-size: cover;
-webkit-background-size: cover;
background-position: center;
@ -202,13 +202,18 @@ export default {
}
}
.login-form {
position: relative;
position: absolute;
background: #ffffff;
width: 480px;
padding: 200px 64px 5px;
width: 420px;
padding: 48px 48px 24px ;
top: 0;
right: 0;
height: calc(100vh - env(safe-area-inset-bottom));
left: 0;
bottom: 0;
margin: auto;
height: fit-content;
border-radius: 16px;
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.1);
.el-input {
height: 38px;
input {

View File

@ -116,7 +116,11 @@
</template>
</el-table-column>
<el-table-column label="请求地址" align="center" prop="operUrl" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']" />
<el-table-column label="操作人" align="center" prop="operName" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']" />
<el-table-column label="操作人" align="center" prop="operName" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']">
<template slot-scope="scope">
<user-link :id="scope.row.operUserId" :text="scope.row.operName" />
</template>
</el-table-column>
<el-table-column label="请求IP" align="center" prop="operIp" :show-overflow-tooltip="true" />
<el-table-column label="操作时间" align="center" prop="operTime" width="160" sortable="custom" :sort-orders="['descending', 'ascending']"/>
<el-table-column label="消耗时间" align="center" prop="costTime" width="110" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']">
@ -194,10 +198,14 @@
<script>
import { cleanOperlog, delOperlog, list } from '@/api/monitor/operlog'
import UserLink from '@/components/Business/User/UserLink'
export default {
name: "Operlog",
dicts: ['sys_oper_type', 'sys_common_status', 'log_biz_type'],
components: {
UserLink
},
props: {
query: {
type: Object,
@ -241,11 +249,7 @@ export default {
},
created() {
this.queryParams = {
...this.queryParams,
...this.query
}
Object.assign(this.queryParams, this.query)
this.getList();
},
methods: {

View File

@ -1,35 +0,0 @@
<template>
<el-link v-if="userType === UserType.ADMIN" type="primary" @click="handleClick" :disabled="id == null">{{name | defaultValue}}</el-link>
<span v-else >{{name | defaultValue}}</span>
</template>
<script>
import { mapGetters } from 'vuex'
import { UserType } from '@/utils/constants'
export default {
name: 'UserLink',
props: {
id: {
type: String,
default: null
},
name: {
type: String,
default: null,
}
},
computed: {
UserType() {
return UserType
},
...mapGetters(['userType'])
},
methods: {
handleClick() {
this.$emit('click');
this.$router.push({path: `/smUser/user/${this.id}`})
}
}
}
</script>

View File

@ -119,12 +119,6 @@
<template v-else-if="column.key === 'deptId'">
{{d.row.dept == null ? '' : d.row.dept.deptName}}
</template>
<template v-else-if="column.key === 'status'">
<dict-tag :value="d.row.status" :options="dict.type.user_status" size="small"/>
</template>
<template v-else-if="column.key === 'isReal'">
<boolean-tag :value="d.row.isReal" size="small"/>
</template>
<template v-else-if="column.key === 'point'">
{{ d.row.point | fix2 | dv }} %
</template>
@ -145,8 +139,13 @@
<el-tag :key="index" v-if="!isEmpty(role.roleName)" size="small" style="margin-right: 4px;">{{role.roleName}}</el-tag>
</template>
</template>
<template v-else-if="['nickName', 'userName', 'email'].includes(column.key)">
<user-link :id="d.row.userId" :text="d.row[column.key]" />
<template v-else-if="['nickName'].includes(column.key)">
<avatar :src="d.row.avatar" :size="24" :name="d.row.nickName" :char-index="-1" style="margin-right:4px"/>
<user-link :id="d.row.userId" :text="d.row.nickName" />
<dict-tag :options="dict.type.user_status" :value="d.row.status" size="mini" style="margin-left: 4px;"/>
<boolean-tag :value="d.row.isReal" size="mini" true-text="已实名" false-text="未实名" style="margin-left: 4px;"/>
<br/>
<user-link :id="d.row.userId" :text="d.row.userName" />
</template>
<template v-else-if="column.key === 'agentName'">
<user-link :id="d.row.agentId" :text="d.row.agentName" />
@ -239,6 +238,7 @@ import BooleanTag from '@/components/BooleanTag/index.vue'
import UserLink from '@/components/Business/User/UserLink.vue'
import RoleSelect from '@/components/Business/Role/RoleSelect.vue'
import UserShowPasswordDialog from '@/views/system/user/components/UserShowPasswordDialog.vue'
import Avatar from '@/components/Avatar/index.vue'
//
const defaultSort = {
@ -250,7 +250,7 @@ export default {
name: "User",
mixins: [$showColumns],
dicts: ['user_status', 'sys_user_sex', 'user_employ_status', 'withdraw_service_type'],
components: {UserFormDialog, FormCol, DeptSelect, BooleanTag, UserLink, RoleSelect, UserShowPasswordDialog},
components: {UserFormDialog, FormCol, DeptSelect, BooleanTag, UserLink, RoleSelect, UserShowPasswordDialog, Avatar},
data() {
return {
WithdrawServiceType,
@ -300,15 +300,14 @@ export default {
//
columns: [
{key: 'userId', visible: false, label: 'ID', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'nickName', visible: true, label: '姓名', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'userName', visible: true, label: '账号', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'nickName', visible: true, label: '姓名', minWidth: null, sortable: true, overflow: false, align: 'left', width: "250"},
{key: 'roles', visible: true, label: '角色', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'point', visible: true, label: '分成比例', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'withdrawServiceValue', visible: true, label: '提现服务费', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'bonusDelay', visible: true, label: '到账延迟', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'balance', visible: true, label: '余额', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'status', visible: true, label: '状态', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'isReal', visible: true, label: '实名状态', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
// {key: 'status', visible: true, label: '', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
// {key: 'isReal', visible: true, label: '', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'agentName', visible: true, label: '所属代理', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'deptName', visible: true, label: '归属部门', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'email', visible: false, label: '邮箱', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},

View File

@ -15,7 +15,6 @@
<line-field label="角色">
{{ detail.roles.map(role => role.roleName).join(',') }}
</line-field>
<line-field label="手机号" :value="detail.phonenumber" />
<line-field label="登录账号" :value="detail.userName" />
<line-field label="分成比例">
{{ detail.point | fix2 | dv }} %
@ -49,10 +48,10 @@
<el-card class="card-box" style="margin-top: 12px;" shadow="hover" v-if="detail.userId">
<el-tabs>
<el-tab-pane label="设备" lazy v-if="checkPermi(['bst:device:list'])">
<el-tab-pane label="车辆" lazy v-if="checkPermi(['bst:device:list'])">
<device :query="{mchId: detail.userId}" />
</el-tab-pane>
<el-tab-pane label="车" lazy v-if="checkPermi(['bst:model:list'])">
<el-tab-pane label="车型" lazy v-if="checkPermi(['bst:model:list'])">
<model :query="{userId: detail.userId}" />
</el-tab-pane>
<el-tab-pane label="套餐" lazy v-if="checkPermi(['bst:suit:list'])">
@ -61,30 +60,45 @@
<el-tab-pane label="运营区" lazy v-if="checkPermi(['bst:area:list'])">
<area-index :query="{userId: detail.userId}" />
</el-tab-pane>
<el-tab-pane label="消费订单" lazy v-if="checkPermi(['bst:order:list'])">
<order :query="{userId: detail.userId}" />
</el-tab-pane>
<el-tab-pane label="收入订单" lazy v-if="checkPermi(['bst:order:list'])">
<order :query="{bonusUserId: detail.userId}" />
</el-tab-pane>
<el-tab-pane label="车辆出租记录" lazy v-if="checkPermi(['bst:orderDevice:list'])">
<el-tab-pane label="出租记录" lazy v-if="checkPermi(['bst:orderDevice:list'])">
<order-device :query="{deviceMchId: detail.userId}" />
</el-tab-pane>
<el-tab-pane label="分成记录" lazy v-if="checkPermi(['bst:bonus:list'])">
<el-tab-pane label="分成" lazy v-if="checkPermi(['bst:bonus:list'])">
<bonus :query="{arrivalId: detail.userId, arrivalTypes: BonusArrivalType.userList()}" />
</el-tab-pane>
<el-tab-pane label="提现记录" lazy v-if="checkPermi(['bst:withdraw:list'])">
<el-tab-pane label="提现" lazy v-if="checkPermi(['bst:withdraw:list'])">
<withdraw :query="{userId: detail.userId}" />
</el-tab-pane>
<el-tab-pane label="账变记录" lazy v-if="checkPermi(['bst:balanceLog:list'])">
<el-tab-pane label="账变" lazy v-if="checkPermi(['bst:balanceLog:list'])">
<balance-log :query="{userId: detail.userId}" />
</el-tab-pane>
<el-tab-pane label="实名认证" lazy v-if="checkPermi(['bst:realName:list'])">
<el-tab-pane label="实名" lazy v-if="checkPermi(['bst:realName:list'])">
<real-name :query="{userId: detail.userId}" />
</el-tab-pane>
<el-tab-pane label="加盟区域" lazy v-if="checkPermi(['bst:areaJoin:list'])">
<area-join :query="{userId: detail.userId, types: [AreaJoinType.JOIN, AreaJoinType.COOPERATE]}" />
</el-tab-pane>
<el-tab-pane label="运维区域" lazy v-if="checkPermi(['bst:areaJoin:list'])">
<area-join :query="{userId: detail.userId, types: [AreaJoinType.OPERATION]}" />
</el-tab-pane>
<el-tab-pane label="收款账户" lazy v-if="checkPermi(['bst:account:list'])">
<account :query="{userId: detail.userId}" />
</el-tab-pane>
<el-tab-pane label="用户APP" lazy v-if="checkPermi(['bst:userApp:list'])">
<user-app :query="{userId: detail.userId}" />
</el-tab-pane>
<el-tab-pane label="操作日志" lazy v-if="checkPermi(['monitor:operlog:list'])">
<oper-log :query="{operUserId: detail.userId}" />
</el-tab-pane>
<el-tab-pane label="被操作日志" lazy v-if="checkPermi(['monitor:operlog:list'])">
<oper-log :query="{bizId: detail.userId, bizType: LogBizType.USER}" />
</el-tab-pane>
</el-tabs>
</el-card>
</div>
@ -99,7 +113,7 @@ import UserStatistics from '@/views/system/user/view/components/UserStatistics'
import CollapsePanel from '@/components/CollapsePanel'
import BooleanTag from '@/components/BooleanTag'
import Bonus from '@/views/bst/bonus/index.vue'
import { BonusArrivalType } from '@/utils/enums'
import { BonusArrivalType, AreaJoinType, LogBizType } from '@/utils/enums'
import OrderDailyStat from '@/views/bst/index/components/OrderDailyStat.vue'
import Device from '@/views/bst/device/index.vue'
import AreaIndex from '@/views/bst/area/index.vue'
@ -112,6 +126,8 @@ import Model from '@/views/bst/model/index.vue'
import OrderDevice from '@/views/bst/orderDevice/index.vue'
import Withdraw from '@/views/bst/withdraw/index.vue'
import RealName from '@/views/bst/realName/index.vue'
import AreaJoin from '@/views/bst/areaJoin/index.vue'
import OperLog from '@/views/monitor/operlog/index.vue'
export default {
name: 'UserView',
@ -133,11 +149,15 @@ export default {
Model,
OrderDevice,
Withdraw,
RealName
RealName,
AreaJoin,
OperLog
},
data() {
return {
BonusArrivalType,
AreaJoinType,
LogBizType,
detail: {
roles: []
},