Lijy 5 ماه پیش
والد
کامیت
616d394ad5

+ 1 - 0
fhKeeper/formulahousekeeper/plugIn/form-design-master/playground/src/components.d.ts

@@ -25,6 +25,7 @@ declare module 'vue' {
     ElRate: typeof import('element-plus/es')['ElRate']
     ElRow: typeof import('element-plus/es')['ElRow']
     ElSelect: typeof import('element-plus/es')['ElSelect']
+    ElSelectV2: typeof import('element-plus/es')['ElSelectV2']
     ElSlider: typeof import('element-plus/es')['ElSlider']
     ElSpace: typeof import('element-plus/es')['ElSpace']
     ElSwitch: typeof import('element-plus/es')['ElSwitch']

+ 13 - 0
fhKeeper/formulahousekeeper/plugIn/form-design-master/playground/vite.config.ts

@@ -3,4 +3,17 @@ import Vue from '@vitejs/plugin-vue'
 
 export default defineConfig({
   plugins: [Vue()],
+  server: {
+    host: '0.0.0.0',
+    port: 19100,
+    open: true,
+    proxy: {
+      '/api': {
+        // 这里的'/api'表示需要转发到的接口路径前缀
+        target: 'http://127.0.0.1:10010', // 将请求转发到的目标地址
+        changeOrigin: true, // 支持跨域
+        rewrite: (path) => path.replace(/^\/api/, '') // 去除请求路径中的'/api'前缀
+      }
+    }
+  },
 })

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 2934 - 2376
fhKeeper/formulahousekeeper/plugIn/form-design-master/pnpm-lock.yaml


+ 3 - 0
fhKeeper/formulahousekeeper/plugIn/form-design-master/src/components.d.ts

@@ -25,13 +25,16 @@ declare module 'vue' {
     ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
     ElRate: typeof import('element-plus/es')['ElRate']
     ElSelect: typeof import('element-plus/es')['ElSelect']
+    ElSelectV2: typeof import('element-plus/es')['ElSelectV2']
     ElSlider: typeof import('element-plus/es')['ElSlider']
     ElSpace: typeof import('element-plus/es')['ElSpace']
     ElSwitch: typeof import('element-plus/es')['ElSwitch']
     ElTable: typeof import('element-plus/es')['ElTable']
     ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
+    ElTag: typeof import('element-plus/es')['ElTag']
     ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
     ElUpload: typeof import('element-plus/es')['ElUpload']
+    PersonnelSearch: typeof import('./components/personnelSearch.vue')['default']
   }
 }
 

+ 281 - 0
fhKeeper/formulahousekeeper/plugIn/form-design-master/src/components/personnelSearch.vue

@@ -0,0 +1,281 @@
+<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;">
+              <template v-if="userInfo.userNameNeedTranslate == 1">
+                <ww-open-data type="userName" :openid="getSelectedLabel"></ww-open-data>
+              </template>
+              <template v-else>
+                {{ getSelectedLabel }}
+              </template>
+            </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;">
+              <template v-if="userInfo.userNameNeedTranslate == 1">
+                <ww-open-data type="userName" :openid="getSelectedLabel"></ww-open-data>
+              </template>
+              <template v-else>
+                {{ getSelectedLabel }}
+              </template>
+            </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">
+        <template v-if="userInfo.userNameNeedTranslate == 1">
+          <ww-open-data type="userName" :openid="item.label"></ww-open-data>
+        </template>
+        <template v-else>
+          {{ item.label }}
+        </template>
+      </div>
+    </template>
+  </el-select-v2>
+</template>
+reset
+<style lang="scss">
+.custom-select-v2-reset {
+  position: relative;
+  .selectV2SingleChoiceReset, .selectV2SingleChoiceTwoReset {
+    position: absolute;
+    margin-left: 12px;
+    display: flex;
+    align-items: center;
+    top: 50%;
+    transform: translate(0,-50%);
+    .selectSingleChoice {
+      background: #fff;
+    }
+  }
+  .el-select-v2__placeholder {
+    display: none !important;
+  }
+  .el-select-v2__selected-item {
+    .el-tag {
+      display: none !important;
+    }
+  }
+
+  .selectV2SingleChoiceTwoReset {
+    position: relative;
+    transform: translate(0);
+    margin-left: 6px;
+  }
+}
+
+.setUpInputReset .el-input__inner {
+  color: #fff !important;
+}
+</style>

+ 1 - 1
fhKeeper/formulahousekeeper/plugIn/form-design-master/src/config/index.ts

@@ -16,7 +16,7 @@ export interface WidgetForm {
     size: '' | 'default' | 'small' | 'large'
     hideRequiredAsterisk: boolean
     labelWidth: number
-    labelPosition: string
+    labelPosition: 'top' | 'right' | 'left' 
   }
 }
 

+ 1 - 0
fhKeeper/formulahousekeeper/plugIn/form-design-master/src/design/WidgetForm.vue

@@ -24,6 +24,7 @@
           :element="element"
           :index="index"
           :list="list"
+          :configurationItems="config"
         />
       </template>
     </Draggable>

+ 40 - 17
fhKeeper/formulahousekeeper/plugIn/form-design-master/src/design/WidgetFormItem.vue

@@ -1,17 +1,22 @@
 <script lang="ts" setup>
 import Draggable from 'vuedraggable'
 import { cloneWidget } from '@/components/ComponentGroup.vue'
+import personnelSearch from '@/components/personnelSearch.vue';
+import type { WidgetForm } from '@/config'
 
-const { element, index, list, ...props } = defineProps<{
+const { element, index, list, ...props  } = defineProps<{
   list: any
   element: any
   index: number
   selectWidget: any
+  configurationItems: WidgetForm['config']
 }>()
 defineEmits(['itemClick', 'delete', 'update:selectWidget'])
 
 let selectWidget = $(useVModel(props, 'selectWidget'))
 
+const { userInfo = {} } = JSON.parse(sessionStorage.getItem('storeInfo') || '{}')
+
 const handleCopyClick = () => {
   list.splice(index + 1, 0, cloneWidget(list[index]))
   selectWidget = list[index + 1]
@@ -50,6 +55,7 @@ const handleDeleteClick = () => {
             :element="colElement"
             :list="col.list"
             :index="colIndex"
+            :configurationItems="configurationItems"
           />
         </template>
       </Draggable>
@@ -234,22 +240,39 @@ const handleDeleteClick = () => {
       </template>
 
       <template v-if="element.type === 'select'">
-        <el-select
-          :model-value="element.options.defaultValue"
-          :multiple="element.options.multiple"
-          :placeholder="element.options.placeholder"
-          :clearable="element.options.clearable"
-          :filterable="element.options.filterable"
-          :disabled="element.options.disabled"
-          :style="{ width: element.options.width }"
-        >
-          <el-option
-            v-for="item of element.options.options"
-            :key="item.value"
-            :value="item.value"
-            :label="element.options.showLabel ? item.label : item.value"
-          />
-        </el-select>
+        <template v-if="userInfo.userNameNeedTranslate == 1 && element.options.remoteFunc.indexOf('getSimpleActiveUserListNew') > -1">
+          <personnelSearch 
+            :model-value="element.options.defaultValue" 
+            :multiple="element.options.multiple"
+            :placeholder="element.options.placeholder"
+            :clearable="element.options.clearable"
+            :filterable="element.options.filterable"
+            :disabled="element.options.disabled"
+            :url="element.options.remoteFunc"
+            :size="configurationItems.size"
+            :options="[]"
+            :style="{ width: element.options.width }"
+          >
+          </personnelSearch>
+        </template>
+        <template v-else>
+          <el-select
+            :model-value="element.options.defaultValue"
+            :multiple="element.options.multiple"
+            :placeholder="element.options.placeholder"
+            :clearable="element.options.clearable"
+            :filterable="element.options.filterable"
+            :disabled="element.options.disabled"
+            :style="{ width: element.options.width }"
+          >
+            <el-option
+              v-for="item of element.options.options"
+              :key="item.value"
+              :value="item.value"
+              :label="element.options.showLabel ? item.label : item.value"
+            />
+          </el-select>
+        </template>
       </template>
 
       <template v-if="element.type === 'switch'">

+ 39 - 19
fhKeeper/formulahousekeeper/plugIn/form-design-master/src/generate/GenerateFormItem.vue

@@ -230,25 +230,43 @@
     </template>
 
     <template v-if="element.type === 'select'">
-      <el-select
-        v-model="data"
-        :multiple="element.options.multiple"
-        :placeholder="element.options.placeholder"
-        :clearable="element.options.clearable"
-        :filterable="element.options.filterable"
-        :disabled="disabled || element.options.disabled"
-        :style="{ width: element.options.width }"
-        @change="(value: any) => specializedHandleSelect(value, element)"
-      >
-        <el-option
-          v-for="item of element.options.remote
-            ? element.options.remoteOptions
-            : element.options.options"
-          :key="item.value"
-          :value="item.value"
-          :label="element.options.showLabel ? item.label : item.value"
-        />
-      </el-select>
+      <template v-if="userInfo.userNameNeedTranslate == 1 && element.options.remoteFunc.indexOf('getSimpleActiveUserListNew') > -1">
+        <personnelSearch 
+          v-model="data" 
+          :multiple="element.options.multiple"
+          :placeholder="element.options.placeholder"
+          :clearable="element.options.clearable"
+          :filterable="element.options.filterable"
+          :disabled="disabled || element.options.disabled"
+          :url="element.options.remoteFunc"
+          :size="config.size"
+          :options="[]"
+          :style="{ width: element.options.width }"
+          @change="(value: any) => specializedHandleSelect(value, element)"
+        >
+        </personnelSearch>
+      </template>
+      <template v-else>
+        <el-select
+          v-model="data"
+          :multiple="element.options.multiple"
+          :placeholder="element.options.placeholder"
+          :clearable="element.options.clearable"
+          :filterable="element.options.filterable"
+          :disabled="disabled || element.options.disabled"
+          :style="{ width: element.options.width }"
+          @change="(value: any) => specializedHandleSelect(value, element)"
+        >
+          <el-option
+            v-for="item of element.options.remote
+              ? element.options.remoteOptions
+              : element.options.options"
+            :key="item.value"
+            :value="item.value"
+            :label="element.options.showLabel ? item.label : item.value"
+          />
+        </el-select>
+      </template>
     </template>
 
     <template v-if="element.type === 'switch'">
@@ -341,7 +359,9 @@
 <script lang="ts" setup>
 import type { WidgetForm } from '@/config'
 import zhCn from "element-plus/es/locale/lang/zh-cn";
+import personnelSearch from '@/components/personnelSearch.vue';
 
+const { userInfo = {} } = JSON.parse(sessionStorage.getItem('storeInfo') || '{}')
 const props = defineProps<{
   config: WidgetForm['config']
   element: any

+ 1 - 1
fhKeeper/formulahousekeeper/plugIn/form-design-master/vite.config.ts

@@ -98,5 +98,5 @@ export default defineConfig({
         },
       },
     },
-  },
+  }
 })