beelink/src/views/mine/Archives.vue
2020-10-15 09:14:23 +08:00

788 lines
30 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="archives">
<div class="user-info">
<div class="avatar">
<a-avatar :size="85" shape="circle" :src="userinfo.head">
<template v-slot:icon><UserOutlined /></template>
</a-avatar>
<div class="user-name">
<div class="value">{{ userinfo.username }}</div>
<div class="update-btn" @click="updateUserName">修改</div>
</div>
</div>
<div class="form-box basic">
<div class="title">基本信息</div>
<div class="main-container">
<div class="input-box country">
<div class="label">来自国家</div>
<a-select
v-model:value="userinfo.country"
style="width: 171px"
size="small"
ref="select"
:getPopupContainer="triggerNode => triggerNode.parentNode"
>
<a-select-option v-for="(item, index) in chiveslist[0]" :key="index" :value="item.name">
{{ item.name }}
</a-select-option>
</a-select>
</div>
<div class="input-box address">
<div class="label">居住地</div>
<a-input size="small" v-model:value="userinfo.live" placeholder="请输入居住地" />
</div>
<div class="input-box teach-lang">
<div class="label">授课语言</div>
<a-select
v-model:value="userinfo.tlanguage"
style="width: 171px"
size="small"
ref="select"
:getPopupContainer="triggerNode => triggerNode.parentNode"
>
<a-select-option v-for="(item, index) in ['英语', '法语']" :key="index" :value="item">
{{ item }}
</a-select-option>
</a-select>
</div>
<div class="input-box speak-lang">
<div class="label">我还会说</div>
<div class="speak-array">
<div class="lang-items">
<div class="speak-item" v-for="(lang, indexs) in userinfo.willsay" :key="indexs">
<a-select
v-model:value="lang.name"
style="width: 171px"
size="small"
ref="select"
:getPopupContainer="triggerNode => triggerNode.parentNode"
>
<a-select-option v-for="(item, index) in chiveslist[1]" :key="index" :value="item.name">
{{ item.name }}
</a-select-option>
</a-select>
<div class="proficiency">
<div class="p-title">熟练度</div>
<div class="value">
<!-- <a-rate v-model:value="lang.proficiency" style="fontSize: 15px">
<template v-slot:character><img src="" style="width: 10px;height: 10px;background-color: #0f0;"/>{{}}</template>
</a-rate> -->
<img @click="setlevel(indexs, i)" v-for="i in 5" :key="i" :src="lang.level >= i ? smilet : smile" alt="" />
</div>
</div>
</div>
</div>
<div class="update-btn" @click="addSpeakLang">继续添加</div>
</div>
</div>
<div class="input-box native-lang">
<div class="label">母语</div>
<a-select
v-model:value="userinfo.mtongue"
style="width: 171px"
size="small"
ref="select"
:getPopupContainer="triggerNode => triggerNode.parentNode"
>
<a-select-option v-for="(item, index) in chiveslist[1]" :key="index" :value="item.name">
{{ item.name }}
</a-select-option>
</a-select>
</div>
<div class="input-box video-lang">
<div class="label">短视频</div>
<a-upload
list-type="picture"
:customRequest="uploads"
:beforeUpload="beforeVideoUpload"
>
<div class="upload-image">
<PlaySquareOutlined
style="fontsize: 22px"
v-if="uploadprogress == 0"
/>
<a-progress
type="circle"
:percent="uploadprogress"
:width="80"
v-else
/>
</div>
</a-upload>
<div class="demand">
<p class="one-line-hide">视频要求:</p>
<p class="one-line-hide"> 1.上传视频时间要求为30s之内</p>
<p class="one-line-hide">2.支持文件大小100M</p>
<p class="one-line-hide">3.文件扩展名fiv、mp4…文件扩展名fiv、mp4…</p>
</div>
</div>
<div class="input-box introduce">
<div class="label">自我介绍</div>
<a-textarea v-model:value="userinfo.desc" class="introduce-textarea" />
</div>
</div>
</div>
<div class="form-box contact">
<div class="title">联系方式</div>
<div class="main-container">
<div class="input-box mailbox">
<div class="label">邮箱</div>
<a-input size="small" v-model:value="userinfo.email" placeholder="请输入邮箱" />
</div>
<div class="input-box phone-box">
<div class="label">手机号</div>
<div class="phone">{{ userinfo.mobile }}</div>
<div class="update-btn" @click="togglePhoneModal(true)">更换手机号</div>
</div>
</div>
</div>
<div class="form-box system-setting">
<div class="title">系统设置</div>
<div class="main-container">
<div class="input-box password-box">
<div class="label">密码</div>
<div class="password">************</div>
<div class="update-btn" @click="togglePasswordModal(true)">修改密码</div>
</div>
<div class="input-box time-zone-box">
<div class="label">时区</div>
<a-select
v-model:value="userinfo.zoneStr"
style="width: 171px"
size="small"
ref="select"
:getPopupContainer="triggerNode => triggerNode.parentNode"
>
<a-select-option v-for="(item, index) in ['北京 GMT +08:00']" :key="index" :value="item">
{{ item }}
</a-select-option>
</a-select>
</div>
<div class="input-box currency-box">
<div class="label">货币</div>
<a-select
v-model:value="userinfo.currency"
style="width: 171px"
size="small"
ref="select"
:getPopupContainer="triggerNode => triggerNode.parentNode"
>
<a-select-option v-for="(item, index) in ['人民币']" :key="index" :value="item">
{{ item }}
</a-select-option>
</a-select>
</div>
<div class="input-box time-zone">
<div class="label">语言</div>
<a-select
v-model:value="userinfo.language"
style="width: 171px"
size="small"
ref="select"
:getPopupContainer="triggerNode => triggerNode.parentNode"
>
<a-select-option v-for="(item, index) in languages" :key="index" :value="item.name">
{{ item.name }}
</a-select-option>
</a-select>
</div>
</div>
</div>
<div class="modal-container">
<a-modal
centered
:footer="null"
:getContainer="modalNode"
dialogClass="modal-dialog"
v-model:visible="updatePhoneVisible"
@cancel="hidePhoneModal"
>
<template v-slot:closeIcon>
<img src="@/static/images/delete.png" class="close" />
</template>
<!-- 换绑手机号第一步 -->
<div class="public-class phone-container" v-if="!isSecondStep">
<div class="title">完成以下操作修改账号密码</div>
<div class="title sub-title">请输入{{ formData.phone }}收到的验证短信码</div>
<div class="form-box">
<div class="form-item">
<label class="label">手机验证码</label>
<a-input size="small" v-model:value="verificationCode" />
<div @click="sendVerificationCode" class="confirm-btn">获取验证码<span v-if="remainTime>0">{{ remainTime }}s</span></div>
</div>
</div>
<div @click="nextPhoneStep" class="confirm-btn">下一步</div>
</div>
<!-- 换绑手机号第二步 -->
<div class="public-class phone-container second-step" v-else>
<div class="title">完成以下操作修改账号密码</div>
<div class="form-box">
<div class="form-item">
<label class="label">手机号</label>
<a-input size="small" v-model:value="bindPhone.number" />
</div>
<div class="form-item">
<label class="label">手机验证码</label>
<a-input size="small" v-model:value="bindPhone.code" />
<div @click="sendVerificationCode" class="confirm-btn">获取验证码<span v-if="remainTime>0">{{ remainTime }}s</span></div>
</div>
</div>
<div @click="nextPhoneStep" class="confirm-btn">绑定手机</div>
</div>
</a-modal>
<!-- 修改密码 -->
<a-modal
centered
:footer="null"
:getContainer="modalNode"
dialogClass="modal-dialog"
v-model:visible="updatePasswordVisible"
@cancel="hidePasswordModal"
>
<template v-slot:closeIcon>
<img src="@/static/images/delete.png" class="close" />
</template>
<div class="public-class password-container">
<div class="title">完成以下操作修改账号密码</div>
<div class="form-box">
<div class="form-item">
<label class="label">原密码</label>
<a-input-password size="small" :visibilityToggle="false" v-model:value="passwordForm.original" />
</div>
<div class="form-item">
<label class="label">新密码</label>
<a-input-password size="small" :visibilityToggle="false" v-model:value="passwordForm.new" />
</div>
<div class="form-item">
<label class="label">确认新密码</label>
<a-input-password size="small" :visibilityToggle="false" v-model:value="passwordForm.confirm" />
</div>
</div>
<div @click="updateUserPassword" class="confirm-btn">修改密码</div>
</div>
</a-modal>
</div>
<div class="submit-btn" @click="submitInfo">保存信息</div>
</div>
<nav-bottom></nav-bottom>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, onMounted, reactive, Ref, ref, toRaw, watch } from "vue";
import { UserOutlined, PlaySquareOutlined } from '@ant-design/icons-vue';
import NavBottom from '@/components/NavBottom.vue';
import { uploadflie } from "@/utils/vod"
import store from '@/store';
import smile from "@/static/images/smile.png"
import smilet from "@/static/images/smilet.png"
import { getarchives, getlanguages } from "@/api/index"
export default defineComponent({
name: "Archives",
components: {
UserOutlined,
PlaySquareOutlined,
NavBottom
},
setup(){
interface SpeakItem{
lang: string;
proficiency: number;
}
const otherSpeak: Array<SpeakItem> = [{
lang: '请选择',
proficiency: 0,
}];
const userinfo = computed(() => store.state.userinfo)
// 表单数据
const formData = reactive(userinfo);
const modalNode = () => document.getElementsByClassName('modal-container')[0]
const chiveslist = ref<unknown>([[],[]]);
const languages = ref<unknown>([])
onMounted(async ()=>{
chiveslist.value = await getarchives()
languages.value = await getlanguages()
})
/**
* 修改用户名
* @return { void }
*/
function updateUserName (): void {
console.log('修改');
}
/**
* 添加我还会说语言
* @return { void }
*/
function addSpeakLang (): void {
formData.value.willsay.push({
name: '请选择',
level: 0
});
}
// 验证码
const verificationCode: Ref<string> = ref(''),
updatePhoneVisible: Ref<boolean> = ref(false);
/**
* 关闭手机对话框 清空数据
*/
function hidePhoneModal(): void {
verificationCode.value = '';
}
/**
* 显示修改手机号对话框
*/
function togglePhoneModal(value: boolean): void {
updatePhoneVisible.value = value;
if(!value) {
hidePhoneModal();
}
}
// 获取验证码间隔
const remainTime: Ref<number> = ref(0);
/**
* 计算验证码倒计时
*/
function computedVerificationCode(): void {
remainTime.value = 60;
const timer = setInterval(() => {
if(remainTime.value > 0) remainTime.value --;
else clearInterval(timer);
}, 1000)
}
/**
* 发送验证码
*/
function sendVerificationCode(): void {
if(remainTime.value === 0) {
computedVerificationCode();
}
}
// 绑定手机号是否是第二步
const isSecondStep: Ref<boolean> = ref(false);
interface BindPhoneItem{
number: string | number;
code: string | number;
}
const bindPhone: BindPhoneItem = reactive({
number: '',
code: '',
});
/**
* 绑定手机号下一步
*/
function nextPhoneStep(): void {
isSecondStep.value = true;
}
/**
* 修改手机号
* @return { void }
*/
function updatePhoneNumber (): void {
console.log('修改手机号');
}
// 是否显示修改密码框
const updatePasswordVisible: Ref<boolean> = ref(false);
interface PassWord {
original?: string;
new?: string;
confirm?: string;
}
const passwordForm: PassWord = reactive({
original: '',
new: '',
confirm: '',
})
/**
* 密码对话框清空数据
*/
function hidePasswordModal(): void {
passwordForm.original = '';
passwordForm.new = '';
passwordForm.confirm = '';
}
/**
* 显示修改密码对话框
*/
function togglePasswordModal(value: boolean): void {
updatePasswordVisible.value = value;
if(!value) {
hidePasswordModal();
}
}
/**
* 修改密码
* @return { void }
*/
function updateUserPassword(): void {
if(passwordForm.new === passwordForm.confirm) {
if(passwordForm.original === '') {
console.log(passwordForm.new);
togglePasswordModal(false);
}
}
}
/**
* 提交表单
* @return { void }
*/
function submitInfo (): void {
console.log(toRaw(formData.value));
}
// uploadflie()3.
function setlevel(index: number, level: number){
store.state.userinfo.willsay[index].level = level
}
/**
* 上传视频
*/
interface AntUpload{
action: string;
data: unknown;
file: File;
}
const uploadprogress: Ref<number> = ref(0);
async function uploads(file: AntUpload) {
uploadprogress.value=0
let res = await uploadflie(file.file, (info: any) => {
console.log(info);
uploadprogress.value = info.percent.toFixed(2) * 100;
});
userinfo.value.video = res.video.url;
}
if(formData.value.video != ""){
uploadprogress.value = 100
}
watch(formData,()=>{
if(formData.value.video != "" && uploadprogress.value == 0){
uploadprogress.value = 100
}
})
return {
modalNode,
formData,
updateUserName,
addSpeakLang,
verificationCode,
updatePhoneVisible,
hidePhoneModal,
sendVerificationCode,
remainTime,
isSecondStep,
nextPhoneStep,
bindPhone,
updatePhoneNumber,
togglePhoneModal,
updatePasswordVisible,
togglePasswordModal,
hidePasswordModal,
passwordForm,
updateUserPassword,
submitInfo,
userinfo: formData,
uploads,
smile,
smilet,
setlevel,
chiveslist,
languages,
uploadprogress
}
}
});
</script>
<style lang="scss" scoped>
.archives {
width: 100%;
min-width: 700px;
background-color: #ffffff;
padding: 46px;
border-radius: 17px;
position: relative;
.update-btn {
font-size: 11px;
color: #08AE98;
font-weight: 500;
cursor: pointer;
user-select: none;
}
.user-info {
margin-bottom: 42px;
.avatar {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
margin-bottom: 30px;
.user-name {
display: flex;
align-items: flex-end;
margin-top: 11px;
font-weight: bold;
.value {
font-size: 17px;
color: #111111;
margin-right: 10px;
}
}
}
.form-box {
margin-bottom: 20px;
.title {
font-size: 11px;
font-weight: bold;
color: #111111;
margin-bottom: 28px;
}
.main-container {
margin-left: 17px;
::v-deep(.input-box) {
display: flex;
align-items: center;
margin-bottom: 28px;
.label {
width: 60px;
font-size: 11px;
font-weight: 500;
color: #808080;
margin-right: 30px;
line-height: 23px;
align-self: flex-start;
}
.ant-input {
width: 171px;
padding: 6px 11px;
border-radius: 3px;
border: 1px solid #DCDFE0;
font-size: 11px;
color: #3F3F3F;
}
.ant-select {
font-size: 12px;
color: #3F3F3F;
}
.ant-select-dropdown {
.ant-select-dropdown-menu-item {
font-size: 12px;
}
}
}
.speak-lang {
.speak-array {
display: flex;
.lang-items {
.speak-item {
display: flex;
align-items: center;
&:not(:last-child) {
margin-bottom: 28px;
}
.proficiency {
margin: 0 107px 0 17px;
display: flex;
align-items: center;
.p-title {
font-size: 11px;
font-weight: 500;
color: #808080;
margin-right: 14px;
}
.value{
display: flex;
>img{
width: 15px;
height: 15px;
margin-right: 6px;
}
}
}
}
}
.update-btn {
align-self: flex-end;
}
}
}
.video-lang {
.upload-image {
width: 171px;
height: 96px;
border: 1px solid #DCDFE0;
border-radius: 3px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 17px;
}
.demand {
line-height: 17px;
font-size: 10px;
font-weight: 500;
color: #808080;
width: 134px;
p {
margin: 0;
}
}
}
.introduce {
.ant-input {
width: 359px;
}
.introduce-textarea {
height: 85px;
min-height: 85px;
max-height: 85px;
}
}
.phone-box {
.phone {
font-size: 11px;
font-weight: bold;
color: #404040;
margin-right: 112px;
}
}
.password-box {
.password {
margin-right: 123px;
}
}
}
}
::v-deep(.modal-dialog) {
.close {
width: 14px;
height: 14px;
}
.ant-modal-content {
box-sizing: border-box;
padding: 25px 30px;
width: 569px;
background: #FFFFFF;
box-shadow: 0px 4px 6px 0px rgba(102, 102, 102, 0.07);
border-radius: 28px;
.public-class {
.title {
font-size: 11px;
font-weight: bold;
color: #111111;
}
.form-box {
.form-item {
display: flex;
align-items: center;
.label {
font-size: 11px;
font-weight: 500;
color: #7F7F7F;
}
}
}
.confirm-btn {
display: inline-block;
background: #07AD97;
border-radius: 2px;
font-size: 9px;
font-weight: 500;
color: #FFFFFF;
text-align: center;
cursor: pointer;
user-select: none;
height: 22px;
line-height: 22px;
padding: 0 17px;
}
}
.password-container {
.title {
margin-bottom: 30px;
}
.form-box {
margin-bottom: 50px;
.form-item {
.label {
width: 90px;
margin-right: 10px;
}
&:not(:last-child) {
margin-bottom: 28px;
}
.ant-input-password {
width: 170px;
font-size: 11px;
color: #3F3F3F;
// .ant-input {
// letter-spacing: 0;
// }
}
}
}
}
.phone-container {
.sub-title {
margin: 16px 0 40px;
}
.form-box {
margin-bottom: 50px;
.form-item {
.label {
width: 80px;
margin-right: 10px;
}
.ant-input {
width: 170px;
font-size: 11px;
color: #3F3F3F;
margin-right: 28px;
}
}
}
}
.second-step {
.title {
margin-bottom: 33px;
}
.form-box {
.form-item {
&:not(:last-child) {
margin-bottom: 28px;
}
}
}
}
}
}
.submit-btn {
width: 63px;
height: 23px;
background: #08AE98;
border-radius: 3px;
font-size: 10px;
font-weight: 500;
color: #FFFFFF;
text-align: center;
line-height: 23px;
cursor: pointer;
user-select: none;
}
}
::v-deep(.ant-upload-list) {
display: none;
}
}
</style>