lrf 10 months ago
parent
commit
b0578168b3

+ 1 - 1
.gitignore

@@ -6,7 +6,7 @@ yarn-debug.log*
 yarn-error.log*
 yarn-error.log*
 pnpm-debug.log*
 pnpm-debug.log*
 lerna-debug.log*
 lerna-debug.log*
-
+cxyyAdmin*
 node_modules
 node_modules
 .DS_Store
 .DS_Store
 dist
 dist

+ 4 - 33
README.md

@@ -1,35 +1,6 @@
 # web-template-vue3-js
 # web-template-vue3-js
 
 
-This template should help get you started developing with Vue 3 in Vite.
-
-## Recommended IDE Setup
-
-[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
-
-## Customize configuration
-
-See [Vite Configuration Reference](https://vitejs.dev/config/).
-
-## Project Setup
-
-```sh
-pnpm install
-```
-
-### Compile and Hot-Reload for Development
-
-```sh
-pnpm dev
-```
-
-### Compile and Minify for Production
-
-```sh
-pnpm build
-```
-
-### Lint with [ESLint](https://eslint.org/)
-
-```sh
-pnpm lint
-```
+## 1.菜单设置
+### 1.1 功能列表
+> 前端:主要是控制角色是否可以显示按钮
+> 服务:主要是用同一编码对接口的使用进行控制

+ 1 - 1
src/lang/package/zh-cn/common.js

@@ -1,7 +1,7 @@
 export default {
 export default {
   opera: '操作',
   opera: '操作',
   back: '返回',
   back: '返回',
-  add: '添加',
+  create: '添加',
   update: '修改',
   update: '修改',
   delete: '删除',
   delete: '删除',
   exam: '审核',
   exam: '审核',

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

@@ -11,6 +11,7 @@ export default {
   system_dict_data: '字典数据',
   system_dict_data: '字典数据',
   system_tags: '导航设置',
   system_tags: '导航设置',
   system_design: '平台设置',
   system_design: '平台设置',
+  system_dept: '部门管理',
   user_admin: '管理员用户',
   user_admin: '管理员用户',
   user_user: '平台用户',
   user_user: '平台用户',
   platform: '信息管理',
   platform: '信息管理',

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

@@ -208,5 +208,15 @@ export default {
     email: '电子邮箱',
     email: '电子邮箱',
     remark: '备注',
     remark: '备注',
     DialogTitle: '查看报名情况'
     DialogTitle: '查看报名情况'
+  },
+  dept: {
+    dialogTitle: '部门信息',
+    rDialogTitle: '部门资源',
+    leftTreeTitle: '部门架构图',
+    name: '部门名称',
+    order_num: '顺序',
+    partent: '上级部门',
+    status: '使用状态',
+    resource: '资源管理'
   }
   }
 }
 }

+ 3 - 2
src/layout/parts/Header.vue

@@ -38,7 +38,7 @@ const router = useRouter()
 const logout = () => {
 const logout = () => {
   userStore.logOut()
   userStore.logOut()
   tagsViewStore.delAllViews()
   tagsViewStore.delAllViews()
-  router.push('/login')
+  window.location.href = '/login'
 }
 }
 // 个人中心
 // 个人中心
 const center = () => {
 const center = () => {
@@ -79,4 +79,5 @@ const center = () => {
       }
       }
     }
     }
   }
   }
-}</style>
+}
+</style>

+ 47 - 0
src/store/api/system/dept.js

@@ -0,0 +1,47 @@
+import { defineStore } from 'pinia'
+import { AxiosWrapper } from '@/utils/axios-wrapper'
+import { get, omit } from 'lodash-es'
+const url = '/dept'
+const axios = new AxiosWrapper()
+
+export const DeptStore = defineStore('dept', () => {
+  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
+  }
+  const nextLevel = async (payload) => {
+    const id = get(payload, 'id', get(payload, '_id'))
+    const querys = omit(payload, ['id'])
+    const res = await axios.$get(`${url}/nextLevel/${id}`, querys)
+    return res
+  }
+  return {
+    query,
+    fetch,
+    create,
+    update,
+    del,
+    nextLevel
+  }
+})

+ 8 - 8
src/utils/axios-wrapper.js

@@ -96,16 +96,16 @@ export class AxiosWrapper {
       const { errcode, errmsg, details } = returnRes
       const { errcode, errmsg, details } = returnRes
       if (errcode) {
       if (errcode) {
         console.warn(`[${uri}] fail: ${errcode}-${errmsg} ${details}`)
         console.warn(`[${uri}] fail: ${errcode}-${errmsg} ${details}`)
-        if(errcode!==0) {
+        if (errcode !== 0) {
           console.log(router)
           console.log(router)
           if (errcode.includes('FRAMEERROR_401')) {
           if (errcode.includes('FRAMEERROR_401')) {
-            await ElMessageBox.alert(errmsg, i18n.global.t('common.user_confirm'), {
-              confirmButtonText: i18n.global.t('common.re_login'),
-              type: 'error',
-              callback: (act) => {
-                // router.replace('/login')
-              }
-            })
+            // await ElMessageBox.alert(errmsg, i18n.global.t('common.user_confirm'), {
+            //   confirmButtonText: i18n.global.t('common.re_login'),
+            //   type: 'error',
+            //   callback: (act) => {
+            //     // router.replace('/login')
+            //   }
+            // })
           }
           }
         }
         }
         return returnRes
         return returnRes

+ 2 - 1
src/utils/directives.js

@@ -8,7 +8,7 @@ const InitDirective = (app) => {
       const { value: code } = binding
       const { value: code } = binding
       const rUser = toRaw(user)
       const rUser = toRaw(user)
       // 超级管理员不进行检查
       // 超级管理员不进行检查
-      if (get(rUser, 'role') === 'Admin' && get(rUser, 'is_super') === '0') return
+      if (get(rUser, 'role').includes('Admin') && get(rUser, 'is_super') === '0') return
       const roleCode = get(rUser, 'role_code')
       const roleCode = get(rUser, 'role_code')
       // 需要判断roleCode中是否有这个权限.但是权限又需要路由拼接起来,最少也得有上层级组合
       // 需要判断roleCode中是否有这个权限.但是权限又需要路由拼接起来,最少也得有上层级组合
       const cr = router.currentRoute.value
       const cr = router.currentRoute.value
@@ -16,6 +16,7 @@ const InitDirective = (app) => {
       const rArr = cr.matched.filter((f) => f.name !== 'Layout').map((i) => i.name)
       const rArr = cr.matched.filter((f) => f.name !== 'Layout').map((i) => i.name)
       rArr.push(code)
       rArr.push(code)
       const thisMethodCode = `${rArr.join('.')}`
       const thisMethodCode = `${rArr.join('.')}`
+      console.log(thisMethodCode)
       if (!isArray(roleCode)) {
       if (!isArray(roleCode)) {
         el.parentNode.removeChild(el)
         el.parentNode.removeChild(el)
       }
       }

+ 1 - 1
src/views/achievement/index.vue

@@ -90,7 +90,7 @@ const opera = [
   { label: t('common.exam'), method: 'exam', type: 'warning', display: (i) => i.status === '0' },
   { label: t('common.exam'), method: 'exam', type: 'warning', display: (i) => i.status === '0' },
   { label: t('common.delete'), method: 'delete', confirm: true, type: 'danger', display: (i) => i.is_use === '1' }
   { label: t('common.delete'), method: 'delete', confirm: true, type: 'danger', display: (i) => i.is_use === '1' }
 ]
 ]
-const buttonFields = [{ label: t('common.add'), method: 'add' }]
+const buttonFields = [{ label: t('common.create'), method: 'add' }]
 let skip = 0
 let skip = 0
 let limit = inject('limit')
 let limit = inject('limit')
 const total = ref(0)
 const total = ref(0)

+ 1 - 0
src/views/login/index.vue

@@ -52,6 +52,7 @@ const loginData = ref({
 const loginRules = computed(() => {})
 const loginRules = computed(() => {})
 const toLogin = async (data) => {
 const toLogin = async (data) => {
   const res = await loginStore.login(data)
   const res = await loginStore.login(data)
+  console.log(res)
   if (res.errcode == '0') {
   if (res.errcode == '0') {
     ElMessage({ message: `登录成功`, type: 'success' })
     ElMessage({ message: `登录成功`, type: 'success' })
     localStorage.setItem('token', res.data)
     localStorage.setItem('token', res.data)

+ 1 - 1
src/views/match/info/index.vue

@@ -201,7 +201,7 @@ const opera = [
     display: (i) => i.is_use === '1' && i.match_status === '0'
     display: (i) => i.is_use === '1' && i.match_status === '0'
   }
   }
 ]
 ]
-const buttonFields = [{ label: t('common.add'), method: 'add' }]
+const buttonFields = [{ label: t('common.create'), method: 'add' }]
 let skip = 0
 let skip = 0
 let limit = inject('limit')
 let limit = inject('limit')
 const total = ref(0)
 const total = ref(0)

+ 1 - 1
src/views/platform/demand/demand/index.vue

@@ -79,7 +79,7 @@ const opera = [
   { label: t('common.exam'), method: 'exam', type: 'warning', display: (i) => i.status === '0' },
   { label: t('common.exam'), method: 'exam', type: 'warning', display: (i) => i.status === '0' },
   { label: t('common.delete'), method: 'delete', confirm: true, type: 'danger', display: (i) => i.is_use === '1' }
   { label: t('common.delete'), method: 'delete', confirm: true, type: 'danger', display: (i) => i.is_use === '1' }
 ]
 ]
-const buttonFields = [{ label: t('common.add'), method: 'add' }]
+const buttonFields = [{ label: t('common.create'), method: 'add' }]
 let skip = 0
 let skip = 0
 let limit = inject('limit')
 let limit = inject('limit')
 const total = ref(0)
 const total = ref(0)

+ 1 - 1
src/views/platform/demand/supply/index.vue

@@ -79,7 +79,7 @@ const opera = [
   { label: t('common.exam'), method: 'exam', type: 'warning', display: (i) => i.status === '0' },
   { label: t('common.exam'), method: 'exam', type: 'warning', display: (i) => i.status === '0' },
   { label: t('common.delete'), method: 'delete', confirm: true, type: 'danger', display: (i) => i.is_use === '1' }
   { label: t('common.delete'), method: 'delete', confirm: true, type: 'danger', display: (i) => i.is_use === '1' }
 ]
 ]
-const buttonFields = [{ label: t('common.add'), method: 'add' }]
+const buttonFields = [{ label: t('common.create'), method: 'add' }]
 let skip = 0
 let skip = 0
 let limit = inject('limit')
 let limit = inject('limit')
 const total = ref(0)
 const total = ref(0)

+ 1 - 1
src/views/platform/news/index.vue

@@ -112,7 +112,7 @@ const opera = [
     display: (i) => i.is_use === '1'
     display: (i) => i.is_use === '1'
   }
   }
 ]
 ]
-const buttonFields = [{ label: t('common.add'), method: 'add' }]
+const buttonFields = [{ label: t('common.create'), method: 'add' }]
 let skip = 0
 let skip = 0
 let limit = inject('limit')
 let limit = inject('limit')
 const total = ref(0)
 const total = ref(0)

+ 1 - 1
src/views/platform/policy/index.vue

@@ -112,7 +112,7 @@ const opera = [
     display: (i) => i.is_use === '1'
     display: (i) => i.is_use === '1'
   }
   }
 ]
 ]
-const buttonFields = [{ label: t('common.add'), method: 'add' }]
+const buttonFields = [{ label: t('common.create'), method: 'add' }]
 let skip = 0
 let skip = 0
 let limit = inject('limit')
 let limit = inject('limit')
 const total = ref(0)
 const total = ref(0)

+ 1 - 1
src/views/project/index.vue

@@ -92,7 +92,7 @@ const opera = [
   { label: t('common.exam'), method: 'exam', type: 'warning', display: (i) => i.status === '0' },
   { label: t('common.exam'), method: 'exam', type: 'warning', display: (i) => i.status === '0' },
   { label: t('common.delete'), method: 'delete', confirm: true, type: 'danger', display: (i) => i.is_use === '1' }
   { label: t('common.delete'), method: 'delete', confirm: true, type: 'danger', display: (i) => i.is_use === '1' }
 ]
 ]
-const buttonFields = [{ label: t('common.add'), method: 'add' }]
+const buttonFields = [{ label: t('common.create'), method: 'add' }]
 let skip = 0
 let skip = 0
 let limit = inject('limit')
 let limit = inject('limit')
 const total = ref(0)
 const total = ref(0)

+ 144 - 0
src/views/system/dept/index.vue

@@ -0,0 +1,144 @@
+<template>
+  <div class="main animate__animated animate__backInRight">
+    <el-row :gutter="10" style="height: 100%">
+      <el-col :span="4" style="padding: 5px">
+        <left-tree></left-tree>
+      </el-col>
+      <!-- style="border: 1px solid; padding: 5px" -->
+      <el-col :span="19" :offset="1" style="padding: 5px">
+        <right-view></right-view>
+      </el-col>
+    </el-row>
+    <el-dialog v-model="dialog" :title="$t('pages.dept.dialogTitle')" :destroy-on-close="true" @close="toClose">
+      <right-form></right-form>
+    </el-dialog>
+    <el-dialog v-model="rDialog" :title="$t('pages.dept.rDialogTitle')" :destroy-on-close="true" @close="toClose">
+      <resource></resource>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import leftTree from './parts/left-tree.vue'
+import rightView from './parts/right-view.vue'
+import rightForm from './parts/right-form.vue'
+import resource from './parts/resource.vue'
+import { cloneDeep, get, omit } from 'lodash-es'
+import { DeptStore } from '@/store/api/system/dept'
+import { MenusStore } from '@/store/api/system/menus'
+import { onMounted, provide } from 'vue'
+const store = DeptStore()
+const menuStore = MenusStore()
+const $checkRes = inject('$checkRes')
+const dialog = ref(false)
+//左树状图
+const treeData = ref([])
+//右部门的列表id
+const viewId = ref()
+provide('viewId', viewId)
+//右部门列表数据
+const list = ref([])
+//右部门数据总数
+const total = ref(0)
+let limit = inject('limit')
+//部门编辑表单
+const form = ref({})
+provide('form', form)
+onMounted(() => {
+  search()
+  searchMenus()
+})
+// #region 接口函数
+const search = async () => {
+  const res = await store.query()
+  if ($checkRes(res)) {
+    treeData.value = res.data
+  }
+}
+const changeDeptList = (id) => {
+  viewId.value = id
+  searchNextLevel()
+}
+provide('changeDeptList', changeDeptList)
+
+const searchNextLevel = async (query = { skip: 0, limit }) => {
+  const res = await store.nextLevel({ id: viewId.value, ...query })
+  if ($checkRes(res)) {
+    list.value = res.data
+    total.value = res.total
+  }
+}
+provide('list', list)
+provide('total', total)
+provide('treeData', treeData)
+const toSave = async () => {
+  const data = cloneDeep(omit(form.value, ['children', 'parent_id_name']))
+  let res
+  if (get(data, '_id')) {
+    res = await store.update(data)
+  } else res = await store.create(data)
+  if ($checkRes(res, true)) {
+    search()
+    searchNextLevel()
+    toClose()
+  }
+}
+provide('toSave', toSave)
+const toDelete = async (row) => {
+  const res = await store.del(row._id)
+  if ($checkRes(res, true)) {
+    search()
+    searchNextLevel()
+  }
+}
+provide('toDelete', toDelete)
+const toChangeUse = async (data) => {
+  const udata = { _id: data._id, is_use: data.is_use === '0' ? '1' : '0' }
+  const res = await store.update(udata)
+  if ($checkRes(res, true)) {
+    searchNextLevel()
+  }
+}
+provide('toChangeUse', toChangeUse)
+
+// #endregion
+
+// #region 工具函数
+const toUpdate = (row) => {
+  form.value = cloneDeep(row)
+  dialog.value = true
+}
+provide('toEdit', toUpdate)
+
+const toAdd = () => {
+  if (!viewId) {
+    return
+  }
+  form.value = { is_use: '0', parent_id: viewId.value, resource: ['home'] }
+  dialog.value = true
+}
+provide('toAdd', toAdd)
+
+const toClose = () => {
+  form.value = {}
+  dialog.value = false
+  rDialog.value = false
+}
+const rDialog = ref(false)
+const toResource = (row) => {
+  form.value = cloneDeep(row)
+  rDialog.value = true
+}
+provide('toResource', toResource)
+const menuList = ref([])
+const searchMenus = async () => {
+  const res = await menuStore.query()
+  if ($checkRes(res)) {
+    menuList.value = res.data
+  }
+}
+provide('menuList', menuList)
+// #endregion
+</script>
+
+<style scoped></style>

+ 27 - 0
src/views/system/dept/parts/left-tree.vue

@@ -0,0 +1,27 @@
+<template>
+  <div id="left-tree">
+    <el-row>
+      <el-col :span="24"> {{ $t('pages.dept.leftTreeTitle') }} </el-col>
+    </el-row>
+    <el-tree style="width: 100%" :data="treeData" :props="defaultProps" accordion @node-click="handleNodeClick" />
+  </div>
+</template>
+
+<script setup>
+import { Plus } from '@element-plus/icons-vue'
+import { inject } from 'vue'
+import { get } from 'lodash-es'
+const treeData = inject('treeData')
+const changeDeptList = inject('changeDeptList')
+const defaultProps = {
+  children: 'children',
+  label: 'name'
+}
+const handleNodeClick = async (data) => {
+  const rd = toRaw(data)
+  const id = get(rd, '_id')
+  changeDeptList(id)
+}
+</script>
+
+<style lang="scss" scoped></style>

+ 93 - 0
src/views/system/dept/parts/resource.vue

@@ -0,0 +1,93 @@
+<template>
+  <div id="resource">
+    <el-tree ref="roleTree" :data="getTreeData()" node-key="code" default-expand-all show-checkbox @check-change="seletNode">
+      <template #default="{ data }">
+        <span>{{ data.name }}</span>
+      </template>
+    </el-tree>
+    <el-row>
+      <el-col :span="24" style="text-align: center">
+        <el-button @click="toSave" type="primary">{{ $t('common.save') }}</el-button>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup>
+import { onMounted } from 'vue'
+
+const form = inject('form')
+const menuList = inject('menuList')
+const toSave = inject('toSave')
+const roleTree = ref()
+const getTreeData = () => {
+  const list = toRaw(menuList.value)
+  const result = dealMenu(list)
+  return result
+}
+onMounted(() => {
+  const treeSelected = toRaw(form.value.resource)
+  for (const key of treeSelected) {
+    roleTree.value.setChecked(key, true)
+  }
+  // 默认选中主页
+  const selectedKeys = roleTree.value.getCheckedKeys()
+  if (!selectedKeys.includes('home')) roleTree.value.setChecked('home', true)
+})
+/**
+ * 处理菜单:将目录,菜单,子页面,权限统一转成 {name,code}形式,code为唯一值
+ * 目录,菜单,子页面:
+ *  route_name是唯一的,所以使用route_name作为code
+ * 权限:
+ *  code并不是唯一,但是加上route_name就是唯一的
+ * @param {Array} list 菜单列表
+ * @param {Array} route_names 将上级的route_name放入此数组中,在转为权限数据时,拼接成code
+ */
+const dealMenu = (list, route_names = []) => {
+  const result = []
+  for (const i of list) {
+    const { name, config = [], children = [], route_name } = i
+    const thisRouteNameArr = [...route_names, route_name]
+    const obj = { name, code: thisRouteNameArr.join('.') }
+    if (route_name === 'home') obj.disabled = true
+    const nextList = []
+    // 先处理该页面配置
+    if (config.length >= 0) {
+      // 如果有配置: 菜单,子页面两种情况,都统一处理
+      for (const c of config) {
+        const codeRouteNameArr = [...thisRouteNameArr]
+        codeRouteNameArr.push(c.code)
+        const cobj = { name: c.zh, code: codeRouteNameArr.join('.') }
+        nextList.push(cobj)
+      }
+    }
+    // 再处理菜单/子页面
+    if (children.length > 0) {
+      const nextRouteNames = [...thisRouteNameArr]
+      const midResult = dealMenu(children, nextRouteNames)
+      nextList.push(...midResult)
+    }
+    obj.children = nextList
+    result.push(obj)
+  }
+  return result
+}
+
+/**
+ * 选择节点
+ */
+const seletNode = () => {
+  if (!form.value.resource) {
+    form.value.resource = []
+  }
+  const selected = roleTree.value.getCheckedNodes(false, true)
+  const result = []
+  for (const s of selected) {
+    const rs = toRaw(s)
+    result.push(rs.code)
+  }
+  form.value.resource = result
+}
+</script>
+
+<style lang="scss" scoped></style>

+ 27 - 0
src/views/system/dept/parts/right-form.vue

@@ -0,0 +1,27 @@
+<template>
+  <custom-form v-model="form" :fields="formFields" @save="toSave"> </custom-form>
+</template>
+
+<script setup>
+import { onMounted } from 'vue'
+const toSave = inject('toSave')
+const { t } = useI18n()
+const form = inject('form')
+const formFields = ref([])
+const formFieldsForCreate = [
+  // 只有部门名称在弹框里改, 使用/禁用在列表里改. 移动部门需要删除
+  { label: t('pages.dept.name'), model: 'name' },
+  { label: t('pages.dept.order_num'), model: 'order_num', type: 'number' }
+]
+const formFieldsForUpdate = [
+  // 只有部门名称在弹框里改, 使用/禁用在列表里改. 移动部门需要删除
+  { label: t('pages.dept.name'), model: 'name' },
+  { label: t('pages.dept.order_num'), model: 'order_num', type: 'number' }
+]
+onMounted(() => {
+  if (!form._id) formFields.value = formFieldsForCreate
+  else formFields.value = formFieldsForUpdate
+})
+</script>
+
+<style lang="scss" scoped></style>

+ 58 - 0
src/views/system/dept/parts/right-view.vue

@@ -0,0 +1,58 @@
+<template>
+  <div id="right-view">
+    <custom-button-bar :fields="buttonFields" @create="toAdd"></custom-button-bar>
+    <custom-table :data="data" :fields="fields" @search="search" :total="total" :opera="opera" @resource="toResource" @edit="toEdit" @changeUse="toChangeUse" @delete="toDelete">
+      <template #is_use="{ row }">
+        <el-tag v-if="row.is_use == '0'" type="success">{{ $t('common.is_use_abled') }}</el-tag>
+        <el-tag v-else type="info">{{ $t('common.is_use_disabled') }}</el-tag>
+      </template>
+    </custom-table>
+  </div>
+</template>
+<script setup>
+const toChangeUse = inject('toChangeUse')
+const toEdit = inject('toEdit')
+const toDelete = inject('toDelete')
+const toAdd = inject('toAdd')
+const viewId = inject('viewId')
+const toResource = inject('toResource')
+const { t } = useI18n()
+const data = inject('list')
+const total = inject('total')
+const fields = [
+  { label: t('pages.dept.name'), model: 'name', filter: true },
+  { label: t('pages.dept.partent'), model: 'parent_id_name' },
+  { label: t('pages.dept.status'), model: 'is_use', format: (i) => (i === '0' ? t('common.is_use_abled') : t('common.is_use_disabled')) }
+]
+const opera = [
+  { label: t('common.update'), method: 'update', display: (i) => i.is_super !== '0' },
+  { label: t('pages.dept.resource'), method: 'resource', display: (i) => i.is_use === '0' },
+  // { label: t('pages.admin.bind'), method: 'bind' },
+  {
+    label: t('common.is_use_disabled'),
+    method: 'changeUse',
+    type: 'warning',
+    confirm: true,
+    confirmWord: t('pages.admin.changeToDisabled'),
+    display: (i) => i.is_use === '0'
+  },
+  {
+    label: t('common.is_use_abled'),
+    method: 'changeUse',
+    type: 'success',
+    confirm: true,
+    confirmWord: t('pages.admin.changeToAbled'),
+    display: (i) => i.is_use === '1'
+  },
+  { label: t('common.delete'), method: 'delete', confirm: true, type: 'danger' }
+]
+const buttonFields = [
+  {
+    label: t('common.create'),
+    method: 'create',
+    disabled: (field) => !viewId.value
+  }
+]
+</script>
+
+<style lang="scss" scoped></style>

+ 6 - 6
src/views/system/dict/index.vue

@@ -1,11 +1,11 @@
 <template>
 <template>
   <div class="main animate__animated animate__backInRight" v-loading="loading">
   <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-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">
+    <custom-button-bar :fields="buttonFields" @create="toAdd"></custom-button-bar>
+    <custom-table :data="data" :fields="fields" @query="search" :total="total" :opera="opera" @dict="toDict" @update="toEdit" @delete="toDelete">
       <template #is_use="{ row }">
       <template #is_use="{ row }">
-        <el-tag v-if="row.is_use == '0'" type="success">启用</el-tag>
-        <el-tag v-else type="info">禁用</el-tag>
+        <el-tag v-if="row.is_use == '0'" type="success">{{ $t('common.is_use_abled') }}</el-tag>
+        <el-tag v-else type="info">{{ $t('common.is_use_disabled') }}</el-tag>
       </template>
       </template>
     </custom-table>
     </custom-table>
     <el-dialog v-model="dialog.show" :title="dialog.title" :destroy-on-close="false" @close="toClose" :top="dialog.top">
     <el-dialog v-model="dialog.show" :title="dialog.title" :destroy-on-close="false" @close="toClose" :top="dialog.top">
@@ -45,10 +45,10 @@ const fields = [
 ]
 ]
 const opera = [
 const opera = [
   { label: t('common.dict'), method: 'dict' },
   { label: t('common.dict'), method: 'dict' },
-  { label: t('common.update'), method: 'edit' },
+  { label: t('common.update'), method: 'update' },
   { label: t('common.delete'), method: 'delete', confirm: true, type: 'danger' }
   { label: t('common.delete'), method: 'delete', confirm: true, type: 'danger' }
 ]
 ]
-const buttonFields = [{ label: t('common.add'), method: 'add' }]
+const buttonFields = [{ label: t('common.create'), method: 'create' }]
 let skip = 0
 let skip = 0
 let limit = inject('limit')
 let limit = inject('limit')
 const total = ref(0)
 const total = ref(0)

+ 7 - 7
src/views/system/dictData/index.vue

@@ -1,11 +1,11 @@
 <template>
 <template>
   <div class="main animate__animated animate__backInRight" v-loading="loading">
   <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-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" @edit="toEdit" @delete="toDelete">
+    <custom-button-bar :fields="buttonFields" @create="toAdd"></custom-button-bar>
+    <custom-table :data="data" :fields="fields" @query="search" :total="total" :opera="opera" @update="toEdit" @delete="toDelete">
       <template #is_use="{ row }">
       <template #is_use="{ row }">
-        <el-tag v-if="row.is_use == '0'" type="success">启用</el-tag>
-        <el-tag v-else type="info">禁用</el-tag>
+        <el-tag v-if="row.is_use == '0'" type="success">{{ $t('common.is_use_abled') }}</el-tag>
+        <el-tag v-else type="info">{{ $t('common.is_use_disabled') }}</el-tag>
       </template>
       </template>
     </custom-table>
     </custom-table>
     <el-dialog v-model="dialog" :title="$t('pages.dictData.dialogTitle')" :destroy-on-close="false" @close="toClose" width="30%">
     <el-dialog v-model="dialog" :title="$t('pages.dictData.dialogTitle')" :destroy-on-close="false" @close="toClose" width="30%">
@@ -34,10 +34,10 @@ const fields = [
   { label: t('pages.dict.is_use'), model: 'is_use', format: (i) => getDict(i), custom: true }
   { label: t('pages.dict.is_use'), model: 'is_use', format: (i) => getDict(i), custom: true }
 ]
 ]
 const opera = [
 const opera = [
-  { label: t('common.update'), method: 'edit' },
+  { label: t('common.update'), method: 'update' },
   { label: t('common.delete'), method: 'delete', confirm: true, type: 'danger' }
   { label: t('common.delete'), method: 'delete', confirm: true, type: 'danger' }
 ]
 ]
-const buttonFields = [{ label: t('common.add'), method: 'add' }]
+const buttonFields = [{ label: t('common.create'), method: 'create' }]
 let skip = 0
 let skip = 0
 let limit = inject('limit')
 let limit = inject('limit')
 const total = ref(0)
 const total = ref(0)
@@ -67,7 +67,7 @@ onMounted(async () => {
 const search = async (query = { skip: 0, limit }) => {
 const search = async (query = { skip: 0, limit }) => {
   const info = { skip: query.skip, limit: query.limit, ...searchForm.value, code: codeInfo.value.code }
   const info = { skip: query.skip, limit: query.limit, ...searchForm.value, code: codeInfo.value.code }
   const res = await store.query(info)
   const res = await store.query(info)
-  if (res.errcode == '0') {
+  if ($checkRes(res)) {
     data.value = res.data
     data.value = res.data
     total.value = res.total
     total.value = res.total
   }
   }

+ 1 - 1
src/views/system/menus/index.vue

@@ -2,7 +2,7 @@
   <div class="main animate__animated animate__backInRight">
   <div class="main animate__animated animate__backInRight">
     <el-row>
     <el-row>
       <el-col :span="24" style="text-align: right; padding: 10px">
       <el-col :span="24" style="text-align: right; padding: 10px">
-        <el-button type="primary" size="small" @click="toAdd()">{{ $t('common.add') }}</el-button>
+        <el-button type="primary" size="small" @click="toAdd()">{{ $t('common.create') }}</el-button>
       </el-col>
       </el-col>
       <el-col :span="24">
       <el-col :span="24">
         <menu-table></menu-table>
         <menu-table></menu-table>

+ 1 - 1
src/views/system/role/index.vue

@@ -2,7 +2,7 @@
   <div class="main animate__animated animate__backInRight" v-loading="loading">
   <div class="main animate__animated animate__backInRight" v-loading="loading">
     <el-row style="padding: 5px">
     <el-row style="padding: 5px">
       <el-col :span="24" style="text-align: right">
       <el-col :span="24" style="text-align: right">
-        <el-button type="primary" @click="toAdd" v-method="'add'">{{ $t('common.add') }}</el-button>
+        <el-button type="primary" @click="toAdd" v-method="'add'">{{ $t('common.create') }}</el-button>
       </el-col>
       </el-col>
     </el-row>
     </el-row>
     <el-row>
     <el-row>

+ 2 - 1
src/views/system/role/parts/form.vue

@@ -45,7 +45,8 @@ onMounted(() => {
   for (const key of treeSelected) {
   for (const key of treeSelected) {
     roleTree.value.setChecked(key, true)
     roleTree.value.setChecked(key, true)
   }
   }
-  console.log('init')
+  const selected = roleTree.value.getCheckedKeys()
+  if (!selected.includes('home')) roleTree.value.setChecked('home', true)
 })
 })
 /**
 /**
  * 处理菜单:将目录,菜单,子页面,权限统一转成 {name,code}形式,code为唯一值
  * 处理菜单:将目录,菜单,子页面,权限统一转成 {name,code}形式,code为唯一值

+ 1 - 1
src/views/system/tags/index.vue

@@ -104,7 +104,7 @@ const opera = [
   { label: t('common.update'), method: 'edit' },
   { label: t('common.update'), method: 'edit' },
   { label: t('common.delete'), method: 'delete', confirm: true, type: 'danger' }
   { label: t('common.delete'), method: 'delete', confirm: true, type: 'danger' }
 ]
 ]
-const buttonFields = [{ label: t('common.add'), method: 'add' }]
+const buttonFields = [{ label: t('common.create'), method: 'add' }]
 let skip = 0
 let skip = 0
 let limit = inject('limit')
 let limit = inject('limit')
 const total = ref(0)
 const total = ref(0)

+ 43 - 7
src/views/user/admin/index.vue

@@ -4,8 +4,8 @@
     <custom-button-bar :fields="buttonFields" @add="toAdd"></custom-button-bar>
     <custom-button-bar :fields="buttonFields" @add="toAdd"></custom-button-bar>
     <custom-table :data="data" :fields="fields" @search="search" :total="total" :opera="opera" @edit="toEdit" @changeUse="toChangeUse" @delete="toDelete" @rp="toResetPwd">
     <custom-table :data="data" :fields="fields" @search="search" :total="total" :opera="opera" @edit="toEdit" @changeUse="toChangeUse" @delete="toDelete" @rp="toResetPwd">
       <template #is_use="{ row }">
       <template #is_use="{ row }">
-        <el-tag v-if="row.is_use == '0'" type="success">启用</el-tag>
-        <el-tag v-else type="info">禁用</el-tag>
+        <el-tag v-if="row.is_use == '0'" type="success">{{ $t('common.is_use_abled') }}</el-tag>
+        <el-tag v-else type="info">{{ $t('common.is_use_disabled') }}</el-tag>
       </template>
       </template>
     </custom-table>
     </custom-table>
     <el-dialog v-model="dialog" :title="$t('pages.menus.dialogTitle')" :destroy-on-close="false" @close="toClose">
     <el-dialog v-model="dialog" :title="$t('pages.menus.dialogTitle')" :destroy-on-close="false" @close="toClose">
@@ -16,22 +16,27 @@
         <template #role>
         <template #role>
           <el-option v-for="i in roleList" :key="i._id" :label="i.name" :value="i.code"></el-option>
           <el-option v-for="i in roleList" :key="i._id" :label="i.name" :value="i.code"></el-option>
         </template>
         </template>
+        <template #dept>
+          <el-tree-select :props="defaultProps" node-key="_id" accordion v-model="form.dept" :data="deptList" check-strictly :render-after-expand="false" />
+        </template>
       </custom-form>
       </custom-form>
     </el-dialog>
     </el-dialog>
   </div>
   </div>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
+import { DeptStore } from '@/store/api/system/dept'
 import { AdminStore } from '@/store/api/user/admin'
 import { AdminStore } from '@/store/api/user/admin'
 import { LoginStore } from '@/store/api/login'
 import { LoginStore } from '@/store/api/login'
 import { RoleStore } from '@/store/api/system/role'
 import { RoleStore } from '@/store/api/system/role'
 import { DictDataStore } from '@/store/api/system/dictData'
 import { DictDataStore } from '@/store/api/system/dictData'
-import { cloneDeep, get } from 'lodash-es'
+import { cloneDeep, get, omit, isArray } from 'lodash-es'
 const $checkRes = inject('$checkRes')
 const $checkRes = inject('$checkRes')
 const store = AdminStore()
 const store = AdminStore()
 const loginStore = LoginStore()
 const loginStore = LoginStore()
 const dictDataStore = DictDataStore()
 const dictDataStore = DictDataStore()
 const roleStore = RoleStore()
 const roleStore = RoleStore()
+const deptStore = DeptStore()
 const { t } = useI18n()
 const { t } = useI18n()
 const loading = ref(false)
 const loading = ref(false)
 let skip = 0
 let skip = 0
@@ -49,6 +54,7 @@ const fields = [
   { label: t('pages.admin.account'), model: 'account', filter: true },
   { label: t('pages.admin.account'), model: 'account', filter: true },
   { label: t('pages.admin.nick_name'), model: 'nick_name' },
   { label: t('pages.admin.nick_name'), model: 'nick_name' },
   { label: t('pages.admin.role'), model: 'role', format: (i) => getRole(i) },
   { label: t('pages.admin.role'), model: 'role', format: (i) => getRole(i) },
+  { label: t('所属部门'), model: 'dept', format: (i) => getDept(i) },
   { label: t('pages.admin.is_super'), model: 'is_super', format: (i) => (i === '0' ? t('common.yes') : t('common.no')) },
   { label: t('pages.admin.is_super'), model: 'is_super', format: (i) => (i === '0' ? t('common.yes') : t('common.no')) },
   { label: t('pages.admin.is_use'), model: 'is_use', format: (i) => getDict(i), custom: true }
   { label: t('pages.admin.is_use'), model: 'is_use', format: (i) => getDict(i), custom: true }
 ]
 ]
@@ -74,7 +80,7 @@ const opera = [
   },
   },
   { label: t('common.delete'), method: 'delete', confirm: true, type: 'danger', display: (i) => i.is_super !== '0' }
   { label: t('common.delete'), method: 'delete', confirm: true, type: 'danger', display: (i) => i.is_super !== '0' }
 ]
 ]
-const buttonFields = [{ label: t('common.add'), method: 'add' }]
+const buttonFields = [{ label: t('common.create'), method: 'add' }]
 const searchForm = ref({})
 const searchForm = ref({})
 const search = async (query = { skip: 0, limit }) => {
 const search = async (query = { skip: 0, limit }) => {
   const info = { skip: query.skip, limit: query.limit, ...searchForm.value }
   const info = { skip: query.skip, limit: query.limit, ...searchForm.value }
@@ -86,6 +92,11 @@ const search = async (query = { skip: 0, limit }) => {
 }
 }
 const isUseList = ref([])
 const isUseList = ref([])
 const roleList = ref([])
 const roleList = ref([])
+const deptList = ref([])
+const defaultProps = {
+  children: 'children',
+  label: 'name'
+}
 const searchOther = async () => {
 const searchOther = async () => {
   const result = await dictDataStore.query({ code: 'isUse', is_use: '0' })
   const result = await dictDataStore.query({ code: 'isUse', is_use: '0' })
   if ($checkRes(result)) {
   if ($checkRes(result)) {
@@ -95,6 +106,10 @@ const searchOther = async () => {
   if ($checkRes(roleResult)) {
   if ($checkRes(roleResult)) {
     roleList.value = roleResult.data
     roleList.value = roleResult.data
   }
   }
+  const deptResult = await deptStore.query({ status: '0' })
+  if ($checkRes(deptResult)) {
+    deptList.value = deptResult.data
+  }
 }
 }
 
 
 const toDelete = async (data) => {
 const toDelete = async (data) => {
@@ -137,17 +152,20 @@ const formFieldsForUpdate = [
   { label: t('pages.admin.nick_name'), model: 'nick_name' },
   { label: t('pages.admin.nick_name'), model: 'nick_name' },
   { label: t('pages.admin.is_use'), model: 'is_use', type: 'radio' }
   { label: t('pages.admin.is_use'), model: 'is_use', type: 'radio' }
 ]
 ]
-const roleField = { label: t('pages.admin.role'), model: 'role', type: 'select' }
+const notSuperFields = [
+  { label: t('所属部门'), model: 'dept', custom: true },
+  { label: t('pages.admin.role'), model: 'role', type: 'select' }
+]
 const toAdd = () => {
 const toAdd = () => {
   formFields.value = formFieldsForCreate
   formFields.value = formFieldsForCreate
-  formFields.value.push(roleField)
+  formFields.value.push(...notSuperFields)
   form.value = cloneDeep(defaultForm)
   form.value = cloneDeep(defaultForm)
   dialog.value = true
   dialog.value = true
 }
 }
 const toEdit = (data) => {
 const toEdit = (data) => {
   formFields.value = cloneDeep(formFieldsForUpdate)
   formFields.value = cloneDeep(formFieldsForUpdate)
   form.value = data
   form.value = data
-  if (data.is_super !== '0') formFields.value.push(roleField)
+  if (data.is_super !== '0') formFields.value.push(...notSuperFields)
   dialog.value = true
   dialog.value = true
 }
 }
 const toSave = async () => {
 const toSave = async () => {
@@ -160,6 +178,24 @@ const toSave = async () => {
     toClose()
     toClose()
   }
   }
 }
 }
+const getDept = (data) => {
+  const resetList = (list) => {
+    const result = []
+    for (const i of list) {
+      const d = omit(i, ['children'])
+      result.push(d)
+      if (isArray(i.children) && i.children.length > 0) {
+        const ml = resetList(i.children)
+        result.push(...ml)
+      }
+    }
+    return result
+  }
+  const odDeptList = resetList(deptList.value)
+  const result = odDeptList.find((f) => f._id === data)
+  if (!result) return '暂无'
+  return result.name
+}
 const getRole = (data) => {
 const getRole = (data) => {
   const res = roleList.value.find((f) => f.code === data)
   const res = roleList.value.find((f) => f.code === data)
   return get(res, 'name')
   return get(res, 'name')

+ 1 - 1
vite.config.js

@@ -32,7 +32,7 @@ export default defineConfig(({ mode }) => {
          */
          */
         [env.VITE_APP_BASE_API]: {
         [env.VITE_APP_BASE_API]: {
           changeOrigin: true,
           changeOrigin: true,
-          target: 'http://localhost:19700'
+          target: 'http://localhost:9700'
         }
         }
       }
       }
     },
     },