/** * Admin Framework * Version: 1.0.0 */ // 引入核心依赖 import Vue from 'vue' import VueRouter from 'vue-router' import Vuex from 'vuex' import ViewUI from 'view-design' // 引入样式 import 'view-design/dist/styles/iview.css' import './assets/css/animate.css' import './assets/css/base.less' import './assets/css/ivewExpand.less' import './assets/icons/iconfont.css' import uiTool from './utils/uiTool' import http from './utils/http' import * as tools from './utils/tools' // 文件下载工具 const funTool = { downloadFile: (res, fileName) => { const blob = new Blob([res.data || res]) const downloadElement = document.createElement('a') const href = window.URL.createObjectURL(blob) downloadElement.href = href downloadElement.download = fileName || new Date().getTime() + '.csv' document.body.appendChild(downloadElement) downloadElement.click() document.body.removeChild(downloadElement) window.URL.revokeObjectURL(href) } } import storeModules, { userModule, appModule } from './store' import { createBaseRoutes, setupRouterGuards } from './router' import HomePage from './views/home/index.vue' import SysLog from './views/system/sys_log.vue' import SysParamSetup from './views/system/sys_param_setup.vue' import SysRole from './views/system/sys_role.vue' import SysUser from './views/system/sys_user.vue' import SysControl from './views/system_high/sys_control.vue' import SysMenu from './views/system_high/sys_menu.vue' import SysTitle from './views/system_high/sys_title.vue' import LoginPage from './views/login/login.vue' import Page401 from './views/error-page/401.vue' import Page404 from './views/error-page/404.vue' import Page500 from './views/error-page/500.vue' import Main from './components/main' import ParentView from './components/parent-view' import Tables from './components/tables' import UploadSingle from './components/upload/Single.vue' import UploadMultiple from './components/upload/Multiple.vue' import TreeGrid from './components/treeGrid' import AsyncModal from './components/asyncModal' import InfoCard from './components/info-card' import LoadFlower from './components/load-flower' import SplitPane from './components/split-pane' import TextArea from './components/text-area' import CommonIcon from './components/common-icon' import Editor from './components/editor/index.vue' import editModal from './components/tables/editModal.vue' import fieldItem from './components/tables/fieldItem.vue' import * as systemApi from './api/system' import * as systemHighApi from './api/system_high' class AdminFramework { constructor() { this.version = '1.0.0' this.installed = false this.config = {} this.store = null this.router = null this.ViewUI = null this.tools = tools this.uiTool = uiTool this.http = http this.funTool = funTool this.storeModules = storeModules this.userModule = userModule this.appModule = appModule this.createBaseRoutes = createBaseRoutes this.setupRouterGuards = setupRouterGuards this.Main = Main this.ParentView = ParentView this.LoginPage = LoginPage this.Page401 = Page401 this.Page404 = Page404 this.Page500 = Page500 this.HomePage = HomePage this.SysLog = SysLog this.SysParamSetup = SysParamSetup this.SysRole = SysRole this.SysUser = SysUser this.SysControl = SysControl this.SysMenu = SysMenu this.SysTitle = SysTitle this.systemApi = systemApi this.systemHighApi = systemHighApi } /** * Vue plugin install method * @param {Object} Vue - Vue instance * @param {Object} options - config options */ install(Vue, options = {}) { if (this.installed) return this.installed = true const { config = {}, ViewUI, VueRouter, Vuex, createPersistedState, componentMap } = options this.config = config this.ViewUI = ViewUI if (ViewUI) { Vue.use(ViewUI) } if (VueRouter) { Vue.use(VueRouter) } if (Vuex) { Vue.use(Vuex) } Vue.prototype.$config = config Vue.prototype.$http = http Vue.prototype.$tools = tools Vue.prototype.$uiTool = uiTool Vue.prototype.$funTool = funTool Vue.prototype.$framework = this this.registerGlobalComponents(Vue) this.setupComponentMap(componentMap) if (Vuex && !this.store) { this.store = this.createStore(Vuex, {}, createPersistedState) http.init(config, this.store) } if (VueRouter && !this.router) { const mainRoute = this.getRoutes({ Main, ParentView, Page404, HomePage: this.HomePage }) this.router = this.createRouter(VueRouter, { Main, ParentView, LoginPage, Page401, Page404, Page500 }, mainRoute ? [mainRoute] : [], ViewUI) } } /** * Register global components */ registerGlobalComponents(Vue) { Vue.component('Main', Main) Vue.component('ParentView', ParentView) Vue.component('Page401', Page401) Vue.component('Page404', Page404) Vue.component('Page500', Page500) Vue.component('LoginPage', LoginPage) Vue.component('Tables', Tables) Vue.component('UploadSingle', UploadSingle) Vue.component('UploadMultiple', UploadMultiple) Vue.component('TreeGrid', TreeGrid) Vue.component('AsyncModal', AsyncModal) Vue.component('InfoCard', InfoCard) Vue.component('LoadFlower', LoadFlower) Vue.component('SplitPane', SplitPane) Vue.component('TextArea', TextArea) Vue.component('CommonIcon', CommonIcon) Vue.component('Editor', Editor) Vue.component('editModal', editModal) Vue.component('fieldItem', fieldItem) } /** * Setup component map * @param {Object} customMap - custom component map */ setupComponentMap(customMap = {}) { const components = { 'home/index': HomePage, 'system/sys_log': SysLog, 'system/sys_param_setup': SysParamSetup, 'system/sys_role': SysRole, 'system/sys_user': SysUser, 'system_high/sys_control': SysControl, 'system_high/sys_menu': SysMenu, 'system_high/sys_title': SysTitle, ...customMap } const map = {} Object.keys(components).forEach(path => { const cleanPath = path.replace(/\.vue$/, '') map[cleanPath] = components[path] map[cleanPath + '.vue'] = components[path] }) uiTool.setComponentMap(map) } /** * Add custom component map * @param {Object} customMap - custom component map * @example * AdminFramework.addComponentMap({ * 'ball/games.vue': GamesComponent, * 'order/pay_orders.vue': PayOrdersComponent * }) */ addComponentMap(customMap) { uiTool.setComponentMap(customMap) } /** * Init HTTP config * @param {Object} config - HTTP config * @param {Object} store - Vuex Store instance */ initHttp(config, store) { http.init(config, store) this.store = store } /** * Create router instance * @param {Object} Router - VueRouter class * @param {Object} components - component object * @param {Array} customRoutes - custom routes * @param {Object} ViewUI - ViewUI instance * @param {String} homeName - home page name * @returns {Object} router instance */ createRouter(Router, components = {}, customRoutes = [], ViewUI, homeName = 'home') { const { LoginPage, Page401, Page404, Page500 } = components if (!LoginPage || !Page401 || !Page404 || !Page500) { console.error('Missing required page components') return null } const baseRoutes = createBaseRoutes(LoginPage, Page401, Page404, Page500) const router = new Router({ routes: [...baseRoutes, ...customRoutes], mode: 'hash' }) if (ViewUI) { setupRouterGuards(router, ViewUI, homeName) } return router } /** * Create Store instance * @param {Object} Vuex - Vuex class * @param {Object} customModules - custom modules * @param {Object} createPersistedState - vuex-persistedstate plugin * @returns {Object} store instance */ createStore(Vuex, customModules = {}, createPersistedState) { const store = new Vuex.Store({ modules: { user: userModule, app: appModule, ...customModules }, plugins: createPersistedState ? [ createPersistedState({ storage: window.localStorage }) ] : [] }) this.store = store return store } /** * Get dynamic routes * @param {Object} components - component object * @returns {Object} main route config */ getRoutes(components = {}) { const { Main, ParentView, Page404, HomePage } = components if (!Main || !ParentView || !Page404) { console.error('Missing required layout components') return null } return uiTool.getRoutes(Main, ParentView, Page404, HomePage || this.HomePage) } /** * Register global components * @param {Object} Vue - Vue instance * @param {Object} components - component object */ registerComponents(Vue, components = {}) { Object.keys(components).forEach(name => { Vue.component(name, components[name]) }) } /** * Create app with simplified API (推荐使用) * @param {Object} config - application config * @param {String} config.title - application title * @param {String} config.apiUrl - API base URL * @param {String} config.uploadUrl - upload URL (可选,默认为 apiUrl + 'upload') * @param {Object} config.componentMap - custom component map (optional) * @param {Function} config.onReady - callback when app is ready (optional) * @returns {Object} Vue instance */ createApp(config = {}) { // Auto install framework using internal dependencies if (!this.installed) { const { componentMap, ...appConfig } = config // 如果没有提供 uploadUrl,自动从 apiUrl 推导 if (!appConfig.uploadUrl && appConfig.apiUrl) { appConfig.uploadUrl = appConfig.apiUrl + (appConfig.apiUrl.endsWith('/') ? 'upload' : '/upload') } this.install(Vue, { config: appConfig, ViewUI, VueRouter, Vuex, createPersistedState: null, componentMap: componentMap || {} }) } // Create Vue instance with auto menu/title restoration const app = new Vue({ router: this.router, store: this.store, render: h => h('router-view'), async created() { console.log('=== Admin Framework App Started ===') console.log('Framework Version:', framework.version) console.log('Config:', this.$config) // Auto restore menu and title on refresh const token = this.$store.state.user.token const authorityMenus = localStorage.getItem('authorityMenus') if (token && authorityMenus) { console.log('Restoring menu and title...') try { // Restore menu await this.$store.dispatch('user/setAuthorityMenus', { Main: framework.Main, ParentView: framework.ParentView, Page404: framework.Page404, authorityMenus: authorityMenus }) console.log('Menu restored') // Get system title await this.$store.dispatch('app/getSysTitle', { defaultTitle: this.$config.title, defaultLogo: '' }) } catch (error) { console.error('Restore failed:', error) } } else { // Not logged in, use default title console.log('Not logged in, using default title') document.title = this.$config.title } // Call user callback if provided if (config.onReady && typeof config.onReady === 'function') { config.onReady.call(this) } } }) // Expose to global for debugging if (typeof window !== 'undefined') { window.app = app window.rootVue = app window.framework = framework } return app } } const framework = new AdminFramework() // 【关键】框架实例创建后立即暴露到全局,确保在任何地方都能访问 if (typeof window !== 'undefined') { window.framework = framework } export default framework export { tools, uiTool, http, funTool, storeModules, userModule, appModule, createBaseRoutes, setupRouterGuards, HomePage, SysLog, SysParamSetup, SysRole, SysUser, SysControl, SysMenu, SysTitle, LoginPage, Page401, Page404, Page500, Main, ParentView, systemApi, systemHighApi, AdminFramework }