绘制对接完成询盘类型页面;2.封装完成公用的tabs组件

This commit is contained in:
hejin 2025-08-17 13:51:05 +08:00
parent 8040be2280
commit 5180c719bf
8 changed files with 428 additions and 3 deletions

View File

@ -33,4 +33,18 @@ export const ordinaryProductApi = () => {
**/
export const hotNewsApi = () => {
return request.get('/web/hotNews')
}
/**
* @function 获取表单配置项
**/
export const formOptionsApi = () => {
return request.get('/web/inquirySet')
}
/**
* @function 提交询盘表单信息
**/
export const submitFormApi = (data) => {
return request.post('/web/inquirySave', data)
}

View File

@ -29,4 +29,38 @@ button {
-webkit-line-clamp: 2; //行数
line-clamp: 2;
-webkit-box-orient: vertical; //盒子中内容竖直排列
}
.form-box {
.label-box {
margin-bottom: 12rpx;
display: flex;
align-items: center;
.required {
margin-right: 4rpx;
color: #dd524d;
}
.label-icon {
margin-right: 4rpx;
width: 26rpx;
height: 26rpx;
}
label {
flex: 1;
color: #393c43;
}
}
.uni-easyinput__content {
border: 2.5rpx solid #d7dbe0 !important;
border-radius: 8rpx;
overflow: hidden;
}
.submit-btn {
width: max-content;
margin: 0 auto !important;
padding: 0 88rpx;
color: #fff;
background-color: #015fe8;
border-radius: 50rpx;
font-size: 28rpx;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

65
src/components/tabs.vue Normal file
View File

@ -0,0 +1,65 @@
<template>
<view class="tabs">
<view
class="tabs-item"
:class="index === props.active ? 'tabs-actvie' : ''"
v-for="(item,index) in props.list"
:key="index"
@click="tabsChange(index)"
>
{{item}}
</view>
</view>
</template>
<script setup>
import { ref } from 'vue';
const emits = defineEmits(['update:active','tabsChange'])
const props = defineProps({
list: {
type: Array,
default: () => {
return []
}
},
active: {
type: Number,
default: 0
}
})
const tabsChange = (index) => {
emits('update:active',index)
emits('tabsChange',index)
}
</script>
<style lang="scss" scoped>
.tabs {
margin: 36rpx 0;
display: flex;
align-items: center;
.tabs-item {
margin-right: 42rpx;
color: #707677;
font-size: 28rpx;
}
.tabs-actvie {
position: relative;
color: #292d2e;
font-weight: bold;
&::before {
content: '';
width: 24rpx;
height: 14rpx;
position: absolute;
left: 50%;
bottom: -15rpx;
transform: translateX(-50%);
background: url('@/assets/images/icon/select-common.png') no-repeat;
}
}
}
</style>

View File

@ -6,6 +6,7 @@ import zh from './locale/zh.json';
import en from './locale/en.json';
import ConfirmPopup from '@/components/comfirm-popup.vue'; // 全局统一的操作弹窗
import CustomHeader from "@/components/custom-header.vue";
import Tabs from "@/components/tabs.vue";
uni.$showTost = function (title='加载失败!',duration=1500,mask=false) {
// 变成异步代码,处理一些特殊页面 必须等待消息提示结束后在做操作
@ -40,6 +41,7 @@ export function createApp() {
app.use(createPinia());
app.component('ConfirmPopup', ConfirmPopup)
app.component('CustomHeader', CustomHeader)
app.component('Tabs', Tabs)
return {
app,
};

View File

@ -3,20 +3,330 @@
<CustomHeader title="Contact Us"></CustomHeader>
<view class="company-information">
<view class="main-box">
<image class="logo" src="@/assets/images/company-logo.png"></image>
<image class="badge" src="@/assets/images/company-badge.png"></image>
<view class="desc">
<view>
<label>{{$t('contactUs.contact')}}: </label>
<text>{{$t('contactUs.contacts')}}</text>
</view>
<view>
<label>{{$t('common.tel')}}: </label>
<text>+86-531-6998513</text>
</view>
<view>
<label>{{$t('common.addressLabel')}}: </label>
<text>{{$t('contactUs.address')}}</text>
</view>
</view>
</view>
</view>
<Tabs
:list="[$t('contactUs.contactUs'),$t('aboutUs.AboutUs')]"
v-model:active="tabsActive"
/>
<view class="tabs-content">
<template v-if="tabsActive===0">
<uni-forms
ref="dataFormRef"
class="form-box"
:model="dataForm"
:rules="dataFormRules"
label-position="top"
>
<uni-forms-item name="name" v-if="formConfig.name">
<template #label>
<view class="label-box">
<text v-if="formConfig.nameMust" class="required">*</text>
<image
class="label-icon"
src="@/assets/images/icon/user.png"
>
</image>
<label>{{$t('contactUs.name')}}</label>
</view>
</template>
<uni-easyinput type="text" v-model="dataForm.name" :placeholder="$t('contactUs.name')" />
</uni-forms-item>
<uni-forms-item name="title" v-if="formConfig.title">
<template #label>
<view class="label-box">
<text v-if="formConfig.titleMust" class="required">*</text>
<image
class="label-icon"
src="@/assets/images/icon/title.png"
>
</image>
<label>{{$t('contactUs.title')}}</label>
</view>
</template>
<uni-easyinput type="text" v-model="dataForm.title" :placeholder="$t('contactUs.title')" />
</uni-forms-item>
<uni-forms-item name="company" v-if="formConfig.company">
<template #label>
<view class="label-box">
<text v-if="formConfig.companyMust" class="required">*</text>
<image
class="label-icon"
src="@/assets/images/icon/company.png"
>
</image>
<label>{{$t('contactUs.company')}}</label>
</view>
</template>
<uni-easyinput type="text" v-model="dataForm.company" :placeholder="$t('contactUs.company')" />
</uni-forms-item>
<uni-forms-item name="email" v-if="formConfig.email">
<template #label>
<view class="label-box">
<text v-if="formConfig.emailMust" class="required">*</text>
<image
class="label-icon"
src="@/assets/images/icon/mail.png"
>
</image>
<label>{{$t('contactUs.mail')}}</label>
</view>
</template>
<uni-easyinput type="text" v-model="dataForm.email" :placeholder="$t('contactUs.mail')" />
</uni-forms-item>
<uni-forms-item name="tel" v-if="formConfig.tel">
<template #label>
<view class="label-box">
<text v-if="formConfig.telMust" class="required">*</text>
<image
class="label-icon"
src="@/assets/images/icon/phone.png"
>
</image>
<label>{{$t('contactUs.contactWay')}}</label>
</view>
</template>
<uni-easyinput type="text" v-model="dataForm.tel" :placeholder="$t('contactUs.contactWay')" />
</uni-forms-item>
<uni-forms-item name="content">
<template #label>
<view class="label-box">
<image
class="label-icon"
src="@/assets/images/icon/msg.png"
>
</image>
<label>{{$t('contactUs.desc')}}</label>
</view>
</template>
<uni-easyinput type="textarea" v-model="dataForm.content" :placeholder="$t('contactUs.desc')" />
</uni-forms-item>
<button class="submit-btn" @click="submit">{{$t('common.submit')}}</button>
</uni-forms>
</template>
<template v-else>
<view class="aboutu-us">
<view class="desc-item">
<image class="icon" src="@/assets/images/icon/phone2.png"></image>
<view class="desc">
<label>{{ $t('contactUs.contactUs') }}</label>
<view>0086 182 5311 2969</view>
</view>
</view>
<view class="desc-item">
<image class="icon" src="@/assets/images/icon/mail2.png"></image>
<view class="desc">
<label>{{ $t('common.E-mail') }}</label>
<view>alicesales@scdtrailer.com</view>
</view>
</view>
<view class="desc-item no-center">
<image class="icon" src="@/assets/images/icon/address.png"></image>
<view class="desc">
<label>{{ $t('common.addressLabel') }}</label>
<view>{{ $t('aboutUs.address') }}</view>
</view>
</view>
</view>
</template>
</view>
</view>
</template>
<script setup>
import { onLoad } from '@dcloudio/uni-app';
import { ref } from 'vue';
import { ref, computed } from 'vue';
import { useI18n } from 'vue-i18n'
import { formOptionsApi, submitFormApi } from '@/api/index.js';
console.log(uni.getSystemInfoSync())
const { t } = useI18n()
const tabsActive = ref(0)
const dataFormRef = ref()
const dataForm = ref({
name: '',
title: '',
company: '',
email: '',
tel: '',
content: '',
equipment: 'App'
})
const dataFormRules = computed(() => {
let config = formConfig.value
let rules = {
name: {
rules: [
{ required: config.nameMust, errorMessage: t('contactUs.name') }
]
},
title: {
rules: [
{ required: config.titleMust, errorMessage: t('contactUs.title') }
]
},
company: {
rules: [
{ required: config.companyMust, errorMessage: t('contactUs.company') }
]
},
email: {
rules: [
{ required: config.emailMust, errorMessage: t('contactUs.mail') }
]
},
tel: {
rules: [
{ required: config.telMust, errorMessage: t('contactUs.desc') }
]
}
}
return rules
})
const formConfig = ref({})
const getFormOptions = () => {
formOptionsApi().then(({data:res}) => {
formConfig.value = res.data
})
}
const submit = () => {
dataFormRef.value.validate().then(() => {
submitFormApi(dataForm.value).then(() => {
uni.$showTost(t('common.submitSuccess'))
dataForm.value.name = ''
dataForm.value.title = ''
dataForm.value.company = ''
dataForm.value.email = ''
dataForm.value.tel = ''
dataForm.value.content = ''
dataFormRef.value.clearValidate()
})
})
}
onLoad(() => {
getFormOptions()
})
</script>
<style lang="scss" scoped>
.pages {
padding: 25rpx;
.company-information {
width: 100%;
height: min-content;
margin-top: calc(var(--status-bar-height) + 30rpx);
/* #ifdef H5 */
margin-top: 40rpx;
/* #endif */
padding: 10rpx;
position: relative;
background-color: #fff;
border-radius: 8rpx;
.main-box {
width: 100%;
min-height: 380rpx;
padding: 50rpx 28rpx;
background-color: #f4f7fe;
border-radius: 8rpx;
.logo {
width: 416rpx;
height: 60rpx;
position: relative;
overflow: unset;
&::before {
content: '';
width: 96rpx;
height: 5rpx;
position: absolute;
left: 0;
bottom: -18rpx;
border-radius: 26rpx;
background-color: #1072ff;
z-index: 99;
}
}
.badge {
width: 136rpx;
height: 172rpx;
position: absolute;
top: -12rpx;
right: 36rpx;
}
.desc {
margin-top: 66rpx;
color: #393c43;
view {
margin-bottom: 20rpx;
&:last-child {
margin-bottom: 0;
}
}
}
}
}
.tabs-content {
width: 100%;
height: min-content;
padding: 24rpx 18rpx;
background-color: #fff;
border-radius: 8rpx;
.aboutu-us {
.desc-item {
padding: 14rpx 0;
display: flex;
align-items: center;
border-bottom: 3rpx dashed #dfe3e8;
image {
width: 56rpx;
height: 56rpx;
}
.desc {
flex: 1;
padding-left: 18rpx;
label {
color: #a9adb6;
}
view {
color: #393c43;
}
}
&:last-child {
border-bottom: none;
}
}
.no-center {
align-items: unset;
}
}
}
}
</style>