/** * 孔夫子网 API - 登录与商品操作 */ /** * 登录孔夫子(从响应Cookie中提取PHPSESSID) * @param {string} username 用户名(手机号) * @param {string} password 明文密码 * @returns {Promise<{success: boolean, token: string, message: string}>} */ export function login(username, password) { return new Promise((resolve, reject) => { uni.request({ url: 'https://login.kongfz.com/Pc/Login/account', method: 'POST', header: { 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148' }, data: { loginName: username, loginPass: password, autoLogin: '0', returnUrl: 'http://user.kongfz.com/' }, success: (res) => { console.log('孔夫子登录响应 status:', res.statusCode) console.log('孔夫子登录响应 header:', JSON.stringify(res.header)) console.log('孔夫子登录响应 data:', typeof res.data === 'string' ? res.data.substring(0, 500) : JSON.stringify(res.data)) // 提取PHPSESSID let phpsessid = '' const setCookie = res.header['Set-Cookie'] || res.header['set-cookie'] if (setCookie) { const match = setCookie.match(/PHPSESSID=([^;]+)/) if (match) { phpsessid = match[1] } } const responseText = typeof res.data === 'string' ? res.data : JSON.stringify(res.data) const isSuccess = responseText.includes('login.kongfz.cn/Pc/Session/rsync') || responseText.includes('window.location.href') || res.statusCode === 302 || (res.statusCode === 200 && phpsessid) if (isSuccess && phpsessid) { resolve({ success: true, token: phpsessid, message: '登录成功' }) } else if (res.statusCode === 200 && responseText.includes('errCode')) { try { const json = typeof res.data === 'string' ? JSON.parse(res.data) : res.data if (json.errCode === 1001) { resolve({ success: false, token: '', message: json.errInfo || '账号或密码错误' }) } else if (json.errCode === 1005) { resolve({ success: false, token: '', message: json.errInfo || '密码错误' }) } else if (json.errCode === 1009) { resolve({ success: false, token: '', message: json.errInfo || '调用次数已达上限,请稍后再试' }) } else { resolve({ success: false, token: '', message: json.errInfo || '登录失败' }) } } catch (e) { resolve({ success: false, token: '', message: '登录失败,请检查账号密码' }) } } else { resolve({ success: false, token: '', message: '登录失败,请检查网络和账号密码' }) } }, fail: (err) => { console.error('孔夫子登录请求失败:', err) resolve({ success: false, token: '', message: '网络请求失败,请检查网络连接' }) } }) }) } /** * 搜索孔夫子商品品相统计(全新/古旧等) * @param {string} keyword ISBN或书名 * @param {object} options {phpsessid, userArea, dataType} dataType=0在售 / 1已售 * @returns {Promise<{newCount: number, oldCount: number, totalFound: number}>} */ export function searchFacet(keyword, options = {}) { const { phpsessid = '', userArea = '1006000000', dataType = 0 } = options return new Promise((resolve, reject) => { uni.request({ url: 'https://search.kongfz.com/pc-gw/search-web/client/pc/product/keyword/normal/facet', method: 'GET', data: { dataType: dataType, keyword: keyword, page: 1, userArea: userArea }, header: { 'Cookie': phpsessid ? `PHPSESSID=${phpsessid}` : '' }, success: (res) => { console.log('孔夫子统计响应:', res.statusCode, res.data) if (res.statusCode === 200 && res.data && res.data.status === 1 && res.data.data) { const qualities = res.data.data.qualities || [] let newCount = 0 let oldCount = 0 qualities.forEach(q => { if (q.showName === '全新') { newCount = parseInt(q.showValue || 0, 10) } if (q.showName === '古 | 旧 | 二手') { oldCount = parseInt(q.showValue || 0, 10) } }) const totalFound = parseInt(res.data.data.totalFoundText || res.data.data.matchInfo?.totalFound || 0, 10) resolve({ newCount, oldCount, totalFound }) } else if (res.statusCode === 200 && res.data && res.data.status === 0 && res.data.errType === '102') { console.warn('孔夫子统计-会话过期,需要重新登录') reject(new Error('KONGZ_SESSION_EXPIRED')) } else { resolve({ newCount: 0, oldCount: 0, totalFound: 0 }) } }, fail: (err) => { console.error('孔夫子统计失败:', err) resolve({ newCount: 0, oldCount: 0, totalFound: 0 }) } }) }) } /** * 获取商品列表(分页) */ export function fetchItems(token, params = {}, onProgress) { const items = [] const pageSize = 50 let currentPage = 1 return new Promise((resolve, reject) => { const fetchPage = (page) => { const requestBody = { requestType: 'onSale', page: page, size: pageSize } if (params.itemSn) requestBody.itemSn = params.itemSn if (params.priceMin) requestBody.priceMin = params.priceMin if (params.priceMax) requestBody.priceMax = params.priceMax if (params.startCreateTime) requestBody.startCreateTime = params.startCreateTime if (params.endCreateTime) requestBody.endCreateTime = params.endCreateTime uni.request({ url: 'https://seller.kongfz.com/pc-gw/book-manage-service/client/pc/goods/unSold/list', method: 'POST', header: { 'Content-Type': 'application/json', 'Cookie': `PHPSESSID=${token}`, 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148' }, data: requestBody, success: (res) => { if (res.data && res.data.data && res.data.data.list) { const list = res.data.data.list items.push(...list.map(item => ({ id: item.itemId || item.id, status: 'wait' }))) if (onProgress) onProgress(items.length, res.data.data.total || 0) if (list.length >= pageSize) { currentPage++ setTimeout(() => fetchPage(currentPage), 1000) } else { resolve(items) } } else { resolve(items) } }, fail: (err) => { console.error('获取商品列表失败:', err) reject(err) } }) } fetchPage(currentPage) }) } /** * 搜索孔夫子在售商品(需要登录Cookie) * @param {string} keyword ISBN或书名 * @param {object} options {phpsessid, page} * @returns {Promise<{total: number, list: Array}>} * list中每项: {id, title, author, press, priceText, imgBigUrl, shopName, qualityText, pubDateText, postage} */ export function searchProducts(keyword, options = {}) { const { phpsessid = '', page = 1, sortType = '', quality = '', publisher = '', author = '' } = options return new Promise((resolve, reject) => { const reqData = { dataType: 0, keyword: keyword, page: page, userArea: '1006000000' } const actionPaths = [] if (sortType) { reqData.sortType = sortType actionPaths.push('sortType') } if (quality) { reqData.quality = quality reqData.quaSelect = '2' actionPaths.push('quality') } if (publisher) { reqData.press = publisher } if (author) { reqData.author = author } if (actionPaths.length > 0) { reqData.actionPath = actionPaths.join(',') } uni.request({ url: 'https://search.kongfz.com/pc-gw/search-web/client/pc/product/keyword/list', method: 'GET', data: reqData, header: { 'Cookie': phpsessid ? `PHPSESSID=${phpsessid}` : '' }, success: (res) => { console.log('孔夫子在售搜索响应:', res.statusCode, res.data) if (res.statusCode === 200 && res.data && res.data.status === 1) { const itemResp = res.data.data && res.data.data.itemResponse if (itemResp) { resolve({ total: itemResp.total || 0, list: itemResp.list || [] }) } else { resolve({ total: 0, list: [] }) } } else if (res.statusCode === 200 && res.data && res.data.status === 0 && res.data.errType === '102') { console.warn('孔夫子搜索-会话过期,需要重新登录') reject(new Error('KONGZ_SESSION_EXPIRED')) } else { resolve({ total: 0, list: [] }) } }, fail: (err) => { console.error('孔夫子搜索失败:', err) resolve({ total: 0, list: [] }) } }) }) } /** * 获取孔网图书分类(根据书名搜索孔网 facet 接口) * @param {string} keyword 书名 * @param {object} options { phpsessid, userArea } * @returns {Promise>} 图书分类列表(normal组) */ export function searchCategories(keyword, options = {}) { const { phpsessid = '', userArea = '1006000000' } = options return new Promise((resolve) => { if (!keyword || !keyword.trim()) { resolve([]) return } uni.request({ url: 'https://search.kongfz.com/pc-gw/search-web/client/pc/product/keyword/normal/facet', method: 'GET', data: { dataType: 0, keyword: keyword.trim(), page: 1, userArea: userArea }, header: { 'Cookie': phpsessid ? `PHPSESSID=${phpsessid}` : '' }, success: (res) => { console.log('【孔网分类搜索】URL: https://search.kongfz.com/pc-gw/search-web/client/pc/product/keyword/normal/facet?dataType=0&keyword=' + encodeURIComponent(keyword) + '&page=1&userArea=' + userArea, '| 响应:', JSON.stringify(res.data)) if (res.statusCode === 200 && res.data && res.data.status === 1 && res.data.data) { var categories = res.data.data.categories || [] // 找到 normal 组(图书分类) var normalGroup = null for (var i = 0; i < categories.length; i++) { if (categories[i].type === 'GROUP' && categories[i].name === 'normal') { normalGroup = categories[i] break } } if (normalGroup && normalGroup.subLabels) { resolve(normalGroup.subLabels.map(function(item) { return { value: item.value, showName: item.showName, showValue: item.showValue } })) } else { resolve([]) } } else { resolve([]) } }, fail: () => { resolve([]) } }) }) } /** * 获取孔网出版社列表(根据书名,可选按作者过滤) * @param {string} keyword 书名 * @param {object} options { phpsessid, userArea, author } * @returns {Promise>} 出版社列表 */ export function searchPresses(keyword, options = {}) { const { phpsessid = '', userArea = '1006000000', author = '' } = options return new Promise((resolve) => { if (!keyword || !keyword.trim()) { resolve([]) return } var reqData = { requestId: Math.random().toString(36).substring(2, 10), platform: 'web', searchType: 'keyword', dataType: 0, keyword: keyword.trim(), hasStock: 'true', isNewBook: 'false', searchMode: 0, userArea: userArea, page: 1, size: 50, tplParams: '{}', sortType: 0, abGroup: 'B', filterType: 'press' } if (author) { reqData.author = author reqData.actionPath = 'author' reqData.notSelectSearchMode = 'false' } else { reqData.notSelectSearchMode = 'true' } uni.request({ url: 'https://search.kongfz.com/pc-gw/search-web/client/pc/product/keyword/more/press/facet', method: 'GET', data: reqData, header: { 'Cookie': phpsessid ? `PHPSESSID=${phpsessid}` : '' }, success: (res) => { console.log('【孔网出版社搜索】URL: https://search.kongfz.com/pc-gw/search-web/client/pc/product/keyword/more/press/facet?keyword=' + encodeURIComponent(keyword) + '&page=1&size=50&userArea=' + userArea + '&filterType=press', '| 响应:', JSON.stringify(res.data)) if (res.statusCode === 200 && res.data && res.data.status === 1 && res.data.data) { var labels = res.data.data.labels || [] resolve(labels.map(function(item) { return { showName: item.showName, showValue: item.showValue } })) } else { resolve([]) } }, fail: () => { resolve([]) } }) }) } /** * 获取孔网作者列表(根据书名,可选按出版社过滤) * @param {string} keyword 书名 * @param {object} options { phpsessid, userArea, publisher } * @returns {Promise>} 作者列表 */ export function searchAuthors(keyword, options = {}) { const { phpsessid = '', userArea = '1006000000', publisher = '' } = options return new Promise((resolve) => { if (!keyword || !keyword.trim()) { resolve([]) return } var reqData = { requestId: Math.random().toString(36).substring(2, 10), platform: 'web', searchType: 'keyword', dataType: 0, keyword: keyword.trim(), hasStock: 'true', isNewBook: 'false', searchMode: 0, userArea: userArea, page: 1, size: 50, tplParams: '{}', sortType: 0, abGroup: 'B', filterType: 'author' } if (publisher) { reqData.press = publisher reqData.actionPath = 'press' reqData.notSelectSearchMode = 'false' } else { reqData.notSelectSearchMode = 'true' } uni.request({ url: 'https://search.kongfz.com/pc-gw/search-web/client/pc/product/keyword/more/author/facet', method: 'GET', data: reqData, header: { 'Cookie': phpsessid ? `PHPSESSID=${phpsessid}` : '' }, success: (res) => { console.log('【孔网作者搜索】URL: https://search.kongfz.com/pc-gw/search-web/client/pc/product/keyword/more/author/facet?keyword=' + encodeURIComponent(keyword) + '&page=1&size=50&userArea=' + userArea + '&filterType=author', '| 响应:', JSON.stringify(res.data)) if (res.statusCode === 200 && res.data && res.data.status === 1 && res.data.data) { var labels = res.data.data.labels || [] resolve(labels.map(function(item) { return { showName: item.showName } })) } else { resolve([]) } }, fail: () => { resolve([]) } }) }) } export default { login, searchFacet, fetchItems, searchProducts, searchCategories, searchPresses, searchAuthors }