diff --git a/.gitignore b/.gitignore index 6704566..f13be61 100644 --- a/.gitignore +++ b/.gitignore @@ -102,3 +102,8 @@ dist # TernJS port file .tern-port + +# settings +miniprogram/settings/settings.pro.js +# cloud dev settings +cloudfunctions/main/settings.js \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..f5906c3 --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +# mini_shop + +### 配置文件说明 + +`const settings = { + app_id: '', // 微信小程序appid + app_secret: '' // 微信小程序appsecret, + enviroment: 'pro' // 当前环境, + cloudenv: 'cake-dev-rlbcr' // 云开发环境名称, + HomePage: '/pages/home/home' // 首页路径, + // tabs页面 + TAB_URLS: [ + '/pages/home/home', + '/pages/me/me', + '/pages/goods/goods', + ], + // 主题颜色 + Theme: { + BgColor: '#d9262f', + lightColor: '#F0f0f2', + lightColor2: '#f4f4f2', + blueColor: '#7dd3da', + redColor: '#e67774', + greenColor: '#8dbb6a' + }, + // 提示信息固定时间(短) + shortTipDuration: 2000, + // 提示信息固定时间(长) + longTipDuration: 4000 +};` \ No newline at end of file diff --git a/cloudfunctions/main/address.js b/cloudfunctions/main/address.js new file mode 100644 index 0000000..8970cc1 --- /dev/null +++ b/cloudfunctions/main/address.js @@ -0,0 +1,149 @@ +const db = require('./db') + +const queryAddress = async (event, wxContext, user) => { + return { + status: true, + message: 'ok', + data: { + entities: user.address + } + } +} + +const getAddress = async (event, wxContext, user) => { + for (let item of user.address) { + if (item.id == event.addressId) { + return { + status: true, + message: 'ok', + data: { + entity: item + } + } + } + } + return { + status: false, + message: 'address_not_found' + } + +} + +const saveAddress = async (event, wxContext, user) => { + let result = null + for (let i = 0; i < user.address.length; i++) { + if (user.address[i].id == event.addressId) { + user.address[i] = event.address + try { + result = await db.collection('user').doc(user._id).update({ + data: { + address: user.address + } + }) + } catch (e) { + console.error(e) + } + if (!result) { + return { + status: false, + message: 'update_address_error' + } + } else { + return { + status: true, + message: 'ok' + } + } + + } + } + return { + status: false, + message: 'address_not_found' + } +} + + +const deleteAddress = async (event, wxContext, user) => { + let result = null + for (let i = 0; i < user.address.length; i++) { + if (user.address[i].id == event.addressId) { + user.address.splice(i, 1) + try { + result = await db.collection('user').doc(user._id).update({ + data: { + address: user.address + } + }) + } catch (e) { + console.error(e) + } + if (!result) { + return { + status: false, + message: 'update_address_error' + } + } else { + return { + status: true, + message: 'ok' + } + } + + } + } + return { + status: false, + message: 'address_not_found' + } +} + +const setDefaultAddress = async (event, wxContext, user) => { + let result = null + let index = null + for (let i = 0; i < user.address.length; i++) { + if (user.address[i].id == event.addressId) { + user.address[i].isDefault = true + index = i + } else { + user.address[i].isDefault = false + } + } + + if (index === null) { + return { + status: false, + message: 'address_not_found' + } + } + + try { + result = await db.collection('user').doc(user._id).update({ + data: { + address: user.address + } + }) + } catch (e) { + console.error(e) + } + if (!result) { + return { + status: false, + message: 'setdefault_address_error' + } + } else { + return { + status: true, + message: 'ok' + } + } +} + + +module.exports = { + queryAddress: queryAddress, + getAddress: getAddres, + saveAddress: saveAddress, + deleteAddress: deleteAddress, + setDefaultAddress: setDefaultAddress +} diff --git a/cloudfunctions/main/admin_funcs.js b/cloudfunctions/main/admin_funcs.js new file mode 100644 index 0000000..a8ea460 --- /dev/null +++ b/cloudfunctions/main/admin_funcs.js @@ -0,0 +1,617 @@ +const cloud = require('wx-server-sdk') +const db = require('./db') +const constant = require('./constant') +const moment = require('moment') + +const _ = db.command + +async function getOrder(orderId) { + let order = await db.collection('order').doc(orderId).get() + console.log('order:', order) + if (order && order.errMsg == 'document.get:ok' && order.data && order.data.is_enable) { + return order + } +} + + +// 搜索用户 +const getUsers = async (event, wxContext, user) => { + console.log(user) + let result = null + let page = event.page || 1; + page = parseInt(page) + let page_size = event.page_size || 20; + page_size = parseInt(page_size) + let skip = (page - 1) * page_size + try { + if (event.search_text) { + result = await db.collection('user').orderBy('create_at', 'desc').where(_.or([{ _id: _.eq(event.search_text) }, { nickName: _.eq(event.search_text) }, { realName: _.eq(event.search_text) }, { mobile_phone: _.eq(event.search_text) }])).where({ is_enable: true }).skip(skip).limit(page_size).get() + } else { + result = await db.collection('user').orderBy('update_at', 'desc').where({ is_enable: true }).skip(skip).limit(page_size).get() + } + + console.log('result:', result) + } catch (e) { + console.error(e) + } + if (!result) { + return { + status: false, + message: 'get_users_error' + } + } + return { + status: true, + message: 'ok', + data: { + entities: result.data, + page: page, + page_size: page_size + } + } +} + + +// 搜索用户 +const getUserOrders = async (event, wxContext, user) => { + console.log(user) + console.log('event:', event) + let result = null + try { + if (event.user_id) { + result = await db.collection('order').orderBy('create_at', 'desc').where({ openid: event.user_id, is_enable: true }).get() + } else if (event.orderid) { + result = await db.collection('order').orderBy('create_at', 'desc').where({ is_enable: true, _id: event.orderid }).get() + } else if (event.start_at && !event.start_at) { + var start_at = moment(event.start_at).toDate() + result = await db.collection('order').orderBy('create_at', 'desc').where({ is_enable: true, create_at: _.gte(start_at) }).get() + } else if (event.end_at && !event.end_at) { + var end_at = moment(event.end_at).toDate() + result = await db.collection('order').orderBy('create_at', 'desc').where({ is_enable: true, create_at: _.lte(end_at) }).get() + } else if (event.start_at && event.end_at) { + var start_at = moment(event.start_at).toDate() + var end_at = moment(event.end_at).toDate() + console.log('start', start_at) + console.log('end', end_at) + result = await db.collection('order').orderBy('create_at', 'desc').where({ is_enable: true, create_at: _.and(_.gte(start_at), _.lt(end_at)) }).get() + } else { + result = await db.collection('order').orderBy('create_at', 'desc').where({ is_enable: true }).get() + } + + console.log('result:', result) + } catch (e) { + console.error(e) + } + if (!result) { + return { + status: false, + message: 'get_user_orders_error' + } + } + return { + status: true, + message: 'ok', + data: { + entities: result.data + } + } +} + + +// 是否是管理员 +const getIsAdmin = async (event, wxContext, user) => { + let admin = await db.collection('admin').doc(user._id) + if (admin && admin.errMsg == 'document.get:ok' && admin.data) { + return { + status: true, + message: 'ok', + data: { + entity: admin.data + } + } + } else { + return { + status: false, + message: 'not_admin' + } + } +} + + +// 修改订单地址 +const updateOrderAddress = async (event, wxContext, user) => { + let result = null + try { + result = await getOrder(event.orderId) + console.log('result:', result) + } catch (e) { + console.error(e) + } + + if (!result || !result.data) { + return { + status: false, + message: 'order_not_found' + } + } + + if (!event.addressInfo.cityName || !event.addressInfo.detailInfo || !event.addressInfo.provinceName || !event.addressInfo.telNumber || !event.addressInfo.userName) { + return { + status: false, + message: 'addressInfo_detail_error' + } + } + + let updateResult = null + try { + updateResult = await db.collection('order').doc(event.orderId).update({ + data: { + addressInfo: event.addressInfo, + admin_update_at: new Date() + } + }) + if (updateResult.stats && updateResult.stats.updated !== 1) { + return { + status: false, + message: 'order_not_found_when_update' + } + } + } catch (e) { + console.error(e) + } + + result = await getOrder(event.orderId) + + return { + status: true, + message: 'ok', + data: { + entity: result.data + } + } +} + + +// 修改订单状态 +const updateOrderStatus = async (event, wxContext, user) => { + + let result = null + try { + result = await getOrder(event.orderId) + console.log('result:', result) + } catch (e) { + console.error(e) + } + + if (!result || !result.data) { + return { + status: false, + message: 'order_not_found' + } + } + + if (!constant.PayStatus[event.status]) { + return { + status: false, + message: 'pay_status_error' + } + } + + + let updateResult = null + try { + updateResult = await db.collection('order').doc(event.orderId).update({ + data: { + status: event.status, + admin_update_at: new Date() + } + }) + if (updateResult.stats && updateResult.stats.updated !== 1) { + return { + status: false, + message: 'order_not_found_when_update_order_status' + } + } + } catch (e) { + console.error(e) + } + + result = await getOrder(event.orderId) + + return { + status: true, + message: 'ok', + data: { + entities: result.data + } + } + +} + +// 修改发货状态 +const updateDeliveryStatus = async (event, wxContext, user) => { + + let result = null + try { + result = await getOrder(event.orderId) + console.log('result:', result) + } catch (e) { + console.error(e) + } + + if (!result || !result.data) { + return { + status: false, + message: 'order_not_found' + } + } + + if (!constant.DeliveryStatus[event.status]) { + return { + status: false, + message: 'delivery_status_error' + } + } + + let updateResult = null + try { + let updateData = { + delivery_status: event.status, + admin_update_at: new Date() + } + + if (event.status == 'shipping' || event.status == 'delivering') { + updateData.deliveryInfo = event.deliveryInfo + } + + updateResult = await db.collection('order').doc(event.orderId).update({ + data: updateData + }) + if (updateResult.stats && updateResult.stats.updated !== 1) { + return { + status: false, + message: 'order_not_found_when_update_delivery_status' + } + } + } catch (e) { + console.error(e) + } + + result = await getOrder(event.orderId) + + return { + status: true, + message: 'ok', + data: { + entities: result.data + } + } +} + +// 修改订单金额 +const updateOrderTotal = async (event, wxContext, user) => { + + if (!event.total) { + return { + status: false, + message: 'total_required' + } + } + + let result = null + try { + result = await getOrder(event.orderId) + console.log('result:', result) + } catch (e) { + console.error(e) + } + + if (!result || !result.data) { + return { + status: false, + message: 'order_not_found' + } + } + + let order = result.data; + console.log('user:', user) + let total = parseFloat(event.total) + console.log('total:', total) + let order_total = parseFloat(order.orderInfo.total) + console.log('order_total:', order_total) + let balance = parseFloat(user.balance) + let difference = total - order_total + + if ((balance + difference) < 0) { + return { + status: false, + message: 'update_order_total_error' + } + } + + let updateLogs = order.updateLogs || [] + updateLogs.push({ + total: total, + order_total: order_total, + balance: user.balance, + user_id: user._id, + create_at: new Date() + }) + + let orderInfo = order.orderInfo + orderInfo.total = total + + let updateResult = null + try { + let updateData = { + admin_update_at: new Date(), + updateLogs: updateLogs, + amount: total, + orderInfo: orderInfo + } + + updateResult = await db.collection('order').doc(event.orderId).update({ + data: updateData + }) + if (updateResult.stats && updateResult.stats.updated !== 1) { + return { + status: false, + message: 'order_not_found_when_update_total' + } + } + } catch (e) { + console.error(e) + } + + let updateBalanceResult = null + console.log('difference:', difference) + try { + updateBalanceResult = await db.collection('user').doc(order.openid).update({ + data: { + balance: db.command.inc(-difference), + update_at: new Date(), + update_by: user._id + } + }) + console.log('updateBalanceResult:', updateBalanceResult) + } catch (e) { + console.error(e) + } + if (!updateBalanceResult || updateBalanceResult.errMsg !== 'document.update:ok') { + return { + status: false, + message: 'update_balance_error_when_update_total' + } + } + + result = await getOrder(event.orderId) + + return { + status: true, + message: 'ok', + data: { + entities: result.data + } + } + + +} + +// 修改订单备注 +const updateOrderRemarks = async (event, wxContext, user) => { + + if (!event.remarks && !event.admin_remarks) { + return { + status: false, + message: 'remarks_required' + } + } + + let result = null + try { + result = await getOrder(event.orderId) + console.log('result:', result) + } catch (e) { + console.error(e) + } + + if (!result || !result.data) { + return { + status: false, + message: 'order_not_found' + } + } + + let updateResult = null + try { + + updateResult = await db.collection('order').doc(event.orderId).update({ + data: { + admin_remarks: event.admin_remarks, + remarks: event.remarks, + admin_update_at: new Date() + } + }) + if (updateResult.stats && updateResult.stats.updated !== 1) { + return { + status: false, + message: 'order_not_found_when_update_delivery_status' + } + } + } catch (e) { + console.error(e) + } + + result = await getOrder(event.orderId) + + return { + status: true, + message: 'ok', + data: { + entities: result.data + } + } + +} + + + +// 取消订单 +const cancelOrder = async (event, wxContext, user) => { + + let result = null + try { + result = await getOrder(event.orderId) + console.log('result:', result) + } catch (e) { + console.error(e) + } + + if (!result || !result.data) { + return { + status: false, + message: 'order_not_found' + } + } + + let order = result.data; + + let updateResult = null + try { + let updateData = { + is_cancel: true, + admin_update_at: new Date() + } + + if (event.refund_amount){ + status: 'refund' + } + if (parseFloat(event.refund_amount) > parseFloat(order.total)) { + return { + status: false, + message: 'refund_amount_error' + } + } + + updateData.refund_amount = event.refund_amount + + updateResult = await db.collection('order').doc(event.orderId).update({ + data: updateData + }) + if (updateResult.stats && updateResult.stats.updated !== 1) { + return { + status: false, + message: 'order_not_found_when_cancel' + } + } + } catch (e) { + console.error(e) + } + + + if (event.refund_amount) { + let updateUserResult = null + try { + updateUserResult = await db.collection('user').doc(order.openid).update({ + data: { + balance: db.command.inc(parseFloat(event.refund_amount)) + } + }) + console.log('updateUserResult:', updateUserResult) + } catch (e) { + console.error(e) + } + if (!updateUserResult || updateUserResult.errMsg !== 'document.update:ok') { + return { + status: false, + message: 'update_balance_error_when_cancel_order' + } + } + } + + result = await getOrder(event.orderId) + + return { + status: true, + message: 'ok', + data: { + entities: result.data + } + } + +} + + + + +// 增加管理员推送的token +const increasePushToken = async (event, wxContext, user) => { + let result = null + let expire_date = moment().subtract(7, 'days').toDate() + try { + result = await db.collection('admin_push_token').where({ user_id: user._id, create_at: _.lte(expire_date) }).remove() + console.log('result:', result) + } catch (e) { + console.error(e) + } + + try { + let record = { + user_id: user._id, + token: event.token, + create_at: new Date() + } + console.log(record) + result = await db.collection('admin_push_token').add({ data: record}) + }catch(e) { + console.error(e) + result = null + } + console.log(result) + if (!result || result.errMsg !== 'collection.add:ok') { + return { + status: false, + message: 'fail_to_increase_admin_token' + } + } + + try { + result = await db.collection('admin_push_token').where({ user_id: user._id }).count() + console.log('result:', result) + } catch (e) { + console.error(e) + result = null + } + + + if (!result || result.errMsg !== 'collection.count:ok') { + return { + status: false, + message: 'fail_to_get_admin_token_count' + } + } + + return { + status: true, + data: { + total: result.total + }, + message: 'ok' + } + +} + + + + +module.exports = { + getUsers: getUsers, + getUserOrders: getUserOrders, + updateOrderAddress: updateOrderAddress, + updateOrderStatus: updateOrderStatus, + updateDeliveryStatus: updateDeliveryStatus, + updateOrderTotal: updateOrderTotal, + updateOrderRemarks: updateOrderRemarks, + cancelOrder: cancelOrder, + increasePushToken: increasePushToken +} diff --git a/cloudfunctions/main/config.json b/cloudfunctions/main/config.json new file mode 100644 index 0000000..407d539 --- /dev/null +++ b/cloudfunctions/main/config.json @@ -0,0 +1,21 @@ +{ + "permissions": { + "openapi": [ + "wxacode.get", + "templateMessage.send", + "logistics.getAllDelivery" + ] + }, + "triggers": [ + { + "name": "wechat_triggers.update_access_token", + "type": "timer", + "config": "0 */5 * * * * *" + }, + { + "name": "wechat_triggers.send_notification", + "type": "timer", + "config": "0 */2 * * * * *" + } + ] +} \ No newline at end of file diff --git a/cloudfunctions/main/constant.js b/cloudfunctions/main/constant.js new file mode 100644 index 0000000..0281e47 --- /dev/null +++ b/cloudfunctions/main/constant.js @@ -0,0 +1,24 @@ +const PayStatus = { + 'submit': 'submit', + 'pay': 'pay', + 'received': 'received', + 'refund': 'refund', + 'complete': 'complete' +} +const PayType = { + 'pay': 'pay', + 'deposit': 'deposit' +} + +const DeliveryStatus = { + 'preparing': 'preparing', + 'shipping': 'shipping', + 'delivering': 'delivering', + 'received': 'received' +} + +module.exports = { + PayType: PayType, + PayStatus: PayStatus, + DeliveryStatus: DeliveryStatus +} \ No newline at end of file diff --git a/cloudfunctions/main/db.js b/cloudfunctions/main/db.js new file mode 100644 index 0000000..add5010 --- /dev/null +++ b/cloudfunctions/main/db.js @@ -0,0 +1,12 @@ +const settings = require('./settings') + +const cloud = require('wx-server-sdk') +cloud.init({ + env: settings.cloudenv +}) +const db = cloud.database() + + + +module.exports = db + diff --git a/cloudfunctions/main/deposit.js b/cloudfunctions/main/deposit.js new file mode 100644 index 0000000..577d65b --- /dev/null +++ b/cloudfunctions/main/deposit.js @@ -0,0 +1,248 @@ + +const cloud = require('wx-server-sdk') +const db = require('./db') +const cryptoMO = require('crypto'); +const request = require('request'); +const xml2js = require('xml2js'); +const uuid = require('./uuid.js') +const constant = require('./constant') +const shortid = require('./utils/shortid') +const settings = require('./settings') +const wechat = settings.wechat + +function non_str_random() { + return new uuid.UUID(); +} + +function create_deposit_orderid(length) { + let s = shortid(length) + return `D${s}` +} + +function bodyData(wechat, payBody, nonce_str, openid, out_trade_no, total_fee, sign) { + return ` + ${wechat.appid} + ${payBody} + ${wechat.mch_id} + ${nonce_str} + ${openid} + ${wechat.notify_url} + ${out_trade_no} + ${wechat.ip} + ${total_fee} + JSAPI + ${sign.toUpperCase()} + ` +} + + +const wxPaymentSubmit = async (data) => { + let result = await new Promise((resolve, reject) => { + request({ url: wechat.url, method: 'POST', body: data.body }, (err, res, body) => { + const xmlParser = new xml2js.Parser({ explicitArray: false, ignoreAttrs: true }) + console.log(err) + console.log(res) + xmlParser.parseString(body, (err, res) => { + var prepay_id = res.xml.prepay_id; + var str = `appId=${data.appid}&nonceStr=${data.non_str}&package=prepay_id=${prepay_id}&signType=MD5&timeStamp=${data.timestamp}&key=${data.key}`; + var paySign = cryptoMO.createHash('md5').update(str).digest('hex'); + resolve({ status: true, data: { timeStamp: data.timestamp, nonceStr: data.non_str, package: `prepay_id=${prepay_id}`, paySign: paySign, outTradeNo: data.out_trade_no, signType: 'MD5' } }); + }) + }) + }) + return result +} + + +const deposit = async (event, wxContext, user) => { + console.log('event:', event) + console.log('user', user) + + let cardResult = null + try { + cardResult = await db.collection('deposit_card').doc(event.cardId).get() + console.log('cardResult:', cardResult) + } catch (e) { + console.error(e) + } + if (!cardResult || cardResult.errMsg !== 'document.get:ok') { + return { + status: false, + message: 'card_not_found' + } + } + console.log('card:', cardResult.data) + console.log('cardId:', cardResult.data._id) + let balance = 0; + if (user.balance !== undefined || user.balance !== null) { + balance = user.balance + } + + const out_trade_no = create_deposit_orderid(5) + const non_str = non_str_random().id; + console.log('non_str:', non_str) + console.log(non_str.length) + var payBody = `Deposit-${cardResult.data.real_value}-${event.cardId}`; + var total_fee = parseInt(parseFloat(cardResult.data.value) * 100) + // var total_fee = 1 + var str = `appid=${wechat.appid}&body=${payBody}&mch_id=${wechat.mch_id}&nonce_str=${non_str}¬ify_url=${wechat.notify_url}&openid=${wxContext.OPENID}&out_trade_no=${out_trade_no}&spbill_create_ip=${wechat.ip}&total_fee=${total_fee}&trade_type=JSAPI&key=${wechat.key}`; + console.log({ 'str': str }) + var sign = cryptoMO.createHash('md5').update(str).digest('hex'); + console.log('sign:', sign) + var temp_body_data = bodyData(wechat, payBody, non_str, wxContext.OPENID, out_trade_no, total_fee, sign); + console.log({ xml: temp_body_data }) + + var payData = { + body: temp_body_data, + appid: wechat.appid, + non_str: non_str, + out_trade_no: out_trade_no, + key: wechat.key, + timestamp: new Date().getTime().toString() + } + + let depositSubmitResult = await wxPaymentSubmit(payData) + + if (!depositSubmitResult.status) { + return { + status: false, + message: 'paysubmit_error' + } + } + + let order = { + orderNo: out_trade_no, + userName: user.nickName, + mobile_phone: user.mobile_phone, + is_admin_notified: false, + orderInfo: { + total: cardResult.data.real_value, + count: 1, + entities: [ + { + id: cardResult.data._id, + name: cardResult.data.name, + name_en: cardResult.data.name_en, + price: cardResult.data.real_value, + display_price: cardResult.data.value, + count: 1, + total: cardResult.data.real_value, + display_total: cardResult.data.value, + cover: cardResult.data.image + } + ] + }, + create_at: new Date(), + update_at: new Date(), + is_enable: true, + openid: user._id, + unionid: user.unionid, + status: constant.PayStatus.submit, + amount: cardResult.data.real_value, + type: constant.PayType.deposit + // balance: balance + parseFloat(cardResult.data.real_value) + } + console.log('orderInfo:', order) + + + + let orderResult = null + try { + orderResult = await db.collection('order').add({ + data: order + }) + console.log('orderResult:', orderResult) + } catch (e) { + console.error(e) + } + if (!orderResult) { + return { + status: false, + message: 'create_deposit_order_error' + } + } + + + return { + status: true, + message: 'ok', + data: { + orderNo: out_trade_no, + payData: depositSubmitResult.data + } + } +} + + +async function depositSuccess(event, wxContext, user) { + + let orderResult = null + try { + orderResult = await db.collection('order').where({ orderNo: event.orderNo }).limit(1).get() + console.log('orderResult:', orderResult) + } catch (e) { + console.error(e) + } + if (!orderResult || !orderResult.data || orderResult.data.length !== 1) { + return { + status: false, + message: 'get_deposit_order_error' + } + } + orderResult = orderResult.data[0] + if (orderResult.status !== constant.PayStatus.submit) { + return { + status: false, + message: 'deposit_order_status_error' + } + } + + let updateOrderStatusRes = null + try { + updateOrderStatusRes = await db.collection('order').doc(orderResult._id).update({ + data: { + balance: db.command.inc(parseFloat(orderResult.orderInfo.total)), + status: constant.PayStatus.complete + } + }) + console.log('updateOrderStatusRes:', updateOrderStatusRes) + } catch (e) { + console.error(e) + } + if (!updateOrderStatusRes || updateOrderStatusRes.errMsg !== 'document.update:ok') { + return { + status: false, + message: 'update_order_status_error' + } + } + + let depositResult = null + try { + depositResult = await db.collection('user').doc(wxContext.OPENID).update({ + data: { + balance: db.command.inc(parseFloat(orderResult.orderInfo.total)), + update_at: new Date() + } + }) + console.log('depositResult:', depositResult) + } catch (e) { + console.error(e) + } + if (!depositResult || depositResult.errMsg !== 'document.update:ok') { + return { + status: false, + message: 'update_balance_error' + } + } + return { + status: true, + message: 'ok' + } +} + + + +module.exports = { + deposit: deposit, + depositSuccess: depositSuccess +} diff --git a/cloudfunctions/main/goods.js b/cloudfunctions/main/goods.js new file mode 100644 index 0000000..ef161f5 --- /dev/null +++ b/cloudfunctions/main/goods.js @@ -0,0 +1,25 @@ +const db = require('./db') + +const getGoods = async (event, wxContext) => { + try { + const result = await db.collection('goods').where({ is_enable: true }).get() + return { + status: true, + data: { + entities: result.data + } + } + } catch (e) { + console.error(e) + return { + status: false, + message: e.message + } + } + +} + + +module.exports = { + getGoods: getGoods +} diff --git a/cloudfunctions/main/index.js b/cloudfunctions/main/index.js new file mode 100644 index 0000000..49df35d --- /dev/null +++ b/cloudfunctions/main/index.js @@ -0,0 +1,365 @@ +const db = require('./db') +const userAPI = require('./user') +const orderAPI = require('./orders') +const loginAPI = require('./login') +const registAPI = require('./regist') +const goodsAPI = require('./goods') +const depositAPI = require('./deposit') +const payAPI = require('./pay') +const adminAPI = require('./admin_funcs') +const wechat_triggers = require('./wechat_triggers') +const constant = require('./constant') +const cloud = require('wx-server-sdk') + + +const getCards = async () => { + let cards = [] + try { + const result = await db.collection('deposit_card').where({ is_enable: true }).get() + cards = result.data + } catch (e) { + console.error(e) + return { + status: false, + message: e.message + } + } + + try { + const result = await db.collection('slide').where({ is_enable: true }).get() + return { + status: true, + data: { + entities: cards, + images: result.data + } + } + } catch (e) { + console.error(e) + return { + status: false, + message: e.message + } + } +} + + + + + +const getUser = async (openid) => { + try { + return await db.collection('user').doc(openid).get() + } catch (e) { + // console.error(e) + return null + } +} + + +const getAdmin = async (openid) => { + let result = null + try { + result = await db.collection('admin').where({ user_id: openid, is_enable: true }).get() + } catch (e) { + // console.error(e) + return null + } + console.log(result) + if (result && result.errMsg == 'collection.get:ok' && result.data) { + return result.data[0] + } + return null +} + + +const getProfile = async (event, wxContext, user) => { + + + let data = { + status: true, + data: { + user: { + id: user._id, + avatar: user.avatar, + balance: user.balance, + nickName: user.nickName, + realName: user.realName, + status: user.status, + gender: user.gender, + birthday: user.birthday, + address: user.address, + update_at: user.update_at, + create_at: user.create_at + } + } + } + + let result = await db.collection('admin').where({ user_id: user._id }).limit(1).get() + console.log(result) + if (result && result.errMsg == 'collection.get:ok' && result.data && result.data.length === 1) { + if (result.data[0].is_enable) { + data.data.admin = { + id: result.data[0]._id, + name: result.data[0].name + } + } + } + + return data +} + + + + +// 云函数入口函数 +exports.main = async (event, context) => { + console.log('event:', event) + console.log(context) + const wxContext = cloud.getWXContext() + if (event.Type == 'Timer' && event.TriggerName.startsWith('wechat_triggers.update_access_token')) { + let triggerResult = await wechat_triggers.update_access_token(event, wxContext) + console.log(triggerResult) + return + } else if (event.Type == 'Timer' && event.TriggerName.startsWith('wechat_triggers.send_notification')) { + let notificationResult = await wechat_triggers.send_notification(event, wxContext) + console.log(notificationResult) + return + } + + + let user = await getUser(wxContext.OPENID) + switch (event.apiName) { + case 'getCards': + return await getCards() + case 'depositAPI.deposit': + if (!user || user.errMsg !== 'document.get:ok') { + return { + status: false, + message: 'user_not_found' + } + } + return await depositAPI.deposit(event, wxContext, user.data) + case 'depositAPI.depositSuccess': + if (!user || user.errMsg !== 'document.get:ok') { + return { + status: false, + message: 'user_not_found' + } + } + return await depositAPI.depositSuccess(event, wxContext, user.data) + case 'payAPI.orderPay': + if (!user || user.errMsg !== 'document.get:ok') { + return { + status: false, + message: 'user_not_found' + } + } + return await payAPI.orderPay(event, wxContext, user.data) + case 'getProfile': + if (!user || user.errMsg !== 'document.get:ok') { + return { + status: false, + message: 'user_not_found' + } + } + return await getProfile(event, wxContext, user.data) + case 'userAPI.updateBirthday': + if (!user || user.errMsg !== 'document.get:ok') { + return { + status: false, + message: 'user_not_found' + } + } + return await userAPI.updateBirthday(event, wxContext, user.data) + case 'userAPI.updateUserName': + if (!user || user.errMsg !== 'document.get:ok') { + return { + status: false, + message: 'user_not_found' + } + } + return await userAPI.updateUserName(event, wxContext, user.data) + case 'userAPI.updateGender': + if (!user || user.errMsg !== 'document.get:ok') { + return { + status: false, + message: 'user_not_found' + } + } + return await userAPI.updateGender(event, wxContext, user.data) + case 'userAPI.updateAddress': + if (!user || user.errMsg !== 'document.get:ok') { + return { + status: false, + message: 'user_not_found' + } + } + return await userAPI.updateAddress(event, wxContext, user.data) + case 'orderAPI.getOrders': + if (!user || user.errMsg !== 'document.get:ok') { + return { + status: false, + message: 'user_not_found' + } + } + return await orderAPI.getOrders(event, wxContext, user.data) + + // admin API start + case 'adminAPI.getUsers': + if (!user || user.errMsg !== 'document.get:ok') { + return { + status: false, + message: 'user_not_found' + } + } + + var admin = await getAdmin(wxContext.OPENID) + if (!admin || !admin._id) { + return { + status: false, + message: 'admin_required' + } + } + + return await adminAPI.getUsers(event, wxContext, user.data) + case 'adminAPI.getUserOrders': + if (!user || user.errMsg !== 'document.get:ok') { + return { + status: false, + message: 'user_not_found' + } + } + + var admin = await getAdmin(wxContext.OPENID) + if (!admin || !admin._id) { + return { + status: false, + message: 'admin_required' + } + } + return await adminAPI.getUserOrders(event, wxContext, user.data) + case 'adminAPI.updateOrderAddress': + if (!user || user.errMsg !== 'document.get:ok') { + return { + status: false, + message: 'user_not_found' + } + } + var admin = await getAdmin(wxContext.OPENID) + if (!admin || !admin._id) { + return { + status: false, + message: 'admin_required' + } + } + return await adminAPI.updateOrderAddress(event, wxContext, user.data) + case 'adminAPI.updateOrderStatus': + if (!user || user.errMsg !== 'document.get:ok') { + return { + status: false, + message: 'user_not_found' + } + } + var admin = await getAdmin(wxContext.OPENID) + if (!admin || !admin._id) { + return { + status: false, + message: 'admin_required' + } + } + return await adminAPI.updateOrderStatus(event, wxContext, user.data) + case 'adminAPI.updateDeliveryStatus': + if (!user || user.errMsg !== 'document.get:ok') { + return { + status: false, + message: 'user_not_found' + } + } + var admin = await getAdmin(wxContext.OPENID) + if (!admin || !admin._id) { + return { + status: false, + message: 'admin_required' + } + } + return await adminAPI.updateDeliveryStatus(event, wxContext, user.data) + case 'adminAPI.updateOrderTotal': + if (!user || user.errMsg !== 'document.get:ok') { + return { + status: false, + message: 'user_not_found' + } + } + var admin = await getAdmin(wxContext.OPENID) + if (!admin || !admin._id) { + return { + status: false, + message: 'admin_required' + } + } + return await adminAPI.updateOrderTotal(event, wxContext, user.data) + case 'adminAPI.updateOrderRemarks': + if (!user || user.errMsg !== 'document.get:ok') { + return { + status: false, + message: 'user_not_found' + } + } + var admin = await getAdmin(wxContext.OPENID) + if (!admin || !admin._id) { + return { + status: false, + message: 'admin_required' + } + } + return await adminAPI.updateOrderRemarks(event, wxContext, user.data) + case 'adminAPI.cancelOrder': + if (!user || user.errMsg !== 'document.get:ok') { + return { + status: false, + message: 'user_not_found' + } + } + var admin = await getAdmin(wxContext.OPENID) + if (!admin || !admin._id) { + return { + status: false, + message: 'admin_required' + } + } + return await adminAPI.cancelOrder(event, wxContext, user.data) + + case 'adminAPI.increasePushToken': + if (!user || user.errMsg !== 'document.get:ok') { + return { + status: false, + message: 'user_not_found' + } + } + var admin = await getAdmin(wxContext.OPENID) + if (!admin || !admin._id) { + return { + status: false, + message: 'admin_required' + } + } + return await adminAPI.increasePushToken(event, wxContext, user.data) + + // admin api end + + case 'loginAPI.login': + return await loginAPI.login(event, wxContext) + case 'registAPI.regist': + return await registAPI.regist(event, wxContext) + case 'registAPI.registByCloudID': + return await registAPI.registByCloudID(event, wxContext) + case 'goodsAPI.getGoods': + return await goodsAPI.getGoods(event, wxContext) + default: + return { + status: false, + message: 'api_not_found' + } + } +} \ No newline at end of file diff --git a/cloudfunctions/main/login.js b/cloudfunctions/main/login.js new file mode 100644 index 0000000..ad96f75 --- /dev/null +++ b/cloudfunctions/main/login.js @@ -0,0 +1,101 @@ +const cloud = require('wx-server-sdk') +const db = require('./db') + + +const getUser = async (openid) => { + try { + return await db.collection('user').doc(openid).get() + } catch (e) { + // console.error(e) + return null + } +} + + + +const createUser = async (openid, unionid, nickName, gender, avatar, balance = 0, inviteBy = null, inviteFrom = null, userinfo = {}) => { + try { + return await db.collection('user').add({ + data: { + _id: openid, + unionid: unionid, + gender: gender, + nickName: nickName, + avatar: avatar, + raw: userinfo, + mobile_phone: "", + balance: balance, + inviteBy: inviteBy, + inviteFrom: inviteFrom, + status: 'regist', + is_enable: true + } + }) + } catch (e) { + // console.error(e) + return null + } +} + +const login = async (event, wxContext) => { + const result = await getUser(wxContext.OPENID) + console.log('getUser:') + console.log(result) + if (!result) { + const userInfo = event.userinfo + const createResult = await createUser( + wxContext.OPENID, + wxContext.UNIONID, + userInfo.nickName, + userInfo.gender, + userInfo.avatarUrl, + 0, + event.inviteBy || null, + event.inviteFrom || null, + userInfo + ) + if (!createResult) { + return { + status: false, + message: 'fail_create_user' + } + } else { + return { + status: true, + message: 'ok', + data: { + registed: false, + nextpage: '/pages/regist/regist', + openid: wxContext.OPENID + } + } + } + } else { + if (result.data.mobile_phone) { + return { + status: true, + message: 'ok', + data: { + registed: true, + nextpage: '/pages/home/home', + openid: wxContext.OPENID + } + } + } else { + return { + status: true, + message: 'ok', + data: { + registed: false, + nextpage: '/pages/regist/regist', + openid: wxContext.OPENID + } + } + } + } +} + + +module.exports = { + login: login +} diff --git a/cloudfunctions/main/orders.js b/cloudfunctions/main/orders.js new file mode 100644 index 0000000..59b0d56 --- /dev/null +++ b/cloudfunctions/main/orders.js @@ -0,0 +1,30 @@ +const cloud = require('wx-server-sdk') +const db = require('./db') + +const getOrders = async (event, wxContext, user) => { + console.log(user) + let result = null + try { + result = await db.collection('order').orderBy('create_at', 'desc').where({ openid: user._id, is_enable: true }).get() + console.log('result:', result) + } catch (e) { + console.error(e) + } + if (!result) { + return { + status: false, + message: 'get_orders_error' + } + } + return { + status: true, + message: 'ok', + data: { + entities: result.data + } + } +} + +module.exports = { + getOrders: getOrders +} diff --git a/cloudfunctions/main/package-lock.json b/cloudfunctions/main/package-lock.json new file mode 100644 index 0000000..c2fd216 --- /dev/null +++ b/cloudfunctions/main/package-lock.json @@ -0,0 +1,603 @@ +{ + "name": "deposit", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@cloudbase/database": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@cloudbase/database/-/database-0.1.1.tgz", + "integrity": "sha512-r6tSlzrDKvu27K9tlQYG6qFphw3ZmGECuch7J2ZKW93iLlqpaBVQdy5kBNKZkpjxrpVw9cZKoC2+k0wMqaTWtQ==", + "requires": { + "bson": "^4.0.2" + } + }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + }, + "@types/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.0.tgz", + "integrity": "sha512-1w52Nyx4Gq47uuu0EVcsHBxZFJgurQ+rTKS3qMHxR1GY2T8c2AJYd6vZoZ9q1rupaDjU0yT+Jc2XTyXkjeMA+Q==" + }, + "@types/node": { + "version": "10.14.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.13.tgz", + "integrity": "sha512-yN/FNNW1UYsRR1wwAoyOwqvDuLDtVXnaJTZ898XIw/Q5cCaeVAlVwvsmXLX5PuiScBYwZsZU4JYSHB3TvfdwvQ==" + }, + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "axios": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz", + "integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==", + "requires": { + "follow-redirects": "1.5.10", + "is-buffer": "^2.0.2" + } + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bson": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.0.2.tgz", + "integrity": "sha512-rBdCxMBCg2aR420e1oKUejjcuPZLTibA7zEhWAlliFWEwzuBCC9Dkp5r7VFFIQB2t1WVsvTbohry575mc7Xw5A==", + "requires": { + "buffer": "^5.1.0", + "long": "^4.0.0" + } + }, + "buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crypto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz", + "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "requires": { + "debug": "=3.1.0" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "is-buffer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "requires": { + "has": "^1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "requires": { + "mime-db": "1.40.0" + } + }, + "moment": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "protobufjs": { + "version": "6.8.8", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.8.tgz", + "integrity": "sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw==", + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.0", + "@types/node": "^10.1.0", + "long": "^4.0.0" + } + }, + "psl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.2.0.tgz", + "integrity": "sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "tcb-admin-node": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/tcb-admin-node/-/tcb-admin-node-1.9.0.tgz", + "integrity": "sha512-TYoBo66CEIIw1QzgK4Jq43G45zvBE6ZB35LbDV8wwLQvg6CiZHlmOTVZkgj2YZ8O87ELi+ZE3UBVNZM3nFa6lQ==", + "requires": { + "@cloudbase/database": "0.1.1", + "is-regex": "^1.0.4", + "lodash.merge": "^4.6.1", + "request": "^2.87.0", + "xml2js": "^0.4.19" + } + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "wx-server-sdk": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/wx-server-sdk/-/wx-server-sdk-0.8.1.tgz", + "integrity": "sha512-mE7O3E7GtRhqk1ukWw2+NiykaO5DaJYiMFCeHrwvekYTVL5Z2nFXnSrUx6nPg/vZ7LWWQbCgQlGOygBjj2+hkQ==", + "requires": { + "protobufjs": "6.8.8", + "tcb-admin-node": "1.9.0", + "tslib": "^1.9.3" + } + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + }, + "xmlreader": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/xmlreader/-/xmlreader-0.2.3.tgz", + "integrity": "sha1-hldutdV5Wabe5+0os8vRw1Wdy5A=", + "requires": { + "sax": "~0.5.2" + }, + "dependencies": { + "sax": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz", + "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=" + } + } + } + } +} diff --git a/cloudfunctions/main/package.json b/cloudfunctions/main/package.json new file mode 100644 index 0000000..f7d1cd3 --- /dev/null +++ b/cloudfunctions/main/package.json @@ -0,0 +1,20 @@ +{ + "name": "deposit", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "axios": "^0.19.0", + "crypto": "^1.0.1", + "moment": "^2.24.0", + "request": "^2.88.0", + "wx-server-sdk": "^0.8.1", + "xml2js": "^0.4.19", + "xmlreader": "^0.2.3" + } +} diff --git a/cloudfunctions/main/pay.js b/cloudfunctions/main/pay.js new file mode 100644 index 0000000..7a59bd4 --- /dev/null +++ b/cloudfunctions/main/pay.js @@ -0,0 +1,193 @@ + +const cloud = require('wx-server-sdk') +const db = require('./db') +const constant = require('./constant') +const shortid = require('./utils/shortid') + + +function checkOrder(orderInfo) { + // todo: add order verifiy function + return true +} + + +function create_pay_orderid(length) { + let s = shortid(length) + return `P${s}` +} + + +const orderPay = async (event, wxContext, user) => { + let orderInfo = event.orderInfo + + // 校验订单数据 + let checkResult = checkOrder(orderInfo) + if (!checkResult) { + return { + status: false, + message: 'order_info_error' + } + } + + // 校验用户余额 + console.log('user.balance:', user.balance) + console.log('orderInfo.total:', orderInfo.total) + let balance; + if (user.balance !== undefined && user.balance !== null) { + balance = user.balance + } + if (balance < parseFloat(orderInfo.total)) { + return { + status: false, + message: 'user_balance_error' + } + } + let orderNo = event.orderNo + let balanceAfter = balance - parseFloat(orderInfo.total); + if (!orderNo) { + let orderNo = create_pay_orderid(5) + let order = { + orderNo: orderNo, + orderInfo: orderInfo, + create_at: new Date(), + update_at: new Date(), + is_enable: true, + openid: user._id, + userName: user.nickName, + mobile_phone: user.mobile_phone, + unionid: user.unionid, + status: constant.PayStatus.submit, + amount: orderInfo.total, + type: constant.PayType.pay, + balance: balance - parseFloat(orderInfo.total), + is_admin_notified: false + + } + + let orderResult = null + try { + orderResult = await db.collection('order').add({ + data: order + }) + console.log('orderResult:', orderResult) + } catch (e) { + console.error(e) + } + if (!orderResult) { + return { + status: false, + message: 'create_order_error' + } + } + + let buyResult = null + console.log('user:', user._id) + try { + buyResult = await db.collection('user').doc(user._id).update({ + data: { + balance: db.command.inc(-parseFloat(orderInfo.total)) + } + }) + console.log('buyResult:', buyResult) + } catch (e) { + console.error(e) + } + if (!buyResult) { + return { + status: false, + message: 'update_balance_error' + } + } + + let payResult = null + try { + payResult = await db.collection('order').doc(orderResult._id).update({ + data: { + status: constant.PayStatus.pay, + update: new Date() + } + }) + console.log('payResult:', payResult) + } catch (e) { + console.error(e) + } + if (!payResult) { + return { + status: false, + message: 'pay_order_error' + } + } + } else { + let orderResult = null + try { + orderResult = await db.collection('order').get({orderNo: orderNo}).limit(1).get() + console.log('orderResult:', orderResult) + } catch (e) { + console.error(e) + } + if (!orderResult) { + return { + status: false, + message: 'orderno_not_found' + } + } + + if (orderResult.status !== constant.PayStatus.submit) { + return { + status: false, + message: 'submit_order_status_error' + } + } + + let buyResult = null + try { + buyResult = await db.collection('user').doc(user.openid).update({ + data: { + balance: db.command.inc(-parseInt(orderInfo.total)), + update_at: new Date() + } + }) + console.log('buyResult:', buyResult) + } catch (e) { + console.error(e) + } + if (!buyResult) { + return { + status: false, + message: 'update_balance_error' + } + } + + let payResult = null + try { + payResult = await db.collection('order').doc(orderResult._id).update({ + data: { + status: constant.PayStatus.pay, + update: new Date() + } + }) + console.log('payResult:', payResult) + } catch (e) { + console.error(e) + } + if (!payResult) { + return { + status: false, + message: 'pay_order_error' + } + } + } + return { + status: true, + message: 'ok', + data: { + orderNo: orderNo, + } + } +} + + + +module.exports = { + orderPay: orderPay +} diff --git a/cloudfunctions/main/regist.js b/cloudfunctions/main/regist.js new file mode 100644 index 0000000..3239192 --- /dev/null +++ b/cloudfunctions/main/regist.js @@ -0,0 +1,133 @@ +const cloud = require('wx-server-sdk') +const db = require('./db') +const WXBizDataCrypt = require('./utils/WXBizDataCrypt') +const settings = require('./settings') + +const getUser = async (openid) => { + try { + return await db.collection('user').doc(openid).get() + } catch (e) { + // console.error(e) + return null + } +} + + +const updateUserMobilePhone = async (openid, mobile_phone) => { + try { + return await db.collection('user').doc(openid).update({ + data: { + mobile_phone: mobile_phone, + update_at: new Date() + } + }) + } catch (e) { + // console.error(e) + return null + } +} + +// 云函数入口函数 +const regist = async (event, wxContext) => { + console.log('regist:') + console.log(event) + console.log(wxContext) + + // var pc = new WXBizDataCrypt(appId, sessionKey) + + // var data = pc.decryptData(encryptedData, iv) + + + const openid = wxContext.OPENID + // const mobile_phone = event.mobile_phone.data.phoneNumber + var pc = new WXBizDataCrypt(settings.app_id, event.sessionKey) + let encryptData = JSON.parse(event.encryptData) + console.log('encryptData:', encryptData) + + var data = null + try { + var data = pc.decryptData(encryptData.encryptedData, encryptData.iv) + } catch(e) { + console.error(e) + } + if(!data) { + return { + status :false, + message: 'fail_parse_encryptdata' + } + } + console.log('data:', data) + // var data = pc.decryptData(encryptedData, iv) + const result = await getUser(openid) + if (!result) { + return { + status: false, + message: 'user_not_found' + } + } + + const updateResult = await updateUserMobilePhone(openid, data.mobile_phone) + if (!updateResult) { + return { + status: false, + message: 'fail_update_user' + } + } + + return { + status: true, + message: 'ok', + data: { + nextpage: '/pages/home/home', + openid: wxContext.OPENID + } + } +} + + + +const registByCloudID = async (event, wxContext) => { + console.log('registByCloudID:') + console.log(event) + console.log(wxContext) + + + const openid = wxContext.OPENID + var mobile_phone = null + if (event.weRunData && event.weRunData.data && event.weRunData.data.purePhoneNumber) { + mobile_phone = event.weRunData.data.purePhoneNumber + } else { + return { + status: false, + message: 'fail_to_get_mobile_phone', + data: event + } + } + + const updateResult = await updateUserMobilePhone(openid, mobile_phone) + if (!updateResult) { + return { + status: false, + message: 'fail_update_user', + data: event + } + } + + return { + status: true, + message: 'ok', + data: { + nextpage: '/pages/home/home', + openid: wxContext.OPENID, + data: event + } + } +} + + + + +module.exports = { + regist: regist, + registByCloudID: registByCloudID +} diff --git a/cloudfunctions/main/settings.example.js b/cloudfunctions/main/settings.example.js new file mode 100644 index 0000000..58c52d2 --- /dev/null +++ b/cloudfunctions/main/settings.example.js @@ -0,0 +1,19 @@ +const settings = { + cloudenv: '', + app_id: '', + app_secret: '', + wechat_access_token_record_id: '', + depositMsgId: '', + payMsgId: '', + wechat: { + appid: "", + mch_id: "", + ip: "", + notify_url: "", + key: "", + url: "" + } +} + + +module.exports = settings \ No newline at end of file diff --git a/cloudfunctions/main/user.js b/cloudfunctions/main/user.js new file mode 100644 index 0000000..792333f --- /dev/null +++ b/cloudfunctions/main/user.js @@ -0,0 +1,109 @@ +const cloud = require('wx-server-sdk') +const db = require('./db') + +const updateBirthday = async (event, wxContext, user) => { + let result = null + try { + result = await db.collection('user').doc(user._id).update({ + data: { + birthday: event.birthday + } + }) + console.log('result:', result) + } catch (e) { + console.error(e) + } + if (!result) { + return { + status: false, + message: 'update_birthday_error' + } + } + return { + status: true, + message: 'ok' + } +} + +const updateGender = async (event, wxContext, user) => { + let result = null + try { + result = await db.collection('user').doc(user._id).update({ + data: { + gender: event.gender + } + }) + console.log('result:', result) + } catch (e) { + console.error(e) + } + if (!result) { + return { + status: false, + message: 'update_gender_error' + } + } + return { + status: true, + message: 'ok' + } +} + +const updateUserName = async (event, wxContext, user) => { + let result = null + try { + result = await db.collection('user').doc(user._id).update({ + data: { + realName: event.realName, + nickName: event.nickName + } + }) + console.log('result:', result) + } catch (e) { + console.error(e) + } + if (!result) { + return { + status: false, + message: 'update_name_error' + } + } + return { + status: true, + message: 'ok' + } +} + + + + +const updateAddress = async (event, wxContext, user) => { + let result = null + try { + result = await db.collection('user').doc(user._id).update({ + data: { + address: event.address + } + }) + console.log('result:', result) + } catch (e) { + console.error(e) + } + if (!result) { + return { + status: false, + message: 'update_address_error' + } + } + return { + status: true, + message: 'ok' + } +} + +module.exports = { + updateBirthday: updateBirthday, + updateGender: updateGender, + updateUserName: updateUserName, + updateAddress, updateAddress +} diff --git a/cloudfunctions/main/utils/WXBizDataCrypt.js b/cloudfunctions/main/utils/WXBizDataCrypt.js new file mode 100755 index 0000000..b6afef7 --- /dev/null +++ b/cloudfunctions/main/utils/WXBizDataCrypt.js @@ -0,0 +1,39 @@ +var crypto = require('crypto') + +function WXBizDataCrypt(appId, sessionKey) { + this.appId = appId + this.sessionKey = sessionKey +} + +WXBizDataCrypt.prototype.decryptData = function (encryptedData, iv) { + // base64 decode + console.log('firstarg:', encryptedData) + console.log('iv:', iv) + console.log(this.appId) + console.log(this.sessionKey) + var sessionKey = new Buffer(this.sessionKey, 'base64') + encryptedData = new Buffer(encryptedData, 'base64') + iv = new Buffer(iv, 'base64') + + try { + // 解密 + var decipher = crypto.createDecipheriv('aes-128-cbc', sessionKey, iv) + // 设置自动 padding 为 true,删除填充补位 + decipher.setAutoPadding(true) + var decoded = decipher.update(encryptedData, 'binary', 'utf8') + decoded += decipher.final('utf8') + + decoded = JSON.parse(decoded) + + } catch (err) { + throw new Error('Illegal Buffer') + } + + if (decoded.watermark.appid !== this.appId) { + throw new Error('Illegal Buffer') + } + + return decoded +} + +module.exports = WXBizDataCrypt diff --git a/cloudfunctions/main/utils/demo.js b/cloudfunctions/main/utils/demo.js new file mode 100755 index 0000000..43be945 --- /dev/null +++ b/cloudfunctions/main/utils/demo.js @@ -0,0 +1,2 @@ +var WXBizDataCrypt = require('./WXBizDataCrypt') +var appId = '' diff --git a/cloudfunctions/main/utils/shortid.js b/cloudfunctions/main/utils/shortid.js new file mode 100644 index 0000000..fd4a29b --- /dev/null +++ b/cloudfunctions/main/utils/shortid.js @@ -0,0 +1,32 @@ + + +Date.prototype.Format = function (fmt) { //author: meizz + var o = { + "M+": this.getMonth() + 1, //月份 + "d+": this.getDate(), //日 + "h+": this.getHours(), //小时 + "m+": this.getMinutes(), //分 + "s+": this.getSeconds(), //秒 + "q+": Math.floor((this.getMonth() + 3) / 3), //季度 + "S": this.getMilliseconds() //毫秒 + }; + if (/(y+)/.test(fmt)) + fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); + for (var k in o) + if (new RegExp("(" + k + ")").test(fmt)) + fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); + return fmt; +} + +function shortid(length=5) { + let maxNum = Math.pow(10, length) - 1 + let minNum = Math.pow(10, length - 1) + + let s = (new Date()).Format("yyyyMMddhhmmss") + console.log(s) + let salt = parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10); + console.log(salt) + return `${s}${salt}` +} + +module.exports = shortid diff --git a/cloudfunctions/main/utils/tpl_notify.js b/cloudfunctions/main/utils/tpl_notify.js new file mode 100644 index 0000000..3cb2f8a --- /dev/null +++ b/cloudfunctions/main/utils/tpl_notify.js @@ -0,0 +1,48 @@ +const axios = require('axios'); +const db = require('../db'); +const sendTemplateMsg = async (msgid, msgData, openid, formid, page) => { + + let tokenResult = null + try { + tokenResult = await db.collection('wechat_token').doc(settings.wechat_access_token_record_id).get() + if(!tokenResult || tokenResult.errMsg != 'document.get.ok' ) { + return + } + } catch(e) { + return { + status: false, + data: 'fail_to_get_token' + } + } + let result = null + console.log('tokenResult:', tokenResult) + try { + result = await axios.post('https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=' + tokenResult.data.token, + { + touser: openid, + template_id: msgid, + page: page, + form_id: formid, + data: msgData + }) + } catch(e) { + console.error(e) + } + + if(!result || !result.data) { + return { + status: false, + data: result + } + } else { + return { + status: true, + data: result + } + } + +} + +module.exports = { + sendTemplateMsg: sendTemplateMsg +} diff --git a/cloudfunctions/main/uuid.js b/cloudfunctions/main/uuid.js new file mode 100644 index 0000000..497a48e --- /dev/null +++ b/cloudfunctions/main/uuid.js @@ -0,0 +1,81 @@ +function UUID() { + this.id = this.createUUID(); +} + + + +// When asked what this Object is, lie and return it's value +UUID.prototype.valueOf = function () { return this.id; }; +UUID.prototype.toString = function () { return this.id; }; + + + +// +// INSTANCE SPECIFIC METHODS +// +UUID.prototype.createUUID = function () { + // + // Loose interpretation of the specification DCE 1.1: Remote Procedure Call + // since JavaScript doesn't allow access to internal systems, the last 48 bits + // of the node section is made up using a series of random numbers (6 octets long). + // + var dg = new Date(1582, 10, 15, 0, 0, 0, 0); + var dc = new Date(); + var t = dc.getTime() - dg.getTime(); + var tl = UUID.getIntegerBits(t, 0, 31); + var tm = UUID.getIntegerBits(t, 32, 47); + var thv = UUID.getIntegerBits(t, 48, 59) + '1'; // version 1, security version is 2 + var csar = UUID.getIntegerBits(UUID.rand(4095), 0, 7); + var csl = UUID.getIntegerBits(UUID.rand(4095), 0, 7); + + // since detection of anything about the machine/browser is far to buggy, + // include some more random numbers here + // if NIC or an IP can be obtained reliably, that should be put in + // here instead. + var n = UUID.getIntegerBits(UUID.rand(8191), 0, 7) + + UUID.getIntegerBits(UUID.rand(8191), 8, 15) + + UUID.getIntegerBits(UUID.rand(8191), 0, 7) + + UUID.getIntegerBits(UUID.rand(8191), 8, 15) + + UUID.getIntegerBits(UUID.rand(8191), 0, 15); // this last number is two octets long + return tl + tm + thv + csar + csl + n; +}; + + + +//Pull out only certain bits from a very large integer, used to get the time +//code information for the first part of a UUID. Will return zero's if there +//aren't enough bits to shift where it needs to. +UUID.getIntegerBits = function (val, start, end) { + var base16 = UUID.returnBase(val, 16); + var quadArray = new Array(); + var quadString = ''; + var i = 0; + for (i = 0; i < base16.length; i++) { + quadArray.push(base16.substring(i, i + 1)); + } + for (i = Math.floor(start / 4); i <= Math.floor(end / 4); i++) { + if (!quadArray[i] || quadArray[i] == '') quadString += '0'; + else quadString += quadArray[i]; + } + return quadString; +}; + + + +//Replaced from the original function to leverage the built in methods in +//JavaScript. Thanks to Robert Kieffer for pointing this one out +UUID.returnBase = function (number, base) { + return (number).toString(base).toUpperCase(); +}; + + + +//pick a random number within a range of numbers +//int b rand(int a); where 0 <= b <= a +UUID.rand = function (max) { + return Math.floor(Math.random() * (max + 1)); +}; + +module.exports = { + UUID: UUID +} diff --git a/cloudfunctions/main/wechat_triggers.js b/cloudfunctions/main/wechat_triggers.js new file mode 100644 index 0000000..7ca2ae2 --- /dev/null +++ b/cloudfunctions/main/wechat_triggers.js @@ -0,0 +1,223 @@ +const cloud = require('wx-server-sdk') +const db = require('./db') +const axios = require('axios'); +const settings = require('./settings') +const tpl_notify = require('./utils/tpl_notify') +const moment = require('moment') +const APPID = settings.app_id; +const APPSECRET = settings.app_secret; +const COLLNAME = 'wechat_token'; +const FIELDNAME = settings.wechat_access_token_record_id + + +const update_access_token = async (event, context) => { + let res = null + let resUpdate = null + try { + res = await axios.get( + "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + APPID + "&secret=" + APPSECRET + ) + console.log('get_token_result:', res) + if (!res.data || !res.data.access_token) { + console.log('wechat:', res) + return + } + let resUpdate = await db.collection(COLLNAME).doc(FIELDNAME).update({ + data: { + token: res.data.access_token, + update_at: new Date() + } + }) + console.log('resUpdate:', resUpdate) + if (!resUpdate || resUpdate.errMsg !== 'document.update:ok') { + + return + } + } catch (e) { + console.error(e) + } +} + + +function getDepositMsgData(order) { + let msgData = { + "keyword1": { + "value": order.orderNo + }, + "keyword2": { + "value": "充值" + }, + "keyword3": { + "value": order.amount + }, + "keyword4": { + "value": order.orderInfo.displayTotal + }, + "keyword5": { + "value": order.balance + }, + "keyword6": { + "value": moment(order.create_at).format('YYYY/MM/DD HH:mm') + } + }; + if (order.mobile_phone && order.userName) { + msgData["keyword7"] = { + "value": `用户姓名: ${order.userName}, 电话: ${order.mobile_phone}` + } + } + return msgData +} + +function getPayMsgData(order) { + let goodsName = [] + for (let item of order.orderInfo.entities) { + goodsName.push(`${item.name}x${item.count}`) + } + + let address = '' + if (order.addressInfo) { + address = `收货人:${order.addressInfo.userName}, 电话:${order.addressInfo.telNumber}, 地址:${order.addressInfo.provinceName} ${order.addressInfo.cityName} ${order.addressInfo.countyName} ${order.addressInfo.detailInfo}` + } + + + let msgData = { + "keyword1": { + "value": order.orderNo + }, + "keyword2": { + "value": order.amount + }, + "keyword3": { + "value": goodsName.join(',') + }, + "keyword4": { + "value": '余额支付' + }, + "keyword9": { + "value": moment(order.create_at).format('YYYY/MM/DD HH:mm') + }, + }; + + if (address) { + msgData["keywords8"] = { + "value": address + } + } + + if (order.userName) { + msgData["keyword5"] = { + "value": order.userName + } + } + if (order.mobile_phone) { + msgData["keyword6"] = { + "value": order.mobile_phone + } + } + return msgData +} + +const send_notification = async (event, context) => { + let result = null + try { + result = await db.collection('admin').where({ is_enable: true }).get() + console.log('result: ', result) + if (!result || result.errMsg !== 'collection.get:ok') { + console.log(result) + } + } catch (e) { + console.error(e) + } + + let admins = [] + for (let item of result.data) { + admins.push({ + name: item.name, + openid: item.user_id + }) + } + console.log('admins:', admins) + let orderResult = null + try { + orderResult = await db.collection('order').where({ + is_enable: true, is_admin_notified: false + }).get() + console.log('orderResult:', orderResult) + if (!orderResult || orderResult.errMsg !== 'collection.get:ok') { + console.log(orderResult) + } + } catch (e) { + console.error(e) + } + + let orders = [] + for (let item of orderResult.data) { + orders.push(item) + } + console.log('orders:', orders) + let sendResult = null + for (let admin of admins) { + for (let order of orders) { + var msgid; + var msgData = null; + if (order.type == 'despit') { + msgid = settings.depositMsgId + msgData = getDepositMsgData(order) + } else if (order.type == 'pay') { + msgid = settings.payMsgId + msgData = getPayMsgData(order) + } + if (msgid && msgData) { + try { + var tokenResult = await db.collection('admin_push_token').where({ user_id: admin.user_id }).orderBy('create_at', 'asc').limit(1).get(); + console.log('tokenResult:', tokenResult) + if (tokenResult && tokenResult.errCode == 'collection.get.ok' && tokenResult.data.length !== 0) { + sendResult = await sendTemplateMsg(tokenResult[0], msgid, msgData, admin.user_id, tokenResult.data[0].token, `pages/user_orders/user_orders?user_id=${order.openid}`) + console.log('sendResult:', sendResult) + } + + } catch (e) { + console.error(e) + } + + } + + } + } + + console.log('start update orders') + let updateResult = null + let orderIds = [] + for (let item of orders) { + orderIds.push(item._id) + } + console.log('orderIds:', orderIds) + if (orderIds.length !== 0) { + try { + updateResult = await db.collection('order').where({ _id: db.command.in(orderIds) }).update({ + data: { + is_admin_notified: true + } + }) + db.collection('todos').where({ + done: false + }).update({ + data: { + progress: _.inc(10) + }, + }) + console.log('updateResult:', updateResult) + if (!updateResult || updateResult.errMsg !== 'collection.update:ok') { + console.log(updateResult) + } + } catch (e) { + console.error(e) + } + } + +} + +module.exports = { + update_access_token: update_access_token, + send_notification: send_notification +} diff --git a/miniprogram/app.js b/miniprogram/app.js new file mode 100644 index 0000000..ecdbf36 --- /dev/null +++ b/miniprogram/app.js @@ -0,0 +1,62 @@ +import moment from './utils/moment.min.js' +import settings from './settings/index' +moment.locale('zh-cn'); + + +App({ + onLaunch: function (e) { + console.log('onLaunch:', e) + this.globalData.systemInfo = wx.getSystemInfoSync() + if (!wx.cloud) { + console.error('请使用 2.2.3 或以上的基础库以使用云能力') + } else { + wx.cloud.init({ + env: settings.cloudenv, + traceUser: true, + }) + } + + + if(e.query.invite_by) { + wx.setStorageSync('invite_by', invite_by) + } + + if (e.query.invite_from) { + wx.setStorageSync('invite_from', invite_from) + } + + const sessionid = wx.getStorageSync('sessionid') + if (sessionid) { + console.log('sessionid:', sessionid) + this.goToURL(e.query.nextpage || settings.HomePage) + } else { + if(e.query.nextpage) { + wx.setStorageSync('nextpage_registed', e.query.nextpage) + } + } + }, + isTab: function (url) { + let flag = false; + for (let item of settings.TAB_URLS) { + if (url.includes(item)) { + return true + } + } + return flag + }, + goToURL: function (url) { + if (this.isTab(url)) { + wx.switchTab({ + url: url + }) + } else { + wx.redirectTo({ + url: url + }) + } + }, + globalData: { + userInfo: null, + systemInfo: null + } +}) diff --git a/miniprogram/app.json b/miniprogram/app.json new file mode 100644 index 0000000..e866341 --- /dev/null +++ b/miniprogram/app.json @@ -0,0 +1,59 @@ +{ + "pages": [ + "pages/index/index", + "pages/home/home", + "pages/goods/goods", + "pages/me/me", + "pages/regist/regist", + "pages/orders/orders", + "pages/profile/profile", + "pages/buycart/buycart", + "pages/name_form/name_form", + "pages/order_details/order_details", + "pages/users/users", + "pages/user_orders/user_orders", + "pages/update_address/update_address", + "pages/update_delivery/update_delivery", + "pages/update_order/update_order", + "pages/update_remarks/update_remarks", + "pages/update_total/update_total", + "pages/cancel_order/cancel_order", + "pages/all_orders/all_orders", + "pages/admin_message/admin_message" + ], + "window": { + "backgroundColor": "#e67774", + "backgroundTextStyle": "light", + "navigationBarBackgroundColor": "#e67774", + "navigationBarTitleText": "Jing Studio", + "navigationBarTextStyle": "white" + }, + "tabBar": { + "selectedColor": "#333", + "color": "#999", + "backgroundColor": "#fff", + "borderStyle": "black", + "position": "bottom", + "list": [ + { + "pagePath": "pages/home/home", + "text": "首页", + "iconPath": "./assets/images/tabs/home.png", + "selectedIconPath": "./assets/images/tabs/home-selected.png" + }, + { + "pagePath": "pages/goods/goods", + "text": "商城", + "iconPath": "./assets/images/tabs/cake.png", + "selectedIconPath": "./assets/images/tabs/cake-selected.png" + }, + { + "pagePath": "pages/me/me", + "text": "我的", + "iconPath": "./assets/images/tabs/me.png", + "selectedIconPath": "./assets/images/tabs/me-selected.png" + } + ] + }, + "sitemapLocation": "sitemap.json" +} \ No newline at end of file diff --git a/miniprogram/app.wxss b/miniprogram/app.wxss new file mode 100644 index 0000000..3181a88 --- /dev/null +++ b/miniprogram/app.wxss @@ -0,0 +1,158 @@ + + +/* +.container { + display: flex; + flex-direction: column; + align-items: center; + box-sizing: border-box; +} + +button { + background: initial; +} + +button:focus{ + outline: 0; +} + +button::after{ + border: none; +} + + +page { + background: #f6f6f6; + display: flex; + flex-direction: column; + justify-content: flex-start; +} + +.userinfo, .uploader, .tunnel { + margin-top: 40rpx; + height: 140rpx; + width: 100%; + background: #fff; + border: 1px solid rgba(0, 0, 0, 0.1); + border-left: none; + border-right: none; + display: flex; + flex-direction: row; + align-items: center; + transition: all 300ms ease; +} + +.userinfo-avatar { + width: 100rpx; + height: 100rpx; + margin: 20rpx; + border-radius: 50%; + background-size: cover; + background-color: white; +} + +.userinfo-avatar:after { + border: none; +} + +.userinfo-nickname { + font-size: 32rpx; + color: #007aff; + background-color: white; + background-size: cover; +} + +.userinfo-nickname::after { + border: none; +} + +.uploader, .tunnel { + height: auto; + padding: 0 0 0 40rpx; + flex-direction: column; + align-items: flex-start; + box-sizing: border-box; +} + +.uploader-text, .tunnel-text { + width: 100%; + line-height: 52px; + font-size: 34rpx; + color: #007aff; +} + +.uploader-container { + width: 100%; + height: 400rpx; + padding: 20rpx 20rpx 20rpx 0; + display: flex; + align-content: center; + justify-content: center; + box-sizing: border-box; + border-top: 1px solid rgba(0, 0, 0, 0.1); +} + +.uploader-image { + width: 100%; + height: 360rpx; +} + +.tunnel { + padding: 0 0 0 40rpx; +} + +.tunnel-text { + position: relative; + color: #222; + display: flex; + flex-direction: row; + align-content: center; + justify-content: space-between; + box-sizing: border-box; + border-top: 1px solid rgba(0, 0, 0, 0.1); +} + +.tunnel-text:first-child { + border-top: none; +} + +.tunnel-switch { + position: absolute; + right: 20rpx; + top: -2rpx; +} + +.disable { + color: #888; +} + +.service { + position: fixed; + right: 40rpx; + bottom: 40rpx; + width: 140rpx; + height: 140rpx; + border-radius: 50%; + background: linear-gradient(#007aff, #0063ce); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.3); + display: flex; + align-content: center; + justify-content: center; + transition: all 300ms ease; +} + +.service-button { + position: absolute; + top: 40rpx; +} + +.service:active { + box-shadow: none; +} + +.request-text { + padding: 20rpx 0; + font-size: 24rpx; + line-height: 36rpx; + word-break: break-all; +} */ diff --git a/miniprogram/assets/icons/demo.css b/miniprogram/assets/icons/demo.css new file mode 100644 index 0000000..a67054a --- /dev/null +++ b/miniprogram/assets/icons/demo.css @@ -0,0 +1,539 @@ +/* Logo 字体 */ +@font-face { + font-family: "iconfont logo"; + src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834'); + src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'), + url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'), + url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'), + url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg'); +} + +.logo { + font-family: "iconfont logo"; + font-size: 160px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* tabs */ +.nav-tabs { + position: relative; +} + +.nav-tabs .nav-more { + position: absolute; + right: 0; + bottom: 0; + height: 42px; + line-height: 42px; + color: #666; +} + +#tabs { + border-bottom: 1px solid #eee; +} + +#tabs li { + cursor: pointer; + width: 100px; + height: 40px; + line-height: 40px; + text-align: center; + font-size: 16px; + border-bottom: 2px solid transparent; + position: relative; + z-index: 1; + margin-bottom: -1px; + color: #666; +} + + +#tabs .active { + border-bottom-color: #f00; + color: #222; +} + +.tab-container .content { + display: none; +} + +/* 页面布局 */ +.main { + padding: 30px 100px; + width: 960px; + margin: 0 auto; +} + +.main .logo { + color: #333; + text-align: left; + margin-bottom: 30px; + line-height: 1; + height: 110px; + margin-top: -50px; + overflow: hidden; + *zoom: 1; +} + +.main .logo a { + font-size: 160px; + color: #333; +} + +.helps { + margin-top: 40px; +} + +.helps pre { + padding: 20px; + margin: 10px 0; + border: solid 1px #e7e1cd; + background-color: #fffdef; + overflow: auto; +} + +.icon_lists { + width: 100% !important; + overflow: hidden; + *zoom: 1; +} + +.icon_lists li { + width: 100px; + margin-bottom: 10px; + margin-right: 20px; + text-align: center; + list-style: none !important; + cursor: default; +} + +.icon_lists li .code-name { + line-height: 1.2; +} + +.icon_lists .icon { + display: block; + height: 100px; + line-height: 100px; + font-size: 42px; + margin: 10px auto; + color: #333; + -webkit-transition: font-size 0.25s linear, width 0.25s linear; + -moz-transition: font-size 0.25s linear, width 0.25s linear; + transition: font-size 0.25s linear, width 0.25s linear; +} + +.icon_lists .icon:hover { + font-size: 100px; +} + +.icon_lists .svg-icon { + /* 通过设置 font-size 来改变图标大小 */ + width: 1em; + /* 图标和文字相邻时,垂直对齐 */ + vertical-align: -0.15em; + /* 通过设置 color 来改变 SVG 的颜色/fill */ + fill: currentColor; + /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示 + normalize.css 中也包含这行 */ + overflow: hidden; +} + +.icon_lists li .name, +.icon_lists li .code-name { + color: #666; +} + +/* markdown 样式 */ +.markdown { + color: #666; + font-size: 14px; + line-height: 1.8; +} + +.highlight { + line-height: 1.5; +} + +.markdown img { + vertical-align: middle; + max-width: 100%; +} + +.markdown h1 { + color: #404040; + font-weight: 500; + line-height: 40px; + margin-bottom: 24px; +} + +.markdown h2, +.markdown h3, +.markdown h4, +.markdown h5, +.markdown h6 { + color: #404040; + margin: 1.6em 0 0.6em 0; + font-weight: 500; + clear: both; +} + +.markdown h1 { + font-size: 28px; +} + +.markdown h2 { + font-size: 22px; +} + +.markdown h3 { + font-size: 16px; +} + +.markdown h4 { + font-size: 14px; +} + +.markdown h5 { + font-size: 12px; +} + +.markdown h6 { + font-size: 12px; +} + +.markdown hr { + height: 1px; + border: 0; + background: #e9e9e9; + margin: 16px 0; + clear: both; +} + +.markdown p { + margin: 1em 0; +} + +.markdown>p, +.markdown>blockquote, +.markdown>.highlight, +.markdown>ol, +.markdown>ul { + width: 80%; +} + +.markdown ul>li { + list-style: circle; +} + +.markdown>ul li, +.markdown blockquote ul>li { + margin-left: 20px; + padding-left: 4px; +} + +.markdown>ul li p, +.markdown>ol li p { + margin: 0.6em 0; +} + +.markdown ol>li { + list-style: decimal; +} + +.markdown>ol li, +.markdown blockquote ol>li { + margin-left: 20px; + padding-left: 4px; +} + +.markdown code { + margin: 0 3px; + padding: 0 5px; + background: #eee; + border-radius: 3px; +} + +.markdown strong, +.markdown b { + font-weight: 600; +} + +.markdown>table { + border-collapse: collapse; + border-spacing: 0px; + empty-cells: show; + border: 1px solid #e9e9e9; + width: 95%; + margin-bottom: 24px; +} + +.markdown>table th { + white-space: nowrap; + color: #333; + font-weight: 600; +} + +.markdown>table th, +.markdown>table td { + border: 1px solid #e9e9e9; + padding: 8px 16px; + text-align: left; +} + +.markdown>table th { + background: #F7F7F7; +} + +.markdown blockquote { + font-size: 90%; + color: #999; + border-left: 4px solid #e9e9e9; + padding-left: 0.8em; + margin: 1em 0; +} + +.markdown blockquote p { + margin: 0; +} + +.markdown .anchor { + opacity: 0; + transition: opacity 0.3s ease; + margin-left: 8px; +} + +.markdown .waiting { + color: #ccc; +} + +.markdown h1:hover .anchor, +.markdown h2:hover .anchor, +.markdown h3:hover .anchor, +.markdown h4:hover .anchor, +.markdown h5:hover .anchor, +.markdown h6:hover .anchor { + opacity: 1; + display: inline-block; +} + +.markdown>br, +.markdown>p>br { + clear: both; +} + + +.hljs { + display: block; + background: white; + padding: 0.5em; + color: #333333; + overflow-x: auto; +} + +.hljs-comment, +.hljs-meta { + color: #969896; +} + +.hljs-string, +.hljs-variable, +.hljs-template-variable, +.hljs-strong, +.hljs-emphasis, +.hljs-quote { + color: #df5000; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-type { + color: #a71d5d; +} + +.hljs-literal, +.hljs-symbol, +.hljs-bullet, +.hljs-attribute { + color: #0086b3; +} + +.hljs-section, +.hljs-name { + color: #63a35c; +} + +.hljs-tag { + color: #333333; +} + +.hljs-title, +.hljs-attr, +.hljs-selector-id, +.hljs-selector-class, +.hljs-selector-attr, +.hljs-selector-pseudo { + color: #795da3; +} + +.hljs-addition { + color: #55a532; + background-color: #eaffea; +} + +.hljs-deletion { + color: #bd2c00; + background-color: #ffecec; +} + +.hljs-link { + text-decoration: underline; +} + +/* 代码高亮 */ +/* PrismJS 1.15.0 +https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */ +/** + * prism.js default theme for JavaScript, CSS and HTML + * Based on dabblet (http://dabblet.com) + * @author Lea Verou + */ +code[class*="language-"], +pre[class*="language-"] { + color: black; + background: none; + text-shadow: 0 1px white; + font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} + +pre[class*="language-"]::-moz-selection, +pre[class*="language-"] ::-moz-selection, +code[class*="language-"]::-moz-selection, +code[class*="language-"] ::-moz-selection { + text-shadow: none; + background: #b3d4fc; +} + +pre[class*="language-"]::selection, +pre[class*="language-"] ::selection, +code[class*="language-"]::selection, +code[class*="language-"] ::selection { + text-shadow: none; + background: #b3d4fc; +} + +@media print { + + code[class*="language-"], + pre[class*="language-"] { + text-shadow: none; + } +} + +/* Code blocks */ +pre[class*="language-"] { + padding: 1em; + margin: .5em 0; + overflow: auto; +} + +:not(pre)>code[class*="language-"], +pre[class*="language-"] { + background: #f5f2f0; +} + +/* Inline code */ +:not(pre)>code[class*="language-"] { + padding: .1em; + border-radius: .3em; + white-space: normal; +} + +.token.comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: slategray; +} + +.token.punctuation { + color: #999; +} + +.namespace { + opacity: .7; +} + +.token.property, +.token.tag, +.token.boolean, +.token.number, +.token.constant, +.token.symbol, +.token.deleted { + color: #905; +} + +.token.selector, +.token.attr-name, +.token.string, +.token.char, +.token.builtin, +.token.inserted { + color: #690; +} + +.token.operator, +.token.entity, +.token.url, +.language-css .token.string, +.style .token.string { + color: #9a6e3a; + background: hsla(0, 0%, 100%, .5); +} + +.token.atrule, +.token.attr-value, +.token.keyword { + color: #07a; +} + +.token.function, +.token.class-name { + color: #DD4A68; +} + +.token.regex, +.token.important, +.token.variable { + color: #e90; +} + +.token.important, +.token.bold { + font-weight: bold; +} + +.token.italic { + font-style: italic; +} + +.token.entity { + cursor: help; +} diff --git a/miniprogram/assets/icons/demo_index.html b/miniprogram/assets/icons/demo_index.html new file mode 100644 index 0000000..56350fb --- /dev/null +++ b/miniprogram/assets/icons/demo_index.html @@ -0,0 +1,883 @@ + + + + + IconFont Demo + + + + + + + + + + + +
+

+ +
+
+
    + +
  • + +
    购物车满
    +
    &#xe600;
    +
  • + +
  • + +
    购物车空
    +
    &#xe601;
    +
  • + +
  • + +
    账户充值
    +
    &#xe621;
    +
  • + +
  • + +
    我的
    +
    &#xe665;
    +
  • + +
  • + +
    蛋糕
    +
    &#xe67e;
    +
  • + +
  • + +
    首页
    +
    &#xe603;
    +
  • + +
  • + +
    首页1
    +
    &#xe666;
    +
  • + +
  • + +
    分类1
    +
    &#xe667;
    +
  • + +
  • + +
    购物车1
    +
    &#xe669;
    +
  • + +
  • + +
    我的1
    +
    &#xe66b;
    +
  • + +
  • + +
    返回
    +
    &#xe676;
    +
  • + +
  • + +
    返回首页
    +
    &#xe677;
    +
  • + +
  • + +
    更多
    +
    &#xe678;
    +
  • + +
  • + +
    查看更多
    +
    &#xe679;
    +
  • + +
  • + +
    菜单
    +
    &#xe67a;
    +
  • + +
  • + +
    搜索
    +
    &#xe67b;
    +
  • + +
  • + +
    关键字
    +
    &#xe67c;
    +
  • + +
  • + +
    关闭
    +
    &#xe67d;
    +
  • + +
  • + +
    选项
    +
    &#xe67f;
    +
  • + +
  • + +
    点赞
    +
    &#xe680;
    +
  • + +
  • + +
    喜欢
    +
    &#xe682;
    +
  • + +
  • + +
    分享
    +
    &#xe684;
    +
  • + +
  • + +
    扫一扫
    +
    &#xe685;
    +
  • + +
  • + +
    客服
    +
    &#xe686;
    +
  • + +
  • + +
    评论
    +
    &#xe687;
    +
  • + +
  • + +
    删除
    +
    &#xe688;
    +
  • + +
  • + +
    提示
    +
    &#xe689;
    +
  • + +
  • + +
    进行中
    +
    &#xe68a;
    +
  • + +
  • + +
    成功
    +
    &#xe68b;
    +
  • + +
  • + +
    失败
    +
    &#xe68c;
    +
  • + +
  • + +
    活动
    +
    &#xe68d;
    +
  • + +
+
+

Unicode 引用

+
+ +

Unicode 是字体在网页端最原始的应用方式,特点是:

+
    +
  • 兼容性最好,支持 IE6+,及所有现代浏览器。
  • +
  • 支持按字体的方式去动态调整图标大小,颜色等等。
  • +
  • 但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。
  • +
+
+

注意:新版 iconfont 支持多色图标,这些多色图标在 Unicode 模式下将不能使用,如果有需求建议使用symbol 的引用方式

+
+

Unicode 使用步骤如下:

+

第一步:拷贝项目下面生成的 @font-face

+
@font-face {
+  font-family: 'iconfont';
+  src: url('iconfont.eot');
+  src: url('iconfont.eot?#iefix') format('embedded-opentype'),
+      url('iconfont.woff2') format('woff2'),
+      url('iconfont.woff') format('woff'),
+      url('iconfont.ttf') format('truetype'),
+      url('iconfont.svg#iconfont') format('svg');
+}
+
+

第二步:定义使用 iconfont 的样式

+
.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+

第三步:挑选相应图标并获取字体编码,应用于页面

+
+<span class="iconfont">&#x33;</span>
+
+
+

"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。

+
+
+
+
+
    + +
  • + +
    + 购物车满 +
    +
    .icon-gouwucheman +
    +
  • + +
  • + +
    + 购物车空 +
    +
    .icon-gouwuchekong +
    +
  • + +
  • + +
    + 账户充值 +
    +
    .icon-zhanghuchongzhi-copy +
    +
  • + +
  • + +
    + 我的 +
    +
    .icon-wode +
    +
  • + +
  • + +
    + 蛋糕 +
    +
    .icon-dangao +
    +
  • + +
  • + +
    + 首页 +
    +
    .icon-shouye +
    +
  • + +
  • + +
    + 首页1 +
    +
    .icon-shouye1 +
    +
  • + +
  • + +
    + 分类1 +
    +
    .icon-fenlei +
    +
  • + +
  • + +
    + 购物车1 +
    +
    .icon-gouwuche +
    +
  • + +
  • + +
    + 我的1 +
    +
    .icon-wode1 +
    +
  • + +
  • + +
    + 返回 +
    +
    .icon-fanhui +
    +
  • + +
  • + +
    + 返回首页 +
    +
    .icon-fanhuishouye +
    +
  • + +
  • + +
    + 更多 +
    +
    .icon-gengduo +
    +
  • + +
  • + +
    + 查看更多 +
    +
    .icon-chakangengduo +
    +
  • + +
  • + +
    + 菜单 +
    +
    .icon-caidan +
    +
  • + +
  • + +
    + 搜索 +
    +
    .icon-sousuo +
    +
  • + +
  • + +
    + 关键字 +
    +
    .icon-guanjianzi +
    +
  • + +
  • + +
    + 关闭 +
    +
    .icon-guanbi +
    +
  • + +
  • + +
    + 选项 +
    +
    .icon-xuanxiang +
    +
  • + +
  • + +
    + 点赞 +
    +
    .icon-dianzan +
    +
  • + +
  • + +
    + 喜欢 +
    +
    .icon-xihuan +
    +
  • + +
  • + +
    + 分享 +
    +
    .icon-fenxiang +
    +
  • + +
  • + +
    + 扫一扫 +
    +
    .icon-saoyisao +
    +
  • + +
  • + +
    + 客服 +
    +
    .icon-kefu +
    +
  • + +
  • + +
    + 评论 +
    +
    .icon-pinglun +
    +
  • + +
  • + +
    + 删除 +
    +
    .icon-shanchu +
    +
  • + +
  • + +
    + 提示 +
    +
    .icon-tishi +
    +
  • + +
  • + +
    + 进行中 +
    +
    .icon-jinhangzhong +
    +
  • + +
  • + +
    + 成功 +
    +
    .icon-chenggong +
    +
  • + +
  • + +
    + 失败 +
    +
    .icon-shibai +
    +
  • + +
  • + +
    + 活动 +
    +
    .icon-huodong +
    +
  • + +
+
+

font-class 引用

+
+ +

font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。

+

与 Unicode 使用方式相比,具有如下特点:

+
    +
  • 兼容性良好,支持 IE8+,及所有现代浏览器。
  • +
  • 相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。
  • +
  • 因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。
  • +
  • 不过因为本质上还是使用的字体,所以多色图标还是不支持的。
  • +
+

使用步骤如下:

+

第一步:引入项目下面生成的 fontclass 代码:

+
<link rel="stylesheet" href="./iconfont.css">
+
+

第二步:挑选相应图标并获取类名,应用于页面:

+
<span class="iconfont icon-xxx"></span>
+
+
+

" + iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。

+
+
+
+
+
    + +
  • + +
    购物车满
    +
    #icon-gouwucheman
    +
  • + +
  • + +
    购物车空
    +
    #icon-gouwuchekong
    +
  • + +
  • + +
    账户充值
    +
    #icon-zhanghuchongzhi-copy
    +
  • + +
  • + +
    我的
    +
    #icon-wode
    +
  • + +
  • + +
    蛋糕
    +
    #icon-dangao
    +
  • + +
  • + +
    首页
    +
    #icon-shouye
    +
  • + +
  • + +
    首页1
    +
    #icon-shouye1
    +
  • + +
  • + +
    分类1
    +
    #icon-fenlei
    +
  • + +
  • + +
    购物车1
    +
    #icon-gouwuche
    +
  • + +
  • + +
    我的1
    +
    #icon-wode1
    +
  • + +
  • + +
    返回
    +
    #icon-fanhui
    +
  • + +
  • + +
    返回首页
    +
    #icon-fanhuishouye
    +
  • + +
  • + +
    更多
    +
    #icon-gengduo
    +
  • + +
  • + +
    查看更多
    +
    #icon-chakangengduo
    +
  • + +
  • + +
    菜单
    +
    #icon-caidan
    +
  • + +
  • + +
    搜索
    +
    #icon-sousuo
    +
  • + +
  • + +
    关键字
    +
    #icon-guanjianzi
    +
  • + +
  • + +
    关闭
    +
    #icon-guanbi
    +
  • + +
  • + +
    选项
    +
    #icon-xuanxiang
    +
  • + +
  • + +
    点赞
    +
    #icon-dianzan
    +
  • + +
  • + +
    喜欢
    +
    #icon-xihuan
    +
  • + +
  • + +
    分享
    +
    #icon-fenxiang
    +
  • + +
  • + +
    扫一扫
    +
    #icon-saoyisao
    +
  • + +
  • + +
    客服
    +
    #icon-kefu
    +
  • + +
  • + +
    评论
    +
    #icon-pinglun
    +
  • + +
  • + +
    删除
    +
    #icon-shanchu
    +
  • + +
  • + +
    提示
    +
    #icon-tishi
    +
  • + +
  • + +
    进行中
    +
    #icon-jinhangzhong
    +
  • + +
  • + +
    成功
    +
    #icon-chenggong
    +
  • + +
  • + +
    失败
    +
    #icon-shibai
    +
  • + +
  • + +
    活动
    +
    #icon-huodong
    +
  • + +
+
+

Symbol 引用

+
+ +

这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇文章 + 这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:

+
    +
  • 支持多色图标了,不再受单色限制。
  • +
  • 通过一些技巧,支持像字体那样,通过 font-size, color 来调整样式。
  • +
  • 兼容性较差,支持 IE9+,及现代浏览器。
  • +
  • 浏览器渲染 SVG 的性能一般,还不如 png。
  • +
+

使用步骤如下:

+

第一步:引入项目下面生成的 symbol 代码:

+
<script src="./iconfont.js"></script>
+
+

第二步:加入通用 CSS 代码(引入一次就行):

+
<style>
+.icon {
+  width: 1em;
+  height: 1em;
+  vertical-align: -0.15em;
+  fill: currentColor;
+  overflow: hidden;
+}
+</style>
+
+

第三步:挑选相应图标并获取类名,应用于页面:

+
<svg class="icon" aria-hidden="true">
+  <use xlink:href="#icon-xxx"></use>
+</svg>
+
+
+
+ +
+
+ + + diff --git a/miniprogram/assets/icons/iconfont.eot b/miniprogram/assets/icons/iconfont.eot new file mode 100644 index 0000000..07c11ce Binary files /dev/null and b/miniprogram/assets/icons/iconfont.eot differ diff --git a/miniprogram/assets/icons/iconfont.js b/miniprogram/assets/icons/iconfont.js new file mode 100644 index 0000000..89ebdec --- /dev/null +++ b/miniprogram/assets/icons/iconfont.js @@ -0,0 +1 @@ +!function(a){var c,t='',l=(c=document.getElementsByTagName("script"))[c.length-1].getAttribute("data-injectcss");if(l&&!a.__iconfont__svg__cssinject__){a.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(c){console&&console.log(c)}}!function(c){if(document.addEventListener)if(~["complete","loaded","interactive"].indexOf(document.readyState))setTimeout(c,0);else{var l=function(){document.removeEventListener("DOMContentLoaded",l,!1),c()};document.addEventListener("DOMContentLoaded",l,!1)}else document.attachEvent&&(h=c,i=a.document,o=!1,(s=function(){try{i.documentElement.doScroll("left")}catch(c){return void setTimeout(s,50)}t()})(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,t())});function t(){o||(o=!0,h())}var h,i,o,s}(function(){var c,l;(c=document.createElement("div")).innerHTML=t,t=null,(l=c.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",function(c,l){l.firstChild?function(c,l){l.parentNode.insertBefore(c,l)}(c,l.firstChild):l.appendChild(c)}(l,document.body))})}(window); \ No newline at end of file diff --git a/miniprogram/assets/icons/iconfont.svg b/miniprogram/assets/icons/iconfont.svg new file mode 100644 index 0000000..a338060 --- /dev/null +++ b/miniprogram/assets/icons/iconfont.svg @@ -0,0 +1,119 @@ + + + + + +Created by iconfont + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/miniprogram/assets/icons/iconfont.ttf b/miniprogram/assets/icons/iconfont.ttf new file mode 100644 index 0000000..b835bd4 Binary files /dev/null and b/miniprogram/assets/icons/iconfont.ttf differ diff --git a/miniprogram/assets/icons/iconfont.woff b/miniprogram/assets/icons/iconfont.woff new file mode 100644 index 0000000..ef419ef Binary files /dev/null and b/miniprogram/assets/icons/iconfont.woff differ diff --git a/miniprogram/assets/icons/iconfont.woff2 b/miniprogram/assets/icons/iconfont.woff2 new file mode 100644 index 0000000..19b2e57 Binary files /dev/null and b/miniprogram/assets/icons/iconfont.woff2 differ diff --git a/miniprogram/assets/icons/iconfont.wxss b/miniprogram/assets/icons/iconfont.wxss new file mode 100644 index 0000000..1bc860f --- /dev/null +++ b/miniprogram/assets/icons/iconfont.wxss @@ -0,0 +1,141 @@ +@font-face {font-family: "iconfont"; + src: url('iconfont.eot?t=1564286613049'); /* IE9 */ + src: url('iconfont.eot?t=1564286613049#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAABPoAAsAAAAAJywAABOYAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCGVAq6VK4nATYCJAOBAAtCAAQgBYRtB4J6G/MfRaSTpJUFsv/rBE6ujnVHCEU4arsFlvYY8SjTj2xpdfnOvbsitmXpV+MtFmAV6iRV8OCgUTRQZZTiiwqOGUrJwz/7ufttjg/RcfoyGU+iUbUE8QQ1kEiU9LCtOUweCykgqsndnCRrNphTk5JDKcnIUOK0I0BDYZwOgOWvffczBDYOGMY3QHDk1wF/fluaD/wXQMDwtM1/F+QRgoEbByJmgDajZSY6MZoZrBIjsWrRunL6w5jr1kUxF6mLX6X+uSg3dcZJStP/7R6W4tj1acddsSXbASmmUg8QYBT/+TnTFkao+SDDuJFFK/5LUnj5/+C3o/QwB9t6HQM7So8oHYJjUAQS5YSc0NN22s35QbqlV+lnrzWmDhn6sN/MB6vAFc44RcVojPrcnZwEqGndcH5xaUuFwNQEg1xfnB2oOLxEQM2EEa0ERebwHRSM9DX0BgBv/O0n/2DgCkjJDDultdULx6b/A/+1R76abIcJuElPw644kAFtIAfJlzDuE4S/2ObUEg39jX80+fTERUBhtax1NiBqtD9NgIsdrbttdeNmgUQs1e2l9ZWIj1Hp/j8ezWCy2IjD5fEFQlIklkhlcoVSpdZodSApoQM3AMkDerRAgKcgASGSgkBESiDsVW5WAJEchEGkDGKeSAXEApEqiEUiNRCFInUQRSINEMVcB1gJuE6wUnBdYGXgusHKwfWAVYDrBasEV4BVgesDM4FrgtWA6werAzcAVg9uEKwB3BBYI7hhsCZwI2DN4EbBWsCNgbWCGwdrAzcB1o7htAAm30VMAx6oLtCYwqI+uDS9+2akHtetEm4y7DyGPSUJKdCqFLGfrYPgVTSIoJLngbmWJuNx8XJb2mPj+1SYxOCjtoqUbn8kLfhFZuvbNIRvGJA2hE/ppyCqGWqu/Guv+xg6JdmXWK3CZ1iqcR4ZpIslRIeB11cY+YR21TlGjtpX1GvuceWEd33Fn2uzTMulkoxw9AaKiV00QGwUU133OCdRCan5dBoqHsbBXdhSQ4d25ZaI7D1vSbHtTa01mtu0Wdx0wPeFYlEMApnSJQggWCp+hiyNExnMyWMEDBDAOzgmQalEVSGs5hPxqBU1+Th0oHSqdCQ0oQUeV5MwN/z2a5+Uz9pH8kHUmeO0572R3i/wNJ36xK8hl1pujLb9Cu4eVYK3glY8P+IfACTbEMvnOZi6q91X7ql3SqBViHfJ5QQbErJgUto4o4R2l9xR7yn3ZRCD+OrDIdcfD3u3AsG1R0OvPBg8KoJKIR7N5VpjRCNi0AEQtDzNAdJz35NXOFPxFoc4hy2qCaFpooiqM4DoqsnBzG0c1W6WOoK0xdRbECq3cZe9P3ljs2GYHosPbY1lvq+raSoW7qYZRF+fSCqn62AHUaRswfJJeXeTI7EHqjoxDAuaaxX5jyCpNnE0T3FF1ytK+VtuXs3aN1TOkVrAV+RzN52cVvBua+DYKHRfB1a7anNnsULU+HEhcunuSxx9HtSHxxiapXQiWDcLfrmAePTDYATT95pQ9k4JQNc+VYXRGk9rWXVAcqnqNws3/JpQsShGg0AOK3RtxOLCYk6LyyE94fuTkQXDimnmGUFXOSnfoOsgpLPoGZXCyuNecuG6drVRdB6CA8j3hTRsGPou2AeUvABSKvXovp6PEq8gBAz7Ir4W0PmM1gXBtKdF8aS/FDWCxmJrP2XUqrQnAh0KQDleCLErzZKZtVOsmAQhMsD2QSJDa0E/rA07VpxS876Vyz0vBHBrsrYzllq+It9TpB6jS0/8itzVTHGGfjI9DcMZL97Ffx9DxO/NmmXPce+1oUEgBkXxyuClJdQnP6ObJCBu/O2gvlKppDjijct5O5EtOrfazPBrLM0hTOcqg9gHOugqJJ0Cz4dSLUYOY6jw5VYcG2yjkQIAF3pZGRh2Ol/LNLkVuqvwa1abiqexMQNMp75DsllFUD8EBG2j/0nB/3LxX9H/xwA7wS3At0QCsvH4qOGkklLEvFUhNjQgiGhHz5YaDDxTEaUrlhmlfTCRPNotrFTGsXxk4icEPZtP8zJKIA53oAxGw7JVyKUYgUuZpCDUitPsyCB5lMLOyIqSejvk5okSMlSqxeR6Tph8KDgIIDT5E++HsFffXjpVIhB2idErWpN3FqzzuVfWnr4fb4tqFuwwOXTtXhWUT/RNu02cOT8Y+oKAVB20EYPF/hntprmBtrjh0eKElofixwVOI2tMqZPkNT5e6OX1WhRMyvCPgzpKJVXorYZYobeO74Ng3+FtpOY5o+dYupBK6TJKF9v+tOKY+8GBurvmcHkBg2LLdclqxVgz4+VYMUVKasr7TQ6FoOoel4vMomqDYassfBkg5TRu6SrOgmHnUH1awStfuod+y4Eej0NYPbYxBejxjk5YI2uXtLX/uTAdgDiNjZqBLQ9CizNdpiFrb1JAvOAMVXGbmlQTqTYAOms4Hc4lAI76gwvmaGlNe1+u2FBMCE98HmaxmNKffAFfL1YaMn1/GKxyTddoCgP+0isIfi7uCC+XYMqIFS31QMJITKtwg/bl+o4ZLfhT3KuhlcznI2nBUuUlDNYojf4lHPMJnSpOwZrBDiAGMHLjSmoYGqosXXOloSbo3G5ZOrcm9k0EaS4ccD0+TlVfGMgOteA32WAkY/Zt1TxbjLleVp3P8tobU+VHsqTa4U75o2frAOiH/JQL/DwvqILH3w1FVz5UCGZkyRDNbIdopOwsJ5kwXLgZWSwzzB6r4KSYVv24Q2mvwIrj2p/Q826mREqaG0QF1ZfSd1z9WNkimvqpqqVUsT2l1WVrHpruamGYbjPAkDqeJopg6VwwNz2znGBbK1OZ+iv+Z6qquW/qz/hfqT53IdPHVbVv/EG4N6Xy683mOb++OFJVFuv4dkBPtndlKXOp8nLffl9CKjk8p8s4fzpib/JrGe1Ty3i+ao50zUvtChsaDSYDiJlv6bXtTRK6tyu/g/e3jXcOspQk6pnlQs/vdQfvvBr/9ogcEjP6pIo3k55B9HO3mnVghtUhz+7EbfNqxA1pmjiln2fdds+MJHlLuglyOGEDgABRnEO/fkXtPpcAl2VO4vm6Pbj9dfBr3VDw2vr6oh9+SOYn4y56zK8NHtK9BvW1wUplK65asECFR/B3aPhKfHTnqXgRO4Q8gV+Ja3g7vgAbnkflblEWtwXiMyHtggVa14AWLjh7pndrNtdPKWNFsaKhKOjaayELF2qnVRPVx+xJUVHVK1ZeHPvhFROqr8J4WsG0X2mTjqHXl/g1l/rl6P0vQggg6CL/De1f/YblY9hCelF4kYQaMYqxseUb9P/CtXZOSU/o5DHEY3xtHTUaJY2dWvNlcqVqEdUqKE+Ttypo1WOusjIH+HAoLLf+Huv/bSDyd2RFVxrHDp+BhJVjwBbQ8MM0Dwd7vyi2Besi/CAfl8xZFYdQb1F6WVOMx/Qp+17KLcsz5AHCduFj4XbCwGXEwzcIB2ze2AwINxyvzhvC9vti9lvGBvpb4Qv7KfoGxhTLd32e1HTT8hZFSj1jebotiHIaLSHE+wqRErTch1mPet6yCXOaiP/VvVCP0UjEnyTUixDCrPt6lVav79JmddrNMpDQ0L7crTu3WQ/sQERiMslk51J1gZOGz8TTOKH8XEJc0mh06i3Lm+sOuKZhXCzNNcQ2jTuTm2Ybqqn0ejwXYDTrQGHht9QvK7cb2KOWBckreYriAN7Di/FafJnBYDnKTr/w7DOpiXyC3ER60UkuMMV+pvp3nejyp36OJ2rybojPZ/mzBHYg8NCe33uPKawjFFZHfu/b7ZNJaISzysszoRGRnTec1RjgnWl1AHUiLFALz0oGbXYBAayHZDrdhLMTsYey9g+LmuJZw/jwME+ckb+W0kNwcpjQCZCs0Yn+8Pc+r5feY97k9ZDpAJzurz61Fbl1E9lqOwlzbUUc+beUgTnxdQrH+Ox/HOJ9oKyKzEmRjoWyEqy8YN9H6sQQl1NlSE8PXGorEh3LEMcQVfsmRIEJZMYJowaQMfN9I+AwxbjoFcesxFXBI4xjYeYRswgXg5Pxq5kinoj51r9w4Mxa3hjY1vdiTMiJblv3a6qApwJj2OxIG5kTlGo0pkGBGX6nerxabs8OBl1xcTMdP116zi8IPFm1x+aeuXAPr0ClXpNJyGyQFEiSJMl8M5gefLPdq141A0ozrk6FD+JLhUbyNJlCDoOdrQ8v5RhrrhqOZe2w25TO2qWtj4RqGG0ja8fC5f9jdasyPo5JxsmI1r1gfmyNzJkYI/pR5v81IAerSGwW3F8GygwPnvvXTvFuSobMNbYGzFfWYwYaiK/6UtI78dL01D6uitspl8nlHVwNcLB0FYh9F6c3BVMu9xoMmFXTKGP4BiV4eb8gY3kNKSmRcvtml7ypg2E4IDNKyEtEoBh6FXcIWSdXze1PTdkFd6am94H2qq6uDlzF7T95sv8lZ9GnOvMpKhCg1HwqEIxh9eF2BSUSUWpeIRJdyBccqjLQURy5kH/AEntLe/Exwi0P5F9AcIT23KAZofR8mhV9Euzbx2hLyhiyFO7aY5XCPT38vzuQGzcQu7clQLII7g5Mv5g9sLefq+P2Dw62N/vHgqPw5CR6DD3aeHQL5DiOJgatAxO3eFyXLB1+7OV28sSr5HK6rFbvZSh5SvMZT8/Yb32OvZLe9a/1XKW+TB/E+zD+JnE9OTHli3rKZzBdVe3UK182bVIXbmLYadj6xuGatAn+fUDHuaA5kG6eZi7ZpfC5ccRxwdndWnIk1jXFzrFM2CQZHtdfLPBkzaWnmrt/HEGMaMJ6as1fFmMQRtYs1eivwCNdf9rmx2qrY7mpGAc7SyGLqS9MDtgZzEpMvg3+zsrSszLhimZoAdNOFxL7b6Ti+PiA2Gs6WKwQEBNj4/ze/zkUqf5r3d40XiKAFlQ0D1S/LP3QyaE+eV0Owg0SxwI3Wa6fPHb2NYU43qw8gjOu/6jQH1CKj8dG+snN613lTvkS0Nh9qBwJzPJISVkpQIBktXsf5kHk558RuwcTIFsqfTB0R6/T6dfDjaYHvU4L+/OmsI8r3tMbGT3pNaGZrcoTNW9IR4rLoQxPhhIX0T3hkl3dRQTgM2MEMyZoNNZGughXMqav9/uC+zFaazQJxqVkTwyjabpyfkjO3tZ+bdycbyozEelLBmsFy60qAvLhBHi8oNsu1EF68f88vvLPiyiaL660WiY+cQuDxW7EUdK1kC2vwZfTRIpOTJYdLwf3an3r7jk673v0tIqP7aKPml91w+jpQycyD58knkGuRXmc8cJ28W+/YnSv2h6o8FrGr5ZDfz0d73/yH9ghjInuQ9bnYLFsunhfdQ1f727zh672O7u+T2unpCRYrF7kosMWFUO69VDi/KJE+hpLHljD/sh/Y6HE9VDqqrJUkhKuJ6gcZQaMVVdHHorT4euomoTGRoYVaGE1aeaQ19O0uisUyh9Bx2ELuPX7a2CEmdFMGlPIVFAcQ23/ocK/vNseig2EQ5ojgJ0uadx23CbsutQfuxVeOTIvrRCTL0qMAtXXkkSK/P2rptWYCWD2S67IhGxFdiqcCRLm/37BD0OvRAxO5Uj/tqRbljowWQwCD5Nnx8kh0rrUiE9or5Ph/qiCxKGLcTGdYwV/HBviyFcSVoT4kvSmZBJPvmr+GDN2WbZp9QkPzqEfu6uesSoyHE9EF04/yy4OmfhsS4glPK1l2Qsex7eTLISfzT5u8yW5R8tvVp2HerdU9HpaXeotn+fSVYpfyVXPeg9wsBPpsWehDO02D+tLvbPD5UAYyTMUpzJ8a+aBfhqH1p/27s9TxRQxObUCLOm0+oI4zkNlFlBe4LCIoK27OrRV3fdZlW3nwrM8t6qvd38HYLrDJyR7+uO04x9EBcD0OZcQBWCGSCUCAJg+4QgSzcNOuoZohFbDSNF0jM7GAID3IrD/LdKLhCLwFX4LvxPVHIFNYQNuIdn+A8aQeITdcwgJwCFqjcBuSEF4Kq2xKG4nref0NEVATL+5sgKTw5J1OczwKTL2b1jXpwnpJg71UuQCAJAB7BcPAfALi6PoyfLVdXUyFNwoeEKgy/pjyTRQp1yaBAE0+APACiNVnwOA32BJbDBW5ihraeVnX5S1JcCABHgCAsjA0YqW9RQIAANigQjIQCpQgQfQFI8BS7ASIABCKQAAd1CvCRCwAPsFGDDAeUREZW8jirKjAgHYgH/cRKpCiEAFtqQvJrGmf/O3iJDRqPaqvBYmdcpzY9BvtGWASJybnP4xJi+s9pvdvdcXMsY08kkne8iZFEUZ1aeWBw6DqClKhzpvHD2n43ZLh3w3Wsa7uUkiBPK7cUNpXZv1NMFo2dnc9ea/IasYgBgwzkuz/1CU+H1X9jZ2EtYvylLjLMvQyYl1kIlG1HPkSIyUT6KhQQ8IZRJn1kFatuFi+CdHWzItkqWb/KPGMUPvet94WeEqQ44CJSrUaKD5z8jdI3TQRQ/9wXA0nkxn88Vytd5sd/uDxZmUc9EOR+ClZdQL29ebA7buCDsSxn6tZbo+ncVgZTyzAKmSk3LF+jPqvvpGHtA38dXncCAYANgVv6QOaUOLbE2RlXbQJ6M49EqDT7R7laQkgs5tAe488M1XB731s8sHLy6frY0IwmkX7+7YZCrTvpoEcvUv46ceqdSTZzsULlvfwNqV55x1hl92nuuk3nY4K6LG1n6x8h6qBV+7ImbnubsDAAA=') format('woff2'), + url('iconfont.woff?t=1564286613049') format('woff'), + url('iconfont.ttf?t=1564286613049') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ + url('iconfont.svg?t=1564286613049#iconfont') format('svg'); /* iOS 4.1- */ +} + +.iconfont { + font-family: "iconfont" !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-gouwucheman:before { + content: "\e600"; +} + +.icon-gouwuchekong:before { + content: "\e601"; +} + +.icon-zhanghuchongzhi-copy:before { + content: "\e621"; +} + +.icon-wode:before { + content: "\e665"; +} + +.icon-dangao:before { + content: "\e67e"; +} + +.icon-shouye:before { + content: "\e603"; +} + +.icon-shouye1:before { + content: "\e666"; +} + +.icon-fenlei:before { + content: "\e667"; +} + +.icon-gouwuche:before { + content: "\e669"; +} + +.icon-wode1:before { + content: "\e66b"; +} + +.icon-fanhui:before { + content: "\e676"; +} + +.icon-fanhuishouye:before { + content: "\e677"; +} + +.icon-gengduo:before { + content: "\e678"; +} + +.icon-chakangengduo:before { + content: "\e679"; +} + +.icon-caidan:before { + content: "\e67a"; +} + +.icon-sousuo:before { + content: "\e67b"; +} + +.icon-guanjianzi:before { + content: "\e67c"; +} + +.icon-guanbi:before { + content: "\e67d"; +} + +.icon-xuanxiang:before { + content: "\e67f"; +} + +.icon-dianzan:before { + content: "\e680"; +} + +.icon-xihuan:before { + content: "\e682"; +} + +.icon-fenxiang:before { + content: "\e684"; +} + +.icon-saoyisao:before { + content: "\e685"; +} + +.icon-kefu:before { + content: "\e686"; +} + +.icon-pinglun:before { + content: "\e687"; +} + +.icon-shanchu:before { + content: "\e688"; +} + +.icon-tishi:before { + content: "\e689"; +} + +.icon-jinhangzhong:before { + content: "\e68a"; +} + +.icon-chenggong:before { + content: "\e68b"; +} + +.icon-shibai:before { + content: "\e68c"; +} + +.icon-huodong:before { + content: "\e68d"; +} + diff --git a/miniprogram/assets/images/tabs/cake-selected.png b/miniprogram/assets/images/tabs/cake-selected.png new file mode 100644 index 0000000..cd2957e Binary files /dev/null and b/miniprogram/assets/images/tabs/cake-selected.png differ diff --git a/miniprogram/assets/images/tabs/cake.png b/miniprogram/assets/images/tabs/cake.png new file mode 100644 index 0000000..11794f2 Binary files /dev/null and b/miniprogram/assets/images/tabs/cake.png differ diff --git a/miniprogram/assets/images/tabs/home-selected.png b/miniprogram/assets/images/tabs/home-selected.png new file mode 100644 index 0000000..d7f4c12 Binary files /dev/null and b/miniprogram/assets/images/tabs/home-selected.png differ diff --git a/miniprogram/assets/images/tabs/home.png b/miniprogram/assets/images/tabs/home.png new file mode 100644 index 0000000..bda6cd9 Binary files /dev/null and b/miniprogram/assets/images/tabs/home.png differ diff --git a/miniprogram/assets/images/tabs/me-selected.png b/miniprogram/assets/images/tabs/me-selected.png new file mode 100644 index 0000000..f6f2ed2 Binary files /dev/null and b/miniprogram/assets/images/tabs/me-selected.png differ diff --git a/miniprogram/assets/images/tabs/me.png b/miniprogram/assets/images/tabs/me.png new file mode 100644 index 0000000..6b5f565 Binary files /dev/null and b/miniprogram/assets/images/tabs/me.png differ diff --git a/miniprogram/assets/images/vip.png b/miniprogram/assets/images/vip.png new file mode 100644 index 0000000..19ae56b Binary files /dev/null and b/miniprogram/assets/images/vip.png differ diff --git a/miniprogram/components/avatar/avatar.js b/miniprogram/components/avatar/avatar.js new file mode 100644 index 0000000..5ac5548 --- /dev/null +++ b/miniprogram/components/avatar/avatar.js @@ -0,0 +1,36 @@ +// components/avatar/avatar.js +Component({ + /** + * 组件的属性列表 + */ + properties: { + size: { + type: Number, + value: 60 + }, + isCube: { + type: Boolean, + value: false + }, + bordered: { + type: Boolean, + value: true + } + }, + + /** + * 组件的初始数据 + */ + data: { + avatarInfo: null + }, + + attached: function() { + let avatarInfo = wx.getStorageSync('avatarInfo') + this.setData({ + avatarInfo: avatarInfo + }) + }, + methods: { + } +}) diff --git a/miniprogram/components/avatar/avatar.json b/miniprogram/components/avatar/avatar.json new file mode 100644 index 0000000..e8cfaaf --- /dev/null +++ b/miniprogram/components/avatar/avatar.json @@ -0,0 +1,4 @@ +{ + "component": true, + "usingComponents": {} +} \ No newline at end of file diff --git a/miniprogram/components/avatar/avatar.wxml b/miniprogram/components/avatar/avatar.wxml new file mode 100644 index 0000000..dfadc93 --- /dev/null +++ b/miniprogram/components/avatar/avatar.wxml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/miniprogram/components/avatar/avatar.wxss b/miniprogram/components/avatar/avatar.wxss new file mode 100644 index 0000000..5a9e13c --- /dev/null +++ b/miniprogram/components/avatar/avatar.wxss @@ -0,0 +1,9 @@ +.avatar { + overflow: hidden; + box-sizing: border-box; + z-index: 2 +} + +.bordered { + border: 4px solid #eee; +} \ No newline at end of file diff --git a/miniprogram/components/counter/counter.js b/miniprogram/components/counter/counter.js new file mode 100644 index 0000000..48f4459 --- /dev/null +++ b/miniprogram/components/counter/counter.js @@ -0,0 +1,112 @@ +// utils/forms/counter/counter.js +var tapInterval; + +Component({ + /** + * 组件的属性列表 + */ + properties: { + counter: { + type: Number, + value: 0 + }, + maxCount: { + type: Number, + value: 0 + }, + price: { + type: String, + value: null + }, + optId: { + type: String, + value: null + }, + initvalue: { + type: String, + value: '0' + } + }, + + /** + * 组件的初始数据 + */ + data: { + + }, + + ready() { + console.log('counterd:', this.data.initvalue) + this.setData({ + counter: this.data.initvalue + }) + }, + methods: { + onTapSub: function(e) { + if((this.data.counter - 1) >= 0) { + this.setData({ + counter: this.data.counter - 1 + }) + this.triggerEvent("action", { + actionType: 'counterUpdate', + counter: this.data.counter, + optId: this.data.optId, + price: this.data.price + }); + } + }, + onTapAdd: function(e) { + if((this.data.counter + 1) <= this.data.maxCount) { + this.setData({ + counter: this.data.counter + 1 + }) + this.triggerEvent("action", { + actionType: 'counterUpdate', + counter: this.data.counter, + optId: this.data.optId, + price: this.data.price + }); + } + }, + onLongTapSub: function (e) { + tapInterval = setInterval(()=>{this.onTapSub()}, 100) + }, + onLongTapAdd: function (e) { + tapInterval = setInterval(()=>{this.onTapAdd()}, 100) + }, + onSubTapEnd: function() { + if(tapInterval){ + clearInterval(tapInterval) + } + }, + onAddTapEnd: function() { + if(tapInterval){ + clearInterval(tapInterval) + } + }, + onInputChange: function(e) { + if(!e.detail.value) { + this.triggerEvent("action", { + actionType: 'AF_FORM_COUNTER_UPDATE', + counter: '0', + optId: this.data.optId, + price: this.data.price + }) + return '0' + } else { + let val = Math.abs(parseInt(e.detail.value)) + if (val <= this.data.maxCount) { + this.triggerEvent("action", { + actionType: 'AF_FORM_COUNTER_UPDATE', + counter: val, + optId: this.data.optId, + price: this.data.price + }) + return val.toString() + } else { + return this.data.maxCount.toString() + } + } + } + } +}) diff --git a/miniprogram/components/counter/counter.json b/miniprogram/components/counter/counter.json new file mode 100644 index 0000000..e8cfaaf --- /dev/null +++ b/miniprogram/components/counter/counter.json @@ -0,0 +1,4 @@ +{ + "component": true, + "usingComponents": {} +} \ No newline at end of file diff --git a/miniprogram/components/counter/counter.wxml b/miniprogram/components/counter/counter.wxml new file mode 100644 index 0000000..26cce6e --- /dev/null +++ b/miniprogram/components/counter/counter.wxml @@ -0,0 +1,7 @@ + + - + + + + + + diff --git a/miniprogram/components/counter/counter.wxss b/miniprogram/components/counter/counter.wxss new file mode 100644 index 0000000..54aacdb --- /dev/null +++ b/miniprogram/components/counter/counter.wxss @@ -0,0 +1,50 @@ +.counter-controls { + width:100%; + height: 30px; + border-radius: 5px; + border: 1px solid #ddd; + display: flex; + overflow: hidden; +} + +.counter-sub, .counter-add { + height: 30px; + line-height: 30px; + width:30px; + box-sizing: border-box; + display: flex; + justify-content: center; + align-items: center; + background-color: #f5f5f5; + font-size: 120%; + font-weight: bold; + color: #333; + z-index: 1 +} +.counter-input { + /* flex: 1; */ + height: 30px; + width: calc(100% - 60px); + box-sizing: border-box; + font-size: 80%; + color: #333; +} + +.counter-input input { + height: 30px; + z-index: 1; + text-align: center; +} + +.counter-sub { + border-right: 1px solid #ddd; +} + +.counter-add { + border-left: 1px solid #ddd; +} + + +.counter-sub.disabled, .counter-add.disabled { + color: #ccc; +} \ No newline at end of file diff --git a/miniprogram/components/list/list.js b/miniprogram/components/list/list.js new file mode 100644 index 0000000..bb7440c --- /dev/null +++ b/miniprogram/components/list/list.js @@ -0,0 +1,47 @@ +// components/list/list.js + +// entity = { + // key: 1 + // isLink: true + // title: '个人资料' + // value: '完成度100%', + // color: #333 + // arrowColor: #999, + // openType + // isPicker + // useSlot +// } + +Component({ + /** + * 组件的属性列表 + */ + properties: { + entities: { + type: Array, + value: [] + } + }, + + /** + * 组件的初始数据 + */ + data: { + + }, + + /** + * 组件的方法列表 + */ + methods: { + onClickItem: function(e) { + let currentItem = this.data.entities[e.currentTarget.dataset.index] + if (currentItem.isLink && currentItem.url) { + wx.navigateTo({ + url: currentItem.url, + }) + } + this.triggerEvent('onTapListItem', {'index': e.currentTarget.dataset.index}) + } + } +}) diff --git a/miniprogram/components/list/list.json b/miniprogram/components/list/list.json new file mode 100644 index 0000000..78013bd --- /dev/null +++ b/miniprogram/components/list/list.json @@ -0,0 +1,5 @@ +{ + "component": true, + "usingComponents": { + } +} \ No newline at end of file diff --git a/miniprogram/components/list/list.wxml b/miniprogram/components/list/list.wxml new file mode 100644 index 0000000..1f740a9 --- /dev/null +++ b/miniprogram/components/list/list.wxml @@ -0,0 +1,15 @@ + + + + + + + {{item.title}} + + {{item.value}} + + + + + + \ No newline at end of file diff --git a/miniprogram/components/list/list.wxss b/miniprogram/components/list/list.wxss new file mode 100644 index 0000000..e52e5a9 --- /dev/null +++ b/miniprogram/components/list/list.wxss @@ -0,0 +1,85 @@ +@import '../../assets/icons/iconfont.wxss'; + +.list { + background-color: #fff; +} + +.item { + height: 60px; + line-height: 60px; + width: 100%; + box-sizing: border-box; + font-size: 14px; + padding-left: 20px; + padding-right: 20px; + color: #333; +} + +.wrapper { + height: 100%; + width: 100%; + display: flex; + border-bottom: 1px solid #eee; +} + +.item:last-child .wrapper { + border-bottom: 0; +} + +.icon { + width: 30px; + /* background-color: #eee; */ + /* border: 1px solid #333; */ + text-align:center; + padding-top:3px; + box-sizing:border-box; +} + +.title { + flex: 1; + /* background-color: #eee; */ + /* border: 1px solid #333; */ + box-sizing: border-box; +} + +.value { + max-width: 100px; + /* background-color: #eee; */ + /* border: 1px solid #333; */ + box-sizing: border-box; + text-align: center; + line-height: 60px; +} + +.arraw { + width: 20px; + /* background-color: #eee; */ + /* border: 1px solid #333; */ + box-sizing: border-box; + display: flex; + justify-content: center; + align-items: center; + padding-top:3px; +} + + +.ellipsis { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +button::after { + border: none; +} + +button { + background-color: #fff; + text-align: left; + padding-left: 0; + padding-right: 0; + border-radius:0; + font-size: 14px; + line-height: 60px; + margin-top: 1px; +} \ No newline at end of file diff --git a/miniprogram/components/list_item/list_item.js b/miniprogram/components/list_item/list_item.js new file mode 100644 index 0000000..ba3d0c8 --- /dev/null +++ b/miniprogram/components/list_item/list_item.js @@ -0,0 +1,76 @@ +Component({ + + properties: { + key: { + type: String, + value: null + }, + icon: { + type: String, + value: null + }, + isLink: { + type: Boolean, + value: false + }, + title: { + type: String, + value: '' + }, + value: { + type: String, + value: null + }, + color: { + type: String, + value: '#666' + }, + iconColor: { + type: String, + value: '#333' + }, + titleColor: { + type: String, + value: '#999' + }, + arrowColor: { + type: String, + value: '#999' + }, + borderColor: { + type: String, + value: '#eee' + }, + borderWidth: { + type: String, + value: '1' + }, + url: { + type: String, + value: null + }, + useSlot: { + type: Boolean, + value: false + }, + openType: { + type: String, + value: null + } + }, + + data: { + + }, + + methods: { + onClickItem: function (e) { + if(this.data.url && this.data.url.startsWith('/pages')) { + wx.navigateTo({ + url: this.data.url, + }) + } + this.triggerEvent('onTapItem', { 'key': this.data.key, 'value': this.data.value, 'url': this.data.url }) + } + } +}) diff --git a/miniprogram/components/list_item/list_item.json b/miniprogram/components/list_item/list_item.json new file mode 100644 index 0000000..2176e13 --- /dev/null +++ b/miniprogram/components/list_item/list_item.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + + } +} \ No newline at end of file diff --git a/miniprogram/components/list_item/list_item.wxml b/miniprogram/components/list_item/list_item.wxml new file mode 100644 index 0000000..c4b2cb5 --- /dev/null +++ b/miniprogram/components/list_item/list_item.wxml @@ -0,0 +1,15 @@ + + + + + + + {{title}} + + + {{value}} + + + + + \ No newline at end of file diff --git a/miniprogram/components/list_item/list_item.wxss b/miniprogram/components/list_item/list_item.wxss new file mode 100644 index 0000000..d85b869 --- /dev/null +++ b/miniprogram/components/list_item/list_item.wxss @@ -0,0 +1,2 @@ +@import '../list/list.wxss'; +@import '../../assets/icons/iconfont.wxss'; diff --git a/miniprogram/components/wux-weapp/animation-group/index.js b/miniprogram/components/wux-weapp/animation-group/index.js new file mode 100644 index 0000000..2c08b5f --- /dev/null +++ b/miniprogram/components/wux-weapp/animation-group/index.js @@ -0,0 +1 @@ +"use strict";var _baseComponent=_interopRequireDefault(require("../helpers/baseComponent")),_styleToCssString=_interopRequireDefault(require("../helpers/styleToCssString"));function _interopRequireDefault(t){return t&&t.__esModule?t:{default:t}}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var ENTER="enter",ENTERING="entering",ENTERED="entered",EXIT="exit",EXITING="exiting",EXITED="exited",UNMOUNTED="unmounted",TRANSITION="transition",ANIMATION="animation",TIMEOUT=1e3/60,defaultClassNames={enter:"",enterActive:"",enterDone:"",exit:"",exitActive:"",exitDone:""};(0,_baseComponent.default)({properties:{in:{type:Boolean,value:!1,observer:function(t){this.data.isMounting&&this.updated(t)}},classNames:{type:null,value:defaultClassNames},duration:{type:null,value:null},type:{type:String,value:TRANSITION},appear:{type:Boolean,value:!1},enter:{type:Boolean,value:!0},exit:{type:Boolean,value:!0},mountOnEnter:{type:Boolean,value:!0},unmountOnExit:{type:Boolean,value:!0},wrapCls:{type:String,value:""},wrapStyle:{type:[String,Object],value:"",observer:function(t){this.setData({extStyle:(0,_styleToCssString.default)(t)})}},disableScroll:{type:Boolean,value:!1}},data:{animateCss:"",animateStatus:EXITED,isMounting:!1,extStyle:""},methods:{addEventListener:function(){var t=this.data.animateStatus,e=this.getTimeouts(),a=e.enter,n=e.exit;t===ENTERING&&!a&&this.data.enter&&this.performEntered(),t===EXITING&&!n&&this.data.exit&&this.performExited()},onTransitionEnd:function(){this.data.type===TRANSITION&&this.addEventListener()},onAnimationEnd:function(){this.data.type===ANIMATION&&this.addEventListener()},updateStatus:function(t,e){var a=1 + + diff --git a/miniprogram/components/wux-weapp/animation-group/index.wxss b/miniprogram/components/wux-weapp/animation-group/index.wxss new file mode 100644 index 0000000..936cd3d --- /dev/null +++ b/miniprogram/components/wux-weapp/animation-group/index.wxss @@ -0,0 +1 @@ +.wux-animate--fadeIn-enter{transition:opacity .3s;opacity:0}.wux-animate--fadeIn-enter-active,.wux-animate--fadeIn-enter-done{opacity:1}.wux-animate--fadeIn-exit{transition:opacity .3s;opacity:1}.wux-animate--fadeIn-exit-active,.wux-animate--fadeIn-exit-done{opacity:0}.wux-animate--fadeInDown-enter{transition:opacity .3s,transform .3s;opacity:0;transform:translate3d(0,-100%,0)}.wux-animate--fadeInDown-enter-active,.wux-animate--fadeInDown-enter-done{opacity:1;transform:none}.wux-animate--fadeInDown-exit{transition:opacity .3s,transform .3s;opacity:1;transform:none}.wux-animate--fadeInDown-exit-active,.wux-animate--fadeInDown-exit-done{opacity:0;transform:translate3d(0,-100%,0)}.wux-animate--fadeInLeft-enter{transition:opacity .3s,transform .3s;opacity:0;transform:translate3d(-100%,0,0)}.wux-animate--fadeInLeft-enter-active,.wux-animate--fadeInLeft-enter-done{opacity:1;transform:none}.wux-animate--fadeInLeft-exit{transition:opacity .3s,transform .3s;opacity:1;transform:none}.wux-animate--fadeInLeft-exit-active,.wux-animate--fadeInLeft-exit-done{opacity:0;transform:translate3d(-100%,0,0)}.wux-animate--fadeInRight-enter{transition:opacity .3s,transform .3s;opacity:0;transform:translate3d(100%,0,0)}.wux-animate--fadeInRight-enter-active,.wux-animate--fadeInRight-enter-done{opacity:1;transform:none}.wux-animate--fadeInRight-exit{transition:opacity .3s,transform .3s;opacity:1;transform:none}.wux-animate--fadeInRight-exit-active,.wux-animate--fadeInRight-exit-done{opacity:0;transform:translate3d(100%,0,0)}.wux-animate--fadeInUp-enter{transition:opacity .3s,transform .3s;opacity:0;transform:translate3d(0,100%,0)}.wux-animate--fadeInUp-enter-active,.wux-animate--fadeInUp-enter-done{opacity:1;transform:none}.wux-animate--fadeInUp-exit{transition:opacity .3s,transform .3s;opacity:1;transform:none}.wux-animate--fadeInUp-exit-active,.wux-animate--fadeInUp-exit-done{opacity:0;transform:translate3d(0,100%,0)}.wux-animate--slideInUp-enter{transition:transform .3s;transform:translate3d(0,100%,0);visibility:visible}.wux-animate--slideInUp-enter-active,.wux-animate--slideInUp-enter-done{transform:translateZ(0)}.wux-animate--slideInUp-exit{transition:transform .3s;transform:translateZ(0)}.wux-animate--slideInUp-exit-active,.wux-animate--slideInUp-exit-done{transform:translate3d(0,100%,0);visibility:visible}.wux-animate--slideInDown-enter{transition:transform .3s;transform:translate3d(0,-100%,0);visibility:visible}.wux-animate--slideInDown-enter-active,.wux-animate--slideInDown-enter-done{transform:translateZ(0)}.wux-animate--slideInDown-exit{transition:transform .3s;transform:translateZ(0)}.wux-animate--slideInDown-exit-active,.wux-animate--slideInDown-exit-done{transform:translate3d(0,-100%,0);visibility:visible}.wux-animate--slideInLeft-enter{transition:transform .3s;transform:translate3d(-100%,0,0);visibility:visible}.wux-animate--slideInLeft-enter-active,.wux-animate--slideInLeft-enter-done{transform:translateZ(0)}.wux-animate--slideInLeft-exit{transition:transform .3s;transform:translateZ(0)}.wux-animate--slideInLeft-exit-active,.wux-animate--slideInLeft-exit-done{transform:translate3d(-100%,0,0);visibility:visible}.wux-animate--slideInRight-enter{transition:transform .3s;transform:translate3d(100%,0,0);visibility:visible}.wux-animate--slideInRight-enter-active,.wux-animate--slideInRight-enter-done{transform:none}.wux-animate--slideInRight-exit{transition:transform .3s;transform:none}.wux-animate--slideInRight-exit-active,.wux-animate--slideInRight-exit-done{transform:translate3d(100%,0,0);visibility:visible}.wux-animate--zoom-enter{transition:all .3s cubic-bezier(.215,.61,.355,1);opacity:.01;transform:scale(.75)}.wux-animate--zoom-enter-active,.wux-animate--zoom-enter-done{opacity:1;transform:none}.wux-animate--zoom-exit{transition:all .25s linear;transform:none}.wux-animate--zoom-exit-active,.wux-animate--zoom-exit-done{opacity:.01;transform:scale(.75)}.wux-animate--punch-enter{transition:all .3s cubic-bezier(.215,.61,.355,1);opacity:.01;transform:scale(1.35)}.wux-animate--punch-enter-active,.wux-animate--punch-enter-done{opacity:1;transform:none}.wux-animate--punch-exit{transition:all .25s linear;transform:none}.wux-animate--punch-exit-active,.wux-animate--punch-exit-done{opacity:.01;transform:scale(1.35)} \ No newline at end of file diff --git a/miniprogram/components/wux-weapp/backdrop/index.js b/miniprogram/components/wux-weapp/backdrop/index.js new file mode 100644 index 0000000..2f7b066 --- /dev/null +++ b/miniprogram/components/wux-weapp/backdrop/index.js @@ -0,0 +1 @@ +"use strict";var _baseComponent=_interopRequireDefault(require("../helpers/baseComponent"));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}(0,_baseComponent.default)({properties:{prefixCls:{type:String,value:"wux-backdrop"},transparent:{type:Boolean,value:!1},zIndex:{type:Number,value:1e3},classNames:{type:null,value:"wux-animate--fadeIn"}},computed:{classes:["prefixCls, transparent",function(e,t){return{wrap:t?"".concat(e,"--transparent"):e}}]},methods:{retain:function(){"number"==typeof this.backdropHolds&&this.backdropHolds||(this.backdropHolds=0),this.backdropHolds=this.backdropHolds+1,1===this.backdropHolds&&this.setData({in:!0})},release:function(){1===this.backdropHolds&&this.setData({in:!1}),this.backdropHolds=Math.max(0,this.backdropHolds-1)},onClick:function(){this.triggerEvent("click")}}}); \ No newline at end of file diff --git a/miniprogram/components/wux-weapp/backdrop/index.json b/miniprogram/components/wux-weapp/backdrop/index.json new file mode 100644 index 0000000..9b9e7ab --- /dev/null +++ b/miniprogram/components/wux-weapp/backdrop/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "wux-animation-group": "../animation-group/index" + } +} \ No newline at end of file diff --git a/miniprogram/components/wux-weapp/backdrop/index.wxml b/miniprogram/components/wux-weapp/backdrop/index.wxml new file mode 100644 index 0000000..d6ee398 --- /dev/null +++ b/miniprogram/components/wux-weapp/backdrop/index.wxml @@ -0,0 +1 @@ + diff --git a/miniprogram/components/wux-weapp/backdrop/index.wxss b/miniprogram/components/wux-weapp/backdrop/index.wxss new file mode 100644 index 0000000..63310d6 --- /dev/null +++ b/miniprogram/components/wux-weapp/backdrop/index.wxss @@ -0,0 +1 @@ +.wux-backdrop{background:rgba(0,0,0,.4)}.wux-backdrop,.wux-backdrop--transparent{position:fixed;z-index:1000;top:0;right:0;left:0;bottom:0}.wux-backdrop--transparent{background:0 0} \ No newline at end of file diff --git a/miniprogram/components/wux-weapp/calendar/index.js b/miniprogram/components/wux-weapp/calendar/index.js new file mode 100644 index 0000000..33d6fdc --- /dev/null +++ b/miniprogram/components/wux-weapp/calendar/index.js @@ -0,0 +1 @@ +"use strict";var _baseComponent=_interopRequireDefault(require("../helpers/baseComponent")),_classNames4=_interopRequireDefault(require("../helpers/classNames"));function _interopRequireDefault(t){return t&&t.__esModule?t:{default:t}}function _toConsumableArray(t){return _arrayWithoutHoles(t)||_iterableToArray(t)||_nonIterableSpread()}function _nonIterableSpread(){throw new TypeError("Invalid attempt to spread non-iterable instance")}function _iterableToArray(t){if(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t))return Array.from(t)}function _arrayWithoutHoles(t){if(Array.isArray(t)){for(var e=0,n=new Array(t.length);enew Date(h).getTime()||c&&dnew Date(s).getTime())return this.resetMonth();if(this.monthsTranslate=this.monthsTranslate-1,r===o){var c=100*-this.monthsTranslate,u=this.monthHTML(h,"next"),l=getTransform(c,this.isH),d=[this.data.months[1],this.data.months[2],u];this.$$setData({months:d,monthsTranslate:[a[1],a[2],l]}),"function"==typeof this.fns.onMonthAdd&&this.fns.onMonthAdd.call(this,d[d.length-1])}this.onMonthChangeStart("next");var f=getTransform(100*this.monthsTranslate,this.isH),m=this.data.animate?.3:0,g="transition-duration: ".concat(m,"s; ").concat(f);this.$$setData({wrapperTranslate:g}),setTimeout(function(){return t.onMonthChangeEnd("next")},m)},prevMonth:function(){var t=this,e=this.data,n=e.months,a=e.monthsTranslate,s=e.minDate,o=e.currentMonth,r=parseInt(n[0].month,10),i=parseInt(n[0].year,10),h=new Date(i,r+1,-1).getTime();if(s&&h + + + + + + + + + {{ currentMonthName }} + + + + + + + + + {{ currentYear }} + + + + + + + + + + + {{ item.dayName }} + + + + + + + + + + + + {{ col.day }} + + + + + + + + + + + + diff --git a/miniprogram/components/wux-weapp/calendar/index.wxss b/miniprogram/components/wux-weapp/calendar/index.wxss new file mode 100644 index 0000000..6e31940 --- /dev/null +++ b/miniprogram/components/wux-weapp/calendar/index.wxss @@ -0,0 +1 @@ +.wux-calendar{position:relative;background:#fff;height:600rpx;width:100%;overflow:hidden}.wux-calendar__content{position:relative;width:100%;height:100%;transition:transform .3s}.wux-calendar__bd{height:100%;position:relative;overflow:hidden}.wux-calendar__hd{position:relative;width:100%}.wux-calendar__hd:before{content:" ";position:absolute;left:0;top:0;right:0;height:2rpx;border-top:2rpx solid #d9d9d9;color:#d9d9d9;transform-origin:0 0;transform:scaleY(.5)}.wux-calendar__hd+.wux-calendar__bd{height:calc(97.8%)}.wux-calendar__toolbar{height:2.2rem;display:-ms-flexbox;display:flex;text-align:center}.wux-calendar__picker{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;width:50%;max-width:400rpx;-ms-flex-negative:10;flex-shrink:10;display:block;line-height:2.2rem}.wux-calendar__link{float:left;width:25%;height:2.2rem;line-height:2rem;min-width:72rpx}.wux-calendar__icon{display:inline-block;vertical-align:middle;background-size:100% auto;background-position:center}.wux-calendar__icon--next,.wux-calendar__icon--prev{width:.75rem;height:.75rem}.wux-calendar__icon--next{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2015%2015'%3E%3Cg%3E%3Cpath%20fill%3D'%23007aff'%20d%3D'M1%2C1.6l11.8%2C5.8L1%2C13.4V1.6%20M0%2C0v15l15-7.6L0%2C0L0%2C0z'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.wux-calendar__icon--prev{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2015%2015'%3E%3Cg%3E%3Cpath%20fill%3D'%23007aff'%20d%3D'M14%2C1.6v11.8L2.2%2C7.6L14%2C1.6%20M15%2C0L0%2C7.6L15%2C15V0L15%2C0z'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.wux-calendar__value{-ms-flex-negative:1;flex-shrink:1;position:relative;overflow:hidden;text-overflow:ellipsis;float:left;width:50%;height:2.2rem}.wux-calendar__weekdays{height:36rpx;background:#f7f7f8;display:-ms-flexbox;display:flex;font-size:22rpx;box-sizing:border-box;position:relative}.wux-calendar__weekdays:after{content:" ";position:absolute;left:0;bottom:0;right:0;height:2rpx;border-bottom:2rpx solid #d9d9d9;color:#d9d9d9;transform-origin:0 100%;transform:scaleY(.5)}.wux-calendar__weekdays+.wux-calendar__months{height:calc(82%)}.wux-calendar__weekday{-ms-flex-negative:1;flex-shrink:1;width:14.28571429%;width:calc(14.28571429%);line-height:34rpx;text-align:center}.wux-calendar__months{width:100%;height:100%;overflow:hidden;position:relative}.wux-calendar__months-content{width:100%;height:100%;display:-ms-flexbox;display:flex;position:relative;-webkit-backface-visibility:hidden;transform:translate3d(0,0,0)}.wux-calendar__month{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;width:100%;height:100%;position:absolute;left:0;top:0}.wux-calendar__days{height:16.66666667%;height:calc(16.66666667%);display:-ms-flexbox;display:flex;-ms-flex-negative:1;flex-shrink:1;width:100%;position:relative}.wux-calendar__days:after{content:" ";position:absolute;left:0;bottom:0;right:0;height:2rpx;border-bottom:2rpx solid #d9d9d9;color:#d9d9d9;transform-origin:0 100%;transform:scaleY(.5)}.wux-calendar__days:last-child:after{display:none}.wux-calendar__day{-ms-flex-negative:1;flex-shrink:1;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center;box-sizing:border-box;width:14.28571429%;width:calc(14.28571429%);text-align:center;color:#3d4145;font-size:30rpx;cursor:pointer}.wux-calendar__day--next,.wux-calendar__day--prev{color:#ccc}.wux-calendar__day--disabled{color:#d4d4d4;cursor:auto}.wux-calendar__day--today .wux-calendar__text{background:#e3e3e3}.wux-calendar__day--selected .wux-calendar__text{background:#0894ec;color:#fff}.wux-calendar__text{display:inline-block;border-radius:100%;width:60rpx;height:60rpx;line-height:60rpx} \ No newline at end of file diff --git a/miniprogram/components/wux-weapp/dialog/index.js b/miniprogram/components/wux-weapp/dialog/index.js new file mode 100644 index 0000000..b4e1a5b --- /dev/null +++ b/miniprogram/components/wux-weapp/dialog/index.js @@ -0,0 +1 @@ +"use strict";var _baseComponent=_interopRequireDefault(require("../helpers/baseComponent")),_classNames3=_interopRequireDefault(require("../helpers/classNames"));function _interopRequireDefault(t){return t&&t.__esModule?t:{default:t}}function _objectSpread(e){for(var t=1;t + {{ title }} + + {{ content }} + + + + + + + + + + diff --git a/miniprogram/components/wux-weapp/dialog/index.wxss b/miniprogram/components/wux-weapp/dialog/index.wxss new file mode 100644 index 0000000..d7ff72a --- /dev/null +++ b/miniprogram/components/wux-weapp/dialog/index.wxss @@ -0,0 +1 @@ +.wux-dialog__button{padding:0;margin:0;border-radius:0;color:inherit!important;background:0 0!important;font-size:inherit;line-height:inherit;text-align:inherit;text-decoration:inherit;overflow:inherit;display:block;-ms-flex:1;flex:1;color:#33cd5f;position:relative}.wux-dialog__button:after{position:static;top:auto;left:auto;width:auto;height:auto;border:none;border-radius:0;transform:none;transform-origin:0 0}.wux-dialog__button--default{color:#353535}.wux-dialog__button--primary{color:#33cd5f!important}.wux-dialog__button--bold{font-weight:500!important}.wux-dialog__button--hover{background-color:#ececec!important}.wux-dialog__button--disabled{opacity:.3}.wux-dialog__prompt{position:relative;margin-top:20rpx}.wux-dialog__prompt:after{content:" ";position:absolute;top:0;left:0;width:200%;height:200%;transform:scale(.5);transform-origin:0 0;pointer-events:none;box-sizing:border-box;border:0 solid #d5d5d6;border-top-width:2rpx;border-right-width:2rpx;border-bottom-width:2rpx;border-left-width:2rpx;border-radius:12rpx}.wux-dialog__input{padding:8rpx 12rpx;height:72rpx;line-height:1;width:100%;text-align:left;box-sizing:border-box}.wux-dialog__buttons{display:-ms-flexbox;display:flex;-ms-flex:1;flex:1}.wux-dialog__buttons--horizontal .wux-dialog__button:after{content:" ";position:absolute;left:0;top:0;width:2rpx;bottom:0;border-left:2rpx solid #d5d5d6;color:#d5d5d6;transform-origin:0 0;transform:scaleX(.5)}.wux-dialog__buttons--horizontal .wux-dialog__button:first-child:after{display:none}.wux-dialog__buttons--vertical{display:block;height:auto}.wux-dialog__buttons--vertical .wux-dialog__button:after{content:" ";position:absolute;left:0;top:0;right:0;height:2rpx;border-top:2rpx solid #d5d5d6;color:#d5d5d6;transform-origin:0 0;transform:scaleY(.5)} \ No newline at end of file diff --git a/miniprogram/components/wux-weapp/helpers/arrayTreeFilter.js b/miniprogram/components/wux-weapp/helpers/arrayTreeFilter.js new file mode 100644 index 0000000..368a7c3 --- /dev/null +++ b/miniprogram/components/wux-weapp/helpers/arrayTreeFilter.js @@ -0,0 +1 @@ +"use strict";function arrayTreeFilter(e,r,t){(t=t||{}).childrenKeyName=t.childrenKeyName||"children";var a=e||[],l=[],i=0;do{var d=a.filter(function(e){return r(e,i)})[0];if(!d)break;l.push(d),a=d[t.childrenKeyName]||[],i+=1}while(0=").concat(libVersion," 后重试。")});var baseComponent=function(e){var r=0=Math.abs(s-o)?0 { + const componentCtx = ctx.selectComponent(selector) + + if (!componentCtx) { + throw new Error('无法找到对应的组件,请按文档说明使用组件') + } + + return componentCtx +} + +const $wuxBackdrop = (selector = '#wux-backdrop', ctx) => getCtx(selector, ctx) +const $wuxDialog = (selector = '#wux-dialog', ctx) => getCtx(selector, ctx) +const $wuxCalendar = (selector = '#wux-calendar', ctx) => getCtx(selector, ctx) +export { + $wuxBackdrop, + $wuxDialog, + $wuxCalendar +} \ No newline at end of file diff --git a/miniprogram/components/wux-weapp/popup/index.js b/miniprogram/components/wux-weapp/popup/index.js new file mode 100644 index 0000000..6edada9 --- /dev/null +++ b/miniprogram/components/wux-weapp/popup/index.js @@ -0,0 +1 @@ +"use strict";var _baseComponent=_interopRequireDefault(require("../helpers/baseComponent")),_classNames2=_interopRequireDefault(require("../helpers/classNames")),_styleToCssString=_interopRequireDefault(require("../helpers/styleToCssString")),_index=require("../index");function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function _defineProperty(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}(0,_baseComponent.default)({useSafeArea:!0,externalClasses:["wux-content-class","wux-header-class","wux-body-class","wux-footer-class","wux-close-class"],properties:{prefixCls:{type:String,value:"wux-popup"},animationPrefixCls:{type:String,value:"wux-animate"},title:{type:String,value:""},content:{type:String,value:""},extra:{type:String,value:""},position:{type:String,value:"center",observer:"getTransitionName"},wrapStyle:{type:[String,Object],value:"",observer:function(e){this.setData({extStyle:(0,_styleToCssString.default)(e)})}},closable:{type:Boolean,value:!1},mask:{type:Boolean,value:!0},maskClosable:{type:Boolean,value:!0},visible:{type:Boolean,value:!1,observer:"setPopupVisible"},zIndex:{type:Number,value:1e3},hasHeader:{type:Boolean,value:!0},hasFooter:{type:Boolean,value:!0},mountOnEnter:{type:Boolean,value:!0},unmountOnExit:{type:Boolean,value:!0}},data:{transitionName:"",popupVisible:!1,extStyle:""},computed:{classes:["prefixCls, position, safeAreaConfig, isIPhoneX",function(e,t,a,i){var o;return{wrap:(0,_classNames2.default)("".concat(e,"-position"),(_defineProperty(o={},"".concat(e,"-position--").concat(t),t),_defineProperty(o,"".concat(e,"-position--is-iphonex"),a.bottom&&i),o)),content:"".concat(e,"__content"),hd:"".concat(e,"__hd"),title:"".concat(e,"__title"),bd:"".concat(e,"__bd"),ft:"".concat(e,"__ft"),extra:"".concat(e,"__extra"),close:"".concat(e,"__close"),x:"".concat(e,"__close-x")}}]},methods:{close:function(){this.triggerEvent("close")},onMaskClick:function(){this.data.maskClosable&&this.close()},onExited:function(){this.triggerEvent("closed")},getTransitionName:function(e){var t=0 + + + + + {{ title }} + + + + + + {{ content }} + + + + {{ extra }} + + + + + + + + + + diff --git a/miniprogram/components/wux-weapp/popup/index.wxss b/miniprogram/components/wux-weapp/popup/index.wxss new file mode 100644 index 0000000..835b55a --- /dev/null +++ b/miniprogram/components/wux-weapp/popup/index.wxss @@ -0,0 +1 @@ +.wux-popup{position:fixed;z-index:1000;width:80%;max-width:600rpx}.wux-popup-position.wux-popup-position--center .wux-popup{top:50%;left:50%;transform:translate(-50%,-50%)}.wux-popup-position.wux-popup-position--center .wux-popup__content{border-radius:6rpx}.wux-popup-position.wux-popup-position--center .wux-popup__hd{padding:1.3em 1.6em .5em}.wux-popup-position.wux-popup-position--center .wux-popup__bd{padding:0 1.6em .8em}.wux-popup-position.wux-popup-position--center .wux-popup__ft:after{content:" ";position:absolute;left:0;top:0;right:0;height:2rpx;border-top:2rpx solid #d5d5d6;color:#d5d5d6;transform-origin:0 0;transform:scaleY(.5)}.wux-popup-position.wux-popup-position--top .wux-popup{position:fixed;left:0;top:0;width:100%;max-width:100%}.wux-popup-position.wux-popup-position--right .wux-popup{position:fixed;top:0;right:0;width:80%;max-width:100%;height:100%;max-height:100%}.wux-popup-position.wux-popup-position--bottom .wux-popup{position:fixed;left:0;bottom:0;width:100%;max-width:100%}.wux-popup-position.wux-popup-position--left .wux-popup{position:fixed;left:0;top:0;width:80%;max-width:100%;height:100%;max-height:100%}.wux-popup-position.wux-popup-position--is-iphonex .wux-popup__content{padding-bottom:68rpx}.wux-popup__content{position:relative;background-color:#fff;border:0;background-clip:padding-box;height:100%;text-align:center;overflow:hidden}.wux-popup__title{font-weight:400;font-size:36rpx}.wux-popup__bd{min-height:80rpx;font-size:30rpx;line-height:1.3;word-wrap:break-word;word-break:break-all;color:#999}.wux-popup__ft{position:relative;line-height:96rpx;font-size:36rpx;display:-ms-flexbox;display:flex}.wux-popup__close{border:0;padding:6rpx;background-color:transparent;outline:0;position:absolute;top:12rpx;right:12rpx;height:42rpx;width:42rpx}.wux-popup__close-x{display:inline-block;width:30rpx;height:30rpx;background-repeat:no-repeat;background-size:cover;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg width='30' height='30' viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23888' fill-rule='evenodd'%3E%3Cpath d='M1.414 0l28.284 28.284-1.414 1.414L0 1.414z'/%3E%3Cpath d='M28.284 0L0 28.284l1.414 1.414L29.698 1.414z'/%3E%3C/g%3E%3C/svg%3E")} \ No newline at end of file diff --git a/miniprogram/images/code-cloud-callback-config.png b/miniprogram/images/code-cloud-callback-config.png new file mode 100644 index 0000000..25b0bfc Binary files /dev/null and b/miniprogram/images/code-cloud-callback-config.png differ diff --git a/miniprogram/images/code-db-inc-dec.png b/miniprogram/images/code-db-inc-dec.png new file mode 100644 index 0000000..d8770b1 Binary files /dev/null and b/miniprogram/images/code-db-inc-dec.png differ diff --git a/miniprogram/images/code-db-onAdd.png b/miniprogram/images/code-db-onAdd.png new file mode 100644 index 0000000..22c7afb Binary files /dev/null and b/miniprogram/images/code-db-onAdd.png differ diff --git a/miniprogram/images/code-db-onQuery.png b/miniprogram/images/code-db-onQuery.png new file mode 100644 index 0000000..218550d Binary files /dev/null and b/miniprogram/images/code-db-onQuery.png differ diff --git a/miniprogram/images/code-db-onRemove.png b/miniprogram/images/code-db-onRemove.png new file mode 100644 index 0000000..b4eff71 Binary files /dev/null and b/miniprogram/images/code-db-onRemove.png differ diff --git a/miniprogram/images/code-func-sum.png b/miniprogram/images/code-func-sum.png new file mode 100644 index 0000000..0414529 Binary files /dev/null and b/miniprogram/images/code-func-sum.png differ diff --git a/miniprogram/images/console-entrance.png b/miniprogram/images/console-entrance.png new file mode 100644 index 0000000..bbbb973 Binary files /dev/null and b/miniprogram/images/console-entrance.png differ diff --git a/miniprogram/images/create-collection.png b/miniprogram/images/create-collection.png new file mode 100644 index 0000000..e0fdb34 Binary files /dev/null and b/miniprogram/images/create-collection.png differ diff --git a/miniprogram/pages/admin_message/admin_message.js b/miniprogram/pages/admin_message/admin_message.js new file mode 100644 index 0000000..a729e95 --- /dev/null +++ b/miniprogram/pages/admin_message/admin_message.js @@ -0,0 +1,68 @@ + +import regeneratorRuntime from '../../utils/regenerator-runtime/runtime' +import BaseMixin from '../base/base' +import mergePages from '../../utils/objectUtils' +const moment = require('../../utils/moment.min.js') +import { CallCloudFuncAPI } from '../../utils/async_cloudfunc.js' +import { $wuxDialog } from '../../components/wux-weapp/index' + +const PageObject = mergePages({}, BaseMixin, { + data: { + total: 0 + }, + onInited(options) { + let push_token_total = wx.getStorageSync('push_token_total') + if(!push_token_total) { + this.setData({ + total: 0 + }) + } else { + this.setData({ + total: parseInt(push_token_total) + }) + } + }, + async submitForm(e) { + console.log(e) + this.showLoading() + let res = null + try { + res = await CallCloudFuncAPI( + "main", + { + apiName: "adminAPI.increasePushToken", + token: e.detail.formId + } + ) + } catch (e) { + console.error(e) + this.hideLoading() + this.showToast({ + title: e.message + }) + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + return + } + + this.hideLoading() + if (!res.result.status) { + this.showToast({ + title: res.result.message + }) + } else { + this.setData({ + total: res.result.data.total + }) + wx.setStorageSync('push_token_total', res.result.data.total) + this.showToast({ + icon: 'success', + title: 'ok' + }) + } + + } +}) + +Page(PageObject) \ No newline at end of file diff --git a/miniprogram/pages/admin_message/admin_message.json b/miniprogram/pages/admin_message/admin_message.json new file mode 100644 index 0000000..8835af0 --- /dev/null +++ b/miniprogram/pages/admin_message/admin_message.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} \ No newline at end of file diff --git a/miniprogram/pages/admin_message/admin_message.wxml b/miniprogram/pages/admin_message/admin_message.wxml new file mode 100644 index 0000000..16a263d --- /dev/null +++ b/miniprogram/pages/admin_message/admin_message.wxml @@ -0,0 +1,16 @@ + + + + 当前Token数量: {{total}} + + + + 请在每天检查token的数量,只有在token数量不为0的情况下才能保证管理员能收到新订单的通知。 + token不足时请点击下方按钮获取token。 + + +
+ +
+
+
\ No newline at end of file diff --git a/miniprogram/pages/admin_message/admin_message.wxss b/miniprogram/pages/admin_message/admin_message.wxss new file mode 100644 index 0000000..ef55271 --- /dev/null +++ b/miniprogram/pages/admin_message/admin_message.wxss @@ -0,0 +1,6 @@ +@import '../base/style.wxss'; + + +.help { + color: #999; font-size: 90%;text-align:center; +} \ No newline at end of file diff --git a/miniprogram/pages/all_orders/all_orders.js b/miniprogram/pages/all_orders/all_orders.js new file mode 100644 index 0000000..74334cc --- /dev/null +++ b/miniprogram/pages/all_orders/all_orders.js @@ -0,0 +1,67 @@ + +import regeneratorRuntime from '../../utils/regenerator-runtime/runtime' +import BaseMixin from '../base/base' +import PulldownMixin from '../base/pulldown_mixin' +import OrdersMixin from '../base/orders_mixin' +import mergePages from '../../utils/objectUtils' +const moment = require('../../utils/moment.min.js') +import { CallCloudFuncAPI } from '../../utils/async_cloudfunc.js' +import { $wuxDialog } from '../../components/wux-weapp/index' +import { $wuxCalendar } from '../../components/wux-weapp/index' +import { StatusLabel, DeliveryStatusLabel } from '../../utils/constant' + + +const PageObject = mergePages({}, BaseMixin, PulldownMixin, OrdersMixin, { + + data: { + targetDate: [], + target_date: '', + reqData: { + page: 1, + pagesize: 10, + start_at: null, + end_at: null + }, + entityIdField: '_id', + apiName: "adminAPI.getUserOrders", + isCloudFunc: true, + statuses: StatusLabel, + deliveryStatus: DeliveryStatusLabel, + itemFlags: { + pay: '-', + deposit: '+' + }, + user_id: null, + orderid: null, + }, + onInited(options) { + let start_at = moment().format('YYYY-MM-DD 00:00:00') + let end_at = moment().format('YYYY-MM-DD 23:59:59') + this.setData({ + 'reqData.start_at': start_at, + 'reqData.end_at': end_at, + 'target_date': moment().format('YYYY-MM-DD') + }) + wx.startPullDownRefresh() + }, + showCalendar() { + $wuxCalendar().open({ + value: this.data.targetDate, + onChange: (values, displayValues) => { + if (values && values.length === 0) { + return + } + console.log('onChange', values, displayValues) + this.setData({ + targetDate: displayValues, + target_date: displayValues[0], + 'reqData.start_at': `${displayValues[0]} 00:00:00`, + 'reqData.end_at': `${displayValues[0]} 23:59:59`, + }) + wx.startPullDownRefresh() + }, + }) + } +}) + +Page(PageObject) \ No newline at end of file diff --git a/miniprogram/pages/all_orders/all_orders.json b/miniprogram/pages/all_orders/all_orders.json new file mode 100644 index 0000000..823f65f --- /dev/null +++ b/miniprogram/pages/all_orders/all_orders.json @@ -0,0 +1,7 @@ +{ + "enablePullDownRefresh": true, + "usingComponents": { + "wux-calendar": "../../components/wux-weapp/calendar/index", + "wux-dialog": "../../components/wux-weapp/dialog/index" + } +} \ No newline at end of file diff --git a/miniprogram/pages/all_orders/all_orders.wxml b/miniprogram/pages/all_orders/all_orders.wxml new file mode 100644 index 0000000..c34a743 --- /dev/null +++ b/miniprogram/pages/all_orders/all_orders.wxml @@ -0,0 +1,50 @@ + + + + + {{target_date}} + + 选择日期 + + + + + 设置 + + + + + + {{item.title}} + {{item.orderNo}} + {{statuses[item.status].name}} {{deliveryStatus[item.delivery_status] ? deliveryStatus[item.delivery_status].name:''}} + {{item.create_at}} + + + + {{entity.name}} + {{entity.price}} x {{entity.count}} + + + + + 收货地址: + {{item.addressInfo.provinceName}} {{item.addressInfo.cityName}} {{item.addressInfo.countyName}} {{item.addressInfo.detailInfo}} + 电话:{{item.addressInfo.telNumber}} + 邮编:{{item.addressInfo.postalCode}} + + + + 快递公司:{{item.deliveryInfo.company_name||'本店御用快递小哥'}} + 订单编号:{{item.deliveryInfo.orderno}} + 送达时间:{{item.deliveryInfo.will_received_date}} {{item.deliveryInfo.will_received_time}} + + + 用户备注: {{item.remarks}} + 管理员备注: {{item.admin_remarks}} + + {{itemFlags[item.type]}} {{ item.orderInfo.total}} + {{itemFlags[item.type]}} {{ item.orderInfo.display_total}} {{ item.orderInfo.display_total !== item.orderInfo.total ? item.orderInfo.total : ''}} + + + \ No newline at end of file diff --git a/miniprogram/pages/all_orders/all_orders.wxss b/miniprogram/pages/all_orders/all_orders.wxss new file mode 100644 index 0000000..c71e76a --- /dev/null +++ b/miniprogram/pages/all_orders/all_orders.wxss @@ -0,0 +1,43 @@ +@import '../base/style.wxss'; +@import '../user_orders/user_orders.wxss'; + + +.datebar { + position: fixed; + left: 0; + top: 0; + width: 100%; + display: flex; + font-size: 12px; + padding-top: 10px; + box-sizing: border-box; + padding-bottom: 10px; + background-color: #f9f9f9; + border-bottom: 1px solid #ddd; +} + + +.datebar .date-label { + flex: 1; + padding-left: 10px; + height: 30px; + line-height:30px; +} + + + +.datebar .date-btn-wrapper { + width: 160px; +} + +.date-button { + width: 80px; + background-color: #E67774; + height: 30px; + color: #fff; + line-height: 30px; + border-radius: 10px; + text-align: center; + float: right; + margin-right: 10px; +} \ No newline at end of file diff --git a/miniprogram/pages/base/base.js b/miniprogram/pages/base/base.js new file mode 100644 index 0000000..e95499f --- /dev/null +++ b/miniprogram/pages/base/base.js @@ -0,0 +1,144 @@ +import regeneratorRuntime from '../../utils/regenerator-runtime/runtime' +import settings from '../../settings/index' +import moment from '../../utils/moment.min.js' +import message from './message' +import { $wuxDialog } from '../../components/wux-weapp/index' +const app = getApp() + +module.exports = { + data: { + pageName: null, + language: {}, + locale: null, + systemInfo: null, + settings: settings + }, + checkSession() { + let sessionid = wx.getStorageSync('sessionid') + if (!sessionid) { + let current_url = this.getCurrentPath() + if (!current_url.includes('home/home')) { + wx.reLaunch({ + url: `${settings.HomePage}?nextpage=${encodeURIComponent(current_url)}`, + }) + } else { + wx.reLaunch({ + url: settings.HomePage, + }) + } + } + }, + showToast(options) { + console.log('options:', options) + let title = message[options.title] + console.log('message:', message) + console.log(title) + if(!title) { + title = '系统内部错误' + } + let myOptions = { + icon: 'none', + duration: settings.shortTipDuration, + ...options + } + myOptions.title = title + console.log(myOptions) + wx.showToast(myOptions) + }, + hideToast() { + wx.hideToast() + }, + showDialog(newConfig, isConfirm = false) { + let config = Object.assign({}, + { + resetOnClose: true, + title: '', + content: '' + }, + newConfig + ) + if (isConfirm) { + $wuxDialog().confirm(config) + } else { + $wuxDialog().alert(config) + } + }, + onReachBottom: function () { + wx.stopPullDownRefresh(); + }, + + showLoading(message) { + wx.showLoading({ + title: message || '加载中...', + }) + }, + hideLoading() { + wx.hideLoading() + }, + onLoad: function (options) { + this.setData({ + systemInfo: app.globalData.systemInfo + }) + console.log('systemInfo:', this.data.systemInfo) + if (options.invite_code) { + wx.setStorage({ + key: 'invite_code', + data: options.invite_code, + }) + } + + if (this.onInited) { + this.onInited(options) + } + }, + getCurrentPath: function () { + let pages = getCurrentPages(); + let currPage = null; + if (pages.length) { + currPage = pages[pages.length - 1]; + } + if (currPage.options) { + let queryStr = this.joinUrlKey(currPage.options); + return `/${currPage.route}?${queryStr}` + } else { + return `/${currPage.route}` + } + }, + joinUrlKey: function (keys) { + return Object.keys(keys).map(function (k) { + return encodeURIComponent(k) + "=" + encodeURIComponent(keys[k]); + }).join('&') + }, + isTab: function (url) { + let flag = false; + for (let item of settings.TAB_URLS) { + if (url.includes(item)) { + return true + } + } + return flag + }, + goToURL: function (url) { + if (this.isTab(url)) { + wx.switchTab({ + url: url + }) + } else { + wx.redirectTo({ + url: url + }) + } + }, + formatEventDate(s1, e1) { + let startDate = moment(s1) + let endDate = moment(e1) + if (startDate.format('YYYY-MM-DD') == endDate.format('YYYY-MM-DD')) { + return `${startDate.format('YYYY-MM-DD HH:mm')}-${endDate.format('HH:mm')}` + } else { + return `${startDate.format('YYYY-MM-DD HH:mm')}-${endDate.format('YYYY-MM-DD HH:mm')}` + } + }, + onShareAppMessage: function () { + + } +} \ No newline at end of file diff --git a/miniprogram/pages/base/buycart.js b/miniprogram/pages/base/buycart.js new file mode 100644 index 0000000..89ca055 --- /dev/null +++ b/miniprogram/pages/base/buycart.js @@ -0,0 +1,121 @@ +import regeneratorRuntime from '../../utils/regenerator-runtime/runtime' +import moment from '../../utils/moment.min.js' + + +module.exports = { + onShow() { + this.loadBuycart() + }, + loadBuycart() { + let buycart = wx.getStorageSync('buycart') + if (buycart) { + this.setData({ + buycart: buycart + }) + } else { + this.setData({ + buycart: { + total: 0, + display_total: 0, + count: 0, + entities: [] + } + }) + } + }, + addGoodsToCart(item) { + console.log('item:', item) + let flag = false + for (let entity of this.data.buycart.entities) { + if (entity.id == item._id) { + entity.count += 1 + entity.total = entity.count * parseFloat(entity.price) + entity.display_total = entity.count * parseFloat(entity.display_price) + flag = true + } + } + console.log('flag:', flag) + if (flag === false) { + this.data.buycart.entities.push({ + id: item._id, + name: item.name, + name_en: item.name_en, + count: 1, + price: item.price, + display_price: item.display_price, + cover: item.cover, + total: item.price, + display_total: item.display_price + }) + } + this.setData({ + 'buycart.entities': this.data.buycart.entities + }) + let total = 0; + let count = 0; + let display_total = 0; + for (let entity of this.data.buycart.entities) { + total += parseFloat(entity.total) + display_total += parseFloat(entity.display_total) + count += entity.count + } + this.setData({ + 'buycart.total': total, + 'buycart.display_total': display_total, + 'buycart.count': count + }) + wx.setStorageSync('buycart', this.data.buycart) + }, + updateGoodsCount(id, count) { + for (let item of this.data.buycart.entities) { + if (id === item.id) { + let itemTotal = parseFloat(item.total) + let itemDisplayTotal = parseFloat(item.display_total) + let itemCount = item.count + let countVal = count - itemCount + let totalVal = countVal * parseFloat(item.price) + let displayTotalVal = countVal * parseFloat(item.display_price) + let currentTotal = itemTotal + totalVal + let currentDisplayTotal = itemDisplayTotal + displayTotalVal + item.count = count + item.total = currentTotal + item.display_total = currentDisplayTotal + } + } + let totalAll = 0; + let displayTotalAll = 0; + let countAll = 0; + for (let item of this.data.buycart.entities) { + totalAll += parseFloat(item.total) + displayTotalAll += parseFloat(item.display_total) + countAll += item.count + } + this.data.buycart.total = totalAll + this.data.buycart.display_total = displayTotalAll + this.data.buycart.count = countAll + + let entities = [] + for (let item of this.data.buycart.entities) { + if (item.count !== 0) { + entities.push(item) + } + } + this.data.buycart.entities = entities + + this.setData({ + buycart: this.data.buycart + }) + wx.setStorageSync('buycart', this.data.buycart) + }, + _clearBuyCart() { + this.setData({ + buycart: { + total: 0, + display_total: 0, + count: 0, + entities: [] + } + }) + wx.setStorageSync('buycart', this.data.buycart) + } +} \ No newline at end of file diff --git a/miniprogram/pages/base/message.js b/miniprogram/pages/base/message.js new file mode 100644 index 0000000..62a6ee9 --- /dev/null +++ b/miniprogram/pages/base/message.js @@ -0,0 +1,17 @@ +const message = { + ok: "成功", + address_not_found: "地址不存在", + update_address_error: "更新地址时发生错误", + setdefault_address_error: "设置默认地址时发生错误", + user_not_found: "用户不存在", + fail_create_user: "创建用户时发生错误", + get_orders_error: "获取订单时发生错误", + fail_update_user: "更新用户时发生错误", + update_birthday_error: "更新生日时发生错误", + update_gender_error: "更新性别时发生错误", + update_name_error: "更新名字时发生错误", + update_address_error: "更新地址是发生错误", + user_balance_error: "付款失败,余额不足" +} + +export default message \ No newline at end of file diff --git a/miniprogram/pages/base/orders_mixin.js b/miniprogram/pages/base/orders_mixin.js new file mode 100644 index 0000000..f04ab4a --- /dev/null +++ b/miniprogram/pages/base/orders_mixin.js @@ -0,0 +1,140 @@ + +import regeneratorRuntime from '../../utils/regenerator-runtime/runtime' +import BaseMixin from '../base/base' +import PulldownMixin from '../base/pulldown_mixin' +import mergePages from '../../utils/objectUtils' +const moment = require('../../utils/moment.min.js') +import { CallCloudFuncAPI } from '../../utils/async_cloudfunc.js' +import { $wuxDialog } from '../../components/wux-weapp/index' +import { StatusLabel, DeliveryStatusLabel } from '../../utils/constant' + + +export default { + + data: { + reqData: { + page: 1, + pagesize: 10, + user_id: null + }, + entityIdField: '_id', + apiName: "adminAPI.getUserOrders", + isCloudFunc: true, + statuses: StatusLabel, + deliveryStatus: DeliveryStatusLabel, + itemFlags: { + pay: '-', + deposit: '+' + }, + user_id: null, + orderid: null, + admin: null + }, + onShow() { + let admin = wx.getStorageSync('admin') + if(admin && admin.id) { + this.setData({ + admin: admin + }) + } else { + this.setData({ + admin: null + }) + } + }, + onInited(options) { + if (!options.user_id) { + return + } + this.setData({ + 'reqData.user_id': options.user_id + }) + console.log('user_id:', this.data.user_id) + wx.startPullDownRefresh() + }, + getEntitiesApiUrl() { + return "main" + }, + formatEntities(data) { + console.log(data) + for (let entity of data.entities) { + entity.create_at = moment(entity.create_at).format('YYYY/MM/DD HH:mm') + if (entity.type == 'deposit') { + entity.title = '购买充值卡' + } else if (entity.type == 'pay') { + entity.title = this.getGoodsName(entity.orderInfo) + } + } + return data + }, + getGoodsName(orderInfo) { + let goodsName = ''; + orderInfo.entities.map((item, index) => { + if (index === 0) { + goodsName += item.name + } else if (index > 0 && index < 3) { + goodsName += '、' + item.name + } else if (index == 3) { + if (orderInfo.entities.length > 3) { + goodsName += '等' + } + } + }) + return goodsName + }, + onControlOrder(e) { + console.log(e) + this.setData({ + orderid: e.currentTarget.dataset.orderid + }) + let that = this; + wx.showActionSheet({ + itemList: ['设置订单地址', '设置订单状态', '设置发货状态', '调整订单金额', '设置订单备注', '取消订单'], + success(res) { + console.log(res.tapIndex) + if (res.tapIndex === 0) { + wx.navigateTo({ + url: `/pages/update_address/update_address?orderid=${that.data.orderid}`, + }) + } + + if (res.tapIndex === 1) { + wx.navigateTo({ + url: `/pages/update_order/update_order?orderid=${that.data.orderid}`, + }) + } + + if (res.tapIndex === 2) { + wx.navigateTo({ + url: `/pages/update_delivery/update_delivery?orderid=${that.data.orderid}`, + }) + } + + if (res.tapIndex === 3) { + wx.navigateTo({ + url: `/pages/update_total/update_total?orderid=${that.data.orderid}`, + }) + } + + if (res.tapIndex === 4) { + wx.navigateTo({ + url: `/pages/update_remarks/update_remarks?orderid=${that.data.orderid}`, + }) + } + + if (res.tapIndex === 5) { + wx.navigateTo({ + url: `/pages/cancel_order/cancel_order?orderid=${that.data.orderid}`, + }) + } + + + + }, + fail(res) { + console.log(res.errMsg) + } + }) + } + +} \ No newline at end of file diff --git a/miniprogram/pages/base/pulldown_mixin.js b/miniprogram/pages/base/pulldown_mixin.js new file mode 100644 index 0000000..ceff946 --- /dev/null +++ b/miniprogram/pages/base/pulldown_mixin.js @@ -0,0 +1,164 @@ +import regeneratorRuntime from '../../utils/regenerator-runtime/runtime' +import { ApiRequest } from '../../utils/async_api' +import { CallCloudFuncAPI } from '../../utils/async_cloudfunc' +export default { + data: { + entities: [], + entityIdField: 'id', + lastId: null, + reqData: { + page: 1, + pagesize: 10 + } + }, + getEntities: async function () { + this.showLoading() + try { + await this._getEntitiesAPI() + } catch (e) { + console.error(e) + } + this.hideLoading() + }, + updateOldEntities: function (newItem) { + for (let i = 0; i < this.data.entities.length; i++) { + if (this.data.entities[i][this.data.entityIdField] == newItem[this.data.entityIdField]) { + this.data.entities[i] = newItem + } + } + }, + refreshNewEntities: async function () { + this.showLoading() + try { + let newReqData = { ...this.data.reqData } + newReqData.page = 1 + let result = await this.callEntitiesAPI(newReqData) + if (!this.data.isCloudFunc && !result.code) { + this.showToast({title: result.message}) + return + } else if (this.data.isCloudFunc && result.result.status === false) { + this.showToast({title: result.result.message}) + return + } + + if (this.data.isCloudFunc) { + result = result.result + } + + let entities = [] + let newEntities = [] + let oldEntities = this._getEntitiyIds() + + if (result.data && result.data.entities) { + if (this.formatEntities) { + let formatedData = await this.formatEntities(result.data) + entities = formatedData.entities + } else { + entities = result.data.entities + } + } + + for (let item of result.data.entities) { + if (!oldEntities.includes(item[this.data.entityIdField])) { + newEntities.push(item) + } else { + this.updateOldEntities(item) + } + } + + if (newEntities.length != 0) { + this.setData({ + entities: [...newEntities, ...this.data.entities] + }) + } else { + this.setData({ + entities: this.data.entities + }) + } + + if (this.data.lastId === null) { + this.setData({ + lastId: this.data.entities[this.data.entities.length - 1][this.data.entityIdField], + 'reqData.page': this.data.reqData.page + 1 + }) + } + } catch (e) { + console.error(e) + } + this.hideLoading() + }, + getEntitiesApiUrl: function () { + return null + }, + + callEntitiesAPI: async function (reqData) { + if(!this.data.isCloudFunc) { + return await ApiRequest(this.getEntitiesApiUrl(), reqData) + } else { + return await CallCloudFuncAPI(this.getEntitiesApiUrl(), { + apiName: this.data.apiName, + ...reqData + }) + } + }, + _getEntitiesAPI: async function () { + let result; + let reqData = this.data.reqData + result = await this.callEntitiesAPI(reqData) + if (!this.data.isCloudFunc && !result.code) { + this.showToast({title: result.message}) + return + } else if(this.data.isCloudFunc && result.result.status === false) { + this.showToast({ + message: result.result.message + }) + return + } + + if(this.data.isCloudFunc) { + result = result.result + } + + let entities = [] + if (result.data && result.data.entities) { + if (this.formatEntities) { + let formatedData = await this.formatEntities(result.data) + entities = formatedData.entities + } else { + entities = result.data.entities + } + } + + if (entities.length === 0) { + this.showToast({ + message: '没有更多数据了' + }) + return + } + + let all_entities = [] + let lastId = entities[entities.length - 1][this.data.entityIdField] + if (this.data.lastId != lastId) { + all_entities = [...this.data.entities, ...entities] + this.setData({ + entities: all_entities, + lastId: lastId, + 'reqData.page': this.data.reqData.page + 1 + }) + } + }, + _getEntitiyIds: function () { + let entityIds = [] + for (let entity of this.data.entities) { + entityIds.push(entity[this.data.entityIdField]) + } + return entityIds + }, + onReachBottom: async function () { + await this.getEntities() + }, + onPullDownRefresh: async function () { + await this.refreshNewEntities() + wx.stopPullDownRefresh() + }, +} \ No newline at end of file diff --git a/miniprogram/pages/base/style.wxss b/miniprogram/pages/base/style.wxss new file mode 100644 index 0000000..214a584 --- /dev/null +++ b/miniprogram/pages/base/style.wxss @@ -0,0 +1,157 @@ +@font-face { + font-family: 'iconfont'; + src: url('../../assets/icons/iconfont.eot'); + src: url('../../assets/icons/iconfont.eot?#iefix') format('embedded-opentype'), + url('../../assets/icons/iconfont.woff2') format('woff2'), + url('../../assets/icons/iconfont.woff') format('woff'), + url('../../assets/icons/iconfont.ttf') format('truetype'), + url('../../assets/icons/iconfont.svg#iconfont') format('svg'); +} +@import '../../assets/icons/iconfont.wxss'; + +/* page { + background-color: #e67774; +} */ + +.round-button { + padding-left: 30rpx; + padding-right: 30rpx; + height: 90rpx; + background-color: #d9262f; + border-radius: 45rpx; + display: flex; + justify-content: center; + align-items: center; + flex-direction: row; + box-sizing: border-box; + border-color: transparent transparent #80161b transparent; + box-shadow: rgba(0, 0, 0, 0.2) 5rpx 5rpx 10rpx 5rpx; + color: #fff; +} + +.round-button text { + color: #fff; +} + +.round-button.floated { + position: fixed; + bottom: 80rpx; + right: 40rpx; +} + +.ellipsis { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.panel-form { + width: 100%; + background-color: #f5f5f5; + border-top-left-radius: 20px; + border-top-right-radius: 20px; + padding-top: 10px; +} + +/* form */ + +.section { + font-size: 90%; + padding: 12px; + width: 100%; + box-sizing: border-box; +} + +.section__field { + border: 1px solid #ddd; + width: 100%; + min-height: 34px; + line-height: 24px; + padding: 5px; + box-sizing: border-box; + background-color: #fff; + font-size: 14px; + color: #333; + border-radius: 4px; +} + +.section__checkbox { + background-color: #f5f5f5; +} + +.section__auto_height { + min-height: 102px; +} + +.section__auto_height textarea { + min-height: 90px; + width: 100%; +} + +.section__note { + font-size: 80%; + color: #999; + margin-top: 3px; +} + +/* panel */ + +.panel-button { + position: relative; + width: 100%; + right: 0; + bottom: 0; + margin-bottom: 30px; +} + +/* triangle */ + +.triangle-bottomright { + width: 0; + height: 0; + border-bottom: 50px solid #fde2e2; + border-left: 50px solid transparent; + position: absolute; + bottom: 0; + right: 0; +} + +.italic-text { + position: absolute; + bottom: 10px; + right: 0; + color: #f56c6c; + font-size: 70%; + width: 40px; + text-align: center; + transform: rotate(-45deg); +} + +/* emptybox */ + +.empty-box { + width: 100px; + height: 100px; + top: 100px; + position: absolute; + left: 50%; + margin-left: -50px; +} + +.empty-icon { + display: flex; + justify-content: center; + align-items: center; +} + +.empty-icon image { + width: 48px; + height: 48px; +} + +.empty-txt { + text-align: center; + color: #999; + font-size: 90%; + margin-top: 20px; +} diff --git a/miniprogram/pages/buycart/buycart.js b/miniprogram/pages/buycart/buycart.js new file mode 100644 index 0000000..b6502fc --- /dev/null +++ b/miniprogram/pages/buycart/buycart.js @@ -0,0 +1,222 @@ +import regeneratorRuntime from '../../utils/regenerator-runtime/runtime' +import mergePages from '../../utils/objectUtils' +import BaseMixin from '../base/base' +import BuycartMixin from '../base/buycart' +import { $wuxDialog } from '../../components/wux-weapp/index' +import { getWxAddress } from '../../utils/async_tools/async_address' +import { CallCloudFuncAPI } from '../../utils/async_cloudfunc' + +const PageObject = mergePages({}, BaseMixin, BuycartMixin, { + + /** + * 页面的初始数据 + */ + data: { + buycart: null, + isAgree: false, + userInfo: null, + address: null + }, + onInited(options) { + this.getProfile() + }, + onShow() { + this.loadBuycart() + this.loadAgreeStatus() + this.loadDeliveryStatus() + }, + loadDeliveryStatus() { + let isDelivery = wx.getStorageSync('isDelivery') + if(isDelivery === true) { + this.setData({ + 'buycart.isDelivery': true + }) + } else { + this.setData({ + 'buycart.isDelivery': false + }) + wx.setStorageSync('isDelivery', false) + } + }, + loadAgreeStatus() { + let isAgree = wx.getStorageSync('isAgree') + if (isAgree === true) { + this.setData({ + isAgree: true + }) + } else { + this.setData({ + isAgree: false + }) + wx.setStorageSync('isAgree', false) + } + }, + counterUpdate(e) { + console.log(e) + if (e.detail.actionType == 'counterUpdate') { + this.updateGoodsCount(e.detail.optId, e.detail.counter) + } + }, + ontapAgree() { + this.setData({ + isAgree: !this.data.isAgree + }) + wx.setStorageSync('isAgree', this.data.isAgree) + }, + goCake() { + wx.navigateBack() + }, + ontapClearBuycart() { + $wuxDialog().confirm({ + resetOnClose: true, + title: '', + content: '请确定是否清空购物车', + onConfirm: (e, response) => { + this._clearBuyCart() + } + }) + }, + ontapSubmit() { + if (!this.data.isAgree) { + $wuxDialog().alert({ + resetOnClose: true, + content: '请点击同意用户协议后再提交订单', + }) + } else { + if (this.data.isDelivery && !this.data.address) { + this.showToast({ + title: '请选择收货地址' + }) + return + } + + + if(!this.data.buycart.entities || this.data.buycart.entities.length === 0) { + $wuxDialog().confirm({ + resetOnClose: true, + title: `您还没有选择商品`, + content: '返回商城', + onConfirm: (e, response) => { + wx.navigateBack() + } + }) + return + } + + $wuxDialog().confirm({ + resetOnClose: true, + title: `订单总金额${this.data.buycart.total}元`, + content: '确定是否提交订单', + onConfirm: (e, response) => { + this.submitOrder() + } + }) + } + }, + async submitOrder() { + console.log('submitOrder') + this.showLoading() + let res = null + try { + res = await CallCloudFuncAPI('main', { + apiName: 'payAPI.orderPay', + orderInfo: this.data.buycart + }) + } catch (e) { + console.error(e) + this.hideLoading() + this.showToast({ + title: e.message + }) + return + } + + this.hideLoading() + if (!res.result.status) { + this.showToast({ + title: res.result.message, + }) + return + } + + this._clearBuyCart() + this.submitPaySuccess() + }, + submitPaySuccess() { + $wuxDialog().alert({ + resetOnClose: true, + content: '支付成功', + onConfirm: (e, response) => { + wx.navigateTo({ + url: '/pages/orders/orders', + }) + } + }) + }, + async ontapAddress() { + let [err, result] = await getWxAddress() + console.log(err) + console.log(result) + if (err !== null) { + return + } + this.updateAddress(result) + + }, + async updateAddress(address) { + let result = null + try { + result = CallCloudFuncAPI("main", + { + apiName: "userAPI.updateAddress", + address: address + }) + } catch (e) { + console.error(e) + } + if (result === null) { + return + } + wx.setStorageSync('address', address) + this.setData({ + address: address + }) + }, + async getProfile() { + let that = this + let res = null + try { + res = await CallCloudFuncAPI( + "main", + { + apiName: "getProfile" + } + ) + } catch (e) { + console.error(e) + } + + + if (res) { + this.setData({ + userInfo: res.result.data.user, + address: res.result.data.user.address + }) + wx.setStorageSync('address', res.result.data.user.address) + } + }, + onSelectNotDelivery() { + this.setData({ + 'buycart.isDelivery': false + }) + wx.setStorageSync('isDelivery', false) + }, + onSelectDelivery() { + this.setData({ + 'buycart.isDelivery': true, + }) + wx.setStorageSync('isDelivery', true) + } +}) + +Page(PageObject) \ No newline at end of file diff --git a/miniprogram/pages/buycart/buycart.json b/miniprogram/pages/buycart/buycart.json new file mode 100644 index 0000000..6779fe6 --- /dev/null +++ b/miniprogram/pages/buycart/buycart.json @@ -0,0 +1,6 @@ +{ + "usingComponents": { + "counter": "../../components/counter/counter", + "wux-dialog": "../../components/wux-weapp/dialog/index" + } +} \ No newline at end of file diff --git a/miniprogram/pages/buycart/buycart.wxml b/miniprogram/pages/buycart/buycart.wxml new file mode 100644 index 0000000..b7d3d1b --- /dev/null +++ b/miniprogram/pages/buycart/buycart.wxml @@ -0,0 +1,107 @@ + + + + + + 购物车 + + ({{buycart.count}}) + + + + + 预计准备时间 + 40分钟 + + + + + + + + {{address.detailInfo}} + + {{address.userName}} + {{address.telNumber}} + + + + 请选择您的收货地址 + + + + + + + + + 新龙路1333弄108号211室 + + 上海市 + 闵行区七宝镇 + + + + + + + 到店自提 + 周边外送 + + + + + + + 我的订单 + 清空购物车 + + + + + + + + + + + {{item.name}} + ¥ {{item.price}} + + + + + + + + ¥ {{item.total}} + + + + + + + + + + + + + + 产品小计 + + ¥ {{buycart.total}} + + 我已阅读、理解并同意接受《服务条款》。请您特别注意,上述使用条款不仅适用于您的本次订单服务,还适用于以后通过本站使用的所有购物服务 + + + + + + + 提交 + + + 继续购物 + + \ No newline at end of file diff --git a/miniprogram/pages/buycart/buycart.wxss b/miniprogram/pages/buycart/buycart.wxss new file mode 100644 index 0000000..4fa9b8b --- /dev/null +++ b/miniprogram/pages/buycart/buycart.wxss @@ -0,0 +1,271 @@ +@import '../base/style.wxss'; + +.container { + /* background-color: #e67774; */ + position: relative; + padding-bottom: 100px +} + +.body { + padding: 5px; + box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.2); +} + +.header { + padding: 20px; + background-color: #e67774; + color: #fff; +} + +.buycart-title text { + display: inline-block; + font-size: 140%; +} + +.buycart-meta { + font-size: 90%; + color: #ccc; +} + +.item { + display: flex; + height: 90px; + padding: 10px; + box-sizing: border-box; + border-top: 1px solid #f5f5f5; +} + +.item:last-child { + border-bottom: 1px solid #f5f5f5; +} + +.goods-cover { + width: 90px; + height: 100%; +} + +.goods-info { + flex: 1; + height: 100%; +} + +.goods-cover image { + width: 60px; + height: 60px; + border-radius: 30px; + box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.2); +} + +.title { + display: flex; + font-weight: bold; +} + +.title .price { + width: 80px; + justify-content: center; + align-items: center; + text-align: right; + color: #333; + font-size: 90%; +} + +.title .name { + flex: 1; + color: #333; +} + +.info { + display: flex; + padding-top: 10px; +} + +.info .count { + flex: 1; +} + +.info .total { + width: 80px; +} + +.count-wrapper { + width: 120px; +} + +.foot-wrapper { + display: flex; + padding-right: 10px; +} + +.goods-agree { + width: 80px; + justify-content: center; + align-items: center; + display: flex; +} + +.goods-agree-info { + flex: 1; + padding-top: 10px; + padding-bottom: 10px; +} + +.agree-button { + width: 40px; + height: 40px; + border: 2px solid #ddd; + border-radius: 20px; + position: relative; + box-sizing: border-box; +} + +.agree-button-inner { + height: 30px; + width: 30px; + border-radius: 15px; + background-color: #fff; + position: absolute; + top: 3px; + left: 3px; + border: 2px solid #ddd; + box-sizing: border-box; +} + +.agree-button-inner.agreed { + background-color: #333; +} + +.goods-note { + font-size: 80%; + color: #666; +} + +.goods-total { + display: flex; + padding-bottom: 5px; +} + +.total-label { + font-size: 80%; +} + +.total-line { + flex: 1; + border-bottom: 1px dotted #ddd; +} + +.total-amount { + font-size: 80%; +} + +.submit-button { + height: 50px; + width: 120px; + line-height: 50px; + border-radius: 25px; + color: #fff; + font-weight: bold; + text-align: center; + background-color: #ddd; + position: fixed; + right: 20px; + bottom: 30px; + box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.2); +} + +.submit-button.agreed { + background-color: #fa8282; +} + +.return-buy { + height: 30px; + width: 120px; + line-height: 30px; + border-radius: 15px; + color: #333; + font-weight: bold; + text-align: center; + background-color: #f5f5f5; + position: fixed; + right: 150px; + bottom: 40px; + box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.2); +} + +.body-header { + padding-bottom: 5px; +} + +.body-header-wrapper { + height: 30px; + line-height: 30px; + display: flex; + padding-left: 10px; + padding-right: 10px; + box-sizing: border-box; + font-size: 80%; + color: #666; +} + +.body-header-wrapper label { + width: 80px; +} + +.body-header-wrapper .clear { + flex: 1; + text-align: right; +} + +.address { + position: relative; + padding: 10px; + box-sizing: border-box; +} + +.address-wrapper { + margin-right: 60px; +} + +.address .icon-gengduo { + position: absolute; + top: 30px; + right: 20px; +} + +.address .address-detail { + color: #333; + font-size: 110%; +} + +.address .address-name { + color: #666; + font-size: 90%; + margin-top: 5px; +} + + +.delivery-method { + padding-left: 10px; + padding-bottom: 10px; + padding-right: 10px; + text-align: right; +} + +.delivery-method .method-name { + display: inline-block; + font-size: 80%; + padding-left: 8px; + padding-right: 8px; + background-color: #ddd; + margin-right: 5px; + color: #fff; + border-radius: 15px; + height: 30px; + line-height: 30px; + box-sizing: border-box; +} + +.delivery-method .method-name.selected { + color: #fff; + background-color: #e67774; +} diff --git a/miniprogram/pages/cancel_order/cancel_order.js b/miniprogram/pages/cancel_order/cancel_order.js new file mode 100644 index 0000000..fe4a2b8 --- /dev/null +++ b/miniprogram/pages/cancel_order/cancel_order.js @@ -0,0 +1,106 @@ + +import regeneratorRuntime from '../../utils/regenerator-runtime/runtime' +import BaseMixin from '../base/base' +import mergePages from '../../utils/objectUtils' +const moment = require('../../utils/moment.min.js') +import { CallCloudFuncAPI } from '../../utils/async_cloudfunc.js' +import { $wuxDialog } from '../../components/wux-weapp/index' + +const PageObject = mergePages({}, BaseMixin, { + data: { + refund_amount: 0 + }, + onInited(options) { + + this.setData({ + orderid: options.orderid + }) + this.getOrderDetail() + }, + async getOrderDetail() { + this.showLoading() + let res = null + try { + res = await CallCloudFuncAPI( + "main", + { + apiName: "adminAPI.getUserOrders", + orderid: this.data.orderid + } + ) + } catch (e) { + console.error(e) + this.hideLoading() + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + return + } + + + this.hideLoading() + if (!res.result.status) { + this.showToast({ + title: res.result.message + }) + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + return + } + }, + + + async submitForm() { + this.showLoading() + let res = null + try { + res = await CallCloudFuncAPI( + "main", + { + apiName: "adminAPI.cancelOrder", + refund_amount: this.data.refund_amount, + orderId: this.data.orderid + } + ) + } catch (e) { + console.error(e) + this.hideLoading() + this.showToast({ + title: e.message + }) + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + return + } + + this.hideLoading() + if (!res.result.status) { + this.showToast({ + title: res.result.message + }) + } else { + this.showToast({ + icon: 'success', + title: 'ok' + }) + } + + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + }, + bindInputChange(e) { + try { + this.setData({ + refund_amount: parseInt(e.detail.value) + }) + } catch (e) { + console.error(e) + } + + } +}) + +Page(PageObject) \ No newline at end of file diff --git a/miniprogram/pages/cancel_order/cancel_order.json b/miniprogram/pages/cancel_order/cancel_order.json new file mode 100644 index 0000000..d66e201 --- /dev/null +++ b/miniprogram/pages/cancel_order/cancel_order.json @@ -0,0 +1,5 @@ +{ + "usingComponents": { + "wux-dialog": "../../components/wux-weapp/dialog/index" + } +} \ No newline at end of file diff --git a/miniprogram/pages/cancel_order/cancel_order.wxml b/miniprogram/pages/cancel_order/cancel_order.wxml new file mode 100644 index 0000000..e3e9fc2 --- /dev/null +++ b/miniprogram/pages/cancel_order/cancel_order.wxml @@ -0,0 +1,11 @@ + + + * 退款金额 + + + + + + 取消订单 + + \ No newline at end of file diff --git a/miniprogram/pages/cancel_order/cancel_order.wxss b/miniprogram/pages/cancel_order/cancel_order.wxss new file mode 100644 index 0000000..d18ce62 --- /dev/null +++ b/miniprogram/pages/cancel_order/cancel_order.wxss @@ -0,0 +1 @@ +@import '../base/style.wxss'; \ No newline at end of file diff --git a/miniprogram/pages/goods/goods.js b/miniprogram/pages/goods/goods.js new file mode 100644 index 0000000..9da3df4 --- /dev/null +++ b/miniprogram/pages/goods/goods.js @@ -0,0 +1,71 @@ + +import regeneratorRuntime from '../../utils/regenerator-runtime/runtime' +import mergePages from '../../utils/objectUtils' +import BaseMixin from '../base/base' +import BuycartMixin from '../base/buycart' +import { CallCloudFuncAPI } from '../../utils/async_cloudfunc' + +const PageObject = mergePages({}, BaseMixin, BuycartMixin, { + + data: { + entities: [], + colors: { + one: '#ffc0d0', + two: '#ffe0e0', + three: '#ffedff' + }, + buycart: null + }, + + onInited: function (options) { + wx.startPullDownRefresh() + }, + onPullDownRefresh: async function () { + await this.getGoods() + wx.stopPullDownRefresh() + }, + async getGoods () { + this.showLoading() + let result = null + try { + result = await CallCloudFuncAPI('main', { + apiName: 'goodsAPI.getGoods' + }) + } catch(e) { + console.error(e) + this.showToast({ + title: e.message + }) + this.hideLoading() + return + } + + if (result.result.status !== true) { + this.showToast({ + title: result.result.message + }) + this.hideLoading() + return + } + + this.setData({ + entities: result.result.data.entities + }) + this.hideLoading() + }, + ontapCard(e) { + console.log('ontapCard') + }, + onCatchTap(e) { + let index = e.currentTarget.dataset.index + this.addGoodsToCart(this.data.entities[index]) + }, + ontapBuycart() { + wx.navigateTo({ + url: '/pages/buycart/buycart' + }) + } +}) + + +Page(PageObject) \ No newline at end of file diff --git a/miniprogram/pages/goods/goods.json b/miniprogram/pages/goods/goods.json new file mode 100644 index 0000000..4047677 --- /dev/null +++ b/miniprogram/pages/goods/goods.json @@ -0,0 +1,6 @@ +{ + "enablePullDownRefresh": true, + "usingComponents": { + "wux-dialog": "../../components/wux-weapp/dialog/index" + } +} \ No newline at end of file diff --git a/miniprogram/pages/goods/goods.wxml b/miniprogram/pages/goods/goods.wxml new file mode 100644 index 0000000..9825c14 --- /dev/null +++ b/miniprogram/pages/goods/goods.wxml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + {{item.name}} + + ¥{{item.display_price}} + 购买 + + + + + + + ¥{{buycart.display_total}} + {{buycart.count}}件商品 + + + + + + \ No newline at end of file diff --git a/miniprogram/pages/goods/goods.wxss b/miniprogram/pages/goods/goods.wxss new file mode 100644 index 0000000..6395960 --- /dev/null +++ b/miniprogram/pages/goods/goods.wxss @@ -0,0 +1,117 @@ +@import '../base/style.wxss'; + +.container { + /* background-color: #e67774; */ + position: relative; +} + +.goods-wrapper { + box-sizing: border-box; + padding: 12px; +} + +.goods .goods-item { + background-color: #f9f9f9; + box-sizing: border-box; + font-size: 12px; + border-radius: 20px; + text-align: center; + box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.2); + overflow: hidden; + position: relative; + height: 220px; +} + +.goods-item .goods-image image { + width: 100%; + height: 220px; +} + +.goods-item .goods-meta { + position: absolute; + left: 0; + bottom: 0; + width: 100%; + height: 50px; + background-color: rgba(255, 255, 255, 0.7); + line-height: 50px; + display: flex; +} + +.goods-label { + font-size: 160%; + color: #333; + /* font-weight: bold; */ + flex: 1; + text-align: left; + padding-left: 20px; +} + +.goods-button { + height: 30px; + line-height: 30px; + border-radius: 15px; + background-color: #fa8282; + margin-top: 10px; + margin-right: 5px; +} + +.goods-button .goods-price { + padding-left: 10px; + padding-right: 5px; + font-size: 120%; +} + +.goods-button .goods-buycart { + padding-right: 10px; +} + +.header { + padding: 10px; + /* border-bottom: 1px solid #f9f9f9; */ +} + +.buycart { + position: fixed; + bottom: 20px; + left: 20px; + width: 60px; + height: 60px; + display: flex; + justify-content: center; + align-items: center; + color: #fa8282; + border-radius: 30px; + box-sizing: border-box; + background-color: #fae3d9; + border: 3px solid #fff; + z-index: 20; +} + +.buycart text { + font-size: 30px; +} + +.display-total { + position: fixed; + bottom: 20px; + left: 50px; + height: 60px; + width: 120px; + border-top-right-radius: 30px; + border-bottom-right-radius: 30px; + padding-left: 15px; + box-sizing: border-box; + z-index: 10; + background-color: #f9f9f9; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.2); +} + +.display-total text { + display: block; + font-size: 13px; +} diff --git a/miniprogram/pages/home/home.js b/miniprogram/pages/home/home.js new file mode 100644 index 0000000..1a69707 --- /dev/null +++ b/miniprogram/pages/home/home.js @@ -0,0 +1,173 @@ + +import regeneratorRuntime from '../../utils/regenerator-runtime/runtime' +import mergePages from '../../utils/objectUtils' +import BaseMixin from '../base/base' +import { $wuxDialog } from '../../components/wux-weapp/index' +import { CallCloudFuncAPI } from '../../utils/async_cloudfunc.js' +import { asyncPayment } from '../../utils/async_tools/async_payment.js' + + +const PageObject = mergePages({}, BaseMixin, { + + data: { + entities: [], + images: [], + targetImage: null, + cardId: null, + colors: { + one: '#ffc0d0', + two: '#ffe0e0', + three: '#ffedff' + } + }, + + onInited: function (options) { + wx.startPullDownRefresh() + }, + onPullDownRefresh: async function () { + await this.getCards() + wx.stopPullDownRefresh() + }, + async getCards() { + this.showLoading() + let res = null + try { + res = await CallCloudFuncAPI('main', { + apiName: 'getCards' + }) + } catch (e) { + console.error(e) + this.showToast({ + title: e.message + }) + this.hideLoading() + wx.stopPullDownRefresh() + return + } + this.hideLoading() + console.log(res) + if (!res.result.status) { + this.showToast({ + title: res.result.message + }) + } else { + this.setData({ + entities: res.result.data.entities, + images: res.result.data.images, + + }) + if(this.data.images && this.data.images.length !== 0 ) { + this.setData({ + targetImage: this.data.images[0].url + }) + console.log(this.data.targetImage) + } + } + wx.stopPullDownRefresh() + }, + ontapCard(e) { + let that = this + let card = e.currentTarget.dataset.card + $wuxDialog().confirm({ + resetOnClose: true, + title: `您正在购买充值卡,支付${card.value}元实际得到${card.real_value}元`, + content: '确定是否提交订单', + onConfirm: (e, response) => { + that.setData({ + cardId: card._id + }) + if (that.data.cardId) { + that.submitDepositOrder() + } + } + }) + }, + submitDepositOrder() { + let that = this + console.log('card:', that.data.cardId) + wx.cloud.callFunction({ + name: 'main', + data: { + apiName: 'depositAPI.deposit', + cardId: that.data.cardId + }, + success: res => { + console.log(res) + if (!res.result.status) { + this.showToast({ + title: res.result.message + }) + return + } else { + this.startPayment(res.result.data.orderNo, res.result.data.payData) + } + + }, + fail: err => { + console.error('[云函数] [login] 调用失败', err) + } + }) + }, + async startPayment(orderNo, payargs) { + let result = null + try { + result = await asyncPayment(payargs) + } catch(e) { + console.error(e) + if (e && e.errMsg == 'requestPayment:fail cancel') { + return + } else { + this.showToast({ + title: e + }) + } + } + console.log(result) + if (result && result.errMsg && result.errMsg == 'requestPayment:ok') { + // TODO: 查询支付结果 + this.depositSuccess(orderNo) + } + + + }, + async depositSuccess(orderNo) { + this.showLoading() + let result = null + try { + result = await CallCloudFuncAPI('main', { + apiName: 'depositAPI.depositSuccess', + orderNo: orderNo + }) + } catch (e) { + console.error(e) + this.showToast({ + title: e.message + }) + this.hideLoading() + return + } + + + this.hideLoading() + if (result.result.status !== true) { + this.showToast({ + title: result.result.message + }) + return + } + + $wuxDialog().alert({ + resetOnClose: true, + content: '充值成功', + onConfirm: (e, response) => { + wx.navigateTo({ + url: '/pages/orders/orders', + }) + } + }) + + }, +}) + + +Page(PageObject) \ No newline at end of file diff --git a/miniprogram/pages/home/home.json b/miniprogram/pages/home/home.json new file mode 100644 index 0000000..4047677 --- /dev/null +++ b/miniprogram/pages/home/home.json @@ -0,0 +1,6 @@ +{ + "enablePullDownRefresh": true, + "usingComponents": { + "wux-dialog": "../../components/wux-weapp/dialog/index" + } +} \ No newline at end of file diff --git a/miniprogram/pages/home/home.wxml b/miniprogram/pages/home/home.wxml new file mode 100644 index 0000000..d0c3f36 --- /dev/null +++ b/miniprogram/pages/home/home.wxml @@ -0,0 +1,22 @@ + + + + + + + + + 购买充值卡 + + + + + {{item.name}} + 买{{item.value}}元得{{item.real_value}}元 + + + + + \ No newline at end of file diff --git a/miniprogram/pages/home/home.wxss b/miniprogram/pages/home/home.wxss new file mode 100644 index 0000000..71305aa --- /dev/null +++ b/miniprogram/pages/home/home.wxss @@ -0,0 +1,83 @@ +@import '../base/style.wxss'; + +.cards { + padding: 20px; + box-sizing: border-box; +} +.card-note { + font-size: 120%; + color: #333; +} + +.card-label { + font-size: 120%; + color: #fff; + font-weight: bold; +} + +.header { + padding: 10px; + border-bottom: 1px solid #f9f9f9; +} + +.grid { + width: 100%; + display: grid; + grid-gap: 20px 20px; + grid-template-rows: repeat(6, 1fr); + grid-template-columns: repeat(6, 1fr); + grid-template-areas: "a a a a b b" "a a a a c c" "f f f f c c" "d d e e c c" "g g g g g g" "g g g g g g"; +} + +.grid .item, .card-free { + min-height: 60px; + border-radius: 20px; + box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.1); + display: flex; + justify-content: center; + align-items: center; + text-align: center; +} + +.grid .item-a { + grid-area: a; + background: skyblue; + flex-direction: column; +} + +.grid .item-b { + grid-area: b; + background: mediumaquamarine; +} + +.grid .item-c { + grid-area: c; + background: wheat; +} + +.grid .item-d { + grid-area: d; + background: lightcoral; +} + +.grid .item-e { + grid-area: e; + background: plum; +} + +.grid .item-f { + grid-area: f; + background: pink; +} + +.grid .item-g { + grid-area: g; + background-color: lavender; +} + + +.grid .item-a .card-note { + color: #fff; + font-size: 100%; +} + diff --git a/miniprogram/pages/index/index.js b/miniprogram/pages/index/index.js new file mode 100644 index 0000000..7165230 --- /dev/null +++ b/miniprogram/pages/index/index.js @@ -0,0 +1,132 @@ +import mergePages from '../../utils/objectUtils' +import BaseMixin from '../base/base' +const app = getApp() + + +const PageObject = mergePages({}, BaseMixin, { + data: { + avatarUrl: './user-unlogin.png', + userInfo: {}, + logged: false, + takeSession: false, + requestResult: '', + nextpage: null + }, + + onInited: function(options) { + // 获取用户信息 + this.showLoading() + wx.getSetting({ + success: res => { + if (res.authSetting['scope.userInfo']) { + // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框 + wx.getUserInfo({ + success: res => { + this.setData({ + avatarUrl: res.userInfo.avatarUrl, + userInfo: res.userInfo + }) + } + }) + } + }, + complete: () => { + this.hideLoading() + } + }) + }, + + onGetUserInfo: function(e) { + console.log(e) + let that = this + this.showLoading() + wx.cloud.callFunction({ + name: 'main', + data: { + apiName: 'loginAPI.login', + userinfo: e.detail.userInfo + }, + success: res => { + console.log('onlogin') + console.log(res) + if (res.result.status) { + app.globalData.openid = res.result.data.openid + if (res.result.data.registed) { + wx.setStorageSync('sessionid', res.result.data.openid) + } + + if (res.result.status) { + that.goToURL(res.result.data.nextpage) + } + } else if (res.result.status === false && res.result.message == 'user_not_found') { + wx.navigateTo({ + url: '/pages/regist/regist' + }) + } + + }, + fail: err => { + console.error('[云函数] [login] 调用失败', err) + }, + complete: () => { + console.log(this) + this.hideLoading() + } + }) + }, + + + // 上传图片 + doUpload: function() { + // 选择图片 + wx.chooseImage({ + count: 1, + sizeType: ['compressed'], + sourceType: ['album', 'camera'], + success: function(res) { + + wx.showLoading({ + title: '上传中', + }) + + const filePath = res.tempFilePaths[0] + + // 上传图片 + const cloudPath = 'my-image' + filePath.match(/\.[^.]+?$/)[0] + wx.cloud.uploadFile({ + cloudPath, + filePath, + success: res => { + console.log('[上传文件] 成功:', res) + + app.globalData.fileID = res.fileID + app.globalData.cloudPath = cloudPath + app.globalData.imagePath = filePath + + wx.navigateTo({ + url: '../storageConsole/storageConsole' + }) + }, + fail: e => { + console.error('[上传文件] 失败:', e) + wx.showToast({ + icon: 'none', + title: '上传失败', + }) + }, + complete: () => { + wx.hideLoading() + } + }) + + }, + fail: e => { + console.error(e) + } + }) + }, + +}) + + +Page(PageObject) \ No newline at end of file diff --git a/miniprogram/pages/index/index.json b/miniprogram/pages/index/index.json new file mode 100644 index 0000000..d66e201 --- /dev/null +++ b/miniprogram/pages/index/index.json @@ -0,0 +1,5 @@ +{ + "usingComponents": { + "wux-dialog": "../../components/wux-weapp/dialog/index" + } +} \ No newline at end of file diff --git a/miniprogram/pages/index/index.wxml b/miniprogram/pages/index/index.wxml new file mode 100644 index 0000000..cc2829c --- /dev/null +++ b/miniprogram/pages/index/index.wxml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/miniprogram/pages/index/index.wxss b/miniprogram/pages/index/index.wxss new file mode 100644 index 0000000..5476991 --- /dev/null +++ b/miniprogram/pages/index/index.wxss @@ -0,0 +1,148 @@ + + +page { + display: flex; + flex-direction: column; + justify-content: flex-start; + background-color: #e67774; +} + +.userinfo, .uploader, .tunnel { + margin-top: 40rpx; + height: 140rpx; + width: 100%; + background: #fff; + border: 1px solid rgba(0, 0, 0, 0.1); + border-left: none; + border-right: none; + display: flex; + flex-direction: row; + align-items: center; + transition: all 300ms ease; +} + +.userinfo-avatar { + width: 140rpx; + height: 140rpx; + border-radius: 50%; + background-size: cover; + background-color: white; + margin-top: 100px; + border: 3px solid #fff; + box-sizing: border-box; +} + +.userinfo-avatar:after { + border: none; +} + +.userinfo-nickname { + font-size: 32rpx; + color: white; + background-color: #7dd3da; + background-size: cover; + height: 40px; + line-height: 40px; + width: 120px; + border-radius: 20px; + position: absolute; + bottom: 100px; + left: 50%; + margin-left: -60px; + box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.3); +} + +.userinfo-nickname::after { + border: none; +} + +.uploader, .tunnel { + height: auto; + padding: 0 0 0 40rpx; + flex-direction: column; + align-items: flex-start; + box-sizing: border-box; +} + +.uploader-text, .tunnel-text { + width: 100%; + line-height: 52px; + font-size: 34rpx; + color: #7dd3da; +} + +.uploader-container { + width: 100%; + height: 400rpx; + padding: 20rpx 20rpx 20rpx 0; + display: flex; + align-content: center; + justify-content: center; + box-sizing: border-box; + border-top: 1px solid rgba(0, 0, 0, 0.1); +} + +.uploader-image { + width: 100%; + height: 360rpx; +} + +.tunnel { + padding: 0 0 0 40rpx; +} + +.tunnel-text { + position: relative; + color: #222; + display: flex; + flex-direction: row; + align-content: center; + justify-content: space-between; + box-sizing: border-box; + border-top: 1px solid rgba(0, 0, 0, 0.1); +} + +.tunnel-text:first-child { + border-top: none; +} + +.tunnel-switch { + position: absolute; + right: 20rpx; + top: -2rpx; +} + +.disable { + color: #888; +} + +.service { + position: fixed; + right: 40rpx; + bottom: 40rpx; + width: 140rpx; + height: 140rpx; + border-radius: 50%; + background: linear-gradient(#007aff, #0063ce); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.3); + display: flex; + align-content: center; + justify-content: center; + transition: all 300ms ease; +} + +.service-button { + position: absolute; + top: 40rpx; +} + +.service:active { + box-shadow: none; +} + +.request-text { + padding: 20rpx 0; + font-size: 24rpx; + line-height: 36rpx; + word-break: break-all; +} diff --git a/miniprogram/pages/index/user-unlogin.png b/miniprogram/pages/index/user-unlogin.png new file mode 100644 index 0000000..95b27e4 Binary files /dev/null and b/miniprogram/pages/index/user-unlogin.png differ diff --git a/miniprogram/pages/me/me.js b/miniprogram/pages/me/me.js new file mode 100644 index 0000000..9dcd73a --- /dev/null +++ b/miniprogram/pages/me/me.js @@ -0,0 +1,228 @@ + +import regeneratorRuntime from '../../utils/regenerator-runtime/runtime' +import BaseMixin from '../base/base' +import mergePages from '../../utils/objectUtils' +const moment = require('../../utils/moment.min.js') +import { CallCloudFuncAPI } from '../../utils/async_cloudfunc.js' +import { $wuxDialog } from '../../components/wux-weapp/index' + + +const PageObject = mergePages({}, BaseMixin, { + data: { + sessionid: '', + action: '', + imagePath: null, + userInfo: null, + admin: null, + myList: [ + { + key: 'userinfo', + isLink: true, + title: '个人资料', + value: '', + color: '#666', + iconColor: '#F56C6C', + titleColor: '#999', + // icon: 'ios-contact', + url: "/pages/profile/profile" + }, + { + key: 'balance', + isLink: true, + title: '查询余额', + value: '', + color: '#666', + iconColor: '#F56C6C', + titleColor: '#999', + // icon: 'ios-contact' + }, + { + key: 'orders', + isLink: true, + title: '我的订单', + value: '', + color: '#666', + iconColor: '#F56C6C', + titleColor: '#999', + // icon: 'ios-list-box', + url: "/pages/orders/orders" + }, + { + key: 'logout', + isLink: true, + title: '退出登录', + value: '', + color: '#666', + iconColor: '#F56C6C', + titleColor: '#999', + // icon: 'ios-log-out' + } + ], + staffList: [ + { + key: 'users', + isLink: true, + title: '客户', + value: '', + color: '#07C160', + iconColor: '#07C160', + titleColor: '#07C160', + // icon: 'ios-log-out' + url: "/pages/users/users" + }, + { + key: 'all_orders', + isLink: true, + title: '订单', + value: '', + color: '#07C160', + iconColor: '#07C160', + titleColor: '#07C160', + // icon: 'ios-log-out' + url: "/pages/all_orders/all_orders" + }, + { + key: 'admin_message', + isLink: true, + title: '消息推送', + value: '', + color: '#07C160', + iconColor: '#07C160', + titleColor: '#07C160', + // icon: 'ios-log-out' + url: "/pages/admin_message/admin_message" + } + ] + }, + onPullDownRefresh: function () { + this.getProfile() + }, + getHeaderCanvas: function () { + var ctx = wx.createCanvasContext('canvas') + // Draw quadratic curve + ctx.beginPath() + ctx.moveTo(0, 60) + ctx.bezierCurveTo(20, 100, 200, 80, this.data.systemInfo.windowWidth, -30) + ctx.lineTo(this.data.systemInfo.windowWidth, 0) + ctx.lineTo(0, 0) + ctx.lineTo(0, 60) + ctx.setFillStyle('#fde2e2') + ctx.fill() + + ctx.beginPath() + ctx.moveTo(0, 45) + ctx.bezierCurveTo(20, 100, 200, 90, this.data.systemInfo.windowWidth, -50) + ctx.lineTo(this.data.systemInfo.windowWidth, 0) + ctx.lineTo(0, 0) + ctx.lineTo(0, 45) + ctx.setFillStyle('#f56c6c') + ctx.fill() + + ctx.beginPath() + ctx.moveTo(0, 30) + ctx.bezierCurveTo(20, 60, 160, 130, this.data.systemInfo.windowWidth, -60) + ctx.lineTo(this.data.systemInfo.windowWidth, 0) + ctx.lineTo(0, 0) + ctx.lineTo(0, 30) + ctx.setFillStyle(this.data.settings.Theme.redColor) + ctx.fill() + + ctx.draw(false, () => { + this.canvasToTempImage(); + }) + }, + + canvasToTempImage: function () { + wx.canvasToTempFilePath({ + canvasId: "canvas", + success: (res) => { + let tempFilePath = res.tempFilePath; + this.setData({ + imagePath: tempFilePath, + }); + } + }, this); + }, + onInited: function (options) { + this.getHeaderCanvas() + wx.startPullDownRefresh() + }, + onTapListItem: async function (e) { + console.log('onTapListItem:', e) + let index = e.detail.index; + let item = this.data.myList[index] + if (item.key == 'logout') { + this.showDialog({ + title: '', + content: '确定是否退出登录', + onConfirm: (e) => { + this.logout() + }, + onCancel(e) { + + }, + }, true) + } else if (item.key == 'balance') { + await this.getProfile() + let balance = this.data.userInfo.balance ? this.data.userInfo.balance : 0 + $wuxDialog().alert({ + title: '您当前的余额为', + content: `${balance}元` + }) + } + + }, + onTapStaffListItem: async function (e) { + console.log('onTapListItem:', e) + let index = e.detail.index; + let item = this.data.staffList[index] + }, + onGotUserInfo: function (res) { + wx.login({ + success: res => { + // 发送 res.code 到后台换取 openId, sessionKey, unionId + console.log(res) + this.getRegistKey(res.code) + }, + fail: () => { + } + }) + + }, + logout: function (res) { + wx.clearStorageSync() + }, + async getProfile() { + this.showLoading() + let that = this + let res = null + try { + res = await CallCloudFuncAPI( + "main", + { + apiName: "getProfile" + } + ) + } catch (e) { + this.hideLoading() + console.error(e) + return + } + + + if (res) { + this.setData({ + userInfo: res.result.data.user + }) + + if(res.result.data.admin && res.result.data.admin.id) { + this.setData({admin: res.result.data.admin}) + wx.setStorageSync('admin', res.result.data.admin) + } + } + this.hideLoading() + wx.stopPullDownRefresh() + } +}) + +Page(PageObject) \ No newline at end of file diff --git a/miniprogram/pages/me/me.json b/miniprogram/pages/me/me.json new file mode 100644 index 0000000..f947073 --- /dev/null +++ b/miniprogram/pages/me/me.json @@ -0,0 +1,8 @@ +{ + "enablePullDownRefresh": true, + "usingComponents": { + "myList": "../../components/list/list", + "avatar": "../../components/avatar/avatar", + "wux-dialog": "../../components/wux-weapp/dialog/index" + } +} \ No newline at end of file diff --git a/miniprogram/pages/me/me.wxml b/miniprogram/pages/me/me.wxml new file mode 100644 index 0000000..88864d1 --- /dev/null +++ b/miniprogram/pages/me/me.wxml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + VIP会员 + + + + + + + \ No newline at end of file diff --git a/miniprogram/pages/me/me.wxss b/miniprogram/pages/me/me.wxss new file mode 100644 index 0000000..a5263aa --- /dev/null +++ b/miniprogram/pages/me/me.wxss @@ -0,0 +1,118 @@ +@import '../base/style.wxss'; + +page { + background-color: #fff; +} + +.container { + background-color: #fff; +} + +.header { + padding: 40rpx; + /* background-color: #d9262f; */ + position: relative; + height: 120rpx; + box-sizing: border-box; + /* border: solid 5px #000; */ + /* border-color: transparent transparent #000 transparent; + border-radius: 0 0 1000rpx 90%/120rpx; */ + width: 100%; + background-color: #E67774 +} + +.lucky-index-img { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 150px; + z-index: 1; +} + +.lucky-index-round { + position: fixed; + top: 9999rpx; + left: 0; + /* position: absolute; + left: 0; + top: 0; + width: 100%; */ +} + +.avatarWrap { + position: absolute; + left: 30px; + z-index: 2; +} + +.userinfo { + position: absolute; + font-size: 13px; + color: #880e4f; + background-color: #fef1e6; + text-align: center; + max-width: 100px; + height: 30px; + line-height: 30px; + border-radius: 4px; + box-shadow: rgba(0, 0, 0, 0.2) 2rpx 2rpx 4rpx 2rpx; + right: 30px; + top: 35px; + padding-left: 10px; + padding-right: 10px; + display: flex; + justify-content: center; + align-items: center; + z-index: 2; +} + +.username { + position: absolute; + font-size: 15px; + color: #333; + font-weight: bold; + top: 30px; + left: 100px; + max-width: 180px; + z-index: 2; +} + +.nickname open-data { + font-size: 36rpx; + color: #333; + font-weight: bold; +} +.nickname { + color: #fff; +} +.nickname { + display: flex; + justify-content: flex-start; + align-items: center; +} + +.nickname wux-icon { + margin-left: 24rpx; +} + +.body { + margin-top: 100rpx; +} + +.round-button { + position: relative !important; + width: 100%; + right: 0; + bottom: 0; +} + +.menuTitle { + margin-top: 30px; + text-align: center; + border-bottom: 1px solid #eee; + padding-bottom: 15px; + margin-left: 20px; + margin-right: 20px; + color: #666; +} diff --git a/miniprogram/pages/name_form/name_form.js b/miniprogram/pages/name_form/name_form.js new file mode 100644 index 0000000..36b6c40 --- /dev/null +++ b/miniprogram/pages/name_form/name_form.js @@ -0,0 +1,104 @@ + +import regeneratorRuntime from '../../utils/regenerator-runtime/runtime' +import BaseMixin from '../base/base' +import mergePages from '../../utils/objectUtils' +const moment = require('../../utils/moment.min.js') +import { CallCloudFuncAPI } from '../../utils/async_cloudfunc.js' +import { $wuxDialog } from '../../components/wux-weapp/index' + + +const PageObject = mergePages({}, BaseMixin, { + data: { + userInfo: null + }, + onInited(options) { + this.getProfile() + }, + async getProfile() { + this.showLoading() + let res = null + try { + res = await CallCloudFuncAPI( + "main", + { + apiName: "getProfile" + } + ) + } catch (e) { + console.error(e) + this.hideLoading() + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + return + } + + + this.hideLoading() + if (!res.result.status) { + this.showToast({ + title: res.result.message + }) + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + return + } + + this.setData({ + userInfo: res.result.data.user + }) + }, + async submitForm() { + this.showLoading() + let res = null + try { + res = await CallCloudFuncAPI( + "main", + { + apiName: "userAPI.updateUserName", + nickName: this.data.userInfo.nickName, + realName: this.data.userInfo.realName + } + ) + } catch (e) { + console.error(e) + this.hideLoading() + this.showToast({ + title: e.message + }) + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + return + } + + this.hideLoading() + if (!res.result.status) { + this.showToast({ + title: res.result.message + }) + } else { + this.showToast({ + icon: 'success', + title: 'ok' + }) + } + + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + }, + bindInputRealName(e) { + this.setData({ + 'userInfo.realName': e.detail.value + }) + }, + bindInputNickName(e) { + this.setData({ + 'userInfo.nickName': e.detail.value + }) + } +}) + +Page(PageObject) \ No newline at end of file diff --git a/miniprogram/pages/name_form/name_form.json b/miniprogram/pages/name_form/name_form.json new file mode 100644 index 0000000..d66e201 --- /dev/null +++ b/miniprogram/pages/name_form/name_form.json @@ -0,0 +1,5 @@ +{ + "usingComponents": { + "wux-dialog": "../../components/wux-weapp/dialog/index" + } +} \ No newline at end of file diff --git a/miniprogram/pages/name_form/name_form.wxml b/miniprogram/pages/name_form/name_form.wxml new file mode 100644 index 0000000..e492fa3 --- /dev/null +++ b/miniprogram/pages/name_form/name_form.wxml @@ -0,0 +1,17 @@ + + + * 姓名 + + + + + + * 昵称 + + + + + + 提交 + + \ No newline at end of file diff --git a/miniprogram/pages/name_form/name_form.wxss b/miniprogram/pages/name_form/name_form.wxss new file mode 100644 index 0000000..d18ce62 --- /dev/null +++ b/miniprogram/pages/name_form/name_form.wxss @@ -0,0 +1 @@ +@import '../base/style.wxss'; \ No newline at end of file diff --git a/miniprogram/pages/order_details/order_details.js b/miniprogram/pages/order_details/order_details.js new file mode 100644 index 0000000..98bfcf6 --- /dev/null +++ b/miniprogram/pages/order_details/order_details.js @@ -0,0 +1,87 @@ + +import regeneratorRuntime from '../../utils/regenerator-runtime/runtime' +import BaseMixin from '../base/base' +import PulldownMixin from '../base/pulldown_mixin' +import mergePages from '../../utils/objectUtils' +const moment = require('../../utils/moment.min.js') +import { CallCloudFuncAPI } from '../../utils/async_cloudfunc.js' +import { $wuxDialog } from '../../components/wux-weapp/index' +import { StatusLabel } from '../../utils/constant' + + +const PageObject = mergePages({}, BaseMixin, PulldownMixin, { + + data: { + reqData: { + page: 1, + pagesize: 10 + }, + entityIdField: '_id', + apiName: "orderAPI.getOrders", + isCloudFunc: true, + statuses: StatusLabel, + itemFlags: { + pay: '-', + deposit: '+' + } + }, + onInited() { + wx.startPullDownRefresh() + }, + getEntitiesApiUrl() { + return "main" + }, + async getOrders() { + let res = null + try { + res = await CallCloudFuncAPI( + "main", + { + apiName: "orderAPI.getOrders" + } + ) + } catch (e) { + console.error(e) + wx.stopPullDownRefresh() + return + } + + if (res) { + console.log(res) + this.setData({ + entities: res.result.data.entities + }) + } + wx.stopPullDownRefresh() + }, + formatEntities(data) { + console.log(data) + for (let entity of data.entities) { + entity.create_at = moment(entity.create_at).format('YYYY/MM/DD HH:mm') + if (entity.type == 'deposit') { + entity.title = '购买充值卡' + } else if (entity.type == 'pay') { + entity.title = this.getGoodsName(entity.orderInfo) + } + } + return data + }, + getGoodsName(orderInfo) { + let goodsName = ''; + orderInfo.entities.map((item, index) => { + if (index === 0) { + goodsName += item.name + } else if (index > 0 && index < 3) { + goodsName += '、' + item.name + } else if (index == 3) { + if (orderInfo.entities.length > 3) { + goodsName += '等' + } + } + }) + return goodsName + } + +}) + +Page(PageObject) \ No newline at end of file diff --git a/miniprogram/pages/order_details/order_details.json b/miniprogram/pages/order_details/order_details.json new file mode 100644 index 0000000..69b19d4 --- /dev/null +++ b/miniprogram/pages/order_details/order_details.json @@ -0,0 +1,4 @@ +{ + "enablePullDownRefresh": true, + "usingComponents": {} +} \ No newline at end of file diff --git a/miniprogram/pages/order_details/order_details.wxml b/miniprogram/pages/order_details/order_details.wxml new file mode 100644 index 0000000..c46862e --- /dev/null +++ b/miniprogram/pages/order_details/order_details.wxml @@ -0,0 +1,2 @@ + +miniprogram/pages/order_details/order_details.wxml diff --git a/miniprogram/pages/order_details/order_details.wxss b/miniprogram/pages/order_details/order_details.wxss new file mode 100644 index 0000000..8be7ae4 --- /dev/null +++ b/miniprogram/pages/order_details/order_details.wxss @@ -0,0 +1 @@ +/* miniprogram/pages/order_details/order_details.wxss */ \ No newline at end of file diff --git a/miniprogram/pages/orders/orders.js b/miniprogram/pages/orders/orders.js new file mode 100644 index 0000000..fe22ab9 --- /dev/null +++ b/miniprogram/pages/orders/orders.js @@ -0,0 +1,55 @@ + +import regeneratorRuntime from '../../utils/regenerator-runtime/runtime' +import BaseMixin from '../base/base' +import PulldownMixin from '../base/pulldown_mixin' +import OrdersMixin from '../base/orders_mixin' +import mergePages from '../../utils/objectUtils' +import { CallCloudFuncAPI } from '../../utils/async_cloudfunc.js' + +const PageObject = mergePages({}, BaseMixin, PulldownMixin, OrdersMixin, { + + data: { + reqData: { + page: 1, + pagesize: 10 + }, + entityIdField: '_id', + apiName: "orderAPI.getOrders", + isCloudFunc: true, + itemFlags: { + pay: '-', + deposit: '+' + } + }, + onInited() { + wx.startPullDownRefresh() + }, + getEntitiesApiUrl() { + return "main" + }, + async getOrders() { + let res = null + try { + res = await CallCloudFuncAPI( + "main", + { + apiName: "orderAPI.getOrders" + } + ) + } catch (e) { + console.error(e) + wx.stopPullDownRefresh() + return + } + + if (res) { + console.log(res) + this.setData({ + entities: res.result.data.entities + }) + } + wx.stopPullDownRefresh() + } +}) + +Page(PageObject) \ No newline at end of file diff --git a/miniprogram/pages/orders/orders.json b/miniprogram/pages/orders/orders.json new file mode 100644 index 0000000..69b19d4 --- /dev/null +++ b/miniprogram/pages/orders/orders.json @@ -0,0 +1,4 @@ +{ + "enablePullDownRefresh": true, + "usingComponents": {} +} \ No newline at end of file diff --git a/miniprogram/pages/orders/orders.wxml b/miniprogram/pages/orders/orders.wxml new file mode 100644 index 0000000..e7eeb08 --- /dev/null +++ b/miniprogram/pages/orders/orders.wxml @@ -0,0 +1,40 @@ + + + + 设置 + + + + + + {{item.title}} + {{item.orderNo}} + {{statuses[item.status].name}} {{deliveryStatus[item.delivery_status] ? deliveryStatus[item.delivery_status].name:''}} {{item.is_cancel?'已取消':''}} + {{item.create_at}} + + + + {{entity.name}} + {{entity.price}} x {{entity.count}} + + + + + 收货地址: + {{item.addressInfo.provinceName}} {{item.addressInfo.cityName}} {{item.addressInfo.countyName}} {{item.addressInfo.detailInfo}} + 电话:{{item.addressInfo.telNumber}} + 邮编:{{item.addressInfo.postalCode}} + + + 快递公司:{{item.deliveryInfo.company_name||'本店御用快递小哥'}} + 订单编号:{{item.deliveryInfo.orderno}} + 送达时间:{{item.deliveryInfo.will_received_date}} {{item.deliveryInfo.will_received_time}} + + + 用户备注: {{item.remarks}} + 管理员备注: {{item.admin_remarks}} + + {{itemFlags[item.type]}} {{item.orderInfo.total}} + + + \ No newline at end of file diff --git a/miniprogram/pages/orders/orders.wxss b/miniprogram/pages/orders/orders.wxss new file mode 100644 index 0000000..8479f8a --- /dev/null +++ b/miniprogram/pages/orders/orders.wxss @@ -0,0 +1,2 @@ +@import '../base/style.wxss'; +@import '../user_orders/user_orders.wxss'; diff --git a/miniprogram/pages/profile/profile.js b/miniprogram/pages/profile/profile.js new file mode 100644 index 0000000..61ef798 --- /dev/null +++ b/miniprogram/pages/profile/profile.js @@ -0,0 +1,149 @@ + +import regeneratorRuntime from '../../utils/regenerator-runtime/runtime' +import BaseMixin from '../base/base' +import mergePages from '../../utils/objectUtils' +const moment = require('../../utils/moment.min.js') +import { CallCloudFuncAPI } from '../../utils/async_cloudfunc.js' +import { $wuxDialog } from '../../components/wux-weapp/index' + +const genderTypes = [ + { + label: '男', + value: '0' + }, + { + label: '女', + value: '1' + }, +] + + +const PageObject = mergePages({}, BaseMixin, { + data: { + userInfo: null, + genderTypes: genderTypes, + genderName: '', + birthEndDay: null + }, + onInited(options) { + this.setData({ + birthEndDay: moment().format('YYYY-MM-DD') + }) + wx.startPullDownRefresh() + }, + async getProfile() { + this.showLoading() + let res = null + try { + res = await CallCloudFuncAPI( + "main", + { + apiName: "getProfile" + } + ) + } catch (e) { + console.error(e) + this.hideLoading() + this.showToast({ + title: e.message + }) + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + + } + + if (!res.result.status) { + this.showToast({ + title: res.result.message + }) + this.hideLoading() + wx.stopPullDownRefresh() + return + } + + this.setData({ + userInfo: res.result.data.user, + genderName: genderTypes[parseInt(res.result.data.user.gender)].label + }) + + wx.hideLoading() + wx.stopPullDownRefresh() + }, + async bindGenderChange(e) { + this.showLoading() + this.setData({ + 'userInfo.gender': this.data.genderTypes[e.detail.value].value, + genderName: this.data.genderTypes[e.detail.value].label + }) + let res = null + try { + res = await CallCloudFuncAPI( + "main", + { + apiName: "userAPI.updateGender", + gender: this.data.userInfo.gender + } + ) + } catch (e) { + this.hideLoading() + this.showToast({ + title: e.message + }) + console.error(e) + return + } + + if (res.result.status) { + console.log(res) + this.hideLoading() + this.showToast({ + icon: 'success', + title: 'ok' + }) + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + + } + }, + async bindDateChange(e) { + console.log(e) + this.showLoading() + let res = null + try { + res = await CallCloudFuncAPI( + "main", + { + apiName: "userAPI.updateBirthday", + birthday: e.detail.value + } + ) + } catch (e) { + this.hideLoading() + this.showToast({ + title: e.message + }) + console.error(e) + return + } + + if (res.result.status) { + console.log(res) + this.hideLoading() + this.showToast({ + icon: 'success', + title: 'ok' + }) + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + + } + }, + onPullDownRefresh: function () { + this.getProfile() + }, +}) + +Page(PageObject) \ No newline at end of file diff --git a/miniprogram/pages/profile/profile.json b/miniprogram/pages/profile/profile.json new file mode 100644 index 0000000..e6dd469 --- /dev/null +++ b/miniprogram/pages/profile/profile.json @@ -0,0 +1,7 @@ +{ + "enablePullDownRefresh": true, + "usingComponents": { + "wux-dialog": "../../components/wux-weapp/dialog/index", + "list-item": "../../components/list_item/list_item" + } +} \ No newline at end of file diff --git a/miniprogram/pages/profile/profile.wxml b/miniprogram/pages/profile/profile.wxml new file mode 100644 index 0000000..b5f7b88 --- /dev/null +++ b/miniprogram/pages/profile/profile.wxml @@ -0,0 +1,14 @@ + + + + 个人资料 + + + + + + + + + + \ No newline at end of file diff --git a/miniprogram/pages/profile/profile.wxss b/miniprogram/pages/profile/profile.wxss new file mode 100644 index 0000000..184b3f5 --- /dev/null +++ b/miniprogram/pages/profile/profile.wxss @@ -0,0 +1,9 @@ +@import '../base/style.wxss'; + +.list-title { + padding-left: 20px; + padding-top: 40px; + padding-bottom: 10px; + font-size: 16px; + color: #333; +} \ No newline at end of file diff --git a/miniprogram/pages/regist/regist.js b/miniprogram/pages/regist/regist.js new file mode 100644 index 0000000..d4959f9 --- /dev/null +++ b/miniprogram/pages/regist/regist.js @@ -0,0 +1,141 @@ + +import regeneratorRuntime from '../../utils/regenerator-runtime/runtime' +import mergePages from '../../utils/objectUtils' +import { asyncLogin } from '../../utils/async_tools/async_login' +import { asyncChecksession } from '../../utils/async_tools/async_checksession' +import { callAsync } from '../../utils/async_tools/async_tools' +import { CallCloudFuncAPI } from '../../utils/async_cloudfunc' +import { wxRequest } from '../../utils/async_http' +import BaseMixin from '../base/base' +import { $wuxDialog } from '../../components/wux-weapp/index' + +const PageObject = mergePages({}, BaseMixin, { + + data: { + nextpage: null, + sessionKey: null + }, + + onInited: async function (options) { + const nextpage = wx.getStorageSync('nextpage_registed') + if (nextpage) { + this.setData({ + nextpage: nextpage + }) + } + // await this.wxLogin() + }, + async cloudRegist(data, sessionKey) { + let res = null + try { + res = await CallCloudFuncAPI( + "main", + { + apiName: "registAPI.regist", + encryptData: data, + sessionKey: sessionKey + } + ) + } catch (e) { + + console.error(e) + this.showToast({ + title: e.message + }) + + return + } + + wx.setStorageSync('sessionid', res.result.data.openid) + if (res.result.status) { + if (this.data.nextpage) { + wx.removeStorageSync('nextpage_registed') + } + wx.switchTab({ + url: this.data.nextpage || res.result.data.nextpage, + }) + } + }, + async registByCloudID(cloudId) { + let res = null + try { + res = await CallCloudFuncAPI( + "main", + { + apiName: "registAPI.registByCloudID", + weRunData: cloudId, + } + ) + } catch (e) { + + console.error('registByCloudID error: ', e) + this.showToast({ + title: 'system_error' + }) + + return + } + + wx.setStorageSync('sessionid', res.result.data.openid) + if (res.result.status) { + if (this.data.nextpage) { + wx.removeStorageSync('nextpage_registed') + } + wx.switchTab({ + url: this.data.nextpage || res.result.data.nextpage, + }) + } + }, + async wxLogin() { + let result = await callAsync(asyncLogin) + console.log('asyncLogin-status:', result[0]) + console.log('asyncLogin-result:', result[1]) + if (result[0]) { + this.showToast({ + title: result.message + }) + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + return + } + let url = `https://api.weixin.qq.com/sns/jscode2session?appid=${this.data.settings.app_id}&secret=${this.data.settings.app_secret}&js_code=${result[1].code}&grant_type=authorization_code` + console.log('url:', url) + result = await wxRequest(url, { method: 'GET' }) + console.log('jscode2session-result:', result) + if (result.errMsg != 'request:ok') { + this.showToast({ + title: result.errMsg + }) + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + return + } + this.setData({ + sessionKey: result.data.session_key + }) + }, + onGetPhoneNumber: async function (e) { + // if(!this.data.sessionKey) { + // this.showToast({ + // title: '未能获取到sessionKey' + // }) + // return + // } + console.log('onGetPhoneNumber:', e) + // await this.cloudRegist(JSON.stringify({ + // iv: e.detail.iv, + // encryptedData: e.detail.encryptedData + // }), this.data.sessionKey) + this.showLoading() + try { + await this.registByCloudID(wx.cloud.CloudID(e.detail.cloudID)) + } catch(e) { + logger.error(e) + } + this.hideLoading() + } +}) + +Page(PageObject) \ No newline at end of file diff --git a/miniprogram/pages/regist/regist.json b/miniprogram/pages/regist/regist.json new file mode 100644 index 0000000..d66e201 --- /dev/null +++ b/miniprogram/pages/regist/regist.json @@ -0,0 +1,5 @@ +{ + "usingComponents": { + "wux-dialog": "../../components/wux-weapp/dialog/index" + } +} \ No newline at end of file diff --git a/miniprogram/pages/regist/regist.wxml b/miniprogram/pages/regist/regist.wxml new file mode 100644 index 0000000..2e22715 --- /dev/null +++ b/miniprogram/pages/regist/regist.wxml @@ -0,0 +1,7 @@ + + + + 为了更好的为您服务,我们需要获取您的手机号 + + + \ No newline at end of file diff --git a/miniprogram/pages/regist/regist.wxss b/miniprogram/pages/regist/regist.wxss new file mode 100644 index 0000000..3301eba --- /dev/null +++ b/miniprogram/pages/regist/regist.wxss @@ -0,0 +1,37 @@ +page { + display: flex; + flex-direction: column; + justify-content: flex-start; + background-color: #e67774; +} + + +.userinfo-nickname { + font-size: 32rpx; + color: white; + background-color: #7dd3da; + background-size: cover; + height: 40px; + line-height: 40px; + width: 120px; + border-radius: 20px; + position: absolute; + bottom: 100px; + left: 50%; + margin-left: -60px; + box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.3); +} + +.userinfo-nickname::after { + border: none; +} + +.note { + padding: 40px; + margin: 40px; + background-color: #fb5655; + text-align: center; + color: #fff; + font-size: 120%; + border-radius: 20px; +} \ No newline at end of file diff --git a/miniprogram/pages/update_address/update_address.js b/miniprogram/pages/update_address/update_address.js new file mode 100644 index 0000000..368f46c --- /dev/null +++ b/miniprogram/pages/update_address/update_address.js @@ -0,0 +1,155 @@ + +import regeneratorRuntime from '../../utils/regenerator-runtime/runtime' +import BaseMixin from '../base/base' +import mergePages from '../../utils/objectUtils' +const moment = require('../../utils/moment.min.js') +import { CallCloudFuncAPI } from '../../utils/async_cloudfunc.js' +import { $wuxDialog } from '../../components/wux-weapp/index' + + +const PageObject = mergePages({}, BaseMixin, { + data: { + addressInfo: { + userName: '', + telNumber: '', + provinceName: '', + cityName: '', + countyName: '', + postalCode: '', + detailInfo: '' + } + }, + onInited(options) { + + this.setData({ + orderid: options.orderid + }) + this.getOrderDetail() + }, + async getOrderDetail() { + this.showLoading() + let res = null + try { + res = await CallCloudFuncAPI( + "main", + { + apiName: "adminAPI.getUserOrders", + orderid: this.data.orderid + } + ) + } catch (e) { + console.error(e) + this.hideLoading() + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + return + } + + + this.hideLoading() + if (!res.result.status) { + this.showToast({ + title: res.result.message + }) + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + return + } + + if(res.result.data.entities && res.result.data.entities[0].addressInfo) { + this.setData({ + addressInfo: res.result.data.entities[0].addressInfo + }) + } + }, + async submitForm() { + this.showLoading() + let res = null + try { + res = await CallCloudFuncAPI( + "main", + { + apiName: "adminAPI.updateOrderAddress", + addressInfo: this.data.addressInfo, + orderId: this.data.orderid + } + ) + } catch (e) { + console.error(e) + this.hideLoading() + this.showToast({ + title: e.message + }) + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + return + } + + this.hideLoading() + if (!res.result.status) { + this.showToast({ + title: res.result.message + }) + } else { + this.showToast({ + icon: 'success', + title: 'ok' + }) + } + + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + }, + bindInputChange(e) { + console.log(e) + if (e.currentTarget.dataset.field == 'userName') { + this.setData({ + 'addressInfo.userName': e.detail.value + }) + } + + if (e.currentTarget.dataset.field == 'telNumber') { + this.setData({ + 'addressInfo.telNumber': e.detail.value + }) + } + + if (e.currentTarget.dataset.field == 'provinceName') { + + this.setData({ + 'addressInfo.provinceName': e.detail.value + }) + } + + if (e.currentTarget.dataset.field == 'cityName') { + this.setData({ + 'addressInfo.cityName': e.detail.value + }) + } + + if (e.currentTarget.dataset.field == 'countyName') { + this.setData({ + 'addressInfo.countyName': e.detail.value + }) + } + + if (e.currentTarget.dataset.field == 'postalCode') { + + this.setData({ + 'addressInfo.postalCode': e.detail.value + }) + } + + if (e.currentTarget.dataset.field == 'detailInfo') { + this.setData({ + 'addressInfo.detailInfo': e.detail.value + }) + } + } +}) + +Page(PageObject) \ No newline at end of file diff --git a/miniprogram/pages/update_address/update_address.json b/miniprogram/pages/update_address/update_address.json new file mode 100644 index 0000000..8835af0 --- /dev/null +++ b/miniprogram/pages/update_address/update_address.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} \ No newline at end of file diff --git a/miniprogram/pages/update_address/update_address.wxml b/miniprogram/pages/update_address/update_address.wxml new file mode 100644 index 0000000..17596c4 --- /dev/null +++ b/miniprogram/pages/update_address/update_address.wxml @@ -0,0 +1,47 @@ + + + * 收货人姓名 + + + + + + * 联系电话 + + + + + + * 所在省份或直辖市 + + + + + + * 所在城市或辖区 + + + + + + 所在区 + + + + + + 邮编 + + + + + + * 详细地址 + + + + + + 保存 + + \ No newline at end of file diff --git a/miniprogram/pages/update_address/update_address.wxss b/miniprogram/pages/update_address/update_address.wxss new file mode 100644 index 0000000..d18ce62 --- /dev/null +++ b/miniprogram/pages/update_address/update_address.wxss @@ -0,0 +1 @@ +@import '../base/style.wxss'; \ No newline at end of file diff --git a/miniprogram/pages/update_delivery/update_delivery.js b/miniprogram/pages/update_delivery/update_delivery.js new file mode 100644 index 0000000..3520e15 --- /dev/null +++ b/miniprogram/pages/update_delivery/update_delivery.js @@ -0,0 +1,190 @@ + +import regeneratorRuntime from '../../utils/regenerator-runtime/runtime' +import BaseMixin from '../base/base' +import mergePages from '../../utils/objectUtils' +const moment = require('../../utils/moment.min.js') +import { CallCloudFuncAPI } from '../../utils/async_cloudfunc.js' +import { $wuxDialog } from '../../components/wux-weapp/index' +import { $wuxCalendar } from '../../components/wux-weapp/index' + +const DeliveryStatus = { + '0': 'preparing', + '1': 'shipping', + '2': 'delivering', + '3': 'received' +} + +const companies = [ + { name: '顺丰' }, + { name: '韵达' }, + { name: '中通' }, + { name: '圆通' }, + { name: '申通' }, + { name: '自营' } +] + +const PageObject = mergePages({}, BaseMixin, { + data: { + status: null, + companies: companies, + targetDate: [], + deliveryInfo: { + company_name: '', + orderno: '', + will_received_date: '', + will_received_time: '', + create_at: '', + fee: 0 + } + }, + onInited(options) { + this.setData({ + orderid: options.orderid + }) + this.getOrderDetail() + }, + + openCalendar() { + $wuxCalendar().open({ + value: this.data.targetDate, + onChange: (values, displayValues) => { + console.log('onChange', values, displayValues) + this.setData({ + targetDate: displayValues, + 'deliveryInfo.will_received_date': displayValues[0] + }) + }, + }) + }, + bindTimeChange(e) { + this.setData({ + 'deliveryInfo.will_received_time': e.detail.value + }) + }, + bindOrdernoChange(e) { + this.setData({ + 'deliveryInfo.orderno': e.detail.value + }) + }, + bindDeliveryCompanyInputChange(e) { + this.setData({ + 'deliveryInfo.company_name': e.detail.value + }) + }, + bindOrdeFeeChange(e) { + try { + parseInt(e.detail.value) + } catch(error) { + console.error(error) + return + } + this.setData({ + 'deliveryInfo.fee': parseInt(e.detail.value) + }) + }, + async getOrderDetail() { + this.showLoading() + let res = null + try { + res = await CallCloudFuncAPI( + "main", + { + apiName: "adminAPI.getUserOrders", + orderid: this.data.orderid + } + ) + } catch (e) { + console.error(e) + this.hideLoading() + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + return + } + + + this.hideLoading() + if (!res.result.status) { + this.showToast({ + title: res.result.message + }) + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + return + } + + this.setData({ + status: res.result.data.delivery_status + }) + }, + + setOrderStatus() { + let that = this; + wx.showActionSheet({ + itemList: ['备货中', '已发货', '正在送货', '已签收'], + success(res) { + console.log(res.tapIndex) + that.setData({ + status: DeliveryStatus[res.tapIndex.toString()] + }) + that.submitForm() + }, + fail(res) { + console.log(res.errMsg) + + } + }) + }, + + async submitForm() { + console.log('status:', this.data.status) + this.showLoading() + let res = null + try { + res = await CallCloudFuncAPI( + "main", + { + apiName: "adminAPI.updateDeliveryStatus", + status: this.data.status, + orderId: this.data.orderid, + deliveryInfo: this.data.deliveryInfo + } + ) + } catch (e) { + console.error(e) + this.hideLoading() + this.showToast({ + title: e.message + }) + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + return + } + + this.hideLoading() + if (!res.result.status) { + this.showToast({ + title: res.result.message + }) + } else { + this.showToast({ + icon: 'success', + title: 'ok' + }) + } + + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + }, + bindDeliveryCompanyChange(e) { + console.log(e) + this.setData({ + 'deliveryInfo.company_name': companies[parseInt(e.detail.value)].name + }) + } +}) + +Page(PageObject) \ No newline at end of file diff --git a/miniprogram/pages/update_delivery/update_delivery.json b/miniprogram/pages/update_delivery/update_delivery.json new file mode 100644 index 0000000..f70ed2d --- /dev/null +++ b/miniprogram/pages/update_delivery/update_delivery.json @@ -0,0 +1,5 @@ +{ + "usingComponents": { + "wux-calendar": "../../components/wux-weapp/calendar/index" + } +} \ No newline at end of file diff --git a/miniprogram/pages/update_delivery/update_delivery.wxml b/miniprogram/pages/update_delivery/update_delivery.wxml new file mode 100644 index 0000000..cee20c7 --- /dev/null +++ b/miniprogram/pages/update_delivery/update_delivery.wxml @@ -0,0 +1,50 @@ + + + + + 快递公司 + + + + + + + + + + 订单号 + + + + + + + 运费(元) + + + + + + + + 预计送达日期 + + + + + + + + 预计送达时间 + + + + + + + + + + 设置发货状态 + + \ No newline at end of file diff --git a/miniprogram/pages/update_delivery/update_delivery.wxss b/miniprogram/pages/update_delivery/update_delivery.wxss new file mode 100644 index 0000000..d18ce62 --- /dev/null +++ b/miniprogram/pages/update_delivery/update_delivery.wxss @@ -0,0 +1 @@ +@import '../base/style.wxss'; \ No newline at end of file diff --git a/miniprogram/pages/update_order/update_order.js b/miniprogram/pages/update_order/update_order.js new file mode 100644 index 0000000..5d6be05 --- /dev/null +++ b/miniprogram/pages/update_order/update_order.js @@ -0,0 +1,133 @@ + +import regeneratorRuntime from '../../utils/regenerator-runtime/runtime' +import BaseMixin from '../base/base' +import mergePages from '../../utils/objectUtils' +const moment = require('../../utils/moment.min.js') +import { CallCloudFuncAPI } from '../../utils/async_cloudfunc.js' +import { $wuxDialog } from '../../components/wux-weapp/index' + + +const OrderStatus = { + '0': 'submit', + '1': 'pay', + '2': 'received', + '3': 'refund', + '4': 'complete', + +} + +const PageObject = mergePages({}, BaseMixin, { + data: { + status: null + }, + onInited(options) { + + this.setData({ + orderid: options.orderid + }) + this.getOrderDetail() + }, + async getOrderDetail() { + this.showLoading() + let res = null + try { + res = await CallCloudFuncAPI( + "main", + { + apiName: "adminAPI.getUserOrders", + orderid: this.data.orderid + } + ) + } catch (e) { + console.error(e) + this.hideLoading() + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + return + } + + + this.hideLoading() + if (!res.result.status) { + this.showToast({ + title: res.result.message + }) + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + return + } + + if (res.result.data.entities && res.result.data.entities[0].addressInfo) { + this.setData({ + addressInfo: res.result.data.entities[0].addressInfo + }) + } + + this.setData({ + status: res.result.data.status + }) + }, + + setOrderStatus() { + let that = this; + wx.showActionSheet({ + itemList: ['订单提交', '已支付', '已接单', '已退款', '已完成'], + success(res) { + console.log(res.tapIndex) + that.setData({ + status: OrderStatus[res.tapIndex.toString()] + }) + that.submitForm() + }, + fail(res) { + console.log(res.errMsg) + + } + }) + }, + + async submitForm() { + this.showLoading() + let res = null + try { + res = await CallCloudFuncAPI( + "main", + { + apiName: "adminAPI.updateOrderStatus", + status: this.data.status, + orderId: this.data.orderid + } + ) + } catch (e) { + console.error(e) + this.hideLoading() + this.showToast({ + title: e.message + }) + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + return + } + + this.hideLoading() + if (!res.result.status) { + this.showToast({ + title: res.result.message + }) + } else { + this.showToast({ + icon: 'success', + title: 'ok' + }) + } + + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + }, +}) + +Page(PageObject) \ No newline at end of file diff --git a/miniprogram/pages/update_order/update_order.json b/miniprogram/pages/update_order/update_order.json new file mode 100644 index 0000000..8835af0 --- /dev/null +++ b/miniprogram/pages/update_order/update_order.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} \ No newline at end of file diff --git a/miniprogram/pages/update_order/update_order.wxml b/miniprogram/pages/update_order/update_order.wxml new file mode 100644 index 0000000..ea5b09d --- /dev/null +++ b/miniprogram/pages/update_order/update_order.wxml @@ -0,0 +1,5 @@ + + + 设置订单状态 + + \ No newline at end of file diff --git a/miniprogram/pages/update_order/update_order.wxss b/miniprogram/pages/update_order/update_order.wxss new file mode 100644 index 0000000..d18ce62 --- /dev/null +++ b/miniprogram/pages/update_order/update_order.wxss @@ -0,0 +1 @@ +@import '../base/style.wxss'; \ No newline at end of file diff --git a/miniprogram/pages/update_remarks/update_remarks.js b/miniprogram/pages/update_remarks/update_remarks.js new file mode 100644 index 0000000..b45216c --- /dev/null +++ b/miniprogram/pages/update_remarks/update_remarks.js @@ -0,0 +1,117 @@ + +import regeneratorRuntime from '../../utils/regenerator-runtime/runtime' +import BaseMixin from '../base/base' +import mergePages from '../../utils/objectUtils' +const moment = require('../../utils/moment.min.js') +import { CallCloudFuncAPI } from '../../utils/async_cloudfunc.js' +import { $wuxDialog } from '../../components/wux-weapp/index' + +const PageObject = mergePages({}, BaseMixin, { + data: { + admin_remarks: '', + remarks: '' + }, + onInited(options) { + + this.setData({ + orderid: options.orderid + }) + this.getOrderDetail() + }, + async getOrderDetail() { + this.showLoading() + let res = null + try { + res = await CallCloudFuncAPI( + "main", + { + apiName: "adminAPI.getUserOrders", + orderid: this.data.orderid + } + ) + } catch (e) { + console.error(e) + this.hideLoading() + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + return + } + + + this.hideLoading() + if (!res.result.status) { + this.showToast({ + title: res.result.message + }) + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + return + } + + if (res.result.data.entities && res.result.data.entities[0].orderInfo) { + console.log(res.result.data.entities[0]) + this.setData({ + remarks: res.result.data.entities[0].remarks || '', + admin_remarks: res.result.data.entities[0].admin_remarks || '', + }) + } + }, + + + async submitForm() { + this.showLoading() + let res = null + try { + res = await CallCloudFuncAPI( + "main", + { + apiName: "adminAPI.updateOrderRemarks", + remarks: this.data.remarks, + admin_remarks: this.data.admin_remarks, + orderId: this.data.orderid + } + ) + } catch (e) { + console.error(e) + this.hideLoading() + this.showToast({ + title: e.message + }) + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + return + } + + this.hideLoading() + if (!res.result.status) { + this.showToast({ + title: res.result.message + }) + } else { + this.showToast({ + icon: 'success', + title: 'ok' + }) + } + + setTimeout(() => { + wx.navigateBack() + }, this.data.settings.shortTipDuration) + }, + bindAdminRemarksChange(e) { + this.setData({ + admin_remarks: e.detail.value + }) + + }, + bindUserRemarksChange(e){ + this.setData({ + remarks: e.detail.value + }) + } +}) + +Page(PageObject) \ No newline at end of file diff --git a/miniprogram/pages/update_remarks/update_remarks.json b/miniprogram/pages/update_remarks/update_remarks.json new file mode 100644 index 0000000..8835af0 --- /dev/null +++ b/miniprogram/pages/update_remarks/update_remarks.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} \ No newline at end of file diff --git a/miniprogram/pages/update_remarks/update_remarks.wxml b/miniprogram/pages/update_remarks/update_remarks.wxml new file mode 100644 index 0000000..be26f1c --- /dev/null +++ b/miniprogram/pages/update_remarks/update_remarks.wxml @@ -0,0 +1,17 @@ + + + * 管理员备注 + +