Kaynağa Gözat

修改导航菜单

zs 1 yıl önce
ebeveyn
işleme
ed2207e9db

+ 1 - 0
src/lang/package/zh-cn/menus.js

@@ -9,6 +9,7 @@ export default {
   system_parameter: '系统参数',
   system_dict: '字典管理',
   system_dict_data: '字典数据',
+  system_tags: '网站导航设置',
   user_admin: '管理员用户',
   user_user: '平台用户',
   platform: '信息管理',

+ 15 - 0
src/lang/package/zh-cn/pages.js

@@ -83,6 +83,21 @@ export default {
     labelMessage: '请输入数据显示值',
     valueMessage: '请输入数据选择值'
   },
+  tags: {
+    addDialogTitle: '新增导航菜单',
+    upDialogTitle: '修改导航菜单',
+    title: '标题',
+    English: '英文标题',
+    href: '路由',
+    children: '子菜单',
+    type: '是否有子菜单',
+    is_use: '是否启用',
+    remark: '备注',
+    sort: '排序',
+    titleMessage: '请输入标题',
+    hrefMessage: '请输入路由',
+    sortfMessage: '请输入排序'
+  },
   news: {
     addDialogTitle: '新增新闻',
     upDialogTitle: '修改新闻',

+ 40 - 0
src/store/api/system/tags.js

@@ -0,0 +1,40 @@
+import { defineStore } from 'pinia'
+import { AxiosWrapper } from '@/utils/axios-wrapper'
+import { get } from 'lodash-es'
+const url = '/tags'
+const axios = new AxiosWrapper()
+
+export const TagsStore = defineStore('tags', () => {
+  const query = async ({ skip = 0, limit = undefined, ...info } = {}) => {
+    let cond = {}
+    if (skip) cond.skip = skip
+    if (limit) cond.limit = limit
+    cond = { ...cond, ...info }
+    const res = await axios.$get(`${url}`, cond)
+    return res
+  }
+  const fetch = async (payload) => {
+    const res = await axios.$get(`${url}/${payload}`)
+    return res
+  }
+  const create = async (payload) => {
+    const res = await axios.$post(`${url}`, payload)
+    return res
+  }
+  const update = async (payload) => {
+    const id = get(payload, 'id', get(payload, '_id'))
+    const res = await axios.$post(`${url}/${id}`, payload)
+    return res
+  }
+  const del = async (payload) => {
+    const res = await axios.$delete(`${url}/${payload}`)
+    return res
+  }
+  return {
+    query,
+    fetch,
+    create,
+    update,
+    del
+  }
+})

+ 212 - 0
src/views/system/tags/index.vue

@@ -0,0 +1,212 @@
+<template>
+  <div class="main animate__animated animate__backInRight" v-loading="loading">
+    <custom-search-bar
+      :fields="fields.filter((f) => f.isSearch)"
+      v-model="searchForm"
+      @search="search"
+      @reset="toReset"
+    ></custom-search-bar>
+    <custom-button-bar :fields="buttonFields" @add="toAdd"></custom-button-bar>
+    <custom-table
+      :data="data"
+      :fields="fields"
+      @query="search"
+      :total="total"
+      :opera="opera"
+      @dict="toDict"
+      @edit="toEdit"
+      @delete="toDelete"
+    >
+      <template #is_use="{ row }">
+        <el-tag v-if="row.is_use == '0'" type="success">启用</el-tag>
+        <el-tag v-else type="info">禁用</el-tag>
+      </template>
+    </custom-table>
+    <el-dialog
+      v-model="dialog.show"
+      :title="dialog.title"
+      :destroy-on-close="false"
+      @close="toClose"
+      :top="dialog.top"
+    >
+      <el-row>
+        <el-col :span="24" v-if="dialog.type == '1'">
+          <custom-form v-model="form" :fields="formFields" :rules="rules" @save="toSave">
+            <template #type>
+              <el-option
+                v-for="i in typeList"
+                :key="i._id"
+                :label="i.label"
+                :value="i.value"
+              ></el-option>
+            </template>
+            <template #children>
+              <el-col :span="24" class="button">
+                <el-button type="primary" size="small" @click="toCadd()">添加</el-button>
+              </el-col>
+              <el-table :data="form.children" border size="mini">
+                <el-table-column align="center" label="标题" prop="title">
+                  <template #default="{ row }">
+                    <el-input v-model="row.title" clearable placeholder="请输入标题"></el-input>
+                  </template>
+                </el-table-column>
+                <el-table-column align="center" label="路由" prop="href">
+                  <template #default="{ row }">
+                    <el-input v-model="row.href" clearable placeholder="请输入路由"></el-input>
+                  </template>
+                </el-table-column>
+                <el-table-column label="操作" align="center" width="100">
+                  <template #default="scope">
+                    <el-button size="mini" type="danger" @click="toCdel(scope.row)">删除</el-button>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </template>
+            <template #is_use>
+              <el-radio v-for="i in isUseList" :key="i._id" :label="i.value">{{
+                i.label
+              }}</el-radio>
+            </template>
+          </custom-form>
+        </el-col>
+      </el-row>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import moment from 'moment'
+const $checkRes = inject('$checkRes')
+import { cloneDeep, get } from 'lodash-es'
+const { t } = useI18n()
+// 接口
+import { TagsStore } from '@/store/api/system/tags'
+import { DictDataStore } from '@/store/api/system/dictData'
+const store = TagsStore()
+const dictDataStore = DictDataStore()
+const data = ref([])
+const searchForm = ref({})
+const fields = [
+  { label: t('pages.tags.title'), model: 'title', isSearch: true },
+  { label: t('pages.tags.href'), model: 'href', isSearch: true },
+  { label: t('pages.tags.English'), model: 'English' },
+  { label: t('pages.tags.sort'), model: 'sort' },
+  { label: t('pages.tags.type'), model: 'type', format: (i) => getDict(i, 'type') },
+  {
+    label: t('pages.tags.is_use'),
+    model: 'is_use',
+    format: (i) => getDict(i, 'is_use'),
+    custom: true
+  },
+  { label: t('pages.tags.remark'), model: 'remark' }
+]
+const opera = [
+  { label: t('common.update'), method: 'edit' },
+  { label: t('common.delete'), method: 'delete', confirm: true, type: 'danger' }
+]
+const buttonFields = [{ label: t('common.add'), method: 'add' }]
+let skip = 0
+let limit = inject('limit')
+const total = ref(0)
+const isUseList = ref([])
+const typeList = [
+  { label: '是', value: '0' },
+  { label: '否', value: '1' }
+]
+// 加载中
+const loading = ref(false)
+const formFields = [
+  { label: t('pages.tags.title'), model: 'title' },
+  { label: t('pages.tags.href'), model: 'href' },
+  { label: t('pages.tags.English'), model: 'English' },
+  { label: t('pages.tags.type'), model: 'type', type: 'select' },
+  {
+    label: t('pages.tags.children'),
+    model: 'children',
+    custom: true,
+    display: () => form.value.type === '0'
+  },
+  { label: t('pages.tags.sort'), model: 'sort', type: 'number' },
+  { label: t('pages.tags.is_use'), model: 'is_use', type: 'radio' },
+  { label: t('pages.tags.remark'), model: 'remark', type: 'textarea' }
+]
+const rules = reactive({
+  title: [{ required: true, message: t('pages.tags.titleMessage'), trigger: 'blur' }],
+  href: [{ required: true, message: t('pages.tags.hrefMessage'), trigger: 'blur' }],
+  sort: [{ required: true, message: t('pages.tags.sortfMessage'), trigger: 'blur' }]
+})
+const dialog = ref({ type: '1', show: false, title: t('pages.tags.dialogTitle'), top: '15vh' })
+const form = ref({ type: '1', children: [] })
+// 请求
+onMounted(async () => {
+  loading.value = true
+  await searchOther()
+  await search({ skip, limit })
+  loading.value = false
+})
+
+const searchOther = async () => {
+  const result = await dictDataStore.query({ code: 'isUse', is_use: '0' })
+  if ($checkRes(result)) isUseList.value = result.data
+}
+const search = async (query = { skip: 0, limit }) => {
+  const info = { skip: query.skip, limit: query.limit, ...searchForm.value }
+  const res = await store.query(info)
+  if (res.errcode == '0') {
+    data.value = res.data
+    total.value = res.total
+  }
+}
+// 字典数据转换
+const getDict = (data, model) => {
+  let res
+  if (model == 'is_use') res = isUseList.value.find((f) => f.value == data)
+  else if (model == 'type') res = typeList.find((f) => f.value == data)
+  return get(res, 'label')
+}
+// 添加
+const toAdd = () => {
+  dialog.value = { type: '1', show: true, title: t('pages.tags.addDialogTitle'), top: '15vh' }
+}
+// 修改
+const toEdit = (data) => {
+  form.value = data
+  dialog.value = { type: '1', show: true, title: t('pages.tags.upDialogTitle'), top: '15vh' }
+}
+// 删除
+const toDelete = async (data) => {
+  const res = await store.del(data._id)
+  if ($checkRes(res, true)) {
+    search({ skip: 0, limit })
+  }
+}
+// 添加子菜单
+const toCadd = async () => {
+  form.value.children.push({ type: '1', _id: moment().valueOf() })
+}
+// 删除子菜单
+const toCdel = async (item) => {
+  const children = form.value.children.filter((i) => i._id != item._id)
+  form.value.children = children
+}
+const toSave = async () => {
+  const data = cloneDeep(form.value)
+  let res
+  if (get(data, '_id')) res = await store.update(data)
+  else res = await store.create(data)
+  if ($checkRes(res, true)) {
+    search({ skip: 0, limit })
+    toClose()
+  }
+}
+// 重置
+const toReset = async () => {
+  searchForm.value = {}
+  await search({ skip, limit })
+}
+const toClose = () => {
+  form.value = { type: '1', children: [] }
+  dialog.value = { show: false }
+}
+</script>
+<style scoped lang="scss"></style>