391 lines
11 KiB
JavaScript
391 lines
11 KiB
JavaScript
|
// pages/sale_order/sale_order.js
|
||
|
const convert = require('xml-js');
|
||
|
const app = getApp();
|
||
|
|
||
|
Page({
|
||
|
/**
|
||
|
* 页面的初始数据
|
||
|
*/
|
||
|
data: {
|
||
|
odooUrl: '',
|
||
|
db: '',
|
||
|
username: '',
|
||
|
password: '',
|
||
|
partners: [],
|
||
|
userId: null // 用于存储用户ID
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* 生命周期函数--监听页面加载
|
||
|
*/
|
||
|
onLoad(options) {
|
||
|
// Odoo 服务器配置
|
||
|
const { odooUrl, db, username, password } = app.globalData;
|
||
|
this.setData({
|
||
|
odooUrl: odooUrl,
|
||
|
db: db,
|
||
|
username: username,
|
||
|
password: password
|
||
|
});
|
||
|
|
||
|
// 登录到 Odoo
|
||
|
const loginUrl = `${this.data.odooUrl}/xmlrpc/2/common`;
|
||
|
const loginParams = [
|
||
|
`<value><string>${this.data.db}</string></value>`,
|
||
|
`<value><string>${this.data.username}</string></value>`,
|
||
|
`<value><string>${this.data.password}</string></value>`,
|
||
|
`<value><struct>
|
||
|
<member>
|
||
|
<name>interactive</name>
|
||
|
<value><boolean>0</boolean></value>
|
||
|
</member>
|
||
|
</struct></value>`
|
||
|
];
|
||
|
|
||
|
this.methodCall(loginUrl, 'authenticate', loginParams, (err, xmlResponse) => {
|
||
|
if (err) {
|
||
|
console.error('Authentication failed:', err);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// 解析 XML 响应
|
||
|
const result = convert.xml2js(xmlResponse, { compact: true, spaces: 4 });
|
||
|
|
||
|
if (result.methodResponse.fault) {
|
||
|
const faultString = result.methodResponse.fault.value.struct.member.find(member => member.name._text === 'faultString').value.string._text;
|
||
|
console.error('Authentication failed:', faultString);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const userId = result.methodResponse.params.param.value.int._text;
|
||
|
console.log('Authentication successful. User ID:', userId);
|
||
|
|
||
|
// 存储用户ID
|
||
|
this.setData({
|
||
|
userId: userId
|
||
|
});
|
||
|
|
||
|
// 获取模型信息
|
||
|
const objectUrl = `${this.data.odooUrl}/xmlrpc/2/object`;
|
||
|
const objectParams = [
|
||
|
`<value><string>${this.data.db}</string></value>`,
|
||
|
`<value><int>${userId}</int></value>`,
|
||
|
`<value><string>${this.data.password}</string></value>`,
|
||
|
`<value><string>sale.order</string></value>`,
|
||
|
`<value><string>search_read</string></value>`,
|
||
|
`<value><array>
|
||
|
<data>
|
||
|
<value><array><data></data></array></value>
|
||
|
<value><array>
|
||
|
<data>
|
||
|
<value><string>id</string></value>
|
||
|
<value><string>name</string></value>
|
||
|
<value><string>orde_ddje</string></value>
|
||
|
<value><string>date_order</string></value>
|
||
|
<value><string>product_ids</string></value>
|
||
|
<value><string>partner_id</string></value> <!-- 添加 partner_id 字段 -->
|
||
|
</data>
|
||
|
</array></value>
|
||
|
</data>
|
||
|
</array></value>`
|
||
|
];
|
||
|
|
||
|
this.methodCall(objectUrl, 'execute_kw', objectParams, (err, xmlResponse) => {
|
||
|
if (err) {
|
||
|
console.error('Failed to fetch data:', err);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// 解析 XML 响应
|
||
|
const result = convert.xml2js(xmlResponse, { compact: true, spaces: 4 });
|
||
|
|
||
|
if (result.methodResponse.fault) {
|
||
|
const faultString = result.methodResponse.fault.value.struct.member.find(member => member.name._text === 'faultString').value.string._text;
|
||
|
console.error('Failed to fetch data:', faultString);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const data = result.methodResponse.params.param.value.array.data.value;
|
||
|
if (!data) {
|
||
|
console.error('No data found in response');
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const partners = data.map(item => {
|
||
|
const id = item.struct.member.find(member => member.name._text === 'id')?.value.int?._text || '';
|
||
|
const name = item.struct.member.find(member => member.name._text === 'name')?.value.string?._text || '';
|
||
|
const date_order = item.struct.member.find(member => member.name._text === 'date_order')?.value.string?._text || '';
|
||
|
const orde_ddje = item.struct.member.find(member => member.name._text === 'orde_ddje')?.value.double?._text || '0.00';
|
||
|
let product_ids = item.struct.member.find(member => member.name._text === 'product_ids')?.value.array?.data?.value || [];
|
||
|
|
||
|
// 如果 product_ids 是对象而不是数组,则处理为数组
|
||
|
if (!Array.isArray(product_ids)) {
|
||
|
product_ids = [];
|
||
|
} else {
|
||
|
product_ids = product_ids.map(idObj => idObj.int?._text);
|
||
|
}
|
||
|
|
||
|
// 提取 partner_id
|
||
|
const partner_id = item.struct.member.find(member => member.name._text === 'partner_id')?.value.array?.data?.value[0]?.int?._text || '';
|
||
|
|
||
|
return { id, name, orde_ddje, date_order, product_ids, partner_id };
|
||
|
});
|
||
|
|
||
|
console.log('Data fetched successfully:', partners);
|
||
|
|
||
|
// 获取产品详细信息
|
||
|
const allProductIds = partners.flatMap(partner => partner.product_ids);
|
||
|
this.fetchProductDetails(allProductIds, (err, products) => {
|
||
|
if (err) {
|
||
|
console.error('Failed to fetch product details:', err);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// 将产品详细信息映射到每个订单
|
||
|
const partnersWithProducts = partners.map(partner => {
|
||
|
const productsInfo = partner.product_ids.map(id => {
|
||
|
return products.find(product => product.id === id);
|
||
|
}).filter(product => product); // 过滤掉未找到的产品
|
||
|
|
||
|
return {
|
||
|
...partner,
|
||
|
products: productsInfo
|
||
|
};
|
||
|
});
|
||
|
|
||
|
console.log('Data with products fetched successfully:', partnersWithProducts);
|
||
|
// 更新页面数据
|
||
|
this.setData({
|
||
|
partners: partnersWithProducts
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
},
|
||
|
/**
|
||
|
* 创建一个函数来进行 XML-RPC 请求
|
||
|
*/
|
||
|
xmlrpcRequest(url, xmlData, callback) {
|
||
|
wx.request({
|
||
|
url: url,
|
||
|
method: 'POST',
|
||
|
data: xmlData,
|
||
|
header: {
|
||
|
'Content-Type': 'text/xml'
|
||
|
},
|
||
|
success: function(res) {
|
||
|
// 确保返回的数据是纯 XML 格式
|
||
|
if (res.data && typeof res.data === 'string') {
|
||
|
callback(null, res.data);
|
||
|
} else {
|
||
|
callback(new Error('Invalid response format'), null);
|
||
|
}
|
||
|
},
|
||
|
fail: function(err) {
|
||
|
callback(err, null);
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* 创建一个函数来进行 XML-RPC 方法调用
|
||
|
*/
|
||
|
methodCall(url, method, params, callback) {
|
||
|
const xmlData = `
|
||
|
<methodCall>
|
||
|
<methodName>${method}</methodName>
|
||
|
<params>
|
||
|
${params.map(param => `<param>${param}</param>`).join('')}
|
||
|
</params>
|
||
|
</methodCall>
|
||
|
`;
|
||
|
|
||
|
this.xmlrpcRequest(url, xmlData, callback);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* 获取产品详细信息
|
||
|
*/
|
||
|
fetchProductDetails(productIds, callback) {
|
||
|
// 确保 productIds 是一个数组
|
||
|
if (!Array.isArray(productIds)) {
|
||
|
productIds = [productIds];
|
||
|
}
|
||
|
|
||
|
// 过滤掉无效的 productIds
|
||
|
const validProductIds = productIds.filter(id => typeof id === 'number' && Number.isInteger(id));
|
||
|
|
||
|
if (validProductIds.length === 0) {
|
||
|
callback(null, []);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const objectUrl = `${this.data.odooUrl}/xmlrpc/2/object`;
|
||
|
const objectParams = [
|
||
|
`<value><string>${this.data.db}</string></value>`,
|
||
|
`<value><int>${this.data.userId}</int></value>`,
|
||
|
`<value><string>${this.data.password}</string></value>`,
|
||
|
`<value><string>product.product</string></value>`,
|
||
|
`<value><string>search_read</string></value>`,
|
||
|
`<value><array>
|
||
|
<data>
|
||
|
<value><array>
|
||
|
<data>
|
||
|
${validProductIds.map(id => `<value><int>${id}</int></value>`).join('')}
|
||
|
</data>
|
||
|
</array></value>
|
||
|
<value><array>
|
||
|
<data>
|
||
|
<value><string>id</string></value>
|
||
|
<value><string>name</string></value>
|
||
|
<value><string>list_price</string></value>
|
||
|
</data>
|
||
|
</array></value>
|
||
|
</data>
|
||
|
</array></value>`
|
||
|
];
|
||
|
|
||
|
this.methodCall(objectUrl, 'execute_kw', objectParams, (err, xmlResponse) => {
|
||
|
if (err) {
|
||
|
console.error('Failed to fetch product details:', err);
|
||
|
callback(err, []);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// 解析 XML 响应
|
||
|
const result = convert.xml2js(xmlResponse, { compact: true, spaces: 4 });
|
||
|
|
||
|
if (result.methodResponse.fault) {
|
||
|
const faultString = result.methodResponse.fault.value.struct.member.find(member => member.name._text === 'faultString').value.string._text;
|
||
|
console.error('Failed to fetch product details:', faultString);
|
||
|
callback(new Error(faultString), []);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const products = result.methodResponse.params.param.value.array.data.value.map(item => {
|
||
|
const id = item.struct.member.find(member => member.name._text === 'id')?.value.int?._text || '';
|
||
|
const name = item.struct.member.find(member => member.name._text === 'name')?.value.string?._text || '';
|
||
|
const list_price = item.struct.member.find(member => member.name._text === 'list_price')?.value.double?._text || '0.00';
|
||
|
|
||
|
return { id, name, list_price };
|
||
|
});
|
||
|
|
||
|
callback(null, products);
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* 生成分享文本
|
||
|
*/
|
||
|
generateShareText(partner) {
|
||
|
const productNames = partner.products.map(product => product.name).join(', ');
|
||
|
return `
|
||
|
销售单详情:
|
||
|
订单号: ${partner.id}
|
||
|
订单名称: ${partner.name}
|
||
|
订单日期: ${partner.date_order}
|
||
|
订单金额: ${partner.orde_ddje}
|
||
|
产品: ${productNames}
|
||
|
合作伙伴ID: ${partner.partner_id || '无'}
|
||
|
`;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* 处理卡片点击事件
|
||
|
*/
|
||
|
onCardClick(event) {
|
||
|
const partner = this.data.partners[event.currentTarget.dataset.index];
|
||
|
if (!partner) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
console.log('Card clicked:', partner);
|
||
|
console.log('Card clicked:', event);
|
||
|
|
||
|
// 在这里可以添加更多的处理逻辑,比如跳转到详情页
|
||
|
wx.showToast({
|
||
|
title: `点击了订单 ${partner.name}`,
|
||
|
icon: 'none'
|
||
|
});
|
||
|
const index = event.currentTarget.dataset.index;
|
||
|
wx.navigateTo({
|
||
|
url: `/pages/sale_order/form/sale_order_form?index=${index}`,
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* 处理图片点击事件
|
||
|
*/
|
||
|
onThumbClick(event) {
|
||
|
const partner = this.data.partners[event.currentTarget.dataset.index];
|
||
|
if (!partner) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
console.log('Thumbnail clicked:', partner);
|
||
|
// 在这里可以添加更多的处理逻辑,比如预览图片
|
||
|
wx.showToast({
|
||
|
title: `点击了订单 ${partner.name} 的图片`,
|
||
|
icon: 'none'
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* 生命周期函数--监听页面初次渲染完成
|
||
|
*/
|
||
|
onReady() {
|
||
|
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* 生命周期函数--监听页面显示
|
||
|
*/
|
||
|
onShow() {
|
||
|
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* 生命周期函数--监听页面隐藏
|
||
|
*/
|
||
|
onHide() {
|
||
|
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* 生命周期函数--监听页面卸载
|
||
|
*/
|
||
|
onUnload() {
|
||
|
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* 页面相关事件处理函数--监听用户下拉动作
|
||
|
*/
|
||
|
onPullDownRefresh() {
|
||
|
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* 页面上拉触底事件的处理函数
|
||
|
*/
|
||
|
onReachBottom() {
|
||
|
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* 用户点击右上角分享
|
||
|
*/
|
||
|
onShareAppMessage() {
|
||
|
const partner = this.data.partners[0]; // 假设分享第一个订单
|
||
|
if (!partner) {
|
||
|
return {};
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
title: '销售单详情',
|
||
|
path: '/pages/sale_order/sale_order?id=' + partner.id,
|
||
|
imageUrl: 'https://fastly.jsdelivr.net/npm/@vant/assets/ipad.jpeg',
|
||
|
desc: this.generateShareText(partner)
|
||
|
};
|
||
|
}
|
||
|
});
|