| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818 |
- <template>
- <view class="withdraw">
- <view class="withdrawContent">
- <view class="tabs">
- <view
- v-for="item in tabsList"
- :key="item.key"
- class="tabs-item"
- :class="[tabsIndex === item.key ? 'active' : '']"
- @click="tabsChange(item)"
- >
- {{ item.title }}
- </view>
- </view>
- <!-- 收货地址模块 -->
- <view class="address" @click="onAddress">
- <view class="addressCon" v-if="addressInfo.realName">
- <view class="name"
- >{{ addressInfo.realName }}
- <text class="phone">{{ addressInfo.phone }}</text>
- </view>
- <view class="acea-row">
- <text class="default font-color" v-if="addressInfo.isDefault"
- >[默认]</text
- >
- <text class="line2"
- >{{ addressInfo.province }}{{ addressInfo.city
- }}{{ addressInfo.district }}{{ addressInfo.detail }}</text
- >
- </view>
- </view>
- <view class="addressCon" v-else>
- <view class="setaddress">设置收货地址</view>
- </view>
- <view class="iconfont icon-jiantou"></view>
- </view>
- <view class="content-top">
- <!-- 快递公司选择模块 -->
- <view class="section">
- <view class="section-title">选择快递公司</view>
- <view class="courier-list">
- <view
- class="courier-item"
- :class="{ active: item.isSelected }"
- v-for="(item, index) in courierList"
- :key="index"
- @click="handleSelectCourier(index)"
- >
- <image class="courier-logo" :src="item.logo"></image>
- <image
- v-show="item.isSelected"
- class="gou"
- src="https://mp-ad17e5cd-05c1-4df9-b060-556e25dac130.cdn.bspapp.com/mini/courier/dui.png"
- ></image>
- </view>
- </view>
- </view>
- </view>
- <view class="gold-box">
- <view class="gold-item">
- <view class="header">
- <h3 class="title">板料克重</h3>
- <view class="live-gold">
- 实时金价
- <text class="price">{{ realprice.toFixed(2) }}</text>
- </view>
- </view>
- <view class="input-box">
- <input
- v-model.number="extract"
- placeholder="请输入克数"
- type="digit"
- class="t-input"
- @input="onKeyInput"
- />
- </view>
- <view class="infoMoney" style="font-size: 16px">
- <view v-if="is_out">
- <text class="info-money-num" style="color: #ff1e0f">
- 输入克重超过可提现克重,账户克重{{ accountWeight }}克
- </text>
- </view>
- <view v-else-if="is_lowest">
- <text class="info-money-num" style="color: #ff1e0f">
- 最低{{ lowest }}克起兑换,账户克重{{
- accountWeight
- }}克,且最多两位小数
- </text>
- <text class="info-money-num" style="color: #ff1e0f"
- >最低{{ lowest }}g起购买,且最多两位小数</text
- >
- </view>
- <text v-else class="infoMoneyNum">
- {{ `手续费:${1}元 运费:${1}元 账户克重:${accountWeight}克` }}
- </text>
- <view class="infoTip">*默认融成小圆饼寄出</view>
- </view>
- </view>
- </view>
- <view class="withdraw-bottom">
- <view
- :class="['submitBtn', is_post ? '' : 'submitBtnActive']"
- style="margin-top: 10px"
- >
- <button @click="handleShowModel">提交兑换</button>
- </view>
- </view>
- </view>
- <!-- <uni-popup
- ref="singPopup"
- type="bottom"
- borderRadius="10px 10px 0 0"
- maskBackgroundColor="rgba(0,0,0,0)"
- >
- <view class="signContent">
- <scroll-view scrollY class="scrollView">
- <rich-text :nodes="agreement"></rich-text>
- </scroll-view>
- <view
- class="confirmBtn footer"
- @click="
- aggregate = true;
- $refs.singPopup.close();
- "
- >
- 我已详细知悉
- </view>
- </view>
- </uni-popup> -->
- <!-- 收货地址组件 -->
- <addressWindow
- ref="addressWindowRef"
- :address="address"
- :pagesUrl="pagesUrl"
- @OnDefaultAddress="OnDefaultAddress"
- @OnChangeAddress="OnChangeAddress"
- @changeClose="changeClose"
- />
- </view>
- </template>
- <script setup>
- import { ref, computed, nextTick } from "vue";
- import { onLoad } from "@dcloudio/uni-app";
- // 导入用户地址详情API接口
- import { getAddressDetail, getAddressDefault } from "@/api/user.js";
- // 导入地址选择组件
- import addressWindow from "@/components/addressWindow";
- import { useAppStore } from "@/stores/app";
- const appStore = useAppStore();
- console.log(appStore.userInfo);
- const tabsList = ref([
- { key: 1, label: "gold", title: "黄金" },
- { key: 2, label: "platinum", title: "铂金" },
- { key: 3, label: "silver", title: "白银" },
- ]);
- // 响应式数据(对应原data())
- const tabsIndex = ref(1);
- const needPrice = ref(0); // 手续费
- const goldAllPrice = ref(0); // 总金价
- const extract = ref(0);
- const lowest = ref(1);
- const is_out = ref(false);
- const is_post = ref(false);
- const is_lowest = ref(false);
- const aggregate = ref(false);
- const agreement = ref([]);
- // 快递公司列表(静态结构,内部选中状态需响应式)
- const courierList = ref([
- {
- type: 2,
- name: "顺丰陆运",
- logo: "https://mp-ad17e5cd-05c1-4df9-b060-556e25dac130.cdn.bspapp.com/mini/courier/sf-land.png",
- isSelected: true,
- price: 15,
- },
- {
- type: 3,
- name: "顺丰空运",
- logo: "https://mp-ad17e5cd-05c1-4df9-b060-556e25dac130.cdn.bspapp.com/mini/courier/sf-air.png",
- isSelected: false,
- price: 24,
- },
- {
- type: 4,
- name: "顺丰到付",
- logo: "https://mp-ad17e5cd-05c1-4df9-b060-556e25dac130.cdn.bspapp.com/mini/courier/sf-cod.png",
- isSelected: false,
- price: 0,
- },
- ]);
- // 快递相关响应式数据
- const courierPrice = ref(15);
- const selectedCourierType = ref(2);
- const selectedGender = ref("gold");
- // 用户余额及手续费(响应式对象)
- const preciousMetal = ref({
- gold: { name: "黄金", pool: 0, fee: 0 },
- platinum: { name: "铂金", pool: 0, fee: 0 },
- silver: { name: "白银", pool: 0, fee: 0 },
- });
- const tabsChange = (item) => {
- tabsIndex.value = item.key;
- selectedGender.value = item.label;
- };
- const handleSelectCourier = (index) => {
- courierList.value.forEach((item, i) => {
- item.isSelected = i === index;
- });
- const selectedCourier = courierList.value.find((item) => item.isSelected);
- if (selectedCourier) {
- // this.courierPrice = this.userInfo?.isSVIP
- // ? vk.myfn.accDivDecimal(selectedCourier.price, 2)
- // : selectedCourier.price;
- // this.selectedCourierType = selectedCourier.type; // 保存选中快递的type
- }
- };
- // 输入框逻辑
- // 在<script setup>中添加输入验证方法
- const onKeyInput = () => {
- // 重置提示状态
- is_lowest.value = false;
- is_out.value = false;
- // 处理空输入
- if (extract.value === null || extract.value === "" || isNaN(extract.value)) {
- is_lowest.value = true; // 空输入时显示最低限制提示
- return;
- }
- const inputWeight = Number(extract.value);
- const minWeight = lowest.value; // 最低1克(来自定义的lowest: ref(1))
- const accountWeightNum = Number(accountWeight.value) || 0;
- // 验证1:是否低于最低限制(1克)
- const isBelowMin = inputWeight < minWeight;
- // 验证2:是否超过两位小数(通过正则判断)
- const hasMoreThanTwoDecimals = /\.\d{3,}$/.test(extract.value.toString());
- // 验证3:是否超过账户可用克重
- const isOverAccount = inputWeight > accountWeightNum;
- // 设置提示状态
- if (isBelowMin || hasMoreThanTwoDecimals) {
- is_lowest.value = true; // 显示最低限制提示(包含兑换和购买)
- }
- if (isOverAccount) {
- is_out.value = true; // 显示超过账户克重提示
- }
- };
- // 账户克重
- const accountWeight = computed(() => {
- if (tabsIndex.value == 1) {
- return appStore.userInfo.goldBalance;
- }
- if (tabsIndex.value == 2) {
- return appStore.userInfo.ptBalance;
- }
- if (tabsIndex.value == 3) {
- return appStore.userInfo.agBalance;
- }
- });
- import useRealGoldPrice from "@/hooks/useRealGoldPrice";
- // 实时价格处理
- const {
- realGoldRecyclePrice,
- realKGoldRecyclePrice,
- realPtRecyclePrice,
- realAgRecyclePrice,
- } = useRealGoldPrice({});
- import { useStoreRights } from "@/stores/rights";
- const rightsStore = useStoreRights();
- // 回收
- const vipRealGoldRecyclePrice = computed(() => {
- let res = 0;
- const basePrice = Number(realGoldRecyclePrice.value || 0);
- const soldBenefit = Number(rightsStore.userBenefits?.sold || 0);
- res = appStore.userInfo.svip
- ? basePrice + soldBenefit + 0.3
- : basePrice + soldBenefit;
- return res;
- });
- const viprealKGoldRecyclePrice = computed(() => {
- let res = 0;
- const basePrice = Number(realKGoldRecyclePrice.value || 0);
- const soldBenefit = Number(rightsStore.userBenefits?.sold || 0);
- res = appStore.userInfo.svip
- ? basePrice + soldBenefit + 0.3
- : basePrice + soldBenefit;
- return res;
- });
- const viprealPtRecyclePrice = computed(() => {
- let res = 0;
- const basePrice = Number(realPtRecyclePrice.value || 0);
- const soldBenefit = Number(rightsStore.userBenefits?.sold || 0);
- res = appStore.userInfo.svip
- ? basePrice + soldBenefit + 0.3
- : basePrice + soldBenefit;
- return res;
- });
- const viprealAgRecyclePrice = computed(() => {
- let res = 0;
- const basePrice = Number(realAgRecyclePrice.value || 0);
- const soldBenefit = Number(rightsStore.userBenefits?.sold || 0);
- res = appStore.userInfo.svip
- ? basePrice + soldBenefit + 0.3
- : basePrice + soldBenefit;
- return res;
- });
- // 实时金价
- const realprice = computed(() => {
- if (tabsIndex.value == 1) {
- return vipRealGoldRecyclePrice.value;
- }
- if (tabsIndex.value == 2) {
- return viprealPtRecyclePrice.value;
- }
- if (tabsIndex.value == 3) {
- return viprealAgRecyclePrice.value;
- }
- });
- // 地址相关
- const textareaStatus = ref(true);
- const pagesUrl = ref("");
- const addressWindowRef = ref(null);
- const address = ref({
- address: false,
- addressId: 0,
- }); // 地址组件
- const addressInfo = ref({}); // 地址信息
- const addressId = ref(0); // 地址id
- // 首次进入页面时展示默认地址
- const OnDefaultAddress = (e) => {
- console.log("保存默认地址详情");
- addressInfo.value = e; // 保存默认地址详情
- address.value.addressId = e.id; // 更新选中地址ID
- };
- // 打开地址选择弹窗
- const onAddress = () => {
- textareaStatus.value = false; // 隐藏备注框
- address.value.address = true; // 显示地址弹窗
- // 设置地址页面跳转链接
- pagesUrl.value = "/pages/users/user_address_list/index";
- nextTick(() => {
- addressWindowRef.value.fetchAddressList();
- });
- };
- // 选择地址后触发的事件
- const OnChangeAddress = (e) => {
- console.log("OnChangeAddress", e);
- addressInfo.value = e; // 保存选中的地址详情
- address.value.addressId = e.id; // 更新选中地址ID
- textareaStatus.value = true; // 显示备注框
- address.value.address = false; // 关闭地址弹窗
- };
- // 获取默认地址或指定地址详情
- const getaddressInfo = () => {
- if (addressId.value) {
- // 若有指定地址ID,获取该地址详情
- getAddressDetail(addressId.value).then((res) => {
- if (res.data) {
- // 若地址存在
- res.data.isDefault = parseInt(res.data.isDefault); // 转换默认地址标识为数字
- addressInfo.value = res.data || {}; // 保存地址详情
- addressId.value = res.data.id || 0; // 更新地址ID
- address.value.addressId = res.data.id || 0; // 更新选中地址ID
- }
- });
- } else {
- // 若没有指定地址ID,获取默认地址
- getAddressDefault().then((res) => {
- // 注意:原代码中未导入getAddressDefault,可能是遗漏
- if (res.data) {
- // 若默认地址存在
- res.data.isDefault = parseInt(res.data.isDefault);
- addressInfo.value = res.data || {};
- addressId.value = res.data.id || 0;
- address.value.addressId = res.data.id || 0;
- }
- });
- }
- };
- onLoad(() => {
- // 若已登录且非支付页面,则获取地址信息(注释掉的逻辑,预留)
- if (appStore.isLogin) {
- // console.log(1111);
- getaddressInfo();
- // 等待DOM更新后,调用地址组件的方法获取地址列表
- nextTick(() => {
- addressWindowRef.value.fetchAddressList();
- });
- }
- });
- // 关闭地址弹窗
- const changeClose = () => {
- address.value.address = false; // 隐藏地址弹窗
- };
- </script>
- <style lang="scss" scoped>
- $item-value-color: #dca537;
- $card-bcolor: #f8f8f8;
- page {
- height: 100%;
- background-color: #ededed;
- }
- .tabs {
- display: flex;
- height: 80rpx;
- border-radius: 40rpx;
- padding: 0 20rpx;
- color: #fff;
- font-size: 38rpx;
- font-weight: 300;
- // margin-bottom: 10rpx;
- .tabs-item {
- width: 50%;
- height: 100%;
- display: flex;
- justify-content: center;
- // align-items:;
- position: relative;
- color: #000000;
- }
- .active::after {
- position: absolute;
- bottom: 18rpx;
- left: 50%;
- transform: translateX(-50%);
- content: "";
- z-index: 100;
- display: block;
- width: 65rpx;
- height: 6rpx;
- background-color: #cc9933;
- }
- }
- .withdraw-bottom {
- width: 100%;
- margin-top: 100rpx;
- display: flex;
- justify-content: center;
- }
- .header {
- padding-left: 5px;
- position: relative;
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 10px 10px;
- border-radius: 5px;
- // background-color: #fff;
- // font-weight: bold;
- font-size: 18px;
- .live-gold {
- font-weight: 0;
- font-size: 30rpx;
- .price {
- color: #dcbe81;
- margin-left: 10rpx;
- }
- }
- .item {
- display: flex;
- align-items: center;
- margin-top: 15px;
- .targe {
- display: flex;
- justify-content: center;
- align-items: center;
- color: #fff;
- width: 35px;
- height: 35px;
- border-radius: 50%;
- background-color: #cc9933;
- }
- .address {
- width: 440rpx;
- margin: 0 10px;
- font-size: 28rpx;
- .receive-address {
- letter-spacing: 9px;
- }
- }
- .end {
- display: flex;
- justify-content: center;
- align-items: center;
- .copy {
- color: #888888;
- border-radius: 3px;
- border: 1px solid #888888;
- font-size: 24rpx;
- padding: 6rpx 23rpx;
- }
- }
- }
- &::before {
- position: absolute;
- top: 50%;
- transform: translatey(-50%);
- left: 0;
- content: "";
- width: 2px;
- height: 15px;
- background-color: #daa520;
- }
- .title {
- font-weight: 500;
- font-size: 32rpx;
- font-family: "黑体";
- }
- }
- .gold-box {
- padding: 30rpx 20rpx;
- }
- .gold-item {
- margin: 0 0 25rpx 0;
- }
- .input-box {
- display: flex;
- background-color: #ededed;
- border-radius: 5px;
- height: 90rpx;
- align-items: center;
- justify-content: space-around;
- font-size: 28rpx;
- padding-left: 20rpx;
- margin-top: 50rpx;
- input {
- width: 90%;
- }
- }
- // 地址相关样式
- .address {
- width: 690rpx;
- max-height: 180rpx;
- margin: 40rpx 0;
- padding: 28rpx;
- box-sizing: border-box;
- border-radius: 30rpx;
- .addressCon {
- width: 596rpx;
- font-size: 26rpx;
- color: #666;
- .name {
- font-size: 30rpx;
- color: #282828;
- font-weight: bold;
- margin-bottom: 10rpx;
- .phone {
- margin-left: 50rpx;
- }
- }
- .default {
- margin-right: 12rpx;
- }
- .setaddress {
- color: #333;
- font-size: 28rpx;
- }
- }
- .iconfont {
- font-size: 35rpx;
- color: #707070;
- }
- }
- .content-top {
- border-radius: 30rpx;
- // padding: 20rpx;
- background: $card-bcolor;
- margin-bottom: 20rpx;
- // 通用区块标题
- .section {
- // margin: 0 24rpx 32rpx;
- .section-title {
- font-size: 32rpx;
- font-weight: bold;
- margin-bottom: 24rpx;
- position: relative;
- padding-left: 20rpx;
- &::after {
- position: absolute;
- top: 0;
- left: 0;
- height: 100%;
- width: 3px;
- background: $item-value-color;
- content: "";
- }
- }
- // 快递公司选择
- .courier-list {
- display: flex;
- // overflow-x: auto;
- justify-content: space-between;
- padding-bottom: 16rpx;
- .courier-item {
- display: flex;
- flex-direction: column;
- align-items: center;
- min-width: 160rpx;
- margin-right: 24rpx;
- padding: 24rpx 20rpx;
- border: 2rpx solid #eee;
- border-radius: 12rpx;
- cursor: pointer;
- position: relative;
- .gou {
- position: absolute;
- width: 40rpx;
- height: 40rpx;
- // background: #dca537;
- right: -7rpx;
- bottom: -7rpx;
- border-radius: 50%;
- right: -6rpx;
- bottom: -6rpx;
- }
- &.active {
- border-color: #dbb870;
- }
- .courier-logo {
- width: 120rpx;
- height: 120rpx;
- margin-bottom: 8rpx;
- }
- .courier-name {
- font-size: 26rpx;
- }
- }
- }
- }
- }
- .withdraw {
- height: 100%;
- background-size: 100% 40%;
- background: $uni-bg-primary !important;
- .withdrawContent {
- padding: 45rpx 40rpx;
- background-color: #f7f7f7;
- // margin-top: ;
- position: relative;
- top: 150rpx;
- border-radius: 50rpx 50rpx 0 0;
- }
- .withdrawBody {
- background-color: #fff;
- padding: 20px 30px;
- font-size: 14px;
- .inputMoney {
- display: flex;
- align-items: center;
- justify-content: center;
- font-weight: 600;
- border-bottom: 1px solid #eaeef1;
- .rmb {
- font-size: 16px;
- // text-wrap: nowrap;
- }
- .tInput {
- height: 1.9em;
- font-size: 2.5em;
- border: none;
- position: relative;
- left: 3.5%;
- outline: none;
- }
- }
- }
- }
- .infoMoney {
- margin-top: 10px;
- font-size: 12px;
- margin-bottom: 20px;
- .infoMoneyNum {
- color: #b2b2b2;
- font-size: 26rpx;
- }
- .infoTip {
- color: red;
- font-size: 23rpx;
- margin-top: 10rpx;
- }
- }
- .agreement {
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 10px;
- .chooseIcon {
- width: 16px;
- height: 16px;
- }
- .agreementText {
- font-size: 14px;
- margin-left: 10px;
- color: #999999;
- .agreementLink {
- color: #dca12b;
- }
- }
- }
- .submitBtn {
- button {
- background-color: #dca12b;
- color: #fff;
- width: 450rpx;
- height: 72rpx;
- display: flex;
- font-size: 30rpx;
- justify-content: center;
- align-items: center;
- border-radius: 30rpx;
- }
- }
- .submitBtnActive {
- button {
- color: #fff;
- background: #c4bba6;
- }
- }
- .signContent {
- background-color: #f8f8f8;
- padding: 20px;
- box-sizing: border-box;
- display: flex;
- justify-content: center;
- align-items: center;
- flex-direction: column;
- border-radius: 20px 20px 0 0;
- .scrollView {
- background-color: #fff;
- padding: 4px;
- height: 300px;
- overflow-y: hidden;
- border: 1px solid #dfdfdf;
- }
- .confirmBtn {
- margin-top: 10px;
- color: #fff;
- padding: 4px 20px;
- border-radius: 20px;
- background: linear-gradient(to right, #8ed187, #5dd665);
- }
- }
- </style>
|