Răsfoiți Sursa

我的企业编写

“陈博论” 9 luni în urmă
părinte
comite
c63f96b477

+ 71 - 0
web/src/api/frontend/me.ts

@@ -50,4 +50,75 @@ export function subordinateList(data:anyObj) {
       method: 'get',
       params:data,
   })
+}
+
+//检查当前用户是否已有企业
+export function checkCompany() {
+  return createAxios({
+      url: '/api/invitation.Company/checkCompany',
+      method: 'get',
+  })
+}
+
+//获取我的企业列表
+export function myCompanies(data:anyObj) {
+  return createAxios({
+      url: '/api/invitation.Company/myCompanies',
+      method: 'get',
+      params:data,
+  })
+}
+
+//获取企业成员列表
+export function members(data:anyObj) {
+  return createAxios({
+      url: '/api/invitation.Company/members',
+      method: 'get',
+      params:data,
+  })
+}
+
+//创建企业
+export function createCompany(data:anyObj) {
+  return createAxios({
+      url: '/api/invitation.Company/createCompany',
+      method: 'post',
+      data:data,
+  })
+}
+
+//搜索邮箱用户(用于添加成员时搜索)
+export function searchEmail(data:anyObj) {
+  return createAxios({
+      url: '/api/invitation.Company/searchEmail',
+      method: 'get',
+      params:data,
+  })
+}
+
+//通过邮箱添加成员
+export function addMember(data:anyObj) {
+  return createAxios({
+      url: '/api/invitation.Company/addMember',
+      method: 'post',
+      data:data,
+  })
+}
+
+//移除企业成员
+export function removeMember(data:anyObj) {
+  return createAxios({
+      url: '/api/invitation.Company/removeMember',
+      method: 'post',
+      data:data,
+  })
+}
+
+//更新企业信息
+export function updateCompany(data:anyObj) {
+  return createAxios({
+      url: '/api/invitation.Company/updateCompany',
+      method: 'post',
+      data:data,
+  })
 }

+ 48 - 57
web/src/views/frontend/components/AddMemberDialog.vue

@@ -1,13 +1,7 @@
 <template>
-  <el-dialog
-    title="邮箱添加人员"
-    v-model:visible="dialogVisible"
-    width="480px"
-    :close-on-click-modal="false"
-    :close-on-press-escape="true"
-    class="add-member-dialog"
-    @close="handleClose"
-  >
+  <el-dialog title="邮箱添加人员" :model-value="props.visible" @update:model-value="(val) => emit('update:visible', val)"
+    width="480px" :close-on-click-modal="false" :close-on-press-escape="true" class="add-member-dialog"
+    @close="handleClose">
     <div class="add-member-form">
       <div class="form-item">
         <div class="label">
@@ -17,27 +11,16 @@
           <span>邮箱地址</span>
         </div>
         <div class="input-with-button">
-          <el-input
-            v-model="form.email"
-            placeholder="请输入邮箱地址"
-            clearable
-            :disabled="searching"
-            @keyup.enter="handleSearch"
-            @clear="handleClear"
-          >
+          <el-input v-model="form.email" placeholder="请输入邮箱地址" clearable :disabled="searching"
+            @keyup.enter="handleSearch" @clear="handleClear">
             <template #prefix>
               <el-icon class="input-prefix">
                 <Message />
               </el-icon>
             </template>
           </el-input>
-          <el-button
-            type="primary"
-            :loading="searching"
-            :disabled="!form.email || !form.email.trim()"
-            class="search-btn"
-            @click="handleSearch"
-          >
+          <el-button type="primary" :loading="searching" :disabled="!form.email || !form.email.trim()"
+            class="search-btn" @click="handleSearch">
             <el-icon v-if="!searching" class="search-icon">
               <Search />
             </el-icon>
@@ -96,16 +79,10 @@
     <template #footer>
       <span class="dialog-footer">
         <el-button size="medium" @click="handleCancel">取消</el-button>
-        <el-button
-          type="primary"
-          size="medium"
-          :loading="submitting"
-          :disabled="!searchedUser"
-          @click="handleSubmit"
-        >
-        <el-icon v-if="!submitting" class="submit-icon">
-          <Check />
-        </el-icon>
+        <el-button type="primary" size="medium" :loading="submitting" :disabled="!searchedUser" @click="handleSubmit">
+          <el-icon v-if="!submitting" class="submit-icon">
+            <Check />
+          </el-icon>
           <span>{{ submitting ? '添加中...' : '确认添加' }}</span>
         </el-button>
       </span>
@@ -114,8 +91,10 @@
 </template>
 
 <script setup>
-import { computed, getCurrentInstance, reactive, ref, watch } from 'vue'
+import { computed, reactive, ref, watch } from 'vue'
 import { Check, Message, Search, SuccessFilled, User, UserFilled, WarningFilled } from '@element-plus/icons-vue'
+import { ElMessage } from 'element-plus'
+import { searchEmail, addMember } from '/@/api/frontend/me'
 
 defineOptions({ name: 'AddMemberDialog' })
 
@@ -131,7 +110,6 @@ const props = defineProps({
 })
 
 const emit = defineEmits(['update:visible', 'success', 'close'])
-const { proxy } = getCurrentInstance()
 
 const form = reactive({
   email: ''
@@ -140,11 +118,6 @@ const searchedUser = ref(null)
 const searching = ref(false)
 const submitting = ref(false)
 
-const dialogVisible = computed({
-  get: () => props.visible,
-  set: val => emit('update:visible', val)
-})
-
 const isValidEmail = computed(() => {
   if (!form.email || !form.email.trim()) {
     return true
@@ -156,14 +129,14 @@ const isValidEmail = computed(() => {
 watch(
   () => props.visible,
   newVal => {
-    if (!newVal) {
+    if (newVal) {
+      resetForm()
+    } else {
       resetForm()
     }
   }
 )
 
-const message = proxy?.$message
-
 const resetForm = () => {
   form.email = ''
   searchedUser.value = null
@@ -177,22 +150,25 @@ const handleClear = () => {
 
 const handleSearch = async () => {
   if (!form.email || !form.email.trim()) {
-    message?.warning('请输入邮箱')
+    ElMessage.warning('请输入邮箱')
     return
   }
 
   if (!isValidEmail.value) {
-    message?.error('邮箱格式不正确')
+    ElMessage.error('邮箱格式不正确')
     return
   }
 
   searching.value = true
   try {
-    message?.info('搜索功能待实现,需要调用搜索用户接口')
-    searchedUser.value = null
+    const response = await searchEmail({
+      keyword: form.email.trim()
+    })
+
+    searchedUser.value = response.data[0]
+    ElMessage.success('搜索成功')
   } catch (error) {
-    console.error('搜索用户失败:', error)
-    message?.error('搜索用户失败')
+    ElMessage.error('搜索用户失败,请稍后重试')
     searchedUser.value = null
   } finally {
     searching.value = false
@@ -201,30 +177,44 @@ const handleSearch = async () => {
 
 const handleSubmit = async () => {
   if (!searchedUser.value) {
-    message?.warning('请先搜索用户')
+    ElMessage.warning('请先搜索用户')
     return
   }
 
   if (!props.companyId) {
-    message?.error('企业ID不能为空')
+    ElMessage.error('企业ID不能为空')
     return
   }
 
+  if (!form.email || !form.email.trim()) {
+    ElMessage.error('邮箱不能为空')
+    return
+  }
+
+  // 获取用户姓名,如果搜索返回的数据中没有name,使用email作为默认值
+  const userName = searchedUser.value.name || searchedUser.value.email || form.email.trim()
+
   submitting.value = true
   try {
-    message?.info('添加成员功能待实现,需要调用添加成员接口')
+    await addMember({
+      company_id: String(props.companyId),
+      email: form.email.trim(),
+      name: userName
+    })
+
+    ElMessage.success('添加成员成功')
     emit('success', searchedUser.value)
-    dialogVisible.value = false
+    emit('update:visible', false)
   } catch (error) {
     console.error('添加成员失败:', error)
-    message?.error('添加成员失败')
+    ElMessage.error('添加成员失败,请稍后重试')
   } finally {
     submitting.value = false
   }
 }
 
 const handleCancel = () => {
-  dialogVisible.value = false
+  emit('update:visible', false)
 }
 
 const handleClose = () => {
@@ -235,6 +225,7 @@ const handleClose = () => {
 
 <style scoped lang="scss">
 ::v-deep .add-member-dialog {
+
   .label-icon,
   .input-prefix,
   .search-icon,
@@ -558,10 +549,10 @@ const handleClose = () => {
     transform: scale(0);
     opacity: 0;
   }
+
   to {
     transform: scale(1);
     opacity: 1;
   }
 }
 </style>
-

+ 34 - 49
web/src/views/frontend/components/CreateEnterpriseDialog.vue

@@ -1,26 +1,15 @@
 <template>
-  <el-dialog
-    title="创建企业"
-    v-model:visible="dialogVisible"
-    width="420px"
-    @close="handleClose"
-  >
+  <el-dialog :model-value="props.visible" @update:model-value="(val) => emit('update:visible', val)" title="创建企业"
+    width="420px" @close="handleClose">
     <div class="enterprise-form">
       <div class="form-item">
         <div class="label">当前账号</div>
-        <el-input
-          v-model="form.account"
-          disabled
-        />
+        <el-input v-model="form.account" disabled />
         <p class="hint">注:一个账号只能归属一个企业</p>
       </div>
       <div class="form-item">
         <div class="label required">企业名称</div>
-        <el-input
-          v-model="form.name"
-          placeholder="请输入企业名称"
-          @keyup.enter="handleSubmit"
-        />
+        <el-input v-model="form.name" placeholder="请输入企业名称" @keyup.enter="handleSubmit" />
       </div>
     </div>
     <template #footer>
@@ -33,7 +22,10 @@
 </template>
 
 <script setup>
-import { computed, getCurrentInstance, reactive, ref, watch } from 'vue'
+import { getCurrentInstance, reactive, ref, watch } from 'vue'
+import { storeToRefs } from 'pinia'
+import { createCompany } from '/@/api/frontend/me'
+import { useUserInfo } from '/@/stores/userInfo'
 
 defineOptions({ name: 'CreateEnterpriseDialog' })
 
@@ -44,12 +36,10 @@ const props = defineProps({
   }
 })
 
-const emit = defineEmits(['update:visible', 'close'])
-const { proxy } = getCurrentInstance()
-// mock client user info to decouple from vuex
-const mockClientUser = reactive({
-  email: 'demo_client@example.com'
-})
+const emit = defineEmits(['update:visible', 'close', 'success'])
+import { ElMessage } from 'element-plus'
+const userStore = useUserInfo()
+const { email } = storeToRefs(userStore)
 
 const form = reactive({
   account: '',
@@ -57,13 +47,6 @@ const form = reactive({
 })
 const submitting = ref(false)
 
-const dialogVisible = computed({
-  get: () => props.visible,
-  set: val => emit('update:visible', val)
-})
-
-const clientEmail = computed(() => mockClientUser.email || '')
-
 watch(
   () => props.visible,
   newVal => {
@@ -76,18 +59,6 @@ watch(
   }
 )
 
-watch(
-  clientEmail,
-  newVal => {
-    if (newVal && !form.account) {
-      form.account = newVal
-    }
-  },
-  { immediate: true }
-)
-
-const message = proxy?.$message
-
 const initForm = () => {
   form.name = ''
   ensureClientEmail()
@@ -99,24 +70,23 @@ const resetForm = () => {
 }
 
 const ensureClientEmail = () => {
-  // use mock email as placeholder until real API is wired
-  form.account = clientEmail.value || 'client@example.com'
+  form.account = email.value || '未知账号'
 }
 
 const validateForm = () => {
   if (!form.name || !form.name.trim()) {
-    message?.error('请输入企业名称')
+    ElMessage.error('请输入企业名称')
     return false
   }
 
   const trimmedName = form.name.trim()
   if (trimmedName.length < 2) {
-    message?.error('企业名称至少需要2个字符')
+    ElMessage.error('企业名称至少需要2个字符')
     return false
   }
 
   if (trimmedName.length > 50) {
-    message?.error('企业名称不能超过50个字符')
+    ElMessage.error('企业名称不能超过50个字符')
     return false
   }
 
@@ -131,11 +101,27 @@ const handleSubmit = async () => {
 }
 
 const createEnterprise = async () => {
-  // TODO: 接入创建企业接口
+  if (submitting.value) return
+
+  submitting.value = true
+  try {
+    const response = await createCompany({ name: form.name.trim() })
+    if (response.code === 1) {
+      ElMessage.success('企业创建成功')
+      emit('success', response.data)
+      emit('update:visible', false)
+    } else {
+      ElMessage.error(response.msg || '创建企业失败')
+    }
+  } catch (error) {
+    ElMessage.error('创建企业失败,请稍后重试')
+  } finally {
+    submitting.value = false
+  }
 }
 
 const handleCancel = () => {
-  dialogVisible.value = false
+  emit('update:visible', false)
 }
 
 const handleClose = () => {
@@ -173,4 +159,3 @@ const handleClose = () => {
   }
 }
 </style>
-

+ 167 - 131
web/src/views/frontend/components/Me/enterprise.vue

@@ -21,7 +21,7 @@
         </div>
         <p class="empty-text">您还没有加入任何企业</p>
 
-        <el-button type="primary" @click="showCreateDialog = true">
+        <el-button type="primary" @click="openCreateDialog">
           创建企业
         </el-button>
       </div>
@@ -48,45 +48,37 @@
 
         <!-- 员工列表表格 -->
         <div class="table-section">
-          <el-table
-            ref="employeeTable"
-            :data="employeeList"
-            style="width: 100%"
-            :header-cell-style="{ background: '#f5f7fa', color: '#606266', fontWeight: '500' }"
-            empty-text="暂无员工数据"
-            @selection-change="handleSelectionChange"
-          >
+          <el-table ref="employeeTable" :data="employeeList" style="width: 100%"
+            :header-cell-style="{ background: '#f5f7fa', color: '#606266', fontWeight: '500' }" empty-text="暂无员工数据"
+            @selection-change="handleSelectionChange">
             <el-table-column type="selection" width="55" align="center" />
             <el-table-column prop="id" label="编号" width="100" align="center" />
             <el-table-column prop="name" label="姓名" min-width="150" align="center" />
             <el-table-column prop="email" label="邮箱" min-width="200" align="center" />
-            <el-table-column prop="status" label="状态" width="120" align="center">
+            <el-table-column prop="role_text" label="角色" width="140" align="center">
               <template #default="{ row }">
-                <el-tag :type="getStatusType(row.status)" size="small">
-                  {{ getStatusText(row.status) }}
+                <el-tag :type="row.role === 1 ? 'success' : 'info'" size="small">
+                  {{ row.role_text }}
                 </el-tag>
               </template>
             </el-table-column>
-            <el-table-column prop="createdAt" label="注册时间" width="180" align="center">
+            <el-table-column prop="status" label="状态" width="120" align="center">
               <template #default="{ row }">
-                {{ formatDate(row.createdAt || row.created_time || row.createdTime) }}
+                <el-tag :type="getStatusType(row.status)" size="small">
+                  {{ row.status_text }}
+                </el-tag>
               </template>
             </el-table-column>
+            <el-table-column prop="join_time_formatted" label="加入时间" width="160" align="center" />
+
             <el-table-column label="操作" width="200" align="center" fixed="right">
               <template #default="{ row }">
-                <el-button
-                  type="primary"
-                  size="small"
-                  @click="handleOpenProductSeatDialog([row.id])"
-                >
+                <el-button type="primary" size="small" :disabled="!row.can_operate"
+                  @click="handleOpenProductSeatDialog([row.id])">
                   产品分配
                 </el-button>
-                <el-button
-                  type="danger"
-                  size="small"
-                  :disabled="row.id === currentUserId"
-                  @click="handleDeleteMember(row)"
-                >
+                <el-button type="danger" size="small" :disabled="!row.can_operate || row.id === currentUserId"
+                  @click="handleDeleteMember(row)">
                   删除
                 </el-button>
               </template>
@@ -100,19 +92,11 @@
             <span>已选择 <strong>{{ selectedEmployeeIds.length }}</strong> 位员工</span>
           </div>
           <div class="batch-buttons">
-            <el-button
-              type="primary"
-              size="small"
-              :icon="Goods"
-              @click="handleOpenProductSeatDialog(selectedEmployeeIds)"
-            >
+            <el-button type="primary" size="small" :icon="Goods" :disabled="!canOperateSelected"
+              @click="handleOpenProductSeatDialog(selectedEmployeeIds)">
               批量产品分配
             </el-button>
-            <el-button
-              size="small"
-              :icon="Close"
-              @click="handleClearSelection"
-            >
+            <el-button size="small" :icon="Close" @click="handleClearSelection">
               取消选择
             </el-button>
           </div>
@@ -120,43 +104,25 @@
 
         <!-- 分页控件 -->
         <div v-if="employeeList.length > 0 || total > 0" class="pagination-section">
-          <el-pagination
-            :current-page="currentPage"
-            :page-size="pageSize"
-            :page-sizes="pageSizes"
-            :total="total"
-            layout="total, sizes, prev, pager, next, jumper"
-            background
-            @size-change="handlePageSizeChange"
-            @current-change="handleCurrentPageChange"
-          />
+          <el-pagination :current-page="currentPage" :page-size="pageSize" :page-sizes="pageSizes" :total="total"
+            layout="total, sizes, prev, pager, next, jumper" background @size-change="handlePageSizeChange"
+            @current-change="handleCurrentPageChange" />
         </div>
       </div>
     </div>
 
     <!-- 创建企业弹框 -->
-    <CreateEnterpriseDialog
-      v-model:visible="showCreateDialog"
-      @success="handleCreateSuccess"
-      @close="handleDialogClose"
-    />
+    <CreateEnterpriseDialog v-model:visible="showCreateDialog" @success="handleCreateSuccess"
+      @close="handleDialogClose" />
 
     <!-- 添加企业成员弹框 -->
-    <AddMemberDialog
-      v-model:visible="showAddMemberDialog"
-      :company-id="currentCompanyId"
-      @success="handleAddMemberSuccess"
-      @close="handleAddMemberDialogClose"
-    />
+    <AddMemberDialog v-model:visible="showAddMemberDialog" :company-id="currentCompanyId" @success="loadEnterpriseList"
+      @close="showAddMemberDialog = false" />
 
     <!-- 产品分配席位弹框 -->
-    <ProductSeatDialog
-      v-model:visible="showProductSeatDialog"
-      :member-list="employeeList"
-      :selected-member-ids="selectedMemberIdsForDialog"
-      @success="handleProductSeatSuccess"
-      @close="handleProductSeatDialogClose"
-    />
+    <ProductSeatDialog v-model:visible="showProductSeatDialog" :member-list="employeeList"
+      :selected-member-ids="selectedMemberIdsForDialog" @success="handleProductSeatSuccess"
+      @close="handleProductSeatDialogClose" />
   </div>
 </template>
 
@@ -169,17 +135,23 @@ import { useUserInfo } from '/@/stores/userInfo'
 import CreateEnterpriseDialog from '../CreateEnterpriseDialog.vue'
 import AddMemberDialog from '../AddMemberDialog.vue'
 import ProductSeatDialog from '../ProductSeatDialog.vue'
+import { checkCompany, myCompanies, members, removeMember } from '/@/api/frontend/me'
 
 defineOptions({ name: 'MeEnterprise' })
 
 type Employee = {
   id: number
-  name: string
-  email: string
-  status: number
-  createdAt: string
-  created_time?: string
-  createdTime?: string
+  name: string // 企业名称
+  email: string // 电子邮箱
+  role: number // 角色:1创建人/管理员,2普通成员
+  status: number // 状态:1正常,2禁用
+  join_time: string // 加入时间
+  create_time: string // 创建时间
+  role_text: string // 角色文本
+  status_text: string // 状态文本
+  join_time_formatted: string // 格式化的加入时间
+  create_time_formatted: string // 格式化的创建时间
+  can_operate: boolean // 是否可以操作(只有创建人可以操作)
 }
 
 type ProductSeatResult = {
@@ -192,25 +164,19 @@ const { id: userId } = storeToRefs(userStore)
 
 const loading = ref(false)
 const employeeList = ref<Employee[]>([
-  { id: 1, name: '张三', email: 'zhangsan@example.com', status: 1, createdAt: '2025-01-01 12:00:00' },
-  { id: 2, name: '李四', email: 'lisi@example.com', status: 1, createdAt: '2025-01-01 12:00:00' },
-  { id: 3, name: '王五', email: 'wangwu@example.com', status: 1, createdAt: '2025-01-01 12:00:00' },
-  { id: 4, name: '赵六', email: 'zhaoliu@example.com', status: 1, createdAt: '2025-01-01 12:00:00' },
-  { id: 5, name: '孙七', email: 'sunqi@example.com', status: 1, createdAt: '2025-01-01 12:00:00' },
-  { id: 6, name: '周八', email: 'zhouba@example.com', status: 1, createdAt: '2025-01-01 12:00:00' },
-  { id: 7, name: '吴九', email: 'wujiu@example.com', status: 1, createdAt: '2025-01-01 12:00:00' },
-  { id: 8, name: '郑十', email: 'zhengshi@example.com', status: 1, createdAt: '2025-01-01 12:00:00' }
+
 ])
 const showCreateDialog = ref(false)
 const showAddMemberDialog = ref(false)
 const showProductSeatDialog = ref(false)
 const selectedEmployeeIds = ref<number[]>([])
 const selectedMemberIdsForDialog = ref<number[]>([])
+
 const employeeTable = ref()
 const currentPage = ref(1)
 const pageSize = ref(10)
 const pageSizes = [10, 20, 30, 50]
-const total = ref(1)
+const total = ref(0)
 
 // 企业数据占位,后续可通过接口填充
 const companyId = ref<number | string | null>(null)
@@ -223,7 +189,7 @@ const hasEnterprise = computed(() => {
   return true
 })
 
-const currentCompanyId = computed(() => companyId.value)
+const currentCompanyId: any = computed(() => companyId.value)
 
 const currentEnterpriseName = computed(() => {
   if (!hasEnterprise.value) return '我的企业'
@@ -233,46 +199,55 @@ const currentEnterpriseName = computed(() => {
 
 const currentUserId = computed(() => userId.value || null)
 
-const formatDate = (dateStr?: string) => {
-  if (!dateStr) return '-'
-  const date = new Date(dateStr)
-  if (Number.isNaN(date.getTime())) return dateStr
-
-  const year = date.getFullYear()
-  const month = String(date.getMonth() + 1).padStart(2, '0')
-  const day = String(date.getDate()).padStart(2, '0')
-  const hours = String(date.getHours()).padStart(2, '0')
-  const minutes = String(date.getMinutes()).padStart(2, '0')
+// 检查选中的员工是否都可以操作
+const canOperateSelected = computed(() => {
+  if (selectedEmployeeIds.value.length === 0) return false
+  const selectedEmployees = employeeList.value.filter(emp => selectedEmployeeIds.value.includes(emp.id))
+  return selectedEmployees.every(emp => emp.can_operate)
+})
 
-  return `${year}-${month}-${day} ${hours}:${minutes}`
-}
+// 请求锁,防止重复请求
+const isLoadingList = ref(false)
 
-type TagType = 'success' | 'warning' | 'info' | 'danger' | 'primary'
-
-const getStatusType = (status: number): TagType => {
-  const statusMap: Record<number, TagType> = {
-    1: 'success',
-    2: 'danger'
+// 获取企业列表及员工
+const loadEnterpriseList = async () => {
+  if (!hasEnterprise.value) {
+    loading.value = false
+    employeeList.value = []
+    total.value = 0
+    return
   }
-  return statusMap[status] || 'info'
-}
 
-const getStatusText = (status: number) => {
-  const statusMap: Record<number, string> = {
-    1: '启用',
-    2: '禁用'
+  // 如果正在加载,直接返回,避免重复请求
+  if (isLoadingList.value) {
+    return
   }
-  return statusMap[status] || '未知'
-}
 
-const loadEnterpriseList = async () => {
-  // TODO: 接入实际接口
-  loading.value = false
-}
+  isLoadingList.value = true
+  loading.value = true
+  try {
+    // 获取企业成员列表
+    const membersRes = await members({
+      company_id: companyId.value,
+      page: currentPage.value,
+      limit: pageSize.value
+    })
 
-const initEnterpriseData = async () => {
-  // TODO: 拉取企业数据并填充 companyId/companyName
-  loadEnterpriseList()
+    employeeList.value = membersRes.data?.list || []
+    total.value = membersRes.data?.total || 0
+  } catch (error: any) {
+    // 如果是取消的请求(axios 自动取消重复请求),不显示错误
+    // axios 取消的请求通常会有 message 属性包含 'cancel' 或 'Cancel'
+    if (error?.message && (error.message.includes('cancel') || error.message.includes('Cancel'))) {
+      return
+    }
+    ElMessage.error('获取成员列表失败')
+    employeeList.value = []
+    total.value = 0
+  } finally {
+    loading.value = false
+    isLoadingList.value = false
+  }
 }
 
 const handlePageSizeChange = (val: number) => {
@@ -286,54 +261,99 @@ const handleCurrentPageChange = (val: number) => {
   loadEnterpriseList()
 }
 
-const handleCreateSuccess = async () => {
-  // TODO: 创建成功后刷新企业信息
-  currentPage.value = 1
-  loadEnterpriseList()
-  ElMessage.success('企业创建成功')
+const handleCreateSuccess = async (data?: any) => {
+  // 创建成功后刷新企业信息
+  if (data?.id) {
+    currentPage.value = 1
+    companyId.value = data.id
+    companyName.value = data.name || ''
+    // companyId 变化会触发 watch,自动加载列表,不需要手动调用
+  } else {
+    // 如果没有返回数据,重新检查企业信息
+    await handleCheckCompany()
+  }
 }
 
 const handleDialogClose = () => {
   showCreateDialog.value = false
 }
 
+// 创建企业
+const openCreateDialog = () => {
+  console.log('openCreateDialog called, showCreateDialog before:', showCreateDialog.value)
+  showCreateDialog.value = true
+  console.log('showCreateDialog after:', showCreateDialog.value)
+}
+
 const handleDeleteMember = async (member: Employee) => {
   if (!member?.id) {
     ElMessage.error('成员信息不完整')
     return
   }
 
+  if (!member.can_operate) {
+    ElMessage.warning('您没有权限操作此成员')
+    return
+  }
+
   try {
     await ElMessageBox.confirm(`确定要删除成员 "${member.name || member.email}" 吗?`, '提示', {
       confirmButtonText: '确定',
       cancelButtonText: '取消',
       type: 'warning'
     })
-    // TODO: 调用删除成员 API
+
+    const res = await removeMember({
+      member_id: member.id,
+      company_id: companyId.value
+    })
+
     ElMessage.success('删除成员成功')
     loadEnterpriseList()
-  } catch {
-    // 用户取消
+  } catch (error: any) {
+    if (error !== 'cancel') {
+      console.error('删除成员失败:', error)
+      ElMessage.error('删除成员失败')
+    }
   }
 }
 
-const handleAddMemberSuccess = () => {
-  loadEnterpriseList()
-}
-
-const handleAddMemberDialogClose = () => {
-  showAddMemberDialog.value = false
+// 检查是否有企业
+const handleCheckCompany = async () => {
+  try {
+    const res = await checkCompany()
+    if (res.code === 1 && res.data?.has_company) {
+      // 如果已有企业,获取企业信息
+      const companiesRes = await myCompanies({})
+      const company = companiesRes.data
+      currentPage.value = 1
+      companyId.value = company.id
+      companyName.value = company.name || ''
+      // companyId 变化会触发 watch,自动加载列表,不需要手动调用
+    } else {
+      // 没有企业,清空数据
+      companyId.value = null
+      companyName.value = ''
+    }
+  } catch (error) {
+    console.error('检查企业失败:', error)
+    ElMessage.error('检查企业状态失败')
+    companyId.value = null
+    companyName.value = ''
+  }
 }
 
 const handleSelectionChange = (selection: Employee[]) => {
   selectedEmployeeIds.value = selection.map(item => item.id)
 }
 
+// 分配产品席位
 const handleClearSelection = () => {
   employeeTable.value?.clearSelection()
   selectedEmployeeIds.value = []
 }
 
+// 选择分配员工
 const handleOpenProductSeatDialog = (memberIds: number[]) => {
   if (!memberIds || memberIds.length === 0) {
     ElMessage.warning('请至少选择一个员工')
@@ -359,18 +379,33 @@ const handleProductSeatDialogClose = () => {
   selectedMemberIdsForDialog.value = []
 }
 
+type TagType = 'success' | 'warning' | 'info' | 'danger' | 'primary'
+
+const getStatusType = (status: number): TagType => {
+  const statusMap: Record<number, TagType> = {
+    1: 'success',
+    2: 'danger'
+  }
+  return statusMap[status] || 'info'
+}
+
 watch(
   companyId,
   (newVal, oldVal) => {
-    if (newVal && !oldVal) {
+    // 只在 companyId 从无到有或发生变化时加载
+    // 避免初始化时 immediate 触发(因为初始值为 null)
+    if (newVal && newVal !== oldVal) {
       loadEnterpriseList()
+    } else if (!newVal && oldVal) {
+      // 如果企业被清空,清空列表
+      employeeList.value = []
+      total.value = 0
     }
-  },
-  { immediate: true }
+  }
 )
 
 onMounted(() => {
-  initEnterpriseData()
+  handleCheckCompany()
 })
 </script>
 
@@ -589,6 +624,7 @@ onMounted(() => {
   0% {
     transform: rotate(0deg);
   }
+
   100% {
     transform: rotate(360deg);
   }