要画高可用原型,顺便学了vue,3.0也出了,现在正在用MyAppBox练手,感觉还挺快,这里记录下,省着忘;

开源地址

1. 环境

  • node.js
  • vue-cli
  • .net core
  • mysql

node.js我也没学过,vue架子安装网上都有教,随便找的;.net core用的webapi做后台,我没用过正好试一试...

vue ui这东西可不错,装了element-ui、echarts等插件

首先建项目,VS2017建的 .net core MVC项目 底层代码还是沾过来的,直接就能用(而且有SQLServer类了);再建一个 基于Vue.js Web应用程序,这样他俩就在一个解决方案下了,

解决方案

vue项目发布路径指到 .net core下的 wwwroot 里,然后将启动页面改喽,这样启动AppServer就能运行了

路径
启动

其次是通讯,vue 用 axios.post 提交,webapi 接收,.net core的Controlle只能接收一个post,多个的话还得再分一层,干脆把功能标识放到参数里,另外时间戳和token也是必要的,token涉及到了拦截器(不能每个类都判断一遍token),我之前写过,拿过来改改就能用,这样提交格式就固定了,返回统一使用MsReturned类,我自己写的,

{
    Action: "Get", //动作标识
    data: {}, //提交的数据
    MenuId: "-1" //菜单ID 判断权限用
    jsTimeStamp: '' //时间戳
}
//token在config.headers["Authorization"]里

后台用OnActionExecuting拦截

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    //这里token我直接存的用户实体的json 加密后的,所以很长~
    string Token = filterContext.HttpContext.Request.Headers["Authorization"];
}

还有个方法是得到请求字符串(文件上传的还没试过)

/// <summary>
///  根据请求信息返回请求串
/// </summary>
/// <param name="request">请求信息</param>
/// <returns>请求串</returns>
public static string QueryString(HttpRequest request)
{
    string text = "";
    using (var ms = new MemoryStream())
    {
        request.Body.Seek(0, 0);
        request.Body.CopyTo(ms);
        var b = ms.ToArray();
        var postParamsString = Encoding.UTF8.GetString(b);
        text = postParamsString.ToString();
    }
    return text;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    //得到Token
    string Token = filterContext.HttpContext.Request.Headers["Authorization"];
    //得到请求路径
    string path = filterContext.HttpContext.Request.Path;
    //得到请求参数
    string body = QueryString(filterContext.HttpContext.Request);
    //任何页面都判断body 转json 和 Action MenuId 字段是否存在 
    //   如果错误返回"参数错误" code 5001
    //判断Token
    //  如果是登录页面,就不判断Token了
    //  非登录页,Token转用户 和 MenuId比对(MenuId=-1就不对比了),
    //    如果用户错误 返回" 重新登录 " code 5002
    //    如果没权限 返回" 访问权限错误 " code 5003
}

axios的用法和配置网上都有,我又包了一层,适合我的项目

/**
 * @description 提交
 * @param {String} url 地址 会自动拼接 /api/
 * @param {String} Action 请求事件名 默认是Get 参数 默认为{}
 * @param {Object} data 传递的参数 默认为{}
 * @return {Object} 返回结果
 */
export default async (url = "", Action = "Get", data = {}, MenuId = "-1") => {
  let jsTimeStamp = new Date().getTime();
  //得到当前路由的菜单ID
  if (_this && _this.$route.meta.activeMenu) {
    MenuId = _this.$route.meta.activeMenu;
  }
  //提交的参数
  let opt = { Action, data, MenuId, jsTimeStamp };
  // console.log("发送消息:" + url);
  // console.log("发送消息:" + JSON.stringify(opt));
  return service
    .post(`/api/${url}`, opt)
    .then(res => {
      // console.log("返回消息:" + JSON.stringify(res));
      return res;
    })
    .catch(err => {
      console.error("返回出错:" + err);
      return err;
    });
}

Controller中接收

[SysPageFilte]
public class System1Controller : SysControllerBase
{
    // 用户类
    // POST: api/System1
    [HttpPost]
    public ActionResult<string> Post([FromBody] dynamic data)
    {
        string jsTimeStamp = data.jsTimeStamp;
        string Action = data.Action == null ? "Get" : data.Action;
        return "";
    }
}

在vue中创建api文件夹,文件名和Controller类名一致(其实也是表名,也是实体名)

用户类
import server from "@/utils/axios.js";
/**
 * @description 用户类
 */
export default class System1 {
  constructor() {}
  /**
   * @description 得到用户List
   */
  static async get() {
    //this.name就是类名 就是System1
    let result = await server(this.name);
    return result;
  }
}

vue中用的时候就是

import { System1 } from "@/api";
...
async initPage() {
    this.sys1Data = await System1.get();
}

至此通讯就打通了,剩下就是撸代码了,

2. Vue.Router 路由

路由挺闹心,涉及子路由,动态路由,跳转,传参,拦截

但是网上也都有,没什么难度,这里主要记一下,我架子上定义了页面路径,在项目里叫功能(功能有地址,菜单没地址),这个地址传过来之后都作为子路由,上级是登录和框架 固定的路由,子路由在框架下,这里用到了node.js的方法,判断文件是否存在,如果不存在则不创建路由

const modulesFiles = require.context("../../view", true);
if(modulesFiles.keys().includes("./" + item.url))

还有一个懒加载页面,网上抄的

//懒加载页面
export default vuename => () => import(`@/view/${vuename}`);

先记这么多,下次记录封装个 dialog selectTree

功能
字典
角色