2100 lines
63 KiB
Vue
2100 lines
63 KiB
Vue
<template>
|
||
<view class="u-page">
|
||
<!-- 账号密码模块 -->
|
||
<view class="u-demo-block">
|
||
<view v-if="!isLoggedIn">
|
||
<view class="section-header custom-layout">
|
||
<text class="section-title" style="flex: 1; min-width: 200rpx; white-space: nowrap;">账号密码</text>
|
||
<text class="section-subtitle"
|
||
style="flex: 1; text-align: right; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">输入孔网账号密码</text>
|
||
</view>
|
||
<view class="login-form-row">
|
||
<!-- 用户名输入框 -->
|
||
<u--input placeholder="请输入账号" v-model="username" class="login-input"></u--input>
|
||
<!-- 密码输入框 -->
|
||
<u--input placeholder="请输入密码" type="password" v-model="password" class="login-input"></u--input>
|
||
|
||
<!-- 登录按钮 -->
|
||
<button text="登录" size="mini" @click="login" :loading="isLoading" :disabled="isLoading"
|
||
:customStyle="{
|
||
flex: '1',
|
||
minWidth: '80rpx',
|
||
maxWidth: '80rpx',
|
||
whiteSpace: 'nowrap',
|
||
height: '70rpx',
|
||
backgroundColor: isLoading ? '#e0e0e0' : '#ffffff'
|
||
}">{{ isLoading ? '正在登录...' : '登录' }}</button>
|
||
</view>
|
||
<!-- 记住密码选项 -->
|
||
<view class="remember-password">
|
||
<checkbox-group @change="handleRememberPasswordChange">
|
||
<label class="checkbox-label">
|
||
<checkbox :checked="rememberPassword" value="1" style="transform:scale(0.7)" color="#007AFF" />
|
||
<text>记住密码</text>
|
||
</label>
|
||
</checkbox-group>
|
||
</view>
|
||
</view>
|
||
<!-- 用户信息展示 -->
|
||
<view v-else class="user-info">
|
||
<view class="user-avatar">
|
||
<image :src="userInfo && userInfo.photo ? userInfo.photo : '/static/admin-avatar.png'"
|
||
mode="aspectFill"></image>
|
||
</view>
|
||
<view class="user-details">
|
||
<text class="username">{{userInfo && userInfo.nickname ? userInfo.nickname : username}}</text>
|
||
<text class="user-area">{{userInfo && userInfo.areaName ? userInfo.areaName : ''}}</text>
|
||
</view>
|
||
<text class="logout" @click="handleLogout">退出登录</text>
|
||
</view>
|
||
|
||
<!-- 账号管理(登录前后都显示) -->
|
||
<view class="accounts-manager">
|
||
<view class="section-header" style="padding-top: 10rpx;">
|
||
<text class="section-title" style="font-size: 26rpx;">账号管理</text>
|
||
<view class="add-account" @click="showAddAccount">+ 添加账号</view>
|
||
</view>
|
||
|
||
<!-- 账号列表 -->
|
||
<view class="account-list">
|
||
<view class="account-item" v-for="(account, index) in accounts" :key="index">
|
||
<view class="account-info">
|
||
<text class="account-username">{{account.username}}</text>
|
||
<text class="account-status" :class="{'active': account.isActive}">{{account.isActive ? '当前使用' : '备用'}}</text>
|
||
</view>
|
||
<view class="account-actions">
|
||
<text class="action-btn" @click="setAsActive(index)" v-if="!account.isActive">使用</text>
|
||
<text class="action-btn delete" @click="removeAccount(index)" v-if="!account.isActive">删除</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 添加账号弹窗 -->
|
||
<uni-popup ref="accountPopup" type="center">
|
||
<view class="add-account-popup">
|
||
<view class="popup-title">添加备用账号</view>
|
||
<view class="popup-form">
|
||
<u--input placeholder="请输入账号" v-model="newAccount.username" class="popup-input" border="surround"></u--input>
|
||
<u--input placeholder="请输入密码" type="password" v-model="newAccount.password" class="popup-input" border="surround"></u--input>
|
||
</view>
|
||
<view class="popup-actions">
|
||
<button class="popup-btn cancel" @click="closePopup">取消</button>
|
||
<button class="popup-btn confirm" @click="addAccount">确认</button>
|
||
</view>
|
||
</view>
|
||
</uni-popup>
|
||
</view>
|
||
<!-- 屏蔽店铺模块 -->
|
||
<view class="u-demo-block">
|
||
<text class="section-title">屏蔽店铺</text>
|
||
<u--textarea v-model="value1" placeholder="在售商品列中不显示的店铺(屏蔽店铺之间使用;分割)"
|
||
:inputStyle="{ fontSize: '32rpx !important' }"
|
||
placeholder-style="font-size: 32rpx !important"></u--textarea>
|
||
</view>
|
||
<!-- 价格模式模块 -->
|
||
<view class="u-demo-block">
|
||
<view class="section-header">
|
||
<text class="section-title">价格模式(总价=书价+运费)</text>
|
||
<text class="section-subtitle">自动生成改价</text>
|
||
</view>
|
||
<view class="u-demo-block__content">
|
||
<!-- 选项卡组件,展示价格模式选项,current1控制当前选中项,选项变化时触发change1方法 -->
|
||
<u-subsection :list="list" mode="button" :current="current1" @change="change1"
|
||
activeColor="#000000"></u-subsection>
|
||
<view class="price-reference" style="color:#888;font-size:28rpx; margin:20rpx 0;">
|
||
<!-- 根据current1的值显示不同的提示文本 -->
|
||
<text v-if="current1 === 0">以最低价的<text class="highlight-text">总价</text>为参照物</text>
|
||
<text v-if="current1 === 1">以<text class="highlight-text">总价</text>最低的<text
|
||
class="highlight-text">{{averageRange}}</text>个价格平均值为参照物</text>
|
||
<!-- 数字输入框,当current1为1时显示,双向绑定averageRange,设置取值范围和步长 -->
|
||
<view v-if="current1 === 1" class="average-range-control">
|
||
<text class="range-label">参考值个数(2-12之间)</text>
|
||
<view class="range-control">
|
||
<text class="range-btn" @click="decreaseRange"></text>
|
||
<text class="range-value">{{averageRange}}</text>
|
||
<text class="range-btn" @click="increaseRange"></text>
|
||
</view>
|
||
</view>
|
||
<!-- 当选择最低价时,显示排序位置选择器 -->
|
||
<view v-if="current1 === 0" class="position-selector">
|
||
<text class="range-label">选择第几条数据(1-12之间)</text>
|
||
<view class="freight-picker" style="margin-top:10rpx;">
|
||
<picker mode="selector" :range="positionOptions" @change="onPositionChange"
|
||
:value="selectedPositionIndex">
|
||
<view class="picker-content">
|
||
{{ positionOptions[selectedPositionIndex] || '请选择位置' }}
|
||
<text class="arrow"></text>
|
||
</view>
|
||
</picker>
|
||
</view>
|
||
</view>
|
||
<text v-if="current1 === 2">以最近售出的<text class="highlight-text">总价</text>为参照<text
|
||
style="color:red">[不含运费]</text></text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<!-- 加减幅度模块 -->
|
||
<view class="u-demo-block">
|
||
<view class="section-header">
|
||
<text class="section-title">运费</text>
|
||
</view>
|
||
<!-- 数字输入框,双向绑定value3,设置取值范围、步长和小数位数 -->
|
||
<view class="number-control-wrapper">
|
||
<text class="number-control-btn minus-btn" @click="decreaseValue3">-</text>
|
||
<input type="digit" v-model="value3" class="custom-input-box" @blur="validateValue3"
|
||
:disabled="false" />
|
||
<text class="number-control-btn plus-btn" @click="increaseValue3">+</text>
|
||
</view>
|
||
<!-- 最低值模块 -->
|
||
<view class="section-header">
|
||
<text class="section-title">最低书价(不含运费)</text>
|
||
</view>
|
||
<!-- 数字输入框,双向绑定value4,设置取值范围、步长和小数位数 -->
|
||
<view class="number-control-wrapper">
|
||
<text class="number-control-btn minus-btn" @click="decreaseValue4">-</text>
|
||
<input type="digit" v-model="value4" class="custom-input-box" @blur="validateValue4"
|
||
:disabled="false" />
|
||
<text class="number-control-btn plus-btn" @click="increaseValue4">+</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 价格排序方式选择模块 -->
|
||
<!-- 已删除价格排序方式下拉框,默认总价从低到高[含运费] -->
|
||
<!-- 品相筛选模块 -->
|
||
<view class="u-demo-block" style="margin-top:40rpx">
|
||
<view class="section-header">
|
||
<text class="section-title">品相筛选</text>
|
||
<text class="section-subtitle">根据自己偏好选择</text>
|
||
</view>
|
||
<view class="freight-picker">
|
||
<!-- 选择器组件,选择品相,range绑定品相选项列表,选择变化时触发onConditionCode方法,value绑定selectConditionCodeIndex -->
|
||
<picker mode="selector" :range="conditionCode" @change="onConditionCode"
|
||
:value="selectConditionCodeIndex">
|
||
<view class="picker-content">
|
||
{{ conditionCode[selectConditionCodeIndex] || '请选择品相' }}
|
||
<text class="arrow"></text>
|
||
</view>
|
||
</picker>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import request from '@/utils/request.js';
|
||
import {
|
||
mapState,
|
||
mapMutations
|
||
} from 'vuex'
|
||
// Vuex 模块拆分后使用命名空间访问
|
||
|
||
export default {
|
||
computed: {
|
||
...mapState('price', ['priceMode', 'priceType'])
|
||
},
|
||
watch: {
|
||
value1: {
|
||
handler(newVal) {
|
||
this.saveBlockedShops();
|
||
},
|
||
immediate: false
|
||
}
|
||
},
|
||
// 添加创建时的初始化检查
|
||
created() {
|
||
console.log('组件创建 - 检查是否有初始化标记');
|
||
// 检查是否是第一次启动应用
|
||
const hasInitialized = uni.getStorageSync('app_initialized');
|
||
|
||
if (!hasInitialized) {
|
||
console.log('首次启动应用 - 设置默认值');
|
||
// 第一次启动应用,设置默认值
|
||
uni.setStorageSync('current1', 1); // 均价
|
||
uni.setStorageSync('current2', 1); // 总价
|
||
uni.setStorageSync('selectedSortIndex', 1); // 价格排序方式默认为总价从低到高
|
||
uni.setStorageSync('sortType', '7'); // 设置sortType为7
|
||
uni.setStorageSync('app_initialized', true); // 标记已初始化
|
||
} else {
|
||
// 即使不是首次启动,也确保有默认值
|
||
if (!uni.getStorageSync('sortType')) {
|
||
uni.setStorageSync('sortType', '7');
|
||
}
|
||
if (!uni.getStorageSync('selectedSortIndex')) {
|
||
uni.setStorageSync('selectedSortIndex', 1);
|
||
}
|
||
}
|
||
|
||
// 读取记住密码设置
|
||
this.rememberPassword = uni.getStorageSync('rememberPassword') === true;
|
||
console.log('初始化时记住密码设置为:', this.rememberPassword);
|
||
|
||
// 加载账号信息
|
||
this.loadAccounts();
|
||
|
||
// 如果设置了记住密码,则填充用户名和密码
|
||
if (this.rememberPassword) {
|
||
const savedUsername = uni.getStorageSync('KongfzUserName');
|
||
const savedPassword = uni.getStorageSync('KongfzPassword');
|
||
console.log('读取到保存的用户名:', savedUsername);
|
||
console.log('是否有保存的密码:', savedPassword ? '是' : '否');
|
||
|
||
this.username = savedUsername || '';
|
||
this.password = savedPassword || '';
|
||
}
|
||
|
||
// 监听账号切换事件
|
||
uni.$on('accountSwitched', this.handleAccountSwitched);
|
||
},
|
||
// 组件销毁时移除事件监听
|
||
beforeDestroy() {
|
||
uni.$off('accountSwitched', this.handleAccountSwitched);
|
||
},
|
||
data() {
|
||
return {
|
||
username: '', // 添加用户名字段
|
||
password: '', // 添加密码字段
|
||
isLogging: false,
|
||
isLoading: false, // 登录加载状态
|
||
isLoggedIn: false, // 登录状态
|
||
userInfo: null, // 添加用户信息字段
|
||
conditionValue: '', // 存储品相对应的数值范围
|
||
sortType: '', //存储价格类型
|
||
shippingTemplate: 1,
|
||
barcodes: [],
|
||
value1: '', // 屏蔽店铺列表
|
||
current1: 1, // 控制价格模式第一个选项卡的当前选中状态
|
||
averageRange: 3, // 当价格模式为"均价"时,用于计算平均值的价格数量范围
|
||
current2: 1, // 控制价格模式相关的第二个选项卡的当前选中状态
|
||
list: ['最低价', '均价'], // 价格模式的选项列表
|
||
list2: ['书价', '总价'], // 与价格模式相关的另一组选项列表
|
||
value3: 0, // 加减幅度的数值
|
||
value4: 0.1, // 最低值的数值
|
||
positionOptions: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'], // 位置选项列表
|
||
selectedPositionIndex: 0, // 选择的位置索引,默认为0(第一条数据)
|
||
freightTemplateId: null, // 选中的运费模板ID
|
||
freightTemplateList: [ // 运费模板数据列表
|
||
{
|
||
id: 1,
|
||
templateName: '模板一'
|
||
},
|
||
{
|
||
id: 2,
|
||
templateName: '模板二'
|
||
},
|
||
{
|
||
id: 3,
|
||
templateName: '模板三'
|
||
}
|
||
],
|
||
conditionCode: ['全部品相', '全新', '古旧书', '九五品以上', '九品以上', '八五品以上', '八品以上'], // 品相筛选的选项列表
|
||
freightTemplateIndex: 0, // 运费模板选择器的当前索引
|
||
selectedFreightTemplate: {}, // 存储当前选中的运费模板对象
|
||
|
||
sortOptions: ['书价从低到高', '总价从低到高[含运费]'], // 价格排序方式的选项列表
|
||
selectedSortIndex: 1, // 价格排序方式选择器的当前索引
|
||
selectConditionCodeIndex: 0, // 品相筛选选择器的当前索引
|
||
selectShopTypeIndex: 0, // 本店分类选择器的当前索引
|
||
selectedGoodsNoIndex: 0,
|
||
searchThenTakePhoto: false, // "搜索完成后开始拍照"功能的开关状态
|
||
takePhotoNextSubmit: false, // "拍照下一步自动提交"功能的开关状态
|
||
submitSound: false, // "提交成功提示音"功能的开关状态
|
||
scanGunMode: false, // "扫码枪模式"功能的开关状态
|
||
isbnCheck: false, // 用于控制"通过isbn检测商品是否存在"开关的状态
|
||
articleNumberCheck: false, // 用于控制"通过货号检测商品是否存在"开关的状态
|
||
goodsNoOptions: ['手动输入或者扫码', '初始货号尾数数字自增', '同isbn码一致'],
|
||
// 参考价小数位选项
|
||
decimalOptions: ['一位小数', '两位小数', '三位小数'],
|
||
selectedDecimalIndex: 0,
|
||
// 商品列表价格展示选项
|
||
priceDisplayOptions: ['显示价格', '不显示价格'],
|
||
priceDisplayIndex: 0,
|
||
// 商品列表展示选项
|
||
displayModeOptions: ['详细展示', '简洁展示'],
|
||
displayModeIndex: 0,
|
||
rememberPassword: false,
|
||
accounts: [], // 存储多个账号信息,初始化为空,从本地存储加载
|
||
showAccountPopup: false, // 控制添加账号弹窗的显示
|
||
newAccount: { // 新增账号的临时数据
|
||
username: '',
|
||
password: ''
|
||
},
|
||
currentAccountIndex: 0, // 当前使用的账号索引
|
||
maxLoginAttempts: 3, // 最大自动登录尝试次数
|
||
loginAttemptCount: 0 // 当前尝试登录次数
|
||
}
|
||
},
|
||
onShow() {
|
||
// 调试:打印初始状态
|
||
console.log('=== 页面显示 - 初始状态 ===');
|
||
console.log('存储中的 current1:', uni.getStorageSync('current1'));
|
||
console.log('存储中的 current2:', uni.getStorageSync('current2'));
|
||
|
||
// 检查是否已登录
|
||
const cookies = uni.getStorageSync('UserInfoCookies');
|
||
const savedUsername = uni.getStorageSync('KongfzUserName');
|
||
const savedPassword = uni.getStorageSync('KongfzPassword');
|
||
|
||
// 初始化登录状态为 false
|
||
this.isLoggedIn = false;
|
||
|
||
if (cookies && savedUsername) {
|
||
// 如果有保存的登录凭证,先临时设置登录状态为true
|
||
this.isLoggedIn = true;
|
||
this.username = savedUsername;
|
||
|
||
// 获取用户信息并验证cookie
|
||
this.getUserInfo(cookies);
|
||
// 失效后尝试自动登录
|
||
// this.verifyCookieValid(cookies, savedUsername, savedPassword);
|
||
}
|
||
// } else if (savedUsername && savedPassword) {
|
||
// // 有账号密码但没有cookie,尝试自动登录
|
||
// console.log('发现账号密码但cookie丢失,尝试自动登录');
|
||
// this.autoLogin(savedUsername, savedPassword);
|
||
// }
|
||
|
||
// 从本地存储中读取之前保存的值 - 直接加载实际存储的值
|
||
this.value1 = uni.getStorageSync('blockedShops') || '';
|
||
|
||
// 添加安全的数据获取函数
|
||
const getSafeNumber = (key, defaultValue, isFloat = false) => {
|
||
const value = uni.getStorageSync(key);
|
||
if (value === '' || value === null || value === undefined) {
|
||
return defaultValue;
|
||
}
|
||
try {
|
||
return isFloat ? parseFloat(value) : parseInt(value);
|
||
} catch (e) {
|
||
console.error(`转换${key}出错:`, e);
|
||
return defaultValue;
|
||
}
|
||
};
|
||
|
||
// 安全读取所有设置
|
||
this.current1 = getSafeNumber('current1', 1);
|
||
this.current2 = getSafeNumber('current2', 1);
|
||
this.averageRange = getSafeNumber('averageRange', 3);
|
||
this.value3 = getSafeNumber('value3', 0, true);
|
||
this.value4 = getSafeNumber('value4', 0.1, true);
|
||
this.selectedSortIndex = getSafeNumber('selectedSortIndex', 1);
|
||
this.selectConditionCodeIndex = getSafeNumber('selectConditionCodeIndex', 0);
|
||
this.selectedPositionIndex = getSafeNumber('selectedPositionIndex', 0);
|
||
|
||
// 调试: 打印加载后的状态
|
||
console.log('=== 页面加载完成 - 当前状态 ===');
|
||
console.log('current1:', this.current1, '- 模式:', this.list[this.current1]);
|
||
console.log('current2:', this.current2, '- 类型:', this.list2[this.current2]);
|
||
|
||
// 读取其他设置
|
||
this.freightTemplateIndex = getSafeNumber('freightTemplateIndex', 0);
|
||
this.selectShopTypeIndex = getSafeNumber('selectShopTypeIndex', 0);
|
||
this.selectedGoodsNoIndex = getSafeNumber('selectedGoodsNoIndex', 0);
|
||
this.selectedDecimalIndex = getSafeNumber('selectedDecimalIndex', 0);
|
||
this.priceDisplayIndex = getSafeNumber('priceDisplayIndex', 0);
|
||
this.displayModeIndex = getSafeNumber('displayModeIndex', 0);
|
||
|
||
// 同步当前值到Vuex store
|
||
this.updatePriceMode(this.current1);
|
||
this.updatePriceType(this.current2);
|
||
this.updateAverageRange(this.averageRange);
|
||
this.updateSelectedPosition(parseInt(this.selectedPositionIndex));
|
||
this.updateFreight(this.value3);
|
||
this.updateMinValue(this.value4);
|
||
|
||
// 确保品相值也被正确设置
|
||
const selectedCondition = this.conditionCode[this.selectConditionCodeIndex];
|
||
switch (selectedCondition) {
|
||
case '九五品以上':
|
||
this.conditionValue = '95~';
|
||
break;
|
||
case '全新':
|
||
this.conditionValue = '100~';
|
||
break;
|
||
case '古旧书':
|
||
this.conditionValue = '~99';
|
||
break;
|
||
case '九品以上':
|
||
this.conditionValue = '90~';
|
||
break;
|
||
case '八五品以上':
|
||
this.conditionValue = '85~';
|
||
break;
|
||
case '八品以上':
|
||
this.conditionValue = '80~';
|
||
break;
|
||
case '七品以上':
|
||
this.conditionValue = '70~';
|
||
break;
|
||
default:
|
||
this.conditionValue = '';
|
||
}
|
||
uni.setStorageSync('conditionValue', this.conditionValue);
|
||
},
|
||
methods: {
|
||
...mapMutations('price', ['updatePriceMode', 'updatePriceType', 'updateAverageRange',
|
||
'updateFreight', 'updateMinValue'
|
||
]),
|
||
...mapMutations('warehouse', ['updateSelectedPosition']),
|
||
// 加载保存的账号信息
|
||
loadAccounts() {
|
||
try {
|
||
const savedAccounts = uni.getStorageSync('accounts');
|
||
if (savedAccounts) {
|
||
this.accounts = JSON.parse(savedAccounts);
|
||
console.log('已加载账号列表,共', this.accounts.length, '个账号');
|
||
|
||
// 获取当前使用的账号索引
|
||
const currentIndex = uni.getStorageSync('currentAccountIndex');
|
||
this.currentAccountIndex = currentIndex !== '' ? parseInt(currentIndex) : 0;
|
||
|
||
// 确保有一个账号被标记为活跃
|
||
let hasActive = false;
|
||
this.accounts.forEach((acc, idx) => {
|
||
if (acc.isActive) {
|
||
hasActive = true;
|
||
this.currentAccountIndex = idx;
|
||
}
|
||
});
|
||
|
||
// 如果没有活跃账号但有账号,则设置第一个为活跃
|
||
if (!hasActive && this.accounts.length > 0) {
|
||
this.accounts[0].isActive = true;
|
||
this.currentAccountIndex = 0;
|
||
uni.setStorageSync('accounts', JSON.stringify(this.accounts));
|
||
}
|
||
|
||
// 如果有活跃账号,设置当前用户名和密码
|
||
if (this.accounts.length > 0 && this.accounts[this.currentAccountIndex]) {
|
||
this.username = this.accounts[this.currentAccountIndex].username;
|
||
this.password = this.accounts[this.currentAccountIndex].password;
|
||
}
|
||
} else {
|
||
// 如果没有保存的账号,创建空数组
|
||
this.accounts = [];
|
||
console.log('没有保存的账号,初始化为空列表');
|
||
|
||
// 如果有保存的单一账号密码,迁移它
|
||
const savedUsername = uni.getStorageSync('KongfzUserName');
|
||
const savedPassword = uni.getStorageSync('KongfzPassword');
|
||
|
||
if (savedUsername && savedPassword) {
|
||
console.log('发现已保存的单一账号,迁移至账号列表');
|
||
this.accounts.push({
|
||
username: savedUsername,
|
||
password: savedPassword,
|
||
isActive: true
|
||
});
|
||
this.currentAccountIndex = 0;
|
||
uni.setStorageSync('accounts', JSON.stringify(this.accounts));
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('加载账号信息失败:', error);
|
||
this.accounts = [];
|
||
}
|
||
},
|
||
// 监听value1变化并保存到本地存储
|
||
saveBlockedShops() {
|
||
uni.setStorageSync('blockedShops', this.value1);
|
||
},
|
||
// 登录孔网
|
||
async login() {
|
||
// 防止重复提交
|
||
if (this.isLogging) return
|
||
this.isLogging = true
|
||
this.isLoading = true // 显示加载动画
|
||
|
||
// 使用当前选择的账号
|
||
let loginUsername = this.username
|
||
let loginPassword = this.password
|
||
|
||
// 如果账号列表中有账号,使用当前活跃账号
|
||
// if (this.accounts.length > 0) {
|
||
// const activeAccount = this.accounts.find(acc => acc.isActive);
|
||
// if (activeAccount) {
|
||
// loginUsername = activeAccount.username;
|
||
// loginPassword = activeAccount.password;
|
||
// console.log("使用账号列表中的活跃账号:", loginUsername);
|
||
// }
|
||
// }
|
||
|
||
try {
|
||
const result = await this.getCookies(loginUsername, loginPassword);
|
||
console.log("result", result)
|
||
|
||
// 检查是否需要手机验证登录
|
||
if (result.responseData && result.responseData.extInfo &&
|
||
result.responseData.extInfo.action === "redirect" &&
|
||
result.responseData.extInfo.uri.includes("请使用手机号验证登录")) {
|
||
// 尝试切换到下一个账号
|
||
if (await this.switchToNextAccount("该账号需要手机验证,尝试下一个账号")) {
|
||
this.isLogging = false;
|
||
this.isLoading = false;
|
||
return this.login(); // 重新尝试登录
|
||
}
|
||
|
||
uni.showToast({
|
||
title: '无法登录,所有账号都需要手机验证',
|
||
icon: 'none',
|
||
duration: 2500
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 检查其他重定向情况
|
||
if (result.responseData && result.responseData.extInfo &&
|
||
result.responseData.extInfo.action === "redirect") {
|
||
// 尝试切换到下一个账号
|
||
if (await this.switchToNextAccount("账号登录异常,尝试下一个账号")) {
|
||
this.isLogging = false;
|
||
this.isLoading = false;
|
||
return this.login(); // 重新尝试登录
|
||
}
|
||
|
||
uni.showToast({
|
||
title: '无法登录,请检查账号或添加新账号',
|
||
icon: 'none',
|
||
duration: 2500
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 检查常见错误情况
|
||
console.log("result.responseData.errType", result.responseData.errType)
|
||
|
||
// 处理错误情况
|
||
if (result.responseData.errType === "102" ||
|
||
[102, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009].includes(result.responseData.errCode)) {
|
||
|
||
// 准备错误消息
|
||
let errorMsg;
|
||
switch (result.responseData.errCode) {
|
||
case 102: errorMsg = '用户名不能为空'; break;
|
||
case 1000: errorMsg = '授权码错误或已过期'; break;
|
||
case 1001: errorMsg = '用户不存在'; break;
|
||
case 1009: errorMsg = '调用次数已达上限'; break;
|
||
default: errorMsg = result.responseData.errInfo || '账号登录异常';
|
||
}
|
||
|
||
// 尝试切换到下一个账号
|
||
if (await this.switchToNextAccount(`${errorMsg},尝试下一个账号`)) {
|
||
this.isLogging = false;
|
||
this.isLoading = false;
|
||
return this.login(); // 重新尝试登录
|
||
}
|
||
|
||
// 如果无法切换账号,显示错误
|
||
uni.showToast({
|
||
title: `${errorMsg},所有账号都无法使用`,
|
||
icon: 'none',
|
||
duration: 2500
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 登录成功,保存 Cookie 到本地存储
|
||
if (result.cookies && result.cookies.PHPSESSID) {
|
||
// 保存cookies
|
||
uni.setStorageSync('cookies', result.cookies.PHPSESSID);
|
||
uni.setStorageSync('UserInfoCookies', result.cookies.PHPSESSID);
|
||
|
||
// 总是保存用户名(当前活跃账号的用户名)
|
||
uni.setStorageSync('KongfzUserName', loginUsername);
|
||
|
||
// 先保存记住密码设置
|
||
console.log('保存记住密码设置:', this.rememberPassword);
|
||
uni.setStorageSync('rememberPassword', this.rememberPassword);
|
||
|
||
if (this.rememberPassword) {
|
||
// 如果选择记住密码,明确保存密码
|
||
console.log('保存密码:', loginPassword);
|
||
uni.setStorageSync('KongfzPassword', loginPassword);
|
||
} else {
|
||
// 如果不记住密码,确保移除保存的密码
|
||
console.log('移除已保存的密码');
|
||
uni.removeStorageSync('KongfzPassword');
|
||
}
|
||
|
||
console.log('成功保存cookies:', result.cookies.PHPSESSID);
|
||
|
||
// 重置登录尝试计数
|
||
this.loginAttemptCount = 0;
|
||
|
||
// 获取用户信息
|
||
await this.getUserInfo(result.cookies.PHPSESSID);
|
||
|
||
// 更新登录状态
|
||
this.isLoggedIn = true;
|
||
// 显示成功提示
|
||
uni.showToast({
|
||
title: '登录成功',
|
||
icon: 'success',
|
||
duration: 2000
|
||
});
|
||
} else {
|
||
// 尝试切换到下一个账号
|
||
if (await this.switchToNextAccount('登录失败,未获取到cookies,尝试下一个账号')) {
|
||
this.isLogging = false;
|
||
this.isLoading = false;
|
||
return this.login(); // 重新尝试登录
|
||
}
|
||
|
||
uni.showToast({
|
||
title: '登录失败,所有账号都无法获取cookies',
|
||
icon: 'none',
|
||
duration: 2500
|
||
});
|
||
}
|
||
} catch (error) {
|
||
console.error('登录出错:', error);
|
||
|
||
// 尝试切换到下一个账号
|
||
if (await this.switchToNextAccount('登录出错,尝试下一个账号')) {
|
||
this.isLogging = false;
|
||
this.isLoading = false;
|
||
return this.login(); // 重新尝试登录
|
||
}
|
||
|
||
uni.showToast({
|
||
title: '所有账号登录失败,请检查网络',
|
||
icon: 'none'
|
||
});
|
||
} finally {
|
||
this.isLogging = false;
|
||
this.isLoading = false; // 隐藏加载动画
|
||
}
|
||
},
|
||
// 切换到下一个可用账号
|
||
async switchToNextAccount(message) {
|
||
if (this.accounts.length <= 1) {
|
||
console.log('没有备用账号可用');
|
||
return false;
|
||
}
|
||
|
||
// 增加尝试次数
|
||
this.loginAttemptCount++;
|
||
|
||
// 检查是否超过最大尝试次数
|
||
if (this.loginAttemptCount > this.maxLoginAttempts) {
|
||
console.log('超过最大尝试登录次数');
|
||
uni.showToast({
|
||
title: '已尝试所有账号,请检查账号状态',
|
||
icon: 'none',
|
||
duration: 2500
|
||
});
|
||
this.loginAttemptCount = 0;
|
||
return false;
|
||
}
|
||
|
||
// 获取当前账号索引
|
||
let currentIndex = this.accounts.findIndex(acc => acc.isActive);
|
||
if (currentIndex === -1) currentIndex = 0;
|
||
|
||
// 找到下一个账号索引
|
||
let nextIndex = (currentIndex + 1) % this.accounts.length;
|
||
|
||
// 确保不会无限循环
|
||
if (nextIndex === currentIndex) {
|
||
return false;
|
||
}
|
||
|
||
// 切换到下一个账号
|
||
console.log(`${message},从账号 ${this.accounts[currentIndex].username} 切换到 ${this.accounts[nextIndex].username}`);
|
||
|
||
this.accounts.forEach((acc, idx) => {
|
||
acc.isActive = (idx === nextIndex);
|
||
});
|
||
|
||
this.currentAccountIndex = nextIndex;
|
||
this.username = this.accounts[nextIndex].username;
|
||
this.password = this.accounts[nextIndex].password;
|
||
|
||
// 保存更新后的账号列表
|
||
uni.setStorageSync('accounts', JSON.stringify(this.accounts));
|
||
uni.setStorageSync('currentAccountIndex', nextIndex);
|
||
|
||
uni.showToast({
|
||
title: `${message.substring(0, 10)}...,切换到备用账号`,
|
||
icon: 'none',
|
||
duration: 1500
|
||
});
|
||
|
||
return true;
|
||
},
|
||
// 获取用户信息
|
||
async getUserInfo(cookies) {
|
||
try {
|
||
console.log("开始获取用户信息...")
|
||
|
||
// 使用API包装函数获取用户信息
|
||
const data = await this.apiRequestWithRetry('https://search.kongfz.com/common-web/v1/api/userInfo', {
|
||
header: { 'Cookie': `PHPSESSID=${cookies}` }
|
||
});
|
||
console.log("用户数据",data)
|
||
if (data && data.status === 1) {
|
||
this.userInfo = data.data;
|
||
// 保存用户信息到本地存储
|
||
uni.setStorageSync('userInfo', data.data);
|
||
this.isLoggedIn = true; // 更新登录状态
|
||
} else {
|
||
throw new Error(data.message || '获取用户信息失败');
|
||
}
|
||
} catch (error) {
|
||
console.error('获取用户信息失败:', error);
|
||
// 如果获取用户信息失败,可能是cookie失效
|
||
this.isLoggedIn = false;
|
||
// 尝试重新登录
|
||
if (this.accounts.length > 0) {
|
||
const activeAccount = this.accounts.find(acc => acc.isActive);
|
||
if (activeAccount) {
|
||
console.log('Cookie无效,尝试重新登录');
|
||
await this.login();
|
||
}
|
||
} else {
|
||
uni.showToast({
|
||
title: '获取用户信息失败,请重新登录',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
}
|
||
},
|
||
|
||
// 孔网API请求包装函数,支持自动重试和账号切换
|
||
async apiRequestWithRetry(url, options = {}, maxRetries = 2) {
|
||
let retryCount = 0;
|
||
let lastError = null;
|
||
|
||
while (retryCount <= maxRetries) {
|
||
try {
|
||
// 获取当前cookie
|
||
const cookies = uni.getStorageSync('UserInfoCookies');
|
||
if (!cookies) {
|
||
throw new Error('未登录,请先登录账号');
|
||
}
|
||
|
||
// 默认添加Cookie头
|
||
const headers = {
|
||
'Cookie': `PHPSESSID=${cookies}`,
|
||
...(options.header || {})
|
||
};
|
||
|
||
// 发起请求
|
||
const [err, res] = await uni.request({
|
||
url,
|
||
method: options.method || 'GET',
|
||
data: options.data,
|
||
header: headers
|
||
});
|
||
|
||
if (err) {
|
||
throw new Error('请求失败: ' + (err.errMsg || '未知错误'));
|
||
}
|
||
|
||
// 检查是否有错误码,如1000、1009等
|
||
if (res.data && (res.data.errCode || res.data.errType)) {
|
||
// 特定错误码表示cookie失效或权限问题
|
||
const errorCode = res.data.errCode || 0;
|
||
const errorType = res.data.errType || '';
|
||
|
||
if ([102, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009].includes(errorCode) ||
|
||
errorType === '102') {
|
||
|
||
console.log(`API返回错误: 代码=${errorCode}, 类型=${errorType}, 信息=${res.data.errInfo || '无'}`);
|
||
|
||
// 尝试切换账号
|
||
if (await this.switchToNextAccount('API调用错误,尝试切换账号')) {
|
||
console.log('切换账号成功,重新登录中...');
|
||
|
||
// 重新登录
|
||
await this.login();
|
||
|
||
// 登录成功后重试
|
||
retryCount++;
|
||
continue;
|
||
} else {
|
||
// 无法切换账号,抛出错误
|
||
throw new Error(res.data.errInfo || `API调用错误 ${errorCode}`);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 成功响应
|
||
return res.data;
|
||
|
||
} catch (error) {
|
||
console.error(`API请求失败(第${retryCount + 1}次尝试):`, error);
|
||
lastError = error;
|
||
retryCount++;
|
||
|
||
// 最后一次尝试失败,抛出异常
|
||
if (retryCount > maxRetries) {
|
||
throw error;
|
||
}
|
||
|
||
// 等待一段时间再重试
|
||
await new Promise(resolve => setTimeout(resolve, 500));
|
||
}
|
||
}
|
||
|
||
// 不应该执行到这里,但为保险起见
|
||
throw lastError || new Error('请求失败,请重试');
|
||
},
|
||
// 退出登录
|
||
handleLogout() {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '确定要退出登录吗?',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
// 清除登录状态和用户信息
|
||
this.isLoggedIn = false;
|
||
|
||
// 获取当前活跃账号
|
||
const activeAccount = this.accounts.find(acc => acc.isActive);
|
||
|
||
if (activeAccount) {
|
||
// 如果有活跃账号,填充用户名和密码
|
||
this.username = activeAccount.username;
|
||
this.password = activeAccount.password;
|
||
} else if (this.rememberPassword) {
|
||
// 如果记住密码但没有活跃账号,使用存储的用户名和密码
|
||
const savedUsername = uni.getStorageSync('KongfzUserName');
|
||
const savedPassword = uni.getStorageSync('KongfzPassword');
|
||
this.username = savedUsername || '';
|
||
this.password = savedPassword || '';
|
||
} else {
|
||
// 如果不记住密码,清空密码字段
|
||
this.password = '';
|
||
}
|
||
|
||
// 清除用户信息和cookies
|
||
this.userInfo = null;
|
||
uni.removeStorageSync('UserInfoCookies');
|
||
uni.removeStorageSync('cookies');
|
||
|
||
uni.showToast({
|
||
title: '已退出登录',
|
||
icon: 'success'
|
||
});
|
||
}
|
||
}
|
||
});
|
||
},
|
||
// 处理价格模式第一个选项卡变化的方法,更新current1的值
|
||
change1(index) {
|
||
console.log('修改价格模式前:', this.current1);
|
||
this.current1 = index;
|
||
// 强制确保保存为数字
|
||
uni.setStorageSync('current1', index);
|
||
console.log('已保存价格模式:', index);
|
||
this.updatePriceMode(index);
|
||
console.log('价格模式已更改为:', this.list[index], '(值:', index, ')');
|
||
|
||
// 立即从存储中读取并验证
|
||
setTimeout(() => {
|
||
const storedValue = uni.getStorageSync('current1');
|
||
console.log('存储中的值现在是:', storedValue);
|
||
}, 100);
|
||
},
|
||
// 处理价格模式第二个选项卡变化的方法,更新current2的值
|
||
change2(index) {
|
||
console.log('修改价格类型前:', this.current2);
|
||
this.current2 = index;
|
||
// 强制确保保存为数字
|
||
uni.setStorageSync('current2', index);
|
||
console.log('已保存价格类型:', index);
|
||
this.updatePriceType(index);
|
||
console.log('价格类型已更改为:', this.list2[index], '(值:', index, ')');
|
||
|
||
// 立即从存储中读取并验证
|
||
setTimeout(() => {
|
||
const storedValue = uni.getStorageSync('current2');
|
||
console.log('存储中的值现在是:', storedValue);
|
||
}, 100);
|
||
},
|
||
// 处理位置选择变化的方法,更新selectedPositionIndex的值
|
||
onPositionChange(e) {
|
||
this.selectedPositionIndex = e.detail.value;
|
||
console.log("选择第几条数据", this.selectedPositionIndex)
|
||
uni.setStorageSync('selectedPositionIndex', this.selectedPositionIndex);
|
||
this.updateSelectedPosition(parseInt(this.selectedPositionIndex));
|
||
},
|
||
|
||
|
||
// 处理品相变化
|
||
onConditionCode(e) {
|
||
this.selectConditionCodeIndex = e.detail.value;
|
||
uni.setStorageSync('selectConditionCodeIndex', this.selectConditionCodeIndex);
|
||
|
||
// 根据选择的品相设置对应的数值范围
|
||
const selectedCondition = this.conditionCode[e.detail.value];
|
||
switch (selectedCondition) {
|
||
case '九五品以上':
|
||
this.conditionValue = '95~';
|
||
break;
|
||
case '全新':
|
||
this.conditionValue = '100~';
|
||
break;
|
||
case '古旧书':
|
||
this.conditionValue = '~99';
|
||
break;
|
||
case '九品以上':
|
||
this.conditionValue = '90~';
|
||
break;
|
||
case '八五品以上':
|
||
this.conditionValue = '85~';
|
||
break;
|
||
case '八品以上':
|
||
this.conditionValue = '80~';
|
||
break;
|
||
case '七品以上':
|
||
this.conditionValue = '70~';
|
||
break;
|
||
default:
|
||
this.conditionValue = '';
|
||
}
|
||
console.log("selectedCondition", this.conditionValue)
|
||
uni.setStorageSync('conditionValue', this.conditionValue);
|
||
},
|
||
onShopType(e) {
|
||
this.selectShopTypeIndex = e.detail.value;
|
||
uni.setStorageSync('selectShopTypeIndex', this.selectShopTypeIndex);
|
||
},
|
||
onGoodsNoChange(e) {
|
||
this.selectedGoodsNoIndex = e.detail.value;
|
||
uni.setStorageSync('selectedGoodsNoIndex', this.selectedGoodsNoIndex);
|
||
},
|
||
handleDecimalChange(e) {
|
||
this.selectedDecimalIndex = e.detail.value;
|
||
uni.setStorageSync('selectedDecimalIndex', this.selectedDecimalIndex);
|
||
console.log('参考价小数位选择变更为:', this.decimalOptions[this.selectedDecimalIndex]);
|
||
},
|
||
handlePriceDisplayChange(e) {
|
||
this.priceDisplayIndex = e.detail.value;
|
||
uni.setStorageSync('priceDisplayIndex', this.priceDisplayIndex);
|
||
console.log('商品列表价格展示选择变更为:', this.priceDisplayOptions[this.priceDisplayIndex]);
|
||
},
|
||
handleDisplayModeChange(e) {
|
||
this.displayModeIndex = e.detail.value;
|
||
uni.setStorageSync('displayModeIndex', this.displayModeIndex);
|
||
console.log('商品列表展示选择变更为:', this.displayModeOptions[this.displayModeIndex]);
|
||
},
|
||
// 运费和最低值相关方法
|
||
validateValue3() {
|
||
let val = parseFloat(this.value3);
|
||
if (isNaN(val)) {
|
||
this.value3 = 0;
|
||
} else if (val > 99) {
|
||
this.value3 = 99;
|
||
} else if (val < -99) {
|
||
this.value3 = -99;
|
||
} else {
|
||
this.value3 = parseFloat(val.toFixed(2));
|
||
}
|
||
this.updateFreight(this.value3);
|
||
console.log("123", this.value3)
|
||
uni.setStorageSync('value3', this.value3);
|
||
},
|
||
validateValue4() {
|
||
let val = parseFloat(this.value4);
|
||
if (isNaN(val)) {
|
||
this.value4 = 0.1;
|
||
} else if (val > 999) {
|
||
this.value4 = 999;
|
||
} else if (val < 0.01) {
|
||
this.value4 = 0.01;
|
||
} else {
|
||
this.value4 = parseFloat(val.toFixed(2));
|
||
}
|
||
this.updateMinValue(this.value4);
|
||
uni.setStorageSync('value4', this.value4);
|
||
},
|
||
// 增加运费值的方法
|
||
increaseValue3() {
|
||
if (parseFloat(this.value3) < 99) {
|
||
this.value3 = parseFloat((parseFloat(this.value3) + 1).toFixed(2));
|
||
uni.setStorageSync('value3', this.value3);
|
||
console.log("增加运费值", this.value3)
|
||
// 同步到Vuex store
|
||
this.updateFreight(this.value3);
|
||
}
|
||
},
|
||
// 减少运费值的方法
|
||
decreaseValue3() {
|
||
if (parseFloat(this.value3) > -99) {
|
||
this.value3 = parseFloat((parseFloat(this.value3) - 1).toFixed(2));
|
||
uni.setStorageSync('value3', this.value3);
|
||
// 同步到Vuex store
|
||
this.updateFreight(this.value3);
|
||
}
|
||
},
|
||
// 增加最低值的方法
|
||
increaseValue4() {
|
||
if (parseFloat(this.value4) < 999) {
|
||
this.value4 = parseFloat((parseFloat(this.value4) + 0.01).toFixed(2));
|
||
uni.setStorageSync('value4', this.value4);
|
||
// 同步到Vuex store
|
||
this.updateMinValue(this.value4);
|
||
}
|
||
},
|
||
// 减少最低值的方法
|
||
decreaseValue4() {
|
||
if (parseFloat(this.value4) > 0.01) {
|
||
this.value4 = parseFloat((parseFloat(this.value4) - 0.01).toFixed(2));
|
||
uni.setStorageSync('value4', this.value4);
|
||
// 同步到Vuex store
|
||
this.updateMinValue(this.value4);
|
||
}
|
||
},
|
||
// 增加averageRange值的方法
|
||
increaseRange() {
|
||
if (this.averageRange < 12) {
|
||
this.averageRange++;
|
||
this.updateAverageRange(this.averageRange);
|
||
uni.setStorageSync('averageRange', this.averageRange);
|
||
}
|
||
},
|
||
// 减少averageRange值的方法
|
||
decreaseRange() {
|
||
if (this.averageRange > 2) {
|
||
this.averageRange--;
|
||
this.updateAverageRange(this.averageRange);
|
||
uni.setStorageSync('averageRange', this.averageRange);
|
||
}
|
||
},
|
||
|
||
// 纯浏览器端 JavaScript 实现
|
||
async getCookies(username, password) {
|
||
try {
|
||
// 第一步:先发送一个GET请求获取初始会话Cookie
|
||
const initResponse = await this.uniRequestPromise({
|
||
url: 'https://login.kongfz.com/Pc/Login/account',
|
||
method: 'GET'
|
||
});
|
||
|
||
// 提取初始响应中的Cookie
|
||
const initCookies = this.extractCookiesFromHeaders(initResponse.header);
|
||
// 第二步:发送登录请求,携带用户名和密码
|
||
const loginData = {
|
||
loginName: username,
|
||
loginPass: password
|
||
};
|
||
|
||
const loginResponse = await this.uniRequestPromise({
|
||
url: 'https://login.kongfz.com/Pc/Login/account',
|
||
method: 'POST',
|
||
data: loginData,
|
||
header: {
|
||
'Content-Type': 'application/x-www-form-urlencoded',
|
||
'Cookie': this.formatCookieHeader(initCookies)
|
||
}
|
||
});
|
||
|
||
// 提取登录响应中的Cookie
|
||
const loginCookies = this.extractCookiesFromHeaders(loginResponse.header);
|
||
|
||
// 合并所有Cookie
|
||
const allCookies = {
|
||
...initCookies,
|
||
...loginCookies
|
||
};
|
||
|
||
// 检查登录是否成功(根据实际返回判断)
|
||
const isLoginSuccess = this.checkLoginSuccess(loginResponse.data);
|
||
|
||
return {
|
||
success: isLoginSuccess,
|
||
cookies: allCookies,
|
||
responseData: loginResponse.data // 包含服务器返回的原始数据
|
||
};
|
||
|
||
} catch (error) {
|
||
console.error('登录请求失败:', error);
|
||
return {
|
||
success: false,
|
||
error: error.message || '登录请求发生错误'
|
||
};
|
||
}
|
||
},
|
||
/**
|
||
* 将 uni.request 转换为 Promise 形式
|
||
*/
|
||
uniRequestPromise(options) {
|
||
return new Promise((resolve, reject) => {
|
||
uni.request({
|
||
...options,
|
||
success: (res) => resolve(res),
|
||
fail: (err) => reject(err)
|
||
});
|
||
});
|
||
},
|
||
|
||
/**
|
||
* 从响应头中提取 Cookies
|
||
*/
|
||
extractCookiesFromHeaders(headers) {
|
||
const cookies = {};
|
||
const cookieHeaders = headers['Set-Cookie'] || headers['set-cookie'];
|
||
|
||
if (!cookieHeaders) return cookies;
|
||
|
||
// 处理可能是数组或字符串的 Cookie 头
|
||
const cookieList = Array.isArray(cookieHeaders) ?
|
||
cookieHeaders : [cookieHeaders];
|
||
|
||
cookieList.forEach(cookieStr => {
|
||
// 提取 cookie 名值对(忽略路径、过期时间等属性)
|
||
const cookieParts = cookieStr.split(';')[0].split('=');
|
||
if (cookieParts.length >= 2) {
|
||
cookies[cookieParts[0].trim()] = cookieParts[1].trim();
|
||
}
|
||
});
|
||
|
||
return cookies;
|
||
},
|
||
|
||
/**
|
||
* 将 Cookie 对象格式化为请求头字符串
|
||
*/
|
||
formatCookieHeader(cookies) {
|
||
return Object.entries(cookies)
|
||
.map(([key, value]) => `${key}=${value}`)
|
||
.join('; ');
|
||
},
|
||
|
||
/**
|
||
* 检查登录是否成功(根据实际接口返回调整)
|
||
*/
|
||
checkLoginSuccess(responseData) {
|
||
// 检查是否需要手机验证登录
|
||
if (responseData.extInfo && responseData.extInfo.action === "redirect" &&
|
||
responseData.extInfo.uri.includes("请使用手机号验证登录")) {
|
||
return false;
|
||
}
|
||
|
||
// 这里需要根据实际返回的数据结构判断登录是否成功
|
||
// 示例:假设返回包含 success: true 或 code: 200
|
||
if (responseData.success === true || responseData.code === 200) {
|
||
return true;
|
||
}
|
||
|
||
// 默认返回 false
|
||
return false;
|
||
},
|
||
// 处理登录按钮点击事件
|
||
click() {
|
||
if (!this.username || !this.password) {
|
||
uni.showToast({
|
||
title: '请输入账号和密码',
|
||
icon: 'none',
|
||
duration: 2500
|
||
});
|
||
return;
|
||
}
|
||
// TODO: 实现登录逻辑
|
||
console.log('登录请求,用户名:', this.username, '密码:', this.password);
|
||
// 这里可以调用登录API
|
||
},
|
||
// 新增方法:自动登录
|
||
async autoLogin(username, password) {
|
||
try {
|
||
console.log('尝试自动登录...');
|
||
this.isLogging = true;
|
||
|
||
const result = await this.getCookies(username, password);
|
||
|
||
if (result.cookies && result.cookies.PHPSESSID) {
|
||
// 保存cookies
|
||
uni.setStorageSync('cookies', result.cookies.PHPSESSID);
|
||
uni.setStorageSync('UserInfoCookies', result.cookies.PHPSESSID);
|
||
|
||
// 获取用户信息
|
||
await this.getUserInfo(result.cookies.PHPSESSID);
|
||
|
||
// 更新登录状态
|
||
this.isLoggedIn = true;
|
||
this.username = username;
|
||
|
||
console.log('自动登录成功');
|
||
return true; // 返回登录成功
|
||
} else {
|
||
console.error('自动登录失败:未获取到有效cookie');
|
||
return false;
|
||
}
|
||
} catch (error) {
|
||
console.error('自动登录失败:', error);
|
||
return false;
|
||
} finally {
|
||
this.isLogging = false;
|
||
}
|
||
},
|
||
|
||
// 新增方法:验证cookie有效性
|
||
async verifyCookieValid(cookie, username, password) {
|
||
try {
|
||
// 使用cookie发送一个简单请求验证有效性
|
||
const [err, res] = await uni.request({
|
||
url: 'https://search.kongfz.com/common-web/v1/api/userInfo',
|
||
method: 'GET',
|
||
header: {
|
||
'Cookie': `PHPSESSID=${cookie}`
|
||
}
|
||
});
|
||
|
||
// 如果请求成功且返回正常状态,cookie有效
|
||
if (!err && res.data && res.data.status === 1) {
|
||
console.log('Cookie验证有效');
|
||
this.isLoggedIn = true; // 确保设置登录状态
|
||
return true;
|
||
}
|
||
|
||
// cookie无效,尝试重新登录
|
||
console.log('Cookie已失效,尝试重新登录');
|
||
if (username && password) {
|
||
const loginSuccess = await this.autoLogin(username, password);
|
||
return loginSuccess; // 返回自动登录结果
|
||
}
|
||
return false;
|
||
|
||
} catch (error) {
|
||
console.error('验证cookie有效性出错:', error);
|
||
return false;
|
||
}
|
||
},
|
||
// 处理记住密码选项变化
|
||
handleRememberPasswordChange(e) {
|
||
this.rememberPassword = e.detail.value.length > 0;
|
||
console.log('记住密码设置变更为:', this.rememberPassword);
|
||
// 保存设置到本地存储
|
||
uni.setStorageSync('rememberPassword', this.rememberPassword);
|
||
},
|
||
// 显示添加账号弹窗
|
||
showAddAccount() {
|
||
this.newAccount = { username: '', password: '' }; // 清空新增账号输入框
|
||
this.$refs.accountPopup.open(); // 使用ref打开弹窗
|
||
console.log('显示添加账号弹窗');
|
||
},
|
||
// 关闭弹窗
|
||
closePopup() {
|
||
this.$refs.accountPopup.close();
|
||
},
|
||
// 添加新账号
|
||
async addAccount() {
|
||
if (!this.newAccount.username || !this.newAccount.password) {
|
||
uni.showToast({
|
||
title: '账号或密码不能为空',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 检查账号是否已存在
|
||
const isDuplicate = this.accounts.some(account => account.username === this.newAccount.username);
|
||
if (isDuplicate) {
|
||
uni.showModal({
|
||
title: '账号已存在',
|
||
content: '该账号已添加,不可重复添加',
|
||
showCancel: false
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 显示加载状态
|
||
uni.showLoading({
|
||
title: '正在验证账号...',
|
||
mask: true
|
||
});
|
||
|
||
try {
|
||
// 尝试使用账号密码登录验证
|
||
const result = await this.getCookies(this.newAccount.username, this.newAccount.password);
|
||
|
||
// 隐藏加载
|
||
uni.hideLoading();
|
||
|
||
// 检查是否需要手机验证登录
|
||
if (result.responseData && result.responseData.extInfo &&
|
||
result.responseData.extInfo.action === "redirect" &&
|
||
result.responseData.extInfo.uri && result.responseData.extInfo.uri.includes("请使用手机号验证登录")) {
|
||
uni.showModal({
|
||
title: '账号需要验证',
|
||
content: '该账号需要手机验证,请添加其他账号',
|
||
showCancel: false
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 检查其他重定向情况
|
||
if (result.responseData && result.responseData.extInfo &&
|
||
result.responseData.extInfo.action === "redirect") {
|
||
uni.showModal({
|
||
title: '账号异常',
|
||
content: '账号登录异常,请检查账号后重试',
|
||
showCancel: false
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 检查常见错误情况
|
||
if (result.responseData && (result.responseData.errType === "102" ||
|
||
[102, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009].includes(result.responseData.errCode))) {
|
||
|
||
// 准备错误消息
|
||
let errorMsg;
|
||
switch (result.responseData.errCode) {
|
||
case 102: errorMsg = '用户名不能为空'; break;
|
||
case 1000: errorMsg = '授权码错误或已过期'; break;
|
||
case 1001: errorMsg = '用户不存在'; break;
|
||
case 1009: errorMsg = '调用次数已达上限'; break;
|
||
default: errorMsg = result.responseData.errInfo || '账号登录异常';
|
||
}
|
||
|
||
uni.showModal({
|
||
title: '账号验证失败',
|
||
content: errorMsg,
|
||
showCancel: false
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 验证成功,获取到了有效cookies,添加账号
|
||
if (result.cookies && result.cookies.PHPSESSID) {
|
||
this.accounts.push({
|
||
username: this.newAccount.username,
|
||
password: this.newAccount.password,
|
||
isActive: false
|
||
});
|
||
this.$refs.accountPopup.close(); // 关闭弹窗
|
||
uni.setStorageSync('accounts', JSON.stringify(this.accounts)); // 保存账号列表
|
||
uni.showToast({
|
||
title: '账号验证成功并已添加',
|
||
icon: 'success'
|
||
});
|
||
} else {
|
||
uni.showModal({
|
||
title: '账号验证失败',
|
||
content: '无法获取有效登录信息,请检查账号密码',
|
||
showCancel: false
|
||
});
|
||
}
|
||
} catch (error) {
|
||
uni.hideLoading();
|
||
console.error('验证账号时出错:', error);
|
||
uni.showModal({
|
||
title: '验证失败',
|
||
content: '网络异常或服务器错误,请稍后重试',
|
||
showCancel: false
|
||
});
|
||
}
|
||
},
|
||
// 设置账号为当前使用
|
||
async setAsActive(index) {
|
||
// 显示加载状态
|
||
uni.showLoading({
|
||
title: '正在切换账号...',
|
||
mask: true
|
||
});
|
||
|
||
try {
|
||
// 获取要切换的账号信息
|
||
const targetAccount = this.accounts[index];
|
||
|
||
// 清除原有的cookie
|
||
uni.removeStorageSync('cookies');
|
||
uni.removeStorageSync('UserInfoCookies');
|
||
|
||
// 尝试使用账号密码登录获取新cookie
|
||
const result = await this.getCookies(targetAccount.username, targetAccount.password);
|
||
|
||
// 检查是否登录成功
|
||
if (result.cookies && result.cookies.PHPSESSID) {
|
||
// 更新账号状态
|
||
this.accounts.forEach(acc => acc.isActive = false);
|
||
this.accounts[index].isActive = true;
|
||
this.currentAccountIndex = index;
|
||
|
||
// 保存cookie到本地存储
|
||
uni.setStorageSync('cookies', result.cookies.PHPSESSID);
|
||
uni.setStorageSync('UserInfoCookies', result.cookies.PHPSESSID);
|
||
uni.setStorageSync('KongfzUserName', targetAccount.username);
|
||
|
||
// 如果设置了记住密码,则保存密码
|
||
if (this.rememberPassword) {
|
||
uni.setStorageSync('KongfzPassword', targetAccount.password);
|
||
}
|
||
|
||
// 保存更新后的账号列表
|
||
uni.setStorageSync('accounts', JSON.stringify(this.accounts));
|
||
uni.setStorageSync('currentAccountIndex', index);
|
||
|
||
// 获取用户信息
|
||
await this.getUserInfo(result.cookies.PHPSESSID);
|
||
|
||
// 更新登录状态和当前用户名
|
||
this.isLoggedIn = true;
|
||
this.username = targetAccount.username;
|
||
this.password = targetAccount.password;
|
||
|
||
uni.showToast({
|
||
title: '已切换到备用账号',
|
||
icon: 'success'
|
||
});
|
||
} else {
|
||
// 登录失败
|
||
let errorMsg = '账号登录失败,无法切换';
|
||
|
||
// 检查是否需要手机验证
|
||
if (result.responseData && result.responseData.extInfo &&
|
||
result.responseData.extInfo.action === "redirect" &&
|
||
result.responseData.extInfo.uri && result.responseData.extInfo.uri.includes("请使用手机号验证登录")) {
|
||
errorMsg = '该账号需要手机验证,无法切换';
|
||
}
|
||
|
||
uni.showModal({
|
||
title: '切换失败',
|
||
content: errorMsg,
|
||
showCancel: false
|
||
});
|
||
}
|
||
} catch (error) {
|
||
console.error('切换账号失败:', error);
|
||
uni.showModal({
|
||
title: '切换失败',
|
||
content: '网络异常或服务器错误,请稍后重试',
|
||
showCancel: false
|
||
});
|
||
} finally {
|
||
uni.hideLoading();
|
||
}
|
||
},
|
||
// 删除账号
|
||
removeAccount(index) {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '确定要删除此账号吗?',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
// 检查是否删除的是当前活跃账号
|
||
const isActiveAccount = this.accounts[index].isActive;
|
||
|
||
// 删除账号
|
||
this.accounts.splice(index, 1);
|
||
|
||
// 保存更新后的账号列表
|
||
uni.setStorageSync('accounts', JSON.stringify(this.accounts));
|
||
|
||
// 处理删除后的情况
|
||
if (this.accounts.length === 0) {
|
||
// 如果没有账号了,清除登录状态
|
||
this.isLoggedIn = false;
|
||
this.username = '';
|
||
this.password = '';
|
||
uni.removeStorageSync('KongfzUserName');
|
||
uni.removeStorageSync('KongfzPassword');
|
||
uni.removeStorageSync('UserInfoCookies');
|
||
uni.removeStorageSync('cookies');
|
||
this.userInfo = null;
|
||
uni.showToast({
|
||
title: '所有账号已删除,请重新登录',
|
||
icon: 'none'
|
||
});
|
||
} else if (isActiveAccount) {
|
||
// 如果删除的是当前使用账号,则切换到第一个账号
|
||
this.setAsActive(0);
|
||
}
|
||
|
||
uni.showToast({
|
||
title: '账号删除成功',
|
||
icon: 'success'
|
||
});
|
||
}
|
||
}
|
||
});
|
||
},
|
||
// 处理账号切换事件
|
||
handleAccountSwitched(event) {
|
||
// 在这里处理账号切换事件的逻辑
|
||
console.log('账号切换事件:', event);
|
||
|
||
// 重新加载账号列表
|
||
try {
|
||
const savedAccounts = uni.getStorageSync('accounts');
|
||
if (savedAccounts) {
|
||
this.accounts = JSON.parse(savedAccounts);
|
||
|
||
// 获取当前使用的账号索引
|
||
const currentIndex = uni.getStorageSync('currentAccountIndex');
|
||
this.currentAccountIndex = currentIndex !== '' ? parseInt(currentIndex) : 0;
|
||
|
||
// 更新当前用户名和密码
|
||
if (this.accounts.length > 0 && this.accounts[this.currentAccountIndex]) {
|
||
this.username = this.accounts[this.currentAccountIndex].username;
|
||
this.password = this.accounts[this.currentAccountIndex].password;
|
||
}
|
||
|
||
// 如果当前已登录,尝试获取用户信息
|
||
if (this.isLoggedIn) {
|
||
const cookies = uni.getStorageSync('UserInfoCookies');
|
||
if (cookies) {
|
||
this.getUserInfo(cookies);
|
||
}
|
||
}
|
||
|
||
console.log('账号切换后更新界面完成');
|
||
}
|
||
} catch (error) {
|
||
console.error('处理账号切换事件失败:', error);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
/* 统一设置u-demo-block的顶部外边距为40rpx,形成模块间的间距 */
|
||
.u-demo-block {
|
||
margin-top: 10rpx;
|
||
background-color: #ffffff;
|
||
padding: 10rpx;
|
||
border-radius: 10rpx;
|
||
}
|
||
|
||
::v-deep .login-form-row.data-v-666e420a {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 1rpx;
|
||
gap: 20rpx;
|
||
}
|
||
|
||
.user-info {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 20rpx;
|
||
background-color: #f8f8f8;
|
||
border-radius: 12rpx;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.user-avatar {
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
border-radius: 50rpx;
|
||
overflow: hidden;
|
||
margin-right: 20rpx;
|
||
border: 2rpx solid #eee;
|
||
}
|
||
|
||
.user-avatar image {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
|
||
.user-details {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 10rpx;
|
||
}
|
||
|
||
.username {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #333;
|
||
}
|
||
|
||
.user-area {
|
||
font-size: 24rpx;
|
||
color: #666;
|
||
}
|
||
|
||
.logout {
|
||
font-size: 24rpx;
|
||
color: #666;
|
||
padding: 8rpx 16rpx;
|
||
background-color: #f5f5f5;
|
||
border-radius: 6rpx;
|
||
cursor: pointer;
|
||
align-self: center;
|
||
margin-left: auto;
|
||
border: 1rpx solid #e0e0e0;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.logout:active {
|
||
background-color: #e0e0e0;
|
||
}
|
||
|
||
.remember-password {
|
||
padding: 0 20rpx;
|
||
margin-top: -10rpx;
|
||
margin-bottom: 15rpx;
|
||
}
|
||
|
||
.checkbox-label {
|
||
display: flex;
|
||
align-items: center;
|
||
font-size: 24rpx;
|
||
color: #666;
|
||
}
|
||
|
||
.checkbox-label text {
|
||
margin-left: 6rpx;
|
||
}
|
||
|
||
.login-button {
|
||
margin-top: 30rpx;
|
||
width: 100%;
|
||
background-color: #ffffff;
|
||
color: #000000;
|
||
border: 1px solid #000000;
|
||
}
|
||
|
||
/* 模块标题区域样式 */
|
||
.section-header {
|
||
display: flex;
|
||
flex-direction: row;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 15rpx;
|
||
}
|
||
|
||
/* 模块主标题样式 */
|
||
.section-title {
|
||
font-size: 32rpx;
|
||
color: #333333;
|
||
font-weight: bold;
|
||
}
|
||
|
||
/* 模块副标题样式 */
|
||
.section-subtitle {
|
||
font-size: 24rpx;
|
||
color: #888888;
|
||
text-align: right;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* 价格参考文本区域样式 */
|
||
.price-reference {
|
||
padding: 15rpx 0;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
/* 高亮文本样式 */
|
||
.highlight-text {
|
||
color: #000000;
|
||
font-weight: bold;
|
||
}
|
||
|
||
/* 均价范围控制区域样式 */
|
||
.average-range-control {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-top: 15rpx;
|
||
}
|
||
|
||
/* 范围标签样式 */
|
||
.range-label {
|
||
font-size: 26rpx;
|
||
color: #666666;
|
||
}
|
||
|
||
/* 范围控制区域样式 */
|
||
.range-control {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
/* 范围控制按钮样式 */
|
||
.range-btn {
|
||
width: 60rpx;
|
||
height: 60rpx;
|
||
line-height: 60rpx;
|
||
text-align: center;
|
||
background-color: #f5f5f5;
|
||
border-radius: 8rpx;
|
||
font-size: 32rpx;
|
||
color: #333333;
|
||
position: relative;
|
||
}
|
||
|
||
/* 第一个按钮显示减号 */
|
||
.range-control .range-btn:first-child::before {
|
||
content: "-";
|
||
position: absolute;
|
||
left: 50%;
|
||
top: 50%;
|
||
transform: translate(-50%, -50%);
|
||
font-weight: bold;
|
||
}
|
||
|
||
/* 最后一个按钮显示加号 */
|
||
.range-control .range-btn:last-child::before {
|
||
content: "+";
|
||
position: absolute;
|
||
left: 50%;
|
||
top: 50%;
|
||
transform: translate(-50%, -50%);
|
||
font-weight: bold;
|
||
}
|
||
|
||
/* 范围值显示样式 */
|
||
.range-value {
|
||
width: 80rpx;
|
||
text-align: center;
|
||
font-size: 28rpx;
|
||
color: #333333;
|
||
}
|
||
|
||
/* 数字控制器容器样式 */
|
||
.number-control-wrapper {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10rpx;
|
||
padding: 10rpx;
|
||
}
|
||
|
||
/* 控制按钮基础样式 */
|
||
.number-control-btn {
|
||
width: 60rpx;
|
||
height: 60rpx;
|
||
background-color: #f5f5f5;
|
||
border-radius: 8rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 32rpx;
|
||
color: #333;
|
||
cursor: pointer;
|
||
}
|
||
|
||
/* 按钮悬停效果 */
|
||
.number-control-btn:active {
|
||
background-color: #e0e0e0;
|
||
}
|
||
|
||
/* 减号按钮样式 */
|
||
.minus-btn {
|
||
font-weight: bold;
|
||
}
|
||
|
||
/* 加号按钮样式 */
|
||
.plus-btn {
|
||
font-weight: bold;
|
||
}
|
||
|
||
/* 自定义数字输入框样式 */
|
||
.custom-input-box {
|
||
margin: 0 20rpx;
|
||
width: 200rpx;
|
||
height: 60rpx;
|
||
text-align: center;
|
||
background-color: #f8f8f8;
|
||
border: 1px solid #dcdfe6;
|
||
border-radius: 8rpx;
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
}
|
||
|
||
/* 运费模板选择器的样式,包括边框、圆角、内边距、背景色、定位和顶部外边距 */
|
||
.freight-picker {
|
||
border: 1rpx solid #dcdfe6;
|
||
border-radius: 8rpx;
|
||
padding: 20rpx;
|
||
background-color: #fff;
|
||
position: relative;
|
||
margin-top: 20rpx;
|
||
}
|
||
|
||
/* 选择器内容区域的样式,弹性布局实现内容左右分布,设置字体大小和颜色 */
|
||
.picker-content {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
font-size: 28rpx;
|
||
color: #606266;
|
||
}
|
||
|
||
/* 选择器箭头的样式,通过边框设置三角形外观 */
|
||
.picker-content .arrow {
|
||
display: inline-block;
|
||
width: 0;
|
||
height: 0;
|
||
border-left: 8rpx solid transparent;
|
||
border-right: 8rpx solid transparent;
|
||
border-top: 12rpx solid #909399;
|
||
margin-left: 10rpx;
|
||
}
|
||
|
||
/* 自动提交模块容器的样式,包括背景色、内边距、圆角和顶部外边距 */
|
||
.auto-submit-container {
|
||
background-color: #f5f5f5;
|
||
padding: 20rpx;
|
||
border-radius: 10rpx;
|
||
margin-top: 40rpx;
|
||
}
|
||
|
||
/* 自动提交模块标题部分的底部外边距样式 */
|
||
/* .section-title {
|
||
margin-bottom: 20rpx;
|
||
} */
|
||
|
||
/* 自动提交模块标题文本的样式,包括颜色、字体大小和加粗 */
|
||
.title-text {
|
||
color: #333333;
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
}
|
||
|
||
/* 开关项的样式,弹性布局实现内容左右分布,设置内边距 */
|
||
.switch-item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 15rpx 0;
|
||
}
|
||
|
||
/* 开关项文本的样式,设置颜色和字体大小 */
|
||
.switch-item text {
|
||
color: #666666;
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
/* 核心布局方案 */
|
||
.login-form-row {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 20rpx;
|
||
gap: 20rpx;
|
||
}
|
||
|
||
/* 输入框宽度控制 */
|
||
.login-input {
|
||
flex: 3;
|
||
/* 输入框占3份 */
|
||
min-width: 200rpx;
|
||
/* 最小宽度保障 */
|
||
border-radius: 8rpx;
|
||
}
|
||
|
||
|
||
/* 按钮样式覆盖 */
|
||
.u-button {
|
||
flex-shrink: 0 !important;
|
||
/* 禁止收缩 */
|
||
padding: 0 20rpx !important;
|
||
}
|
||
|
||
::v-depp .u-border {
|
||
border-width: 0.5rpx !important;
|
||
border-color: #dadbde !important;
|
||
border-style: solid;
|
||
}
|
||
|
||
::v-deep .u-button--square.data-v-2bf0e569 {
|
||
border-bottom-left-radius: 10rpx;
|
||
border-bottom-right-radius: 10rpx;
|
||
border-top-left-radius: 10rpx;
|
||
border-top-right-radius: 10rpx;
|
||
}
|
||
|
||
/* 微信小程序需用 ::v-deep */
|
||
::v-deep .u-textarea__field.data-v-09988a29 {
|
||
flex: 1;
|
||
font-size: 29rpx;
|
||
color: #606266;
|
||
width: 100%;
|
||
}
|
||
|
||
/* 唯一class控制布局 */
|
||
.custom-layout {
|
||
display: flex !important;
|
||
justify-content: space-between !important;
|
||
/* align-items: center !important; */
|
||
width: 100% !important;
|
||
padding: 20rpx 0 !important;
|
||
}
|
||
|
||
/* 分段器按钮字体变大,适用于uView2的u-subsection */
|
||
::v-deep .u-subsection__item {
|
||
font-size: 36rpx !important;
|
||
height: 70rpx !important;
|
||
line-height: 70rpx !important;
|
||
padding: 0 30rpx !important;
|
||
}
|
||
|
||
::v-deep .u-subsection__item--active {
|
||
font-size: 38rpx !important;
|
||
font-weight: bold !important;
|
||
color: #111 !important;
|
||
background: #2979ff !important;
|
||
border-color: #2979ff !important;
|
||
}
|
||
|
||
.u-demo-block__content {
|
||
height: auto !important;
|
||
overflow: visible !important;
|
||
}
|
||
|
||
::v-deep .u-subsection {
|
||
margin-bottom: 40rpx !important;
|
||
margin-top: 10rpx !important;
|
||
min-height: 70rpx !important;
|
||
width: 100% !important;
|
||
}
|
||
|
||
.price-reference {
|
||
margin-bottom: 40rpx !important;
|
||
margin-top: 30rpx !important;
|
||
line-height: 1.8;
|
||
min-height: 60rpx;
|
||
word-break: break-all;
|
||
}
|
||
|
||
.u-demo-block__content>view[style*="margin-top:20rpx"] {
|
||
margin-top: 40rpx !important;
|
||
}
|
||
|
||
::v-deep .u-subsection--button__bar.data-v-78c1286e {
|
||
background-color: #c5c5c5;
|
||
border-radius: 3rpx !important;
|
||
}
|
||
|
||
/* 多账号管理样式 */
|
||
.accounts-manager {
|
||
margin-top: 20rpx;
|
||
padding: 0 20rpx;
|
||
}
|
||
|
||
.account-list {
|
||
margin-top: 10rpx;
|
||
}
|
||
|
||
.account-item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 15rpx 0;
|
||
border-bottom: 1rpx solid #eee;
|
||
}
|
||
|
||
.account-item:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.account-info {
|
||
flex: 1;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.account-username {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.account-status {
|
||
font-size: 24rpx;
|
||
color: #666;
|
||
padding: 4rpx 10rpx;
|
||
border-radius: 6rpx;
|
||
border: 1rpx solid #e0e0e0;
|
||
}
|
||
|
||
.account-status.active {
|
||
color: #fff;
|
||
background-color: #007AFF;
|
||
border-color: #007AFF;
|
||
}
|
||
|
||
.account-actions {
|
||
display: flex;
|
||
gap: 10rpx;
|
||
}
|
||
|
||
.action-btn {
|
||
font-size: 24rpx;
|
||
color: #007AFF;
|
||
padding: 4rpx 10rpx;
|
||
border: 1rpx solid #007AFF;
|
||
border-radius: 6rpx;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.action-btn.delete {
|
||
color: #f00;
|
||
border-color: #f00;
|
||
}
|
||
|
||
.action-btn:active {
|
||
background-color: #e0e0e0;
|
||
}
|
||
|
||
.add-account {
|
||
font-size: 24rpx;
|
||
color: #007AFF;
|
||
padding: 6rpx 12rpx;
|
||
border-radius: 6rpx;
|
||
cursor: pointer;
|
||
background-color: #f0f8ff;
|
||
border: 1rpx solid #007AFF;
|
||
display: inline-block;
|
||
}
|
||
|
||
/* 添加账号弹窗样式 */
|
||
.add-account-popup {
|
||
padding: 40rpx;
|
||
background-color: #fff;
|
||
border-radius: 20rpx;
|
||
width: 600rpx;
|
||
}
|
||
|
||
.popup-title {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #333;
|
||
margin-bottom: 30rpx;
|
||
text-align: center;
|
||
}
|
||
|
||
.popup-form {
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.popup-input {
|
||
margin-bottom: 30rpx;
|
||
border: 1rpx solid #dcdfe6;
|
||
border-radius: 8rpx;
|
||
padding: 10rpx 20rpx;
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.popup-actions {
|
||
display: flex;
|
||
justify-content: space-around;
|
||
gap: 20rpx;
|
||
}
|
||
|
||
.popup-btn {
|
||
flex: 1;
|
||
height: 80rpx;
|
||
line-height: 80rpx;
|
||
font-size: 32rpx;
|
||
border-radius: 8rpx;
|
||
border: none;
|
||
}
|
||
|
||
.popup-btn.cancel {
|
||
background-color: #f5f5f5;
|
||
color: #333;
|
||
}
|
||
|
||
.popup-btn.confirm {
|
||
background-color: #007AFF;
|
||
color: #fff;
|
||
}
|
||
</style> |