餐饮油烟智能监测与监管一体化平台
riku
2026-03-17 b1a0d701cf898c8b7812e66a808a1c91f2bae6cc
src/views/system/SystemManage.vue
@@ -1,2 +1,523 @@
<template>系统管理</template>
<script setup lang="ts"></script>
<template>
  <div class="system-manage">
    <el-card class="system-card">
      <template #header>
        <div class="card-header">
          <span>系统管理</span>
        </div>
      </template>
      <!-- 导航标签页 -->
      <el-tabs v-model="activeTab" class="system-tabs">
        <!-- 用户管理 -->
        <el-tab-pane label="用户管理" name="users">
          <div class="tab-content">
            <!-- 搜索和添加按钮 -->
            <div class="search-add-bar">
              <el-input
                v-model="userSearchQuery"
                placeholder="搜索用户"
                style="width: 200px"
                prefix-icon="el-icon-search"
              />
              <el-button type="primary" @click="openUserDialog">
                <el-icon><Plus /></el-icon> 添加用户
              </el-button>
            </div>
            <!-- 用户表格 -->
            <el-table :data="filteredUsers" style="width: 100%">
              <el-table-column prop="id" label="ID" width="80" />
              <el-table-column prop="username" label="用户名" />
              <el-table-column prop="name" label="姓名" />
              <el-table-column prop="role" label="角色" />
              <el-table-column prop="status" label="状态">
                <template #default="scope">
                  <el-tag :type="scope.row.status === 'active' ? 'success' : 'danger'">
                    {{ scope.row.status === 'active' ? '活跃' : '禁用' }}
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column label="操作" width="200">
                <template #default="scope">
                  <el-button size="small" @click="editUser(scope.row)"> 编辑 </el-button>
                  <el-button size="small" type="danger" @click="deleteUser(scope.row.id)">
                    删除
                  </el-button>
                  <el-button size="small" @click="setPermissions(scope.row)"> 权限 </el-button>
                </template>
              </el-table-column>
            </el-table>
            <!-- 分页 -->
            <el-pagination
              v-model:current-page="userCurrentPage"
              v-model:page-size="userPageSize"
              :page-sizes="[10, 20, 50]"
              layout="total, sizes, prev, pager, next, jumper"
              :total="users.length"
              style="margin-top: 20px"
            />
          </div>
        </el-tab-pane>
      </el-tabs>
    </el-card>
    <!-- 用户对话框 -->
    <el-dialog
      v-model="userDialogVisible"
      :title="isEditUser ? '编辑用户' : '添加用户'"
      width="500px"
    >
      <el-form :model="userForm" label-width="80px">
        <el-form-item label="用户名">
          <el-input v-model="userForm.username" />
        </el-form-item>
        <el-form-item label="姓名">
          <el-input v-model="userForm.name" />
        </el-form-item>
        <el-form-item label="密码" v-if="!isEditUser">
          <el-input type="password" v-model="userForm.password" />
        </el-form-item>
        <el-form-item label="角色">
          <el-select v-model="userForm.role">
            <el-option label="管理员" value="admin" />
            <el-option label="普通用户" value="user" />
            <el-option label="店铺管理员" value="restaurant_admin" />
          </el-select>
        </el-form-item>
        <el-form-item label="状态">
          <el-switch v-model="userForm.status" active-value="active" inactive-value="inactive" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="userDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="saveUser">保存</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- 权限设置对话框 -->
    <el-dialog v-model="permissionDialogVisible" title="权限设置" width="500px">
      <el-form label-width="80px">
        <el-form-item label="用户">
          <el-input :value="selectedUser?.name" disabled />
        </el-form-item>
        <el-form-item label="权限">
          <el-checkbox-group v-model="userPermissions">
            <el-checkbox label="user_management">用户管理</el-checkbox>
            <el-checkbox label="restaurant_management">店铺管理</el-checkbox>
            <el-checkbox label="device_management">设备管理</el-checkbox>
            <el-checkbox label="data_analysis">数据分析</el-checkbox>
            <el-checkbox label="system_settings">系统设置</el-checkbox>
          </el-checkbox-group>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="permissionDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="savePermissions">保存</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- 店铺对话框 -->
    <el-dialog
      v-model="restaurantDialogVisible"
      :title="isEditRestaurant ? '编辑店铺' : '添加店铺'"
      width="500px"
    >
      <el-form :model="restaurantForm" label-width="80px">
        <el-form-item label="店铺名称">
          <el-input v-model="restaurantForm.name" />
        </el-form-item>
        <el-form-item label="地址">
          <el-input v-model="restaurantForm.address" />
        </el-form-item>
        <el-form-item label="联系人">
          <el-input v-model="restaurantForm.contact" />
        </el-form-item>
        <el-form-item label="联系电话">
          <el-input v-model="restaurantForm.phone" />
        </el-form-item>
        <el-form-item label="营业执照">
          <el-input v-model="restaurantForm.license" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="restaurantDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="saveRestaurant">保存</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- 设备对话框 -->
    <el-dialog
      v-model="deviceDialogVisible"
      :title="isEditDevice ? '编辑设备' : '添加设备'"
      width="500px"
    >
      <el-form :model="deviceForm" label-width="80px">
        <el-form-item label="设备编号">
          <el-input v-model="deviceForm.deviceId" />
        </el-form-item>
        <el-form-item label="设备类型">
          <el-select v-model="deviceForm.type">
            <el-option label="油烟监测仪" value="fume_monitor" />
            <el-option label="颗粒物监测仪" value="particle_monitor" />
            <el-option label="噪声监测仪" value="noise_monitor" />
          </el-select>
        </el-form-item>
        <el-form-item label="安装位置">
          <el-input v-model="deviceForm.location" />
        </el-form-item>
        <el-form-item label="安装日期">
          <el-date-picker v-model="deviceForm.installDate" type="date" />
        </el-form-item>
        <el-form-item label="状态">
          <el-select v-model="deviceForm.status">
            <el-option label="在线" value="online" />
            <el-option label="离线" value="offline" />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="deviceDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="saveDevice">保存</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { Plus } from '@element-plus/icons-vue'
// 标签页状态
const activeTab = ref('users')
// 用户管理相关
const users = ref([
  { id: 1, username: 'admin', name: '管理员', role: 'admin', status: 'active' },
  { id: 2, username: 'user1', name: '用户1', role: 'user', status: 'active' },
  {
    id: 3,
    username: 'restaurant1',
    name: '店铺管理员1',
    role: 'restaurant_admin',
    status: 'active',
  },
])
const userSearchQuery = ref('')
const userCurrentPage = ref(1)
const userPageSize = ref(10)
const userDialogVisible = ref(false)
const isEditUser = ref(false)
const userForm = ref({
  id: 0,
  username: '',
  name: '',
  password: '',
  role: 'user',
  status: 'active',
})
// 权限管理相关
const permissionDialogVisible = ref(false)
const selectedUser = ref<any>(null)
const userPermissions = ref<string[]>([])
// 餐饮店铺管理相关
const restaurants = ref([
  {
    id: 1,
    name: '测试餐厅1',
    address: '北京市朝阳区',
    contact: '张三',
    phone: '13800138001',
    license: '123456789',
  },
  {
    id: 2,
    name: '测试餐厅2',
    address: '北京市海淀区',
    contact: '李四',
    phone: '13800138002',
    license: '987654321',
  },
])
const restaurantSearchQuery = ref('')
const restaurantCurrentPage = ref(1)
const restaurantPageSize = ref(10)
const restaurantDialogVisible = ref(false)
const isEditRestaurant = ref(false)
const restaurantForm = ref({
  id: 0,
  name: '',
  address: '',
  contact: '',
  phone: '',
  license: '',
})
// 设备管理相关
const devices = ref([
  {
    id: 1,
    restaurantId: 1,
    deviceId: 'FUM-001',
    type: 'fume_monitor',
    location: '厨房',
    status: 'online',
    installDate: '2024-01-01',
  },
  {
    id: 2,
    restaurantId: 1,
    deviceId: 'FUM-002',
    type: 'particle_monitor',
    location: '排烟口',
    status: 'online',
    installDate: '2024-01-02',
  },
  {
    id: 3,
    restaurantId: 2,
    deviceId: 'FUM-003',
    type: 'fume_monitor',
    location: '厨房',
    status: 'offline',
    installDate: '2024-01-03',
  },
])
const deviceSearchQuery = ref('')
const deviceCurrentPage = ref(1)
const devicePageSize = ref(10)
const deviceDialogVisible = ref(false)
const isEditDevice = ref(false)
const deviceForm = ref({
  id: 0,
  restaurantId: 0,
  deviceId: '',
  type: 'fume_monitor',
  location: '',
  status: 'online',
  installDate: '',
})
const selectedRestaurant = ref<any>(null)
// 计算属性
const filteredUsers = computed(() => {
  if (!userSearchQuery.value) return users.value
  return users.value.filter(
    (user) =>
      user.username.includes(userSearchQuery.value) || user.name.includes(userSearchQuery.value),
  )
})
const filteredRestaurants = computed(() => {
  if (!restaurantSearchQuery.value) return restaurants.value
  return restaurants.value.filter(
    (restaurant) =>
      restaurant.name.includes(restaurantSearchQuery.value) ||
      restaurant.address.includes(restaurantSearchQuery.value),
  )
})
const filteredDevices = computed(() => {
  if (!selectedRestaurant.value) return []
  let result = devices.value.filter((device) => device.restaurantId === selectedRestaurant.value.id)
  if (deviceSearchQuery.value) {
    result = result.filter(
      (device) =>
        device.deviceId.includes(deviceSearchQuery.value) ||
        device.type.includes(deviceSearchQuery.value),
    )
  }
  return result
})
// 方法
// 用户管理方法
const openUserDialog = () => {
  isEditUser.value = false
  userForm.value = {
    id: 0,
    username: '',
    name: '',
    password: '',
    role: 'user',
    status: 'active',
  }
  userDialogVisible.value = true
}
const editUser = (user: any) => {
  isEditUser.value = true
  userForm.value = { ...user }
  userDialogVisible.value = true
}
const saveUser = () => {
  if (isEditUser.value) {
    const index = users.value.findIndex((u) => u.id === userForm.value.id)
    if (index !== -1) {
      users.value[index] = { ...userForm.value }
    }
  } else {
    const newUser = {
      ...userForm.value,
      id: users.value.length + 1,
    }
    users.value.push(newUser)
  }
  userDialogVisible.value = false
}
const deleteUser = (id: number) => {
  users.value = users.value.filter((user) => user.id !== id)
}
const setPermissions = (user: any) => {
  selectedUser.value = user
  // 模拟权限数据
  userPermissions.value = ['user_management', 'restaurant_management']
  permissionDialogVisible.value = true
}
const savePermissions = () => {
  // 保存权限逻辑
  permissionDialogVisible.value = false
}
// 店铺管理方法
const openRestaurantDialog = () => {
  isEditRestaurant.value = false
  restaurantForm.value = {
    id: 0,
    name: '',
    address: '',
    contact: '',
    phone: '',
    license: '',
  }
  restaurantDialogVisible.value = true
}
const editRestaurant = (restaurant: any) => {
  isEditRestaurant.value = true
  restaurantForm.value = { ...restaurant }
  restaurantDialogVisible.value = true
}
const saveRestaurant = () => {
  if (isEditRestaurant.value) {
    const index = restaurants.value.findIndex((r) => r.id === restaurantForm.value.id)
    if (index !== -1) {
      restaurants.value[index] = { ...restaurantForm.value }
    }
  } else {
    const newRestaurant = {
      ...restaurantForm.value,
      id: restaurants.value.length + 1,
    }
    restaurants.value.push(newRestaurant)
  }
  restaurantDialogVisible.value = false
}
const deleteRestaurant = (id: number) => {
  restaurants.value = restaurants.value.filter((restaurant) => restaurant.id !== id)
  // 同时删除关联的设备
  devices.value = devices.value.filter((device) => device.restaurantId !== id)
  if (selectedRestaurant.value && selectedRestaurant.value.id === id) {
    selectedRestaurant.value = null
  }
}
const manageDevices = (restaurant: any) => {
  selectedRestaurant.value = restaurant
  activeTab.value = 'devices'
}
// 设备管理方法
const openDeviceDialog = () => {
  isEditDevice.value = false
  deviceForm.value = {
    id: 0,
    restaurantId: selectedRestaurant.value.id,
    deviceId: '',
    type: 'fume_monitor',
    location: '',
    status: 'online',
    installDate: '',
  }
  deviceDialogVisible.value = true
}
const editDevice = (device: any) => {
  isEditDevice.value = true
  deviceForm.value = { ...device }
  deviceDialogVisible.value = true
}
const saveDevice = () => {
  if (isEditDevice.value) {
    const index = devices.value.findIndex((d) => d.id === deviceForm.value.id)
    if (index !== -1) {
      devices.value[index] = { ...deviceForm.value }
    }
  } else {
    const newDevice = {
      ...deviceForm.value,
      id: devices.value.length + 1,
    }
    devices.value.push(newDevice)
  }
  deviceDialogVisible.value = false
}
const deleteDevice = (id: number) => {
  devices.value = devices.value.filter((device) => device.id !== id)
}
</script>
<style scoped>
.system-manage {
  padding: 20px;
}
.system-card {
  margin-bottom: 20px;
}
.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.system-tabs {
  margin-top: 20px;
}
.tab-content {
  padding: 20px 0;
}
.search-add-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}
.dialog-footer {
  display: flex;
  justify-content: flex-end;
}
</style>