Commit 73e3efe9 authored by zhengke's avatar zhengke

导入成员

parent 2e29e609
...@@ -3,6 +3,21 @@ import Api,{ HttpResponse, Result } from './../utils/request'; ...@@ -3,6 +3,21 @@ import Api,{ HttpResponse, Result } from './../utils/request';
class UserServices{ class UserServices{
static async setMyNickNamed(nk:string):Promise<HttpResponse>{
let msg = {nk}
return Api.Post("travel_SetMyNickName",msg)
}
static async setModifyUserPwd(oldpwd:Number,pwd:Number):Promise<HttpResponse>{
let msg = {oldpwd,pwd}
return Api.Post("travel_ModifyUserPwd",msg)
}
static async setBindUserEmail(mail:string,code:Number):Promise<HttpResponse>{
let msg = {mail,code}
return Api.Post("travel_BindUserEmail",msg)
}
static async AutoLoginAsync(t:string):Promise<HttpResponse>{ static async AutoLoginAsync(t:string):Promise<HttpResponse>{
let msg = {t} let msg = {t}
return Api.Post("travel_auto_login",msg) return Api.Post("travel_auto_login",msg)
......
...@@ -36,23 +36,65 @@ ...@@ -36,23 +36,65 @@
<template #default="scope"> <template #default="scope">
<div class="row items-center"> <div class="row items-center">
<el-avatar shape="square" :src="scope.row.photo.includes('http://')||scope.row.photo.includes('https://')?scope.row.photo:USER_DEFAULT_HEADER" :size="32"></el-avatar> <el-avatar shape="square" :src="scope.row.photo.includes('http://')||scope.row.photo.includes('https://')?scope.row.photo:USER_DEFAULT_HEADER" :size="32"></el-avatar>
<div class="col row items-center user-nickname" v-if="editorTarget!=scope.row.id"> <div class="col row items-center user-nickname" v-if="editorTarget!=scope.row.id||editorIndex!=0">
<span class="q-ml-md"> <span class="q-ml-md">
{{ scope.row.name }} {{ scope.row.ism?'(我自己)':'' }} {{ scope.row.name }} {{ scope.row.ism?'(我自己)':'' }}
</span> </span>
<IconPencli size="14" style="color:#000;" class="q-ml-md cusor-pointer editor-pencli" @click="setNickNameHandler(scope.row)"></IconPencli> <IconPencli size="14" style="color:#000;" class="q-ml-md cusor-pointer editor-pencli" @click="setNickNameHandler(scope.row,0)"></IconPencli>
</div> </div>
<div class="col row items-center" v-else> <div class="col row items-center" v-else>
<el-input v-model="nickNameModel" placeholder="请输入用户昵称" size="small" class="col q-ml-md" /> <el-input v-model="nickNameModel" placeholder="请输入用户昵称" size="small" class="col q-ml-md" />
<el-button link size="small" class="q-ml-sm" type="primary" @click="setMemberNickName(scope.row)">确认</el-button> <el-button link size="small" class="q-ml-sm" type="primary" @click="setMemberNickName(scope.row,0)">确认</el-button>
<el-button link size="small" style="margin-left: 5px;" @click="setNickNameHandler">取消</el-button> <el-button link size="small" style="margin-left: 5px;" @click="setNickNameHandler">取消</el-button>
</div> </div>
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="account" label="账号" width="200" /> <el-table-column prop="" label="账号" width="200">
<el-table-column prop="mail" label="邮箱" /> <template #default="scope">
<el-table-column prop="mobile" label="手机号" /> <div class="col row items-center user-nickname" v-if="editorTarget!=scope.row.id||editorIndex!=1">
<span class="q-ml-md">
{{ scope.row.account }}
</span>
<IconPencli size="14" style="color:#000;" class="q-ml-md cusor-pointer editor-pencli" @click="setNickNameHandler(scope.row,1)"></IconPencli>
</div>
<div class="col row items-center" v-else>
<el-input v-model="nickNameModel" placeholder="请输入账号" size="small" class="col q-ml-md" />
<el-button link size="small" class="q-ml-sm" type="primary" @click="setMemberNickName(scope.row,1)">确认</el-button>
<el-button link size="small" style="margin-left: 5px;" @click="setNickNameHandler">取消</el-button>
</div>
</template>
</el-table-column>
<el-table-column prop="" label="邮箱">
<template #default="scope">
<div class="col row items-center user-nickname" v-if="editorTarget!=scope.row.id||editorIndex!=2">
<span class="q-ml-md">
{{ scope.row.mail }}
</span>
<IconPencli size="14" style="color:#000;" class="q-ml-md cusor-pointer editor-pencli" @click="setNickNameHandler(scope.row,2)"></IconPencli>
</div>
<div class="col row items-center" v-else>
<el-input v-model="nickNameModel" placeholder="请输入邮箱" size="small" class="col q-ml-md" />
<el-button link size="small" class="q-ml-sm" type="primary" @click="setMemberNickName(scope.row,2)">确认</el-button>
<el-button link size="small" style="margin-left: 5px;" @click="setNickNameHandler">取消</el-button>
</div>
</template>
</el-table-column>
<el-table-column prop="" label="手机号">
<template #default="scope">
<div class="col row items-center user-nickname" v-if="editorTarget!=scope.row.id||editorIndex!=3">
<span class="q-ml-md">
{{ scope.row.mobile }}
</span>
<IconPencli size="14" style="color:#000;" class="q-ml-md cusor-pointer editor-pencli" @click="setNickNameHandler(scope.row,3)"></IconPencli>
</div>
<div class="col row items-center" v-else>
<el-input v-model="nickNameModel" placeholder="请输入手机号" size="small" class="col q-ml-md" />
<el-button link size="small" class="q-ml-sm" type="primary" @click="setMemberNickName(scope.row,3)">确认</el-button>
<el-button link size="small" style="margin-left: 5px;" @click="setNickNameHandler">取消</el-button>
</div>
</template>
</el-table-column>
<el-table-column prop="" label="系统角色" width="180"> <el-table-column prop="" label="系统角色" width="180">
<template #default="scope"> <template #default="scope">
<span v-if="scope.row.ic">超级管理员</span> <span v-if="scope.row.ic">超级管理员</span>
...@@ -145,6 +187,7 @@ const pageCount = ref(0) ...@@ -145,6 +187,7 @@ const pageCount = ref(0)
const used = ref<number[]>([0,0]) const used = ref<number[]>([0,0])
const memberListRef = ref() const memberListRef = ref()
const editorTarget = ref('') const editorTarget = ref('')
const editorIndex = ref(0)
const nickNameModel = ref('') const nickNameModel = ref('')
const removeVisible = ref(false) const removeVisible = ref(false)
const removeTokenStr = ref('') const removeTokenStr = ref('')
...@@ -163,13 +206,18 @@ const parameters = ref<any>({ ...@@ -163,13 +206,18 @@ const parameters = ref<any>({
pageIndex:1, pageIndex:1,
pageSize:20 pageSize:20
}) })
const setNickNameHandler = (target:any) =>{ const setNickNameHandler = (target:any,type:number) =>{
editorIndex.value = type
if(target){ if(target){
editorTarget.value = target.id editorTarget.value = target.id
nickNameModel.value = target.name if(type==0) nickNameModel.value = target.name
if(type==1) nickNameModel.value = target.account
if(type==2) nickNameModel.value = target.mail
if(type==3) nickNameModel.value = target.mobile
}else{ }else{
editorTarget.value = '' editorTarget.value = ''
nickNameModel.value = '' nickNameModel.value = ''
editorIndex.value = 0
} }
} }
const setSaExchangeHandler = (status:boolean)=>{ const setSaExchangeHandler = (status:boolean)=>{
...@@ -235,11 +283,13 @@ const setMemberManagerStatus = async (target:any,value:0|1)=>{ ...@@ -235,11 +283,13 @@ const setMemberManagerStatus = async (target:any,value:0|1)=>{
loading.value=false loading.value=false
} }
const setMemberNickName = async (target:any)=>{ const setMemberNickName = async (target:any,type:any)=>{
if(loading.value || nickNameModel.value=='') return if(loading.value || nickNameModel.value=='') return
loading.value=true loading.value=true
const response = await UserServices.SetMemberInfoAsync(nickNameModel.value,target.id,-1) let response
if(type==0) response = await UserServices.SetMemberInfoAsync(nickNameModel.value,target.id,-1)
if(response){
if(response.data.resultCode == ApiResult.SUCCESS){ if(response.data.resultCode == ApiResult.SUCCESS){
ElMessage.success({message:'更新成功'}) ElMessage.success({message:'更新成功'})
target.name =nickNameModel.value target.name =nickNameModel.value
...@@ -251,6 +301,7 @@ const setMemberNickName = async (target:any)=>{ ...@@ -251,6 +301,7 @@ const setMemberNickName = async (target:any)=>{
}else{ }else{
ElMessage.error({message:'更新失败'}) ElMessage.error({message:'更新失败'})
} }
}
loading.value=false loading.value=false
} }
......
...@@ -9,9 +9,11 @@ ...@@ -9,9 +9,11 @@
<div class="q-mt-xl q-mb-md row flex-center items-center" style="height:26px;"> <div class="q-mt-xl q-mb-md row flex-center items-center" style="height:26px;">
<template v-if="!isEditorNickname"> <template v-if="!isEditorNickname">
<div>{{ userInfo.nickname }}</div> <div>{{ userInfo.nickname }}</div>
<IconWrite :size="16" class="q-ml-md cusor-pointer" @click="()=>editorNicknameHandler(nicknameRef)"></IconWrite> <IconWrite :size="16" class="q-ml-md cusor-pointer"
@click="()=>editorNicknameHandler(nicknameRef,0)"></IconWrite>
</template> </template>
<input type="text" ref="nicknameRef" class="nickname" v-model="userInfo.nickname" :autofocus="true" v-show="isEditorNickname" @blur="()=>isEditorNickname=false"> <input type="text" ref="nicknameRef" class="nickname"
v-model="userInfo.nickname" :autofocus="true" v-show="isEditorNickname" @blur="()=>{isEditorNickname=false,bindHandler()}">
</div> </div>
<div class="text-small text-info text-center">用户ID:9020345764199812103</div> <div class="text-small text-info text-center">用户ID:9020345764199812103</div>
<div class="q-mt-lg setting-body rounded"> <div class="q-mt-lg setting-body rounded">
...@@ -27,7 +29,7 @@ ...@@ -27,7 +29,7 @@
<div class="text-dark">邮箱</div> <div class="text-dark">邮箱</div>
<div class="">绑定邮箱后,可以更方便的登录、管理稿定账号</div> <div class="">绑定邮箱后,可以更方便的登录、管理稿定账号</div>
</div> </div>
<el-button>立即绑定</el-button> <el-button @click="bindDatas(1)">立即绑定</el-button>
</div> </div>
<!-- <div class="setting-item"> <!-- <div class="setting-item">
<div> <div>
...@@ -48,7 +50,7 @@ ...@@ -48,7 +50,7 @@
<div class="text-dark">密码</div> <div class="text-dark">密码</div>
<div class="">已设置</div> <div class="">已设置</div>
</div> </div>
<el-button>更换密码</el-button> <el-button @click="bindDatas(2)">更换密码</el-button>
</div> </div>
</div> </div>
<div class="q-mt-lg setting-body rounded"> <div class="q-mt-lg setting-body rounded">
...@@ -61,13 +63,56 @@ ...@@ -61,13 +63,56 @@
</div> </div>
</div> </div>
</div> </div>
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="344" @close="closeForm">
<el-form ref="bindFormRef" :model="model" :rules="rules" label-width="0px" size="large" class="full-width" :disabled="loading">
<template v-if="dialogType==1">
<el-form-item label="" prop="mail">
<el-input v-model="model.mail" placeholder="邮箱">
<template #suffix>
<el-button link :disabled="!mailRegex.test(model.mail)" :loading="sending"
v-if="!isCountdown" @click="sendVerifyCode">{{ isSend?'重新发送':'发送验证码' }}</el-button>
<template v-else>
<el-countdown title="" format="ss" :value="countValue" value-style="font-size:14px;color:#f89c53;" class="inline q-mx-sm" @finish="()=>isCountdown=false" />s
</template>
</template>
</el-input>
</el-form-item>
<el-form-item label="" prop="code">
<el-input v-model="model.code" placeholder="验证码" />
</el-form-item>
</template>
<template v-if="dialogType==2">
<el-form-item label="" prop="oldpwd">
<el-input v-model="model.oldpwd" type="password" placeholder="原密码" autocomplete="new-password" show-password/>
</el-form-item>
<el-form-item label="" prop="pwd">
<el-input v-model="model.pwd" type="password" placeholder="新密码" autocomplete="new-password" show-password/>
</el-form-item>
</template>
<el-form-item label="">
<vue-hcaptcha ref="invisibleHcaptchaBind" sitekey="46e00e53-ddb2-4e7b-9c51-621534c2f1f5" @verify="verifyHandler"></vue-hcaptcha>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm(bindFormRef)" :loading="loading">
确定{{dialogType==1?'绑定':'更换'}}
</el-button>
</div>
</template>
</el-dialog>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ElMessage, FormInstance, FormRules } from 'element-plus';
import { useUserStore } from "@/store"; import { useUserStore } from "@/store";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
import { nextTick } from "vue"; import { nextTick } from "vue";
import { ref } from "vue"; import { ref, reactive } from "vue";
import { ApiResult } from '@/configs/axios';
import UserServices from '@/services/UserService'
import VueHcaptcha from "@hcaptcha/vue3-hcaptcha";
const useUser = useUserStore() const useUser = useUserStore()
const { userInfo } = storeToRefs(useUser) const { userInfo } = storeToRefs(useUser)
...@@ -75,16 +120,132 @@ const userTheme = useUser.getUserTheme ...@@ -75,16 +120,132 @@ const userTheme = useUser.getUserTheme
const isEditorNickname = ref(false) const isEditorNickname = ref(false)
const nicknameRef=ref<HTMLElement>() const nicknameRef=ref<HTMLElement>()
const pushAdStatus = ref(false) const pushAdStatus = ref(false)
const dialogVisible = ref(false)
const dialogType = ref(null as any)
const dialogTitle = ref('')
const mailRegex = /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(.[a-zA-Z0-9_-]+)+$/
const model = ref({
//account:'',
oldpwd:'',
pwd:'',
mail:'',
code:''
} as any)
const validateToken = ref('')
const invisibleHcaptchaBind = ref<VueHcaptcha|null>(null)
const bindFormRef = ref<FormInstance>()
const loading = ref(false)
const sending = ref(false)
const isSend = ref(false)
const isCountdown = ref(false)
const countValue = ref<number>(0)
const validateMail = (rule:any,value:any,callback:any)=>{
if (value === '') {
callback(new Error('请输入你的邮箱账户'))
} else if (!mailRegex.test(value)) {
callback(new Error("请输入正确的邮箱账户"))
} else {
callback()
}
}
const rules = reactive<FormRules<RuleForm>>({
oldpwd: [
{ required: true, message: '请输入你的原密码', trigger: 'blur' },
{ min: 6,max:20, message: '密码的长度应为6-20位', trigger: 'blur' },
],
pwd:[
{ required: true, message: '请输入你的新密码', trigger: 'blur' },
{ min: 6,max:20, message: '密码的长度应为6-20位', trigger: 'blur' },
],
mail:[
{ validator: validateMail, trigger: 'blur' }
],
code:[
{ required: true, message: '请输入验证码', trigger: 'blur' },
{ min: 6,max:6, message: '验证码应为6位', trigger: 'blur' },
]
})
const editorNicknameHandler = (target:HTMLElement|undefined)=>{ const closeForm = () => {
isEditorNickname.value=true bindFormRef.value.clearValidate()
bindFormRef.value.resetFields()
}
const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate(async (valid) => {
loading.value=true
if (valid) {
if (invisibleHcaptchaBind.value && validateToken.value == '') {
invisibleHcaptchaBind.value.execute()
loading.value=false
return
}
await bindHandler()
}
loading.value=false
})
}
const bindHandler = async () =>{
let response
if(dialogType.value==0) response = await UserServices.setMyNickNamed(userInfo.value.nickname)
if(dialogType.value==1) response = await UserServices.setBindUserEmail(model.value.mail,model.value.code)
if(dialogType.value==2) response = await UserServices.setModifyUserPwd(model.value.oldpwd,model.value.pwd)
if(response){
if(response.data.resultCode == ApiResult.SUCCESS){
if(dialogType.value==1) ElMessage.success({message:'绑定邮箱成功'})
if(dialogType.value==2) ElMessage.success({message:'更换密码成功'})
dialogVisible.value = false
dialogType.value = null
return
}
ElMessage.error({message:response.data.message})
invisibleHcaptchaBind.value?.reset()
validateToken.value=''
}
}
// 发送邮箱验证码
const sendVerifyCode = async () => {
if(!mailRegex.test(model.value.mail) || sending.value) return
sending.value= true
const response = await UserServices.SendRegistCodeAsync(model.value.mail)
if(response.data.resultCode == ApiResult.SUCCESS){
ElMessage.success({message:'验证码已发送,请前往邮箱查看'})
isCountdown.value = true
countValue.value = Date.now() + 1000 * 60
isSend.value = true
} else {
ElMessage.error({message:response.data.message})
}
sending.value= false
}
const bindDatas = (type:Number) =>{
dialogType.value = type
if(type==1) dialogTitle.value = '绑定邮箱'
if(type==2) dialogTitle.value = '更换密码'
dialogVisible.value = true
}
const editorNicknameHandler = (target:HTMLElement|undefined,type:Number)=>{
dialogType.value = type
isEditorNickname.value=true
nextTick(()=>{ nextTick(()=>{
if(target){ if(target){
target.focus() target.focus()
} }
}) })
} }
const verifyHandler = (token:string,ekey:string)=>{
validateToken.value = token
}
</script> </script>
<style> <style>
......
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
:action="getUploadActionUrl()" :action="getUploadActionUrl()"
:on-success="handleAvatarSuccess" :on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload" :before-upload="beforeAvatarUpload"
v-model:file-list="fileList"
> >
<IconUpload size="54" class=""></IconUpload> <IconUpload size="54" class=""></IconUpload>
<div class="el-upload__text"> <div class="el-upload__text">
...@@ -76,7 +77,7 @@ ...@@ -76,7 +77,7 @@
</div> </div>
</el-dialog> </el-dialog>
<el-dialog v-model="dialogVisible" title="导入成员名单提示" width="500" @close="closeUploadRes"> <el-dialog v-model="dialogVisible" title="导入成员名单提示" width="500" @close="closeUploadRes">
<div class="row"> <div class="row flex-between">
<div> <div>
<el-alert show-icon title="人员总数" type="info" :closable="false"> <el-alert show-icon title="人员总数" type="info" :closable="false">
<i class="el-icon-coin"></i> <i class="el-icon-coin"></i>
...@@ -86,18 +87,18 @@ ...@@ -86,18 +87,18 @@
<div class="q-px-md"> <div class="q-px-md">
<el-alert show-icon title="成功人数" type="success" :closable="false"> <el-alert show-icon title="成功人数" type="success" :closable="false">
<i class="el-icon-coin"></i> <i class="el-icon-coin"></i>
<span>{{UploadResults.successNum}}</span> <span>{{UploadResults.successNum>=0?UploadResults.successNum:0}}</span>
</el-alert> </el-alert>
</div> </div>
<div> <div>
<el-alert show-icon title="失败人数" type="warning" :closable="false"> <el-alert show-icon title="失败人数" type="warning" :closable="false">
<i class="el-icon-coin"></i> <i class="el-icon-coin"></i>
<span class="row"> <span class="row">
<span>{{UploadResults.failNum}}</span> <span>{{UploadResults.failNum>=0?UploadResults.failNum:0}}</span>
<span class="col text-primary row items-center cusor-pointer q-ml-md" <span v-if="UploadResults.DownloadUrl" class="col text-primary row items-center cusor-pointer q-ml-md"
@click="goDownload(1)"> @click="goDownload(1)">
<IconToBottom size="16" class="q-mr-sm"></IconToBottom> <IconToBottom size="16" class="q-mr-sm"></IconToBottom>
<span>下载失败数据</span> <span>下载</span>
</span> </span>
</span> </span>
</el-alert> </el-alert>
...@@ -125,7 +126,7 @@ import { ElMessage } from "element-plus" ...@@ -125,7 +126,7 @@ import { ElMessage } from "element-plus"
import { storeToRefs } from "pinia" import { storeToRefs } from "pinia"
import { ref, unref } from "vue" import { ref, unref } from "vue"
import { domainManager } from '@/utils/domainManager' import { domainManager } from '@/utils/domainManager'
import { ElAlert } from 'element-plus'; import { ElAlert,UploadUserFile } from 'element-plus';
const props = defineProps({ const props = defineProps({
showType: { showType: {
...@@ -148,9 +149,11 @@ const useUser = useUserStore() ...@@ -148,9 +149,11 @@ const useUser = useUserStore()
const { userInfo } = storeToRefs(useUser) const { userInfo } = storeToRefs(useUser)
const dialogVisible = ref(false) const dialogVisible = ref(false)
const UploadResults = ref({} as any) const UploadResults = ref({} as any)
const fileList = ref<UploadUserFile[]>([])
const closeUploadRes = () => { const closeUploadRes = () => {
UploadResults.value = {} UploadResults.value = {}
fileList.value = []
} }
const closed = () => { const closed = () => {
emit('close') emit('close')
...@@ -168,15 +171,20 @@ const getUploadActionUrl=()=>{ ...@@ -168,15 +171,20 @@ const getUploadActionUrl=()=>{
} }
const handleAvatarSuccess=async (res:any)=>{ const handleAvatarSuccess=async (res:any)=>{
if(res.resultCode==0){ if(res.data&&res.data.totalNum){
UploadResults.value = res.data UploadResults.value = res.data
UploadResults.value.DownloadUrl = domainManager().DownloadUrl.replace("common","file")+`${res.data.failUrl}` if(res.data.failUrl) UploadResults.value.DownloadUrl = domainManager().DownloadUrl.replace("common","file")+`${res.data.failUrl}`
} }
console.log("handleAvatarSuccess_res",res); console.log("handleAvatarSuccess_res",res);
} }
const beforeAvatarUpload=async (res:any)=>{ const beforeAvatarUpload=async (res:any)=>{
console.log("beforeAvatarUpload_res",res); console.log("beforeAvatarUpload_res",res);
fileList.value.push({
name: res.name,
url: ''
})
dialogVisible.value = true dialogVisible.value = true
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment