diff --git a/src/api/agent/user.js b/src/api/agent/user.js new file mode 100644 index 0000000..fe52f87 --- /dev/null +++ b/src/api/agent/user.js @@ -0,0 +1,29 @@ +import request from '@/utils/request' + +// 代理商获取直属下级代理商列表 +export function agentListAgent(params) { + return request({ + url: '/agent/user/agentList', + method: 'get', + params + }) +} + +// 代理商获取直属下级业务员列表 +export function agentListBiz(params) { + return request({ + url: '/agent/user/bizList', + method: 'get', + params + }) +} + +// 代理商获取直属下级投资人列表 +export function agentListInvestor(params) { + return request({ + url: '/agent/user/investorList', + method: 'get', + params + }) +} + diff --git a/src/api/app/withdraw.js b/src/api/app/withdraw.js new file mode 100644 index 0000000..604d529 --- /dev/null +++ b/src/api/app/withdraw.js @@ -0,0 +1,22 @@ +import request from '@/utils/request' + +// 用户获取提现手续费 +export function appGetWithdrawService(channelId) { + return request({ + url: "/app/bill/getWithdrawService", + method: 'get', + params: { + channelId + } + }) +} + +// 用户申请提现 +export function appAddWithdraw(data) { + return request({ + url: "/app/bill/withdraw", + method: 'post', + data + }) + +} diff --git a/src/api/app/withdrawChannel.js b/src/api/app/withdrawChannel.js new file mode 100644 index 0000000..7d502db --- /dev/null +++ b/src/api/app/withdrawChannel.js @@ -0,0 +1,9 @@ +import request from '@/utils/request' + +// 获取启用的提现渠道列表 +export function getEnabledWithdrawChannel() { + return request({ + url: '/app/channel/withdraw/enabledList', + method: 'get' + }) +} diff --git a/src/api/ss/bonus.js b/src/api/ss/bonus.js index f9d7119..2ca2993 100644 --- a/src/api/ss/bonus.js +++ b/src/api/ss/bonus.js @@ -42,3 +42,14 @@ export function delBonus(id) { method: 'delete' }) } + +// 根据订单ID查询分成明细 +export function listBonusByBill(billId) { + return request({ + url: '/ss/bonus/byBill', + method: 'get', + params: { + billId + } + }) +} diff --git a/src/components/Business/Dept/DeptTreeSelect.vue b/src/components/Business/Dept/DeptTreeSelect.vue index 772c6e6..0a37a11 100644 --- a/src/components/Business/Dept/DeptTreeSelect.vue +++ b/src/components/Business/Dept/DeptTreeSelect.vue @@ -4,6 +4,7 @@ :options="deptOptions" :normalizer="normalizer" :placeholder="placeholder" + :disabled="disabled" @select="onSelect" /> </template> @@ -25,6 +26,10 @@ export default { placeholder: { type: String, default: '选择运营商' + }, + disabled: { + type: Boolean, + default: false } }, data() { diff --git a/src/components/LineField/index.vue b/src/components/LineField/index.vue index 4cad180..61a83cf 100644 --- a/src/components/LineField/index.vue +++ b/src/components/LineField/index.vue @@ -7,7 +7,7 @@ </div> <div class="right-box" > <slot> - {{value}} + {{value | defaultValue}} </slot> </div> </div> diff --git a/src/router/mchRouter.js b/src/router/agentRouter.js similarity index 89% rename from src/router/mchRouter.js rename to src/router/agentRouter.js index 5847762..10f9369 100644 --- a/src/router/mchRouter.js +++ b/src/router/agentRouter.js @@ -1,9 +1,10 @@ import Layout from '@/layout/index.vue' +import { FieldName } from '@/utils/constants' /** * 商户中心路由 */ -export const mchRoutes = [ +export const agentRouter = [ { path: '/share', component: Layout, @@ -14,7 +15,17 @@ export const mchRoutes = [ icon: 'user' }, children: [ - + { + path: 'user', + component: () => import('@/views/mch/user/agent.vue'), + hidden: false, + name: "User", + meta: { + noCache: false, + title: `${FieldName.AGENT}列表`, + icon: 'store' + } + }, ] }, { @@ -29,7 +40,7 @@ export const mchRoutes = [ children: [ { path: 'store', - component: () => import('../views/mch/store'), + component: () => import('@/views/mch/store'), hidden: false, name: "MyStore", meta: { @@ -40,7 +51,7 @@ export const mchRoutes = [ }, { path: 'store/:storeId', - component: () => import('../views/mch/store/detail.vue'), + component: () => import('@/views/mch/store/detail.vue'), hidden: true, name: "MyStoreDetail", meta: { diff --git a/src/store/getters.js b/src/store/getters.js index f993ff6..da0e526 100644 --- a/src/store/getters.js +++ b/src/store/getters.js @@ -9,6 +9,7 @@ const getters = { avatar: state => state.user.avatar, name: state => state.user.name, userType: state => state.user.userType, + smUserType: state => state.user.smUserType, userId: state => state.user.id, title: state => state.user.title, introduction: state => state.user.introduction, diff --git a/src/store/modules/permission.js b/src/store/modules/permission.js index 4e511f8..faf8d51 100644 --- a/src/store/modules/permission.js +++ b/src/store/modules/permission.js @@ -4,9 +4,9 @@ import { getRouters } from '@/api/menu' import Layout from '@/layout/index' import ParentView from '@/components/ParentView' import InnerLink from '@/layout/components/InnerLink' -import { mchRoutes } from '@/router/mchRouter' +import { agentRouter } from '@/router/agentRouter' import store from '@/store' -import { UserType } from '@/utils/constants' +import { SmUserType, UserType } from '@/utils/constants' const permission = { state: { @@ -37,7 +37,11 @@ const permission = { return new Promise(resolve => { // 商户 if (store.getters.userType === UserType.APP) { - handleRoutes(mchRoutes, mchRoutes, resolve, commit); + let smUserType = store.getters.smUserType + // 代理商路由 + if (smUserType === SmUserType.SALE) { + handleRoutes(agentRouter, agentRouter, resolve, commit); + } } // 管理员 else { diff --git a/src/store/modules/user.js b/src/store/modules/user.js index 9d058a8..ceb2154 100644 --- a/src/store/modules/user.js +++ b/src/store/modules/user.js @@ -11,6 +11,7 @@ const user = { roles: [], permissions: [], userType: getUserType(), + smUserType: '', title: process.env.VUE_APP_TITLE, deptId: null, }, @@ -42,6 +43,9 @@ const user = { }, SET_DEPT_ID: (state, deptId) => { state.deptId = deptId; + }, + SET_SM_USER_TYPE: (state, smUserType) => { + state.smUserType = smUserType; } }, @@ -83,7 +87,7 @@ const user = { return new Promise((resolve, reject) => { getInfo().then(res => { const user = res.user - const avatar = (user.avatar == "" || user.avatar == null) ? require("@/assets/images/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar; + const avatar = (user.avatar == "" || user.avatar == null) ? require("@/assets/images/profile.jpg") : user.avatar; if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组 commit('SET_ROLES', res.roles) commit('SET_PERMISSIONS', res.permissions) @@ -100,6 +104,7 @@ const user = { commit('SET_USER_TYPE', userType) if (userType === UserType.APP) { commit('SET_TITLE', "创亿康-商户中心") + commit('SET_SM_USER_TYPE', user.type); } resolve(res) }).catch(error => { diff --git a/src/utils/filter.js b/src/utils/filter.js index 23cdbf6..549835f 100644 --- a/src/utils/filter.js +++ b/src/utils/filter.js @@ -4,7 +4,11 @@ const filters = { if (num == null) { return num; } - return num.toFixed(2); + if (num instanceof Number) { + return num.toFixed(2); + } else { + return parseFloat(num).toFixed(2); + } }, // 缺省值 defaultValue(data) { diff --git a/src/utils/index.js b/src/utils/index.js index 08b75d1..4c5d465 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -460,3 +460,61 @@ export function findLabel(options, value, prop = 'value', propLabel = 'label') { let obj = options.find(item => item[prop] === value); return obj == null ? null : obj[propLabel] } + + +// 获取前n天的日期 +export function getLastDate(n) { + let now = new Date(); + return new Date(now.getTime() - n * 24 * 3600 * 1000) +} + +// 获取前n月的日期 +export function getLastMonth(n) { + const date = new Date(); + const year = date.getFullYear(); + const month = date.getMonth(); + const day = date.getDate(); + + // 减去 n 个月 + date.setMonth(month - n); + + // 确保日期不超过当月的最大天数 + const maxDay = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(); + date.setDate(Math.min(day, maxDay)); + + return date; +} + +// 获取前n月的日期字符串 +export function getLastMonthDateStr(n) { + let date = getLastMonth(n); + return parseTime(date, "{y}-{m}-{d}") +} + +// 获取前n天的日期字符串 +export function getLastDateStr(n) { + let date = getLastDate(n); + return parseTime(date, "{y}-{m}-{d}"); +} + +// 获取前n天的日期时间字符串00:00:00 +export function getLastDateTimeStartStr(n) { + let date = getLastDate(n); + return parseTime(date, "{y}-{m}-{d} 00:00:00"); +} + +// 获取前n天的日期时间字符串23:59:59 +export function getLastDateTimeEndStr(n) { + let date = getLastDate(n); + return parseTime(date, "{y}-{m}-{d} 23:59:59"); +} + +// 获取前n天的日期时间00:00:00 +export function getLastDateTimeStart(n) { + return new Date(getLastDateTimeStartStr(n)); +} + +// 获取前n天的日期时间23:59:59 +export function getLastDateTimeEnd(n) { + return new Date(getLastDateTimeEndStr(n)); +} diff --git a/src/views/mch/index/components/MchBalance.vue b/src/views/mch/index/components/MchBalance.vue new file mode 100644 index 0000000..fdbb396 --- /dev/null +++ b/src/views/mch/index/components/MchBalance.vue @@ -0,0 +1,206 @@ +<template> + <div> + <div class="balance-box"> + <div class="balance-label">账户余额(元)</div> + <div class="balance-amount">{{user.balance | money | defaultValue}}</div> + <div class="balance-sub-title"> + <div style="flex: 1"> + 累计提现:{{user.withDrawlAmount | money | defaultValue}} 元 + </div> + <transition name="el-fade-in-linear"> + <div class="balance-withdraw-btn" @click="handleWithdraw" v-show="!showWithdraw">立即提现</div> + </transition> + </div> + </div> + + <el-collapse-transition> + <div class="withdraw-box" v-show="showWithdraw"> + <el-form :model="withdrawForm" :rules="withdrawRules" ref="withdrawForm"> + <el-form-item label="提现金额" prop="money"> + <el-input v-model="withdrawForm.money" placeholder="请输入提现金额(元)" clearable @input="computeArrivalAmount"> + <template #append> + <el-button @click="withdrawForm.money = user.balance">全部提现</el-button> + </template> + </el-input> + <div>提现手续费 {{withdrawForm.serviceCharge | money | defaultValue}} 元</div> + </el-form-item> + <el-form-item label="提现方式" prop="channelId"> + <el-radio-group style="width: 100%" v-model="withdrawForm.channelId" @change="onChangeChannel"> + <el-radio v-for="channel of channelList" + :key="channel.channelId" + :label="channel.channelId" + border + class="channel-item"> + {{channel.name}} + </el-radio> + </el-radio-group> + </el-form-item> + </el-form> + <el-row type="flex" style="justify-content: right"> + <el-button @click="showWithdraw = false" round>取消</el-button> + <el-button @click="submitWithdraw" type="primary" round :loading="loading">确认提现</el-button> + </el-row> + </div> + </el-collapse-transition> + </div> + + +</template> + +<script> +import { getEnabledWithdrawChannel } from '@/api/app/withdrawChannel' +import { isEmpty } from '@/utils' +import { appAddWithdraw, appGetWithdrawService } from '@/api/app/withdraw' + +export default { + name: 'MchBalance', + props: { + user: { + type: Object, + default: () => { + return {} + } + } + }, + data() { + return { + loading: false, + showWithdraw: false, + withdrawForm: {}, + channelList: [], + withdrawRules: { + money: [{ required: true, message: '提现金额不能为空', trigger: 'blur' }], + channelId: [{ required: true, message: '提现方式不能为空', trigger: 'change' }] + } + } + }, + created() { + this.getChannel(); + }, + methods: { + resetWithdrawForm() { + this.withdrawForm = { + money: null, + channelId: null, + arrivalAmount: null, + serviceCharge: 0, + serviceRate: null, + serviceType: null + } + if (!isEmpty(this.channelList)) { + this.withdrawForm.channelId = this.channelList[0].channelId; + this.onChangeChannel(this.withdrawForm.channelId); + } + }, + onChangeChannel(channelId) { + appGetWithdrawService(channelId).then(res => { + this.withdrawForm.serviceType = res.data.serviceType; + this.withdrawForm.serviceRate = res.data.serviceRate; + this.computeArrivalAmount(); + }) + }, + computeArrivalAmount() { + if (this.withdrawForm.serviceType == null || this.withdrawForm.money == null) { + this.withdrawForm.serviceCharge = 0; + return; + } + if (this.withdrawForm.serviceType === "1") { + this.withdrawForm.serviceCharge = (this.withdrawForm.money * this.withdrawForm.serviceRate / 100).toFixed(2); + } else if (this.withdrawForm.serviceType === "2") { + this.withdrawForm.serviceCharge = this.withdrawForm.serviceRate.toFixed(2); + } + this.withdrawForm.arrivalAmount = (this.withdrawForm.money - this.withdrawForm.serviceCharge).toFixed(2) + }, + // 确认提现 + submitWithdraw() { + this.$refs.withdrawForm.validate(valid => { + if (valid) { + this.loading = true; + appAddWithdraw(this.withdrawForm).then(res => { + if (res.code === 200) { + this.$message.success("提交成功,等待审核通过"); + this.showWithdraw = false; + this.$emit('withdraw') + } + }).finally(() => { + this.loading = false; + }) + } + }) + }, + // 处理提现 + handleWithdraw() { + this.resetWithdrawForm(); + this.showWithdraw = true; + }, + getChannel() { + getEnabledWithdrawChannel().then(res => { + this.channelList = res.data; + }) + } + } +} +</script> + +<style scoped lang="scss"> +.balance-box { + z-index: 2; + position: relative; + background-image: url('https://api.ccttiot.com/smartmeter/img/static/uXaoTV3GIW6q0QHcM4De'); + width: 100%; + aspect-ratio: 2 / 1; + background-size: cover; + background-repeat: no-repeat; + padding: 2em 2em calc(2em + 32px); + color: #fff; + border-radius: 16px; + transition: .25s; + + .balance-label{ + font-size: 20px; + } + .balance-amount{ + font-size: 32px; + font-weight: bold; + margin-top: 0.5em; + } + .balance-sub-title { + position: absolute; + width: calc(100% - 4em); + display: flex; + justify-content: space-between; + bottom: 1.5em; + line-height: 32px; + + .balance-withdraw-btn { + height: 32px; + bottom: 2em; + right: 2em; + background-color: #FFFFFF; + color: #a3a0ff; + padding: 0 1em; + border-radius: 16px; + cursor: pointer; + transition: .25s; + } + .balance-withdraw-btn:hover { + transform: scale(1.15); + } + } + +} + +.withdraw-box { + z-index: 1; + position: relative; + top: -2em; + width: 100%; + padding: 3em 2em 1.5em; + background-color: #fff; + border-radius: 16px; + + .channel-item { + margin: 0; + } +} +</style> diff --git a/src/views/mch/index/components/MchRechargeCountReport.vue b/src/views/mch/index/components/MchRechargeCountReport.vue index 4cb9a5d..899812d 100644 --- a/src/views/mch/index/components/MchRechargeCountReport.vue +++ b/src/views/mch/index/components/MchRechargeCountReport.vue @@ -2,14 +2,16 @@ <div v-loading="loading"> <el-row type="flex" style="justify-content: space-between"> <el-date-picker - v-model="computedMonth" - type="month" - placeholder="选择月" - @change="getData" + v-model="computedDate" + type="daterange" + value-format="yyyy-MM-dd" + placeholder="选择日期" :clearable="false" - /> + @change="getData" + > + </el-date-picker> <div> - {{queryParams.year}}年{{queryParams.month}}月收入 + 合计 <span style="font-size: 26px">{{totalIncome | money}}</span> 元 </div> @@ -19,9 +21,10 @@ </template> <script> -import { mchRechargeCount } from '@/api/mch/recharge' import SingleLineChart from '@/components/SingleLineChart/index.vue' import RangePicker from '@/components/RangePicker/index.vue' +import { appBonusDailyAmount } from '@/api/app/dashboard' +import { getLastDateStr, getLastMonthDateStr } from '@/utils' export default { name: 'MchRechargeCountReport', @@ -29,9 +32,8 @@ export default { data() { return { queryParams: { - year: new Date().getFullYear(), - month: new Date().getMonth() + 1, - groupBy: "create_date" + payDateStart: getLastMonthDateStr(1), + payDateEnd: getLastDateStr(0) }, data: [], loading: false, @@ -40,30 +42,25 @@ export default { computed: { // 数据列表 chartData() { - return this.data.map(item => item.recharge); + return this.data.map(item => item.sum); }, labels() { - return this.data.map(item => item.createDate); + return this.data.map(item => item.key); }, - computedMonth: { + computedDate: { get() { - let date = new Date(); - date.setFullYear(this.queryParams.year); - date.setMonth(this.queryParams.month - 1); - console.log('get', date) - return date; + return [this.queryParams.payDateStart, this.queryParams.payDateEnd] }, set(val) { - console.log('set', val) - this.queryParams.year = val.getFullYear(); - this.queryParams.month = val.getMonth() + 1; + this.queryParams.payDateStart = val[0]; + this.queryParams.payDateEnd = val[1]; } }, totalIncome() { if (this.data == null) { return 0; } - return this.data.reduce((pre, cur) => pre + cur.recharge, 0); + return this.data.reduce((pre, cur) => pre + cur.sum, 0); } }, created() { @@ -72,7 +69,7 @@ export default { methods: { getData() { this.loading = true; - mchRechargeCount(this.queryParams).then(res => { + appBonusDailyAmount(this.queryParams).then(res => { this.data = res.data; }).finally(() => { this.loading = false; diff --git a/src/views/mch/index/components/MchUserProfile.vue b/src/views/mch/index/components/MchUserProfile.vue index 4474b17..dca025c 100644 --- a/src/views/mch/index/components/MchUserProfile.vue +++ b/src/views/mch/index/components/MchUserProfile.vue @@ -7,14 +7,19 @@ <el-statistic title="账户余额" :value="user.balance" suffix="元" :precision="2"/> </el-row> <el-row type="flex" style="margin-bottom: 1em"> - <el-statistic :title="FieldName.AGENT" :value="user.agentCount" suffix="人"/> - <el-statistic :title="FieldName.BIZ" :value="user.bizManCount" suffix="人"/> - <el-statistic :title="FieldName.INVESTOR" :value="user.investorCount" suffix="人"/> + <el-statistic v-if="SmUserType.SALE === smUserType" :title="FieldName.AGENT" :value="user.agentCount" suffix="人"/> + <el-statistic v-if="[SmUserType.SALE, SmUserType.BIZ].includes(smUserType)" :title="FieldName.BIZ" :value="user.bizManCount" suffix="人"/> + <el-statistic v-if="[SmUserType.SALE, SmUserType.BIZ].includes(smUserType)" :title="FieldName.INVESTOR" :value="user.investorCount" suffix="人"/> <el-statistic title="设备数" :value="user.deviceCount" suffix="台"/> <el-statistic :title="FieldName.STORE" :value="user.storeCount" suffix="家"/> </el-row> <el-row> + <line-field label="当前角色"> + <dict-tag :value="user.type" :options="dict.type.user_type" size="mini"/> + </line-field> <line-field label="绑定手机" :value="user.phonenumber"/> + <line-field v-if="[SmUserType.SALE, SmUserType.BIZ, SmUserType.INVESTOR].includes(smUserType)" label="推广人" :value="user.referenceName"/> + <line-field v-if="[SmUserType.SALE, SmUserType.BIZ, SmUserType.INVESTOR].includes(smUserType)" label="分成比例" :value="`${user.point} %`"/> </el-row> </div> </template> @@ -25,38 +30,36 @@ import { mapGetters } from 'vuex' import { appGetUserInfo } from '@/api/app/user' import { $serviceType, $withdrawServiceType } from '@/utils/mixins' import LineField from '@/components/LineField/index.vue' -import { FieldName } from '@/utils/constants' +import { FieldName, SmUserType } from '@/utils/constants' +import smUser from '@/views/system/smUser/index.vue' export default { name: "MchUserProfile", mixins: [$serviceType, $withdrawServiceType], - dicts: ['withdraw_service_type', 'service_type'], + dicts: ['user_type'], components: { LineField }, + props: { + user: { + type: Object, + default: () => { + return {} + } + } + }, data() { return { loading: false, - user: {} } }, computed: { + SmUserType() { + return SmUserType + }, FieldName() { return FieldName }, - ...mapGetters(['avatar']) + ...mapGetters(['avatar', 'smUserType']) }, - created() { - this.getUserInfo(); - }, - methods: { - getUserInfo() { - this.loading = true; - appGetUserInfo().then(res => { - this.user = res.data; - }).finally(() => { - this.loading = false; - }) - } - } } </script> diff --git a/src/views/mch/index/index.vue b/src/views/mch/index/index.vue index 7719287..e15195d 100644 --- a/src/views/mch/index/index.vue +++ b/src/views/mch/index/index.vue @@ -1,8 +1,9 @@ <template> <el-row :gutter="12"> <el-col :xl="6" :lg="8" :md="10" :sm="12" :xs="24"> + <mch-balance :user="user" style="margin-bottom: 1em" @withdraw="getUserInfo"/> <el-card class="card-box"> - <mch-user-profile/> + <mch-user-profile :user="user"/> </el-card> <!-- <el-card class="card-box" header="收款账户">--> <!-- <mch-account/>--> @@ -29,12 +30,32 @@ import { mapGetters } from 'vuex' import MchUserProfile from '@/views/mch/index/components/MchUserProfile.vue' import LineField from '@/components/LineField/index.vue' import MchAccount from '@/views/mch/index/components/MchAccount.vue' +import MchBalance from '@/views/mch/index/components/MchBalance.vue' +import { appGetUserInfo } from '@/api/app/user' export default { name: 'MchIndex', - components: { MchAccount, LineField, MchUserProfile, MchRechargeCountReport }, + components: { MchBalance, MchAccount, LineField, MchUserProfile, MchRechargeCountReport }, computed: { ...mapGetters(['name']) + }, + data() { + return { + user: {} + } + }, + created() { + this.getUserInfo(); + }, + methods: { + getUserInfo() { + this.loading = true; + appGetUserInfo().then(res => { + this.user = res.data; + }).finally(() => { + this.loading = false; + }) + } } } </script> diff --git a/src/views/mch/user/agent.vue b/src/views/mch/user/agent.vue new file mode 100644 index 0000000..dfe9ed3 --- /dev/null +++ b/src/views/mch/user/agent.vue @@ -0,0 +1,484 @@ +<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="name"> + <el-input + v-model="queryParams.name" + placeholder="请输入用户名" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="手机号码" prop="mobile"> + <el-input + v-model="queryParams.mobile" + placeholder="请输入手机号码" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar> + </el-row> + + <el-table + ref="table" + v-loading="loading" + :data="smUserList" + @row-click="changeSelection" + @selection-change="handleSelectionChange" + @sort-change="onSortChange" + :default-sort="defaultSort" + > + <el-table-column type="selection" width="55" align="center" /> + <template v-for="column of showColumns"> + <el-table-column + :key="column.key" + :label="column.label" + :prop="column.key" + :align="column.align" + :min-width="column.minWidth" + :sort-orders="['ascending', 'descending', null]" + :sortable="column.sortable" + :show-overflow-tooltip="column.overflow" + :width="column.width" + > + <template slot-scope="d"> + <template v-if="column.key === 'type'"> + <dict-tag :value="d.row.type" :options="dict.type.user_type"/> + </template> + <template v-else-if="column.key === 'phonenumber'"> + <user-link :id="d.row.userId" :name="d.row.phonenumber"/> + </template> + <template v-else-if="column.key === 'userName'"> + <user-link :id="d.row.userId" :name="d.row.userName"/> + </template> + <template v-else-if="column.key === 'referenceId'"> + <user-link :id="d.row.referenceId" :name="d.row.referenceName"/> + </template> + <template v-else-if="column.key === 'agentId'"> + <user-link :id="d.row.agentId" :name="d.row.agentName"/> + </template> + <template v-else-if="column.key === 'point'"> + {{d.row.point | money | defaultValue}} % + </template> + <template v-else-if="column.key === 'storeCount'"> + {{d.row.storeCount | defaultValue}} 家 + </template> + <template v-else-if="column.key === 'deviceCount'"> + {{d.row.deviceCount | defaultValue}} 台 + </template> + <template v-else-if="column.key === 'billCount'"> + {{d.row.billCount | defaultValue}} 单 + </template> + <template v-else-if="column.key === 'investorCount'"> + {{d.row.investorCount | defaultValue}} 人 + </template> + <template v-else-if="['totalIncome', 'withDrawlAmount', 'balance', 'billAmount'].includes(column.key)"> + {{d.row[column.key] | money | defaultValue}} 元 + </template> + <template v-else-if="column.key === 'status'"> + <dict-tag :options="dict.type.sm_user_status" :value="d.row.status"/> + </template> + <template v-else-if="column.key === 'deviceAdmin'"> + <el-tag :type="d.row.deviceAdmin ? 'danger' : 'info'">{{d.row.deviceAdmin ? '是' : '否'}}</el-tag> + </template> + <template v-else> + {{d.row[column.key] | defaultValue}} + </template> + </template> + </el-table-column> + </template> + <el-table-column label="操作" align="center" width="200" class-name="small-padding fixed-width" fixed="right"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-view" + @click="handleSee(scope.row)" + v-hasPermi="['system:smUser:detail']" + >详情</el-button> +<!-- <el-button--> +<!-- type="text"--> +<!-- icon="el-icon-refresh"--> +<!-- size="mini"--> +<!-- @click="handleResetService(scope.row)"--> +<!-- v-hasPermi="['system:smUser:edit']"--> +<!-- >重置服务费</el-button>--> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:smUser:edit']" + >修改</el-button> + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:smUser:remove']" + >删除</el-button> + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total>0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + + <!-- 添加或修改普通用户信息对话框 --> + <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="80px"> + <el-row> + <form-col :span="span" label="头像"> + <image-upload v-model="form.avatar" :limit="1"/> + </form-col> + <form-col :span="span" label="用户类型" prop="type"> + <el-select v-model="form.type" placeholder="请选择用户类型" style="width: 100%" :disabled="isEdit"> + <el-option + v-for="dict in dict.type.user_type" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </form-col> + <form-col :span="span" label="运营商" prop="deptId"> + <dept-tree-select v-model="form.deptId" @change="onChangeDept" :disabled="isEdit"/> + </form-col> + <form-col :span="span" label="推广人" prop="referenceId" v-if="![SmUserType.NORMAL, SmUserType.BUSINESS_PLACE].includes(form.type)"> + <user-input v-model="form.referenceId" @change="onChangeReference" show-type :query="referenceQuery" :before-open="beforeOpenReference" :disabled="isEdit"/> + </form-col> + <form-col :span="span" label="用户名" prop="userName"> + <el-input v-model="form.userName" placeholder="请输入用户名" /> + </form-col> + <form-col :span="span" label="手机号码" prop="phonenumber"> + <el-input v-model="form.phonenumber" placeholder="请输入手机号码" :maxlength="11" show-word-limit/> + </form-col> + <form-col :span="span" label="密码" prop="password"> + <el-input v-model="form.password" placeholder="请输入密码" type="password" :maxlength="32" show-word-limit/> + </form-col> + <form-col :span="span" label="分成比例" prop="point" v-if="![SmUserType.NORMAL, SmUserType.BUSINESS_PLACE].includes(form.type)"> + <el-input-number v-model="form.point" placeholder="请输入分成比例" :precision="2" controls-position="right" :min="0" style="width: calc(100% - 1.5em)"/> % + </form-col> + <form-col :span="span * 2" label="备注" prop="remark"> + <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" /> + </form-col> + </el-row> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">确 定</el-button> + <el-button @click="cancel">取 消</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { + listSmUser, + getSmUser, + addSmUser, + updateSmUser, + delSmUser, listAgent, listBiz, listInvestor, listStoreUser +} from '@/api/system/smUser' +import { $serviceType, $showColumns, $withdrawServiceType } from '@/utils/mixins' +import UserLink from '@/components/Business/SmUser/UserLink.vue' +import UserInput from '@/components/Business/SmUser/UserInput.vue' +import DeptTreeSelect from '@/components/Business/Dept/DeptTreeSelect.vue' +import { FieldName, SmUserType, UserType } from '@/utils/constants' +import { mapGetters } from 'vuex' +import { agentListAgent } from '@/api/agent/user' + +const defaultSort = { + prop: "createTime", + order: "descending" +} + +export default { + name: "SmUser", + mixins: [$showColumns, $serviceType, $withdrawServiceType], + dicts: ['sm_user_status', 'user_type', 'sys_user_sex', 'service_type', 'withdraw_service_type'], + components: { DeptTreeSelect, UserInput, UserLink }, + props: { + query: { + type: Object, + default: () => { + return {} + } + } + }, + computed: { + isEdit() { + return this.form != null && this.form.userId != null; + }, + FieldName() { + return FieldName + }, + ...mapGetters(['deptId', 'smUserType']), + SmUserType() { + return SmUserType + }, + // 推广人查询条件 + referenceQuery() { + let query = { + excludeId: this.form.userId, + deptId: this.form.deptId, + } + if (this.type === SmUserType.SALE) { + query.type = SmUserType.SALE; + } + if (this.type === SmUserType.BIZ) { + query.types = [SmUserType.SALE, SmUserType.BIZ] + } + return query; + }, + rules() { + return { + userName: [{ required: true, message: '请输入用户名称', trigger: 'blur' }], + phonenumber: [{ required: true, message: '请输入手机号', trigger: 'blur' }, + { pattern: /^1(3|4|5|7|8|9)\d{9}$/, message: '手机号格式错误', trigger: 'blur' } + ], + referenceId: [ + {required: this.form.type !== SmUserType.SALE, message: '请选择推广人', trigger: 'blur' } + ], + deptId: [ + {required: true,message: '请选择运营商', trigger: 'blur' } + ], + point: [ + { required: true, type: 'number', message: "分成比例不能为空", trigger: "blur" }, + ], + type: [ + { required: true, message: '请选择用户类型', trigger: 'blur' } + ] + } + } + }, + data() { + return { + defaultSort, + type: null, // 用户类型 + span: 12, + columns: [ + {key: 'userId', visible: false, label: '用户ID', align: 'center', minWidth: "80", sortable: true, width: null}, + {key: 'phonenumber', visible: true, label: '手机号码', align: 'center', minWidth: null, sortable: true, width: "120"}, + {key: 'userName', visible: true, label: '用户名称', align: 'center', minWidth: null, sortable: false, width: "120"}, + {key: 'type', visible: true, label: '用户角色', align: 'center', minWidth: null, sortable: true, width: null}, + {key: 'point', visible: true, label: '分成比例', align: 'center', minWidth: null, sortable: true, width: null}, + {key: 'referenceId', visible: true, label: '推广人', align: 'center', minWidth: null, sortable: true, width: null}, + {key: 'remark', visible: true, label: '备注', align: 'center', minWidth: null, sortable: false, overflow: true, width: null}, + {key: 'status', visible: true, label: '账号状态', align: 'center', minWidth: null, sortable: true, width: null}, + {key: 'createTime', visible: true, label: '注册时间', align: 'center', minWidth: null, sortable: true, width: "100"}, + {key: 'totalIncome', visible: true, label: '收入金额', align: 'center', minWidth: null, sortable: true, width: null}, + {key: 'withDrawlAmount', visible: true, label: '提现金额', align: 'center', minWidth: null, sortable: true, width: null}, + {key: 'balance', visible: true, label: '账户余额', align: 'center', minWidth: null, sortable: true, width: null}, + {key: 'agentId', visible: true, label: `直属${FieldName.AGENT}`, align: 'center', minWidth: null, sortable: false, width: null}, + {key: 'investorCount', visible: false, label: `${FieldName.INVESTOR}数`, align: 'center', minWidth: null, sortable: false, width: null}, + {key: 'storeCount', visible: false, label: `${FieldName.STORE}数`, align: 'center', minWidth: null, sortable: false, width: null}, + {key: 'deviceCount', visible: false, label: '设备数', align: 'center', minWidth: null, sortable: false, width: null}, + {key: 'billCount', visible: false, label: '订单数', align: 'center', minWidth: null, sortable: false, width: null}, + {key: 'billAmount', visible: false, label: '订单总额', align: 'center', minWidth: null, sortable: false, width: null}, + {key: 'deviceAdmin', visible: false, label: '是否设备管理员', align: 'center', minWidth: null, sortable: false, width: null}, + ], + openServiceRate: false, + // 遮罩层 + loading: true, + // 选中数组 + ids: [], + // 非单个禁用 + single: true, + // 非多个禁用 + multiple: true, + // 显示搜索条件 + showSearch: true, + // 总条数 + total: 0, + // 普通用户信息表格数据 + smUserList: [], + // 弹出层标题 + title: "", + // 是否显示弹出层 + open: false, + // 查询参数 + queryParams: { + pageNum: 1, + pageSize: 10, + orderByColumn: defaultSort.prop, + isAsc: defaultSort.order, + phonenumber: null, + serviceType: null, + status: null, + }, + // 表单参数 + form: {}, + }; + }, + created() { + this.queryParams = { + ...this.queryParams, + ...this.query + } + this.getList(); + }, + methods: { + onChangeDept(dept) { + if (this.form.referenceId != null) { + this.form.referenceId = null; + this.$message.info("更换运营商,请重新选择推广人") + } + }, + beforeOpenReference() { + if (this.form.deptId == null) { + this.$message.warning("请先选择运营商"); + return false; + } + return true; + }, + onChangeReference(user) { + this.form.deptId = user.deptId; + }, + 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(); + }, + // 更换某一行的选中状态 + changeSelection(row){ + if (this.ids.includes(row.userId)){ + this.$refs.table.toggleRowSelection(row, false); + this.ids = this.ids.filter(i => i !== row.userId); + }else { + this.$refs.table.toggleRowSelection(row, true); + this.ids.push(row.ids); + } + }, + /** 查询普通用户信息列表 */ + getList() { + this.loading = true; + if (this.smUserType === SmUserType.SALE) { + agentListAgent(this.queryParams).then(res => { + this.smUserList = res.rows; + }).finally(() => { + this.loading = false; + }) + } + }, + afterList(res) { + this.smUserList = res.rows; + this.total = res.total; + this.loading = false; + }, + // 取消按钮 + cancel() { + this.open = false; + this.reset(); + }, + // 表单重置 + reset() { + this.form = { + userId: null, + userName: null, + nickName: null, + phonenumber: null, + sex: "2", + avatar: null, + isMch: false, + deviceAdmin: false, + serviceType: '1', + type: this.type, + deptId: this.deptId, + point: 0, + }; + this.resetForm("form"); + }, + /** 搜索按钮操作 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 重置按钮操作 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + // 多选框选中数据 + handleSelectionChange(selection) { + this.ids = selection.map(item => item.userId) + this.single = selection.length!==1 + this.multiple = !selection.length + }, + /** 新增按钮操作 */ + handleAdd() { + this.reset(); + this.open = true; + this.title = "添加用户信息"; + }, + /** 查看按钮操作 */ + handleSee(row) { + this.$router.push({path: `/smUser/user/${row.userId}`}) + }, + /** 修改按钮操作 */ + handleUpdate(row) { + this.reset(); + const userId = row.userId || this.ids + getSmUser(userId).then(response => { + this.form = response.data; + this.open = true; + this.title = "修改用户信息"; + }); + }, + /** 提交按钮 */ + submitForm() { + this.$refs["form"].validate(valid => { + if (valid) { + if (this.form.userId != null) { + updateSmUser(this.form).then(response => { + this.$modal.msgSuccess("修改成功"); + this.open = false; + this.getList(); + }); + } else { + addSmUser(this.form).then(response => { + this.$modal.msgSuccess("新增成功"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + /** 删除按钮操作 */ + handleDelete(row) { + const userIds = row.userId || this.ids; + this.$modal.confirm('是否确认删除普通用户信息编号为"' + userIds + '"的数据项?').then(function() { + return delSmUser(userIds); + }).then(() => { + this.getList(); + this.$modal.msgSuccess("删除成功"); + }).catch(() => {}); + }, + /** 导出按钮操作 */ + handleExport() { + this.download('system/smUser/export', { + ...this.queryParams + }, `smUser_${new Date().getTime()}.xlsx`) + } + } +}; +</script> diff --git a/src/views/ss/payBill/index.vue b/src/views/ss/payBill/index.vue index 8e2df21..21b7d10 100644 --- a/src/views/ss/payBill/index.vue +++ b/src/views/ss/payBill/index.vue @@ -154,7 +154,7 @@ <script> import { listPayBill, getPayBill, delPayBill, addPayBill, updatePayBill, refundPayBill } from '@/api/ss/payBill' import { $showColumns, $view } from '@/utils/mixins' -import { PayBillStatus } from '@/utils/constants' +import { PayBillStatus, views } from '@/utils/constants' // 默认排序字段 const defaultSort = { @@ -194,18 +194,18 @@ export default { // 字段列表 columns: [ {key: 'payId', visible: false, label: 'ID', minWidth: null, sortable: true, overflow: false, align: 'center', width: null}, - {key: 'payNo', visible: true, label: '支付订单编号', minWidth: null, sortable: true, overflow: false, align: 'center', width: "180"}, - {key: 'bstType', visible: true, label: '业务类型', minWidth: null, sortable: true, overflow: false, align: 'center', width: null}, + {key: 'payNo', visible: true, label: '编号', minWidth: null, sortable: true, overflow: false, align: 'center', width: "100"}, + {key: 'bstType', visible: true, label: '类型', minWidth: null, sortable: true, overflow: false, align: 'center', width: null}, {key: 'bstId', visible: false, label: '业务ID', minWidth: null, sortable: true, overflow: false, align: 'center', width: null}, - {key: 'amount', visible: true, label: '支付金额', minWidth: null, sortable: true, overflow: false, align: 'center', width: null}, - {key: 'channelId', 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: 'payTime', visible: true, label: '支付时间', minWidth: "120", sortable: false, overflow: false, align: 'center', width: null}, - {key: 'description', visible: true, label: '描述', minWidth: "200", sortable: true, overflow: true, align: 'center', width: null}, + {key: 'amount', visible: true, label: '金额', minWidth: null, sortable: true, overflow: false, align: 'center', width: null}, + {key: 'channelId', 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: 'payTime', visible: true, label: '支付时间', minWidth: "120", sortable: true, overflow: false, align: 'center', width: "100"}, + {key: 'description', visible: true, label: '描述', minWidth: "200", sortable: false, overflow: true, align: 'center', width: null}, {key: 'account', visible: true, label: '支付账号', minWidth: "100", sortable: true, overflow: true, align: 'center', width: null}, - {key: 'channelCost', visible: true, label: '渠道成本', minWidth: null, sortable: true, overflow: false, align: 'center', width: null}, - {key: 'refundAmount', visible: true, label: '已退款金额', minWidth: null, sortable: true, overflow: false, align: 'center', width: null}, - {key: 'refundingAmount', visible: true, label: '退款中金额', minWidth: null, sortable: true, overflow: false, align: 'center', width: null}, + {key: 'channelCost', visible: true, label: '成本', minWidth: null, sortable: true, overflow: false, align: 'center', width: null}, + {key: 'refundAmount', visible: true, label: '已退款', minWidth: null, sortable: true, overflow: false, align: 'center', width: null}, + {key: 'refundingAmount', visible: true, label: '退款中', minWidth: null, sortable: true, overflow: false, align: 'center', width: null}, ], // 排序方式 orderSorts: ['ascending', 'descending', null], @@ -281,6 +281,10 @@ export default { }; }, created() { + // 订单列表中,隐藏搜索 + if (this.hasView(views.recharge)) { + this.showSearch = false; + } this.queryParams = { ...this.queryParams, ...this.query diff --git a/src/views/system/recharge/detail.vue b/src/views/system/recharge/detail.vue index 30d9cf8..eaf77d4 100644 --- a/src/views/system/recharge/detail.vue +++ b/src/views/system/recharge/detail.vue @@ -2,28 +2,33 @@ <div class="app-container" v-loading="loading"> <el-row :gutter="12"> <el-col :span="18"> - <el-card class="box-card"> - <el-descriptions title="基本信息"> + <el-card class="box-card" header="基本信息"> + <el-descriptions> <el-descriptions-item label="订单编号">{{detail.billNo | defaultValue}}</el-descriptions-item> <el-descriptions-item label="交易状态"> <dict-tag :value="detail.status" :options="dict.type.sm_transaction_bill_status" size="small"/> </el-descriptions-item> - <el-descriptions-item label="交易金额">{{detail.money | money | defaultValue}} 元</el-descriptions-item> + <el-descriptions-item label="订单金额">{{detail.money | money | defaultValue}} 元</el-descriptions-item> <el-descriptions-item label="设备编号"> <device-link :id="detail.deviceId" :text="detail.deviceNo"/> </el-descriptions-item> <el-descriptions-item label="设备名称"> <device-link :id="detail.deviceId" :text="detail.deviceName"/> </el-descriptions-item> - <el-descriptions-item label="经营场所"> + <el-descriptions-item label="设备充值状态" v-if="[SuitFeeType.TIMING, SuitFeeType.COUNT].includes(detail.suitFeeType)"> + <dict-tag :value="detail.deviceRechargeStatus" + :options="dict.type.sm_transaction_bill_device_recharge_status" + size="small"/> + </el-descriptions-item> + <el-descriptions-item :label="FieldName.STORE"> <store-link :id="detail.storeId" :name="detail.storeName"/> </el-descriptions-item> - <el-descriptions-item label="经营场所地址"> - {{detail.storeAddress | defaultValue}} - </el-descriptions-item> - <el-descriptions-item label="房间号" :span="2"> + <el-descriptions-item label="房间号"> {{detail.deviceRoom | defaultValue}} </el-descriptions-item> + <el-descriptions-item label="地址"> + {{detail.storeAddress | defaultValue}} + </el-descriptions-item> <el-descriptions-item :label="FieldName.AGENT"> <user-link :id="detail.agentId" :name="detail.agentName"/>({{detail.agentMobile}}) </el-descriptions-item> @@ -35,25 +40,31 @@ </el-descriptions-item> </el-descriptions> </el-card> - <el-card class="box-card"> - <el-descriptions title="套餐信息"> + <el-card class="box-card" header="套餐信息"> + <el-descriptions> <el-descriptions-item label="套餐名称">{{detail.suitName | defaultValue}}</el-descriptions-item> <el-descriptions-item label="套餐时长" v-if="detail.suitFeeType === SuitFeeType.TIMING">{{detail.suitTime | defaultValue}} {{suitTimeUnit(detail.suitTimeUnit)}}</el-descriptions-item> <el-descriptions-item label="套餐电量" v-if="detail.suitFeeType === SuitFeeType.COUNT">{{detail.suitTime | defaultValue}} 度</el-descriptions-item> - <el-descriptions-item label="设备充值状态" v-if="[SuitFeeType.TIMING, SuitFeeType.COUNT].includes(detail.suitFeeType)"> - <dict-tag :value="detail.deviceRechargeStatus" - :options="dict.type.sm_transaction_bill_device_recharge_status" - size="small"/> - </el-descriptions-item> <el-descriptions-item label="套餐开始时间">{{detail.suitStartTime | defaultValue}}</el-descriptions-item> <el-descriptions-item label="套餐结束时间">{{detail.suitEndTime | defaultValue}}</el-descriptions-item> <el-descriptions-item label="套餐失效时间">{{detail.suitExpireTime | defaultValue}}</el-descriptions-item> </el-descriptions> </el-card> + + <el-card class="box-card"> + <el-tabs> + <el-tab-pane label="支付信息" lazy v-if="checkPermi(['ss:payBill:list'])"> + <pay-bill v-if="detail.billId != null" :query="{bstId: detail.billId}" :view="views.recharge"/> + </el-tab-pane> +<!-- <el-tab-pane label="分成信息" lazy v-if="checkPermi(['ss:bonus:list'])">--> +<!-- <bonus :query="{billId: detail.billId}" :view="views.recharge"/>--> +<!-- </el-tab-pane>--> + </el-tabs> + </el-card> </el-col> <el-col :span="6"> - <el-card class="box-card"> - <el-descriptions title="支付方信息" :column="1"> + <el-card class="box-card" header="支付方信息"> + <el-descriptions :column="1"> <el-descriptions-item label="用户名称"> <user-link :id="detail.userId" :name="detail.userName"/> </el-descriptions-item> @@ -61,21 +72,24 @@ <dict-tag :value="detail.channelId" :options="dict.type.channel_type" size="small"/> </el-descriptions-item> <el-descriptions-item label="支付时间">{{detail.payTime | defaultValue}}</el-descriptions-item> + <el-descriptions-item label="支付账号">{{detail.accountNo | defaultValue}}</el-descriptions-item> </el-descriptions> </el-card> + <el-card class="box-card" header="分成信息" v-if="checkPermi(['ss:bonus:list'])"> + <line-field v-for="item of bonusList" :key="item.id"> + <template #label> + <dict-tag :value="item.arrivalType" :options="dict.type.bonus_arrival_type" size="mini" style="margin-right: 0.5em"/> + {{item.arrivalName}} + ({{item.point | money | defaultValue}}%) + </template> + <div> + <dict-tag :value="item.status" :options="dict.type.bonus_status" size="mini"/> + {{item.amount | money | defaultValue}} 元 + </div> + </line-field> + </el-card> </el-col> </el-row> - - <el-card class="box-card"> - <el-tabs> - <el-tab-pane label="支付信息" lazy v-if="checkPermi(['ss:payBill:list'])"> - <pay-bill v-if="detail.billId != null" :query="{bstId: detail.billId}" :view="views.recharge"/> - </el-tab-pane> - <el-tab-pane label="分成信息" lazy v-if="checkPermi(['ss:bonus:list'])"> - <bonus :query="{billId: detail.billId}" :view="views.recharge"/> - </el-tab-pane> - </el-tabs> - </el-card> </div> </template> @@ -90,11 +104,13 @@ import PayBill from '@/views/ss/payBill/index.vue' import StoreLink from '@/components/Business/Store/StoreLink.vue' import Bonus from '@/views/ss/bonus/index.vue' import { checkPermi } from '@/utils/permission' +import { listBonusByBill } from '@/api/ss/bonus' +import LineField from '@/components/LineField/index.vue' export default { name: 'RechargeDetail', - components: { Bonus, StoreLink, PayBill, UserLink, DeviceLink, Refund }, - dicts: ['channel_type','sm_transaction_bill_status', 'sm_transaction_bill_device_recharge_status', 'time_unit', 'suit_fee_mode', 'suit_fee_type'], + components: { LineField, Bonus, StoreLink, PayBill, UserLink, DeviceLink, Refund }, + dicts: ['channel_type','sm_transaction_bill_status', 'sm_transaction_bill_device_recharge_status', 'time_unit', 'suit_fee_mode', 'suit_fee_type', 'bonus_status', 'bonus_arrival_type'], computed: { FieldName() { return FieldName @@ -116,6 +132,7 @@ export default { return { loading: false, detail: {}, + bonusList: [], // 分成列表 id: null, suitUsingType: ['info', 'warning', 'success', 'danger'], suitUsingText: ['未知', '未生效', '使用中', '已结束'] @@ -131,6 +148,9 @@ export default { getBill(this.id).then(res => { this.detail = res.data; }) + listBonusByBill(this.id).then(res => { + this.bonusList = res.data; + }) } } } diff --git a/src/views/system/smUser/index.vue b/src/views/system/smUser/index.vue index 724b6ac..2c74fc9 100644 --- a/src/views/system/smUser/index.vue +++ b/src/views/system/smUser/index.vue @@ -124,7 +124,7 @@ <template v-else-if="column.key === 'investorCount'"> {{d.row.investorCount | defaultValue}} 人 </template> - <template v-else-if="['rechargeAmount', 'withDrawlAmount', 'balance', 'billAmount'].includes(column.key)"> + <template v-else-if="['totalIncome', 'withDrawlAmount', 'balance', 'billAmount'].includes(column.key)"> {{d.row[column.key] | money | defaultValue}} 元 </template> <template v-else-if="column.key === 'status'"> @@ -189,7 +189,7 @@ <image-upload v-model="form.avatar" :limit="1"/> </form-col> <form-col :span="span" label="用户类型" prop="type"> - <el-select v-model="form.type" placeholder="请选择用户类型" style="width: 100%"> + <el-select v-model="form.type" placeholder="请选择用户类型" style="width: 100%" :disabled="isEdit"> <el-option v-for="dict in dict.type.user_type" :key="dict.value" @@ -199,10 +199,10 @@ </el-select> </form-col> <form-col :span="span" label="运营商" prop="deptId"> - <dept-tree-select v-model="form.deptId" @change="onChangeDept"/> + <dept-tree-select v-model="form.deptId" @change="onChangeDept" :disabled="isEdit"/> </form-col> <form-col :span="span" label="推广人" prop="referenceId" v-if="![SmUserType.NORMAL, SmUserType.BUSINESS_PLACE].includes(form.type)"> - <user-input v-model="form.referenceId" @change="onChangeReference" show-type :query="referenceQuery" :before-open="beforeOpenReference"/> + <user-input v-model="form.referenceId" @change="onChangeReference" show-type :query="referenceQuery" :before-open="beforeOpenReference" :disabled="isEdit"/> </form-col> <form-col :span="span" label="用户名" prop="userName"> <el-input v-model="form.userName" placeholder="请输入用户名" /> @@ -263,6 +263,9 @@ export default { } }, computed: { + isEdit() { + return this.form != null && this.form.userId != null; + }, FieldName() { return FieldName }, @@ -320,7 +323,7 @@ export default { {key: 'remark', visible: true, label: '备注', align: 'center', minWidth: null, sortable: false, overflow: true, width: null}, {key: 'status', visible: true, label: '账号状态', align: 'center', minWidth: null, sortable: true, width: null}, {key: 'createTime', visible: true, label: '注册时间', align: 'center', minWidth: null, sortable: true, width: "100"}, - {key: 'rechargeAmount', visible: true, label: '充值金额', align: 'center', minWidth: null, sortable: true, width: null}, + {key: 'totalIncome', visible: true, label: '收入金额', align: 'center', minWidth: null, sortable: true, width: null}, {key: 'withDrawlAmount', visible: true, label: '提现金额', align: 'center', minWidth: null, sortable: true, width: null}, {key: 'balance', visible: true, label: '账户余额', align: 'center', minWidth: null, sortable: true, width: null}, {key: 'agentId', visible: true, label: `直属${FieldName.AGENT}`, align: 'center', minWidth: null, sortable: false, width: null}, @@ -379,7 +382,7 @@ export default { } else if (this.type === SmUserType.BUSINESS_PLACE) { this.hideColumn(['investorCount', 'billAmount', 'point', 'agentId', 'deviceCount', 'billCount', 'billAmount', 'referenceId']) } else if (this.type === SmUserType.NORMAL) { - this.hideColumn(['investorCount', 'billAmount', 'point', 'agentId', 'deviceCount', 'billCount', 'billAmount', 'storeCount', 'referenceId']) + this.hideColumn(['investorCount', 'billAmount', 'point', 'agentId', 'deviceCount', 'billCount', 'billAmount', 'storeCount', 'referenceId', 'totalIncome', 'withDrawlAmount']) } this.queryParams = { diff --git a/src/views/system/user/profile/userAvatar.vue b/src/views/system/user/profile/userAvatar.vue index cbf3ca1..2bbb755 100644 --- a/src/views/system/user/profile/userAvatar.vue +++ b/src/views/system/user/profile/userAvatar.vue @@ -137,7 +137,7 @@ export default { formData.append("avatarfile", data, this.options.filename); uploadAvatar(formData).then(response => { this.open = false; - this.options.img = process.env.VUE_APP_BASE_API + response.imgUrl; + this.options.img = response.imgUrl; store.commit('SET_AVATAR', this.options.img); this.$modal.msgSuccess("修改成功"); this.visible = false;