张涛 1 жил өмнө
parent
commit
12aba100d7

+ 2 - 2
public/i18n/lang-zh.json

@@ -53,8 +53,8 @@
     "role": "角色",
     "account": "账号",
     "organization": "机构",
-    "group": "群组",
-    "resource": "资源"
+    "resource": "资源",
+    "group": "用户组"
   },
   "conversation": {
     "chat_new": "开启新会话",

+ 0 - 66
src/modules/permission/AccountPage.vue

@@ -1,66 +0,0 @@
-<template>
-  <div>
-    <Action></Action>
-    <DataTable :data="tableData" :columns="tableColumns" row-key="id" :loading="isLoading" :pagination="paginationProps"
-      @sorterChange="handleSorterChange" @select="handleSelect" @selectAll="handleSelectAll" @expand="handleExpand"
-      @pageChange="handlePageChange" @sizeChange="handleSizeChange">
-    </DataTable>
-  </div>
-
-
-</template>
-
-<script setup>
-import { ref } from 'vue';
-import DataTable from '../../views/permission/DataTable.vue';
-// import Action from '../../views/permission/Actions.vue';
-
-// 示例数据
-const tableData = ref([
-  { id: 1, name: '李雷', age: 25 },
-  { id: 2, name: '韩梅梅', age: 30 },
-]);
-
-const tableColumns = ref([
-  { title: '用户名', dataIndex: 'name', titleSlotName: 'nameSlot' },
-  { title: '角色', dataIndex: 'age', titleSlotName: 'ageSlot' },
-  { title: '所属部门', dataIndex: 'dept', titleSlotName: 'deptSlot' },
-  { title: '状态', dataIndex: 'status', titleSlotName: 'statusSlot' },
-  { title: '操作', dataIndex: 'operation', titleSlotName: 'operationSlot' },
-]);
-
-const isLoading = ref(false);
-const paginationProps = ref({
-  current: 1,
-  total: 100,
-  pageSize: 10,
-});
-
-// 事件处理函数
-const handleSorterChange = (sorter) => {
-  console.log('排序变化:', sorter);
-};
-
-const handleSelect = (selected, record) => {
-  console.log('选择:', selected, record);
-};
-
-const handleSelectAll = (selected, records) => {
-  console.log('选择所有:', selected, records);
-};
-
-const handleExpand = (expanded, record) => {
-  console.log('展开:', expanded, record);
-};
-
-const handlePageChange = (page) => {
-  console.log('当前页面:', page);
-};
-
-const handleSizeChange = (current, size) => {
-  console.log('当前页面和页面大小:', current, size);
-};
-</script>
-
-
-<style lang="css" scoped></style>

+ 88 - 0
src/modules/permission/account/EditModal.vue

@@ -0,0 +1,88 @@
+<template>
+  <a-modal v-model:visible="visible" :title="title" @ok="editHandleOk" @cancel="editHandleCancel" width="48%">
+    <a-form ref="formRef" :model="editform" auto-label-width>
+      <a-row :gutter="20">
+        <a-col :span="10">
+          <a-form-item field="loginName" label="用户名" :rules="[
+            { required: true, message: '用户名必填' },
+            { maxLength: 50, message: '长度不超过50' },
+          ]">
+            <a-input v-model="editform.loginName" />
+          </a-form-item>
+        </a-col>
+        <a-col :span="10">
+          <a-form-item field="userName" label="姓名">
+            <a-input v-model="editform.userName" />
+          </a-form-item>
+        </a-col>
+      </a-row>
+      <a-row :gutter="20">
+        <a-col :span="10">
+          <a-form-item field="phoneNumber" label="手机号">
+            <a-input v-model="editform.phoneNumber" />
+          </a-form-item>
+        </a-col>
+        <a-col :span="10">
+          <a-form-item required field="email" label="邮箱" :rules="[
+            { required: true, message: '邮箱必填' },
+            { maxLength: 50, message: '长度不超过50' },
+          ]">
+            <a-input v-model="editform.email" />
+          </a-form-item>
+        </a-col>
+      </a-row>
+      <a-row :gutter="20">
+        <a-col :span="10">
+          <a-form-item field="password" label="密码">
+            <a-input v-model="editform.password" type="password" />
+          </a-form-item>
+        </a-col>
+        <a-col :span="10">
+          <a-form-item field="role" label="角色">
+            <a-select multiple v-model="editform.role" :options="roles" :field-names="fieldNames" @change="roleChange">
+            </a-select>
+          </a-form-item>
+        </a-col>
+      </a-row>
+    </a-form>
+  </a-modal>
+</template>
+
+<script setup>
+import { toRefs } from 'vue';
+
+// 定义组件的 props(根据实际需要进行修改)
+const props = defineProps({
+  editform: Object,
+  visible: Boolean,
+  title: String,
+  roles: Array,
+  fieldNames: Object
+});
+
+// 事件发射器
+const emit = defineEmits(['save', 'cancel']);
+
+const { editform, visible, title, roles, fieldNames } = toRefs(props);
+
+// 处理确认事件
+const editHandleOk = () => {
+  // 进行表单验证和提交逻辑
+  // 根据需要增加表单验证逻辑
+  emit('save', editform);
+}
+
+const editHandleCancel = () => {
+  emit('cancel');
+  visible.value = false;
+}
+
+// 角色变化处理
+const roleChange = (selectedRoles) => {
+  editform.role = selectedRoles;
+}
+</script>
+
+<style lang="css" scoped>
+/* 这里可以添加自定义样式 */
+</style>

+ 78 - 0
src/modules/permission/account/ViewPermission.vue

@@ -0,0 +1,78 @@
+<template>
+  <a-modal width="50%" v-model:visible="resourceVisible" title="用户所有权限" okText="关闭" hide-cancel="true" @ok="handleOk">
+    <div :style="{ 'display': 'flex', 'flex-direction': 'column' }">
+      <a-card :style="{
+        'width': '100%',
+        'height': '40%',
+        'overflow-y': 'auto',
+        'margin': '1px',
+      }" class="card-demo" title="用户所有权限" hoverable>
+        <a-space wrap>
+          菜单功能:
+          <a-tag v-for="(tag, index) in checkStrictlyMenu" :key="tag.menuId">
+            {{ tag.menuName }}
+          </a-tag>
+        </a-space>
+        <a-divider />
+        <a-space wrap>
+          知识库:
+          <a-tag v-for="(tag, index) in checkStrictlyKnowledge" :key="tag.knowledgeId">
+            {{ tag.knowledgeName }}
+          </a-tag>
+        </a-space>
+        <a-divider />
+        <a-space wrap>
+          智能体:
+          <a-tag v-for="(tag, index) in checkStrictlyDialog" :key="tag.dialogId">
+            {{ tag.dialogName }}
+          </a-tag>
+          <a-tag v-for="(tag, index) in checkStrictlyAgent" :key="tag.agentId">
+            {{ tag.agentName }}
+          </a-tag>
+        </a-space>
+      </a-card>
+    </div>
+  </a-modal>
+</template>
+
+<script setup>
+import { ref, } from 'vue';
+
+// 定义Props,接收外部传入的数据
+const props = defineProps({
+  resourceVisible: {
+    type: Boolean,
+    required: true
+  },
+  checkStrictlyMenu: {
+    type: Array,
+    required: true
+  },
+  checkStrictlyKnowledge: {
+    type: Array,
+    required: true
+  },
+  checkStrictlyDialog: {
+    type: Array,
+    required: true
+  },
+  checkStrictlyAgent: {
+    type: Array,
+    required: true
+  }
+});
+
+// 定义Emits,抛出事件
+const emit = defineEmits(['close']);
+
+// 处理确认的函数
+const handleOk = () => {
+  emit('close'); // 关闭模态框并通知父组件更新状态
+};
+
+// 你可以在这里添加其他的逻辑,例如获取权限数据等
+</script>
+
+<style lang="css" scoped>
+/* 您可以在这里添加样式 */
+</style>

+ 121 - 0
src/modules/permission/account/index.vue

@@ -0,0 +1,121 @@
+<template>
+  <a-card class="account-page-card">
+    <Action :btn-text="'新建用户组'" @searchClick="searchClick" @resetClick="resetClick" @createClick="createClick"
+      @sizeChange="tableSizeChange" @refreshClick="refreshClick"></Action>
+    <DataTable :data="tableData" :columns="tableColumns" row-key="id" :size="tableSize" :loading="tableLoading"
+      :pagination="paginationProps" @pageChange="handlePageChange">
+      <template #status="{ record }">
+        <a-switch v-model="record.status" />
+      </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)">编辑</a-button>
+        <a-button type="text" @click="handleView(record)">查看权限</a-button>
+        <a-button type="text" @click="handleDeptConfig(record)">部门配置</a-button>
+        <a-popconfirm content="确定删除该条数据吗?" type="warning" @ok="handleDelete(record)">
+          <a-button type="text" status="warning">删除</a-button>
+        </a-popconfirm>
+      </template>
+    </DataTable>
+  </a-card>
+
+  <editModal :visible.sync="editVisible" @save="editModalSave" @cancel="editVisible = false" :title="'编辑'"
+    :editform="editform"></editModal>
+</template>
+
+<script setup>
+import { ref, reactive } from 'vue';
+import { Modal } from '@arco-design/web-vue';
+import DataTable from '../../../views/permission/DataTable.vue';
+import Action from '../../../views/permission/Action.vue';
+import editModal from './EditModal.vue';
+
+// 表格相关
+const tableData = ref([
+  { id: 1, name: '李雷', age: 25, status: true },
+  { id: 2, name: '韩梅梅', age: 30, status: false },
+]);
+const tableColumns = ref([
+  { title: '用户名', dataIndex: 'name', titleSlotName: 'name' },
+  { title: '角色', dataIndex: 'age', titleSlotName: 'age' },
+  { title: '所属部门', dataIndex: 'dept', titleSlotName: 'dept' },
+  { title: '状态', dataIndex: 'status', slotName: 'status' },
+  { title: '操作', dataIndex: 'operation', slotName: 'operationSlot' },
+]);
+const paginationProps = ref({
+  total: 100,
+  current: 1,
+  pageSize: 15,
+})
+const tableSize = ref('medium');
+const tableLoading = ref(false);
+
+// 编辑表单相关
+const editVisible = ref(false);
+const editform = reactive({
+  loginName: '',
+  userName: '',
+  phoneNumber: '',
+  email: '',
+  password: '',
+  role: []
+});
+
+
+const searchClick = (value) => {
+  console.log('value', value)
+}
+const resetClick = () => {
+  console.log('重置')
+}
+const createClick = () => {
+
+  console.log('新建')
+}
+const refreshClick = () => {
+  console.log('刷新')
+}
+
+const handleResetPassword = (record) => {
+  Modal.success({
+    title: '重置密码',
+    content: '该用户密码重置为000000',
+  });
+
+  // Modal.error({
+  //   title: '重置密码',
+  //   content: '该用户密码重置失败',
+  // });
+}
+const handleEdit = (record) => {
+  editVisible.value = true;
+  console.log('record', record)
+  editform.loginName = record.loginName;
+  editform.userName = record.userName;
+  editform.phoneNumber = record.phoneNumber;
+  editform.email = record.email;
+  editform.password = record.password;
+  editform.role = record.role;
+}
+const editModalSave = () => {
+  editVisible.value = false;
+  console.log('编辑保存')
+}
+const tableSizeChange = (size) => {
+  tableSize.value = size;
+}
+
+const handlePageChange = (current) => {
+  paginationProps.value.current = current;
+};
+
+</script>
+
+
+<style lang="css" scoped>
+.account-page-card {
+  height: calc(100% - 40px);
+}
+</style>

+ 1 - 1
src/views/Home.vue

@@ -23,7 +23,7 @@
       <li><router-link class="arco-link" to="/permission/org">机构</router-link></li>
       <li><router-link class="arco-link" to="/permission/account">账号</router-link></li>
       <li><router-link class="arco-link" to="/permission/role">角色</router-link></li>
-      <li><router-link class="arco-link" to="/permission/resource">资源</router-link></li>
+      <li><router-link class="arco-link" to="/permission/group">用户组</router-link></li>
       <li><router-link class="arco-link" to="/profile">个人中心</router-link></li>
       <li><router-link class="arco-link" to="/setting">设置</router-link></li>
       <li><router-link class="arco-link" to="/about">关于</router-link></li>

+ 1 - 2
src/views/PermissionAccount.vue

@@ -1,7 +1,6 @@
 <template>
   <ContentContainer>
     <BreadCrumbMenu :current_label="'账号'" />
-
     <AccountPage />
   </ContentContainer>
 </template>
@@ -10,5 +9,5 @@
 import ContentContainer from './layout/ContentContainer.vue';
 import BreadCrumbMenu from './common/BreadCrumbMenu.vue';
 
-import AccountPage from '../modules/permission/AccountPage.vue';
+import AccountPage from '../modules/permission/account/index.vue';
 </script>

+ 19 - 19
src/views/common/PermissionDropdown.vue

@@ -8,24 +8,20 @@
       </div>
 
       <template #content>
-        <a-doption
-          ><router-link class="arco-link" to="/permission/role">{{ $t('permission.role') }}</router-link></a-doption
-        >
-        <a-doption
-          ><router-link class="arco-link" to="/permission/account">{{
-            $t('permission.account')
-          }}</router-link></a-doption
-        >
-        <a-doption
-          ><router-link class="arco-link" to="/permission/org">{{
-            $t('permission.organization')
-          }}</router-link></a-doption
-        >
-        <a-doption
-          ><router-link class="arco-link" to="/permission/resource">{{
-            $t('permission.resource')
-          }}</router-link></a-doption
-        >
+        <a-doption><router-link class="arco-link" to="/permission/role">{{ $t('permission.role')
+            }}</router-link></a-doption>
+        <a-doption><router-link class="arco-link" to="/permission/account">{{
+          $t('permission.account')
+            }}</router-link></a-doption>
+        <a-doption><router-link class="arco-link" to="/permission/org">{{
+          $t('permission.organization')
+            }}</router-link></a-doption>
+        <a-doption><router-link class="arco-link" to="/permission/resource">{{
+          $t('permission.resource')
+            }}</router-link></a-doption>
+        <a-doption><router-link class="arco-link" to="/permission/group">{{
+          $t('permission.group')
+            }}</router-link></a-doption>
       </template>
     </a-dropdown>
   </a-space>
@@ -44,7 +40,7 @@ const route = useRoute();
 const is_active = computed(() => {
   const cur_path = route.path;
 
-  const active_list = ['/permission/role', '/permission/account', '/permission/org', '/permission/resource'];
+  const active_list = ['/permission/role', '/permission/account', '/permission/org', '/permission/resource', '/permission/group'];
 
   return active_list.indexOf(cur_path) >= 0;
 });
@@ -79,10 +75,12 @@ const img_src = computed(() => {
 
   cursor: pointer;
 }
+
 .nav-item:hover {
   background-color: var(--color-fill-4);
   color: #fff;
 }
+
 .nav-item.is-active {
   background-color: rgb(var(--primary-6));
   color: #fff;
@@ -95,6 +93,7 @@ const img_src = computed(() => {
 
   margin-right: 5px;
 }
+
 .nav-item-icon img {
   width: 18px;
 }
@@ -102,6 +101,7 @@ const img_src = computed(() => {
 .nav-item-icon.arrow-down {
   margin-left: 2px;
 }
+
 .nav-item-icon.arrow-down img {
   width: 14px;
 }

+ 135 - 0
src/views/permission/Action.vue

@@ -0,0 +1,135 @@
+<template>
+  <div class="table-page-search-wrapper">
+    <div class="search-wrapper">
+      <div>
+        <a-input v-model="inputValue" :style="{ width: '320px' }" placeholder="请输入关键字查询" />
+      </div>
+      <div>
+        <a-button type="primary" style="margin-right: 20px; margin-left: 10px" @click="search">
+          <template #icon>
+            <icon-search />
+          </template>
+          查询
+        </a-button>
+        <a-button @click="reset">
+          <template #icon>
+            <icon-refresh />
+          </template>
+          重制
+        </a-button>
+      </div>
+    </div>
+    <div class="search-wrapper">
+      <div>
+        <a-space>
+          <a-button type="primary" @click="create">
+            <template #icon>
+              <icon-plus />
+            </template>
+            {{ btnText }}
+          </a-button>
+        </a-space>
+      </div>
+      <div class="wrapper-icon">
+        <a-tooltip content="刷新">
+          <div class="action-icon" @click="refresh">
+            <icon-refresh size="18" />
+          </div>
+        </a-tooltip>
+        <a-dropdown @select="sizeChange">
+          <a-tooltip content="密度">
+            <div class="action-icon">
+              <icon-line-height size="18" />
+            </div>
+          </a-tooltip>
+          <template #content>
+            <a-doption v-for="item in densityList" :key="item.value" :value="item.value"
+              :class="{ active: item.value === size }">
+              <span>{{ item.name }}</span>
+            </a-doption>
+          </template>
+        </a-dropdown>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, toRefs } from 'vue';
+const props = defineProps({
+  btnText: {
+    required: true,
+    type: String,
+  }
+});
+const { btnText } = toRefs(props);
+const inputValue = ref('');
+const size = ref('medium');
+const densityList = [
+  {
+    name: '迷你',
+    value: 'mini',
+  },
+  {
+    name: '偏小',
+    value: 'small',
+  },
+  {
+    name: '中等',
+    value: 'medium',
+  },
+  {
+    name: '偏大',
+    value: 'large',
+  },
+];
+
+const emit = defineEmits(['search', 'reset', 'createClick', 'refreshClick', 'sizeChange']);
+const search = () => {
+  emit('searchClick', inputValue.value);
+}
+const reset = () => {
+  inputValue.value = '';
+  emit('resetClick');
+}
+const create = () => {
+  emit('createClick');
+}
+const refresh = () => {
+  emit('refreshClick');
+}
+const sizeChange = (val) => {
+  size.value = val;
+  emit('sizeChange', val);
+};
+
+</script>
+
+<style lang="css" scoped>
+.table-page-search-wrapper {
+  background-color: #fff;
+  padding-top: 10px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+  padding-bottom: 10px;
+  border-bottom: 1px solid #e8e8e8;
+}
+
+.search-wrapper {
+  display: flex;
+}
+
+.wrapper-icon {
+  width: 60px;
+  margin-left: 16px;
+  display: flex;
+  justify-content: space-around;
+  align-items: center;
+}
+
+.wrapper-icon .action-icon {
+  cursor: pointer;
+}
+</style>

+ 0 - 54
src/views/permission/Actions.vue

@@ -1,54 +0,0 @@
-<template>
-  <div class="table-page-search-wrapper">
-    <div class="search-wrapper">
-      <div>
-        <a-input v-model="formModel.name" :style="{ width: '320px' }" :placeholder="$t('请输入')" />
-      </div>
-      <div>
-        <a-button type="primary" style="margin-right: 20px; margin-left: 10px" @click="search">
-          <template #icon>
-            <icon-search />
-          </template>
-          查询
-        </a-button>
-        <a-button @click="reset">
-          <template #icon>
-            <icon-refresh />
-          </template>
-          重制
-        </a-button>
-      </div>
-    </div>
-    <div class="search-wrapper">
-      <div>
-        <a-space>
-          <a-button type="primary" :align="'right'" @click="operation(0)">+ 新建用户组</a-button>
-        </a-space>
-      </div>
-      <div class="wrapper-icon">
-        <a-tooltip :content="$t('searchTable.actions.refresh')">
-          <div class="action-icon" @click="search">
-            <icon-refresh size="18" />
-          </div>
-        </a-tooltip>
-        <a-dropdown @select="handleSelectDensity">
-          <a-tooltip :content="$t('searchTable.actions.density')">
-            <div class="action-icon">
-              <icon-line-height size="18" />
-            </div>
-          </a-tooltip>
-          <template #content>
-            <a-doption v-for="item in densityList" :key="item.value" :value="item.value"
-              :class="{ active: item.value === size }">
-              <span>{{ item.name }}</span>
-            </a-doption>
-          </template>
-        </a-dropdown>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script setup>
-
-</script>

+ 10 - 27
src/views/permission/DataTable.vue

@@ -1,7 +1,6 @@
 <template>
-  <a-card>
-    <a-table :columns="columns" :data="data" :row-key="rowKey" :loading="loading" :pagination="false"
-      @sorter-change="handleSorterChange" @select="handleSelect" @select-all="handleSelectAll" @expand="handleExpand">
+  <div>
+    <a-table :columns="columns" :data="data" :row-key="rowKey" :size="size" :loading="loading" :pagination="false">
       <template v-for="item in columns" :key="item.slotName" #[item.slotName]="{ record, rowIndex, column }">
         <slot :name="item.slotName" v-bind="{ record, rowIndex, column }"></slot>
       </template>
@@ -12,9 +11,9 @@
         </a-popover>
       </template>
     </a-table>
-    <a-pagination class="pagination" v-if="pagination.total" :current="pagination.current" :total="pagination.total"
-      :page-size="pagination.pageSize" @change="handlePageChange" @show-size-change="handleSizeChange" />
-  </a-card>
+    <a-pagination v-if="pagination.total" class="pagination" :current="pagination.current" :total="pagination.total"
+      :page-size="pagination.pageSize" @change="handlePageChange" @page-size-change="handleSizeChange" />
+  </div>
 </template>
 
 <script setup>
@@ -25,42 +24,26 @@ const props = defineProps({
   data: Array,
   columns: Array,
   rowKey: String,
+  size: String,
   loading: Boolean,
   pagination: Object
 });
 
-const { data, columns, rowKey, loading, pagination } = toRefs(props);
+const { data, columns, rowKey, size, loading, pagination } = toRefs(props);
 
 // 定义 emit 事件
-const emit = defineEmits(['sorterChange', 'select', 'selectAll', 'expand', 'pageChange', 'sizeChange']);
+const emit = defineEmits(['expand', 'pageChange', 'sizeChange']);
 
 // 分页事件处理
 const handlePageChange = (page) => {
   emit('pageChange', page);
 };
 
-const handleSizeChange = (current, size) => {
-  emit('sizeChange', current, size);
+const handleSizeChange = (pageSize) => {
+  emit('pageSizeChange', pageSize);
 };
 
-// 排序事件处理
-const handleSorterChange = (sorter) => {
-  emit('sorterChange', sorter);
-};
-
-// 选择事件处理
-const handleSelect = (selected, record) => {
-  emit('select', selected, record);
-};
 
-const handleSelectAll = (selected, records) => {
-  emit('selectAll', selected, records);
-};
-
-// 展开事件处理
-const handleExpand = (expanded, record) => {
-  emit('expand', expanded, record);
-};
 </script>
 
 <style lang="css" scoped>