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

13 KiB
Raw Blame History

Admin Framework 正确使用方法

一、框架打包说明

Admin Framework 打包后是一个单独的 JS 文件:

  • 生产版本: dist/admin-framework.js (压缩,无 sourcemap
  • 开发版本: dist/admin-framework.dev.js (不压缩,有 sourcemap

二、在业务页面中使用框架功能

1. HTTP 请求

错误用法(不要这样写):

import http from '@/utils/admin-framework.js'  // ❌ 错误!

正确用法

// 方式一:在 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. 工具函数

正确用法

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 工具

正确用法

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. 配置信息

正确用法

export default {
  data() {
    return {
      // 从配置中获取 API 地址
      uploadUrl: this.$config.uploadUrl
    }
  },
  
  mounted() {
    console.log('系统标题:', this.$config.title)
    console.log('API 地址:', this.$config.apiUrl)
  }
}

5. Vuex Store

正确用法

import { mapGetters, mapActions } from 'vuex'

export default {
  computed: {
    // 使用框架内置的 store
    ...mapGetters('user', ['userName', 'menuList']),
    ...mapGetters('app', ['sysFormModel'])
  },
  
  methods: {
    ...mapActions('user', ['handleLogOut'])
  }
}

6. 路由跳转

正确用法

export default {
  methods: {
    goToPage() {
      // 使用 path 跳转(推荐)
      this.$router.push({ path: '/ball/games' })
      
      // 带参数跳转
      this.$router.push({ 
        path: '/ball/game_comments',
        query: { id: 123 }
      })
    }
  }
}

三、创建业务 API 模块

正确的 API 封装方式

// 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

<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>

四、完整的页面示例

<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. 不要尝试导入框架内部模块

    import http from '@/utils/admin-framework.js'  // ❌ 错误
    import tools from 'admin-framework/tools'     // ❌ 错误
    
  2. 使用 Vue 实例上的属性

    this.$http    // ✅ 正确
    this.$tools   // ✅ 正确
    this.$uiTool  // ✅ 正确
    
  3. 或使用全局对象

    window.framework.http     // ✅ 正确
    window.framework.tools    // ✅ 正确
    window.framework.uiTool   // ✅ 正确
    
  4. 路由跳转使用 path 而不是 name

    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