Explorar o código

feat: PDA协同办公增加部门级联选择组件, 退货入库审批包装和产品不对应问题

liujt hai 1 mes
pai
achega
db4b9c21fd

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 188 - 188
lib/vue-form-making-v3/dist/form-making-v3.es.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
lib/vue-form-making-v3/dist/form-making-v3.umd.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
lib/vue-form-making-v3/dist/index.css


+ 21 - 1
lib/vue-form-making-v3/src/components/Container.vue

@@ -342,6 +342,7 @@ import Outline from './Outline.vue'
 import { findModelNodeString } from '../util/find-node.js'
 import { getModels } from '../util/model-outline.js'
 import { ElMessage } from '../util/message.js'
+import { defaultDataSource } from './defaultDataSource.js'
 
 export default {
   name: 'fm-making-form',
@@ -381,7 +382,7 @@ export default {
     },
     basicFields: {
       type: Array,
-      default: () => ['input', 'textarea', 'number', 'radio', 'checkbox', 'time', 'date', 'rate', 'color', 'select', 'switch', 'slider', 'text', 'html', 'button', 'link', 'cascader', 'treeselect', 'steps', 'transfer', 'pagination']
+      default: () => ['input', 'textarea', 'number', 'radio', 'checkbox', 'time', 'date', 'rate', 'color', 'select', 'switch', 'slider', 'text', 'html', 'button', 'link', 'cascader', 'treeselect', 'deptCascader', 'steps', 'transfer', 'pagination']
     },
     advanceFields: {
       type: Array,
@@ -543,6 +544,10 @@ export default {
       ...this.globalConfig
     }
 
+    // 注入默认数据源(部门树 getDeptTree 等),与 vue-form-making 保持一致
+    // 合并而非直接覆盖,避免清掉用户已保存的数据源
+    this.widgetForm.config.dataSource = this.mergeDefaultDataSource(this.widgetForm.config.dataSource)
+
     this.platform = this.widgetForm.config.platform || 'pc'
 
     this.initConfig()
@@ -749,6 +754,11 @@ export default {
         list: json.list ?? json.list.map(item => UpgradeData(item))
       })
 
+      // 缓存/导入恢复后,补齐默认数据源(部门树 getDeptTree 等),
+      // 否则被覆盖为空的 config.dataSource 会导致数据源下拉为空、远程数据拉取失败
+      if (!this.widgetForm.config) this.widgetForm.config = {}
+      this.widgetForm.config.dataSource = this.mergeDefaultDataSource(this.widgetForm.config.dataSource)
+
       if (this.widgetForm.config?.eventScript) {
         this.widgetForm.config.eventScript.findIndex(item => item.key === 'onFormChange') < 0
           && this.widgetForm.config.eventScript.unshift({key: 'onFormChange', name: 'onFormChange', type: 'rule'})
@@ -1003,6 +1013,16 @@ export default {
         args: item.args ? Object.fromEntries(item.args.map(o => [o, ''])) : {}
       }))
     },
+    // 将默认数据源(getDeptTree 等)合并进已保存的数据源列表,
+    // 保留用户自定义项,仅补齐缺失的默认项(深拷贝避免污染模块级常量)
+    mergeDefaultDataSource (existing) {
+      const list = Array.isArray(existing) ? existing : []
+      const existingKeys = list.map(item => item && item.key)
+      const appends = defaultDataSource
+        .filter(item => !existingKeys.includes(item.key))
+        .map(item => ({ ...item }))
+      return [...list, ...appends]
+    },
     onEventScriptUpdate (eventScript) {
       this.eventScriptArray = eventScript.map(item => ({
         value: item.key,

+ 20 - 1
lib/vue-form-making-v3/src/components/VantGenerator/GenerateElementItem.vue

@@ -394,6 +394,23 @@
     ></fm-vant-cascader>
   </template>
 
+  <template v-if="widget.type == 'deptCascader'">
+    <fm-vant-dept-cascader
+      v-model="dataModel"
+      :placeholder="widget.options.placeholder"
+      :disabled="elementDisabled"
+      :customProps="widget.options.customProps"
+      :extendProps="extendProps"
+      :publicProps="publicProps"
+      :options="remoteOptions"
+      :title="widget.name"
+      :is-path-value="true"
+      :multiple="widget.options.multiple"
+      :print-read="printRead"
+      :ref="'fm-'+widget.model"
+    ></fm-vant-dept-cascader>
+  </template>
+
   <template v-if="widget.type == 'steps'">
     <van-field
       v-bind="{...publicProps}"
@@ -640,6 +657,7 @@ import { getTimeColumnsType, parseTimeToArray, formatTimeValue } from '../../uti
 import FmVantSelect from './components/Select.vue'
 import FmVantCascader from './components/Cascader.vue'
 import FmVantUploader from './components/Uploader.vue'
+import FmVantDeptCascader from './components/DeptCascader.vue'
 
 export default {
   components: {
@@ -648,6 +666,7 @@ export default {
     FmVantSelect,
     FmVantCascader,
     FmVantUploader,
+    FmVantDeptCascader,
     FmVantFormTable: defineAsyncComponent(() => import('./FormTable.vue')),
   },
   mixins: [generateElementItemMixin],
@@ -738,7 +757,7 @@ export default {
       if (!Array.isArray(data)) return
       this.remoteOptions = data.map(item => {
 
-        if (this.widget.type == 'cascader' || this.widget.type == 'treeselect') {
+        if (this.widget.type == 'cascader' || this.widget.type == 'treeselect' || this.widget.type == 'deptCascader') {
           if (this.widget.options.props.children && this.widget.options.props.children.length && Object.keys(item).includes(this.widget.options.props.children)) {
             return {
               value: item[this.widget.options.props.value],

+ 208 - 0
lib/vue-form-making-v3/src/components/VantGenerator/components/DeptCascader.vue

@@ -0,0 +1,208 @@
+<template>
+  <van-field
+    v-model="fieldValue"
+    :is-link="!printRead && !disabled"
+    readonly
+    :placeholder="placeholder"
+    :disabled="disabled"
+    v-bind="{ ...publicProps }"
+    @click="onShowPicker"
+    :key="printRead"
+  >
+    <template #input v-if="printRead">
+      {{ fieldValue }}
+    </template>
+  </van-field>
+
+  <van-popup v-model:show="show" round position="bottom" teleport="body" z-index="5000">
+    <div class="dept-cascader__header">
+      <span class="dept-cascader__title">{{ title || publicProps?.label || '' }}</span>
+      <div v-if="multiple" class="dept-cascader__tools">
+        <van-button size="mini" @click="toggleExpandAll">{{ expandAll ? '收起全部' : '展开全部' }}</van-button>
+        <van-button size="mini" type="primary" @click="show = false">完成</van-button>
+      </div>
+    </div>
+
+    <div v-if="multiple" class="dept-cascader__body">
+      <DeptCascaderTree
+        :nodes="options"
+        :model-value="selectedValues"
+        :expand-all="expandAll"
+        @update:model-value="onMultiChange"
+      />
+    </div>
+
+    <van-cascader
+      v-else
+      v-model="cascaderValue"
+      :options="options"
+      :title="title || publicProps?.label"
+      @close="show = false"
+      @finish="onFinish"
+      v-bind="{ ...customProps, ...extendProps }"
+    />
+  </van-popup>
+</template>
+
+<script setup>
+import { ref, watch } from 'vue'
+import DeptCascaderTree from './DeptCascaderTree.vue'
+
+const props = defineProps({
+  modelValue: [String, Number, Array],
+  placeholder: String,
+  disabled: Boolean,
+  customProps: Object,
+  extendProps: Object,
+  publicProps: Object,
+  options: { type: Array, default: () => [] },
+  title: String,
+  isPathValue: Boolean,
+  multiple: { type: Boolean, default: false },
+  printRead: Boolean
+})
+
+const emit = defineEmits(['update:modelValue'])
+
+const show = ref(false)
+const cascaderValue = ref('')
+const fieldValue = ref('')
+const expandAll = ref(false)
+const selectedValues = ref([])
+
+function isLeaf(node) {
+  return !node.children || node.children.length === 0
+}
+
+// 数值 / 字符串 id 统一比较,保证 Vue2 保存的数值 id 在 v3 详情返显时仍能对上
+function sameVal(a, b) {
+  return String(a) === String(b)
+}
+
+function getTreeText(value, options) {
+  for (let i = 0; i < options.length; i++) {
+    const cur = options[i]
+    if (sameVal(cur.value, value)) return cur.text
+    if (!isLeaf(cur)) {
+      const res = getTreeText(value, cur.children)
+      if (res) return res
+    }
+  }
+  return ''
+}
+
+function getCascaderText(values, options, texts = []) {
+  if (values.length >= 1) {
+    const cur = options?.find((opt) => sameVal(opt.value, values[0]))
+    if (cur) texts.push(cur.text)
+    values.splice(0, 1)
+    return getCascaderText(values, cur?.children, texts)
+  }
+  return texts
+}
+
+// 根据单个 value 查找其从根到叶的完整 value 路径(用于兼容旧格式的纯叶子值)
+function findPath(value, options, prefix = []) {
+  for (const opt of options) {
+    const cur = [...prefix, opt.value]
+    if (sameVal(opt.value, value)) return cur
+    if (opt.children && opt.children.length) {
+      const r = findPath(value, opt.children, cur)
+      if (r) return r
+    }
+  }
+  return null
+}
+
+// 把一条完整 value 路径转成「/」分隔的文本路径
+function getPathText(path, options) {
+  const texts = []
+  let cur = options
+  for (const v of path) {
+    const node = cur?.find((o) => sameVal(o.value, v))
+    if (!node) break
+    texts.push(node.text)
+    cur = node.children
+  }
+  return texts.join('/')
+}
+
+watch(
+  () => props.modelValue,
+  (val) => {
+    if (props.multiple) {
+      const arr = Array.isArray(val) ? val : val ? [val] : []
+      // 兼容旧格式:纯叶子值自动补成完整路径
+      selectedValues.value = arr.map((item) =>
+        Array.isArray(item) ? item : findPath(item, props.options) || [item]
+      )
+      fieldValue.value = selectedValues.value
+        .map((p) => (Array.isArray(p) ? getPathText(p, props.options) : getTreeText(p, props.options)))
+        .filter(Boolean)
+        .join('、')
+    } else if (props.isPathValue) {
+      const values = Array.isArray(val) ? val : val ? [val] : []
+      cascaderValue.value = values.length ? values[values.length - 1] : ''
+      fieldValue.value = getCascaderText([...values], props.options).join('/')
+    } else {
+      const value = Array.isArray(val) ? val[0] : val
+      cascaderValue.value = value
+      fieldValue.value = getTreeText(value, props.options)
+    }
+  },
+  { immediate: true }
+)
+
+function onFinish({ selectedOptions }) {
+  if (props.isPathValue) {
+    emit('update:modelValue', selectedOptions.map((i) => i.value))
+    fieldValue.value = selectedOptions.map((i) => i.text).join('/')
+  } else {
+    emit('update:modelValue', cascaderValue.value)
+    fieldValue.value = selectedOptions[selectedOptions.length - 1].text
+  }
+  show.value = false
+}
+
+function onMultiChange(val) {
+  emit('update:modelValue', val)
+  selectedValues.value = val
+  fieldValue.value = val
+    .map((p) => (Array.isArray(p) ? getPathText(p, props.options) : getTreeText(p, props.options)))
+    .filter(Boolean)
+    .join('、')
+}
+
+function onShowPicker() {
+  if (props.printRead || props.disabled) return
+  show.value = true
+}
+
+function toggleExpandAll() {
+  expandAll.value = !expandAll.value
+}
+</script>
+
+<style scoped>
+.dept-cascader__header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 12px 16px;
+  border-bottom: 1px solid #ebedf0;
+}
+.dept-cascader__title {
+  font-weight: 600;
+  font-size: 15px;
+  color: #323233;
+}
+.dept-cascader__tools {
+  display: flex;
+  gap: 8px;
+}
+.dept-cascader__body {
+  max-height: 60vh;
+  overflow-y: auto;
+  padding: 4px 0;
+}
+</style>

+ 171 - 0
lib/vue-form-making-v3/src/components/VantGenerator/components/DeptCascaderTree.vue

@@ -0,0 +1,171 @@
+<template>
+  <div class="dept-tree">
+    <div v-for="node in nodes" :key="node.value" class="dept-tree__node">
+      <div class="dept-tree__row" :style="{ paddingLeft: level * 18 + 14 + 'px' }">
+        <span
+          v-if="hasChildren(node)"
+          class="dept-tree__arrow"
+          :class="{ 'is-expanded': isExpanded(node) }"
+          @click="toggleExpand(node)"
+          >▶</span
+        >
+        <span v-else class="dept-tree__arrow dept-tree__arrow--leaf"></span>
+
+        <van-checkbox
+          class="dept-tree__checkbox"
+          :model-value="state(node).checked"
+          :indeterminate="state(node).indeterminate"
+          @change="toggle(node)"
+        />
+
+        <span class="dept-tree__label" @click="toggleExpand(node)">{{ node.text }}</span>
+      </div>
+
+      <DeptCascaderTree
+        v-if="hasChildren(node) && isExpanded(node)"
+        :nodes="node.children"
+        :model-value="modelValue"
+        :level="level + 1"
+        :prefix="[...prefix, node.value]"
+        :expand-all="expandAll"
+        @update:model-value="emitChange"
+      />
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+
+const props = defineProps({
+  // 当前层级的节点
+  nodes: { type: Array, default: () => [] },
+  // 已选中的完整路径数组:每个元素是从根到叶的 value 路径,如 ['1','2','3']
+  modelValue: { type: Array, default: () => [] },
+  // 层级,仅用于缩进
+  level: { type: Number, default: 0 },
+  // 祖先路径(从根到当前层父节点的 value 数组),用于拼接完整路径
+  prefix: { type: Array, default: () => [] },
+  // 是否一次性展开全部
+  expandAll: { type: Boolean, default: false }
+})
+const emit = defineEmits(['update:modelValue'])
+
+const expanded = ref({})
+
+function hasChildren(node) {
+  return node.children && node.children.length > 0
+}
+
+function isExpanded(node) {
+  if (props.expandAll) return true
+  return !!expanded.value[node.value]
+}
+
+function toggleExpand(node) {
+  expanded.value = { ...expanded.value, [node.value]: !isExpanded(node) }
+}
+
+// 收集某节点下所有叶子 value
+function collectLeaves(node, acc = []) {
+  if (hasChildren(node)) {
+    node.children.forEach((c) => collectLeaves(c, acc))
+  } else {
+    acc.push(node.value)
+  }
+  return acc
+}
+
+// 收集某节点下所有「完整路径」(从根到叶的 value 数组)
+function collectPaths(node, prefix = [], acc = []) {
+  const cur = [...prefix, node.value]
+  if (hasChildren(node)) {
+    node.children.forEach((c) => collectPaths(c, cur, acc))
+  } else {
+    acc.push(cur)
+  }
+  return acc
+}
+
+// 把每条路径的最后一个 value 视作该叶子是否被选中(兼容旧格式的纯叶子值 + 数值/字符串 id 兼容)
+function selectedLeafSet() {
+  const set = new Set()
+  props.modelValue.forEach((p) => {
+    const leaf = Array.isArray(p) ? p[p.length - 1] : p
+    set.add(String(leaf))
+  })
+  return set
+}
+
+// 用于比较/去重的路径 key(统一转字符串,避免数值/字符串 id 不一致导致返显失效)
+function pathKey(p) {
+  return Array.isArray(p) ? p.map(String).join('/') : String(p)
+}
+
+// 计算某节点的勾选态:叶子 -> 选中/未选;父节点 -> 全选/半选/未选
+function state(node) {
+  if (!hasChildren(node)) {
+    return { checked: selectedLeafSet().has(String(node.value)), indeterminate: false }
+  }
+  const leaves = collectLeaves(node)
+  if (leaves.length === 0) return { checked: false, indeterminate: false }
+  const sel = leaves.filter((v) => selectedLeafSet().has(String(v)))
+  return {
+    checked: sel.length === leaves.length,
+    indeterminate: sel.length > 0 && sel.length < leaves.length
+  }
+}
+
+// 勾选切换:父节点联动其下所有完整路径(含祖先前缀)
+function toggle(node) {
+  const paths = collectPaths(node, props.prefix)
+  const isChecked = state(node).checked
+  // 以「原始路径对象」为单位维护,避免 split('/') 把数值 id 转成字符串,
+  // 否则二次返显时路径与选项 value(数值)对不上,导致勾选态/文本丢失
+  const pathMap = new Map(props.modelValue.map((p) => [pathKey(p), p]))
+  if (isChecked) {
+    const rm = new Set(paths.map(pathKey))
+    rm.forEach((k) => pathMap.delete(k))
+  } else {
+    paths.forEach((p) => pathMap.set(pathKey(p), p))
+  }
+  emitChange([...pathMap.values()])
+}
+
+function emitChange(val) {
+  emit('update:modelValue', val)
+}
+</script>
+
+<style scoped>
+.dept-tree__row {
+  display: flex;
+  align-items: center;
+  min-height: 40px;
+}
+.dept-tree__arrow {
+  width: 18px;
+  font-size: 12px;
+  line-height: 1;
+  color: #969799;
+  transition: transform 0.2s;
+  cursor: pointer;
+  flex: none;
+}
+.dept-tree__arrow.is-expanded {
+  transform: rotate(90deg);
+}
+.dept-tree__arrow--leaf {
+  cursor: default;
+}
+.dept-tree__checkbox {
+  margin-right: 8px;
+  flex: none;
+}
+.dept-tree__label {
+  flex: 1;
+  font-size: 14px;
+  color: #323233;
+  cursor: pointer;
+}
+</style>

+ 18 - 2
lib/vue-form-making-v3/src/components/VantWidget/WidgetElementItem.vue

@@ -309,6 +309,20 @@
     ></fm-vant-cascader>
   </template>
 
+  <template v-if="element.type == 'deptCascader'">
+    <fm-vant-dept-cascader
+      v-model="element.options.defaultValue"
+      :placeholder="element.options.placeholder"
+      :disabled="elementDisabled"
+      :customProps="element.options.customProps"
+      :extendProps="extendProps"
+      :publicProps="publicProps"
+      :options="selectOptions"
+      :is-path-value="true"
+      :multiple="element.options.multiple"
+    ></fm-vant-dept-cascader>
+  </template>
+
   <template v-if="element.type == 'steps'">
     <van-field
       v-bind="{...publicProps}"
@@ -503,12 +517,14 @@ import { widgetElementItemMixin } from '../../mixins/widgetElementItem.js'
 import FmVantSelect from '../VantGenerator/components/Select.vue'
 import FmVantCascader from '../VantGenerator/components/Cascader.vue'
 import FmVantUploader from '../VantGenerator/components/Uploader.vue'
+import FmVantDeptCascader from '../VantGenerator/components/DeptCascader.vue'
 
 export default {
   components: {
     FmVantSelect,
     FmVantCascader,
-    FmVantUploader
+    FmVantUploader,
+    FmVantDeptCascader
   },
   name: 'VantWidgetElementItem',
   mixins: [widgetElementItemMixin],
@@ -528,7 +544,7 @@ export default {
 
     selectOptions () {
       return this.element.options.options.map(item => {
-        if (this.element.type == 'cascader' || this.element.type == 'treeselect') {
+        if (this.element.type == 'cascader' || this.element.type == 'treeselect' || this.element.type == 'deptCascader') {
           if (this.element.options.props.children && this.element.options.props.children.length && Object.keys(item).includes(this.element.options.props.children)) {
             return {
               value: item[this.element.options.props.value],

+ 7 - 4
lib/vue-form-making-v3/src/components/WidgetConfig.vue

@@ -156,7 +156,7 @@
               </el-radio-group>
             </el-form-item>
 
-            <el-form-item :label="$t('fm.config.widget.multiple')" v-if="data.type=='select' || data.type=='imgupload' || data.type == 'fileupload' || data.type == 'cascader' || data.type == 'treeselect'">
+            <el-form-item :label="$t('fm.config.widget.multiple')" v-if="data.type=='select' || data.type=='imgupload' || data.type == 'fileupload' || data.type == 'cascader' || data.type == 'treeselect' || data.type == 'deptCascader'">
               <el-switch v-model="data.options.multiple" @change="handleSelectMuliple"></el-switch>
             </el-form-item>
             <el-form-item :label="$t('fm.config.widget.filterable')" v-if="data.type=='select' || data.type == 'cascader' || data.type=='transfer' || data.type == 'treeselect'">
@@ -876,7 +876,7 @@
                 </el-popover>
               </template>
 
-              <template v-if="data.type == 'cascader'">
+              <template v-if="data.type == 'cascader' || data.type == 'deptCascader'">
                 <el-cascader
                   v-model="data.options.defaultValue"
                   clearable
@@ -1018,7 +1018,7 @@
                     </draggable>
                   </el-checkbox-group>
                 </template>
-                <div style="margin-left: 22px;" v-if="data.type != 'cascader' && data.type != 'treeselect'">
+                <div style="margin-left: 22px;" v-if="data.type != 'cascader' && data.type != 'treeselect' && data.type != 'deptCascader'">
                   <el-button link type="primary" @click="handleAddOption" >{{$t('fm.actions.addOption')}}</el-button>
                   <el-button link type="primary" @click="handleClearSelect" >{{$t('fm.actions.clearSelect')}}</el-button>
                 </div>
@@ -1028,6 +1028,9 @@
                 <template v-if="data.type == 'treeselect'">
                   <el-button style="width: 100%;" @click="handleSetTree">{{$t('fm.config.widget.setting')}}</el-button>
                 </template>
+                <template v-if="data.type == 'deptCascader'">
+                  <el-button style="width: 100%;" @click="handleSetCascader">{{$t('fm.config.widget.setting')}}</el-button>
+                </template>
               </template>
             </el-form-item>
 
@@ -1634,7 +1637,7 @@ export default {
       }
     },
     handleSelectMuliple (value) {
-      if (this.data.type == 'select' || this.data.type == 'treeselect') {
+      if (this.data.type == 'select' || this.data.type == 'treeselect' || this.data.type == 'deptCascader') {
         if (value) {
           if (this.data.options.defaultValue) {
             this.data.options.defaultValue = [this.data.options.defaultValue]

+ 59 - 0
lib/vue-form-making-v3/src/components/componentsConfig.js

@@ -645,6 +645,65 @@ export const basicComponents = [
       onBlur: ''
     }
   },
+  {
+    type: 'deptCascader',
+    icon: 'icon-shuxuanzeqi',
+    options: {
+      defaultValue: [],
+      width: '',
+      placeholder: '',
+      disabled: false,
+      clearable: false,
+      options: [
+        {
+          value: '总部',
+          label: '总部',
+          children: [
+            { value: '技术部', label: '技术部' },
+            { value: '财务部', label: '财务部' }
+          ]
+        },
+        {
+          value: '分公司',
+          label: '分公司',
+          children: [
+            { value: '华东分公司', label: '华东分公司' }
+          ]
+        }
+      ],
+      remote: true,
+      remoteType: 'datasource',
+      remoteDataSource: 'getDeptTree',
+      remoteOption: '',
+      remoteOptions: [],
+      props: {
+        value: 'id',
+        label: 'name',
+        children: 'children'
+      },
+      remoteFunc: '',
+      customClass: '',
+      labelWidth: 100,
+      isLabelWidth: false,
+      hidden: false,
+      dataBind: true,
+      required: false,
+      validatorCheck: false,
+      validator: '',
+      multiple: true,
+      filterable: false,
+      checkStrictly: false,
+      customProps: {},
+      tip: '',
+      extendProps: {}
+    },
+    events: {
+      onMounted: '',
+      onChange: '',
+      onFocus: '',
+      onBlur: ''
+    }
+  },
   {
     type: 'steps',
     icon: 'icon-m-buzhou',

+ 49 - 0
lib/vue-form-making-v3/src/components/defaultDataSource.js

@@ -0,0 +1,49 @@
+import {getToken} from "../util/token";
+
+const token = getToken();
+
+// 默认数据源(与 vue-form-making 保持一致)
+// deptCascader / deptAndUserCascader 等控件默认使用 getDeptTree 拉取部门树
+export const defaultDataSource = [
+  {
+    key: "getGroupUserTree",
+    name: "部门人员",
+    url: "/api/main/group/getGroupUserTree",
+    method: "GET",
+    auto: true,
+    params: {},
+    headers: token,
+    responseFunc: "return res.data;",
+    requestFunc: "return config;",
+    errorFunc: "",
+    args: []
+  },
+  {
+    key: "getUserPage",
+    name: "人员",
+    url: "/api/main/user/getUserPage",
+    method: "GET",
+    auto: true,
+    params: {
+      pageNum: "1", size: "-1"
+    },
+    headers: token,
+    responseFunc: "return res.data.list.map((item) => {\r\n        return {\r\n          value: item.id,\r\n          label: item.name\r\n        };\r\n      });",
+    requestFunc: "return config;",
+    errorFunc: "",
+    args: []
+  },
+  {
+    key: "getDeptTree",
+    name: "部门",
+    url: "/api/main/group/getGroupList",
+    method: "GET",
+    auto: true,
+    params: {},
+    headers: token,
+    responseFunc: "const data = [...res.data];\n     return data.reduce((acc, item) => {\n        const parent = data.find(i => i.id == item.parentId);\n        if (parent) {\n            if (!parent.children) {\n                parent.children = [];\n            }\n            parent.children.push(item);\n        } else {\n            acc.push(item);\n        }\n        return acc;\n    }, []);\n\n",
+    requestFunc: "return config;",
+    errorFunc: "",
+    args: []
+  }
+]

+ 1 - 0
lib/vue-form-making-v3/src/lang/en-us.js

@@ -33,6 +33,7 @@ export default {
         steps: 'Steps',
         transfer: 'Transfer',
         treeselect: 'TreeSelect',
+        deptCascader: 'Department Cascader',
         alert: 'Alert',
         subform: 'Sub-Form +',
         custom: 'Custom',

+ 1 - 0
lib/vue-form-making-v3/src/lang/zh-cn.js

@@ -33,6 +33,7 @@ export default {
         steps: '步骤条',
         transfer: '穿梭框',
         treeselect: '树选择',
+        deptCascader: '部门级联',
         alert: '提示',
         subform: '子表单+',
         custom: '自定义',

+ 15 - 0
lib/vue-form-making-v3/src/util/token.js

@@ -0,0 +1,15 @@
+// token 存储的名称
+export const TOKEN_STORE_NAME = window.__POWERED_BY_QIANKUN__
+  ? 'token'
+  : `token`;
+
+/**
+ * 获取缓存的 token
+ */
+export function getToken() {
+  const token = localStorage.getItem(TOKEN_STORE_NAME);
+  if (!token) {
+    return {'Authorization': sessionStorage.getItem(TOKEN_STORE_NAME)} ;
+  }
+  return {'Authorization': token};
+}

+ 12 - 7
src/views/bpm/handleTask/components/saleOrder/saleReturnGoods/submit.vue

@@ -171,18 +171,23 @@
         }
         // 入库来源isSkip 0-正常  1-外部(外部跳过内部审核流程)
         storageData.isSkip = 1;
-  
         try {
           this.isSaveLoading = true;
           if (storageData?._packingList?.length) {
             res.productList.forEach((val, index) => {
-              val.receiveTotalWeight = storageData._packingList[index].weight;
-              val.materielDesignation =
-                storageData._packingList[index].materielDesignation;
-              val.clientCode = storageData._packingList[index].clientCode;
-              val.engrave = storageData._packingList[index].engrave;
+              storageData._packingList.forEach((item, iindex) => {
+                if(item.productCode == val.categoryCode){
+                  val.receiveTotalWeight = item.weight;
+                  val.materielDesignation =
+                    item.materielDesignation;
+                  val.clientCode = item.clientCode;
+                  val.engrave = item.engrave;
+                }
+              })
+              
             });
           }
+          // console.log('storageData~~~!!!', storageData);
           await UpdateReturnInformation(res);
           await storageApi.storage(storageData);
           approveTaskWithVariables({
@@ -202,7 +207,7 @@
           });
         } catch (error) {
           this.isSaveLoading = false;
-          this.$message.error('保存失败');
+          this.$message.error('保存失败', error);
         }
       },
 

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio