zuohuaijun 3 лет назад
Родитель
Сommit
5c68bff283

+ 3 - 3
Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj

@@ -24,9 +24,9 @@
 
   <ItemGroup>
     <PackageReference Include="AspNetCoreRateLimit" Version="4.0.2" />
-    <PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.5.8" />
-    <PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.5.8" />
-    <PackageReference Include="Furion.Pure" Version="4.5.8" />
+    <PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.5.9" />
+    <PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.5.9" />
+    <PackageReference Include="Furion.Pure" Version="4.5.9" />
     <PackageReference Include="Magicodes.IE.Excel" Version="2.6.4" />
     <PackageReference Include="Magicodes.IE.Pdf" Version="2.6.4" />
     <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.9" />

+ 0 - 25
Admin.NET/Admin.NET.Core/Admin.NET.Core.xml

@@ -5860,11 +5860,6 @@
             </summary>
             <returns></returns>
         </member>
-        <member name="P:Admin.NET.Core.Service.OrgInput.Pid">
-            <summary>
-            父Id
-            </summary>
-        </member>
         <member name="P:Admin.NET.Core.Service.OrgInput.Name">
             <summary>
             名称
@@ -5875,26 +5870,6 @@
             编码
             </summary>
         </member>
-        <member name="P:Admin.NET.Core.Service.OrgInput.Order">
-            <summary>
-            排序
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.OrgInput.Remark">
-            <summary>
-            备注
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.OrgInput.Status">
-            <summary>
-            状态
-            </summary>
-        </member>
-        <member name="P:Admin.NET.Core.Service.OrgInput.Level">
-            <summary>
-            级别 例如:省、市、县、区
-            </summary>
-        </member>
         <member name="P:Admin.NET.Core.Service.AddOrgInput.Name">
             <summary>
             名称

+ 5 - 28
Admin.NET/Admin.NET.Core/Service/Org/Dto/OrgInput.cs

@@ -2,43 +2,19 @@
 
 public class OrgInput : BaseIdInput
 {
-    /// <summary>
-    /// 父Id
-    /// </summary>
-    public virtual long Pid { get; set; }
-
     /// <summary>
     /// 名称
     /// </summary>
-    public virtual string Name { get; set; }
+    public string Name { get; set; }
 
     /// <summary>
     /// 编码
     /// </summary>
-    public virtual string Code { get; set; }
-
-    /// <summary>
-    /// 排序
-    /// </summary>
-    public virtual int Order { get; set; }
-
-    /// <summary>
-    /// 备注
-    /// </summary>
-    public virtual string Remark { get; set; }
-
-    /// <summary>
-    /// 状态
-    /// </summary>
-    public virtual int Status { get; set; }
-
-    /// <summary>
-    /// 级别 例如:省、市、县、区
-    /// </summary>
-    public virtual string Level { get; set; }
+    public string Code { get; set; }
 }
 
-public class AddOrgInput : OrgInput
+[NotTable]
+public class AddOrgInput : SysOrg
 {
     /// <summary>
     /// 名称
@@ -47,6 +23,7 @@ public class AddOrgInput : OrgInput
     public override string Name { get; set; }
 }
 
+[NotTable]
 public class UpdateOrgInput : AddOrgInput
 {
 }

+ 13 - 9
Admin.NET/Admin.NET.Core/Service/Org/SysOrgService.cs

@@ -53,15 +53,19 @@ public class SysOrgService : IDynamicApiController, ITransient
         var orgIdList = input.Id > 0 ? await GetChildIdListWithSelfById(input.Id) : await GetUserOrgIdList();
 
         var iSugarQueryable = _sysOrgRep.AsQueryable().OrderBy(u => u.Order)
-            .WhereIF(orgIdList.Count > 0, u => orgIdList.Contains(u.Id)); // 非超级管理员限制
+            .WhereIF(orgIdList.Count > 0, u => orgIdList.Contains(u.Id));
 
-        if (!string.IsNullOrWhiteSpace(input.Name) || !string.IsNullOrWhiteSpace(input.Code) || input.Id > 0)
+        // 条件筛选可能造成无法构造树(列表数据)
+        if (!string.IsNullOrWhiteSpace(input.Name) || !string.IsNullOrWhiteSpace(input.Code))
         {
-            iSugarQueryable = iSugarQueryable
+            return await iSugarQueryable
                 .WhereIF(!string.IsNullOrWhiteSpace(input.Name), u => u.Name.Contains(input.Name))
-                .WhereIF(!string.IsNullOrWhiteSpace(input.Code), u => u.Code.Contains(input.Code));
+                .WhereIF(!string.IsNullOrWhiteSpace(input.Code), u => u.Code.Contains(input.Code))
+                .ToListAsync();
         }
-        return await iSugarQueryable.ToTreeAsync(u => u.Children, u => u.Pid, input.Id > 0 ? input.Id : 0);
+        return input.Id > 0
+            ? await iSugarQueryable.ToChildListAsync(u => u.Pid, input.Id)
+            : await iSugarQueryable.ToTreeAsync(u => u.Children, u => u.Pid, 0);
     }
 
     /// <summary>
@@ -160,15 +164,15 @@ public class SysOrgService : IDynamicApiController, ITransient
                 throw Oops.Oh(ErrorCodeEnum.D2003);
         }
 
-        // 若子机构有用户则禁止删除
-        var orgTreeList = await _sysOrgRep.AsQueryable().ToChildListAsync(u => u.Pid, input.Id);
-        var orgIdList = orgTreeList.Select(u => u.Id).ToList();
-
         // 若附属机构有用户则禁止删除
         var hasExtOrgEmp = await _sysEmpExtOrgPosService.HasExtOrgEmp(sysOrg.Id);
         if (hasExtOrgEmp)
             throw Oops.Oh(ErrorCodeEnum.D2005);
 
+        // 若子机构有用户则禁止删除
+        var orgTreeList = await _sysOrgRep.AsQueryable().ToChildListAsync(u => u.Pid, input.Id);
+        var orgIdList = orgTreeList.Select(u => u.Id).ToList();
+
         // 级联删除机构子节点
         await _sysOrgRep.DeleteAsync(u => orgIdList.Contains(u.Id));
 

+ 0 - 4
vue-next-admin/.eslintrc.js

@@ -59,9 +59,5 @@ module.exports = {
 		'no-v-model-argument': 'off',
 		'no-case-declarations': 'off',
 		'no-console': 'off',
-		"vue/no-reserved-component-names": ["error", {
-			"disallowVueBuiltInComponents": false,
-			"disallowVue3BuiltInComponents": false
-		}],
 	},
 };

+ 7 - 47
vue-next-admin/src/api-services/apis/sys-org-api.ts

@@ -113,17 +113,12 @@ export const SysOrgApiAxiosParamCreator = function (configuration?: Configuratio
          * 
          * @summary 获取机构列表
          * @param {number} id 主键Id
-         * @param {number} [pid] 父Id
          * @param {string} [name] 名称
          * @param {string} [code] 编码
-         * @param {number} [order] 排序
-         * @param {string} [remark] 备注
-         * @param {number} [status] 状态
-         * @param {string} [level] 级别 例如:省、市、县、区
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        sysOrgListGet: async (id: number, pid?: number, name?: string, code?: string, order?: number, remark?: string, status?: number, level?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+        sysOrgListGet: async (id: number, name?: string, code?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
             // verify required parameter 'id' is not null or undefined
             if (id === null || id === undefined) {
                 throw new RequiredError('id','Required parameter id was null or undefined when calling sysOrgListGet.');
@@ -141,10 +136,6 @@ export const SysOrgApiAxiosParamCreator = function (configuration?: Configuratio
 
             // authentication Bearer required
 
-            if (pid !== undefined) {
-                localVarQueryParameter['Pid'] = pid;
-            }
-
             if (name !== undefined) {
                 localVarQueryParameter['Name'] = name;
             }
@@ -153,22 +144,6 @@ export const SysOrgApiAxiosParamCreator = function (configuration?: Configuratio
                 localVarQueryParameter['Code'] = code;
             }
 
-            if (order !== undefined) {
-                localVarQueryParameter['Order'] = order;
-            }
-
-            if (remark !== undefined) {
-                localVarQueryParameter['Remark'] = remark;
-            }
-
-            if (status !== undefined) {
-                localVarQueryParameter['Status'] = status;
-            }
-
-            if (level !== undefined) {
-                localVarQueryParameter['Level'] = level;
-            }
-
             if (id !== undefined) {
                 localVarQueryParameter['Id'] = id;
             }
@@ -313,18 +288,13 @@ export const SysOrgApiFp = function(configuration?: Configuration) {
          * 
          * @summary 获取机构列表
          * @param {number} id 主键Id
-         * @param {number} [pid] 父Id
          * @param {string} [name] 名称
          * @param {string} [code] 编码
-         * @param {number} [order] 排序
-         * @param {string} [remark] 备注
-         * @param {number} [status] 状态
-         * @param {string} [level] 级别 例如:省、市、县、区
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async sysOrgListGet(id: number, pid?: number, name?: string, code?: string, order?: number, remark?: string, status?: number, level?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListSysOrg>>> {
-            const localVarAxiosArgs = await SysOrgApiAxiosParamCreator(configuration).sysOrgListGet(id, pid, name, code, order, remark, status, level, options);
+        async sysOrgListGet(id: number, name?: string, code?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListSysOrg>>> {
+            const localVarAxiosArgs = await SysOrgApiAxiosParamCreator(configuration).sysOrgListGet(id, name, code, options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
                 return axios.request(axiosRequestArgs);
@@ -391,18 +361,13 @@ export const SysOrgApiFactory = function (configuration?: Configuration, basePat
          * 
          * @summary 获取机构列表
          * @param {number} id 主键Id
-         * @param {number} [pid] 父Id
          * @param {string} [name] 名称
          * @param {string} [code] 编码
-         * @param {number} [order] 排序
-         * @param {string} [remark] 备注
-         * @param {number} [status] 状态
-         * @param {string} [level] 级别 例如:省、市、县、区
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async sysOrgListGet(id: number, pid?: number, name?: string, code?: string, order?: number, remark?: string, status?: number, level?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListSysOrg>> {
-            return SysOrgApiFp(configuration).sysOrgListGet(id, pid, name, code, order, remark, status, level, options).then((request) => request(axios, basePath));
+        async sysOrgListGet(id: number, name?: string, code?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListSysOrg>> {
+            return SysOrgApiFp(configuration).sysOrgListGet(id, name, code, options).then((request) => request(axios, basePath));
         },
         /**
          * 
@@ -460,19 +425,14 @@ export class SysOrgApi extends BaseAPI {
      * 
      * @summary 获取机构列表
      * @param {number} id 主键Id
-     * @param {number} [pid] 父Id
      * @param {string} [name] 名称
      * @param {string} [code] 编码
-     * @param {number} [order] 排序
-     * @param {string} [remark] 备注
-     * @param {number} [status] 状态
-     * @param {string} [level] 级别 例如:省、市、县、区
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysOrgApi
      */
-    public async sysOrgListGet(id: number, pid?: number, name?: string, code?: string, order?: number, remark?: string, status?: number, level?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListSysOrg>> {
-        return SysOrgApiFp(this.configuration).sysOrgListGet(id, pid, name, code, order, remark, status, level, options).then((request) => request(this.axios, this.basePath));
+    public async sysOrgListGet(id: number, name?: string, code?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListSysOrg>> {
+        return SysOrgApiFp(this.configuration).sysOrgListGet(id, name, code, options).then((request) => request(this.axios, this.basePath));
     }
     /**
      * 

+ 1 - 1
vue-next-admin/src/api-services/models/add-menu-input.ts

@@ -139,7 +139,7 @@ export interface AddMenuInput {
      * @type {number}
      * @memberof AddMenuInput
      */
-    orderNo?: number;
+    order?: number;
     /**
      * 
      * @type {StatusEnum}

+ 49 - 5
vue-next-admin/src/api-services/models/add-org-input.ts

@@ -11,6 +11,8 @@
  * https://github.com/swagger-api/swagger-codegen.git
  * Do not edit the class manually.
  */
+import { StatusEnum } from './status-enum';
+import { SysOrg } from './sys-org';
 /**
  * 
  * @export
@@ -18,11 +20,47 @@
  */
 export interface AddOrgInput {
     /**
-     * 主键Id
+     * 雪花Id
      * @type {number}
      * @memberof AddOrgInput
      */
-    id: number;
+    id?: number;
+    /**
+     * 创建时间
+     * @type {Date}
+     * @memberof AddOrgInput
+     */
+    createTime?: Date | null;
+    /**
+     * 更新时间
+     * @type {Date}
+     * @memberof AddOrgInput
+     */
+    updateTime?: Date | null;
+    /**
+     * 创建者Id
+     * @type {number}
+     * @memberof AddOrgInput
+     */
+    createUserId?: number | null;
+    /**
+     * 修改者Id
+     * @type {number}
+     * @memberof AddOrgInput
+     */
+    updateUserId?: number | null;
+    /**
+     * 软删除
+     * @type {boolean}
+     * @memberof AddOrgInput
+     */
+    isDelete?: boolean;
+    /**
+     * 租户Id
+     * @type {number}
+     * @memberof AddOrgInput
+     */
+    tenantId?: number | null;
     /**
      * 父Id
      * @type {number}
@@ -48,17 +86,23 @@ export interface AddOrgInput {
      */
     remark?: string | null;
     /**
-     * 状态
-     * @type {number}
+     * 
+     * @type {StatusEnum}
      * @memberof AddOrgInput
      */
-    status?: number;
+    status?: StatusEnum;
     /**
      * 级别 例如:省、市、县、区
      * @type {string}
      * @memberof AddOrgInput
      */
     level?: string | null;
+    /**
+     * 机构子项
+     * @type {Array<SysOrg>}
+     * @memberof AddOrgInput
+     */
+    children?: Array<SysOrg> | null;
     /**
      * 名称
      * @type {string}

+ 1 - 1
vue-next-admin/src/api-services/models/sys-menu-meta.ts

@@ -65,7 +65,7 @@ export interface SysMenuMeta {
      * @type {number}
      * @memberof SysMenuMeta
      */
-    orderNo?: number;
+    order?: number;
     /**
      * 
      * @type {StatusEnum}

+ 1 - 1
vue-next-admin/src/api-services/models/sys-menu.ts

@@ -145,7 +145,7 @@ export interface SysMenu {
      * @type {number}
      * @memberof SysMenu
      */
-    orderNo?: number;
+    order?: number;
     /**
      * 
      * @type {StatusEnum}

+ 1 - 1
vue-next-admin/src/api-services/models/update-menu-input.ts

@@ -139,7 +139,7 @@ export interface UpdateMenuInput {
      * @type {number}
      * @memberof UpdateMenuInput
      */
-    orderNo?: number;
+    order?: number;
     /**
      * 
      * @type {StatusEnum}

+ 49 - 5
vue-next-admin/src/api-services/models/update-org-input.ts

@@ -11,6 +11,8 @@
  * https://github.com/swagger-api/swagger-codegen.git
  * Do not edit the class manually.
  */
+import { StatusEnum } from './status-enum';
+import { SysOrg } from './sys-org';
 /**
  * 
  * @export
@@ -18,11 +20,47 @@
  */
 export interface UpdateOrgInput {
     /**
-     * 主键Id
+     * 雪花Id
      * @type {number}
      * @memberof UpdateOrgInput
      */
-    id: number;
+    id?: number;
+    /**
+     * 创建时间
+     * @type {Date}
+     * @memberof UpdateOrgInput
+     */
+    createTime?: Date | null;
+    /**
+     * 更新时间
+     * @type {Date}
+     * @memberof UpdateOrgInput
+     */
+    updateTime?: Date | null;
+    /**
+     * 创建者Id
+     * @type {number}
+     * @memberof UpdateOrgInput
+     */
+    createUserId?: number | null;
+    /**
+     * 修改者Id
+     * @type {number}
+     * @memberof UpdateOrgInput
+     */
+    updateUserId?: number | null;
+    /**
+     * 软删除
+     * @type {boolean}
+     * @memberof UpdateOrgInput
+     */
+    isDelete?: boolean;
+    /**
+     * 租户Id
+     * @type {number}
+     * @memberof UpdateOrgInput
+     */
+    tenantId?: number | null;
     /**
      * 父Id
      * @type {number}
@@ -48,17 +86,23 @@ export interface UpdateOrgInput {
      */
     remark?: string | null;
     /**
-     * 状态
-     * @type {number}
+     * 
+     * @type {StatusEnum}
      * @memberof UpdateOrgInput
      */
-    status?: number;
+    status?: StatusEnum;
     /**
      * 级别 例如:省、市、县、区
      * @type {string}
      * @memberof UpdateOrgInput
      */
     level?: string | null;
+    /**
+     * 机构子项
+     * @type {Array<SysOrg>}
+     * @memberof UpdateOrgInput
+     */
+    children?: Array<SysOrg> | null;
     /**
      * 名称
      * @type {string}

+ 8 - 7
vue-next-admin/src/views/system/menu/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="page-container">
+  <div class="sys-menu-container">
     <el-card shadow="hover">
       <el-form :model="queryParams" ref="queryForm" :inline="true">
         <el-form-item label="菜单名称" prop="title">
@@ -96,9 +96,9 @@ export default defineComponent({
   setup() {
     const { proxy } = getCurrentInstance() as any;
     const editMenuRef = ref();
-    const state: any = reactive({
+    const state = reactive({
       loading: true,
-      menuData: [],
+      menuData: [] as any,
       queryParams: {
         title: undefined,
         type: undefined,
@@ -118,11 +118,12 @@ export default defineComponent({
     });
 
     // 查询操作
-    const handleQuery = async () => {
+    const handleQuery = () => {
       state.loading = true;
-      var res = await getAPI(SysMenuApi).sysMenuListGet(state.queryParams.title, state.queryParams.type);
-      state.menuData = res.data.result;
-      state.loading = false;
+      getAPI(SysMenuApi).sysMenuListGet(state.queryParams.title, state.queryParams.type).then((res) => {
+        state.menuData = res.data.result;
+        state.loading = false;
+      });
     };
     // 重置操作
     const resetQuery = () => {

+ 90 - 119
vue-next-admin/src/views/system/org/component/editOrg.vue

@@ -1,66 +1,60 @@
 <template>
-	<div class="system-edit-dept-container">
-		<el-dialog title="修改部门" v-model="isShowDialog" width="769px">
-			<el-form :model="ruleForm" size="default" label-width="90px">
+	<div class="sys-org-container">
+		<el-dialog v-model="isShowDialog" width="500px">
+			<template #header>
+				<div style="font-size: large" v-drag="['.el-dialog','.el-dialog__header']">
+					{{ title }}
+				</div>
+			</template>
+			<el-form :model="ruleForm" :rules="ruleRules" ref="ruleFormRef" size="default" label-width="80px">
 				<el-row :gutter="35">
 					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
-						<el-form-item label="上级部门">
-							<el-cascader
-								:options="deptData"
-								:props="{ checkStrictly: true, value: 'deptName', label: 'deptName' }"
-								placeholder="请选择部门"
-								clearable
-								class="w100"
-								v-model="ruleForm.deptLevel"
-							>
+						<el-form-item label="上级机构">
+							<el-cascader :options="orgData" :props="{ checkStrictly: true, value: 'id', label: 'name' }"
+								placeholder="请选择上级机构" clearable class="w100" v-model="ruleForm.pid">
 								<template #default="{ node, data }">
-									<span>{{ data.deptName }}</span>
+									<span>{{ data.name }}</span>
 									<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
 								</template>
 							</el-cascader>
 						</el-form-item>
 					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-						<el-form-item label="部门名称">
-							<el-input v-model="ruleForm.deptName" placeholder="请输入部门名称" clearable></el-input>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-						<el-form-item label="负责人">
-							<el-input v-model="ruleForm.person" placeholder="请输入负责人" clearable></el-input>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-						<el-form-item label="手机号">
-							<el-input v-model="ruleForm.phone" placeholder="请输入手机号" clearable></el-input>
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
+						<el-form-item label="机构名称" prop="name">
+							<el-input v-model="ruleForm.name" placeholder="机构名称" clearable></el-input>
 						</el-form-item>
 					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-						<el-form-item label="邮箱">
-							<el-input v-model="ruleForm.email" placeholder="请输入" clearable></el-input>
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
+						<el-form-item label="机构编码" prop="code">
+							<el-input v-model="ruleForm.code" placeholder="机构编码" clearable></el-input>
 						</el-form-item>
 					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
 						<el-form-item label="排序">
-							<el-input-number v-model="ruleForm.sort" :min="0" :max="999" controls-position="right" placeholder="请输入排序" class="w100" />
+							<el-input-number v-model="ruleForm.order" controls-position="right" placeholder="排序"
+								class="w100" />
 						</el-form-item>
 					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
-						<el-form-item label="部门状态">
-							<el-switch v-model="ruleForm.status" inline-prompt active-text="启" inactive-text="禁"></el-switch>
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
+						<el-form-item label="是否启用">
+							<el-radio-group v-model="ruleForm.status">
+								<el-radio :label="1">启用</el-radio>
+								<el-radio :label="2">不启用</el-radio>
+							</el-radio-group>
 						</el-form-item>
 					</el-col>
 					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
-						<el-form-item label="部门描述">
-							<el-input v-model="ruleForm.describe" type="textarea" placeholder="请输入部门描述" maxlength="150"></el-input>
+						<el-form-item label="备注">
+							<el-input v-model="ruleForm.remark" placeholder="请输入备注内容" clearable type="textarea">
+							</el-input>
 						</el-form-item>
 					</el-col>
 				</el-row>
 			</el-form>
 			<template #footer>
 				<span class="dialog-footer">
-					<el-button @click="onCancel" size="default">取 消</el-button>
-					<el-button type="primary" @click="onSubmit" size="default">修 改</el-button>
+					<el-button @click="cancel" size="default">取 消</el-button>
+					<el-button type="primary" @click="submit" size="default">确 定</el-button>
 				</span>
 			</template>
 		</el-dialog>
@@ -68,112 +62,89 @@
 </template>
 
 <script lang="ts">
-import { reactive, toRefs, onMounted, defineComponent } from 'vue';
+import { reactive, toRefs, defineComponent, getCurrentInstance, ref, unref } from 'vue';
 
-// 定义接口来定义对象的类型
-interface TableDataRow {
-	deptName: string;
-	createTime: string;
-	status: boolean;
-	sort: number;
-	describe: string;
-	id: number;
-	children?: TableDataRow[];
-}
-interface RuleFormState {
-	deptLevel: Array<string>;
-	deptName: string;
-	person: string;
-	phone: string | number;
-	email: string;
-	sort: number;
-	status: boolean;
-	describe: string;
-}
-interface DeptSate {
-	isShowDialog: boolean;
-	ruleForm: RuleFormState;
-	deptData: Array<TableDataRow>;
-}
+import { getAPI } from '/@/utils/axios-utils';
+import { SysOrgApi } from '/@/api-services/api';
 
 export default defineComponent({
 	name: 'sysEditOrg',
+	components: {},
+	props: {
+		// 弹窗标题
+		title: {
+			type: String,
+			default: () => "",
+		},
+		// 机构数据
+		orgData: {
+			type: Array,
+			default: () => [],
+		}
+	},
 	setup() {
-		const state = reactive<DeptSate>({
+		const { proxy } = getCurrentInstance() as any;
+		const ruleFormRef = ref<HTMLElement | null>(null);
+		const state = reactive({
 			isShowDialog: false,
 			ruleForm: {
-				deptLevel: [], // 上级部门
-				deptName: '', // 部门名称
-				person: '', // 负责人
-				phone: '', // 手机号
-				email: '', // 邮箱
-				sort: 0, // 排序
-				status: true, // 部门状态
-				describe: '', // 部门描述
+				id: 0, // Id
+				pid: 0, // 父节点Id
+				name: '', // 机构名称
+				code: '', // 机构编码
+				order: 10, // 排序
+				status: 1, // 是否启用
+				remark: '', // 备注
+			},
+			ruleRules: {
+				name: [{ required: true, message: "机构名称不能为空", trigger: "blur" }],
+				code: [{ required: true, message: "机构编码不能为空", trigger: "blur" }],
 			},
-			deptData: [], // 部门数据
 		});
 		// 打开弹窗
-		const openDialog = (row: RuleFormState) => {
-			row.deptLevel = ['vueNextAdmin'];
-			row.person = 'lyt';
-			row.phone = '12345678910';
-			row.email = 'vueNextAdmin@123.com';
+		const openDialog = (row: any) => {
 			state.ruleForm = row;
 			state.isShowDialog = true;
 		};
 		// 关闭弹窗
 		const closeDialog = () => {
+			proxy.mittBus.emit("submitRefresh");
 			state.isShowDialog = false;
 		};
 		// 取消
-		const onCancel = () => {
-			closeDialog();
-		};
-		// 新增
-		const onSubmit = () => {
-			closeDialog();
+		const cancel = () => {
+			state.isShowDialog = false;
 		};
-		// 初始化部门数据
-		const initTableData = () => {
-			state.deptData.push({
-				deptName: 'vueNextAdmin',
-				createTime: new Date().toLocaleString(),
-				status: true,
-				sort: Math.random(),
-				describe: '顶级部门',
-				id: Math.random(),
-				children: [
-					{
-						deptName: 'IT外包服务',
-						createTime: new Date().toLocaleString(),
-						status: true,
-						sort: Math.random(),
-						describe: '总部',
-						id: Math.random(),
-					},
-					{
-						deptName: '资本控股',
-						createTime: new Date().toLocaleString(),
-						status: true,
-						sort: Math.random(),
-						describe: '分部',
-						id: Math.random(),
-					},
-				],
-			});
+		// 提交
+		const submit = () => {
+			const formWrap = unref(ruleFormRef) as any;
+			if (!formWrap) return;
+
+			// 取父节点Id
+			if (Array.isArray(state.ruleForm.pid))
+				state.ruleForm.pid = state.ruleForm.pid[state.ruleForm.pid.length - 1];
+			formWrap.validate(() => {
+				if (state.ruleForm.id != undefined && state.ruleForm.id != 0) {
+					getAPI(SysOrgApi).sysOrgUpdatePost(state.ruleForm).then(() => {
+						closeDialog();
+					})
+				}
+				else {
+					getAPI(SysOrgApi).sysOrgAddPost(state.ruleForm).then(() => {
+						closeDialog();
+					})
+				}
+			})
 		};
-		// 页面加载时
-		onMounted(() => {
-			initTableData();
-		});
 		return {
+			ruleFormRef,
 			openDialog,
 			closeDialog,
-			onCancel,
-			onSubmit,
+			cancel,
+			submit,
 			...toRefs(state),
 		};
 	},
 });
 </script>
+	

+ 130 - 0
vue-next-admin/src/views/system/org/component/orgTree.vue

@@ -0,0 +1,130 @@
+<template>
+  <el-card class='box-card' shadow="hover" style='height: 100%;' body-style='height:100%; overflow:auto'>
+    <template #header>
+      <div class='card-header'>
+        <div class='tree-h-flex'>
+          <div class='tree-h-left'>
+            <el-input :prefix-icon='Search' v-model='filterText' placeholder='机构名称' />
+          </div>
+          <div class='tree-h-right'>
+            <el-dropdown @command='handleCommand'>
+              <el-button style='margin-left: 8px;width: 34px'>
+                <el-icon class='el-icon--center'>
+                  <more-filled />
+                </el-icon>
+              </el-button>
+              <template #dropdown>
+                <el-dropdown-menu>
+                  <el-dropdown-item command='expandAll'>全部展开</el-dropdown-item>
+                  <el-dropdown-item command='collapseAll'>全部折叠</el-dropdown-item>
+                  <el-dropdown-item command='rootNode'>根节点</el-dropdown-item>
+                  <el-dropdown-item command='refresh'>刷新</el-dropdown-item>
+                </el-dropdown-menu>
+              </template>
+            </el-dropdown>
+          </div>
+        </div>
+      </div>
+    </template>
+    <div style='margin-bottom: 45px'>
+      <el-tree ref='treeRef' class='filter-tree' :data='state.orgData' :props='defaultProps'
+        :filter-node-method='filterNode' @node-click="nodeClick" />
+    </div>
+  </el-card>
+</template>
+
+<script lang='ts' setup>
+import { onMounted, reactive, ref, watch } from 'vue';
+import type { ElTree } from 'element-plus';
+import { Search, MoreFilled } from '@element-plus/icons-vue';
+
+import { getAPI } from '/@/utils/axios-utils';
+import { SysOrgApi } from '/@/api-services/apis/sys-org-api';
+
+interface Tree {
+  id: number;
+  name: string;
+  children?: Tree[];
+}
+
+const filterText = ref('');
+const treeRef = ref<InstanceType<typeof ElTree>>();
+const defaultProps = {
+  children: 'children',
+  label: 'name',
+};
+
+const props = defineProps({
+  maInit: Boolean,
+});
+
+const state = reactive({
+  loading: true,
+  orgData: [] as any,
+});
+
+onMounted(() => {
+  if (props.maInit == false) {
+    initTreeData();
+  }
+});
+
+watch(filterText, (val) => {
+  treeRef.value!.filter(val);
+});
+
+const initTreeData = () => {
+  state.loading = true;
+  getAPI(SysOrgApi).sysOrgListGet(0).then((res) => {
+    state.orgData = res.data.result;
+    state.loading = false;
+  })
+};
+
+const filterNode = (value: string, data: Tree) => {
+  if (!value) return true;
+  return data.name.includes(value);
+};
+
+const handleCommand = async (command: string | number | object) => {
+  if ('expandAll' == command) {
+    for (let i = 0; i < treeRef.value!.store._getAllNodes().length; i++) {
+      treeRef.value!.store._getAllNodes()[i].expanded = true;
+    }
+  } else if ('collapseAll' == command) {
+    for (let i = 0; i < treeRef.value!.store._getAllNodes().length; i++) {
+      treeRef.value!.store._getAllNodes()[i].expanded = false;
+    }
+  } else if ('refresh' == command) {
+    initTreeData();
+  } else if ('rootNode' == command) {
+    emits('node-click', { id: 0, name: '' });
+  }
+};
+
+// 与父组件的交互逻辑
+const emits = defineEmits(['node-click']);
+const nodeClick = (node: any) => {
+  emits('node-click', { id: node.id, name: node.name });
+};
+// const init = () => {
+//   initTreeData();
+// };
+// defineExpose({ init });
+</script>
+
+<style scoped>
+.tree-h-flex {
+  display: flex;
+}
+
+.tree-h-left {
+  flex: 1;
+  width: 100%;
+}
+
+.tree-h-right {
+  width: 42px;
+  min-width: 42px;
+}
+</style>

+ 146 - 121
vue-next-admin/src/views/system/org/index.vue

@@ -1,152 +1,177 @@
 <template>
-	<div class="system-dept-container">
-		<el-card shadow="hover">
-			<div class="system-dept-search mb15">
-				<el-input size="default" placeholder="请输入部门名称" style="max-width: 180px"> </el-input>
-				<el-button size="default" type="primary" class="ml10">
-					<el-icon>
-						<ele-Search />
-					</el-icon>
-					查询
-				</el-button>
-				<el-button size="default" type="success" class="ml10" @click="onOpenAddDept">
-					<el-icon>
-						<ele-FolderAdd />
-					</el-icon>
-					新增部门
-				</el-button>
-			</div>
-			<el-table :data="tableData.data" style="width: 100%" row-key="id" default-expand-all
-				:tree-props="{ children: 'children', hasChildren: 'hasChildren' }">
-				<el-table-column prop="deptName" label="部门名称" show-overflow-tooltip> </el-table-column>
-				<el-table-column label="排序" show-overflow-tooltip width="80">
-					<template #default="scope">
-						{{ scope.$index }}
-					</template>
-				</el-table-column>
-				<el-table-column prop="status" label="部门状态" show-overflow-tooltip>
-					<template #default="scope">
-						<el-tag type="success" v-if="scope.row.status">启用</el-tag>
-						<el-tag type="info" v-else>禁用</el-tag>
-					</template>
-				</el-table-column>
-				<el-table-column prop="describe" label="部门描述" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column>
-				<el-table-column label="操作" show-overflow-tooltip width="140">
-					<template #default="scope">
-						<el-button size="small" text type="primary" @click="onOpenAddDept">新增</el-button>
-						<el-button size="small" text type="primary" @click="onOpenEditDept(scope.row)">修改</el-button>
-						<el-button size="small" text type="primary" @click="onTabelRowDel(scope.row)">删除</el-button>
-					</template>
-				</el-table-column>
-			</el-table>
-		</el-card>
-		<EditOrg ref="editOrgRef" />
+	<div class="sys-org-container">
+		<el-row :gutter="5">
+			<el-col :span="4" :xs="24">
+				<OrgTree @node-click='nodeClick' />
+			</el-col>
+
+			<el-col :span="20" :xs="24">
+				<el-card shadow="hover">
+					<el-form :model="queryParams" ref="queryForm" :inline="true">
+						<el-form-item label="机构名称" prop="name">
+							<el-input placeholder="机构名称" clearable @keyup.enter="handleQuery"
+								v-model="queryParams.name" />
+						</el-form-item>
+						<el-form-item label="机构编码" prop="code">
+							<el-input placeholder="机构编码" clearable @keyup.enter="handleQuery"
+								v-model="queryParams.code" />
+						</el-form-item>
+						<el-form-item>
+							<el-button @click="resetQuery">
+								<el-icon>
+									<ele-Refresh />
+								</el-icon>
+								重置
+							</el-button>
+							<el-button type="primary" @click="handleQuery">
+								<el-icon>
+									<ele-Search />
+								</el-icon>
+								查询
+							</el-button>
+							<el-button @click="openAddOrg">
+								<el-icon>
+									<ele-Plus />
+								</el-icon>
+								新增
+							</el-button>
+						</el-form-item>
+					</el-form>
+				</el-card>
+
+				<el-card shadow="hover" style="margin-top: 5px;">
+					<el-table :data="orgData" style="width: 100%" row-key="id" default-expand-all
+						:tree-props="{ children: 'children', hasChildren: 'hasChildren' }">
+						<el-table-column prop="name" label="机构名称" show-overflow-tooltip> </el-table-column>
+						<el-table-column prop="code" label="机构编码" show-overflow-tooltip></el-table-column>
+						<el-table-column prop="order" label="排序" show-overflow-tooltip width="80" align="center">
+						</el-table-column>
+						<el-table-column prop="status" label="状态" show-overflow-tooltip width="80" align="center">
+							<template #default="scope">
+								<el-tag type="success" v-if="scope.row.status === 1">启用</el-tag>
+								<el-tag type="danger" v-else>禁用</el-tag>
+							</template>
+						</el-table-column>
+						<el-table-column prop="createTime" label="修改时间" show-overflow-tooltip></el-table-column>
+						<el-table-column prop="remark" label="备注" show-overflow-tooltip></el-table-column>
+						<el-table-column label="操作" show-overflow-tooltip width="80" fixed="right" align="center">
+							<template #default="scope">
+								<el-button size="small" text type="primary" @click="openEditOrg(scope.row)">
+									<el-icon>
+										<ele-Edit />
+									</el-icon>
+								</el-button>
+								<el-button size="small" text type="primary" @click="delOrg(scope.row)">
+									<el-icon>
+										<ele-Delete />
+									</el-icon>
+								</el-button>
+							</template>
+						</el-table-column>
+					</el-table>
+				</el-card>
+			</el-col>
+		</el-row>
+		<EditOrg ref="editOrgRef" :title="editOrgTitle" :orgData="orgTreeData" />
 	</div>
 </template>
 
 <script lang="ts">
-import { ref, toRefs, reactive, onMounted, defineComponent } from 'vue';
+import { ref, toRefs, reactive, onMounted, defineComponent, getCurrentInstance, onUnmounted } from 'vue';
 import { ElMessageBox, ElMessage } from 'element-plus';
+import OrgTree from '/@/views/system/org/component/orgTree.vue';
 import EditOrg from '/@/views/system/org/component/editOrg.vue';
 
-// 定义接口来定义对象的类型
-interface TableDataRow {
-	deptName: string;
-	createTime: string;
-	status: boolean;
-	sort: number;
-	describe: string;
-	id: number;
-	children?: TableDataRow[];
-}
-interface TableDataState {
-	tableData: {
-		data: Array<TableDataRow>;
-		total: number;
-		loading: boolean;
-		param: {
-			pageNum: number;
-			pageSize: number;
-		};
-	};
-}
+import { getAPI } from '/@/utils/axios-utils';
+import { SysOrgApi } from '/@/api-services/apis/sys-org-api';
 
 export default defineComponent({
 	name: 'sysOrg',
-	components: { EditOrg },
+	components: { OrgTree, EditOrg },
 	setup() {
+		const { proxy } = getCurrentInstance() as any;
 		const editOrgRef = ref();
-		const state = reactive<TableDataState>({
-			tableData: {
-				data: [],
-				total: 0,
-				loading: false,
-				param: {
-					pageNum: 1,
-					pageSize: 10,
-				},
+		const state = reactive({
+			loading: true,
+			orgData: [] as any,
+			orgTreeData: [] as any, // 编辑页面上级机构树
+			queryParams: {
+				id: -1,
+				name: undefined,
+				code: undefined,
 			},
+			editOrgTitle: "",
 		});
-		// 初始化表格数据
-		const initTableData = () => {
-			state.tableData.data.push({
-				deptName: 'vueNextAdmin',
-				createTime: new Date().toLocaleString(),
-				status: true,
-				sort: Math.random(),
-				describe: '顶级部门',
-				id: Math.random(),
-				children: [
-					{
-						deptName: 'IT外包服务',
-						createTime: new Date().toLocaleString(),
-						status: true,
-						sort: Math.random(),
-						describe: '总部',
-						id: Math.random(),
-					},
-					{
-						deptName: '资本控股',
-						createTime: new Date().toLocaleString(),
-						status: true,
-						sort: Math.random(),
-						describe: '分部',
-						id: Math.random(),
-					},
-				],
+		onMounted(async () => {
+			handleQuery();
+
+			proxy.mittBus.on("submitRefresh", () => {
+				handleQuery();
 			});
-			state.tableData.total = state.tableData.data.length;
+		});
+		onUnmounted(() => {
+			proxy.mittBus.off("submitRefresh");
+		});
+		// 查询操作
+		const handleQuery = () => {
+			state.loading = true;
+			getAPI(SysOrgApi).sysOrgListGet(state.queryParams.id, state.queryParams.name, state.queryParams.code).then((res) => {
+				state.orgData = res.data.result;
+				state.loading = false;
+
+				if (state.queryParams.id == -1) {
+					state.orgTreeData = state.orgData;
+					console.log(state.orgTreeData)
+				}
+			});
+		};
+		// 重置操作
+		const resetQuery = () => {
+			state.queryParams.id = -1;
+			state.queryParams.name = undefined;
+			state.queryParams.code = undefined;
+			handleQuery();
 		};
-		// 打开新增菜单弹窗
-		const onOpenAddOrg = () => {
-			addDeptRef.value.openDialog();
+		// 打开新增页面
+		const openAddOrg = () => {
+			state.editOrgTitle = "添加机构";
+			editOrgRef.value.openDialog({});
 		};
-		// 打开编辑菜单弹窗
-		const onOpenEditOrg = (row: TableDataRow) => {
-			editDeptRef.value.openDialog(row);
+		// 打开编辑页面
+		const openEditOrg = (row: any) => {
+			state.editOrgTitle = "编辑机构";
+			editOrgRef.value.openDialog(row);
 		};
-		// 删除当前行
-		const onTabelRowDel = (row: TableDataRow) => {
-			ElMessageBox.confirm(`此操作将永久删除部门:${row.deptName}, 是否继续?`, '提示', {
-				confirmButtonText: '删除',
+		// 删除
+		const delOrg = (row: any) => {
+			ElMessageBox.confirm(`确定删除机构:【${row.name}】?`, '提示', {
+				confirmButtonText: '确定',
 				cancelButtonText: '取消',
 				type: 'warning',
 			})
 				.then(() => {
-					ElMessage.success('删除成功');
+					getAPI(SysOrgApi).sysOrgDeletePost({ id: row.id }).then(() => {
+						handleQuery();
+						ElMessage.success('删除成功');
+					})
 				})
 				.catch(() => { });
 		};
-		// 页面加载时
-		onMounted(() => {
-			initTableData();
-		});
+		// 树组件点击
+		const nodeClick = async (node: any) => {
+			state.queryParams.id = node.id;
+			state.queryParams.name = undefined; // node.name;
+			state.queryParams.code = undefined;
+			handleQuery();
+		};
 		return {
+			handleQuery,
+			resetQuery,
 			editOrgRef,
-			onOpenAddOrg,
-			onOpenEditOrg,
-			onTabelRowDel,
+			openAddOrg,
+			openEditOrg,
+			delOrg,
+			nodeClick,
 			...toRefs(state),
 		};
 	},

+ 8 - 7
vue-next-admin/src/views/system/pos/index.vue

@@ -1,5 +1,5 @@
 <template>
-	<div class="system-dic-container">
+	<div class="sys-pos-container">
 		<el-card shadow="hover">
 			<el-form :model="queryParams" ref="queryForm" :inline="true">
 				<el-form-item label="职位名称" prop="name">
@@ -80,9 +80,9 @@ export default defineComponent({
 	setup() {
 		const { proxy } = getCurrentInstance() as any;
 		const editPosRef = ref();
-		const state: any = reactive({
+		const state = reactive({
 			loading: true,
-			posData: [],
+			posData: [] as any,
 			queryParams: {
 				name: undefined,
 				code: undefined,
@@ -101,11 +101,12 @@ export default defineComponent({
 		});
 
 		// 查询操作
-		const handleQuery = async () => {
+		const handleQuery = () => {
 			state.loading = true;
-			var res = await getAPI(SysPosApi).sysPosListGet(state.queryParams.name, state.queryParams.code);
-			state.posData = res.data.result;
-			state.loading = false;
+			getAPI(SysPosApi).sysPosListGet(state.queryParams.name, state.queryParams.code).then((res) => {
+				state.posData = res.data.result;
+				state.loading = false;
+			});
 		};
 		// 重置操作
 		const resetQuery = () => {