1
This commit is contained in:
@@ -45,7 +45,7 @@ admin-framework/
|
||||
│ │ ├── home/ # 主页
|
||||
│ │ ├── login/ # 登录页
|
||||
│ │ ├── system/ # 系统管理页面
|
||||
│ │ └── system_high/ # 高级系统页面
|
||||
│ │ └── system/ # 高级系统页面
|
||||
│ └── index.js # 框架入口
|
||||
├── dist/ # 打包产物
|
||||
│ └── admin-framework.js # 框架打包文件(3.6 MB,内置所有依赖)
|
||||
|
||||
@@ -43,7 +43,7 @@ npm run dev
|
||||
|
||||
✅ **主页组件**(欢迎页面,自动显示系统标题)
|
||||
✅ **系统管理页面**(sys 开头的所有页面和功能)
|
||||
✅ **系统 API**(system 和 system_high 所有 API)
|
||||
✅ **系统 API**(system 和 system 所有 API)
|
||||
✅ **全局组件**(Tables、Editor、Upload 等)
|
||||
✅ **布局组件**(Main、ParentView)
|
||||
✅ **登录和错误页面**(Login、401、404、500)
|
||||
@@ -139,8 +139,8 @@ import AdminFramework from 'admin-framework'
|
||||
|
||||
✅ **已包含**:
|
||||
- **主页组件**(HomePage - 欢迎页面,显示系统标题)
|
||||
- 所有系统页面(system、system_high)
|
||||
- 所有系统 API(system、system_high)
|
||||
- 所有系统页面(system、system)
|
||||
- 所有系统 API(system、system)
|
||||
- 所有全局组件(Tables、Editor、Upload 等)
|
||||
- 布局组件(Main、ParentView)
|
||||
- 登录和错误页面
|
||||
@@ -605,7 +605,7 @@ import {
|
||||
} from 'admin-framework'
|
||||
```
|
||||
|
||||
#### system_high 目录页面
|
||||
#### system 目录页面
|
||||
```javascript
|
||||
import {
|
||||
SysControl, // 控制器管理
|
||||
@@ -635,7 +635,7 @@ const routes = [
|
||||
component: SysRole
|
||||
},
|
||||
{
|
||||
path: '/system_high/menu',
|
||||
path: '/system/menu',
|
||||
name: 'sys_menu',
|
||||
component: SysMenu
|
||||
}
|
||||
@@ -662,7 +662,7 @@ const users = await userServer.getList({ page: 1 })
|
||||
const roles = await roleServer.getList()
|
||||
```
|
||||
|
||||
#### system_high API
|
||||
#### system API
|
||||
```javascript
|
||||
import { systemHighApi } from 'admin-framework'
|
||||
|
||||
@@ -1229,9 +1229,9 @@ AdminFramework.addComponentMap({
|
||||
- ✅ `system/sys_role.vue` - 角色管理
|
||||
- ✅ `system/sys_log.vue` - 日志管理
|
||||
- ✅ `system/sys_param_setup.vue` - 参数设置
|
||||
- ✅ `system_high/sys_menu.vue` - 菜单管理
|
||||
- ✅ `system_high/sys_control.vue` - 控制器管理
|
||||
- ✅ `system_high/sys_title.vue` - 系统标题设置
|
||||
- ✅ `system/sys_menu.vue` - 菜单管理
|
||||
- ✅ `system/sys_control.vue` - 控制器管理
|
||||
- ✅ `system/sys_title.vue` - 系统标题设置
|
||||
|
||||
#### 配置技巧
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
|
||||
class ShpProfitServer {
|
||||
async report(param) {
|
||||
let res = await window.framework.http.post('/shpProfit/report', param)
|
||||
return res
|
||||
}
|
||||
|
||||
async list(param) {
|
||||
let res = await window.framework.http.post('/shpProfit/list', param)
|
||||
return res
|
||||
}
|
||||
}
|
||||
|
||||
const shpProfitServer = new ShpProfitServer()
|
||||
export default shpProfitServer
|
||||
@@ -41,7 +41,7 @@
|
||||
<script>
|
||||
|
||||
|
||||
import menuServer from '@/api/system_high/menuServer.js'
|
||||
import menuServer from '@/api/system/menuServer.js'
|
||||
import gameParticipantsServer from '@/api/ball/game_participants_server.js'
|
||||
export default {
|
||||
data() {
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
<script>
|
||||
|
||||
|
||||
import menuServer from '@/api/system_high/menuServer.js'
|
||||
import menuServer from '@/api/system/menuServer.js'
|
||||
import gamesServer from '@/api/ball/games_server.js'
|
||||
export default {
|
||||
data() {
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
<script>
|
||||
|
||||
|
||||
import menuServer from '@/api/system_high/menuServer.js'
|
||||
import menuServer from '@/api/system/menuServer.js'
|
||||
import venuesServer from '@/api/ball/venues_server.js'
|
||||
export default {
|
||||
data() {
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
<script>
|
||||
|
||||
|
||||
import menuServer from '@/api/system_high/menuServer.js'
|
||||
import menuServer from '@/api/system/menuServer.js'
|
||||
import wch_usersServer from '@/api/ball/wch_users_server.js'
|
||||
export default {
|
||||
data() {
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<script>
|
||||
|
||||
|
||||
import menuServer from '@/api/system_high/menuServer.js'
|
||||
import menuServer from '@/api/system/menuServer.js'
|
||||
import walletTransactionsServer from '@/api/ball/wallet_transactions_server.js'
|
||||
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<script>
|
||||
|
||||
|
||||
import menuServer from '@/api/system_high/menuServer.js'
|
||||
import menuServer from '@/api/system/menuServer.js'
|
||||
import wch_professionsServer from '@/api/system/wch_professions_server.js'
|
||||
export default {
|
||||
data() {
|
||||
|
||||
@@ -4,8 +4,6 @@ export { default as fileServe } from './fileServe'
|
||||
export { default as plaAccountServer } from './pla_account_server'
|
||||
export { default as rolePermissionServer } from './rolePermissionServer'
|
||||
export { default as roleServer } from './roleServer'
|
||||
export { default as shpProfitServer } from './shpProfitServer'
|
||||
export { default as specificationServer } from './specificationServer'
|
||||
export { default as sysAddressServer } from './sysAddressServer'
|
||||
export { default as sysModuleServer } from './sysModuleServer'
|
||||
export { default as sysLogServe } from './sys_log_serve'
|
||||
@@ -13,3 +11,13 @@ export { default as systemTypeServer } from './systemType_server'
|
||||
export { default as tableServer } from './tableServer'
|
||||
export { default as userServer } from './userServer'
|
||||
|
||||
export { default as formFieldServer } from './formFieldServer'
|
||||
export { default as formServer } from './formServer'
|
||||
export { default as menuServer } from './menuServer'
|
||||
export { default as modelFieldServer } from './modelFieldServer'
|
||||
export { default as modelServer } from './modelServer'
|
||||
export { default as paramSetupServer } from './paramSetupServer'
|
||||
export { default as sysControlTypeServer } from './sysControlTypeServer'
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import http from '@/utils/http'
|
||||
class ShpProfitServer {
|
||||
async report(param) {
|
||||
let res = await http.post('/shpProfit/report', param)
|
||||
return res
|
||||
}
|
||||
|
||||
async list(param) {
|
||||
let res = await http.post('/shpProfit/list', param)
|
||||
return res
|
||||
}
|
||||
}
|
||||
|
||||
const shpProfitServer = new ShpProfitServer()
|
||||
export default shpProfitServer
|
||||
@@ -1,10 +0,0 @@
|
||||
// 高级系统 API 统一导出
|
||||
|
||||
export { default as formFieldServer } from './formFieldServer'
|
||||
export { default as formServer } from './formServer'
|
||||
export { default as menuServer } from './menuServer'
|
||||
export { default as modelFieldServer } from './modelFieldServer'
|
||||
export { default as modelServer } from './modelServer'
|
||||
export { default as paramSetupServer } from './paramSetupServer'
|
||||
export { default as sysControlTypeServer } from './sysControlTypeServer'
|
||||
|
||||
21
src/components/date-picker/index.vue
Normal file
21
src/components/date-picker/index.vue
Normal file
@@ -0,0 +1,21 @@
|
||||
<template>
|
||||
<DatePicker
|
||||
:value="value"
|
||||
v-bind="$attrs"
|
||||
@on-change="handleChange"
|
||||
:style="'width:100%;'"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'DatePicker',
|
||||
props: ['value'],
|
||||
methods: {
|
||||
handleChange(date) {
|
||||
this.$emit('input', date)
|
||||
this.$emit('change', date)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
84
src/components/index.js
Normal file
84
src/components/index.js
Normal file
@@ -0,0 +1,84 @@
|
||||
import Main from './main'
|
||||
import ParentView from './parent-view'
|
||||
|
||||
// 导入页面组件
|
||||
import pages from '../views/index'
|
||||
const {
|
||||
LoginPage,
|
||||
Page401,
|
||||
Page404,
|
||||
Page500
|
||||
} = pages
|
||||
|
||||
import Tables from './tables'
|
||||
import UploadSingle from './upload/Single.vue'
|
||||
import UploadMultiple from './upload/Multiple.vue'
|
||||
import TreeGrid from './treeGrid'
|
||||
import AsyncModal from './asyncModal'
|
||||
import InfoCard from './info-card'
|
||||
import LoadFlower from './load-flower'
|
||||
import SplitPane from './split-pane'
|
||||
import TextArea from './text-area'
|
||||
import CommonIcon from './common-icon'
|
||||
import Editor from './editor/index.vue'
|
||||
import editModal from './tables/editModal.vue'
|
||||
import fieldItem from './tables/fieldItem.vue'
|
||||
import FieldRenderer from './tables/fieldRenderer.vue'
|
||||
|
||||
|
||||
// 注册全局组件的方法
|
||||
export function 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)
|
||||
Vue.component('FieldRenderer', FieldRenderer)
|
||||
}
|
||||
|
||||
// 注册自定义组件的方法
|
||||
export function registerComponents(Vue, components = {}) {
|
||||
Object.keys(components).forEach(name => {
|
||||
Vue.component(name, components[name])
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
Main,
|
||||
ParentView,
|
||||
Tables,
|
||||
UploadSingle,
|
||||
UploadMultiple,
|
||||
TreeGrid,
|
||||
AsyncModal,
|
||||
InfoCard,
|
||||
LoadFlower,
|
||||
SplitPane,
|
||||
TextArea,
|
||||
CommonIcon,
|
||||
Editor,
|
||||
editModal,
|
||||
fieldItem,
|
||||
FieldRenderer,
|
||||
registerGlobalComponents,
|
||||
registerComponents
|
||||
}
|
||||
|
||||
|
||||
20
src/components/switch/index.vue
Normal file
20
src/components/switch/index.vue
Normal file
@@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<Switch
|
||||
:value="value"
|
||||
v-bind="$attrs"
|
||||
@on-change="handleChange"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Switch',
|
||||
props: ['value'],
|
||||
methods: {
|
||||
handleChange(checked) {
|
||||
this.$emit('input', checked)
|
||||
this.$emit('change', checked)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -13,38 +13,14 @@
|
||||
<div :class="col.inLine?'inline-row':'line-row'" :key="col.name" v-if="col.key&&!col.display">
|
||||
<FormItem :label="col.title" :prop="col.key" :rules="curRules[col.key]" :style=" col.rowStyle">
|
||||
<Row>
|
||||
|
||||
<Select class="text-left" filterable v-if="col.com==='Select'" v-model='row[col.key]' v-bind="col" :disabled="getDisabled(col)">
|
||||
<Option :value="item.key" :key="item.key" v-for="item in col.source">{{item.value }}</Option>
|
||||
</Select>
|
||||
|
||||
<RadioGroup v-else-if="col.com==='Radio'" v-model="row[col.key]" v-bind="col" :disabled="getDisabled(col)">
|
||||
<Radio :label="item.key" :key="item.key" v-for="item in col.source">
|
||||
{{item.value}}
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
|
||||
<AutoComplete v-else-if="col.com==='SelectIcon'" icon="ios-search" v-model="row[col.key]" v-bind="col" :disabled="getDisabled(col)">
|
||||
<Option v-for="(icon,index) in icons" :value="icon" :key="index">
|
||||
<Icon size="20" :type="icon" />
|
||||
{{ icon }}
|
||||
</Option>
|
||||
</AutoComplete>
|
||||
|
||||
<UploadSingle v-else-if="col.com==='upload_Img'" v-model="row[col.key]" v-bind="col" :disabled="getDisabled(col)">
|
||||
|
||||
</UploadSingle>
|
||||
|
||||
<TextArea v-else-if="col.com==='TextArea'" v-model="row[col.key]" v-bind="col" :disabled="getDisabled(col)">
|
||||
|
||||
</TextArea>
|
||||
|
||||
<templateRender v-else-if="col.editRender" :value="row[col.key]" :render='col.editRender'></templateRender>
|
||||
|
||||
<Input v-else-if="!col.com" v-model="row[col.key]" v-bind="col" style="width:100%;" :disabled="getDisabled(col)" />
|
||||
|
||||
<component v-else v-bind:is="col.com" v-model="row[col.key]" v-bind="col" :disabled="getDisabled(col)"></component>
|
||||
|
||||
<!-- 使用专门的字段渲染组件 -->
|
||||
<FieldRenderer
|
||||
:col="col"
|
||||
:value="row[col.key]"
|
||||
:disabled="getDisabled(col)"
|
||||
@input="handleFieldInput(col.key, $event)"
|
||||
@change="handleFieldChange(col.key, $event)"
|
||||
/>
|
||||
</Row>
|
||||
</FormItem>
|
||||
</div>
|
||||
@@ -64,21 +40,12 @@
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import dayjs from 'dayjs'
|
||||
import templateRender from './templateRender'
|
||||
|
||||
// 导入框架中的图标配置
|
||||
let icons = []
|
||||
try {
|
||||
icons = require('../../config/icons.json') || []
|
||||
} catch (e) {
|
||||
console.warn('未找到图标配置文件,图标选择功能将不可用', e)
|
||||
icons = []
|
||||
}
|
||||
import FieldRenderer from './fieldRenderer'
|
||||
|
||||
export default {
|
||||
props: ['columns', 'width'],
|
||||
components: {
|
||||
templateRender
|
||||
FieldRenderer
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -87,7 +54,6 @@ export default {
|
||||
isRefresh: true,
|
||||
isEdit: false,
|
||||
isOPen: false,
|
||||
icons: [],
|
||||
row: {},
|
||||
callback: null
|
||||
}
|
||||
@@ -123,6 +89,16 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 处理字段输入事件
|
||||
handleFieldInput(key, value) {
|
||||
this.$set(this.row, key, value)
|
||||
},
|
||||
|
||||
// 处理字段变化事件
|
||||
handleFieldChange(key, value) {
|
||||
this.$set(this.row, key, value)
|
||||
},
|
||||
|
||||
// 判断字段是否禁用
|
||||
getDisabled(col) {
|
||||
// 如果是编辑模式且字段设置了disabled,则禁用
|
||||
@@ -192,12 +168,6 @@ export default {
|
||||
this.isOPen = false
|
||||
},
|
||||
async init(row, isgl) {
|
||||
// 安全处理图标数据
|
||||
if (Array.isArray(icons)) {
|
||||
this.icons = icons.map((item) => item.trim ? item.trim() : item)
|
||||
} else {
|
||||
this.icons = []
|
||||
}
|
||||
row = row || {}
|
||||
let rules = this.curRules
|
||||
if (isgl) {
|
||||
|
||||
196
src/components/tables/fieldRenderer.vue
Normal file
196
src/components/tables/fieldRenderer.vue
Normal file
@@ -0,0 +1,196 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 使用组件映射表来简化条件渲染 -->
|
||||
<component
|
||||
:is="getComponentName(col.com)"
|
||||
v-model="value"
|
||||
v-bind="getComponentProps(col)"
|
||||
:disabled="disabled"
|
||||
:class="getComponentClass(col.com)"
|
||||
:style="getComponentStyle(col.com)"
|
||||
@input="handleInput"
|
||||
@change="handleChange"
|
||||
>
|
||||
<!-- Select 组件的选项 -->
|
||||
<template v-if="col.com === 'Select'">
|
||||
<Option
|
||||
:value="item.key"
|
||||
:key="item.key"
|
||||
v-for="item in col.source"
|
||||
>
|
||||
{{ item.value }}
|
||||
</Option>
|
||||
</template>
|
||||
|
||||
<!-- Radio 组件的选项 -->
|
||||
<template v-else-if="col.com === 'Radio'">
|
||||
<Radio
|
||||
:label="item.key"
|
||||
:key="item.key"
|
||||
v-for="item in col.source"
|
||||
>
|
||||
{{ item.value }}
|
||||
</Radio>
|
||||
</template>
|
||||
|
||||
<!-- SelectIcon 组件的选项 -->
|
||||
<template v-else-if="col.com === 'SelectIcon'">
|
||||
<Option
|
||||
v-for="(icon, index) in icons"
|
||||
:value="icon"
|
||||
:key="index"
|
||||
>
|
||||
<Icon size="20" :type="icon" />
|
||||
{{ icon }}
|
||||
</Option>
|
||||
</template>
|
||||
|
||||
<!-- 自定义渲染 -->
|
||||
<template v-else-if="col.editRender">
|
||||
<templateRender
|
||||
:value="value"
|
||||
:render="col.editRender"
|
||||
/>
|
||||
</template>
|
||||
</component>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import templateRender from './templateRender'
|
||||
|
||||
// 导入框架中的图标配置
|
||||
let icons = []
|
||||
try {
|
||||
icons = require('../../config/icons.json') || []
|
||||
} catch (e) {
|
||||
console.warn('未找到图标配置文件,图标选择功能将不可用', e)
|
||||
icons = []
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'FieldRenderer',
|
||||
components: {
|
||||
templateRender
|
||||
},
|
||||
props: {
|
||||
col: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
value: {
|
||||
type: [String, Number, Boolean, Array, Object, Date],
|
||||
default: ''
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
icons: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 安全处理图标数据
|
||||
if (Array.isArray(icons)) {
|
||||
this.icons = icons.map((item) => item.trim ? item.trim() : item)
|
||||
} else {
|
||||
this.icons = []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 组件映射表 - 统一管理组件类型
|
||||
getComponentName(componentType) {
|
||||
const componentMap = {
|
||||
'Select': 'Select',
|
||||
'Radio': 'RadioGroup',
|
||||
'SelectIcon': 'AutoComplete',
|
||||
'UploadSingle': 'UploadSingle',
|
||||
'TextArea': 'TextArea',
|
||||
'Input': 'Input',
|
||||
'DatePicker': 'DatePicker',
|
||||
'TimePicker': 'TimePicker',
|
||||
'Switch': 'Switch',
|
||||
'Checkbox': 'Checkbox',
|
||||
'Slider': 'Slider',
|
||||
'Rate': 'Rate',
|
||||
'Cascader': 'Cascader',
|
||||
'TreeSelect': 'TreeSelect',
|
||||
'Transfer': 'Transfer',
|
||||
'Upload': 'Upload',
|
||||
'ColorPicker': 'ColorPicker',
|
||||
'InputNumber': 'InputNumber'
|
||||
}
|
||||
|
||||
// 如果没有指定组件类型,默认为 Input
|
||||
return componentMap[componentType] || 'Input'
|
||||
},
|
||||
|
||||
// 获取组件属性
|
||||
getComponentProps(col) {
|
||||
const baseProps = { ...col }
|
||||
|
||||
// 移除不需要传递给组件的属性
|
||||
delete baseProps.com
|
||||
delete baseProps.source
|
||||
delete baseProps.editRender
|
||||
delete baseProps.inLine
|
||||
delete baseProps.display
|
||||
delete baseProps.disabled
|
||||
delete baseProps.disabledOnAdd
|
||||
delete baseProps.required
|
||||
delete baseProps.data_type
|
||||
delete baseProps.type
|
||||
delete baseProps.rowStyle
|
||||
|
||||
// 根据组件类型添加特定属性
|
||||
if (col.com === 'Select') {
|
||||
baseProps.filterable = true
|
||||
baseProps.clearable = true
|
||||
} else if (col.com === 'SelectIcon') {
|
||||
baseProps.icon = 'ios-search'
|
||||
} else if (col.com === 'TextArea') {
|
||||
baseProps.rows = 4
|
||||
baseProps.placeholder = '请输入内容'
|
||||
} else if (col.com === 'Input' || !col.com) {
|
||||
baseProps.placeholder = col.placeholder || '请输入' + col.title
|
||||
baseProps.clearable = true
|
||||
}
|
||||
|
||||
return baseProps
|
||||
},
|
||||
|
||||
// 获取组件样式类
|
||||
getComponentClass(componentType) {
|
||||
const classMap = {
|
||||
'Select': 'text-left',
|
||||
'SelectIcon': 'text-left'
|
||||
}
|
||||
return classMap[componentType] || ''
|
||||
},
|
||||
|
||||
// 获取组件样式
|
||||
getComponentStyle(componentType) {
|
||||
const styleMap = {
|
||||
'Input': 'width:100%;',
|
||||
'TextArea': 'width:100%;',
|
||||
'DatePicker': 'width:100%;',
|
||||
'TimePicker': 'width:100%;'
|
||||
}
|
||||
return styleMap[componentType] || ''
|
||||
},
|
||||
|
||||
// 处理输入事件
|
||||
handleInput(value) {
|
||||
this.$emit('input', value)
|
||||
},
|
||||
|
||||
// 处理变化事件
|
||||
handleChange(value) {
|
||||
this.$emit('change', value)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -75,7 +75,7 @@ export const defaultMenus = [
|
||||
{
|
||||
id: 120,
|
||||
name: '高级管理',
|
||||
path: '/system_high',
|
||||
path: '/system',
|
||||
component: '',
|
||||
parent_id: 0,
|
||||
type: '菜单',
|
||||
@@ -86,8 +86,8 @@ export const defaultMenus = [
|
||||
{
|
||||
id: 122,
|
||||
name: '菜单管理',
|
||||
path: '/system_high/menu',
|
||||
component: 'system_high/sys_menu',
|
||||
path: '/system/menu',
|
||||
component: 'system/sys_menu',
|
||||
parent_id: 120,
|
||||
type: '页面',
|
||||
is_show_menu: 1,
|
||||
@@ -97,8 +97,8 @@ export const defaultMenus = [
|
||||
{
|
||||
id: 123,
|
||||
name: '控制管理',
|
||||
path: '/system_high/control',
|
||||
component: 'system_high/sys_control',
|
||||
path: '/system/control',
|
||||
component: 'system/sys_control',
|
||||
parent_id: 120,
|
||||
type: '页面',
|
||||
is_show_menu: 1,
|
||||
@@ -108,8 +108,8 @@ export const defaultMenus = [
|
||||
{
|
||||
id: 124,
|
||||
name: '系统标题',
|
||||
path: '/system_high/title',
|
||||
component: 'system_high/sys_title',
|
||||
path: '/system/title',
|
||||
component: 'system/sys_title',
|
||||
parent_id: 120,
|
||||
type: '页面',
|
||||
is_show_menu: 1,
|
||||
|
||||
324
src/index.js
324
src/index.js
@@ -20,197 +20,64 @@ import uiTool from './utils/uiTool'
|
||||
import http from './utils/http'
|
||||
import * as tools from './utils/tools'
|
||||
|
||||
import storeModules, { userModule, appModule } from './store'
|
||||
import storeModules, { createStore } from './store'
|
||||
|
||||
import { createBaseRoutes, setupRouterGuards } from './router'
|
||||
import { createBaseRoutes, setupRouterGuards, createRouter, getRoutes } 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 components from './components/index'
|
||||
import pages from './views/index'
|
||||
|
||||
// 导入页面组件
|
||||
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'
|
||||
// 通过模块化方式导入页面组件
|
||||
const {
|
||||
HomePage,
|
||||
LoginPage,
|
||||
Page401,
|
||||
Page404,
|
||||
Page500,
|
||||
SysLog,
|
||||
SysParamSetup,
|
||||
SysRole,
|
||||
SysUser,
|
||||
SysControl,
|
||||
SysMenu,
|
||||
SysTitle,
|
||||
setupComponentMap
|
||||
} = pages
|
||||
|
||||
// 导入组件相关功能
|
||||
import components, { registerGlobalComponents, registerComponents } from './components/index'
|
||||
|
||||
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.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.pages = pages
|
||||
this.components = components
|
||||
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.$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
|
||||
@@ -222,7 +89,7 @@ class AdminFramework {
|
||||
* })
|
||||
*/
|
||||
addComponentMap(customMap) {
|
||||
uiTool.setComponentMap(customMap)
|
||||
setupComponentMap(customMap, uiTool)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -235,88 +102,9 @@ class AdminFramework {
|
||||
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 (推荐使用)
|
||||
@@ -329,23 +117,50 @@ class AdminFramework {
|
||||
* @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')
|
||||
if (!config.uploadUrl && config.apiUrl) {
|
||||
config.uploadUrl = config.apiUrl + (config.apiUrl.endsWith('/') ? 'upload' : '/upload')
|
||||
}
|
||||
|
||||
this.install(Vue, {
|
||||
config: appConfig,
|
||||
ViewUI,
|
||||
VueRouter,
|
||||
Vuex,
|
||||
createPersistedState: null,
|
||||
componentMap: componentMap || {}
|
||||
})
|
||||
// 设置配置
|
||||
this.config = config
|
||||
|
||||
// 初始化 Vue 插件
|
||||
Vue.use(ViewUI)
|
||||
Vue.use(VueRouter)
|
||||
Vue.use(Vuex)
|
||||
|
||||
// 设置全局属性
|
||||
Vue.prototype.$config = config
|
||||
Vue.prototype.$http = http
|
||||
Vue.prototype.$tools = tools
|
||||
Vue.prototype.$uiTool = uiTool
|
||||
Vue.prototype.$framework = this
|
||||
|
||||
// 注册全局组件
|
||||
registerGlobalComponents(Vue)
|
||||
|
||||
// 设置组件映射
|
||||
setupComponentMap(config.componentMap || {}, uiTool)
|
||||
|
||||
// 创建 Store
|
||||
if (!this.store) {
|
||||
this.store = createStore(Vuex, {}, null)
|
||||
http.init(config, this.store)
|
||||
}
|
||||
|
||||
// 创建 Router
|
||||
if (!this.router) {
|
||||
const mainRoute = getRoutes({ Main, ParentView, Page404, HomePage: this.HomePage }, uiTool)
|
||||
|
||||
this.router = createRouter(VueRouter, {
|
||||
Main,
|
||||
ParentView,
|
||||
LoginPage,
|
||||
Page401,
|
||||
Page404,
|
||||
Page500
|
||||
}, mainRoute ? [mainRoute] : [], ViewUI)
|
||||
}
|
||||
|
||||
// Create Vue instance with auto menu/title restoration
|
||||
@@ -421,9 +236,6 @@ export {
|
||||
http,
|
||||
|
||||
storeModules,
|
||||
userModule,
|
||||
appModule,
|
||||
|
||||
createBaseRoutes,
|
||||
setupRouterGuards,
|
||||
|
||||
|
||||
@@ -89,8 +89,45 @@ export const setupRouterGuards = (router, ViewUI, homeName = 'home') => {
|
||||
return router
|
||||
}
|
||||
|
||||
export default {
|
||||
createBaseRoutes,
|
||||
setupRouterGuards
|
||||
// 获取动态路由的方法
|
||||
export function getRoutes(components = {}, uiTool) {
|
||||
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)
|
||||
}
|
||||
|
||||
// 创建路由实例的方法
|
||||
export function createRouter(Router, components = {}, customRoutes = [], ViewUI) {
|
||||
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, 'home')
|
||||
}
|
||||
|
||||
return router
|
||||
}
|
||||
|
||||
export default {
|
||||
createBaseRoutes,
|
||||
setupRouterGuards,
|
||||
createRouter,
|
||||
getRoutes
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getBreadCrumbList, getHomeRoute } from '../utils/tools'
|
||||
import paramSetupServer from '../api/system_high/paramSetupServer'
|
||||
import paramSetupServer from '../api/system/paramSetupServer'
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
|
||||
@@ -1,10 +1,27 @@
|
||||
import userModule from './user'
|
||||
import appModule from './app'
|
||||
|
||||
export { userModule, appModule }
|
||||
// 创建 Store 实例的方法
|
||||
export function createStore(Vuex, customModules = {}, createPersistedState) {
|
||||
const store = new Vuex.Store({
|
||||
modules: {
|
||||
user: appModule,
|
||||
app: userModule,
|
||||
...customModules
|
||||
},
|
||||
plugins: createPersistedState ? [
|
||||
createPersistedState({
|
||||
storage: window.localStorage
|
||||
})
|
||||
] : []
|
||||
})
|
||||
|
||||
return store
|
||||
}
|
||||
|
||||
export default {
|
||||
user: userModule,
|
||||
app: appModule
|
||||
app: appModule,
|
||||
createStore
|
||||
}
|
||||
|
||||
|
||||
61
src/views/index.js
Normal file
61
src/views/index.js
Normal file
@@ -0,0 +1,61 @@
|
||||
import HomePage from './home/index.vue'
|
||||
|
||||
import SysLog from './system/sys_log.vue'
|
||||
import SysParamSetup from './system/sys_param_setup.vue'
|
||||
import SysRole from './system/sys_role.vue'
|
||||
import SysUser from './system/sys_user.vue'
|
||||
|
||||
import SysControl from './system/sys_control.vue'
|
||||
import SysMenu from './system/sys_menu.vue'
|
||||
import SysTitle from './system/sys_title.vue'
|
||||
|
||||
import LoginPage from './login/login.vue'
|
||||
|
||||
import Page401 from './error-page/401.vue'
|
||||
import Page404 from './error-page/404.vue'
|
||||
import Page500 from './error-page/500.vue'
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 设置组件映射的方法
|
||||
export function setupComponentMap(customMap = {}, uiTool) {
|
||||
const componentMap = {
|
||||
'home/index': HomePage,
|
||||
'system/sys_log': SysLog,
|
||||
'system/sys_param_setup': SysParamSetup,
|
||||
'system/sys_role': SysRole,
|
||||
'system/sys_user': SysUser,
|
||||
'system/sys_control': SysControl,
|
||||
'system/sys_menu': SysMenu,
|
||||
'system/sys_title': SysTitle,
|
||||
...customMap
|
||||
}
|
||||
|
||||
const map = {}
|
||||
Object.keys(componentMap).forEach(path => {
|
||||
const cleanPath = path.replace(/\.vue$/, '')
|
||||
map[cleanPath] = componentMap[path]
|
||||
map[cleanPath + '.vue'] = componentMap[path]
|
||||
})
|
||||
|
||||
uiTool.setComponentMap(map)
|
||||
}
|
||||
|
||||
export default {
|
||||
HomePage,
|
||||
SysLog,
|
||||
SysParamSetup,
|
||||
SysRole,
|
||||
SysUser,
|
||||
SysControl,
|
||||
SysMenu,
|
||||
SysTitle,
|
||||
LoginPage,
|
||||
Page401,
|
||||
Page404,
|
||||
Page500,
|
||||
setupComponentMap
|
||||
}
|
||||
@@ -21,8 +21,8 @@
|
||||
<script>
|
||||
import tools from '@/utils/tools'
|
||||
import uiTool from '@/utils/uiTool'
|
||||
import modelServer from '@/api/system_high/modelServer.js'
|
||||
import sysControlTypeServer from '@/api/system_high/sysControlTypeServer.js'
|
||||
import modelServer from '@/api/system/modelServer.js'
|
||||
import sysControlTypeServer from '@/api/system/sysControlTypeServer.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
<script>
|
||||
import uiTool from '@/utils/uiTool'
|
||||
import menuServer from '@/api/system_high/menuServer'
|
||||
import menuServer from '@/api/system/menuServer'
|
||||
|
||||
export default {
|
||||
name: 'tree_table_page',
|
||||
@@ -15,7 +15,7 @@
|
||||
</template>
|
||||
<script>
|
||||
import uiTool from '@/utils/uiTool'
|
||||
import paramSetupServer from '@/api/system_high/paramSetupServer'
|
||||
import paramSetupServer from '@/api/system/paramSetupServer'
|
||||
|
||||
export default {
|
||||
name: 'tables_page',
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<script>
|
||||
import uiTool from '@/utils/uiTool'
|
||||
import roleServer from '@/api/system/roleServer'
|
||||
import menuServer from '@/api/system_high/menuServer'
|
||||
import menuServer from '@/api/system/menuServer'
|
||||
|
||||
export default {
|
||||
name: 'tables_page',
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import paramSetupServer from '@/api/system_high/paramSetupServer'
|
||||
import paramSetupServer from '@/api/system/paramSetupServer'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -1,33 +0,0 @@
|
||||
<template>
|
||||
<Select @on-change="changeInput" :value="value">
|
||||
<Option v-for="item in source" :value="item.key" :key="item.key">{{ item.value }}</Option>
|
||||
</Select>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['value'],
|
||||
data() {
|
||||
return {
|
||||
source: [
|
||||
{ key: 'STRING', value: '字符串-STRING' },
|
||||
{ key: 'TEXT', value: '富文本-TEXT' },
|
||||
{ key: 'JSON', value: 'JSON' },
|
||||
{ key: 'INTEGER', value: '整型-INTEGER' },
|
||||
{ key: 'BOOLEAN', value: '布尔值-BOOLEAN' },
|
||||
{ key: 'DOUBLE', value: '双精度浮点数-DOUBLE' },
|
||||
{ key: 'DATE', value: '日期-DATE' },
|
||||
{ key: 'ENUM', value: '枚举-ENUM' }
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeInput(val) {
|
||||
this.$emit('input', val)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -1,251 +0,0 @@
|
||||
<template>
|
||||
<Card class="pa5" dis-hover v-if="value">
|
||||
<Select :value="value.comType" @on-change="changeComType">
|
||||
<Option v-for="item in sourceCom" :value="item.key" :key="item.key">{{ item.value }}</Option>
|
||||
</Select>
|
||||
<div style="width:100%;" v-if="value.comType==='Select'|| value.comType==='Radio'|| value.comType==='Checkbox'">
|
||||
|
||||
<div class="select-form ">
|
||||
<div class="select-item">
|
||||
<label class="label">
|
||||
<span class="red"> *</span>
|
||||
<span class="ml5"> 数据源类型</span>
|
||||
</label>
|
||||
<div class="item-com">
|
||||
<RadioGroup :value="value.interfaceType" @on-change="changeInterfaceType">
|
||||
<Radio :label="item.key" :key="item.key" v-for="item in sourceType">
|
||||
<span>{{ item.value }}</span>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div v-if="value.interfaceType==='接口'">
|
||||
<div class="select-item">
|
||||
<label class="label">
|
||||
<span class="red"> *</span>
|
||||
<span class="ml5">选择model</span>
|
||||
</label>
|
||||
<div class="item-com">
|
||||
|
||||
<Select :value="value.modelKey" placeholder="请选择model" @on-change="changeModel">
|
||||
<Option v-for="item in modelRows" :value="item.key" :key="item.key">{{ item.value }}</Option>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="select-item">
|
||||
<label class="label">
|
||||
<span class="red"> *</span>
|
||||
<span class="ml5">key(映射)</span>
|
||||
</label>
|
||||
<div class="item-com">
|
||||
<Select :value="value.modelMap.key" placeholder="请选择字段" @on-change="changeKey">
|
||||
<Option v-for="item in fieldRows" :value="item.key" :key="item.key">{{ item.value }}</Option>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="select-item">
|
||||
<label class="label">
|
||||
<span class="red"> *</span>
|
||||
<span class="ml5">value(映射)</span>
|
||||
</label>
|
||||
<div class="item-com">
|
||||
<Select :value="value.modelMap.value" placeholder="请选择字段" @on-change="changeValue">
|
||||
<Option v-for="item in fieldRows" :value="item.key" :key="item.key">{{ item.value }}</Option>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<div class="bd tag-box">
|
||||
<Tag v-for="item in value.localData" :key="item.key" :name="item.name" closable @on-close="handleClose(item.key)">{{ item.key+':'+item.value }}</Tag>
|
||||
</div>
|
||||
|
||||
<div class="mt5">
|
||||
<Input :max="10" :min="1" v-model="localVal.key" type="number" size="small" placeholder="输入key" style="width: 60px"></Input>
|
||||
<Input class="ml5" v-model="localVal.value" size="small" placeholder="输入value" style="width: 80px" />
|
||||
<Button class="ml10" size="small" @click="handleAdd">添加数据</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else></div>
|
||||
</Card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import modelServer from '@/api/system_high/modelServer'
|
||||
import modelFieldServer from '@/api/system_high/modelFieldServer'
|
||||
|
||||
export default {
|
||||
props: ['value'],
|
||||
data() {
|
||||
return {
|
||||
localData: [],
|
||||
localVal: { key: 0, value: '' },
|
||||
sourceCom: [
|
||||
{ key: 'Input', value: '文本输入框-Input', default_option: { data_type: 'STRING', data_length: 50 } },
|
||||
{ key: 'TextArea', value: '文本区域框-TextArea', default_option: { data_type: 'STRING', data_length: 500 } },
|
||||
{ key: 'InputNumber', value: '数字输入框-InputNumber', default_option: { data_type: 'INTEGER', data_length: 11, defaultValue: 0 } },
|
||||
{ key: 'i-switch', value: '开关-Switch', default_option: { data_type: 'BOOLEAN', data_length: 2 } },
|
||||
{ key: 'Radio', value: '单选框-Radio', default_option: { data_type: 'INTEGER', data_length: 2 } },
|
||||
{ key: 'Select', value: '下拉选择器-Select', default_option: { data_type: 'STRING', data_length: 50 } },
|
||||
{ key: 'Checkbox', value: '多选框-Checkbox', default_option: { data_type: 'INTEGER', data_length: 11 } },
|
||||
{ key: 'DatePicker', value: '日期选择器-DatePicker', default_option: { data_type: 'DATE', data_length: 50 } },
|
||||
{ key: 'Editor', value: '富文本-Editor', default_option: { data_type: 'TEXT', data_length: 0 } },
|
||||
{ key: 'UploadSingle', value: '图片框-UploadSingle', default_option: { data_type: 'STRING', data_length: 1000 } }
|
||||
],
|
||||
sourceType: [
|
||||
{ key: '接口', value: '接口' },
|
||||
{ key: '本地数据', value: '本地数据' }
|
||||
],
|
||||
modelRows: [],
|
||||
fieldRows: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
comType() {
|
||||
return this.value.comType
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.init()
|
||||
},
|
||||
methods: {
|
||||
async init() {
|
||||
await this.getModel()
|
||||
await this.getField()
|
||||
},
|
||||
handleClose(key) {
|
||||
const index = this.localData.findIndex((p) => p.key === key)
|
||||
this.localData.splice(index, 1)
|
||||
let { comType, localData } = this
|
||||
let newVal = Object.assign({}, this.value, { comType, localData })
|
||||
this.$emit('input', newVal)
|
||||
},
|
||||
handleAdd() {
|
||||
if ((this.localVal.key || this.localVal.key === 0) && this.localVal.value) {
|
||||
const index = this.localData.findIndex((p) => p.key === this.localVal.key)
|
||||
if (index === -1) {
|
||||
this.localData.push(this.localVal)
|
||||
let { comType, localData } = this
|
||||
let newVal = Object.assign({}, this.value, { comType, localData })
|
||||
this.$emit('input', newVal)
|
||||
this.localVal = { key: this.localData.length, value: '' }
|
||||
} else {
|
||||
this.$Message.error('不能添加重复项')
|
||||
}
|
||||
} else {
|
||||
this.$Message.error('请输入值')
|
||||
}
|
||||
},
|
||||
|
||||
async getField() {
|
||||
this.$nextTick(async () => {
|
||||
if (this.value) {
|
||||
let key = this.value.modelKey
|
||||
if (key) {
|
||||
let res = await modelFieldServer.allByKey({ key })
|
||||
let data = res.data.map((p) => {
|
||||
let { key, name } = p
|
||||
return { key, value: key }
|
||||
})
|
||||
|
||||
this.fieldRows = [{ key: 'id', value: 'id' }, ...data]
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
async getModel() {
|
||||
let res = await modelServer.all()
|
||||
this.modelRows = res.data.map((p) => {
|
||||
let { key, name } = p
|
||||
return { key, value: key + '-' + name }
|
||||
})
|
||||
},
|
||||
|
||||
changeComType(val) {
|
||||
let remoteKeys = ['Select', 'Radio', 'Checkbox']
|
||||
let newRow = { comType: val }
|
||||
if (remoteKeys.indexOf(val) > -1) {
|
||||
newRow = Object.assign(newRow, { interfaceType: '接口', modelKey: '', modelMap: { key: 'id', value: 'name' } })
|
||||
}
|
||||
|
||||
this.$emit('input', newRow)
|
||||
let com = this.sourceCom.find((p) => p.key === val)
|
||||
if (com && com.default_option) {
|
||||
this.$emit('changeOption', com.default_option)
|
||||
}
|
||||
},
|
||||
changeModel(val) {
|
||||
let newRow = Object.assign({ modelMap: { key: '', value: '' } }, this.value, { modelKey: val })
|
||||
this.$emit('input', newRow)
|
||||
this.getField()
|
||||
},
|
||||
|
||||
changeInterfaceType(val) {
|
||||
if (val === '接口') {
|
||||
let newRow = Object.assign({ modelMap: { key: '', value: '' } }, this.value, { interfaceType: val })
|
||||
this.$emit('input', newRow)
|
||||
} else {
|
||||
let newRow = Object.assign({ modelMap: { key: '', value: '' } }, this.value, { interfaceType: val })
|
||||
console.log(newRow, val)
|
||||
this.$emit('input', newRow)
|
||||
}
|
||||
},
|
||||
changeKey(val) {
|
||||
let newRow = Object.assign({ modelMap: { key: '', value: '' } }, this.value)
|
||||
newRow.modelMap.key = val
|
||||
this.$emit('input', newRow)
|
||||
},
|
||||
changeValue(val) {
|
||||
let newRow = Object.assign({ modelMap: { key: '', value: '' } }, this.value)
|
||||
newRow.modelMap.value = val
|
||||
this.$emit('input', newRow)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.select-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 10px;
|
||||
.select-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin: 10px 0px;
|
||||
|
||||
.label {
|
||||
display: inline-flex;
|
||||
width: 100px;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
.item-com {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tag-box {
|
||||
line-height: 30px;
|
||||
width: 100%;
|
||||
height: 70px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.bd {
|
||||
border: solid 1px #ccc;
|
||||
}
|
||||
</style>
|
||||
68
使用说明.md
68
使用说明.md
@@ -5,11 +5,13 @@
|
||||
## 📦 框架特性
|
||||
|
||||
### ✨ 核心功能
|
||||
- ✅ **简化的 API** - 只需调用 `createApp()` 即可完成所有初始化
|
||||
- ✅ **模块化设计** - 组件、路由、状态管理等功能按模块组织
|
||||
- ✅ **完整的系统管理页面** - 用户、角色、菜单、日志等管理
|
||||
- ✅ **登录和权限管理** - 完整的登录流程和权限控制
|
||||
- ✅ **动态路由管理** - 基于权限菜单的动态路由生成
|
||||
- ✅ **Vuex 状态管理** - 用户、应用状态管理
|
||||
- ✅ **全局组件库** - Tables、Editor、Upload、TreeGrid 等
|
||||
- ✅ **全局组件库** - Tables、Editor、Upload、TreeGrid、FieldRenderer 等
|
||||
- ✅ **工具库** - HTTP、日期、Token、Cookie 等工具
|
||||
- ✅ **内置样式** - base.less、animate.css、iconfont 等
|
||||
- ✅ **响应式布局** - 支持移动端适配
|
||||
@@ -62,6 +64,34 @@ npm run build
|
||||
# 3. 产物在 dist/admin-framework.js
|
||||
```
|
||||
|
||||
## 🎯 极简使用方式
|
||||
|
||||
### 只需 3 步即可完成集成!
|
||||
|
||||
#### 1. 引入框架
|
||||
```javascript
|
||||
import AdminFramework from './admin-framework.js'
|
||||
```
|
||||
|
||||
#### 2. 创建应用
|
||||
```javascript
|
||||
const app = AdminFramework.createApp({
|
||||
title: '我的管理系统',
|
||||
apiUrl: 'http://localhost:9098/admin_api/',
|
||||
componentMap: {
|
||||
'business/product': ProductComponent,
|
||||
'business/order': OrderComponent
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
#### 3. 挂载应用
|
||||
```javascript
|
||||
app.$mount('#app')
|
||||
```
|
||||
|
||||
**就这么简单!** 框架会自动完成所有初始化工作。
|
||||
|
||||
## 📖 完整使用指南
|
||||
|
||||
### 1. 项目结构准备
|
||||
@@ -112,7 +142,35 @@ module.exports = {
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 创建 main.js
|
||||
### 4. 创建 main.js(新版本 - 推荐)
|
||||
|
||||
```javascript
|
||||
import AdminFramework from './libs/admin-framework.js'
|
||||
|
||||
// 导入业务组件(根据权限菜单接口的 component 字段)
|
||||
import GamesComponent from './views/ball/games.vue'
|
||||
import PayOrdersComponent from './views/order/pay_orders.vue'
|
||||
|
||||
// 🎉 只需一行代码!框架自动完成所有初始化
|
||||
const app = AdminFramework.createApp({
|
||||
title: '我的管理系统',
|
||||
apiUrl: 'http://localhost:9098/admin_api/',
|
||||
componentMap: {
|
||||
'ball/games': GamesComponent,
|
||||
'order/pay_orders': PayOrdersComponent
|
||||
// 添加更多业务组件...
|
||||
},
|
||||
onReady() {
|
||||
console.log('应用已启动!')
|
||||
// 应用启动完成后的回调
|
||||
}
|
||||
})
|
||||
|
||||
// 挂载应用
|
||||
app.$mount('#app')
|
||||
```
|
||||
|
||||
### 4.1 传统方式(兼容旧版本)
|
||||
|
||||
```javascript
|
||||
import Vue from 'vue'
|
||||
@@ -381,9 +439,9 @@ Vue.use(AdminFramework, {
|
||||
- ✅ `system/sys_role` - 角色管理
|
||||
- ✅ `system/sys_log` - 日志管理
|
||||
- ✅ `system/sys_param_setup` - 参数设置
|
||||
- ✅ `system_high/sys_menu` - 菜单管理
|
||||
- ✅ `system_high/sys_control` - 控制器管理
|
||||
- ✅ `system_high/sys_title` - 系统标题设置
|
||||
- ✅ `system/sys_menu` - 菜单管理
|
||||
- ✅ `system/sys_control` - 控制器管理
|
||||
- ✅ `system/sys_title` - 系统标题设置
|
||||
|
||||
## 🌐 全局访问
|
||||
|
||||
|
||||
6
快速开始.md
6
快速开始.md
@@ -128,9 +128,9 @@ app.$mount('#app')
|
||||
- ✅ 角色管理 (`/system/role`)
|
||||
- ✅ 日志管理 (`/system/log`)
|
||||
- ✅ 参数设置 (`/system/param`)
|
||||
- ✅ 菜单管理 (`/system_high/menu`)
|
||||
- ✅ 权限控制 (`/system_high/control`)
|
||||
- ✅ 标题设置 (`/system_high/title`)
|
||||
- ✅ 菜单管理 (`/system/menu`)
|
||||
- ✅ 权限控制 (`/system/control`)
|
||||
- ✅ 标题设置 (`/system/title`)
|
||||
|
||||
### 3. 全局组件
|
||||
- ✅ `<Tables>` - 增强型表格
|
||||
|
||||
Reference in New Issue
Block a user