var _customState = {}; var APP_TYPE = 'APP_N9NPHVTQLPBPO8MR6WFG'; var CUSTOMER_FORM_UUID = 'FORM-NO966791YOK2XKW9DMSEGD5L1IN73UHW3ME6LR1'; var STORAGE_KEY = 'tyson.customer-info-query.selected-customer'; var requestSequence = 0; var FIELDS = { customerNumber: 'textField_l6em70k2', customerName: 'textField_l6em70k4' }; export function didMount() { var cached = null; try { cached = JSON.parse(window.localStorage.getItem(STORAGE_KEY) || 'null'); } catch (e) { cached = null; } this.setCustomState({ keyword: cached && cached.customerNumber ? cached.customerNumber + ' - ' + (cached.customerName || '') : '', searching: false, customers: [], selectedCustomer: cached && cached.customerNumber ? cached : null, queryType: 'balance', querying: false, result: null, error: '', searchVisible: false }); } export function didUnmount() { if (this._customerSearchTimer) { clearTimeout(this._customerSearchTimer); } } export function setQueryType(queryType) { this.setCustomState({ queryType: queryType, result: null, error: '' }); this.forceUpdate(); } export function updateKeyword(value) { var self = this; var keyword = value || ''; self.setCustomState({ keyword: keyword, searchVisible: true, error: '' }); self.forceUpdate(); if (self._customerSearchTimer) { clearTimeout(self._customerSearchTimer); } if (keyword.trim().length < 2) { self.setCustomState({ customers: [], searching: false }); self.forceUpdate(); return; } self._customerSearchTimer = setTimeout(function () { self.searchCustomers(keyword.trim()); }, 300); } export function searchCustomers(keyword) { var self = this; var base = { formUuid: CUSTOMER_FORM_UUID, appType: APP_TYPE, currentPage: 1, pageSize: 20 }; var codeCondition = [{ key: FIELDS.customerNumber, value: keyword, type: 'TEXT', operator: 'contains', componentName: 'TextField' }]; var nameCondition = [{ key: FIELDS.customerName, value: keyword, type: 'TEXT', operator: 'contains', componentName: 'TextField' }]; self.setCustomState({ searching: true }); self.forceUpdate(); var codeParams = {}; var nameParams = {}; Object.keys(base).forEach(key => { codeParams[key] = base[key]; nameParams[key] = base[key]; }); codeParams.searchFieldJson = JSON.stringify(codeCondition); nameParams.searchFieldJson = JSON.stringify(nameCondition); return Promise.all([self.utils.yida.searchFormDatas(codeParams), self.utils.yida.searchFormDatas(nameParams)]).then(function (responses) { var seen = {}; var customers = []; responses.forEach(response => { var rows = response && response.data || response && response.content && response.content.data || []; rows.forEach(row => { var formData = row.formData || {}; var customerNumber = formData[FIELDS.customerNumber]; if (customerNumber && !seen[customerNumber]) { seen[customerNumber] = true; customers.push({ customerNumber: customerNumber, customerName: formData[FIELDS.customerName] || '' }); } }); }); self.setCustomState({ customers: customers, searching: false }); self.forceUpdate(); }).catch(function (error) { self.setCustomState({ searching: false, customers: [] }); self.utils.toast({ title: error && error.message ? error.message : '客户查询失败', type: 'error' }); self.forceUpdate(); }); } export function selectCustomer(customer) { try { window.localStorage.setItem(STORAGE_KEY, JSON.stringify(customer)); } catch (e) { // The query remains usable when browser storage is unavailable. } this.setCustomState({ selectedCustomer: customer, keyword: customer.customerNumber + ' - ' + customer.customerName, searchVisible: false, customers: [], result: null, error: '' }); this.forceUpdate(); } export function clearCustomer() { try { window.localStorage.removeItem(STORAGE_KEY); } catch (e) { // Ignore storage cleanup errors. } this.setCustomState({ keyword: '', selectedCustomer: null, customers: [], result: null, error: '' }); this.forceUpdate(); } export function queryCustomerInfo() { var self = this; var state = self.getCustomState(); var selected = state.selectedCustomer; if (!selected) { self.utils.toast({ title: '请先选择客户', type: 'warning' }); return; } var dataSourceName = state.queryType === 'balance' ? 'customerBalance' : 'customerUnlockOrders'; var dataSource = self.dataSourceMap && self.dataSourceMap[dataSourceName]; if (!dataSource || !dataSource.load) { var availableDataSources = self.dataSourceMap ? Object.keys(self.dataSourceMap).join(', ') : '未初始化'; var message = '查询数据源不可用:' + dataSourceName + ';当前数据源:' + availableDataSources; self.setCustomState({ error: message, result: null }); self.utils.toast({ title: message, type: 'error' }); self.forceUpdate(); return; } self.setCustomState({ querying: true, error: '', result: null }); self.forceUpdate(); var request = { inputs: JSON.stringify({ Headers: { 'Content-Type': 'application/json' }, Query: {}, Body: { requestID: self.createRequestId(), CUSTOMER_NUMBER: selected.customerNumber, CUSTOMER_NAME: selected.customerName } }) }; try { return Promise.resolve(dataSource.load(request)).then(function (result) { self.handleQueryResponse(result); }).catch(function (error) { self.setCustomState({ querying: false, result: null, error: error && error.message ? error.message : 'SAP查询失败' }); self.utils.toast({ title: error && error.message ? error.message : 'SAP查询失败', type: 'error' }); self.forceUpdate(); }); } catch (error) { self.setCustomState({ querying: false, result: null, error: error && error.message ? error.message : 'SAP查询初始化失败' }); self.utils.toast({ title: error && error.message ? error.message : 'SAP查询初始化失败', type: 'error' }); self.forceUpdate(); } } export function handleQueryResponse(result) { var response = result && result.Response !== undefined ? result.Response : result; response = response && response.content !== undefined ? response.content : response; response = response && response.serviceReturnValue !== undefined ? response.serviceReturnValue : response; if (typeof response === 'string') { try { response = JSON.parse(response); } catch (e) { var responseText = response.toLowerCase(); var gatewayMessage = responseText.indexOf('502 bad gateway') >= 0 || responseText.indexOf('503 service unavailable') >= 0 || responseText.indexOf('= 0 || responseText.indexOf('= 0 ? 'SAP查询服务暂时不可用,请稍后重试' : 'SAP查询服务返回格式异常'; this.setCustomState({ querying: false, result: null, error: gatewayMessage }); this.utils.toast({ title: gatewayMessage, type: 'error' }); this.forceUpdate(); return; } } if (response && response.success === false) { var responseMessage = response.message || response.errorMsg || 'SAP查询失败'; this.setCustomState({ querying: false, result: null, error: responseMessage }); this.utils.toast({ title: responseMessage, type: 'error' }); this.forceUpdate(); return; } if (response && response.STATUS && response.STATUS !== 'S') { var sapMessage = response.MESSAGE || 'SAP查询失败,状态=' + response.STATUS; this.setCustomState({ querying: false, result: null, error: sapMessage }); this.utils.toast({ title: sapMessage, type: 'error' }); this.forceUpdate(); return; } var message = response && response.MESSAGE; var errorItem = response && response.ITEM && response.ITEM.filter(item => item && item.ERRO_MESSAGE)[0]; if (message || errorItem) { var errorMessage = message || errorItem.ERRO_MESSAGE; this.setCustomState({ querying: false, result: null, error: errorMessage }); this.utils.toast({ title: errorMessage, type: 'error' }); this.forceUpdate(); return; } this.setCustomState({ querying: false, result: response || {} }); this.forceUpdate(); } export function createRequestId() { requestSequence += 1; if (window.crypto && window.crypto.randomUUID) { return window.crypto.randomUUID(); } if (window.crypto && window.crypto.getRandomValues) { var values = new Uint32Array(4); window.crypto.getRandomValues(values); return values[0].toString(16) + '-' + values[1].toString(16) + '-' + values[2].toString(16) + '-' + values[3].toString(16); } return Date.now().toString(36) + '-' + requestSequence.toString(36) + '-' + Math.random().toString(36).slice(2); } export function formatAmount(value) { var amount = Number(value || 0); if (isNaN(amount)) { return value || '-'; } return amount.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); } export function formatDate(value) { if (!value) { return value || '-'; } var text = String(value); if (text.length === 8) { return text.slice(0, 4) + '-' + text.slice(4, 6) + '-' + text.slice(6, 8); } var matched = text.match(/^(\d{4}-\d{2}-\d{2})/); return matched ? matched[1] : text; } export function formatTime(value) { if (!value) { return '-'; } var matched = String(value).match(/T(\d{2}:\d{2}:\d{2})/); return matched ? matched[1] : String(value); } export function renderBalanceSummary(result) { return
客户组{result.CUSTOMER_GROUP || '-'}
客户组描述{result.CUSTOMER_GROUP_DESC || '-'}
总风险金额{this.formatAmount(result.TOTAL_RISK_AMT)}
; } export function renderBalance(state, mobile) { var result = state.result || {}; var items = result.ITEM || []; if (!items.length) { return
未查询到余额数据
; } return
{this.renderBalanceSummary(result)}
{items.map((item, index) => )}
公司代码币种未结金额
{item.COMPANY_CODE || '-'}{item.CURRENCY || '-'}{this.formatAmount(item.OUTSTAND_AMT)}
; } export function renderOrders(state, mobile) { var items = state.result && state.result.ITEM || []; if (!items.length) { return
未查询到收款解锁订单
; } if (mobile) { return
{items.map((item, index) =>
{item.SALES_ORDER || '-'}{item.RELEASE_STATUS === 'S' ? '成功' : '失败'}
公司代码{item.COMPANY_CODE || '-'}
销售组织{item.SALES_ORG || '-'}
订单金额{this.formatAmount(item.SALES_AMOUNT)} {item.CURRENCY || ''}
释放日期{this.formatDate(item.RELEASE_DATE)}
释放时间{this.formatTime(item.RELEASE_TIME)}
)}
; } return
{items.map((item, index) => )}
公司代码销售订单号销售组织订单金额币种释放日期释放时间状态
{item.COMPANY_CODE || '-'}{item.SALES_ORDER || '-'}{item.SALES_ORG || '-'}{this.formatAmount(item.SALES_AMOUNT)}{item.CURRENCY || '-'}{this.formatDate(item.RELEASE_DATE)}{this.formatTime(item.RELEASE_TIME)}{item.RELEASE_STATUS === 'S' ? '成功' : '失败'}
; } export function renderJsx() { var self = this; var state = self.getCustomState(); var mobile = self.utils.isMobile(); var selected = state.selectedCustomer; var result = state.result; return
CUSTOMER SERVICE

客户信息查询

查询客户余额与收款解锁订单

选择客户
{ self.updateKeyword(e.target.value); }} onFocus={e => { self.setCustomState({ searchVisible: true }); self.forceUpdate(); }} style={styles.input} /> {selected && } {state.searchVisible && (state.searching || state.customers && state.customers.length > 0) &&
{state.searching &&
正在搜索客户...
} {!state.searching && state.customers.map(customer => )}
}
查询内容
客户余额 收款解锁订单
{!mobile &&
操作
}
{!selected &&
请选择客户后再查询
}
{state.error &&
{state.error}
} {result &&
{state.queryType === 'balance' ? 'BALANCE' : 'UNLOCKED ORDERS'}

{state.queryType === 'balance' ? '客户余额' : '收款解锁订单'}

客户编码:{result.CUSTOMER_NUMBER || selected && selected.customerNumber || '-'}客户名称:{result.CUSTOMER_NAME || selected && selected.customerName || '-'}
{state.queryType === 'balance' ? self.renderBalance(state, mobile) : self.renderOrders(state, mobile)}
} {!result && !state.error &&
选择客户和查询内容后,可查看对应的 SAP 信息。
}
{this.state && this.state.timestamp}
; } var styles = { page: { minHeight: '100vh', background: '#F4F6F5', color: '#17211E', fontFamily: 'Microsoft YaHei, Arial, sans-serif', padding: '20px 16px 40px' }, shell: { maxWidth: 1120, margin: '0 auto' }, header: { padding: '12px 0 22px', borderBottom: '1px solid #DCE3DF', marginBottom: 20, textAlign: 'center' }, eyebrow: { color: '#3B6C55', fontSize: 11, fontWeight: 700, letterSpacing: 1.2, marginBottom: 6 }, title: { margin: 0, fontSize: 28, lineHeight: 1.2, letterSpacing: '-0.5px' }, subtitle: { margin: '8px 0 0', color: '#66746E', fontSize: 14 }, panel: { background: '#FFFFFF', border: '1px solid #DCE3DF', padding: 20, boxShadow: '0 10px 28px rgba(25,48,38,.06)' }, fieldLabel: { color: '#405149', fontSize: 13, fontWeight: 700, margin: '0 0 8px' }, queryRow: { display: 'flex', alignItems: 'flex-end', gap: 14 }, queryStack: { display: 'flex', flexDirection: 'column', gap: 14 }, customerField: { flex: 1, minWidth: 260 }, queryTypeField: { width: 280 }, queryActionField: { width: 110 }, queryActionFieldMobile: { width: '100%' }, searchWrap: { position: 'relative' }, input: { width: '100%', boxSizing: 'border-box', minHeight: 46, border: '1px solid #B7C5BD', borderRadius: 4, padding: '0 72px 0 13px', fontSize: 15, outline: 'none', background: '#fff' }, clearButton: { position: 'absolute', right: 8, top: 8, border: 0, background: '#EEF3F0', color: '#466253', minHeight: 30, borderRadius: 3, padding: '0 10px', cursor: 'pointer' }, searchMenu: { position: 'absolute', zIndex: 20, top: 49, left: 0, right: 0, maxHeight: 280, overflowY: 'auto', background: '#fff', border: '1px solid #B7C5BD', boxShadow: '0 12px 24px rgba(22,43,34,.14)' }, searchHint: { padding: 14, color: '#66746E', fontSize: 13 }, customerOption: { display: 'flex', width: '100%', minHeight: 48, padding: '10px 13px', gap: 12, alignItems: 'center', border: 0, borderBottom: '1px solid #EDF1EE', background: '#fff', textAlign: 'left', cursor: 'pointer', color: '#17211E' }, switchRow: { display: 'flex', minHeight: 44, alignItems: 'center', justifyContent: 'space-between', gap: 8 }, switchLabel: { color: '#89958F', fontSize: 13, whiteSpace: 'nowrap' }, switchLabelActive: { color: '#24563E', fontSize: 13, fontWeight: 700, whiteSpace: 'nowrap' }, switchTrack: { position: 'relative', width: 46, height: 24, flex: '0 0 46px', padding: 0, border: 0, borderRadius: 12, background: '#24563E', cursor: 'pointer' }, switchTrackActive: { position: 'relative', width: 46, height: 24, flex: '0 0 46px', padding: 0, border: 0, borderRadius: 12, background: '#D76F2B', cursor: 'pointer' }, switchThumb: { position: 'absolute', top: 3, left: 3, width: 18, height: 18, borderRadius: '50%', background: '#fff', boxShadow: '0 1px 3px rgba(0,0,0,.22)' }, switchThumbActive: { position: 'absolute', top: 3, right: 3, width: 18, height: 18, borderRadius: '50%', background: '#fff', boxShadow: '0 1px 3px rgba(0,0,0,.22)' }, queryButton: { width: '100%', minHeight: 46, border: 0, borderRadius: 4, background: '#D76F2B', color: '#fff', fontSize: 15, fontWeight: 700, cursor: 'pointer' }, queryDisabled: { width: '100%', minHeight: 46, border: 0, borderRadius: 4, background: '#C8D0CB', color: '#FFFFFF', fontSize: 15, fontWeight: 700, cursor: 'not-allowed' }, queryButtonMobile: { width: '100%', minHeight: 42, border: 0, borderRadius: 4, background: '#D76F2B', color: '#fff', fontSize: 14, fontWeight: 700, cursor: 'pointer' }, queryDisabledMobile: { width: '100%', minHeight: 42, border: 0, borderRadius: 4, background: '#C8D0CB', color: '#FFFFFF', fontSize: 14, fontWeight: 700, cursor: 'not-allowed' }, validationHint: { marginTop: 8, color: '#9B3D15', fontSize: 12 }, resultPanel: { background: '#FFFFFF', border: '1px solid #DCE3DF', margin: '20px auto 0', padding: 24, maxWidth: 1120, boxSizing: 'border-box' }, resultHeader: { display: 'flex', justifyContent: 'center', alignItems: 'center', flexDirection: 'column', gap: 8, borderBottom: '1px solid #E7ECE9', paddingBottom: 16, marginBottom: 18, textAlign: 'center' }, resultTitle: { margin: 0, fontSize: 22 }, customerSummary: { display: 'flex', justifyContent: 'center', flexWrap: 'wrap', gap: '4px 16px', color: '#5D6B64', fontSize: 13, textAlign: 'center' }, balanceSummary: { display: 'flex', justifyContent: 'center', gap: 40, marginBottom: 18, padding: '14px 18px', background: '#F6F9F7', border: '1px solid #DDE6E0', color: '#405149', textAlign: 'center' }, summaryLabel: { display: 'block', marginBottom: 5, color: '#718078', fontSize: 12, fontWeight: 400 }, summaryAmount: { color: '#1D6141', fontVariantNumeric: 'tabular-nums' }, empty: { padding: '36px 18px', marginTop: 20, textAlign: 'center', color: '#7A8881', background: '#FFFFFF', border: '1px dashed #C9D5CE', fontSize: 14 }, error: { marginTop: 20, padding: '12px 14px', background: '#FFF1EB', border: '1px solid #F1B895', color: '#9B3D15', fontSize: 14 }, tableWrap: { overflowX: 'auto', border: '1px solid #DDE6E0', borderRadius: 4, background: '#FFFFFF' }, table: { width: '100%', borderCollapse: 'collapse', fontSize: 13, minWidth: 620, textAlign: 'center', lineHeight: 1.35 }, balanceTableWrapMobile: { overflowX: 'auto', border: '1px solid #DDE6E0', borderRadius: 4, background: '#FFFFFF' }, balanceTableMobile: { width: '100%', borderCollapse: 'collapse', fontSize: 12, minWidth: 300, textAlign: 'center', lineHeight: 1.2 }, amountCell: { textAlign: 'right', fontVariantNumeric: 'tabular-nums' }, amountHighlight: { textAlign: 'right', color: '#1D6141', fontWeight: 700, fontVariantNumeric: 'tabular-nums' }, nameCell: { textAlign: 'left', minWidth: 150 }, orderCell: { fontFamily: 'Consolas, monospace', fontWeight: 700 }, orderCard: { marginBottom: 10, padding: '13px 14px', border: '1px solid #DDE6E0', borderRadius: 4, background: '#FFFFFF' }, orderCardHeader: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', paddingBottom: 10, marginBottom: 10, borderBottom: '1px solid #E7ECE9' }, orderCardNumber: { fontFamily: 'Consolas, monospace', color: '#17211E', fontSize: 15 }, orderCardGrid: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '10px 14px', color: '#64726B', fontSize: 12 }, orderCardAmount: { color: '#1D6141', fontVariantNumeric: 'tabular-nums' }, mobileCard: { border: '1px solid #DFE7E2', padding: 15, marginBottom: 10, background: '#FBFCFB' }, cardTop: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 14 }, currency: { color: '#5F6E66', fontSize: 12 }, metric: { display: 'flex', justifyContent: 'space-between', gap: 12, padding: '8px 0', borderTop: '1px solid #E7ECE9', color: '#64726B', fontSize: 13 }, highlight: { color: '#1D6141', fontWeight: 700 }, detailGrid: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '8px 12px', fontSize: 13, color: '#64726B' }, statusSuccess: { display: 'inline-block', padding: '3px 8px', borderRadius: 12, color: '#1D6141', background: '#E4F1E8', fontSize: 12, fontWeight: 700 }, statusError: { display: 'inline-block', padding: '3px 8px', borderRadius: 12, color: '#A83B27', background: '#FCE9E4', fontSize: 12, fontWeight: 700 } }; export function getCustomState(key) { if (typeof _customState === "undefined") { return key ? undefined : {}; } if (key) { return _customState[key]; } return Object.assign({}, _customState); } export function setCustomState(newState) { if (typeof _customState === "undefined") { return; } Object.keys(newState || {}).forEach(function(key) { _customState[key] = newState[key]; }); this.forceUpdate(); } export function forceUpdate() { this.setState({ timestamp: new Date().getTime() }); }