鸿蒙开发-材料清单

0 阅读5分钟

锻造材料清单怎么管理?HarmonyOS数据管理与清单计算

如果你对金属锻造感兴趣,可以去鸿蒙应用市场搜一下**「锻艺册」**,下载下来体验体验。管理金属材料、工具清单、计算用量,一套流程走下来对锻造项目的材料管理会有更直观的理解。体验完了再回来看这篇文章,你会更清楚这些材料数据是怎么管理的。


写在前面

大家好,我是一名写了十多年Web前端的老兵。从jQuery时代一路走到React/Vue,CSS3动画、requestAnimationFrame、Web Animation API这些都算是看家本领。去年开始转战鸿蒙生态,用ArkTS开发App,这一路踩了不少坑,也积累了不少心得。

很多人觉得"前端转鸿蒙"应该很容易——都是写UI嘛,组件化、状态管理、生命周期,概念都差不多。但真正上手之后你会发现,相似的地方让你觉得亲切,不同的地方让你抓狂

比如:

  • 材料数据管理:金属类型、工具种类繁多,需要分类管理。
  • 清单计算:根据项目需求自动计算材料用量。

别担心,接下来这篇文章,我会用"锻艺册"的材料清单功能,带你看看怎么在HarmonyOS里管理锻造材料数据。


这篇文章聊什么

锻艺册的材料清单功能,核心要解决:

  1. 金属材料管理:各种金属类型的属性和用途
  2. 工具清单:项目需要的工具列表
  3. 用量计算:根据项目尺寸计算材料用量
  4. 清单导出:生成购物清单

第一步:设计材料数据结构

// 金属类型
interface MetalType {
  id: string;
  name: string;
  symbol: string;
  color: string;
  hardness: number;
  meltingPoint: number;
  description: string;
  price: number; // 每克价格
}

// 工具
interface Tool {
  id: string;
  name: string;
  category: string;
  description: string;
  required: boolean;
}

// 材料清单项
interface MaterialItem {
  type: 'metal' | 'tool' | 'consumable';
  itemId: string;
  name: string;
  quantity: number;
  unit: string;
  notes: string;
}

// 金属类型定义
const METAL_TYPES: MetalType[] = [
  { id: 'silver', name: '纯银', symbol: 'Ag', color: '#c0c0c0', hardness: 2.5, meltingPoint: 962, description: '最常用的首饰金属', price: 5.5 },
  { id: 'copper', name: '红铜', symbol: 'Cu', color: '#b87333', hardness: 3, meltingPoint: 1085, description: '色泽温暖,易加工', price: 0.05 },
  { id: 'brass', name: '黄铜', symbol: 'CuZn', color: '#d4a937', hardness: 3.5, meltingPoint: 930, description: '金黄色,价格实惠', price: 0.03 },
  { id: 'gold', name: '黄金', symbol: 'Au', color: '#ffd700', hardness: 2.5, meltingPoint: 1064, description: '贵金属,永不褪色', price: 400 },
  { id: 'bronze', name: '青铜', symbol: 'CuSn', color: '#8c7853', hardness: 3, meltingPoint: 950, description: '古典质感,硬度适中', price: 0.04 },
  { id: 'steel', name: '不锈钢', symbol: 'Fe', color: '#a8a8a8', hardness: 5, meltingPoint: 1500, description: '坚硬耐用,不易氧化', price: 0.02 },
];

// 工具定义
const TOOLS: Tool[] = [
  { id: 'hammer', name: '锻造锤', category: 'forging', description: '基本成型工具', required: true },
  { id: 'anvil', name: '铁砧', category: 'forging', description: '锤打支撑台面', required: true },
  { id: 'torch', name: '焊枪', category: 'heating', description: '退火焊接热源', required: true },
  { id: 'pliers', name: '钳子', category: 'holding', description: '夹持弯折金属', required: true },
  { id: 'file_set', name: '锉刀组', category: 'finishing', description: '锉修整形', required: true },
  { id: 'sandpaper', name: '砂纸', category: 'finishing', description: '打磨表面', required: true },
  { id: 'polishing', name: '抛光机', category: 'finishing', description: '表面抛光', required: false },
  { id: 'saw', name: '锯弓', category: 'cutting', description: '切割金属片', required: true },
  { id: 'mandrel', name: '戒指芯棒', category: 'forming', description: '戒指成型工具', required: false },
  { id: 'bezel_pusher', name: '镶嵌推杆', category: 'setting', description: '镶嵌宝石用', required: false },
  { id: 'pickle_pot', name: '酸洗锅', category: 'cleaning', description: '去除氧化层', required: false },
  { id: 'measuring', name: '卡尺', category: 'measuring', description: '精确测量尺寸', required: true },
];

第二步:实现材料清单管理

// 计算金属用量
function calculateMetalUsage(
  metalType: string,
  dimensions: { width: number; height: number; depth: number },
  thickness: number
): { weight: number; volume: number; cost: number } {
  const metal = METAL_TYPES.find(m => m.id === metalType);
  if (!metal) return { weight: 0, volume: 0, cost: 0 };

  // 体积(立方毫米)
  const volume = dimensions.width * dimensions.height * thickness;

  // 重量(克)- 假设密度为金属的典型密度
  const densities: Record<string, number> = {
    'silver': 10.49,
    'copper': 8.96,
    'brass': 8.5,
    'gold': 19.32,
    'bronze': 8.8,
    'steel': 7.85
  };
  const density = densities[metalType] || 8.0;
  const weight = (volume / 1000) * density; // 转换为克

  // 成本
  const cost = weight * metal.price;

  return { weight: Math.round(weight * 10) / 10, volume, cost: Math.round(cost * 100) / 100 };
}

// 生成材料清单
function generateMaterialList(
  project: ForgingProject,
  dimensions: { width: number; height: number; depth: number }
): MaterialItem[] {
  const items: MaterialItem[] = [];

  // 金属材料
  const metalUsage = calculateMetalUsage(project.metalType, dimensions, 2);
  items.push({
    type: 'metal',
    itemId: project.metalType,
    name: METAL_TYPES.find(m => m.id === project.metalType)?.name || '',
    quantity: metalUsage.weight,
    unit: '克',
    notes: `预计成本: ¥${metalUsage.cost}`
  });

  // 必需工具
  TOOLS.filter(t => t.required).forEach(tool => {
    items.push({
      type: 'tool',
      itemId: tool.id,
      name: tool.name,
      quantity: 1,
      unit: '个',
      notes: tool.description
    });
  });

  // 消耗品
  items.push(
    { type: 'consumable', itemId: 'sandpaper', name: '砂纸', quantity: 5, unit: '张', notes: '多种目数' },
    { type: 'consumable', itemId: 'flux', name: '焊药', quantity: 1, unit: '瓶', notes: '' },
    { type: 'consumable', itemId: 'pickle', name: '酸洗液', quantity: 1, unit: '瓶', notes: '稀硫酸' }
  );

  return items;
}

第三步:实现材料清单页面

@Entry
@Component
struct MaterialListPage {
  @State materialItems: MaterialItem[] = []
  @State totalCost: number = 0

  async aboutToAppear() {
    // 生成材料清单
    const projects = await getProjects(getContext(this) as Context);
    if (projects.length > 0) {
      this.materialItems = generateMaterialList(projects[0], { width: 50, height: 20, depth: 5 });
      this.totalCost = this.materialItems
        .filter(item => item.type === 'metal')
        .reduce((sum, item) => {
          const costMatch = item.notes.match(/¥(\d+\.?\d*)/);
          return sum + (costMatch ? parseFloat(costMatch[1]) : 0);
        }, 0);
    }
  }

  build() {
    Column() {
      Text('材料清单')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 16)

      // 总成本
      Row() {
        Text('预计总成本')
          .fontSize(14)
          .fontColor('#6b7280')
        Text(${this.totalCost.toFixed(2)}`)
          .fontSize(20)
          .fontWeight(FontWeight.Bold)
          .fontColor('#f97316')
      }
      .width('100%')
      .justifyContent(FlexAlign.SpaceBetween)
      .padding(16)
      .backgroundColor('#fff7ed')
      .borderRadius(12)
      .margin({ bottom: 16 })

      // 材料列表
      ForEach(this.materialItems, (item: MaterialItem) => {
        Row() {
          // 类型图标
          Circle({ width: 32, height: 32 })
            .fill(item.type === 'metal' ? '#f97316' : item.type === 'tool' ? '#3b82f6' : '#22c55e')
            .overlay(
              Text(item.type === 'metal' ? '🔩' : item.type === 'tool' ? '🔧' : '📦')
                .fontSize(16)
            )

          // 材料信息
          Column() {
            Text(item.name)
              .fontSize(14)
              .fontWeight(FontWeight.Medium)

            Text(`${item.quantity} ${item.unit}`)
              .fontSize(12)
              .fontColor('#9ca3af')

            if (item.notes) {
              Text(item.notes)
                .fontSize(12)
                .fontColor('#6b7280')
            }
          }
          .layoutWeight(1)
          .margin({ left: 12 })
          .alignItems(HorizontalAlign.Start)
        }
        .width('100%')
        .padding(12)
        .backgroundColor('#ffffff')
        .borderRadius(12)
        .margin({ bottom: 8 })
      })
    }
    .padding(16)
  }
}

第四步:常见问题

4.1 价格波动

问题:金属价格波动大,计算的成本可能不准确。

解决:提示用户价格仅供参考,建议查询实时价格。

4.2 工具借用

问题:用户可能借用工具,不需要购买。

解决:支持标记工具状态(已有、需购买、可借用)。


总结

这篇文章围绕"锻艺册"的材料清单功能,讲解了:

材料管理

  • 金属类型和属性
  • 工具清单和分类
  • 用量计算和成本估算

清单功能

  • 自动生成材料清单
  • 分类显示和成本统计

如果你对"锻艺册"感兴趣,欢迎去鸿蒙应用市场搜索下载体验。