首页静态完成

This commit is contained in:
魏啾
2024-04-01 16:31:14 +08:00
parent a9b9da0bbf
commit 653da2ad81
54 changed files with 6265 additions and 687 deletions

View File

@@ -1,16 +1,23 @@
{ // launch.json 配置了启动调试时相关设置configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
// launchtype项可配置值为local或remote, local代表前端连本地云函数remote代表前端连云端云函数
"version": "0.0",
"configurations": [{
"default" :
{
"launchtype" : "local"
},
"mp-weixin" :
{
"launchtype" : "local"
},
"type" : "uniCloud"
}
{
// launch.json 配置了启动调试时相关设置configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
// launchtype项可配置值为local或remote, local代表前端连本地云函数remote代表前端连云端云函数
"version" : "0.0",
"configurations" : [
{
"app-plus" : {
"launchtype" : "local"
},
"default" : {
"launchtype" : "local"
},
"mp-weixin" : {
"launchtype" : "local"
},
"type" : "uniCloud"
},
{
"playground" : "custom",
"type" : "uni-app:app-android"
}
]
}

70
App.vue
View File

@@ -1,13 +1,81 @@
<script>
export default {
onLaunch: function() {
// console.log('App Launch');
// #ifdef MP-WEIXIN
uni.cache.set('menuInfo', uni.getMenuButtonBoundingClientRect());
// #endif
},
onShow: function() {
this.$store.dispatch("HeightActions"); //获取随时获取页面的高度
// console.log('App Show');
try {
// #ifdef APP-PLUS
uni.getSystemInfo({
success: (res) => {
let system = res;
if (system.platform == 'ios') {
console.log('ios', 64);
uni.request({
url: uni.conf.baseUrl + '/api/systemConfig/updateSystemVersion?platformCode=' + 1,
method: 'POST',
// header: {
// userId: uni.getStorageSync('userId'),
// token: uni.getStorageSync('token'),
// myLoginName: uni.getStorageSync('myLoginName')
// },
success: (res) => {
let datares = res.data;
// uni.showToast({
// title: res.message || res.msg,
// icon: "none",
// })
// console.log(datares, '11111111')
if (datares.code == 200) {
uni.is_update = datares.data.versionCode; //是版本号,判断是否升级
uni.is_force = datares.data.forceUpdate; //是否强制更新 1强制 0未强制
uni.versionName = datares.data.versionName; //是版本号 显示版本号
uni.is_wgt = 0; //是热更新 目前好像没有该功能
uni.updateUrlApp = datares.data.url; //是下载地址
uni.update_content = datares.data.updateInfo; //版本说明
// uni.pro.switchTab('index/index');
}
},
fail: (res) => {
// uni.showToast({
// title: res.message || res.msg,
// icon: "none",
// })
}
});
} else {
console.log(res, 66);
uni.request({
url: uni.conf.baseUrl + '/api/systemConfig/updateSystemVersion?platformCode=' + 0,
method: 'POST',
// header: {
// userId: uni.getStorageSync('userId'),
// token: uni.getStorageSync('token'),
// myLoginName: uni.getStorageSync('myLoginName')
// },
success: (res) => {
let datares = res.data;
console.log(res);
if (datares.code == 200) {
uni.is_update = datares.data.versionCode; //是版本号,判断是否升级
uni.is_force = datares.data.forceUpdate; //是否强制更新 1强制 0未强制
uni.versionName = datares.data.versionName; //是版本号 显示版本号
uni.is_wgt = 0; //是热更新 目前好像没有该功能
uni.updateUrlApp = datares.data.url; //是下载地址
uni.update_content = datares.data.updateInfo; //版本说明
// uni.pro.switchTab('index/index');
}
}
});
}
}
});
// #endif
} catch (e) {}
},
onHide: function() {
// console.log('App Hide');

View File

@@ -1,35 +0,0 @@
var crypto = require('crypto')
function WXBizDataCrypt(appId, sessionKey) {
this.appId = appId
this.sessionKey = sessionKey
}
WXBizDataCrypt.prototype.decryptData = function (encryptedData, iv) {
// base64 decode
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

11
common/js/apix.js Normal file
View File

@@ -0,0 +1,11 @@
export default {
cashierServiceloginregister(data) { //用户注册
return uni.api.post("/cashierService/login/register", data);
},
cashierServiceloginregister(data) { //APP登录
return uni.api.post("/login/app/login", data);
},
phoneValidateCode(data) { //验证码
return uni.api.get("/phoneValidateCode", data);
},
}

View File

@@ -1,74 +0,0 @@
const env = {
aliyunServerURL: 'https://czg-qr-order.oss-cn-beijing.aliyuncs.com',
accessid: 'LTAI5tMLHwnM1zYYAFuRa1fK',
AccessKeySecret: 'jS1h2STq1vcODczDNFQkjcU6ODyYAj',
timeout: 100000
}
const Base64 = require('./Base64.js');
require('./hmac.js');
require('./sha1.js');
const Crypto = require('./crypto.js');
const uploadFile = function(filePath, key = new Date().getTime()) {
return new Promise((resolve, reject) => {
// const aliyunFileKey = `${new Date().getTime()}_${userId}`;
const aliyunServerURL = env.aliyunServerURL;
const accessid = env.accessid;
const policyBase64 = getPolicyBase64();
const signature = getSignature(policyBase64);
wx.uploadFile({
url: aliyunServerURL, //仅为示例,非真实的接口地址
filePath: filePath,
name: 'file',
formData: {
'key': 'headportrait/' + key,
'OSSAccessKeyId': accessid,
'policy': policyBase64,
'Signature': signature,
'success_action_status': '200',
},
success: function(res) {
if (res.statusCode != 200) {
reject('上传错误:' + JSON.stringify(res))
return;
}
resolve(`https://czh5.sxczgkj.cn/headportrait/${key}`)
},
fail: function(err) {
reject('上传错误:' + JSON.stringify(err))
}
})
})
}
const getPolicyBase64 = function() {
let date = new Date();
date.setHours(date.getHours() + env.timeout);
let srcT = date.toISOString();
const policyText = {
"expiration": srcT, //设置该Policy的失效时间超过这个失效时间之后就没有办法通过这个policy上传文件了 指定了Post请求必须发生在2020年01月01日12点之前("2020-01-01T12:00:00.000Z")。
"conditions": [
["content-length-range", 0, 20 * 1024 * 1024] // 设置上传文件的大小限制,1048576000=1000mb
]
};
const policyBase64 = Base64.encode(JSON.stringify(policyText));
return policyBase64;
}
const getSignature = function(policyBase64) {
const accesskey = env.AccessKeySecret;
const bytes = Crypto.HMAC(Crypto.SHA1, policyBase64, accesskey, {
asBytes: true
});
const signature = Crypto.util.bytesToBase64(bytes);
return signature;
}
module.exports = uploadFile;

192
components/countdown.vue Normal file
View File

@@ -0,0 +1,192 @@
<template>
<view class="uni-countdown">
<text v-if="showDay" class="uni-countdown__number">{{ d }}</text>
<text v-if="showDay" class="uni-countdown__splitor"></text>
<text class="uni-countdown__number">{{ h }}</text>
<text class="uni-countdown__splitor">{{ showColon ? ':' : '时' }}</text>
<text class="uni-countdown__number">{{ i }}</text>
<text class="uni-countdown__splitor">{{ showColon ? ':' : '分' }}</text>
<text class="uni-countdown__number">{{ s }}</text>
<text v-if="!showColon" class="uni-countdown__splitor"></text>
</view>
</template>
<script>
/**
* Countdown 倒计时
* @description 倒计时组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=25
* @property {String} backgroundColor 背景色
* @property {String} color 文字颜色
* @property {Number} day 天数
* @property {Number} hour 小时
* @property {Number} minute 分钟
* @property {Number} second 秒
* @property {Boolean} showDay = [true|false] 是否显示天数
* @property {Boolean} showColon = [true|false] 是否以冒号为分隔符
* @property {String} splitorColor 分割符号颜色
* @event {Function} timeup 倒计时时间到触发事件
* @example <uni-countdown :day="1" :hour="1" :minute="12" :second="40"></uni-countdown>
*/
export default {
name: 'UniCountdown',
props: {
showDay: {
type: Boolean,
default: true
},
showColon: {
type: Boolean,
default: true
},
backgroundColor: {
type: String,
default: '#FFFFFF'
},
borderColor: {
type: String,
default: '#000000'
},
color: {
type: String,
default: '#000000'
},
splitorColor: {
type: String,
default: '#000000'
},
indexs: {
type: Number,
default: 0
},
day: {
type: Number,
default: 0
},
hour: {
type: Number,
default: 0
},
minute: {
type: Number,
default: 0
},
second: {
type: Number,
default: 0
}
},
data() {
return {
timer: null,
syncFlag: false,
d: '00',
h: '00',
i: '00',
s: '00',
leftTime: 0,
seconds: 0
}
},
watch: {
day(val) {
this.changeFlag()
},
hour(val) {
this.changeFlag()
},
minute(val) {
this.changeFlag()
},
second(val) {
this.changeFlag()
}
},
created: function(e) {
this.startData();
},
beforeDestroy() {
clearInterval(this.timer)
},
methods: {
toSeconds(day, hours, minutes, seconds) {
return day * 60 * 60 * 24 + hours * 60 * 60 + minutes * 60 + seconds
},
timeUp() {
console.log(1)
clearInterval(this.timer)
this.$emit('timeup',this.indexs)
},
countDown() {
let seconds = this.seconds
let [day, hour, minute, second] = [0, 0, 0, 0]
if (seconds > 0) {
day = Math.floor(seconds / (60 * 60 * 24))
hour = Math.floor(seconds / (60 * 60)) - (day * 24)
minute = Math.floor(seconds / 60) - (day * 24 * 60) - (hour * 60)
second = Math.floor(seconds) - (day * 24 * 60 * 60) - (hour * 60 * 60) - (minute * 60)
} else {
this.timeUp()
}
if (day < 10) {
day = '0' + day
}
if (hour < 10) {
hour = '0' + hour
}
if (minute < 10) {
minute = '0' + minute
}
if (second < 10) {
second = '0' + second
}
this.d = day
this.h = hour
this.i = minute
this.s = second
},
startData() {
this.seconds = this.toSeconds(this.day, this.hour, this.minute, this.second)
if (this.seconds <= 0) {
return
}
this.countDown()
this.timer = setInterval(() => {
this.seconds--
if (this.seconds < 0) {
this.timeUp()
return
}
this.countDown()
}, 1000)
},
changeFlag() {
console.log(this.syncFlag,111111)
if (!this.syncFlag) {
this.seconds = this.toSeconds(this.day, this.hour, this.minute, this.second)
this.startData();
this.syncFlag = true;
}
}
}
}
</script>
<style scoped>
.uni-countdown {
display: flex;
flex-direction: row;
justify-content: flex-start;
}
.uni-countdown__splitor {
display: flex;
justify-content: center;
font-size: 22rpx;
}
.uni-countdown__number {
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
</style>

View File

@@ -1,22 +1,25 @@
const debug = true;
const debug = process.env.NODE_ENV == 'development' ? true : false;
// #ifdef H5
const proxyApi = "/api"
// #endif
// #ifdef MP-WEIXIN || MP-ALIPAY
const baseUrl = 'https://cashier.sxczgkj.cn/cashierService' // 线上
const baseUrlwws = 'wss://cashier.sxczgkj.cn/cashierService' // 线上
// const baseUrl = "https://cashierapplet.sxczgkj.cn/cashierService" //测试
// const baseUrlwws = 'wss://cashierapplet.sxczgkj.cn/cashierService' // 测试
// #ifdef MP-WEIXIN || APP
const proxyApi = 'https://cashier.sxczgkj.cn/cashierService' // 线上
// #endif
// #ifdef H5
const baseUrl = debug ? proxyApi : 'http://192.168.2.161:9889/cashierService/' // 线上
const baseUrlwws = debug ? proxyApi : 'http://192.168.2.161:9889/cashierService/' // 线上
const baseUrl = debug ? proxyApi : "https://cashier.sxczgkj.cn/cashierService"
const baseUrlwws = 'wss://cashier.sxczgkj.cn/cashierService' // 线上
// #endif
// #ifdef APP || MP-WEIXIN
const baseUrl = debug ? proxyApi : 'https://cashier.sxczgkj.cn/cashierService'
const baseUrlwws = 'wss://cashier.sxczgkj.cn/cashierService' // 线上
// #endif
// import VConsole from "./vConsole.js"
// if (debug) {
// // new VConsole()
// }
const version = '109'
const version = '100'
const autoRemoveCache = {
count: 100000,
size: 100000

View File

@@ -61,6 +61,14 @@ async function request(options) {
}
if (options.type == 1) {
options.header = {
version: uni.conf.version,
type: uni.getSystemInfoSync().platform,
// #ifdef APP-PLUS
environment: 'app',
// #endif
// #ifdef MP-WEIXIN
environment: 'wx',
// #endif
token: uni.cache.get('token'),
openId: uni.cache.get('miniAppOpenId'),
id: uni.cache.get('userInfo').id,

View File

@@ -4,12 +4,16 @@ import useStorage from '@/utils/useStroage.js'
import './framework/bootstrap'
import Api from "./common/js/api.js"
import Shop from "./common/js/shop.js"
import Ashopx from "./common/js/apix.js"
import store from './store'
// #ifndef VUE3
import Vue from 'vue'
import './uni.promisify.adaptor'
Vue.config.productionTip = false
Vue.prototype.$store = store
App.mpType = 'app'
const app = new Vue({
store,
...App
})
app.$mount()
@@ -20,6 +24,7 @@ uni.$u.config.unit = 'rpx'
Vue.prototype.useStorage = useStorage
Vue.prototype.api = Api;
Vue.prototype.shop = Shop;
Vue.prototype.apix = Ashopx;
// #ifdef VUE3
import {
createSSRApp

View File

@@ -1,98 +1,102 @@
{
"name": "cashier_weapp",
"appid": "__UNI__8092421",
"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": {
"Barcode": {}
},
/* */
"distribute": {
/* android */
"android": {
"permissions": [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios */
"ios": {},
/* SDK */
"sdkConfigs": {}
}
},
/* */
"quickapp": {},
/* */
"mp-weixin": {
"appid": "wxd88fffa983758a30",
"setting": {
"urlCheck": false
},
"usingComponents": true,
"libVersion": "latest"
},
"h5": {
"devServer": {
"https": false,
"disableHostCheck": false,
"proxy": {
"/api": {
"target": "https://p40312246f.goho.co/cashierService/",
// "target" : "https://ky.sxczgkj.cn",
"ws": false,
"changeOrigin": true, //是否跨域
"secure": false, // 设置支持https协议的代理
"pathRewrite": {
"^/api": "" //需要rewrite重写的,
}
}
}
},
"template": "template.h5.html",
"router": {
"mode": "history",
"base": "/h5/"
}
},
"mp-alipay": {
"usingComponents": true
},
"mp-baidu": {
"usingComponents": true
},
"mp-toutiao": {
"usingComponents": true
},
"uniStatistics": {
"enable": false
},
"vueVersion": "2"
}
"name" : "cashier_weapp",
"appid" : "__UNI__8092421",
"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" : {
"Barcode" : {}
},
/* */
"distribute" : {
/* android */
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios */
"ios" : {
"dSYMs" : false
},
/* SDK */
"sdkConfigs" : {
"ad" : {}
}
}
},
/* */
"quickapp" : {},
/* */
"mp-weixin" : {
"appid" : "wxd88fffa983758a30",
"setting" : {
"urlCheck" : false
},
"usingComponents" : true,
"libVersion" : "latest"
},
"h5" : {
"devServer" : {
"https" : false,
"disableHostCheck" : false,
"proxy" : {
"/api" : {
"target" : "https://cashier.sxczgkj.cn/cashierService",
// "target" : "https://ky.sxczgkj.cn",
"ws" : false,
"changeOrigin" : true, //是否跨域
"secure" : false, // 设置支持https协议的代理
"pathRewrite" : {
"^/api" : "" //需要rewrite重写的,
}
}
}
},
"template" : "template.h5.html",
"router" : {
"mode" : "history",
"base" : "/h5/"
}
},
"mp-alipay" : {
"usingComponents" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
},
"uniStatistics" : {
"enable" : false
},
"vueVersion" : "2"
}

View File

@@ -9,7 +9,14 @@
{
"path": "pages/login/login",
"style": {
"navigationBarTitleText": "用户授权"
"navigationBarTitleText": "登录",
"navigationStyle": "custom"
}
},
{
"path": "pages/login/register",
"style": {
"navigationBarTitleText": "注册"
}
},
{

View File

@@ -1,169 +1,218 @@
<template>
<view>
<view class="banner-wrap">
<u-swiper :list="banners" height="440" radius="0" :indicator="banners.length > 1"
imgMode="widthFix"></u-swiper>
</view>
<view class="container">
<view class="user-info">
<view class="top">
<view class="col">
<view style="width: 36px; height: 36px;border-radius: 10rpx;">
<button open-type="chooseAvatar" @chooseavatar='onChooseAvatar'
style="padding: 0;margin: 0; width: 36px; height: 36px;border-radius: 10rpx;">
<image style="width: 36px; height: 36px;" v-if="userInfo.avatar" :src="userInfo.avatar"
mode="aspectFill">
</image>
<image style="width: 36px; height: 36px;" v-else src="@/static/avatar.png"
mode="aspectFill">
</image>
</button>
<view class="content">
<!-- 导航栏 -->
<view class="navbar" :class="{active:opacity}">
<view class="status-bar"></view>
<!-- #ifdef APP-PLUS -->
<view class="navbar_tow flex-between">
<!-- #endif -->
<!-- #ifndef APP-PLUS -->
<view class="navbar_tow flex-between"
:style="{'height':HeighT.customBar+'px','padding-right':HeighT.custwidth + 'px'}">
<!-- #endif -->
<!-- 盒子2 返回标题搜索框 -->
<view class="flex-between">
<view class="navbar_tow_one flex-start">
<text>美味抢先点</text>
<text>西安</text>
<u-icon style="margin-left: 8rpx;" name="arrow-down-fill" color="#333333"
size="16"></u-icon>
</view>
<text class="t">{{userInfo.nickName}}</text>
</view>
<navigator class="ewm-wrap" url="/pages/pay_code/pay_code" hover-class="none">
<image class="ewm" src="../../static/ewm.png" mode="aspectFit"></image>
<text class="t">会员码</text>
</navigator>
</view>
<view class="bottom">
<view class="col">
<text class="t1 num">{{shopUser.amount || '0'}}</text>
<text class="t2">余额</text>
</view>
<view class="col">
<text class="t1 num">{{shopUser.levelConsume || '0'}}</text>
<text class="t2">积分</text>
</view>
</view>
</view>
<view class="menu-wrap">
<view class="top-wrap">
<view class="item" @click="scanCodehandle">
<image class="bg" src="../../static/index_m2.png" mode="widthFix"></image>
<view class="btn">
<text class="t">扫码点餐</text>
</view>
</view>
<view class="item" @click="memberindex">
<image class="bg" src="../../static/index_m1.png" mode="widthFix"></image>
<view class="btn">
<text class="t">会员充值</text>
<view class="navbar_tow_tow">
<input type="text" class="navbar_tow_towinput" v-model="keyword" placeholder="请输入关键字" />
</view>
</view>
</view>
</view>
<view class="footer-banner">
<u-swiper :list="footerBanners" radius="20" height="160" :indicator="banners.length > 1"
imgMode="widthFix"></u-swiper>
<!-- 轮播图 -->
<view class="viewswiper">
<u-swiper :list="list1" @change="e => current = e.current" indicatorStyle="right: 20px" height='484'>
<view slot="indicator" class="indicator">
<view class="indicator__dot" v-for="(item, index) in list1" :key="index"
:class="[index === current && 'indicator__dot--active']"
:style="[index === current && {'width':16+'px'}]">
</view>
</view>
</u-swiper>
</view>
<!-- 广告 -->
<view class="onecontent flex-between">
<view class="onecontentleft">
现有<text>0元无门槛</text>抵价券 正在出售
</view>
<view class="onecontentright flex-start">
<view class="onecontentrightimage flex-start">
<u-swiper class="onecontentrightswiper" circular style="width: 100%;" nextMargin="50"
:list="list1" height='28'></u-swiper>
</view>
<view class="onecontentrighttext">购买了10面值优惠券</view>
</view>
<!-- 小内切圆 -->
<view class="after"></view>
</view>
<!-- 金刚区 -->
<view class="towcontent flex-between">
<view class="towcontent_item flex-colum" v-for="(item,index) in 5" :key="index">
<image src="@/static/avatar.png" mode="aspectFill"></image>
<text>扫码点餐</text>
</view>
</view>
<!-- 今日上线 -->
<view class="therecontent flex-between">
<view class="therecontent_box_item" v-for="item in 2" :key="item">
<view class="therecontent_box_imge flex-between" :style="item&&item">
<view class="therecontent_box_imge_text">
今日上新
</view>
<view class="therecontent_box_imge_right flex-start">
<view>
10点更新
</view>
<u-icon name="arrow-right" color="#666666" size="16"></u-icon>
</view>
</view>
<view class="therecontent_box_itembox">
<view class="therecontent_box_itembox_item flex-between" v-for="item in 2" :key="item">
<image src="@/static/avatar.png" mode="aspectFill"></image>
<view class="therecontent_box_itembox_itemview">
<view class="therecontent_box_itembox_itemviewone">
书亦烧仙草新品书亦烧仙草新品亦烧仙草新品
</view>
<view class="therecontent_box_itembox_itemviewtow flex-start">
<image src="https://czg-qr-order.oss-cn-beijing.aliyuncs.com/index/xia.png"
mode="widthFix"></image>
<view>
8
</view>
</view>
<view class="therecontent_box_itembox_itemviewthere flex-start">
<text>15.00</text>
<text>18.00</text>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 类目 -->
<view class="fourcontent flex-between">
<view class="fourcontent_item flex-start" v-for="(item,index) in 10" :key="index">
<text>西安</text>
<u-icon style="margin-left: 8rpx;" name="arrow-down-fill" color="#333333" size="16"></u-icon>
</view>
</view>
<!-- 产品 -->
<view class="fivecontent">
<view class="fivecontent_item" v-for="(item,index) in 12" :key="index">
<view class="fivecontent_item_nav flex-start">
<image src="@/static/avatar.png" mode="aspectFill"></image>
<view class="fivecontent_item_nav_left">
<view class="fivecontent_item_nav_lefttop flex-between">
<view>
幸运咖啡荣民时代广场店
</view>
<view>
龙首.151m
</view>
</view>
<view class="fivecontent_item_nav_leftlang flex-start">
<image src="https://czg-qr-order.oss-cn-beijing.aliyuncs.com/index/hong_h.png"
mode="aspectFill"></image>
<text>人气连锁品牌</text>
</view>
</view>
</view>
<view class="fivecontent_item_box">
<view class="fivecontent_item_boxitem flex-between">
<image src="@/static/avatar.png" mode=""></image>
<view class="fivecontent_item_boxitemleft flex-colum-start">
<view class="fivecontent_item_boxitemleftone flex-between">
<view>全场饮品任选</view>
<text>已抢15789份</text>
</view>
<view class="fivecontent_item_boxitemlefttow flex-start">
<image src="https://czg-qr-order.oss-cn-beijing.aliyuncs.com/index/hong_h.png"
mode="aspectFill"></image>
<text>人气连锁品牌</text>
</view>
<view class="indexboxitemleftthere flex-colum-start">
<view class="indexboxitemleftthereabsolute">
马上抢
</view>
<view class="indexboxitemlefttheretext flex-start">
<view class="indexboxitemlefttheretextone">
<text>¥</text>
<text>1444</text>
</view>
<view class="indexboxitemlefttheretexttow">
¥111
</view>
</view>
<view class="indexboxitemleftthere_countdown flex-between">
<text class="indexboxitemleftthere_countdowntext">共省4元</text>
<!-- <view class="indexboxitemleftthere_countdowntexts">
已失效
</view> -->
<!-- <view v-else class="indexboxitemleftthere_countdowntexts">
<uni-countdown @timeup="updateCity" :day="item.end_times.d"
:hour="item.end_times.h" :minute="item.end_times.m"
:second="item.end_times.s" :indexs='index'></uni-countdown>
</view> -->
<view class="indexboxitemleftthere_countdowntexts">
<uni-countdown :show-day="false" :day="1" :hour="1" :minute="12"
:second="40" color="#FFFFFF" border-color="#00B26A"
splitorColor="#FFFFFF" :font-size="8"></uni-countdown>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import uploadImage from "@/js_sdk/yushijie-ossutil/ossutil/uploadFile.js";
export default {
data() {
return {
banners: [require('@/static/banner1.png')],
footerBanners: [require('@/static/footer_banner1.png')],
shopUser: {},
userInfo: {},
shopInfo: {}
Backgroundtow: 'none',
keyword: '',
current: 0,
opacity: 0,
list1: [
'https://cdn.uviewui.com/uview/swiper/swiper1.png',
'https://cdn.uviewui.com/uview/swiper/swiper2.png',
'https://cdn.uviewui.com/uview/swiper/swiper3.png',
]
};
},
onLoad() {
// #ifdef MP-WEIXIN
if (!uni.cache.get('token')) {
uni.reLaunch({
url: '/pages/login/login'
})
}
// #endif
},
onShow() {
if (uni.cache.get('token')) {
this.loginwxuserInfo()
onPageScroll(e) {
if (e.scrollTop <= 44) {
this.opacity = false
} else {
uni.reLaunch({
url: '/pages/login/login'
})
this.opacity = true
}
},
computed: {
HeighT() {
return this.$store.getters.is_BarHeight
},
},
onLoad() {
},
onShow() {},
methods: {
async loginwxuserInfo() {
let res = await this.api.loginwxuserInfo({
userId: uni.cache.get('userInfo').id,
shopId: uni.cache.get('shopUser').shopId
})
if (res.code == 0) {
uni.cache.set('userInfo', res.data.userInfo);
uni.cache.set('shopUser', res.data.shopUser);
uni.cache.set('shopInfo', res.data.shopInfo);
this.shopUser = uni.cache.get('shopUser')
this.userInfo = uni.cache.get('userInfo')
this.shopInfo = uni.cache.get('shopInfo')
}
},
scanCodehandle() {
// #ifndef H5
uni.scanCode({
success: (res) => {
let tableCode = this.getQueryString(decodeURIComponent(res.result), 'code')
if (tableCode) {
uni.pro.navigateTo('order_food/order_food', {
tableCode: tableCode,
})
}
},
fail: (err) => {
console.log(err)
}
})
// #endif
// #ifdef H5
uni.pro.navigateTo('order_food/order_food', {
tableCode: '3000103958',
})
// #endif
},
memberindex() {
uni.pro.navigateTo('member/index')
},
getQueryString(url, name) { //解码
var reg = new RegExp('(^|&|/?)' + name + '=([^&|/?]*)(&|/?|$)', 'i')
var r = url.substr(1).match(reg)
if (r != null) {
return r[2]
}
return null;
},
// / 更换头像
onChooseAvatar(e) {
uni.showLoading({
title: '上传中',
mask: true
})
console.log(e.detail.avatarUrl)
let file = e.detail.avatarUrl;
uploadImage(file, 'avatar',
result => {
//将上传后的图片以对象官方要求的格式的形式存入uni-file-picker的value值imageValueimageValue值的结构为数组包对象用于图片回显
// let objAge = {
// 'url': result,
// 'extname': 'png',
// 'name': 'imgss.png'
// };
// this.userlist.avatar.push(objAge)
this.userInfo.avatar = result
console.log(this.userInfo.avatar)
uni.hideLoading()
}, result => {
uni.hideLoading()
})
updateCity(data) {
this.list[data].end_times = 0;
this.$forceUpdate();
},
}
@@ -171,109 +220,508 @@
</script>
<style scoped lang="scss">
.container {
padding: 40upx;
page {
background: #F9F9F9;
}
.user-info {
background-color: #fff;
padding: 40upx;
border-radius: 20upx;
.content {
.top {
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1upx solid #ececec;
padding-bottom: 42upx;
.col {
display: flex;
align-items: center;
.t {
margin-left: 20upx;
}
}
.ewm-wrap {
display: flex;
flex-direction: column;
align-items: center;
.ewm {
$size: 50upx;
width: $size;
height: $size;
}
.t {
font-size: 20upx;
padding-top: 8upx;
}
}
.active {
background:rgba(249,249,249,1);
}
.status-bar {
// #ifdef APP-PLUS
height: calc(var(--status-bar-height) / 2);
// #endif
// #ifndef APP-PLUS
height: var(--status-bar-height);
// #endif
}
.bottom {
padding-top: 40upx;
display: flex;
.col {
flex: 1;
display: flex;
align-items: center;
flex-direction: column;
.t1 {
font-size: 38upx;
}
}
}
}
.menu-wrap {
padding: 40upx 0 0 0;
$gap: 20upx;
.top-wrap {
display: flex;
gap: $gap;
.item {
flex: auto;
display: flex;
align-items: center;
flex-direction: column;
background-color: #fff;
border-radius: 20upx;
.navbar {
position: fixed;
top: 0;
width: 100%;
z-index: 99;
.navbar_tow {
width: 100%;
position: relative;
font-size: 36rpx;
.bg {
.flex-between {
// #ifdef APP-PLUS || H5
margin: 28rpx;
// #endif
// #ifdef MP-WEIXIN
margin-left: 28rpx;
// #endif
width: 100%;
height: auto;
border-radius: $gap;
flex-wrap: nowrap;
height: 100%;
line-height: 100%;
.navbar_tow_one {
height: 100%;
line-height: 100%;
text:nth-child(1) {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: bold;
font-size: 28rpx;
color: #333333;
}
text:nth-child(2) {
margin-left: 16rpx;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 28rpx;
color: #333333;
}
}
.navbar_tow_tow {
position: relative;
height: 100%;
line-height: 100%;
flex: 1;
margin-left: 10rpx;
.navbar_tow_towinput {
padding-left: 32rpx;
height: 100%;
width: auto;
background: #FFFFFF;
border-radius: 34rpx;
}
}
}
.btn {
margin-top: $gap;
padding: $gap $gap * 2;
border-radius: 100upx;
display: flex;
justify-content: center;
font-size: 32upx;
background-color: #fff;
box-shadow: 0 12upx 12upx rgba(0, 0, 0, 0.05);
position: absolute;
bottom: $gap * 2;
left: 50%;
transform: translateX(-50%);
white-space: nowrap;
}
}
.viewswiper {
.indicator {
margin-bottom: 46rpx;
@include flex(row);
justify-content: center;
&__dot {
height: 6px;
width: 6px;
border-radius: 100px;
background-color: rgba(255, 255, 255, 0.35);
margin: 0 5px;
transition: background-color 0.3s;
&--active {
background-color: #ffffff;
}
}
}
.indicator-num {
padding: 2px 0;
background-color: rgba(0, 0, 0, 0.35);
border-radius: 100px;
width: 35px;
@include flex;
justify-content: center;
&__text {
color: #FFFFFF;
font-size: 12px;
}
}
}
}
.footer-banner {
padding-top: 20upx;
.onecontent {
position: relative;
margin-top: -30rpx;
padding: 14rpx 28rpx 44rpx 28rpx;
width: 100%;
background: linear-gradient(92deg, #FCECAA 0%, #fff 100%);
border-radius: 40rpx 0rpx 0rpx 0rpx;
.onecontentleft {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 24rpx;
color: #333333;
text {
color: #FC851E;
}
}
.onecontentright {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 24rpx;
color: #333333;
.onecontentrightimage {
width: 90rpx;
.onecontentrightswiper {
border: 50%;
width: 28rpx;
height: 28rpx;
}
}
}
.after {
position: absolute;
top: -40rpx;
right: 0;
width: 40rpx;
height: 40rpx;
line-height: 40rpx;
text-align: center;
background-image: radial-gradient(160rpx at 0px 0px, rgba(0, 0, 0, 0) 40rpx, #fff 40rpx);
}
}
.towcontent {
position: relative;
margin-top: -32rpx;
padding: 32rpx 40rpx;
width: 100%;
background: #F9F9F9;
border-radius: 48rpx 48rpx 0rpx 0rpx;
.towcontent_item {
image {
width: 92rpx;
height: 92rpx;
}
text {
margin-top: 16rpx;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 28rpx;
color: #333333;
}
}
}
.therecontent {
padding: 0 28rpx;
background: #F9F9F9;
.therecontent_box_item {
width: 336rpx;
border-radius: 18rpx;
background: #FFFFFF;
.therecontent_box_itembox {
padding: 10rpx 18rpx 24rpx 24rpx;
.therecontent_box_itembox_item {
margin-top: 20rpx;
image {
width: 114rpx;
height: 136rpx;
border-radius: 10rpx;
}
.therecontent_box_itembox_itemview {
margin-left: 12rpx;
.therecontent_box_itembox_itemviewone {
width: 168rpx;
height: 68rpx;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 24rpx;
color: #333333;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.therecontent_box_itembox_itemviewtow {
margin-top: 8rpx;
width: 60rpx;
padding: 4rpx 10rpx;
background: #FFFFFF;
border-radius: 4rpx;
border: 2rpx solid #FF7127;
image {
width: 9.74rpx;
height: 13.51rpx;
}
view {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: bold;
font-size: 16rpx;
color: #FF7127;
}
}
.therecontent_box_itembox_itemviewthere {
margin-top: 4rpx;
text:nth-child(1) {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 500;
font-size: 24rpx;
color: #FF7127;
}
text:nth-child(2) {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 500;
font-size: 16rpx;
color: #999999;
text-decoration-line: line-through;
}
}
}
}
.therecontent_box_itembox_item:nth-child(1) {
margin-top: 0;
}
}
.therecontent_box_imge {
padding: 24rpx 16rpx 6rpx 24rpx;
background: url(https://czg-qr-order.oss-cn-beijing.aliyuncs.com/index/towcontent_box1.png) no-repeat;
width: 100%;
height: 70rpx;
background-size: cover;
.therecontent_box_imge_text {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: bold;
font-size: 28rpx;
color: #333333;
}
.therecontent_box_imge_right {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 500;
font-size: 24rpx;
color: #666666;
}
}
.therecontent_box_imge:nth-child(2) {
background: url(https://czg-qr-order.oss-cn-beijing.aliyuncs.com/index/towcontent_box2.png) no-repeat;
}
}
}
.fourcontent {
padding: 32rpx 0 0 28rpx;
overflow-x: auto;
flex-wrap: nowrap;
.fourcontent_item {
flex-wrap: nowrap;
margin-left: 22rpx;
padding: 4rpx 14rpx;
background: #FFFFFF;
border-radius: 8rpx 8rpx 8rpx 8rpx;
text {
width: max-content;
}
}
.fourcontent_item:nth-child(1) {
margin-left: 0;
}
}
.fivecontent {
padding: 0 28rpx;
.fivecontent_item {
margin-top: 32rpx;
padding: 24rpx 32rpx;
width: 100%;
background: #FFFFFF;
border-radius: 18rpx 18rpx 18rpx 18rpx;
.fivecontent_item_nav {
image {
width: 60rpx;
height: 60rpx;
border-radius: 8rpx;
}
.fivecontent_item_nav_left {
flex: auto;
margin-left: 12rpx;
.fivecontent_item_nav_lefttop {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 24rpx;
color: #666666;
}
.fivecontent_item_nav_leftlang {
margin-top: 8rpx;
width: max-content;
padding: 4rpx 10rpx;
background: #FFF9E1;
border-radius: 4rpx 4rpx 4rpx 4rpx;
text {
margin-left: 6rpx;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 16rpx;
color: #F9A511;
}
image {
width: 10.82rpx;
height: 14.06rpx;
}
}
}
}
.fivecontent_item_box {
margin-top: 20rpx;
border-top: 2rpx solid #E5E5E5;
padding-top: 14rpx;
.fivecontent_item_boxitem {
image {
width: 192rpx;
height: 192rpx;
border-radius: 12rpx;
}
.fivecontent_item_boxitemleft {
margin-left: 24rpx;
flex: auto;
.fivecontent_item_boxitemleftone {
width: 100%;
text {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 24rpx;
color: #999999;
}
view {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 500;
font-size: 28rpx;
color: #333333;
}
}
.fivecontent_item_boxitemlefttow {
margin-top: 8rpx;
width: max-content;
padding: 4rpx 10rpx;
background: #FFF9E1;
border-radius: 4rpx 4rpx 4rpx 4rpx;
text {
margin-left: 6rpx;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 16rpx;
color: #F9A511;
}
image {
width: 10.82rpx;
height: 14.06rpx;
}
}
.indexboxitemleftthere {
position: relative;
margin-top: 30rpx;
padding-left: 16rpx;
width: 100%;
height: 88rpx;
background: url(https://czg-qr-order.oss-cn-beijing.aliyuncs.com/index/qinggou.png) no-repeat;
background-size: 100% 100%;
.indexboxitemleftthereabsolute {
position: absolute;
top: 14rpx;
right: 12rpx;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: bold;
font-size: 24rpx;
color: #FFFFFF;
}
.indexboxitemlefttheretext {
.indexboxitemlefttheretextone {
text {
font-family: SourceHanSansCN-Bold, SourceHanSansCN-Bold;
font-weight: normal;
color: #FF5053;
}
text:nth-child(2) {
font-weight: bold;
font-size: 34rpx;
}
text:nth-child(1) {
font-size: 24rpx;
}
}
.indexboxitemlefttheretexttow {
margin-left: 12rpx;
font-size: 20rpx;
font-family: SourceHanSansCN-Regular, SourceHanSansCN-Regular;
font-weight: normal;
color: #999999;
text-decoration: line-through;
}
}
.indexboxitemleftthere_countdown {
width: 100%;
.indexboxitemleftthere_countdowntext {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 24rpx;
color: #999999;
}
.indexboxitemleftthere_countdowntexts {
font-family: Roboto, Roboto;
font-weight: 400;
color: #333333;
margin-left: 16rpx;
font-size: 22rpx;
}
}
}
}
}
}
}
}
}
</style>

View File

@@ -1,31 +1,68 @@
<template>
<view class="container">
<view class="containerbox flex-colum">
<view class="containerimage_logo">
<image class="input_itemone" src="https://ointmentweapp.oss-cn-beijing.aliyuncs.com/manage/login2.png"
mode=""></image>
<view class="box flex-colum-start">
<text>您好</text>
<text>欢迎使用银收客</text>
</view>
<view class="top_box" :style="h">
<view class="top_box_one">
<text class="top_box_one_text">手机号码</text>
<input type="text" v-model="form.loginName" :adjust-position="false" placeholder="请输入手机号码"
maxlength="-1" data-key="mobile" />
</view>
<view class="containertext">
微信昵称
<view class="top_box_one">
<text class="top_box_one_text">密码</text>
<input type="mobile" v-model="form.password" :adjust-position="false" placeholder="8-16位密码"
maxlength="16" :password="!showPassword" />
<view class="repeat" @click="display">
<u-icon name="eye" v-if="showPassword"></u-icon>
<u-icon v-else name="eye-off"></u-icon>
</view>
</view>
<view class="containerbottom">
<view class="containerbottom_text flex-colum-start">
<text>该程序获得以下授权</text>
<text>获得您的手机号</text>
</view>
<view class="containerbottom_item flex-between">
<navigator class="containerbottomone" open-type="exit" target="miniProgram"><button
class="containerbottomone" open-type="launchApp" app-parameter="wechat"
binderror="launchAppError">
暂不授权
</button></navigator>
<button class="containerbottomtow" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">
确认授权
</button>
</view>
<view class="top_box_tow flex-between">
<text @click="register">注册账号</text>
<text @click="passwords">忘记密码</text>
</view>
<view class="toLogin" @click="toLogin">登录</view>
<view class="agreement flex-start">
<u-checkbox-group><u-checkbox shape="circle" @change="radioChange"
size="12"></u-checkbox></u-checkbox-group>
<text>阅读并同意银收客</text>
<view class="agreement-Item" @click="Privacy(1)">用户协议</view>
<view class="agreement-Item" @click="Privacy(2)">隐私政策</view>
</view>
</view>
<view class="box_conf" v-if="debug" @click="showpicker = true">{{ baseUrl || '切换' }}</view>
<u-overlay :show="agreeShow">
<view class="warp">
<view class="rect">
<view class="rect_img"></view>
<view class="rect_text flex-colum">
<view class="rect_text_one">用户须知</view>
<view class="rect_text_tow">
感谢您使用银收客我们非常重视您的个 人信息和隐私保护在您使用服务前请仔 细阅读
<text @click="Privacy(1)">用户协议</text>
<text @click="Privacy(2)">隐私协议</text>
</view>
<view class="rect_text_there">如您同意此条款请点击同意并开始使 用我们的产品和服务我们将尽全力保护您 的个人信息安全</view>
<view class="rect_text_four flex-between">
<view class="rect_text_four_o" @click="refuse">拒绝</view>
<view class="rect_text_four_t" @click="agree">同意</view>
</view>
</view>
</view>
</view>
</u-overlay>
<u-popup :show="showpopup" mode="center">
<view style="width: 600rpx; height: 100rpx">
<u--input style="width: 100%; height: 100%" placeholder="请输入内容" border="surround" @blur="blurinput"
v-model="valueinput"></u--input>
</view>
</u-popup>
<u-picker :show="showpicker" @cancel="showpicker = false" :columns="columns"
@confirm="confirmpicker"></u-picker>
</view>
</template>
@@ -33,249 +70,391 @@
export default {
data() {
return {
phone: ''
}
showpicker: false,
showpopup: false,
valueinput: '',
columns: [
['http://admintestapi.sxczgkj.cn/', 'https://ky.sxczgkj.cn', 'http://192.168.2.22:7004',
'http://admintestapi.sxczgkj.cn/', '自定义输入'
]
],
radioChangeItem: false, //单选框
agreeShow: false,
h: null, //动态高度
showPassword: false, //是否显示密码
debug: uni.conf.debug,
baseUrl: uni.conf.baseUrl,
form: {
//密码
loginName: '',
password: ''
}
};
},
mounted() {
this.computed_h();
},
onLoad() {
uni.cache.clear();
},
onLoad() {},
methods: {
async userlogin() {
// #ifdef MP-WEIXIN || MP-ALIPAY
uni.login({ //alipay weixin
// #ifdef MP-ALIPAY
provider: 'alipay',
// #endif
// #ifdef MP-WEIXIN
provider: 'weixin',
// #endif
success: async (data) => {
try {
uni.getUserInfo({
provider: 'weixin',
success: async (infoRes) => {
console.log(infoRes, 81);
uni.cache.set('weixincode', data.code);
let res = await this.api.userwxlogin({
code: uni.cache.get('weixincode'), //临时登录凭证
encryptedData: infoRes
.encryptedData, // 用户非敏感信息
rawData: infoRes.rawData,
signature: infoRes.signature,
iv: infoRes.iv,
phone: this.phone
})
if (res.code == 0) {
console.log(res, 88)
uni.cache.set('token', res.data.token);
uni.cache.set('miniAppOpenId', res.data.userInfo
.miniAppOpenId)
uni.cache.set('userInfo', res.data.userInfo);
uni.cache.set('shopUser', res.data.shopUser);
uni.pro.switchTab('index/index')
}
},
fail: (err) => {
console.log(err)
}
});
} catch (e) {
console.log(e)
}
}
});
// 同意隐私政策
agree() {
uni.setStorageSync('agree', 1);
this.agreeShow = false;
},
blurinput(e) {
console.log(e);
uni.conf.baseUrl = e;
this.baseUrl = e;
this.showpopup = false;
},
confirmpicker(e) {
this.showpicker = false;
if (e.value == '自定义输入') {
this.showpopup = true;
} else {
this.baseUrl = e.value[0];
uni.conf.baseUrl = e.value;
}
},
// 拒绝隐私政策-退出应用
refuse() {
// #ifdef APP-PLUS
//android 退出方法
plus.runtime.quit();
// ios 退出方法
plus.ios.import('UIApplication').sharedApplication().performSelector('exit');
// #endif
},
async getPhoneNumber(res) { // 获取手机号
var resdataa = res
console.log(res)
// #ifdef MP-WEIXIN
uni.login({
provider: 'weixin',
success: async (data) => {
let resdata = await this.api.logingetPhoneNumber({
code: data.code,
iv: resdataa.detail.iv,
encryptedData: resdataa.detail.encryptedData
})
console.log(resdata)
if (resdata.data) {
this.phone = resdata.data
this.userlogin()
}
// this.userlogin()
}
});
// #endif
// #ifdef MP-WEIXIN
// #endif
radioChange(n) {
//是否同意
this.radioChangeItem = n;
},
},
display() {
// 切换图片显示隐藏
this.showPassword = !this.showPassword;
},
async Privacy(e) {
if (e == 1) {
//用户协议
let res = await this.api.agreementgetAgreementOne({
discern: 0
});
uni.pro.navigateTo('my/about/agreement', {
discern: 0,
list: res.data.content
});
} else {
let res3 = await this.api.agreementgetAgreementOne({
discern: 3
});
uni.pro.navigateTo('my/about/agreement', {
discern: 3,
list: res3.data.content
});
}
},
rightClick() {
console.log(11);
uni.switchTab({
url: '/pages/device_shop/index'
});
},
register() {
uni.navigateTo({
url: '../login/register'
});
},
passwords() {
uni.navigateTo({
url: '../login/password'
});
},
async computed_h() {
//获取div宽度
let content_Icon = await uni.utils.info_distance('box');
let system_info = await uni.getSystemInfo();
let h = null;
h = system_info.windowHeight - content_Icon.height + 'px';
this.h = {
height: h
};
},
async toLogin() {
//登录
if (this.form.loginName == null || this.form.loginName == '') {
uni.showToast({
title: '请输入电话号码',
icon: 'none'
});
return false;
}
if (this.form.password == null || this.form.password == '' || uni.$u.trim(this.form.password, 'all') ==
'') {
uni.showToast({
title: '请输入密码或密码不能输入空格',
icon: 'none'
});
return false;
}
if (this.radioChangeItem == false) {
uni.showToast({
icon: 'none',
title: '请先阅读《用户协议》和《隐私政策》'
});
return;
}
let res = await this.api.Login({
loginName: this.form.loginName,
password: this.form.password
});
console.log(res);
if (res.code == 200) {
uni.cache.set('loginName', this.form.loginName + '');
uni.cache.set('password', this.form.password + '');
uni.cache.set('token', res.data.userApp.token);
uni.cache.set('myLoginName', res.data.userInfo.loginName);
uni.cache.set('userId', res.data.userInfo.id);
uni.cache.set('userInfo', res.data.userInfo);
uni.cache.set('userApp', res.data.userApp);
}
// 积分商城用到的token
// uni.cache.set('rechargeToken', res.data.rechargeToken);
this.$store.commit('set_login', true);
this.$store.commit('userInfo', res.data.userInfo);
this.$store.commit('userApp', res.data.userApp);
this.$store.dispatch('USerVoiceactions'); //获取语音播报初始数据
// #ifdef APP-PLUS
try {
let pinf = plus.push.getClientInfo();
let cid = (pinf && pinf.clientid) || ''; //客户端标识
uni.cache.set('cid', cid);
let res = await this.api.pushbindalias({
cid: cid
});
console.log('cid res===', res);
console.log('cid===', cid);
} catch (e) {
console.log('ciderr===', e);
//TODO handle the exception
}
// #endif
uni.pro.switchTab('/pages/index/index');
} else {
this.$api.msg(res.message);
}
}
}
};
</script>
<style lang="scss">
page {
background: #F9F9F9;
width: 100%;
height: 100%;
background: linear-gradient(104deg, #4679ff 0%, #2868e8 47%, #2a94fc 100%);
}
button {}
.container {
position: relative;
.containerbox {
position: relative;
width: 100%;
.top {
position: absolute;
left: 64rpx;
.containerimage_logo {
margin-top: 66rpx;
border-radius: 50%;
width: 120rpx;
height: 120rpx;
.u-navbar--fixed {
top: 88rpx;
}
}
image {
.box {
padding-top: 228rpx;
padding-left: 64rpx;
padding-bottom: 144rpx;
box-sizing: border-box;
text {
font-size: 40rpx;
font-family: Source Han Sans CN-Medium, Source Han Sans CN;
font-weight: 500;
color: #ffffff;
}
}
.warp {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
.rect {
width: 606rpx;
background-color: #fff;
border-radius: 12rpx;
.rect_img {
// background: url(@/static/login/uoverlay.png) no-repeat;
background-size: 100% 100%;
width: 100%;
height: 100%;
height: 120px;
}
}
.containertext {
margin-top: 32rpx;
font-size: 28rpx;
}
.rect_text {
padding: 0 40rpx;
.rect_text_one {
margin-top: 32rpx;
font-size: 32rpx;
font-family: Source Han Sans CN-Medium, Source Han Sans CN;
font-weight: 500;
color: #333333;
}
.containerbottom {
margin-top: 40rpx;
border-top: 1px solid #ccc;
width: 100%;
padding: 0 28rpx;
.containerbottom_text {
margin-top: 32rpx;
text:nth-child(1) {
.rect_text_tow {
margin-top: 32rpx;
font-size: 28rpx;
font-family: Source Han Sans CN-Regular, Source Han Sans CN;
font-weight: 400;
text {
color: #2f87fd;
}
color: #333333;
}
text:nth-child(2) {
font-size: 24rpx;
color: #847f7f;
}
}
.containerbottom_item {
margin-top: 60rpx;
.containerbottomone {
padding: 10rpx 80rpx;
font-size: 24rpx;
.rect_text_there {
margin-top: 16rpx;
font-size: 28rpx;
font-family: Source Han Sans CN-Regular, Source Han Sans CN;
font-weight: 400;
color: #999999;
}
.containerbottomone::after {
background: none;
border: 1px solid #000;
}
.rect_text_four {
width: 100%;
padding: 48rpx 40rpx 30rpx 40rpx;
.containerbottomtow {
font-size: 24rpx;
background: #baf505;
border: none;
padding: 10rpx 80rpx;
}
.rect_text_four_o {
padding: 16rpx 64rpx;
background: #ffffff;
border-radius: 36rpx;
font-size: 28rpx;
font-family: Source Han Sans CN-Medium, Source Han Sans CN;
font-weight: 500;
color: #333333;
border: 2rpx solid #333333;
}
.containerbottomtow::after {
background: none;
border: none;
.rect_text_four_t {
background: #2f87fd;
padding: 16rpx 64rpx;
border-radius: 36rpx;
font-size: 28rpx;
font-family: Source Han Sans CN-Medium, Source Han Sans CN;
font-weight: 500;
color: #ffffff;
}
}
}
}
}
.wrapper {
position: relative;
top: -118rpx;
z-index: 90;
padding: 0 28rpx;
.box_conf {
position: fixed;
top: 10%;
color: #fff;
padding: 20rpx;
right: 2%;
}
.wrapper_box {
.top_box::after {
position: absolute;
// content: url(@/static/icon.png);
width: 282rpx;
height: 280rpx;
top: -240rpx;
right: 32rpx;
z-index: 2;
}
.top_box {
z-index: 9;
padding: 0 64rpx;
box-sizing: border-box;
width: 100%;
position: fixed;
bottom: 0;
display: flex;
flex-direction: column;
align-items: center;
background: #ffffff;
border-radius: 40rpx 40rpx 0px 0px;
.top_box_one {
position: relative;
width: 100%;
background: #FFFFFF;
border-radius: 32rpx;
padding: 16rpx 30rpx;
margin-top: 64rpx;
border-bottom: 6rpx solid #e5e5e5;
.input_content {
.input_item {
margin-top: 32rpx;
.input_itemone {
width: 49.68rpx;
height: 49.68rpx;
}
.input_itemtow {
position: relative;
flex: auto;
margin-left: 16rpx;
.input_itemtowicon {
position: absolute;
right: 0;
bottom: 20rpx;
z-index: 999;
}
.tit {
font-size: 32rpx;
font-family: Source Han Sans CN-Medium, Source Han Sans CN;
font-weight: 500;
color: #333333;
}
input {
width: 100%;
padding: 10rpx 0;
border-bottom: 2rpx solid rgba(229, 229, 229, 0.7);
font-size: 28rpx;
font-family: Source Han Sans CN-Medium, Source Han Sans CN;
font-weight: 500;
color: #999999;
}
}
}
}
.agreement {
margin-top: 24rpx;
font-size: 20rpx;
.top_box_one_text {
font-size: 36rpx;
font-family: Source Han Sans CN-Medium, Source Han Sans CN;
font-weight: 500;
color: #7c8e97;
.agreement-Item {
color: #4ca1fc;
}
color: #333333;
}
.confirm-button {
margin: 40rpx auto 50rpx auto;
width: 90%;
background: #2F87FD;
padding: 28rpx 0;
border-radius: 50rpx;
text-align: center;
box-shadow: 0px 6rpx 12rpx 2rpx rgba(0, 0, 0, 0.16);
font-size: 36rpx;
font-family: Source Han Sans CN-Bold, Source Han Sans CN;
font-weight: bold;
color: #FFFFFF;
input {
height: auto;
padding: 18rpx 0 20rpx 0;
}
.repeat {
position: absolute;
bottom: 26rpx;
right: 0;
width: 25rpx;
height: 17rpx;
}
}
.top_box_tow {
width: 100%;
text {
margin-top: 34rpx;
font-size: 24rpx;
font-family: $uni_family;
font-weight: 400;
color: #666666;
}
}
.toLogin {
width: 570rpx;
margin-top: 112rpx;
padding: 10rpx 0;
text-align: center;
background: #288efb;
border-radius: 40rpx 40rpx 40rpx 40rpx;
font-size: 36rpx;
font-family: $uni_family;
font-weight: 400;
color: #ffffff;
}
.agreement {
margin-top: 14rpx;
font-size: 20rpx;
font-family: Source Han Sans CN-Medium, Source Han Sans CN;
font-weight: 500;
color: #7c8e97;
.agreement-Item {
color: #4ca1fc;
}
}
}
}
</style>

281
pages/login/loginw.vue Normal file
View File

@@ -0,0 +1,281 @@
<template>
<view class="container">
<view class="containerbox flex-colum">
<view class="containerimage_logo">
<image class="input_itemone" src="https://ointmentweapp.oss-cn-beijing.aliyuncs.com/manage/login2.png"
mode=""></image>
</view>
<view class="containertext">
微信昵称
</view>
<view class="containerbottom">
<view class="containerbottom_text flex-colum-start">
<text>该程序获得以下授权</text>
<text>获得您的手机号</text>
</view>
<view class="containerbottom_item flex-between">
<navigator class="containerbottomone" open-type="exit" target="miniProgram"><button
class="containerbottomone" open-type="launchApp" app-parameter="wechat"
binderror="launchAppError">
暂不授权
</button></navigator>
<button class="containerbottomtow" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">
确认授权
</button>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
phone: ''
}
},
onLoad() {
uni.cache.clear();
},
methods: {
async userlogin() {
// #ifdef MP-WEIXIN || MP-ALIPAY
uni.login({ //alipay weixin
// #ifdef MP-ALIPAY
provider: 'alipay',
// #endif
// #ifdef MP-WEIXIN
provider: 'weixin',
// #endif
success: async (data) => {
try {
uni.getUserInfo({
provider: 'weixin',
success: async (infoRes) => {
console.log(infoRes, 81);
uni.cache.set('weixincode', data.code);
let res = await this.api.userwxlogin({
code: uni.cache.get('weixincode'), //临时登录凭证
encryptedData: infoRes
.encryptedData, // 用户非敏感信息
rawData: infoRes.rawData,
signature: infoRes.signature,
iv: infoRes.iv,
phone: this.phone
})
if (res.code == 0) {
console.log(res, 88)
uni.cache.set('token', res.data.token);
uni.cache.set('miniAppOpenId', res.data.userInfo
.miniAppOpenId)
uni.cache.set('userInfo', res.data.userInfo);
uni.cache.set('shopUser', res.data.shopUser);
uni.pro.switchTab('index/index')
}
},
fail: (err) => {
console.log(err)
}
});
} catch (e) {
console.log(e)
}
}
});
// #endif
},
async getPhoneNumber(res) { // 获取手机号
var resdataa = res
console.log(res)
// #ifdef MP-WEIXIN
uni.login({
provider: 'weixin',
success: async (data) => {
let resdata = await this.api.logingetPhoneNumber({
code: data.code,
iv: resdataa.detail.iv,
encryptedData: resdataa.detail.encryptedData
})
console.log(resdata)
if (resdata.data) {
this.phone = resdata.data
this.userlogin()
}
// this.userlogin()
}
});
// #endif
// #ifdef MP-WEIXIN
// #endif
},
},
}
</script>
<style lang="scss">
page {
background: #F9F9F9;
}
button {}
.container {
position: relative;
.containerbox {
position: relative;
width: 100%;
.containerimage_logo {
margin-top: 66rpx;
border-radius: 50%;
width: 120rpx;
height: 120rpx;
image {
width: 100%;
height: 100%;
}
}
.containertext {
margin-top: 32rpx;
font-size: 28rpx;
}
.containerbottom {
margin-top: 40rpx;
border-top: 1px solid #ccc;
width: 100%;
padding: 0 28rpx;
.containerbottom_text {
margin-top: 32rpx;
text:nth-child(1) {
font-size: 28rpx;
}
text:nth-child(2) {
font-size: 24rpx;
color: #847f7f;
}
}
.containerbottom_item {
margin-top: 60rpx;
.containerbottomone {
padding: 10rpx 80rpx;
font-size: 24rpx;
}
.containerbottomone::after {
background: none;
border: 1px solid #000;
}
.containerbottomtow {
font-size: 24rpx;
background: #baf505;
border: none;
padding: 10rpx 80rpx;
}
.containerbottomtow::after {
background: none;
border: none;
}
}
}
}
.wrapper {
position: relative;
top: -118rpx;
z-index: 90;
padding: 0 28rpx;
.wrapper_box {
width: 100%;
background: #FFFFFF;
border-radius: 32rpx;
padding: 16rpx 30rpx;
.input_content {
.input_item {
margin-top: 32rpx;
.input_itemone {
width: 49.68rpx;
height: 49.68rpx;
}
.input_itemtow {
position: relative;
flex: auto;
margin-left: 16rpx;
.input_itemtowicon {
position: absolute;
right: 0;
bottom: 20rpx;
z-index: 999;
}
.tit {
font-size: 32rpx;
font-family: Source Han Sans CN-Medium, Source Han Sans CN;
font-weight: 500;
color: #333333;
}
input {
width: 100%;
padding: 10rpx 0;
border-bottom: 2rpx solid rgba(229, 229, 229, 0.7);
font-size: 28rpx;
font-family: Source Han Sans CN-Medium, Source Han Sans CN;
font-weight: 500;
color: #999999;
}
}
}
}
.agreement {
margin-top: 24rpx;
font-size: 20rpx;
font-family: Source Han Sans CN-Medium, Source Han Sans CN;
font-weight: 500;
color: #7c8e97;
.agreement-Item {
color: #4ca1fc;
}
}
.confirm-button {
margin: 40rpx auto 50rpx auto;
width: 90%;
background: #2F87FD;
padding: 28rpx 0;
border-radius: 50rpx;
text-align: center;
box-shadow: 0px 6rpx 12rpx 2rpx rgba(0, 0, 0, 0.16);
font-size: 36rpx;
font-family: Source Han Sans CN-Bold, Source Han Sans CN;
font-weight: bold;
color: #FFFFFF;
}
}
}
}
</style>

345
pages/login/register.vue Normal file
View File

@@ -0,0 +1,345 @@
<template>
<view class="container">
<view class="box flex-colum-start">
<text>您好</text>
<text>欢迎使用银收客</text>
</view>
<view class="top_box" :style="h">
<view class="top_box_one">
<text class="top_box_one_text">用户昵称</text>
<input type="text" v-model="form.nickName" placeholder="请输入用户昵称" data-key="mobile" />
</view>
<view class="top_box_one">
<text class="top_box_one_text">手机号码</text>
<input type="text" v-model="form.telephone" placeholder="请输入手机号码" data-key="mobile" />
</view>
<view class="top_box_one">
<text class="top_box_one_text">密码</text>
<input type="mobile" v-model="form.password" placeholder="8-16位密码" maxlength="16" :password="!showPassword" />
<view class="repeat" @click="display">
<u-icon name="eye" v-if="showPassword"></u-icon>
<u-icon v-else name="eye-off"></u-icon>
</view>
</view>
<view class="top_box_one">
<text class="top_box_one_text">验证码</text>
<input type="mobile" v-model="form.code" placeholder="请输入短信验证码" maxlength="6" />
<view class="repeats">
<view v-if="showText == true" class="yzm" style="padding: 8rpx 16rpx 6rpx 16rpx; background: #288efb; border-radius: 15rpx" @click="CodeRegister">
{{ Recapture }}
</view>
<view v-else style="color: #ccc; background-color: #f9f9f9; padding: 8rpx 16rpx 6rpx 16rpx; border-radius: 15rpx">{{ second }}s重新发送</view>
</view>
</view>
<!-- <view class="top_box_one">
<text class="top_box_one_text" @click="showTips">
邀请码选填
<uni-icons type="help" size="18"></uni-icons>
</text>
<input type="mobile" v-model="form.inviteCode" placeholder="请输入邀请人邀请码" />
</view> -->
<view class="Register" @click="Register">注册</view>
<view class="agreement flex-start">
<u-checkbox-group><u-checkbox shape="circle" @change="radioChange" size="12"></u-checkbox></u-checkbox-group>
<text>阅读并同意银收客</text>
<view class="agreement-Item" @click="Privacy(1)">用户协议</view>
<view class="agreement-Item" @click="Privacy(3)">隐私政策</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
radioChangeItem: false, //单选框
h: null,
showPassword: false,
// 注册定时器 初始值
second: 60,
showText: true,
Recapture: '发送验证码',
form: {
nickName:'',
telephone: '',
password: '',
code: '',
inviteCode: ''
}
};
},
mounted() {
this.computed_h();
},
onLoad() {},
methods: {
showTips() {
uni.showModal({
title: '注意',
content: '若该邀请码的用户无推广权限,将自动绑定到其上级名下',
showCancel: false
});
},
leftClick() {
uni.navigateBack();
},
async CodeRegister() {
//发起验证码
if (this.form.telephone == null || this.form.telephone == '') {
uni.showToast({
title: '请输入电话号码',
icon: 'none'
});
return false;
}
const res = await this.apix.phoneValidateCode({
// post 手机验证码
phone: this.form.telephone
});
console.log(res);
if (res) {
uni.showToast({
title: '验证码获取成功',
icon: 'none'
});
// 定时器
this.showText = false;
this.Recapture = '重新获取';
var interval = setInterval(() => {
let times = --this.second;
this.second = times < 10 ? '0' + times : times; //小于10秒补 0
}, 1000);
setTimeout(() => {
clearInterval(interval);
this.second = 60;
this.showText = true;
}, 60000);
}
},
radioChange(n) {
//是否同意
console.log(n);
this.radioChangeItem = n;
},
display() {
// 切换密码显示隐藏
this.showPassword = !this.showPassword;
},
async Privacy(e) {
if (e == 1) {
//用户协议
let res = await this.api.agreementgetAgreementOne({
discern: 0
});
uni.pro.navigateTo('my/about/agreement', { discern: 0, list: res.data.content });
} else {
let res3 = await this.api.agreementgetAgreementOne({
discern: 3
});
uni.pro.navigateTo('my/about/agreement', { discern: 3, list: res3.data.content });
}
},
async computed_h() {
//获取div宽度
let content_Icon = await uni.utils.info_distance('box');
let content_top_box = await uni.utils.info_distance('top_box');
let system_info = await uni.getSystemInfo();
var h_ = null;
if (content_Icon.height + content_top_box.height > system_info.windowHeight) {
console.log(135);
h_ = content_top_box.height + 30 + 'px';
} else {
h_ = system_info.windowHeight - content_Icon.height + 'px';
}
this.h = {
height: h_
};
},
async Register() {
//注册
if (this.form.nickName == null || this.form.nickName == '') {
uni.showToast({
title: '请输入用户昵称',
icon: 'none'
});
return false;
}
if (this.form.telephone == null || this.form.telephone == '') {
uni.showToast({
title: '请输入电话号码',
icon: 'none'
});
return false;
}
if (this.form.password == null || this.form.password == '' || uni.$u.trim(this.form.password, 'all') == '') {
uni.showToast({
title: '请输入密码或密码不能输入空格',
icon: 'none'
});
return false;
}
if (this.form.code == null || this.form.code == '') {
uni.showToast({
title: '请输入验证码',
icon: 'none'
});
return false;
}
if (this.radioChangeItem == false) {
uni.showToast({
icon: 'none',
title: '请先阅读《用户协议》和《隐私政策》'
});
return;
}
let res = await this.apix.cashierServiceloginregister({
telephone: this.form.telephone,
nickName: this.form.nickName,
password: this.form.password,
code: this.form.code,
// inviteCode: this.form.inviteCode,
source: 'promoter'
});
if (res) {
setTimeout((res) => {
uni.showToast({
title: '注册成功',
icon: 'none',
success: () => {
uni.navigateTo({
url: '../login/login'
});
}
});
}, 1500);
// uni.cache.set('storage:authorization', res.data.auth_token);
// this.$store.commit('set_login', true);
// uni.pro.switchTab('index/index');
}
// if (result.status === 1) {
// this.login(result.data);
// uni.navigateBack();
// } else {
// this.$api.msg(result.msg);
// this.logining = false;
// }
}
}
};
</script>
<style lang="scss">
page {
width: 100%;
background: linear-gradient(104deg, #4679ff 0%, #2868e8 47%, #2a94fc 100%);
}
.container {
position: relative;
.top {
position: absolute;
left: 64rpx;
.u-navbar--fixed {
top: 88rpx;
}
}
.box {
padding-top: 228rpx;
padding-left: 64rpx;
padding-bottom: 144rpx;
text {
font-size: 40rpx;
font-family: Source Han Sans CN-Medium, Source Han Sans CN;
font-weight: 500;
color: #ffffff;
}
}
.top_box::after {
position: absolute;
// content: url(@/static/icon.png);
width: 282rpx;
height: 280rpx;
top: -240rpx;
right: 32rpx;
z-index: 2;
}
.top_box {
position: relative;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
background: #ffffff;
border-radius: 40rpx 40rpx 0px 0px;
.top_box_one {
position: relative;
width: 85%;
margin-top: 64rpx;
border-bottom: 6rpx solid #e5e5e5;
.top_box_one_text {
display: flex;
align-items: center;
font-size: 36rpx;
font-family: Source Han Sans CN-Medium, Source Han Sans CN;
font-weight: 500;
color: #333333;
}
input {
padding: 18rpx 0 20rpx 0;
}
.repeat {
position: absolute;
bottom: 26rpx;
right: 0;
width: 25rpx;
height: 17rpx;
}
.repeats {
position: absolute;
bottom: 26rpx;
right: 0;
font-size: 24rpx;
z-index: 9;
font-family: $uni_family;
font-weight: 400;
color: #ffffff;
border-radius: 12rpx;
}
}
.top_box_tow {
width: 85%;
text {
margin-top: 34rpx;
font-size: 24rpx;
font-family: $uni_family;
font-weight: 400;
color: #666666;
}
}
.Register {
width: 75%;
margin-top: 112rpx;
padding: 10rpx 0;
text-align: center;
background: #288efb;
border-radius: 40rpx 40rpx 40rpx 40rpx;
font-size: 36rpx;
font-family: $uni_family;
font-weight: 400;
color: #ffffff;
}
.agreement {
margin-top: 14rpx;
font-size: 20rpx;
font-family: Source Han Sans CN-Medium, Source Han Sans CN;
font-weight: 500;
color: #7c8e97;
.agreement-Item {
color: #4ca1fc;
}
}
}
}
</style>

122
store/index.js Normal file
View File

@@ -0,0 +1,122 @@
import Vue from 'vue'
import Vuex from 'vuex'
import Api from '@/common/js/api.js'
Vue.use(Vuex);
//Vuex.Store 构造器选项
const store = new Vuex.Store({
state: { //存放状态
"login": false,
"info": {
ft_sum: 0,
},
"BarHeight": {
statusBar: '',
customBar: '',
info: '',
custwidth: '',
bottompadding: "",
heightBar: ''
},
},
getters: {
is_login(state) {
return state.login;
},
bottomnavigation(state) {
return state.ationbottomnavigation;
},
is_BarHeight(state) {
//二次修改后的值 或者过滤的
return state.BarHeight;
},
get_info(state) {
//二次修改后的值 或者过滤的
return state.info;
},
},
mutations: {
SET_STATUS_BAR(state, data) {
state.BarHeight.statusBar = data;
},
SET_CUSTOM_BAR(state, data) {
state.BarHeight.customBar = data;
},
Bottom_heightBar(state, data) {
state.BarHeight.heightBar = data;
},
SET_SYSTEM_INFO(state, data) {
state.BarHeight.info = data;
},
Bottom_Padding(state, data) {
state.BarHeight.bottompadding = data;
},
SUS_THIDTH(state, data) {
state.BarHeight.custwidth = data;
},
},
actions: {
HeightActions({
commit
}) {
uni.getSystemInfo({
success: (e) => {
let statusBar = 0
let customBar = 0
let heightBar = 0
let custwidth = 0
let bottomPadding = 0
// #ifdef MP
statusBar = e.statusBarHeight
customBar = e.statusBarHeight + 45
bottomPadding = (e.screenHeight - e.safeArea.bottom)
if (e.platform === 'android') {
commit('SET_SYSTEM_IOSANDROID', false)
customBar = e.statusBarHeight + 50
}
// #endif
// #ifdef MP-WEIXIN
statusBar = e.statusBarHeight
// @ts-ignore
const custom = wx.getMenuButtonBoundingClientRect()
console.log(custom, e, 1111)
// customBar = custom.bottom + custom.top - e.statusBarHeight
customBar = custom.height
heightBar = custom.top
custwidth = custom.width + 10,
bottomPadding = (e.screenHeight - e.safeArea.bottom)
// #endif
// #ifdef MP-ALIPAY
statusBar = e.statusBarHeight
customBar = e.statusBarHeight + e.titleBarHeight
bottomPadding = (e.screenHeight - e.safeArea.bottom)
// #endif
// #ifdef APP-PLUS
console.log('app-plus', e)
statusBar = e.statusBarHeight
heightBar = e.statusBarHeight/2
customBar = e.statusBarHeight + 45
bottomPadding = (e.screenHeight - e.safeArea.bottom)
customBar = 0
// #endif
// #ifdef H5
statusBar = 0
customBar = e.statusBarHeight == 0
bottomPadding = (e.screenHeight - e.safeArea.bottom)
// #endif
// console.log(statusBar,customBar,custwidth,e)
commit('SET_STATUS_BAR', statusBar) //状态栏高度
commit('SET_CUSTOM_BAR', customBar) //顶部距离
commit('SUS_THIDTH', custwidth) //胶囊宽度
commit('Bottom_Padding', bottomPadding) //底部导航栏Padding
commit('Bottom_heightBar', heightBar) //底部导航栏Padding
commit('SET_SYSTEM_INFO', e)
}
})
}
}
})
export default store

View File

@@ -3,3 +3,98 @@ $color-priamry: #ffd100;
$linear-color-priamry: linear-gradient(to right, #ffdc00, #f7ad12);
$paddingSize: 28upx;
$numColor: #eb5232;
// 字体
$uni_family: Source Han Sans CN-Regular, Source Han Sans CN;
/* 行为相关颜色 */
$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:24rpx;
$uni-font-size-base:28rpx;
$uni-font-size-lg:32rpx;
/* 图片尺寸 */
$uni-img-size-sm:40rpx;
$uni-img-size-base:52rpx;
$uni-img-size-lg:80rpx;
/* Border Radius */
$uni-border-radius-sm: 4rpx;
$uni-border-radius-base: 6rpx;
$uni-border-radius-lg: 12rpx;
$uni-border-radius-circle: 50%;
/* 水平间距 */
$uni-spacing-row-sm: 10px;
$uni-spacing-row-base: 20rpx;
$uni-spacing-row-lg: 30rpx;
/* 垂直间距 */
$uni-spacing-col-sm: 8rpx;
$uni-spacing-col-base: 16rpx;
$uni-spacing-col-lg: 24rpx;
/* 透明度 */
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
/* 文章场景相关 */
$uni-color-title: #2C405A; // 文章标题颜色
$uni-font-size-title:40rpx;
$uni-color-subtitle: #555555; // 二级标题颜色
$uni-font-size-subtitle:36rpx;
$uni-color-paragraph: #3F536E; // 文章段落颜色
$uni-font-size-paragraph:30rpx;
/* 页面左右间距 */
$page-row-spacing: 30upx;
$page-color-base: #f8f8f8;
$page-color-light: #f8f6fc;
$base-color: #fa436a;
/* 文字尺寸 */
$font-sm: 24upx;
$font-base: 28upx;
$font-lg: 32upx;
/*文字颜色*/
$font-color-dark: #303133;
$font-color-base: #606266;
$font-color-light: #909399;
$font-color-disabled: #C0C4CC;
$font-color-spec: #4399fc;
/* 边框颜色 */
$border-color-dark: #DCDFE6;
$border-color-base: #E4E7ED;
$border-color-light: #EBEEF5;
/* 图片加载中颜色 */
$image-bg-color: #eee;
/* 行为相关颜色 */
$uni-color-primary:#fa436a;
$uni-color-success: #4cd964;
$uni-color-warning: #f0ad4e;
$uni-color-error: #dd524d;
// 高度
$uni-height-nav: 44px;

View File

@@ -0,0 +1,26 @@
## 1.2.32024-02-20
- 新增 支持控制小时分钟的显隐showHour showMinute
## 1.2.22022-01-19
- 修复 在微信小程序中样式不生效的bug
## 1.2.12022-01-18
- 新增 update 方法 ,在动态更新时间后,刷新组件
## 1.2.02021-11-19
- 优化 组件UI并提供设计资源详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-countdown](https://uniapp.dcloud.io/component/uniui/uni-countdown)
## 1.1.32021-10-18
- 重构
- 新增 font-size 支持自定义字体大小
## 1.1.22021-08-24
- 新增 支持国际化
## 1.1.12021-07-30
- 优化 vue3下小程序事件警告的问题
## 1.1.02021-07-30
- 组件兼容 vue3如何创建vue3项目详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 1.0.52021-06-18
- 修复 uni-countdown 重复赋值跳两秒的 bug
## 1.0.42021-05-12
- 新增 组件示例地址
## 1.0.32021-05-08
- 修复 uni-countdown 不能控制倒计时的 bug
## 1.0.22021-02-04
- 调整为uni_modules目录规范

View File

@@ -0,0 +1,6 @@
{
"uni-countdown.day": "day",
"uni-countdown.h": "h",
"uni-countdown.m": "m",
"uni-countdown.s": "s"
}

View File

@@ -0,0 +1,8 @@
import en from './en.json'
import zhHans from './zh-Hans.json'
import zhHant from './zh-Hant.json'
export default {
en,
'zh-Hans': zhHans,
'zh-Hant': zhHant
}

View File

@@ -0,0 +1,6 @@
{
"uni-countdown.day": "天",
"uni-countdown.h": "时",
"uni-countdown.m": "分",
"uni-countdown.s": "秒"
}

View File

@@ -0,0 +1,6 @@
{
"uni-countdown.day": "天",
"uni-countdown.h": "時",
"uni-countdown.m": "分",
"uni-countdown.s": "秒"
}

View File

@@ -0,0 +1,281 @@
<template>
<view class="uni-countdown">
<text v-if="showDay" :style="[timeStyle]" class="uni-countdown__number">{{ d }}</text>
<text v-if="showDay" :style="[splitorStyle]" class="uni-countdown__splitor">{{dayText}}</text>
<text v-if="showHour" :style="[timeStyle]" class="uni-countdown__number">{{ h }}</text>
<text v-if="showHour" :style="[splitorStyle]" class="uni-countdown__splitor">{{ showColon ? ':' : hourText }}</text>
<text v-if="showMinute" :style="[timeStyle]" class="uni-countdown__number">{{ i }}</text>
<text v-if="showMinute" :style="[splitorStyle]" class="uni-countdown__splitor">{{ showColon ? ':' : minuteText }}</text>
<text :style="[timeStyle]" class="uni-countdown__number">{{ s }}</text>
<text v-if="!showColon" :style="[splitorStyle]" class="uni-countdown__splitor">{{secondText}}</text>
</view>
</template>
<script>
import {
initVueI18n
} from '@dcloudio/uni-i18n'
import messages from './i18n/index.js'
const {
t
} = initVueI18n(messages)
/**
* Countdown 倒计时
* @description 倒计时组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=25
* @property {String} backgroundColor 背景色
* @property {String} color 文字颜色
* @property {Number} day 天数
* @property {Number} hour 小时
* @property {Number} minute 分钟
* @property {Number} second 秒
* @property {Number} timestamp 时间戳
* @property {Boolean} showDay = [true|false] 是否显示天数
* @property {Boolean} showHour = [true|false] 是否显示小时
* @property {Boolean} showMinute = [true|false] 是否显示分钟
* @property {Boolean} show-colon = [true|false] 是否以冒号为分隔符
* @property {String} splitorColor 分割符号颜色
* @event {Function} timeup 倒计时时间到触发事件
* @example <uni-countdown :day="1" :hour="1" :minute="12" :second="40"></uni-countdown>
*/
export default {
name: 'UniCountdown',
emits: ['timeup'],
props: {
showDay: {
type: Boolean,
default: true
},
showHour: {
type: Boolean,
default: true
},
showMinute: {
type: Boolean,
default: true
},
showColon: {
type: Boolean,
default: true
},
start: {
type: Boolean,
default: true
},
backgroundColor: {
type: String,
default: ''
},
color: {
type: String,
default: '#333'
},
fontSize: {
type: Number,
default: 14
},
splitorColor: {
type: String,
default: '#333'
},
day: {
type: Number,
default: 0
},
hour: {
type: Number,
default: 0
},
minute: {
type: Number,
default: 0
},
second: {
type: Number,
default: 0
},
timestamp: {
type: Number,
default: 0
}
},
data() {
return {
timer: null,
syncFlag: false,
d: '00',
h: '00',
i: '00',
s: '00',
leftTime: 0,
seconds: 0
}
},
computed: {
dayText() {
return t("uni-countdown.day")
},
hourText(val) {
return t("uni-countdown.h")
},
minuteText(val) {
return t("uni-countdown.m")
},
secondText(val) {
return t("uni-countdown.s")
},
timeStyle() {
const {
color,
backgroundColor,
fontSize
} = this
return {
color,
backgroundColor,
fontSize: `${fontSize}px`,
width: `${fontSize * 22 / 14}px`, // 按字体大小为 14px 时的比例缩放
lineHeight: `${fontSize * 20 / 14}px`,
borderRadius: `${fontSize * 3 / 14}px`,
}
},
splitorStyle() {
const { splitorColor, fontSize, backgroundColor } = this
return {
color: splitorColor,
fontSize: `${fontSize * 12 / 14}px`,
margin: backgroundColor ? `${fontSize * 4 / 14}px` : ''
}
}
},
watch: {
day(val) {
this.changeFlag()
},
hour(val) {
this.changeFlag()
},
minute(val) {
this.changeFlag()
},
second(val) {
this.changeFlag()
},
start: {
immediate: true,
handler(newVal, oldVal) {
if (newVal) {
this.startData();
} else {
if (!oldVal) return
clearInterval(this.timer)
}
}
}
},
created: function(e) {
this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
this.countDown()
},
// #ifndef VUE3
destroyed() {
clearInterval(this.timer)
},
// #endif
// #ifdef VUE3
unmounted() {
clearInterval(this.timer)
},
// #endif
methods: {
toSeconds(timestamp, day, hours, minutes, seconds) {
if (timestamp) {
return timestamp - parseInt(new Date().getTime() / 1000, 10)
}
return day * 60 * 60 * 24 + hours * 60 * 60 + minutes * 60 + seconds
},
timeUp() {
clearInterval(this.timer)
this.$emit('timeup')
},
countDown() {
let seconds = this.seconds
let [day, hour, minute, second] = [0, 0, 0, 0]
if (seconds > 0) {
day = Math.floor(seconds / (60 * 60 * 24))
hour = Math.floor(seconds / (60 * 60)) - (day * 24)
minute = Math.floor(seconds / 60) - (day * 24 * 60) - (hour * 60)
second = Math.floor(seconds) - (day * 24 * 60 * 60) - (hour * 60 * 60) - (minute * 60)
} else {
this.timeUp()
}
if (day < 10) {
day = '0' + day
}
if (hour < 10) {
hour = '0' + hour
}
if (minute < 10) {
minute = '0' + minute
}
if (second < 10) {
second = '0' + second
}
this.d = day
this.h = hour
this.i = minute
this.s = second
},
startData() {
this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
if (this.seconds <= 0) {
this.seconds = this.toSeconds(0, 0, 0, 0, 0)
this.countDown()
return
}
clearInterval(this.timer)
this.countDown()
this.timer = setInterval(() => {
this.seconds--
if (this.seconds < 0) {
this.timeUp()
return
}
this.countDown()
}, 1000)
},
update(){
this.startData();
},
changeFlag() {
if (!this.syncFlag) {
this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
this.startData();
this.syncFlag = true;
}
}
}
}
</script>
<style lang="scss" scoped>
$font-size: 14px;
.uni-countdown {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
&__splitor {
margin: 0 2px;
font-size: $font-size;
color: #333;
}
&__number {
border-radius: 3px;
text-align: center;
font-size: $font-size;
}
}
</style>

View File

@@ -0,0 +1,83 @@
{
"id": "uni-countdown",
"displayName": "uni-countdown 倒计时",
"version": "1.2.3",
"description": "CountDown 倒计时组件",
"keywords": [
"uni-ui",
"uniui",
"countdown",
"倒计时"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": ""
},
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
"type": "component-vue"
},
"uni_modules": {
"dependencies": ["uni-scss"],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}

View File

@@ -0,0 +1,10 @@
## CountDown 倒计时
> **组件名uni-countdown**
> 代码块: `uCountDown`
倒计时组件。
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-countdown)
#### 如使用过程中有任何问题或者您对uni-ui有一些好的建议欢迎加入 uni-ui 交流群871950839

View File

@@ -0,0 +1,8 @@
## 1.1.02024-03-25
[重要] 支持支付宝小程序云
## 1.0.22023-08-01
优化配置读取方式
## 1.0.12023-08-01
初版
## 1.0.02023-08-01
初版文档地址https://uniapp.dcloud.net.cn/uniCloud/uni-map-common.html

View File

@@ -0,0 +1,83 @@
{
"id": "uni-map-common",
"displayName": "uni-map-common地图服务端API",
"version": "1.1.0",
"description": "聚合了多家地图供应商的服务端API几行代码即可快速接入地图API",
"keywords": [
"uni-map-common",
"地图服务端API"
],
"repository": "",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"type": "unicloud-template-function",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "插件不采集任何数据",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y",
"alipay": "y"
},
"client": {
"Vue": {
"vue2": "u",
"vue3": "u"
},
"App": {
"app-vue": "u",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "u",
"Android Browser": "u",
"微信浏览器(Android)": "u",
"QQ浏览器(Android)": "u"
},
"H5-pc": {
"Chrome": "u",
"IE": "u",
"Edge": "u",
"Firefox": "u",
"Safari": "u"
},
"小程序": {
"微信": "u",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u",
"钉钉": "u",
"快手": "u",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
# uni-map-common
聚合了多家地图供应商的服务端API
## 使用教程
> 文档地址:[https://uniapp.dcloud.net.cn/uniCloud/uni-map-common.html](https://uniapp.dcloud.net.cn/uniCloud/uni-map-common.html)
## bug反馈地址
> 加群:[uni-map交流群](https://im.dcloud.net.cn/#/?joinGroup=64d62b106823de10406ad72f)

View File

@@ -0,0 +1,100 @@
const service = require('./service/index.js');
class UniMap {
// 构造函数
constructor(data = {}) {
let {
provider, // 平台 weixin-mp 微信小程序 weixin-h5 微信公众号
key, // 密钥
needOriginalResult = false, // 是否需要返回原始信息默认false
} = data;
let runService = service[provider];
if (!runService) {
throw new Error(`不支持平台:${provider}`);
}
this.service = new runService({
provider,
key,
needOriginalResult
});
//return this.service;
}
// API - 逆地址解析(坐标转地址)
async location2address(data = {}) {
let res = await this._call("location2address", data);
return res;
}
// API - 地址解析(地址转坐标)
async address2location(data = {}) {
let res = await this._call("address2location", data);
return res;
}
// API - 坐标转换
async translate(data = {}) {
let res = await this._call("translate", data);
return res;
}
// API - IP定位
async ip2location(data = {}) {
let res = await this._call("ip2location", data);
return res;
}
// API - 关键词输入提示
async inputtips(data = {}) {
let res = await this._call("inputtips", data);
return res;
}
// API - 周边搜索
async search(data = {}) {
let res = await this._call("search", data);
return res;
}
// API - 行政区划
async districtSearch(data = {}) {
let res = await this._call("districtSearch", data);
return res;
}
// API - 路线规划(驾车/步行/骑行/电动车/公交)
async route(data = {}) {
let urlObj = {
"driving": "drivingRoute",
"walking": "walkingRoute",
"bicycling": "bicyclingRoute",
"ebicycling": "ebicyclingRoute",
"transit": "transitRoute"
};
let res = await this._call(urlObj[data.mode], data);
res.result.mode = data.mode;
return res;
}
// 私有函数
async _call(name, data = {}) {
let runFunction = this.service[name];
if (!runFunction) {
throw new Error(`平台:${this.service.config.provider} 不支持API${name}`);
}
let res = await runFunction.call(this.service, data); // 此处需要使用call防止里面的this作用域被意外改变
if (!this.service.config.needOriginalResult) {
delete res.originalResult;
}
//res = JSON.parse(JSON.stringify(res));
return {
provider: this.service.config.provider,
...res
};
}
}
module.exports = UniMap;

View File

@@ -0,0 +1,74 @@
/**
* 通用公共函数
*/
var common = {};
// 经纬度表示形式转换
common.getLocation = function(location = "", type = "", returnType = "") {
let lat;
let lng;
// 去除所有空格
type = type.trim();
returnType = returnType.replace(/\s+/g, '');
if (type === "lat,lng") {
location = location.replace(/\s+/g, '');
let arr = location.split(",");
lat = arr[0];
lng = arr[1];
} else if (type === "lng,lat") {
location = location.replace(/\s+/g, '');
let arr = location.split(",");
lat = arr[1];
lng = arr[0];
} else if (type === "lat lng") {
let arr = location.split(" ");
lat = arr[0];
lng = arr[1];
} else if (type === "lng lat") {
let arr = location.split(" ");
lat = arr[1];
lng = arr[0];
} else {
lat = location.lat;
lng = location.lng;
}
if (returnType == "lng,lat") {
return `${lng},${lat}`;
} else if (returnType == "lat,lng") {
return `${lat},${lng}`;
} else {
return {
lat: Number(lat),
lng: Number(lng)
}
}
};
// 字符串格式的坐标经纬度反转
common.getReversalLocation = function(input="") {
// 按分隔符拆分字符串
let parts = input.split("|");
// 遍历每个部分进行值交换
for (let i = 0; i < parts.length; i++) {
let pairs = parts[i].split(";");
for (let j = 0; j < pairs.length; j++) {
let values = pairs[j].split(",");
// 交换两个值
let temp = values[0];
values[0] = values[1];
values[1] = temp;
// 更新交换后的值
pairs[j] = values.join(",");
}
// 更新交换后的部分
parts[i] = pairs.join(";");
}
// 返回交换后的结果
return parts.join("|");
};
module.exports = common;

View File

@@ -0,0 +1,13 @@
const errSubject = "uni-map-common";
class UniCloudError {
constructor(options = {}) {
this.errCode = options.errCode || options.code;
this.errMsg = options.errMsg || options.msg || options.message || "";
this.errSubject = options.subject || errSubject;
}
}
module.exports = {
UniCloudError
}

View File

@@ -0,0 +1,7 @@
const common = require('./common');
const error = require('./error');
module.exports = {
common,
error
};

View File

@@ -0,0 +1,15 @@
{
"name": "uni-map-common",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"uni-config-center": "file:../../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"
}
}

View File

@@ -0,0 +1,979 @@
const libs = require('../libs');
// https://lbs.amap.com/api/webservice/guide/tools/info
const ERRCODE = {
"10000": 0,
"10001": 190,
"10002": 113,
"10003": 121,
"10004": 120,
"10005": 112,
"10006": 110,
"10007": 111,
"10008": 111,
"10009": 110,
"10010": 122,
"10011": 311,
"10012": 113,
"10013": 190,
"10014": 500,
"10015": 500,
"10016": 500,
"10017": 500,
"10019": 500,
"10020": 500,
"10021": 500,
"10026": 110,
"10029": 500,
"10041": 110,
"10044": 121,
"10045": 121,
"20000": 395,
"20001": 300,
"20002": 500,
"20003": 500,
"20011": 395,
"20012": 395,
"20801": 395,
"20802": 395,
"20803": 373,
"40000": 123,
"40001": 123,
"40002": 123,
"40003": 123
};
class Service {
// 构造函数
constructor(data = {}) {
let {
key,
needOriginalResult = false, // 是否需要返回原始信息默认false
} = data;
this.config = {
provider: "amap",
key,
needOriginalResult,
serviceUrl: "https://restapi.amap.com"
}
}
async request(obj = {}) {
let {
url,
data = {}
} = obj;
if (url.indexOf("http") !== 0) {
url = `${this.config.serviceUrl}/${url}`
}
if (this.config.key && !data.key) {
data.key = this.config.key;
}
obj.data = JSON.parse(JSON.stringify(obj.data));
let requestRes = await uniCloud.httpclient.request(url, obj);
let result = this.getResult(requestRes);
if (result.errCode != 0) {
throw new libs.error.UniCloudError(result);
}
return result;
}
getResult(requestRes) {
let {
data: originalResult = {}
} = requestRes;
let res = {
errCode: originalResult.infocode == "10000" ? 0 : this.getErrCode(originalResult.infocode),
errMsg: originalResult.info,
originalResult,
};
return res;
}
getErrCode(errCode) {
return ERRCODE[errCode] || errCode;
}
// API - 逆地址解析(坐标转地址)
async location2address(data = {}) {
let {
location,
get_poi,
poi_options,
} = data;
let requestData = {
location: libs.common.getLocation(location, "lat,lng", "lng,lat"),
extensions: get_poi ? "all" : "base",
};
if (get_poi && typeof poi_options == "object") {
let {
poitype,
radius,
roadlevel,
homeorcorp
} = poi_options;
requestData = Object.assign(requestData, {
poitype,
radius,
roadlevel,
homeorcorp
})
}
let requestRes = await this.request({
method: "GET",
url: "v3/geocode/regeo",
dataType: "json",
data: requestData
});
let originalResult = requestRes.originalResult.regeocode;
let pois;
if (originalResult.pois) {
pois = originalResult.pois.map((item) => {
return {
id: item.id,
title: item.name,
address: item.address,
location: libs.common.getLocation(item.location, "lng,lat", "object"),
distance: item.distance,
direction: item.direction,
category: item.type
}
});
}
let roads;
if (originalResult.roads) {
roads = originalResult.roads.map((item) => {
return {
id: item.id,
title: item.name,
distance: Number(item.distance),
direction: item.direction,
location: libs.common.getLocation(item.location, "lng,lat", "object")
}
});
}
let roadinters;
if (originalResult.roadinters) {
roadinters = originalResult.roadinters.map((item) => {
return {
distance: Number(item.distance),
direction: item.direction,
first_id: item.first_id,
first_name: item.first_name,
second_id: item.second_id,
second_name: item.second_name,
location: libs.common.getLocation(item.location, "lng,lat", "object")
}
});
}
let result = {
formatted_addresses: originalResult.formatted_address,
country: originalResult.addressComponent.country,
province: originalResult.addressComponent.province,
city: JSON.stringify(originalResult.addressComponent.city) === "[]" || !originalResult.addressComponent.city ? originalResult.addressComponent.province : originalResult
.addressComponent.city,
district: originalResult.addressComponent.district,
street: originalResult.addressComponent.country,
street_number: originalResult.addressComponent.streetNumber.street + originalResult.addressComponent.streetNumber.number,
adcode: originalResult.addressComponent.adcode,
pois,
roads,
roadinters
};
let res = {
result,
...requestRes
};
return res;
}
// API - 地址解析(地址转坐标)
async address2location(data = {}) {
let {
address,
city,
} = data;
let requestRes = await this.request({
method: "GET",
url: "v3/geocode/geo",
dataType: "json",
data: {
address,
city
}
});
let originalResult = requestRes.originalResult.geocodes[0];
let result = {
location: libs.common.getLocation(originalResult.location, "lng,lat", "object"),
adcode: originalResult.adcode,
province: originalResult.province,
city: originalResult.city,
district: originalResult.district,
street: originalResult.street,
street_number: originalResult.number,
};
let res = {
result,
...requestRes
};
return res;
}
// API - 坐标转换
async translate(data = {}) {
let {
locations,
type,
} = data;
let locationsStr = "";
locations.map((item, index) => {
if (index > 0) {
locationsStr += ";";
}
locationsStr += libs.common.getLocation(item, "object", "lng,lat");
})
let coordsys = {
"1": "gps",
"4": "mapbar",
"3": "baidu",
"": "autonavi",
} [type + ""];
let requestRes = await this.request({
method: "GET",
url: "v3/assistant/coordinate/convert",
dataType: "json",
data: {
locations: locationsStr,
coordsys
}
});
let originalResult = requestRes.originalResult;
let returnLocationsStr = originalResult.locations;
let arr = returnLocationsStr.split(";");
let returnLocations = arr.map((item) => {
return libs.common.getLocation(item, "lng,lat", "object");
});
let result = {
locations: returnLocations
};
let res = {
result,
...requestRes
};
return res;
}
// API - IP定位
async ip2location(data = {}) {
let {
ip,
} = data;
let requestRes = await this.request({
method: "GET",
url: "v3/ip",
dataType: "json",
data: {
ip
}
});
let originalResult = requestRes.originalResult;
let result = {
adcode: originalResult.adcode,
province: originalResult.province,
city: originalResult.city,
rectangle: originalResult.rectangle
};
let res = {
result,
...requestRes
};
return res;
}
// API - 关键词输入提示
async inputtips(data = {}) {
let {
keyword,
city,
citylimit,
location,
datatype,
} = data;
let requestData = {
keywords: keyword,
city,
citylimit,
datatype
};
if (location) {
requestData.location = libs.common.getLocation(location, "object", "lng,lat");
}
let requestRes = await this.request({
method: "GET",
url: "v3/assistant/inputtips",
dataType: "json",
data: requestData,
});
let originalResult = requestRes.originalResult;
let _data = originalResult.tips.map((item) => {
return {
id: item.id,
name: item.name,
address: item.address,
location: libs.common.getLocation(item.location, "lng,lat", "object"),
adcode: item.adcode,
district: item.district
}
});
let result = {
data: _data
};
let res = {
result,
...requestRes
};
return res;
}
// API - 周边搜索
async search(data = {}) {
let {
keyword,
location,
radius = 1000,
auto_extend = 1,
get_subpois,
orderby,
page_index = 1,
page_size = 20,
types,
city
} = data;
let requestData = {
keywords: keyword,
types,
location: libs.common.getLocation(location, "object", "lng,lat"),
radius,
sortrule: orderby,
region: city,
city_limit: auto_extend ? false : true,
page_num: page_index,
page_size,
show_fields: get_subpois ? "children,business,navi,photos" : "business,navi,photos"
};
let requestRes = await this.request({
method: "GET",
url: "v5/place/around",
dataType: "json",
data: requestData
});
let originalResult = requestRes.originalResult;
let _data = originalResult.pois.map((item) => {
return {
id: item.id,
title: item.name,
tel: item.business.tel,
address: item.address,
category: item.type,
location: libs.common.getLocation(item.location, "lng,lat", "object"),
distance: Number(item.distance),
adcode: item.adcode,
province: item.pname,
city: item.cityname,
district: item.adname,
children: item.children ? item.children.map((item2) => {
return {
parent_id: item.id,
id: item2.id,
title: item2.name,
address: item2.address,
category: item2.subtype,
location: libs.common.getLocation(item2.location, "lng,lat", "object")
}
}) : get_subpois ? [] : undefined,
}
});
let result = {
data: _data
};
let res = {
result,
...requestRes
};
return res;
}
// API - 行政区划
async districtSearch(data = {}) {
let {
adcode,
get_polygon,
page_index,
page_size,
filter,
subdistrict
} = data;
let requestData = {
keywords: adcode,
subdistrict,
page: page_index,
offset: page_size,
filter
};
let requestRes = await this.request({
method: "GET",
url: "v3/config/district",
dataType: "json",
data: requestData
});
let originalResult = requestRes.originalResult;
const formatDistricts = (list) => {
return list.map((item) => {
return {
adcode: item.adcode,
name: item.name,
fullname: item.name,
location: libs.common.getLocation(item.center, "lng,lat", "object"),
level: item.level,
children: typeof item.districts !== "undefined" ? formatDistricts(item.districts): undefined,
//polygon: item.polyline,
}
});
}
let _data = formatDistricts(originalResult.districts[0].districts);
let result = {
data: _data
};
let res = {
result,
...requestRes
};
return res;
}
// API - 路线规划(驾车)
async drivingRoute(data = {}) {
let {
mode,
from,
to,
from_poi,
to_poi,
policy,
waypoints,
avoid_polygons,
road_type,
plate_number,
cartype,
avoidroad,
ferry,
} = data;
let requestRes = await this.request({
method: "GET",
url: `v5/direction/driving`,
dataType: "json",
data: {
origin: libs.common.getLocation(from, "lat,lng", "lng,lat"),
destination: libs.common.getLocation(to, "lat,lng", "lng,lat"),
origin_id: from_poi,
destination_id: to_poi,
strategy: policy,
waypoints: libs.common.getReversalLocation(waypoints),
avoidpolygons: libs.common.getReversalLocation(avoid_polygons),
origin_type: road_type,
plate: plate_number,
cartype,
avoidroad,
ferry,
show_fields: "cost,tmcs,navi,cities,polyline"
}
});
let originalResult = requestRes.originalResult.route;
let routes = originalResult.paths.map((item) => {
let steps = item.steps.map((item2) => {
return {
instruction: item2.instruction,
road_name: item2.road_name,
dir_desc: item2.orientation,
distance: Number(item2.step_distance),
act_desc: item2.navi.action,
accessorial_desc: item2.navi.assistant_action,
cost: this.costFormat(item2.cost),
speed: item2.tmcs ? item2.tmcs.map((item3) => {
let levelIndex = {
"畅通": 0,
"缓行": 1,
"拥堵": 2,
"未知": 3,
"严重拥堵": 4,
}
return {
distance: Number(item3.tmc_distance),
level: levelIndex[item3.tmc_status],
polyline: this.polylineFormat(item3.tmc_polyline),
}
}) : undefined,
cities: item2.cities,
polyline: this.polylineFormat(item2.polyline),
}
});
return {
mode: "driving",
distance: Number(item.distance),
restriction_status: Number(item.restriction),
taxi_cost: Number(originalResult.taxi_cost),
steps
}
});
let result = {
routes
};
let res = {
result,
...requestRes
};
return res;
}
// API - 路线规划(步行)
async walkingRoute(data = {}) {
let {
mode,
from,
to,
alternative_route,
} = data;
let requestRes = await this.request({
method: "GET",
url: `v5/direction/walking`,
dataType: "json",
data: {
origin: libs.common.getLocation(from, "lat,lng", "lng,lat"),
destination: libs.common.getLocation(to, "lat,lng", "lng,lat"),
alternative_route,
show_fields: "cost,navi,polyline", // 此处强制传,为了和腾讯地图字段对齐
}
});
let originalResult = requestRes.originalResult.route;
let routes = originalResult.paths.map((item) => {
let duration1 = 0;
let steps = item.steps.map((item2) => {
let duration2 = this.durationFormat(item2.cost.duration);
duration1 += duration2;
return {
instruction: item2.instruction,
road_name: item2.road_name,
dir_desc: item2.orientation,
distance: Number(item2.step_distance),
act_desc: item2.navi.action || item2.navi.assistant_action,
taxi_cost: item2.cost.taxi ? this.priceFormat(item2.cost.taxi) : undefined,
duration: duration2,
polyline: this.polylineFormat(item2.polyline),
}
});
return {
mode: "walking",
distance: Number(item.distance),
duration: duration1,
steps
}
});
let result = {
routes
};
let res = {
result,
...requestRes
};
return res;
}
// API - 路线规划(骑行)
async bicyclingRoute(data = {}) {
let {
mode,
from,
to,
alternative_route,
} = data;
let requestRes = await this.request({
method: "GET",
url: `v5/direction/bicycling`,
dataType: "json",
data: {
origin: libs.common.getLocation(from, "lat,lng", "lng,lat"),
destination: libs.common.getLocation(to, "lat,lng", "lng,lat"),
alternative_route,
show_fields: "cost,navi,polyline", // 此处强制传,为了和腾讯地图字段对齐
}
});
let originalResult = requestRes.originalResult.route;
let routes = originalResult.paths.map((item) => {
let duration1 = 0;
let steps = item.steps.map((item2) => {
let duration2 = this.durationFormat(item2.cost.duration);
duration1 += duration2;
return {
instruction: item2.instruction,
road_name: item2.road_name,
dir_desc: item2.orientation,
distance: Number(item2.step_distance),
act_desc: item2.navi.action || item2.navi.assistant_action,
duration: duration2,
polyline: this.polylineFormat(item2.polyline),
}
});
return {
mode: "walking",
distance: Number(item.distance),
duration: duration1,
steps
}
});
let result = {
routes
};
let res = {
result,
...requestRes
};
return res;
}
// API - 路线规划(电动车)
async ebicyclingRoute(data = {}) {
let {
mode,
from,
to,
alternative_route,
} = data;
let requestRes = await this.request({
method: "GET",
url: `v5/direction/electrobike`,
dataType: "json",
data: {
origin: libs.common.getLocation(from, "lat,lng", "lng,lat"),
destination: libs.common.getLocation(to, "lat,lng", "lng,lat"),
alternative_route,
show_fields: "cost,navi,polyline", // 此处强制传,为了和腾讯地图字段对齐
}
});
let originalResult = requestRes.originalResult.route;
let routes = originalResult.paths.map((item) => {
let duration1 = 0;
let steps = item.steps.map((item2) => {
let duration2 = this.durationFormat(item2.cost.duration);
duration1 += duration2;
return {
instruction: item2.instruction,
road_name: item2.road_name,
dir_desc: item2.orientation,
distance: Number(item2.step_distance),
act_desc: item2.navi.action || item2.navi.assistant_action,
duration: duration2,
polyline: this.polylineFormat(item2.polyline),
}
});
return {
mode: "walking",
distance: Number(item.distance),
duration: duration1,
steps
}
});
let result = {
routes
};
let res = {
result,
...requestRes
};
return res;
}
// API - 路线规划(公交)
async transitRoute(data = {}) {
let {
mode,
from,
to,
from_poi,
to_poi,
policy,
ad1,
ad2,
city1,
city2,
alternative_route,
multiexport,
max_trans,
nightflag,
date,
time
} = data;
let requestRes = await this.request({
method: "GET",
url: `v5/direction/transit/integrated`,
dataType: "json",
data: {
origin: libs.common.getLocation(from, "lat,lng", "lng,lat"),
destination: libs.common.getLocation(to, "lat,lng", "lng,lat"),
originpoi: from_poi,
destinationpoi: to_poi,
strategy: policy,
ad1,
ad2,
city1,
city2,
AlternativeRoute: alternative_route,
multiexport,
max_trans,
nightflag,
date,
time,
show_fields: "cost,navi,polyline", // 此处强制传,为了和腾讯地图字段对齐
}
});
let originalResult = requestRes.originalResult.route;
let routes = originalResult.transits.map((item) => {
let stepsItem = this.getSteps(item.segments);
let steps = stepsItem.map((item2) => {
let mode = item2.mode.toLowerCase();
if (mode === "walking") {
// 步行
return {
mode: "walking",
distance: Number(item2.distance),
duration: this.durationFormat(item2.cost.duration),
steps: item2.steps.map((item3) => {
return {
instruction: item3.instruction,
road_name: item3.road,
distance: Number(item3.distance),
act_desc: item3.navi.action || item3.navi.assistant_action,
polyline: this.polylineFormat(item3.polyline)
}
}),
}
} else if (mode === "bus") {
return {
mode: "transit",
lines: item2.buslines.map((item3) => {
return {
vehicle: item3.type.indexOf("地铁") > -1 ? "SUBWAY" : "BUS",
id: item3.id,
title: item3.name,
type: item3.type,
station_count: Number(item3.via_num),
distance: Number(item3.distance),
duration: this.durationFormat(item3.cost.duration),
polyline: this.polylineFormat(item3.polyline),
start_time: item3.start_time,
end_time: item3.end_time,
geton: {
id: item3.departure_stop.id,
title: item3.departure_stop.name,
location: libs.common.getLocation(item3.departure_stop.location, "lng,lat", "object"),
},
getoff: {
id: item3.arrival_stop.id,
title: item3.arrival_stop.name,
location: libs.common.getLocation(item3.arrival_stop.location, "lng,lat", "object"),
},
stations: item3.via_stops.map((item4) => {
return {
id: item4.id,
title: item4.name,
location: libs.common.getLocation(item4.location, "lng,lat", "object"),
}
})
}
}),
}
} else if (mode === "railway") {
// 火车
let item3 = item2;
return {
mode: "transit",
lines: [{
vehicle: "RAIL",
id: item3.id,
title: item3.name,
type: item3.type,
distance: Number(item3.distance),
duration: this.durationFormat(item3.time),
geton: {
id: item3.departure_stop.id,
title: item3.departure_stop.name,
location: libs.common.getLocation(item3.departure_stop.location, "lng lat", "object"),
adcode: item3.departure_stop.adcode,
time: item3.departure_stop.time,
start: Number(item3.departure_stop.start),
},
getoff: {
id: item3.arrival_stop.id,
title: item3.arrival_stop.name,
location: libs.common.getLocation(item3.arrival_stop.location, "lng lat", "object"),
adcode: item3.arrival_stop.adcode,
time: item3.arrival_stop.time,
end: Number(item3.arrival_stop.end),
},
spaces: item3.spaces ? item3.spaces.map((item4) => {
return {
code: item4.code,
cost: this.priceFormat(item4.cost),
}
}) : undefined
}],
}
} else if (mode === "taxi") {
// 打车
let item3 = item2;
return {
mode: "transit",
lines: [{
vehicle: "TAXI",
distance: Number(item3.distance),
price: this.priceFormat(item3.price),
drivetime: this.durationFormat(item3.drivetime),
polyline: this.polylineFormat(item3.polyline),
startpoint: libs.common.getLocation(item3.startpoint, "lng,lat", "lat,lng"),
startname: item3.startname,
endpoint: libs.common.getLocation(item3.endpoint, "lng,lat", "lat,lng"),
endname: item3.endname
}]
}
}
});
return {
mode: "transit",
distance: Number(item.distance),
duration: this.durationFormat(item.cost.duration),
transit_fee: this.priceFormat(item.cost.transit_fee),
steps
}
});
let result = {
routes
};
let res = {
result,
...requestRes
};
return res;
}
getSteps(segments) {
let steps = [];
segments.map((item, index) => {
for (let mode in item) {
steps.push({
mode,
...item[mode]
});
}
});
return steps;
}
// 格式化价格将字符串价格转成数值保留2位小数
priceFormat(price) {
try {
if (price === "") {
return -1;
} else {
return parseFloat(Number(price).toFixed(2));
}
} catch (err) {
return -1;
}
}
// 格式化cost
costFormat(cost = {}) {
let {
duration,
taxi_cost,
transit_fee,
tolls,
toll_distance,
toll_road,
traffic_lights
} = cost;
let res = {};
if (typeof duration !== "undefined") res.duration = this.durationFormat(duration);
if (typeof taxi_cost !== "undefined") res.taxi_cost = this.priceFormat(taxi_cost);
if (typeof transit_fee !== "undefined") res.transit_fee = this.priceFormat(transit_fee);
if (typeof tolls !== "undefined") res.tolls = this.priceFormat(tolls);
if (typeof toll_distance !== "undefined") res.toll_distance = Number(toll_distance);
if (typeof toll_road !== "undefined") res.toll_road = toll_road;
if (typeof traffic_lights !== "undefined") res.traffic_lights = Number(traffic_lights);
return res;
}
// 格式化polyline将原本polyline.polyline转成polyline
polylineFormat(polyline = {}) {
if (polyline.polyline) {
return libs.common.getReversalLocation(polyline.polyline);
} else if (typeof polyline === "string") {
return libs.common.getReversalLocation(polyline);
} else {
return "";
}
}
// 格式化时间秒转分向上进1
durationFormat(duration) {
try {
return Math.ceil(Number(duration) / 60);
} catch (err) {
return undefined;
}
}
}
module.exports = Service;

View File

@@ -0,0 +1,4 @@
module.exports = {
"qqmap": require('./qqmap.js'),
"amap": require('./amap.js')
}

View File

@@ -0,0 +1,847 @@
const libs = require('../libs');
class Service {
// 构造函数
constructor(data = {}) {
let {
key,
needOriginalResult = false, // 是否需要返回原始信息默认false
} = data;
this.config = {
provider: "qqmap",
key,
needOriginalResult,
serviceUrl: "https://apis.map.qq.com"
}
}
async request(obj = {}) {
let {
url,
data = {}
} = obj;
if (url.indexOf("http") !== 0) {
url = `${this.config.serviceUrl}/${url}`
}
if (this.config.key && !data.key) {
data.key = this.config.key;
}
obj.data = JSON.parse(JSON.stringify(obj.data));
let requestRes = await uniCloud.httpclient.request(url, obj);
let result = this.getResult(requestRes);
if (result.errCode != 0) {
throw new libs.error.UniCloudError(result);
}
return result;
}
getResult(requestRes) {
let {
data: originalResult = {}
} = requestRes;
let res = {
errCode: originalResult.status == 0 ? 0 : this.getErrCode(originalResult.status),
errMsg: originalResult.message,
originalResult,
};
return res;
}
getErrCode(errCode) {
return errCode;
}
// API - 逆地址解析(坐标转地址)
async location2address(data = {}) {
let {
location,
get_poi,
poi_options
} = data;
let _poi_options = "";
if (typeof poi_options === "object") {
let {
address_format,
radius,
policy
} = poi_options;
if (address_format && address_format !== "long") {
_poi_options += `address_format=${address_format};`
}
if (radius) {
_poi_options += `radius=${radius};`
}
if (policy) {
_poi_options += `policy=${policy};`
}
if (_poi_options.lastIndexOf(";") === _poi_options.length - 1) {
_poi_options = _poi_options.substring(0, _poi_options.length - 1);
}
}
if (!_poi_options) _poi_options = undefined;
let requestRes = await this.request({
method: "GET",
url: "ws/geocoder/v1/",
dataType: "json",
data: {
location,
get_poi,
poi_options: _poi_options,
}
});
let originalResult = requestRes.originalResult.result;
let pois;
if (originalResult.pois) {
pois = originalResult.pois.map((item) => {
return {
id: item.id,
title: item.title,
address: item.address,
location: item.location,
distance: item._distance,
direction: item._dir_desc,
category: item.category
}
});
}
let result = {
formatted_addresses: originalResult.address,
country: originalResult.address_component.nation,
province: originalResult.address_component.province,
city: originalResult.address_component.city,
district: originalResult.address_component.district,
street: originalResult.address_component.street,
street_number: originalResult.address_component.street_number,
adcode: originalResult.ad_info.adcode,
pois
};
let res = {
result,
...requestRes
};
return res;
}
// API - 地址解析(地址转坐标)
async address2location(data = {}) {
let {
address,
city,
} = data;
let requestRes = await this.request({
method: "GET",
url: "ws/geocoder/v1/",
dataType: "json",
data: {
smart_address: address,
region: city,
}
});
let originalResult = requestRes.originalResult.result;
let result = {
location: originalResult.location,
adcode: originalResult.ad_info.adcode,
province: originalResult.address_components.province,
city: originalResult.address_components.city,
district: originalResult.address_components.district,
street: originalResult.address_components.street,
street_number: originalResult.address_components.street_number,
};
let res = {
result,
...requestRes
};
return res;
}
// API - 坐标转换
async translate(data = {}) {
let {
locations,
type,
} = data;
let locationsStr = "";
locations.map((item, index) => {
if (index > 0) {
locationsStr += ";";
}
locationsStr += libs.common.getLocation(item, "object", "lat,lng");
})
let requestRes = await this.request({
method: "GET",
url: "ws/coord/v1/translate",
dataType: "json",
data: {
locations: locationsStr,
type
}
});
let originalResult = requestRes.originalResult;
let result = {
locations: originalResult.locations
};
let res = {
result,
...requestRes
};
return res;
}
// API - IP定位
async ip2location(data = {}) {
let {
ip,
} = data;
let requestRes = await this.request({
method: "GET",
url: "ws/location/v1/ip",
dataType: "json",
data: {
ip
}
});
let originalResult = requestRes.originalResult.result;
let result = {
location: libs.common.getLocation(originalResult.location, "object", "object"),
nation: originalResult.ad_info.nation,
nation_code: originalResult.ad_info.nation_code,
adcode: originalResult.ad_info.adcode,
province: originalResult.ad_info.province,
city: originalResult.ad_info.city,
district: originalResult.ad_info.district
};
let res = {
result,
...requestRes
};
return res;
}
// API - 关键词输入提示
async inputtips(data = {}) {
let {
keyword,
city,
citylimit,
location,
get_subpois,
policy,
filter,
address_format,
page_index,
page_size
} = data;
let requestData = {
keyword,
region: city,
region_fix: citylimit ? 1 : 0,
get_subpois,
policy,
filter,
address_format,
page_index,
page_size
};
if (location) {
requestData.location = libs.common.getLocation(location, "object", "lat,lng");
}
let requestRes = await this.request({
method: "GET",
url: "ws/place/v1/suggestion",
dataType: "json",
data: requestData
});
let originalResult = requestRes.originalResult;
let _data = originalResult.data.map((item) => {
let children;
if (originalResult.sub_pois) {
children = [];
originalResult.sub_pois.map((item2) => {
if (item2.parent_id === item.id) {
children.push({
parent_id: item.id,
id: item2.id,
title: item2.title,
address: item2.address,
category: item2.category,
location: item2.location,
adcode: String(item2.adcode),
city: item2.city,
});
}
});
}
return {
id: item.id,
title: item.title,
address: item.address,
category: item.category,
type: item.type,
location: item.location,
adcode: item.adcode,
province: item.province,
city: item.city,
district: item.district,
children
}
});
let result = {
data: _data
};
let res = {
result,
...requestRes
};
return res;
}
// API - 周边搜索
async search(data = {}) {
let {
keyword,
location,
radius = 1000,
auto_extend = 1,
get_subpois,
orderby,
page_index = 1,
page_size = 20,
filter
} = data;
if (radius < 10) radius = 10;
let boundary = `nearby(${location.lat},${location.lng},${radius},${auto_extend})`;
let requestData = {
keyword,
boundary,
get_subpois,
filter,
orderby: orderby === "distance" ? "_distance" : undefined,
page_index,
page_size
};
let requestRes = await this.request({
method: "GET",
url: "ws/place/v1/search",
dataType: "json",
data: requestData
});
let originalResult = requestRes.originalResult;
let _data = originalResult.data.map((item) => {
let children;
if (originalResult.sub_pois) {
children = [];
originalResult.sub_pois.map((item2) => {
if (item2.parent_id === item.id) {
children.push({
parent_id: item.id,
id: item2.id,
title: item2.title,
address: item2.address,
category: item2.category,
location: item2.location,
tel: item2.tel,
adcode: String(item2.ad_info.adcode),
province: item2.ad_info.province,
city: item2.ad_info.city,
district: item2.ad_info.district,
});
}
});
}
return {
id: item.id,
title: item.title,
tel: item.tel,
address: item.address,
category: item.category,
type: item.type,
location: item.location,
distance: item._distance,
adcode: String(item.ad_info.adcode),
province: item.ad_info.province,
city: item.ad_info.city,
district: item.ad_info.district,
children
}
});
let result = {
data: _data
};
let res = {
result,
...requestRes
};
return res;
}
// API - 行政区划
async districtSearch(data = {}) {
let {
adcode,
get_polygon,
max_offset
} = data;
let requestData = {
id: adcode,
get_polygon,
max_offset
};
let requestRes = await this.request({
method: "GET",
url: "ws/district/v1/getchildren",
dataType: "json",
data: requestData
});
let originalResult = requestRes.originalResult;
let _data = originalResult.result[0].map((item) => {
return {
adcode: item.id,
name: item.name || item.fullname,
fullname: item.fullname,
location: item.location,
pinyin: item.pinyin,
cidx: item.cidx,
polygon: item.polygon,
}
});
let result = {
data: _data,
data_version: originalResult.data_version
};
let res = {
result,
...requestRes
};
return res;
}
// API - 路线规划(驾车)
async drivingRoute(data = {}) {
let {
mode,
from,
to,
from_poi,
to_poi,
policy,
waypoints,
avoid_polygons,
road_type,
plate_number,
cartype,
heading,
speed,
accuracy,
from_track,
get_mp,
no_step
} = data;
let requestRes = await this.request({
method: "GET",
url: `ws/direction/v1/driving`,
dataType: "json",
data: {
from,
to,
from_poi,
to_poi,
policy,
waypoints,
avoid_polygons,
road_type,
plate_number,
cartype,
heading,
speed,
accuracy,
from_track,
get_mp,
get_speed: 1,
added_fields: "cities",
no_step
}
});
let originalResult = requestRes.originalResult.result;
let routes = originalResult.routes.map((item) => {
let waypoints;
if (item.waypoints) {
waypoints = item.waypoints.map((item2) => {
return {
title: item2.title,
location: item2.location,
duration: item2.duration,
distance: item2.distance,
polyline: this.getPolyline(item.polyline, item2.polyline_idx),
polyline_idx: item2.polyline_idx,
}
});
}
let steps = item.steps.map((item2) => {
return {
instruction: item2.instruction,
road_name: item2.road_name,
dir_desc: item2.dir_desc,
distance: item2.distance,
act_desc: item2.act_desc,
accessorial_desc: item2.accessorial_desc,
polyline: this.getPolyline(item.polyline, item2.polyline_idx),
polyline_idx: item2.polyline_idx,
}
});
let speed = item.speed.map((item2) => {
return {
distance: item2.distance,
level: item2.level,
polyline: this.getPolyline(item.polyline, item2.polyline_idx),
polyline_idx: item2.polyline_idx,
}
});
return {
mode: "driving",
tags: item.tags,
distance: item.distance,
duration: item.duration,
traffic_light_count: item.traffic_light_count,
restriction_status: item.restriction.status,
polyline: this.polylineFormat(item.polyline),
waypoints,
taxi_cost: item.taxi_fare.fare,
cities: item.cities,
steps,
speed
}
});
let result = {
routes
};
let res = {
result,
...requestRes
};
return res;
}
// API - 路线规划(步行)
async walkingRoute(data = {}) {
let {
mode,
from,
to,
to_poi
} = data;
let requestRes = await this.request({
method: "GET",
url: `ws/direction/v1/walking`,
dataType: "json",
data: {
from,
to,
to_poi
}
});
let originalResult = requestRes.originalResult.result;
let routes = originalResult.routes.map((item) => {
let steps = item.steps.map((item2) => {
return {
instruction: item2.instruction,
road_name: item2.road_name,
dir_desc: item2.dir_desc,
distance: item2.distance,
act_desc: item2.act_desc,
type: item2.type,
polyline: this.getPolyline(item.polyline, item2.polyline_idx),
polyline_idx: item2.polyline_idx,
}
});
return {
mode: "walking",
distance: item.distance,
duration: item.duration,
direction: item.direction,
polyline: this.polylineFormat(item.polyline),
steps
}
});
let result = {
routes
};
let res = {
result,
...requestRes
};
return res;
}
// API - 路线规划(骑行)
async bicyclingRoute(data = {}) {
let {
mode,
from,
to,
to_poi
} = data;
let requestRes = await this.request({
method: "GET",
url: `ws/direction/v1/bicycling`,
dataType: "json",
data: {
from,
to,
to_poi
}
});
let originalResult = requestRes.originalResult.result;
let routes = originalResult.routes.map((item) => {
let steps = item.steps.map((item2) => {
return {
instruction: item2.instruction,
road_name: item2.road_name,
dir_desc: item2.dir_desc,
distance: item2.distance,
act_desc: item2.act_desc,
polyline: this.getPolyline(item.polyline, item2.polyline_idx),
polyline_idx: item2.polyline_idx
}
});
return {
mode: "bicycling",
distance: item.distance,
duration: item.duration,
direction: item.direction,
polyline: this.polylineFormat(item.polyline),
steps
}
});
let result = {
routes
};
let res = {
result,
...requestRes
};
return res;
}
// API - 路线规划(电动车)
async ebicyclingRoute(data = {}) {
let {
mode,
from,
to,
to_poi
} = data;
let requestRes = await this.request({
method: "GET",
url: `ws/direction/v1/ebicycling`,
dataType: "json",
data: {
from,
to,
to_poi
}
});
let originalResult = requestRes.originalResult.result;
let routes = originalResult.routes.map((item) => {
let steps = item.steps.map((item2) => {
return {
instruction: item2.instruction,
polyline_idx: item2.polyline_idx,
road_name: item2.road_name,
dir_desc: item2.dir_desc,
distance: item2.distance,
act_desc: item2.act_desc,
polyline: this.getPolyline(item.polyline, item2.polyline_idx)
}
});
return {
mode: "ebicycling",
distance: item.distance,
duration: item.duration,
direction: item.direction,
polyline: this.polylineFormat(item.polyline),
steps
}
});
let result = {
routes
};
let res = {
result,
...requestRes
};
return res;
}
// API - 路线规划(公交)
async transitRoute(data = {}) {
let {
mode,
from,
to,
from_poi,
to_poi,
departure_time,
policy
} = data;
let requestRes = await this.request({
method: "GET",
url: `ws/direction/v1/transit`,
dataType: "json",
data: {
from,
to,
from_poi,
to_poi,
departure_time,
policy
}
});
let originalResult = requestRes.originalResult.result;
let routes = originalResult.routes.map((item) => {
let steps = item.steps.map((item2) => {
let mode = item2.mode.toLowerCase();
if (mode === "walking") {
// 步行
return {
mode: mode,
distance: item2.distance,
duration: item2.duration,
direction: item2.direction,
polyline: this.polylineFormat(item2.polyline),
steps: item2.steps ? item2.steps.map((item3) => {
return {
instruction: item3.instruction,
road_name: item3.road_name,
act_desc: item3.dir_desc,
distance: item3.distance,
polyline: this.getPolyline(item2.polyline, item3.polyline_idx),
polyline_idx: item3.polyline_idx,
}
}) : undefined,
}
} else {
// 非步行
return {
mode: mode,
lines: item2.lines.map((item3) => {
return {
...item3,
price: item3.vehicle !== "RAIL" ? this.priceFormat(item3.price) : item3.price,
polyline: this.polylineFormat(item3.polyline)
}
})
}
}
});
return {
mode: "transit",
distance: item.distance,
duration: item.duration,
bounds: item.bounds,
steps
}
});
let result = {
routes
};
let res = {
result,
...requestRes
};
return res;
}
// 格式化polyline将压缩的polyline还原成完整的经纬度
polylineFormat(polyline) {
try {
let coors = JSON.parse(JSON.stringify(polyline));
for (let i = 2; i < coors.length; i++) {
coors[i] = parseFloat((coors[i - 2] + coors[i] / 1000000).toFixed(6));
}
return coors;
} catch (err) {
return "";
}
}
// 格式化价格将以分为单位的价格转元保留2位小数
priceFormat(price) {
try {
if (price === "" || price == -1) {
return -1;
} else {
return parseFloat((price / 100).toFixed(2));
}
} catch (err) {
return -1;
}
}
getPolyline(polyline, polyline_idx) {
let polylineArr = this.polylineFormat(polyline);
if (typeof polyline_idx == "object") {
let arr = polylineArr.slice(polyline_idx[0], polyline_idx[1] + 1);
let str = "";
arr.map((item, index) => {
if (index % 2 === 0) {
str += `${item}`
} else {
str += `,${item};`
}
});
// 去除最后一个;
if (str.lastIndexOf(";") === str.length - 1) {
str = str.substring(0, str.length - 1);
}
return str;
} else {
return polylineArr[polyline_idx] + "," + polylineArr[polyline_idx + 1];
}
}
}
module.exports = Service;

View File

@@ -0,0 +1,501 @@
// 引入uni-map-common公共模块
const UniMap = require('uni-map-common');
const configCenter = require("uni-config-center");
// 读取配置中心地图配置
var UniMapConfig = configCenter({ pluginId: 'uni-map' }).requireFile('config.js');
// 本地地图配置
var LocalMapConfig = {
"default": "", // 默认使用的平台
"key": {
"qqmap": "", // 腾讯地图key
"amap": "", // 高德地图key
}
}
const db = uniCloud.database();
const _ = db.command;
const $ = _.aggregate;
const opendbPoiDB = db.collection("opendb-poi");
module.exports = {
_before: function() {
// 如果配置中心不存在地图配置,则使用本地地图配置
if (!UniMapConfig) {
UniMapConfig = LocalMapConfig;
}
let defaultProvider = UniMapConfig.default || "qqmap";
let params = this.getParams();
let {
provider = defaultProvider
} = params[0] || {};
console.log('provider: ', provider)
const key = UniMapConfig.key[provider] || LocalMapConfig.key[provider];
if (!key) {
throw { errCode: -1, errMsg: `请在uni-config-center/uni-map/config.js中或LocalMapConfig中配置地图供应商${provider}对应的key` };
}
// 初始化实例
let uniMap = new UniMap({
provider: provider, // 指定使用哪家地图供应商
key: key,
needOriginalResult: false
});
this.uniMap = uniMap;
},
_after: function(error, res) {
if (error) {
throw error; // 如果方法抛出错误,也直接抛出不处理
}
console.log("result", res.result);
return res;
},
// 经纬度坐标转地址
async location2address(data = {}) {
let res = {};
// 获取uniMap实例
const uniMap = this.uniMap;
// 调用API
let result = await uniMap.location2address(data);
res.result = result;
return res;
},
// 地址转经纬度坐标
async address2location(data = {}) {
let res = {};
// 获取uniMap实例
const uniMap = this.uniMap;
// 调用API
let result = await uniMap.address2location(data);
res.result = result;
return res;
},
// 坐标系转换
async translate(data = {}) {
let res = {};
// 获取uniMap实例
const uniMap = this.uniMap;
// 调用API
let result = await uniMap.translate(data);
res.result = result;
return res;
},
// ip定位
async ip2location(data = {}) {
let res = {};
// 获取uniMap实例
const uniMap = this.uniMap;
// 调用API
let result = await uniMap.ip2location(data);
res.result = result;
return res;
},
// 输入提示
async inputtips(data = {}) {
let res = {};
// 获取uniMap实例
const uniMap = this.uniMap;
// 调用API
let result = await uniMap.inputtips(data);
res.result = result;
return res;
},
// 搜索
async search(data = {}) {
let res = {};
// 获取uniMap实例
const uniMap = this.uniMap;
// 调用API
let result = await uniMap.search(data);
res.result = result;
return res;
},
// 行政区划
async districtSearch(data = {}) {
let res = {};
// 获取uniMap实例
const uniMap = this.uniMap;
// 调用API
let result = await uniMap.districtSearch(data);
res.result = result;
return res;
},
// 路径规划
async route(data = {}) {
let res = {};
// 获取uniMap实例
const uniMap = this.uniMap;
// 调用API
let result = await uniMap.route(data);
res.result = result;
return res;
},
// 演示用 - 清空所有的测试POI
async clearPoi(data = {}) {
let res = { errCode: 0 };
const db = uniCloud.database();
await db.collection("opendb-poi").where({
is_random: true
}).remove();
return res;
},
// 演示用 - 初始化静态001场景演示数据
async initStatic001(data = {}) {
let res = { errCode: 0 };
const category = "static-001";
// 先删除
await opendbPoiDB.where({
category: category
}).remove();
// 后添加随机数据
// 以天安门为中心
let tiananmen = {
longitude: 116.39747,
latitude: 39.908823,
};
let time = Date.now();
// 随机生成6个门店地址
let list = [];
for (let i = 1; i <= 6; i++) {
let randomCoordinate = getRandomCoordinateWithinRadius(tiananmen.longitude, tiananmen.latitude, 10); // 随机生成在天安门方圆X KM内的坐标
list.push({
category: category, // 场景值用于区分这些POI所属哪张地图
type: "门店",
title: `随机门店-${i}`,
location: new db.Geo.Point(randomCoordinate.longitude, randomCoordinate.latitude),
create_date: time,
visible: true,
is_random: true, // 表示此为随机生成的点,方便删除
level: i
});
}
// 随机生成1个总部地址
let randomCoordinate = getRandomCoordinateWithinRadius(tiananmen.longitude, tiananmen.latitude, 1); // 随机生成在天安门方圆X KM内的坐标
list.push({
category: category, // 场景值用于区分这些POI所属哪张地图
type: "总部",
title: `随机总部`,
location: new db.Geo.Point(randomCoordinate.longitude, randomCoordinate.latitude),
create_date: time,
visible: true,
is_random: true, // 表示此为随机生成的点,方便删除
level: 7
});
// 添加到数据库
await opendbPoiDB.add(list);
return res;
},
// 演示用 - 初始化动态001场景演示数据模拟送外卖场景
async initDynamics001(data = {}) {
let res = { errCode: 0 };
const category = "dynamics-001";
// 先删除
await opendbPoiDB.where({
category: category
}).remove();
// 后添加随机数据
// 以天安门为中心
let tiananmen = {
longitude: 116.39747,
latitude: 39.908823,
};
let time = Date.now();
// 随机生成配送员坐标
let randomCoordinate1 = getRandomCoordinateWithinRadius(tiananmen.longitude, tiananmen.latitude, 2); // 随机生成在天安门方圆X KM内的坐标
let data1 = {
category: category, // 场景值用于区分这些POI所属哪张地图
type: "配送员",
title: "配送员",
location: new db.Geo.Point(randomCoordinate1.longitude, randomCoordinate1.latitude),
create_date: time,
visible: true,
is_random: true, // 表示此为随机生成的点,方便删除
}
// 随机生成目的地坐标
let randomCoordinate2 = getRandomCoordinateWithinRadius(tiananmen.longitude, tiananmen.latitude, 2); // 随机生成在天安门方圆X KM内的坐标
let data2 = {
category: category, // 场景值用于区分这些POI所属哪张地图
type: "目的地",
title: "配送目的地",
location: new db.Geo.Point(randomCoordinate2.longitude, randomCoordinate2.latitude),
create_date: time,
visible: true,
is_random: true, // 表示此为随机生成的点,方便删除
}
let list = [data1, data2];
// 添加到数据库
await opendbPoiDB.add(list);
// 获取配送路线
// 获取uniMap实例
const uniMap = this.uniMap;
// 调用电瓶车路径规划API
let result = await uniMap.route({
mode: "ebicycling",
from: `${randomCoordinate1.latitude},${randomCoordinate1.longitude}`,
to: `${randomCoordinate2.latitude},${randomCoordinate2.longitude}`,
alternative_route: 1
});
let route = result.result.routes[0];
let { steps = [] } = route;
let points = [];
steps.map((step) => {
let {
polyline = ""
} = step;
let arr = polyline.split(";");
arr.map((item) => {
let arr2 = item.split(",");
points.push({
latitude: arr2[0],
longitude: arr2[1],
});
});
});
let polyline = {
points,
color: "#19b411",
width: 6,
dottedLine: false,
arrowLine: true,
borderWidth: 1,
borderColor: "#000000",
};
res.polyline = [polyline];
return res;
},
// 演示用 - 获取配送员配送路径
async getPolyline(data = {}) {
let res = { errCode: 0 };
const category = "dynamics-001";
let getRes1 = await opendbPoiDB.where({
category: category,
type: "配送员",
visible: true
}).get();
let poi1 = getRes1.data[0];
let getRes2 = await opendbPoiDB.where({
category: category,
type: "目的地",
visible: true
}).get();
let poi2 = getRes2.data[0];
if (!poi2) {
return {
errCode: 0,
end: true
}
}
let coordinate1 = {
longitude: poi1.location.coordinates[0],
latitude: poi1.location.coordinates[1]
};
let coordinate2 = {
longitude: poi2.location.coordinates[0],
latitude: poi2.location.coordinates[1]
};
// 获取uniMap实例
const uniMap = this.uniMap;
// 调用电瓶车路径规划API
let result = await uniMap.route({
mode: "ebicycling",
from: `${coordinate1.latitude},${coordinate1.longitude}`,
to: `${coordinate2.latitude},${coordinate2.longitude}`,
alternative_route: 1
});
let route = result.result.routes[0];
//console.log('route: ', route)
let { steps = [], distance, duration } = route;
let points = [];
let dir_desc;
steps.map((step) => {
let {
polyline = ""
} = step;
if (!dir_desc) dir_desc = step.dir_desc;
if (polyline) {
let arr = polyline.split(";");
arr.map((item) => {
let arr2 = item.split(",");
if (!isNaN(arr2[0]) && !isNaN(arr2[1])) {
points.push({
latitude: Number(arr2[0]),
longitude: Number(arr2[1]),
});
}
});
}
});
let polyline = {
points,
color: "#19b411",
width: 6,
dottedLine: false,
arrowLine: true,
borderWidth: 1,
borderColor: "#000000",
};
res.polyline = [polyline];
if (distance <= 30 || duration <= 0) {
await opendbPoiDB.doc(poi1._id).update({
title: `配送员已到达目的地`,
location: new db.Geo.Point(Number(coordinate2.longitude), Number(coordinate2.latitude)),
rotate: 0
});
// 隐藏目的地
await opendbPoiDB.doc(poi2._id).update({
visible: false,
});
return {
errCode: 0,
end: true
}
} else {
// 从最近2个点计算出当前行驶方向
let rotate = 0;
if (points && points.length >= 2) {
rotate = calculateDirectionAngle(points[0], points[1]);
}
await opendbPoiDB.doc(poi1._id).update({
title: `配送员正在配送\r\n还有 ${distance}\r\n预计 ${duration} 分钟送达`,
rotate: rotate, // 设置角度0°的图片方向应朝左(西) 故90° 朝上(北) 180° 朝右(东) 270° 朝下(南)
});
}
return res;
},
// 演示用 - 模拟上报配送员坐标
async updateMyLocation(data = {}) {
let res = {};
const category = "dynamics-001";
let {
longitude,
latitude
} = data;
let getRes1 = await opendbPoiDB.where({
category: category,
type: "配送员",
visible: true
}).get();
let poi1 = getRes1.data[0];
await opendbPoiDB.doc(poi1._id).update({
location: new db.Geo.Point(Number(longitude), Number(latitude))
});
return res;
},
// 演示用 - xxxx
async test(data = {}) {
let res = {};
// 获取uniMap实例
const uniMap = this.uniMap;
// 调用API
let result = await uniMap.location2address({
});
res.result = result;
return res;
}
}
/**
* 生成在指定经纬度圆内的随机坐标
const latitude = 39.908823; // 指定纬度
const longitude = 116.39747; // 指定经度
const radiusInKm = 10; // 指定圆的半径(单位:千米)
const randomCoordinate = getRandomCoordinateWithinRadius(latitude, longitude, radiusInKm);
console.log(randomCoordinate);
*/
function getRandomCoordinateWithinRadius(longitude, latitude, radiusInKm) {
// 地球半径(单位:千米)
const earthRadius = 6371;
// 将圆的半径转换为弧度
const radiusInRad = radiusInKm / earthRadius;
// 生成随机的方位角弧度0到2π
const randomAngleRad = Math.random() * 2 * Math.PI;
// 生成随机的距离弧度0到圆的半径
const randomDistanceRad = Math.acos(Math.random() * (Math.cos(radiusInRad) - 1) + 1);
// 使用球面三角学计算随机点的纬度和经度
const randomLatitudeRad = latitude * (Math.PI / 180) + randomDistanceRad * Math.cos(randomAngleRad);
const randomLongitudeRad = longitude * (Math.PI / 180) + randomDistanceRad * Math.sin(randomAngleRad) / Math.cos(latitude * (Math.PI / 180));
// 转换为度并保留6位小数
const randomLatitude = parseFloat((randomLatitudeRad * (180 / Math.PI)).toFixed(6));
const randomLongitude = parseFloat((randomLongitudeRad * (180 / Math.PI)).toFixed(6));
return { latitude: randomLatitude, longitude: randomLongitude };
}
/**
* 计算坐标B在坐标A的方向0代表正西方 90 代表正北方
const latitude = 39.908823; // 指定纬度
const longitude = 116.39747; // 指定经度
const radiusInKm = 10; // 指定圆的半径(单位:千米)
const randomCoordinate = getRandomCoordinateWithinRadius(latitude, longitude, radiusInKm);
console.log(randomCoordinate);
*/
function calculateDirectionAngle(coordA, coordB) {
const toRadians = (angle) => angle * (Math.PI / 180);
const toDegrees = (angle) => angle * (180 / Math.PI);
const lat1 = toRadians(coordA.latitude);
const lon1 = toRadians(coordA.longitude);
const lat2 = toRadians(coordB.latitude);
const lon2 = toRadians(coordB.longitude);
const dLon = lon2 - lon1;
const y = Math.sin(dLon) * Math.cos(lat2);
const x =
Math.cos(lat1) * Math.sin(lat2) -
Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon);
const angleRadians = Math.atan2(y, x);
let angleDegrees = toDegrees(angleRadians);
angleDegrees = (angleDegrees + 360) % 360;
angleDegrees = (angleDegrees > 180) ? angleDegrees - 180 : angleDegrees + 180;
angleDegrees -= 90; // 以正西方为0°表示因此需要-90
return angleDegrees;
}

View File

@@ -0,0 +1,9 @@
{
"name": "uni-map-co",
"dependencies": {
"uni-config-center": "file:../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center",
"uni-map-common": "file:../common/uni-map-common",
"uni-id-common": "file:../../../../uni-id-common/uniCloud/cloudfunctions/common/uni-id-common"
},
"extensions": {}
}

View File

@@ -0,0 +1,104 @@
location2address({
location: "39.908815,116.397507",
get_poi: 1,
poi_options: {
address_format: "short",
radius: 5000,
policy: 4,
//poitype: "010101",
roadlevel: 1,
homeorcorp: 1
}
});
// address2location({
// address: "北京市海淀区彩和坊路海淀西大街74号",
// city: "北京"
// });
// translate({
// locations: [
// { lat: 39.908815, lng: 116.397507 },
// { lat: 39.908815, lng: 116.397107 }
// ],
// type: 3
// });
// ip定位
// ip2location({
// ip: "111.206.145.41"
// });
// 输入提示
// inputtips({
// keyword: "人民医院",
// city: "北京市",
// datatype: "all",
// get_subpois: 1
// });
// 周边搜索
// search({
// keyword: "酒店",
// location: {
// lat: 39.908815,
// lng: 116.397507
// },
// radius: 1000,
// auto_extend: 1,
// get_subpois: 1,
// orderby: "weight",
// page_index: 1,
// page_size: 20,
// city: "北京市"
// });
// 行政区划
// districtSearch({
// adcode: "110000",
// get_polygon: 2,
// max_offset: 500,
// subdistrict: 2
// });
// 导航 - 驾车
// route({
// mode: "driving",
// from: "39.808815,116.387507",
// to: "39.908815,116.397507",
// get_mp: 1,
// });
// 导航 - 步行
// route({
// mode: "walking",
// from: "40.034852,116.319820",
// to: "39.771075,116.351395",
// alternative_route: 3
// });
// 导航 - 骑行
// route({
// mode: "bicycling",
// from: "40.034852,116.319820",
// to: "39.771075,116.351395",
// alternative_route: 3
// });
// 导航 - 电动车
// route({
// mode: "ebicycling",
// from: "40.034852,116.319820",
// to: "39.771075,116.351395",
// alternative_route: 3
// });
// 导航 - 公交
// route({
// mode: "transit",
// from: "40.034852,116.319820",
// to: "29.771075,116.351395",
// //alternative_route: 3,
// city1: "010",
// city2: "0792",
// });

View File

@@ -0,0 +1,8 @@
## 1.0.32022-01-21
- 优化 组件示例
## 1.0.22021-11-22
- 修复 / 符号在 vue 不同版本兼容问题引起的报错问题
## 1.0.12021-11-22
- 修复 vue3中scss语法兼容问题
## 1.0.02021-11-18
- init

View File

@@ -0,0 +1 @@
@import './styles/index.scss';

View File

@@ -0,0 +1,82 @@
{
"id": "uni-scss",
"displayName": "uni-scss 辅助样式",
"version": "1.0.3",
"description": "uni-sass是uni-ui提供的一套全局样式 通过一些简单的类名和sass变量实现简单的页面布局操作比如颜色、边距、圆角等。",
"keywords": [
"uni-scss",
"uni-ui",
"辅助样式"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"category": [
"JS SDK",
"通用 SDK"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "n",
"联盟": "n"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}

View File

@@ -0,0 +1,4 @@
`uni-sass``uni-ui`提供的一套全局样式 ,通过一些简单的类名和`sass`变量,实现简单的页面布局操作,比如颜色、边距、圆角等。
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-sass)
#### 如使用过程中有任何问题或者您对uni-ui有一些好的建议欢迎加入 uni-ui 交流群871950839

View File

@@ -0,0 +1,7 @@
@import './setting/_variables.scss';
@import './setting/_border.scss';
@import './setting/_color.scss';
@import './setting/_space.scss';
@import './setting/_radius.scss';
@import './setting/_text.scss';
@import './setting/_styles.scss';

View File

@@ -0,0 +1,3 @@
.uni-border {
border: 1px $uni-border-1 solid;
}

View File

@@ -0,0 +1,66 @@
// TODO 暂时不需要 class ,需要用户使用变量实现 ,如果使用类名其实并不推荐
// @mixin get-styles($k,$c) {
// @if $k == size or $k == weight{
// font-#{$k}:#{$c}
// }@else{
// #{$k}:#{$c}
// }
// }
$uni-ui-color:(
// 主色
primary: $uni-primary,
primary-disable: $uni-primary-disable,
primary-light: $uni-primary-light,
// 辅助色
success: $uni-success,
success-disable: $uni-success-disable,
success-light: $uni-success-light,
warning: $uni-warning,
warning-disable: $uni-warning-disable,
warning-light: $uni-warning-light,
error: $uni-error,
error-disable: $uni-error-disable,
error-light: $uni-error-light,
info: $uni-info,
info-disable: $uni-info-disable,
info-light: $uni-info-light,
// 中性色
main-color: $uni-main-color,
base-color: $uni-base-color,
secondary-color: $uni-secondary-color,
extra-color: $uni-extra-color,
// 背景色
bg-color: $uni-bg-color,
// 边框颜色
border-1: $uni-border-1,
border-2: $uni-border-2,
border-3: $uni-border-3,
border-4: $uni-border-4,
// 黑色
black:$uni-black,
// 白色
white:$uni-white,
// 透明
transparent:$uni-transparent
) !default;
@each $key, $child in $uni-ui-color {
.uni-#{"" + $key} {
color: $child;
}
.uni-#{"" + $key}-bg {
background-color: $child;
}
}
.uni-shadow-sm {
box-shadow: $uni-shadow-sm;
}
.uni-shadow-base {
box-shadow: $uni-shadow-base;
}
.uni-shadow-lg {
box-shadow: $uni-shadow-lg;
}
.uni-mask {
background-color:$uni-mask;
}

View File

@@ -0,0 +1,55 @@
@mixin radius($r,$d:null ,$important: false){
$radius-value:map-get($uni-radius, $r) if($important, !important, null);
// Key exists within the $uni-radius variable
@if (map-has-key($uni-radius, $r) and $d){
@if $d == t {
border-top-left-radius:$radius-value;
border-top-right-radius:$radius-value;
}@else if $d == r {
border-top-right-radius:$radius-value;
border-bottom-right-radius:$radius-value;
}@else if $d == b {
border-bottom-left-radius:$radius-value;
border-bottom-right-radius:$radius-value;
}@else if $d == l {
border-top-left-radius:$radius-value;
border-bottom-left-radius:$radius-value;
}@else if $d == tl {
border-top-left-radius:$radius-value;
}@else if $d == tr {
border-top-right-radius:$radius-value;
}@else if $d == br {
border-bottom-right-radius:$radius-value;
}@else if $d == bl {
border-bottom-left-radius:$radius-value;
}
}@else{
border-radius:$radius-value;
}
}
@each $key, $child in $uni-radius {
@if($key){
.uni-radius-#{"" + $key} {
@include radius($key)
}
}@else{
.uni-radius {
@include radius($key)
}
}
}
@each $direction in t, r, b, l,tl, tr, br, bl {
@each $key, $child in $uni-radius {
@if($key){
.uni-radius-#{"" + $direction}-#{"" + $key} {
@include radius($key,$direction,false)
}
}@else{
.uni-radius-#{$direction} {
@include radius($key,$direction,false)
}
}
}
}

View File

@@ -0,0 +1,56 @@
@mixin fn($space,$direction,$size,$n) {
@if $n {
#{$space}-#{$direction}: #{$size*$uni-space-root}px
} @else {
#{$space}-#{$direction}: #{-$size*$uni-space-root}px
}
}
@mixin get-styles($direction,$i,$space,$n){
@if $direction == t {
@include fn($space, top,$i,$n);
}
@if $direction == r {
@include fn($space, right,$i,$n);
}
@if $direction == b {
@include fn($space, bottom,$i,$n);
}
@if $direction == l {
@include fn($space, left,$i,$n);
}
@if $direction == x {
@include fn($space, left,$i,$n);
@include fn($space, right,$i,$n);
}
@if $direction == y {
@include fn($space, top,$i,$n);
@include fn($space, bottom,$i,$n);
}
@if $direction == a {
@if $n {
#{$space}:#{$i*$uni-space-root}px;
} @else {
#{$space}:#{-$i*$uni-space-root}px;
}
}
}
@each $orientation in m,p {
$space: margin;
@if $orientation == m {
$space: margin;
} @else {
$space: padding;
}
@for $i from 0 through 16 {
@each $direction in t, r, b, l, x, y, a {
.uni-#{$orientation}#{$direction}-#{$i} {
@include get-styles($direction,$i,$space,true);
}
.uni-#{$orientation}#{$direction}-n#{$i} {
@include get-styles($direction,$i,$space,false);
}
}
}
}

View File

@@ -0,0 +1,167 @@
/* #ifndef APP-NVUE */
$-color-white:#fff;
$-color-black:#000;
@mixin base-style($color) {
color: #fff;
background-color: $color;
border-color: mix($-color-black, $color, 8%);
&:not([hover-class]):active {
background: mix($-color-black, $color, 10%);
border-color: mix($-color-black, $color, 20%);
color: $-color-white;
outline: none;
}
}
@mixin is-color($color) {
@include base-style($color);
&[loading] {
@include base-style($color);
&::before {
margin-right:5px;
}
}
&[disabled] {
&,
&[loading],
&:not([hover-class]):active {
color: $-color-white;
border-color: mix(darken($color,10%), $-color-white);
background-color: mix($color, $-color-white);
}
}
}
@mixin base-plain-style($color) {
color:$color;
background-color: mix($-color-white, $color, 90%);
border-color: mix($-color-white, $color, 70%);
&:not([hover-class]):active {
background: mix($-color-white, $color, 80%);
color: $color;
outline: none;
border-color: mix($-color-white, $color, 50%);
}
}
@mixin is-plain($color){
&[plain] {
@include base-plain-style($color);
&[loading] {
@include base-plain-style($color);
&::before {
margin-right:5px;
}
}
&[disabled] {
&,
&:active {
color: mix($-color-white, $color, 40%);
background-color: mix($-color-white, $color, 90%);
border-color: mix($-color-white, $color, 80%);
}
}
}
}
.uni-btn {
margin: 5px;
color: #393939;
border:1px solid #ccc;
font-size: 16px;
font-weight: 200;
background-color: #F9F9F9;
// TODO 暂时处理边框隐藏一边的问题
overflow: visible;
&::after{
border: none;
}
&:not([type]),&[type=default] {
color: #999;
&[loading] {
background: none;
&::before {
margin-right:5px;
}
}
&[disabled]{
color: mix($-color-white, #999, 60%);
&,
&[loading],
&:active {
color: mix($-color-white, #999, 60%);
background-color: mix($-color-white,$-color-black , 98%);
border-color: mix($-color-white, #999, 85%);
}
}
&[plain] {
color: #999;
background: none;
border-color: $uni-border-1;
&:not([hover-class]):active {
background: none;
color: mix($-color-white, $-color-black, 80%);
border-color: mix($-color-white, $-color-black, 90%);
outline: none;
}
&[disabled]{
&,
&[loading],
&:active {
background: none;
color: mix($-color-white, #999, 60%);
border-color: mix($-color-white, #999, 85%);
}
}
}
}
&:not([hover-class]):active {
color: mix($-color-white, $-color-black, 50%);
}
&[size=mini] {
font-size: 16px;
font-weight: 200;
border-radius: 8px;
}
&.uni-btn-small {
font-size: 14px;
}
&.uni-btn-mini {
font-size: 12px;
}
&.uni-btn-radius {
border-radius: 999px;
}
&[type=primary] {
@include is-color($uni-primary);
@include is-plain($uni-primary)
}
&[type=success] {
@include is-color($uni-success);
@include is-plain($uni-success)
}
&[type=error] {
@include is-color($uni-error);
@include is-plain($uni-error)
}
&[type=warning] {
@include is-color($uni-warning);
@include is-plain($uni-warning)
}
&[type=info] {
@include is-color($uni-info);
@include is-plain($uni-info)
}
}
/* #endif */

View File

@@ -0,0 +1,24 @@
@mixin get-styles($k,$c) {
@if $k == size or $k == weight{
font-#{$k}:#{$c}
}@else{
#{$k}:#{$c}
}
}
@each $key, $child in $uni-headings {
/* #ifndef APP-NVUE */
.uni-#{$key} {
@each $k, $c in $child {
@include get-styles($k,$c)
}
}
/* #endif */
/* #ifdef APP-NVUE */
.container .uni-#{$key} {
@each $k, $c in $child {
@include get-styles($k,$c)
}
}
/* #endif */
}

View File

@@ -0,0 +1,146 @@
// @use "sass:math";
@import '../tools/functions.scss';
// 间距基础倍数
$uni-space-root: 2 !default;
// 边框半径默认值
$uni-radius-root:5px !default;
$uni-radius: () !default;
// 边框半径断点
$uni-radius: map-deep-merge(
(
0: 0,
// TODO 当前版本暂时不支持 sm 属性
// 'sm': math.div($uni-radius-root, 2),
null: $uni-radius-root,
'lg': $uni-radius-root * 2,
'xl': $uni-radius-root * 6,
'pill': 9999px,
'circle': 50%
),
$uni-radius
);
// 字体家族
$body-font-family: 'Roboto', sans-serif !default;
// 文本
$heading-font-family: $body-font-family !default;
$uni-headings: () !default;
$letterSpacing: -0.01562em;
$uni-headings: map-deep-merge(
(
'h1': (
size: 32px,
weight: 300,
line-height: 50px,
// letter-spacing:-0.01562em
),
'h2': (
size: 28px,
weight: 300,
line-height: 40px,
// letter-spacing: -0.00833em
),
'h3': (
size: 24px,
weight: 400,
line-height: 32px,
// letter-spacing: normal
),
'h4': (
size: 20px,
weight: 400,
line-height: 30px,
// letter-spacing: 0.00735em
),
'h5': (
size: 16px,
weight: 400,
line-height: 24px,
// letter-spacing: normal
),
'h6': (
size: 14px,
weight: 500,
line-height: 18px,
// letter-spacing: 0.0125em
),
'subtitle': (
size: 12px,
weight: 400,
line-height: 20px,
// letter-spacing: 0.00937em
),
'body': (
font-size: 14px,
font-weight: 400,
line-height: 22px,
// letter-spacing: 0.03125em
),
'caption': (
'size': 12px,
'weight': 400,
'line-height': 20px,
// 'letter-spacing': 0.03333em,
// 'text-transform': false
)
),
$uni-headings
);
// 主色
$uni-primary: #2979ff !default;
$uni-primary-disable:lighten($uni-primary,20%) !default;
$uni-primary-light: lighten($uni-primary,25%) !default;
// 辅助色
// 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。
$uni-success: #18bc37 !default;
$uni-success-disable:lighten($uni-success,20%) !default;
$uni-success-light: lighten($uni-success,25%) !default;
$uni-warning: #f3a73f !default;
$uni-warning-disable:lighten($uni-warning,20%) !default;
$uni-warning-light: lighten($uni-warning,25%) !default;
$uni-error: #e43d33 !default;
$uni-error-disable:lighten($uni-error,20%) !default;
$uni-error-light: lighten($uni-error,25%) !default;
$uni-info: #8f939c !default;
$uni-info-disable:lighten($uni-info,20%) !default;
$uni-info-light: lighten($uni-info,25%) !default;
// 中性色
// 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。
$uni-main-color: #3a3a3a !default; // 主要文字
$uni-base-color: #6a6a6a !default; // 常规文字
$uni-secondary-color: #909399 !default; // 次要文字
$uni-extra-color: #c7c7c7 !default; // 辅助说明
// 边框颜色
$uni-border-1: #F0F0F0 !default;
$uni-border-2: #EDEDED !default;
$uni-border-3: #DCDCDC !default;
$uni-border-4: #B9B9B9 !default;
// 常规色
$uni-black: #000000 !default;
$uni-white: #ffffff !default;
$uni-transparent: rgba($color: #000000, $alpha: 0) !default;
// 背景色
$uni-bg-color: #f7f7f7 !default;
/* 水平间距 */
$uni-spacing-sm: 8px !default;
$uni-spacing-base: 15px !default;
$uni-spacing-lg: 30px !default;
// 阴影
$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5) !default;
$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2) !default;
$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5) !default;
// 蒙版
$uni-mask: rgba($color: #000000, $alpha: 0.4) !default;

View File

@@ -0,0 +1,19 @@
// 合并 map
@function map-deep-merge($parent-map, $child-map){
$result: $parent-map;
@each $key, $child in $child-map {
$parent-has-key: map-has-key($result, $key);
$parent-value: map-get($result, $key);
$parent-type: type-of($parent-value);
$child-type: type-of($child);
$parent-is-map: $parent-type == map;
$child-is-map: $child-type == map;
@if (not $parent-has-key) or ($parent-type != $child-type) or (not ($parent-is-map and $child-is-map)){
$result: map-merge($result, ( $key: $child ));
}@else {
$result: map-merge($result, ( $key: map-deep-merge($parent-value, $child) ));
}
}
@return $result;
};

View File

@@ -0,0 +1,31 @@
// 间距基础倍数
$uni-space-root: 2;
// 边框半径默认值
$uni-radius-root:5px;
// 主色
$uni-primary: #2979ff;
// 辅助色
$uni-success: #4cd964;
// 警告色
$uni-warning: #f0ad4e;
// 错误色
$uni-error: #dd524d;
// 描述色
$uni-info: #909399;
// 中性色
$uni-main-color: #303133;
$uni-base-color: #606266;
$uni-secondary-color: #909399;
$uni-extra-color: #C0C4CC;
// 背景色
$uni-bg-color: #f5f5f5;
// 边框颜色
$uni-border-1: #DCDFE6;
$uni-border-2: #E4E7ED;
$uni-border-3: #EBEEF5;
$uni-border-4: #F2F6FC;
// 常规色
$uni-black: #000000;
$uni-white: #ffffff;
$uni-transparent: rgba($color: #000000, $alpha: 0);

View File

@@ -0,0 +1,62 @@
@import './styles/setting/_variables.scss';
// 间距基础倍数
$uni-space-root: 2;
// 边框半径默认值
$uni-radius-root:5px;
// 主色
$uni-primary: #2979ff;
$uni-primary-disable:mix(#fff,$uni-primary,50%);
$uni-primary-light: mix(#fff,$uni-primary,80%);
// 辅助色
// 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。
$uni-success: #18bc37;
$uni-success-disable:mix(#fff,$uni-success,50%);
$uni-success-light: mix(#fff,$uni-success,80%);
$uni-warning: #f3a73f;
$uni-warning-disable:mix(#fff,$uni-warning,50%);
$uni-warning-light: mix(#fff,$uni-warning,80%);
$uni-error: #e43d33;
$uni-error-disable:mix(#fff,$uni-error,50%);
$uni-error-light: mix(#fff,$uni-error,80%);
$uni-info: #8f939c;
$uni-info-disable:mix(#fff,$uni-info,50%);
$uni-info-light: mix(#fff,$uni-info,80%);
// 中性色
// 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。
$uni-main-color: #3a3a3a; // 主要文字
$uni-base-color: #6a6a6a; // 常规文字
$uni-secondary-color: #909399; // 次要文字
$uni-extra-color: #c7c7c7; // 辅助说明
// 边框颜色
$uni-border-1: #F0F0F0;
$uni-border-2: #EDEDED;
$uni-border-3: #DCDCDC;
$uni-border-4: #B9B9B9;
// 常规色
$uni-black: #000000;
$uni-white: #ffffff;
$uni-transparent: rgba($color: #000000, $alpha: 0);
// 背景色
$uni-bg-color: #f7f7f7;
/* 水平间距 */
$uni-spacing-sm: 8px;
$uni-spacing-base: 15px;
$uni-spacing-lg: 30px;
// 阴影
$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5);
$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2);
$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5);
// 蒙版
$uni-mask: rgba($color: #000000, $alpha: 0.4);