You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

916 lines
27 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<script setup>
import _ from 'lodash'
import axios from 'axios'
import { ref , nextTick, onBeforeMount} from 'vue'
import { Cropper } from 'vue-advanced-cropper';
import 'vue-advanced-cropper/dist/style.css';
// import Footer from '@/components/Footer.vue'
import { useStore } from 'vuex'
import { useRouter } from 'vue-router'
import { showToast } from 'vant'
import { showLoadingToast,showSuccessToast } from 'vant';
import { getUserInfo, updateUserInfo, updateCard, searchConnection, addUserFavi, setUserNfcTpl} from '@/api'
import imgTp1 from '@/assets/images/tp/tp_1.jpg'
import imgTp2 from '@/assets/images/tp/tp_2.jpg'
import imgTp3 from '@/assets/images/tp/tp_3.jpg'
import imgTp4 from '@/assets/images/tp/tp_4.jpg'
const URL = window.URL || window.webkitURL;
const store = useStore()
const router = useRouter()
const form = ref({addon:[]})
const uInfoForm = ref({addon:[]})
const genderChecked = ref()
const resourceActive = ref('1');
const fileList = ref([]);
const myCrop = ref(null)
const tabActive = ref(0)
const tabItemObj = ref([
{title:"基本資料",icon:"fa-id-card-clip"},
{title:"社群分享",icon:"fa-share-nodes"},
{title:"人脈資訊",icon:"fa-gem"},
{title:"版型設定",icon:"fa-layer-group"}
]);
const crop = ref({
show: false,
img: null,
})
const validatorUrl = (val) => {
if(val.length>0){
return /(https?:\/\/|line:\/\/|tel:|mailto:)\S+/.test(val)
}else{
return true
}
};
const validatorTel = (val) => {
if(val.length>0){
return /(\d{2,3}-?|\(\d{2,3}\))\d{3,4}-?\d{4}/.test(val)
}else{
return true
}
};
// onMounted(async ()=>{
let userRes = await getUserInfo()
if(userRes.code===200){
form.value = userRes.data
}else{
}
// })
if (userRes.data.nfc_addon && (userRes.data.nfc_addon.length > 0)) {
form.value.addon = JSON.parse(userRes.data.nfc_addon)
}
console.log(form,"form")
const onCrop = () => {
const { canvas } = myCrop.value.getResult();
if (canvas) {
const imgFile = new FormData();
canvas.toBlob(async (blob) => {
let ufile = new File([blob], "image.jpg");
imgFile.append("user_id", form.value.user_id)
imgFile.append("fileType", "IMAGE")
imgFile.append('file', ufile)
crop.value.show = false
showLoadingToast({
duration: 0,
message: '圖片上傳中...',
forbidClick: true,
});
let res = await axios.post(
`${import.meta.env.VITE_APP_API_URL}/user/uploadAvatar`,
imgFile,
{
}
)
if (res.data.code == 200) {
form.value.avatar = res.data.data
showSuccessToast('上傳成功');
}else{
showToast.fail('上傳失敗');
}
}, 'image/jpeg');
}
return
}
const afterRead = async(file, name) => {
crop.value.show = true
const ofile = file.file
crop.value.img = URL.createObjectURL(ofile);
// crop.value.img = ofile
return
};
const onAddBtn = () => {
if(form.value.addon){
form.value.addon.push({icon:'',name:'',link:''})
}else{
form.value.addon = [{icon:'',name:'',link:''}]
}
}
const onDelBtn = (index) => {
form.value.addon.splice(index, 1)
}
const onMoveBtn = (type, index) => {
if (type === 0) {
if (index !== 0) {
[form.value.addon[index], form.value.addon[index - 1]] = [form.value.addon[index - 1], form.value.addon[index]]
}
} else {
if (index + 1 !== form.value.addon.length) {
[form.value.addon[index + 1], form.value.addon[index]] = [form.value.addon[index], form.value.addon[index + 1]]
}
}
}
const onSubmit = async () => {
showLoadingToast({
duration: 0,
message: '資料更新中...',
forbidClick: true,
});
// console.log(form.value,"test");
let res = await updateCard(form.value)
if(res.code===200){
showSuccessToast('更新成功')
store.commit('user/setUserInfo',form.value)
router.push('/member')
}else{
showToast.fail('更新失敗')
}
};
const userInfoSubmit = async (values) => {
showLoadingToast({
duration: 0,
message: '資料更新中...',
forbidClick: true,
});
console.log("test",values);
let res = await updateUserInfo(values)
if(res.code===200){
showSuccessToast('更新成功')
store.commit('user/setUserInfo',values)
router.push('/member')
}else{
showToast.fail('更新失敗')
}
};
const searchChecked = ref(true);
const searchOnUpdateValue = (newValue) => {
showConfirmDialog({
title: '提醒',
message: '是否切换开关?',
}).then(() => {
searchChecked.value = newValue;
});
};
const userExtraSubmit = async (values) => {
// showLoadingToast({
// duration: 0,
// message: '資料更新中...',
// forbidClick: true,
// });
console.log("test",values);
let res = await updateUserInfo(values)
if(res.code===200){
showSuccessToast('更新成功')
store.commit('user/setUserInfo',values)
router.push('/member')
}else{
showToast.fail('更新失敗')
}
};
// START: 人脈資源
const search = ref({
type: 0,
keyword: '',
})
const tab2result = ref('你所需要的資源');
const tab2showPicker = ref(false);
const tab2columns = [
{ text: '你所需要的資源', value: 0 },
{ text: '你能提供的資源', value: 1 },
];
const tab2OnConfirm = ({ selectedOptions }) => {
tab2result.value = selectedOptions[0].text;
search.value.type = selectedOptions[0].value;
tab2showPicker.value = false;
handleSearch();
};
const tab2OnSearch = async () => {
handleSearch();
};
const handleSearch = async () => {
let res = await searchConnection(search.value);
if(res.code===200){
tab2list.value = res.data;
}
};
const tab2list = ref([]);
const tab2Loading = ref(false);
const tab2Finished = ref(false);
const tab2TodoLists = ref([]);
const tab2AddFriend = ref([]);
const tab2ListonLoad = () => {
// 异步更新数据
// setTimeout 仅做示例,真实场景中一般为 ajax 请求
// setTimeout(() => {
// for (let i = 0; i < 10; i++) {
// tab2list.value.push(tab2list.value.length + 1);
// }
// // 加载状态结束
// tab2Loading.value = false;
// // 数据全部加载完成
// if (tab2list.value.length >= 40) {
// tab2Finished.value = true;
// }
// }, 1000);
};
const handleAddFavi = async (uf_user_id) => {
let res = await addUserFavi({uf_user_id});
if(res.code===200){
return showToast({
message: '已加入好友',
duration: 1000,
});
}
return showToast({
message: '加入失敗',
duration: 1000,
});
}
// END: 人脈資源
const tab3list = ref([]);
onBeforeMount(async () => {
let res = await setUserNfcTpl();
if(res.code===200){
tab3list.value = res.data;
}
});
</script>
<template>
<div class="member page">
<van-nav-bar class="bg-skyBlue py-1" left-arrow @click-left="$router.push('/')">
<template #title>
<h5 class="text-white mb-1"><strong>會員資料</strong></h5>
</template>
<template #left>
<h4><i class="fa-solid fa-angle-left text-white" :style="{opacity:0.5}"></i></h4>
</template>
</van-nav-bar>
<van-tabs class="van-tabs" :lazy-render="true" v-model:active="tabActive">
<van-tab v-for="(item,index) in tabItemObj" :key="index">
<template #title>
<div class="tab_item">
<i :class="`fa-solid ${item.icon} fa-2x mb-1`"></i>
<p class="mb-3">{{item.title}}</p>
</div>
</template>
</van-tab>
</van-tabs>
<div class="content cnt0" v-show="tabActive === 0">
<van-cell-group inset>
<van-form @submit="userInfoSubmit">
<div class="text-center p-4">
<van-uploader :after-read="afterRead" :max-count="1" name="avatar" class="mb-4">
<div class="upload-main">
<img
class="upload-img avatar"
:src="form.avatar"
alt=""
v-if="form.avatar"
/>
<img
class="upload-img avatar"
src="@/assets/images/upload.jpg"
alt=""
v-else
/>
<div class="ml-3">
<p class="text-skyBlue mb-2">上傳圖片預設為Line頭像</p>
<van-button class="btn-darkBlue" icon="plus" block size="small">上傳檔案</van-button>
</div>
</div>
</van-uploader>
<van-field
v-model="form.mark"
rows="3"
type="textarea"
maxlength="100"
name="mark"
placeholder="請輸入100字以內的簡介"
show-word-limit
:style="{border:'1px #e3e3e3 solid',borderRadius:'6px'}"
/>
</div>
<van-field
v-model="form.real_name"
label="姓名"
name="real_name"
placeholder="請輸入您的姓名"
:rules="[{ required: true, message: '姓名為必填' }]"
/>
<van-field
v-model="form.company"
label="公司名稱"
name="company"
placeholder="請輸入您的公司名稱"
:rules="[{ required: true, message: '公司名稱必填' }]"
/>
<van-field
v-model="form.title"
label="職稱"
name="title"
placeholder="請輸入您的職稱"
/>
<van-field
v-model="form.phone"
label="手機"
name="phone"
type="tel"
placeholder="Ex. 0900000001 不要有空格"
:rules="[{ required: true, message: '手機號必填' },{ pattern: /\d{10}/ , message: '手機號格式錯誤' }]"
/>
<van-field
v-model="form.tel"
label="市話"
name="tel"
type="tel"
placeholder="請輸入您的市話"
:rules="[{ validator: validatorTel, message: '市話格式不正確,Ex. 02xxxx or 02-xxxx' }]"
/>
<van-field
v-model="form.email"
label="Email"
name="email"
placeholder="請輸入您的Email"
:rules="[{ required: true, message: 'Email必填' },{ pattern: /^([\w\.\-]){1,64}\@([\w\.\-]){1,64}/ , message: 'Email格式錯誤' }]"
/>
<van-field
v-model="form.address"
label="住址"
name="address"
placeholder="請輸入您的地址"
/>
<van-field
v-model="form.age"
label="年齡"
name="age"
placeholder="請輸入您的年齡"
/>
<van-field name="sex" label="性別">
<template #input>
<van-radio-group
v-model="genderChecked"
direction="horizontal"
checked-color="#345068"
>
<van-radio name="0">男</van-radio>
<van-radio name="1">女</van-radio>
</van-radio-group>
</template>
</van-field>
<van-field
v-model="form.area"
label="區域"
name="area"
placeholder="請選擇縣市區域"
/>
<van-field
v-model="form.work"
label="工作性質"
name="work"
placeholder="請選擇工作性質"
/>
<van-field readonly>
<template #label>是否公開<br/>資料搜尋</template>
<template #input>
<van-switch
v-model="searchChecked"
@update:model-value="searchOnUpdateValue"
size="18px"
active-color="#345068"
inactive-color="#888888"
/>
</template>
</van-field>
<div class="p-5">
<van-button block class="btn-darkBlue" native-type="submit">
確認修改
</van-button>
</div>
</van-form>
</van-cell-group>
<van-cell-group inset>
<van-form @submit="userExtraSubmit">
<van-cell class="text-center bg-lightPink py-3">
<template #title>
<h6 class="text-darkBlue"><strong>人脈資訊</strong></h6>
</template>
</van-cell>
<van-field
v-model="form.introduction"
name="introduction"
placeholder="請輸入簡短的自我介紹"
label-align="top"
>
<template #label>
<i class="fa-solid fa-gem text-darkBlue"></i> 一句話介紹自己
</template>
</van-field>
<van-divider
:style="{
color: '#345068',
borderColor: '#345068',
padding: '0 16px',
}"
><strong>貴人資源共享</strong></van-divider
>
<div style="text-align: center;">
下面為客製型會員專屬提供被搜尋
</div>
<van-collapse v-model="resourceActive" accordion>
<van-collapse-item title="工商簡介" name="3">
<van-field
v-model="form.exchange"
rows="3"
type="textarea"
name="exchange"
maxlength="100"
placeholder="請填寫工商簡介"
show-word-limit
/>
<van-field
v-model="form.exchange_link"
label="分享網址:"
name="exchange_link"
placeholder="需求連結"
/>
</van-collapse-item>
<van-collapse-item title="我能分享的資源" name="1">
<van-field
v-model="form.supply"
rows="3"
type="textarea"
maxlength="100"
name="supply"
placeholder="請填寫能分享的資源"
show-word-limit
/>
<van-field
v-model="form.supply_link"
label="分享網址:"
name="supply_link"
placeholder="分享網址"
:rules="[{ validator: validatorUrl, message: '網址格式不正確,Ex. http://' }]"
/>
</van-collapse-item>
<van-collapse-item title="我需要的資源" name="2">
<van-field
v-model="form.demand"
rows="3"
type="textarea"
maxlength="100"
name="demand"
placeholder="請填寫需要的的資源"
show-word-limit
/>
<van-field
v-model="form.demand_link"
label="分享網址:"
name="demand_link"
placeholder="需求連結"
/>
</van-collapse-item>
</van-collapse>
<div class="p-5">
<van-button block class="btn-darkBlue" native-type="submit">
確認修改
</van-button>
</div>
</van-form>
</van-cell-group>
</div>
<div class="content cnt1" v-show="tabActive === 1">
<van-cell-group inset>
<van-form @submit="onSubmit">
<van-field
v-model="form.nfcurl"
label="個人網頁"
name=""
placeholder="請輸入您的個人網頁"
/>
<van-field
v-model="form.line"
label="Line"
name=""
placeholder="請輸入您的Line ID"
/>
<van-field
v-model="form.facebook"
label="Facebook"
name=""
placeholder="請輸入您的Facebook"
/>
<van-field
v-model="form.ig"
label="IG"
name=""
placeholder="請輸入您的IG"
/>
<van-field
v-model="form.youTube"
label="YouTube"
name=""
placeholder="請輸入您的YouTube"
/>
<van-field
v-model="form.wechat"
label="WeChat"
name=""
placeholder="請輸入您的WeChat"
/>
<div class="px-5 py-4">
<van-button block class="btn-darkBlue" native-type="submit">
<h6>確認修改</h6>
</van-button>
</div>
</van-form>
</van-cell-group>
<van-cell-group inset>
<van-form @submit="onSubmit">
<van-cell class="bg-lightPink">
<template #title>
<h6 class="text-darkBlue"><strong>相關連結</strong></h6>
</template>
<template #value>
<van-button size="small" class="btn-outline-darkBlue" @click="onAddBtn">
<h6>新增連結</h6>
</van-button>
</template>
</van-cell>
<van-field v-for="(item,idx) in form.addon" :key="idx">
<template #label>
<van-field
v-model="item.name"
name=""
maxlength="10"
placeholder="請輸入您的連結名稱"
:rules="[{ required: true, message: '連結名稱必填' }]"
/>
</template>
<template #input>
<van-field
v-model="item.link"
name=""
placeholder="請輸入您的按鈕連結"
:rules="[{ required: true, message: '按鈕連結必填' }]"
/>
</template>
<template #button>
<van-button size="small" class="ml-1 btn-tomatoRed" icon="delete-o" hairline @click="onDelBtn(idx)"></van-button>
<van-button size="small" class="ml-1 btn-skyBlue" icon="arrow-up" hairline @click="onMoveBtn(0,idx)"></van-button>
<van-button size="small" class="ml-1 btn-skyBlue" icon="arrow-down" plain hairline @click="onMoveBtn(1,idx)"></van-button>
</template>
</van-field>
<!-- <van-swipe-cell v-for="(item,idx) in form.addon" :key="idx">
<template #left>
<van-button type="danger" icon="delete-o" plain hairline @click="onDelBtn(idx)">刪除</van-button>
</template>
<van-field
v-model="item.name"
name=""
placeholder="請輸入您的連結名稱"
:rules="[{ required: true, message: '連結名稱必填' }]"
/>
<van-field
v-model="item.link"
name=""
placeholder="請輸入您的按鈕連結"
:rules="[{ pattern: /^([\w\.\-]){1,64}\@([\w\.\-]){1,64}/ , message: 'Email格式錯誤' }]"
/>
<template #right>
<van-button type="primary" icon="arrow-up" plain hairline @click="onMoveBtn(0,idx)">上移</van-button>
<van-button type="primary" icon="arrow-down" plain hairline @click="onMoveBtn(1,idx)">下移</van-button>
</template>
</van-swipe-cell> -->
<div class="px-5 py-4">
<van-button block class="btn-darkBlue" native-type="submit">
<h6>確認修改</h6>
</van-button>
</div>
</van-form>
</van-cell-group>
</div>
<div class="content cnt2" v-show="tabActive === 2">
<van-cell-group inset>
<van-row align="center">
<van-col span="8">
<van-field
v-model="tab2result"
is-link
readonly
name="picker"
:border="false"
placeholder="請選擇"
@click="tab2showPicker = true"
/>
<van-popup v-model:show="tab2showPicker" position="bottom">
<van-picker
:columns="tab2columns"
@confirm="tab2OnConfirm"
@cancel="tab2showPicker = false"
/>
</van-popup>
</van-col>
<van-col span="16">
<van-search
v-model="search.keyword"
placeholder="請輸入搜尋關鍵字"
@search="tab2OnSearch"
/>
</van-col>
</van-row>
</van-cell-group>
<van-cell-group inset>
<van-list
v-model:loading="loading"
:finished="finished"
finished-text="没有更多了"
@load="tab2ListonLoad"
class="accordion"
id="accordion"
>
<!-- <van-cell v-for="item in list" :key="item" :title="item" > -->
<!-- <van-cell v-for="item in tab2list" :key="item" :title="item">
<template #title>
<div class="list-item">
<div class="avatar"><img :src="item.avatar"></div>
<div class="text">
<h5 class="name ellipsis">{{item.real_name}}</h5>
<div class="desc ellipsis">@{{item.note}}</div>
</div>
</div>
</template>
<template #value>
<van-button size="normal" class="border-0"><h5><i class="fa-solid fa-layer-group text-darkBlue"></i></h5></van-button>
<van-button size="normal" class="border-0"><h5><i class="fa-solid fa-comment-medical text-darkBlue"></i></h5></van-button>
</template>
</van-cell> -->
<div class="list-item" v-for="(item, index) in tab2list" :key="index">
<div class="left">
<div class="avatar"><img :src="item.avatar"></div>
<div class="text">
<h5 class="name ellipsis">{{item.real_name}}</h5>
<div class="desc ellipsis">@{{item.note}}</div>
</div>
</div>
<div class="right">
<van-button size="normal" class="border-0" data-toggle="collapse" :href="`#c${index}`" role="button" aria-expanded="false" :aria-controls="`c${index}`">
<h5><i class="fa-solid fa-layer-group text-darkBlue"></i></h5>
</van-button>
<van-button size="normal" class="border-0" @click="handleAddFavi(item.user_id)"><h5><i class="fa-solid fa-comment-medical text-darkBlue"></i></h5></van-button>
</div>
<div class="bottom collapse" :id="`c${index}`" data-parent="#accordion">
<h6 class="text-darkBlue"><strong>我能分享的資源</strong></h6>
<div class="desc">{{item.supply}}</div>
<div class="url py-2">網址:<a :href="item.supply_link" class="text-moBlue">{{item.supply_link}}</a></div>
<hr/>
<h6 class="text-darkBlue"><strong>我需要的資源</strong></h6>
<div class="desc">{{item.demand}}</div>
<div class="url py-2">網址:<a :href="item.demand_link" class="text-moBlue">{{item.demand_link}}</a></div>
</div>
</div>
</van-list>
</van-cell-group>
</div>
<div class="content cnt3" v-show="tabActive === 3">
<van-cell-group inset>
<van-form @submit="onSubmit">
<van-cell class="text-center bg-lightPink py-3">
<template #title>
<h6 class="text-darkBlue"><strong>感應式版型切換</strong></h6>
</template>
</van-cell>
<div class="block">
<van-image
width="100%"
position="top"
fit="cover"
:src="imgTp1"
/>
</div>
<div class="d-flex justify-content-center py-3">
<van-button class="btn-tomatoRed px-5 mr-2">
預覽
</van-button>
<van-button class="btn-darkBlue px-5" native-type="submit">
確認修改
</van-button>
</div>
</van-form>
</van-cell-group>
<van-cell-group inset>
<van-row>
<van-col span="12" v-for="(item, index) in tab3list" :key="index">
<div class="imgBtn" :data-id="index">
<div class="imgCnt">
<van-image
:src="imgTp1"
/>
</div>
</div>
</van-col>
</van-row>
</van-cell-group>
</div>
<!-- <Footer/> -->
<van-popup class="cropPopup" v-model:show="crop.show" closeable>
<h5 class="text-center mt-3">檔案裁切上傳</h5>
<div class="cropper-section">
<div class="crop-area">
<cropper
class="cropper"
ref="myCrop"
:src="crop.img"
:stencil-props="{
aspectRatio: 1 / 1,
}"
:auto-zoom="true"
/>
</div>
<van-button round class="btn-tomatoRed rounded-pill w-50 mt-3" size="small" @click="onCrop">
</van-button>
</div>
</van-popup>
</div>
</template>
<style src="@/assets/css/main.css"></style>
<style lang="less" scoped>
.cnt2{
.van-list{
.list-item{
display: flex;
align-items: center;
flex-wrap: wrap;
padding: 15px 0;
margin:0 15px;
border-bottom: 1px #e3e3e3 solid;
.left{
flex:1 0 0%;
display: flex;
align-items: center;
.avatar{
width: 55px;
min-width: 55px;
aspect-ratio: 1/1;
border-radius: 50%;
margin-right: 10px;
overflow: hidden;
img{
width:100%;
height:100%;
object-fit: cover;
}
}
.name{
font-weight: bold;
}
}
.right{
flex:0 0 auto;
}
.bottom{
flex:1 0 100%;
border: 1px #e3e3e3 solid;
border-radius: 10px;
padding: 0 10px;
margin: 0;
transition: all .2s;
&.show{
padding: 10px;
margin: 5px 0;
}
}
}
}
}
.cnt3{
.block{
height:500px;
text-align: center;
background-color: #000;
padding: 20px 35px;
overflow: hidden;
overflow-y: auto;
}
.imgBtn{
padding: 10px;
margin: 10px;
background-color: #333;
border-radius: 10px;
overflow: hidden;
cursor: pointer;
transform: scale(1);
transition: all .3s;
&.active,&:hover{
transform: scale(1.02);
}
.imgCnt{
width:100%;
height: 150px;
img{
width:100%;
height: 100%;
object-fit: cover;
}
}
}
}
</style>