This commit is contained in:
parent
3214f66fb9
commit
96869761e2
|
|
@ -0,0 +1,33 @@
|
|||
# Design QA
|
||||
|
||||
- source visual truth path: `C:\Users\29169\AppData\Local\Temp\codex-clipboard-5202e314-49da-48b8-a154-05e5d4a96bcc.png`
|
||||
- implementation screenshot path: unavailable
|
||||
- viewport: target 750 x 1624
|
||||
- state: default form state
|
||||
|
||||
## Full-view comparison evidence
|
||||
|
||||
The source image was opened at its original resolution and used to reproduce the page structure, spacing, typography hierarchy, form controls, green action button, and footer content. A browser-rendered implementation screenshot could not be captured because the repository's existing H5 production build fails in the legacy Babel post-processing stage with an invalid `development` compilation target.
|
||||
|
||||
## Focused region comparison evidence
|
||||
|
||||
Blocked for the same reason. Source details were inspected directly, but a rendered comparison artifact is unavailable.
|
||||
|
||||
## Findings
|
||||
|
||||
- No code-level P0/P1 issue was found by the WeChat production build or stylesheet validation.
|
||||
- Visual fidelity remains unverified in a browser-rendered 750 x 1624 comparison.
|
||||
|
||||
## Comparison history
|
||||
|
||||
- Initial implementation completed from the supplied reference.
|
||||
- No visual comparison iteration could be performed because the H5 preview build is blocked by the existing Babel target configuration.
|
||||
|
||||
## Verification
|
||||
|
||||
- Primary interactions implemented: service type selection, all text inputs, agreement selection, policy dialogs, validation feedback, and success dialog.
|
||||
- WeChat production build: passed.
|
||||
- Stylesheet validation: passed.
|
||||
- Browser console check: blocked because no browser-rendered preview was available.
|
||||
|
||||
final result: blocked
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
export default definePageConfig({
|
||||
navigationBarTitleText: '门店企业标注快办',
|
||||
navigationBarBackgroundColor: '#05256e',
|
||||
navigationBarTextStyle: 'white',
|
||||
backgroundColor: '#f3f7ff',
|
||||
backgroundTextStyle: 'light'
|
||||
navigationBarBackgroundColor: '#ffffff',
|
||||
navigationBarTextStyle: 'black',
|
||||
backgroundColor: '#f2f7fb',
|
||||
backgroundTextStyle: 'dark'
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,19 +1,18 @@
|
|||
/* stylelint-disable selector-class-pattern -- The project requires BEM class names. */
|
||||
|
||||
.landing-page {
|
||||
--landing-midnight: #05256e;
|
||||
--landing-service-blue: #0b57d0;
|
||||
--landing-action-blue: #1677ff;
|
||||
--landing-signal-cyan: #5fc8ff;
|
||||
--landing-canvas: #f3f7ff;
|
||||
--landing-green: #07c160;
|
||||
--landing-green-dark: #06ae56;
|
||||
--landing-canvas: #f2f7fb;
|
||||
--landing-surface: #fff;
|
||||
--landing-ink: #102a56;
|
||||
--landing-muted: #425f8c;
|
||||
--landing-border: #d7e4ff;
|
||||
--landing-ink: #17181a;
|
||||
--landing-muted: #606772;
|
||||
--landing-placeholder: #959ba3;
|
||||
--landing-border: #c7ccd2;
|
||||
--landing-error: #d94242;
|
||||
|
||||
min-height: 100vh;
|
||||
padding-bottom: calc(132px + constant(safe-area-inset-bottom));
|
||||
padding-bottom: calc(132px + env(safe-area-inset-bottom));
|
||||
padding: 54px 30px calc(38px + env(safe-area-inset-bottom));
|
||||
overflow-x: hidden;
|
||||
box-sizing: border-box;
|
||||
color: var(--landing-ink);
|
||||
|
|
@ -21,295 +20,195 @@
|
|||
background: var(--landing-canvas);
|
||||
}
|
||||
|
||||
@supports (color: oklch(0 0 0)) {
|
||||
.landing-page {
|
||||
--landing-midnight: oklch(29.95% 0.1316 262.9deg);
|
||||
--landing-service-blue: oklch(49.49% 0.1992 260.6deg);
|
||||
--landing-action-blue: oklch(59.87% 0.2194 259deg);
|
||||
--landing-signal-cyan: oklch(79.25% 0.1244 234.3deg);
|
||||
--landing-canvas: oklch(97.54% 0.0115 264.5deg);
|
||||
--landing-surface: oklch(100% 0 0deg);
|
||||
--landing-ink: oklch(29.25% 0.086 260.3deg);
|
||||
--landing-muted: oklch(48.32% 0.0808 258.9deg);
|
||||
--landing-border: oklch(91.74% 0.0395 265.1deg);
|
||||
}
|
||||
.landing-page__intro {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.landing-page__hero {
|
||||
position: relative;
|
||||
padding: 52px 32px 0;
|
||||
overflow: hidden;
|
||||
border-radius: 0 0 36px 36px;
|
||||
box-sizing: border-box;
|
||||
background:
|
||||
radial-gradient(circle at 88% 12%, rgb(95 200 255 / 18%) 0, rgb(95 200 255 / 0%) 30%),
|
||||
linear-gradient(145deg, var(--landing-midnight) 0%, #073b9e 52%, var(--landing-service-blue) 100%);
|
||||
}
|
||||
|
||||
.landing-page__hero-copy {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
max-width: 640px;
|
||||
animation: landing-rise 620ms cubic-bezier(0.16, 1, 0.3, 1) both;
|
||||
}
|
||||
|
||||
.landing-page__hero-title {
|
||||
.landing-page__title {
|
||||
display: block;
|
||||
color: var(--landing-surface);
|
||||
font-size: 54px;
|
||||
font-size: 48px;
|
||||
font-weight: 700;
|
||||
line-height: 1.18;
|
||||
line-height: 1.35;
|
||||
letter-spacing: -1px;
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.landing-page__hero-description {
|
||||
.landing-page__description {
|
||||
display: block;
|
||||
max-width: 620px;
|
||||
margin-top: 18px;
|
||||
color: rgb(255 255 255 / 88%);
|
||||
color: var(--landing-muted);
|
||||
font-size: 28px;
|
||||
line-height: 1.65;
|
||||
text-wrap: pretty;
|
||||
}
|
||||
|
||||
.landing-page__hero-visual {
|
||||
position: relative;
|
||||
height: 340px;
|
||||
margin: 20px -32px 0;
|
||||
overflow: hidden;
|
||||
animation: landing-reveal 760ms 100ms cubic-bezier(0.16, 1, 0.3, 1) both;
|
||||
}
|
||||
|
||||
.landing-page__hero-image {
|
||||
.landing-page__notice {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
margin-top: -68px;
|
||||
}
|
||||
|
||||
.landing-page__content {
|
||||
padding: 40px 28px 72px;
|
||||
box-sizing: border-box;
|
||||
background: var(--landing-canvas);
|
||||
}
|
||||
|
||||
.landing-page__section-title {
|
||||
display: block;
|
||||
color: var(--landing-ink);
|
||||
font-size: 34px;
|
||||
font-weight: 700;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.landing-page__section-note {
|
||||
display: block;
|
||||
margin-top: 8px;
|
||||
color: var(--landing-muted);
|
||||
font-size: 28px;
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.landing-page__industries {
|
||||
display: flex;
|
||||
margin-top: 32px;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--landing-border);
|
||||
border-radius: 28px;
|
||||
background: var(--landing-surface);
|
||||
}
|
||||
|
||||
.landing-page__industry {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 28px 8px 24px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.landing-page__industry + .landing-page__industry {
|
||||
border-left: 1px solid var(--landing-border);
|
||||
}
|
||||
|
||||
.landing-page__industry-mark {
|
||||
display: flex;
|
||||
width: 88px;
|
||||
height: 88px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px solid rgb(22 119 255 / 18%);
|
||||
border-radius: 50%;
|
||||
color: var(--landing-service-blue);
|
||||
font-size: 34px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
background: rgb(22 119 255 / 8%);
|
||||
}
|
||||
|
||||
.landing-page__industry-name {
|
||||
margin-top: 14px;
|
||||
color: var(--landing-ink);
|
||||
color: var(--landing-muted);
|
||||
font-size: 24px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.landing-page__form {
|
||||
margin-top: 30px;
|
||||
padding: 28px;
|
||||
border: 1px solid #d9dde1;
|
||||
border-radius: 14px;
|
||||
box-sizing: border-box;
|
||||
background: var(--landing-surface);
|
||||
box-shadow: 0 8px 28px rgb(40 65 86 / 5%);
|
||||
}
|
||||
|
||||
.landing-page__field + .landing-page__field {
|
||||
margin-top: 26px;
|
||||
}
|
||||
|
||||
.landing-page__label {
|
||||
display: block;
|
||||
margin-bottom: 12px;
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.landing-page__section--services {
|
||||
margin-top: 56px;
|
||||
.landing-page__service-types {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.landing-page__services {
|
||||
margin-top: 28px;
|
||||
overflow: hidden;
|
||||
.landing-page__service-type {
|
||||
display: flex;
|
||||
height: 72px;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px solid var(--landing-border);
|
||||
border-radius: 24px;
|
||||
border-radius: 10px;
|
||||
box-sizing: border-box;
|
||||
font-size: 28px;
|
||||
background: var(--landing-surface);
|
||||
}
|
||||
|
||||
.landing-page__service {
|
||||
.landing-page__service-type--selected {
|
||||
border-color: rgb(7 193 96 / 45%);
|
||||
background: rgb(7 193 96 / 3%);
|
||||
}
|
||||
|
||||
.landing-page__radio {
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
align-items: center;
|
||||
padding: 30px 26px;
|
||||
border-bottom: 1px solid var(--landing-border);
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.landing-page__input,
|
||||
.landing-page__textarea {
|
||||
width: 100%;
|
||||
border: 1px solid var(--landing-border);
|
||||
border-radius: 10px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.landing-page__service:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.landing-page__service-mark {
|
||||
display: flex;
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
flex: 0 0 72px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
color: var(--landing-surface);
|
||||
font-size: 26px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
background: var(--landing-service-blue);
|
||||
}
|
||||
|
||||
.landing-page__service-copy {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.landing-page__service-name {
|
||||
color: var(--landing-ink);
|
||||
font-size: 28px;
|
||||
background: var(--landing-surface);
|
||||
transition: border-color 160ms ease, box-shadow 160ms ease;
|
||||
}
|
||||
|
||||
.landing-page__input {
|
||||
height: 72px;
|
||||
padding: 0 22px;
|
||||
}
|
||||
|
||||
.landing-page__textarea {
|
||||
height: 116px;
|
||||
padding: 18px 22px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.landing-page__input:focus,
|
||||
.landing-page__textarea:focus {
|
||||
border-color: var(--landing-green);
|
||||
box-shadow: 0 0 0 3px rgb(7 193 96 / 10%);
|
||||
}
|
||||
|
||||
.landing-page__input--error {
|
||||
border-color: var(--landing-error);
|
||||
}
|
||||
|
||||
.landing-page__placeholder {
|
||||
color: var(--landing-placeholder);
|
||||
}
|
||||
|
||||
.landing-page__error,
|
||||
.landing-page__agreement-error {
|
||||
display: block;
|
||||
margin-top: 8px;
|
||||
color: var(--landing-error);
|
||||
font-size: 22px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.landing-page__agreement {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 26px 18px 0;
|
||||
font-size: 24px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.landing-page__checkbox {
|
||||
margin-right: 10px;
|
||||
transform: scale(0.88);
|
||||
transform-origin: left center;
|
||||
}
|
||||
|
||||
.landing-page__agreement-text {
|
||||
color: var(--landing-ink);
|
||||
}
|
||||
|
||||
.landing-page__link {
|
||||
color: var(--landing-green);
|
||||
}
|
||||
|
||||
.landing-page__agreement-error {
|
||||
margin-right: 18px;
|
||||
margin-left: 18px;
|
||||
}
|
||||
|
||||
.landing-page__submit {
|
||||
height: 84px;
|
||||
margin: 24px 10px 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
border-radius: 12px;
|
||||
color: #fff;
|
||||
font-size: 32px;
|
||||
font-weight: 700;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.landing-page__service-description {
|
||||
margin-top: 8px;
|
||||
color: var(--landing-muted);
|
||||
font-size: 28px;
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.landing-page__consultation {
|
||||
position: fixed;
|
||||
z-index: 20;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
align-items: center;
|
||||
padding: 18px 24px;
|
||||
padding-bottom: calc(18px + constant(safe-area-inset-bottom));
|
||||
padding-bottom: calc(18px + env(safe-area-inset-bottom));
|
||||
border-top: 1px solid var(--landing-border);
|
||||
box-sizing: border-box;
|
||||
background: var(--landing-surface);
|
||||
box-shadow: 0 -12px 36px rgb(16 42 86 / 14%);
|
||||
}
|
||||
|
||||
.landing-page__consultation-copy {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.landing-page__consultation-label {
|
||||
color: var(--landing-muted);
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.landing-page__consultation-phone {
|
||||
margin-top: 2px;
|
||||
color: var(--landing-ink);
|
||||
font-size: 30px;
|
||||
font-weight: 700;
|
||||
line-height: 1.35;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.landing-page__call-button {
|
||||
min-width: 200px;
|
||||
height: 88px;
|
||||
margin: 0;
|
||||
padding: 0 32px;
|
||||
border: 0;
|
||||
border-radius: 999px;
|
||||
color: var(--landing-surface);
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
line-height: 88px;
|
||||
background: var(--landing-action-blue);
|
||||
line-height: 84px;
|
||||
background: var(--landing-green);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.landing-page__call-button::after {
|
||||
.landing-page__submit::after {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.landing-page__call-button--pressed {
|
||||
background: #0849b4;
|
||||
.landing-page__submit--pressed {
|
||||
background: var(--landing-green-dark);
|
||||
transform: scale(0.99);
|
||||
}
|
||||
|
||||
@keyframes landing-rise {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes landing-reveal {
|
||||
from {
|
||||
opacity: 0.7;
|
||||
clip-path: inset(28% 0 0 0);
|
||||
transform: translateY(18px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
clip-path: inset(0 0 0 0);
|
||||
transform: translateY(0);
|
||||
}
|
||||
.landing-page__footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 28px;
|
||||
flex-direction: column;
|
||||
color: var(--landing-muted);
|
||||
font-size: 22px;
|
||||
line-height: 1.75;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.landing-page__hero-copy,
|
||||
.landing-page__hero-visual {
|
||||
animation: none;
|
||||
.landing-page__input,
|
||||
.landing-page__textarea,
|
||||
.landing-page__submit {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,132 +1,213 @@
|
|||
import { Button, Image, Text, View } from '@tarojs/components'
|
||||
import { Button, Checkbox, CheckboxGroup, Input, Radio, RadioGroup, Text, Textarea, View } from '@tarojs/components'
|
||||
import Taro from '@tarojs/taro'
|
||||
import heroImage from '@/assets/images/landing-storefronts.jpg'
|
||||
import { useState } from 'react'
|
||||
import './index.scss'
|
||||
|
||||
const CONTACT_PHONE = '4001166311'
|
||||
type ServiceType = 'new' | 'update'
|
||||
|
||||
const INDUSTRIES = [
|
||||
{ mark: '百', name: '百货' },
|
||||
{ mark: '超', name: '超市' },
|
||||
{ mark: '便', name: '便利店' },
|
||||
]
|
||||
type ApplicationForm = {
|
||||
serviceType: ServiceType
|
||||
storeName: string
|
||||
storeAddress: string
|
||||
contactName: string
|
||||
contactPhone: string
|
||||
description: string
|
||||
}
|
||||
|
||||
const SERVICES = [
|
||||
{
|
||||
mark: '推',
|
||||
name: '推广',
|
||||
description: '为门店推广提供支持',
|
||||
},
|
||||
{
|
||||
mark: '曝',
|
||||
name: '门店曝光',
|
||||
description: '提高门店曝光量',
|
||||
},
|
||||
]
|
||||
type FormErrors = Partial<Record<keyof ApplicationForm | 'agreement', string>>
|
||||
|
||||
const getErrorMessage = (error: unknown) => {
|
||||
if (error instanceof Error) {
|
||||
return error.message
|
||||
const INITIAL_FORM: ApplicationForm = {
|
||||
serviceType: 'new',
|
||||
storeName: '',
|
||||
storeAddress: '',
|
||||
contactName: '',
|
||||
contactPhone: '',
|
||||
description: '',
|
||||
}
|
||||
|
||||
const PHONE_PATTERN = /^1[3-9]\d{9}$/
|
||||
|
||||
const validateForm = (form: ApplicationForm, agreed: boolean) => {
|
||||
const errors: FormErrors = {}
|
||||
|
||||
if (!form.storeName.trim()) errors.storeName = '请输入门店名称'
|
||||
if (!form.storeAddress.trim()) errors.storeAddress = '请输入门店地址'
|
||||
if (!form.contactName.trim()) errors.contactName = '请输入联系人姓名'
|
||||
|
||||
if (!form.contactPhone.trim()) {
|
||||
errors.contactPhone = '请输入联系电话'
|
||||
} else if (!PHONE_PATTERN.test(form.contactPhone.trim())) {
|
||||
errors.contactPhone = '请输入正确的手机号码'
|
||||
}
|
||||
|
||||
if (typeof error === 'object' && error && 'errMsg' in error) {
|
||||
return String((error as { errMsg?: string }).errMsg)
|
||||
}
|
||||
if (!form.description.trim()) errors.description = '请描述需要办理的内容'
|
||||
if (!agreed) errors.agreement = '请阅读并同意隐私政策和服务说明'
|
||||
|
||||
return ''
|
||||
return errors
|
||||
}
|
||||
|
||||
export default function Landing () {
|
||||
const handleCall = async () => {
|
||||
try {
|
||||
await Taro.makePhoneCall({ phoneNumber: CONTACT_PHONE })
|
||||
} catch (error) {
|
||||
const errorMessage = getErrorMessage(error)
|
||||
const [form, setForm] = useState<ApplicationForm>(INITIAL_FORM)
|
||||
const [agreed, setAgreed] = useState(false)
|
||||
const [errors, setErrors] = useState<FormErrors>({})
|
||||
|
||||
if (errorMessage.toLowerCase().includes('cancel')) {
|
||||
const updateField = <K extends keyof ApplicationForm>(field: K, value: ApplicationForm[K]) => {
|
||||
setForm((current) => ({ ...current, [field]: value }))
|
||||
setErrors((current) => ({ ...current, [field]: undefined }))
|
||||
}
|
||||
|
||||
const showPolicy = (type: 'privacy' | 'service') => {
|
||||
const isPrivacy = type === 'privacy'
|
||||
|
||||
Taro.showModal({
|
||||
title: isPrivacy ? '隐私政策' : '服务说明',
|
||||
content: isPrivacy
|
||||
? '您填写的信息仅用于本次门店标注服务的联系与确认,我们将妥善保护您的个人信息。'
|
||||
: '提交申请后,工作人员将在服务时间内联系您核对资料。具体办理结果以实际审核情况为准。',
|
||||
showCancel: false,
|
||||
confirmText: '我知道了',
|
||||
})
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
const validationErrors = validateForm(form, agreed)
|
||||
const firstError = Object.values(validationErrors)[0]
|
||||
|
||||
setErrors(validationErrors)
|
||||
|
||||
if (firstError) {
|
||||
Taro.showToast({ title: firstError, icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
console.error('Failed to make phone call.', error)
|
||||
Taro.showToast({
|
||||
title: '暂时无法拨打,请稍后重试',
|
||||
icon: 'none'
|
||||
Taro.showModal({
|
||||
title: '提交成功',
|
||||
content: '您的申请已提交,工作人员将在服务时间内联系您确认。',
|
||||
showCancel: false,
|
||||
confirmText: '我知道了',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<View className='landing-page'>
|
||||
<View className='landing-page__hero'>
|
||||
<View className='landing-page__hero-copy'>
|
||||
<Text className='landing-page__hero-title'>门店企业标注快办</Text>
|
||||
<Text className='landing-page__hero-description'>
|
||||
面向百货、超市与便利店,提供门店企业标注快办服务。
|
||||
<View className='landing-page__intro'>
|
||||
<Text className='landing-page__title'>门店企业标注,在线提交</Text>
|
||||
<Text className='landing-page__description'>
|
||||
提供门店新增标注、信息修改等企业服务,提交资料后由工作人员联系确认。
|
||||
</Text>
|
||||
<Text className='landing-page__notice'>第三方企业服务,非地图平台官方服务</Text>
|
||||
</View>
|
||||
|
||||
<View className='landing-page__hero-visual'>
|
||||
<Image
|
||||
className='landing-page__hero-image'
|
||||
src={heroImage}
|
||||
mode='widthFix'
|
||||
ariaLabel='百货、超市和便利店门店剪影'
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className='landing-page__content'>
|
||||
<View className='landing-page__section'>
|
||||
<Text className='landing-page__section-title'>服务行业</Text>
|
||||
<Text className='landing-page__section-note'>覆盖常见线下零售业态</Text>
|
||||
|
||||
<View className='landing-page__industries'>
|
||||
{INDUSTRIES.map((industry) => (
|
||||
<View className='landing-page__industry' key={industry.name}>
|
||||
<View className='landing-page__industry-mark'>
|
||||
<Text>{industry.mark}</Text>
|
||||
</View>
|
||||
<Text className='landing-page__industry-name'>{industry.name}</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className='landing-page__section landing-page__section--services'>
|
||||
<Text className='landing-page__section-title'>核心服务</Text>
|
||||
<Text className='landing-page__section-note'>围绕门店现场提供业务支持</Text>
|
||||
|
||||
<View className='landing-page__services'>
|
||||
{SERVICES.map((service) => (
|
||||
<View className='landing-page__service' key={service.name}>
|
||||
<View className='landing-page__service-mark'>
|
||||
<Text>{service.mark}</Text>
|
||||
</View>
|
||||
<View className='landing-page__service-copy'>
|
||||
<Text className='landing-page__service-name'>{service.name}</Text>
|
||||
<Text className='landing-page__service-description'>
|
||||
{service.description}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className='landing-page__consultation'>
|
||||
<View className='landing-page__consultation-copy'>
|
||||
<Text className='landing-page__consultation-label'>业务咨询</Text>
|
||||
<Text className='landing-page__consultation-phone'>{CONTACT_PHONE}</Text>
|
||||
</View>
|
||||
<Button
|
||||
className='landing-page__call-button'
|
||||
hoverClass='landing-page__call-button--pressed'
|
||||
ariaLabel={`拨打业务咨询电话 ${CONTACT_PHONE}`}
|
||||
onClick={handleCall}
|
||||
<View className='landing-page__form'>
|
||||
<View className='landing-page__field'>
|
||||
<Text className='landing-page__label'>办理类型</Text>
|
||||
<RadioGroup
|
||||
className='landing-page__service-types'
|
||||
onChange={(event) => updateField('serviceType', event.detail.value as ServiceType)}
|
||||
>
|
||||
立即拨打
|
||||
<View className={`landing-page__service-type ${form.serviceType === 'new' ? 'landing-page__service-type--selected' : ''}`}>
|
||||
<Radio className='landing-page__radio' value='new' checked={form.serviceType === 'new'} color='#07c160'>新增标注</Radio>
|
||||
</View>
|
||||
<View className={`landing-page__service-type ${form.serviceType === 'update' ? 'landing-page__service-type--selected' : ''}`}>
|
||||
<Radio className='landing-page__radio' value='update' checked={form.serviceType === 'update'} color='#07c160'>信息修改</Radio>
|
||||
</View>
|
||||
</RadioGroup>
|
||||
</View>
|
||||
|
||||
<View className='landing-page__field'>
|
||||
<Text className='landing-page__label'>门店名称</Text>
|
||||
<Input
|
||||
className={`landing-page__input ${errors.storeName ? 'landing-page__input--error' : ''}`}
|
||||
value={form.storeName}
|
||||
maxlength={50}
|
||||
placeholder='请输入营业执照上的门店名称'
|
||||
placeholderClass='landing-page__placeholder'
|
||||
onInput={(event) => updateField('storeName', event.detail.value)}
|
||||
/>
|
||||
{errors.storeName && <Text className='landing-page__error'>{errors.storeName}</Text>}
|
||||
</View>
|
||||
|
||||
<View className='landing-page__field'>
|
||||
<Text className='landing-page__label'>门店地址</Text>
|
||||
<Input
|
||||
className={`landing-page__input ${errors.storeAddress ? 'landing-page__input--error' : ''}`}
|
||||
value={form.storeAddress}
|
||||
maxlength={100}
|
||||
placeholder='请输入完整经营地址'
|
||||
placeholderClass='landing-page__placeholder'
|
||||
onInput={(event) => updateField('storeAddress', event.detail.value)}
|
||||
/>
|
||||
{errors.storeAddress && <Text className='landing-page__error'>{errors.storeAddress}</Text>}
|
||||
</View>
|
||||
|
||||
<View className='landing-page__field'>
|
||||
<Text className='landing-page__label'>联系人</Text>
|
||||
<Input
|
||||
className={`landing-page__input ${errors.contactName ? 'landing-page__input--error' : ''}`}
|
||||
value={form.contactName}
|
||||
maxlength={30}
|
||||
placeholder='请输入联系人姓名'
|
||||
placeholderClass='landing-page__placeholder'
|
||||
onInput={(event) => updateField('contactName', event.detail.value)}
|
||||
/>
|
||||
{errors.contactName && <Text className='landing-page__error'>{errors.contactName}</Text>}
|
||||
</View>
|
||||
|
||||
<View className='landing-page__field'>
|
||||
<Text className='landing-page__label'>联系电话</Text>
|
||||
<Input
|
||||
className={`landing-page__input ${errors.contactPhone ? 'landing-page__input--error' : ''}`}
|
||||
value={form.contactPhone}
|
||||
type='number'
|
||||
maxlength={11}
|
||||
placeholder='请输入手机号码'
|
||||
placeholderClass='landing-page__placeholder'
|
||||
onInput={(event) => updateField('contactPhone', event.detail.value)}
|
||||
/>
|
||||
{errors.contactPhone && <Text className='landing-page__error'>{errors.contactPhone}</Text>}
|
||||
</View>
|
||||
|
||||
<View className='landing-page__field'>
|
||||
<Text className='landing-page__label'>补充说明</Text>
|
||||
<Textarea
|
||||
className={`landing-page__textarea ${errors.description ? 'landing-page__input--error' : ''}`}
|
||||
value={form.description}
|
||||
maxlength={300}
|
||||
placeholder='请描述需要办理的内容'
|
||||
placeholderClass='landing-page__placeholder'
|
||||
onInput={(event) => updateField('description', event.detail.value)}
|
||||
/>
|
||||
{errors.description && <Text className='landing-page__error'>{errors.description}</Text>}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<CheckboxGroup
|
||||
className='landing-page__agreement'
|
||||
onChange={(event) => {
|
||||
setAgreed(event.detail.value.includes('agreed'))
|
||||
setErrors((current) => ({ ...current, agreement: undefined }))
|
||||
}}
|
||||
>
|
||||
<Checkbox className='landing-page__checkbox' value='agreed' checked={agreed} color='#07c160' />
|
||||
<Text className='landing-page__agreement-text'>我已阅读并同意</Text>
|
||||
<Text className='landing-page__link' onClick={() => showPolicy('privacy')}>《隐私政策》</Text>
|
||||
<Text className='landing-page__agreement-text'>和</Text>
|
||||
<Text className='landing-page__link' onClick={() => showPolicy('service')}>《服务说明》</Text>
|
||||
</CheckboxGroup>
|
||||
{errors.agreement && <Text className='landing-page__agreement-error'>{errors.agreement}</Text>}
|
||||
|
||||
<Button
|
||||
className='landing-page__submit'
|
||||
hoverClass='landing-page__submit--pressed'
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
提交申请
|
||||
</Button>
|
||||
|
||||
<View className='landing-page__footer'>
|
||||
<Text>服务时间:工作日 9:00-18:00</Text>
|
||||
<Text>客服电话:400-800-1234</Text>
|
||||
<Text>第三方企业服务,请根据实际需求自愿提交</Text>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in New Issue