forked from tools/tape-springboot-sysadmin
init
This commit is contained in:
491
src/views/business/IndexDemo.vue
Normal file
491
src/views/business/IndexDemo.vue
Normal 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>
|
||||
Reference in New Issue
Block a user