Browse Source

增加拜访时间的保存

tags/AL.0.8.0_20240113_base
yuan 1 year ago
parent
commit
edb796b294
10 changed files with 469 additions and 33 deletions
  1. +2
    -1
      src/app.config.ts
  2. +18
    -4
      src/components/contact-form/index.vue
  3. +47
    -11
      src/pages/contact-edit/index.vue
  4. +38
    -6
      src/pages/contact-new/index.vue
  5. +6
    -0
      src/pages/contact-send-invite-sms/index.config.ts
  6. +20
    -0
      src/pages/contact-send-invite-sms/index.scss
  7. +143
    -0
      src/pages/contact-send-invite-sms/index.vue
  8. +28
    -9
      src/stores/contact-item.ts
  9. +164
    -0
      src/stores/contact-visit-record.ts
  10. +3
    -2
      src/stores/contacts.ts

+ 2
- 1
src/app.config.ts View File

@@ -9,7 +9,8 @@ export default defineAppConfig({
'pages/login/index',
'pages/web-view/index',
'pages/contact-pass-records/index',
'pages/contact-edit-logs/index'
'pages/contact-edit-logs/index',
'pages/contact-send-invite-sms/index'
],
window: {
backgroundTextStyle: 'light',


+ 18
- 4
src/components/contact-form/index.vue View File

@@ -8,13 +8,27 @@ import { reactive, ref } from 'vue';
import {BjxHelper} from "../../utils";
import {useContactsStore} from "../../stores/contacts";
import {useContactItemStore} from "../../stores/contact-item";

const props = defineProps(['data'])
import {useContactVisitRecordStore} from "../../stores/contact-visit-record";

const contacts = useContactsStore()
const contact = useContactItemStore()
const contactVisitRecord = useContactVisitRecordStore()
contact.setNewAvatar("")

if (contact.contact.id) {
contactVisitRecord.getVisitRecord(contact.contact.id)
.then(contactVisitRecord => {
console.log("contactVisitRecord", contactVisitRecord)
if (contactVisitRecord) {
contact.contact.nextVisitDate = contactVisitRecord.visitDate
console.log(contactVisitRecord.visitDate)
console.log(contact.contact)
}
})
.catch(e => console.log(e))
}
console.log("id", contact.contact.id)

const onShowSuggestionsMenu = ref(false)

const state = reactive({
@@ -28,7 +42,7 @@ const openSwitch = (param) => {
};
const closeSwitch = (param) => {
state[`${param}`] = false;
};
}
const setChooseDate = (param) => {
contact.contact.nextVisitDate = param[3]
}
@@ -99,7 +113,7 @@ const onNickNameSelected = (value) => {
<!-- </view>-->

<nut-form-item label="电话">
<nut-input v-model="contact.contact.phone" class="nut-input-text" />
<nut-input v-model="contact.contact.phone" class="nut-input-text" type="number" />
</nut-form-item>
<nut-form-item label="公司">
<nut-input v-model="contact.contact.company" class="nut-input-text" />


+ 47
- 11
src/pages/contact-edit/index.vue View File

@@ -1,15 +1,18 @@
<script setup>
<script setup lang="ts">
import { Router } from 'tarojs-router-next'
import './index.scss'
import {useContactItemStore} from "../../stores/contact-item";
import { useContactsStore } from "../../stores/contacts";
import Taro from "@tarojs/taro";
import {ref} from "vue";
import {useContactVisitRecordStore} from "../../stores/contact-visit-record";


const contactData = Router.getData()
const contact = useContactItemStore()
const contacts = useContactsStore()
const contactVisitRecord = useContactVisitRecordStore()

contact.setContact(contactData)
const showDeleteConfirmMenu = ref(false)
const showBlockConfirmMenu = ref(false)
@@ -17,7 +20,7 @@ const showBlockConfirmMenu = ref(false)
const goBack = () => {
Router.back()
}
const onSaveClicked = () => {
const onSaveClicked = (isSmsSend: boolean) => {
Taro.showLoading({
title: 'loading',
})
@@ -26,8 +29,19 @@ const onSaveClicked = () => {
console.log(contact.contact)
contact.updateVisitor().then(r => {
contacts.loadContactsFromServer().then( contactsResult => {
Taro.hideLoading()
Router.back()
if (contact.contact.nextVisitDate !== "") {
contactVisitRecord.save(contact.contact.id, contact.contact.nextVisitDate).then( visitRecordResult => {
console.log("save contactVisitRecord DONE")
Taro.hideLoading()
if (isSmsSend) Router.toContactSendInviteSms()
else Router.back()
})
}
else {
Taro.hideLoading()
if (isSmsSend) Router.toContactSendInviteSms()
else Router.back()
}
})
}).catch(error => {
Taro.hideLoading()
@@ -107,6 +121,24 @@ const onDeleteConfirm = (item) => {
console.log("error", error)
})
}
const onSaveAndSendMessage = () => {
if (contactData.phone.length !== 11){
Taro.showToast({
title: '请正确填写手机号',
icon: 'none',
duration: 2000})
}
else if (contactData.isBlock) {
Taro.showToast({
title: '联系人被阻止',
icon: 'none',
duration: 2000})
}
else {
onSaveClicked(true)
}
console.log(contactData.id, contactData.nextVisitDate)
}

</script>

@@ -125,7 +157,7 @@ const onDeleteConfirm = (item) => {
<view class="text-black-50">更新来访联系人信息,并设置下次到访时间</view>
</view>
<view class="d-flex align-items-end">
<view class="text-primary save-button" hover-class="btn-hover-primary" @tap="onSaveClicked">保存</view>
<view class="text-primary save-button" hover-class="btn-hover-primary" @tap="onSaveClicked(false)">保存</view>
</view>
</view>

@@ -142,12 +174,16 @@ const onDeleteConfirm = (item) => {
</view>

<view hover-class="card-hover-gray">
<nut-cell title="编辑记录" sub-title="此联系人的信息修改记录" @tap="onClickEditLogs">
<template #desc>
<Text className="fas fa-chevron-right"/>
</template>
</nut-cell>
</view>
<nut-cell title="编辑记录" sub-title="此联系人的信息修改记录" @tap="onClickEditLogs">
<template #desc>
<Text className="fas fa-chevron-right"/>
</template>
</nut-cell>
</view>

<view class="p-3">
<nut-button :disabled="contactData.phone.length !== 11 || contactData.isBlock" block type="info" @tap="onSaveAndSendMessage">保存并发送邀约短信</nut-button>
</view>

<view class="p-3">
<nut-button v-if="contactData.isBlock" block color="red" plain @tap="onBlockConfirm">取消阻止此联系人</nut-button>


+ 38
- 6
src/pages/contact-new/index.vue View File

@@ -1,9 +1,10 @@
<script setup>
<script setup lang="ts">
import { Router } from 'tarojs-router-next'
import './index.scss'
import {useContactItemStore} from "../../stores/contact-item";
import {useContactsStore} from "../../stores/contacts";
import Taro from "@tarojs/taro";
import {useContactVisitRecordStore} from "../../stores/contact-visit-record";

const goBack = () => {
Router.back()
@@ -13,8 +14,10 @@ const contact = useContactItemStore()
contact.setContact(contact.getEmptyContactData())

const contacts = useContactsStore()
const contactVisitRecord = useContactVisitRecordStore()

const onSaveClicked = () => {

const onSaveClicked = (isSmsSend: boolean) => {
Taro.showLoading({
title: 'loading',
})
@@ -23,8 +26,19 @@ const onSaveClicked = () => {
console.log(contact.contact)
contact.createVisitor().then(r => {
contacts.loadContactsFromServer().then( contactsResult => {
Taro.hideLoading()
Router.back()
if (contact.contact.nextVisitDate !== "") {
contactVisitRecord.save(contact.contact.id, contact.contact.nextVisitDate).then( visitRecordResult => {
console.log("save contactVisitRecord DONE")
Taro.hideLoading()
if (isSmsSend) Router.toContactSendInviteSms()
else Router.back()
})
}
else {
Taro.hideLoading()
if (isSmsSend) Router.toContactSendInviteSms()
else Router.back()
}
})
}).catch(error => {
Taro.hideLoading()
@@ -37,6 +51,19 @@ const onSaveClicked = () => {
})
}

const onSaveAndSendMessage = () => {
if (contact.contact.phone.length !== 11){
Taro.showToast({
title: '请正确填写手机号',
icon: 'none',
duration: 2000})
}
else {
onSaveClicked(true)
}
console.log(contact.contact.id, contact.contact.nextVisitDate)
}

</script>

<template>
@@ -53,15 +80,20 @@ const onSaveClicked = () => {
<view class="text-black-50">新建来访联系人,并设置到访时间</view>
</view>
<view class="d-flex align-items-end">
<view class="text-primary save-button" hover-class="btn-hover-primary" @tap="onSaveClicked">保存</view>
<view class="text-primary save-button" hover-class="btn-hover-primary" @tap="onSaveClicked(false)">保存</view>
</view>
</view>


<view class="scroll pb-5">
<view class="scroll pb-2">
<ContactForm/>
</view>

<view class="p-3 pb-5">
<nut-button :disabled="contact.contact.phone.length !== 11 || contact.contact.isBlock" block type="info" @tap="onSaveAndSendMessage">保存并发送邀约短信</nut-button>
</view>



</view>



+ 6
- 0
src/pages/contact-send-invite-sms/index.config.ts View File

@@ -0,0 +1,6 @@
export default definePageConfig({
navigationBarTitleText: '',
usingComponents: {},
navigationStyle: 'custom',
disableScroll: true
})

+ 20
- 0
src/pages/contact-send-invite-sms/index.scss View File

@@ -0,0 +1,20 @@
page {
height: 100%;
}

.nut-navbar {
background: transparent;
}

.scroll {
flex: 1;
overflow: scroll;
}

.save-button {
font-size: 36px
}

.nut-action-sheet__item {
color: red !important;
}

+ 143
- 0
src/pages/contact-send-invite-sms/index.vue View File

@@ -0,0 +1,143 @@
<script setup lang="ts">
import { reactive } from 'vue'
import { View } from '@tarojs/components'

import './index.scss'
import {weappAuth} from "../../utils";
import {
GroupedContactPassRecords,
useContactPassRecordsStore
} from "../../stores/contact-pass-records";
import {Router} from "tarojs-router-next";
import { BjxHelper } from "../../utils";
import {ContactEditLog, useContactEditLogsStore} from "../../stores/contact-edit-logs";


const contactData = Router.getData()
console.log("contactData", contactData)

const state = reactive<{
isPageDataLoading: boolean,
isAuthError: boolean,
contactEditLogs: ContactEditLog[],
}>({
isPageDataLoading: true,
isAuthError: false,
contactEditLogs: [],
})
const editLogs = useContactEditLogsStore()

init()

function init() {
state.isAuthError = false
state.isPageDataLoading = true
console.log("contactData", contactData)
weappAuth().then(r => {
console.log(r)
editLogs.loadContactEditLogsFromServer(contactData.id).then( editLogs => {
state.isPageDataLoading = false
state.contactEditLogs = editLogs
// console.log(state.groupedPassRecords)
})
.catch(error => {
console.log("error", error)
state.isAuthError = true
state.isPageDataLoading = false
})
}).catch(e => {
console.log("error", e)
state.isAuthError = true
state.isPageDataLoading = false
})
}

const onAuthErrorRefresh = () => {
init()
}
// const onPullDownRefresh = () => {
// console.log("onPullDownRefresh")
// state.isRefresherTriggered = false
// }
function onPullDownRefresh (e) {
console.log("onPullDownRefresh", e)
// state.isRefresherTriggered = false
}
const goBack = () => {
Router.back(undefined, { delta: 2 })
}

</script>





<template>
<view class="h-100 d-flex flex-column">
<BackgroundBasic/>
<NutNavbar title=""></NutNavbar>
<view class="p-3 d-flex">
<view class="flex-grow-1">
<view class="h3">
<view class="fas fa-chevron-left text-primary" @tap="goBack()" hover-class="btn-hover-primary"/>
发送短信
</view>
<view class="text-black-50">此联系人的最近编辑记录</view>
</view>
<view class="d-flex align-items-end">
<View></View>
</view>
</view>

<View v-if="state.isAuthError">
<nut-empty description="连接出现问题,请稍后重试">
<div style="margin-top: 10px">
<nut-button type="default" @tap="onAuthErrorRefresh">刷新</nut-button>
</div>
</nut-empty>
</View>
<View class="scroll 100vh" v-else>
<view class="scroll 100vh" v-if="!state.isPageDataLoading">
</view>
<View v-else class="skeleton">
<NutSkeleton v-for="_ in 10" class="pl-4 pt-4 pb-4 pr-5" height="20px" width="60vw" animated avatar avatar-size="50px" row="2"/>
</View>
</View>
</view>




<!-- <view class="p-4">-->
<!-- <button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">使用电话号码登录</button>-->
<!-- </view>-->


<!-- <Counter/>-->


<!-- <nut-cell title="展示弹出层" is-link @click="show = true"></nut-cell>-->
<!-- <nut-popup :style="{ padding: '30px 50px' }" v-model:visible="show">正文</nut-popup>-->
<!-- <View><Text>{{state.msg}}</Text></View>-->
<!-- <nut-button type="primary" @click="handleClick(state.msg2)">点我</nut-button>-->
<!-- <Add color="red" />-->
<!-- <div class="alert alert-primary" role="alert">-->
<!-- A simple primary alert—check it out!-->
<!-- </div>-->
<!-- <h1>Example heading <span class="badge bg-secondary">New</span></h1>-->
<!-- <button type="button" class="btn btn-primary">-->
<!-- Notifications <span class="badge text-bg-secondary">4</span>-->
<!-- </button>-->
<!-- <button type="button" class="btn btn-primary position-relative">-->
<!-- Inbox-->
<!-- <span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">-->
<!-- 99+-->
<!-- <span class="visually-hidden">unread messages</span>-->
<!-- </span>-->
<!-- </button>-->

<!-- </view>-->
</template>



+ 28
- 9
src/stores/contact-item.ts View File

@@ -15,6 +15,9 @@ export const useContactItemStore = defineStore('contact-item', () => {
contact.value = contactItem
console.log("setContact", contact.value)
}
function setContactNextVisitDate(nextVisitDate: string) {
contact.value.nextVisitDate = nextVisitDate
}
function setNewAvatar(avatar: string) {
contactNewAvatar.value = avatar
}
@@ -30,8 +33,8 @@ export const useContactItemStore = defineStore('contact-item', () => {
avatar: "",
phone: "",
company: "",
nextVisitDate: undefined,
firstCharPinyin: ""
nextVisitDate: "",
firstCharPinyin: "",
}
}

@@ -45,7 +48,9 @@ export const useContactItemStore = defineStore('contact-item', () => {
isVip: $isVIP,
flexVisit: $flexVisit,
resourceId: $resourceId
} )
} ) {
id
}
}
`

@@ -60,7 +65,9 @@ export const useContactItemStore = defineStore('contact-item', () => {
isVip: $isVIP,
flexVisit: $flexVisit,
resourceId: $resourceId
} )
} ) {
id
}
}
`

@@ -95,7 +102,10 @@ export const useContactItemStore = defineStore('contact-item', () => {
console.log(r)
const resourceId = r.data.resourceId
GQLRequest.query(CREATE_VISITOR, { staffId, name, nickName, phone, company, isVIP, flexVisit, resourceId })
.then(r=> resolve(r))
.then(r=> {
contact.value.id = r.data.createVisitor.id
resolve(r)
})
.catch(e=> reject(e))
}).catch(e => {
reject(e.msg)
@@ -103,7 +113,10 @@ export const useContactItemStore = defineStore('contact-item', () => {
}
else {
GQLRequest.query(CREATE_VISITOR, { staffId, name, nickName, phone, company, isVIP, flexVisit })
.then(r=> resolve(r))
.then(r=> {
contact.value.id = r.data.createVisitor.id
resolve(r)
})
.catch(e=> reject(e))
}
})
@@ -127,7 +140,10 @@ export const useContactItemStore = defineStore('contact-item', () => {
console.log(r)
const resourceId = r.data.resourceId
GQLRequest.query(UPDATE_VISITOR, {staffId, id, name, nickName, phone, company, isVIP, flexVisit, resourceId })
.then(r=> resolve(r))
.then(r=> {
// contact.value.id = r.data.updateVisitor.id
resolve(r)
})
.catch(e=> reject(e))
}).catch(e => {
reject(e.msg)
@@ -135,7 +151,10 @@ export const useContactItemStore = defineStore('contact-item', () => {
}
else {
GQLRequest.query(UPDATE_VISITOR, {staffId, id, name, nickName, phone, company, isVIP, flexVisit })
.then(r=> resolve(r))
.then(r=> {
// contact.value.id = r.data.updateVisitor.id
resolve(r)
})
.catch(e=> reject(e))
}
})
@@ -178,5 +197,5 @@ export const useContactItemStore = defineStore('contact-item', () => {
}


return { contact, setContact, createVisitor, updateVisitor, deleteVisitor, getEmptyContactData, setNewAvatar, setBlockStatus }
return { contact, setContact, createVisitor, updateVisitor, deleteVisitor, getEmptyContactData, setNewAvatar, setBlockStatus, setContactNextVisitDate }
})

+ 164
- 0
src/stores/contact-visit-record.ts View File

@@ -0,0 +1,164 @@
// https://pinia.esm.dev/introduction.html
import { defineStore } from 'pinia'
import {GQLRequest, PinyinHelper, Session} from "../utils";
import {gql} from "graphql-tag";
import {ContactData} from "./contacts";
import {ref, Ref, UnwrapRef} from "vue";
import Taro from "@tarojs/taro";
import dayjs from "dayjs";

export interface ContactVisitRecord {
id: number
visitorId: number
userId: number
receiverName?: string
receiverPhone?: string
recordStatus?: number
visitDate: string
visitCode?: string
}

export const useContactVisitRecordStore = defineStore('contact-visit-record', () => {

const visitRecord: Ref<UnwrapRef<ContactVisitRecord|null>> = ref(null)

function reset() {
visitRecord.value = null
}
function setContact(contactItem: ContactData) {
contact.value = contactItem
console.log("setContact", contact.value)
}
function setNewAvatar(avatar: string) {
contactNewAvatar.value = avatar
}

const GET_VISIT_RECORD = gql`
query ($visitorId: ID, $limit: Int ) {
visitRecords(visitorId: $visitorId, limit: $limit) {
id
visitorId
userId
visitDate
visitorCode
}
}
`

const CREATE_VISIT_RECORD = gql`
mutation CreateVisitRecord($staffId: ID!, $visitorId: ID!, $visitDate: Date!) {
createVisitRecord( staffId: $staffId, input: {
visitorId: $visitorId,
visitDate: $visitDate,
} ) {
id
visitorId
userId
visitDate
visitorCode
}
}
`

const UPDATE_VISIT_RECORD = gql`
mutation UpdateVisitRecord($staffId: ID!, $visitRecordId: ID!, $visitorId: ID!, $visitDate: Date!) {
updateVisitRecord( staffId: $staffId, input: {
id: $visitRecordId,
visitorId: $visitorId,
visitDate: $visitDate,
} ) {
id
visitorId
userId
visitDate
visitorCode
}
}
`

function getVisitRecord(visitorId: string) {
reset()
const limit = 1
return new Promise((resolve, reject) => {
GQLRequest.query(GET_VISIT_RECORD, { visitorId, limit })
.then(result=> {
if (result.code == 500) {
reject("Network Error")
} else {
console.log("result", result)
if (result.data.visitRecords.length > 0) {
const item = result.data.visitRecords[0]
createData(item)
}
resolve(visitRecord.value)
}
})
.catch(e => {
reject()
})
})
}

function createData(item: any) {
const todayString = dayjs().format("YYYY-MM-DD")
const dateDiff = dayjs(todayString + " 00:00:00").diff(dayjs(item.visitDate, "YYYY-MM-DD"))
if (dateDiff <= 0) {
visitRecord.value = {
id: item.id,
visitorId: item.visitorId,
userId: item.userId,
receiverName: undefined,
receiverPhone: undefined,
recordStatus: undefined,
visitDate: item.visitDate,
visitCode: undefined,
} as ContactVisitRecord
}
}

function save(visitorId: string, date: string) {
return new Promise((resolve, reject) => {
if (visitRecord.value) {

updateVisitRecord(visitRecord.value.id, visitorId, date).then(r => resolve(r))
.catch(e => reject(e))
}
else {
createVisitRecord(visitorId, date).then(r => resolve(r))
.catch(e => reject(e))
}
})
}

function createVisitRecord(visitorId: string, visitDate: string) {
const staffId = Session.get("staff").id
return new Promise((resolve, reject) => {
GQLRequest.query(CREATE_VISIT_RECORD, { staffId, visitorId, visitDate })
.then(r=> {
if (r.code == 500) reject("Network Error")
else {
console.log(r)
createData(r.data.createVisitRecord)
resolve(r)
}
})
.catch(e=> reject(e))
})

}

function updateVisitRecord(visitRecordId: string, visitorId: string, visitDate: string) {
const staffId = Session.get("staff").id
return new Promise((resolve, reject) => {
GQLRequest.query(UPDATE_VISIT_RECORD, { staffId, visitRecordId, visitorId, visitDate })
.then(r=> {
if (r.code == 500) reject("Network Error")
else resolve(r)
})
.catch(e=> reject(e))
})

}

return { getVisitRecord , save }
})

+ 3
- 2
src/stores/contacts.ts View File

@@ -16,7 +16,7 @@ export interface ContactData {
avatar: string
phone: string
company: string
nextVisitDate?: string
nextVisitDate: string
firstCharPinyin: string
}

@@ -63,7 +63,8 @@ export const useContactsStore = defineStore('contacts', () => {
flexVisit: item.flexVisit,
isBlock: item.isBlock,
isVIP: item.isVip,
firstCharPinyin: PinyinHelper.getPinyinGroupName(item.name)
firstCharPinyin: PinyinHelper.getPinyinGroupName(item.name),
nextVisitDate: ""
} as ContactData)
}
allContacts.value = items.sort((a, b) => a.firstCharPinyin.localeCompare(b.firstCharPinyin));


Loading…
Cancel
Save