hookehuyr

✨ feat(组件): 新增捐花组件,和相关页面操作

......@@ -40,10 +40,10 @@
</div>
<div class="donate-handle">
<div class="donate-cancel">
<my-button @on-click="cancelDonate" type="plain">取消</my-button>
<my-button type="plain" @on-click="cancelDonate">取消</my-button>
</div>
<div class="donate-imd">
<my-button @on-click="donateBook" type="primary">立即捐赠</my-button>
<my-button type="primary" @on-click="donateBook">立即捐赠</my-button>
</div>
</div>
</div>
......@@ -174,25 +174,31 @@ export default {
.donate-wrapper {
.donate-header {
padding: 1rem;
.donate-book {
border: 1px solid #ECECEC;
border-radius: 5px;
padding: 0.1rem;
}
.donate-detail {
font-size: 1.25rem;
padding: 1rem;
.text {
color: #292929;
font-weight: bold;
}
.price {
color: #EE332E;
}
}
}
.donate-name {
padding: 1rem;
.donate-input {
border: 1px solid #B9B9B9;
border-radius: 5px;
......@@ -200,25 +206,31 @@ export default {
margin-left: 1rem;
}
}
.donate-tips {
padding: 1rem;
padding-top: 0;
}
.donate-number {
padding: 1rem;
}
.donate-handle {
overflow: auto;
.donate-cancel {
width: 49%;
float: left;
}
.donate-imd {
width: 50%;
float: left;
}
}
}
.button {
display: flex;
flex-direction: column;
......
<template>
<van-popup v-model:show="show" :close-on-click-overlay="false" round position="bottom" :style="{ height: popupHeight, zIndex: 3000 }">
<div class="donate-wrapper">
<div class="donate-title">
您所有捐助的爱心
<van-icon :name="icon_flower" />
都将用于多民族语言发展
</div>
<div class="shortcut-choose-wrapper">
<van-row gutter="10">
<van-col span="8">
<div :class="['base-item', checked_one_flower ? 'checked-item' : 'uncheck-item']" @click="checkFlower(1)">
1朵花花
</div>
</van-col>
<van-col span="8">
<div :class="['base-item', checked_two_flower ? 'checked-item' : 'uncheck-item']" @click="checkFlower(2)">
2朵花花
</div>
</van-col>
<van-col span="8">
<div :class="['base-item', checked_three_flower ? 'checked-item' : 'uncheck-item']" @click="checkFlower(3)">
3朵花花
</div>
</van-col>
</van-row>
</div>
<!-- <div style="background: #FFFFFF; border-radius: 3px; border: 1px solid #713610; padding: 0.5rem 1rem; margin: 0.5rem 1rem; text-align: center;">更多花花</div> -->
<div class="donate-number">
<van-row>
<van-col span="12">&nbsp;花花数量 </van-col>
<van-col span="12" style="text-align: right;">
<van-stepper v-model="donate_number" min="1" max="100" integer input-width="40px" button-size="32px" @change="onChangeDonate" />
</van-col>
</van-row>
</div>
<div class="donate-name">
<van-row>
<van-col span="4" style="line-height: 2;">幼儿园</van-col>
<van-col span="18">
<div class="donate-text">杨浦民办科技幼稚园杨浦民办科技幼稚园</div>
</van-col>
</van-row>
</div>
<div class="donate-name">
<van-row>
<van-col span="4" style="line-height: 2;">助力人</van-col>
<van-col span="18">
<div class="donate-text">瑟日古娜</div>
</van-col>
</van-row>
</div>
<div class="donate-name">
<van-row>
<van-col span="4" style="line-height: 2;">捐赠人<span style="color: red;">*</span></van-col>
<van-col class="donate-input" span="18">
<input v-model="item.perf_name" type="text" style="border: 0; padding: 0.25rem;" />
</van-col>
</van-row>
</div>
<van-row style="margin: 1rem 0;">
<van-col span="12" offset="8">
<div style="display: flex;align-items: center; box-sizing: content-box;">
<div style="display: flex; flex-direction: column; justify-content: center;">
<van-checkbox v-model="agreed" checked-color="#ee0a24">同意&nbsp;</van-checkbox>
</div>
<div style="display: flex; flex-direction: column; justify-content: center;">
<span style="text-decoration: underline; color: #713610;" @click="handleDonationAgreement">捐赠协议</span>
</div>
</div>
</van-col>
</van-row>
<div class="donate-handle">
<div class="donate-cancel">
<my-button type="plain" @on-click="cancelDonate">取消</my-button>
</div>
<div class="donate-imd">
<my-button type="primary" @on-click="donateBook">确定</my-button>
</div>
</div>
</div>
</van-popup>
<van-popup v-model:show="showDonationAgreement" position="bottom" :style="{ height: '100%', zIndex: 4000 }">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloremque earum voluptates architecto! Itaque magnam modi ducimus minima. Ullam quam, excepturi modi cupiditate quidem optio consequuntur minus porro, saepe, neque incidunt!
<div class="bottom-btn" @click="closeDonationAgreement">
<div class="text">关闭</div>
</div>
</van-popup>
</template>
<script setup>
import Cookies from 'js-cookie'
import { icon_flower } from '@/utils/generateIcons'
import MyButton from '@/components/MyButton/index.vue'
import { ref, reactive, onMounted, watch, nextTick } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import axios from '@/utils/axios';
import $ from 'jquery'
import { Toast, Dialog } from 'vant';
const $route = useRoute();
const $router = useRouter();
const props = defineProps({
item: Object,
showPopup: Boolean
})
const emit = defineEmits(['on-close']);
let donate_number = ref(1);
// 捐赠数量回调
const onChangeDonate = (v) => {
if (v > 3) { // 大于3朵取消选中
checked_one_flower.value = false;
checked_two_flower.value = false;
checked_three_flower.value = false;
} else {
checkFlower(v)
}
}
const donateBook = () => {
// 爱心捐书接口
axios.post('/srv/?a=add_donate', {
book_id: props.item.book_id,
qty: donate_number.value,
donate_name: props.item.perf_name,
})
.then(res => {
if (res.data.code === 1) {
console.warn(res.data.data);
closeBtn();
// 交易成功跳转回调页面
// TEMP: 临时传参 donate_id
$router.push({
path: '/client/wechatpayCallback',
query: {
donate_id: res.data.data.id
}
})
} else {
console.warn(res);
if (!res.data.show) return false;
Toast({
icon: 'close',
message: res.data.msg
});
}
})
.catch(err => {
console.error(err);
})
}
const show = ref(false);
let popupHeight = ref('100%');
watch(() => props.showPopup, (v) => {
// 如果没有默认儿童需要用户确认一次
if (v && !props.item.perf_id) {
Dialog.confirm({
title: '温馨提示',
message: '默认儿童为空, 是否继续捐书!',
confirmButtonColor: '#713610'
})
.then(() => {
show.value = v;
// DOM调整后,把弹出框高度设定到适合高度,配合不同分辨率效果
nextTick(() => {
let height = $('.donate-wrapper').height();
popupHeight.value = height + 10 + 'px';
})
})
.catch(() => {
// 取消按钮回调
closeBtn();
});
return false;
}
show.value = v;
// DOM调整后,把弹出框高度设定到适合高度,配合不同分辨率效果
nextTick(() => {
let height = $('.donate-wrapper').height();
popupHeight.value = height + 10 + 'px';
})
})
const closeBtn = () => {
emit('on-close', false)
show.value = false;
}
const cancelDonate = () => {
closeBtn();
}
// TODO: 微信支付
onMounted(() => {
})
// 选择捐赠数量
const checked_one_flower = ref(true);
const checked_two_flower = ref(false);
const checked_three_flower = ref(false);
const checkFlower = (number) => {
switch (number) {
case 1:
checked_one_flower.value = true;
checked_two_flower.value = false;
checked_three_flower.value = false;
donate_number.value = 1;
break;
case 2:
checked_one_flower.value = false;
checked_two_flower.value = true;
checked_three_flower.value = false;
donate_number.value = 2;
break;
case 3:
checked_one_flower.value = false;
checked_two_flower.value = false;
checked_three_flower.value = true;
donate_number.value = 3;
break;
}
}
// 捐赠协议
const agreed = ref(false);
// 显示捐赠协议弹框
const showDonationAgreement = ref(false);
const handleDonationAgreement = () => {
showDonationAgreement.value = true
}
const closeDonationAgreement = () => {
showDonationAgreement.value = false
}
</script>
<style lang="less" scoped>
.donate-wrapper {
.donate-title {
padding: 1rem 1rem 0 1rem;
color: #999999;
text-align: center;
}
.shortcut-choose-wrapper {
padding: 1rem;
.base-item {
text-align: center;
color: #713610;
padding: 0.5rem 0;
}
.checked-item {
background: #F9EA57;
border-radius: 3px;
border: 1px solid #F9EA57;
}
.uncheck-item {
background: #FFFFFF;
border-radius: 3px;
border: 1px solid #713610;
}
}
.donate-name {
padding: 1rem;
.donate-text {
background: #F4F4F4;
border-radius: 3px;
padding: 0.5rem;
margin-left: 5%;
width: 95%;
}
.donate-input {
border: 1px solid #B9B9B9;
border-radius: 5px;
padding: 0.2rem;
margin-left: 1rem;
}
}
.donate-number {
padding: 1rem;
}
.donate-handle {
overflow: auto;
.donate-cancel {
width: 49%;
float: left;
}
.donate-imd {
width: 50%;
float: left;
}
}
}
.button {
display: flex;
flex-direction: column;
justify-content: center;
flex: 1;
padding: 0 0.5rem;
}
.bottom-btn {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background-color: white;
box-shadow: 0px -2px 4px 0px rgba(0, 0, 0, 0.07);
.text {
text-align: center;
padding: 0.7rem;
margin: 0.8rem;
font-size: 1rem;
font-weight: bold;
border-radius: 24px;
// border: 1px solid F7F7F7;
color: #713610;
background-color: @base-color;
box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.06);
}
}
</style>
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-31 12:06:19
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-01 00:50:37
* @FilePath: /tswj/src/main.js
* @Description:
*/
import { createApp } from 'vue';
import { Button, Image as VanImage, Col, Row, Icon, Form, Field, CellGroup, ConfigProvider, Toast, Uploader, Empty, Tab, Tabs, Overlay, NumberKeyboard, Lazyload, List, PullRefresh, Popup, Picker, Sticky, Stepper, Tag, Swipe, SwipeItem, Dialog, ActionSheet, Loading } from 'vant';
import { Button, Image as VanImage, Col, Row, Icon, Form, Field, CellGroup, ConfigProvider, Toast, Uploader, Empty, Tab, Tabs, Overlay, NumberKeyboard, Lazyload, List, PullRefresh, Popup, Picker, Sticky, Stepper, Tag, Swipe, SwipeItem, Dialog, ActionSheet, Loading, Checkbox } from 'vant';
import router from './router';
import App from './App.vue';
// import axios from './utils/axios';
......@@ -12,7 +20,7 @@ const app = createApp(App);
app.config.globalProperties.$http = axios; // 关键语句
app.use(pinia).use(router).use(Button).use(VanImage).use(Col).use(Row).use(Icon).use(Form).use(Field).use(CellGroup).use(Toast).use(Uploader).use(Empty).use(Tab).use(Tabs).use(Overlay).use(NumberKeyboard).use(Lazyload).use(List).use(PullRefresh).use(Popup).use(Picker).use(Sticky).use(Stepper).use(Tag).use(Swipe).use(SwipeItem).use(Dialog).use(ActionSheet).use(Loading);
app.use(pinia).use(router).use(Button).use(VanImage).use(Col).use(Row).use(Icon).use(Form).use(Field).use(CellGroup).use(Toast).use(Uploader).use(Empty).use(Tab).use(Tabs).use(Overlay).use(NumberKeyboard).use(Lazyload).use(List).use(PullRefresh).use(Popup).use(Picker).use(Sticky).use(Stepper).use(Tag).use(Swipe).use(SwipeItem).use(Dialog).use(ActionSheet).use(Loading).use(Checkbox);
app.use(ConfigProvider);
......
......@@ -2,7 +2,7 @@
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-17 11:17:58
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-05-31 18:34:18
* @LastEditTime: 2022-05-31 22:11:29
* @FilePath: /tswj/src/utils/generateModules.js
* @Description:
*/
......@@ -14,6 +14,7 @@ import ShortcutFixed from '@/components/ShortcutFixed/index.vue'
import BookCard from '@/components/BookCard/index.vue'
import VideoDetail from '@/components/VideoDetail/index.vue'
import DonateBar from '@/components/DonateBar/index.vue'
import DonateFlower from '@/components/DonateFlower/index.vue'
export {
MyButton,
......@@ -24,4 +25,5 @@ export {
BookCard,
VideoDetail,
DonateBar,
DonateFlower,
}
......
......@@ -111,7 +111,7 @@
</div>
</notice-overlay>
<donate-book :show-popup="showDonate" :item="userInfo" @on-close="closeDonate" />
<donate-flower :show-popup="showDonate" :item="userInfo" @on-close="closeDonate" />
<van-overlay :show="show" z-index="9999">
<div class="wrapper" @click.stop>
......@@ -124,7 +124,7 @@
import { ref, onActivated, nextTick } from 'vue'
import { useRoute, useRouter, onBeforeRouteLeave } from 'vue-router'
import { Cookies, _, storeToRefs, mainStore, Toast, hasEllipsis } from '@/utils/generatePackage'
import { MyButton, VideoCard, NoticeOverlay, DonateBook, ShortcutFixed } from '@/utils/generateModules'
import { MyButton, VideoCard, NoticeOverlay, DonateFlower, ShortcutFixed } from '@/utils/generateModules'
import { icon_video, icon_up, icon_down, icon_subscribed, icon_unsubscribe, no_image } from '@/utils/generateIcons'
import { JSJ_FORM_C } from '@/constant'
import { useVideoList, useDefaultPerf, useShortcutBar, useScrollTop } from '@/composables';
......
......@@ -6,10 +6,13 @@
<p>捐赠总金额</p>
<p>{{ donateInfo.total ? donateInfo.total : 0 }}&nbsp;元</p>
</van-col>
<van-col span="1"><div class="line"></div></van-col>
<van-col span="1">
<div class="line" />
</van-col>
<van-col class="book" span="11">
<p>点亮书籍</p>
<p>{{ donateInfo.num ? donateInfo.num : 0 }}&nbsp;个</p>
<p>捐赠次数</p>
<!-- TODO: 捐赠次数数据联调-->
<p>{{ donateInfo.num ? donateInfo.num : 0 }}&nbsp;次</p>
</van-col>
</van-row>
</div>
......@@ -18,8 +21,8 @@
<template v-for="(item, key) in dataList" :key="key">
<div class="book-row">
<van-row>
<van-col span="8" class="book-col" v-for="(v, index) in item" :key="index">
<div @click="showCert(v)" v-if="v.is_donate" class="ENABLE">
<van-col v-for="(v, index) in item" :key="index" span="8" class="book-col">
<div v-if="v.is_donate" class="ENABLE" @click="showCert(v)">
<van-image width="90%" height="7rem" :src="v.cover" />
</div>
<div v-else class="DISABLE">
......@@ -35,19 +38,15 @@
</div>
</template>
</div>
<van-empty v-if="!dataList.length"
class="custom-image"
:image="no_image"
description="暂无捐赠信息"
/>
<van-empty v-if="!dataList.length" class="custom-image" :image="no_image" description="暂无捐赠信息" />
</div>
<!-- TODO: 需要改造显示方式 -->
<van-overlay :show="show" @click="onHide">
<div style="width: auto; height: 100%; margin: 2rem 2rem 0 2rem; overflow: hidden;">
<van-swipe class="my-swipe" ref="swipe">
<van-swipe ref="swipe" class="my-swipe">
<van-swipe-item v-for="(d, k) in certItems" :key="k">
<donate-cert :item="d"></donate-cert>
<div style="height: 2rem;"></div>
<donate-cert :item="d" />
<div style="height: 2rem;" />
</van-swipe-item>
<template #indicator="{ active, total }">
<div class="custom-indicator">{{ active + 1 }}/{{ total }}</div>
......@@ -55,7 +54,6 @@
</van-swipe>
</div>
</van-overlay>
</template>
<script setup>
......@@ -77,7 +75,7 @@ const $router = useRouter();
const donateInfo = ref('');
const dataList = ref([]);
axios.post('/srv/?a=my_donate')
.then(res => {
.then(res => {
if (res.data.code === 1) {
donateInfo.value = res.data.data;
dataList.value = _.chunk(res.data.data.book, 3);
......@@ -89,10 +87,10 @@ axios.post('/srv/?a=my_donate')
message: res.data.msg
});
}
})
.catch(err => {
})
.catch(err => {
console.error(err);
});
});
// 显示捐赠证书
const show = ref(false);
......@@ -147,42 +145,53 @@ watch(show, (v) => {
padding: 1rem;
text-align: center;
color: #713610;
.sum {
line-height: 1.5;
p:last-child {
font-weight: bold;
font-size: 1.25rem;
}
}
.line {
border-right: 1px solid #733912;
height: 100%;
opacity: 0.15;
}
.book {
line-height: 1.5;
p:last-child {
font-weight: bold;
font-size: 1.25rem;
}
}
}
.donate-book-wrapper {
padding: 0 1rem;
.book-row {
margin: 1rem 0;
text-align: center;
.book-col {
padding: 0 0.5rem;
.ENABLE {
background: #FFFFFF;
box-shadow: 3px 3px 5px 0px rgba(0, 0, 0, 0.15);
border-radius: 5px;
border: 1px solid #FFE000;
}
.DISABLE {
border-radius: 6px;
position: relative;
.mask {
position: absolute;
width: 100%;
......@@ -190,12 +199,14 @@ watch(show, (v) => {
background: rgba(0, 0, 0, 0.4);
border-radius: 6px;
top: 0;
img {
margin-top: 20%;
width: 50%;
}
}
}
.text {
font-size: 1rem;
margin-top: 0.5rem;
......