Jelajahi Sumber

功能优化

songxy 1 tahun lalu
induk
melakukan
823e26b8cd

+ 2 - 2
client/.env.dev

@@ -4,8 +4,8 @@ NODE_ENV=development
 VITE_DEV=false
 
 # 请求路径
-VITE_BASE_URL='http://10.10.9.113:48080'
-# VITE_BASE_URL='http://10.10.10.7:48080'
+# VITE_BASE_URL='http://10.10.9.113:48080'
+VITE_BASE_URL='http://10.10.10.7:48080'
 
 # VITE_BASE_URL='http://10.10.9.168:48080'
 

TEMPAT SAMPAH
client/src/assets/imgs/user_icon.png


TEMPAT SAMPAH
client/src/assets/imgs/xzq_icon.png


+ 0 - 32
client/src/components/AreaSelectTree/index.vue

@@ -1,32 +0,0 @@
-<script lang="ts" setup>
-/**
- * @description 行政区选择树
- */
-import { getAreaTree } from '@/service/system'
-
-const treeData = ref([])
-const checkCode = ref('')
-onMounted(async () => {
-  const data = await getAreaTree()
-  treeData.value = data
-})
-</script>
-<template>
-  <el-tree-select
-    v-model="checkCode"
-    node-key="id"
-    check-strictly
-    filterable
-    clearable
-    default-expand-all
-    :props="{ label: 'name' }"
-    :data="treeData"
-    :multiple="false"
-    class="select-tree"
-  />
-</template>
-<style scoped lang="scss">
-.select-tree {
-  width: 100%;
-}
-</style>

+ 112 - 26
client/src/components/TreeSelectV2/index.vue

@@ -1,26 +1,41 @@
 <template>
   <div class="treeSelectV2">
-    <el-popover placement="bottom" trigger="click" :teleported="false">
+    <el-popover placement="bottom" :visible="visiable" @hide="visiable = false" :teleported="false">
       <template #reference>
-        <el-input v-model="xzqdmName" readonly :disabled="disabled">
+        <el-input
+          v-model="labelName"
+          @input="onQueryFilter"
+          @mouseenter="mouseHandler(1)"
+          @mouseleave="mouseHandler(0)"
+          @click="clickHander"
+          :disabled="disabled"
+          :placeholder="placeholder"
+        >
           <template #suffix>
-            <el-icon><ArrowDown /></el-icon>
+            <el-icon v-if="labelName && isHover">
+              <CircleClose @click="clearHandler" />
+            </el-icon>
+            <el-icon :class="{ rotate: isRotate }" v-else>
+              <ArrowDown />
+            </el-icon>
           </template>
         </el-input>
       </template>
       <template #default>
-        <template v-if="filterMethod != null">
-          <el-input v-model="filterName" @input="onQueryFilter" style="margin-bottom: 10px" />
-        </template>
         <el-tree-v2
           ref="treeRef"
-          @node-click="nodeClickHandle"
+          highlight-current
           style="width: 100%"
           :filter-method="filterMethod"
           :props="props"
           :data="data"
-          :render-after-expand="expend"
-        />
+          :expand-on-click-node="false"
+          @node-click="nodeClickHandle"
+        >
+          <template v-if="$slots.default" #default="{ node }">
+            <slot :node="node"></slot>
+          </template>
+        </el-tree-v2>
       </template>
     </el-popover>
   </div>
@@ -33,34 +48,97 @@ import { ArrowDown } from '@element-plus/icons-vue'
 defineOptions({
   name: 'TreeSelectV2'
 })
-const $props = defineProps<
-  Partial<{
-    data: any[]
-    modelValue: string | number
-    props: any
-    disabled: boolean
-    expend: boolean
-    filterMethod: any
-  }>
->()
+const $props = withDefaults(
+  defineProps<
+    Partial<{
+      data: any[]
+      modelValue: string | number
+      props: any
+      disabled: boolean
+      expend: boolean
+      filterMethod: any
+      placeholder: string
+    }>
+  >(),
+  {
+    props: {
+      label: 'label',
+      value: 'value',
+      children: 'children'
+    },
+    expend: true,
+    placeholder: '请选择'
+  }
+)
 const $emit = defineEmits<{
   (e: 'update:modelValue', v: any): void
 }>()
-const xzqdmName = ref<string>()
-const filterName = ref<string>()
-
+const visiable = ref<boolean>(false)
+const isRotate = ref<boolean>(false)
+const labelName = ref<string>('')
+const isHover = ref<boolean>(false)
+const mouseHandler = (type: number) => {
+  isHover.value = type === 1 ? true : false
+}
+const clickHander = () => {
+  visiable.value = !visiable.value
+}
+const clearHandler = () => {
+  nodeClickHandle({
+    [$props.props['value'] ?? 'value']: '',
+    [$props.props['label'] ?? 'label']: ''
+  })
+  onQueryFilter('')
+}
+watch(visiable, () => {
+  isRotate.value = visiable.value ? true : false
+})
 const treeRef = ref<InstanceType<typeof ElTreeV2>>()
 const onQueryFilter = (query: string) => {
   treeRef.value!.filter(query)
 }
 const nodeClickHandle = (data) => {
-  xzqdmName.value = data['name']
-  $emit('update:modelValue', data['id'])
+  visiable.value = false
+  labelName.value = data[$props.props['label'] ?? 'label']
+  $emit('update:modelValue', data[$props.props['value'] ?? 'value'])
+}
+const getExpandedIds = (nodes?: any[]) => {
+  if (nodes && nodes.length === 0) return []
+  const ids: any[] = []
+  function getIdByDfs(nodes) {
+    for (let i = 0; i < nodes.length; i++) {
+      const node = nodes[i]
+      if (
+        !node[$props.props['children'] ?? 'children'] ||
+        node[$props.props['children'] ?? 'children'].length == 0
+      )
+        break
+      ids.push(node[$props.props['value'] ?? 'value'])
+      if (
+        node[$props.props['children'] ?? 'children'] &&
+        node[$props.props['children'] ?? 'children'].length > 0
+      ) {
+        getIdByDfs(node[$props.props['children'] ?? 'children'])
+      }
+    }
+  }
+  getIdByDfs(nodes)
+  return ids
+}
+const setExpandedKeys = async () => {
+  await nextTick()
+  const allChooseIds = getExpandedIds($props.data)
+  treeRef.value?.setExpandedKeys(allChooseIds)
 }
+watchEffect(() => {
+  if ($props.data && $props.expend) {
+    setExpandedKeys()
+  }
+})
 watchEffect(() => {
   const item = treeRef.value?.getNode($props.modelValue)
   if (item) {
-    xzqdmName.value = item['label']
+    labelName.value = item['label'] as string
   }
 })
 </script>
@@ -84,8 +162,16 @@ watchEffect(() => {
   }
   :deep(.is-focus) {
     .el-input__suffix .el-icon {
-      transform: rotateZ(-180deg);
       cursor: pointer;
+      transform: rotateZ(0);
+    }
+  }
+  .rotate {
+    transform: rotateZ(-180deg) !important;
+  }
+  :deep(.el-tree-node__content) {
+    .is-leaf {
+      flex-shrink: 0;
     }
   }
 }

+ 0 - 2
client/src/components/UserSelect/index.vue

@@ -112,8 +112,6 @@ const checkOnChange = (data) => {
       :filter-node-method="filterNodeMethod"
       :render-after-expand="false"
       :default-expand-all="true"
-      collapse-tags
-      collapse-tags-tooltip
       :show-checkbox="multiple"
       :check-strictly="false"
       filterable

+ 4 - 2
client/src/service/system.ts

@@ -15,7 +15,8 @@ export const getAllUserSimpleByList = async () => {
         label: item['name'],
         value: item['id'],
         parentId: item['parentId'],
-        children: item['children']
+        children: item['children'],
+        type: item['type']
       }
     }),
     'value'
@@ -36,7 +37,8 @@ export const getAllUserSimpleByListByDeptId = async (params: { deptId: string })
         label: item['name'],
         value: item['id'],
         parentId: item['parentId'],
-        children: item['children']
+        children: item['children'],
+        type: item['type']
       }
     }),
     'value'

+ 29 - 1
client/src/views/OaSystem/components/DistrictTree/index.vue

@@ -4,9 +4,16 @@
       :data="areaTree"
       :props="{ label: 'name', value: 'id' }"
       v-model="xzqdm"
+      :expend="expend"
       :filter-method="filterNodeMethod"
       :disabled="disabled"
-    />
+      :placeholder="placeholder"
+    >
+      <template #default="{ node }">
+        <span class="prefix"> </span>
+        <span>{{ node.label }}</span>
+      </template>
+    </TreeSelectV2>
   </div>
 </template>
 
@@ -27,6 +34,14 @@ const props = defineProps({
   modelValue: {
     type: [Number, String],
     default: null
+  },
+  expend: {
+    type: Boolean,
+    default: true
+  },
+  placeholder: {
+    type: String,
+    default: '请选择'
   }
 })
 const emit = defineEmits<{ (e: 'update:modelValue', v: any): void }>()
@@ -63,5 +78,18 @@ const { data: areaTree } = useQuery([getAreaTree.name], getAreaTree)
       cursor: pointer;
     }
   }
+  .prefix {
+    display: inline-block;
+    margin-right: 3px;
+    width: 16px;
+    height: 16px;
+    background: url('@/assets/imgs/xzq_icon.png') no-repeat;
+    background-size: 100% 100%;
+  }
+  :deep(.el-tree-node__content) {
+    .prefix {
+      flex-shrink: 0;
+    }
+  }
 }
 </style>

+ 110 - 0
client/src/views/OaSystem/components/UserOrgTree/index copy.vue

@@ -0,0 +1,110 @@
+<template>
+  <div class="treeSelectV2">
+    <TreeSelectV2
+      :data="allUserList"
+      v-model="receiveUserId"
+      :expend="defaultExpandAll"
+      :filter-method="filterNodeMethod"
+      :disabled="disabled"
+      :placeholder="placeholder"
+    >
+      <template #default="{ node }">
+        <span class="prefix"> </span>
+        <span>{{ node.label }}</span>
+      </template>
+    </TreeSelectV2>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { useQuery } from '@tanstack/vue-query'
+import { getAllUserSimpleByList, getAllUserSimpleByListByDeptId } from '@/service/system'
+
+defineOptions({ name: 'UserOrgTree' })
+interface PropsType {
+  disabled: boolean
+  modelValue: any
+  clearable: boolean
+  defaultExpandAll: boolean
+  deptId: string
+  placeholder: string
+}
+const props = withDefaults(defineProps<PropsType>(), {
+  disabled: false,
+  defaultExpandAll: true,
+  clearable: true,
+  deptId: '',
+  placeholder: '请选择'
+})
+const emit = defineEmits<{
+  (e: 'update:modelValue', v: string): void
+  (e: 'nodeClick', v: any): void
+}>()
+const receiveUserId = computed({
+  get: () => props.modelValue,
+  set: (nVal: string) => emit('update:modelValue', nVal)
+})
+console.log('receiveUserId----------------')
+console.log(receiveUserId)
+async function queryUserSimpleByList() {
+  if (!props.deptId) {
+    return await getAllUserSimpleByList()
+  } else {
+    return await getAllUserSimpleByListByDeptId({
+      deptId: props.deptId
+    })
+  }
+}
+const { data: allUserList } = useQuery(['list-all-user-simple'], queryUserSimpleByList, {
+  staleTime: Infinity
+})
+console.log()
+const filterNodeMethod = (value, data) => {
+  if (!data) return
+  return data.label.includes(value)
+}
+const nodeClickHandler = (data) => {
+  emit('nodeClick', data)
+}
+</script>
+<style lang="scss" scoped>
+.treeSelectV2 {
+  position: relative;
+
+  :deep(.el-popper) {
+    width: 100% !important;
+    left: 0px !important;
+    right: 0px !important;
+  }
+
+  :deep(.el-input__suffix) {
+    .el-icon {
+      color: var(--el-select-input-color);
+      font-size: var(--el-select-input-font-size);
+      transition: transform var(--el-transition-duration);
+      transform: rotateZ(0);
+      cursor: pointer;
+    }
+  }
+
+  :deep(.is-focus) {
+    .el-input__suffix .el-icon {
+      transform: rotateZ(-180deg);
+      cursor: pointer;
+    }
+  }
+  .prefix {
+    display: inline-block;
+    margin-right: 3px;
+    width: 16px;
+    height: 16px;
+    background: url('@/assets/imgs/xzq_icon.png') no-repeat;
+    background-size: 100% 100%;
+  }
+  :deep(.el-tree-node__content) {
+    .prefix {
+      flex-shrink: 0;
+    }
+  }
+}
+</style>

+ 21 - 1
client/src/views/OaSystem/components/UserOrgTree/index.vue

@@ -9,7 +9,12 @@
     :clearable="clearable"
     filterable
     @node-click="nodeClickHandler"
-  />
+  >
+    <template #default="{ data: { label, type } }">
+      <span :class="{ item_icon: true, user: type === 'user' }"> </span>
+      {{ label }}
+    </template>
+  </el-tree-select>
 </template>
 
 <script setup lang="ts">
@@ -56,3 +61,18 @@ const nodeClickHandler = (data) => {
   emit('nodeClick', data)
 }
 </script>
+
+<style scoped lang="scss">
+.item_icon {
+  display: inline-block;
+  margin-right: 3px;
+  width: 16px;
+  height: 16px;
+  background-image: url('@/assets/imgs/xzq_icon.png');
+  background-repeat: no-repeat;
+  background-size: 100% 100%;
+  &.user {
+    background-image: url('@/assets/imgs/user_icon.png');
+  }
+}
+</style>

+ 24 - 7
client/src/views/OaSystem/home/components/CardItemTwo.vue

@@ -16,6 +16,7 @@
 </template>
 
 <script setup lang="ts">
+import request from '@/config/axios'
 import FuncOperation from './FuncOperation.vue'
 // 获取assets静态资源
 const getAssetURL = (url: string) => {
@@ -30,13 +31,12 @@ const functions = ref<
     key: string
   }[]
 >([
-  { title: '差旅报销', icon: 'clvbx-icon', key: '' },
-  { title: '普通报销', icon: 'ptbx-icon', key: '' },
-  { title: '请假申请', icon: 'yksq-icon', key: '' },
-  { title: '考勤说明条', icon: 'htqd-icon', key: '' },
-  { title: '出差申请', icon: 'kpsq-icon', key: '' },
-  { title: '盖章申请', icon: 'kpsq-icon', key: '' }
-  // { title: '添加功能', icon: 'tjgn-icon', key: 'addFunction' }
+  { title: '差旅报销', icon: 'clvbx-icon', key: '018d7305392d0a07e1f88d5e36cc01c9' },
+  { title: '普通报销', icon: 'ptbx-icon', key: '018c5ccc82c60947f6bd8c5ccc800001' },
+  { title: '请假申请', icon: 'yksq-icon', key: '018c1f593f2c09477b1b8c1080b6000b' },
+  { title: '考勤说明条', icon: 'htqd-icon', key: '018c24045d65094794178c23e986001e' },
+  { title: '出差申请', icon: 'kpsq-icon', key: '018c389986fb0947969a8c33d89b000a' },
+  { title: '盖章申请', icon: 'kpsq-icon', key: '018de899ff700a0796ba8dd062c80302' }
 ])
 const $emit = defineEmits<{
   (e: 'click', val: any): void
@@ -45,6 +45,23 @@ const clickHandle = (item): void => {
   if (item['title'] === '添加功能') {
     showFuncModal.value = true
   }
+  createProcessById(item['key']).then((result) => {
+    console.log('result-------------------')
+    console.log(result)
+  })
+}
+
+/** 发起流程 */
+const createProcessById = async (templateId: string) => {
+  return await request.post(
+    {
+      url: `/TProcessEngine/addPC`,
+      params: {
+        templateId: templateId
+      }
+    },
+    'workflow'
+  )
 }
 const changeHandle = (item) => {
   console.log(item)

+ 2 - 2
client/src/views/OaSystem/marketCenter/khglPage/SearchForm.vue

@@ -10,7 +10,7 @@
     </div>
     <div class="form area">
       <span class="formSpan">行政区:</span>
-      <AreaSelectTree v-model="queryParams.xzqdm" />
+      <DistrictTree v-model="queryParams.xzqdm" />
     </div>
     <div class="form type">
       <span class="formSpan">客户类型:</span>
@@ -43,7 +43,7 @@
  * @description 查询表单
  */
 
-import AreaSelectTree from '@/components/AreaSelectTree/index.vue'
+import DistrictTree from '@/views/OaSystem/components/DistrictTree/index.vue'
 import PubsubService from '@/utils/PubsubService'
 import { getDictOptions } from '@/utils/dict'
 import CompanySelect from '../khxjPage/CompanySelect.vue'

+ 2 - 2
client/src/views/OaSystem/marketCenter/khxjPage/index.vue

@@ -52,7 +52,7 @@
           <tr>
             <td class="th">所属区域:</td>
             <td>
-              <AreaSelectTree v-model="queryParams.xzqdm" />
+              <DistrictTree v-model="queryParams.xzqdm" />
             </td>
             <td class="th">联系地址:</td>
             <td><el-input clearable v-model="queryParams.address" /></td>
@@ -159,7 +159,7 @@
  * @description 新建客户
  */
 import request from '@/config/axios'
-import AreaSelectTree from '@/components/AreaSelectTree/index.vue'
+import DistrictTree from '@/views/OaSystem/components/DistrictTree/index.vue'
 import { ICustomer, IContacts } from '../interface'
 import { getDictOptions } from '@/utils/dict'
 import CompanySelect from './CompanySelect.vue'

+ 2 - 9
client/src/views/OaSystem/projectCenter/projectBook/deptProject.vue

@@ -12,15 +12,7 @@
       <div class="form">
         <span class="formSpan">行政区:</span>
         <div style="width: 160px">
-          <el-tree-select
-            v-model="queryParams.xzqdm"
-            node-key="id"
-            check-strictly
-            filterable
-            :filter-node-method="filterNodeMethod"
-            :props="{ label: 'name' }"
-            :data="areaTree"
-          />
+          <DistrictTree v-model="queryParams.xzqdm" />
         </div>
       </div>
       <div class="form">
@@ -154,6 +146,7 @@
 </template>
 <script setup lang="ts">
 import { useRouter } from 'vue-router'
+import DistrictTree from '@/views/OaSystem/components/DistrictTree/index.vue'
 import { DICT_TYPE, getDictLabel, getDictOptions } from '@/utils/dict'
 import { useMixins, infoList } from './common'
 import request from '@/config/axios'

+ 0 - 1
client/src/views/OaSystem/projectCenter/projectDetail/components/xmxx/index.vue

@@ -345,7 +345,6 @@ const saveChildProject = () => {
 const saveProjectHandle = (type: number): void => {
   if (type === 0 && !isMaster) return
   const obj = {
-    xzqdm: parentProjectDetail.xzqdm,
     projectTypeId: parentProjectDetail.projectTypeId,
     projectTypeName: parentProjectDetail.projectTypeName
   }

+ 29 - 0
zjugis-workflow/src/main/java/com/zjugis/z_workflow/controller/TProcessEngineController.java

@@ -12,6 +12,8 @@ import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.ResponseBody;
 
+import java.util.Map;
+
 /**
  * 新建流程控制器
  * @author: Administrator
@@ -73,4 +75,31 @@ public class TProcessEngineController extends BaseController {
         processCreateDto.setStart(true);
         return ok(processEngineService.createProcessInstance(processCreateDto));
 	}
+
+    /**
+     * 新建业务流程
+     * @param flowInstanceId
+     * @param templateId
+     * @param fatherFlowActivityId
+     * @return
+     * @throws Exception
+     */
+    @RequestMapping
+    @ResponseBody
+    public Map addPC(String flowInstanceId, String templateId, String fatherFlowActivityId) throws Exception {
+
+
+        boolean flag = false;
+        if("temp".equals(flowInstanceId)){
+            flowInstanceId = null;
+            flag = true;
+        }
+        ProcessCreateDto processCreateDto = new ProcessCreateDto(templateId, Constant.getUserId(),
+                null, fatherFlowActivityId, null, null, null, flowInstanceId);
+        if(flag){
+            processCreateDto.setHandleAuthority(1);
+        }
+        processCreateDto.setStart(true);
+        return result(processEngineService.createProcessInstance(processCreateDto));
+    }
 }

+ 11 - 3
zjugis-workflow/src/main/resources/templates/HandlerCaseCenter/js/index.js

@@ -94,14 +94,22 @@ var windowid;
         	var htmlStr = "<ul>";
         	for(var i = 0; i < arr.length; i++){
         		var item = arr[i]
+				if(item['name'] === '项目相关'){
+					if(item['children']){
+						for(var n = 0; n < item['children'].length; n++){
+                            if(['开票申请', '分包申请', '外包申请', '合同签订', '项目验收', '项目结项', '分包合同签订', '外包合同签订'].indexOf(item['children'][n]['name']) != -1){
+                                item['children'].splice(n, 1);
+                                n--;
+                                continue;
+                            }
+						}
+					}
+				}
         		if(item['children'] && item['children'].length > 0){
                     htmlStr += `<li><p class="title">${item["name"]}</p>`;
         			htmlStr += `<div class="process_list">`;
         			for(var j = 0; j < item['children'].length; j++){
         				var cItem = item['children'][j]
-                        if(['开票申请', '分包申请', '外包申请', '合同签订', '项目验收', '项目结项', '分包合同签订', '外包合同签订'].indexOf(cItem['name']) != -1){
-                        	continue;
-						}
 						htmlStr += `<div class="process_item" data-id="${cItem['id']}" data-name="${cItem['name']}">${cItem['name']}</div>`
 					}
 					htmlStr += '</div>';