From 588048abd720ff3fcd69aa9322b632e50dd3a651 Mon Sep 17 00:00:00 2001
From: yinbangzhong <zhongbangyin@126.com>
Date: 星期六, 27 七月 2024 19:12:06 +0800
Subject: [PATCH] 权限

---
 src/views/authority/users/index.vue              |  500 +++++++++++++++++++++++++++++++++
 src/locale/en-US.ts                              |    6 
 src/views/authority/organization/locale/en-US.ts |    5 
 src/views/authority/organization/locale/zh-CN.ts |    4 
 src/locale/zh-CN.ts                              |    6 
 src/views/authority/users/locale/zh-CN.ts        |    3 
 src/api/interceptor.ts                           |   11 
 src/views/authority/users/locale/en-US.ts        |    4 
 src/api/authority.ts                             |   80 +++++
 src/assets/style/global.less                     |    4 
 src/views/authority/components/authheader.vue    |   15 +
 src/router/routes/modules/authority.ts           |   38 ++
 src/views/authority/organization/index.vue       |  222 ++++++++++++++
 13 files changed, 891 insertions(+), 7 deletions(-)

diff --git a/src/api/authority.ts b/src/api/authority.ts
new file mode 100644
index 0000000..0e4e193
--- /dev/null
+++ b/src/api/authority.ts
@@ -0,0 +1,80 @@
+import axios from "axios";
+import { Pagination } from "@/types/global";
+
+export interface User {
+  userId: string;
+  userName: string;
+  nickName: string;
+  email: string;
+  phoneNumber: string;
+  dept: any;
+  createTime: string;
+  status: string;
+}
+
+export interface Organization {
+  deptId: string;
+  deptName: string;
+  email: string;
+  leader: string;
+  phone: string;
+  orderNum: string;
+  parentId: string;
+  status: string;
+  address: string;
+  parentName: string;
+}
+
+export interface Result<T> {
+  code: number;
+  msg: string;
+  rows: T;
+  total: number;
+}
+
+export function UserList(params: Pagination) {
+  return axios.get<Result<User[]>>("/base/system/user/list", { params });
+}
+
+export function Userstatus(userID, status) {
+  return axios.put("/base/system/user/changeStatus", { "userId": userID, "status": status });
+}
+
+export function UserChangePwd(userId) {
+  return axios.put("/base/system/user/profile/updatePwd", { "userId": userId });
+}
+
+
+export function UserEdit(user) {
+  return axios.put("/base/system/user", { user });
+}
+
+export function UserAdd(user) {
+  return axios.post("/base/system/user", { user });
+}
+
+export function UserDelete(userId) {
+  return axios.delete("/base/system/user/" + userId);
+}
+
+export function OrganizationList(key: string) {
+  return axios.post<Result<Organization[]>>("/base/system/dept/list", { "deptName": key });
+}
+
+
+export function OrganizationAdd(organization) {
+  return axios.post("/base/system/dept", { organization });
+}
+
+export function OrganizationDelete(id) {
+  return axios.delete("/base/system/dept/" + id);
+}
+
+export function OrganizationUpdate(organization) {
+  return axios.put("/base/system/dept", { organization });
+}
+
+
+export function OrganizationById(id) {
+  return axios.get<Result<Organization>>("/base/system/dept/" + id);
+}
\ No newline at end of file
diff --git a/src/api/interceptor.ts b/src/api/interceptor.ts
index 000000d..09e9392 100644
--- a/src/api/interceptor.ts
+++ b/src/api/interceptor.ts
@@ -2,7 +2,7 @@
 import type { AxiosRequestConfig, AxiosResponse } from 'axios';
 import { Message, Modal } from '@arco-design/web-vue';
 import { useUserStore } from '@/store';
-import { getAuthorization, getToken, setAuthorization } from "@/utils/auth";
+import { getAuthorization, getToken, setAuthorization, setToken } from "@/utils/auth";
 
 export interface HttpResponse<T = unknown> {
   status: number;
@@ -14,7 +14,7 @@
 if (import.meta.env.VITE_API_BASE_URL) {
   axios.defaults.baseURL = import.meta.env.VITE_API_BASE_URL;
 }
-
+axios.defaults.withCredentials = true
 axios.interceptors.request.use(
   (config: AxiosRequestConfig) => {
     // let each request carry token
@@ -35,11 +35,8 @@
       if (!config.headers) {
         config.headers = {};
       }
-      config.headers.Authorization = authorization;
-      config.headers.token = getToken();
+      config.headers.Authorization = `${authorization}`;
     }
-
-    config.headers.Authorization = 'Ijg3NmFjZjJlNGIzMzExZWY4NzI0MDI0MmFjMTIwMDA2Ig.ZqNvxw.Kgp8PcT4n2cxpzxFrYHttO4i2Eo';
     return config;
   },
   (error) => {
@@ -79,7 +76,7 @@
       return Promise.reject(new Error(res.msg || 'Error'));
     }
 
-    if(response.config.url === '/v1/user/login')  {
+    if(response.config.url === '/v1/user/login'|| response.config.url === '/base/login')  {
       setAuthorization(response.headers.authorization);
     }
     return res;
diff --git a/src/assets/style/global.less b/src/assets/style/global.less
index f90b206..bf8d1ff 100644
--- a/src/assets/style/global.less
+++ b/src/assets/style/global.less
@@ -92,3 +92,7 @@
     }
   }
 }
+
+.container {
+    padding: 0 20px 20px 20px;
+}
\ No newline at end of file
diff --git a/src/locale/en-US.ts b/src/locale/en-US.ts
index 1da1e91..a8b9a48 100644
--- a/src/locale/en-US.ts
+++ b/src/locale/en-US.ts
@@ -3,6 +3,9 @@
 
 import localeWorkplace from '@/views/dashboard/workplace/locale/en-US';
 
+import localeUser from '@/views/authority/users/locale/en-US';
+import localeOrganization from '@/views/authority/organization/locale/en-US';
+
 import localeMonitor from '@/views/dashboard/monitor/locale/en-US';
 
 import localeSearchTable from '@/views/list/search-table/locale/en-US';
@@ -51,6 +54,9 @@
   ...localeLogin,
   ...localeWorkplace,
 
+  ...localeUser,
+  ...localeOrganization,
+
   ...localeMonitor,
   ...localeSearchTable,
   ...localeCardList,
diff --git a/src/locale/zh-CN.ts b/src/locale/zh-CN.ts
index 3e8f537..fb7b257 100644
--- a/src/locale/zh-CN.ts
+++ b/src/locale/zh-CN.ts
@@ -3,6 +3,9 @@
 
 import localeWorkplace from '@/views/dashboard/workplace/locale/zh-CN';
 
+import localeUser from '@/views/authority/users/locale/zh-CN';
+import localeOrganization from '@/views/authority/organization/locale/zh-CN';
+
 import localeMonitor from '@/views/dashboard/monitor/locale/zh-CN';
 
 import localeSearchTable from '@/views/list/search-table/locale/zh-CN';
@@ -54,6 +57,9 @@
   ...localeLogin,
   ...localeWorkplace,
 
+  ...localeUser,
+  ...localeOrganization,
+
   ...localeMonitor,
   ...localeSearchTable,
   ...localeCardList,
diff --git a/src/router/routes/modules/authority.ts b/src/router/routes/modules/authority.ts
new file mode 100644
index 0000000..de853c3
--- /dev/null
+++ b/src/router/routes/modules/authority.ts
@@ -0,0 +1,38 @@
+import { DEFAULT_LAYOUT } from '../base';
+import { AppRouteRecordRaw } from '../types';
+
+const AUTHORITY: AppRouteRecordRaw = {
+  path: '/authority',
+  name: 'authority',
+  component: DEFAULT_LAYOUT,
+  meta: {
+    locale: 'menu.authority',
+    requiresAuth: true,
+    icon: 'icon-lock',
+    order: 1,
+  },
+  children: [
+    {
+      path: 'users',
+      name: 'users',
+      component: () => import('@/views/authority/users/index.vue'),
+      meta: {
+        locale: 'menu.user.title',
+        requiresAuth: true,
+        roles: ['*'],
+      },
+    },
+    {
+      path: 'organization',
+      name: 'organization',
+      component: () => import('@/views/authority/organization/index.vue'),
+      meta: {
+        locale: 'menu.organization.title',
+        requiresAuth: true,
+        roles: ['*'],
+      },
+    },
+  ],
+};
+
+export default AUTHORITY;
\ No newline at end of file
diff --git a/src/views/authority/components/authheader.vue b/src/views/authority/components/authheader.vue
new file mode 100644
index 0000000..d5fff12
--- /dev/null
+++ b/src/views/authority/components/authheader.vue
@@ -0,0 +1,15 @@
+<template>
+  <Breadcrumb :items="items" />
+</template>
+<script lang="ts" setup>
+import { PropType } from 'vue';
+
+defineProps({
+  items: {
+    type: Array as PropType<string[]>,
+    default() {
+      return [];
+    },
+  },
+});
+</script>
\ No newline at end of file
diff --git a/src/views/authority/organization/index.vue b/src/views/authority/organization/index.vue
new file mode 100644
index 0000000..8da1c6c
--- /dev/null
+++ b/src/views/authority/organization/index.vue
@@ -0,0 +1,222 @@
+<template>
+  <div class="container">
+    <authheader :items="menuTips"></authheader>
+
+    <a-row :gutter="20">
+      <a-col :span="8">
+        <a-card :title="$t('menu.organization.title')" :bordered="false" :style="{ width: '100%',height: '900px', 'overflow-y': 'auto' }">
+          <a-tree
+            class="tree-demo"
+            draggable
+            blockNode
+            :data="treeData"
+            :show-line="showLine"
+            :fieldNames="{
+              key:'deptId',
+              title:'deptName',
+              children:'children',
+            }"
+            @drop="onDrop"
+            @select="showDetail"
+          >
+            <template #extra="nodeData">
+              <IconPlus
+                style="position: absolute; right: 60px; font-size: 12px; top: 10px; color: #3370ff;"
+                @click="() => onIconClick(nodeData)"
+              />
+              <IconDelete style="position: absolute; right: 40px; font-size: 12px; top: 10px; color: #3370ff;"
+                          @click="() => onIconClickDelete(nodeData)" />
+            </template>
+          </a-tree>
+
+        </a-card>
+      </a-col>
+      <a-col :span="16">
+        <a-card :title="$t('menu.organization.detail')" :bordered="false" :style="{ width: '100%' }">
+          <a-form :model="deptform" layout="horizontal">
+            <a-form-item field="parentName" label="涓婄骇鏈烘瀯">
+              <a-input v-model="deptform.parentId" />
+            </a-form-item>
+            <a-form-item field="status" label="鏈烘瀯鐘舵��">
+              <a-switch checked-value="0" unchecked-value="1" v-model="deptform.status"></a-switch>
+            </a-form-item>
+            <a-form-item field="deptName" label="鏈烘瀯鍚嶇О">
+              <a-input v-model="deptform.deptName" />
+            </a-form-item>
+            <a-form-item field="leader" label="鑱旂郴浜�">
+              <a-input v-model="deptform.leader" />
+            </a-form-item>
+            <a-form-item field="phone" label="鑱旂郴鐢佃瘽">
+              <a-input v-model="deptform.phone" />
+            </a-form-item>
+            <a-form-item field="address" label="鏈烘瀯鍦板潃" style="align: start">
+              <a-input v-model="deptform.address" />
+            </a-form-item>
+            <a-form-item>
+              <a-space>
+                <a-button  @click="editdept">淇濆瓨</a-button>
+                <a-button @click="reset(deptform.deptId)">閲嶇疆</a-button>
+              </a-space>
+            </a-form-item>
+          </a-form>
+        </a-card>
+      </a-col>
+    </a-row>
+    <a-modal width="50%" v-model:visible="visible" title="鏂板" @cancel="handleCancel" @ok="addDept">
+      <a-form :model="deptform" layout="horizontal">
+        <a-form-item field="parentName" label="涓婄骇鏈烘瀯">
+          <a-input v-model="deptform.parentName" />
+        </a-form-item>
+        <a-form-item field="status" label="鏈烘瀯鐘舵��">
+          <a-switch checked-value="0" unchecked-value="1" v-model="deptform.status"></a-switch>
+        </a-form-item>
+        <a-form-item field="deptName" label="鏈烘瀯鍚嶇О">
+          <a-input v-model="deptform.deptName" />
+        </a-form-item>
+        <a-form-item field="leader" label="鑱旂郴浜�">
+          <a-input v-model="deptform.leader" />
+        </a-form-item>
+        <a-form-item field="phone" label="鑱旂郴鐢佃瘽">
+          <a-input v-model="deptform.phone" />
+        </a-form-item>
+        <a-form-item field="address" label="鏈烘瀯鍦板潃" style="align: start">
+          <a-input v-model="deptform.address" />
+        </a-form-item>
+      </a-form>
+    </a-modal>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { ref } from "vue";
+import { IconPlus } from "@arco-design/web-vue/es/icon";
+import {
+  Organization,
+  OrganizationAdd,
+  OrganizationById,
+  OrganizationDelete,
+  OrganizationList,
+  OrganizationUpdate
+} from "@/api/authority";
+import Authheader from "@/views/authority/components/authheader.vue";
+import { Modal } from "@arco-design/web-vue";
+
+let visible = ref(false);
+let treeData = ref([]);
+let showLine = ref(true);
+let menuTips = ref(["鏉冮檺绠$悊", "鏈烘瀯"]);
+let deptform = ref<Organization>({
+  deptName: "",
+  email: "",
+  leader: "",
+  orderNum: "0",
+  parentId: "",
+  parentName: "",
+  phone: "",
+  status: "",
+  address: "",
+  deptId: ""
+});
+
+const onIconClick = (nodeData) => {
+  deptform.value.parentName = nodeData.deptName;
+  deptform.value.parentId = nodeData.deptId;
+  visible.value = true;
+};
+
+const addDept = async () => {
+  await OrganizationAdd({
+    ...deptform.value
+  } as unknown as Organization).then((res) => {
+    OrganizationData("");
+  });
+};
+
+const onIconClickDelete = (nodeData) => {
+  OrganizationDelete(nodeData.deptId).then(() => {
+    OrganizationData("");
+  });
+};
+
+const showDetail = (id) => {
+  OrganizationById(id).then((res) => {
+    deptform.value = {...res.data};
+  });
+};
+const editdept=()=>{
+   OrganizationUpdate({
+    ...deptform.value
+  } as unknown as Organization).then((res) => {
+    OrganizationData("");
+     Modal.success({
+       title: "淇濆瓨鎴愬姛",
+       content: "淇濆瓨鎴愬姛"
+     });
+  });
+}
+const reset=(id)=>{
+  OrganizationById(id).then((res) => {
+    deptform.value = {...res.data};
+  });
+}
+
+const onDrop = ({ dragNode, dropNode, dropPosition }) => {
+  const data = treeData.value;
+  OrganizationUpdate({
+    orderNum: "0", parentId: dropNode.deptId, deptId: dragNode.deptId
+  });
+  const loop = (data, key, callback) => {
+    data.some((item, index, arr) => {
+      if (item.deptId === key) {
+        callback(item, index, arr);
+        return true;
+      }
+      if (item.children) {
+        return loop(item.children, key, callback);
+      }
+      return false;
+    });
+  };
+
+  loop(data, dragNode.deptId, (_, index, arr) => {
+    arr.splice(index, 1);
+  });
+
+  if (dropPosition === 0) {
+    loop(data, dropNode.deptId, (item) => {
+      item.children = item.children || [];
+      item.children.push(dragNode);
+    });
+  } else {
+    loop(data, dropNode.deptId, (_, index, arr) => {
+      arr.splice(dropPosition < 0 ? index : index + 1, 0, dragNode);
+    });
+  }
+};
+
+const OrganizationData = async (key) => {
+  await OrganizationList(key).then((res) => {
+    treeData.value = [...res.rows];
+  });
+};
+
+OrganizationData("");
+</script>
+
+
+<style scoped>
+.tree-demo :deep(.tree-node-dropover) > :deep(.arco-tree-node-title),
+.tree-demo :deep(.tree-node-dropover) > :deep(.arco-tree-node-title):hover {
+  animation: blinkBg 0.4s 2;
+}
+
+@keyframes blinkBg {
+  0% {
+    background-color: transparent;
+  }
+
+  100% {
+    background-color: var(--color-primary-light-1);
+  }
+}
+</style>
diff --git a/src/views/authority/organization/locale/en-US.ts b/src/views/authority/organization/locale/en-US.ts
new file mode 100644
index 0000000..44a0554
--- /dev/null
+++ b/src/views/authority/organization/locale/en-US.ts
@@ -0,0 +1,5 @@
+export default {
+  "menu.organization.title": "Organization",
+  'menu.organization.detail': 'Detail',
+};
+// export default { "menu.user.title": "Account" };
\ No newline at end of file
diff --git a/src/views/authority/organization/locale/zh-CN.ts b/src/views/authority/organization/locale/zh-CN.ts
new file mode 100644
index 0000000..83ed76d
--- /dev/null
+++ b/src/views/authority/organization/locale/zh-CN.ts
@@ -0,0 +1,4 @@
+export default {
+  'menu.organization.title': '鏈烘瀯',
+  'menu.organization.detail': '璇︽儏',
+};
\ No newline at end of file
diff --git a/src/views/authority/users/index.vue b/src/views/authority/users/index.vue
new file mode 100644
index 0000000..097ab35
--- /dev/null
+++ b/src/views/authority/users/index.vue
@@ -0,0 +1,500 @@
+<template>
+  <div class="container">
+    <authheader :items="menuTips"></authheader>
+    <a-card ref="account" class="general-card" :title="$t('menu.user.title')">
+      <a-row>
+        <a-col :flex="2"></a-col>
+        <a-col :flex="1">
+          <a-form :model="formModel">
+            <a-form-item field="name">
+              <a-input v-model="formModel.name" :style="{width:'320px'}" :placeholder="$t('璇疯緭鍏�')" />
+            </a-form-item>
+          </a-form>
+        </a-col>
+        <a-divider style="height: 40px" direction="vertical" />
+        <a-col :flex="'200px'" style="text-align: right">
+          <a-button @click="reset" style="margin-right: 20px">
+            <template #icon>
+              <icon-refresh />
+            </template>
+            {{ $t("searchTable.form.reset") }}
+          </a-button>
+          <a-button type="primary" @click="search">
+            <template #icon>
+              <icon-search />
+            </template>
+            {{ $t("searchTable.form.search") }}
+          </a-button>
+        </a-col>
+      </a-row>
+      <a-divider style="margin-top: 0" />
+      <a-row style="margin-bottom: 16px">
+        <a-col :span="12">
+          <a-space>
+            <a-button type="primary" :align="'right'" @click="operation(0)">+ 鏂板缓璐︽埛</a-button>
+          </a-space>
+        </a-col>
+        <a-col
+          :span="12"
+          style="display: flex; align-items: center; justify-content: end"
+        >
+          <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>
+        </a-col>
+      </a-row>
+      <a-table
+        row-key="id"
+        :loading="loading"
+        :pagination="pagination"
+        :columns="columns"
+        :data="renderData"
+        :bordered="false"
+        :size="size"
+        @page-change="onPageChange"
+      >
+        <template #index="{ rowIndex }">
+          {{ rowIndex + 1 + (pagination.current - 1) * pagination.pageSize }}
+        </template>
+        <template #dept="{ record }">{{ record.dept ? record.dept.deptName : "" }}</template>
+        <template #status="{record}">
+          <a-switch checked-value="0" unchecked-value="1" @change="statusChange(record.status,record)"
+                    v-model="record.status" />
+        </template>
+        <template #operations="{ record }">
+          <a-button type="outline" @click="operation(1,record)">閲嶇疆瀵嗙爜</a-button>
+          <a-button type="outline" @click="operation(2,record)">缂栬緫</a-button>
+          <a-popconfirm content="Are you sure you want to delete?" type="success" @ok="operation(3,record)">
+            <a-button type="outline">鍒犻櫎</a-button>
+          </a-popconfirm>
+          <a-button type="outline" @click="operation(4,record)">鏉冮檺閰嶇疆</a-button>
+          <a-button type="outline" @click="operation(5,record)">閮ㄩ棬閰嶇疆</a-button>
+        </template>
+      </a-table>
+    </a-card>
+    <a-modal v-model:visible="visible" :title="save" @cancel="handleCancel(1)" @ok="editHandleOk">
+      <a-form :model="editform">
+        <a-form-item field="name" label="鏄电О">
+          <a-input v-model="editform.nickName" />
+        </a-form-item>
+        <a-form-item field="userName" label="鐢ㄦ埛鍚�">
+          <a-input v-model="editform.userName" />
+        </a-form-item>
+        <a-form-item field="phoneNumber" label="鎵嬫満鍙�">
+          <a-input v-model="editform.phoneNumber" />
+        </a-form-item>
+        <a-form-item field="email" label="閭">
+          <a-input v-model="editform.email" />
+        </a-form-item>
+      </a-form>
+    </a-modal>
+    <a-modal width="50%" v-model:visible="deptvisible" title="閮ㄩ棬閰嶇疆" @cancel="handleCancel(2)"
+             @ok="editDeptHandleOk">
+      <div :style="{ display: 'flex' }">
+        <a-card :style="{ width: '460px',height: '500px', 'overflow-y': 'auto' }" title="鏈烘瀯" hoverable>
+          <a-tree
+            class="tree-demo"
+            v-model:checked-keys="checkedKeys"
+            v-model:expanded-keys="expandKdys"
+            :checkable="true"
+            :data="treeData"
+            :show-line="showLine"
+            @check="onCheck"
+            :fieldNames="{
+              key:'deptId',
+              title:'deptName',
+              children:'children',
+            }"
+            :check-strictly="checkStrictly"
+          >
+          </a-tree>
+        </a-card>
+        <a-card
+          class="card-demo"
+          title="鐢ㄦ埛鎵�灞炴満鏋�"
+          hoverable
+        >
+          <a-space wrap>
+            <a-tag
+              v-for="(tag, index) of checkStrictly"
+              :key="tag.deptId"
+              @close="handleRemove(tag)"
+            >
+              {{ tag.deptName }}
+            </a-tag>
+          </a-space>
+        </a-card>
+      </div>
+
+    </a-modal>
+    <a-modal width="30%" v-model:visible="resourcevisible" title="鏉冮檺閰嶇疆" @cancel="handleCancel(3)"
+             @ok="editDeptHandleOk">
+      <div :style="{ display:'flex', 'flex-direction':'column' }">
+        <a-tabs :style="{ width: '100%',height: '500px', 'overflow-y': 'auto' }">
+          <a-tab-pane key="1">
+            <template #title>
+              <icon-calendar/> 鑿滃崟
+            </template>
+            Content of Tab Panel 1
+          </a-tab-pane>
+          <a-tab-pane key="2">
+            <template #title>
+              <icon-clock-circle/> 鐭ヨ瘑搴�
+            </template>
+            Content of Tab Panel 2
+          </a-tab-pane>
+          <a-tab-pane key="3">
+            <template #title>
+              <icon-user/> 鏅鸿兘浣�
+            </template>
+            Content of Tab Panel 3
+          </a-tab-pane>
+        </a-tabs>
+        <a-card  :style="{ width: '100%',height: '200px', 'overflow-y': 'auto', margin:'1px'}"
+          class="card-demo"
+          title="鐢ㄦ埛鎵�鏈夋潈闄�"
+          hoverable
+        >
+          <a-space wrap>
+            <a-tag
+              v-for="(tag, index) of checkResourceStrictly"
+              :key="tag.deptId"
+              @close="handleRemove(tag)"
+            >
+              {{ tag.deptName }}
+            </a-tag>
+          </a-space>
+        </a-card>
+      </div>
+
+    </a-modal>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { computed, reactive, ref } from "vue";
+import { useI18n } from "vue-i18n";
+import useLoading from "@/hooks/loading";
+import { Pagination } from "@/types/global";
+import type { TableColumnData } from "@arco-design/web-vue/es/table/interface";
+import {
+  OrganizationList,
+  User,
+  UserAdd,
+  UserChangePwd,
+  UserDelete,
+  UserEdit,
+  UserList,
+  Userstatus
+} from "@/api/authority";
+import { Modal } from "@arco-design/web-vue";
+import Authheader from "@/views/authority/components/authheader.vue";
+
+let treeData = ref([]);
+let checkedKeys = ref([]);
+let expandKdys = ref([]);
+let checkStrictly = ref([]);
+let checkResourceStrictly=ref([])
+let menuTips = ref(["鏉冮檺绠$悊", "璐﹀彿"]);
+type SizeProps = "mini" | "small" | "medium" | "large";
+const account = ref(null);
+const generateFormModel = () => {
+  return {
+    name: ""
+  };
+};
+let showLine = ref(true);
+const { loading, setLoading } = useLoading(true);
+const { t } = useI18n();
+let save = ref("鏂板");
+let renderData = ref<User[]>([]);
+let formModel = ref(generateFormModel());
+let editform = ref<User>({
+  createTime: "",
+  dept: undefined,
+  email: "",
+  nickName: "",
+  phoneNumber: "",
+  status: "",
+  userId: "",
+  userName: ""
+});
+
+let size = ref<SizeProps>("medium");
+let visible = ref(false);
+let deptvisible = ref(false);
+let resourcevisible = ref(false);
+let selectUser = ref({});
+
+const onCheck = (newCheckedKeys, event) => {
+  let o = { "deptId": event.node.deptId, "deptName": event.node.deptName };
+  if (event.checked) {
+    checkStrictly.value.push(o);
+  } else {
+    checkStrictly.value.forEach((val, idx, array) => {
+      // val: 褰撳墠鍊�
+      if (val.deptId == event.node.deptId) {
+        checkStrictly.value.splice(idx, 1);
+        return true;
+      }
+    });
+
+  }
+};
+const handleRemove = (key) => {
+  checkStrictly.value = checkStrictly.value.filter((tag) => tag !== key);
+};
+const basePagination: Pagination = {
+  current: 1,
+  pageSize: 20
+};
+const pagination = reactive({
+  ...basePagination
+});
+
+const densityList = computed(() => [
+  {
+    name: t("searchTable.size.mini"),
+    value: "mini"
+  },
+  {
+    name: t("searchTable.size.small"),
+    value: "small"
+  },
+  {
+    name: t("searchTable.size.medium"),
+    value: "medium"
+  },
+  {
+    name: t("searchTable.size.large"),
+    value: "large"
+  }
+]);
+const columns = computed<TableColumnData[]>(() => [
+  {
+    title: t("搴忓彿"),
+    dataIndex: "index",
+    slotName: "index"
+  },
+  {
+    title: t("鐢ㄦ埛鍚�"),
+    dataIndex: "userName"
+  },
+  {
+    title: t("鍒涘缓鏃堕棿"),
+    dataIndex: "createTime"
+  },
+  {
+    title: t("鎵�灞為儴闂�"),
+    dataIndex: "dept",
+    slotName: "dept"
+  },
+  {
+    title: t("鐘舵��"),
+    dataIndex: "status",
+    slotName: "status"
+  },
+  {
+    title: t("searchTable.columns.operations"),
+    dataIndex: "operations",
+    slotName: "operations"
+  }
+]);
+
+const statusChange = async (value, record) => {
+  await Userstatus(record.userId, value).then((res) => {
+
+  });
+};
+
+const handleCancel = (type) => {
+  if (type == 1) {
+    visible.value = false;
+  }
+  if (type == 2) {
+    deptvisible.value = false;
+  }
+  if (type == 2) {
+    resourcevisible.value = false;
+  }
+
+};
+
+const editDeptHandleOk = async () => {
+  let depts: Array = [], user: User = { "userId": selectUser.value.userId };
+  checkStrictly.value.forEach((val) => {
+    depts.push(val.deptId);
+  });
+  user.dept = depts;
+  await UserEdit(user).then((res) => {
+    fetchData();
+  });
+};
+
+const editHandleOk = async () => {
+  if (editform.value.userId.length > 0) {
+    await UserEdit({
+      ...editform.value
+    } as unknown as User).then((res) => {
+      fetchData();
+    });
+  } else {
+    await UserAdd({
+      ...editform.value
+    } as unknown as User).then((res) => {
+      fetchData();
+    });
+  }
+};
+const operation = async (t, record) => {
+  if (t == 0) {
+    save.value = "鏂板";
+    visible.value = true;
+    editform.value.userId = "";
+    editform.value.userName = "";
+    editform.value.nickName = "";
+    editform.value.email = "";
+    editform.value.phoneNumber = "";
+  }
+//閲嶇疆瀵嗙爜
+  if (t == 1) {
+    await UserChangePwd(record.userId).then((res) => {
+      if (res.code == 20000) {
+        Modal.success({
+          title: "閲嶇疆瀵嗙爜",
+          content: "璇ョ敤鎴峰瘑鐮侀噸缃负000000"
+        });
+      } else {
+        Modal.error({
+          title: "閲嶇疆瀵嗙爜",
+          content: "璇ョ敤鎴峰瘑鐮侀噸缃け璐�"
+        });
+      }
+    });
+  }
+  //缂栬緫
+  if (t == 2) {
+    visible.value = true;
+    save.value = "缂栬緫";
+    editform.value.userId = record.userId;
+    editform.value.userName = record.userName;
+    editform.value.nickName = record.nickName;
+    editform.value.email = record.email;
+    editform.value.phoneNumber = record.phoneNumber;
+  }
+  //鍒犻櫎
+  if (t == 3) {
+    await UserDelete(record.userId).then((res) => {
+      if (res.code == 20000) {
+        fetchData();
+      }
+    });
+  }
+  //鏉冮檺
+  if (t == 4) {
+    resourcevisible.value = true;
+
+
+  }
+  //鏈烘瀯
+  if (t == 5) {
+    deptvisible.value = true;
+    checkedKeys.value = [];
+    expandKdys.value = [];
+    checkStrictly.value = [];
+    selectUser.value = record;
+    expandKdys.value.push("0");
+    record.dept.forEach((val) => {
+      checkStrictly.value.push({ "deptId": val.deptId, "deptName": val.deptName });
+      checkedKeys.value.push(val.deptId);
+      expandKdys.value.push(val.deptId);
+    });
+
+  }
+};
+
+const fetchData = async (
+  params: Pagination = { current: 1, pageSize: 20 }
+) => {
+  setLoading(true);
+  try {
+    await UserList(params).then((res) => {
+      renderData.value = res.rows;
+      console.log(renderData);
+      pagination.current = params.current;
+      pagination.total = res.total;
+    });
+  } catch (err) {
+    // you can report use errorHandler or other
+  } finally {
+    setLoading(false);
+  }
+};
+
+const search = () => {
+  fetchData({
+    ...basePagination,
+    ...formModel.value
+  } as unknown as Pagination);
+};
+
+const onPageChange = (current: number) => {
+  fetchData({ ...basePagination, current });
+};
+
+const OrganizationData = async (key) => {
+  await OrganizationList(key).then((res) => {
+    treeData.value = [...res.rows];
+  });
+};
+
+fetchData();
+OrganizationData("");
+
+const reset = () => {
+  formModel.value = generateFormModel();
+};
+
+const handleSelectDensity = (
+  val: string | number | Record<string, any> | undefined,
+  e: Event
+) => {
+  size.value = val as SizeProps;
+};
+
+</script>
+
+
+<style scoped>
+.card-demo {
+  width: 460px;
+  margin-left: 24px;
+  transition-property: all;
+}
+
+.card-demo:hover {
+  transform: translateY(-4px);
+}
+</style>
+
diff --git a/src/views/authority/users/locale/en-US.ts b/src/views/authority/users/locale/en-US.ts
new file mode 100644
index 0000000..d88f727
--- /dev/null
+++ b/src/views/authority/users/locale/en-US.ts
@@ -0,0 +1,4 @@
+export default {
+  "menu.user.title": "Account",
+};
+// export default { "menu.user.title": "Account" };
\ No newline at end of file
diff --git a/src/views/authority/users/locale/zh-CN.ts b/src/views/authority/users/locale/zh-CN.ts
new file mode 100644
index 0000000..b3e03a8
--- /dev/null
+++ b/src/views/authority/users/locale/zh-CN.ts
@@ -0,0 +1,3 @@
+export default {
+  'menu.user.title': '璐︽埛',
+};
\ No newline at end of file

--
Gitblit v1.8.0