| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485 |
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
- <title>审核</title>
- <script src="/js/mp_base/base.js"></script>
- <style>
- /* 防止Vue模板闪烁 */
- [v-cloak] {
- display: none !important;
- }
- #app {
- background: #edf1f5;
- min-height: 100vh;
- display: flex;
- flex-direction: column;
- }
- .header-section {
- position: relative;
- padding: 10px 0;
- cursor: pointer;
- user-select: none;
- touch-action: none;
- transition: background-color 0.3s ease;
- }
- .header-section::after {
- width: 95%;
- height: 1px;
- content: " ";
- position: absolute;
- bottom: 0px;
- left: 50%;
- transform: translateX(-50%);
- background: #e2e4ec;
- }
- .header-section:hover {
- background: rgba(64, 172, 109, 0.05);
- }
- .header-section.dragging {
- background: rgba(64, 172, 109, 0.1);
- }
- </style>
- </head>
- <body>
- <div id="app" v-cloak>
- <div class="sh-list-container">
- <!-- 头部节点 -->
- <div class="header-section" @click="handleHeaderClick" @mousedown="handleDragStart"
- @touchstart="handleDragStart">
- <ss-verify-node v-if="rightHeader" class="header-node" :item="rightHeader" />
- </div>
- <!-- 审批链条 -->
- <div class="verify-section">
- <ss-verify v-if="rightGroupList && rightGroupList.length > 0" :verify-list="rightGroupList"
- class="fit-height-content" @toggle-group="handleToggleGroup" />
- </div>
- <!-- 空状态 -->
- <div v-else class="empty-state">
- <Icon name="icon-kongzhuangtai" size="64" color="#ccc" />
- <p>暂无审核节点数据</p>
- </div>
- </div>
- </div>
- <script>
- // 等待SS框架加载完成
- window.SS.ready(function () {
- // 使用SS框架的方式创建Vue实例
- window.SS.dom.initializeFormApp({
- el: '#app',
- data() {
- return {
-
- ssObjName:'',
- ssObjId:'',
- sqid: '',
- shid: '',
- bdlbm: '',
- dataType:'',
- encode_shid:'',
- pageParams: {},
- // 头部节点数据
- rightHeader: null,
- // 审批链条数据
- rightGroupList: [],
- loading: false,
- // 拖拽相关
- isDragging: false,
- dragStartY: 0,
- dragStartTime: 0,
- dragTimer: null,
- hasMoved: false,
- dragStarted: false,
- }
- },
- mounted() {
- // 获取URL参数
- this.pageParams = this.getUrlParams()
- console.log('🔗 mp_shList页面接收到参数:', this.pageParams)
- // 如果有sqid参数,调用selSh接口
- if (this.pageParams.sqid) {
- this.ssObjName = this.pageParams.ssObjName
- this.ssObjId = this.pageParams.ssObjId
- this.sqid = this.pageParams.sqid
- this.shid = this.pageParams.shid
- this.bdlbm = this.pageParams.bdlbm
- this.dataType = this.pageParams.dataType
- this.encode_shid = this.pageParams.encode_shid
- this.loadSelSh()
- }
- },
- methods: {
- // 获取URL参数
- getUrlParams() {
- const params = {}
- const urlSearchParams = new URLSearchParams(window.location.search)
- for (const [key, value] of urlSearchParams) {
- params[key] = decodeURIComponent(value)
- }
- return params
- },
- // 加载selSh数据
- async loadSelSh() {
- if (!this.sqid) {
- console.warn('⚠️ sqid为空,无法调用selSh接口')
- return
- }
- this.loading = true
- try {
- console.log('📋 调用selSh服务获取数据...', this.sqid)
- const selShResponse = await request.post(
- `/service?ssServ=selSh&sqid=${this.sqid}`,
-
- { loading: false, formData: true }
- )
- console.log('✅ selSh响应:', selShResponse)
- // 处理selSh数据
- if (selShResponse && selShResponse.data) {
- this.processShListData(selShResponse.data)
- }
- } catch (error) {
- console.error('❌ 加载selSh数据失败:', error)
- } finally {
- this.loading = false
- }
- },
- // 处理审核列表数据
- processShListData(data) {
- console.log('🔄 开始处理审核列表数据:', data)
- // 构建完整的审核记录列表
- const allRecords = []
- // 1. 添加申请人记录 (来自sq字段)
- if (data.sq) {
- allRecords.push({
- ...data.sq,
- isSqry: true // 标记为申请人
- })
- }
- // 2. 添加审核人员记录 (来自shList)
- if (data.shList && Array.isArray(data.shList)) {
- data.shList.forEach(group => {
- if (group.ryList && Array.isArray(group.ryList)) {
- group.ryList.forEach(ry => {
- allRecords.push({
- ...ry,
- isSqry: false // 标记为审核人
- })
- })
- }
- })
- }
- console.log('📋 所有审核记录:', allRecords)
- // 3. 设置申请人头部信息 (第一条记录)
- const sqry = allRecords.find(item => item.isSqry) || {}
- this.rightHeader = {
- thumb: this.getThumbUrl(sqry.zjzwj),
- name: sqry.xm || '',
- role: sqry.bmmc || '',
- description: sqry.sm || '发起审核',
- time: this.formatTime(sqry.shsj),
- link: false,
- }
- console.log('👤 申请人信息:', this.rightHeader)
- // 4. 按部门分组构建审核链条
- const shRecords = allRecords.filter(item => !item.isSqry)
- this.rightGroupList = this.groupByDepartment(shRecords)
- console.log('📊 审核链条:', this.rightGroupList)
- },
- // 按部门分组
- groupByDepartment(records) {
- const groups = {}
- records.forEach(item => {
- const groupKey = item.bmmc || '未知部门'
- if (!groups[groupKey]) {
- groups[groupKey] = {
- groupName: groupKey,
- open: true,
- children: []
- }
- }
- groups[groupKey].children.push({
- thumb: this.getThumbUrl(item.zjzwj),
- name: item.xm || '',
- role: item.bmmc || '',
- description: item.sm || '同意',
- time: this.formatTime(item.shsj),
- link: false
- })
- })
- return Object.values(groups)
- },
- // 获取头像URL
- getThumbUrl(path) {
- // 如果没有路径,返回默认头像
- if (!path) {
- return 'skin/easy/image/default-personalPhoto.png'
- }
- // 使用全局的 getImageUrl 方法处理图片路径
- if (typeof window.getImageUrl === 'function') {
- return window.getImageUrl(path)
- }
- // 如果 getImageUrl 不存在,返回原路径
- console.warn('⚠️ getImageUrl 方法不存在')
- return path
- },
- // 格式化时间
- formatTime(timeStr) {
- // 检查时间字符串是否有效
- if (!timeStr || timeStr === '' || timeStr === null || timeStr === undefined) {
- console.log('⚠️ formatTime: 时间为空')
- return ''
- }
- console.log('🕐 formatTime 输入:', timeStr)
- // 检查 dayjs 是否可用
- if (typeof dayjs === 'undefined') {
- console.error('❌ dayjs 未加载')
- return ''
- }
- try {
- // 清理字符串:移除特殊空格字符
- const cleanedDateStr = String(timeStr)
- .replace(/[\u202F\u00A0]/g, ' ')
- .replace(/\s+/g, ' ')
- .trim()
- console.log('清理后的字符串:', cleanedDateStr)
- // 使用原生 Date 解析
- const jsDate = new Date(cleanedDateStr)
- if (isNaN(jsDate.getTime())) {
- console.warn('⚠️ Date 解析失败')
- return ''
- }
- // 转换为 dayjs
- const date = dayjs(jsDate)
- if (!date.isValid()) {
- console.warn('⚠️ dayjs 无效')
- return ''
- }
- console.log('✅ dayjs 解析成功')
- // 格式化: HH:mm MM/DD
- const result = date.format('HH:mm MM/DD')
- console.log('🕐 formatTime 输出:', result)
- return result
- } catch (error) {
- console.error('❌ 时间格式化失败:', error, timeStr)
- return ''
- }
- },
- // 处理分组展开/收起
- handleToggleGroup(data) {
- console.log('🔄 分组状态变化:', data)
- },
- // ===== 与父页面通信方法 =====
- // 发送消息到父页面
- sendMessageToParent(type, data = {}) {
- try {
- // 通过postMessage向父页面发送消息
- if (window.parent && window.parent !== window) {
- window.parent.postMessage({
- type,
- data
- }, '*') // 在生产环境中应该使用具体的origin
- }
- } catch (error) {
- console.error('发送消息到父页面失败:', error)
- }
- },
- // 处理header-section点击
- handleHeaderClick(event) {
- // 如果正在拖拽中,不处理点击
- if (this.isDragging) {
- return
- }
- console.log('🖱️ header-section被点击')
- this.sendMessageToParent('header-section-click')
- },
- // 处理拖拽开始(长按检测)
- handleDragStart(event) {
- // 阻止默认行为,防止页面滚动
- event.preventDefault()
- // 只处理鼠标左键或触摸事件
- if (event.type === 'mousedown' && event.button !== 0) {
- return
- }
- console.log('🔄 开始长按检测')
- // 记录开始时间和位置
- this.dragStartTime = Date.now()
- this.dragStartY = event.type === 'mousedown' ? event.clientY : event.touches[0].clientY
- this.hasMoved = false
- this.dragStarted = false
- // 添加长按检测
- this.dragTimer = setTimeout(() => {
- if (!this.hasMoved && !this.dragStarted) {
- this.dragStarted = true
- console.log('🔄 开始拖拽header-section')
- this.isDragging = true
- // 添加拖拽样式
- document.querySelector('.header-section').classList.add('dragging')
- // 通知父页面开始拖拽
- this.sendMessageToParent('header-section-drag-start', {
- startY: this.dragStartY
- })
- // 添加全局事件监听器
- if (event.type === 'mousedown') {
- document.addEventListener('mousemove', this.handleDragMove)
- document.addEventListener('mouseup', this.handleDragEnd)
- } else {
- document.addEventListener('touchmove', this.handleDragMove, { passive: false })
- document.addEventListener('touchend', this.handleDragEnd)
- }
- }
- }, 500) // 500ms后开始拖拽
- // 添加临时事件监听器来检测移动
- const tempMouseMove = (e) => {
- const currentY = e.type === 'mousemove' ? e.clientY : e.touches[0].clientY
- const moveDistance = Math.abs(currentY - this.dragStartY)
- if (moveDistance > 10) { // 移动超过10px就认为不是长按
- this.hasMoved = true
- clearTimeout(this.dragTimer)
- // 移除临时监听器
- this.removeTempListeners(event.type, tempMouseMove, tempMouseUp)
- }
- }
- const tempMouseUp = (e) => {
- clearTimeout(this.dragTimer)
- // 如果没有开始拖拽且有移动,则触发点击事件
- if (!this.dragStarted && !this.hasMoved) {
- console.log('🖱️ 触发点击事件(mouseup)')
- // 延迟触发点击,避免与拖拽冲突
- setTimeout(() => {
- this.handleHeaderClick(e)
- }, 50)
- }
- // 移除临时监听器
- this.removeTempListeners(event.type, tempMouseMove, tempMouseUp)
- }
- // 添加临时事件监听器
- if (event.type === 'mousedown') {
- document.addEventListener('mousemove', tempMouseMove)
- document.addEventListener('mouseup', tempMouseUp)
- } else {
- document.addEventListener('touchmove', tempMouseMove, { passive: false })
- document.addEventListener('touchend', tempMouseUp)
- }
- },
- // 移除临时监听器的辅助方法
- removeTempListeners(eventType, mouseMoveHandler, mouseUpHandler) {
- if (eventType === 'mousedown') {
- document.removeEventListener('mousemove', mouseMoveHandler)
- document.removeEventListener('mouseup', mouseUpHandler)
- } else {
- document.removeEventListener('touchmove', mouseMoveHandler)
- document.removeEventListener('touchend', mouseUpHandler)
- }
- },
- // 处理拖拽移动
- handleDragMove(event) {
- if (!this.isDragging) return
- event.preventDefault()
- const currentY = event.type === 'mousemove'
- ? event.clientY
- : event.touches[0].clientY
- const deltaY = currentY - this.dragStartY
- // 通知父页面拖拽移动
- this.sendMessageToParent('header-section-drag-move', {
- deltaY
- })
- },
- // 处理拖拽结束
- handleDragEnd() {
- if (!this.isDragging) return
- console.log('🔚 结束拖拽')
- // 移除拖拽样式
- const headerSection = document.querySelector('.header-section')
- if (headerSection) {
- headerSection.classList.remove('dragging')
- }
- // 重置状态
- this.isDragging = false
- this.dragStartY = 0
- // 移除全局事件监听器
- document.removeEventListener('mousemove', this.handleDragMove)
- document.removeEventListener('mouseup', this.handleDragEnd)
- document.removeEventListener('touchmove', this.handleDragMove)
- document.removeEventListener('touchend', this.handleDragEnd)
- // 通知父页面拖拽结束
- this.sendMessageToParent('header-section-drag-end')
- },
- }
- })
- })
- </script>
- </body>
|