123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- <script lang="ts" setup>
- // import { ref, reactive, onMounted, inject, watchEffect, watch, computed } from 'vue';
- const props = defineProps({
- modelValue: { type: null, required: true },
- multiple: { type: Boolean, required: false, default: false },
- size: { type: String as () => '' | 'large' | 'default' | 'small', required: true, default: () => '' },
- placeholder: { type: String, required: false, default: () => '请选择' },
- disabled: { type: Boolean, required: false, default: false },
- options: { type: Array as () => optionsType, required: false, default: () => [] },
- clearable: { type: Boolean, required: false, default: true },
- width: { type: String, required: false, default: () => '100%' },
- url: { type: String, required: false, default: () => '' },
- });
- type optionsType = {
- label: string,
- value: string | number,
- jobNumber?: string,
- }[]
- interface Emits {
- (event: "change", value: any): void;
- /**
- * 双向绑定事件
- * @param value 对应数据
- */
- (event: "update:modelValue", value: any): void;
- }
- const emit = defineEmits<Emits>();
- const personnelArray = ref<optionsType>([]);
- const { userInfo = {}, personnelList = [] } = JSON.parse(sessionStorage.getItem('storeInfo') || '{}')
- const textSize = ref({
- 'small': { height: '20px', fontSize: '12px' },
- 'default': { height: '28px', fontSize: '14px' },
- '': { height: '28px', fontSize: '14px' },
- 'large': { height: '36px', fontSize: '14px' },
- })
- const selectLoading = ref(false);
- const controlTranslation = reactive({
- visibleFlag: false // 下拉框出现隐藏
- })
- const selectedValue = ref(props.modelValue); // 响应式绑定 v-model 的值
- watch(() => props.modelValue, (newValue, _oldValue) => {
- if(newValue != selectedValue.value) {
- selectedValue.value = newValue
- }
- });
- const getSelectedLabel = computed(() => {
- if (!props.multiple) {
- const item = getPersonnelListItems(selectedValue.value || props.modelValue);
- return item ? item.label : props.placeholder
- }
- if (props.multiple) {
- if (Array.isArray(selectedValue.value)) {
- if (selectedValue.value.length <= 0) {
- return props.placeholder
- }
- const item = getPersonnelListItems(selectedValue.value || props.modelValue);
- return item ? item.label : props.placeholder
- } else {
- return props.placeholder
- }
- }
- return props.placeholder
- })
- function tagClose(_evt: MouseEvent) {
- if (Array.isArray(selectedValue.value)) {
- selectedValue.value.shift()
- updateValue(selectedValue.value)
- }
- }
- function getPersonnelListItems(val: any) {
- let value = val;
- if (Array.isArray(val) && val.length > 0) {
- value = val[0]
- }
- return personnelList.find((item: any) => item.value == value)
- }
- function getUserList(keyword: string = '') {
- newPost(props.url, keyword).then(res => {
- personnelArray.value = (res || [])
- }).finally(() => {
- selectLoading.value = false
- })
- }
- function newPost(url: string, keyword: string): Promise<any> {
- return new Promise((resolve, reject) => {
- const token: any = sessionStorage.getItem('token');
-
- if (!token) {
- reject(new Error("Token is missing"));
- return;
- }
- const body = new URLSearchParams();
- body.append('keyword', keyword);
-
- fetch(url, {
- method: "POST", // 确保请求方法正确,如果是其他方法需要修改
- headers: {
- "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
- "Token": token
- },
- body: body.toString()
- })
- .then(resp => {
- if (!resp.ok) {
- reject(new Error(`Error: ${resp.statusText}`));
- }
- return resp.json();
- })
- .then((json) => {
- const res = json.data;
- if (Array.isArray(res)) {
- const personnelArray = res.map(data => ({
- label: data['label'],
- value: data['value'],
- }));
- resolve(personnelArray);
- } else {
- reject(new Error("Invalid data format"));
- }
- })
- .catch((error) => {
- reject(error);
- });
- });
- }
- function visibleChange(visible: boolean) { // 下拉框出现/隐藏时触发
- if(visible) {
- personnelArray.value = personnelList
- }
- controlTranslation.visibleFlag = visible
- }
- const filterMethod = debounce(filterMethods, 500)
- function filterMethods(val: string) {
- if (val == '') {
- personnelArray.value = personnelList
- selectLoading.value = false
- return personnelArray.value
- }
- selectLoading.value = true
- getUserList(val)
- }
- function updateValue(val: any) { // 值改变的时候触发
- emit('update:modelValue', selectedValue.value)
- emit('change', val)
- }
- function debounce(func: Function, delay: number) {
- let timer: any;
- return (...args: any[]) => {
- if (timer) {
- clearTimeout(timer);
- }
- timer = setTimeout(() => {
- func(...args);
- }, delay);
- };
- }
- onMounted(() => {
- if (personnelList.length == 0) {
- getUserList()
- } else {
- personnelArray.value = personnelList
- }
- })
- </script>
- <template>
- <!-- <el-select-v2 v-model="selectedValue" :multiple="multiple" :size="size"
- :loading="selectLoading" :placeholder="placeholder" :disabled="disabled" :clearable="clearable" filterable collapse-tags :options="(personnelArray || [])"
- :style="`width: ${width}`" :class="`custom-select-v2-reset ${!controlTranslation.visibleFlag ? 'setUpInputReset' : ''}`"
- @change="updateValue"
- @visible-change="visibleChange" :filter-method="filterMethod">
- <template #prefix v-if="!multiple">
- <div class="selectV2SingleChoiceReset">
- <div v-if="!controlTranslation.visibleFlag" class="selectSingleChoice" :style="`line-height: ${textSize[size].height};font-size:${textSize[size].fontSize}`">
- <template v-if="getSelectedLabel == placeholder">
- <span style="color: #A8ABB2">{{ placeholder }}</span>
- </template>
- <template v-else>
- <span style="color: #606266;">
- {{ getSelectedLabel }}
- </span>
- </template>
- </div>
- </div>
- </template>
- <template #prefix v-if="multiple">
- <div class="selectV2SingleChoiceTwoReset">
- <div class="selectSingleChoice" :style="`line-height: ${textSize[size].height};font-size:${textSize[size].fontSize}`">
- <template v-if="getSelectedLabel == placeholder">
- <span style="color: #A8ABB2">{{ placeholder }}</span>
- </template>
- <template v-else>
- <el-tag type="info" :size="size" closable @close="tagClose" style="margin-right: 5px;">
- {{ getSelectedLabel }}
- </el-tag>
- <el-tag type="info" :size="size" v-if="selectedValue.length > 1">+{{ selectedValue.length }}</el-tag>
- </template>
- </div>
- </div>
- </template>
- <template #default="{ item }">
- <div class="flex items-center">
- {{ item.label }}
- </div>
- </template>
- </el-select-v2> -->
- <el-select v-model="selectedValue" :multiple="multiple" :size="size"
- :loading="selectLoading" :placeholder="placeholder" :disabled="disabled" :clearable="clearable" filterable collapse-tags
- :style="`width: ${width}`" :class="`custom-select-v2-reset ${!controlTranslation.visibleFlag ? 'setUpInputReset' : ''}`"
- @change="updateValue"
- @visible-change="visibleChange" :filter-method="filterMethod">
- <template #prefix v-if="!multiple">
- <div class="selectV2SingleChoiceReset">
- <div v-if="!controlTranslation.visibleFlag" class="selectSingleChoice" :style="`line-height: ${textSize[size].height};font-size:${textSize[size].fontSize}`">
- <template v-if="getSelectedLabel == placeholder">
- <span style="color: #A8ABB2">{{ placeholder }}</span>
- </template>
- <template v-else>
- <span style="color: #606266;">
- <!-- {{ getSelectedLabel }} -->
- <ww-open-data type='userName' :openid='getSelectedLabel'></ww-open-data>
- </span>
- </template>
- </div>
- </div>
- </template>
- <template #prefix v-if="multiple">
- <div class="selectV2SingleChoiceTwoReset">
- <div class="selectSingleChoice" :style="`line-height: ${textSize[size].height};font-size:${textSize[size].fontSize}`">
- <template v-if="getSelectedLabel == placeholder">
- <span style="color: #A8ABB2">{{ placeholder }}</span>
- </template>
- <template v-else>
- <el-tag type="info" :size="size" closable @close="tagClose" style="margin-right: 5px;">
- <!-- {{ getSelectedLabel }} -->
- <ww-open-data type='userName' :openid='getSelectedLabel'></ww-open-data>
- </el-tag>
- <el-tag type="info" :size="size" v-if="selectedValue.length > 1">+{{ selectedValue.length }}</el-tag>
- </template>
- </div>
- </div>
- </template>
- <el-option
- v-for="item in (personnelArray || [])"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- >
- <span style="float: left">
- <ww-open-data type='userName' :openid='item.label'></ww-open-data>
- <!-- {{ item.label }} -->
- </span>
- </el-option>
- </el-select>
- </template>
- reset
- <style lang="scss">
- .custom-select-v2-reset {
- position: relative;
- .selectV2SingleChoiceReset, .selectV2SingleChoiceTwoReset {
- position: absolute;
- display: flex;
- align-items: center;
- transform: translate(0,-50%);
- .selectSingleChoice {
- background: #fff;
- }
- }
- .el-select-v2__placeholder {
- display: none !important;
- }
- .el-select-v2__selected-item {
- .el-tag {
- display: none !important;
- }
- }
- .selectV2SingleChoiceReset {
- top: 50%;
- left: 14px;
- }
- .selectV2SingleChoiceTwoReset {
- position: relative;
- transform: translate(0);
- }
- .el-input__inner::placeholder {
- color: transparent !important;
- }
- .el-select__tags {
- .el-tag {
- display: none !important;
- }
- }
- .el-select-tags-wrapper {
- width: 110px !important;
- }
- }
- .setUpInputReset .el-input__inner {
- color: #fff !important;
- }
- </style>
|