Compare commits
110 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
cc59af9aad | 2 years ago |
|
|
e4439433d3 | 2 years ago |
|
|
fe1ad1f98a | 2 years ago |
|
|
39b5bd0ab5 | 2 years ago |
|
|
eafd24ff65 | 2 years ago |
|
|
be6f1aee23 | 2 years ago |
|
|
4ba596edca | 2 years ago |
|
|
605cdb30d7 | 2 years ago |
|
|
4bb4229dd8 | 2 years ago |
|
|
9b080e37f9 | 2 years ago |
|
|
7487871484 | 2 years ago |
|
|
3834c55abe | 2 years ago |
|
|
f41a23e851 | 2 years ago |
|
|
30acb05ca0 | 2 years ago |
|
|
cd1c12dd3f | 2 years ago |
|
|
cfe5eba817 | 2 years ago |
|
|
eed9a1eaca | 2 years ago |
|
|
13d47f941e | 2 years ago |
|
|
150ab7d9d4 | 2 years ago |
|
|
9fbb42c5dd | 2 years ago |
|
|
51aa9452d4 | 2 years ago |
|
|
23a6348e4f | 2 years ago |
|
|
dc0d0e7a26 | 2 years ago |
|
|
f5fa9cccfa | 2 years ago |
|
|
3a7a91b496 | 2 years ago |
|
|
224ec188ac | 2 years ago |
|
|
0cb90ffe7e | 2 years ago |
|
|
cddada9408 | 2 years ago |
|
|
fcbc94fd2a | 2 years ago |
|
|
3a6d13162b | 2 years ago |
|
|
2c6c89a3ed | 2 years ago |
|
|
62b7fb2ef2 | 2 years ago |
|
|
7b9d560788 | 2 years ago |
|
|
879fbdc151 | 2 years ago |
|
|
b194ffd690 | 2 years ago |
|
|
78d1e9845b | 2 years ago |
|
|
fb7be73a6e | 2 years ago |
|
|
06c4a5bb4a | 2 years ago |
|
|
bf4cae338e | 2 years ago |
|
|
8d42353a6c | 2 years ago |
|
|
5c0a63d855 | 2 years ago |
|
|
d56e4f4008 | 2 years ago |
|
|
69cee05bec | 2 years ago |
|
|
443acf6cc3 | 2 years ago |
|
|
a843ef4e57 | 2 years ago |
|
|
c6b742e903 | 2 years ago |
|
|
5843aa3bc1 | 2 years ago |
|
|
b62a6a694e | 2 years ago |
|
|
e861b4f988 | 2 years ago |
|
|
89375c64bd | 2 years ago |
|
|
ce432ada07 | 2 years ago |
|
|
3e54bc1e36 | 2 years ago |
|
|
7d53365d12 | 2 years ago |
|
|
d19f2426a6 | 2 years ago |
|
|
7ff6f225ae | 2 years ago |
|
|
c9661a0dc0 | 2 years ago |
|
|
163ef76626 | 2 years ago |
|
|
2951358fcd | 2 years ago |
|
|
3cf93201e3 | 2 years ago |
|
|
355e65749a | 2 years ago |
|
|
822ba3c881 | 2 years ago |
|
|
30a5f6c53b | 2 years ago |
|
|
6c6ff6fcd4 | 2 years ago |
|
|
3e2df10116 | 2 years ago |
|
|
f7515aab19 | 2 years ago |
|
|
486aa23da7 | 2 years ago |
|
|
aa59a1068f | 2 years ago |
|
|
db77b14659 | 2 years ago |
|
|
370963f653 | 2 years ago |
|
|
1fc1dfd7a7 | 2 years ago |
|
|
54bbae189b | 2 years ago |
|
|
53daffd285 | 2 years ago |
|
|
088dca0355 | 2 years ago |
|
|
46a1611f76 | 2 years ago |
|
|
e9dfe78ea9 | 2 years ago |
|
|
e4e8d5d13a | 2 years ago |
|
|
daa3c8145a | 2 years ago |
|
|
46a3998f09 | 2 years ago |
|
|
d0930be7d1 | 2 years ago |
|
|
24383d4ead | 2 years ago |
|
|
8da54e528e | 2 years ago |
|
|
a14c38747f | 2 years ago |
|
|
105440ea8d | 2 years ago |
|
|
d3ad65cea7 | 2 years ago |
|
|
f1d3ad7dc9 | 2 years ago |
|
|
00a3369baf | 2 years ago |
|
|
50a156e16a | 2 years ago |
|
|
a56c5470e2 | 2 years ago |
|
|
8033a7f261 | 2 years ago |
|
|
b406125e5d | 2 years ago |
|
|
a7de319c42 | 2 years ago |
|
|
1acade3753 | 2 years ago |
|
|
35f8691a59 | 2 years ago |
|
|
15af258de7 | 2 years ago |
|
|
c583ac9982 | 2 years ago |
|
|
5f134c034b | 2 years ago |
|
|
6c0d12d328 | 2 years ago |
|
|
6c7f503e8c | 2 years ago |
|
|
8a4ac9e844 | 2 years ago |
|
|
e7a0d071ce | 2 years ago |
|
|
d07a8c2f8d | 2 years ago |
|
|
c8c4d6e1c5 | 2 years ago |
|
|
2a958df547 | 2 years ago |
|
|
58b5b000a5 | 2 years ago |
|
|
a7bd5998f3 | 2 years ago |
|
|
d408a5dc4e | 2 years ago |
|
|
908a601f7e | 3 years ago |
|
|
345da1f3f3 | 3 years ago |
|
|
71ead16745 | 3 years ago |
|
|
41bd11ab97 | 3 years ago |
@ -1,6 +1,10 @@
|
|||||||
import ajax from "./ajax";
|
import ajax from "./ajax";
|
||||||
|
|
||||||
//通訊錄
|
|
||||||
export const getCardData = async () =>
|
export const getCardData = async () =>
|
||||||
ajax(`/Card/getCardData`);
|
ajax(`/Card/getCardData`);
|
||||||
|
|
||||||
|
export const updateRemark = async (params) =>
|
||||||
|
ajax(`/card/updateRemark`, params, "POST");
|
||||||
|
|
||||||
|
export const updateIsSend = async (params) =>
|
||||||
|
ajax(`/card/updateIsSend`, params, "POST");
|
||||||
|
|||||||
@ -0,0 +1,13 @@
|
|||||||
|
import ajax from "./ajax";
|
||||||
|
|
||||||
|
export const getFaviLogs = async (id) =>
|
||||||
|
ajax(`/faviLog/getFaviLogs`,{id},"GET");
|
||||||
|
|
||||||
|
export const addFaviLog = async (params) =>
|
||||||
|
ajax(`/faviLog/addFaviLog`,params,"POST");
|
||||||
|
|
||||||
|
export const deleteFaviLog = async (id) =>
|
||||||
|
ajax(`/faviLog/deleteFaviLog`,{id},"GET");
|
||||||
|
|
||||||
|
export const updateFaviLog = async (params) =>
|
||||||
|
ajax(`/faviLog/updateFaviLog`,params,"POST");
|
||||||
@ -1,14 +1,17 @@
|
|||||||
import ajax from "./ajax";
|
import ajax from "./ajax";
|
||||||
|
|
||||||
//通訊錄
|
|
||||||
export const getUserData = async (params) =>
|
export const getUserData = async () =>
|
||||||
ajax(`/User/getUser`, params, "POST");
|
ajax(`/user/getUser`);
|
||||||
|
|
||||||
|
export const getUserExtra = async (uid) =>
|
||||||
|
ajax(`/user/getUserExtra`, { uid }, "GET");
|
||||||
|
|
||||||
export const updateUserExtra = async (params) =>
|
export const updateUserExtra = async (params) =>
|
||||||
ajax(`/User/updateUserExtra`, params, "POST");
|
ajax(`/user/updateUserExtra`, params, "POST");
|
||||||
|
|
||||||
export const updateUserLink = async (params) =>
|
export const updateUserLink = async (params) =>
|
||||||
ajax(`/User/updateUserLink`, params, "POST");
|
ajax(`/user/updateUserLink`, params, "POST");
|
||||||
|
|
||||||
export const updateUserAddon = async (params) =>
|
export const updateUserAddon = async (params) =>
|
||||||
ajax(`/User/updateUserAddon`, {nfc_addon:params}, "POST");
|
ajax(`/user/updateUserAddon`, {nfc_addon:params}, "POST");
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 371 KiB After Width: | Height: | Size: 750 KiB |
|
Before Width: | Height: | Size: 398 KiB After Width: | Height: | Size: 792 KiB |
|
Before Width: | Height: | Size: 382 KiB After Width: | Height: | Size: 751 KiB |
|
Before Width: | Height: | Size: 398 KiB After Width: | Height: | Size: 729 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 33 KiB |
@ -0,0 +1,52 @@
|
|||||||
|
function genAdCard(ctx,option) {
|
||||||
|
const { json5: vcard } = ctx;
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: "flex",
|
||||||
|
altText: "廣告卡片",
|
||||||
|
contents: {
|
||||||
|
type: "carousel",
|
||||||
|
contents: [
|
||||||
|
ctx.contents,
|
||||||
|
{
|
||||||
|
"type": "bubble",
|
||||||
|
"size":"giga",
|
||||||
|
"hero": {
|
||||||
|
"type": "image",
|
||||||
|
"url": option.ad_image,
|
||||||
|
"size": "full",
|
||||||
|
"aspectMode": "cover",
|
||||||
|
"aspectRatio": "5:2",
|
||||||
|
"action": {
|
||||||
|
"type": "uri",
|
||||||
|
"label": option.ad_title,
|
||||||
|
"uri": option.ad_link
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"type": "box",
|
||||||
|
"layout": "vertical",
|
||||||
|
"contents": [
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"text": option.ad_title,
|
||||||
|
"weight": "bold",
|
||||||
|
"size": "xl",
|
||||||
|
"color": "#333333"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"text": option.ad_desc,
|
||||||
|
"color": "#666666",
|
||||||
|
"size": "md",
|
||||||
|
"wrap": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export { genAdCard };
|
||||||
@ -1,12 +1,5 @@
|
|||||||
import { useCardStore } from '@/store/card.js';
|
// import { useCardStore } from '@/store/card.js';
|
||||||
import { getCardData } from '@/api/card.js';
|
// import { getCardData } from '@/api/card.js';
|
||||||
|
|
||||||
export const initStore = async (pinia) => {
|
// export const initStore = async (pinia) => {
|
||||||
const cardStore = useCardStore();
|
// };
|
||||||
|
|
||||||
let res = await getCardData();
|
|
||||||
if (res.code === 200) {
|
|
||||||
cardStore.cusCard = res.data.cus_card;
|
|
||||||
cardStore.vipCard = res.data.vip_card;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|||||||
@ -1,50 +1,759 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import liff from "@line/liff";
|
import _ from 'lodash';
|
||||||
|
import { onMounted, onBeforeMount, ref , watch } from 'vue'
|
||||||
|
import { toClipboard } from "@soerenmartius/vue3-clipboard";
|
||||||
|
import { showToast, showSuccessToast, showConfirmDialog,showFailToast } from 'vant';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
import { showToast,showSuccessToast } from 'vant';
|
import {
|
||||||
|
getUserFaviList
|
||||||
|
, getUserCateList
|
||||||
|
, updateUserCate
|
||||||
|
, setUserFaviCate
|
||||||
|
, addUserFavi
|
||||||
|
, deleteUserFavi
|
||||||
|
} from '@/api'
|
||||||
|
|
||||||
import { onMounted, reactive, ref, toRefs, computed, watch } from 'vue'
|
import { getFaviLogs, addFaviLog ,deleteFaviLog,updateFaviLog } from '@/api/faviLog'
|
||||||
|
|
||||||
|
import { getAreaList } from '@/api/system';
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
const setShowPicker = ref(false);
|
const setShowPicker = ref(false);
|
||||||
|
|
||||||
|
const selectVal1 = ref('all');
|
||||||
|
const selectVal2 = ref('普通');
|
||||||
|
const selectOpt1 = ref([{ text: '全部', value: 'all' }]);
|
||||||
|
const selectOpt2 = ref([{ text: '重要', value: '重要' }, { text: '普通', value: '普通' }]);
|
||||||
|
|
||||||
|
const addressList = ref([]);
|
||||||
|
|
||||||
|
const showFaviLog = ref(false);
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
if (route.query.act === 'add') {
|
||||||
|
let res = await addUserFavi({ uf_user_id: route.query.cardid });
|
||||||
|
if (res.code === 445) {
|
||||||
|
showToast('您為基本型用戶僅能最多收藏10人');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
initData();
|
||||||
|
getCateList();
|
||||||
|
});
|
||||||
|
|
||||||
|
const initData = async () => {
|
||||||
|
let res = await getUserFaviList(search.value);
|
||||||
|
if (res.code === 200) {
|
||||||
|
addressList.value = res.data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getCateList = async () => {
|
||||||
|
let res = await getUserCateList();
|
||||||
|
if (res.code === 200) {
|
||||||
|
columns.value = [columns.value[0], ...res.data];
|
||||||
|
columns2.value = [columns2.value[0], ...res.data];
|
||||||
|
if (res.data.length > 0) {
|
||||||
|
modalForm.value.sort = res.data;
|
||||||
|
} else {
|
||||||
|
modalForm.value.sort = [_.cloneDeep(defaultCate)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 複製連結
|
||||||
|
const doCopy = (text) => {
|
||||||
|
toClipboard(text);
|
||||||
|
showToast("已放入剪貼簿");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteFavi = async (id) => {
|
||||||
|
// vant 詢問是否刪除
|
||||||
|
showConfirmDialog({
|
||||||
|
title: '確認刪除',
|
||||||
|
message:
|
||||||
|
'是否確認刪除好友?',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
confirmButtonText: '確認',
|
||||||
|
})
|
||||||
|
.then(async () => {
|
||||||
|
let res = await deleteUserFavi(id);
|
||||||
|
if (res.code === 200) {
|
||||||
|
initData();
|
||||||
|
showSuccessToast('刪除成功')
|
||||||
|
} else {
|
||||||
|
showToast('刪除失敗')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleGoNfc = (item) => {
|
||||||
|
window.open(item.nfcurl, '_blank');
|
||||||
|
};
|
||||||
|
|
||||||
|
// START: 通訊錄類別
|
||||||
|
const fieldValue = ref('全部-全部');
|
||||||
|
const showCatePicker = ref(false);
|
||||||
|
|
||||||
|
const customFieldName = {
|
||||||
|
text: 'name',
|
||||||
|
value: 'id',
|
||||||
|
children: 'children',
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns = ref([
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
name: '全部',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
name: '全部'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const onCateConfirm = async (value) => {
|
||||||
|
search.value.cate = value.selectedValues[1]
|
||||||
|
showCatePicker.value = false
|
||||||
|
};
|
||||||
|
|
||||||
|
const onCateChange = (value) => {
|
||||||
|
fieldValue.value = value.selectedOptions.map((item) => item.name).join('-');
|
||||||
|
};
|
||||||
|
|
||||||
|
// END: 通訊錄類別
|
||||||
|
|
||||||
|
// START: 更改好友類別
|
||||||
|
const columns2 = ref([
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
name: '未分類',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
name: '未分類'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const showChangeCatePicker = ref(false);
|
||||||
|
const changeUserId = ref('');
|
||||||
|
|
||||||
|
const handleChangeCate = (userId) => {
|
||||||
|
changeUserId.value = userId;
|
||||||
|
showChangeCatePicker.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChangeCateConfirm = async (value) => {
|
||||||
|
|
||||||
|
let res = await setUserFaviCate({ uf_user_id: changeUserId.value, cate_id: value.selectedValues[1] });
|
||||||
|
if (res.code === 200) {
|
||||||
|
getCateList();
|
||||||
|
showSuccessToast('更新成功')
|
||||||
|
} else {
|
||||||
|
showToast('更新失敗')
|
||||||
|
}
|
||||||
|
showChangeCatePicker.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChangeCateChange = (value) => {
|
||||||
|
// console.log('Change Category');
|
||||||
|
};
|
||||||
|
|
||||||
|
// END: 更改好友類別
|
||||||
|
|
||||||
|
// START: 編輯通訊錄
|
||||||
|
const defaultCate = {
|
||||||
|
"id": 0,
|
||||||
|
"name": ""
|
||||||
|
};
|
||||||
|
|
||||||
|
const modalForm = ref({
|
||||||
|
page: 1,
|
||||||
|
sort: [_.cloneDeep(defaultCate)]
|
||||||
|
});
|
||||||
|
|
||||||
|
const sel1Change = (value) => {
|
||||||
|
if (value != 'all') {
|
||||||
|
let child = modalForm.value.sort[value].children;
|
||||||
|
let ary = [];
|
||||||
|
|
||||||
|
child.forEach((item, i) => {
|
||||||
|
ary.push({
|
||||||
|
text: item.name,
|
||||||
|
value: item.name
|
||||||
|
})
|
||||||
|
});
|
||||||
|
selectOpt2.value = ary;
|
||||||
|
selectVal2.value = child[0].name;
|
||||||
|
} else {
|
||||||
|
selectOpt2.value = [];
|
||||||
|
selectVal2.value = '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const addCard = () => {
|
||||||
|
modalForm.value.sort.push(_.cloneDeep(defaultCate));
|
||||||
|
modalForm.value.page = modalForm.value.sort.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
const delCard = (page) => {
|
||||||
|
if (page > 1) {
|
||||||
|
modalForm.value.page = page - 1;
|
||||||
|
}
|
||||||
|
modalForm.value.sort.splice(page - 1, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addBtn = (page) => {
|
||||||
|
if (!modalForm.value.sort[page - 1].children) {
|
||||||
|
modalForm.value.sort[page - 1].children = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
modalForm.value.sort[page - 1].children.push(_.cloneDeep(defaultCate));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const moveCard = (type, page) => {
|
||||||
|
if (type === 0) {
|
||||||
|
if (page !== 1) {
|
||||||
|
[modalForm.value.sort[page - 1], modalForm.value.sort[page - 2]] = [
|
||||||
|
modalForm.value.sort[page - 2],
|
||||||
|
modalForm.value.sort[page - 1],
|
||||||
|
];
|
||||||
|
modalForm.value.page = page - 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (page !== modalForm.value.sort.length) {
|
||||||
|
[modalForm.value.sort[page], modalForm.value.sort[page - 1]] = [
|
||||||
|
modalForm.value.sort[page - 1],
|
||||||
|
modalForm.value.sort[page],
|
||||||
|
];
|
||||||
|
modalForm.value.page = page + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const delBtn = (index) => {
|
||||||
|
modalForm.value.sort[modalForm.value.page - 1].children.splice(index, 1);
|
||||||
|
if (modalForm.value.sort[modalForm.value.page - 1].children.length === 0) {
|
||||||
|
delete modalForm.value.sort[modalForm.value.page - 1].children;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const moveBtn = (type, index) => {
|
||||||
|
if (type === 0) {
|
||||||
|
if (index !== 0) {
|
||||||
|
[
|
||||||
|
modalForm.value.sort[modalForm.value.page - 1].children[index],
|
||||||
|
modalForm.value.sort[modalForm.value.page - 1].children[index - 1],
|
||||||
|
] = [
|
||||||
|
modalForm.value.sort[modalForm.value.page - 1].children[index - 1],
|
||||||
|
modalForm.value.sort[modalForm.value.page - 1].children[index],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (index + 1 !== modalForm.value.sort[modalForm.value.page - 1].children.length) {
|
||||||
|
[
|
||||||
|
modalForm.value.sort[modalForm.value.page - 1].children[index + 1],
|
||||||
|
modalForm.value.sort[modalForm.value.page - 1].children[index],
|
||||||
|
] = [
|
||||||
|
modalForm.value.sort[modalForm.value.page - 1].children[index],
|
||||||
|
modalForm.value.sort[modalForm.value.page - 1].children[index + 1],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const onSubmit = async () => {
|
||||||
|
let res = await updateUserCate({ category: modalForm.value.sort })
|
||||||
|
if (res.code === 200) {
|
||||||
|
getCateList();
|
||||||
|
showSuccessToast('更新成功')
|
||||||
|
// router.push('/member')
|
||||||
|
} else {
|
||||||
|
showToast('更新失敗')
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const search = ref({
|
||||||
|
cate: 0,
|
||||||
|
area: 0,
|
||||||
|
sex: 2,
|
||||||
|
keyword: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const tab2showPicker = ref(false);
|
||||||
|
|
||||||
|
const tab3showPicker = ref(false)
|
||||||
|
const tab3columns = ref([])
|
||||||
|
const areaName = ref('')
|
||||||
|
|
||||||
|
//取得區域資料
|
||||||
|
let areaRes = await getAreaList()
|
||||||
|
if (areaRes.code === 200) {
|
||||||
|
tab3columns.value = areaRes.data
|
||||||
|
// tab3columns加上第一項為全部
|
||||||
|
tab3columns.value.unshift({
|
||||||
|
text: '全部',
|
||||||
|
value: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
//取得區域名稱
|
||||||
|
// if (areaRes.data.length > 0) {
|
||||||
|
// const findRes = _.find(areaRes.data, { value: form.value.area })
|
||||||
|
// if (findRes) {
|
||||||
|
// areaName.value = findRes.text
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
const tab3OnConfirm = (value) => {
|
||||||
|
areaName.value = value.selectedOptions[0].text
|
||||||
|
search.value.area = value.selectedOptions[0].value
|
||||||
|
tab3showPicker.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const tab4showPicker = ref(false);
|
||||||
|
const tab4columns = ref([
|
||||||
|
{
|
||||||
|
text: '全部',
|
||||||
|
value: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '男',
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '女',
|
||||||
|
value: 0
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
const sexName = ref('')
|
||||||
|
|
||||||
|
const tab4OnConfirm = (value) => {
|
||||||
|
sexName.value = value.selectedOptions[0].text
|
||||||
|
search.value.sex = value.selectedOptions[0].value
|
||||||
|
tab4showPicker.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const handleSearch = async () => {
|
||||||
|
let res = await getUserFaviList(search.value);
|
||||||
|
if (res.code === 200) {
|
||||||
|
addressList.value = res.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// START:好友往來紀錄
|
||||||
|
const faviLogId = ref(0) // 往來紀錄id
|
||||||
|
const faviLogMsg = ref('') // 輸入的往來紀錄訊息
|
||||||
|
const faviLogList = ref([]) // 往來紀錄列表
|
||||||
|
const faviLogEditId = ref(0) // 編輯往來紀錄id
|
||||||
|
|
||||||
|
const handleFaviLog = (id) => {
|
||||||
|
showFaviLog.value = true
|
||||||
|
faviLogId.value = id
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(faviLogId, async (val) => {
|
||||||
|
if (val > 0) {
|
||||||
|
// 取得往來紀錄
|
||||||
|
loadFaviLog()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const loadFaviLog = async () => {
|
||||||
|
let res = await getFaviLogs(faviLogId.value)
|
||||||
|
if(res.code === 200){
|
||||||
|
faviLogList.value = res.data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAddFaviLog = async () => {
|
||||||
|
let res = await addFaviLog({ uf_id: faviLogId.value, note: faviLogMsg.value })
|
||||||
|
if(res.code === 200){
|
||||||
|
showToast('新增成功')
|
||||||
|
faviLogMsg.value = ''
|
||||||
|
loadFaviLog()
|
||||||
|
}else{
|
||||||
|
showFailToast('新增失敗')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDeleteFaviLog = async (id) => {
|
||||||
|
let res = await deleteFaviLog(id)
|
||||||
|
if(res.code === 200){
|
||||||
|
showToast('刪除成功')
|
||||||
|
loadFaviLog()
|
||||||
|
}else{
|
||||||
|
showFailToast('刪除失敗')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleEditFaviLog = async (item) => {
|
||||||
|
let res = await updateFaviLog(item)
|
||||||
|
if(res.code === 200){
|
||||||
|
showToast('更新成功')
|
||||||
|
faviLogEditId.value = 0
|
||||||
|
// loadFaviLog()
|
||||||
|
}else{
|
||||||
|
showFailToast('更新失敗')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCloseFaviLog = () => {
|
||||||
|
faviLogId.value = 0
|
||||||
|
faviLogMsg.value = ''
|
||||||
|
showFaviLog.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatNote = (note) => {
|
||||||
|
// 匹配電郵地址
|
||||||
|
const emailRegex = /([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/gi;
|
||||||
|
// 匹配電話號碼, 格式為0983214434
|
||||||
|
const phoneRegex = /(0[2-9]\d{7,8}|09\d{8})/g;
|
||||||
|
// 匹配網址
|
||||||
|
const urlRegex = /(https?:\/\/[^\s]+)/g;
|
||||||
|
|
||||||
|
let formattedNote = note
|
||||||
|
.replace(emailRegex, '<a href="mailto:$1">$1</a>')
|
||||||
|
.replace(phoneRegex, '<a href="tel:$1">$1</a>')
|
||||||
|
.replace(urlRegex, '<a href="$1" target="_blank">$1</a>');
|
||||||
|
|
||||||
|
return formattedNote;
|
||||||
|
};
|
||||||
|
|
||||||
|
// END:好友往來紀錄
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="member page">
|
<div class="address page">
|
||||||
<van-nav-bar
|
<van-nav-bar class="bg-skyBlue py-1" left-arrow right-arrow @click-left="$router.push('/')"
|
||||||
class="bg-skyBlue py-1"
|
@click-right="setShowPicker = true">
|
||||||
left-arrow
|
|
||||||
right-arrow
|
|
||||||
@click-left="$router.push('/')"
|
|
||||||
@click-right="setShowPicker = true"
|
|
||||||
>
|
|
||||||
<template #title>
|
<template #title>
|
||||||
<h5 class="text-white mb-1"><strong>通訊錄</strong></h5>
|
<h5 class="text-white mb-1"><strong>通訊錄</strong></h5>
|
||||||
</template>
|
</template>
|
||||||
<template #left>
|
<template #left>
|
||||||
<h4><i class="fa-solid fa-angle-left text-white" :style="{ opacity: 0.5 }"></i></h4>
|
<h4><i class="fa-solid fa-angle-left text-white" :style="{ opacity: 0.5 }"></i></h4>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #right>
|
<template #right>
|
||||||
<h4><i class="fa-solid fa-sliders text-white" :style="{opacity:0.5}"></i></h4>
|
<h4><i class="fa-solid fa-gear text-white" :style="{ opacity: 0.5 }"></i></h4>
|
||||||
</template>
|
</template>
|
||||||
</van-nav-bar>
|
</van-nav-bar>
|
||||||
|
|
||||||
<van-popup v-model:show="setShowPicker" position="bottom">
|
<div class="content">
|
||||||
<van-picker
|
<!-- START: 通訊錄類別 -->
|
||||||
:columns="setColumns"
|
<van-cell-group inset>
|
||||||
@confirm="setConfirm"
|
<van-field v-model="fieldValue" is-link readonly label="類別" placeholder="通訊錄類別"
|
||||||
@cancel="setShowPicker = false"
|
@click="showCatePicker = true" />
|
||||||
/>
|
<van-popup v-model:show="showCatePicker" round position="bottom">
|
||||||
|
<van-picker :columns="columns" :columns-field-names="customFieldName" confirm-button-text="確認"
|
||||||
|
cancel-button-text="取消" @cancel="showCatePicker = false" @confirm="onCateConfirm" @change="onCateChange" />
|
||||||
|
</van-popup>
|
||||||
|
</van-cell-group>
|
||||||
|
<van-cell-group inset>
|
||||||
|
<van-row gutter="0" align="center">
|
||||||
|
<van-col span="5">
|
||||||
|
<van-field v-model="areaName" is-link readonly name="picker" :border="false" placeholder="縣市"
|
||||||
|
@click="tab3showPicker = true" />
|
||||||
|
<van-popup v-model:show="tab3showPicker" position="bottom">
|
||||||
|
<van-picker confirm-button-text="確認" cancel-button-text="取消" :columns="tab3columns"
|
||||||
|
@confirm="tab3OnConfirm" @cancel="tab3showPicker = false" />
|
||||||
</van-popup>
|
</van-popup>
|
||||||
|
</van-col>
|
||||||
|
<van-col span="5">
|
||||||
|
<van-field v-model="sexName" is-link readonly name="picker" :border="false" placeholder="性別"
|
||||||
|
@click="tab4showPicker = true" />
|
||||||
|
<van-popup v-model:show="tab4showPicker" position="bottom">
|
||||||
|
<van-picker confirm-button-text="確認" cancel-button-text="取消" :columns="tab4columns"
|
||||||
|
@confirm="tab4OnConfirm" @cancel="tab4showPicker = false" />
|
||||||
|
</van-popup>
|
||||||
|
</van-col>
|
||||||
|
<van-col span="14">
|
||||||
|
<van-search v-model="search.keyword" show-action placeholder="請輸入搜尋關鍵字" @search="handleSearch">
|
||||||
|
<template #action>
|
||||||
|
<van-button class="btn-darkBlue" @click="handleSearch">
|
||||||
|
搜索
|
||||||
|
</van-button>
|
||||||
|
</template>
|
||||||
|
</van-search>
|
||||||
|
</van-col>
|
||||||
|
</van-row>
|
||||||
|
</van-cell-group>
|
||||||
|
<!-- END: 通訊錄類別 -->
|
||||||
|
|
||||||
|
<van-cell-group inset>
|
||||||
|
<van-list>
|
||||||
|
<div class="list-item" style="font-weight: 700;">
|
||||||
|
<div class="left">
|
||||||
|
電子名片
|
||||||
|
</div>
|
||||||
|
<div class="right">
|
||||||
|
分類/紀錄/刪除
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="list-item" v-for="(item, index) in addressList" :data-cateid="item.user_cate_id" :key="index">
|
||||||
|
<div class="left" @click="handleGoNfc(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.line }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="right">
|
||||||
|
<van-button size="small" class="border-0" @click="handleChangeCate(item.user_id)">
|
||||||
|
<h5><i class="fa-solid fa-heart text-darkBlue"></i></h5>
|
||||||
|
</van-button>
|
||||||
|
<van-button size="small" class="border-0" @click="handleFaviLog(item.uf_id)">
|
||||||
|
<h5><i class="fa-solid fa-share-nodes text-darkBlue"></i></h5>
|
||||||
|
</van-button>
|
||||||
|
<van-button size="small" class="border-0" @click="handleDeleteFavi(item.uf_id)">
|
||||||
|
<h5><i class="fa-solid fa-trash text-darkBlue"></i></h5>
|
||||||
|
</van-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</van-list>
|
||||||
|
</van-cell-group>
|
||||||
|
</div>
|
||||||
|
<!-- START: 編輯通訊錄 -->
|
||||||
|
<van-dialog v-model:show="setShowPicker" width="400" showCancelButton confirm-button-text="確認修改"
|
||||||
|
@confirm="onSubmit">
|
||||||
|
|
||||||
|
<van-form @submit="onSubmit">
|
||||||
|
<div id="app" class="address-block">
|
||||||
|
<div class="bg-lightPink px-2 pt-3">
|
||||||
|
<ul class="nav nav-tabs">
|
||||||
|
<li class="nav-item" v-for="(card, index) in modalForm.sort" :key="index"
|
||||||
|
@click="modalForm.page = index + 1">
|
||||||
|
<button type="button" class="nav-link" :class="{ active: modalForm.page === index + 1 }">
|
||||||
|
{{ index + 1 }}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" @click="addCard" v-if="modalForm.sort.length < 10">
|
||||||
|
<button type="button" class="nav-link">
|
||||||
|
<i class="fa fa-plus-circle"></i>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<van-cell-group class="m-0 pt-2">
|
||||||
|
<van-field label="調整卡片順序" :border="false" v-if="modalForm.sort.length > 1">
|
||||||
|
<template #button>
|
||||||
|
<van-button size="small" class="ml-1 btn-skyBlue" icon="arrow-left"
|
||||||
|
@click="moveCard(0, modalForm.page)">前移</van-button>
|
||||||
|
<van-button size="small" class="ml-1 btn-skyBlue" icon="arrow"
|
||||||
|
@click="moveCard(1, modalForm.page)">後移</van-button>
|
||||||
|
<van-button size="small" class="ml-1 btn-tomatoRed" icon="delete-o"
|
||||||
|
@click="delCard(modalForm.page)"></van-button>
|
||||||
|
</template>
|
||||||
|
</van-field>
|
||||||
|
|
||||||
|
<van-field v-model="modalForm.sort[modalForm.page - 1].name" label="分類名稱" id="vcard-title"
|
||||||
|
input-align="right" placeholder="請輸入分類名稱" />
|
||||||
|
|
||||||
|
<div class="listCnt">
|
||||||
|
<div class="item" v-for="(btn, index) in modalForm.sort[modalForm.page - 1].children" :key="index">
|
||||||
|
<van-field v-model="btn.name" id="cardbtn-text-0" placeholder="請輸入子項目名稱" class="bg-transparent">
|
||||||
|
<template #button>
|
||||||
|
<van-button size="small" class="bg-transparent border-0" icon="arrow-up" @click="moveBtn(0, index)"
|
||||||
|
v-if="modalForm.sort[modalForm.page - 1].children.length > 1"></van-button>
|
||||||
|
<van-button size="small" class="bg-transparent border-0" icon="arrow-down"
|
||||||
|
@click="moveBtn(1, index)"
|
||||||
|
v-if="modalForm.sort[modalForm.page - 1].children.length > 1"></van-button>
|
||||||
|
<van-button size="small" class="bg-transparent border-0" icon="delete-o"
|
||||||
|
@click="delBtn(index)"></van-button>
|
||||||
|
</template>
|
||||||
|
</van-field>
|
||||||
|
</div>
|
||||||
|
<van-button block class="btn-tomatoRed" icon="add-o" @click="addBtn(modalForm.page)">
|
||||||
|
<h6>新增按鈕</h6>
|
||||||
|
</van-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</van-cell-group>
|
||||||
|
</div>
|
||||||
|
</van-form>
|
||||||
|
|
||||||
|
</van-dialog>
|
||||||
|
<!-- END: 編輯通訊錄 -->
|
||||||
|
<van-popup v-model:show="showChangeCatePicker" round position="bottom">
|
||||||
|
<van-picker :columns="columns2" :columns-field-names="customFieldName" confirm-button-text="確認"
|
||||||
|
cancel-button-text="取消" @cancel="showChangeCatePicker = false" @confirm="onChangeCateConfirm"
|
||||||
|
@change="onChangeCateChange" />
|
||||||
|
</van-popup>
|
||||||
|
<!-- START: 往來紀錄 -->
|
||||||
|
<van-popup v-model:show="showFaviLog" round closeable position="bottom" @close="handleCloseFaviLog" :style="{ height: '90%' }">
|
||||||
|
<div style="padding-top: 50px;border: 1px;height: 100%;" class="content">
|
||||||
|
<!-- 好友往來紀錄 -->
|
||||||
|
<van-cell-group inset>
|
||||||
|
<van-field v-model="faviLogMsg" center label="往來紀錄" placeholder="請輸入往來紀錄">
|
||||||
|
<template #button>
|
||||||
|
<van-button size="small" class="btn-darkBlue" @click="handleAddFaviLog">送出</van-button>
|
||||||
|
</template>
|
||||||
|
</van-field>
|
||||||
|
</van-cell-group>
|
||||||
|
<van-cell-group inset>
|
||||||
|
<van-steps direction="vertical">
|
||||||
|
<van-step v-for="item in faviLogList" :key="item.id">
|
||||||
|
<div class="favi-log">
|
||||||
|
<div class="title">
|
||||||
|
<div class="left">
|
||||||
|
<h5>{{ item.create_time }}</h5>
|
||||||
|
</div>
|
||||||
|
<div class="right">
|
||||||
|
<van-button size="small" plain type="primary" @click="faviLogEditId = item.id">修改</van-button>
|
||||||
|
|
||||||
|
<van-button size="small" type="danger" @click="handleDeleteFaviLog(item.id)">刪除</van-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="body">
|
||||||
|
<template v-if="faviLogEditId === item.id">
|
||||||
|
<van-field v-model="item.note" center>
|
||||||
|
<template #button>
|
||||||
|
<van-button size="small" type="primary" @click="handleEditFaviLog(item)">送出</van-button>
|
||||||
|
</template>
|
||||||
|
</van-field>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<p v-html="formatNote(item.note)"></p>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</van-step>
|
||||||
|
</van-steps>
|
||||||
|
</van-cell-group>
|
||||||
|
</div>
|
||||||
|
</van-popup>
|
||||||
|
<!-- END: 往來紀錄 -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
.address {
|
||||||
|
>.content {
|
||||||
|
min-height: calc(100vh - 54px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tabs {
|
||||||
|
.nav-link {
|
||||||
|
color: #4a677d;
|
||||||
|
background-color: #fff;
|
||||||
|
border-color: transparent;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item.show .nav-link,
|
||||||
|
.nav-link.active {
|
||||||
|
color: #fff;
|
||||||
|
background-color: #4a677d;
|
||||||
|
border-color: #4a677d #4a677d #4a677d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.listCnt {
|
||||||
|
padding: 15px;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
border: 1px #ddd solid;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.favi-log {
|
||||||
|
.title {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.left {
|
||||||
|
flex: 1 0 0%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right {
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.body {
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
:deep(a) {
|
||||||
|
color: #1989fa;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.address-block {
|
||||||
|
max-height: 80vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.van-popup__close-icon) {
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -1,344 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="reg-container">
|
|
||||||
<van-nav-bar :title="title" />
|
|
||||||
<van-form @submit="onSubmit">
|
|
||||||
<van-cell-group inset>
|
|
||||||
<van-field
|
|
||||||
v-model="form.real_name"
|
|
||||||
label="姓名"
|
|
||||||
name="pattern"
|
|
||||||
required
|
|
||||||
placeholder="請輸入您的姓名"
|
|
||||||
:rules="[{ required: true, message: '姓名為必填' }]"
|
|
||||||
/>
|
|
||||||
<van-field
|
|
||||||
v-model="form.company"
|
|
||||||
label="公司名稱"
|
|
||||||
name=""
|
|
||||||
required
|
|
||||||
placeholder="請輸入您的公司名稱"
|
|
||||||
:rules="[{ required: true, message: '公司名稱必填' }]"
|
|
||||||
/>
|
|
||||||
<van-field
|
|
||||||
v-model="form.title"
|
|
||||||
label="職稱"
|
|
||||||
name=""
|
|
||||||
placeholder="請輸入您的職稱"
|
|
||||||
/>
|
|
||||||
<van-field
|
|
||||||
v-model="form.phone"
|
|
||||||
label="手機"
|
|
||||||
name=""
|
|
||||||
required
|
|
||||||
placeholder="Ex. 0900000001 不要有空格"
|
|
||||||
:rules="[
|
|
||||||
{ required: true, message: '手機號必填' },
|
|
||||||
{ pattern: /\d{10}/, message: '手機號格式錯誤' },
|
|
||||||
]"
|
|
||||||
/>
|
|
||||||
<van-field
|
|
||||||
v-model="form.tel"
|
|
||||||
label="市話"
|
|
||||||
name=""
|
|
||||||
placeholder="請輸入您的市話"
|
|
||||||
/>
|
|
||||||
<van-field
|
|
||||||
v-model="form.email"
|
|
||||||
label="Email"
|
|
||||||
name=""
|
|
||||||
required
|
|
||||||
placeholder="請輸入您的Email"
|
|
||||||
:rules="[
|
|
||||||
{ required: true, message: 'Email必填' },
|
|
||||||
{
|
|
||||||
pattern: /^([\w\.\-]){1,64}\@([\w\.\-]){1,64}/,
|
|
||||||
message: 'Email格式錯誤',
|
|
||||||
},
|
|
||||||
]"
|
|
||||||
/>
|
|
||||||
<van-field
|
|
||||||
v-model="form.address"
|
|
||||||
label="住址"
|
|
||||||
name=""
|
|
||||||
placeholder="請輸入您的地址"
|
|
||||||
/>
|
|
||||||
<van-field
|
|
||||||
v-model="form.url"
|
|
||||||
label="網址"
|
|
||||||
name=""
|
|
||||||
placeholder="請輸入您的網址"
|
|
||||||
:rules="[
|
|
||||||
{ validator: validatorUrl, message: '網址格式不正確,Ex. http://' },
|
|
||||||
]"
|
|
||||||
/>
|
|
||||||
<van-field
|
|
||||||
v-model="form.line"
|
|
||||||
label="Line"
|
|
||||||
name=""
|
|
||||||
placeholder="請輸入您的Line ID"
|
|
||||||
/>
|
|
||||||
<van-field
|
|
||||||
v-model="form.facebook"
|
|
||||||
label="Facebook"
|
|
||||||
name=""
|
|
||||||
placeholder="請輸入您的臉書連結"
|
|
||||||
/>
|
|
||||||
<van-field
|
|
||||||
v-model="form.ig"
|
|
||||||
label="IG"
|
|
||||||
name=""
|
|
||||||
placeholder="請輸入您的IG ID"
|
|
||||||
/>
|
|
||||||
<van-field
|
|
||||||
v-model="form.youtube"
|
|
||||||
label="YouTube"
|
|
||||||
name=""
|
|
||||||
placeholder="請輸入您的Youtube連結"
|
|
||||||
/>
|
|
||||||
<van-uploader :after-read="afterRead" :max-count="1" name="averter">
|
|
||||||
<div class="upload-main">
|
|
||||||
<img
|
|
||||||
class="upload-img"
|
|
||||||
:src="form.avatar"
|
|
||||||
alt=""
|
|
||||||
v-if="form.avatar"
|
|
||||||
/>
|
|
||||||
<img
|
|
||||||
class="upload-img"
|
|
||||||
src="@/assets/images/upload.jpg"
|
|
||||||
alt=""
|
|
||||||
v-else
|
|
||||||
/>
|
|
||||||
<p>上傳圖片,預設為Line頭像</p>
|
|
||||||
</div>
|
|
||||||
</van-uploader>
|
|
||||||
</van-cell-group>
|
|
||||||
<div style="margin: 16px">
|
|
||||||
<van-button round block type="primary" native-type="submit">
|
|
||||||
送出註冊
|
|
||||||
</van-button>
|
|
||||||
<br />
|
|
||||||
<van-button round block type="default" @click="leaveReg">
|
|
||||||
以後在說
|
|
||||||
</van-button>
|
|
||||||
</div>
|
|
||||||
</van-form>
|
|
||||||
<van-overlay :show="crop.show" @click="crop.show = false" />
|
|
||||||
<div class="cropper-section" v-if="crop.show">
|
|
||||||
<div class="crop-area">
|
|
||||||
<cropper
|
|
||||||
class="cropper"
|
|
||||||
ref="myCrop"
|
|
||||||
:src="crop.img"
|
|
||||||
:stencil-props="{
|
|
||||||
aspectRatio: 1 / 1,
|
|
||||||
}"
|
|
||||||
:auto-zoom="true"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="crop-btn">
|
|
||||||
<van-button type="primary" size="small" plain @click="onClose"
|
|
||||||
>取消</van-button
|
|
||||||
>
|
|
||||||
<van-button type="success" size="small" plain @click="onCrop"
|
|
||||||
>剪裁</van-button
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import axios from "axios";
|
|
||||||
|
|
||||||
import { ref, inject } from "vue";
|
|
||||||
|
|
||||||
import store from "@/store";
|
|
||||||
import router from "@/router";
|
|
||||||
import { useRoute } from "vue-router";
|
|
||||||
|
|
||||||
import { showToast } from "vant";
|
|
||||||
import { showLoadingToast,showSuccessToast } from 'vant';
|
|
||||||
|
|
||||||
import { Cropper } from "vue-advanced-cropper";
|
|
||||||
import "vue-advanced-cropper/dist/style.css";
|
|
||||||
|
|
||||||
import { register, checkLineId } from "@/api";
|
|
||||||
|
|
||||||
const URL = window.URL || window.webkitURL;
|
|
||||||
|
|
||||||
const route = useRoute();
|
|
||||||
|
|
||||||
const form = ref({
|
|
||||||
verify: route.query.verify || null,
|
|
||||||
aid: route.query.aid || undefined,
|
|
||||||
});
|
|
||||||
|
|
||||||
const title = ref("註冊成為會員");
|
|
||||||
|
|
||||||
const myCrop = ref(null);
|
|
||||||
|
|
||||||
const crop = ref({
|
|
||||||
show: false,
|
|
||||||
img: null,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (route.query.verify) {
|
|
||||||
title.value = "會員開通";
|
|
||||||
}
|
|
||||||
|
|
||||||
const validatorUrl = (val) => {
|
|
||||||
if (val.length > 0) {
|
|
||||||
return /(https?:\/\/|line:\/\/|tel:|mailto:)\S+/.test(val);
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const leaveReg = () => {
|
|
||||||
window.location.replace("/error.html");
|
|
||||||
};
|
|
||||||
|
|
||||||
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 onClose = () => {
|
|
||||||
crop.value.show = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
const afterRead = async (file, name) => {
|
|
||||||
crop.value.show = true;
|
|
||||||
|
|
||||||
const ofile = file.file;
|
|
||||||
|
|
||||||
crop.value.img = URL.createObjectURL(ofile);
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
const onSubmit = async () => {
|
|
||||||
const liff = window.liff;
|
|
||||||
try {
|
|
||||||
if (!liff.isLoggedIn()) liff.login({ redirectUri: window.location.href });
|
|
||||||
} catch (err) {
|
|
||||||
console.log(`liff.state init error ${err}`);
|
|
||||||
showToast("登入失敗。請聯絡管理員");
|
|
||||||
router.push("/login");
|
|
||||||
}
|
|
||||||
|
|
||||||
const profile = await liff.getProfile();
|
|
||||||
|
|
||||||
let checkRes = await checkLineId(profile.userId);
|
|
||||||
|
|
||||||
if (checkRes.code !== 200) {
|
|
||||||
showToast("您已是我們的會員,請直接登入");
|
|
||||||
router.push("/login");
|
|
||||||
}
|
|
||||||
|
|
||||||
const id_token = liff.getIDToken();
|
|
||||||
|
|
||||||
showLoadingToast({
|
|
||||||
duration: 0,
|
|
||||||
message: "資料傳送中...",
|
|
||||||
forbidClick: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
let regRes = await register({
|
|
||||||
line_id: profile.userId,
|
|
||||||
line_name: profile.displayName,
|
|
||||||
line_picture: profile.pictureUrl,
|
|
||||||
token: id_token,
|
|
||||||
...form.value,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (regRes.code === 500) {
|
|
||||||
if (liff.isLoggedIn()) {
|
|
||||||
liff.logout();
|
|
||||||
}
|
|
||||||
showToast("line 登入已過期");
|
|
||||||
return;
|
|
||||||
} else if (regRes.code === 200) {
|
|
||||||
showToast("註冊成功");
|
|
||||||
sessionStorage.setItem("token", regRes.data.token);
|
|
||||||
sessionStorage.setItem("uid", regRes.data.uid);
|
|
||||||
return router.push("/");
|
|
||||||
} else {
|
|
||||||
showToast("註冊失敗");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="less" scoped>
|
|
||||||
.container {
|
|
||||||
padding-bottom: 30px;
|
|
||||||
}
|
|
||||||
.title {
|
|
||||||
font-size: 20px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-img {
|
|
||||||
width: 80px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cropper {
|
|
||||||
height: 300px;
|
|
||||||
// width: 300px;
|
|
||||||
background: #ddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cropper-section {
|
|
||||||
margin: 0 auto;
|
|
||||||
position: fixed;
|
|
||||||
text-align: center;
|
|
||||||
top: 50px;
|
|
||||||
// left: 0;
|
|
||||||
height: 350px;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 500px;
|
|
||||||
background: #ddd;
|
|
||||||
z-index: 8888;
|
|
||||||
.crop-area {
|
|
||||||
margin: 5 auto;
|
|
||||||
width: 100%;
|
|
||||||
height: 330px;
|
|
||||||
}
|
|
||||||
.crop-btn {
|
|
||||||
background-color: #666;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||