Ver Fonte

权限管理

yzx há 2 meses atrás
pai
commit
04d3c1f3e4

+ 5 - 0
src/api/gislayer/gisform/index.ts

@@ -101,4 +101,9 @@ export const GisFormApi = {
   updateBatchMember: async (data: TeamMemberUpdateVO) => {
     return await request.put({ url: `/layer/gis-name/update-batch-member`, data })
   },
+  // 批量更新团队成员(有过期时间)
+  updateLayersByUser: async (data: TeamMemberUpdateVO) => {
+    return await request.put({ url: `/layer/gis-name/update-user-layers`, data })
+  },
+
 }

+ 1 - 1
src/views/bpm/disbursement/AuthorityForm.vue

@@ -158,7 +158,7 @@ import {dateFormatter} from "@/utils/formatTime";
 import {ref, reactive, onMounted} from "vue";
 import {useMessage} from "@/hooks/web/useMessage";
 import { ElMessage, ElTable, ElTableColumn } from 'element-plus'
-
+import { getSimpleGisNameList } from "@/api/layer/gisname"
 const message = useMessage() // 消息弹窗
 const loading = ref(false) // 列表的加载中
 const total = ref(0) // 列表的总页数

+ 3 - 15
src/views/layer/gisname/AuthorityForm.vue

@@ -243,7 +243,6 @@ interface UserRow {
 const dialogVisible = ref(false)
 const list = ref<UserRow[]>([])          // 表格数据
 const userOptions = ref<UserApi.UserVO[]>([]) // 用户选项
-const deletedUserIds = ref<number[]>([]) // 存储已标记为删除的用户ID
 
 // 字段权限相关
 const fieldPermissionDrawer = ref(false) // 字段权限抽屉是否可见
@@ -267,7 +266,6 @@ const queryParams = reactive({
 const submitData = ref({
   layer: undefined as string | undefined,
   list: [] as UserRow[],
-  deletedUserIds: [] as number[] // 存储要删除的用户ID
 })
 
 // 判断是否为特殊用户(管理者或当前用户)
@@ -285,9 +283,7 @@ const open = async (shpName: string) => {
   dialogVisible.value = true
   queryParams.layer = shpName
   submitData.value.layer = shpName
-  
-  // 重置删除列表
-  deletedUserIds.value = []
+
   
   // 加载用户选项
   userOptions.value = await UserApi.getSimpleUserList()
@@ -519,12 +515,7 @@ const handleDeleteRow = (index: number) => {
     message.warning('无法删除管理者或当前用户')
     return
   }
-  
-  // 如果是已有记录(有ID),将用户ID添加到要删除的列表中
-  if (row.id && row.userId) {
-    deletedUserIds.value.push(row.userId);
-  }
-  
+
   // 从列表中移除
   list.value.splice(index, 1);
   updateSubmitData();
@@ -555,9 +546,7 @@ const updateSubmitData = () => {
         fieldPermissions: fieldPermissionsJson // 添加字段权限JSON
       };
     });
-    
-  // 更新要删除的用户ID列表
-  submitData.value.deletedUserIds = [...deletedUserIds.value];
+
 }
 
 // 验证表单数据
@@ -617,7 +606,6 @@ const submitForm = async () => {
     const submitData = {
       layer: queryParams.layer,
       list: submitList,
-      deletedUserIds: deletedUserIds.value
     };
     
     // 提交数据 - 使用批量更新接口,同时处理删除

+ 597 - 155
src/views/system/user/AuthorityForm.vue

@@ -1,35 +1,22 @@
 <template>
-  <Dialog title="权限管理" v-model="dialogVisible" width="70%">
+  <Dialog title="图层权限管理" v-model="dialogVisible" width="70%">
     <el-form
       ref="formRef"
       :model="formData"
       label-width="100px"
       v-loading="formLoading"
     >
-<!--      <el-form-item label="角色">-->
-<!--        <el-select v-model="formData.roleIds" multiple placeholder="请选择角色">-->
-<!--          <el-option v-for="item in roleList" :key="item.id" :label="item.name" :value="item.id" />-->
-<!--        </el-select>-->
-<!--      </el-form-item>-->
-
-<!--      <el-form-item label="用户">-->
-<!--        <el-select v-model="formData.userIds" multiple placeholder="请选择用户">-->
-<!--          <el-option v-for="item in userOptions" :key="item.id" :label="item.nickname" :value="item.id" />-->
-<!--        </el-select>-->
-<!--      </el-form-item>-->
-
-<!--      <el-form-item label="只读角色">-->
-<!--        <el-select v-model="formData.readRoleIds" multiple placeholder="请选择角色">-->
-<!--          <el-option v-for="item in roleList" :key="item.id" :label="item.name" :value="item.id" />-->
-<!--        </el-select>-->
-<!--      </el-form-item>-->
-
-<!--      <el-form-item label="只读用户">-->
-<!--        <el-select v-model="formData.readUserIds" multiple placeholder="请选择用户">-->
-<!--          <el-option v-for="item in userOptions" :key="item.id" :label="item.nickname" :value="item.id" />-->
-<!--        </el-select>-->
-<!--      </el-form-item>-->
-
+      <!-- 用户信息展示区域 -->
+      <el-descriptions :column="2" border>
+        <el-descriptions-item label="用户">{{ currentUserInfo.nickname }}</el-descriptions-item>
+        <el-descriptions-item label="部门">{{ currentUserInfo.deptName }}</el-descriptions-item>
+        <el-descriptions-item label="手机号码">{{ currentUserInfo.mobile }}</el-descriptions-item>
+        <el-descriptions-item label="状态">
+          <el-tag :type="currentUserInfo.status === 0 ? 'success' : 'danger'">
+            {{ currentUserInfo.status === 0 ? '正常' : '停用' }}
+          </el-tag>
+        </el-descriptions-item>
+      </el-descriptions>
     </el-form>
     <ContentWrap>
         <el-form
@@ -39,19 +26,10 @@
           :inline="true"
           label-width="100px"
         >
-          <el-form-item label="昵称" prop="username">
+          <el-form-item label="图层名称" prop="layer">
             <el-input
-              v-model="queryParams.nickname"
-              placeholder="请输入用户昵称"
-              clearable
-              @keyup.enter="handleQuery"
-              class="!w-240px"
-            />
-          </el-form-item>
-          <el-form-item label="手机号码" prop="mobile">
-            <el-input
-              v-model="queryParams.mobile"
-              placeholder="请输入手机号码"
+              v-model="queryParams.layer"
+              placeholder="请输入图层名称"
               clearable
               @keyup.enter="handleQuery"
               class="!w-240px"
@@ -61,11 +39,11 @@
           <el-form-item>
             <el-button @click="handleQuery"><Icon icon="ep:search" />搜索</el-button>
             <el-button @click="resetQuery"><Icon icon="ep:refresh" />重置</el-button>
-
           </el-form-item>
         </el-form>
       </ContentWrap>
     <ContentWrap>
+        <!-- 用户图层权限表格 -->
         <el-table v-loading="loading" :data="list">
           <el-table-column
             label="图层"
@@ -73,14 +51,64 @@
             key="layer"
             prop="layer"
             :show-overflow-tooltip="true"
-          />
+          >
+            <template #default="scope">
+              <el-select 
+                v-if="scope.row.isNew"
+                v-model="scope.row.shpName" 
+                placeholder="选择图层"
+                filterable
+                clearable
+                style="width: 100%;"
+                @change="handleLayerSelect(scope.row)"
+              >
+                <el-option 
+                  v-for="item in availableLayers(scope.row)" 
+                  :key="item.shpName" 
+                  :label="item.shpName" 
+                  :value="item.shpName" 
+                />
+              </el-select>
+              <span v-else>{{ scope.row.layer }}</span>
+            </template>
+          </el-table-column>
+
           <el-table-column
-              label="到期时间"
+              label="截止时间"
               align="center"
-              prop="maturityTime"
-              :formatter="dateFormatter"
-              width="180"
-          />
+              width="220"
+          >
+            <template #default="scope">
+              <el-date-picker
+                  v-model="scope.row.maturityTime"
+                  type="datetime"
+                  placeholder="选择截止时间"
+                  class="w-full"
+                  @change="handleDateChange(scope.row)"
+                  :disabled-date="disabledDate"
+                  value-format="x"
+              />
+            </template>
+          </el-table-column>
+          
+          <!-- 添加剩余天数列 -->
+          <el-table-column
+              label="状态"
+              align="center"
+              width="120"
+          >
+            <template #default="scope">
+              <div>
+                <el-tag v-if="scope.row.maturityTime" :type="scope.row.valid ? 'success' : 'danger'" size="small" effect="plain">
+                  <template v-if="scope.row.valid">
+                    剩余{{ scope.row.daysLeft }}天
+                  </template>
+                  <template v-else>已过期</template>
+                </el-tag>
+              </div>
+            </template>
+          </el-table-column>
+          
           <el-table-column
               label="创建时间"
               align="center"
@@ -88,177 +116,591 @@
               :formatter="dateFormatter"
               width="180"
           />
-          <el-table-column label="操作" align="center" width="160">
+          <el-table-column label="字段权限" align="center" width="120">
+            <template #default="scope">
+              <el-button
+                type="primary"
+                link
+                @click="openFieldPermissions(scope.row)"
+                :disabled="!scope.row.layer && !scope.row.shpName"
+              >
+                <Icon icon="ep:key" />配置
+              </el-button>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" align="center" width="120">
             <template #default="scope">
               <div class="flex items-center justify-center">
                 <el-button
-                  type="primary"
+                  type="danger"
                   link
-                  @click="deleteQuery(scope.row.id)"
-                  :disabled="scope.row.isSelf"
+                  @click="handleDeleteRow(scope.$index)"
                 >
-                  <Icon icon="ep:edit" />删除
+                  <Icon icon="ep:delete" />删除
                 </el-button>
               </div>
             </template>
           </el-table-column>
         </el-table>
-        <Pagination
-          :total="total"
-          v-model:page="queryParams.pageNo"
-          v-model:limit="queryParams.pageSize"
-          @pagination="getList"
-        />
-        <el-form :inline="true" label-width="100px">
-          <el-form-item label="添加用户">
-            <el-select v-model="queryParams.addUserId" placeholder="请选择用户" style="width: 200px;" >
-              <el-option v-for="item in userOptions" :key="item.id" :label="item.nickname" :value="item.id" />
-            </el-select>
-          </el-form-item>
-          <el-form-item>
-            <el-button @click="addQuery"><Icon icon="ep:plus" />添加</el-button>
-          </el-form-item>
-        </el-form>
-
+        
+        <!-- 分页和添加按钮 -->
+        <div class="mt-15px flex justify-between">
+          <el-button @click="handleAddRow" type="primary">
+            <Icon icon="ep:plus" />添加图层
+          </el-button>
+        </div>
     </ContentWrap>
     <template #footer>
-      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
       <el-button @click="dialogVisible = false">取 消</el-button>
+      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
     </template>
   </Dialog>
+
+  <!-- 字段权限配置抽屉 -->
+  <el-drawer
+    v-model="fieldPermissionDrawer"
+    title="字段权限配置"
+    size="50%"
+    append-to-body
+  >
+    <template #default>
+      <div class="p-4">
+        <el-alert
+          title="配置字段级权限控制"
+          type="info"
+          description="开启或关闭用户对特定字段的访问权限。"
+          show-icon
+          :closable="false"
+          class="mb-4"
+        />
+        
+        <!-- 快速设置按钮组 -->
+        <div class="mb-4 flex gap-2">
+          <el-button type="primary" @click="applyAllPermissions(true)">
+            全部启用
+          </el-button>
+          <el-button @click="applyAllPermissions(false)">
+            全部禁用
+          </el-button>
+        </div>
+        
+        <!-- 字段权限加载状态 -->
+        <div v-if="fieldLoading" class="flex justify-center items-center py-10">
+          <el-icon class="is-loading"><Loading /></el-icon>
+          <span class="ml-2">正在加载字段信息...</span>
+        </div>
+        
+        <!-- 字段权限表格 -->
+        <el-table v-else :data="layerFields" border style="width: 100%">
+          <el-table-column prop="fieldName" label="字段名称" min-width="180" />
+          <el-table-column label="是否启用" width="120" align="center">
+            <template #default="scope">
+              <el-switch v-model="scope.row.enabled" />
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+    </template>
+    <template #footer>
+      <div class="flex justify-between items-center">
+        <span class="text-gray-500 text-sm">修改后的权限将在提交时生效</span>
+        <div>
+          <el-button @click="fieldPermissionDrawer = false">取消</el-button>
+          <el-button type="primary" @click="saveFieldPermissions">确认</el-button>
+        </div>
+      </div>
+    </template>
+  </el-drawer>
 </template>
 <script setup lang="ts">
 import { GisFormApi } from '@/api/gislayer/gisform/index.ts'
-import * as RoleApi from "@/api/system/role";
 import * as UserApi from "@/api/system/user";
-import  { ref }  from 'vue';
-import {dateFormatter} from "@/utils/formatTime";
+import { ref, reactive, computed } from 'vue';
+import { dateFormatter } from "@/utils/formatTime";
+import { getgisAttr } from "@/api/layer/gisname"; // 导入获取图层属性的API
+import { Loading } from '@element-plus/icons-vue'
+import { useI18n } from '@/hooks/web/useI18n'
+import { useMessage } from '@/hooks/web/useMessage'
+import { getSimpleGisNameList } from "@/api/layer/gisname"
+
+/** 字段权限相关接口 */
+interface FieldPermission {
+  fieldName: string;   // 字段名称
+  enabled: boolean;    // 是否启用(开/关状态)
+}
+
+interface GisNameVO {
+  id?: number;        // 图层ID
+  shpName: string;    // 图层名称
+  [key: string]: any; // 其他属性
+}
 
-/** 资金拨付流程表	 表单 */
-defineOptions({ name: 'LayerAuthorityForm' })
+interface LayerRow {
+  id?: number;         // 记录ID
+  userId?: number;      // 用户ID
+  layer?: string;       // 图层名称
+  shpName?: string;     // 选择的图层名称(用于新行)
+  maturityTime?: number | string;  // 过期时间
+  createTime?: Date | string;    // 创建时间
+  onlyRead?: number;    // 权限类型:1=管理权限, 2=操作权限, 3=只读权限
+  fieldPermissions?: Record<string, boolean>; // 字段权限(字段名 -> 是否启用)
+  isNew?: boolean;      // 标记为新增行
+  valid?: boolean;      // 有效状态
+  daysLeft?: number;    // 剩余天数
+}
+
+interface UserInfo {
+  id?: number;
+  nickname?: string;
+  deptName?: string;
+  mobile?: string;
+  status?: number;
+}
+
+/** 图层权限管理表单 */
+defineOptions({ name: 'UserLayerAuthorityForm' })
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 const dialogVisible = ref(false) // 弹窗的是否展示
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formRef = ref() // 表单 Ref
 const formData = ref({
-  addUserId : undefined,
-  projectId : undefined,
-  pageNo: 1,
-  pageSize: 10,
-  nickname: undefined,
-  mobile: undefined,
-  status: undefined,
-  deptId: undefined,
-  createTime: []
+  userId: undefined as number | undefined,
+})
+
+// 当前用户信息
+const currentUserInfo = ref<UserInfo>({
+  nickname: '',
+  deptName: '',
+  mobile: '',
+  status: 0
 })
+
 const loading = ref(true) // 列表的加载中
 const total = ref(0) // 列表的总页数
-const list = ref([]) // 列表的数
+const list = ref<LayerRow[]>([]) // 列表的数据
+const deletedRows = ref<number[]>([]) // 要删除的行ID
+
+// 处理日期变更
+const handleDateChange = (row) => {
+  updateExpirationStatus(row);
+}
+
+// 更新过期状态和剩余天数
+const updateExpirationStatus = (row) => {
+  if (row.maturityTime != null && row.maturityTime !== 0) {
+    const maturityDate = typeof row.maturityTime === 'number'
+      ? new Date(row.maturityTime)
+      : new Date(parseInt(row.maturityTime));
+      
+    const now = new Date();
+    row.valid = maturityDate > now;
+
+    if (row.valid) {
+      // 计算剩余天数
+      const diffTime = maturityDate.getTime() - now.getTime();
+      row.daysLeft = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
+    } else {
+      row.daysLeft = 0;
+    }
+  }
+}
+
 const queryParams = reactive({
-  addUserId : undefined,
-  layer : undefined,
+  layer: undefined as string | undefined,
   pageNo: 1,
   pageSize: 10,
-  nickname: undefined,
-  mobile: undefined,
-  status: undefined,
-  deptId: undefined,
-  createTime: [],
-  userId : undefined
+  userId: undefined as number | undefined,
 })
 const queryFormRef = ref() // 搜索的表单
 
+// 字段权限相关
+const fieldPermissionDrawer = ref(false) // 字段权限抽屉是否可见
+const currentLayer = ref<LayerRow | null>(null) // 当前正在编辑字段权限的图层
+const layerFields = ref<FieldPermission[]>([]) // 图层字段列表
+const fieldLoading = ref(false) // 字段加载状态
+
+// 图层选项
+const layerOptions = ref<GisNameVO[]>([]);
+
+// 禁用过去的日期
+const disabledDate = (time: Date) => {
+  return time.getTime() < Date.now() - 8.64e7; // 禁用今天之前的日期
+}
+
+// 获取权限标签类型
+const getPermissionTagType = (onlyRead?: number) => {
+  switch (onlyRead) {
+    case 1: return 'danger'; // 管理权限
+    case 2: return 'warning'; // 操作权限
+    case 3: return 'success'; // 只读权限
+    default: return 'info';
+  }
+}
+
+// 获取权限标签文本
+const getPermissionLabel = (onlyRead?: number) => {
+  switch (onlyRead) {
+    case 1: return '管理权限';
+    case 2: return '操作权限';
+    case 3: return '只读权限';
+    default: return '未知权限';
+  }
+}
+
+// 获取可用的图层选项(过滤掉已经分配的)
+const availableLayers = (currentRow: LayerRow) => {
+  // 获取已分配的图层名称列表(排除当前行)
+  const assignedLayers = list.value
+    .filter(row => row !== currentRow && (row.layer || row.shpName))
+    .map(row => row.layer || row.shpName);
+  
+  // 返回未分配的图层选项
+  return layerOptions.value.filter(option => 
+    !assignedLayers.includes(option.shpName)
+  );
+};
+
+// 获取用户的图层列表
 const getList = async () => {
-  loading.value = true
+  loading.value = true;
   try {
-      const data = await GisFormApi.getUserLayer(queryParams)
-      console.log(data)
-      list.value = data.list
-      total.value = data.total
+    const data = await GisFormApi.getUserLayer({
+      ...queryParams,
+      userId: formData.value.userId
+    });
+    
+    // 处理数据,确保字段权限格式正确
+    list.value = data.map((item: any) => {
+      // 解析字段权限
+      if (item.fieldPermissions) {
+        try {
+          // 如果是字符串,则解析JSON
+          if (typeof item.fieldPermissions === 'string') {
+            item.fieldPermissions = JSON.parse(item.fieldPermissions);
+          }
+        } catch (error) {
+          console.error('解析字段权限失败:', error);
+          item.fieldPermissions = {}; // 使用空对象作为默认值
+        }
+      } else {
+        // 如果没有字段权限,使用空对象
+        item.fieldPermissions = {};
+      }
+      
+      // 确保日期处理和到期状态计算
+      if (item.maturityTime) {
+        // 如果后端返回的是ISO格式日期字符串,将其转换为时间戳
+        if (typeof item.maturityTime === 'string' && !item.maturityTime.includes('T')) {
+          // 将YYYY-MM-DD HH:mm:ss 转换为时间戳
+          const date = new Date(item.maturityTime.replace(' ', 'T') + 'Z');
+          item.maturityTime = date.getTime();
+        }
+      }
+      
+      // 更新过期状态和剩余天数
+      updateExpirationStatus(item);
+      
+      return item;
+    });
+    
+    // 重置删除记录
+    deletedRows.value = [];
+    
+    total.value = data.length;
+  } catch (error) {
+    console.error('获取用户图层列表失败:', error);
+    message.error('获取用户图层列表失败');
   } finally {
-    loading.value = false
+    loading.value = false;
+  }
+}
+
+// 获取可用图层列表
+const getLayerOptions = async () => {
+  try { 
+    const data = await getSimpleGisNameList();
+    layerOptions.value = data || [];
+  } catch (error) {
+    console.error('获取图层列表失败:', error);
+    message.error('获取图层列表失败');
+    layerOptions.value = [];
+  }
+}
+
+// 获取用户详细信息
+const getUserInfo = async (userId: number) => {
+  try {
+    const userInfo = await UserApi.getUser(userId);
+    currentUserInfo.value = userInfo;
+  } catch (error) {
+    console.error('获取用户信息失败:', error);
+    message.error('获取用户信息失败');
   }
 }
 
-const roleList = ref([] as RoleApi.RoleVO[]) // 角色的列表
-const userOptions = ref<UserApi.UserVO[]>([]) // 用户列表
 /** 打开弹窗 */
-const open = async ( userId : any) => {
-    queryParams.userId = userId
-    getList();
-    dialogVisible.value = true
-    resetForm()
-    // 修改时,设置数据
-    roleList.value = await RoleApi.getSimpleRoleList()
-    userOptions.value = await UserApi.getSimpleUserList()
+const open = async (userId: number) => {
+  formData.value.userId = userId;
+  queryParams.userId = userId;
+  
+  dialogVisible.value = true;
+  resetForm();
+  
+  // 获取用户详细信息
+  await getUserInfo(userId);
+  
+  // 获取可用图层列表
+  await getLayerOptions();
+  
+  // 获取用户的图层列表
+  await getList();
 }
 
-defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+// 添加一个新行
+const handleAddRow = () => {
+  // 创建一个新的空行
+  const newRow: LayerRow = {
+    userId: formData.value.userId,
+    onlyRead: 3, // 默认只读权限
+    maturityTime: Date.now() + 7 * 24 * 60 * 60 * 1000, // 默认7天后过期
+    fieldPermissions: {},
+    isNew: true
+  };
+  
+  // 添加到列表开头
+  list.value.unshift(newRow);
+}
 
-/** 提交表单 */
-const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
-const submitForm = async () => {
-    formLoading.value = true
-    try {
-        console.log(formData.value)
-
-        await GisFormApi.setAuthority(formData.value);
-
-        message.success(t('common.createSuccess'))
-        dialogVisible.value = false
-        // 发送操作成功的事件
-        emit('success')
-    } finally {
-        formLoading.value = false
+// 删除一行
+const handleDeleteRow = (index: number) => {
+  const row = list.value[index];
+  
+  // 如果是已有记录(有ID),将ID添加到要删除的列表中
+  if (row.id) {
+    deletedRows.value.push(row.id);
+  }
+  
+  // 从列表中移除
+  list.value.splice(index, 1);
+  
+  message.success('已移除该图层');
+}
+
+// 处理图层选择
+const handleLayerSelect = (row: LayerRow) => {
+  if (!row.shpName) {
+    row.layer = undefined;
+    return;
+  }
+  
+  // 使用选择的图层名称
+  row.layer = row.shpName;
+}
+
+// 打开字段权限配置抽屉
+const openFieldPermissions = async (row: LayerRow) => {
+  // 确定图层名称
+  const layerName = row.layer || row.shpName;
+  if (!layerName) {
+    message.warning('请先选择图层');
+    return;
+  }
+  
+  currentLayer.value = row;
+  fieldPermissionDrawer.value = true;
+  
+  // 加载字段信息
+  fieldLoading.value = true;
+  try {
+    // 从getgisAttr API获取字段列表
+    const fieldList = await getgisAttr(layerName);
+    
+    // 将返回的字段列表处理为我们需要的格式
+    if (fieldList && Array.isArray(fieldList)) {
+      // 如果用户已有字段权限配置,合并现有配置
+      if (row.fieldPermissions) {
+        // 创建新的字段权限列表
+        layerFields.value = fieldList.map((field: any) => {
+          // 根据API返回的字段格式来确定属性名
+          // 假设API返回的是字段名称字符串数组
+          const fieldName = typeof field === 'string' ? field : field.name || field.fieldName || field.toString();
+          return {
+            fieldName,
+            enabled: row.fieldPermissions?.[fieldName] ?? true // 默认启用
+          };
+        });
+      } else {
+        // 如果没有现有配置,所有字段默认启用
+        layerFields.value = fieldList.map((field: any) => {
+          const fieldName = typeof field === 'string' ? field : field.name || field.fieldName || field.toString();
+          return {
+            fieldName,
+            enabled: true
+          };
+        });
+      }
+    } else {
+      // 如果API返回的不是数组,显示警告
+      layerFields.value = [];
+      message.warning('无法获取图层字段信息');
     }
+  } catch (error) {
+    console.error('获取字段信息失败:', error);
+    message.error('获取字段信息失败');
+    layerFields.value = [];
+  } finally {
+    fieldLoading.value = false;
+  }
 }
 
-/** 重置按钮操作 */
-const addQuery = async () => {
-  await  GisFormApi.addTeamMember(queryParams)
-  message.success(t('common.createSuccess'))
-  queryFormRef.value?.resetFields()
-  handleQuery()
+// 批量应用权限设置
+const applyAllPermissions = (enabled: boolean) => {
+  layerFields.value.forEach(field => {
+    field.enabled = enabled;
+  });
+}
+
+// 保存字段权限配置
+const saveFieldPermissions = () => {
+  if (!currentLayer.value) return;
+  
+  // 将字段权限列表转换为字段->布尔值的映射
+  const fieldPermissions: Record<string, boolean> = {};
+  layerFields.value.forEach(field => {
+    fieldPermissions[field.fieldName] = field.enabled;
+  });
+  
+  // 保存到当前图层
+  currentLayer.value.fieldPermissions = fieldPermissions;
+  
+  // 关闭抽屉
+  fieldPermissionDrawer.value = false;
+  
+  message.success('字段权限配置已保存');
+}
+
+// 是否表单有效
+const isFormValid = (): boolean => {
+  // 检查是否所有新行都已选择图层和设置过期时间
+  const invalidRows = list.value.filter(row => 
+    (!row.layer && !row.shpName) || !row.maturityTime || !row.onlyRead
+  );
+  
+  if (invalidRows.length > 0) {
+    message.warning('请完善所有图层信息(包括图层、权限类型和过期时间)');
+    return false;
+  }
+  
+  // 检查是否有重复的图层
+  const layerNames = list.value.map(row => row.layer || row.shpName);
+  const uniqueLayerNames = new Set(layerNames);
+  
+  if (uniqueLayerNames.size !== layerNames.length) {
+    message.warning('存在重复的图层,请检查');
+    return false;
+  }
+  
+  return true;
 }
 
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  if (!isFormValid()) return;
+  
+  formLoading.value = true;
+  try {
+    // 准备提交数据
+    const submitData = {
+      userId: formData.value.userId,
+      layerList: list.value.map(row => ({
+        id: row.id, // 如果是新行,则为undefined
+        userId: formData.value.userId,
+        layer: row.layer || row.shpName,
+        onlyRead: row.onlyRead,
+        maturityTime:row.maturityTime,
+        fieldPermissions: JSON.stringify(row.fieldPermissions || {})
+      })),
+      deletedIds: deletedRows.value
+    };
+    
+    // 提交所有数据 - 使用批量更新方法
+    await GisFormApi.updateLayersByUser(submitData);
+    
+    message.success('图层权限更新成功');
+    dialogVisible.value = false;
+    // 发送操作成功的事件
+    emit('success');
+  } catch (error) {
+    console.error('提交失败:', error);
+    message.error('操作失败');
+  } finally {
+    formLoading.value = false;
+  }
+}
 
 /** 搜索按钮操作 */
 const handleQuery = () => {
-  queryParams.pageNo = 1
-  getList()
+  queryParams.pageNo = 1;
+  getList();
 }
 
 /** 重置按钮操作 */
 const resetQuery = () => {
-  queryFormRef.value?.resetFields()
-  handleQuery()
-}
-
-/** 删除人员按钮操作 */
-const deleteQuery = async (id : any) => {
-  await GisFormApi.deleteTeamMember(queryParams.layer,id)
-  message.success("删除成功!")
-  queryFormRef.value?.resetFields()
-  handleQuery()
+  queryFormRef.value?.resetFields();
+  queryParams.layer = undefined;
+  handleQuery();
 }
 
-// const handlePermissionChange =async (row) =>{
-//   loading.value = true
-//   await GisFormApi.updateTeamMember(row)
-//   message.success("更新成功!")
-//   loading.value = false
-// }
 /** 重置表单 */
 const resetForm = () => {
-  formData.value = {
-    id: -1 ,
-    roleIds: [],
-    userIds :[],
-    userIds :[],
-    readRoleIds: [],
-    readUserIds :[]
-  }
-  formRef.value?.resetFields()
+  queryParams.layer = undefined;
+  
+  // 重置删除列表
+  deletedRows.value = [];
 }
+
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
 </script>
+
+<style scoped>
+.flex {
+  display: flex;
+}
+.items-center {
+  align-items: center;
+}
+.justify-center {
+  justify-content: center;
+}
+.justify-between {
+  justify-content: space-between;
+}
+.gap-2 {
+  gap: 0.5rem;
+}
+.mb-4 {
+  margin-bottom: 1rem;
+}
+.mt-15px {
+  margin-top: 15px;
+}
+.py-10 {
+  padding-top: 2.5rem;
+  padding-bottom: 2.5rem;
+}
+.ml-2 {
+  margin-left: 0.5rem;
+}
+.text-gray-500 {
+  color: #6b7280;
+}
+.text-sm {
+  font-size: 0.875rem;
+  line-height: 1.25rem;
+}
+.p-4 {
+  padding: 1rem;
+}
+</style>