Laravel 使用 iview-admin

iView admin是基于Vue.js,搭配使用iView UI组件库形成的一套后台集成解决方案,由TalkingData前端可视化团队部分成员开发维护.
在线访问体验(密码随意填,但要记住!)
github地址
官方文档

第一步 下载 iview-admin

首先你需要去 iview-admin 下载最新的包,随便你用任何方式 download.
下载完后的文件夹内容

image.png

第二步 文件整理

把 iview-admin 里面的 src 目录下的东西,全部复制粘贴到 laravel项目 里面的 resources\assets\js 目录下(把laravel 原来js目录下的东西全部删掉或者只留下bootstrap.js)然后把laravel 里面 resources\assets\js 目录下的 main.js 改名为 app.js


image.png

第三步 修改 laravel-mix 和 webpack 相关文件

把根目录下的 package.json 文件修改为

{
        "private": true,
        "scripts": {
        "dev": "npm run development",
        "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
        "watch": "npm run development -- --watch",
        "watch-poll": "npm run watch -- --watch-poll",
        "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
        "prod": "npm run production",
        "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
    },
    "dependencies": {
        "axios": "^0.18.0",
        "clipboard": "^2.0.0",
        "codemirror": "^5.38.0",
        "countup": "^1.8.2",
        "cropperjs": "^1.2.2",
        "dayjs": "^1.7.7",
        "echarts": "^4.0.4",
        "html2canvas": "^1.0.0-alpha.12",
        "iview": "^3.1.3",
        "iview-area": "^1.5.17",
        "js-cookie": "^2.2.0",
        "simplemde": "^1.11.2",
        "sortablejs": "^1.7.0",
        "tree-table-vue": "^1.0.5",
        "vue": "^2.5.10",
        "vue-i18n": "^7.8.0",
        "vue-router": "^3.0.1",
        "vuedraggable": "^2.16.0",
        "vuex": "^3.0.1",
        "wangeditor": "^3.1.1",
        "xlsx": "^0.13.3"
    },
    "devDependencies": {
        "@vue/cli-plugin-babel": "^3.0.1",
        "@vue/cli-plugin-eslint": "^3.0.1",
        "@vue/cli-plugin-unit-mocha": "^3.0.1",
        "@vue/cli-service": "^3.0.1",
        "@vue/eslint-config-standard": "^3.0.0-beta.10",
        "@vue/test-utils": "^1.0.0-beta.10",
        "chai": "^4.1.2",
        "eslint-plugin-cypress": "^2.0.1",
        "less": "^2.7.3",
        "less-loader": "^4.0.5",
        "lint-staged": "^6.0.0",
        "mockjs": "^1.0.1-beta3",
        "vue-template-compiler": "^2.5.13"
    }
}

把根目录下的 webpack.mix.js 文件修改为

let mix = require('laravel-mix');

const path = require('path')
const resolve = dir => {
    return path.join(__dirname, dir)
}
mix.webpackConfig({
    resolve: {
        alias:{
            '@':resolve('resources/assets/js'),
            '_c':resolve('resources/assets/js/components'),
            // '_conf':resolve('resources/assets/js/config')
        }
    }
});
mix.js('resources/assets/js/app.js', 'public/js/')
    .sass('resources/assets/sass/app.scss', 'public/css/');

把resources\assets\js\router\routers.js 文件修改为

import Main from '@/components/main'
import parentView from '@/components/parent-view'

/**
 * iview-admin中meta除了原生参数外可配置的参数:
 * meta: {
 *  title: { String|Number|Function }
 *         显示在侧边栏、面包屑和标签栏的文字
 *         使用'{{ 多语言字段 }}'形式结合多语言使用,例子看多语言的路由配置;
 *         可以传入一个回调函数,参数是当前路由对象,例子看动态路由和带参路由
 *  hideInBread: (false) 设为true后此级路由将不会出现在面包屑中,示例看QQ群路由配置
 *  hideInMenu: (false) 设为true后在左侧菜单不会显示该页面选项
 *  notCache: (false) 设为true后页面在切换标签后不会缓存,如果需要缓存,无需设置这个字段,而且需要设置页面组件name属性和路由配置的name一致
 *  access: (null) 可访问该页面的权限数组,当前路由设置的权限会影响子路由
 *  icon: (-) 该页面在左侧菜单、面包屑和标签导航处显示的图标,如果是自定义图标,需要在图标名称前加下划线'_'
 *  beforeCloseName: (-) 设置该字段,则在关闭当前tab页时会去'@/router/before-close.js'里寻找该字段名对应的方法,作为关闭前的钩子函数
 * }
 */

export default [
    {
        path: '/login',
        name: 'login',
        meta: {
            title: 'Login - 登录',
            hideInMenu: true
        },
        component: resolve => { require(['@/view/login/login.vue'], resolve); }
},
{
    path: '/',
        name: '_home',
    redirect: '/home',
    component: Main,
    meta: {
    hideInMenu: true,
        notCache: true
},
    children: [
        {
            path: '/home',
            name: 'home',
            meta: {
                hideInMenu: true,
                title: '首页',
                notCache: true,
                icon: 'md-home'
            },
            component: resolve => { require(['@/view/single-page/home'], resolve); }

        }
]
},
{
    path: '',
        name: 'doc',
    meta: {
    title: '文档',
        href: 'https://lison16.github.io/iview-admin-doc/#/',
        icon: 'ios-book'
}
},
{
    path: '/join',
        name: 'join',
    component: Main,
    meta: {
    hideInBread: true
},
    children: [
        {
            path: 'join_page',
            name: 'join_page',
            meta: {
                icon: '_qq',
                title: 'QQ群'
            },
            component: resolve => { require(['@/view/join-page.vue'], resolve); }

        }
]
},
{
    path: '/message',
        name: 'message',
    component: Main,
    meta: {
    hideInBread: true,
        hideInMenu: true
},
    children: [
        {
            path: 'message_page',
            name: 'message_page',
            meta: {
                icon: 'md-notifications',
                title: '消息中心'
            },
            component: resolve => { require(['@/view/single-page/message/index.vue'], resolve); }

        }
]
},
{
    path: '/components',
        name: 'components',
    meta: {
    icon: 'logo-buffer',
        title: '组件'
},
    component: Main,
        children: [
    {
        path: 'count_to_page',
        name: 'count_to_page',
        meta: {
            icon: 'md-trending-up',
            title: '数字渐变'
        },
        component: resolve => { require(['@/view/components/count-to/count-to.vue'], resolve); }

    },
    {
        path: 'drag_list_page',
            name: 'drag_list_page',
        meta: {
        icon: 'ios-infinite',
            title: '拖拽列表'
    },
        component: resolve => { require(['@/view/components/drag-list/drag-list.vue'], resolve); }

    },
    {
        path: 'tree_table_page',
            name: 'tree_table_page',
        meta: {
        icon: 'md-git-branch',
            title: '树状表格'
    },
        component: resolve => { require(['@/view/components/tree-table/index.vue'], resolve); }

    },
    {
        path: 'cropper_page',
            name: 'cropper_page',
        meta: {
        icon: 'md-crop',
            title: '图片裁剪'
    },
        component: resolve => { require(['@/view/components/cropper/cropper.vue'], resolve); }

    },
    {
        path: 'tables_page',
            name: 'tables_page',
        meta: {
        icon: 'md-grid',
            title: '多功能表格'
    },
        component: resolve => { require(['@/view/components/tables/tables.vue'], resolve); }

    },
    {
        path: 'split_pane_page',
            name: 'split_pane_page',
        meta: {
        icon: 'md-pause',
            title: '分割窗口'
    },
        component: resolve => { require(['@/view/components/split-pane/split-pane.vue'], resolve); }

    },
    {
        path: 'markdown_page',
            name: 'markdown_page',
        meta: {
        icon: 'logo-markdown',
            title: 'Markdown编辑器'
    },
        component: resolve => { require(['@/view/components/markdown/markdown.vue'], resolve); }

    },
    {
        path: 'editor_page',
            name: 'editor_page',
        meta: {
        icon: 'ios-create',
            title: '富文本编辑器'
    },
        component: resolve => { require(['@/view/components/editor/editor.vue'], resolve); }
    },
    {
        path: 'icons_page',
            name: 'icons_page',
        meta: {
        icon: '_bear',
            title: '自定义图标'
    },
        component: resolve => { require(['@/view/components/icons/icons.vue'], resolve); }

    }
]
},
{
    path: '/update',
        name: 'update',
    meta: {
    icon: 'md-cloud-upload',
        title: '数据上传'
},
    component: Main,
        children: [
    {
        path: 'update_table_page',
        name: 'update_table_page',
        meta: {
            icon: 'ios-document',
            title: '上传Csv'
        },
        component: resolve => { require(['@/view/update/update-table.vue'], resolve); }

    },
    {
        path: 'update_paste_page',
            name: 'update_paste_page',
        meta: {
        icon: 'md-clipboard',
            title: '粘贴表格数据'
    },
        component: resolve => { require(['@/view/update/update-paste.vue'], resolve); }
    }
]
},
{
    path: '/excel',
        name: 'excel',
    meta: {
    icon: 'ios-stats',
        title: 'EXCEL导入导出'
},
    component: Main,
        children: [
    {
        path: 'upload-excel',
        name: 'upload-excel',
        meta: {
            icon: 'md-add',
            title: '导入EXCEL'
        },
        component: resolve => { require(['@/view/excel/upload-excel.vue'], resolve); }

    },
    {
        path: 'export-excel',
            name: 'export-excel',
        meta: {
        icon: 'md-download',
            title: '导出EXCEL'
    },
        component: resolve => { require(['@/view/excel/export-excel.vue'], resolve); }
    }
]
},
{
    path: '/tools_methods',
        name: 'tools_methods',
    meta: {
    hideInBread: true
},
    component: Main,
        children: [
    {
        path: 'tools_methods_page',
        name: 'tools_methods_page',
        meta: {
            icon: 'ios-hammer',
            title: '工具方法',
            beforeCloseName: 'before_close_normal'
        },
        component: resolve => { require(['@/view/tools-methods/tools-methods.vue'], resolve); }

    }
]
},
{
    path: '/i18n',
        name: 'i18n',
    meta: {
    hideInBread: true
},
    component: Main,
        children: [
    {
        path: 'i18n_page',
        name: 'i18n_page',
        meta: {
            icon: 'md-planet',
            title: 'i18n - {{ i18n_page }}'
        },
        component: resolve => { require(['@/view/i18n/i18n-page.vue'], resolve); }

    }
]
},
{
    path: '/error_store',
        name: 'error_store',
    meta: {
    hideInBread: true
},
    component: Main,
        children: [
    {
        path: 'error_store_page',
        name: 'error_store_page',
        meta: {
            icon: 'ios-bug',
            title: '错误收集'
        },
        component: resolve => { require(['@/view/error-store/error-store.vue'], resolve); }

    }
]
},
{
    path: '/error_logger',
        name: 'error_logger',
    meta: {
    hideInBread: true,
        hideInMenu: true
},
    component: Main,
        children: [
    {
        path: 'error_logger_page',
        name: 'error_logger_page',
        meta: {
            icon: 'ios-bug',
            title: '错误收集'
        },
        component: resolve => { require(['@/view/single-page/error-logger.vue'], resolve); }

    }
]
},
{
    path: '/directive',
        name: 'directive',
    meta: {
    hideInBread: true
},
    component: Main,
        children: [
    {
        path: 'directive_page',
        name: 'directive_page',
        meta: {
            icon: 'ios-navigate',
            title: '指令'
        },
        component: resolve => { require(['@/view/directive/directive.vue'], resolve); }

    }
]
},
{
    path: '/multilevel',
        name: 'multilevel',
    meta: {
    icon: 'md-menu',
        title: '多级菜单'
},
    component: Main,
        children: [
    {
        path: 'level_2_1',
        name: 'level_2_1',
        meta: {
            icon: 'md-funnel',
            title: '二级-1'
        },
        component: resolve => { require(['@/view/multilevel/level-2-1.vue'], resolve); }

    },
    {
        path: 'level_2_2',
            name: 'level_2_2',
        meta: {
        access: ['super_admin'],
            icon: 'md-funnel',
            showAlways: true,
            title: '二级-2'
    },
        component: parentView,
            children: [
        {
            path: 'level_2_2_1',
            name: 'level_2_2_1',
            meta: {
                icon: 'md-funnel',
                title: '三级'
            },
            component: resolve => { require(['@/view/multilevel/level-2-2/level-3-1.vue'], resolve); }

        }
    ]
    },
    {
        path: 'level_2_3',
            name: 'level_2_3',
        meta: {
        icon: 'md-funnel',
            title: '二级-3'
    },
        component: resolve => { require(['@/view/multilevel/level-2-3.vue'], resolve); }

    }
]
},
{
    path: '/argu',
        name: 'argu',
    meta: {
    hideInMenu: true
},
    component: Main,
        children: [
    {
        path: 'params/:id',
        name: 'params',
        meta: {
            icon: 'md-flower',
            title: route => `{{ params }}-${route.params.id}`,
        notCache: true,
        beforeCloseName: 'before_close_normal'
    },
        component: resolve => { require(['@/view/argu-page/params.vue'], resolve); }

    },
    {
        path: 'query',
            name: 'query',
        meta: {
        icon: 'md-flower',
            title: route => `{{ query }}-${route.query.id}`,
            notCache: true
    },
        component: resolve => { require(['@/view/argu-page/query.vue'], resolve); }

    }
]
},
{
    path: '/401',
        name: 'error_401',
    meta: {
    hideInMenu: true
},
    component: resolve => { require(['@/view/error-page/401.vue'], resolve); }

},
{
    path: '/500',
        name: 'error_500',
    meta: {
    hideInMenu: true
},
    component: resolve => { require(['@/view/error-page/500.vue'], resolve); }

},
{
    path: '*',
        name: 'error_404',
    meta: {
    hideInMenu: true
},
    component: resolve => { require(['@/view/error-page/404.vue'], resolve); }

}
]

把根目录下的 resources\assets\js\app.js 文件修改为

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from '@/App.vue'
import router from '@/router'
import store from '@/store'
import iView from 'iview'
import i18n from '@/locale'
import config from '@/config'
import importDirective from '@/directive'
import installPlugin from '@/plugin'
import './index.less'
import '@/assets/icons/iconfont.css'
import TreeTable from 'tree-table-vue'
// 实际打包时应该不引入mock
/* eslint-disable */
if (process.env.NODE_ENV !== 'production') require('@/mock')

Vue.use(iView, {
    i18n: (key, value) => i18n.t(key, value)
})
Vue.use(TreeTable)
/**
 * @description 注册admin内置插件
 */
installPlugin(Vue)
/**
 * @description 生产环境关掉提示
 */
Vue.config.productionTip = false
/**
 * @description 全局注册应用配置
 */
Vue.prototype.$config = config
/**
 * 注册指令
 */
importDirective(Vue)

/* eslint-disable no-new */
new Vue({
    el: '#app',
    router,
    i18n,
    store,
    render: h => h(App)
})

还有如果你把resources\assets\js\中的原来的bootstrap.js文件删了别忘了把resources\assets\sass\app.scss中 bootsrap 注释掉

// Fonts
@import url("https://fonts.googleapis.com/css?family=Raleway:300,400,600");

// Variables
@import "variables";

// Bootstrap
//@import "~bootstrap-sass/assets/stylesheets/bootstrap";

第四步 构建展示

根目录下执行npm(cnpm) install然后执行npm(cnpm) run dev 或者 npm(cnpm) run watch应该不会再看到报错了.

在laravel 根目录下 routes/web.php 里面加个路由:

Route::get('/', function () {
    return view('admin');
});

再到 laravel 根目录下 resources\views 目录下,添加文件 admin.blade.php :

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Laravel-iview-admin</title>
    </head>
    <body>
        <div id="app"></div>
        <script type="text/javascript" src="{{asset('js/app.js')}}"></script>
    </body>
</html>

然后在laravel 根目录下 执行 php artisan serve
然后打开浏览器 输入 http://127.0.0.1 就能看到登录界面了

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,440评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,814评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,427评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,710评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,625评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,014评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,511评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,162评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,311评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,262评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,278评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,989评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,583评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,664评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,904评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,274评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,856评论 2 339

推荐阅读更多精彩内容

  • 姓名:赵彦春 公司:江苏和和新材料股份有限公司 【日精进打卡第26天】 【知~学习】 《六项精进》背诵0遍25遍...
    江苏和和赵彦春阅读 104评论 0 0
  • 美丽的乡村景色-Bexhill 海边一个风情小镇,喜欢这座桥 后院的野树和艳丽的花 村里的深潭,一泊碧水 烂漫绽放的花朵
    妮小猫鱼阅读 183评论 0 1
  • 一 一个阳光被树影摇碎的下午,我坐于市立图书馆的窗边,娜罕古树茶的悠远香味,仿佛氤氲了一个世纪之久。窗外的蓝花楹似...
    青灯影阅读 1,332评论 0 2
  • 要说当下的时代潮流,让人想到的一定是大数据时代的到来。大数据时代其实在很早就已经进入到人类的视野,并且给个人带来一...
    大数据学习02阅读 240评论 0 0
  • 今天在出差,想写这个话题是因为前天遛狗正好碰到小区的另一个单身姑娘,小马儿,她也养了一条狗,叫艾伦。我说...
    闲度阅读 185评论 0 0