Browse Source

表单组件

lifanagju_citu 1 year ago
parent
commit
e1af91df27

+ 1 - 0
components.d.ts

@@ -28,6 +28,7 @@ declare module 'vue' {
     Item: typeof import('./src/components/Position/item.vue')['default']
     JobTypeCard: typeof import('./src/components/jobTypeCard/index.vue')['default']
     Positions: typeof import('./src/components/Enterprise/components/positions.vue')['default']
+    RadioGroup: typeof import('./src/components/FormUI/radioGroup/index.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']
     SimilarPositions: typeof import('./src/components/Position/similarPositions.vue')['default']

+ 8 - 1
src/components/CtForm/index.vue

@@ -9,7 +9,7 @@
               <div :class="item.class" :style="item.slotTitleStyle">{{ item.slotTitle }}</div>
             </template>
             <div class="d-flex" :class="item.flexStyle || 'flex-row'">
-              <span>{{ item.value }}</span>
+              <!-- <span>{{ item.value }}</span> -->
               <textUI
                 v-if="['text', 'password', 'number'].includes(item.type)"
                 v-model="item.value"
@@ -22,6 +22,12 @@
                 :item="item"
                 @change="handleChange(item)"
               ></autocompleteUI>
+              <radioGroupUI
+                v-if="item.type === 'ifRadio'"
+                v-model="item.value"
+                :item="item"
+                @change="handleChange(item)"
+              ></radioGroupUI>
               <template v-if="item.slotName">
                 <slot :name="item.slotName" :item="item"></slot>
               </template>
@@ -37,6 +43,7 @@
 defineOptions({ name:'components-ct-form'})
 import textUI from './../FormUI/TextInput'
 import autocompleteUI from './../FormUI/autocomplete'
+import radioGroupUI from './../FormUI/radioGroup'
 import { ref, defineEmits } from 'vue'
 const emit = defineEmits(['change', 'inputUpdateAutocomplete'])// 定义一个或多个自定义事件
 const props = defineProps({items: Object})

+ 9 - 9
src/components/FormUI/TextInput/index.vue

@@ -23,23 +23,23 @@
       :prepend-inner-icon="item.prependInnerIcon"
       hide-spin-buttons
       @wheel="$event => handleWheel($event, item)"
-      @keyup.enter="item.keyupEnterNative && item.keyupEnterNative(index)"
-      @click="item.click && item.click(index)"
-      @click:append-inner="item.clickAppendInner"
+      @update:modelValue="modelValueUpDate"
     ></v-text-field>
   </div>
 </template>
 <script setup>
-import { computed, defineEmits } from 'vue';
+import { defineEmits, ref } from 'vue';
 defineOptions({ name:'FormUI-v-text-field'})
 
 const props = defineProps({item: Object, modelValue: [String, Number]})
-const emit = defineEmits(['update:modelValue'])
+const emit = defineEmits(['update:modelValue', 'change'])
 const item = props.item
-const value = computed({
-  get() { return props.modelValue },
-  set(value) { emit('update:modelValue', value) }
-})
+const value = ref(props.modelValue)
+const modelValueUpDate = (val) => {
+  value.value = val
+  emit('update:modelValue', value.value)
+  emit('change', value.value)
+}
 const handleWheel = (event, item) => {
   if (item.type !== 'number') return
   event.preventDefault()

+ 9 - 6
src/components/FormUI/autocomplete/index.vue

@@ -20,20 +20,23 @@
       :hide-no-data="item.hideNoData"
       :no-data-text="item.noDataText || 'No data available'"
       :hide-selected="item.hideSelected"
+      @update:modelValue="modelValueUpDate"
     ></v-autocomplete>
   </div>
 </template>
 <script setup>
-import { computed, defineEmits } from 'vue';
+import { ref, defineEmits } from 'vue';
 defineOptions({ name:'FormUI-v-autocomplete'})
 
 const props = defineProps({item: Object, modelValue: [String, Number]})
-const emit = defineEmits(['update:modelValue'])
+const emit = defineEmits(['update:modelValue', 'change'])
 const item = props.item
-const value = computed({
-  get() { return props.modelValue },
-  set(value) { emit('update:modelValue', value) }
-})
+const value = ref(props.modelValue)
+const modelValueUpDate = (val) => {
+  value.value = val
+  emit('update:modelValue', value.value)
+  emit('change', value.value)
+}
 </script>
 <style lang="scss" scoped>
 </style>

+ 45 - 0
src/components/FormUI/radioGroup/index.vue

@@ -0,0 +1,45 @@
+<template>
+  
+  <!-- <div :style="`width: ${item.width || 120}px;`">{{ item.label }}</div> -->
+  <v-radio-group
+    v-model="value"
+    :disabled="item.disabled"
+    mandatory
+    inline
+    class="mr-8"
+    @update:modelValue="modelValueUpDate"
+  >
+    <template v-slot:label>
+      <div :style="`width: ${item.width || 120}px;`">{{ item.label }}</div>
+    </template>
+    <v-radio
+      v-for="radio in item.items"
+      :key="`${item.key}_radio_${radio.label}`"
+      :readonly="radio.readonly"
+      :label="radio.label"
+      :value="radio.value"
+    ></v-radio>
+  </v-radio-group>
+</template>
+<script setup>
+import { ref, defineEmits } from 'vue';
+defineOptions({ name:'FormUI-v-text-field'})
+
+const props = defineProps({item: Object, modelValue: [String, Number]})
+const emit = defineEmits(['update:modelValue', 'change'])
+const item = props.item
+const value = ref(props.modelValue)
+const modelValueUpDate = (val) => {
+  value.value = val
+  emit('update:modelValue', value.value)
+  emit('change', value.value)
+}
+</script>
+<style lang="scss" scoped>
+:deep(.v-input__control) {
+  flex-direction: row !important;
+}
+:deep(.v-selection-control-group) {
+  margin-top: 0 !important;
+}
+</style>

+ 84 - 0
src/views/resume/components/right/basicInfo.vue

@@ -0,0 +1,84 @@
+<template>
+  <div class="d-flex align-center my-3">
+    <!-- 头像 -->
+    <div class="avatarsBox" @mouseover="showIcon = true" @mouseleave="showIcon = false">
+      <v-img class="img" cover src="https://cdn.vuetifyjs.com/images/john.jpg"></v-img>
+      <div v-show="showIcon" class="mdi mdi-camera-outline"></div>
+    </div>
+    <!-- 基础信息 -->
+    <div style="flex: 1;" class="mr-8">
+      <CtForm :items="items" style="width: 100%;"></CtForm>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import CtForm from '@/components/CtForm';
+import { ref } from 'vue';
+
+defineOptions({name: 'resume-components-right-basicInfo'})
+const showIcon = ref(false)
+const items = ref({
+  options: [
+    {
+      type: 'text',
+      key: 'name',
+      value: null,
+      default: null,
+      label: '姓名 *',
+      outlined: true,
+      rules: [v => !!v || '请输入姓名']
+    },
+    {
+      type: 'ifRadio',
+      key: 'sex',
+      value: true,
+      default: true,
+      label: '性别',
+      width: 70,
+      items: [{ label: '男', value: true }, { label: '女', value: false }],
+    },
+    {
+      type: 'autocomplete',
+      key: 'birth',
+      value: null,
+      default: null,
+      label: '请选择出生年月 *',
+      outlined: true,
+      dense: true,
+      itemText: 'label',
+      itemValue: 'value',
+      rules: [v => !!v || '请选择出生年月']
+      // items: [{}]
+    },
+  ]
+})
+
+
+</script>
+<style lang="scss" scoped>
+
+.avatarsBox {
+  height: 80px;
+  width: 80px;
+  position: relative;
+  cursor: pointer;
+  margin: 32px;
+  margin-right: 40px;
+  .img {
+    width: 100%;
+    height: 100%;
+  }
+  .mdi {
+    font-size: 42px;
+    color: #fff;
+  }
+  div {
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    border-radius: 50%;
+  }
+}
+</style>

+ 2 - 6
src/views/resume/dynamic/right.vue

@@ -1,12 +1,11 @@
 <template>
   <div class="box">
-    <div class="avatarsBox">
-      132
-    </div>
+    <basicInfo></basicInfo>
   </div>
 </template>
 
 <script setup>
+import basicInfo from '../components/right/basicInfo.vue'
 defineOptions({ name: 'resume-right'})
 </script>
 
@@ -15,8 +14,5 @@ defineOptions({ name: 'resume-right'})
   width: 100%;
   background-color: #fff;
   padding: 12px;
-  .avatarsBox {
-    height: 50px;
-  }
 }
 </style>