f
This commit is contained in:
@@ -26,10 +26,10 @@ export default defineUniPages({
|
||||
selectedIconPath: 'static/tabbar/home-active.png',
|
||||
},
|
||||
{
|
||||
pagePath: 'pages/report',
|
||||
text: '报告',
|
||||
iconPath: 'static/tabbar/report.png',
|
||||
selectedIconPath: 'static/tabbar/report-active.png',
|
||||
pagePath: 'pages/toolbox/index',
|
||||
text: '工具',
|
||||
iconPath: 'static/tabbar/toolbox.png',
|
||||
selectedIconPath: 'static/tabbar/toolbox-active.png',
|
||||
},
|
||||
{
|
||||
pagePath: 'pages/mine',
|
||||
|
||||
@@ -1087,6 +1087,63 @@ export const toolboxItems = [
|
||||
index: '热度',
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'star',
|
||||
name: '星座运势',
|
||||
desc: '查询十二星座今日运势(娱乐)',
|
||||
icon: 'i-carbon-star',
|
||||
fields: [
|
||||
{ key: 'astro', label: '星座', type: 'select', mode: 'selector', options: [
|
||||
{ label: '白羊座', value: '白羊座' },
|
||||
{ label: '金牛座', value: '金牛座' },
|
||||
{ label: '双子座', value: '双子座' },
|
||||
{ label: '巨蟹座', value: '巨蟹座' },
|
||||
{ label: '狮子座', value: '狮子座' },
|
||||
{ label: '处女座', value: '处女座' },
|
||||
{ label: '天秤座', value: '天秤座' },
|
||||
{ label: '天蝎座', value: '天蝎座' },
|
||||
{ label: '射手座', value: '射手座' },
|
||||
{ label: '摩羯座', value: '摩羯座' },
|
||||
{ label: '水瓶座', value: '水瓶座' },
|
||||
{ label: '双鱼座', value: '双鱼座' },
|
||||
], placeholder: '请选择星座' },
|
||||
],
|
||||
validate: (form) => (form.astro || '').length > 0,
|
||||
validateMsg: '请选择星座',
|
||||
resultType: 'list',
|
||||
resultLabels: {
|
||||
type: '运势类型',
|
||||
content: '运势内容',
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'tianqishiju',
|
||||
name: '天气诗句',
|
||||
desc: '根据天气类型随机返回经典诗句',
|
||||
icon: 'i-carbon-cloud',
|
||||
fields: [
|
||||
{ key: 'tqtype', label: '天气类型', type: 'select', mode: 'selector', options: [
|
||||
{ label: '风', value: 1 },
|
||||
{ label: '云', value: 2 },
|
||||
{ label: '雨', value: 3 },
|
||||
{ label: '雪', value: 4 },
|
||||
{ label: '霜', value: 5 },
|
||||
{ label: '露', value: 6 },
|
||||
{ label: '雾', value: 7 },
|
||||
{ label: '雷', value: 8 },
|
||||
{ label: '晴', value: 9 },
|
||||
{ label: '阴', value: 10 },
|
||||
], placeholder: '可选,选择天气类型' },
|
||||
],
|
||||
validate: () => true,
|
||||
validateMsg: '',
|
||||
resultLabels: {
|
||||
content: '诗句',
|
||||
author: '作者',
|
||||
source: '出处',
|
||||
weather: '天气',
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'verse',
|
||||
name: '诗词名句',
|
||||
@@ -1457,7 +1514,9 @@ export const toolboxItems = [
|
||||
resultLabels: {
|
||||
name: '名称',
|
||||
type_name: '分类',
|
||||
explain: '说明',
|
||||
explain: '分类说明',
|
||||
contain: '包含类型',
|
||||
tip: '投放提示',
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -2214,17 +2273,19 @@ export const toolboxItems = [
|
||||
},
|
||||
{
|
||||
key: 'anslajifenlei',
|
||||
name: '按师垃圾分类',
|
||||
desc: '按垃圾分类指南',
|
||||
name: '垃圾分类问答',
|
||||
desc: '随机出现一个物品,选出它属于哪种垃圾分类,考考你的环保知识',
|
||||
icon: 'i-carbon-recycle',
|
||||
autoQuery: true,
|
||||
isGame: true,
|
||||
fields: [],
|
||||
validate: () => true,
|
||||
validateMsg: '',
|
||||
resultType: 'list',
|
||||
resultLabels: {
|
||||
name: '名称',
|
||||
type_name: '分类',
|
||||
name: { label: '物品名称' },
|
||||
type: { label: '正确分类', hidden: true },
|
||||
type_name: { label: '分类名称', hidden: true },
|
||||
explain: { label: '分类说明', hidden: true },
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -2268,6 +2329,7 @@ export const toolboxItems = [
|
||||
content: '问候语',
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
key: 'story',
|
||||
name: '故事大全',
|
||||
|
||||
@@ -74,6 +74,16 @@
|
||||
"navigationBarTextStyle": "black"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/inquire/list",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationBarTitleText": "车辆查询服务",
|
||||
"navigationStyle": "default",
|
||||
"navigationBarBackgroundColor": "#ffffff",
|
||||
"navigationBarTextStyle": "black"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/legal/authorization",
|
||||
"type": "page",
|
||||
@@ -128,7 +138,7 @@
|
||||
"path": "pages/toolbox/index",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationBarTitleText": "实用工具",
|
||||
"navigationBarTitleText": "工具分类",
|
||||
"navigationStyle": "default",
|
||||
"navigationBarBackgroundColor": "#ffffff",
|
||||
"navigationBarTextStyle": "black"
|
||||
@@ -161,10 +171,10 @@
|
||||
"selectedIconPath": "static/tabbar/home-active.png"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/report",
|
||||
"text": "报告",
|
||||
"iconPath": "static/tabbar/report.png",
|
||||
"selectedIconPath": "static/tabbar/report-active.png"
|
||||
"pagePath": "pages/toolbox/index",
|
||||
"text": "工具",
|
||||
"iconPath": "static/tabbar/toolbox.png",
|
||||
"selectedIconPath": "static/tabbar/toolbox-active.png"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/mine",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
<script setup>
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { computed, onUnmounted, ref } from 'vue'
|
||||
import { getProductByEn, getUserDetail, postAuthSendSmsQuery, postPayPayment, postQueryService, postUploadImage } from '@/api'
|
||||
@@ -21,12 +21,7 @@ const loading = ref(true)
|
||||
const productLoadOk = ref(false)
|
||||
const submitting = ref(false)
|
||||
const paying = ref(false)
|
||||
const featureData = ref<{
|
||||
product_name?: string
|
||||
description?: string
|
||||
sell_price?: number
|
||||
product_en?: string
|
||||
}>({})
|
||||
const featureData = ref({})
|
||||
|
||||
const queryId = ref('')
|
||||
const showPaySheet = ref(false)
|
||||
@@ -35,7 +30,7 @@ const vlphotoPreviewPath = ref('')
|
||||
const imageUrlUploading = ref(false)
|
||||
|
||||
const countdown = ref(0)
|
||||
let smsTimer: ReturnType<typeof setInterval> | null = null
|
||||
let smsTimer = null
|
||||
|
||||
const userTypeOptions = [
|
||||
{ text: 'ETC开户人', value: '1' },
|
||||
@@ -78,7 +73,7 @@ const isIdCardWomanValid = computed(() => /^\d{17}[\dX]$/i.test(formData.idCardW
|
||||
const isCreditCodeValid = computed(() => /^.{18}$/.test(formData.entCode || ''))
|
||||
|
||||
onLoad((options) => {
|
||||
feature.value = (options?.feature as string) || ''
|
||||
feature.value = (options?.feature) || ''
|
||||
void loadProduct()
|
||||
})
|
||||
|
||||
@@ -119,10 +114,7 @@ async function loadProduct() {
|
||||
}
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await getProductByEn(feature.value) as {
|
||||
code?: number
|
||||
data?: typeof featureData.value
|
||||
}
|
||||
const res = await getProductByEn(feature.value)
|
||||
if (res?.code === 200 && res.data) {
|
||||
featureData.value = res.data
|
||||
productLoadOk.value = true
|
||||
@@ -145,7 +137,7 @@ async function loadProduct() {
|
||||
}
|
||||
}
|
||||
|
||||
function readToken(): string {
|
||||
function readToken() {
|
||||
try {
|
||||
const t = uni.getStorageSync('token')
|
||||
return typeof t === 'string' ? t : ''
|
||||
@@ -155,17 +147,14 @@ function readToken(): string {
|
||||
}
|
||||
}
|
||||
|
||||
async function ensureLoginAndMobile(): Promise<boolean> {
|
||||
async function ensureLoginAndMobile() {
|
||||
if (!readToken()) {
|
||||
uni.showToast({ title: '请先登录', icon: 'none' })
|
||||
uni.navigateTo({ url: '/pages/login' })
|
||||
return false
|
||||
}
|
||||
try {
|
||||
const res = await getUserDetail() as {
|
||||
code?: number
|
||||
data?: { userInfo?: { mobile?: string } }
|
||||
}
|
||||
const res = await getUserDetail()
|
||||
const mobile = (res?.data?.userInfo?.mobile || '').trim()
|
||||
if (res?.code !== 200 || !/^1[3-9]\d{9}$/.test(mobile)) {
|
||||
uni.showModal({
|
||||
@@ -188,11 +177,11 @@ async function ensureLoginAndMobile(): Promise<boolean> {
|
||||
}
|
||||
|
||||
function validateField(
|
||||
field: string,
|
||||
value: unknown,
|
||||
ok: (v: unknown) => boolean,
|
||||
msg: string,
|
||||
): boolean {
|
||||
field,
|
||||
value,
|
||||
ok,
|
||||
msg,
|
||||
) {
|
||||
if (!isHasInput(field))
|
||||
return true
|
||||
if (!ok(value)) {
|
||||
@@ -202,7 +191,7 @@ function validateField(
|
||||
return true
|
||||
}
|
||||
|
||||
function validateAll(): boolean {
|
||||
function validateAll() {
|
||||
if (!formData.agreeToTerms) {
|
||||
uni.showToast({ title: '请阅读并同意用户协议与隐私政策', icon: 'none' })
|
||||
return false
|
||||
@@ -240,17 +229,17 @@ function validateAll(): boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
function onUserTypePick(e: { detail: { value: string | number } }) {
|
||||
function onUserTypePick(e) {
|
||||
const idx = Number(e.detail.value)
|
||||
formData.userType = userTypeOptions[idx]?.value ?? '1'
|
||||
}
|
||||
|
||||
function onAuthorizedPick(e: { detail: { value: string | number } }) {
|
||||
function onAuthorizedPick(e) {
|
||||
const idx = Number(e.detail.value)
|
||||
formData.authorized = authorizedOptions[idx]?.value ?? '1'
|
||||
}
|
||||
|
||||
function onFirstRegChange(e: { detail: { value: string } }) {
|
||||
function onFirstRegChange(e) {
|
||||
formData.firstRegistrationDate = (e.detail.value || '').slice(0, 7)
|
||||
}
|
||||
|
||||
@@ -285,7 +274,7 @@ async function sendSmsCode() {
|
||||
if (!(await ensureLoginAndMobile()))
|
||||
return
|
||||
try {
|
||||
const res = await postAuthSendSmsQuery({ mobile: formData.mobile, captchaVerifyParam: '' }) as { code?: number }
|
||||
const res = await postAuthSendSmsQuery({ mobile: formData.mobile, captchaVerifyParam: '' })
|
||||
if (res?.code === 200) {
|
||||
uni.showToast({ title: '验证码已发送', icon: 'none' })
|
||||
startSmsCountdown()
|
||||
@@ -296,7 +285,7 @@ async function sendSmsCode() {
|
||||
}
|
||||
}
|
||||
|
||||
function chooseImageFile(maxBytes: number): Promise<{ path: string, base64: string }> {
|
||||
function chooseImageFile(maxBytes) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
@@ -338,7 +327,7 @@ async function onPickImageUrl() {
|
||||
try {
|
||||
const { base64 } = await chooseImageFile(3 * 1024 * 1024)
|
||||
imageUrlUploading.value = true
|
||||
const up = await postUploadImage(base64) as { code?: number, data?: { url?: string }, msg?: string }
|
||||
const up = await postUploadImage(base64)
|
||||
if (up?.code === 200 && up.data?.url)
|
||||
formData.imageUrl = up.data.url
|
||||
else if (up?.msg)
|
||||
@@ -371,11 +360,7 @@ async function doCreateQuery(captchaVerifyParam = '') {
|
||||
const res = await postQueryService(feature.value, {
|
||||
data: enc,
|
||||
captchaVerifyParam,
|
||||
}) as {
|
||||
code?: number
|
||||
data?: { id?: string }
|
||||
msg?: string
|
||||
}
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -419,7 +404,7 @@ async function onConfirmPay() {
|
||||
return
|
||||
}
|
||||
try {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
await new Promise((resolve, reject) => {
|
||||
uni.showModal({
|
||||
title: '重要提示',
|
||||
content: '请确认您了解本服务为大数据报告查询,付款前请仔细阅读产品说明。是否继续支付?',
|
||||
@@ -443,17 +428,7 @@ async function onConfirmPay() {
|
||||
id: queryId.value,
|
||||
pay_method: 'wechat',
|
||||
pay_type: 'query',
|
||||
}) as {
|
||||
code?: number
|
||||
data?: {
|
||||
prepay_data?: Record<string, string>
|
||||
prepayData?: Record<string, string>
|
||||
prepay_id?: string
|
||||
prepayId?: string
|
||||
order_no?: string
|
||||
orderNo?: string
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (payRes?.code !== 200 || !payRes.data) {
|
||||
return
|
||||
@@ -478,7 +453,7 @@ async function onConfirmPay() {
|
||||
return
|
||||
}
|
||||
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
await new Promise((resolve, reject) => {
|
||||
uni.requestPayment({
|
||||
provider: 'wxpay',
|
||||
timeStamp: String(prepay.timeStamp ?? prepay.timestamp ?? ''),
|
||||
@@ -502,7 +477,7 @@ async function onConfirmPay() {
|
||||
resolve()
|
||||
},
|
||||
fail(err) {
|
||||
const msg = (err as { errMsg?: string })?.errMsg || '支付未完成'
|
||||
const msg = err?.errMsg || '支付未完成'
|
||||
uni.showToast({ title: msg.replace('requestPayment:fail ', ''), icon: 'none' })
|
||||
reject(err)
|
||||
},
|
||||
@@ -528,8 +503,15 @@ async function onConfirmPay() {
|
||||
</view>
|
||||
<scroll-view v-else scroll-y class="scroll page-inner">
|
||||
<view class="card-container">
|
||||
<!-- 顶部产品长图 -->
|
||||
<view class="inquire-banner">
|
||||
<image class="inquire-banner-img" src="/static/home/images/VIN.png" mode="widthFix" />
|
||||
<view class="inquire-banner-overlay">
|
||||
<text class="inquire-banner-title">{{ featureData.product_name || '查询服务' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="card-header">
|
||||
{{ featureData.product_name || feature || '查询' }}
|
||||
请输入查询信息
|
||||
</view>
|
||||
|
||||
<view class="section-row">
|
||||
@@ -577,7 +559,7 @@ async function onConfirmPay() {
|
||||
</view>
|
||||
<view v-if="isHasInput('mobile')" class="field">
|
||||
<text class="label">手机号</text>
|
||||
<input v-model="formData.mobile" class="input" type="number" maxlength="11" placeholder="请输入手机号" placeholder-class="ph">
|
||||
<input v-model="formData.mobile" class="input" type="number" :maxlength="11" placeholder="请输入手机号" placeholder-class="ph">
|
||||
</view>
|
||||
<view v-if="isHasInput('carLicense')" class="field">
|
||||
<text class="label">车牌号</text>
|
||||
@@ -654,7 +636,7 @@ async function onConfirmPay() {
|
||||
|
||||
<view v-if="isHasInput('verificationCode')" class="field code-row">
|
||||
<text class="label">验证码</text>
|
||||
<input v-model="formData.verificationCode" class="input flex1" maxlength="6" placeholder="请输入验证码" placeholder-class="ph">
|
||||
<input v-model="formData.verificationCode" class="input flex1" :maxlength="6" placeholder="请输入验证码" placeholder-class="ph">
|
||||
<view class="sms-btn" :class="{ disabled: isCountingDown || !isPhoneNumberValid }" @tap="sendSmsCode">
|
||||
{{ isCountingDown ? `${countdown}s重新获取` : '获取验证码' }}
|
||||
</view>
|
||||
@@ -750,6 +732,33 @@ async function onConfirmPay() {
|
||||
padding: 24rpx 24rpx 48rpx;
|
||||
}
|
||||
|
||||
/* 顶部产品图 */
|
||||
.inquire-banner {
|
||||
position: relative;
|
||||
border-radius: 16rpx;
|
||||
overflow: hidden;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.inquire-banner-img {
|
||||
width: 100%;
|
||||
max-height: 260rpx;
|
||||
display: block;
|
||||
}
|
||||
.inquire-banner-overlay {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: 16rpx 24rpx;
|
||||
background: linear-gradient(transparent, rgba(0,0,0,0.4));
|
||||
}
|
||||
.inquire-banner-title {
|
||||
font-size: 26rpx;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
text-shadow: 0 1rpx 4rpx rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.card-container {
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
|
||||
190
src/pages/inquire/list.vue
Normal file
190
src/pages/inquire/list.vue
Normal file
@@ -0,0 +1,190 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { getInquireCategoryConfig, getInquiryItemIconUrl } from '@/config/inquireCategories'
|
||||
|
||||
definePage({
|
||||
style: {
|
||||
navigationBarTitleText: '车辆查询服务',
|
||||
navigationStyle: 'default',
|
||||
navigationBarBackgroundColor: '#ffffff',
|
||||
navigationBarTextStyle: 'black',
|
||||
},
|
||||
})
|
||||
|
||||
const vehicleItems = computed(() => getInquireCategoryConfig('vehicle')?.items ?? [])
|
||||
|
||||
function goInquireFeature(feature: string) {
|
||||
uni.navigateTo({ url: `/pages/inquire/index?feature=${encodeURIComponent(feature)}` })
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="page-root">
|
||||
<scroll-view scroll-y class="scrollarea">
|
||||
<view class="page">
|
||||
<!-- 头部统计 -->
|
||||
<view class="list-header">
|
||||
<view class="list-header-icon">
|
||||
<view class="i-carbon-car" />
|
||||
</view>
|
||||
<view class="list-header-info">
|
||||
<text class="list-header-title">车辆查询服务</text>
|
||||
<text class="list-header-desc">共 {{ vehicleItems.length }} 项专业车况核验服务</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 服务列表 -->
|
||||
<view class="service-list">
|
||||
<view
|
||||
v-for="item in vehicleItems"
|
||||
:key="item.feature"
|
||||
class="service-item"
|
||||
@tap="goInquireFeature(item.feature)"
|
||||
>
|
||||
<view class="svc-icon-wrap">
|
||||
<image class="svc-icon" :src="getInquiryItemIconUrl(item)" mode="aspectFit" />
|
||||
</view>
|
||||
<view class="svc-content">
|
||||
<text class="svc-name">{{ item.name }}</text>
|
||||
<text class="svc-desc">{{ item.desc }}</text>
|
||||
</view>
|
||||
<text class="svc-arrow">›</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.page-root {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: linear-gradient(180deg, #f8faff 0%, #f3f5fb 100%);
|
||||
}
|
||||
|
||||
.scrollarea {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.page {
|
||||
padding: 24rpx 24rpx 40rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.list-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
padding: 28rpx 28rpx;
|
||||
background: linear-gradient(145deg, #ffffff 0%, #f7f8ff 100%);
|
||||
border-radius: 24rpx;
|
||||
border: 1rpx solid #e5e6f0;
|
||||
margin-bottom: 24rpx;
|
||||
box-shadow: 0 16rpx 40rpx rgba(15, 35, 52, 0.04),
|
||||
0 0 0 1rpx rgba(255, 255, 255, 0.5) inset;
|
||||
}
|
||||
|
||||
.list-header-icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 20rpx;
|
||||
background: linear-gradient(135deg, #e8f0fe, #d4e4fd);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 38rpx;
|
||||
color: #1768ff;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.list-header-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.list-header-title {
|
||||
display: block;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #1d2129;
|
||||
margin-bottom: 6rpx;
|
||||
}
|
||||
|
||||
.list-header-desc {
|
||||
display: block;
|
||||
font-size: 24rpx;
|
||||
color: #86909c;
|
||||
}
|
||||
|
||||
.service-list {
|
||||
background: linear-gradient(145deg, #ffffff 0%, #f7f8ff 100%);
|
||||
border-radius: 24rpx;
|
||||
border: 1rpx solid #e5e6f0;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 16rpx 40rpx rgba(15, 35, 52, 0.04),
|
||||
0 0 0 1rpx rgba(255, 255, 255, 0.5) inset;
|
||||
}
|
||||
|
||||
.service-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
padding: 24rpx 28rpx;
|
||||
border-bottom: 1rpx solid #f2f3f5;
|
||||
}
|
||||
|
||||
.service-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.service-item:active {
|
||||
background: #f7f8fa;
|
||||
}
|
||||
|
||||
.svc-icon-wrap {
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
border-radius: 18rpx;
|
||||
background: linear-gradient(135deg, #e8f0fe, #d4e4fd);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.svc-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.svc-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.svc-name {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #1d2129;
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
|
||||
.svc-desc {
|
||||
display: block;
|
||||
font-size: 22rpx;
|
||||
color: #86909c;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.svc-arrow {
|
||||
font-size: 32rpx;
|
||||
color: #c9cdd4;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -329,120 +329,160 @@ onUnmounted(() => {
|
||||
<view class="page-root">
|
||||
<scroll-view scroll-y class="scrollarea">
|
||||
<view class="page">
|
||||
<view class="banner mine-banner">
|
||||
<view class="banner-text">
|
||||
<view class="banner-title">
|
||||
买车先查车况,更安心
|
||||
</view>
|
||||
<view class="banner-sub">
|
||||
减少隐蔽事故车、泡水车、调表车风险
|
||||
</view>
|
||||
</view>
|
||||
<view class="banner-illustration">
|
||||
<view class="car-illus" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="card mine-user">
|
||||
<view class="mine-user-main" @tap="handleUserTap">
|
||||
<view class="mine-avatar-placeholder" />
|
||||
<view class="mine-user-text">
|
||||
<view class="mine-user-name">
|
||||
{{ isLogin ? nickname : '您还没有登录,立即登录' }}
|
||||
</view>
|
||||
<view class="mine-user-desc">
|
||||
{{ isLogin ? userDesc : '登录后可同步历史报告与收藏' }}
|
||||
<!-- ═══ 区块1: 个人信息栏 ═══ -->
|
||||
<view class="profile-card">
|
||||
<view class="profile-bg" />
|
||||
<view class="profile-content" @tap="handleUserTap">
|
||||
<view class="profile-avatar">
|
||||
<view class="avatar-inner">
|
||||
<view class="avatar-icon i-carbon-user" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="profile-info">
|
||||
<text class="profile-name">{{ isLogin ? nickname : '点击登录' }}</text>
|
||||
<text class="profile-desc">{{ isLogin ? userDesc : '登录后可同步历史报告与收藏' }}</text>
|
||||
</view>
|
||||
<view class="profile-arrow">
|
||||
<view class="i-carbon-chevron-right" />
|
||||
</view>
|
||||
</view>
|
||||
<!-- 已登录未绑定手机 -->
|
||||
<view v-if="isLogin && !hasBoundMobile" class="profile-actions">
|
||||
<view class="action-btn" @tap.stop="openBindModal">
|
||||
<view class="action-icon i-carbon-phone" />
|
||||
<text class="action-text">绑定手机号</text>
|
||||
</view>
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<view v-if="isLogin && !hasBoundMobile" class="mine-user-extra">
|
||||
<text class="extra-link" @tap.stop="syncWxNickname">同步微信昵称</text>
|
||||
<text class="extra-dot">·</text>
|
||||
<text class="extra-hint">绑定手机后优先显示手机号</text>
|
||||
<view class="action-btn" @tap.stop="syncWxNickname">
|
||||
<view class="action-icon i-carbon-edit" />
|
||||
<text class="action-text">同步昵称</text>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<view
|
||||
v-if="isLogin && !hasBoundMobile"
|
||||
class="mine-bind-row"
|
||||
@tap.stop="openBindModal"
|
||||
>
|
||||
<text class="mine-bind-text">绑定手机号</text>
|
||||
<text class="mine-bind-arrow">›</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="card">
|
||||
<view class="grid-4">
|
||||
<view class="grid-item" @tap="goHistoryReport">
|
||||
<view class="icon-tool i-carbon-document" />
|
||||
<view class="grid-text">
|
||||
历史报告
|
||||
<!-- ═══ 区块2: 快捷功能(4宫格) ═══ -->
|
||||
<view class="section">
|
||||
<view class="section-title">快捷功能</view>
|
||||
<view class="quick-grid">
|
||||
<view class="quick-item" @tap="goHistoryReport">
|
||||
<view class="quick-icon-wrap" style="background: rgba(23,104,255,0.08)">
|
||||
<view class="quick-icon i-carbon-document" style="color: #1768ff" />
|
||||
</view>
|
||||
<text class="quick-name">历史报告</text>
|
||||
</view>
|
||||
<view class="grid-item" @tap="goFreeValuation">
|
||||
<view class="icon-tool i-carbon-chart-line" />
|
||||
<view class="grid-text">
|
||||
免费估值
|
||||
<view class="quick-item" @tap="goFreeValuation">
|
||||
<view class="quick-icon-wrap" style="background: rgba(250,140,22,0.08)">
|
||||
<view class="quick-icon i-carbon-chart-line" style="color: #fa8c16" />
|
||||
</view>
|
||||
<text class="quick-name">免费估值</text>
|
||||
</view>
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<button class="grid-item grid-item-btn" open-type="share" hover-class="grid-item-hover">
|
||||
<view class="icon-tool i-carbon-share" />
|
||||
<view class="grid-text">
|
||||
分享好友
|
||||
<button class="quick-item quick-item-btn" open-type="share" hover-class="quick-item-hover">
|
||||
<view class="quick-icon-wrap" style="background: rgba(19,194,94,0.08)">
|
||||
<view class="quick-icon i-carbon-share" style="color: #13c25e" />
|
||||
</view>
|
||||
<text class="quick-name">分享好友</text>
|
||||
</button>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-WEIXIN -->
|
||||
<view class="grid-item" @tap="goShareFallback">
|
||||
<view class="icon-tool i-carbon-share" />
|
||||
<view class="grid-text">
|
||||
分享好友
|
||||
<view class="quick-item" @tap="goShareFallback">
|
||||
<view class="quick-icon-wrap" style="background: rgba(19,194,94,0.08)">
|
||||
<view class="quick-icon i-carbon-share" style="color: #13c25e" />
|
||||
</view>
|
||||
<text class="quick-name">分享好友</text>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<view class="grid-item" @tap="openCoopModal">
|
||||
<view class="icon-tool i-carbon-enterprise" />
|
||||
<view class="grid-text">
|
||||
商务合作
|
||||
<view class="quick-item" @tap="openCoopModal">
|
||||
<view class="quick-icon-wrap" style="background: rgba(114,46,209,0.08)">
|
||||
<view class="quick-icon i-carbon-enterprise" style="color: #722ed1" />
|
||||
</view>
|
||||
<text class="quick-name">商务合作</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="card list-card">
|
||||
<view class="list-item" @tap="goLegalUserAgreement">
|
||||
<view class="list-icon i-carbon-document-blank" />
|
||||
<text class="list-text">用户协议</text>
|
||||
<!-- ═══ 区块3: 常用工具 ═══ -->
|
||||
<view class="section">
|
||||
<view class="section-title">常用工具</view>
|
||||
<view class="tool-list">
|
||||
<view class="tool-row" @tap="goOilPrice">
|
||||
<view class="tool-row-icon-wrap" style="background: rgba(23,104,255,0.08)">
|
||||
<view class="tool-row-icon i-carbon-gas-station" style="color: #1768ff" />
|
||||
</view>
|
||||
<view class="list-item" @tap="goLegalPrivacyPolicy">
|
||||
<view class="list-icon i-carbon-security" />
|
||||
<text class="list-text">隐私政策</text>
|
||||
<text class="tool-row-name">实时油价查询</text>
|
||||
<text class="tool-row-arrow">›</text>
|
||||
</view>
|
||||
<view class="tool-row" @tap="goIllegalCode">
|
||||
<view class="tool-row-icon-wrap" style="background: rgba(250,140,22,0.08)">
|
||||
<view class="tool-row-icon i-carbon-search" style="color: #fa8c16" />
|
||||
</view>
|
||||
<text class="tool-row-name">违章代码查询</text>
|
||||
<text class="tool-row-arrow">›</text>
|
||||
</view>
|
||||
<view class="list-item" @tap="goLegalAuthorization">
|
||||
<view class="list-icon i-carbon-certificate" />
|
||||
<text class="list-text">授权书</text>
|
||||
</view>
|
||||
<view class="list-item" @tap="goHelp">
|
||||
<view class="list-icon i-carbon-help" />
|
||||
<text class="list-text">帮助中心</text>
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
<button
|
||||
class="list-item list-item-contact no-border"
|
||||
open-type="contact"
|
||||
hover-class="list-item-contact-hover"
|
||||
>
|
||||
<view class="list-icon i-carbon-chat" />
|
||||
<view class="service-row">
|
||||
<text class="list-text">在线客服</text>
|
||||
<text class="service-time">人工客服 周一至周日 9:00-20:00</text>
|
||||
<!-- ═══ 区块4: 服务与支持 ═══ -->
|
||||
<view class="section">
|
||||
<view class="section-title">服务与支持</view>
|
||||
<view class="tool-list">
|
||||
<button class="tool-row tool-row-btn no-border" open-type="contact" hover-class="tool-row-hover">
|
||||
<view class="tool-row-icon-wrap" style="background: rgba(19,194,94,0.08)">
|
||||
<view class="tool-row-icon i-carbon-chat" style="color: #13c25e" />
|
||||
</view>
|
||||
<view class="tool-row-text">
|
||||
<text class="tool-row-name">在线客服</text>
|
||||
<text class="tool-row-sub">周一至周日 9:00-20:00</text>
|
||||
</view>
|
||||
</button>
|
||||
<view class="tool-row" @tap="goHelp">
|
||||
<view class="tool-row-icon-wrap" style="background: rgba(114,46,209,0.08)">
|
||||
<view class="tool-row-icon i-carbon-help" style="color: #722ed1" />
|
||||
</view>
|
||||
<text class="tool-row-name">帮助中心</text>
|
||||
<text class="tool-row-arrow">›</text>
|
||||
</view>
|
||||
<view class="tool-row" @tap="goAbout">
|
||||
<view class="tool-row-icon-wrap" style="background: rgba(78,89,105,0.08)">
|
||||
<view class="tool-row-icon i-carbon-information" style="color: #4e5969" />
|
||||
</view>
|
||||
<text class="tool-row-name">关于我们</text>
|
||||
<text class="tool-row-arrow">›</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- ═══ 区块5: 法律条款 ═══ -->
|
||||
<view class="section">
|
||||
<view class="section-title">法律条款</view>
|
||||
<view class="tool-list">
|
||||
<view class="tool-row" @tap="goLegalUserAgreement">
|
||||
<view class="tool-row-icon-wrap" style="background: rgba(78,89,105,0.06)">
|
||||
<view class="tool-row-icon i-carbon-document-blank" style="color: #86909c" />
|
||||
</view>
|
||||
<text class="tool-row-name">用户协议</text>
|
||||
<text class="tool-row-arrow">›</text>
|
||||
</view>
|
||||
<view class="tool-row" @tap="goLegalPrivacyPolicy">
|
||||
<view class="tool-row-icon-wrap" style="background: rgba(78,89,105,0.06)">
|
||||
<view class="tool-row-icon i-carbon-security" style="color: #86909c" />
|
||||
</view>
|
||||
<text class="tool-row-name">隐私政策</text>
|
||||
<text class="tool-row-arrow">›</text>
|
||||
</view>
|
||||
<view class="tool-row no-border" @tap="goLegalAuthorization">
|
||||
<view class="tool-row-icon-wrap" style="background: rgba(78,89,105,0.06)">
|
||||
<view class="tool-row-icon i-carbon-certificate" style="color: #86909c" />
|
||||
</view>
|
||||
<text class="tool-row-name">授权书</text>
|
||||
<text class="tool-row-arrow">›</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view style="height: 40rpx" />
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
@@ -531,7 +571,7 @@ onUnmounted(() => {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: linear-gradient(180deg, #f8faff 0%, #f3f5fb 100%);
|
||||
background: linear-gradient(180deg, #f0f5ff 0%, #f5f7fa 30%, #f3f5fb 100%);
|
||||
}
|
||||
|
||||
.scrollarea {
|
||||
@@ -541,143 +581,355 @@ onUnmounted(() => {
|
||||
}
|
||||
|
||||
.page {
|
||||
padding: 24rpx 24rpx 40rpx;
|
||||
padding: 0 24rpx 40rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.banner {
|
||||
display: flex;
|
||||
padding: 32rpx 28rpx;
|
||||
/* ═══ 区块1: 个人信息栏 ═══ */
|
||||
.profile-card {
|
||||
position: relative;
|
||||
border-radius: 0 0 32rpx 32rpx;
|
||||
overflow: hidden;
|
||||
margin-bottom: 24rpx;
|
||||
background: linear-gradient(135deg, #fff7f0 0%, #ffffff 100%);
|
||||
border-radius: 24rpx;
|
||||
box-shadow:
|
||||
0 18rpx 40rpx rgba(15, 35, 52, 0.05),
|
||||
0 0 0 1rpx rgba(226, 229, 239, 0.9);
|
||||
}
|
||||
|
||||
.banner-text {
|
||||
flex: 1;
|
||||
.profile-bg {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, #1768ff 0%, #4d94ff 60%, #7bb8ff 100%);
|
||||
}
|
||||
|
||||
.banner-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #1d2129;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.banner-sub {
|
||||
font-size: 24rpx;
|
||||
color: #4e5969;
|
||||
}
|
||||
|
||||
.banner-illustration {
|
||||
width: 180rpx;
|
||||
.profile-content {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 48rpx 32rpx 32rpx;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.car-illus {
|
||||
width: 160rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 16rpx;
|
||||
background: linear-gradient(145deg, #ffe8dc 0%, #ffc9a8 100%);
|
||||
opacity: 0.95;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: linear-gradient(145deg, #ffffff 0%, #f7f8ff 100%);
|
||||
border-radius: 24rpx;
|
||||
padding: 24rpx 24rpx 20rpx;
|
||||
margin-bottom: 24rpx;
|
||||
border: 1rpx solid #e5e6f0;
|
||||
box-shadow:
|
||||
0 16rpx 40rpx rgba(15, 35, 52, 0.04),
|
||||
0 0 0 1rpx rgba(255, 255, 255, 0.5) inset;
|
||||
}
|
||||
|
||||
.mine-user {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.mine-user-main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mine-avatar-placeholder {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #f2f3f5;
|
||||
margin-right: 20rpx;
|
||||
.profile-avatar {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.mine-user-text {
|
||||
.avatar-inner {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 3rpx solid rgba(255, 255, 255, 0.4);
|
||||
}
|
||||
|
||||
.avatar-icon {
|
||||
font-size: 44rpx;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.profile-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.mine-user-name {
|
||||
.profile-name {
|
||||
display: block;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
margin-bottom: 6rpx;
|
||||
}
|
||||
|
||||
.profile-desc {
|
||||
display: block;
|
||||
font-size: 22rpx;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
.profile-arrow {
|
||||
flex-shrink: 0;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.profile-actions {
|
||||
position: relative;
|
||||
display: flex;
|
||||
gap: 24rpx;
|
||||
padding: 0 32rpx 28rpx;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
padding: 10rpx 24rpx;
|
||||
border-radius: 24rpx;
|
||||
background: rgba(255, 255, 255, 0.18);
|
||||
}
|
||||
|
||||
.action-icon {
|
||||
font-size: 24rpx;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.action-text {
|
||||
font-size: 22rpx;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* ═══ 区块通用 ═══ */
|
||||
.section {
|
||||
background: #fff;
|
||||
border-radius: 24rpx;
|
||||
padding: 28rpx 24rpx 8rpx;
|
||||
margin-bottom: 24rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(15, 35, 52, 0.03);
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 26rpx;
|
||||
font-weight: 600;
|
||||
color: #1d2129;
|
||||
margin-bottom: 4rpx;
|
||||
margin-bottom: 20rpx;
|
||||
padding-left: 4rpx;
|
||||
}
|
||||
|
||||
.mine-user-desc {
|
||||
font-size: 22rpx;
|
||||
color: #86909c;
|
||||
}
|
||||
|
||||
.mine-user-extra {
|
||||
margin-top: 16rpx;
|
||||
padding-top: 16rpx;
|
||||
border-top: 1rpx solid #f0f0f0;
|
||||
font-size: 22rpx;
|
||||
color: #86909c;
|
||||
/* ═══ 区块2: 快捷功能(4宫格) ═══ */
|
||||
.quick-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.quick-item {
|
||||
width: 25%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 12rpx 0;
|
||||
}
|
||||
|
||||
.extra-link {
|
||||
color: #1768ff;
|
||||
.quick-item-btn {
|
||||
margin: 0;
|
||||
padding: 12rpx 0;
|
||||
border: none;
|
||||
background: transparent;
|
||||
line-height: normal;
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.extra-dot {
|
||||
margin: 0 8rpx;
|
||||
.quick-item-btn::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.quick-item-hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.quick-icon-wrap {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.quick-icon {
|
||||
font-size: 36rpx;
|
||||
}
|
||||
|
||||
.quick-name {
|
||||
font-size: 22rpx;
|
||||
color: #4e5969;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* ═══ 区块3/4/5: 列表行 ═══ */
|
||||
.tool-list {
|
||||
padding-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.tool-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx 4rpx;
|
||||
border-bottom: 1rpx solid #f5f5f5;
|
||||
}
|
||||
|
||||
.tool-row:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.tool-row:active {
|
||||
background: #fafbfc;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.tool-row-btn {
|
||||
margin: 0;
|
||||
padding: 20rpx 4rpx;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
background: transparent;
|
||||
text-align: left;
|
||||
line-height: inherit;
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
border-bottom: 1rpx solid #f5f5f5;
|
||||
}
|
||||
|
||||
.tool-row-btn::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tool-row-hover {
|
||||
background: rgba(23, 104, 255, 0.04);
|
||||
}
|
||||
|
||||
.tool-row-icon-wrap {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 16rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.tool-row-icon {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.tool-row-text {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.tool-row-name {
|
||||
flex: 1;
|
||||
font-size: 26rpx;
|
||||
color: #1d2129;
|
||||
}
|
||||
|
||||
.tool-row-sub {
|
||||
display: block;
|
||||
font-size: 20rpx;
|
||||
color: #ffb020;
|
||||
margin-top: 2rpx;
|
||||
}
|
||||
|
||||
.tool-row-arrow {
|
||||
font-size: 28rpx;
|
||||
color: #c9cdd4;
|
||||
flex-shrink: 0;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
.no-border {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
|
||||
/* ═══ 弹窗样式 ═══ */
|
||||
.coop-mask {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 1001;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 48rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.coop-dialog {
|
||||
width: 100%;
|
||||
max-width: 600rpx;
|
||||
background: #fff;
|
||||
border-radius: 24rpx;
|
||||
padding: 36rpx 32rpx 28rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.coop-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #1d2129;
|
||||
text-align: center;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.coop-hint {
|
||||
font-size: 24rpx;
|
||||
color: #86909c;
|
||||
text-align: center;
|
||||
margin-bottom: 28rpx;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.coop-qr {
|
||||
display: block;
|
||||
width: 360rpx;
|
||||
height: 360rpx;
|
||||
margin: 0 auto 28rpx;
|
||||
border-radius: 12rpx;
|
||||
background: #f7f8fa;
|
||||
}
|
||||
|
||||
.coop-qr-placeholder {
|
||||
width: 360rpx;
|
||||
height: 360rpx;
|
||||
margin: 0 auto 28rpx;
|
||||
border-radius: 12rpx;
|
||||
border: 2rpx dashed #dcdfe6;
|
||||
background: #fafbfc;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 24rpx;
|
||||
box-sizing: border-box;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.coop-qr-placeholder-text {
|
||||
font-size: 22rpx;
|
||||
color: #86909c;
|
||||
line-height: 1.6;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.coop-qr-placeholder-sub {
|
||||
font-size: 20rpx;
|
||||
color: #c9cdd4;
|
||||
}
|
||||
|
||||
.extra-hint {
|
||||
color: #86909c;
|
||||
}
|
||||
|
||||
.mine-bind-row {
|
||||
margin-top: 12rpx;
|
||||
padding: 16rpx 0 4rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.mine-bind-text {
|
||||
font-size: 26rpx;
|
||||
color: #1768ff;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.mine-bind-arrow {
|
||||
font-size: 36rpx;
|
||||
color: #1768ff;
|
||||
line-height: 1;
|
||||
.coop-close {
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
text-align: center;
|
||||
background: linear-gradient(90deg, #1768ff 0%, #4d94ff 100%);
|
||||
color: #fff;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
border-radius: 40rpx;
|
||||
}
|
||||
|
||||
/* ═══ 绑定手机弹窗 ═══ */
|
||||
.bind-mask {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
@@ -785,198 +1037,4 @@ onUnmounted(() => {
|
||||
color: #86909c;
|
||||
padding: 12rpx;
|
||||
}
|
||||
|
||||
.grid-4 {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.grid-item {
|
||||
width: 25%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-top: 8rpx;
|
||||
}
|
||||
|
||||
.grid-item-btn {
|
||||
margin: 0;
|
||||
padding: 8rpx 0 0;
|
||||
border: none;
|
||||
background: transparent;
|
||||
line-height: normal;
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.grid-item-btn::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.grid-item-hover {
|
||||
opacity: 0.88;
|
||||
}
|
||||
|
||||
.coop-mask {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 1001;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 48rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.coop-dialog {
|
||||
width: 100%;
|
||||
max-width: 600rpx;
|
||||
background: #fff;
|
||||
border-radius: 24rpx;
|
||||
padding: 36rpx 32rpx 28rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.coop-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #1d2129;
|
||||
text-align: center;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.coop-hint {
|
||||
font-size: 24rpx;
|
||||
color: #86909c;
|
||||
text-align: center;
|
||||
margin-bottom: 28rpx;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.coop-qr {
|
||||
display: block;
|
||||
width: 360rpx;
|
||||
height: 360rpx;
|
||||
margin: 0 auto 28rpx;
|
||||
border-radius: 12rpx;
|
||||
background: #f7f8fa;
|
||||
}
|
||||
|
||||
.coop-qr-placeholder {
|
||||
width: 360rpx;
|
||||
height: 360rpx;
|
||||
margin: 0 auto 28rpx;
|
||||
border-radius: 12rpx;
|
||||
border: 2rpx dashed #dcdfe6;
|
||||
background: #fafbfc;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 24rpx;
|
||||
box-sizing: border-box;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.coop-qr-placeholder-text {
|
||||
font-size: 22rpx;
|
||||
color: #86909c;
|
||||
line-height: 1.6;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.coop-qr-placeholder-sub {
|
||||
font-size: 20rpx;
|
||||
color: #c9cdd4;
|
||||
}
|
||||
|
||||
.coop-close {
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
text-align: center;
|
||||
background: linear-gradient(90deg, #1768ff 0%, #4d94ff 100%);
|
||||
color: #fff;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
border-radius: 40rpx;
|
||||
}
|
||||
|
||||
.icon-tool {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
margin-bottom: 8rpx;
|
||||
color: #1768ff;
|
||||
}
|
||||
|
||||
.grid-text {
|
||||
font-size: 24rpx;
|
||||
color: #4e5969;
|
||||
}
|
||||
|
||||
.list-card {
|
||||
padding: 0 24rpx;
|
||||
}
|
||||
|
||||
.list-item {
|
||||
height: 96rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.list-item-contact {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
background: transparent;
|
||||
text-align: left;
|
||||
line-height: inherit;
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.list-item-contact::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.list-item-contact-hover {
|
||||
background: rgba(23, 104, 255, 0.06);
|
||||
}
|
||||
|
||||
.list-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin-right: 20rpx;
|
||||
flex-shrink: 0;
|
||||
color: #1768ff;
|
||||
}
|
||||
|
||||
.no-border {
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
.list-text {
|
||||
font-size: 26rpx;
|
||||
color: #1d2129;
|
||||
}
|
||||
|
||||
.service-row {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.service-time {
|
||||
font-size: 22rpx;
|
||||
color: #ffb020;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { toolboxCategories, getCategoryAllTools } from '@/config/toolboxRegistry'
|
||||
import { toolboxCategories, toolboxItems, getCategoryAllTools } from '@/config/toolboxRegistry'
|
||||
|
||||
definePage({
|
||||
style: {
|
||||
@@ -15,11 +15,44 @@ definePage({
|
||||
const categoryKey = ref('')
|
||||
const category = ref<any>(null)
|
||||
const tools = ref<any[]>([])
|
||||
const isAllCategories = ref(false)
|
||||
|
||||
/** 当前选中的 tab 索引 */
|
||||
const activeTab = ref(0)
|
||||
|
||||
/** 搜索关键词 */
|
||||
const searchKeyword = ref('')
|
||||
|
||||
/** 当前选中分类的完整数据 */
|
||||
const activeCategory = computed(() => toolboxCategories[activeTab.value] || toolboxCategories[0])
|
||||
|
||||
/** 当前选中分类的全部工具 */
|
||||
const activeTools = computed(() => getCategoryAllTools(activeCategory.value.key))
|
||||
|
||||
/** 是否正在搜索(有关键词) */
|
||||
const isSearching = computed(() => searchKeyword.value.trim().length > 0)
|
||||
|
||||
/** 搜索结果:从所有工具中匹配名称 / 描述 / key */
|
||||
const searchResults = computed(() => {
|
||||
const kw = searchKeyword.value.trim().toLowerCase()
|
||||
if (!kw) return []
|
||||
return toolboxItems.filter(item =>
|
||||
item.name.toLowerCase().includes(kw)
|
||||
|| item.desc.toLowerCase().includes(kw)
|
||||
|| item.key.toLowerCase().includes(kw),
|
||||
)
|
||||
})
|
||||
|
||||
onLoad((query) => {
|
||||
const key = (query?.category as string) || ''
|
||||
categoryKey.value = key
|
||||
|
||||
if (key === 'all') {
|
||||
isAllCategories.value = true
|
||||
uni.setNavigationBarTitle({ title: '全部分类' })
|
||||
return
|
||||
}
|
||||
|
||||
const cat = toolboxCategories.find(c => c.key === key)
|
||||
if (cat) {
|
||||
category.value = cat
|
||||
@@ -28,6 +61,15 @@ onLoad((query) => {
|
||||
}
|
||||
})
|
||||
|
||||
function switchTab(idx: number) {
|
||||
activeTab.value = idx
|
||||
searchKeyword.value = ''
|
||||
}
|
||||
|
||||
function clearSearch() {
|
||||
searchKeyword.value = ''
|
||||
}
|
||||
|
||||
function goTool(key: string) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/toolbox/query?key=${encodeURIComponent(key)}`,
|
||||
@@ -37,9 +79,109 @@ function goTool(key: string) {
|
||||
|
||||
<template>
|
||||
<view class="page-root">
|
||||
<!-- 全部分类视图 -->
|
||||
<template v-if="isAllCategories">
|
||||
<!-- 搜索栏 -->
|
||||
<view class="search-bar">
|
||||
<view class="search-input-wrap">
|
||||
<view class="search-icon i-carbon-search" />
|
||||
<input
|
||||
class="search-input"
|
||||
type="text"
|
||||
placeholder="搜索工具名称"
|
||||
placeholder-class="search-placeholder"
|
||||
:value="searchKeyword"
|
||||
confirm-type="search"
|
||||
@input="searchKeyword = $event.detail.value"
|
||||
/>
|
||||
<view v-if="isSearching" class="search-clear i-carbon-close-filled" @tap="clearSearch" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Tab 栏(搜索时隐藏) -->
|
||||
<view v-show="!isSearching" class="tab-bar-wrap">
|
||||
<scroll-view scroll-x class="tab-scroll" :scroll-into-view="'tab-' + activeTab" :scroll-with-animation="true">
|
||||
<view class="tab-bar">
|
||||
<view
|
||||
v-for="(cat, idx) in toolboxCategories"
|
||||
:id="'tab-' + idx"
|
||||
:key="cat.key"
|
||||
class="tab-item"
|
||||
:class="{ 'tab-item--active': activeTab === idx }"
|
||||
@tap="switchTab(idx)"
|
||||
>
|
||||
<text class="tab-text" :class="{ 'tab-text--active': activeTab === idx }">{{ cat.name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="tab-indicator-track">
|
||||
<view
|
||||
class="tab-indicator"
|
||||
:style="{ width: `${100 / toolboxCategories.length}%`, transform: `translateX(${activeTab * 100}%)` }"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 搜索结果 / 工具网格 -->
|
||||
<scroll-view scroll-y class="tool-scrollarea">
|
||||
<view class="tool-grid-page">
|
||||
<!-- 搜索结果视图 -->
|
||||
<template v-if="isSearching">
|
||||
<view v-if="searchResults.length === 0" class="search-empty">
|
||||
<view class="search-empty-icon i-carbon-search" />
|
||||
<text class="search-empty-text">未找到相关工具</text>
|
||||
</view>
|
||||
<template v-else>
|
||||
<view class="grid-header">
|
||||
<text class="grid-header-name">搜索结果</text>
|
||||
<text class="grid-header-count">共 {{ searchResults.length }} 个</text>
|
||||
</view>
|
||||
<view class="tool-grid">
|
||||
<view
|
||||
v-for="item in searchResults"
|
||||
:key="item.key"
|
||||
class="tool-cell"
|
||||
@tap="goTool(item.key)"
|
||||
>
|
||||
<view class="tool-cell-icon-wrap" style="background: #eef4ff">
|
||||
<view :class="['tool-cell-icon', item.icon]" style="color: #1768ff" />
|
||||
</view>
|
||||
<text class="tool-cell-name">{{ item.name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<!-- 正常 Tab 工具网格 -->
|
||||
<template v-else>
|
||||
<view class="grid-header">
|
||||
<view class="grid-header-dot" :style="{ background: activeCategory.color }" />
|
||||
<text class="grid-header-name">{{ activeCategory.name }}</text>
|
||||
<text class="grid-header-count">共 {{ activeTools.length }} 个</text>
|
||||
</view>
|
||||
<view class="tool-grid">
|
||||
<view
|
||||
v-for="item in activeTools"
|
||||
:key="item.key"
|
||||
class="tool-cell"
|
||||
@tap="goTool(item.key)"
|
||||
>
|
||||
<view class="tool-cell-icon-wrap" :style="{ background: `${activeCategory.color}12` }">
|
||||
<view :class="['tool-cell-icon', item.icon]" :style="{ color: activeCategory.color }" />
|
||||
</view>
|
||||
<text class="tool-cell-name">{{ item.name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</template>
|
||||
|
||||
<!-- 单分类视图 -->
|
||||
<template v-else-if="category">
|
||||
<scroll-view scroll-y class="scrollarea">
|
||||
<view class="page">
|
||||
<view v-if="category" class="cat-header">
|
||||
<view class="cat-header">
|
||||
<view class="cat-icon-large" :style="{ background: `${category.color}15` }">
|
||||
<view :class="['icon', category.icon]" :style="{ color: category.color }" />
|
||||
</view>
|
||||
@@ -63,11 +205,11 @@ function goTool(key: string) {
|
||||
<text class="item-name">{{ item.name }}</text>
|
||||
<text class="item-desc">{{ item.desc }}</text>
|
||||
</view>
|
||||
<!-- <text class="item-arrow"></text> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -79,6 +221,204 @@ function goTool(key: string) {
|
||||
background: linear-gradient(180deg, #f8faff 0%, #f3f5fb 100%);
|
||||
}
|
||||
|
||||
/* ============ 搜索栏 ============ */
|
||||
.search-bar {
|
||||
padding: 16rpx 24rpx 12rpx;
|
||||
background: #fff;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.search-input-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 72rpx;
|
||||
background: #f5f6fa;
|
||||
border-radius: 36rpx;
|
||||
padding: 0 24rpx;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
font-size: 30rpx;
|
||||
color: #c0c4cc;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
flex: 1;
|
||||
font-size: 26rpx;
|
||||
color: #1d2129;
|
||||
height: 72rpx;
|
||||
line-height: 72rpx;
|
||||
}
|
||||
|
||||
.search-placeholder {
|
||||
color: #c0c4cc;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.search-clear {
|
||||
font-size: 30rpx;
|
||||
color: #c0c4cc;
|
||||
flex-shrink: 0;
|
||||
padding: 8rpx;
|
||||
}
|
||||
|
||||
.search-empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 120rpx 0 80rpx;
|
||||
}
|
||||
|
||||
.search-empty-icon {
|
||||
font-size: 80rpx;
|
||||
color: #dcdfe6;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.search-empty-text {
|
||||
font-size: 26rpx;
|
||||
color: #86909c;
|
||||
}
|
||||
|
||||
/* ============ Tab 栏 ============ */
|
||||
.tab-bar-wrap {
|
||||
background: #fff;
|
||||
flex-shrink: 0;
|
||||
border-bottom: 1rpx solid #f0f1f5;
|
||||
}
|
||||
|
||||
.tab-scroll {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tab-bar {
|
||||
display: flex;
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 8rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab-text {
|
||||
font-size: 28rpx;
|
||||
color: #86909c;
|
||||
transition: color 0.25s, font-weight 0.25s;
|
||||
}
|
||||
|
||||
.tab-text--active {
|
||||
color: #1d2129;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 下划线指示器 */
|
||||
.tab-indicator-track {
|
||||
height: 6rpx;
|
||||
position: relative;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.tab-indicator {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 6rpx;
|
||||
border-radius: 3rpx;
|
||||
background: #1768ff;
|
||||
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
/* ============ 工具网格区域 ============ */
|
||||
.tool-scrollarea {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.tool-grid-page {
|
||||
padding: 24rpx 24rpx 40rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.grid-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
margin-bottom: 24rpx;
|
||||
padding: 0 4rpx;
|
||||
}
|
||||
|
||||
.grid-header-dot {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.grid-header-name {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #1d2129;
|
||||
}
|
||||
|
||||
.grid-header-count {
|
||||
font-size: 22rpx;
|
||||
color: #86909c;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
/* 4列网格 */
|
||||
.tool-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.tool-cell {
|
||||
width: 25%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20rpx 4rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tool-cell:active {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.tool-cell-icon-wrap {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.tool-cell-icon {
|
||||
font-size: 38rpx;
|
||||
}
|
||||
|
||||
.tool-cell-name {
|
||||
font-size: 22rpx;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
line-height: 1.3;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* ============ 单分类详情 ============ */
|
||||
.scrollarea {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
@@ -99,8 +439,7 @@ function goTool(key: string) {
|
||||
border-radius: 24rpx;
|
||||
border: 1rpx solid #e5e6f0;
|
||||
margin-bottom: 24rpx;
|
||||
box-shadow:
|
||||
0 16rpx 40rpx rgba(15, 35, 52, 0.04),
|
||||
box-shadow: 0 16rpx 40rpx rgba(15, 35, 52, 0.04),
|
||||
0 0 0 1rpx rgba(255, 255, 255, 0.5) inset;
|
||||
}
|
||||
|
||||
@@ -140,8 +479,7 @@ function goTool(key: string) {
|
||||
border-radius: 24rpx;
|
||||
border: 1rpx solid #e5e6f0;
|
||||
overflow: hidden;
|
||||
box-shadow:
|
||||
0 16rpx 40rpx rgba(15, 35, 52, 0.04),
|
||||
box-shadow: 0 16rpx 40rpx rgba(15, 35, 52, 0.04),
|
||||
0 0 0 1rpx rgba(255, 255, 255, 0.5) inset;
|
||||
}
|
||||
|
||||
@@ -196,10 +534,4 @@ function goTool(key: string) {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.item-arrow {
|
||||
font-size: 24rpx;
|
||||
color: #c9cdd4;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,69 +1,186 @@
|
||||
<script setup lang="ts">
|
||||
import { toolboxCategories, getCategoryHotTools } from '@/config/toolboxRegistry'
|
||||
import { ref, computed } from 'vue'
|
||||
import { toolboxCategories, getCategoryAllTools } from '@/config/toolboxRegistry'
|
||||
import { getInquireCategoryConfig, getInquiryItemIconUrl } from '@/config/inquireCategories'
|
||||
|
||||
definePage({
|
||||
style: {
|
||||
navigationBarTitleText: '实用工具',
|
||||
navigationBarTitleText: '工具分类',
|
||||
navigationStyle: 'default',
|
||||
navigationBarBackgroundColor: '#ffffff',
|
||||
navigationBarTextStyle: 'black',
|
||||
},
|
||||
})
|
||||
|
||||
function goTool(key: string) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/toolbox/query?key=${encodeURIComponent(key)}`,
|
||||
})
|
||||
const vehicleItems = computed(() => getInquireCategoryConfig('vehicle')?.items ?? [])
|
||||
|
||||
/** 左侧分类列表:热门推荐 + 车辆查询 + 所有工具分类 */
|
||||
const sidebarItems = computed(() => [
|
||||
{ key: 'hot', name: '热门推荐', icon: '', color: '#ff6b6b' },
|
||||
{ key: 'vehicle', name: '车辆查询', icon: 'i-carbon-car', color: '#1768ff' },
|
||||
...toolboxCategories.map(cat => ({
|
||||
key: cat.key,
|
||||
name: cat.name,
|
||||
icon: cat.icon,
|
||||
color: cat.color,
|
||||
})),
|
||||
])
|
||||
|
||||
const activeKey = ref('hot')
|
||||
|
||||
/** 当前选中分类的数据(仅工具分类有) */
|
||||
const activeCategory = computed(() => {
|
||||
if (activeKey.value === 'hot' || activeKey.value === 'vehicle') return null
|
||||
return toolboxCategories.find(c => c.key === activeKey.value) || null
|
||||
})
|
||||
|
||||
/** 当前分类的工具列表 */
|
||||
const activeTools = computed(() => {
|
||||
if (activeKey.value === 'hot' || activeKey.value === 'vehicle') return []
|
||||
return getCategoryAllTools(activeKey.value)
|
||||
})
|
||||
|
||||
/** 热门推荐的分类卡片:车辆查询 + 所有工具分类 */
|
||||
const hotCategoryCards = computed(() => [
|
||||
{ key: 'vehicle', name: '车辆查询', icon: 'i-carbon-car', color: '#1768ff', count: vehicleItems.value.length, previews: [] },
|
||||
...toolboxCategories.map(cat => ({
|
||||
key: cat.key,
|
||||
name: cat.name,
|
||||
icon: cat.icon,
|
||||
color: cat.color,
|
||||
count: getCategoryAllTools(cat.key).length,
|
||||
previews: getCategoryAllTools(cat.key).slice(0, 4),
|
||||
})),
|
||||
])
|
||||
|
||||
function switchCategory(key: string) {
|
||||
activeKey.value = key
|
||||
}
|
||||
|
||||
function goCategory(categoryKey: string) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/toolbox/category?category=${encodeURIComponent(categoryKey)}`,
|
||||
})
|
||||
function goTool(key: string) {
|
||||
uni.navigateTo({ url: `/pages/toolbox/query?key=${encodeURIComponent(key)}` })
|
||||
}
|
||||
|
||||
function goInquireFeature(feature: string) {
|
||||
uni.navigateTo({ url: `/pages/inquire/index?feature=${encodeURIComponent(feature)}` })
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="page-root">
|
||||
<scroll-view scroll-y class="scrollarea">
|
||||
<view class="page">
|
||||
<view class="layout">
|
||||
<!-- 左侧分类导航 -->
|
||||
<scroll-view scroll-y class="sidebar">
|
||||
<view
|
||||
v-for="cat in toolboxCategories"
|
||||
:key="cat.key"
|
||||
class="card"
|
||||
v-for="item in sidebarItems"
|
||||
:key="item.key"
|
||||
class="sidebar-item"
|
||||
:class="{ 'sidebar-item--active': activeKey === item.key }"
|
||||
@tap="switchCategory(item.key)"
|
||||
>
|
||||
<!-- 分类标题 -->
|
||||
<view class="card-header" @tap="goCategory(cat.key)">
|
||||
<view class="card-header-left">
|
||||
<view class="cat-icon-wrap" :style="{ background: `${cat.color}15` }">
|
||||
<view :class="['cat-icon', cat.icon]" :style="{ color: cat.color }" />
|
||||
</view>
|
||||
<text class="card-title">{{ cat.name }}</text>
|
||||
</view>
|
||||
<view class="card-more">
|
||||
<text class="more-text">查看更多</text>
|
||||
<!-- <text class="more-arrow">></text> -->
|
||||
</view>
|
||||
<view v-if="activeKey === item.key" class="sidebar-indicator" />
|
||||
<text class="sidebar-text" :class="{ 'sidebar-text--active': activeKey === item.key }">{{ item.name }}</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 热门工具网格 -->
|
||||
<!-- 右侧内容区 -->
|
||||
<scroll-view scroll-y class="content" :scroll-top="0">
|
||||
<!-- 热门推荐:分类卡片网格 -->
|
||||
<template v-if="activeKey === 'hot'">
|
||||
<view class="content-header">
|
||||
<view class="content-icon-wrap" style="background: rgba(255,107,107,0.1)">
|
||||
<view class="content-icon i-carbon-grid" style="color: #ff6b6b" />
|
||||
</view>
|
||||
<view class="content-info">
|
||||
<text class="content-title">热门推荐</text>
|
||||
<text class="content-count">全部分类入口</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="cat-grid">
|
||||
<view
|
||||
v-for="card in hotCategoryCards"
|
||||
:key="card.key"
|
||||
class="cat-card"
|
||||
@tap="switchCategory(card.key)"
|
||||
>
|
||||
<!-- 车辆查询用单图标 -->
|
||||
<view v-if="card.key === 'vehicle'" class="cat-card-single-icon" :style="{ background: `${card.color}12` }">
|
||||
<view :class="card.icon" :style="{ color: card.color, fontSize: '28rpx' }" />
|
||||
</view>
|
||||
<!-- 工具分类用四宫格 -->
|
||||
<view v-else class="cat-card-grid-icon" :style="{ background: `${card.color}10` }">
|
||||
<view
|
||||
v-for="(preview, pIdx) in card.previews"
|
||||
:key="preview.key"
|
||||
class="mini-icon-cell"
|
||||
>
|
||||
<view :class="[preview.icon, 'mini-icon']" :style="{ color: card.color }" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="cat-card-text">
|
||||
<text class="cat-card-name">{{ card.name }}</text>
|
||||
<text class="cat-card-count">{{ card.count }}个</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 车辆查询 -->
|
||||
<template v-else-if="activeKey === 'vehicle'">
|
||||
<view class="content-header">
|
||||
<view class="content-icon-wrap" style="background: rgba(23,104,255,0.1)">
|
||||
<view class="content-icon i-carbon-car" style="color: #1768ff" />
|
||||
</view>
|
||||
<view class="content-info">
|
||||
<text class="content-title">车辆查询服务</text>
|
||||
<text class="content-count">{{ vehicleItems.length }} 项专业车况核验</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="tool-grid">
|
||||
<view
|
||||
v-for="item in getCategoryHotTools(cat.key)"
|
||||
:key="item.key"
|
||||
v-for="item in vehicleItems"
|
||||
:key="item.feature"
|
||||
class="tool-cell"
|
||||
@tap="goTool(item.key)"
|
||||
@tap="goInquireFeature(item.feature)"
|
||||
>
|
||||
<view class="tool-icon-wrap" :style="{ background: `${cat.color}12` }">
|
||||
<view :class="['tool-icon', item.icon]" :style="{ color: cat.color }" />
|
||||
<view class="tool-icon-wrap" style="background: rgba(23,104,255,0.08)">
|
||||
<image class="tool-icon-img" :src="getInquiryItemIconUrl(item)" mode="aspectFit" />
|
||||
</view>
|
||||
<text class="tool-name">{{ item.name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 工具分类 -->
|
||||
<template v-else-if="activeCategory">
|
||||
<view class="content-header">
|
||||
<view class="content-icon-wrap" :style="{ background: `${activeCategory.color}15` }">
|
||||
<view :class="['content-icon', activeCategory.icon]" :style="{ color: activeCategory.color }" />
|
||||
</view>
|
||||
<view class="content-info">
|
||||
<text class="content-title">{{ activeCategory.name }}</text>
|
||||
<text class="content-count">{{ activeTools.length }} 个工具</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="tool-grid">
|
||||
<view
|
||||
v-for="item in activeTools"
|
||||
:key="item.key"
|
||||
class="tool-cell"
|
||||
@tap="goTool(item.key)"
|
||||
>
|
||||
<view class="tool-icon-wrap" :style="{ background: `${activeCategory.color}12` }">
|
||||
<view :class="['tool-icon-grid', item.icon]" :style="{ color: activeCategory.color }" />
|
||||
</view>
|
||||
<text class="tool-name">{{ item.name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<view style="height: 32rpx" />
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@@ -71,101 +188,201 @@ function goCategory(categoryKey: string) {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: linear-gradient(180deg, #f8faff 0%, #f3f5fb 100%);
|
||||
background: #f5f6fa;
|
||||
}
|
||||
|
||||
.scrollarea {
|
||||
/* ============ 双栏布局 ============ */
|
||||
.layout {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.page {
|
||||
padding: 24rpx 24rpx 40rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: linear-gradient(145deg, #ffffff 0%, #f7f8ff 100%);
|
||||
border-radius: 24rpx;
|
||||
padding: 24rpx 24rpx 20rpx;
|
||||
margin-bottom: 24rpx;
|
||||
border: 1rpx solid #e5e6f0;
|
||||
box-shadow:
|
||||
0 16rpx 40rpx rgba(15, 35, 52, 0.04),
|
||||
0 0 0 1rpx rgba(255, 255, 255, 0.5) inset;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.card-header-left {
|
||||
/* 左侧分类导航 */
|
||||
.sidebar {
|
||||
width: 180rpx;
|
||||
height: 100%;
|
||||
background: #f0f1f5;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sidebar-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 104rpx;
|
||||
padding: 0 8rpx;
|
||||
}
|
||||
|
||||
.sidebar-item:active {
|
||||
background: #e8e9ed;
|
||||
}
|
||||
|
||||
.sidebar-item--active {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.sidebar-indicator {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 8rpx;
|
||||
height: 40rpx;
|
||||
border-radius: 0 4rpx 4rpx 0;
|
||||
background: #1768ff;
|
||||
}
|
||||
|
||||
.sidebar-text {
|
||||
font-size: 24rpx;
|
||||
color: #86909c;
|
||||
text-align: center;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.sidebar-text--active {
|
||||
color: #1d2129;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 右侧内容区 */
|
||||
.content {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.content-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
padding: 28rpx 28rpx 16rpx;
|
||||
}
|
||||
|
||||
.cat-icon-wrap {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
.content-icon-wrap {
|
||||
width: 52rpx;
|
||||
height: 52rpx;
|
||||
border-radius: 14rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.content-icon {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.content-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.content-title {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #1d2129;
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
|
||||
.content-count {
|
||||
display: block;
|
||||
font-size: 20rpx;
|
||||
color: #86909c;
|
||||
}
|
||||
|
||||
/* ============ 热门推荐:分类卡片网格 ============ */
|
||||
.cat-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 14rpx;
|
||||
padding: 8rpx 20rpx;
|
||||
}
|
||||
|
||||
.cat-card {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 14rpx;
|
||||
padding: 20rpx 16rpx;
|
||||
border-radius: 16rpx;
|
||||
background: #f7f8fa;
|
||||
}
|
||||
|
||||
.cat-card:active {
|
||||
background: #eef1f5;
|
||||
}
|
||||
|
||||
/* 车辆查询单图标 */
|
||||
.cat-card-single-icon {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
border-radius: 12rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 四宫格图标 */
|
||||
.cat-card-grid-icon {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
border-radius: 12rpx;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
overflow: hidden;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.mini-icon-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.cat-icon {
|
||||
font-size: 32rpx;
|
||||
.mini-icon {
|
||||
font-size: 16rpx;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
color: #1d2129;
|
||||
.cat-card-text {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.card-more {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4rpx;
|
||||
padding: 8rpx 16rpx;
|
||||
border-radius: 20rpx;
|
||||
background: #f2f3f5;
|
||||
}
|
||||
|
||||
.more-text {
|
||||
.cat-card-name {
|
||||
display: block;
|
||||
font-size: 22rpx;
|
||||
font-weight: 500;
|
||||
color: #1d2129;
|
||||
margin-bottom: 2rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.cat-card-count {
|
||||
display: block;
|
||||
font-size: 18rpx;
|
||||
color: #86909c;
|
||||
}
|
||||
|
||||
.more-arrow {
|
||||
font-size: 22rpx;
|
||||
color: #c9cdd4;
|
||||
}
|
||||
|
||||
.card-more:active {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* ============ 工具网格 ============ */
|
||||
.tool-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: 0 -6rpx;
|
||||
padding: 0 16rpx;
|
||||
}
|
||||
|
||||
.tool-cell {
|
||||
width: 33.333%;
|
||||
padding: 6rpx;
|
||||
box-sizing: border-box;
|
||||
width: 25%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-top: 12rpx;
|
||||
padding-bottom: 12rpx;
|
||||
padding: 16rpx 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tool-cell:active {
|
||||
@@ -173,27 +390,33 @@ function goCategory(categoryKey: string) {
|
||||
}
|
||||
|
||||
.tool-icon-wrap {
|
||||
width: 76rpx;
|
||||
height: 76rpx;
|
||||
border-radius: 20rpx;
|
||||
width: 68rpx;
|
||||
height: 68rpx;
|
||||
border-radius: 18rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 10rpx;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.tool-icon {
|
||||
font-size: 36rpx;
|
||||
.tool-icon-grid {
|
||||
font-size: 34rpx;
|
||||
}
|
||||
|
||||
.tool-icon-img {
|
||||
width: 38rpx;
|
||||
height: 38rpx;
|
||||
}
|
||||
|
||||
.tool-name {
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: #1d2129;
|
||||
font-size: 20rpx;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
line-height: 1.3;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
padding: 0 4rpx;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -253,6 +253,14 @@ async function handleQuery() {
|
||||
if (toolKey.value === 'idiom-quiz' || toolKey.value === 'poem-fill') {
|
||||
prepareGameOptions()
|
||||
}
|
||||
// 百科题库:准备选项
|
||||
if (toolKey.value === 'baiketiku') {
|
||||
prepareBaiKeOptions()
|
||||
}
|
||||
// 垃圾分类问答:准备选项
|
||||
if (toolKey.value === 'anslajifenlei') {
|
||||
prepareGarbageOptions()
|
||||
}
|
||||
// 成语接龙:记录系统返回的成语
|
||||
if (toolKey.value === 'chengyujielong') {
|
||||
if (result.value?.word) {
|
||||
@@ -354,6 +362,59 @@ const prepareGameOptions = () => {
|
||||
answered.value = false
|
||||
}
|
||||
|
||||
// 百科题库:准备选项(A/B/C/D 四个选项,标记正确答案)
|
||||
const prepareBaiKeOptions = () => {
|
||||
if (!result.value)
|
||||
return
|
||||
|
||||
// answer 可能是选项字母标识(如 "A"),也可能是选项文本内容
|
||||
const correctAnswer = String(result.value.answer || '').trim()
|
||||
const optionKeys = ['answerA', 'answerB', 'answerC', 'answerD'] as const
|
||||
const optionLabels = ['A', 'B', 'C', 'D'] as const
|
||||
const options = optionKeys
|
||||
.map((key, i) => {
|
||||
const val = String(result.value[key] || '').trim()
|
||||
if (!val) return null
|
||||
// answer 可能是字母标识 "A"/"B"/...,也可能是选项文本本身
|
||||
const isCorrect = correctAnswer === optionLabels[i] || correctAnswer === val
|
||||
return { label: `${optionLabels[i]}. ${val}`, value: val, isCorrect }
|
||||
})
|
||||
.filter(Boolean) as Array<{ label: string; value: string; isCorrect: boolean }>
|
||||
|
||||
gameOptions.value = options
|
||||
selectedOption.value = null
|
||||
answered.value = false
|
||||
}
|
||||
|
||||
// 垃圾分类问答:准备选项(四个分类,标记正确答案)
|
||||
const prepareGarbageOptions = () => {
|
||||
if (!result.value)
|
||||
return
|
||||
|
||||
const correctType = result.value.type
|
||||
const typeNames: Record<number, string> = {
|
||||
0: '可回收物',
|
||||
1: '有害垃圾',
|
||||
2: '厨余垃圾',
|
||||
3: '其他垃圾',
|
||||
}
|
||||
const options = Object.entries(typeNames).map(([typeKey, typeName]) => ({
|
||||
label: typeName,
|
||||
value: typeName,
|
||||
isCorrect: Number(typeKey) === Number(correctType),
|
||||
}))
|
||||
|
||||
// 打乱顺序
|
||||
for (let i = options.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1))
|
||||
;[options[i], options[j]] = [options[j], options[i]]
|
||||
}
|
||||
|
||||
gameOptions.value = options
|
||||
selectedOption.value = null
|
||||
answered.value = false
|
||||
}
|
||||
|
||||
// 点击选项
|
||||
function handleOptionClick(option: { label: string; value: string; isCorrect: boolean }) {
|
||||
if (answered.value)
|
||||
@@ -538,11 +599,15 @@ function handleRestart() {
|
||||
|
||||
<!-- 题目 -->
|
||||
<view class="game-question">
|
||||
<text class="game-question-text">{{ result.question }}</text>
|
||||
<text v-if="toolKey === 'anslajifenlei'" class="game-question-text game-question-garbage">
|
||||
<text class="garbage-name">{{ result.name }}</text>
|
||||
<text class="garbage-prompt">属于什么垃圾?</text>
|
||||
</text>
|
||||
<text v-else class="game-question-text">{{ result.title || result.question }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 选项按钮 -->
|
||||
<view class="game-options">
|
||||
<view class="game-options" :class="{ 'game-options-col': toolKey === 'anslajifenlei' }">
|
||||
<view
|
||||
v-for="(option, index) in gameOptions"
|
||||
:key="index"
|
||||
@@ -551,6 +616,10 @@ function handleRestart() {
|
||||
'game-option-selected': selectedOption === option.value,
|
||||
'game-option-correct': answered && option.isCorrect,
|
||||
'game-option-wrong': answered && selectedOption === option.value && !option.isCorrect,
|
||||
'game-option-recyclable': toolKey === 'anslajifenlei' && option.value === '可回收物',
|
||||
'game-option-hazardous': toolKey === 'anslajifenlei' && option.value === '有害垃圾',
|
||||
'game-option-kitchen': toolKey === 'anslajifenlei' && option.value === '厨余垃圾',
|
||||
'game-option-other': toolKey === 'anslajifenlei' && option.value === '其他垃圾',
|
||||
}"
|
||||
@tap="handleOptionClick(option)"
|
||||
>
|
||||
@@ -610,6 +679,30 @@ function handleRestart() {
|
||||
<text class="game-explan-value">{{ result.note }}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 百科题库:显示正确答案和解析 -->
|
||||
<template v-else-if="toolKey === 'baiketiku'">
|
||||
<view class="game-answer">
|
||||
<text class="game-answer-label">正确答案:</text>
|
||||
<text class="game-answer-value">{{ result.answer }}</text>
|
||||
</view>
|
||||
<view v-if="result.analytic" class="game-explan">
|
||||
<text class="game-explan-label">解析:</text>
|
||||
<text class="game-explan-value">{{ result.analytic }}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 垃圾分类问答:显示正确分类 -->
|
||||
<template v-else-if="toolKey === 'anslajifenlei'">
|
||||
<view class="game-answer">
|
||||
<text class="game-answer-label">正确分类:</text>
|
||||
<text class="game-answer-value garbage-answer-type">{{ result.type_name }}</text>
|
||||
</view>
|
||||
<view v-if="result.explain" class="game-explan">
|
||||
<text class="game-explan-label">说明:</text>
|
||||
<text class="game-explan-value">{{ result.explain }}</text>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -1473,4 +1566,50 @@ function handleRestart() {
|
||||
.chain-empty-text {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
/* 垃圾分类游戏样式 */
|
||||
.game-question-garbage {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16rpx;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.garbage-name {
|
||||
font-size: 56rpx;
|
||||
font-weight: 700;
|
||||
color: #1d2129;
|
||||
}
|
||||
|
||||
.garbage-prompt {
|
||||
font-size: 30rpx;
|
||||
color: #86909c;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.garbage-answer-type {
|
||||
color: #00b42a;
|
||||
}
|
||||
|
||||
/* 垃圾分类选项布局 - 单列 */
|
||||
.game-options-col {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
/* 垃圾分类四个类别的默认色 */
|
||||
.game-option-recyclable {
|
||||
border-left: 6rpx solid #1768ff;
|
||||
}
|
||||
|
||||
.game-option-hazardous {
|
||||
border-left: 6rpx solid #f53f3f;
|
||||
}
|
||||
|
||||
.game-option-kitchen {
|
||||
border-left: 6rpx solid #00b42a;
|
||||
}
|
||||
|
||||
.game-option-other {
|
||||
border-left: 6rpx solid #86909c;
|
||||
}
|
||||
</style>
|
||||
|
||||
BIN
src/static/tabbar/toolbox-active.png
Normal file
BIN
src/static/tabbar/toolbox-active.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 468 B |
BIN
src/static/tabbar/toolbox.png
Normal file
BIN
src/static/tabbar/toolbox.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 464 B |
3
uni-pages.d.ts
vendored
3
uni-pages.d.ts
vendored
@@ -10,6 +10,7 @@ type _LocationUrl =
|
||||
"/pages/report" |
|
||||
"/pages/inquire/example" |
|
||||
"/pages/inquire/index" |
|
||||
"/pages/inquire/list" |
|
||||
"/pages/legal/authorization" |
|
||||
"/pages/legal/privacy-policy" |
|
||||
"/pages/legal/user-agreement" |
|
||||
@@ -24,7 +25,7 @@ interface NavigateToOptions {
|
||||
interface RedirectToOptions extends NavigateToOptions {}
|
||||
|
||||
interface SwitchTabOptions {
|
||||
url: "/pages/index" | "/pages/report" | "/pages/mine"
|
||||
url: "/pages/index" | "/pages/toolbox/index" | "/pages/mine"
|
||||
}
|
||||
|
||||
type ReLaunchOptions = NavigateToOptions | SwitchTabOptions;
|
||||
|
||||
Reference in New Issue
Block a user