liu
3 天以前 fe2d6627b8f1002af7a31b08f6f43bec034d04ee
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
<script lang="ts" setup>
import type { WxCpActivityApi } from '#/api/wxcp/activity';
 
import { Button, Input, Select, Switch } from 'ant-design-vue';
 
import { FIELD_TYPE_OPTIONS } from '../data';
 
defineOptions({ name: 'WxCpActivityFieldEditor' });
 
interface Props {
  /** 采集字段列表 */
  modelValue?: WxCpActivityApi.Field[];
  disabled?: boolean;
}
 
const props = withDefaults(defineProps<Props>(), {
  modelValue: () => [],
  disabled: false,
});
 
const emit = defineEmits<{
  'update:modelValue': [value: WxCpActivityApi.Field[]];
}>();
 
/** 需要填写选项的字段类型 */
const OPTION_TYPES = new Set(['checkbox', 'radio', 'select']);
 
function update(index: number, patch: Partial<WxCpActivityApi.Field>) {
  const list = [...props.modelValue];
  list[index] = { ...list[index], ...patch };
  emit('update:modelValue', list);
}
 
function handleAdd() {
  emit('update:modelValue', [
    ...props.modelValue,
    {
      fieldLabel: '',
      fieldType: 'text',
      required: false,
      sortNo: props.modelValue.length + 1,
    },
  ]);
}
 
function handleRemove(index: number) {
  const list = props.modelValue.filter((_, i) => i !== index);
  emit('update:modelValue', list);
}
 
function needOptions(type?: string) {
  return OPTION_TYPES.has(type ?? '');
}
</script>
 
<template>
  <div class="mb-4">
    <div class="mb-2 flex items-center justify-between">
      <span class="text-sm font-medium">采集字段</span>
      <Button size="small" :disabled="disabled" @click="handleAdd">
        添加字段
      </Button>
    </div>
 
    <div v-if="!modelValue.length" class="text-xs text-gray-400">
      未添加字段时,成员只需填写姓名、手机号、参与说明并上传附件。
    </div>
 
    <div
      v-for="(item, index) in modelValue"
      :key="index"
      class="mb-2 rounded border border-gray-200 p-2 dark:border-gray-700"
    >
      <div class="flex flex-wrap items-center gap-2">
        <Input
          :value="item.fieldLabel"
          class="w-44"
          placeholder="字段名称"
          :disabled="disabled"
          @update:value="(value: string) => update(index, { fieldLabel: value })"
        />
        <Select
          :value="item.fieldType"
          class="w-32"
          :options="FIELD_TYPE_OPTIONS"
          :disabled="disabled"
          @update:value="(value: unknown) => update(index, { fieldType: String(value) })"
        />
        <Input
          v-if="needOptions(item.fieldType)"
          :value="item.fieldOptions"
          class="w-64"
          placeholder="选项,用英文逗号分隔"
          :disabled="disabled"
          @update:value="(value: string) => update(index, { fieldOptions: value })"
        />
        <Input
          v-else
          :value="item.placeholder"
          class="w-64"
          placeholder="输入提示(选填)"
          :disabled="disabled"
          @update:value="(value: string) => update(index, { placeholder: value })"
        />
        <span class="text-xs text-gray-500">必填</span>
        <Switch
          :checked="item.required"
          size="small"
          :disabled="disabled"
          @change="(checked: unknown) => update(index, { required: checked === true })"
        />
        <Button
          danger
          type="link"
          size="small"
          :disabled="disabled"
          @click="handleRemove(index)"
        >
          删除
        </Button>
      </div>
    </div>
  </div>
</template>