当前位置: 首页 > news >正文

FastbuildAI新建套餐-前端代码分析

1. 功能概述

FastbuildAI的"新建套餐"功能是充值管理模块的核心功能,允许管理员创建和管理用户充值套餐。该功能位于用户管理菜单下的充值管理页面,提供了完整的套餐配置界面。

1.1 业务流程

  1. 管理员登录: 使用管理员账号登录FastbuildAI后台管理系统
  2. 导航到充值管理: 点击"用户管理" → "充值管理"菜单
  3. 新建套餐: 点击"新建套餐"按钮添加新的充值规则
  4. 配置套餐信息: 输入充值金额、赠送电力值、售价、标签等信息
  5. 保存套餐: 点击右下角"保存"按钮提交配置

1.2 功能特性

  • 动态表格管理: 支持动态添加和删除充值套餐行
  • 实时数据验证: 表单字段实时验证和错误提示
  • 权限控制: 基于用户权限控制功能访问
  • 多语言支持: 完整的国际化文本配置
  • 状态管理: 智能检测数据变更状态

2. 页面路由与菜单结构

2.1 菜单配置

前端配置文件: apps/web/core/i18n/zh/console-menu.json

{"userManagement": {"title": "用户管理","userList": "用户列表","userInfo": "用户信息","userRecharge": "充值管理"}
}

后端菜单配置文件: apps/server/src/core/database/install/menu.json

{"name": "console-menu.userManagement.userRecharge","code": "user-user-recharge","path": "user-recharge","icon": "","component": "/console/user/user-recharge/index","permissionCode": "recharge-config:getConfig","sort": 100,"isHidden": 0,"type": 2,"sourceType": 1,"pluginPackName": null,"children": [{"name": "console-common.save","code": "user-user-recharge-save","path": "","icon": "","component": "","permissionCode": "recharge-config:setConfig","sort": 0,"isHidden": 1,"type": 2,"sourceType": 1,"pluginPackName": null}]
}

2.2 路由结构

基于Nuxt.js的文件系统路由,充值管理页面的路由结构:

apps/web/app/console/user/user-recharge/
├── index.vue                 # 充值管理主页面

访问路径: /console/user/user-recharge

2.3 菜单层级

控制台首页
└── 用户管理 (userManagement)├── 用户列表 (userList)├── 用户信息 (userInfo)└── 充值管理 (userRecharge) ← 目标页面

3. 核心组件分析

3.1 主组件结构

文件位置: apps/web/app/console/user/user-recharge/index.vue

这是一个完整的Vue 3 Composition API组件,使用TypeScript和Nuxt UI组件库构建。

3.1.1 Script Setup部分
<script setup lang="ts">
import { useMessage } from "@fastbuildai/ui";
import type { TableColumn } from "@nuxt/ui";
import { useI18n } from "vue-i18n";import type { RechargeConfigData, RechargeRule } from "@/models/package-management";
import { apiGetRechargeRules, saveRechargeRules } from "@/services/console/package-management";const { t } = useI18n();
const toast = useMessage();// 响应式数据状态
const rechargeStatus = ref(true);
const changeValue = ref(false);
const rechargeRules = ref<RechargeRule[]>([]);
const rechargeExplain = ref("");// 表格列配置
const columns: TableColumn<RechargeRule>[] = [{id: "move",header: "#",size: 40,enableSorting: false,enableHiding: false,},{id: "rechargeValue",accessorKey: "rechargeValue",header: t("console-marketing.packageManagement.tab.rechargeValue"),},{id: "freeQuantity",accessorKey: "freeQuantity",header: t("console-marketing.packageManagement.tab.freeQuantity"),},{id: "price",accessorKey: "price",header: t("console-marketing.packageManagement.tab.price"),},{id: "label",accessorKey: "label",header: t("console-marketing.packageManagement.tab.label"),},{id: "action",header: t("console-marketing.packageManagement.tab.action"),size: 40,enableSorting: false,enableHiding: false,},
];const oldData = ref<RechargeConfigData>();// 获取充值规则数据
const getRechargeRules = async () => {const data = await apiGetRechargeRules();oldData.value = data;rechargeRules.value = data.rechargeRule.map((item) => ({ ...item }));rechargeStatus.value = data.rechargeStatus;rechargeExplain.value = data.rechargeExplain;
};// 添加新的充值套餐行
const addRow = () => {const newRow = ref<RechargeRule>({givePower: 0,label: "",power: 0,sellPrice: 0,});rechargeRules.value.push(newRow.value);
};// 删除充值套餐行
const deleteRow = (row: RechargeRule) => {rechargeRules.value = rechargeRules.value.filter((item) => item !== row);
};// 保存充值规则配置
const saveRules = async () => {try {await saveRechargeRules({rechargeRule: rechargeRules.value,rechargeStatus: rechargeStatus.value,rechargeExplain: rechargeExplain.value,});getRechargeRules();toast.success(t("console-marketing.packageManagement.saveSuccess"));} catch (error) {console.error(error);}
};watch(rechargeStatus, () => {if (rechargeStatus.value !== oldData.value?.rechargeStatus) {changeValue.value = true;} else {changeValue.value = false;}
});watch(rechargeExplain, () => {if (rechargeExplain.value !== oldData.value?.rechargeExplain) {changeValue.value = true;} else {changeValue.value = false;}
});// 判断充值规则是否变化
const isEqual = (arr1: RechargeRule[], arr2: RechargeRule[] | undefined) => {if (!arr2) return false;if (arr1.length !== arr2.length) return false;return arr1.every((item, index) => {if (item?.power !== arr2[index]?.power ||item?.givePower !== arr2[index]?.givePower ||item?.sellPrice !== arr2[index]?.sellPrice ||item?.label !== arr2[index]?.label) {return false;} else {return true;}});
};watch(rechargeRules,() => {if (!isEqual(rechargeRules.value, oldData.value?.rechargeRule)) {changeValue.value = true;} else {changeValue.value = false;}},{ deep: true },
);onMounted(() => {getRechargeRules();
});
</script>
3.1.2 Template部分
<template><div class="my-px space-y-4 pb-6"><div class="flex flex-col gap-6"><!-- 功能状态开关 --><div class=""><div><div class="mb-4 flex flex-col gap-1"><div class="text-secondary-foreground text-md font-bold">{{ t("console-marketing.packageManagement.statusTitle") }}</div><div class="text-muted-foreground text-xs">{{ t("console-marketing.packageManagement.statusDescription") }}</div></div><USwitch v-model="rechargeStatus" /></div></div><!-- 充值说明配置 --><div v-if="rechargeStatus"><div class="mb-4 flex flex-col gap-1"><div class="text-secondary-foreground text-md font-bold">{{ t("console-marketing.packageManagement.rechargeInstructionsTitle") }}</div><div class="text-muted-foreground text-xs">{{ t("console-marketing.packageManagement.rechargeInstructionsDescription") }}</div></div><div class="w-full text-sm"><UTextareaclass="w-full"v-model="rechargeExplain":rows="6"placeholder="请输入套餐充值说明..."/></div></div><!-- 充值规则表格 --><div class="flex-1"><div class="flex w-full items-center justify-between"><div class="text-secondary-foreground text-md font-bold">{{ t("console-marketing.packageManagement.rechargeRulesTitle") }}</div><div class="flex items-center justify-between gap-2 px-4"><UButtoncolor="primary"variant="outline"icon="tabler:plus":ui="{ leadingIcon: 'size-4' }"@click="addRow">{{ t("console-marketing.packageManagement.button.new") }}</UButton></div></div><!-- 数据表格 --><div class="mt-4"><UTableref="table":data="rechargeRules":columns="columns":ui="{base: 'table-fixed border-separate border-spacing-0',thead: '[&>tr]:bg-elevated/50 [&>tr]:after:content-none',tbody: '[&>tr]:last:[&>td]:border-b-0',th: 'py-2 first:rounded-l-lg last:rounded-r-lg border-y border-default first:border-l last:border-r',td: 'border-b border-default',tr: '[&:has(>td[colspan])]:hidden',}"><!-- 序号列 --><template #move-cell="{ row }">{{ row.index + 1 }}</template><!-- 充值数量输入 --><template #rechargeValue-cell="{ row }"><UInput v-model="row.original.power" type="number" /></template><!-- 赠送数量输入 --><template #freeQuantity-cell="{ row }"><UInput v-model="row.original.givePower" type="number" /></template><!-- 价格输入(带单位) --><template #price-cell="{ row }"><UInputv-model="row.original.sellPrice"type="number"min="0"step="0.01":ui="{trailing: 'bg-muted-foreground/15 pl-2 rounded-tr-lg rounded-br-lg',}"><template #trailing><span>{{ t("console-marketing.packageManagement.tab.priceUnit") }}</span></template></UInput></template><!-- 标签输入 --><template #label-cell="{ row }"><UInput v-model="row.original.label" /></template><!-- 操作按钮 --><template #action-cell="{ row }"><UButtonicon="tabler:trash"color="error"variant="ghost"@click="deleteRow(row.original)"/></template></UTable></div></div><!-- 保存按钮 --><div class="flex justify-end"><AccessControl :codes="['recharge-config:setConfig']"><UButtoncolor="primary":disabled="!changeValue":ui="{ base: 'w-16 flex justify-center items-center' }"@click="saveRules">{{ t("console-marketing.packageManagement.button.save") }}</UButton></AccessControl></div></div></div>
</template>

3.2 数据模型定义

文件位置: apps/web/models/package-management.d.ts

/*** 套餐充值配置响应接口*/
export interface RechargeConfigData {/*** 充值说明*/rechargeExplain: string;/*** 充值规则*/rechargeRule: RechargeRule[];/*** 充值开关:true-开启;false-关闭*/rechargeStatus: boolean;
}/*** 充值规则接口*/
export interface RechargeRule {/*** 赠送数量*/givePower: number;/*** 规则ID(可选)*/id?: string;/*** 标签*/label: string;/*** 充值数量*/power: number;/*** 售价*/sellPrice: string | number;
}

3.3 API接口服务

文件位置: apps/web/services/console/package-management.ts

// ==================== 套餐管理相关 API ====================import type { RechargeConfigData } from "@/models/package-management";/*** 获取套餐充值配置*/
export const apiGetRechargeRules = (): Promise<RechargeConfigData> => {return useConsoleGet("/recharge-config");
};/*** 保存套餐充值配置*/
export const saveRechargeRules = (data: RechargeConfigData): Promise<void> => {return useConsolePost("/recharge-config", data);
};

4. 用户交互流程详解

4.1 页面初始化流程

页面加载
组件挂载 onMounted
调用 getRechargeRules API
获取服务器数据
更新响应式状态
备份原始数据 oldData
渲染页面内容
用户可以开始操作

4.2 新建套餐流程

用户点击新建套餐按钮
调用 addRow 方法
创建新的 RechargeRule 对象
添加到 rechargeRules 数组
触发响应式更新
表格自动渲染新行
用户可以编辑新行数据

4.3 数据保存流程

用户修改数据
触发 watch 监听
检测数据变更
数据是否变更?
启用保存按钮
禁用保存按钮
用户点击保存
调用 saveRules 方法
发送 API 请求
保存成功?
显示成功提示
显示错误信息
重新获取数据
重置变更状态

4.4 表单验证机制

组件实现了多层次的数据验证:

  1. 输入类型验证: 使用 type="number" 确保数值输入
  2. 最小值限制: 价格字段设置 min="0" 防止负数
  3. 精度控制: 价格字段使用 step="0.01" 支持小数
  4. 深度比较: 使用 isEqual 函数精确检测数据变更

4.5 错误处理和用户反馈

// 保存操作的错误处理
const saveRules = async () => {try {await saveRechargeRules({rechargeRule: rechargeRules.value,rechargeStatus: rechargeStatus.value,rechargeExplain: rechargeExplain.value,});getRechargeRules();toast.success(t("console-marketing.packageManagement.saveSuccess"));} catch (error) {console.error(error);// 这里可以添加错误提示toast.error(t("console-marketing.packageManagement.saveFailed"));}
};

5. UI组件详解

5.1 USwitch 开关组件

<USwitch v-model="rechargeStatus" />

功能: 控制充值功能的启用/禁用状态
特点:

  • 双向数据绑定
  • 响应式状态更新
  • 自动触发变更检测

5.2 UTextarea 文本域组件

<UTextareaclass="w-full"v-model="rechargeExplain":rows="6"placeholder="请输入套餐充值说明..."
/>

功能: 输入充值说明文本
特点:

  • 多行文本输入
  • 固定行数显示
  • 占位符提示

5.3 UTable 表格组件

表格组件是页面的核心,具有以下特性:

5.3.1 表格配置
const columns: TableColumn<RechargeRule>[] = [{id: "move",header: "#",size: 40,enableSorting: false,enableHiding: false,},// ... 其他列配置
];
5.3.2 自定义单元格模板
<!-- 价格输入单元格 -->
<template #price-cell="{ row }"><UInputv-model="row.original.sellPrice"type="number"min="0"step="0.01":ui="{trailing: 'bg-muted-foreground/15 pl-2 rounded-tr-lg rounded-br-lg',}"><template #trailing><span>{{ t("console-marketing.packageManagement.tab.priceUnit") }}</span></template></UInput>
</template>

5.4 UInput 输入组件

支持多种输入类型:

  1. 数值输入: type="number"
  2. 文本输入: 默认类型
  3. 带单位显示: 使用 trailing 插槽

5.5 UButton 按钮组件

<!-- 新建套餐按钮 -->
<UButtoncolor="primary"variant="outline"icon="tabler:plus":ui="{ leadingIcon: 'size-4' }"@click="addRow"
>{{ t("console-marketing.packageManagement.button.new") }}
</UButton><!-- 删除按钮 -->
<UButtonicon="tabler:trash"color="error"variant="ghost"@click="deleteRow(row.original)"
/><!-- 保存按钮 -->
<UButtoncolor="primary":disabled="!changeValue":ui="{ base: 'w-16 flex justify-center items-center' }"@click="saveRules"
>{{ t("console-marketing.packageManagement.button.save") }}
</UButton>

6. 权限控制机制

6.1 AccessControl 组件

文件位置: common/components/access-control.vue

<AccessControl :codes="['recharge-config:setConfig']"><UButtoncolor="primary":disabled="!changeValue"@click="saveRules">{{ t("console-marketing.packageManagement.button.save") }}</UButton>
</AccessControl>

权限控制逻辑:

  1. 检查用户权限数组中是否包含指定权限码
  2. Root用户拥有所有权限
  3. 权限不足时隐藏或禁用相关功能

6.2 权限码说明

  • recharge-config:setConfig: 充值配置设置权限
  • 只有拥有此权限的用户才能看到保存按钮
  • 确保数据安全和操作权限控制

7. 国际化支持

7.1 文本配置文件

中文配置 (core/i18n/zh/console-marketing.json):

{"packageManagement": {"rechargeInstructionsTitle": "充值说明","saveSuccess": "保存成功","saveFailed": "保存失败","statusTitle": "功能状态","statusDescription": "启用后用户可以访问充值功能","rechargeRulesTitle": "充值规则","tab": {"rechargeValue": "充值数量","freeQuantity": "赠送数量","price": "价格","label": "标签","action": "操作","priceUnit": "元"},"button": {"save": "保存","new": "新建套餐"}}
}

英文配置 (core/i18n/en/console-marketing.json):

{"packageManagement": {"rechargeInstructionsTitle": "Recharge Policy","saveSuccess": "Saved","saveFailed": "Save failed","statusTitle": "Feature Status","statusDescription": "Enable for user access to recharge","rechargeRulesTitle": "Recharge Rules","tab": {"rechargeValue": "Amount","freeQuantity": "Bonus","price": "Price","label": "Label","action": "Actions","priceUnit": "¥"},"button": {"save": "Save","new": "New Package"}}
}

7.2 使用方式

// 在组件中使用国际化
const { t } = useI18n();// 获取翻译文本
const title = t("console-marketing.packageManagement.rechargeInstructionsTitle");

支持的语言:

  • 中文 (zh)
  • 英文 (en)
  • 日文 (jp)

8. 状态管理与数据流

8.1 响应式状态变量

// 核心状态变量
const rechargeStatus = ref(true);           // 充值功能开关
const changeValue = ref(false);             // 数据变更标志
const rechargeRules = ref<RechargeRule[]>([]);  // 充值规则数组
const rechargeExplain = ref("");            // 充值说明文本
const oldData = ref<RechargeConfigData>();  // 原始数据备份

8.2 数据变更监听

8.2.1 简单值监听
// 监听充值状态变更
watch(rechargeStatus, () => {if (rechargeStatus.value !== oldData.value?.rechargeStatus) {changeValue.value = true;} else {changeValue.value = false;}
});// 监听充值说明变更
watch(rechargeExplain, () => {if (rechargeExplain.value !== oldData.value?.rechargeExplain) {changeValue.value = true;} else {changeValue.value = false;}
});
8.2.2 深度对象监听
// 深度比较函数
const isEqual = (arr1: RechargeRule[], arr2: RechargeRule[] | undefined) => {if (!arr2) return false;if (arr1.length !== arr2.length) return false;return arr1.every((item, index) => {if (item?.power !== arr2[index]?.power ||item?.givePower !== arr2[index]?.givePower ||item?.sellPrice !== arr2[index]?.sellPrice ||item?.label !== arr2[index]?.label) {return false;} else {return true;}});
};// 深度监听充值规则数组
watch(rechargeRules,() => {if (!isEqual(rechargeRules.value, oldData.value?.rechargeRule)) {changeValue.value = true;} else {changeValue.value = false;}},{ deep: true },
);

8.3 数据流向图

API数据
oldData备份
响应式状态
用户界面
用户操作
状态更新
Watch监听
变更检测
UI反馈
保存操作
API调用

8.4 生命周期管理

// 组件挂载时初始化数据
onMounted(() => {getRechargeRules();
});// 数据获取函数
const getRechargeRules = async () => {const data = await apiGetRechargeRules();oldData.value = data;  // 备份原始数据rechargeRules.value = data.rechargeRule.map((item) => ({ ...item }));  // 深拷贝rechargeStatus.value = data.rechargeStatus;rechargeExplain.value = data.rechargeExplain;
};

9. 表单验证与用户交互

9.1 输入验证机制

9.1.1 数值输入验证
<!-- 充值数量输入 -->
<UInput v-model="row.original.power" type="number" /><!-- 赠送数量输入 -->
<UInput v-model="row.original.givePower" type="number" /><!-- 价格输入(带最小值和步长限制) -->
<UInputv-model="row.original.sellPrice"type="number"min="0"step="0.01"
/>

验证特性:

  • type="number": 限制只能输入数字
  • min="0": 防止输入负数
  • step="0.01": 支持小数点后两位
9.1.2 实时验证反馈
// 数据变更时实时检测
watch(rechargeRules, () => {if (!isEqual(rechargeRules.value, oldData.value?.rechargeRule)) {changeValue.value = true;  // 启用保存按钮} else {changeValue.value = false; // 禁用保存按钮}
}, { deep: true });

9.2 用户反馈机制

9.2.1 成功反馈
// 保存成功提示
toast.success(t("console-marketing.packageManagement.saveSuccess"));
9.2.2 错误处理
try {await saveRechargeRules(data);// 成功处理
} catch (error) {console.error(error);// 错误处理
}
9.2.3 按钮状态控制
<UButtoncolor="primary":disabled="!changeValue"  <!-- 根据数据变更状态控制按钮可用性 -->@click="saveRules"
>{{ t("console-marketing.packageManagement.button.save") }}
</UButton>

9.3 改进建议

9.3.1 删除确认对话框
// 建议使用模态确认对话框
const deleteRow = async (row: RechargeRule) => {const confirmed = await useModal().confirm({title: "确认删除",content: "确定要删除这个充值套餐吗?此操作不可撤销。",confirmText: "删除",cancelText: "取消"});if (confirmed) {rechargeRules.value = rechargeRules.value.filter((item) => item !== row);}
};
9.3.2 表单验证增强
// 可以添加更严格的验证规则
const validateRule = (rule: RechargeRule): boolean => {if (rule.power <= 0) {toast.error("充值数量必须大于0");return false;}if (rule.sellPrice <= 0) {toast.error("售价必须大于0");return false;}if (!rule.label.trim()) {toast.error("标签不能为空");return false;}return true;
};

10. 技术架构总结

10.1 技术栈

  • 前端框架: Vue 3 + Nuxt.js
  • UI组件库: Nuxt UI (基于Tailwind CSS)
  • 状态管理: Vue 3 Composition API + Pinia
  • 类型系统: TypeScript
  • 国际化: Vue I18n
  • HTTP客户端: Nuxt内置的$fetch
  • 权限控制: 自定义AccessControl组件

10.2 架构特点

10.2.1 组件化设计
  • 单文件组件: 使用Vue SFC格式,逻辑、模板、样式集中管理
  • 组合式API: 采用Composition API提高代码复用性
  • 类型安全: 全面使用TypeScript确保类型安全
10.2.2 响应式数据流
  • 双向绑定: 表单数据与状态自动同步
  • 深度监听: 复杂对象变更的精确检测
  • 状态管理: 清晰的数据流向和状态变更
10.2.3 用户体验优化
  • 实时反馈: 数据变更即时反映在UI上
  • 权限控制: 基于用户权限的功能访问控制
  • 国际化: 完整的多语言支持
10.2.4 可维护性
  • 模块化: 清晰的文件组织和模块划分
  • 类型定义: 完整的TypeScript类型定义
  • 代码复用: 通用组件和工具函数的抽象

10.3 设计模式

10.3.1 MVVM模式
View (Template) ↔ ViewModel (Script) ↔ Model (API/Store)
10.3.2 组件通信
  • Props Down: 父组件向子组件传递数据
  • Events Up: 子组件向父组件发送事件
  • Provide/Inject: 跨层级组件通信
10.3.3 状态管理模式
State → View → Action → State

10.4 性能优化

10.4.1 响应式优化
  • ref vs reactive: 合理选择响应式API
  • 深度监听: 仅在必要时使用deep watch
  • 计算属性: 缓存复杂计算结果
10.4.2 组件优化
  • 懒加载: 按需加载组件和模块
  • 虚拟滚动: 大数据量表格的性能优化
  • 防抖节流: 用户输入的性能优化

10.5 安全性考虑

10.5.1 权限控制
  • 前端权限: AccessControl组件控制UI显示
  • 后端验证: API层面的权限验证
  • 角色管理: 基于角色的访问控制
10.5.2 数据验证
  • 客户端验证: 表单数据的前端验证
  • 服务端验证: API接口的后端验证
  • 类型安全: TypeScript类型检查

10.6 扩展性设计

10.6.1 组件扩展
  • 插槽机制: 支持内容自定义
  • 属性配置: 灵活的组件配置
  • 事件系统: 完整的事件通信
10.6.2 功能扩展
  • 模块化: 新功能模块的独立开发
  • 插件系统: 支持第三方插件扩展
  • 配置化: 通过配置文件控制功能

FastbuildAI的新建套餐功能展现了现代Vue.js应用的最佳实践,通过Vue 3 + Nuxt.js + TypeScript的技术组合,实现了一个功能完善、用户体验优秀、可维护强劲的前端管理界面。该实现不仅满足了当前的业务需求,也为未来的功能扩展提供了良好的技术基础。

http://www.dtcms.com/a/492168.html

相关文章:

  • 网站建好了还需要什么维护扬中网站推广托管
  • [Sora] 集成 | 封装-调用-推理 | `prepare_api`与`api_fn`
  • 新一代Java应用日志可视化与监控系统开源啦
  • 网站做镜像是什么房产律师网站模板
  • 汕头网站优化系统wordpress格行代码
  • 抓取源ip的包
  • 北京手机版网站制作个人博客主页登录
  • php企业网站程序做网站分层技术
  • 网站建立的链接不安全怎么解决p2p网站制作价格
  • Python 3.14 安装教程:新手友好版
  • SQL 日期处理指南
  • 网站建设备案查询上海建筑网站建设
  • [c++语法学习]Day11:c++面向对象 1
  • 网站建设报价表格江门微信网站建设
  • 工业协议:Profinet栈开发,实时通信实现?
  • 东莞部门网站建设装饰网站建设重要性
  • 如何在linux上做Java基准测试工具JMH测试(2)
  • 毕业设计网站最容易做什莫类型wordpress社区
  • YOLOV1与YOLOV2
  • 什么是python中的functools.partial
  • 旅游网站的市场需求怎么做介绍asp网站后台管理系统密码破解
  • 做网站公司 陕西渭南网站建设上机课
  • 苍穹外卖-购物车部分
  • 《深入浅出数据分析》笔记
  • Docker 完整指南:从入门到企业实战
  • LLM入门笔记:注意力机制与输出预测
  • 网站开发网站开发设计网站建设收费明细
  • 西南能矿建设工程公司网站贵阳网站建设-中国互联
  • 网站建设策划书封面网站做seo有什么作用
  • 网站建设前需求调研表知名网站建设定制