Compare commits

..
10 Commits
Author SHA1 Message Date
wenfp 13bb939099 update 2026-08-21 14:12:00 +08:00
wenfp 68dc57ffe5 fix: 调整商品名称最大宽度并更新构建产物
将商品名称的 max-width 从固定像素单位改为相对单位 em,以改善响应式布局
更新 wap/index.html 中的构建产物哈希引用
2026-04-27 21:03:21 +08:00
wenfp 0265cfe27c fix: 优化页面UI及修复安全区域占位符问题
- 将“进展状态”文案统一改为“活动进展”以提升一致性
- 在商品详情页添加安全区域占位符,防止底部内容被遮挡
- 优化用户功德组件样式,调整日期显示格式和布局
- 更新构建产物引用路径
2026-04-23 20:25:13 +08:00
wenfp d9d8100e4a update 2026-04-23 20:03:27 +08:00
wenfp 48324cd36f 增加商品客服显示 2026-04-21 23:58:58 +08:00
wenfp 1a5279a8f5 增加商品客服显示 2026-04-21 23:55:16 +08:00
kevin 74572077e4 修复查询路径错误的问题 2026-02-11 18:36:30 +08:00
walker 74b05adf7c 增加订单反馈 2026-02-06 15:38:01 +08:00
wenfp be2a7ac33c 增加手机处理订单页面 2026-02-06 15:02:34 +08:00
wenfp 33d9d6bb06 update 2025-07-13 14:42:38 +08:00
56 changed files with 3838 additions and 30187 deletions
-17673
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -3,7 +3,7 @@
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"scripts": { "scripts": {
"serve": "vue-cli-service serve --mode development", "dev": "vue-cli-service serve --mode development",
"build:test": "vue-cli-service build --mode test", "build:test": "vue-cli-service build --mode test",
"build": "vue-cli-service build --mode production", "build": "vue-cli-service build --mode production",
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint"
@@ -36,8 +36,8 @@
"eslint": "^6.7.2", "eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2", "eslint-plugin-vue": "^6.2.2",
"sass": "^1.89.0", "sass": "^1.89.0",
"sass-loader": "^7.1.0", "sass-loader": "^8.0.2",
"sass-resources-loader": "^2.2.4", "sass-resources-loader": "^2.2.5",
"vue-template-compiler": "^2.6.11" "vue-template-compiler": "^2.6.11"
}, },
"eslintConfig": { "eslintConfig": {
+770 -664
View File
File diff suppressed because it is too large Load Diff
+8 -9
View File
@@ -1,19 +1,18 @@
<!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>
Binary file not shown.

After

Width:  |  Height:  |  Size: 313 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

+58 -52
View File
@@ -1,12 +1,12 @@
<template> <template>
<div class="app-safe-area" :style="{minHeight: minHeight + 'px'}"> <div class="app-safe-area" :style="{ minHeight: minHeight + 'px' }">
<div id="app" :data-height="minHeight - tabHeight" :style="{ minHeight: minHeight - tabHeight + 'px', paddingBottom: tabHeight + 'px'}"> <div id="app" :data-height="minHeight - tabHeight" :style="{ minHeight: minHeight - tabHeight + 'px', paddingBottom: tabHeight + 'px' }">
<router-view /> <router-view />
<van-tabbar v-if="showTabbar" class="tabbar" v-model="actionRoute" ref="tabbar" active-color="#CF9E3B" inactive-color="#999"> <van-tabbar v-if="showTabbar" class="tabbar" v-model="actionRoute" ref="tabbar" active-color="#CF9E3B;" inactive-color="#999">
<van-tabbar-item replace name v-for="(tab, index) in tabbar" :key="index" @click="onNavigation(tab)"> <van-tabbar-item replace name v-for="(tab, index) in tabbar" :key="index" @click="onNavigation(tab)">
<span>{{ tab.title }}</span> <span>{{ tab.title }}</span>
<template #icon="props"> <template #icon="props">
<img :src="props.active ? tab.active: tab.inactive" alt=""> <img :src="props.active ? tab.active : tab.inactive" alt="" />
</template> </template>
</van-tabbar-item> </van-tabbar-item>
</van-tabbar> </van-tabbar>
@@ -15,13 +15,13 @@
</template> </template>
<script> <script>
import { tabbar } from '../src/router'; import { tabbar } from "../src/router";
import safeAreaInsets from 'safe-area-insets'; import safeAreaInsets from "safe-area-insets";
export default { export default {
name: 'App', name: "App",
data() { data() {
return { return {
active: '3', active: "3",
minHeight: 0, minHeight: 0,
tabbar, tabbar,
tabHeight: 0, tabHeight: 0,
@@ -39,10 +39,13 @@ export default {
}; };
}, },
watch: { watch: {
'$route': { $route: {
handler(val) { handler(val) {
document.title = val.meta.title || '自在福田' document.title = val.meta.title || "自在福田";
this.active = tabbar.map(v => v.name).indexOf(val.name).toString(); this.active = tabbar
.map((v) => v.name)
.indexOf(val.name)
.toString();
}, },
deep: true, deep: true,
}, },
@@ -50,54 +53,57 @@ export default {
handler() { handler() {
this.$nextTick(() => { this.$nextTick(() => {
const { tabbar } = this.$refs; const { tabbar } = this.$refs;
this.tabHeight = tabbar ? tabbar.$el.offsetHeight - safeAreaInsets.bottom: 0; this.tabHeight = tabbar ? tabbar.$el.offsetHeight - safeAreaInsets.bottom : 0;
}) });
}, },
immediate: true, immediate: true,
}
}, },
mounted(){ },
this.$store.commit('SET_LAUNCH', this.$route.query) mounted() {
this.$store.commit("SET_LAUNCH", this.$route.query);
setTimeout(() => { setTimeout(() => {
this.minHeight = window.innerHeight - safeAreaInsets.bottom; this.minHeight = window.innerHeight - safeAreaInsets.bottom;
}, 30) }, 30);
}, },
methods: { methods: {
onNavigation(tab){ onNavigation(tab) {
const { path } = this.$route; const { path } = this.$route;
if(path === tab.path) return; if (path === tab.path) return;
this.$router.push({ path: tab.path, query: { temple_id: this.$route.query.temple_id}}) this.$router.push({ path: tab.path, query: { temple_id: this.$route.query.temple_id } });
} },
}, },
computed: { computed: {
actionRoute: { actionRoute: {
get(){ get() {
const { tabbar } = this; const { tabbar } = this;
return tabbar.map(tab => tab.name).indexOf(this.$route.name) return tabbar.map((tab) => tab.name).indexOf(this.$route.name);
}, },
set(){ } set() {},
}, },
showTabbar() { showTabbar() {
const path = tabbar.map(tab => tab.name); const path = tabbar.map((tab) => tab.name);
const { name, query: { hideTab } } = this.$route; const {
name,
query: { hideTab },
} = this.$route;
// 等于寺庙功德箱时隐藏底部导航 // 等于寺庙功德箱时隐藏底部导航
if(name === 'merit-box' || (name === 'temple-list' && hideTab === '1')){ if (name === "merit-box" || (name === "temple-list" && hideTab === "1")) {
return false return false;
} }
return path.includes(this.$route.name); return path.includes(this.$route.name);
}, },
paddingBottom() { paddingBottom() {
return this.showTabbar ? this.$refs.tabbar ? this.$refs.tabbar.$el.offsetHeight : 0 : 0; return this.showTabbar ? (this.$refs.tabbar ? this.$refs.tabbar.$el.offsetHeight : 0) : 0;
} },
} },
}; };
</script> </script>
<style lang="scss"> <style lang="scss">
@import '~@/assets/css/reset.css'; @import "~@/assets/css/reset.css";
@import '//at.alicdn.com/t/font_2897403_8d7w3rodyu2.css'; @import "//at.alicdn.com/t/font_2897403_8d7w3rodyu2.css";
.app-safe-area{ .app-safe-area {
position: relative; position: relative;
padding-bottom: env(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom);
#app { #app {
@@ -117,60 +123,60 @@ export default {
bottom: 0; bottom: 0;
} }
} }
.loadmore{ .loadmore {
font-size: .4rem; font-size: 0.4rem;
text-align: center; text-align: center;
color: #888; color: #888;
padding: .4rem 0; padding: 0.4rem 0;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
.icon{ .icon {
width: .6rem; width: 0.6rem;
vertical-align: middle; vertical-align: middle;
margin-right: .2rem; margin-right: 0.2rem;
animation: loading 3s linear infinite; animation: loading 3s linear infinite;
} }
} }
.icon-home{ .icon-home {
width: 1.1rem; width: 1.1rem;
height: 1.1rem; height: 1.1rem;
font-size: .5rem; font-size: 0.5rem;
background: white; background: white;
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: 1rem; border-radius: 1rem;
position: absolute; position: absolute;
left: .4rem; left: 0.4rem;
top: .4rem; top: 0.4rem;
&:active{ &:active {
background: #f1f1f1; background: #f1f1f1;
} }
} }
.no-more{ .no-more {
font-size: .4rem; font-size: 0.4rem;
text-align: center; text-align: center;
color: #888; color: #888;
padding: .4rem 0; padding: 0.4rem 0;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.read-more{ .read-more {
height: 1.3rem; height: 1.3rem;
text-align: center; text-align: center;
font-size: .4rem; font-size: 0.4rem;
line-height: 1.3rem; line-height: 1.3rem;
color: #888; color: #888;
} }
@keyframes loading { @keyframes loading {
from{ from {
transform: rotateZ(0); transform: rotateZ(0);
} }
to{ to {
transform: rotateZ(-360deg); transform: rotateZ(-360deg);
} }
} }
+13
View File
@@ -0,0 +1,13 @@
import service from "./service";
// 订单列表
export const getOrderList = (params) => service.get("/api/admin/orders", { data: params });
// 订单详情
export const getOrderDetail = (id) => service.get(`/api/admin/order/${id}`);
// 反馈
export const postFeedback = (id, data) => service.post(`/api/admin/order-done/${id}`, data);
// 上传图片
export const uploadImage = (data) => service.post("/admin/api/upload", data);
+8
View File
@@ -179,8 +179,15 @@ const getMeritTypes = () => service.get("/api/order/get-merit-types");
// 支付广告 // 支付广告
const getPayAdv = () => service.get("/api/ad/ad-pay"); const getPayAdv = () => service.get("/api/ad/ad-pay");
// 保存手机号
const saveMobileNumber = (mobile) => service.put("/api/mobile", { mobile });
// 检查是否有手机号
const checkUserMobile = () => service.get("/api/mobile-check");
export { export {
getPayAdv, getPayAdv,
saveMobileNumber,
getMeritTypes, getMeritTypes,
getDynamicDataByGoodsId, getDynamicDataByGoodsId,
hasLogin, hasLogin,
@@ -229,4 +236,5 @@ export {
getCertList, getCertList,
getStationTemplate, getStationTemplate,
getPlatformHome, getPlatformHome,
checkUserMobile,
}; };
+4
View File
@@ -28,6 +28,10 @@ instance.interceptors.request.use((request) => {
request.data = qs.stringify(request.data); request.data = qs.stringify(request.data);
return request; return request;
} }
if (request.method == "get") {
request.url += `${request.url.includes("?") ? "" : "?"}${qs.stringify(request.data).slice(0, -1)}`;
return request;
}
return request; return request;
}); });
+43 -29
View File
@@ -1,27 +1,29 @@
@import './variable.scss'; @use "./variable.scss" as *;
.divider { .divider {
height: .24rem; height: .24rem;
background: #F9F9FC; background: #F9F9FC;
} }
.text-multiple-3{ .text-multiple-3 {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
display: -webkit-box; display: -webkit-box;
-webkit-line-clamp: 3; -webkit-line-clamp: 3;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
} }
.text-multiple-2{
overflow: hidden; .text-multiple-2 {
text-overflow: ellipsis; overflow: hidden;
display: -webkit-box; text-overflow: ellipsis;
-webkit-line-clamp: 2; display: -webkit-box;
-webkit-box-orient: vertical; -webkit-line-clamp: 2;
-webkit-box-orient: vertical;
} }
.panel { .panel {
padding-bottom: .4rem; padding-bottom: .4rem;
.panel-head { .panel-head {
//padding: .53rem .4rem; //padding: .53rem .4rem;
padding: .3rem .4rem; padding: .3rem .4rem;
@@ -51,18 +53,21 @@ display: -webkit-box;
} }
} }
} }
.process-more{
.process-more {
line-height: 1.17rem; line-height: 1.17rem;
text-align: center; text-align: center;
font-size: .37rem; font-size: .37rem;
.iconfont{
.iconfont {
vertical-align: middle; vertical-align: middle;
} }
} }
.border-bottom{ .border-bottom {
position: relative; position: relative;
&::after{
&::after {
content: ''; content: '';
height: 1px; height: 1px;
width: 200%; width: 200%;
@@ -75,9 +80,11 @@ display: -webkit-box;
left: 0; left: 0;
} }
} }
.border-top{
.border-top {
position: relative; position: relative;
&::before{
&::before {
content: ''; content: '';
height: 1px; height: 1px;
width: 200%; width: 200%;
@@ -90,9 +97,11 @@ display: -webkit-box;
left: 0; left: 0;
} }
} }
.border-circle{
.border-circle {
position: relative; position: relative;
&::before{
&::before {
content: ''; content: '';
height: 199%; height: 199%;
width: 200%; width: 200%;
@@ -108,27 +117,32 @@ display: -webkit-box;
} }
} }
.active{ .active {
&::before{ &::before {
border-color: $primary-color; border-color: #CF9E3B;
;
} }
color: $primary-color;
color: #CF9E3B;
;
} }
.multiple-line-3{ .multiple-line-3 {
overflow : hidden; overflow: hidden;
display: -webkit-box; display: -webkit-box;
-webkit-line-clamp: 3; -webkit-line-clamp: 3;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
} }
.no-more{
.no-more {
height: 1rem; height: 1rem;
line-height: 1rem; line-height: 1rem;
font-size: .4rem; font-size: .4rem;
color: #666; color: #666;
text-align: center; text-align: center;
} }
button:disabled{
button:disabled {
background: #e1e1e1 !important; background: #e1e1e1 !important;
border-color: #e1e1e1 !important; border-color: #e1e1e1 !important;
-1
View File
@@ -1,2 +1 @@
$primary-color: #CF9E3B;
$btn-border-radius: .07rem; $btn-border-radius: .07rem;
+14 -9
View File
@@ -13,13 +13,16 @@ import {
TabbarItem, TabbarItem,
Cell, Cell,
CellGroup, CellGroup,
Tab, Tabs, Tab,
Tabs,
Progress, Progress,
Form, Form,
Field, Field,
Uploader, Uploader,
Step, Steps, Step,
Checkbox, CheckboxGroup, Steps,
Checkbox,
CheckboxGroup,
Popup, Popup,
Stepper, Stepper,
Radio, Radio,
@@ -31,10 +34,12 @@ import {
Loading, Loading,
Dialog, Dialog,
Icon, Icon,
Popover,
} from "vant"; } from "vant";
Vue.use(NavBar); Vue.use(NavBar);
Vue.use(Button); Vue.use(Button);
Vue.use(Popover);
Vue.use(Loading); Vue.use(Loading);
Vue.use(Icon); Vue.use(Icon);
Vue.use(Search); Vue.use(Search);
@@ -60,9 +65,9 @@ Vue.use(Checkbox);
Vue.use(CheckboxGroup); Vue.use(CheckboxGroup);
Vue.use(Popup); Vue.use(Popup);
Vue.use(Stepper); Vue.use(Stepper);
Vue.use(Radio) Vue.use(Radio);
Vue.use(RadioGroup) Vue.use(RadioGroup);
Vue.use(Switch) Vue.use(Switch);
Vue.use(ActionSheet) Vue.use(ActionSheet);
Vue.use(Cascader) Vue.use(Cascader);
Vue.use(Dialog) Vue.use(Dialog);
+88 -50
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;
const safeShareConfig = getShareConfig(shareConfig);
if (typeof wx.updateAppMessageShareData === "function") {
wx.updateAppMessageShareData({
title: safeShareConfig.title,
desc: safeShareConfig.desc,
link: safeShareConfig.link,
imgUrl: safeShareConfig.imgUrl,
complete: (res) => {
emitShareCallback(safeShareConfig, "updateAppMessageShareData", 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({ wx.onMenuShareAppMessage({
title: shareConfig.title, title: safeShareConfig.title,
desc: shareConfig.desc, desc: safeShareConfig.desc,
link: util.addExternalParamsToQuery(shareConfig.link, "no_login", 1), link: safeShareConfig.link,
imgUrl: shareConfig.imgUrl, imgUrl: safeShareConfig.imgUrl,
complete: (res) => { complete: (res) => {
shareConfig.callback && emitShareCallback(safeShareConfig, "onMenuShareAppMessage", res);
shareConfig.callback({
key: "updateAppMessageShareData",
...res,
});
}, },
}); });
}
// // 分享朋友圈 if (typeof wx.onMenuShareTimeline === "function") {
wx.onMenuShareTimeline({ wx.onMenuShareTimeline({
title: shareConfig.title, title: safeShareConfig.title,
link: util.addExternalParamsToQuery(shareConfig.link, "no_login", 1), link: safeShareConfig.link,
imgUrl: shareConfig.imgUrl, imgUrl: safeShareConfig.imgUrl,
complete: (res) => { complete: (res) => {
shareConfig.callback && emitShareCallback(safeShareConfig, "onMenuShareTimeline", res);
shareConfig.callback({
key: "updateTimelineShareData",
...res,
});
}, },
}); });
}
// wx.updateAppMessageShareData({ resolve(wx);
// 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
// });
// }
// });
}); });
if (typeof wx.error === "function") {
wx.error((error) => {
reject(error);
});
}
});
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("用户取消定位"));
}, },
}); });
}); });
+19 -19
View File
@@ -8,7 +8,7 @@
<div class="image-group"> <div class="image-group">
<img :src="cover" v-for="(cover, index) in covers" :key="index" alt="" /> <img :src="cover" v-for="(cover, index) in covers" :key="index" alt="" />
</div> </div>
<button class="purchase" v-if="showGoodsBtn" @click.stop="onGoodsDetail">{{privateData.btn_title}}</button> <button class="purchase" v-if="showGoodsBtn" @click.stop="onGoodsDetail">{{ privateData.btn_title }}</button>
<div class="bar"> <div class="bar">
<span class="join">已有{{ privateData.sales }}人参与</span> <span class="join">已有{{ privateData.sales }}人参与</span>
<div class="btn-group"> <div class="btn-group">
@@ -27,10 +27,10 @@
</template> </template>
<script> <script>
import { toggleCollect } from '@/api'; import { toggleCollect } from "@/api";
export default { export default {
name: 'buddha-process', name: "buddha-process",
props: { props: {
data: { data: {
required: true, required: true,
@@ -38,7 +38,7 @@ export default {
showGoodsBtn: { showGoodsBtn: {
type: Boolean, type: Boolean,
default: true, default: true,
} },
}, },
watch: { watch: {
data: { data: {
@@ -57,7 +57,7 @@ export default {
covers: { covers: {
get() { get() {
const type = Object.prototype.toString.call(this.privateData.covers); const type = Object.prototype.toString.call(this.privateData.covers);
return type === '[object Object]' ? []: this.privateData.covers.slice(0, 3); return type === "[object Object]" ? [] : this.privateData.covers.slice(0, 3);
}, },
}, },
}, },
@@ -65,26 +65,26 @@ export default {
async onCollect() { async onCollect() {
await toggleCollect(this.data.id); await toggleCollect(this.data.id);
this.privateData.is_collected = this.privateData.is_collected === 1 ? 0 : 1; this.privateData.is_collected = this.privateData.is_collected === 1 ? 0 : 1;
this.$emit('collection', this.data.id); this.$emit("collection", this.data.id);
}, },
onProcessDetail() { onProcessDetail() {
const { id } = this.privateData; const { id } = this.privateData;
this.$router.push({ this.$router.push({
name: 'buddha-detail', name: "buddha-detail",
query: { id } query: { id },
}) });
}, },
onGoodsDetail(){ onGoodsDetail() {
const { goods_type, goods_id, temple_id, spec_ids } = this.privateData; const { goods_type, goods_id, temple_id, spec_ids } = this.privateData;
this.onPushToGoodsDetail(goods_type, goods_id, temple_id, spec_ids) this.onPushToGoodsDetail(goods_type, goods_id, temple_id, spec_ids);
} },
}, },
}; };
</script> </script>
<style lang="scss"> <style lang="scss">
.panel-body { .panel-body {
.buddha-process{ .buddha-process {
padding-left: 0; padding-left: 0;
padding-right: 0; padding-right: 0;
} }
@@ -94,7 +94,7 @@ export default {
position: relative; position: relative;
padding: 0 0.4rem; padding: 0 0.4rem;
&::after { &::after {
content: ''; content: "";
height: 1px; height: 1px;
width: 200%; width: 200%;
background: #ededed; background: #ededed;
@@ -131,9 +131,9 @@ export default {
@extend .text-multiple-3; @extend .text-multiple-3;
} }
.detail-text{ .detail-text {
font-size: .4rem; font-size: 0.4rem;
padding-top: .2rem; padding-top: 0.2rem;
color: #b74100; color: #b74100;
} }
.image-group { .image-group {
@@ -180,7 +180,7 @@ export default {
align-items: center; align-items: center;
.iconfont { .iconfont {
color: $primary-color; color: #cf9e3b;
vertical-align: middle; vertical-align: middle;
font-size: 0.4rem; font-size: 0.4rem;
margin-top: -3px; margin-top: -3px;
@@ -195,7 +195,7 @@ export default {
} }
.collect { .collect {
.iconfont { .iconfont {
color: $primary-color; color: #cf9e3b;
} }
} }
.un-collect { .un-collect {
+148
View File
@@ -0,0 +1,148 @@
<template>
<van-popover v-model="showPopover" trigger="click" placement="top-end">
<template #reference>
<button class="customer-service-btn">
<svg t="1776784019841" class="icon" viewBox="0 0 1051 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5796" width="20" height="20">
<path
d="M55.351351 553.402811v110.924108a83.027027 83.027027 0 0 0 166.054054 0v-110.924108a83.027027 83.027027 0 0 0-166.054054 0z m763.101406 211.552865A137.852541 137.852541 0 0 1 774.918919 664.326919v-110.924108A138.378378 138.378378 0 0 1 912.328649 415.135135C898.131027 214.071351 730.499459 55.351351 525.837838 55.351351 321.148541 55.351351 153.544649 214.071351 139.347027 415.135135A138.461405 138.461405 0 0 1 276.756757 553.402811v110.924108a138.378378 138.378378 0 0 1-276.756757 0v-110.924108a138.378378 138.378378 0 0 1 83.303784-126.865297C91.883243 189.523027 286.72 0 525.837838 0s433.954595 189.523027 442.534054 426.537514A138.461405 138.461405 0 0 1 1051.675676 553.402811v110.924108a138.378378 138.378378 0 0 1-184.790487 130.269405 470.763243 470.763243 0 0 1-188.858811 121.21946A96.809514 96.809514 0 0 1 580.912432 1010.162162h-82.528864c-53.690811 0-97.113946-43.174054-97.113946-96.864865 0-53.607784 43.284757-96.864865 97.141621-96.864865h82.473514c34.954378 0 65.536 18.265946 82.639567 45.803244a415.273514 415.273514 0 0 0 154.900757-97.28zM830.27027 553.402811v110.924108a83.027027 83.027027 0 0 0 166.054054 0v-110.924108a83.027027 83.027027 0 0 0-166.054054 0zM498.438919 954.810811h82.473513c23.302919 0 41.79027-18.487351 41.790271-41.513514 0-23.053838-18.570378-41.513514-41.790271-41.513513h-82.473513c-23.302919 0-41.79027 18.487351-41.79027 41.513513 0 23.053838 18.570378 41.513514 41.79027 41.513514z"
fill="#666666"
p-id="5797"
></path>
</svg>
<span>客服</span>
</button>
</template>
<div class="customer-group">
<p class="head">点击下方客服即可复制客服号码,可添加或添加微信号</p>
<div class="customer-type-group" v-for="(cus, index) in list" :key="index" @click="onService(cus)">
<img :src="cus.icon_url" alt="" />
<div class="info">
<h1>{{ cus.title }} <span class="wechat-account" v-copy="cus.value"></span></h1>
<p v-html="cus.content"></p>
</div>
<a class="phone" :href="'tel://' + cus.value" v-if="cus.title === '电话客服'"></a>
</div>
</div>
</van-popover>
</template>
<script>
import { getCustomerList } from "@/api";
export default {
data() {
return {
list: [],
showPopover: false,
actions: [{ name: "选项1" }, { name: "选项2" }, { name: "选项3" }],
};
},
watch: {
showPopover(val) {
console.log("val", val);
document.body.style.overflow = val ? "hidden" : "auto";
},
},
mounted() {
setTimeout(() => {
this.getCustomerList();
}, 1000);
},
methods: {
async getCustomerList() {
if (this.list.length) return;
const res = await getCustomerList();
this.list = res.list;
this.qrcode = this.$config.qrcode.wechatAccount || res.platform_code;
},
onService(cus) {
this.showPopover = false;
navigator.clipboard.writeText(cus.value);
this.$toast.success("已复制");
},
},
};
</script>
<style lang="scss" scoped>
.customer-service-btn {
width: 1.2rem;
height: 1.2rem;
background: white;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border-radius: 8px;
font-size: 0.25rem;
gap: 0.14rem;
border: 1px solid #ddd;
}
.van-popover__content {
width: 90%;
}
.customer-group {
padding: 0.3rem;
width: 100%;
position: relative;
z-index: 10;
box-shadow: 0 -10px 10px rgba(0, 0, 0, 0.1);
.head {
font-size: 0.3rem;
color: #aaa;
padding: 0 0.4rem;
}
.customer-type-group {
display: flex;
background: white;
height: 1.67rem;
border-radius: 0.27rem;
padding: 0.2rem 0.4rem;
align-items: center;
position: relative;
img {
width: 1.07rem;
height: 1.07rem;
border-radius: 50%;
margin-right: 0.3rem;
}
&::after {
content: "";
width: 90%;
height: 1px;
background: #f1f1f1;
position: absolute;
bottom: 0;
left: 0;
right: 0;
margin: 0 auto;
}
&:last-child::after {
display: none;
}
.phone {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
.info {
flex: 1;
font-size: 0.37rem;
h1 {
font-size: 0.4rem;
margin-bottom: 0.2rem;
.wechat-account {
color: rgb(167, 54, 54);
}
}
p {
color: #aaa;
font-size: 0.3rem;
line-height: 1.3;
}
}
}
}
</style>
@@ -1,6 +1,6 @@
<template> <template>
<div class="detail-content-expand"> <div class="detail-content-expand">
<div class="content" :class="[contentOverflow && !show && '']" ref="wrapper" :style="{ height: (show ? contentHeight : defaultContentHeight) + 'px' }"> <div class="content" :class="[contentOverflow && !show && '']" ref="wrapper" :style="{ height: show ? 'auto' : defaultContentHeight + 'px' }">
<div ref="content" class="ref-content"> <div ref="content" class="ref-content">
<slot></slot> <slot></slot>
</div> </div>
@@ -41,7 +41,8 @@ export default {
mounted() { mounted() {
this.wrapperHeight = this.$refs.wrapper.offsetHeight; this.wrapperHeight = this.$refs.wrapper.offsetHeight;
this.$nextTick(() => { this.$nextTick(() => {
this.contentHeight = this.$refs.content.offsetHeight; console.log(this.$refs.content.clientHeight);
this.contentHeight = this.$refs.content.clientHeight;
this.wrapperContainerHeight = this.wrapperHeight; this.wrapperContainerHeight = this.wrapperHeight;
this.refresh(); this.refresh();
}); });
@@ -56,7 +57,7 @@ export default {
this.defaultContentHeight = 100; this.defaultContentHeight = 100;
return; return;
} }
this.defaultContentHeight = selector.offsetHeight / (4 / 1); this.defaultContentHeight = selector.offsetHeight / (2 / 1);
}, },
}, },
}; };
+72 -75
View File
@@ -1,11 +1,10 @@
<template> <template>
<van-popup :value.sync="visible" position="bottom" @close="onClose" @click-overlay="onClose" safe-area-inset-bottom <van-popup :value.sync="visible" position="bottom" @close="onClose" @click-overlay="onClose" safe-area-inset-bottom style="min-height: 50vh">
style="min-height: 50vh"> <div class="add-merit-name">
<div class="add-merit-name" >
<h3 class="title">心愿</h3> <h3 class="title">心愿</h3>
<div class="desire-input"> <div class="desire-input">
<textarea class="desire-textarea" v-model="desire" type="text" :max-length="maxLength" placeholder="请输入您的心愿" /> <textarea class="desire-textarea" v-model="desire" type="text" :max-length="maxLength" placeholder="请输入您的心愿" />
<span>{{desire.length}}/{{maxLength}}</span> <span>{{ desire.length }}/{{ maxLength }}</span>
</div> </div>
<div class="desire-quike"> <div class="desire-quike">
<div class="bar"> <div class="bar">
@@ -13,7 +12,7 @@
<span class="update" @click="getDreamList">换一组<i class="iconfont icon-shuaxin"></i></span> <span class="update" @click="getDreamList">换一组<i class="iconfont icon-shuaxin"></i></span>
</div> </div>
<div class="name-group"> <div class="name-group">
<span class="name" v-for="(dream, index) in dreamList" :key="index" @click="onFill(dream)">{{dream}}</span> <span class="name" v-for="(dream, index) in dreamList" :key="index" @click="onFill(dream)">{{ dream }}</span>
</div> </div>
</div> </div>
<button class="confirm" @click="onConfirmDream">确认</button> <button class="confirm" @click="onConfirmDream">确认</button>
@@ -22,80 +21,80 @@
</template> </template>
<script> <script>
import { getDreamList } from '@/api'; import { getDreamList } from "@/api";
export default { export default {
name: 'merit-desire', name: "merit-desire",
props: { props: {
visible: { visible: {
type: Boolean, type: Boolean,
default: false default: false,
}, },
mode: { mode: {
type: String, type: String,
default: 'increment', // increment | single default: "increment", // increment | single
}, },
selected: { selected: {
type: Array, type: Array,
default(){ default() {
return [] return [];
} },
}, },
maxLength: { maxLength: {
type: Number, type: Number,
default: 50 default: 50,
} },
}, },
data() { data() {
return { return {
name: '', name: "",
desire: '', desire: "",
dreamList: [] dreamList: [],
}; };
}, },
watch: { watch: {
visible(value){ visible(value) {
if(value){ if (value) {
this.selectedName = this.selected.map(v => v.id) this.selectedName = this.selected.map((v) => v.id);
}
} }
}, },
},
created() { created() {
this.getDreamList(); this.getDreamList();
}, },
methods: { methods: {
onFill(dream){ onFill(dream) {
if(this.mode === 'single'){ if (this.mode === "single") {
return this.desire = dream; return (this.desire = dream);
} }
this.desire += dream + ','; this.desire += dream + ",";
this.desire = this.desire.slice(0, this.maxLength) this.desire = this.desire.slice(0, this.maxLength);
}, },
onClose() { onClose() {
this.$emit('update:visible', false); this.$emit("update:visible", false);
}, },
//获取心愿列表 //获取心愿列表
async getDreamList(){ async getDreamList() {
const list = await getDreamList(); const list = await getDreamList();
this.dreamList = list; this.dreamList = list;
}, },
onConfirmDream(){ onConfirmDream() {
this.showDialog = false; this.showDialog = false;
this.dream = this.desire; this.dream = this.desire;
this.$emit('update:visible', false); this.$emit("update:visible", false);
this.$emit('change', this.dream) this.$emit("change", this.dream);
},
}, },
}
}; };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.add-merit-name { .add-merit-name {
padding: .4rem; padding: 0.4rem;
.title { .title {
font-size: .4rem; font-size: 0.4rem;
margin-bottom: .4rem; margin-bottom: 0.4rem;
} }
.add-name { .add-name {
@@ -103,49 +102,49 @@ export default {
.input { .input {
flex: 1; flex: 1;
height: .8rem; height: 0.8rem;
line-height: .8rem; line-height: 0.8rem;
padding-left: .3rem; padding-left: 0.3rem;
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: .11rem; border-radius: 0.11rem;
font-size: .4rem; font-size: 0.4rem;
} }
.btn { .btn {
padding: .2rem .6rem; padding: 0.2rem 0.6rem;
background: $primary-color; background: #cf9e3b;
color: white; color: white;
border: 1px solid $primary-color; border: 1px solid #cf9e3b;
font-size: .4rem; font-size: 0.4rem;
border-radius: .11rem; border-radius: 0.11rem;
margin-left: .3rem; margin-left: 0.3rem;
} }
} }
.name-group { .name-group {
padding: .5rem 0; padding: 0.5rem 0;
height: 30vh; height: 30vh;
span { span {
display: inline-block; display: inline-block;
padding: .2rem .3rem; padding: 0.2rem 0.3rem;
background: #fff; background: #fff;
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: .08rem; border-radius: 0.08rem;
position: relative; position: relative;
margin-right: .2rem; margin-right: 0.2rem;
margin-bottom: .2rem; margin-bottom: 0.2rem;
font-size: .35rem; font-size: 0.35rem;
position: relative; position: relative;
vertical-align: top; vertical-align: top;
.iconfont { .iconfont {
position: absolute; position: absolute;
right: -.25rem; right: -0.25rem;
top: -.25rem; top: -0.25rem;
font-size: .5rem; font-size: 0.5rem;
color: red; color: red;
} }
input[type=checkbox]{ input[type="checkbox"] {
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
@@ -153,25 +152,24 @@ export default {
height: 100%; height: 100%;
opacity: 0; opacity: 0;
} }
&.selected{ &.selected {
background: $primary-color; background: #cf9e3b;
color: white; color: white;
} }
} }
} }
.desire-input { .desire-input {
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: .13rem; border-radius: 0.13rem;
overflow: hidden; overflow: hidden;
.desire-textarea { .desire-textarea {
border: none; border: none;
display: block; display: block;
font-size: .35rem; font-size: 0.35rem;
width: calc(100% - .5rem); width: calc(100% - 0.5rem);
padding: .25rem; padding: 0.25rem;
height: 2rem; height: 2rem;
resize: none; resize: none;
line-height: 1.4; line-height: 1.4;
@@ -180,8 +178,8 @@ export default {
span { span {
display: block; display: block;
text-align: right; text-align: right;
padding: .2rem; padding: 0.2rem;
font-size: .35rem; font-size: 0.35rem;
} }
} }
@@ -192,34 +190,33 @@ export default {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
font-size: .4rem; font-size: 0.4rem;
margin-bottom: .3rem; margin-bottom: 0.3rem;
.update { .update {
font-size: .35rem; font-size: 0.35rem;
color: $primary-color; color: #cf9e3b;
} }
} }
.name-group { .name-group {
padding: .1rem 0; padding: 0.1rem 0;
.name { .name {
} }
} }
} }
.confirm { .confirm {
background: $primary-color; background: #cf9e3b;
color: white; color: white;
border: 1px solid $primary-color; border: 1px solid #cf9e3b;
width: 100%; width: 100%;
padding: .3rem 0; padding: 0.3rem 0;
border-radius: 1rem; border-radius: 1rem;
display: block; display: block;
margin: 0 auto; margin: 0 auto;
font-size: .4rem; font-size: 0.4rem;
} }
} }
</style> </style>
+37 -35
View File
@@ -1,11 +1,11 @@
<template> <template>
<div class="merit-goods" @click="onJoin"> <div class="merit-goods" @click="onJoin">
<img class="goods" :src="data.cover_url" alt=""> <img class="goods" :src="data.cover_url" alt="" />
<div class="info"> <div class="info">
<h3 class="title">{{data.title}}</h3> <h3 class="title">{{ data.title }}</h3>
<div class="bar"> <div class="bar">
<span class="join-number">已有{{data.sales}}人参与</span> <span class="join-number">已有{{ data.sales }}人参与</span>
<button class="join" >参与</button> <button class="join">参与</button>
</div> </div>
</div> </div>
</div> </div>
@@ -13,62 +13,64 @@
<script> <script>
export default { export default {
name: 'merit-goods', name: "merit-goods",
props: ['data'], props: ["data"],
methods: { methods: {
onJoin(){ onJoin() {
this.$router.push({ this.$router.push({
name: 'goods-detail', name: "goods-detail",
query: { query: {
goods_id: this.data.id, goods_id: this.data.id,
temple_id: this.data.temple_id temple_id: this.data.temple_id,
} },
}) });
} },
} },
} };
</script> </script>
<style lang="scss"> <style lang="scss">
.merit-goods{ .merit-goods {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
padding: .4rem; padding: 0.4rem;
border-bottom: .01rem solid #f2f2f2; border-bottom: 0.01rem solid #f2f2f2;
.goods{ .goods {
width: 2.93rem; width: 2.93rem;
height: 2.93rem; height: 2.93rem;
margin-right: .4rem; margin-right: 0.4rem;
border-radius: .11rem; border-radius: 0.11rem;
object-fit: contain;
background: #f1f1f1;
} }
.info{ .info {
flex: 1; flex: 1;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between; justify-content: space-between;
.title{ .title {
font-size: .4rem; font-size: 0.4rem;
line-height: 1.3; line-height: 1.3;
} }
.bar{ .bar {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
.join-number{ .join-number {
font-size: .35rem; font-size: 0.35rem;
color: #666; color: #666;
} }
.join{ .join {
height: .67rem; height: 0.67rem;
padding: 0 .4rem; padding: 0 0.4rem;
background: #CF9E3B; background: #cf9e3b;
border: .01rem solid #CF9E3B; border: 0.01rem solid #cf9e3b;
color: white; color: white;
border-radius: .05rem; border-radius: 0.05rem;
font-size: .37rem; font-size: 0.37rem;
line-height: .67rem; line-height: 0.67rem;
}
} }
} }
} }
}
</style> </style>
+67 -70
View File
@@ -1,16 +1,15 @@
<template> <template>
<van-popup :value.sync="visible" position="bottom" @close="onClose" @click-overlay="onClose" safe-area-inset-bottom <van-popup :value.sync="visible" position="bottom" @close="onClose" @click-overlay="onClose" safe-area-inset-bottom style="min-height: 50vh">
style="min-height: 50vh">
<div class="add-merit-name"> <div class="add-merit-name">
<h3 class="title">功德芳名</h3> <h3 class="title">功德芳名</h3>
<div class="add-name"> <div class="add-name">
<input class="input" type="text" v-model="name" placeholder="请输入功德主姓名"> <input class="input" type="text" v-model="name" placeholder="请输入功德主姓名" />
<button class="btn" @click="addName">添加</button> <button class="btn" @click="addName">添加</button>
</div> </div>
<div class="name-group"> <div class="name-group">
<span class="name" :class="[selectedName.includes(name.id) && 'selected']" v-for="(name, index) in names" :key="name.id" @click="onSelectName(name)"> <span class="name" :class="[selectedName.includes(name.id) && 'selected']" v-for="(name, index) in names" :key="name.id" @click="onSelectName(name)">
{{ name.name }} {{ name.name }}
<input type="checkbox" v-model="selectedName" :value="name.id" > <input type="checkbox" v-model="selectedName" :value="name.id" />
<i class="iconfont icon-biaodankongjianshanchu" @click.stop="onDeleteName(name, index)"></i> <i class="iconfont icon-biaodankongjianshanchu" @click.stop="onDeleteName(name, index)"></i>
</span> </span>
</div> </div>
@@ -20,52 +19,52 @@
</template> </template>
<script> <script>
import { deleteMeritName, getMeritName, postMeritName } from '@/api'; import { deleteMeritName, getMeritName, postMeritName } from "@/api";
export default { export default {
name: 'merit-name', name: "merit-name",
props: { props: {
visible: { visible: {
type: Boolean, type: Boolean,
default: false default: false,
}, },
selected: { selected: {
type: Array, type: Array,
default(){ default() {
return [] return [];
} },
}, },
}, },
data() { data() {
return { return {
loading: false, loading: false,
name: '', name: "",
names: [], names: [],
selectedName: [], selectedName: [],
}; };
}, },
watch: { watch: {
visible(value){ visible(value) {
if(value){ if (value) {
this.selectedName = this.selected.map(v => v.id) this.selectedName = this.selected.map((v) => v.id);
}
} }
}, },
},
created() { created() {
this.getName(); this.getName();
}, },
methods: { methods: {
onClose() { onClose() {
this.$emit('update:visible', false); this.$emit("update:visible", false);
}, },
onSelectName(name){ onSelectName(name) {
this.person = name; this.person = name;
this.showDialog = false; this.showDialog = false;
}, },
async addName() { async addName() {
if (!this.name) return; if (!this.name) return;
await postMeritName(this.name); await postMeritName(this.name);
this.name = ''; this.name = "";
await this.getName(); await this.getName();
}, },
async onDeleteName(name) { async onDeleteName(name) {
@@ -77,29 +76,29 @@ export default {
this.names = data; this.names = data;
}, },
async onConfirmMeritName() { async onConfirmMeritName() {
if(this.name){ if (this.name) {
const name = this.name; const name = this.name;
await this.addName(this.name); await this.addName(this.name);
const selected = this.names.filter(item => item.name === name); const selected = this.names.filter((item) => item.name === name);
this.onClose(); this.onClose();
this.$emit('change', selected); this.$emit("change", selected);
return ; return;
} }
const selected = this.names.filter(item => this.selectedName.includes(item.id)); const selected = this.names.filter((item) => this.selectedName.includes(item.id));
this.onClose(); this.onClose();
this.$emit('change', selected); this.$emit("change", selected);
} },
} },
}; };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.add-merit-name { .add-merit-name {
padding: .4rem; padding: 0.4rem;
.title { .title {
font-size: .4rem; font-size: 0.4rem;
margin-bottom: .4rem; margin-bottom: 0.4rem;
} }
.add-name { .add-name {
@@ -107,50 +106,50 @@ export default {
.input { .input {
flex: 1; flex: 1;
height: .8rem; height: 0.8rem;
line-height: .8rem; line-height: 0.8rem;
padding-left: .3rem; padding-left: 0.3rem;
font-size: .35rem; font-size: 0.35rem;
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: .11rem; border-radius: 0.11rem;
font-size: .4rem; font-size: 0.4rem;
} }
.btn { .btn {
padding: .2rem .6rem; padding: 0.2rem 0.6rem;
background: $primary-color; background: #cf9e3b;
color: white; color: white;
border: 1px solid $primary-color; border: 1px solid #cf9e3b;
font-size: .4rem; font-size: 0.4rem;
border-radius: .11rem; border-radius: 0.11rem;
margin-left: .3rem; margin-left: 0.3rem;
} }
} }
.name-group { .name-group {
padding: .5rem 0; padding: 0.5rem 0;
height: 30vh; height: 30vh;
span { span {
display: inline-block; display: inline-block;
padding: .3rem .6rem; padding: 0.3rem 0.6rem;
background: #fff; background: #fff;
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: .08rem; border-radius: 0.08rem;
position: relative; position: relative;
margin-right: .2rem; margin-right: 0.2rem;
margin-bottom: .2rem; margin-bottom: 0.2rem;
font-size: .4rem; font-size: 0.4rem;
position: relative; position: relative;
vertical-align: top; vertical-align: top;
.iconfont { .iconfont {
position: absolute; position: absolute;
right: -.25rem; right: -0.25rem;
top: -.25rem; top: -0.25rem;
font-size: .7rem; font-size: 0.7rem;
color: red; color: red;
} }
input[type=checkbox]{ input[type="checkbox"] {
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
@@ -158,25 +157,24 @@ export default {
height: 100%; height: 100%;
opacity: 0; opacity: 0;
} }
&.selected{ &.selected {
background: $primary-color; background: #cf9e3b;
color: white; color: white;
} }
} }
} }
.desire-input { .desire-input {
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: .13rem; border-radius: 0.13rem;
overflow: hidden; overflow: hidden;
.desire-textarea { .desire-textarea {
border: none; border: none;
display: block; display: block;
font-size: .35rem; font-size: 0.35rem;
width: calc(100% - .5rem); width: calc(100% - 0.5rem);
padding: .25rem; padding: 0.25rem;
height: 2rem; height: 2rem;
resize: none; resize: none;
} }
@@ -184,8 +182,8 @@ export default {
span { span {
display: block; display: block;
text-align: right; text-align: right;
padding: .2rem; padding: 0.2rem;
font-size: .35rem; font-size: 0.35rem;
} }
} }
@@ -196,34 +194,33 @@ export default {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
font-size: .4rem; font-size: 0.4rem;
margin-bottom: .3rem; margin-bottom: 0.3rem;
.update { .update {
font-size: .35rem; font-size: 0.35rem;
color: $primary-color; color: #cf9e3b;
} }
} }
.name-group { .name-group {
padding: .1rem 0; padding: 0.1rem 0;
.name { .name {
} }
} }
} }
.confirm { .confirm {
background: $primary-color; background: #cf9e3b;
color: white; color: white;
border: 1px solid $primary-color; border: 1px solid #cf9e3b;
width: 100%; width: 100%;
padding: .3rem 0; padding: 0.3rem 0;
border-radius: 1rem; border-radius: 1rem;
display: block; display: block;
margin: 0 auto; margin: 0 auto;
font-size: .4rem; font-size: 0.4rem;
} }
} }
</style> </style>
+79 -80
View File
@@ -1,22 +1,22 @@
<template> <template>
<van-popup v-model="value" position="bottom" @close="$emit('update:value', false)"> <van-popup v-model="value" position="bottom" @close="$emit('update:value', false)">
<div class="red-packet" v-if="user"> <div class="red-packet" v-if="user">
<img class="avatar" :src="anonymous ? avatar : user.avatar" alt=""> <img class="avatar" :src="anonymous ? avatar : user.avatar" alt="" />
<div class="username-container"> <div class="username-container">
<div class="username" v-if="!edit" @click="onEdit"> <div class="username" v-if="!edit" @click="onEdit">
<span>{{user.nickname}}</span> <span>{{ user.nickname }}</span>
<i class="iconfont icon-bianjisekuai"></i> <i class="iconfont icon-bianjisekuai"></i>
</div> </div>
<input class="input-username" ref="input" v-if="edit" v-model="user.nickname" @blur="edit = false"> <input class="input-username" ref="input" v-if="edit" v-model="user.nickname" @blur="edit = false" />
</div> </div>
<vue-number-scroll v-model="number"></vue-number-scroll> <vue-number-scroll v-model="number"></vue-number-scroll>
<div class="money-input"> <div class="money-input">
<input type="tel" v-model="money" v-number-only @change="onMoneyInput"> <input type="tel" v-model="money" v-number-only @change="onMoneyInput" />
<span>元</span> <span>元</span>
</div> </div>
<!-- <div class="bar"> <!-- <div class="bar">
<span> <span>
<van-checkbox v-model="anonymous" checked-color="#CF9E3B" @change="onAnonymous">匿名参与</van-checkbox> <van-checkbox v-model="anonymous" checked-color="#CF9E3B;" @change="onAnonymous">匿名参与</van-checkbox>
</span> </span>
<span>查看服务协议</span> <span>查看服务协议</span>
</div> --> </div> -->
@@ -29,152 +29,151 @@
</template> </template>
<script> <script>
import { getRandMoney, getUserData } from '@/api'; import { getRandMoney, getUserData } from "@/api";
import VueNumberScroll from '../vue-number-scroll' import VueNumberScroll from "../vue-number-scroll";
export default { export default {
name: 'random-money', name: "random-money",
components: { components: {
VueNumberScroll VueNumberScroll,
}, },
data(){ data() {
return { return {
avatar: require('@/assets/img/xiaoheshang.jpg'), avatar: require("@/assets/img/xiaoheshang.jpg"),
edit: false, edit: false,
anonymous: false, anonymous: false,
numberArr: ['3', '.', '9','9'], numberArr: ["3", ".", "9", "9"],
number: 0, number: 0,
money: 0, money: 0,
user: null, user: null,
privateUser: null, privateUser: null,
inputNickname: '', inputNickname: "",
randList: [], randList: [],
} };
}, },
props: { props: {
value: { value: {
type: Boolean, type: Boolean,
default: false, default: false,
} },
}, },
mounted() {
mounted(){ this.getRandMoney();
this.getRandMoney()
this.getUserData(); this.getUserData();
}, },
methods: { methods: {
onAnonymous(checked){ onAnonymous(checked) {
this.anonymous = checked; this.anonymous = checked;
if(checked){ if (checked) {
this.user.nickname = '匿名用户' this.user.nickname = "匿名用户";
} else { } else {
this.user.nickname = this.privateUser.nickname this.user.nickname = this.privateUser.nickname;
} }
}, },
onEdit(){ onEdit() {
this.edit = true; this.edit = true;
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.input.focus(); this.$refs.input.focus();
}) });
}, },
async getUserData(){ async getUserData() {
const res = await getUserData(); const res = await getUserData();
this.user = res; this.user = res;
this.privateUser = Object.assign({}, res); this.privateUser = Object.assign({}, res);
this.inputNickname = res.nickname; this.inputNickname = res.nickname;
}, },
onMoneyInput(e){ onMoneyInput(e) {
this.number = e.target.value this.number = e.target.value;
}, },
changeMoney(){ changeMoney() {
const rand = Math.floor(Math.random() * this.randList.length); const rand = Math.floor(Math.random() * this.randList.length);
this.number = Number(this.randList[rand]) this.number = Number(this.randList[rand]);
this.money = this.number; this.money = this.number;
}, },
async getRandMoney(){ async getRandMoney() {
const res = await getRandMoney(); const res = await getRandMoney();
this.randList = res; this.randList = res;
this.money = Number(res[0]) this.money = Number(res[0]);
this.number = Number(res[0]) this.number = Number(res[0]);
}, },
onNext(){ onNext() {
this.$emit('change', { this.$emit("change", {
anonymous: this.anonymous, anonymous: this.anonymous,
money: this.number money: this.number,
}) });
this.$emit('update:value', false) this.$emit("update:value", false);
} },
} },
}; };
</script> </script>
<style lang="scss"> <style lang="scss">
.red-packet{ .red-packet {
min-height: 60vh; min-height: 60vh;
background: #e85042 url('~@/assets/img/red-packet.jpg') top center no-repeat; background: #e85042 url("~@/assets/img/red-packet.jpg") top center no-repeat;
background-size: contain; background-size: contain;
overflow: hidden; overflow: hidden;
padding-bottom: constant(safe-area-inset-bottom); padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom);
.avatar{ .avatar {
width: 2rem; width: 2rem;
height: 2rem; height: 2rem;
display: block; display: block;
border-radius: 1.5rem; border-radius: 1.5rem;
border: 2px solid yellow; border: 2px solid yellow;
margin: 2rem auto .1rem; margin: 2rem auto 0.1rem;
} }
.username-container{ .username-container {
padding-top: .3rem; padding-top: 0.3rem;
height: 1rem; height: 1rem;
.username{ .username {
color: white; color: white;
font-size: .4rem; font-size: 0.4rem;
text-align: center; text-align: center;
margin-top: .3rem; margin-top: 0.3rem;
span{ span {
padding-right: .1rem; padding-right: 0.1rem;
} }
} }
.input-username{ .input-username {
border: 1px solid yellow; border: 1px solid yellow;
font-size: .4rem; font-size: 0.4rem;
background: transparent; background: transparent;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
display: block; display: block;
height: 1rem; height: 1rem;
color: white; color: white;
padding: .1rem .3rem; padding: 0.1rem 0.3rem;
border-radius: 4px; border-radius: 4px;
} }
} }
.money{ .money {
color: yellow; color: yellow;
text-align: center; text-align: center;
height: 1rem; height: 1rem;
line-height: 1rem; line-height: 1rem;
font-size: 1rem; font-size: 1rem;
overflow: hidden; overflow: hidden;
margin-top: .6rem; margin-top: 0.6rem;
margin-bottom: .8rem; margin-bottom: 0.8rem;
ul{ ul {
li{ li {
display: inline-block; display: inline-block;
} }
} }
} }
.bar{ .bar {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
font-size: .4rem; font-size: 0.4rem;
color: white; color: white;
padding: .3rem .6rem; padding: 0.3rem 0.6rem;
margin-top: .6rem; margin-top: 0.6rem;
} }
.money-input{ .money-input {
border: 1px solid yellow; border: 1px solid yellow;
height: 1.2rem; height: 1.2rem;
width: 60%; width: 60%;
@@ -184,48 +183,48 @@ export default {
align-items: center; align-items: center;
border-radius: 2px; border-radius: 2px;
justify-content: space-between; justify-content: space-between;
input{ input {
background: transparent; background: transparent;
border: 1px solid transparent; border: 1px solid transparent;
flex: 1; flex: 1;
height: 100%; height: 100%;
padding-left: .5rem; padding-left: 0.5rem;
font-size: .5rem; font-size: 0.5rem;
width: 50%; width: 50%;
} }
span{ span {
padding: 0 .2rem; padding: 0 0.2rem;
font-size: .5rem; font-size: 0.5rem;
} }
} }
.van-checkbox__label{ .van-checkbox__label {
color: white; color: white;
} }
.random-button-group{ .random-button-group {
text-align: center; text-align: center;
font-size: .5rem; font-size: 0.5rem;
margin-top: .7rem; margin-top: 0.7rem;
display: flex; display: flex;
padding: 0 .4rem; padding: 0 0.4rem;
margin-bottom: .5rem; margin-bottom: 0.5rem;
button{ button {
background: transparent; background: transparent;
margin: 0 .2rem; margin: 0 0.2rem;
height: 1.3rem; height: 1.3rem;
border: 1px solid transparent; border: 1px solid transparent;
color: white; color: white;
} }
.change{ .change {
color: yellow; color: yellow;
border: 1px solid yellow; border: 1px solid yellow;
border-radius: 4px; border-radius: 4px;
flex: 1.3; flex: 1.3;
} }
.next{ .next {
background: yellow; background: yellow;
color: rgb(224, 61, 61); color: rgb(224, 61, 61);
border-radius: 4px; border-radius: 4px;
flex: 2 flex: 2;
} }
} }
} }
+47 -47
View File
@@ -1,10 +1,10 @@
<template> <template>
<div class="input-box"> <div class="input-box">
<div class="input-content" @keydown="keydown" @keyup="keyup" @paste="paste" @mousewheel="mousewheel" @input="inputEvent"> <div class="input-content" @keydown="keydown" @keyup="keyup" @paste="paste" @mousewheel="mousewheel" @input="inputEvent">
<input max="9" min="0" maxlength="1" data-index="0" v-model.trim.number="input[0]" type="number" ref="firstinput"/> <input max="9" min="0" maxlength="1" data-index="0" v-model.trim.number="input[0]" type="number" ref="firstinput" />
<input max="9" min="0" maxlength="1" data-index="1" v-model.trim.number="input[1]" type="number"/> <input max="9" min="0" maxlength="1" data-index="1" v-model.trim.number="input[1]" type="number" />
<input max="9" min="0" maxlength="1" data-index="2" v-model.trim.number="input[2]" type="number"/> <input max="9" min="0" maxlength="1" data-index="2" v-model.trim.number="input[2]" type="number" />
<input max="9" min="0" maxlength="1" data-index="3" v-model.trim.number="input[3]" type="number"/> <input max="9" min="0" maxlength="1" data-index="3" v-model.trim.number="input[3]" type="number" />
</div> </div>
</div> </div>
</template> </template>
@@ -22,7 +22,7 @@
font-family: inherit; font-family: inherit;
border: 0; border: 0;
outline: 0; outline: 0;
border-bottom: 2px solid $primary-color; border-bottom: 2px solid #cf9e3b;
height: 60px; height: 60px;
width: 60px; width: 60px;
font-size: 1rem; font-size: 1rem;
@@ -48,27 +48,27 @@ export default {
pasteResult: [], pasteResult: [],
}; };
}, },
props: ['code'], props: ["code"],
computed: { computed: {
input() { input() {
if (this.code && Array.isArray(this.code) && this.code.length === this.codeCount) { if (this.code && Array.isArray(this.code) && this.code.length === this.codeCount) {
return this.code; return this.code;
} else if (/^\d{this.codeCount}$/.test(this.code.toString())) { } else if (/^\d{this.codeCount}$/.test(this.code.toString())) {
return this.code.toString().split(''); return this.code.toString().split("");
} else if (this.pasteResult.length === this.codeCount) { } else if (this.pasteResult.length === this.codeCount) {
return this.pasteResult; return this.pasteResult;
} else { } else {
return new Array(this.codeCount); return new Array(this.codeCount);
} }
}, },
is_weixn(){ is_weixn() {
const ua = navigator.userAgent.toLowerCase(); const ua = navigator.userAgent.toLowerCase();
if(ua.match(/MicroMessenger/i)=="micromessenger") { if (ua.match(/MicroMessenger/i) == "micromessenger") {
return true; return true;
} else { } else {
return false; return false;
} }
} },
}, },
methods: { methods: {
// 解决一个输入框输入多个字符 // 解决一个输入框输入多个字符
@@ -76,48 +76,48 @@ export default {
var index = e.target.dataset.index * 1; var index = e.target.dataset.index * 1;
var el = e.target; var el = e.target;
// el.value = el.value.replace(/Digit|Numpad/i, '').replace(/1/g, '').slice(0, 1); // el.value = el.value.replace(/Digit|Numpad/i, '').replace(/1/g, '').slice(0, 1);
this.$set(this.input, index, el.value) this.$set(this.input, index, el.value);
}, },
keydown(e) { keydown(e) {
var index = e.target.dataset.index * 1; var index = e.target.dataset.index * 1;
var el = e.target; var el = e.target;
if (e.key === 'Backspace') { if (e.key === "Backspace") {
if (this.input[index].length > 0) { if (this.input[index].length > 0) {
this.$set(this.input, index, '') this.$set(this.input, index, "");
} else { } else {
if (el.previousElementSibling) { if (el.previousElementSibling) {
el.previousElementSibling.focus() el.previousElementSibling.focus();
this.$set(this.input, index - 1, '') this.$set(this.input, index - 1, "");
} }
} }
} else if (e.key === 'Delete') { } else if (e.key === "Delete") {
if (this.input[index].length > 0) { if (this.input[index].length > 0) {
this.$set(this.input, index, '') this.$set(this.input, index, "");
} else { } else {
if (el.nextElementSibling) { if (el.nextElementSibling) {
this.$set(this.input, index = 1, '') this.$set(this.input, (index = 1), "");
} }
} }
if (el.nextElementSibling) { if (el.nextElementSibling) {
el.nextElementSibling.focus() el.nextElementSibling.focus();
} }
} else if (e.key === 'Home') { } else if (e.key === "Home") {
el.parentElement.children[0] && el.parentElement.children[0].focus() el.parentElement.children[0] && el.parentElement.children[0].focus();
} else if (e.key === 'End') { } else if (e.key === "End") {
el.parentElement.children[this.input.length - 1] && el.parentElement.children[this.input.length - 1].focus() el.parentElement.children[this.input.length - 1] && el.parentElement.children[this.input.length - 1].focus();
} else if (e.key === 'ArrowLeft') { } else if (e.key === "ArrowLeft") {
if (el.previousElementSibling) { if (el.previousElementSibling) {
el.previousElementSibling.focus() el.previousElementSibling.focus();
} }
} else if (e.key === 'ArrowRight') { } else if (e.key === "ArrowRight") {
if (el.nextElementSibling) { if (el.nextElementSibling) {
el.nextElementSibling.focus() el.nextElementSibling.focus();
} }
} else if (e.key === 'ArrowUp') { } else if (e.key === "ArrowUp") {
if (this.input[index] * 1 < 9) { if (this.input[index] * 1 < 9) {
this.$set(this.input, index, (this.input[index] * 1 + 1).toString()); this.$set(this.input, index, (this.input[index] * 1 + 1).toString());
} }
} else if (e.key === 'ArrowDown') { } else if (e.key === "ArrowDown") {
if (this.input[index] * 1 > 0) { if (this.input[index] * 1 > 0) {
this.$set(this.input, index, (this.input[index] * 1 - 1).toString()); this.$set(this.input, index, (this.input[index] * 1 - 1).toString());
} }
@@ -129,20 +129,20 @@ export default {
// 解决输入e的问题 // 解决输入e的问题
var reg = /Digit|Numpad/i; var reg = /Digit|Numpad/i;
this.eventObj = JSON.stringify(e); this.eventObj = JSON.stringify(e);
el.value = el.value.replace(reg, '').slice(0, 1); el.value = el.value.replace(reg, "").slice(0, 1);
if (reg.test(e) || this.is_weixn) { if (reg.test(e) || this.is_weixn) {
// 必须在这里符直,否则输入框会是空值 // 必须在这里符直,否则输入框会是空值
this.$set(this.input, index, el.value); this.$set(this.input, index, el.value);
el.nextElementSibling && el.nextElementSibling.focus(); el.nextElementSibling && el.nextElementSibling.focus();
if (index === this.codeCount-1) { if (index === this.codeCount - 1) {
if (this.input.join('').length === this.codeCount) { if (this.input.join("").length === this.codeCount) {
document.activeElement.blur(); document.activeElement.blur();
this.$emit('complete', this.input); this.$emit("complete", this.input);
} }
} }
} else { } else {
if (this.input[index] === '') { if (this.input[index] === "") {
this.$set(this.input, index, ''); this.$set(this.input, index, "");
} }
} }
}, },
@@ -156,33 +156,33 @@ export default {
if (this.input[index] * 1 > 0) { if (this.input[index] * 1 > 0) {
this.$set(this.input, index, (this.input[index] * 1 - 1).toString()); this.$set(this.input, index, (this.input[index] * 1 - 1).toString());
} }
} else if (e.key === 'Enter') { } else if (e.key === "Enter") {
if (this.input.join('').length === this.codeCount) { if (this.input.join("").length === this.codeCount) {
document.activeElement.blur(); document.activeElement.blur();
this.$emit('complete', this.input); this.$emit("complete", this.input);
} }
} }
}, },
paste(e) { paste(e) {
// 当进行粘贴时 // 当进行粘贴时
e.clipboardData.items[0].getAsString(str => { e.clipboardData.items[0].getAsString((str) => {
if (str.toString().length === this.codeCount) { if (str.toString().length === this.codeCount) {
this.pasteResult = str.split(''); this.pasteResult = str.split("");
document.activeElement.blur(); document.activeElement.blur();
this.$emit('complete', this.input); this.$emit("complete", this.input);
this.pasteResult = []; this.pasteResult = [];
} else { } else {
// 如果粘贴内容不合规,清除所有内容 // 如果粘贴内容不合规,清除所有内容
this.input[0] = new Array(6) this.input[0] = new Array(6);
}
})
} }
});
},
}, },
mounted() { mounted() {
// 等待dom渲染完成,在执行focus,否则无法获取到焦点 // 等待dom渲染完成,在执行focus,否则无法获取到焦点
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.firstinput.focus() this.$refs.firstinput.focus();
}) });
}, },
} };
</script> </script>
+28 -32
View File
@@ -1,21 +1,17 @@
<template> <template>
<div class="user-merit border-bottom" v-if="data"> <div class="user-merit border-bottom" v-if="data">
<img <img :src="avatar" alt="" />
:src="data.avatar || data.user_info.avatar"
alt=""
/>
<div class="profile"> <div class="profile">
<div> <div>
<div class="name"> <div class="name">
<span>{{data.merit_name || data.nickname || data.user_info.nickname}}</span> <span>{{ data.merit_name || data.nickname || data.user_info.nickname }}</span>
<!-- <span>{{data.user_info.region}}</span>-->
</div> </div>
<p class="goods_name">{{data.goods_name}}</p> <p class="goods_name">{{ data.goods_name }}</p>
</div> </div>
</div> </div>
<div class="result"> <div class="result">
<p class="money">{{data.order_amount || data.sum_money}}元</p> <p class="money">已参与</p>
<span class="date">{{data.paid_at}}</span> <span class="date">{{ format(data.paid_at) }}</span>
</div> </div>
</div> </div>
</template> </template>
@@ -23,14 +19,24 @@
<script> <script>
export default { export default {
name: "user-merit", name: "user-merit",
props: ['data'] props: ["data"],
data() {
return {
avatar: "/touxiang.png",
};
},
methods: {
format(time) {
return time ? time.slice(0, 10) : "";
},
},
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.user-merit { .user-merit {
display: flex; display: flex;
padding: .27rem 0.4rem; padding: 0.27rem 0.4rem;
img { img {
width: 1.17rem; width: 1.17rem;
height: 1.17rem; height: 1.17rem;
@@ -39,31 +45,21 @@ export default {
} }
.profile { .profile {
flex: 1; flex: 1;
padding-top: .13rem; padding-top: 0.13rem;
.name { .name {
display: flex; display: flex;
align-items: flex-end; align-items: flex-end;
margin-bottom: .27rem; margin-bottom: 0.2rem;
span:first-child {
font-size: 0.4rem; font-size: 0.4rem;
color: #222;
vertical-align: top;
display: inline-block;
margin-right: .4rem;
line-height: 1.3; line-height: 1.3;
} }
span:last-child { p.goods_name {
font-size: 0.32rem; font-size: 0.34rem;
color: #666; max-width: 15em;
vertical-align: text-bottom; line-height: 1.2;
display: inline-block;
}
}
p.goods_name{
font-size: 0.32rem;
max-width: 4rem;
white-space: nowrap;
overflow: hidden; overflow: hidden;
color: #666;
white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
} }
@@ -72,15 +68,15 @@ export default {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
flex-direction: column; flex-direction: column;
padding: .13rem 0; padding: 0.13rem 0;
text-align: right; text-align: right;
.money { .money {
font-size: 0.37rem; font-size: 0.37rem;
color: $primary-color; color: #cf9e3b;
font-weight: bold; font-weight: bold;
} }
.date { .date {
font-size: 0.3rem; font-size: 0.34rem;
color: #888; color: #888;
} }
} }
+3
View File
@@ -0,0 +1,3 @@
<template>
<div>订单详情</div>
</template>
+152
View File
@@ -0,0 +1,152 @@
<template>
<div class="order-page">
<van-search v-model="keyword" placeholder="请输入手机号" />
<mescroll-vue ref="mescroll" :down="mescrollDown" :up="mescrollUp" @init="mescrollInit">
<div class="scroll-wrapper">
<!--内容...-->
<div class="list" v-for="(item, index) in dataList" :key="index">
<div class="order-item">
<div class="temple">
<span class="sn">{{ item.order_sn }}</span>
<span class="name">{{ item.temple_name }}</span>
</div>
<div class="goods">
<h3 class="name">
<span class="state" v-if="item.status == 2">待处理</span>
<span>{{ item.goods_name }}</span>
</h3>
<div class="sku">
<span>数量: x{{ item.buy_total }}</span>
<span>金额: ¥{{ item.price }}</span>
<span>行善时间: {{ item.paid_at }}</span>
<span>行善者: {{ item.user_name }}</span>
</div>
</div>
<div class="action-buttons">
<van-button type="info" block round v-if="item.status == 2" @click="onProcess(item)"> 立即处理</van-button>
<!-- <van-button type="info" plain block round>查看详情</van-button> -->
</div>
</div>
</div>
</div>
</mescroll-vue>
</div>
</template>
<script>
import MescrollVue from "mescroll.js/mescroll.vue";
import { getOrderList } from "@/api/admin";
export default {
comments: {
MescrollVue,
},
data() {
return {
pagination: {
page: 1,
size: 10,
},
keyword: "",
mescroll: null,
mescrollDown: {},
mescrollUp: {
// 上拉加载的配置.
callback: this.upCallback,
},
dataList: [],
};
},
methods: {
mescrollInit(mescroll) {
this.mescroll = mescroll;
},
upCallback(page) {
console.log("load", page);
this.pagination.page = page.num;
this.getOrderList();
},
async getOrderList() {
const res = await getOrderList({
keyword: this.keyword,
...this.pagination,
});
this.dataList = this.dataList.concat(res.results);
this.total = res.total;
console.log("mescroll", this.mescroll);
this.mescroll.endSuccess();
console.log(res);
},
onProcess(item) {
this.$router.push({
name: "adminOrderProcess",
query: {
id: item.id,
name: item.goods_name,
},
});
},
},
};
</script>
<style lang="scss">
.order-page {
background-color: #f5f1fd;
height: 100vh;
.scroll-wrapper {
flex: 1;
overflow: hidden;
.list {
padding: 0.1rem 0.2rem;
}
.order-item {
background: white;
padding: 0.2rem;
border-radius: 0.2rem;
box-shadow: 0 0 6ox rgba(0, 0, 0, 0.1);
.temple {
display: flex;
justify-content: space-between;
padding: 0.2rem 0;
.sn,
.name {
font-size: 0.3rem;
color: #888;
}
}
.goods {
padding-top: 0.2rem;
.name {
font-size: 0.4rem;
font-weight: bold;
margin-bottom: 0.4rem;
line-height: 1.6;
.state {
font-size: 0.25rem;
color: #fff;
background-color: #188fff;
padding: 0.1rem 0.2rem;
border-radius: 0.13rem;
margin-right: 0.1rem;
}
}
.sku {
display: grid;
gap: 0.3rem;
grid-template-columns: repeat(2, 1fr);
font-size: 0.3rem;
color: #888;
}
}
.action-buttons {
margin-top: 12px;
display: flex;
column-gap: 12px;
.van {
}
}
}
}
}
</style>
+78
View File
@@ -0,0 +1,78 @@
<template>
<van-form @submit="onSubmit">
<van-field name="name" label="善缘名称">
<template #input>
<span>{{ $route.query.name }}</span>
</template>
</van-field>
<van-field name="feedback_pictures" label="反馈照片">
<template #input>
<van-uploader preview-size="76px" accept="image/*" multiple v-model="form.feedback_pictures" :max-count="5" :after-read="afterRead" />
</template>
<span style="font-size: 0.2rem; color: #999">最多5张</span>
</van-field>
<van-field name="feedback_content" label="反馈内容" v-model="form.feedback_content"> </van-field>
<div style="margin: 16px">
<van-button round block type="info" native-type="submit">提交</van-button>
</div>
</van-form>
</template>
<script>
import { uploadImage, postFeedback } from "@/api/admin";
export default {
data() {
return {
form: {
feedback_pictures: [],
feedback_content: "",
},
};
},
methods: {
afterRead(file) {
console.log("file", file);
const files = Array.isArray(file) ? file : [file];
for (const item of files) {
item.status = "uploading";
item.message = "上传中...";
const formData = new FormData();
formData.append("photo", item.file);
uploadImage(formData)
.then((res) => {
console.log("res", res);
item.status = "success";
item.message = "上传成功";
item.url = res.url;
})
.catch((err) => {
console.log("err", err);
item.status = "error";
item.message = "上传失败";
});
}
},
onSubmit(values) {
if (values.feedback_pictures.some((item) => item.status == "uploading")) {
this.$toast("还有照片正在上传,请稍后");
return;
}
postFeedback(this.$route.query.id, {
feedback_content: values.feedback_content,
feedback_pictures: values.feedback_pictures.map((item) => item.url),
})
.then((res) => {
console.log("res", res);
this.$toast("反馈成功");
this.$router.replace({
name: "adminOrder",
});
})
.catch((err) => {
console.log("err", err);
this.$toast("反馈失败");
});
},
},
};
</script>
+31 -31
View File
@@ -20,10 +20,10 @@
<i class="iconfont icon-guanzhu-yiguanzhu"></i> <i class="iconfont icon-guanzhu-yiguanzhu"></i>
<b>关注</b> <b>关注</b>
</span> </span>
<!-- <span class="btn" @click="onShare">--> <!-- <span class="btn" @click="onShare">-->
<!-- <i class="iconfont icon-zhuanfa"></i>--> <!-- <i class="iconfont icon-zhuanfa"></i>-->
<!-- <b>转发</b>--> <!-- <b>转发</b>-->
<!-- </span>--> <!-- </span>-->
</div> </div>
</div> </div>
</div> </div>
@@ -31,17 +31,17 @@
</template> </template>
<script> <script>
import { getDynamicDetail, toggleCollect } from '@/api'; import { getDynamicDetail, toggleCollect } from "@/api";
export default { export default {
name: 'buddha-detail', name: "buddha-detail",
data() { data() {
return { return {
data: null, data: null,
showShare: false, showShare: false,
options: [ options: [
{ name: '微信', icon: 'wechat' }, { name: "微信", icon: "wechat" },
{ name: '朋友圈', icon: 'wechat-moments' }, { name: "朋友圈", icon: "wechat-moments" },
], ],
}; };
}, },
@@ -49,7 +49,7 @@ export default {
covers: { covers: {
get() { get() {
const type = Object.prototype.toString.call(this.data.covers); const type = Object.prototype.toString.call(this.data.covers);
return type === '[object Object]' ? []: this.data.covers.slice(0, 3); return type === "[object Object]" ? [] : this.data.covers.slice(0, 3);
}, },
}, },
}, },
@@ -57,28 +57,28 @@ export default {
this.getDynamicDetail(); this.getDynamicDetail();
}, },
methods: { methods: {
onShare(){ onShare() {
this.showShare = true; this.showShare = true;
}, },
async getDynamicDetail(){ async getDynamicDetail() {
const data = await getDynamicDetail(this.$route.query.id); const data = await getDynamicDetail(this.$route.query.id);
this.data = data; this.data = data;
this.wechatReady({ this.wechatReady({
...data.shareConfig, ...data.shareConfig,
link: location.href + '&jumpUrl=https://baidu.com', link: location.href + "&jumpUrl=https://baidu.com",
}) });
}, },
async onCollect() { async onCollect() {
await toggleCollect(this.data.id); await toggleCollect(this.data.id);
this.data.is_collected = this.data.is_collected === 1 ? 0 : 1; this.data.is_collected = this.data.is_collected === 1 ? 0 : 1;
}, },
onGoodsDetail(){ onGoodsDetail() {
const { goods_type, goods_id, temple_id } = this.data; const { goods_type, goods_id, temple_id } = this.data;
this.onPushToGoodsDetail(goods_type, goods_id, temple_id) this.onPushToGoodsDetail(goods_type, goods_id, temple_id);
} },
}, },
}; };
</script> </script>
@@ -87,10 +87,10 @@ export default {
.process-detail-wrapper { .process-detail-wrapper {
display: flex; display: flex;
position: relative; position: relative;
padding: .5rem .4rem env(safe-area-inset-bottom) .4rem; padding: 0.5rem 0.4rem env(safe-area-inset-bottom) 0.4rem;
margin-bottom: 1rem; margin-bottom: 1rem;
&::after { &::after {
content: ''; content: "";
height: 1px; height: 1px;
width: 200%; width: 200%;
background: #ededed; background: #ededed;
@@ -111,8 +111,8 @@ export default {
font-size: 0.35rem; font-size: 0.35rem;
color: #666666; color: #666666;
display: block; display: block;
margin-bottom: .3rem; margin-bottom: 0.3rem;
padding: .1rem 0; padding: 0.1rem 0;
} }
.title { .title {
font-size: 0.43rem; font-size: 0.43rem;
@@ -126,9 +126,9 @@ export default {
color: #5a5a5a; color: #5a5a5a;
text-align: justify; text-align: justify;
} }
.detail-text{ .detail-text {
font-size: .4rem; font-size: 0.4rem;
padding-top: .2rem; padding-top: 0.2rem;
color: #b74100; color: #b74100;
} }
.image-group { .image-group {
@@ -144,16 +144,16 @@ export default {
} }
} }
} }
.process-content{ .process-content {
font-size: .4rem; font-size: 0.4rem;
img{ img {
max-width: 100%; max-width: 100%;
} }
p{ p {
margin: .3rem 0; margin: 0.3rem 0;
line-height: 1.4; line-height: 1.4;
color: #5a5a5a; color: #5a5a5a;
font-size: .37rem; font-size: 0.37rem;
letter-spacing: 1px; letter-spacing: 1px;
} }
& * { & * {
@@ -190,7 +190,7 @@ export default {
align-items: center; align-items: center;
.iconfont { .iconfont {
color: $primary-color; color: #cf9e3b;
vertical-align: middle; vertical-align: middle;
font-size: 0.4rem; font-size: 0.4rem;
margin-top: -3px; margin-top: -3px;
@@ -205,7 +205,7 @@ export default {
} }
.collect { .collect {
.iconfont { .iconfont {
color: $primary-color; color: #cf9e3b;
} }
} }
.un-collect { .un-collect {
+9 -9
View File
@@ -78,7 +78,7 @@
<p class="label">自动行善</p> <p class="label">自动行善</p>
<div class="donate"> <div class="donate">
<span>每天早上六点寺院联盟帮你自动行善一次</span> <span>每天早上六点寺院联盟帮你自动行善一次</span>
<van-checkbox v-model="is_auto" shape="square" checked-color="#cf9e3b"></van-checkbox> <van-checkbox v-model="is_auto" shape="square" checked-color="#CF9E3B;"></van-checkbox>
</div> </div>
</div> </div>
<div class="auto-donate-time" v-if="is_auto"> <div class="auto-donate-time" v-if="is_auto">
@@ -116,7 +116,7 @@
<p class="label">每日填砖</p> <p class="label">每日填砖</p>
<div class="donate"> <div class="donate">
<span>每天早上六点寺院联盟帮你自动填砖一次</span> <span>每天早上六点寺院联盟帮你自动填砖一次</span>
<van-checkbox v-model="is_auto" shape="square" checked-color="#cf9e3b"></van-checkbox> <van-checkbox v-model="is_auto" shape="square" checked-color="#CF9E3B;"></van-checkbox>
</div> </div>
</div> </div>
<div class="auto-donate-time" v-if="is_auto"> <div class="auto-donate-time" v-if="is_auto">
@@ -457,7 +457,7 @@ export default {
user-select: none; user-select: none;
color: #666; color: #666;
&:active { &:active {
background: rgba($primary-color, 0.1); background: rgba(#cf9e3b, 0.1);
} }
} }
span.spec-disabled { span.spec-disabled {
@@ -480,7 +480,7 @@ export default {
align-items: center; align-items: center;
} }
span.active { span.active {
color: $primary-color; color: #cf9e3b;
} }
} }
.auto-donate { .auto-donate {
@@ -537,7 +537,7 @@ export default {
.total { .total {
font-size: 0.4rem; font-size: 0.4rem;
em { em {
color: $primary-color; color: #cf9e3b;
font-size: 0.4rem; font-size: 0.4rem;
font-weight: bold; font-weight: bold;
} }
@@ -545,8 +545,8 @@ export default {
.next { .next {
font-size: 0.4rem; font-size: 0.4rem;
padding: 0.3rem 1rem; padding: 0.3rem 1rem;
background: $primary-color; background: #cf9e3b;
border: 1px solid $primary-color; border: 1px solid #cf9e3b;
color: white; color: white;
border-radius: 0.1rem; border-radius: 0.1rem;
} }
@@ -637,13 +637,13 @@ export default {
padding-bottom: calc(env(safe-area-inset-bottom) + 0.2rem); padding-bottom: calc(env(safe-area-inset-bottom) + 0.2rem);
.merit-button { .merit-button {
display: inline-block; display: inline-block;
background: $primary-color; background: #cf9e3b;
color: white; color: white;
height: 1.2rem; height: 1.2rem;
font-size: 0.37rem; font-size: 0.37rem;
width: 60%; width: 60%;
padding: 0 0.53rem; padding: 0 0.53rem;
border: 0.01rem solid $primary-color; border: 0.01rem solid #cf9e3b;
border-radius: 1.33rem; border-radius: 1.33rem;
} }
} }
+83 -82
View File
@@ -5,11 +5,11 @@
<div class="field"> <div class="field">
<label class="required">功德芳名</label> <label class="required">功德芳名</label>
<div class="input-wrapper"> <div class="input-wrapper">
<input class="input" :value="meritName" type="text" readonly placeholder="请输入功德芳名" @click="onShowDialog('name')"> <input class="input" :value="meritName" type="text" readonly placeholder="请输入功德芳名" @click="onShowDialog('name')" />
</div> </div>
</div> </div>
<div class="field"> <div class="field">
<label >心愿</label> <label>心愿</label>
<div class="input-wrapper" @click="onShowDesire"> <div class="input-wrapper" @click="onShowDesire">
<textarea class="input" v-model="dream" placeholder="请填写您的心愿" readonly type="textarea" /> <textarea class="input" v-model="dream" placeholder="请填写您的心愿" readonly type="textarea" />
<i class="iconfont icon-arrow-right"></i> <i class="iconfont icon-arrow-right"></i>
@@ -19,27 +19,29 @@
<div class="field"> <div class="field">
<label class="required">阳上人</label> <label class="required">阳上人</label>
<div class="input-wrapper"> <div class="input-wrapper">
<input class="input" v-model="live_name" type="tel" placeholder="请填写阳上人"> <input class="input" v-model="live_name" type="tel" placeholder="请填写阳上人" />
</div> </div>
</div> </div>
<div class="field"> <div class="field">
<label class="required">往生者</label> <label class="required">往生者</label>
<div class="input-wrapper"> <div class="input-wrapper">
<input class="input" v-model="die_name" type="tel" placeholder="请填写往生者"> <input class="input" v-model="die_name" type="tel" placeholder="请填写往生者" />
</div> </div>
</div> </div>
</template> </template>
<div class="field"> <div class="field">
<label >手机号码</label> <label>手机号码</label>
<div class="input-wrapper"> <div class="input-wrapper">
<input class="input" v-model="mobile" type="tel" placeholder="请填写手机号码"> <input class="input" v-model="mobile" type="tel" placeholder="请填写手机号码" />
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="btn-wrapper"> <div class="btn-wrapper">
<span class="total">合计: <b class="price">¥{{query.amount}}</b></span> <span class="total"
>合计: <b class="price">¥{{ query.amount }}</b></span
>
<button type="button" @click="onNext">下一步</button> <button type="button" @click="onNext">下一步</button>
</div> </div>
@@ -51,167 +53,166 @@
<script> <script>
export default { export default {
name: 'fill-name', name: "fill-name",
data(){ data() {
return { return {
query: this.$route.query, query: this.$route.query,
mobile: '', mobile: "",
dream: '', dream: "",
merit_name_id: '', merit_name_id: "",
dialogName: '', dialogName: "",
showMeritName: false, showMeritName: false,
showDesire: false, showDesire: false,
merit_names: [], merit_names: [],
meritTypes: [], meritTypes: [],
meritTypeId: null, meritTypeId: null,
showBuddhi: true, showBuddhi: true,
live_name: '', // 阳上人姓名 live_name: "", // 阳上人姓名
die_name: '', // 往生人姓名 die_name: "", // 往生人姓名
} };
}, },
computed: { computed: {
meritName(){ meritName() {
return this.merit_names.map(item => item.name).join(',') return this.merit_names.map((item) => item.name).join(",");
}, },
meritId(){ meritId() {
return this.merit_names.map(item => item.id).join(',') return this.merit_names.map((item) => item.id).join(",");
}, },
}, },
methods: { methods: {
onShowDialog() {
onShowDialog(){
this.showMeritName = true; this.showMeritName = true;
}, },
onShowDesire(){ onShowDesire() {
this.showDesire = true; this.showDesire = true;
}, },
onMeritName(meritNameArr){ onMeritName(meritNameArr) {
this.merit_names = meritNameArr; this.merit_names = meritNameArr;
}, },
onMeritDesire(desire){ onMeritDesire(desire) {
this.dream = desire; this.dream = desire;
}, },
onNext(){ onNext() {
if(!this.meritId){ if (!this.meritId) {
return this.$toast.fail('请填写功德芳名'); return this.$toast.fail("请填写功德芳名");
} }
if(this.query.is_die == 1 && (!this.live_name || !this.die_name)){ if (this.query.is_die == 1 && (!this.live_name || !this.die_name)) {
return this.$toast.fail('请填写阳上人与往生人') return this.$toast.fail("请填写阳上人与往生人");
} }
this.$router.push({ this.$router.push({
name: 'pay', name: "pay",
query: { query: {
...this.$route.query, ...this.$route.query,
dream: this.dream, dream: this.dream,
merit_name: this.meritName, merit_name: this.meritName,
mobile: this.mobile, mobile: this.mobile,
live_name: this.live_name, live_name: this.live_name,
die_name: this.die_name die_name: this.die_name,
} },
}) });
} },
} },
}; };
</script> </script>
<style lang="scss"> <style lang="scss">
.fill-name{ .fill-name {
.field{ .field {
.van-radio__icon--checked .van-icon{ .van-radio__icon--checked .van-icon {
background: #CF9E3B; background: #cf9e3b;
border-color: #CF9E3B; border-color: #cf9e3b;
} }
} }
} }
</style> </style>
<style scoped lang="scss"> <style scoped lang="scss">
.fill-name{ .fill-name {
background: #f9f9f9; background: #f9f9f9;
height: 100vh; height: 100vh;
position: relative; position: relative;
.panel-wrapper{ .panel-wrapper {
padding: .3rem; padding: 0.3rem;
} }
.panel{ .panel {
padding: .3rem; padding: 0.3rem;
border-radius: .1rem; border-radius: 0.1rem;
font-size: .4rem; font-size: 0.4rem;
background: white; background: white;
box-shadow: 0 0 .2rem rgba(0,0,0,0.05); box-shadow: 0 0 0.2rem rgba(0, 0, 0, 0.05);
} }
.field{ .field {
margin-bottom: .6rem; margin-bottom: 0.6rem;
.required{ .required {
&::after{ &::after {
content: '*'; content: "*";
color: red; color: red;
margin-left: .1rem; margin-left: 0.1rem;
} }
} }
label{ label {
color: #333; color: #333;
} }
.input-wrapper{ .input-wrapper {
margin-top: .2rem; margin-top: 0.2rem;
border: 1px solid rgba(183, 173, 173, 0.54); border: 1px solid rgba(183, 173, 173, 0.54);
padding: .2rem .3rem; padding: 0.2rem 0.3rem;
border-radius: .1rem; border-radius: 0.1rem;
position: relative; position: relative;
background: #fdfdfd; background: #fdfdfd;
.input{ .input {
display: block; display: block;
width: 100%; width: 100%;
border: none; border: none;
background: transparent; background: transparent;
} }
.input[type=textarea]{ .input[type="textarea"] {
min-height: 2rem; min-height: 2rem;
width: calc(100% - .5rem); width: calc(100% - 0.5rem);
padding-right: .5rem; padding-right: 0.5rem;
line-height: 1.4; line-height: 1.4;
text-align: justify; text-align: justify;
} }
.icon-arrow-right{ .icon-arrow-right {
position: absolute; position: absolute;
right: .1rem; right: 0.1rem;
top: 50%; top: 50%;
transform: translateY(-.35rem); transform: translateY(-0.35rem);
display: inline-block; display: inline-block;
font-size: .7rem; font-size: 0.7rem;
color: #aaa; color: #aaa;
} }
} }
} }
.btn-wrapper{ .btn-wrapper {
position: absolute; position: absolute;
left: .3rem; left: 0.3rem;
right: .3rem; right: 0.3rem;
bottom: calc(.5rem + env(safe-area-inset-bottom)); bottom: calc(0.5rem + env(safe-area-inset-bottom));
border: 1px solid $primary-color; border: 1px solid #cf9e3b;
border-radius: 100px; border-radius: 100px;
background: white; background: white;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
overflow: hidden; overflow: hidden;
align-items: center; align-items: center;
.total{ .total {
font-size: .4rem; font-size: 0.4rem;
color: $primary-color; color: #cf9e3b;
padding-left: .4rem; padding-left: 0.4rem;
.price{ .price {
font-size: .5rem; font-size: 0.5rem;
line-height: 1; line-height: 1;
font-weight: bold; font-weight: bold;
} }
} }
button{ button {
background: linear-gradient(to bottom, $primary-color, #9f7313); background: linear-gradient(to bottom, #cf9e3b, #9f7313);
color: white; color: white;
height: 1.4rem; height: 1.4rem;
border: none; border: none;
font-size: .5rem; font-size: 0.5rem;
padding: 0 1rem; padding: 0 1rem;
width: 50%; width: 50%;
} }
+81 -80
View File
@@ -6,7 +6,7 @@
<h1 class="title">在线护持 寺院道场 供养三宝 广种福田</h1> <h1 class="title">在线护持 寺院道场 供养三宝 广种福田</h1>
<div class="inner"> <div class="inner">
<div class="field"> <div class="field">
<input type="tel" v-model="mobile" maxlength="11" placeholder="请输入手机号码"> <input type="tel" v-model="mobile" maxlength="11" placeholder="请输入手机号码" />
</div> </div>
<p class="tip">未注册的手机号验证后自动创建账户</p> <p class="tip">未注册的手机号验证后自动创建账户</p>
@@ -23,174 +23,175 @@
</div> </div>
<div class="top" v-if="sended"> <div class="top" v-if="sended">
<h1 class="title">请输入验证码</h1> <h1 class="title">请输入验证码</h1>
<p class="send-to">验证码已发送至 {{mobile | fmMobile}}</p> <p class="send-to">验证码已发送至 {{ mobile | fmMobile }}</p>
<sms-code-input :code="validCode" @complete="onSubmitBefore"></sms-code-input> <sms-code-input :code="validCode" @complete="onSubmitBefore"></sms-code-input>
<p class="resend"><span>{{countdown}}</span>秒后重新发送验证码</p> <p class="resend">
<span>{{ countdown }}</span
>秒后重新发送验证码
</p>
<van-button type="info" :disabled="!(validCode.length === 4)" block @click="onSubmit">提交</van-button> <van-button type="info" :disabled="!(validCode.length === 4)" block @click="onSubmit">提交</van-button>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { getMobileValidateCode, postMobileCode } from '@/api'; import { getMobileValidateCode, postMobileCode } from "@/api";
import SmsCodeInput from '@/components/sms-code-input' import SmsCodeInput from "@/components/sms-code-input";
export default { export default {
components: { components: {
SmsCodeInput SmsCodeInput,
}, },
data() { data() {
return { return {
query: this.$route.query, query: this.$route.query,
mobile: '', mobile: "",
validCode: '', validCode: "",
countdown: 0, countdown: 0,
timer: null, timer: null,
sended: false, sended: false,
}; };
}, },
filters: { filters: {
fmMobile(val){ fmMobile(val) {
return val.replace(/(\d{3})(\d{4})/, "$1 $2 ") return val.replace(/(\d{3})(\d{4})/, "$1 $2 ");
} },
}, },
computed: { computed: {
validMobile(){ validMobile() {
const reg = /^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$/; const reg = /^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$/;
return !reg.test(this.mobile) return !reg.test(this.mobile);
}, },
}, },
methods: { methods: {
onAgreement(agreeId){ onAgreement(agreeId) {
this.$router.push({ name: 'user-temple-station-agreement', query: { agreeId }}) this.$router.push({ name: "user-temple-station-agreement", query: { agreeId } });
}, },
onSubmitBefore(code){ onSubmitBefore(code) {
this.validCode = code this.validCode = code;
this.onSubmit(); this.onSubmit();
}, },
async onSubmit() { async onSubmit() {
const { mobile, validCode } = this; const { mobile, validCode } = this;
if(!mobile){ if (!mobile) {
return this.$toast('请输入手机号') return this.$toast("请输入手机号");
} }
if(!validCode){ if (!validCode) {
return this.$toast('请输入验证码') return this.$toast("请输入验证码");
} }
const res = await postMobileCode(mobile, validCode.join('')) const res = await postMobileCode(mobile, validCode.join(""));
if(res){ if (res) {
this.$toast.success('登记成功,请继续后续操作') this.$toast.success("登记成功,请继续后续操作");
this.$delay(500); this.$delay(500);
this.$bus.$emit('updateMobile') this.$bus.$emit("updateMobile");
this.$router.replace({ this.$router.replace({
path: this.query.redirectPath, path: this.query.redirectPath,
query: this.$utils.queryStringToObj(decodeURIComponent(this.query.redirectPathQuery)) query: this.$utils.queryStringToObj(decodeURIComponent(this.query.redirectPathQuery)),
}) });
} }
}, },
onSendCode(){ onSendCode() {
const { mobile } = this; const { mobile } = this;
if(!mobile){ if (!mobile) {
return this.$toast('请输入手机号') return this.$toast("请输入手机号");
} }
getMobileValidateCode(mobile).then(success => { getMobileValidateCode(mobile).then((success) => {
if(success){ if (success) {
this.$toast('发送成功,请注意查收短信'); this.$toast("发送成功,请注意查收短信");
this.sended = true; this.sended = true;
if(this.countdown === 0){ if (this.countdown === 0) {
this.countdown = 60; this.countdown = 60;
this.countdownSecond() this.countdownSecond();
} }
} }
}) });
}, },
countdownSecond(){ countdownSecond() {
this.timer = setInterval(() => { this.timer = setInterval(() => {
this.countdown --; this.countdown--;
if(this.countdown == 0){ if (this.countdown == 0) {
clearInterval(this.timer) clearInterval(this.timer);
}
}, 1000)
} }
}, 1000);
},
}, },
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.top{ .top {
padding: 0 .5rem; padding: 0 0.5rem;
font-size: .35rem; font-size: 0.35rem;
padding-top: .3rem; padding-top: 0.3rem;
.title{ .title {
font-size: .5rem; font-size: 0.5rem;
margin-top: 1rem; margin-top: 1rem;
font-weight: bold; font-weight: bold;
text-align: center; text-align: center;
color: #a5161a; color: #a5161a;
font-family: '宋体'; font-family: "宋体";
} }
.inner{ .inner {
margin-top: 1rem; margin-top: 1rem;
.field{ .field {
background: #f1f1f1; background: #f1f1f1;
margin-bottom: .2rem; margin-bottom: 0.2rem;
padding: .1rem .4rem; padding: 0.1rem 0.4rem;
input{ input {
height: .8rem; height: 0.8rem;
background: transparent; background: transparent;
border: none; border: none;
display: block; display: block;
width: 100%; width: 100%;
font-size: .4rem; font-size: 0.4rem;
} }
} }
.tip{ .tip {
font-size: .3rem; font-size: 0.3rem;
margin-bottom: 1.2rem; margin-bottom: 1.2rem;
color: #888; color: #888;
} }
.desc{ .desc {
font-size: .4rem; font-size: 0.4rem;
text-align: center; text-align: center;
padding-top: 2rem; padding-top: 2rem;
} }
.agree{ .agree {
font-size: .35rem; font-size: 0.35rem;
text-align: center; text-align: center;
position: absolute; position: absolute;
left: 0; left: 0;
right: 0; right: 0;
bottom: 2rem; bottom: 2rem;
a{ a {
color: $primary-color; color: #cf9e3b;
} }
} }
} }
.send-to{ .send-to {
font-size: .35rem; font-size: 0.35rem;
margin-top: .2rem; margin-top: 0.2rem;
} }
.notification{ .notification {
padding-top: .8rem; padding-top: 0.8rem;
p{ p {
margin: 0; margin: 0;
font-size: .34rem; font-size: 0.34rem;
color: #a5161a; color: #a5161a;
line-height: 1.4; line-height: 1.4;
margin-bottom: .2rem; margin-bottom: 0.2rem;
font-family: '宋体'; font-family: "宋体";
text-align: justify; text-align: justify;
} }
} }
.resend{ .resend {
padding-top: .6rem; padding-top: 0.6rem;
margin-bottom: 3rem; margin-bottom: 3rem;
span{ span {
color: $primary-color; color: #cf9e3b;
padding-right: .2rem; padding-right: 0.2rem;
} }
} }
} }
@@ -116,9 +116,9 @@ export default {
} }
.btn { .btn {
padding: 0.2rem 0.6rem; padding: 0.2rem 0.6rem;
background: $primary-color; background: #cf9e3b;
color: white; color: white;
border: 1px solid $primary-color; border: 1px solid #cf9e3b;
font-size: 0.4rem; font-size: 0.4rem;
border-radius: 0.11rem; border-radius: 0.11rem;
margin-left: 0.3rem; margin-left: 0.3rem;
@@ -176,7 +176,7 @@ export default {
margin-bottom: 0.3rem; margin-bottom: 0.3rem;
.update { .update {
font-size: 0.35rem; font-size: 0.35rem;
color: $primary-color; color: #cf9e3b;
} }
} }
.name-group { .name-group {
@@ -186,9 +186,9 @@ export default {
} }
} }
.confirm { .confirm {
background: $primary-color; background: #cf9e3b;
color: white; color: white;
border: 1px solid $primary-color; border: 1px solid #cf9e3b;
width: 3rem; width: 3rem;
padding: 0.3rem 0; padding: 0.3rem 0;
border-radius: 0.07rem; border-radius: 0.07rem;
@@ -2,11 +2,11 @@
<span> <span>
<ul class="spec-group"> <ul class="spec-group">
<li class="border-circle" :class="[value === 'is_customized' && 'active']" @click="onAnyAmount"> <li class="border-circle" :class="[value === 'is_customized' && 'active']" @click="onAnyAmount">
<span>{{data.rule_btn}}</span> <span>{{ data.rule_btn }}</span>
</li> </li>
<li class="border-circle" v-for="spec in data.spec" :key="spec.id" :class="[ value === spec.id && 'active']" @click="onSelectSpec(spec)"> <li class="border-circle" v-for="spec in data.spec" :key="spec.id" :class="[value === spec.id && 'active']" @click="onSelectSpec(spec)">
<span>{{spec.spec_name}}</span> <span>{{ spec.spec_name }}</span>
<span>¥ {{spec.price}}</span> <span>¥ {{ spec.price }}</span>
</li> </li>
</ul> </ul>
@@ -14,7 +14,7 @@
<div class="donate"> <div class="donate">
<span class="label">数量</span> <span class="label">数量</span>
<span class="time-cycle"> <span class="time-cycle">
<van-stepper v-model="num" step="1" @change="onChangeNumber"/> <van-stepper v-model="num" step="1" @change="onChangeNumber" />
</span> </span>
</div> </div>
</div> </div>
@@ -22,65 +22,63 @@
</template> </template>
<script> <script>
export default { export default {
props: { props: {
value: { value: {
type: [String, Number] type: [String, Number],
}, },
data: { data: {
type: Object, type: Object,
}, },
number: Number, number: Number,
}, },
data(){ data() {
return { return {
num: 0, num: 0,
is_customized: false, is_customized: false,
} };
}, },
watch: { watch: {
number: { number: {
handler(val) { handler(val) {
this.num = val; this.num = val;
} },
} },
}, },
methods: { methods: {
onChangeNumber(value){ onChangeNumber(value) {
this.$emit('update:number', value) this.$emit("update:number", value);
},
onSelectSpec(spec) {
this.$emit("input", spec.id);
},
onAnyAmount() {
this.$emit("input", "is_customized");
}, },
onSelectSpec(spec){
this.$emit('input', spec.id)
}, },
onAnyAmount(){
this.$emit('input', 'is_customized')
}
}
}; };
</script> </script>
<style lang="scss"> <style lang="scss">
.spec-group{ .spec-group {
padding: .2rem .4rem; padding: 0.2rem 0.4rem;
max-height: 50vh; max-height: 50vh;
overflow: scroll; overflow: scroll;
li{ li {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 0 .4rem; padding: 0 0.4rem;
font-size: .4rem; font-size: 0.4rem;
height: 1rem; height: 1rem;
& ~ li{ & ~ li {
margin-top: .3rem; margin-top: 0.3rem;
} }
} }
li.active{ li.active {
border-color: $primary-color; border-color: #cf9e3b;
color: $primary-color; color: #cf9e3b;
} }
} }
</style> </style>
+90 -21
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">
@@ -32,15 +32,21 @@
<li :class="[lTypeId === lType.id && 'active']" v-for="lType in listTypes" :key="lType.id" @click="getPayRecords(lType.id, 1)">{{ lType.name }}</li> <li :class="[lTypeId === lType.id && 'active']" v-for="lType in listTypes" :key="lType.id" @click="getPayRecords(lType.id, 1)">{{ lType.name }}</li>
</ul> </ul>
</div> </div>
<div> <div class="paied_list">
<user-merit v-for="pay in payList" :key="pay.id" :data="pay"></user-merit> <user-merit v-for="pay in payList" :key="pay.id" :data="pay"></user-merit>
<div ref="target" class="observer-target">
<div class="read-more" v-if="noMore && page > 1">没有更多了</div> <div class="read-more" v-if="noMore && page > 1">没有更多了</div>
<div class="read-more" v-if="noMore && page === 1">暂无数据</div> <div class="read-more" v-if="noMore && page === 1">暂无数据</div>
<div class="read-more" v-else @click="loadMoreFn">查看更多</div> <div class="read-more" v-if="!noMore" @click="loadMoreFn">查看更多</div>
</div> </div>
</div> </div>
</div>
<div class="safe-inset-placeholder"></div>
<fixed-bottom ref="fixedBottom"> <fixed-bottom ref="fixedBottom">
<div class="customer-absolute">
<customer-service></customer-service>
</div>
<button class="iconfont icon-home" v-if="query.no_login === '1'" @click="backHome"></button> <button class="iconfont icon-home" v-if="query.no_login === '1'" @click="backHome"></button>
<button class="merit-button" @click="onHasLoginToNext">{{ data.pay_name }}</button> <button class="merit-button" @click="onHasLoginToNext">{{ data.pay_name }}</button>
</fixed-bottom> </fixed-bottom>
@@ -77,20 +83,21 @@
<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";
import ObserverInteraction from "@/util/ObserverInteraction";
import CustomerService from "@/components/customer-service/index.vue";
export default { export default {
components: { components: {
swiper,
swiperSlide,
SelectSpec, SelectSpec,
CustomerService,
FillInformation, FillInformation,
}, },
data() { data() {
return { return {
observer: null,
result: "a", result: "a",
showAnyAmount: false, showAnyAmount: false,
paddingBottom: 0, paddingBottom: 0,
@@ -107,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: () => {},
}, },
@@ -136,17 +143,47 @@ 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;
} }
return (parseInt(this.priceUnit * 100, 10) * this.quantity) / 100; return (parseInt(this.priceUnit * 100, 10) * this.quantity) / 100;
}, },
safeInsetBottomHeight() {
return this.$store.state.safeInsetBottomHeight;
},
}, },
mounted() { mounted() {
this.getGoodsDetail("common"); this.getGoodsDetail("common");
}, },
beforeDestroy() {
this.observer.disconnect();
},
methods: { methods: {
checkPlaceholderHeight() {
const el = document.querySelector(".safe-inset-placeholder");
const rect = el.getBoundingClientRect();
if (rect.height > 0) {
el.parentNode.removeChild(el);
} else {
el.style.height = "1rem";
}
},
initObserver() {
this.observer = new ObserverInteraction();
// 3. 监听元素可见性
this.observer.observeVisibility(
this.$refs.target,
() => {
this.loadMoreFn();
},
{ threshold: 0.5 }
);
},
backHome() { backHome() {
const { query } = this.$router.currentRoute; const { query } = this.$router.currentRoute;
const name = query.temple_id === "1" ? "home" : "temple-home"; const name = query.temple_id === "1" ? "home" : "temple-home";
@@ -217,6 +254,8 @@ export default {
await this.getPayRecords(this.lTypeId, 1); await this.getPayRecords(this.lTypeId, 1);
this.$nextTick(() => { this.$nextTick(() => {
this.paddingBottom = this.$refs.fixedBottom.getOffsetHeight() - 50; this.paddingBottom = this.$refs.fixedBottom.getOffsetHeight() - 50;
this.initObserver();
this.checkPlaceholderHeight();
}); });
this.wechatReady({ this.wechatReady({
...this.data.shareConfig, ...this.data.shareConfig,
@@ -226,6 +265,7 @@ export default {
// 获取更多感恩功德1 // 获取更多感恩功德1
loadMoreFn() { loadMoreFn() {
this.page += 1; this.page += 1;
if (this.noMore) return;
this.getPayRecords(this.lTypeId, this.page); this.getPayRecords(this.lTypeId, this.page);
}, },
// 获取感恩功德 // 获取感恩功德
@@ -246,12 +286,24 @@ export default {
<style lang="scss"> <style lang="scss">
$lightWidth: 1.3rem; $lightWidth: 1.3rem;
.goods-detail { .goods-detail {
.safe-inset-placeholder {
padding-bottom: env(safe-area-inset-bottom);
padding-bottom: constant(safe-area-inset-bottom);
}
.goods-content { .goods-content {
padding-left: 0.3rem; padding-left: 0.3rem;
padding-right: 0.3rem; padding-right: 0.3rem;
* { * {
max-width: 100%; width: 100%;
font-size: 0.35rem; font-size: 0.35rem;
word-wrap: break-word;
white-space: wrap !important;
}
img {
width: 100%;
}
p {
text-align: justify;
} }
} }
.light-container { .light-container {
@@ -288,7 +340,7 @@ $lightWidth: 1.3rem;
background: #bbb; background: #bbb;
} }
.van-swipe__indicator--active { .van-swipe__indicator--active {
background: $primary-color; background: #cf9e3b;
} }
} }
} }
@@ -339,13 +391,24 @@ $lightWidth: 1.3rem;
} }
} }
} }
.paied_list {
flex: 1 1;
}
} }
.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 {
@@ -419,7 +482,7 @@ $lightWidth: 1.3rem;
} }
.merit-button { .merit-button {
display: block; display: block;
background: $primary-color; background: #cf9e3b;
color: white; color: white;
height: 1.2rem; height: 1.2rem;
font-size: 0.37rem; font-size: 0.37rem;
@@ -428,7 +491,7 @@ $lightWidth: 1.3rem;
margin-top: 0.3rem; margin-top: 0.3rem;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
border: 0.01rem solid $primary-color; border: 0.01rem solid #cf9e3b;
border-radius: 0.13rem; border-radius: 0.13rem;
margin-bottom: 0.3rem; margin-bottom: 0.3rem;
} }
@@ -455,7 +518,7 @@ $lightWidth: 1.3rem;
} }
} }
li.current { li.current {
color: $primary-color; color: #cf9e3b;
} }
} }
} }
@@ -492,7 +555,7 @@ $lightWidth: 1.3rem;
.total { .total {
font-size: 0.4rem; font-size: 0.4rem;
em { em {
color: $primary-color; color: #cf9e3b;
font-size: 0.4rem; font-size: 0.4rem;
font-weight: bold; font-weight: bold;
} }
@@ -500,12 +563,18 @@ $lightWidth: 1.3rem;
.next { .next {
font-size: 0.4rem; font-size: 0.4rem;
padding: 0.3rem 1rem; padding: 0.3rem 1rem;
background: $primary-color; background: #cf9e3b;
border: 1px solid $primary-color; border: 1px solid #cf9e3b;
color: white; color: white;
border-radius: 0.1rem; border-radius: 0.1rem;
} }
} }
} }
.customer-absolute {
position: absolute;
right: 0.3rem;
top: 0.28rem;
}
} }
</style> </style>
@@ -116,9 +116,9 @@ export default {
} }
.btn { .btn {
padding: 0.2rem 0.6rem; padding: 0.2rem 0.6rem;
background: $primary-color; background: #cf9e3b;
color: white; color: white;
border: 1px solid $primary-color; border: 1px solid #cf9e3b;
font-size: 0.4rem; font-size: 0.4rem;
border-radius: 0.11rem; border-radius: 0.11rem;
margin-left: 0.3rem; margin-left: 0.3rem;
@@ -176,7 +176,7 @@ export default {
margin-bottom: 0.3rem; margin-bottom: 0.3rem;
.update { .update {
font-size: 0.35rem; font-size: 0.35rem;
color: $primary-color; color: #cf9e3b;
} }
} }
.name-group { .name-group {
@@ -186,9 +186,9 @@ export default {
} }
} }
.confirm { .confirm {
background: $primary-color; background: #cf9e3b;
color: white; color: white;
border: 1px solid $primary-color; border: 1px solid #cf9e3b;
width: 3rem; width: 3rem;
padding: 0.3rem 0; padding: 0.3rem 0;
border-radius: 0.07rem; border-radius: 0.07rem;
@@ -2,11 +2,11 @@
<span> <span>
<ul class="spec-group"> <ul class="spec-group">
<li class="border-circle" :class="[value === 'is_customized' && 'active']" @click="onAnyAmount"> <li class="border-circle" :class="[value === 'is_customized' && 'active']" @click="onAnyAmount">
<span>{{data.rule_btn}}</span> <span>{{ data.rule_btn }}</span>
</li> </li>
<li class="border-circle" v-for="spec in data.spec" :key="spec.id" :class="[ value === spec.id && 'active']" @click="onSelectSpec(spec)"> <li class="border-circle" v-for="spec in data.spec" :key="spec.id" :class="[value === spec.id && 'active']" @click="onSelectSpec(spec)">
<span>{{spec.spec_name}}</span> <span>{{ spec.spec_name }}</span>
<span>¥ {{spec.price}}</span> <span>¥ {{ spec.price }}</span>
</li> </li>
</ul> </ul>
@@ -14,7 +14,7 @@
<div class="donate"> <div class="donate">
<span class="label">数量</span> <span class="label">数量</span>
<span class="time-cycle"> <span class="time-cycle">
<van-stepper v-model="num" step="1" @change="onChangeNumber"/> <van-stepper v-model="num" step="1" @change="onChangeNumber" />
</span> </span>
</div> </div>
</div> </div>
@@ -22,65 +22,63 @@
</template> </template>
<script> <script>
export default { export default {
props: { props: {
value: { value: {
type: [String, Number] type: [String, Number],
}, },
data: { data: {
type: Object, type: Object,
}, },
number: Number, number: Number,
}, },
data(){ data() {
return { return {
num: 0, num: 0,
is_customized: false, is_customized: false,
} };
}, },
watch: { watch: {
number: { number: {
handler(val) { handler(val) {
this.num = val; this.num = val;
} },
} },
}, },
methods: { methods: {
onChangeNumber(value){ onChangeNumber(value) {
this.$emit('update:number', value) this.$emit("update:number", value);
},
onSelectSpec(spec) {
this.$emit("input", spec.id);
},
onAnyAmount() {
this.$emit("input", "is_customized");
}, },
onSelectSpec(spec){
this.$emit('input', spec.id)
}, },
onAnyAmount(){
this.$emit('input', 'is_customized')
}
}
}; };
</script> </script>
<style lang="scss"> <style lang="scss">
.spec-group{ .spec-group {
padding: .2rem .4rem; padding: 0.2rem 0.4rem;
max-height: 50vh; max-height: 50vh;
overflow: scroll; overflow: scroll;
li{ li {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 0 .4rem; padding: 0 0.4rem;
font-size: .4rem; font-size: 0.4rem;
height: 1rem; height: 1rem;
& ~ li{ & ~ li {
margin-top: .3rem; margin-top: 0.3rem;
} }
} }
li.active{ li.active {
border-color: $primary-color; border-color: #cf9e3b;
color: $primary-color; color: #cf9e3b;
} }
} }
</style> </style>
+9 -9
View File
@@ -304,10 +304,10 @@ $lightWidth: 1.15rem;
padding-right: 0; padding-right: 0;
} }
.current-light { .current-light {
border: 1px solid $primary-color; border: 1px solid #cf9e3b;
border-radius: 4px; border-radius: 4px;
span { span {
color: $primary-color; color: #cf9e3b;
} }
} }
img.light-icon { img.light-icon {
@@ -336,7 +336,7 @@ $lightWidth: 1.15rem;
background: #bbb; background: #bbb;
} }
.van-swipe__indicator--active { .van-swipe__indicator--active {
background: $primary-color; background: #cf9e3b;
} }
} }
} }
@@ -480,7 +480,7 @@ $lightWidth: 1.15rem;
} }
.merit-button { .merit-button {
display: block; display: block;
background: $primary-color; background: #cf9e3b;
color: white; color: white;
height: 1.2rem; height: 1.2rem;
font-size: 0.37rem; font-size: 0.37rem;
@@ -489,7 +489,7 @@ $lightWidth: 1.15rem;
margin-top: 0.3rem; margin-top: 0.3rem;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
border: 0.01rem solid $primary-color; border: 0.01rem solid #cf9e3b;
border-radius: 0.13rem; border-radius: 0.13rem;
margin-bottom: 0.3rem; margin-bottom: 0.3rem;
} }
@@ -516,7 +516,7 @@ $lightWidth: 1.15rem;
} }
} }
li.current { li.current {
color: $primary-color; color: #cf9e3b;
} }
} }
} }
@@ -553,7 +553,7 @@ $lightWidth: 1.15rem;
.total { .total {
font-size: 0.4rem; font-size: 0.4rem;
em { em {
color: $primary-color; color: #cf9e3b;
font-size: 0.4rem; font-size: 0.4rem;
font-weight: bold; font-weight: bold;
} }
@@ -561,8 +561,8 @@ $lightWidth: 1.15rem;
.next { .next {
font-size: 0.4rem; font-size: 0.4rem;
padding: 0.3rem 1rem; padding: 0.3rem 1rem;
background: $primary-color; background: #cf9e3b;
border: 1px solid $primary-color; border: 1px solid #cf9e3b;
color: white; color: white;
border-radius: 0.1rem; border-radius: 0.1rem;
} }
+32 -28
View File
@@ -46,19 +46,19 @@
<div class="divider"></div> <div class="divider"></div>
<div class="panel" v-if="data.dynamic_data.length > 0"> <div class="panel" v-if="data.dynamic_data.length > 0">
<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>
</div> </div>
<div class="panel-body goods-panel-body"> <div class="panel-body goods-panel-body">
<buddha-process v-for="process in data.dynamic_data" :key="process.id" :data="process"></buddha-process> <buddha-process v-for="process in data.dynamic_data" :key="process.id" :data="process"></buddha-process>
<div class="process-more" @click="onMoreProcess"> <div class="process-more" @click="onMoreProcess">
<span>查看更多进展状态</span> <span>查看更多法会</span>
<i class="iconfont icon-arrow-right"></i> <i class="iconfont icon-arrow-right"></i>
</div> </div>
</div> </div>
<div class="divider"></div> <div class="divider"></div>
<thanks-giving :temple-id="query.temple_id" :agent-id="query.agent_id"></thanks-giving>
</div> </div>
<thanks-giving :temple-id="query.temple_id" :agent-id="query.agent_id"></thanks-giving>
</div> </div>
</template> </template>
@@ -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);
@@ -259,53 +267,49 @@ export default {
border-radius: 10px; border-radius: 10px;
} }
.van-swipe__indicator--active { .van-swipe__indicator--active {
background: $primary-color; background: #cf9e3b;
} }
} }
.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 { .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;
} }
}
} }
</style> </style>
+16 -11
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="merit-box" :style="{ height: root.minHeight + 'px' }"> <div class="merit-box">
<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 class="merit-container"> <div class="merit-container">
<img class="goods-picture" :style="{ width: width + 'px', height: width / 2 + 'px' }" :src="info.merit_box_cover" alt="" /> <img class="goods-picture" :style="{ width: width + 'px', height: width / 2 + 'px' }" :src="info.merit_box_cover" alt="" />
@@ -28,11 +28,11 @@
</scroll-view> </scroll-view>
</div> </div>
</div> </div>
</div>
<div class="merit-button-group" :style="{ bottom: tabHeight + 'px' }"> <div class="merit-button-group" :style="{ bottom: tabHeight + 'px' }">
<button class="iconfont icon-arrow-left" @click="back"></button> <button class="iconfont icon-arrow-left" @click="back"></button>
<button class="merit-button" @click="openBox">随喜功德</button> <button class="merit-button" @click="openBox">随喜功德</button>
</div> </div>
</div>
<random-money :value.sync="randVisible" @change="onRandNext"></random-money> <random-money :value.sync="randVisible" @change="onRandNext"></random-money>
</div> </div>
</template> </template>
@@ -154,26 +154,31 @@ export default {
<style lang="scss"> <style lang="scss">
.merit-box { .merit-box {
position: relative; position: relative;
height: 100%; height: 100vh;
display: flex;
flex-direction: column;
.goods-picture { .goods-picture {
vertical-align: top; vertical-align: top;
position: fixed;
left: 0; left: 0;
top: 0; top: 0;
right: 0; right: 0;
} }
.merit-container { .merit-container {
height: 100%; flex: 1 1;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
display: flex;
flex-direction: column;
} }
.merit-rank-container { .merit-rank-container {
background: white; background: white;
position: relative; position: relative;
border-top-left-radius: 10px; border-top-left-radius: 10px;
border-top-right-radius: 10px; border-top-right-radius: 10px;
margin-top: 5rem; flex: 1 1;
height: 61vh; display: flex;
flex-direction: column;
overflow: hidden;
.head { .head {
padding: 0.53rem 0.4rem; padding: 0.53rem 0.4rem;
padding-bottom: 0.13rem; padding-bottom: 0.13rem;
@@ -237,20 +242,20 @@ export default {
.merit-button { .merit-button {
//display: inline-block; //display: inline-block;
//vertical-align: top; //vertical-align: top;
//background: $primary-color; //background: #CF9E3B;;
//color: white; //color: white;
//height: 1.4rem; //height: 1.4rem;
//font-size: .37rem; //font-size: .37rem;
//padding: 0 2rem; //padding: 0 2rem;
//border: .01rem solid $primary-color; //border: .01rem solid #CF9E3B;;
//border-radius: $btn-border-radius; //border-radius: $btn-border-radius;
//flex: 1; //flex: 1;
flex: 1; flex: 1;
font-size: 0.4rem; font-size: 0.4rem;
padding: 0.3rem 1rem; padding: 0.3rem 1rem;
background: $primary-color; background: #cf9e3b;
border: 1px solid $primary-color; border: 1px solid #cf9e3b;
color: white; color: white;
border-radius: 0.1rem; border-radius: 0.1rem;
} }
-130
View File
@@ -1,130 +0,0 @@
<template>
<div>
<!--mescroll滚动区域的基本结构-->
<mescroll-vue ref="mescroll" :down="mescrollDown" :up="mescrollUp" @init="mescrollInit">
<!--内容...-->
<div class="div" v-for="(v, i) in dataList" :key="i">{{ v }}</div>
</mescroll-vue>
</div>
</template>
<script>
// 引入mescroll的vue组件
import MescrollVue from "mescroll.js/mescroll.vue";
const axios = {
current: 0,
get() {
return new Promise((resolve) => {
this.current += 1;
setTimeout(() => {
if (this.current === 3) {
resolve({
data: [],
});
return;
}
resolve({
data: Array.from(Array(10), () => Math.random() * 100),
});
}, Math.random() * 1000);
});
},
};
export default {
components: {
MescrollVue, // 注册mescroll组件
},
data() {
return {
data: [],
mescroll: null, // mescroll实例对象
mescrollDown: {}, //下拉刷新的配置. (如果下拉刷新和上拉加载处理的逻辑是一样的,则mescrollDown可不用写了)
mescrollUp: {
// 上拉加载的配置.
callback: this.upCallback, // 上拉回调,此处简写; 相当于 callback: function(page, mescroll) { }
//以下是一些常用的配置,当然不写也可以的.
page: {
num: 0, //当前页 默认0,回调之前会加1; 即callback(page)会从1开始
size: 10, //每页数据条数,默认10
},
htmlNodata: '<p class="upwarp-nodata">-- END --</p>',
noMoreSize: 5, //如果列表已无数据,可设置列表的总数量要大于5才显示无更多数据; 避免列表数据过少(比如只有一条数据),显示无更多数据会不好看这就是为什么无更多数据有时候不显示的原因
toTop: {
//回到顶部按钮
src: "./static/mescroll/mescroll-totop.png", //图片路径,默认null,支持网络图
offset: 1000, //列表滚动1000px才显示回到顶部按钮
},
empty: {
//列表第一页无任何数据时,显示的空提示布局; 需配置warpId才显示
warpId: "xxid", //父布局的id (1.3.5版本支持传入dom元素)
icon: "./static/mescroll/mescroll-empty.png", //图标,默认null,支持网络图
tip: "暂无相关数据~", //提示
},
},
dataList: [], // 列表数据
};
},
beforeRouteEnter(to, from, next) {
// 如果没有配置顶部按钮或isBounce,则beforeRouteEnter不用写
next((vm) => {
// 滚动到原来的列表位置,恢复顶部按钮和isBounce的配置
vm.$refs.mescroll && vm.$refs.mescroll.beforeRouteEnter();
});
},
beforeRouteLeave(to, from, next) {
// 如果没有配置顶部按钮或isBounce,则beforeRouteLeave不用写
// 记录列表滚动的位置,隐藏顶部按钮和isBounce的配置
this.$refs.mescroll && this.$refs.mescroll.beforeRouteLeave();
next();
},
methods: {
// mescroll组件初始化的回调,可获取到mescroll对象
mescrollInit(mescroll) {
this.mescroll = mescroll; // 如果this.mescroll对象没有使用到,则mescrollInit可以不用配置
},
// 上拉回调 page = {num:1, size:10}; num:当前页 ,默认从1开始; size:每页数据条数,默认10
upCallback(page, mescroll) {
// 联网请求
axios
.get({
params: {
num: page.num, // 页码
size: page.size, // 每页长度
},
})
.then((response) => {
// 请求的列表数据
let arr = response.data;
// 如果是第一页需手动置空列表
if (page.num === 1) this.dataList = [];
// 把请求到的数据添加到列表
this.dataList = this.dataList.concat(arr);
// 数据渲染成功后,隐藏下拉刷新的状态
this.$nextTick(() => {
mescroll.endSuccess(arr.length);
});
})
.catch(() => {
// 联网失败的回调,隐藏下拉刷新和上拉加载的状态;
mescroll.endErr();
});
},
},
};
</script>
<style scoped>
/*通过fixed固定mescroll的高度*/
.mescroll {
position: fixed;
top: 0;
bottom: 0;
height: auto;
}
.div {
height: 40px;
background: red;
border: 10px solid blue;
margin-bottom: 10px;
}
</style>
+68 -68
View File
@@ -1,32 +1,32 @@
<template> <template>
<div class="monk-detail" v-if="data"> <div class="monk-detail" v-if="data">
<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>
<swiper class="swiper-container" :options="swiperOption"> <swiper class="swiper-container" :options="swiperOption">
<swiper-slide v-for="(cover, index) in data.pictures" :key="index"> <swiper-slide v-for="(cover, index) in data.pictures" :key="index">
<div style="height: 100vw;" class="picture"> <div style="height: 100vw" class="picture">
<img :src="cover" alt=""> <img :src="cover" alt="" />
</div> </div>
</swiper-slide> </swiper-slide>
</swiper> </swiper>
<div class="monk-profile"> <div class="monk-profile">
<h1 class="position">{{data.title}}</h1> <h1 class="position">{{ data.title }}</h1>
<p class="introduction" v-html="data.description"></p> <p class="introduction" v-html="data.description"></p>
</div> </div>
<!-- <div class="support">--> <!-- <div class="support">-->
<!-- <div class="support-head">--> <!-- <div class="support-head">-->
<!-- <span class="label">供养者</span>--> <!-- <span class="label">供养者</span>-->
<!-- <ul class="external">--> <!-- <ul class="external">-->
<!-- <li class="active">实时</li>--> <!-- <li class="active">实时</li>-->
<!-- <li>月榜</li>--> <!-- <li>月榜</li>-->
<!-- <li>总榜</li>--> <!-- <li>总榜</li>-->
<!-- </ul>--> <!-- </ul>-->
<!-- </div>--> <!-- </div>-->
<!-- <div>--> <!-- <div>-->
<!-- </div>--> <!-- </div>-->
<!-- </div>--> <!-- </div>-->
<div class="merit-button-group"> <div class="merit-button-group">
<button class="merit-button" @click="onProvide">供养</button> <button class="merit-button" @click="onProvide">供养</button>
</div> </div>
@@ -34,98 +34,98 @@
</template> </template>
<script> <script>
import { getMasterDetail } from '@/api' import { getMasterDetail } from "@/api";
import 'swiper/css/swiper.css' import "swiper/css/swiper.css";
import { swiper, swiperSlide } from 'vue-awesome-swiper' import { swiper, swiperSlide } from "vue-awesome-swiper";
export default { export default {
components: { components: {
swiper, swiperSlide swiper,
swiperSlide,
}, },
data(){ data() {
return { return {
query: this.$route.query, query: this.$route.query,
banners: [ '/1.jpg', '/2.jpg', '/3.jpg' ], banners: ["/1.jpg", "/2.jpg", "/3.jpg"],
data: null, data: null,
swiperOption: { swiperOption: {
autoplay: 8000, autoplay: 8000,
initialSlide: 1, initialSlide: 1,
loop: true, loop: true,
pagination: '.swiper-pagination', pagination: ".swiper-pagination",
onSlideChangeEnd: () => { onSlideChangeEnd: () => {},
}
}
}
}, },
mounted(){ };
},
mounted() {
this.getMasterDetail(); this.getMasterDetail();
}, },
methods: { methods: {
onProvide(){ onProvide() {
const { goods_type, goods_id, temple_id, spec_id } = this.data; const { goods_type, goods_id, temple_id, spec_id } = this.data;
this.onPushToGoodsDetail(goods_type, goods_id, temple_id, spec_id) this.onPushToGoodsDetail(goods_type, goods_id, temple_id, spec_id);
}, },
async getMasterDetail(){ async getMasterDetail() {
const res = await getMasterDetail(this.query.master_id) const res = await getMasterDetail(this.query.master_id);
this.data = res; this.data = res;
} },
} },
} };
</script> </script>
<style lang="scss"> <style lang="scss">
.swiper-container{ .swiper-container {
background: #f5f5f5; background: #f5f5f5;
.picture, img{ .picture,
img {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
} }
.support{ .support {
.support-head{ .support-head {
padding: 0 .4rem; padding: 0 0.4rem;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
height: 1.07rem; height: 1.07rem;
line-height: 1.07rem; line-height: 1.07rem;
.label{ .label {
font-size: .4rem; font-size: 0.4rem;
font-weight: bold; font-weight: bold;
} }
.external{ .external {
display: flex; display: flex;
align-items: center; align-items: center;
li{ li {
margin-left: .3rem; margin-left: 0.3rem;
font-size: .35rem; font-size: 0.35rem;
color: #666; color: #666;
} }
li.active{ li.active {
color: #333; color: #333;
font-weight: bold; font-weight: bold;
} }
} }
} }
} }
.monk-detail{ .monk-detail {
.monk-profile{ .monk-profile {
padding: .4rem; padding: 0.4rem;
margin-bottom: .53rem; margin-bottom: 0.53rem;
.position{ .position {
font-size: .5rem; font-size: 0.5rem;
padding-top: .2rem; padding-top: 0.2rem;
color: #19282E; color: #19282e;
} }
.introduction{ .introduction {
font-size: .37rem; font-size: 0.37rem;
margin-top: .4rem; margin-top: 0.4rem;
line-height: 1.3; line-height: 1.3;
text-align: justify; text-align: justify;
color: #666; color: #666;
} }
} }
.merit-button-group{ .merit-button-group {
text-align: center; text-align: center;
position: fixed; position: fixed;
bottom: 0; bottom: 0;
@@ -133,18 +133,18 @@ export default {
left: 0; left: 0;
right: 0; right: 0;
background: white; background: white;
padding: .4rem 0; padding: 0.4rem 0;
border-top: .01rem solid #ddd; border-top: 0.01rem solid #ddd;
.merit-button{ .merit-button {
display: inline-block; display: inline-block;
background: $primary-color; background: #cf9e3b;
color: white; color: white;
height: 1.2rem; height: 1.2rem;
font-size: .37rem; font-size: 0.37rem;
width: 60%; width: 60%;
padding: 0 .53rem; padding: 0 0.53rem;
border: .01rem solid $primary-color; border: 0.01rem solid #cf9e3b;
border-radius: 1.33rem border-radius: 1.33rem;
} }
} }
} }
+104 -5
View File
@@ -14,13 +14,35 @@
<button class="detail" @click="onToOrder">查看详情</button> <button class="detail" @click="onToOrder">查看详情</button>
<button class="again" @click="onPayAgain">再结善缘</button> <button class="again" @click="onPayAgain">再结善缘</button>
</div> </div>
<van-popup v-model="show" round closeable>
<div class="mobile-dialog">
<div class="pic-wrap">
<img class="mobile-picture" src="/thanks.jpeg" alt="" />
</div>
<div class="body">
<div class="info">
<span>登记手机号获取功德反馈</span>
<i>或</i>
<span>添加客堂微信<b>19122065157</b>获取</span>
</div>
<div class="field-wrap">
<van-field v-model="mobile" placeholder="请填写手机号码" maxlength="11" border type="digit"></van-field>
</div>
<van-button type="info" round block @click="saveMobile">确认</van-button>
</div>
</div>
</van-popup>
</div> </div>
</template> </template>
<script> <script>
import { saveMobileNumber, checkUserMobile } from "@/api";
export default { export default {
data() { data() {
return { return {
show: false,
mobile: "",
query: this.$route.query, query: this.$route.query,
}; };
}, },
@@ -29,10 +51,32 @@ export default {
return `https://temple-h5-new.oss-cn-hangzhou.aliyuncs.com//uploads/merit/certificate/${this.query.order_id}.jpg`; return `https://temple-h5-new.oss-cn-hangzhou.aliyuncs.com//uploads/merit/certificate/${this.query.order_id}.jpg`;
}, },
}, },
mounted() {
checkUserMobile().then((hasMobile) => {
if (!hasMobile) {
this.show = true;
}
});
},
methods: { methods: {
onToOder() { onToOrder() {
this.$router.push("/user/order"); this.$router.push("/user/order");
}, },
saveMobile() {
const reg = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/g;
const mobile = this.mobile;
if (!mobile) {
return this.$toast("请输入11位手机号");
}
if (!reg.test(mobile)) {
return this.$toast("请输入合法的手机号");
}
saveMobileNumber(mobile).then(() => {
this.$toast("登记成功");
this.show = false;
});
console.log("mobile", mobile);
},
onPayAgain() { onPayAgain() {
// 功德箱订单再结善缘重新随喜 // 功德箱订单再结善缘重新随喜
if (this.query.from === "meritBox") { if (this.query.from === "meritBox") {
@@ -59,6 +103,61 @@ export default {
<style lang="scss"> <style lang="scss">
.pay-result { .pay-result {
.mobile-dialog {
width: 90vw;
height: 90vh;
background-color: white;
border-radius: 12px;
display: flex;
flex-direction: column;
.pic-wrap {
height: 70%;
overflow: hidden;
.mobile-picture {
width: 100%;
object-fit: fill;
display: block;
}
}
.body {
padding: 12px;
display: flex;
flex-direction: column;
row-gap: 12px;
.info {
font-size: 14px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
row-gap: 8px;
color: #383838;
i {
font-size: 12px;
}
b {
font-weight: bold;
color: #bc1717;
padding: 0 4px;
}
}
.van-button--info {
background-color: #bc1717;
border-color: #bc1717;
}
}
.field-wrap {
border: 1px solid #ddd;
border-radius: 12px;
overflow: hidden;
.van-field__control {
font-size: 16px;
font-weight: bold;
letter-spacing: 2px;
}
}
}
.cert-show { .cert-show {
height: 70vh; height: 70vh;
background: #f5f5f5; background: #f5f5f5;
@@ -105,13 +204,13 @@ export default {
background: white; background: white;
} }
.detail { .detail {
color: $primary-color; color: #cf9e3b;
border-color: $primary-color; border-color: #cf9e3b;
} }
.again { .again {
background: $primary-color; background: #cf9e3b;
color: white; color: white;
border-color: $primary-color; border-color: #cf9e3b;
} }
} }
} }
+51 -51
View File
@@ -1,8 +1,8 @@
<template> <template>
<div class="temple-detail" v-if="data"> <div class="temple-detail" v-if="data">
<img class="banner" :src="data.picture" alt=""> <img class="banner" :src="data.picture" alt="" />
<div class="authed border-bottom"> <div class="authed border-bottom">
<img src="@/assets/img/cert.jpg" alt=""> <img src="@/assets/img/cert.jpg" alt="" />
<span>已通过 <b>自在福田</b> 认证,可放心访问</span> <span>已通过 <b>自在福田</b> 认证,可放心访问</span>
</div> </div>
@@ -11,19 +11,19 @@
<ul class="list"> <ul class="list">
<li> <li>
<span class="label">单位名称:</span> <span class="label">单位名称:</span>
<span class="value">{{data.unit_name}}</span> <span class="value">{{ data.unit_name }}</span>
</li> </li>
<li> <li>
<span class="label">登记编号:</span> <span class="label">登记编号:</span>
<span class="value">{{data.institution_code}}</span> <span class="value">{{ data.institution_code }}</span>
</li> </li>
<li> <li>
<span class="label">负责人:</span> <span class="label">负责人:</span>
<span class="value">{{data.represent}}</span> <span class="value">{{ data.represent }}</span>
</li> </li>
<li> <li>
<span class="label">所在地址:</span> <span class="label">所在地址:</span>
<span class="value">{{data.details_address}}</span> <span class="value">{{ data.details_address }}</span>
</li> </li>
</ul> </ul>
</div> </div>
@@ -32,7 +32,7 @@
<h4 class="title border-bottom">认证授权</h4> <h4 class="title border-bottom">认证授权</h4>
<ul class="cert"> <ul class="cert">
<li v-for="(cert, index) in data.register_cert_url" :key="index"> <li v-for="(cert, index) in data.register_cert_url" :key="index">
<img :src="cert" @click="previewImage(cert, data.register_cert_url)" alt=""> <img :src="cert" @click="previewImage(cert, data.register_cert_url)" alt="" />
</li> </li>
</ul> </ul>
</div> </div>
@@ -45,99 +45,99 @@
</template> </template>
<script> <script>
import { getTempleDetail } from "@/api" import { getTempleDetail } from "@/api";
import { previewImage } from '@/common/wechat-web'; import { previewImage } from "@/common/wechat-web";
export default { export default {
data(){ data() {
return { return {
query: this.$route.query, query: this.$route.query,
data: null, data: null,
} };
}, },
mounted(){ mounted() {
this.getTempleDetail(); this.getTempleDetail();
this.wechatReady() this.wechatReady();
}, },
methods: { methods: {
previewImage(cert, certArr){ previewImage(cert, certArr) {
previewImage(cert, certArr) previewImage(cert, certArr);
}, },
async getTempleDetail(){ async getTempleDetail() {
const res = await getTempleDetail(this.query.temple_id); const res = await getTempleDetail(this.query.temple_id);
this.data = res; this.data = res;
} },
} },
} };
</script> </script>
<style lang="scss"> <style lang="scss">
.temple-detail{ .temple-detail {
padding-bottom: env(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom);
.banner{ .banner {
width: 100%; width: 100%;
} }
.authed{ .authed {
font-size: .35rem; font-size: 0.35rem;
line-height: 1.2rem; line-height: 1.2rem;
padding-left: .4rem; padding-left: 0.4rem;
color: #888; color: #888;
img{ img {
width: .3rem; width: 0.3rem;
vertical-align: middle; vertical-align: middle;
margin-right: .1rem; margin-right: 0.1rem;
} }
span{ span {
vertical-align: middle; vertical-align: middle;
b{ b {
color: $primary-color; color: #cf9e3b;
} }
} }
} }
.auth{ .auth {
margin: .4rem; margin: 0.4rem;
margin-top: .8rem; margin-top: 0.8rem;
.title{ .title {
font-size: .4rem; font-size: 0.4rem;
font-weight: bold; font-weight: bold;
padding-bottom: .3rem; padding-bottom: 0.3rem;
} }
.list{ .list {
margin-top: .2rem; margin-top: 0.2rem;
li{ li {
line-height: .8rem; line-height: 0.8rem;
font-size: .4rem; font-size: 0.4rem;
.label{ .label {
display: inline-block; display: inline-block;
width: 5em; width: 5em;
color: #777; color: #777;
text-align: right; text-align: right;
} }
.value{ .value {
color: #666; color: #666;
} }
} }
} }
.cert{ .cert {
white-space: nowrap; white-space: nowrap;
margin-top: .3rem; margin-top: 0.3rem;
overflow-x: scroll; overflow-x: scroll;
li{ li {
width: 5rem; width: 5rem;
display: inline-block; display: inline-block;
border: 1px solid #ddd; border: 1px solid #ddd;
margin-right: .3rem; margin-right: 0.3rem;
img{ img {
width: 100%; width: 100%;
vertical-align: top; vertical-align: top;
} }
} }
} }
.description{ .description {
font-size: .4rem; font-size: 0.4rem;
color: #888; color: #888;
line-height: 1.7; line-height: 1.7;
padding-top: .35rem; padding-top: 0.35rem;
letter-spacing: 1px; letter-spacing: 1px;
text-align: justify; text-align: justify;
} }
+148 -166
View File
@@ -7,16 +7,16 @@
<span>{{ data.temple_data.visit }}到访</span> <span>{{ data.temple_data.visit }}到访</span>
</div> </div>
</div> </div>
<div class="certed-temple" @click="$router.push({name: 'temple-detail', query: { temple_id: query.temple_id}})"> <div class="certed-temple" @click="$router.push({ name: 'temple-detail', query: { temple_id: query.temple_id } })">
<img class="cert-icon" src="@/assets/img/cert.jpg" alt=""> <img class="cert-icon" src="@/assets/img/cert.jpg" alt="" />
<span class="text">认证寺院可放心访问</span> <span class="text">认证寺院可放心访问</span>
<span class="btn">查看</span> <span class="btn">查看</span>
</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>
</van-swipe> </van-swipe>
</div> </div>
@@ -24,7 +24,7 @@
<van-swipe-item v-for="(item, index) in data.icon_data" :key="index"> <van-swipe-item v-for="(item, index) in data.icon_data" :key="index">
<van-grid :border="false"> <van-grid :border="false">
<van-grid-item icon="photo-o" :text="nav.name" v-for="(nav, _index) in item" :key="_index" @click="locationTo(nav)"> <van-grid-item icon="photo-o" :text="nav.name" v-for="(nav, _index) in item" :key="_index" @click="locationTo(nav)">
<img :src="nav.icon_url" class="nav-icon" slot="icon"> <img :src="nav.icon_url" class="nav-icon" slot="icon" />
</van-grid-item> </van-grid-item>
</van-grid> </van-grid>
</van-swipe-item> </van-swipe-item>
@@ -39,9 +39,8 @@
</div> </div>
<div class="divider"></div> <div class="divider"></div>
<div class="temple-manager"> <div class="temple-manager">
<div class="manager" v-for="manager in data.member_data" :key="manager.id" <div class="manager" v-for="manager in data.member_data" :key="manager.id" @click="$router.push({ name: 'monk', query: { master_id: manager.id } })">
@click="$router.push({ name: 'monk', query: { master_id: manager.id }})"> <img class="avatar" :src="manager.avatar_url" alt="" />
<img class="avatar" :src="manager.avatar_url" alt="">
<div class="manager-container"> <div class="manager-container">
<h3 class="name">{{ manager.title }}</h3> <h3 class="name">{{ manager.title }}</h3>
<p class="content"> <p class="content">
@@ -53,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">
@@ -68,53 +67,51 @@
</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>
</div> </div>
<div class="panel-body goods-panel-body"> <div class="panel-body goods-panel-body">
<buddha-process v-for="process in data.dynamic_data" :key="process.id" :data="process"></buddha-process> <buddha-process v-for="process in data.dynamic_data" :key="process.id" :data="process"></buddha-process>
<div class="process-more" @click="onMoreProcess"> <div class="process-more" @click="onMoreProcess">
<span>查看更多进展状态</span> <span>查看更多活动进展</span>
<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>
</div> </div>
<van-popup v-model="showUserMenu" position="left" style="width: 80%; height: 100%"> <van-popup v-model="showUserMenu" position="left" style="width: 80%; height: 100%">
<div class="user-menu" v-if="user"> <div class="user-menu" v-if="user">
<div class="user"> <div class="user">
<img class="avatar" :src="user.avatar" alt=""> <img class="avatar" :src="user.avatar" alt="" />
<div class="profile"> <div class="profile">
<h5 class="name">{{user.nickname}}</h5> <h5 class="name">{{ user.nickname }}</h5>
<p class="account">用户号: {{user.account_no}}</p> <p class="account">用户号: {{ user.account_no }}</p>
</div> </div>
</div> </div>
<ul class="user-list"> <ul class="user-list">
<li @click="onPushForRouteName('user-order')"> <li @click="onPushForRouteName('user-order')">
<img src="@/assets/img/user-popup/我的善缘.png" alt=""> <img src="@/assets/img/user-popup/我的善缘.png" alt="" />
<span>我的善缘</span> <span>我的善缘</span>
</li> </li>
<li @click="onPushForRouteName('user-customer')"> <li @click="onPushForRouteName('user-customer')">
<img src="@/assets/img/user-popup/联系客服.png" alt=""> <img src="@/assets/img/user-popup/联系客服.png" alt="" />
<span>联系客服</span> <span>联系客服</span>
</li> </li>
<li @click="onPushForRouteName('merit-box')"> <li @click="onPushForRouteName('merit-box')">
<img src="@/assets/img/user-popup/功德箱.png" alt=""> <img src="@/assets/img/user-popup/功德箱.png" alt="" />
<span>功德箱</span> <span>功德箱</span>
</li> </li>
<li @click="onPushForRouteName('home')"> <li @click="onPushForRouteName('home')">
<img src="@/assets/img/user-popup/查看更多寺院.png" alt=""> <img src="@/assets/img/user-popup/查看更多寺院.png" alt="" />
<span>自在福田首页</span> <span>自在福田首页</span>
</li> </li>
</ul> </ul>
@@ -124,13 +121,13 @@
</p> </p>
</van-popup> </van-popup>
<!-- 功德箱--> <!-- 功德箱-->
<img src="@/assets/img/gongdexiang.png" class="gongdexiang" @click="openBox"/> <img src="@/assets/img/gongdexiang.png" class="gongdexiang" @click="openBox" />
</div> </div>
</template> </template>
<script> <script>
import { getTempleIndex, getUserData } from '@/api'; import { getTempleIndex, getUserData } from "@/api";
export default { export default {
data() { data() {
@@ -146,95 +143,94 @@ export default {
this.getUserData(); this.getUserData();
}, },
methods: { methods: {
openBox(){ openBox() {
this.$router.push({ this.$router.push({
name: 'merit-box', name: "merit-box",
query: { temple_id : this.query.temple_id, open_box: 1, fromPathName: this.$route.name } query: { temple_id: this.query.temple_id, open_box: 1, fromPathName: this.$route.name },
}) });
}, },
locationTo(nav) { locationTo(nav) {
// nav.type: 0外部链接,1日行一善商品,2添砖加瓦类商品,3通用商品,4功德箱,5进展动态 // nav.type: 0外部链接,1日行一善商品,2添砖加瓦类商品,3通用商品,4功德箱,5进展动态
if(nav.icon_type === 6){ if (nav.icon_type === 6) {
this.$router.push({ this.$router.push({
name: 'goods-light-detail', name: "goods-light-detail",
query: { query: {
goods_type: nav.goods_type, goods_type: nav.goods_type,
temple_id: nav.temple_id, temple_id: nav.temple_id,
goods_id: nav.goods_id, goods_id: nav.goods_id,
} },
}) });
return return;
} }
if(nav.icon_type === 0){ if (nav.icon_type === 0) {
window.location.href = nav.url; window.location.href = nav.url;
return return;
} }
if(nav.icon_type === 5){ if (nav.icon_type === 5) {
this.$router.push({ this.$router.push({
name: 'buddha-detail', name: "buddha-detail",
query: { id: nav.dynamic_id } query: { id: nav.dynamic_id },
}) });
return return;
} }
if(nav.icon_type === 4){ if (nav.icon_type === 4) {
this.$router.push({ this.$router.push({
name: 'merit-box' name: "merit-box",
}) });
return return;
} }
if(nav.icon_type === 3){ if (nav.icon_type === 3) {
this.$router.push({ this.$router.push({
name: 'goods-detail', name: "goods-detail",
query: { query: {
goods_type: nav.goods_type, goods_type: nav.goods_type,
goods_id: nav.goods_id , goods_id: nav.goods_id,
temple_id: nav.temple_id, temple_id: nav.temple_id,
} },
}) });
} }
if(nav.icon_type === 1 || nav.icon_type === 2){ if (nav.icon_type === 1 || nav.icon_type === 2) {
this.$router.push({ this.$router.push({
name: 'everyday-donation', name: "everyday-donation",
query: { query: {
goods_type: nav.goods_type, goods_type: nav.goods_type,
goods_id: nav.goods_id , goods_id: nav.goods_id,
temple_id: nav.temple_id, temple_id: nav.temple_id,
}, },
}); });
} }
}, },
onPushForRouteName(routeName){ onPushForRouteName(routeName) {
if(routeName === 'merit-box'){ if (routeName === "merit-box") {
return this.openBox(); return this.openBox();
} }
if(routeName === 'temple-list'){ if (routeName === "temple-list") {
return this.$router.push({ name: routeName, query: { hideTab: '1'}}) return this.$router.push({ name: routeName, query: { hideTab: "1" } });
} }
this.$router.push({ name: routeName }) this.$router.push({ name: routeName });
}, },
async getUserData(){ async getUserData() {
const res = await getUserData(); const res = await getUserData();
this.user = res; this.user = res;
}, },
onMoreProcess() { onMoreProcess() {
this.$router.push({ this.$router.push({
name: 'buddha-activity', name: "buddha-activity",
query: this.query query: this.query,
}); });
}, },
onToGoods(goods) { onToGoods(goods) {
this.$router.push({ this.$router.push({
name: 'goods-detail', name: "goods-detail",
query: { query: {
goods_id: goods.goods_id, goods_id: goods.goods_id,
temple_id: goods.temple_id temple_id: goods.temple_id,
} },
}); });
}, },
async getTempleIndex() { async getTempleIndex() {
@@ -243,14 +239,14 @@ export default {
this.data.icon_data = this.sliceNav(res.icon_data); this.data.icon_data = this.sliceNav(res.icon_data);
setTimeout(() => { setTimeout(() => {
document.title = res.temple_data.unit_name; document.title = res.temple_data.unit_name;
}, 30) }, 30);
this.wechatReady({ this.wechatReady({
...res.shareConfig, ...res.shareConfig,
link: location.href, link: location.href,
}) });
}, },
onTempleStation(){ onTempleStation() {
this.$router.push({ name: 'user-temple-station'}) this.$router.push({ name: "user-temple-station" });
}, },
sliceNav(navData) { sliceNav(navData) {
const nav = []; const nav = [];
@@ -263,7 +259,7 @@ export default {
return nav; return nav;
}, },
} },
}; };
</script> </script>
@@ -271,9 +267,9 @@ export default {
.van-nav-bar__title { .van-nav-bar__title {
color: white; color: white;
} }
.temple-home-page{ .temple-home-page {
padding-bottom: 2rem; padding-bottom: 2rem;
.gongdexiang{ .gongdexiang {
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;
@@ -282,20 +278,17 @@ export default {
margin-left: auto; margin-left: auto;
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 {
font-size: .4rem; font-size: 0.4rem;
background: $primary-color; background: #cf9e3b;
color: white; color: white;
border: 1px solid $primary-color; border: 1px solid #cf9e3b;
padding: .3rem .6rem; padding: 0.3rem 0.6rem;
border-radius: 1rem; border-radius: 1rem;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
@@ -327,7 +320,7 @@ export default {
text-align: right; text-align: right;
.iconfont { .iconfont {
font-size: .8rem; font-size: 0.8rem;
} }
} }
} }
@@ -343,19 +336,19 @@ export default {
width: 1.33rem; width: 1.33rem;
height: 1.33rem; height: 1.33rem;
border-radius: 1.33rem; border-radius: 1.33rem;
margin-right: .4rem; margin-right: 0.4rem;
} }
.profile { .profile {
.name { .name {
font-size: .4rem; font-size: 0.4rem;
color: #666; color: #666;
} }
.account { .account {
margin-top: .2rem; margin-top: 0.2rem;
color: #666; color: #666;
font-size: .3rem; font-size: 0.3rem;
} }
} }
} }
@@ -363,18 +356,18 @@ export default {
.user-list { .user-list {
padding-left: 1rem; padding-left: 1rem;
margin-top: 1rem; margin-top: 1rem;
margin-right: .6rem; margin-right: 0.6rem;
li { li {
height: 1.2rem; height: 1.2rem;
line-height: 1.2rem; line-height: 1.2rem;
font-size: .4rem; font-size: 0.4rem;
display: flex; display: flex;
align-items: center; align-items: center;
img { img {
width: .8rem; width: 0.8rem;
margin-right: .27rem; margin-right: 0.27rem;
} }
& ~ li { & ~ li {
@@ -386,7 +379,7 @@ export default {
.panel-menu-btn { .panel-menu-btn {
position: fixed; position: fixed;
left: .53rem; left: 0.53rem;
bottom: 1.33rem; bottom: 1.33rem;
z-index: 1000; z-index: 1000;
width: 1.33rem; width: 1.33rem;
@@ -395,50 +388,49 @@ export default {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
flex-direction: column; flex-direction: column;
background: $primary-color; background: #cf9e3b;
border: 1px solid $primary-color; border: 1px solid #cf9e3b;
border-radius: 50%; border-radius: 50%;
.iconfont{ .iconfont {
font-size: .5rem; font-size: 0.5rem;
color: white; color: white;
} }
.menu-text { .menu-text {
font-size: .27rem; font-size: 0.27rem;
margin-top: .1rem; margin-top: 0.1rem;
} }
} }
.temple-manager { .temple-manager {
.manager { .manager {
display: flex; display: flex;
margin: .4rem; margin: 0.4rem;
& ~ .manager { & ~ .manager {
border-top: 1px solid #ddd; border-top: 1px solid #ddd;
padding-top: .4rem; padding-top: 0.4rem;
} }
.avatar { .avatar {
width: 1rem; width: 1rem;
height: 1rem; height: 1rem;
border-radius: 1.33rem; border-radius: 1.33rem;
border: .08rem solid #f7e4bf; border: 0.08rem solid #f7e4bf;
vertical-align: top; vertical-align: top;
} }
.manager-container { .manager-container {
flex: 1; flex: 1;
margin-left: .4rem; margin-left: 0.4rem;
.name { .name {
padding: .3rem .3rem .3rem 0; padding: 0.3rem 0.3rem 0.3rem 0;
font-size: .4rem; font-size: 0.4rem;
color: #666; color: #666;
} }
.content { .content {
font-size: .35rem; font-size: 0.35rem;
line-height: 1.5; line-height: 1.5;
display: -webkit-box; display: -webkit-box;
overflow: hidden; overflow: hidden;
@@ -452,18 +444,17 @@ export default {
} }
} }
} }
} }
.merit-rank-container { .merit-rank-container {
.head { .head {
padding: .53rem .4rem; padding: 0.53rem 0.4rem;
padding-bottom: .13rem; padding-bottom: 0.13rem;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
.title { .title {
font-size: .43rem; font-size: 0.43rem;
color: #222222; color: #222222;
} }
@@ -471,12 +462,12 @@ export default {
display: flex; display: flex;
span { span {
font-size: .37rem; font-size: 0.37rem;
color: #999999; color: #999999;
display: inline-block; display: inline-block;
margin-left: .4rem; margin-left: 0.4rem;
border-bottom: .03rem solid transparent; border-bottom: 0.03rem solid transparent;
padding-bottom: .13rem; padding-bottom: 0.13rem;
} }
span.current { span.current {
@@ -503,42 +494,42 @@ export default {
} }
.van-swipe__indicator--active { .van-swipe__indicator--active {
background: $primary-color; background: #cf9e3b;
} }
} }
} }
.certed-temple { .certed-temple {
display: flex; display: flex;
border: 1px solid $primary-color; border: 1px solid #cf9e3b;
border-radius: 4px; border-radius: 4px;
margin: 0 .4rem; margin: 0 0.4rem;
align-items: center; align-items: center;
font-size: .37rem; font-size: 0.37rem;
padding: .3rem; padding: 0.3rem;
margin-bottom: .2rem; margin-bottom: 0.2rem;
.cert-icon { .cert-icon {
width: .3rem; width: 0.3rem;
margin-right: .1rem; margin-right: 0.1rem;
} }
.text { .text {
flex: 1; flex: 1;
font-size: .3rem; font-size: 0.3rem;
color: #888; color: #888;
padding-top: 2px; padding-top: 2px;
} }
.btn { .btn {
color: $primary-color; color: #cf9e3b;
} }
} }
.process-more { .process-more {
line-height: 1.5rem; line-height: 1.5rem;
text-align: center; text-align: center;
font-size: .4rem; font-size: 0.4rem;
.iconfont { .iconfont {
vertical-align: middle; vertical-align: middle;
@@ -546,8 +537,8 @@ export default {
} }
.container { .container {
padding: .4rem; padding: 0.4rem;
padding-bottom: .33rem; padding-bottom: 0.33rem;
.my-swipe .van-swipe-item { .my-swipe .van-swipe-item {
color: #fff; color: #fff;
@@ -558,37 +549,36 @@ export default {
img { img {
width: 100%; width: 100%;
height: 100%; height: 100%;
border-radius: .16rem; border-radius: 0.16rem;
} }
} }
.swiper { .swiper {
margin-bottom: .4rem; margin-bottom: 0.4rem;
} }
.van-notice-bar { .van-notice-bar {
border: 1px solid #E6B759; border: 1px solid #e6b759;
border-radius: .16rem; border-radius: 0.16rem;
} }
} }
.panel { .panel {
.panel-head { .panel-head {
padding: .53rem .4rem; padding: 0.13rem 0.4rem;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
.title { .title {
font-size: .43rem; font-size: 0.43rem;
color: #222222; color: #222222;
} }
} }
.panel-body { .panel-body {
padding: 0 .4rem; padding: 0 0.4rem;
overflow-x: scroll; overflow-x: hidden;
.merit-group { .merit-group {
display: flex; display: flex;
@@ -598,11 +588,11 @@ export default {
} }
.temple-home-activity { .temple-home-activity {
.buddha-process{ .buddha-process {
padding: 0 padding: 0;
} }
.process { .process {
padding: .4rem 0; padding: 0.4rem 0;
.bar { .bar {
padding-bottom: 0; padding-bottom: 0;
@@ -611,56 +601,48 @@ export default {
} }
.merit { .merit {
width: 3.39rem; display: flex;
height: 3.39rem;
display: inline-block;
position: relative; position: relative;
border-radius: .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: .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: .91rem;
background: rgba(0, 0, 0, 0.7);
color: white;
line-height: .91rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
font-size: .37rem; font-size: 0.37rem;
padding: 0 .11rem; padding: 0 0.11rem;
} }
} }
.temple-home-page { .temple-home-page {
.temple-home { .temple-home {
display: flex; display: flex;
font-size: .37rem; font-size: 0.37rem;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: .4rem .3rem; padding: 0.4rem 0.3rem;
.temple-name { .temple-name {
font-size: .45rem; font-size: 0.45rem;
color: #666; color: #666;
} }
.visitor { .visitor {
color: #999; color: #999;
font-size: .3rem; font-size: 0.3rem;
span { span {
padding-left: 10px; padding-left: 10px;
+57 -90
View File
@@ -1,7 +1,7 @@
<template> <template>
<div class="mega-approve"> <div class="mega-approve">
<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>
<template v-if="authing"> <template v-if="authing">
<div class="reviewing"> <div class="reviewing">
@@ -13,12 +13,7 @@
<template v-if="!authing"> <template v-if="!authing">
<van-notice-bar text="真实法师社区,法师身份认证审核通过后才能使用" /> <van-notice-bar text="真实法师社区,法师身份认证审核通过后才能使用" />
<van-form @submit="onSubmit"> <van-form @submit="onSubmit">
<van-field <van-field v-model="form.nickname" label="法号" placeholder="请输入法号全称" :rules="[{ required: true }]" />
v-model="form.nickname"
label="法号"
placeholder="请输入法号全称"
:rules="[{ required: true }]"
/>
<van-field label="称谓" v-model="form.rank_text" :rules="[{ required: true }]" readonly placeholder="请选择称谓" @click="showTitle = true"> <van-field label="称谓" v-model="form.rank_text" :rules="[{ required: true }]" readonly placeholder="请选择称谓" @click="showTitle = true">
<template #right-icon> <template #right-icon>
<span class="iconfont icon-arrow-down-filling"></span> <span class="iconfont icon-arrow-down-filling"></span>
@@ -29,17 +24,8 @@
<span class="iconfont icon-arrow-down-filling"></span> <span class="iconfont icon-arrow-down-filling"></span>
</template> </template>
</van-field> </van-field>
<van-field <van-field v-model="form.place_temple" type="text" label="驻锡寺院" placeholder="名称含所在城市; 如:深圳弘法寺" :rules="[{ required: true }]" />
v-model="form.place_temple" <van-field label="真人头像" placeholder="真人头像">
type="text"
label="驻锡寺院"
placeholder="名称含所在城市; 如:深圳弘法寺"
:rules="[{ required: true }]"
/>
<van-field
label="真人头像"
placeholder="真人头像"
>
<template #input> <template #input>
<div> <div>
<p class="input-small-tip">照片需清晰美观,用于信众展示</p> <p class="input-small-tip">照片需清晰美观,用于信众展示</p>
@@ -47,11 +33,7 @@
</div> </div>
</template> </template>
</van-field> </van-field>
<van-field <van-field type="text" label="戒牒照片" placeholder="戒牒照片">
type="text"
label="戒牒照片"
placeholder="戒牒照片"
>
<template #input> <template #input>
<div> <div>
<p class="input-small-tip">仅用于认证,不公开</p> <p class="input-small-tip">仅用于认证,不公开</p>
@@ -59,76 +41,61 @@
</div> </div>
</template> </template>
</van-field> </van-field>
<van-field <van-field v-model="form.description" type="textarea" label="自我介绍" placeholder="向他人展示自己的文字说明" :rules="[{ required: true }]" maxlength="500" :rows="4" show-word-limit />
v-model="form.description" <div style="margin: 16px">
type="textarea"
label="自我介绍"
placeholder="向他人展示自己的文字说明"
:rules="[{ required: true }]"
maxlength="500"
:rows="4"
show-word-limit
/>
<div style="margin: 16px;">
<van-button round block type="temple" native-type="submit">提交</van-button> <van-button round block type="temple" native-type="submit">提交</van-button>
</div> </div>
</van-form> </van-form>
</template> </template>
<!-- 选择称谓 --> <!-- 选择称谓 -->
<van-action-sheet v-model="showTitle" :actions="actions" @select="onSelect" cancel-text="取消" close-on-click-action/> <van-action-sheet v-model="showTitle" :actions="actions" @select="onSelect" cancel-text="取消" close-on-click-action />
<!-- 选择城市 --> <!-- 选择城市 -->
<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" />
v-model="cascaderValue"
title="请选择所在地区"
:options="cityOptions"
@close="showProvince = false"
@finish="onFinishProvince"
/>
</van-popup> </van-popup>
</div> </div>
</template> </template>
<script> <script>
import { getMonkAppellation, getRegion, certifyMonk } from '@/api'; import { getMonkAppellation, getRegion, certifyMonk } from "@/api";
export default { export default {
data(){ data() {
return { return {
showProvince: false, // 显示城市选择 showProvince: false, // 显示城市选择
showTitle: false, // 显示法师称谓 showTitle: false, // 显示法师称谓
form: { form: {
nickname: '', // 法号 nickname: "", // 法号
rank_id: '', // 称谓 rank_id: "", // 称谓
rank_text: '', // 称谓 rank_text: "", // 称谓
region: '', region: "",
place_temple: '', // 驻赐寺院 place_temple: "", // 驻赐寺院
avatar_url: [], // 法师照片 avatar_url: [], // 法师照片
cert_url: [], // 戒牒照片 cert_url: [], // 戒牒照片
description: '' description: "",
}, },
cascaderValue: '', cascaderValue: "",
cityOptions: [], cityOptions: [],
uploader: [], uploader: [],
actions: [], actions: [],
authing: false, // 是否正在认证 authing: false, // 是否正在认证
} };
}, },
mounted(){ mounted() {
this.getParams(); this.getParams();
}, },
methods: { methods: {
async onSubmit(){ async onSubmit() {
const { form } = this; const { form } = this;
const [province_id, city_id, county_id] = form.city_id; const [province_id, city_id, county_id] = form.city_id;
const { avatar_url, cert_url } = form; const { avatar_url, cert_url } = form;
if(!avatar_url.length){ if (!avatar_url.length) {
return this.$toast.fail('请上传头像照片'); return this.$toast.fail("请上传头像照片");
} }
if(!cert_url.length){ if (!cert_url.length) {
return this.$toast.fail('请上传戒牒照片') return this.$toast.fail("请上传戒牒照片");
} }
const params = { const params = {
...this.form, ...this.form,
@@ -136,58 +103,58 @@ export default {
cert_url: this.form.cert_url[0].url, cert_url: this.form.cert_url[0].url,
province_id, province_id,
city_id, city_id,
county_id county_id,
} };
await certifyMonk(params) await certifyMonk(params);
this.$toast.success('认证信息提交成功') this.$toast.success("认证信息提交成功");
await this.$delay(2000) await this.$delay(2000);
await this.$router.replace({ name: 'user-temple-station-review'}) await this.$router.replace({ name: "user-temple-station-review" });
}, },
getParams(){ getParams() {
getMonkAppellation().then(res => { getMonkAppellation().then((res) => {
this.actions = res; this.actions = res;
}) });
getRegion().then(city => { getRegion().then((city) => {
this.cityOptions = city this.cityOptions = city;
}) });
}, },
onSelect(action){ onSelect(action) {
this.form.rank_id = action.id; this.form.rank_id = action.id;
this.form.rank_text = action.name; this.form.rank_text = action.name;
}, },
onFinishProvince({selectedOptions}){ onFinishProvince({ 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">
.mega-approve{ .mega-approve {
.input-small-tip{ .input-small-tip {
font-size: .32rem; font-size: 0.32rem;
color: #aaa; color: #aaa;
} }
.van-button--temple{ .van-button--temple {
background: $primary-color; background: #cf9e3b;
border: 1px solid $primary-color; border: 1px solid #cf9e3b;
color: white; color: white;
} }
.reviewing{ .reviewing {
text-align: center; text-align: center;
padding-top: 1.33rem; padding-top: 1.33rem;
.iconfont{ .iconfont {
font-size: 2.33rem; font-size: 2.33rem;
color: $primary-color; color: #cf9e3b;
} }
.review-text{ .review-text {
padding: .4rem 0; padding: 0.4rem 0;
font-size: .4rem; font-size: 0.4rem;
} }
.van-button{ .van-button {
width: 60%; width: 60%;
margin-top: 1.33rem; margin-top: 1.33rem;
} }
+6 -6
View File
@@ -138,7 +138,7 @@ export default {
padding: 0 0.7rem; padding: 0 0.7rem;
border-top-left-radius: 1rem; border-top-left-radius: 1rem;
border-bottom-left-radius: 1rem; border-bottom-left-radius: 1rem;
background: $primary-color; background: #cf9e3b;
opacity: 0.8; opacity: 0.8;
height: 1.07rem; height: 1.07rem;
line-height: 1.07rem; line-height: 1.07rem;
@@ -155,7 +155,7 @@ export default {
justify-content: space-between; justify-content: space-between;
.feedback { .feedback {
font-size: 0.4rem; font-size: 0.4rem;
color: $primary-color; color: #cf9e3b;
} }
.title-text { .title-text {
font-size: 0.5rem; font-size: 0.5rem;
@@ -204,7 +204,7 @@ export default {
font-size: 0.4rem; font-size: 0.4rem;
flex: 1; flex: 1;
.btn { .btn {
background: $primary-color; background: #cf9e3b;
color: white; color: white;
font-size: 0.3rem; font-size: 0.3rem;
border-radius: 2px; border-radius: 2px;
@@ -244,7 +244,7 @@ export default {
position: absolute; position: absolute;
left: -0.2rem; left: -0.2rem;
top: -0.2rem; top: -0.2rem;
border: 0.2rem solid $primary-color; border: 0.2rem solid #cf9e3b;
transition: transform 0.1s linear; transition: transform 0.1s linear;
transform-origin: center center; transform-origin: center center;
} }
@@ -263,7 +263,7 @@ export default {
animation: scale 0.1s linear; animation: scale 0.1s linear;
} }
&::after { &::after {
border-color: $primary-color; border-color: #cf9e3b;
} }
} }
span { span {
@@ -317,7 +317,7 @@ export default {
display: block; display: block;
margin-top: 0.4rem; margin-top: 0.4rem;
font-size: 0.4rem; font-size: 0.4rem;
color: $primary-color; color: #cf9e3b;
} }
} }
.backword { .backword {
+93 -98
View File
@@ -1,18 +1,18 @@
<template> <template>
<div class="course-detail" v-if="data"> <div class="course-detail" v-if="data">
<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="course-container"> <div class="course-container">
<div class="practice"> <div class="practice">
<h1 class="title">{{data.name}}</h1> <h1 class="title">{{ data.name }}</h1>
<div class="accumulation"> <div class="accumulation">
<p> <p>
<span>今日计数 / 今日目标(遍):</span> <span>今日计数 / 今日目标(遍):</span>
<span> <span>
<b>{{data.now_count}}</b> <b>{{ data.now_count }}</b>
<i>/</i> <i>/</i>
<b>{{data.now_target}}</b> <b>{{ data.now_target }}</b>
<i class="iconfont icon-bianjisekuai"></i> <i class="iconfont icon-bianjisekuai"></i>
</span> </span>
</p> </p>
@@ -20,16 +20,16 @@
<div class="progress-bar"> <div class="progress-bar">
<div class="progress-inline"></div> <div class="progress-inline"></div>
</div> </div>
<span class="progress-text">{{data.progress || 0}}%</span> <span class="progress-text">{{ data.progress || 0 }}%</span>
</div> </div>
</div> </div>
<div class="accumulation"> <div class="accumulation">
<p> <p>
<span>总计数 / 总目标(遍):</span> <span>总计数 / 总目标(遍):</span>
<span> <span>
<b>{{data.count}}</b> <b>{{ data.count }}</b>
<i>/</i> <i>/</i>
<b>{{data.target}}</b> <b>{{ data.target }}</b>
<i class="iconfont icon-bianjisekuai"></i> <i class="iconfont icon-bianjisekuai"></i>
</span> </span>
</p> </p>
@@ -58,13 +58,13 @@
</div> </div>
<div class="divider"></div> <div class="divider"></div>
<a href="#"> <a href="#">
<img src="" alt=""> <img src="" alt="" />
</a> </a>
<div class="merit-rank-container"> <div class="merit-rank-container">
<div class="head"> <div class="head">
<span class="title">排行榜</span> <span class="title">排行榜</span>
<div class="list"> <div class="list">
<span :class="[li.id === type_id && 'current']" v-for="(li, index) in types" :key="index" @click="onNav(li)">{{li.name}}</span> <span :class="[li.id === type_id && 'current']" v-for="(li, index) in types" :key="index" @click="onNav(li)">{{ li.name }}</span>
</div> </div>
</div> </div>
<div class="body"> <div class="body">
@@ -73,14 +73,14 @@
<div class="profile"> <div class="profile">
<div> <div>
<div class="name"> <div class="name">
<span>{{course.nickname}}</span> <span>{{ course.nickname }}</span>
<span></span> <span></span>
</div> </div>
<p>{{course.rank}}</p> <p>{{ course.rank }}</p>
</div> </div>
</div> </div>
<div class="result"> <div class="result">
<p class="money">{{course.sum_count}} 遍</p> <p class="money">{{ course.sum_count }} 遍</p>
</div> </div>
</div> </div>
</div> </div>
@@ -89,164 +89,160 @@
<button class="button">恭请法师加持</button> <button class="button">恭请法师加持</button>
</div> </div>
<!-- 计数 --> <!-- 计数 -->
<div class="on-count" @click="onToCount"> <div class="on-count" @click="onToCount">计数</div>
计数
</div>
</div> </div>
</template> </template>
<script> <script>
import { getCourseDetail } from "@/api" import { getCourseDetail } from "@/api";
export default { export default {
data(){ data() {
const { query } = this.$route; const { query } = this.$route;
return { return {
query, query,
data: null, data: null,
type_id: 1, type_id: 1,
types: [ types: [
{ id: 1, name: '实时' }, { id: 1, name: "实时" },
{ id: 2, name: '月榜' }, { id: 2, name: "月榜" },
{ id: 3, name: '总榜' }, { id: 3, name: "总榜" },
] ],
} };
}, },
mounted(){ mounted() {
this.getCourseDetail(); this.getCourseDetail();
}, },
methods: { methods: {
async getCourseDetail(){ async getCourseDetail() {
const res = await getCourseDetail(this.query.id, this.type_id); const res = await getCourseDetail(this.query.id, this.type_id);
this.data = res; this.data = res;
}, },
onNav(li){ onNav(li) {
this.type_id = li.id; this.type_id = li.id;
this.getCourseDetail(); this.getCourseDetail();
}, },
onToCount(){ onToCount() {
this.$router.push({ this.$router.push({
name: 'user-course-count', name: "user-course-count",
query: { id: this.data.id } query: { id: this.data.id },
}) });
} },
} },
} };
</script> </script>
<style lang="scss"> <style lang="scss">
.course-detail{ .course-detail {
background: url('~@/assets/img/background.jpeg') top center no-repeat; background: url("~@/assets/img/background.jpeg") top center no-repeat;
background-size: 100%; background-size: 100%;
.on-count{ .on-count {
position: fixed; position: fixed;
right: 0; right: 0;
bottom: 4rem; bottom: 4rem;
padding: 0 .7rem; padding: 0 0.7rem;
border-top-left-radius: 1rem; border-top-left-radius: 1rem;
border-bottom-left-radius: 1rem; border-bottom-left-radius: 1rem;
background: $primary-color; background: #cf9e3b;
opacity: 0.8; opacity: 0.8;
height: 1.07rem; height: 1.07rem;
line-height: 1.07rem; line-height: 1.07rem;
font-size: .4rem; font-size: 0.4rem;
color: white; color: white;
} }
.course-container{ .course-container {
padding: .4rem; padding: 0.4rem;
.practice{ .practice {
.title{ .title {
font-size: .5rem; font-size: 0.5rem;
color: white; color: white;
padding-top: .4rem; padding-top: 0.4rem;
margin-bottom: 1.33rem; margin-bottom: 1.33rem;
} }
.accumulation{ .accumulation {
font-size: .35rem; font-size: 0.35rem;
margin-bottom: .8rem; margin-bottom: 0.8rem;
p{ p {
color: white; color: white;
font-size: .4rem; font-size: 0.4rem;
.iconfont{ .iconfont {
margin-left: .4rem; margin-left: 0.4rem;
display: inline-block; display: inline-block;
} }
} }
.progress{ .progress {
display: flex; display: flex;
margin-top: .2rem; margin-top: 0.2rem;
align-items: center; align-items: center;
color: white; color: white;
.progress-bar{ .progress-bar {
flex: 1; flex: 1;
border-radius: 8px; border-radius: 8px;
margin-right: .27rem; margin-right: 0.27rem;
height: .3rem; height: 0.3rem;
background: #ddd; background: #ddd;
position: relative; position: relative;
.progress-inline{ .progress-inline {
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
height: .3rem; height: 0.3rem;
width: 50%; width: 50%;
background: #188fff; background: #188fff;
border-radius: 8px; border-radius: 8px;
} }
} }
.progress-text{ .progress-text {
width: .7rem; width: 0.7rem;
display: inline-block; display: inline-block;
text-align: right; text-align: right;
} }
} }
} }
} }
} }
.buddhist-scriptures{ .buddhist-scriptures {
padding: .4rem; padding: 0.4rem;
margin-top: .9rem; margin-top: 0.9rem;
.scriptures{ .scriptures {
margin-bottom: .4rem; margin-bottom: 0.4rem;
.title{ .title {
font-size: .4rem; font-size: 0.4rem;
font-weight: bold; font-weight: bold;
} }
} }
} }
.merit-rank-container{ .merit-rank-container {
.head{ .head {
padding: .53rem .4rem; padding: 0.53rem 0.4rem;
padding-bottom: .13rem; padding-bottom: 0.13rem;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
.title{ .title {
font-size: .43rem; font-size: 0.43rem;
color: #222222; color: #222222;
} }
.list{ .list {
display: flex; display: flex;
span{ span {
font-size: .37rem; font-size: 0.37rem;
color: #999999; color: #999999;
display: inline-block; display: inline-block;
margin-left: .4rem; margin-left: 0.4rem;
border-bottom: .03rem solid transparent; border-bottom: 0.03rem solid transparent;
padding-bottom: .13rem; padding-bottom: 0.13rem;
} }
span.current{ span.current {
color: #222; color: #222;
border-bottom-color: rgb(168, 28, 28); border-bottom-color: rgb(168, 28, 28);
} }
} }
} }
.body{ .body {
.user-merit-course{ .user-merit-course {
display: flex; display: flex;
padding: .27rem 0.4rem; padding: 0.27rem 0.4rem;
img { img {
width: 1.17rem; width: 1.17rem;
height: 1.17rem; height: 1.17rem;
@@ -255,17 +251,17 @@ export default {
} }
.profile { .profile {
flex: 1; flex: 1;
padding-top: .13rem; padding-top: 0.13rem;
.name { .name {
display: flex; display: flex;
align-items: flex-end; align-items: flex-end;
margin-bottom: .27rem; margin-bottom: 0.27rem;
span:first-child { span:first-child {
font-size: 0.4rem; font-size: 0.4rem;
color: #777; color: #777;
vertical-align: top; vertical-align: top;
display: inline-block; display: inline-block;
margin-right: .4rem; margin-right: 0.4rem;
} }
span:last-child { span:last-child {
font-size: 0.32rem; font-size: 0.32rem;
@@ -283,7 +279,7 @@ export default {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
flex-direction: column; flex-direction: column;
padding: .13rem 0; padding: 0.13rem 0;
text-align: right; text-align: right;
.money { .money {
font-size: 0.35rem; font-size: 0.35rem;
@@ -293,18 +289,17 @@ export default {
} }
} }
} }
.button-buff{ .button-buff {
text-align: center; text-align: center;
padding: .4rem; padding: 0.4rem;
.button{ .button {
background: $primary-color; background: #cf9e3b;
border: 1px solid $primary-color; border: 1px solid #cf9e3b;
font-size: .4rem; font-size: 0.4rem;
color: white; color: white;
border-radius: .13rem; border-radius: 0.13rem;
padding: .27rem .4rem; padding: 0.27rem 0.4rem;
} }
} }
} }
</style> </style>
+3 -3
View File
@@ -78,7 +78,7 @@ export default {
color: #999; color: #999;
padding-top: 0.2rem; padding-top: 0.2rem;
span { span {
color: $primary-color; color: #cf9e3b;
padding: 0 0.13rem; padding: 0 0.13rem;
font-weight: bold; font-weight: bold;
} }
@@ -134,7 +134,7 @@ export default {
font-size: 0.3rem; font-size: 0.3rem;
color: #666; color: #666;
span { span {
color: $primary-color; color: #cf9e3b;
font-weight: bold; font-weight: bold;
} }
} }
@@ -151,7 +151,7 @@ export default {
top: 0; top: 0;
height: 0.11rem; height: 0.11rem;
width: 50%; width: 50%;
background: $primary-color; background: #cf9e3b;
border-radius: 4px; border-radius: 4px;
} }
} }
+143 -104
View File
@@ -1,21 +1,25 @@
<template> <template>
<div class="order-detail" v-if="data"> <div class="order-detail" v-if="data">
<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="order-detail-container" > <div class="order-detail-container">
<div class="top"> <div class="top">
<h1 class="status">{{data.status}}</h1>
<div class="order-panel"> <div class="order-panel">
<div class="order-info"> <div class="order-info">
<span class="order-icon"> <span class="order-icon">
<van-icon name="success" /> <van-icon name="success" />
<!-- <van-icon name="fail" />--> <!-- <van-icon name="fail" />-->
</span> </span>
<div class="order-desc"> <div class="order-desc">
<h3 class="text">感谢您对自在福田的信任,恭祝再结善缘。</h3> <h3 class="text">
<p class="desc">处理时间:{{data.created_at}}</p> <span class="tag">{{ data.status }}</span
<p class="desc">处理单位:{{data.unit_name}}</p> >{{ data.goods_name }}
</h3>
<p class="desc">付款时间:{{ data.paid_at }}</p>
<p class="desc">处理时间:{{ data.created_at }}</p>
<p class="desc">处理单位:{{ data.unit_name }}</p>
<p class="desc">感谢您对{{ data.unit_name }}的信任,恭祝再结善缘。</p>
</div> </div>
</div> </div>
<div class="order-btns"> <div class="order-btns">
@@ -23,22 +27,22 @@
<button class="order-btn" @click="onShowCert">功德证书</button> <button class="order-btn" @click="onShowCert">功德证书</button>
</div> </div>
<div class="order-no"> <div class="order-no">
<span>善缘编号:{{data.order_sn}}</span> <span>善缘编号:{{ data.order_sn }}</span>
<button class="order-repeat" @click="onOrderAgain">再结善缘</button> <button class="order-repeat" @click="onOrderAgain">再结善缘</button>
</div> </div>
</div> </div>
<div class="order-feedback" v-if="data.feedback_content"> <div class="order-feedback" v-if="data.feedback_content">
<h3 class="feed-title">反馈内容</h3> <h3 class="feed-title">来自{{ data.unit_name }}的反馈</h3>
<p class="feed-content">{{data.feedback_content}}</p> <p class="feed-content">{{ data.feedback_content }}</p>
<div class="feed-picture"> <div class="feed-picture">
<img v-for="(pic, index) in data.feedback_pictures" :key="index" :src="pic" alt="" class="feed-picture" @click="onPreview(pic, data.feedback_pictures)"> <img v-for="(pic, index) in data.feedback_pictures" :key="index" :src="pic" alt="" class="feed-picture" @click="onPreview(pic, data.feedback_pictures)" />
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<van-popup v-model="showCert" round> <van-popup v-model="showCert" round>
<div class="cert"> <div class="cert">
<img :src="certUrl"> <img :src="certUrl" />
<p class="tip">长按图片保存到手机</p> <p class="tip">长按图片保存到手机</p>
</div> </div>
</van-popup> </van-popup>
@@ -46,168 +50,203 @@
</template> </template>
<script> <script>
import { getOrder } from '@/api'; import { getOrder } from "@/api";
import { previewImage } from '@/common/wechat-web'; import { previewImage } from "@/common/wechat-web";
export default { export default {
data(){ data() {
const { query } = this.$route; const { query } = this.$route;
return { return {
query, query,
data: null, data: {
showCert: false, // id: 22807,
} // temple_id: 48,
// order_sn: "K12721900403102616",
// goods_type: 3,
// goods_id: 355,
// goods_name: "\u5927\u96c4\u5b9d\u6bbf\u4f5b\u50cf\u8d34\u91d1\u5706\u6ee1\uff0c\u5c3e\u6b3e\u52a9\u7f18\u9700\u60a8\u62a4\u6301\uff01",
// spec_id: 0,
// buy_quantity: 1,
// buy_total: 1,
// price: "0.01",
// order_amount: "0.01",
// is_customized: 1,
// feedback_pictures: [
// "https://temple-h5-new.oss-cn-hangzhou.aliyuncs.com/uploads/dev/2026/01/27/phpKk16ba.jpeg",
// "https://temple-h5-new.oss-cn-hangzhou.aliyuncs.com/uploads/dev/2026/01/27/php4bqshn.jpeg",
// ],
// feedback_content: "\u5df2\u5904\u7406\uff0c\u8fd9\u662f\u540e\u53f0\u7684\u5904\u7406\u6d88\u606f",
// status: "\u5df2\u5904\u7406",
// paid_at: "2026-01-27 21:51:48",
// created_at: "2026-01-27 21:51:40",
// spec_name: "",
// dream: "",
// merit_name: "",
// is_auto: "",
// friendly_time: "",
// unit_name: "\u51c6\u63d0\u9053\u573a",
}, },
mounted(){ showCert: false,
};
},
mounted() {
this.getOrder(); this.getOrder();
}, },
computed: { computed: {
certUrl(){ certUrl() {
return `https://wdx-temple.oss-cn-hangzhou.aliyuncs.com/uploads/merit/certificate/${this.data.id}.jpg` return `https://wdx-temple.oss-cn-hangzhou.aliyuncs.com/uploads/merit/certificate/${this.data.id}.jpg`;
} },
}, },
methods: { methods: {
onPreview(picture, pictureArr){ onPreview(picture, pictureArr) {
previewImage(picture, pictureArr) previewImage(picture, pictureArr);
}, },
async getOrder(){ async getOrder() {
const res = await getOrder(this.query.id); const res = await getOrder(this.query.id);
this.data = res; this.data = res;
this.wechatReady((wx) => { this.wechatReady((wx) => {
this.shareToWechat(wx, res.data.shareConfig) this.shareToWechat(wx, res.data.shareConfig);
}) });
}, },
onOrderAgain(){ onOrderAgain() {
this.onPushToGoodsDetail(this.data.goods_type, this.data.goods_id, this.data.temple_id, this.data.spec_ids) this.onPushToGoodsDetail(this.data.goods_type, this.data.goods_id, this.data.temple_id, this.data.spec_ids);
}, },
onCustomer(){ onCustomer() {
this.$router.push({ name: 'user-customer'}) this.$router.push({ name: "user-customer" });
}, },
onShowCert(){ onShowCert() {
this.showCert = true; this.showCert = true;
} },
} },
} };
</script> </script>
<style lang="scss"> <style lang="scss">
.order-detail{ .order-detail {
font-size: .35rem; font-size: 0.35rem;
min-height: 100vh; min-height: 100vh;
background: #f9f9f9; background: #f9f9f9;
.cert{ .cert {
padding: .3rem; padding: 0.3rem;
border-radius: .1rem; border-radius: 0.1rem;
img{ img {
width: 8rem; width: 8rem;
} }
.tip{ .tip {
font-size: .4rem; font-size: 0.4rem;
padding: .4rem 0; padding: 0.4rem 0;
text-align: center; text-align: center;
} }
} }
.order-detail-container{ .order-detail-container {
padding: 0 .3rem; padding: 0 0.3rem;
.top{ .top {
.status{ padding-top: 0.4rem;
font-size: .5rem; .order-panel {
padding: .3rem 0;
padding-top: .6rem;
text-indent: .4rem;
}
.order-panel{
background: white; background: white;
border-radius: .1rem; border-radius: 0.1rem;
padding: .4rem; padding: 0.4rem;
box-shadow: 0 0 .3rem rgba(0,0,0,0.1); border-radius: 12px;
.order-info{ box-shadow: 0 0 0.3rem rgba(0, 0, 0, 0.1);
.order-info {
display: flex; display: flex;
padding-bottom: .3rem; padding-bottom: 0.3rem;
.order-icon{ .order-icon {
width: 1rem; width: 1rem;
height: 1rem; height: 1rem;
display: flex; display: flex;
background: forestgreen; background: forestgreen;
color: white; color: white;
border-radius: 1rem; border-radius: 1rem;
font-size: .6rem; font-size: 0.6rem;
align-items: center; align-items: center;
display: none;
justify-content: center; justify-content: center;
margin-right: .3rem; margin-right: 0.3rem;
} }
.order-desc{ .order-desc {
flex: 1; flex: 1;
.text{ .text {
font-size: .4rem; font-size: 0.4rem;
line-height: 1.3; line-height: 1.6;
.tag {
background: #efbe2d;
color: white;
padding: 3px 10px;
border-radius: 4px;
display: inline-block;
margin-right: 4px;
} }
.desc{ }
font-size: .35rem; .desc {
font-size: 0.35rem;
color: #999; color: #999;
margin-top: .3rem; margin-top: 0.3rem;
} }
} }
} }
.order-btns{ .order-btns {
display: flex; display: flex;
justify-content: flex-start; justify-content: center;
padding-top: .2rem; column-gap: 12px;
padding-top: 0.2rem;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
padding-bottom: .5rem; padding-bottom: 0.5rem;
padding-left: 1.3rem; // padding-left: 1.3rem;
padding-right: .3rem; // padding-right: 0.3rem;
margin-bottom: .4rem; margin-bottom: 0.4rem;
.order-btn{ .order-btn {
height: 1rem; height: 1rem;
border-radius: .1rem; border-radius: 0.1rem;
border: 1px solid #ddd; border: 1px solid #ddd;
background: white; background: white;
padding: 0 .5rem; padding: 0 0.5rem;
margin-right: .2rem; margin-right: 0.2rem;
} }
} }
.order-no{ .order-no {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
span{ span {
color: #555; color: #555;
} }
.order-repeat{ .order-repeat {
height: 1rem; height: 1rem;
border-radius: .1rem; border-radius: 1rem;
border: 1px solid #e77979; border: 1px solid #efbe2d;
padding: 0 .5rem; padding: 0 0.5rem;
background: #e77979; background: #efbe2d;
color: white; color: white;
} }
} }
} }
.order-feedback{ .order-feedback {
background: white; background: white;
border-radius: .1rem; border-radius: 0.1rem;
padding: .4rem; padding: 0.4rem;
box-shadow: 0 0 .3rem rgba(0,0,0,0.1); box-shadow: 0 0 0.3rem rgba(0, 0, 0, 0.1);
margin-top: 1rem; margin-top: 0.5rem;
.feed-title{ border-radius: 12px;
font-size: .4rem; .feed-title {
font-size: 0.4rem;
padding-bottom: 0.2rem;
} }
.feed-content{ .feed-content {
padding-top: .3rem; padding-top: 0.3rem;
padding-bottom: .3rem; padding-bottom: 0.3rem;
line-height: 1.4; line-height: 1.4;
font-size: .38rem; font-size: 0.38rem;
color: #888; color: #888;
text-align: justify; text-align: justify;
} }
.feed-picture{ .feed-picture {
img{ display: grid;
width: 23%; grid-template-columns: repeat(3, 1fr);
margin-right: 2%; gap: 0.2rem;
margin-bottom: .1rem; img {
height: 1.5rem; width: 100%;
} }
} }
} }
+253 -209
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>
@@ -47,7 +47,7 @@
</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">
@@ -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
}
}, },
created(){ canNextStep2() {
TMAPLoader.load({ return this.form.register_cert_url.length > 0 && this.agreement;
},
},
created() {
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>
+245 -224
View File
@@ -1,280 +1,301 @@
import Vue from 'vue' import Vue from "vue";
import Router from 'vue-router'; import Router from "vue-router";
Vue.use(Router); Vue.use(Router);
const routes = [ const routes = [
{ {
path: '', path: "",
redirect: '/home' redirect: "/home",
}, },
{ {
path: '/home', path: "/home",
name: 'home', name: "home",
component: () => import('../pages/home.vue') component: () => import("../pages/home.vue"),
}, },
{ {
path: '/search', path: "/search",
name: 'search', name: "search",
meta: { title: '搜索' }, meta: { title: "搜索" },
component: () => import('@/pages/search') component: () => import("@/pages/search"),
},
{
path: '/mescroll',
name: 'mescroll',
meta: { title: '上拉下刷' },
component: () => import('@/pages/mescroll-test')
},
{
path: '/temple',
meta: { title: '寺院', navBarBackgroundColor: 'white', showNavBar: false },
component: { render: h => h('router-view') },
children: [
{
path: '',
name: 'temple-home',
meta: { title: '寺院首页', navBarBackgroundColor: 'white', showNavBar: false },
component: () => import('@/pages/temple-home')
},
{
path: 'list',
name: 'temple-list',
meta: { title: '寺院列表', navBarBackgroundColor: 'white',showNavBar: false },
component: () => import('@/pages/temple-list')
},
{
path: 'detail',
name: 'temple-detail',
meta: { title: '寺院详情', navBarBackgroundColor: 'white',showNavBar: false },
component: () => import('@/pages/temple-detail')
}
]
},
{
path: '/buddha-activity',
name: 'buddha-activity',
meta: { title: '进展活动', navBarBackgroundColor: 'white' },
component: () => import('@/pages/buddha-activity')
},
{
path: '/buddha-activity-scroll',
name: 'buddha-activity-scroll',
meta: { title: '进展活动', navBarBackgroundColor: 'white' },
component: () => import('@/pages/buddha-activity-scroll')
},
{
path: '/buddha-detail',
name: 'buddha-detail',
meta: { title: '进展活动详情', navBarBackgroundColor: 'white' },
component: () => import('@/pages/buddha-detail')
},
{
path: '/merit-list',
name: 'merit-list',
meta: { title: '功德无量', navBarBackgroundColor: 'white' },
component: () => import('@/pages/merit-list')
},
{
path: '/merit-box',
name: 'merit-box',
meta: { title: '功德无量', navBarBackgroundColor: 'white', showNavBar: false},
component: () => import('@/pages/merit-box')
}, },
{ {
path: '/monk', path: "/temple",
name: 'monk', meta: { title: "寺院", navBarBackgroundColor: "white", showNavBar: false },
meta: { title: '详情', navBarBackgroundColor: 'white' }, component: { render: (h) => h("router-view") },
component: () => import('@/pages/monk')
},
{
path: '/pay',
name: 'pay',
meta: { title: '支付', navBarBackgroundColor: 'white' },
component: () => import('@/pages/pay')
},
{
path: '/pay-result',
name: 'pay-result',
meta: { title: '支付成功', navBarBackgroundColor: 'white' },
component: () => import('@/pages/pay-result')
},
{
path: '/join-cert',
name: 'join-cert',
meta: { title: '参与成功', navBarBackgroundColor: 'white' },
component: () => import('@/pages/join-cert')
},
{
path: '/get-user-phone',
name: 'get-user-phone',
meta: { title: '自在福田', navBarBackgroundColor: 'white' },
component: () => import('@/pages/get-user-phone')
},
{
path: '/goods-detail',
name: 'goods-detail',
meta: { title: '详情', navBarBackgroundColor: 'white' },
component: () => import('@/pages/goods-detail')
},
{
path: '/goods-light-detail',
name: 'goods-light-detail',
meta: { title: '详情', navBarBackgroundColor: 'white' },
component: () => import('@/pages/goods-light-detail')
},
{
path: '/fill-name',
name: 'fill-name',
meta: { title: '详情', navBarBackgroundColor: 'white' },
component: () => import('@/pages/fill-name')
},
{
path: '/everyday-donation',
name: 'everyday-donation',
meta: { title: '日行一善', navBarBackgroundColor: 'white', showNavBar: false },
component: () => import('@/pages/everyday-donation')
},
{
path: '/user',
component: () => import('@/pages/user/root'),
children: [ children: [
{ {
path: '', path: "",
name: 'user-home', name: "temple-home",
meta: { title: '个人中心', showNavBar: false }, meta: { title: "寺院首页", navBarBackgroundColor: "white", showNavBar: false },
component: () => import('@/pages/user/index') component: () => import("@/pages/temple-home"),
}, },
{ {
path: 'customer', path: "list",
name: 'user-customer', name: "temple-list",
meta: { title: '客服中心' }, meta: { title: "寺院列表", navBarBackgroundColor: "white", showNavBar: false },
component: () => import('@/pages/user/customer') component: () => import("@/pages/temple-list"),
}, },
{ {
path: 'temple-station', path: "detail",
name: 'user-temple-station', name: "temple-detail",
meta: { title: '寺院入驻', showNavBar: false }, meta: { title: "寺院详情", navBarBackgroundColor: "white", showNavBar: false },
component: () => import('@/pages/user/temple-station') component: () => import("@/pages/temple-detail"),
},
],
}, },
{ {
path: 'temple-station-agreement', path: "/buddha-activity",
name: 'user-temple-station-agreement', name: "buddha-activity",
meta: { title: '寺院入驻协议', showNavBar: false }, meta: { title: "进展活动", navBarBackgroundColor: "white" },
component: () => import('@/pages/user/temple-station-agreement') component: () => import("@/pages/buddha-activity"),
}, },
{ {
path: 'temple-station-review', path: "/buddha-activity-scroll",
name: 'user-temple-station-review', name: "buddha-activity-scroll",
meta: { title: '寺院入驻', showNavBar: false }, meta: { title: "进展活动", navBarBackgroundColor: "white" },
component: () => import('@/pages/user/temple-station/review') component: () => import("@/pages/buddha-activity-scroll"),
}, },
{ {
path: 'certificate', path: "/buddha-detail",
name: 'user-certificate', name: "buddha-detail",
meta: { title: '客服中心' }, meta: { title: "进展活动详情", navBarBackgroundColor: "white" },
component: () => import('@/pages/user/certificate') component: () => import("@/pages/buddha-detail"),
}, },
{ {
path: 'order', path: "/merit-list",
name: 'user-order', name: "merit-list",
meta: { title: '我的善缘' }, meta: { title: "近期活动", navBarBackgroundColor: "white" },
component: () => import('@/pages/user/order') component: () => import("@/pages/merit-list"),
}, },
{ {
path: 'order-detail', path: "/merit-box",
name: 'user-order-detail', name: "merit-box",
meta: { title: '善缘详情' }, meta: { title: "近期活动", navBarBackgroundColor: "white", showNavBar: false },
component: () => import('@/pages/user/order-detail') component: () => import("@/pages/merit-box"),
},
{
path: "/monk",
name: "monk",
meta: { title: "详情", navBarBackgroundColor: "white" },
component: () => import("@/pages/monk"),
}, },
{ {
path: 'focus', path: "/pay",
name: 'user-focus', name: "pay",
meta: { title: '我的关注' }, meta: { title: "捐赠", navBarBackgroundColor: "white" },
component: () => import('@/pages/user/focus') component: () => import("@/pages/pay"),
}, },
{ {
path: 'approve', path: "/pay-result",
name: 'user-approve', name: "pay-result",
meta: { title: '认证法师' }, meta: { title: "护持成功", navBarBackgroundColor: "white" },
component: () => import('@/pages/user/approve') component: () => import("@/pages/pay-result"),
}, },
{ {
path: 'course', path: "/join-cert",
meta: { title: '修行' }, name: "join-cert",
name: 'user-course', meta: { title: "参与成功", navBarBackgroundColor: "white" },
component: { render: h => h('router-view')}, component: () => import("@/pages/join-cert"),
},
{
path: "/get-user-phone",
name: "get-user-phone",
meta: { title: "自在福田", navBarBackgroundColor: "white" },
component: () => import("@/pages/get-user-phone"),
},
{
path: "/goods-detail",
name: "goods-detail",
meta: { title: "详情", navBarBackgroundColor: "white" },
component: () => import("@/pages/goods-detail"),
},
{
path: "/goods-light-detail",
name: "goods-light-detail",
meta: { title: "详情", navBarBackgroundColor: "white" },
component: () => import("@/pages/goods-light-detail"),
},
{
path: "/fill-name",
name: "fill-name",
meta: { title: "详情", navBarBackgroundColor: "white" },
component: () => import("@/pages/fill-name"),
},
{
path: "/everyday-donation",
name: "everyday-donation",
meta: { title: "日行一善", navBarBackgroundColor: "white", showNavBar: false },
component: () => import("@/pages/everyday-donation"),
},
{
path: "/user",
component: () => import("@/pages/user/root"),
children: [ children: [
{ {
path: '', path: "",
name: 'user-course-list', name: "user-home",
meta: { title: '修行', showNavBar: false }, meta: { title: "个人中心", showNavBar: false },
component: () => import('@/pages/user/course'), component: () => import("@/pages/user/index"),
}, },
{ {
path: 'detail', path: "customer",
name: 'user-course-detail', name: "user-customer",
meta: { title: '我的功课', showNavBar: false }, meta: { title: "客服中心" },
component: () => import('@/pages/user/course/detail'), component: () => import("@/pages/user/customer"),
}, },
{ {
path: 'count', path: "temple-station",
name: 'user-course-count', name: "user-temple-station",
meta: { title: '我的功课 - 修行', showNavBar: false }, meta: { title: "寺院入驻", showNavBar: false },
component: () => import('@/pages/user/course/count'), component: () => import("@/pages/user/temple-station"),
}, },
] {
path: "temple-station-agreement",
name: "user-temple-station-agreement",
meta: { title: "寺院入驻协议", showNavBar: false },
component: () => import("@/pages/user/temple-station-agreement"),
}, },
] {
} path: "temple-station-review",
] name: "user-temple-station-review",
meta: { title: "寺院入驻", showNavBar: false },
component: () => import("@/pages/user/temple-station/review"),
},
{
path: "certificate",
name: "user-certificate",
meta: { title: "客服中心" },
component: () => import("@/pages/user/certificate"),
},
{
path: "order",
name: "user-order",
meta: { title: "我的善缘" },
component: () => import("@/pages/user/order"),
},
{
path: "order-detail",
name: "user-order-detail",
meta: { title: "善缘详情" },
component: () => import("@/pages/user/order-detail"),
},
{
path: "focus",
name: "user-focus",
meta: { title: "我的关注" },
component: () => import("@/pages/user/focus"),
},
{
path: "approve",
name: "user-approve",
meta: { title: "认证法师" },
component: () => import("@/pages/user/approve"),
},
{
path: "course",
meta: { title: "修行" },
name: "user-course",
component: { render: (h) => h("router-view") },
children: [
{
path: "",
name: "user-course-list",
meta: { title: "修行", showNavBar: false },
component: () => import("@/pages/user/course"),
},
{
path: "detail",
name: "user-course-detail",
meta: { title: "我的功课", showNavBar: false },
component: () => import("@/pages/user/course/detail"),
},
{
path: "count",
name: "user-course-count",
meta: { title: "我的功课 - 修行", showNavBar: false },
component: () => import("@/pages/user/course/count"),
},
],
},
],
},
{
path: "/admin",
name: "admin",
meta: { title: "后台", navBarBackgroundColor: "white", showNavBar: false },
component: { render: (h) => h("router-view") },
children: [
{
path: "orders",
name: "adminOrder",
meta: { title: "订单列表", navBarBackgroundColor: "white", showNavBar: false },
component: () => import("@/pages/admin/order/index.vue"),
},
{
path: "order-detail",
name: "adminOrderDetail",
meta: { title: "订单详情", navBarBackgroundColor: "white", showNavBar: false },
component: () => import("@/pages/admin/order/detail.vue"),
},
{
path: "order-process",
name: "adminOrderProcess",
meta: { title: "订单处理", navBarBackgroundColor: "white", showNavBar: false },
component: () => import("@/pages/admin/order/process.vue"),
},
],
},
];
const router = new Router({ const router = new Router({
mode: 'hash', mode: "hash",
routes, routes,
scrollBehavior(){ scrollBehavior() {
return { return {
x: 0, x: 0,
y: 0 y: 0,
} };
} },
}) });
export default router; export default router;
export const tabbar = [ export const tabbar = [
{ {
path: '/home', path: "/home",
name: 'home', name: "home",
active: require('../assets/img/tabbar/tabbar_icon_01_click.png'), active: require("../assets/img/tabbar/tabbar_icon_01_click.png"),
inactive: require('../assets/img/tabbar/tabbar_icon_01.png'), inactive: require("../assets/img/tabbar/tabbar_icon_01.png"),
title: '首页' title: "首页",
},
// {
// path: '/user/course',
// name: 'user-course-list',
// active: require('../assets/img/tabbar/tabbar_icon_02_click.png'),
// inactive: require('../assets/img/tabbar/tabbar_icon_02.png'),
// title: '修行'
// },
{
path: "/merit-box",
name: "merit-box",
active: require("../assets/img/tabbar/tabbar_icon_03_click.png"),
inactive: require("../assets/img/tabbar/tabbar_icon_03.png"),
title: "每日功德",
}, },
{ {
path: '/user/course', path: "/temple/list",
name: 'user-course-list', name: "temple-list",
active: require('../assets/img/tabbar/tabbar_icon_02_click.png'), active: require("../assets/img/tabbar/tabbar_icon_04_click.png"),
inactive: require('../assets/img/tabbar/tabbar_icon_02.png'), inactive: require("../assets/img/tabbar/tabbar_icon_04.png"),
title: '修行' title: "参寺",
}, },
{ {
path: '/merit-box', path: "/user/",
name: 'merit-box', name: "user-home",
active: require('../assets/img/tabbar/tabbar_icon_03_click.png'), active: require("../assets/img/tabbar/tabbar_icon_05_click.png"),
inactive: require('../assets/img/tabbar/tabbar_icon_03.png'), inactive: require("../assets/img/tabbar/tabbar_icon_05.png"),
title: '每日功德' title: "我的",
}, },
{ ];
path: '/temple/list',
name: 'temple-list',
active: require('../assets/img/tabbar/tabbar_icon_04_click.png'),
inactive: require('../assets/img/tabbar/tabbar_icon_04.png'),
title: '参寺'
},
{
path: '/user/',
name: 'user-home',
active: require('../assets/img/tabbar/tabbar_icon_05_click.png'),
inactive: require('../assets/img/tabbar/tabbar_icon_05.png'),
title: '我的'
},
]
+284
View File
@@ -0,0 +1,284 @@
// utils/ObserverInteraction.js
class ObserverInteraction {
constructor(options = {}) {
this.options = {
attributes: true, // 观察属性变化
childList: false, // 观察子节点变化
subtree: false, // 观察后代节点
attributeFilter: [], // 观察特定属性
attributeOldValue: false, // 记录属性旧值
...options,
};
this.observer = null;
this.callbacks = new Map();
this.targets = new Set();
}
/**
* 开始观察目标元素
* @param {HTMLElement} target - 要观察的DOM元素
* @param {Function} callback - 变化时的回调函数
* @param {Object} customOptions - 自定义观察选项
*/
observe(target, callback, customOptions = {}) {
if (!target) {
console.error("ObserverInteraction: 目标元素不存在");
return;
}
const options = { ...this.options, ...customOptions };
// 如果已存在观察器,先断开
if (this.observer) {
this.disconnect();
}
// 创建新的观察器
this.observer = new MutationObserver((mutationsList) => {
const changes = this._processMutations(mutationsList);
if (changes.length > 0 && callback) {
callback(changes, target);
}
// 触发所有注册的回调
this.callbacks.forEach((cb, element) => {
if (element === target || element.contains(target)) {
cb(changes, target);
}
});
});
// 开始观察
this.observer.observe(target, options);
this.targets.add(target);
// 存储回调
if (callback) {
this.callbacks.set(target, callback);
}
return this;
}
/**
* 监听特定属性的变化
* @param {HTMLElement} target - 目标元素
* @param {string} attributeName - 属性名
* @param {Function} callback - 回调函数
*/
watchAttribute(target, attributeName, callback) {
return this.observe(target, callback, {
attributes: true,
attributeFilter: [attributeName],
attributeOldValue: true,
});
}
/**
* 监听元素大小变化(使用 ResizeObserver)
* @param {HTMLElement} target - 目标元素
* @param {Function} callback - 回调函数
*/
observeResize(target, callback) {
if (!window.ResizeObserver) {
console.warn("ResizeObserver 不支持当前浏览器");
return;
}
const resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
const { width, height } = entry.contentRect;
callback({ width, height, target: entry.target });
}
});
resizeObserver.observe(target);
// 存储以便清理
this.resizeObservers = this.resizeObservers || new Map();
this.resizeObservers.set(target, resizeObserver);
return () => this.unobserveResize(target);
}
/**
* 处理 mutations 数据
* @private
*/
_processMutations(mutationsList) {
const changes = [];
for (const mutation of mutationsList) {
const change = {
type: mutation.type,
target: mutation.target,
timestamp: Date.now(),
};
if (mutation.type === "attributes") {
change.attributeName = mutation.attributeName;
change.oldValue = mutation.oldValue;
change.newValue = mutation.target.getAttribute(mutation.attributeName);
}
if (mutation.type === "childList") {
change.addedNodes = Array.from(mutation.addedNodes);
change.removedNodes = Array.from(mutation.removedNodes);
}
changes.push(change);
}
return changes;
}
/**
* 注册交互事件
* @param {HTMLElement} element - 元素
* @param {string} eventType - 事件类型
* @param {Function} callback - 回调
*/
on(element, eventType, callback) {
if (!element || !callback) return;
const handler = (event) => {
callback(event, element);
};
element.addEventListener(eventType, handler);
// 存储以便清理
this.eventHandlers = this.eventHandlers || new Map();
if (!this.eventHandlers.has(element)) {
this.eventHandlers.set(element, new Map());
}
this.eventHandlers.get(element).set(eventType, handler);
return () => this.off(element, eventType);
}
/**
* 移除事件监听
* @param {HTMLElement} element - 元素
* @param {string} eventType - 事件类型
*/
off(element, eventType) {
if (!this.eventHandlers?.has(element)) return;
const handlers = this.eventHandlers.get(element);
if (eventType) {
const handler = handlers.get(eventType);
if (handler) {
element.removeEventListener(eventType, handler);
handlers.delete(eventType);
}
} else {
handlers.forEach((handler, type) => {
element.removeEventListener(type, handler);
});
this.eventHandlers.delete(element);
}
}
/**
* 观察元素可见性(Intersection Observer)
* @param {HTMLElement} target - 目标元素
* @param {Function} callback - 可见性变化回调
* @param {Object} options - IntersectionObserver 配置
*/
observeVisibility(target, callback, options = {}) {
const defaultOptions = {
threshold: 0.1,
rootMargin: "0px",
};
const intersectionObserver = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
callback({
isIntersecting: entry.isIntersecting,
intersectionRatio: entry.intersectionRatio,
boundingClientRect: entry.boundingClientRect,
target: entry.target,
});
});
},
{ ...defaultOptions, ...options }
);
intersectionObserver.observe(target);
this.intersectionObservers = this.intersectionObservers || new Map();
this.intersectionObservers.set(target, intersectionObserver);
return () => this.unobserveVisibility(target);
}
/**
* 停止观察可见性
* @param {HTMLElement} target - 目标元素
*/
unobserveVisibility(target) {
const observer = this.intersectionObservers?.get(target);
if (observer) {
observer.unobserve(target);
this.intersectionObservers.delete(target);
}
}
/**
* 停止观察大小变化
* @param {HTMLElement} target - 目标元素
*/
unobserveResize(target) {
const observer = this.resizeObservers?.get(target);
if (observer) {
observer.unobserve(target);
this.resizeObservers.delete(target);
}
}
/**
* 断开所有观察器
*/
disconnect() {
if (this.observer) {
this.observer.disconnect();
this.observer = null;
}
// 清理 ResizeObservers
this.resizeObservers?.forEach((observer) => {
observer.disconnect();
});
this.resizeObservers?.clear();
// 清理 IntersectionObservers
this.intersectionObservers?.forEach((observer) => {
observer.disconnect();
});
this.intersectionObservers?.clear();
this.targets.clear();
this.callbacks.clear();
}
/**
* 销毁实例
*/
destroy() {
this.disconnect();
// 清理所有事件监听
this.eventHandlers?.forEach((handlers, element) => {
handlers.forEach((handler, type) => {
element.removeEventListener(type, handler);
});
});
this.eventHandlers?.clear();
}
}
export default ObserverInteraction;
+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;
} },
} };
+7 -3
View File
@@ -51,11 +51,15 @@ module.exports = {
css: { css: {
sourceMap: false, sourceMap: false,
loaderOptions: { loaderOptions: {
sass: {
sassOptions: {
silenceDeprecations: ["legacy-js-api", "import"],
},
},
scss: { scss: {
data: null, sassOptions: {
silenceDeprecations: ["legacy-js-api", "import"],
}, },
postcss: {
plugins: [],
}, },
}, },
}, },
+1 -1
View File
File diff suppressed because one or more lines are too long
-9621
View File
File diff suppressed because it is too large Load Diff