|
@@ -37,10 +37,10 @@
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- <div class="creator" v-if="user.id">
|
|
|
|
|
|
|
+ <div class="creator" v-if="info.user && info.user.id">
|
|
|
<div class="text1">产品持有人:</div>
|
|
<div class="text1">产品持有人:</div>
|
|
|
- <van-image width="20" height="20" radius="4" :src="user.avatar"></van-image>
|
|
|
|
|
- <div class="text2">{{ user.nickname }}</div>
|
|
|
|
|
|
|
+ <van-image width="20" height="20" radius="4" :src="info.user.avatar"></van-image>
|
|
|
|
|
+ <div class="text2">{{ info.user.nickname }}</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -64,26 +64,59 @@
|
|
|
<ion-footer v-if="info.status === 'IN_STOCK'">
|
|
<ion-footer v-if="info.status === 'IN_STOCK'">
|
|
|
<ion-toolbar>
|
|
<ion-toolbar>
|
|
|
<div class="footer">
|
|
<div class="footer">
|
|
|
- <van-button type="primary" block>立即购买</van-button>
|
|
|
|
|
|
|
+ <van-button type="primary" block @click="onPay">立即购买</van-button>
|
|
|
</div>
|
|
</div>
|
|
|
</ion-toolbar>
|
|
</ion-toolbar>
|
|
|
</ion-footer>
|
|
</ion-footer>
|
|
|
|
|
+ <ion-modal
|
|
|
|
|
+ :is-open="showPayModal"
|
|
|
|
|
+ class="pay-modal"
|
|
|
|
|
+ :initial-breakpoint="breakpoint"
|
|
|
|
|
+ :breakpoints="[0, breakpoint]"
|
|
|
|
|
+ @didDismiss="showPayModal = false"
|
|
|
|
|
+ >
|
|
|
|
|
+ <ion-content :style="{ height: `${breakpoint * 100}%` }">
|
|
|
|
|
+ <div class="head">
|
|
|
|
|
+ <div class="title">{{ $t('order.payInfo') }}</div>
|
|
|
|
|
+ <div class="close" @click="showWithdrawModal = false">
|
|
|
|
|
+ <img src="@/assets/icon_close.svg" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="price-box">
|
|
|
|
|
+ <div class="label">{{ $t('order.total') }}({{ $t('balance.unit') }})</div>
|
|
|
|
|
+ <div class="value">{{ info.currentPrice }}</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="divider"></div>
|
|
|
|
|
+ <div class="pay-item">
|
|
|
|
|
+ <img src="@/assets/icon_pay_wallet.png" class="icon" />
|
|
|
|
|
+ <div class="label">{{ $t('order.walletPay') }}</div>
|
|
|
|
|
+ <van-checkbox name="wallet" v-model="payMethod" @click.stop />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="footer">
|
|
|
|
|
+ <van-button type="primary" block @click="pay">{{ $t('order.buyNow') }}</van-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </ion-content>
|
|
|
|
|
+ </ion-modal>
|
|
|
</ion-page>
|
|
</ion-page>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
|
import { Swiper, SwiperSlide } from 'swiper/vue'
|
|
import { Swiper, SwiperSlide } from 'swiper/vue'
|
|
|
import 'swiper/swiper.min.css'
|
|
import 'swiper/swiper.min.css'
|
|
|
-import { ref, getCurrentInstance, onMounted, computed } from 'vue'
|
|
|
|
|
-import { useRoute } from 'vue-router'
|
|
|
|
|
|
|
+import { ref, onMounted, computed } from 'vue'
|
|
|
|
|
+import { useRoute, useRouter } from 'vue-router'
|
|
|
|
|
+import { useWindowSize } from '@vueuse/core'
|
|
|
|
|
+import toast from '@/utils/toast'
|
|
|
|
|
+import { http } from '@/plugins/http'
|
|
|
|
|
+import { useI18n } from 'vue-i18n'
|
|
|
|
|
+import { IonButton, alertController } from '@ionic/vue'
|
|
|
|
|
+import { useUserStore } from '@/stores/user'
|
|
|
|
|
+import { mapState } from 'pinia'
|
|
|
|
|
|
|
|
-const {
|
|
|
|
|
- appContext: {
|
|
|
|
|
- config: { globalProperties: global }
|
|
|
|
|
- }
|
|
|
|
|
-} = getCurrentInstance()
|
|
|
|
|
const route = useRoute()
|
|
const route = useRoute()
|
|
|
-
|
|
|
|
|
|
|
+const router = useRouter()
|
|
|
|
|
+const userState = useUserStore()
|
|
|
|
|
+const { t } = useI18n()
|
|
|
const info = ref({
|
|
const info = ref({
|
|
|
pic: []
|
|
pic: []
|
|
|
})
|
|
})
|
|
@@ -91,12 +124,9 @@ const info = ref({
|
|
|
const category = computed(() => {
|
|
const category = computed(() => {
|
|
|
return info.value.category || {}
|
|
return info.value.category || {}
|
|
|
})
|
|
})
|
|
|
-const user = computed(() => {
|
|
|
|
|
- return info.value.user || {}
|
|
|
|
|
-})
|
|
|
|
|
|
|
|
|
|
function getDetail() {
|
|
function getDetail() {
|
|
|
- global.$http.get('/product/get/' + route.query.id).then(res => {
|
|
|
|
|
|
|
+ http.get('/product/get/' + route.query.id).then(res => {
|
|
|
info.value = res
|
|
info.value = res
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
@@ -104,6 +134,41 @@ function getDetail() {
|
|
|
onMounted(() => {
|
|
onMounted(() => {
|
|
|
getDetail()
|
|
getDetail()
|
|
|
})
|
|
})
|
|
|
|
|
+
|
|
|
|
|
+const showPayModal = ref(false)
|
|
|
|
|
+const { height: windowHeight } = useWindowSize()
|
|
|
|
|
+const breakpoint = computed(() => {
|
|
|
|
|
+ return 450 / windowHeight.value
|
|
|
|
|
+})
|
|
|
|
|
+const payMethod = ref('wallet')
|
|
|
|
|
+const onPay = () => {
|
|
|
|
|
+ console.log(userState.user)
|
|
|
|
|
+ if (!userState.user) {
|
|
|
|
|
+ router.push({ name: 'login' })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ showPayModal.value = true
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+const pay = () => {
|
|
|
|
|
+ showPayModal.value = false
|
|
|
|
|
+ toast.loading(t('order.processing'))
|
|
|
|
|
+ http.post('/order/createOrder', {
|
|
|
|
|
+ productId: info.value.id
|
|
|
|
|
+ })
|
|
|
|
|
+ .then(res => {
|
|
|
|
|
+ toast.clear()
|
|
|
|
|
+ router.push({
|
|
|
|
|
+ name: 'orderDetail',
|
|
|
|
|
+ query: {
|
|
|
|
|
+ id: res.id
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(e => {
|
|
|
|
|
+ console.log(e)
|
|
|
|
|
+ toast.error(e.error)
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="less" scoped>
|
|
<style lang="less" scoped>
|
|
@@ -223,4 +288,77 @@ ion-footer {
|
|
|
--van-button-border-width: 0;
|
|
--van-button-border-width: 0;
|
|
|
--van-button-primary-background: linear-gradient(135deg, #d700ff 0%, #3e22ff 100%);
|
|
--van-button-primary-background: linear-gradient(135deg, #d700ff 0%, #3e22ff 100%);
|
|
|
}
|
|
}
|
|
|
|
|
+.pay-modal {
|
|
|
|
|
+ ion-content {
|
|
|
|
|
+ --background: var(--ion-color-step-0);
|
|
|
|
|
+ }
|
|
|
|
|
+ .head {
|
|
|
|
|
+ .f();
|
|
|
|
|
+ padding-left: 16px;
|
|
|
|
|
+ border-bottom: 1px solid var(--ion-color-step-50);
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ .title {
|
|
|
|
|
+ flex-grow: 1;
|
|
|
|
|
+ color: var(--ion-color-text);
|
|
|
|
|
+ padding: 16px 0 10px 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ .close {
|
|
|
|
|
+ padding: 16px 16px 10px 0;
|
|
|
|
|
+ img {
|
|
|
|
|
+ width: 24px;
|
|
|
|
|
+ height: 24px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ .price-box {
|
|
|
|
|
+ background: #f5f7fa;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ margin: 16px;
|
|
|
|
|
+ padding: 20px 0;
|
|
|
|
|
+ border-radius: 4px;
|
|
|
|
|
+ .label {
|
|
|
|
|
+ color: var(--ion-color-step-400);
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ line-height: 24px;
|
|
|
|
|
+ }
|
|
|
|
|
+ .value {
|
|
|
|
|
+ line-height: 30px;
|
|
|
|
|
+ font-size: 30px;
|
|
|
|
|
+ margin-top: 6px;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ .footer {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ bottom: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+ padding: 9px 27px;
|
|
|
|
|
+ }
|
|
|
|
|
+ .divider {
|
|
|
|
|
+ margin: 0 16px;
|
|
|
|
|
+ height: 1px;
|
|
|
|
|
+ background: var(--ion-color-step-50);
|
|
|
|
|
+ }
|
|
|
|
|
+ .pay-item {
|
|
|
|
|
+ .f();
|
|
|
|
|
+ height: 48px;
|
|
|
|
|
+ margin-top: 12px;
|
|
|
|
|
+ padding: 0 16px;
|
|
|
|
|
+ .icon {
|
|
|
|
|
+ width: 24px;
|
|
|
|
|
+ height: 24px;
|
|
|
|
|
+ }
|
|
|
|
|
+ .label {
|
|
|
|
|
+ margin-left: 10px;
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ :deep(.van-checkbox__icon--checked .van-icon) {
|
|
|
|
|
+ background: linear-gradient(135deg, #a108ff 0%, #5c7cff 100%);
|
|
|
|
|
+ border-color: var(--ion-color-step-0);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
</style>
|
|
</style>
|