一键登录
App 微信的登录
小程序地图问题
WXML
<view class="aa" hover-class="none" hover-stop-propagation="false">
<map id="map" longitude="{{longitude}}" latitude=" {{latitude}}" markers="{{markers}}" scale="14" show-location
style="width: 100%; height: 100%;" bindregionchange="bindregionchange" bindtap="bindtapMap"></map>
</view>
js
Page({
data: {
longitude: 113.14278, //地图界面中心的经度
latitude: 23.02882, //地图界面中心的纬度
markers: [ //标志点的位置
//位置0
{
id: 0,
iconPath: "../../images/tabs/contact-active.png",
latitude: 23.04308268848755,
longitude: 113.13562655285273,
width: 28,
height: 32
},
//位置1
{
id: 1,
iconPath: "../../images/tabs/contact-active.png",
latitude: 23.03814334110172,
longitude: 113.15378758608608,
width: 28,
height: 32
},
//位置2
{
id: 2,
iconPath: "../../images/tabs/contact-active.png",
latitude: 23.03377135768493,
longitude: 113.17075479351229,
width: 28,
height: 32
},
//位置3
{
id: 3,
iconPath: "../../images/tabs/contact-active.png",
latitude: 23.02542516569787,
longitude: 113.1417505798413,
width: 28,
height: 32
},
//位置4
{
id: 4,
iconPath: "../../images/tabs/contact-active.png",
latitude: 23.022740816325694,
longitude: 113.14681189547798,
width: 28,
height: 32
},
]
},
onLoad: function () {
var that = this;
wx.getLocation({
type: "wgs84",
success: function (res) {
var latitude = res.latitude;
var longitude = res.longitude;
console.log("当前位置的经纬度为:", res.latitude, res.longitude);
that.setData({
latitude: res.latitude,
longitude: res.longitude,
})
}
})
},
onReady: function () {
},
/**
* 地图放大缩小事件触发
* @param {*} e
*/
bindregionchange(e) {
console.log('=bindregiοnchange=', e)
},
/**
* 点击地图事件,有经纬度信息返回
* @param {*} e
*/
bindtapMap(e) {
console.log('=bindtapMap=', e)
}
})
JSON
{
"plugins": {
"chooseLocation": {
"version": "1.0.9",
"provider": "wx76a9a06e5b4e693e"
}
},
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置接口的效果展示"
}
},
}
地图导航开始
<view bindtap="nav">
<view>
<text>导航</text>
</view>
</view>
// js 事件
nav(){
wx.openLocation({
latitude:36.0812917700, //维度
longitude: 114.4562530500, //经度
name: "目的地", //目的地定位名称
scale: 15, //缩放比例
address: "目的地" //导航详细地址
})
}
仿抖音功能
// wxss
/**index.wxss**/
page{
width: 100%;
height: 100%;
}
.q_swiper{
width: 100%;
height: 100%;
background-color: #000;
}
.q_videoView{
width: 100%;
height: 100%;
position: relative;
}
.q_videoView video{
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
// wxml
<!--index.wxml-->
<swiper class="q_swiper" circular="{{true}}" vertical="{{true}}" bindchange="q_swiperBindchange">
<block wx:for="{{q_videos}}" wx:key="q_videos">
<swiper-item>
<view class="q_videoView">
<!-- wx:if="{{index==q_videoIndex}}" 用于控制只播放当前视频,否则多个视频会同时播放没刷到的也会播放 -->
<video wx:if="{{index==q_videoIndex}}" src="{{item.url}}" autoplay="{{true}}" loop="{{true}}" show-fullscreen-btn="{{false}}" play-btn-position="center" enable-play-gesture="{{true}}"></video>
</view>
</swiper-item>
</block>
</swiper>
// js
//index.js
Page({
/**
* 页面的初始数据
*/
data: {
q_videos: [], //视频
q_videoIndex: 0, //视频index
q_yjz: false, //是否允许预加载
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
// videoList内的视频地址为临时地址,届时视频链接可能失效,如果视频链接失效,您只需自己随意找几个视频替换掉地址即可
var videoList = [{
id: '1',
url: "http://sns-1255549670.cos.ap-guangzhou.myqcloud.com/tmp_29f5566f128e9a4ee470f30c310b63678b7e786e2ab03ac2.mp4?0.42363964325301695",
}, {
id: '2',
url: "http://sns-1255549670.cos.ap-guangzhou.myqcloud.com/tmp_4eeae5bfcad7f75ec481b5ad87f4a9102ea7c735df672d18.mp4?0.9295834871549054",
}, {
id: '3',
url: "http://sns-1255549670.cos.ap-guangzhou.myqcloud.com/tmp_7a9caafe0a37a460686fcf2a4a6dc492e0e44119c10cc47b.mp4?0.401603295588834",
}]
this.setData({
q_videos: videoList, //视频
// 每次加载3个视频,当获取的视频数量小于3时,证明没有后续视频了,也就不需要在进行预加载了
q_yjz: videoList.length < 3 ? false : true, //是否允许预加载
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
},
//动态更新当前视频下标
q_swiperBindchange: function (e) {
console.log('当前视频下标:', e.detail.current)
this.setData({
q_videoIndex: e.detail.current
})
// 当加载的视频还剩1个未被滑到时加载下一页
if (this.data.q_videos.length - (e.detail.current + 1) == 1 && this.data.q_yjz) {
this.q_yjzVideos() //预加载视频
}
},
//预加载视频
q_yjzVideos: function () {
console.log('预加载视频')
var videoList = [{
id: '4',
url: "http://sns-1255549670.cos.ap-guangzhou.myqcloud.com/tmp_b0855d9c92f6ce4cd91796e8b1ca39a78bca4d48f524bb06.mp4?0.27723747875520743",
}, {
id: '5',
url: "http://sns-1255549670.cos.ap-guangzhou.myqcloud.com/wx982ed8d3473ced2c.o6zAJs8Oghy9CSGBPJEdSoJABPEU.SZVa80OoOknW8750107432d93943f9ce930651ad5ffa.mp4?0.27723747875520743",
}]
var array = this.data.q_videos.concat(videoList) //concat() 方法:用于连接两个或多个数组,并返回一个新数组
this.setData({
q_videos: array, //视频
q_yjz: videoList.length < 3 ? false : true, //是否允许预加载
})
},
})
// json
{
"usingComponents": {},
"navigationStyle":"custom",
"navigationBarTextStyle":"white"
}
图片上传
<template>
<view class="da">
<!-- 输入框开始 -->
<view class="shuru" style="height: 165px;">
<text>问题和意见</text>
<textarea v-model="form.text" class="wenzitijiao" placeholder="简要描述你要反馈的问题和意见" />
</view>
<view class="shuru">
<text>上传图片(最多3张)</text>
<view class="shangchaun">
<uni-file-picker ref="unifile"
@mydelete="mydelete"
v-model="imageValue" limit="3" fileMediatype="image" mode="grid"
@select="select" @progress="progress" @success="success" @fail="fail" />
</view>
</view>
<view class="shuru" style="height: 114px;">
<text>联系方式</text>
<textarea v-model="form.mobile" class="wenzitijiao" placeholder="请填写您的手机号码" />
</view>
<!-- 输入框结束 -->
<!-- 底部按钮开始 -->
<view class="tijiao">
<view @click="tijaio" class="tijiaowen">
立即提交
</view>
</view>
<!-- 底部按钮结束 -->
</view>
</template>
<script>
import { mapState } from 'vuex'
import { add } from '@/api/jiemi.js'
export default {
data() {
return {
imageValue: [],
imageValuesss: [],
form: {
mobile: '',
text: ''
}
}
},
computed: {
...mapState('m_user', ['address'])
},
methods: {
async tijaio() {
const reg = /^(?:(?:\+|00)86)?1\d{10}$/
if (this.form.text === '') {
uni.$showMsg("请填写意见")
return
}
if (this.form.mobile === '' || !reg.test(this.form.mobile)) {
uni.$showMsg("请填写正确手机号")
return
}
let img = '';
if(this.imageValuesss.length > 0){
img = this.imageValuesss.join(',')
}
const res = await add({
user_id: this.address.id,
image: img,
...this.form
})
this.form = {}
this.imageValuesss = []
this.imageValue = []
this.$refs.unifile.files = []
uni.$showMsg("提交成功")
},
// 删除图拍你
mydelete(index){
console.log(index);
this.imageValuesss.splice(index, 1)
},
// 删除图图片
// 获取上传状态
select(e) {
console.log('ok', e.tempFilePaths[0]);
let that = this
//选取图片
that.uploadfilepath(e.tempFilePaths[0])
},
uploadfilepath(tempFilePaths) {
//上传图片
let that= this
wx.uploadFile({
//请求后台的网址
url:'http://ss.iifaka.com/index.php/api/Opinion/upload',
//小程序本地的路径
filePath: tempFilePaths,
//后台获取我们图片的key
name: 'file',
// //额外的参数formData
// formData: {
// user_id: '5',
// mobile: '13075300312',
// 'from': 'xcx'
// },
// header: {
// token: gb.token
// },
success: function(res) {
const res2 = JSON.parse(res.data)
that.imageValuesss.push(res2.data)
},
fail: function(res) {
},
})
},
progress(e) {
console.log('上传进度:', e)
},
success(e) {
console.log('上传成功')
},
fail(e) {
console.log('上传失败:', e)
}
}
}
</script>
分享
<template>
<view>
<!-- #ifdef APP-PLUS -->
<view class="goodsMenu" @click="appShare">
<view class="menuIcon">
<image src="/package/static/mall/goodsShare.png" mode=""></image>
</view>
<view class="menuName">分享</view>
</view>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<button open-type="share" hover-class="none" class="goodsMenu">
<view class="menuIcon">
<image src="/package/static/mall/goodsShare.png" mode=""></image>
</view>
<view class="menuName">分享</view>
</button>
<!-- #endif -->
</view>
</template>
<script>
export default {
data() {
return {
text: '兼容'
}
},
components: {},
onShareAppMessage(res) {
let _this = this;
return {
title: _this.goodsTit,
// imageUrl: '',
path: '/package/pages/mall/goodsDetail/goodsDetail?goods_id=' + _this.goods_id,
}
},
methods: {
appShare() {
var _this=this;
// App分享为微信小程序(App中分享一个内容到微信好友,对方微信中呈现的是一个小程序卡片)
uni.share({
provider: 'weixin',
scene: "WXSceneSession",
type: 5,
imageUrl: '',
title: _this.goodsDetail.goods_name,
miniProgram: {
id: getApp().globalData.originalId,
path: 'pages/index/index',
type: 0,
webUrl: 'http://uniapp.dcloud.io'
},
success: res => {
console.log(JSON.stringify(res));
}
});
}
}
}
</script>
</style>
配置axios
npm install axios
// 在 main.js 中
// 引入封装后的axios
import axios from './utils/http.js'
/**
* 给Vue函数添加一个原型属性$axios 指向Axios
* 这样做的好处是在vue实例或组件中不用再去重复引用Axios 直接用this.$axios就能执行axios 方法了
* 在.vue中使用,this.$axios.get
* @param {Object} config
*/
Vue.prototype.$axios = axios
axios.defaults.adapter = function(config) {
return new Promise((resolve, reject) => {
console.log(config)
var settle = require('axios/lib/core/settle');
var buildURL = require('axios/lib/helpers/buildURL');
uni.request({
method: config.method.toUpperCase(),
url: config.baseURL + buildURL(config.url, config.params, config.paramsSerializer),
header: config.headers,
data: config.data,
dataType: config.dataType,
responseType: config.responseType,
sslVerify: config.sslVerify,
complete: function complete(response) {
response = {
data: response.data,
status: response.statusCode,
errMsg: response.errMsg,
header: response.header,
config: config
};
settle(resolve, reject, response);
}
})
})
}
// 在utils 中配置一下请求头
import Vue from 'vue'
import axios from 'axios'
// create an axios instance
const service = axios.create({
baseURL: 'http://ss.iifaka.com/index.php', // url = base url + request url
//withCredentials: true, // send cookies when cross-domain requests 注意:withCredentials和后端配置的cross跨域不可同时使用
timeout: 6000, // request timeout
crossDomain: true
})
// request拦截器,在请求之前做一些处理
service.interceptors.request.use(
// config => {
// // if (store.state.token) {
// // // 给请求头添加user-token
// // config.headers["user-token"] = store.state.token;
// // }
// console.log('请求拦截成功')
// return config;
// },
// error => {
// console.log(error); // for debug
// return Promise.reject(error);
// }
);
//配置成功后的拦截器
service.interceptors.response.use(res => {
// console.log(res);
const { code, data, msg } = res.data
if (code > 0) {
return data
} else {
uni.showToast({
title: msg,
duration: 1500,
icon: 'none',
})
return Promise.reject(new Error(res.data.msg));
}
}, error => {
console.log(error);
uni.showToast({
title: res.data.msg,
duration: 1500,
icon: 'none',
})
return Promise.reject(new Error(res.data.msg));
// if (error.response.status) {
// switch (error.response.status) {
// case 401:
// break;
// default:
// break;
// }
// }
// return Promise.reject(error)
})
export default service
// 配置api
import service from '@/utils/http.js'
export const toLogin = (data) => {
return service({
url: '/login',
method: 'post',
params : data
})
}
拍摄加入水印
<template>
<view><!-- 拍照上传图片带水印 -->
<!-- <camera device-position="back" flash="off" @error="error" style="width: 100%; height: 300px;"></camera>
<button type="primary" @tap="takePhoto">拍照</button>
<view>预览</view>
<image mode="widthFix" :src="src"></image>
<canvas class='canvas' :style="canvasStyle" canvas-id="firstCanvas"></canvas> -->
<view>
<camera device-position="back" flash="off" @error="error" style="width: 100%; height: 70vh;"></camera>
<button type="primary" class="pai" @click="takePhoto">拍照</button>
<view>预览</view>
<image mode="widthFix" :src="src"></image>
<canvas class='canvas' :style="canvasStyle" canvas-id="firstCanvas"></canvas>
<view class="">
sdasdadsadasd
sdasdadsadasd
sdasdadsadasd
sdasdadsadasd
sdasdadsadasd
sdasdadsadasd
sdasdadsadasd
sdasdadsadasd
sdasdadsadasd
sdasdadsadasd
sdasdadsadasd
sdasdadsadasd
sdasdadsadasd
sdasdadsadasd
sdasdadsadasd
</view>
</view>
</view>
</template>
<script>
export default{
data() {
return {
socketOpen: false,
src:'',
canvasStyle:{}
}
},
methods:{
takePhoto() {
const ctx = uni.createCameraContext()
ctx.takePhoto({
quality: 'high',
success: res => {
this.src=res.tempImagePath
let that = this
uni.getImageInfo({
src: res.tempImagePath,
success: ress => {
console.log(ress)
let date = 'sadd'+'\n'+'dasdas' /** 作为水印 */
let ctx = uni.createCanvasContext('firstCanvas') /** 创建画布 */
let textToWidth = ress.width / 5 * 0.5 /**这里设置的是水印位置*/
let textToHeight = ress.height / 3 * 0.9
that.canvasStyle=`{width:${ress}.width/3px;height:${ress}.height/3px}`
//将图片src放到cancas内,宽高为图片大小
ctx.drawImage(res.tempImagePath, 0, 0, ress.width , ress.height)
//将声明的时间放入canvas
ctx.setFontSize(14) //注意:设置文字大小必须放在填充文字之前,否则不生效
ctx.setFillStyle('white')
ctx.fillText(date, textToWidth, textToHeight) //水印内容,位置
// ctx.strokeText(date, ress.width, ress.height)
uni.showLoading({ title: '制作水印中...', })
ctx.draw(false, () => {//开始制作
setTimeout(() => {//使用定时是因为制作水印需要时间,设置定时才不会出bug
uni.canvasToTempFilePath({ //将画布中内容转成图片,即水印与图片合成
canvasId: 'firstCanvas',
success: res => {
uni.hideLoading()
uni.saveImageToPhotosAlbum({ //保存到手机
filePath: res.tempFilePath,
success(res) {
console.log('1')
}
})
}
})
}, 500)
})
}
})
}
})
}
}
}
</script>
<style>
.pai{
position: absolute;
top: 0;
}
.canvas{
width: 100vh;
height: 100vh;
margin-bottom: 20px;
background-color: saddlebrown;
}
</style>
聊天模块
<template>
<view class="da">
<!-- 聊天区域开始 -->
<view class="sssssss">
<scroll-view class="top" scroll-y="true">
<view id="dissan" v-for="(item, index) in chatList" :key="index" class="">
<!-- 之心姐姐 -->
<view class="" v-if="item.isMe === false" >
<view class="shijian">
2000-30-366
</view>
<view class="wo">
<view class="xinxi">
<text v-if="item.type === 'txt'">{{item.content}}</text>
<image v-if="item.type === 'img'" :src="item.content" mode=""></image>
</view>
<image src="../../static/Frame.png" mode=""></image>
</view>
</view>
<!-- 之心姐姐 -->
<!-- 我 -->
<view class="" v-else>
<view class="shijian">
2000-30-366
</view>
<view class="dui">
<image src="../../static/Frame.png" mode=""></image>
<view class="dui_xinxi">
<text v-if="item.type === 'txt'">{{item.content}}</text>
<image v-if="item.type === 'img'" :src="item.content" mode=""></image>
</view>
</view>
</view>
<!-- 我 -->
</view>
</scroll-view>
</view>
<!-- 咯傲天区域结束 -->
<view class="bottom">
<view class="zuo">
<image src="../../static/yemian/VectoSdasd.png" mode=""></image>
</view>
<view class="zhong">
<input v-model.trim="input" type="text">
</view>
<view class="you">
<image @click="choseImgSend" src="../../static/yemian/Groudssadasdas.png" mode=""></image>
<image @click="fasong" src="../../static/yemian/sdsadsadsa554.png" mode=""></image>
</view>
</view>
<view class="" style="height: 48px;">
adsad1221324234
</view>
</view>
</template>
<script>
export default {
data() {
return {
chatList:[{
isMe: false,// 之心姐姐
type: 'txt',
content: '我是之心姐姐', // 聊天内容
}
,{
isMe: true,// 我的信息
type: 'txt',
content: 'chatList', // 聊天内容
},{
isMe: true,// 我的信息
type: 'img',
content: '../../static/yemian/sdsadsadsa554.png', // 聊天内容
},{
isMe: true,// 我的信息
type: 'img',
content: '../../static/yemian/sdsadsadsa554.png', // 聊天内容
},{
isMe: true,// 我的信息
type: 'img',
content: '../../static/yemian/sdsadsadsa554.png', // 聊天内容
},{
isMe: true,// 我的信息
type: 'img',
content: '../../static/yemian/sdsadsadsa554.png', // 聊天内容
},{
isMe: true,// 我的信息
type: 'img',
content: '../../static/yemian/sdsadsadsa554.png', // 聊天内容
},{
isMe: true,// 我的信息
type: 'img',
content: '../../static/yemian/sdsadsadsa554.png', // 聊天内容
},{
isMe: true,// 我的信息
type: 'img',
content: '../../static/yemian/sdsadsadsa554.png', // 聊天内容
}],
input: ''
}
},
onShow() {
this.dibu()
},
methods: {
// 发送图片
choseImgSend(){
uni.chooseImage({
count: 1,
success :res => {
console.log(res.tempFilePaths[0])
let senMsg = {
isMe: true,
type: 'img',
content: res.tempFilePaths[0]
}
let resMsg = {
isMe: false,
type: 'img',
content: res.tempFilePaths[0]
}
this.chatList.push(senMsg, resMsg)
this.dibu()
}
})
},
// 发送图片
// 返回底部的信息
dibu(){
uni.createSelectorQuery().select('#dissan').boundingClientRect(function(rect){
uni.pageScrollTo({ duration:200,scrollTop:9999999 })
}).exec()
// uni.pageScrollTo({
// scrollTop: 9999999,
// duration: 0,
// success: res => {
// console.log(res)
// }
// })
},
// 返回底部的信息
//信息发送
fasong(){
let resMsg = {
isMe: false,
type: 'txt',
content: this.input
}
let senMsg = {
isMe: true,
type: 'txt',
content: '之心小姐姐'+this.input
}
this.chatList.push(senMsg, resMsg)
this.dibu()
this.input = ''
}
//信息发送结束
}
}
</script>
<style scoped lang="scss">
.da{
// height: 100vh;
height: auto;
}
.sssssss{
// padding-bottom: 300px;
background-color: wheat;
}
.top{
background-color: saddlebrown;
// height: calc(100% - 48px);
// height: calc(100% - 80rpx);
.shijian{
width: 140px;
text-align: center;
margin: auto;
font-weight: 400;
font-size: 12px;
line-height: 17px;
/* identical to box height */
text-align: center;
color: #333333;
}
}
.bottom{
height: 48px;
display: flex;
background-color: #eff0ef;
justify-content: space-between;
box-shadow: 0px 0px 13px rgba(0, 0, 0, 0.08);
position: fixed;
bottom: 130px;
width: 100%;
.zuo,.zhong, .you{
display: flex;
justify-content: space-around;
align-items: center;
}
.zuo{
width: 15%;
}
.zhong{
width: 65%;
input{
margin: auto;
padding: 3px 12px;
width: 100%;
height: 24px;
border-radius: 18px;
border: 1px solid #eff0ef;
}
}
.you{
width: 20%;
}
image{
width: 24px;
height: 24px;
}
}
// 聊天区域开始
.wo{
text-align: right;
display: flex;
justify-content: flex-end;
image{
width: 48px;
height: 48px;
}
.xinxi{
margin: 9px 8px 20px 0;
display: flex;
padding: 10px;
justify-content: center;
align-items: center;
background: #7ABFF0;
font-weight: 400;
font-size: 14px;
text-align: right;
color: #333333;
box-shadow: 0px 0px 8px rgba(238, 238, 238, 0.75);
border-radius: 23px 23px 1px 24px;
}
}
// 对方的信息
.dui{
text-align: left;
display: flex;
justify-content: flex-start;
image{
width: 48px;
height: 48px;
}
.dui_xinxi{
margin: 9px 0 20px 8px;
display: flex;
padding: 10px;
justify-content: center;
align-items: center;
font-weight: 400;
font-size: 14px;
text-align: right;
color: #333333;
background: honeydew;
box-shadow: 0px 0px 8px rgba(238, 238, 238, 0.75);
border-radius: 6px 24px 24px 24px;
}
}
// 对方的信息
// 聊天区域结束
</style>