zjk
2026-04-09 06b96c68b0b0811eb310ee23cba7a332d3737e75
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
<script setup lang="ts">
import { reactive, ref } from 'vue'
 
definePage({
  name: 'appointment',
  layout: 'default',
  style: {
    navigationBarTitleText: '预约',
    navigationBarBackgroundColor: '#F6FBFF',
  },
})
 
const router = useRouter()
 
// 表单数据
const formData = reactive({
  interviewee: '',
  reason: '',
  dateType: 'single', // single 单日 | multi 多日
  visitTimeSingle: '',
  visitTimeMultiStart: '',
  visitTimeMultiEnd: '',
  entryType: 'person', // person 人员 | vehicle 车辆
  visitors: [] as any[], // 访客列表
})
 
// UI 选项
const reasonColumns = ['拜访', '会议', '邀约', '合作', '其他']
 
// 提交 loading 状态
const isSubmitting = ref(false)
 
// 校验与提交
function handleSubmit() {
  // 简单的前端校验
  if (!formData.interviewee) {
    return uni.showToast({ title: '请输入被访人', icon: 'none' })
  }
  if (!formData.reason) {
    return uni.showToast({ title: '请选择拜访事由', icon: 'none' })
  }
  if (formData.dateType === 'single' && !formData.visitTimeSingle) {
    return uni.showToast({ title: '请选择拜访时间', icon: 'none' })
  }
  if (formData.dateType === 'multi' && (!formData.visitTimeMultiStart || !formData.visitTimeMultiEnd)) {
    return uni.showToast({ title: '请选择完整的拜访时间', icon: 'none' })
  }
  if (!formData.entryType) {
    return uni.showToast({ title: '请选择进场类型', icon: 'none' })
  }
  if (formData.visitors.length === 0) {
    return uni.showToast({ title: '请选择来访人员', icon: 'none' })
  }
 
  isSubmitting.value = true
  uni.showLoading({ title: '提交中...' })
 
  // 模拟接口请求
  setTimeout(() => {
    isSubmitting.value = false
    uni.hideLoading()
    uni.showToast({
      title: '预约成功',
      icon: 'success',
      duration: 2000,
    })
    setTimeout(() => {
      router.back()
    }, 2000)
  }, 1500)
}
 
// 模拟选择来访人员
function handleSelectVisitor() {
  // 这里可以跳转到选人页面,为了演示直接 Mock
  formData.visitors.push({ name: `访客${formData.visitors.length + 1}` })
}
</script>
 
<template>
  <view class="min-h-screen bg-[#F6FBFF] pb-[200rpx]">
    <!-- 顶部背景点缀 (与首页风格类似) -->
    <view class="absolute left-0 top-0 z-0 h-[400rpx] w-full" style="background: linear-gradient(180deg, #D1E6FE 0%, #F6FBFF 100%);" />
 
    <view class="relative z-10 px-[32rpx] pt-[32rpx]">
      <!-- 拜访信息模块 -->
      <view class="mb-[16rpx]">
        <text class="text-[32rpx] text-[#1A1A1A] font-bold">
          拜访信息
        </text>
      </view>
      <view class="mb-[48rpx] rounded-[16rpx] bg-white p-[8rpx] shadow-sm">
        <wd-form :model="formData">
          <!-- 被访人 -->
          <wd-input
            v-model="formData.interviewee"
            label="被访人"
            placeholder="请输入要接见谁"
            required
            align="right"
          />
 
          <!-- 拜访事由 -->
          <wd-picker
            v-model="formData.reason"
            label="拜访事由"
            :columns="reasonColumns"
            placeholder="请选择拜访事由"
            required
            align="right"
          />
 
          <!-- 拜访时间类型切换 -->
          <wd-cell title="拜访时间" required custom-class="cell-with-switch">
            <view class="flex justify-end">
              <view class="h-[64rpx] w-[180rpx] flex rounded-full bg-[#F5F5F5] p-[4rpx]">
                <view
                  class="flex flex-1 items-center justify-center rounded-full text-[24rpx] transition-all"
                  :class="formData.dateType === 'single' ? 'bg-[#0068FF] text-white' : 'text-[#666666]'"
                  @click="formData.dateType = 'single'"
                >
                  单日
                </view>
                <view
                  class="flex flex-1 items-center justify-center rounded-full text-[24rpx] transition-all"
                  :class="formData.dateType === 'multi' ? 'bg-[#0068FF] text-white' : 'text-[#666666]'"
                  @click="formData.dateType = 'multi'"
                >
                  多日
                </view>
              </view>
            </view>
          </wd-cell>
 
          <!-- 单日时间选择 -->
          <wd-datetime-picker
            v-if="formData.dateType === 'single'"
            v-model="formData.visitTimeSingle"
            type="datetime"
            placeholder="请选择拜访时间"
            align="right"
          />
 
          <!-- 多日时间选择 (由于 wd-datetime-picker 没有 range,这里用两个 picker 或一个特定交互代替) -->
          <template v-if="formData.dateType === 'multi'">
            <wd-datetime-picker
              v-model="formData.visitTimeMultiStart"
              type="datetime"
              label="开始时间"
              placeholder="请选择开始时间"
              align="right"
            />
            <wd-datetime-picker
              v-model="formData.visitTimeMultiEnd"
              type="datetime"
              label="结束时间"
              placeholder="请选择结束时间"
              align="right"
            />
          </template>
        </wd-form>
      </view>
 
      <!-- 来访人信息模块 -->
      <view class="mb-[16rpx] flex items-end">
        <text class="text-[32rpx] text-[#1A1A1A] font-bold">
          来访人信息
        </text>
        <text class="ml-[16rpx] text-[24rpx] text-[#999999]">
          选择您及同行人员
        </text>
      </view>
      <view class="mb-[24rpx] rounded-[16rpx] bg-white p-[8rpx] shadow-sm">
        <wd-cell title="进场类型" custom-class="cell-with-switch">
          <view class="flex justify-end">
            <wd-radio-group v-model="formData.entryType" inline shape="dot">
              <wd-radio value="person">
                人员进场
              </wd-radio>
              <wd-radio value="vehicle">
                车辆进场
              </wd-radio>
            </wd-radio-group>
          </view>
        </wd-cell>
      </view>
 
      <view class="mb-[48rpx] rounded-[16rpx] bg-white p-[32rpx] shadow-sm">
        <view class="mb-[32rpx] flex items-center">
          <text class="text-[28rpx] text-[#1A1A1A]">
            来访人员
          </text>
          <text class="ml-[8rpx] text-[24rpx] text-[#FF4D4F]">
            (必填)
          </text>
        </view>
 
        <view class="flex flex-col items-center">
          <view v-if="formData.visitors.length > 0" class="mb-[24rpx] w-full flex flex-wrap gap-[16rpx]">
            <view v-for="(v, index) in formData.visitors" :key="index" class="rounded-full bg-[#F5F5F5] px-[24rpx] py-[8rpx] text-[24rpx]">
              {{ v.name }}
            </view>
          </view>
          <view
            class="h-[72rpx] w-[280rpx] flex items-center justify-center border border-[#0068FF] rounded-full border-solid bg-[#F0F6FF]"
            @click="handleSelectVisitor"
          >
            <text class="mb-[4rpx] text-[36rpx] text-[#0068FF] leading-none">
              +
            </text>
            <text class="ml-[8rpx] text-[28rpx] text-[#0068FF]">
              选择来访人员
            </text>
          </view>
        </view>
      </view>
 
      <!-- 提交按钮 -->
      <view class="mt-[64rpx]">
        <wd-button type="primary" size="large" block custom-class="submit-btn" :loading="isSubmitting" @click="handleSubmit">
          提交
        </wd-button>
      </view>
    </view>
  </view>
</template>
 
<style lang="scss" scoped>
:deep(.cell-with-switch .wd-cell__value) {
  flex: 1;
}
 
:deep(.submit-btn) {
  height: 96rpx !important;
  border-radius: 48rpx !important;
  font-size: 32rpx !important;
  background: #0068FF !important;
}
</style>