diff --git a/src/api/login.js b/src/api/login.js index fa3c78a..6c51b68 100644 --- a/src/api/login.js +++ b/src/api/login.js @@ -7,9 +7,10 @@ import { LOGIN, GET_PHONE, USER_SHARE,USER_WALLET,RECHARGE_WALLET,USER_WXPAY,USE // 微信登陆 export const getCodeByWxLogin = () => { return new Promise((resolve, reject) => { - uni.login({ - provider: "weixin", + tt.login({ + provider: "toutiao", success: function (loginRes) { + // console.log(loginRes,'?1?') resolve(loginRes.code); }, fail: function (err) { @@ -22,7 +23,7 @@ export const getCodeByWxLogin = () => { import Store from "../store"; // 登录鉴权 -export const login = (phone) => { +export const login = (nickName, avatarUrl) => { return getCodeByWxLogin().then((code) => { // 从 vuex 中获取 referrerID(如果通过二维码扫描进入) const referrerID = Store.state.user?.referrerID || 0; @@ -31,12 +32,17 @@ export const login = (phone) => { url: LOGIN, method: "POST", data: { + nickName:nickName, + avatarUrl:avatarUrl, code: code, - // yaoqing_code: inviteCode || null, - phone: phone || null, - source: "wechat", - referrerID: Number(referrerID) || 0, - referrerType: "wechat" + source:'douyin', + referrerID:0, + referrerType:'douyin' + // // yaoqing_code: inviteCode || null, + // phone: phone || null, + // source: "wechat", + // referrerID: Number(referrerID) || 0, + // referrerType: "wechat" }, }).then((res) => { // 登录接口使用完 referrerID 后,清除一次,避免重复使用 diff --git a/src/api/url.js b/src/api/url.js index ecd420a..2bf651d 100644 --- a/src/api/url.js +++ b/src/api/url.js @@ -26,7 +26,7 @@ export const RECHARGE_WALLET = '/wallet/details' export const USER_WALLET = '/wallet/info' //钱包充值接口 -export const USER_WXPAY = '/wxpay/jsapi' +export const USER_WXPAY = '/ttpay/jsapi' //钱包充值金额 export const USER_RECHARGE = '/recharge/bonus-list' //积分充值列表 @@ -186,7 +186,7 @@ export const HOME_ORDERS_CANCEL = "/home/orders/cancel"; // 校验节假日费用 export const CHECK_HOLIDAY_FEE = "/check_holiday_fee"; //支付订单 -export const PAY_ORDER = "/wxpay/jsapi"; +export const PAY_ORDER = "/ttpay/jsapi"; //取消订单 export const CANCEL_ORDER = "/app/chongwu_order/order_quxiao"; @@ -235,7 +235,7 @@ export const CREATE_ORDER_NEW = "/product/order/create"; // 创建购物车订单 export const CREATE_CART_ORDER = "/product/order/create"; // 订单支付 -export const PAY_ORDER_NEW = "/wxpay/jsapi"; +export const PAY_ORDER_NEW = "/ttpay/jsapi"; // 订单列表 export const SHOP_ORDER_LIST = "/product/order/list"; // 订单详情 @@ -304,3 +304,5 @@ export const HOMETRAINING_ORDERS_CANCEL = '/hometraining/orders/cancel' // 撤销申请(领养申请) export const ADOPTIONS_PET_APPLY_CANCEL = '/adoptions/pet/apply/cancel' + + diff --git a/src/components/NavBar.vue b/src/components/NavBar.vue index 7b79958..b7df0a9 100644 --- a/src/components/NavBar.vue +++ b/src/components/NavBar.vue @@ -1,6 +1,6 @@ @@ -107,7 +114,7 @@ export default { }, onReady() { // 获取 wxml-to-canvas 组件实例 - this.widget = this.$refs.widget || this.selectComponent('.widget'); + // this.widget = this.$refs.widget || this.selectComponent('.widget'); }, methods: { getCertificates(data) { @@ -125,6 +132,27 @@ export default { closeModal() { this.showModal = false; }, + wrapText(ctx, text, x, y, maxWidth, lineHeight) { + const words = text.split(''); + let line = ''; + let currentY = y; + + for (let i = 0; i < words.length; i++) { + const testLine = line + words[i]; + const metrics = ctx.measureText(testLine); + const testWidth = metrics.width; + + if (testWidth > maxWidth && i > 0) { + ctx.fillText(line, x, currentY); + line = words[i]; + currentY += lineHeight; + } else { + line = testLine; + } + } + + ctx.fillText(line, x, currentY); + }, onScroll(e) { // 获取滚动位置(单位:px) const scrollLeft = e.detail.scrollLeft; @@ -141,138 +169,172 @@ export default { this.currentPage = newPage; } }, - async saveCurrentImage() { - // 保存当前图片 - 使用 wxml-to-canvas 生成 - const currentIndex = this.currentPage - 1; - const currentItem = this.certificateList[currentIndex]; - if (!currentItem) { - uni.showToast({ - title: '证书信息加载中,请稍候', - icon: 'none' - }); - return; - } - - // 存储当前证书信息到 data,供模板使用 - this.currentCertificateItem = currentItem; - - // 获取组件实例 - 多种方式尝试 - if (!this.widget) { - this.widget = this.$refs.widget; - } - if (!this.widget) { - this.widget = this.selectComponent('.widget'); - } - if (!this.widget) { - // 延迟重试一次 - await new Promise(resolve => setTimeout(resolve, 100)); - this.widget = this.$refs.widget || this.selectComponent('.widget'); - } - - if (!this.widget) { - uni.hideLoading(); - uni.showToast({ - title: '组件初始化失败,请重试', - icon: 'none', - duration: 3000 - }); - console.error('wxml-to-canvas 组件获取失败'); - return; - } - - // 检查组件方法是否可用 - if (typeof this.widget.renderToCanvas !== 'function') { - uni.hideLoading(); - uni.showToast({ - title: '组件方法不可用,请重试', - icon: 'none', - duration: 3000 - }); - console.error('renderToCanvas 方法不存在'); - return; - } - - uni.showLoading({ - title: '生成图片中...', - mask: true - }); - - try { - // 固定画布尺寸 - const canvasWidth = 317; - const canvasHeight = 224; - - // 更新 canvas 尺寸 - this.canvasWidth = canvasWidth; - this.canvasHeight = canvasHeight; - - await this.$nextTick(); - - // 生成证书的 wxml 和 style(使用固定尺寸) - const { wxml, style } = this.generateCertificateTemplate(); - - // 渲染到 canvas - const container = await this.widget.renderToCanvas({ wxml, style }); - - // 转换为图片 - const res = await this.widget.canvasToTempFilePath({ - fileType: 'png', - quality: 1, - width: this.canvasWidth, - height: this.canvasHeight - }); - - if (!res || !res.tempFilePath) { - throw new Error('生成图片路径失败'); + async loadImage(src) { + console.log('正在加载图片:', src); + return new Promise((resolve, reject) => { + tt.downloadFile({ + url: src, + success: (res) => { + if (res.statusCode === 200) { + console.log('图片加载成功:', res.tempFilePath); + resolve(res.tempFilePath); + } else { + console.error('图片加载失败,状态码:', res.statusCode); + reject(new Error(`图片加载失败,状态码: ${res.statusCode}`)); } - - // 保存到相册 - uni.saveImageToPhotosAlbum({ - filePath: res.tempFilePath, - success: () => { - uni.hideLoading(); - uni.showToast({ - title: '保存成功', - icon: 'success' - }); - }, - fail: (err) => { - uni.hideLoading(); - const errMsg = err?.errMsg || '未知错误'; - uni.showToast({ - title: '保存失败,请检查相册权限', - icon: 'none', - duration: 3000 - }); - console.error('保存图片失败:', errMsg, err); + }, + fail: (err) => { + console.error('图片加载失败:', err.errMsg); + reject(new Error(`图片加载失败: ${err.errMsg}`)); + } + }); + }); +}, + +async saveCurrentImage() { + const currentIndex = this.currentPage - 1; + const currentItem = this.certificateList[currentIndex]; + + if (!currentItem) { + uni.showToast({ + title: '证书信息加载中,请稍候', + icon: 'none' + }); + return; + } + + this.currentCertificateItem = currentItem; + + uni.showLoading({ + title: '生成图片中...', + mask: true + }); + + try { + // 获取 Canvas 节点 + const query = tt.createSelectorQuery(); + const canvasNode = await new Promise((resolve, reject) => { + query + .select('#myCanvas') + .fields({ node: true, size: true }) + .exec((res) => { + if (res[0]) { + resolve(res[0].node); + } else { + reject(new Error('Canvas 节点获取失败')); } }); - } catch (error) { + }); + + // 获取 2D 上下文 + const ctx = canvasNode.getContext('2d'); + const dpr = tt.getSystemInfoSync().pixelRatio; + canvasNode.width = this.canvasWidth * dpr; + canvasNode.height = this.canvasHeight * dpr; + ctx.scale(dpr, dpr); + + // 清空画布 + ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight); + + // 加载并绘制背景图 + const backgroundImgPath = await this.loadImage(`${this.imgPrefix}certificateGround.png`); + const backgroundImg = canvasNode.createImage(); + backgroundImg.src = backgroundImgPath; + await new Promise((resolve) => { + backgroundImg.onload = () => { + ctx.drawImage(backgroundImg, 0, 0, this.canvasWidth, this.canvasHeight); + resolve(); + }; + }); + + // 设置字体样式 + ctx.font = '20px sans-serif'; + ctx.fillStyle = '#FF19A0'; + ctx.textAlign = 'center'; + + // 绘制证书标题 + const title = currentItem.title || '为爱续航证书'; + ctx.fillText(title, this.canvasWidth / 2, 50); + + // 绘制英文标题 + ctx.font = '12px sans-serif'; + const titleEn = currentItem.title_en || 'Certificate of Love Endurance'; + ctx.fillText(titleEn, this.canvasWidth / 2, 70); + + // 绘制用户名 + ctx.font = '16px sans-serif'; + const userName = this.userName || '周佳佳'; + ctx.fillText(userName, this.canvasWidth / 2, 100); + + // 绘制描述文本 + ctx.font = '12px sans-serif'; + ctx.fillStyle = '#333333'; + ctx.textAlign = 'left'; + const description = `您累计捐赠${currentItem.source_value || 0}克粮,为毛孩子奉献爱心,点燃希望,感谢您的捐赠让世界变得更温暖。`; + this.wrapText(ctx, description, 20, 130, this.canvasWidth - 40, 16); + + // 绘制结尾文字 + ctx.fillText('特发此证,以表谢忱!', 20, 200); + + // 绘制证书编号 + ctx.font = '10px sans-serif'; + ctx.fillStyle = '#FF19A0'; + ctx.textAlign = 'right'; + const certificateNo = `证书编号: ${currentItem.certificate_no || currentItem.id || '234546678896666788'}`; + ctx.fillText(certificateNo, this.canvasWidth - 20, this.canvasHeight - 20); + + // 绘制证书图标 + const badgeImgPath = await this.loadImage(currentItem.certificate_url); + const badgeImg = canvasNode.createImage(); + badgeImg.src = badgeImgPath; + await new Promise((resolve) => { + badgeImg.onload = () => { + ctx.drawImage(badgeImg, this.canvasWidth - 60, this.canvasHeight - 80, 40, 40); + resolve(); + }; + }); + + // 导出为 base64 数据 + const dataURL = canvasNode.toDataURL('image/png'); + const base64Data = dataURL.replace(/^data:image\/\w+;base64,/, ''); + + // 将 base64 数据写入临时文件 + const tempFilePath = `${tt.env.USER_DATA_PATH}/temp_certificate.png`; + const fs = tt.getFileSystemManager(); + fs.writeFileSync(tempFilePath, base64Data, 'base64'); + + // 保存到相册 + uni.saveImageToPhotosAlbum({ + filePath: tempFilePath, + success: () => { uni.hideLoading(); - const errorMsg = error?.message || error?.toString() || '未知错误'; - const errorInfo = `生成图片失败: ${errorMsg}`; - console.log(errorInfo, '--=') uni.showToast({ - title: errorInfo.length > 20 ? '生成图片失败,请重试' : errorInfo, + title: '保存成功', + icon: 'success' + }); + }, + fail: (err) => { + uni.hideLoading(); + const errMsg = err?.errMsg || '未知错误'; + uni.showToast({ + title: '保存失败,请检查相册权限', icon: 'none', duration: 3000 }); - // 使用多种方式记录错误,确保线上环境能捕获 - console.error('生成证书图片失败:', error); - console.error('错误详情:', { - message: error?.message, - stack: error?.stack, - error: error - }); - // 如果 console 不可用,尝试通过其他方式记录 - if (typeof uni.reportError === 'function') { - uni.reportError({ - error: errorInfo, - errorInfo: JSON.stringify(error) - }); - } + console.error('保存图片失败:', errMsg, err); } - }, + }); + } catch (error) { + uni.hideLoading(); + const errorMsg = error?.message || error?.toString() || '未知错误'; + uni.showToast({ + title: errorMsg.length > 20 ? '生成图片失败,请重试' : errorMsg, + icon: 'none', + duration: 3000 + }); + console.error('生成证书图片失败:', error); + } +}, generateCertificateTemplate() { // 使用存储的证书信息 const item = this.currentCertificateItem; diff --git a/src/pageHome/welfare/components/donation-confirm-modal.vue b/src/pageHome/welfare/components/donation-confirm-modal.vue index 4bbf763..4c84400 100644 --- a/src/pageHome/welfare/components/donation-confirm-modal.vue +++ b/src/pageHome/welfare/components/donation-confirm-modal.vue @@ -1,5 +1,5 @@ + + diff --git a/src/pages/client/news/index.vue b/src/pages/client/news/index.vue index 32270c2..45a1f96 100644 --- a/src/pages/client/news/index.vue +++ b/src/pages/client/news/index.vue @@ -14,10 +14,12 @@ getNoticeList } from "../../../api/notice"; import NewsItem from "./components/NewsItem.vue"; +import ListPageTemp from "./components/ListPageTemp.vue"; import { imgPrefix } from "@/utils/common"; export default { components: { NewsItem, + ListPageTemp }, data() { return { diff --git a/src/pages/client/order/after-sale.vue b/src/pages/client/order/after-sale.vue index b645045..588d277 100644 --- a/src/pages/client/order/after-sale.vue +++ b/src/pages/client/order/after-sale.vue @@ -24,7 +24,7 @@ + + diff --git a/src/pages/client/order/create.vue b/src/pages/client/order/create.vue index 9cfe3af..e8cabfb 100644 --- a/src/pages/client/order/create.vue +++ b/src/pages/client/order/create.vue @@ -93,8 +93,8 @@ - - 微信支付 + + 抖音支付 { - const payData = res?.data || {}; - console.log(payData,'--=') - uni.requestPayment({ - provider: "wxpay", - timeStamp: payData.timeStamp, - nonceStr: payData.nonceStr, - package: payData.package, - signType: payData.signType, - paySign: payData.paySign, + tt.pay({ + orderInfo: { + order_id:res.data.orderInfo.order_id, + order_token:res.data.orderInfo.order_token, + }, + service:5, success: (res) => { console.log(res,'--==') uni.hideLoading(); diff --git a/src/pages/client/order/details.vue b/src/pages/client/order/details.vue index 63be160..7627041 100644 --- a/src/pages/client/order/details.vue +++ b/src/pages/client/order/details.vue @@ -227,8 +227,8 @@ - - 微信支付 + + 抖音支付 { - const payData = res?.data || {}; - uni.requestPayment({ - provider: "wxpay", - timeStamp: payData.timeStamp, - nonceStr: payData.nonceStr, - package: payData.package, - signType: payData.signType, - paySign: payData.paySign, + tt.pay({ + orderInfo: { + order_id:res.data.orderInfo.order_id, + order_token:res.data.orderInfo.order_token, + }, + service:5, success: (res) => { uni.hideLoading(); uni.showToast({ diff --git a/src/pages/client/order/list.vue b/src/pages/client/order/list.vue index 1d36eb5..1f9a1b6 100644 --- a/src/pages/client/order/list.vue +++ b/src/pages/client/order/list.vue @@ -61,8 +61,8 @@ - - 微信 + + 抖音 @@ -99,7 +99,7 @@ + + diff --git a/src/pages/client/recharge/components/points-content.vue b/src/pages/client/recharge/components/points-content.vue index 916b98f..d415a2e 100644 --- a/src/pages/client/recharge/components/points-content.vue +++ b/src/pages/client/recharge/components/points-content.vue @@ -32,8 +32,8 @@ - - 微信 + + 抖音 @@ -141,13 +141,12 @@ walletWxpay(data).then((res) => { uni.hideLoading(); // 使用获取的支付参数进行支付 - uni.requestPayment({ - provider: 'wxpay', - timeStamp: res.data.timeStamp, - nonceStr: res.data.nonceStr, - package: res.data.package, - signType: res.data.signType, - paySign: res.data.paySign, + tt.pay({ + orderInfo: { + order_id:res.data.orderInfo.order_id, + order_token:res.data.orderInfo.order_token, + }, + service:5, success: (payRes) => { uni.showToast({ title: '支付成功', diff --git a/src/pages/client/recharge/index.vue b/src/pages/client/recharge/index.vue index 4ea0215..78da6c7 100644 --- a/src/pages/client/recharge/index.vue +++ b/src/pages/client/recharge/index.vue @@ -63,8 +63,8 @@ - - 微信 + + 抖音 @@ -188,12 +188,12 @@ }; walletWxpay(data).then((res) => { // 使用获取的支付参数进行支付 - uni.requestPayment({ - timeStamp: res.data.timeStamp, // 确保这些字段都正确 - nonceStr: res.data.nonceStr, - package: res.data.package, - signType: res.data.signType, - paySign: res.data.paySign, + tt.pay({ + orderInfo: { + order_id:res.data.orderInfo.order_id, + order_token:res.data.orderInfo.order_token, + }, + service:5, success: (res) => { this.buyService(this.user_id); // console.log('支付成功:', res); diff --git a/src/pages/client/recharge/invite-friends.vue b/src/pages/client/recharge/invite-friends.vue index fc350c2..b7da045 100644 --- a/src/pages/client/recharge/invite-friends.vue +++ b/src/pages/client/recharge/invite-friends.vue @@ -37,7 +37,7 @@ + + diff --git a/src/pages/client/remark/list.vue b/src/pages/client/remark/list.vue index da51757..b1b6c24 100644 --- a/src/pages/client/remark/list.vue +++ b/src/pages/client/remark/list.vue @@ -16,7 +16,7 @@ + \ No newline at end of file diff --git a/src/wxcomponents/wxml-to-canvas/miniprogram_dist/index.vue b/src/wxcomponents/wxml-to-canvas/miniprogram_dist/index.vue new file mode 100644 index 0000000..fa444af --- /dev/null +++ b/src/wxcomponents/wxml-to-canvas/miniprogram_dist/index.vue @@ -0,0 +1,794 @@ + + + + \ No newline at end of file