Service Provider
Overview
Core Function
The Service Provider (Provider) is a core feature of the MineAdmin 3.0 frontend architecture. Drawing on the design concept of backend service providers, it offers a modular service registration and management mechanism for frontend applications.
Main Features
- Global Service Registration: Register services into Vue's
globalPropertiesorprovide/injectsystem - Component Initialization: Automatically initialize and configure global components
- Plugin Configuration Management: Provide default configurations and parameter management for plugins
- Dependency Injection: Implement dependency relationship management between services
- Modular Architecture: Support organizing services by functional modules
Initialization Order
Important Note
Service providers are loaded in the early stages of application initialization, before the initialization of pinia, vue-router, vue-i18n, and other libraries. Therefore, these libraries' functionalities cannot be directly used within service providers.
Initialization Order:
- Service Provider scanning and registration ⚡
- Pinia state management initialization
- Vue Router routing initialization
- Vue I18n internationalization initialization
- Application main body startup
Architecture Design
Directory Structure
src/provider/
├── dictionary/ # Dictionary Service Provider
│ ├── index.ts # Service Provider Main File
│ └── data/ # Dictionary Data Files
├── echarts/ # Chart Service Provider
│ └── index.ts
├── plugins/ # Plugin Configuration Service Provider
│ └── index.ts
├── mine-core/ # Core Component Service Provider
│ └── index.ts
├── settings/ # System Configuration Service Provider
│ ├── index.ts
│ └── settings.config.ts
└── toolbars/ # Toolbar Service Provider
└── index.ts2
3
4
5
6
7
8
9
10
11
12
13
14
15
Auto-Discovery Mechanism
Upon system startup, all subdirectories under src/provider/ are automatically scanned. The index.ts file in each subdirectory is identified as a service provider and registered automatically.
System Built-in Services
Dictionary Service
Function Description: Provides unified data dictionary management functionality, supporting multi-language and theme color schemes.
Source Location:
- GitHub: src/provider/dictionary/
- Local:
/Users/zhuzhu/project/mineadmin/web/src/provider/dictionary/
Core Features:
- Supports multi-language internationalization identifiers
- Built-in theme color system
- Automatic type inference
- Reactive data updates
Dictionary Data Example (src/provider/dictionary/data/system-status.ts):
import type { Dictionary } from '#/global'
export default [
{
label: 'Enabled',
value: 1,
i18n: 'dictionary.system.statusEnabled',
color: 'primary'
},
{
label: 'Disabled',
value: 2,
i18n: 'dictionary.system.statusDisabled',
color: 'danger'
},
] as Dictionary[]2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Usage:
// Using dictionary data in components
import { useDictionary } from '@/composables/useDictionary'
const { getDictionary } = useDictionary()
const statusDict = getDictionary('system-status')2
3
4
5
ECharts Service
Function Description: Provides ECharts chart library initialization, configuration, and theme management capabilities.
Source Location:
- GitHub: src/provider/echarts/
- Local:
/Users/zhuzhu/project/mineadmin/web/src/provider/echarts/
Core Features:
- Import chart components on demand, reducing bundle size
- Automatic adaptation to system themes (light/dark mode)
- Global instance registration into Vue
- Responsive chart size adjustment
Usage:
// Getting ECharts instance in components
import { useGlobal } from '@/composables/useGlobal'
const { $echarts } = useGlobal()
// Initialize chart
const chartInstance = $echarts.init(chartRef.value)2
3
4
5
6
7
Reference Component: MaEcharts
Plugins Service
Function Description: Provides default configuration management for the MineAdmin plugin system, supporting unified configuration and management of plugin parameters.
Source Location:
- GitHub: src/provider/plugins/
- Local:
/Users/zhuzhu/project/mineadmin/web/src/provider/plugins/
Core Features:
- Centralized plugin configuration management
- Default parameter registration
- Configuration hot-reload support
- Plugin dependency relationship management
Reference Documentation: Plugin System
MineCore Service
Function Description: Initializes the MineAdmin core component library, providing global configuration and component registration services.
Source Location:
- GitHub: src/provider/mine-core/
- Local:
/Users/zhuzhu/project/mineadmin/web/src/provider/mine-core/
Managed Components:
ma-table- Data table componentma-search- Search form componentma-form- Form componentma-pro-table- Advanced table component
Usage:
import { useGlobal } from '@/composables/useGlobal'
const { $mineCore } = useGlobal()
const tableConfig = $mineCore.table2
3
4
Settings Service
Function Description: Provides global configuration parameter management for the frontend application, supporting configuration separation between development and production environments.
Source Location:
- GitHub: src/provider/settings/
- Local:
/Users/zhuzhu/project/mineadmin/web/src/provider/settings/
Configuration Files:
index.ts- Default configuration (do not modify directly)settings.config.ts- User custom configuration file
Configuration Example:
// settings.config.ts
export default {
// System base configuration
app: {
name: 'MineAdmin',
version: '3.0.0',
logo: '/logo.png'
},
// API configuration
api: {
baseUrl: process.env.NODE_ENV === 'development'
? 'http://localhost:9501'
: 'https://api.example.com',
timeout: 10000
},
// Theme configuration
theme: {
primaryColor: '#409eff',
darkMode: 'auto'
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Development Guide
Creating a Basic Service Provider
Step 1: Create the service directory
mkdir src/provider/my-serviceStep 2: Create the service provider file (src/provider/my-service/index.ts)
import type { App } from 'vue'
import type { ProviderService } from '#/global'
// Define service interface
interface MyService {
version: string
getName: () => string
setConfig: (config: any) => void
}
const provider: ProviderService.Provider<MyService> = {
name: 'myService',
init() {
console.log('MyService is initializing...')
},
setProvider(app: App) {
const service: MyService = {
version: '1.0.0',
getName: () => 'My Custom Service',
setConfig: (config) => {
console.log('Configuration updated:', config)
}
}
// Register to global properties
app.config.globalProperties.$myService = service
// Or use provide/inject
app.provide('myService', service)
},
getProvider() {
return useGlobal().$myService
}
}
export default provider2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Creating an Advanced Service Provider with Configuration
import type { App } from 'vue'
import type { ProviderService } from '#/global'
// Service configuration interface
interface ServiceConfig {
apiUrl: string
timeout: number
retries: number
}
// Service instance interface
interface AdvancedService {
config: ServiceConfig
request: (url: string) => Promise<any>
updateConfig: (newConfig: Partial<ServiceConfig>) => void
}
const provider: ProviderService.Provider<AdvancedService> = {
name: 'advancedService',
config: {
enabled: true,
priority: 10,
dependencies: ['settings'] // Depends on the settings service
},
async init() {
// Asynchronous initialization logic
await this.loadExternalLibrary()
},
setProvider(app: App) {
const defaultConfig: ServiceConfig = {
apiUrl: '/api/v1',
timeout: 5000,
retries: 3
}
const service: AdvancedService = {
config: { ...defaultConfig },
async request(url: string) {
// Implement request logic
return fetch(`${this.config.apiUrl}${url}`, {
timeout: this.config.timeout
})
},
updateConfig(newConfig) {
Object.assign(this.config, newConfig)
}
}
app.config.globalProperties.$advancedService = service
},
getProvider() {
return useGlobal().$advancedService
},
async loadExternalLibrary() {
// Logic for loading external dependency libraries
}
}
export default provider2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
Using a Service Provider
In a Vue Component:
<template>
<div>
<h3>{{ serviceName }}</h3>
<p>Version: {{ version }}</p>
</div>
</template>
<script setup lang="ts">
import { useGlobal } from '@/composables/useGlobal'
const { $myService } = useGlobal()
const serviceName = $myService.getName()
const version = $myService.version
// Update configuration
$myService.setConfig({ theme: 'dark' })
</script>2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
In a Composable:
// composables/useMyService.ts
import { useGlobal } from '@/composables/useGlobal'
export function useMyService() {
const { $myService } = useGlobal()
const updateServiceConfig = (config: any) => {
$myService.setConfig(config)
}
return {
service: $myService,
updateServiceConfig
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
Best Practices
1. Naming Conventions
- Service provider names use camelCase format
- Directory names use kebab-case format
- Global properties use the
$prefix
2. Type Safety
// Extending global property types
declare module '@vue/runtime-core' {
interface ComponentCustomProperties {
$myService: MyService
}
}2
3
4
5
6
3. Dependency Management
const provider: ProviderService.Provider = {
name: 'dependentService',
config: {
dependencies: ['settings', 'dictionary']
},
// ...other configurations
}2
3
4
5
6
7
4. Error Handling
setProvider(app: App) {
try {
// Service initialization logic
app.config.globalProperties.$service = createService()
} catch (error) {
console.error(`Service ${this.name} initialization failed:`, error)
// Provide fallback solution
app.config.globalProperties.$service = createFallbackService()
}
}2
3
4
5
6
7
8
9
10
Service Management
Disabling a Service Provider
const provider: ProviderService.Provider = {
name: 'optionalService',
config: {
enabled: false // Disable this service
},
// ...other configurations
}2
3
4
5
6
7
Removing a Service Provider
Simply delete the corresponding service provider directory:
rm -rf src/provider/unwanted-serviceDebugging a Service Provider
const provider: ProviderService.Provider = {
name: 'debugService',
init() {
if (process.env.NODE_ENV === 'development') {
console.log(`[Provider] ${this.name} initialization complete`)
}
},
setProvider(app: App) {
// Add debug information in development environment
if (process.env.NODE_ENV === 'development') {
window.__DEBUG_PROVIDERS__ = window.__DEBUG_PROVIDERS__ || {}
window.__DEBUG_PROVIDERS__[this.name] = this
}
// Normal service registration logic
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Common Issues
| Issue | Cause | Solution |
|---|---|---|
| Service not registered successfully | Missing index.ts file or required interfaces not implemented | Check file existence and interface implementation |
| Cannot use Pinia | Service provider initialization occurs before Pinia | Move Pinia-related logic to components or Composables |
| Service dependency conflict | Circular dependency or incorrect dependency order | Redesign dependency relationships or use an event bus |
| Type inference error | Global property types not correctly extended | Add TypeScript module declaration |
| Hot reload not working | Service caching issue | Restart the development server |
Related Resources
Source Code Reference:
- GitHub Repository: MineAdmin Source Code
- Service Provider Directory: web/src/provider/
- Local Source Code:
/Users/zhuzhu/project/mineadmin/web/src/provider/
Related Documentation: