更新优化

This commit is contained in:
磷叶 2025-04-24 17:29:53 +08:00
parent 7cdd8308f8
commit 39f03f8e3f
11 changed files with 242 additions and 72 deletions

View File

@ -11,7 +11,21 @@
v-on="$listeners"
:clearable="clearable"
:size="size"
/>
>
<template #option="scope">
<el-option
v-for="item in scope.options"
:key="item[prop]"
:value="item[prop]"
:label="item[showProp]"
>
<div style="display: flex; justify-content: space-between;">
<span>{{item[showProp] | dv}}</span>
<span style="color: #ccc">{{item.userName | dv}}</span>
</div>
</el-option>
</template>
</base-remote-select>
</template>
<script>

View File

@ -0,0 +1,56 @@
<template>
<el-select
v-model="selectedValue"
:multiple="multiple"
:clearable="clearable"
placeholder="请选择角色"
v-on="$listeners">
<el-option v-for="item in options" :key="item.roleId" :label="item.roleName" :value="item.roleId"></el-option>
</el-select>
</template>
<script>
import { listRole } from '@/api/system/role';
export default {
name: 'RoleSelect',
props: {
value: {
type: [String, Array],
default: null
},
multiple: {
type: Boolean,
default: false
},
clearable: {
type: Boolean,
default: true
}
},
data() {
return {
options: [],
}
},
computed: {
selectedValue: {
get() {
return this.value;
},
set(val) {
this.$emit('input', val);
}
}
},
created() {
this.getOptions();
},
methods: {
getOptions() {
listRole({pageNum: 1, pageSize: 9999}).then(res => {
this.options = res.rows;
});
}
}
}
</script>

View File

@ -1,12 +1,11 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="运营区" prop="areaName">
<el-input
v-model="queryParams.areaName"
placeholder="请输入运营区"
<el-form-item label="运营区" prop="areaId">
<area-remote-select
v-model="queryParams.areaId"
clearable
@keyup.enter.native="handleQuery"
@change="handleQuery"
/>
</el-form-item>
<el-form-item label="类型" prop="type">
@ -160,6 +159,7 @@ import { listAreaJoin, delAreaJoin } from "@/api/bst/areaJoin";
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';
//
const defaultSort = {
@ -171,7 +171,7 @@ export default {
name: "AreaJoin",
mixins: [$showColumns],
dicts: ['area_join_type', 'area_join_permission'],
components: { AreaJoinEditDialog, UserLink },
components: { AreaJoinEditDialog, UserLink, AreaRemoteSelect },
data() {
return {
//

View File

@ -20,12 +20,12 @@
<device-stat :stat="stat"/>
<el-row :gutter="gutter" style="margin-top:12px">
<el-col :sm="24" :md="18">
<el-col :sm="24" :md="16">
<el-card header="每日流水统计" shadow="never">
<order-daily-stat style="width:100%"/>
</el-card>
</el-col>
<el-col :sm="24" :md="6">
<el-col :sm="24" :md="8">
<order-stat :stat="stat"/>
</el-col>
</el-row>

View File

@ -7,7 +7,7 @@
<div class="title-1">
<i class="el-icon-s-data"></i>
运营统计
<el-select v-model="areaId" @change="onChangeArea" placeholder="请选择运营区" clearable>
<el-select v-model="areaId" @change="onChangeArea" placeholder="请选择运营区" clearable filterable>
<el-option v-for="item in areaList" :key="item.id" :label="item.name" :value="item.id"/>
</el-select>
</div>
@ -24,12 +24,12 @@
<device-stat :stat="stat"/>
<el-row :gutter="gutter" style="margin-top:12px">
<el-col :sm="24" :md="18">
<el-col :sm="24" :md="16">
<el-card header="每日流水统计" shadow="never">
<order-daily-stat ref="dailyStat" :query="areaQuery"/>
</el-card>
</el-col>
<el-col :sm="24" :md="6">
<el-col :sm="24" :md="8">
<order-stat :stat="stat"/>
</el-col>
</el-row>

View File

@ -9,10 +9,10 @@
</div>
<div class="item-info">
<div class="item-label">当前余额</div>
<div class="item-value">{{balance | fix2 | dv}}</div>
<div class="item-value">{{balance + waitBonus | fix2 | dv}}</div>
</div>
</div>
<div class="balance-item">
<!-- <div class="balance-item">
<div class="item-icon" style="background: linear-gradient(135deg, #f6ab4f, #ffbc58);">
<i class="el-icon-time"></i>
</div>
@ -20,11 +20,15 @@
<div class="item-label">未入账</div>
<div class="item-value">{{waitBonus | fix2 | dv}}</div>
</div>
</div>
</div> -->
</div>
<!-- 次要数据区域 -->
<div class="secondary-data">
<div class="withdraw-item">
<div class="item-label">可提现金额</div>
<div class="item-value">{{balance | fix2 | dv}}</div>
</div>
<div class="withdraw-item">
<div class="item-label">累计提现</div>
<div class="item-value">{{totalWithdraw | fix2 | dv}}</div>

View File

@ -30,6 +30,7 @@
end-color="#5C27FE"
sub-label="今日我的收入"
:sub-value="todayStat.bonus.amount - todayStat.bonusRefund.amount"
:precision="2"
/>
<statistics-card
class="stat-card"

View File

@ -1,26 +1,13 @@
<template>
<el-card class="box-card" shadow="never" header="订单概况">
<el-row :gutter="20">
<el-col :span="12" v-for="dict in dict.type.order_status" :key="dict.value">
<el-statistic
class="statistic"
group-separator=","
:value="stat.order.statusCount[dict.value] || 0"
:title="getOrderStatusLabel(dict.value)"
suffix="单"
>
<template #prefix>
<el-icon :class="icon(dict.value)" :style="{ color: color(dict.value) }" font-size="20px"/>
</template>
</el-statistic>
</el-col>
</el-row>
<div ref="chart" class="chart-container" :style="{height: height}"></div>
</el-card>
</template>
<script>
import { dictLabel } from '@/utils'
import { OrderStatus } from '@/utils/enums'
import * as echarts from 'echarts'
export default {
name: 'OrderStat',
@ -29,10 +16,15 @@ export default {
stat: {
type: Object,
required: true
},
height: {
type: String,
default: '300px'
}
},
data() {
return {
chart: null,
statusMap: {
[OrderStatus.WAIT_PAY]: {
icon: 'el-icon-wallet',
@ -62,33 +54,109 @@ export default {
icon: 'el-icon-money',
color: '#9270CA' // ,退
}
},
}
}
},
computed: {
icon() {
return (value) => {
return this.statusMap[value]?.icon
}
watch: {
stat: {
handler: 'initChart',
deep: true
},
color() {
return (value) => {
return this.statusMap[value]?.color
}
'dict.type.order_status': {
handler: 'initChart',
deep: true
}
},
mounted() {
this.initChart()
window.addEventListener('resize', this.resizeChart)
},
beforeDestroy() {
if (this.chart) {
this.chart.dispose()
this.chart = null
}
window.removeEventListener('resize', this.resizeChart)
},
methods: {
getOrderStatusLabel(value) {
return dictLabel(this.dict.type.order_status, value)
},
initChart() {
if (!this.dict.type.order_status || !this.stat.order?.statusCount) return
if (!this.chart) {
this.chart = echarts.init(this.$refs.chart)
}
const data = this.dict.type.order_status
.filter(item => item.value !== OrderStatus.CANCELED && item.value !== OrderStatus.WAIT_PAY)
.map(item => ({
value: this.stat.order.statusCount[item.value] || 0,
name: this.getOrderStatusLabel(item.value),
itemStyle: {
color: this.statusMap[item.value]?.color
}
}))
const option = {
tooltip: {
trigger: 'item',
formatter: '{b}: {c}单 ({d}%)'
},
legend: {
orient: 'horizontal',
bottom: 0,
left: 'center',
itemGap: 20,
padding: [0, 0, 10, 0]
},
grid: {
top: '5%',
bottom: '5%'
},
series: [
{
type: 'pie',
radius: ['25%', '45%'],
center: ['50%', '45%'],
avoidLabelOverlap: false,
label: {
show: true,
position: 'outside',
formatter: '{b}: {c}单',
padding: [0, -20, 15, -20]
},
emphasis: {
label: {
show: true,
fontSize: '16',
fontWeight: 'bold'
}
},
labelLine: {
show: true,
length: 12,
length2: 8
},
data: data
}
]
}
this.chart.setOption(option)
},
resizeChart() {
this.chart && this.chart.resize()
}
}
}
</script>
<style lang="scss" scoped>
.statistic {
margin-bottom: 20px;
.chart-container {
width: 100%;
padding: 10px;
}
</style>

View File

@ -432,7 +432,7 @@ export default {
const promise = this.form.id != null ? updateSuit(data) : addSuit(data);
promise.then(response => {
this.$modal.msgSuccess(this.form.id != null ? "修改成功" : "新增成功");
this.dialogVisible = false;
this.cancel();
this.$emit('success');
});
}

View File

@ -1,14 +1,6 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="运营商" prop="userName">
<el-input
v-model="queryParams.userName"
placeholder="请输入运营商名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="套餐名称" prop="name">
<el-input
v-model="queryParams.name"
@ -17,6 +9,34 @@
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="类型" prop="type">
<el-select v-model="queryParams.type" placeholder="请选择类型" clearable @change="handleQuery">
<el-option
v-for="dict in dict.type.suit_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="计费规则" prop="ridingRule">
<el-select v-model="queryParams.ridingRule" placeholder="请选择计费规则" clearable @change="handleQuery">
<el-option
v-for="dict in dict.type.suit_riding_rule"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="运营商" prop="userName">
<el-input
v-model="queryParams.userName"
placeholder="请输入运营商名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable @change="handleQuery">
<el-option
@ -27,24 +47,6 @@
/>
</el-select>
</el-form-item>
<el-form-item label="类型" prop="type">
<el-select v-model="queryParams.type" placeholder="请选择类型" clearable @change="handleQuery">
<el-option
v-for="dict in dict.type.suit_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="计费规则" prop="ridingRule">
<el-input
v-model="queryParams.ridingRule"
placeholder="请输入计费规则"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="租赁单位" prop="rentalUnit">
<el-input
v-model="queryParams.rentalUnit"

View File

@ -9,6 +9,14 @@
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="角色" prop="roleId" v-if="isShow('roles')">
<role-select
v-model="queryParams.roleId"
placeholder="请选择角色"
clearable
@change="handleQuery"
/>
</el-form-item>
<el-form-item label="归属部门" prop="deptId" v-if="isShow('deptName')">
<dept-select
v-model="queryParams.deptId"
@ -90,7 +98,7 @@
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange" @sort-change="onSortChange">
<el-table-column type="selection" width="50" align="center" />
<template v-for="column of showColumns">
<el-table-column
@ -223,13 +231,19 @@ import DeptSelect from '@/components/Business/Dept/DeptSelect.vue'
import { UserType, WithdrawServiceType } from '@/utils/enums'
import BooleanTag from '@/components/BooleanTag/index.vue'
import UserLink from '@/components/Business/User/UserLink.vue'
import RoleSelect from '@/components/Business/Role/RoleSelect.vue'
//
const defaultSort = {
prop: "createTime",
order: "descending"
}
export default {
name: "User",
mixins: [$showColumns],
dicts: ['user_status', 'sys_user_sex', 'user_employ_status', 'withdraw_service_type'],
components: {UserFormDialog, FormCol, DeptSelect, BooleanTag, UserLink},
components: {UserFormDialog, FormCol, DeptSelect, BooleanTag, UserLink, RoleSelect},
data() {
return {
WithdrawServiceType,
@ -316,6 +330,17 @@ export default {
this.getList();
},
methods: {
/** 当排序按钮被点击时触发 **/
onSortChange(column) {
if (column.order == null) {
this.queryParams.orderByColumn = defaultSort.prop;
this.queryParams.isAsc = defaultSort.order;
} else {
this.queryParams.orderByColumn = column.prop;
this.queryParams.isAsc = column.order;
}
this.getList();
},
handleView(row) {
this.$router.push(`/view/user/${row.userId}`);
},