feat:访客邀约和详情

This commit is contained in:
weiwei committed 2025-09-05 11:19:50 +08:00
1 parent c86d29bd8d
commit b7ae1b0062
10 files changed
+111 -89

No files matched your search

+24 -15
View File
@@ -1,8 +1,12 @@
<template>
<crud-layout title="详情" mainIsScroll bg="/static/page/blue-bg.png">
<view v-if="detail.id">
<tm-sheet :margin="[0, 20]" class="second-text-32">
<tm-text font-size="32">访客信息</tm-text>
<view class="h-20rpx" />
<tm-alert v-if="alertList[detail.checkStatus]" :showClose="false" skin="normal" :color="alertList[detail.checkStatus].color">
{{ alertList[detail.checkStatus].text }}
</tm-alert>
<tm-sheet :margin="[0, 20]" class="second-text-30">
<tm-text class="prefix_title" font-size="32">访客信息</tm-text>
<view class="flex justify-between mt-1">
<text>访客姓名:</text>
<text>{{ detail.name }}</text>
@@ -37,8 +41,8 @@
</view>
</tm-sheet>
<tm-sheet :margin="[0, 20]" class="second-text-32">
<tm-text font-size="32">时间</tm-text>
<tm-sheet :margin="[0, 20]" class="second-text-30">
<tm-text class="prefix_title" font-size="32">时间</tm-text>
<view class="flex justify-between mt-1">
<text>预计来访时间:</text>
<text>{{ detail.vendDate }}</text>
@@ -49,8 +53,8 @@
</view>
</tm-sheet>
<tm-sheet :margin="[0, 20]" class="second-text-32">
<tm-text font-size="32">其他</tm-text>
<tm-sheet :margin="[0, 20]" class="second-text-30">
<tm-text class="prefix_title" font-size="32">其他</tm-text>
<view class="flex justify-between mt-1">
<text>创建方式:</text>
<text>{{ detail.type == "1" ? "主动申请" : detail.type == "2" ? "邀约" : "后台创建" }}</text>
@@ -67,10 +71,17 @@
</template>
<script setup lang="ts">
import { onMounted, ref } from "vue"
import { ref } from "vue"
import { onLoad } from "@dcloudio/uni-app"
import { invitationApi } from "@/sheep/api"
const alertList = {
1: { color: "#f5a623", text: "访客未接受邀约" },
2: { color: "#2db7f5", text: "访客待到访" },
3: { color: "#52c41a", text: "访客拒绝了邀约" },
5: { color: "#f5222d", text: "访客取消了邀约" },
}
const detail = ref<any>({})
const visitorReasonList = ref<{ title: string; id: string }[]>([])
@@ -78,19 +89,17 @@ onLoad(async (options: any) => {
const id = options.id
try {
uni.showLoading({ title: "加载中..." })
const { code, data, msg } = await invitationApi.getInvitationDetail(id)
if (code == 0) {
detail.value = data
return
}
uni.showToast({ title: msg || "获取详情失败", icon: "none" })
if (code != 0) return uni.showToast({ title: msg || "获取详情失败", icon: "none" })
detail.value = data
} catch (error: any) {
uni.showToast({ title: error.message, icon: "none" })
} finally {
uni.hideLoading()
}
})
onMounted(() => {
getVisitorReasonList()
await getVisitorReasonList()
})
// 获取拜访原因列表
+68 -31
View File
@@ -19,16 +19,26 @@
<span>拜访开始时间 </span>
<tm-icon name="arrow-right-s-line" />
</template>
<tm-input :modelValue="form.vStartDate" placeholder="请选择拜访开始时间" style="pointer-events: none"
disabled color="transparent" />
<tm-input
:modelValue="form.vStartDate"
placeholder="请选择拜访开始时间"
style="pointer-events: none"
disabled
color="transparent"
/>
</tm-form-item>
<tm-form-item name="vEndDate" label="拜访离开时间 >" @click="endDatePicker('vEndDate')">
<template #label>
<span>拜访离开时间 </span>
<tm-icon name="arrow-right-s-line" />
</template>
<tm-input :modelValue="form.vEndDate" placeholder="请选择拜访离开时间" style="pointer-events: none" disabled
color="transparent" />
<tm-input
:modelValue="form.vEndDate"
placeholder="请选择拜访离开时间"
style="pointer-events: none"
disabled
color="transparent"
/>
</tm-form-item>
<!-- <tm-form-item name="deptId" label="拜访部门">
@@ -40,7 +50,7 @@
</template>
</tm-input>
</template>
<tm-text color="#999999">精致美观的对话框,可全局配置风格</tm-text>
<tm-text color="#999999"></tm-text>
</tm-drawer>
</tm-form-item> -->
@@ -64,14 +74,36 @@
</tm-form>
</tm-sheet>
<tm-drawer title="请选择时间" :showClose="true" :showFooter="false" size="auto" placement="bottom"
v-model:show="showDatePicker" :duration="100" zIndex="100">
<tm-drawer
title="请选择时间"
:showClose="true"
:showFooter="false"
size="auto"
placement="bottom"
v-model:show="showDatePicker"
:duration="100"
zIndex="100"
>
<time-range-picker @confirm="onDatePickerConfirm" @cancel="showDatePicker = false" />
</tm-drawer>
<tm-modal v-model:show="modalShow" :overlayClick="false" title="提示" position="bottom" height="auto"
:showCancel="true" cancelText="取消" confirmText="确定" @confirm="confirmSubmit" @cancel="modalShow = false">
<view class="text-center"><tm-text font-size="30" color="#999999">确认提交吗?</tm-text></view>
<tm-modal
v-model:show="confirmModalShow"
:overlayClick="false"
title="确定提交吗?"
position="bottom"
height="auto"
:showCancel="true"
cancelText="取消"
confirmText="确定"
@confirm="confirmSubmit"
@cancel="confirmModalShow = false"
>
<view class="text-center">
<tm-text font-size="30" color="#999999">提交后系统将会向手机号</tm-text>
<tm-text font-size="30" color="#0779FD">{{ form.mobile || "" }}</tm-text>
<tm-text font-size="30" color="#999999">发送邀约短信</tm-text>
</view>
</tm-modal>
<template #main-bottom>
@@ -92,9 +124,17 @@
<script setup lang="ts">
import { reactive, ref } from "vue"
import { invitationApi } from "@/sheep/api/index"
import TimeRangePicker from "@/sheep/components/TimePointPicker.vue"
import TimeRangePicker from "@/sheep/components/time-range-picker.vue"
const form = reactive<any>({
interface FormData {
mobile: string
vStartDate: string
vEndDate: string
isOtherPeople: boolean | string
isDrive: boolean | string
}
const form = reactive<FormData>({
// name: "",
mobile: "",
// companyName: "",
@@ -106,8 +146,8 @@ const form = reactive<any>({
isDrive: true,
})
const showDatePicker = ref(false)
const curSelectedInputName = ref("")
const modalShow = ref(false)
const curDateType = ref("")
const confirmModalShow = ref(false)
// const visitorReasonList = ref<{ title: string; id: string }[]>([])
// onLoad(() => {
@@ -141,20 +181,20 @@ const rules: Record<string, TM.FORM_RULE[]> = {
}
// 开始日期选择
const startDatePicker = (key: string) => {
const startDatePicker = (dateType: string) => {
showDatePicker.value = true
curSelectedInputName.value = key
curDateType.value = dateType
}
// 离开日期选择
const endDatePicker = (key: string) => {
const endDatePicker = (dateType: string) => {
showDatePicker.value = true
curSelectedInputName.value = key
curDateType.value = dateType
}
// 日期选择器确认
const onDatePickerConfirm = (dateValue: any, timeValue: string) => {
form[curSelectedInputName.value] = `${dateValue.fullDate} ${timeValue}`
form[curDateType.value] = `${dateValue.fullDate} ${timeValue}`
showDatePicker.value = false
}
@@ -162,7 +202,7 @@ const onDatePickerConfirm = (dateValue: any, timeValue: string) => {
const onsubmit = (evt: TM.FORM_SUBMIT_RESULT) => {
// console.log("校验结果:", evt)
if (!evt.isPass) return
modalShow.value = true
confirmModalShow.value = true
}
// 确认提交
@@ -182,15 +222,12 @@ const confirmSubmit = async () => {
form.mobile = form.mobile.trim().replace(/\s/g, "")
try {
const { code, data, msg } = await invitationApi.saveInvitation(form)
if (code == 0) {
uni.showToast({ title: "提交成功", icon: "success" })
resetForm()
modalShow.value = false
uni.navigateTo({ url: "/pages/integrated/visitor/invitationRecord" })
return
}
uni.showToast({ title: msg || "提交失败", icon: "none" })
const { code, msg } = await invitationApi.saveInvitation(form)
if (code != 0) return uni.showToast({ title: msg || "提交失败", icon: "error" })
uni.showToast({ title: "提交成功", icon: "success" })
resetForm()
confirmModalShow.value = false
uni.navigateTo({ url: "/pages/integrated/visitor/invitationRecord" })
} catch (error: any) {
uni.showToast({ title: error.message || "提交失败", icon: "none" })
}
@@ -202,8 +239,8 @@ const resetForm = () => {
// name: "",
mobile: "",
// companyName: "",
vStartDate: "",
vEndDate: "",
vstartDate: "",
vendDate: "",
// reasonValue: "",
// reasonText: "",
isOtherPeople: true,
@@ -54,26 +54,21 @@
</template>
<view class="flex-col justify-center card p-3 m-b-20rpx" v-for="(v, i) in pageHook.list" :key="i">
<view class="flex justify-between items-center">
<view v-if="v.checkStatus == '1'" class="p-1 c-white! sub-text-26 rounded-1 bg-#f5a623">待接受</view>
<view v-if="v.checkStatus == '2'" class="p-1 c-white! sub-text-26 rounded-1 bg-#2db7f5">待到访</view>
<view v-if="v.checkStatus == '3'" class="p-1 c-white! sub-text-26 rounded-1 bg-#52c41a">已拒绝</view>
<view v-if="v.checkStatus == '5'" class="p-1 c-white! sub-text-26 rounded-1 bg-#f5222d">已取消</view>
<view v-if="v.checkStatus == '1'" class="p-1 c-white! sub-text-22 rounded-1 bg-#f5a623">待接受</view>
<view v-if="v.checkStatus == '2'" class="p-1 c-white! sub-text-22 rounded-1 bg-#2db7f5">待到访</view>
<view v-if="v.checkStatus == '3'" class="p-1 c-white! sub-text-22 rounded-1 bg-#52c41a">已拒绝</view>
<view v-if="v.checkStatus == '5'" class="p-1 c-white! sub-text-22 rounded-1 bg-#f5222d">已取消</view>
<view class="sub-text-26">{{ v.vstartDate + " ~ " + v.vendDate }}</view>
</view>
<view class="flex-col my-1 px-4 py-2 bg-#ECF4F9 rounded-4">
<view class="flex justify-start sub-text-30 whitespace-nowrap">
<view>{{ v.name }}</view>
<view class="second-text-28 ml-2">{{ v.mobile }}</view>
</view>
<view class="flex justify-center sub-text-28 font-italic whitespace-nowrap my-2">
<span v-if="v.reasonValue">拜访原因:{{ visitorReasonList.find((item) => item.id == v.reasonValue)?.title || "" }}</span>
</view>
<!-- <view class="flex justify-end second-text-28 whitespace-nowrap">
<span v-if="state.params.type == 1">接待人:{{ v.userName }}</span>
</view> -->
<view class="m-2 h-1rpx bg-#A0A0A044"></view>
<view class="flex justify-between sub-text-26 whitespace-nowrap">
<!-- <view>{{ v.name }}</view> -->
<view>访客手机号:{{ v.mobile }}</view>
<!-- <view v-if="v.reasonValue">拜访原因:{{ visitorReasonList.find((item) => item.id == v.reasonValue)?.title || "" }}</view> -->
<tm-button class="px-1" size="xs" @click.stop="goDetail(v)">查看详情</tm-button>
</view>
<view class="flex justify-end items-center gap-2">
<!-- <view v-if="v.checkStatus == 1" class="flex items-center gap-2">
<!-- <view class="flex justify-end items-center gap-2"> -->
<!-- <view v-if="v.checkStatus == 1" class="flex items-center gap-2">
<tm-modal title="确定审核通过吗?" height="auto" @confirm="visitorCheck(v.id, 2)">
<template v-slot:trigger><tm-button class="px-1" size="s">审核通过</tm-button></template>
</tm-modal>
@@ -81,8 +76,7 @@
<template v-slot:trigger><tm-button class="px-1" size="s" color="danger">审核拒绝</tm-button></template>
</tm-modal>
</view> -->
<tm-button v-if="v.checkStatus == '2'" class="px-1" size="s" color="success" @click.stop="goDetail(v)">查看详情</tm-button>
</view>
<!-- </view> -->
</view>
</z-paging>
@@ -102,7 +96,7 @@
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from "vue"
import { ref, reactive } from "vue"
import { onShow } from "@dcloudio/uni-app"
import { hooks, router } from "@@/index"
import zTabs from "@@/components/other/z-tabs/z-tabs.vue"
@@ -123,30 +117,12 @@ const state = reactive<any>({
},
})
const pageRef = ref<any>(null)
const visitorReasonList = ref<{ title: string; id: string }[]>([])
onShow(async () => {
const isLogin = await hooks.useCheckLogin()
if (!isLogin) return
if (pageRef.value) {
pageRef.value.reload(false)
}
})
onMounted(() => {
getVisitorReasonList()
})
// 获取拜访原因列表
const getVisitorReasonList = async () => {
const { code, data } = await invitationApi.getDictListByType("1")
if (code == 0 && data) {
visitorReasonList.value = data.map((item: any) => ({ title: item.label, id: item.value }))
return
}
visitorReasonList.value = []
}
const doTab = (e: any) => {
const target = tabs[e]
state.params.checkStatus = target.value
+1 -1
View File
@@ -46,7 +46,7 @@ import { filePath } from "@/sheep/utils/file"
import { displayPrice, storePrice } from "@/sheep/utils/formatMoney"
import { usePayStore } from "@/sheep/stores/pay"
import { isEmpty } from "radash"
import NumberKeyboard from "@/sheep/components/numberKeyboard.vue"
import NumberKeyboard from "@/sheep/components/number-keyboard.vue"
const loading = ref(false)
const scanPayState = reactive({
+1 -1
View File
@@ -68,7 +68,7 @@
<script setup lang="ts">
import { ref, computed, reactive } from "vue"
import { onLoad } from "@dcloudio/uni-app"
import NumberKeyboard from "@/sheep/components/numberKeyboard.vue"
import NumberKeyboard from "@/sheep/components/number-keyboard.vue"
import { payApi, walletApi } from "@/sheep/api"
import { hooks, router } from "@@/index"
import { filePath } from "@/sheep/utils/file"
+1 -1
View File
@@ -16,7 +16,7 @@ export default {
data,
}),
// 获取访客邀约列表
// 获取访客邀约记录列表
// type为1:主动申请 type为2:邀约 type为3:后台创建
getInvitationRecord: (params: { current: number; size: number; checkStatus?: string; type?: number }): Promise<any> =>
request({
@@ -36,7 +36,7 @@
</template>
<script setup lang="ts">
import { ref, reactive, watch, computed, onUnmounted } from "vue"
import { ref, reactive, watch, onUnmounted } from "vue"
import { userApi } from "@@/api"
const props = withDefaults(
@@ -1,5 +1,5 @@
import { h, render } from "vue"
import VerifyDeviceImpModel from "./verifyDeviceImpModel.vue"
import VerifyDeviceImpModel from "./verify-device-imp-model.vue"
let VerifyDeviceImpModelInstance: boolean | null = null