2.2提交

This commit is contained in:
zoujiandong 2026-02-02 17:44:10 +08:00
parent d06ee397cf
commit a7b2a673a9
54 changed files with 3615 additions and 1317 deletions

View File

@ -67,6 +67,8 @@ export default {
uni.$emit('paySuccess',{
type:'GandanFile',
});
}else if(data.type=='BuyPoint'){
uni.navigateBack();
}
}
});

View File

@ -120,11 +120,11 @@ const api = {
},
// 积分支付列表
bonusPointsPayList(data) {
return request('/expertAPI/bonusPointsPayList', data, 'post', false);
return request('/expertAPI/bonusPointsPayList', data, 'post', true);
},
// 积分列表
bonusPointsList(data) {
return request('/expertAPI/bonusPointsList', data, 'post', false);
return request('/expertAPI/bonusPointsList', data, 'post', true);
},
getWelfarePage(data) {
@ -673,9 +673,7 @@ const api = {
welfareList(data){
return request('/expertAPI/welfareList', data, 'post', false);
},
getUGoods(data){
return request('/expertApp/getUGoods', data, 'post', false);
},
getUGoods(data){
return request('/expertAPI/getGoodsDetailU', data, 'post', false);
},
@ -688,6 +686,10 @@ const api = {
createBointsOrder(data){
return request('/expertPay/createBointsOrder', data, 'post', false);
},
receiveWelfare(data){
return request('/expertAPI/receiveWelfare', data, 'post', false);
},
}

View File

@ -28,6 +28,18 @@ const goods_api = {
},
getGoodsOrderList(data) {
return request('/expertAPI/goodsOrderList', data, 'post', true);
},
getUpanWelfareCount(data){
return request('/expertAPI/getUpanWelfareCount', data, 'post', false);
},
getGoodsOrderDetail(data) {
return request('/expertAPI/getGoodsOrder', data, 'post', true);
},
getOrderTrack(data) {
return request('/expertAPI/getOrderTrack', data, 'post', true);
},
cancelGoodsOrder(data) {
return request('/expertAPI/cancleGoodsOrder', data, 'post', true);
}
}

View File

@ -0,0 +1,94 @@
<template>
<!-- domId 是要截图的容器 id -->
<view class="my-html2canvas" :prop="domId" :change:prop="h2cRender.watchDomId">
<!-- 用于触发 renderjs 截图 -->
<text :prop="expOver" :change:prop="h2cRender.watchExpOver"></text>
</view>
</template>
<script>
export default {
props: {
domId: {
type: String,
required: true
}
},
data() {
return {
expOver: 0
}
},
methods: {
//
h2cRenderDom() {
// #ifdef H5
// H5 DOM renderDom
this.$emit('renderDomInH5')
// #endif
// #ifndef H5
// H5APP expOver renderjs
this.expOver++
// #endif
},
// renderjs callMethod
renderOver(base64) {
this.$emit('renderOver', base64)
}
}
}
</script>
<!-- renderjs 只能内联 -->
<script module="h2cRender" lang="renderjs">
import html2canvas from 'html2canvas'
export default {
data() {
return {
domIdValue: ''
}
},
methods: {
async renderDom() {
try {
const el = document.getElementById(this.domIdValue)
if (!el) {
console.error('[MyHtml2canvas] dom 未找到,请检查 domId', this.domIdValue)
return
}
const canvas = await html2canvas(el, {
width: el.offsetWidth,
height: el.offsetHeight,
x: 0,
y: 0,
useCORS: true,
scale: 2
})
const base64 = canvas.toDataURL('image/png', 1)
this.$ownerInstance.callMethod('renderOver', base64)
} catch (err) {
console.error('[MyHtml2canvas] html2canvas 失败:', err && err.message)
}
},
// script :prop domId
watchDomId(newVal) {
this.domIdValue = newVal
},
// expOver
watchExpOver(newVal) {
if (newVal !== 0) {
this.renderDom()
}
}
}
}
</script>
<style>
.my-html2canvas {
position: relative;
}
</style>

View File

@ -3,7 +3,7 @@
<view class="dialog-container" @click.stop>
<!-- 弹窗标题 -->
<view class="dialog-header">
<text class="dialog-title">{{ title }}</text>
<text class="dialog-title" :style="{ color: titleColor }">{{ title }}</text>
</view>
<!-- 弹窗内容 -->
@ -63,6 +63,10 @@
type: Boolean,
default: false
},
titleColor: {
type: String,
default: '#8B2316'
},
title: {
type: String,
default: '温馨提示'

View File

@ -1,7 +1,7 @@
<template>
<view class="emptybox">
<up-image :src="emptyImg" width="176rpx" height="204rpx" ></up-image>
<text class="empty-text">暂无数据</text>
<text class="empty-text">{{ emptyDesc }}</text>
</view>
</template>
@ -9,6 +9,12 @@
import { ref } from 'vue';
import { onShow } from "@dcloudio/uni-app";
import emptyImg from "@/static/icon_empty.png"
const props = defineProps({
emptyDesc: {
type: String,
default: '暂无数据'
}
})
</script>
<style scoped lang="scss">

File diff suppressed because it is too large Load Diff

View File

@ -2,8 +2,8 @@
"name" : "肝胆相照专家版",
"appid" : "__UNI__89F511F",
"description" : "",
"versionName" : "4.2.0",
"versionCode" : 420,
"versionName" : "4.2.2",
"versionCode" : 422,
"transformPx" : false,
"app-plus" : {
/* 5+App */
@ -166,6 +166,34 @@
}
}
}
},
"PLV-MediaPlayer" : {
"__plugin_info__" : {
"name" : "Polyv播放器插件",
"description" : "该插件封装了保利威底层播放器,是云直播和云点播插件必须的附属插件",
"platforms" : "Android,iOS",
"url" : "https://ext.dcloud.net.cn/plugin?id=4798",
"android_package_name" : "cn.shangyu.gdxzExpert",
"ios_bundle_id" : "cn.shangyu.gdxzExport",
"isCloud" : true,
"bought" : 1,
"pid" : "4798",
"parameters" : {}
}
},
"PLV-VodUniPlugin" : {
"__plugin_info__" : {
"name" : "polyv保利威视频云点播插件",
"description" : "polyv保利威视频云点播软件组件支持聊天弹幕、视频加密、多码率、去广告等还支持视频多维数据统计适用于教学录播、产品介绍片、视频门户等",
"platforms" : "Android,iOS",
"url" : "https://ext.dcloud.net.cn/plugin?id=2802",
"android_package_name" : "cn.shangyu.gdxzExpert",
"ios_bundle_id" : "cn.shangyu.gdxzExport",
"isCloud" : true,
"bought" : 1,
"pid" : "2802",
"parameters" : {}
}
}
}
},

View File

@ -573,6 +573,7 @@
"path": "myWelfareCard/exchange",
"style": {
"navigationStyle": "custom",
"softinputMode": "adjustResize",
"navigationBarTitleText": "uni-app分页",
"app": {
"bounce": "none"
@ -1332,6 +1333,16 @@
}
}
},
{
"path": "logistics/logistics",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "物流信息",
"app": {
"bounce": "none"
}
}
},
{
"path": "exchange/index",
"style": {
@ -1342,6 +1353,16 @@
}
}
},
{
"path": "exchange/exchangeDetail",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "在线兑换",
"app": {
"bounce": "none"
}
}
},
{
"path": "exchange/address_list",
"style": {
@ -1541,7 +1562,7 @@
"list": [
{
"name": "",
"path": "pages_app/myWelfare/myWelfare",
"path": "",
"query": ""
}
]

View File

@ -4,21 +4,42 @@
</template>
<script setup>
import { onMounted } from 'vue';
import { onMounted,ref} from 'vue';
import { onLoad,onUnload,onHide,onShow } from '@dcloudio/uni-app';
import navBar from '@/components/navBar/navBar.vue';
const timer=ref(null);
const count=ref(0);
const countDown=()=>{
if(timer.value){
return
}
timer.value=setInterval(()=>{
count.value++;
if(count.value>=3){
clearInterval(timer.value);
plus.runtime.quit();
}
},1000);
}
onShow(() => {
uni.showLoading({
title: '加载中...',
mask: true
});
countDown()
});
onUnload(() => {
uni.hideLoading();
if(timer.value){
clearInterval(timer.value);
}
});
onHide(() => {
uni.hideLoading();
if(timer.value){
clearInterval(timer.value);
}
});
</script>

View File

@ -523,7 +523,7 @@
url="/pages_app/changeMobile/changeMobile"
break;
case 'benefitExchange':
url="/pages_app/myWelfareCard/myWelfareCard"
url="/pages_app/myWelfareCard/myWelfareCard?from=my"
break;
case 'bankCard':
url="/pages_app/idcardAuth/bankCardList"

View File

@ -267,7 +267,7 @@
if(index==1){
navTo({
url: '/pages_app/patientVideo/patientVideo'
url: '/pages_app/patientVideo/patientVideo?from=patientClass'
})
}else if(index==2){
let url=encodeURIComponent('https://wx.igandan.com/wxPatient/index.htm#/problem?link=share&fromtype=doctor')

299
pages/upload/upload.nvue Normal file
View File

@ -0,0 +1,299 @@
<template>
<view class="wrap">
<view :class="isFull ? 'player-full' : 'player'">
<plv-player
ref="vodPlayer"
class="vod-player"
seekType=1
autoPlay=true
disableScreenCAP=false
rememberLastPosition=false
@onPlayStatus="onPlayStatus"
@onPlayError="onPlayError"
@positionChange="positionChange"
@onEnableSubtitle="onEnableSubtitle"
@onSRTTextConfig="onSRTTextConfig"
@onSRTTitle="onSRTTitle">
</plv-player>
<skin ref="skinRef"
class="skin-control"
:defaultVolume="defaultVolume"
@onPlayBtnClick="onPlayBtnClick"
@onToSeek="onToSeek"
@onFullBtnClick="onFullBtnClick"
@onHdBtnClick="onHdBtnClick"
@onRateBtnClick="onRateBtnClick"
@onVolumeChanged="onVolumeChanged"
@onScalingBtnClick="onScalingBtnClick"
@onScreenShot="onScreenShot"
@onChangeSRTBtnClick="onChangeSRTBtnClick"
@onChangeSRTSingleMode="onChangeSRTSingleMode"
@onOpenSRT="onOpenSRT">
</skin>
</view>
<view v-if="!isFull" style="padding: 20rpx;">
<input class="uni-input" style="min-height: 35px; height: 35px; border: 1px solid #cccccc;font-size: 14px;" :value="videoVid"
@input="onVidInput" placeholder="请输入视频vid" />
<button type="primary" @click="setVid()">播放</button>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue';
import { onShow } from '@dcloudio/uni-app';
//import Head from '../../components/page-head.nvue';
//import skin from '@/components/plv-player-skin/skin.nvue';
//import DragTips from '@/components/plv-player-skin/drag-tips.nvue';
const dom = weex.requireModule('dom');
var configModule = uni.requireNativePlugin("PLV-VodUniPlugin-ConfigModule")
const vod=ref(null);
const title='播放器Demo';
// 播放器组件
const vodPlayer=ref(null);
const skinRef=ref(null);
const isFull=ref(false);
const defaultVolume=ref(0.5);
const videoVid=ref('4ae3fe3ab5a2009a8d6605d81b2e3c9b_4');
onShow(() => {
configModule.setConfig({
'config': "dDzXiPJ8psA/7LvtlPgpNfdOjzKVVEYvca1QBOp2MqCVKC93YiligqqfzOzETkDmolLNBUF4vAykBuUnn+U4V9NoK9vaofwESluIMO9WSB0eWhrw+fBkn+h+OZAmwmYgHQ6fCtsggZKN6cW/FhjWAQ==", //加密串配置
},
(ret) => {
if (ret.isSuccess == true) {
uni.showToast({
title: '设置加密串成功',
icon: "none"
})
}
})
})
const onVidInput=(event)=> {
videoVid.value = event.detail.value;
};
const setVid=()=> {
if(!videoVid.value) {
uni.showToast({
title: "请输入视频Vid",
icon: "none"
})
return;
}
vodPlayer.value.setVid({
vid:videoVid.value,
level:0
}, (ret) => {
console.log(12)
console.log(ret)
text.value = JSON.stringify(ret);
if (ret.errMsg != null) {
uni.showToast({
title: ret.errMsg,
icon: "none"
})
}
});
};
const onPlayError=(e)=>{
console.log(e);
if (e.detail.errEvent != null) {
uni.showToast({
title:'playErrorEvent - '+e.detail.errEvent,
icon: "none"
})
}
};
const positionChange=(e)=>{
skinRef.value.timeUpdate(e.detail.currentPosition);
};
const onEnableSubtitle=(e)=>{
console.log("===1" + e.detail);
skinRef.value.setEnableSubtitle(e.detail.isEnableSubtitle, e.detail.isEnableDoubleSubtitle);
};
const onSRTTextConfig=(e)=>{
console.log("===1 fontColor: " + e.detail.fontColor);
skinRef.value.setSRTTextConfig(e.detail);
};
const onSRTTitle=(e)=>{
console.log("===1 onSRTTitle" + e.detail);
};
const onPlayStatus=(e)=>{
//const { skin, vodPlayer } = this;
const state = e.detail.playbackState;
const preparedToPlay = e.detail.preparedToPlay;
if (state != null) {
skinRef.value.changePlayStatus(state === 'start');
} else if (preparedToPlay != null) {
updateDuration();
updateLevels();
updateScaling();
}
};
const updateDuration=()=> {
if (vodPlayer.value) return;
vodPlayer.value.getDuration(null, ret => {
skinRef.value.updateDuration(ret.duration);
});
};
const updateLevels=()=> {
if (vodPlayer.value) return;
vodPlayer.value.getLevelNum(null, ret => {
skinRef.value.updateLevels(ret.levelNum);
});
vodPlayer.value.getCurrentLevel(null, ret => {
skinRef.value.updateCurrentLevel(ret.currentLevel);
});
};
const updateScaling=()=> {
if (vodPlayer.value) return;
vodPlayer.value.getScalingMode({}, ret => {
skinRef.value.updateScaling(ret.scalingMode);
});
};
const onPlayBtnClick=(isPlaying)=> {
if (vodPlayer.value) return;
isPlaying ? vodPlayer.value.start() : vodPlayer.value.pause();
};
const onHdBtnClick=(level)=> {
if (vodPlayer.value) return;
vodPlayer.value.changeLevel({level});
};
const onRateBtnClick=(speed)=> {
if (vodPlayer.value) return;
vodPlayer.value.setSpeed({speed});
};
const onScalingBtnClick=(scalingMode)=> {
if (vodPlayer.value) return;
vodPlayer.value.setScalingMode({scalingMode});
};
const onChangeSRTBtnClick=(srt)=> {
console.log("===1 " + srt);
if (vodPlayer.value) return;
vodPlayer.value.changeSRT(srt);
};
const onChangeSRTSingleMode=(isSingle)=> {
if (vodPlayer.value) return;
vodPlayer.value.changeSRTSingleMode(isSingle);
};
const onOpenSRT=(isOpen)=> {
if (vodPlayer.value) return;
vodPlayer.value.setOpenSRT({
openSrt: isOpen
});
};
const onFullBtnClick=(isFull)=> {
// plus.screen.unlockOrientation();
plus.navigator.setFullscreen(isFull);
if (vodPlayer.value) return;
isFull ? vodPlayer.value.changeToLandscape() : vodPlayer.value.changeToPortrait();
isFull.value = isFull;
};
const onToSeek=(time)=> {
if (vodPlayer.value) return;
vodPlayer.value.seekTo({seconds: time});
};
const onVolumeChanged=(value)=> {
if (vodPlayer.value) return;
vodPlayer.value.getVolume(null, ret => {
const changedValue = ret.volume + value;
const realValue =limit(changedValue, 0, 1);
vodPlayer.value.setVolume({volume: realValue});
skinRef.value.updateVolumeValue(realValue);
});
};
const onScreenShot=()=> {
if (vodPlayer.value) return;
vodPlayer.value.snapshot(null, result =>{
if(result.errMsg != null){
console.log(result.errMsg)
}
});
};
/**
* 控制最小值,最大值
* @param num
* @param min
* @param max
* @returns {*}
*/
const limit=(num, min, max)=> {
if (num < min) return min;
if (num > max) return max;
return num;
}
</script>
<style>
.wrap {
flex: 1;
}
.title {
height: 140rpx;
}
.player {
height: 400rpx;
}
.player-full {
flex: 1;
}
.vod-player {
flex: 1;
}
.skin-control {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1;
}
.hide {
height: 0;
}
</style>

View File

@ -1,119 +0,0 @@
<template>
<view class="content">
<view class="img-grid">
<view
v-if="tempImageList.length>0"
v-for="(img, index) in tempImageList"
:key="index"
class="img-item"
@click="preview(index)"
>
<image :src="img" mode="aspectFill" class="img" />
<view class="del" @click.stop="remove(index)">×</view>
</view>
<view v-if="tempImageList.length < maxImages" class="img-item add" @click="beforeAddImages">
<view class="plus"></view>
</view>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue'
import { pathToBase64} from "image-tools";
import { getCameraPermission } from "@/utils/permission.js";
import isAndroid from "@/utils/platform.js";
const uuid=ref('');
const answer_uuid=ref('');
const maxImages = 6;
const imgList = ref([]);
const isLock=ref(false);
const tempImageList = ref([]);
const beforeAddImages=()=>{
addImages();
};
const addImages=()=>{
console.log('执行选择图片')
uni.chooseImage({
count:6,
sizeType: ['original', 'compressed'],
sourceType: ['album','camera'],
success: (res)=>{
uni.showToast({
title: '选择图片成功',
icon: 'none'
})
//console.log(res.tempFilePaths)
// tempImageList.value = [...tempImageList.value, ...res.tempFilePaths];
// for (let i = 0; i < res.tempFilePaths.length; i++) {
// pathToBase64(res.tempFilePaths[i])
// .then((base64) => {
// console.log('base64')
// imgList.value.push(base64.split(',')[1]);
// })
// .catch((error) => {
// console.log('base64')
// console.error(error);
// });
// }
// console.log(tempImageList.value)
// console.log(imgList.value)
},
fail: (err)=>{
console.log(err)
uni.showToast({
title: '选择图片失败:'+err.errMsg,
icon: 'none'
})
//console.log(':'+err.errMsg)
}
})
}
function preview(index){
uni.previewImage({
urls:tempImageList.value,
current: index
})
}
</script>
<style>
.content{
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.img-grid{
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16rpx;
}
.img-item{
position: relative;
width:150rpx;
height: 150rpx;
border-radius: 12rpx;
overflow: hidden;
background: #f0f0f0;
}
.img{ width: 100%; height: 100%; }
.add{ display:flex; align-items:center; justify-content:center;}
.plus{ font-size: 80rpx; color:#c0c0c0; line-height: 1; }
.del{
position: absolute;
top: 8rpx;
right: 8rpx;
width: 44rpx;
height: 44rpx;
border-radius: 22rpx;
background: rgba(0,0,0,.5);
color: #fff;
text-align: center;
line-height: 44rpx;
font-size: 28rpx;
}
</style>

View File

@ -63,6 +63,8 @@
import navBar from '@/components/navBar/navBar.vue';
const freeVisible = ref(false);
const freeContent = ref('您确定是否购买?');
const product_id = ref('');
const type = ref('');
const freeClose = () => {
freeVisible.value = false;
};
@ -72,18 +74,30 @@
point: selectedPackageData.value.points
}).then(res => {
if(res.code==200){
console.log('price:'+res.data.amount);
console.log('order_id:'+res.data.order_id);
console.log('trade_no:'+res.data.trade_no);
console.log('jifen:'+res.data.point);
uni.sendNativeEvent('payPonitPage', {
msg: {
"price":res.data.amount,
"order_id":res.data.order_id,
"trade_no":res.data.trade_no,
'jifen':res.data.point,
'product_id':product_id.value,
'type':type.value,
},
});
}
});
};
onLoad(() => {
onLoad((options) => {
if(options.product_id){
product_id.value = options.product_id;
}
if(options.type){
type.value = options.type;
}
getPointUnitPrice();
});
const pointUnitPrice = ref(1);

View File

@ -20,7 +20,7 @@
<view class="label">邮箱</view>
<input class="input" v-model="email" type="text" placeholder="用于接收电子卡等信息(可选)" />
</view> -->
<view class="divider-line"></view>
<view class="form-item select-item" @click="openAreaPicker">
<view class="label">地址</view>
@ -34,6 +34,7 @@
<view class="label">详细地址</view>
<input class="input" v-model="detail" placeholder="请输入街道、门牌等详细地址信息" />
</view>
<view class="divider-line"></view>
</scroll-view>
<view class="footer-bar" @click="submit">
@ -63,28 +64,29 @@
</view>
</view>
<unidialog
:title="'确认收货信息'"
:title="'确认兑换信息'"
:visible="freeVisible"
:content="freeContent"
:titleColor="'#000'"
@close="freeClose"
@confirm="freeConfirm"
>
<template #content>
<view>
<view class="row">
<view class="left">收件人:</view>
<view class="left">收件人</view>
<view class="right">{{ receiver }}</view>
</view>
<view class="row">
<view class="left">手机号:</view>
<view class="left">手机号</view>
<view class="right">{{ mobile }}</view>
</view>
<view class="row">
<view class="left">地址:</view>
<view class="left">地址</view>
<view class="right">{{ regionText+detail }}</view>
</view>
<view class="row">
<view class="left">兑换积分:</view>
<view class="left">兑换积分</view>
<view class="right"><text class="price">0积分</text>(包邮)</view>
</view>
<view class="row">请确认此次兑换物品不退不换</view>
@ -102,6 +104,7 @@ import unidialog from '@/components/dialog/dialog.vue';
const freeVisible = ref(false)
const freeContent = ref('')
const goods_order_id = ref('')
import navTo from '@/utils/navTo';
const freeClose = () => {
freeVisible.value = false
}
@ -112,11 +115,21 @@ const freeConfirm = () => {
type: 5
}).then(res => {
if(res.code == 1 || res.code == 200){
uni.sendNativeEvent('goTabbarPage', {
msg: 'mine'
},ret => {
console.log(ret);
})
uni.showToast({
title: '兑换成功',
icon: 'none'
});
setTimeout(() => {
navTo({
url: '/pages_goods/myRedemption/myRedemption?from=upan'
});
}, 1000);
// uni.sendNativeEvent('goTabbarPage', {
// msg: 'mine'
// },ret => {
// console.log(ret);
// })
}
})
}
@ -198,13 +211,36 @@ onLoad((opts) => {
console.log(opts);
goodsUuid.value = opts.goodsUuid
goodsNum.value = opts.goodsNum
getAddress()
})
const saveAddress = () => {
uni.setStorageSync('goods_address', {
receiver: receiver.value,
mobile: mobile.value,
regionText: regionText.value,
detail: detail.value,
email: email.value
})
}
const getAddress = () => {
const address = uni.getStorageSync('goods_address')
if(address){
receiver.value = address.receiver
mobile.value = address.mobile
regionText.value = address.regionText
detail.value = address.detail
email.value = address.email
}
}
const submit = () => {
if (!receiver.value) return uni.showToast({ title: '请输入收件人', icon: 'none' })
if (!/^1\d{10}$/.test(mobile.value)) return uni.showToast({ title: '请输入正确手机号', icon: 'none' })
if (!regionText.value) return uni.showToast({ title: '请选择地址', icon: 'none' })
if (!detail.value) return uni.showToast({ title: '请输入详细地址', icon: 'none' })
saveAddress();
api.createGoodsOrder({
goodsUuid: goodsUuid.value,
goodsNum: goodsNum.value,
@ -216,6 +252,7 @@ const submit = () => {
if(res.code == 1 || res.code == 200){
freeVisible.value = true
goods_order_id.value = res.data.goods_order_id
}
})
@ -228,7 +265,7 @@ const submit = () => {
.form-item { display: flex; align-items: center; padding: 24rpx; }
.label { width: 160rpx; color: #333; font-size: 30rpx; }
.input { flex: 1; color: #333; font-size: 30rpx; }
.placeholder { color: #bbb; }
.placeholder { color: #808080;}
.divider-line { height: 2rpx; background: #eee; margin: 0 24rpx; }
.select-item { position: relative; }
.arrow { position: absolute; right: 24rpx; color: #999; font-size: 48rpx; }
@ -247,15 +284,16 @@ const submit = () => {
.picker-empty { padding: 40rpx; text-align: center; color: #999; }
.row{
display: flex;
align-items: center;
align-items: flex-start;
font-size: 28rpx;
padding: 12rpx 0;
max-width: 800rpx;
margin-left: -100rpx;
.left{
text-align: left;
max-width: 125rpx;
max-width: 142rpx;
white-space: nowrap;
width:auto!important;
}
.price{

View File

@ -7,7 +7,7 @@
<!-- 商品信息卡片 -->
<view class="product-card">
<!-- 商品描述 -->
<view class="product-title">超实用~肝胆相照知识U盘(2026年版)</view>
<view class="product-title">{{ goodsInfo.name }}</view>
<!-- 兑换信息 -->
<view class="exchange-info">
@ -52,15 +52,16 @@
<script setup>
import { ref, onMounted } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import { onShow } from '@dcloudio/uni-app';
import navBar from '@/components/navBar/navBar.vue';
import api from '@/api/api';
import goods_api from '@/api/goods_api';
import navTo from '@/utils/navTo';
const goodsUuid = ref('');
//
const remainingCount = ref(2); //
const remainingCount = ref(0); //
const exchangedCount = ref(1129); //
const quantity = ref(1); //
const goodsInfo = ref({});
@ -71,7 +72,12 @@
quantity.value += 1;
}
};
const getUpanCount = async () => {
const res = await goods_api.getUpanWelfareCount()
if (res.code == 200) {
remainingCount.value=res.data;
};
}
//
const decreaseQuantity = () => {
if (quantity.value > 1) {
@ -89,13 +95,13 @@
return;
}
if (quantity.value > remainingCount.value) {
uni.showToast({
title: '兑换数量不能超过剩余数量',
icon: 'none'
});
return;
}
// if (quantity.value > remainingCount.value) {
// uni.showToast({
// title: '',
// icon: 'none'
// });
// return;
// }
// TODO:
navTo({
@ -111,6 +117,7 @@
//
console.log(33);
console.log(res.data);
goodsInfo.value = res.data;
if (res.data) {
//remainingCount.value = res.data.remainingCount;
exchangedCount.value = res.data.times;
@ -122,10 +129,12 @@
});
};
onLoad((options) => {
remainingCount.value = options.restNum;
onShow((options) => {
//remainingCount.value = options.restNum;
//
//getUGoods();
getUpanWelfareCount();
getUpanCount();
});
</script>
@ -162,14 +171,11 @@
//
}
.main-content {
padding: 40rpx 30rpx;
}
//
.product-card {
background-color: $white;
border-radius: 16rpx;
padding: 40rpx 30rpx;
margin-bottom: 40rpx;
@ -186,7 +192,7 @@
font-size: 28rpx;
.info-left {
color: $text-secondary;
color: red;
}
.info-right {

View File

@ -110,6 +110,7 @@ const name=ref('');
const showInnerSort=ref(false);
const innerSortTitle=ref('上传时间');
import downloadStore from "@/store/downloadStoreFile.js";
import isAndroid from '@/utils/platform';
const downloadTasks=ref([]);
const downLoadtaskList=computed(()=>{
return downloadTasks.value.filter((item)=>item.status == "completed" && item.type == "zhinan").map((item)=>item.id);
@ -405,6 +406,7 @@ const viewGuideline = (cell) => {
console.log(downloadTasks.value);
downloadTasks.value.forEach(item => {
if(item.id == cell.uuid) {
// if(isAndroid){
plus.runtime.openFile(item.localPath, function(e) {
console.log('打开成功');
}, function(e) {
@ -415,6 +417,13 @@ const viewGuideline = (cell) => {
});
console.log('打开失败:' + e.message);
});
// }else{
// uni.sendNativeEvent('openDocument', {
// msg: item.localPath.replaceAll('_doc/uniapp_save/',''),
// }, ret => {
// console.log(ret);
// });
// }
// uni.openDocument({
// filePath: item.localPath,
// fileType: 'pdf',

View File

@ -1,6 +1,35 @@
<template>
<navBar title="我的二维码" v-if="!jieping"/>
<!-- <sp-html2canvas-render :useCORS="true" :allowTaint="true" domId="render-dom" ref="renderRef" @renderOver="renderOver"></sp-html2canvas-render> -->
<view class="navbox" v-if="!jieping">
<view class="status_bar"></view>
<uni-nav-bar
left-icon="left"
title="我的二维码"
@clickLeft="goBack"
color="#8B2316"
:border="false"
backgroundColor="#eeeeee"
>
<template #right>
<view class="nav-actions">
<view class="collect-img" @click="shareToggle" >
<image
class="share-img-icon"
:src="shareIcon"
mode="aspectFill"
/>
</view>
</view>
</template>
</uni-nav-bar>
</view>
<!-- <navBar title="我的二维码" v-if="!jieping"/> -->
<!-- 自己实现的 html2canvas 截图组件 -->
<MyHtml2canvas
ref="shotRef"
domId="render-dom"
@renderOver="onRenderOver"
/>
<view class="my-code-page renderDom" id="render-dom" :class="{'active':jieping}">
<!-- <webview src="https://dev-wx.igandan.com/expert/expertcodeimg?expert_uuid=9UFkll2Xo57km6224XE&fromtype=doctor"></webview> -->
<!-- 顶部导航栏 -->
@ -10,7 +39,7 @@
<scroll-view scroll-y class="page-scroll" id="pageContent">
<!-- 顶部蓝色横幅 -->
<view class="blue-banner">
<up-image :src="bgImg" width="100%" mode="widthFix" ></up-image>
<up-image :src="bgBase64 || bgImg" width="100%" mode="widthFix" ></up-image>
</view>
<!-- 白色信息卡 -->
@ -19,10 +48,17 @@
<view class="leftCircle"></view>
<view class="rightCircle"></view>
<view class="halfCircle"></view>
<view class="avatar-wrapper">
<image class="avatar" :src="docUrl+userInfo.photo" mode="aspectFill" />
<view class="star" v-if="userInfo.isStar==1">
咨询专家
</view>
<view class="name-viewne">{{ userInfo.realName }} {{ userInfo.positionName }}</view>
<view class="avatar-wrapper">
<image
class="avatar"
:src="userInfo.avatarBase64 || userInfo.localPhoto || (docUrl+userInfo.photo)"
mode="aspectFill"
/>
</view>
<view class="name-viewne">{{ userInfo.realName }} <text class="position-name">{{ userInfo.positionName }}</text></view>
<view class="org-viewne">{{ userInfo.hospitalName }}</view>
<view class="dash-viewne"></view>
<view class="slogan">
@ -31,10 +67,10 @@
</view>
<view class="contact-qr">
<view class="contact-btn">
<up-image :src="viewnkImg" width="430rpx" height="131rpx" ></up-image>
<up-image :src="viewnkBase64 || viewnkImg" width="430rpx" height="131rpx" ></up-image>
</view>
<image class="qr-img" :src="docUrl+userInfo.qrcode" mode="aspectFit" />
<image class="qr-img" :src="userInfo.localQrcode || (docUrl+userInfo.qrcode)" mode="aspectFit" />
</view>
</view>
</view>
@ -47,8 +83,8 @@
<view class="s-bottom">
<view>
<view class="descrow"><text>1</text>微信扫一扫上方二维码关注肝胆相照一家人公众号</view>
<view class="descrow"><text>2</text>点击邹建东专家工作室选择微信登录注册后直接发送随访申请</view>
<view class="descrow"><text>3</text>若未弹出随访申请发送成功提示请再次点击邹建东专家工作室发送随访申请</view>
<view class="descrow"><text>2</text>点击{{ userInfo.realName }}专家工作室选择微信登录注册后直接发送随访申请</view>
<view class="descrow"><text>3</text>若未弹出随访申请发送成功提示请再次点击{{ userInfo.realName }}专家工作室发送随访申请</view>
<view class="descrow"><text>4</text>审核通过后点击就医服务-随访交流与专家进行图文交流</view>
</view>
</view>
@ -65,34 +101,150 @@
<button class="save-btn" @click="onSave">保存到手机相册</button>
</view>
</view>
<!-- 分享弹窗 -->
<uni-popup ref="shareRef" type="bottom" safeArea backgroundColor="#fff">
<view class="share-popup">
<view class="share-title">分享到</view>
<view class="share-content">
<view class="share-item" @click="shareToWechat">
<view class="share-icon wechat-icon">
<image class="share-img" :src="wxImg" mode="aspectFill" />
</view>
<text class="share-text">微信</text>
</view>
<view class="share-item" @click="shareToMoments">
<view class="share-icon moments-icon">
<image class="share-img" :src="friendImg" mode="aspectFill" />
</view>
<text class="share-text">朋友圈</text>
</view>
<view class="share-item" @click="shareToWeibo">
<view class="share-icon weibo-icon">
<image class="share-img" :src="sinaImg" mode="aspectFill" />
</view>
<text class="share-text">新浪微博</text>
</view>
</view>
<view class="share-cancel" @click="closeShare">
<text>取消</text>
</view>
</view>
</uni-popup>
</template>
<script setup >
import { base64ToPath } from 'image-tools'
import { urlToBase64 } from '@/uni_modules/sp-html2canvas-render/utils/index.js'
import navBar from '@/components/navBar/navBar.vue'
import { onShow } from "@dcloudio/uni-app";
import spHtml2canvasRender from '@/uni_modules/sp-html2canvas-render/components/sp-html2canvas-render/sp-html2canvas-render.vue'
import { onShow,onBackPress,onLoad} from "@dcloudio/uni-app";
import { ref } from 'vue';
import MyHtml2canvas from '@/components/MyHtml2canvas.vue'
import docUrl from '@/utils/docUrl'
import bgImg from "@/static/background.jpg"
import otherHost from '@/utils/otherHost'
import shareIcon from "@/static/icon_share.png";
import sinaImg from "@/static/share_sina.png";
import wxImg from "@/static/share_weixin.png";
import friendImg from "@/static/share_wxc.png";
import logoImg from "@/static/weiboShare.png";
import isAndroid from "@/utils/platform.js";
// 使线
const bgImg = 'https://oss.igandan.com/images/expertcode_background.jpg?v=1'
import viewnkImg from "@/static/arr.png"
const userInfo = ref({})
const renderRef = ref(null)
const jieping = ref(false)
const shotRef = ref(null)
const bgBase64 = ref('')
const viewnkBase64 = ref('')
const from=ref('');
const title=ref('');
const summary=ref('参与爱肝行动,共创美好前程');
const link=ref('');
onBackPress(() => {
if(!from.value){
plus.runtime.quit();
return true;
}
});
const goBack = () => {
if(!from.value){
plus.runtime.quit();
return true;
}else{
uni.navigateBack();
}
};
onShow(()=>{
userInfo.value = uni.getStorageSync('userInfo')
onLoad((options) => {
from.value = options.from;
})
//
// base64 html2canvas
onShow(async () => {
const info = uni.getStorageSync('userInfo') || {}
console.log('[myCode] onShow userInfo:', info)
title.value = '不方便到医院就诊,'+info.realName+'医生在肝胆相照平台帮助您!';
link.value = otherHost+'/expert/expertcodeimg?expert_uuid='+info.uuid+'&fromtype=doctor'
// base64
if (!bgBase64.value) {
try {
console.log('[myCode] 准备将背景图转为 base64:', bgImg)
const bg = await urlToBase64(bgImg, 'jpg')
bgBase64.value = bg
console.log('[myCode] 背景图转 base64 成功,长度:', bg && bg.length)
} catch (e) {
console.error('[myCode] 背景图转 base64 失败:', e)
}
}
// base64
if (!viewnkBase64.value) {
try {
console.log('[myCode] 准备将按钮图转为 base64:', viewnkImg)
const btn = await urlToBase64(viewnkImg, 'png')
viewnkBase64.value = btn
console.log('[myCode] 按钮图转 base64 成功,长度:', btn && btn.length)
} catch (e) {
console.error('[myCode] 按钮图转 base64 失败:', e)
}
}
// base64 avatarBase64使
if (info.photo && !info.avatarBase64) {
const avatarUrl = docUrl + info.photo
try {
console.log('[myCode] 准备将头像转为 base64:', avatarUrl)
const avatarBase64 = await urlToBase64(avatarUrl, 'jpg')
info.avatarBase64 = avatarBase64
console.log('[myCode] 头像转 base64 成功,长度:', avatarBase64 && avatarBase64.length)
} catch (e) {
console.error('[myCode] 头像转 base64 失败:', e)
}
}
// base64 localQrcode使
if (info.qrcode && !info.localQrcode) {
const qrUrl = docUrl + info.qrcode
try {
console.log('[myCode] 准备将二维码转为 base64:', qrUrl)
const qrBase64 = await urlToBase64(qrUrl, 'png')
info.localQrcode = qrBase64
console.log('[myCode] 二维码转 base64 成功,长度:', qrBase64 && qrBase64.length)
} catch (e) {
console.error('[myCode] 二维码转 base64 失败:', e)
}
}
userInfo.value = info
})
//
const handleSaveError = (err) => {
if (err.errMsg && (err.errMsg.includes('auth deny') || err.errMsg.includes('authorize'))) {
if (err && err.errMsg && (err.errMsg.includes('auth deny') || err.errMsg.includes('authorize'))) {
uni.showModal({
title: '权限提示',
content: '需要相册权限才能保存图片,请在设置中开启权限',
content: '需要相册权限才能保存图片,请在系统设置中开启相册权限',
showCancel: false,
confirmText: '知道了'
});
@ -104,56 +256,294 @@ const handleSaveError = (err) => {
});
}
};
//
const onSave = () => {
jieping.value = true //
const that = this
setTimeout(()=>{
var pages = getCurrentPages(); //
var page = pages[pages.length - 1];
var bitmap = null;
var currentWebview = page.$getAppWebview();
bitmap = new plus.nativeObj.Bitmap('amway_img');// webviewBitmap
currentWebview.draw(bitmap, function() {
let rand = Math.floor(Math.random() * 10000)
let saveUrl = '_doc/' + rand + 'a.jpg'
bitmap.save(saveUrl, {}, function(i) {
console.log('[myCode] onSave 点击,准备开始截图')
// 使 html2canvas renderjs
jieping.value = true
//
if (shotRef.value && shotRef.value.h2cRenderDom) {
shotRef.value.h2cRenderDom()
} else {
console.error('[myCode] shotRef 或 h2cRenderDom 不存在')
jieping.value = false
uni.showToast({
title: '截图组件未准备好',
icon: 'none'
})
}
};
// base64
const onRenderOver = (base64) => {
console.log('[myCode] onRenderOver base64 长度:', base64 && base64.length)
if (!base64) {
jieping.value = false
uni.showToast({
title: '生成图片失败',
icon: 'none'
})
return
}
base64ToPath(base64)
.then((res) => {
const path = res.path || res
console.log('[myCode] base64ToPath 转换成功path:', path)
uni.saveImageToPhotosAlbum({
filePath: i.target,
success: function() {
filePath: path,
success() {
uni.showToast({
title: '保存图片成功',
mask: false,
duration: 1500
});
jieping.value = false //
})
},
fail(err) {
console.error('[myCode] 保存到相册失败:', err)
handleSaveError(err)
},
complete() {
jieping.value = false
}
})
})
.catch((err) => {
console.error('[myCode] base64ToPath 失败:', err)
handleSaveError(err)
jieping.value = false
})
}
});
}, function(e) {
console.log('保存图片失败:' + JSON.stringify(e));
jieping.value = false //
});
}, function(e) {
console.log('截屏绘制图片失败:' + JSON.stringify(e));
jieping.value = false //
});
},100)
const shareRef = ref();
// APP
const shareToggle = () => {
shareRef.value.open();
};
// const onSave = () => {
// //jieping.value = true //
// renderRef.value.h2cRenderDom();
// };
const renderOver = (e) => {
// ebase64
console.log("==== renderOver :", e);
base64ToPath(e).then((res) => {
console.log("==== path :", res);
//
const closeShare = () => {
shareRef.value.close();
};
//
const shareToWechat = () => {
// #ifdef APP-PLUS
// 使
uni.downloadFile({
url:'https://doc.igandan.com/app/html/img/2016/20160714132557.png',
success: function (res) {
uni.compressImage({
src: res.tempFilePath,
quality: 60,
success: function (res2) {
uni.share({
provider: "weixin",
scene: "WXSceneSession",
type: 0,
title: title.value,
summary: summary.value,
href: link.value,
imageUrl: res2.tempFilePath,
success: function (res) {
console.log("success:" + JSON.stringify(res));
},
fail: function (err) {
console.log("fail:" + JSON.stringify(err));
},
});
},
});
},
});
// uni.share({
// provider: "weixin",
// scene: "WXSceneSession",
// type: 0,
// title: videoInfo.value.name,
// summary: videoInfo.value.note,
// href: shareLink.value,
// imageUrl: docUrl + videoInfo.value.imgpath,
// success: function (res) {
// //console.log("success:" + JSON.stringify(res));
// },
// fail: function (err) {
// //console.log("fail:" + JSON.stringify(err));
// },
// });
// #endif
// #ifdef H5
// H5
if (navigator.share) {
navigator
.share({
title: "肝胆相照APP",
text: "专业的医疗健康平台,快来下载体验吧!",
url: shareLink.value,
})
.then(() => {
uni.showToast({
title: "分享成功",
icon: "success",
});
})
.catch(() => {
uni.showToast({
title: "分享失败",
icon: "none",
});
});
} else {
//
uni.setClipboardData({
data:
"肝胆相照APP - 专业的医疗健康平台,快来下载体验吧!\n下载链接" +
shareLink.value,
success: () => {
uni.showToast({
title: "已复制到剪贴板",
icon: "success",
});
},
});
}
// #endif
// #ifdef MP-WEIXIN
//
uni.showShareMenu({
withShareTicket: true,
menus: ["shareAppMessage", "shareTimeline"],
});
// #endif
closeShare();
};
//
const shareToMoments = () => {
// #ifdef APP-PLUS
uni.downloadFile({
url: 'https://doc.igandan.com/app/html/img/2016/20160714132557.png',
success: function (res) {
uni.compressImage({
src: res.tempFilePath,
quality: 60,
success: function (res2) {
uni.share({
provider: "weixin",
scene: "WXSceneTimeline",
type: 0,
title: title.value,
summary: summary.value,
href: link.value,
imageUrl: res2.tempFilePath,
success: function (res) {
//console.log("success:" + JSON.stringify(res));
},
fail: function (err) {
//console.log("fail:" + JSON.stringify(err));
},
});
},
});
},
});
// #endif
// #ifdef H5
//
uni.setClipboardData({
data: "肝胆相照APP - 专业的医疗健康平台,快来下载体验吧!\n下载链接https://www.igandan.com",
success: () => {
uni.showToast({
title: "已复制到剪贴板,可分享到朋友圈",
icon: "success",
});
},
});
// #endif
// #ifdef MP-WEIXIN
uni.showShareMenu({
withShareTicket: true,
menus: ["shareAppMessage", "shareTimeline"],
});
// #endif
closeShare();
};
//
const shareToWeibo = () => {
// #ifdef APP-PLUS
uni.share({
provider: "sinaweibo",
type: 0,
title: title.value,
summary: summary.value,
href: link.value,
imageUrl: logoImg,
success: function (res) {
//console.log("");
},
fail: function (err) {
//console.log("fail:" + JSON.stringify(err));
},
});
// plus.share.sendWithSystem({
// type: 'text',
// content: 'APP - \nhttps://www.igandan.com'
// }, () => {
// uni.showToast({
// title: '',
// icon: 'success'
// })
// }, (err) => {
// console.log('', err)
// uni.showToast({
// title: '',
// icon: 'none'
// })
// })
// #endif
// #ifdef H5
//
uni.setClipboardData({
data: "肝胆相照APP - 专业的医疗健康平台,快来下载体验吧!\n下载链接https://www.igandan.com",
success: () => {
uni.showToast({
title: "已复制到剪贴板,可分享到微博",
icon: "success",
});
},
});
// #endif
closeShare();
};
</script>
<style lang="scss" scoped>
.share-img {
width: 100rpx;
height: 100rpx;
}
.share-img-icon {
width: 40rpx;
height:40rpx;
}
.nav-actions {
display: flex;
align-items: center;
justify-content: center;
}
.my-code-page {
min-height: 100vh;
background-color: #0d7dfd;
@ -240,7 +630,7 @@ const renderOver = (e) => {
}
.page-scroll {
margin-top: calc(var(--status-bar-height) + 44px);
height: calc(100vh - var(--status-bar-height) - 44px);
// height: calc(100vh - var(--status-bar-height) - 44px);
padding-bottom: 140rpx;
}
@ -265,7 +655,7 @@ const renderOver = (e) => {
.qr-card {
position: relative;
margin: 76rpx 30rpx 30rpx;
margin: -80rpx 30rpx 30rpx;
background: #ffffff;
border-radius: 20rpx;
padding: 140rpx 30rpx 30rpx;
@ -289,6 +679,22 @@ const renderOver = (e) => {
border-radius: 50%;
background-color: #0d7dfd;
}
.star{
position: absolute;
top: 48rpx;
height: 40rpx;
padding:0 16rpx;
left: 50%;
transform: translateX(-50%);
background-color:#ff9f1a;
color: #fff;
border-radius: 20rpx;
display: flex;
align-items: center;
justify-content: center;
z-index:10;
font-size: 24rpx;
}
.halfCircle{
border-radius: 50%;
position: absolute;
@ -326,13 +732,17 @@ const renderOver = (e) => {
.name-viewne {
text-align: center;
font-size: 34rpx;
font-size: 36rpx;
color: #1a76d2;
font-weight: bold;
margin-top: 10rpx;
.position-name{
font-weight: normal;
}
}
.org-viewne {
text-align: center;
font-size: 28rpx;
font-size: 36rpx;
color: #4a90e2;
margin-top: 16rpx;
}
@ -414,4 +824,158 @@ const renderOver = (e) => {
font-weight: normal;
}
}
/* 分享弹窗样式 */
.share-popup {
background-color: #fff;
border-radius: 20rpx 20rpx 0 0;
padding: 40rpx 0 0;
}
.share-title {
text-align: center;
font-size: 32rpx;
color: #333;
margin-bottom: 40rpx;
font-weight: 500;
}
.share-content {
display: flex;
justify-content: space-around;
padding: 0 40rpx 40rpx;
}
.share-item {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
}
.share-icon {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 20rpx;
}
.wechat-icon {
background-color: #07c160;
}
.moments-icon {
background-color: #07c160;
}
.weibo-icon {
background-color: #e6162d;
}
.qq-icon {
background-color: #12b7f5;
}
.share-icon-text {
font-size: 50rpx;
color: #fff;
font-weight: bold;
}
.share-text {
font-size: 24rpx;
color: #666;
}
.share-cancel {
height: 100rpx;
display: flex;
align-items: center;
justify-content: center;
border-top: 1rpx solid #f0f0f0;
font-size: 32rpx;
color: #333;
}
.share-cancel:active {
background-color: #f5f5f5;
}
//
.delete-modal-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
}
.delete-modal-content {
width: 600rpx;
background-color: #fff;
border-radius: 24rpx;
padding: 60rpx 40rpx 40rpx;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.15);
}
.delete-modal-title {
font-size: 36rpx;
font-weight: 600;
color: #333;
text-align: center;
margin-bottom: 30rpx;
}
.delete-modal-text {
font-size: 28rpx;
color: #666;
text-align: center;
line-height: 1.6;
margin-bottom: 50rpx;
word-break: break-all;
}
.delete-modal-buttons {
display: flex;
gap: 20rpx;
}
.delete-modal-btn {
flex: 1;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 12rpx;
font-size: 32rpx;
font-weight: 500;
transition: all 0.3s ease;
}
.cancel-btn {
background-color: #f5f5f5;
color: #333;
&:active {
background-color: #e0e0e0;
}
}
.confirm-btn {
background-color: #8b2316;
color: #fff;
&:active {
background-color: #6b1a0f;
}
}
</style>

View File

@ -147,11 +147,11 @@
<!-- 底部导航 -->
<view class="bottom-nav">
<view class="nav-item" @click="goToPointsCoupon">
<!-- <view class="nav-icon">🎫</view> -->
<!-- <view class="nav-item" @click="goToPointsCoupon">
<view class="nav-icon">🎫</view>
<up-image :src="pointImg" width="44rpx" height="44rpx" ></up-image>
<text class="nav-text">积分券</text>
</view>
</view> -->
<view class="nav-item active" @click="goToBuyPoints">
<!-- <view class="nav-icon">📷</view> -->
<up-image :src="buyPointImg" width="44rpx" height="44rpx" ></up-image>
@ -177,11 +177,11 @@
</view>
<view class="signcontent">
<view class="day">今天是我们相识的第{{signInfo.gdxzday}}</view>
<view class="signtotal">本周共签到{{signInfo.totalDay}}</view>
<view class="signcontinue">连续签到{{signInfo.continuous_day}}</view>
<view class="signtotal">本周共签到<text class="day-red" decode="true">&nbsp;{{signInfo.totalDay}}&nbsp;</text></view>
<view class="signcontinue">连续签到<text class="day-red" decode="true">&nbsp;{{signInfo.continuous_day}}&nbsp;</text></view>
<view class="tip">连续签到获取更多积分</view>
<view class="news twoline" @click.stop="goNews">
{{signInfo.news.summary}}
{{signInfo.news.title}}
</view>
</view>
</view>
@ -225,7 +225,8 @@ import signImg from "@/static/sign_in_bng_big.png"
const showSign = ref(false)
const signInfo=reactive({
news:{
summary:''
summary:'',
title:''
}
})
// -
@ -297,10 +298,10 @@ const performCheckin = () => {
//
setTimeout(() => {
uni.showToast({
title: "签到成功 +2积分",
icon: "none",
});
// uni.showToast({
// title: " +2",
// icon: "none",
// });
//showSign.value = true;
//
getMyBonusPoints();
@ -315,7 +316,7 @@ const goNews=()=>{
const encoded = encodeURIComponent(url);
navTo({
url: `/pages_app/webview/webview?url=${encoded}`
url: `/pages_app/webview/webview?url=${encoded}&type=news&share=1&sharetitle=${signInfo.news.title}`
});
}
@ -355,10 +356,12 @@ try {
//
getMyBonusPoints();
getBonusPointsList();
uni.showToast({
title: '签到成功,获得'+res.bonuspoints+'积分',
icon: 'none'
});
// uni.showToast({
// title: ''+res.bonuspoints+'',
// icon: 'none'
// });
console.log(res)
console.log(123)
Object.assign(signInfo,res);
} else {
uni.showToast({
@ -962,7 +965,8 @@ onMounted(() => {
top: calc(var(--status-bar-height) + 44px + 392rpx + 120rpx);
left: 0;
right: 0;
height: calc(100vh - calc(var(--status-bar-height) + 44px + 392rpx + 120rpx));
height: calc(100vh - calc(var(--status-bar-height) + 44px + 392rpx + 120rpx + 145rpx));
z-index: 10;
bottom: 100rpx;
background-color: #ffffff;
@ -1011,7 +1015,7 @@ onMounted(() => {
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1rpx solid #f0f0f0;
border-bottom: 2rpx solid #eee;
transition: background-color 0.3s ease;
}
@ -1355,13 +1359,18 @@ onMounted(() => {
.signwrap .signtotal{
margin-top: 30rpx;
text-align: center;
font-size: 30rpx;
font-size:28rpx;
color:#999;
}
.signwrap .signcontinue{
font-size: 30rpx;
font-size: 28rpx;
color:#999;
text-align: center;
}
.signwrap .day-red{
color:red;
font-size: 34rpx;
}
.signwrap .signcontent .tip{
margin-top: 40rpx;
color:red;
@ -1370,7 +1379,7 @@ onMounted(() => {
}
.signwrap .signcontent .news{
margin: 208rpx 60rpx 0;
height: 100rpx;
height:86rpx;
font-size: 30rpx;
}
.signwrap .signbg{

View File

@ -28,7 +28,7 @@
<view class="segmented-control">
<view
class="tab-item"
:class="{ active: activeTab === 0 }"
:class="{ active: activeTab == 0 }"
@click="switchTab(0)"
>
<text class="tab-text">领取福利</text>
@ -36,7 +36,7 @@
<view class="divider"></view>
<view
class="tab-item"
:class="{ active: activeTab === 1 }"
:class="{ active: activeTab == 1 }"
@click="switchTab(1)"
>
<text class="tab-text">使用福利</text>
@ -44,25 +44,25 @@
<view class="divider"></view>
<view
class="tab-item"
:class="{ active: activeTab === 2 }"
:class="{ active: activeTab == 2 }"
@click="switchTab(2)"
>
<text class="tab-text">兑福利卡</text>
</view>
</view>
<!-- v-if="(benefit.name != 'upan') || (getFirstNum(benefit.left_result) > 0 && benefit.name == 'upan')" -->
<!-- 福利卡片列表 -->
<view class="scrollbox">
<scroll-view class="benefits-list" scroll-y="true" :show-scrollbar="false">
<scroll-view class="scrollbox" scroll-y="true" :show-scrollbar="false">
<view
class="benefit-card"
v-show="(benefit.name != 'upan') || (getFirstNum(benefit.left_result) > 0 && benefit.name == 'upan')"
v-for="(benefit, index) in benefitsList"
:key="index"
:class="fotmatType(benefit.name)"
@click="claimBenefit(benefit)"
:class="fotmatType(benefit)"
>
<view class="card-title">{{ benefit.title }}</view>
<view class="card-title" :class="fotmatType(benefit)">{{ benefit.title }}</view>
<!-- <view class="card-bg">
</view> -->
@ -70,7 +70,8 @@
<image :src="jifenBgImg" mode="widthFix" class="card-img" v-if="benefit.name == 'jifen'"></image>
<image :src="videoImg" mode="widthFix" class="card-img" v-if="benefit.name == 'video'"></image>
<image :src="kejianImg" mode="widthFix" class="card-img" v-if="benefit.name == 'kejian'"></image>
<image :src="upanImg" mode="widthFix" class="card-img" v-if="benefit.name == 'upan'"></image>
<image :src="upanImg" mode="widthFix" class="card-img" v-if="benefit.name == 'upan' && (!(benefit.right_tip =='已领取' || benefit.right_result =='已领取') || activeTab == 1)"></image>
<image :src="upanNoimg" mode="widthFix" class="card-img" v-if="benefit.name == 'upan' && ((benefit.right_tip =='已领取' || benefit.right_result =='已领取') && activeTab == 0)"></image>
<image :src="wanfangImg" mode="widthFix" class="card-img" v-if="benefit.name == 'wanfang'"></image>
<image :src="wenxianImg" mode="widthFix" class="card-img" v-if="benefit.name == 'daicha'"></image>
<view class="card-details">
@ -78,17 +79,19 @@
<text class="condition">{{ benefit.left_tip }}</text>
<text class="requirement">{{ benefit.left_result }}</text>
</view>
<view class="right-section">
<view class="right-section" @click="claimBenefit(benefit)">
<text class="reward-type">{{ benefit.right_tip }}</text>
<text class="reward-value">{{ benefit.right_result }}</text>
<text class="reward-value" v-if="activeTab == 0 && !benefit.flag && benefit.name != 'upan'">{{ benefit.right_result }}</text>
<text class="reward-value" v-else-if="activeTab == 0 && benefit.name == 'upan' && !(benefit.right_tip =='已领取' || benefit.right_result =='已领取') && benefit.right_result !='立即领取'">{{ benefit.right_result }}</text>
<!-- <text class="reward-value" v-if="activeTab == 1">{{ benefit.right_result }}</text> -->
</view>
</view>
<view class="panbox" v-if="benefit.name == 'upan'">知识U盘</view>
<view class="panbox" :class="{'disabled': ((benefit.right_tip =='已领取' || benefit.right_result =='已领取') && activeTab== 0)}" v-if="benefit.name == 'upan'">知识U盘</view>
</view>
</view>
</scroll-view>
</view>
<!-- 底部导航栏 -->
<view class="bottom-nav">
@ -112,7 +115,7 @@
<script setup>
import { ref, onMounted } from 'vue';
import {onShow,onBackPress} from '@dcloudio/uni-app';
import {onShow,onBackPress,onLoad,onHide} from '@dcloudio/uni-app';
import docUrl from '@/utils/docUrl.js';
onBackPress(() => {
plus.runtime.quit();
@ -132,6 +135,7 @@
import upanImg from "@/static/flupan_big2.png"
import wanfangImg from "@/static/flwanfang_big.png"
import wenxianImg from "@/static/flwen_big.png"
import upanNoimg from "@/static/flupannull_big.png"
const showDialog = ref(false);
const content = ref('肝胆相照平台协助查找文献次数已经用完,谢谢您的支持!');
const confirmDialog = () => {
@ -195,13 +199,21 @@
icon: 'none'
});
};
const fotmatType = (name) => {
const fotmatType = (benefit) => {
let name = benefit.name;
let name1 = benefit.right_tip;
let name2 = benefit.right_result;
if(name == 'video'){
return 'video';
}else if(name == 'kejian'){
return 'kejian';
}else if(name == 'upan'){
if((name1 == '已领取' && name2 == '已领取') && activeTab.value == 0){
return 'upan_disabled';
}else{
return 'upan';
}
}else if(name == 'wanfang'){
return 'wanfang';
}else if(name=='jifen'){
@ -213,19 +225,32 @@
const switchTab = (index) => {
if (index === 0) {
if (index == 0) {
activeTab.value = index;
getWelfarePage();
} else if (index === 1) {
} else if (index == 1) {
activeTab.value = index;
useWelfarePage();
} else if (index === 2) {
} else if (index == 2) {
uni.setStorageSync('lookWelfare', '');
navTo({
url: '/pages_app/myWelfareCard/myWelfareCard'
url: '/pages_app/myWelfareCard/myWelfareCard?from=myWelfare'
});
}
};
onLoad((options) => {
getWelfarePage();
});
onHide(() => {
uni.setStorageSync('lookWelfare', '');
});
onShow(() => {
let lookWelfare = uni.getStorageSync('lookWelfare');
if(lookWelfare){
activeTab.value =1;
switchTab(activeTab.value);
}
});
const claimBenefit = (benefit) => {
console.log(benefit);
console.log(activeTab.value);
@ -243,8 +268,9 @@
url: '/pages_app/ppt/ppt'
});
}else if(benefit.name == 'upan'){
let num = getFirstNum(benefit.left_result) || benefit.num;
navTo({
url: '/pages_app/buyUpan/buyUpan?restNum='+benefit.num
url: '/pages_app/buyUpan/buyUpan?restNum='+num
});
}else if(benefit.name == 'wanfang'){
@ -276,6 +302,11 @@
//}
}
}else if(activeTab.value == 0){
if(benefit.flag){
receiveWelfare(benefit.name);
}
}
};
@ -299,7 +330,7 @@
// console.log(ret);
// })
navTo({
url: '/pages_app/myCode/myCode'
url: '/pages_app/myCode/myCode?from=myWelfare'
})
};
const goRules = () => {
@ -308,6 +339,40 @@
url: '/pages_app/webview/webview?url='+encodeURIComponent('https://doc.igandan.com/app/integral/integral_welfare.html')+'&title=福利规则'
})
};
const receiveWelfare = (name) => {
let type = '';
if(name == 'jifen'){
type = 0;
}else if(name == 'video'){
type = 1;
}else if(name == 'kejian'){
type = 2;
}else if(name == 'upan'){
type = 5;
}else if(name == 'wanfang'){
return false;
}else if(name == 'daicha'){
return false;
}
api.receiveWelfare({
type: type
}).then(res => {
if(res.code == 200){
uni.showToast({
title:'领取成功',
icon: 'success'
});
getWelfarePage();
}
})
}
const getFirstNum = (str) => {
if(!str) return '';
let num = str.substring(0,1);
return Number(num);
}
const useWelfarePage = () => {
api.useWelfarePage().then(res => {
if (res.code === '200' && res.data) {
@ -353,9 +418,7 @@
});
};
onMounted(() => {
getWelfarePage();
});
</script>
<style lang="scss" scoped>
@ -374,9 +437,9 @@
.benefits-page {
min-height: 100vh;
height: 100vh;
background-color: $bg-color;
padding-top: $nav-height; //
}
.status-bar {
@ -461,7 +524,7 @@
display: flex;
align-items: center;
padding: 0 30rpx;
border-bottom: 1rpx solid $border-color;
border-bottom: 1rpx solid #eee;
.tab-item {
flex: 1;
@ -489,37 +552,39 @@
.divider {
width: 2rpx;
height: 40rpx;
background-color: $divider-color;
background-color:#eee;
}
}
.scrollbox{
position: fixed;
top: calc(#{$nav-height} + #{$segmented-height});
left: 30rpx;
right: 30rpx;
width:100%;
top: calc(var(--status-bar-height) + 44px + 82rpx);
height:calc(100vh - var(--status-bar-height) - 44px - 82rpx - 100rpx);
box-sizing: border-box;
bottom: $bottom-nav-height;
margin: 30rpx 0 ;
overflow-y: scroll;
// bottom: 100rpx;
padding-bottom: 50rpx;
margin: 30rpx 0 0;
}
.benefits-list {
.benefit-card {
background: $white;
border-radius: 20rpx;
padding: 30rpx;
margin-bottom: 30rpx;
margin:0 30rpx 30rpx;
position: relative;
overflow: hidden;
border:2rpx solid #fff;
&.jifen{
border:2rpx solid #ffad17;
border:2rpx solid #ef828f;
background:#feeae9;
}
&.wenxian{
border:2rpx solid #33c966;
background:#fdeafe;
background:#efffe9;
}
&.video{
border:2rpx solid #ff951d;
@ -548,7 +613,33 @@
left:20rpx;
z-index:0;
}
.card-title {
font-size: 32rpx;
margin-bottom: 30rpx;
line-height: 1.4;
&.jifen{
color: #ef828f;
}
&.video{
color: #ff951d;
}
&.kejian{
color: #f17dff;
}
&.upan{
color: #40cdc5;
}
&.upan_disabled{
color: #cccccc;
}
&.wanfang{
color: #4aa2fe;
}
&.wenxian{
color: #33c966;
}
}
.card-content {
margin-top: 30rpx;
position: relative;
@ -563,13 +654,7 @@
height: 100%;
}
.card-title {
font-size: 32rpx;
color: $white;
font-weight: 600;
margin-bottom: 30rpx;
line-height: 1.4;
}
.panbox{
margin-top: 20rpx;
@ -582,6 +667,9 @@
border-radius: 10rpx;
padding: 0 20rpx;
text-align: center;
&.disabled{
background: #cccccc;
}
}
.card-details {
position: relative;
@ -591,7 +679,28 @@
align-items: center;
padding:0 40rpx;
height: 220rpx;
.left-section,
.left-section{
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
.condition,
.reward-type {
font-size: 32rpx;
color: rgba(255, 255, 255, 11);
}
.requirement,
.reward-value {
margin-top: 8rpx;
font-size: 42rpx;
color: $white;
font-weight: bold;
}
.requirement{
margin-top: 40rpx;
}
}
.right-section {
display: flex;
flex-direction: column;
@ -639,7 +748,7 @@
background-color: #FF9800;
}
}
}
.bottom-nav {
position: fixed;

View File

@ -59,7 +59,7 @@
<!-- 空数据状态 -->
<view v-if="!loading && filteredList.length === 0" class="empty-wrap">
<text class="empty-text">暂无数据</text>
<empty />
</view>
<!-- 加载更多提示 -->
@ -68,9 +68,9 @@
</view>
<!-- 没有更多数据提示 -->
<view v-if="isLastPage && filteredList.length > 0" class="no-more">
<!-- <view v-if="isLastPage && filteredList.length > 0" class="no-more">
<text>没有更多数据了</text>
</view>
</view> -->
</scroll-view>
</view>
</template>
@ -80,6 +80,7 @@
import navBar from '@/components/navBar/navBar.vue';
import api from '@/api/api';
import dayjs from 'dayjs';
import empty from '@/components/empty/empty.vue';
// Tab0: , 1: , 2:
const activeTab = ref(1);
@ -321,7 +322,7 @@
right: 0;
top: calc(var(--status-bar-height) + 44px + $segmented-height + $table-header-height);
height: calc(100vh - var(--status-bar-height) - 44px - $segmented-height - $table-header-height);
background-color: #f5f5f5;
background-color: #fff;
}
//
@ -330,8 +331,8 @@
justify-content: space-between;
align-items: center;
padding: 24rpx 30rpx;
border-bottom: 1rpx solid #f0f0f0;
background-color: #f5f5f5;
border-bottom: 2rpx solid #eee;
// background-color: #f5f5f5;
font-size: 28rpx;
color: $text-primary;

View File

@ -13,13 +13,13 @@
<view class="exchange-page">
<!-- 顶部红色横幅 -->
<view class="top-banner">
<view class="top-banner" @click="goWelfare">
<image :src="bgImg" mode="widthFix" class="bg-img"></image>
<view class="banner-text">
<view class="line1">已兑换{{ exchangedCount }}</view>
<view class="line2" @click="goMyWelfare">查看现有权益</view>
<view class="line2" @click.stop="goWelfare">查看现有权益</view>
</view>
<view class="help-btn" @click="showHelp">帮助说明</view>
<view class="help-btn" @click.stop="showHelp">帮助说明</view>
</view>
<!-- 使用统一的自定义居中模态框 -->
@ -40,20 +40,20 @@
</view>
<!-- 输入提示 -->
<!-- <text class="paste-action" @click="pasteFromClipboard">粘贴</text> -->
<view class="tips">请输入16位福利卡密码不区分大小写</view>
<view class="tips">请输入16位福利卡密码不区分大小写<text class="paste-action" @click="fillByText" v-if="hasPaste">粘贴</text> </view>
<!-- 四段输入框 -->
<view class="code-inputs">
<input class="code-box" type="text" v-model="code1" maxlength="4" placeholder="" :focus="f1" @input="handleInput(1, $event)" @paste="handlePaste"/>
<input class="code-box" type="text" v-model="code2" maxlength="4" placeholder="" :focus="f2" @input="handleInput(2, $event)"/>
<input class="code-box" type="text" v-model="code3" maxlength="4" placeholder="" :focus="f3" @input="handleInput(3, $event)"/>
<input class="code-box" type="text" v-model="code4" maxlength="4" placeholder="" :focus="f4" @input="handleInput(4, $event)"/>
<input :adjust-position="false" class="code-box" type="text" v-model="code1" maxlength="4" placeholder="" :focus="f1" @input="handleInput(1, $event)" @paste="handlePaste"/>
<input :adjust-position="false" class="code-box" type="text" v-model="code2" maxlength="4" placeholder="" :focus="f2" @input="handleInput(2, $event)" />
<input :adjust-position="false" class="code-box" type="text" v-model="code3" maxlength="4" placeholder="" :focus="f3" @input="handleInput(3, $event)"/>
<input :adjust-position="false" class="code-box" type="text" v-model="code4" maxlength="4" placeholder="" :focus="f4" @input="handleInput(4, $event)"/>
</view>
<!-- 按钮 -->
<view class="btn-wrapper">
<button class="submit-btn" :disabled="!isFull" @click="submit">立即兑换</button>
<button class="submit-btn" @click="submit">立即兑换</button>
</view>
</view>
</template>
@ -63,7 +63,9 @@
import api from '@/api/api';
import navBar from '@/components/navBar/navBar.vue'
import bgImg from '@/static/fulicard_bg.png'
const exchangedCount = ref(5)
const exchangedCount = ref(0)
const hasPaste = ref(false)
const pasteText = ref('')
const code1 = ref('')
const code2 = ref('')
const code3 = ref('')
@ -71,18 +73,23 @@
const f1 = ref(true)
const f2 = ref(false)
const f3 = ref(false)
const f4 = ref(false)
const f4 = ref(false);
import { onLoad } from '@dcloudio/uni-app'
const helpVisible = ref(false)
const centerVisible = ref(false)
const centerText = ref('')
const centerHelp = ref(false)
const centerHelp = ref(false);
const isabled = ref(true);
const isFull = computed(() => (code1.value+code2.value+code3.value+code4.value).length === 16)
const goBack = () => {
uni.navigateBack({
fail() {
uni.redirectTo({ url: '/pages/index/index' })
}
onLoad((opts) => {
exchangedCount.value = opts.num
pasteFromClipboard()
})
const goWelfare = () => {
uni.setStorageSync('lookWelfare', 'useWelfare');
uni.redirectTo({
url:
'/pages_app/myWelfare/myWelfare?from=useWelfare'
})
}
const showHelp = () => {
@ -116,9 +123,19 @@
if (sanitized.length === 4 && idx < 4) {
nextTick(() => setFocus(idx + 1))
}
if(code1.value.length+code2.value.length+code3.value.length+code4.value.length==16){
isFull.value = true
console.log(1111)
}else{
isFull.value = false
console.log(2222)
}
}
const submit = () => {
if (!isFull.value) return
if(code1.value.length+code2.value.length+code3.value.length+code4.value.length!=16){
uni.showToast({ title: '请输入16位福利卡密码', icon: 'none' })
return
}
const code = (code1.value+code2.value+code3.value+code4.value).toUpperCase()
uni.showToast({ title: '兑换中: '+ code, icon: 'none' })
api.exchangeWelfareCard({password: code}).then(res => {
@ -138,6 +155,7 @@
const handlePaste = (e) => {
const text = (e.clipboardData && e.clipboardData.getData('text')) || ''
fillByText(text)
//
e && e.preventDefault && e.preventDefault()
}
@ -146,18 +164,30 @@
const pasteFromClipboard = () => {
uni.getClipboardData({
success: (res) => {
fillByText(res.data || '')
if(res.data.length>0){
hasPaste.value = true
pasteText.value = res.data
}
}
})
}
const fillByText = (raw) => {
const v = String(raw || '').replace(/[^a-zA-Z0-9]/g, '').toUpperCase().slice(0, 16)
const v = pasteText.value.replace(/[^a-zA-Z0-9]/g, '').toUpperCase().slice(0, 16);
console.log(v)
code1.value = v.slice(0, 4)
code2.value = v.slice(4, 8)
code3.value = v.slice(8, 12)
code4.value = v.slice(12, 16)
nextTick(() => setFocus(v.length >= 16 ? 4 : Math.floor((v.length)/4) + 1))
if(code1.value.length+code2.value.length+code3.value.length+code4.value.length==16){
isFull.value = true
console.log(1111)
}else{
isFull.value = false
console.log(2222)
}
}
</script>
@ -203,17 +233,18 @@
color: #000;
font-size: 30rpx;
.paste-action{
color: #007aff;
color: #8B2316;
text-decoration: underline;
}
}
.code-inputs{
display: flex;
gap: 30rpx;
justify-content: space-between;
padding: 0 48rpx;
.code-box{
flex: 1;
height: 96rpx;
max-width: 142rpx;
background: #fff;
border-radius: 16rpx;
text-align: center;

View File

@ -1,25 +1,28 @@
<template>
<!-- <uni-nav-bar
<view class="navbox">
<view class="status_bar"></view>
<uni-nav-bar
left-icon="left"
title="我的福利卡"
@clickLeft="goBack"
fixed
color="#8B2316"
height="180rpx"
:border="false"
backgroundColor="#eeeeee"
></uni-nav-bar> -->
<navBar :title="'我的福利卡'" />
>
</uni-nav-bar>
</view>
<!-- <navBar :title="'我的福利卡'" /> -->
<view class="benefits-page">
<!-- 顶部红色横幅 -->
<view class="top-banner">
<view class="top-banner" @click="goWelfare" v-if="hasCard">
<image :src="bgImg" mode="widthFix" class="bg-img"></image>
<view class="banner-text">
<view class="line1">已兑换{{ cardInfo.length }}</view>
<view class="line2" @click="goMyWelfare">查看现有权益</view>
<view class="line2" @click.stop="goWelfare">查看现有权益</view>
</view>
<view class="help-btn" @click="showRules">帮助说明</view>
<view class="help-btn" @click.stop="showRules">帮助说明</view>
</view>
<!-- 帮助说明模态框与兑换页一致的居中弹层 -->
@ -39,7 +42,16 @@
</view>
<!-- 有卡展示多张 -->
<view v-if="hasCard" >
<scroll-view
v-if="hasCard"
class="scroll-container"
scroll-y
:refresher-enabled="true"
:refresher-triggered="refreshing"
@refresherrefresh="onRefresh"
@scrolltolower="onLoadMore"
:lower-threshold="50"
>
<view class="card-wrapper" v-for="(card, cIdx) in cardInfo" :key="card.id">
<image :src="cardImg" mode="widthFix" class="card-img"></image>
<view class="cardbox">
@ -51,29 +63,55 @@
</view>
</view>
<view class="card-body">
<image v-if="card.welfare_list && card.welfare_list.length > 3 && (swiperCurrent[cIdx] || 0) > 0"
:src="rightImg" mode="widthFix" class="left-img" @click="swipeLeft(cIdx)"></image>
<view v-else class="left-img-placeholder"></view>
<!-- 超过3条使用swiper否则直接显示 -->
<swiper v-if="card.welfare_list && card.welfare_list.length > 3"
:class="'welfare-swiper-' + cIdx"
class="welfare-swiper"
:indicator-dots="false"
:autoplay="false"
:circular="false"
:display-multiple-items="1"
:current="swiperCurrent[cIdx] || 0"
@change="onSwiperChange($event, cIdx)">
<swiper-item v-for="(page, pageIdx) in getWelfarePages(card.welfare_list)" :key="pageIdx">
<view class="linebox">
<view class="benefit-line" v-for="(w, idx) in page" :key="idx">
<text class="index">{{ pageIdx * 3 + idx + 1 }}</text>
<text class="text">{{ w.type_name }}{{ w.num }}{{ w.type_unit }}</text>
</view>
</view>
</swiper-item>
</swiper>
<view v-else class="linebox">
<view class="benefit-line" v-for="(w, idx) in card.welfare_list" :key="idx">
<text class="index">{{ idx + 1 }}</text>
<text class="text">{{ w.type_name }}{{ w.num }}{{ w.type_unit }}</text>
</view>
</view>
<image v-if="card.welfare_list && card.welfare_list.length > 3 && (swiperCurrent[cIdx] || 0) < getWelfarePages(card.welfare_list).length - 1"
:src="rightImg" mode="widthFix" class="right-img" @click="swipeRight(cIdx)"></image>
<view v-else class="right-img-placeholder"></view>
</view>
</view>
</view>
<!-- 加载提示 -->
<view class="loadmore-tip" v-if="isLoading || isLastPage">
<text>{{ isLoading ? '加载中...' : (isLastPage ? '没有更多了' : '') }}</text>
</view>
</view>
</scroll-view>
<!-- 无卡空状态 -->
<view v-else class="emptybox">
<up-image :src="emptyImg" width="176rpx" height="204rpx"></up-image>
<view class="empty_desc">暂无福利卡</view>
<empty />
</view>
<!-- 底部导航栏 -->
<view class="bottom-nav">
<view class="nav-item" @click="goPointsDetail">
<!-- <up-image :src="jifenImg" width="34rpx" height="34rpx"></up-image> -->
<up-image :src="jifenImg" width="34rpx" height="34rpx"></up-image>
<text class="nav-text">兑换福利卡</text>
</view>
</view>
@ -88,7 +126,27 @@
import cardImg from '@/static/carditem_bg.png'
import api from '@/api/api';
import logoImg from '@/static/logo_gdxz.png'
import { onPullDownRefresh, onReachBottom } from '@dcloudio/uni-app'
import rightImg from '@/static/right_selsect_big.png'
import empty from '@/components/empty/empty.vue'
import { onLoad,onBackPress } from '@dcloudio/uni-app'
const from=ref('');
onBackPress(() => {
if(!from.value){
plus.runtime.quit();
return true;
}
});
onLoad((options) => {
from.value = options.from;
})
const goWelfare = () => {
uni.setStorageSync('lookWelfare', 'useWelfare');
console.log('6789');
uni.redirectTo({
url: '/pages_app/myWelfare/myWelfare'
});
}
//
const hasCard = ref(true)
const cardInfo = ref([]);
@ -97,6 +155,9 @@
const pageSize = ref(10)
const isLastPage = ref(false)
const isLoading = ref(false)
const refreshing = ref(false)
// swiper
const swiperCurrent = ref({})
const getMyWelfareCard = (opts = { isRefresh: false }) => {
if (isLoading.value) return
@ -116,38 +177,39 @@
})
.finally(() => {
isLoading.value = false
uni.stopPullDownRefresh()
refreshing.value = false
})
}
const goBack = () => {
console.log('我的福利卡goBack');
console.log(from.value)
if(!from.value){
plus.runtime.quit();
}else{
uni.navigateBack();
}
}
onMounted(() => {
getMyWelfareCard()
})
//
onPullDownRefresh(() => {
// scroll-view
const onRefresh = () => {
refreshing.value = true
pageNum.value = 1
isLastPage.value = false
getMyWelfareCard({ isRefresh: true })
})
}
//
onReachBottom(() => {
// scroll-view
const onLoadMore = () => {
if (isLastPage.value || isLoading.value) return
pageNum.value += 1
getMyWelfareCard()
})
}
//
const goBack = () => {
uni.navigateBack({
fail() {
uni.redirectTo({
url: '/pages/index/index'
});
}
});
};
const centerVisible = ref(false)
const showRules = () => {
@ -159,12 +221,47 @@
const goPointsDetail = () => {
console.log('goPointsDetail')
uni.navigateTo({ url: '/pages_app/myWelfareCard/exchange' })
uni.navigateTo({ url: '/pages_app/myWelfareCard/exchange?num='+cardInfo.value.length })
};
const goMyWelfare = () => {
uni.navigateTo({ url: '/pages_app/myWelfare/myWelfare' })
}
// 3
const getWelfarePages = (welfareList) => {
if (!welfareList || welfareList.length === 0) return []
const pages = []
for (let i = 0; i < welfareList.length; i += 3) {
pages.push(welfareList.slice(i, i + 3))
}
return pages
}
// swiper
const onSwiperChange = (e, cardIndex) => {
swiperCurrent.value[cardIndex] = e.detail.current
}
//
const swipeLeft = (cardIndex) => {
const current = swiperCurrent.value[cardIndex] || 0
if (current > 0) {
swiperCurrent.value[cardIndex] = current - 1
}
}
//
const swipeRight = (cardIndex) => {
const current = swiperCurrent.value[cardIndex] || 0
const card = cardInfo.value[cardIndex]
if (card && card.welfare_list) {
const pages = getWelfarePages(card.welfare_list)
if (current < pages.length - 1) {
swiperCurrent.value[cardIndex] = current + 1
}
}
}
</script>
<style lang="scss" scoped>
@ -199,8 +296,16 @@
}
.benefits-page {
min-height: 100vh;
background-color: $bg-color;
height: 100vh;
.scroll-container {
position: fixed;
top: calc(var(--status-bar-height) + 44px + 286rpx);
left: 0;
right: 0;
bottom: 100rpx;
height: calc(100vh - var(--status-bar-height) - 44px - 286rpx - 100rpx);
box-sizing: border-box;
}
.emptybox{
display: flex;
height: 100vh;
@ -322,16 +427,7 @@
background-color: $divider-color;
}
}
.scrollbox{
position: fixed;
top: calc(#{$nav-height} + #{$segmented-height});
left: 30rpx;
right: 30rpx;
box-sizing: border-box;
bottom: $bottom-nav-height;
margin: 30rpx 0 ;
overflow-y: auto;
}
.benefits-list {
@ -409,9 +505,10 @@
/* 顶部横幅与卡片样式 */
.top-banner{
position: relative;
position: fixed;
height: 286rpx;
margin-top: calc(var(--status-bar-height) + 44px);
width:100%;
top: calc(var(--status-bar-height) + 44px);
.bg-img{
position: absolute;
width: 100%;
@ -479,13 +576,52 @@
}
}
.card-body{
padding:92rpx 28rpx;
height: 240rpx;
display: flex;
justify-content: center;
align-items: center;
padding:0rpx 28rpx;
.left-img{
width:28rpx;
height: 50rpx;
transform: rotate(180deg);
cursor: pointer;
}
.right-img{
width:28rpx;
height: 50rpx;
cursor: pointer;
}
.left-img-placeholder,
.right-img-placeholder{
width:28rpx;
height: 50rpx;
}
.welfare-swiper{
flex: 1;
height: 100%;
}
.linebox{
min-width: 500rpx;
display: flex;
flex-flow: column;
justify-content: center;
align-items: center;
padding:0 20rpx;
height: 100%;
}
.benefit-line{
font-size: 30rpx;
width:355rpx;
color: #8B2316;
line-height: 56rpx;
text-align: center;
text-align: left;
.index{color:#8B2316;}
.text{
text-align: left;
}
}
}
}

View File

@ -185,7 +185,7 @@
<script setup>
import { ref, onMounted, computed,reactive } from 'vue';
import { onShow,onLoad} from "@dcloudio/uni-app";
import { onShow,onLoad,onBackPress} from "@dcloudio/uni-app";
import api from '@/api/api.js';
import allImg from "@/static/video_all.png"
import allOnImg from "@/static/video_select.png"
@ -215,6 +215,7 @@
import searchImg from "@/static/search.png";
const sort =ref(2);
const keywords=ref('');
const from=ref('');
const typeUuid=ref('0e5fa3d76b8047528fdd3c452b77e9dd');
const typeName=ref('乙肝')
const isFilterActive=ref(false)
@ -227,6 +228,18 @@
//
const showAllVideoPopup = ref(false);
const selectedCategory = ref('全部');
onBackPress(() => {
if(!from.value){
plus.runtime.quit();
return true;
}
});
onLoad((options) => {
if(options.from){
from.value = options.from;
}
});
const selectCategory=(uuid)=>{
console.log(222)
console.log(uuid)
@ -528,8 +541,14 @@
//
const goBack = () => {
if(!from.value){
plus.runtime.quit();
return true;
}else{
uni.navigateBack();
}
}
const goSearch = () => {
uni.sendNativeEvent(
"goHomeSearch",
@ -817,7 +836,7 @@ const goSearch = () => {
.popup-content {
width: 100%;
background-color: #fff;
height:calc(100vh - 242rpx);
height:calc(100vh - var(--status-bar-height) - 44px - 92rpx);
overflow-y: scroll;
}

View File

@ -144,8 +144,6 @@
if(!from.vlaue){
plus.runtime.quit();
return true;
}else{
uni.navigateBack();
}
});

View File

@ -58,8 +58,10 @@
<view class="item-content">
<view class="item-title twoline">{{item.title}}</view>
<view class="info">
<view >{{ item.providername }}</view>
<view class="item-author">{{ item.hospitalname }}</view>
<view class="author-name">{{ item.providername }}</view>
<view class="item-author">
<view>{{ item.hospitalname }}</view>
</view>
</view>
<view class="item-stats">
<view class="views">
@ -613,20 +615,19 @@
top:calc(var(--status-bar-height) + 44px + 100rpx);
flex: 1;
bottom:0;
left:30rpx;
right:30rpx;
left:0rpx;
right:0rpx;
padding-top: 20rpx;
width:auto;
.courseware-item {
margin:0 30rpx 20rpx;
background-color: $white;
border-radius: 16rpx;
padding: 30rpx 20rpx;
margin-bottom: 20rpx;
@include shadow;
display: flex;
gap: 20rpx;
.item-left {
.pdf-icon {
@ -636,10 +637,11 @@
}
.item-content {
flex: 1;
width:500rpx;
display: flex;
margin-left: 10px;
flex-direction: column;
gap: 16rpx;
margin-right: 30rpx;
.item-title{
font-size: 32rpx;
color:#333;
@ -648,15 +650,29 @@
display: flex;
font-size: 26rpx;
color:#666;
width:100%;
min-width: 0;
margin:10rpx 0;
overflow: hidden;
}
.author-name{
white-space: nowrap;
}
.item-author {
flex:1;
min-width: 0;
max-width: 100%;
margin-left: 10rpx;
margin-right: 30rpx;
overflow: hidden;
view{
width:100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 200rpx; /* 限制最大宽度 */
}
}
.item-stats {

View File

@ -132,6 +132,7 @@ const canDownload = ref(false);
const orderId = ref('');
import otherHost from "@/utils/otherHost.js";
import docUrl from "@/utils/docUrl.js";
import isAndroid from "@/utils/platform.js";
const isFirstDownload = ref(false);
const path=ref('');
const from=ref('');
@ -595,6 +596,7 @@ const closeShare = () => {
const goView = () => {
for(let i = 0; i < downloadTasks.value.length; i++) {
if(downloadTasks.value[i].id == uuid.value) {
// if(isAndroid){
plus.runtime.openFile(downloadTasks.value[i].localPath, function(e) {
console.log('打开成功');
}, function(e) {
@ -603,6 +605,13 @@ const goView = () => {
icon: "none",
});
});
// }else{
// uni.sendNativeEvent('openDocument', {
// msg: downloadTasks.value[i].localPath.replaceAll('_doc/uniapp_save/',''),
// }, ret => {
// console.log(ret);
// });
// }
break;
}
}

View File

@ -130,6 +130,7 @@ const isRefreshing = ref(false);
const keywords = ref("");
const showDeleteModal = ref(false);
const currentDeleteItem = ref(null);
import isAndroid from "@/utils/platform.js";
import upImg from "@/static/triangle_green_theme.png";
import downImg from "@/static/triangle_normal.png";
const loadMoreStatus = ref("more"); // 'loading', 'more', 'noMore'
@ -408,6 +409,7 @@ const viewGuideline = (cell) => {
if(item.id == cell.id) {
console.log(2222222222);
console.log(item.localPath);
// if(isAndroid){
plus.runtime.openFile(item.localPath, function(e) {
console.log('打开成功');
}, function(e) {
@ -418,6 +420,14 @@ const viewGuideline = (cell) => {
});
console.log('打开失败:' + e.message);
});
// }else{
// uni.sendNativeEvent('openDocument', {
// msg: item.localPath.replaceAll('_doc/uniapp_save/',''),
// }, ret => {
// console.log(ret);
// });
// }
// uni.openDocument({
// filePath: item.localPath,
// fileType: 'pdf',

View File

@ -700,7 +700,7 @@ const playVideo = (video) => {
//
const goPatientVideo = () => {
navTo({
url: "/pages_app/patientVideo/patientVideo",
url: "/pages_app/patientVideo/patientVideo?from=video",
});
};

View File

@ -25,13 +25,17 @@
</template>
</uni-nav-bar>
</view>
<view class="videobox ">
<!-- <cover-view class="play-img" v-if="showVideo && !isPlaying && !isAndroid" @click="playVideo">
<cover-image :src="playImg" mode="aspectFill" />
</cover-view> -->
<video
v-if="showVideo"
class="player-wrapper"
:style="{width: videoWidth + 'px'}"
:src="videoSrc"
controls
id="myVideo"
object-fit="contain"
:autoplay="false"
@error="onVideoError"
@ -45,6 +49,10 @@
:seekTime="0"
@fullscreenchange="onFullscreenChange"
/> -->
</view>
<!-- @play="onVideoPlay"
@pause="onVideoPause" -->
<!-- 标签切换 -->
<cover-view class="tabs" v-if="from != 'download'" :style="{ opacity:isFullScreen?0:1, width: videoWidth + 'px' }" >
@ -225,7 +233,7 @@
<script setup>
import { ref, nextTick } from "vue";
//import uniVideo from "@/components/uniVideo/uniVideo.vue";
import { onLoad, onShow } from "@dcloudio/uni-app";
import { onLoad, onShow,onReady } from "@dcloudio/uni-app";
import unidialog from "@/components/dialog/dialog.vue";
import collectImg from "@/static/icon_book_collect_sel.png";
import discollectImg from "@/static/icon_book_collect_nor.png";
@ -236,6 +244,7 @@ import friendImg from "@/static/share_wxc.png";
import logoImg from "@/static/weiboShare.png";
import isAndroid from "@/utils/platform.js";
import avastarImg from "@/static/avastar.png";
import playImg from "@/static/play.png";
import api from "@/api/api";
import docUrl from "@/utils/docUrl";
import navTo from "@/utils/navTo";
@ -250,6 +259,7 @@ const pointContent = ref("");
const notEnoughVisible = ref(false);
const notEnoughContent = ref("");
const welfareNum = ref(0);
const isPlaying = ref(false);
//
const showDeleteModal = ref(false);
const currentDeleteItem = ref(null);
@ -260,12 +270,17 @@ const downLoadStatus = ref('start');
let downList = uni.getStorageSync("downLoadVideo") || [];
const downLoadList = ref(downList);
const isFullScreen = ref(false);
//import DomVideoPlayer from 'uniapp-video-player'
//import sunnyVideo from "@/uni_modules/sunny-video/components/sunny-video/sunny-video.vue";
import downloadStore from "@/store/downloadStoreVideo.js";
const downloadTasks = ref([]);
let userInfo = uni.getStorageSync("userInfo");
const current_user_id = ref(userInfo.uuid);
//const videoContext = ref(null);
// onReady(() => {
// videoContext.value = uni.createVideoContext('myVideo');
// });
//
const onFullscreenChange = (e) => {
@ -274,6 +289,15 @@ const onFullscreenChange = (e) => {
isFullScreen.value = fullScreen;
});
};
const onVideoPlay = () => {
isPlaying.value = true;
};
// const playVideo = () => {
// videoContext.value.play();
// };
// const onVideoPause = () => {
// isPlaying.value = false;
// };
const addDownloadTask = (item) => {
// 使store
@ -372,14 +396,14 @@ const syncTasksFromStore = () => {
const notEnoughConfirm = () => {
notEnoughVisible.value = false;
uni.sendNativeEvent('buyPointPage', {
msg: 'buyPointPage'
},ret => {
console.log(ret);
});
// navTo({
// url: "/pages_app/buyPoint/buyPoint",
// uni.sendNativeEvent('buyPointPage', {
// msg: 'buyPointPage'
// },ret => {
// console.log(ret);
// });
navTo({
url: "/pages_app/buyPoint/buyPoint?product_id="+video_uuid.value+"&type=video",
});
};
const pointConfirm = () => {
pointVisible.value = false;
@ -814,6 +838,12 @@ onLoad((options) => {
videoWidth.value = res.windowWidth; //
},
});
console.log('enrtyVideoDetail');
uni.sendNativeEvent('enrtyVideoDetail', {
msg: 'enrtyVideoDetail'
}, ret => {
console.log(ret);
})
video_uuid.value = options.id;
from.value = options.from;
if(from.value != 'download') {
@ -1060,6 +1090,26 @@ $bg-color: #f7f7f7;
$text-primary: #333;
$text-secondary: #666;
$theme-color: #8b2316;
.videobox{
top: calc(var(--status-bar-height) + 44px);
width:100%;
height:auto;
overflow: hidden;
position: relative;
.play-img{
position: absolute;
z-index:9999;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100rpx;
height:100rpx;
image{
width: 100rpx;
height:100rpx;
}
}
}
.navbox {
:deep(.uni-navbar__header-btns-right) {
width: 100px !important;
@ -1096,7 +1146,7 @@ $theme-color: #8b2316;
.player-wrapper {
background: #fff;
position: relative;
top: calc(var(--status-bar-height) + 44px);
z-index: 0;
height:220px;
overflow: hidden;

View File

@ -119,7 +119,7 @@ onLoad((query) => {
const raw = query && (query.url || "");
try {
safeUrl.value = decodeURIComponent(raw);
shareImg.value = decodeURIComponent(query.imgPath);
shareImg.value = query.imgPath?decodeURIComponent(query.imgPath):'https://doc.igandan.com/app/html/img/2016/20160714132557.png';
if (query.type == "live_yugao") {
shareTitle.value = query.sharetitle;
summary.value = "分享一篇来自“肝胆相照”的会议预告:" + shareTitle.value;
@ -129,6 +129,9 @@ onLoad((query) => {
} else if (query.type == "live") {
shareTitle.value = "肝胆相照直播:" + query.sharetitle;
summary.value = shareTitle.value;
}else if(query.type=='news'){
shareTitle.value = query.sharetitle;
summary.value ='';
}
// #ifdef APP-PLUS
const resInfo = uni.getSystemInfoSync(); // 使 uni.getSystemInfo({...}).then(res => {...})

View File

@ -239,7 +239,7 @@
if(item.id == cell.id) {
console.log(2222222222);
console.log(item.localPath);
if(isAndroid){
// if(isAndroid){
plus.runtime.openFile(item.localPath, function(e) {
console.log('打开成功');
}, function(e) {
@ -250,19 +250,15 @@
});
console.log('打开失败:' + e.message);
});
}else{
uni.openDocument({
filePath: item.localPath,
success: () => console.log('打开成功'),
fail: (err) => {
uni.showToast({
title: '打开失败:' + err.message,
icon: "none",
duration: 2000,
});
}
});
}
// }else{
// uni.sendNativeEvent('openDocument', {
// msg: item.localPath.replaceAll('_doc/uniapp_save/',''),
// }, ret => {
// console.log(ret);
// });
// }
// plus.runtime.openFile(item.localPath, function(e) {
// console.log('');
// }, function(e) {

View File

@ -155,6 +155,7 @@ import hotImg from "@/static/hot_booklist.png";
import downIng from "@/static/icon_library_down.png";
let downList = uni.getStorageSync("downLoadPdf") || [];
import empty from "@/components/empty/empty.vue";
import isAndroid from '@/utils/platform';
const downLoadList = ref(downList);
//
const guidelinesList = ref([]);
@ -484,6 +485,7 @@ const viewGuideline = (cell) => {
if(item.id == cell.uuid) {
console.log(2222222222);
console.log(item.localPath);
// if(isAndroid){
plus.runtime.openFile(item.localPath, function(e) {
console.log('打开成功');
}, function(e) {
@ -494,6 +496,13 @@ const viewGuideline = (cell) => {
});
console.log('打开失败:' + e.message);
});
// }else{
// uni.sendNativeEvent('openDocument', {
// msg: item.localPath.replaceAll('_doc/uniapp_save/',''),
// }, ret => {
// console.log(ret);
// });
// }
// uni.openDocument({
// filePath: item.localPath,
// fileType: 'pdf',

View File

@ -238,7 +238,7 @@
if(index==1){
navTo({
url: '/pages_app/patientVideo/patientVideo'
url: '/pages_app/patientVideo/patientVideo?from=article'
})
}else if(index==2){
let url=encodeURIComponent('https://wx.igandan.com/wxPatient/index.htm#/problem?link=share&fromtype=doctor')

View File

@ -269,7 +269,7 @@
if(index==1){
navTo({
url: '/pages_app/patientVideo/patientVideo'
url: '/pages_app/patientVideo/patientVideo?from=searchArticle'
})
}else if(index==2){
let url=encodeURIComponent('https://wx.igandan.com/wxPatient/index.htm#/problem?link=share&fromtype=doctor')

View File

@ -18,9 +18,9 @@
<view class="form-item" v-if="type==2">
<view class="label">邮箱</view>
<input class="input" v-model="email" type="text" placeholder="用于接收电子卡等信息(可选)" />
<input class="input" v-model="email" type="text" placeholder="请输入您的邮箱" />
</view>
<view class="divider-line" v-if="type==2"></view>
<view class="form-item select-item" @click="openAreaPicker" v-if="type==1">
<view class="label">地址</view>
@ -28,13 +28,13 @@
<view class="input" v-else>{{ regionText }}</view>
<text class="arrow"></text>
</view>
<view class="divider-line"></view>
<view class="divider-line" v-if="type==1"></view>
<view class="form-item" v-if="type==1">
<view class="label">详细地址</view>
<input class="input" v-model="detail" placeholder="请输入街道、门牌等详细地址信息" />
</view>
<view class="divider-line"></view>
<view class="divider-line" v-if="type==1"></view>
</scroll-view>
<view class="footer-bar" @click="submit">
@ -64,28 +64,33 @@
</view>
</view>
<unidialog
:title="'确认收货信息'"
:title="'确认兑换信息'"
:visible="freeVisible"
:content="freeContent"
:titleColor="'#000'"
@close="freeClose"
@confirm="freeConfirm"
>
<template #content>
<view>
<view class="row">
<view class="left">收件人:</view>
<view class="left">收件人</view>
<view class="right">{{ receiver }}</view>
</view>
<view class="row">
<view class="left">手机号:</view>
<view class="left">手机号</view>
<view class="right">{{ mobile }}</view>
</view>
<view class="row" >
<view class="left">地址:</view>
<view class="row" v-if="type==1">
<view class="left">地址</view>
<view class="right">{{ regionText+detail }}</view>
</view>
<view class="row" v-else>
<view class="left">邮箱</view>
<view class="right">{{ email?email:'无' }}</view>
</view>
<view class="row">
<view class="left">兑换积分:</view>
<view class="left">兑换积分</view>
<view class="right"><text class="price">{{ points }}积分</text>(包邮)</view>
</view>
<view class="row">请确认此次兑换物品不退不换</view>
@ -118,13 +123,13 @@ const freeConfirm = () => {
uni.showToast({
title: '兑换成功',
icon: 'none',
duration: 2000
duration: 1000
});
setTimeout(() => {
uni.navigateBack({
delta: 2
navTo({
url: '/pages_goods/pointMall/pointMall?from=exchange'
})
}, 2000)
}, 1000)
}
})
}
@ -208,9 +213,30 @@ onLoad((opts) => {
goodsUuid.value = opts.goodsUuid
goodsNum.value = opts.goodsNum;
type.value = opts.type;
getAddress()
})
const saveAddress = () => {
uni.setStorageSync('goods_address', {
receiver: receiver.value,
mobile: mobile.value,
regionText: regionText.value,
detail: detail.value,
email: email.value
})
}
const getAddress = () => {
const address = uni.getStorageSync('goods_address')
if(address){
receiver.value = address.receiver
mobile.value = address.mobile
regionText.value = address.regionText
detail.value = address.detail
email.value = address.email
}
}
const submit = () => {
if (!receiver.value) return uni.showToast({ title: '请输入收件人', icon: 'none' })
if (!/^1\d{10}$/.test(mobile.value)) return uni.showToast({ title: '请输入正确手机号', icon: 'none' })
@ -220,6 +246,7 @@ const submit = () => {
}else{
if (email.value && !/^([a-zA-Z0-9_\.-]+)@([a-zA-Z0-9\.-]+)\.([a-zA-Z]{2,})$/.test(email.value)) return uni.showToast({ title: '邮箱格式不正确', icon: 'none' })
}
saveAddress();
goods_api.createGoodsOrder({
goodsUuid: goodsUuid.value,
goodsNum: goodsNum.value,
@ -229,22 +256,27 @@ const submit = () => {
address: regionText.value+detail.value
}).then(res => {
if(res.code == 1 || res.code == 200){
points.value = res.data.pionts*res.data.goods_num;
points.value = res.data.pionts;
freeVisible.value = true
goods_order_id.value = res.data.goods_order_id
}
})
}
</script>
<style scoped lang="scss">
.address-page :deep(.dialog-title){
color:#000!important;
}
.address-page { min-height: 100vh; background: #fff; }
.content { position: absolute; top: calc(var(--status-bar-height) + 44px); bottom: 120rpx; left: 0; right: 0; background: #fff; }
.form-item { display: flex; align-items: center; padding: 24rpx; }
.form-item { display: flex; align-items: center; padding: 30rpx 24rpx; }
.label { width: 160rpx; color: #333; font-size: 30rpx; }
.input { flex: 1; color: #333; font-size: 30rpx; }
.placeholder { color: #bbb; }
.placeholder { color: #808080; }
.divider-line { height: 2rpx; background: #eee; margin: 0 24rpx; }
.select-item { position: relative; }
.arrow { position: absolute; right: 24rpx; color: #999; font-size: 48rpx; }
@ -263,15 +295,16 @@ const submit = () => {
.picker-empty { padding: 40rpx; text-align: center; color: #999; }
.row{
display: flex;
align-items: center;
align-items: flex-start;
font-size: 28rpx;
padding: 12rpx 0;
max-width: 800rpx;
margin-left: -100rpx;
.left{
text-align: left;
max-width: 125rpx;
max-width: 142rpx;
white-space: nowrap;
width:auto!important;
}
.price{

View File

@ -0,0 +1,437 @@
<template>
<view class="page">
<navBar :title="'兑换详情'" />
<scroll-view scroll-y class="content">
<!-- 兑换详情信息区域 -->
<view class="detail-card">
<view class="detail-row">
<text class="detail-label">兑换号</text>
<text class="detail-value">{{ exchangeNo }}</text>
</view>
<view class="detail-row" style="align-items: flex-start;">
<text class="detail-label">兑换物品</text>
<text class="detail-value">{{ goodsName }}</text>
</view>
<view class="detail-row">
<text class="detail-label">兑换数量</text>
<text class="detail-value">{{ quantity }}</text>
</view>
<view class="detail-row">
<text class="detail-label">积分</text>
<text class="detail-value points-value">{{ points }}</text>
</view>
<view class="detail-row">
<text class="detail-label">创建时间</text>
<text class="detail-value">{{ createTime }}</text>
</view>
<view class="detail-row" v-if="type == 1">
<text class="detail-label">物流</text>
<text class="detail-value">{{ logistics }}</text>
</view>
<view class="detail-row logistics-row" v-if="type == 1">
<text class="detail-label">物流编号</text>
<view class="logistics-no-wrapper">
<text class="detail-value logistics-no" >{{ logisticsNo }}</text>
<view class="copy-btn" @click="copyLogisticsNo" v-if="logisticsNo ">复制</view>
</view>
</view>
<view class="detail-row" v-if="type == 2">
<text class="detail-label">手机号</text>
<text class="detail-value">{{ mobile }}</text>
</view>
</view>
</scroll-view>
<!-- 底部快递查询按钮 -->
<view class="bottom-bar" @click="goLogistics" v-if="status == 4 && type == 1 && logistics && logisticsNo">
<text class="query-btn-text">快递查询</text>
</view>
<view class="bottom-bar bew" v-if="status == 1 && restTime > 0">
<view class="left"><up-count-down :time="restTime" format="mm:ss" @finish="finishCount"></up-count-down>分钟后此订单自动取消</view>
<view class="right">
<view class="cancel" @click="cancelOrder">取消订单</view>
<view class="pay" @click="goPay">去支付</view>
</view>
</view>
</view>
<unidialog
:title="'确认兑换信息'"
:visible="freeVisible"
:content="freeContent"
:titleColor="'#000'"
@close="freeClose"
@confirm="freeConfirm"
>
<template #content>
<view>
<view class="row">
<view class="left">收件人</view>
<view class="right">{{ user_name }}</view>
</view>
<view class="row">
<view class="left">手机号</view>
<view class="right">{{ mobile }}</view>
</view>
<view class="row" v-if="type==1">
<view class="left">地址</view>
<view class="right">{{ address }}</view>
</view>
<view class="row" v-else>
<view class="left">邮箱</view>
<view class="right">{{ email }}</view>
</view>
<view class="row">
<view class="left">兑换积分</view>
<view class="right"><text class="price">{{ points }}积分</text>(包邮)</view>
</view>
<view class="row">请确认此次兑换物品不退不换</view>
</view>
</template>
</unidialog>
</template>
<script setup>
import navBar from '@/components/navBar/navBar.vue';
import { onLoad } from '@dcloudio/uni-app';
import { ref } from 'vue';
import goods_api from '@/api/goods_api';
import navTo from '@/utils/navTo';
import unidialog from '@/components/dialog/dialog.vue';
import dayjs from 'dayjs';
const id = ref('');
const user_name = ref('');
const address = ref('');
const email = ref('');
const goods_order_id = ref('');
const cancelOrder = () => {
goods_api.cancelGoodsOrder({
goods_order_uuid: exchangeNo.value,
}).then(res => {
if(res.code == 200){
uni.showToast({
title: '取消成功',
icon: 'none',
duration: 2000
});
fetchExchangeDetail()
}
})
}
onLoad((options) => {
if (options && options.id) {
id.value = options.id;
}
fetchExchangeDetail()
});
//
const restTime = ref(0);
const exchangeNo = ref('');
const goodsName = ref('');
const quantity = ref();
const points = ref();
const createTime = ref('2');
const logistics = ref('');
const logisticsNo = ref('');
const mobile = ref('');
const type = ref(1);
const status = ref(null);
const freeVisible = ref(false)
//
const freeClose = () => {
freeVisible.value = false
}
const freeConfirm = () => {
freeVisible.value = false;
goods_api.payGoodsOrder({
goods_order_uuid: goods_order_id.value,
}).then(res => {
if(res.code == 1 || res.code == 200){
uni.showToast({
title: '兑换成功',
icon: 'none',
duration:1000
});
setTimeout(() => {
navTo({
url: '/pages_goods/pointMall/pointMall?from=exchange'
})
}, 1000)
}
})
}
const finishCount = () => {
restTime.value = 0;
cancelOrder();
}
const copyLogisticsNo = () => {
uni.setClipboardData({
data: logisticsNo.value,
success: () => {
uni.showToast({
title: '已复制',
icon: 'none'
});
},
fail: () => {
uni.showToast({
title: '复制失败',
icon: 'none'
});
}
});
};
//
const goLogistics = () => {
uni.navigateTo({
url: `/pages_goods/logistics/logistics?order_id=${exchangeNo.value}&name=${logistics.value}`
});
};
const goPay = () => {
console.log('222')
freeVisible.value = true
};
//
const formatDateTime = (timestamp) => {
if (!timestamp) return '';
const d = new Date(Number(timestamp) * 1000);
const y = d.getFullYear();
const m = String(d.getMonth() + 1).padStart(2, '0');
const day = String(d.getDate()).padStart(2, '0');
const h = String(d.getHours()).padStart(2, '0');
const min = String(d.getMinutes()).padStart(2, '0');
return `${y}-${m}-${day} ${h}:${min}`;
};
// API
const fetchExchangeDetail = async () => {
try {
// API
const res = await goods_api.getGoodsOrderDetail({
uuid:id.value
});
if (res.code === 200 && res.data) {
const data = res.data;
exchangeNo.value = data.goods_order_id || '';
goodsName.value = data.name || '';
quantity.value = data.goods_num || 0;
points.value = data.pionts || 0;
createTime.value = formatDateTime(data.create_date) || '';
logistics.value = data.express_name || '';
logisticsNo.value = data.express_id || '';
mobile.value = data.mobile || '';
type.value = data.type;
status.value = data.status;
goods_order_id.value = data.goods_order_id;
user_name.value = data.user_name || '';
address.value = data.address || '';
email.value = data.email || '';
let time1=dayjs(new Date().getTime());
//console.log(dayjs(data.time_expire*1000).format('YYYY-MM-DD HH:mm:ss'))
let time2=dayjs(data.time_expire*1000);
restTime.value = time2.diff(time1, 'millisecond');
if(restTime.value <=0 && status.value == 1){
cancelOrder();
}
console.log(restTime.value)
}
} catch (e) {
console.error('获取兑换详情失败:', e);
uni.showToast({
title: '获取详情失败',
icon: 'none'
});
}
};
</script>
<style scoped lang="scss">
.page {
min-height: 100vh;
background: #f5f5f5;
:deep(.dialog-title){
color:#000;
}
:deep(.u-count-down__text){
color:#ff0000!important;
}
}
.content {
position: absolute;
top: calc(var(--status-bar-height) + 44px);
bottom: 100rpx;
left: 0;
right: 0;
background: #f5f5f5;
}
//
.detail-card {
background: #fff;
padding: 30rpx;
// border-radius: 16rpx;
margin-bottom: 40rpx;
padding-top: 0;
}
.detail-row {
display: flex;
align-items: center;
padding: 20rpx 0;
border-bottom: 1rpx solid #f5f5f5;
&:last-child {
border-bottom: none;
}
}
.detail-label {
color: #333;
font-size: 30rpx;
white-space: nowrap;
width: 180rpx;
flex-shrink: 0;
}
.detail-value {
color: #666;
font-size: 30rpx;
flex: 1;
word-break: break-all;
}
//
.points-value {
color: #ff0000;
font-weight: 500;
}
//
.logistics-row {
align-items: center;
}
.logistics-no-wrapper {
display: flex;
align-items: center;
flex: 1;
gap: 20rpx;
}
.logistics-no {
flex: 1;
}
//
.copy-btn {
background: #ff0000;
color: #fff;
font-size: 24rpx;
padding: 8rpx 20rpx;
border-radius: 8rpx;
white-space: nowrap;
flex-shrink: 0;
}
//
.reference-text {
text-align: center;
color: #ff0000;
font-size: 30rpx;
padding: 40rpx 0;
}
//
.bottom-bar {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: #27c5b8;
height: 100rpx;
display: flex;
align-items: center;
justify-content: center;
z-index: 100;
}
.bottom-bar.bew{
display: flex;
align-items: center;
justify-content: space-between;
background:#efefef;
.left{
display: flex;
align-items: center;
white-space: nowrap;
font-size: 26rpx;
margin-left: 30rpx;
color: #666;
}
.right{
margin-right: 30rpx;
display: flex;
align-items: center;
justify-content: space-between;
.cancel{
display: flex;
align-items: center;
justify-content: center;
font-size: 26rpx;
color: #666;
padding: 10rpx 20rpx;
border-radius: 10rpx;
border: 2rpx solid #666;
}
.pay{
display: flex;
align-items: center;
margin-left: 20rpx;
justify-content: center;
font-size: 26rpx;
color: #ffff;
background: #8b2116;
padding: 10rpx 20rpx;
border-radius: 10rpx;
border: 2rpx solid #8b2116;
}
}
}
.query-btn-text {
color: #fff;
font-size: 32rpx;
font-weight: 500;
}
.row{
display: flex;
align-items: flex-start;
font-size: 28rpx;
padding: 12rpx 0;
max-width: 800rpx;
.left{
text-align: left;
max-width: 141rpx;
white-space: nowrap;
width:auto!important;
}
.price{
color: #FF4D4F;
}
}
.left{
width: 160rpx;
}
</style>

View File

@ -18,7 +18,10 @@
</view> -->
<view class="goods-title">{{ title }}</view>
<view class="top-row flex">
<view class="price">{{ price }}积分</view>
<view class="times" v-if="times>0">已兑换{{ times }}</view>
</view>
<view class="divider"></view>
@ -31,8 +34,8 @@
</view>
</view>
<view class="section">
<view class="section-label">所需积分</view>
<view class="section flex">
<view class="section-label" style="margin-bottom: 0;">所需积分</view>
<view class="need-points">{{ needPoints }}积分</view>
</view>
</scroll-view>
@ -42,7 +45,8 @@
</view>
</view>
<unidialog
:title="'确认收货信息'"
:title="'确认兑换信息'"
:titleColor="'#000'"
:visible="freeVisible"
:content="freeContent"
@close="freeClose"
@ -66,9 +70,10 @@ const freeClose = () => {
const freeConfirm = () => {
freeVisible.value = false;
navTo({
url: '/pages_app/buyPoint/buyPoint'
url: '/pages_app/buyPoint/buyPoint?product_id='+id.value+'&type=goods'
})
}
const times=ref(0);
const title = ref('')
const price = ref(0)
const qty = ref(1)
@ -92,13 +97,15 @@ onLoad((opts) => {
price.value = Number(opts.price || 0)
id.value = opts.id || ''
type.value = opts.type
times.value = opts.times
setQty(1)
getTotalPoints()
}
})
onShow(() => {
loadAddress()
getTotalPoints()
})
const STORAGE_KEY = 'goods_addresses'
@ -183,6 +190,19 @@ const getTotalPoints = () => {
</script>
<style scoped>
.flex{
display: flex;
align-items: center;
justify-content: space-between;
}
.top-row {
padding-bottom: 24rpx;
padding-right: 24rpx;
}
.top-row .times{
color: #999;
font-size: 28rpx;
}
.exchange-page { min-height: 100vh; background: #fff; }
.content { position: absolute; top: calc(var(--status-bar-height) + 44px); bottom: 120rpx; left: 0; right: 0; background: #fff; }
.addr-card { background: #fff; padding: 24rpx; border-bottom: 1rpx solid #f0f0f0; }
@ -194,12 +214,12 @@ const getTotalPoints = () => {
.addr-row.small { color: #666; font-size: 26rpx; }
.addr-empty { color: #bbb; font-size: 28rpx; }
.goods-title { padding: 24rpx; font-size: 32rpx; color: #333; line-height: 1.6; }
.price { padding: 0 24rpx 24rpx; color: #e74c3c; font-size: 30rpx; }
.price { padding: 0 24rpx 0rpx; color: #e74c3c; font-size: 30rpx; }
.divider { height: 16rpx; background: #f5f5f5; }
.section { padding: 24rpx; }
.section-label { color: #333; font-size: 30rpx; margin-bottom: 20rpx; }
.qty-row { display: flex; gap: 24rpx; }
.qty-btn { flex: 1; text-align: center; height: 96rpx; line-height: 96rpx; border: 2rpx solid #38c1b1; color: #38c1b1; border-radius: 12rpx; font-size: 36rpx; }
.qty-row { display: flex; justify-content: space-between; }
.qty-btn { flex: 1;max-width:205rpx; text-align: center; height: 96rpx; line-height: 96rpx; border: 2rpx solid #38c1b1; color: #38c1b1; border-radius: 12rpx; font-size: 36rpx; }
.qty-btn.active { background: #38c1b1; color: #fff; }
.need-points { color: #333; font-size: 30rpx; text-align: right; }
.footer-bar { position: fixed; left: 0; right: 0; bottom: 0; height: 120rpx; background: #27c5b8; display: flex; align-items: center; justify-content: center; }

View File

@ -0,0 +1,348 @@
<template>
<navBar :title="'物流信息'"></navBar>
<view class="logistics-page">
<!-- 顶部导航 -->
<!-- 内容区域 -->
<scroll-view class="content" scroll-y>
<!-- 头部基础信息 -->
<view class="base-info" v-if="hasData">
<view class="row">
<text class="label">信息来源</text>
<text class="value">{{ logisticsInfo.source }}</text>
</view>
<view class="row waybill-row">
<text class="label">运单编号</text>
<text class="value">{{ logisticsInfo.waybillNo }}</text>
<view class="btn-copy" @click="onCopy">
复制
</view>
</view>
</view>
<!-- 时间轴 -->
<view class="timeline" v-if="hasData">
<view class="left"></view>
<!-- 左侧日期 -->
<up-steps current="0" direction="column" dot>
<up-steps-item :desc="item.context" v-for="(item, index) in logisticsList">
<template #title>
<view class="timebox">
<text class="time">{{ formatDate(item.time) }}</text>
<text class="date">{{ formatTime(item.time) }}</text>
</view>
</template>
</up-steps-item>
</up-steps>
<!-- <view
v-for="(item, index) in logisticsList"
:key="index"
class="timeline-item"
>
</view> -->
</view>
<empty :emptyDesc="'暂无物流信息'" v-else />
</scroll-view>
</view>
</template>
<script setup>
import { ref } from "vue";
import navBar from "@/components/navBar/navBar.vue";
import goodsApi from "@/api/goods_api";
import { onLoad } from "@dcloudio/uni-app";
import empty from "@/components/empty/empty.vue";
import dayjs from "dayjs";
const hasData = ref(false);
onLoad((options) => {
console.log(options);
if(options.order_id){
order_id.value = options.order_id;
}
if(options.name){
logisticsInfo.value.source = options.name;
}
getLogisticsInfo();
});
const order_id = ref('');
const logisticsInfo = ref({
source: "",
waybillNo: "",
});
const getLogisticsInfo = async () => {
const res = await goodsApi.getOrderTrack({
order_id: order_id.value,
});
if(res.code==200){
logisticsInfo.value.waybillNo=res.data.nu;
if(res.data && res.data.data.length > 0){
hasData.value = true;
logisticsList.value = res.data.data;
}else{
hasData.value = false;
}
}
};
const formatDate = (time) => {
return dayjs(time).format("MM-DD");
};
const formatTime = (time) => {
return dayjs(time).format("HH:mm");
};
//
const logisticsList = ref([
{
date: "01-27",
time: "01:14",
desc: "您的快件离开【华北转运中心】已发往【乌鲁木齐转运中心】。预计【01月30日】到达【乌鲁木齐市】因运输距离较远预计将在【30日晚上】为您更新快件状态请您放心",
},
{
date: "01-27",
time: "00:17",
desc: "您的快件已经到达【华北转运中心】。【物流问题无需找商家或平台,请致电(专属热线:95554更快解决】",
},
{
date: "01-26",
time: "23:24",
desc: "您的快件离开【河北省廊坊市固安县】,已发往【华北转运中心】",
},
{
date: "01-26",
time: "18:31",
desc: "您的快件在【河北省廊坊市固安县】已揽收揽收人邢徐芳18832637908【物流问题无需找商家或平台请致电专属热线:95554更快解决】",
},
]);
const onBack = () => {
// 使 uni-app
uni.navigateBack({
delta: 1,
});
};
const onCopy = () => {
uni.setClipboardData({
data: logisticsInfo.value.waybillNo,
success: () => {
uni.showToast({
title: "已复制运单号",
icon: "none",
});
},
});
};
</script>
<style scoped lang="scss">
.timebox {
color: #333333;
margin-left: -130rpx;
display: flex;
flex-direction: column;
.date{
font-size: 26rpx;
color: #999999;
margin-left: 8rpx;
}
.time{
font-size: 28rpx;
color: #999999;
}
// margin-top: 20rpx;
}
.timeline :deep(.u-steps-item__content__desc){
margin-top: -68rpx;
}
.timeline :deep(.u-text__value--tips){
font-size: 28rpx!important;
color:#666666!important;
}
.logistics-page {
display: flex;
flex-direction: column;
height: 100vh;
background-color: #f7f7f7;
}
.nav-bar {
height: 44px;
padding: 0 12px;
display: flex;
align-items: center;
justify-content: space-between;
background-color: #ffffff;
border-bottom: 1px solid #f0f0f0;
}
.nav-left,
.nav-right {
width: 60rpx;
display: flex;
align-items: center;
justify-content: flex-start;
}
.nav-back-icon {
font-size: 18px;
color: #333333;
}
.nav-title {
flex: 1;
text-align: center;
font-size: 16px;
font-weight: 500;
color: #333333;
}
.content {
flex: 1;
margin-top: calc(var(--status-bar-height) + 44px);
}
.base-info {
padding: 16px 16px 12px;
background-color: #ffffff;
border-bottom: 1px solid #f0f0f0;
}
.row {
display: flex;
align-items: center;
margin-bottom: 8px;
}
.row:last-child {
margin-bottom: 0;
}
.label {
font-size: 30rpx;
color: #333333;
}
.value {
font-size: 30rpx;
color: #999999;
}
.waybill-row .value {
margin-right: 8px;
}
.btn-copy {
padding: 2px 15px;
border-radius: 20px;
border: 1px solid #dddddd;
background-color: #f8f8f8;
font-size: 12px;
color: #666666;
}
.btn-copy-text {
font-size: 12px;
color: #666666;
}
.timeline {
margin-top: 12px;
padding: 16px 38px 32px;
background-color: #ffffff;
display: flex;
.left{
width: 250rpx;
}
}
.timeline-item {
display: flex;
align-items: flex-start;
}
.timeline-item + .timeline-item {
margin-top: 18px;
}
.time-col {
width: 76rpx;
text-align: left;
margin-right: 8px;
}
.date {
font-size: 26rpx;
color: #666666;
}
.time {
margin-top: 2px;
font-size: 28rpx;
color: #999999;
}
.axis-col {
width: 32rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.dot {
width: 18px;
height: 18px;
border-radius: 50%;
border: 2px solid #e0e0e0;
background-color: #ffffff;
display: flex;
align-items: center;
justify-content: center;
}
.dot.active {
background-color: #00c15b;
border-color: #00c15b;
}
.dot-icon {
font-size: 12px;
color: #ffffff;
}
.line {
flex: 1;
width: 2px;
background-color: #00c15b;
margin-top: 2px;
}
.line-gray {
background-color: #e0e0e0;
}
.content-col {
flex: 1;
padding-left: 8px;
}
.desc {
font-size: 13px;
line-height: 1.6;
color: #999999;
}
.desc-active {
color: #333333;
}
</style>

View File

@ -1,7 +1,20 @@
<template>
<view class="page">
<!-- <uni-nav-bar left-icon="left" title="我的兑换" fixed color="#8B2316" height="180rpx" :border="false" backgroundColor="#ffffff" @clickLeft="goBack" /> -->
<navBar :title="'我的兑换'" />
<!-- <navBar :title="'我的兑换'" /> -->
<view class="navbox">
<view class="status_bar"></view>
<uni-nav-bar
left-icon="left"
title="我的兑换"
@clickLeft="goBack"
color="#8B2316"
:border="false"
backgroundColor="#eeeeee"
>
</uni-nav-bar>
</view>
<scroll-view
scroll-y
class="content"
@ -13,10 +26,10 @@
>
<empty v-if="!orderList.length" />
<!-- <view v-if="!orderList.length" class="empty">暂无兑换记录</view> -->
<view v-for="item in orderList" :key="item.uuid" class="card">
<view class="row">
<view v-for="item in orderList" :key="item.uuid" class="card" @click="goDetail(item)">
<view class="row" style="align-items: flex-start;">
<text class="label">兑换物品</text>
<text class="value">{{ item.goods_name }}</text>
<text class="value oneline">{{ item.goods_name }}</text>
</view>
<view class="row">
<text class="label">兑换时间</text>
@ -24,7 +37,7 @@
</view>
<view class="row">
<text class="label">状态</text>
<text class="status" :class="statusClass(item.status)">{{ statusText(item.status) }}</text>
<text class="status" >{{ statusText(item.status) }}</text>
</view>
</view>
<view class="list-footer" v-if="isLoading">加载中...</view>
@ -38,12 +51,39 @@ import goods_api from '@/api/goods_api'
import { ref, onMounted } from 'vue'
import navBar from '@/components/navBar/navBar.vue'
import empty from '@/components/empty/empty.vue'
import navTo from '@/utils/navTo.js'
import { onLoad,onBackPress} from '@dcloudio/uni-app'
const orderList = ref([])
const page = ref(1)
const pageSize = ref(10)
const isLoading = ref(false)
const noMore = ref(false)
const refresherTriggered = ref(false)
const refresherTriggered = ref(false);
const from = ref('')
onLoad((options) => {
if(options.from){
from.value = options.from
}
})
const goBack = () => {
if(from.value){
plus.runtime.quit();
}else{
uni.navigateBack();
}
}
onBackPress(() => {
if(from.value){
plus.runtime.quit();
return true;
}
});
const goDetail=(item)=>{
navTo({
url: `/pages_goods/exchange/exchangeDetail?id=${item.uuid}`
})
}
const fetchList = () => {
if (isLoading.value || noMore.value) return
@ -82,9 +122,13 @@ const formatDate = (sec) => {
}
const statusText = (s) => {
if (s === 1 || s === 2) return '已支付'
if (s === 3) return '待支付'
return ''
if (s === 1 ) return '待支付'
if (s === 2 ) return '已支付'
if (s === 3) return '已取消'
if (s === 4) return '已发货'
if (s === 5) return '已收货'
if(s === 6) return '订单异常'
}
const statusClass = (s) => {
@ -97,17 +141,17 @@ onMounted(() => {
orderList.value = []
fetchList()
})
const goBack = () => uni.navigateBack()
</script>
<style scoped>
.page { min-height: 100vh; background: #fff; }
.content { position: absolute; top: calc(var(--status-bar-height) + 44px); bottom: 0; left: 0; right: 0; background: #fff; }
.card { background: #fff; padding: 24rpx; border-bottom: 2rpx solid #f5f5f5; }
.card { background: #fff; padding: 24rpx; border-bottom: 2rpx solid #eee; }
.row { display: flex; align-items: center; padding: 10rpx 0; }
.label { color: #333; font-size: 30rpx; width: 180rpx; }
.label { color: #333; white-space: nowrap;font-size: 30rpx; width: 157rpx; }
.value { color: #666; font-size: 30rpx; }
.status { font-size: 30rpx; }
.status { font-size: 30rpx; color: #666;}
.status.paid { color: #666; }
.status.unpaid { color: #666; }
.list-footer { text-align: center; color: #999; padding: 24rpx 0; }

View File

@ -35,8 +35,8 @@
<!-- 轮播图横幅 -->
<view class="banner-section">
<view class="swipemask">
<view class="banner-subtitle" v-if="bannerList.length > 0">{{
<view class="swipemask" v-if="bannerList.length > 0">
<view class="banner-subtitle" >{{
bannerList[currentBannerIndex].title
}}</view>
<view class="dotbox">
@ -50,10 +50,11 @@
</view>
<swiper
class="banner-swiper"
:indicator-dots="true"
:autoplay="true"
:indicator-dots="bannerList.length > 0 ? true : false"
:autoplay="bannerList.length > 0 ? true : false"
:interval="3000"
:duration="500"
:circular="true"
indicator-active-color="#8B2316"
@change="onSwiperChange"
>
@ -74,10 +75,10 @@
<view class="banner-item">
<image
class="banner-image"
src="/static/banner-bg.jpg"
:src="rewardImg"
mode="aspectFill"
></image>
<view class="banner-content">
<!-- <view class="banner-content">
<view class="banner-text green"
>第二届京津冀感染肝病高峰论坛&</view
>
@ -86,7 +87,7 @@
>
<view class="banner-text orange">2016.10.14-2016.10.16</view>
<view class="banner-text orange">河北石家庄</view>
</view>
</view> -->
</view>
</swiper-item>
</swiper>
@ -209,10 +210,12 @@
import { ref, onMounted } from "vue";
import goods_api from "@/api/goods_api";
import docUrl from "@/utils/docUrl";
import { onBackPress,onLoad } from "@dcloudio/uni-app";
import pointImg from "@/static/integralticket.png";
import buyPointImg from "@/static/buy_points.png";
import filter from "@/static/triangle_normal.png";
import filterOn from "@/static/triangle_green_theme.png";
import rewardImg from "@/static/reward.png";
//
const bannerList = ref([]);
const currentBannerIndex = ref(0);
@ -244,10 +247,32 @@ const sortOptions = ref([
{ label: "兑换从多到少", value: 5 },
{ label: "兑换从少到多", value: 6 },
]);
const from=ref('');
const name=ref('');
onBackPress(() => {
if(!from.vlaue){
plus.runtime.quit();
return true;
}
});
onLoad((opts) => {
if(opts.from){
from.value = opts.from;
}
if(opts.name){
name.value = opts.name;
}
});
//
const goBack = () => {
if(!from.vlaue){
plus.runtime.quit();
}else{
uni.navigateBack();
}
};
const goToSearch = () => {
@ -321,7 +346,7 @@ const goToBannerDetail = (banner) => {
uni.navigateTo({
url: `/pages_app/webview/webview?url=${encodeURIComponent(
docUrl+banner.path
)}&title=${banner.title}`,
)}&title=积分商城`,
});
};
@ -361,7 +386,7 @@ const getGoodsList = () => {
const sortParam = selectedSortValue.value ? selectedSortValue.value : 1;
goods_api
.goodsList({
name: "",
name: name.value,
page: page.value,
sort: sortParam,
tag_type: tagParam,
@ -606,8 +631,8 @@ onMounted(() => {
.dropdown-item {
padding: 12px 16px;
font-size: 14px;
color: #333;
font-size: 28rpx;
color: #666;
text-align: center;
border-bottom: 1px solid #eee;
}
@ -625,8 +650,8 @@ onMounted(() => {
}
.filter-text {
font-size: 14px;
color: #333;
font-size: 28rpx;
color: #666;
margin-right: 4px;
}
@ -662,9 +687,13 @@ onMounted(() => {
display: flex;
flex-wrap: wrap;
padding: 16px;
gap: 16px;
}
// gap: 16px;
}
.grid-wrap .product-item:nth-child(2n+1){
margin-right: 16px;
}
.list-footer {
text-align: center;
color: #999;
@ -678,6 +707,7 @@ onMounted(() => {
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transition: transform 0.2s ease;
margin-bottom: 16px;
}
.product-item:active {
@ -702,7 +732,7 @@ onMounted(() => {
}
.product-title {
font-size: 12px;
font-size: 28rpx;
color: #333;
line-height: 1.4;
margin-bottom: 8px;

View File

@ -18,7 +18,7 @@
<view class="swiper-box">
<swiper class="detail-swiper" :indicator-dots="true" :autoplay="images.length > 1 ? true : false" :interval="5000" :duration="400" indicator-color="#ccc" indicator-active-color="#8B2316" :circular="true">
<swiper-item v-for="(img, idx) in images" :key="idx">
<image class="swiper-image" :src="img" mode="aspectFit"></image>
<image class="swiper-image" :src="img" mode="widthFix"></image>
</swiper-item>
</swiper>
</view>
@ -28,7 +28,7 @@
<view class="title"><text v-if="product.type == 1">[包邮]</text>{{ product.title }}</view>
<view class="price-row">
<text class="price">{{ product.price }}积分</text>
<text class="exchanged">已兑换{{ product.times }}</text>
<text class="exchanged" v-if="product.times > 0">已兑换{{ product.times }}</text>
</view>
</view>
@ -51,8 +51,10 @@
</scroll-view>
<!-- 底部兑换按钮 -->
<view class="bottom-bar" @click="goExchange">
<view class="redeem-btn" >在线兑换</view>
<view class="bottom-bar" >
<view class="redeem-btn" @click="goExchange">在线兑换</view>
<view class="bar" v-if="isUpan"></view>
<view class="redeem-btn" @click="goExchangeUpan" v-if="isUpan" :class="{'disabled': restNum <= 0}">福利兑换<text v-if="restNum > 0">剩余{{ restNum }}</text></view>
</view>
</view>
</template>
@ -66,22 +68,35 @@ import navBar from '@/components/navBar/navBar.vue'
const product = ref({ id: '', title: '', price: 0, times: 0, content: '' })
const images = ref([])
const navTitle = ref('商品详情')
const navTitle = ref('商品详情');
const isUpan = ref(false);
const restNum = ref(0);
const goBack = () => uni.navigateBack()
const getUpanWelfareCount = async () => {
const res = await goods_api.getUpanWelfareCount()
if (res.code == 200) {
restNum.value=res.data;
};
}
const fetchDetail = async (id) => {
try {
const res = await goods_api.getGoodsDetail({ uuid: id })
if ((res.code === 200 || res.code === '200') && res.data) {
let content=res.data.content.replace(/\<img/gi, '<img class="richImg"');
product.value = {
id,
type: res.data.type,
title: res.data.name || '',
price: res.data.bonuspoints || 0,
times: res.data.times || 0,
content: res.data.content || ''
content: content
}
if(res.data.name.indexOf('U盘') > -1 || res.data.name.indexOf('u盘') > -1){
isUpan.value = true;
getUpanWelfareCount();
};
navTitle.value = (product.value.title || '').slice(0, 18)
const list = []
if (res.data.detial_imgpath) {
@ -101,10 +116,18 @@ const fetchDetail = async (id) => {
onLoad((opts) => {
if (opts && opts.id) fetchDetail(opts.id)
})
const goExchangeUpan = () => {
console.log(restNum.value);
if(restNum.value>0){
uni.navigateTo({
url: `/pages_app/buyUpan/buyUpan?restNum=${restNum.value}`
})
}
}
const goExchange = () => {
uni.navigateTo({
url: `/pages_goods/exchange/index?id=${product.value.id}&title=${encodeURIComponent(product.value.title)}&price=${product.value.price}&type=${product.value.type}`
url: `/pages_goods/exchange/index?id=${product.value.id}&title=${encodeURIComponent(product.value.title)}&price=${product.value.price}&type=${product.value.type}&times=${product.value.times}`
})
}
</script>
@ -127,8 +150,8 @@ const goExchange = () => {
/* 主图轮播 */
.swiper-box { background: #fff; }
.detail-swiper { height: 480rpx; }
.swiper-image { width: 100%; height: 100%; }
.detail-swiper { height: 440rpx; }
.swiper-image { width: 100%; height: 440rpx; }
/* 概要 */
.summary { background: #fff; padding: 24rpx; }
@ -160,5 +183,23 @@ const goExchange = () => {
align-items: center;
justify-content: center;
}
.redeem-btn { color: #fff; font-size: 32rpx; font-weight: 700; }
.bottom-bar .bar{
height: 100rpx;
background-color: #f7f7f7;
width:2rpx;
}
.bottom-bar .redeem-btn{
height: 100rpx;
background-color: #27c5b8;
display: flex;
align-items: center;
justify-content: center;
color: #fff; font-size: 32rpx;flex:1;
}
.bottom-bar .redeem-btn.disabled{
background-color: #ccc;
}
.rich-wrapper >>> .richImg{
width: 100%!important;
}
</style>

BIN
static/myjifen_big-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 32 KiB

BIN
static/play.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
static/reward.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -96,6 +96,14 @@

View File

@ -1,4 +1,4 @@
let BASE_URL='https://dev-app.igandan.com/app';
//let BASE_URL='https://app.igandan.com/app'
//let BASE_URL='https://dev-app.igandan.com/app';
let BASE_URL='https://app.igandan.com/app'
export default BASE_URL

View File

@ -1,5 +1,5 @@
let DOC_URL='https://dev-doc.igandan.com/app/';
//let DOC_URL='https://doc.igandan.com/app/'
//let DOC_URL='https://dev-doc.igandan.com/app/';
let DOC_URL='https://doc.igandan.com/app/'
// if(app.globalData.apiHost.indexOf('dev')>-1){
// DOC_URL='https://dev-doc.igandan.com/app/'
// }else{

View File

@ -1,5 +1,5 @@
let OTHER_HOST='https://dev-wx.igandan.com'
//let OTHER_HOST='https://wx.igandan.com'
//let OTHER_HOST='https://dev-wx.igandan.com'
let OTHER_HOST='https://wx.igandan.com'
//const app = getApp({allowDefault: true});
// if(app.globalData.apiHost && app.globalData.apiHost.indexOf('dev')>-1){
// OTHER_HOST='https://dev-wx.igandan.com'

View File

@ -1,2 +1,2 @@
const version="4.2.0"
const version="4.2.2"
export default version