准备工作
1、vue环境安装:https://editor.csdn.net/md/?articleId=108667564
2、申请一个公众号(订阅号)测试使用
3、申请开发者测试号
4、下载微信开发者工具:https://developers.weixin.qq.com/miniprogram/dev/devtools/stable.html
5、搭建一个简单的后台(随便什么都行,通过请求访问)
开始
1、搭建vue3手脚架,推荐使用vue ui或npm install -g @vue/cli
2、必要的组件:router/store/axios
3、任选一款框架,我选的是element-plus,还推荐一个vant(移动端开发比Element友好)
4、看看必须要用的几个东西
constant.js
export const serverUrl = '' // 前端页面的地址(如果是映射的就写外网地址)
export const wwwUrl = ''// 公众号的外网地址
export const appid = '' // 公众号的appid
export const appsecret = '' // 公众号的appsecret
通过https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index拿到测试用的appid和appsecret
main.js
import { createApp } from 'vue';
import App from './App.vue';
import router from '@/router';
import store from '@/store';
// axios
import {post,get,patch,put,del} from './http/request';
// ! element-plus vue3.0
import ElementPlus from 'element-plus';
import 'element-plus/lib/theme-chalk/index.css';
const app = createApp(App);
// axios定义全局变量
app.config.globalProperties.$post = post;
app.config.globalProperties.$get = get;
app.config.globalProperties.$patch = patch;
app.config.globalProperties.$put = put;
app.config.globalProperties.$del = del;
app.use(ElementPlus).use(router).use(store).mount('#app')
axios之所以这样的是因为我这边做了一个简单的封装,封装代码如下:
import axios from "axios"
import {
serverUrl
} from "@/untils/constant"; // 这里我是将所有常量放在一个地方的,需要的时候做引入,也可以直接写地址
import qs from "qs";
axios.defaults.timeout = 5000;
axios.defaults.baseURL = serverUrl;
//http request 拦截器
axios.interceptors.request.use(
config => {
let newConfig = config;
if (newConfig.url) {
// 不同的请求可以做不同的处理
newConfig.data = qs.stringify(config.data);
newConfig.headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
return newConfig;
},
error => {
return Promise.reject(err);
}
);
//http response 拦截器
axios.interceptors.response.use(
response => {
if (response.data.errCode == 2) {
router.push({
path: "/login",
query: {
redirect: router.currentRoute.fullPath
} //从哪个页面跳转
})
}
return response;
},
error => {
return Promise.reject(error)
}
)
/**
* 封装get方法
* @param url
* @param data
* @returns {Promise}
*/
export function get(url, params = {}) {
return new Promise((resolve, reject) => {
axios.get(url, {
params: params
})
.then(response => {
resolve(response.data);
})
.catch(err => {
reject(err)
})
})
}
/**
* 封装post请求
* @param url
* @param data
* @returns {Promise}
*/
export function post(url, data = {}) {
return new Promise((resolve, reject) => {
axios.post(url, data)
.then(response => {
resolve(response.data);
}, err => {
reject(err)
})
})
}
/**
* 封装patch请求(局部更新)
* @param url
* @param data
* @returns {Promise}
*/
export function patch(url, data = {}) {
return new Promise((resolve, reject) => {
axios.patch(url, data)
.then(response => {
resolve(response.data);
}, err => {
reject(err)
})
})
}
/**
* 封装put请求
* @param url
* @param data
* @returns {Promise}
*/
export function put(url, data = {}) {
return new Promise((resolve, reject) => {
axios.put(url, data)
.then(response => {
resolve(response.data);
}, err => {
reject(err)
})
})
}
/**
* 封装del请求
* @param url
* @param data
* @returns {Promise}
*/
export function del(url, data = {}) {
return new Promise((resolve, reject) => {
axios.delete(url, {data: data})
.then(response => {
resolve(response.data);
}, err => {
reject(err)
})
})
}
封装store,store作为临时数据存放的地方,对其进行一个简单的封装:
首先封装的是localStorage.js,这个的主要功能是获取浏览器内的缓存
let storage = window.localStorage;
const db = {
// 保存
save(key, value) {
storage.setItem(key, JSON.stringify(value))
},
// 获取
get(key, defaultValue = {}) {
return JSON.parse(storage.getItem(key)) || defaultValue
},
// 获取
getItem(key) {
try {
return JSON.parse(storage.getItem(key))
} catch (err) {
return null
}
},
// 移除
remove(key) {
storage.removeItem(key)
},
// 所有的key
keys() {
return storage.keys()
},
// 清除缓存
clear() {
storage.clear()
}
};
export default db
然后是store的index.js:
import { createStore } from 'vuex';
import state from './state';
import getters from './getters';
import actions from './actions';
import mutations from './mutations';
export default createStore({
// 1. state
state,
// // 2. getters
getters,
// 3. actions
// 通常跟api接口打交道
actions,
// 4. mutations
mutations
});
接下来是接口层actions
const actions = {
// 参数列表:{commit, state}
// state指的是state数据
// commit调用mutations的方法
// name就是调用此方法时要传的参数
setUser({
commit,
state
}, user) {
// 跟后台打交道
// 调用mutaions里面的方法
commit("setUser", user);
},
setAccessToken({
commit,
state
}, accessToken) {
commit("setAccessToken", accessToken);
},
setInspectRouteType({
commit,
state
}, inspectRouteType) {
commit("setInspectRouteType", inspectRouteType);
}
};
export default actions
然后是获取数据的get
import db from '@/localstorage/localstorage'
const getters = {
// 参数列表state指的是state数据
getUser(state) {
return state.user || db.get('USER-INFO');
},
getAccessToken(state) {
return state.accessToken || db.get('ACCESS_TOKEN');
},
getInspectRouteType(state) {
return state.inspectRouteType || db.get('INSPECTION-TYPE');
},
};
export default getters
设置数据的set:
import db from '@/localstorage/localstorage'
const state = {
// state指的是state的数据
// name传递过来的数据
setUser(state, val) {
db.save('USER-INFO', val);
state.user = val;
},
setAccessToken(state, val) {
db.save('ACCESS_TOKEN', val);
state.accessToken = val
},
setInspectRouteType(state, val) {
db.save('INSPECTION-TYPE', val);
state.inspectRouteType = val
},
};
export default state
初始化的state
import db from '@/localstorage/localstorage'
const state = {
userInfo: db.get('USER-INFO'),
accessToken: db.get('ACCESS_TOKEN'),
inspectRouteType: db.get('INSPECTION-TYPE')
};
export default state
至此文件结构如下:
然后就可以正常开发了:
获取微信授权
首先我们需要微信的授权才能,只有这样才能正常访问我们的网页,所以开始搞授权:
前端代码:
import { appid, wwwUrl } from "@/untils/constant";
export default {
name: "Home",
data() {
return {};
},
components: {
Footer,
},
methods: {
goTo(name) {
this.$router.push({ name: name });
},
getOpenId() {
//先判断有没有授权(判断地址栏code,有就-用户同意了授权,没有-没授权或者拒绝授权)
var str = this.$route.query.code; //此处使用的是history路由模式,hash这么拿不到。
if (str) {
// 走后端接口(把code传给后台,让后台根据code获取openID与用户信息)
this.$get("/open/lims/mdm/wechats/queries/wechat-token/" + str,{
openid : appid
})
.then((res) => {
if (res.openid) {
//拿到了ACCESS_TOKEN与用户openid,跳转到登录页面
this.$router.push({
name: "Login",
params: res,
});
} else {
alert("授权失败");
}
})
.catch((err) => {
alert("授权失败");
});
} else {
this.getCode();
}
},
getCode() {
//没授权先授权,授权后会有一个code在地址栏上
window.location.href =
"https://open.weixin.qq.com/connect/oauth2/authorize?appid=" +
appid +
"&redirect_uri=" +
wwwUrl +
"&response_type=code&scope=snsapi_userinfo&state=STATE&connect_redirect=1#wechat_redirect";
},
},
mounted() {},
created() {
this.getOpenId();
},
};
后台代码:
/**
* 获取微信的token
* @param code
* @return
*/
@Override
public JSONObject getToken(String code) {
// 拼接url
StringBuilder urlStr = new StringBuilder(url);
urlStr.append("?appid=").append(appid)
.append("&secret=").append(appSecret)
.append("&code=").append(code)
.append("&grant_type=authorization_code");
String request = HttpUtils.getRequest(urlStr.toString());
// 拿到微信的token返回给前端
final JSONObject jsonObject = JSONObject.parseObject(request);
return jsonObject;
}
private CoreUserBean getUser(String openId){
if (StringUtils.isEmpty(openId)){
return null;
}
LimsUserWechatExtBean limsUserWechatExtBean = this.selectFirstByFilter(SearchFilter.instance().match("openId", openId).filter(MatchPattern.EQ));
if (limsUserWechatExtBean != null){
// 验证用户信息,根据实际情况自行验证
return coreUserService.selectByIdIfPresent(limsUserWechatExtBean.getUserId());
}
return null;
}
获取授权后则表示用户,且我们可以获取到一些基础的用户信息作为用户的唯一的判断:
然后就是登录了:
import { loginType } from "@/untils/constant";
export default {
data() {
return {
form: {
username: "",
password: "",
openid: "",
},
};
},
methods: {
onSubmit() {
// 调起登录
let _this = this;
_this
.$post("/core/module/sys/login", {
id: _this.form.username, // 用户名
password: _this.form.password, // 密码
openid: _this.$route.params.openid || _this.$store.getters.getAccessToken.openid, // 用户微信id
loginType: loginType,
})
.then((res) => {
// 存入信息到vuex
_this.saveLoginData();
_this.goTo("ChooseInspect");
})
.catch((err) => {
alert("请检查用户名和密码是否正确!");
});
},
goTo(name) {
this.$router.push({ name: name, params: {} });
},
saveLoginData() {
let _this = this;
_this.$store.dispatch("setUser", {
id: _this.form.username,
});
_this.$store.dispatch("setAccessToken", _this.$route.params);
},
},
created() {},
mounted() {},
};
上线配置
登录后就能正常访问其他页面了,所以至此,基本开发结束,然后就是页面开发,就部多赘述了。
微信公众号上线配置:
首先需要一个已经备案的网址,然后需要在微信公众号上面配置这几个东西:
注意,这里需要上传一个tx的校验文件到服务器的根目录下面,也就是项目文件夹里面就好了。
然后就可以在微信公众号里面访问了。
nginx看情况配置就好了