准备工作

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

微信开发工具如何开发公众号项目引入本地vue 微信公众号vue开发教程_ios

通过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

至此文件结构如下:

微信开发工具如何开发公众号项目引入本地vue 微信公众号vue开发教程_封装_02


然后就可以正常开发了:

获取微信授权

首先我们需要微信的授权才能,只有这样才能正常访问我们的网页,所以开始搞授权:
前端代码:

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() {},
};

上线配置

登录后就能正常访问其他页面了,所以至此,基本开发结束,然后就是页面开发,就部多赘述了。
微信公众号上线配置:
首先需要一个已经备案的网址,然后需要在微信公众号上面配置这几个东西:

微信开发工具如何开发公众号项目引入本地vue 微信公众号vue开发教程_vue.js_03


注意,这里需要上传一个tx的校验文件到服务器的根目录下面,也就是项目文件夹里面就好了。

微信开发工具如何开发公众号项目引入本地vue 微信公众号vue开发教程_java_04


然后就可以在微信公众号里面访问了。

nginx看情况配置就好了