This commit is contained in:
iqudoo
2026-06-05 17:22:32 +08:00
commit eb4e8f1a04
90 changed files with 21224 additions and 0 deletions

View File

@@ -0,0 +1,491 @@
<template>
<div class="demo-page">
<div class="demo-intro">
<p>本页演示项目中 <code>@/iview</code> 封装组件的常见用法数据均为本地 Mock无需后端接口</p>
</div>
<IViewTabs v-model:activeKey="activeSection" :animated="false" embedded>
<IViewTabPane key="form" tab="表单 IViewForm">
<div v-if="activeSection === 'form'" class="demo-section">
<IViewForm
ref="formRef"
v-model="formData"
:config="formConfig"
:read-only="formReadOnly"
/>
<div class="demo-actions">
<a-button type="primary" @click="handleFormSubmit">提交校验</a-button>
<a-button @click="handleFormReset">重置</a-button>
<a-button @click="formReadOnly = !formReadOnly">
{{ formReadOnly ? "切换为编辑" : "切换为只读" }}
</a-button>
</div>
<a-alert
v-if="formResult"
type="info"
show-icon
:message="'表单数据:' + formResult"
style="margin-top: 16px"
/>
</div>
</IViewTabPane>
<IViewTabPane key="list" tab="列表 IViewTable">
<div v-if="activeSection === 'list'" class="demo-section">
<IViewFilter
v-model="filterParams"
:config="filterConfig"
@search="handleFilterSearch"
@reset="handleFilterReset"
/>
<div class="demo-list-header">
<span class="demo-list-title">订单列表示例 {{ filteredList.length }} </span>
<a-button type="primary" @click="handleAddRecord">
<template #icon><plus-outlined /></template>
新增
</a-button>
</div>
<IViewTable
:loading="listLoading"
:columns="listColumns"
:data-source="filteredList"
row-key="id"
:pagination="tablePagination"
@change="handleTableChange"
>
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'status'">
<a-tag :color="statusColor(record.status)">{{ statusLabel(record.status) }}</a-tag>
</template>
<template v-if="column.dataIndex === 'action'">
<a-button size="small" type="link" @click="handleViewRecord(record)">查看</a-button>
<IViewConfirm
importance="normal"
title="确认删除该记录吗?"
@confirm="() => handleDeleteRecord(record)"
>
<a-button size="small" type="link" danger>删除</a-button>
</IViewConfirm>
</template>
</template>
</IViewTable>
</div>
</IViewTabPane>
<IViewTabPane key="detail" tab="详情 IViewDescriptions">
<div v-if="activeSection === 'detail'" class="demo-section">
<IViewDescriptions
:record-data="detailRecord"
:columns-list="detailColumns"
:column-size="2"
:hidden-label="false"
>
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'status'">
<a-tag :color="statusColor(record.status)">{{ statusLabel(record.status) }}</a-tag>
</template>
</template>
</IViewDescriptions>
</div>
</IViewTabPane>
<IViewTabPane key="layout" tab="页面 ILayoutPage">
<div v-if="activeSection === 'layout'" class="demo-section">
<a-alert
type="warning"
show-icon
message="ILayoutPage 需配置真实 API完整示例请参考「系统设置 → 管理员账号」页面。"
style="margin-bottom: 16px"
/>
<pre class="demo-code">{{ layoutPageExample }}</pre>
</div>
</IViewTabPane>
</IViewTabs>
<IViewDrawer :open="drawerOpen" title="订单详情" @close="drawerOpen = false">
<IViewDescriptions
v-if="currentRecord"
:record-data="currentRecord"
:columns-list="detailColumns"
:column-size="1"
:hidden-label="false"
>
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'status'">
<a-tag :color="statusColor(record.status)">{{ statusLabel(record.status) }}</a-tag>
</template>
</template>
</IViewDescriptions>
</IViewDrawer>
</div>
</template>
<script setup>
import { ref, computed } from "vue";
import { PlusOutlined } from "@ant-design/icons-vue";
import IViewTabs from "@/iview/IViewTabs.vue";
import IViewTabPane from "@/iview/IViewTabPane.vue";
import IViewForm from "@/iview/IViewForm.vue";
import IViewFilter from "@/iview/IViewFilter.vue";
import IViewTable from "@/iview/IViewTable.vue";
import IViewDescriptions from "@/iview/IViewDescriptions.vue";
import IViewConfirm from "@/iview/IViewConfirm.vue";
import IViewDrawer from "@/iview/IViewDrawer.vue";
import { showSuccessTips, showErrorTips } from "@/iview/utils/messageTips";
const activeSection = ref("form");
// ── 表单示例 ──────────────────────────────────────────
const formRef = ref(null);
const formReadOnly = ref(false);
const formResult = ref("");
const formData = ref({
name: "张三",
age: 28,
gender: "male",
tags: ["vip"],
city: "guangzhou",
birthday: "1998-05-20",
enabled: 1,
remark: "这是一段备注说明",
});
const formConfig = ref({
fields: [
{ type: "title", label: "基础信息" },
{
name: "name",
label: "姓名",
type: "text",
required: true,
maxlength: 20,
placeholder: "请输入姓名",
tips: "2~20 个字符",
},
{
name: "age",
label: "年龄",
type: "number",
required: true,
min: 1,
max: 120,
},
{
name: "gender",
label: "性别",
type: "radio",
required: true,
options: [
{ value: "male", label: "男" },
{ value: "female", label: "女" },
],
},
{
name: "tags",
label: "标签",
type: "checkbox",
options: [
{ value: "vip", label: "VIP" },
{ value: "new", label: "新用户" },
],
},
{
name: "city",
label: "城市",
type: "select",
required: true,
options: [
{ value: "guangzhou", label: "广州" },
{ value: "shenzhen", label: "深圳" },
{ value: "beijing", label: "北京" },
],
},
{
name: "birthday",
label: "生日",
type: "date",
},
{
name: "enabled",
label: "启用状态",
type: "boolean",
trueValue: 1,
falseValue: 0,
defaultValue: 1,
},
{
name: "remark",
label: "备注",
type: "textarea",
maxlength: 200,
textRows: 3,
},
],
});
const handleFormSubmit = async () => {
try {
await formRef.value.validate();
formResult.value = JSON.stringify(formData.value);
showSuccessTips("表单校验通过");
} catch (error) {
showErrorTips(error);
}
};
const handleFormReset = () => {
formRef.value?.resetFormData?.();
formResult.value = "";
};
// ── 列表示例 ──────────────────────────────────────────
const listLoading = ref(false);
const filterParams = ref({});
const drawerOpen = ref(false);
const currentRecord = ref(null);
const mockRecords = ref([
{ id: 1, orderNo: "ORD-20250605001", customer: "广州物流有限公司", amount: 1280.5, status: 1, createTime: "2025-06-05 09:30:00" },
{ id: 2, orderNo: "ORD-20250605002", customer: "深圳科技股份", amount: 5600, status: 2, createTime: "2025-06-05 10:15:00" },
{ id: 3, orderNo: "ORD-20250605003", customer: "北京贸易集团", amount: 890, status: 0, createTime: "2025-06-05 11:00:00" },
{ id: 4, orderNo: "ORD-20250604004", customer: "上海仓储中心", amount: 3200, status: 3, createTime: "2025-06-04 16:20:00" },
{ id: 5, orderNo: "ORD-20250604005", customer: "杭州电商公司", amount: 450, status: 1, createTime: "2025-06-04 18:45:00" },
]);
const filterConfig = ref({
fields: [
{
name: "keyword",
label: "关键词",
type: "text",
placeholder: "订单号 / 客户名称",
},
{
name: "status",
label: "状态",
type: "select",
options: [
{ value: 0, label: "待处理" },
{ value: 1, label: "进行中" },
{ value: 2, label: "已完成" },
{ value: 3, label: "已取消" },
],
},
{
name: "createTime",
label: "创建日期",
type: "date",
advanced: true,
},
],
});
const listColumns = ref([
{ title: "订单号", dataIndex: "orderNo", width: 160 },
{ title: "客户", dataIndex: "customer", ellipsis: true },
{ title: "金额", dataIndex: "amount", width: 100, align: "right" },
{ title: "状态", dataIndex: "status", width: 90, bodySlot: true },
{ title: "创建时间", dataIndex: "createTime", width: 170 },
{ title: "操作", dataIndex: "action", width: 130, bodySlot: true, fixed: "right" },
]);
const filteredList = computed(() => {
let rows = [...mockRecords.value];
const { keyword, status } = filterParams.value;
if (keyword) {
const kw = String(keyword).trim().toLowerCase();
rows = rows.filter(
(r) =>
r.orderNo.toLowerCase().includes(kw) ||
r.customer.toLowerCase().includes(kw)
);
}
if (status !== undefined && status !== null && status !== "") {
rows = rows.filter((r) => r.status === Number(status));
}
return rows;
});
const tablePagination = computed(() => ({
current: paginationState.value.current,
pageSize: paginationState.value.pageSize,
total: filteredList.value.length,
showTotal: (total) => `${total}`,
}));
const paginationState = ref({
current: 1,
pageSize: 10,
});
const statusLabel = (status) => {
const map = { 0: "待处理", 1: "进行中", 2: "已完成", 3: "已取消" };
return map[status] ?? "未知";
};
const statusColor = (status) => {
const map = { 0: "default", 1: "processing", 2: "success", 3: "error" };
return map[status] ?? "default";
};
const handleFilterSearch = () => {
paginationState.value.current = 1;
};
const handleFilterReset = () => {
filterParams.value = {};
paginationState.value.current = 1;
};
const handleTableChange = (pagination) => {
paginationState.value.current = pagination.current;
paginationState.value.pageSize = pagination.pageSize;
};
const handleViewRecord = (record) => {
currentRecord.value = record;
drawerOpen.value = true;
};
const handleDeleteRecord = (record) => {
mockRecords.value = mockRecords.value.filter((r) => r.id !== record.id);
showSuccessTips(`已删除 ${record.orderNo}`);
};
const handleAddRecord = () => {
const id = mockRecords.value.length + 1;
mockRecords.value.unshift({
id,
orderNo: `ORD-202506050${String(id).padStart(2, "0")}`,
customer: "新客户示例",
amount: 999,
status: 0,
createTime: "2025-06-05 12:00:00",
});
showSuccessTips("已添加一条示例记录");
};
// ── 详情示例 ──────────────────────────────────────────
const detailRecord = ref({
orderNo: "ORD-20250605001",
customer: "广州物流有限公司",
amount: 1280.5,
status: 1,
createTime: "2025-06-05 09:30:00",
remark: "优先配送,请联系收货人确认时间。",
});
const detailColumns = ref([
{ title: "订单号", dataIndex: "orderNo" },
{ title: "客户", dataIndex: "customer" },
{ title: "金额", dataIndex: "amount" },
{ title: "状态", dataIndex: "status", bodySlot: true },
{ title: "创建时间", dataIndex: "createTime" },
{ title: "备注", dataIndex: "remark", span: 2 },
]);
// ── ILayoutPage 配置示例 ──────────────────────────────
const layoutPageExample = `const config = ref({
listPages: [{
title: "列表标题",
name: "recordList",
api: "api.xxx.list", // 列表接口
rowKey: "guid",
isDefault: true,
showFilter: true,
pagination: { pageSize: 10 },
columns: [/* 列配置 */],
filters: { fields: [/* 筛选项 */] },
}],
formPages: [{
name: "create",
title: "新增",
submitApi: "api.xxx.create",
formConfig: { fields: [/* 表单字段 */] },
}, {
name: "update",
title: "编辑",
paramsKey: ["guid"],
recordApi: "api.xxx.detail",
submitApi: "api.xxx.update",
formConfig: { fields: [/* 表单字段 */] },
}],
detailPages: [{
name: "detail",
title: "详情",
paramsKey: ["guid"],
recordApi: "api.xxx.detail",
columns: [/* 详情字段 */],
}],
});
// 模板中使用
<ILayoutPage ref="pageRef" :config="config">
<template #listActions="{ refresh }">
<a-button type="primary" @click="pageRef.showFormPage('create')">添加</a-button>
</template>
<template #bodyCell="{ column, record }">
<!-- 自定义列渲染 -->
</template>
</ILayoutPage>`;
</script>
<style scoped>
.demo-page {
width: 100%;
background: #fff;
}
.demo-intro {
margin-bottom: 16px;
color: rgba(0, 0, 0, 0.65);
font-size: 13px;
line-height: 1.6;
}
.demo-intro code {
padding: 2px 6px;
background: #f5f5f5;
border-radius: 4px;
font-size: 12px;
}
.demo-section {
padding: 4px 0 16px;
}
.demo-actions {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 16px;
}
.demo-list-header {
display: flex;
justify-content: space-between;
align-items: center;
margin: 16px 0;
flex-wrap: wrap;
gap: 10px;
}
.demo-list-title {
color: rgba(0, 0, 0, 0.45);
font-size: 14px;
}
.demo-code {
margin: 0;
padding: 16px;
background: #fafafa;
border: 1px solid #f0f0f0;
border-radius: 6px;
font-size: 12px;
line-height: 1.6;
overflow-x: auto;
white-space: pre-wrap;
word-break: break-all;
color: #333;
}
</style>