zouyu
2025-11-14 5067cad099f9e3ec0a006a5913c28850f5a13391
src/views/demo/fakePage/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,248 @@
<template>
  <div class="app-container">
    <el-card shadow="never">
      <div class="toolbar">
        <el-input
          v-model="query.keyword"
          placeholder="搜索名称/类别"
          clearable
          style="width: 240px"
          @keyup.enter="handleSearch"
        />
        <el-select
          v-model="query.status"
          placeholder="状态"
          clearable
          style="width: 140px; margin-left: 12px"
        >
          <el-option label="启用" value="启用" />
          <el-option label="停用" value="停用" />
        </el-select>
        <el-button type="primary" style="margin-left: 12px" @click="handleSearch">查询</el-button>
        <el-button @click="resetQuery">重置</el-button>
        <el-button type="success" plain style="float: right" @click="openCreate">新增</el-button>
      </div>
      <el-table :data="pagedList" border style="width: 100%" height="480" stripe>
        <el-table-column prop="id" label="编号" width="90" sortable />
        <el-table-column prop="name" label="名称" min-width="140" />
        <el-table-column prop="category" label="类别" width="120" />
        <el-table-column prop="stock" label="库存" width="100" sortable />
        <el-table-column prop="price" label="单价(Â¥)" width="120">
          <template #default="scope">{{ formatPrice(scope.row.price) }}</template>
        </el-table-column>
        <el-table-column label="状态" width="120">
          <template #default="scope">
            <el-tag :type="scope.row.status === '启用' ? 'success' : 'info'">{{ scope.row.status }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="updatedAt" label="更新时间" min-width="160" />
        <el-table-column label="操作" width="180" fixed="right">
          <template #default="scope">
            <el-button link type="primary" @click="openEdit(scope.row)">编辑</el-button>
            <el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <div class="pagination">
        <el-pagination
          background
          layout="total, sizes, prev, pager, next, jumper"
          :total="filteredList.length"
          :page-sizes="[5, 10, 20, 50]"
          :page-size="pager.pageSize"
          :current-page="pager.pageNum"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
      </div>
    </el-card>
    <el-dialog v-model="dialogVisible" :title="isEdit ? '编辑' : '新增'" width="520px">
      <el-form :model="form" :rules="rules" ref="formRef" label-width="90px">
        <el-form-item label="名称" prop="name">
          <el-input v-model="form.name" placeholder="请输入名称" />
        </el-form-item>
        <el-form-item label="类别" prop="category">
          <el-select v-model="form.category" placeholder="请选择类别" style="width: 100%">
            <el-option label="原料" value="原料" />
            <el-option label="半成品" value="半成品" />
            <el-option label="成品" value="成品" />
          </el-select>
        </el-form-item>
        <el-form-item label="库存" prop="stock">
          <el-input v-model.number="form.stock" type="number" min="0" />
        </el-form-item>
        <el-form-item label="单价(Â¥)" prop="price">
          <el-input v-model.number="form.price" type="number" min="0" step="0.01" />
        </el-form-item>
        <el-form-item label="状态" prop="status">
          <el-radio-group v-model="form.status">
            <el-radio label="启用">启用</el-radio>
            <el-radio label="停用">停用</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取 æ¶ˆ</el-button>
        <el-button type="primary" @click="submitForm">ç¡® å®š</el-button>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import { ref, reactive, computed, nextTick } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
defineOptions({ name: 'FakePage' })
const query = reactive({
  keyword: '',
  status: ''
})
const pager = reactive({
  pageNum: 1,
  pageSize: 10
})
const allList = ref(generateMockData())
const filteredList = computed(() => {
  const keyword = (query.keyword || '').trim()
  const status = query.status
  return allList.value.filter(item => {
    const hitKeyword = !keyword || item.name.includes(keyword) || item.category.includes(keyword)
    const hitStatus = !status || item.status === status
    return hitKeyword && hitStatus
  })
})
const pagedList = computed(() => {
  const start = (pager.pageNum - 1) * pager.pageSize
  const end = start + pager.pageSize
  return filteredList.value.slice(start, end)
})
function handleSearch() {
  pager.pageNum = 1
}
function resetQuery() {
  query.keyword = ''
  query.status = ''
  pager.pageNum = 1
}
function handleSizeChange(size) {
  pager.pageSize = size
  pager.pageNum = 1
}
function handleCurrentChange(page) {
  pager.pageNum = page
}
function formatPrice(val) {
  return Number(val || 0).toFixed(2)
}
// æ–°å¢ž/编辑
const dialogVisible = ref(false)
const isEdit = ref(false)
const formRef = ref()
const form = reactive({ id: null, name: '', category: '', stock: 0, price: 0, status: '启用' })
const rules = {
  name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
  category: [{ required: true, message: '请选择类别', trigger: 'change' }],
  stock: [{ required: true, message: '请输入库存', trigger: 'blur' }],
  price: [{ required: true, message: '请输入单价', trigger: 'blur' }]
}
function openCreate() {
  isEdit.value = false
  Object.assign(form, { id: null, name: '', category: '', stock: 0, price: 0, status: '启用' })
  dialogVisible.value = true
  nextTick(() => formRef.value?.clearValidate?.())
}
function openEdit(row) {
  isEdit.value = true
  Object.assign(form, JSON.parse(JSON.stringify(row)))
  dialogVisible.value = true
  nextTick(() => formRef.value?.clearValidate?.())
}
function submitForm() {
  formRef.value?.validate?.((valid) => {
    if (!valid) return
    if (isEdit.value) {
      const index = allList.value.findIndex(x => x.id === form.id)
      if (index > -1) {
        allList.value[index] = { ...form, updatedAt: nowString() }
        ElMessage.success('已保存')
      }
    } else {
      const newId = Date.now()
      allList.value.unshift({ ...form, id: newId, updatedAt: nowString() })
      ElMessage.success('已新增')
    }
    dialogVisible.value = false
  })
}
function handleDelete(row) {
  ElMessageBox.confirm(`确认删除【${row.name}】吗?`, '提示', { type: 'warning' })
    .then(() => {
      allList.value = allList.value.filter(x => x.id !== row.id)
      ElMessage.success('已删除')
    })
    .catch(() => {})
}
function generateMockData() {
  const categories = ['原料', '半成品', '成品']
  const statusOptions = ['启用', '停用']
  const list = []
  for (let i = 1; i <= 36; i++) {
    list.push({
      id: i,
      name: `物料-${i.toString().padStart(3, '0')}`,
      category: categories[i % categories.length],
      stock: Math.floor(Math.random() * 1000),
      price: (Math.random() * 500 + 10).toFixed(2),
      status: statusOptions[i % 2],
      updatedAt: nowString()
    })
  }
  return list
}
function nowString() {
  const d = new Date()
  const yyyy = d.getFullYear()
  const MM = String(d.getMonth() + 1).padStart(2, '0')
  const dd = String(d.getDate()).padStart(2, '0')
  const hh = String(d.getHours()).padStart(2, '0')
  const mm = String(d.getMinutes()).padStart(2, '0')
  const ss = String(d.getSeconds()).padStart(2, '0')
  return `${yyyy}-${MM}-${dd} ${hh}:${mm}:${ss}`
}
</script>
<style scoped>
.toolbar {
  margin-bottom: 12px;
}
.pagination {
  margin-top: 12px;
  text-align: right;
}
</style>