小宣 4 mesi fa
parent
commit
a45b7dd1bd

+ 1 - 0
package.json

@@ -68,6 +68,7 @@
         "speak-tts": "^2.0.8",
         "tinymce": "^6.1.2",
         "v-viewer": "^1.6.4",
+        "vant": "^2.13.6",
         "videojs-contrib-hls": "^5.15.0",
         "vue": "2.6.10",
         "vue-count-to": "^1.0.13",

BIN
src/assets/image/radiusOff.png


BIN
src/assets/image/radiusOn.png


+ 4 - 0
src/main.js

@@ -11,6 +11,7 @@ import router from './router'
 import '@/icons' // icon
 import '@/permission' // permission control
 import 'echarts-liquidfill'
+import 'vant/lib/index.css'
 // 引入富文本编译器
 import VueQuillEditor from 'vue-quill-editor'
 import 'quill/dist/quill.core.css'
@@ -30,6 +31,9 @@ import channel from './static/utils/channel.js'
 import md5 from 'js-md5'
 //全局注册
 import SearchBar from 'search-bar-vue2'
+const Vant = require('vant')
+
+Vue.use(Vant)
 // 引入第三方字体
 import '@/assets/css/font.css'
 import 'element-ui/lib/theme-chalk/index.css'

+ 9 - 0
src/router/index.js

@@ -402,6 +402,15 @@ export const constantRoutes = [
         path: '/mapEcharts',//h5设备详情
         component: () => import('@/views/life-line/components/mapCharts/mapEchartsNew.vue'),
         hidden: false
+    },,
+    {
+        path: '/paymentApplication',//h5付款申请
+        component: () => import('@/views/paymentApplication/index.vue'),
+        hidden: false,
+        meta: {
+            name: '付款申请',
+            keepAlive: true
+        }
     },
 
 

+ 278 - 0
src/views/components/userSelectForH5.vue

@@ -0,0 +1,278 @@
+<template>
+  <div class="userSelectForH5">
+    <el-popover
+      ref="reference"
+      :disabled="disab"
+      width="80%"
+      placement="bottom-start"
+      trigger="click"
+      @hide="popoverHide"
+    >
+      <el-tabs v-model="activeName" width="80%" class="h5Tab" type="card" @tab-click="handleClick">
+        <el-input v-model="checkLabel" placeholder="请输入搜索内容" size="mini">
+          <i slot="suffix" class="el-icon-edit el-input__icon" />
+        </el-input>
+        <el-tab-pane label="按组织" name="1" style="height: 300px; overflow-y:auto;">
+          <el-tree ref="tree_1" :data="data_1" :default-expanded-keys="expandedKeys" :filter-node-method="filterNode" :props="defaultProps" empty-text="没有数据了" node-key="id" show-checkbox @check="handleNodeChange" />
+        </el-tab-pane>
+        <el-tab-pane label="按岗位" name="2" style="height: 300px; overflow-y:auto;">
+          <el-tree ref="tree_2" :data="data_2" :default-expanded-keys="expandedKeys" :filter-node-method="filterNode" :props="defaultProps" empty-text="没有数据了" node-key="id" show-checkbox @check="handleNodeChange" />
+        </el-tab-pane>
+        <el-tab-pane label="我的下属" name="3" style="height: 300px; overflow-y:auto;">
+          <el-tree ref="tree_3" :data="data_3" :default-expanded-keys="expandedKeys" :filter-node-method="filterNode" :props="defaultProps" empty-text="没有数据了" node-key="id" show-checkbox @check="handleNodeChange" />
+        </el-tab-pane>
+        <el-tab-pane label="我的部门" name="4" style="height: 300px; overflow-y:auto;">
+          <el-tree ref="tree_4" :data="data_4" :default-expanded-keys="expandedKeys" :filter-node-method="filterNode" :props="defaultProps" empty-text="没有数据了" node-key="id" show-checkbox @check="handleNodeChange" />
+        </el-tab-pane>
+      </el-tabs>
+
+      <div slot="reference" class="col-input el-col el-col-20" data-v-51add840="" style="width: 100%;" @click="search">
+        <div class="el-form-item" data-v-51add840="">
+          <div class="el-form-item__content">
+            <div class="el-select" data-v-51add840="">
+              <div class="el-input el-input--suffix is-focus">
+                <input v-model="selectLabel" autocomplete="off" class="el-input__inner" placeholder="请选择人员" type="text">
+                <span class="el-input__suffix">
+                  <span class="el-input__suffix-inner">
+                    <i :class="classType==1?class_up:class_dow" style="" />
+                  </span>
+                </span>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+    </el-popover>
+  </div>
+</template>
+
+<script>
+export default {
+    props: {
+        defaultSelect: Array,
+        width: String,
+        multiple: Boolean,
+        disab: Boolean,
+        groupId: String
+    },
+    data() {
+        return {
+            classType: 1,
+            checkLabel: '',
+            selectLabel: '',
+            selectValue: [],
+            labels: [],
+            selectTree: [],
+            expandedKeys: ['0'],
+            activeName: '1',
+            class_up: 'el-select__caret el-input__icon el-icon-arrow-up',
+            class_dow: 'el-select__caret el-input__icon el-icon-arrow-up is-reverse',
+
+            data_1: [],
+            data_2: [],
+            data_3: [],
+            data_4: [],
+            defaultProps: {
+                children: 'children',
+                label: 'label'
+            }
+        }
+    },
+    watch: {
+        defaultSelect: {
+            deep: true,
+            handler(val) {
+                this.labels = []
+                this.selectValue = []
+                this.getTreeDate()
+                this.$refs.tree_1.setCheckedKeys(val)
+                const _this = this
+                setTimeout(function() {
+                    _this.popoverHide()
+                }, 600)
+            }
+        },
+        checkLabel(val) {
+            this.$refs['tree_' + this.activeName].filter(val)
+        }
+    },
+    mounted() {
+        this.getTreeDate()
+        this.$refs.tree_1.setCheckedKeys(this.defaultSelect)
+        const _this = this
+        setTimeout(function() {
+            _this.popoverHide()
+        }, 600)
+    },
+    methods: {
+        search: function() {
+            if (this.classType === 1) {
+                this.classType = 2
+            } else {
+                this.classType = 1
+            }
+        },
+
+        handleClick: function() {
+            this.getTreeDate()
+        },
+
+        handleNodeChange: function(data, checked, indeterminate) {
+            debugger
+            // console.log(data)
+            // console.log(checked)
+            // console.log(indeterminate)
+            if (!this.multiple) {
+                if (checked) {
+                    this.$refs['tree_' + this.activeName].setCheckedKeys([])
+                    this.$refs['tree_' + this.activeName].setChecked(data, true)
+                    if (data.children == null) {
+                        this.selectValue = [data.id]
+                        this.labels = [data.label]
+                    }
+                }
+            } else {
+                if (this.selectValue.indexOf(data.id) > -1) {
+                    this.selectValue = this.selectValue.filter(item => item !== data.id)
+                    this.labels = this.labels.filter(item => item !== data.label)
+                }
+                if (data.children != null && data.children.length > 0) {
+                    this.deleteSelect(data.children)
+                }
+            }
+            this.popoverHide()
+        },
+        deleteSelect(data) {
+            data.forEach(it => {
+                if (it.children != null && it.children.length > 0) {
+                    this.deleteSelect(it.children)
+                }
+                this.selectValue = this.selectValue.filter(item => item !== it.id)
+                this.labels = this.labels.filter(item => item !== it.label)
+            })
+        },
+
+        popoverHide: function() {
+            const sectd = this.$refs['tree_' + this.activeName].getCheckedNodes()
+            const seachId = []
+            const seachVal = []
+            sectd.forEach(element => {
+                // console.log('element_:', element)
+                if (element.selectType && this.selectValue.indexOf(element.id) === -1) {
+                    seachId.push(element.id)
+                    seachVal.push(element.label)
+                }
+            })
+
+            if (seachVal.length > 0) {
+                seachVal.forEach(ii => {
+                    this.labels.push(ii)
+                })
+            }
+            this.selectLabel = this.labels.toString()
+            if (seachId.length > 0) {
+                seachId.forEach(ij => {
+                    this.selectValue.push(ij)
+                })
+            }
+            // if (!this.multiple && (sectd[0].children != null)) {
+            //     this.labels = []
+            //     this.selectLabel = ''
+            //     this.selectValue = ''
+            // }
+
+            // console.log('selectLabel:', this.selectValue)
+            this.$emit('selectValue', this.selectValue)
+        },
+
+        filterNode: function(value, data) {
+            if (!value) return true
+            return data.label.indexOf(value) !== -1
+        },
+
+        // 获取树级数据
+        getTreeDate: function() {
+            const postData = {
+                groupType: this.activeName,
+                groupId: this.groupId
+            }
+            this['data_' + this.activeName] = []
+            this.baseUserRequest('getUserListGroupType', postData).then((res) => {
+                if (res.data) {
+                    if (!this.multiple) {
+                        this.getData(res.data.data)
+                    }
+                    this['data_' + this.activeName] = res.data.data
+                    this.$refs['tree_' + this.activeName].setCheckedKeys(this.defaultSelect.length === 0 ? this.selectValue : this.defaultSelect)
+                }
+                this.loading = false
+            }).catch(() => {
+            })
+        },
+        getData(data) {
+            data.map(item => {
+                this.getLeadKeys(item)
+            })
+        },
+        getLeadKeys(node) {
+            if (node.children && node.children.length > 0) {
+                node.disabled = true
+                node.children.forEach(item => {
+                    this.getLeadKeys(item)
+                })
+            } else {
+                if (node.selectType) {
+                    node.disabled = false
+                } else {
+                    node.disabled = true
+                }
+            }
+        },
+
+        baseUserRequest(opUrl, postData) {
+            return this.$channel.globeRequest('FrameExclusiveUserController', opUrl, postData, 'project')
+        }
+
+    }
+}
+</script>
+<style lang="scss">
+.userSelectForH5 {
+    position: relative;
+    width: 100%;
+
+    .el-popover {
+        width: 90vw !important;
+        // 针对移动端的样式调整
+        @media (max-width: 768px) {
+            width: 100vw !important;
+        }
+    }
+
+    // 调整输入框和选择框的样式
+    .el-input__inner,
+    .el-select__caret {
+        font-size: 14px;
+        @media (max-width: 768px) {
+            font-size: 12px;
+        }
+    }
+
+    // 调整树状结构的样式
+    .el-tree {
+        @media (max-width: 768px) {
+            font-size: 12px;
+        }
+    }
+    .col-input{
+        padding-left: 0;
+    }
+}
+.h5Tab{
+    .el-tabs__item{
+        padding: 0 4vw !important;
+    }
+
+}
+</style>

+ 444 - 0
src/views/paymentApplication/index.vue

@@ -0,0 +1,444 @@
+
+<template>
+  <div class="payment-application">
+    <div class="processCode">流程编号:</div>
+    <div class="paymentRowBox">
+      <div>标题:</div>
+      <input v-model="postData.title" readonly class="paymentInput" type="text">
+    </div>
+    <div class="paymentRowBox">
+      <div>创建人:</div>
+      <input v-model="postData.create" readonly class="paymentInput" type="text">
+    </div>
+    <div class="paymentRowBox">
+      <div>创建部门:</div>
+      <input v-model="postData.createDepartment" readonly class="paymentInput" type="text">
+    </div>
+    <div class="paymentRowBox">
+      <div>是否为无合同付款:</div>
+      <input v-model="postData.isPay" readonly class="paymentInput" type="text">
+    </div>
+    <div class="paymentRowBox">
+      <div>付款单位:</div>
+      <input v-model="postData.payUnit" readonly class="paymentInput" type="text">
+    </div>
+    <div class="paymentRowBox">
+      <div>收款单位:</div>
+      <input v-model="postData.payeeUnit" readonly class="paymentInput" type="text">
+    </div>
+    <div class="paymentRowBox">
+      <div>资金用途:</div>
+      <input v-model="postData.useFor" readonly class="paymentInput" type="text">
+    </div>
+    <div class="paymentRowBox">
+      <div>合同总价:</div>
+      <input v-model="postData.totalPrice" readonly class="paymentInput" type="text">
+    </div>
+    <div class="paymentRowBox">
+      <div>付款说明:</div>
+      <el-input
+        v-model="postData.describe"
+        type="textarea"
+        autosize
+        rows="5"
+        placeholder="请输入内容"
+        readonly
+      />
+    </div>
+    <div class="paymentRowBox">
+      <div>申请金额(小写)</div>
+      <input v-model="postData.priceSmall" readonly class="paymentInput" type="text">
+    </div>
+    <div class="paymentRowBox">
+      <div>申请金额(大写)</div>
+      <input v-model="postData.priceBig" readonly class="paymentInput" type="text">
+    </div>
+    <div class="paymentRowBox">
+      <div>相关附件</div>
+      <van-uploader v-model="fileList" :deletable="false" :show-upload="false" @click-preview="clickPre3">
+        <!--        <img src="../../assets/image/upload.png">-->
+      </van-uploader>
+    </div>
+    <van-collapse v-model="activeNames">
+      <van-collapse-item name="1">
+        <template #title>
+          <div style="display: flex;align-items: center;color: rgba(51, 51, 51, 1);font-weight: 600;font-size: 3.6vw">
+            <div class="blueBg" />流程历史
+          </div>
+        </template>
+        <div style="background: #FAFAFA" class="container">
+          <div v-for="(item, index) in dtList" :key="index" class="itemBox">
+            <div class="itemLeft">
+              <!--                             <div class="radius"></div>-->
+              <img :src="item.auditResult=='-1'?radiusOn:radiusOff" class="radius">
+              <div class="itemTitBox">
+                <div style="display: flex;margin: 1vw 0">
+                  <div style="color: rgba(51, 51, 51, 1)">{{ item.nodeName }}{{ item.auditResultString?':':'' }}</div>
+                  <div :style="{'color':item.auditResultString==='同意'?'#5ABF68':item.auditResultString==='处理中'?'#E08E42':'red'}">{{ item.auditResultString }}</div>
+                </div>
+                <div v-show="item.auditContent" style="padding: 2vw;background: #F2F2F2;margin: 1vw 0;border-radius: 1vw">{{ item.auditContent }}</div>
+                <div style="display: flex;justify-content: space-between;width: 100%;margin: 1vw 0">
+                  <div>{{ item.auditUserName }}</div>
+                  <div>{{ item.createdAt?item.createdAt:'' }}</div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </van-collapse-item>
+    </van-collapse>
+    <div style="display: flex;align-items: center;color: rgba(51, 51, 51, 1);font-weight: 600;font-size: 3.6vw">
+      <div class="blueBg" />处理
+    </div>
+    <div class="paymentRowBox">
+      <div class="handleTit">处理结果</div>
+      <van-radio-group v-model="radio" direction="horizontal" checked-color="rgba(41, 64, 150, 1)" icon-size="4vw">
+        <van-radio name="1">通过,转下一步</van-radio>
+        <van-radio name="2">退回发起人</van-radio>
+      </van-radio-group>
+    </div>
+    <div class="paymentRowBox">
+      <div class="handleTit">处理意见</div>
+      <el-input
+        v-model="postData.opinion"
+        type="textarea"
+        autosize
+        rows="5"
+        placeholder="请输入处理意见"
+        maxlength="2000"
+        show-word-limit
+      />
+    </div>
+    <div class="paymentRowBox">
+      <div class="handleTit">抄送</div>
+      <userSelectForH5
+        :default-select="confirmList"
+        :multiple="true"
+        class="cclist,statistic_base"
+        :append-to-body="true"
+        :modal-append-to-body="true"
+        custom-class="tagdialog"
+        @selectValue="parentMethod"
+      />
+    </div>
+    <div class="paymentRowBox" style="margin-top: 0">
+      <div class="handleTit">处理人   &nbsp;&nbsp;&nbsp;&nbsp;<span>王一博</span></div>
+    </div>
+    <div class="paymentBtnBox">
+      <button class="closeBtn">关闭</button>
+      <button class="submitBtn">提交</button>
+    </div>
+  </div>
+</template>
+
+<script>
+import userSelectForH5 from '@/views/components/userSelectForH5.vue'
+
+export default {
+    name: 'Index',
+    components: { userSelectForH5 },
+    data() {
+        return {
+            confirmList: [],
+            activeNames: ['1'],
+            postData: {
+                title: '付款领用单20250116-004',
+                create: '万妮娅',
+                createDepartment: '商管中心',
+                isPay: '是',
+                payUnit: '无锡市安居投资发展有限公司',
+                payeeUnit: '欧阳小峰',
+                useFor: '买保健品',
+                totalPrice: '5000',
+                describe: '我不知道我不知道我不知道我不知道我不知道我不知道我不知道我不知道我不知道我不知道我不知道我不知道',
+                priceSmall: '5000',
+                priceBig: '五千',
+                opinion: '',
+                cs: ''
+            },
+            radio: '1',
+            fileList: [{ url: 'https://img01.yzcdn.cn/vant/leaf.jpg' }],
+            dtList: [
+                {
+                    auditContent:
+                        null,
+                    auditResult:
+                        null,
+                    auditResultString:
+                        null,
+                    auditUser:
+                        '996375895163797504',
+                    auditUserName:
+                        '宣胜伟',
+                    createdAt:
+                        1736321293000,
+                    id:
+                        'aFdtLdth02lLfk26nMZ',
+                    nodeName:
+                        '申请人发起'
+                },
+                {
+                    auditContent:
+                        '',
+                    auditResult:
+                        '1',
+                    auditResultString:
+                        '同意',
+                    auditUser:
+                        '927859716221042688',
+                    auditUserName:
+                        '崔伟',
+                    createdAt:
+                        1735647785000,
+                    id:
+                        'IrFA28epluWZB3agf6x',
+                    nodeName:
+                        '直接上级审核'
+                },
+                {
+                    auditContent:
+                        '测试一下啊',
+                    auditResult:
+                        '-1',
+                    auditResultString:
+                        '退回上一节点',
+                    auditUser:
+                        '927859716221042688',
+                    auditUserName:
+                        '章敏',
+                    createdAt:
+                        1735647785000,
+                    id:
+                        'IrFA28epluWZB3agf6x',
+                    nodeName:
+                        '分管领导审核'
+                }
+            ],
+            radiusOn: require('@/assets/image/radiusOn.png'),
+            radiusOff: require('@/assets/image/radiusOff.png')
+        }
+    },
+    mounted() {
+        const dayjs = require('dayjs')
+        this.dtList.forEach(item => {
+            if (item.createdAt) {
+                item.createdAt = dayjs(item.createdAt).format('YYYY-MM-DD HH:mm:ss')
+            }
+        })
+    },
+    methods: {
+        parentMethod(val) {
+            if (val.length > 0) {
+                this.confirmForm.ccList = val.join(',')
+            }
+        },
+        clickPre3(file) {
+            if (this.matchType(file.url) !== 'image') {
+                window.location.href = file.url
+            }
+        },
+        matchType(fileName) {
+            // 后缀获取
+            var suffix = ''
+            // 获取类型结果
+            var result = ''
+            try {
+                var flieArr = fileName.split('.')
+                suffix = flieArr[flieArr.length - 1]
+            } catch (err) {
+                suffix = ''
+            }
+            // fileName无后缀返回 false
+            if (!suffix) {
+                result = false
+                return result
+            }
+            // 图片格式
+            var imglist = ['png', 'jpg', 'jpeg', 'bmp', 'gif']
+            // 进行图片匹配
+            result = imglist.some(function(item) {
+                return item == suffix
+            })
+            if (result) {
+                result = 'image'
+                return result
+            }
+            // 匹配txt
+            var txtlist = ['txt']
+            result = txtlist.some(function(item) {
+                return item == suffix
+            })
+            if (result) {
+                result = 'txt'
+                return result
+            }
+            // 匹配 excel
+            var excelist = ['xls', 'xlsx']
+            result = excelist.some(function(item) {
+                return item == suffix
+            })
+            if (result) {
+                result = 'excel'
+                return result
+            }
+            // 匹配 word
+            var wordlist = ['doc', 'docx']
+            result = wordlist.some(function(item) {
+                return item == suffix
+            })
+            if (result) {
+                result = 'word'
+                return result
+            }
+            // 匹配 pdf
+            var pdflist = ['pdf']
+            result = pdflist.some(function(item) {
+                return item == suffix
+            })
+            if (result) {
+                result = 'pdf'
+                return result
+            }
+            // 匹配 ppt
+            var pptlist = ['ppt']
+            result = pptlist.some(function(item) {
+                return item == suffix
+            })
+            if (result) {
+                result = 'ppt'
+                return result
+            }
+            // 匹配 视频
+            var videolist = ['mp4', 'm2v', 'mkv']
+            result = videolist.some(function(item) {
+                return item == suffix
+            })
+            if (result) {
+                result = 'video'
+                return result
+            }
+            // 匹配 音频
+            var radiolist = ['mp3', 'wav', 'wmv']
+            result = radiolist.some(function(item) {
+                return item == suffix
+            })
+            if (result) {
+                result = 'radio'
+                return result
+            }
+            // 其他 文件类型
+            result = 'other'
+            return result
+        }
+    }
+}
+</script>
+
+<style lang="scss">
+    .payment-application{
+        padding: 2vw 3vw 10vw 3vw;
+        display: flex;
+        flex-direction: column;
+         .processCode{
+             color: rgba(119, 119, 119, 1);
+             font-size: 3.4vw;
+         }
+        .paymentRowBox{
+            font-size: 3.5vw;
+            color: rgba(51, 51, 51, 1);
+            margin-top: 2vw;
+            .paymentInput{
+                color: rgba(68, 68, 68, 1);
+                padding: 2.2vw 2vw;
+                width: 100% !important;
+                margin: 1vw 0;
+                border:1px solid rgba(230, 230, 230, 1);
+            }
+            .el-textarea__inner{
+                padding: 2.2vw 2vw;
+                margin: 1vw 0;
+            }
+            .handleTit{
+                font-size: 3.4vw;
+                color: rgba(51, 51, 51, 1);
+                margin-bottom: 1.5vw;
+                margin-top: 4.5vw;
+            }
+        }
+        .paymentBtnBox{
+            display: flex;
+            justify-content: space-evenly;
+            font-size: 3.4vw;
+            margin-top: 8vw;
+            .closeBtn{
+                width: 29.4vw;
+                height: 8vw;
+                background: rgba(87,106,201,0.15);
+                border-radius: 1vw;
+                border: 1px solid rgba(42,57,128,0.75);
+                color: #2A3980;
+            }
+            .submitBtn{
+                width: 29.4vw;
+                height: 8vw;
+                background: #2A3980;
+                border-radius: 1vw;
+                color: #FFFFFF;
+            }
+        }
+        .itemBox {
+            display: flex;
+            justify-content: space-between;
+            padding: 2vw 1vw 1vw 1vw;
+            position: relative;
+            z-index: 1;
+            .itemLeft {
+                display: flex;
+                align-items: center;
+                width: 100%;
+                margin: 0.5vw 2vw;
+                .itemTitBox {
+                    //height: 2.3vw;
+                    width: 100%;
+                    display: flex;
+                    flex-direction: column;
+                    justify-content: space-between;
+                }
+                .timeBox {
+                    display: flex;
+                    color: #999999;
+                    font-size: 16px;
+                }
+                .radius{
+                    width: 5vw;
+                    height: 5vw;
+                    margin-right: 3vw;
+                }
+            }
+            .itemRight {
+                display: flex;
+                height: 2.8vw;
+                flex-direction: column;
+                justify-content: space-between;
+                flex-direction: column;
+                .tagBox {
+                    text-align: right;
+
+                    // margin: 0.5vw 0;
+                }
+            }
+        }
+        .blueBg{
+            width: 0.6vw;
+            height: 4vw;
+            background: rgba(76, 92, 168, 1);
+            margin-right: 1vw;
+        }
+        .van-cell{
+            padding: 5vw 0 1vw 0;
+        }
+        .van-collapse-item__content{
+            padding: 1vw 0;
+        }
+    }
+</style>