This commit is contained in:
wenfp
2026-08-21 14:12:00 +08:00
parent 68dc57ffe5
commit 13bb939099
13 changed files with 510 additions and 415 deletions
+22 -23
View File
@@ -1,26 +1,25 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="" manifest="IGNORE.manifest"> <html lang="" manifest="IGNORE.manifest">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8" />
<meta http-equiv="Pragma" content="no-cache"> <meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Cache" content="no-cache"> <meta http-equiv="Cache" content="no-cache" />
<meta http-equiv="Cache-control" content="no-cache,must-revalidate"> <meta http-equiv="Cache-control" content="no-cache,must-revalidate" />
<meta http-equiv="cache-control" content="max-age=0" /> <meta http-equiv="cache-control" content="max-age=0" />
<meta http-equiv="cache-control" content="no-cache" /> <meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="0" /> <meta http-equiv="expires" content="0" />
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" /> <meta name="referrer" content="never" />
<meta name="referrer" content="never"> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no" />
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no"> <script src="https://res2.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
<script src="https://res2.wx.qq.com/open/js/jweixin-1.6.0.js"></script> <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> <title></title>
<title></title> </head>
</head> <body>
<body> <noscript>
<noscript> <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> </noscript>
</noscript> <div id="app"></div>
<div id="app"></div> <!-- built files will be auto injected -->
<!-- built files will be auto injected --> </body>
</body>
</html> </html>
+1 -1
View File
@@ -1,4 +1,4 @@
@import 'variable.scss'; @use "./variable.scss" as *;
.divider { .divider {
height: .24rem; height: .24rem;
+98 -60
View File
@@ -1,88 +1,126 @@
let wechatInstance; let wechatInstance;
import util from "@/util"; let wechatReadyPromise = null;
// import util from "@/util";
function getShareConfig(shareConfig = {}) {
// const link = shareConfig.link || location.href;
return {
title: shareConfig.title || document.title || "自在福田",
desc: shareConfig.desc || "",
link: shareConfig.link,
imgUrl: shareConfig.imgUrl || "",
callback: shareConfig.callback,
};
}
function emitShareCallback(shareConfig, key, res) {
shareConfig.callback &&
shareConfig.callback({
key,
...res,
});
}
function signToWechat(config, shareConfig) { function signToWechat(config, shareConfig) {
if (!wx) { if (!wx) {
console.warn("请安装微信网页JS-SDK, url: https://res2.wx.qq.com/open/js/jweixin-1.6.0.js"); console.warn("请安装微信网页JS-SDK, url: https://res2.wx.qq.com/open/js/jweixin-1.6.0.js");
return;
} }
const defaultConfig = { const defaultConfig = {
...config, ...config,
debug: false, debug: false,
jsApiList: ["onMenuShareTimeline", "onMenuShareAppMessage", "scanQRCode", "getLocation", "openLocation", "updateAppMessageShareData", "updateTimelineShareData"], jsApiList: ["onMenuShareTimeline", "onMenuShareAppMessage", "scanQRCode", "getLocation", "openLocation", "updateAppMessageShareData", "updateTimelineShareData"],
}; };
wx.config(defaultConfig); wechatReadyPromise = new Promise((resolve, reject) => {
wx.ready(function () { wx.ready(function () {
console.log("wechat sdk config success"); wechatInstance = wx;
wechatInstance = wx;
wx.onMenuShareAppMessage({ const safeShareConfig = getShareConfig(shareConfig);
title: shareConfig.title, if (typeof wx.updateAppMessageShareData === "function") {
desc: shareConfig.desc, wx.updateAppMessageShareData({
link: util.addExternalParamsToQuery(shareConfig.link, "no_login", 1), title: safeShareConfig.title,
imgUrl: shareConfig.imgUrl, desc: safeShareConfig.desc,
complete: (res) => { link: safeShareConfig.link,
shareConfig.callback && imgUrl: safeShareConfig.imgUrl,
shareConfig.callback({ complete: (res) => {
key: "updateAppMessageShareData", emitShareCallback(safeShareConfig, "updateAppMessageShareData", res);
...res, },
}); });
}, }
if (typeof wx.updateTimelineShareData === "function") {
wx.updateTimelineShareData({
title: safeShareConfig.title,
link: safeShareConfig.link,
imgUrl: safeShareConfig.imgUrl,
complete: (res) => {
emitShareCallback(safeShareConfig, "updateTimelineShareData", res);
},
});
}
if (typeof wx.onMenuShareAppMessage === "function") {
wx.onMenuShareAppMessage({
title: safeShareConfig.title,
desc: safeShareConfig.desc,
link: safeShareConfig.link,
imgUrl: safeShareConfig.imgUrl,
complete: (res) => {
emitShareCallback(safeShareConfig, "onMenuShareAppMessage", res);
},
});
}
if (typeof wx.onMenuShareTimeline === "function") {
wx.onMenuShareTimeline({
title: safeShareConfig.title,
link: safeShareConfig.link,
imgUrl: safeShareConfig.imgUrl,
complete: (res) => {
emitShareCallback(safeShareConfig, "onMenuShareTimeline", res);
},
});
}
resolve(wx);
}); });
// // 分享朋友圈 if (typeof wx.error === "function") {
wx.onMenuShareTimeline({ wx.error((error) => {
title: shareConfig.title, reject(error);
link: util.addExternalParamsToQuery(shareConfig.link, "no_login", 1), });
imgUrl: shareConfig.imgUrl, }
complete: (res) => {
shareConfig.callback &&
shareConfig.callback({
key: "updateTimelineShareData",
...res,
});
},
});
// wx.updateAppMessageShareData({
// title: shareConfig.title,
// desc: shareConfig.desc,
// link: shareConfig.link,
// imgUrl: shareConfig.imgUrl,
// complete: res => {
// shareConfig.callback && shareConfig.callback({
// key: 'updateAppMessageShareData',
// ...res
// });
// }
// });
// // 分享朋友圈
// wx.updateTimelineShareData({
// title: shareConfig.title,
// link: shareConfig.link,
// imgUrl: shareConfig.imgUrl,
// complete: res => {
// shareConfig.callback && shareConfig.callback({
// key: 'updateTimelineShareData',
// ...res
// });
// }
// });
}); });
wx.config(defaultConfig);
} }
function getLocation() { async function getWechatInstance() {
if (wechatInstance) {
return wechatInstance;
}
if (wechatReadyPromise) {
return wechatReadyPromise;
}
return Promise.reject(new Error("微信 JS-SDK 尚未初始化"));
}
async function getLocation() {
const instance = await getWechatInstance();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
wechatInstance.getLocation({ instance.getLocation({
type: "wgs84", type: "wgs84",
success: (res) => { success: (res) => {
if (res.errMsg === "getLocation:ok") { if (res.errMsg === "getLocation:ok") {
resolve(res); resolve(res);
} else { } else {
reject(); reject(new Error(res.errMsg || "获取定位失败"));
} }
}, },
error: () => { fail: (error) => {
reject(); reject(error || new Error("获取定位失败"));
},
cancel: () => {
reject(new Error("用户取消定位"));
}, },
}); });
}); });
+2
View File
@@ -40,6 +40,8 @@ export default {
height: 2.93rem; height: 2.93rem;
margin-right: 0.4rem; margin-right: 0.4rem;
border-radius: 0.11rem; border-radius: 0.11rem;
object-fit: contain;
background: #f1f1f1;
} }
.info { .info {
flex: 1; flex: 1;
+2 -1
View File
@@ -51,12 +51,13 @@ export default {
align-items: flex-end; align-items: flex-end;
margin-bottom: 0.2rem; margin-bottom: 0.2rem;
font-size: 0.4rem; font-size: 0.4rem;
line-height: 1.3;
} }
p.goods_name { p.goods_name {
font-size: 0.34rem; font-size: 0.34rem;
max-width: 15em; max-width: 15em;
line-height: 1.2; line-height: 1.2;
overflow-x: hidden; overflow: hidden;
color: #666; color: #666;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
+19 -11
View File
@@ -1,12 +1,12 @@
<template> <template>
<div class="goods-detail" v-if="data" :style="{ paddingBottom: paddingBottom + 'px' }"> <div class="goods-detail" v-if="data" :style="{ paddingBottom: paddingBottom + 'px' }">
<swiper class="swiper-container" :options="swiperOption"> <van-swipe class="swiper-container" :autoplay="4000" indicator-color="white">
<swiper-slide> <van-swipe-item v-for="(banner, index) in pictures" :key="index">
<div style="height: 100vw" class="picture"> <div class="picture-wrap">
<img :src="data.cover_url" alt="" /> <img :src="banner" alt="" />
</div> </div>
</swiper-slide> </van-swipe-item>
</swiper> </van-swipe>
<div class="monk-profile"> <div class="monk-profile">
<h1 class="position">{{ data.name }}</h1> <h1 class="position">{{ data.name }}</h1>
<div class="bar"> <div class="bar">
@@ -83,7 +83,6 @@
<script> <script>
import "swiper/css/swiper.css"; import "swiper/css/swiper.css";
import { swiper, swiperSlide } from "vue-awesome-swiper";
import { getGoodsDetail, getOrderCompare, hasLogin } from "@/api"; import { getGoodsDetail, getOrderCompare, hasLogin } from "@/api";
import SelectSpec from "./components/select-spec.vue"; import SelectSpec from "./components/select-spec.vue";
import FillInformation from "./components/fill-information.vue"; import FillInformation from "./components/fill-information.vue";
@@ -92,8 +91,6 @@ import CustomerService from "@/components/customer-service/index.vue";
export default { export default {
components: { components: {
swiper,
swiperSlide,
SelectSpec, SelectSpec,
CustomerService, CustomerService,
FillInformation, FillInformation,
@@ -117,9 +114,9 @@ export default {
dreamInfo: null, dreamInfo: null,
anyPrice: 0, // 随喜金额 anyPrice: 0, // 随喜金额
swiperOption: { swiperOption: {
autoplay: 8000, autoplay: 5000,
initialSlide: 1, initialSlide: 1,
loop: false, loop: true,
pagination: ".swiper-pagination", pagination: ".swiper-pagination",
onSlideChangeEnd: () => {}, onSlideChangeEnd: () => {},
}, },
@@ -146,6 +143,9 @@ export default {
} }
return Number(spec.price); return Number(spec.price);
}, },
pictures() {
return [this.data.cover_url, ...this.data.pictures];
},
priceTotal() { priceTotal() {
if (this.is_auto) { if (this.is_auto) {
return (parseInt(this.priceUnit * 100, 10) * this.quantity * 30) / 100; return (parseInt(this.priceUnit * 100, 10) * this.quantity * 30) / 100;
@@ -397,10 +397,18 @@ $lightWidth: 1.3rem;
} }
.swiper-container { .swiper-container {
background: #f5f5f5; background: #f5f5f5;
height: 10rem;
.picture-wrap {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.picture, .picture,
img { img {
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: cover;
} }
} }
.monk-profile { .monk-profile {
+43 -39
View File
@@ -166,6 +166,14 @@ export default {
this.data = res; this.data = res;
this.$store.commit("setTempleMeritId", res.temple_merit_id); this.$store.commit("setTempleMeritId", res.temple_merit_id);
this.data.icon_data = this.sliceNav(res.icon_data); this.data.icon_data = this.sliceNav(res.icon_data);
this.wechatReady({
...res.shareConfig,
link: location.href.replace("#/home", ""),
title: "菩提家园",
desc: "给心一个家",
imgUrl: "https://temple-h5-new.oss-cn-hangzhou.aliyuncs.com/uploads/dev/2025/04/16/phpGweHzl.jpg",
});
setTimeout(() => { setTimeout(() => {
document.title = "自在福田"; document.title = "自在福田";
}, 10); }, 10);
@@ -265,47 +273,43 @@ export default {
.panel { .panel {
padding-bottom: 0; padding-bottom: 0;
} }
}
.merit-scroll-container { .merit-scroll-container {
margin: 0 0.4rem; margin: 0 0.4rem;
height: 3.39rem; height: 3.39rem;
overflow-x: auto; overflow-x: auto;
.merit-scroll-wrapper { .merit-scroll-wrapper {
white-space: nowrap; white-space: nowrap;
}
} }
} .merit-group {
.merit-group { padding-bottom: 0.4rem;
padding-bottom: 0.4rem;
}
.merit {
width: 3.39rem;
height: 3.39rem;
display: inline-block;
position: relative;
border-radius: 0.16rem;
vertical-align: top;
overflow: hidden;
& ~ .merit {
margin-left: 0.4rem;
} }
img { .merit {
width: 100%; display: flex;
height: 100%; position: relative;
} vertical-align: top;
.title { gap: 0.2rem;
position: absolute; border-bottom: 1px solid #f1f1f1;
left: 0; padding-bottom: 0.4rem;
right: 0; & ~ .merit {
bottom: 0; margin-top: 0.4rem;
height: 0.91rem; }
background: rgba(0, 0, 0, 0.7);
color: white; img {
line-height: 0.91rem; width: 2rem;
overflow: hidden; height: 2rem;
text-overflow: ellipsis; object-fit: cover;
white-space: nowrap; border-radius: 0.1rem;
font-size: 0.37rem; }
padding: 0 0.11rem;
.title {
color: #333;
flex: 1;
white-space: nowrap;
font-size: 0.37rem;
padding: 0 0.11rem;
}
} }
} }
</style> </style>
+19 -31
View File
@@ -14,7 +14,7 @@
</div> </div>
<div class="container"> <div class="container">
<div class="swiper" v-if="data.banner_data.length > 0"> <div class="swiper" v-if="data.banner_data.length > 0">
<van-swipe class="my-swipe" :autoplay="8000" indicator-color="white"> <van-swipe class="my-swipe" :autoplay="5000" indicator-color="white">
<van-swipe-item v-for="(banner, index) in data.banner_data" :key="index"> <van-swipe-item v-for="(banner, index) in data.banner_data" :key="index">
<img :src="banner.cover" alt="" @click="$router.push({ path: banner.url })" /> <img :src="banner.cover" alt="" @click="$router.push({ path: banner.url })" />
</van-swipe-item> </van-swipe-item>
@@ -52,7 +52,7 @@
<div class="divider"></div> <div class="divider"></div>
<div class="panel"> <div class="panel">
<div class="panel-head"> <div class="panel-head">
<span class="title">功德无量</span> <span class="title">近期活动</span>
<arrow-more @click="$router.push({ name: 'merit-list', query: { temple_id: query.temple_id } })"></arrow-more> <arrow-more @click="$router.push({ name: 'merit-list', query: { temple_id: query.temple_id } })"></arrow-more>
</div> </div>
<div class="panel-body"> <div class="panel-body">
@@ -67,7 +67,7 @@
</div> </div>
</div> </div>
<div class="divider"></div> <div class="divider"></div>
<div class="panel temple-home-activity"> <div class="panel temple-home-activity" v-if="data.dynamic_data.length">
<div class="panel-head"> <div class="panel-head">
<span class="title">活动进展</span> <span class="title">活动进展</span>
<arrow-more @click="onMoreProcess"></arrow-more> <arrow-more @click="onMoreProcess"></arrow-more>
@@ -79,11 +79,10 @@
<i class="iconfont icon-arrow-right"></i> <i class="iconfont icon-arrow-right"></i>
</div> </div>
</div> </div>
<div class="divider"></div>
<thanks-giving :temple-id="query.temple_id || '1'"></thanks-giving>
<button class="temple-station-in" @click="onTempleStation">寺院入驻</button>
</div> </div>
<div class="divider"></div>
<thanks-giving :temple-id="query.temple_id || '1'"></thanks-giving>
<button class="temple-station-in" @click="onTempleStation">寺院入驻</button>
<div class="panel-menu-btn" @click="showUserMenu = true"> <div class="panel-menu-btn" @click="showUserMenu = true">
<span class="iconfont icon-liebiao"></span> <span class="iconfont icon-liebiao"></span>
@@ -280,11 +279,8 @@ export default {
margin-right: auto; margin-right: auto;
} }
.merit-scroll-container { .merit-scroll-container {
height: 3.39rem;
margin: 0; margin: 0;
overflow-x: auto;
.merit-scroll-wrapper { .merit-scroll-wrapper {
white-space: nowrap;
} }
} }
.temple-station-in { .temple-station-in {
@@ -569,7 +565,7 @@ export default {
.panel { .panel {
.panel-head { .panel-head {
padding: 0.53rem 0.4rem; padding: 0.13rem 0.4rem;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
@@ -582,7 +578,7 @@ export default {
.panel-body { .panel-body {
padding: 0 0.4rem; padding: 0 0.4rem;
overflow-x: scroll; overflow-x: hidden;
.merit-group { .merit-group {
display: flex; display: flex;
@@ -605,34 +601,26 @@ export default {
} }
.merit { .merit {
width: 3.39rem; display: flex;
height: 3.39rem;
display: inline-block;
position: relative; position: relative;
border-radius: 0.16rem;
vertical-align: top; vertical-align: top;
overflow: hidden; gap: 0.2rem;
border-bottom: 1px solid #f1f1f1;
padding-bottom: 0.4rem;
& ~ .merit { & ~ .merit {
margin-left: 0.4rem; margin-top: 0.4rem;
} }
img { img {
width: 100%; width: 2rem;
height: 100%; height: 2rem;
object-fit: cover;
border-radius: 0.1rem;
} }
.title { .title {
position: absolute; color: #333;
left: 0; flex: 1;
right: 0;
bottom: 0;
height: 0.91rem;
background: rgba(0, 0, 0, 0.7);
color: white;
line-height: 0.91rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
font-size: 0.37rem; font-size: 0.37rem;
padding: 0 0.11rem; padding: 0 0.11rem;
+264 -220
View File
@@ -1,10 +1,10 @@
<template> <template>
<div class="settle-in"> <div class="settle-in">
<div class="topbar" ref="topbar"> <div class="topbar" ref="topbar">
<van-nav-bar left-arrow v-if="$route.meta.showNavBar" :title="$route.meta.title" @click-left="$router.back()" :style="{backgroundColor: $route.meta.navBarBackgroundColor}" /> <van-nav-bar left-arrow v-if="$route.meta.showNavBar" :title="$route.meta.title" @click-left="$router.back()" :style="{ backgroundColor: $route.meta.navBarBackgroundColor }" />
</div> </div>
<div class="steps"> <div class="steps">
<div class="step" :class="[step == 1 && 'active']" > <div class="step" :class="[step == 1 && 'active']">
<span class="circle">1</span> <span class="circle">1</span>
<span class="text">资料准备</span> <span class="text">资料准备</span>
</div> </div>
@@ -38,17 +38,17 @@
<van-form> <van-form>
<div class="group"> <div class="group">
<label class="label-temple" for="#">寺院信息设置</label> <label class="label-temple" for="#">寺院信息设置</label>
<van-field label="单位名称" v-model="form.unit_name" name="单位名称" placeholder="单位名称" /> <van-field label="单位名称" v-model="form.unit_name" name="单位名称" placeholder="单位名称" />
<van-field label="机构代码" v-model="form.institution_code" name="机构代码" maxlength="18" placeholder="机构代码、信用代码(18位)" /> <van-field label="机构代码" v-model="form.institution_code" name="机构代码" maxlength="18" placeholder="机构代码、信用代码(18位)" />
<van-field label="省份城市" v-model="form.city_name" name="省份城市" is-link readonly placeholder="省份城市" @click="showProvince = true" /> <van-field label="省份城市" v-model="form.city_name" name="省份城市" is-link readonly placeholder="省份城市" @click="showProvince = true" />
<van-field label="详细地址" v-model="form.details_address" name="详细地址" placeholder="请输入详细地址" @blur="onUpdateLatLng"> <van-field label="详细地址" v-model="form.details_address" name="详细地址" placeholder="请输入详细地址" @blur="onUpdateLatLng">
<template #right-icon> <template #right-icon>
<van-button type="info" size="small" @click="onGetAddress">自动获取</van-button> <van-button type="info" size="small" @click="onGetAddress">自动获取</van-button>
</template> </template>
</van-field> </van-field>
<van-field label="寺院法人" v-model="form.represent" name="寺院法人" placeholder="请输入真实姓名" /> <van-field label="寺院法人" v-model="form.represent" name="寺院法人" placeholder="请输入真实姓名" />
<van-field label="手机号码" v-model="form.mobile" name="手机号码" placeholder="请输入法人手机号码" type="tel"/> <van-field label="手机号码" v-model="form.mobile" name="手机号码" placeholder="请输入法人手机号码" type="tel" />
<van-field label="寺院来源" v-model="form.source" name="寺院来源" placeholder="请输入来源" /> <van-field label="寺院来源" v-model="form.source" name="寺院来源" placeholder="请输入来源" />
</div> </div>
<div class="group"> <div class="group">
<label class="label-temple" for="#">后台登录设置</label> <label class="label-temple" for="#">后台登录设置</label>
@@ -57,7 +57,7 @@
<van-checkbox v-model="form.is_representd" shape="aquare"></van-checkbox> <van-checkbox v-model="form.is_representd" shape="aquare"></van-checkbox>
</div> </div>
<van-field v-if="!form.is_representd" v-model="form.register_name" label="注册人" placeholder="请输入真实姓名"></van-field> <van-field v-if="!form.is_representd" v-model="form.register_name" label="注册人" placeholder="请输入真实姓名"></van-field>
<van-field label="手机号码" v-model="form.login_mobile" placeholder="请输入手机号码" type="tel" /> <van-field label="手机号码" v-model="form.login_mobile" placeholder="请输入手机号码" type="tel" />
<van-field label="登录密码" v-model="form.password" placeholder="请输入至少6位数字、字母和符号组合" type="password"></van-field> <van-field label="登录密码" v-model="form.password" placeholder="请输入至少6位数字、字母和符号组合" type="password"></van-field>
<van-field label="确认密码" v-model="form.password_confirm" placeholder="请确认密码" type="password"></van-field> <van-field label="确认密码" v-model="form.password_confirm" placeholder="请确认密码" type="password"></van-field>
</div> </div>
@@ -69,7 +69,7 @@
<div class="administrator_wechat" v-if="step === 3"> <div class="administrator_wechat" v-if="step === 3">
<h1 class="title">扫码添加平台管理员微信</h1> <h1 class="title">扫码添加平台管理员微信</h1>
<img class="qrcode" src="https://wdx-temple.oss-cn-hangzhou.aliyuncs.com/uploads/common/religion-cert-bg.jpg" alt=""> <img class="qrcode" src="https://wdx-temple.oss-cn-hangzhou.aliyuncs.com/uploads/common/religion-cert-bg.jpg" alt="" />
<p class="label">平台入驻管理员微信</p> <p class="label">平台入驻管理员微信</p>
<p class="notice">审核通过后将微信通知入驻上架具体事宜</p> <p class="notice">审核通过后将微信通知入驻上架具体事宜</p>
<div class="button-group"> <div class="button-group">
@@ -83,49 +83,43 @@
</div> </div>
<van-popup v-model="showProvince" round position="bottom" safe-area-inset-bottom> <van-popup v-model="showProvince" round position="bottom" safe-area-inset-bottom>
<van-cascader <van-cascader v-model="cascaderValue" title="请选择所在地区" :options="cityOptions" @close="showProvince = false" @finish="onFinishProvince" @change="onChangeProvince" />
v-model="cascaderValue"
title="请选择所在地区"
:options="cityOptions"
@close="showProvince = false"
@finish="onFinishProvince"
@change="onChangeProvince"
/>
</van-popup> </van-popup>
</div> </div>
</template> </template>
<script> <script>
import { getRegion, getStationTemplate, postTemple } from '@/api'; import { getRegion, getStationTemplate, postTemple } from "@/api";
import { getLocation } from '@/common/wechat-web'; import { getLocation } from "@/common/wechat-web";
import TMAPLoader from '@/common/tmap'; import TMAPLoader from "@/common/tmap";
import Schema from 'async-validator'; import Schema from "async-validator";
export default { export default {
data(){ data() {
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
const testForm = { const testForm = {
// register_cert_url: [{url: 'https://caiyuehui.oss-cn-hangzhou.aliyuncs.com/uploads/dev/2021/11/04/phpjXpokW.jpeg'}], // register_cert_url: [{url: 'https://caiyuehui.oss-cn-hangzhou.aliyuncs.com/uploads/dev/2021/11/04/phpjXpokW.jpeg'}],
register_cert_url: [], register_cert_url: [],
unit_name: '123', // 单位名称 unit_name: "123", // 单位名称
institution_code: '123123123123123123', // 机构代码 institution_code: "123123123123123123", // 机构代码
province_id: 3, // 省份ID province_id: 3, // 省份ID
city_name: 32, // 省份ID city_name: 32, // 省份ID
city_id: [3, 23, 32], city_id: [3, 23, 32],
details_address: '孤男弘法寺', // 详细地址 details_address: "孤男弘法寺", // 详细地址
lng: 103.5, // 经度 lng: 103.5, // 经度
lat: 23, // 纬度 lat: 23, // 纬度
represent: '赵', // 寺院法人 represent: "赵", // 寺院法人
mobile: '13892894922', // 手机号 mobile: "13892894922", // 手机号
source: '网络', // 寺院来源 source: "网络", // 寺院来源
is_representd: false, // 是否为寺院法人 is_representd: false, // 是否为寺院法人
register_name: '赵', // 法人姓名 register_name: "赵", // 法人姓名
login_mobile: '13983828488', // 登录手机号 login_mobile: "13983828488", // 登录手机号
password: '123456', // 登录密码 password: "123456", // 登录密码
password_confirm: '123456', // 确认密码 password_confirm: "123456", // 确认密码
} };
return { return {
loading: false, loading: false,
locating: false,
query: this.$route.query, query: this.$route.query,
active: 0, active: 0,
agreement: true, // 是否同意寺院联盟服务协议 agreement: true, // 是否同意寺院联盟服务协议
@@ -136,272 +130,323 @@ export default {
form: { form: {
register_cert_url: [], register_cert_url: [],
unit_name: '', // 单位名称 unit_name: "", // 单位名称
institution_code: '', // 机构代码 institution_code: "", // 机构代码
province_id: '', // 省份ID province_id: "", // 省份ID
city_name: '', // 城市名称 city_name: "", // 城市名称
details_address: '', // 详细地址 details_address: "", // 详细地址
lng: '', // 经度 lng: "", // 经度
lat: '', // 纬度 lat: "", // 纬度
represent: '', // 寺院法人 represent: "", // 寺院法人
mobile: '', // 手机号 mobile: "", // 手机号
source: '', // 寺院来源 source: "", // 寺院来源
is_representd: '', // 是否为寺院法人 is_representd: "", // 是否为寺院法人
register_name: '', // 法人姓名 register_name: "", // 法人姓名
login_mobile: '', // 登录手机号 login_mobile: "", // 登录手机号
password: '', // 登录密码 password: "", // 登录密码
password_confirm: '', // 确认密码 password_confirm: "", // 确认密码
}, },
formRules: { formRules: {
unit_name: { required: true, message: '请输入单位名称' }, unit_name: { required: true, message: "请输入单位名称" },
institution_code: [ institution_code: [
{ required: true, message: '请输入机构代码' }, { required: true, message: "请输入机构代码" },
{ message: '请输入18位的机构代码', validator: (rule, value) => value.length === 18 } { message: "请输入18位的机构代码", validator: (rule, value) => value.length === 18 },
], ],
city_id: { required: true, message: '请选择城市' }, city_id: { required: true, message: "请选择城市" },
details_address: { required: true, message: '请输入详细地址' }, details_address: { required: true, message: "请输入详细地址" },
represent: { required: true, message: '请输入寺院法人' }, represent: { required: true, message: "请输入寺院法人" },
mobile: [ mobile: [
{ required: true, message: '请输入手机号码' }, { required: true, message: "请输入手机号码" },
{ validator: (rule, value) => this.$config.RegExp.mobile.test(value), message: '请输入合法的手机号码'} { validator: (rule, value) => this.$config.RegExp.mobile.test(value), message: "请输入合法的手机号码" },
], ],
source: { required: true, message: '请输入寺院来源' }, source: { required: true, message: "请输入寺院来源" },
register_name: { validator: {} }, register_name: { validator: {} },
login_mobile: { required: true, message: '请输入法人手机号码' }, login_mobile: { required: true, message: "请输入法人手机号码" },
password: { required: true, message: '请输入登陆密码' }, password: { required: true, message: "请输入登陆密码" },
password_confirm: { required: true, message: '请确认登录密码' } password_confirm: { required: true, message: "请确认登录密码" },
}, },
// form: testForm, // form: testForm,
geocoder: null, geocoder: null,
TMap: null, TMap: null,
mapReady: null,
selectedOptions: [], selectedOptions: [],
} };
}, },
computed: { computed: {
step: { step: {
get(){ get() {
return Number(this.$route.query.step) || 1; return Number(this.$route.query.step) || 1;
} },
},
canNextStep2() {
return this.form.register_cert_url.length > 0 && this.agreement;
}, },
canNextStep2(){
return this.form.register_cert_url.length > 0 && this.agreement
}
}, },
created(){ created() {
TMAPLoader.load({ this.mapReady = TMAPLoader.load({
key: process.env.VUE_APP_TMAP_KEY, key: process.env.VUE_APP_TMAP_KEY,
libraries: ['service'] libraries: ["service"],
}).then(TMap => { }).then((TMap) => {
this.TMap = TMap; this.TMap = TMap;
this.geocoder = new TMap.service.Geocoder(); this.geocoder = new TMap.service.Geocoder();
}) return TMap;
});
this.getParams(); this.getParams();
this.wechatReady(() => { this.wechatReady(() => {
console.log('wechat ready') console.log("wechat ready");
}); });
}, },
mounted(){ mounted() {
if(this.$route.query.template_id){ if (this.$route.query.template_id) {
return this.getStationTemplate() return this.getStationTemplate();
} }
if(this.form.register_cert_url.length === 0 && Number(this.$route.query.step) !== 1){ if (this.form.register_cert_url.length === 0 && Number(this.$route.query.step) !== 1) {
return this.$router.push({ query: { step: 1 }}); return this.$router.push({ query: { step: 1 } });
} }
}, },
methods: { methods: {
async getStationTemplate(){ async getStationTemplate() {
this.loading = true; this.loading = true;
const data = await getStationTemplate(this.$route.query.template_id); const data = await getStationTemplate(this.$route.query.template_id);
this.loading = false; this.loading = false;
data.register_cert_url = data.register_cert_url.split(',').map(item => ({ url: item })); data.register_cert_url = data.register_cert_url.split(",").map((item) => ({ url: item }));
data.is_representd = data.is_representd === 1; data.is_representd = data.is_representd === 1;
this.form = { ...this.form, ...data } this.form = { ...this.form, ...data };
const selectedOptions = []; const selectedOptions = [];
const province = this.cityOptions.find(item => item.value === data.province_id); const province = this.cityOptions.find((item) => item.value === data.province_id);
selectedOptions.push(province); selectedOptions.push(province);
const city = province.children.find(item => item.value === data.city_id); const city = province.children.find((item) => item.value === data.city_id);
selectedOptions.push(city) selectedOptions.push(city);
this.onFinishProvince({ selectedOptions }) this.onFinishProvince({ selectedOptions });
}, },
onAgreement(){ onAgreement() {
this.$router.push({ name: 'user-temple-station-agreement' }) this.$router.push({ name: "user-temple-station-agreement" });
}, },
handleErrors(errors){ handleErrors(errors) {
for(let i = 0; i < errors.length; i++){ for (let i = 0; i < errors.length; i++) {
if(errors[i]){ if (errors[i]) {
this.$toast.fail(errors[i].message) this.$toast.fail(errors[i].message);
break; break;
} }
} }
}, },
onNextStep(step = 1){ onNextStep(step = 1) {
this.$router.push({ query: { step: this.step + step }}) this.$router.push({ query: { step: this.step + step } });
}, },
onGetAddress(){ async ensureMapReady() {
getLocation().then(({ longitude, latitude}) => { if (this.geocoder && this.TMap) {
const location = new this.TMap.LatLng(latitude, longitude) return;
this.geocoder.getAddress({ location }).then(res => { }
this.form.details_address = res.result.address await this.mapReady;
this.form.lng = longitude
this.form.lat = latitude
})
})
}, },
async getLatLngByAddress(addressText){ async onGetAddress() {
try {
this.locating = true;
await this.ensureMapReady();
const { longitude, latitude } = await getLocation();
const location = new this.TMap.LatLng(latitude, longitude);
const res = await this.geocoder.getAddress({ location });
this.form.details_address = res.result.address;
this.form.lng = longitude || "0.0";
this.form.lat = latitude || "0.0";
} catch (error) {
const message = error && error.message ? error.message : "自动获取地址失败,请稍后重试";
this.$toast.fail(message);
} finally {
this.locating = false;
}
},
async getLatLngByAddress(addressText) {
await this.ensureMapReady();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.loading = true; this.loading = true;
const cityAddress = this.selectedOptions.map(v => v.text).join('') const cityAddress = this.selectedOptions.map((v) => v.text).join("");
this.geocoder.getLocation({address: cityAddress + addressText}).then(res => { const address = `${cityAddress}${addressText || ""}`.trim();
this.loading = false this.geocoder
resolve(res.result.location) .getLocation({ address })
}).catch(error => { .then((res) => {
this.loading = false; this.loading = false;
if(error.status === 347){ if (res && res.result && res.result.location) {
this.$toast.fail('未查询到地址信息,请核对地址') resolve(res.result.location);
reject(); return;
} }
}); reject(new Error("未查询到地址信息,请核对地址"));
}) })
.catch((error) => {
this.loading = false;
if (error.status === 347) {
reject(new Error("未查询到地址信息,请核对地址"));
return;
}
reject(error || new Error("地址解析失败"));
});
});
}, },
// 根据地址更新坐标 // 根据地址更新坐标
async onUpdateLatLng({ target: { value }}){ async onUpdateLatLng({ target: { value } }) {
const { lat, lng } = await this.getLatLngByAddress(value) if (!value || !this.selectedOptions.length) {
return;
}
try {
const { lat, lng } = await this.getLatLngByAddress(value);
this.form.lat = lat;
this.form.lng = lng;
} catch (error) {
const message = error && error.message ? error.message : "地址解析失败";
this.$toast.fail(message);
}
},
getParams() {
getRegion().then((city) => {
this.cityOptions = city;
});
},
onChangeProvince() {},
async ensureFormLatLng() {
if (this.form.lat && this.form.lng) {
return;
}
if (!this.form.details_address || !this.selectedOptions.length) {
throw new Error("请先完善省市和详细地址");
}
const { lat, lng } = await this.getLatLngByAddress(this.form.details_address);
this.form.lat = lat; this.form.lat = lat;
this.form.lng = lng; this.form.lng = lng;
}, },
getParams(){ onSubmitBefore() {
getRegion().then(city => {
this.cityOptions = city
})
},
onChangeProvince(){
},
onSubmitBefore(){
const validator = new Schema(this.formRules); const validator = new Schema(this.formRules);
validator.validate(this.form, ((errors) => { validator.validate(this.form, async (errors) => {
if(errors){ if (errors) {
return this.handleErrors(errors) return this.handleErrors(errors);
}
try {
await this.ensureFormLatLng();
} catch (error) {
this.$toast.fail(error.message || "经纬度获取失败,请检查地址后重试");
return;
} }
//
this.onNextStep(1); this.onNextStep(1);
})) });
}, },
async onSubmit(){ async onSubmit() {
const [province_id, city_id, country_id] = this.form.city_id; const [province_id, city_id, country_id] = this.form.city_id;
const request = { const request = {
...this.form, ...this.form,
is_representd: this.form.is_representd ? 1: 0, is_representd: this.form.is_representd ? 1 : 0,
province_id, city_id, country_id, province_id,
register_cert_url: this.form.register_cert_url.map(v => v.url), city_id,
} country_id,
register_cert_url: this.form.register_cert_url.map((v) => v.url),
};
await postTemple(request); await postTemple(request);
this.$toast.success('提交成功') this.$toast.success("提交成功");
await this.$delay(2000) await this.$delay(2000);
this.$router.replace({ name: 'user-home'}) this.$router.replace({ name: "user-home" });
}, },
onFinishProvince({selectedOptions}){ onFinishProvince({ selectedOptions }) {
this.selectedOptions = selectedOptions; this.selectedOptions = selectedOptions;
this.showProvince = false; this.showProvince = false;
this.form.city_name = selectedOptions.map(v => v.text).join(' / ') this.form.city_name = selectedOptions.map((v) => v.text).join(" / ");
this.form.city_id = selectedOptions.map(v => v.value) this.form.city_id = selectedOptions.map((v) => v.value);
} },
} },
} };
</script> </script>
<style lang="scss"> <style lang="scss">
.steps{ .steps {
background: #f5f5f5; background: #f5f5f5;
padding: .27rem .4rem; padding: 0.27rem 0.4rem;
font-size: .37rem; font-size: 0.37rem;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
border-bottom: 1px solid #ddd; border-bottom: 1px solid #ddd;
.circle{ .circle {
width: .8rem; width: 0.8rem;
height: .8rem; height: 0.8rem;
display: inline-block; display: inline-block;
text-align: center; text-align: center;
vertical-align: middle; vertical-align: middle;
line-height: .9rem; line-height: 0.9rem;
background: #ddd; background: #ddd;
color: white; color: white;
border-radius: .53rem; border-radius: 0.53rem;
margin-right: .27rem; margin-right: 0.27rem;
} }
.text{ .text {
font-size: .37rem; font-size: 0.37rem;
color: #666; color: #666;
} }
.active{ .active {
.circle{ .circle {
background: rgb(187, 95, 95); background: rgb(187, 95, 95);
color: white; color: white;
} }
span{ span {
color: rgb(187, 95, 95);; color: rgb(187, 95, 95);
} }
} }
} }
.settle-in{ .settle-in {
.infor{ .infor {
padding: .53rem .7rem; padding: 0.53rem 0.7rem;
.title{ .title {
font-size: .37rem; font-size: 0.37rem;
line-height: 1.2; line-height: 1.2;
margin-bottom: 1rem; margin-bottom: 1rem;
} }
.cert-group{ .cert-group {
.cert{ .cert {
font-size: .37rem; font-size: 0.37rem;
color: #666; color: #666;
span{ span {
font-size: .28rem; font-size: 0.28rem;
} }
} }
.uploader{ .uploader {
text-align: center; text-align: center;
padding: .4rem 0; padding: 0.4rem 0;
margin-top: .4rem; margin-top: 0.4rem;
} }
} }
.attention{ .attention {
font-size: .35rem; font-size: 0.35rem;
color: #999; color: #999;
margin-top: .3rem; margin-top: 0.3rem;
line-height: 1.4; line-height: 1.4;
text-align: justify; text-align: justify;
&::before{ &::before {
content: '*'; content: "*";
color: red; color: red;
margin-right: .1rem; margin-right: 0.1rem;
} }
} }
.agreement{ .agreement {
text-align: center; text-align: center;
font-size: .37rem; font-size: 0.37rem;
padding: 1rem 0; padding: 1rem 0;
display: flex; display: flex;
justify-content: center; justify-content: center;
} }
} }
.loading{ .loading {
position: fixed; position: fixed;
left: 0;top:0;right: 0;bottom: 0; left: 0;
top: 0;
right: 0;
bottom: 0;
width: 3rem; width: 3rem;
height: 3rem; height: 3rem;
background: rgba(0,0,0,0.6); background: rgba(0, 0, 0, 0.6);
margin: auto; margin: auto;
border-radius: .3rem; border-radius: 0.3rem;
font-size: .3rem; font-size: 0.3rem;
color: white; color: white;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
.loading-mask{ .loading-mask {
position: fixed; position: fixed;
left: 0; left: 0;
top: 0; top: 0;
@@ -409,17 +454,17 @@ export default {
bottom: 0; bottom: 0;
} }
} }
.form{ .form {
padding: .4rem 0; padding: 0.4rem 0;
.group{ .group {
margin-bottom: .6rem; margin-bottom: 0.6rem;
.label-temple{ .label-temple {
font-size: .4rem; font-size: 0.4rem;
padding-left: .4rem; padding-left: 0.4rem;
&::before{ &::before {
content: ''; content: "";
width: 4px; width: 4px;
height: .37rem; height: 0.37rem;
background: #bb5f5f; background: #bb5f5f;
display: inline-block; display: inline-block;
margin-right: 5px; margin-right: 5px;
@@ -427,55 +472,54 @@ export default {
margin-top: -4px; margin-top: -4px;
} }
} }
.legal-person{ .legal-person {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: .5rem .4rem .3rem; padding: 0.5rem 0.4rem 0.3rem;
.label{ .label {
font-size: .37rem; font-size: 0.37rem;
} }
} }
} }
} }
.administrator_wechat{ .administrator_wechat {
padding: .4rem; padding: 0.4rem;
.title{ .title {
font-size: .4rem; font-size: 0.4rem;
margin-top: 1rem; margin-top: 1rem;
margin-bottom: 1rem; margin-bottom: 1rem;
} }
.qrcode{ .qrcode {
width: 4rem; width: 4rem;
height: 4rem; height: 4rem;
display: block; display: block;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
} }
.label{ .label {
font-size: .4rem; font-size: 0.4rem;
padding: .5rem 0; padding: 0.5rem 0;
text-align: center; text-align: center;
} }
.notice{ .notice {
font-size: .4rem; font-size: 0.4rem;
color: rgb(129, 43, 43); color: rgb(129, 43, 43);
margin-top: 2rem; margin-top: 2rem;
text-align: center; text-align: center;
} }
.button-group{ .button-group {
margin-top: 2rem; margin-top: 2rem;
display: flex; display: flex;
.prev{ .prev {
margin-right: .3rem; margin-right: 0.3rem;
width: 3rem; width: 3rem;
} }
} }
} }
.button-group{ .button-group {
padding: 0 .4rem; padding: 0 0.4rem;
padding-top: 0rem; padding-top: 0rem;
} }
} }
</style> </style>
+3 -3
View File
@@ -66,13 +66,13 @@ const routes = [
{ {
path: "/merit-list", path: "/merit-list",
name: "merit-list", name: "merit-list",
meta: { title: "功德无量", navBarBackgroundColor: "white" }, meta: { title: "近期活动", navBarBackgroundColor: "white" },
component: () => import("@/pages/merit-list"), component: () => import("@/pages/merit-list"),
}, },
{ {
path: "/merit-box", path: "/merit-box",
name: "merit-box", name: "merit-box",
meta: { title: "功德无量", navBarBackgroundColor: "white", showNavBar: false }, meta: { title: "近期活动", navBarBackgroundColor: "white", showNavBar: false },
component: () => import("@/pages/merit-box"), component: () => import("@/pages/merit-box"),
}, },
@@ -91,7 +91,7 @@ const routes = [
{ {
path: "/pay-result", path: "/pay-result",
name: "pay-result", name: "pay-result",
meta: { title: "捐赠成功", navBarBackgroundColor: "white" }, meta: { title: "护持成功", navBarBackgroundColor: "white" },
component: () => import("@/pages/pay-result"), component: () => import("@/pages/pay-result"),
}, },
{ {
+21 -22
View File
@@ -1,34 +1,33 @@
export default { export default {
setSearchParamsFromObj(obj){ setSearchParamsFromObj(obj) {
let search = '?'; let search = "?";
for(let i in obj){ for (let i in obj) {
search += `${i}=${obj[i]}&` search += `${i}=${obj[i]}&`;
} }
return search.slice(0, -1); return search.slice(0, -1);
}, },
addExternalParamsToQuery(url, key, value){ addExternalParamsToQuery(url, key, value) {
if(!url){ if (!url) {
return '' return "";
} }
const hasQuery = url.indexOf('?') > -1 const [beforeHash] = url.split("#");
url = url.split('?') const [beforeQuery, query = ""] = beforeHash.split("?");
const before = url.shift() const searchParams = new URLSearchParams(query);
let after = url.join('&') if (!searchParams.has(key)) {
const searchParams = new URLSearchParams(after); searchParams.set(key, value);
if(!searchParams.has(key)){
return before+'?'+after+'&'+key+'='+value;
} }
return before+(hasQuery ? '?': '&') + after; const queryString = searchParams.toString();
return `${beforeQuery}?${queryString}`;
}, },
queryStringToObj(queryString){ queryStringToObj(queryString) {
const string = queryString.split('&'); const string = queryString.split("&");
const obj = {}; const obj = {};
string.forEach(str => { string.forEach((str) => {
const [key, value] = str.split('='); const [key, value] = str.split("=");
obj[key] = value; obj[key] = value;
}) });
return obj; return obj;
} },
} };
+12
View File
@@ -50,5 +50,17 @@ module.exports = {
}, },
css: { css: {
sourceMap: false, sourceMap: false,
loaderOptions: {
sass: {
sassOptions: {
silenceDeprecations: ["legacy-js-api", "import"],
},
},
scss: {
sassOptions: {
silenceDeprecations: ["legacy-js-api", "import"],
},
},
},
}, },
}; };
+1 -1
View File
File diff suppressed because one or more lines are too long