# Vue3 + TypeScript + Element Plus 页面生成提示词

当需要创建新的前端页面时,按照以下模板生成代码:

## API 接口定义模板

```typescript
// src/api/{module}/{name}.ts
import request from '@/utils/request'

/**
 * {业务名称} VO 接口
 */
export interface {Name}VO {
  id?: number | string
  // ... 其他字段
}

/**
 * {业务名称} Form 接口
 */
export interface {Name}Form {
  id?: number | string
  // ... 其他字段
}

/**
 * {业务名称} 查询参数
 */
export interface {Name}Query {
  pageNum: number
  pageSize: number
  // ... 其他查询字段
}

/**
 * 查询{业务名称}列表
 */
export const list{Name} = (params: {Name}Query) => {
  return request({
    url: '/{module}/{path}/list',
    method: 'get',
    params
  })
}

/**
 * 查询{业务名称}详情
 */
export const get{Name} = (id: number | string) => {
  return request({
    url: `/{module}/{path}/${id}`,
    method: 'get'
  })
}

/**
 * 新增{业务名称}
 */
export const add{Name} = (data: {Name}Form) => {
  return request({
    url: '/{module}/{path}',
    method: 'post',
    data
  })
}

/**
 * 修改{业务名称}
 */
export const update{Name} = (data: {Name}Form) => {
  return request({
    url: '/{module}/{path}',
    method: 'put',
    data
  })
}

/**
 * 删除{业务名称}
 */
export const del{Name} = (ids: (number | string)[]) => {
  return request({
    url: `/{module}/{path}/${ids}`,
    method: 'delete'
  })
}
```

## 列表页面模板

```vue
<!-- src/views/{module}/{name}/index.vue -->
<script setup lang="ts" name="{Name}">
import { ref, reactive } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { {Name}VO, {Name}Query } from '@/api/{module}/{name}'
import { list{Name}, del{Name} } from '@/api/{module}/{name}'

// 查询参数
const queryParams = reactive<{Name}Query>({
  pageNum: 1,
  pageSize: 10
})

// 数据
const dataList = ref<{Name}VO[]>([])
const total = ref(0)
const loading = ref(false)

// 对话框
const dialogVisible = ref(false)
const dialogTitle = ref('')

/** 查询列表 */
const getList = async () => {
  loading.value = true
  try {
    const res = await list{Name}(queryParams)
    dataList.value = res.rows
    total.value = res.total
  } finally {
    loading.value = false
  }
}

/** 搜索按钮操作 */
const handleQuery = () => {
  queryParams.pageNum = 1
  getList()
}

/** 重置按钮操作 */
const resetQuery = () => {
  queryParams.pageNum = 1
  queryParams.pageSize = 10
  // 重置其他查询字段
  getList()
}

/** 新增按钮操作 */
const handleAdd = () => {
  dialogTitle.value = '添加{业务名称}'
  dialogVisible.value = true
}

/** 修改按钮操作 */
const handleUpdate = (row: {Name}VO) => {
  dialogTitle.value = '修改{业务名称}'
  dialogVisible.value = true
}

/** 删除按钮操作 */
const handleDelete = async (row: {Name}VO) => {
  try {
    await ElMessageBox.confirm(`是否确认删除该{业务名称}?`, '警告', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
    await del{Name}([row.id!])
    ElMessage.success('删除成功')
    await getList()
  } catch (error) {
    console.error(error)
  }
}

// 初始化
getList()
</script>

<template>
  <div class="p-2">
    <!-- 搜索栏 -->
    <el-form :model="queryParams" :inline="true">
      <el-form-item label="关键词" prop="keyword">
        <el-input
          v-model="queryParams.keyword"
          placeholder="请输入关键词"
          clearable
          @keyup.enter="handleQuery"
        />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="handleQuery">
          <i-ep-search /> 搜索
        </el-button>
        <el-button @click="resetQuery">
          <i-ep-refresh /> 重置
        </el-button>
      </el-form-item>
    </el-form>

    <!-- 工具栏 -->
    <el-row :gutter="10" class="mb-2">
      <el-col :span="1.5">
        <el-button
          type="primary"
          plain
          @click="handleAdd"
          v-hasPermi="['{module}:{function}:add']"
        >
          <i-ep-plus /> 新增
        </el-button>
      </el-col>
    </el-row>

    <!-- 表格 -->
    <el-table
      v-loading="loading"
      :data="dataList"
      border
      stripe
    >
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column label="ID" prop="id" width="100" />
      <!-- 其他列 -->
      <el-table-column label="操作" align="center" width="150" fixed="right">
        <template #default="{ row }">
          <el-button
            link
            type="primary"
            @click="handleUpdate(row)"
            v-hasPermi="['{module}:{function}:edit']"
          >
            修改
          </el-button>
          <el-button
            link
            type="danger"
            @click="handleDelete(row)"
            v-hasPermi="['{module}:{function}:remove']"
          >
            删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>

    <!-- 分页 -->
    <pagination
      v-show="total > 0"
      v-model:page="queryParams.pageNum"
      v-model:limit="queryParams.pageSize"
      :total="total"
      @pagination="getList"
    />

    <!-- 表单对话框 -->
    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="600px">
      <!-- 表单内容 -->
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submitForm">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>
```

## 表单组件模板

```vue
<!-- src/views/{module}/{name}/components/{Name}Form.vue -->
<script setup lang="ts">
import { ref, reactive } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import type { {Name}Form } from '@/api/{module}/{name}'
import { add{Name}, update{Name} } from '@/api/{module}/{name}'

const props = defineProps<{
  id?: number | string
}>()

const emit = defineEmits<{
  success: []
  cancel: []
}>()

const formRef = ref<FormInstance>()
const formData = reactive<{Name}Form>({})

const rules = reactive<FormRules<{Name}Form>>({
  // 字段验证规则
})

const submitForm = async () => {
  if (!formRef.value) return
  await formRef.value.validate()

  try {
    if (props.id) {
      await update{Name}(formData)
    } else {
      await add{Name}(formData)
    }
    emit('success')
  } catch (error) {
    console.error(error)
  }
}

defineExpose({
  submitForm
})
</script>

<template>
  <el-form
    ref="formRef"
    :model="formData"
    :rules="rules"
    label-width="100px"
  >
    <!-- 表单项 -->
  </el-form>
</template>
```

## 注意事项

1. 所有占位符 `{xxx}` 需要替换为实际值
2. 使用 Composition API 和 `<script setup>` 语法
3. 权限指令格式: `v-hasPermi="['模块:功能:操作']"`
4. 使用 Element Plus 图标: `<i-ep-icon-name />`
5. 表单验证规则根据实际需求添加
6. 使用 TypeScript 进行类型约束
7. 组件命名使用 PascalCase
