panhui %!s(int64=2) %!d(string=hai) anos
pai
achega
9b88db07cc
Modificáronse 4 ficheiros con 237 adicións e 57 borrados
  1. 17 0
      src/api/index.ts
  2. 153 52
      src/components/common/InfoForm.vue
  3. 50 3
      src/views/chat/Chat.vue
  4. 17 2
      src/views/page/InfoView.vue

+ 17 - 0
src/api/index.ts

@@ -211,3 +211,20 @@ export function fetchGetCompany<T>() {
         url: '/org/'
     })
 }
+
+export function fetchGetUserFileds<T>(userId: any, orgId: any) {
+    return get<T>({
+        url: '/form/getUserFields',
+        data: {
+            userId,
+            orgId
+        }
+    })
+}
+
+export function fetchUserFileds<T>(datas: any) {
+    return post<T>({
+        url: '/form/userFileds',
+        data: datas
+    })
+}

+ 153 - 52
src/components/common/InfoForm.vue

@@ -1,24 +1,57 @@
 <template>
     <div class="p-5">
-        <n-form ref="loginForm" :model="form" :rules="rules">
-            <n-form-item ref="phoneRef" path="phone" label="姓名">
-                <n-input v-model:value="form.phone" placeholder="请输入手机号" :allow-input="onlyAllowNumber">
+        <n-form ref="formRef" :model="form" :rules="rules">
+            <n-form-item
+                v-for="(item, index) in fileds"
+                :key="index"
+                :path="'field_' + (index + 1)"
+                :label="index + 1 + '.' + item.name"
+            >
+                <n-input
+                    v-if="item.formType === 'singleLineText'"
+                    v-model:value="form[String(`field_${index + 1}`)]"
+                    :placeholder="item.placeholder || '请输入...'"
+                    :allow-input="onlyAllowNumber"
+                >
                 </n-input>
+
+                <n-radio-group
+                    v-else-if="item.formType === 'radio'"
+                    v-model:value="form[String(`field_${index + 1}`)]"
+                    :name="`field_${index + 1}`"
+                >
+                    <n-space>
+                        <n-radio v-for="(option, optionIndex) in item.options" :key="optionIndex" :value="option.value">
+                            {{ option.label }}
+                        </n-radio>
+                    </n-space>
+                </n-radio-group>
+
+                <n-checkbox-group
+                    v-else-if="item.formType === 'checkbox'"
+                    v-model:value="form[String(`field_${index + 1}`)]"
+                >
+                    <n-space item-style="display: flex;">
+                        <n-checkbox
+                            v-for="(option, optionIndex) in item.options"
+                            :key="optionIndex"
+                            :value="option.value"
+                            :label="option.label"
+                        />
+                    </n-space>
+                </n-checkbox-group>
             </n-form-item>
-            <n-form-item path="code" label="验证码" class="w-100">
-                <div class="flex flex-1">
-                    <n-input
-                        class="flex-1"
-                        v-model:value="form.code"
-                        placeholder="请输入验证码"
-                        :allow-input="onlyAllowNumber"
-                    >
-                    </n-input>
-                </div>
-            </n-form-item>
-            <div class="mt-3">
-                <n-button class="h-10" @click="submit" block type="primary" size="large" :loading="loading" circle>
-                    登录
+            <div class="mt-3 flex justify-center">
+                <n-button
+                    class="h-10 max-w-[320px] mx-auto"
+                    @click="submit"
+                    block
+                    type="primary"
+                    size="large"
+                    :loading="loading"
+                    circle
+                >
+                    确认
                 </n-button>
             </div>
         </n-form>
@@ -26,46 +59,114 @@
 </template>
 
 <script setup lang="ts">
-import { NForm, NFormItem, NInput, NButton } from 'naive-ui'
-import { ref } from 'vue'
+import {
+    NForm,
+    NFormItem,
+    NInput,
+    FormInst,
+    NButton,
+    NRadioGroup,
+    NSpace,
+    NRadio,
+    NCheckboxGroup,
+    NCheckbox,
+    useMessage
+} from 'naive-ui'
+import { ref, computed, Ref } from 'vue'
+import { fetchGetUserFileds, fetchUserFileds } from '@/api'
+import { useUserStore, useCompanyStore } from '@/store'
+import { emitter } from '@/plugins'
+import { refDebounced } from '@vueuse/core'
+import { AnyARecord } from 'dns'
 
-const form = ref({
-    phone: '',
-    code: '',
-    invitor: ''
+const rules = ref({})
+const onlyAllowNumber = (value: string) => !value || /^\d+$/.test(value)
+
+const loading = ref(false)
+
+const userStore = useUserStore()
+const companyStore = useCompanyStore()
+const userInfo = computed(() => {
+    return userStore.userInfo
 })
-const rules = {
-    phone: [
-        {
-            validator(rule: any, value: any) {
-                if (!value) {
-                    return new Error('请输入手机号')
-                } else if (!/^1[3-9]\d{9}$/.test(value)) {
-                    return new Error('手机号格式错误')
-                }
 
-                return true
-            },
-            trigger: ['submit']
-        }
-    ],
-    code: [
-        {
-            validator(rule: any, value: any) {
-                if (!value) {
-                    return new Error('请输入验证码')
-                } else if (!/^\d{4}$/.test(value)) {
-                    return new Error('验证码格式错误')
+const company = computed(() => {
+    return companyStore.company
+})
+
+const fileds = ref(<any>[])
+
+type stringkey = Record<any, any>
+
+const form = ref(<stringkey>{})
+const unitForm = ref(<any>{})
+fetchGetUserFileds(userInfo.value.id, company.value.id).then((res: any) => {
+    if (res.code === 0) {
+        emitter.emit('updateInfoTitle', res.form.name)
+        unitForm.value = res.form
+        fileds.value = res.fileds.map((item: any) => {
+            if (
+                item.formType === 'radio' ||
+                item.formType === 'select' ||
+                item.formType === 'multiSelect' ||
+                item.formType === 'checkbox'
+            ) {
+                return {
+                    ...item,
+                    options: JSON.parse(item.optionsValue)
                 }
+            }
+            return item
+        })
+
+        let _form = <stringkey>{}
+        let _rules = <stringkey>{}
+        res.fileds.forEach((item: any, index: any) => {
+            let _name = String(`field_${index + 1}`)
+            _form[_name] = ''
+            if (item.required) {
+                _rules[_name] = [
+                    {
+                        required: true,
+                        message: '请输入',
+                        trigger: 'blur'
+                    }
+                ]
+            }
+        })
+        rules.value = _rules
+        form.value = _form
+    }
+})
+
+const formRef: Ref<FormInst | null> = ref(null)
 
-                return true
-            },
-            trigger: ['submit']
+const message = useMessage()
+function submit() {
+    console.log('验证')
+    formRef.value?.validate((errors: any) => {
+        if (!errors) {
+            console.log(form.value)
+
+            let datas = []
+            datas = fileds.value.map((item: any, index: number) => {
+                return {
+                    userId: userInfo.value.id,
+                    formId: unitForm.value.id,
+                    filedId: item.id,
+                    value:
+                        item.formType === 'multiSelect' || item.formType === 'checkbox'
+                            ? form.value[`field_${index + 1}`].join(',')
+                            : form.value[`field_${index + 1}`]
+                }
+            })
+            fetchUserFileds(datas).then(res => {
+                message.success('填写成功')
+                emitter.emit('backChat')
+            })
+        } else {
+            console.log(errors)
         }
-    ]
+    })
 }
-const onlyAllowNumber = (value: string) => !value || /^\d+$/.test(value)
-
-const loading = ref(false)
-function submit() {}
 </script>

+ 50 - 3
src/views/chat/Chat.vue

@@ -11,10 +11,18 @@ import { useChat } from './hooks/useChat'
 import { useCopyCode } from './hooks/useCopyCode'
 import { useUsingContext } from './hooks/useUsingContext'
 import HeaderComponent from './components/Header/index.vue'
-import { HoverButton, SvgIcon, MinePannel, VipPannel, MaskPannel, Share } from '@/components/common'
+import { HoverButton, SvgIcon, MinePannel, InfoForm, VipPannel, MaskPannel, Share } from '@/components/common'
 import { useBasicLayout } from '@/hooks/useBasicLayout'
-import { useChatStore, useAppStore, usePromptStore, useAuthStore, useUserMemberStore, useCompanyStore } from '@/store'
-import { fetchChatAPIProcess } from '@/api'
+import {
+    useChatStore,
+    useAppStore,
+    usePromptStore,
+    useAuthStore,
+    useUserMemberStore,
+    useCompanyStore,
+    useUserStore
+} from '@/store'
+import { fetchChatAPIProcess, fetchGetUserFileds } from '@/api'
 import { t } from '@/locales'
 import { useTheme } from '@/hooks/useTheme'
 import { emitter } from '@/plugins'
@@ -471,6 +479,11 @@ watch(isMobile, val => {
     // showVip.value = false
 })
 
+const userStore = useUserStore()
+const userInfo = computed(() => {
+    return userStore.userInfo
+})
+const showInfo = ref(false)
 onMounted(() => {
     emitter.on('changeMineShow', res => {
         console.log(res)
@@ -494,6 +507,32 @@ onMounted(() => {
     emitter.on('changeShare', res => {
         showShareModal.value = true
     })
+    emitter.on('backChat', res => {
+        showInfo.value = false
+    })
+    fetchGetUserFileds(userInfo.value.id, company.value.id).then((res: any) => {
+        if (res.code === 0) {
+            dialog.create({
+                title: `《${res.form.name}》需要您的帮助`,
+                content: '是否立即填写?',
+                positiveText: '立即填写',
+                negativeText: '不填写',
+                iconPlacement: 'top',
+                showIcon: false,
+                closable: false,
+                onPositiveClick: () => {
+                    if (isMobile.value) {
+                        router.push({
+                            name: 'info'
+                        })
+                    } else {
+                        showInfo.value = true
+                    }
+                },
+                onNegativeClick: () => {}
+            })
+        }
+    })
 })
 const showMask = ref(false)
 
@@ -629,6 +668,14 @@ const company = computed(() => {
             </n-card>
         </n-modal>
 
+        <n-modal v-model:show="showInfo" transform-origin="center">
+            <n-card :bordered="false" class="!max-w-xl !rounded-xl" content-style="padding:0">
+                <div class="pt-3 rounded-xl">
+                    <info-form></info-form>
+                </div>
+            </n-card>
+        </n-modal>
+
         <n-modal v-model:show="showMask" transform-origin="center">
             <n-card :bordered="false" class="!max-w-md !rounded-xl" content-style="padding:0">
                 <div class="!rounded-xl">

+ 17 - 2
src/views/page/InfoView.vue

@@ -1,6 +1,6 @@
 <template>
     <div class="page h-full flex flex-col">
-        <n-page-header title="获取信息" @back="handleBack">
+        <n-page-header :title="pageTitle" @back="handleBack">
             <template #extra>
                 <div class="w-[22px]"></div>
             </template>
@@ -10,14 +10,29 @@
 </template>
 
 <script setup lang="ts">
-import {InfoForm} from '@/components/common'
+import { InfoForm } from '@/components/common'
 import { NPageHeader } from 'naive-ui'
 import { useRouter } from 'vue-router'
+import { emitter } from '@/plugins'
+import { onMounted, ref } from 'vue'
 
 const router = useRouter()
 function handleBack() {
     router.back()
 }
+
+const pageTitle = ref('调查表单')
+
+onMounted(() => {
+    emitter.on('updateInfoTitle', title => {
+        if (title) {
+            pageTitle.value = String(title)
+        }
+    })
+    emitter.on('backChat', res => {
+        router.back()
+    })
+})
 </script>
 
 <style lang="less" scoped>