diff --git a/.local.config.js b/.local.config.js index 28cf028..6386cb0 100644 --- a/.local.config.js +++ b/.local.config.js @@ -38,6 +38,10 @@ const localDevConfig = ({ uniacid: 1, domain: 'https://test.aigc-quickapp.com', }, + 'local-2': { // 测试平台 + uniacid: 2, + domain: 'http://localhost:8050/', + }, })['2811']; // 选择要使用的环境配置 export default localDevConfig; \ No newline at end of file diff --git a/.local.config.js.example b/.local.config.js.example index 6386cb0..92772a3 100644 --- a/.local.config.js.example +++ b/.local.config.js.example @@ -18,6 +18,10 @@ const localDevConfig = ({ uniacid: 2811, domain: 'https://xcx6.aigc-quickapp.com/', }, + '2812': { // IVD数商模式 + uniacid: 2812, + domain: 'https://xcx6.aigc-quickapp.com/', + }, '2724': { // 生物菌肥 uniacid: 2724, domain: 'https://xcx.aigc-quickapp.com/', @@ -42,6 +46,10 @@ const localDevConfig = ({ uniacid: 2, domain: 'http://localhost:8050/', }, -})['2811']; // 选择要使用的环境配置 + 'local-2-dev': { // 本地开发测试平台 + uniacid: 2, + domain: 'http://localhost:8050/', + }, +})['2812']; // 选择要使用的环境配置 export default localDevConfig; \ No newline at end of file diff --git a/common/js/uniapp.utils.js b/common/js/uniapp.utils.js index e450d28..2034bd9 100644 --- a/common/js/uniapp.utils.js +++ b/common/js/uniapp.utils.js @@ -6,13 +6,23 @@ /** * 显示错误信息 * @param {Exception} err + * @param {Boolean} useModal */ -const showError = (err) => { - uni.showToast({ - title: err?.message || err?.errMsg || err?.toString(), - icon: 'none', - duration: 2000 - }); +const showError = (err, useModal = false) => { + const content = err?.message || err?.errMsg || err?.toString(); + if (!useModal) { + uni.showToast({ + title: content, + icon: 'none', + duration: 3000 + }); + } else { + uni.showModal({ + title: '错误提示', + content, + showCancel: false, + }) + } } /** @@ -33,43 +43,92 @@ export const makePhoneCall = (mobile) => { } /** - * 拷贝文本 + * 拷贝文本(返回 Promise) * @param {*} text * @param {*} options + * @returns {Promise} 返回 Promise,成功时 resolve,失败时 reject */ -export const copyText = (text, { copySuccess = '', copyFailed = '' } = {}) => { - try { - console.log('copyText'); - uni.setClipboardData({ - data: `${text}`, - success: () => { - console.error('复制成功'); - try { - uni.showToast({ - title: copySuccess, - icon: 'success', - duration: 2000 - }); - } catch (e) { - showError(e); +export const copyTextAsync = (text, { copySuccess = '', copyFailed = '' } = {}) => { + return new Promise((resolve, reject) => { + // 输入验证 + if (!text && text !== '') { + const error = new Error('复制文本不能为空'); + showError(error); + reject(error); + return; + } + + // 超时监测 + const timeoutId = setTimeout(() => { + let error = new Error('复制操作长时间无响应,请检查相关权限及配置是否正确'); + // #ifdef MP-WEIXIN + error = new Error([ + '复制操作长时间无响应!', + '原因:', + '1.微信平台->用户隐私保护指引->"剪贴板"功能未添加或审核未通过;', + '2.微信平台对剪贴板API调用频率有限制' + ].join('\r\n')); + // #endif + showError(error, true); + reject(error); + }, 5000); + + try { + uni.setClipboardData({ + data: `${text}`, + success: (res) => { + clearTimeout(timeoutId); + + try { + if (copySuccess) { + uni.showToast({ + title: copySuccess, + icon: 'success', + duration: 2000 + }); + } + } catch (e) { + showError(e); + } + + resolve(res); + }, + fail: (err) => { + clearTimeout(timeoutId); + try { + uni.showToast({ + title: err.message || err.errMsg || copyFailed || '复制失败', + icon: 'none', + duration: 2000 + }); + } catch (e) { + showError(e); + } + reject(err); } - }, - fail: (err) => { - console.error('复制失败:', err); - try { - uni.showToast({ - title: err.message || err.errMsg || copyFailed, - icon: 'none', - duration: 2000 - }); - } catch (e) { - showError(e); - } - } + }); + } catch (err) { + clearTimeout(timeoutId); + showError(err); + reject(err); + } + }); +} + +/** + * 拷贝文本(回调形式,兼容旧代码) + * @param {*} text + * @param {*} options + * @param {Function} callback 回调函数,接收 (success, error) 参数 + */ +export const copyText = (text, options = {}, callback) => { + copyTextAsync(text, options) + .then(res => { + if (callback) callback(true, null); + }) + .catch(err => { + if (callback) callback(false, err); }); - } catch (err) { - showError(err); - } } /** diff --git a/common/js/util.js b/common/js/util.js index 21b3588..59114f2 100644 --- a/common/js/util.js +++ b/common/js/util.js @@ -843,6 +843,15 @@ export default { uni.navigateBack(); } }, + /** + * 隐藏“返回首页/小房子”按钮 + * 这个函数,用到页面show, onshow 的生命周期时 + */ + hideHomeButton() { + // #ifdef MP-WEIXIN + wx.hideHomeButton(); + // #endif + }, /** * * @param val 转化时间字符串 (转化时分秒) diff --git a/components-diy/diy-map.vue b/components-diy/diy-map.vue index a0e1fb5..cd705d4 100644 --- a/components-diy/diy-map.vue +++ b/components-diy/diy-map.vue @@ -3,11 +3,18 @@ - 一键导航 - + --> + + +
+ 一键导航 +
diff --git a/manifest.json b/manifest.json index 6a72520..4beada8 100644 --- a/manifest.json +++ b/manifest.json @@ -104,7 +104,7 @@ }, "router" : { "mode" : "history", - "base" : "/hwappx/common/" + "base" : "/hwappx/2811/" }, "title" : "", "devServer" : { diff --git a/package.json b/package.json index 3c45a8f..c82e734 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,9 @@ { "scripts": { - "mp-weixin": "node scripts/mp-weixin.patch.js" + "mp-weixin": "node scripts/mp-weixin.patch.js", + "mp-weixin:patch": "node scripts/mp-weixin.patch.js --no-zip", + "mp-weixin:dev": "node scripts/mp-weixin.patch.js --mode development", + "mp-weixin:dev:patch": "node scripts/mp-weixin.patch.js --mode development --no-zip" }, "devDependencies": { "dart-sass": "^1.25.0", diff --git a/pages_goods/category.vue b/pages_goods/category.vue index 9edb1b9..be21c82 100644 --- a/pages_goods/category.vue +++ b/pages_goods/category.vue @@ -30,13 +30,13 @@ export default { }; }, onLoad() { + this.$util.hideHomeButton(); //刷新多语言 this.$langConfig.refresh(); - - uni.hideTabBar(); this.getDiyInfo(); }, onShow() { + this.$util.hideHomeButton(); if (this.$refs.category) this.$refs.category[0].pageShow(); }, onUnload() { diff --git a/pages_tool/agreement/contenr.vue b/pages_tool/agreement/contenr.vue index 0477a08..4d0f37f 100644 --- a/pages_tool/agreement/contenr.vue +++ b/pages_tool/agreement/contenr.vue @@ -1,52 +1,187 @@ - \ No newline at end of file diff --git a/pages_tool/ai-chat/ai-chat-message.vue b/pages_tool/ai-chat/ai-chat-message.vue index 22f1346..a9f68fc 100644 --- a/pages_tool/ai-chat/ai-chat-message.vue +++ b/pages_tool/ai-chat/ai-chat-message.vue @@ -10,8 +10,7 @@ - + @@ -392,6 +391,19 @@ export default { isFetchingHistory: false } }, + computed: { + // 为每条消息生成兼容小程序的唯一 key + messagesWithKey() { + return this.messages.map((msg, idx) => { + const uniqueId = msg.id || msg.timestamp || idx; + return { + ...msg, + __renderKey: `msg_${uniqueId}_${idx}`, + __index: idx // 保留原始索引,用于判断 first-message 等 + }; + }); + } + }, onShow() { // 优先读取本地缓存的会话 ID const localConvId = this.getConversationIdFromLocal(); diff --git a/pages_tool/contact/contact.vue b/pages_tool/contact/contact.vue index 08ece5a..9b97a97 100644 --- a/pages_tool/contact/contact.vue +++ b/pages_tool/contact/contact.vue @@ -252,6 +252,7 @@ export default { }; }, onLoad(option) { + this.$util.hideHomeButton(); this.$langConfig.refresh(); this.$api.sendRequest({ url: '/api/member/personnel', @@ -301,6 +302,9 @@ export default { fail: res => { } }); }, + onShow() { + this.$util.hideHomeButton(); + }, methods: { // 分享文件 shareFile(file) { diff --git a/pages_tool/member/index.vue b/pages_tool/member/index.vue index 499ee06..27081c1 100644 --- a/pages_tool/member/index.vue +++ b/pages_tool/member/index.vue @@ -86,6 +86,12 @@ export default { nsNewGift }, mixins: [diyJs, indexJs], + onLoad() { + this.$util.hideHomeButton(); + }, + onShow() { + this.$util.hideHomeButton(); + }, methods: { tourl(url) { diff --git a/project.config.json b/project.config.json index 7126295..776d6c4 100644 --- a/project.config.json +++ b/project.config.json @@ -1,12 +1,13 @@ { "description": "项目配置文件", "packOptions": { - "ignore": [] + "ignore": [], + "include": [] }, "setting": { "urlCheck": true, "es6": true, - "enhance": false, + "enhance": true, "postcss": true, "preloadBackgroundData": false, "minified": true, @@ -37,7 +38,15 @@ "userConfirmedBundleSwitch": false, "packNpmManually": false, "packNpmRelationList": [], - "minifyWXSS": true + "minifyWXSS": true, + "condition": true, + "swc": false, + "disableSWC": true, + "minifyWXML": true, + "compileWorklet": true, + "localPlugins": false, + "disableUseStrict": false, + "useCompilerPlugins": false }, "compileType": "miniprogram", "libVersion": "2.16.1", diff --git a/project.private.config.json b/project.private.config.json index cd9faf2..ba3edb6 100644 --- a/project.private.config.json +++ b/project.private.config.json @@ -1,6 +1,6 @@ { "libVersion": "3.12.0", - "projectname": "lucky_shop", + "projectname": "mp-weixin", "condition": {}, "setting": { "urlCheck": true, diff --git a/readme.md b/readme.md index a9279d0..eeb484c 100644 --- a/readme.md +++ b/readme.md @@ -1,7 +1,5 @@ # 小程序及快应用前端源码 -来源于外包提供的源代码,"0731xcx20微信小程序(1).zip" - ## 项目说明 @@ -9,7 +7,7 @@ ## 开发说明 -1. 源码基于Vue2版本,scss采用node-sass进行编译输出。 + 源码基于Vue2版本,scss采用dart-sass进行编译输出。 ## 开发调试说明 @@ -18,7 +16,7 @@ 应用访问等关键参数的配置来源于 `./common/js/config.js` -### 小程序调试 + @@ -26,151 +24,90 @@ ### 小程序发布 -基本操作步骤: - -1. 使用HBuilderX打开项目 -2. 选择菜单栏 "发行" -> "小程序-微信",进行发布构建 -3. 然后在终端进入项目根目录,执行 `npm run mp-weixin` 手动输出构建包。例如:mp-weixin-2025-10-31-1761881054836.zip(改id) -4. 然后将mp-weixin-2025-10-31-1761881054836发给微信开发定制客户技术人员, -5. 定制客户技术人员可以修改解压后,修改项目根目录下的site.js,进行针对客户的信息配置,然后使用微信开发者工具打开发布后的代码进行上传发布 - -参照:`common\js\config.js` 文件内容说明: - -```js -// 发行版本,配置说明 -let releaseCfg = undefined; -try { - if (site) { - releaseCfg = { - baseUrl: site.baseUrl, - imgDomain: site.baseUrl, - h5Domain: site.baseUrl, - uniacid: site.uniacid, - } - } -} catch (e) {} - -// 调试版本,配置说明 -const devCfg = { - // 商户ID - uniacid: 460, //825 - - //api请求地址 - baseUrl: 'https://xcx30.5g-quickapp.com/', - - // 图片域名 - imgDomain: 'https://xcx30.5g-quickapp.com/', - - // H5端域名 - h5Domain: 'https://xcx30.5g-quickapp.com/', - - // // api请求地址 - // baseUrl: 'https://tsaas.liveplatform.cn/', - - // // 图片域名 - // imgDomain: 'https://tsaas.liveplatform.cn/', - - // // H5端域名 - // h5Domain: 'https://tsaas.liveplatform.cn/', - - // api请求地址 - // baseUrl: 'http://saas.cn/', - - // // 图片域名 - // imgDomain: 'http://saas.cn/', - - // // H5端域名 - // h5Domain: 'http://saas.cn/', -}; - -var config = { - /** - * 1.开发调试模式 - * 去掉注释 ...devCfg; - * 注释掉 ...releaseCfg, - * 2.发行/发布模式,例如通过`HBuilder>发行>小程序微信`的时候,原理 - * 然后将 `import site from "../site.js";`追加到 `unpackage\dist\build\mp-weixin\common\vendor.js` 文件内容开头部分 - * 然后将 site.js 文件放到 `unpackage\dist\build\mp-weixin\` 目录下面 - */ - ...(releaseCfg ?? devCfg), - // 腾讯地图key - mpKey: 'TUHBZ-CNWKU-UHAVP-GZQ26-HNZFO-3YBF4', +#### 基本操作步骤:(通用版/定制化版) + +#### 【前置准备】 +1. 在项目根目录打开终端安装依赖“npm install”(已有依赖可跳过此步骤)。 +#### 【发布构建】 +2. 使用HBuilderX打开项目; +3. 选择菜单栏「发行」 → 「小程序-微信」→ 「发行」,等待构建完成。(⚠️注:底部控制台弹出"请在微信小程序开发者工具中点击上传"后再执行下一步); +4. 打开资源管理器→项目根目录,右键选择「在终端中打开」,执行"npm run mp-weixin"命令并回车; + +5. 找到项目根目录 /unpackage/dist/build 下生成的 mp-weixin 压缩包 + +💡例如:mp-weixin-2026-01-23-1769152056146.zip;同时该目录下会生成未压缩的 mp-weixin 目录。 + +#### 【验证与重命名】 +6. 打开该目录下同时生成未压缩的 mp-weixin 目录,找到site.js文件,将文件内的uniacid值改为当前客户编号(如:2812)并保存; +7. 打开微信开发者工具,导入「mp-weixin」目录,点击「编译」,在开发者工具控制台验证有无报错,以及能否返回对应客户的业务数据; + +8. 确保无误后将生成的mp-weixin的压缩包重命名,格式为:定制化-客户编号-域名-mp-weixin-当前日期-生成编号.zip。 +***(📌通用版无需重命名)*** + +💡例如:custom-2812-xcx.aigc-quickapp.com-mp-weixin-2026-01-22-1769152056146.zip + +🚫压缩包命名禁止包含 / \ : * ? " < > | 等特殊字符。 + + +#### 【交付与最终发布】🔍🔍 +9. 将重命名后的文件发送给技术人员; ***(📌通用版直接将生成的 mp-weixin 压缩包直接发送给技术人员)*** + +10. 技术人员操作:解压压缩包 → 确认site.js中的uniacid为客户编号 → 用微信开发者工具导入解压后的代码目录 → 编译验证无误后 → 上传发布。 - //客服地址 - webSocket: '{{$webSocket}}', - //本地端主动给服务器ping的时间, 0 则不开启 , 单位秒 - pingInterval: 1500, - // 版本号 - version: '1.0' -}; -export default config; -``` ### 快应用发布 -1. 使用HBuilderX打开项目 -2. 点击项目中【⚙】manifest.jion--->web配置--->运行的基础路径--->/hwappx/改编号/ -"h5" : { - "sdkConfigs" : { - "maps" : { - "qqmap" : { - "key" : "TUHBZ-CNWKU-UHAVP-GZQ26-HNZFO-3YBF4" - } - } - }, - "router" : { - "mode" : "history", - "base" : "/hwappx/2811/" - }, - -(编号可以在.local.config.js中找到需要的编号) -const localDevConfig = ({ - '460': { // 制氧设备平台 - uniacid: 460, - domain: 'https://xcx30.5g-quickapp.com/', - }, - '576-xcx30.5g': { // 活性石灰装备 - uniacid: 576, - domain: 'https://xcx30.5g-quickapp.com/', - }, - '2285': { // 数码喷墨墨水 - uniacid: 2285, - domain: 'https://xcx.aigc-quickapp.com/', - }, - '2811': { // POCT检测分析平台 - uniacid: 2811, - domain: 'https://xcx6.aigc-quickapp.com/', - }, - '2724': { // 生物菌肥 - uniacid: 2724, - domain: 'https://xcx.aigc-quickapp.com/', - }, - '2505': { // 煤矿钻机 - uniacid: 2505, - domain: 'https://xcx.aigc-quickapp.com/', - }, - '2777': { // 养老服务 - uniacid: 2777, - domain: 'https://xcx.aigc-quickapp.com/', - }, - '1': { // 开发平台 - uniacid: 1, - domain: 'https://dev.aigc-quickapp.com', - }, - '1-test': { // 测试平台 - uniacid: 1, - domain: 'https://test.aigc-quickapp.com', - }, -})['2811']; // 选择要使用的环境配置 -3. 选择菜单栏 "发行" ->自定义发行--->H5-xcx.aigc-quickapp.com "快应用",网站标题为"快应用" 域名为xcx.aigc-quickapp.com 进行发布构建 -4. 在电脑本地文件夹里找到unpackage--->dist--->build--->h5中h5-xcx.aigc-quickapp.com--->进行手动打包,例如:static.zip -(压缩包改id 公版--例如 hwappx-common-xcx.aigc-quickapp.com-2026-01-09.zip - 定制化--例如 POCT检测分析平台-定制化--- hwappx-2811-xcx.aigc-quickapp.com-2026-01-09.zip) -5. 然后将压缩包发给开发定制客户技术人员, -6. 使用快应用开发者工具打开发布后的代码进行上传发布 \ No newline at end of file + +#### 基本操作(通用版/定制化版) + + + +#### 【发布构建】 +1. 使用HBuilderX打开项目; + +2. 打开项目根目录的manifest.json文件,切换至可视化配置界面:依次点击「Web 配置」→「运行的基础配置」,修改路径中的客户编号;***(📌通用版保留原有/hwappx/common/)*** + +💡例如:/hwappx/2811/,其中2811为定制化版客户编号; + +3. 选择菜单栏「发行」 → 「自定义发行」 →「H5-xcx.aigc-quickapp.com」,先修改以下配置: +网站标题:快应用 +网站域名:当前客户域名(示例:xcx.aigc-quickapp.com) +确认后点击「发行」等待构建完成。 + +⚠️注:底部控制台弹出“项目 lucky_shop 导出Web成功,路径为:D:\项目文件\项目根目录\unpackage\dist\build\web”后再执行下一步 + +💡例如:项目 lucky_shop 导出Web成功,路径为:D:\0.项目源码\lucky_shop\unpackage\dist\build\web + +4. 按控制台提示的路径找到web目录,将该目录下所有文件手动打包成一个.zip压缩包(仅打包文件,不包含外层web目录); + +#### 【重命名】 +5. 按版本类型规范重命名压缩包: + +📌通用版:hwappx-common-域名-时间.zip +例如: hwappx-common-xcx.aigc-quickapp.com-2026-01-24.zip + +📌定制化:客户名称-定制化---hwappx-客户编号-域名-时间.zip + 例如:POCT检测分析平台-定制化---hwappx-2811-xcx.aigc-quickapp.com-2026-01-24.zip + +🚫压缩包命名禁止包含 / \ : * ? " < > | 等特殊字符 + +#### 【交付与最终发布】🔍🔍 +6. 将重命名后的压缩包发送给运维人员; + +7. 运维人员操作: + +① 解压压缩包; + +② 打开快应用开发者工具,导入解压后的代码目录; + +③ 验证代码无报错后,执行上传发布操作。 + + + + diff --git a/scripts/mp-weixin.patch.js b/scripts/mp-weixin.patch.js index c3c0de9..43f5032 100644 --- a/scripts/mp-weixin.patch.js +++ b/scripts/mp-weixin.patch.js @@ -9,7 +9,10 @@ * 如果这个文件开头已经有了这行代码,则不追加 * * 使用: - * node fix-wechat-miniapp.js + * node fix-wechat-miniapp.js # 打补丁并创建 ZIP 文件(默认 mode=production) + * node fix-wechat-miniapp.js --no-zip # 只打补丁,不创建 ZIP 文件 + * node fix-wechat-miniapp.js --mode development # 使用 development 模式打补丁 + * node fix-wechat-miniapp.js --mode production # 使用 production 模式打补丁(默认) * * 注意: * - 在 Windows 上路径使用反斜杠也是可以的;脚本使用 path.join 来兼容不同平台。 @@ -29,8 +32,6 @@ async function commonPatch(mode = 'production') { // 根据当前脚本所在目录(scripts),定位到项目根目录 const cwd = path.join(__dirname, '..'); - - const srcSitePath = path.join(cwd, 'site.js'); const destDir = path.join(cwd, 'unpackage', 'dist', mode === 'production' ? 'build' : 'dev', 'mp-weixin'); const destSitePath = path.join(destDir, 'site.js'); @@ -47,6 +48,22 @@ async function commonPatch(mode = 'production') { // 确保目标目录存在 await ensureDir(destDir); + // 复制 project.config.json 及 project.private.config.json 文件到 destDir 下面 + const configFiles = ['project.config.json', 'project.private.config.json']; + for (const fileName of configFiles) { + const srcPath = path.join(cwd, fileName); + const destPath = path.join(destDir, fileName); + + // 检查源文件是否存在 + const fileExists = await exists(srcPath); + if (fileExists) { + await fsp.copyFile(srcPath, destPath); + console.log(`已拷贝: ${srcPath} -> ${destPath}`); + } else { + console.warn(`源文件不存在,跳过复制: ${srcPath}`); + } + } + // 复制 site.js 到目标目录(覆盖) await fsp.copyFile(srcSitePath, destSitePath); console.log(`已拷贝: ${srcSitePath} -> ${destSitePath}`); @@ -96,22 +113,37 @@ async function commonPatch(mode = 'production') { } } - - async function main() { + // 解析命令行参数 + const argv = process.argv.slice(2); + const options = { + noZip: argv.includes('--no-zip'), + mode: 'production' // 默认值 + }; + + // 解析 --mode 参数 + const modeIndex = argv.indexOf('--mode'); + if (modeIndex !== -1 && modeIndex + 1 < argv.length) { + options.mode = argv[modeIndex + 1]; + } + // 1) 打补丁 - await commonPatch('production'); + await commonPatch(options.mode); // await commonPatch('development'); - // 2) 创建 ZIP 文件 - const cwd = path.join(__dirname, '..'); - const sourceDir = path.join(cwd, 'unpackage', 'dist', 'build', 'mp-weixin'); - const destDir = path.join(cwd, 'unpackage', 'dist', 'build'); - const zipFilePath = await createZipWithSystemCommand(sourceDir, destDir); - console.log(`ZIP 文件路径: ${zipFilePath}`); + // 2) 创建 ZIP 文件(如果未指定 --no-zip) + if (!options.noZip) { + const cwd = path.join(__dirname, '..'); + const sourceDir = path.join(cwd, 'unpackage', 'dist', 'build', 'mp-weixin'); + const destDir = path.join(cwd, 'unpackage', 'dist', 'build'); + const zipFilePath = await createZipWithSystemCommand(sourceDir, destDir); + console.log(`ZIP 文件路径: ${zipFilePath}`); - // 3) 自动打开zip所在的目录 - await openFileDirectory(zipFilePath); + // 3) 自动打开zip所在的目录 + await openFileDirectory(zipFilePath); + } else { + console.log('跳过创建 ZIP 文件和打开目录'); + } } async function exists(p) {