Files
admin_core/src/index.js
张成 fd3c1a5563 init
2025-10-20 18:18:27 +08:00

470 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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
}