From db4a95e35d8cde0bdc2969acc7d8112c7e2f8b43 Mon Sep 17 00:00:00 2001 From: whitechiina <1293616053@qq.com> Date: Tue, 25 Nov 2025 11:21:13 +0800 Subject: [PATCH] first commit --- App.vue | 17 + api/index.js | 90 ++ api/order.js | 448 +++++++ api/public.js | 11 + components/OnlineShop.vue | 573 +++++++++ components/countDown/index.vue | 128 ++ components/mono-keyboard/mono-keyboard.vue | 223 ++++ components/numberScroll.vue | 160 +++ config/app.js | 11 + config/cache.js | 46 + config/payChat.js | 35 + config/socket.js | 18 + index.html | 20 + main.js | 27 + manifest.json | 77 ++ pages.json | 27 + pages/Paysuccessful/jxPaysuccessful.vue | 189 +++ pages/index/index.vue | 606 ++++++++++ static/css/pageElement.scss | 16 + static/fail.png | Bin 0 -> 47313 bytes static/icon/demo.css | 539 +++++++++ static/icon/demo_index.html | 257 ++++ static/icon/iconfont.css | 27 + static/icon/iconfont.js | 1 + static/icon/iconfont.json | 30 + static/icon/iconfont.ttf | Bin 0 -> 2128 bytes static/icon/iconfont.woff | Bin 0 -> 1408 bytes static/icon/iconfont.woff2 | Bin 0 -> 992 bytes static/js/appconfig.js | 5 + static/js/indt.ts | 214 ++++ static/logo.png | Bin 0 -> 4023 bytes static/mono-keyboard/backspace.png | Bin 0 -> 1065 bytes static/mono-keyboard/backspace_dark.png | Bin 0 -> 959 bytes static/success.png | Bin 0 -> 26868 bytes store/getters.js | 28 + store/index.js | 23 + store/modules/app.js | 37 + store/modules/index.js | 14 + uni.promisify.adaptor.js | 13 + uni.scss | 76 ++ utils/cache.js | 230 ++++ utils/request.js | 87 ++ utils/urlUtils.js | 77 ++ utils/util.js | 1278 ++++++++++++++++++++ utils/utils.js | 58 + 45 files changed, 5716 insertions(+) create mode 100644 App.vue create mode 100644 api/index.js create mode 100644 api/order.js create mode 100644 api/public.js create mode 100644 components/OnlineShop.vue create mode 100644 components/countDown/index.vue create mode 100644 components/mono-keyboard/mono-keyboard.vue create mode 100644 components/numberScroll.vue create mode 100644 config/app.js create mode 100644 config/cache.js create mode 100644 config/payChat.js create mode 100644 config/socket.js create mode 100644 index.html create mode 100644 main.js create mode 100644 manifest.json create mode 100644 pages.json create mode 100644 pages/Paysuccessful/jxPaysuccessful.vue create mode 100644 pages/index/index.vue create mode 100755 static/css/pageElement.scss create mode 100755 static/fail.png create mode 100755 static/icon/demo.css create mode 100755 static/icon/demo_index.html create mode 100755 static/icon/iconfont.css create mode 100755 static/icon/iconfont.js create mode 100755 static/icon/iconfont.json create mode 100755 static/icon/iconfont.ttf create mode 100755 static/icon/iconfont.woff create mode 100755 static/icon/iconfont.woff2 create mode 100755 static/js/appconfig.js create mode 100755 static/js/indt.ts create mode 100644 static/logo.png create mode 100644 static/mono-keyboard/backspace.png create mode 100644 static/mono-keyboard/backspace_dark.png create mode 100755 static/success.png create mode 100644 store/getters.js create mode 100644 store/index.js create mode 100644 store/modules/app.js create mode 100644 store/modules/index.js create mode 100644 uni.promisify.adaptor.js create mode 100644 uni.scss create mode 100644 utils/cache.js create mode 100644 utils/request.js create mode 100644 utils/urlUtils.js create mode 100644 utils/util.js create mode 100644 utils/utils.js diff --git a/App.vue b/App.vue new file mode 100644 index 0000000..99f6e28 --- /dev/null +++ b/App.vue @@ -0,0 +1,17 @@ + + + diff --git a/api/index.js b/api/index.js new file mode 100644 index 0000000..e38e827 --- /dev/null +++ b/api/index.js @@ -0,0 +1,90 @@ +import request from "@/utils/request.js"; + +// 推送播报 +export function cancelPaymentSoundAPI(data) { + return request.get('MiniProgram/Order/cancelPaymentSound', data); +} + +// 取消发声 +export function cancelPay(data) { + return request.post('/api/gzh/cancelPay', data); +} + +// 获取商户信息 +export function getMerchantAPI(data) { + return request.get('MiniProgram/Api/getMerchant', data); +} + +// 获取用户信息 +export function userInfoAPI(data) { + return request.get('MiniProgram/Api/userInfo', data); +} + +// 支付 +export function createScanOrderAPI(data) { + return request.get('MiniProgram/Api/submitOrder', data); +} + +// 发送验证码 +export function sendSmsAPI(data) { + return request.get('MiniProgram/Api/sendSms', data); +} + +// 绑定手机号 +export function bindPhoneAPI(data) { + return request.get('MiniProgram/Api/bindPhone', data); +} + +// 商户端支付 +export function againPayAPI(data) { + return request.get('client/mall/againPay', data); +} + +// 订单详情? +export function orderDetailAPI(data) { + return request.get('MiniProgram/Api/orderDetail', data); +} + +// code查店铺 +export function getMerchantInfoByCode(data) { + return request.post('/api/gzh/getMerchantInfoByCode', data); +} + +// id查店铺 +export function getMerchantInfo(data) { + return request.post('/api/gzh/getMerchantInfo', data); +} + +// 下单 1 +export function doOrder(data) { + return request.post('/api/merchant/doOrder', data); +} + +// 下单 0 +export function dogzhOrder(data) { + return request.post('/api/gzh/doOrder', data); +} + +// 券 1 +export function computedOrder(data) { + return request.post('/api/merchant/computedOrder', data); +} + + +// 券 0 +export function gzhcomputedOrder(data) { + return request.post('/api/gzh/computedOrder', data); +} + +// 支付宝订单号查询 1 +export function getOfflineOrderDetail(data) { + return request.post('/api/merchant/getOfflineOrderDetail', data); +} + +// 支付宝订单号查询 0 +export function getgzhlineOrderDetail(data) { + return request.post('/api/gzh/getOfflineOrderDetail', data); +} + + + diff --git a/api/order.js b/api/order.js new file mode 100644 index 0000000..8e23ed4 --- /dev/null +++ b/api/order.js @@ -0,0 +1,448 @@ +// +---------------------------------------------------------------------- +// | CRMEB [ CRMEB赋能开发者,助力企业发展 ] +// +---------------------------------------------------------------------- +// | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved. +// +---------------------------------------------------------------------- +// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权 +// +---------------------------------------------------------------------- +// | Author: CRMEB Team +// +---------------------------------------------------------------------- + +import request from "@/utils/request.js"; + +/** + * 获取购物车列表 + * @param numType boolean true 购物车数量,false=购物车产品数量 + */ +export function getCartCounts(numType) { + return request.get("cart/count", { + numType: numType === undefined ? 0 : numType + }); +} +/** + * 获取购物车列表 + * + */ +export function getCartList(data) { + return request.get("cart/list", data); +} + +/** + * 修改购物车 + * + */ +export function getResetCart(data) { + return request.post("v2/reset_cart", data); +} + +/** + * 修改购物车数量 + * @param int cartId 购物车id + * @param int number 修改数量 + */ +export function changeCartNum(cartId, number) { + return request.post("cart/num", { + id: cartId, + number: number + }); +} +/** + * 清除购物车 + * @param object ids join(',') 切割成字符串 + */ +export function cartDel(ids) { + if (typeof ids === 'object') + ids = ids.join(','); + return request.post('cart/del', { + ids: ids + }); +} +/** + * 订单列表 + * @param object data + */ +export function getOrderList(data) { + return request.get('order/list', data); +} + +/** + * 订单产品信息 + * @param string unique + */ +export function orderProduct(unique) { + return request.post('order/product', { + unique: unique + }); +} + +/** + * 订单评价 + * @param object data + * + */ +export function orderComment(data) { + return request.post('order/comment', data); +} + +/** + * 订单支付 + * @param object data + */ +export function orderPay(data) { + return request.post('/api/order/pay', data); +} + +/** + * 删除已退款和拒绝退款的订单 + * @param string uni + * + */ +export function refundOrderDel(uni) { + return request.get('order/refund/del/' + uni, {}); +} + +/** + * 订单统计数据 + */ +export function orderData() { + return request.get('order/data') +} + +/** + * 订单取消 + * @param string id + * + */ +export function orderCancel(id) { + return request.post('mall/api/cancel_order', { + order_id: id + }); +} + +/** + * 删除已完成订单 + * @param string uni + * + */ +export function orderDel(uni) { + return request.post('order/del', { + uni: uni + }); +} + +/** + * 订单详情 + * @param string uni + */ +export function getOrderDetail(uni, cart_id) { + return request.get('order/detail/' + uni + `${cart_id ? `/${cart_id}`:''}`); +} +/** + * 退款订单详情 + * @param string uni + */ +export function getRefundOrderDetail(uni, cart_id) { + return request.get('order/refund_detail/' + uni + `${cart_id ? `/${cart_id}`:''}`); +} + +/** + * 再次下单 + * @param string uni + * + */ +export function orderAgain(uni) { + return request.post('order/again', { + uni: uni + }); +} + +/** + * 订单收货 + * @param string uni + * + */ +export function orderTake(uni) { + return request.post('order/take', { + uni: uni + }); +} + +/** + * 订单查询物流信息 + * @returns {*} + */ +export function express(uni, type) { + return request.get("order/express/" + uni + `${type?'/refund':''}`); +} +/** + * 订单查询物流信息 + * @returns {*} + */ +export function adminExpress(uni, type) { + return request.get("admin/order/express/" + uni + `${type?'/refund':''}`); +} + +/** + * 获取退款理由 + * + */ +export function ordeRefundReason() { + return request.get('order/refund/reason'); +} + +/** + * 订单退款审核 + * @param object data + */ +export function orderRefundVerify(data) { + return request.post('order/refund/verify', data); +} + +/** + * 订单确认获取订单详细信息 + * @param string cartId + */ +export function orderConfirm(cartId, news, addressId, shipping_type) { + return request.post('order/confirm', { + cartId, + 'new': news, + addressId, + shipping_type + }); +} + +/** + * 获取确认订单页面是否展示快递配送和到店自提 + * @param string cartId + */ +export function checkShipping(cartId, news) { + return request.post('order/check_shipping', { + cartId, + 'new': news + }); +} + +/** + * 获取当前金额能使用的优惠卷 + * @param string price + * + */ +export function getCouponsOrderPrice(price, data) { + return request.get('coupons/order/' + price, data) +} + +/** + * 订单创建 + * @param string key + * @param object data + * + */ +export function orderCreate(key, data) { + return request.post('order/create/' + key, data); +} + +/** + * 计算订单金额 + * @param key + * @param data + * @returns {*} + */ +export function postOrderComputed(key, data) { + return request.post("order/computed/" + key, data); +} + +/** + * 订单优惠券 + * @param key + * @param data + * @returns {*} + */ +export function orderCoupon(orderId) { + return request.post("v2/order/product_coupon/" + orderId); +} + +/** + * 计算会员线下付款金额 + * @param {Object} data + */ +export function offlineCheckPrice(data) { + return request.post("order/offline/check/price", data); +} + +/** + * 线下扫码付款 + * @param {Object} data + */ +export function offlineCreate(data) { + return request.post("order/offline/create", data); +} + +/** + * 支付方式开关 + */ +export function orderOfflinePayType() { + return request.get('order/offline/pay/type'); +} + +/** + * 开票记录 + */ +export function orderInvoiceList(data) { + return request.get('v2/order/invoice_list', data); +} + +/** + * 开票订单详情 + * @param {Object} id + */ +export function orderInvoiceDetail(id) { + return request.get(`v2/order/invoice_detail/${id}`); +} + + +/** + * 支付宝支付 + * @param {Object} key + * @param {Object} quitUrl + */ +export function aliPay(key, quitUrl) { + return request.get('ali_pay', { + key, + quitUrl + }, { + noAuth: true + }); +} + + +/** + * 退货物流单号提交 + * @param {Object} data + */ +export function refundExpress(data) { + return request.post("order/refund/express", data); +} + +/** + * 分类购物车列表 + */ +export function vcartList() { + return request.get("v2/cart_list"); +} + +/** + * 退款商品列表 + */ +export function refundGoodsList(orderId) { + return request.get(`order/refund/cart_info/${orderId}`); +} + +/** + * 申请退款商品列表 + */ +export function postRefundGoods(data) { + return request.post(`order/refund/cart_info`, data); +} + +/** + * 退款商品提交 + */ +export function returnGoodsSubmit(id, data) { + return request.post(`order/refund/apply/${id}`, data); +} + +/** + * 新订单列表 2.1版本 + * @param object data + */ +export function getNewOrderList(data) { + return request.get('order/refund/list', data); +} + +/** + * 退款订单详情 + * @param string uni + */ +export function refundOrderDetail(uni) { + return request.get('order/refund/detail/' + uni); +} + +/** + * 放弃申请退款 + * @param string uni + */ +export function cancelRefundOrder(uni) { + return request.post('order/refund/cancel/' + uni); +} + +/** + * 收银台订单信息 + * @param object data + */ +export function getCashierOrder(orderId, type) { + return request.get(`/api/order/cashier/${orderId}/${type}`); +} + +/** + * 发票地址获取 + * @param object data + */ +export function getInvoiceLink(id) { + return request.get(`v2/order/down_invoice/${id}`); +} + + +/** + * 点餐取消订单 + * @param string data + */ +export function cancelShopOrder(data) { + return request.post('merchant_order/order/cancelOrder', data); +} + +// /** +// * 线上商品取消订单 +// * @param string data +// */ +// export function cancelonlineOrder(data) { +// return request.post('/mall/api/cancel_order', data); +// } + + +/** + * 点餐扫码订单详情 + * @param string data + */ + +export function getOrderShopDetail(id) { + return request.get(`merchant/getOrderDetail?id=${id}`); +} + +/** + * 线上订单详情 + * @param string data + */ + +export function getonlineOrderDetail(id) { + return request.get(`order/detail/${id}`); +} +/** + * 充值订单详情 + * @param string data + */ +export function RechargeOrderDetail(id) { + return request.get(`virtual/orderDetail?id=${id}`); +} +/** + * 充值订单取消 + */ +export function RechargeorderCancel(data) { + return request.post('virtual/cancelOrder', data); +} + +/** + * 获取订单顶部Tabs + */ +export function OrderTabs(data) { + return request.get('order_tab_config', data); +} \ No newline at end of file diff --git a/api/public.js b/api/public.js new file mode 100644 index 0000000..dc46015 --- /dev/null +++ b/api/public.js @@ -0,0 +1,11 @@ +import request from "@/utils/request.js"; + +/** + * 配置信息 + * + */ +export function basicConfig(name) { + return request.get(`/api/basic_config`, {}, { + noAuth: true + }); +} \ No newline at end of file diff --git a/components/OnlineShop.vue b/components/OnlineShop.vue new file mode 100644 index 0000000..342b4e7 --- /dev/null +++ b/components/OnlineShop.vue @@ -0,0 +1,573 @@ + + + + + + + \ No newline at end of file diff --git a/components/countDown/index.vue b/components/countDown/index.vue new file mode 100644 index 0000000..b0e6e12 --- /dev/null +++ b/components/countDown/index.vue @@ -0,0 +1,128 @@ + + + + + diff --git a/components/mono-keyboard/mono-keyboard.vue b/components/mono-keyboard/mono-keyboard.vue new file mode 100644 index 0000000..e95f4d7 --- /dev/null +++ b/components/mono-keyboard/mono-keyboard.vue @@ -0,0 +1,223 @@ + + + \ No newline at end of file diff --git a/components/numberScroll.vue b/components/numberScroll.vue new file mode 100644 index 0000000..2ace75d --- /dev/null +++ b/components/numberScroll.vue @@ -0,0 +1,160 @@ + + + + + diff --git a/config/app.js b/config/app.js new file mode 100644 index 0000000..b18ec30 --- /dev/null +++ b/config/app.js @@ -0,0 +1,11 @@ +module.exports = { + HTTP_REQUEST_URL: 'https://point.agrimedia.cn', + HEADER: {}, + TOKENNAME: 'Authori-zation', + // 缓存时间 0 永久 + EXPIRE: 0, + //分页最多显示条数 + LIMIT: 10, + // 请求超时限制 默认10秒 + TIMEOUT: 10000 +} diff --git a/config/cache.js b/config/cache.js new file mode 100644 index 0000000..187ecb4 --- /dev/null +++ b/config/cache.js @@ -0,0 +1,46 @@ +// +---------------------------------------------------------------------- +// | CRMEB [ CRMEB赋能开发者,助力企业发展 ] +// +---------------------------------------------------------------------- +// | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved. +// +---------------------------------------------------------------------- +// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权 +// +---------------------------------------------------------------------- +// | Author: CRMEB Team +// +---------------------------------------------------------------------- + +module.exports = { + //token + LOGIN_STATUS: 'LOGIN_STATUS_TOKEN', + ISPAY: '', + //uid + UID:'UID', + //用户信息 + USER_INFO: 'USER_INFO', + //token过期时间 + EXPIRES_TIME: 'EXPIRES_TIME', + //微信登录 + WX_AUTH: 'WX_AUTH', + //公众号登录code + STATE_KEY: 'wx_authorize_state', + //登录类型 + LOGINTYPE: 'loginType', + //登录跳转地址 + BACK_URL: 'login_back_url', + //小程序登录状态code + STATE_R_KEY: 'roution_authorize_state', + //logo 地址 + LOGO_URL: 'LOGO_URL', + //模板缓存 + SUBSCRIBE_MESSAGE: 'SUBSCRIBE_MESSAGE', + + TIPS_KEY: 'TIPS_KEY', + + SPREAD: 'spread', + //缓存经度 + CACHE_LONGITUDE: 'LONGITUDE', + //缓存纬度 + CACHE_LATITUDE: 'LATITUDE', + + // 店铺信息 + USER_ADDRESS: 'USER_ADDRESS' +} diff --git a/config/payChat.js b/config/payChat.js new file mode 100644 index 0000000..9234ac5 --- /dev/null +++ b/config/payChat.js @@ -0,0 +1,35 @@ +import store from '@/store/index.js'; +import { HTTP_REQUEST_URL } from '@/config/app'; +import { getMerchantInfo } from '@/api/user.js'; + +/** + * 使用方式: + * 进入半屏小程序所需的参数 + * parameter: { + need_login: 1, + shop_id: 1 + } +*/ + +const PayParams = function(parameter) { + return getMerchantInfo(parameter.shop_id).then(res => { + let shopData = res.data; + + return { + name: shopData.name, + code: res.data.bar_code, + need_login: parameter.need_login, + shop_id: parameter.shop_id, + price: parameter.price, + isVip: parameter.isVip, + envVersion: parameter.envVersion, + + status: parameter.status, + token: parameter.token, + BASE_URL: HTTP_REQUEST_URL, + REQUEST_URL: parameter.REQUEST_URL, + }; + }); +}; + +export default PayParams; \ No newline at end of file diff --git a/config/socket.js b/config/socket.js new file mode 100644 index 0000000..7ac0205 --- /dev/null +++ b/config/socket.js @@ -0,0 +1,18 @@ +// +---------------------------------------------------------------------- +// | CRMEB [ CRMEB赋能开发者,助力企业发展 ] +// +---------------------------------------------------------------------- +// | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved. +// +---------------------------------------------------------------------- +// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权 +// +---------------------------------------------------------------------- +// | Author: CRMEB Team +// +---------------------------------------------------------------------- + +module.exports = { + // Socket链接 暂不做配置 + WSS_SERVER_URL:'', + // Socket调试模式 + SERVER_DEBUG:true, + // 心跳间隔 + PINGINTERVAL:3000 +} \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..b5d330d --- /dev/null +++ b/index.html @@ -0,0 +1,20 @@ + + + + + + + + + + +
+ + + diff --git a/main.js b/main.js new file mode 100644 index 0000000..dae342d --- /dev/null +++ b/main.js @@ -0,0 +1,27 @@ +import App from './App' +import store from './store' +import util from 'utils/util' + +// #ifndef VUE3 +import Vue from 'vue' +import './uni.promisify.adaptor' + +Vue.prototype.$util = util; +Vue.config.productionTip = false +App.mpType = 'app' +const app = new Vue({ + store, + ...App +}) +app.$mount() +// #endif + +// #ifdef VUE3 +import { createSSRApp } from 'vue' +export function createApp() { + const app = createSSRApp(App) + return { + app + } +} +// #endif \ No newline at end of file diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..cf0875a --- /dev/null +++ b/manifest.json @@ -0,0 +1,77 @@ +{ + "name" : "收银台支付", + "appid" : "__UNI__B05F7DA", + "description" : "", + "versionName" : "1.0.0", + "versionCode" : "100", + "transformPx" : false, + /* 5+App特有相关 */ + "app-plus" : { + "usingComponents" : true, + "nvueStyleCompiler" : "uni-app", + "compilerVersion" : 3, + "splashscreen" : { + "alwaysShowBeforeRender" : true, + "waiting" : true, + "autoclose" : true, + "delay" : 0 + }, + /* 模块配置 */ + "modules" : {}, + /* 应用发布信息 */ + "distribute" : { + /* android打包配置 */ + "android" : { + "permissions" : [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ] + }, + /* ios打包配置 */ + "ios" : {}, + /* SDK配置 */ + "sdkConfigs" : {} + } + }, + /* 快应用特有相关 */ + "quickapp" : {}, + /* 小程序特有相关 */ + "mp-weixin" : { + "appid" : "", + "setting" : { + "urlCheck" : false + }, + "usingComponents" : true + }, + "mp-alipay" : { + "usingComponents" : true + }, + "mp-baidu" : { + "usingComponents" : true + }, + "mp-toutiao" : { + "usingComponents" : true + }, + "uniStatistics" : { + "enable" : false + }, + "vueVersion" : "2", + "h5" : { + "router" : { + "mode" : "history" + } + } +} diff --git a/pages.json b/pages.json new file mode 100644 index 0000000..ec1f6d0 --- /dev/null +++ b/pages.json @@ -0,0 +1,27 @@ +{ + "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages + { + "path": "pages/index/index", + "style": { + "navigationBarTitleText": "向商家付款", + "enablePullDownRefresh": false, + "navigationStyle": "custom" + } + }, + { + "path": "pages/Paysuccessful/jxPaysuccessful", + "style": { + "navigationBarTitleText": "支付结果", + "enablePullDownRefresh": false, + "navigationStyle": "custom" + } + } + ], + "globalStyle": { + "navigationBarTextStyle": "black", + "navigationBarTitleText": "uni-app", + "navigationBarBackgroundColor": "#F8F8F8", + "backgroundColor": "#F8F8F8" + }, + "uniIdRouter": {} +} diff --git a/pages/Paysuccessful/jxPaysuccessful.vue b/pages/Paysuccessful/jxPaysuccessful.vue new file mode 100644 index 0000000..45b35fb --- /dev/null +++ b/pages/Paysuccessful/jxPaysuccessful.vue @@ -0,0 +1,189 @@ + + + + + \ No newline at end of file diff --git a/pages/index/index.vue b/pages/index/index.vue new file mode 100644 index 0000000..4d5c19a --- /dev/null +++ b/pages/index/index.vue @@ -0,0 +1,606 @@ + + + + + \ No newline at end of file diff --git a/static/css/pageElement.scss b/static/css/pageElement.scss new file mode 100755 index 0000000..048f72c --- /dev/null +++ b/static/css/pageElement.scss @@ -0,0 +1,16 @@ +#app { + max-width: 750rpx; + min-width: 750rpx; + height: auto; + margin: 0 auto; + min-height: 100%; +} + +page { + /* // background-color: #1C1C1E; + // background-image: url('https://img.agrimedia.cn/sch5/bg.png'); + // background-size: cover; */ + padding: 30.77rpx; + height: 100%; + width: 100; +} \ No newline at end of file diff --git a/static/fail.png b/static/fail.png new file mode 100755 index 0000000000000000000000000000000000000000..c8dc1d325fe330d410e6ab34e2fb4f66ee0efd1a GIT binary patch literal 47313 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 literal 0 HcmV?d00001 diff --git a/static/icon/demo.css b/static/icon/demo.css new file mode 100755 index 0000000..a67054a --- /dev/null +++ b/static/icon/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/static/icon/demo_index.html b/static/icon/demo_index.html new file mode 100755 index 0000000..24eb3b3 --- /dev/null +++ b/static/icon/demo_index.html @@ -0,0 +1,257 @@ + + + + + iconfont Demo + + + + + + + + + + + + + +
+

+ + +

+ +
+
+
    + +
  • + +
    对勾_块
    +
    &#xed1d;
    +
  • + +
  • + +
    警告
    +
    &#xeb65;
    +
  • + +
  • + +
    购物车满
    +
    &#xe600;
    +
  • + +
+
+

Unicode 引用

+
+ +

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

+
    +
  • 支持按字体的方式去动态调整图标大小,颜色等等。
  • +
  • 默认情况下不支持多色,直接添加多色图标会自动去色。
  • +
+
+

注意:新版 iconfont 支持两种方式引用多色图标:SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)

+
+

Unicode 使用步骤如下:

+

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

+
@font-face {
+  font-family: 'iconfont';
+  src: url('iconfont.woff2?t=1669284444124') format('woff2'),
+       url('iconfont.woff?t=1669284444124') format('woff'),
+       url('iconfont.ttf?t=1669284444124') format('truetype');
+}
+
+

第二步:定义使用 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-duigou_kuai +
    +
  • + +
  • + +
    + 警告 +
    +
    .icon-jinggao +
    +
  • + +
  • + +
    + 购物车满 +
    +
    .icon-gouwucheman +
    +
  • + +
+
+

font-class 引用

+
+ +

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

+

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

+
    +
  • 相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。
  • +
  • 因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。
  • +
+

使用步骤如下:

+

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

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

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

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

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

+
+
+
+
+
    + +
  • + +
    对勾_块
    +
    #icon-duigou_kuai
    +
  • + +
  • + +
    警告
    +
    #icon-jinggao
    +
  • + +
  • + +
    购物车满
    +
    #icon-gouwucheman
    +
  • + +
+
+

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/static/icon/iconfont.css b/static/icon/iconfont.css new file mode 100755 index 0000000..fc4ffdd --- /dev/null +++ b/static/icon/iconfont.css @@ -0,0 +1,27 @@ +@font-face { + font-family: "iconfont"; /* Project id 3770712 */ + src: url('iconfont.woff2?t=1669284444124') format('woff2'), + url('iconfont.woff?t=1669284444124') format('woff'), + url('iconfont.ttf?t=1669284444124') format('truetype'); +} + +.iconfont { + font-family: "iconfont" !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-duigou_kuai:before { + content: "\ed1d"; +} + +.icon-jinggao:before { + content: "\eb65"; +} + +.icon-gouwucheman:before { + content: "\e600"; +} + diff --git a/static/icon/iconfont.js b/static/icon/iconfont.js new file mode 100755 index 0000000..439ddcf --- /dev/null +++ b/static/icon/iconfont.js @@ -0,0 +1 @@ +window._iconfont_svg_string_3770712='',function(n){var t=(t=document.getElementsByTagName("script"))[t.length-1],e=t.getAttribute("data-injectcss"),t=t.getAttribute("data-disable-injectsvg");if(!t){var o,i,a,d,c,s=function(t,e){e.parentNode.insertBefore(t,e)};if(e&&!n.__iconfont__svg__cssinject__){n.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(t){console&&console.log(t)}}o=function(){var t,e=document.createElement("div");e.innerHTML=n._iconfont_svg_string_3770712,(e=e.getElementsByTagName("svg")[0])&&(e.setAttribute("aria-hidden","true"),e.style.position="absolute",e.style.width=0,e.style.height=0,e.style.overflow="hidden",e=e,(t=document.body).firstChild?s(e,t.firstChild):t.appendChild(e))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(o,0):(i=function(){document.removeEventListener("DOMContentLoaded",i,!1),o()},document.addEventListener("DOMContentLoaded",i,!1)):document.attachEvent&&(a=o,d=n.document,c=!1,r(),d.onreadystatechange=function(){"complete"==d.readyState&&(d.onreadystatechange=null,l())})}function l(){c||(c=!0,a())}function r(){try{d.documentElement.doScroll("left")}catch(t){return void setTimeout(r,50)}l()}}(window); \ No newline at end of file diff --git a/static/icon/iconfont.json b/static/icon/iconfont.json new file mode 100755 index 0000000..8ec8bd7 --- /dev/null +++ b/static/icon/iconfont.json @@ -0,0 +1,30 @@ +{ + "id": "3770712", + "name": "no name", + "font_family": "iconfont", + "css_prefix_text": "icon-", + "description": "", + "glyphs": [ + { + "icon_id": "7954334", + "name": "对勾_块", + "font_class": "duigou_kuai", + "unicode": "ed1d", + "unicode_decimal": 60701 + }, + { + "icon_id": "3868273", + "name": "警告", + "font_class": "jinggao", + "unicode": "eb65", + "unicode_decimal": 60261 + }, + { + "icon_id": "5030", + "name": "购物车满", + "font_class": "gouwucheman", + "unicode": "e600", + "unicode_decimal": 58880 + } + ] +} diff --git a/static/icon/iconfont.ttf b/static/icon/iconfont.ttf new file mode 100755 index 0000000000000000000000000000000000000000..92ac68d18abae0438aff0ddd088faa64cbe458e6 GIT binary patch literal 2128 zcmd^A&2Jk;6n`^oJBbs2BPd!2|q1?{=nvx($*=j=A*4; z{}agWl6s}WWLkv%F~~|;EouHQ#=jwQ!p?IQy=LSxuOPQ(nCUbjcWJG@Mi(4HCXAw* zgUw-TpiOw!zrE-i|A$&F?w#v@-4;Y^uCF^tQXw`Ix7|e~2hEYwl!exfA5qIy$L9~*!wNb>f+{Y zN33q2LIBUk1F+0ygVA`sR`~pD9Fhk=JGKw zi}i+jlbr!qtQV{VLnWAxr$(Psq=BfPISJ;6fkF)_v14*?4dSktYD z;$hMYp242oO&@oT$dTQ9f$okrX;|($?F)FF-JyJ-%PToKce=Q~_x?MfvCvE2aBRQ| zi!fe(NSyWu!z~*_%7vqyk&d32ubz9;-`VBv47bVd_GVwtfbwpLg+%Q{9kgNJ10or+ z^)!n&hHPU_P4u{pCFr9zb^sr>u@i6iq>WwBKVxGzJxQl*+=_@5@x(h?uuea{Wn+eY z|H{UkymZsX67;{=*a7^zjhz&vdp34KziVSR%`uOSTdALAPF6M5(3X_NRi%*8%UQi_ zH0Co}Zl$PJ8)9Rg)2g+CURFlp!wuDpR@SPGFty9Mq+w*0Y*jBQ(}<@Pi@H*&>dRWj zi02KXaw3rs>j-^3qnGF;RY@b242(;p;Ip%eu|OHpsZ3dOG#--AfSsciD#Ek+koBM*|rt=v7220ZrTaX~?7qtl$8JZ5eSg zV8m~%cl3gcg8us literal 0 HcmV?d00001 diff --git a/static/icon/iconfont.woff b/static/icon/iconfont.woff new file mode 100755 index 0000000000000000000000000000000000000000..759bf40f0a1c52317b961760f11bcebfb0c8f0ef GIT binary patch literal 1408 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 literal 0 HcmV?d00001 diff --git a/static/js/appconfig.js b/static/js/appconfig.js new file mode 100755 index 0000000..b9c31da --- /dev/null +++ b/static/js/appconfig.js @@ -0,0 +1,5 @@ +import { createSSRApp } from "vue"; +const app = createSSRApp(App); +const globals = app.config.globalProperties; +// console.log(app,'globals'); +export {globals}; \ No newline at end of file diff --git a/static/js/indt.ts b/static/js/indt.ts new file mode 100755 index 0000000..3c567a6 --- /dev/null +++ b/static/js/indt.ts @@ -0,0 +1,214 @@ +import Request_ from '../../api/request'; + + +class _init { + + // 登录完成回调(包含处理完成用户携带数据) + UserLoginInitCollback = undefined; + userInfor = {}; + // 微信登录之后获取到 参数 + openid : String = ""; + session_key : string = ""; + // Wechat = {}; + // 支付宝登录之后获取到的参数 + Apple = { + access_token: "0", + alipay_user_id: "0", + auth_start: "0", + expires_in: 0, + re_expires_in: 0, + refresh_token: "", + user_id: "", + }; + code = ''; + pay_type : number = 0; + provider : "weixin" | "qq" | "sinaweibo" | "xiaomi" | "apple" | "univerify" = 'weixin'; + // 进入来源 Scan | Half + referrerInfo:'Scan' | 'Half'; + // 初始参数 + __programParameter__ = null; + /** 请求参数 */ + APIoptions = {}; + constructor(parameters) { + // #ifdef MP-ALIPAY + this['pay_type'] = 2; + // #endif + // #ifdef MP-WEIXIN + this['pay_type'] = 1; + // #endif + /** + * 初始化来源 + */ + // parameters.referrerInfo = { + // path:"pages/index/index", + // quer:{}, + // scene:1037, + // referrerInfo:{"appId":"wxc8e2e1d28d15d2e3"}, + // extraData:{ + // "thrust_code":"4871020984", + // code:"49750683" + // }, + // mode:"embedded", + // apiCategory:"embedded" + // }; + if(parameters?.referrerInfo && Object.keys(parameters['referrerInfo'])['length']){ + this.referrerInfo = 'Half'; + /** + * 初始化参数 + */ + this.__programParameter__ = parameters['referrerInfo']['extraData']; + this.APIoptions = this['__programParameter__']; + }else{ + this.referrerInfo = 'Scan'; + /** + * 初始化参数 + */ + this.__programParameter__ = parameters; + /**处理拿到的初始化参数 */ + this.InitParam(); + + }; + + + } + + /** 获取来源 */ + get source(){ + return this['referrerInfo']; + } + + + // 推送播报 + // Pushbroadcast(data){ + // if(getApp()['globalData']['Pay_Status'] == 2) return; + // Request_.GET({ url:"/MiniProgram/Order/cancelPaymentSound", data }); + // } + + Login() { + let url : string = null; + // #ifdef MP-ALIPAY + url = '/MiniProgram/Api/alipayCodeLogin'; + this['pay_type'] = 2; + // #endif + // #ifdef MP-WEIXIN + url = '/MiniProgram/Api/wechatCodeLogin'; + this['pay_type'] = 1; + console.log(uni.login,this['provider'],'执行登录'); + // #endif + uni.login({ + provider: this['provider'], + success: loginRes => { + console.log(loginRes['code'], 'code---'); + if (loginRes.code) { + let data = null; + // #ifdef MP-ALIPAY + console.log(loginRes['code'], 'apple:code'); + data = { code: loginRes['code'] }; + // #endif + + // #ifdef MP-WEIXIN + console.log(loginRes['code'], 'WeChat:code'); + data = { code: loginRes['code'], type: 1 }; + // #endif + data['thrust_code'] = this['options']['thrust_code'] || ''; + data['invite_code'] = this['options']['invite_code'] || ''; + // return + + console.log(data,'data') + this.userInfor = data; + Request_.GET({ url, data }).then(res => { + this.userInfor = {...this['userInfor'],...res['data']} + uni.setStorageSync('token', res['data']['token']); + console.log(res, '登录信息'); + // #ifdef MP-ALIPAY + // let { openid, session_key } = res['data']; + this['Apple'] = res['data']; + // #endif + // #ifdef MP-WEIXIN + let { scan_openid, session_key } = res['data']; + this['openid'] = scan_openid; + this['session_key'] = session_key; + // #endif + console.log(this['UserLoginInitCollback'], 'UserLoginInitCollback'); + if (this['UserLoginInitCollback'] != null && typeof this['UserLoginInitCollback'] == 'function') { + this.UserLoginInitCollback(); + } + }) + } else { + uni.showToast({ + title: '登录失败!未获取到code', + icon: 'none', + duration: 2000 + }) + } + }, + fail:error=>{ + console.log(error,'error') + } + }); + } + + // 支付时获取指定平台字段 + get Getopenid() { + // #ifdef MP-ALIPAY + return this['Apple']['user_id']; + // #endif + // #ifdef MP-WEIXIN + return this['openid']; + // #endif + } + + get options(){ + return this['APIoptions'] + } + + // 解析小程序初始参数 + InitParam() { + console.log(this['__programParameter__'],this['source'],'__programParameter__'); + // 扫码进入 + if (this['__programParameter__']?.query?.q || this['__programParameter__']?.query?.scene || this['__programParameter__']?.query?.qrCode) { + let searchParamToObj = ''; + searchParamToObj = this['__programParameter__']['query']?.q || this['__programParameter__']['query']?.scene || this['__programParameter__']['query']?.qrCode; + console.log(searchParamToObj, 'searchParamToObj'); + const obj = {}; + const Para = this.escape2Html(decodeURIComponent(searchParamToObj)); + const _i = Para.indexOf('?'); + console.log(Para, _i, 'Para'); + if (~_i) { + const _U = Para.slice(_i + 1, Para['length']); + const _M = _U.split('&'); + + for (let i = 0; i < _M['length']; i++) { + const index = _M[i].indexOf("="); + console.log(index, 'index'); + const KEY = _M[i].substring(0, index); + const VAL = _M[i].substring(index + 1, _M[i].length); + obj[KEY] = VAL; + }; + this.APIoptions = obj; + + } else { + this.APIoptions = {}; + } + } else { + // 商户端扫码进入 + try{ + this.APIoptions = this['__programParameter__']['query']; + }catch(e){ + this.APIoptions = {}; + //TODO handle the exception + } + } + + } + + // 字符转义 + escape2Html(str) { + var arrEntities = { 'lt': '<', 'gt': '>', 'nbsp': ' ', 'amp': '&', 'quot': '"' }; + return str.replace(/&(lt|gt|nbsp|amp|quot);/ig, function (all, t) { return arrEntities[t]; }); + }; + +} + + +export default _init; \ No newline at end of file diff --git a/static/logo.png b/static/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b5771e209bb677e2ebd5ff766ad5ee11790f305a GIT binary patch literal 4023 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 Y1Aa(eNnrr6#sB~S07*qoM6N<$g2wFBAOHXW literal 0 HcmV?d00001 diff --git a/store/getters.js b/store/getters.js new file mode 100644 index 0000000..6f2c885 --- /dev/null +++ b/store/getters.js @@ -0,0 +1,28 @@ +// +---------------------------------------------------------------------- +// | CRMEB [ CRMEB赋能开发者,助力企业发展 ] +// +---------------------------------------------------------------------- +// | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved. +// +---------------------------------------------------------------------- +// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权 +// +---------------------------------------------------------------------- +// | Author: CRMEB Team +// +---------------------------------------------------------------------- + +export default { + token: state => state.app.token, + isLogin: state => !!state.app.token, + backgroundColor: state => state.app.backgroundColor, + userInfo: state => state.app.userInfo || {}, + uid: state => state.app.uid, + homeActive: state => state.app.homeActive, + home: state => state.app.home, + cartNum: state => state.indexData.cartNum, + activityTab: state => state.app.activityTab, + address: state => state.app.addressInfo +}; +// export default { +// token: state => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJrYWlmYS5jcm1lYi5uZXQiLCJhdWQiOiJrYWlmYS5jcm1lYi5uZXQiLCJpYXQiOjE1NzcwODM1MzQsIm5iZiI6MTU3NzA4MzUzNCwiZXhwIjoxNTc3MDk0MzM0LCJqdGkiOnsiaWQiOjExMCwidHlwZSI6InVzZXIifX0.U-i1pbdRjyXI1gr79Uq2XBPZ89T8f5Ai9jwrR8woTwE', +// isLogin: state => true, +// backgroundColor: state => state.app.backgroundColor, +// userInfo: state => state.app.userInfo || {} +// }; \ No newline at end of file diff --git a/store/index.js b/store/index.js new file mode 100644 index 0000000..ce3da58 --- /dev/null +++ b/store/index.js @@ -0,0 +1,23 @@ +// +---------------------------------------------------------------------- +// | CRMEB [ CRMEB赋能开发者,助力企业发展 ] +// +---------------------------------------------------------------------- +// | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved. +// +---------------------------------------------------------------------- +// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权 +// +---------------------------------------------------------------------- +// | Author: CRMEB Team +// +---------------------------------------------------------------------- + +import Vue from "vue"; +import Vuex from "vuex"; +import modules from "./modules"; +import getters from "./getters"; + +Vue.use(Vuex); +const debug = process.env.NODE_ENV !== "production"; + +export default new Vuex.Store({ + modules, + getters, + strict: debug +}); diff --git a/store/modules/app.js b/store/modules/app.js new file mode 100644 index 0000000..9e0c2b6 --- /dev/null +++ b/store/modules/app.js @@ -0,0 +1,37 @@ + +import { + LOGIN_STATUS, + ISPAY, + UID, + USER_INFO, + USER_ADDRESS +} from '../../config/cache'; +import Cache from '../../utils/cache'; + +const state = { + token: Cache.get(LOGIN_STATUS) || false, + ISPAY: Cache.get(ISPAY) || '', +}; + +const mutations = { + LOGIN(state, opt) { + state.token = opt.token; + }, + UPDATE_LOGIN(state, token) { + state.token = token; + Cache.set(LOGIN_STATUS, token); + }, + SETALL_PAT(state, data) { + state.ISPAY = data; + Cache.set(ISPAY, data); + } +}; + +const actions = { +}; + +export default { + state, + mutations, + actions +}; diff --git a/store/modules/index.js b/store/modules/index.js new file mode 100644 index 0000000..e46e951 --- /dev/null +++ b/store/modules/index.js @@ -0,0 +1,14 @@ +// +---------------------------------------------------------------------- +// | CRMEB [ CRMEB赋能开发者,助力企业发展 ] +// +---------------------------------------------------------------------- +// | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved. +// +---------------------------------------------------------------------- +// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权 +// +---------------------------------------------------------------------- +// | Author: CRMEB Team +// +---------------------------------------------------------------------- + +import app from "./app"; +export default { + app, +}; diff --git a/uni.promisify.adaptor.js b/uni.promisify.adaptor.js new file mode 100644 index 0000000..5fec4f3 --- /dev/null +++ b/uni.promisify.adaptor.js @@ -0,0 +1,13 @@ +uni.addInterceptor({ + returnValue (res) { + if (!(!!res && (typeof res === "object" || typeof res === "function") && typeof res.then === "function")) { + return res; + } + return new Promise((resolve, reject) => { + res.then((res) => { + if (!res) return resolve(res) + return res[0] ? reject(res[0]) : resolve(res[1]) + }); + }); + }, +}); \ No newline at end of file diff --git a/uni.scss b/uni.scss new file mode 100644 index 0000000..62eb87b --- /dev/null +++ b/uni.scss @@ -0,0 +1,76 @@ +/** + * 这里是uni-app内置的常用样式变量 + * + * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量 + * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App + * + */ + +/** + * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能 + * + * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件 + */ + +/* 颜色变量 */ + +/* 行为相关颜色 */ +$uni-color-primary: #007aff; +$uni-color-success: #4cd964; +$uni-color-warning: #f0ad4e; +$uni-color-error: #dd524d; + +/* 文字基本颜色 */ +$uni-text-color:#333;//基本色 +$uni-text-color-inverse:#fff;//反色 +$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息 +$uni-text-color-placeholder: #808080; +$uni-text-color-disable:#c0c0c0; + +/* 背景颜色 */ +$uni-bg-color:#ffffff; +$uni-bg-color-grey:#f8f8f8; +$uni-bg-color-hover:#f1f1f1;//点击状态颜色 +$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色 + +/* 边框颜色 */ +$uni-border-color:#c8c7cc; + +/* 尺寸变量 */ + +/* 文字尺寸 */ +$uni-font-size-sm:12px; +$uni-font-size-base:14px; +$uni-font-size-lg:16px; + +/* 图片尺寸 */ +$uni-img-size-sm:20px; +$uni-img-size-base:26px; +$uni-img-size-lg:40px; + +/* Border Radius */ +$uni-border-radius-sm: 2px; +$uni-border-radius-base: 3px; +$uni-border-radius-lg: 6px; +$uni-border-radius-circle: 50%; + +/* 水平间距 */ +$uni-spacing-row-sm: 5px; +$uni-spacing-row-base: 10px; +$uni-spacing-row-lg: 15px; + +/* 垂直间距 */ +$uni-spacing-col-sm: 4px; +$uni-spacing-col-base: 8px; +$uni-spacing-col-lg: 12px; + +/* 透明度 */ +$uni-opacity-disabled: 0.3; // 组件禁用态的透明度 + +/* 文章场景相关 */ +$uni-color-title: #2C405A; // 文章标题颜色 +$uni-font-size-title:20px; +$uni-color-subtitle: #555555; // 二级标题颜色 +$uni-font-size-subtitle:26px; +$uni-color-paragraph: #3F536E; // 文章段落颜色 +$uni-font-size-paragraph:15px; diff --git a/utils/cache.js b/utils/cache.js new file mode 100644 index 0000000..634edb9 --- /dev/null +++ b/utils/cache.js @@ -0,0 +1,230 @@ +// +---------------------------------------------------------------------- +// | CRMEB [ CRMEB赋能开发者,助力企业发展 ] +// +---------------------------------------------------------------------- +// | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved. +// +---------------------------------------------------------------------- +// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权 +// +---------------------------------------------------------------------- +// | Author: CRMEB Team +// +---------------------------------------------------------------------- + +import { + EXPIRE +} from '../config/app'; + +class Cache { + + constructor(handler) { + this.cacheSetHandler = uni.setStorageSync; + this.cacheGetHandler = uni.getStorageSync; + this.cacheClearHandler = uni.removeStorageSync; + this.cacheExpire = 'UNI-APP-CRMEB:TAG'; + this.clearOverdue(); + } + + /** + * 获取当前时间戳 + */ + time() { + return Math.round(new Date() / 1000); + } + + /** + * 字符串转时间戳 + * @param {Object} expiresTime + */ + strTotime(expiresTime) { + let expires_time = expiresTime.substring(0, 19); + expires_time = expires_time.replace(/-/g, '/'); + return Math.round(new Date(expires_time).getTime() / 1000); + } + + + /** + * 设置过期时间缓存 + * @param {Object} key + * @param {Object} expire + */ + setExpireCaheTag(key, expire) { + expire = expire !== undefined ? expire : EXPIRE; + if (typeof expire === 'number') { + let tag = this.cacheGetHandler(this.cacheExpire), + newTag = [], + newKeys = []; + if (typeof tag === 'object' && tag.length) { + newTag = tag.map(item => { + newKeys.push(item.key); + if (item.key === key) { + item.expire = expire === 0 ? 0 : this.time() + expire; + } + return item; + }); + } + if (!newKeys.length || newKeys.indexOf(key) === -1) { + newTag.push({ + key: key, + expire: expire === 0 ? 0 : this.time() + expire + }); + } + this.cacheSetHandler(this.cacheExpire, newTag); + } + } + + /** + * 缓存是否过期,过期自动删除 + * @param {Object} key + * @param {Object} $bool true = 删除,false = 不删除 + */ + getExpireCahe(key, $bool) { + try { + let tag = this.cacheGetHandler(this.cacheExpire), + time = 0, + index = false; + if (typeof tag === 'object' && tag.length) { + tag.map((item, i) => { + if (item.key === key) { + time = item.expire + index = i + } + }); + if (time) { + let newTime = parseInt(time); + if (time && time < this.time() && !Number.isNaN(newTime)) { + if ($bool === undefined || $bool === true) { + this.cacheClearHandler(key); + if (index !== false) { + tag.splice(index, 1) + this.cacheSetHandler(this.cacheExpire, tag); + } + } + return false; + } else + return true; + } else { + return !!this.cacheGetHandler(key); + } + } + return false; + } catch (e) { + return false; + } + } + + /** + * 设置缓存 + * @param {Object} key + * @param {Object} data + */ + set(key, data, expire) { + if (data === undefined) { + return true; + } + if (typeof data === 'object') + data = JSON.stringify(data); + try { + this.setExpireCaheTag(key, expire); + return this.cacheSetHandler(key, data); + } catch (e) { + return false; + } + } + + /** + * 检测缓存是否存在 + * @param {Object} key + */ + has(checkwhethethecacheexists, isDel) { + this.clearOverdue(); + return this.getExpireCahe(checkwhethethecacheexists, isDel); + } + + /** + * 获取缓存 + * @param {Object} key + * @param {Object} $default + * @param {Object} expire + */ + get(key, $default, expire) { + this.clearOverdue(); + try { + let isBe = this.getExpireCahe(key); + let data = this.cacheGetHandler(key); + if (data && isBe) { + if (typeof $default === 'boolean') + return JSON.parse(data); + else + return data; + } else { + if (typeof $default === 'function') { + let value = $default(); + this.set(key, value, expire); + return value; + } else { + this.set(key, $default, expire); + return $default; + } + } + } catch (e) { + return null; + } + } + + /** + * 删除缓存 + * @param {Object} key + */ + clear(key) { + try { + let cahceValue = this.cacheGetHandler(this.cacheExpire), + index = false; + if (cahceValue && typeof cahceValue === 'object' && cahceValue.length) { + cahceValue.map((item, i) => { + if (item.key === key) { + index = i; + } + }); + + if (index !== false) { + cahceValue.splice(index, 1); + } + this.cacheSetHandler(this.cacheExpire, cahceValue); + } + return this.cacheClearHandler(key); + } catch (e) { + return false; + } + } + + /** + * 清除过期缓存 + */ + clearOverdue() { + let cahceValue = this.cacheGetHandler(this.cacheExpire), + time = this.time(), + newBeOverdueValue = [], + newTagValue = []; + + if (cahceValue && typeof cahceValue === 'object' && cahceValue.length) { + cahceValue.map(item => { + if (item) { + if ((item.expire !== undefined && item.expire > time) || item.expire === 0) { + newTagValue.push(item); + } else { + newBeOverdueValue.push(item.key); + } + } + }); + } + //保存没有过期的缓存标签 + if (newTagValue.length !== cahceValue.length) { + this.cacheSetHandler(this.cacheExpire, newTagValue); + } + //删除过期缓存 + newBeOverdueValue.forEach(k => { + this.cacheClearHandler(k); + }) + } +} + + +export default new Cache; diff --git a/utils/request.js b/utils/request.js new file mode 100644 index 0000000..282b9e2 --- /dev/null +++ b/utils/request.js @@ -0,0 +1,87 @@ +import { + HTTP_REQUEST_URL, + HEADER, + TOKENNAME, + TIMEOUT +} from '@/config/app'; +import store from '../store'; +import UrlUtils from './urlUtils.js'; + +/** + * 发送请求 + */ +function baseRequest(url, method, data, { + noAuth = false, + noVerify = false +}) { + let Url = HTTP_REQUEST_URL; + let header = HEADER; + + HEADER['form-type'] = 'gzh'; + header = HEADER; + + + if (store.state.app.token) header[TOKENNAME] = 'Bearer ' + store.state.app.token; + return new Promise((reslove, reject) => { + if (uni.getStorageSync('locale')) { + header['Cb-lang'] = uni.getStorageSync('locale') + } + uni.request({ + url: url, + method: method || 'GET', + header: header, + data: data || {}, + timeout: TIMEOUT, + success: (res) => { + if (noVerify) + reslove(res.data, res); + else if (res.data.status == 200) + reslove(res.data, res); + else if ([110002, 110003, 110004].indexOf(res.data.status) !== -1) { + // #ifdef H5 + window.location.replace(`${HTTP_REQUEST_URL}/api/v2/routine/gzhLogin?back_url=${encodeURIComponent(UrlUtils.keepParams(window.location.href))}`); + // #endif + + reject(res.data); + } else if (res.data.status == 400 && res.data.msg !== '商户未绑定码牌') { + uni.showToast({ + title: res.data.msg, + icon: 'error' + }) + reject(res.data.msg || '系统错误'); + } else if (res.data.status == 100103) { + uni.showModal({ + title: '提示', + content: res.data.msg, + showCancel: false, + confirmText: 我知道了 + }); + } else + reject(res.data.msg || '系统错误'); + }, + fail: (msg) => { + console.log(msg) + let data = { + mag: '请求失败1', + status: 1 //1没网 + } + // #ifdef APP-PLUS + reject(data); + // #endif + // #ifndef APP-PLUS + reject('请求失败'); + // #endif + } + }) + }); +} + +const request = {}; + +['options', 'get', 'post', 'put', 'head', 'delete', 'trace', 'connect'].forEach((method) => { + request[method] = (api, data, opt) => baseRequest(api, method, data, opt || {}) +}); + + + +export default request; \ No newline at end of file diff --git a/utils/urlUtils.js b/utils/urlUtils.js new file mode 100644 index 0000000..ecfe894 --- /dev/null +++ b/utils/urlUtils.js @@ -0,0 +1,77 @@ +const UrlUtils = { + /** + * 清理URL(合并多余的?,规范参数分隔符) + * @param {string} url - 原始URL + * @returns {string} 清理后的URL + */ + clean: function(url) { + let cleanUrl = url.replace(/\?+/g, '?'); + const firstQuestionMarkIndex = cleanUrl.indexOf('?'); + + if (firstQuestionMarkIndex !== -1) { + const beforeParams = cleanUrl.substring(0, firstQuestionMarkIndex + 1); + const afterParams = cleanUrl.substring(firstQuestionMarkIndex + 1).replace(/\?/g, '&'); + cleanUrl = beforeParams + afterParams; + } + + return cleanUrl; + }, + + /** + * 保留URL中指定的参数(默认只保留merchant_id) + * @param {string} url - 原始URL + * @param {string[]} [paramsToKeep=['merchant_id']] - 需要保留的参数名数组 + * @returns {string} 简化后的URL + */ + keepParams: function(url, paramsToKeep = ['merchant_id']) { + // 先清理URL + const cleanedUrl = this.clean(url); + + try { + const urlObj = new URL(cleanedUrl); + const newSearchParams = new URLSearchParams(); + + // 遍历原始参数,只保留需要的 + urlObj.searchParams.forEach((value, key) => { + if (paramsToKeep.includes(key)) { + newSearchParams.append(key, value); + } + }); + + // 重建URL + urlObj.search = newSearchParams.toString(); + return urlObj.toString(); + } catch (e) { + // 如果URL解析失败(如缺少协议),回退到字符串处理 + const [basePart, queryPart] = cleanedUrl.split('?'); + if (!queryPart) return basePart; + + const keptParams = queryPart.split('&').filter(param => { + const [key] = param.split('='); + return paramsToKeep.includes(key); + }); + + return keptParams.length > 0 + ? `${basePart}?${keptParams.join('&')}` + : basePart; + } + } +}; + +export default UrlUtils + + +// // 使用示例 +// const dirtyUrl = "http://10.210.254.149:8081/h5_pay/??merchant_id=1&token=xxx&expires_time=123??is_all_api=1"; + +// // 1. 只清理URL +// console.log(UrlUtils.clean(dirtyUrl)); +// // 输出: "http://10.210.254.149:8081/h5_pay/?merchant_id=1&token=xxx&expires_time=123&is_all_api=1" + +// // 2. 清理并只保留merchant_id +// console.log(UrlUtils.keepParams(dirtyUrl)); +// // 输出: "http://10.210.254.149:8081/h5_pay/?merchant_id=1" + +// // 3. 清理并保留多个参数 +// console.log(UrlUtils.keepParams(dirtyUrl, ['merchant_id', 'expires_time'])); +// // 输出: "http://10.210.254.149:8081/h5_pay/?merchant_id=1&expires_time=123" diff --git a/utils/util.js b/utils/util.js new file mode 100644 index 0000000..8871b34 --- /dev/null +++ b/utils/util.js @@ -0,0 +1,1278 @@ +// +---------------------------------------------------------------------- +// | CRMEB [ CRMEB赋能开发者,助力企业发展 ] +// +---------------------------------------------------------------------- +// | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved. +// +---------------------------------------------------------------------- +// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权 +// +---------------------------------------------------------------------- +// | Author: CRMEB Team +// +---------------------------------------------------------------------- + +export default { + /** + * opt object | string + * to_url object | string + * 例: + * this.Tips('/pages/test/test'); 跳转不提示 + * this.Tips({title:'提示'},'/pages/test/test'); 提示并跳转 + * this.Tips({title:'提示'},{tab:1,url:'/pages/index/index'}); 提示并跳转值table上 + * tab=1 一定时间后跳转至 table上 + * tab=2 一定时间后跳转至非 table上 + * tab=3 一定时间后返回上页面 + * tab=4 关闭所有页面,打开到应用内的某个页面 + * tab=5 关闭当前页面,跳转到应用内的某个页面 + */ + Tips: function(opt, to_url) { + if (typeof opt == 'string') { + to_url = opt; + opt = {}; + } + let title = opt.title || '', + icon = opt.icon || 'none', + endtime = opt.endtime || 2000, + success = opt.success; + if (title) uni.showToast({ + title: title, + icon: icon, + duration: endtime, + success + }) + if (to_url != undefined) { + if (typeof to_url == 'object') { + let tab = to_url.tab || 1, + url = to_url.url || ''; + switch (tab) { + case 1: + //一定时间后跳转至 table + setTimeout(function() { + uni.switchTab({ + url: url + }) + }, endtime); + break; + case 2: + //跳转至非table页面 + setTimeout(function() { + uni.navigateTo({ + url: url, + }) + }, endtime); + break; + case 3: + //返回上页面 + setTimeout(function() { + // #ifndef H5 + uni.navigateBack({ + delta: parseInt(url), + }) + // #endif + // #ifdef H5 + history.back(); + // #endif + }, endtime); + break; + case 4: + //关闭所有页面,打开到应用内的某个页面 + setTimeout(function() { + uni.reLaunch({ + url: url, + }) + }, endtime); + break; + case 5: + //关闭当前页面,跳转到应用内的某个页面 + setTimeout(function() { + uni.redirectTo({ + url: url, + }) + }, endtime); + break; + } + + } else if (typeof to_url == 'function') { + setTimeout(function() { + to_url && to_url(); + }, endtime); + } else { + //没有提示时跳转不延迟 + setTimeout(function() { + uni.navigateTo({ + url: to_url, + }) + }, title ? endtime : 0); + } + } + }, + /** + * 移除数组中的某个数组并组成新的数组返回 + * @param array array 需要移除的数组 + * @param int index 需要移除的数组的键值 + * @param string | int 值 + * @return array + * + */ + ArrayRemove: function(array, index, value) { + const valueArray = []; + if (array instanceof Array) { + for (let i = 0; i < array.length; i++) { + if (typeof index == 'number' && array[index] != i) { + valueArray.push(array[i]); + } else if (typeof index == 'string' && array[i][index] != value) { + valueArray.push(array[i]); + } + } + } + return valueArray; + }, + /** + * 生成海报获取文字 + * @param string text 为传入的文本 + * @param int num 为单行显示的字节长度 + * @return array + */ + textByteLength: function(text, num) { + let strLength = 0; + let rows = 1; + let str = 0; + let arr = []; + for (let j = 0; j < text.length; j++) { + if (text.charCodeAt(j) > 255) { + strLength += 2; + if (strLength > rows * num) { + strLength++; + arr.push(text.slice(str, j)); + str = j; + rows++; + } + } else { + strLength++; + if (strLength > rows * num) { + arr.push(text.slice(str, j)); + str = j; + rows++; + } + } + } + arr.push(text.slice(str, text.length)); + return [strLength, arr, rows] // [处理文字的总字节长度,每行显示内容的数组,行数] + }, + + /** + * 获取分享海报 + * @param array arr2 海报素材 + * @param string store_name 素材文字 + * @param string price 价格 + * @param string ot_price 原始价格 + * @param function successFn 回调函数 + * + * + */ + PosterCanvas: function(arr2, store_name, price, ot_price, successFn) { + let that = this; + uni.showLoading({ + title: i18n.t(`海报生成中`), + mask: true + }); + const ctx = uni.createCanvasContext('myCanvas'); + ctx.clearRect(0, 0, 0, 0); + + + /** + * 只能获取合法域名下的图片信息,本地调试无法获取 + * + */ + ctx.fillStyle = '#fff'; + ctx.fillRect(0, 0, 750, 1250); + uni.getImageInfo({ + src: arr2[0], + success: function(res) { + const WIDTH = res.width; + const HEIGHT = res.height; + // ctx.drawImage(arr2[0], 0, 0, WIDTH, 1050); + ctx.drawImage(arr2[1], 0, 0, WIDTH, WIDTH); + ctx.save(); + let r = 110; + let d = r * 2; + let cx = 480; + let cy = 790; + ctx.arc(cx + r, cy + r, r, 0, 2 * Math.PI); + // ctx.clip(); + ctx.drawImage(arr2[2], cx, cy, d, d); + ctx.restore(); + const CONTENT_ROW_LENGTH = 20; + let [contentLeng, contentArray, contentRows] = that.textByteLength(store_name, + CONTENT_ROW_LENGTH); + if (contentRows > 2) { + contentRows = 2; + let textArray = contentArray.slice(0, 2); + textArray[textArray.length - 1] += '……'; + contentArray = textArray; + } + ctx.setTextAlign('left'); + ctx.setFontSize(36); + ctx.setFillStyle('#000'); + // let contentHh = 36 * 1.5; + let contentHh = 36; + for (let m = 0; m < contentArray.length; m++) { + if (m) { + ctx.fillText(contentArray[m], 50, 1000 + contentHh * m + 18, 1100); + } else { + ctx.fillText(contentArray[m], 50, 1000 + contentHh * m, 1100); + } + } + ctx.setTextAlign('left') + ctx.setFontSize(72); + ctx.setFillStyle('#DA4F2A'); + ctx.fillText(i18n.t(`¥`) + price, 40, 820 + contentHh); + + ctx.setTextAlign('left') + ctx.setFontSize(36); + ctx.setFillStyle('#999'); + + if (ot_price) { + ctx.fillText(i18n.t(`¥`) + ot_price, 50, 876 + contentHh); + var underline = function(ctx, text, x, y, size, color, thickness, offset) { + var width = ctx.measureText(text).width; + switch (ctx.textAlign) { + case "center": + x -= (width / 2); + break; + case "right": + x -= width; + break; + } + + y += size + offset; + + ctx.beginPath(); + ctx.strokeStyle = color; + ctx.lineWidth = thickness; + ctx.moveTo(x, y); + ctx.lineTo(x + width, y); + ctx.stroke(); + } + underline(ctx, i18n.t(`¥`) + ot_price, 55, 865, 36, '#999', 2, 0) + } + ctx.setTextAlign('left') + ctx.setFontSize(28); + ctx.setFillStyle('#999'); + ctx.fillText(i18n.t(`长按或扫描查看`), 490, 1030 + contentHh); + ctx.draw(true, function() { + uni.canvasToTempFilePath({ + canvasId: 'myCanvas', + fileType: 'png', + destWidth: WIDTH, + destHeight: HEIGHT, + success: function(res) { + uni.hideLoading(); + successFn && successFn(res.tempFilePath); + } + }) + }); + }, + fail: function(err) { + uni.hideLoading(); + that.Tips({ + title: i18n.t(`无法获取图片信息`) + }); + } + }) + }, + /** + * 获取砍价/拼团海报 + * @param array arr2 海报素材 背景图 + * @param string store_name 素材文字 + * @param string price 价格 + * @param string ot_price 原始价格 + * @param function successFn 回调函数 + * + * + */ + bargainPosterCanvas: function(arr2, title, label, msg, price, wd, hg, successFn) { + let that = this; + const ctx = uni.createCanvasContext('myCanvas'); + ctx.clearRect(0, 0, 0, 0); + /** + * 只能获取合法域名下的图片信息,本地调试无法获取 + * + */ + ctx.fillStyle = '#fff'; + ctx.fillRect(0, 0, wd * 2, hg * 2); + uni.getImageInfo({ + src: arr2[0], + success: function(res) { + const WIDTH = res.width; + const HEIGHT = res.height; + ctx.drawImage(arr2[0], 0, 0, wd, hg); + + // 保证在不同机型对应坐标准确 + let labelx = 0.6500 //标签x + let labely = 0.166 //标签y + let pricex = 0.1857 //价格x + let pricey = 0.180 //价格x + let codex = 0.385 //二维码 + let codey = 0.77 + let picturex = 0.1571 //商品图左上点 + let picturey = 0.2916 + let picturebx = 0.6857 //商品图右下点 + let pictureby = 0.4316 + let msgx = 0.1036 //msg + let msgy = 0.2306 + let codew = 0.25 + ctx.drawImage(arr2[1], wd * picturex, hg * picturey, wd * picturebx, hg * pictureby); + ctx.drawImage(arr2[2], wd * codex, hg * codey, wd * codew, wd * codew); + ctx.save(); + //标题 + const CONTENT_ROW_LENGTH = 32; + let [contentLeng, contentArray, contentRows] = that.textByteLength(title, + CONTENT_ROW_LENGTH); + if (contentRows > 2) { + contentRows = 2; + let textArray = contentArray.slice(0, 2); + textArray[textArray.length - 1] += '…'; + contentArray = textArray; + } + ctx.setTextAlign('left'); + ctx.setFillStyle('#000'); + if (contentArray.length < 2) { + ctx.setFontSize(22); + } else { + ctx.setFontSize(20); + } + let contentHh = 8; + for (let m = 0; m < contentArray.length; m++) { + if (m) { + ctx.fillText(contentArray[m], 20, 35 + contentHh * m + 18, 1100); + } else { + ctx.fillText(contentArray[m], 20, 35, 1100); + } + } + // 标签内容 + ctx.setTextAlign('left') + ctx.setFontSize(16); + ctx.setFillStyle('#FFF'); + ctx.fillText(label, wd * labelx, hg * labely); + ctx.save(); + // 价格 + ctx.setFillStyle('red'); + ctx.setFontSize(26); + ctx.fillText(price, wd * pricex, hg * pricey); + ctx.save(); + // msg + ctx.setFillStyle('#333'); + ctx.setFontSize(16); + ctx.fillText(msg, wd * msgx, hg * msgy); + ctx.save(); + ctx.draw(true, () => { + uni.canvasToTempFilePath({ + canvasId: 'myCanvas', + fileType: 'png', + quality: 1, + success: (res) => { + successFn && successFn(res.tempFilePath); + uni.hideLoading(); + } + }) + }); + }, + fail: function(err) { + uni.hideLoading(); + that.Tips({ + title: i18n.t(`无法获取图片信息`) + }); + } + }) + }, + /** + * 用户信息分享海报 + * @param array arr2 海报素材 1背景 0二维码 + * @param string nickname 昵称 + * @param string sitename 价格 + * @param function successFn 回调函数 + * + * + */ + userPosterCanvas: function(arr2, nickname, sitename, index, w, h, uid, successFn) { + let that = this; + const ctx = uni.createCanvasContext('myCanvas' + index); + ctx.clearRect(0, 0, 0, 0); + /** + * 只能获取合法域名下的图片信息,本地调试无法获取 + * + */ + uni.getImageInfo({ + src: arr2[1], + success: function(res) { + const WIDTH = res.width; + const HEIGHT = res.height; + ctx.fillStyle = '#fff'; + ctx.fillRect(0, 0, w, h); + ctx.drawImage(arr2[1], 0, 0, w, h); + ctx.setTextAlign('left') + ctx.setFontSize(12); + ctx.setFillStyle('#333'); + + // x:240 y:426 + let codex = 0.1906 + let codey = 0.7746 + let codeSize = 0.21666 + let namex = 0.4283 + let namey = 0.8215 + let markx = 0.4283 + let marky = 0.8685 + ctx.drawImage(arr2[0], w * codex, h * codey, w * codeSize, w * codeSize); + if (w < 270) { + ctx.setFontSize(8); + } else { + ctx.setFontSize(10); + } + ctx.fillText(nickname, w * namex, h * namey-5); + if (w < 270) { + ctx.setFontSize(8); + } else { + ctx.setFontSize(10); + } + console.log(w, markx, w * markx) + ctx.fillText(i18n.t(`邀请您加入`) + sitename, w * markx, h * marky-11); + ctx.fillText(i18n.t(`邀请码: ${uid}`), w * markx, h * marky+8); + ctx.save(); + ctx.draw(true, function() { + uni.canvasToTempFilePath({ + canvasId: 'myCanvas' + index, + fileType: 'png', + quality: 1, + success: function(res) { + successFn && successFn(res.tempFilePath); + } + }) + }); + }, + fail: function(err) { + console.log(err) + uni.hideLoading(); + that.Tips({ + title: i18n.t(`无法获取图片信息`) + }); + } + }) + }, + + /* + * 判断身份证是否过期 + */ + isIDCardExpired: function(validityPeriod, currentDate = new Date()) { + let that = this; + // 检查有效期格式是否正确 + if (!validityPeriod || !validityPeriod.includes('-')) { + that.Tips({ + title: '识别身份证有效期格式错误' + }); + } + + // 拆分有效期(起始日期和截止日期) + const [startDateStr, endDateStr] = validityPeriod.split('-'); + + // 解析日期字符串为 Date 对象 + const parseDate = (dateStr) => { + const year = parseInt(dateStr.slice(0, 4), 10); + const month = parseInt(dateStr.slice(4, 6), 10) - 1; // 月份从 0 开始 + const day = parseInt(dateStr.slice(6, 8), 10); + return new Date(year, month, day); + }; + + const startDate = parseDate(startDateStr); + const endDate = parseDate(endDateStr); + + // 检查当前日期是否在有效期内 + return currentDate > endDate || currentDate < startDate; + }, + + /* + * 单图上传 + * @param object opt + * @param callable successCallback 成功执行方法 data + * @param callable errorCallback 失败执行方法 + */ + uploadImageOne: function(opt, successCallback, errorCallback) { + let that = this; + if (typeof opt === 'string') { + let url = opt; + opt = {}; + opt.url = url; + } + let count = opt.count || 1, + sizeType = opt.sizeType || ['compressed'], + sourceType = opt.sourceType || ['album', 'camera'], + is_load = opt.is_load || true, + uploadUrl = opt.url || '', + inputName = opt.name || 'pics', + fileType = opt.fileType || 'image'; + uni.chooseImage({ + count: count, //最多可以选择的图片总数 + sizeType: sizeType, // 可以指定是原图还是压缩图,默认二者都有 + sourceType: sourceType, // 可以指定来源是相册还是相机,默认二者都有 + success: function(res) { + //启动上传等待中... + uni.showLoading({ + title: i18n.t(`图片上传中`), + }); + uni.uploadFile({ + url: HTTP_REQUEST_URL + '/api/' + uploadUrl, + filePath: res.tempFilePaths[0], + fileType: fileType, + name: inputName, + formData: { + 'filename': inputName + }, + header: { + // #ifdef MP + "Content-Type": "multipart/form-data", + // #endif + [TOKENNAME]: 'Bearer ' + store.state.app.token + }, + success: function(res) { + uni.hideLoading(); + if (res.statusCode == 403) { + that.Tips({ + title: res.data + }); + } else { + let data = res.data ? JSON.parse(res.data) : {}; + if (data.status == 200) { + successCallback && successCallback(data) + } else { + errorCallback && errorCallback(data); + that.Tips({ + title: data.msg + }); + } + } + }, + fail: function(res) { + console.log(res) + uni.hideLoading(); + that.Tips({ + title: i18n.t(`上传图片失败`) + }); + } + }) + } + }) + }, + + compressImageToTargetSize: function(opt, successCallback, errorCallback, sizeCallback) { + let that = this; + if (typeof opt === 'string') { + let url = opt; + opt = {}; + opt.url = url; + } + let count = opt.count || 1, + sizeType = opt.sizeType || ['compressed'], + sourceType = opt.sourceType || ['album', 'camera'], + is_load = opt.is_load || true, + uploadUrl = opt.url || '', + inputName = opt.name || 'pics', + fileType = opt.fileType || 'image'; + uni.chooseImage({ + count: count, + sizeType: sizeType, + sourceType: sourceType, + success: function(res) { + //启动上传等待中... + const tempFilePaths = res.tempFilePaths[0]; // 获取到图片的临时路径 + uni.compressImage({ + src: tempFilePaths, + quality: 80, + success: res => { + uploadImg(res.tempFilePath) + } + }) + return + compress(tempFilePaths, 800, 600); // 调用压缩函数,指定宽度和高度 + }, + fail: function(res) { + var title = res.errMsg; + console.log(title, '111111111') + if (title == 'chooseImage:fail cancel') { + title = '取消选择照片' + } + + if (title == 'chooseImage:fail:systempermission denied') { + title = '请检查相册和相机权限' + } + + if (title == 'chooseImage:fail privacy permission is not authorized') { + title = '获取照片隐私权限失败' + } + + if (title == 'chooseImage:fail privacy permission is not authorized in gap') { + title = '获取照片隐私权限失败' + } + + that.Tips({ + title: title + }); + } + }) + + // 废弃 质量太低 + function compress(src, width, height) { + const that = this; + uni.getImageInfo({ + src: src, + success: function (infoRes) { + const { width: imgWidth, height: imgHeight } = infoRes; + const scale = Math.min(width / imgWidth, height / imgHeight); // 计算缩放比例 + const newWidth = imgWidth * scale; + const newHeight = imgHeight * scale; + const ctx = uni.createCanvasContext('myCanvas', that); // 创建canvas上下文 + ctx.drawImage(src, 0, 0, newWidth, newHeight); // 绘制图片到canvas上 + setTimeout(() => { + ctx.draw(true, () => { // 完成绘制后,导出图片 + uni.canvasToTempFilePath({ + canvasId: 'myCanvas', + success: function (res) { + console.log(res.tempFilePath) // 设置压缩后的图片路径 + uploadImg(res.tempFilePath) + }, + fail: function (err) { + console.error(err); + } + }); + }); + }, 1000) + } + }); + } + + function uploadImg(filePath) { + uni.uploadFile({ + url: HTTP_REQUEST_URL + '/api/' + uploadUrl, + filePath, + fileType: fileType, + name: inputName, + formData: { + 'filename': inputName + }, + header: { + // #ifdef MP + "Content-Type": "multipart/form-data", + // #endif + [TOKENNAME]: 'Bearer ' + store.state.app.token + }, + success: function(res) { + uni.hideLoading(); + if (res.statusCode == 403) { + that.Tips({ + title: res.data + }); + } else { + let data = res.data ? JSON.parse(res.data) : {}; + if (data.status == 200) { + successCallback && successCallback(data) + } else { + errorCallback && errorCallback(data); + that.Tips({ + title: data.msg + }); + } + } + }, + fail: function(res) { + console.log(res) + uni.hideLoading(); + that.Tips({ + title: i18n.t(`上传图片失败`) + }); + } + }) + } + }, + + /* + * 单图上传压缩版 + * @param object opt + * @param callable successCallback 成功执行方法 data + * @param callable errorCallback 失败执行方法 + */ + uploadImageChange: function(opt, successCallback, errorCallback, sizeCallback) { + let that = this; + if (typeof opt === 'string') { + let url = opt; + opt = {}; + opt.url = url; + } + let count = opt.count || 1, + sizeType = opt.sizeType || ['compressed'], + sourceType = opt.sourceType || ['album', 'camera'], + is_load = opt.is_load || true, + uploadUrl = opt.url || '', + inputName = opt.name || 'pics', + fileType = opt.fileType || 'image'; + uni.chooseImage({ + count: count, //最多可以选择的图片总数 + sizeType: sizeType, // 可以指定是原图还是压缩图,默认二者都有 + sourceType: sourceType, // 可以指定来源是相册还是相机,默认二者都有 + success: function(res) { + //启动上传等待中... + let imgSrc + uni.getImageInfo({ + src: res.tempFilePaths[0], + success(ress) { + uni.showLoading({ + title: i18n.t(`图片上传中`), + }); + if (res.tempFiles[0].size <= 2097152) { + uploadImg(ress.path) + return + } + // uploadImg(canvasPath.tempFilePath) + let canvasWidth, canvasHeight, xs, maxWidth = 750 + xs = ress.width / ress.height // 宽高比例 + if (ress.width > maxWidth) { + canvasWidth = maxWidth // 这里是最大限制宽度 + canvasHeight = maxWidth / xs + } else { + canvasWidth = ress.width + canvasHeight = ress.height + } + sizeCallback && sizeCallback({ + w: canvasWidth, + h: canvasHeight + }) + let canvas = uni.createCanvasContext('canvas'); + canvas.width = canvasWidth + canvas.height = canvasHeight + canvas.clearRect(0, 0, canvasWidth, canvasHeight); + canvas.drawImage(ress.path, 0, 0, canvasWidth, canvasHeight) + canvas.save(); + // 这里的画布drawImage是一种异步属性 可能存在未绘制全就执行了draw的问题 so添加延迟 + setTimeout(e => { + canvas.draw(true, () => { + uni.canvasToTempFilePath({ + canvasId: 'canvas', + fileType: 'JPEG', + destWidth: canvasWidth, + destHeight: canvasHeight, + quality: 0.7, + success: function(canvasPath) { + uploadImg(canvasPath + .tempFilePath) + } + }) + }); + }, 200) + + + } + }) + }, + fail: function(res) { + var title = res.errMsg; + console.log(title, '111111111') + if (title == 'chooseImage:fail cancel') { + title = '取消选择照片' + } + + if (title == 'chooseImage:fail:systempermission denied') { + title = '请检查相册和相机权限' + } + + if (title == 'chooseImage:fail privacy permission is not authorized') { + title = '获取照片隐私权限失败' + } + + if (title == 'chooseImage:fail privacy permission is not authorized in gap') { + title = '获取照片隐私权限失败' + } + + that.Tips({ + title: title + }); + } + }) + + function uploadImg(filePath) { + uni.uploadFile({ + url: HTTP_REQUEST_URL + '/api/' + uploadUrl, + filePath, + fileType: fileType, + name: inputName, + formData: { + 'filename': inputName + }, + header: { + // #ifdef MP + "Content-Type": "multipart/form-data", + // #endif + [TOKENNAME]: 'Bearer ' + store.state.app.token + }, + success: function(res) { + uni.hideLoading(); + if (res.statusCode == 403) { + that.Tips({ + title: res.data + }); + } else { + let data = res.data ? JSON.parse(res.data) : {}; + if (data.status == 200) { + successCallback && successCallback(data) + } else { + errorCallback && errorCallback(data); + that.Tips({ + title: data.msg + }); + } + } + }, + fail: function(res) { + console.log(res) + uni.hideLoading(); + that.Tips({ + title: i18n.t(`上传图片失败`) + }); + } + }) + } + }, + /** + * 小程序头像获取上传 + * @param uploadUrl 上传接口地址 + * @param filePath 上传文件路径 + * @param successCallback success回调 + * @param errorCallback err回调 + */ + uploadImgs(uploadUrl, filePath, successCallback, errorCallback) { + let that = this; + uni.uploadFile({ + url: HTTP_REQUEST_URL + '/api/' + + uploadUrl, + filePath: filePath, + fileType: 'image', + name: 'pics', + formData: { + 'filename': 'pics' + }, + header: { + // #ifdef MP + "Content-Type": "multipart/form-data", + // #endif + [TOKENNAME]: 'Bearer ' + store.state + .app.token + }, + success: (res) => { + uni.hideLoading(); + if (res.statusCode == 403) { + that.Tips({ + title: res.data + }); + } else { + let data = res.data ? JSON + .parse(res.data) : {}; + if (data.status == 200) { + successCallback && + successCallback( + data) + } else { + errorCallback && + errorCallback(data); + that.Tips({ + title: data + .msg + }); + } + } + }, + fail: (err) => { + uni.hideLoading(); + console.log(res) + that.Tips({ + title: i18n.t( + `上传图片失败`) + }); + } + }) + }, + /** + * 小程序比较版本信息 + * @param v1 当前版本 + * @param v2 进行比较的版本 + * @return boolen + * + */ + compareVersion(v1, v2) { + v1 = v1.split('.') + v2 = v2.split('.') + const len = Math.max(v1.length, v2.length) + + while (v1.length < len) { + v1.push('0') + } + while (v2.length < len) { + v2.push('0') + } + + for (let i = 0; i < len; i++) { + const num1 = parseInt(v1[i]) + const num2 = parseInt(v2[i]) + + if (num1 > num2) { + return 1 + } else if (num1 < num2) { + return -1 + } + } + + return 0 + }, + /* + * 获取当前时间 + */ + getNowTime() { + let today = new Date(); + let year = today.getFullYear(); // 获取当前年份 + let month = today.getMonth() + 1; // 获取当前月份(注意:月份从 0 开始计数,所以需要加 1) + let day = today.getDate(); // 获取当前日(几号) + let hour = today.getHours(); // 获取当前小时 + let minute = today.getMinutes(); // 获取当前分钟 + let second = today.getSeconds(); // 获取当前秒钟 + + // 格式化输出当前时间 + let nowTime = year + '/' + month + '/' + day + ' ' + hour + ':' + minute + ':' + second; + return nowTime + }, + /** + * 处理服务器扫码带进来的参数 + * @param string param 扫码携带参数 + * @param string k 整体分割符 默认为:& + * @param string p 单个分隔符 默认为:= + * @return object + * + */ + // #ifdef MP + getUrlParams: function(param, k, p) { + if (typeof param != 'string') return {}; + k = k ? k : '&'; //整体参数分隔符 + p = p ? p : '='; //单个参数分隔符 + var value = {}; + if (param.indexOf(k) !== -1) { + param = param.split(k); + for (var val in param) { + if (param[val].indexOf(p) !== -1) { + var item = param[val].split(p); + value[item[0]] = item[1]; + } + } + } else if (param.indexOf(p) !== -1) { + var item = param.split(p); + value[item[0]] = item[1]; + } else { + return param; + } + return value; + }, + // #endif + /* + * 合并数组 + */ + SplitArray(list, sp) { + if (typeof list != 'object') return []; + if (sp === undefined) sp = []; + for (var i = 0; i < list.length; i++) { + sp.push(list[i]); + } + return sp; + }, + trim(backUrlCRshlcICwGdGY) { + return String.prototype.trim.call(backUrlCRshlcICwGdGY); + }, + $h: { + //除法函数,用来得到精确的除法结果 + //说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。 + //调用:$h.Div(arg1,arg2) + //返回值:arg1除以arg2的精确结果 + Div: function(arg1, arg2) { + arg1 = parseFloat(arg1); + arg2 = parseFloat(arg2); + var t1 = 0, + t2 = 0, + r1, r2; + try { + t1 = arg1.toString().split(".")[1].length; + } catch (e) {} + try { + t2 = arg2.toString().split(".")[1].length; + } catch (e) {} + r1 = Number(arg1.toString().replace(".", "")); + r2 = Number(arg2.toString().replace(".", "")); + return this.Mul(r1 / r2, Math.pow(10, t2 - t1)); + }, + //加法函数,用来得到精确的加法结果 + //说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。 + //调用:$h.Add(arg1,arg2) + //返回值:arg1加上arg2的精确结果 + Add: function(arg1, arg2) { + arg2 = parseFloat(arg2); + var r1, r2, m; + try { + r1 = arg1.toString().split(".")[1].length + } catch (e) { + r1 = 0 + } + try { + r2 = arg2.toString().split(".")[1].length + } catch (e) { + r2 = 0 + } + m = Math.pow(100, Math.max(r1, r2)); + return (this.Mul(arg1, m) + this.Mul(arg2, m)) / m; + }, + //减法函数,用来得到精确的减法结果 + //说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的减法结果。 + //调用:$h.Sub(arg1,arg2) + //返回值:arg1减去arg2的精确结果 + Sub: function(arg1, arg2) { + arg1 = parseFloat(arg1); + arg2 = parseFloat(arg2); + var r1, r2, m, n; + try { + r1 = arg1.toString().split(".")[1].length + } catch (e) { + r1 = 0 + } + try { + r2 = arg2.toString().split(".")[1].length + } catch (e) { + r2 = 0 + } + m = Math.pow(10, Math.max(r1, r2)); + //动态控制精度长度 + n = (r1 >= r2) ? r1 : r2; + return ((this.Mul(arg1, m) - this.Mul(arg2, m)) / m).toFixed(n); + }, + //乘法函数,用来得到精确的乘法结果 + //说明:javascript的乘法结果会有误差,在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。 + //调用:$h.Mul(arg1,arg2) + //返回值:arg1乘以arg2的精确结果 + Mul: function(arg1, arg2) { + arg1 = parseFloat(arg1); + arg2 = parseFloat(arg2); + var m = 0, + s1 = arg1.toString(), + s2 = arg2.toString(); + try { + m += s1.split(".")[1].length + } catch (e) {} + try { + m += s2.split(".")[1].length + } catch (e) {} + return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m); + }, + }, + // 获取地理位置; + $L: { + async getLocation() { + // #ifdef APP-PLUS + let status = await this.checkPermission(); + if (status !== 1) { + return; + } + // #endif + // #ifdef MP-WEIXIN || MP-TOUTIAO || MP-QQ + let status = await this.getSetting(); + if (status === 2) { + this.openSetting(); + return; + } + // #endif + + this.doGetLocation(); + }, + doGetLocation() { + uni.getLocation({ + success: (res) => { + uni.removeStorageSync('CACHE_LONGITUDE'); + uni.removeStorageSync('CACHE_LATITUDE'); + uni.setStorageSync('CACHE_LONGITUDE', res.longitude); + uni.setStorageSync('CACHE_LATITUDE', res.latitude); + }, + fail: (err) => { + // #ifdef MP-BAIDU + if (err.errCode === 202 || err.errCode === 10003) { // 202模拟器 10003真机 user deny + this.openSetting(); + } + // #endif + // #ifndef MP-BAIDU + if (err.errMsg.indexOf("auth deny") >= 0) { + uni.showToast({ + title: i18n.t(`访问位置被拒绝`) + }) + } else { + uni.showToast({ + title: err.errMsg + }) + } + // #endif + } + }) + }, + getSetting: function() { + return new Promise((resolve, reject) => { + uni.getSetting({ + success: (res) => { + if (res.authSetting['scope.userLocation'] === undefined) { + resolve(0); + return; + } + if (res.authSetting['scope.userLocation']) { + resolve(1); + } else { + resolve(2); + } + } + }); + }); + }, + openSetting: function() { + uni.openSetting({ + success: (res) => { + if (res.authSetting && res.authSetting['scope.userLocation']) { + this.doGetLocation(); + } + }, + fail: (err) => {} + }) + }, + async checkPermission() { + let status = permision.isIOS ? await permision.requestIOS('location') : + await permision.requestAndroid('android.permission.ACCESS_FINE_LOCATION'); + + if (status === null || status === 1) { + status = 1; + } else if (status === 2) { + uni.showModal({ + content: i18n.t(`系统定位已关闭`), + confirmText: i18n.t(`确定`), + showCancel: false, + success: function(res) {} + }) + } else if (status.code) { + uni.showModal({ + content: status.message + }) + } else { + uni.showModal({ + content: i18n.t(`需要定位权限`), + confirmText: i18n.t(`确定`), + success: function(res) { + if (res.confirm) { + permision.gotoAppSetting(); + } + } + }) + } + return status; + }, + }, + + /** + * 跳转路径封装函数 + * @param url 跳转路径 + */ + JumpPath: function(url) { + let arr = url.split('@APPID='); + if (arr.length > 1) { + //#ifdef MP + uni.navigateToMiniProgram({ + appId: arr[arr.length - 1], // 此为生活缴费appid + path: arr[0], // 此为生活缴费首页路径 + envVersion: "release", + success: res => { + console.log("打开成功", res); + }, + fail: err => {} + }) + //#endif + //#ifndef MP + this.Tips({ + title: 'h5与app端不支持跳转外部小程序' + }); + //#endif + } else { + console.log(url,'----------'); + if (url.indexOf("http") != -1) { + uni.navigateTo({ + url: `/pages/annex/web_view/index?url=${encodeURIComponent(url)}` + }); + } else { + if (['/pages/goods_cate/goods_cate', '/pages/order_addcart/order_addcart', '/pages/user/index', + '/pages/index/index' + ] + .indexOf(url) == -1) { + uni.navigateTo({ + url + }) + } else { + uni.switchTab({ + url + }) + } + } + } + }, + /** + * 打开内置地图 + * @param {type} + */ + openLocation:function(para){ + console.log(para); + uni.openLocation({ + ...para, + success: function () { + console.log('success'); + }, + fail:function(err){ + console.log(err); + } + }); + }, + + + /** + * px转rpx + */ + pxToRpx:function(px){ + // 获取屏幕宽度 + const screenWidth = uni.getSystemInfoSync().screenWidth; + // 使用示例 + const pxValue = 50; + const rpxValue = (px / (screenWidth / 750)); + return rpxValue; + }, + + /** + * 获取月份tab + */ + getLastMonths: function(startDateStr) { + const result = []; + let date; + if (startDateStr) { + const [year, month] = startDateStr.split('-').map(Number); + date = new Date(year, month - 1); + } else { + date = new Date(); + } + + date.setDate(1); + for (let i = 0; i < 4; i++) { + const year = date.getFullYear(); + const month = String(date.getMonth()).padStart(2, '0'); + result.push({ name: `${year}-${month}` }); + + date.setMonth(date.getMonth() - 1); + } + + return result; + } +} diff --git a/utils/utils.js b/utils/utils.js new file mode 100644 index 0000000..8b6a146 --- /dev/null +++ b/utils/utils.js @@ -0,0 +1,58 @@ +/* + * @LastEditors: whitechiina 1293616053@qq.com + * @LastEditTime: 2025-07-31 13:42:48 + */ +/** + * 获取URL参数工具函数 + * @param {string|array} keys - 要获取的参数名,可以是字符串或数组 + * @param {any} defaultValue - 当参数不存在时的默认值 + * @returns {any} 返回参数值或参数对象 + */ + +const getUrlParam = function(keys, defaultValue = undefined) { + // 获取原始查询字符串(包含开头的'?') + let queryString = window.location.search; + + // 预处理:将第一个问号后的所有问号替换为'&' + if (queryString.includes('?')) { + // 移除开头的'?',然后处理多个问号 + let queryWithoutQuestion = queryString.substring(1); + // 将多个问号替换为& + queryWithoutQuestion = queryWithoutQuestion.replace(/\?/g, '&'); + queryString = '?' + queryWithoutQuestion; + } + + // 解析处理后的查询字符串 + const params = new URLSearchParams(queryString); + + // 1. 未传入keys:返回全部参数组成的对象 + if (!keys) { + const result = {}; + for (const [key, value] of params.entries()) { + result[key] = decodeURIComponent(value); + } + return result; + } + + // 2. 传入数组:返回包含这些参数的对象 + if (Array.isArray(keys)) { + return keys.reduce((result, key) => { + result[key] = params.has(key) + ? decodeURIComponent(params.get(key)) + : defaultValue; + return result; + }, {}); + } + + // 3. 传入字符串:返回单个参数值 + if (typeof keys === 'string') { + return params.has(keys) + ? decodeURIComponent(params.get(keys)) + : defaultValue; + } + + // 4. 无效keys类型返回默认值 + return defaultValue; +} + +export default getUrlParam; \ No newline at end of file