ZaiZai hai 1 ano
pai
achega
60abbf00d8

+ 1 - 1
public/version.json

@@ -1,3 +1,3 @@
 {
-  "value": "20231024162420"
+  "value": "20231025110649"
 }

+ 468 - 0
src/components/hc-tasks-user/index.vue

@@ -0,0 +1,468 @@
+<template>
+    <div :class="ui" class="hc-tasks-user">
+        <div class="tasks-user-box">
+            <div class="tag-user-list" @click="showModalClick">
+                <template v-for="(item, index) in UserDataList" :key="index">
+                    <el-tag>{{ setCheckboxUserName(item) }}</el-tag>
+                    <HcIcon v-if="(UserDataList.length - 1) > index" name="arrow-right" ui="arrow-icon-tag" />
+                </template>
+                <div v-if="UserDataList.length <= 0" class="tasks-placeholder">点击这里选择任务人</div>
+            </div>
+        </div>
+
+        <!-- 选择任务人 -->
+        <hc-new-dialog v-model="showModal" ui="hc-modal-border hc-modal-nop" title="选择任务人" widths="62rem">
+            <div class="hc-tasks-user-modal-content-box">
+                <div class="tree-box">
+                    <el-scrollbar>
+                        <ElTree
+                            v-if="isShowTree"
+                            :data="ElTreeData" :default-expanded-keys="[0]" :props="ElTreeProps" accordion
+                            class="hc-tree-node-box" highlight-current node-key="roleId"
+                            @node-click="ElTreeNodeClick"
+                        />
+                    </el-scrollbar>
+                </div>
+                <div class="user-box">
+                    <div class="y-user-list-box">
+                        <div class="title-box">
+                            <div class="title">
+                                可选择
+                            </div>
+                        </div>
+                        <div class="user-list">
+                            <el-scrollbar>
+                                <el-checkbox-group v-model="checkboxUserList">
+                                    <template v-for="item in signUserList">
+                                        <div class="user-item checkbox-li">
+                                            <el-checkbox
+                                                :label="`${item.certificateUserName}-${item.certificateUserId}`"
+                                            >
+                                                <div class="item-user-name">
+                                                    {{ item.certificateUserName }}
+                                                </div>
+                                            </el-checkbox>
+                                        </div>
+                                    </template>
+                                </el-checkbox-group>
+                            </el-scrollbar>
+                        </div>
+                    </div>
+                    <div class="s-user-list-box">
+                        <div class="title-box">
+                            <div class="title">
+                                已选择({{ checkboxUserList.length }})
+                            </div>
+                            <el-button plain size="small" @click="sequenceModal = true">
+                                调整顺序
+                            </el-button>
+                        </div>
+                        <div class="user-list">
+                            <el-scrollbar>
+                                <template v-for="(item, index) in checkboxUserList" :key="index">
+                                    <el-tag closable @close="delCheckboxUser(index)">
+                                        {{ setCheckboxUserName(item) }}
+                                    </el-tag>
+                                </template>
+                            </el-scrollbar>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <template #footer>
+                <div class="dialog-footer">
+                    <el-button size="large" @click="showModal = false">
+                        <HcIcon name="close" />
+                        <span>取消</span>
+                    </el-button>
+                    <el-button :loading="sureSignUserLoading" hc-btn type="primary" @click="sureSignUserClick">
+                        <HcIcon name="check" />
+                        <span>确定</span>
+                    </el-button>
+                </div>
+            </template>
+        </hc-new-dialog>
+
+        <!-- 调整顺序 -->
+        <hc-new-dialog v-model="sequenceModal" ui="hc-modal-border" title="调整顺序" widths="38rem">
+            <el-alert :closable="false" title="可拖动排序,也可在后面点击图标,切换排序" type="warning" />
+            <div class="sort-node-body-box list-group header">
+                <div class="list-group-item">
+                    <div class="index-box">
+                        序号
+                    </div>
+                    <div class="title-box">
+                        任务人
+                    </div>
+                    <div class="icon-box">
+                        排序
+                    </div>
+                </div>
+            </div>
+            <Draggable
+                :list="checkboxUserList" class="sort-node-body-box list-group" ghost-class="ghost" item-key="id"
+                @end="sortNodeDrag = false" @start="sortNodeDrag = true"
+            >
+                <template #item="{ element, index }">
+                    <div class="list-group-item">
+                        <div class="index-box">
+                            {{ index + 1 }}
+                        </div>
+                        <div class="title-box">
+                            {{ setCheckboxUserName(element) }}
+                        </div>
+                        <div class="icon-box">
+                            <span class="icon" @click="downSortClick(index)">
+                                <HcIcon name="arrow-down" ui="text-lg" />
+                            </span>
+                            <span class="icon" @click="upSortClick(index)">
+                                <HcIcon name="arrow-up" ui="text-lg" />
+                            </span>
+                        </div>
+                    </div>
+                </template>
+            </Draggable>
+            <template #footer>
+                <div class="dialog-footer">
+                    <el-button size="large" @click="sequenceModal = false">
+                        取消
+                    </el-button>
+                    <el-button hc-btn type="primary" @click="sequenceModal = false">
+                        确认
+                    </el-button>
+                </div>
+            </template>
+        </hc-new-dialog>
+    </div>
+</template>
+
+<script setup>
+import { onMounted, ref, watch } from 'vue'
+//import tasksFlowApi from '~api/tasks/flow'
+import { deepClone, getArrValue } from 'js-fast-way'
+//import { checkCustomFlowUserIsEVisaPermissions, checkCustomFlowUserIsEVisaPermissionsquery } from '~api/other'
+import Draggable from 'vuedraggable'
+
+//参数
+const props = defineProps({
+    ui: {
+        type: String,
+        default: '',
+    },
+    //选中的用户数组
+    users: {
+        type: String,
+        default: '',
+    },
+    projectId: {
+        type: [String, Number],
+        default: '',
+    },
+    contractId: {
+        type: [String, Number],
+        default: '',
+    },
+    type: { //first,log,wbs
+        type: [String, Number],
+        default: '',
+    },
+    typeData: {
+        type: [String, Number, Array, Object],
+        default: '',
+    },
+    classifyType: {
+        type: [String, Number],
+        default: '',
+    },
+    tableOwner: {
+        type: [String, Number],
+        default: '',
+    },
+    nodeId: {
+        type: [String, Number],
+        default: '', //选中节点nodeid
+    },
+    infoIds:{
+        type: [String, Number],
+        default: '', //上报任务ID
+    },
+
+})
+
+//事件
+const emit = defineEmits(['change'])
+//变量
+const showModal = ref(false)
+const sequenceModal = ref(false)
+const checkboxUserList = ref([])
+const UserDataList = ref([])
+const projectId = ref(props.projectId)
+const contractId = ref(props.contractId)
+const isTypes = ref(props.type)
+const typeDatas = ref(props.typeData)
+const classifyType = ref(props.classifyType)
+const tableOwner = ref(props.tableOwner)
+const nodeId = ref(props.nodeId)
+const infoIds = ref(props.infoIds)
+
+//树数据
+const ElTreeProps = { children: 'childRoleList', label: 'roleName' }
+const ElTreeData = ref([{
+    roleName: '全部人员',
+    roleId: 0,
+    childRoleList: [],
+    signPfxFileList: [],
+}])
+const isShowTree = ref(true)
+//监听
+watch(() => [
+    props.users,
+    props.projectId,
+    props.contractId,
+    props.type,
+    props.typeData,
+    props.classifyType,
+    props.tableOwner,
+    props.nodeId,
+    props.infoIds,
+], ([users, pid, cid, type, data, cla, tab, noid, infoid]) => {
+    projectId.value = pid
+    contractId.value = cid
+    isTypes.value = type
+    typeDatas.value = data
+    setUserDataList(users)
+    classifyType.value = cla
+    tableOwner.value = tab
+    nodeId.value = noid
+    infoIds.value = infoid
+})
+
+//渲染完成
+onMounted(() => {
+    setUserDataList(props.users)
+    queryAllRoleList()
+})
+
+//处理用户数据
+const setUserDataList = (users) => {
+    if (users) {
+        const usersArr = users.split(',')
+        UserDataList.value = usersArr
+        checkboxUserList.value = usersArr
+    } else {
+        UserDataList.value = []
+        checkboxUserList.value = []
+    }
+}
+
+//展开弹窗
+const showModalClick = () => {
+    showModal.value = true
+}
+
+//获取系统所有角色划分
+const signUserList = ref([])
+const queryAllRoleList = async () => {
+    isShowTree.value = false
+    /*const { error, code, data } = await tasksFlowApi.queryAllRoleList({
+        contractId: contractId.value,
+    })
+    isShowTree.value = true
+    //处理数据
+    if (!error && code === 200) {
+        let signList = [], dataArr = getArrValue(data)
+        ElTreeData.value[0].childRoleList = dataArr
+        if (dataArr.length > 0) {
+            dataArr.forEach(item => {
+                signList = signList.concat(item.signPfxFileList)
+            })
+        }
+        ElTreeData.value[0].signPfxFileList = signList
+        signUserList.value = signList
+    } else {
+        signUserList.value = []
+        ElTreeData.value[0].childRoleList = []
+        ElTreeData.value[0].signPfxFileList = []
+    }*/
+}
+
+//树被点击
+const ElTreeNodeClick = (data) => {
+    signUserList.value = getArrValue(data?.signPfxFileList)
+}
+
+//处理已选择的用户问题
+const setCheckboxUserName = (item) => {
+    if (item) {
+        const itemArr = item.split('-')
+        if (itemArr.length > 0 && itemArr[0]) {
+            return itemArr[0]
+        } else {
+            return ''
+        }
+    } else {
+        return ''
+    }
+}
+
+//删除已选择的用户
+const delCheckboxUser = (index) => {
+    checkboxUserList.value.splice(index, 1)
+}
+
+//排序
+const sortNodeDrag = ref(false)
+//向下
+const downSortClick = (index) => {
+    const indexs = index + 1
+    const data = checkboxUserList.value
+    if (indexs !== data.length) {
+        const tmp = data.splice(indexs, 1)
+        checkboxUserList.value.splice(index, 0, tmp[0])
+    } else {
+        window?.$message?.warning('已经处于置底,无法下移')
+    }
+}
+//向上
+const upSortClick = (index) => {
+    const data = checkboxUserList.value || []
+    if (index !== 0) {
+        const tmp = data.splice(index - 1, 1)
+        checkboxUserList.value.splice(index, 0, tmp[0])
+    } else {
+        window?.$message?.warning('已经处于置顶,无法上移')
+    }
+}
+
+//确认选择
+const sureSignUserLoading = ref(false)
+const sureSignUserClick = () => {
+    let type = isTypes.value, flowJson = {}, newUser = [], newUserId = [], users = ''
+    const dataList = deepClone(checkboxUserList.value)
+    UserDataList.value = dataList
+    if (dataList.length > 0) {
+        sureSignUserLoading.value = true
+        //判断类型
+        if (type === 'first') {
+            flowJson['firstId'] = typeDatas.value
+        } else if (type === 'log') {
+            flowJson['theLogPrimaryKeyId'] = typeDatas.value
+        } else if (type === 'wbs') {
+            flowJson['privatePKeyId'] = typeDatas.value
+        } else if (type === 'query') {
+            flowJson['privatePKeyId'] = typeDatas.value
+        }
+        //封装数据
+        dataList.forEach(item => {
+            const itemArr = item.split('-')
+            if (itemArr.length > 0 && itemArr[0]) {
+                users = users ? `${users},${item}` : item
+                newUser.push({
+                    userId: itemArr[1],
+                    userName: itemArr[0],
+                })
+                newUserId.push(itemArr[1])
+            }
+        })
+        //效验人员
+        if (type === 'first' || type === 'log' || type === 'wbs') {
+            getCheckCustomFlowUserIsEVisaPermissions(flowJson, newUser, newUserId, users)
+        } else if (type === 'query') {
+            getCheckCustomFlowUserIsEVisaPermissionsquery(flowJson, newUser, newUserId, users)
+        } else {
+            showModal.value = false
+            sureSignUserLoading.value = false
+            emit('change', newUser, newUserId, users)
+        }
+    } else {
+        window.$message?.warning('请先选择任务人员,或点击取消')
+    }
+}
+
+//检查所选的流程环节处理人是否具有审批权限(三大填报页、日志列表的批量上报、首件列表的批量上报)
+const getCheckCustomFlowUserIsEVisaPermissions = async (flowJson, newUser, newUserId, users) => {
+    /*const { error, code, data } = await checkCustomFlowUserIsEVisaPermissions({
+        projectId: projectId.value,
+        contractId: contractId.value,
+        customFlowUserList: newUserId,
+        ...flowJson,
+        classifyType:classifyType.value,
+        tableOwner:tableOwner.value,
+        nodeId:nodeId.value,
+
+    })
+    //处理数据
+    sureSignUserLoading.value = false
+    if (!error && code === 200 && data === true) {
+        showModal.value = false
+        emit('change', newUser, newUserId, users)
+    } else {
+        emit('change', [], [], '')
+    }*/
+}
+//资料查询页面
+const getCheckCustomFlowUserIsEVisaPermissionsquery = async (flowJson, newUser, newUserId, users) => {
+    /*const { error, code, data } = await checkCustomFlowUserIsEVisaPermissionsquery({
+        projectId: projectId.value,
+        contractId: contractId.value,
+        customFlowUserList: newUserId,
+        ...flowJson,
+        nodeId:nodeId.value,
+        classifyType:classifyType.value,
+        tableOwner:tableOwner.value,
+        infoIds:infoIds.value,
+    })
+    //处理数据
+    sureSignUserLoading.value = false
+    if (!error && code === 200 && data === true) {
+        showModal.value = false
+        emit('change', newUser, newUserId, users)
+    } else {
+        emit('change', [], [], '')
+    }*/
+}
+</script>
+
+<style lang="scss" scoped>
+@import './style.scss';
+</style>
+
+<style lang="scss">
+.hc-tasks-user .tasks-user-box .tag-user-list {
+    .el-tag {
+        --el-icon-size: 14px;
+        padding: 0 10px;
+        height: 26px;
+        margin: 4px 0;
+    }
+}
+.hc-tasks-user-modal-content-box {
+    .checkbox-li .el-checkbox {
+        width: 100%;
+        .el-checkbox__input {
+            position: absolute;
+            right: 0;
+            .el-checkbox__inner {
+                width: 18px;
+                height: 18px;
+                &:after {
+                    height: 9px;
+                    left: 6px;
+                    top: 2px;
+                }
+            }
+        }
+        .el-checkbox__label {
+            flex: 1;
+            padding-left: 0;
+            padding-right: 20px;
+        }
+    }
+    .user-list {
+        .el-tag {
+            margin-right: 10px;
+            margin-top: 12px;
+        }
+    }
+}
+</style>

+ 147 - 0
src/components/hc-tasks-user/style.scss

@@ -0,0 +1,147 @@
+.hc-tasks-user {
+    position: relative;
+    .tasks-user-box {
+        position: relative;
+        border: 1px solid #e0e0e6;
+        border-radius: 4px;
+        padding: 0 12px;
+        cursor: pointer;
+        min-height: 40px;
+        .tag-user-list {
+            position: relative;
+            display: flex;
+            align-items: center;
+            flex-flow: row wrap;
+            min-height: inherit;
+            .tasks-placeholder {
+                color: #a9abb2;
+                font-size: 14px;
+            }
+            .arrow-icon-tag {
+                position: relative;
+                color: #a9abb2;
+                font-size: 18px;
+                margin: 0 8px;
+            }
+        }
+    }
+}
+
+.hc-tasks-user-modal-content-box {
+    position: relative;
+    display: flex;
+    height: 460px;
+    .tree-box {
+        flex: 1;
+        user-select: none;
+        position: relative;
+        padding: 20px;
+        overflow: hidden;
+        border-right: 1px solid #EEEEEE;
+    }
+    .user-box {
+        flex: 2;
+        position: relative;
+        display: flex;
+        flex-direction: column;
+        .y-user-list-box, .s-user-list-box {
+            position: relative;
+            overflow: hidden;
+            display: flex;
+            flex-direction: column;
+            .title-box {
+                position: relative;
+                padding: 2px 24px;
+                display: flex;
+                align-items: center;
+                border-bottom: 1px solid #EEEEEE;
+                background-color: #F8F8F8;
+                color: #838791;
+                .title {
+                    flex: auto;
+                }
+            }
+            .user-list {
+                position: relative;
+                overflow: hidden;
+                padding: 0 24px;
+                .user-item {
+                    position: relative;
+                    padding: 4px 0;
+                }
+                .user-item + .user-item {
+                    border-top: 1px dashed #EEEEEE;
+                }
+            }
+        }
+        .y-user-list-box {
+            flex: 1;
+            .user-list {
+                flex: 1;
+            }
+        }
+        .s-user-list-box {
+            position: relative;
+            border-top: 1px solid #EEEEEE;
+            .user-list {
+                height: 6rem;
+            }
+        }
+    }
+}
+
+.sort-node-body-box.list-group {
+    position: relative;
+    min-height: 20px;
+    border: 1px solid #EEEEEE;
+    .list-group-item {
+        position: relative;
+        display: flex;
+        align-items: center;
+        padding: 6px 15px;
+        cursor: move;
+        transition: background 0.2s;
+        .index-box {
+            position: relative;
+            width: 50px;
+        }
+        .title-box {
+            position: relative;
+            padding-right: 24px;
+            flex: 1;
+        }
+        .icon-box {
+            position: relative;
+            font-size: 18px;
+            display: flex;
+            align-items: center;
+            .icon {
+                cursor: pointer;
+                display: flex;
+                align-items: center;
+            }
+        }
+        &:first-child .icon-box i:last-child,
+        &:last-child .icon-box i:first-child {
+            cursor: default;
+            color: #aaaaaa;
+        }
+        &:hover {
+            background: var(--el-color-primary-light-9);
+        }
+    }
+    .list-group-item + .list-group-item {
+        border-top: 1px solid #EEEEEE;
+    }
+    &.header {
+        border-bottom: 0;
+        .list-group-item {
+            cursor: default;
+            padding: 8px 15px;
+            background-color: #F8F8F8;
+            .index-box, .title-box, .icon-box {
+                font-size: 14px;
+            }
+        }
+    }
+}

+ 2 - 0
src/components/index.js

@@ -7,6 +7,7 @@ import HcInfoTableTd from './info-table/info-table-td.vue'
 import HcCharts from './echarts/echarts.vue'
 import HcTitle from './hc-title/hc-title.vue'
 import HcSearchInput from './search-input/search-input.vue'
+import HcTasksUser from './hc-tasks-user/index.vue'
 
 
 //注册全局组件
@@ -20,4 +21,5 @@ export const setupComponents = (App) => {
     App.component('HcCharts', HcCharts)
     App.component('HcTitle', HcTitle)
     App.component('HcSearchInput', HcSearchInput)
+    App.component('HcTasksUser', HcTasksUser)
 }

+ 101 - 6
src/views/tasks/flow.vue

@@ -1,19 +1,114 @@
 <template>
-    <div class="hc-layout-box">
-        1111
-    </div>
+    <hc-new-card>
+        <template #header>
+            <el-button hc-btn type="primary" @click="addFlowData">新建流程</el-button>
+        </template>
+        <template #extra>
+            <el-alert :closable="false" title="同一合同段内,只需要设置重复岗位的流程即可,其他任务岗位,系统将自动推送,无需创建更多任务流" type="error" />
+        </template>
+        <hc-table :column="tableColumn" :datas="tableData" :loading="tableLoading" is-new :index-style="{ width: 60 }">
+            <template #action="{ row }">
+                <el-link type="success" @click="handleTableEdit(row)">修改</el-link>
+                <el-link type="danger">删除</el-link>
+            </template>
+        </hc-table>
+        <template #action>
+            <hc-pages :pages="searchForm" @change="pageChange" />
+        </template>
+        <!-- 新增/编辑流程 弹框 -->
+        <hc-new-dialog v-model="showEditModal" :title="`${flowFormData.id ? '编辑' : '新增'}流程`" widths="40rem">
+            <el-form ref="formFlowRef" class="p-4" :model="flowFormData" :rules="formFlowRules" label-width="auto" size="large">
+                <el-form-item label="流程名称" prop="fixedFlowName">
+                    <el-input v-model="flowFormData.fixedFlowName" placeholder="请输入流程名称" />
+                </el-form-item>
+                <el-form-item label="任务人" prop="linkUserJoinString">
+                    <hc-tasks-user :contract-id="contractId" :project-id="projectId" :users="flowFormData.linkUserJoinString" ui="w-full" @change="tasksUserChange" />
+                </el-form-item>
+            </el-form>
+            <template #footer>
+                <div class="dialog-footer">
+                    <el-button size="large" @click="showEditModal = false">取消</el-button>
+                    <el-button :loading="sevaLoading" hc-btn type="primary" @click="saveFormClick">保存</el-button>
+                </div>
+            </template>
+        </hc-new-dialog>
+    </hc-new-card>
 </template>
 
 <script setup>
 import { onMounted, ref } from 'vue'
+import { useAppStore } from '~src/store'
+
+//变量
+const store = useAppStore()
+const projectId = ref(store.getProjectId)
+const contractId = ref(store.getContractId)
 
 //渲染完成
 onMounted(() => {
 
 })
-</script>
 
-<style lang="scss" scoped>
+//搜索表单
+const searchForm = ref({
+    key1: null, current: 1, size: 10, total: 0,
+})
+
+//分页
+const pageChange = ({ current, size }) => {
+    searchForm.value.current = current
+    searchForm.value.size = size
+}
+
+//表格数据
+const tableLoading = ref(false)
+const tableColumn = ref([
+    { key: 'fixedFlowName', name: '流程名称' },
+    { key: 'linkUserJoinString', name: '流程详情' },
+    { key: 'action', name: '操作', width: 94 },
+])
+const tableData = ref([
+    { fixedFlowName: '1111' },
+])
 
-</style>
+//新建流程
+const addFlowData = () => {
+    flowFormData.value = { id: '', fixedFlowName: '', linkUserJoinString: '' }
+    showEditModal.value = true
+}
 
+//编辑流程
+const handleTableEdit = async (row) => {
+    flowFormData.value = { id: '', fixedFlowName: '', linkUserJoinString: '' }
+    showEditModal.value = true
+}
+
+//新增编辑数据
+const showEditModal = ref(false)
+const formFlowRef = ref(null)
+const flowFormData = ref({ id: '', fixedFlowName: '', linkUserJoinString: '' })
+const formFlowRules = {
+    fixedFlowName: {
+        required: true,
+        trigger: 'blur',
+        message: '请输入流程名称',
+    },
+    linkUserJoinString: {
+        required: true,
+        trigger: 'blur',
+        message: '请选择任务人',
+    },
+}
+
+//任务人选择改变
+const tasksUserChange = (a, b, users) => {
+    flowFormData.value.linkUserJoinString = users
+}
+
+//提交保存
+const sevaLoading = ref(false)
+const saveFormClick = async () => {
+    const form = flowFormData.value
+    console.log(form)
+}
+</script>

+ 1 - 1
src/views/tasks/message.vue

@@ -1,6 +1,6 @@
 <template>
     <div class="hc-layout-box">
-        222
+        消息提醒
     </div>
 </template>