Files
admin_core/demo/使用说明.md
张成 ba61c9e45d 1
2025-10-09 18:17:41 +08:00

585 lines
13 KiB
Markdown
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 正确使用方法
## 一、框架打包说明
Admin Framework 打包后是一个单独的 JS 文件:
- **生产版本**: `dist/admin-framework.js` (压缩,无 sourcemap
- **开发版本**: `dist/admin-framework.dev.js` (不压缩,有 sourcemap
## 二、在业务页面中使用框架功能
### 1. HTTP 请求
**错误用法**(不要这样写):
```javascript
import http from '@/utils/admin-framework.js' // ❌ 错误!
```
**正确用法**
```javascript
// 方式一:在 Vue 组件中使用 this.$http推荐
export default {
async mounted() {
// GET 请求
const res = await this.$http.get('/api/users')
// POST 请求
const res2 = await this.$http.post('/api/users', { name: '张三' })
}
}
// 方式二:使用全局 framework.http
const res = await window.framework.http.get('/api/users')
```
### 2. 工具函数
**正确用法**
```javascript
export default {
methods: {
formatDate() {
// 使用 this.$tools
const formatted = this.$tools.formatDate(new Date(), 'yyyy-MM-dd')
// 或使用全局 framework.tools
const formatted2 = window.framework.tools.formatDate(new Date(), 'yyyy-MM-dd')
}
}
}
```
### 3. UI 工具
**正确用法**
```javascript
export default {
methods: {
showMessage() {
// 使用 this.$uiTool
this.$uiTool.success('操作成功')
this.$uiTool.error('操作失败')
// 或使用全局 framework.uiTool
window.framework.uiTool.success('操作成功')
},
async confirmDelete() {
// 确认对话框
try {
await this.$uiTool.confirm('确定删除吗?')
// 确认后的操作
this.$Message.success('已删除')
} catch {
// 取消操作
this.$Message.info('已取消')
}
}
}
}
```
### 4. 配置信息
**正确用法**
```javascript
export default {
data() {
return {
// 从配置中获取 API 地址
uploadUrl: this.$config.uploadUrl
}
},
mounted() {
console.log('系统标题:', this.$config.title)
console.log('API 地址:', this.$config.apiUrl)
}
}
```
### 5. Vuex Store
**正确用法**
```javascript
import { mapGetters, mapActions } from 'vuex'
export default {
computed: {
// 使用框架内置的 store
...mapGetters('user', ['userName', 'menuList']),
...mapGetters('app', ['sysFormModel'])
},
methods: {
...mapActions('user', ['handleLogOut'])
}
}
```
### 6. 路由跳转
**正确用法**
```javascript
export default {
methods: {
goToPage() {
// 使用 path 跳转(推荐)
this.$router.push({ path: '/ball/games' })
// 带参数跳转
this.$router.push({
path: '/ball/game_comments',
query: { id: 123 }
})
}
}
}
```
## 三、创建业务 API 模块
### 正确的 API 封装方式
```javascript
// src/api/ball/gamesServer.js
/**
* 球赛管理 API
* 注意:不需要 import http直接使用 window.framework.http
*/
class GamesServer {
/**
* 获取球赛列表
*/
async getList(params) {
return await window.framework.http.post('/games/page', params)
}
/**
* 获取球赛详情
*/
async getDetail(id) {
return await window.framework.http.get(`/games/detail/${id}`)
}
/**
* 创建球赛
*/
async create(data) {
return await window.framework.http.post('/games/create', data)
}
/**
* 更新球赛
*/
async update(id, data) {
return await window.framework.http.post(`/games/update/${id}`, data)
}
/**
* 删除球赛
*/
async delete(id) {
return await window.framework.http.post(`/games/delete/${id}`)
}
/**
* 批量删除
*/
async batchDelete(ids) {
return await window.framework.http.post('/games/batch_delete', { ids })
}
}
export default new GamesServer()
```
### 在组件中使用 API
```vue
<template>
<div>
<Tables
:columns="columns"
:data="tableData"
:loading="loading"
@on-refresh="getList"
/>
</div>
</template>
<script>
// 导入 API 模块
import gamesServer from '@/api/ball/gamesServer.js'
export default {
name: 'Games',
data() {
return {
columns: [
{ title: 'ID', key: 'id' },
{ title: '名称', key: 'name' },
{ title: '时间', key: 'time' }
],
tableData: [],
loading: false,
queryParams: {
page: 1,
size: 20
}
}
},
mounted() {
this.getList()
},
methods: {
async getList() {
this.loading = true
try {
const res = await gamesServer.getList(this.queryParams)
if (res.code === 0) {
this.tableData = res.data.list
}
} catch (error) {
this.$uiTool.error('获取数据失败')
} finally {
this.loading = false
}
},
async handleDelete(id) {
try {
await this.$uiTool.confirm('确定删除吗?')
const res = await gamesServer.delete(id)
if (res.code === 0) {
this.$uiTool.success('删除成功')
this.getList()
}
} catch (error) {
// 取消删除
}
}
}
}
</script>
```
## 四、完整的页面示例
```vue
<template>
<div class="page-container">
<Card>
<p slot="title">
<Icon type="ios-list" />
球赛管理
</p>
<!-- 搜索栏 -->
<Form inline style="margin-bottom: 16px;">
<FormItem>
<Input
v-model="queryParams.keyword"
placeholder="请输入关键词"
clearable
style="width: 200px;"
/>
</FormItem>
<FormItem>
<Button type="primary" @click="handleSearch">
<Icon type="ios-search" />
搜索
</Button>
<Button @click="handleReset" style="margin-left: 8px;">
重置
</Button>
<Button type="success" @click="handleAdd" style="margin-left: 8px;">
<Icon type="ios-add" />
新增
</Button>
</FormItem>
</Form>
<!-- 数据表格 -->
<Tables
ref="table"
:columns="columns"
:data="tableData"
:loading="loading"
:total="total"
:page-size="queryParams.size"
:current-page="queryParams.page"
@on-page-change="handlePageChange"
@on-page-size-change="handlePageSizeChange"
/>
</Card>
<!-- 编辑弹窗 -->
<Modal
v-model="modalVisible"
:title="modalTitle"
width="600"
@on-ok="handleSubmit"
@on-cancel="handleCancel"
>
<Form ref="form" :model="formData" :rules="rules" :label-width="100">
<FormItem label="名称" prop="name">
<Input v-model="formData.name" placeholder="请输入名称" />
</FormItem>
<FormItem label="时间" prop="time">
<DatePicker
v-model="formData.time"
type="datetime"
placeholder="请选择时间"
style="width: 100%;"
/>
</FormItem>
</Form>
</Modal>
</div>
</template>
<script>
import gamesServer from '@/api/ball/gamesServer.js'
export default {
name: 'Games',
data() {
return {
// 查询参数
queryParams: {
page: 1,
size: 20,
keyword: ''
},
// 表格数据
columns: [
{ title: 'ID', key: 'id', width: 80 },
{ title: '名称', key: 'name' },
{
title: '时间',
key: 'time',
render: (h, params) => {
return h('span', this.$tools.formatDate(params.row.time, 'yyyy-MM-dd HH:mm'))
}
},
{
title: '操作',
width: 200,
render: (h, params) => {
return h('div', [
h('Button', {
props: { type: 'primary', size: 'small' },
style: { marginRight: '5px' },
on: { click: () => this.handleEdit(params.row) }
}, '编辑'),
h('Button', {
props: { type: 'error', size: 'small' },
on: { click: () => this.handleDelete(params.row.id) }
}, '删除')
])
}
}
],
tableData: [],
total: 0,
loading: false,
// 弹窗相关
modalVisible: false,
modalTitle: '新增',
formData: {
name: '',
time: ''
},
rules: {
name: [
{ required: true, message: '请输入名称', trigger: 'blur' }
],
time: [
{ required: true, type: 'date', message: '请选择时间', trigger: 'change' }
]
}
}
},
mounted() {
this.getList()
},
methods: {
// 获取列表
async getList() {
this.loading = true
try {
const res = await gamesServer.getList(this.queryParams)
if (res.code === 0) {
this.tableData = res.data.list
this.total = res.data.total
} else {
this.$uiTool.error(res.message || '获取数据失败')
}
} catch (error) {
this.$uiTool.error('获取数据失败')
} finally {
this.loading = false
}
},
// 搜索
handleSearch() {
this.queryParams.page = 1
this.getList()
},
// 重置
handleReset() {
this.queryParams = {
page: 1,
size: 20,
keyword: ''
}
this.getList()
},
// 新增
handleAdd() {
this.modalTitle = '新增'
this.formData = {
name: '',
time: ''
}
this.modalVisible = true
},
// 编辑
handleEdit(row) {
this.modalTitle = '编辑'
this.formData = { ...row }
this.modalVisible = true
},
// 删除
async handleDelete(id) {
try {
await this.$uiTool.confirm('确定删除吗?')
const res = await gamesServer.delete(id)
if (res.code === 0) {
this.$uiTool.success('删除成功')
this.getList()
} else {
this.$uiTool.error(res.message || '删除失败')
}
} catch (error) {
// 取消删除
}
},
// 提交表单
handleSubmit() {
this.$refs.form.validate(async (valid) => {
if (valid) {
try {
const res = this.formData.id
? await gamesServer.update(this.formData.id, this.formData)
: await gamesServer.create(this.formData)
if (res.code === 0) {
this.$uiTool.success('操作成功')
this.modalVisible = false
this.getList()
} else {
this.$uiTool.error(res.message || '操作失败')
}
} catch (error) {
this.$uiTool.error('操作失败')
}
}
})
},
// 取消
handleCancel() {
this.$refs.form.resetFields()
},
// 分页
handlePageChange(page) {
this.queryParams.page = page
this.getList()
},
handlePageSizeChange(size) {
this.queryParams.size = size
this.queryParams.page = 1
this.getList()
}
}
}
</script>
<style scoped>
.page-container {
padding: 20px;
}
</style>
```
## 五、全局可用的对象
在任何 Vue 组件中,都可以使用以下对象:
| 对象 | 说明 | 使用示例 |
|-----|------|---------|
| `this.$http` | HTTP 请求实例 | `this.$http.get('/api/users')` |
| `this.$tools` | 工具函数集合 | `this.$tools.formatDate(new Date())` |
| `this.$uiTool` | UI 工具函数 | `this.$uiTool.success('成功')` |
| `this.$config` | 配置对象 | `this.$config.apiUrl` |
| `this.$router` | 路由实例 | `this.$router.push({ path: '/home' })` |
| `this.$store` | Vuex Store | `this.$store.state.user.userName` |
| `window.framework` | 框架实例 | `window.framework.version` |
| `window.app` | Vue 根实例 | `window.app.$router` |
## 六、注意事项
1.**不要尝试导入框架内部模块**
```javascript
import http from '@/utils/admin-framework.js' // ❌ 错误
import tools from 'admin-framework/tools' // ❌ 错误
```
2. ✅ **使用 Vue 实例上的属性**
```javascript
this.$http // ✅ 正确
this.$tools // ✅ 正确
this.$uiTool // ✅ 正确
```
3. ✅ **或使用全局对象**
```javascript
window.framework.http // ✅ 正确
window.framework.tools // ✅ 正确
window.framework.uiTool // ✅ 正确
```
4. **路由跳转使用 path 而不是 name**
```javascript
this.$router.push({ path: '/ball/games' }) // ✅ 正确
this.$router.push({ name: '球赛管理' }) // ❌ 错误name 可能不存在)
```
## 七、快速开始检查清单
- [ ] 框架已构建:`npm run build`
- [ ] Demo 依赖已安装:`cd demo && npm install`
- [ ] 组件映射表已配置:`demo/src/router/component-map.js`
- [ ] API 地址已配置:`demo/src/main.js` 中的 `config.apiUrl`
- [ ] 页面中使用 `this.$http` 而不是 `import http`
- [ ] 路由跳转使用 `path` 而不是 `name`