Compare commits

...

29 Commits

Author SHA1 Message Date
4e480d35df Merge branch 'Branch_release/v1.4.1' 2026-04-09 15:54:51 +08:00
bc6d243362 chore: 2026-04-09 15:30:32 +08:00
a285706112 chore:用户隐私协议点击不同意后不会在弹出了 2026-04-09 14:56:49 +08:00
9c04c031ab chore:删除原来的多余的调动弹窗的代码 2026-04-09 10:40:43 +08:00
0ce929f8a1 chore:点击同意后,用户隐私不在弹出 2026-04-09 10:04:29 +08:00
61ab9f11bd chore:H5只弹一次,点击同意后就不弹了 2026-04-09 09:35:08 +08:00
2747cb49ae chore:弹出用户隐私 2026-04-08 18:20:03 +08:00
9c8ebf8d74 Merge branch 'main' of https://git.aigc-quickapp.com/Uniapp/lucky_shop 2026-04-08 15:02:08 +08:00
e19fef785f chore:改了commom 2026-04-08 14:39:23 +08:00
92ae114c5c chore: 2026-04-08 11:47:07 +08:00
b25c366a5b chore:增加了弹窗用户隐私 2026-04-08 11:37:29 +08:00
4ad93ceace refactor: 将视频标题样式绑定从对象改为数组 2026-02-07 18:11:42 +08:00
294856d9ef Merge branch 'test/diy-tabs' into dev/1.0 2026-02-07 17:53:30 +08:00
ba2c7d6d64 Revert "chore:点击中英文按钮不跳到‘我的’了"
This reverts commit 19a53ef414.
2026-02-07 17:51:10 +08:00
ec9e76fda7 chore:改了中英文模式 2026-02-07 16:53:40 +08:00
5dba8071e4 refactor(diy-tab): 统一样式绑定语法为数组形式
将模板中的样式绑定从对象展开语法改为数组形式,保持代码风格一致
2026-02-07 16:16:43 +08:00
19a53ef414 chore:点击中英文按钮不跳到‘我的’了 2026-02-07 16:10:55 +08:00
e943b11c8f fix(组件): 修复tab组件中子组件moduleIndex冲突问题
为tab组件中的子组件添加tabIndex前缀,避免不同tab页中子组件的moduleIndex冲突
2026-02-07 15:57:49 +08:00
e9db54980e refactor(diy-tab): 使用模板字符串和可选链优化key生成逻辑 2026-02-07 14:59:26 +08:00
3ddcc665b8 refactor(diy-tab): 统一使用生成函数获取tab和panel的key
使用getTabKey和getPanelKey方法统一生成key,提高代码可维护性
2026-02-07 14:11:51 +08:00
a981c02baf chore:智能客服页面右上角改成齿轮图标,更多功能图标改为(...) 2026-02-07 13:59:43 +08:00
1c3f759b35 feat: 为DIY标签组件添加可配置的动画效果 2026-02-07 11:41:59 +08:00
bb58866192 feat: 为标签组件添加悬停动画和对齐选项 2026-02-07 11:34:45 +08:00
069b3c2c07 feat: 为DIY标签页组件添加滚动容器和样式 2026-02-06 17:55:44 +08:00
6897fc631b feat: 重构DIY标签页组件,支持多种布局和样式配置 2026-02-06 16:47:32 +08:00
b23c21d05b Merge pull request 'fix/lang' (#4) from fix/lang into main
Reviewed-on: #4
2026-02-04 09:12:58 +00:00
65a24f25bb fix(lang): 提取getCurrentLocale为独立函数并优化代码格式
将getCurrentLocale方法提取为独立函数以避免重复代码
移除多余的空格并保持代码风格一致
2026-02-04 17:10:12 +08:00
2a0935b581 Merge pull request 'docs: 更新readme文档结构和内容' (#2) from dev/1.0 into main
Reviewed-on: #2
2026-01-24 09:41:36 +00:00
b31197a8b4 Merge pull request 'dev/1.0' (#1) from dev/1.0 into main
Reviewed-on: #1
2026-01-24 09:24:05 +00:00
11 changed files with 1415 additions and 721 deletions

View File

@@ -41,7 +41,13 @@ const localDevConfig = ({
'local-2': { // 测试平台
uniacid: 2,
domain: 'http://localhost:8050/',
},
})['1']; // 选择要使用的环境配置
'47': { // 修改弹窗
uniacid: 47,
domain: 'https://5g.aigc-quickapp.com/',
},
'2075': { //
uniacid: 2075,
domain: 'https://xcx.aigc-quickapp.com/',
},
})['47']; // 选择要使用的环境配置
export default localDevConfig;

View File

@@ -30,12 +30,12 @@ function processRoutePath(route) {
}
}
// ---- 处理页面目录映射 <end>----
// 去掉pages目录,只保留子目录
if (routeParts[0] === 'pages') {
routeParts = routeParts.slice(1);
}
}
return routeParts.join("/");
}
@@ -54,11 +54,14 @@ function loadLangPackSync(lang, path) {
}
}
/**
* 获得当前本地语言
* @returns
*/
function getCurrentLocale() {
return uni.getStorageSync('lang') || "zh-cn";
return uni.getStorageSync('lang') || "zh-cn";
}
export default {
langList: langConfig.langList,
@@ -77,18 +80,18 @@ export default {
if (!_page) return;
const locale = getCurrentLocale(); // 获得当前本地语言
let value = ''; // 存放解析后的语言值
let langPath = ''; // 存放当前页面语言包路径
try {
//公共语言包(同步加载)
var lang = loadLangPackSync(locale, 'common');
//当前页面语言包(同步加载)
let route = _page.route;
langPath = processRoutePath(route);
// 加载当前页面语言包
let currentPageLang = loadLangPackSync(locale, langPath);
@@ -113,7 +116,7 @@ export default {
} else {
value = mergedLang[field] !== undefined ? mergedLang[field] : field;
}
} catch (e) {
console.error('解析语言包失败:', e, { langPath, field, locale });
value = field;
@@ -129,7 +132,7 @@ export default {
// 多语言调试,注释后可以关闭控制台输出
if (field == value) {
console.warn(`警告: 字段 ${field} 在语言包 ${langPath} 中未找到对应值,使用默认值 ${field} 当前语言: ${locale}`);
console.warn(`警告: 字段 ${field} 在语言包 ${langPath} 中未找到对应值,使用默认值 ${field} 当前语言: ${locale}`);
}
return value;
@@ -165,7 +168,7 @@ export default {
if (!_page) return;
const locale = getCurrentLocale();
this.title(this.lang("title"));
//设置tabbar的文字语言
@@ -215,4 +218,4 @@ export default {
}
return list;
}
}
}

View File

@@ -14,7 +14,7 @@
</view>
<view class="video-info">
<!-- 视频标题,支持多行显示控制 -->
<view class="video-title" :style="{ '--title-line-clamp': titleLineClamp }">{{ value.videoTitle }}
<view class="video-title" :style="[{ '--title-line-clamp': titleLineClamp }]">{{ value.videoTitle }}
</view>
<!-- 视频统计信息 -->
<view class="video-stats" v-if="showViewCount && value.showViewCount">{{ value.viewCount }}次观看</view>
@@ -34,7 +34,7 @@
</view>
<view class="video-info">
<!-- 视频标题,支持多行显示控制 -->
<view class="video-title" :style="{ '--title-line-clamp': titleLineClamp }">{{ value.videoTitle }}
<view class="video-title" :style="[{ '--title-line-clamp': titleLineClamp }]">{{ value.videoTitle }}
</view>
<!-- 视频统计信息,非列表模式下显示 -->
<view class="video-stats" v-if="showViewCount && value.showViewCount && !listMode">{{ value.viewCount }}次观看</view>

View File

@@ -317,7 +317,12 @@ export default {
this.diyGlobalData.value.forEach((item, index) => {
item.pageStyle = '';
// 给每个组件增加位置属性,用于定位,搜索、分类导航等定位
item.moduleIndex = index + 1;
// 如果是Tab组件内部的子组件,添加tabIndex前缀避免moduleIndex冲突
if (this.diyData.tabIndex !== undefined) {
item.moduleIndex = `${this.diyData.tabIndex}-${index + 1}`;
} else {
item.moduleIndex = index + 1;
}
// 特殊处理搜索框 当显示位置为滚动至顶部固定时,只设置背景颜色
if (item.componentName == 'Search' && item.positionWay == 'fixed') {

File diff suppressed because it is too large Load Diff

View File

@@ -216,8 +216,15 @@ export default {
this.currentLangIndex = this.currentLangIndex === 0 ? 1 : 0;
const targetLang = this.langIndexMap[this.currentLangIndex];
// 调用语言切换逻辑(设置 storage + 清空缓存)
this.$langConfig.change(targetLang);
uni.setStorageSync("lang", targetLang);
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
const currentRoute = currentPage.route;
uni.reLaunch({
url: '/' + currentRoute
});
},
handleUnifiedKefuClick() {

View File

@@ -158,22 +158,48 @@ export default {
success: (res) => {
// console.log(res)
if (res.needAuthorization) {
this.popUp()
// 额外逻辑:当前页面的隐私弹窗弹起的时候,关掉其他页面的隐私弹窗
this.closeOtherPagePopUp(this.disPopUp)
// 检查本地存储中是否已经同意过隐私政策
const privacyAgreed = uni.getStorageSync('privacyAgreed');
if (!privacyAgreed) {
this.popUp()
// 额外逻辑:当前页面的隐私弹窗弹起的时候,关掉其他页面的隐私弹窗
this.closeOtherPagePopUp(this.disPopUp)
} else {
this.$emit('agree')
}
} else {
this.$emit('agree')
}
},
});
} else {
this.$emit('agree')
// 检查本地存储中是否已经同意过隐私政策
const privacyAgreed = uni.getStorageSync('privacyAgreed');
if (privacyAgreed) {
this.$emit('agree');
} else {
this.popUp()
// 额外逻辑:当前页面的隐私弹窗弹起的时候,关掉其他页面的隐私弹窗
this.closeOtherPagePopUp(this.disPopUp)
}
}
// #endif
// #ifdef QUICKAPP-WEBVIEW
this.getPrivacySettingByQuickApp();
// #endif
// #ifdef H5 || WEB
// 检查本地存储中是否已经同意过隐私政策
const privacyAgreed = uni.getStorageSync('privacyAgreed');
if (privacyAgreed) {
this.$emit('agree');
} else {
this.popUp()
// 额外逻辑:当前页面的隐私弹窗弹起的时候,关掉其他页面的隐私弹窗
this.closeOtherPagePopUp(this.disPopUp)
}
// #endif
},
//初始化监听程序
curPageShow() {
@@ -261,6 +287,8 @@ export default {
this.privacyResolves.clear()
//关闭弹窗
this.disPopUp()
// 保存用户授权状态到本地存储,无论同意还是不同意,都不再重复弹出
uni.setStorageSync('privacyAgreed', true);
//退出小程序
uni.showModal({
content: '未同意隐私协议,无法使用相关功能',
@@ -281,10 +309,8 @@ export default {
//关闭弹窗
this.disPopUp()
// #ifdef QUICKAPP-WEBVIEW || H5 || WEB
// 保存用户授权状态到本地存储,用于快应用Webview组件中的H5方式处理
// 保存用户授权状态到本地存储,用于所有环境
uni.setStorageSync('privacyAgreed', true);
// #endif
this.$emit('agree')
},
//打开弹窗

View File

@@ -17,10 +17,6 @@
}}</view>
</view>
<!-- <view class="page-header" v-if="diyData.global && diyData.global.navBarSwitch" :style="{ backgroundImage: bgImg }">
<ns-navbar :title-color="textNavColor" :data="diyData.global" :scrollTop="scrollTop" :isBack="false"/>
</view> -->
<diy-index-page v-if="topIndexValue" ref="indexPage" :value="topIndexValue" :bgUrl="bgUrl"
:scrollTop="scrollTop" :diyGlobal="diyData.global" class="diy-index-page">
<template v-slot:components>
@@ -43,35 +39,17 @@
<view @touchmove.prevent.stop>
<uni-popup ref="uniPopupWindow" type="center" class="wap-floating" :maskClick="false">
<view class="small-bot">
<!-- <view class="adver-time" wx:if="{{startadv.params.style=='default'&&startadv.params.canclose==1}}">
<view bindtap="adverclose">跳过</view>
<view class="time">{{clock}}s</view>
</view>
<view class="adver-time" wx:if="{{startadv.params.style=='default'&&startadv.params.canclose==0}}">
<view class="time" style="line-height: 64rpx;">{{clock}}s</view>
</view> -->
<swiper autoplay="true" :circular="true" indicator-active-color="#fff"
indicator-color="rgba(255,255,255,0.6)" :indicator-dots="true" interval="3000">
<swiper-item v-for="(item, index) in adv.list" :key="index">
<image class="slide-image" @click="$util.diyRedirectTo(item.link)" height="100%"
:src="$util.img(item.imageUrl)" width="100%"></image>
<!-- <image bindtap="adverclose" class="slide-image" height="100%" src="{{item.imgurl}}" width="100%" wx:if="{{item.click==1}}"></image> -->
</swiper-item>
</swiper>
<view bindtap="adverclose" class="small-bot-close" @click="closePopupWindow">
<i class="iconfont icon-round-close" style="color:#fff"></i>
</view>
</view>
<!-- <view class="image-wrap">
<swiper class="swiper" style="width:100%;height: 1200rpx;" :autoplay="true" interval="3000" circular="true" :indicator-dots="true" indicator-color="#000" indicator-active-color="red">
<swiper-item class="swiper-item" v-for="(item, index) in adv.list" :key="index" v-if="item.imageUrl" @click="$util.diyRedirectTo(item.link)">
<view class="item">
<image :src="$util.img(item.imageUrl)" mode="aspectFit" :show-menu-by-longpress="true"/>
</view>
</swiper-item>
</swiper>
</view>
<text class="iconfont icon-round-close" @click="closePopupWindow"></text> -->
</uni-popup>
</view>
</template>
@@ -101,7 +79,7 @@
</view>
</uni-popup>
<!-- 选择门店弹出框,定位当前位置,展示最近的一个门店 -->
<!-- 选择门店弹出框 -->
<view @touchmove.prevent.stop class="choose-store">
<uni-popup ref="chooseStorePopup" type="center" :maskClick="false" class="choose-store">
<view class="choose-store-popup">
@@ -136,8 +114,27 @@
</view>
</uni-popup>
</view>
<hover-nav :need="true"></hover-nav>
<!-- 隐私协议 -->
<!-- 隐私协议弹窗 UI (新增) -->
<view v-if="showPrivacyModal" class="privacy-modal-mask" @touchmove.prevent>
<view class="privacy-modal-container">
<view class="modal-header">用户隐私保护提示</view>
<view class="modal-body">
<text>感谢您使用本应用,在使用前您应当阅读并同意</text>
<text class="link" @click="viewPrivacy('privacy')">《隐私条款》</text>
<text class="link" @click="viewPrivacy('agreement')">《用户服务协议》</text>
<text>,当点击同意并继续时,即表示您已理解并同意该条款内容,该条款将对您产生法律约束力;如您不同意,将无法继续使用相关功能。</text>
</view>
<view class="modal-footer">
<view class="btn btn-disagree" @click="handleDisagree">不同意</view>
<view class="btn btn-agree" @click="handleAgree">同意并继续</view>
</view>
</view>
</view>
<!-- 隐私协议组件 (原有) -->
<privacy-popup ref="privacyPopup"></privacy-popup>
<to-top v-if="showTop" @toTop="scrollToTopNative()"></to-top>
<ns-login ref="login"></ns-login>
@@ -146,14 +143,132 @@
</template>
<script>
import diyJs from '@/common/js/diy.js';
import scroll from '@/common/js/scroll-view.js';
import indexJs from './public/js/index.js';
export default {
mixins: [diyJs, scroll, indexJs]
mixins: [diyJs, scroll, indexJs],
data() {
return {
minScrollTop: 100,
wechatQrcode: '',
diyRoute: '/pages/index/index',
showPrivacyModal: false // 新增:控制隐私弹窗显示
};
},
onLoad(option) {
// #ifdef H5
if (option.module && option.module == 'locationPicker') {
option.name = '';
}
// #endif
this.name = option.name || 'DIY_VIEW_INDEX';
},
onShow() {
this.getFollowQrcode();
// 页面显示时检查隐私设置
this.checkPrivacySetting();
},
mounted() {
this.unsubscribe = this.$eventBus?.onMany([
'rubik-cube-tap',
'picture-tap',
'text-tap',
'goods-list-tap',
'presale-tap',
'notes-tap',
'merch-list-tap',
'map-tap',
'img-ads-tap',
'many-goods-list-tap',
'search-tap',
], this._handleDiyGroupInteractionEvent);
},
beforeDestroy() {
if (this.unsubscribe) this.unsubscribe();
},
methods: {
// 检查隐私弹窗逻辑
checkPrivacySetting() {
// 模拟检查本地存储,看用户是否已经同意过
// 实际项目中请替换为你真实的存储逻辑
const hasAgreed = uni.getStorageSync('HAS_AGREED_PRIVACY');
if (!hasAgreed) {
// 延迟显示,防止遮挡页面渲染
setTimeout(() => {
this.showPrivacyModal = true;
}, 500);
}
},
// 用户点击同意
handleAgree() {
// 保存同意状态
uni.setStorageSync('HAS_AGREED_PRIVACY', true);
this.showPrivacyModal = false;
},
// 用户点击不同意
handleDisagree() {
// 微信小程序环境下,不同意通常退出小程序
// #ifdef MP-WEIXIN
uni.exitMiniProgram();
// #endif
// H5 或 App 下可以提示或直接不显示内容
// #ifndef MP-WEIXIN
uni.showToast({
title: '您已拒绝协议,无法使用',
icon: 'none',
duration: 2000
});
// 这里可以选择关闭页面或保持弹窗
// this.showPrivacyModal = false;
// #endif
},
// 查看具体条款(可选功能)
viewPrivacy(type) {
// 这里可以跳转到具体的条款页面,或者使用你现有的 privacy-popup 组件
// 假设你有现成的组件逻辑:
if (this.$refs.privacyPopup) {
// 假设 privacy-popup 组件有一个 show 方法
// this.$refs.privacyPopup.show(type);
}
uni.showToast({
title: '请在此处实现查看条款逻辑',
icon: 'none'
});
},
getFollowQrcode() {
if (!this.$util.isWeiXin()) return;
this.$api.sendRequest({
url: '/wechat/api/wechat/followqrcode',
success: res => {
if (res.code >= 0 && res.data) {
this.wechatQrcode = res.data.qrcode;
}
}
});
},
officialAccountsOpen() {
this.$refs.officialAccountsPopup.open();
},
officialAccountsClose() {
this.$refs.officialAccountsPopup.close();
},
_handleDiyGroupInteractionEvent(payload) {
// #ifdef H5
return true;
// #endif
if (this.storeToken) {
return true;
}
this.$refs.login?.open();
return false;
}
}
};
</script>
@@ -199,6 +314,74 @@ export default {
.small-bot-close i {
font-size: 60rpx;
}
/* 新增:隐私弹窗样式 */
.privacy-modal-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.6); // 半透明背景
z-index: 9999; // 确保层级最高
display: flex;
justify-content: center;
align-items: center;
}
.privacy-modal-container {
width: 80%;
background-color: #ffffff;
border-radius: 12rpx;
padding: 40rpx 30rpx;
text-align: center;
}
.modal-header {
font-size: 36rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
}
.modal-body {
font-size: 28rpx;
color: #666;
line-height: 1.6;
text-align: left;
margin-bottom: 30rpx;
}
.link {
color: #007aff; // 蓝色链接
margin: 0 4rpx;
}
.modal-footer {
display: flex;
justify-content: space-between;
padding: 0 20rpx;
}
.btn {
flex: 1;
height: 80rpx;
line-height: 80rpx;
border-radius: 40rpx;
font-size: 30rpx;
text-align: center;
margin: 0 15rpx;
}
.btn-disagree {
background-color: #f5f5f5;
color: #333;
}
.btn-agree {
background-color: #07c160; // 微信绿
color: #fff;
}
</style>
<style scoped>
.swiper ::v-deep .uni-swiper-dots-horizontal {

View File

@@ -1,82 +1,95 @@
export default {
data() {
return {
minScrollTop: 100, // 设置回到顶端按钮显示要求,最小页面滚动距离
wechatQrcode: '', // 公众号二维码
diyRoute: '/pages/index/index'
};
},
onLoad(option) {
// #ifdef H5
// H5地图选择位置回调数据
if (option.module && option.module == 'locationPicker') {
option.name = ''; // 清空地址
}
// #endif
this.name = option.name || 'DIY_VIEW_INDEX'; // 根据店铺运营模式,打开平台(shop)或者连锁门店(stroe)页面,接口会自行判断
data() {
return {
minScrollTop: 100, // 设置回到顶端按钮显示要求,最小页面滚动距离
wechatQrcode: "", // 公众号二维码
diyRoute: "/pages/index/index",
};
},
onLoad(option) {
// #ifdef H5
// H5地图选择位置回调数据
if (option.module && option.module == "locationPicker") {
option.name = ""; // 清空地址
}
// #endif
this.name = option.name || "DIY_VIEW_INDEX"; // 根据店铺运营模式,打开平台(shop)或者连锁门店(stroe)页面,接口会自行判断
},
onShow() {
// 获取关注公众号二维码
this.getFollowQrcode();
// 检查隐私设置并显示弹窗
this.checkPrivacySetting();
},
mounted() {
// 监听图片、文字、商品列表等组件的点击事件
this.unsubscribe = this.$eventBus?.onMany(
[
"rubik-cube-tap",
"picture-tap",
"text-tap",
"goods-list-tap",
"presale-tap",
"notes-tap",
"merch-list-tap",
"map-tap",
"img-ads-tap",
"many-goods-list-tap",
"search-tap",
],
this._handleDiyGroupInteractionEvent,
);
},
beforeDestroy() {
// 移除图片点击事件监听
if (this.unsubscribe) this.unsubscribe();
},
methods: {
// 检查隐私设置
checkPrivacySetting() {
// 延迟执行,确保组件已经挂载
setTimeout(() => {
if (this.$refs.privacyPopup) {
this.$refs.privacyPopup.proactive();
}
}, 100);
},
// 关注公众号
getFollowQrcode() {
if (!this.$util.isWeiXin()) return;
this.$api.sendRequest({
url: "/wechat/api/wechat/followqrcode",
success: (res) => {
if (res.code >= 0 && res.data) {
this.wechatQrcode = res.data.qrcode;
}
},
});
},
officialAccountsOpen() {
this.$refs.officialAccountsPopup.open();
},
officialAccountsClose() {
this.$refs.officialAccountsPopup.close();
},
// 统一处理点击及触摸事件
_handleDiyGroupInteractionEvent(payload) {
// #ifdef H5
// 如果是 H5 环境,直接返回 true 继续传播
return true;
// #endif
},
onShow() {
// 获取关注公众号二维码
this.getFollowQrcode();
},
mounted() {
// 监听图片、文字、商品列表等组件的点击事件
this.unsubscribe = this.$eventBus?.onMany([
'rubik-cube-tap',
'picture-tap',
'text-tap',
'goods-list-tap',
'presale-tap',
'notes-tap',
'merch-list-tap',
'map-tap',
'img-ads-tap',
'many-goods-list-tap',
'search-tap',
], this._handleDiyGroupInteractionEvent);
},
beforeDestroy() {
// 移除图片点击事件监听
if (this.unsubscribe) this.unsubscribe();
},
methods: {
// 关注公众号
getFollowQrcode() {
if (!this.$util.isWeiXin()) return;
this.$api.sendRequest({
url: '/wechat/api/wechat/followqrcode',
success: res => {
if (res.code >= 0 && res.data) {
this.wechatQrcode = res.data.qrcode;
}
}
});
},
officialAccountsOpen() {
this.$refs.officialAccountsPopup.open();
},
officialAccountsClose() {
this.$refs.officialAccountsPopup.close();
},
// 统一处理点击及触摸事件
_handleDiyGroupInteractionEvent(payload) {
// #ifdef H5
// 如果是 H5 环境,直接返回 true 继续传播
return true;
// #endif
// 如果已登录,直接返回 true 继续传播
if (this.storeToken) {
return true;
}
// 如果已登录,直接返回 true 继续传播
if (this.storeToken) {
return true;
}
// 打开登录弹窗
// console.log('==> _handleDiyGroupInteractionEvent, 未登录,打开登录弹窗', { payload })
this.$refs.login?.open();
// 打开登录弹窗
// console.log('==> _handleDiyGroupInteractionEvent, 未登录,打开登录弹窗', { payload })
this.$refs.login?.open();
// 阻止事件继续传播
return false;
}
}
}
// 阻止事件继续传播
return false;
},
},
};

View File

@@ -183,7 +183,7 @@
<view class="input-area">
<view class="input-tools">
<button class="tool-btn" @click="showMoreTools">
<text class="iconfont icon-plus">📌</text>
<text class="iconfont icon-plus">...</text>
</button>
<button class="tool-btn" @click="toggleVoiceInput">
<text class="iconfont" :class="voiceInputing ? 'icon-stop' : 'icon-voice'">🎤</text>
@@ -2070,6 +2070,7 @@ $radius-lg: 36rpx;
.input-tools {
display: flex;
margin-bottom: 16rpx;
align-items: flex-start;
.tool-btn {
width: 64rpx;
@@ -2077,6 +2078,7 @@ $radius-lg: 36rpx;
border-radius: 50%;
background-color: $bg-main;
margin-right: 16rpx;
margin-top: -8rpx;
display: flex;
align-items: center;
justify-content: center;

View File

@@ -14,7 +14,7 @@
</view>
<view class="header-right">
<button class="menu-btn" v-show="showMenuButton" @click="showMenu">
<text class="iconfont icon-ellipsis"></text>
<text>⚙️</text>
</button>
<!-- 占位元素,确保布局平衡 -->
<view v-show="!showMenuButton" class="placeholder"></view>