lin-cms后台管理TO-B的图书业务流程解析

前端 2019-11-13T17:08:16 浏览:82

TO-B 意为对待商家,也就是管理者。

在lin-cms这台后台管理系统中,其架构基于 RESTful 架构的API设计原则,实现了前端后端完全分离的状态,分工明确便于维护。

在这里只对后台管理系统UI逻辑做简要概述,这里以框架中自带的图书管理业务为例。

在后台管理系统的实现上也将系统的维护分为model层和view层。

在view层中:图书book分为,Book.vue、BookAdd.vue、BookEdit.vue、BookList.vue。

1.Book.vue

<template>
  <div>
    <!-- 页面过度动画 -->
    <transition name="fade-transform" mode="out-in">
      <!-- 主要用于保留组件状态或避免重新渲染 -->
      <!-- <keep-alive> -->
        <!-- 渲染路径匹配到的视图组件 -->
        <router-view></router-view>
      <!-- </keep-alive> -->
    </transition>
  </div>
</template>

2. BookAdd.vue

<template>
  <div class="container">
    <div class="title">新建图书</div>
    <lin-1px></lin-1px>
    <div class="wrap">
      <el-row>
        <el-col :lg="16" :md="20" :sm="24" :xs="24">
          <el-form :model="form" status-icon ref="form" label-width="100px">
            <el-form-item label="书名" prop="title">
              <el-input v-model="form.title" placeholder="请填写书名"></el-input>
            </el-form-item>
            <el-form-item label="作者" prop="author">
              <el-input v-model="form.author" placeholder="请填写作者"></el-input>
            </el-form-item>
            <el-form-item label="封面" prop="image">
              <el-input v-model="form.image" placeholder="请填写封面地址"></el-input>
            </el-form-item>
            <el-form-item label="简介" prop="summary">
              <el-input
                type="textarea"
                :autosize="{ minRows: 4, maxRows: 8}"
                placeholder="请输入简介"
                v-model="form.summary">
              </el-input>
            </el-form-item>
            <el-form-item class="submit">
              <el-button type="primary" @click="submitForm('form')">保 存</el-button>
              <el-button @click="resetForm('form')">重 置</el-button>
            </el-form-item>
          </el-form>
        </el-col>
      </el-row>
    </div>

  </div>
</template>

<script>
import book from '@/lin/models/book'
import Scroll from '@/base/scroll/scroll'
export default {
  data() {
    return {
      form: {
        title: '',
        author: '',
        summary: '',
        image: '',
      },
    }
  },
  components: {
    Scroll,
  },
  methods: {
    // 提交表单
    async submitForm(formName) {
      const res = await book.addBook(this.form)
      if (res.error_code === 0) {
        this.$message.success(`${res.msg}`)
        this.resetForm(formName)
      }
    },
    // 重置表单
    resetForm(formName) {
      this.$refs[formName].resetFields()
    },
  },
}
</script>

3.BookEdit.vue

图片编辑组件作为图书列表组件的子组件,这里用了父子组件的通信模式 props down, events up ,实现父子组件之间的交互

<template>
  <div class="container">
    <div class="title">
      <span>修改图书</span>
      <span class="back" @click="back"><i class="iconfont icon-fanhui"></i> 返回</span>
    </div>
    <lin-1px></lin-1px>
    <div class="wrap">
      <el-row>
        <el-col :lg="16" :md="20" :sm="24" :xs="24">
          <el-form :model="form" status-icon ref="form" label-width="100px">
            <el-form-item label="书名" prop="title">
              <el-input v-model="form.title" placeholder="请填写书名"></el-input>
            </el-form-item>
            <el-form-item label="作者" prop="author">
              <el-input v-model="form.author" placeholder="请填写作者"></el-input>
            </el-form-item>
            <el-form-item label="封面" prop="image">
              <el-input v-model="form.image" placeholder="请填写封面地址"></el-input>
            </el-form-item>
            <el-form-item label="简介" prop="summary">
              <el-input
                type="textarea"
                :rows="4"
                placeholder="请输入简介"
                v-model="form.summary">
              </el-input>
            </el-form-item>
            <el-form-item class="submit">
              <el-button type="primary" @click="submitForm('form')">保 存</el-button>
              <el-button @click="resetForm('form')">重 置</el-button>
            </el-form-item>
          </el-form>
        </el-col>
      </el-row>
    </div>
  </div>
</template>
<script>
import Book from '@/lin/models/book'
export default {
  // 父组件通过 props 向下传递数据给子组件,子组件这里告知父组件可以传递的字段
  props: {
    editBookID: {
      type: Number,
    },
  },
  data() {
    return {
      form: {
        title: '',
        author: '',
        summary: '',
        image: '',
      },
    }
  },
  async mounted() {
    this.form = await Book.getBook(this.editBookID)
  },
  methods: {
    // 提交表单
    async submitForm() {
      const res = await Book.editBook(this.editBookID, this.form)
      if (res.error_code === 0) {
        this.$message.success(`${res.msg}`)
        this.$emit('editClose')
      }
    },
    // 重置表单
    resetForm(formName) {
      this.$refs[formName].resetFields()
    },
    // 返回列表页,子组件通过this.$emit执行 events 给父组件发送消息
    back() {
      this.$emit('editClose')
    },
  },
}
</script>

4.BookList.vue

<template>
  <div>
    <!-- 列表页面 -->
    <div class="container" v-if="!showEdit">
      <div class="header">
        <div class="title">图书列表</div>
      </div>
      <!-- 表格 -->
      <lin-table :tableColumn="tableColumn"
                :tableData="tableData"
                :operate="operate"
                @handleEdit="handleEdit"
                @handleDelete="handleDelete"
                v-loading="loading">
      </lin-table>
    </div>
    <!-- 编辑页面 通过子组件props的editBookID,父组件将值传递给子组件,注册自定义事件editClose,届时子组件可以通过触发该事件改变父组件的状态-->
    <book-edit
      v-else
      @editClose="editClose"
      :editBookID="editBookID"
    ></book-edit>
    <!-- 分页 -->
    <div class="pagination">
      <el-pagination @current-change="handleCurrentChange"
                     :background="true"
                     :page-size="pageCount"
                     :current-page="currentPage"
                     layout="prev, pager, next, jumper"
                     :total="total_nums">
      </el-pagination>
    </div>
  </div>
</template>

<script>
import Book from '@/lin/models/book'
import LinTable from '@/base/table/lin-table'
//子组件BookEdit.vue
import BookEdit from './BookEdit'

export default {
  components: {
    LinTable,
    BookEdit,
  },
  data() {
    return {
      tableColumn: [{ prop: 'id', label: 'ID' }, { prop: 'title', label: '书名' }, { prop: 'author', label: '作者' }],
      tableData: [],
      operate: [],
      showEdit: false,
      editBookID: 1,
      currentPage: 1,
      pageCount: 7,
      total_nums: 0,
      loading: false,
    }
  },
  async created() {
    this.loading = true
    this.getBooks()
    this.operate = [{ name: '编辑', func: 'handleEdit', type: 'edit' }, { name: '删除', func: 'handleDelete', type: 'del' }]
    this.loading = false
  },
  methods: {
    async getBooks() {
      const currentPage = this.currentPage - 1
      const res = await Book.getBooks({ page: currentPage, pageCount: this.pageCount })
      this.total_nums = res.total
      this.tableData = res.items
    },
    // 分页
    async handleCurrentChange(val) {
      this.currentPage = val
      this.loading = true
      await this.getBooks()
      this.loading = false
    },
    handleEdit(val) {
      this.showEdit = true
      this.editBookID = val.row[val.index].id
    },
    handleDelete(val) {
      this.$confirm('此操作将永久删除该图书, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }).then(async () => {
        const res = await Book.delectBook(val.row[val.index].id)
        if (res.error_code === 0) {
          this.getBooks()
          this.$message({
            type: 'success',
            message: `${res.msg}`,
          })
        }
      })
    },
    editClose() {
      this.showEdit = false
    },
  },
}
</script>

在这几个文件中,都引用了

import Book from '@/lin/models/book'

5.book.js

/* eslint-disable class-methods-use-this */
import { get, post, put, _delete } from '../utils/http'

export default class Book {
  constructor(lPage = 0, lCount = 7) {
    this.lPage = lPage
    this.lCount = lCount
  }
  async increseLpage() {
    this.lPage += 1
  }
  async decreseGpage() {
    this.lPage -= 1
    if (this.lPage < 0) {
      this.lPage = 0
    }
  }
  // 按条件查询图书
  static async getBooks({ page = this.lPage, pageCount = this.lCount }) {
    const res = await get('v1/book/', {
      page,
      pageCount,
    })
    return res
  }
  // 添加图书
  static async addBook(info) {
    const res = await post('v1/book/', info)
    return res
  }
  // 获取图书
  static async getBook(id) {
    const res = await get(`v1/book/${id}`)
    return res
  }
  // 编辑图书
  static async editBook(id, info) {
    const res = await put(`v1/book/${id}`, info)
    return res
  }
  // 删除图书
  static async delectBook(id) {
    const res = await _delete(`v1/book/${id}`)
    return res
  }
}

book.js这个文件中,都是与数据直接交互的业务逻辑,也就是model层,实现了分层管理代码。