zoukankan      html  css  js  c++  java
  • JEECG技术文档摘录

    1、Hello World

    前后端分离框如何快速进入开发,请参照下面hello world实现demo

    一、后台请求实现

    @RestController
    @RequestMapping("/test/jeecgDemo")
    @Slf4j
    public class JeecgDemoController {
    
        /**
         * hello world
         * 
         * @param id
         * @return
         */
        @GetMapping(value = "/hello")
        public Result<String> hello() {
            Result<String> result = new Result<String>();
            result.setResult("Hello World!");
            result.setSuccess(true);
            return result;
        }
    }
    

    直接访问请求http://localhost:8080/jeecg-boot/test/jeecgDemo/hello 会提示token无效, 所以需要配置下拦截器ShiroConfig排除。

    配置文件: jeecg-boot-module-system/src/main/java/org/jeecg/config/ShiroConfig.java 
    加入配置:filterChainDefinitionMap.put("/test/jeecgDemo/hello", "anon");
    

    输入图片说明

    再访问请求http://localhost:8080/jeect-boot/test/jeecgDemo/hello,会返回结果如下:

    {
        "success": true,
        "message": null,
        "code": null,
        "result": "Hello World!",
        "timestamp": 1548833208562
    }
    

    二、前台vue页面实现

    (1)创建vue页面src/views/jeecg/helloworld.vue 调用后台请求,获取返回的Hello World! 输出到页面,页面代码如下:

    <template>
      <div>
        {{ msg }}
      </div>
    </template>
    
    <script>
      import {getAction} from '@/api/manage'
      export default {
        data () {
          return {
            msg: ""
          }
        },
        methods: {
          hello () {
            var url = "/test/jeecgDemo/hello"
            getAction(url).then((res) => {
              if (res.success) {
                this.msg = res.result;
              }
            })
          }
        },
        created() {
          this.hello();
        }
      }
    </script>
    

    代码说明:

    1、data() 方法中定义数据对象msg 2、数据对象msg输出到页面,表达式如下:

    {{ msg }}
    3、定义一个方法,发起请求获取后台响应 后台实现的是get方法,引入getAction方法 import {getAction} from '@/api/manage' 定义方法调用:

         hello () {
            var url = "/test/jeecgDemo/hello"
            getAction(url).then((res) => {
              if (res.success) {
                this.msg = res.result;
              }
            })
          }
    

    4、Vue生命周期 created 中调用方法 created() { this.hello(); } hello方法中 this.msg = res.result; 把请求返回的Hello World! 赋值给msg数据对象,msg值改变则页面显示也改变。

    三、配置菜单

    配置helloword菜单【系统管理】-【菜单管理】 输入图片说明

    • 其中前端组件配置相对src/views/目录下的 目录名+文件名
    • 例如页面src/views/jeecg/helloworld.vue 前端组件配置 jeecg/helloworld

    输入图片说明 用户角色授权【系统管理】-【角色管理】-授权 输入图片说明 输入图片说明 点击菜单访问页面展示Hello World!

    2、UI前端开发技巧

    2.1全局配置文件

    升级日志: 20190324

    前台全局配置文件 配置内容:后台域名、图片服务器域名配置 文件位置:public/index.html 好处: 前端build完也可以直接修改index.html配置内容

    <!-- 全局配置 -->
      <script>
        window._CONFIG = {};
        window._CONFIG['domianURL'] = 'http://localhost:8080/jeecg-boot';
        window._CONFIG['imgDomainURL'] = 'http://localhost:8080/jeecg-boot/sys/common/view';
        window._CONFIG['pdfDomainURL'] = 'http://localhost:8080/jeecg-boot/sys/common/pdf/pdfPreviewIframe';
        window._CONFIG['casPrefixUrl'] = 'http://cas.example.org:8443/cas';
      </script>
    

    用法:

    参数 写法 描述
    后台服务域名 window._CONFIG['domianURL'] -
    图片服务器域名 window._CONFIG['imgDomainURL'] -
    pdf文件预览地址 window._CONFIG['pdfDomainURL'] -
    CAS服务器地址 window._CONFIG['casPrefixUrl'] -

    2.2源码解读

    1. 登录页面代码位置

      srccomponentslayoutsUserLayout.vue
      src/views/user/Login.vue
      
    2. 首页logo修改

      src/components/tools/Logo.vue
      
    3. 图片预览路径

      public/index.html
      <!-- 全局配置 -->
      <script>
       window._CONFIG = {};
       window._CONFIG['imgDomainURL'] = 'http://localhost:8080/jeecg-boot/sys/common/view';
      </script>
      图文访问路径: http://127.0.0.1:8080/jeecg-boot/sys/common/view/user/h.jpg
      

      4.首页报表

      src/views/dashboard/*
      src/views/dashboard/Analysis.vue
      
    4. 登录退出逻辑

      1.登录页面: src/views/user/Login.vue
      2.相关API定义位置: src/api/index.js(很多无用的删掉)
                       src/api/index.js
                       src/api/login.js
                       src/api/manage.js
      3.左侧菜单加载页面:src/components/menu
                  src/utils/util.js
                  src/permission.js
      4.隐藏路由配置
       用途: 如果那个组件不想在菜单上配置,但有需要路由跳转,则需要在这个地方配置路由。
       src/config/router.config.js
       对象: constantRouterMap
      5. 接口:   /sys/login        登录接口
               /sys/permission/queryByUser  获取用户信息接口(首页菜单)
      

    6.首页风格设置 src/defaultSettings.js

    2.3vue路由带参总结

    2.3.1 params

    配置路由格式要求: path: "/test/:id"
    js参数获取:this.$route.params.id


    2.3.2 query

    配置路由:无要求
    js参数获取:this.$route.query.id


    备注:

    router-link是html写法,JS中语法如下:
    this.$router.push({name:'test',query: {id:'1'}})
    this.$router.push({name:'test',params: {id:'1'}})

    2.4vuex 使用详解

    一、什么是vuex

    vuex是一个专门为vue.js设计的集中式状态管理架构。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。。
    

    二、vuex使用场景

    vuex主要是是做数据交互,父子组件传值可以很容易办到,但是兄弟组件间传值(兄弟组件下又有父子组件),或者大型spa单页面框架项目,页面多并且一层嵌套一层的传值,异常麻烦,用vuex来维护共有的状态或数据会更便捷
    

    场景说明:

    • 由于vuex中的state存放的数据在页面刷新时会丢失,vuex只能用于单个页面中不同组件(例如兄弟组件)的数据流通

    三、Vuex核心概念

    • 1、store:类似容器,包含应用的大部分状态

      一个页面只能有一个容器 状态存储是响应式的 不能直接改变store中的状态,唯一途径显示地提交mutations 在actions里面,也不能直接更改state里面的状态值,必须先定义一个mutations,然后在actions里面commit这个mutations,从而来更改state的状态值; 如果要再次请求异步,那么就是dispatch一个actions

    • 2、State:包含所有应用级别状态的对象

    • 3、Getters:在组件内部获取store中状态的函数,类似组件的计算属性computed

    • 4、Mutations:唯一修改状态的事件回调函数,默认是同步的,如果要异步就使用Actions

    • 5、Actions:包含异步操作、提交mutations改变状态

    • 6、Modules:将store分割成不同的模块

    四、引入Vuex

    1、安装vuex

    npm install vuex --save
    

    2、新建一个store文件夹(这个不是必须的),并在文件夹下新建index.js文件,文件中引入我们的vue和vuex

    输入图片说明

    3、在main.js 中引入新建的store

    import store from './store/'
    
     new Vue({
          el: '#app',
          router,
          store,//使用store
          template: '<App/>',
          components: { App }
        })
    

    五、页面使用

    1.读取store里的值:
    
    this.$store.state.字段名 
    如果有 moudle 的话,假设叫 user ,那么取值又要变了,加上 module 名
    
    this.$store.state.user.字段名 
    
    2.发起操作请求:
    
    this.$store.dispatch('action中的方法名' , '参数') ;
    
    参数你可以随便传json
    
    3.getters的用法
    
    this.$store.getters.filterDoned 
    filterDoned 是在 todo 里写的一个 getters 方法,就这么
    

    3、菜单路由配置

    3.1菜单配置说明

    字段名称 说明
    菜单类型 一级菜单:配置一级菜单;子菜单:配置下级菜单;按钮:配置页面按钮权限
    菜单名称 定义菜单名称
    上级菜单 菜单类型为子菜单时,选择关联的上级菜单
    菜单路径 定义菜单的路径,通常为:/包名/文件名 具体参见【菜单路径配置说明】
    前端组件 定义菜单访问的组件名称,有两种类型,一种为通用组件,一种为具体的页面,
    具体参见【前端组件配置说明】
    菜单图标 菜单树展示的图标
    排序 菜单展示的先后顺序
    是否路由 此处很重要,默认是路由;如果是非的话,访问404
    隐藏路由 不展示为菜单,但是在页面中跳转,弹出的页面路由菜单
    聚合路由 多个下级菜单路由在一个页面聚合展示
    3.1.1前端组件配置说明:
    • 1、非叶子菜单(即没有下级的菜单)配置固定 前端组件layouts/RouteView

    • 2、普通的叶子菜单(即具体的页面) 配置相对于src/views目录的路径

      例如src/views/jeecg/helloworld.vue 这个页面(具体参考底部截图) 配置菜单时 前端组件为 jeecg/helloworld

    • 3、需要跳转到第三页面的菜单 前端组件固定为:layouts/IframePageView(具体参考底部截图)

      (比如跳转百度:https://www.baidu.com)/)

    • 4、java后台请求的菜单

      需要以{{ window._CONFIG['domianURL'] }}开头(具体参考底部截图)

    3.1.2菜单路径配置说明
    • 1、非叶子菜单(即没有下级的菜单),URL配置规则:按照功能模块定义的关键根路径即可,不能重复,需以“/”开头
    • 2、普通的叶子菜单(即具体的页面),URL和前端组件配置保持一致即可,需在前端组件值前加“/”
    • 3、需要跳转到第三方页面的菜单,菜单路径配置第三方跳转的地址即可,例如http://www.baidu.com

    参考示例:

    • 1.路由菜单配置截图 输入图片说明
    • 2.外部链接菜单 输入图片说明
    • 3.后台链接菜单 输入图片说明

    3.2路由菜单规则

    菜单配置就是配置前端所需要的路由 菜单路径 : 对应页面访问请求URL (系统唯一,不能有重复URL) 前端组件 : 对应前端页面组件(路径+名字,无.vue后缀)

    路由name取值规则:

    通过菜单URL,生成路由name(去掉URL前缀斜杠,替换内容中的斜杠‘/’为-)
    举例: URL = /account/settings/base
          RouteName = account-settings-base
    

    前端页面跳转用法:

    <router-link :to="{ name: 'account-settings-base' }">
       基本设置
     </router-link>
    

    4、系统权限用法

    4.1页面表单权限

    4.1.1显示隐藏控制

    一、用法
    v-has="'name'"
    

    代码示例:

    <a-form-item v-has="'name'"
      :labelCol="labelCol"
      :wrapperCol="wrapperCol"
      label="请假人">
      <a-input placeholder="请输入请假人" v-decorator="['name', {}]" />
    </a-form-item>
    
    二、权限配置:

    输入图片说明

    三、使用说明
    • v-has="'name'" 指令值“name”为授权标识,可对该授权标识进行“显示/访问”控制
    • 权限编码在【系统管理--菜单管理】中配置,添加按钮类型的菜单数据,授权标识配置值“name”,策略选择显示/访问,状态选择有效
    • 控制规则:
    • (1)使用v-has指令后,菜单权限中若没有对应指令编码的配置,则不显示控件,
    • (2)权限配置无效状态时,则不进行权限控制,有效状态时进行控制
    • (3)策略:显示/访问,未授权时不显示,授权后显示
    四、流程节点权限

    (1)说明:

    • 节点权限配置优先级高于菜单权限配置
    • 节点权限应用于使用组件方式加载的附加表单页面,并对附加表单页面进行权限控制
    • 显示控制用法见上面用法描述
    • 节点权限是通过 props: ['formData'],来传递给节点表单页面的,因此页面一定要定义这个,否则,节点配置的权限不生效
    • 权限配置无效状态时,则不进行权限控制,有效状态时进行控制

    (2)权限配置: 在【流程管理-流程设计】中找到需要配置的流程,进入【流程配置-流程节点】选择需要进行权限控制的节点, 点击【更多-权限设置】,新增/编辑 来配置权限。

    输入图片说明

    4.1.2禁用控制用法一

    一、用法

    (1)页面引入混入代码

    import {DisabledAuthFilterMixin} from '@/mixins/DisabledAuthFilterMixin'
    mixins: [DisabledAuthFilterMixin],
    

    输入图片说明

    (2)权限控制代码示例:

    <a-input-number :disabled="isDisabledAuth('name')"   v-decorator="[ 'days', {}]" />
    
    二、权限配置:

    输入图片说明

    三、使用说明
    • :disabled="isDisabledAuth('name')" 调用方法disabledAuth,方法参数“name”为授权标识,该方法根据授权规则返回true/false,控制是否禁用
    • 权限编码在【系统管理--菜单管理】中配置,添加按钮类型的菜单数据,授权标识配置值“name”,策略选择可编辑,状态选择有效
    • 控制规则:
    • (1)菜单权限中若没有对应指令编码的配置,则不进行禁用控制,
    • (2)权限配置无效状态时,则不进行权限控制,有效状态时进行控制
    • (3)策略:可编辑,未授权时控件禁用,授权后可编辑
    四、流程节点权限

    (1)说明:

    • 节点权限配置优先级高于菜单权限配置
    • 节点权限应用于使用组件方式加载的附加表单页面,并对附加表单页面进行权限控制
    • 显示控制用法见上面用法描述
    • 节点权限是通过 props: ['formData'],来传递给节点表单页面的,因此页面一定要定义这个,否则,节点配置的权限不生效,节点表单开发方法见【流程节点对接表单页面开发方法】
    • 权限配置无效状态时,则不进行权限控制,有效状态时进行控制

    (2)权限配置: 在【流程管理-流程设计】中找到需要配置的流程,进入【流程配置-流程节点】选择需要进行权限控制的节点, 点击【更多-权限设置】,新增/编辑 来配置权限。

    输入图片说明

    4.1.3禁用控制用法二

    一、用法

    (1)页面引入工具js

    import { disabledAuthFilter } from "@/utils/authFilter"
    

    (2)methods方法中实现:

    isDisabledAuth(code){
          return disabledAuthFilter(code);
        },
    

    输入图片说明

    输入图片说明

    (2)权限控制代码示例:

    <a-input-number :disabled="isDisabledAuth('name')"   v-decorator="[ 'days', {}]" />
    
    二、权限配置:

    输入图片说明

    三、使用说明
    • :disabled="isDisabledAuth('name')" 调用方法disabledAuth,方法参数“name”为授权标识,该方法根据授权规则返回true/false,控制是否禁用
    • 权限编码在【系统管理--菜单管理】中配置,添加按钮类型的菜单数据,授权标识配置值“name”,策略选择可编辑,状态选择有效
    • 控制规则:
    • (1)菜单权限中若没有对应指令编码的配置,则不进行禁用控制,
    • (2)权限配置无效状态时,则不进行权限控制,有效状态时进行控制
    • (3)策略:可编辑,未授权时控件禁用,授权后可编辑
    四、流程节点权限

    (1)说明:

    • 节点权限配置优先级高于菜单权限配置

    • 节点权限应用于使用组件方式加载的附加表单页面,并对附加表单页面进行权限控制

    • 显示控制用法见上面用法描述

    • 节点权限是通过 props: ['formData'],来传递给节点表单页面的,因此页面一定要定义这个,否则,节点配置的权限不生效,节点表单开发方法见【流程节点对接表单页面开发方法】

    • 权限配置无效状态时,则不进行权限控制,有效状态时进行控制

    • (2)methods方法中实现:

      isDisabledAuth(code){
            return disabledAuthFilter(code,this.formData);
          },
      

    (2)权限配置: 在【流程管理-流程设计】中找到需要配置的流程,进入【流程配置-流程节点】选择需要进行权限控制的节点, 点击【更多-权限设置】,新增/编辑 来配置权限。

    输入图片说明

    4.2页面按钮权限用法

    1.前端页面通过使用指令 v-has

    <a-button @click="handleAdd" v-has="'user:add'" type="primary" icon="plus">添加用户</a-button>
    

    2.后台进入菜单管理页面配置按钮权限菜单 输入图片说明

    3.进入角色管理授权按钮(授权后即可看见按钮) 输入图片说明

    4.3JAVA访问权限控制

    1.后台请求权限控制,通过Shiro注解 @RequiresPermissions

    @RequestMapping(value = "/add", method = RequestMethod.POST)
    @RequiresPermissions("user:add")
    public Result<SysUser> add(@RequestBody JSONObject jsonObject) {
    

    2.后台进入菜单管理页面配置访问权限标识(选择按钮类型) (配置方式与按钮权限一样,即同一个授权标识,可以同时控制后台请求和前台按钮显示控制) 输入图片说明

    3.进入角色管理授权访问权限(授权后即可访问该请求) 输入图片说明

    4.4数据权限

    4.4.1数据权限规则篇

    一、功能说明

    列表数据权限,主要通过数据权限控制行数据,让不同的人有不同的查看数据规则; 比如: 销售人员只能看自己的数据;销售经理可以看所有下级销售人员的数据;财务只看金额大于5000的数据等等;

    二、数据权限分两大类型
    序号 类型 规则字段区别 说明
    1 编码方式 规则字段是驼峰写法,对应mybatis实体的字段 编码模式(通过代码生成器生成代码)
    2 Online方式 规则字段是下划线写法,对应表的字段 Online模式(在线表单模式,无代码)
    规则字段配置说明(非常重要): 
    ①条件规则:大于/大于等于/小于/小于等于/等于/包含/模糊/不等于
    ②规则值:指定值 ( 固定值/系统上下文变量 )
    
    三、数据权限规则篇
    1.当前用户上下文变量

    注意:数据权限配置,规则值可以填写系统上下文变量(当前登录人信息),从而根据当前登录人信息进行权限控制。

    编码 描述
    sys_user_code 当前登录用户登录账号
    sys_user_name 当前登录用户真实名称
    sys_date 当前系统日期
    sys_time 当前系统时间
    sys_org_code 当前登录用户部门编号
    sysMultiOrgCode 当前登录用户拥有的所有机构编码,逗号分隔

    规则值,配置写法如下:#{sys_user_code}

    2.建表规范(系统标准字段)

    如果需要通过当前登录人,进行数据权限控制,则业务表必须有以下系统标准字段;数据添加和编辑,jeecg会通过拦截器自动注入操作人的信息。 比如:创建人,创建时间,创建人所属部门、创建人所属公司,有了这些标准字段,就可以通过当前登录人进行数据隔离控制;

    字段英文名 字段中文名
    CREATE_BY 系统用户登录账号
    CREATE_NAME 系统用户真实名字
    SYS_ORG_CODE 登录用户所属部门
    3.组织机构邮编规则

    JEECG组织机构支持无限层级,上下级关系通过组织机构编码实现,组织机构编码规则类似邮编方式,看下图; 邮编规则优势: 邮编规则,上下级编码固定规律,便于定位下级和上级; 输入图片说明

    4.4.2系统数据权限用法

    一、功能说明

    列表数据权限,主要通过数据权限控制行数据,让不同的人有不同的查看数据规则; 比如: 销售人员只能看自己的数据;销售经理可以看所有下级销售人员的数据;财务只看金额大于5000的数据等等;

    二、使用说明 (有两种使用方法,以下说明以用户管理列表查询示例 配置数据规则:只查询用户账号带1的用户

    方法A步骤如下:

    • A-1.新增权限菜单:进入【系统管理】-->【菜单管理】界面 新增一个权限菜单(如下图)

    输入图片说明

    • A-2.配置数据权限规则:找到上述1新增的菜单,点击操作列更多中的数据规则,配置,只查询用户账号带1的用户(如下图) 输入图片说明
    • A-3.角色授权:进入【系统管理】-->【角色管理】界面找到当前用户对应的角色,点击 更多->授权 操作,右侧弹出框中找到上述1菜单,点击后勾选权限规则,保存(如下图) 输入图片说明
    • A-4.在后台请求方法上加注解 @PermissionData 在方法上加注解是为了提高系统运行效率,这样就可以指定请求走权限过滤的逻辑,而非一棍子打死,让所有请求都去筛选一下权限(如下图) 输入图片说明
    • A-5.测试,访问用户管理界面发现数据被过滤了,即权限生效!

    方法A的问题在于,每个请求都需要配置一个权限菜单,这样其实也很费劲,同时对于菜单管理也不是很好,鉴于此可以考虑使用方法B 方法B基于注解属性pageComponent,步骤如下:

    • B-1.找到需要配置权限的页面菜单,这里是用户管理菜单

    输入图片说明 直接在该菜单上配置数据规则(如A-2)

    • B-2.角色授权(如A-3)
    • B-3.添加注解 (如A-4,不同的是注解上增加了一个属性)@PermissionData(pageComponent="system/UserList") pageComponent的值和B-1中菜单的前端组件值保持一致
    • B-4.测试,访问用户管理界面发现数据被过滤了,即权限生效!
    规则字段配置说明(非常重要): 
    ①条件规则:大于/大于等于/小于/小于等于/等于/包含/模糊/不等于/自定义SQL
    ②规则值:指定值 ( 固定值/系统上下文变量 )
    
    三、数据权限规范说明
    1.系统上下文变量

    注意:数据权限配置,规则值可以填写系统上下文变量(当前登录人信息),从而根据当前登录人信息进行权限控制。

    编码 描述
    sys_user_code 当前登录用户登录账号
    sys_user_name 当前登录用户真实名称
    sys_date 当前系统日期
    sys_time 当前系统时间
    sys_org_code 当前登录用户部门编号

    规则值,配置写法如下:#{sys_user_code}

    2.建表规范(系统标准字段)

    如果需要通过当前登录人,进行数据权限控制,则业务表必须有以下系统标准字段;数据添加和编辑,jeecg会通过拦截器自动注入操作人的信息。 比如:创建人,创建时间,创建人所属部门、创建人所属公司,有了这些标准字段,就可以通过当前登录人进行数据隔离控制;

    字段英文名 字段中文名
    CREATE_BY 系统用户登录账号
    CREATE_NAME 系统用户真实名字
    SYS_ORG_CODE 登录用户所属部门
    3.组织机构邮编规则

    JEECG组织机构支持无限层级,上下级关系通过组织机构编码实现,组织机构编码规则类似邮编方式,看下图; 邮编规则优势: 邮编规则,上下级编码固定规律,便于定位下级和上级; 输入图片说明

    4.5列表列权限控制

    针对数据列表的列进行权限控制,控制列的展示与不展示,需要菜单的权限配置与页面代码配置使用 控制规则: 增加权限控制配置与代码后,配置有效的状态未授权时隐藏,授权时显示

    举例: 针对常用示例列表,的用户名字段 输入图片说明

    权限控制步骤
    1. 针对列表列配置权限
    在配置前需要对需要控制的列表权限编码定义一个前缀,规则自己设计,不同的列表定义不同前缀最好不要重复
    例如:定义前缀“testdemo:”  则需要对列表中的name列进行控制,权限编码为,前缀+列字段名 (“testdemo:name”)
    

    在对应的列表页面菜单下配置权限:

    输入图片说明

    配置说明:

    • 菜单类型:选择“按钮/权限”
    • 授权标识:前缀+列字段名 (“testdemo:name”)
    • 授权策略:选择“显示/访问(授权后显示/可访问)”
    • 状态:选择“有效”
    2. 增加页面控制代码

    (1)引入工具方法

    import { colAuthFilter } from "@/utils/authFilter"
    

    (2)created方法中增加方法调用,根据权限过滤展示的列

    created() {
          this.columns = colAuthFilter(this.columns,'testdemo:');
          this.loadData();
        },
    
    说明:
    colAuthFilter方法:
    第一个参数:列表定义的列信息
    第二个参数:列权限控制定义的权限编码前缀“t
    

    4.6聚合路由的使用

    聚合路由, 配置后子菜单路由不显示,子菜单之间的跳转通过页面上的路由链接进行跳转

    输入图片说明

    输入图片说明

    输入图片说明

    备注:父级菜单配置如下
    (1)配置聚合路由,选择是;
    (2)菜单地址配置其子菜单中的一个菜单地址,作为默认跳转的地址;
    
  • 相关阅读:
    【C#界面库】关于C#界面库的选择
    asp.net mvc 学习笔记
    ASP.NET MVC5+EF6+LayUI实战教程,通用后台管理系统框架(7)- EF增删改查
    ASP.NET MVC5+EF6+LayUI实战教程,通用后台管理系统框架(6)- 创建数据库
    ASP.NET MVC5+EF6+LayUI实战教程,通用后台管理系统框架(5)- 创建项目结构
    ASP.NET MVC5+EF6+LayUI实战教程,通用后台管理系统框架(4)- 漂亮的登录界面
    ASP.NET MVC5 + EF6 + LayUI实战教程,通用后台管理系统框架(3)
    ASP.NET MVC5+EF6+LayUI实战教程,通用后台管理系统框架(2)
    ASP.NET MVC5+EF6+LayUI实战教程,通用后台管理系统框架(1)
    初学编程:8款最佳Raspberry Pi 操作系统/项目
  • 原文地址:https://www.cnblogs.com/cnbzys/p/12084430.html
Copyright © 2011-2022 走看看