源文件
This commit is contained in:
400
jeepay-ui-agent/src/views/sysuser/AddOrEdit.vue
Normal file
400
jeepay-ui-agent/src/views/sysuser/AddOrEdit.vue
Normal file
@@ -0,0 +1,400 @@
|
||||
<template>
|
||||
<a-drawer
|
||||
v-model:visible="vdata.isShow"
|
||||
:title=" vdata.isAdd ? '新增操作员' : '修改操作员' "
|
||||
placement="right"
|
||||
:closable="true"
|
||||
width="600"
|
||||
:mask-closable="false"
|
||||
@ok="handleOkFunc"
|
||||
@close="onClose"
|
||||
>
|
||||
<!-- <a-modal :confirmLoading="confirmLoading"> -->
|
||||
|
||||
<a-form
|
||||
ref="infoFormModel"
|
||||
:model="vdata.saveObject"
|
||||
layout="vertical"
|
||||
:rules="rules"
|
||||
style="padding-bottom:50px"
|
||||
>
|
||||
<a-row justify="space-between" type="flex">
|
||||
<a-col :span="10">
|
||||
<a-form-item label="用户登录名:" name="loginUsername">
|
||||
<a-input v-model:value="vdata.saveObject['loginUsername']" :disabled="!vdata.isAdd" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="10">
|
||||
<a-form-item label="用户姓名:" name="realname">
|
||||
<a-input v-model:value="vdata.saveObject['realname']" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="10">
|
||||
<a-form-item label="手机号:" name="telphone">
|
||||
<a-input v-model:value="vdata.saveObject['telphone']" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="10">
|
||||
<a-form-item label="编号:" name="userNo">
|
||||
<a-input v-model:value="vdata.saveObject['userNo']" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="10">
|
||||
<a-form-item label="请选择性别:" name="sex">
|
||||
<a-radio-group v-model:value="vdata.saveObject['sex']">
|
||||
<a-radio :value="1">
|
||||
男
|
||||
</a-radio>
|
||||
<a-radio :value="2">
|
||||
女
|
||||
</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<!-- <a-col :span="10">
|
||||
<a-form-item label="是否为超级管理员:" name="isAdmin">
|
||||
<a-radio-group v-model:value="vdata.saveObject['isAdmin']">
|
||||
<a-radio :value="1">
|
||||
是
|
||||
</a-radio>
|
||||
<a-radio :value="0">
|
||||
否
|
||||
</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-col> -->
|
||||
|
||||
<a-col :span="10">
|
||||
<a-form-item label="状态:" name="state">
|
||||
<a-radio-group v-model:value="vdata.saveObject['state']">
|
||||
<a-radio :value="1">
|
||||
启用
|
||||
</a-radio>
|
||||
<a-radio :value="0">
|
||||
停用
|
||||
</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="10">
|
||||
<a-form-item label="用户类型:" name="userType">
|
||||
<a-select v-model:value="vdata.saveObject.userType" placeholder="请选择用户类型" @change="changeUserType">
|
||||
<a-select-option :value="1">超级管理员</a-select-option>
|
||||
<a-select-option :value="2">普通操作员</a-select-option>
|
||||
<a-select-option :value="3">商户拓展员</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col v-if="vdata.saveObject.userType == 3" :span="10">
|
||||
<a-form-item label="选择团队" name="provider">
|
||||
<a-select v-model:value="vdata.saveObject.teamId" placeholder="请选择团队">
|
||||
<a-select-option v-for="(item, key) in vdata.teamList" :key="key" v-model:value="item.teamId">
|
||||
{{ item.teamName }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col v-if="vdata.saveObject.userType == 3" :span="10">
|
||||
<a-form-item label="是否队长" name="isTeamLeader">
|
||||
<a-radio-group v-model:value="vdata.saveObject.isTeamLeader">
|
||||
<a-radio :value="1">
|
||||
是
|
||||
</a-radio>
|
||||
<a-radio :value="0">
|
||||
否
|
||||
</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-divider orientation="left">
|
||||
<a-tag color="#FF4B33">
|
||||
账户安全
|
||||
</a-tag>
|
||||
</a-divider>
|
||||
|
||||
<div v-if="vdata.isAdd">
|
||||
<a-row justify="space-between" type="flex">
|
||||
<a-col :span="24">
|
||||
<a-form-item label="是否发送开通提醒">
|
||||
<a-radio-group v-model:value="vdata.saveObject['isNotify']">
|
||||
<a-radio :value="0">否</a-radio>
|
||||
<a-radio :value="1">是</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="密码设置">
|
||||
<a-radio-group v-model:value="vdata.saveObject['passwordType']">
|
||||
<a-radio value="default">默认密码</a-radio>
|
||||
<a-radio value="custom">自定义密码</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col v-if="vdata.saveObject['passwordType'] == 'custom'" :span="12">
|
||||
<a-form-item label="登录密码" name="loginPassword">
|
||||
<a-input
|
||||
v-model:value="vdata.saveObject['loginPassword']"
|
||||
placeholder="请输入登录密码"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-button type="primary" ghost @click="randomPassage(false, 6, 0)"><file-sync-outlined />随机生成密码</a-button>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div style="display:flex;flex-direction:row;">
|
||||
<a-row justify="space-between" type="flex" style="width:100%">
|
||||
<a-col :span="10">
|
||||
<a-form-item v-if="vdata.resetIsShow" label="">
|
||||
重置密码:<a-checkbox v-model:checked="vdata.sysPassword.resetPass" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="10">
|
||||
<a-form-item v-if="vdata.sysPassword.resetPass" label="">
|
||||
恢复默认密码:<a-checkbox v-model:checked="vdata.sysPassword.defaultPass" @click="isResetPass" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
|
||||
<div v-if="vdata.sysPassword.resetPass">
|
||||
<div v-show="!vdata.sysPassword.defaultPass">
|
||||
<a-row justify="space-between" type="flex">
|
||||
<a-col :span="10">
|
||||
<a-form-item label="新密码:" name="newPwd">
|
||||
<a-input-password
|
||||
v-model:value="vdata.newPwd"
|
||||
autocomplete="new-password"
|
||||
:disabled="vdata.sysPassword.defaultPass"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="10">
|
||||
<a-form-item label="确认新密码:" name="confirmPwd">
|
||||
<a-input-password
|
||||
v-model:value="vdata.sysPassword.confirmPwd"
|
||||
autocomplete="new-password"
|
||||
:disabled="vdata.sysPassword.defaultPass"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="drawer-btn-center">
|
||||
<a-button :style="{ marginRight: '8px' }" @click="onClose">
|
||||
<close-outlined />
|
||||
取消
|
||||
</a-button>
|
||||
<a-button type="primary" :loading="vdata.confirmLoading" @click="handleOkFunc">
|
||||
<check-outlined />
|
||||
保存
|
||||
</a-button>
|
||||
</div>
|
||||
</a-form>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { req, API_URL_SYS_USER_LIST, API_URL_SYS_USER_TEAM_LIST, $getPasswordRules } from '@/api/manage'
|
||||
import { reactive,ref } from 'vue'
|
||||
import { Base64 } from 'js-base64'
|
||||
import { message } from 'ant-design-vue'
|
||||
|
||||
const props = defineProps ({
|
||||
callbackFunc: { type: Function, default: () => ({}) }
|
||||
})
|
||||
|
||||
const infoFormModel = ref()
|
||||
const vdata = reactive ({
|
||||
newPwd: '', // 新密码
|
||||
resetIsShow: false, // 重置密码是否展现
|
||||
passwordRules: /^$/, //密码规则
|
||||
passwordRulesText: '', //密码规则提示文字
|
||||
sysPassword: {
|
||||
resetPass: false, // 重置密码
|
||||
defaultPass: true, // 使用默认密码
|
||||
confirmPwd: '' // 确认密码
|
||||
},
|
||||
loading: false, // 按钮上的loading
|
||||
value: 1, // 单选框默认的值
|
||||
teamList: [] as any, // 团队列表
|
||||
confirmLoading: false, // 显示确定按钮loading图标
|
||||
isAdd: true, // 新增 or 修改页面标识
|
||||
isShow: false, // 是否显示弹层/抽屉
|
||||
saveObject: {} as any, // 数据对象
|
||||
recordId: null, // 更新对象ID
|
||||
})
|
||||
const rules = reactive({
|
||||
realname: [{ required: true, message: '请输入用户姓名', trigger: 'blur' }],
|
||||
telphone: [{ required: true, pattern: /^[1][0-9]{10}$/, message: '请输入正确的手机号码', trigger: 'blur' }],
|
||||
userNo: [{ required: true, message: '请输入编号', trigger: 'blur' }],
|
||||
userType: [{ required: true, message: '请选择用户类型', trigger: 'blur' }],
|
||||
loginUsername: [] as any[],
|
||||
newPwd: [{ required: false, trigger: 'blur' }, {
|
||||
validator: (rule, value) => {
|
||||
if (!vdata.sysPassword.defaultPass) {
|
||||
if (!vdata.passwordRules.test(vdata.newPwd)) {
|
||||
return Promise.reject(vdata.passwordRulesText)
|
||||
} else if(vdata.newPwd !== vdata.sysPassword.confirmPwd) {
|
||||
return Promise.reject('新密码与确认密码不一致')
|
||||
} else return Promise.resolve()
|
||||
} else {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
}
|
||||
}], // 新密码
|
||||
confirmPwd: [{ required: false, trigger: 'blur' }, {
|
||||
validator: (rule, value) => {
|
||||
if (!vdata.sysPassword.defaultPass) {
|
||||
// vdata.newPwd === vdata.sysPassword.confirmPwd ? callBack() : callBack('新密码与确认密码不一致')
|
||||
if(!vdata.passwordRules.test(vdata.sysPassword.confirmPwd)){
|
||||
return Promise.reject(vdata.passwordRulesText)
|
||||
} else if(vdata.newPwd !== vdata.sysPassword.confirmPwd) {
|
||||
return Promise.reject('新密码与确认密码不一致')
|
||||
} else return Promise.resolve()
|
||||
} else {
|
||||
return Promise.resolve()
|
||||
}
|
||||
}
|
||||
}] // 确认新密码
|
||||
})
|
||||
function getPasswordRules () { // 获取密码规则
|
||||
$getPasswordRules().then(res => {
|
||||
vdata.passwordRules = new RegExp(res.regexpRules)
|
||||
vdata.passwordRulesText = res.errTips
|
||||
})
|
||||
}
|
||||
defineExpose({show})
|
||||
function show (recordId) { // 弹层打开事件
|
||||
getPasswordRules()
|
||||
if (infoFormModel.value !== undefined) {
|
||||
infoFormModel.value.resetFields()
|
||||
}
|
||||
|
||||
vdata.isAdd = !recordId
|
||||
// 数据恢复为默认数据
|
||||
vdata.saveObject = {isAdmin: 1, state: 1, sex: 1, passwordType: 'default', isNotify: 0, userType: 1, isTeamLeader: 0}
|
||||
rules.loginUsername = []
|
||||
vdata.confirmLoading = false // 关闭loading
|
||||
|
||||
req.list(API_URL_SYS_USER_TEAM_LIST, { 'pageSize': -1 }).then(res => { // 团队下拉选择列表
|
||||
vdata.teamList = res.records
|
||||
})
|
||||
|
||||
if (vdata.isAdd) {
|
||||
rules.loginUsername.push({
|
||||
required: true,
|
||||
pattern: /^[a-zA-Z][a-zA-Z0-9]{5,17}$/,
|
||||
message: '请输入字母开头,长度为6-18位的登录名',
|
||||
trigger: 'blur'
|
||||
})
|
||||
}
|
||||
|
||||
if (!vdata.isAdd) { // 修改信息 延迟展示弹层
|
||||
vdata.resetIsShow = true // 展示重置密码板块
|
||||
vdata.recordId = recordId
|
||||
req.getById(API_URL_SYS_USER_LIST, recordId).then(res => { vdata.saveObject = res })
|
||||
vdata.isShow = true
|
||||
} else {
|
||||
vdata.isShow = true // 立马展示弹层信息
|
||||
}
|
||||
}
|
||||
function handleOkFunc () { // 点击【确认】按钮事件
|
||||
infoFormModel.value.validate().then(valid=>{
|
||||
vdata.loading = true // 打开按钮上的 loading
|
||||
vdata.confirmLoading = true // 显示loading
|
||||
if (vdata.isAdd) {
|
||||
if(vdata.saveObject.passwordType == 'default' || !vdata.saveObject.loginPassword) {
|
||||
vdata.saveObject.loginPassword = ''
|
||||
}
|
||||
if(vdata.saveObject.passwordType == 'custom' && !vdata.passwordRules.test(vdata.saveObject.loginPassword)) {
|
||||
vdata.confirmLoading = false
|
||||
return message.error(vdata.passwordRulesText)
|
||||
}
|
||||
req.add(API_URL_SYS_USER_LIST, vdata.saveObject).then(res => {
|
||||
message.success('新增成功')
|
||||
vdata.isShow = false
|
||||
vdata.loading = false
|
||||
props.callbackFunc() // 刷新列表
|
||||
}).catch((res) => {
|
||||
vdata.confirmLoading = false
|
||||
})
|
||||
} else {
|
||||
vdata.sysPassword.confirmPwd = Base64.encode(vdata.sysPassword.confirmPwd)
|
||||
Object.assign(vdata.saveObject, vdata.sysPassword) // 拼接对象
|
||||
console.log(vdata.saveObject)
|
||||
req.updateById(API_URL_SYS_USER_LIST, vdata.recordId, vdata.saveObject).then(res => {
|
||||
message.success('修改成功')
|
||||
vdata.isShow = false
|
||||
props.callbackFunc() // 刷新列表
|
||||
vdata.resetIsShow = false // 取消展示
|
||||
vdata.sysPassword.resetPass = false
|
||||
vdata.sysPassword.defaultPass = true// 是否使用默认密码默认为true
|
||||
resetPassEmpty(vdata) // 清空密码
|
||||
}).catch(res => {
|
||||
vdata.confirmLoading = false
|
||||
vdata.resetIsShow = false // 取消展示
|
||||
vdata.sysPassword.resetPass = false
|
||||
vdata.sysPassword.defaultPass = true// 是否使用默认密码默认为true
|
||||
resetPassEmpty(vdata) // 清空密码
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
// 关闭抽屉
|
||||
function onClose () {
|
||||
vdata.isShow = false
|
||||
vdata.resetIsShow = false // 取消重置密码板块展示
|
||||
resetPassEmpty(vdata) // 清空密码
|
||||
vdata.sysPassword.resetPass = false // 关闭密码输入
|
||||
vdata.sysPassword.defaultPass = true// 是否使用默认密码默认为true
|
||||
}
|
||||
// 使用默认密码重置是否为true
|
||||
function isResetPass () {
|
||||
if (!vdata.sysPassword.defaultPass) {
|
||||
vdata.newPwd = ''
|
||||
vdata.sysPassword.confirmPwd = ''
|
||||
}
|
||||
}
|
||||
// 保存后清空密码
|
||||
function resetPassEmpty (that) {
|
||||
vdata.newPwd = ''
|
||||
vdata.sysPassword.confirmPwd = ''
|
||||
}
|
||||
|
||||
// 切换操作员类型
|
||||
function changeUserType() {
|
||||
if (vdata.saveObject.userType == 1 || vdata.saveObject.userType == 2) {
|
||||
vdata.saveObject.isTeamLeader = 0
|
||||
vdata.saveObject.teamId = ''
|
||||
}
|
||||
}
|
||||
|
||||
function randomPassage(randomFlag, min, max) { // 生成6位随机密码
|
||||
let str = ''
|
||||
let range = min
|
||||
const arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
|
||||
// 随机产生
|
||||
if (randomFlag) {
|
||||
range = Math.round(Math.random() * (max - min)) + min
|
||||
}
|
||||
for (var i = 0; i < range; i++) {
|
||||
var pos = Math.round(Math.random() * (arr.length - 1))
|
||||
str += arr[ pos ]
|
||||
}
|
||||
vdata.saveObject['loginPassword'] = str
|
||||
}
|
||||
</script>
|
||||
150
jeepay-ui-agent/src/views/sysuser/Detail.vue
Normal file
150
jeepay-ui-agent/src/views/sysuser/Detail.vue
Normal file
@@ -0,0 +1,150 @@
|
||||
<template>
|
||||
<a-drawer
|
||||
v-model:visible="vdata.visible"
|
||||
:title=" true ? '操作员详情' : '' "
|
||||
:body-style="{ paddingBottom: '80px' }"
|
||||
width="40%"
|
||||
@close="onClose"
|
||||
>
|
||||
<a-row justify="space-between" type="flex">
|
||||
<a-col :sm="12">
|
||||
<a-descriptions>
|
||||
<a-descriptions-item label="姓名">
|
||||
{{ vdata.detailData.realname }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-col>
|
||||
<a-col :sm="12">
|
||||
<a-descriptions>
|
||||
<a-descriptions-item label="手机号">
|
||||
{{ vdata.detailData.telphone }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-col>
|
||||
<a-col :sm="12">
|
||||
<a-descriptions>
|
||||
<a-descriptions-item label="登录名">
|
||||
{{ vdata.detailData.loginUsername }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-col>
|
||||
<a-col :sm="12">
|
||||
<a-descriptions>
|
||||
<a-descriptions-item label="编号">
|
||||
{{ vdata.detailData.userNo }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-col>
|
||||
<a-col :sm="12">
|
||||
<a-descriptions>
|
||||
<a-descriptions-item label="所属团队">
|
||||
{{ vdata.detailData.teamName || '无' }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-col>
|
||||
<a-col v-if="vdata.detailData.teamId" :sm="12">
|
||||
<a-descriptions>
|
||||
<a-descriptions-item label="是否队长">
|
||||
{{ vdata.detailData.isTeamLeader === 1 ? '是' : '否' }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-col>
|
||||
<a-col :sm="12">
|
||||
<a-descriptions>
|
||||
<a-descriptions-item label="拓展员性别">
|
||||
{{ vdata.detailData.sex === 1 ? '男' : vdata.detailData.sex === 2 ? '女' : '未知' }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-col>
|
||||
<a-col :sm="12">
|
||||
<a-descriptions>
|
||||
<a-descriptions-item label="状态">
|
||||
<a-tag :color="vdata.detailData['state'] === 1?'green':'volcano'">
|
||||
{{ vdata.detailData.state === 0?'禁用':vdata.detailData.state === 1?'启用':'未知' }}
|
||||
</a-tag>
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-col>
|
||||
<a-col :sm="12">
|
||||
<a-descriptions>
|
||||
<a-descriptions-item label="创建时间">
|
||||
{{ vdata.detailData.createdAt }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-divider orientation="left" v-if="vdata.detailData.userType === 3">
|
||||
<a-tag color="green">
|
||||
数据统计
|
||||
</a-tag>
|
||||
</a-divider>
|
||||
<a-tabs v-model:activeKey="vdata.activeKey" @change="changeDateTime" v-if="vdata.detailData.userType === 3">
|
||||
<a-tab-pane key="currMonth" tab="本月"><StatDetail :data="vdata.statData" /></a-tab-pane>
|
||||
<a-tab-pane key="prevMonth" tab="上月"><StatDetail :data="vdata.statData" /></a-tab-pane>
|
||||
<a-tab-pane key="today" tab="今天"><StatDetail :data="vdata.statData" /></a-tab-pane>
|
||||
<a-tab-pane key="yesterday" tab="昨天"><StatDetail :data="vdata.statData" /></a-tab-pane>
|
||||
<a-tab-pane key="customDateTime" tab="自定义">
|
||||
<a-range-picker v-model:value="vdata.customDateTimeValue" show-time @change="customDateTimeChange" />
|
||||
<StatDetail :data="vdata.statData" />
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { API_URL_SYS_USER_LIST, req, $userChart } from '@/api/manage'
|
||||
import { defineProps, reactive, toRaw } from 'vue'
|
||||
import StatDetail from './StatDetail.vue'
|
||||
|
||||
const props = defineProps({
|
||||
callbackFunc: { type: Function,default:null }
|
||||
})
|
||||
|
||||
const vdata = reactive({
|
||||
btnLoading: false,
|
||||
detailData: {} as any, // 数据对象
|
||||
recordId: null, // 更新对象ID
|
||||
visible: false, // 是否显示弹层/抽屉
|
||||
activeKey: 'currMonth',
|
||||
customDateTimeValue: [] as any, // 自定义时间
|
||||
statData: {} // 拓展员统计数据
|
||||
})
|
||||
|
||||
function show (recordId) { // 弹层打开事件
|
||||
vdata.recordId = recordId
|
||||
|
||||
req.getById(API_URL_SYS_USER_LIST, recordId).then(res => {
|
||||
vdata.detailData = res
|
||||
})
|
||||
vdata.visible = true
|
||||
|
||||
changeDateTime()
|
||||
}
|
||||
|
||||
function onClose () {
|
||||
vdata.visible = false
|
||||
}
|
||||
|
||||
function changeDateTime() {
|
||||
if (vdata.activeKey != 'customDateTime') {
|
||||
$userChart(vdata.recordId, vdata.activeKey).then(res => {
|
||||
vdata.statData = res
|
||||
})
|
||||
}else {
|
||||
customDateTimeChange()
|
||||
}
|
||||
}
|
||||
|
||||
function customDateTimeChange() {
|
||||
if (vdata.customDateTimeValue) {
|
||||
const queryDateRange = 'customDateTime_' + vdata.customDateTimeValue[0].format('YYYY-MM-DD HH:mm:ss') + '_' + vdata.customDateTimeValue[1].format('YYYY-MM-DD HH:mm:ss')
|
||||
$userChart(vdata.recordId, queryDateRange).then(res => {
|
||||
vdata.statData = res
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
show //抛出show函数给父组件
|
||||
})
|
||||
</script>
|
||||
107
jeepay-ui-agent/src/views/sysuser/RoleDist.vue
Normal file
107
jeepay-ui-agent/src/views/sysuser/RoleDist.vue
Normal file
@@ -0,0 +1,107 @@
|
||||
<template>
|
||||
<a-drawer
|
||||
v-model:visible="vdata.isShow"
|
||||
title="分配角色"
|
||||
width="30%"
|
||||
:mask-closable="true"
|
||||
@close="vdata.isShow = false"
|
||||
>
|
||||
<div>
|
||||
<div :style="{ borderBottom: '1px solid #E9E9E9' }">
|
||||
<a-checkbox
|
||||
:checked="vdata.checkedVal.length != 0 && vdata.allRoleList.length === vdata.checkedVal.length"
|
||||
:indeterminate="vdata.checkedVal.length != 0 && vdata.allRoleList.length != vdata.checkedVal.length"
|
||||
@change="onCheckAllChange"
|
||||
>
|
||||
全选
|
||||
</a-checkbox>
|
||||
</div>
|
||||
<br>
|
||||
<a-checkbox-group v-model:value="vdata.checkedVal" :options="vdata.allRoleList" />
|
||||
</div>
|
||||
|
||||
<div class="drawer-btn-center">
|
||||
<a-button :style="{ marginRight: '8px' }" @click="vdata.isShow = false">
|
||||
<close-outlined />
|
||||
取消
|
||||
</a-button>
|
||||
<a-button type="primary" :loading="vdata.confirmLoading" @click="handleOkFunc">
|
||||
<check-outlined />
|
||||
保存
|
||||
</a-button>
|
||||
</div>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { $uSysUserRoleRela, req, reqLoad, API_URL_ROLE_LIST, API_URL_USER_ROLE_RELA_LIST } from '@/api/manage'
|
||||
import {ref,reactive} from 'vue'
|
||||
import {message} from 'ant-design-vue'
|
||||
|
||||
const props =defineProps({
|
||||
callbackFunc: { type: Function,default:null }
|
||||
})
|
||||
|
||||
|
||||
const vdata = reactive ({
|
||||
confirmLoading: false, // 显示确定按钮loading图标
|
||||
isShow: false, // 是否显示弹层/抽屉
|
||||
recordId: null, // 更新对象ID
|
||||
|
||||
allRoleList: []as any[], // 全部的角色集合 {label: '', value: ''}
|
||||
checkedVal: []as any[] // 已选择的数据集合
|
||||
})
|
||||
|
||||
|
||||
defineExpose({show})
|
||||
function show (recordId) { // 弹层打开事件
|
||||
// 重置数据
|
||||
vdata.allRoleList = []
|
||||
vdata.checkedVal = []
|
||||
vdata.confirmLoading = false // 关闭loading
|
||||
vdata.recordId = recordId
|
||||
|
||||
// 查询所有角色列表
|
||||
reqLoad.list(API_URL_ROLE_LIST, { pageSize: -1 }).then(res => {
|
||||
if (res.total <= 0) {
|
||||
return message.error(`当前暂无角色,请先行添加`)
|
||||
}
|
||||
|
||||
vdata.allRoleList = []
|
||||
res.records.map(role => {
|
||||
vdata.allRoleList.push({ label: role.roleName, value: role.roleId })
|
||||
vdata.isShow = true
|
||||
})
|
||||
|
||||
// 查询已分配的列表
|
||||
req.list(API_URL_USER_ROLE_RELA_LIST, { pageSize: -1, userId: recordId }).then(relaRes => {
|
||||
relaRes.records.map(rela => {
|
||||
vdata.checkedVal.push(rela.roleId)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function handleOkFunc () { // 点击【确认】按钮事件
|
||||
|
||||
|
||||
vdata.confirmLoading = true // 显示loading
|
||||
$uSysUserRoleRela(vdata.recordId, vdata.checkedVal).then(res => {
|
||||
message.success('更新成功!')
|
||||
vdata.isShow = false
|
||||
|
||||
if (props.callbackFunc !== undefined) {
|
||||
props.callbackFunc() // 刷新列表
|
||||
}
|
||||
}).catch(res => { vdata.confirmLoading = false }) // 恢复loading
|
||||
}
|
||||
|
||||
function onCheckAllChange (e) { // 点击全选/非全选的状态更改
|
||||
|
||||
|
||||
vdata.checkedVal = []
|
||||
if (e.target.checked) { // 全选
|
||||
vdata.allRoleList.map(role => { vdata.checkedVal.push(role.value) })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
32
jeepay-ui-agent/src/views/sysuser/StatDetail.vue
Normal file
32
jeepay-ui-agent/src/views/sysuser/StatDetail.vue
Normal file
@@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<a-row>
|
||||
<a-col :span="8">
|
||||
<a-statistic title="商户总数" :value="data.mchAllCount" style="margin-right: 50px" />
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-statistic title="新增商户数" :value="data.mchTodayAddCount" />
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-statistic title="商户交易总额" :precision="2" :value="(data.payAllAmount/100).toFixed(2)" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row style="margin-top: 30px;">
|
||||
<a-col :span="8">
|
||||
<a-statistic title="入网商户总数" :value="data.mchOnNetCount" style="margin-right: 50px" />
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-statistic title="新增入网商户数" :value="data.mchOnNetNewCount" />
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-statistic title="商户交易额" :precision="2" :value="(data.payAmount/100).toFixed(2)" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { defineProps, reactive } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
data: { type: Object, default:null }
|
||||
})
|
||||
</script>
|
||||
261
jeepay-ui-agent/src/views/sysuser/SysUserPage.vue
Normal file
261
jeepay-ui-agent/src/views/sysuser/SysUserPage.vue
Normal file
@@ -0,0 +1,261 @@
|
||||
<template>
|
||||
<page-header-wrapper>
|
||||
<a-card>
|
||||
<JeepaySearchForm v-if="$access('ENT_UR_ROLE_SEARCH')" :searchConditionNum="6" :searchFunc="searchFunc" :resetFunc="() => { data.searchData= {} }">
|
||||
<jeepay-text-up v-model:value="data.searchData['sysUserId']" :placeholder="'用户ID'" />
|
||||
<jeepay-text-up v-model:value="data.searchData['realname']" :placeholder="'用户姓名'" />
|
||||
<jeepay-text-up v-model:value="data.searchData['telphone']" :placeholder="'用户手机号'" />
|
||||
<a-form-item label="" class="table-search-item">
|
||||
<a-select v-model:value="data.searchData['userType']" placeholder="操作员类型">
|
||||
<a-select-option value="">全部</a-select-option>
|
||||
<a-select-option value="1">超级管理员</a-select-option>
|
||||
<a-select-option value="2">普通操作员</a-select-option>
|
||||
<a-select-option value="3">商户扩展员</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</JeepaySearchForm>
|
||||
|
||||
<!-- 列表渲染 -->
|
||||
<JeepayTable
|
||||
ref="infoTable"
|
||||
:init-data="true"
|
||||
:req-table-data-func="reqTableDataFunc"
|
||||
:table-columns="tableColumns"
|
||||
:search-data="data.searchData"
|
||||
row-key="sysUserId"
|
||||
@btnLoadClose="data.btnLoading=false"
|
||||
>
|
||||
<template #topBtnSlot>
|
||||
<div>
|
||||
<a-button
|
||||
v-if="$access('ENT_UR_USER_ADD')"
|
||||
type="primary"
|
||||
class="mg-b-30"
|
||||
@click="addFunc"
|
||||
>
|
||||
<plus-outlined />
|
||||
新建
|
||||
</a-button>
|
||||
</div>
|
||||
</template>
|
||||
<template #bodyCell="{column,record}">
|
||||
<template v-if="column.key === 'avatar'">
|
||||
<a-avatar size="default" :src="record.avatarUrl" />
|
||||
</template>
|
||||
<template v-if="column.key === 'realname'">
|
||||
{{ record.realname }}
|
||||
<a-tag v-if="record.initUser" :key="record.initUser" color="green">
|
||||
初始
|
||||
</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'state'">
|
||||
<JeepayTableColState :state="record.state" :show-switch-type="$access('ENT_UR_USER_EDIT')" :on-change="(state) => { return updateState(record.sysUserId, state)}" />
|
||||
</template>
|
||||
<template v-if="column.key === 'inviteCode'">
|
||||
<span v-if="record.userType == 1 || record.userType == 3">
|
||||
<a-button v-clipboard:copy="record.inviteCode" v-clipboard:success="() => $infoBox.message.success('邀请码已复制')" type="link" size="small">{{ record.inviteCode }}</a-button>
|
||||
<info-circle-outlined style="cursor: pointer;" @click="showQrImgFunc(record)" />
|
||||
</span>
|
||||
<span v-else />
|
||||
</template>
|
||||
|
||||
<template v-if="column.key === 'sex'">
|
||||
<span v-if="record.sex == 1">男</span>
|
||||
<span v-else-if="record.sex == 2">女</span>
|
||||
<span v-else>未知</span>
|
||||
</template>
|
||||
|
||||
<template v-if="column.key === 'userType'">
|
||||
<span v-if="record.userType == 1">超级管理员</span>
|
||||
<span v-else-if="record.userType == 2">普通操作员</span>
|
||||
<span v-else-if="record.userType == 3">商户拓展员</span>
|
||||
<span v-else>其他</span>
|
||||
</template>
|
||||
|
||||
<template v-if="column.key === 'op'">
|
||||
<!-- 操作列插槽 -->
|
||||
<JeepayTableColumns>
|
||||
<a-button v-if="$access('ENT_UR_USER_VIEW')" type="link" @click="detailFunc(record.sysUserId)">详情</a-button>
|
||||
<a-button v-if="$access('ENT_UR_USER_UPD_ROLE') && record.userType == 2" type="link" @click="roleDistFun(record.sysUserId)">变更角色</a-button>
|
||||
<a-button v-if="$access('ENT_UR_USER_EDIT')" type="link" @click="editFunc(record.sysUserId)">修改</a-button>
|
||||
<a-button v-if="$access('ENT_UR_USER_MFA_DELETE') && (userStore.userInfo['userType'] == '1' && record.mfaBindState == '1')" style="color: red;" type="link" @click="mfaRelieve(record.sysUserId)">MFA解绑</a-button>
|
||||
<a-button v-if="$access('ENT_UR_USER_LOGIN_LIMIT_DELETE')" style="color: red;" type="link" @click="deleteLoginLimit(record.sysUserId)">解除登录限制</a-button>
|
||||
<a-button v-if="$access('ENT_UR_USER_DELETE')" type="link" style="color: red;margin-right: 20px;" @click="delFunc(record.sysUserId)">删除</a-button>
|
||||
</JeepayTableColumns>
|
||||
</template>
|
||||
</template>
|
||||
</JeepayTable>
|
||||
</a-card>
|
||||
|
||||
<a-modal v-model:visible="data.codeVisible" title="邀请码" :footer="null" :width="600" @ok="() => data.codeVisible = false">
|
||||
<div v-if="!data.inviteCode">
|
||||
<span>无邀请码</span>
|
||||
<a-button type="link" @click="setInviteCodeFunc(data.sysUserId)">点此修复</a-button>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div>
|
||||
<span>邀请码:{{ data.inviteCode }}</span>
|
||||
<a-button v-clipboard:copy="data.inviteCode" v-clipboard:success="() => $infoBox.message.success('邀请码已复制')" type="link">复制</a-button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<span>商户注册链接:{{ data.inviteCodeUrl }}</span>
|
||||
<a-button v-clipboard:copy="data.inviteCodeUrl" v-clipboard:success="() => $infoBox.message.success('复制成功')" type="link">复制</a-button>
|
||||
</div>
|
||||
<div>
|
||||
<span>商户注册二维码:</span>
|
||||
<div style="padding: 20px 0 20px 50px;"><QrcodeVue :value="data.inviteCodeUrl" :size="200" /></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="data.sysType == 'PLATFORM' || data.sysType == 'AGENT'">
|
||||
<div>
|
||||
<span>代理商注册链接:{{ data.agentInviteCodeUrl }}</span>
|
||||
<a-button v-clipboard:copy="data.agentInviteCodeUrl" v-clipboard:success="() => $infoBox.message.success('复制成功')" type="link">复制</a-button>
|
||||
</div>
|
||||
<div>
|
||||
<span>代理商注册二维码:</span>
|
||||
<div style="padding: 20px 0 20px 50px;"><QrcodeVue :value="data.agentInviteCodeUrl" :size="200" /></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-modal>
|
||||
|
||||
<!-- 新增 / 修改 页面组件 -->
|
||||
<InfoAddOrEdit ref="infoAddOrEdit" :callback-func="searchFunc" />
|
||||
|
||||
<!-- 分配角色 页面组件 -->
|
||||
<RoleDist ref="roleDist" />
|
||||
|
||||
<!-- 详情页面组件 -->
|
||||
<InfoDetail ref="infoDetail" :callback-func="searchFunc" />
|
||||
</page-header-wrapper>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { API_URL_SYS_USER_LIST, req, reqLoad, $deleteLoginLimit } from '@/api/manage'
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
import InfoAddOrEdit from './AddOrEdit.vue'
|
||||
import RoleDist from './RoleDist.vue'
|
||||
import InfoDetail from './Detail.vue'
|
||||
import QrcodeVue from 'qrcode.vue'
|
||||
import { reactive,ref,getCurrentInstance} from 'vue'
|
||||
const { $infoBox,$access } = getCurrentInstance()!.appContext.config.globalProperties
|
||||
const userStore = useUserStore()
|
||||
|
||||
const tableColumns = reactive([
|
||||
{key:'avatar',title: '头像', },
|
||||
{key:'realname', title: '姓名', dataIndex: 'realname' },
|
||||
{key:'sysUserId', title: '用户ID', dataIndex: 'sysUserId',},
|
||||
{key:'sex', title: '性别', dataIndex: 'sex',},
|
||||
{key:'userNo', title: '编号', dataIndex: 'userNo', },
|
||||
{key:'telphone', title: '手机号', dataIndex: 'telphone', },
|
||||
{key:'userType' ,title: '操作员类型', dataIndex: 'userType', },
|
||||
{key:'teamName' ,title: '团队', dataIndex: 'teamName' },
|
||||
{key:'inviteCode' ,title: '邀请码', dataIndex: 'inviteCode', },
|
||||
{key:'state', title: '状态', align: 'center' ,},
|
||||
{key:'createdAt', title: '创建时间', dataIndex: 'createdAt',},
|
||||
{key: 'op',title: '操作', fixed: 'right',align: 'center' }
|
||||
])
|
||||
|
||||
const infoTable = ref()
|
||||
const infoAddOrEdit =ref()
|
||||
const infoDetail = ref()
|
||||
const roleDist = ref()
|
||||
const data : any =reactive ({
|
||||
tableColumns: tableColumns,
|
||||
searchData: {},
|
||||
btnLoading: false
|
||||
})
|
||||
|
||||
// 请求table接口数据
|
||||
function reqTableDataFunc(params){
|
||||
return req.list(API_URL_SYS_USER_LIST, params)
|
||||
}
|
||||
|
||||
function searchFunc() { // 点击【查询】按钮点击事件
|
||||
data.btnLoading = true // 打开查询按钮的loading
|
||||
infoTable.value.refTable(true)
|
||||
}
|
||||
|
||||
function addFunc () { // 业务通用【新增】 函数
|
||||
infoAddOrEdit.value.show()
|
||||
}
|
||||
|
||||
function editFunc (recordId) { // 业务通用【修改】 函数
|
||||
console.log(infoAddOrEdit)
|
||||
infoAddOrEdit.value.show(recordId)
|
||||
}
|
||||
|
||||
function detailFunc (recordId: any) { // 商户详情页
|
||||
infoDetail.value.show(recordId)
|
||||
}
|
||||
function setInviteCodeFunc (recordId: any) { // 修复邀请码
|
||||
return req.updateById(API_URL_SYS_USER_LIST, recordId, { setInviteCode: true }).then(res => {
|
||||
$infoBox.message.success('修复成功')
|
||||
console.log(res)
|
||||
showQrImgFunc(res)
|
||||
infoTable.value.refTable(false)
|
||||
})
|
||||
}
|
||||
|
||||
function delFunc(recordId) { // 业务通用【删除】 函数
|
||||
$infoBox.confirmDanger('确认删除?', '', () => {
|
||||
return req.delById(API_URL_SYS_USER_LIST, recordId).then(res => {
|
||||
$infoBox.message.success('删除成功!')
|
||||
infoTable.value.refTable(false)
|
||||
})
|
||||
})
|
||||
}
|
||||
function roleDistFun(recordId) { // 【分配权限】 按钮点击事件
|
||||
roleDist.value.show(recordId)
|
||||
}
|
||||
|
||||
function updateState (recordId, state) { // 【更新状态】
|
||||
const title = state === 1 ? '确认[启用]该用户?' : '确认[停用]该用户?'
|
||||
const content = state === 1 ? '启用后用户可进行登陆等一系列操作' : '停用后该用户将立即退出系统并不可再次登陆'
|
||||
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
$infoBox.confirmDanger(title, content, () => {
|
||||
return reqLoad.updateById(API_URL_SYS_USER_LIST, recordId, { state: state }).then(res => {
|
||||
searchFunc()
|
||||
resolve()
|
||||
}).catch(err => reject(err))
|
||||
},
|
||||
() => {
|
||||
reject(new Error())
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 显示二维码图片
|
||||
function showQrImgFunc(record){
|
||||
data.codeVisible = true
|
||||
data.inviteCodeUrl = record.inviteCodeUrl
|
||||
data.inviteCode = record.inviteCode
|
||||
data.agentInviteCodeUrl = record.agentInviteCodeUrl
|
||||
data.sysUserId = record.sysUserId
|
||||
data.sysType = record.sysType
|
||||
}
|
||||
function onCopySuccess () {
|
||||
$infoBox.message.success('复制成功')
|
||||
}
|
||||
|
||||
function mfaRelieve(recordId) { // MFA解绑
|
||||
$infoBox.confirmDanger('确认解绑吗?', '', () => {
|
||||
return req.updateById(API_URL_SYS_USER_LIST, 'mfaRelieve', {recordId: recordId}).then(res => {
|
||||
$infoBox.message.success('解绑成功!')
|
||||
infoTable.value.refTable(false)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function deleteLoginLimit(recordId) { // 解除登录限制
|
||||
$infoBox.confirmDanger('确认解除吗?', '', () => {
|
||||
return $deleteLoginLimit(recordId).then(res => {
|
||||
$infoBox.message.success('解除成功!')
|
||||
infoTable.value.refTable(false)
|
||||
})
|
||||
})
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user