Browse Source

完成角色管理以及侧边栏路由

@sun-chaoqun 2 years ago
parent
commit
d6ecc2855f

+ 1 - 1
auto-imports.d.ts

@@ -4,5 +4,5 @@
 // Generated by unplugin-auto-import
 export {}
 declare global {
-
+  const ElMessage: typeof import('element-plus/es')['ElMessage']
 }

+ 11 - 0
package-lock.json

@@ -11,6 +11,7 @@
         "@element-plus/icons-vue": "^2.1.0",
         "axios": "^1.3.4",
         "element-plus": "^2.3.0",
+        "js-md5": "^0.7.3",
         "nprogress": "^0.2.0",
         "pinia": "^2.0.33",
         "vue": "^3.2.45",
@@ -2994,6 +2995,11 @@
         "node": "*"
       }
     },
+    "node_modules/js-md5": {
+      "version": "0.7.3",
+      "resolved": "https://registry.npmmirror.com/js-md5/-/js-md5-0.7.3.tgz",
+      "integrity": "sha512-ZC41vPSTLKGwIRjqDh8DfXoCrdQIyBgspJVPXHBGu4nZlAEvG3nf+jO9avM9RmLiGakg7vz974ms99nEV0tmTQ=="
+    },
     "node_modules/js-sdsl": {
       "version": "4.3.0",
       "resolved": "https://registry.npmmirror.com/js-sdsl/-/js-sdsl-4.3.0.tgz",
@@ -6716,6 +6722,11 @@
         }
       }
     },
+    "js-md5": {
+      "version": "0.7.3",
+      "resolved": "https://registry.npmmirror.com/js-md5/-/js-md5-0.7.3.tgz",
+      "integrity": "sha512-ZC41vPSTLKGwIRjqDh8DfXoCrdQIyBgspJVPXHBGu4nZlAEvG3nf+jO9avM9RmLiGakg7vz974ms99nEV0tmTQ=="
+    },
     "js-sdsl": {
       "version": "4.3.0",
       "resolved": "https://registry.npmmirror.com/js-sdsl/-/js-sdsl-4.3.0.tgz",

+ 1 - 0
package.json

@@ -12,6 +12,7 @@
     "@element-plus/icons-vue": "^2.1.0",
     "axios": "^1.3.4",
     "element-plus": "^2.3.0",
+    "js-md5": "^0.7.3",
     "nprogress": "^0.2.0",
     "pinia": "^2.0.33",
     "vue": "^3.2.45",

+ 3 - 4
src/App.vue

@@ -4,10 +4,9 @@ import zh from 'element-plus/lib/locale/lang/zh-cn'
 </script>
 
 <template>
-  <!-- <ElConfigProvider :locale="zh">
-    
-  </ElConfigProvider> -->
-  <router-view></router-view>
+  <ElConfigProvider :locale="zh">
+    <router-view></router-view>
+  </ElConfigProvider>
 </template>
 
 <style scoped></style>

+ 3 - 3
src/api/index.ts

@@ -43,9 +43,9 @@ class RequestHttp {
           background: 'rgba(0, 0, 0, 0.7)'
         })
         // 加入token
-        if (globalStore.GET_User_tokey) {
-          config.headers['User_tokey'] = globalStore.GET_User_tokey
-        }
+        // if (globalStore.GET_User_tokey) {
+        //   config.headers['User_tokey'] = globalStore.GET_User_tokey
+        // }
         return config
       },
       (err: any) => err

+ 2 - 2
src/api/interface/index.ts

@@ -28,11 +28,11 @@ export enum ContentType {
 
 // * 请求响应参数(不包含data)
 export interface Result {
-  code: string
+  Code: string
   msg: string
 }
 
 // * 请求响应参数(包含data)
 export interface ResultData<T = any> extends Result {
-  data: T
+  Data: T
 }

+ 16 - 0
src/api/role/index.ts

@@ -0,0 +1,16 @@
+import $http from '../index'
+
+// 获取列表
+export const User_Power_List = (params: any) => $http.post('/api/user/Power/List', params)
+// 权限系统列表
+export const User_Sys_List = (params: any) => $http.post('/api/user/Power/Sys_List', params)
+// 弹框菜单
+export const Menu_List = (params: any): any => $http.post('/api/user/Menu/List', params)
+// 左侧菜单栏
+export const Menu_User_List = (params: any) => $http.post('/api/user/Menu/User_List', params)
+// 添加角色名
+export const User_Power_Add = (params: any): any => $http.post('/api/user/Power/Add', params)
+// 编辑角色名
+export const User_Power_Edit = (params: any): any => $http.post('/api/user/Power/Edit', params)
+// 删除角色名
+export const User_Power_Del = (params: any): any => $http.post('/api/user/Power/Del', params)

+ 14 - 2
src/api/user/index.ts

@@ -1,3 +1,15 @@
 import $http from '../index'
-
-export const Login_verification = (params: any) => $http.post('/user/Login_verification', params)
+// 登录
+export const Login_verification = (params: any) => $http.post('/api/user/Login_verification', params)
+// 获取列表
+export const User_List = (params: any) => $http.post('/api/user/User/List', params)
+// 添加用户
+export const User_Add = (params: any) => $http.post('/api/user/User/Add', params)
+// 编辑用户
+export const User_Edit = (params: any) => $http.post('/api/user/User/Edit', params)
+// 删除用户
+export const User_Del = (params: any) => $http.post('/api/user/User/Del', params)
+//部门列表
+export const User_Dept_List = (params?: any) => $http.post('/api/user/Dept/List', params)
+//岗位列表
+export const User_Post_List = (params?: any) => $http.post('/api/user/Post/List', params)

+ 31 - 0
src/assets/iconfont.css

@@ -0,0 +1,31 @@
+@font-face {
+  font-family: "iconfont"; /* Project id 3967191 */
+  src: url('iconfont.woff2?t=1679391620275') format('woff2'),
+       url('iconfont.woff?t=1679391620275') format('woff'),
+       url('iconfont.ttf?t=1679391620275') format('truetype');
+}
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.icon-money:before {
+  content: "\e663";
+}
+
+.icon-moneybag:before {
+  content: "\e7d1";
+}
+
+.icon-moneycollect:before {
+  content: "\e7cd";
+}
+
+.icon-money-funds:before {
+  content: "\e831";
+}
+

+ 10 - 4
src/components/TableBase/index.vue

@@ -1,5 +1,5 @@
 <script setup lang="ts">
-import { ref } from 'vue'
+import { ref, onMounted } from 'vue'
 import Pagination from './components/Pagination.vue'
 import { useTable } from '@/hooks/useTable'
 import { ElTable, TableProps } from 'element-plus'
@@ -28,7 +28,7 @@ const props = withDefaults(defineProps<ProTableProps>(), {
   selectId: 'id',
   searchCol: () => ({ xs: 1, sm: 2, md: 2, lg: 3, xl: 4 })
 })
-console.log(props)
+// console.log(props)
 
 // 表格操作 Hooks
 const {
@@ -36,7 +36,7 @@ const {
   pageable,
   // searchParam,
   // searchInitParam,
-  // getTableList,
+  getTableList,
   // search,
   // reset,
   handleSizeChange,
@@ -45,7 +45,13 @@ const {
 // 接收 columns 并设置为响应式
 const tableColumns = ref<ColumnProps[]>(props.columns)
 
-console.log(tableData, tableColumns)
+onMounted(() => {
+  getTableList()
+})
+
+defineExpose({
+  getTableList
+})
 </script>
 
 <template>

+ 2 - 22
src/hooks/useTable.ts

@@ -30,28 +30,7 @@ export const useTable = (
 ) => {
   const state = reactive<Table>({
     // 表格数据
-    tableData: [
-      {
-        date: '2016-05-03',
-        name: 'Tom',
-        address: 'No. 189, Grove St, Los Angeles'
-      },
-      {
-        date: '2016-05-02',
-        name: 'Tom',
-        address: 'No. 189, Grove St, Los Angeles'
-      },
-      {
-        date: '2016-05-04',
-        name: 'Tom',
-        address: 'No. 189, Grove St, Los Angeles'
-      },
-      {
-        date: '2016-05-01',
-        name: 'Tom',
-        address: 'No. 189, Grove St, Los Angeles'
-      }
-    ],
+    tableData: [],
     // 分页数据
     pageable: {
       // 当前页数
@@ -75,6 +54,7 @@ export const useTable = (
     const res = await requestApi(initParam)
     dataCallback && dataCallback(res)
     console.log(res)
+    state.tableData = res.Data.Data
   }
 
   if (isPagination) {

+ 3 - 0
src/layouts/Header/index.vue

@@ -1,8 +1,11 @@
 <script setup lang="ts">
 import { useRouter } from 'vue-router'
+import { GlobalStore } from '@/stores/index'
+const globalStore = GlobalStore()
 const router = useRouter()
 const logOut = () => {
   localStorage.clear()
+  globalStore.SET_User_Tokey('')
   router.replace('/login')
 }
 </script>

+ 2 - 2
src/layouts/Main/index.vue

@@ -3,13 +3,13 @@ import { ref, provide } from 'vue'
 import { KeepAliveStore } from '@/stores/modules/keepAlive'
 const isRouterShow = ref(true)
 const refreshCurrentPage = (val: boolean) => {
-  console.log(val)
+  // console.log(val)
   isRouterShow.value = val
 }
 provide('refresh', refreshCurrentPage)
 
 const keepAliveStore = KeepAliveStore()
-console.log(keepAliveStore)
+// console.log(keepAliveStore)
 </script>
 
 <template>

+ 2 - 2
src/router/index.ts

@@ -16,9 +16,9 @@ router.beforeEach((to, from, next) => {
   const store = GlobalStore()
   let title = to.meta.title
   title && (document.title = title as string)
-  console.log(to, from)
+  // console.log(to, from)
 
-  console.log(store.GET_User_tokey)
+  // console.log(store.GET_User_tokey)
 
   if (store.GET_User_tokey && to.path !== '/login') {
     next()

+ 24 - 0
src/router/modules/staticRouter.ts

@@ -35,6 +35,30 @@ export const staticRouter: RouteRecordRaw[] = [
         meta: {
           title: '账户管理'
         }
+      },
+      {
+        path: '/salary',
+        name: 'Salary',
+        component: () => import('@/views/salary/Salary.vue'),
+        meta: {
+          title: '薪资管理'
+        }
+      },
+      {
+        path: '/salaryCount',
+        name: 'SalaryCount',
+        component: () => import('@/views/salary/SalaryCount.vue'),
+        meta: {
+          title: '薪资统计'
+        }
+      },
+      {
+        path: '/salaryMy',
+        name: 'SalaryMy',
+        component: () => import('@/views/salary/SalaryMy.vue'),
+        meta: {
+          title: '我的薪资'
+        }
       }
     ]
   },

+ 19 - 7
src/style.scss

@@ -27,13 +27,25 @@ body,
 }
 
 ::-webkit-scrollbar {
-  width: 2px;
-}
-::-webkit-scrollbar-thumb {
-  border-radius: 2px;
-  background: rgba(0, 0, 0, 0.2);
+  width: 3px;
+  height: 3px;
 }
 ::-webkit-scrollbar-track {
-  border-radius: 0;
-  background: rgba(0, 0, 0, 0.1);
+  width: 3px;
+  background-color: #f9f9f9;
 }
+::-webkit-scrollbar-thumb {
+  background-color: #999;
+}
+
+// ::-webkit-scrollbar {
+//   width: 2px;
+// }
+// ::-webkit-scrollbar-thumb {
+//   border-radius: 2px;
+//   background: rgba(0, 0, 0, 0.2);
+// }
+// ::-webkit-scrollbar-track {
+//   border-radius: 0;
+//   background: rgba(0, 0, 0, 0.1);
+// }

+ 10 - 0
src/typings/config.ts

@@ -0,0 +1,10 @@
+export interface RetrunData {
+  Code: string
+  Data: any
+  [props: string]: string
+}
+
+export interface InLogin {
+  username: string
+  password: string
+}

+ 1 - 0
src/typings/plugins.d.ts

@@ -1 +1,2 @@
 declare module 'nprogress'
+declare module 'js-md5'

+ 3 - 0
src/utils/common.ts

@@ -0,0 +1,3 @@
+import md5 from 'js-md5'
+
+export const fnMd5 = () => md5

+ 33 - 18
src/views/Index.vue

@@ -2,6 +2,15 @@
 import SubMenu from '@/layouts/Menu/SubMenu.vue'
 import Main from '@/layouts/Main/index.vue'
 import Header from '@/layouts/Header/index.vue'
+import { Menu_User_List } from '@/api/role/index'
+import { GlobalStore } from '@/stores/index'
+// import md5 from 'js-md5'
+// console.log(md5('123456'))
+const globalStore = GlobalStore()
+const getMenu = async () => {
+  const res = await Menu_User_List({ User_tokey: globalStore.GET_User_tokey })
+}
+getMenu()
 const routerList = [
   {
     path: '/home',
@@ -22,8 +31,8 @@ const routerList = [
     },
     children: [
       {
-        path: '/roles',
-        name: 'Roles',
+        path: '/users',
+        name: 'Users',
         meta: {
           icon: 'Memo',
           title: '账户管理',
@@ -31,8 +40,8 @@ const routerList = [
         }
       },
       {
-        path: '/users',
-        name: 'Users',
+        path: '/roles',
+        name: 'Roles',
         meta: {
           icon: 'UserFilled',
           title: '角色管理',
@@ -52,39 +61,38 @@ const routerList = [
     }
   },
   {
-    path: '',
+    path: '/salary',
     name: '薪资管理',
-    iocn: '',
     meta: {
       icon: 'HomeFilled',
-      title: '首页',
+      title: '薪资管理',
       isKeepAlive: true
     },
     children: [
       {
-        path: '',
+        path: '/salary',
         name: '薪资管理',
         meta: {
           icon: 'HomeFilled',
-          title: '首页',
+          title: '薪资管理',
           isKeepAlive: true
         }
       },
       {
-        path: '',
+        path: '/salaryCount',
         name: '薪资统计',
         meta: {
           icon: 'HomeFilled',
-          title: '首页',
+          title: '薪资统计',
           isKeepAlive: true
         }
       },
       {
-        path: '',
+        path: '/salaryMy',
         name: '我的薪资',
         meta: {
           icon: 'HomeFilled',
-          title: '首页',
+          title: '我的薪资',
           isKeepAlive: true
         }
       }
@@ -130,8 +138,16 @@ const routerList = [
 <template>
   <el-container class="home-container">
     <el-aside width="210px">
+      <!-- <h1 style="color: #fff; text-align: center; margin: 20px; font-size: 32px">ERP系统</h1> -->
       <el-scrollbar class="scrollbar">
-        <el-menu :unique-opened="true" :collapse-transition="false" text-color="#303133">
+        <!-- text-color="#303133" -->
+        <el-menu
+          :unique-opened="true"
+          :collapse-transition="false"
+          active-text-color="#ffd04b"
+          text-color="#fff"
+          background-color="#091215"
+        >
           <SubMenu :menu-list="routerList"></SubMenu>
         </el-menu>
       </el-scrollbar>
@@ -154,12 +170,11 @@ const routerList = [
       border-right: none;
     }
   }
-  // .el-aside {
-  //   background-color: #f2f2f2;
-  // }
+  .el-aside {
+    background-color: #091215;
+  }
   .el-header {
     display: flex;
-    // justify-content: center;
     align-items: center;
     border-bottom: solid 1px var(--el-menu-border-color);
   }

+ 9 - 2
src/views/Login.vue

@@ -2,12 +2,15 @@
 import { reactive, ref } from 'vue'
 import { ElNotification } from 'element-plus'
 import type { FormInstance, FormRules } from 'element-plus'
+import type { InLogin } from '@/typings/config'
 import { User, View, Lock } from '@element-plus/icons-vue'
 import { Login_verification } from '@/api/user/index'
 import { useRouter } from 'vue-router'
+import { GlobalStore } from '@/stores/index'
 const router = useRouter()
+const globalStore = GlobalStore()
 const ruleFormRef = ref<FormInstance>()
-const ruleForm = reactive({
+const ruleForm = reactive<InLogin>({
   username: '',
   password: ''
 })
@@ -29,7 +32,6 @@ const submitForm = (formEl: FormInstance | undefined) => {
   if (!formEl) return
   formEl.validate(async valid => {
     if (valid) {
-      // console.log(ruleForm)
       let res: any = {}
       res = await Login_verification({ bzd_username: ruleForm.username, bzd_password: ruleForm.password })
       console.log(res)
@@ -40,6 +42,7 @@ const submitForm = (formEl: FormInstance | undefined) => {
           position: 'bottom-right'
         })
         localStorage.setItem('User_tokey', res.Data)
+        globalStore.SET_User_Tokey(res.Data)
         router.replace('/')
       }
     } else {
@@ -58,6 +61,10 @@ const changeType = () => {
 <template>
   <div class="login">
     <div class="content">
+      <div class="title">
+        <h2>宝智达ERP系统</h2>
+        <span>ShenZhen Baozhida Technology ERP. system</span>
+      </div>
       <el-form ref="ruleFormRef" :model="ruleForm" :rules="rules">
         <el-form-item label="账号:" prop="username">
           <el-input v-model="ruleForm.username" type="text" :prefix-icon="User" />

+ 150 - 84
src/views/account/roles/Roles.vue

@@ -1,126 +1,192 @@
 <script setup lang="ts">
+import { ref, reactive, nextTick } from 'vue'
 import TableBase from '@/components/TableBase/index.vue'
-import { ColumnProps } from '@/components/TableBase/interface/index'
-import { Edit, Delete } from '@element-plus/icons-vue'
+import type { ColumnProps } from '@/components/TableBase/interface/index'
+import { User_Power_List, User_Sys_List, Menu_List, User_Power_Add, User_Power_Del } from '@/api/role/index'
+import { Edit, Delete, Operation } from '@element-plus/icons-vue'
+import Dialog from '@/components/dialog/Dialog.vue'
 import Drawer from '@/components/Drawer/index.vue'
-import { ref, reactive } from 'vue'
-const drawerRef = ref()
-const action = ref(true)
-const formLabelWidth = ref('80px')
-const form = reactive({
-  username: '',
-  password: '',
-  user: '',
-  department: '',
-  post: ''
-})
+import { GlobalStore } from '@/stores/index'
+import type { FormInstance, FormRules } from 'element-plus'
+import { ElNotification, ElMessageBox, ElMessage } from 'element-plus'
+
+const globalStore = GlobalStore()
+const dialog = ref()
+const TableRef = ref()
+const DialogOpen = async (row: any) => {
+  console.log(row)
+  await getSysList()
+  dialog.value.DialogOpen()
+}
+const checkList = ref()
 const columns: ColumnProps[] = [
   { type: 'index', label: '#', width: 80 },
-  { prop: 'date', label: '时间', width: 120, search: { el: 'input' } },
-  {
-    prop: 'name',
-    label: '姓名',
-    width: 120,
-    sortable: true,
-    // enum: getUserGender,
-    search: { el: 'select' },
-    fieldNames: { label: 'genderLabel', value: 'genderValue' }
-  },
-  { prop: 'address', label: '身份证号' },
-  { prop: 'email', label: '邮箱' },
-  { prop: 'address', label: '居住地址' },
-  {
-    prop: 'status',
-    label: '用户状态',
-    width: 120,
-    sortable: true,
-    tag: true,
-    // enum: getUserStatus,
-    search: { el: 'select' },
-    fieldNames: { label: 'userLabel', value: 'userStatus' }
-  },
-  { prop: 'createTime', label: '创建时间', width: 180 },
+  { prop: 'T_name', label: '姓名' },
+  { prop: 'T_id', label: 'id' },
   { prop: 'operation', label: '操作', width: 200, fixed: 'right' }
 ]
-const requestApi = async () => {
-  return false
+
+interface InSys {
+  T_sys: string
+  T_name: string
+  children: any
 }
 
-const openDrawer = () => {
-  drawerRef.value.closeDrawer()
-  console.log(drawerRef.value)
+let SysList = ref<InSys[]>([])
+const getSysList = async () => {
+  const { Data } = await User_Sys_List({ User_tokey: globalStore.GET_User_tokey })
+  SysList.value = Data as InSys[]
+}
+// let MenuList = reactive([])
+const getMenuList = async (code: string) => {
+  const res = await Menu_List({ User_tokey: globalStore.GET_User_tokey, T_code: code })
+  const sys = SysList.value.find(item => item.T_sys === code) as InSys
+  console.log(SysList, sys, res)
+  sys.children = res.Data.Data[0].Children
+}
+const submitUserRole = () => {
+  console.log(checkList)
+}
+const initParam = {
+  User_tokey: globalStore.GET_User_tokey,
+  page: 1,
+  page_z: 10
 }
 
+// 添加角色
+const drawerRef = ref()
+const ruleFormRef = ref<FormInstance>()
+const formLabelWidth = ref('80px')
+const isNew = ref(true)
+const rules = reactive<FormRules>({
+  name: [{ required: true, message: '请输入角色名称', trigger: 'blur' }]
+})
 type Fn = () => void
 const callbackDrawer = (done: Fn) => {
-  console.log('触发回调')
+  resetForm(ruleFormRef.value)
   done()
 }
+const openDrawer = (type: string, row?: any) => {
+  isNew.value = type === 'new' ? true : false
+  nextTick(() => {
+    !isNew.value && (form.name = row.T_name)
+  })
+  drawerRef.value.closeDrawer()
+}
+const form = reactive({
+  name: ''
+})
+const resetForm = (formEl: FormInstance | undefined) => {
+  if (!formEl) return
+  formEl.resetFields()
+}
+const AddUserName = (formEl: FormInstance | undefined) => {
+  if (!formEl) return
+  formEl.validate(async valid => {
+    if (valid) {
+      let res = await User_Power_Add({ User_tokey: globalStore.GET_User_tokey, T_name: form.name })
+      if (res.Code === 200) {
+        ElNotification.success({
+          title: '添加角色',
+          message: '添加成功!',
+          position: 'bottom-right'
+        })
+        drawerRef.value.closeDrawer()
+        TableRef.value.getTableList()
+      }
+    } else {
+      console.log('error submit!')
+      return false
+    }
+  })
+}
+
+// 删除
+const UserDelete = (row: any) => {
+  ElMessageBox.confirm('您确定要删除吗?', '警告', {
+    confirmButtonText: 'OK',
+    cancelButtonText: 'Cancel',
+    type: 'warning'
+  })
+    .then(async () => {
+      const res = await User_Power_Del({ User_tokey: globalStore.GET_User_tokey, T_id: row.T_id })
+      console.log(res)
+    })
+    .catch(() => {
+      ElMessage({
+        type: 'warning',
+        message: '取消成功!'
+      })
+    })
+}
 </script>
 
 <template>
-  <TableBase :columns="columns" :requestApi="requestApi">
+  <TableBase ref="TableRef" :columns="columns" :requestApi="User_Power_List" :initParam="initParam">
     <template #table-header>
       <div class="input-suffix">
         <el-row :gutter="20">
           <el-col :span="12">
-            <span class="ml-3 w-35 text-gray-600 inline-flex items-center">账户查询:</span>
+            <span class="ml-3 w-35 text-gray-600 inline-flex items-center">角色名:</span>
             <el-input type="text" class="w-50 m-2" />
             <el-button type="primary">搜索</el-button>
           </el-col>
-          <el-col :span="6" :offset="6"><el-button type="primary" @click="openDrawer">添加</el-button></el-col>
+          <el-col :span="6" :offset="6"><el-button type="primary" @click="openDrawer('new')">添加</el-button></el-col>
         </el-row>
       </div>
     </template>
-    <template #right>
-      <el-button link type="primary" size="small" :icon="Edit">编辑</el-button>
-      <el-button link type="danger" size="small" :icon="Delete">删除</el-button>
+    <template #right="{ row }">
+      <el-button link type="primary" size="small" :icon="Edit" @click="openDrawer('edit', row)">编辑</el-button>
+      <el-button link type="success" size="small" :icon="Operation" @click="DialogOpen(row)">权限</el-button>
+      <el-button link type="danger" size="small" :icon="Delete" @click="UserDelete(row)">删除</el-button>
     </template>
   </TableBase>
+  <Dialog ref="dialog" width="80%">
+    <template #header>
+      <h3>编辑权限</h3>
+    </template>
+    <el-row :gutter="24">
+      <el-col :span="3"><div class="grid-content">功能模块</div></el-col>
+      <el-col :span="18"><div class="grid-content">权限</div></el-col>
+      <el-col :span="3"><div class="grid-content">操作</div></el-col>
+    </el-row>
+    <el-row :gutter="24" v-for="item in SysList" :key="item.T_sys">
+      <el-col :span="3"
+        ><div class="grid-content">
+          <el-button type="success" link @click="getMenuList(item.T_sys)">{{ item.T_name }}</el-button>
+        </div></el-col
+      >
+      <el-col :span="18"
+        ><div class="grid-content grid-active">
+          <el-checkbox-group v-model="checkList" v-if="item.children">
+            <el-checkbox :label="child.T_name" v-for="child in item.children" :key="'rr' + child.Id">{{
+              child.T_name
+            }}</el-checkbox>
+          </el-checkbox-group>
+        </div></el-col
+      >
+      <el-col :span="3"
+        ><div class="grid-content">
+          <el-button type="primary" @click="submitUserRole">提交</el-button>
+        </div></el-col
+      >
+    </el-row>
+  </Dialog>
   <Drawer ref="drawerRef" :handleClose="callbackDrawer">
     <template #header="{ params }">
-      <h4 :id="params.titleId" :class="params.titleClass">{{ action ? '添加' : '编辑' }} - 账户管理</h4>
+      <h4 :id="params.titleId" :class="params.titleClass">{{ isNew ? '添加' : '编辑' }} - 角色</h4>
     </template>
-    <el-form :model="form" class="form">
-      <el-form-item label="用户名:" :label-width="formLabelWidth">
-        <el-input v-model="form.username" autocomplete="off" />
-      </el-form-item>
-      <el-form-item label="密码:" :label-width="formLabelWidth">
-        <el-input v-model="form.username" autocomplete="off" />
-      </el-form-item>
-      <el-form-item label="角色名:" :label-width="formLabelWidth">
-        <el-select v-model="form.password" placeholder="请选择角色">
-          <el-option label="Area1" value="shanghai" />
-          <el-option label="Area2" value="beijing" />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="部门:" :label-width="formLabelWidth">
-        <el-select v-model="form.password" placeholder="请选择部门">
-          <el-option label="Area1" value="shanghai" />
-          <el-option label="Area2" value="beijing" />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="岗位:" :label-width="formLabelWidth">
-        <el-select v-model="form.password" placeholder="请选择岗位">
-          <el-option label="Area1" value="shanghai" />
-          <el-option label="Area2" value="beijing" />
-        </el-select>
+    <el-form ref="ruleFormRef" :model="form" :rules="rules">
+      <el-form-item label="角色名:" :label-width="formLabelWidth" prop="name">
+        <el-input v-model="form.name" type="text" autocomplete="off" placeholder="请输入角色名称" />
       </el-form-item>
       <el-form-item :label-width="formLabelWidth">
-        <el-button color="#626aef">添加</el-button>
+        <el-button color="#626aef" @click="AddUserName(ruleFormRef)">添加</el-button>
       </el-form-item>
     </el-form>
   </Drawer>
 </template>
 
 <style scoped lang="scss">
-.input-suffix {
-  width: 100%;
-  .w-50 {
-    width: 12.5rem;
-  }
-}
-.form {
-  margin-top: 3rem;
-}
+@import './index.scss';
 </style>

+ 35 - 0
src/views/account/roles/index.scss

@@ -0,0 +1,35 @@
+.grid-content {
+  background-color: #e4e7ed;
+  padding: 1rem 2rem;
+  max-height: 3.5rem;
+  height: 3.5rem;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  white-space: nowrap;
+}
+.grid-active {
+  display: flex;
+  justify-content: start;
+  align-items: center;
+  flex-wrap: nowrap;
+}
+.el-checkbox-group {
+  display: flex;
+  overflow-x: auto;
+}
+.el-row {
+  margin-bottom: 1rem;
+  max-height: 3.5rem;
+}
+h3 span {
+  font-size: 1rem;
+  color: #606266;
+}
+
+.input-suffix {
+  width: 100%;
+  .w-50 {
+    width: 12.5rem;
+  }
+}

+ 117 - 75
src/views/account/users/Users.vue

@@ -1,84 +1,126 @@
-<template>
-  <div class="role">
-    <el-button type="primary" @click="DialogOpen">添加</el-button>
-    <Dialog ref="dialog" width="80%">
-      <template #header>
-        <h3>
-          角色名:<span>{{ '程序员' }}</span>
-        </h3>
-      </template>
-      <el-row :gutter="24">
-        <el-col :span="4"><div class="grid-content">功能模块</div></el-col>
-        <el-col :span="16"><div class="grid-content">权限</div></el-col>
-        <el-col :span="4"><div class="grid-content">操作</div></el-col>
-      </el-row>
-      <el-row :gutter="24">
-        <el-col :span="4"
-          ><div class="grid-content"><el-button type="success" text>仓库管理</el-button></div></el-col
-        >
-        <el-col :span="16"
-          ><div class="grid-content grid-active">
-            <el-checkbox-group v-model="checkList">
-              <el-checkbox label="Option A" />
-              <el-checkbox label="Option B" />
-              <el-checkbox label="Option C" />
-              <el-checkbox label="Option B" />
-              <el-checkbox label="Option C" />
-              <el-checkbox label="Option B" />
-              <el-checkbox label="Option C" />
-              <el-checkbox label="Option C" />
-              <el-checkbox label="Option B" />
-              <el-checkbox label="Option C" />
-              <el-checkbox label="Option C" />
-              <el-checkbox label="Option B" />
-              <el-checkbox label="Option C" />
-            </el-checkbox-group></div
-        ></el-col>
-        <el-col :span="4"
-          ><div class="grid-content">
-            <el-button type="primary">提交</el-button>
-          </div></el-col
-        >
-      </el-row>
-    </Dialog>
-  </div>
-</template>
-
 <script setup lang="ts">
-import { ref } from 'vue'
-import Dialog from '@/components/dialog/Dialog.vue'
-const dialog = ref()
-const DialogOpen = () => {
-  dialog.value.DialogOpen()
+import TableBase from '@/components/TableBase/index.vue'
+import { ColumnProps } from '@/components/TableBase/interface/index'
+import { Edit, Delete } from '@element-plus/icons-vue'
+import Drawer from '@/components/Drawer/index.vue'
+import { ref, reactive, onMounted } from 'vue'
+import { GlobalStore } from '@/stores/index'
+import { User_List, User_Add, User_Edit, User_Del, User_Post_List, User_Dept_List } from '@/api/user/index'
+const globalStore = GlobalStore()
+const drawerRef = ref()
+const action = ref(true)
+const formLabelWidth = ref('80px')
+const form = reactive({
+  username: '',
+  password: '',
+  user: '',
+  department: '',
+  post: ''
+})
+const columns: ColumnProps[] = [
+  { type: 'index', label: '#', width: 80 },
+  { prop: 'T_name', label: '姓名', search: { el: 'input' } },
+  { prop: 'T_post_name', label: '职位' },
+  { prop: 'T_dept_name', label: '部门' },
+  { prop: 'operation', label: '操作', width: 200, fixed: 'right' }
+]
+const openDrawer = () => {
+  drawerRef.value.closeDrawer()
+  console.log(drawerRef.value)
 }
-const checkList = ref()
-</script>
 
-<style scoped lang="scss">
-.grid-content {
-  background-color: #e4e7ed;
-  padding: 1rem 2rem;
-  max-height: 3.5rem;
-  display: flex;
-  justify-content: center;
-  align-items: center;
+type Fn = () => void
+const callbackDrawer = (done: Fn) => {
+  console.log('触发回调')
+  done()
+}
+
+const AddUser = () => {}
+
+const Posts = []
+const getPosts = async () => {
+  const res = await User_Post_List()
+  console.log(res)
 }
-.grid-active {
-  display: flex;
-  justify-content: start;
-  align-items: center;
-  flex-wrap: nowrap;
+const Depts = []
+const getDept = async () => {
+  const res = await User_Dept_List()
+  console.log(res)
 }
-.el-checkbox-group {
-  display: flex;
-  overflow-x: auto;
+onMounted(() => {
+  getPosts()
+  getDept()
+})
+const initParam = {
+  User_tokey: globalStore.GET_User_tokey,
+  page: 1,
+  page_z: 10
 }
-.el-row {
-  margin-bottom: 1rem;
-  max-height: 3.5rem;
+</script>
+
+<template>
+  <TableBase :columns="columns" :requestApi="User_List" :initParam="initParam">
+    <template #table-header>
+      <div class="input-suffix">
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <span class="ml-3 w-35 text-gray-600 inline-flex items-center">账户查询:</span>
+            <el-input type="text" class="w-50 m-2" />
+            <el-button type="primary">搜索</el-button>
+          </el-col>
+          <el-col :span="6" :offset="6"><el-button type="primary" @click="openDrawer">添加</el-button></el-col>
+        </el-row>
+      </div>
+    </template>
+    <template #right>
+      <el-button link type="primary" size="small" :icon="Edit">编辑</el-button>
+      <el-button link type="danger" size="small" :icon="Delete">删除</el-button>
+    </template>
+  </TableBase>
+  <Drawer ref="drawerRef" :handleClose="callbackDrawer">
+    <template #header="{ params }">
+      <h4 :id="params.titleId" :class="params.titleClass">{{ action ? '添加' : '编辑' }} - 账户管理</h4>
+    </template>
+    <el-form :model="form" class="form">
+      <el-form-item label="用户名:" :label-width="formLabelWidth">
+        <el-input v-model="form.username" autocomplete="off" />
+      </el-form-item>
+      <el-form-item label="密码:" :label-width="formLabelWidth">
+        <el-input v-model="form.username" autocomplete="off" />
+      </el-form-item>
+      <el-form-item label="角色名:" :label-width="formLabelWidth">
+        <el-select v-model="form.password" placeholder="请选择角色">
+          <el-option label="Area1" value="shanghai" />
+          <el-option label="Area2" value="beijing" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="部门:" :label-width="formLabelWidth">
+        <el-select v-model="form.password" placeholder="请选择部门">
+          <el-option label="Area1" value="shanghai" />
+          <el-option label="Area2" value="beijing" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="岗位:" :label-width="formLabelWidth">
+        <el-select v-model="form.password" placeholder="请选择岗位">
+          <el-option label="Area1" value="shanghai" />
+          <el-option label="Area2" value="beijing" />
+        </el-select>
+      </el-form-item>
+      <el-form-item :label-width="formLabelWidth">
+        <el-button color="#626aef" @click="AddUser">添加</el-button>
+      </el-form-item>
+    </el-form>
+  </Drawer>
+</template>
+
+<style scoped lang="scss">
+.input-suffix {
+  width: 100%;
+  .w-50 {
+    width: 12.5rem;
+  }
 }
-h3 span {
-  font-size: 1rem;
-  color: #606266;
+.form {
+  margin-top: 3rem;
 }
 </style>

+ 26 - 0
src/views/account/users/index.scss

@@ -0,0 +1,26 @@
+.grid-content {
+  background-color: #e4e7ed;
+  padding: 1rem 2rem;
+  max-height: 3.5rem;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.grid-active {
+  display: flex;
+  justify-content: start;
+  align-items: center;
+  flex-wrap: nowrap;
+}
+.el-checkbox-group {
+  display: flex;
+  overflow-x: auto;
+}
+.el-row {
+  margin-bottom: 1rem;
+  max-height: 3.5rem;
+}
+h3 span {
+  font-size: 1rem;
+  color: #606266;
+}

+ 24 - 9
src/views/login.scss

@@ -1,25 +1,40 @@
-
 .login {
+  background-color: #091215;
   height: 100%;
-  display:flex;
+  display: flex;
   justify-content: center;
   align-items: center;
-  background: #eee;
-  .content{
-    background: #fff;
+  // background: #eee;
+  .content {
+    background: #eee;
     width: 26.25rem;
     padding: 1.5rem;
     padding-top: 35px;
     border-radius: 6px;
-    :deep(.el-form-item__label){
+    :deep(.el-form-item__label) {
       font-weight: 600;
       font-size: 18px;
     }
-    .submit{
+    .submit {
       width: 100%;
     }
-    .view{
+    .view {
       cursor: pointer;
     }
   }
-}
+  .title {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    margin: 30px 30px 10px;
+  }
+  h2 {
+    color: #2684b4;
+    margin-bottom: 10px;
+    letter-spacing: 4px;
+  }
+  span {
+    font-size: 12px;
+    color: #bbb;
+  }
+}

+ 3 - 3
vite.config.ts

@@ -22,10 +22,10 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
       open: true,
       host: '0.0.0.0',
       proxy: {
-        '/user': {
+        '/api': {
           target: 'http://erp.baozhida.cn',
-          changeOrigin: true
-          // rewrite: path => path.replace(/^\/api/, '')
+          changeOrigin: true,
+          rewrite: path => path.replace(/^\/api/, '')
         },
         '/salary': {
           target: 'http://erp.baozhida.cn',