New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

admate

Package Overview
Dependencies
Maintainers
1
Versions
67
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

admate

Mate of admin management system

  • 0.3.0
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
17
increased by6.25%
Maintainers
1
Weekly downloads
 
Created
Source

Admate / 管理后台伴侣

Admate 的目标是以快速简洁的方式开发管理后台页面

并在此基础上确保灵活可配 避免过度封装(opinionated)


Installation


NPM

系统集成

参考管理后台脚手架 admin-cli

局部引入

  1. 安装依赖
yarn add admate kikimore element-form-verify
  1. 初始化
// @/utils/admate.js

import Vue from 'vue'
import { mapGetters } from 'vuex'
import request from '@/utils/request'

/**
 * mixins
 */
import { CancelToken } from 'axios'
import { getMixins } from 'admate'
let mixins = getMixins({
  getListProxy (motive) {
    this.$_admate_getList()
    if (['c', 'u', 'd', 'updateStatus', 'enable', 'disable'].includes(motive)) {
      this.$message.success('操作成功')
    }
  },
  CancelToken
})
mixins = {
  ...mixins,
  // mixins补充
  computed: {
    ...mixins.computed,
    ...mapGetters([
      'dict',
    ]),
  }
}
export { mixins }

/**
 * apiGenerator
 */
import { getApiGenerator } from 'admate'
const apiGenerator = getApiGenerator({ request })
export { apiGenerator }

/**
 * axiosShortcut
 */
import { getAxiosShortcut } from 'admate'
const axiosShortcut = getAxiosShortcut({ request })
for (let k in axiosShortcut) {
  Vue.prototype[k] = axiosShortcut[k]
}

/**
 * filters
 */
import { filters } from 'admate'
Object.keys(filters).map(filter => {
  const key = `$${filter}`
  Vue.filter(key, filters[filter])
  Object.defineProperty(Vue.prototype, key, {
    value: filters[filter]
  })
})

/**
 * 注册指令表单校验
 */
import ElementFormVerify from 'element-form-verify'
Vue.use(ElementFormVerify)

/**
 * [AuthButton] show属性
 */
import router from '../router'
import store from '../store'
export const showAuthButton = name => {
  let authButtons = store.getters?.authButtons?.[router.currentRoute.path] || []

  // 分解连缀的权限词, 例如: ['启用/停用'] 拆分成: ['启用','停用']
  authButtons.forEach((item, index) => {
    const splitArr = item.split('/')
    if (splitArr.length > 1) {
      authButtons.splice(index, 1)
      splitArr.forEach(key => {
        authButtons.push(key)
      })
    }
  })
  return authButtons.includes(name)
}

::: warning
showAuthButton 是判断权限按钮是否显示的逻辑 根据你的系统需求自行修改 :::

  1. 页面使用
<!-- xxx.vue -->

<template>
  <!-- AuthButton示例 -->
  <AuthButton name="新增" :show="showAuthButton"/>
</template>

<script>
import { apiGenerator, mixins, showAuthButton } from '@/utils/admate.js'
import 'kikimore/dist/style.css'
import { FormDialog, AuthButton, Selector, Pagination, FormItemTip, Tag, Swal } from 'kikimore'
const { success, info, warning, error, confirm } = Swal

export default {
  mixins: [mixins],
  components: { FormDialog, AuthButton, Selector, Pagination, FormItemTip, Tag },
  data () {
    return {
      $_admate_api: apiGenerator('xxx'),
      showAuthButton,
    }
  },
}
</script>

搭配代码生成器使用

:one: 在 VSCode 插件市场搜索 yapi2code 并安装

:two: 打开命令面板(F1) 输入 yapi2code 运行


mixins

页面公共逻辑混入

::: danger
mixins属于vue2.0时代遗留物 其思想已淘汰 仅作为升级vue3.0之前的临时方案 :::

获取实例:调用 getMixins()

mixins 集成了一些什么功能?

  • 获取列表、增删查改、状态启停用等管理后台页面标配

  • 关闭表单对话框时 自动将表单绑定的数据恢复至初始状态(不是直接清空)

  • 离开页面时 如果存在未完成的请求 自动终止该请求调用

  • 删除当前分页最后一条记录时 自动切换至上一页(如果当前不在第一页)

  • 节流控制表格筛选的接口触发频率

    ...

::: warning
mixins 中所有的变量均按照 Vue官方风格指南 以$_admate_开头命名 避免和你的代码冲突 :::

初始化

// main.js

import Vue from 'vue'
import { CancelToken } from 'axios'
import { getMixins } from 'admate'

let mixins = getMixins({
  // 全局配置

  //  接口参数、返回值格式定制化
  props: {
    // [列表查询接口] 页码字段名
    pageNo: 'pageNo',

    // [列表查询接口] 页容量字段名
    pageSize: 'pageSize',

    // [列表查询接口] 返回值中列表字段所在位置
    // 考虑到分页与不分页的返回格式可能是不同的 所以支持传入一个数组 数组会被遍历 直到找到为止
    list: ['data', 'data.records'],

    // [列表查询接口] 返回值中总记录数字段所在位置
    total: 'data.total',

    // [单条查询接口] 返回值中数据所在位置
    r: 'data'
  },

  // 获取列表代理 详见生命周期-查询列表时
  getListProxy (motive, res) {
    this.$_admate_getList()
    if (['c', 'u', 'd', 'updateStatus', 'enable', 'disable'].includes(motive)) {
      this.$message.success('操作成功')
    }
  },

  // 用于切换页面时中断请求
  CancelToken,

})

// 对mixins进行补充 如加入computed
mixins = {
  ...mixins,
  computed: {
    ...mixins.computed,
    ...mapGetters([
      'dict',
    ]),
  }
}

export { mixins }

局部配置

import { mixins } from '@/main'

export default {
  mixins: [mixins],
  data () {
    return {
      $_admate_props: {}, // 注意双下划线结尾
    }
  },
  methods: {
    // 注意双下划线结尾
    $_admate_getListProxy (motive, res) {
      this.$_admate_getList()
      if (['c', 'u', 'd', 'updateStatus', 'enable', 'disable'].includes(motive)) {
        this.$message.success('操作成功')
      }
    }
  }
}

生命周期

查询单条时
/**
 * @return {Promise} 查询单条接口调用
 */
this.$_admate_retrieve()

$_admate_retrieve 是针对 FormDialog 组件的 retrieve 属性定制的方法

<!-- 示例:修改接口返回值 -->

<template>
  <FormDialog :retrieve="retrieve"/>
</template>

<script>
export default {
  methods: {
    retrieve () {
      return this.$_admate_retrieve()
      ?.then( // 新增时 retrieve__返回为空 需要判空
        /**
         * @param {object} rowData - 单条数据
         */
        rowData => {
          this.$_admate_row.data.status = 1
        }
      )
    }
  }
}
</script>
<!-- 在查询单条记录之前做点什么 -->

<template>
  <FormDialog :retrieve="retrieve"/>
</template>

<script>
export default {
  methods: {
    retrieve () {
      // retrieve方法在FormDialog打开时会被调用 包括新增时
      // retrieve__帮你排除了新增的情况 但当该方法被你覆写时 需要自行排除
      if ('c' !== this.$_admate_row.status) {
        // 在查询单条记录之前做点什么
      }

      return this.$_admate_retrieve()
    }
  }
}
</script>

提交表单时
/**
 * @param {function|object|FormData} paramHandler - 提交之前的钩子或指定表单参数
 * @return {Promise} 提交表单接口调用
 */
this.$_admate_submit(paramHandler)

$_admate_submit 是针对 FormDialog 组件的 submit 属性定制的方法

<!-- 示例:修改提交参数 -->

<template>
  <FormDialog :submit="submit"/>
</template>

<script>
export default {
  methods: {
    submit () {
      // 在提交之前做点什么(无论表单校验是否通过)...
      return this.$_admate_submit(
        () => {
          // 在提交之前做点什么(表单校验通过后)...
          if ('c' === this.$_admate_row.status) {
            this.$_admate_row.data.status = 1
          }
        })
      .then(() => {
        // 在提交成功后做点什么...
      })
    }
  }
}
</script>
<!-- 示例:指定提交参数 -->

<template>
  <FormDialog :submit="submit"/>
</template>

<script>
export default {
  methods: {
    submit () {
      return this.$_admate_submit({
        ...this.$_admate_row.data,
        status: 1
      })
    }
  }
}
</script>
<!-- 示例:额外的校验 自行控制表单的关闭 -->

<template>
  <FormDialog :submit="submit"/>
</template>

<script>
export default {
  methods: {
    submit () {
      let valid = false
      if (valid) {
        return this.$_admate_submit()
      } else {
        this.$Swal.warning('校验失败')
        return {
          close: false
        }
      }
    }
  }
}
</script>

查询列表时

$_admate_getList :在首次进入页面、列表查询参数改变、单条增删查改后会被调用

$_admate_getListProxy:你可以在 methods 中定义一个 $_admate_getListProxy 方法来代理 $_admate_getList

methods: {
  /**
   * @param {string} motive - 调用动机 可能的值:'init' 'pageNoChange' 'filterChange' 'c' 'r' 'u' 'd' 'updateStatus' 'enable' 'disable'
   * @param {object} res - 调用动机的接口返回值(首次进入页面、列表查询参数改变时为空)
   */
  $_admate_getListProxy(motive, res)
  {
    // 在查询列表之前做点什么...
    this.$_admate_getList()
    .then(res => {
      // 在查询列表之后做点什么...
    })
    .catch(res => {})
    .finally()
  }
}

表单状态

this.$_admate_row.status

可能的值:

  • 'c' 新增
  • 'r' 查看
  • 'u' 编辑
  • '' 关闭

列表参数

this.$_admate_list.filter

给列表参数绑定默认值

data()
{
  return {
    $_admate_list: {
      filter: {
        pageSize: 15, // 覆盖默认值10
        status: 1 // 新增的
      }
    }
  }
}

列表加载状态

this.$_admate_list.loading

methods: {
  xxx()
  {
    this.$_admate_list.loading = true
    this.POST('')
    .finally(() => {
      this.$_admate_list.loading = false
    })
  }
}

表单数据

this.$_admate_row.data

给表单数据绑定默认值

data()
{
  return {
    $_admate_row: {
      data: {
        arr: [],
        num: 100
      }
    },
  }
}

apiGenerator

根据接口前缀自动生成增删查改接口调用

获取实例:调用 getApiGenerator 方法

初始化

// main.js

import { getApiGenerator } from 'admate'
import request from '@/utils/request'

const apiGenerator = getApiGenerator({
  // 全局配置

  // axios实例
  request,

  // 接口后缀默认值
  url: {
    c: 'create',                  // 单条新增
    r: 'queryForDetail',          // 单条查询
    u: 'update',                  // 单条编辑
    d: 'delete',                  // 单条删除
    list: 'queryForPage',         // 列表查询
    updateStatus: 'updateStatus', // 单条状态变更
    enable: 'enable',             // 状态启用
    disable: 'enable',            // 状态停用
  },

  // 请求方式 默认全POST
  method: {
    c: 'POST',
    r: 'POST',
    u: 'POST',
    d: 'POST',
    list: 'POST',
    updateStatus: 'POST',
    enable: 'POST',
    disable: 'POST',
  },

  // 提交方式 默认空数组(全json) 可以在这里指定接口使用formData
  formData: ['c', 'u'],

  // 使用config你可以完全自定义每个接口的请求配置 甚至支持function(从而能够拿到data)
  config: {
    c: {},
    r (data) {
      return {}
    },
  }
})

export { apiGenerator }

局部配置

import { apiGenerator } from '@/main'

export default {
  data () {
    return {
      $_admate_api: apiGenerator('/somepage', {
        // 全局配置中的所有配置项均支持局部配置
      })
    }
  }
}

覆盖统一前缀

如果某个接口的前缀不是 somepage 可以在后缀前加斜线

data()
{
  return {
    $_admate_api: apiGenerator('/somepage', {
      url: {
        r: '/anotherpage/selectOne',
      },
    })
  }
}

将得到:

  • /somepage/create
  • /somepage/update
  • /somepage/delete
  • /somepage/queryForPage
  • /somepage/updateStatus
  • /anotherpage/selectOne

增删查改

查询列表
/**
 * @param {function} callback - 回调函数
 *        {object} res - 接口返回值
 */
this.$_admate_getList()
查询单条
/**
 * @param {object|FormData} obj - 必传
 * @param {string} objIs - 指定参数1的用途 默认'param'
 */
this.$_admate_r()
新增单条

this.$_admate_c()

编辑单条
/**
 * @param {object|FormData} obj - 必传
 * @param {string} objIs - 指定参数1的用途 默认'param'
 */
this.$_admate_u()
删除单条
/**
 * @param {object|FormData} obj - 必传
 * @param {string} objIs - 指定参数1的用途 默认'param'
 */
this.$_admate_d()
变更单条状态
/**
 * @param {object|FormData} obj - 必传
 * @param {string} objIs - 指定参数1的用途 默认'param'
 */
this.$_admate_updateStatus()
启用单条
/**
 * @param {object|FormData} obj - 必传
 * @param {string} objIs - 指定参数1的用途 默认'param'
 */
this.$_admate_enable()
停用单条
/**
 * @param {object|FormData} obj - 必传
 * @param {string} objIs - 指定参数1的用途 默认'param'
 */
this.$_admate_disable()

参数2的可选值:

  • 'param':将参数1用作请求参数(默认)
  • 'config':将参数1仅用于请求配置
  • 'data':将参数1直接用作表单数据(不调用查询单条接口)(仅 $_admate_r$_admate_u 可用)

单条状态变更

状态变更的两种方式:

  • 调用同一个接口,传参指定新的状态:使用 updateStatus

<el-table-column label="操作" align="center">
  <template slot-scope="{row:{id,status}}">
    <AuthButton @click="$_admate_updateStatus({id,status:status^1})" :name="['启用', '停用'][status]"/>
  </template>
</el-table-column>
  • 启用和停用是独立的两个接口:使用 enabledisable

<el-table-column label="操作" align="center">
  <template slot-scope="{row:{id,status}}">
    <AuthButton @click="[$_admate_enable,$_admate_disable][status]({id})" :name="['启用', '停用'][status]"/>
  </template>
</el-table-column>

不调用查询单条接口

对于 $_admate_r$_admate_u 支持直接使用列表中的单条数据(而不是调用接口)

  1. 第一个参数:不再传接口参数 将列表中的行数据直接传入
  2. 第二个参数:传 'data'

<el-table-column label="操作" align="center">
  <template slot-scope="{row}">
    <AuthButton @click="$_admate_r(row,'data')" name="查看"/>
    <AuthButton @click="$_admate_u(row,'data')" name="编辑"/>
  </template>
</el-table-column>

RESTful

如果接口地址需要进行动态拼接


<template>
  <el-table-column label="操作" align="center">
    <template slot-scope="{row}">
      <AuthButton @click="$_admate_r(row,'config')" name="查看"/>
      <AuthButton @click="$_admate_u(row,'config')" name="编辑"/>
    </template>
  </el-table-column>
</template>

<script>
export default {
  data () {
    return {
      $_admate_api: apiGenerator('/somepage', {

        // 方式1
        url: {
          r: row => 'module/' + row.id,
        },

        // 方式2
        config: {
          r (row) {
            return {
              url: 'module/' + row.id
            }
          },
        }

      })
    }
  }
}
</script>

axiosShortcut

根据axios实例生成axios实例的调用捷径

通过 getAxiosShortcut 方法获取 axiosShortcut


初始化

import Vue from 'vue'
import { getAxiosShortcut } from 'admate'
import request from '@/utils/request'

const axiosShortcut = getAxiosShortcut({
  // 全局配置

  // axios实例
  request
})
for (let k in axiosShortcut) {
  Vue.prototype[k] = axiosShortcut[k]
}

AJAX

快捷方式

  • GET
  • POST
  • PATCH
  • PUT
  • DELETE
  • HEAD
/**
 * @param {string} url - 接口地址
 * @param {object} data - 接口参数
 * @param {object} config - axios配置
 * @return {Promise<object>} 接口返回值
 */
this.POST()

::: tip
屏蔽了GET和POST请求参数属性不一致的差异

过滤掉参数中无效的值(null | NaN | undefined)

有时候参数所绑定的对象中会存在一些临时属性 而这些属性是不应该提交到后端的 我们约定这些临时变量以双下划线__开头 __开头的属性会被过滤掉 :::


上传

请求体类型为 multipart/form-data

/**
 * @param {string} url - 接口地址
 * @param {object} data - 接口参数
 * @param {object} config - axios配置
 * @return {Promise<object>} 接口返回值
 */
this.POST.upload()

::: tip
示例中的 POST 可替换为其他请求方式 :::


下载

ajax请求方式

/**
 * @param {string} url - 接口地址
 * @param {object} data - 接口参数
 * @param {object} config - axios配置
 * @return {Promise<object>} 接口返回值
 */
this.POST.download()

::: tip
示例中的 POST 可替换为其他请求方式 :::

地址栏请求方式

/**
 * @param {string} url - 接口地址
 * @param {object} data - 接口参数
 * @param {object} config - axios配置
 */
this.DOWNLOAD()

给上传/下载添加全局回调

上传/下载本质上还是调用axios实例 所以在axios实例的响应拦截器中判断即可

request.interceptors.response.use(
  response => {
    // download
    if (response.config.responseType === 'blob') {
      console.log('导出成功')
    }
  },
)

filters

管理后台常用filters

::: tip
所有过滤器均可当作方法调用 :::

初始化

import { filters } from 'admate'
Object.keys(filters).map(filter => {
  const key = `$${filter}`
  Vue.filter(key, filters[filter])
  Object.defineProperty(Vue.prototype, key, {
    value: filters[filter]
  })
})

key2label

数据字典转义


<el-table-column>
  <template slot-scope="{row}">
    {{row.type | $key2label(dict.type)}}
  </template>
</el-table-column>

当作方法调用:

/**
 * @param {string|Symbol} 需要查询的id
 * @param {array} 由多个`{[id]: '', [name]: ''}`构成的数组
 * @param {string} 自定义id和name对应的属性名 默认为'dataValue/dataName'
 * @return {Any} id对应的name
 */
this.$key2label('1', [
  { dataValue: '1', dataName: 'a' },
  { dataValue: '2', dataName: 'b' },
]) // 'a'

this.$key2label('1', [
  { id: '1', name: 'a' },
  { id: '2', name: 'b' },
], 'id/name') // 'a'

dialogTitle

表单对话框标题


<FormDialog :title="$_admate_row.status | $dialogTitle"/>

默认对应关系:

  • c:新增
  • r:查看
  • u:编辑

修改默认值或补充其他:


<FormDialog :title="$_admate_row.status | $dialogTitle({ c: '注册' })"/>

FAQs

Package last updated on 29 Apr 2021

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc