Pārlūkot izejas kodu

添加权限相关API和功能实现,优化用户信息获取逻辑,调整表单字段和表格操作。

张涛 1 gadu atpakaļ
vecāks
revīzija
c9b8e41cc8

+ 69 - 0
src/apis/permission/account.js

@@ -0,0 +1,69 @@
+import request from '../../base/ajax';
+
+const prefix = '/api/user';
+// 获取用户列表
+export function QueryUserList(params) {
+  return request({
+    url: `${prefix}/list`,
+    method: 'get',
+    params
+  });
+}
+// TODO接口待定
+// 获取用户详情
+export function QueryUserDetail(userId) {
+  return request({
+    url: `${prefix}/user_info`,
+    method: 'get',
+    params: {
+      userId: userId
+    }
+  });
+}
+// 切换用户状态
+export function UserStatusSwitch(data) {
+  return request({
+    url: `${prefix}/change_status`,
+    method: 'put',
+    data
+  });
+}
+// 重置密码
+export function ResetPassword(userId) {
+  return request({
+    url: `${prefix}/reset_pwd`,
+    method: 'put',
+    data: {
+      userId
+    }
+  });
+}
+// 查看用户权限
+export function QueryUserPermission(userId) {
+  return request({
+    url: `${prefix}/permission`,
+    method: 'get',
+    params: {
+      userId
+    }
+  });
+}
+
+// 机构列表
+export function QueryUserDept(userId) {
+  return request({
+    url: `${prefix}/dept`,
+    method: 'get',
+    params: {
+      userId
+    }
+  });
+}
+
+// 删除用户
+export function DeleteUser(userId) {
+  return request({
+    url: `${prefix}/delete_user/${userId}`,
+    method: 'delete'
+  });
+}

+ 12 - 0
src/apis/permission/role.js

@@ -0,0 +1,12 @@
+import request from '../../base/ajax';
+
+const prefix = '/api/role';
+
+// 获取用角色列表
+export function QueryRoleList(params) {
+  return request({
+    url: `${prefix}/list`,
+    method: 'get',
+    params
+  });
+}

+ 14 - 22
src/base/store/use-current-user.js

@@ -49,28 +49,20 @@ export const useCurrentUserStore = defineStore('current_user', {
           });
       });
     },
-    getInfo() {
-      return new Promise((resolve, reject) => {
-        getInfo()
-          .then((res) => {
-            if (res.code == 200) {
-              this.dept = res.data.dept;
-              if (res.roles && res.roles.length > 0) {
-                // 验证返回的roles是否是一个非空数组
-                this.roles = res.roles;
-                this.permissions = res.permissions;
-              } else {
-                this.roles = ['ROLE_DEFAULT'];
-              }
-              resolve(res.msg);
-            } else {
-              reject(res.msg);
-            }
-          })
-          .catch((err) => {
-            reject(err);
-          });
-      });
+    async getInfo() {
+      try {
+        const res = await getInfo();
+        if (res.code === 200) {
+          this.dept = res.data.dept;
+          this.roles = res.roles || ['ROLE_DEFAULT'];
+          this.permissions = res.permissions;
+          return res.msg;
+        } else {
+          throw new Error(res.msg);
+        }
+      } catch (err) {
+        throw err;
+      }
     }
   }
 });

+ 24 - 0
src/directive/hasPermi/index.js

@@ -0,0 +1,24 @@
+import { DirectiveBinding } from 'vue';
+import { useUserStore } from '@/store';
+import { getUserResources } from '@/utils/auth';
+
+function hasPermissionDirective(el, binding) {
+  // 获取用户权限
+  const userStore = useUserStore();
+  const roleData = JSON.parse(getUserResources());
+  const roleBtn = roleData.map((item) => item.component);
+  const permission = binding.value;
+
+  if (!roleBtn.includes(permission)) {
+    el.style.display = 'none';
+  }
+}
+
+export default {
+  mounted(el, binding) {
+    hasPermissionDirective(el, binding);
+  },
+  updated(el, binding) {
+    hasPermissionDirective(el, binding);
+  }
+};

+ 7 - 0
src/directive/index.js

@@ -0,0 +1,7 @@
+import hasPermi from './hasPermi';
+
+export default {
+  install(Vue) {
+    Vue.directive('hasPermi', hasPermi);
+  }
+};

+ 3 - 1
src/index.js

@@ -21,6 +21,7 @@ import { createPinia } from 'pinia';
 import App from './App.vue';
 
 import router from './router'; // 路由
+// import directive from './directive'; // 指令
 import { setupI18n } from './i18n';
 
 import { initTheme } from './base/theme';
@@ -28,11 +29,12 @@ import { initTheme } from './base/theme';
 const pinia = createPinia();
 const app = createApp(App);
 
+app.use(router);
+// app.use(directive);
 app.use(WujieVue);
 app.use(pinia);
 app.use(ArcoVue);
 app.use(ArcoVueIcon);
-app.use(router);
 
 setupI18n().then((i18n) => {
   app.use(i18n);

+ 12 - 10
src/modules/permission/account/AccountForm.vue

@@ -2,23 +2,23 @@
   <a-form :model="edit_form" auto-label-width>
     <a-row :gutter="24">
       <a-col :span="12">
-        <a-form-item field="loginName" label="用户名" :rules="[
+        <a-form-item field="userName" label="用户名" :rules="[
           { required: true, message: '用户名必填' },
           { maxLength: 50, message: '长度不超过50' },
         ]">
-          <a-input v-model="edit_form.loginName" />
+          <a-input v-model="edit_form.userName" />
         </a-form-item>
       </a-col>
       <a-col :span="12">
-        <a-form-item field="userName" label="姓名">
-          <a-input v-model="edit_form.userName" />
+        <a-form-item field="loginName" label="姓名">
+          <a-input v-model="edit_form.loginName" />
         </a-form-item>
       </a-col>
     </a-row>
     <a-row :gutter="24">
       <a-col :span="12">
-        <a-form-item field="phoneNumber" label="手机号">
-          <a-input v-model="edit_form.phoneNumber" />
+        <a-form-item field="phone" label="手机号">
+          <a-input v-model="edit_form.phone" />
         </a-form-item>
       </a-col>
       <a-col :span="12">
@@ -31,9 +31,10 @@
       </a-col>
     </a-row>
     <a-row :gutter="24">
-      <a-col :span="12">
-        <a-form-item field="password" label="密码">
-          <a-input v-model="edit_form.password" type="password" />
+      <!-- 编辑则不显示密码 -->
+      <a-col v-if="!edit_mode" :span="12">
+        <a-form-item field="pwd" label="密码">
+          <a-input v-model="edit_form.pwd" type="pwd" />
         </a-form-item>
       </a-col>
       <a-col :span="12">
@@ -51,13 +52,14 @@ import { toRefs } from 'vue';
 
 const props = defineProps({
   edit_form: Object,
+  edit_mode: Boolean,
   roles: Array,
 });
 
 // 事件发射器
 const emit = defineEmits(['ok', 'cancel']);
 
-const { edit_form, roles } = toRefs(props);
+const { edit_form, edit_mode, roles } = toRefs(props);
 
 // 角色变化处理
 const roleChange = (selectedRoles) => {

+ 179 - 65
src/modules/permission/account/index.vue

@@ -2,10 +2,10 @@
   <a-card class="account-page-card">
     <Action :btn_text="'新建用户组'" @searchClick="searchClick" @resetClick="resetClick" @createClick="createClick"
       @sizeChange="table_size_change" @refreshClick="refreshClick"></Action>
-    <DataTable :data="table_data" :columns="table_columns" row-key="id" :size="table_size" :loading="table_loading"
+    <DataTable :data="table_data" :columns="table_columns" row-key="userId" :size="table_size" :loading="table_loading"
       :pagination="pagination_props" @pageChange="handlePageChange">
       <template #status="{ record }">
-        <a-switch v-model="record.status" />
+        <a-switch v-model="record.status" @change="statusChange(record)" checked-value="1" unchecked-value="0" />
       </template>
       <template #operationSlot="{ record }">
         <a-popconfirm content="确定重置该账号密码吗?" @ok="handleResetPassword(record)">
@@ -14,15 +14,16 @@
         <a-button type="text" @click="handleEdit(record, true)">编辑</a-button>
         <a-button type="text" @click="handleView(record, true)">查看权限</a-button>
         <a-button type="text" @click="handleDeptConfig(record, true)">部门配置</a-button>
-        <a-popconfirm content="确定删除该条数据吗?" type="warning" @ok="handleDelete(record)">
+        <a-popconfirm content="确定删除该条数据吗?" type="warning" @ok="handleDelete(record.userId)">
           <a-button type="text" status="warning">删除</a-button>
         </a-popconfirm>
       </template>
     </DataTable>
   </a-card>
 
-  <Modal :visible.sync="edit_visible" @ok="editModalSave" @cancel="handleEdit(null, false)" :title="'编辑'">
-    <AccountForm :edit_form="edit_form" />
+  <Modal :visible.sync="edit_visible" @ok="editModalSave" @cancel="handleEdit(null, false)"
+    :title="edit_mode ? '编辑' : '新增'">
+    <AccountForm :edit_form="edit_form" :edit_mode="edit_mode" />
   </Modal>
 
   <ViewPermission :visible.sync="view_permission_visible" @cancel="handleView(null, false)"
@@ -36,8 +37,8 @@
 </template>
 
 <script setup>
-import { ref, reactive } from 'vue';
-import { Modal as ArcoModal } from '@arco-design/web-vue';
+import { ref, reactive, onMounted } from 'vue';
+import { Message } from '@arco-design/web-vue';
 import DataTable from '../../../views/permission/DataTable.vue';
 import Action from '../../../views/permission/Action.vue';
 import Modal from '../Modal.vue';
@@ -45,66 +46,49 @@ import AccountForm from './AccountForm.vue';
 import ViewPermission from './ViewPermission.vue';
 import DeptConfigModal from './DeptConfigModal.vue';
 
-const current_record = ref(null);
+import { QueryUserList, QueryUserDetail, QueryUserPermission, QueryUserDept, UserStatusSwitch, ResetPassword, DeleteUser } from '../../../apis/permission/account';
+
+const keywords = ref('');
 // 表格相关
-const table_data = ref([
-  { id: 1, name: '李雷', age: 25, status: true },
-  { id: 2, name: '韩梅梅', age: 30, status: false },
-]);
+const table_data = ref([]);
 const table_columns = ref([
-  { title: '用户名', dataIndex: 'name', titleSlotName: 'name' },
-  { title: '角色', dataIndex: 'age', titleSlotName: 'age' },
-  { title: '所属部门', dataIndex: 'dept', titleSlotName: 'dept' },
+  { title: '序号', slotName: 'index' },
+  { title: '用户名', dataIndex: 'userName', titleSlotName: 'userName' },
+  { title: '角色', dataIndex: 'roleName', titleSlotName: 'roleName' },
+  { title: '所属部门', dataIndex: 'deptName', titleSlotName: 'deptName' },
   { title: '状态', dataIndex: 'status', slotName: 'status' },
   { title: '操作', dataIndex: 'operation', slotName: 'operationSlot' },
 ]);
 const pagination_props = ref({
-  total: 100,
+  total: 10,
   current: 1,
-  pageSize: 15,
+  pageSize: 12,
 })
 const table_size = ref('medium');
 const table_loading = ref(false);
 
 // 编辑表单相关
 const edit_visible = ref(false);
+const edit_mode = ref(false);
 const edit_form = reactive({
-  loginName: '',
   userName: '',
-  phoneNumber: '',
+  userName: '',
+  phone: '',
   email: '',
-  password: '',
+  pwd: '',
   role: []
 });
 
-
-
 // 查看权限相关
 const view_permission_visible = ref(false);
-const menu_permissions_list = ref([
-  { name: '智能体设置', id: 1 },
-  { name: 'root', id: 2 },
-  { name: '智能体列表', id: 3 },
-  { name: '会话记录', id: 4 },
-])
-const knowledge_permissions_list = ref([
-  { name: '知识库管理', id: 1 },
-  { name: '知识库列表', id: 2 },
-  { name: '知识库分类', id: 3 },
-])
-const dialog_permissions_list = ref([
-  { name: '对话管理', id: 1 },
-  { name: '对话列表', id: 2 },
-  { name: '对话分类', id: 3 },
-])
-const agent_permissions_list = ref([
-  { name: '智能体管理', id: 1 },
-  { name: '智能体列表', id: 2 },
-  { name: '智能体分类', id: 3 },
-])
+const menu_permissions_list = ref([])
+const knowledge_permissions_list = ref([])
+const dialog_permissions_list = ref([])
+const agent_permissions_list = ref([])
 
 // 部门配置相关
 const dept_config_visible = ref(false);
+const current_record = ref(null);
 const dept_list = ref([
   {
     "address": null,
@@ -231,61 +215,191 @@ const dept_list = ref([
   }
 ]);
 
+const getUserList = async () => {
+  const params = {
+    keyword: keywords.value,
+    current: pagination_props.value.current,
+    pageSize: pagination_props.value.pageSize,
+  };
+  table_loading.value = true
+  const { code, data } = await QueryUserList(params);
+  if (code === 200) {
+    for (const user of data.rows) {
+      if (user.dept) {
+        for (const d of user.dept) {
+          if (user.deptName) {
+            user.deptName += d.deptName + ',';
+          } else {
+            user.deptName = d.deptName + ',';
+          }
+        }
+      }
+      if (user.roles) {
+        for (const r of user.roles) {
+          if (user.roleName) {
+            user.roleName += r.roleName + ',';
+          } else {
+            user.roleName = r.roleName + ',';
+          }
+        }
+      }
+    }
+
+    pagination_props.value.total = data.total;
+    table_data.value = data.rows;
+
+    table_loading.value = false
+  } else {
+    table_loading.value = false
+  }
+}
+
 const searchClick = (value) => {
-  console.log('value', value)
+  keywords.value = value;
+  getUserList();
 }
 const resetClick = () => {
-  console.log('重置')
+  keywords.value = '';
+  getUserList();
 }
 const createClick = () => {
-  console.log('新建')
+  edit_form.userName = '';
+  edit_form.loginName = '';
+  edit_form.phone = '';
+  edit_form.email = '';
+  edit_form.pwd = '';
+  edit_form.role = [];
+  edit_mode.value = false;
+  edit_visible.value = true;
 }
 const refreshClick = () => {
   console.log('刷新')
 }
 
-const handleResetPassword = (record) => {
-  ArcoModal.success({
-    title: '重置密码',
-    content: '该用户密码重置为000000',
-  });
+// 切换页码
+const handlePageChange = (current) => {
+  pagination_props.value.current = current;
+  getUserList();
+};
+
+// TODO功能 状态切换拦截
+const beforeStatusChange = async () => {
+  await new Promise((resolve, reject) => setTimeout(() => {
+    resolve()
+  }, 1000))
+}
+
+// 用户状态切换
+const statusChange = async (record) => {
+  if (record?.dept) {
+    const params = {
+      userId: record.userId,
+      status: record.status,
+    };
+    const { code } = await UserStatusSwitch(params)
+    if (code === 200) {
+      Message.success({
+        title: '成功',
+        content: '状态切换成功.',
+      });
+    }
+  } else {
+
+  }
+};
+//重置密码
+const handleResetPassword = async (record) => {
+  const { code } = await ResetPassword(record.userId);
+  if (code === 200) {
+    Message.success({
+      title: '重置密码',
+      content: '该用户密码重置为000000',
+    });
+  }
 }
 
 const handleEdit = (record, visible) => {
+
   if (record) {
-    console.log('record', record)
-    edit_form.loginName = record.loginName;
+
     edit_form.userName = record.userName;
-    edit_form.phoneNumber = record.phoneNumber;
+    edit_form.loginName = record.loginName;
+    edit_form.phone = record.phone;
     edit_form.email = record.email;
-    edit_form.password = record.password;
+    edit_form.pwd = record.pwd;
     edit_form.role = record.role;
+
+    edit_mode.value = true;
   }
 
   edit_visible.value = visible;
 }
+// 查看权限
+const handleView = async (record, visible) => {
+  if (record) {
+    dialog_permissions_list.value = [];
+    knowledge_permissions_list.value = [];
+    menu_permissions_list.value = [];
+    const { code, data } = await QueryUserPermission(record.userId);
+    if (code === 200) {
+      const { knowledge, menus, dialog } = data;
+      if (dialog && dialog.length > 0) dialog_permissions_list.value = dialog
+      if (knowledge && knowledge.length > 0) knowledge_permissions_list.value = knowledge
+      if (menus && menus.length > 0) menu_permissions_list.value = getMenuTitles(menus)
 
-const handleView = (record, visible) => {
-  console.log('record', record)
+    }
+  }
   view_permission_visible.value = visible;
 }
-
-const handleDeptConfig = (record, visible) => {
-  current_record.value = record;
+// 部门配置
+const handleDeptConfig = async (record, visible) => {
+  if (record) {
+    current_record.value = record;
+    const { code, data: { rows } } = await QueryUserDept(record.userId);
+    if (code === 200) {
+      // TODO接口 机构接上再接这个
+      console.log('rows', rows)
+      // dept_list.value = rows;
+    }
+  }
   dept_config_visible.value = visible;
 }
+
+// 删除用户
+const handleDelete = async (userId) => {
+  const { code } = await DeleteUser(userId);
+  if (code === 200) {
+    Message.success({
+      title: '删除用户',
+      content: '该用户已删除',
+    });
+    getUserList();
+  }
+}
 const editModalSave = () => {
   edit_visible.value = false;
-  console.log('编辑保存')
 }
 const table_size_change = (size) => {
   table_size.value = size;
 }
+// 铺开路由菜单title
+const getMenuTitles = (data, result = []) => {
+  data.forEach(item => {
+    // 检查item是否有id和name属性
+    if (item.id && item.meta.title) {
+      result.push({ id: item.id, name: item.meta.title });
+    }
+    // 如果有子项,递归调用函数
+    if (item.children && item.children.length > 0) {
+      getMenuTitles(item.children, result);
+    }
+  });
+  return result;
+}
 
-const handlePageChange = (current) => {
-  pagination_props.value.current = current;
-};
-
+onMounted(() => {
+  getUserList()
+})
 </script>
 
 <style lang="css" scoped>

+ 1 - 2
src/modules/permission/role/PermissionConfigModal.vue

@@ -97,8 +97,7 @@ const handleTabChange = (key) => {
 };
 // 处理取消事件
 const handleCancel = () => {
-  visible.value = false;
-  emit('close');
+  emit('cancel');
 };
 
 // 处理确认事件

+ 363 - 0
src/modules/permission/role/index.vue

@@ -0,0 +1,363 @@
+<template>
+  <a-card class="account-page-card">
+    <Action :btn_text="'新建用户组'" @searchClick="searchClick" @resetClick="resetClick" @createClick="createClick"
+      @sizeChange="table_size_change" @refreshClick="refreshClick"></Action>
+    <DataTable :data="table_data" :columns="table_columns" row-key="userId" :size="table_size" :loading="table_loading"
+      :pagination="pagination_props" @pageChange="handlePageChange">
+      <template #status="{ record }">
+        <a-switch v-model="record.status" @change="statusChange(record)" checked-value="1" unchecked-value="0" />
+      </template>
+      <template #operationSlot="{ record }">
+        <a-popconfirm content="确定重置该账号密码吗?" @ok="handleResetPassword(record)">
+          <a-button type="text">重制密码</a-button>
+        </a-popconfirm>
+        <a-button type="text" @click="handleEdit(record, true)">编辑</a-button>
+        <a-button type="text" @click="handlePermissionConfig(record, true)">权限配置</a-button>
+        <a-button type="text" @click="handleDeptConfig(record, true)">部门配置</a-button>
+        <a-popconfirm content="确定删除该条数据吗?" type="warning" @ok="handleDelete(record.userId)">
+          <a-button type="text" status="warning">删除</a-button>
+        </a-popconfirm>
+      </template>
+    </DataTable>
+  </a-card>
+
+  <Modal :visible.sync="edit_visible" @ok="editModalSave" @cancel="handleEdit(null, false)" :title="'编辑'">
+    <AccountForm :edit_form="edit_form" />
+  </Modal>
+
+  <!-- TODO -->
+  <PermissionConfigModal :visible.sync="permission_config_visible" @cancel="handlePermissionConfig(null, false)" />
+
+  <DeptConfigModal :visible.sync="dept_config_visible" :dept_list="dept_list" :record="current_record" @ok=""
+    @cancel="handleDeptConfig(null, false)" />
+
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue';
+import { Message } from '@arco-design/web-vue';
+import DataTable from '../../../views/permission/DataTable.vue';
+import Action from '../../../views/permission/Action.vue';
+import Modal from '../Modal.vue';
+import AccountForm from './AccountForm.vue';
+import PermissionConfigModal from './PermissionConfigModal.vue';
+import DeptConfigModal from './DeptConfigModal.vue';
+
+import { QueryRoleList, } from '../../../apis/permission/role';
+
+const keywords = ref('');
+// 表格相关
+const table_data = ref([]);
+const table_columns = ref([
+  { title: '序号', slotName: 'index' },
+  { title: '用户名', dataIndex: 'userName', titleSlotName: 'userName' },
+  { title: '角色', dataIndex: 'roleName', titleSlotName: 'roleName' },
+  { title: '所属部门', dataIndex: 'deptName', titleSlotName: 'deptName' },
+  { title: '状态', dataIndex: 'status', slotName: 'status' },
+  { title: '操作', dataIndex: 'operation', slotName: 'operationSlot' },
+]);
+const pagination_props = ref({
+  total: 10,
+  current: 1,
+  pageSize: 12,
+})
+const table_size = ref('medium');
+const table_loading = ref(false);
+
+// 编辑表单相关
+const edit_visible = ref(false);
+const edit_form = reactive({
+  userName: '',
+  userName: '',
+  phone: '',
+  email: '',
+  pwd: '',
+  role: []
+});
+
+// 权限配置相关
+const permission_config_visible = ref(false);
+const menu_permissions_list = ref([])
+const knowledge_permissions_list = ref([])
+const dialog_permissions_list = ref([])
+const agent_permissions_list = ref([])
+
+// 部门配置相关
+const dept_config_visible = ref(false);
+const current_record = ref(null);
+const dept_list = ref([
+  {
+    "address": null,
+    "children": [
+      {
+        "address": "",
+        "children": [],
+        "code": null,
+        "createTime": "Thu, 12 Sep 2024 14:56:43 GMT",
+        "deptId": "2af7cb5e-1178-4adc-8abb-9780f7543081",
+        "deptName": "成都",
+        "email": "",
+        "iconCls": null,
+        "leader": "成都",
+        "orderNum": 0,
+        "parentId": "0",
+        "parentName": "总部",
+        "phone": "成都",
+        "roles": [],
+        "status": "",
+        "updateTime": "Thu, 12 Sep 2024 14:56:43 GMT"
+      },
+      {
+        "address": null,
+        "children": [],
+        "code": null,
+        "createTime": "Sun, 22 May 2022 09:59:33 GMT",
+        "deptId": "5477d9a9-e41e-485f-bb08-697e8facef88",
+        "deptName": "南京分公司",
+        "email": "ss@ada.com",
+        "iconCls": null,
+        "leader": "dd",
+        "orderNum": 0,
+        "parentId": "0",
+        "parentName": "总部",
+        "phone": "18905189016",
+        "roles": [],
+        "status": "0",
+        "updateTime": "Tue, 12 Nov 2024 03:05:10 GMT"
+      },
+      {
+        "address": null,
+        "children": [
+          {
+            "address": "",
+            "children": [
+              {
+                "address": "",
+                "children": [],
+                "code": null,
+                "createTime": "Tue, 12 Nov 2024 03:09:57 GMT",
+                "deptId": "c6ae93de-2436-4090-b567-ec4835c74112",
+                "deptName": "成都",
+                "email": "",
+                "iconCls": null,
+                "leader": "柔柔弱弱",
+                "orderNum": 0,
+                "parentId": "f86724f0-94d9-445c-9d95-3ec2540da0f8",
+                "parentName": "太平洋派出所",
+                "phone": "1234242342",
+                "roles": [],
+                "status": "",
+                "updateTime": "Tue, 12 Nov 2024 06:58:15 GMT"
+              }
+            ],
+            "code": null,
+            "createTime": "Thu, 05 Sep 2024 03:15:13 GMT",
+            "deptId": "f86724f0-94d9-445c-9d95-3ec2540da0f8",
+            "deptName": "太平洋派出所",
+            "email": "",
+            "iconCls": null,
+            "leader": "12",
+            "orderNum": 0,
+            "parentId": "ce627e90-57d6-4ed4-a789-1f3dd467ae7d",
+            "parentName": "上海分公司",
+            "phone": "12",
+            "roles": [
+              {
+                "deptId": "f86724f0-94d9-445c-9d95-3ec2540da0f8",
+                "roleId": "19f00d46-8f1b-45b5-b7b7-6197d7b8cb33",
+                "roleName": "管理员1"
+              }
+            ],
+            "status": "0",
+            "updateTime": "Tue, 12 Nov 2024 06:58:07 GMT"
+          }
+        ],
+        "code": null,
+        "createTime": "Tue, 24 May 2022 23:54:10 GMT",
+        "deptId": "ce627e90-57d6-4ed4-a789-1f3dd467ae7d",
+        "deptName": "上海分公司",
+        "email": null,
+        "iconCls": null,
+        "leader": "jack",
+        "orderNum": 0,
+        "parentId": "0",
+        "parentName": "总部",
+        "phone": null,
+        "roles": [
+          {
+            "deptId": "ce627e90-57d6-4ed4-a789-1f3dd467ae7d",
+            "roleId": "301ca518-2ed0-4092-a2ee-e46c24a42c8a",
+            "roleName": "普通"
+          }
+        ],
+        "status": "0",
+        "updateTime": "Wed, 18 Sep 2024 09:58:16 GMT"
+      }
+    ],
+    "code": null,
+    "createTime": "Mon, 28 Nov 2016 10:34:54 GMT",
+    "deptId": "0",
+    "deptName": "总部",
+    "email": null,
+    "iconCls": "ext-icon-bricks",
+    "leader": null,
+    "orderNum": 100,
+    "parentId": "",
+    "parentName": "",
+    "phone": null,
+    "roles": [],
+    "status": "0",
+    "updateTime": "Mon, 28 Nov 2016 10:35:12 GMT"
+  }
+]);
+
+const getUserList = async () => {
+  const params = {
+    keyword: keywords.value,
+    current: pagination_props.value.current,
+    pageSize: pagination_props.value.pageSize,
+  };
+  table_loading.value = true
+  const { code, data } = await QueryRoleList(params);
+  if (code === 200) {
+
+    pagination_props.value.total = data.total;
+    table_data.value = data.rows;
+
+    table_loading.value = false
+  } else {
+    table_loading.value = false
+  }
+}
+
+const searchClick = (value) => {
+  keywords.value = value;
+  getUserList();
+}
+const resetClick = () => {
+  keywords.value = '';
+  getUserList();
+}
+const createClick = () => {
+  edit_form.userName = '';
+  edit_form.loginName = '';
+  edit_form.phone = '';
+  edit_form.email = '';
+  edit_form.pwd = '';
+  edit_form.role = [];
+  edit_visible.value = true;
+}
+const refreshClick = () => {
+  console.log('刷新')
+}
+
+// 切换页码
+const handlePageChange = (current) => {
+  pagination_props.value.current = current;
+  getUserList();
+};
+
+// TODO功能 状态切换拦截
+const beforeStatusChange = async () => {
+  await new Promise((resolve, reject) => setTimeout(() => {
+    resolve()
+  }, 1000))
+}
+
+// 用户状态切换
+const statusChange = async (record) => {
+  if (record?.dept) {
+    const params = {
+      userId: record.userId,
+      status: record.status,
+    };
+    const { code } = await UserStatusSwitch(params)
+    if (code === 200) {
+      Message.success({
+        title: '成功',
+        content: '状态切换成功.',
+      });
+    }
+  } else {
+
+  }
+};
+//重置密码
+const handleResetPassword = async (record) => {
+  const { code } = await ResetPassword(record.userId);
+  if (code === 200) {
+    Message.success({
+      title: '重置密码',
+      content: '该用户密码重置为000000',
+    });
+  }
+}
+
+const handleEdit = (record, visible) => {
+  if (record) {
+    edit_form.userName = record.userName;
+    edit_form.loginName = record.loginName;
+    edit_form.phone = record.phone;
+    edit_form.email = record.email;
+    edit_form.pwd = record.pwd;
+    edit_form.role = record.role;
+  }
+
+  edit_visible.value = visible;
+}
+// 权限配置
+const handlePermissionConfig = async (record, visible) => {
+  if (record) {
+    const { code, data } = await QueryUserPermission(record.userId);
+    if (code === 200) {
+      const { knowledge, menu, dialog } = data;
+      if (dialog && dialog.length > 0) dialog_permissions_list.value = dialog
+      if (menu && menu.length > 0) menu_permissions_list.value = menu
+      if (knowledge && knowledge.length > 0) knowledge_permissions_list.value = knowledge
+    }
+  }
+  permission_config_visible.value = visible;
+}
+// 部门配置
+const handleDeptConfig = async (record, visible) => {
+  if (record) {
+    current_record.value = record;
+    const { code, data: { rows } } = await QueryUserDept(record.userId);
+    if (code === 200) {
+      // TODO接口 机构接上再接这个
+      console.log('rows', rows)
+      // dept_list.value = rows;
+    }
+  }
+  dept_config_visible.value = visible;
+}
+
+// 删除用户
+const handleDelete = async (userId) => {
+  const { code } = await DeleteUser(userId);
+  if (code === 200) {
+    Message.success({
+      title: '删除用户',
+      content: '该用户已删除',
+    });
+    getUserList();
+  }
+}
+const editModalSave = () => {
+  edit_visible.value = false;
+}
+const table_size_change = (size) => {
+  table_size.value = size;
+}
+
+
+onMounted(() => {
+  getUserList()
+})
+</script>
+
+<style lang="css" scoped>
+.account-page-card {
+  height: calc(100% - 40px);
+}
+</style>

+ 6 - 5
src/views/permission/DataTable.vue

@@ -1,14 +1,15 @@
 <template>
   <div>
-    <a-table :columns="columns" :data="data" :row-key="rowKey" :size="size" :loading="loading" :pagination="false">
+    <a-table :columns="columns" :data="data" :row-key="rowKey" :size="size" :loading="loading" :bordered="false"
+      :pagination="false">
       <template v-for="item in columns" :key="item.slotName" #[item.slotName]="{ record, rowIndex, column }">
+        <!-- 如果是序号列则显示序号 -->
+        <span v-if="item.slotName === 'index'"> {{ rowIndex + 1 + (pagination.current - 1) * pagination.pageSize
+          }}</span>
         <slot :name="item.slotName" v-bind="{ record, rowIndex, column }"></slot>
       </template>
       <template v-for="item in columns" :key="item.titleSlotName" #[item.titleSlotName]="{ record, rowIndex, column }">
-        <a-popover :content="item.titleTip"
-          :content-style="{ fontSize: '13px', padding: '10px 14px', fontWeight: 500 }">
-          <div class="title-tip">{{ item.title }}</div>
-        </a-popover>
+        <div class="title-tip">{{ item.title }}</div>
       </template>
     </a-table>
     <a-pagination v-if="pagination.total" class="pagination" :current="pagination.current" :total="pagination.total"

+ 2 - 2
vite.config.mjs

@@ -21,8 +21,8 @@ export default defineConfig({
     host: '0.0.0.0', // IP配置,支持从IP启动
     proxy: {
       '/api/': {
-        target: 'http://192.168.20.119:9301',
-        // target: "http://192.168.20.119:9301",
+        // target: 'http://192.168.20.119:9301',
+        target: 'http://smartai.com:8191',
         changeOrigin: true,
         secure: false,
         ws: true,