640 lines
16 KiB
Vue
640 lines
16 KiB
Vue
<template>
|
||
<view class="content">
|
||
|
||
<image :src="bg" style="width: 100%; height: 100%; background-color: bisque; position: absolute;" mode="">
|
||
</image>
|
||
<uniNoticeBar showIcon single scrollable text="赠品仅限线下购买设备的用户领取,需人工审核,预计3个工作日内完成!"
|
||
style="width: 100%;position:fixed;top:10%" background-color="transparent" color="#000" />
|
||
|
||
|
||
<view class="auto-scroll-container" catchtouchmove="return false">
|
||
<!-- 滚动容器 -->
|
||
<scroll-view class="scroll-view" scroll-x :scroll-with-animation="false" ref="scrollView"
|
||
@scroll="onScroll">
|
||
<!-- 图片列表容器 (复制一份实现无缝滚动) -->
|
||
<view class="scroll-content" :style="{ transform: `translateX(${translateX}px)` }"
|
||
catchtouchmove="return false">
|
||
<view class="image-list" ref="imageList">
|
||
<view class="image-item" v-for="(item, index) in imageList" :key="index">
|
||
<image :src="item.url" mode="aspectFill" class="item-image" :alt="item.alt"></image>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 复制一份列表用于无缝衔接 -->
|
||
<view class="image-list copy-list" catchtouchmove="return false">
|
||
<view class="image-item" v-for="(item, index) in imageList" :key="'copy-' + index">
|
||
<image :src="item.url" mode="aspectFill" class="item-image" :alt="item.alt"></image>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
|
||
|
||
<view class="center" @click="openReceivePop"
|
||
style="width: 386rpx; height: 102rpx; background-color: #0877FF; border-radius: 16rpx; position: absolute; bottom: 200rpx;">
|
||
<text style="font-size: 35rpx; color: white;">设备专属权益兑换</text>
|
||
</view>
|
||
|
||
<view class="center" @click="openRecordPop"
|
||
style="width: 386rpx; height: 80rpx; border-radius: 16rpx; position: absolute; bottom: 100rpx;">
|
||
<text style="font-size: 30rpx; color: black;">领取记录</text>
|
||
</view>
|
||
|
||
|
||
<!-- 领奖弹窗 -->
|
||
<uni-popup ref="receivePop" type="center" :is-mask-click="false">
|
||
<view class="column"
|
||
style="width: 600rpx; height: 1250rpx; background-color: #F5F5F5; border-radius: 16rpx; align-items: center; font-size: 25rpx;">
|
||
|
||
<text style="font-size: 35rpx; font-weight: 600; color: black; margin-top: 40rpx;">恭喜您获得赠礼</text>
|
||
|
||
<text style="font-size: 25rpx; color: black; margin-top: 10rpx;">填写地址和产品信息,送货上门</text>
|
||
|
||
<view class="column"
|
||
style="width: 550rpx; background-color: white; align-items: center;margin-top: 20rpx;border-radius: 16rpx; padding-bottom: 20rpx;">
|
||
|
||
<text style="font-size: 25rpx; color: black; margin-top: 10rpx;">收货地址填写</text>
|
||
|
||
<view class="row line">
|
||
<text style="width: 110rpx;">姓名</text>
|
||
<input v-model="name" type="text" style="margin-left: 50rpx; width: 350rpx;" />
|
||
</view>
|
||
|
||
<view class="row line">
|
||
<text style="width: 110rpx;">联系方式</text>
|
||
<input v-model="phone" type="text" style=" margin-left: 50rpx; width: 350rpx;" />
|
||
</view>
|
||
|
||
<view class="row line">
|
||
<text style="width: 110rpx;">工作单位</text>
|
||
<input v-model="workUnit" type="text" style="margin-left: 50rpx; width: 350rpx;" />
|
||
</view>
|
||
|
||
<view class="row line">
|
||
<text style="margin-top: 20rpx; width: 110rpx;">收货地址</text>
|
||
<textarea v-model="address" placeholder="" :auto-height="false" :maxlength="-1"
|
||
style="height: 50px; width: 350rpx;margin-left: 50rpx;" />
|
||
</view>
|
||
</view>
|
||
|
||
<view class="column"
|
||
style="width: 550rpx; background-color: white; align-items: center;margin-top: 20rpx;border-radius: 16rpx; padding-bottom: 20rpx;">
|
||
|
||
<text style="font-size: 25rpx; color: black; margin-top: 40rpx;">产品信息填写</text>
|
||
|
||
<view class="row line">
|
||
<text style="width: 110rpx;">型号</text>
|
||
<input v-model="model" type="text" style="margin-left: 50rpx; width: 350rpx;" />
|
||
</view>
|
||
|
||
<view class="row line">
|
||
<text style="width: 110rpx;">出品编号</text>
|
||
<input v-model="number" type="text" style="margin-left: 50rpx; width: 350rpx;" />
|
||
</view>
|
||
|
||
<view class="row line">
|
||
<text style="width: 110rpx;">出品年月</text>
|
||
<input v-model="createTime" type="text" style="margin-left: 50rpx; width: 350rpx;" />
|
||
</view>
|
||
|
||
<view class="row" style="width: 100%; margin-top: 40rpx; align-items: flex-start; flex-wrap: wrap;">
|
||
<view class="center" @click="seleImg"
|
||
style="width: 150rpx; height:150rpx; background-color: gainsboro; margin-left: 30rpx; margin-right: 20rpx; position: relative;">
|
||
<text style="position: absolute;">+</text>
|
||
</view>
|
||
<image style="width: 150rpx; height:150rpx; margin-right: 20rpx;" v-if="imagePath"
|
||
:src="imagePath" mode="aspectFit" @click="previewImage">
|
||
</image>
|
||
</view>
|
||
|
||
<text style="font-size: 22rpx; margin-top: 20rpx;width: 90%;">拍摄并上传清晰的产品铭牌信息用于辅助审核,通过后立即发货</text>
|
||
</view>
|
||
|
||
<view class="row" style="width: 550rpx; justify-content: space-between; margin-top: 40rpx;">
|
||
<view class="center" @click="closeReceivePop"
|
||
style="width: 150rpx; height: 80rpx; background-color: #CCCCCC; border-radius: 16rpx;">
|
||
<text style="font-size: 28rpx; color: #333;">关闭</text>
|
||
</view>
|
||
<view class="center" @click="submitForm"
|
||
style="width: 350rpx; height: 80rpx; background-color: #0877FF; border-radius: 16rpx;position: relative;">
|
||
<text style="font-size: 28rpx; color: white;">提交</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</uni-popup>
|
||
|
||
|
||
<!-- 领取记录 -->
|
||
<uni-popup ref="recordPop" type="center">
|
||
|
||
<view class="column"
|
||
style="width: 604rpx; height: 598rpx; background-color: #F5F5F5; border-radius: 16rpx; align-items: center;">
|
||
|
||
<view class="row"
|
||
style="width: 90%; justify-content: space-between; align-items: center; margin-top: 30rpx;">
|
||
<view class="" style="width: 30rpx;">
|
||
|
||
</view>
|
||
|
||
<text style="font-size: 35rpx; font-weight: 600; color: black;">领取记录</text>
|
||
|
||
<image src="/static/ic_close.png" @click="closeRecordPop()" style="width: 30rpx; height: 30rpx;"
|
||
mode=""></image>
|
||
</view>
|
||
|
||
<view class="column"
|
||
style="width: 100%; height: 460rpx; margin-top: 30rpx; overflow-y: auto; font-size: 25rpx; align-items: center;">
|
||
|
||
|
||
<view class="column" v-for="item in recordList" :key="item.phone + item.time"
|
||
style="width: 90%; height: 180rpx; margin-bottom: 10rpx; position: relative; background-color: white; padding: 10rpx; border-radius: 16rpx;">
|
||
|
||
<view class="row" style="justify-content: space-between; margin-top: 20rpx;">
|
||
<view class="row">
|
||
<text>{{ item.name }}</text>
|
||
<text style="margin-left: 20rpx;">{{ item.phone }}</text>
|
||
</view>
|
||
<text>{{ item.time }}</text>
|
||
</view>
|
||
<text style="margin-top: 20rpx;">{{ item.address }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</uni-popup>
|
||
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import uniNoticeBar from '@/uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue'
|
||
import {
|
||
processImage
|
||
} from '@/common/utils'
|
||
export default {
|
||
components: {
|
||
uniNoticeBar
|
||
},
|
||
onLoad() {
|
||
this.getConfig();
|
||
var userId = uni.getStorageSync("user_id");
|
||
if (!userId || userId == 0) {
|
||
this.login();
|
||
}
|
||
this.userId = userId;
|
||
},
|
||
data() {
|
||
return {
|
||
bg: "",
|
||
userId: 0,
|
||
imagePath: '',
|
||
name: "",
|
||
phone: "",
|
||
base64: "",
|
||
workUnit: "",
|
||
address: "",
|
||
createTime: "",
|
||
number: "",
|
||
model: "",
|
||
recordList: [],
|
||
// 图片数据
|
||
imageList: [{
|
||
url: 'https://picsum.photos/300/200?random=1',
|
||
alt: '图片1'
|
||
},
|
||
{
|
||
url: 'https://picsum.photos/300/200?random=2',
|
||
alt: '图片2'
|
||
},
|
||
{
|
||
url: 'https://picsum.photos/300/200?random=3',
|
||
alt: '图片3'
|
||
},
|
||
{
|
||
url: 'https://picsum.photos/300/200?random=4',
|
||
alt: '图片4'
|
||
},
|
||
{
|
||
url: 'https://picsum.photos/300/200?random=5',
|
||
alt: '图片5'
|
||
},
|
||
{
|
||
url: 'https://picsum.photos/300/200?random=6',
|
||
alt: '图片6'
|
||
}
|
||
],
|
||
scrollTimer: null, // 滚动定时器
|
||
scrollSpeed: 1, // 滚动速度 (px/帧)
|
||
translateX: 0, // 位移量
|
||
listWidth: 0, // 列表宽度
|
||
isScrolling: false // 是否正在滚动
|
||
}
|
||
},
|
||
|
||
onReady() {
|
||
// 获取列表宽度
|
||
this.$nextTick(() => {
|
||
const query = uni.createSelectorQuery().in(this);
|
||
query.select('.image-list').boundingClientRect(data => {
|
||
this.listWidth = data.width;
|
||
// 开始自动滚动
|
||
this.startAutoScroll();
|
||
}).exec();
|
||
});
|
||
},
|
||
|
||
onUnload() {
|
||
// 页面卸载时清除定时器
|
||
this.stopAutoScroll();
|
||
},
|
||
|
||
methods: {
|
||
request(url, method, data) {
|
||
return new Promise((resolve, reject) => {
|
||
const header = {
|
||
|
||
};
|
||
if (method == "post") {
|
||
header['content-type'] = 'application/json';
|
||
}
|
||
uni.request({
|
||
url: "https://gift.zpc-xy.com/" + url,
|
||
method: method,
|
||
data: data,
|
||
header: header,
|
||
timeout: 10000,
|
||
success: (res) => {
|
||
console.log('API响应:', res);
|
||
if (res.statusCode === 200) {
|
||
resolve(res.data);
|
||
} else {
|
||
reject(new Error(`请求失败,状态码: ${res.statusCode}`));
|
||
}
|
||
},
|
||
fail: (err) => {
|
||
console.error('API请求失败:', err);
|
||
reject(err);
|
||
}
|
||
});
|
||
})
|
||
},
|
||
async getConfig() {
|
||
const res = await this.request("config", "get", {});
|
||
console.log(res);
|
||
if (res.home != "") {
|
||
this.bg = res.home;
|
||
}
|
||
},
|
||
wxLogin() {
|
||
return new Promise((resolve, reject) => {
|
||
uni.login({
|
||
provider: 'weixin', //使用微信登录
|
||
onlyAuthorize: true,
|
||
success: async function (res) {
|
||
// if()
|
||
resolve(res.code);
|
||
},
|
||
fail: function (err) {
|
||
reject(err);
|
||
}
|
||
})
|
||
})
|
||
|
||
},
|
||
async login() {
|
||
try {
|
||
const wxCode = await this.wxLogin();
|
||
if (wxCode) {
|
||
const res = await this.request("userLogin?code=" + wxCode, "post", {});
|
||
if (res.code == 200) {
|
||
uni.setStorageSync("user_id", res.data.user_id);
|
||
this.userId = res.data.user_id;
|
||
console.log('登录成功, userId:', this.userId);
|
||
} else {
|
||
console.error('登录失败:', res.message);
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('登录过程出错:', error);
|
||
}
|
||
},
|
||
openReceivePop() {
|
||
this.$refs.receivePop.open();
|
||
},
|
||
|
||
closeReceivePop() {
|
||
this.$refs.receivePop.close();
|
||
},
|
||
getUserId() {
|
||
|
||
if (this.userId == 0) {
|
||
|
||
var userId = uni.getStorageSync("user_id");
|
||
if (!userId || userId == 0) {
|
||
this.login();
|
||
} else {
|
||
this.userId = userId;
|
||
}
|
||
}
|
||
return this.userId;
|
||
|
||
},
|
||
async openRecordPop() {
|
||
await this.loadRecordList();
|
||
this.$refs.recordPop.open();
|
||
},
|
||
|
||
async loadRecordList() {
|
||
try {
|
||
uni.showLoading({
|
||
title: '加载中...'
|
||
});
|
||
// 这里可以调用API获取实际的领取记录
|
||
const result = await this.request('getRecord?userId=' + this.getUserId(), 'GET', {});
|
||
console.log(result);
|
||
if (result.data.length > 0) {
|
||
let isShow = true;
|
||
let record = [];
|
||
for (var index = 0; index < result.data.length; index++) {
|
||
var element = result.data[index];
|
||
if (element.status == 1) {
|
||
record.push(element)
|
||
}
|
||
}
|
||
this.recordList = record;
|
||
}
|
||
// 目前使用模拟数据
|
||
console.log('加载领取记录...');
|
||
} catch (error) {
|
||
console.error('加载领取记录失败:', error);
|
||
}
|
||
uni.hideLoading();
|
||
},
|
||
|
||
closeRecordPop() {
|
||
this.$refs.recordPop.close();
|
||
},
|
||
|
||
async seleImg() {
|
||
try {
|
||
uni.showLoading({
|
||
title: '处理中...'
|
||
});
|
||
|
||
const {
|
||
base64,
|
||
path
|
||
} = await processImage();
|
||
console.log('最终Base64长度:', base64.length, path);
|
||
this.imagePath = path;
|
||
this.base64 = base64;
|
||
uni.showToast({
|
||
title: '上传成功'
|
||
});
|
||
} catch (err) {
|
||
console.error('处理失败', err);
|
||
uni.showToast({
|
||
title: '处理失败',
|
||
icon: 'none'
|
||
});
|
||
} finally {
|
||
uni.hideLoading();
|
||
}
|
||
|
||
},
|
||
|
||
validateForm() {
|
||
if (!this.name.trim()) {
|
||
uni.showToast({
|
||
title: '请填写姓名',
|
||
icon: 'none'
|
||
});
|
||
return false;
|
||
}
|
||
if (!this.phone.trim()) {
|
||
uni.showToast({
|
||
title: '请填写联系方式',
|
||
icon: 'none'
|
||
});
|
||
return false;
|
||
}
|
||
if (!this.workUnit.trim()) {
|
||
uni.showToast({
|
||
title: '请填写工作单位',
|
||
icon: 'none'
|
||
});
|
||
return false;
|
||
}
|
||
if (!this.address.trim()) {
|
||
uni.showToast({
|
||
title: '请填写收货地址',
|
||
icon: 'none'
|
||
});
|
||
return false;
|
||
}
|
||
if (!this.model.trim()) {
|
||
uni.showToast({
|
||
title: '请填写设备型号',
|
||
icon: 'none'
|
||
});
|
||
return false;
|
||
}
|
||
if (!this.number.trim()) {
|
||
uni.showToast({
|
||
title: '请填写出品编号',
|
||
icon: 'none'
|
||
});
|
||
return false;
|
||
}
|
||
if (!this.createTime.trim()) {
|
||
uni.showToast({
|
||
title: '请填写出品年月',
|
||
icon: 'none'
|
||
});
|
||
return false;
|
||
}
|
||
if (!this.imagePath) {
|
||
uni.showToast({
|
||
title: '请上传产品铭牌照片',
|
||
icon: 'none'
|
||
});
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
|
||
async submitForm() {
|
||
if (!this.validateForm()) {
|
||
return;
|
||
}
|
||
|
||
uni.showLoading({
|
||
title: '提交中...'
|
||
});
|
||
|
||
try {
|
||
const formData = {
|
||
UserId: this.userId,
|
||
Name: this.name,
|
||
Phone: this.phone,
|
||
Company: this.workUnit,
|
||
Address: this.address,
|
||
ProductModel: this.model,
|
||
ProductSerialNumber: this.number,
|
||
ProductDate: this.createTime,
|
||
ProductImage: this.base64
|
||
};
|
||
|
||
// 这里可以调用API提交数据
|
||
const result = await this.request('addRecord', 'POST', formData);
|
||
console.log(result);
|
||
uni.hideLoading();
|
||
if (result.code == 200) {
|
||
uni.showToast({
|
||
title: '提交成功,请等待审核',
|
||
icon: 'success'
|
||
});
|
||
this.closeReceivePop();
|
||
this.clearForm();
|
||
} else {
|
||
uni.showToast({
|
||
title: '提交失败,请重试',
|
||
icon: 'none'
|
||
});
|
||
|
||
}
|
||
|
||
|
||
} catch (error) {
|
||
uni.hideLoading();
|
||
uni.showToast({
|
||
title: '提交失败,请重试',
|
||
icon: 'none'
|
||
});
|
||
console.error('提交失败:', error);
|
||
}
|
||
},
|
||
|
||
clearForm() {
|
||
this.name = '';
|
||
this.phone = '';
|
||
this.workUnit = '';
|
||
this.address = '';
|
||
this.model = '';
|
||
this.number = '';
|
||
this.createTime = '';
|
||
this.imagePath = '';
|
||
this.base64 = '';
|
||
},
|
||
|
||
previewImage() {
|
||
if (this.imagePath) {
|
||
uni.previewImage({
|
||
current: this.imagePath,
|
||
urls: [this.imagePath],
|
||
success: function(res) {
|
||
console.log('预览图片成功');
|
||
},
|
||
fail: function(err) {
|
||
console.error('预览图片失败:', err);
|
||
uni.showToast({
|
||
title: '预览失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
});
|
||
}
|
||
},
|
||
|
||
|
||
// 开始自动滚动
|
||
startAutoScroll() {
|
||
this.stopAutoScroll(); // 先清除已有定时器
|
||
|
||
// 每16ms滚动一次 (约60帧/秒)
|
||
this.scrollTimer = setInterval(() => {
|
||
this.translateX -= this.scrollSpeed;
|
||
|
||
// 当滚动距离达到一个列表宽度时,重置位置实现无缝滚动
|
||
if (Math.abs(this.translateX) >= this.listWidth) {
|
||
this.translateX = 0;
|
||
}
|
||
|
||
this.isScrolling = true;
|
||
}, 16);
|
||
},
|
||
|
||
// 停止自动滚动
|
||
stopAutoScroll() {
|
||
if (this.scrollTimer) {
|
||
clearInterval(this.scrollTimer);
|
||
this.scrollTimer = null;
|
||
this.isScrolling = false;
|
||
}
|
||
},
|
||
|
||
// 监听滚动事件 (用于鼠标悬停暂停)
|
||
onScroll() {
|
||
// 可以在这里处理手动滚动后的逻辑
|
||
}
|
||
|
||
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.content {
|
||
width: 100%;
|
||
height: 100vh;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
position: relative;
|
||
}
|
||
|
||
.line {
|
||
width: 90%;
|
||
justify-content: center;
|
||
margin-top: 20rpx;
|
||
border-bottom: 0.86px solid #e3e3e3;
|
||
|
||
}
|
||
|
||
.auto-scroll-container {
|
||
width: 100%;
|
||
overflow: hidden;
|
||
/* 隐藏滚动条 */
|
||
padding: 20rpx 0;
|
||
}
|
||
|
||
.scroll-view {
|
||
width: 100%;
|
||
white-space: nowrap;
|
||
/* 防止换行 */
|
||
}
|
||
|
||
.scroll-content {
|
||
display: flex;
|
||
}
|
||
|
||
.image-list {
|
||
display: flex;
|
||
flex-direction: row;
|
||
}
|
||
|
||
.image-item {
|
||
width: 240rpx;
|
||
height: 200rpx;
|
||
margin-right: 20rpx;
|
||
border-radius: 8rpx;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.item-image {
|
||
width: 100%;
|
||
height: 100%;
|
||
display: block;
|
||
}
|
||
</style> |