diff --git a/app.json b/app.json index 0896c5a..14e0fdd 100644 --- a/app.json +++ b/app.json @@ -4,6 +4,7 @@ "pages/app-auth/index", "pages/category/index", "pages/cart/cart", + "pages/share/index", "pages/search/search", "pages/order-check/index", "pages/goods/goods", diff --git a/components/canvasdrawer/canvasdrawer.js b/components/canvasdrawer/canvasdrawer.js new file mode 100644 index 0000000..478816d --- /dev/null +++ b/components/canvasdrawer/canvasdrawer.js @@ -0,0 +1,330 @@ +/* global Component wx */ + +Component({ + properties: { + painting: { + type: Object, + value: { + view: [] + }, + observer(newVal, oldVal) { + if (!this.data.isPainting) { + if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) { + if (newVal && newVal.width && newVal.height) { + this.setData({ + showCanvas: true, + isPainting: true + }) + this.readyPigment() + } + } else { + if (newVal && newVal.mode !== 'same') { + this.triggerEvent('getImage', { + errMsg: 'canvasdrawer:samme params' + }) + } + } + } + } + } + }, + data: { + showCanvas: false, + width: 100, + height: 100, + tempFileList: [], + isPainting: false + }, + ctx: null, + cache: {}, + ready() { + console.log('ready'); + wx.removeStorageSync('canvasdrawer_pic_cache') + this.cache = wx.getStorageSync('canvasdrawer_pic_cache') || {} + this.ctx = wx.createCanvasContext('canvasdrawer', this) + }, + methods: { + readyPigment() { + const { + width, + height, + views + } = this.data.painting + this.setData({ + width, + height + }) + const inter = setInterval(() => { + if (this.ctx) { + clearInterval(inter) + this.ctx.clearActions() + this.ctx.save() + this.getImagesInfo(views) + } + }, 100) + }, + getImagesInfo(views) { + const imageList = [] + for (let i = 0; i < views.length; i++) { + if (views[i].type === 'image') { + imageList.push(this.getImageInfo(views[i].url)) + } + } + const loadTask = [] + for (let i = 0; i < Math.ceil(imageList.length / 8); i++) { + loadTask.push(new Promise((resolve, reject) => { + Promise.all(imageList.splice(i * 8, 8)).then(res => { + resolve(res) + }).catch(res => { + reject(res) + }) + })) + } + Promise.all(loadTask).then(res => { + let tempFileList = [] + for (let i = 0; i < res.length; i++) { + tempFileList = tempFileList.concat(res[i]) + } + this.setData({ + tempFileList + }) + this.startPainting() + }) + }, + startPainting() { + console.log('startPainting'); + const { + tempFileList, + painting: { + views + } + } = this.data + console.log(tempFileList) + for (let i = 0, imageIndex = 0; i < views.length; i++) { + // console.log(views[i]); + // console.log(views[i].type); + if (views[i].type === 'image') { + this.drawImage({ + ...views[i], + url: tempFileList[imageIndex] + }) + imageIndex++ + } else if (views[i].type === 'text') { + if (!this.ctx.measureText) { + wx.showModal({ + title: '提示', + content: '当前微信版本过低,无法使用 measureText 功能,请升级到最新微信版本后重试。' + }) + this.triggerEvent('getImage', { + errMsg: 'canvasdrawer:version too low' + }) + return + } else { + this.drawText(views[i]) + } + } else if (views[i].type === 'rect') { + this.drawRect(views[i]) + } + } + console.log('????????为什么'); + this.ctx.draw(false, () => { + console.log(this.cache); + wx.setStorageSync('canvasdrawer_pic_cache', this.cache) + const system = wx.getSystemInfoSync().system + if (/ios/i.test(system)) { + this.saveImageToLocal() + } else { + // 延迟保存图片,解决安卓生成图片错位bug。 + setTimeout(() => { + this.saveImageToLocal() + }, 800) + } + }) + }, + drawImage(params) { + console.log('drawImage'); + this.ctx.save() + const { + url, + top = 0, + left = 0, + width = 0, + height = 0, + borderRadius = 0, + deg = 0 + } = params + // if (borderRadius) { + // this.ctx.beginPath() + // this.ctx.arc(left + borderRadius, top + borderRadius, borderRadius, 0, 2 * Math.PI) + // this.ctx.clip() + // this.ctx.drawImage(url, left, top, width, height) + // } else { + if (deg !== 0) { + this.ctx.translate(left + width / 2, top + height / 2) + this.ctx.rotate(deg * Math.PI / 180) + this.ctx.drawImage(url, -width / 2, -height / 2, width, height) + } else { + this.ctx.drawImage(url, left, top, width, height) + } + // } + this.ctx.restore() + }, + drawText(params) { + console.log('drawText'); + this.ctx.save() + // console.log('drawText'); + const { + MaxLineNumber = 2, + breakWord = false, + color = 'black', + content = '', + fontSize = 16, + top = 0, + left = 0, + lineHeight = 20, + textAlign = 'left', + width, + bolder = false, + textDecoration = 'none' + } = params + + this.ctx.beginPath() + this.ctx.setTextBaseline('top') + this.ctx.setTextAlign(textAlign) + this.ctx.setFillStyle(color) + this.ctx.setFontSize(fontSize) + + if (!breakWord) { + this.ctx.fillText(content, left, top) + this.drawTextLine(left, top, textDecoration, color, fontSize, content) + } else { + let fillText = '' + let fillTop = top + let lineNum = 1 + for (let i = 0; i < content.length; i++) { + fillText += [content[i]] + if (this.ctx.measureText(fillText).width > width) { + if (lineNum === MaxLineNumber) { + if (i !== content.length) { + fillText = fillText.substring(0, fillText.length - 1) + '...' + this.ctx.fillText(fillText, left, fillTop) + this.drawTextLine(left, fillTop, textDecoration, color, fontSize, fillText) + fillText = '' + break + } + } + this.ctx.fillText(fillText, left, fillTop) + this.drawTextLine(left, fillTop, textDecoration, color, fontSize, fillText) + fillText = '' + fillTop += lineHeight + lineNum++ + } + } + this.ctx.fillText(fillText, left, fillTop) + this.drawTextLine(left, fillTop, textDecoration, color, fontSize, fillText) + } + this.ctx.restore() + if (bolder) { + this.drawText({ + ...params, + left: left + 0.3, + top: top + 0.3, + bolder: false, + textDecoration: 'none' + }) + } + }, + drawTextLine(left, top, textDecoration, color, fontSize, content) { + if (textDecoration === 'underline') { + this.drawRect({ + background: color, + top: top + fontSize * 1.2, + left: left - 1, + width: this.ctx.measureText(content).width + 3, + height: 1 + }) + } else if (textDecoration === 'line-through') { + this.drawRect({ + background: color, + top: top + fontSize * 0.6, + left: left - 1, + width: this.ctx.measureText(content).width + 3, + height: 1 + }) + } + }, + drawRect(params) { + this.ctx.save() + const { + background, + top = 0, + left = 0, + width = 0, + height = 0 + } = params + this.ctx.setFillStyle(background) + this.ctx.fillRect(left, top, width, height) + this.ctx.restore() + }, + getImageInfo(url) { + return new Promise((resolve, reject) => { + if (this.cache[url]) { + resolve(this.cache[url]) + } else { + const objExp = new RegExp(/^http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/) + if (objExp.test(url)) { + wx.getImageInfo({ + src: url, + complete: res => { + // console.log(res.errMsg); + if (res.errMsg === 'getImageInfo:ok') { + this.cache[url] = res.path + resolve(res.path) + } else { + this.triggerEvent('getImage', { + errMsg: 'canvasdrawer:download fail' + }) + reject(new Error('getImageInfo fail')) + } + } + }) + } else { + this.cache[url] = url + resolve(url) + } + } + }) + }, + saveImageToLocal() { + // console.log('saveImageToLocal'); + const { + width, + height + } = this.data + wx.canvasToTempFilePath({ + x: 0, + y: 0, + width, + height, + canvasId: 'canvasdrawer', + complete: res => { + if (res.errMsg === 'canvasToTempFilePath:ok') { + this.setData({ + showCanvas: false, + isPainting: false, + tempFileList: [] + }) + this.triggerEvent('getImage', { + tempFilePath: res.tempFilePath, + errMsg: 'canvasdrawer:ok' + }) + } else { + this.triggerEvent('getImage', { + errMsg: 'canvasdrawer:fail' + }) + } + } + }, this) + } + } +}) \ No newline at end of file diff --git a/components/canvasdrawer/canvasdrawer.json b/components/canvasdrawer/canvasdrawer.json new file mode 100644 index 0000000..32640e0 --- /dev/null +++ b/components/canvasdrawer/canvasdrawer.json @@ -0,0 +1,3 @@ +{ + "component": true +} \ No newline at end of file diff --git a/components/canvasdrawer/canvasdrawer.wxml b/components/canvasdrawer/canvasdrawer.wxml new file mode 100644 index 0000000..2d3c3d1 --- /dev/null +++ b/components/canvasdrawer/canvasdrawer.wxml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/canvasdrawer/canvasdrawer.wxss b/components/canvasdrawer/canvasdrawer.wxss new file mode 100644 index 0000000..186ebee --- /dev/null +++ b/components/canvasdrawer/canvasdrawer.wxss @@ -0,0 +1,4 @@ +.board { + position: fixed; + top: 2000rpx; +} \ No newline at end of file diff --git a/config/api.js b/config/api.js index 42360b2..8ec14a0 100755 --- a/config/api.js +++ b/config/api.js @@ -1,4 +1,5 @@ -const ApiRootUrl = 'http://localhost:8360/api/'; +const ApiRootUrl = 'http://localhost:8300/api/'; +// const ApiRootUrl = 'http://192.168.0.103:8300/api/'; // const ApiRootUrl = 'https://www.hiolabs.com/api/'; module.exports = { @@ -22,6 +23,7 @@ module.exports = { GoodsCount: ApiRootUrl + 'goods/count', //统计商品总数 GoodsDetail: ApiRootUrl + 'goods/detail', //获得商品的详情 GoodsList: ApiRootUrl + 'goods/list', //获得商品列表 + GoodsShare: ApiRootUrl + 'goods/goodsShare', //获得商品的详情 SaveUserId: ApiRootUrl + 'goods/saveUserId', // 收货地址 AddressDetail: ApiRootUrl + 'address/addressDetail', //收货地址详情 @@ -50,4 +52,6 @@ module.exports = { ShowSettings: ApiRootUrl + 'settings/showSettings', SaveSettings: ApiRootUrl + 'settings/save', SettingsDetail: ApiRootUrl + 'settings/userDetail', + GetBase64: ApiRootUrl + 'qrcode/getBase64', //获取商品详情二维码 + }; \ No newline at end of file diff --git a/pages/cart/cart.js b/pages/cart/cart.js index 360567a..409895e 100644 --- a/pages/cart/cart.js +++ b/pages/cart/cart.js @@ -19,15 +19,11 @@ Page({ startX: 0, //开始坐标 startY: 0, hasCartGoods: 0 - }, onLoad: function() { - }, - onReady: function() { // 页面渲染完成 - }, onShow: function() { // 页面显示 @@ -43,19 +39,14 @@ Page({ }, onHide: function() { // 页面隐藏 - }, onUnload: function() { // 页面关闭 - }, toIndexPage: function() { wx.switchTab({ url: '/pages/index/index', }); - // wx.redirectTo({ - // url: '/pages/payResult/payResult?status=1&orderId=192' - // }); }, getCartList: function() { let that = this; @@ -80,7 +71,6 @@ Page({ checkedAllStatus: that.isCheckedAll() }); }); - }, isCheckedAll: function() { //判断购物车商品已全选 @@ -143,7 +133,7 @@ Page({ } }, - updateCart: function (itemIndex,productId, number, id) { + updateCart: function(itemIndex, productId, number, id) { let that = this; util.request(api.CartUpdate, { productId: productId, @@ -158,8 +148,7 @@ Page({ let cartItem = that.data.cartGoods[itemIndex]; cartItem.number = number; that.getCartNum(); - } - else{ + } else { util.showErrorToast('库存不足了') } that.setData({ @@ -175,24 +164,19 @@ Page({ util.showErrorToast('删除左滑试试') } let number = (cartItem.number - 1 > 1) ? cartItem.number - 1 : 1; - - // cartItem.number = number; this.setData({ cartGoods: this.data.cartGoods, }); - this.updateCart(itemIndex,cartItem.product_id, number, cartItem.id); - }, - clicknone: function() { + this.updateCart(itemIndex, cartItem.product_id, number, cartItem.id); }, addNumber: function(event) { let itemIndex = event.target.dataset.itemIndex; let cartItem = this.data.cartGoods[itemIndex]; let number = Number(cartItem.number) + 1; - // cartItem.number = number; this.setData({ cartGoods: this.data.cartGoods, }); - this.updateCart(itemIndex,cartItem.product_id, number, cartItem.id); + this.updateCart(itemIndex, cartItem.product_id, number, cartItem.id); }, getCartNum: function() { util.request(api.CartGoodsCount).then(function(res) { diff --git a/pages/goods/goods.js b/pages/goods/goods.js index ac2307b..a318bd3 100644 --- a/pages/goods/goods.js +++ b/pages/goods/goods.js @@ -9,6 +9,7 @@ Page({ id: 0, goods: {}, gallery: [], + galleryImages:[], specificationList: [], productList: [], cartGoodsCount: 0, @@ -27,6 +28,39 @@ Page({ goodsNumber: 0, loading: 0, current: 0, + showShareDialog:0, + }, + hideDialog: function (e) { + let that = this; + that.setData({ + showShareDialog: false, + }); + }, + shareTo:function(){ + let userInfo = wx.getStorageSync('userInfo'); + if (userInfo == '') { + util.loginNow(); + return false; + } else { + this.setData({ + showShareDialog: !this.data.showShareDialog, + }); + } + }, + + createShareImage: function () { + let id = this.data.id; + wx.navigateTo({ + url: '/pages/share/index?goodsid=' + id + }) + }, + previewImage: function (e) { + let current = e.currentTarget.dataset.src; + let that = this; + wx.previewImage({ + current: current, // 当前显示图片的http链接 + urls: that.data.galleryImages // 需要预览的图片http链接列表 + }) }, saveUserId: function(e) { let formId = e.detail.formId; @@ -68,7 +102,7 @@ Page({ onShareAppMessage: function(res) { let id = this.data.id; let name = this.data.goods.name; - let image = this.data.goods.primary_pic_url; + let image = this.data.goods.list_pic_url; let userId = this.data.userId; return { title: name, @@ -101,6 +135,10 @@ Page({ checkedSpecText: '请选择规格和数量' }); } + let galleryImages = []; + for (const item of res.data.gallery) { + galleryImages.push(item.img_url); + } that.setData({ goods: res.data.info, goodsNumber: res.data.info.goods_number, @@ -108,8 +146,9 @@ Page({ specificationList: res.data.specificationList, productList: res.data.productList, checkedSpecPrice: res.data.info.retail_price, + galleryImages: galleryImages, }); - var checkedSpecPrice = res.data.info.retail_price; + wx.setStorageSync('goodsImage', res.data.info.https_pic_url); } wx.hideLoading(); }); @@ -229,7 +268,6 @@ Page({ return; } let checkedProduct = checkedProductArray[0]; - if (checkedProduct.goods_number < this.data.number) { //找不到对应的product信息,提示没有库存 this.setData({ @@ -276,11 +314,17 @@ Page({ }); }, onLoad: function(options) { + let id = 0; + var scene = decodeURIComponent(options.scene); + if (scene != 'undefined') { + id = scene; + } else { + id = options.id; + } this.setData({ - id: parseInt(options.id), // 这个是商品id - valueId: parseInt(options.id), + id: id, // 这个是商品id + valueId: id, }); - }, onShow: function() { let userInfo = wx.getStorageSync('userInfo'); diff --git a/pages/goods/goods.wxml b/pages/goods/goods.wxml index 5c10045..76c6748 100644 --- a/pages/goods/goods.wxml +++ b/pages/goods/goods.wxml @@ -13,9 +13,9 @@ - @@ -31,10 +31,10 @@ {{goods.goods_brief}} - + @@ -92,7 +92,7 @@ {{specificationList.name}} - {{item.value}} + {{item.value}} @@ -147,5 +147,24 @@ 商品已下架 - + + + + + 取消 + + \ No newline at end of file diff --git a/pages/goods/goods.wxss b/pages/goods/goods.wxss index 5453371..10bdf4b 100644 --- a/pages/goods/goods.wxss +++ b/pages/goods/goods.wxss @@ -524,9 +524,6 @@ width: 30%; line-height: 100rpx; color: #192841; - background: -webkit-linear-gradient(left, #fdbb43, #ff347d); /* Safari 5.1 - 6.0 */ - background: -o-linear-gradient(right, #fdbb43, #ff347d); /* Opera 11.1 - 12.0 */ - background: -moz-linear-gradient(right, #fdbb43, #ff347d); /* Firefox 3.6 - 15 *//* background: linear-gradient(to right, #131313, #000); 标准的语法(必须放在最后) */ background: linear-gradient(to right, #f8cd4e, #fae277); /* 标准的语法(必须放在最后) */ font-size: 28rpx; text-align: center; @@ -884,4 +881,140 @@ button::after { border-radius: 0; border: none; +} + +.dialog_show .dialog-mask2 { + display: block; +} + +.dialog-share .share-wrap { + background: #fafafa; + display: flex; + flex-direction: column; + padding: 30rpx; + width: 100%; + box-sizing: border-box; +} + + +.dialog-fixed { + position: fixed; + bottom: 0; + width: 100%; + transform: translateY(150%); + transition: all 0.4s ease; + z-index: 33; + display: flex; + flex-direction: column; + align-items: center; +} + +.dialog_show .dialog-share { + transform: translateY(0); + background: #e0e0e0; +} + +.dialog_show .dialog-mask { + display: block; +} + +.dialog_show .dialog-mask2 { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 10; + background: rgba(0, 0, 0, 0.5); + display: none; +} + +.dialog_show .dialog-mask2 { + display: block; +} + +.dialog-share .share-wrap { + background: #fafafa; + display: flex; + flex-direction: column; + padding: 30rpx; + width: 100%; + box-sizing: border-box; +} + +.dialog-share .cancel { + padding: 30rpx; + color: #333; + text-align: center; + font-size: 30rpx; + background: #fafafa; + width: 100%; + box-sizing: border-box; + margin-top: 12rpx; +} + +.share-wrap .top { + border-bottom: 1rpx solid #f1f1f1; + font-size: 28rpx; + color: #111; + text-align: center; + padding-bottom: 30rpx; +} + +.share-wrap .top .img { + width: 50rpx; + height: 50rpx; +} + +.share-wrap .content { + display: flex; + flex-direction: column; +} + +.share-wrap .content .tip { + font-size: 26rpx; + color: #666; + text-align: center; + padding: 30rpx 0; +} + +.share-wrap .content .share-block { + display: flex; + justify-content: center; + align-items: center; + padding-bottom: 4rpx; +} + +.share-wrap .content .share-block .block { + /* border: 1rpx solid #f0f0f0; */ + display: flex; + flex-direction: column; + align-items: center; + padding: 32rpx; + margin: 0 20rpx 0 0; + background: #fff; + border-radius: 20rpx; + box-shadow: 2rpx 2rpx 5rpx #f1f1f1; +} + +.share-wrap .content .share-block .block.share-btn::after { + border: 1rpx solid #f0f0f0; +} + +.share-wrap .content .share-block .block:last-child { + margin-right: 0; +} + +.share-wrap .content .share-block .block .img { + width: 50rpx; + height: 50rpx; + margin-bottom: 20rpx; +} + +.share-wrap .content .share-block .block .text { + text-align: center; + color: #555; + font-size: 26rpx; + height: 40rpx; + line-height: 40rpx; } \ No newline at end of file diff --git a/pages/index/index.wxml b/pages/index/index.wxml index ce6f523..2068e0f 100644 --- a/pages/index/index.wxml +++ b/pages/index/index.wxml @@ -10,7 +10,7 @@ 搜索, 共{{goodsCount}}款好物