Files
trade-assistant/miniprogram/pages/quotation/quotation.js
T
TradeMate Dev c6206787da Initial commit: TradeMate 外贸小助手 MVP
项目结构:
- backend/     Python FastAPI 后端
- uni-app/     uni-app跨端前端
- docs/        设计文档
- docker-compose.yml  Docker编排
- nginx/scripts/systemd 运维配置

已完成功能:
- 用户认证 (JWT)
- 智能翻译 + 回复建议
- 营销素材生成
- 客户管理 + 沉默检测
- 报价单管理
- 产品库管理
- 汇率换算
- 推送通知 (uni-push)
- WhatsApp Webhook框架
- Celery定时任务
2026-05-08 18:17:12 +08:00

155 lines
3.6 KiB
JavaScript

const { quotationApi, customerApi } = require('../../utils/api');
Page({
data: {
quotations: [],
page: 1,
hasMore: true,
loading: false,
showCreateModal: false,
customers: [],
newQuotation: {
customer_id: '',
title: '',
items: [],
currency: 'USD',
payment_terms: 'T/T 30% deposit',
delivery_terms: 'FOB',
lead_time: '',
notes: '',
},
tempItem: {
product_name: '',
quantity: 1,
unit_price: 0,
},
},
onLoad() {
this.loadQuotations();
},
onReachBottom() {
if (this.data.hasMore && !this.data.loading) {
this.setData({ page: this.data.page + 1 });
this.loadQuotations(true);
}
},
async loadQuotations(isAppend = false) {
if (this.data.loading) return;
this.setData({ loading: true });
try {
const result = await quotationApi.list(this.data.page);
this.setData({
quotations: isAppend ? [...this.data.quotations, ...result.items] : result.items,
hasMore: result.items.length >= result.size,
loading: false,
});
} catch (err) {
wx.showToast({ title: err.message || '加载失败', icon: 'none' });
this.setData({ loading: false });
}
},
async showCreate() {
try {
const customers = await customerApi.list(1, 100);
this.setData({
showCreateModal: true,
customers: customers.items,
});
} catch (err) {
wx.showToast({ title: '加载客户失败', icon: 'none' });
}
},
hideCreate() {
this.setData({
showCreateModal: false,
newQuotation: {
customer_id: '',
title: '',
items: [],
currency: 'USD',
payment_terms: 'T/T 30% deposit',
delivery_terms: 'FOB',
lead_time: '',
notes: '',
},
});
},
onInput(e) {
const field = e.currentTarget.dataset.field;
const value = e.detail.value;
this.setData({ [`newQuotation.${field}`]: value });
},
onItemInput(e) {
const field = e.currentTarget.dataset.field;
const value = e.detail.value;
this.setData({ [`tempItem.${field}`]: value });
},
addItem() {
const { tempItem, newQuotation } = this.data;
if (!tempItem.product_name) {
wx.showToast({ title: '请输入产品名称', icon: 'none' });
return;
}
this.setData({
newQuotation: {
...newQuotation,
items: [...newQuotation.items, { ...tempItem }],
},
tempItem: {
product_name: '',
quantity: 1,
unit_price: 0,
},
});
},
removeItem(e) {
const index = e.currentTarget.dataset.index;
const { newQuotation } = this.data;
newQuotation.items.splice(index, 1);
this.setData({ newQuotation });
},
async createQuotation() {
const { newQuotation } = this.data;
if (!newQuotation.customer_id) {
wx.showToast({ title: '请选择客户', icon: 'none' });
return;
}
if (newQuotation.items.length === 0) {
wx.showToast({ title: '请添加产品', icon: 'none' });
return;
}
try {
await quotationApi.create(newQuotation);
wx.showToast({ title: '创建成功', icon: 'success' });
this.hideCreate();
this.setData({ page: 1, quotations: [] });
this.loadQuotations();
} catch (err) {
wx.showToast({ title: err.message || '创建失败', icon: 'none' });
}
},
viewDetail(e) {
const id = e.currentTarget.dataset.id;
wx.navigateTo({ url: `/pages/quotation/detail?id=${id}` });
},
onPullDownRefresh() {
this.setData({ page: 1, quotations: [] });
this.loadQuotations();
wx.stopPullDownRefresh();
},
});