commit
This commit is contained in:
@@ -128,6 +128,17 @@ public class SysHomeController {
|
||||
public void index() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 兼容旧手机端首页地址,无需请求参数。
|
||||
* 未登录时沿用现有登录拦截;登录后重定向到标准 H5 首页,使底部导航按首页地址正常显示。
|
||||
* 方法返回 void,无响应数据字段,由重定向视图跳转到 /platform/h5/home。
|
||||
*/
|
||||
@At(value = "/mobile/index", top = true)
|
||||
@Ok(">>:/platform/h5/home")
|
||||
@SaCheckLogin
|
||||
public void mobileIndex() {
|
||||
}
|
||||
|
||||
@At(value = "/platform/h5", top = true)
|
||||
@Ok("re")
|
||||
@SaCheckLogin
|
||||
|
||||
@@ -69,7 +69,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<Sys_user> implements Sys
|
||||
* sys_user_role 仅用于确认用户具有目标角色,组织范围统一取 sys_user.unitId,
|
||||
* 避免依赖未维护的 sys_user_role.unitId 字段导致流程无人可分派。
|
||||
*
|
||||
* @param unitId 单位 ID
|
||||
* @param unitId 单位 ID
|
||||
* @param roleCode 角色编码
|
||||
* @return 对应单位下有效且具有目标角色的用户 ID
|
||||
*/
|
||||
@@ -104,7 +104,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<Sys_user> implements Sys
|
||||
* 角色用户通过 sys_user.unitId 关联 sys_unit,再以 sys_unit.unionId 确定
|
||||
* 二级党组织范围,不读取未维护的 sys_user_role.unionId 字段。
|
||||
*
|
||||
* @param unionId 分工会 ID
|
||||
* @param unionId 分工会 ID
|
||||
* @param roleCode 角色编码
|
||||
* @return 对应二级党组织下有效且具有目标角色的用户 ID
|
||||
*/
|
||||
@@ -381,9 +381,9 @@ public class SysUserServiceImpl extends BaseServiceImpl<Sys_user> implements Sys
|
||||
String decodePwd = Base64Decoder.decodeStr(passowrd);
|
||||
String hashedPassword = PwdUtil.getPassword(decodePwd, user.getSalt());
|
||||
if (!Strings.sNull(hashedPassword).equalsIgnoreCase(user.getPassword())) {
|
||||
// if (Globals.sso) {
|
||||
throw new BaseException("用户名或者密码不正确");
|
||||
// }
|
||||
if (Globals.sso) {
|
||||
throw new BaseException("用户名或者密码不正确");
|
||||
}
|
||||
}
|
||||
user = this.fetchLinks(user, "unit");
|
||||
if (Lang.isNotEmpty(user.getUnit()) && StrUtil.isNotBlank(user.getUnit().getUnionId())) {
|
||||
|
||||
@@ -1,59 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<configuration scan="false" scanPeriod="60000" debug="false">
|
||||
|
||||
<!-- 定义日志文件的存储路径 -->
|
||||
<!-- 日志存储路径 -->
|
||||
<property name="LOG_HOME" value="./logs"/>
|
||||
|
||||
<!-- 控制台输出配置 -->
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- INFO级别日志文件配置 -->
|
||||
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_HOME}/info.log</file>
|
||||
|
||||
<!--
|
||||
#################################################################################
|
||||
# #
|
||||
# 全文输出日志(一个文件存储)start #
|
||||
# #
|
||||
#################################################################################
|
||||
-->
|
||||
|
||||
<!-- 所有级别日志写入同一个文件 -->
|
||||
<appender name="ALL_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_HOME}/app.log</file>
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>INFO</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_HOME}/info-%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<maxHistory>30</maxHistory>
|
||||
<fileNamePattern>${LOG_HOME}/app-%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<maxHistory>300</maxHistory>
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
|
||||
<!-- ERROR级别日志文件配置 -->
|
||||
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_HOME}/error.log</file>
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>ERROR</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_HOME}/error-%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<maxHistory>30</maxHistory>
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
|
||||
<logger name="java" additivity="false" />
|
||||
<!-- 框架日志级别(按需调整) -->
|
||||
<logger name="org.eclipse.jetty" level="INFO"/>
|
||||
<logger name="org.quartz" level="INFO"/>
|
||||
<logger name="org.nutz" level="DEBUG"/>
|
||||
|
||||
<!-- 日志级别和appender的关联 -->
|
||||
<!-- root logger:DEBUG 级别,输出到控制台和全量文件 -->
|
||||
<root level="DEBUG">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
<appender-ref ref="INFO_FILE"/>
|
||||
<appender-ref ref="ERROR_FILE"/>
|
||||
<appender-ref ref="ALL_FILE"/>
|
||||
</root>
|
||||
|
||||
<!--
|
||||
#################################################################################
|
||||
# #
|
||||
# 全文输出日志(一个文件存储)end #
|
||||
# #
|
||||
#################################################################################
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</configuration>
|
||||
|
||||
|
||||
@@ -124,11 +124,71 @@ body {
|
||||
}
|
||||
|
||||
.custom-list-loading {
|
||||
background-color: unset;
|
||||
min-width: 132px;
|
||||
padding: 15px 12px 12px;
|
||||
border-radius: 14px;
|
||||
color: #666;
|
||||
background-color: rgba(255, 255, 255, 0.98);
|
||||
box-shadow: 0 6px 22px rgba(128, 72, 72, 0.08);
|
||||
}
|
||||
|
||||
.custom-list-loading .van-icon {
|
||||
font-size: 108px;
|
||||
position: relative;
|
||||
width: 88px;
|
||||
height: 88px;
|
||||
overflow: visible;
|
||||
font-size: 88px;
|
||||
}
|
||||
|
||||
.custom-list-loading .van-icon::before {
|
||||
position: absolute;
|
||||
inset: 6px;
|
||||
border: 1px solid rgba(255, 112, 103, 0.24);
|
||||
border-radius: 50%;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.custom-list-loading .van-icon::after {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 41px;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
background: #ff8c83;
|
||||
box-shadow: 33px 37px 0 #ff6f68, -35px 21px 0 #ffb0a9;
|
||||
content: "";
|
||||
transform-origin: 3px 42px;
|
||||
animation: smart-union-loading-orbit 1.8s linear infinite;
|
||||
}
|
||||
|
||||
.custom-list-loading .van-icon__image {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
box-sizing: border-box;
|
||||
width: 54px;
|
||||
height: 54px;
|
||||
padding: 5px;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 238, 236, 0.92);
|
||||
object-fit: contain;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
@keyframes smart-union-loading-orbit {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.custom-list-loading .van-toast__text {
|
||||
margin-top: 4px;
|
||||
color: #707070;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
line-height: 18px;
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
.list-card {
|
||||
@@ -308,3 +368,11 @@ body {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
|
||||
/* 西财独有的幸福工荟与立案分派页面沿用迁移后的卡片间距和手机安全区。 */
|
||||
.swufe-mobile-page { min-height:100vh; background:#f3f7fd; padding-bottom:calc(20px + env(safe-area-inset-bottom)); }
|
||||
.swufe-mobile-page .van-search { margin:10px 12px; padding:0; border-radius:12px; overflow:hidden; }
|
||||
.swufe-mobile-page .van-search__content { background:#fff; }
|
||||
.swufe-mobile-page .van-nav-bar .van-icon, .swufe-mobile-page .van-nav-bar__text { color:#1989fa; }
|
||||
.swufe-mobile-page .van-cell-group { border-radius:12px; overflow:hidden; }
|
||||
.swufe-mobile-page img { max-width:100%; }
|
||||
|
||||
@@ -8,6 +8,8 @@ const commonUtil = {
|
||||
"x-requested-with": "XMLHttpRequest"
|
||||
}
|
||||
})
|
||||
// H5 布局提供加载状态适配;PC 布局未提供此方法时不改变其请求行为。
|
||||
if (window.bindH5AxiosLoading) window.bindH5AxiosLoading(axiosService)
|
||||
//axios拦截器
|
||||
axiosService.interceptors.response.use(
|
||||
(response) => {
|
||||
|
||||
@@ -1,79 +1,197 @@
|
||||
/**
|
||||
* H5 弹框浏览器历史栈管理器。
|
||||
* 页面只注册关闭回调;本文件全局统一监听 popstate,避免每个页面重复绑定返回事件。
|
||||
* H5 弹框统一历史栈。两种页面 API 和 Vant 弹框适配共用唯一的 popstate 监听。
|
||||
* 历史状态保留 PJAX 页面信息;关闭弹框只消费本页增加的记录,不触发业务页面返回。
|
||||
*/
|
||||
;((global) => {
|
||||
if (global.h5PopupHistory && global.h5PopupHistory.unified) return
|
||||
const callbacks = new Map()
|
||||
const popupStack = []
|
||||
let tokenSeed = 0
|
||||
let stateSeed = 0
|
||||
let pendingClear = null
|
||||
|
||||
const invokeClose = (entry) => {
|
||||
const entries = []
|
||||
const subscribers = new Set()
|
||||
const pageInstances = new Set()
|
||||
const sessionId = Date.now().toString(36)
|
||||
let sequence = 0
|
||||
let pending = null
|
||||
let notifying = false
|
||||
let pageKey = ""
|
||||
let pageCallback = null
|
||||
const names = () => entries.map((entry) => entry.popupKey)
|
||||
const notify = () => {
|
||||
notifying = true
|
||||
try {
|
||||
if (pageCallback) pageCallback(names())
|
||||
subscribers.forEach((callback) => callback(names()))
|
||||
} finally { notifying = false }
|
||||
}
|
||||
/** entry 为栈记录;同步业务回调与 Vant input 事件,不再创建或回退历史。 */
|
||||
const dismiss = (entry) => {
|
||||
const callback = callbacks.get(entry.token)
|
||||
if (callback) callback(entry.popupKey)
|
||||
if (entry.component && !entry.component._isDestroyed) {
|
||||
const component = entry.component
|
||||
if ((component.$options.name || "").replace(/-/g, "").toLowerCase() === "vandialog") {
|
||||
// 返回键等同取消确认,结束 Dialog.confirm 的 Promise,避免后续操作一直等待。
|
||||
component.$emit("cancel")
|
||||
component.onClose("cancel")
|
||||
} else component.$emit("input", false)
|
||||
}
|
||||
}
|
||||
/** token 为注册标识,popupKey 为弹框名称;返回栈记录,重复打开同一弹框时复用记录。 */
|
||||
const open = (token, popupKey, component = null) => {
|
||||
const existing = entries.find((entry) => entry.token === token && entry.popupKey === popupKey)
|
||||
if (existing) return existing
|
||||
if (pending) {
|
||||
pending.promise.then(() => {
|
||||
if (!component || (!component._isDestroyed && component.value)) open(token, popupKey, component)
|
||||
})
|
||||
return null
|
||||
}
|
||||
const entry = {id: ++sequence, token: token, popupKey: popupKey, component: component, claimable: !component}
|
||||
entries.push(entry)
|
||||
global.history.pushState(Object.assign({}, global.history.state || {}, {
|
||||
__h5PopupHistory: {session: sessionId, ids: entries.map((item) => item.id)}
|
||||
}), global.document.title, global.location.href)
|
||||
notify()
|
||||
// 命名弹层触发本轮 Vue 渲染后不再允许其他弹框占用其记录。
|
||||
if (global.Vue) global.Vue.nextTick(() => { entry.claimable = false })
|
||||
return entry
|
||||
}
|
||||
/** index 为需要关闭的最外层弹框位置;Promise<void> 在浏览器完成回退后才结束。 */
|
||||
const closeFrom = (index) => {
|
||||
if (index < 0 || index >= entries.length) return Promise.resolve()
|
||||
if (pending) {
|
||||
// 重复关闭只追踪本次请求时的弹框,避免异步回退结束后误关新打开的弹框。
|
||||
const closingIds = entries.slice(index).map((entry) => entry.id)
|
||||
return pending.promise.then(() => closeFrom(entries.findIndex((entry) => closingIds.includes(entry.id))))
|
||||
}
|
||||
let resolveClose
|
||||
const promise = new Promise((resolve) => { resolveClose = resolve })
|
||||
pending = {promise: promise, resolve: resolveClose}
|
||||
global.history.go(-(entries.length - index))
|
||||
return promise
|
||||
}
|
||||
|
||||
global.addEventListener("popstate", (event) => {
|
||||
if (pendingClear) {
|
||||
event.stopImmediatePropagation()
|
||||
const clear = pendingClear
|
||||
pendingClear = null
|
||||
clear.resolve()
|
||||
const marker = event.state && event.state.__h5PopupHistory
|
||||
if (!entries.length && !pending) {
|
||||
// 已关闭的弹框不因浏览器前进而重新显示,也不把旧弹框记录交给 PJAX。
|
||||
if (marker && marker.session === sessionId) event.stopImmediatePropagation()
|
||||
return
|
||||
}
|
||||
if (!popupStack.length) return
|
||||
|
||||
// 有弹框历史时消费本次返回事件,阻止 PJAX 将页面直接切回上一个业务页面。
|
||||
event.stopImmediatePropagation()
|
||||
const entry = popupStack.pop()
|
||||
invokeClose(entry)
|
||||
const targetIds = marker && marker.session === sessionId ? marker.ids : []
|
||||
const removed = []
|
||||
while (entries.length && !targetIds.includes(entries[entries.length - 1].id)) removed.push(entries.pop())
|
||||
notifying = true
|
||||
try { removed.forEach(dismiss) } finally { notifying = false }
|
||||
notify()
|
||||
const finished = pending
|
||||
pending = null
|
||||
if (finished) finished.resolve()
|
||||
}, true)
|
||||
|
||||
global.h5PopupHistory = {
|
||||
unified: true,
|
||||
register(closeCallback) {
|
||||
tokenSeed += 1
|
||||
const token = "h5-popup-page-" + tokenSeed
|
||||
const token = "h5-popup-" + (++sequence)
|
||||
callbacks.set(token, closeCallback)
|
||||
return token
|
||||
},
|
||||
unregister(token) {
|
||||
callbacks.delete(token)
|
||||
for (let index = popupStack.length - 1; index >= 0; index -= 1) {
|
||||
if (popupStack[index].token === token) popupStack.splice(index, 1)
|
||||
}
|
||||
},
|
||||
open(token, popupKey) {
|
||||
if (!callbacks.has(token)) return
|
||||
const current = popupStack[popupStack.length - 1]
|
||||
if (current && current.token === token && current.popupKey === popupKey) return
|
||||
|
||||
stateSeed += 1
|
||||
const entry = {token:token,popupKey:popupKey,stateId:stateSeed}
|
||||
popupStack.push(entry)
|
||||
const state = Object.assign({}, global.history.state || {}, {
|
||||
__h5PopupHistory: {token:token,popupKey:popupKey,stateId:stateSeed}
|
||||
})
|
||||
global.history.pushState(state, global.document.title, global.location.href)
|
||||
},
|
||||
unregister(token) { this.clear(token).then(() => callbacks.delete(token)) },
|
||||
open(token, popupKey) { if (callbacks.has(token)) open(token, popupKey) },
|
||||
close(token, popupKey) {
|
||||
const current = popupStack[popupStack.length - 1]
|
||||
if (!current || current.token !== token || current.popupKey !== popupKey) return false
|
||||
global.history.back()
|
||||
if (notifying) return false
|
||||
const index = entries.findIndex((entry) => entry.token === token && entry.popupKey === popupKey)
|
||||
if (index < 0) return false
|
||||
closeFrom(index)
|
||||
return true
|
||||
},
|
||||
clear(token) {
|
||||
const entries = popupStack.filter((entry) => entry.token === token)
|
||||
if (!entries.length) return Promise.resolve()
|
||||
|
||||
entries.forEach((entry) => invokeClose(entry))
|
||||
for (let index = popupStack.length - 1; index >= 0; index -= 1) {
|
||||
if (popupStack[index].token === token) popupStack.splice(index, 1)
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
pendingClear = {resolve:resolve}
|
||||
global.history.go(-entries.length)
|
||||
})
|
||||
clear(token) { return closeFrom(entries.findIndex((entry) => entry.token === token)) },
|
||||
clearAll() { return closeFrom(0) },
|
||||
hasOpen() { return entries.length > 0 || !!pending },
|
||||
// PJAX 替换 DOM 前销毁旧页面实例,使业务组件的 beforeDestroy 能正常注销监听。
|
||||
destroyPage() {
|
||||
pageInstances.forEach((instance) => { if (!instance._isDestroyed) instance.$destroy() })
|
||||
pageInstances.clear()
|
||||
}
|
||||
}
|
||||
// 命名弹层 API 适配到同一历史栈,不另行监听 popstate。
|
||||
global.h5HistoryLayerManager = {
|
||||
get stack() { return names() },
|
||||
get pageKey() { return pageKey },
|
||||
register(key, onChange) {
|
||||
pageKey = key
|
||||
pageCallback = typeof onChange === "function" ? onChange : null
|
||||
notify()
|
||||
},
|
||||
ensureRegistered(key) { if (!pageKey) pageKey = key; return true },
|
||||
subscribe(callback) {
|
||||
subscribers.add(callback)
|
||||
callback(names())
|
||||
return () => subscribers.delete(callback)
|
||||
},
|
||||
unregister(key) { if (!key || key === pageKey) this.reset() },
|
||||
open(name) { if (!name) return false; open("named-layer", name); return true },
|
||||
close(name, afterClose = null) {
|
||||
if (notifying) return false
|
||||
const index = name ? entries.findIndex((entry) => entry.popupKey === name) : entries.length - 1
|
||||
if (index < 0) { if (afterClose) afterClose(); return false }
|
||||
closeFrom(index).then(() => { if (afterClose) afterClose() })
|
||||
return true
|
||||
},
|
||||
closeAll(afterClose = null) {
|
||||
const hadEntries = entries.length > 0
|
||||
closeFrom(0).then(() => { if (afterClose) afterClose() })
|
||||
return hadEntries
|
||||
},
|
||||
/** url 为业务页面地址,data 为可选 PJAX 参数;返回 true 表示已接管导航。 */
|
||||
closeAllAndNavigate(url, data = null) {
|
||||
if (!url) return false
|
||||
closeFrom(0).then(() => global.pjaxReplace(url, data))
|
||||
return true
|
||||
},
|
||||
reset() {
|
||||
pageCallback = null
|
||||
pageKey = ""
|
||||
subscribers.clear()
|
||||
return closeFrom(0)
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Vant Popup/Dialog 统一适配已有 v-model 页面,包括 ActionSheet 内部的 Popup。
|
||||
* 已登记弹层复用记录;未登记弹层自动注册,组件销毁时注销 watcher 和回调。
|
||||
*/
|
||||
if (global.Vue) global.Vue.mixin({
|
||||
beforeCreate() {
|
||||
const props = this.$options.props || {}
|
||||
if (props.closeOnPopstate) {
|
||||
// 禁用 Vant 的组件级返回监听,由统一栈按后进先出顺序处理。
|
||||
this.$options.propsData = Object.assign({}, this.$options.propsData, {closeOnPopstate: false})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.$el && this.$el.id === "app" && this.$root === this) pageInstances.add(this)
|
||||
const name = (this.$options.name || "").toLowerCase().replace(/-/g, "")
|
||||
if (name !== "vanpopup" && name !== "vandialog") return
|
||||
this._h5PopupToken = global.h5PopupHistory.register(() => this.$emit("input", false))
|
||||
const sync = (visible) => {
|
||||
if (notifying) return
|
||||
if (visible) {
|
||||
const top = entries[entries.length - 1]
|
||||
if (top && !top.component && top.claimable) top.component = this
|
||||
else open(this._h5PopupToken, "vant-popup-" + this._uid, this)
|
||||
} else {
|
||||
const index = entries.findIndex((entry) => entry.component === this)
|
||||
if (index >= 0) closeFrom(index)
|
||||
}
|
||||
}
|
||||
this._h5PopupUnwatch = this.$watch("value", sync, {immediate: true})
|
||||
},
|
||||
beforeDestroy() {
|
||||
pageInstances.delete(this)
|
||||
if (this._h5PopupUnwatch) this._h5PopupUnwatch()
|
||||
if (this._h5PopupToken) {
|
||||
const index = entries.findIndex((entry) => entry.component === this)
|
||||
if (index >= 0) closeFrom(index)
|
||||
global.h5PopupHistory.unregister(this._h5PopupToken)
|
||||
}
|
||||
}
|
||||
})
|
||||
})(window)
|
||||
|
||||
@@ -37,26 +37,32 @@ module.exports = {
|
||||
<style scoped>
|
||||
.table-column {
|
||||
display: flex;
|
||||
padding: 6px 0;
|
||||
align-items: center;
|
||||
width: calc(50% - 6px);
|
||||
min-width: 0;
|
||||
padding: 4px 0;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.label {
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
color: #98a3b3;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
flex-shrink: 0;
|
||||
max-width: 120px;
|
||||
max-width: 50%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #555;
|
||||
font-size: 14px;
|
||||
flex-grow: 1; /* 动态占据剩余部分 */
|
||||
white-space: nowrap; /* 防止换行 */
|
||||
overflow: hidden; /* 隐藏溢出的部分 */
|
||||
text-overflow: ellipsis; /* 省略号 */
|
||||
min-width: 0;
|
||||
color: #56657a;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
flex-grow: 1;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<template>
|
||||
<van-pull-refresh v-model="tableRefreshing" @refresh="onRefresh">
|
||||
<van-pull-refresh class="table-list" v-model="tableRefreshing" @refresh="onRefresh">
|
||||
<div v-if="tableData.length === 0" class="empty-state">
|
||||
<van-empty description="暂无数据"></van-empty>
|
||||
<slot name="empty">
|
||||
<van-empty description="暂无数据"></van-empty>
|
||||
</slot>
|
||||
</div>
|
||||
<van-list v-if="tableData && tableData.length>0"
|
||||
v-model="tableLoading"
|
||||
@@ -9,7 +11,8 @@
|
||||
finished-text="没有更多了"
|
||||
@load="onLoad">
|
||||
<div class="table-list-container">
|
||||
<div v-for="(row, index) in tableData" :key="index" class="table-list-item">
|
||||
<div v-for="(row, index) in tableData" :key="index" class="table-list-item"
|
||||
:data-row-id="row && row.id ? row.id : ''">
|
||||
<slot name="header" :index="index" :row="row">
|
||||
<div class="item-header">
|
||||
<div class="item-title">{{ calcTitle(row) }}</div>
|
||||
@@ -18,12 +21,12 @@
|
||||
</div>
|
||||
</slot>
|
||||
|
||||
<div style="display: flex;column-gap: 10px"
|
||||
<div class="table-list-content"
|
||||
:style="{'max-height':img ? '100px':'unset', 'overflow': img ? 'hidden':'unset' }">
|
||||
<div class="img-container" v-if="img">
|
||||
<img :src="row[img]" alt="" style="object-fit: cover">
|
||||
<img :src="row[img]" alt="">
|
||||
</div>
|
||||
<div style="width: 100%">
|
||||
<div class="table-list-columns">
|
||||
<slot :index="index" :row="row"></slot>
|
||||
</div>
|
||||
</div>
|
||||
@@ -66,6 +69,10 @@ module.exports = {
|
||||
img: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
show_loading_overlay: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -87,6 +94,33 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 获取当前列表快照。
|
||||
* 返回值包含已加载记录、分页参数和加载完成状态,供业务页面在进入详情前暂存列表现场。
|
||||
*/
|
||||
getListState() {
|
||||
return {
|
||||
tableData: JSON.parse(JSON.stringify(this.tableData)),
|
||||
localPageForm: JSON.parse(JSON.stringify(this.localPageForm)),
|
||||
tableFinished: this.tableFinished
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 恢复列表快照。
|
||||
* state 应包含 tableData、localPageForm 和 tableFinished;返回 true 表示恢复成功。
|
||||
*/
|
||||
restoreListState(state) {
|
||||
if (!state || !Array.isArray(state.tableData)) return false
|
||||
this.$set(this, "tableData", state.tableData)
|
||||
this.$set(this, "localPageForm", {...this.localPageForm, ...(state.localPageForm || {})})
|
||||
this.$set(this, "tableFinished", !!state.tableFinished)
|
||||
this.$set(this, "tableLoading", false)
|
||||
this.$set(this, "tableRefreshing", false)
|
||||
this.$emit("update:page_form", {...this.localPageForm})
|
||||
return true
|
||||
},
|
||||
|
||||
calcTitle(row) {
|
||||
if (!this.title) return ""
|
||||
// 处理key1.key2.key3 这样的形式
|
||||
@@ -111,23 +145,32 @@ module.exports = {
|
||||
|
||||
pageData() {
|
||||
this.tableLoading = true
|
||||
const isInitialLoad = this.tableData.length === 0
|
||||
this.$emit("loading-change", {loading: true, initial: isInitialLoad})
|
||||
|
||||
const loading = createListLoading()
|
||||
this.$axios.post(this.api, this.json ? ({pageForm: JSON.stringify(this.localPageForm)}) : this.localPageForm).then((res) => {
|
||||
const loading = this.show_loading_overlay ? createListLoading() : null
|
||||
return this.$axios.post(
|
||||
this.api,
|
||||
this.json ? ({pageForm: JSON.stringify(this.localPageForm)}) : this.localPageForm,
|
||||
{h5SkeletonLoading: !this.show_loading_overlay}
|
||||
).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.tableData = this.tableData.concat(res.data.list)
|
||||
// 接口异常返回 null 行时不渲染该行,避免业务插槽读取行字段产生渲染异常。
|
||||
const responseList = Array.isArray(res.data.list) ? res.data.list.filter((item) => item) : []
|
||||
this.tableData = this.tableData.concat(responseList)
|
||||
this.localPageForm.totalCount = res.data.totalCount
|
||||
if (this.tableData.length >= this.localPageForm.totalCount) {
|
||||
this.tableFinished = true
|
||||
}
|
||||
this.$emit("update:page_form", {...this.localPageForm})
|
||||
}
|
||||
}).catch(() => {
|
||||
// 公共请求拦截器展示错误;保留当前列表,允许用户再次下拉刷新。
|
||||
}).finally(() => {
|
||||
loading.close()
|
||||
console.log(this.tableLoading)
|
||||
if (loading) loading.close()
|
||||
this.tableLoading = false
|
||||
console.log(this.tableLoading)
|
||||
this.tableRefreshing = false
|
||||
this.$emit("loading-change", {loading: false, initial: isInitialLoad})
|
||||
})
|
||||
},
|
||||
doSearch() {
|
||||
@@ -152,33 +195,36 @@ module.exports = {
|
||||
<style scoped>
|
||||
.table-list-container {
|
||||
padding: 0;
|
||||
margin-top: 10px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item {
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #eaecef;
|
||||
padding: 16px;
|
||||
border: 1px solid #eef1f6;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
padding: 14px;
|
||||
position: relative;
|
||||
margin-bottom: 10px;
|
||||
margin-bottom: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item:last-child {
|
||||
border-bottom: none;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .item-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 10px;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .item-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #1f2f3d;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
color: #263548;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
@@ -190,15 +236,29 @@ module.exports = {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
flex-shrink: 0;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .img-container img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 6px;
|
||||
object-fit: cover;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .table-list-content {
|
||||
display: flex;
|
||||
column-gap: 10px;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .table-list-columns {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
flex-wrap: wrap;
|
||||
column-gap: 12px;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .item-meta {
|
||||
display: flex;
|
||||
@@ -245,48 +305,57 @@ module.exports = {
|
||||
|
||||
.table-list-container .table-list-item .item-actions {
|
||||
display: flex;
|
||||
column-gap: 20px;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
justify-content: end;
|
||||
margin-top: 15px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid #eaecef;
|
||||
margin-top: 10px;
|
||||
padding-top: 10px;
|
||||
border-top: 1px solid #edf1f6;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .action-btn {
|
||||
display: flex;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: end;
|
||||
font-size: 14px;
|
||||
justify-content: center;
|
||||
min-height: 26px;
|
||||
padding: 4px 10px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 14px;
|
||||
background-color: #eaf4ff;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
color: var(--color-primary);
|
||||
padding: 4px 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .action-btn i {
|
||||
margin-right: 6px;
|
||||
font-size: 16px;
|
||||
margin-right: 5px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .action-btn.delete {
|
||||
color: #ff0000;
|
||||
color: #f04444;
|
||||
background-color: #fff0f0;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .action-btn.review {
|
||||
color: #67c23a;
|
||||
background-color: #eef9e9;
|
||||
}
|
||||
|
||||
.table-list-container .empty-state {
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.table-list-container .empty-state i {
|
||||
.empty-state i {
|
||||
font-size: 60px;
|
||||
margin-bottom: 16px;
|
||||
color: #dcdee0;
|
||||
}
|
||||
|
||||
.table-list-container .empty-state p {
|
||||
.empty-state p {
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
<div class="file-preview-container" v-if="fileList && fileList.length > 0">
|
||||
<div class="file-item" v-for="item in fileList" :key="item.id">
|
||||
<img
|
||||
v-if="item.suffix === 'jpg' || item.suffix === 'png' || item.suffix === 'jpeg' || item.suffix === 'gif'"
|
||||
v-if="isImageFile(item)"
|
||||
:src="item.thumbnail"
|
||||
@click.stop="$commonUtil.previewFile(item)"
|
||||
@click.stop="onPreviewFile(item)"
|
||||
class="file-image"
|
||||
/>
|
||||
|
||||
<img
|
||||
v-else
|
||||
:src="$commonUtil.getFileItemShowIcon(item.suffix)"
|
||||
@click.stop="$commonUtil.previewFile(item)"
|
||||
@click.stop="onPreviewFile(item)"
|
||||
class="file-image"
|
||||
/>
|
||||
|
||||
@@ -57,7 +57,12 @@ module.exports = {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
fileList: []
|
||||
fileList: [],
|
||||
imagePreviewInstance: null,
|
||||
imagePreviewContainer: null,
|
||||
imagePreviewHistoryUnsubscribe: null,
|
||||
closingImagePreviewFromHistory: false,
|
||||
imagePreviewLayerName: "h5-file-image-preview"
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -65,22 +70,10 @@ module.exports = {
|
||||
let ids = []
|
||||
if (this.complete_result) {
|
||||
if (Array.isArray(val)) {
|
||||
ids = val.map((item) => {
|
||||
if (item.response.data.includes("=")) {
|
||||
return item?.response?.data.substring(item?.response?.data.lastIndexOf("=") + 1)
|
||||
} else {
|
||||
return item?.response?.data
|
||||
}
|
||||
})
|
||||
ids = val.map((item) => this.resolveFileId(item)).filter((id) => id)
|
||||
} else {
|
||||
try {
|
||||
ids = JSON.parse(val).map((item) => {
|
||||
if (item.response.data.includes("=")) {
|
||||
return item?.response?.data.substring(item?.response?.data.lastIndexOf("=") + 1)
|
||||
} else {
|
||||
return item?.response?.data
|
||||
}
|
||||
})
|
||||
ids = JSON.parse(val).map((item) => this.resolveFileId(item)).filter((id) => id)
|
||||
} catch (err) {
|
||||
this.fileList = []
|
||||
}
|
||||
@@ -100,12 +93,109 @@ module.exports = {
|
||||
this.requestFullFile(ids)
|
||||
},
|
||||
|
||||
// 新版上传组件保存 response.data,迁移的历史附件保留原文件主键 id。
|
||||
resolveFileId(item) {
|
||||
if (!item) {
|
||||
return ""
|
||||
}
|
||||
const fileValue = item.response && item.response.data ? item.response.data : item.id
|
||||
if (typeof fileValue !== "string" || !fileValue) {
|
||||
return ""
|
||||
}
|
||||
return fileValue.includes("=") ? fileValue.substring(fileValue.lastIndexOf("=") + 1) : fileValue
|
||||
},
|
||||
|
||||
requestFullFile(ids) {
|
||||
this.$axios.post("/platform/sys/file/previewFileData", {ids: JSON.stringify(ids)}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.fileList = res.data
|
||||
this.$set(this, "fileList", res.data || [])
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 判断附件是否为图片;item 传完整文件对象,返回 boolean 类型。
|
||||
isImageFile(item) {
|
||||
const suffix = item && item.suffix ? String(item.suffix).toLowerCase() : ""
|
||||
return ["jpg", "jpeg", "png", "gif", "bmp", "webp"].includes(suffix)
|
||||
},
|
||||
|
||||
/**
|
||||
* 预览附件。
|
||||
* item 传 previewFileData 返回的文件对象,需包含 id、suffix、downloadPath;方法无返回值。
|
||||
* 图片会与当前附件列表中的其他图片组成轮播,非图片继续使用公共文件预览逻辑。
|
||||
*/
|
||||
onPreviewFile(item) {
|
||||
if (!this.isImageFile(item)) {
|
||||
this.$commonUtil.previewFile(item)
|
||||
return
|
||||
}
|
||||
if (this.imagePreviewInstance) return
|
||||
const imageFiles = this.fileList.filter((file) => this.isImageFile(file) && file.downloadPath)
|
||||
const startPosition = imageFiles.findIndex((file) => file.id === item.id)
|
||||
if (startPosition < 0) return
|
||||
const previewContainer = document.createElement("div")
|
||||
previewContainer.style.display = "none"
|
||||
imageFiles.forEach((file) => {
|
||||
const image = document.createElement("img")
|
||||
image.src = file.downloadPath
|
||||
image.alt = file.name || ""
|
||||
previewContainer.appendChild(image)
|
||||
})
|
||||
document.body.appendChild(previewContainer)
|
||||
this.$set(this, "closingImagePreviewFromHistory", false)
|
||||
this.$set(this, "imagePreviewContainer", previewContainer)
|
||||
this.$set(this, "imagePreviewInstance", new Viewer(previewContainer, {
|
||||
zIndex: 99999,
|
||||
title: false,
|
||||
initialViewIndex: startPosition,
|
||||
hidden: () => { this.handleImagePreviewHidden() }
|
||||
}))
|
||||
this.imagePreviewInstance.show()
|
||||
window.h5HistoryLayerManager.open(this.imagePreviewLayerName)
|
||||
},
|
||||
|
||||
// Viewer 完全关闭后销毁实例和临时图片容器,并按关闭来源同步浏览器历史。
|
||||
handleImagePreviewHidden() {
|
||||
const closedFromHistory = this.closingImagePreviewFromHistory
|
||||
this.cleanupImagePreview()
|
||||
if (closedFromHistory) {
|
||||
this.$set(this, "closingImagePreviewFromHistory", false)
|
||||
return
|
||||
}
|
||||
if (window.h5HistoryLayerManager.stack.includes(this.imagePreviewLayerName)) {
|
||||
window.h5HistoryLayerManager.close(this.imagePreviewLayerName)
|
||||
}
|
||||
},
|
||||
|
||||
// 清理 Viewer 实例及其临时 DOM;方法无参数、无返回值。
|
||||
cleanupImagePreview() {
|
||||
const previewInstance = this.imagePreviewInstance
|
||||
const previewContainer = this.imagePreviewContainer
|
||||
this.$set(this, "imagePreviewInstance", null)
|
||||
this.$set(this, "imagePreviewContainer", null)
|
||||
if (previewInstance) previewInstance.destroy()
|
||||
if (previewContainer && previewContainer.parentNode) {
|
||||
previewContainer.parentNode.removeChild(previewContainer)
|
||||
}
|
||||
},
|
||||
|
||||
// 浏览器返回导致图片预览层出栈时,仅关闭预览实例,不再重复回退历史记录。
|
||||
syncImagePreviewHistory(stack) {
|
||||
if (!this.imagePreviewInstance || stack.includes(this.imagePreviewLayerName)) return
|
||||
this.$set(this, "closingImagePreviewFromHistory", true)
|
||||
this.imagePreviewInstance.hide()
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$set(this, "imagePreviewHistoryUnsubscribe", window.h5HistoryLayerManager.subscribe((stack) => {
|
||||
this.syncImagePreviewHistory(stack)
|
||||
}))
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.imagePreviewHistoryUnsubscribe) this.imagePreviewHistoryUnsubscribe()
|
||||
if (this.imagePreviewInstance || this.imagePreviewContainer) {
|
||||
this.$set(this, "closingImagePreviewFromHistory", true)
|
||||
this.cleanupImagePreview()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,28 @@
|
||||
<template>
|
||||
<div class="h5-signature">
|
||||
<div v-if="!showSignaturePanel" class="main-panel">
|
||||
<slot v-if="$slots.default"></slot>
|
||||
<template v-else>
|
||||
<van-button @click="openSignature" class="open-button" size="middle" plain native-type="button">打开签字板</van-button>
|
||||
<van-image :src="signatureContent"></van-image>
|
||||
</template>
|
||||
<slot v-if="$slots.default"></slot>
|
||||
<div v-else class="signature-entry">
|
||||
<!-- 未签名时展示统一空状态和入口,组件放入 van-field 时仍保持完整宽度。 -->
|
||||
<div v-if="!signatureContent" class="signature-entry-panel">
|
||||
<van-icon class="signature-placeholder-icon" name="edit"></van-icon>
|
||||
<div class="signature-placeholder-text">请完成本人手写签名</div>
|
||||
<van-button @click="openSignature" class="signature-open-button" block plain
|
||||
native-type="button">进入签字板</van-button>
|
||||
</div>
|
||||
|
||||
<!-- 已签名时直接预览结果,并在下方提供统一的重新签名入口。 -->
|
||||
<div v-else class="signature-entry-panel signature-entry-panel--completed">
|
||||
<van-image :src="signatureContent" class="signature-preview" fit="contain"></van-image>
|
||||
<div class="signature-completed-text">
|
||||
<van-icon name="passed"></van-icon>
|
||||
<span>已完成本人手写签名</span>
|
||||
</div>
|
||||
</div>
|
||||
<button v-if="signatureContent" @click="openSignature" class="signature-reset-button"
|
||||
type="button">重新签名</button>
|
||||
</div>
|
||||
<van-popup v-model="showSignaturePanel" :style="{ height: '100vh', width: '100vw' }">
|
||||
<van-popup v-model="showSignaturePanel" :close-on-click-overlay="false"
|
||||
:style="{ height: '100vh', width: '100vw' }" @close="handleSignaturePopupClose">
|
||||
<signature @save="save"></signature>
|
||||
</van-popup>
|
||||
</div>
|
||||
@@ -36,14 +51,43 @@ module.exports = {
|
||||
data() {
|
||||
return {
|
||||
signatureContent: null,
|
||||
showSignaturePanel: false
|
||||
|
||||
|
||||
showSignaturePanel: false,
|
||||
historyLayerName: "",
|
||||
historyLayerUnsubscribe: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
|
||||
/**
|
||||
* 打开签字板。
|
||||
* 无请求参数;优先向全局历史栈增加当前签字弹层,返回值为空。
|
||||
*/
|
||||
openSignature() {
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (manager && manager.open(this.historyLayerName)) return
|
||||
this.showSignaturePanel = true
|
||||
},
|
||||
|
||||
// 保存成功或业务主动关闭时同步回退签字弹层历史,管理器不可用时直接关闭 Popup。
|
||||
closeSignaturePanel() {
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (manager && manager.close(this.historyLayerName)) return
|
||||
this.showSignaturePanel = false
|
||||
},
|
||||
|
||||
// Vant 组件自行关闭时仅处理仍位于栈顶的签字层,避免返回同步触发重复 history.back。
|
||||
handleSignaturePopupClose() {
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (!manager) return
|
||||
const stack = manager.stack
|
||||
if (stack[stack.length - 1] === this.historyLayerName) {
|
||||
manager.close(this.historyLayerName)
|
||||
}
|
||||
},
|
||||
|
||||
save(signature) {
|
||||
const file = this.base64ToFile(signature, "signature.png")
|
||||
const formData = new FormData()
|
||||
@@ -59,11 +103,20 @@ module.exports = {
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
alert("保存成功")
|
||||
this.showSignaturePanel = false
|
||||
// 保存成功后使用项目统一的 Vant 反馈,避免浏览器原生弹框阻塞签字流程。
|
||||
this.$toast.success({
|
||||
message: "签名保存成功",
|
||||
duration: 1500,
|
||||
forbidClick: true
|
||||
})
|
||||
this.$emit("input", res.data)
|
||||
this.closeSignaturePanel()
|
||||
} else {
|
||||
alert("保存失败")
|
||||
// 接口返回失败时保留签字板,方便用户重试。
|
||||
this.$toast.fail({
|
||||
message: res.msg || "签名保存失败,请重试",
|
||||
duration: 2000
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -86,27 +139,114 @@ module.exports = {
|
||||
return new File([blob], filename, { type: contentType })
|
||||
}
|
||||
},
|
||||
created() {}
|
||||
mounted() {
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (!manager || typeof manager.ensureRegistered !== "function" || typeof manager.subscribe !== "function") return
|
||||
|
||||
// 每个组件实例使用唯一弹层名称,同一页面存在多个签字组件时互不影响。
|
||||
this.historyLayerName = "h5-signature-" + this._uid
|
||||
manager.ensureRegistered("h5-signature-page-" + window.location.pathname + window.location.search)
|
||||
this.historyLayerUnsubscribe = manager.subscribe((stack) => {
|
||||
this.showSignaturePanel = stack.includes(this.historyLayerName)
|
||||
})
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (typeof this.historyLayerUnsubscribe === "function") {
|
||||
this.historyLayerUnsubscribe()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.h5-signature {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.main-panel {
|
||||
position: relative;
|
||||
flex-direction: column-reverse;
|
||||
.signature-entry {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
row-gap: 10px;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.main-panel .van-image {
|
||||
.signature-entry-panel {
|
||||
width: 100%;
|
||||
min-height: 150px;
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
border: 1px dashed #dfe6ef;
|
||||
border-radius: 9px;
|
||||
background: #fbfcfe;
|
||||
}
|
||||
|
||||
.main-panel .open-button {
|
||||
color: var(--color-primary);
|
||||
.signature-placeholder-icon {
|
||||
margin-bottom: 6px;
|
||||
color: #c7cfda;
|
||||
font-size: 38px;
|
||||
}
|
||||
|
||||
.signature-placeholder-text {
|
||||
margin-bottom: 12px;
|
||||
color: #9aa4b2;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.signature-open-button {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
color: var(--color-primary, #1989fa);
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
background: linear-gradient(90deg, #f0f7ff, #f5f9ff);
|
||||
border-color: #d8e9ff;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
.signature-entry-panel--completed {
|
||||
min-height: 150px;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.signature-preview {
|
||||
width: 100%;
|
||||
height: 96px;
|
||||
background: #fff;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.signature-completed-text {
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #5f6b7a;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.signature-completed-text .van-icon {
|
||||
margin-right: 5px;
|
||||
color: #28a745;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.signature-reset-button {
|
||||
align-self: center;
|
||||
margin-top: 10px;
|
||||
padding: 3px 12px;
|
||||
color: var(--color-primary, #1989fa);
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -57,7 +57,16 @@ module.exports = {
|
||||
},
|
||||
save() {
|
||||
if (signature.isEmpty()) {
|
||||
alert("请签字后再保存")
|
||||
// H5 页面使用统一的 Vant 提示;未加载 Vant 的独立签字页保留原生提示作为兼容兜底。
|
||||
if (typeof this.$toast === "function") {
|
||||
this.$toast({
|
||||
message: "请先完成手写签名",
|
||||
icon: "edit",
|
||||
duration: 2000
|
||||
})
|
||||
} else {
|
||||
alert("请先完成手写签名")
|
||||
}
|
||||
return
|
||||
}
|
||||
// const png = signature.getPNG()
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
<template>
|
||||
<van-dropdown-item :options="yearOptions" @change="yearChange" v-model="year"></van-dropdown-item>
|
||||
<van-dropdown-item
|
||||
:options="yearOptions"
|
||||
v-model="year"
|
||||
@change="yearChange"
|
||||
@open="$emit('open')"
|
||||
@close="$emit('close')"
|
||||
></van-dropdown-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -17,7 +23,7 @@ module.exports = {
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler: function (val) {
|
||||
handler(val) {
|
||||
this.year = val
|
||||
},
|
||||
immediate: true
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
<script src="${base!}/assets/platform/js/mixin/styleMixin.js"></script>
|
||||
<script src="${base!}/assets/platform/js/tool/businessTool.js"></script>
|
||||
<script src="${base!}/assets/platform/js/util/h5AutoShowError.js"></script>
|
||||
<script src="${base!}/assets/platform/js/util/h5PopupHistory.js"></script>
|
||||
|
||||
<!--富文本编辑器-->
|
||||
<link rel="stylesheet" href="${base!}/assets/platform/plugins/wangEditor4/wangEditor.css"/>
|
||||
@@ -84,7 +85,7 @@
|
||||
vant.Form.props.showErrorMessage.default = false
|
||||
vant.ActionSheet.props.lazyRender.default = false
|
||||
|
||||
function toggleShowBar() {
|
||||
const toggleShowBar = () => {
|
||||
if (["/platform/h5/home", "/platform/home"].includes(window.location.pathname)) {
|
||||
document.querySelector("body>.main-page").classList.add("page-showtabbar")
|
||||
} else {
|
||||
@@ -96,8 +97,10 @@
|
||||
vant.Toast.allowMultiple()
|
||||
|
||||
//初始化pjax
|
||||
;(function initPjax() {
|
||||
;(() => {
|
||||
if ($.support.pjax) {
|
||||
// jquery-pjax 的历史缓存读取全局默认值;必须在初始化前关闭,避免返回时恢复缺少 Vue 动态样式的旧 DOM。
|
||||
$.pjax.defaults.maxCacheLength = 0
|
||||
$(document).pjax("a[data-pjax]", "#container", {
|
||||
maxCacheLength: 0,
|
||||
push: true,
|
||||
@@ -105,39 +108,44 @@
|
||||
fragment: "#container",
|
||||
timeout: 8000
|
||||
})
|
||||
$(document).on("pjax:send", function () {
|
||||
$(document).on("pjax:send", () => {
|
||||
window.h5HistoryLayerManager.reset()
|
||||
showH5PageSkeleton()
|
||||
NProgress.start()
|
||||
window.customStyleList = document.querySelectorAll('style[id^="style-"]')
|
||||
})
|
||||
$(document).on("pjax:complete", function () {
|
||||
$(document).on("pjax:complete", () => {
|
||||
// PJAX 替换 #container 时可能已经移除旧样式节点,清理前需兼容节点脱离 DOM 的情况。
|
||||
if (window.customStyleList) {
|
||||
window.customStyleList.forEach((style) => {
|
||||
style.parentNode.removeChild(style)
|
||||
if (style && style.parentNode) {
|
||||
style.parentNode.removeChild(style)
|
||||
}
|
||||
})
|
||||
window.customStyleList = null
|
||||
}
|
||||
NProgress.done()
|
||||
hideH5PageSkeleton()
|
||||
toggleShowBar()
|
||||
})
|
||||
|
||||
// 监听浏览器的前进和后退操作
|
||||
$(window).on("popstate", function (event) {
|
||||
if (event.originalEvent.state) {
|
||||
// 如果存在历史记录状态,触发 Pjax 加载对应内容
|
||||
$.pjax({
|
||||
url: event.originalEvent.state.url,
|
||||
container: "#container",
|
||||
fragment: "#container",
|
||||
timeout: 8000,
|
||||
push: false,
|
||||
scrollTo: false
|
||||
})
|
||||
}
|
||||
$(document).on("pjax:beforeReplace", () => {
|
||||
window.h5PopupHistory.destroyPage()
|
||||
})
|
||||
|
||||
}
|
||||
})()
|
||||
|
||||
function pjaxReplace(url, data = null) {
|
||||
$.pjax({
|
||||
window.pjaxReplace = (url, data = null) => {
|
||||
// 导航必须等待弹框历史退栈,避免返回时恢复已关闭的弹框记录。
|
||||
if (window.h5PopupHistory.hasOpen()) return window.h5PopupHistory.clearAll().then(() => pjaxReplace(url, data))
|
||||
showH5PageSkeleton(url)
|
||||
// 疗休养报名页面使用独立 H5 布局,其中包含图片懒加载等专用初始化逻辑。
|
||||
// 禁止通过公共 PJAX 只替换页面片段,否则专用布局脚本不会执行,首次进入会出现图片懒加载指令未注册。
|
||||
if (url && url.indexOf("/platform/tour/signup/h5") === 0) {
|
||||
window.location.href = url
|
||||
return
|
||||
}
|
||||
return $.pjax({
|
||||
url: url,
|
||||
container: "#container",
|
||||
maxCacheLength: 0,
|
||||
@@ -149,17 +157,97 @@
|
||||
})
|
||||
}
|
||||
|
||||
function createListLoading(icon = "https://preview.qiantucdn.com/58pic/35/39/61/62K58PICb88i68HEwVnm5_PIC2018.gif!qt480") {
|
||||
return vant.Toast.loading({
|
||||
icon: icon,
|
||||
forbidClick: true,
|
||||
loadingType: "spinner",
|
||||
duration: 0,
|
||||
className: "custom-list-loading"
|
||||
window.pjaxReplace = pjaxReplace
|
||||
|
||||
// 仅在疗休养 H5 页面切换期间显示骨架,避免影响共用布局下的其他业务模块。
|
||||
const showH5PageSkeleton = (targetUrl) => {
|
||||
const pageUrl = targetUrl || window.location.pathname
|
||||
if (pageUrl.indexOf("/platform/tour/") !== 0) return
|
||||
const skeleton = document.getElementById("tour-page-transition-skeleton")
|
||||
if (skeleton) skeleton.classList.add("is-visible")
|
||||
}
|
||||
|
||||
const hideH5PageSkeleton = () => {
|
||||
const skeleton = document.getElementById("tour-page-transition-skeleton")
|
||||
if (skeleton) skeleton.classList.remove("is-visible")
|
||||
}
|
||||
|
||||
// 从疗休养完整页面返回公共 H5 页面时可能命中 BFCache,需要清除离开前保留的骨架状态。
|
||||
window.addEventListener("pageshow", () => {
|
||||
hideH5PageSkeleton()
|
||||
})
|
||||
|
||||
let h5GlobalLoading = null
|
||||
let h5PendingRequestCount = 0
|
||||
let h5ManualLoadingCount = 0
|
||||
|
||||
const showH5GlobalLoading = (icon = "/assets/mobile/img/common/smart-union-loading-red.svg") => {
|
||||
if (!h5GlobalLoading) {
|
||||
h5GlobalLoading = vant.Toast.loading({
|
||||
icon: icon,
|
||||
message: "加载中...",
|
||||
forbidClick: true,
|
||||
loadingType: "spinner",
|
||||
duration: 0,
|
||||
className: "custom-list-loading"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const closeH5GlobalLoading = () => {
|
||||
if (h5PendingRequestCount > 0 || h5ManualLoadingCount > 0 || !h5GlobalLoading) return
|
||||
h5GlobalLoading.clear()
|
||||
h5GlobalLoading = null
|
||||
}
|
||||
|
||||
// 请求数量归零后关闭统一 Loading;使用页面骨架屏的请求不叠加遮罩。
|
||||
window.bindH5AxiosLoading = (axiosService) => {
|
||||
if (axiosService.__h5LoadingBound) return
|
||||
axiosService.__h5LoadingBound = true
|
||||
axiosService.interceptors.request.use((config) => {
|
||||
if (config.h5SkeletonLoading) return config
|
||||
h5PendingRequestCount++
|
||||
showH5GlobalLoading()
|
||||
return config
|
||||
}, (error) => {
|
||||
return Promise.reject(error)
|
||||
})
|
||||
|
||||
axiosService.interceptors.response.use((response) => {
|
||||
if (!response.config || !response.config.h5SkeletonLoading) {
|
||||
h5PendingRequestCount = Math.max(0, h5PendingRequestCount - 1)
|
||||
closeH5GlobalLoading()
|
||||
}
|
||||
return response
|
||||
}, (error) => {
|
||||
if (!error.config || !error.config.h5SkeletonLoading) {
|
||||
h5PendingRequestCount = Math.max(0, h5PendingRequestCount - 1)
|
||||
closeH5GlobalLoading()
|
||||
}
|
||||
return Promise.reject(error)
|
||||
})
|
||||
}
|
||||
|
||||
function historyBack(func) {
|
||||
const createListLoading = (icon = "/assets/mobile/img/common/smart-union-loading-red.svg") => {
|
||||
h5ManualLoadingCount++
|
||||
showH5GlobalLoading(icon)
|
||||
let cleared = false
|
||||
const closeLoading = () => {
|
||||
if (cleared) return
|
||||
cleared = true
|
||||
h5ManualLoadingCount = Math.max(0, h5ManualLoadingCount - 1)
|
||||
closeH5GlobalLoading()
|
||||
}
|
||||
|
||||
return {
|
||||
clear: closeLoading,
|
||||
close: closeLoading
|
||||
}
|
||||
}
|
||||
|
||||
const historyBack = (func) => {
|
||||
if (window.h5PopupHistory.hasOpen()) { window.h5HistoryLayerManager.close(); return }
|
||||
showH5PageSkeleton()
|
||||
if (window.history.length > 1) {
|
||||
window.history.back()
|
||||
} else {
|
||||
@@ -168,7 +256,8 @@
|
||||
func && typeof func === "function" && func()
|
||||
}
|
||||
|
||||
function returnH5Home(activeTab = "home") {
|
||||
const returnH5Home = (activeTab = "home") => {
|
||||
if (window.h5PopupHistory.hasOpen()) return window.h5PopupHistory.clearAll().then(() => returnH5Home(activeTab))
|
||||
if (window.store && typeof window.store.commit === "function") {
|
||||
window.store.commit("setActiveTarBar", activeTab || "home")
|
||||
}
|
||||
@@ -177,10 +266,10 @@
|
||||
|
||||
Vue.mixin({
|
||||
methods: {
|
||||
historyBack: function(func = ()=>{}) {
|
||||
historyBack(func = ()=>{}) {
|
||||
historyBack(func);
|
||||
},
|
||||
returnH5Home: function(activeTab = "home") {
|
||||
returnH5Home(activeTab = "home") {
|
||||
returnH5Home(activeTab)
|
||||
}
|
||||
},
|
||||
@@ -405,10 +494,12 @@
|
||||
Vue.prototype.$axios = commonUtil.axiosService()
|
||||
Vue.prototype.$downLoad = commonUtil.downLoadService.bind(commonUtil)
|
||||
Vue.prototype.$pjaxReplace = pjaxReplace
|
||||
Vue.prototype.$showH5PageSkeleton = showH5PageSkeleton
|
||||
Vue.prototype.$hideH5PageSkeleton = hideH5PageSkeleton
|
||||
</script>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
const h5ComponentVersion = "20260524"
|
||||
const h5ComponentVersion = "20260821_2"
|
||||
Vue.component("rich-text", httpVueLoader("/components/plugins/sysRichTextView/index.vue?v=" + h5ComponentVersion))
|
||||
Vue.component("h5-file-upload", httpVueLoader("/components/plugins/sysUpload/h5Index.vue?v=" + h5ComponentVersion))
|
||||
Vue.component("h5-signature", httpVueLoader("/components/plugins/sysSignature/h5Index.vue?v=" + h5ComponentVersion))
|
||||
@@ -450,9 +541,41 @@
|
||||
.h5-voice-menu .voice-menu-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tour-page-transition-skeleton {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 30000;
|
||||
display: none;
|
||||
padding: 58px 12px 20px;
|
||||
background: #f3f7fd;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.tour-page-transition-skeleton.is-visible { display: block; }
|
||||
.tour-page-transition-skeleton__nav,
|
||||
.tour-page-transition-skeleton__hero,
|
||||
.tour-page-transition-skeleton__line,
|
||||
.tour-page-transition-skeleton__card {
|
||||
background: linear-gradient(90deg, #edf2f8 25%, #f8fbff 37%, #edf2f8 63%);
|
||||
background-size: 400% 100%;
|
||||
animation: tour-page-skeleton-loading 1.35s ease infinite;
|
||||
}
|
||||
.tour-page-transition-skeleton__nav { position: absolute; top: 0; left: 0; right: 0; height: 46px; background-color: #fff; }
|
||||
.tour-page-transition-skeleton__hero { height: 154px; border-radius: 14px; }
|
||||
.tour-page-transition-skeleton__line { width: 42%; height: 18px; margin: 18px 2px 12px; border-radius: 9px; }
|
||||
.tour-page-transition-skeleton__card { height: 126px; margin-top: 12px; border-radius: 14px; }
|
||||
@keyframes tour-page-skeleton-loading { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="tour-page-transition-skeleton" class="tour-page-transition-skeleton" aria-hidden="true">
|
||||
<div class="tour-page-transition-skeleton__nav"></div>
|
||||
<div class="tour-page-transition-skeleton__hero"></div>
|
||||
<div class="tour-page-transition-skeleton__line"></div>
|
||||
<div class="tour-page-transition-skeleton__card"></div>
|
||||
<div class="tour-page-transition-skeleton__card"></div>
|
||||
<div class="tour-page-transition-skeleton__card"></div>
|
||||
</div>
|
||||
<div class="main-page page-showtabbar">
|
||||
<div class="page-wrapper">
|
||||
<div id="container">${layoutContent}</div>
|
||||
|
||||
@@ -11,11 +11,38 @@
|
||||
<link rel="stylesheet" href="${base!}/assets/platform/css/common.css?v=20260524"/>
|
||||
<link rel="stylesheet" href="${base!}/assets/platform/css/h5.css?v=20260524"/>
|
||||
|
||||
<style>
|
||||
.tour-page-transition-skeleton {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 30000;
|
||||
display: none;
|
||||
padding: 58px 12px 20px;
|
||||
background: #f3f7fd;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.tour-page-transition-skeleton.is-visible { display: block; }
|
||||
.tour-page-transition-skeleton__nav,
|
||||
.tour-page-transition-skeleton__hero,
|
||||
.tour-page-transition-skeleton__line,
|
||||
.tour-page-transition-skeleton__card {
|
||||
background: linear-gradient(90deg, #edf2f8 25%, #f8fbff 37%, #edf2f8 63%);
|
||||
background-size: 400% 100%;
|
||||
animation: tour-page-skeleton-loading 1.35s ease infinite;
|
||||
}
|
||||
.tour-page-transition-skeleton__nav { position: absolute; top: 0; left: 0; right: 0; height: 46px; background-color: #fff; }
|
||||
.tour-page-transition-skeleton__hero { height: 154px; border-radius: 14px; }
|
||||
.tour-page-transition-skeleton__line { width: 42%; height: 18px; margin: 18px 2px 12px; border-radius: 9px; }
|
||||
.tour-page-transition-skeleton__card { height: 126px; margin-top: 12px; border-radius: 14px; }
|
||||
@keyframes tour-page-skeleton-loading { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
|
||||
</style>
|
||||
|
||||
<script src="${base!}/assets/platform/plugins/vue/vue.js?v=20260524"></script>
|
||||
<script src="${base!}/assets/platform/plugins/vant/index.js?v=20260524"></script>
|
||||
<script src="${base!}/assets/platform/plugins/axios/axios.js?v=20260524"></script>
|
||||
<script src="${base!}/assets/platform/plugins/jquery/jquery.js?v=20260524"></script>
|
||||
<script src="${base!}/assets/platform/js/util/commonUtil.js?v=20260524"></script>
|
||||
<script src="${base!}/assets/platform/js/util/h5PopupHistory.js?v=20260830"></script>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
Vue.config.devtools = true
|
||||
@@ -31,12 +58,12 @@
|
||||
Vue.use(vant.Lazyload)
|
||||
}
|
||||
|
||||
window.loadScriptOnce = function(src) {
|
||||
window.loadScriptOnce = (src) => {
|
||||
window.__scriptLoadingMap = window.__scriptLoadingMap || {}
|
||||
if (window.__scriptLoadingMap[src]) {
|
||||
return window.__scriptLoadingMap[src]
|
||||
}
|
||||
window.__scriptLoadingMap[src] = new Promise(function(resolve, reject) {
|
||||
window.__scriptLoadingMap[src] = new Promise((resolve, reject) => {
|
||||
const existing = document.querySelector('script[src="' + src + '"]')
|
||||
if (existing) {
|
||||
resolve()
|
||||
@@ -44,10 +71,10 @@
|
||||
}
|
||||
const script = document.createElement("script")
|
||||
script.src = src
|
||||
script.onload = function() {
|
||||
script.onload = () => {
|
||||
resolve()
|
||||
}
|
||||
script.onerror = function() {
|
||||
script.onerror = () => {
|
||||
reject(new Error("script load failed: " + src))
|
||||
}
|
||||
document.head.appendChild(script)
|
||||
@@ -55,12 +82,12 @@
|
||||
return window.__scriptLoadingMap[src]
|
||||
}
|
||||
|
||||
window.loadStyleOnce = function(href) {
|
||||
window.loadStyleOnce = (href) => {
|
||||
window.__styleLoadingMap = window.__styleLoadingMap || {}
|
||||
if (window.__styleLoadingMap[href]) {
|
||||
return window.__styleLoadingMap[href]
|
||||
}
|
||||
window.__styleLoadingMap[href] = new Promise(function(resolve, reject) {
|
||||
window.__styleLoadingMap[href] = new Promise((resolve, reject) => {
|
||||
const existing = document.querySelector('link[href="' + href + '"]')
|
||||
if (existing) {
|
||||
resolve()
|
||||
@@ -69,10 +96,10 @@
|
||||
const link = document.createElement("link")
|
||||
link.rel = "stylesheet"
|
||||
link.href = href
|
||||
link.onload = function() {
|
||||
link.onload = () => {
|
||||
resolve()
|
||||
}
|
||||
link.onerror = function() {
|
||||
link.onerror = () => {
|
||||
reject(new Error("style load failed: " + href))
|
||||
}
|
||||
document.head.appendChild(link)
|
||||
@@ -123,13 +150,38 @@
|
||||
}
|
||||
}
|
||||
|
||||
function historyBack(fallbackUrl, func) {
|
||||
// 疗休养页面跳转前统一展示结构化骨架,避免旧页面或未完成样式短暂闪现。
|
||||
const showH5PageSkeleton = () => {
|
||||
const skeleton = document.getElementById("tour-page-transition-skeleton")
|
||||
if (skeleton) skeleton.classList.add("is-visible")
|
||||
}
|
||||
|
||||
const hideH5PageSkeleton = () => {
|
||||
const skeleton = document.getElementById("tour-page-transition-skeleton")
|
||||
if (skeleton) skeleton.classList.remove("is-visible")
|
||||
}
|
||||
|
||||
// 浏览器返回或前进时可能直接恢复 BFCache 页面,需要主动关闭离开页面前显示的骨架层。
|
||||
// 此处只恢复页面展示,不刷新数据,从而保留线路列表的筛选条件、分页和滚动位置。
|
||||
window.addEventListener("pageshow", () => {
|
||||
hideH5PageSkeleton()
|
||||
})
|
||||
|
||||
const pjaxReplace = (url) => {
|
||||
if (window.h5PopupHistory.hasOpen()) return window.h5PopupHistory.clearAll().then(() => pjaxReplace(url))
|
||||
showH5PageSkeleton()
|
||||
window.location.href = url
|
||||
}
|
||||
|
||||
const historyBack = (fallbackUrl, func) => {
|
||||
if (window.h5PopupHistory.hasOpen()) { window.h5HistoryLayerManager.close(); return }
|
||||
if (typeof fallbackUrl === "function") {
|
||||
func = fallbackUrl
|
||||
fallbackUrl = "/platform/h5/home"
|
||||
} else if (typeof fallbackUrl !== "string" || !fallbackUrl) {
|
||||
fallbackUrl = "/platform/h5/home"
|
||||
}
|
||||
showH5PageSkeleton()
|
||||
if (window.history.length > 1) {
|
||||
window.history.back()
|
||||
} else {
|
||||
@@ -138,17 +190,18 @@
|
||||
func && typeof func === "function" && func()
|
||||
}
|
||||
|
||||
function returnH5Home(activeTab = "home") {
|
||||
const returnH5Home = (activeTab = "home") => {
|
||||
if (window.h5PopupHistory.hasOpen()) return window.h5PopupHistory.clearAll().then(() => returnH5Home(activeTab))
|
||||
store.commit("setActiveTarBar", activeTab || "home")
|
||||
window.location.replace("/platform/h5/home")
|
||||
}
|
||||
|
||||
Vue.mixin({
|
||||
methods: {
|
||||
historyBack: function(fallbackUrl = "/platform/h5/home", func = function(){}) {
|
||||
historyBack(fallbackUrl = "/platform/h5/home", func = ()=>{}) {
|
||||
historyBack(fallbackUrl, func)
|
||||
},
|
||||
returnH5Home: function(activeTab = "home") {
|
||||
returnH5Home(activeTab = "home") {
|
||||
returnH5Home(activeTab)
|
||||
}
|
||||
}
|
||||
@@ -158,9 +211,21 @@
|
||||
Vue.prototype.$auth = commonUtil.authService()
|
||||
Vue.prototype.$axios = commonUtil.axiosService()
|
||||
Vue.prototype.$downLoad = commonUtil.downLoadService.bind(commonUtil)
|
||||
window.pjaxReplace = pjaxReplace
|
||||
Vue.prototype.$pjaxReplace = pjaxReplace
|
||||
Vue.prototype.$showH5PageSkeleton = showH5PageSkeleton
|
||||
Vue.prototype.$hideH5PageSkeleton = hideH5PageSkeleton
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="tour-page-transition-skeleton" class="tour-page-transition-skeleton" aria-hidden="true">
|
||||
<div class="tour-page-transition-skeleton__nav"></div>
|
||||
<div class="tour-page-transition-skeleton__hero"></div>
|
||||
<div class="tour-page-transition-skeleton__line"></div>
|
||||
<div class="tour-page-transition-skeleton__card"></div>
|
||||
<div class="tour-page-transition-skeleton__card"></div>
|
||||
<div class="tour-page-transition-skeleton__card"></div>
|
||||
</div>
|
||||
<div class="main-page">
|
||||
<div class="page-wrapper">
|
||||
<div id="container">${layoutContent}</div>
|
||||
|
||||
@@ -3,79 +3,448 @@ layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style>
|
||||
.list-card {
|
||||
border-radius: 0;
|
||||
body {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.list-card-body {
|
||||
/* width: calc(100% - 140px);
|
||||
display: flex;*/
|
||||
width: calc(100% - 140px);
|
||||
.culture-activity-page {
|
||||
min-height: 100vh;
|
||||
padding-bottom: calc(24px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.culture-activity-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.culture-activity-page .van-nav-bar__title {
|
||||
color: #1f2937;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.culture-activity-page .van-nav-bar .van-icon,
|
||||
.culture-activity-page .van-nav-bar__text {
|
||||
color: #397fbd;
|
||||
}
|
||||
|
||||
.culture-activity-content {
|
||||
padding: 12px 12px 0;
|
||||
}
|
||||
|
||||
.culture-activity-hero {
|
||||
position: relative;
|
||||
height: 134px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
color: #fff;
|
||||
background-color: #247fe8;
|
||||
box-shadow: 0 8px 20px rgba(51, 117, 219, .18);
|
||||
}
|
||||
|
||||
.culture-activity-hero__image {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
|
||||
.culture-activity-hero__copy {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
width: 64%;
|
||||
height: 100%;
|
||||
padding-left: 16px;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
background: linear-gradient(90deg, rgba(22, 112, 232, .98) 0%, rgba(22, 112, 232, .88) 52%, rgba(22, 112, 232, 0) 100%);
|
||||
}
|
||||
|
||||
.culture-activity-hero__title {
|
||||
font-size: 25px;
|
||||
line-height: 34px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 1px;
|
||||
text-shadow: 0 2px 6px rgba(17, 86, 182, .18);
|
||||
}
|
||||
|
||||
.culture-activity-hero__subtitle {
|
||||
margin-top: 4px;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
letter-spacing: .5px;
|
||||
opacity: .95;
|
||||
}
|
||||
|
||||
.culture-activity-sticky {
|
||||
padding: 10px 0 1px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.van-sticky--fixed .culture-activity-sticky {
|
||||
padding-right: 12px;
|
||||
padding-left: 12px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.culture-activity-search {
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.culture-activity-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.culture-activity-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.culture-activity-search .van-field__control::placeholder {
|
||||
color: #a7b0bf;
|
||||
}
|
||||
|
||||
.culture-activity-filter {
|
||||
margin: 0 0 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
transition: border-radius .18s ease;
|
||||
}
|
||||
|
||||
.culture-activity-filter.is-open {
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
.culture-activity-filter .van-dropdown-menu__bar {
|
||||
height: 44px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.culture-activity-filter .van-dropdown-menu__item {
|
||||
min-width: 0;
|
||||
flex: 1 1 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.culture-activity-filter .van-dropdown-menu__item:last-child {
|
||||
flex-grow: 1.35;
|
||||
}
|
||||
|
||||
.culture-activity-filter .van-dropdown-menu__title {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
padding: 0 15px 0 4px;
|
||||
overflow: hidden;
|
||||
color: #66758a;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.culture-activity-filter .van-dropdown-menu__title::after {
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
.culture-activity-filter .van-dropdown-menu__title--active,
|
||||
.culture-activity-filter .van-dropdown-item__option--active,
|
||||
.culture-activity-filter .van-dropdown-item__option--active .van-dropdown-item__icon {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.culture-activity-filter .van-dropdown-menu__title--down::after {
|
||||
border-color: transparent transparent #1989fa #1989fa;
|
||||
}
|
||||
|
||||
.culture-activity-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
margin: 0 12px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0 0 12px 12px;
|
||||
box-shadow: 0 10px 24px rgba(31, 65, 108, .14);
|
||||
}
|
||||
|
||||
.culture-activity-filter .van-dropdown-item__option {
|
||||
min-height: 48px;
|
||||
padding: 0 16px;
|
||||
color: #46566c;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.culture-activity-filter .van-cell::after {
|
||||
right: 16px;
|
||||
left: 16px;
|
||||
}
|
||||
|
||||
.culture-activity-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.list-card-body .title {
|
||||
.culture-activity-card {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.culture-activity-card__cover,
|
||||
.culture-activity-card__cover-state {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
background-color: #edf4fc;
|
||||
}
|
||||
|
||||
.culture-activity-card__cover {
|
||||
display: block;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.culture-activity-card__cover-state {
|
||||
flex-direction: column;
|
||||
row-gap: 8px;
|
||||
color: #8da1ba;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.culture-activity-card__cover-state .van-icon {
|
||||
font-size: 34px;
|
||||
}
|
||||
|
||||
.culture-activity-card__cover-state.is-error {
|
||||
color: #c27b75;
|
||||
background-color: #fff3f1;
|
||||
}
|
||||
|
||||
.culture-activity-card__body {
|
||||
padding: 12px 38px 14px 14px;
|
||||
}
|
||||
|
||||
.culture-activity-card__title {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
color: #303846;
|
||||
font-size: 14px;
|
||||
line-height: 21px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.culture-activity-card__time {
|
||||
margin-top: 4px;
|
||||
color: #98a2b2;
|
||||
font-size: 12px;
|
||||
line-height: 17px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.culture-activity-card__meta {
|
||||
margin-top: 10px;
|
||||
padding-top: 9px;
|
||||
border-top: 1px solid #edf1f6;
|
||||
}
|
||||
|
||||
.culture-activity-card__address {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
color: #69788d;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.culture-activity-card__address .van-icon {
|
||||
margin: 2px 5px 0 0;
|
||||
flex: none;
|
||||
color: #6c9ff8;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.culture-activity-card__address span {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 1.1em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.list-card-body .time {
|
||||
color: #9a9696;
|
||||
line-height: 20px;
|
||||
.culture-activity-card__tags {
|
||||
display: flex;
|
||||
margin-top: 8px;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.list-card-body .footer {
|
||||
text-align: right;
|
||||
.culture-activity-card__tag {
|
||||
display: inline-flex;
|
||||
padding: 3px 8px;
|
||||
align-items: center;
|
||||
border-radius: 4px;
|
||||
color: #397de0;
|
||||
background-color: #edf5ff;
|
||||
font-size: 11px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.list-card-body .footer .tag {
|
||||
border: 1px solid transparent;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
.culture-activity-card__tag-label {
|
||||
margin-right: 4px;
|
||||
color: #8aa7cf;
|
||||
}
|
||||
.list-card-img img{
|
||||
width: 100%;
|
||||
|
||||
.culture-activity-card__arrow {
|
||||
position: absolute;
|
||||
top: 164px;
|
||||
right: 14px;
|
||||
color: #b4bdca;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.culture-activity-empty {
|
||||
display: flex;
|
||||
min-height: 260px;
|
||||
padding: 26px 18px 32px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.culture-activity-empty img {
|
||||
display: block;
|
||||
width: 82%;
|
||||
max-width: 280px;
|
||||
height: auto;
|
||||
border-radius: 12px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.culture-activity-empty__title {
|
||||
margin-top: 14px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.culture-activity-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.culture-activity-page .van-list__finished-text,
|
||||
.culture-activity-page .van-list__loading {
|
||||
color: #9aa7b8;
|
||||
font-size: 13px;
|
||||
line-height: 44px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar title="活动列表" @click-left="historyBack" left-arrow left-text="返回" placeholder fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<van-dropdown-menu>
|
||||
<year-van-dropdown-item :num="5" @change="doSearch" v-model="pageForm.year"></year-van-dropdown-item>
|
||||
<van-dropdown-item :options="stateList" @change="doSearch" v-model="pageForm.state"></van-dropdown-item>
|
||||
<van-dropdown-item :options="isEnrolledOptions" @change="doSearch" v-model="pageForm.isEnrolled"></van-dropdown-item>
|
||||
<van-dropdown-item :options="activityTypeOptions" @change="doSearch" v-model="pageForm.activity_type"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</van-sticky>
|
||||
<table-list api="/platform/activity/culture/applyUser/pageData"
|
||||
:page_form.sync="pageForm"
|
||||
ref="tableListRef"
|
||||
title="name"
|
||||
img="cover"
|
||||
@ready="onReady"
|
||||
>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="报名开始时间">
|
||||
{{$moment(row.startTime).format('MM/DD HH:mm')}}
|
||||
</table-column>
|
||||
<table-column label="报名结束时间">
|
||||
{{$moment(row.endTime).format('MM/DD HH:mm')}}
|
||||
</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<template v-if="$moment().isBefore($moment(row.endTime))">
|
||||
<div class="action-btn" @click="openDetail(row)">
|
||||
<i class="fa fa-edit"></i>
|
||||
<span>去报名</span>
|
||||
<div class="culture-activity-page">
|
||||
<van-nav-bar title="文化活动" @click-left="historyBack" left-arrow left-text="返回" placeholder fixed></van-nav-bar>
|
||||
|
||||
<div class="culture-activity-content">
|
||||
<section class="culture-activity-hero">
|
||||
<img class="culture-activity-hero__image" src="/assets/mobile/img/activity/hero/culture-hero-v3.png" alt="文化活动插画">
|
||||
<div class="culture-activity-hero__copy">
|
||||
<div class="culture-activity-hero__title">文化活动</div>
|
||||
<div class="culture-activity-hero__subtitle">丰富生活 · 乐享校园</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</table-list>
|
||||
</section>
|
||||
|
||||
<van-sticky :offset-top="46">
|
||||
<div class="culture-activity-sticky">
|
||||
<van-search
|
||||
v-model="searchKeyword"
|
||||
class="culture-activity-search"
|
||||
placeholder="搜索文化活动"
|
||||
shape="round"
|
||||
clearable
|
||||
@search="doSearch"
|
||||
@clear="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu class="culture-activity-filter" :class="{'is-open': filterOpened}" active-color="#1989fa">
|
||||
<year-van-dropdown-item :num="5" @change="doSearch" @open="$set($data, 'filterOpened', true)" @close="$set($data, 'filterOpened', false)" v-model="pageForm.year"></year-van-dropdown-item>
|
||||
<van-dropdown-item :options="stateList" @change="doSearch" @open="$set($data, 'filterOpened', true)" @close="$set($data, 'filterOpened', false)" v-model="pageForm.state"></van-dropdown-item>
|
||||
<van-dropdown-item :options="isEnrolledOptions" @change="doSearch" @open="$set($data, 'filterOpened', true)" @close="$set($data, 'filterOpened', false)" v-model="pageForm.isEnrolled"></van-dropdown-item>
|
||||
<van-dropdown-item :options="activityTypeOptions" @change="doSearch" @open="$set($data, 'filterOpened', true)" @close="$set($data, 'filterOpened', false)" v-model="pageForm.activity_type"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
|
||||
<van-list v-model="loading" :finished="finished" @load="onLoad">
|
||||
<div class="culture-activity-list">
|
||||
<div v-for="row in tableData" :key="row.id" class="culture-activity-card" @click="openDetail(row)">
|
||||
<img
|
||||
v-if="hasCover(row) && !imageLoadErrors[row.id]"
|
||||
class="culture-activity-card__cover"
|
||||
:src="row.cover"
|
||||
:alt="row.name"
|
||||
@error="handleImageError(row)"
|
||||
>
|
||||
<div v-else class="culture-activity-card__cover-state" :class="{'is-error': hasCover(row)}">
|
||||
<van-icon name="photo-o"></van-icon>
|
||||
<span>{{ hasCover(row) ? '图片加载失败' : '暂无图片' }}</span>
|
||||
</div>
|
||||
<div class="culture-activity-card__body">
|
||||
<div class="culture-activity-card__title">{{ row.name }}</div>
|
||||
<div class="culture-activity-card__time" v-if="row.applyStartTime && row.applyEndTime">
|
||||
报名时间:{{ $moment(row.applyStartTime).format('MM/DD HH:mm') }}~{{ $moment(row.applyEndTime).format('MM/DD HH:mm') }}
|
||||
</div>
|
||||
<div class="culture-activity-card__time" v-if="row.startTime && row.endTime">
|
||||
活动时间:{{ $moment(row.startTime).format('MM/DD HH:mm') }}~{{ $moment(row.endTime).format('MM/DD HH:mm') }}
|
||||
</div>
|
||||
<div class="culture-activity-card__meta" v-if="row.address || row.projectTypeName || formatSignUpMethod(row.signUpMethod)">
|
||||
<div class="culture-activity-card__address" v-if="row.address">
|
||||
<van-icon name="location-o"></van-icon>
|
||||
<span>{{ row.address }}</span>
|
||||
</div>
|
||||
<div class="culture-activity-card__tags" v-if="row.projectTypeName || formatSignUpMethod(row.signUpMethod)">
|
||||
<span class="culture-activity-card__tag" v-if="row.projectTypeName">
|
||||
<span class="culture-activity-card__tag-label">活动类型</span>{{ row.projectTypeName }}
|
||||
</span>
|
||||
<span class="culture-activity-card__tag" v-if="formatSignUpMethod(row.signUpMethod)">
|
||||
<span class="culture-activity-card__tag-label">报名方式</span>{{ formatSignUpMethod(row.signUpMethod) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<van-icon class="culture-activity-card__arrow" name="arrow"></van-icon>
|
||||
</div>
|
||||
</div>
|
||||
</van-list>
|
||||
<div v-if="!loading && tableData.length === 0" class="culture-activity-empty">
|
||||
<img src="/assets/mobile/img/activity/culture-empty.png" alt="文化活动空状态插画">
|
||||
<div class="culture-activity-empty__title">暂无文化活动</div>
|
||||
<div class="culture-activity-empty__hint">当前筛选条件下暂时没有可展示的活动</div>
|
||||
</div>
|
||||
</van-pull-refresh>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<van-popup :style="{ height: '100%',width: '100%'}" position="right" v-model="viewShow">
|
||||
<mobile-culture-apply-user :id="viewData.id" @back="back" @submit_back="submit_back" ref="viewInfo"></mobile-culture-apply-user>
|
||||
@@ -92,10 +461,14 @@ layout("/layouts/platform_h5.html"){
|
||||
finished: false,
|
||||
loading: false,
|
||||
refreshing: false,
|
||||
searchKeyword: "",
|
||||
imageLoadErrors: {},
|
||||
filterOpened: false,
|
||||
pageForm: {
|
||||
state: 2,
|
||||
isEnrolled: 0,
|
||||
year: new Date().getFullYear(),
|
||||
name: "",
|
||||
pageNumber: 1,
|
||||
pageSize: 5,
|
||||
totalCount: 0,
|
||||
@@ -128,6 +501,47 @@ layout("/layouts/platform_h5.html"){
|
||||
onReady() {
|
||||
this.doSearch()
|
||||
},
|
||||
hasCover(row) {
|
||||
return !!(row && row.cover && String(row.cover).trim())
|
||||
},
|
||||
handleImageError(row) {
|
||||
this.$set(this.imageLoadErrors, row.id, true)
|
||||
},
|
||||
formatSignUpMethod(value) {
|
||||
return {
|
||||
1: "个人报名",
|
||||
2: "组队报名",
|
||||
3: "分工会报名"
|
||||
}[Number(value)] || ""
|
||||
},
|
||||
onLoad() {
|
||||
if (!this.finished) this.loadActivities(false)
|
||||
},
|
||||
onRefresh() {
|
||||
this.loadActivities(true)
|
||||
},
|
||||
loadActivities(reset) {
|
||||
if (reset) {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.tableData = []
|
||||
this.finished = false
|
||||
this.imageLoadErrors = {}
|
||||
}
|
||||
this.loading = true
|
||||
this.$axios.post("/platform/activity/culture/applyUser/pageData", this.pageForm).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const list = res.data && res.data.list ? res.data.list : []
|
||||
this.tableData = this.pageForm.pageNumber === 1 ? list : this.tableData.concat(list)
|
||||
this.pageForm.totalCount = res.data && res.data.totalCount ? res.data.totalCount : 0
|
||||
this.finished = this.tableData.length >= this.pageForm.totalCount
|
||||
if (!this.finished) this.pageForm.pageNumber++
|
||||
}
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
this.refreshing = false
|
||||
})
|
||||
},
|
||||
|
||||
openDetail(row) {
|
||||
this.$axios.post('/platform/activity/basic/scope/getScopeUser',{activityGroupId:row.groupId}).then(res=>{
|
||||
@@ -161,66 +575,61 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$refs.viewInfo.getActivityInfo()
|
||||
}, 500)
|
||||
},
|
||||
async doAdd(row) {
|
||||
this.$dialog
|
||||
.confirm({
|
||||
title: "提示",
|
||||
message: "确认要报名吗?"
|
||||
})
|
||||
.then(() => {
|
||||
this.$axios.post("/platform/activity/culture/applyUser/singleSignUp", { activityId: row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.loading({
|
||||
duration: 0,
|
||||
forbidClick: true,
|
||||
message: "加载中...."
|
||||
})
|
||||
setTimeout(() => {
|
||||
this.$toast.clear()
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
this.subLoading = false
|
||||
}, 1000)
|
||||
} else {
|
||||
this.subLoading = false
|
||||
}
|
||||
})
|
||||
})
|
||||
.catch(() => {})
|
||||
doAdd(row) {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "确认要报名吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/platform/activity/culture/applyUser/singleSignUp", {
|
||||
activityId: row.id
|
||||
}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.loading({
|
||||
duration: 0,
|
||||
forbidClick: true,
|
||||
message: "加载中...."
|
||||
});
|
||||
setTimeout(() => {
|
||||
this.$toast.clear();
|
||||
this.$toast.success(res.msg);
|
||||
this.doSearch();
|
||||
this.subLoading = false;
|
||||
}, 1000);
|
||||
} else {
|
||||
this.subLoading = false;
|
||||
}
|
||||
});
|
||||
}).catch(() => {});
|
||||
},
|
||||
async doDelete(row) {
|
||||
this.$dialog
|
||||
.confirm({
|
||||
title: "提示",
|
||||
message: "确认要取消报名吗?"
|
||||
})
|
||||
.then(() => {
|
||||
this.$axios.post("/platform/activity/culture/applyUser/cancelSignUp", { activityId: row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.loading({
|
||||
duration: 0,
|
||||
forbidClick: true,
|
||||
message: "加载中...."
|
||||
})
|
||||
setTimeout(() => {
|
||||
this.$toast.clear()
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
this.subLoading = false
|
||||
}, 1000)
|
||||
} else {
|
||||
this.$toast.fail(res.msg)
|
||||
}
|
||||
})
|
||||
})
|
||||
.catch(() => {})
|
||||
doDelete(row) {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "确认要取消报名吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/platform/activity/culture/applyUser/cancelSignUp", {
|
||||
activityId: row.id
|
||||
}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.loading({
|
||||
duration: 0,
|
||||
forbidClick: true,
|
||||
message: "加载中...."
|
||||
});
|
||||
setTimeout(() => {
|
||||
this.$toast.clear();
|
||||
this.$toast.success(res.msg);
|
||||
this.doSearch();
|
||||
this.subLoading = false;
|
||||
}, 1000);
|
||||
} else {
|
||||
this.$toast.fail(res.msg);
|
||||
}
|
||||
});
|
||||
}).catch(() => {});
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
this.pageForm.name = this.searchKeyword.trim()
|
||||
this.loadActivities(true)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,112 +2,572 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
.info-title {
|
||||
font-weight: bold;
|
||||
background-color: white;
|
||||
padding: 13px;
|
||||
box-shadow: 0 8px 12px #ebedf0;
|
||||
text-align: center !important;
|
||||
<style>
|
||||
body {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
.info-container {
|
||||
margin-bottom: 60px;
|
||||
|
||||
.family-activity-page {
|
||||
min-height: 100vh;
|
||||
padding-bottom: calc(24px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
.button {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
|
||||
.family-activity-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
.info-img {
|
||||
display: block;
|
||||
|
||||
.family-activity-page .van-nav-bar__title {
|
||||
color: #1f2937;
|
||||
font-size: 16px;
|
||||
}
|
||||
.van-count-down {
|
||||
|
||||
.family-activity-page .van-nav-bar .van-icon,
|
||||
.family-activity-page .van-nav-bar__text {
|
||||
color: #397fbd;
|
||||
}
|
||||
|
||||
.family-activity-content {
|
||||
padding: 12px 12px 0;
|
||||
}
|
||||
|
||||
.family-activity-hero {
|
||||
position: relative;
|
||||
height: 134px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
color: #fff;
|
||||
background-color: #247fe8;
|
||||
box-shadow: 0 8px 20px rgba(51, 117, 219, .18);
|
||||
}
|
||||
.item-header .van-tag {
|
||||
|
||||
.family-activity-hero__image {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: left center;
|
||||
}
|
||||
|
||||
.family-activity-hero__copy {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
width: 64%;
|
||||
height: 100%;
|
||||
padding-left: 16px;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
background: linear-gradient(90deg, rgba(22, 112, 232, .98) 0%, rgba(22, 112, 232, .88) 52%, rgba(22, 112, 232, 0) 100%);
|
||||
}
|
||||
|
||||
.family-activity-hero__title {
|
||||
font-size: 25px;
|
||||
line-height: 34px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 1px;
|
||||
text-shadow: 0 2px 6px rgba(17, 86, 182, .18);
|
||||
}
|
||||
|
||||
.family-activity-hero__subtitle {
|
||||
margin-top: 4px;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
letter-spacing: .5px;
|
||||
opacity: .95;
|
||||
}
|
||||
|
||||
.family-activity-sticky {
|
||||
padding: 10px 0 1px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.van-sticky--fixed .family-activity-sticky {
|
||||
padding-right: 12px;
|
||||
padding-left: 12px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.family-activity-search {
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.family-activity-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.family-activity-filter {
|
||||
margin-bottom: 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
transition: border-radius .18s ease;
|
||||
}
|
||||
|
||||
.family-activity-filter.is-open {
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
.family-activity-filter .van-dropdown-menu__bar {
|
||||
height: 44px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.family-activity-filter .van-dropdown-menu__title {
|
||||
color: #66758a;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.family-activity-filter .van-dropdown-menu__title--active,
|
||||
.family-activity-filter .van-dropdown-item__option--active,
|
||||
.family-activity-filter .van-dropdown-item__option--active .van-dropdown-item__icon {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.family-activity-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
margin: 0 12px;
|
||||
overflow: hidden;
|
||||
border-radius: 0 0 12px 12px;
|
||||
box-shadow: 0 10px 24px rgba(31, 65, 108, .14);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.family-activity-list .table-list-container {
|
||||
display: flex;
|
||||
margin-top: 0 !important;
|
||||
padding: 0 !important;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.family-activity-list .table-list-item {
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
overflow: hidden;
|
||||
border: 0 !important;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.family-activity-list .table-list-item .item-header {
|
||||
display: block !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.family-activity-list .table-list-item .item-actions:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.family-activity-card__cover,
|
||||
.family-activity-card__cover-state {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
background-color: #edf4fc;
|
||||
}
|
||||
|
||||
.family-activity-card__cover {
|
||||
display: block;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.family-activity-card__cover-state {
|
||||
flex-direction: column;
|
||||
row-gap: 8px;
|
||||
color: #8da1ba;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.family-activity-card__cover-state .van-icon {
|
||||
font-size: 34px;
|
||||
}
|
||||
|
||||
.family-activity-card__cover-state.is-error {
|
||||
color: #c27b75;
|
||||
background-color: #fff3f1;
|
||||
}
|
||||
|
||||
.family-activity-card__body {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
padding: 12px 38px 14px 14px;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.family-activity-card__title {
|
||||
overflow: hidden;
|
||||
color: #303846;
|
||||
font-size: 14px;
|
||||
line-height: 21px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.family-activity-card__time {
|
||||
margin-top: 4px;
|
||||
overflow: hidden;
|
||||
color: #98a2b2;
|
||||
font-size: 12px;
|
||||
padding: 3px 6px;
|
||||
border-radius: 6px;
|
||||
line-height: 17px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.family-activity-card__meta {
|
||||
display: flex;
|
||||
margin-top: 10px;
|
||||
padding-top: 9px;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
border-top: 1px solid #edf1f6;
|
||||
}
|
||||
|
||||
.family-activity-card__tag {
|
||||
display: inline-flex;
|
||||
padding: 3px 8px;
|
||||
align-items: center;
|
||||
border-radius: 4px;
|
||||
color: #397de0;
|
||||
background-color: #edf5ff;
|
||||
font-size: 11px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.family-activity-card__tag-label {
|
||||
margin-right: 4px;
|
||||
color: #8aa7cf;
|
||||
}
|
||||
|
||||
.family-activity-card__arrow {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 14px;
|
||||
color: #b4bdca;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.family-activity-empty {
|
||||
display: flex;
|
||||
min-height: 260px;
|
||||
padding: 26px 18px 32px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.family-activity-empty img {
|
||||
width: 82%;
|
||||
max-width: 280px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.family-activity-empty__title {
|
||||
margin-top: 14px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.family-activity-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.family-intro-popup,
|
||||
.family-intro-page {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.family-intro-page {
|
||||
position: relative;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.family-intro-scroll {
|
||||
height: calc(100vh - 46px);
|
||||
padding: 12px 12px calc(92px + env(safe-area-inset-bottom));
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.family-intro-hero {
|
||||
display: flex;
|
||||
min-height: 82px;
|
||||
padding: 16px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
color: #fff;
|
||||
background: linear-gradient(120deg, #2d7eea 0%, #5ba6f7 100%);
|
||||
box-shadow: 0 8px 20px rgba(45, 126, 234, .18);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.family-intro-hero__icon {
|
||||
display: flex;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
margin-right: 12px;
|
||||
flex: 0 0 44px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 11px;
|
||||
color: #2d7eea;
|
||||
background-color: rgba(255, 255, 255, .92);
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.family-intro-hero__title {
|
||||
font-size: 17px;
|
||||
line-height: 24px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.family-intro-hero__subtitle {
|
||||
margin-top: 3px;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
.family-intro-card {
|
||||
margin-top: 12px;
|
||||
padding: 16px;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.family-intro-card .content {
|
||||
padding: 0 !important;
|
||||
color: #3f4c5e !important;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.family-intro-card .content div,
|
||||
.family-intro-card .content p,
|
||||
.family-intro-card .content span,
|
||||
.family-intro-card .content li {
|
||||
color: #3f4c5e !important;
|
||||
font-size: 14px !important;
|
||||
line-height: 1.8 !important;
|
||||
white-space: normal !important;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.family-intro-card .content h1,
|
||||
.family-intro-card .content h2,
|
||||
.family-intro-card .content h3,
|
||||
.family-intro-card .content h4 {
|
||||
margin: 16px 0 9px !important;
|
||||
color: #1f2f43 !important;
|
||||
font-size: 18px !important;
|
||||
line-height: 1.5 !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
.family-intro-card .content > :first-child {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
.family-intro-card .content p {
|
||||
margin: 0 0 8px !important;
|
||||
}
|
||||
|
||||
.family-intro-card .content ul,
|
||||
.family-intro-card .content ol {
|
||||
margin: 8px 0 !important;
|
||||
padding-left: 22px !important;
|
||||
}
|
||||
|
||||
.family-intro-card .content img {
|
||||
max-width: 100% !important;
|
||||
height: auto !important;
|
||||
margin: 8px auto !important;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.family-intro-card .content table {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
overflow-x: auto;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.family-intro-empty {
|
||||
display: flex;
|
||||
min-height: 180px;
|
||||
margin-top: 12px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
row-gap: 10px;
|
||||
border-radius: 12px;
|
||||
color: #9aa7b8;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.family-intro-empty .van-icon {
|
||||
color: #83b5f4;
|
||||
font-size: 36px;
|
||||
}
|
||||
|
||||
.family-intro-footer {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 5;
|
||||
padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
|
||||
border-top: 1px solid #edf1f6;
|
||||
background-color: rgba(255, 255, 255, .96);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.family-intro-footer .van-button {
|
||||
height: 42px;
|
||||
border: 0;
|
||||
border-radius: 21px;
|
||||
font-size: 15px;
|
||||
background-color: #1989fa;
|
||||
box-shadow: 0 6px 16px rgba(25, 137, 250, .22);
|
||||
}
|
||||
|
||||
.family-intro-footer .van-button--disabled {
|
||||
color: #8b98aa !important;
|
||||
background-color: #eef2f7 !important;
|
||||
opacity: 1;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.family-intro-footer .van-count-down {
|
||||
display: inline-block;
|
||||
margin-left: 4px;
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app">
|
||||
<van-nav-bar title="亲子活动" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
<div id="app" v-cloak>
|
||||
<div class="family-activity-page">
|
||||
<van-nav-bar title="亲子活动" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
|
||||
<van-sticky offset-top="46px">
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<year-van-dropdown-item :num="5" @change="doSearch" v-model="pageForm.year"></year-van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.activityType" :options="typeOptions" :multiple="false"
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</van-sticky>
|
||||
|
||||
<table-list api="/platform/family/apply/activityPageData"
|
||||
:page_form.sync="pageForm"
|
||||
ref="tableListRef"
|
||||
img="cover"
|
||||
@ready="onReady"
|
||||
>
|
||||
<template #header="{index,row}">
|
||||
<div class="item-header">
|
||||
<div class="item-title">{{ row.activityName }}</div>
|
||||
<div>
|
||||
<van-tag type="primary" v-if="$moment().isBefore($moment(row.activitySignUpStartTime))">
|
||||
即将开始
|
||||
</van-tag>
|
||||
<van-tag type="success" v-if="$moment().isAfter($moment(row.activitySignUpStartTime)) && $moment().isBefore($moment(row.activitySignUpEndTime))">
|
||||
进行中
|
||||
</van-tag>
|
||||
<van-tag class="grey" v-if="$moment().isAfter($moment(row.activitySignUpEndTime))">
|
||||
已结束
|
||||
</van-tag>
|
||||
<div class="family-activity-content">
|
||||
<section class="family-activity-hero">
|
||||
<img class="family-activity-hero__image" src="/assets/mobile/img/activity/hero/family-hero-v3.png" alt="亲子活动插画">
|
||||
<div class="family-activity-hero__copy">
|
||||
<div class="family-activity-hero__title">亲子活动</div>
|
||||
<div class="family-activity-hero__subtitle">温馨陪伴 · 快乐成长</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<van-sticky :offset-top="46">
|
||||
<div class="family-activity-sticky">
|
||||
<van-search v-model="pageForm.searchKeyword" class="family-activity-search" placeholder="搜索亲子活动"
|
||||
shape="round" clearable @search="doSearch" @clear="doSearch"></van-search>
|
||||
<van-dropdown-menu class="family-activity-filter" :class="{'is-open': filterOpened}" active-color="#1989fa">
|
||||
<year-van-dropdown-item :num="5" @change="doSearch" @open="$set($data, 'filterOpened', true)" @close="$set($data, 'filterOpened', false)" v-model="pageForm.year"></year-van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.activityType" :options="typeOptions" :multiple="false"
|
||||
@change="doSearch" @open="$set($data, 'filterOpened', true)" @close="$set($data, 'filterOpened', false)"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<table-list class="family-activity-list" api="/platform/family/apply/activityPageData"
|
||||
:page_form.sync="pageForm" ref="tableListRef" @ready="onReady">
|
||||
<template #empty>
|
||||
<div class="family-activity-empty">
|
||||
<img src="/assets/mobile/img/activity/family-empty.png" alt="亲子活动空状态插画">
|
||||
<div class="family-activity-empty__title">暂无亲子活动</div>
|
||||
<div class="family-activity-empty__hint">当前筛选条件下暂时没有可展示的活动</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #header="{index,row}">
|
||||
<img v-if="hasCover(row) && !imageLoadErrors[row.id]" class="family-activity-card__cover"
|
||||
:src="row.cover" :alt="row.activityName" @error="handleImageError(row)" @click="onView(row)">
|
||||
<div v-else class="family-activity-card__cover-state" :class="{'is-error': hasCover(row)}" @click="onView(row)">
|
||||
<van-icon name="photo-o"></van-icon>
|
||||
<span>{{ hasCover(row) ? '图片加载失败' : '暂无图片' }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="面向对象">{{row.activityGroupName}}</table-column>
|
||||
<table-column label="报名时间">
|
||||
{{$moment(row.activitySignUpStartTime).format('MM/DD HH:mm') + '~' + $moment(row.activitySignUpEndTime).format('MM/DD HH:mm')}}
|
||||
</table-column>
|
||||
<table-column label="活动时间">
|
||||
{{$moment(row.activityStartTime).format('MM/DD HH:mm') + '~' + $moment(row.activityEndTime).format('MM/DD HH:mm')}}
|
||||
</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<template v-if="$moment().isBefore($moment(row.activitySignUpEndTime))">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span>查看介绍</span>
|
||||
<div class="family-activity-card__body" @click="onView(row)">
|
||||
<div class="family-activity-card__title">{{ row.activityName }}</div>
|
||||
<div class="family-activity-card__time" v-if="row.activitySignUpStartTime && row.activitySignUpEndTime">
|
||||
报名时间:{{ $moment(row.activitySignUpStartTime).format('MM/DD HH:mm') }}~{{ $moment(row.activitySignUpEndTime).format('MM/DD HH:mm') }}
|
||||
</div>
|
||||
<div class="action-btn" @click="onApply(row)">
|
||||
<i class="fa fa-edit"></i>
|
||||
<span>去报名</span>
|
||||
<div class="family-activity-card__time" v-if="row.activityStartTime && row.activityEndTime">
|
||||
活动时间:{{ $moment(row.activityStartTime).format('MM/DD HH:mm') }}~{{ $moment(row.activityEndTime).format('MM/DD HH:mm') }}
|
||||
</div>
|
||||
</template>
|
||||
<div class="family-activity-card__meta" v-if="row.activityGroupName || row.trainType">
|
||||
<span class="family-activity-card__tag" v-if="row.activityGroupName"><span class="family-activity-card__tag-label">面向对象</span>{{row.activityGroupName}}</span>
|
||||
<span class="family-activity-card__tag" v-if="row.trainType"><span class="family-activity-card__tag-label">活动类型</span>{{row.trainType}}</span>
|
||||
</div>
|
||||
<van-icon class="family-activity-card__arrow" name="arrow"></van-icon>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<van-action-sheet :close-on-click-overlay="false" title="详细信息" v-model="infoVisible">
|
||||
|
||||
<div class="info-container">
|
||||
<div>
|
||||
<van-image class="info-img" height="186" width="100%" :src="infoRow.cover"></van-image>
|
||||
<div class="info-title">{{infoRow.activityName}}</div>
|
||||
<pdf-preview :content="infoRow.introduce"></pdf-preview>
|
||||
<van-popup class="family-intro-popup" :style="{height: '100%', width: '100%'}" position="right" safe-area-inset-bottom v-model="infoVisible">
|
||||
<div class="family-intro-page">
|
||||
<van-nav-bar title="活动介绍" left-text="返回" left-arrow @click-left="historyBack"></van-nav-bar>
|
||||
<div class="family-intro-scroll">
|
||||
<div class="family-intro-hero">
|
||||
<div class="family-intro-hero__icon"><van-icon name="description"></van-icon></div>
|
||||
<div>
|
||||
<div class="family-intro-hero__title">亲子活动报名须知</div>
|
||||
<div class="family-intro-hero__subtitle">请仔细阅读活动安排与报名要求</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="family-intro-card" v-if="infoRow.introduce">
|
||||
<pdf-preview :content="infoRow.introduce"></pdf-preview>
|
||||
</div>
|
||||
<div v-else class="family-intro-empty">
|
||||
<van-icon name="description"></van-icon>
|
||||
<span>暂无活动介绍</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="button">
|
||||
<van-button @click="onApply(infoRow)" type="primary" block>
|
||||
<span v-if="time >= 0">
|
||||
去报名
|
||||
</span>
|
||||
<template v-else>
|
||||
距离开始
|
||||
<van-count-down :time="Math.abs(time)" class="count-down" format="DD 天 HH 时 mm 分 ss 秒" @finish="time = 0"></van-count-down>
|
||||
</template>
|
||||
<div class="family-intro-footer">
|
||||
<van-button v-if="canApply(infoRow)" @click="onApply(infoRow)" type="primary" block round>进入报名</van-button>
|
||||
<van-button v-else-if="time < 0" @click="onApply(infoRow)" type="primary" block round>
|
||||
距离开始
|
||||
<van-count-down :time="Math.abs(time)" format="DD 天 HH 时 mm 分 ss 秒" @finish="$set($data, 'time', 0)"></van-count-down>
|
||||
</van-button>
|
||||
<van-button v-else disabled block round>{{ registrationStatusText(infoRow) }}</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</van-action-sheet>
|
||||
</van-popup>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -136,17 +596,48 @@ layout("/layouts/platform_h5.html"){
|
||||
],
|
||||
infoVisible: false,
|
||||
infoRow: {},
|
||||
imageLoadErrors: {},
|
||||
filterOpened: false,
|
||||
|
||||
id: GetQueryString('id')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
hasCover(row) {
|
||||
return !!(row && row.cover && String(row.cover).trim())
|
||||
},
|
||||
handleImageError(row) {
|
||||
this.$set(this.imageLoadErrors, row.id, true)
|
||||
},
|
||||
isRegistrationClosed(row) {
|
||||
return !!(row && row.activitySignUpEndTime && !this.$moment().isBefore(this.$moment(row.activitySignUpEndTime)))
|
||||
},
|
||||
canApply(row) {
|
||||
if(!row || !row.activitySignUpStartTime || !row.activitySignUpEndTime) {
|
||||
return false
|
||||
}
|
||||
const now = Date.now()
|
||||
return now >= this.$moment(row.activitySignUpStartTime).valueOf()
|
||||
&& now <= this.$moment(row.activitySignUpEndTime).valueOf()
|
||||
},
|
||||
registrationStatusText(row) {
|
||||
if(!row || !row.activitySignUpStartTime || !row.activitySignUpEndTime) {
|
||||
return '当前不可报名'
|
||||
}
|
||||
if(Date.now() < this.$moment(row.activitySignUpStartTime).valueOf()) {
|
||||
return '报名未开始'
|
||||
}
|
||||
return '已过报名时间'
|
||||
},
|
||||
onView(row) {
|
||||
this.infoRow = row
|
||||
this.time = this.$moment().diff(this.$moment(row.activitySignUpStartTime), 'milliseconds')
|
||||
this.infoVisible = true
|
||||
},
|
||||
onApply(row) {
|
||||
if(this.isRegistrationClosed(row)) {
|
||||
return
|
||||
}
|
||||
if(this.$moment().isBefore(this.$moment(row.activitySignUpStartTime))) {
|
||||
this.onView(row)
|
||||
return
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
const times = {
|
||||
template:
|
||||
/*language=HTML*/
|
||||
`
|
||||
template: /*language=HTML*/ `
|
||||
<div>
|
||||
<van-action-sheet v-model="visible" title="时间段" cancel-text="取消">
|
||||
<button v-for="(item,index) in row?.courseTimes" type="button" class="van-action-sheet__item">
|
||||
<van-action-sheet class="family-course-times-sheet" :style="{height: '78%'}" :close-on-click-overlay="true" v-model="visible" title="时间段" cancel-text="取消">
|
||||
<div class="family-course-times-list">
|
||||
<button v-for="(item,index) in row?.courseTimes" :key="index" type="button" class="van-action-sheet__item family-course-time-item">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center">
|
||||
<div>
|
||||
<div class="van-action-sheet__name">
|
||||
@@ -21,12 +20,13 @@ const times = {
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</van-action-sheet>
|
||||
|
||||
<van-popup round :safe-area-inset-bottom="true"
|
||||
:close-on-click-overlay="false"
|
||||
v-model="signVisible"
|
||||
:style="{ width: '80%', height: '66%' }"
|
||||
<van-popup round :safe-area-inset-bottom="true"
|
||||
:close-on-click-overlay="false"
|
||||
v-model="signVisible"
|
||||
:style="{ width: '80%', height: '66%' }"
|
||||
get-container="#app"
|
||||
@close="onSignClose"
|
||||
closeable
|
||||
@@ -84,6 +84,84 @@ const times = {
|
||||
},
|
||||
},
|
||||
style: /*language=CSS*/ `
|
||||
|
||||
.family-course-times-sheet {
|
||||
overflow: hidden;
|
||||
border-radius: 16px 16px 0 0;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.family-course-times-sheet /deep/ .van-action-sheet__header {
|
||||
height: 48px;
|
||||
color: #1f2f43;
|
||||
background-color: #fff;
|
||||
font-size: 16px;
|
||||
line-height: 48px;
|
||||
}
|
||||
|
||||
.family-course-times-sheet /deep/ .van-action-sheet__close {
|
||||
top: 13px;
|
||||
color: #b5bdc9;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.family-course-times-list {
|
||||
height: calc(100% - 98px);
|
||||
padding: 10px 12px 0;
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.family-course-times-sheet /deep/ .family-course-time-item {
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
padding: 14px;
|
||||
border-radius: 10px;
|
||||
color: #263548;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 6px 18px rgba(55, 85, 126, .07);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.family-course-times-sheet /deep/ .van-action-sheet__name {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
line-height: 21px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.family-course-times-sheet /deep/ .van-action-sheet__subname {
|
||||
margin-top: 5px;
|
||||
color: #98a2b2;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.family-course-times-sheet /deep/ .sign_button .van-button {
|
||||
min-width: 48px;
|
||||
height: 28px;
|
||||
padding: 0 12px;
|
||||
border: 0;
|
||||
border-radius: 14px;
|
||||
color: #fff;
|
||||
background-color: #1989fa;
|
||||
font-size: 12px;
|
||||
line-height: 28px;
|
||||
box-shadow: 0 4px 10px rgba(25, 137, 250, .18);
|
||||
}
|
||||
|
||||
.family-course-times-sheet /deep/ .sign_button .van-button--disabled {
|
||||
color: #8b98aa;
|
||||
background-color: #eef2f7;
|
||||
opacity: 1;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.family-course-times-sheet /deep/ .van-action-sheet__cancel {
|
||||
height: 50px;
|
||||
color: #66758a;
|
||||
background-color: #fff;
|
||||
font-size: 14px;
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
const applyForm = {
|
||||
template:
|
||||
/*language=HTML*/
|
||||
`
|
||||
template: /*language=HTML*/ `
|
||||
<div>
|
||||
<van-action-sheet :close-on-click-overlay="false" title="报名信息" v-model="visible">
|
||||
<van-action-sheet class="family-course-form-sheet" :style="{height: '78%'}" :close-on-click-overlay="true" title="报名信息" v-model="visible">
|
||||
<van-form ref="formRef" class="form-container">
|
||||
<van-cell-group title="活动信息" class="form-section">
|
||||
<van-field label="活动名称" readonly v-model="row.courseName"></van-field>
|
||||
@@ -21,7 +19,7 @@ const applyForm = {
|
||||
required
|
||||
:rules="[{ required: true, message: '请选择报名时段' }]"
|
||||
readonly
|
||||
@click="showCoursePicker = true"
|
||||
@click="$set($data, 'showCoursePicker', true)"
|
||||
placeholder="请选择报名时段"
|
||||
name="courseTimeName"
|
||||
v-model="formData.courseTimeName">
|
||||
@@ -31,7 +29,7 @@ const applyForm = {
|
||||
show-toolbar
|
||||
:columns="courseTimeSelectList"
|
||||
@confirm="onCourseConfirm"
|
||||
@cancel="showCoursePicker=false"
|
||||
@cancel="$set($data, 'showCoursePicker', false)"
|
||||
></van-picker>
|
||||
</van-popup>
|
||||
</template>
|
||||
@@ -39,16 +37,20 @@ const applyForm = {
|
||||
|
||||
<van-cell-group class="form-section">
|
||||
<template #title>
|
||||
<div style="display: flex; align-items: center; justify-content: space-between">
|
||||
<div class="family-member-section-title">
|
||||
<div>{{activity.keyWord}}信息</div>
|
||||
<div>
|
||||
<van-tag @click="delFamily" size="large" type="primary" color="#ff3b30">删除{{activity.keyWord}}</van-tag>
|
||||
<van-tag @click="addFamily" size="large" type="primary" color="#1867b0">添加{{activity.keyWord}}</van-tag>
|
||||
<div class="family-member-actions">
|
||||
<button type="button" class="family-member-action family-member-action--delete" :aria-label="'删除' + activity.keyWord" @click="delFamily">
|
||||
<van-icon name="delete-o"></van-icon>
|
||||
</button>
|
||||
<button type="button" class="family-member-action family-member-action--add" :aria-label="'添加' + activity.keyWord" @click="addFamily">
|
||||
<van-icon name="plus"></van-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div v-if="formData.mobileColumnsValue && formData.mobileColumnsValue.length > 0" class="mt10">
|
||||
<van-tabs v-model="familyActive" type="card" color="#0e78c5" animated>
|
||||
<van-tabs v-model="familyActive" color="#1989fa" title-active-color="#1989fa" animated>
|
||||
<van-tab v-for="item, index in formData.mobileColumnsValue"
|
||||
:name="index + ''"
|
||||
:title="activity.keyWord + (index + 1)"
|
||||
@@ -65,7 +67,7 @@ const applyForm = {
|
||||
</van-cell-group>
|
||||
|
||||
<div class="button">
|
||||
<van-button @click="onSubmit" round type="info" block>提交</van-button>
|
||||
<van-button :loading="formLoading" :disabled="formLoading" @click="onSubmit" round type="info" block>提交</van-button>
|
||||
</div>
|
||||
</van-form>
|
||||
</van-action-sheet>
|
||||
@@ -77,6 +79,7 @@ const applyForm = {
|
||||
row: {},
|
||||
activity: {},
|
||||
visible: false,
|
||||
formLoading: false,
|
||||
formData: {},
|
||||
showCoursePicker: false,
|
||||
courseTimeSelectList: [],
|
||||
@@ -100,16 +103,18 @@ const applyForm = {
|
||||
const ac = (Number(this.familyActive) - 1)
|
||||
this.familyActive = '' + (ac >= 0 ? ac : 0)
|
||||
},
|
||||
async onOpen(row, courseType, activity) {
|
||||
this.row = row
|
||||
this.courseType = courseType
|
||||
this.activity = activity
|
||||
|
||||
this.init(row, courseType)
|
||||
if(row.courseIsLimitApply) {
|
||||
await this.getCourseTimeSelectList(row)
|
||||
}
|
||||
this.visible = true
|
||||
onOpen(row, courseType, activity) {
|
||||
this.row = row;
|
||||
this.courseType = courseType;
|
||||
this.activity = activity;
|
||||
this.init(row, courseType);
|
||||
if (row.courseIsLimitApply) {
|
||||
return this.getCourseTimeSelectList(row).then(() => {
|
||||
this.visible = true;
|
||||
});
|
||||
} else {
|
||||
this.visible = true;
|
||||
}
|
||||
},
|
||||
init(row, courseType) {
|
||||
this.$set(this.formData, 'username', this.$store.state.user.username)
|
||||
@@ -127,13 +132,16 @@ const applyForm = {
|
||||
this.$set(this.formData, "courseTimeName", val.text.substring(0, 12))
|
||||
this.showCoursePicker = false
|
||||
},
|
||||
async getCourseTimeSelectList(o) {
|
||||
const resp = await this.$axios.post('/platform/family/apply/getCourseTimeSelectList',{courseId: o.id})
|
||||
getCourseTimeSelectList(o) {
|
||||
return this.$axios.post('/platform/family/apply/getCourseTimeSelectList', {
|
||||
courseId: o.id
|
||||
}).then(resp => {
|
||||
if (resp.code === 0) {
|
||||
this.courseTimeSelectList = resp.data
|
||||
this.courseTimeSelectList = resp.data;
|
||||
} else {
|
||||
this.$toast.fail("获取时段信息失败,请联系管理员")
|
||||
this.$toast.fail("获取时段信息失败,请联系管理员");
|
||||
}
|
||||
});
|
||||
},
|
||||
validateIdCard(idCard) {
|
||||
if (!idCard) {
|
||||
@@ -266,78 +274,181 @@ const applyForm = {
|
||||
|
||||
return { age, sex, };
|
||||
},
|
||||
async validateSignUp() {
|
||||
// 获取家属人数
|
||||
const res = await this.$axios.post("/platform/family/apply/validateSignUp", {
|
||||
courseId: this.formData.courseId,
|
||||
currentFamilyNumber: this.formData.mobileColumnsValue.length || 0
|
||||
})
|
||||
if(res.code !== 0) {
|
||||
this.$dialog.alert({title: '温馨提示', message: res.msg})
|
||||
validateSignUp() {
|
||||
return this.$axios.post("/platform/family/apply/validateSignUp", {
|
||||
courseId: this.formData.courseId,
|
||||
currentFamilyNumber: this.formData.mobileColumnsValue.length || 0
|
||||
}).then(res => {
|
||||
if (res.code !== 0) {
|
||||
this.$dialog.alert({
|
||||
title: '温馨提示',
|
||||
message: res.msg
|
||||
});
|
||||
}
|
||||
return res.code === 0
|
||||
return res.code === 0;
|
||||
});
|
||||
},
|
||||
async validateCourseTime() {
|
||||
const res = await this.$axios.post('/platform/family/apply/validateSourceSignUp', {
|
||||
activityCourseId: this.formData.activityCourseId,
|
||||
courseId: this.row.id
|
||||
})
|
||||
if(res.code !== 0) {
|
||||
this.$dialog.alert({title: '温馨提示', message: res.msg})
|
||||
validateCourseTime() {
|
||||
return this.$axios.post('/platform/family/apply/validateSourceSignUp', {
|
||||
activityCourseId: this.formData.activityCourseId,
|
||||
courseId: this.row.id
|
||||
}).then(res => {
|
||||
if (res.code !== 0) {
|
||||
this.$dialog.alert({
|
||||
title: '温馨提示',
|
||||
message: res.msg
|
||||
});
|
||||
}
|
||||
return res.code === 0
|
||||
return res.code === 0;
|
||||
});
|
||||
},
|
||||
async onSubmit() {
|
||||
onSubmit() {
|
||||
// 保留原有报名资格、动态表单和限额时段校验;确认后才发送报名数据。
|
||||
if (this.formLoading) return
|
||||
if (!this.validFamilyForm()) return
|
||||
if (!await this.validateSignUp()) return
|
||||
|
||||
this.$refs.formRef.validate().then(() => {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(async () => {
|
||||
if (this.row.courseIsLimitApply) {
|
||||
if(!await this.validateCourseTime()) return
|
||||
}
|
||||
|
||||
return this.validateSignUp().then((valid) => {
|
||||
if (!valid) return
|
||||
return this.$refs.formRef.validate().then(() => {
|
||||
return this.$dialog.confirm({title: "提示", message: "您确定要提交吗?"})
|
||||
}).then(() => {
|
||||
return this.row.courseIsLimitApply ? this.validateCourseTime() : true
|
||||
}).then((validTime) => {
|
||||
if (!validTime) return
|
||||
this.$set(this, "formLoading", true)
|
||||
const formData = clone(this.formData)
|
||||
let array = []
|
||||
formData.mobileColumnsValue.forEach(item => {
|
||||
const o = item.map((v) => {
|
||||
return {
|
||||
columnName: v.columnName,
|
||||
columnValue: v.columnValue,
|
||||
columnCode: v.columnCode,
|
||||
columnFormType: v.columnFormType
|
||||
formData.mobileColumnsValue = JSON.stringify(formData.mobileColumnsValue.map((items) => items.map((item) => ({
|
||||
columnName: item.columnName, columnValue: item.columnValue,
|
||||
columnCode: item.columnCode, columnFormType: item.columnFormType
|
||||
}))))
|
||||
return this.$axios.post("/platform/family/apply/doSignUp", formData).then((res) => {
|
||||
// 保留原有报名结果确认,阅读提示后再关闭报名表单。
|
||||
return this.$dialog.alert({title: "温馨提示", message: res.msg}).then(() => {
|
||||
if (res.code === 0) {
|
||||
this.$set(this, "visible", false)
|
||||
this.$emit("refresh")
|
||||
}
|
||||
})
|
||||
array.push(o)
|
||||
})
|
||||
formData.mobileColumnsValue = JSON.stringify(clone(array))
|
||||
this.$axios.post("/platform/family/apply/doSignUp", formData).then(res => {
|
||||
this.$dialog.alert({title: '温馨提示', message: res.msg})
|
||||
.then(() => {
|
||||
if (res.code === 0) {
|
||||
this.visible = false
|
||||
this.$emit('refresh')
|
||||
}
|
||||
})
|
||||
}).finally(() => {
|
||||
this.$set(this, "formLoading", false)
|
||||
})
|
||||
}).catch(() => {
|
||||
// 取消确认或校验未通过时保留表单,网络错误由公共请求拦截器提示。
|
||||
})
|
||||
})
|
||||
},
|
||||
},
|
||||
style: /*language=CSS*/ `
|
||||
.family-course-form-sheet {
|
||||
overflow: hidden;
|
||||
border-radius: 16px 16px 0 0;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.family-course-form-sheet /deep/ .van-action-sheet__header {
|
||||
height: 48px;
|
||||
color: #1f2f43;
|
||||
background-color: #fff;
|
||||
font-size: 16px;
|
||||
line-height: 48px;
|
||||
}
|
||||
|
||||
.family-course-form-sheet /deep/ .van-action-sheet__close {
|
||||
top: 13px;
|
||||
color: #b5bdc9;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.family-course-form-sheet /deep/ .form-container {
|
||||
height: calc(100% - 48px);
|
||||
padding: 10px 12px 72px;
|
||||
overflow-y: auto;
|
||||
background-color: #f3f7fd;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.family-course-form-sheet /deep/ .form-section {
|
||||
margin-bottom: 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 6px 18px rgba(55, 85, 126, .07);
|
||||
}
|
||||
|
||||
.family-course-form-sheet /deep/ .van-cell-group__title {
|
||||
padding: 12px 14px 8px;
|
||||
color: #263548;
|
||||
background-color: #fff;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.family-course-form-sheet /deep/ .van-cell-group__title::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.family-course-form-sheet /deep/ .van-cell {
|
||||
padding: 11px 14px;
|
||||
color: #263548;
|
||||
background-color: #fff;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.family-course-form-sheet /deep/ .van-field__label {
|
||||
color: #66758a;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.family-course-form-sheet /deep/ .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.family-course-form-sheet /deep/ .van-tabs__nav--card {
|
||||
overflow: hidden;
|
||||
border: 0;
|
||||
border-radius: 16px;
|
||||
background-color: #eef3f9;
|
||||
}
|
||||
|
||||
.family-course-form-sheet /deep/ .van-tabs__nav--card .van-tab {
|
||||
border-right: 0;
|
||||
color: #66758a;
|
||||
}
|
||||
|
||||
.family-course-form-sheet /deep/ .van-tabs__nav--card .van-tab--active {
|
||||
color: #1989fa;
|
||||
background-color: #e7f2ff;
|
||||
}
|
||||
|
||||
/deep/ .companionList_empty_text {
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
font-size: 14px;
|
||||
color: grey;
|
||||
}
|
||||
/deep/ .button {
|
||||
position: fixed;
|
||||
|
||||
.family-course-form-sheet /deep/ .button {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
z-index: 2;
|
||||
width: auto;
|
||||
padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
|
||||
border-top: 1px solid #edf1f6;
|
||||
background-color: rgba(255, 255, 255, .96);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.family-course-form-sheet /deep/ .button .van-button {
|
||||
height: 42px;
|
||||
border: 0;
|
||||
border-radius: 21px;
|
||||
color: #fff;
|
||||
background-color: #1989fa;
|
||||
font-size: 15px;
|
||||
box-shadow: 0 6px 16px rgba(25, 137, 250, .22);
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,248 +2,462 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
.info-title {
|
||||
font-weight: bold;
|
||||
background-color: white;
|
||||
padding: 13px;
|
||||
box-shadow: 0 8px 12px #ebedf0;
|
||||
text-align: center !important;
|
||||
}
|
||||
.info-container {
|
||||
|
||||
}
|
||||
.button {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.info-img {
|
||||
display: block;
|
||||
}
|
||||
.van-count-down {
|
||||
color: #fff;
|
||||
}
|
||||
.table-list-container {
|
||||
padding: 0;
|
||||
margin-top: 10px;
|
||||
<style>
|
||||
body {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item {
|
||||
.family-mine-page {
|
||||
min-height: 100vh;
|
||||
padding-bottom: calc(24px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.family-mine-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #eaecef;
|
||||
padding: 16px;
|
||||
position: relative;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item:last-child {
|
||||
border-bottom: none;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .item-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .item-title {
|
||||
.family-mine-page .van-nav-bar__title {
|
||||
color: #1f2937;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #1f2f3d;
|
||||
}
|
||||
|
||||
.family-mine-page .van-nav-bar .van-icon,
|
||||
.family-mine-page .van-nav-bar__text {
|
||||
color: #397fbd;
|
||||
}
|
||||
|
||||
.family-mine-content {
|
||||
padding: 12px 12px 0;
|
||||
}
|
||||
|
||||
.family-mine-hero {
|
||||
position: relative;
|
||||
height: 134px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
flex: 1;
|
||||
padding-right: 10px;
|
||||
border-radius: 10px;
|
||||
color: #fff;
|
||||
background: linear-gradient(115deg, #347eea 0%, #5b9cf4 58%, #cfe3ff 100%);
|
||||
box-shadow: 0 8px 20px rgba(51, 117, 219, .18);
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .img-container {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
flex-shrink: 0;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .img-container img {
|
||||
width: 100%;
|
||||
.family-mine-hero__image {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 67%;
|
||||
height: 100%;
|
||||
border-radius: 6px;
|
||||
object-fit: cover;
|
||||
object-position: right center;
|
||||
-webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 26%);
|
||||
mask-image: linear-gradient(90deg, transparent 0%, #000 26%);
|
||||
}
|
||||
|
||||
|
||||
.table-list-container .table-list-item .item-meta {
|
||||
.family-mine-hero__copy {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
color: #606266;
|
||||
font-size: 14px;
|
||||
margin-bottom: 5px;
|
||||
padding: 4px 0;
|
||||
height: 100%;
|
||||
padding-left: 16px;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .meta-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
.family-mine-hero__title {
|
||||
font-size: 25px;
|
||||
line-height: 34px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .meta-item i {
|
||||
font-size: 14px;
|
||||
color: #909399;
|
||||
width: 16px;
|
||||
text-align: center;
|
||||
.family-mine-hero__subtitle {
|
||||
margin-top: 4px;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
letter-spacing: .5px;
|
||||
opacity: .95;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .item-content {
|
||||
color: #606266;
|
||||
font-size: 14px;
|
||||
.family-mine-sticky {
|
||||
padding: 10px 0 1px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.van-sticky--fixed .family-mine-sticky {
|
||||
padding-right: 12px;
|
||||
padding-left: 12px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.family-mine-search {
|
||||
margin-bottom: 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
line-height: 1.5;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .item-footer {
|
||||
.family-mine-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.family-mine-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.family-mine-filter {
|
||||
margin-bottom: 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
transition: border-radius .18s ease;
|
||||
}
|
||||
|
||||
.family-mine-filter.is-open {
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
.family-mine-filter .van-dropdown-menu__bar {
|
||||
height: 44px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.family-mine-filter .van-dropdown-menu__title {
|
||||
width: auto;
|
||||
max-width: calc(100% - 24px);
|
||||
padding: 0 12px 0 0;
|
||||
color: #66758a;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.family-mine-filter .van-dropdown-menu__title::after {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.family-mine-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
margin: 0 12px;
|
||||
overflow: hidden;
|
||||
border-radius: 0 0 12px 12px;
|
||||
box-shadow: 0 10px 24px rgba(31, 65, 108, .14);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.family-mine-list {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 12px;
|
||||
padding-top: 8px;
|
||||
border-top: 1px dashed #eaecef;
|
||||
color: #909399;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.family-mine-card {
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.family-mine-card__cover,
|
||||
.family-mine-card__cover-state {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #edf4fc;
|
||||
}
|
||||
|
||||
.family-mine-card__cover {
|
||||
display: block;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.family-mine-card__cover-state {
|
||||
flex-direction: column;
|
||||
row-gap: 8px;
|
||||
color: #8da1ba;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .item-actions {
|
||||
display: flex;
|
||||
column-gap: 20px;
|
||||
justify-content: end;
|
||||
margin-top: 15px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid #eaecef;
|
||||
.family-mine-card__cover-state .van-icon {
|
||||
font-size: 34px;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .action-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: end;
|
||||
font-size: 14px;
|
||||
color: var(--color-primary);
|
||||
padding: 4px 0;
|
||||
.family-mine-card__cover-state.is-error {
|
||||
color: #c27b75;
|
||||
background-color: #fff3f1;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .action-btn i {
|
||||
margin-right: 6px;
|
||||
font-size: 16px;
|
||||
.family-mine-card__body {
|
||||
padding: 12px 14px 14px;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .action-btn.delete {
|
||||
color: #ff0000;
|
||||
}
|
||||
|
||||
.table-list-container .table-list-item .action-btn.review {
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.table-list-container .empty-state {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.table-list-container .empty-state i {
|
||||
font-size: 60px;
|
||||
margin-bottom: 16px;
|
||||
color: #dcdee0;
|
||||
}
|
||||
|
||||
.table-list-container .empty-state p {
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.table-column {
|
||||
display: flex;
|
||||
padding: 6px 0;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.label {
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
flex-shrink: 0;
|
||||
max-width: 120px;
|
||||
white-space: nowrap;
|
||||
.family-mine-card__title {
|
||||
overflow: hidden;
|
||||
color: #303846;
|
||||
font-size: 14px;
|
||||
line-height: 21px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #555;
|
||||
.family-mine-card__time {
|
||||
margin-top: 4px;
|
||||
overflow: hidden;
|
||||
color: #98a2b2;
|
||||
font-size: 12px;
|
||||
line-height: 17px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.family-mine-card__meta {
|
||||
display: flex;
|
||||
margin-top: 10px;
|
||||
padding-top: 9px;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
border-top: 1px solid #edf1f6;
|
||||
}
|
||||
|
||||
.family-mine-card__tag {
|
||||
display: inline-flex;
|
||||
padding: 3px 8px;
|
||||
border-radius: 4px;
|
||||
color: #397de0;
|
||||
background-color: #edf5ff;
|
||||
font-size: 11px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.family-mine-card__tag-label {
|
||||
margin-right: 4px;
|
||||
color: #8aa7cf;
|
||||
}
|
||||
|
||||
.family-mine-card__actions {
|
||||
display: flex;
|
||||
padding: 12px 14px;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
border-top: 1px solid #edf1f6;
|
||||
background-color: #f8fbff;
|
||||
}
|
||||
|
||||
.family-mine-card__action {
|
||||
display: inline-flex;
|
||||
min-width: 82px;
|
||||
height: 32px;
|
||||
padding: 0 14px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 0;
|
||||
border-radius: 16px;
|
||||
color: #397de0;
|
||||
background-color: #edf5ff;
|
||||
font-size: 13px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.family-mine-card__action .van-icon {
|
||||
margin-right: 6px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.family-mine-card__action.is-primary {
|
||||
color: #fff;
|
||||
background-color: #1989fa;
|
||||
box-shadow: 0 5px 12px rgba(25, 137, 250, .18);
|
||||
}
|
||||
|
||||
.family-mine-empty {
|
||||
display: flex;
|
||||
min-height: 260px;
|
||||
padding: 26px 18px 32px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.family-mine-empty img {
|
||||
width: 82%;
|
||||
max-width: 280px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.family-mine-empty__title {
|
||||
margin-top: 14px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.family-mine-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.family-mine-intro-page {
|
||||
min-height: 100vh;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.family-mine-intro-scroll {
|
||||
height: calc(100vh - 46px);
|
||||
padding: 12px;
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.family-mine-intro-hero {
|
||||
display: flex;
|
||||
min-height: 82px;
|
||||
padding: 16px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
color: #fff;
|
||||
background: linear-gradient(120deg, #2d7eea 0%, #5ba6f7 100%);
|
||||
box-shadow: 0 8px 20px rgba(45, 126, 234, .18);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.family-mine-intro-hero__icon {
|
||||
display: flex;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
margin-right: 12px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 0 0 44px;
|
||||
border-radius: 11px;
|
||||
color: #2d7eea;
|
||||
background-color: rgba(255, 255, 255, .92);
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.family-mine-intro-hero__title {
|
||||
font-size: 17px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.family-mine-intro-hero__subtitle {
|
||||
margin-top: 3px;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
.family-mine-intro-card {
|
||||
margin-top: 12px;
|
||||
padding: 18px 16px;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
color: #3f4c5e;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
font-size: 14px;
|
||||
flex-grow: 1; /* 动态占据剩余部分 */
|
||||
white-space: nowrap; /* 防止换行 */
|
||||
overflow: hidden; /* 隐藏溢出的部分 */
|
||||
text-overflow: ellipsis; /* 省略号 */
|
||||
line-height: 1.8;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.family-mine-intro-card img {
|
||||
max-width: 100% !important;
|
||||
height: auto !important;
|
||||
border-radius: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app">
|
||||
<van-nav-bar title="亲子活动-我的报名" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
<div id="app" v-cloak>
|
||||
<div class="family-mine-page">
|
||||
<van-nav-bar title="亲子活动-我的报名" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
|
||||
<van-sticky offset-top="46px">
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<year-van-dropdown-item :num="5" @change="doSearch" v-model="pageForm.year"></year-van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.activityType" :options="typeOptions" :multiple="false"
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</van-sticky>
|
||||
<div class="family-mine-content">
|
||||
<section class="family-mine-hero">
|
||||
<img class="family-mine-hero__image" src="/assets/mobile/img/activity/hero/family-hero-v3.png" alt="亲子活动插画">
|
||||
<div class="family-mine-hero__copy">
|
||||
<div class="family-mine-hero__title">我的报名</div>
|
||||
<div class="family-mine-hero__subtitle">亲子活动 · 报名记录</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<table-list api="/platform/family/apply/activityPageData"
|
||||
:page_form.sync="pageForm"
|
||||
ref="tableListRef"
|
||||
title="activityName"
|
||||
img="cover"
|
||||
@ready="onReady"
|
||||
>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="面向对象">{{row.activityGroupName}}</table-column>
|
||||
<table-column label="报名时间">
|
||||
{{$moment(row.activitySignUpStartTime).format('MM/DD HH:mm') + '~' + $moment(row.activitySignUpEndTime).format('MM/DD HH:mm')}}
|
||||
</table-column>
|
||||
<table-column label="活动时间">
|
||||
{{$moment(row.activityStartTime).format('MM/DD HH:mm') + '~' + $moment(row.activityEndTime).format('MM/DD HH:mm')}}
|
||||
</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span>活动介绍</span>
|
||||
</div>
|
||||
<div class="action-btn" @click="onInfo(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span>{{row.keyWord}}信息</span>
|
||||
</div>
|
||||
<div class="action-btn" @click="onApply(row)">
|
||||
<i class="fa fa-edit"></i>
|
||||
<span>操作</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
<van-sticky :offset-top="46">
|
||||
<div class="family-mine-sticky">
|
||||
<van-search v-model="pageForm.searchKeyword" class="family-mine-search" placeholder="搜索已报名活动" shape="round" clearable @search="doSearch" @clear="doSearch"></van-search>
|
||||
<van-dropdown-menu class="family-mine-filter" :class="{'is-open': filterOpened}" active-color="#1989fa">
|
||||
<year-van-dropdown-item :num="5" @change="doSearch" @open="$set($data, 'filterOpened', true)" @close="$set($data, 'filterOpened', false)" v-model="pageForm.year"></year-van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.activityType" :options="typeOptions" :multiple="false" @change="doSearch" @open="$set($data, 'filterOpened', true)" @close="$set($data, 'filterOpened', false)"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<van-action-sheet :close-on-click-overlay="false" title="活动详细信息" v-model="infoVisible" cancel-text="取消">
|
||||
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
|
||||
<van-list v-model="loading" :finished="finished" :immediate-check="false" @load="onLoad">
|
||||
<div class="family-mine-list">
|
||||
<div v-for="row in tableData" :key="row.id" class="family-mine-card">
|
||||
<img v-if="hasCover(row) && !imageLoadErrors[row.id]" class="family-mine-card__cover" :src="row.cover" :alt="row.activityName" @error="handleImageError(row)">
|
||||
<div v-else class="family-mine-card__cover-state" :class="{'is-error': hasCover(row)}">
|
||||
<van-icon name="photo-o"></van-icon>
|
||||
<span>{{ hasCover(row) ? '图片加载失败' : '暂无图片' }}</span>
|
||||
</div>
|
||||
<div class="family-mine-card__body">
|
||||
<div class="family-mine-card__title">{{ row.activityName }}</div>
|
||||
<div class="family-mine-card__time" v-if="row.activitySignUpStartTime && row.activitySignUpEndTime">
|
||||
报名时间:{{ $moment(row.activitySignUpStartTime).format('MM/DD HH:mm') }}~{{ $moment(row.activitySignUpEndTime).format('MM/DD HH:mm') }}
|
||||
</div>
|
||||
<div class="family-mine-card__time" v-if="row.activityStartTime && row.activityEndTime">
|
||||
活动时间:{{ $moment(row.activityStartTime).format('MM/DD HH:mm') }}~{{ $moment(row.activityEndTime).format('MM/DD HH:mm') }}
|
||||
</div>
|
||||
<div class="family-mine-card__meta" v-if="row.activityGroupName || row.trainType">
|
||||
<span class="family-mine-card__tag" v-if="row.activityGroupName"><span class="family-mine-card__tag-label">面向对象</span>{{ row.activityGroupName }}</span>
|
||||
<span class="family-mine-card__tag" v-if="row.trainType"><span class="family-mine-card__tag-label">活动类型</span>{{ row.trainType }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="family-mine-card__actions">
|
||||
<button type="button" class="family-mine-card__action" @click="onView(row)"><van-icon name="eye-o"></van-icon>查看介绍</button>
|
||||
<button type="button" class="family-mine-card__action" @click="onInfo(row)"><van-icon name="calendar-o"></van-icon>我的课程</button>
|
||||
<button type="button" class="family-mine-card__action is-primary" @click="onApply(row)"><van-icon name="edit"></van-icon>查看报名</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-list>
|
||||
<div v-if="!loading && tableData.length === 0" class="family-mine-empty">
|
||||
<img src="/assets/mobile/img/activity/family-empty.png" alt="亲子活动报名空状态插画">
|
||||
<div class="family-mine-empty__title">暂无报名记录</div>
|
||||
<div class="family-mine-empty__hint">当前筛选条件下暂时没有已报名活动</div>
|
||||
</div>
|
||||
</van-pull-refresh>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-container">
|
||||
<div>
|
||||
<van-image class="info-img" height="186" width="100%" :src="infoRow.cover"></van-image>
|
||||
<div class="info-title">{{infoRow.activityName}}</div>
|
||||
<pdf-preview :content="infoRow.introduce"></pdf-preview>
|
||||
<van-popup :style="{height: '100%', width: '100%'}" position="right" v-model="infoVisible">
|
||||
<div class="family-mine-intro-page">
|
||||
<van-nav-bar title="活动介绍" left-text="返回" left-arrow @click-left="historyBack"></van-nav-bar>
|
||||
<div class="family-mine-intro-scroll">
|
||||
<div class="family-mine-intro-hero">
|
||||
<div class="family-mine-intro-hero__icon"><van-icon name="description"></van-icon></div>
|
||||
<div>
|
||||
<div class="family-mine-intro-hero__title">亲子活动报名须知</div>
|
||||
<div class="family-mine-intro-hero__subtitle">请仔细阅读活动安排与报名要求</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="infoRow.introduce" class="family-mine-intro-card" v-html="infoRow.introduce"></div>
|
||||
<div v-else class="family-mine-intro-card">暂无活动介绍</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-action-sheet>
|
||||
|
||||
</van-popup>
|
||||
<van-action-sheet :close-on-click-overlay="false" title="报名信息" v-model="courseVisible" cancel-text="取消">
|
||||
<div class="table-list-container">
|
||||
<div v-for="(row, index) in mineCourses" :key="index" class="table-list-item">
|
||||
@@ -280,18 +494,20 @@ layout("/layouts/platform_h5.html"){
|
||||
<div class="item-actions"></div>
|
||||
</div>
|
||||
</van-action-sheet>
|
||||
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
components: {
|
||||
"pdf-preview": httpVueLoader("/components/plugins/sysFilePreview/PdfIndex.vue?v=" + new Date().getTime())
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tableData: [],
|
||||
loading: false,
|
||||
finished: false,
|
||||
refreshing: false,
|
||||
imageLoadErrors: {},
|
||||
filterOpened: false,
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
@@ -307,20 +523,12 @@ layout("/layouts/platform_h5.html"){
|
||||
{text: '已结束', value: 3},
|
||||
],
|
||||
infoVisible: false,
|
||||
infoRow: {},
|
||||
|
||||
mineCourses: [],
|
||||
courseVisible: false,
|
||||
mineCourses: [],
|
||||
infoRow: {},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onView(row) {
|
||||
this.infoRow = row
|
||||
this.infoVisible = true
|
||||
},
|
||||
onApply(row) {
|
||||
this.$pjaxReplace('/platform/family/apply/list/h5?id=' + row.id + '&dataType=mine')
|
||||
},
|
||||
onInfo(row) {
|
||||
this.$axios.post('/platform/family/mine/queryMineCourse', {activityId: row.id})
|
||||
.then((res) => {
|
||||
@@ -328,17 +536,58 @@ layout("/layouts/platform_h5.html"){
|
||||
this.courseVisible = true
|
||||
})
|
||||
},
|
||||
onReady() {
|
||||
this.doSearch()
|
||||
hasCover(row) {
|
||||
return !!(row && row.cover && String(row.cover).trim())
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
handleImageError(row) {
|
||||
this.$set(this.imageLoadErrors, row.id, true)
|
||||
},
|
||||
onView(row) {
|
||||
this.infoRow = row
|
||||
this.infoVisible = true
|
||||
},
|
||||
onApply(row) {
|
||||
this.$pjaxReplace('/platform/family/apply/list/h5?id=' + row.id + '&dataType=mine')
|
||||
},
|
||||
onLoad() {
|
||||
if(!this.finished) {
|
||||
this.loadActivities(false)
|
||||
}
|
||||
},
|
||||
onRefresh() {
|
||||
this.loadActivities(true)
|
||||
},
|
||||
loadActivities(reset) {
|
||||
if(reset) {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
this.tableData = []
|
||||
this.finished = false
|
||||
this.imageLoadErrors = {}
|
||||
}
|
||||
this.loading = true
|
||||
this.$axios.post('/platform/family/apply/activityPageData', this.pageForm).then((res) => {
|
||||
if(res.code === 0) {
|
||||
const list = res.data && res.data.list ? res.data.list : []
|
||||
this.tableData = this.pageForm.pageNumber === 1 ? list : this.tableData.concat(list)
|
||||
this.pageForm.totalCount = res.data && res.data.totalCount ? res.data.totalCount : 0
|
||||
this.finished = this.tableData.length >= this.pageForm.totalCount
|
||||
if(!this.finished) {
|
||||
this.pageForm.pageNumber++
|
||||
}
|
||||
}
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
this.refreshing = false
|
||||
})
|
||||
},
|
||||
doSearch() {
|
||||
this.loadActivities(true)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadActivities(true)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -2,53 +2,682 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<style>
|
||||
.van-tag--default {
|
||||
background-color: #f1f1f1 !important;
|
||||
body {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.sports-activity-page {
|
||||
min-height: 100vh;
|
||||
padding-bottom: calc(24px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.sports-activity-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.sports-activity-page .van-nav-bar__title {
|
||||
color: #1f2937;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.sports-activity-page .van-nav-bar .van-icon,
|
||||
.sports-activity-page .van-nav-bar__text {
|
||||
color: #397fbd;
|
||||
}
|
||||
|
||||
.sports-activity-content {
|
||||
padding: 12px 12px 0;
|
||||
}
|
||||
|
||||
.sports-activity-hero {
|
||||
position: relative;
|
||||
height: 134px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
color: #fff;
|
||||
background-color: #247fe8;
|
||||
box-shadow: 0 8px 20px rgba(51, 117, 219, .18);
|
||||
}
|
||||
|
||||
.sports-activity-hero__image {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
|
||||
.sports-activity-hero__copy {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
width: 64%;
|
||||
height: 100%;
|
||||
padding-left: 16px;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
background: linear-gradient(90deg, rgba(22, 112, 232, .98) 0%, rgba(22, 112, 232, .88) 52%, rgba(22, 112, 232, 0) 100%);
|
||||
}
|
||||
|
||||
.sports-activity-hero__title {
|
||||
font-size: 25px;
|
||||
line-height: 34px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 1px;
|
||||
text-shadow: 0 2px 6px rgba(17, 86, 182, .18);
|
||||
}
|
||||
|
||||
.sports-activity-hero__subtitle {
|
||||
margin-top: 4px;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
letter-spacing: .5px;
|
||||
opacity: .95;
|
||||
}
|
||||
|
||||
.sports-activity-sticky {
|
||||
padding: 10px 0 1px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.van-sticky--fixed .sports-activity-sticky {
|
||||
padding-right: 12px;
|
||||
padding-left: 12px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.sports-activity-search {
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.sports-activity-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.sports-activity-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.sports-activity-search .van-field__control::placeholder {
|
||||
color: #a7b0bf;
|
||||
}
|
||||
|
||||
.sports-activity-filter {
|
||||
margin: 0 0 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
transition: border-radius .18s ease;
|
||||
}
|
||||
|
||||
.sports-activity-filter.is-open {
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
.sports-activity-filter .van-dropdown-menu__bar {
|
||||
height: 44px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.sports-activity-filter .van-dropdown-menu__title {
|
||||
color: #66758a;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.sports-activity-filter .van-dropdown-menu__title--active,
|
||||
.sports-activity-filter .van-dropdown-item__option--active,
|
||||
.sports-activity-filter .van-dropdown-item__option--active .van-dropdown-item__icon {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.sports-activity-filter .van-dropdown-menu__title--down::after {
|
||||
border-color: transparent transparent #1989fa #1989fa;
|
||||
}
|
||||
|
||||
.sports-activity-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
margin: 0 12px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0 0 12px 12px;
|
||||
box-shadow: 0 10px 24px rgba(31, 65, 108, .14);
|
||||
}
|
||||
|
||||
.sports-activity-filter .van-dropdown-item__option {
|
||||
min-height: 48px;
|
||||
padding: 0 16px;
|
||||
color: #46566c;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.sports-activity-filter .van-cell::after {
|
||||
right: 16px;
|
||||
left: 16px;
|
||||
}
|
||||
|
||||
.sports-activity-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.sports-activity-card {
|
||||
display: flex;
|
||||
min-height: 74px;
|
||||
padding: 14px;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.sports-activity-card {
|
||||
position: relative;
|
||||
min-height: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
align-items: stretch;
|
||||
flex-direction: column;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sports-activity-card__icon {
|
||||
display: flex;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
margin-right: 12px;
|
||||
flex: 0 0 38px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 9px;
|
||||
color: #4d91ef;
|
||||
background-color: #edf4ff;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.sports-activity-card__body {
|
||||
min-width: 0;
|
||||
padding: 12px 38px 14px 14px;
|
||||
box-sizing: border-box;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.sports-activity-card__cover {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
margin: 0;
|
||||
flex: 0 0 150px;
|
||||
object-fit: cover;
|
||||
border-radius: 0;
|
||||
background-color: #edf4ff;
|
||||
}
|
||||
|
||||
.sports-activity-card__cover-state {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
flex: 0 0 150px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
row-gap: 8px;
|
||||
color: #8da1ba;
|
||||
background-color: #edf4fc;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.sports-activity-card__cover-state .van-icon {
|
||||
font-size: 34px;
|
||||
}
|
||||
|
||||
.sports-activity-card__cover-state.is-error {
|
||||
color: #c27b75;
|
||||
background-color: #fff3f1;
|
||||
}
|
||||
|
||||
.sports-activity-card > .sports-activity-card__icon {
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
margin: 0;
|
||||
flex: 0 0 150px;
|
||||
border-radius: 0;
|
||||
font-size: 40px;
|
||||
}
|
||||
|
||||
.sports-activity-card__title {
|
||||
color: #303846;
|
||||
font-size: 14px;
|
||||
line-height: 21px;
|
||||
}
|
||||
|
||||
.sports-activity-card__title {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sports-activity-card__time {
|
||||
margin-top: 4px;
|
||||
color: #98a2b2;
|
||||
font-size: 12px;
|
||||
line-height: 17px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sports-activity-card__meta {
|
||||
margin-top: 10px;
|
||||
padding-top: 9px;
|
||||
border-top: 1px solid #edf1f6;
|
||||
}
|
||||
|
||||
.sports-activity-card__address {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
color: #69788d;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.sports-activity-card__address .van-icon {
|
||||
margin: 2px 5px 0 0;
|
||||
flex: none;
|
||||
color: #6c9ff8;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.sports-activity-card__address span {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sports-activity-card__tags {
|
||||
display: flex;
|
||||
margin-top: 8px;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.sports-activity-card__tag {
|
||||
display: inline-flex;
|
||||
padding: 3px 8px;
|
||||
align-items: center;
|
||||
border-radius: 4px;
|
||||
color: #397de0;
|
||||
background-color: #edf5ff;
|
||||
font-size: 11px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.sports-activity-card__tag-label {
|
||||
margin-right: 4px;
|
||||
color: #8aa7cf;
|
||||
}
|
||||
|
||||
.sports-activity-card__arrow {
|
||||
position: absolute;
|
||||
top: 164px;
|
||||
right: 14px;
|
||||
color: #b4bdca;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.sports-activity-empty-illustration {
|
||||
display: flex;
|
||||
min-height: 250px;
|
||||
padding: 24px 18px 32px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.sports-activity-empty-illustration img {
|
||||
display: block;
|
||||
width: 82%;
|
||||
max-width: 280px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.sports-activity-empty-illustration__title {
|
||||
margin-top: -8px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.sports-activity-empty-illustration__hint {
|
||||
margin-top: 6px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.activity-notification-popup,
|
||||
.activity-notification-page {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.activity-notification-page {
|
||||
position: relative;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.activity-notification-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.activity-notification-page .van-nav-bar__title {
|
||||
color: #1f2937;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.activity-notification-page .van-nav-bar .van-icon,
|
||||
.activity-notification-page .van-nav-bar__text {
|
||||
color: #397fbd;
|
||||
}
|
||||
|
||||
.activity-notification-scroll {
|
||||
height: calc(100vh - 46px);
|
||||
padding: 12px 12px calc(92px + env(safe-area-inset-bottom));
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.activity-notification-hero {
|
||||
display: flex;
|
||||
min-height: 82px;
|
||||
padding: 16px;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
border-radius: 12px;
|
||||
color: #fff;
|
||||
background: linear-gradient(120deg, #2d7eea 0%, #5ba6f7 100%);
|
||||
box-shadow: 0 8px 20px rgba(45, 126, 234, .18);
|
||||
}
|
||||
|
||||
.activity-notification-hero__icon {
|
||||
display: flex;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
margin-right: 12px;
|
||||
flex: 0 0 44px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 11px;
|
||||
color: #2d7eea;
|
||||
background-color: rgba(255, 255, 255, .92);
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.activity-notification-hero__title {
|
||||
font-size: 17px;
|
||||
line-height: 24px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.activity-notification-hero__subtitle {
|
||||
margin-top: 3px;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
.activity-notification-card {
|
||||
margin-top: 12px;
|
||||
padding: 18px 16px;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.activity-notification-content,
|
||||
.activity-notification-content div,
|
||||
.activity-notification-content p,
|
||||
.activity-notification-content span,
|
||||
.activity-notification-content li {
|
||||
color: #3f4c5e !important;
|
||||
font-size: 14px !important;
|
||||
line-height: 1.8 !important;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.activity-notification-content h1,
|
||||
.activity-notification-content h2,
|
||||
.activity-notification-content h3 {
|
||||
margin: 16px 0 10px !important;
|
||||
color: #1f2f43 !important;
|
||||
font-size: 19px !important;
|
||||
line-height: 1.5 !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
.activity-notification-content > :first-child {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
.activity-notification-content p {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 8px !important;
|
||||
}
|
||||
|
||||
.activity-notification-content img {
|
||||
max-width: 100% !important;
|
||||
height: auto !important;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.activity-notification-content table {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
overflow-x: auto;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.activity-notification-empty {
|
||||
display: flex;
|
||||
min-height: 180px;
|
||||
margin-top: 12px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
row-gap: 10px;
|
||||
border-radius: 12px;
|
||||
color: #9aa7b8;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.activity-notification-empty .van-icon {
|
||||
color: #83b5f4;
|
||||
font-size: 36px;
|
||||
}
|
||||
|
||||
.activity-notification-footer {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 5;
|
||||
padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
|
||||
border-top: 1px solid #edf1f6;
|
||||
background-color: rgba(255, 255, 255, .96);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.activity-notification-footer .van-button {
|
||||
height: 42px;
|
||||
border: 0;
|
||||
font-size: 15px;
|
||||
background-color: #1989fa;
|
||||
box-shadow: 0 6px 16px rgba(25, 137, 250, .22);
|
||||
}
|
||||
|
||||
.activity-notification-footer .van-button.is-disabled,
|
||||
.activity-notification-footer .van-button--disabled {
|
||||
color: #8b98aa !important;
|
||||
background-color: #eef2f7 !important;
|
||||
opacity: 1;
|
||||
box-shadow: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar title="活动列表" @click-left="()=>this.$pjaxReplace('/platform/home')" left-arrow left-text="返回" placeholder fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<van-dropdown-menu>
|
||||
<year-van-dropdown-item :num="5" @change="doSearch" v-model="pageForm.year"></year-van-dropdown-item>
|
||||
<van-dropdown-item :options="stateList" @change="doSearch"
|
||||
v-model="pageForm.isActivity"></van-dropdown-item>
|
||||
<van-dropdown-item :options="applyStatusOptions" @change="doSearch"
|
||||
v-model="pageForm.applyStatus"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</van-sticky>
|
||||
<div class="sports-activity-page">
|
||||
<van-nav-bar
|
||||
title="体育活动"
|
||||
left-arrow
|
||||
left-text="返回"
|
||||
fixed
|
||||
placeholder
|
||||
@click-left="goBack"
|
||||
></van-nav-bar>
|
||||
|
||||
<table-list api="/platform/activity/apply/h5/activityData"
|
||||
:page_form.sync="pageForm"
|
||||
ref="tableListRef"
|
||||
title="NAME"
|
||||
img="image"
|
||||
@ready="onReady"
|
||||
>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="报名时间">
|
||||
{{$moment(row.applyStartTime).format('MM/DD HH:mm') + '~' + $moment(row.applyEndTime).format('MM/DD HH:mm')}}
|
||||
</table-column>
|
||||
<table-column label="活动时间">
|
||||
{{$moment(row.startTime).format('MM/DD HH:mm') + '~' + $moment(row.endTime).format('MM/DD HH:mm')}}
|
||||
</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<template v-if="$moment().isBefore($moment(row.applyEndTime))">
|
||||
<div class="action-btn" @click="openView(row)">
|
||||
<i class="fa fa-edit"></i>
|
||||
<span>去报名</span>
|
||||
<div class="sports-activity-content">
|
||||
<section class="sports-activity-hero">
|
||||
<img
|
||||
class="sports-activity-hero__image"
|
||||
src="/assets/mobile/img/activity/hero/sports-hero-v2.png"
|
||||
alt="体育活动插画"
|
||||
>
|
||||
<div class="sports-activity-hero__copy">
|
||||
<div class="sports-activity-hero__title">体育活动</div>
|
||||
<div class="sports-activity-hero__subtitle">强健体魄 · 运动同行</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</table-list>
|
||||
</section>
|
||||
|
||||
<activity_event_notification
|
||||
:event_notification="viewData.eventNotification"
|
||||
:id="viewData.id"
|
||||
ref="eventNotification"
|
||||
></activity_event_notification>
|
||||
<van-sticky :offset-top="46">
|
||||
<div class="sports-activity-sticky">
|
||||
<van-search
|
||||
v-model="searchKeyword"
|
||||
class="sports-activity-search"
|
||||
placeholder="搜索体育活动"
|
||||
shape="round"
|
||||
clearable
|
||||
@search="doSearch"
|
||||
@clear="doSearch"
|
||||
></van-search>
|
||||
|
||||
<van-dropdown-menu
|
||||
class="sports-activity-filter"
|
||||
:class="{'is-open': filterOpened}"
|
||||
active-color="#1989fa"
|
||||
>
|
||||
<year-van-dropdown-item
|
||||
:num="5"
|
||||
v-model="pageForm.year"
|
||||
@change="doSearch"
|
||||
@open="$set($data, 'filterOpened', true)"
|
||||
@close="$set($data, 'filterOpened', false)"
|
||||
></year-van-dropdown-item>
|
||||
<van-dropdown-item
|
||||
v-model="pageForm.isActivity"
|
||||
:options="stateList"
|
||||
@change="doSearch"
|
||||
@open="$set($data, 'filterOpened', true)"
|
||||
@close="$set($data, 'filterOpened', false)"
|
||||
></van-dropdown-item>
|
||||
<van-dropdown-item
|
||||
v-model="pageForm.applyStatus"
|
||||
:options="applyStatusOptions"
|
||||
@change="doSearch"
|
||||
@open="$set($data, 'filterOpened', true)"
|
||||
@close="$set($data, 'filterOpened', false)"
|
||||
></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<div class="sports-activity-list">
|
||||
<div
|
||||
v-for="row in activityList"
|
||||
:key="row.id"
|
||||
class="sports-activity-card"
|
||||
@click="openView(row)"
|
||||
>
|
||||
<img
|
||||
v-if="hasActivityImage(row) && !imageLoadErrors[row.id]"
|
||||
class="sports-activity-card__cover"
|
||||
:src="row.image"
|
||||
:alt="row.NAME || row.name"
|
||||
@error="handleImageError(row)"
|
||||
>
|
||||
<div
|
||||
v-else
|
||||
class="sports-activity-card__cover-state"
|
||||
:class="{'is-error': hasActivityImage(row)}"
|
||||
>
|
||||
<van-icon name="photo-o"></van-icon>
|
||||
<span>{{ hasActivityImage(row) ? '图片加载失败' : '暂无图片' }}</span>
|
||||
</div>
|
||||
<div class="sports-activity-card__body">
|
||||
<div class="sports-activity-card__title">{{ row.NAME || row.name }}</div>
|
||||
<div class="sports-activity-card__time" v-if="row.applyStartTime && row.applyEndTime">
|
||||
报名时间:{{ $moment(row.applyStartTime).format('MM/DD HH:mm') }}~{{ $moment(row.applyEndTime).format('MM/DD HH:mm') }}
|
||||
</div>
|
||||
<div class="sports-activity-card__time" v-if="row.startTime && row.endTime">
|
||||
活动时间:{{ $moment(row.startTime).format('MM/DD HH:mm') }}~{{ $moment(row.endTime).format('MM/DD HH:mm') }}
|
||||
</div>
|
||||
<div class="sports-activity-card__meta" v-if="row.address || formatGameStyle(row.gameStyle) || formatApplyType(row.applyType) || formatApplyWay(row.applyWay)">
|
||||
<div class="sports-activity-card__address" v-if="row.address">
|
||||
<van-icon name="location-o"></van-icon>
|
||||
<span>{{ row.address }}</span>
|
||||
</div>
|
||||
<div class="sports-activity-card__tags" v-if="formatGameStyle(row.gameStyle) || formatApplyType(row.applyType) || formatApplyWay(row.applyWay)">
|
||||
<span class="sports-activity-card__tag" v-if="formatGameStyle(row.gameStyle)">
|
||||
<span class="sports-activity-card__tag-label">竞赛方式</span>{{ formatGameStyle(row.gameStyle) }}
|
||||
</span>
|
||||
<span class="sports-activity-card__tag" v-if="formatApplyType(row.applyType)">
|
||||
<span class="sports-activity-card__tag-label">活动类型</span>{{ formatApplyType(row.applyType) }}
|
||||
</span>
|
||||
<span class="sports-activity-card__tag" v-if="formatApplyWay(row.applyWay)">
|
||||
<span class="sports-activity-card__tag-label">报名方式</span>{{ formatApplyWay(row.applyWay) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<van-icon class="sports-activity-card__arrow" name="arrow"></van-icon>
|
||||
</div>
|
||||
|
||||
<div v-if="activityList.length === 0" class="sports-activity-empty-illustration">
|
||||
<img src="/assets/mobile/img/activity/sports-empty.png" alt="体育活动空状态插画">
|
||||
<div class="sports-activity-empty-illustration__title">{{ emptyText }}</div>
|
||||
<div class="sports-activity-empty-illustration__hint">{{ emptyHint }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<activity_event_notification
|
||||
:event_notification="viewData.eventNotification"
|
||||
:id="viewData.id"
|
||||
:apply_start_time="viewData.applyStartTime"
|
||||
:apply_end_time="viewData.applyEndTime"
|
||||
ref="eventNotification"
|
||||
></activity_event_notification>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
@@ -57,52 +686,106 @@ layout("/layouts/platform_h5.html"){
|
||||
el: "#app",
|
||||
data() {
|
||||
return {
|
||||
tableData: [],
|
||||
finished: false,
|
||||
loading: false,
|
||||
activityList: [],
|
||||
searchKeyword: "",
|
||||
imageLoadErrors: {},
|
||||
filterOpened: false,
|
||||
pageForm: {
|
||||
isActivity: 2,
|
||||
applyStatus: 1,
|
||||
year: new Date().getFullYear(),
|
||||
pageNumber: 1,
|
||||
pageSize: 5,
|
||||
totalCount: 0
|
||||
year: new Date().getFullYear()
|
||||
},
|
||||
yearList: [],
|
||||
stateList: [
|
||||
{value: 1, text: "全部活动"},
|
||||
{value: 2, text: "报名中"},
|
||||
{value: 3, text: "报名已结束"}
|
||||
],
|
||||
applyStatusOptions: [
|
||||
{value: 1, text: "未报名"},
|
||||
{value: 2, text: "已报名"}
|
||||
],
|
||||
stateList: [
|
||||
{value: 1, text: "全部"},
|
||||
{value: 2, text: "报名中"},
|
||||
{value: 3, text: "报名已结束"}
|
||||
],
|
||||
subLoading: false,
|
||||
viewShow: false,
|
||||
viewData: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
emptyText() {
|
||||
if (this.searchKeyword.trim()) return "未找到相关体育活动"
|
||||
if (this.pageForm.isActivity === 3) return "暂无已结束的体育活动"
|
||||
if (this.pageForm.isActivity === 2) return "暂无报名中的体育活动"
|
||||
return "暂无体育活动"
|
||||
},
|
||||
emptyHint() {
|
||||
return this.searchKeyword.trim() ? "请尝试更换搜索关键词" : "当前筛选条件下暂时没有活动"
|
||||
}
|
||||
},
|
||||
components: {
|
||||
activity_event_notification: ACTIVITY_EVENT_NOTIFICATION
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
this.$pjaxReplace("/platform/home")
|
||||
},
|
||||
openView(row) {
|
||||
this.viewData = row
|
||||
this.$refs.eventNotification.viewShow = true
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
this.$refs.eventNotification.viewShow = true
|
||||
})
|
||||
},
|
||||
onReady() {
|
||||
this.doSearch()
|
||||
doSearch() {
|
||||
this.loadActivities()
|
||||
},
|
||||
hasActivityImage(row) {
|
||||
return !!(row && row.image && String(row.image).trim())
|
||||
},
|
||||
handleImageError(row) {
|
||||
this.$set(this.imageLoadErrors, row.id, true)
|
||||
},
|
||||
formatGameStyle(value) {
|
||||
return {
|
||||
1: "竞赛类",
|
||||
2: "非竞赛类"
|
||||
}[Number(value)] || ""
|
||||
},
|
||||
formatApplyType(value) {
|
||||
return {
|
||||
1: "单一团体赛",
|
||||
2: "综合赛",
|
||||
3: "个人赛"
|
||||
}[Number(value)] || ""
|
||||
},
|
||||
formatApplyWay(value) {
|
||||
if (value === null || value === undefined || value === "") return ""
|
||||
let values = value
|
||||
if (typeof values === "string") {
|
||||
try {
|
||||
values = JSON.parse(values)
|
||||
} catch (e) {
|
||||
values = values.split(",")
|
||||
}
|
||||
}
|
||||
if (!Array.isArray(values)) values = [values]
|
||||
const labels = {
|
||||
1: "个人报名",
|
||||
2: "分工会报名",
|
||||
3: "小程序报名"
|
||||
}
|
||||
return values.map(item => labels[Number(item)]).filter(Boolean).join("、")
|
||||
},
|
||||
loadActivities() {
|
||||
this.activityList = []
|
||||
this.imageLoadErrors = {}
|
||||
const queryForm = Object.assign({}, this.pageForm, {
|
||||
searchKeyword: this.searchKeyword.trim()
|
||||
})
|
||||
this.$axios.post("/platform/activity/apply/h5/activityData", queryForm).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.activityList = res.data && res.data.list ? res.data.list : []
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadActivities()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,8 +1,580 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<style>
|
||||
body {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.sports-event-page {
|
||||
min-height: 100vh;
|
||||
padding-bottom: calc(24px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.sports-event-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.sports-event-page .van-nav-bar__title {
|
||||
color: #1f2937;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.sports-event-page .van-nav-bar .van-icon,
|
||||
.sports-event-page .van-nav-bar__text {
|
||||
color: #397fbd;
|
||||
}
|
||||
|
||||
.sports-event-summary {
|
||||
display: flex;
|
||||
min-height: 82px;
|
||||
margin: 12px 12px 0;
|
||||
padding: 16px;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
border-radius: 12px;
|
||||
color: #fff;
|
||||
background: linear-gradient(120deg, #2d7eea 0%, #5ba6f7 100%);
|
||||
box-shadow: 0 8px 20px rgba(45, 126, 234, .18);
|
||||
}
|
||||
|
||||
.sports-event-summary__icon {
|
||||
display: flex;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
margin-right: 12px;
|
||||
overflow: hidden;
|
||||
flex: 0 0 44px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 11px;
|
||||
color: #2d7eea;
|
||||
background-color: rgba(255, 255, 255, .92);
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.sports-event-summary__body {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.sports-event-summary__title {
|
||||
overflow: hidden;
|
||||
color: #fff;
|
||||
font-size: 17px;
|
||||
line-height: 24px;
|
||||
font-weight: 600;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sports-event-summary__subtitle {
|
||||
margin-top: 3px;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
.sports-event-sticky {
|
||||
padding: 10px 0 8px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.sports-event-search {
|
||||
margin: 0 12px;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.sports-event-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 13px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(55, 85, 126, .07);
|
||||
}
|
||||
|
||||
.sports-event-search .van-field__control {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.sports-event-list-head {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
margin: 16px 0 0;
|
||||
padding: 0 12px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.sports-event-list-head__title {
|
||||
color: #263548;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.sports-event-list-head__count {
|
||||
color: #8d9aad;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.sports-event-list-head__tools {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.sports-event-view-toggle {
|
||||
display: inline-flex;
|
||||
height: 28px;
|
||||
padding: 0 10px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 0;
|
||||
border-radius: 14px;
|
||||
color: #397de0;
|
||||
background-color: #eaf3ff;
|
||||
font-size: 12px;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
.sports-event-view-toggle i {
|
||||
margin-right: 5px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.sports-event-page .sports-event-card-list {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.sports-event-page .table-card {
|
||||
margin-bottom: 12px;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.sports-event-page .table-card > .van-image,
|
||||
.sports-event-page .table-card > .van-image img {
|
||||
display: block;
|
||||
border-radius: 12px 12px 0 0;
|
||||
}
|
||||
|
||||
.sports-event-page .table-card .van-cell {
|
||||
padding: 9px 16px;
|
||||
color: #566579;
|
||||
font-size: 13px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.sports-event-page .table-card .van-cell:first-of-type {
|
||||
padding-top: 15px;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
.sports-event-page .table-card .van-cell::after {
|
||||
right: 16px;
|
||||
left: 16px;
|
||||
border-color: #edf1f6;
|
||||
}
|
||||
|
||||
.sports-event-page .table-card .van-cell__title {
|
||||
color: #66758a;
|
||||
}
|
||||
|
||||
.sports-event-page .table-card .van-cell__value,
|
||||
.sports-event-page .table-card .van-cell__right-icon {
|
||||
color: #263548;
|
||||
}
|
||||
|
||||
.sports-event-page .table-card .font-size3 {
|
||||
color: #23344a;
|
||||
font-size: 16px;
|
||||
line-height: 23px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.sports-event-page .table-card .van-tag {
|
||||
padding: 3px 7px;
|
||||
justify-content: center;
|
||||
border: 0;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.sports-event-page .table-card .sports-event-status-tag.is-pending {
|
||||
color: #397de0;
|
||||
background-color: #edf5ff;
|
||||
}
|
||||
|
||||
.sports-event-page .table-card .sports-event-status-tag.is-success {
|
||||
color: #35a86b;
|
||||
background-color: #eaf8f1;
|
||||
}
|
||||
|
||||
.sports-event-page .table-card .sports-event-status-tag.is-rejected {
|
||||
color: #df5b59;
|
||||
background-color: #fff1f0;
|
||||
}
|
||||
|
||||
.sports-event-card__body {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.sports-event-card__title-row {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.sports-event-card__title {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
color: #23344a;
|
||||
font-size: 16px;
|
||||
line-height: 23px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.sports-event-card__status {
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.sports-event-card__activity {
|
||||
display: flex;
|
||||
margin-top: 5px;
|
||||
align-items: center;
|
||||
color: #78879a;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.sports-event-card__activity .van-icon {
|
||||
margin-right: 5px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.sports-event-card__tags,
|
||||
.sports-event-card__config {
|
||||
display: flex;
|
||||
margin-top: 10px;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.sports-event-card__tag,
|
||||
.sports-event-card__config-tag {
|
||||
display: inline-flex;
|
||||
min-height: 24px;
|
||||
padding: 3px 8px;
|
||||
align-items: center;
|
||||
border-radius: 5px;
|
||||
color: #397de0;
|
||||
background-color: #edf5ff;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.sports-event-card__tag-label {
|
||||
margin-right: 4px;
|
||||
color: #7f9fc9;
|
||||
}
|
||||
|
||||
.sports-event-card__stats {
|
||||
display: grid;
|
||||
margin-top: 12px;
|
||||
padding: 12px 0;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
border-top: 1px solid #edf1f6;
|
||||
border-bottom: 1px solid #edf1f6;
|
||||
}
|
||||
|
||||
.sports-event-card__stat {
|
||||
min-width: 0;
|
||||
padding: 0 10px;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.sports-event-card__stat:first-child {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.sports-event-card__stat:last-child {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.sports-event-card__stat + .sports-event-card__stat {
|
||||
border-left: 1px solid #edf1f6;
|
||||
}
|
||||
|
||||
.sports-event-card__stat-label {
|
||||
color: #7b899b;
|
||||
font-size: 11px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.sports-event-card__stat-value {
|
||||
margin-top: 3px;
|
||||
overflow: hidden;
|
||||
color: #33445a;
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sports-event-card__config-tag {
|
||||
color: #66758a;
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
.sports-event-card__extra {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.sports-event-card__extra-row {
|
||||
display: flex;
|
||||
padding: 4px 0;
|
||||
align-items: flex-start;
|
||||
color: #66758a;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.sports-event-card__extra-row .van-icon {
|
||||
margin: 2px 6px 0 0;
|
||||
flex: 0 0 auto;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.sports-event-card__extra-label {
|
||||
margin-right: 8px;
|
||||
flex: 0 0 auto;
|
||||
color: #7b899b;
|
||||
}
|
||||
|
||||
.sports-event-card__extra-value {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
color: #33445a;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.sports-event-page .table-card .table-card-footer {
|
||||
min-height: 56px;
|
||||
margin-top: 4px;
|
||||
padding: 12px 16px;
|
||||
align-items: center;
|
||||
border-top: 1px solid #edf1f6;
|
||||
background-color: #f8fbff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.sports-event-page .table-card .table-card-footer::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sports-event-card__footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.sports-event-card__footer > div {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.sports-event-union-action-hint {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: #ed6a0c;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.sports-event-union-action-hint.is-authorized {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.sports-event-page .table-card .table-card-footer .van-cell__value {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.sports-event-page .table-card-footer .van-button {
|
||||
min-width: 78px;
|
||||
height: 32px;
|
||||
padding: 0 14px;
|
||||
border: 0;
|
||||
border-radius: 16px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.sports-event-page .table-card-footer .van-button i {
|
||||
margin-right: 6px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.sports-event-page .table-card-footer .sports-event-apply-button {
|
||||
width: 108px;
|
||||
min-width: 108px;
|
||||
height: 32px;
|
||||
color: #fff !important;
|
||||
border-color: #1989fa !important;
|
||||
background-color: #1989fa !important;
|
||||
box-shadow: 0 5px 12px rgba(25, 137, 250, .18);
|
||||
}
|
||||
|
||||
.sports-event-page .table-card-footer .sports-event-cancel-button {
|
||||
width: 108px;
|
||||
min-width: 108px;
|
||||
height: 32px;
|
||||
color: #fff !important;
|
||||
border-color: #e84d4f !important;
|
||||
background-color: #e84d4f !important;
|
||||
box-shadow: 0 5px 12px rgba(232, 77, 79, .16);
|
||||
}
|
||||
|
||||
.sports-event-page .table-card-footer .van-button__content {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sports-event-compact-list {
|
||||
margin: 0 12px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.sports-event-compact-item {
|
||||
display: flex;
|
||||
min-height: 68px;
|
||||
padding: 12px 14px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 1px solid #edf1f6;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.sports-event-compact-item:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.sports-event-compact-item__name {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
color: #23344a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sports-event-compact-item__action {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.sports-event-page .sports-event-compact-list .sports-event-compact-button.van-button {
|
||||
min-width: 0;
|
||||
height: 28px !important;
|
||||
padding: 0 10px !important;
|
||||
border: 0 !important;
|
||||
border-radius: 14px;
|
||||
font-size: 12px;
|
||||
line-height: 28px;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.sports-event-compact-button i {
|
||||
margin-right: 4px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.sports-event-page .sports-event-compact-list .sports-event-compact-button--apply.van-button {
|
||||
color: #397de0 !important;
|
||||
background: #edf5ff !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.sports-event-page .sports-event-compact-list .sports-event-compact-button--cancel.van-button {
|
||||
color: #df5b59 !important;
|
||||
background: #fff1f0 !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.sports-event-compact-button .van-button__content {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sports-event-page .van-list__finished-text,
|
||||
.sports-event-page .van-list__loading {
|
||||
color: #9aa7b8;
|
||||
font-size: 13px;
|
||||
line-height: 44px;
|
||||
}
|
||||
|
||||
.sports-event-refresh {
|
||||
min-height: calc(100vh - 226px);
|
||||
}
|
||||
|
||||
.sports-event-empty {
|
||||
display: flex;
|
||||
min-height: 300px;
|
||||
padding: 28px 18px;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.sports-event-empty img {
|
||||
display: block;
|
||||
width: 82%;
|
||||
max-width: 300px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.sports-event-empty__title {
|
||||
margin-top: -8px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.sports-event-empty__hint {
|
||||
margin-top: 6px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<div class="sports-event-page">
|
||||
<van-sticky>
|
||||
<van-nav-bar
|
||||
@click-left="historyBack"
|
||||
@@ -13,99 +585,188 @@ layout("/layouts/platform_h5.html"){
|
||||
></van-nav-bar>
|
||||
</van-sticky>
|
||||
|
||||
<div class="sports-event-summary">
|
||||
<div class="sports-event-summary__icon">
|
||||
<van-icon name="award-o"></van-icon>
|
||||
</div>
|
||||
<div class="sports-event-summary__body">
|
||||
<div class="sports-event-summary__title">体育活动项目</div>
|
||||
<div class="sports-event-summary__subtitle">选择适合的项目,参与健康运动</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<van-sticky :offset-top="46">
|
||||
<div class="sports-event-sticky">
|
||||
<van-search
|
||||
v-model="pageForm.searchKeyword"
|
||||
class="sports-event-search"
|
||||
placeholder="搜索项目名称"
|
||||
shape="round"
|
||||
clearable
|
||||
@search="doSearch"
|
||||
@clear="doSearch"
|
||||
></van-search>
|
||||
|
||||
<div class="sports-event-list-head">
|
||||
<button type="button" class="sports-event-view-toggle" @click="toggleViewMode">
|
||||
<i :class="viewMode === 'card' ? 'fa fa-list' : 'fa fa-th-large'"></i>
|
||||
<span>{{ viewMode === 'card' ? '列表' : '卡片' }}</span>
|
||||
</button>
|
||||
<div class="sports-event-list-head__count" v-if="pageForm.totalCount">共 {{ pageForm.totalCount }} 项</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<van-pull-refresh class="sports-event-refresh" v-model="refreshing" @refresh="onRefresh">
|
||||
<div>
|
||||
<van-list :finished="finished" @load="pageData" finished-text="没有更多了" v-if="tableData.length>0"
|
||||
v-model="loading">
|
||||
<div class="table-list">
|
||||
<div class="sports-event-card-list" v-if="viewMode === 'card'">
|
||||
<div :key="row.id" class="table-card" v-for="row in tableData">
|
||||
<van-image :src="row.image" fit="cover" height="200" v-if="row.image" width="100%"></van-image>
|
||||
<van-cell>
|
||||
<template slot="title">
|
||||
<div class="flex-align">
|
||||
<span class="font-size3 bold">{{row.allName}}</span>
|
||||
<div class="sports-event-card__body">
|
||||
<div class="sports-event-card__title-row">
|
||||
<div class="sports-event-card__title">{{row.allName}}</div>
|
||||
<div class="sports-event-card__status">
|
||||
<template v-if="row.status&&row.applyWay.length===1&&row.applyWay.includes(1)">
|
||||
<van-tag class="sports-event-status-tag is-pending" v-if="row.status===1">待审核</van-tag>
|
||||
<van-tag class="sports-event-status-tag is-success" v-if="row.status===2">已成功报名</van-tag>
|
||||
<van-tag class="sports-event-status-tag is-rejected" v-if="row.status===3">审核不通过</van-tag>
|
||||
</template>
|
||||
<template v-else>
|
||||
<van-tag class="sports-event-status-tag is-pending" v-if="row.status2===0">待审核</van-tag>
|
||||
<van-tag class="sports-event-status-tag is-success" v-if="row.status2===2">已成功报名</van-tag>
|
||||
<van-tag class="sports-event-status-tag is-rejected" v-if="row.status2===3">审核不通过</van-tag>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<template #right-icon>
|
||||
<div style="display: flex; justify-content: flex-end"
|
||||
v-if="row.status&&row.applyWay.length===1&&row.applyWay.includes(1)">
|
||||
<van-tag type="primary" v-if="row.status===1">待审核</van-tag>
|
||||
<van-tag type="success" v-if="row.status===2">已成功报名</van-tag>
|
||||
<van-tag type="danger" v-if="row.status===3">审核不通过</van-tag>
|
||||
</div>
|
||||
<div class="sports-event-card__activity" v-if="row.name">
|
||||
<van-icon name="flag-o"></van-icon>
|
||||
<span>{{row.name}}</span>
|
||||
</div>
|
||||
<div class="sports-event-card__tags">
|
||||
<span class="sports-event-card__tag" v-if="row.eveProjectType"><span class="sports-event-card__tag-label">项目</span>{{row.eveProjectType == 2 ? '团体' : '单项'}}</span>
|
||||
<span class="sports-event-card__tag"><span class="sports-event-card__tag-label">性别</span>{{row.isMenWomen == 1 ? '男子' : row.isMenWomen == 2 ? '女子' : '不限'}}</span>
|
||||
<span class="sports-event-card__tag" v-if="row.isInterest">趣味项目</span>
|
||||
<span class="sports-event-card__tag" v-if="row.registrationWays"><span class="sports-event-card__tag-label">报名</span>{{row.registrationWays == 2 ? '双人' : '单人'}}</span>
|
||||
<span class="sports-event-card__tag" v-if="row.applyType"><span class="sports-event-card__tag-label">活动</span>{{row.applyType == 2 ? '综合类' : '单一类'}}</span>
|
||||
<span class="sports-event-card__tag" v-if="row.applyWay && row.applyWay.includes(1)">个人报名</span>
|
||||
<span class="sports-event-card__tag" v-if="row.applyWay && row.applyWay.includes(2)">分工会报名</span>
|
||||
<span class="sports-event-card__tag" v-if="row.applyWay && row.applyWay.includes(3)">小程序报名</span>
|
||||
</div>
|
||||
<div class="sports-event-card__stats">
|
||||
<div class="sports-event-card__stat">
|
||||
<div class="sports-event-card__stat-label">可报队数</div>
|
||||
<div class="sports-event-card__stat-value">{{row.eveProjectType == 2 && row.restrictTotalTeam != null ? row.restrictTotalTeam + '队' : '不适用'}}</div>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: flex-end" v-else>
|
||||
<van-tag type="primary" v-if="row.status2===0">待审核</van-tag>
|
||||
<van-tag type="success" v-if="row.status2===2">已成功报名</van-tag>
|
||||
<van-tag type="danger" v-if="row.status2===3">审核不通过</van-tag>
|
||||
<div class="sports-event-card__stat">
|
||||
<div class="sports-event-card__stat-label">运动员人数</div>
|
||||
<div class="sports-event-card__stat-value" v-if="row.athletesMinNum != null && row.athletesMaxNum != null">{{row.athletesMinNum}}-{{row.athletesMaxNum}}人</div>
|
||||
<div class="sports-event-card__stat-value" v-else-if="row.athletesMaxNum != null">最多{{row.athletesMaxNum}}人</div>
|
||||
<div class="sports-event-card__stat-value" v-else>暂无限制</div>
|
||||
</div>
|
||||
</template>
|
||||
</van-cell>
|
||||
<van-cell title="可报队数" v-if="row.eveProjectType==='2'">
|
||||
<template #right-icon>{{ row.restrictTotalTeam }}队</template>
|
||||
</van-cell>
|
||||
<van-cell title="每队可报人数" v-if="row.athletesMaxNum<=99">
|
||||
<template #right-icon>
|
||||
<span v-if="row.athletesMaxNum">{{ row.athletesMaxNum }}人</span>
|
||||
<span v-else-if="row.applyType===1">{{ row.athletesMaxNum * row.restrictTotalTeam}}人</span>
|
||||
<span v-else-if="row.applyType===2&&row.eveProjectType==='1'">{{row.athletesMaxNum}}人</span>
|
||||
<span v-else-if="row.applyType===2&&row.eveProjectType==='2'">
|
||||
{{(row.restrictGirlNum ? row.restrictGirlNum : 0) + (row.restrictBoyNum ? row.restrictBoyNum : 0)}}人
|
||||
</span>
|
||||
<span v-else>暂无</span>
|
||||
</template>
|
||||
</van-cell>
|
||||
<!-- <van-cell title="已报名总人数">-->
|
||||
<!-- <template #right-icon>-->
|
||||
<!-- <span v-if="row.successUserApply>0&&row.applyType!==3">{{ row.successUserApply }}人</span>-->
|
||||
<!-- <span v-else-if="JSON.parse(row.applyWay).length===2&&row.applyWay.includes(1)">{{row.totalApplyNum}}人</span>-->
|
||||
<!-- <span v-else-if="row.totalApplyNum>0&&row.applyType===3">{{ row.totalApplyNum }}人</span>-->
|
||||
<!-- <span v-else>0人</span>-->
|
||||
<!-- </template>-->
|
||||
<!-- </van-cell>-->
|
||||
<van-cell title="暂保存人数">
|
||||
<template #right-icon>
|
||||
<span v-if="row.apply_num_bc>0">已保存({{row.apply_num_bc}})人</span>
|
||||
<span v-else>暂无已保存人数</span>
|
||||
</template>
|
||||
</van-cell>
|
||||
<van-cell title="已报名人员" v-if="JSON.parse(row.applyWay).length===1">
|
||||
<template #right-icon>
|
||||
<span @click="openApplyUser(row)" v-if="row.userApplyNames">{{ row.userApplyNames}}</span>
|
||||
<span v-else>暂无</span>
|
||||
</template>
|
||||
</van-cell>
|
||||
<van-cell class="table-card-footer">
|
||||
<div class="sports-event-card__stat">
|
||||
<div class="sports-event-card__stat-label">每人限报</div>
|
||||
<div class="sports-event-card__stat-value">{{row.restrictRegNumber != null ? row.restrictRegNumber + '项' : '暂无限制'}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sports-event-card__config" v-if="row.restrictBoyNum != null || row.restrictGirlNum != null || row.coachNum != null || row.leanderNum != null || row.substituteNum != null || row.isLeader || row.isManGirlNum">
|
||||
<span class="sports-event-card__config-tag" v-if="row.restrictBoyNum != null">男子 {{row.restrictBoyNum}}人</span>
|
||||
<span class="sports-event-card__config-tag" v-if="row.restrictGirlNum != null">女子 {{row.restrictGirlNum}}人</span>
|
||||
<span class="sports-event-card__config-tag" v-if="row.coachNum != null">教练 {{row.coachNum}}人</span>
|
||||
<span class="sports-event-card__config-tag" v-if="row.leanderNum != null">领队 {{row.leanderNum}}人</span>
|
||||
<span class="sports-event-card__config-tag" v-if="row.substituteNum != null">替补 {{row.substituteNum}}人</span>
|
||||
<span class="sports-event-card__config-tag" v-if="row.isLeader">仅报领队</span>
|
||||
<span class="sports-event-card__config-tag" v-if="row.isManGirlNum">男女不限</span>
|
||||
</div>
|
||||
<div class="sports-event-card__extra">
|
||||
<div class="sports-event-card__extra-row" v-if="row.startAgeDate || row.endAgeDate"><van-icon name="calendar-o"></van-icon><span class="sports-event-card__extra-label">出生日期</span><span class="sports-event-card__extra-value">{{row.startAgeDate || '不限'}} 至 {{row.endAgeDate || '不限'}}</span></div>
|
||||
<div class="sports-event-card__extra-row" v-if="row.activityTeamName"><van-icon name="friends-o"></van-icon><span class="sports-event-card__extra-label">当前小队</span><span class="sports-event-card__extra-value">{{row.activityTeamName}}</span></div>
|
||||
<div class="sports-event-card__extra-row" v-if="row.userApplyNames"><van-icon name="contact-o"></van-icon><span class="sports-event-card__extra-label">已报名人员</span><span class="sports-event-card__extra-value" @click="openApplyUser(row)">{{row.userApplyNames}}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-card-footer sports-event-card__footer">
|
||||
<div v-if="row.applyWay.length===1&&row.applyWay.includes(1)">
|
||||
<van-button :loading="subLoading" @click="signUpUser(row)" round
|
||||
<van-button class="sports-event-apply-button" :loading="subLoading" @click="signUpUser(row)" round
|
||||
size="small"
|
||||
type="primary" v-if="activityData.applyWay.includes(1)&&row.userApply===0">
|
||||
报 名
|
||||
<i class="fa fa-sign-in"></i>
|
||||
我要报名
|
||||
</van-button>
|
||||
<van-button :loading="subLoading" @click="cancelApply(row)" round
|
||||
<van-button class="sports-event-cancel-button" :loading="subLoading" @click="cancelApply(row)" round
|
||||
size="small"
|
||||
color="#dd6363"
|
||||
type="primary" v-if="activityData.applyWay.includes(1)&&row.userApply>0">
|
||||
<i class="fa fa-trash"></i>
|
||||
取消报名
|
||||
</van-button>
|
||||
</div>
|
||||
<div v-else>
|
||||
<van-button :loading="subLoading" @click="signUpUser(row)" round
|
||||
<van-button class="sports-event-apply-button" :loading="subLoading" @click="signUpUser(row)" round
|
||||
size="small"
|
||||
type="primary" v-if="activityData.applyWay.includes(1)&&row.userApply2===0">
|
||||
报 名
|
||||
<i class="fa fa-sign-in"></i>
|
||||
我要报名
|
||||
</van-button>
|
||||
<van-button :loading="subLoading" @click="cancelApply(row)" round
|
||||
<van-button class="sports-event-cancel-button" :loading="subLoading" @click="cancelApply(row)" round
|
||||
size="small"
|
||||
color="#dd6363"
|
||||
type="primary" v-if="activityData.applyWay.includes(1)&&row.userApply2>0">
|
||||
<i class="fa fa-trash"></i>
|
||||
取消报名
|
||||
</van-button>
|
||||
</div>
|
||||
</van-cell>
|
||||
<span
|
||||
v-if="row.applyWay.includes(2) && !row.applyWay.includes(1)"
|
||||
class="sports-event-union-action-hint"
|
||||
:class="{'is-authorized': canUnionApplyOnPc}">
|
||||
{{ canUnionApplyOnPc ? '分工会报名请在PC端进行' : '该活动为分工会报名,暂无权限' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sports-event-compact-list" v-else>
|
||||
<div :key="row.id" class="sports-event-compact-item" v-for="row in tableData">
|
||||
<div class="sports-event-compact-item__name">{{ row.allName }}</div>
|
||||
<div class="sports-event-compact-item__action">
|
||||
<div v-if="row.applyWay.length===1&&row.applyWay.includes(1)">
|
||||
<van-button class="sports-event-compact-button sports-event-compact-button--apply" :loading="subLoading" @click="signUpUser(row)" round
|
||||
size="small" type="default"
|
||||
v-if="activityData.applyWay.includes(1)&&row.userApply===0">
|
||||
<i class="fa fa-sign-in"></i>我要报名
|
||||
</van-button>
|
||||
<van-button class="sports-event-compact-button sports-event-compact-button--cancel" :loading="subLoading" @click="cancelApply(row)" round
|
||||
size="small" type="default"
|
||||
v-if="activityData.applyWay.includes(1)&&row.userApply>0">
|
||||
<i class="fa fa-trash"></i>取消报名
|
||||
</van-button>
|
||||
</div>
|
||||
<div v-else>
|
||||
<van-button class="sports-event-compact-button sports-event-compact-button--apply" :loading="subLoading" @click="signUpUser(row)" round
|
||||
size="small" type="default"
|
||||
v-if="activityData.applyWay.includes(1)&&row.userApply2===0">
|
||||
<i class="fa fa-sign-in"></i>我要报名
|
||||
</van-button>
|
||||
<van-button class="sports-event-compact-button sports-event-compact-button--cancel" :loading="subLoading" @click="cancelApply(row)" round
|
||||
size="small" type="default"
|
||||
v-if="activityData.applyWay.includes(1)&&row.userApply2>0">
|
||||
<i class="fa fa-trash"></i>取消报名
|
||||
</van-button>
|
||||
</div>
|
||||
<span
|
||||
v-if="row.applyWay.includes(2) && !row.applyWay.includes(1)"
|
||||
class="sports-event-union-action-hint"
|
||||
:class="{'is-authorized': canUnionApplyOnPc}">
|
||||
{{ canUnionApplyOnPc ? '分工会报名请在PC端进行' : '该活动为分工会报名,暂无权限' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-list>
|
||||
<van-empty image="/assets/platform/plugins/vant-green/images/nodata/nodata.png" description="暂无数据"
|
||||
v-else></van-empty>
|
||||
<div class="sports-event-empty" v-else>
|
||||
<img src="/assets/mobile/img/activity/sports-empty.png" alt="体育活动项目空状态插画">
|
||||
<div class="sports-event-empty__title">暂无可报名项目</div>
|
||||
<div class="sports-event-empty__hint">当前活动暂未发布可报名项目</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-pull-refresh>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -118,18 +779,34 @@ layout("/layouts/platform_h5.html"){
|
||||
tableData: [],
|
||||
finished: false,
|
||||
loading: false,
|
||||
refreshing: false,
|
||||
pageForm: {
|
||||
activityId: GetQueryString("activityId"),
|
||||
searchKeyword: "",
|
||||
pageNumber: 1,
|
||||
pageSize: 5,
|
||||
totalCount: 0
|
||||
},
|
||||
subLoading: false,
|
||||
activityData: {}
|
||||
activityData: {},
|
||||
viewMode: "card"
|
||||
}
|
||||
},
|
||||
components: {},
|
||||
computed: {
|
||||
canUnionApplyOnPc() {
|
||||
return this.$auth.hasRoleOr([
|
||||
"SYSADMIN",
|
||||
"SCHOOL_UNION_ADMIN",
|
||||
"BRANCH_UNION_CHAIRMAN",
|
||||
"BRANCH_UNION_WENTI_SPORTS"
|
||||
]) && this.$auth.hasPermission("activity.apply")
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleViewMode() {
|
||||
this.viewMode = this.viewMode === "card" ? "list" : "card"
|
||||
},
|
||||
openApplyUser() {
|
||||
},
|
||||
cancelApply(row) {
|
||||
@@ -165,45 +842,51 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "确认要报名吗?"
|
||||
}).then(async () => {
|
||||
const teamList = await this.listTeamList(row)
|
||||
}).then(() => {
|
||||
return this.listTeamList(row).then(teamList => {
|
||||
if (teamList.length > 0) {
|
||||
row.teamId = teamList[0].id
|
||||
row.teamId = teamList[0].id;
|
||||
}
|
||||
this.$axios.post("/platform/activity/apply/h5/signUpUser", {
|
||||
activityId: row.activityId,
|
||||
teamId: row.teamId,
|
||||
eventId: row.eventId,
|
||||
schoolEventId: row.id
|
||||
activityId: row.activityId,
|
||||
teamId: row.teamId,
|
||||
eventId: row.eventId,
|
||||
schoolEventId: row.id
|
||||
}).then(resp => {
|
||||
if (resp.code === 0) {
|
||||
this.doSearch()
|
||||
this.$dialog.alert({
|
||||
title: '温馨提示',
|
||||
message: resp.msg,
|
||||
}).then(() => {
|
||||
// on close
|
||||
});
|
||||
}
|
||||
})
|
||||
if (resp.code === 0) {
|
||||
this.doSearch();
|
||||
this.$dialog.alert({
|
||||
title: '温馨提示',
|
||||
message: resp.msg
|
||||
}).then(() => {
|
||||
// on close
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
})
|
||||
},
|
||||
async listTeamList(row) {
|
||||
const resp = await this.$axios.post("/platform/activity/apply/h5/listTeamList", {
|
||||
activityId: row.activityId,
|
||||
eventId: row.eventId,
|
||||
})
|
||||
listTeamList(row) {
|
||||
return this.$axios.post("/platform/activity/apply/h5/listTeamList", {
|
||||
activityId: row.activityId,
|
||||
eventId: row.eventId
|
||||
}).then(resp => {
|
||||
if (resp.code === 0) {
|
||||
return resp.data
|
||||
return resp.data;
|
||||
}
|
||||
});
|
||||
},
|
||||
doSearch() {
|
||||
this.tableKey = new Date().getTime()
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.finished = false
|
||||
this.tableData = []
|
||||
this.pageData()
|
||||
},
|
||||
onRefresh() {
|
||||
this.doSearch()
|
||||
},
|
||||
pageData() {
|
||||
this.loading = true
|
||||
this.$axios.post("/platform/activity/apply/h5/pageData", {data: JSON.stringify(this.pageForm)}).then((res) => {
|
||||
@@ -214,7 +897,9 @@ layout("/layouts/platform_h5.html"){
|
||||
this.pageForm.pageNumber++
|
||||
}
|
||||
this.pageForm.totalCount = res.data.totalCount
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
this.refreshing = false
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
@@ -1,16 +1,47 @@
|
||||
let ACTIVITY_EVENT_NOTIFICATION = {
|
||||
template: `
|
||||
<div>
|
||||
<van-popup :style="{ height: '100%',width: '100%'}" position="right" safe-area-inset-bottom v-model="viewShow">
|
||||
<van-sticky>
|
||||
<van-nav-bar @click-left="viewShow=false" left-arrow left-text="返回" title="活动通知"></van-nav-bar>
|
||||
</van-sticky>
|
||||
<div style="height: calc(100vh - 44px); overflow-y: auto">
|
||||
<div v-html="event_notification"class="paddingX10" style="padding-bottom: 44px;white-space: pre-wrap;overflow-x: hidden" v-if="event_notification"></div>
|
||||
<div v-else>暂无</div>
|
||||
<van-button @click="openReg" block style="position: fixed; bottom: 0;"
|
||||
type="primary">进入报名
|
||||
</van-button>
|
||||
template: /*language=HTML*/ `
|
||||
<div class="activity-notification-component">
|
||||
<van-popup
|
||||
v-model="viewShow"
|
||||
class="activity-notification-popup"
|
||||
:style="{ height: '100%', width: '100%' }"
|
||||
position="right"
|
||||
safe-area-inset-bottom
|
||||
>
|
||||
<div class="activity-notification-page">
|
||||
<van-sticky>
|
||||
<van-nav-bar
|
||||
title="活动通知"
|
||||
left-arrow
|
||||
left-text="返回"
|
||||
@click-left="historyBack"
|
||||
></van-nav-bar>
|
||||
</van-sticky>
|
||||
|
||||
<div class="activity-notification-scroll">
|
||||
<div class="activity-notification-hero">
|
||||
<div class="activity-notification-hero__icon">
|
||||
<van-icon name="description"></van-icon>
|
||||
</div>
|
||||
<div>
|
||||
<div class="activity-notification-hero__title">活动报名须知</div>
|
||||
<div class="activity-notification-hero__subtitle">请仔细阅读活动安排与报名要求</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<article v-if="event_notification" class="activity-notification-card">
|
||||
<div class="activity-notification-content" v-html="event_notification"></div>
|
||||
</article>
|
||||
<div v-else class="activity-notification-empty">
|
||||
<van-icon name="description"></van-icon>
|
||||
<span>暂无活动通知</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="activity-notification-footer">
|
||||
<van-button v-if="inApplyTime" type="primary" round block @click="openReg">进入报名</van-button>
|
||||
<van-button v-else class="is-disabled" disabled round block>{{ applyStatusText }}</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</div>
|
||||
@@ -21,6 +52,12 @@ let ACTIVITY_EVENT_NOTIFICATION = {
|
||||
},
|
||||
id: {
|
||||
value: { type: String, default: "暂无" }
|
||||
},
|
||||
apply_start_time: {
|
||||
value: { type: String, default: "" }
|
||||
},
|
||||
apply_end_time: {
|
||||
value: { type: String, default: "" }
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -28,9 +65,189 @@ let ACTIVITY_EVENT_NOTIFICATION = {
|
||||
viewShow: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 详情页统一控制报名入口状态,活动列表仅负责进入详情。
|
||||
inApplyTime() {
|
||||
if (!this.apply_start_time || !this.apply_end_time) return false
|
||||
const now = Date.now()
|
||||
return now >= this.$moment(this.apply_start_time).valueOf()
|
||||
&& now <= this.$moment(this.apply_end_time).valueOf()
|
||||
},
|
||||
applyStatusText() {
|
||||
if (!this.apply_start_time || !this.apply_end_time) return "当前不可报名"
|
||||
if (Date.now() < this.$moment(this.apply_start_time).valueOf()) return "报名未开始"
|
||||
return "已过报名时间"
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
openReg() {
|
||||
this.$pjaxReplace("/platform/activity/apply/h5/eventList?activityId=" + this.id)
|
||||
}
|
||||
}
|
||||
},
|
||||
style: /*language=CSS*/ `
|
||||
.activity-notification-popup {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.activity-notification-page {
|
||||
position: relative;
|
||||
min-height: 100vh;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.activity-notification-page /deep/ .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.activity-notification-page /deep/ .van-nav-bar__title {
|
||||
color: #1f2937;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.activity-notification-page /deep/ .van-nav-bar .van-icon,
|
||||
.activity-notification-page /deep/ .van-nav-bar__text {
|
||||
color: #397fbd;
|
||||
}
|
||||
|
||||
.activity-notification-scroll {
|
||||
height: calc(100vh - 46px);
|
||||
padding: 12px 12px calc(92px + env(safe-area-inset-bottom));
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.activity-notification-hero {
|
||||
display: flex;
|
||||
min-height: 82px;
|
||||
padding: 16px;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
border-radius: 12px;
|
||||
color: #fff;
|
||||
background: linear-gradient(120deg, #2d7eea 0%, #5ba6f7 100%);
|
||||
box-shadow: 0 8px 20px rgba(45, 126, 234, .18);
|
||||
}
|
||||
|
||||
.activity-notification-hero__icon {
|
||||
display: flex;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
margin-right: 12px;
|
||||
flex: 0 0 44px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 11px;
|
||||
color: #2d7eea;
|
||||
background-color: rgba(255, 255, 255, .92);
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.activity-notification-hero__title {
|
||||
font-size: 17px;
|
||||
line-height: 24px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.activity-notification-hero__subtitle {
|
||||
margin-top: 3px;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
.activity-notification-card {
|
||||
margin-top: 12px;
|
||||
padding: 18px 16px;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.activity-notification-content {
|
||||
color: #3f4c5e;
|
||||
font-size: 14px;
|
||||
line-height: 1.8;
|
||||
white-space: normal;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.activity-notification-content /deep/ h1,
|
||||
.activity-notification-content /deep/ h2,
|
||||
.activity-notification-content /deep/ h3 {
|
||||
margin: 0 0 12px !important;
|
||||
color: #1f2f43 !important;
|
||||
font-size: 20px !important;
|
||||
line-height: 1.5 !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
.activity-notification-content /deep/ p {
|
||||
margin: 0 0 8px !important;
|
||||
font-size: 14px !important;
|
||||
line-height: 1.8 !important;
|
||||
}
|
||||
|
||||
.activity-notification-content /deep/ img {
|
||||
max-width: 100% !important;
|
||||
height: auto !important;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.activity-notification-content /deep/ table {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
overflow-x: auto;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.activity-notification-empty {
|
||||
display: flex;
|
||||
min-height: 180px;
|
||||
margin-top: 12px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
row-gap: 10px;
|
||||
border-radius: 12px;
|
||||
color: #9aa7b8;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.activity-notification-empty /deep/ .van-icon {
|
||||
color: #83b5f4;
|
||||
font-size: 36px;
|
||||
}
|
||||
|
||||
.activity-notification-footer {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 5;
|
||||
padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
|
||||
border-top: 1px solid #edf1f6;
|
||||
background-color: rgba(255, 255, 255, .96);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.activity-notification-footer /deep/ .van-button {
|
||||
height: 42px;
|
||||
border: 0;
|
||||
font-size: 15px;
|
||||
background-color: #1989fa;
|
||||
box-shadow: 0 6px 16px rgba(25, 137, 250, .22);
|
||||
}
|
||||
|
||||
.activity-notification-footer /deep/ .van-button.is-disabled,
|
||||
.activity-notification-footer /deep/ .van-button--disabled {
|
||||
color: #8b98aa !important;
|
||||
background-color: #eef2f7 !important;
|
||||
opacity: 1;
|
||||
box-shadow: none;
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
@@ -2,93 +2,621 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
.info-title {
|
||||
font-weight: bold;
|
||||
background-color: white;
|
||||
padding: 13px;
|
||||
box-shadow: 0 8px 12px #ebedf0;
|
||||
text-align: center !important;
|
||||
<style>
|
||||
body {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
.info-container {
|
||||
margin-bottom: 60px;
|
||||
|
||||
.brand-activity-page {
|
||||
min-height: 100vh;
|
||||
padding-bottom: calc(24px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
.button {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
|
||||
.brand-activity-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
.info-img {
|
||||
display: block;
|
||||
|
||||
.brand-activity-page .van-nav-bar__title {
|
||||
color: #1f2937;
|
||||
font-size: 16px;
|
||||
}
|
||||
.van-count-down {
|
||||
|
||||
.brand-activity-page .van-nav-bar .van-icon,
|
||||
.brand-activity-page .van-nav-bar__text {
|
||||
color: #397fbd;
|
||||
}
|
||||
|
||||
.brand-activity-content {
|
||||
padding: 12px 12px 0;
|
||||
}
|
||||
|
||||
.brand-activity-hero {
|
||||
position: relative;
|
||||
height: 134px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
color: #fff;
|
||||
background-color: #247fe8;
|
||||
box-shadow: 0 8px 20px rgba(51, 117, 219, .18);
|
||||
}
|
||||
|
||||
.brand-activity-hero__image {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
|
||||
.brand-activity-hero__copy {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
width: 64%;
|
||||
height: 100%;
|
||||
padding-left: 16px;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
background: linear-gradient(90deg, rgba(22, 112, 232, .98) 0%, rgba(22, 112, 232, .88) 52%, rgba(22, 112, 232, 0) 100%);
|
||||
}
|
||||
|
||||
.brand-activity-hero__title {
|
||||
font-size: 25px;
|
||||
line-height: 34px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 1px;
|
||||
text-shadow: 0 2px 6px rgba(17, 86, 182, .18);
|
||||
}
|
||||
|
||||
.brand-activity-hero__subtitle {
|
||||
margin-top: 4px;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
letter-spacing: .5px;
|
||||
opacity: .95;
|
||||
}
|
||||
|
||||
.brand-activity-sticky {
|
||||
padding: 10px 0 1px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.van-sticky--fixed .brand-activity-sticky {
|
||||
padding-right: 12px;
|
||||
padding-left: 12px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.brand-activity-search {
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.brand-activity-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.brand-activity-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.brand-activity-search .van-field__control::placeholder {
|
||||
color: #a7b0bf;
|
||||
}
|
||||
|
||||
.brand-activity-filter {
|
||||
margin: 0 0 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
transition: border-radius .18s ease;
|
||||
}
|
||||
|
||||
.brand-activity-filter.is-open {
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
.brand-activity-filter .van-dropdown-menu__bar {
|
||||
height: 44px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.brand-activity-filter .van-dropdown-menu__item {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.brand-activity-filter .van-dropdown-menu__title {
|
||||
width: auto;
|
||||
max-width: calc(100% - 24px);
|
||||
padding: 0 12px 0 0;
|
||||
overflow: hidden;
|
||||
color: #66758a;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.brand-activity-filter .van-dropdown-menu__title::after {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.brand-activity-filter .van-dropdown-menu__title--active,
|
||||
.brand-activity-filter .van-dropdown-item__option--active,
|
||||
.brand-activity-filter .van-dropdown-item__option--active .van-dropdown-item__icon {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.brand-activity-filter .van-dropdown-menu__title--down::after {
|
||||
border-color: transparent transparent #1989fa #1989fa;
|
||||
}
|
||||
|
||||
.brand-activity-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
margin: 0 12px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0 0 12px 12px;
|
||||
box-shadow: 0 10px 24px rgba(31, 65, 108, .14);
|
||||
}
|
||||
|
||||
.brand-activity-filter .van-dropdown-item__option {
|
||||
min-height: 48px;
|
||||
padding: 0 16px;
|
||||
color: #46566c;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.brand-activity-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.brand-activity-card {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.brand-activity-card__cover,
|
||||
.brand-activity-card__cover-state {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
background-color: #edf4fc;
|
||||
}
|
||||
|
||||
.brand-activity-card__cover {
|
||||
display: block;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.brand-activity-card__cover-state {
|
||||
flex-direction: column;
|
||||
row-gap: 8px;
|
||||
color: #8da1ba;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.brand-activity-card__cover-state .van-icon {
|
||||
font-size: 34px;
|
||||
}
|
||||
|
||||
.brand-activity-card__cover-state.is-error {
|
||||
color: #c27b75;
|
||||
background-color: #fff3f1;
|
||||
}
|
||||
|
||||
.brand-activity-card__body {
|
||||
padding: 12px 38px 14px 14px;
|
||||
}
|
||||
|
||||
.brand-activity-card__title {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
color: #303846;
|
||||
font-size: 14px;
|
||||
line-height: 21px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.brand-activity-card__time {
|
||||
margin-top: 4px;
|
||||
overflow: hidden;
|
||||
color: #98a2b2;
|
||||
font-size: 12px;
|
||||
line-height: 17px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.brand-activity-card__meta {
|
||||
display: flex;
|
||||
margin-top: 10px;
|
||||
padding-top: 9px;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
border-top: 1px solid #edf1f6;
|
||||
}
|
||||
|
||||
.brand-activity-card__tag {
|
||||
display: inline-flex;
|
||||
padding: 3px 8px;
|
||||
align-items: center;
|
||||
border-radius: 4px;
|
||||
color: #397de0;
|
||||
background-color: #edf5ff;
|
||||
font-size: 11px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.brand-activity-card__tag-label {
|
||||
margin-right: 4px;
|
||||
color: #8aa7cf;
|
||||
}
|
||||
|
||||
.brand-activity-card__arrow {
|
||||
position: absolute;
|
||||
top: 164px;
|
||||
right: 14px;
|
||||
color: #b4bdca;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.brand-activity-empty {
|
||||
display: flex;
|
||||
min-height: 260px;
|
||||
padding: 26px 18px 32px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.brand-activity-empty img {
|
||||
display: block;
|
||||
width: 82%;
|
||||
max-width: 280px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.brand-activity-empty__title {
|
||||
margin-top: 14px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.brand-activity-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.brand-activity-page .van-list__loading {
|
||||
color: #9aa7b8;
|
||||
font-size: 13px;
|
||||
line-height: 44px;
|
||||
}
|
||||
|
||||
.brand-intro-popup,
|
||||
.brand-intro-page {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.brand-intro-page {
|
||||
position: relative;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.brand-intro-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.brand-intro-page .van-nav-bar__title {
|
||||
color: #1f2937;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.brand-intro-page .van-nav-bar .van-icon,
|
||||
.brand-intro-page .van-nav-bar__text {
|
||||
color: #397fbd;
|
||||
}
|
||||
|
||||
.brand-intro-scroll {
|
||||
height: calc(100vh - 46px);
|
||||
padding: 12px 12px calc(92px + env(safe-area-inset-bottom));
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.brand-intro-hero {
|
||||
display: flex;
|
||||
min-height: 82px;
|
||||
padding: 16px;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
border-radius: 12px;
|
||||
color: #fff;
|
||||
background: linear-gradient(120deg, #2d7eea 0%, #5ba6f7 100%);
|
||||
box-shadow: 0 8px 20px rgba(45, 126, 234, .18);
|
||||
}
|
||||
|
||||
.brand-intro-hero__icon {
|
||||
display: flex;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
margin-right: 12px;
|
||||
flex: 0 0 44px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 11px;
|
||||
color: #2d7eea;
|
||||
background-color: rgba(255, 255, 255, .92);
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.brand-intro-hero__title {
|
||||
font-size: 17px;
|
||||
line-height: 24px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.brand-intro-hero__subtitle {
|
||||
margin-top: 3px;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
.brand-intro-card {
|
||||
margin-top: 12px;
|
||||
padding: 18px 16px;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.brand-intro-content,
|
||||
.brand-intro-content div,
|
||||
.brand-intro-content p,
|
||||
.brand-intro-content span,
|
||||
.brand-intro-content li {
|
||||
color: #3f4c5e !important;
|
||||
font-size: 14px !important;
|
||||
line-height: 1.8 !important;
|
||||
white-space: normal;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.brand-intro-content h1,
|
||||
.brand-intro-content h2,
|
||||
.brand-intro-content h3 {
|
||||
margin: 16px 0 10px !important;
|
||||
color: #1f2f43 !important;
|
||||
font-size: 19px !important;
|
||||
line-height: 1.5 !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
.brand-intro-content > :first-child {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
.brand-intro-content p {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 8px !important;
|
||||
}
|
||||
|
||||
.brand-intro-content img {
|
||||
max-width: 100% !important;
|
||||
height: auto !important;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.brand-intro-content table {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
overflow-x: auto;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.brand-intro-empty {
|
||||
display: flex;
|
||||
min-height: 180px;
|
||||
margin-top: 12px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
row-gap: 10px;
|
||||
border-radius: 12px;
|
||||
color: #9aa7b8;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.brand-intro-empty .van-icon {
|
||||
color: #83b5f4;
|
||||
font-size: 36px;
|
||||
}
|
||||
|
||||
.brand-intro-footer {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 5;
|
||||
padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
|
||||
border-top: 1px solid #edf1f6;
|
||||
background-color: rgba(255, 255, 255, .96);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.brand-intro-footer .van-button {
|
||||
height: 42px;
|
||||
border: 0;
|
||||
border-radius: 21px;
|
||||
font-size: 15px;
|
||||
background-color: #1989fa;
|
||||
box-shadow: 0 6px 16px rgba(25, 137, 250, .22);
|
||||
}
|
||||
|
||||
.brand-intro-footer .van-button--disabled {
|
||||
color: #8b98aa !important;
|
||||
background-color: #eef2f7 !important;
|
||||
opacity: 1;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.brand-intro-footer .van-count-down {
|
||||
display: inline-block;
|
||||
margin-left: 4px;
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app">
|
||||
<van-nav-bar title="品牌活动" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
<div id="app" v-cloak>
|
||||
<div class="brand-activity-page">
|
||||
<van-nav-bar title="品牌活动" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
|
||||
<van-sticky offset-top="46px">
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<year-van-dropdown-item :num="5" @change="doSearch" v-model="pageForm.year"></year-van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.activityType" :options="typeOptions" :multiple="false"
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</van-sticky>
|
||||
|
||||
<table-list api="/platform/trainSignUp/apply/activityPageData"
|
||||
:page_form.sync="pageForm"
|
||||
ref="tableListRef"
|
||||
title="activityName"
|
||||
img="cover"
|
||||
@ready="onReady"
|
||||
>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="面向对象">{{row.activityGroupName}}</table-column>
|
||||
<table-column label="报名时间">
|
||||
{{$moment(row.activitySignUpStartTime).format('MM/DD HH:mm') + '~' + $moment(row.activitySignUpEndTime).format('MM/DD HH:mm')}}
|
||||
</table-column>
|
||||
<table-column label="活动时间">
|
||||
{{$moment(row.activityStartTime).format('MM/DD HH:mm') + '~' + $moment(row.activityEndTime).format('MM/DD HH:mm')}}
|
||||
</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<template v-if="$moment().isBefore($moment(row.activitySignUpEndTime))">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span>查看介绍</span>
|
||||
<div class="brand-activity-content">
|
||||
<section class="brand-activity-hero">
|
||||
<img class="brand-activity-hero__image" src="/assets/mobile/img/activity/hero/brand-hero-v2.png" alt="品牌活动插画">
|
||||
<div class="brand-activity-hero__copy">
|
||||
<div class="brand-activity-hero__title">品牌活动</div>
|
||||
<div class="brand-activity-hero__subtitle">品牌引领 · 成长同行</div>
|
||||
</div>
|
||||
<div class="action-btn" @click="onApply(row)">
|
||||
<i class="fa fa-edit"></i>
|
||||
<span>去报名</span>
|
||||
</section>
|
||||
|
||||
<van-sticky :offset-top="46">
|
||||
<div class="brand-activity-sticky">
|
||||
<van-search
|
||||
v-model="pageForm.searchKeyword"
|
||||
class="brand-activity-search"
|
||||
placeholder="搜索品牌活动"
|
||||
shape="round"
|
||||
clearable
|
||||
@search="doSearch"
|
||||
@clear="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu class="brand-activity-filter" :class="{'is-open': filterOpened}" active-color="#1989fa">
|
||||
<year-van-dropdown-item :num="5" @change="doSearch" @open="$set($data, 'filterOpened', true)" @close="$set($data, 'filterOpened', false)" v-model="pageForm.year"></year-van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.activityType" :options="typeOptions" :multiple="false" @change="doSearch" @open="$set($data, 'filterOpened', true)" @close="$set($data, 'filterOpened', false)"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</table-list>
|
||||
</van-sticky>
|
||||
|
||||
<van-action-sheet :close-on-click-overlay="false" title="详细信息" v-model="infoVisible">
|
||||
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
|
||||
<van-list v-model="loading" :finished="finished" :immediate-check="false" @load="onLoad">
|
||||
<div class="brand-activity-list">
|
||||
<div v-for="row in tableData" :key="row.id" class="brand-activity-card" @click="onView(row)">
|
||||
<img
|
||||
v-if="hasCover(row) && !imageLoadErrors[row.id]"
|
||||
class="brand-activity-card__cover"
|
||||
:src="row.cover"
|
||||
:alt="row.activityName"
|
||||
@error="handleImageError(row)"
|
||||
>
|
||||
<div v-else class="brand-activity-card__cover-state" :class="{'is-error': hasCover(row)}">
|
||||
<van-icon name="photo-o"></van-icon>
|
||||
<span>{{ hasCover(row) ? '图片加载失败' : '暂无图片' }}</span>
|
||||
</div>
|
||||
<div class="brand-activity-card__body">
|
||||
<div class="brand-activity-card__title">{{ row.activityName }}</div>
|
||||
<div class="brand-activity-card__time" v-if="row.activitySignUpStartTime && row.activitySignUpEndTime">
|
||||
报名时间:{{ $moment(row.activitySignUpStartTime).format('MM/DD HH:mm') }}~{{ $moment(row.activitySignUpEndTime).format('MM/DD HH:mm') }}
|
||||
</div>
|
||||
<div class="brand-activity-card__time" v-if="row.activityStartTime && row.activityEndTime">
|
||||
活动时间:{{ $moment(row.activityStartTime).format('MM/DD HH:mm') }}~{{ $moment(row.activityEndTime).format('MM/DD HH:mm') }}
|
||||
</div>
|
||||
<div class="brand-activity-card__meta" v-if="row.activityGroupName || row.trainType">
|
||||
<span class="brand-activity-card__tag" v-if="row.activityGroupName">
|
||||
<span class="brand-activity-card__tag-label">面向对象</span>{{ row.activityGroupName }}
|
||||
</span>
|
||||
<span class="brand-activity-card__tag" v-if="row.trainType">
|
||||
<span class="brand-activity-card__tag-label">活动类型</span>{{ row.trainType }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<van-icon class="brand-activity-card__arrow" name="arrow"></van-icon>
|
||||
</div>
|
||||
</div>
|
||||
</van-list>
|
||||
<div v-if="!loading && tableData.length === 0" class="brand-activity-empty">
|
||||
<img src="/assets/mobile/img/activity/culture-empty.png" alt="品牌活动空状态插画">
|
||||
<div class="brand-activity-empty__title">暂无品牌活动</div>
|
||||
<div class="brand-activity-empty__hint">当前筛选条件下暂时没有可展示的活动</div>
|
||||
</div>
|
||||
</van-pull-refresh>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-container">
|
||||
<div>
|
||||
<van-image class="info-img" height="186" width="100%" :src="infoRow.cover"></van-image>
|
||||
<div class="info-title">{{infoRow.activityName}}</div>
|
||||
<pdf-preview :content="infoRow.introduce"></pdf-preview>
|
||||
<van-popup class="brand-intro-popup" :style="{height: '100%', width: '100%'}" position="right" safe-area-inset-bottom v-model="infoVisible">
|
||||
<div class="brand-intro-page">
|
||||
<van-sticky>
|
||||
<van-nav-bar title="活动介绍" left-text="返回" left-arrow @click-left="historyBack"></van-nav-bar>
|
||||
</van-sticky>
|
||||
<div class="brand-intro-scroll">
|
||||
<div class="brand-intro-hero">
|
||||
<div class="brand-intro-hero__icon">
|
||||
<van-icon name="description"></van-icon>
|
||||
</div>
|
||||
<div>
|
||||
<div class="brand-intro-hero__title">活动报名须知</div>
|
||||
<div class="brand-intro-hero__subtitle">请仔细阅读活动安排与报名要求</div>
|
||||
</div>
|
||||
</div>
|
||||
<article v-if="infoRow.introduce" class="brand-intro-card">
|
||||
<div class="brand-intro-content" v-html="infoRow.introduce"></div>
|
||||
</article>
|
||||
<div v-else class="brand-intro-empty">
|
||||
<van-icon name="description"></van-icon>
|
||||
<span>暂无活动介绍</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="button">
|
||||
<van-button @click="onApply(infoRow)" type="primary" block>
|
||||
<span v-if="time >= 0">
|
||||
去报名
|
||||
</span>
|
||||
<template v-else>
|
||||
距离开始
|
||||
<van-count-down :time="Math.abs(time)" class="count-down" format="DD 天 HH 时 mm 分 ss 秒" @finish="time = 0"></van-count-down>
|
||||
</template>
|
||||
<div class="brand-intro-footer">
|
||||
<van-button v-if="canApply(infoRow)" @click="onApply(infoRow)" type="primary" block round>进入报名</van-button>
|
||||
<van-button v-else-if="time < 0" @click="onApply(infoRow)" type="primary" block round>
|
||||
距离开始
|
||||
<van-count-down :time="Math.abs(time)" format="DD 天 HH 时 mm 分 ss 秒" @finish="$set($data, 'time', 0)"></van-count-down>
|
||||
</van-button>
|
||||
<van-button v-else disabled block round>{{ registrationStatusText(infoRow) }}</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</van-action-sheet>
|
||||
|
||||
</van-popup>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
@@ -96,11 +624,16 @@ layout("/layouts/platform_h5.html"){
|
||||
el: "#app",
|
||||
store,
|
||||
components: {
|
||||
"pdf-preview": httpVueLoader("/components/plugins/sysFilePreview/PdfIndex.vue?v=" + new Date().getTime())
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
time: 0,
|
||||
tableData: [],
|
||||
loading: false,
|
||||
finished: false,
|
||||
refreshing: false,
|
||||
imageLoadErrors: {},
|
||||
filterOpened: false,
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
@@ -121,12 +654,41 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
hasCover(row) {
|
||||
return !!(row && row.cover && String(row.cover).trim())
|
||||
},
|
||||
handleImageError(row) {
|
||||
this.$set(this.imageLoadErrors, row.id, true)
|
||||
},
|
||||
isRegistrationClosed(row) {
|
||||
return !!(row && row.activitySignUpEndTime && !this.$moment().isBefore(this.$moment(row.activitySignUpEndTime)))
|
||||
},
|
||||
canApply(row) {
|
||||
if(!row || !row.activitySignUpStartTime || !row.activitySignUpEndTime) {
|
||||
return false
|
||||
}
|
||||
const now = Date.now()
|
||||
return now >= this.$moment(row.activitySignUpStartTime).valueOf()
|
||||
&& now <= this.$moment(row.activitySignUpEndTime).valueOf()
|
||||
},
|
||||
registrationStatusText(row) {
|
||||
if(!row || !row.activitySignUpStartTime || !row.activitySignUpEndTime) {
|
||||
return '当前不可报名'
|
||||
}
|
||||
if(Date.now() < this.$moment(row.activitySignUpStartTime).valueOf()) {
|
||||
return '报名未开始'
|
||||
}
|
||||
return '已过报名时间'
|
||||
},
|
||||
onView(row) {
|
||||
this.infoRow = row
|
||||
this.time = this.$moment().diff(this.$moment(row.activitySignUpStartTime), 'milliseconds')
|
||||
this.infoVisible = true
|
||||
},
|
||||
onApply(row) {
|
||||
if(this.isRegistrationClosed(row)) {
|
||||
return
|
||||
}
|
||||
if(this.$moment().isBefore(this.$moment(row.activitySignUpStartTime))) {
|
||||
this.onView(row)
|
||||
return
|
||||
@@ -151,22 +713,47 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
})
|
||||
},
|
||||
onReady() {
|
||||
this.doSearch()
|
||||
if(this.id) {
|
||||
this.fetchOne()
|
||||
onLoad() {
|
||||
if(!this.finished) {
|
||||
this.loadActivities(false)
|
||||
}
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
onRefresh() {
|
||||
this.loadActivities(true)
|
||||
},
|
||||
loadActivities(reset) {
|
||||
if(reset) {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
this.tableData = []
|
||||
this.finished = false
|
||||
this.imageLoadErrors = {}
|
||||
}
|
||||
this.loading = true
|
||||
this.$axios.post('/platform/trainSignUp/apply/activityPageData', this.pageForm).then((res) => {
|
||||
if(res.code === 0) {
|
||||
const list = res.data && res.data.list ? res.data.list : []
|
||||
this.tableData = this.pageForm.pageNumber === 1 ? list : this.tableData.concat(list)
|
||||
this.pageForm.totalCount = res.data && res.data.totalCount ? res.data.totalCount : 0
|
||||
this.finished = this.tableData.length >= this.pageForm.totalCount
|
||||
if(!this.finished) {
|
||||
this.pageForm.pageNumber++
|
||||
}
|
||||
}
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
this.refreshing = false
|
||||
})
|
||||
},
|
||||
doSearch() {
|
||||
this.loadActivities(true)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
created() {
|
||||
this.loadActivities(true)
|
||||
if(this.id) {
|
||||
this.fetchOne()
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
const times = {
|
||||
template:
|
||||
/*language=HTML*/
|
||||
`
|
||||
template: /*language=HTML*/ `
|
||||
<div>
|
||||
<van-action-sheet v-model="visible" title="时间段" cancel-text="取消">
|
||||
<div id="mapContainer" v-if="row?.isMobileSign === true && row?.signType === 3" style="width: 100%; height: 250px"></div>
|
||||
<button v-for="(item,index) in row?.courseTimes" type="button" class="van-action-sheet__item">
|
||||
<van-action-sheet class="brand-course-times-sheet" :style="{height: '78%'}" :close-on-click-overlay="true" v-model="visible" title="时间段" cancel-text="取消">
|
||||
<div class="brand-course-times-list">
|
||||
<div id="mapContainer" v-if="row?.isMobileSign === true && row?.signType === 3" class="brand-course-times-map"></div>
|
||||
<button v-for="(item,index) in row?.courseTimes" :key="index" type="button" class="van-action-sheet__item brand-course-time-item">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center">
|
||||
<div>
|
||||
<div class="van-action-sheet__name">
|
||||
@@ -22,12 +21,13 @@ const times = {
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</van-action-sheet>
|
||||
|
||||
<van-popup round :safe-area-inset-bottom="true"
|
||||
:close-on-click-overlay="false"
|
||||
v-model="signVisible"
|
||||
:style="{ width: '80%', height: '66%' }"
|
||||
<van-popup round :safe-area-inset-bottom="true"
|
||||
:close-on-click-overlay="false"
|
||||
v-model="signVisible"
|
||||
:style="{ width: '80%', height: '66%' }"
|
||||
get-container="#app"
|
||||
@close="onSignClose"
|
||||
closeable
|
||||
@@ -75,43 +75,43 @@ const times = {
|
||||
}
|
||||
})
|
||||
},
|
||||
async onSign(courseTime) {
|
||||
this.selectCourseTime = courseTime
|
||||
if (this.row.signType === 1) {
|
||||
this.signVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.scanCodeRef.init()
|
||||
})
|
||||
}
|
||||
if (this.row.signType === 2) {
|
||||
this.makeCode()
|
||||
}
|
||||
if (this.row.signType === 3) {
|
||||
this.getLocation((coords) => {
|
||||
if (coords) {
|
||||
this.$axios.post('/platform/trainSignUp/mine/positionSign', {
|
||||
timeId: courseTime.id,
|
||||
courseId: this.row.id,
|
||||
lat: coords.lat,
|
||||
lng: coords.lng
|
||||
}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$toast('签到成功')
|
||||
this.visible = false
|
||||
} else {
|
||||
this.$toast(res.msg)
|
||||
this.markerLayer.remove(["current"])
|
||||
this.getLocation((coords) => {
|
||||
if (coords) {
|
||||
const center = new TMap.LatLng(coords.lat, coords.lng)
|
||||
this.createMarker(center, 'current', 'current')
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
onSign(courseTime) {
|
||||
this.selectCourseTime = courseTime;
|
||||
if (this.row.signType === 1) {
|
||||
this.signVisible = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.scanCodeRef.init();
|
||||
});
|
||||
}
|
||||
if (this.row.signType === 2) {
|
||||
this.makeCode();
|
||||
}
|
||||
if (this.row.signType === 3) {
|
||||
this.getLocation(coords => {
|
||||
if (coords) {
|
||||
this.$axios.post('/platform/trainSignUp/mine/positionSign', {
|
||||
timeId: courseTime.id,
|
||||
courseId: this.row.id,
|
||||
lat: coords.lat,
|
||||
lng: coords.lng
|
||||
}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$toast('签到成功');
|
||||
this.visible = false;
|
||||
} else {
|
||||
this.$toast(res.msg);
|
||||
this.markerLayer.remove(["current"]);
|
||||
this.getLocation(coords => {
|
||||
if (coords) {
|
||||
const center = new TMap.LatLng(coords.lat, coords.lng);
|
||||
this.createMarker(center, 'current', 'current');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
getLocation(callback) {
|
||||
if (typeof callback !== 'function') {
|
||||
@@ -215,6 +215,70 @@ const times = {
|
||||
},
|
||||
},
|
||||
style: /*language=CSS*/ `
|
||||
|
||||
.brand-course-times-sheet {
|
||||
overflow: hidden;
|
||||
border-radius: 16px 16px 0 0;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.brand-course-times-sheet /deep/ .van-action-sheet__header {
|
||||
height: 48px;
|
||||
color: #1f2f43;
|
||||
background-color: #fff;
|
||||
font-size: 16px;
|
||||
line-height: 48px;
|
||||
}
|
||||
|
||||
.brand-course-times-sheet /deep/ .van-action-sheet__close {
|
||||
top: 13px;
|
||||
color: #b5bdc9;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.brand-course-times-list {
|
||||
height: calc(100% - 98px);
|
||||
padding: 10px 12px 0;
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.brand-course-times-map {
|
||||
width: 100%;
|
||||
height: 180px;
|
||||
margin-bottom: 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.brand-course-times-sheet /deep/ .brand-course-time-item {
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
padding: 14px;
|
||||
border-radius: 10px;
|
||||
color: #263548;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 6px 18px rgba(55, 85, 126, .07);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.brand-course-times-sheet /deep/ .van-action-sheet__name {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
line-height: 21px;
|
||||
}
|
||||
|
||||
.brand-course-times-sheet /deep/ .van-action-sheet__subname {
|
||||
margin-top: 5px;
|
||||
color: #98a2b2;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.brand-course-times-sheet /deep/ .van-action-sheet__cancel {
|
||||
height: 50px;
|
||||
color: #66758a;
|
||||
background-color: #fff;
|
||||
font-size: 14px;
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
const applyForm = {
|
||||
template:
|
||||
/*language=HTML*/
|
||||
`
|
||||
template: /*language=HTML*/ `
|
||||
<div>
|
||||
<van-action-sheet :close-on-click-overlay="false" title="报名信息" v-model="visible">
|
||||
<van-action-sheet class="brand-course-form-sheet" :style="{height: '78%'}" :close-on-click-overlay="true" title="报名信息" v-model="visible">
|
||||
<van-form ref="formRef" class="form-container">
|
||||
<van-cell-group title="活动信息" class="form-section">
|
||||
<van-field label="活动名称" readonly v-model="row.courseName"></van-field>
|
||||
@@ -21,7 +19,7 @@ const applyForm = {
|
||||
required
|
||||
:rules="[{ required: true, message: '请选择报名时段' }]"
|
||||
readonly
|
||||
@click="showCoursePicker = true"
|
||||
@click="$set($data, 'showCoursePicker', true)"
|
||||
placeholder="请选择报名时段"
|
||||
name="courseTimeName"
|
||||
v-model="formData.courseTimeName">
|
||||
@@ -31,7 +29,7 @@ const applyForm = {
|
||||
show-toolbar
|
||||
:columns="courseTimeSelectList"
|
||||
@confirm="onCourseConfirm"
|
||||
@cancel="showCoursePicker=false"
|
||||
@cancel="$set($data, 'showCoursePicker', false)"
|
||||
></van-picker>
|
||||
</van-popup>
|
||||
</template>
|
||||
@@ -39,7 +37,7 @@ const applyForm = {
|
||||
</van-cell-group>
|
||||
|
||||
<div class="button">
|
||||
<van-button @click="onSubmit" round type="info" block>提交</van-button>
|
||||
<van-button :loading="formLoading" :disabled="formLoading" @click="onSubmit" round type="info" block>提交</van-button>
|
||||
</div>
|
||||
</van-form>
|
||||
</van-action-sheet>
|
||||
@@ -51,6 +49,7 @@ const applyForm = {
|
||||
activity: {},
|
||||
dynamicColumnsData: [],
|
||||
visible: false,
|
||||
formLoading: false,
|
||||
formData: {},
|
||||
showCoursePicker: false,
|
||||
courseTimeSelectList: [],
|
||||
@@ -60,13 +59,16 @@ const applyForm = {
|
||||
"train-dynamic-form": httpVueLoader("/components/module/trainSignUp/TrainDynamicForm.vue")
|
||||
},
|
||||
methods: {
|
||||
async onOpen(row, courseType) {
|
||||
this.row = row
|
||||
this.init(row, courseType)
|
||||
if(row.courseIsLimitApply) {
|
||||
await this.getCourseTimeSelectList(row)
|
||||
}
|
||||
this.visible = true
|
||||
onOpen(row, courseType) {
|
||||
this.row = row;
|
||||
this.init(row, courseType);
|
||||
if (row.courseIsLimitApply) {
|
||||
return this.getCourseTimeSelectList(row).then(() => {
|
||||
this.visible = true;
|
||||
});
|
||||
} else {
|
||||
this.visible = true;
|
||||
}
|
||||
},
|
||||
init(row, courseType) {
|
||||
this.$set(this.formData, 'username', this.$store.state.user.username)
|
||||
@@ -88,72 +90,157 @@ const applyForm = {
|
||||
this.$set(this.formData, "courseTimeName", val.text.substring(0, 12))
|
||||
this.showCoursePicker = false
|
||||
},
|
||||
async getCourseTimeSelectList(o) {
|
||||
const resp = await this.$axios.post('/platform/trainSignUp/apply/getCourseTimeSelectList',{courseId: o.id})
|
||||
getCourseTimeSelectList(o) {
|
||||
return this.$axios.post('/platform/trainSignUp/apply/getCourseTimeSelectList', {
|
||||
courseId: o.id
|
||||
}).then(resp => {
|
||||
if (resp.code === 0) {
|
||||
this.courseTimeSelectList = resp.data
|
||||
this.courseTimeSelectList = resp.data;
|
||||
} else {
|
||||
this.$toast.fail("获取时段信息失败,请联系管理员")
|
||||
this.$toast.fail("获取时段信息失败,请联系管理员");
|
||||
}
|
||||
});
|
||||
},
|
||||
async validateSignUp() {
|
||||
// 验证自定义表单
|
||||
await this.$refs.dynamicForm.$refs.form.validate()
|
||||
validateSignUp() {
|
||||
return this.$refs.dynamicForm.$refs.form.validate().then(() => {
|
||||
// 获取家属人数
|
||||
let familyCount = this.dynamicColumnsData.filter(o => o.columnCode === 'xdqsrs').reduce((sum, item) => {
|
||||
return sum + (Number(item.columnValue) || 0)
|
||||
}, 0)
|
||||
|
||||
const res = await this.$axios.post("/platform/trainSignUp/apply/validateSignUp", {
|
||||
courseId: this.formData.courseId,
|
||||
currentFamilyNumber: familyCount
|
||||
})
|
||||
return res.code === 0
|
||||
return sum + (Number(item.columnValue) || 0);
|
||||
}, 0);
|
||||
return this.$axios.post("/platform/trainSignUp/apply/validateSignUp", {
|
||||
courseId: this.formData.courseId,
|
||||
currentFamilyNumber: familyCount
|
||||
}).then(res => {
|
||||
return res.code === 0;
|
||||
});
|
||||
});
|
||||
},
|
||||
async validateCourseTime() {
|
||||
const res = await this.$axios.post('/platform/trainSignUp/apply/validateSourceSignUp', {
|
||||
activityCourseId: this.formData.activityCourseId,
|
||||
courseId: this.row.id
|
||||
})
|
||||
return res.code === 0
|
||||
validateCourseTime() {
|
||||
return this.$axios.post('/platform/trainSignUp/apply/validateSourceSignUp', {
|
||||
activityCourseId: this.formData.activityCourseId,
|
||||
courseId: this.row.id
|
||||
}).then(res => {
|
||||
return res.code === 0;
|
||||
});
|
||||
},
|
||||
async onSubmit() {
|
||||
if(!await this.validateSignUp()) return
|
||||
onSubmit() {
|
||||
// 保留原有报名资格、动态表单和限额时段校验;确认后才发送报名数据。
|
||||
if (this.formLoading) return
|
||||
|
||||
this.$refs.formRef.validate().then(() => {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(async () => {
|
||||
if (this.row.courseIsLimitApply) {
|
||||
if(!await this.validateCourseTime()) return
|
||||
}
|
||||
|
||||
const mobileColumnsValue = this.dynamicColumnsData.map((v) => {
|
||||
return {
|
||||
columnName: v.columnName,
|
||||
columnValue: v.columnValue,
|
||||
columnCode: v.columnCode,
|
||||
columnFormType: v.columnFormType
|
||||
}
|
||||
})
|
||||
this.formData.mobileColumnsValue = JSON.stringify(mobileColumnsValue)
|
||||
this.$axios.post("/platform/trainSignUp/apply/doSignUp", this.formData).then(res => {
|
||||
return this.validateSignUp().then((valid) => {
|
||||
if (!valid) return
|
||||
return this.$refs.formRef.validate().then(() => {
|
||||
return this.$dialog.confirm({title: "提示", message: "您确定要提交吗?"})
|
||||
}).then(() => {
|
||||
return this.row.courseIsLimitApply ? this.validateCourseTime() : true
|
||||
}).then((validTime) => {
|
||||
if (!validTime) return
|
||||
this.$set(this, "formLoading", true)
|
||||
const formData = clone(this.formData)
|
||||
formData.mobileColumnsValue = JSON.stringify(this.dynamicColumnsData.map((item) => ({
|
||||
columnName: item.columnName, columnValue: item.columnValue,
|
||||
columnCode: item.columnCode, columnFormType: item.columnFormType
|
||||
})))
|
||||
return this.$axios.post("/platform/trainSignUp/apply/doSignUp", formData).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$toast(res.msg)
|
||||
this.visible = false
|
||||
this.$emit('refresh')
|
||||
this.$set(this, "visible", false)
|
||||
this.$emit("refresh")
|
||||
}
|
||||
}).finally(() => {
|
||||
this.$set(this, "formLoading", false)
|
||||
})
|
||||
}).catch(() => {
|
||||
// 取消确认或校验未通过时保留表单,网络错误由公共请求拦截器提示。
|
||||
})
|
||||
})
|
||||
},
|
||||
},
|
||||
style: /*language=CSS*/ `
|
||||
/deep/ .button {
|
||||
position: fixed;
|
||||
.brand-course-form-sheet {
|
||||
overflow: hidden;
|
||||
border-radius: 16px 16px 0 0;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.brand-course-form-sheet /deep/ .van-action-sheet__header {
|
||||
height: 48px;
|
||||
color: #1f2f43;
|
||||
background-color: #fff;
|
||||
font-size: 16px;
|
||||
line-height: 48px;
|
||||
}
|
||||
|
||||
.brand-course-form-sheet /deep/ .van-action-sheet__close {
|
||||
top: 13px;
|
||||
color: #b5bdc9;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.brand-course-form-sheet /deep/ .form-container {
|
||||
height: calc(100% - 48px);
|
||||
padding: 10px 12px 72px;
|
||||
overflow-y: auto;
|
||||
background-color: #f3f7fd;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.brand-course-form-sheet /deep/ .form-section {
|
||||
margin-bottom: 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 6px 18px rgba(55, 85, 126, .07);
|
||||
}
|
||||
|
||||
.brand-course-form-sheet /deep/ .van-cell-group__title {
|
||||
padding: 12px 14px 8px;
|
||||
color: #263548;
|
||||
background-color: #fff;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.brand-course-form-sheet /deep/ .van-cell-group__title::before {
|
||||
width: 3px;
|
||||
top: 12px;
|
||||
bottom: 8px;
|
||||
border-radius: 2px;
|
||||
background-color: #1989fa;
|
||||
}
|
||||
|
||||
.brand-course-form-sheet /deep/ .van-cell {
|
||||
padding: 11px 14px;
|
||||
color: #263548;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.brand-course-form-sheet /deep/ .van-field__label {
|
||||
color: #66758a;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.brand-course-form-sheet /deep/ .button {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
z-index: 2;
|
||||
padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
|
||||
border-top: 1px solid #edf1f6;
|
||||
background-color: rgba(255, 255, 255, .96);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.brand-course-form-sheet /deep/ .button .van-button {
|
||||
height: 42px;
|
||||
border: 0;
|
||||
border-radius: 21px;
|
||||
color: #fff;
|
||||
background-color: #1989fa;
|
||||
font-size: 15px;
|
||||
box-shadow: 0 6px 16px rgba(25, 137, 250, .22);
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,91 +2,475 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
.info-title {
|
||||
font-weight: bold;
|
||||
background-color: white;
|
||||
padding: 13px;
|
||||
box-shadow: 0 8px 12px #ebedf0;
|
||||
text-align: center !important;
|
||||
<style>
|
||||
body {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
.info-container {
|
||||
|
||||
.brand-mine-page {
|
||||
min-height: 100vh;
|
||||
padding-bottom: calc(24px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
.button {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
|
||||
.brand-mine-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
.info-img {
|
||||
display: block;
|
||||
|
||||
.brand-mine-page .van-nav-bar__title {
|
||||
color: #1f2937;
|
||||
font-size: 16px;
|
||||
}
|
||||
.van-count-down {
|
||||
|
||||
.brand-mine-page .van-nav-bar .van-icon,
|
||||
.brand-mine-page .van-nav-bar__text {
|
||||
color: #397fbd;
|
||||
}
|
||||
|
||||
.brand-mine-content {
|
||||
padding: 12px 12px 0;
|
||||
}
|
||||
|
||||
.brand-mine-hero {
|
||||
position: relative;
|
||||
height: 134px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
color: #fff;
|
||||
background: linear-gradient(115deg, #347eea 0%, #5b9cf4 58%, #cfe3ff 100%);
|
||||
box-shadow: 0 8px 20px rgba(51, 117, 219, .18);
|
||||
}
|
||||
|
||||
.brand-mine-hero__image {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 67%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: right center;
|
||||
-webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 26%);
|
||||
mask-image: linear-gradient(90deg, transparent 0%, #000 26%);
|
||||
}
|
||||
|
||||
.brand-mine-hero__copy {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
padding-left: 16px;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.brand-mine-hero__title {
|
||||
font-size: 25px;
|
||||
line-height: 34px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.brand-mine-hero__subtitle {
|
||||
margin-top: 4px;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
letter-spacing: .5px;
|
||||
opacity: .95;
|
||||
}
|
||||
|
||||
.brand-mine-sticky {
|
||||
padding: 10px 0 1px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.van-sticky--fixed .brand-mine-sticky {
|
||||
padding-right: 12px;
|
||||
padding-left: 12px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.brand-mine-search {
|
||||
margin-bottom: 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.brand-mine-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.brand-mine-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.brand-mine-filter {
|
||||
margin-bottom: 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
transition: border-radius .18s ease;
|
||||
}
|
||||
|
||||
.brand-mine-filter.is-open {
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
.brand-mine-filter .van-dropdown-menu__bar {
|
||||
height: 44px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.brand-mine-filter .van-dropdown-menu__title {
|
||||
width: auto;
|
||||
max-width: calc(100% - 24px);
|
||||
padding: 0 12px 0 0;
|
||||
color: #66758a;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.brand-mine-filter .van-dropdown-menu__title::after {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.brand-mine-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
margin: 0 12px;
|
||||
overflow: hidden;
|
||||
border-radius: 0 0 12px 12px;
|
||||
box-shadow: 0 10px 24px rgba(31, 65, 108, .14);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.brand-mine-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.brand-mine-card {
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.brand-mine-card__cover,
|
||||
.brand-mine-card__cover-state {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #edf4fc;
|
||||
}
|
||||
|
||||
.brand-mine-card__cover {
|
||||
display: block;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.brand-mine-card__cover-state {
|
||||
flex-direction: column;
|
||||
row-gap: 8px;
|
||||
color: #8da1ba;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.brand-mine-card__cover-state .van-icon {
|
||||
font-size: 34px;
|
||||
}
|
||||
|
||||
.brand-mine-card__cover-state.is-error {
|
||||
color: #c27b75;
|
||||
background-color: #fff3f1;
|
||||
}
|
||||
|
||||
.brand-mine-card__body {
|
||||
padding: 12px 14px 14px;
|
||||
}
|
||||
|
||||
.brand-mine-card__title {
|
||||
overflow: hidden;
|
||||
color: #303846;
|
||||
font-size: 14px;
|
||||
line-height: 21px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.brand-mine-card__time {
|
||||
margin-top: 4px;
|
||||
overflow: hidden;
|
||||
color: #98a2b2;
|
||||
font-size: 12px;
|
||||
line-height: 17px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.brand-mine-card__meta {
|
||||
display: flex;
|
||||
margin-top: 10px;
|
||||
padding-top: 9px;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
border-top: 1px solid #edf1f6;
|
||||
}
|
||||
|
||||
.brand-mine-card__tag {
|
||||
display: inline-flex;
|
||||
padding: 3px 8px;
|
||||
border-radius: 4px;
|
||||
color: #397de0;
|
||||
background-color: #edf5ff;
|
||||
font-size: 11px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.brand-mine-card__tag-label {
|
||||
margin-right: 4px;
|
||||
color: #8aa7cf;
|
||||
}
|
||||
|
||||
.brand-mine-card__actions {
|
||||
display: flex;
|
||||
padding: 12px 14px;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
border-top: 1px solid #edf1f6;
|
||||
background-color: #f8fbff;
|
||||
}
|
||||
|
||||
.brand-mine-card__action {
|
||||
display: inline-flex;
|
||||
min-width: 82px;
|
||||
height: 32px;
|
||||
padding: 0 14px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 0;
|
||||
border-radius: 16px;
|
||||
color: #397de0;
|
||||
background-color: #edf5ff;
|
||||
font-size: 13px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.brand-mine-card__action .van-icon {
|
||||
margin-right: 6px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.brand-mine-card__action.is-primary {
|
||||
color: #fff;
|
||||
background-color: #1989fa;
|
||||
box-shadow: 0 5px 12px rgba(25, 137, 250, .18);
|
||||
}
|
||||
|
||||
.brand-mine-empty {
|
||||
display: flex;
|
||||
min-height: 260px;
|
||||
padding: 26px 18px 32px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.brand-mine-empty img {
|
||||
width: 82%;
|
||||
max-width: 280px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.brand-mine-empty__title {
|
||||
margin-top: 14px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.brand-mine-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.brand-mine-intro-page {
|
||||
min-height: 100vh;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.brand-mine-intro-scroll {
|
||||
height: calc(100vh - 46px);
|
||||
padding: 12px;
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.brand-mine-intro-hero {
|
||||
display: flex;
|
||||
min-height: 82px;
|
||||
padding: 16px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
color: #fff;
|
||||
background: linear-gradient(120deg, #2d7eea 0%, #5ba6f7 100%);
|
||||
box-shadow: 0 8px 20px rgba(45, 126, 234, .18);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.brand-mine-intro-hero__icon {
|
||||
display: flex;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
margin-right: 12px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 0 0 44px;
|
||||
border-radius: 11px;
|
||||
color: #2d7eea;
|
||||
background-color: rgba(255, 255, 255, .92);
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.brand-mine-intro-hero__title {
|
||||
font-size: 17px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.brand-mine-intro-hero__subtitle {
|
||||
margin-top: 3px;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
.brand-mine-intro-card {
|
||||
margin-top: 12px;
|
||||
padding: 18px 16px;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
color: #3f4c5e;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
font-size: 14px;
|
||||
line-height: 1.8;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.brand-mine-intro-card img {
|
||||
max-width: 100% !important;
|
||||
height: auto !important;
|
||||
border-radius: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app">
|
||||
<van-nav-bar title="品牌活动-我的报名" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
<div id="app" v-cloak>
|
||||
<div class="brand-mine-page">
|
||||
<van-nav-bar title="品牌活动-我的报名" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
|
||||
<van-sticky offset-top="46px">
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<year-van-dropdown-item :num="5" @change="doSearch" v-model="pageForm.year"></year-van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.activityType" :options="typeOptions" :multiple="false"
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</van-sticky>
|
||||
<div class="brand-mine-content">
|
||||
<section class="brand-mine-hero">
|
||||
<img class="brand-mine-hero__image" src="/assets/mobile/img/home/v4/feature-activity.png" alt="品牌活动插画">
|
||||
<div class="brand-mine-hero__copy">
|
||||
<div class="brand-mine-hero__title">我的报名</div>
|
||||
<div class="brand-mine-hero__subtitle">品牌活动 · 报名记录</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<table-list api="/platform/trainSignUp/apply/activityPageData"
|
||||
:page_form.sync="pageForm"
|
||||
ref="tableListRef"
|
||||
title="activityName"
|
||||
img="cover"
|
||||
@ready="onReady"
|
||||
>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="面向对象">{{row.activityGroupName}}</table-column>
|
||||
<table-column label="报名时间">
|
||||
{{$moment(row.activitySignUpStartTime).format('MM/DD HH:mm') + '~' + $moment(row.activitySignUpEndTime).format('MM/DD HH:mm')}}
|
||||
</table-column>
|
||||
<table-column label="活动时间">
|
||||
{{$moment(row.activityStartTime).format('MM/DD HH:mm') + '~' + $moment(row.activityEndTime).format('MM/DD HH:mm')}}
|
||||
</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span>查看介绍</span>
|
||||
</div>
|
||||
<div class="action-btn" @click="onApply(row)">
|
||||
<i class="fa fa-edit"></i>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
<van-sticky :offset-top="46">
|
||||
<div class="brand-mine-sticky">
|
||||
<van-search v-model="pageForm.searchKeyword" class="brand-mine-search" placeholder="搜索已报名活动" shape="round" clearable @search="doSearch" @clear="doSearch"></van-search>
|
||||
<van-dropdown-menu class="brand-mine-filter" :class="{'is-open': filterOpened}" active-color="#1989fa">
|
||||
<year-van-dropdown-item :num="5" @change="doSearch" @open="$set($data, 'filterOpened', true)" @close="$set($data, 'filterOpened', false)" v-model="pageForm.year"></year-van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.activityType" :options="typeOptions" :multiple="false" @change="doSearch" @open="$set($data, 'filterOpened', true)" @close="$set($data, 'filterOpened', false)"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<van-action-sheet :close-on-click-overlay="false" title="活动详细信息" v-model="infoVisible" cancel-text="取消">
|
||||
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
|
||||
<van-list v-model="loading" :finished="finished" :immediate-check="false" @load="onLoad">
|
||||
<div class="brand-mine-list">
|
||||
<div v-for="row in tableData" :key="row.id" class="brand-mine-card">
|
||||
<img v-if="hasCover(row) && !imageLoadErrors[row.id]" class="brand-mine-card__cover" :src="row.cover" :alt="row.activityName" @error="handleImageError(row)">
|
||||
<div v-else class="brand-mine-card__cover-state" :class="{'is-error': hasCover(row)}">
|
||||
<van-icon name="photo-o"></van-icon>
|
||||
<span>{{ hasCover(row) ? '图片加载失败' : '暂无图片' }}</span>
|
||||
</div>
|
||||
<div class="brand-mine-card__body">
|
||||
<div class="brand-mine-card__title">{{ row.activityName }}</div>
|
||||
<div class="brand-mine-card__time" v-if="row.activitySignUpStartTime && row.activitySignUpEndTime">
|
||||
报名时间:{{ $moment(row.activitySignUpStartTime).format('MM/DD HH:mm') }}~{{ $moment(row.activitySignUpEndTime).format('MM/DD HH:mm') }}
|
||||
</div>
|
||||
<div class="brand-mine-card__time" v-if="row.activityStartTime && row.activityEndTime">
|
||||
活动时间:{{ $moment(row.activityStartTime).format('MM/DD HH:mm') }}~{{ $moment(row.activityEndTime).format('MM/DD HH:mm') }}
|
||||
</div>
|
||||
<div class="brand-mine-card__meta" v-if="row.activityGroupName || row.trainType">
|
||||
<span class="brand-mine-card__tag" v-if="row.activityGroupName"><span class="brand-mine-card__tag-label">面向对象</span>{{ row.activityGroupName }}</span>
|
||||
<span class="brand-mine-card__tag" v-if="row.trainType"><span class="brand-mine-card__tag-label">活动类型</span>{{ row.trainType }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="brand-mine-card__actions">
|
||||
<button type="button" class="brand-mine-card__action" @click="onView(row)"><van-icon name="eye-o"></van-icon>查看介绍</button>
|
||||
<button type="button" class="brand-mine-card__action is-primary" @click="onApply(row)"><van-icon name="edit"></van-icon>查看报名</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-list>
|
||||
<div v-if="!loading && tableData.length === 0" class="brand-mine-empty">
|
||||
<img src="/assets/mobile/img/activity/culture-empty.png" alt="品牌活动报名空状态插画">
|
||||
<div class="brand-mine-empty__title">暂无报名记录</div>
|
||||
<div class="brand-mine-empty__hint">当前筛选条件下暂时没有已报名活动</div>
|
||||
</div>
|
||||
</van-pull-refresh>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-container">
|
||||
<div>
|
||||
<van-image class="info-img" height="186" width="100%" :src="infoRow.cover"></van-image>
|
||||
<div class="info-title">{{infoRow.activityName}}</div>
|
||||
<pdf-preview :content="infoRow.introduce"></pdf-preview>
|
||||
<van-popup :style="{height: '100%', width: '100%'}" position="right" v-model="infoVisible">
|
||||
<div class="brand-mine-intro-page">
|
||||
<van-nav-bar title="活动介绍" left-text="返回" left-arrow @click-left="historyBack"></van-nav-bar>
|
||||
<div class="brand-mine-intro-scroll">
|
||||
<div class="brand-mine-intro-hero">
|
||||
<div class="brand-mine-intro-hero__icon"><van-icon name="description"></van-icon></div>
|
||||
<div>
|
||||
<div class="brand-mine-intro-hero__title">活动报名须知</div>
|
||||
<div class="brand-mine-intro-hero__subtitle">请仔细阅读活动安排与报名要求</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="infoRow.introduce" class="brand-mine-intro-card" v-html="infoRow.introduce"></div>
|
||||
<div v-else class="brand-mine-intro-card">暂无活动介绍</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-action-sheet>
|
||||
|
||||
</van-popup>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
components: {
|
||||
"pdf-preview": httpVueLoader("/components/plugins/sysFilePreview/PdfIndex.vue?v=" + new Date().getTime())
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tableData: [],
|
||||
loading: false,
|
||||
finished: false,
|
||||
refreshing: false,
|
||||
imageLoadErrors: {},
|
||||
filterOpened: false,
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
@@ -106,6 +490,12 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
hasCover(row) {
|
||||
return !!(row && row.cover && String(row.cover).trim())
|
||||
},
|
||||
handleImageError(row) {
|
||||
this.$set(this.imageLoadErrors, row.id, true)
|
||||
},
|
||||
onView(row) {
|
||||
this.infoRow = row
|
||||
this.infoVisible = true
|
||||
@@ -113,17 +503,45 @@ layout("/layouts/platform_h5.html"){
|
||||
onApply(row) {
|
||||
this.$pjaxReplace('/platform/trainSignUp/apply/list/h5?id=' + row.id + '&dataType=mine')
|
||||
},
|
||||
onReady() {
|
||||
this.doSearch()
|
||||
onLoad() {
|
||||
if(!this.finished) {
|
||||
this.loadActivities(false)
|
||||
}
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
onRefresh() {
|
||||
this.loadActivities(true)
|
||||
},
|
||||
loadActivities(reset) {
|
||||
if(reset) {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
this.tableData = []
|
||||
this.finished = false
|
||||
this.imageLoadErrors = {}
|
||||
}
|
||||
this.loading = true
|
||||
this.$axios.post('/platform/trainSignUp/apply/activityPageData', this.pageForm).then((res) => {
|
||||
if(res.code === 0) {
|
||||
const list = res.data && res.data.list ? res.data.list : []
|
||||
this.tableData = this.pageForm.pageNumber === 1 ? list : this.tableData.concat(list)
|
||||
this.pageForm.totalCount = res.data && res.data.totalCount ? res.data.totalCount : 0
|
||||
this.finished = this.tableData.length >= this.pageForm.totalCount
|
||||
if(!this.finished) {
|
||||
this.pageForm.pageNumber++
|
||||
}
|
||||
}
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
this.refreshing = false
|
||||
})
|
||||
},
|
||||
doSearch() {
|
||||
this.loadActivities(true)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadActivities(true)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
+589
-62
@@ -1,47 +1,474 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<div id="app">
|
||||
<!-- 导航栏 -->
|
||||
<style>
|
||||
body {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
<van-nav-bar title="作品上传" left-text="返回" left-arrow placeholder
|
||||
@click-left="historyBack" fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<year-van-dropdown-item :num="5" @change="doSearch" v-model="pageForm.year"></year-van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</van-sticky>
|
||||
<table-list api="/platform/activity/worksCollection/upload/pageData"
|
||||
:page_form.sync="pageForm"
|
||||
ref="tableListRef"
|
||||
title="name"
|
||||
@ready="onReady"
|
||||
>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="主题类型">{{row.subjectName}}</table-column>
|
||||
<table-column label="作品类型">{{row.worksName}}</table-column>
|
||||
<table-column label="姓名">{{row.userName}}</table-column>
|
||||
<table-column label="上传时间">{{$moment(row.createdAt).format('YYYY-MM-DD')}}</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" @click="onEdit(row)">
|
||||
<i class="fa fa-edit"></i>
|
||||
<span>编辑</span>
|
||||
</div>
|
||||
<div class="action-btn delete" @click="onDelete(row)">
|
||||
<i class="fa fa-trash"></i>
|
||||
<span>删除</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
.works-mine-page {
|
||||
min-height: 100vh;
|
||||
padding-bottom: calc(24px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
<apply-form ref="applyFormRef"></apply-form>
|
||||
.works-mine-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.works-mine-page .van-nav-bar__title {
|
||||
color: #1f2937;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.works-mine-page .van-nav-bar .van-icon,
|
||||
.works-mine-page .van-nav-bar__text {
|
||||
color: #397fbd;
|
||||
}
|
||||
|
||||
.works-mine-content {
|
||||
padding: 12px 12px 0;
|
||||
}
|
||||
|
||||
.works-mine-hero {
|
||||
position: relative;
|
||||
height: 134px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
color: #fff;
|
||||
background-color: #247fe8;
|
||||
box-shadow: 0 8px 20px rgba(51, 117, 219, .18);
|
||||
}
|
||||
|
||||
.works-mine-hero__image {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
|
||||
.works-mine-hero__copy {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
width: 66%;
|
||||
height: 100%;
|
||||
padding-left: 16px;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
background: linear-gradient(90deg, rgba(22, 112, 232, .98) 0%, rgba(22, 112, 232, .88) 52%, rgba(22, 112, 232, 0) 100%);
|
||||
}
|
||||
|
||||
.works-mine-hero__title {
|
||||
font-size: 25px;
|
||||
line-height: 34px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.works-mine-hero__subtitle {
|
||||
margin-top: 4px;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
letter-spacing: .5px;
|
||||
opacity: .95;
|
||||
}
|
||||
|
||||
.works-mine-sticky {
|
||||
padding: 10px 0 1px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.van-sticky--fixed .works-mine-sticky {
|
||||
padding-right: 12px;
|
||||
padding-left: 12px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.works-mine-search {
|
||||
margin-bottom: 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.works-mine-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.works-mine-filter {
|
||||
margin-bottom: 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
transition: border-radius .18s ease;
|
||||
}
|
||||
|
||||
.works-mine-filter.is-open {
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
.works-mine-filter .van-dropdown-menu__bar {
|
||||
height: 44px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.works-mine-filter .van-dropdown-menu__item {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.works-mine-filter .van-dropdown-menu__title {
|
||||
width: auto;
|
||||
max-width: calc(100% - 24px);
|
||||
padding: 0 12px 0 0;
|
||||
overflow: hidden;
|
||||
color: #66758a;
|
||||
font-size: 14px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.works-mine-filter .van-dropdown-menu__title::after {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.works-mine-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
margin: 0 12px;
|
||||
overflow: hidden;
|
||||
border-radius: 0 0 12px 12px;
|
||||
box-shadow: 0 10px 24px rgba(31, 65, 108, .14);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.works-mine-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.works-mine-card {
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.works-mine-card__cover,
|
||||
.works-mine-card__cover-state {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #edf4fc;
|
||||
}
|
||||
|
||||
.works-mine-card__cover {
|
||||
display: block;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.works-mine-card__cover-state {
|
||||
flex-direction: column;
|
||||
row-gap: 8px;
|
||||
color: #8da1ba;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.works-mine-card__cover-state .van-icon {
|
||||
font-size: 34px;
|
||||
}
|
||||
|
||||
.works-mine-card__cover-state.is-error {
|
||||
color: #c27b75;
|
||||
background-color: #fff3f1;
|
||||
}
|
||||
|
||||
.works-mine-card__body {
|
||||
padding: 12px 14px 14px;
|
||||
}
|
||||
|
||||
.works-mine-card__title {
|
||||
overflow: hidden;
|
||||
color: #303846;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.works-mine-card__activity,
|
||||
.works-mine-card__time {
|
||||
margin-top: 4px;
|
||||
overflow: hidden;
|
||||
color: #8794a7;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.works-mine-card__meta {
|
||||
display: flex;
|
||||
margin-top: 10px;
|
||||
padding-top: 9px;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
border-top: 1px solid #edf1f6;
|
||||
}
|
||||
|
||||
.works-mine-card__tag {
|
||||
display: inline-flex;
|
||||
padding: 3px 8px;
|
||||
border-radius: 4px;
|
||||
color: #397de0;
|
||||
background-color: #edf5ff;
|
||||
font-size: 11px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.works-mine-card__tag-label {
|
||||
margin-right: 4px;
|
||||
color: #8aa7cf;
|
||||
}
|
||||
|
||||
.works-mine-card__actions {
|
||||
display: flex;
|
||||
padding: 12px 14px;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
border-top: 1px solid #edf1f6;
|
||||
background-color: #f8fbff;
|
||||
}
|
||||
|
||||
.works-mine-card__action {
|
||||
display: inline-flex;
|
||||
min-width: 72px;
|
||||
height: 32px;
|
||||
padding: 0 12px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 0;
|
||||
border-radius: 16px;
|
||||
color: #397de0;
|
||||
background-color: #edf5ff;
|
||||
font-size: 13px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.works-mine-card__action .van-icon {
|
||||
margin-right: 5px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.works-mine-card__action.is-primary {
|
||||
color: #fff;
|
||||
background-color: #1989fa;
|
||||
box-shadow: 0 5px 12px rgba(25, 137, 250, .18);
|
||||
}
|
||||
|
||||
.works-mine-card__action.is-danger {
|
||||
color: #e45c5c;
|
||||
background-color: #fff0f0;
|
||||
}
|
||||
|
||||
.works-mine-skeleton {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.works-mine-skeleton__card {
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.works-mine-skeleton__cover,
|
||||
.works-mine-skeleton__body .van-skeleton,
|
||||
.works-mine-skeleton__actions .van-skeleton {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.works-mine-skeleton__cover .van-skeleton__row {
|
||||
width: 100% !important;
|
||||
height: 150px;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.works-mine-skeleton__body {
|
||||
padding: 13px 14px 14px;
|
||||
}
|
||||
|
||||
.works-mine-skeleton__body .van-skeleton__title {
|
||||
width: 52%;
|
||||
height: 15px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.works-mine-skeleton__body .van-skeleton__row {
|
||||
height: 12px;
|
||||
margin-top: 9px;
|
||||
}
|
||||
|
||||
.works-mine-skeleton__body .van-skeleton__row:last-child {
|
||||
width: 58%;
|
||||
}
|
||||
|
||||
.works-mine-skeleton__actions {
|
||||
padding: 12px 14px;
|
||||
border-top: 1px solid #edf1f6;
|
||||
background-color: #f8fbff;
|
||||
}
|
||||
|
||||
.works-mine-skeleton__actions .van-skeleton__row {
|
||||
width: 72%;
|
||||
height: 32px;
|
||||
margin: 0 0 0 auto;
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.works-mine-empty {
|
||||
display: flex;
|
||||
min-height: 260px;
|
||||
padding: 26px 18px 32px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.works-mine-empty img {
|
||||
width: 82%;
|
||||
max-width: 280px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.works-mine-empty__title {
|
||||
margin-top: 14px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.works-mine-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<div class="works-mine-page">
|
||||
<van-nav-bar title="我的作品" left-text="返回" left-arrow fixed placeholder @click-left="handlePageBack"></van-nav-bar>
|
||||
|
||||
<div class="works-mine-content">
|
||||
<section class="works-mine-hero">
|
||||
<img class="works-mine-hero__image" src="/assets/mobile/img/activity/hero/brand-hero-v2.png" alt="我的作品插画">
|
||||
<div class="works-mine-hero__copy">
|
||||
<div class="works-mine-hero__title">我的作品</div>
|
||||
<div class="works-mine-hero__subtitle">作品征集 · 提交记录</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<van-sticky :offset-top="46">
|
||||
<div class="works-mine-sticky">
|
||||
<van-search v-model="pageForm.searchKeyword" class="works-mine-search" placeholder="搜索作品或征集活动"
|
||||
shape="round" clearable @search="doSearch" @clear="doSearch"></van-search>
|
||||
<van-dropdown-menu class="works-mine-filter" :class="{'is-open': filterOpened}" active-color="#1989fa">
|
||||
<year-van-dropdown-item :num="5" v-model="pageForm.year" @change="doSearch"
|
||||
@open="onFilterOpen" @close="onFilterClose"></year-van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.activityType" :options="typeOptions" :multiple="false"
|
||||
@change="doSearch" @open="onFilterOpen" @close="onFilterClose"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<div v-if="skeletonLoading" class="works-mine-skeleton">
|
||||
<div v-for="index in 3" :key="'mine-skeleton-' + index" class="works-mine-skeleton__card">
|
||||
<van-skeleton class="works-mine-skeleton__cover" :row="1" animated></van-skeleton>
|
||||
<div class="works-mine-skeleton__body">
|
||||
<van-skeleton title :row="3" animated></van-skeleton>
|
||||
</div>
|
||||
<div class="works-mine-skeleton__actions">
|
||||
<van-skeleton :row="1" animated></van-skeleton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<van-pull-refresh v-show="!skeletonLoading" v-model="refreshing" @refresh="onRefresh">
|
||||
<van-list v-model="loading" :finished="finished" :immediate-check="false" @load="onLoad">
|
||||
<div class="works-mine-list">
|
||||
<article v-for="row in tableData" :key="row.id" class="works-mine-card">
|
||||
<img v-if="hasCover(row) && !imageLoadErrors[row.id]" class="works-mine-card__cover"
|
||||
:src="row.cover" :alt="row.activityName" @error="handleImageError(row)">
|
||||
<div v-else class="works-mine-card__cover-state" :class="{'is-error': hasCover(row)}">
|
||||
<van-icon name="photo-o"></van-icon>
|
||||
<span>{{hasCover(row) ? '图片加载失败' : '暂无图片'}}</span>
|
||||
</div>
|
||||
<div class="works-mine-card__body">
|
||||
<div class="works-mine-card__title">{{row.name}}</div>
|
||||
<div class="works-mine-card__activity">所属活动:{{row.activityName || '暂无活动信息'}}</div>
|
||||
<div class="works-mine-card__time" v-if="row.createdAt">
|
||||
提交时间:{{$moment(row.createdAt).format('YYYY-MM-DD HH:mm')}}
|
||||
</div>
|
||||
<div class="works-mine-card__meta" v-if="row.subjectName || row.worksName">
|
||||
<span class="works-mine-card__tag" v-if="row.subjectName">
|
||||
<span class="works-mine-card__tag-label">主题</span>{{row.subjectName}}
|
||||
</span>
|
||||
<span class="works-mine-card__tag" v-if="row.worksName">
|
||||
<span class="works-mine-card__tag-label">类型</span>{{row.worksName}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="works-mine-card__actions">
|
||||
<button type="button" class="works-mine-card__action" @click="onView(row)">
|
||||
<van-icon name="eye-o"></van-icon>查看
|
||||
</button>
|
||||
<button type="button" class="works-mine-card__action" @click="onEdit(row)">
|
||||
<van-icon name="edit"></van-icon>编辑
|
||||
</button>
|
||||
<button type="button" class="works-mine-card__action is-danger" @click="onDelete(row)">
|
||||
<van-icon name="delete-o"></van-icon>删除
|
||||
</button>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</van-list>
|
||||
<div v-if="!loading && tableData.length === 0" class="works-mine-empty">
|
||||
<img src="/assets/mobile/img/activity/culture-empty.png" alt="作品记录空状态插画">
|
||||
<div class="works-mine-empty__title">暂无作品记录</div>
|
||||
<div class="works-mine-empty__hint">当前筛选条件下暂时没有已提交作品</div>
|
||||
</div>
|
||||
</van-pull-refresh>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<van-dialog title="删除确认" message="确认删除当前作品吗?" :value="deleteConfirmVisible"
|
||||
:close-on-click-overlay="false" show-cancel-button cancel-button-text="取消" confirm-button-text="确认删除"
|
||||
@cancel="closeDeleteConfirm" @confirm="confirmDelete"></van-dialog>
|
||||
|
||||
<apply-form ref="applyFormRef" @submit-success="handleEditSubmitSuccess"></apply-form>
|
||||
<info ref="infoRef"></info>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -51,22 +478,59 @@ layout("/layouts/platform_h5.html"){
|
||||
new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
components: {
|
||||
'apply-form': applyForm,
|
||||
'info': INFO,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tableData: [],
|
||||
loading: false,
|
||||
skeletonLoading: true,
|
||||
finished: false,
|
||||
refreshing: false,
|
||||
imageLoadErrors: {},
|
||||
filterOpened: false,
|
||||
deleteConfirmVisible: false,
|
||||
deleteLoading: false,
|
||||
pendingDeleteRow: {},
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
searchKeyword: '',
|
||||
year: new Date().getFullYear(),
|
||||
activityType: 1,
|
||||
},
|
||||
typeOptions: [
|
||||
{text: '全部', value: 1},
|
||||
{text: '征集中', value: 2},
|
||||
{text: '已结束', value: 3},
|
||||
],
|
||||
historyLayerPageKey: 'works-collection-mine-h5',
|
||||
historyLayerUnsubscribe: null,
|
||||
}
|
||||
},
|
||||
components: {
|
||||
'apply-form': applyForm,
|
||||
'info': INFO,
|
||||
},
|
||||
methods: {
|
||||
hasCover(row) {
|
||||
return !!(row && row.cover && String(row.cover).trim())
|
||||
},
|
||||
handleImageError(row) {
|
||||
this.$set(this.imageLoadErrors, row.id, true)
|
||||
},
|
||||
onFilterOpen() {
|
||||
this.$set(this, 'filterOpened', true)
|
||||
},
|
||||
onFilterClose() {
|
||||
this.$set(this, 'filterOpened', false)
|
||||
},
|
||||
handlePageBack() {
|
||||
if (window.h5HistoryLayerManager.stack.length) {
|
||||
window.h5HistoryLayerManager.close()
|
||||
return
|
||||
}
|
||||
this.historyBack()
|
||||
},
|
||||
onView(row) {
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
},
|
||||
@@ -77,31 +541,94 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
this.$refs.applyFormRef.onOpenEdit(row)
|
||||
},
|
||||
// 编辑提交成功后留在我的作品页面,仅刷新当前列表数据。
|
||||
handleEditSubmitSuccess() {
|
||||
this.loadWorks(true)
|
||||
},
|
||||
onDelete(row) {
|
||||
this.$dialog.confirm({
|
||||
title: '温馨提示',
|
||||
message: '您确定要删除吗?',
|
||||
}).then(() => {
|
||||
this.$axios.post("/platform/activity/worksCollection/upload/delete", {id:row.id}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
// on cancel
|
||||
});
|
||||
this.$set(this, 'pendingDeleteRow', row)
|
||||
window.h5HistoryLayerManager.open('works-collection-mine-delete-confirm')
|
||||
},
|
||||
onReady() {
|
||||
this.doSearch()
|
||||
closeDeleteConfirm() {
|
||||
window.h5HistoryLayerManager.close('works-collection-mine-delete-confirm')
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
confirmDelete() {
|
||||
const row = this.pendingDeleteRow
|
||||
window.h5HistoryLayerManager.close('works-collection-mine-delete-confirm', () => {
|
||||
this.deleteRow(row)
|
||||
})
|
||||
},
|
||||
// 删除接口接收作品 id,成功后重置分页列表;接口返回 Result JSON。
|
||||
deleteRow(row) {
|
||||
if (!row || !row.id || this.deleteLoading) return
|
||||
this.$set(this, 'deleteLoading', true)
|
||||
this.$axios.post('/platform/activity/worksCollection/upload/delete', {id: row.id}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.success(res.msg || '删除成功')
|
||||
this.loadWorks(true)
|
||||
}
|
||||
}).finally(() => {
|
||||
this.$set(this, 'deleteLoading', false)
|
||||
})
|
||||
},
|
||||
onLoad() {
|
||||
if (!this.finished) this.loadWorks(false)
|
||||
},
|
||||
onRefresh() {
|
||||
this.loadWorks(true)
|
||||
},
|
||||
/**
|
||||
* 加载当前用户作品分页数据。
|
||||
* reset 为 true 时从第一页重新查询;接口返回 Pagination,list 为作品数组、totalCount 为总数。
|
||||
*/
|
||||
loadWorks(reset) {
|
||||
const showSkeleton = !!reset
|
||||
if (reset) {
|
||||
this.$set(this, 'skeletonLoading', true)
|
||||
this.$set(this.pageForm, 'pageNumber', 1)
|
||||
this.$set(this.pageForm, 'totalCount', 0)
|
||||
this.$set(this, 'tableData', [])
|
||||
this.$set(this, 'finished', false)
|
||||
this.$set(this, 'imageLoadErrors', {})
|
||||
}
|
||||
this.$set(this, 'loading', true)
|
||||
this.$axios.post('/platform/activity/worksCollection/upload/pageData', this.pageForm, {
|
||||
h5SkeletonLoading: showSkeleton
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const list = res.data && res.data.list ? res.data.list : []
|
||||
this.$set(this, 'tableData', this.pageForm.pageNumber === 1 ? list : this.tableData.concat(list))
|
||||
this.$set(this.pageForm, 'totalCount', res.data && res.data.totalCount ? res.data.totalCount : 0)
|
||||
this.$set(this, 'finished', this.tableData.length >= this.pageForm.totalCount)
|
||||
if (!this.finished) {
|
||||
this.$set(this.pageForm, 'pageNumber', this.pageForm.pageNumber + 1)
|
||||
}
|
||||
}
|
||||
}).finally(() => {
|
||||
this.$set(this, 'loading', false)
|
||||
this.$set(this, 'refreshing', false)
|
||||
if (showSkeleton) this.$set(this, 'skeletonLoading', false)
|
||||
})
|
||||
},
|
||||
doSearch() {
|
||||
this.loadWorks(true)
|
||||
},
|
||||
syncHistoryLayers(stack) {
|
||||
this.$set(this, 'deleteConfirmVisible', stack.includes('works-collection-mine-delete-confirm'))
|
||||
}
|
||||
},
|
||||
created() {
|
||||
window.h5HistoryLayerManager.register(this.historyLayerPageKey, (stack) => {
|
||||
this.syncHistoryLayers(stack)
|
||||
})
|
||||
this.$set(this, 'historyLayerUnsubscribe', window.h5HistoryLayerManager.subscribe((stack) => {
|
||||
this.syncHistoryLayers(stack)
|
||||
}))
|
||||
this.loadWorks(true)
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.historyLayerUnsubscribe) this.historyLayerUnsubscribe()
|
||||
window.h5HistoryLayerManager.unregister(this.historyLayerPageKey)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,64 +1,197 @@
|
||||
const INFO = {
|
||||
template: /*language=HTML*/
|
||||
`
|
||||
template: /*language=HTML*/ `
|
||||
<div>
|
||||
<van-action-sheet v-model="visible" :style="{ 'background-color': '#F7F8FA' }" title="报名信息">
|
||||
<div class="detail-container">
|
||||
<van-cell-group>
|
||||
<van-cell title="姓名">
|
||||
{{ viewData.userName }}
|
||||
</van-cell>
|
||||
<van-cell title="工号">
|
||||
{{ viewData.loginName }}
|
||||
</van-cell>
|
||||
<van-cell title="单位">
|
||||
{{ viewData.unitName }}
|
||||
</van-cell>
|
||||
<van-cell title="分工会">
|
||||
{{ viewData.unionName }}
|
||||
</van-cell>
|
||||
<van-cell title="作品名称">
|
||||
{{ viewData.name }}
|
||||
</van-cell>
|
||||
<van-cell title="活动主题">
|
||||
{{ viewData.activityName }}
|
||||
</van-cell>
|
||||
<van-cell title="主题类型">
|
||||
{{ viewData.subjectName }}
|
||||
</van-cell>
|
||||
<van-cell title="作品类型">
|
||||
{{ viewData.worksName }}
|
||||
</van-cell>
|
||||
<van-cell title="作品描述" class="direction-column-cell">
|
||||
{{ viewData.description }}
|
||||
</van-cell>
|
||||
<van-cell title="作品附件" class="direction-column-cell">
|
||||
<file-preview :files="viewData.files" complete_result></file-preview>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
<van-popup class="works-detail-popup" :style="{height: '100%', width: '100%'}" position="right"
|
||||
safe-area-inset-bottom :close-on-click-overlay="false" v-model="visible">
|
||||
<div class="works-detail-page">
|
||||
<van-sticky>
|
||||
<van-nav-bar title="作品详情" left-text="返回" left-arrow @click-left="closeInfo"></van-nav-bar>
|
||||
</van-sticky>
|
||||
<div ref="detailScrollRef" class="works-detail-scroll">
|
||||
<section class="works-detail-card">
|
||||
<h2 class="works-detail-card__title">基础信息</h2>
|
||||
<van-cell-group :border="false">
|
||||
<van-cell title="姓名" :value="viewData.userName || '-' "></van-cell>
|
||||
<van-cell title="工号" :value="viewData.loginName || '-' "></van-cell>
|
||||
<van-cell title="单位" :value="viewData.unitName || '-' "></van-cell>
|
||||
<van-cell title="分工会" :value="viewData.unionName || '-' "></van-cell>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
|
||||
<section class="works-detail-card">
|
||||
<h2 class="works-detail-card__title">作品信息</h2>
|
||||
<van-cell-group :border="false">
|
||||
<van-cell title="所属活动" :value="viewData.activityName || '-' "></van-cell>
|
||||
<van-cell title="主题类型" :value="viewData.subjectName || '-' "></van-cell>
|
||||
<van-cell title="作品类型" :value="viewData.worksName || '-' "></van-cell>
|
||||
<van-cell title="作品名称" :value="viewData.name || '-' "></van-cell>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
|
||||
<section class="works-detail-card">
|
||||
<h2 class="works-detail-card__title">作品描述</h2>
|
||||
<div class="works-detail-description">{{viewData.description || '暂无作品描述'}}</div>
|
||||
</section>
|
||||
|
||||
<section class="works-detail-card">
|
||||
<h2 class="works-detail-card__title">作品附件</h2>
|
||||
<div v-if="viewData.files && viewData.files.length" class="works-detail-files">
|
||||
<file-preview :files="viewData.files" complete_result></file-preview>
|
||||
</div>
|
||||
<div v-else class="works-detail-empty">暂无作品附件</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</van-action-sheet>
|
||||
</div>
|
||||
</van-popup>
|
||||
<slot></slot>
|
||||
</div>
|
||||
`,
|
||||
style: /*language=CSS*/ `
|
||||
/deep/ .works-detail-popup,
|
||||
/deep/ .works-detail-page {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
/deep/ .works-detail-page {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/deep/ .works-detail-page .van-nav-bar__title {
|
||||
color: #1f2937;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/deep/ .works-detail-page .van-nav-bar .van-icon,
|
||||
/deep/ .works-detail-page .van-nav-bar__text {
|
||||
color: #397fbd;
|
||||
}
|
||||
|
||||
/deep/ .works-detail-scroll {
|
||||
height: calc(100vh - 46px);
|
||||
padding: 12px 12px calc(24px + env(safe-area-inset-bottom));
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/deep/ .works-detail-card {
|
||||
margin-top: 12px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #e9eff7;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
/deep/ .works-detail-scroll > .works-detail-card:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/deep/ .works-detail-card__title {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
padding: 13px 14px 9px 22px;
|
||||
color: #354255;
|
||||
font-size: 15px;
|
||||
line-height: 21px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/deep/ .works-detail-card__title::before {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
bottom: 12px;
|
||||
left: 12px;
|
||||
width: 2px;
|
||||
border-radius: 2px;
|
||||
background-color: #1989fa;
|
||||
content: "";
|
||||
}
|
||||
|
||||
/deep/ .works-detail-card .van-cell {
|
||||
padding: 10px 14px;
|
||||
color: #596779;
|
||||
}
|
||||
|
||||
/deep/ .works-detail-card .van-cell__title {
|
||||
flex: 0 0 82px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/deep/ .works-detail-card .van-cell__value {
|
||||
color: #4f5d70;
|
||||
font-size: 14px;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
/deep/ .works-detail-description,
|
||||
/deep/ .works-detail-files,
|
||||
/deep/ .works-detail-empty {
|
||||
padding: 4px 14px 16px;
|
||||
color: #536174;
|
||||
font-size: 14px;
|
||||
line-height: 1.8;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
/deep/ .works-detail-empty {
|
||||
color: #9aa7b8;
|
||||
}
|
||||
`,
|
||||
data() {
|
||||
return {
|
||||
viewData: {},
|
||||
visible: false,
|
||||
historyLayerUnsubscribe: null,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 查询并打开作品详情。
|
||||
* row 需传作品 id;接口返回作品、活动、主题、类型及附件信息的 Result JSON。
|
||||
*/
|
||||
onOpen(row) {
|
||||
this.$set(this, "viewData", Object.assign({}, row, {files: this.normalizeFiles(row.files)}))
|
||||
window.h5HistoryLayerManager.open("works-collection-mine-info")
|
||||
this.resetScrollPosition()
|
||||
this.$axios.post("/platform/activity/worksCollection/common/findOne", {id: row.id}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.viewData = res.data
|
||||
try {
|
||||
this.viewData.files = JSON.parse(this.viewData.files)
|
||||
} catch (err) {
|
||||
}
|
||||
const viewData = res.data || {}
|
||||
viewData.files = this.normalizeFiles(viewData.files)
|
||||
this.$set(this, "viewData", viewData)
|
||||
}
|
||||
})
|
||||
this.visible = true
|
||||
},
|
||||
|
||||
// 弹窗组件会被复用,每次打开后需清除上一次查看时保留的滚动位置。
|
||||
resetScrollPosition() {
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.detailScrollRef) this.$refs.detailScrollRef.scrollTop = 0
|
||||
})
|
||||
},
|
||||
normalizeFiles(files) {
|
||||
if (Array.isArray(files)) return files
|
||||
if (!files) return []
|
||||
try {
|
||||
const result = JSON.parse(files)
|
||||
return Array.isArray(result) ? result : []
|
||||
} catch (err) {
|
||||
return []
|
||||
}
|
||||
},
|
||||
closeInfo() {
|
||||
window.h5HistoryLayerManager.close("works-collection-mine-info")
|
||||
},
|
||||
syncHistoryLayers(stack) {
|
||||
this.$set(this, "visible", stack.includes("works-collection-mine-info"))
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$set(this, "historyLayerUnsubscribe", window.h5HistoryLayerManager.subscribe((stack) => {
|
||||
this.syncHistoryLayers(stack)
|
||||
}))
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.historyLayerUnsubscribe) this.historyLayerUnsubscribe()
|
||||
}
|
||||
}
|
||||
|
||||
+615
-107
@@ -1,66 +1,502 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<div id="app">
|
||||
<!-- 导航栏 -->
|
||||
<style>
|
||||
body {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
<van-nav-bar title="作品阅览" left-text="返回" left-arrow placeholder
|
||||
@click-left="historyBack" fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<van-search
|
||||
:reverse-color="false"
|
||||
:show-action="false"
|
||||
@search="doSearch"
|
||||
input-align="left"
|
||||
placeholder="请输入姓名/工号搜索"
|
||||
v-model="pageForm.searchKeyword"
|
||||
></van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item v-model="pageForm.activityId" :options="activityOptions"
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-tabs v-model="pageForm.pageOrderName"
|
||||
@change="doSearch">
|
||||
<van-tab title="按上传时间正序排序" name="createdAt"></van-tab>
|
||||
<van-tab title="按点赞多少倒序排序" name="num"></van-tab>
|
||||
</van-tabs>
|
||||
</van-sticky>
|
||||
<table-list api="/platform/activity/worksCollection/read/h5/pageData"
|
||||
:page_form.sync="pageForm"
|
||||
ref="tableListRef"
|
||||
title="name"
|
||||
@ready="onReady"
|
||||
>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="主题类型">{{row.subjectName}}</table-column>
|
||||
<table-column label="作品类型">{{row.worksName}}</table-column>
|
||||
<table-column label="姓名">{{row.userName}}</table-column>
|
||||
<table-column label="上传时间">{{$moment(row.createdAt).format('YYYY-MM-DD')}}</table-column>
|
||||
<table-column label="点赞数">{{row.num}}</table-column>
|
||||
<table-column label="附件">
|
||||
<template v-if="row.files">
|
||||
<file-preview :files="JSON.parse(row.files)" complete_result></file-preview>
|
||||
</template>
|
||||
</table-column>
|
||||
.works-read-page {
|
||||
min-height: 100vh;
|
||||
padding-bottom: calc(24px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span>查看</span>
|
||||
.works-read-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.works-read-page .van-nav-bar__title {
|
||||
color: #172033;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.works-read-page .van-nav-bar .van-icon,
|
||||
.works-read-page .van-nav-bar__text {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.works-read-sticky {
|
||||
padding: 22px 12px 1px;
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.works-read-search {
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.works-read-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.works-read-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.works-read-search .van-field__control::placeholder {
|
||||
color: #a7b0bf;
|
||||
}
|
||||
|
||||
.works-read-filter {
|
||||
margin: 0 0 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
transition: border-radius .18s ease;
|
||||
}
|
||||
|
||||
.works-read-filter.is-open {
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
.works-read-filter .van-dropdown-menu__bar {
|
||||
height: 44px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.works-read-filter .van-dropdown-menu__item {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.works-read-filter .van-dropdown-menu__title {
|
||||
width: auto;
|
||||
max-width: calc(100% - 24px);
|
||||
padding: 0 12px 0 0;
|
||||
overflow: hidden;
|
||||
color: #66758a;
|
||||
font-size: 14px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.works-read-filter .van-dropdown-menu__title::after {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.works-read-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
margin: 0 12px;
|
||||
overflow: hidden;
|
||||
border-radius: 0 0 12px 12px;
|
||||
box-shadow: 0 10px 24px rgba(31, 65, 108, .14);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.works-read-content {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.works-read-list .empty-state {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.works-read-skeleton {
|
||||
padding-top: 12px;
|
||||
}
|
||||
|
||||
.works-read-skeleton__card {
|
||||
margin-bottom: 12px;
|
||||
padding: 14px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #eef1f6;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.works-read-skeleton__card .van-skeleton {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.works-read-skeleton__card .van-skeleton__title {
|
||||
width: 42%;
|
||||
height: 16px;
|
||||
margin-bottom: 13px;
|
||||
}
|
||||
|
||||
.works-read-skeleton__card .van-skeleton__row {
|
||||
height: 12px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.works-read-skeleton__card .van-skeleton__row:nth-child(2n) {
|
||||
width: 72%;
|
||||
}
|
||||
|
||||
.works-read-skeleton__card .van-skeleton__row:last-child {
|
||||
width: 48%;
|
||||
height: 28px;
|
||||
margin-top: 16px;
|
||||
border-radius: 14px;
|
||||
}
|
||||
|
||||
.works-read-empty {
|
||||
display: flex;
|
||||
min-height: 280px;
|
||||
padding: 46px 18px 36px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.works-read-empty img {
|
||||
display: block;
|
||||
width: 86%;
|
||||
max-width: 290px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.works-read-empty__title {
|
||||
margin-top: 14px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.works-read-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.works-read-card-header {
|
||||
display: flex;
|
||||
margin-bottom: 7px;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.works-read-card-heading {
|
||||
min-width: 0;
|
||||
padding-right: 10px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.works-read-card-title {
|
||||
overflow: hidden;
|
||||
color: #253247;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.works-read-card-activity {
|
||||
margin-top: 1px;
|
||||
overflow: hidden;
|
||||
color: #9ba6b6;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.works-read-like-summary {
|
||||
display: inline-flex;
|
||||
min-height: 24px;
|
||||
align-items: center;
|
||||
flex: none;
|
||||
color: #7f8da1;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 顶部仅展示累计点赞信息,人员图标与无底色文字用于区别底部可点击的点赞按钮。 */
|
||||
.works-read-like-summary .van-icon {
|
||||
display: inline-flex;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 5px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
color: #ffffff;
|
||||
background-color: #8795aa;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.works-read-files-row {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
margin-top: 8px;
|
||||
padding-top: 10px;
|
||||
border-top: 1px solid #edf1f6;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.works-read-files-label {
|
||||
display: flex;
|
||||
margin-bottom: 7px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
color: #98a3b3;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.works-read-files-hint {
|
||||
flex: none;
|
||||
color: #7893af;
|
||||
font-size: 11px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.works-read-files-scroll {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.works-read-files-scroll::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.works-read-list .works-read-files-scroll .file-preview-container {
|
||||
display: flex !important;
|
||||
width: max-content;
|
||||
min-width: 100%;
|
||||
padding: 0;
|
||||
grid-template-columns: none !important;
|
||||
gap: 8px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.works-read-list .works-read-files-scroll .file-preview-container .file-item {
|
||||
width: 88px;
|
||||
height: 88px;
|
||||
flex: 0 0 88px;
|
||||
aspect-ratio: auto;
|
||||
}
|
||||
|
||||
.works-read-action-icon {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.works-read-like-action-wrap {
|
||||
position: relative;
|
||||
display: flex;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.works-read-like-hearts {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
bottom: 24px;
|
||||
left: 50%;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.works-read-like-heart {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
color: #ee3f4d;
|
||||
font-size: 18px;
|
||||
line-height: 1;
|
||||
opacity: 0;
|
||||
text-shadow: 0 3px 8px rgba(238, 63, 77, .32);
|
||||
animation: works-read-heart-bubble 1s ease-out forwards;
|
||||
}
|
||||
|
||||
.works-read-like-heart.is-heart-1 {
|
||||
--heart-x: -26px;
|
||||
--heart-y: -62px;
|
||||
font-size: 15px;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.works-read-like-heart.is-heart-2 {
|
||||
--heart-x: -11px;
|
||||
--heart-y: -82px;
|
||||
font-size: 21px;
|
||||
animation-delay: .08s;
|
||||
}
|
||||
|
||||
.works-read-like-heart.is-heart-3 {
|
||||
--heart-x: 7px;
|
||||
--heart-y: -68px;
|
||||
font-size: 14px;
|
||||
animation-delay: .16s;
|
||||
}
|
||||
|
||||
.works-read-like-heart.is-heart-4 {
|
||||
--heart-x: 24px;
|
||||
--heart-y: -88px;
|
||||
font-size: 18px;
|
||||
animation-delay: .24s;
|
||||
}
|
||||
|
||||
.works-read-like-heart.is-heart-5 {
|
||||
--heart-x: -18px;
|
||||
--heart-y: -102px;
|
||||
font-size: 13px;
|
||||
animation-delay: .32s;
|
||||
}
|
||||
|
||||
.works-read-like-heart.is-heart-6 {
|
||||
--heart-x: 15px;
|
||||
--heart-y: -108px;
|
||||
font-size: 16px;
|
||||
animation-delay: .4s;
|
||||
}
|
||||
|
||||
@keyframes works-read-heart-bubble {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translate(-50%, 5px) scale(.35);
|
||||
}
|
||||
20% {
|
||||
opacity: 1;
|
||||
transform: translate(-50%, -8px) scale(1.15);
|
||||
}
|
||||
62% {
|
||||
opacity: 1;
|
||||
transform: translate(-50%, -42px) scale(1);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: translate(calc(-50% + var(--heart-x)), var(--heart-y)) scale(.72);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 350px) {
|
||||
.works-read-content,
|
||||
.works-read-sticky {
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<div class="works-read-page">
|
||||
<van-nav-bar title="作品阅览" left-text="返回" left-arrow placeholder fixed
|
||||
@click-left="handlePageBack"></van-nav-bar>
|
||||
|
||||
<van-sticky :offset-top="46">
|
||||
<div class="works-read-sticky">
|
||||
<van-search v-model="pageForm.searchKeyword" class="works-read-search"
|
||||
placeholder="请输入姓名或工号搜索" shape="round" clearable
|
||||
@search="doSearch" @clear="doSearch"></van-search>
|
||||
<van-dropdown-menu class="works-read-filter" :class="{'is-open': filterOpened}" active-color="#1989fa">
|
||||
<van-dropdown-item v-model="pageForm.activityId" :options="activityOptions" :multiple="false"
|
||||
@change="doSearch" @open="onFilterOpen" @close="onFilterClose"></van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.pageOrderName" :options="orderOptions" :multiple="false"
|
||||
@change="doSearch" @open="onFilterOpen" @close="onFilterClose"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</div>
|
||||
<template v-if="row.nbCount>0">
|
||||
<div class="action-btn" @click="onLike(row)" v-if="!row.isThisLike">
|
||||
<i class="fa fa-thumbs-o-up"></i>
|
||||
<span>点赞</span>
|
||||
</van-sticky>
|
||||
|
||||
<main class="works-read-content">
|
||||
<div class="works-read-list">
|
||||
<div v-if="skeletonLoading" class="works-read-skeleton">
|
||||
<div v-for="index in 3" :key="'read-skeleton-' + index" class="works-read-skeleton__card">
|
||||
<van-skeleton title :row="5" animated></van-skeleton>
|
||||
</div>
|
||||
</div>
|
||||
<div class="action-btn" @click="onDeleteLike(row)" v-if="row.isThisLike">
|
||||
<i class="fa fa-thumbs-up"></i>
|
||||
<span>取消点赞</span>
|
||||
<div v-if="!skeletonLoading && pageForm.totalCount === 0" class="works-read-empty">
|
||||
<img src="/assets/mobile/img/activity/culture-empty.png" alt="暂无作品记录插画">
|
||||
<div class="works-read-empty__title">暂无作品记录</div>
|
||||
<div class="works-read-empty__hint">当前筛选条件下暂时没有可阅览作品</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</table-list>
|
||||
<table-list api="/platform/activity/worksCollection/read/h5/pageData"
|
||||
:page_form.sync="pageForm" ref="tableListRef" title="name" v-show="!skeletonLoading"
|
||||
:show_loading_overlay="false" @ready="onReady" @loading-change="handleListLoadingChange">
|
||||
<template #header="{index,row}">
|
||||
<div class="works-read-card-header">
|
||||
<div class="works-read-card-heading">
|
||||
<div class="works-read-card-title">{{row.name || '未命名作品'}}</div>
|
||||
<div class="works-read-card-activity">{{row.activityName || '暂无活动信息'}}</div>
|
||||
</div>
|
||||
<div class="works-read-like-summary">
|
||||
<van-icon name="friends"></van-icon>
|
||||
<span>已有 {{row.num || 0}} 人点赞</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="作品类型">{{row.worksName || '--'}}</table-column>
|
||||
<table-column label="作者">{{row.userName || '--'}}</table-column>
|
||||
<table-column label="工号">{{row.loginName || '--'}}</table-column>
|
||||
<table-column label="上传时间">{{$moment(row.createdAt).format('YYYY-MM-DD')}}</table-column>
|
||||
<div v-if="hasListFiles(row.files)" class="works-read-files-row">
|
||||
<div class="works-read-files-label">
|
||||
<span>上传附件</span>
|
||||
<span v-if="getAttachmentCount(row.files) > 1" class="works-read-files-hint">
|
||||
共{{getAttachmentCount(row.files)}}个附件 · 左滑查看更多
|
||||
</span>
|
||||
</div>
|
||||
<div class="works-read-files-scroll">
|
||||
<file-preview :files="row.files" complete_result></file-preview>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<van-icon class="works-read-action-icon" name="eye-o"></van-icon>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div v-if="row.nbCount > 0" class="works-read-like-action-wrap">
|
||||
<div class="action-btn" v-if="!row.isThisLike" @click="onLike(row)">
|
||||
<van-icon class="works-read-action-icon" name="good-job-o"></van-icon>
|
||||
<span>点赞</span>
|
||||
</div>
|
||||
<div class="action-btn delete" v-else @click="onDeleteLike(row)">
|
||||
<van-icon class="works-read-action-icon" name="good-job"></van-icon>
|
||||
<span>取消点赞</span>
|
||||
</div>
|
||||
<span v-if="likeHeartEffects[row.id]"
|
||||
:key="'like-heart-' + row.id + '-' + (likeHeartEffectKeys[row.id] || 0)"
|
||||
class="works-read-like-hearts" aria-hidden="true">
|
||||
<span v-for="heartIndex in 6" :key="heartIndex"
|
||||
class="works-read-like-heart" :class="'is-heart-' + heartIndex">♥</span>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<info ref="infoRef"></info>
|
||||
|
||||
</div>
|
||||
@@ -69,6 +505,9 @@ layout("/layouts/platform_h5.html"){
|
||||
new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
components: {
|
||||
'info': INFO,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageForm: {
|
||||
@@ -77,79 +516,148 @@ layout("/layouts/platform_h5.html"){
|
||||
totalCount: 0,
|
||||
searchKeyword: '',
|
||||
pageOrderName: 'createdAt',
|
||||
pageOrderNameText: '',
|
||||
activityId: '',
|
||||
year: new Date().getFullYear(),
|
||||
},
|
||||
activityOptions: []
|
||||
activityOptions: [],
|
||||
orderOptions: [
|
||||
{text: '按上传时间排序', value: 'createdAt'},
|
||||
{text: '按点赞数量排序', value: 'num'},
|
||||
],
|
||||
filterOpened: false,
|
||||
likeLoading: false,
|
||||
likeHeartEffects: {},
|
||||
likeHeartEffectKeys: {},
|
||||
likeHeartEffectTimers: {},
|
||||
skeletonLoading: true,
|
||||
historyLayerPageKey: 'works-collection-read-h5',
|
||||
}
|
||||
},
|
||||
components: {
|
||||
'info': INFO,
|
||||
},
|
||||
methods: {
|
||||
// state.initial 表示查询前列表为空,仅在首次或重置查询时显示整组卡片骨架。
|
||||
handleListLoadingChange(state) {
|
||||
if (state.initial) this.$set(this, 'skeletonLoading', state.loading)
|
||||
},
|
||||
// 判断列表附件是否包含有效记录;files 支持上传组件保存的 JSON 字符串或数组。
|
||||
hasListFiles(files) {
|
||||
if (Array.isArray(files)) return files.length > 0
|
||||
if (!files) return false
|
||||
try {
|
||||
const fileList = JSON.parse(files)
|
||||
return Array.isArray(fileList) && fileList.length > 0
|
||||
} catch (err) {
|
||||
return false
|
||||
}
|
||||
},
|
||||
// 获取当前作品的全部附件数量;files 支持 JSON 字符串或数组,返回 Number 类型。
|
||||
getAttachmentCount(files) {
|
||||
if (Array.isArray(files)) return files.length
|
||||
if (!files) return 0
|
||||
try {
|
||||
const fileList = JSON.parse(files)
|
||||
return Array.isArray(fileList) ? fileList.length : 0
|
||||
} catch (err) {
|
||||
return 0
|
||||
}
|
||||
},
|
||||
onLike(row) {
|
||||
this.$dialog.confirm({
|
||||
title: '温馨提示',
|
||||
message: '您确定要点赞吗?',
|
||||
}).then(() => {
|
||||
this.$axios.post("/platform/activity/worksCollection/read/h5/doLike", {uploadId: row.id}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
row.num = row.num + 1
|
||||
row.isThisLike = true
|
||||
this.$toast.success(res.msg)
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
// on cancel
|
||||
});
|
||||
this.executeLikeAction(row, 'like')
|
||||
},
|
||||
onDeleteLike(row) {
|
||||
this.$dialog.confirm({
|
||||
title: '温馨提示',
|
||||
message: '您确定要取消点赞吗?',
|
||||
}).then(() => {
|
||||
this.$axios.post("/platform/activity/worksCollection/read/h5/doDeleteLike", {uploadId: row.id}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
row.num = row.num - 1
|
||||
row.isThisLike = false
|
||||
this.$toast.success(res.msg)
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
// on cancel
|
||||
});
|
||||
this.executeLikeAction(row, 'cancel')
|
||||
},
|
||||
/**
|
||||
* 执行作品点赞或取消点赞。
|
||||
* row 需包含作品 id,action 传 like 或 cancel;接口返回 Result JSON,方法无返回值。
|
||||
*/
|
||||
executeLikeAction(row, action) {
|
||||
if (!row || !row.id || this.likeLoading) return
|
||||
const isCancel = action === 'cancel'
|
||||
const url = isCancel
|
||||
? '/platform/activity/worksCollection/read/h5/doDeleteLike'
|
||||
: '/platform/activity/worksCollection/read/h5/doLike'
|
||||
this.$set(this, 'likeLoading', true)
|
||||
this.$axios.post(url, {uploadId: row.id}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const currentNum = Number(row.num) || 0
|
||||
this.$set(row, 'num', isCancel ? Math.max(currentNum - 1, 0) : currentNum + 1)
|
||||
this.$set(row, 'isThisLike', !isCancel)
|
||||
if (!isCancel) this.playLikeHeart(row.id)
|
||||
}
|
||||
}).finally(() => {
|
||||
this.$set(this, 'likeLoading', false)
|
||||
})
|
||||
},
|
||||
// 点赞成功后为当前作品播放多颗红色爱心错峰上浮动画,重复触发时重新开始计时。
|
||||
playLikeHeart(rowId) {
|
||||
if (!rowId) return
|
||||
if (this.likeHeartEffectTimers[rowId]) {
|
||||
clearTimeout(this.likeHeartEffectTimers[rowId])
|
||||
}
|
||||
this.$set(this.likeHeartEffects, rowId, false)
|
||||
this.$set(this.likeHeartEffectKeys, rowId, (this.likeHeartEffectKeys[rowId] || 0) + 1)
|
||||
this.$nextTick(() => {
|
||||
this.$set(this.likeHeartEffects, rowId, true)
|
||||
const timer = setTimeout(() => {
|
||||
this.$set(this.likeHeartEffects, rowId, false)
|
||||
this.$delete(this.likeHeartEffectTimers, rowId)
|
||||
}, 1400)
|
||||
this.$set(this.likeHeartEffectTimers, rowId, timer)
|
||||
})
|
||||
},
|
||||
onView(row) {
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
},
|
||||
async listActivity() {
|
||||
const res = await this.$axios.post("/platform/activity/worksCollection/common/listActivity")
|
||||
if (res.code === 0) {
|
||||
res.data.forEach(v => {
|
||||
v.text = v.name
|
||||
v.value = v.id
|
||||
})
|
||||
this.activityOptions = res.data
|
||||
if (this.activityOptions.length > 0) {
|
||||
this.pageForm.activityId = this.activityOptions[0].id
|
||||
}
|
||||
}
|
||||
onFilterOpen() {
|
||||
this.$set(this, 'filterOpened', true)
|
||||
},
|
||||
async onReady() {
|
||||
await this.listActivity()
|
||||
this.doSearch()
|
||||
onFilterClose() {
|
||||
this.$set(this, 'filterOpened', false)
|
||||
},
|
||||
handlePageBack() {
|
||||
if (window.h5HistoryLayerManager.stack.length) {
|
||||
window.h5HistoryLayerManager.close()
|
||||
return
|
||||
}
|
||||
this.historyBack()
|
||||
},
|
||||
// 活动接口接收年度,返回 id、name 组成的活动列表;完成后触发首次作品查询。
|
||||
listActivity() {
|
||||
return this.$axios.post('/platform/activity/worksCollection/common/listActivity', {
|
||||
year: this.pageForm.year
|
||||
}, {
|
||||
h5SkeletonLoading: true
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const options = (res.data || []).map((item) => {
|
||||
return {text: item.name, value: item.id}
|
||||
})
|
||||
this.$set(this, 'activityOptions', options)
|
||||
this.$set(this.pageForm, 'activityId', options.length > 0 ? options[0].value : '')
|
||||
}
|
||||
})
|
||||
},
|
||||
onReady() {
|
||||
this.listActivity().then(() => {
|
||||
this.doSearch()
|
||||
})
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$set(this.pageForm, 'pageNumber', 1)
|
||||
this.$set(this.pageForm, 'totalCount', 0)
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
window.h5HistoryLayerManager.register(this.historyLayerPageKey, null)
|
||||
},
|
||||
beforeDestroy() {
|
||||
Object.keys(this.likeHeartEffectTimers).forEach((rowId) => {
|
||||
clearTimeout(this.likeHeartEffectTimers[rowId])
|
||||
})
|
||||
window.h5HistoryLayerManager.unregister(this.historyLayerPageKey)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
+532
-166
@@ -1,191 +1,557 @@
|
||||
const applyForm = {
|
||||
template:
|
||||
/*language=HTML*/
|
||||
`
|
||||
template: /*language=HTML*/ `
|
||||
<div>
|
||||
<van-action-sheet v-model="visible" :style="{ 'background-color': '#F7F8FA' }" title="报名信息">
|
||||
<van-form ref="formRef" class="form-container">
|
||||
<van-cell-group title="基础信息" class="form-section">
|
||||
<van-field label="姓名" readonly v-model="formData.username"></van-field>
|
||||
<van-field label="工号" readonly v-model="formData.loginname"></van-field>
|
||||
<van-field label="所在单位" readonly v-model="formData.unitName"></van-field>
|
||||
<van-field label="所属工会" readonly v-model="formData.unionName"></van-field>
|
||||
<van-field label="性别" readonly v-model="formData.sex"></van-field>
|
||||
</van-cell-group>
|
||||
<van-cell-group title="报名信息" class="form-section">
|
||||
<van-field label="主题类型"
|
||||
required
|
||||
:rules="[{ required: true, message: '请选择主题类型' }]"
|
||||
readonly
|
||||
is-link
|
||||
@click="showSubjectPicker = true"
|
||||
placeholder="请选择主题类型"
|
||||
name="subjectName"
|
||||
v-model="formData.subjectName">
|
||||
</van-field>
|
||||
<van-popup v-model="showSubjectPicker" position="bottom">
|
||||
<van-picker
|
||||
show-toolbar
|
||||
:columns="subjectTypesOptions.map(v=>v.typeName)"
|
||||
@confirm="onSubjectConfirm"
|
||||
@cancel="showSubjectPicker=false"
|
||||
></van-picker>
|
||||
</van-popup>
|
||||
<van-popup class="works-apply-popup" :style="{height: '100%', width: '100%'}" position="right"
|
||||
safe-area-inset-bottom :close-on-click-overlay="false" v-model="visible">
|
||||
<div class="works-apply-page">
|
||||
<van-sticky>
|
||||
<van-nav-bar title="作品提交" left-text="返回" left-arrow @click-left="closeApply"></van-nav-bar>
|
||||
</van-sticky>
|
||||
<van-form ref="formRef" class="works-apply-form form-container">
|
||||
<div ref="applyScrollRef" class="works-apply-scroll">
|
||||
<section class="works-apply-section">
|
||||
<h2 class="works-apply-section__title">基础信息</h2>
|
||||
<van-cell-group :border="false">
|
||||
<van-field label="姓名" readonly v-model="formData.username"></van-field>
|
||||
<van-field label="工号" readonly v-model="formData.loginname"></van-field>
|
||||
<van-field label="所在单位" readonly v-model="formData.unitName"></van-field>
|
||||
<van-field label="所属工会" readonly v-model="formData.unionName"></van-field>
|
||||
<van-field label="性别" readonly v-model="formData.sex"></van-field>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
|
||||
<van-field label="作品类型"
|
||||
required
|
||||
:rules="[{ required: true, message: '请选择作品类型' }]"
|
||||
readonly
|
||||
is-link
|
||||
@click="showWorksPicker = true"
|
||||
placeholder="请选择作品类型"
|
||||
name="worksName"
|
||||
v-model="formData.worksName">
|
||||
</van-field>
|
||||
<van-popup v-model="showWorksPicker" position="bottom">
|
||||
<van-picker
|
||||
show-toolbar
|
||||
:columns="worksTypeOptions.map(v=>v.worksTypeName)"
|
||||
@confirm="onWorksConfirm"
|
||||
@cancel="showWorksPicker=false"
|
||||
></van-picker>
|
||||
</van-popup>
|
||||
<section class="works-apply-section">
|
||||
<h2 class="works-apply-section__title">作品信息</h2>
|
||||
<van-cell-group :border="false">
|
||||
<van-field label="主题类型" required readonly is-link name="subjectName"
|
||||
placeholder="请选择主题类型" :rules="[{required: true, message: '请选择主题类型'}]"
|
||||
v-model="formData.subjectName" @click="openSubjectPicker"></van-field>
|
||||
<van-field label="作品类型" required readonly is-link name="worksName"
|
||||
placeholder="请先选择主题类型" :rules="[{required: true, message: '请选择作品类型'}]"
|
||||
v-model="formData.worksName" @click="openWorksPicker"></van-field>
|
||||
<van-field label="作品名称" required name="name" maxlength="100" show-word-limit
|
||||
placeholder="请填写作品名称" :rules="[{required: true, message: '请填写作品名称'}]"
|
||||
v-model="formData.name"></van-field>
|
||||
<van-field class="more-text" label="作品描述" required type="textarea" name="description"
|
||||
rows="4" autosize show-word-limit :maxlength="descriptionMaxLength"
|
||||
placeholder="请填写作品描述" :rules="[{required: true, message: '请填写作品描述'}]"
|
||||
v-model="formData.description"></van-field>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
|
||||
<van-field label="作品名称"
|
||||
required
|
||||
v-model="formData.name"
|
||||
name="name"
|
||||
placeholder="请填写作品名称"
|
||||
:rules="[{ required: true, message: '请填写作品名称' }]"></van-field>
|
||||
<van-field label="作品描述"
|
||||
v-model="formData.description"
|
||||
type="textarea"
|
||||
name="description"
|
||||
rows="4"
|
||||
autosize
|
||||
maxlength="150"
|
||||
:rules="[{ required: true, message: '请填写作品描述' }]"
|
||||
class="more-text"
|
||||
placeholder="请填写作品描述"></van-field>
|
||||
</van-cell-group>
|
||||
<van-cell-group title="附件">
|
||||
<van-field class="more-text"
|
||||
name="files"
|
||||
:rules="[{ required: true,message:'请上传附件' }]"
|
||||
label=""
|
||||
required>
|
||||
<template #input>
|
||||
<h5-file-upload
|
||||
slot="input"
|
||||
:value.sync="formData.files"
|
||||
:upload_number="chooseWorksType && chooseWorksType.allowFileNum"
|
||||
upload_mode="file"
|
||||
upload_result_category="array"
|
||||
upload_result_type="url"
|
||||
complete_result
|
||||
:accept="fileAccept"
|
||||
></h5-file-upload>
|
||||
</template>
|
||||
</van-field>
|
||||
</van-cell-group>
|
||||
<section class="works-apply-section">
|
||||
<h2 class="works-apply-section__title">作品附件</h2>
|
||||
<div class="works-apply-section__hint">附件说明:请根据所选作品类型上传符合要求的文件</div>
|
||||
<van-cell-group :border="false">
|
||||
<van-field class="more-text works-apply-upload-field" name="files" label="" required
|
||||
:rules="[{required: true, message: '请上传附件'}]">
|
||||
<template #input>
|
||||
<h5-file-upload slot="input" :value.sync="formData.files"
|
||||
:upload_number="chooseWorksType && chooseWorksType.allowFileNum"
|
||||
upload_mode="file" upload_result_category="array"
|
||||
upload_result_type="url" complete_result :accept="fileAccept">
|
||||
</h5-file-upload>
|
||||
</template>
|
||||
</van-field>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
</div>
|
||||
<div class="works-apply-footer">
|
||||
<van-button type="primary" block round :loading="formLoading" loading-text="提交中..."
|
||||
@click="onSubmit">提交作品</van-button>
|
||||
</div>
|
||||
</van-form>
|
||||
</div>
|
||||
</van-popup>
|
||||
|
||||
<div class="form-actions">
|
||||
<van-button @click="onSubmit" round type="info">提交</van-button>
|
||||
</div>
|
||||
</van-form>
|
||||
|
||||
</van-action-sheet>
|
||||
<van-popup class="works-option-popup" v-model="showOptionPicker" position="bottom" round
|
||||
:close-on-click-overlay="false">
|
||||
<div class="works-option-popup__header">
|
||||
<button type="button" class="works-option-popup__action" @click="cancelOptionPopup">取消</button>
|
||||
<div class="works-option-popup__title">{{optionPopupTitle}}</div>
|
||||
<button type="button" class="works-option-popup__action"
|
||||
:disabled="pendingOptionValue === null || pendingOptionValue === undefined || pendingOptionValue === ''"
|
||||
@click="confirmOptionPopup">确认</button>
|
||||
</div>
|
||||
<div class="works-option-popup__list">
|
||||
<div v-if="optionPopupOptions.length === 0" class="works-option-popup__empty">暂无可选内容</div>
|
||||
<button v-for="option in optionPopupOptions" :key="option.value" type="button"
|
||||
class="works-option-popup__option"
|
||||
:class="{'is-selected': pendingOptionValue === option.value}"
|
||||
:aria-pressed="pendingOptionValue === option.value"
|
||||
@click="selectOptionPopupItem(option)">
|
||||
<span class="works-option-popup__option-text">{{option.text}}</span>
|
||||
</button>
|
||||
</div>
|
||||
</van-popup>
|
||||
<van-dialog class="works-apply-confirm" title="提交确认" message="确认提交当前作品信息吗?"
|
||||
:value="submitConfirmVisible" :close-on-click-overlay="false" show-cancel-button
|
||||
cancel-button-text="取消" confirm-button-text="确认提交"
|
||||
@cancel="closeSubmitConfirm" @confirm="confirmSubmit"></van-dialog>
|
||||
</div>
|
||||
`,
|
||||
style: /*language=CSS*/ `
|
||||
/deep/ .works-apply-popup {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
/deep/ .works-apply-page {
|
||||
position: relative;
|
||||
min-height: 100vh;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
/deep/ .works-apply-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
/deep/ .works-apply-page .van-nav-bar__title {
|
||||
color: #1f2937;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/deep/ .works-apply-page .van-nav-bar .van-icon,
|
||||
/deep/ .works-apply-page .van-nav-bar__text {
|
||||
color: #397fbd;
|
||||
}
|
||||
|
||||
/deep/ .works-apply-form.form-container {
|
||||
min-height: 100%;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
background: #f3f7fc;
|
||||
}
|
||||
|
||||
/deep/ .works-apply-scroll {
|
||||
height: calc(100vh - 46px);
|
||||
padding: 12px 15px calc(84px + env(safe-area-inset-bottom));
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
background: #f3f7fc;
|
||||
}
|
||||
|
||||
/deep/ .works-apply-section {
|
||||
margin-bottom: 11px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #e9eff7;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
box-shadow: 0 3px 11px rgba(51, 87, 126, .08);
|
||||
}
|
||||
|
||||
/deep/ .works-apply-section__title {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
padding: 12px 14px 8px 21px;
|
||||
color: #354255;
|
||||
font-size: 15px;
|
||||
line-height: 20px;
|
||||
font-weight: 600;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/deep/ .works-apply-section__title::before {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
bottom: 11px;
|
||||
left: 12px;
|
||||
width: 2px;
|
||||
border-radius: 2px;
|
||||
background: #1989fa;
|
||||
content: "";
|
||||
}
|
||||
|
||||
/deep/ .works-apply-section__hint {
|
||||
padding: 0 14px 8px 21px;
|
||||
color: orangered;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/deep/ .works-apply-section .van-cell-group {
|
||||
margin: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/deep/ .works-apply-section .van-cell {
|
||||
min-height: 44px;
|
||||
padding: 10px 14px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/deep/ .works-apply-section .van-cell:not(:last-child)::after {
|
||||
right: 14px;
|
||||
left: 14px;
|
||||
border-color: #eef2f7;
|
||||
}
|
||||
|
||||
/deep/ .works-apply-section .van-field__label {
|
||||
width: 84px;
|
||||
color: #596779;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
/deep/ .works-apply-section .van-field__value,
|
||||
/deep/ .works-apply-section .van-field__control {
|
||||
color: #4f5d70;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
/deep/ .works-apply-section .van-field__control::placeholder {
|
||||
color: #b1bac6;
|
||||
}
|
||||
|
||||
/deep/ .works-apply-section .van-cell--required::before {
|
||||
left: 6px;
|
||||
color: #f06464;
|
||||
}
|
||||
|
||||
/deep/ .works-apply-upload-field .van-field__value {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/deep/ .works-apply-footer {
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
padding: 10px 18px calc(10px + env(safe-area-inset-bottom));
|
||||
border-top: 1px solid #edf1f6;
|
||||
background: rgba(255, 255, 255, .98);
|
||||
box-shadow: 0 -4px 14px rgba(50, 78, 112, .06);
|
||||
}
|
||||
|
||||
/deep/ .works-apply-footer .van-button {
|
||||
flex: 1;
|
||||
height: 40px;
|
||||
margin: 0;
|
||||
border-color: #1989fa;
|
||||
border-radius: 14px !important;
|
||||
font-size: 16px;
|
||||
background: #1989fa;
|
||||
}
|
||||
|
||||
/deep/ .works-option-popup {
|
||||
display: flex;
|
||||
height: 50%;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background: #f5f7fa;
|
||||
}
|
||||
|
||||
/deep/ .works-option-popup__header {
|
||||
display: flex;
|
||||
min-height: 52px;
|
||||
padding: 0 16px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex: none;
|
||||
border-bottom: 1px solid #edf1f6;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
/deep/ .works-option-popup__title {
|
||||
color: #263548;
|
||||
font-size: 17px;
|
||||
line-height: 24px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/deep/ .works-option-popup__action {
|
||||
min-width: 48px;
|
||||
padding: 8px 0;
|
||||
border: 0;
|
||||
color: #1989fa;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
text-align: left;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/deep/ .works-option-popup__action:last-child {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/deep/ .works-option-popup__action:disabled {
|
||||
color: #b7c0cc;
|
||||
}
|
||||
|
||||
/deep/ .works-option-popup__list {
|
||||
min-height: 0;
|
||||
padding: 12px;
|
||||
overflow-y: auto;
|
||||
flex: 1;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
/deep/ .works-option-popup__empty {
|
||||
padding: 44px 18px;
|
||||
color: #98a4b3;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/deep/ .works-option-popup__option {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
min-height: 58px;
|
||||
margin-bottom: 10px;
|
||||
padding: 12px 14px;
|
||||
align-items: center;
|
||||
border: 1px solid #e3e9f1;
|
||||
border-radius: 10px;
|
||||
color: #536174;
|
||||
text-align: left;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
/deep/ .works-option-popup__option:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/deep/ .works-option-popup__option.is-selected {
|
||||
border-color: #1989fa;
|
||||
color: #176fbd;
|
||||
background: #eef7ff;
|
||||
box-shadow: 0 3px 10px rgba(25, 137, 250, .1);
|
||||
}
|
||||
|
||||
/deep/ .works-option-popup__option-text {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
font-size: 15px;
|
||||
line-height: 23px;
|
||||
word-break: break-word;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
/deep/ .works-apply-confirm .van-dialog__header {
|
||||
color: #263548;
|
||||
font-size: 17px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/deep/ .works-apply-confirm .van-dialog__message {
|
||||
padding: 24px 20px;
|
||||
color: #536174;
|
||||
font-size: 15px;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
`,
|
||||
data() {
|
||||
return {
|
||||
row: {},
|
||||
visible: false,
|
||||
formData: {},
|
||||
subjectTypesOptions: [],
|
||||
showSubjectPicker: false,
|
||||
|
||||
worksTypeOptions: [],
|
||||
showWorksPicker: false,
|
||||
|
||||
fileAccept: null,
|
||||
chooseWorksType: {}
|
||||
row: {}, visible: false, formData: {}, formLoading: false,
|
||||
subjectTypesOptions: [], worksTypeOptions: [],
|
||||
showOptionPicker: false, optionPopupType: "", optionPopupTitle: "",
|
||||
optionPopupOptions: [], pendingOptionValue: "",
|
||||
submitConfirmVisible: false, fileAccept: null, chooseWorksType: {},
|
||||
submitSuccessMode: "navigate",
|
||||
historyLayerPageKey: "works-collection-upload-h5",
|
||||
historyLayerUnsubscribe: null, ownsHistoryRegistration: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
descriptionMaxLength() {
|
||||
return this.chooseWorksType && this.chooseWorksType.maxWordCount ? this.chooseWorksType.maxWordCount : 150
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async onOpen(row) {
|
||||
this.$set(this.formData, 'username', this.$store.state.user.username)
|
||||
this.$set(this.formData, 'loginname', this.$store.state.user.loginname)
|
||||
this.$set(this.formData, 'unionName', this.$store.state.user.union.name)
|
||||
this.$set(this.formData, 'unitName', this.$store.state.user.unit.name)
|
||||
this.$set(this.formData, 'sex', this.$store.state.user.sex)
|
||||
this.$set(this.formData, 'activityId', row.id)
|
||||
await this.activityChange(row.id)
|
||||
this.row = row
|
||||
this.visible = true
|
||||
resetFormData() {
|
||||
const user = this.$store.state.user || {}
|
||||
const union = user.union || {}
|
||||
const unit = user.unit || {}
|
||||
this.$set(this, "formData", {})
|
||||
this.$set(this.formData, "username", user.username)
|
||||
this.$set(this.formData, "loginname", user.loginname)
|
||||
this.$set(this.formData, "unionName", union.name)
|
||||
this.$set(this.formData, "unitName", unit.name)
|
||||
this.$set(this.formData, "sex", user.sex)
|
||||
this.$set(this.formData, "files", [])
|
||||
this.$set(this, "subjectTypesOptions", [])
|
||||
this.$set(this, "worksTypeOptions", [])
|
||||
this.$set(this, "chooseWorksType", {})
|
||||
this.$set(this, "fileAccept", null)
|
||||
},
|
||||
async onOpenEdit(row) {
|
||||
onOpen(row) {
|
||||
this.resetFormData()
|
||||
this.$set(this, "submitSuccessMode", "navigate")
|
||||
this.$set(this, "row", row)
|
||||
this.$set(this.formData, "activityId", row.id)
|
||||
this.activityChange(row.id).then(() => {
|
||||
window.h5HistoryLayerManager.open("works-collection-apply")
|
||||
this.resetScrollPosition()
|
||||
})
|
||||
},
|
||||
onOpenEdit(row) {
|
||||
const formData = clone(row)
|
||||
formData.files = JSON.parse(formData.files)
|
||||
await this.activityChange(formData.activityId)
|
||||
await this.subjectChange(formData.subjectId)
|
||||
this.row = formData
|
||||
this.formData = formData
|
||||
this.$set(this.formData, 'username', this.$store.state.user.username)
|
||||
this.$set(this.formData, 'loginname', this.$store.state.user.loginname)
|
||||
this.$set(this.formData, 'sex', this.$store.state.user.sex)
|
||||
this.chooseWorksType = this.worksTypeOptions.find((o) => o.id === formData.worksId)
|
||||
if (this.chooseWorksType.allowFileTypes && this.chooseWorksType.allowFileTypes.length > 0) {
|
||||
this.fileAccept = this.chooseWorksType.allowFileTypes.map((item) => "." + item).join(",")
|
||||
}
|
||||
this.visible = true
|
||||
formData.files = this.normalizeFiles(formData.files)
|
||||
this.resetFormData()
|
||||
this.$set(this, "submitSuccessMode", "close")
|
||||
this.$set(this, "row", formData)
|
||||
this.$set(this, "formData", formData)
|
||||
const user = this.$store.state.user || {}
|
||||
this.$set(this.formData, "username", user.username)
|
||||
this.$set(this.formData, "loginname", user.loginname)
|
||||
this.$set(this.formData, "sex", user.sex)
|
||||
this.activityChange(formData.activityId).then(() => {
|
||||
// 编辑时以主题主键匹配当前活动配置,避免列表未携带主题名称时无法回显。
|
||||
const subjectType = this.subjectTypesOptions.find((item) => item.id === formData.subjectId)
|
||||
if (subjectType) this.$set(this.formData, "subjectName", subjectType.typeName)
|
||||
return this.subjectChange(formData.subjectId)
|
||||
}).then(() => {
|
||||
this.setSelectedWorksType(formData.worksId)
|
||||
window.h5HistoryLayerManager.open("works-collection-apply")
|
||||
this.resetScrollPosition()
|
||||
})
|
||||
},
|
||||
onWorksConfirm(value, index) {
|
||||
this.$set(this.formData, 'worksName', value)
|
||||
this.$set(this.formData, 'worksId', this.worksTypeOptions[index].id)
|
||||
this.showWorksPicker = false
|
||||
this.chooseWorksType = this.worksTypeOptions.find((o) => o.id === this.worksTypeOptions[index].id)
|
||||
if (this.chooseWorksType.allowFileTypes && this.chooseWorksType.allowFileTypes.length > 0) {
|
||||
this.fileAccept = this.chooseWorksType.allowFileTypes.map((item) => "." + item).join(",")
|
||||
// 表单弹窗会被复用,每次打开后需清除上一次编辑或提交时保留的滚动位置。
|
||||
resetScrollPosition() {
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.applyScrollRef) this.$refs.applyScrollRef.scrollTop = 0
|
||||
})
|
||||
},
|
||||
// 附件可能由列表 SQL 返回 JSON 字符串,也可能已被序列化为数组;统一转换为上传组件需要的数组。
|
||||
normalizeFiles(files) {
|
||||
if (Array.isArray(files)) return files
|
||||
if (!files) return []
|
||||
try {
|
||||
const result = JSON.parse(files)
|
||||
return Array.isArray(result) ? result : []
|
||||
} catch (err) {
|
||||
return []
|
||||
}
|
||||
},
|
||||
async onSubjectConfirm(value, index) {
|
||||
this.$set(this.formData, 'subjectName', value)
|
||||
this.$set(this.formData, 'subjectId', this.subjectTypesOptions[index].id)
|
||||
await this.subjectChange(this.subjectTypesOptions[index].id)
|
||||
this.showSubjectPicker = false
|
||||
closeApply() { window.h5HistoryLayerManager.close("works-collection-apply") },
|
||||
// 打开统一选择弹框:主题选项由活动配置提供,确认后再写入表单。
|
||||
openSubjectPicker() {
|
||||
this.$set(this, "optionPopupType", "subject")
|
||||
this.$set(this, "optionPopupTitle", "选择主题类型")
|
||||
this.$set(this, "optionPopupOptions", this.subjectTypesOptions.map((item) => {
|
||||
return {value: item.id, text: item.typeName, source: item}
|
||||
}))
|
||||
this.$set(this, "pendingOptionValue", this.formData.subjectId || "")
|
||||
window.h5HistoryLayerManager.open("works-collection-option-picker")
|
||||
},
|
||||
openWorksPicker() {
|
||||
if (!this.formData.subjectId) {
|
||||
this.$toast("请先选择主题类型")
|
||||
return
|
||||
}
|
||||
this.$set(this, "optionPopupType", "works")
|
||||
this.$set(this, "optionPopupTitle", "选择作品类型")
|
||||
this.$set(this, "optionPopupOptions", this.worksTypeOptions.map((item) => {
|
||||
return {value: item.id, text: item.worksTypeName, source: item}
|
||||
}))
|
||||
this.$set(this, "pendingOptionValue", this.formData.worksId || "")
|
||||
window.h5HistoryLayerManager.open("works-collection-option-picker")
|
||||
},
|
||||
cancelOptionPopup() { window.h5HistoryLayerManager.close("works-collection-option-picker") },
|
||||
selectOptionPopupItem(option) { this.$set(this, "pendingOptionValue", option.value) },
|
||||
/**
|
||||
* 确认类型选项并回填作品表单。
|
||||
* optionPopupType 为 subject 或 works,pendingOptionValue 为对应业务主键;方法无返回值。
|
||||
*/
|
||||
confirmOptionPopup() {
|
||||
const selectedOption = this.optionPopupOptions.find((item) => {
|
||||
return item.value === this.pendingOptionValue
|
||||
})
|
||||
if (!selectedOption) return
|
||||
if (this.optionPopupType === "subject") {
|
||||
this.onSubjectConfirm(selectedOption)
|
||||
return
|
||||
}
|
||||
this.onWorksConfirm(selectedOption)
|
||||
},
|
||||
onWorksConfirm(selectedOption) {
|
||||
this.$set(this.formData, "worksName", selectedOption.text)
|
||||
this.$set(this.formData, "worksId", selectedOption.value)
|
||||
this.setSelectedWorksType(selectedOption.value)
|
||||
this.cancelOptionPopup()
|
||||
},
|
||||
onSubjectConfirm(selectedOption) {
|
||||
this.$set(this.formData, "subjectName", selectedOption.text)
|
||||
this.$set(this.formData, "subjectId", selectedOption.value)
|
||||
this.$set(this.formData, "worksName", "")
|
||||
this.$set(this.formData, "worksId", "")
|
||||
this.$set(this.formData, "files", [])
|
||||
this.$set(this, "chooseWorksType", {})
|
||||
this.$set(this, "fileAccept", null)
|
||||
this.subjectChange(selectedOption.value).then(() => { this.cancelOptionPopup() })
|
||||
},
|
||||
setSelectedWorksType(worksId) {
|
||||
const worksType = this.worksTypeOptions.find((item) => item.id === worksId) || {}
|
||||
this.$set(this, "chooseWorksType", worksType)
|
||||
if (worksType.allowFileTypes && worksType.allowFileTypes.length > 0) {
|
||||
this.$set(this, "fileAccept", worksType.allowFileTypes.map((item) => "." + item).join(","))
|
||||
return
|
||||
}
|
||||
this.$set(this, "fileAccept", null)
|
||||
},
|
||||
onSubmit() {
|
||||
this.$refs.formRef.validate().then(() => {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
this.$toast.loading({
|
||||
message: '提交中...',
|
||||
forbidClick: true,
|
||||
});
|
||||
this.$axios.post("/platform/activity/worksCollection/upload" + (this.formData.id ? "/update" : "/insert"), {data: JSON.stringify(this.formData)}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.clear();
|
||||
this.$toast.success("提交成功")
|
||||
pjaxReplace("/platform/activity/worksCollection/mine/h5")
|
||||
}
|
||||
})
|
||||
})
|
||||
}).catch();
|
||||
window.h5HistoryLayerManager.open("works-collection-submit-confirm")
|
||||
}).catch(() => {
|
||||
// 表单校验失败时由字段规则直接展示提示,不进入提交确认。
|
||||
})
|
||||
},
|
||||
async activityChange(value) {
|
||||
const resp = await this.$axios.post("/platform/activity/worksCollection/common/getSubjectTypes", {activityId: value})
|
||||
if (resp.code === 0) {
|
||||
this.subjectTypesOptions = resp.data
|
||||
}
|
||||
closeSubmitConfirm() { window.h5HistoryLayerManager.close("works-collection-submit-confirm") },
|
||||
confirmSubmit() {
|
||||
window.h5HistoryLayerManager.close("works-collection-submit-confirm", () => { this.submitForm() })
|
||||
},
|
||||
async subjectChange(value) {
|
||||
const resp = await this.$axios.post("/platform/activity/worksCollection/common/getWorksTypes", {subjectId: value})
|
||||
if (resp.code === 0) {
|
||||
this.worksTypeOptions = resp.data
|
||||
}
|
||||
submitForm() {
|
||||
this.$set(this, "formLoading", true)
|
||||
this.$axios.post("/platform/activity/worksCollection/upload" + (this.formData.id ? "/update" : "/insert"), {
|
||||
data: JSON.stringify(this.formData)
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.success("提交成功")
|
||||
if (this.submitSuccessMode === "close") {
|
||||
// 我的作品页使用弹窗编辑,成功后只关闭当前表单并通知父页面刷新列表。
|
||||
window.h5HistoryLayerManager.close("works-collection-apply", () => {
|
||||
this.$emit("submit-success")
|
||||
})
|
||||
return
|
||||
}
|
||||
window.h5HistoryLayerManager.closeAllAndNavigate("/platform/activity/worksCollection/mine/h5")
|
||||
}
|
||||
}).finally(() => { this.$set(this, "formLoading", false) })
|
||||
},
|
||||
activityChange(value) {
|
||||
return this.$axios.post("/platform/activity/worksCollection/common/getSubjectTypes", {activityId: value}).then((res) => {
|
||||
if (res.code === 0) this.$set(this, "subjectTypesOptions", res.data || [])
|
||||
})
|
||||
},
|
||||
subjectChange(value) {
|
||||
return this.$axios.post("/platform/activity/worksCollection/common/getWorksTypes", {subjectId: value}).then((res) => {
|
||||
if (res.code === 0) this.$set(this, "worksTypeOptions", res.data || [])
|
||||
})
|
||||
},
|
||||
syncHistoryLayers(stack) {
|
||||
this.$set(this, "visible", stack.includes("works-collection-apply"))
|
||||
this.$set(this, "showOptionPicker", stack.includes("works-collection-option-picker"))
|
||||
this.$set(this, "submitConfirmVisible", stack.includes("works-collection-submit-confirm"))
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (!window.h5HistoryLayerManager.pageKey) {
|
||||
window.h5HistoryLayerManager.ensureRegistered(this.historyLayerPageKey)
|
||||
this.$set(this, "ownsHistoryRegistration", true)
|
||||
}
|
||||
this.$set(this, "historyLayerUnsubscribe", window.h5HistoryLayerManager.subscribe((stack) => {
|
||||
this.syncHistoryLayers(stack)
|
||||
}))
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.historyLayerUnsubscribe) this.historyLayerUnsubscribe()
|
||||
if (this.ownsHistoryRegistration) window.h5HistoryLayerManager.unregister(this.historyLayerPageKey)
|
||||
}
|
||||
}
|
||||
|
||||
+765
-97
@@ -1,108 +1,690 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<style scoped>
|
||||
.info-title {
|
||||
font-weight: bold;
|
||||
background-color: white;
|
||||
padding: 13px;
|
||||
box-shadow: 0 8px 12px #ebedf0;
|
||||
text-align: center !important;
|
||||
|
||||
<style>
|
||||
body {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.info-container {
|
||||
height: calc(100vh - 46px - 44px);
|
||||
min-height: calc(100vh - 46px - 44px);
|
||||
overflow-y: auto;
|
||||
.works-collection-page {
|
||||
min-height: 100vh;
|
||||
padding-bottom: calc(24px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.info-img {
|
||||
display: block;
|
||||
.works-collection-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.van-count-down {
|
||||
.works-collection-page .van-nav-bar__title {
|
||||
color: #1f2937;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.works-collection-page .van-nav-bar .van-icon,
|
||||
.works-collection-page .van-nav-bar__text {
|
||||
color: #397fbd;
|
||||
}
|
||||
|
||||
.works-collection-content {
|
||||
padding: 12px 12px 0;
|
||||
}
|
||||
|
||||
.works-collection-hero {
|
||||
position: relative;
|
||||
height: 134px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
color: #fff;
|
||||
background-color: #247fe8;
|
||||
box-shadow: 0 8px 20px rgba(51, 117, 219, .18);
|
||||
}
|
||||
|
||||
.works-collection-hero__image {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
|
||||
.works-collection-hero__copy {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
width: 64%;
|
||||
height: 100%;
|
||||
padding-left: 16px;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
background: linear-gradient(90deg, rgba(22, 112, 232, .98) 0%, rgba(22, 112, 232, .88) 52%, rgba(22, 112, 232, 0) 100%);
|
||||
}
|
||||
|
||||
.works-collection-hero__title {
|
||||
font-size: 25px;
|
||||
line-height: 34px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 1px;
|
||||
text-shadow: 0 2px 6px rgba(17, 86, 182, .18);
|
||||
}
|
||||
|
||||
.works-collection-hero__subtitle {
|
||||
margin-top: 4px;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
letter-spacing: .5px;
|
||||
opacity: .95;
|
||||
}
|
||||
|
||||
.works-collection-sticky {
|
||||
padding: 10px 0 1px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.van-sticky--fixed .works-collection-sticky {
|
||||
padding-right: 12px;
|
||||
padding-left: 12px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.works-collection-search {
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.works-collection-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.works-collection-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.works-collection-search .van-field__control::placeholder {
|
||||
color: #a7b0bf;
|
||||
}
|
||||
|
||||
.works-collection-filter {
|
||||
margin: 0 0 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
transition: border-radius .18s ease;
|
||||
}
|
||||
|
||||
.works-collection-filter.is-open {
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
.works-collection-filter .van-dropdown-menu__bar {
|
||||
height: 44px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.works-collection-filter .van-dropdown-menu__item {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.works-collection-filter .van-dropdown-menu__title {
|
||||
width: auto;
|
||||
max-width: calc(100% - 24px);
|
||||
padding: 0 12px 0 0;
|
||||
overflow: hidden;
|
||||
color: #66758a;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.works-collection-filter .van-dropdown-menu__title::after {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.works-collection-filter .van-dropdown-menu__title--active,
|
||||
.works-collection-filter .van-dropdown-item__option--active,
|
||||
.works-collection-filter .van-dropdown-item__option--active .van-dropdown-item__icon {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.works-collection-filter .van-dropdown-menu__title--down::after {
|
||||
border-color: transparent transparent #1989fa #1989fa;
|
||||
}
|
||||
|
||||
.works-collection-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
margin: 0 12px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0 0 12px 12px;
|
||||
box-shadow: 0 10px 24px rgba(31, 65, 108, .14);
|
||||
}
|
||||
|
||||
.works-collection-filter .van-dropdown-item__option {
|
||||
min-height: 48px;
|
||||
padding: 0 16px;
|
||||
color: #46566c;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.works-collection-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.works-collection-card {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.works-collection-card__cover,
|
||||
.works-collection-card__cover-state {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
background-color: #edf4fc;
|
||||
}
|
||||
|
||||
.works-collection-card__cover {
|
||||
display: block;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.works-collection-card__cover-state {
|
||||
flex-direction: column;
|
||||
row-gap: 8px;
|
||||
color: #8da1ba;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.works-collection-card__cover-state .van-icon {
|
||||
font-size: 34px;
|
||||
}
|
||||
|
||||
.works-collection-card__cover-state.is-error {
|
||||
color: #c27b75;
|
||||
background-color: #fff3f1;
|
||||
}
|
||||
|
||||
.works-collection-card__body {
|
||||
padding: 12px 38px 14px 14px;
|
||||
}
|
||||
|
||||
.works-collection-card__title {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
color: #303846;
|
||||
font-size: 14px;
|
||||
line-height: 21px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.works-collection-card__time {
|
||||
margin-top: 4px;
|
||||
overflow: hidden;
|
||||
color: #98a2b2;
|
||||
font-size: 12px;
|
||||
line-height: 17px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.works-collection-card__meta {
|
||||
display: flex;
|
||||
margin-top: 10px;
|
||||
padding-top: 9px;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
border-top: 1px solid #edf1f6;
|
||||
}
|
||||
|
||||
.works-collection-card__tag {
|
||||
display: inline-flex;
|
||||
padding: 3px 8px;
|
||||
align-items: center;
|
||||
border-radius: 4px;
|
||||
color: #397de0;
|
||||
background-color: #edf5ff;
|
||||
font-size: 11px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.works-collection-card__tag-label {
|
||||
margin-right: 4px;
|
||||
color: #8aa7cf;
|
||||
}
|
||||
|
||||
.works-collection-card__arrow {
|
||||
position: absolute;
|
||||
top: 164px;
|
||||
right: 14px;
|
||||
color: #b4bdca;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.works-collection-empty {
|
||||
display: flex;
|
||||
min-height: 260px;
|
||||
padding: 26px 18px 32px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.works-collection-empty img {
|
||||
display: block;
|
||||
width: 82%;
|
||||
max-width: 280px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.works-collection-empty__title {
|
||||
margin-top: 14px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.works-collection-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.works-collection-page .van-list__loading {
|
||||
color: #9aa7b8;
|
||||
font-size: 13px;
|
||||
line-height: 44px;
|
||||
}
|
||||
|
||||
.works-collection-skeleton {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.works-collection-skeleton__card {
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.works-collection-skeleton__cover,
|
||||
.works-collection-skeleton__body .van-skeleton {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.works-collection-skeleton__cover .van-skeleton__row {
|
||||
width: 100% !important;
|
||||
height: 150px;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.works-collection-skeleton__body {
|
||||
padding: 13px 14px 15px;
|
||||
}
|
||||
|
||||
.works-collection-skeleton__body .van-skeleton__title {
|
||||
width: 54%;
|
||||
height: 15px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.works-collection-skeleton__body .van-skeleton__row {
|
||||
height: 12px;
|
||||
margin-top: 9px;
|
||||
}
|
||||
|
||||
.works-collection-skeleton__body .van-skeleton__row:last-child {
|
||||
width: 46%;
|
||||
}
|
||||
|
||||
.works-intro-popup,
|
||||
.works-intro-page {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.works-intro-page {
|
||||
position: relative;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.works-intro-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.works-intro-page .van-nav-bar__title {
|
||||
color: #1f2937;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.works-intro-page .van-nav-bar .van-icon,
|
||||
.works-intro-page .van-nav-bar__text {
|
||||
color: #397fbd;
|
||||
}
|
||||
|
||||
.works-intro-scroll {
|
||||
height: calc(100vh - 46px);
|
||||
padding: 12px 12px calc(92px + env(safe-area-inset-bottom));
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.works-intro-hero {
|
||||
display: flex;
|
||||
min-height: 82px;
|
||||
padding: 16px;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
border-radius: 12px;
|
||||
color: #fff;
|
||||
background: linear-gradient(120deg, #2d7eea 0%, #5ba6f7 100%);
|
||||
box-shadow: 0 8px 20px rgba(45, 126, 234, .18);
|
||||
}
|
||||
|
||||
.works-intro-hero__icon {
|
||||
display: flex;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
margin-right: 12px;
|
||||
flex: 0 0 44px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 11px;
|
||||
color: #2d7eea;
|
||||
background-color: rgba(255, 255, 255, .92);
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.works-intro-hero__title {
|
||||
font-size: 17px;
|
||||
line-height: 24px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.works-intro-hero__subtitle {
|
||||
margin-top: 3px;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
.works-intro-card {
|
||||
margin-top: 12px;
|
||||
padding: 18px 16px;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.works-intro-content,
|
||||
.works-intro-content div,
|
||||
.works-intro-content p,
|
||||
.works-intro-content span,
|
||||
.works-intro-content li {
|
||||
color: #3f4c5e !important;
|
||||
font-size: 14px !important;
|
||||
line-height: 1.8 !important;
|
||||
white-space: normal;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.works-intro-content h1,
|
||||
.works-intro-content h2,
|
||||
.works-intro-content h3 {
|
||||
margin: 16px 0 10px !important;
|
||||
color: #1f2f43 !important;
|
||||
font-size: 19px !important;
|
||||
line-height: 1.5 !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
.works-intro-content > :first-child {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
.works-intro-content p {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 8px !important;
|
||||
}
|
||||
|
||||
.works-intro-content img {
|
||||
max-width: 100% !important;
|
||||
height: auto !important;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.works-intro-content table {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
overflow-x: auto;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.works-intro-empty {
|
||||
display: flex;
|
||||
min-height: 180px;
|
||||
margin-top: 12px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
row-gap: 10px;
|
||||
border-radius: 12px;
|
||||
color: #9aa7b8;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.works-intro-empty .van-icon {
|
||||
color: #83b5f4;
|
||||
font-size: 36px;
|
||||
}
|
||||
|
||||
.works-intro-footer {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 5;
|
||||
padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
|
||||
border-top: 1px solid #edf1f6;
|
||||
background-color: rgba(255, 255, 255, .96);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.works-intro-footer .van-button {
|
||||
height: 42px;
|
||||
border: 0;
|
||||
border-radius: 21px;
|
||||
font-size: 15px;
|
||||
background-color: #1989fa;
|
||||
box-shadow: 0 6px 16px rgba(25, 137, 250, .22);
|
||||
}
|
||||
|
||||
.works-intro-footer .van-button--disabled {
|
||||
color: #8b98aa !important;
|
||||
background-color: #eef2f7 !important;
|
||||
opacity: 1;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.works-intro-footer .van-count-down {
|
||||
display: inline-block;
|
||||
margin-left: 4px;
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
<div id="app">
|
||||
<!-- 导航栏 -->
|
||||
|
||||
<van-nav-bar title="作品上传" left-text="返回" left-arrow placeholder
|
||||
@click-left="historyBack" fixed></van-nav-bar>
|
||||
<div id="app" v-cloak>
|
||||
<div class="works-collection-page">
|
||||
<van-nav-bar title="作品征集" left-text="返回" left-arrow @click-left="handlePageBack" fixed placeholder></van-nav-bar>
|
||||
|
||||
<van-sticky offset-top="46px">
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<year-van-dropdown-item :num="5" @change="doSearch" v-model="pageForm.year"></year-van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.activityType" :options="typeOptions" :multiple="false"
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</van-sticky>
|
||||
<div class="works-collection-content">
|
||||
<section class="works-collection-hero">
|
||||
<img class="works-collection-hero__image" src="/assets/mobile/img/activity/hero/brand-hero-v2.png" alt="作品征集插画">
|
||||
<div class="works-collection-hero__copy">
|
||||
<div class="works-collection-hero__title">作品征集</div>
|
||||
<div class="works-collection-hero__subtitle">汇聚创意 · 展示风采</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<van-sticky :offset-top="46">
|
||||
<div class="works-collection-sticky">
|
||||
<van-search
|
||||
v-model="pageForm.searchKeyword"
|
||||
class="works-collection-search"
|
||||
placeholder="搜索作品征集活动"
|
||||
shape="round"
|
||||
clearable
|
||||
@search="doSearch"
|
||||
@clear="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu class="works-collection-filter" :class="{'is-open': filterOpened}" active-color="#1989fa">
|
||||
<year-van-dropdown-item :num="5" @change="doSearch" @open="onFilterOpen" @close="onFilterClose" v-model="pageForm.year"></year-van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.activityType" :options="typeOptions" :multiple="false" @change="doSearch" @open="onFilterOpen" @close="onFilterClose"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<table-list api="/platform/activity/worksCollection/upload/h5/activityPageData"
|
||||
:page_form.sync="pageForm"
|
||||
ref="tableListRef"
|
||||
title="name"
|
||||
img="cover"
|
||||
@ready="onReady"
|
||||
>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="面向对象">{{row.activityGroupName}}</table-column>
|
||||
<table-column label="报名时间">
|
||||
{{$moment(row.startDateTime).format('MM/DD HH:mm')
|
||||
+ '~' + $moment(row.endDateTime).format('MM/DD HH:mm')}}
|
||||
</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span>查看介绍</span>
|
||||
<div v-if="skeletonLoading" class="works-collection-skeleton">
|
||||
<div v-for="index in 3" :key="'upload-skeleton-' + index" class="works-collection-skeleton__card">
|
||||
<van-skeleton class="works-collection-skeleton__cover" :row="1" animated></van-skeleton>
|
||||
<div class="works-collection-skeleton__body">
|
||||
<van-skeleton title :row="2" animated></van-skeleton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="action-btn" @click="onApply(row)">
|
||||
<i class="fa fa-edit"></i>
|
||||
<span>去报名</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
|
||||
<van-action-sheet v-model="infoVisible" title="详细信息">
|
||||
<div class="info-container">
|
||||
<van-image class="info-img" height="186" width="100%" :src="infoRow.cover"></van-image>
|
||||
<div class="info-title">{{infoRow.name}}</div>
|
||||
<pdf-preview style="height: calc(100vh - 46px - 44px - 186px - 57px)"
|
||||
:content="infoRow.content"></pdf-preview>
|
||||
<van-pull-refresh v-show="!skeletonLoading" v-model="refreshing" @refresh="onRefresh">
|
||||
<van-list v-model="loading" :finished="finished" :immediate-check="false" @load="onLoad">
|
||||
<div class="works-collection-list">
|
||||
<div v-for="row in tableData" :key="row.id" class="works-collection-card" @click="onView(row)">
|
||||
<img
|
||||
v-if="hasCover(row) && !imageLoadErrors[row.id]"
|
||||
class="works-collection-card__cover"
|
||||
:src="row.cover"
|
||||
:alt="row.name"
|
||||
@error="handleImageError(row)"
|
||||
>
|
||||
<div v-else class="works-collection-card__cover-state" :class="{'is-error': hasCover(row)}">
|
||||
<van-icon name="photo-o"></van-icon>
|
||||
<span>{{ hasCover(row) ? '图片加载失败' : '暂无图片' }}</span>
|
||||
</div>
|
||||
<div class="works-collection-card__body">
|
||||
<div class="works-collection-card__title">{{ row.name }}</div>
|
||||
<div class="works-collection-card__time" v-if="row.startDateTime && row.endDateTime">
|
||||
征集时间:{{ $moment(row.startDateTime).format('MM/DD HH:mm') }}~{{ $moment(row.endDateTime).format('MM/DD HH:mm') }}
|
||||
</div>
|
||||
<div class="works-collection-card__meta" v-if="row.activityGroupName">
|
||||
<span class="works-collection-card__tag" v-if="row.activityGroupName">
|
||||
<span class="works-collection-card__tag-label">面向对象</span>{{ row.activityGroupName }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<van-icon class="works-collection-card__arrow" name="arrow"></van-icon>
|
||||
</div>
|
||||
</div>
|
||||
</van-list>
|
||||
<div v-if="!loading && tableData.length === 0" class="works-collection-empty">
|
||||
<img src="/assets/mobile/img/activity/culture-empty.png" alt="作品征集空状态插画">
|
||||
<div class="works-collection-empty__title">暂无作品征集活动</div>
|
||||
<div class="works-collection-empty__hint">当前筛选条件下暂时没有可展示的活动</div>
|
||||
</div>
|
||||
</van-pull-refresh>
|
||||
</div>
|
||||
<div class="form-container">
|
||||
<div class="form-actions">
|
||||
</div>
|
||||
|
||||
<van-button @click="onApply(infoRow)" type="primary" block>
|
||||
<span v-if="time >= 0">
|
||||
去报名
|
||||
</span>
|
||||
<template v-else>
|
||||
距离开始
|
||||
<van-count-down :time="Math.abs(time)" class="count-down" format="DD 天 HH 时 mm 分 ss 秒"
|
||||
@finish="time = 0"></van-count-down>
|
||||
</template>
|
||||
<van-popup class="works-intro-popup" :style="{height: '100%', width: '100%'}" position="right" safe-area-inset-bottom :close-on-click-overlay="false" v-model="infoVisible">
|
||||
<div class="works-intro-page">
|
||||
<van-sticky>
|
||||
<van-nav-bar title="征集介绍" left-text="返回" left-arrow @click-left="closeInfo"></van-nav-bar>
|
||||
</van-sticky>
|
||||
<div class="works-intro-scroll">
|
||||
<div class="works-intro-hero">
|
||||
<div class="works-intro-hero__icon">
|
||||
<van-icon name="description"></van-icon>
|
||||
</div>
|
||||
<div>
|
||||
<div class="works-intro-hero__title">作品征集须知</div>
|
||||
<div class="works-intro-hero__subtitle">请仔细阅读征集内容与作品要求</div>
|
||||
</div>
|
||||
</div>
|
||||
<article v-if="infoRow.content" class="works-intro-card">
|
||||
<div class="works-intro-content" v-html="infoRow.content"></div>
|
||||
</article>
|
||||
<div v-else class="works-intro-empty">
|
||||
<van-icon name="description"></van-icon>
|
||||
<span>暂无征集介绍</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="works-intro-footer">
|
||||
<van-button v-if="canApply(infoRow)" @click="onApply(infoRow)" type="primary" block round>上传作品</van-button>
|
||||
<van-button v-else-if="time < 0" @click="onApply(infoRow)" type="primary" block round>
|
||||
距离开始
|
||||
<van-count-down :time="Math.abs(time)" format="DD 天 HH 时 mm 分 ss 秒" @finish="onCountdownFinish"></van-count-down>
|
||||
</van-button>
|
||||
<van-button v-else disabled block round>{{ registrationStatusText(infoRow) }}</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</van-action-sheet>
|
||||
</van-popup>
|
||||
|
||||
<apply-form ref="applyFormRef"></apply-form>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
<!--#include('applyForm.js'){}#-->
|
||||
new Vue({
|
||||
<!--#include("applyForm.js"){}#-->
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
components: {
|
||||
"apply-form": applyForm
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
time: 0,
|
||||
tableData: [],
|
||||
loading: false,
|
||||
skeletonLoading: true,
|
||||
finished: false,
|
||||
refreshing: false,
|
||||
imageLoadErrors: {},
|
||||
filterOpened: false,
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
@@ -114,53 +696,139 @@ layout("/layouts/platform_h5.html"){
|
||||
typeOptions: [
|
||||
{text: '全部', value: 1},
|
||||
{text: '即将开始', value: 4},
|
||||
{text: '报名中', value: 2},
|
||||
{text: '征集中', value: 2},
|
||||
{text: '已结束', value: 3},
|
||||
],
|
||||
infoVisible: false,
|
||||
infoRow: {},
|
||||
|
||||
|
||||
historyLayerPageKey: "works-collection-upload-h5",
|
||||
historyLayerUnsubscribe: null
|
||||
}
|
||||
},
|
||||
components: {
|
||||
'apply-form': applyForm,
|
||||
"pdf-preview": httpVueLoader("/components/plugins/sysFilePreview/PdfIndex.vue?v=" + new Date().getTime())
|
||||
},
|
||||
methods: {
|
||||
onApply(row) {
|
||||
if (this.$moment().isBefore(this.$moment(row.startDateTime))) {
|
||||
this.onView(row)
|
||||
hasCover(row) {
|
||||
return !!(row && row.cover && String(row.cover).trim())
|
||||
},
|
||||
handleImageError(row) {
|
||||
this.$set(this.imageLoadErrors, row.id, true)
|
||||
},
|
||||
onFilterOpen() {
|
||||
this.$set(this, "filterOpened", true)
|
||||
},
|
||||
onFilterClose() {
|
||||
this.$set(this, "filterOpened", false)
|
||||
},
|
||||
onCountdownFinish() {
|
||||
this.$set(this, "time", 0)
|
||||
},
|
||||
isRegistrationClosed(row) {
|
||||
return !!(row && row.endDateTime && !this.$moment().isBefore(this.$moment(row.endDateTime)))
|
||||
},
|
||||
canApply(row) {
|
||||
if(!row || !row.startDateTime || !row.endDateTime) {
|
||||
return false
|
||||
}
|
||||
const now = Date.now()
|
||||
return now >= this.$moment(row.startDateTime).valueOf()
|
||||
&& now <= this.$moment(row.endDateTime).valueOf()
|
||||
},
|
||||
registrationStatusText(row) {
|
||||
if(!row || !row.startDateTime || !row.endDateTime) {
|
||||
return '当前不可参与'
|
||||
}
|
||||
if(Date.now() < this.$moment(row.startDateTime).valueOf()) {
|
||||
return '征集未开始'
|
||||
}
|
||||
return '征集已结束'
|
||||
},
|
||||
onView(row) {
|
||||
this.$set(this, "infoRow", row)
|
||||
this.$set(this, "time", this.$moment().diff(this.$moment(row.startDateTime), "milliseconds"))
|
||||
window.h5HistoryLayerManager.open("works-collection-info")
|
||||
},
|
||||
closeInfo() {
|
||||
window.h5HistoryLayerManager.close("works-collection-info")
|
||||
},
|
||||
handlePageBack() {
|
||||
if (window.h5HistoryLayerManager.stack.length) {
|
||||
window.h5HistoryLayerManager.close()
|
||||
return
|
||||
}
|
||||
if (this.$moment().isAfter(this.$moment(row.endDateTime))) {
|
||||
this.$toast.fail("活动已结束")
|
||||
this.historyBack()
|
||||
},
|
||||
syncHistoryLayers(stack) {
|
||||
this.$set(this, "infoVisible", stack.includes("works-collection-info"))
|
||||
},
|
||||
onApply(row) {
|
||||
if(this.isRegistrationClosed(row)) {
|
||||
this.$toast.fail("征集已结束")
|
||||
return
|
||||
}
|
||||
if(this.$moment().isBefore(this.$moment(row.startDateTime))) {
|
||||
this.onView(row)
|
||||
return
|
||||
}
|
||||
this.$refs.applyFormRef.onOpen(row)
|
||||
},
|
||||
onView(row) {
|
||||
this.infoRow = row
|
||||
this.time = this.$moment().diff(this.$moment(row.startDateTime), 'milliseconds')
|
||||
this.infoVisible = true
|
||||
onLoad() {
|
||||
if(!this.finished) {
|
||||
this.loadActivities(false)
|
||||
}
|
||||
},
|
||||
onReady() {
|
||||
this.doSearch()
|
||||
onRefresh() {
|
||||
this.loadActivities(true)
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
loadActivities(reset) {
|
||||
const showSkeleton = !!reset
|
||||
if(reset) {
|
||||
this.$set(this, "skeletonLoading", true)
|
||||
this.$set(this.pageForm, "pageNumber", 1)
|
||||
this.$set(this.pageForm, "totalCount", 0)
|
||||
this.$set(this, "tableData", [])
|
||||
this.$set(this, "finished", false)
|
||||
this.$set(this, "imageLoadErrors", {})
|
||||
}
|
||||
this.$set(this, "loading", true)
|
||||
this.$axios.post('/platform/activity/worksCollection/upload/h5/activityPageData', this.pageForm, {
|
||||
h5SkeletonLoading: showSkeleton
|
||||
}).then((res) => {
|
||||
if(res.code === 0) {
|
||||
const list = res.data && res.data.list ? res.data.list : []
|
||||
this.$set(this, "tableData", this.pageForm.pageNumber === 1 ? list : this.tableData.concat(list))
|
||||
this.$set(this.pageForm, "totalCount", res.data && res.data.totalCount ? res.data.totalCount : 0)
|
||||
this.$set(this, "finished", this.tableData.length >= this.pageForm.totalCount)
|
||||
if(!this.finished) {
|
||||
this.$set(this.pageForm, "pageNumber", this.pageForm.pageNumber + 1)
|
||||
}
|
||||
}
|
||||
}).finally(() => {
|
||||
this.$set(this, "loading", false)
|
||||
this.$set(this, "refreshing", false)
|
||||
if(showSkeleton) this.$set(this, "skeletonLoading", false)
|
||||
})
|
||||
},
|
||||
doSearch() {
|
||||
this.loadActivities(true)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
window.h5HistoryLayerManager.register(this.historyLayerPageKey, (stack) => {
|
||||
this.syncHistoryLayers(stack)
|
||||
})
|
||||
this.$set(this, "historyLayerUnsubscribe", window.h5HistoryLayerManager.subscribe((stack) => {
|
||||
this.syncHistoryLayers(stack)
|
||||
}))
|
||||
this.loadActivities(true)
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.historyLayerUnsubscribe) {
|
||||
this.historyLayerUnsubscribe()
|
||||
}
|
||||
window.h5HistoryLayerManager.unregister(this.historyLayerPageKey)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
|
||||
@@ -3,140 +3,106 @@ layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
/* 同意条款样式 */
|
||||
.agree-section {
|
||||
padding: 16px;
|
||||
background-color: #fff;
|
||||
border-radius: 12px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.agree-section .van-checkbox__label {
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
color: #666;
|
||||
}
|
||||
#app { --club-primary: #1989fa; background: #f3f7fd; }
|
||||
.club-apply-page { min-height: 100vh; background: #f3f7fd; }
|
||||
.club-apply-page .van-nav-bar { background: #fff; box-shadow: 0 1px 8px rgba(28, 69, 120, .06); }
|
||||
.club-apply-page .van-nav-bar__title { color: #1f2d3d; font-size: 16px; font-weight: 600; }
|
||||
.club-apply-page .van-nav-bar__left { color: var(--club-primary); }
|
||||
.club-apply-page .van-nav-bar .van-icon, .club-apply-page .van-nav-bar .van-nav-bar__text { color: var(--club-primary); }
|
||||
.club-apply-form { padding: 12px 15px calc(132px + env(safe-area-inset-bottom)); background: #f3f7fd; }
|
||||
.club-apply-section { overflow: hidden; margin-bottom: 12px; background: #fff; border: 1px solid #e9eff7; border-radius: 10px; box-shadow: 0 4px 12px rgba(36, 77, 122, .04); }
|
||||
.club-apply-section__title { position: relative; margin: 0; padding: 13px 15px 8px 24px; color: #1f2d3d; font-size: 14px; font-weight: 600; line-height: 20px; }
|
||||
.club-apply-section__title::before { position: absolute; top: 16px; left: 15px; width: 3px; height: 14px; border-radius: 2px; background: var(--club-primary); content: ''; }
|
||||
.club-apply-section .van-cell-group { margin: 0; }
|
||||
.club-apply-section .van-cell { min-height: 46px; padding: 11px 15px; color: #40526a; font-size: 14px; }
|
||||
.club-apply-section .van-cell::after { right: 15px; left: 15px; border-color: #edf2f8; }
|
||||
.club-apply-section .van-field__label { width: 105px; color: #65778e; }
|
||||
.club-apply-section .van-field__control { color: #40526a; font-size: 14px; }
|
||||
.club-apply-section .van-field__control::placeholder { color: #b4c0cf; }
|
||||
.club-apply-section .van-field--disabled .van-field__control { color: #8b9bb0; }
|
||||
.club-apply-section .direction-column-field .van-field__label { width: 100%; margin-bottom: 8px; }
|
||||
.club-apply-section .direction-column-field .van-field__value { width: 100%; }
|
||||
.club-apply-section .van-field__word-limit { color: #b4c0cf; font-size: 11px; }
|
||||
.club-apply-actions { position: fixed; right: 0; bottom: 0; left: 0; z-index: 5; padding: 10px 15px calc(10px + env(safe-area-inset-bottom)); background: rgba(255, 255, 255, .98); border-top: 1px solid #edf2f8; }
|
||||
.club-apply-actions__agree { padding-bottom: 9px; }
|
||||
.club-apply-actions__agree .van-checkbox { align-items: flex-start; }
|
||||
.club-apply-actions__agree .van-checkbox__icon { margin-top: 2px; }
|
||||
.club-apply-actions__agree .van-checkbox__label { color: #65778e; font-size: 12px; line-height: 18px; }
|
||||
.club-apply-actions__buttons { display: flex; gap: 10px; }
|
||||
.club-apply-actions .van-button { flex: 1; height: 40px; border-radius: 8px; font-size: 14px; font-weight: 500; }
|
||||
.club-apply-actions .van-button--info { background: var(--club-primary); border-color: var(--club-primary); }
|
||||
.club-apply-actions .van-button--info.van-button--plain { color: var(--club-primary); background: #fff; }
|
||||
</style>
|
||||
|
||||
<div id="app">
|
||||
<!-- 导航栏 -->
|
||||
<van-nav-bar title="文体社团会员申请" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
<div id="app" v-cloak class="club-apply-page">
|
||||
<van-nav-bar title="文体社团会员申请" left-text="返回" left-arrow @click-left="onNavBack" fixed placeholder></van-nav-bar>
|
||||
|
||||
<!-- 表单容器 -->
|
||||
<van-form ref="formRef" class="form-container">
|
||||
<!-- 社团信息 -->
|
||||
<van-cell-group title="社团信息" class="form-section">
|
||||
<van-field
|
||||
:rules="[{ required: true }]"
|
||||
v-model="formData.clubName"
|
||||
label="社团"
|
||||
placeholder="请选择社团"
|
||||
required
|
||||
is-link
|
||||
readonly
|
||||
name="clubName"
|
||||
@click="showClubPopup = true"
|
||||
></van-field>
|
||||
<van-popup v-model:show="showClubPopup" position="bottom">
|
||||
<van-picker
|
||||
show-toolbar
|
||||
:columns="clubOptions.map(i => i.clubName)"
|
||||
@confirm="onClubConfirm"
|
||||
@cancel="showClubPopup = false"
|
||||
class="picker-style"
|
||||
></van-picker>
|
||||
</van-popup>
|
||||
</van-cell-group>
|
||||
<van-form ref="formRef" class="club-apply-form">
|
||||
<section class="club-apply-section">
|
||||
<h2 class="club-apply-section__title">基本信息</h2>
|
||||
<van-cell-group :border="false">
|
||||
<van-field :rules="[{ required: true, message: '请选择社团' }]" v-model="formData.clubName" label="社团" placeholder="请选择社团" required is-link readonly name="clubName" @click="openClubPopup"></van-field>
|
||||
<van-field label="姓名" :rules="[{ required: true }]" v-model="formData.userName" readonly required name="userName"></van-field>
|
||||
<van-field label="工号" :rules="[{ required: true }]" v-model="formData.loginName" readonly required name="loginName"></van-field>
|
||||
<van-field label="性别" :rules="[{ required: true }]" v-model="formData.sex" readonly required></van-field>
|
||||
<van-field label="出生年月" v-model="formData.birthday" readonly placeholder="读取信息中心数据"></van-field>
|
||||
<van-field label="联系电话" v-model="formData.mobile" placeholder="请输入联系电话"></van-field>
|
||||
<van-field label="电子信箱" v-model="formData.email" placeholder="请输入电子信箱"></van-field>
|
||||
<van-field label="分工会" v-model="formData.unionName" readonly></van-field>
|
||||
<van-field label="部门" v-model="formData.unitName" readonly></van-field>
|
||||
<van-field label="职务" v-model="formData.position" readonly placeholder="读取信息中心数据"></van-field>
|
||||
<van-field label="职称" v-model="formData.technicalTitle" readonly placeholder="读取信息中心数据"></van-field>
|
||||
<van-field label="学历" v-model="formData.education" readonly placeholder="读取信息中心数据"></van-field>
|
||||
<van-field label="学位" v-model="formData.academicDegree" readonly placeholder="读取信息中心数据"></van-field>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
|
||||
<!-- 基本信息 -->
|
||||
<van-cell-group title="基本信息" class="form-section">
|
||||
<van-field label="姓名" :rules="[{ required: true }]" v-model="formData.userName" readonly
|
||||
required name="userName"></van-field>
|
||||
<van-field label="工号" :rules="[{ required: true }]" v-model="formData.loginName" readonly
|
||||
required name="loginName"></van-field>
|
||||
<van-field label="性别" :rules="[{ required: true }]" v-model="formData.sex" readonly required></van-field>
|
||||
<van-field label="出生年月" v-model="formData.birthday" readonly placeholder="读取信息中心数据"></van-field>
|
||||
<van-field label="联系电话" v-model="formData.mobile" placeholder="请输入联系电话"></van-field>
|
||||
<van-field label="电子信箱" v-model="formData.email" placeholder="请输入电子信箱"></van-field>
|
||||
</van-cell-group>
|
||||
<section class="club-apply-section">
|
||||
<h2 class="club-apply-section__title">其他信息</h2>
|
||||
<van-cell-group :border="false">
|
||||
<van-field class="direction-column-field" v-model="formData.sameTimeJoinOtherClubSituation" label="同时参加其他社团情况" type="textarea" rows="4" autosize maxlength="500" show-word-limit placeholder="请填写同时参加其他社团情况"></van-field>
|
||||
<van-field class="direction-column-field" v-model="formData.awardsExperience" label="文化、体育方面的活动经历、获奖情况" type="textarea" rows="4" autosize maxlength="500" show-word-limit placeholder="请填写相关经历及获奖情况"></van-field>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
|
||||
<!-- 工作信息 -->
|
||||
<van-cell-group title="工作信息" class="form-section">
|
||||
<van-field label="分工会" v-model="formData.unionName" readonly></van-field>
|
||||
<van-field label="部门" v-model="formData.unitName" readonly></van-field>
|
||||
<van-field label="职务" v-model="formData.governmentPosition" readonly
|
||||
placeholder="读取信息中心数据"></van-field>
|
||||
<van-field label="职称" v-model="formData.technicalTitle" readonly
|
||||
placeholder="读取信息中心数据"></van-field>
|
||||
<van-field label="学历" v-model="formData.education" readonly placeholder="读取信息中心数据"></van-field>
|
||||
<van-field label="学位" v-model="formData.academicDegree" readonly
|
||||
placeholder="读取信息中心数据"></van-field>
|
||||
</van-cell-group>
|
||||
<section class="club-apply-section">
|
||||
<h2 class="club-apply-section__title">照片</h2>
|
||||
<van-cell-group :border="false">
|
||||
<van-field class="direction-column-field" name="avatar" label="上传本人照片">
|
||||
<template #input>
|
||||
<h5-file-upload slot="input" :value.sync="formData.avatar" :upload_number="1" upload_mode="image" upload_result_category="interval" upload_result_type="url"></h5-file-upload>
|
||||
</template>
|
||||
</van-field>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
|
||||
<!-- 其他信息 -->
|
||||
<van-cell-group title="其他信息" class="form-section">
|
||||
<van-field
|
||||
class="direction-column-field"
|
||||
v-model="formData.sameTimeJoinOtherClubSituation"
|
||||
label="同时参加其他社团情况"
|
||||
type="textarea"
|
||||
rows="4"
|
||||
autosize
|
||||
maxlength="500"
|
||||
placeholder="请填写同时参加其他社团情况"
|
||||
></van-field>
|
||||
<van-field
|
||||
class="direction-column-field"
|
||||
v-model="formData.awardsExperience"
|
||||
label="文化、体育方面的活动经历、获奖情况"
|
||||
type="textarea"
|
||||
rows="4"
|
||||
autosize
|
||||
maxlength="500"
|
||||
placeholder="请填写相关经历及获奖情况"
|
||||
></van-field>
|
||||
</van-cell-group>
|
||||
<section class="club-apply-section">
|
||||
<h2 class="club-apply-section__title">电子签名</h2>
|
||||
<van-cell-group :border="false">
|
||||
<van-field class="direction-column-field" name="signature" label="请确认签名">
|
||||
<template #input>
|
||||
<h5-signature v-model="formData.signature" slot="input"></h5-signature>
|
||||
</template>
|
||||
</van-field>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
|
||||
<!-- 照片上传 -->
|
||||
<van-cell-group title="照片" class="form-section">
|
||||
<van-field class="direction-column-field" name="avatar" label="">
|
||||
<template #input>
|
||||
<h5-file-upload
|
||||
slot="input"
|
||||
:value.sync="formData.avatar"
|
||||
:upload_number="1"
|
||||
upload_mode="image"
|
||||
upload_result_category="interval"
|
||||
upload_result_type="url"
|
||||
complete_result
|
||||
></h5-file-upload>
|
||||
</template>
|
||||
</van-field>
|
||||
</van-cell-group>
|
||||
|
||||
<!-- 电子签名 -->
|
||||
<van-cell-group title="电子签名" class="form-section">
|
||||
<van-field class="direction-column-field" name="signature" label="">
|
||||
<template #input>
|
||||
<h5-signature v-model="formData.signature" slot="input"></h5-signature>
|
||||
</template>
|
||||
</van-field>
|
||||
</van-cell-group>
|
||||
|
||||
<!-- 同意条款 -->
|
||||
<van-cell-group class="agree-section form-section">
|
||||
<van-checkbox v-model="isAgree" shape="square">
|
||||
注:本人已仔细阅读并愿意遵守所参加本校教职工文体社团的章程和规定,自愿加入所报名社团。
|
||||
</van-checkbox>
|
||||
</van-cell-group>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<div class="form-actions">
|
||||
<van-button native-type="button" @click="onSave" round type="info" plain>保存申请</van-button>
|
||||
<van-button @click="onSubmit" round type="info" v-if="!taskId">提交申请</van-button>
|
||||
<van-button @click="onFinishTask" round type="info" v-else>提交申请</van-button>
|
||||
</div>
|
||||
</van-form>
|
||||
|
||||
<div class="club-apply-actions">
|
||||
<div class="club-apply-actions__agree"><van-checkbox v-model="isAgree" shape="square">注:本人已仔细阅读并愿意遵守所参加本校教职工文体社团的章程和规定,自愿加入所报名社团。</van-checkbox></div>
|
||||
<div class="club-apply-actions__buttons">
|
||||
<van-button native-type="button" :loading="formLoading" @click="onSave" type="info" plain>保存申请</van-button>
|
||||
<van-button :loading="formLoading" @click="onSubmit" type="info" v-if="!taskId">提交申请</van-button>
|
||||
<van-button :loading="formLoading" @click="onFinishTask" type="info" v-else>提交申请</van-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<van-popup v-model="showClubPopup" position="bottom" get-container="#app" @click-overlay="closeClubPopup">
|
||||
<van-picker show-toolbar :columns="clubOptions.map((item) => item.clubName)" @confirm="onClubConfirm" @cancel="closeClubPopup"></van-picker>
|
||||
</van-popup>
|
||||
|
||||
<van-dialog :value="confirmVisible" title="提示" :message="confirmMessage" show-cancel-button @confirm="confirmPendingAction" @cancel="closeConfirm"></van-dialog>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
@@ -149,145 +115,211 @@ layout("/layouts/platform_h5.html"){
|
||||
bizId: GetQueryString("bizId"),
|
||||
taskId: GetQueryString("taskId"),
|
||||
formData: {
|
||||
clubId: "",
|
||||
clubName: "",
|
||||
userName: "",
|
||||
loginName: "",
|
||||
sex: "",
|
||||
birthday: "",
|
||||
mobile: "",
|
||||
email: "",
|
||||
unionName: "",
|
||||
unitName: "",
|
||||
governmentPosition: "",
|
||||
technicalTitle: "",
|
||||
education: "",
|
||||
academicDegree: "",
|
||||
sameTimeJoinOtherClubSituation: "",
|
||||
awardsExperience: "",
|
||||
avatar: [],
|
||||
signature: ""
|
||||
clubId: "", clubName: "", userName: "", loginName: "", sex: "", birthday: "", mobile: "", email: "", unionName: "", unitName: "", position: "", technicalTitle: "", education: "", academicDegree: "", sameTimeJoinOtherClubSituation: "", awardsExperience: "", avatar: "", signature: ""
|
||||
},
|
||||
clubOptions: [],
|
||||
showClubPopup: false,
|
||||
isAgree: false
|
||||
isAgree: false,
|
||||
formLoading: false,
|
||||
confirmVisible: false,
|
||||
pendingAction: "",
|
||||
historyLayerUnsubscribe: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSave() {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定保存吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/platform/club/join/apply/save", { data: JSON.stringify(this.formData) }).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$toast(res.msg)
|
||||
this.$pjaxReplace("/platform/club/join/mine/h5")
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
async onSubmit() {
|
||||
this.$refs.formRef.validate().then(() => {
|
||||
if (!this.isAgree) {
|
||||
this.$toast('请先阅读并同意协议')
|
||||
return
|
||||
}
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交申请吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/platform/club/join/apply/submit", {
|
||||
data: JSON.stringify(this.formData),
|
||||
mode: true
|
||||
}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$toast(res.msg)
|
||||
this.$pjaxReplace("/platform/club/join/mine/h5")
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
async onFinishTask() {
|
||||
this.$refs.formRef.validate().then(() => {
|
||||
if (!this.isAgree) {
|
||||
this.$toast('请先阅读并同意协议')
|
||||
return
|
||||
}
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交申请吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/platform/club/join/apply/submitAgain", {
|
||||
data: JSON.stringify(this.formData),
|
||||
taskId: GetQueryString("taskId")
|
||||
}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$toast(res.msg)
|
||||
this.$pjaxReplace("/platform/club/join/mine/h5")
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
checkApplyClub(clubId) {
|
||||
this.$axios.post("/platform/club/join/apply/checkApplyClub", { clubId }).then(res => {
|
||||
if (res.code !== 0) {
|
||||
this.$toast(res.msg)
|
||||
this.formData.clubId = ""
|
||||
this.formData.clubName = ""
|
||||
}
|
||||
})
|
||||
},
|
||||
onClubConfirm(value, index) {
|
||||
this.formData.clubId = this.clubOptions[index].id
|
||||
this.formData.clubName = value
|
||||
this.showClubPopup = false
|
||||
|
||||
// 检查是否已申请该社团
|
||||
this.checkApplyClub(this.formData.clubId)
|
||||
},
|
||||
listClub() {
|
||||
this.$axios.post("/platform/club/common/listClub").then(res => {
|
||||
if (res.code === 0) {
|
||||
this.clubOptions = res.data
|
||||
}
|
||||
})
|
||||
},
|
||||
init() {
|
||||
this.bizId = GetQueryString("bizId")
|
||||
if (this.bizId) {
|
||||
this.$axios.post("/platform/club/join/apply/info", { id: this.bizId }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.formData = res.data
|
||||
this.isAgree = true
|
||||
}
|
||||
})
|
||||
} else {
|
||||
const user = this.$store.state.user
|
||||
this.$set(this.formData, "userId", user.id)
|
||||
this.$set(this.formData, "userName", user.username)
|
||||
this.$set(this.formData, "loginName", user.loginname)
|
||||
this.$set(this.formData, "unitId", user.unit ? user.unit.id : null)
|
||||
this.$set(this.formData, "unitName", user.unit ? user.unit.name : null)
|
||||
this.$set(this.formData, "unionId", user.union ? user.union.id : null)
|
||||
this.$set(this.formData, "unionName", user.union ? user.union.name : null)
|
||||
this.$set(this.formData, "sex", user.sex)
|
||||
this.$set(this.formData, "birthday", user.birthday ? this.$moment(user.birthday).format('YYYY-MM-DD') : '')
|
||||
this.$set(this.formData, "nation", user.nation)
|
||||
this.$set(this.formData, "mobile", user.mobile)
|
||||
this.$set(this.formData, "political", user.political)
|
||||
this.$set(this.formData, "education", user.education)
|
||||
this.$set(this.formData, "technicalTitle", user.technicalTitle)
|
||||
this.$set(this.formData, "position", user.position)
|
||||
this.$set(this.formData, "academicDegree", user.academicDegree)
|
||||
}
|
||||
computed: {
|
||||
confirmMessage() {
|
||||
return this.pendingAction === 'save' ? '您确定保存当前申请吗?' : '您确定提交申请吗?';
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.listClub()
|
||||
this.init()
|
||||
const manager = window.h5HistoryLayerManager;
|
||||
if (manager) {
|
||||
manager.ensureRegistered('club-apply');
|
||||
this.historyLayerUnsubscribe = manager.subscribe((layers) => {
|
||||
this.$set(this, 'showClubPopup', layers.includes('club-apply-club-picker'));
|
||||
this.$set(this, 'confirmVisible', layers.includes('club-apply-confirm'));
|
||||
});
|
||||
}
|
||||
this.listClub();
|
||||
this.init();
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.historyLayerUnsubscribe) {
|
||||
this.historyLayerUnsubscribe();
|
||||
}
|
||||
const manager = window.h5HistoryLayerManager;
|
||||
if (manager) {
|
||||
manager.unregister('club-apply');
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onNavBack() {
|
||||
const manager = window.h5HistoryLayerManager;
|
||||
if (manager && manager.stack.length) {
|
||||
manager.close();
|
||||
return;
|
||||
}
|
||||
historyBack();
|
||||
},
|
||||
openClubPopup() {
|
||||
const manager = window.h5HistoryLayerManager;
|
||||
if (manager) {
|
||||
manager.open('club-apply-club-picker');
|
||||
return;
|
||||
}
|
||||
this.$set(this, 'showClubPopup', true);
|
||||
},
|
||||
closeClubPopup(afterClose) {
|
||||
const manager = window.h5HistoryLayerManager;
|
||||
if (manager) {
|
||||
manager.close('club-apply-club-picker', afterClose);
|
||||
return;
|
||||
}
|
||||
this.$set(this, 'showClubPopup', false);
|
||||
if (afterClose) {
|
||||
afterClose();
|
||||
}
|
||||
},
|
||||
openConfirm(action) {
|
||||
this.$set(this, 'pendingAction', action);
|
||||
const manager = window.h5HistoryLayerManager;
|
||||
if (manager) {
|
||||
manager.open('club-apply-confirm');
|
||||
return;
|
||||
}
|
||||
this.$set(this, 'confirmVisible', true);
|
||||
},
|
||||
closeConfirm(afterClose) {
|
||||
const manager = window.h5HistoryLayerManager;
|
||||
if (manager) {
|
||||
manager.close('club-apply-confirm', afterClose);
|
||||
return;
|
||||
}
|
||||
this.$set(this, 'confirmVisible', false);
|
||||
if (afterClose) {
|
||||
afterClose();
|
||||
}
|
||||
},
|
||||
onSave() {
|
||||
this.openConfirm('save');
|
||||
},
|
||||
onSubmit() {
|
||||
this.validateAndConfirm('submit');
|
||||
},
|
||||
onFinishTask() {
|
||||
this.validateAndConfirm('submitAgain');
|
||||
},
|
||||
validateAndConfirm(action) {
|
||||
this.$refs.formRef.validate().then(() => {
|
||||
if (!this.isAgree) {
|
||||
this.$toast('请先阅读并同意协议');
|
||||
return;
|
||||
}
|
||||
this.openConfirm(action);
|
||||
});
|
||||
},
|
||||
confirmPendingAction() {
|
||||
const action = this.pendingAction;
|
||||
this.closeConfirm(() => {
|
||||
if (action === 'save') {
|
||||
this.saveApplication();
|
||||
} else if (action === 'submitAgain') {
|
||||
this.submitApplication('/platform/club/join/apply/submitAgain', {data: JSON.stringify(this.formData), taskId: this.taskId});
|
||||
} else {
|
||||
this.submitApplication('/platform/club/join/apply/submit', {data: JSON.stringify(this.formData), mode: true});
|
||||
}
|
||||
});
|
||||
},
|
||||
saveApplication() {
|
||||
this.$set(this, 'formLoading', true);
|
||||
this.$axios.post('/platform/club/join/apply/save', {data: JSON.stringify(this.formData)}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$toast(res.msg);
|
||||
this.clearLayersAndGoMine();
|
||||
}
|
||||
}).finally(() => {
|
||||
this.$set(this, 'formLoading', false);
|
||||
});
|
||||
},
|
||||
submitApplication(url, params) {
|
||||
this.$set(this, 'formLoading', true);
|
||||
this.$axios.post(url, params).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$toast(res.msg);
|
||||
this.clearLayersAndGoMine();
|
||||
}
|
||||
}).finally(() => {
|
||||
this.$set(this, 'formLoading', false);
|
||||
});
|
||||
},
|
||||
clearLayersAndGoMine() {
|
||||
const manager = window.h5HistoryLayerManager;
|
||||
if (manager) {
|
||||
manager.closeAll(() => {
|
||||
this.$pjaxReplace('/platform/club/join/mine/h5');
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.$pjaxReplace('/platform/club/join/mine/h5');
|
||||
},
|
||||
checkApplyClub(clubId) {
|
||||
this.$axios.post('/platform/club/join/apply/checkApplyClub', {clubId: clubId}).then((res) => {
|
||||
if (res.code !== 0) {
|
||||
this.$toast(res.msg);
|
||||
this.$set(this.formData, 'clubId', '');
|
||||
this.$set(this.formData, 'clubName', '');
|
||||
}
|
||||
});
|
||||
},
|
||||
onClubConfirm(value, index) {
|
||||
const club = this.clubOptions[index];
|
||||
if (club) {
|
||||
this.$set(this.formData, 'clubId', club.id);
|
||||
this.$set(this.formData, 'clubName', value);
|
||||
this.checkApplyClub(club.id);
|
||||
}
|
||||
this.closeClubPopup();
|
||||
},
|
||||
listClub() {
|
||||
this.$axios.post('/platform/club/common/listClub').then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$set(this, 'clubOptions', res.data || []);
|
||||
}
|
||||
});
|
||||
},
|
||||
init() {
|
||||
if (this.bizId) {
|
||||
this.$axios.post('/platform/club/join/apply/info', {id: this.bizId}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const formData = Object.assign({}, res.data || {});
|
||||
// 兼容历史空数组字符串,避免编辑页把 "[]" 当作图片地址回显。
|
||||
if (formData.avatar === '[]') {
|
||||
formData.avatar = '';
|
||||
}
|
||||
this.$set(this, 'formData', formData);
|
||||
this.$set(this, 'isAgree', true);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
const user = this.$store.state.user;
|
||||
this.$set(this.formData, 'userId', user.id);
|
||||
this.$set(this.formData, 'userName', user.username);
|
||||
this.$set(this.formData, 'loginName', user.loginname);
|
||||
this.$set(this.formData, 'unitId', user.unit ? user.unit.id : null);
|
||||
this.$set(this.formData, 'unitName', user.unit ? user.unit.name : null);
|
||||
this.$set(this.formData, 'unionId', user.union ? user.union.id : null);
|
||||
this.$set(this.formData, 'unionName', user.union ? user.union.name : null);
|
||||
this.$set(this.formData, 'sex', user.sex);
|
||||
this.$set(this.formData, 'birthday', user.birthday ? this.$moment(user.birthday).format('YYYY-MM-DD') : '');
|
||||
this.$set(this.formData, 'nation', user.nation);
|
||||
this.$set(this.formData, 'mobile', user.mobile);
|
||||
this.$set(this.formData, 'political', user.political);
|
||||
this.$set(this.formData, 'education', user.education);
|
||||
this.$set(this.formData, 'technicalTitle', user.technicalTitle);
|
||||
this.$set(this.formData, 'position', user.position);
|
||||
this.$set(this.formData, 'academicDegree', user.academicDegree);
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -2,108 +2,136 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
.payed-field .van-field__control--custom {
|
||||
display: block;
|
||||
}
|
||||
.payed-field .label{
|
||||
color: rgb(153, 153, 153);
|
||||
font-size: 13px;
|
||||
}
|
||||
<style id="style-club-user-join-h5">
|
||||
<!--#include('../common/clubUserJoin.css'){}#-->
|
||||
</style>
|
||||
|
||||
<div id="app">
|
||||
<van-nav-bar title="社团审核" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
<style>
|
||||
#app { --club-primary: #1989fa; }
|
||||
.club-approval-page { min-height: 100vh; padding-bottom: calc(24px + env(safe-area-inset-bottom)); box-sizing: border-box; background: #f3f7fd; }
|
||||
.club-approval-page .van-nav-bar, .club-approval-page .van-sticky--fixed { background: #fff; }
|
||||
.club-approval-page .van-nav-bar__title { color: #172033; font-size: 16px; font-weight: 600; }
|
||||
.club-approval-page .van-nav-bar .van-icon, .club-approval-page .van-nav-bar__text { color: #1989fa; }
|
||||
.club-approval-sticky { padding: 22px 12px 1px; box-sizing: border-box; background: #f3f7fd; }
|
||||
.club-approval-search { margin: 0 0 8px; padding: 0; overflow: hidden; border-radius: 12px; background: #fff; box-shadow: 0 5px 16px rgba(43, 73, 112, .1); }
|
||||
.club-approval-search .van-search__content { height: 42px; padding-left: 12px; align-items: center; border-radius: 12px; background: #fff; }
|
||||
.club-approval-search .van-field__control { color: #263548; font-size: 14px; }
|
||||
.club-approval-search .van-field__control::placeholder { color: #a7b0bf; }
|
||||
.club-approval-filter { margin-bottom: 8px; overflow: hidden; border-radius: 10px; box-shadow: 0 5px 16px rgba(43, 73, 112, .08); }
|
||||
.club-approval-filter .van-dropdown-menu__bar { height: 44px; box-shadow: none; }
|
||||
.club-approval-filter .van-dropdown-menu__item, .club-approval-filter .van-dropdown-menu__title { height: 44px; }
|
||||
.club-approval-filter .van-dropdown-menu__item { align-items: center; justify-content: center; }
|
||||
.club-approval-filter .van-dropdown-menu__title { display: inline-flex; align-items: center; color: #66758a; font-size: 14px; line-height: 20px; }
|
||||
.club-approval-filter .van-dropdown-menu__title--active, .club-approval-filter .van-dropdown-item__option--active, .club-approval-filter .van-dropdown-item__option--active .van-dropdown-item__icon { color: #1989fa; }
|
||||
.club-approval-filter .van-dropdown-item__content { width: calc(100% - 24px); margin: 0 12px; overflow: hidden; box-sizing: border-box; border-radius: 0 0 12px 12px; box-shadow: 0 10px 24px rgba(31, 65, 108, .14); }
|
||||
.club-approval-filter .van-dropdown-item__option { display: flex; min-height: 48px; padding: 0 16px; align-items: center; color: #46566c; font-size: 14px; }
|
||||
.club-approval-list-content { padding: 0 12px; }
|
||||
.club-approval-page .table-list-container { margin-top: 0; padding-bottom: 2px; }
|
||||
.club-approval-page .table-list-container .table-list-item { margin-bottom: 12px; padding: 14px; border: 1px solid #e9eff7; border-radius: 12px; box-shadow: 0 5px 16px rgba(43, 73, 112, .08); }
|
||||
.club-card-header { display: flex; margin-bottom: 8px; align-items: flex-start; justify-content: space-between; }
|
||||
.club-card-header__heading { min-width: 0; padding-right: 10px; flex: 1; }
|
||||
.club-card-header__title { overflow: hidden; color: #253247; font-size: 15px; font-weight: 600; line-height: 22px; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.club-card-header__sub { margin-top: 1px; color: #9ba6b6; font-size: 12px; line-height: 18px; }
|
||||
.club-card-header__status { display: inline-flex; flex: none; }
|
||||
.club-card-header__status .van-tag { min-height: 24px; padding: 3px 9px; border: 0; border-radius: 12px; box-sizing: border-box; font-size: 12px; line-height: 18px; }
|
||||
.club-approval-page .table-list-container .table-list-item .item-actions { margin-top: 10px; padding-top: 10px; border-top-color: #edf1f6; }
|
||||
.club-approval-page .table-list-container .table-list-item .action-btn { min-height: 28px; padding: 4px 11px; border-radius: 14px; color: #1989fa; background: #eaf4ff; font-size: 12px; line-height: 18px; }
|
||||
.club-approval-page .table-list-container .table-list-item .action-btn.delete { color: #f04444; background: #fff0f0; }
|
||||
.club-approval-page .table-list-container .table-list-item .action-btn .van-icon { margin-right: 5px; font-size: 13px; }
|
||||
.club-approval-page .empty-state { padding: 0; }
|
||||
.club-audit-card { margin: 0 0 11px; overflow: hidden; border: 1px solid #e9eff7; border-radius: 10px; background: #fff; box-shadow: 0 3px 11px rgba(51, 87, 126, .08); }
|
||||
.club-audit-card__title { position: relative; margin: 0; padding: 12px 14px 8px 21px; color: #354255; font-size: 15px; font-weight: 600; line-height: 22px; }
|
||||
.club-audit-card__title::before { position: absolute; top: 15px; bottom: 11px; left: 12px; width: 2px; border-radius: 2px; background: var(--club-primary); content: ''; }
|
||||
.club-audit-card__required { position: absolute; left: 6px; color: #ee0a24; font-size: 12px; }
|
||||
.club-audit-card .club-audit-payment-field { min-height: 44px; padding: 10px 14px; background: transparent; }
|
||||
.club-audit-card .club-audit-payment-field::after { right: 14px; left: 14px; border-color: #eef2f7; }
|
||||
.club-audit-card .club-audit-payment-field .van-field__label { width: 102px; color: #596779; font-size: 12px; line-height: 24px; }
|
||||
.club-audit-card .club-audit-payment-field .van-field__control { color: #4f5d70; font-size: 12px; line-height: 24px; }
|
||||
.club-audit-card .van-radio-group { display: flex; align-items: center; min-height: 24px; white-space: nowrap; }
|
||||
.club-audit-card .van-radio { margin-right: 12px; }
|
||||
.club-audit-card .van-radio__label { color: #4f5d70; font-size: 12px; line-height: 24px; }
|
||||
.club-audit-field-label { position: relative; margin: 0; padding: 10px 14px 6px; color: #596779; font-size: 12px; line-height: 24px; }
|
||||
.club-audit-card .van-field.club-audit-field { width: calc(100% - 28px); margin: 0 14px 14px; padding: 12px; box-sizing: border-box; border: 1px solid #c9d5e5; border-radius: 10px; background: #f7f9fd; }
|
||||
.club-audit-card .van-field.club-audit-field .van-field__control { min-height: 150px; color: #253247; font-size: 12px; line-height: 22px; }
|
||||
.club-audit-card .van-field.club-audit-field .van-field__control::placeholder { color: #9aa7b8; }
|
||||
.club-audit-card .van-field.club-audit-field .van-field__word-limit { color: #718096; font-size: 12px; }
|
||||
.club-audit-card .van-field.club-audit-field::after { display: none; }
|
||||
.club-audit-actions { display: flex; column-gap: 10px; padding: 10px 12px calc(12px + env(safe-area-inset-bottom)); }
|
||||
.club-audit-actions .van-button { height: 40px; border-radius: 14px; font-size: 14px; }
|
||||
.club-audit-actions .van-button--primary { border-color: var(--club-primary); background: var(--club-primary); }
|
||||
.club-audit-actions .van-button--danger { border-color: #ff4d4f; background: #ff4d4f; }
|
||||
.club-list-skeleton { padding: 0; }
|
||||
.club-skeleton-card { margin-bottom: 12px; padding: 14px; background: #fff; border: 1px solid #e9eff7; border-radius: 12px; }
|
||||
.club-skeleton-line { height: 13px; margin-bottom: 12px; border-radius: 7px; background: linear-gradient(90deg, #f2f3f5 25%, #e6e8eb 37%, #f2f3f5 63%); background-size: 400% 100%; animation: club-skeleton-loading 1.4s ease infinite; }
|
||||
.club-skeleton-line--title { width: 46%; height: 16px; }
|
||||
.club-skeleton-line--short { width: 60%; }
|
||||
.club-empty { display: flex; min-height: 280px; padding: 46px 18px 36px; align-items: center; justify-content: center; box-sizing: border-box; flex-direction: column; text-align: center; }
|
||||
.club-empty img { display: block; width: 86%; max-width: 290px; height: auto; object-fit: contain; }
|
||||
.club-empty__title { margin-top: 14px; color: #50627a; font-size: 15px; font-weight: 600; line-height: 22px; }
|
||||
.club-empty__hint { margin-top: 5px; color: #9aa7b8; font-size: 12px; line-height: 18px; }
|
||||
@keyframes club-skeleton-loading { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
|
||||
</style>
|
||||
|
||||
<div id="app" v-cloak class="club-approval-page">
|
||||
<van-nav-bar title="社团审核" left-text="返回" left-arrow @click-left="onNavBack" fixed placeholder></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<van-search
|
||||
v-model="pageForm.searchKeyword"
|
||||
:show-action="false"
|
||||
:reverse-color="false"
|
||||
input-align="left"
|
||||
placeholder="请输入姓名或者工号搜索"
|
||||
@search="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<div class="club-approval-sticky">
|
||||
<van-search v-model="pageForm.searchKeyword" class="club-approval-search" placeholder="请输入姓名或者工号搜索" shape="round" clearable @search="doSearch" @clear="doSearch"></van-search>
|
||||
<van-dropdown-menu class="club-approval-filter" :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<year-van-dropdown-item :num="5" @change="doSearch" v-model="pageForm.year"></year-van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.mode" :options="modeOptions" :multiple="false"
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.unionId" :options="unionOptions" :multiple="false"
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.mode" :options="modeOptions" :multiple="false" @change="doSearch"></van-dropdown-item>
|
||||
<!-- 全部工会筛选已按移动端审核页面要求隐藏,接口不再传 unionId。 -->
|
||||
<van-dropdown-item v-model="pageForm.approvalText" :options="approvalOptions" :multiple="false" @change="onApprovalFilterChange"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<table-list api="/platform/club/join/clubApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" title="clubName" @ready="onReady">
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="姓名">{{row.userName}}</table-column>
|
||||
<table-column label="工号">{{row.loginName}}</table-column>
|
||||
<table-column label="申请模式">{{row.mode ? '加入' : '退出'}}</table-column>
|
||||
<table-column label="申请时间">{{row.applyDate}}</table-column>
|
||||
<table-column label="当前节点">{{row.curTaskName}}</table-column>
|
||||
<main class="club-approval-list-content">
|
||||
<table-list api="/platform/club/join/clubApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" title="clubName" :show_loading_overlay="false" @ready="onReady" @loading-change="onLoadingChange">
|
||||
<template #header="{row}">
|
||||
<div class="club-card-header">
|
||||
<div class="club-card-header__heading"><div class="club-card-header__title">{{ row.userName || '--' }}</div><div class="club-card-header__sub">工号:{{ row.loginName || '--' }}</div></div>
|
||||
<enum-tag class="club-card-header__status" v-if="row.instanceState" :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
|
||||
<i class="fa fa-edit"></i>
|
||||
<span>审核</span>
|
||||
</div>
|
||||
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">
|
||||
<i class="fa fa-reply"></i>
|
||||
<span>撤回</span>
|
||||
</div>
|
||||
<template v-slot="{row}">
|
||||
<table-column label="社团名称">{{ row.clubName || '--' }}</table-column>
|
||||
<table-column label="所属工会">{{ row.unionName || '--' }}</table-column>
|
||||
<table-column label="申请类型">{{ row.mode === 1 ? '加入社团' : '退出社团' }}</table-column>
|
||||
<table-column label="申请时间">{{ row.applyDate || '--' }}</table-column>
|
||||
<table-column label="所属单位">{{ row.unitName || '--' }}</table-column>
|
||||
<table-column label="当前节点">{{ row.curTaskName || '--' }}</table-column>
|
||||
</template>
|
||||
<template #actions="{row}">
|
||||
<div class="action-btn" @click="onView(row)"><van-icon name="eye-o"></van-icon><span>查看</span></div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)"><van-icon name="edit"></van-icon><span>审核</span></div>
|
||||
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)"><van-icon name="revoke"></van-icon><span>撤回</span></div>
|
||||
</template>
|
||||
<template #empty>
|
||||
<div v-if="listLoading" class="club-list-skeleton"><div v-for="item in 2" :key="item" class="club-skeleton-card"><div class="club-skeleton-line club-skeleton-line--title"></div><div class="club-skeleton-line"></div><div class="club-skeleton-line club-skeleton-line--short"></div></div></div>
|
||||
<div v-else class="club-empty"><img src="/assets/mobile/img/club/club-approval-empty.png" alt="暂无社团审核记录插画"><div class="club-empty__title">暂无社团审核记录</div><div class="club-empty__hint">当前筛选条件下暂时没有社团申请</div></div>
|
||||
</template>
|
||||
</table-list>
|
||||
</main>
|
||||
|
||||
<info ref="infoRef">
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">{{formData.taskName}}</div>
|
||||
<info ref="infoRef" page-key="club-approval" :merge-apply-info="true">
|
||||
<template v-if="showApprovalForm">
|
||||
<section class="club-audit-card">
|
||||
<h2 class="club-audit-card__title">{{ formData.taskName || '社团审核' }}</h2>
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
v-if="formData.mode === true"
|
||||
v-model="formData.tf_payed"
|
||||
name="tf_payed"
|
||||
label="缴费状态"
|
||||
placeholder="请选择缴费状态"
|
||||
:rules="[{ required: true, message: '请选择缴费状态' }]"
|
||||
required
|
||||
class="payed-field"
|
||||
>
|
||||
<van-field v-if="formData.mode === 1" v-model="formData.tf_payed" class="club-audit-payment-field" name="tf_payed" label="缴费状态" :rules="[{ required: true, message: '请选择缴费状态' }]" required>
|
||||
<template #input>
|
||||
<div class="label">(说明:请确认{{ formData.userName }}当年是否缴费)</div>
|
||||
<div>
|
||||
<van-radio-group v-model="formData.tf_payed" direction="horizontal">
|
||||
<van-radio name="0">未缴费</van-radio>
|
||||
<van-radio name="1">已缴费</van-radio>
|
||||
</van-radio-group>
|
||||
</div>
|
||||
<van-radio-group v-model="formData.tf_payed" direction="horizontal"><van-radio name="0">未缴费</van-radio><van-radio name="1">已缴费</van-radio></van-radio-group>
|
||||
</template>
|
||||
</van-field>
|
||||
<van-field
|
||||
v-model="formData.tf_opinion"
|
||||
name="tf_opinion"
|
||||
label="审批意见"
|
||||
placeholder="请输入审批意见"
|
||||
:rules="[{ required: true, message: '请填写审批意见' }]"
|
||||
required
|
||||
maxlength="100"
|
||||
show-word-limit
|
||||
></van-field>
|
||||
<p class="club-audit-field-label"><span class="club-audit-card__required">*</span>审批意见</p>
|
||||
<van-field v-model="formData.tf_opinion" class="club-audit-field" name="tf_opinion" type="textarea" rows="6" label="" placeholder="请输入审批意见" :rules="[{ required: true, message: '请填写审批意见' }]" maxlength="100" show-word-limit></van-field>
|
||||
</van-form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(2)">不同意</van-button>
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">同意</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<div class="club-audit-actions"><van-button :loading="formLoading" type="primary" block @click="handleTaskAction(1)">同意</van-button><van-button :loading="formLoading" type="danger" block @click="handleTaskAction(2)">拒绝</van-button><van-button :loading="formLoading" type="danger" block @click="handleTaskAction(6)">退回</van-button></div>
|
||||
</template>
|
||||
</info>
|
||||
<van-dialog :value="confirmVisible" title="提示" :message="confirmMessage" show-cancel-button :confirm-button-loading="formLoading" @confirm="confirmPendingAction" @cancel="closeConfirm"></van-dialog>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
@@ -111,105 +139,124 @@ layout("/layouts/platform_h5.html"){
|
||||
new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
components: {
|
||||
info: clubUserJoin
|
||||
},
|
||||
dicts: ['PROCESS_INSTANCE_STATE'],
|
||||
components: {info: clubUserJoin},
|
||||
data() {
|
||||
return {
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
searchKeyword: '',
|
||||
name: null,
|
||||
approvalText: "0",
|
||||
approval: false,
|
||||
year: new Date().getFullYear(),
|
||||
unionId: null,
|
||||
mode: null,
|
||||
},
|
||||
unionOptions: [],
|
||||
pageForm: {pageNumber: 1, pageSize: 10, totalCount: 0, searchKeyword: '', name: null, approvalText: '0', approval: false, year: new Date().getFullYear(), mode: null},
|
||||
formData: {},
|
||||
showApprovalForm: false,
|
||||
modeOptions: [{text: "全部类型", value: null}, {text: "申请加入", value: true}, {text: "申请退出", value: false}],
|
||||
modeOptions: [{text: '全部类型', value: null}, {text: '申请加入', value: true}, {text: '申请退出', value: false}],
|
||||
approvalOptions: [{text: '未审核', value: '0'}, {text: '已审核', value: '1'}],
|
||||
listLoading: true,
|
||||
formLoading: false,
|
||||
confirmVisible: false,
|
||||
pendingAction: '',
|
||||
pendingSubmitType: null,
|
||||
pendingRevokeRow: null,
|
||||
historyLayerUnsubscribe: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
confirmMessage() { return this.pendingAction === 'revoke' ? '您确定要撤回吗?' : '您确定要提交审核结果吗?'; }
|
||||
},
|
||||
created() {
|
||||
const manager = window.h5HistoryLayerManager;
|
||||
if (manager) {
|
||||
manager.ensureRegistered('club-approval');
|
||||
this.historyLayerUnsubscribe = manager.subscribe((layers) => {
|
||||
this.$set(this, 'confirmVisible', layers.includes('club-approval-confirm'));
|
||||
});
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.historyLayerUnsubscribe) { this.historyLayerUnsubscribe(); }
|
||||
const manager = window.h5HistoryLayerManager;
|
||||
if (manager) { manager.unregister('club-approval'); }
|
||||
},
|
||||
methods: {
|
||||
async onReady() {
|
||||
const unionList = await this.$businessTool.listUnion()
|
||||
this.unionOptions = [
|
||||
{
|
||||
text: "全部工会",
|
||||
value: null
|
||||
}
|
||||
].concat(unionList.map((v) => ({ text: v.name, value: v.id })))
|
||||
if (this.unionOptions.length > 0) {
|
||||
this.pageForm.unionId = this.unionOptions[0].value
|
||||
this.doSearch()
|
||||
}
|
||||
onNavBack() {
|
||||
const manager = window.h5HistoryLayerManager;
|
||||
if (manager && manager.stack.length) { manager.close(); return; }
|
||||
historyBack();
|
||||
},
|
||||
onReady() {
|
||||
this.doSearch();
|
||||
},
|
||||
onApprovalFilterChange(value) {
|
||||
// 下拉组件使用字符串,查询接口 approval 参数需转换为布尔值;默认 false 查询未审核记录。
|
||||
this.$set(this.pageForm, 'approval', value === '1');
|
||||
this.doSearch();
|
||||
},
|
||||
onLoadingChange(state) { this.$set(this, 'listLoading', state.loading); },
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
this.$set(this, 'showApprovalForm', false);
|
||||
this.$refs.infoRef.onOpen(row, '社团申请详情');
|
||||
},
|
||||
onApproval(row) {
|
||||
this.showApprovalForm = true
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
this.formData = {
|
||||
processTaskId: row.taskId,
|
||||
taskName: row.curTaskName,
|
||||
tf_payed: 0,
|
||||
userName: row.userName,
|
||||
mode: row.mode
|
||||
}
|
||||
this.$set(this, 'formData', {processTaskId: row.taskId, taskName: row.curTaskName, tf_payed: '0', userName: row.userName, mode: row.mode, tf_opinion: ''});
|
||||
this.$set(this, 'showApprovalForm', true);
|
||||
this.$refs.infoRef.onOpen(row, row.curTaskName || '社团审核');
|
||||
},
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate();
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: val
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.infoRef.onClose()
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
|
||||
})
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
openConfirm(action, submitType, row) {
|
||||
this.$set(this, 'pendingAction', action);
|
||||
this.$set(this, 'pendingSubmitType', submitType);
|
||||
this.$set(this, 'pendingRevokeRow', row);
|
||||
const manager = window.h5HistoryLayerManager;
|
||||
if (manager) { manager.open('club-approval-confirm'); return; }
|
||||
this.$set(this, 'confirmVisible', true);
|
||||
},
|
||||
onRevoke(row){
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要撤回吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
})
|
||||
closeConfirm(afterClose) {
|
||||
const manager = window.h5HistoryLayerManager;
|
||||
if (manager) { manager.close('club-approval-confirm', afterClose); return; }
|
||||
this.$set(this, 'confirmVisible', false);
|
||||
if (afterClose) { afterClose(); }
|
||||
},
|
||||
// 审批意见为空时先提示并触发字段校验,校验通过后才允许打开审核确认框。
|
||||
handleTaskAction(submitType) {
|
||||
const opinion = (this.formData.tf_opinion || '').trim();
|
||||
if (!opinion) {
|
||||
this.$toast('请填写审批意见');
|
||||
this.$refs.formRef.validate('tf_opinion').catch(() => {});
|
||||
return;
|
||||
}
|
||||
this.$set(this.formData, 'tf_opinion', opinion);
|
||||
this.$refs.formRef.validate().then(() => { this.openConfirm('submit', submitType, null); }).catch(() => {});
|
||||
},
|
||||
confirmPendingAction() {
|
||||
const action = this.pendingAction;
|
||||
const submitType = this.pendingSubmitType;
|
||||
const row = this.pendingRevokeRow;
|
||||
this.closeConfirm(() => {
|
||||
if (action === 'revoke') { this.revoke(row); } else { this.submitTaskAction(submitType); }
|
||||
});
|
||||
},
|
||||
submitTaskAction(submitType) {
|
||||
this.$set(this, 'formLoading', true);
|
||||
const taskData = Object.assign({}, this.formData, {submitType: submitType});
|
||||
this.$axios.post('/flow/common/executeTask', {data: JSON.stringify(taskData)}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const afterClose = () => { this.$toast.success(res.msg); this.doSearch(); };
|
||||
const manager = window.h5HistoryLayerManager;
|
||||
if (manager) { manager.closeAll(afterClose); } else { this.$refs.infoRef.onClose(afterClose); }
|
||||
}
|
||||
}).finally(() => { this.$set(this, 'formLoading', false); });
|
||||
},
|
||||
onRevoke(row) { this.openConfirm('revoke', null, row); },
|
||||
revoke(row) {
|
||||
this.$set(this, 'formLoading', true);
|
||||
this.$axios.post('/flow/common/revokeTask', {taskId: row.taskId}).then((res) => {
|
||||
if (res.code === 0) { this.$toast.success(res.msg); this.doSearch(); }
|
||||
}).finally(() => { this.$set(this, 'formLoading', false); });
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
this.pageForm.pageNumber = 1;
|
||||
this.pageForm.totalCount = 0;
|
||||
this.$refs.tableListRef.doSearch();
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,104 +1,176 @@
|
||||
const clubUserJoin = {
|
||||
template:
|
||||
/*language=HTML*/
|
||||
`
|
||||
<van-action-sheet v-model="visible" title="查看详情">
|
||||
<div class="detail-container">
|
||||
<van-cell-group title="基本信息">
|
||||
<van-cell title="社团名称">{{ viewData.clubName }}</van-cell>
|
||||
<van-cell title="姓名">{{ viewData.userName }}</van-cell>
|
||||
<van-cell title="工号">{{ viewData.loginName }}</van-cell>
|
||||
<van-cell title="性别">{{ viewData.sex }}</van-cell>
|
||||
<van-cell title="出生年月">{{ $moment(viewData.birthday).format('YYYY-MM-DD') }}</van-cell>
|
||||
<van-cell title="联系电话">{{ viewData.mobile }}</van-cell>
|
||||
<van-cell title="电子信箱">{{ viewData.email }}</van-cell>
|
||||
<van-cell title="分工会">{{ viewData.unionName }}</van-cell>
|
||||
<van-cell title="部门">{{ viewData.unitName }}</van-cell>
|
||||
<van-cell title="职务">{{ viewData.governmentPosition }}</van-cell>
|
||||
<van-cell title="职称">{{ viewData.technicalTitle }}</van-cell>
|
||||
<van-cell title="学历">{{ viewData.education }}</van-cell>
|
||||
<van-cell title="学位">{{ viewData.academicDegree }}</van-cell>
|
||||
<van-cell class="direction-column-cell" title="同时参加其他社团情况">
|
||||
{{ viewData.sameTimeJoinOtherClubSituation || '暂无' }}
|
||||
</van-cell>
|
||||
<van-cell class="direction-column-cell" title="文化、体育方面的活动经历、获奖情况">
|
||||
{{ viewData.awardsExperience || '暂无' }}
|
||||
</van-cell>
|
||||
<van-cell class="direction-column-cell" title="照片">
|
||||
<template slot="default">
|
||||
<van-image v-if="viewData.avatar && viewData.avatar !== '[]'" :src="viewData.avatar"></van-image>
|
||||
<span v-else>暂无</span>
|
||||
</template>
|
||||
</van-cell>
|
||||
<van-cell title="签字" >
|
||||
<van-image :src="viewData.signature"
|
||||
v-if="viewData.signature"
|
||||
class="signature-image"></van-image>
|
||||
<span v-else>暂无</span>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
<template v-for="task in doneTasks">
|
||||
<van-cell-group :title="task.displayName" v-if="task.ext.isFirstTaskNode">
|
||||
<van-cell title="申请用户">{{ task.ext.initiatorName }}({{task.ext.initiatorAccount}})
|
||||
</van-cell>
|
||||
<van-cell title="申请时间">{{ task.finishTime }}</van-cell>
|
||||
<van-cell title="办理结果">
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
|
||||
:value="task.ext.submitType"></dict-tag>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
<van-cell-group :title="task.displayName" v-else>
|
||||
<van-cell title="办理用户">{{ task.taskFormData.userName }}({{task.taskFormData.loginName}})
|
||||
</van-cell>
|
||||
<van-cell title="办理时间">{{ task.finishTime }}</van-cell>
|
||||
<van-cell title="办理结果">
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
|
||||
:value="task.ext.submitType"></dict-tag>
|
||||
</van-cell>
|
||||
<van-cell title="办理意见" v-if="!task.ext.isFirstTaskNode" class="direction-column-cell">
|
||||
<div v-html="task.taskFormData.tf_opinion"></div>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
</template>
|
||||
template: /*language=HTML*/ `
|
||||
<van-popup v-model="visible" position="right" :style="{ width: '100%', height: '100%' }" get-container="#app" class="club-user-join-popup" :close-on-click-overlay="false">
|
||||
<div class="club-user-join-detail">
|
||||
<van-nav-bar :title="detailTitle" left-text="返回" left-arrow fixed @click-left="onBack"></van-nav-bar>
|
||||
<div class="club-user-join-detail__scroll">
|
||||
<main class="club-user-join-detail__content">
|
||||
<section class="club-user-join-card club-user-join-info-card">
|
||||
<h3 class="club-user-join-card__title">申请信息</h3>
|
||||
<van-cell-group :border="false" v-if="mergeApplyInfo">
|
||||
<van-cell title="社团名称">{{ viewData.clubName || '--' }}</van-cell>
|
||||
<van-cell title="姓名">{{ viewData.userName || '--' }}</van-cell>
|
||||
<van-cell title="工号">{{ viewData.loginName || '--' }}</van-cell>
|
||||
<van-cell title="联系电话">{{ viewData.mobile || '--' }}</van-cell>
|
||||
<van-cell title="分工会">{{ viewData.unionName || '--' }}</van-cell>
|
||||
<van-cell title="部门">{{ viewData.unitName || '--' }}</van-cell>
|
||||
<van-cell title="性别">{{ viewData.sex || '--' }}</van-cell>
|
||||
<van-cell title="出生年月">{{ formatDate(viewData.birthday) }}</van-cell>
|
||||
<van-cell title="电子信箱">{{ viewData.email || '--' }}</van-cell>
|
||||
<van-cell title="职务">{{ viewData.position || viewData.governmentPosition || '--' }}</van-cell>
|
||||
<van-cell title="职称">{{ viewData.technicalTitle || viewData.jobTitle || '--' }}</van-cell>
|
||||
<van-cell title="学历 / 学位">{{ educationText }}</van-cell>
|
||||
<van-cell title="同时参加其他社团情况" class="club-user-join-info-long-cell"><div>{{ viewData.sameTimeJoinOtherClubSituation || '暂无' }}</div></van-cell>
|
||||
<van-cell title="文化、体育活动经历及获奖情况" class="club-user-join-info-long-cell"><div>{{ viewData.awardsExperience || '暂无' }}</div></van-cell>
|
||||
<van-cell title="照片" class="club-user-join-info-long-cell"><van-image v-if="viewData.avatar && viewData.avatar !== '[]'" :src="viewData.avatar" class="club-user-join-info-image" fit="cover"></van-image><span v-else>暂无</span></van-cell>
|
||||
<van-cell title="签字" class="club-user-join-info-long-cell"><van-image v-if="viewData.signature" :src="viewData.signature" class="club-user-join-info-image" fit="contain"></van-image><span v-else>暂无</span></van-cell>
|
||||
</van-cell-group>
|
||||
<div v-else class="club-user-join-card__grid">
|
||||
<div class="club-user-join-card__item"><span>社团名称</span><strong>{{ viewData.clubName || '--' }}</strong></div>
|
||||
<div class="club-user-join-card__item"><span>姓名</span><strong>{{ viewData.userName || '--' }}</strong></div>
|
||||
<div class="club-user-join-card__item"><span>工号</span><strong>{{ viewData.loginName || '--' }}</strong></div>
|
||||
<div class="club-user-join-card__item"><span>联系电话</span><strong>{{ viewData.mobile || '--' }}</strong></div>
|
||||
<div class="club-user-join-card__item"><span>分工会</span><strong>{{ viewData.unionName || '--' }}</strong></div>
|
||||
<div class="club-user-join-card__item"><span>部门</span><strong>{{ viewData.unitName || '--' }}</strong></div>
|
||||
</div>
|
||||
</section>
|
||||
<section v-if="!mergeApplyInfo" class="club-user-join-card">
|
||||
<h3 class="club-user-join-card__title">个人信息</h3>
|
||||
<div class="club-user-join-card__grid">
|
||||
<div class="club-user-join-card__item"><span>性别</span><strong>{{ viewData.sex || '--' }}</strong></div>
|
||||
<div class="club-user-join-card__item"><span>出生年月</span><strong>{{ formatDate(viewData.birthday) }}</strong></div>
|
||||
<div class="club-user-join-card__item"><span>电子信箱</span><strong>{{ viewData.email || '--' }}</strong></div>
|
||||
<div class="club-user-join-card__item"><span>职务</span><strong>{{ viewData.position || viewData.governmentPosition || '--' }}</strong></div>
|
||||
<div class="club-user-join-card__item"><span>职称</span><strong>{{ viewData.technicalTitle || viewData.jobTitle || '--' }}</strong></div>
|
||||
<div class="club-user-join-card__item"><span>学历 / 学位</span><strong>{{ educationText }}</strong></div>
|
||||
<div class="club-user-join-card__item club-user-join-card__item--full"><span>同时参加其他社团情况</span><strong>{{ viewData.sameTimeJoinOtherClubSituation || '暂无' }}</strong></div>
|
||||
<div class="club-user-join-card__item club-user-join-card__item--full"><span>文化、体育活动经历及获奖情况</span><strong>{{ viewData.awardsExperience || '暂无' }}</strong></div>
|
||||
</div>
|
||||
</section>
|
||||
<section v-if="!mergeApplyInfo" class="club-user-join-card">
|
||||
<h3 class="club-user-join-card__title">申请材料</h3>
|
||||
<div class="club-user-join-material">
|
||||
<span>照片</span>
|
||||
<van-image v-if="viewData.avatar && viewData.avatar !== '[]'" :src="viewData.avatar" fit="cover"></van-image>
|
||||
<strong v-else>暂无</strong>
|
||||
</div>
|
||||
<div class="club-user-join-material">
|
||||
<span>签字</span>
|
||||
<van-image v-if="viewData.signature" :src="viewData.signature" fit="contain"></van-image>
|
||||
<strong v-else>暂无</strong>
|
||||
</div>
|
||||
</section>
|
||||
<section v-for="(task, index) in doneTasks" :key="task.id || index" class="club-user-join-card club-user-join-task-card">
|
||||
<h3 class="club-user-join-card__title">{{ task.displayName || '审核节点' }}</h3>
|
||||
<van-cell-group :border="false" v-if="task.ext && task.ext.isFirstTaskNode">
|
||||
<van-cell title="申请用户">{{ task.ext.initiatorName || '--' }}({{ task.ext.initiatorAccount || '--' }})</van-cell>
|
||||
<van-cell title="申请时间">{{ task.finishTime || '--' }}</van-cell>
|
||||
<van-cell title="办理结果"><dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE" :value="task.ext.submitType"></dict-tag></van-cell>
|
||||
</van-cell-group>
|
||||
<van-cell-group :border="false" v-else>
|
||||
<van-cell title="办理用户">{{ task.taskFormData && task.taskFormData.userName || '--' }}({{ task.taskFormData && task.taskFormData.loginName || '--' }})</van-cell>
|
||||
<van-cell title="办理时间">{{ task.finishTime || '--' }}</van-cell>
|
||||
<van-cell title="办理结果"><dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE" :value="task.ext && task.ext.submitType"></dict-tag></van-cell>
|
||||
<van-cell title="办理意见"><div v-html="task.taskFormData && task.taskFormData.tf_opinion || '暂无'"></div></van-cell>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
<slot></slot>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
<slot></slot>
|
||||
</van-action-sheet>
|
||||
</van-popup>
|
||||
`,
|
||||
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
|
||||
dicts: ['PROCESS_TASK_SUBMIT_TYPE'],
|
||||
data() {
|
||||
return {
|
||||
visible:false,
|
||||
visible: false,
|
||||
detailTitle: '社团申请详情',
|
||||
viewData: {},
|
||||
doneTasks: [],
|
||||
row: null,
|
||||
historyLayerUnsubscribe: null
|
||||
}
|
||||
},
|
||||
props: {
|
||||
pageKey: {
|
||||
type: String,
|
||||
default: 'club-user-join-detail'
|
||||
},
|
||||
// 三个社团查看页启用后,将申请、个人及材料信息合并为同一张申请信息卡片。
|
||||
mergeApplyInfo: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
educationText() {
|
||||
const education = this.viewData.education || '';
|
||||
const degree = this.viewData.academicDegree || '';
|
||||
return education || degree ? education + (education && degree ? ' / ' : '') + degree : '--';
|
||||
}
|
||||
},
|
||||
created() {
|
||||
const manager = window.h5HistoryLayerManager;
|
||||
if (manager) {
|
||||
manager.ensureRegistered(this.pageKey);
|
||||
this.historyLayerUnsubscribe = manager.subscribe((layers) => {
|
||||
this.$set(this, 'visible', layers.includes('club-user-join-detail'));
|
||||
});
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.historyLayerUnsubscribe) {
|
||||
this.historyLayerUnsubscribe();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onOpen(row) {
|
||||
this.row = row
|
||||
this.visible = true
|
||||
this.getInfo()
|
||||
this.getDoneTasks()
|
||||
onOpen(row, title) {
|
||||
this.$set(this, 'row', row);
|
||||
this.$set(this, 'detailTitle', title || '社团申请详情');
|
||||
this.$set(this, 'viewData', Object.assign({}, row || {}));
|
||||
this.$set(this, 'doneTasks', []);
|
||||
const manager = window.h5HistoryLayerManager;
|
||||
if (manager) {
|
||||
manager.open('club-user-join-detail');
|
||||
} else {
|
||||
this.$set(this, 'visible', true);
|
||||
}
|
||||
if (!this.row || !this.row.id) {
|
||||
return;
|
||||
}
|
||||
this.getInfo();
|
||||
this.getDoneTasks();
|
||||
},
|
||||
onClose(){
|
||||
this.visible = false
|
||||
onClose(afterClose) {
|
||||
const manager = window.h5HistoryLayerManager;
|
||||
if (manager) {
|
||||
manager.close('club-user-join-detail', afterClose);
|
||||
return;
|
||||
}
|
||||
this.$set(this, 'visible', false);
|
||||
if (afterClose) {
|
||||
afterClose();
|
||||
}
|
||||
},
|
||||
onBack() {
|
||||
this.onClose();
|
||||
},
|
||||
formatDate(date) {
|
||||
return date ? this.$moment(date).format('YYYY-MM-DD') : '--';
|
||||
},
|
||||
getInfo() {
|
||||
this.$axios.post("/platform/club/join/mine/info", { id: this.row.id }).then((res) => {
|
||||
this.$axios.post('/platform/club/join/mine/info', {id: this.row.id}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.viewData = res.data
|
||||
this.$set(this, 'viewData', Object.assign({}, this.viewData, res.data || {}));
|
||||
}
|
||||
})
|
||||
},
|
||||
getDoneTasks() {
|
||||
this.$axios.post("/flow/common/doneTasks", {bizId: this.row.id}).then((res) => {
|
||||
this.$axios.post('/flow/common/doneTasks', {bizId: this.row.id}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.doneTasks = res.data
|
||||
this.$set(this, 'doneTasks', res.data || []);
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
style: /*language=CSS*/ `
|
||||
|
||||
`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,140 +2,111 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
.van-cell__value {
|
||||
min-width: 70%;
|
||||
}
|
||||
<style id="style-club-user-join-h5">
|
||||
<!--#include('../common/clubUserJoin.css'){}#-->
|
||||
</style>
|
||||
|
||||
<div id="app">
|
||||
<van-nav-bar title="我的申请" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
<style>
|
||||
#app { --club-primary: #1989fa; }
|
||||
.club-mine-page { min-height: 100vh; padding-bottom: calc(24px + env(safe-area-inset-bottom)); box-sizing: border-box; background: #f3f7fd; }
|
||||
.club-mine-page .van-nav-bar, .club-mine-page .van-sticky--fixed { background: #fff; }
|
||||
.club-mine-page .van-nav-bar__title { color: #172033; font-size: 16px; font-weight: 600; }
|
||||
.club-mine-page .van-nav-bar .van-icon, .club-mine-page .van-nav-bar__text { color: #1989fa; }
|
||||
.club-mine-sticky { padding: 22px 12px 1px; box-sizing: border-box; background: #f3f7fd; }
|
||||
.club-mine-search { margin: 0 0 8px; padding: 0; overflow: hidden; border-radius: 12px; background: #fff; box-shadow: 0 5px 16px rgba(43, 73, 112, .1); }
|
||||
.club-mine-search .van-search__content { height: 42px; padding-left: 12px; align-items: center; border-radius: 12px; background: #fff; }
|
||||
.club-mine-search .van-field__control { color: #263548; font-size: 14px; }
|
||||
.club-mine-search .van-field__control::placeholder { color: #a7b0bf; }
|
||||
.club-mine-filter { margin-bottom: 8px; overflow: hidden; border-radius: 10px; box-shadow: 0 5px 16px rgba(43, 73, 112, .08); }
|
||||
.club-mine-filter .van-dropdown-menu__bar, .club-mine-filter .van-dropdown-menu__item, .club-mine-filter .van-dropdown-menu__title { height: 44px; box-shadow: none; }
|
||||
.club-mine-filter .van-dropdown-menu__item { align-items: center; justify-content: center; }
|
||||
.club-mine-filter .van-dropdown-menu__title { display: inline-flex; align-items: center; color: #66758a; font-size: 14px; line-height: 20px; }
|
||||
.club-mine-filter .van-dropdown-menu__title--active, .club-mine-filter .van-dropdown-item__option--active, .club-mine-filter .van-dropdown-item__option--active .van-dropdown-item__icon { color: #1989fa; }
|
||||
.club-mine-filter .van-dropdown-item__content { width: calc(100% - 24px); margin: 0 12px; overflow: hidden; box-sizing: border-box; border-radius: 0 0 12px 12px; box-shadow: 0 10px 24px rgba(31, 65, 108, .14); }
|
||||
.club-mine-filter .van-dropdown-item__option { display: flex; min-height: 48px; padding: 0 16px; align-items: center; color: #46566c; font-size: 14px; }
|
||||
.club-mine-list-content { padding: 0 12px; }
|
||||
.club-mine-page .table-list-container { margin-top: 0; padding-bottom: 2px; }
|
||||
.club-mine-page .table-list-container .table-list-item { margin-bottom: 12px; padding: 14px; border: 1px solid #e9eff7; border-radius: 12px; box-shadow: 0 5px 16px rgba(43, 73, 112, .08); }
|
||||
.club-mine-page .empty-state { padding: 0; }
|
||||
.club-card-header { display: flex; margin-bottom: 8px; align-items: flex-start; justify-content: space-between; }
|
||||
.club-card-header__heading { min-width: 0; padding-right: 10px; flex: 1; }
|
||||
.club-card-header__title { overflow: hidden; color: #253247; font-size: 15px; font-weight: 600; line-height: 22px; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.club-card-header__sub { margin-top: 1px; color: #9ba6b6; font-size: 12px; line-height: 18px; }
|
||||
.club-card-header__status { display: inline-flex; flex: none; }
|
||||
.club-card-header__status .van-tag { min-height: 24px; padding: 3px 9px; border: 0; border-radius: 12px; box-sizing: border-box; font-size: 12px; line-height: 18px; }
|
||||
.club-mine-page .table-list-container .table-list-item .item-actions { margin-top: 10px; padding-top: 10px; border-top-color: #edf1f6; }
|
||||
.club-mine-page .table-list-container .table-list-item .action-btn { min-height: 28px; padding: 4px 11px; border-radius: 14px; color: #1989fa; background: #eaf4ff; font-size: 12px; line-height: 18px; }
|
||||
.club-mine-page .table-list-container .table-list-item .action-btn.delete { color: #f04444; background: #fff0f0; }
|
||||
.club-mine-page .table-list-container .table-list-item .action-btn .van-icon { margin-right: 5px; font-size: 13px; }
|
||||
.club-list-skeleton { padding: 0; }
|
||||
.club-skeleton-card { margin-bottom: 12px; padding: 14px; background: #fff; border: 1px solid #e9eff7; border-radius: 12px; }
|
||||
.club-skeleton-line { height: 13px; margin-bottom: 12px; border-radius: 7px; background: linear-gradient(90deg, #f2f3f5 25%, #e6e8eb 37%, #f2f3f5 63%); background-size: 400% 100%; animation: club-skeleton-loading 1.4s ease infinite; }
|
||||
.club-skeleton-line--title { width: 46%; height: 16px; }
|
||||
.club-skeleton-line--short { width: 60%; }
|
||||
.club-empty { display: flex; min-height: 280px; padding: 46px 18px 36px; align-items: center; justify-content: center; box-sizing: border-box; flex-direction: column; text-align: center; }
|
||||
.club-empty img { display: block; width: 86%; max-width: 290px; height: auto; object-fit: contain; }
|
||||
.club-empty__title { margin-top: 14px; color: #50627a; font-size: 15px; font-weight: 600; line-height: 22px; }
|
||||
.club-empty__hint { margin-top: 5px; color: #9aa7b8; font-size: 12px; line-height: 18px; }
|
||||
@keyframes club-skeleton-loading { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
|
||||
</style>
|
||||
|
||||
<div id="app" v-cloak class="club-mine-page">
|
||||
<van-nav-bar title="我的申请" left-text="返回" left-arrow @click-left="onNavBack" fixed placeholder></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<year-van-dropdown-item :num="5" @change="doSearch" v-model="pageForm.year"></year-van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<div class="club-mine-sticky">
|
||||
<van-search v-model="pageForm.clubName" class="club-mine-search" placeholder="请输入社团名称搜索" shape="round" clearable @search="doSearch" @clear="doSearch"></van-search>
|
||||
<van-dropdown-menu class="club-mine-filter" :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<year-van-dropdown-item :num="5" @change="doSearch" v-model="pageForm.year"></year-van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<table-list api="/platform/club/join/mine/pageData" :page_form.sync="pageForm" ref="tableListRef" title="clubName" @ready="doSearch">
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="姓名">{{row.userName}}</table-column>
|
||||
<table-column label="工号">{{row.loginName}}</table-column>
|
||||
<table-column label="申请模式">{{row.mode ? '加入' : '退出'}}</table-column>
|
||||
<table-column label="申请时间">{{row.applyDate}}</table-column>
|
||||
<table-column label="当前节点">{{row.taskName}}</table-column>
|
||||
<main class="club-mine-list-content">
|
||||
<table-list api="/platform/club/join/mine/pageData" :page_form.sync="pageForm" ref="tableListRef" title="clubName" :show_loading_overlay="false" @ready="doSearch" @loading-change="onLoadingChange">
|
||||
<template #header="{row}">
|
||||
<div v-if="row" class="club-card-header"><div class="club-card-header__heading"><div class="club-card-header__title">{{ row.userName || '--' }}</div><div class="club-card-header__sub">工号:{{ row.loginName || '--' }}</div></div><enum-tag class="club-card-header__status" v-if="row.instanceState" :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag></div>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" @click="onEdit(row)"
|
||||
v-if="(row.taskKey === 'startTask' || !row.instanceId) && row.mode === true">
|
||||
<i class="fa fa-edit"></i>
|
||||
<span>编辑</span>
|
||||
</div>
|
||||
<div class="action-btn" @click="exitSubmitAgain(row)"
|
||||
v-if="(row.taskKey === 'startTask' || !row.instanceId) && row.mode === false">
|
||||
<i class="fa fa-edit"></i>
|
||||
<span>提交</span>
|
||||
</div>
|
||||
<div class="action-btn delete" @click="onRevoke(row)"
|
||||
v-if="row.canRevoke">
|
||||
<i class="fa fa-undo"></i>
|
||||
<span>撤回</span>
|
||||
</div>
|
||||
<div class="action-btn delete" @click="onDelete(row)"
|
||||
v-if="row.taskKey === 'startTask' || !row.instanceId">
|
||||
<i class="fa fa-trash"></i>
|
||||
<span>删除</span>
|
||||
</div>
|
||||
<template v-slot="{row}">
|
||||
<template v-if="row"><table-column label="社团名称">{{ row.clubName || '--' }}</table-column><table-column label="申请类型"><van-tag v-if="row.mode === 2" type="primary">系统处理</van-tag><span v-else>{{ row.mode === 1 ? '加入社团' : '退出社团' }}</span></table-column><table-column label="申请时间">{{ row.applyDate || '--' }}</table-column><table-column label="当前节点">{{ row.taskName || '--' }}</table-column></template>
|
||||
</template>
|
||||
<template #actions="{row}">
|
||||
<template v-if="row"><div class="action-btn" @click="onView(row)"><van-icon name="eye-o"></van-icon><span>查看</span></div><div class="action-btn" @click="onEdit(row)" v-if="(row.taskKey === 'startTask' || !row.instanceId) && row.mode === 1"><van-icon name="edit"></van-icon><span>编辑</span></div><div class="action-btn" @click="exitSubmitAgain(row)" v-if="(row.taskKey === 'startTask' || !row.instanceId) && row.mode === 0"><van-icon name="passed"></van-icon><span>提交</span></div><div class="action-btn delete" @click="onRevoke(row)" v-if="row.canRevoke"><van-icon name="revoke"></van-icon><span>撤回</span></div><div class="action-btn delete" @click="onDelete(row)" v-if="row.mode !== 2 && (row.taskKey === 'startTask' || !row.instanceId)"><van-icon name="delete-o"></van-icon><span>删除</span></div></template>
|
||||
</template>
|
||||
<template #empty>
|
||||
<div v-if="listLoading" class="club-list-skeleton"><div v-for="item in 2" :key="item" class="club-skeleton-card"><div class="club-skeleton-line club-skeleton-line--title"></div><div class="club-skeleton-line"></div><div class="club-skeleton-line club-skeleton-line--short"></div></div></div>
|
||||
<div v-else class="club-empty"><img src="/assets/mobile/img/club/club-approval-empty.png" alt="暂无社团申请记录插画"><div class="club-empty__title">暂无社团申请记录</div><div class="club-empty__hint">当前筛选条件下暂时没有社团申请</div></div>
|
||||
</template>
|
||||
</table-list>
|
||||
</main>
|
||||
|
||||
<info ref="infoRef"></info>
|
||||
<info ref="infoRef" page-key="club-mine" :merge-apply-info="true"></info>
|
||||
<van-dialog :value="confirmVisible" title="提示" :message="confirmMessage" show-cancel-button :confirm-button-loading="formLoading" @confirm="confirmPendingAction" @cancel="closeConfirm"></van-dialog>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
<!--#include('../common/clubUserJoin.js'){}#-->
|
||||
new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
components: {
|
||||
info: clubUserJoin
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
year: new Date().getFullYear()
|
||||
},
|
||||
}
|
||||
},
|
||||
el: "#app", store, dicts: ['PROCESS_INSTANCE_STATE'], components: {info: clubUserJoin},
|
||||
data() { return {pageForm: {pageNumber: 1, pageSize: 10, totalCount: 0, year: new Date().getFullYear(), clubName: ''}, listLoading: true, formLoading: false, confirmVisible: false, pendingAction: '', pendingRow: null, historyLayerUnsubscribe: null} },
|
||||
computed: { confirmMessage() { if (this.pendingAction === 'revoke') { return '您确定要撤回吗?'; } if (this.pendingAction === 'delete') { return '确定要删除此申请吗?'; } return '您确定要提交申请吗?'; } },
|
||||
created() { const manager = window.h5HistoryLayerManager; if (manager) { manager.ensureRegistered('club-mine'); this.historyLayerUnsubscribe = manager.subscribe((layers) => { this.$set(this, 'confirmVisible', layers.includes('club-mine-confirm')); }); } },
|
||||
beforeDestroy() { if (this.historyLayerUnsubscribe) { this.historyLayerUnsubscribe(); } const manager = window.h5HistoryLayerManager; if (manager) { manager.unregister('club-mine'); } },
|
||||
methods: {
|
||||
exitSubmitAgain(row) {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交申请吗?"
|
||||
}).then(async () => {
|
||||
const res = await this.$axios.post("/platform/club/join/apply/info", {id: row.id})
|
||||
this.$axios.post('/platform/club/join/apply/submitAgain', {
|
||||
data: JSON.stringify(res.data),
|
||||
taskId: row.startTaskId,
|
||||
}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$toast(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
onRevoke(row) {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要撤回吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/revokeTask", { taskId: row.startTaskId }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$toast(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
onView(row) {
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
},
|
||||
onEdit(row) {
|
||||
this.$pjaxReplace("/platform/club/join/apply/h5?taskId=" + (row.startTaskId || "") + "&bizId=" + row.id)
|
||||
},
|
||||
onDelete(row) {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "确定要删除此申请吗?"
|
||||
})
|
||||
.then(() => {
|
||||
this.$axios.post("/platform/club/join/mine/delete", { id: row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
} else {
|
||||
this.$toast.fail(res.msg)
|
||||
}
|
||||
})
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
}
|
||||
},
|
||||
onNavBack() { const manager = window.h5HistoryLayerManager; if (manager && manager.stack.length) { manager.close(); return; } historyBack(); },
|
||||
onLoadingChange(state) { this.$set(this, 'listLoading', state.loading); },
|
||||
openConfirm(action, row) { this.$set(this, 'pendingAction', action); this.$set(this, 'pendingRow', row); const manager = window.h5HistoryLayerManager; if (manager) { manager.open('club-mine-confirm'); return; } this.$set(this, 'confirmVisible', true); },
|
||||
closeConfirm(afterClose) { const manager = window.h5HistoryLayerManager; if (manager) { manager.close('club-mine-confirm', afterClose); return; } this.$set(this, 'confirmVisible', false); if (afterClose) { afterClose(); } },
|
||||
confirmPendingAction() { const action = this.pendingAction; const row = this.pendingRow; this.closeConfirm(() => { if (action === 'revoke') { this.revoke(row); } else if (action === 'delete') { this.deleteApplication(row); } else { this.submitAgain(row); } }); },
|
||||
exitSubmitAgain(row) { this.openConfirm('submitAgain', row); },
|
||||
submitAgain(row) { this.$set(this, 'formLoading', true); this.$axios.post('/platform/club/join/apply/info', {id: row.id}).then((res) => { if (res.code === 0) { return this.$axios.post('/platform/club/join/apply/submitAgain', {data: JSON.stringify(res.data), taskId: row.startTaskId}); } this.$toast.fail(res.msg); return null; }).then((res) => { if (res && res.code === 0) { this.$toast(res.msg); this.doSearch(); } }).finally(() => { this.$set(this, 'formLoading', false); }); },
|
||||
onRevoke(row) { this.openConfirm('revoke', row); },
|
||||
revoke(row) { this.$set(this, 'formLoading', true); this.$axios.post('/flow/common/revokeTask', {taskId: row.startTaskId}).then((res) => { if (res.code === 0) { this.$toast(res.msg); this.doSearch(); } }).finally(() => { this.$set(this, 'formLoading', false); }); },
|
||||
onView(row) { this.$refs.infoRef.onOpen(row, '社团申请详情'); },
|
||||
onEdit(row) { this.$pjaxReplace('/platform/club/join/apply/h5?taskId=' + (row.startTaskId || '') + '&bizId=' + row.id); },
|
||||
onDelete(row) { this.openConfirm('delete', row); },
|
||||
deleteApplication(row) { this.$set(this, 'formLoading', true); this.$axios.post('/platform/club/join/mine/delete', {id: row.id}).then((res) => { if (res.code === 0) { this.$toast.success(res.msg); this.doSearch(); } else { this.$toast.fail(res.msg); } }).finally(() => { this.$set(this, 'formLoading', false); }); },
|
||||
doSearch() { this.$nextTick(() => { this.$set(this.pageForm, 'pageNumber', 1); this.$set(this.pageForm, 'totalCount', 0); this.$refs.tableListRef.doSearch(); }); }
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -2,91 +2,113 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
.van-cell__value {
|
||||
min-width: 70%;
|
||||
}
|
||||
<style id="style-club-user-join-h5">
|
||||
<!--#include('../common/clubUserJoin.css'){}#-->
|
||||
</style>
|
||||
|
||||
<div id="app">
|
||||
<van-nav-bar title="我的社团" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
<style>
|
||||
#app { --club-primary: #1989fa; }
|
||||
.club-member-page { min-height: 100vh; padding-bottom: calc(24px + env(safe-area-inset-bottom)); box-sizing: border-box; background: #f3f7fd; }
|
||||
.club-member-page .van-nav-bar, .club-member-page .van-sticky--fixed { background: #fff; }
|
||||
.club-member-page .van-nav-bar__title { color: #172033; font-size: 16px; font-weight: 600; }
|
||||
.club-member-page .van-nav-bar .van-icon, .club-member-page .van-nav-bar__text { color: #1989fa; }
|
||||
.club-member-sticky { padding: 22px 12px 1px; box-sizing: border-box; background: #f3f7fd; }
|
||||
.club-member-search { margin: 0 0 8px; padding: 0; overflow: hidden; border-radius: 12px; background: #fff; box-shadow: 0 5px 16px rgba(43, 73, 112, .1); }
|
||||
.club-member-search .van-search__content { height: 42px; padding-left: 12px; align-items: center; border-radius: 12px; background: #fff; }
|
||||
.club-member-search .van-field__control { color: #263548; font-size: 14px; }
|
||||
.club-member-search .van-field__control::placeholder { color: #a7b0bf; }
|
||||
.club-member-list-content { padding: 0 12px; }
|
||||
.club-member-page .table-list-container { margin-top: 0; padding-bottom: 2px; }
|
||||
.club-member-page .table-list-container .table-list-item { margin-bottom: 12px; padding: 14px; border: 1px solid #e9eff7; border-radius: 12px; box-shadow: 0 5px 16px rgba(43, 73, 112, .08); }
|
||||
.club-member-page .empty-state { padding: 0; }
|
||||
.club-card-header { display: flex; margin-bottom: 8px; align-items: flex-start; justify-content: space-between; }
|
||||
.club-card-header__heading { min-width: 0; padding-right: 10px; flex: 1; }
|
||||
.club-card-header__title { overflow: hidden; color: #253247; font-size: 15px; font-weight: 600; line-height: 22px; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.club-card-header__sub { margin-top: 1px; color: #9ba6b6; font-size: 12px; line-height: 18px; }
|
||||
.club-card-header__status { display: inline-flex; flex: none; }
|
||||
.club-card-header__status.van-tag, .club-card-header__status .van-tag { min-height: 24px; padding: 3px 9px; border: 0; border-radius: 12px; box-sizing: border-box; font-size: 12px; line-height: 18px; }
|
||||
.club-member-page .table-list-container .table-list-item .item-actions { margin-top: 10px; padding-top: 10px; border-top-color: #edf1f6; }
|
||||
.club-member-page .table-list-container .table-list-item .action-btn { min-height: 28px; padding: 4px 11px; border-radius: 14px; color: #1989fa; background: #eaf4ff; font-size: 12px; line-height: 18px; }
|
||||
.club-member-page .table-list-container .table-list-item .action-btn.delete { color: #f04444; background: #fff0f0; }
|
||||
.club-member-page .table-list-container .table-list-item .action-btn .van-icon { margin-right: 5px; font-size: 13px; }
|
||||
.club-list-skeleton { padding: 0; }
|
||||
.club-skeleton-card { margin-bottom: 12px; padding: 14px; background: #fff; border: 1px solid #e9eff7; border-radius: 12px; }
|
||||
.club-skeleton-line { height: 13px; margin-bottom: 12px; border-radius: 7px; background: linear-gradient(90deg, #f2f3f5 25%, #e6e8eb 37%, #f2f3f5 63%); background-size: 400% 100%; animation: club-skeleton-loading 1.4s ease infinite; }
|
||||
.club-skeleton-line--title { width: 46%; height: 16px; }
|
||||
.club-skeleton-line--short { width: 60%; }
|
||||
.club-empty { display: flex; min-height: 280px; padding: 46px 18px 36px; align-items: center; justify-content: center; box-sizing: border-box; flex-direction: column; text-align: center; }
|
||||
.club-empty img { display: block; width: 86%; max-width: 290px; height: auto; object-fit: contain; }
|
||||
.club-empty__title { margin-top: 14px; color: #50627a; font-size: 15px; font-weight: 600; line-height: 22px; }
|
||||
.club-empty__hint { margin-top: 5px; color: #9aa7b8; font-size: 12px; line-height: 18px; }
|
||||
@keyframes club-skeleton-loading { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
|
||||
</style>
|
||||
|
||||
<van-sticky offset-top="46px">
|
||||
<van-search
|
||||
v-model="pageForm.clubName"
|
||||
:show-action="false"
|
||||
:reverse-color="false"
|
||||
input-align="left"
|
||||
placeholder="请输入社团名称"
|
||||
@search="doSearch"
|
||||
></van-search>
|
||||
</van-sticky>
|
||||
<div id="app" v-cloak class="club-member-page">
|
||||
<van-nav-bar title="我的社团" left-text="返回" left-arrow @click-left="onNavBack" fixed placeholder></van-nav-bar>
|
||||
<van-sticky offset-top="46px"><div class="club-member-sticky"><van-search v-model="pageForm.clubName" class="club-member-search" placeholder="请输入社团名称搜索" shape="round" clearable @search="doSearch" @clear="doSearch"></van-search></div></van-sticky>
|
||||
|
||||
<table-list api="/platform/club/join/mine/club/pageData" :page_form.sync="pageForm" ref="tableListRef" title="clubName" @ready="doSearch">
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="社团编码">{{row.clubCode}}</table-column>
|
||||
<table-column label="成立时间">{{row.foundTime}}</table-column>
|
||||
<table-column label="会长">{{row.clubLeader}}</table-column>
|
||||
<table-column label="秘书长">{{row.clubSecretary}}</table-column>
|
||||
<table-column label="当前人数">{{row.currentPeopleNum}}</table-column>
|
||||
<main class="club-member-list-content">
|
||||
<table-list api="/platform/club/join/mine/club/pageData" :page_form.sync="pageForm" ref="tableListRef" title="userName" :show_loading_overlay="false" @ready="doSearch" @loading-change="onLoadingChange">
|
||||
<template #header="{row}">
|
||||
<div v-if="row" class="club-card-header"><div class="club-card-header__heading"><div class="club-card-header__title">{{ row.userName || '--' }}</div><div class="club-card-header__sub">工号:{{ row.loginName || '--' }}</div></div><van-tag class="club-card-header__status" type="success" size="small">已完成</van-tag></div>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<!--<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span>查看</span>
|
||||
</div>-->
|
||||
<div class="action-btn delete" @click="onExit(row)">
|
||||
<i class="fa fa-undo"></i>
|
||||
<span>申请退会</span>
|
||||
</div>
|
||||
<template v-slot="{row}">
|
||||
<template v-if="row"><table-column label="社团名称">{{ row.clubName || '--' }}</table-column><table-column label="会长">{{ row.clubLeader || '--' }}</table-column><table-column label="秘书长">{{ row.clubSecretary || '--' }}</table-column><table-column label="当前人数">{{ row.currentPeopleNum || 0 }} 人</table-column></template>
|
||||
</template>
|
||||
<template #actions="{row}"><template v-if="row"><div class="action-btn" @click="onView(row)"><van-icon name="eye-o"></van-icon><span>查看</span></div><div class="action-btn delete" @click="onExit(row)"><van-icon name="revoke"></van-icon><span>申请退会</span></div></template></template>
|
||||
<template #empty>
|
||||
<div v-if="listLoading" class="club-list-skeleton"><div v-for="item in 2" :key="item" class="club-skeleton-card"><div class="club-skeleton-line club-skeleton-line--title"></div><div class="club-skeleton-line"></div><div class="club-skeleton-line club-skeleton-line--short"></div></div></div>
|
||||
<div v-else class="club-empty"><img src="/assets/mobile/img/club/club-approval-empty.png" alt="暂无社团记录插画"><div class="club-empty__title">暂无社团记录</div><div class="club-empty__hint">当前筛选条件下暂时没有加入的社团</div></div>
|
||||
</template>
|
||||
</table-list>
|
||||
</main>
|
||||
<van-popup v-model="clubDetailVisible" position="right" :style="{ width: '100%', height: '100%' }" get-container="#app" class="club-user-join-popup" :close-on-click-overlay="false">
|
||||
<div class="club-user-join-detail">
|
||||
<van-nav-bar title="社团详情" left-text="返回" left-arrow fixed @click-left="closeClubDetail"></van-nav-bar>
|
||||
<div class="club-user-join-detail__scroll">
|
||||
<main class="club-user-join-detail__content">
|
||||
<section class="club-user-join-card club-user-join-info-card">
|
||||
<h3 class="club-user-join-card__title">社团基础信息</h3>
|
||||
<van-cell-group :border="false">
|
||||
<van-cell title="社团名称">{{ clubDetail.clubName || '--' }}</van-cell>
|
||||
<van-cell title="成立时间">{{ clubDetail.foundTime || '--' }}</van-cell>
|
||||
<van-cell title="社团编码">{{ clubDetail.clubCode || '--' }}</van-cell>
|
||||
<van-cell title="社团类型"><dict-tag :options="dict.type.CLUB_REGISTER_TYPE" :value="clubDetail.clubType"></dict-tag></van-cell>
|
||||
<van-cell title="会长">{{ clubDetail.clubLeader || '--' }}</van-cell>
|
||||
<van-cell title="秘书长">{{ clubDetail.clubSecretary || '--' }}</van-cell>
|
||||
<van-cell title="当前人数">{{ clubDetail.currentPeopleNum || 0 }} 人</van-cell>
|
||||
<van-cell title="会费标准">{{ clubDetail.due || '--' }}</van-cell>
|
||||
<van-cell title="社团介绍" class="club-user-join-info-long-cell"><div v-if="hasClubContent(clubDetail.introduce)" v-html="clubDetail.introduce"></div><span v-else>暂无</span></van-cell>
|
||||
<van-cell title="社团宗旨" class="club-user-join-info-long-cell"><div v-if="hasClubContent(clubDetail.purpose)" v-html="clubDetail.purpose"></div><span v-else>暂无</span></van-cell>
|
||||
<van-cell title="社团章程" class="club-user-join-info-long-cell"><file-preview v-if="clubDetail.rulesFile && clubDetail.rulesFile.length" :files="clubDetail.rulesFile" complete_result></file-preview><span v-else>暂无</span></van-cell>
|
||||
<van-cell title="年度活动计划" class="club-user-join-info-long-cell"><file-preview v-if="clubDetail.yearPlanFile && clubDetail.yearPlanFile.length" :files="clubDetail.yearPlanFile" complete_result></file-preview><span v-else>暂无</span></van-cell>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
<van-dialog :value="confirmVisible" title="提示" :message="confirmMessage" show-cancel-button :confirm-button-loading="formLoading" @confirm="confirmExit" @cancel="closeConfirm"></van-dialog>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
components: {
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
el: "#app", store, dicts: ['CLUB_REGISTER_TYPE'],
|
||||
data() { return {pageForm: {pageNumber: 1, pageSize: 10, totalCount: 0, clubName: ''}, listLoading: true, formLoading: false, clubDetailVisible: false, clubDetail: {}, confirmVisible: false, currentRow: null, historyLayerUnsubscribe: null} },
|
||||
computed: { confirmMessage() { return this.currentRow ? '您确定要申请退出“' + this.currentRow.clubName + '”吗?' : '您确定要申请退出该社团吗?'; } },
|
||||
created() { const manager = window.h5HistoryLayerManager; if (manager) { manager.ensureRegistered('club-mineclub'); this.historyLayerUnsubscribe = manager.subscribe((layers) => { this.$set(this, 'clubDetailVisible', layers.includes('club-mineclub-detail')); this.$set(this, 'confirmVisible', layers.includes('club-mineclub-confirm')); }); } },
|
||||
beforeDestroy() { if (this.historyLayerUnsubscribe) { this.historyLayerUnsubscribe(); } const manager = window.h5HistoryLayerManager; if (manager) { manager.unregister('club-mineclub'); } },
|
||||
methods: {
|
||||
onExit(row) {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要申请退出" + row.clubName + "吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post('/platform/club/join/apply/submit', {
|
||||
data: JSON.stringify(row),
|
||||
mode: false,
|
||||
}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$toast(res.msg)
|
||||
this.$pjaxReplace("/platform/club/join/mine/h5")
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
onView(row) {
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
}
|
||||
},
|
||||
onNavBack() { const manager = window.h5HistoryLayerManager; if (manager && manager.stack.length) { manager.close(); return; } historyBack(); },
|
||||
onLoadingChange(state) { this.$set(this, 'listLoading', state.loading); },
|
||||
onView(row) { this.$set(this, 'clubDetail', Object.assign({}, row || {})); const manager = window.h5HistoryLayerManager; if (manager) { manager.open('club-mineclub-detail'); return; } this.$set(this, 'clubDetailVisible', true); },
|
||||
closeClubDetail(afterClose) { const manager = window.h5HistoryLayerManager; if (manager) { manager.close('club-mineclub-detail', afterClose); return; } this.$set(this, 'clubDetailVisible', false); if (afterClose) { afterClose(); } },
|
||||
hasClubContent(value) { return value !== null && value !== undefined && String(value).replace(/<[^>]*>/g, '').replace(/ /gi, '').trim().length > 0; },
|
||||
onExit(row) { this.$set(this, 'currentRow', row); const manager = window.h5HistoryLayerManager; if (manager) { manager.open('club-mineclub-confirm'); return; } this.$set(this, 'confirmVisible', true); },
|
||||
closeConfirm(afterClose) { const manager = window.h5HistoryLayerManager; if (manager) { manager.close('club-mineclub-confirm', afterClose); return; } this.$set(this, 'confirmVisible', false); if (afterClose) { afterClose(); } },
|
||||
confirmExit() { const row = this.currentRow; this.closeConfirm(() => { this.$set(this, 'formLoading', true); this.$axios.post('/platform/club/join/apply/submit', {data: JSON.stringify(row), mode: false}).then((res) => { if (res.code === 0) { this.$toast(res.msg); const manager = window.h5HistoryLayerManager; if (manager) { manager.closeAll(() => { this.$pjaxReplace('/platform/club/join/mine/h5'); }); } else { this.$pjaxReplace('/platform/club/join/mine/h5'); } } }).finally(() => { this.$set(this, 'formLoading', false); }); }); },
|
||||
doSearch() { this.$nextTick(() => { this.$set(this.pageForm, 'pageNumber', 1); this.$set(this.pageForm, 'totalCount', 0); this.$refs.tableListRef.doSearch(); }); }
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
+3
-3
@@ -15,7 +15,7 @@ layout("/layouts/platform_h5.html"){
|
||||
v-model="pageForm.searchKeyword"
|
||||
></van-search>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
@change="(val)=>{$set(this.pageForm, 'approval', val==='1');this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
@@ -80,9 +80,9 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-cell-group>
|
||||
<!-- 按钮区域 -->
|
||||
<div class="form-actions">
|
||||
<van-button type="danger" @click="handleTaskAction(6)">退回到发起人</van-button>
|
||||
<van-button type="danger" @click="handleTaskAction(2)">拒绝申请</van-button>
|
||||
<van-button type="primary" @click="handleTaskAction(1)">同意申请</van-button>
|
||||
<van-button type="danger" @click="handleTaskAction(2)">拒绝申请</van-button>
|
||||
<van-button type="danger" @click="handleTaskAction(6)">退回到发起人</van-button>
|
||||
</div>
|
||||
</van-form>
|
||||
</div>
|
||||
|
||||
+3
-3
@@ -18,7 +18,7 @@ layout("/layouts/platform_h5.html"){
|
||||
<year-van-dropdown-item :num="5" @change="doSearch" v-model="pageForm.year"></year-van-dropdown-item>
|
||||
</van-dropdown-menu>-->
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
@change="(val)=>{$set(this.pageForm, 'approval', val==='1');this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
@@ -82,9 +82,9 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-cell-group>
|
||||
<!-- 按钮区域 -->
|
||||
<div class="form-actions">
|
||||
<van-button type="danger" @click="handleTaskAction(6)">退回到发起人</van-button>
|
||||
<van-button type="danger" @click="handleTaskAction(2)">拒绝申请</van-button>
|
||||
<van-button type="primary" @click="handleTaskAction(1)">同意申请</van-button>
|
||||
<van-button type="danger" @click="handleTaskAction(2)">拒绝申请</van-button>
|
||||
<van-button type="danger" @click="handleTaskAction(6)">退回到发起人</van-button>
|
||||
</div>
|
||||
</van-form>
|
||||
</div>
|
||||
|
||||
+41
-41
@@ -24,7 +24,7 @@ layout("/layouts/platform_h5.html"){
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
@change="(val)=>{$set(this.pageForm, 'approval', val==='1');this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
@@ -72,9 +72,9 @@ layout("/layouts/platform_h5.html"){
|
||||
></van-field>
|
||||
</van-form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(20)">不同意</van-button>
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">同意</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(20)">不同意</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</leave-info>
|
||||
@@ -106,18 +106,20 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async onReady() {
|
||||
const typeList = await this.queryMeetingType()
|
||||
this.typeOptions = [
|
||||
{
|
||||
text: "全部类型",
|
||||
value: null
|
||||
}
|
||||
].concat(typeList.map((v) => ({ text: v.name, value: v.id })))
|
||||
onReady() {
|
||||
return this.queryMeetingType().then(typeList => {
|
||||
this.typeOptions = [{
|
||||
text: "全部类型",
|
||||
value: null
|
||||
}].concat(typeList.map(v => ({
|
||||
text: v.name,
|
||||
value: v.id
|
||||
})));
|
||||
if (this.typeOptions.length > 0) {
|
||||
this.pageForm.type = this.typeOptions[0].value
|
||||
this.doSearch()
|
||||
this.pageForm.type = this.typeOptions[0].value;
|
||||
this.doSearch();
|
||||
}
|
||||
});
|
||||
},
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
@@ -131,31 +133,28 @@ layout("/layouts/platform_h5.html"){
|
||||
taskName: row.curTaskName
|
||||
}
|
||||
},
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate();
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: val
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.infoRef.onClose()
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
|
||||
})
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
handleTaskAction(val) {
|
||||
return Promise.resolve().then(() => {
|
||||
return this.$refs.formRef.validate().then(() => {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: val
|
||||
})
|
||||
}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.infoRef.onClose();
|
||||
this.$toast.success(res.msg);
|
||||
this.doSearch();
|
||||
}
|
||||
});
|
||||
}).catch(() => {});
|
||||
});
|
||||
}).catch(error => {});
|
||||
},
|
||||
onRevoke(row){
|
||||
this.$dialog.confirm({
|
||||
@@ -170,9 +169,10 @@ layout("/layouts/platform_h5.html"){
|
||||
})
|
||||
})
|
||||
},
|
||||
async queryMeetingType() {
|
||||
const res = await this.$axios.post('/platform/meeting/type/queryMeetingType')
|
||||
return res.data
|
||||
queryMeetingType() {
|
||||
return this.$axios.post('/platform/meeting/type/queryMeetingType').then(res => {
|
||||
return res.data;
|
||||
});
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
|
||||
+41
-41
@@ -24,7 +24,7 @@ layout("/layouts/platform_h5.html"){
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
@change="(val)=>{$set(this.pageForm, 'approval', val==='1');this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
@@ -72,9 +72,9 @@ layout("/layouts/platform_h5.html"){
|
||||
></van-field>
|
||||
</van-form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(20)">不同意</van-button>
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">同意</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(20)">不同意</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</leave-info>
|
||||
@@ -106,18 +106,20 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async onReady() {
|
||||
const typeList = await this.queryMeetingType()
|
||||
this.typeOptions = [
|
||||
{
|
||||
text: "全部类型",
|
||||
value: null
|
||||
}
|
||||
].concat(typeList.map((v) => ({ text: v.name, value: v.id })))
|
||||
onReady() {
|
||||
return this.queryMeetingType().then(typeList => {
|
||||
this.typeOptions = [{
|
||||
text: "全部类型",
|
||||
value: null
|
||||
}].concat(typeList.map(v => ({
|
||||
text: v.name,
|
||||
value: v.id
|
||||
})));
|
||||
if (this.typeOptions.length > 0) {
|
||||
this.pageForm.type = this.typeOptions[0].value
|
||||
this.doSearch()
|
||||
this.pageForm.type = this.typeOptions[0].value;
|
||||
this.doSearch();
|
||||
}
|
||||
});
|
||||
},
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
@@ -131,31 +133,28 @@ layout("/layouts/platform_h5.html"){
|
||||
taskName: row.curTaskName
|
||||
}
|
||||
},
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate();
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: val
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.infoRef.onClose()
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
|
||||
})
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
handleTaskAction(val) {
|
||||
return Promise.resolve().then(() => {
|
||||
return this.$refs.formRef.validate().then(() => {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: val
|
||||
})
|
||||
}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.infoRef.onClose();
|
||||
this.$toast.success(res.msg);
|
||||
this.doSearch();
|
||||
}
|
||||
});
|
||||
}).catch(() => {});
|
||||
});
|
||||
}).catch(error => {});
|
||||
},
|
||||
onRevoke(row){
|
||||
this.$dialog.confirm({
|
||||
@@ -170,9 +169,10 @@ layout("/layouts/platform_h5.html"){
|
||||
})
|
||||
})
|
||||
},
|
||||
async queryMeetingType() {
|
||||
const res = await this.$axios.post('/platform/meeting/type/queryMeetingType')
|
||||
return res.data
|
||||
queryMeetingType() {
|
||||
return this.$axios.post('/platform/meeting/type/queryMeetingType').then(res => {
|
||||
return res.data;
|
||||
});
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
|
||||
+3
-3
@@ -15,7 +15,7 @@ layout("/layouts/platform_h5.html"){
|
||||
v-model="pageForm.searchKeyword"
|
||||
></van-search>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
@change="(val)=>{$set(this.pageForm, 'approval', val==='1');this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
@@ -78,9 +78,9 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-field>
|
||||
<!-- 按钮区域 -->
|
||||
<div class="form-actions">
|
||||
<van-button @click="handleTaskAction(6)">退回到发起人</van-button>
|
||||
<van-button type="danger" @click="handleTaskAction(2)">拒绝申请</van-button>
|
||||
<van-button type="primary" @click="handleTaskAction(1)">同意申请</van-button>
|
||||
<van-button type="danger" @click="handleTaskAction(2)">拒绝申请</van-button>
|
||||
<van-button @click="handleTaskAction(6)">退回到发起人</van-button>
|
||||
</div>
|
||||
</van-form>
|
||||
</div>
|
||||
|
||||
+3
-3
@@ -15,7 +15,7 @@ layout("/layouts/platform_h5.html"){
|
||||
v-model="pageForm.searchKeyword"
|
||||
></van-search>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
@change="(val)=>{$set(this.pageForm, 'approval', val==='1');this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
@@ -78,9 +78,9 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-field>
|
||||
<!-- 按钮区域 -->
|
||||
<div class="form-actions">
|
||||
<van-button @click="handleTaskAction(6)">退回到发起人</van-button>
|
||||
<van-button type="danger" @click="handleTaskAction(2)">拒绝申请</van-button>
|
||||
<van-button type="primary" @click="handleTaskAction(1)">同意申请</van-button>
|
||||
<van-button type="danger" @click="handleTaskAction(2)">拒绝申请</van-button>
|
||||
<van-button @click="handleTaskAction(6)">退回到发起人</van-button>
|
||||
</div>
|
||||
</van-form>
|
||||
</div>
|
||||
|
||||
+3
-3
@@ -15,7 +15,7 @@ layout("/layouts/platform_h5.html"){
|
||||
v-model="pageForm.searchKeyword"
|
||||
></van-search>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
@change="(val)=>{$set(this.pageForm, 'approval', val==='1');this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
@@ -78,9 +78,9 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-field>
|
||||
<!-- 按钮区域 -->
|
||||
<div class="form-actions">
|
||||
<van-button @click="handleTaskAction(6)">退回到发起人</van-button>
|
||||
<van-button type="danger" @click="handleTaskAction(2)">拒绝申请</van-button>
|
||||
<van-button type="primary" @click="handleTaskAction(1)">同意申请</van-button>
|
||||
<van-button type="danger" @click="handleTaskAction(2)">拒绝申请</van-button>
|
||||
<van-button @click="handleTaskAction(6)">退回到发起人</van-button>
|
||||
</div>
|
||||
</van-form>
|
||||
</div>
|
||||
|
||||
+11
-8
@@ -15,7 +15,7 @@ layout("/layouts/platform_h5.html"){
|
||||
v-model="pageForm.searchKeyword"
|
||||
></van-search>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
@change="(val)=>{$set(this.pageForm, 'approval', val==='1');this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
@@ -82,15 +82,15 @@ layout("/layouts/platform_h5.html"){
|
||||
show-toolbar
|
||||
:columns="detailsTypeOption.map(i => i.name)"
|
||||
@confirm="onDetailsTypeConfirm"
|
||||
@cancel="showDetailsTypePopup = false"
|
||||
@cancel="$set($data, 'showDetailsTypePopup', false)"
|
||||
|
||||
></van-picker>
|
||||
</van-popup>
|
||||
<!-- 按钮区域 -->
|
||||
<div class="form-actions">
|
||||
<van-button @click="handleTaskAction(6)">退回到发起人</van-button>
|
||||
<van-button type="danger" @click="handleTaskAction(2)">拒绝申请</van-button>
|
||||
<van-button type="primary" @click="openHandleTaskAction">同意申请</van-button>
|
||||
<van-button type="danger" @click="handleTaskAction(2)">拒绝申请</van-button>
|
||||
<van-button @click="handleTaskAction(6)">退回到发起人</van-button>
|
||||
</div>
|
||||
</van-form>
|
||||
</div>
|
||||
@@ -127,10 +127,13 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async openHandleTaskAction() {
|
||||
await this.$refs.formRef.validate();
|
||||
this.detailsTypeOption = await this.$businessTool.getDictOptions("ACTIVITY_BUDGET_DETAILS_TYPE")
|
||||
this.showDetailsTypePopup = true
|
||||
openHandleTaskAction() {
|
||||
return this.$refs.formRef.validate().then(() => {
|
||||
return this.$businessTool.getDictOptions("ACTIVITY_BUDGET_DETAILS_TYPE").then(resolvedValue4 => {
|
||||
this.detailsTypeOption = resolvedValue4;
|
||||
this.showDetailsTypePopup = true;
|
||||
});
|
||||
});
|
||||
},
|
||||
onDetailsTypeConfirm(value, index) {
|
||||
this.formData.detailsType = this.detailsTypeOption[index].value
|
||||
|
||||
+3
-3
@@ -15,7 +15,7 @@ layout("/layouts/platform_h5.html"){
|
||||
v-model="pageForm.searchKeyword"
|
||||
></van-search>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
@change="(val)=>{$set(this.pageForm, 'approval', val==='1');this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
@@ -78,9 +78,9 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-field>
|
||||
<!-- 按钮区域 -->
|
||||
<div class="form-actions">
|
||||
<van-button @click="handleTaskAction(6)">退回到发起人</van-button>
|
||||
<van-button type="danger" @click="handleTaskAction(2)">拒绝申请</van-button>
|
||||
<van-button type="primary" @click="handleTaskAction(1)">同意申请</van-button>
|
||||
<van-button type="danger" @click="handleTaskAction(2)">拒绝申请</van-button>
|
||||
<van-button @click="handleTaskAction(6)">退回到发起人</van-button>
|
||||
</div>
|
||||
</van-form>
|
||||
</div>
|
||||
|
||||
+3
-3
@@ -15,7 +15,7 @@ layout("/layouts/platform_h5.html"){
|
||||
v-model="pageForm.searchKeyword"
|
||||
></van-search>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
@change="(val)=>{$set(this.pageForm, 'approval', val==='1');this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
@@ -78,9 +78,9 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-field>
|
||||
<!-- 按钮区域 -->
|
||||
<div class="form-actions">
|
||||
<van-button @click="handleTaskAction(6)">退回到发起人</van-button>
|
||||
<van-button type="danger" @click="handleTaskAction(2)">拒绝申请</van-button>
|
||||
<van-button type="primary" @click="handleTaskAction(1)">同意申请</van-button>
|
||||
<van-button type="danger" @click="handleTaskAction(2)">拒绝申请</van-button>
|
||||
<van-button @click="handleTaskAction(6)">退回到发起人</van-button>
|
||||
</div>
|
||||
</van-form>
|
||||
</div>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+41
-41
@@ -24,7 +24,7 @@ layout("/layouts/platform_h5.html"){
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
@change="(val)=>{$set(this.pageForm, 'approval', val==='1');this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
@@ -71,9 +71,9 @@ layout("/layouts/platform_h5.html"){
|
||||
></van-field>
|
||||
</van-form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(20)">不同意</van-button>
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">同意</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(20)">不同意</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</info>
|
||||
@@ -105,18 +105,20 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async onReady() {
|
||||
const typeList = await this.querySiteType()
|
||||
this.typeOptions = [
|
||||
{
|
||||
text: "全部类型",
|
||||
value: null
|
||||
}
|
||||
].concat(typeList.map((v) => ({ text: v.name, value: v.id })))
|
||||
onReady() {
|
||||
return this.querySiteType().then(typeList => {
|
||||
this.typeOptions = [{
|
||||
text: "全部类型",
|
||||
value: null
|
||||
}].concat(typeList.map(v => ({
|
||||
text: v.name,
|
||||
value: v.id
|
||||
})));
|
||||
if (this.typeOptions.length > 0) {
|
||||
this.pageForm.siteType = this.typeOptions[0].value
|
||||
this.doSearch()
|
||||
this.pageForm.siteType = this.typeOptions[0].value;
|
||||
this.doSearch();
|
||||
}
|
||||
});
|
||||
},
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
@@ -130,31 +132,28 @@ layout("/layouts/platform_h5.html"){
|
||||
taskName: row.curTaskName
|
||||
}
|
||||
},
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate();
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: val
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.infoRef.onClose()
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
|
||||
})
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
handleTaskAction(val) {
|
||||
return Promise.resolve().then(() => {
|
||||
return this.$refs.formRef.validate().then(() => {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: val
|
||||
})
|
||||
}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.infoRef.onClose();
|
||||
this.$toast.success(res.msg);
|
||||
this.doSearch();
|
||||
}
|
||||
});
|
||||
}).catch(() => {});
|
||||
});
|
||||
}).catch(error => {});
|
||||
},
|
||||
onRevoke(row){
|
||||
this.$dialog.confirm({
|
||||
@@ -169,9 +168,10 @@ layout("/layouts/platform_h5.html"){
|
||||
})
|
||||
})
|
||||
},
|
||||
async querySiteType() {
|
||||
const res = await this.$axios.post("/platform/site/type/querySiteType")
|
||||
return res.data
|
||||
querySiteType() {
|
||||
return this.$axios.post("/platform/site/type/querySiteType").then(res => {
|
||||
return res.data;
|
||||
});
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
|
||||
+46
-46
@@ -176,9 +176,9 @@ layout("/layouts/platform_h5.html"){
|
||||
></van-field>
|
||||
</van-form>
|
||||
<div style="display:flex;justify-content:space-between;column-gap:10px;padding:10px;">
|
||||
<van-button type="info" block :loading="auditLoading" :disabled="auditLoading" @click="handleTaskAction(6)">退回</van-button>
|
||||
<van-button type="danger" block :loading="auditLoading" :disabled="auditLoading" @click="handleTaskAction(2)">不同意</van-button>
|
||||
<van-button type="primary" block :loading="auditLoading" :disabled="auditLoading" @click="handleTaskAction(1)">同意</van-button>
|
||||
<van-button type="danger" block :loading="auditLoading" :disabled="auditLoading" @click="handleTaskAction(2)">不同意</van-button>
|
||||
<van-button type="info" block :loading="auditLoading" :disabled="auditLoading" @click="handleTaskAction(6)">退回</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</info>
|
||||
@@ -225,11 +225,13 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
methods: {
|
||||
historyBack,
|
||||
async onReady() {
|
||||
this.installTableListFoldHook()
|
||||
await this.querySiteType()
|
||||
await this.querySites()
|
||||
this.doSearch()
|
||||
onReady() {
|
||||
this.installTableListFoldHook();
|
||||
return this.querySiteType().then(() => {
|
||||
return this.querySites().then(() => {
|
||||
this.doSearch();
|
||||
});
|
||||
});
|
||||
},
|
||||
onApprovalTabChange(val) {
|
||||
this.pageForm.approval = val === '1'
|
||||
@@ -354,46 +356,44 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
},
|
||||
async handleTaskAction(submitType) {
|
||||
if (this.auditLoading) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
await this.$refs.formRef.validate()
|
||||
this.$dialog.confirm({
|
||||
handleTaskAction(submitType) {
|
||||
if (this.auditLoading) {
|
||||
return;
|
||||
}
|
||||
return Promise.resolve().then(() => {
|
||||
return this.$refs.formRef.validate().then(() => {
|
||||
this.$dialog.confirm({
|
||||
title: '提示',
|
||||
message: this.formData.yearlyBatch ? '该记录属于“预约本月”批量预约,提交后将一并审核同批次的 ' + (this.formData.batchAuditCount || 0) + ' 条预约记录,是否继续?' : '您确定要提交吗?'
|
||||
}).then(() => {
|
||||
this.auditLoading = true;
|
||||
this.$axios.post('/platform/siteCug/schoolUnionAudit/executeTask', {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: submitType
|
||||
})
|
||||
}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.infoRef.onClose();
|
||||
this.$toast.success(res.msg || '提交成功');
|
||||
this.doSearch();
|
||||
} else {
|
||||
this.$dialog.alert({
|
||||
title: '提示',
|
||||
message: res.msg || '提交失败'
|
||||
}).catch(() => {});
|
||||
}
|
||||
}).catch(err => {
|
||||
this.$dialog.alert({
|
||||
title: '提示',
|
||||
message: this.formData.yearlyBatch
|
||||
? ('该记录属于“预约本月”批量预约,提交后将一并审核同批次的 ' + (this.formData.batchAuditCount || 0) + ' 条预约记录,是否继续?')
|
||||
: '您确定要提交吗?',
|
||||
}).then(() => {
|
||||
this.auditLoading = true
|
||||
this.$axios.post('/platform/siteCug/schoolUnionAudit/executeTask', {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: submitType,
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.infoRef.onClose()
|
||||
this.$toast.success(res.msg || '提交成功')
|
||||
this.doSearch()
|
||||
} else {
|
||||
this.$dialog.alert({
|
||||
title: '提示',
|
||||
message: res.msg || '提交失败',
|
||||
}).catch(() => {})
|
||||
}
|
||||
}).catch((err) => {
|
||||
this.$dialog.alert({
|
||||
title: '提示',
|
||||
message: (err && err.msg) || '提交失败',
|
||||
}).catch(() => {})
|
||||
}).finally(() => {
|
||||
this.auditLoading = false
|
||||
})
|
||||
}).catch(() => {})
|
||||
} catch (e) {
|
||||
}
|
||||
message: err && err.msg || '提交失败'
|
||||
}).catch(() => {});
|
||||
}).finally(() => {
|
||||
this.auditLoading = false;
|
||||
});
|
||||
}).catch(() => {});
|
||||
});
|
||||
}).catch(e => {});
|
||||
},
|
||||
onRevoke(row) {
|
||||
if (!this.canRevoke(row) || this.revokeLoading) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+412
-45
@@ -2,34 +2,36 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
<style>
|
||||
.tour-approval-page {
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #f4f6f8;
|
||||
background: #f4f8ff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-approval-sticky {
|
||||
flex-shrink: 0;
|
||||
background: #f4f6f8;
|
||||
padding: 8px 12px 10px;
|
||||
background: #f4f8ff;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll {
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding-bottom: 18px;
|
||||
padding: 2px 12px 18px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-approval-search /deep/ .van-search__content,
|
||||
.tour-approval-search .van-search__content {
|
||||
border-radius: 8px;
|
||||
border-radius: 18px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 4px 16px rgba(34, 94, 170, 0.06);
|
||||
}
|
||||
|
||||
.tour-card-tags {
|
||||
@@ -39,12 +41,36 @@ layout("/layouts/platform_h5.html"){
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.tour-card-heading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.tour-card-person {
|
||||
overflow: hidden;
|
||||
color: #17233d;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tour-card-job-no {
|
||||
margin-left: 7px;
|
||||
color: #64748b;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.tour-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 22px;
|
||||
padding: 0 8px;
|
||||
border-radius: 4px;
|
||||
border-radius: 999px;
|
||||
background: #eef6ff;
|
||||
color: #0b75bd;
|
||||
font-size: 12px;
|
||||
@@ -60,17 +86,24 @@ layout("/layouts/platform_h5.html"){
|
||||
color: #d97706;
|
||||
}
|
||||
|
||||
.tour-approval-detail {
|
||||
height: 100%;
|
||||
background: #f4f8ff;
|
||||
}
|
||||
|
||||
.tour-approval-sheet {
|
||||
max-height: 86vh;
|
||||
height: calc(100% - 46px);
|
||||
overflow-y: auto;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
background: #f4f6f8;
|
||||
padding: 2px 0 calc(86px + env(safe-area-inset-bottom));
|
||||
background: #f4f8ff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-section {
|
||||
margin: 10px 12px;
|
||||
overflow: hidden;
|
||||
border-radius: 8px;
|
||||
border-radius: 14px;
|
||||
box-shadow: 0 4px 16px rgba(34, 94, 170, 0.06);
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
@@ -78,7 +111,7 @@ layout("/layouts/platform_h5.html"){
|
||||
position: relative;
|
||||
padding: 14px 16px;
|
||||
border-bottom: 1px solid #edf0f4;
|
||||
color: #0b75bd;
|
||||
color: #17233d;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
@@ -92,7 +125,7 @@ layout("/layouts/platform_h5.html"){
|
||||
width: 30px;
|
||||
height: 4px;
|
||||
border-radius: 0 0 3px 3px;
|
||||
background: #0b75bd;
|
||||
background: #1677ff;
|
||||
}
|
||||
|
||||
.tour-approval-actions {
|
||||
@@ -106,9 +139,303 @@ layout("/layouts/platform_h5.html"){
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.tour-approval-sticky /deep/ .van-dropdown-menu__bar,
|
||||
.tour-approval-sticky .van-dropdown-menu__bar {
|
||||
height: 44px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 16px rgba(34, 94, 170, 0.06);
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll /deep/ .table-list-card,
|
||||
.tour-approval-list-scroll /deep/ .list-card {
|
||||
border-radius: 14px;
|
||||
box-shadow: 0 4px 16px rgba(34, 94, 170, 0.06);
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll /deep/ .action-btn {
|
||||
color: #1677ff;
|
||||
}
|
||||
|
||||
<!--#include("../common/theme.css"){}#-->
|
||||
|
||||
/* 审核列表与提案校工会预审核采用同一信息层级和卡片规范。 */
|
||||
body {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-approval-page {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-approval-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.tour-approval-page .van-nav-bar__title {
|
||||
color: #172033;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-approval-sticky {
|
||||
padding: 22px 12px 1px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-approval-search {
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.tour-approval-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.tour-approval-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tour-approval-filter {
|
||||
margin-bottom: 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
transition: border-radius .18s ease;
|
||||
}
|
||||
|
||||
.tour-approval-filter.is-open {
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-menu__bar,
|
||||
.tour-approval-filter .van-dropdown-menu__item,
|
||||
.tour-approval-filter .van-dropdown-menu__title {
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-menu__bar {
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-menu__title {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: #66758a;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-menu__title--active,
|
||||
.tour-approval-filter .van-dropdown-item__option--active,
|
||||
.tour-approval-filter .van-dropdown-item__option--active .van-dropdown-item__icon {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
margin: 0 12px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0 0 12px 12px;
|
||||
box-shadow: 0 10px 24px rgba(31, 65, 108, .14);
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-item__option {
|
||||
display: flex;
|
||||
min-height: 48px;
|
||||
padding: 0 16px;
|
||||
align-items: center;
|
||||
color: #46566c;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll {
|
||||
padding: 2px 12px 24px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll .empty-state {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tour-approval-empty {
|
||||
display: flex;
|
||||
min-height: 280px;
|
||||
padding: 46px 18px 36px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tour-approval-empty img {
|
||||
display: block;
|
||||
width: 60%;
|
||||
max-width: 190px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.tour-approval-empty__title {
|
||||
margin-top: 10px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-approval-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.tour-card-heading {
|
||||
margin: 0 0 7px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.tour-card-heading-main {
|
||||
min-width: 0;
|
||||
padding-right: 10px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.tour-card-person {
|
||||
color: #253247;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-card-job-no {
|
||||
display: block;
|
||||
margin: 1px 0 0;
|
||||
color: #9ba6b6;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.tour-card-status {
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.tour-card-tags {
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll .action-btn {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll .action-btn .van-icon {
|
||||
margin-right: 6px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.tour-approval-detail,
|
||||
.tour-approval-sheet {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-approval-sheet {
|
||||
padding: 18px 12px calc(92px + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.tour-section {
|
||||
margin: 0 0 11px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #e9eff7;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 3px 11px rgba(51, 87, 126, .08);
|
||||
}
|
||||
|
||||
.tour-section-title {
|
||||
position: relative;
|
||||
padding: 12px 14px 8px 21px;
|
||||
border-bottom: 0;
|
||||
color: #354255;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-section-title::before {
|
||||
top: 15px;
|
||||
bottom: 11px;
|
||||
left: 12px;
|
||||
width: 2px;
|
||||
height: auto;
|
||||
border-radius: 2px;
|
||||
background-color: #1989fa;
|
||||
}
|
||||
|
||||
.tour-section .van-cell {
|
||||
min-height: 44px;
|
||||
padding: 10px 14px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.tour-section .van-cell__title {
|
||||
flex: 0 0 92px;
|
||||
width: 92px;
|
||||
color: #596779;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tour-section .van-cell__value {
|
||||
color: #4f5d70;
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.tour-section .tour-approval-opinion {
|
||||
width: calc(100% - 28px);
|
||||
margin: 0 14px 14px;
|
||||
padding: 12px;
|
||||
border: 1px solid #c9d5e5;
|
||||
border-radius: 10px;
|
||||
background-color: #f7f9fd;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-approval-actions {
|
||||
gap: 10px;
|
||||
padding: 0 14px 14px;
|
||||
}
|
||||
|
||||
.tour-approval-actions .van-button {
|
||||
height: 40px;
|
||||
border-radius: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@media (max-width: 350px) {
|
||||
.tour-approval-sticky,
|
||||
.tour-approval-list-scroll {
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" class="tour-approval-page" v-cloak>
|
||||
<div id="app" class="tour-approval-page tour-h5-theme" v-cloak>
|
||||
<van-nav-bar title="校工会审核" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
|
||||
<van-sticky offset-top="46px" class="tour-approval-sticky">
|
||||
@@ -116,27 +443,39 @@ layout("/layouts/platform_h5.html"){
|
||||
class="tour-approval-search"
|
||||
v-model="pageForm.keyword"
|
||||
placeholder="请输入工号/姓名/线路搜索"
|
||||
show-action
|
||||
clearable
|
||||
input-align="left"
|
||||
@search="doSearch"
|
||||
@clear="doSearch">
|
||||
<template #action>
|
||||
<div @click="doSearch">搜索</div>
|
||||
</template>
|
||||
</van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item :options="auditOptions" @change="doSearch" v-model="pageForm.audit"></van-dropdown-item>
|
||||
<van-dropdown-item :options="unionOptions" @change="doSearch" v-model="pageForm.unionId"></van-dropdown-item>
|
||||
<van-dropdown-item :options="lineTypeOptions" @change="doSearch" v-model="pageForm.lineType"></van-dropdown-item>
|
||||
<van-dropdown-menu class="tour-approval-filter" :class="{'is-open': filterOpened}" active-color="#1989fa" :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item :options="auditOptions" @change="doSearch" @open="onFilterOpen" @close="onFilterClose" v-model="pageForm.audit"></van-dropdown-item>
|
||||
<van-dropdown-item :options="unionOptions" @change="doSearch" @open="onFilterOpen" @close="onFilterClose" v-model="pageForm.unionId"></van-dropdown-item>
|
||||
<van-dropdown-item :options="lineTypeOptions" @change="doSearch" @open="onFilterOpen" @close="onFilterClose" v-model="pageForm.lineType"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</van-sticky>
|
||||
|
||||
<div class="tour-approval-list-scroll">
|
||||
<table-list api="/platform/tour/schoolUnionApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" title="userName" @ready="onReady">
|
||||
<div v-if="pageSkeletonLoading" class="tour-content-skeleton">
|
||||
<div class="tour-content-skeleton__card" v-for="index in 3" :key="'school-approval-skeleton-' + index"></div>
|
||||
</div>
|
||||
<div v-if="!pageSkeletonLoading && pageForm.totalCount === 0" class="tour-approval-empty">
|
||||
<img src="/assets/platform/images/tour/tour-h5-empty-v3.png?v=20260831" alt="暂无审核记录插画">
|
||||
<div class="tour-approval-empty__title">暂无审核记录</div>
|
||||
<div class="tour-approval-empty__hint">当前筛选条件下暂时没有疗休养报名</div>
|
||||
</div>
|
||||
<table-list v-show="!pageSkeletonLoading" api="/platform/tour/schoolUnionApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" title="userName" :show_loading_overlay="false" @ready="onReady" @loading-change="onTableLoading">
|
||||
<template #header="{index,row}">
|
||||
<div class="tour-card-heading">
|
||||
<div class="tour-card-heading-main">
|
||||
<div class="tour-card-person">{{ row.userName || '--' }}</div>
|
||||
<div class="tour-card-job-no">工号:{{ row.jobNo || '--' }}</div>
|
||||
</div>
|
||||
<span class="tour-h5-tag tour-card-status" :class="row.taskState === 10 ? 'is-warning' : 'is-success'">{{ row.curTaskName || (row.taskState === 10 ? '待审核' : '已处理') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot="{index,row}">
|
||||
<div class="tour-card-tags">
|
||||
<span v-if="row.jobNo" class="tour-tag">{{ row.jobNo }}</span>
|
||||
<span v-if="row.lineType" class="tour-tag gray">{{ row.lineType }}</span>
|
||||
<span v-if="row.overCostReimbursed" class="tour-tag warn">报销超出费用</span>
|
||||
</div>
|
||||
@@ -156,11 +495,11 @@ layout("/layouts/platform_h5.html"){
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<van-icon name="eye-o"></van-icon>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
|
||||
<i class="fa fa-check"></i>
|
||||
<van-icon name="edit"></van-icon>
|
||||
<span>审核</span>
|
||||
</div>
|
||||
</template>
|
||||
@@ -172,6 +511,7 @@ layout("/layouts/platform_h5.html"){
|
||||
<div class="tour-section-title">{{ formData.taskName || '审核' }}</div>
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
class="tour-approval-opinion"
|
||||
v-model="formData.tf_opinion"
|
||||
name="tf_opinion"
|
||||
label="审批意见"
|
||||
@@ -185,9 +525,9 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-field>
|
||||
</van-form>
|
||||
<div class="tour-approval-actions">
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(2)">拒绝</van-button>
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">同意</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(2)">拒绝</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</tour-info>
|
||||
@@ -197,8 +537,10 @@ layout("/layouts/platform_h5.html"){
|
||||
<script nonce="${cspNonce!}">
|
||||
const TOUR_INFO = {
|
||||
template: /*language=HTML*/ `
|
||||
<van-action-sheet v-model="visible" title="报名详情">
|
||||
<div class="tour-approval-sheet">
|
||||
<van-popup v-model="visible" position="right" :style="{ width: '100%', height: '100%' }" :close-on-click-overlay="false">
|
||||
<div class="tour-approval-detail">
|
||||
<van-nav-bar title="报名详情" left-text="返回" left-arrow @click-left="onClose"></van-nav-bar>
|
||||
<div class="tour-approval-sheet">
|
||||
<div class="tour-section">
|
||||
<div class="tour-section-title">教职工信息</div>
|
||||
<van-cell title="工号" :value="detail.jobNo || ''"></van-cell>
|
||||
@@ -261,9 +603,10 @@ layout("/layouts/platform_h5.html"){
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<slot></slot>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</van-action-sheet>
|
||||
</van-popup>
|
||||
`,
|
||||
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
|
||||
data() {
|
||||
@@ -276,13 +619,15 @@ layout("/layouts/platform_h5.html"){
|
||||
allowFamily: false,
|
||||
fillBedInfo: true,
|
||||
directFamilyUnitLine: false,
|
||||
doneTasks: []
|
||||
doneTasks: [],
|
||||
popupHistoryToken: ""
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onOpen(row) {
|
||||
this.row = row || {}
|
||||
this.visible = true
|
||||
this.$set(this, "visible", true)
|
||||
window.h5PopupHistory.open(this.popupHistoryToken, "detail")
|
||||
this.detail = {}
|
||||
this.familyData = []
|
||||
this.directRelative = {}
|
||||
@@ -294,7 +639,9 @@ layout("/layouts/platform_h5.html"){
|
||||
this.getDoneTasks()
|
||||
},
|
||||
onClose() {
|
||||
this.visible = false
|
||||
if (!window.h5PopupHistory.close(this.popupHistoryToken, "detail")) {
|
||||
this.$set(this, "visible", false)
|
||||
}
|
||||
},
|
||||
info() {
|
||||
this.$axios.post("/platform/tour/schoolUnionApproval/detail", { id: this.row.id }).then((res) => {
|
||||
@@ -337,6 +684,15 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
return this.hasFamily() ? "是" : "否"
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$set(this, "popupHistoryToken", window.h5PopupHistory.register(() => {
|
||||
this.$set(this, "visible", false)
|
||||
this.$emit("closed")
|
||||
}))
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.h5PopupHistory.unregister(this.popupHistoryToken)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,7 +726,9 @@ layout("/layouts/platform_h5.html"){
|
||||
{ text: "全部线路类型", value: "" }
|
||||
],
|
||||
formData: {},
|
||||
showApprovalForm: false
|
||||
showApprovalForm: false,
|
||||
pageSkeletonLoading: true,
|
||||
filterOpened: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -378,12 +736,24 @@ layout("/layouts/platform_h5.html"){
|
||||
onReady() {
|
||||
this.doSearch()
|
||||
},
|
||||
onTableLoading(state) {
|
||||
if (state && state.initial) {
|
||||
this.$set(this, "pageSkeletonLoading", !!state.loading)
|
||||
}
|
||||
},
|
||||
onFilterOpen() {
|
||||
this.$set(this, "filterOpened", true)
|
||||
},
|
||||
onFilterClose() {
|
||||
this.$set(this, "filterOpened", false)
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(async () => {
|
||||
await Promise.all([this.loadUnionOptions(), this.loadLineTypeOptions()])
|
||||
this.$nextTick(() => {
|
||||
Promise.all([this.loadUnionOptions(), this.loadLineTypeOptions()]).then(() => {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
})
|
||||
},
|
||||
loadUnionOptions() {
|
||||
@@ -435,16 +805,12 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
},
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate()
|
||||
} catch (e) {
|
||||
return
|
||||
}
|
||||
this.$dialog.confirm({
|
||||
handleTaskAction(val) {
|
||||
this.$refs.formRef.validate().then(() => {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
}).then(() => {
|
||||
const loading = this.$toast.loading({
|
||||
message: "加载中...",
|
||||
forbidClick: true,
|
||||
@@ -467,6 +833,7 @@ layout("/layouts/platform_h5.html"){
|
||||
}).finally(() => {
|
||||
loading.close()
|
||||
})
|
||||
}).catch(() => {})
|
||||
}).catch(() => {})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,28 +40,132 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
}
|
||||
|
||||
.tour-card-title-row {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-card-actions {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.tour-family-tab {
|
||||
margin: 10px 12px 0;
|
||||
height: 30px;
|
||||
border-radius: 5px;
|
||||
background: #1684d2;
|
||||
color: #ffffff;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
line-height: 30px;
|
||||
.tour-family-tabs {
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.tour-family-tabs-shell {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tour-family-tab-arrow {
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
z-index: 2;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
padding: 0;
|
||||
border: 1px solid #d7e7fb;
|
||||
border-radius: 50%;
|
||||
color: #1989fa;
|
||||
background-color: rgba(255, 255, 255, .94);
|
||||
font-size: 15px;
|
||||
line-height: 26px;
|
||||
text-align: center;
|
||||
box-shadow: 0 2px 8px rgba(43, 73, 112, .1);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-family-tab-arrow.is-left {
|
||||
left: 7px;
|
||||
}
|
||||
|
||||
.tour-family-tab-arrow.is-right {
|
||||
right: 7px;
|
||||
}
|
||||
|
||||
.tour-family-tab-arrow:disabled {
|
||||
border-color: #edf1f6;
|
||||
color: #c5ceda;
|
||||
background-color: #f8fafc;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.tour-family-tabs.is-single {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
/* 只有一位亲属时直接展示表单,不显示没有切换意义的页签标题栏。 */
|
||||
.tour-family-tabs.is-single .van-tabs__wrap {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tour-family-tabs .van-tabs__wrap {
|
||||
height: 40px;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.tour-family-tabs .van-tabs__nav {
|
||||
background-color: #f6f9fd;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
/* 页签标题栏使用原生惯性滚动,复杂亲属表单不再参与手势拖动。 */
|
||||
.tour-family-tabs .van-tabs__wrap--scrollable .van-tabs__nav {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
width: 100%;
|
||||
justify-content: flex-start;
|
||||
scroll-behavior: smooth;
|
||||
overscroll-behavior-x: contain;
|
||||
touch-action: pan-x;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-family-tabs .van-tabs__wrap--scrollable .van-tab {
|
||||
-webkit-box-flex: 0 !important;
|
||||
-webkit-flex: 0 0 auto !important;
|
||||
flex: 0 0 auto !important;
|
||||
min-width: 88px;
|
||||
padding: 0 14px;
|
||||
color: #718198;
|
||||
font-size: 13px;
|
||||
transition: color .2s ease, background-color .2s ease;
|
||||
}
|
||||
|
||||
.tour-family-tabs .van-tab--active {
|
||||
color: #1989fa;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-family-tabs .van-tabs__line {
|
||||
width: 26px;
|
||||
height: 3px;
|
||||
border-radius: 2px;
|
||||
background-color: #1989fa;
|
||||
transition-timing-function: cubic-bezier(.22, .61, .36, 1);
|
||||
}
|
||||
|
||||
.tour-family-tabs .van-tabs__track {
|
||||
transition-timing-function: cubic-bezier(.22, .61, .36, 1) !important;
|
||||
}
|
||||
|
||||
.tour-family-tabs .van-tab__text {
|
||||
display: block;
|
||||
max-width: 112px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tour-family-form {
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.tour-field-tip {
|
||||
@@ -96,21 +200,77 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
<!--#include("../common/theme.css"){}#-->
|
||||
|
||||
.tour-apply-page {
|
||||
padding: 12px 12px 82px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-apply-card {
|
||||
margin-bottom: 10px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.tour-apply-title {
|
||||
min-height: 46px;
|
||||
padding: 0 14px 0 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom-color: #edf1f6;
|
||||
color: #202938;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.tour-apply-title::before {
|
||||
top: 15px;
|
||||
bottom: 15px;
|
||||
left: 10px;
|
||||
width: 3px;
|
||||
height: auto;
|
||||
border-radius: 2px;
|
||||
background-color: #1989fa;
|
||||
}
|
||||
|
||||
.tour-card-actions .van-button {
|
||||
height: 29px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.tour-submit-bar {
|
||||
padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
|
||||
border-top-color: #edf1f6;
|
||||
box-shadow: 0 -6px 18px rgba(38, 66, 103, .08);
|
||||
}
|
||||
|
||||
.tour-submit-bar .van-button {
|
||||
height: 42px;
|
||||
border-radius: 8px;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app">
|
||||
<div id="app" class="tour-h5-theme" v-cloak>
|
||||
<van-nav-bar title="疗休养报名" left-text="返回" left-arrow @click-left="historyBack('/platform/tour/signup/h5/signup')" fixed placeholder></van-nav-bar>
|
||||
|
||||
<div class="tour-apply-page">
|
||||
<van-loading v-if="pageLoading" size="24px" vertical>加载中...</van-loading>
|
||||
<div v-if="pageLoading" class="tour-content-skeleton">
|
||||
<div class="tour-content-skeleton__card"></div>
|
||||
<div class="tour-content-skeleton__card"></div>
|
||||
<div class="tour-content-skeleton__card"></div>
|
||||
</div>
|
||||
|
||||
<template v-else>
|
||||
<div class="tour-apply-card">
|
||||
<div class="tour-apply-title">教职工信息</div>
|
||||
<van-field label="姓名" readonly v-model="signupForm.userName"></van-field>
|
||||
<van-field label="工号" readonly v-model="signupForm.jobNo"></van-field>
|
||||
<van-field label="身份证号码" v-model="signupForm.idCard" maxlength="30" placeholder="请填写身份证号码"></van-field>
|
||||
<van-field label="手机号" v-model="signupForm.mobile" type="tel" maxlength="30" placeholder="请填写手机号"></van-field>
|
||||
<van-field required label="身份证号码" v-model="signupForm.idCard" maxlength="30" placeholder="请填写身份证号码"></van-field>
|
||||
<van-field required label="手机号" v-model="signupForm.mobile" type="tel" maxlength="30" placeholder="请填写手机号"></van-field>
|
||||
<van-field label="所属工会" readonly v-model="signupForm.unionName"></van-field>
|
||||
</div>
|
||||
|
||||
@@ -177,41 +337,81 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
当前线路不支持填写亲属
|
||||
</div>
|
||||
<template v-else-if="familyData.length > 0">
|
||||
<div class="tour-family-tab">亲属{{ familyActive + 1 }}</div>
|
||||
<van-field label="姓名" v-model="currentFamily.familyName" maxlength="100" placeholder="请填写姓名"></van-field>
|
||||
<van-field label="年龄" v-model.number="currentFamily.age" type="digit" placeholder="请填写年龄"></van-field>
|
||||
<van-field label="性别">
|
||||
<template #input>
|
||||
<van-radio-group v-model="currentFamily.gender" direction="horizontal">
|
||||
<van-radio name="男">男</van-radio>
|
||||
<van-radio name="女">女</van-radio>
|
||||
</van-radio-group>
|
||||
</template>
|
||||
</van-field>
|
||||
<van-field label="身份证号码" v-model="currentFamily.idCard" maxlength="18" placeholder="请填写身份证号码" @blur="normalizeFamilyIdCard(currentFamily)"></van-field>
|
||||
<van-field label="手机号" v-model="currentFamily.mobile" maxlength="30" placeholder="请填写手机号"></van-field>
|
||||
<van-field
|
||||
label="与本人关系"
|
||||
readonly
|
||||
clickable
|
||||
is-link
|
||||
placeholder="请选择关系"
|
||||
v-model="currentFamily.relationship"
|
||||
@click="openRelationshipPicker">
|
||||
</van-field>
|
||||
<van-field
|
||||
v-if="fillBedInfo"
|
||||
label="床型"
|
||||
readonly
|
||||
clickable
|
||||
is-link
|
||||
placeholder="请选择房型"
|
||||
v-model="currentFamily.bedType"
|
||||
@click="openBedPicker('family')">
|
||||
</van-field>
|
||||
<van-field v-if="fillBedInfo" label="床位" v-model="currentFamily.bedInfo" maxlength="100" placeholder="请输入床位数量"></van-field>
|
||||
<van-field v-if="fillBedInfo" label="意向拼床人" v-model="currentFamily.intendedRoommate" maxlength="100" placeholder="请输入意向拼床人"></van-field>
|
||||
<div v-if="fillBedInfo" class="tour-field-tip">提醒:如果跟报名人员同一房间,无须选择!</div>
|
||||
<div class="tour-family-tabs-shell" :class="{ 'has-arrows': familyData.length > 4 }">
|
||||
<button
|
||||
v-if="familyData.length > 4"
|
||||
type="button"
|
||||
class="tour-family-tab-arrow is-left"
|
||||
:disabled="familyActive <= 0"
|
||||
aria-label="上一位亲属"
|
||||
@click.stop="moveFamilyTab(-1)">
|
||||
<van-icon name="arrow-left"></van-icon>
|
||||
</button>
|
||||
<van-tabs
|
||||
ref="familyTabs"
|
||||
class="tour-family-tabs"
|
||||
:class="{ 'is-single': familyData.length === 1 }"
|
||||
v-model="familyActive"
|
||||
animated
|
||||
:duration="0.28"
|
||||
:ellipsis="false"
|
||||
:swipe-threshold="3"
|
||||
color="#1989fa"
|
||||
title-active-color="#1989fa"
|
||||
@change="handleFamilyTabChange">
|
||||
<van-tab
|
||||
v-for="(family, familyIndex) in familyData"
|
||||
:key="family.id || 'family-' + familyIndex"
|
||||
:title="familyTabTitle(family, familyIndex)">
|
||||
<div class="tour-family-form">
|
||||
<van-field required label="姓名" v-model="family.familyName" maxlength="100" placeholder="请填写姓名"></van-field>
|
||||
<van-field required label="年龄" v-model.number="family.age" type="digit" placeholder="请填写年龄"></van-field>
|
||||
<van-field required label="性别">
|
||||
<template #input>
|
||||
<van-radio-group v-model="family.gender" direction="horizontal">
|
||||
<van-radio name="男">男</van-radio>
|
||||
<van-radio name="女">女</van-radio>
|
||||
</van-radio-group>
|
||||
</template>
|
||||
</van-field>
|
||||
<van-field :required="familyContactRequired(family)" label="身份证号码" v-model="family.idCard" maxlength="18" placeholder="请填写身份证号码" @blur="normalizeFamilyIdCard(family)"></van-field>
|
||||
<van-field :required="familyContactRequired(family)" label="手机号" v-model="family.mobile" type="tel" maxlength="30" placeholder="请填写手机号"></van-field>
|
||||
<van-field
|
||||
required
|
||||
label="与本人关系"
|
||||
readonly
|
||||
clickable
|
||||
is-link
|
||||
placeholder="请选择关系"
|
||||
v-model="family.relationship"
|
||||
@click="openRelationshipPicker">
|
||||
</van-field>
|
||||
<van-field
|
||||
v-if="fillBedInfo"
|
||||
label="床型"
|
||||
readonly
|
||||
clickable
|
||||
is-link
|
||||
placeholder="请选择房型"
|
||||
v-model="family.bedType"
|
||||
@click="openBedPicker('family')">
|
||||
</van-field>
|
||||
<van-field v-if="fillBedInfo" label="床位" v-model="family.bedInfo" maxlength="100" placeholder="请输入床位数量"></van-field>
|
||||
<van-field v-if="fillBedInfo" label="意向拼床人" v-model="family.intendedRoommate" maxlength="100" placeholder="请输入意向拼床人"></van-field>
|
||||
<div v-if="fillBedInfo" class="tour-field-tip">提醒:如果跟报名人员同一房间,无须选择!</div>
|
||||
</div>
|
||||
</van-tab>
|
||||
</van-tabs>
|
||||
<button
|
||||
v-if="familyData.length > 4"
|
||||
type="button"
|
||||
class="tour-family-tab-arrow is-right"
|
||||
:disabled="familyActive >= familyData.length - 1"
|
||||
aria-label="下一位亲属"
|
||||
@click.stop="moveFamilyTab(1)">
|
||||
<van-icon name="arrow"></van-icon>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
<div v-else class="tour-apply-empty">暂无亲属,请按需添加</div>
|
||||
</div>
|
||||
@@ -222,16 +422,16 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
<van-button type="info" block round :loading="submitLoading" @click="submitSignup">提交报名</van-button>
|
||||
</div>
|
||||
|
||||
<van-popup v-model="bedPickerVisible" position="bottom">
|
||||
<van-picker show-toolbar :columns="bedTypeColumns" @confirm="confirmBedType" @cancel="bedPickerVisible=false"></van-picker>
|
||||
<van-popup v-model="bedPickerVisible" position="bottom" :close-on-click-overlay="false">
|
||||
<van-picker show-toolbar :columns="bedTypeColumns" @confirm="confirmBedType" @cancel="closePicker('bed-picker')"></van-picker>
|
||||
</van-popup>
|
||||
|
||||
<van-popup v-model="relationshipPickerVisible" position="bottom">
|
||||
<van-picker show-toolbar :columns="relationshipColumns" @confirm="confirmRelationship" @cancel="relationshipPickerVisible=false"></van-picker>
|
||||
<van-popup v-model="relationshipPickerVisible" position="bottom" :close-on-click-overlay="false">
|
||||
<van-picker show-toolbar :columns="relationshipColumns" @confirm="confirmRelationship" @cancel="closePicker('relationship-picker')"></van-picker>
|
||||
</van-popup>
|
||||
|
||||
<van-popup v-model="directRelativePickerVisible" position="bottom">
|
||||
<van-picker show-toolbar :columns="directRelativeColumns" @confirm="confirmDirectRelative" @cancel="directRelativePickerVisible=false"></van-picker>
|
||||
<van-popup v-model="directRelativePickerVisible" position="bottom" :close-on-click-overlay="false">
|
||||
<van-picker show-toolbar :columns="directRelativeColumns" @confirm="confirmDirectRelative" @cancel="closePicker('direct-relative-picker')"></van-picker>
|
||||
</van-popup>
|
||||
</div>
|
||||
|
||||
@@ -255,6 +455,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
bedPickerVisible: false,
|
||||
relationshipPickerVisible: false,
|
||||
directRelativePickerVisible: false,
|
||||
popupHistoryToken: "",
|
||||
bedPickerTarget: "self",
|
||||
matterId: GetQueryString("matterId") || ""
|
||||
}
|
||||
@@ -274,6 +475,52 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 页签优先展示亲属姓名;姓名尚未填写时使用亲属序号,便于区分每份亲属表单。
|
||||
familyTabTitle(family, familyIndex) {
|
||||
const familyName = family && family.familyName ? String(family.familyName).trim() : ""
|
||||
return familyName || "亲属" + (familyIndex + 1)
|
||||
},
|
||||
// 等待页签渲染完成后再滚动定位,确保新增亲属始终展示在可视区域内。
|
||||
focusFamilyTab(familyIndex) {
|
||||
const lastIndex = Math.max(this.familyData.length - 1, 0)
|
||||
const nextIndex = Math.min(Math.max(Number(familyIndex) || 0, 0), lastIndex)
|
||||
this.$set(this, "familyActive", nextIndex)
|
||||
this.$nextTick(() => {
|
||||
const familyTabs = this.$refs.familyTabs
|
||||
if (familyTabs && typeof familyTabs.resize === "function") {
|
||||
familyTabs.resize()
|
||||
}
|
||||
this.scrollFamilyTabIntoView(nextIndex)
|
||||
})
|
||||
},
|
||||
// 将当前亲属页签平滑定位到导航可视区域中间,兼容箭头切换和直接点击页签。
|
||||
scrollFamilyTabIntoView(familyIndex) {
|
||||
const familyTabs = this.$refs.familyTabs
|
||||
const tabRoot = familyTabs && familyTabs.$el
|
||||
if (!tabRoot) return
|
||||
const tabNav = tabRoot.querySelector(".van-tabs__nav")
|
||||
const tabItems = tabRoot.querySelectorAll(".van-tab")
|
||||
const currentTab = tabItems[familyIndex]
|
||||
if (!tabNav || !currentTab) return
|
||||
const maxScrollLeft = Math.max(tabNav.scrollWidth - tabNav.clientWidth, 0)
|
||||
const targetScrollLeft = currentTab.offsetLeft - (tabNav.clientWidth - currentTab.offsetWidth) / 2
|
||||
tabNav.scrollTo({
|
||||
left: Math.min(Math.max(targetScrollLeft, 0), maxScrollLeft),
|
||||
behavior: "smooth"
|
||||
})
|
||||
},
|
||||
// 直接点击页签时,等待 Vant 更新激活状态后再执行横向定位。
|
||||
handleFamilyTabChange(familyIndex) {
|
||||
this.$nextTick(() => {
|
||||
this.scrollFamilyTabIntoView(Number(familyIndex) || 0)
|
||||
})
|
||||
},
|
||||
// 左右箭头按相邻顺序切换亲属,并复用页签组件的平滑定位能力。
|
||||
moveFamilyTab(step) {
|
||||
const nextIndex = Number(this.familyActive) + Number(step)
|
||||
if (nextIndex < 0 || nextIndex >= this.familyData.length) return
|
||||
this.focusFamilyTab(nextIndex)
|
||||
},
|
||||
formatDateTime(date) {
|
||||
const pad = (value) => String(value).padStart(2, "0")
|
||||
return date.getFullYear()
|
||||
@@ -426,13 +673,15 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
addFamily() {
|
||||
if (!this.allowFamily || this.isDirectFamilyLine(this.signupForm)) return
|
||||
this.familyData.push(this.emptyFamily())
|
||||
this.familyActive = this.familyData.length - 1
|
||||
this.focusFamilyTab(this.familyData.length - 1)
|
||||
this.signupForm.hasFamily = true
|
||||
},
|
||||
removeFamily() {
|
||||
if (this.familyData.length === 0) return
|
||||
this.familyData.splice(this.familyActive, 1)
|
||||
this.familyActive = Math.max(0, this.familyActive - 1)
|
||||
const removedIndex = this.familyActive
|
||||
this.familyData.splice(removedIndex, 1)
|
||||
// 删除当前页签后优先停留在同一位置;删除末项时回到新的最后一项。
|
||||
this.focusFamilyTab(this.familyData.length === 0 ? 0 : Math.min(removedIndex, this.familyData.length - 1))
|
||||
this.signupForm.hasFamily = this.familyData.length > 0
|
||||
},
|
||||
openBedPicker(target) {
|
||||
@@ -442,6 +691,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
}
|
||||
this.bedPickerTarget = target
|
||||
this.bedPickerVisible = true
|
||||
window.h5PopupHistory.open(this.popupHistoryToken, "bed-picker")
|
||||
},
|
||||
confirmBedType(value) {
|
||||
if (this.bedPickerTarget === "family") {
|
||||
@@ -449,7 +699,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
} else {
|
||||
this.signupForm.bedType = value
|
||||
}
|
||||
this.bedPickerVisible = false
|
||||
this.closePicker("bed-picker")
|
||||
},
|
||||
openRelationshipPicker() {
|
||||
if (this.relationshipColumns.length === 0) {
|
||||
@@ -457,10 +707,11 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
return
|
||||
}
|
||||
this.relationshipPickerVisible = true
|
||||
window.h5PopupHistory.open(this.popupHistoryToken, "relationship-picker")
|
||||
},
|
||||
confirmRelationship(value) {
|
||||
this.currentFamily.relationship = value
|
||||
this.relationshipPickerVisible = false
|
||||
this.closePicker("relationship-picker")
|
||||
},
|
||||
openDirectRelativePicker() {
|
||||
if (this.directRelativeColumns.length === 0) {
|
||||
@@ -468,12 +719,27 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
return
|
||||
}
|
||||
this.directRelativePickerVisible = true
|
||||
window.h5PopupHistory.open(this.popupHistoryToken, "direct-relative-picker")
|
||||
},
|
||||
confirmDirectRelative(value) {
|
||||
const item = value && value.item ? value.item : {}
|
||||
this.directRelativeForm.relationshipCode = item.code || ""
|
||||
this.directRelativeForm.relationshipName = item.name || value.text || ""
|
||||
this.directRelativePickerVisible = false
|
||||
this.closePicker("direct-relative-picker")
|
||||
},
|
||||
closePicker(popupKey) {
|
||||
if (!window.h5PopupHistory.close(this.popupHistoryToken, popupKey)) {
|
||||
this.syncPickerVisible(popupKey, false)
|
||||
}
|
||||
},
|
||||
syncPickerVisible(popupKey, visible) {
|
||||
if (popupKey === "bed-picker") {
|
||||
this.bedPickerVisible = visible
|
||||
} else if (popupKey === "relationship-picker") {
|
||||
this.relationshipPickerVisible = visible
|
||||
} else if (popupKey === "direct-relative-picker") {
|
||||
this.directRelativePickerVisible = visible
|
||||
}
|
||||
},
|
||||
normalizeFamilyIdCard(row) {
|
||||
if (!row || !row.idCard) return
|
||||
@@ -484,18 +750,46 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
const idCard = String(value).trim().toUpperCase()
|
||||
return /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dX]$/.test(idCard)
|
||||
},
|
||||
isBlankValue(value) {
|
||||
return value === undefined || value === null || !String(value).trim()
|
||||
},
|
||||
// 年满16周岁的亲属才强制填写身份证号码和手机号。
|
||||
familyContactRequired(family) {
|
||||
return family && !this.isBlankValue(family.age) && Number(family.age) >= 16
|
||||
},
|
||||
// 报名人身份证号码和手机号为提交报名的基础必填信息。
|
||||
validateSignupContact() {
|
||||
if (this.isBlankValue(this.signupForm.idCard)) {
|
||||
vant.Toast("请填写身份证号码")
|
||||
return false
|
||||
}
|
||||
if (this.isBlankValue(this.signupForm.mobile)) {
|
||||
vant.Toast("请填写手机号")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
validateFamilies() {
|
||||
if (!this.allowFamily || !this.signupForm.hasFamily) return true
|
||||
if (this.familyData.length === 0) {
|
||||
vant.Toast("请添加亲属信息")
|
||||
return false
|
||||
}
|
||||
const invalid = this.familyData.some(item => !item.familyName || !item.gender || !item.idCard || !item.relationship)
|
||||
if (invalid) {
|
||||
vant.Toast("请完善亲属姓名、性别、身份证号码和关系")
|
||||
const invalidBase = this.familyData.some(item => this.isBlankValue(item.familyName)
|
||||
|| this.isBlankValue(item.age)
|
||||
|| this.isBlankValue(item.gender)
|
||||
|| this.isBlankValue(item.relationship))
|
||||
if (invalidBase) {
|
||||
vant.Toast("请完善亲属姓名、年龄、性别和与本人关系")
|
||||
return false
|
||||
}
|
||||
const invalidIdCard = this.familyData.some(item => !this.isValidIdCard(item.idCard))
|
||||
const invalidContact = this.familyData.some(item => this.familyContactRequired(item)
|
||||
&& (this.isBlankValue(item.idCard) || this.isBlankValue(item.mobile)))
|
||||
if (invalidContact) {
|
||||
vant.Toast("年满16周岁的亲属必须填写身份证号码和手机号")
|
||||
return false
|
||||
}
|
||||
const invalidIdCard = this.familyData.some(item => !this.isBlankValue(item.idCard) && !this.isValidIdCard(item.idCard))
|
||||
if (invalidIdCard) {
|
||||
vant.Toast("请输入正确的亲属身份证号码")
|
||||
return false
|
||||
@@ -528,6 +822,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
},
|
||||
submitSignup() {
|
||||
if (this.pageLoading || this.submitLoading) return
|
||||
if (!this.validateSignupContact()) return
|
||||
if (!this.validateFamilies()) return
|
||||
if (!this.validateDirectRelative()) return
|
||||
const families = this.allowFamily && this.signupForm.hasFamily ? this.familyData : []
|
||||
@@ -537,13 +832,13 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
})
|
||||
this.submitLoading = true
|
||||
this.$axios.post("/platform/tour/signup/doSignup", form).then((res) => {
|
||||
this.submitLoading = false
|
||||
if (res.code === 0) {
|
||||
vant.Dialog.alert({
|
||||
title: "提示",
|
||||
message: res.msg || "报名成功",
|
||||
confirmButtonColor: "#1867b0"
|
||||
}).then(() => {
|
||||
this.$showH5PageSkeleton()
|
||||
window.location.replace("/platform/tour/signup/h5/signup")
|
||||
})
|
||||
} else {
|
||||
@@ -554,13 +849,20 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
})
|
||||
}
|
||||
}).catch(() => {
|
||||
// 接口失败提示由全局 Axios 拦截器统一展示,避免与名额已满等业务提示重复。
|
||||
}).finally(() => {
|
||||
this.submitLoading = false
|
||||
vant.Toast("报名提交失败")
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.popupHistoryToken = window.h5PopupHistory.register((popupKey) => {
|
||||
this.syncPickerVisible(popupKey, false)
|
||||
})
|
||||
this.init()
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.h5PopupHistory.unregister(this.popupHistoryToken)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -163,10 +163,123 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
box-sizing: border-box;
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
<!--#include("../common/theme.css"){}#-->
|
||||
|
||||
#app.tour-signup-h5 {
|
||||
padding-bottom: 0;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-signup-banner {
|
||||
height: 208px;
|
||||
margin: 12px 12px 0;
|
||||
border-radius: 14px;
|
||||
background-color: #1779d8;
|
||||
box-shadow: 0 8px 22px rgba(30, 112, 207, .2);
|
||||
}
|
||||
|
||||
.tour-signup-swipe img {
|
||||
height: 208px;
|
||||
}
|
||||
|
||||
.tour-signup-banner::after {
|
||||
background: linear-gradient(90deg, rgba(8, 72, 145, .74) 0%, rgba(8, 72, 145, .36) 51%, rgba(8, 72, 145, .04) 100%);
|
||||
}
|
||||
|
||||
.tour-signup-banner__text {
|
||||
left: 18px;
|
||||
bottom: 25px;
|
||||
}
|
||||
|
||||
.tour-signup-title {
|
||||
width: 180px;
|
||||
font-size: 25px;
|
||||
line-height: 1.35;
|
||||
letter-spacing: .5px;
|
||||
}
|
||||
|
||||
.tour-signup-subtitle {
|
||||
margin-top: 10px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.tour-signup-card {
|
||||
margin: 12px 12px 0;
|
||||
padding: 14px 14px 16px;
|
||||
height: calc(100vh - 352px);
|
||||
height: calc(100vh - 352px - env(safe-area-inset-bottom));
|
||||
min-height: 240px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
border-radius: 14px;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .09);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-signup-card__header {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
/* 标题栏保持固定,富文本、PDF、空状态及加载骨架只在卡片剩余区域内滚动。 */
|
||||
.tour-signup-card > .van-skeleton,
|
||||
.tour-signup-card > .tour-signup-notice,
|
||||
.tour-signup-card > .tour-signup-empty {
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.tour-signup-card__title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #202938;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.tour-signup-card__title .van-icon {
|
||||
margin-right: 7px;
|
||||
color: #1989fa;
|
||||
font-size: 19px;
|
||||
}
|
||||
|
||||
.tour-signup-card__year {
|
||||
min-height: 24px;
|
||||
padding: 2px 9px;
|
||||
border-radius: 12px;
|
||||
background-color: #eaf4ff;
|
||||
line-height: 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-signup-notice {
|
||||
font-size: 14px;
|
||||
line-height: 1.75;
|
||||
}
|
||||
|
||||
.tour-signup-footer {
|
||||
padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
|
||||
border-top: 1px solid #edf1f6;
|
||||
box-shadow: 0 -6px 18px rgba(38, 66, 103, .08);
|
||||
}
|
||||
|
||||
.tour-signup-footer-spacer {
|
||||
height: 62px;
|
||||
height: calc(62px + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.tour-signup-footer .van-button {
|
||||
height: 42px;
|
||||
border-radius: 8px;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" class="tour-signup-h5">
|
||||
<van-nav-bar title="疗休养报名" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
<div id="app" class="tour-signup-h5 tour-h5-theme" v-cloak>
|
||||
<van-nav-bar title="疗休养报名" left-text="返回" left-arrow @click-left="$pjaxReplace('/platform/h5/home')" fixed placeholder></van-nav-bar>
|
||||
|
||||
<div class="tour-signup-banner">
|
||||
<van-swipe class="tour-signup-swipe" :autoplay="3500" indicator-color="white">
|
||||
@@ -175,13 +288,14 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
</van-swipe-item>
|
||||
</van-swipe>
|
||||
<div class="tour-signup-banner__text">
|
||||
<div class="tour-signup-title">疗休养报名</div>
|
||||
<div class="tour-signup-title">工会疗休养<br>乐享健康时光</div>
|
||||
<div class="tour-signup-subtitle">放松身心 · 收获健康 · 美好同行</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tour-signup-card">
|
||||
<div class="tour-signup-card__header">
|
||||
<div class="tour-signup-card__title">服务须知</div>
|
||||
<div class="tour-signup-card__title"><van-icon name="notes-o"></van-icon>报名须知</div>
|
||||
<div class="tour-signup-card__year">{{ setting.year || currentYear }}年度</div>
|
||||
</div>
|
||||
|
||||
@@ -227,7 +341,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
store,
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
loading: true,
|
||||
currentYear: new Date().getFullYear(),
|
||||
serviceNoticePdfHref: "",
|
||||
pdfDoc: null,
|
||||
@@ -240,8 +354,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
readCountdown: 10,
|
||||
readCountdownTimer: null,
|
||||
bannerList: [
|
||||
"/assets/platform/images/tour/tour-h5-banner-1.jpg",
|
||||
"/assets/platform/images/tour/tour-h5-banner-2.jpg"
|
||||
"/assets/platform/images/tour/tour-h5-hero-v3.png?v=20260830"
|
||||
],
|
||||
setting: {
|
||||
year: "",
|
||||
@@ -419,7 +532,6 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
loadServiceNotice() {
|
||||
this.loading = true
|
||||
this.$axios.post("/platform/tour/signup/h5/serviceNotice").then((res) => {
|
||||
this.loading = false
|
||||
if (res.code === 0) {
|
||||
this.setting = Object.assign({}, this.setting, res.data || {})
|
||||
this.serviceNoticePdfHref = this.parseContentHref(this.setting.serviceNotice)
|
||||
@@ -430,6 +542,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
vant.Toast(res.msg || "服务须知加载失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
@@ -438,7 +551,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
if (this.readCountdown > 0) {
|
||||
return
|
||||
}
|
||||
window.location.href = "/platform/tour/signup/h5/signup"
|
||||
this.$pjaxReplace('/platform/tour/signup/h5/signup')
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
@@ -170,14 +170,111 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
background: #ffffff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
<!--#include("../common/theme.css"){}#-->
|
||||
|
||||
#app {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-detail-page {
|
||||
padding: 12px 12px 76px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-detail-cover {
|
||||
width: 100%;
|
||||
height: 178px;
|
||||
flex: none;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #eaf2fb;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .1);
|
||||
}
|
||||
|
||||
.tour-detail-cover .van-image__img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.tour-detail-header {
|
||||
margin-top: 10px;
|
||||
padding: 14px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.tour-detail-title {
|
||||
color: #202938;
|
||||
font-size: 18px;
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
.tour-line-tag {
|
||||
min-height: 22px;
|
||||
height: auto;
|
||||
padding: 2px 8px;
|
||||
border-radius: 11px;
|
||||
color: #1989fa;
|
||||
background-color: #eaf4ff;
|
||||
font-size: 11px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.tour-detail-meta {
|
||||
margin-top: 12px;
|
||||
padding-top: 10px;
|
||||
border-top: 1px solid #edf1f6;
|
||||
color: #35445a;
|
||||
font-size: 13px;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.tour-detail-section {
|
||||
margin-top: 10px;
|
||||
padding: 14px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.tour-detail-section-title {
|
||||
margin-bottom: 10px;
|
||||
border-left-color: #1989fa;
|
||||
color: #202938;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.tour-detail-footer {
|
||||
padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
|
||||
border-top-color: #edf1f6;
|
||||
box-shadow: 0 -6px 18px rgba(38, 66, 103, .08);
|
||||
}
|
||||
|
||||
.tour-detail-footer .van-button {
|
||||
height: 42px;
|
||||
border-radius: 8px;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app">
|
||||
<div id="app" class="tour-h5-theme" v-cloak>
|
||||
<van-nav-bar title="线路详情" left-text="返回" left-arrow @click-left="historyBack('/platform/tour/signup/h5/signup')" fixed placeholder></van-nav-bar>
|
||||
|
||||
<div class="tour-detail-page">
|
||||
<van-loading v-if="detailLoading" size="24px" vertical>加载中...</van-loading>
|
||||
<div v-if="detailLoading" class="tour-content-skeleton">
|
||||
<div class="tour-content-skeleton__cover"></div>
|
||||
<div class="tour-content-skeleton__title"></div>
|
||||
<div class="tour-content-skeleton__row"></div>
|
||||
<div class="tour-content-skeleton__row"></div>
|
||||
<div class="tour-content-skeleton__card"></div>
|
||||
</div>
|
||||
<template v-else>
|
||||
<van-image class="tour-detail-cover" :src="detailCover()" fit="cover">
|
||||
<template #loading><van-loading type="spinner" size="22"></van-loading></template>
|
||||
<template #error><van-icon name="photo-o" size="36" color="#9ba9bc"></van-icon></template>
|
||||
</van-image>
|
||||
<div class="tour-detail-header">
|
||||
<div class="tour-detail-title">{{ lineDetail.lineName || signupDetail.lineName || '线路详情' }}</div>
|
||||
<div class="tour-detail-tags">
|
||||
@@ -257,6 +354,9 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
detailCover() {
|
||||
return this.lineDetail.mobileThumb || "/assets/platform/images/tour/tour-h5-hero-v3.png?v=20260830"
|
||||
},
|
||||
travelPeriod(row) {
|
||||
if (!row) {
|
||||
return ""
|
||||
@@ -493,7 +593,6 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
this.$axios.post("/platform/tour/signup/lineDetail", { lineId: this.lineId }),
|
||||
this.$axios.post("/platform/tour/signup/signupDetail", { matterId: this.matterId })
|
||||
]).then(([lineRes, signupRes]) => {
|
||||
this.detailLoading = false
|
||||
if (lineRes.code !== 0) {
|
||||
vant.Toast(lineRes.msg || "线路详情加载失败")
|
||||
} else {
|
||||
@@ -513,8 +612,9 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
}, process)
|
||||
}
|
||||
}).catch(() => {
|
||||
this.detailLoading = false
|
||||
vant.Toast("线路详情加载失败")
|
||||
}).finally(() => {
|
||||
this.detailLoading = false
|
||||
})
|
||||
},
|
||||
onApply() {
|
||||
@@ -523,7 +623,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
return
|
||||
}
|
||||
const goApply = () => {
|
||||
window.location.href = "/platform/tour/signup/h5/apply?matterId=" + encodeURIComponent(this.matterId)
|
||||
this.$pjaxReplace("/platform/tour/signup/h5/apply?matterId=" + encodeURIComponent(this.matterId))
|
||||
}
|
||||
this.$axios.post("/platform/tour/signup/signupEligibilityNotice", { matterId: this.matterId }).then((res) => {
|
||||
if (res.code !== 0) {
|
||||
|
||||
@@ -21,6 +21,10 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-line-refresh {
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.tour-line-toolbar {
|
||||
padding: 10px 0 8px 16px;
|
||||
background: #f4f6f8;
|
||||
@@ -60,52 +64,51 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
padding: 0 0 0 6px;
|
||||
}
|
||||
|
||||
.tour-line-search-button {
|
||||
width: 42px;
|
||||
height: 38px;
|
||||
border: 0;
|
||||
border-radius: 8px;
|
||||
background: #1e88e5;
|
||||
color: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 20px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.tour-line-search-row {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 4px;
|
||||
gap: 8px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-line-union-entry {
|
||||
width: 48px;
|
||||
min-height: 42px;
|
||||
flex-shrink: 0;
|
||||
width: 100%;
|
||||
height: 44px;
|
||||
margin-top: 8px;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
color: #64748b;
|
||||
padding: 0 14px;
|
||||
border-radius: 10px;
|
||||
background: #ffffff;
|
||||
color: #66758a;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 2px;
|
||||
font-size: 11px;
|
||||
line-height: 1.2;
|
||||
justify-content: space-between;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-line-union-entry .van-icon {
|
||||
color: #64748b;
|
||||
font-size: 24px;
|
||||
font-size: 16px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.tour-line-union-entry__label {
|
||||
display: inline-flex;
|
||||
min-width: 0;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.tour-line-union-entry__text {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tour-line-union-entry--active,
|
||||
.tour-line-union-entry--active .van-icon {
|
||||
color: #0b75bd;
|
||||
@@ -376,25 +379,252 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.tour-line-thumb-loading {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, #edf2f8 25%, #f8fbff 37%, #edf2f8 63%);
|
||||
background-size: 400% 100%;
|
||||
animation: tour-content-skeleton-loading 1.35s ease infinite;
|
||||
}
|
||||
|
||||
<!--#include("../common/theme.css"){}#-->
|
||||
|
||||
.tour-line-page {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-line-toolbar {
|
||||
padding: 12px 12px 10px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-line-toolbar .van-search {
|
||||
display: flex;
|
||||
width: 0;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.tour-line-toolbar .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.tour-line-toolbar .van-search__field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tour-line-toolbar .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.tour-line-union-entry {
|
||||
color: #66758a;
|
||||
}
|
||||
|
||||
.tour-line-union-entry .van-icon {
|
||||
color: #8fa0b5;
|
||||
}
|
||||
|
||||
.tour-line-search-row .tour-line-union-entry {
|
||||
width: 52px;
|
||||
height: 42px;
|
||||
min-height: 42px;
|
||||
margin-top: 0;
|
||||
padding: 0;
|
||||
flex-shrink: 0;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
gap: 2px;
|
||||
border-radius: 0;
|
||||
color: #66758a;
|
||||
background: transparent;
|
||||
font-size: 11px;
|
||||
line-height: 1.2;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.tour-line-search-row .tour-line-union-entry .van-icon {
|
||||
color: #8fa0b5;
|
||||
font-size: 21px;
|
||||
}
|
||||
|
||||
.tour-line-search-row .tour-line-union-entry--active,
|
||||
.tour-line-search-row .tour-line-union-entry--active .van-icon {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.tour-line-shortcuts {
|
||||
gap: 8px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.tour-line-shortcut {
|
||||
min-height: 86px;
|
||||
padding: 11px 5px 9px;
|
||||
border-radius: 11px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .07);
|
||||
}
|
||||
|
||||
.tour-line-shortcut__icon {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
}
|
||||
|
||||
.tour-line-shortcut__text {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.tour-line-shortcut__hint {
|
||||
color: #9aa7b8;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.tour-line-scroll {
|
||||
padding-bottom: 18px;
|
||||
}
|
||||
|
||||
.tour-line-list {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.tour-line-card {
|
||||
display: block;
|
||||
min-height: 0;
|
||||
margin: 0 0 10px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.tour-line-thumb {
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.tour-line-main {
|
||||
position: relative;
|
||||
padding: 12px 38px 14px 14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tour-line-title {
|
||||
overflow: hidden;
|
||||
color: #303846;
|
||||
font-size: 14px;
|
||||
line-height: 21px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tour-line-type-badge,
|
||||
.tour-line-tag {
|
||||
height: auto;
|
||||
padding: 3px 8px;
|
||||
border: 0;
|
||||
border-radius: 4px;
|
||||
color: #397de0;
|
||||
background-color: #edf5ff;
|
||||
font-size: 11px;
|
||||
line-height: 16px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.tour-line-info {
|
||||
margin-top: 4px;
|
||||
padding-top: 0;
|
||||
border-top: 0;
|
||||
color: #98a2b2;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.tour-line-info span {
|
||||
color: #98a2b2;
|
||||
}
|
||||
|
||||
.tour-line-tags {
|
||||
margin-top: 10px;
|
||||
padding-top: 9px;
|
||||
gap: 6px;
|
||||
border-top: 1px solid #edf1f6;
|
||||
}
|
||||
|
||||
.tour-line-card__arrow {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 14px;
|
||||
color: #b4bdca;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.tour-line-actions {
|
||||
margin-top: 10px;
|
||||
margin-right: -24px;
|
||||
}
|
||||
|
||||
.tour-line-action {
|
||||
display: inline-flex;
|
||||
min-width: 64px;
|
||||
height: 30px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #1989fa;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 6px;
|
||||
color: #1989fa;
|
||||
background: transparent;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-line-action .van-icon {
|
||||
margin-right: 5px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.tour-line-action--danger {
|
||||
border-color: #ee4d5a;
|
||||
color: #ee4d5a;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.tour-line-action--disabled {
|
||||
border-color: #d8dee8;
|
||||
color: #b8c0cc;
|
||||
background: transparent;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" class="tour-line-page">
|
||||
<div id="app" class="tour-line-page tour-h5-theme" v-cloak>
|
||||
<van-nav-bar title="疗休养线路" left-text="返回" left-arrow @click-left="historyBack('/platform/tour/signup/h5')" fixed placeholder></van-nav-bar>
|
||||
|
||||
<div class="tour-line-toolbar">
|
||||
<div class="tour-line-search-row">
|
||||
<van-search
|
||||
v-model="pageForm.lineName"
|
||||
show-action
|
||||
clearable
|
||||
placeholder="请输入线路名称搜索"
|
||||
shape="round"
|
||||
placeholder="搜索疗休养线路"
|
||||
@search="doSearch"
|
||||
@clear="doSearch">
|
||||
<template #action>
|
||||
<button type="button" class="tour-line-search-button" @click="doSearch">
|
||||
<van-icon name="search"></van-icon>
|
||||
</button>
|
||||
</template>
|
||||
</van-search>
|
||||
<button
|
||||
type="button"
|
||||
@@ -413,6 +643,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
<img class="tour-line-shortcut__icon" src="/assets/platform/images/tour/tour-in-province.png" alt="省内线路">
|
||||
<div class="tour-line-shortcut__text">
|
||||
<div>省内线路</div>
|
||||
<div class="tour-line-shortcut__hint">发现身边美景</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -422,6 +653,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
<img class="tour-line-shortcut__icon" src="/assets/platform/images/tour/tour-out-province.png" alt="省外线路">
|
||||
<div class="tour-line-shortcut__text">
|
||||
<div>省外线路</div>
|
||||
<div class="tour-line-shortcut__hint">畅游大好河山</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -431,23 +663,29 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
<img class="tour-line-shortcut__icon" src="/assets/platform/images/tour/tour-direct-family-icon.png?v=20260524" alt="直系亲属">
|
||||
<div class="tour-line-shortcut__text">
|
||||
<div>直系亲属</div>
|
||||
<div class="tour-line-shortcut__hint">家属同行共享</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tour-line-scroll">
|
||||
<van-pull-refresh class="tour-line-refresh" v-model="refreshing" @refresh="onRefresh">
|
||||
<div v-if="initialLoading" class="tour-content-skeleton">
|
||||
<div class="tour-content-skeleton__card" v-for="index in 3" :key="'line-skeleton-' + index"></div>
|
||||
</div>
|
||||
<van-list
|
||||
v-else
|
||||
v-model="loading"
|
||||
:finished="finished"
|
||||
finished-text="没有更多了"
|
||||
:finished-text="list.length > 0 ? '没有更多了' : ''"
|
||||
@load="loadData">
|
||||
<div class="tour-line-list">
|
||||
<div class="tour-line-card" v-for="row in list" :key="row.matterId" @click="onLine(row)">
|
||||
<div class="tour-line-thumb">
|
||||
<van-image v-if="thumbUrl(row)" :src="thumbUrl(row)" fit="cover" lazy-load>
|
||||
<template #loading>
|
||||
<div class="tour-line-thumb-empty">图片加载中</div>
|
||||
<div class="tour-line-thumb-loading" aria-label="图片加载中"></div>
|
||||
</template>
|
||||
<template #error>
|
||||
<div class="tour-line-thumb-empty">暂无图片</div>
|
||||
@@ -463,10 +701,6 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
<van-icon name="good-job"></van-icon>
|
||||
</span>
|
||||
</div>
|
||||
<div class="tour-line-tags">
|
||||
<span v-if="row.lotName" class="tour-line-tag">{{ row.lotName }}</span>
|
||||
<span v-if="row.unionName" class="tour-line-tag">{{ row.unionName }}</span>
|
||||
</div>
|
||||
<div class="tour-line-info">
|
||||
<div><span>出行开始时间:</span>{{ row.travelStartTime || '暂无' }}</div>
|
||||
<div><span>出行结束时间:</span>{{ row.travelEndTime || '暂无' }}</div>
|
||||
@@ -474,6 +708,11 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
<div><span>服务单位:</span>{{ row.travelAgencyName || '暂无' }}</div>
|
||||
-->
|
||||
</div>
|
||||
<div class="tour-line-tags">
|
||||
<span v-if="row.lotName" class="tour-line-tag">{{ row.lotName }}</span>
|
||||
<span v-if="row.unionName" class="tour-line-tag">{{ row.unionName }}</span>
|
||||
</div>
|
||||
<van-icon class="tour-line-card__arrow" name="arrow"></van-icon>
|
||||
<div class="tour-line-actions">
|
||||
<button
|
||||
v-if="showSignupAction(row)"
|
||||
@@ -485,7 +724,8 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
}"
|
||||
:disabled="signupActionDisabled(row)"
|
||||
@click.stop="handleSignupAction(row)">
|
||||
{{ signupActionText(row) }}
|
||||
<van-icon :name="canRevokeSignup(row) ? 'revoke' : 'edit'"></van-icon>
|
||||
<span>{{ signupActionText(row) }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -493,10 +733,15 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
</div>
|
||||
</van-list>
|
||||
|
||||
<van-empty v-if="!loading && list.length === 0" description="暂无线路"></van-empty>
|
||||
<div v-if="!loading && list.length === 0" class="tour-h5-empty">
|
||||
<img src="/assets/platform/images/tour/tour-h5-empty-v3.png?v=20260831" alt="暂无线路插画">
|
||||
<div class="tour-h5-empty__title">暂无线路</div>
|
||||
<div class="tour-h5-empty__hint">当前筛选条件下暂未发布疗休养线路</div>
|
||||
</div>
|
||||
</van-pull-refresh>
|
||||
</div>
|
||||
|
||||
<van-popup v-model="showUnionPopup" position="bottom" round>
|
||||
<van-popup v-model="showUnionPopup" position="bottom" round :close-on-click-overlay="false" @click-overlay="closeUnionPopup">
|
||||
<div class="tour-line-union-popup">
|
||||
<div class="tour-line-union-popup__title">选择分工会</div>
|
||||
<div class="tour-line-union-popup__list">
|
||||
@@ -525,9 +770,12 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
return {
|
||||
list: [],
|
||||
loading: false,
|
||||
refreshing: false,
|
||||
initialLoading: true,
|
||||
finished: false,
|
||||
lineChecking: false,
|
||||
showUnionPopup: false,
|
||||
popupHistoryToken: "",
|
||||
unionList: [
|
||||
{id: "", name: "全部分工会"}
|
||||
],
|
||||
@@ -619,7 +867,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
return
|
||||
}
|
||||
const go = () => {
|
||||
window.location.href = "/platform/tour/signup/h5/apply?matterId=" + encodeURIComponent(row.matterId)
|
||||
this.$pjaxReplace("/platform/tour/signup/h5/apply?matterId=" + encodeURIComponent(row.matterId))
|
||||
}
|
||||
this.$axios.post("/platform/tour/signup/signupEligibilityNotice", { matterId: row.matterId }).then((res) => {
|
||||
if (res.code !== 0) {
|
||||
@@ -672,6 +920,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.list = []
|
||||
this.$set(this, "initialLoading", true)
|
||||
this.finished = false
|
||||
this.loadData()
|
||||
},
|
||||
@@ -689,17 +938,26 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
},
|
||||
openUnionPopup() {
|
||||
this.showUnionPopup = true
|
||||
if (this.popupHistoryToken) {
|
||||
window.h5PopupHistory.open(this.popupHistoryToken, "union-picker")
|
||||
}
|
||||
if (this.unionList.length <= 1) {
|
||||
this.loadUnionOptions()
|
||||
}
|
||||
},
|
||||
closeUnionPopup() {
|
||||
if (!this.popupHistoryToken || !window.h5PopupHistory.close(this.popupHistoryToken, "union-picker")) {
|
||||
this.showUnionPopup = false
|
||||
}
|
||||
},
|
||||
selectUnion(item) {
|
||||
const unionId = item && item.id ? item.id : ""
|
||||
this.showUnionPopup = false
|
||||
if (this.pageForm.unionId === unionId) {
|
||||
this.closeUnionPopup()
|
||||
return
|
||||
}
|
||||
this.pageForm.unionId = unionId
|
||||
this.closeUnionPopup()
|
||||
this.doSearch()
|
||||
},
|
||||
loadUnionOptions() {
|
||||
@@ -723,7 +981,6 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
}
|
||||
this.loading = true
|
||||
this.$axios.post("/platform/tour/signup/h5/pageData", this.pageForm).then((res) => {
|
||||
this.loading = false
|
||||
if (res.code !== 0) {
|
||||
vant.Toast(res.msg || "线路加载失败")
|
||||
this.finished = true
|
||||
@@ -739,10 +996,27 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
this.pageForm.pageNumber += 1
|
||||
}
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.finished = true
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
this.$set(this, "refreshing", false)
|
||||
this.$set(this, "initialLoading", false)
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 下拉刷新当前筛选结果:保留线路名称、线路类型和分工会条件,只重置分页数据。
|
||||
*/
|
||||
onRefresh() {
|
||||
if (this.loading) {
|
||||
this.$set(this, "refreshing", false)
|
||||
return
|
||||
}
|
||||
this.$set(this.pageForm, "pageNumber", 1)
|
||||
this.$set(this.pageForm, "totalCount", 0)
|
||||
this.$set(this, "list", [])
|
||||
this.$set(this, "finished", false)
|
||||
this.loadData()
|
||||
},
|
||||
onLine(row) {
|
||||
if (!row || !row.lineId || !row.matterId) {
|
||||
vant.Toast("线路信息不完整")
|
||||
@@ -758,7 +1032,6 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
"x-requested-with": "XMLHttpRequest"
|
||||
}
|
||||
}).then((resp) => {
|
||||
this.lineChecking = false
|
||||
const res = resp.data || {}
|
||||
if (res.code !== 0) {
|
||||
vant.Dialog.alert({
|
||||
@@ -768,23 +1041,32 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
})
|
||||
return
|
||||
}
|
||||
window.location.href = "/platform/tour/signup/h5/lineInfo?matterId="
|
||||
this.$pjaxReplace("/platform/tour/signup/h5/lineInfo?matterId="
|
||||
+ encodeURIComponent(row.matterId)
|
||||
+ "&lineId="
|
||||
+ encodeURIComponent(row.lineId)
|
||||
+ encodeURIComponent(row.lineId))
|
||||
}).catch((err) => {
|
||||
this.lineChecking = false
|
||||
vant.Dialog.alert({
|
||||
title: "温馨提醒",
|
||||
message: err && err.msg ? err.msg : "当前线路暂不能报名",
|
||||
confirmButtonColor: "#1867b0"
|
||||
})
|
||||
}).finally(() => {
|
||||
this.lineChecking = false
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.popupHistoryToken = window.h5PopupHistory.register((popupKey) => {
|
||||
if (popupKey === "union-picker") {
|
||||
this.showUnionPopup = false
|
||||
}
|
||||
})
|
||||
this.loadUnionOptions()
|
||||
this.loadData()
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.h5PopupHistory.unregister(this.popupHistoryToken)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
+411
-44
@@ -2,34 +2,36 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
<style>
|
||||
.tour-approval-page {
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #f4f6f8;
|
||||
background: #f4f8ff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-approval-sticky {
|
||||
flex-shrink: 0;
|
||||
background: #f4f6f8;
|
||||
padding: 8px 12px 10px;
|
||||
background: #f4f8ff;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll {
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding-bottom: 18px;
|
||||
padding: 2px 12px 18px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-approval-search /deep/ .van-search__content,
|
||||
.tour-approval-search .van-search__content {
|
||||
border-radius: 8px;
|
||||
border-radius: 18px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 4px 16px rgba(34, 94, 170, 0.06);
|
||||
}
|
||||
|
||||
.tour-card-tags {
|
||||
@@ -39,12 +41,36 @@ layout("/layouts/platform_h5.html"){
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.tour-card-heading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.tour-card-person {
|
||||
overflow: hidden;
|
||||
color: #17233d;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tour-card-job-no {
|
||||
margin-left: 7px;
|
||||
color: #64748b;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.tour-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 22px;
|
||||
padding: 0 8px;
|
||||
border-radius: 4px;
|
||||
border-radius: 999px;
|
||||
background: #eef6ff;
|
||||
color: #0b75bd;
|
||||
font-size: 12px;
|
||||
@@ -60,17 +86,24 @@ layout("/layouts/platform_h5.html"){
|
||||
color: #d97706;
|
||||
}
|
||||
|
||||
.tour-approval-detail {
|
||||
height: 100%;
|
||||
background: #f4f8ff;
|
||||
}
|
||||
|
||||
.tour-approval-sheet {
|
||||
max-height: 86vh;
|
||||
height: calc(100% - 46px);
|
||||
overflow-y: auto;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
background: #f4f6f8;
|
||||
padding: 2px 0 calc(86px + env(safe-area-inset-bottom));
|
||||
background: #f4f8ff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-section {
|
||||
margin: 10px 12px;
|
||||
overflow: hidden;
|
||||
border-radius: 8px;
|
||||
border-radius: 14px;
|
||||
box-shadow: 0 4px 16px rgba(34, 94, 170, 0.06);
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
@@ -78,7 +111,7 @@ layout("/layouts/platform_h5.html"){
|
||||
position: relative;
|
||||
padding: 14px 16px;
|
||||
border-bottom: 1px solid #edf0f4;
|
||||
color: #0b75bd;
|
||||
color: #17233d;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
@@ -92,7 +125,7 @@ layout("/layouts/platform_h5.html"){
|
||||
width: 30px;
|
||||
height: 4px;
|
||||
border-radius: 0 0 3px 3px;
|
||||
background: #0b75bd;
|
||||
background: #1677ff;
|
||||
}
|
||||
|
||||
.tour-approval-actions {
|
||||
@@ -106,9 +139,303 @@ layout("/layouts/platform_h5.html"){
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.tour-approval-sticky /deep/ .van-dropdown-menu__bar,
|
||||
.tour-approval-sticky .van-dropdown-menu__bar {
|
||||
height: 44px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 16px rgba(34, 94, 170, 0.06);
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll /deep/ .table-list-card,
|
||||
.tour-approval-list-scroll /deep/ .list-card {
|
||||
border-radius: 14px;
|
||||
box-shadow: 0 4px 16px rgba(34, 94, 170, 0.06);
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll /deep/ .action-btn {
|
||||
color: #1677ff;
|
||||
}
|
||||
|
||||
<!--#include("../common/theme.css"){}#-->
|
||||
|
||||
/* 审核列表与提案校工会预审核采用同一信息层级和卡片规范。 */
|
||||
body {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-approval-page {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-approval-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.tour-approval-page .van-nav-bar__title {
|
||||
color: #172033;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-approval-sticky {
|
||||
padding: 22px 12px 1px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-approval-search {
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.tour-approval-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.tour-approval-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tour-approval-filter {
|
||||
margin-bottom: 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
transition: border-radius .18s ease;
|
||||
}
|
||||
|
||||
.tour-approval-filter.is-open {
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-menu__bar,
|
||||
.tour-approval-filter .van-dropdown-menu__item,
|
||||
.tour-approval-filter .van-dropdown-menu__title {
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-menu__bar {
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-menu__title {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: #66758a;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-menu__title--active,
|
||||
.tour-approval-filter .van-dropdown-item__option--active,
|
||||
.tour-approval-filter .van-dropdown-item__option--active .van-dropdown-item__icon {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
margin: 0 12px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0 0 12px 12px;
|
||||
box-shadow: 0 10px 24px rgba(31, 65, 108, .14);
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-item__option {
|
||||
display: flex;
|
||||
min-height: 48px;
|
||||
padding: 0 16px;
|
||||
align-items: center;
|
||||
color: #46566c;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll {
|
||||
padding: 2px 12px 24px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll .empty-state {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tour-approval-empty {
|
||||
display: flex;
|
||||
min-height: 280px;
|
||||
padding: 46px 18px 36px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tour-approval-empty img {
|
||||
display: block;
|
||||
width: 60%;
|
||||
max-width: 190px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.tour-approval-empty__title {
|
||||
margin-top: 10px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-approval-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.tour-card-heading {
|
||||
margin: 0 0 7px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.tour-card-heading-main {
|
||||
min-width: 0;
|
||||
padding-right: 10px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.tour-card-person {
|
||||
color: #253247;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-card-job-no {
|
||||
display: block;
|
||||
margin: 1px 0 0;
|
||||
color: #9ba6b6;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.tour-card-status {
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.tour-card-tags {
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll .action-btn {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll .action-btn .van-icon {
|
||||
margin-right: 6px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.tour-approval-detail,
|
||||
.tour-approval-sheet {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-approval-sheet {
|
||||
padding: 18px 12px calc(92px + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.tour-section {
|
||||
margin: 0 0 11px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #e9eff7;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 3px 11px rgba(51, 87, 126, .08);
|
||||
}
|
||||
|
||||
.tour-section-title {
|
||||
position: relative;
|
||||
padding: 12px 14px 8px 21px;
|
||||
border-bottom: 0;
|
||||
color: #354255;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-section-title::before {
|
||||
top: 15px;
|
||||
bottom: 11px;
|
||||
left: 12px;
|
||||
width: 2px;
|
||||
height: auto;
|
||||
border-radius: 2px;
|
||||
background-color: #1989fa;
|
||||
}
|
||||
|
||||
.tour-section .van-cell {
|
||||
min-height: 44px;
|
||||
padding: 10px 14px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.tour-section .van-cell__title {
|
||||
flex: 0 0 92px;
|
||||
width: 92px;
|
||||
color: #596779;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tour-section .van-cell__value {
|
||||
color: #4f5d70;
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.tour-section .tour-approval-opinion {
|
||||
width: calc(100% - 28px);
|
||||
margin: 0 14px 14px;
|
||||
padding: 12px;
|
||||
border: 1px solid #c9d5e5;
|
||||
border-radius: 10px;
|
||||
background-color: #f7f9fd;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-approval-actions {
|
||||
gap: 10px;
|
||||
padding: 0 14px 14px;
|
||||
}
|
||||
|
||||
.tour-approval-actions .van-button {
|
||||
height: 40px;
|
||||
border-radius: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@media (max-width: 350px) {
|
||||
.tour-approval-sticky,
|
||||
.tour-approval-list-scroll {
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" class="tour-approval-page" v-cloak>
|
||||
<div id="app" class="tour-approval-page tour-h5-theme" v-cloak>
|
||||
<van-nav-bar title="分工会审核" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
|
||||
<van-sticky offset-top="46px" class="tour-approval-sticky">
|
||||
@@ -116,26 +443,38 @@ layout("/layouts/platform_h5.html"){
|
||||
class="tour-approval-search"
|
||||
v-model="pageForm.keyword"
|
||||
placeholder="请输入工号/姓名/线路搜索"
|
||||
show-action
|
||||
clearable
|
||||
input-align="left"
|
||||
@search="doSearch"
|
||||
@clear="doSearch">
|
||||
<template #action>
|
||||
<div @click="doSearch">搜索</div>
|
||||
</template>
|
||||
</van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item :options="auditOptions" @change="doSearch" v-model="pageForm.audit"></van-dropdown-item>
|
||||
<van-dropdown-item :options="lineTypeOptions" @change="doSearch" v-model="pageForm.lineType"></van-dropdown-item>
|
||||
<van-dropdown-menu class="tour-approval-filter" :class="{'is-open': filterOpened}" active-color="#1989fa" :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item :options="auditOptions" @change="doSearch" @open="onFilterOpen" @close="onFilterClose" v-model="pageForm.audit"></van-dropdown-item>
|
||||
<van-dropdown-item :options="lineTypeOptions" @change="doSearch" @open="onFilterOpen" @close="onFilterClose" v-model="pageForm.lineType"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</van-sticky>
|
||||
|
||||
<div class="tour-approval-list-scroll">
|
||||
<table-list api="/platform/tour/unionApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" title="userName" @ready="onReady">
|
||||
<div v-if="pageSkeletonLoading" class="tour-content-skeleton">
|
||||
<div class="tour-content-skeleton__card" v-for="index in 3" :key="'union-approval-skeleton-' + index"></div>
|
||||
</div>
|
||||
<div v-if="!pageSkeletonLoading && pageForm.totalCount === 0" class="tour-approval-empty">
|
||||
<img src="/assets/platform/images/tour/tour-h5-empty-v3.png?v=20260831" alt="暂无审核记录插画">
|
||||
<div class="tour-approval-empty__title">暂无审核记录</div>
|
||||
<div class="tour-approval-empty__hint">当前筛选条件下暂时没有疗休养报名</div>
|
||||
</div>
|
||||
<table-list v-show="!pageSkeletonLoading" api="/platform/tour/unionApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" title="userName" :show_loading_overlay="false" @ready="onReady" @loading-change="onTableLoading">
|
||||
<template #header="{index,row}">
|
||||
<div class="tour-card-heading">
|
||||
<div class="tour-card-heading-main">
|
||||
<div class="tour-card-person">{{ row.userName || '--' }}</div>
|
||||
<div class="tour-card-job-no">工号:{{ row.jobNo || '--' }}</div>
|
||||
</div>
|
||||
<span class="tour-h5-tag tour-card-status" :class="row.taskState === 10 ? 'is-warning' : 'is-success'">{{ row.curTaskName || (row.taskState === 10 ? '待审核' : '已处理') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot="{index,row}">
|
||||
<div class="tour-card-tags">
|
||||
<span v-if="row.jobNo" class="tour-tag">{{ row.jobNo }}</span>
|
||||
<span v-if="row.lineType" class="tour-tag gray">{{ row.lineType }}</span>
|
||||
<span v-if="row.overCostReimbursed" class="tour-tag warn">报销超出费用</span>
|
||||
</div>
|
||||
@@ -155,11 +494,11 @@ layout("/layouts/platform_h5.html"){
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<van-icon name="eye-o"></van-icon>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
|
||||
<i class="fa fa-check"></i>
|
||||
<van-icon name="edit"></van-icon>
|
||||
<span>审核</span>
|
||||
</div>
|
||||
</template>
|
||||
@@ -171,6 +510,7 @@ layout("/layouts/platform_h5.html"){
|
||||
<div class="tour-section-title">{{ formData.taskName || '审核' }}</div>
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
class="tour-approval-opinion"
|
||||
v-model="formData.tf_opinion"
|
||||
name="tf_opinion"
|
||||
label="审批意见"
|
||||
@@ -184,9 +524,9 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-field>
|
||||
</van-form>
|
||||
<div class="tour-approval-actions">
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(2)">拒绝</van-button>
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">同意</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(2)">拒绝</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</tour-info>
|
||||
@@ -195,8 +535,10 @@ layout("/layouts/platform_h5.html"){
|
||||
<script nonce="${cspNonce!}">
|
||||
const TOUR_INFO = {
|
||||
template: /*language=HTML*/ `
|
||||
<van-action-sheet v-model="visible" title="报名详情">
|
||||
<div class="tour-approval-sheet">
|
||||
<van-popup v-model="visible" position="right" :style="{ width: '100%', height: '100%' }" :close-on-click-overlay="false">
|
||||
<div class="tour-approval-detail">
|
||||
<van-nav-bar title="报名详情" left-text="返回" left-arrow @click-left="onClose"></van-nav-bar>
|
||||
<div class="tour-approval-sheet">
|
||||
<div class="tour-section">
|
||||
<div class="tour-section-title">教职工信息</div>
|
||||
<van-cell title="工号" :value="detail.jobNo || ''"></van-cell>
|
||||
@@ -259,9 +601,10 @@ layout("/layouts/platform_h5.html"){
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<slot></slot>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</van-action-sheet>
|
||||
</van-popup>
|
||||
`,
|
||||
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
|
||||
data() {
|
||||
@@ -274,13 +617,15 @@ layout("/layouts/platform_h5.html"){
|
||||
allowFamily: false,
|
||||
fillBedInfo: true,
|
||||
directFamilyUnitLine: false,
|
||||
doneTasks: []
|
||||
doneTasks: [],
|
||||
popupHistoryToken: ""
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onOpen(row) {
|
||||
this.row = row || {}
|
||||
this.visible = true
|
||||
this.$set(this, "visible", true)
|
||||
window.h5PopupHistory.open(this.popupHistoryToken, "detail")
|
||||
this.detail = {}
|
||||
this.familyData = []
|
||||
this.directRelative = {}
|
||||
@@ -292,7 +637,9 @@ layout("/layouts/platform_h5.html"){
|
||||
this.getDoneTasks()
|
||||
},
|
||||
onClose() {
|
||||
this.visible = false
|
||||
if (!window.h5PopupHistory.close(this.popupHistoryToken, "detail")) {
|
||||
this.$set(this, "visible", false)
|
||||
}
|
||||
},
|
||||
info() {
|
||||
this.$axios.post("/platform/tour/unionApproval/detail", { id: this.row.id }).then((res) => {
|
||||
@@ -335,6 +682,15 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
return this.hasFamily() ? "是" : "否"
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$set(this, "popupHistoryToken", window.h5PopupHistory.register(() => {
|
||||
this.$set(this, "visible", false)
|
||||
this.$emit("closed")
|
||||
}))
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.h5PopupHistory.unregister(this.popupHistoryToken)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -364,7 +720,9 @@ layout("/layouts/platform_h5.html"){
|
||||
{ text: "全部线路类型", value: "" }
|
||||
],
|
||||
formData: {},
|
||||
showApprovalForm: false
|
||||
showApprovalForm: false,
|
||||
pageSkeletonLoading: true,
|
||||
filterOpened: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -372,12 +730,24 @@ layout("/layouts/platform_h5.html"){
|
||||
onReady() {
|
||||
this.doSearch()
|
||||
},
|
||||
onTableLoading(state) {
|
||||
if (state && state.initial) {
|
||||
this.$set(this, "pageSkeletonLoading", !!state.loading)
|
||||
}
|
||||
},
|
||||
onFilterOpen() {
|
||||
this.$set(this, "filterOpened", true)
|
||||
},
|
||||
onFilterClose() {
|
||||
this.$set(this, "filterOpened", false)
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(async () => {
|
||||
await this.loadLineTypeOptions()
|
||||
this.$nextTick(() => {
|
||||
this.loadLineTypeOptions().then(() => {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
})
|
||||
},
|
||||
loadLineTypeOptions() {
|
||||
@@ -410,16 +780,12 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
},
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate()
|
||||
} catch (e) {
|
||||
return
|
||||
}
|
||||
this.$dialog.confirm({
|
||||
handleTaskAction(val) {
|
||||
this.$refs.formRef.validate().then(() => {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
}).then(() => {
|
||||
const loading = this.$toast.loading({
|
||||
message: "加载中...",
|
||||
forbidClick: true,
|
||||
@@ -442,6 +808,7 @@ layout("/layouts/platform_h5.html"){
|
||||
}).finally(() => {
|
||||
loading.close()
|
||||
})
|
||||
}).catch(() => {})
|
||||
}).catch(() => {})
|
||||
}
|
||||
}
|
||||
|
||||
+244
-336
@@ -2,14 +2,15 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
|
||||
<style>
|
||||
body {
|
||||
background: #f5f6fa;
|
||||
background: #f3f7fd;
|
||||
}
|
||||
|
||||
#app {
|
||||
min-height: 100vh;
|
||||
background: #f5f6fa;
|
||||
background: #f3f7fd;
|
||||
}
|
||||
|
||||
.custom-nav {
|
||||
@@ -186,14 +187,46 @@ layout("/layouts/platform_h5.html"){
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
/* 仅本页底部弹层固定半屏;选择内容在弹层内部滚动。 */
|
||||
.union-half-popup.van-popup--bottom,
|
||||
.union-half-popup.van-action-sheet {
|
||||
height: 50vh;
|
||||
max-height: 50vh;
|
||||
}
|
||||
|
||||
.union-half-popup.van-popup--bottom:not(.invoice-popup):not(.bank-account-popup):not(.van-action-sheet) {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.invoice-popup {
|
||||
height: 86vh;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
max-height: 100vh;
|
||||
padding-top: env(safe-area-inset-top);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.invoice-popup,
|
||||
.bank-account-popup {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.invoice-popup .van-nav-bar,
|
||||
.invoice-popup-actions,
|
||||
.bank-account-popup .van-nav-bar {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.bank-account-popup-body {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.invoice-popup-body {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
background: #f7f8fa;
|
||||
position: relative;
|
||||
@@ -215,7 +248,7 @@ layout("/layouts/platform_h5.html"){
|
||||
.invoice-popup-actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
padding: 10px 16px;
|
||||
padding: 10px 16px calc(10px + env(safe-area-inset-bottom));
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
@@ -234,151 +267,6 @@ layout("/layouts/platform_h5.html"){
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.payment-detail-item {
|
||||
margin-top: 7px;
|
||||
border: 1px solid #e8ebf0;
|
||||
border-radius: 9px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
box-shadow: 0 1px 4px rgba(31, 35, 41, 0.07);
|
||||
}
|
||||
|
||||
.payment-detail-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
min-height: 34px;
|
||||
padding: 0 12px;
|
||||
color: #323233;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
background: #f8f9fc;
|
||||
border-bottom: 1px solid #eef0f4;
|
||||
}
|
||||
|
||||
.payment-title-left {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 5px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.payment-index-text {
|
||||
color: #9aa3af;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.payment-detail-title .van-tag {
|
||||
min-width: 50px;
|
||||
height: 22px;
|
||||
padding: 0 8px;
|
||||
border-radius: 4px;
|
||||
color: #1677ff;
|
||||
background: #eaf3ff;
|
||||
font-size: 12px;
|
||||
line-height: 22px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.payment-detail-item .van-cell {
|
||||
padding: 11px 12px;
|
||||
}
|
||||
|
||||
.payment-detail-item .van-cell::after {
|
||||
left: 12px;
|
||||
right: 0;
|
||||
border-color: #edf0f4;
|
||||
}
|
||||
|
||||
.payment-detail-item .van-field__label {
|
||||
width: 70px;
|
||||
color: #1f2329;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.payment-detail-item .van-field__control {
|
||||
color: #1f2329;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.payment-detail-item .van-field__control::placeholder {
|
||||
color: #b8bec8;
|
||||
}
|
||||
|
||||
.payment-detail-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 9px 12px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.payment-detail-actions .van-button {
|
||||
height: 28px;
|
||||
padding: 0 13px;
|
||||
border-radius: 14px;
|
||||
}
|
||||
|
||||
.payment-swipe {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.payment-swipe .van-swipe__track {
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.payment-swipe .van-swipe-item {
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.payment-nav-buttons {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.payment-nav-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border: 1px solid #edf0f4;
|
||||
border-radius: 50%;
|
||||
color: #c0c6d0;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.payment-nav-btn.active {
|
||||
color: #8b95a3;
|
||||
border-color: #e1e5eb;
|
||||
}
|
||||
|
||||
.payment-delete-btn {
|
||||
color: #ff4d4f;
|
||||
border-color: #ff9a9c;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.payment-dots {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 5px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.payment-dot {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
border-radius: 999px;
|
||||
background: #d6dbe3;
|
||||
}
|
||||
|
||||
.payment-dot.active {
|
||||
width: 14px;
|
||||
background: #1677ff;
|
||||
}
|
||||
|
||||
.van-empty {
|
||||
padding: 26px 0;
|
||||
}
|
||||
@@ -394,7 +282,11 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
|
||||
</style>
|
||||
<div id="app" v-cloak>
|
||||
<style id="style-union-reimburse-h5">
|
||||
<!--#include('../common/unionReimburse.css'){}#-->
|
||||
</style>
|
||||
|
||||
<div id="app" v-cloak class="union-reimburse-page union-reimburse-form">
|
||||
<van-nav-bar title="报销申请" left-text="返回" left-arrow @click-left="historyBack" placeholder fixed z-index="999"
|
||||
class="custom-nav"></van-nav-bar>
|
||||
|
||||
@@ -481,14 +373,14 @@ layout("/layouts/platform_h5.html"){
|
||||
label="报销类别"
|
||||
readonly
|
||||
placeholder="请选择报销类别"
|
||||
@click="showReimburseTypePicker = true"
|
||||
@click="$set(this, 'showReimburseTypePicker', true)"
|
||||
clickable
|
||||
:rules="[{ required: true, message: '请选择报销类别' }]"
|
||||
required
|
||||
is-link
|
||||
></van-field>
|
||||
<van-popup position="bottom" round v-model:show="showReimburseTypePicker">
|
||||
<van-picker :columns="reimburseTypeColumns" @cancel="showReimburseTypePicker = false"
|
||||
<van-picker :columns="reimburseTypeColumns" @cancel="$set(this, 'showReimburseTypePicker', false)"
|
||||
@confirm="onReimburseTypeConfirm" show-toolbar></van-picker>
|
||||
</van-popup>
|
||||
-->
|
||||
@@ -504,7 +396,7 @@ layout("/layouts/platform_h5.html"){
|
||||
readonly
|
||||
:rules="[{ required: true }]"
|
||||
placeholder="请点击选择证明人"
|
||||
@click="certifierUserSelectShow = true"
|
||||
@click="$set(this, 'certifierUserSelectShow', true)"
|
||||
is-link
|
||||
></van-field>
|
||||
<van-action-sheet v-model="certifierUserSelectShow" title="证明人" class="height100">
|
||||
@@ -995,7 +887,7 @@ layout("/layouts/platform_h5.html"){
|
||||
<van-nav-bar :title="invoiceDialogMode === 'edit' ? '编辑发票明细' : '新增发票明细'"
|
||||
left-text="取消"
|
||||
left-arrow
|
||||
@click-left="invoiceDialogVisible = false"></van-nav-bar>
|
||||
@click-left="historyBack"></van-nav-bar>
|
||||
<div class="invoice-popup-body">
|
||||
<div class="invoice-recognizing-mask" v-if="recognizingInvoice">
|
||||
<van-loading type="spinner" color="#1677ff" size="24px">发票识别中...</van-loading>
|
||||
@@ -1043,7 +935,7 @@ layout("/layouts/platform_h5.html"){
|
||||
<div class="invoice-tip" style="padding: 8px 16px;">上传发票文件后会自动识别发票信息;开启自动校验时会同步校验发票是否重复。</div>
|
||||
</div>
|
||||
<div class="invoice-popup-actions">
|
||||
<van-button native-type="button" block plain @click="invoiceDialogVisible = false">取消</van-button>
|
||||
<van-button native-type="button" block plain @click="$set($data, 'invoiceDialogVisible', false)">取消</van-button>
|
||||
<van-button native-type="button" block type="primary" @click="saveInvoiceDetail">保存</van-button>
|
||||
</div>
|
||||
</van-popup>
|
||||
@@ -1815,12 +1707,13 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$set(this, "searchKeyword", "")
|
||||
this.$set(this, "userOptions", [])
|
||||
},
|
||||
async userRemoteMethod(event) {
|
||||
if (event) {
|
||||
const userOptions = await this.selectQueryUser(event)
|
||||
this.$set(this, "userOptions", userOptions)
|
||||
this.$set(this, "certifierUserSelectShow", true)
|
||||
}
|
||||
userRemoteMethod(event) {
|
||||
if (event) {
|
||||
return this.selectQueryUser(event).then(userOptions => {
|
||||
this.$set(this, "userOptions", userOptions);
|
||||
this.$set(this, "certifierUserSelectShow", true);
|
||||
});
|
||||
} else {}
|
||||
},
|
||||
selectQueryUser(keyword) {
|
||||
return this.$axios.post("/platform/UnionReimburse/apply/listUser", { keyword: keyword }).then((res) => {
|
||||
@@ -1991,106 +1884,104 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
})
|
||||
},
|
||||
async onSave() {
|
||||
this.normalizeContactFields()
|
||||
this.normalizeCondolenceDateFields()
|
||||
this.rebuildInvoiceSummary()
|
||||
const paymentDetails = this.preparePaymentDetailsForSubmit()
|
||||
this.$axios.post("/platform/unionReimburse/apply/save", { data: JSON.stringify(this.buildSubmitFormData(paymentDetails)) })
|
||||
.then((res) => {
|
||||
this.$toast.clear()
|
||||
if (res.code === 0) {
|
||||
this.$toast.success(res.msg)
|
||||
this.$pjaxReplace("/platform/unionReimburse/mine/h5")
|
||||
} else {
|
||||
this.$toast.fail(res.msg || "保存失败")
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
this.$toast.clear()
|
||||
this.$toast.fail(this.getRequestErrorMessage(err, "保存失败"))
|
||||
})
|
||||
onSave() {
|
||||
this.normalizeContactFields();
|
||||
this.normalizeCondolenceDateFields();
|
||||
this.rebuildInvoiceSummary();
|
||||
const paymentDetails = this.preparePaymentDetailsForSubmit();
|
||||
this.$axios.post("/platform/unionReimburse/apply/save", {
|
||||
data: JSON.stringify(this.buildSubmitFormData(paymentDetails))
|
||||
}).then(res => {
|
||||
this.$toast.clear();
|
||||
if (res.code === 0) {
|
||||
this.$toast.success(res.msg);
|
||||
this.$pjaxReplace("/platform/unionReimburse/mine/h5");
|
||||
} else {
|
||||
this.$toast.fail(res.msg || "保存失败");
|
||||
}
|
||||
}).catch(err => {
|
||||
this.$toast.clear();
|
||||
this.$toast.fail(this.getRequestErrorMessage(err, "保存失败"));
|
||||
});
|
||||
},
|
||||
// 提交
|
||||
async onSubmit() {
|
||||
|
||||
this.normalizeContactFields()
|
||||
this.normalizeCondolenceDateFields()
|
||||
this.rebuildInvoiceSummary()
|
||||
const paymentDetails = this.preparePaymentDetailsForSubmit()
|
||||
this.$refs.formRef.validate().then(() => {
|
||||
// if (!this.formData.userSign) {
|
||||
// this.$toast.fail("请签名")
|
||||
// return
|
||||
// }
|
||||
if (!this.validatePaymentDetailsBeforeSubmit(paymentDetails)) {
|
||||
return
|
||||
onSubmit() {
|
||||
this.normalizeContactFields();
|
||||
this.normalizeCondolenceDateFields();
|
||||
this.rebuildInvoiceSummary();
|
||||
const paymentDetails = this.preparePaymentDetailsForSubmit();
|
||||
this.$refs.formRef.validate().then(() => {
|
||||
// if (!this.formData.userSign) {
|
||||
// this.$toast.fail("请签名")
|
||||
// return
|
||||
// }
|
||||
if (!this.validatePaymentDetailsBeforeSubmit(paymentDetails)) {
|
||||
return;
|
||||
}
|
||||
if (!this.validateInvoiceDetailsBeforeSubmit()) {
|
||||
return;
|
||||
}
|
||||
this.$dialog.confirm({
|
||||
title: "温馨提示",
|
||||
message: "您确定要提交吗?审核通过后可前往pc端我的报销打印!"
|
||||
}).then(() => {
|
||||
this.$axios.post("/platform/unionReimburse/apply/submit", {
|
||||
data: JSON.stringify(this.buildSubmitFormData(paymentDetails))
|
||||
}).then(res => {
|
||||
this.$toast.clear();
|
||||
if (res.code === 0) {
|
||||
this.$toast.success("提交成功");
|
||||
this.$pjaxReplace("/platform/unionReimburse/mine/h5");
|
||||
} else {
|
||||
this.$toast.fail(res.msg || "提交失败");
|
||||
}
|
||||
if (!this.validateInvoiceDetailsBeforeSubmit()) {
|
||||
return
|
||||
}
|
||||
this.$dialog.confirm({
|
||||
title: "温馨提示",
|
||||
message: "您确定要提交吗?审核通过后可前往pc端我的报销打印!"
|
||||
}).then(() => {
|
||||
this.$axios.post("/platform/unionReimburse/apply/submit", { data: JSON.stringify(this.buildSubmitFormData(paymentDetails)) })
|
||||
.then(res => {
|
||||
this.$toast.clear()
|
||||
if (res.code === 0) {
|
||||
this.$toast.success("提交成功")
|
||||
this.$pjaxReplace("/platform/unionReimburse/mine/h5")
|
||||
} else {
|
||||
this.$toast.fail(res.msg || "提交失败")
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
this.$toast.clear()
|
||||
this.$toast.fail(this.getRequestErrorMessage(err, "提交失败"))
|
||||
})
|
||||
})
|
||||
})
|
||||
}).catch(err => {
|
||||
this.$toast.clear();
|
||||
this.$toast.fail(this.getRequestErrorMessage(err, "提交失败"));
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
// 再次提交
|
||||
async onSubmitAgain() {
|
||||
|
||||
this.normalizeContactFields()
|
||||
this.normalizeCondolenceDateFields()
|
||||
this.rebuildInvoiceSummary()
|
||||
const paymentDetails = this.preparePaymentDetailsForSubmit()
|
||||
this.$refs.formRef.validate().then(() => {
|
||||
if (!this.formData.userSign) {
|
||||
this.$toast.fail("请签名")
|
||||
return
|
||||
onSubmitAgain() {
|
||||
this.normalizeContactFields();
|
||||
this.normalizeCondolenceDateFields();
|
||||
this.rebuildInvoiceSummary();
|
||||
const paymentDetails = this.preparePaymentDetailsForSubmit();
|
||||
this.$refs.formRef.validate().then(() => {
|
||||
if (!this.formData.userSign) {
|
||||
this.$toast.fail("请签名");
|
||||
return;
|
||||
}
|
||||
if (!this.validatePaymentDetailsBeforeSubmit(paymentDetails)) {
|
||||
return;
|
||||
}
|
||||
if (!this.validateInvoiceDetailsBeforeSubmit()) {
|
||||
return;
|
||||
}
|
||||
this.$dialog.confirm({
|
||||
title: "温馨提示",
|
||||
message: "您确定要提交吗?审核通过后可前往pc端我的报销打印!"
|
||||
}).then(() => {
|
||||
this.$axios.post("/platform/unionReimburse/apply/submitAgain", {
|
||||
data: JSON.stringify(this.buildSubmitFormData(paymentDetails)),
|
||||
taskId: GetQueryString("taskId")
|
||||
}).then(res => {
|
||||
this.$toast.clear();
|
||||
if (res.code === 0) {
|
||||
this.$toast.success("提交成功");
|
||||
setTimeout(() => {
|
||||
this.$pjaxReplace("/platform/unionReimburse/mine/h5");
|
||||
}, 1500);
|
||||
} else {
|
||||
this.$toast.fail(res.msg || "提交失败");
|
||||
}
|
||||
if (!this.validatePaymentDetailsBeforeSubmit(paymentDetails)) {
|
||||
return
|
||||
}
|
||||
if (!this.validateInvoiceDetailsBeforeSubmit()) {
|
||||
return
|
||||
}
|
||||
this.$dialog.confirm({
|
||||
title: "温馨提示",
|
||||
message: "您确定要提交吗?审核通过后可前往pc端我的报销打印!"
|
||||
}).then(() => {
|
||||
this.$axios.post("/platform/unionReimburse/apply/submitAgain", {
|
||||
data: JSON.stringify(this.buildSubmitFormData(paymentDetails)),
|
||||
taskId: GetQueryString("taskId")
|
||||
}).then(res => {
|
||||
this.$toast.clear()
|
||||
if (res.code === 0) {
|
||||
this.$toast.success("提交成功")
|
||||
setTimeout(() => {
|
||||
this.$pjaxReplace("/platform/unionReimburse/mine/h5")
|
||||
}, 1500)
|
||||
} else {
|
||||
this.$toast.fail(res.msg || "提交失败")
|
||||
}
|
||||
}).catch(err => {
|
||||
this.$toast.clear()
|
||||
this.$toast.fail(this.getRequestErrorMessage(err, "提交失败"))
|
||||
})
|
||||
})
|
||||
})
|
||||
}).catch(err => {
|
||||
this.$toast.clear();
|
||||
this.$toast.fail(this.getRequestErrorMessage(err, "提交失败"));
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
onReimburseTypeConfirm(o) {
|
||||
this.$set(this.formData, "reimburseTypeName", o.text) // 显示名称
|
||||
@@ -2218,33 +2109,48 @@ layout("/layouts/platform_h5.html"){
|
||||
const project = this.descOptions.find(item => item.reimburseProject === projectCode)
|
||||
return project ? project.projectTip : ""
|
||||
},
|
||||
async initDictOptions() {
|
||||
// 报销类别
|
||||
const reimburseTypeData = await this.$businessTool.getDictOptions("UNION_REIMBURSE_TYPE")
|
||||
initDictOptions() {
|
||||
return this.$businessTool.getDictOptions("UNION_REIMBURSE_TYPE").then(reimburseTypeData => {
|
||||
this.reimburseTypeColumns = reimburseTypeData.map(item => {
|
||||
return { value: item.code, text: item.name }
|
||||
})
|
||||
return {
|
||||
value: item.code,
|
||||
text: item.name
|
||||
};
|
||||
});
|
||||
|
||||
// 支付方式
|
||||
const paymentWayData = await this.$businessTool.getDictOptions("UNION_REIMBURSE_PAYMENT_WAY")
|
||||
this.paymentWayColumns = paymentWayData.map(item => {
|
||||
return { value: item.code, text: item.name }
|
||||
})
|
||||
return this.$businessTool.getDictOptions("UNION_REIMBURSE_PAYMENT_WAY").then(paymentWayData => {
|
||||
this.paymentWayColumns = paymentWayData.map(item => {
|
||||
return {
|
||||
value: item.code,
|
||||
text: item.name
|
||||
};
|
||||
});
|
||||
|
||||
// 报销项目
|
||||
const reimburseProjectData = await this.$businessTool.getDictOptions("UNION_REIMBURSE_PROJECT")
|
||||
this.reimburseProjectColumns = reimburseProjectData.map(item => {
|
||||
return { value: item.code, text: item.name }
|
||||
})
|
||||
this.reimburseProjectList = reimburseProjectData // 保存原始数据
|
||||
// 报销项目
|
||||
return this.$businessTool.getDictOptions("UNION_REIMBURSE_PROJECT").then(reimburseProjectData => {
|
||||
this.reimburseProjectColumns = reimburseProjectData.map(item => {
|
||||
return {
|
||||
value: item.code,
|
||||
text: item.name
|
||||
};
|
||||
});
|
||||
this.reimburseProjectList = reimburseProjectData; // 保存原始数据
|
||||
|
||||
// 报销经费来源
|
||||
const reimburseFundSourceData = await this.$businessTool.getDictOptions("UNION_REIMBURSE_FUND_SOURCE")
|
||||
this.reimburseFundSourceColumns = reimburseFundSourceData.map(item => {
|
||||
return { value: item.code, text: item.name }
|
||||
})
|
||||
// 添加经费来源区分
|
||||
await this.filterReimburseFundSources()
|
||||
// 报销经费来源
|
||||
return this.$businessTool.getDictOptions("UNION_REIMBURSE_FUND_SOURCE").then(reimburseFundSourceData => {
|
||||
this.reimburseFundSourceColumns = reimburseFundSourceData.map(item => {
|
||||
return {
|
||||
value: item.code,
|
||||
text: item.name
|
||||
};
|
||||
});
|
||||
// 添加经费来源区分
|
||||
return this.filterReimburseFundSources().then(() => {});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// 查询慰问对象
|
||||
@@ -2404,62 +2310,60 @@ layout("/layouts/platform_h5.html"){
|
||||
})
|
||||
},
|
||||
// 添加经费来源区分
|
||||
async filterReimburseFundSources() {
|
||||
const filteredSources = []
|
||||
filterReimburseFundSources() {
|
||||
const filteredSources = [];
|
||||
|
||||
// 原角色过滤逻辑保留如下,手机端现统一改为按权限控制,与 PC 端保持一致
|
||||
// if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])) {
|
||||
// return
|
||||
// }
|
||||
// if (this.$auth.hasRoleOr(["SCHOOL_OUTLAY_ADMIN", "SCHOOL_UNION_ADMIN"])) {
|
||||
// this.reimburseFundSourceColumns.map(item => {
|
||||
// if (item.value === "UNION_REIMBURSE_FUND_SOURCE_1") {
|
||||
// filteredSources.push(item)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// if (this.$auth.hasRoleOr(["BRANCH_UNION_CHAIRMAN", "BRANCH_UNION_ADMIN"])) {
|
||||
// this.reimburseFundSourceColumns.map(item => {
|
||||
// if (item.value === "UNION_REIMBURSE_FUND_SOURCE_2") {
|
||||
// filteredSources.push(item)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// if (this.$auth.hasRoleOr(["CLUB_MANAGER", "CLUB_PRESIDENT"])) {
|
||||
// this.reimburseFundSourceColumns.map(item => {
|
||||
// if (item.value === "UNION_REIMBURSE_FUND_SOURCE_3") {
|
||||
// filteredSources.push(item)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// 原角色过滤逻辑保留如下,手机端现统一改为按权限控制,与 PC 端保持一致
|
||||
// if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])) {
|
||||
// return
|
||||
// }
|
||||
// if (this.$auth.hasRoleOr(["SCHOOL_OUTLAY_ADMIN", "SCHOOL_UNION_ADMIN"])) {
|
||||
// this.reimburseFundSourceColumns.map(item => {
|
||||
// if (item.value === "UNION_REIMBURSE_FUND_SOURCE_1") {
|
||||
// filteredSources.push(item)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// if (this.$auth.hasRoleOr(["BRANCH_UNION_CHAIRMAN", "BRANCH_UNION_ADMIN"])) {
|
||||
// this.reimburseFundSourceColumns.map(item => {
|
||||
// if (item.value === "UNION_REIMBURSE_FUND_SOURCE_2") {
|
||||
// filteredSources.push(item)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// if (this.$auth.hasRoleOr(["CLUB_MANAGER", "CLUB_PRESIDENT"])) {
|
||||
// this.reimburseFundSourceColumns.map(item => {
|
||||
// if (item.value === "UNION_REIMBURSE_FUND_SOURCE_3") {
|
||||
// filteredSources.push(item)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
// 经费来源子权限和 PC 端保持一致,避免手机端因 h5 前缀过滤为空。
|
||||
if (this.$auth.hasPermission("unionReimburse.xgh")) {
|
||||
this.reimburseFundSourceColumns.forEach(item => {
|
||||
if (item.value === "UNION_REIMBURSE_FUND_SOURCE_1") {
|
||||
filteredSources.push(item)
|
||||
}
|
||||
})
|
||||
}
|
||||
// 经费来源子权限和 PC 端保持一致,避免手机端因 h5 前缀过滤为空。
|
||||
if (this.$auth.hasPermission("unionReimburse.xgh")) {
|
||||
this.reimburseFundSourceColumns.forEach(item => {
|
||||
if (item.value === "UNION_REIMBURSE_FUND_SOURCE_1") {
|
||||
filteredSources.push(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (this.$auth.hasPermission("unionReimburse.fgh")) {
|
||||
this.reimburseFundSourceColumns.forEach(item => {
|
||||
if (item.value === "UNION_REIMBURSE_FUND_SOURCE_2") {
|
||||
filteredSources.push(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (this.$auth.hasPermission("unionReimburse.club")) {
|
||||
this.reimburseFundSourceColumns.forEach(item => {
|
||||
if (item.value === "UNION_REIMBURSE_FUND_SOURCE_3") {
|
||||
filteredSources.push(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (this.$auth.hasPermission("unionReimburse.fgh")) {
|
||||
this.reimburseFundSourceColumns.forEach(item => {
|
||||
if (item.value === "UNION_REIMBURSE_FUND_SOURCE_2") {
|
||||
filteredSources.push(item)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (this.$auth.hasPermission("unionReimburse.club")) {
|
||||
this.reimburseFundSourceColumns.forEach(item => {
|
||||
if (item.value === "UNION_REIMBURSE_FUND_SOURCE_3") {
|
||||
filteredSources.push(item)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 更新经费来源选项
|
||||
this.reimburseFundSourceColumns = filteredSources
|
||||
// 更新经费来源选项
|
||||
this.reimburseFundSourceColumns = filteredSources;
|
||||
},
|
||||
init() {
|
||||
this.bizId = GetQueryString("bizId")
|
||||
@@ -2579,12 +2483,16 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
},
|
||||
|
||||
async created() {
|
||||
await this.initDictOptions()
|
||||
await this.queryProjectDesc()
|
||||
await this.queryCondolenceType()
|
||||
await this.queryClubs()
|
||||
await this.init()
|
||||
created() {
|
||||
return this.initDictOptions().then(() => {
|
||||
return this.queryProjectDesc().then(() => {
|
||||
return this.queryCondolenceType().then(() => {
|
||||
return this.queryClubs().then(() => {
|
||||
return this.init().then(() => {});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@ layout("/layouts/platform_h5.html"){
|
||||
v-model="pageForm.userName"
|
||||
></van-search>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
@change="(val)=>{$set(this.pageForm, 'approval', val==='1');this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
@@ -83,8 +83,8 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-cell-group>
|
||||
<!-- 按钮区域 -->
|
||||
<div class="form-actions">
|
||||
<van-button type="danger" @click="handleTaskAction(6)">退回到发起人</van-button>
|
||||
<van-button type="primary" @click="handleTaskAction(1)">同意</van-button>
|
||||
<van-button type="danger" @click="handleTaskAction(6)">退回到发起人</van-button>
|
||||
</div>
|
||||
</van-form>
|
||||
</div>
|
||||
|
||||
+69
-86
@@ -2,71 +2,57 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style>
|
||||
.state-primary {
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.state-success {
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.state-danger {
|
||||
color: #f56c6c;
|
||||
}
|
||||
<style id="style-union-reimburse-h5">
|
||||
<!--#include('../common/unionReimburse.css'){}#-->
|
||||
</style>
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="报销统计" placeholder fixed></van-nav-bar>
|
||||
<div id="app" v-cloak class="union-reimburse-page">
|
||||
<van-nav-bar @click-left="onNavBack" left-arrow left-text="返回" title="报销统计" placeholder fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item :options="yearList" @change="doSearch" v-model="pageForm.year"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-search
|
||||
:reverse-color="false"
|
||||
:show-action="false"
|
||||
@search="doSearch"
|
||||
input-align="left"
|
||||
placeholder="请输入经办人搜索"
|
||||
v-model="pageForm.userName"
|
||||
></van-search>
|
||||
<div class="union-reimburse-sticky">
|
||||
<van-search class="union-reimburse-search" :reverse-color="false" :show-action="false" @search="doSearch" @clear="doSearch" input-align="left" placeholder="请输入姓名或工号搜索" v-model="pageForm.searchKeyword"></van-search>
|
||||
<van-dropdown-menu class="union-reimburse-filter" :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item :options="yearList" @change="doSearch" v-model="pageForm.year"></van-dropdown-item>
|
||||
<van-dropdown-item :options="reimburseProjectOptions" @change="doSearch" v-model="pageForm.reimburseProject"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
|
||||
<table-list api="/platform/unionReimburse/collect/pageData" :page_form.sync="pageForm" ref="tableListRef"
|
||||
@ready="doSearch" >
|
||||
<main class="union-reimburse-list-content">
|
||||
<table-list api="/platform/unionReimburse/collect/pageData" :page_form.sync="pageForm" ref="tableListRef" :show_loading_overlay="false"
|
||||
@ready="doSearch" @loading-change="onLoadingChange">
|
||||
<template #header="{row}"><div v-if="row" class="union-reimburse-card-header"><div class="union-reimburse-card-header__heading"><div class="union-reimburse-card-header__title">{{row.userName || '--'}}</div><div class="union-reimburse-card-header__sub">工号:{{row.loginName || '--'}}</div></div><van-tag :class="['union-reimburse-card-header__status', getStatusClass(row.stateId)]">{{getStateName(row.stateId)}}</van-tag></div></template>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="经办人工号">{{row.loginName}}</table-column>
|
||||
<table-column label="姓名">{{row.userName}}</table-column>
|
||||
<table-column label="所属工会">{{row.unionName}}</table-column>
|
||||
<table-column label="所属单位">{{row.unitName}}</table-column>
|
||||
<table-column label="申请时间">{{formatCreateTime(row.createTime)}}</table-column>
|
||||
<table-column label="报销项目">{{getReimburseProjectName(row.reimburseProject)}}</table-column>
|
||||
<table-column label="备注">{{getRemarkText(row)}}</table-column>
|
||||
<table-column label="申请状态">
|
||||
<span :class="getStateClass(row.stateId)">{{getStateName(row.stateId)}}</span>
|
||||
</table-column>
|
||||
<table-column label="报销项目">{{getReimburseProjectName(row.reimburseProject) || '--'}}</table-column>
|
||||
<table-column label="" label_suffix="">{{getRemarkText(row) || '--'}}</table-column>
|
||||
<table-column label="所属工会">{{row.unionName || '--'}}</table-column>
|
||||
<table-column label="所属单位">{{row.unitName || '--'}}</table-column>
|
||||
<table-column label="申请时间">{{formatCreateTime(row.createTime) || '--'}}</table-column>
|
||||
<table-column label="申请金额">{{formatMoney(row.money)}}</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<van-icon name="eye-o"></van-icon>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<!-- <div class="action-btn" @click="onEdit(row)" v-if="row.taskKey === 'startTask' || !row.instanceId">-->
|
||||
<!-- <i class="fa fa-edit"></i>-->
|
||||
<!-- <span>编辑</span>-->
|
||||
<!-- </div>-->
|
||||
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(item)">
|
||||
<i class="fa fa-undo"></i>
|
||||
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">
|
||||
<van-icon name="revoke"></van-icon>
|
||||
<span>撤回</span>
|
||||
</div>
|
||||
<div class="action-btn delete" @click="onDelete(row)" v-if="row.taskKey === 'startTask' || !row.instanceId">
|
||||
<i class="fa fa-trash"></i>
|
||||
<van-icon name="delete-o"></van-icon>
|
||||
<span>删除</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #empty><div v-if="listLoading" class="union-reimburse-list-skeleton"><div v-for="item in 2" :key="item" class="union-reimburse-skeleton-card"><div class="union-reimburse-skeleton-line union-reimburse-skeleton-line--title"></div><div class="union-reimburse-skeleton-line"></div><div class="union-reimburse-skeleton-line union-reimburse-skeleton-line--short"></div></div></div><div v-else class="union-reimburse-empty"><img src="/assets/mobile/img/unionReimburse/union-reimburse-empty.png" alt="暂无报销统计记录插画"><div class="union-reimburse-empty__title">暂无报销统计记录</div><div class="union-reimburse-empty__hint">当前筛选条件下暂时没有报销记录</div></div></template>
|
||||
</table-list>
|
||||
</main>
|
||||
|
||||
<union-reimburse-info ref="unionReimburseInfoRef"></union-reimburse-info>
|
||||
<union-reimburse-info ref="unionReimburseInfoRef" history-layer-name="union-reimburse-collect-info"></union-reimburse-info>
|
||||
<van-dialog :value="confirmVisible" title="提示" :message="confirmMessage" show-cancel-button :confirm-button-loading="formLoading" @confirm="confirmPendingAction" @cancel="closeConfirm"></van-dialog>
|
||||
|
||||
</div>
|
||||
<script nonce="${cspNonce!}">
|
||||
@@ -80,18 +66,32 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
viewShow: false,
|
||||
listLoading: true,
|
||||
formLoading: false,
|
||||
confirmVisible: false,
|
||||
pendingAction: "",
|
||||
pendingRow: null,
|
||||
historyLayerUnsubscribe: null,
|
||||
yearList: [],
|
||||
reimburseProjectOptions: [
|
||||
{text: "全部项目", value: ""},
|
||||
{text: "慰问", value: "UNION_REIMBURSE_PROJECT_1"},
|
||||
{text: "文体活动", value: "UNION_REIMBURSE_PROJECT_2"},
|
||||
{text: "日常活动", value: "UNION_REIMBURSE_PROJECT_3"},
|
||||
{text: "专项活动", value: "UNION_REIMBURSE_PROJECT_4"}
|
||||
],
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
searchKeyword: "",
|
||||
year: "",
|
||||
reimburseProject: ""
|
||||
},
|
||||
infoShow: false
|
||||
}
|
||||
},
|
||||
computed: { confirmMessage() { return this.pendingAction === "revoke" ? "您确定要撤回申请吗?" : "您确定要删除吗?" } },
|
||||
methods: {
|
||||
// 手机端统计列表字段展示与我的报销列表保持一致。
|
||||
getReimburseProjectName(reimburseProject) {
|
||||
@@ -133,58 +133,35 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
return stateId || ""
|
||||
},
|
||||
getStateClass(stateId) {
|
||||
if (stateId == 3) {
|
||||
return "state-success"
|
||||
}
|
||||
if (stateId == 4) {
|
||||
return "state-danger"
|
||||
}
|
||||
return "state-primary"
|
||||
},
|
||||
getStatusClass(stateId) { if (stateId == 3) return "union-reimburse-card-header__status--success"; if (stateId == 4 || stateId == 5) return "union-reimburse-card-header__status--danger"; return "union-reimburse-card-header__status--pending" },
|
||||
formatCreateTime(value) {
|
||||
return value && this.$moment(value).isValid() ? this.$moment(value).format("YYYY-MM-DD HH:mm:ss") : ""
|
||||
},
|
||||
formatMoney(value) {
|
||||
if (value === null || value === undefined || value === "") return "--"
|
||||
const amount = Number(value)
|
||||
return isNaN(amount) ? value : amount.toFixed(2) + "元"
|
||||
},
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
this.$refs.unionReimburseInfoRef.onOpen(row)
|
||||
this.$refs.unionReimburseInfoRef.onOpen(row, "报销详情")
|
||||
},
|
||||
onEdit(row) {
|
||||
this.$pjaxReplace("/platform/unionReimburse/apply/h5?bizId=" + row.id + "&taskId=" + row.startTaskId)
|
||||
},
|
||||
|
||||
onRevoke(row){
|
||||
this.$dialog
|
||||
.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要撤销申请吗?"
|
||||
})
|
||||
.then(() => {
|
||||
this.$axios.post("/flow/common/revokeTask", {taskId: row.startTaskId}).then((resp) => {
|
||||
this.$toast.success(resp.msg)
|
||||
this.doSearch()
|
||||
})
|
||||
})
|
||||
},
|
||||
onDelete(row) {
|
||||
this.$dialog
|
||||
.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要删除吗?"
|
||||
})
|
||||
.then(() => {
|
||||
this.$axios.post("/platform/unionReimburse/mine/delete", {id: row.id}).then((resp) => {
|
||||
if (resp.code === 0) {
|
||||
this.$toast.success(resp.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
onLoadingChange(state) { this.$set(this, "listLoading", state.loading) },
|
||||
onNavBack() { const manager = window.h5HistoryLayerManager; if (manager && manager.stack.length) { manager.close(); return } historyBack() },
|
||||
openConfirm(action, row) { this.$set(this, "pendingAction", action); this.$set(this, "pendingRow", row); const manager = window.h5HistoryLayerManager; if (manager) { manager.open("union-reimburse-collect-confirm"); return } this.$set(this, "confirmVisible", true) },
|
||||
closeConfirm(afterClose) { const manager = window.h5HistoryLayerManager; if (manager) { manager.close("union-reimburse-collect-confirm", afterClose); return } this.$set(this, "confirmVisible", false); if (afterClose) afterClose() },
|
||||
confirmPendingAction() { const action = this.pendingAction; const row = this.pendingRow; this.closeConfirm(() => { if (action === "revoke") { this.revoke(row) } else { this.deleteApplication(row) } }) },
|
||||
onRevoke(row) { this.openConfirm("revoke", row) },
|
||||
revoke(row) { this.$set(this, "formLoading", true); this.$axios.post("/flow/common/revokeTask", {taskId: row.startTaskId}).then((resp) => { if (resp.code === 0) { this.$toast.success(resp.msg); this.doSearch() } else { this.$toast.fail(resp.msg) } }).finally(() => { this.$set(this, "formLoading", false) }) },
|
||||
onDelete(row) { this.openConfirm("delete", row) },
|
||||
deleteApplication(row) { this.$set(this, "formLoading", true); this.$axios.post("/platform/unionReimburse/mine/delete", {id: row.id}).then((resp) => { if (resp.code === 0) { this.$toast.success(resp.msg); this.doSearch() } else { this.$toast.fail(resp.msg) } }).finally(() => { this.$set(this, "formLoading", false) }) },
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$set(this.pageForm, "pageNumber", 1)
|
||||
this.$set(this.pageForm, "totalCount", 0)
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
},
|
||||
@@ -198,7 +175,13 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
created() {
|
||||
this.initData()
|
||||
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (manager) { manager.ensureRegistered("union-reimburse-collect"); this.$set(this, "historyLayerUnsubscribe", manager.subscribe((layers) => { this.$set(this, "confirmVisible", layers.includes("union-reimburse-collect-confirm")) })) }
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.historyLayerUnsubscribe) this.historyLayerUnsubscribe()
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (manager) manager.unregister("union-reimburse-collect")
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
const UNION_REIMBURSE_INFO = {
|
||||
template:
|
||||
/*language=HTML*/
|
||||
`
|
||||
<van-action-sheet v-model="visible" class="union-reimburse-info-sheet">
|
||||
<div class="union-info-header">
|
||||
<div class="union-info-header-title">查看详情</div>
|
||||
<div class="union-info-close" @click="onClose">
|
||||
<van-icon name="cross"></van-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-container">
|
||||
template: /*language=HTML*/ `
|
||||
<van-popup v-model="visible" position="right" :style="{width: '100%', height: '100%'}" :get-container="false" :close-on-click-overlay="false" class="union-reimburse-info-sheet">
|
||||
<div class="union-reimburse-info-detail">
|
||||
<van-nav-bar :title="detailTitle" left-text="返回" left-arrow fixed @click-left="onClose"></van-nav-bar>
|
||||
<div class="detail-container">
|
||||
<div class="union-info-scroll">
|
||||
<div class="union-info-section">
|
||||
<div class="union-info-section-title">报销申请</div>
|
||||
@@ -19,7 +13,7 @@ const UNION_REIMBURSE_INFO = {
|
||||
</div>
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">经办人</div>
|
||||
<div class="union-info-value union-info-link">{{ viewData.userName }}</div>
|
||||
<div class="union-info-value">{{ viewData.userName }}</div>
|
||||
</div>
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">联系方式</div>
|
||||
@@ -59,6 +53,8 @@ const UNION_REIMBURSE_INFO = {
|
||||
</div>
|
||||
<van-swipe ref="paymentInfoSwipe" :loop="false" :show-indicators="false" @change="handlePaymentSwipeChange">
|
||||
<van-swipe-item v-for="(item, index) in paymentInfoRows" :key="index">
|
||||
<div class="union-payment-card">
|
||||
<div class="union-payment-card-title">支付信息{{ index + 1 }}</div>
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">支付方式</div>
|
||||
<div class="union-info-value">{{ getPaymentWayText(item.paymentWay) }}</div>
|
||||
@@ -85,6 +81,7 @@ const UNION_REIMBURSE_INFO = {
|
||||
<div class="union-info-value">{{ item.bankCardNumber }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</van-swipe-item>
|
||||
</van-swipe>
|
||||
</template>
|
||||
@@ -101,18 +98,6 @@ const UNION_REIMBURSE_INFO = {
|
||||
<div class="union-info-label">性别</div>
|
||||
<div class="union-info-value">{{ viewData.condolenceSex }}</div>
|
||||
</div>
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">生日</div>
|
||||
<div class="union-info-value">{{ formatDateText(viewData.condolenceBirthday) }}</div>
|
||||
</div>
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">身份证号</div>
|
||||
<div class="union-info-value">{{ viewData.condolenceIdCard }}</div>
|
||||
</div>
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">联系方式</div>
|
||||
<div class="union-info-value">{{ viewData.condolenceMobile }}</div>
|
||||
</div>
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">慰问类型</div>
|
||||
<div class="union-info-value">{{ viewData.typeName || viewData.condolenceTypeName }}</div>
|
||||
@@ -129,15 +114,15 @@ const UNION_REIMBURSE_INFO = {
|
||||
<div class="union-info-label">慰问时间</div>
|
||||
<div class="union-info-value">{{ formatDateText(viewData.condolenceTime) }}</div>
|
||||
</div>
|
||||
<div class="union-info-row" v-if="isCondolenceType('cf4ce7af322d464f8f86d818fcc00203')">
|
||||
<div class="union-info-row" v-if="condolenceTypeCode === 'A'">
|
||||
<div class="union-info-label">结婚时间</div>
|
||||
<div class="union-info-value">{{ formatDateText(viewData.marryTime) }}</div>
|
||||
</div>
|
||||
<div class="union-info-row" v-if="isCondolenceType('c90cb10dce6542e99ae271bee6fe8cc0')">
|
||||
<div class="union-info-row" v-if="condolenceTypeCode === 'D'">
|
||||
<div class="union-info-label">生育时间</div>
|
||||
<div class="union-info-value">{{ formatDateText(viewData.fertilityTime) }}</div>
|
||||
</div>
|
||||
<template v-if="isCondolenceType('4e316737e71047e0b01aea78524c1416')">
|
||||
<template v-if="condolenceTypeCode === 'E'">
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">住院病由</div>
|
||||
<div class="union-info-value">{{ viewData.hospitalCausation }}</div>
|
||||
@@ -159,12 +144,12 @@ const UNION_REIMBURSE_INFO = {
|
||||
<div class="union-info-value">{{ viewData.hospitalCount }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="isCondolenceType('60f03a87b62b4823855814afdbf5672a')">
|
||||
<template v-if="condolenceTypeCode === 'G' || condolenceTypeCode === 'H'">
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">去逝时间</div>
|
||||
<div class="union-info-value">{{ formatDateText(viewData.deathTime) }}</div>
|
||||
</div>
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-row" v-if="condolenceTypeCode === 'H'">
|
||||
<div class="union-info-label">与被慰问人关系</div>
|
||||
<div class="union-info-value">{{ viewData.condolenceRelationship }}</div>
|
||||
</div>
|
||||
@@ -177,17 +162,13 @@ const UNION_REIMBURSE_INFO = {
|
||||
<div class="union-info-label">报销事由</div>
|
||||
<div class="union-info-value">{{ viewData.paymentNotes }}</div>
|
||||
</div>
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">备注</div>
|
||||
<div class="union-info-value">{{ viewData.notes }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="union-info-section" v-if="viewData.reimburseProject && viewData.reimburseProject !== 'UNION_REIMBURSE_PROJECT_1'">
|
||||
<div class="union-info-section-title">活动信息</div>
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">活动名称</div>
|
||||
<div class="union-info-value union-info-link">{{ viewData.activityName }}</div>
|
||||
<div class="union-info-value">{{ viewData.activityName }}</div>
|
||||
</div>
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">活动人数</div>
|
||||
@@ -201,10 +182,6 @@ const UNION_REIMBURSE_INFO = {
|
||||
<div class="union-info-label">活动时间</div>
|
||||
<div class="union-info-value">{{ formatDateText(viewData.activityTime) }}</div>
|
||||
</div>
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">支付内容</div>
|
||||
<div class="union-info-value">{{ viewData.paymentNotes }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="union-info-section">
|
||||
@@ -225,6 +202,10 @@ const UNION_REIMBURSE_INFO = {
|
||||
<div class="union-info-label">发票张数</div>
|
||||
<div class="union-info-value">{{ viewData.invoiceNumber }}</div>
|
||||
</div>
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">支付内容</div>
|
||||
<div class="union-info-value">{{ viewData.notes }}</div>
|
||||
</div>
|
||||
<div class="union-invoice-subtitle">发票明细表</div>
|
||||
<div class="union-invoice-card-list" v-if="viewData.invoiceDetails && viewData.invoiceDetails.length > 0">
|
||||
<div class="union-invoice-card" v-for="(item, index) in viewData.invoiceDetails" :key="index">
|
||||
@@ -234,7 +215,15 @@ const UNION_REIMBURSE_INFO = {
|
||||
<div class="union-info-value">{{ item.invoiceNo || '未填写' }}</div>
|
||||
</div>
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">发票金额</div>
|
||||
<div class="union-info-label">税前金额</div>
|
||||
<div class="union-info-value">{{ item.amountWithoutTax == null ? '未识别' : formatMoney(item.amountWithoutTax) }}</div>
|
||||
</div>
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">税额</div>
|
||||
<div class="union-info-value">{{ item.taxAmount == null ? '未识别' : formatMoney(item.taxAmount) }}</div>
|
||||
</div>
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">价税合计</div>
|
||||
<div class="union-info-value">{{ formatMoney(item.invoiceAmount) }}</div>
|
||||
</div>
|
||||
<div class="union-info-row">
|
||||
@@ -272,12 +261,12 @@ const UNION_REIMBURSE_INFO = {
|
||||
<!-- </van-cell-group>-->
|
||||
|
||||
<template v-for="(task,index) in doneTasks">
|
||||
<div class="union-info-section">
|
||||
<div class="process-title">{{ task.displayName }}</div>
|
||||
<template v-if="task.ext.isFirstTaskNode">
|
||||
<section class="union-info-section union-info-task-card">
|
||||
<h3 class="union-info-section-title union-info-task-card__title">{{ task.displayName || '审核节点' }}</h3>
|
||||
<template v-if="task.ext && task.ext.isFirstTaskNode">
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">申请用户</div>
|
||||
<div class="union-info-value">{{ task.ext.initiatorName}}({{task.ext.initiatorAccount}})</div>
|
||||
<div class="union-info-value">{{ task.ext.initiatorName || '--' }}({{task.ext.initiatorAccount || '--'}})</div>
|
||||
</div>
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">申请时间</div>
|
||||
@@ -286,14 +275,14 @@ const UNION_REIMBURSE_INFO = {
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">办理结果</div>
|
||||
<div class="union-info-value">
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE" :value="task.ext.submitType"></dict-tag>
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE" :value="task.ext && task.ext.submitType"></dict-tag>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">办理用户</div>
|
||||
<div class="union-info-value">{{ task.taskFormData.userName}}({{task.taskFormData.loginName}})</div>
|
||||
<div class="union-info-value">{{ getTaskUserText(task) }}</div>
|
||||
</div>
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">办理时间</div>
|
||||
@@ -302,47 +291,78 @@ const UNION_REIMBURSE_INFO = {
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">办理结果</div>
|
||||
<div class="union-info-value">
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE" :value="task.ext.submitType"></dict-tag>
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE" :value="task.ext && task.ext.submitType"></dict-tag>
|
||||
</div>
|
||||
</div>
|
||||
<div class="union-info-row" v-if="!task.ext.isFirstTaskNode">
|
||||
<div class="union-info-row">
|
||||
<div class="union-info-label">办理意见</div>
|
||||
<div class="union-info-value">{{ task.taskFormData.opinion }}</div>
|
||||
<div class="union-info-value">{{ getTaskOpinion(task) }}</div>
|
||||
</div>
|
||||
<div class="union-info-row" v-if="!task.ext.isFirstTaskNode && task.ext.tf_userSign">
|
||||
<div class="union-info-row" v-if="task.ext && task.ext.tf_userSign">
|
||||
<div class="union-info-label">签字</div>
|
||||
<div class="union-info-value">
|
||||
<van-image :src="task.ext.tf_userSign" class="signature-image"></van-image>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
<slot></slot>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<slot></slot>
|
||||
</van-action-sheet>
|
||||
<div v-if="$slots.footer" class="union-reimburse-info-footer">
|
||||
<slot name="footer"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
`,
|
||||
dicts: ["UNION_REIMBURSE_TYPE", "UNION_REIMBURSE_PAYMENT_WAY", "UNION_REIMBURSE_FUND_SOURCE", "UNION_REIMBURSE_PROJECT", "PROCESS_TASK_SUBMIT_TYPE"],
|
||||
props: {
|
||||
historyLayerName: {
|
||||
type: String,
|
||||
default: "union-reimburse-info"
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
viewData: {},
|
||||
doneTasks: [],
|
||||
row: null,
|
||||
currentPaymentIndex: 0
|
||||
currentPaymentIndex: 0,
|
||||
detailTitle: "报销详情",
|
||||
historyLayerUnsubscribe: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 详情接口按关联类型返回业务编码,避免不同环境的类型 ID 影响字段显示。
|
||||
condolenceTypeCode() {
|
||||
return this.viewData.reimburseProject === "UNION_REIMBURSE_PROJECT_1"
|
||||
? (this.viewData.condolenceTypeCode || "") : ""
|
||||
},
|
||||
paymentInfoRows() {
|
||||
return this.viewData.paymentDetails || []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.injectInfoStyle()
|
||||
this.subscribeHistoryLayer()
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.historyLayerUnsubscribe) this.historyLayerUnsubscribe()
|
||||
},
|
||||
methods: {
|
||||
// PJAX 会重置全局历史栈订阅;每次打开前重新订阅,保证返回事件能同步关闭详情。
|
||||
subscribeHistoryLayer() {
|
||||
if (this.historyLayerUnsubscribe) this.historyLayerUnsubscribe()
|
||||
this.$set(this, "historyLayerUnsubscribe", null)
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (!manager) return
|
||||
manager.ensureRegistered("union-reimburse-info")
|
||||
this.$set(this, "historyLayerUnsubscribe", manager.subscribe((layers) => {
|
||||
this.$set(this, "visible", layers.includes(this.historyLayerName))
|
||||
}))
|
||||
},
|
||||
injectInfoStyle() {
|
||||
// 当前组件是普通 JS 对象注册,Vue 不会自动注入 style 字段,这里只为本详情弹窗注入一次样式。
|
||||
const styleId = "union-reimburse-info-style"
|
||||
@@ -355,16 +375,30 @@ const UNION_REIMBURSE_INFO = {
|
||||
styleNode.appendChild(document.createTextNode(this.$options.style))
|
||||
document.head.appendChild(styleNode)
|
||||
},
|
||||
onOpen(row) {
|
||||
this.row = row
|
||||
this.visible = true
|
||||
this.currentPaymentIndex = 0
|
||||
onOpen(row, title) {
|
||||
this.$set(this, "row", row)
|
||||
this.$set(this, "detailTitle", title || "报销详情")
|
||||
this.$set(this, "currentPaymentIndex", 0)
|
||||
// 详情弹层的显示状态由全局历史栈统一同步,确保系统返回键与页面返回按钮关闭同一层。
|
||||
this.subscribeHistoryLayer()
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (manager && manager.open(this.historyLayerName)) {
|
||||
this.getInfo()
|
||||
this.getDoneTasks()
|
||||
return
|
||||
}
|
||||
this.$set(this, "visible", true)
|
||||
this.getInfo()
|
||||
this.getDoneTasks()
|
||||
},
|
||||
// 关闭
|
||||
// 详情之上存在确认框或预览时先关闭最上层;无历史层时才直接关闭详情。
|
||||
onClose() {
|
||||
this.visible = false
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (manager && manager.stack.length) {
|
||||
manager.close()
|
||||
return
|
||||
}
|
||||
this.$set(this, "visible", false)
|
||||
},
|
||||
formatCreateTime(value) {
|
||||
return value && this.$moment(value).isValid() ? this.$moment(value).format("YYYY-MM-DD HH:mm:ss") : ""
|
||||
@@ -379,13 +413,20 @@ const UNION_REIMBURSE_INFO = {
|
||||
const numberValue = Number(value)
|
||||
return isNaN(numberValue) ? value : numberValue.toFixed(2)
|
||||
},
|
||||
isCondolenceType(typeId) {
|
||||
return this.viewData.condolenceTypeId === typeId || this.viewData.condolenceType === typeId
|
||||
},
|
||||
getPaymentWayText(paymentWay) {
|
||||
const matchedPaymentWay = this.dict.type.UNION_REIMBURSE_PAYMENT_WAY.find(item => item.code === paymentWay)
|
||||
return matchedPaymentWay ? matchedPaymentWay.name : ""
|
||||
},
|
||||
getTaskUserText(task) {
|
||||
const formData = task && task.taskFormData ? task.taskFormData : {}
|
||||
const userName = formData.userName || formData.username || "--"
|
||||
const loginName = formData.loginName || formData.loginname || "--"
|
||||
return userName + "(" + loginName + ")"
|
||||
},
|
||||
getTaskOpinion(task) {
|
||||
const formData = task && task.taskFormData ? task.taskFormData : {}
|
||||
return formData.reviewOpinion || formData.opinion || formData.tf_opinion || "--"
|
||||
},
|
||||
buildViewData(data) {
|
||||
const viewData = Object.assign({
|
||||
files: [],
|
||||
@@ -425,15 +466,15 @@ const UNION_REIMBURSE_INFO = {
|
||||
}
|
||||
},
|
||||
handlePaymentSwipeChange(index) {
|
||||
this.currentPaymentIndex = index
|
||||
this.$set(this, "currentPaymentIndex", index)
|
||||
},
|
||||
swipeToPayment(index) {
|
||||
if (!this.paymentInfoRows.length) {
|
||||
this.currentPaymentIndex = 0
|
||||
this.$set(this, "currentPaymentIndex", 0)
|
||||
return
|
||||
}
|
||||
const targetIndex = Math.max(0, Math.min(index, this.paymentInfoRows.length - 1))
|
||||
this.currentPaymentIndex = targetIndex
|
||||
this.$set(this, "currentPaymentIndex", targetIndex)
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.paymentInfoSwipe && this.$refs.paymentInfoSwipe.swipeTo) {
|
||||
this.$refs.paymentInfoSwipe.swipeTo(targetIndex)
|
||||
@@ -456,8 +497,8 @@ const UNION_REIMBURSE_INFO = {
|
||||
getInfo() {
|
||||
this.$axios.post("/platform/unionReimburse/apply/info", { id: this.row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.viewData = this.buildViewData(res.data)
|
||||
this.currentPaymentIndex = 0
|
||||
this.$set(this, "viewData", this.buildViewData(res.data))
|
||||
this.$set(this, "currentPaymentIndex", 0)
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -471,120 +512,138 @@ const UNION_REIMBURSE_INFO = {
|
||||
getDoneTasks() {
|
||||
this.$axios.post("/flow/common/doneTasks", { bizId: this.row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.doneTasks = res.data
|
||||
this.$set(this, "doneTasks", res.data || [])
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
style: /*language=CSS*/ `
|
||||
.union-reimburse-info-sheet {
|
||||
height: 92vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
background: #f3f7fd;
|
||||
}
|
||||
|
||||
.union-reimburse-info-sheet .van-action-sheet__content {
|
||||
.union-reimburse-info-detail {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
padding-top: 46px;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
background: #f3f7fd;
|
||||
}
|
||||
|
||||
.union-info-header {
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 56px;
|
||||
padding: 0 20px;
|
||||
.union-reimburse-info-detail > .van-nav-bar {
|
||||
z-index: 20;
|
||||
background: #fff;
|
||||
border-top: 4px solid #1677ff;
|
||||
border-bottom: 1px solid #e7ebf0;
|
||||
}
|
||||
|
||||
.union-info-header-title {
|
||||
color: #111827;
|
||||
.union-reimburse-info-detail > .van-nav-bar .van-nav-bar__title {
|
||||
color: #172033;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.union-info-close {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
color: #8b95a3;
|
||||
font-size: 20px;
|
||||
.union-reimburse-info-detail > .van-nav-bar .van-icon,
|
||||
.union-reimburse-info-detail > .van-nav-bar .van-nav-bar__text {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.detail-container {
|
||||
.union-reimburse-info-detail > .detail-container {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
background: #f2f4f7;
|
||||
background: #f3f7fd;
|
||||
}
|
||||
|
||||
/* 审核按钮占独立底部区域,意见表单随正文滚动,避免被按钮遮挡或挤出可视区。 */
|
||||
.union-reimburse-info-footer {
|
||||
flex-shrink: 0;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.union-info-scroll {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
padding-bottom: 16px;
|
||||
padding: 12px 15px calc(18px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.union-info-section {
|
||||
overflow: hidden;
|
||||
margin-bottom: 11px;
|
||||
border: 1px solid #e9eff7;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
margin-bottom: 10px;
|
||||
box-shadow: 0 3px 11px rgba(51, 87, 126, .08);
|
||||
}
|
||||
|
||||
.union-info-section-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 44px;
|
||||
padding: 0 16px;
|
||||
color: #1f2937;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
background: #f5f7fa;
|
||||
border-bottom: 1px solid #e7ebf0;
|
||||
position: relative;
|
||||
margin: 0;
|
||||
padding: 12px 14px 8px 21px;
|
||||
color: #354255;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.union-info-section-title::before {
|
||||
content: "";
|
||||
width: 4px;
|
||||
height: 16px;
|
||||
margin-right: 8px;
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
bottom: 11px;
|
||||
left: 12px;
|
||||
width: 2px;
|
||||
border-radius: 2px;
|
||||
background: #1677ff;
|
||||
background: #1989fa;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.union-info-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
min-height: 44px;
|
||||
padding: 12px 20px;
|
||||
border-bottom: 1px solid #edf0f4;
|
||||
min-height: 43px;
|
||||
padding: 10px 14px;
|
||||
border-bottom: 1px solid #eef2f7;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 查看详情中的流程节点字段与社团审核详情卡片保持一致的行高和内边距。 */
|
||||
.union-info-task-card > .union-info-task-card__title {
|
||||
margin: 0;
|
||||
padding: 12px 14px 8px 21px;
|
||||
}
|
||||
|
||||
.union-info-task-card .union-info-row {
|
||||
min-height: 44px;
|
||||
padding: 10px 14px;
|
||||
}
|
||||
|
||||
.union-info-task-card .union-info-label,
|
||||
.union-info-task-card .union-info-value {
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.union-info-row:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.union-info-label {
|
||||
flex: 0 0 96px;
|
||||
color: #8a94a6;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
flex: 0 0 102px;
|
||||
color: #596779;
|
||||
font-size: 12px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.union-info-value {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
color: #1f2937;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
text-align: right;
|
||||
color: #4f5d70;
|
||||
font-size: 12px;
|
||||
line-height: 22px;
|
||||
text-align: left;
|
||||
word-break: break-all;
|
||||
white-space: pre-line;
|
||||
}
|
||||
@@ -597,7 +656,7 @@ const UNION_REIMBURSE_INFO = {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
padding: 12px 20px 4px;
|
||||
padding: 10px 14px 3px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
@@ -617,21 +676,44 @@ const UNION_REIMBURSE_INFO = {
|
||||
background: #1677ff;
|
||||
}
|
||||
|
||||
.union-payment-card {
|
||||
margin: 8px 12px 12px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #e6ebf2;
|
||||
border-radius: 9px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.union-payment-card-title {
|
||||
padding: 9px 12px;
|
||||
color: #40526a;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
line-height: 20px;
|
||||
background: #f7f9fd;
|
||||
border-bottom: 1px solid #eef2f7;
|
||||
}
|
||||
|
||||
.union-payment-card .union-info-row {
|
||||
padding-right: 12px;
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
.union-empty-text {
|
||||
padding: 14px 20px;
|
||||
padding: 12px 14px;
|
||||
color: #9aa3af;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.union-file-preview {
|
||||
padding: 12px 20px 16px;
|
||||
padding: 10px 14px 14px;
|
||||
}
|
||||
|
||||
.union-invoice-subtitle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 40px;
|
||||
padding: 0 20px;
|
||||
padding: 0 14px;
|
||||
color: #6b7280;
|
||||
font-size: 13px;
|
||||
background: #f5f7fa;
|
||||
@@ -640,13 +722,13 @@ const UNION_REIMBURSE_INFO = {
|
||||
}
|
||||
|
||||
.union-invoice-card-list {
|
||||
padding: 12px 16px 4px;
|
||||
padding: 10px 12px 0;
|
||||
}
|
||||
|
||||
.union-invoice-card {
|
||||
margin-bottom: 12px;
|
||||
padding: 14px 14px 12px;
|
||||
border-radius: 12px;
|
||||
padding: 12px 12px 10px;
|
||||
border-radius: 9px;
|
||||
border: 1px solid #e6ebf2;
|
||||
background: #fff;
|
||||
box-shadow: 0 1px 3px rgba(31, 35, 41, 0.05);
|
||||
@@ -663,17 +745,6 @@ const UNION_REIMBURSE_INFO = {
|
||||
padding: 12px 0 0;
|
||||
}
|
||||
|
||||
.process-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 40px;
|
||||
padding: 0 20px;
|
||||
color: #1f2937;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
background: #f5f7fa;
|
||||
}
|
||||
|
||||
.signature-image {
|
||||
width: 100%;
|
||||
height: 120px;
|
||||
|
||||
+70
-78
@@ -2,63 +2,65 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style>
|
||||
.state-primary {
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.state-success {
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.state-danger {
|
||||
color: #f56c6c;
|
||||
}
|
||||
<style id="style-union-reimburse-h5">
|
||||
<!--#include('../common/unionReimburse.css'){}#-->
|
||||
</style>
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="我的报销" placeholder fixed></van-nav-bar>
|
||||
<div id="app" v-cloak class="union-reimburse-page">
|
||||
<van-nav-bar @click-left="onNavBack" left-arrow left-text="返回" title="我的报销" placeholder fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item :options="yearList" @change="doSearch" v-model="pageForm.year"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<div class="union-reimburse-sticky">
|
||||
<van-search v-model="pageForm.searchKeyword" class="union-reimburse-search" placeholder="请输入姓名或工号搜索" shape="round" clearable @search="doSearch" @clear="doSearch"></van-search>
|
||||
<van-dropdown-menu class="union-reimburse-filter" :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item :options="yearList" @change="doSearch" v-model="pageForm.year"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
|
||||
<table-list api="/platform/unionReimburse/mine/pageData" :page_form.sync="pageForm" ref="tableListRef"
|
||||
@ready="doSearch" >
|
||||
<main class="union-reimburse-list-content">
|
||||
<table-list api="/platform/unionReimburse/mine/pageData" :page_form.sync="pageForm" ref="tableListRef" :show_loading_overlay="false"
|
||||
@ready="doSearch" @loading-change="onLoadingChange">
|
||||
<template #header="{row}">
|
||||
<div v-if="row" class="union-reimburse-card-header">
|
||||
<div class="union-reimburse-card-header__heading"><div class="union-reimburse-card-header__title">{{row.userName || '--'}}</div><div class="union-reimburse-card-header__sub">工号:{{row.loginName || '--'}}</div></div>
|
||||
<enum-tag class="union-reimburse-card-header__status" v-if="row.instanceState" :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||
<van-tag v-else :class="['union-reimburse-card-header__status', getStatusClass(row.stateId)]">{{getStateName(row.stateId)}}</van-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="经办人工号">{{row.loginName}}</table-column>
|
||||
<table-column label="姓名">{{row.userName}}</table-column>
|
||||
<table-column label="所属工会">{{row.unionName}}</table-column>
|
||||
<table-column label="所属单位">{{row.unitName}}</table-column>
|
||||
<table-column label="申请时间">{{formatCreateTime(row.createTime)}}</table-column>
|
||||
<table-column label="报销项目">{{getReimburseProjectName(row.reimburseProject)}}</table-column>
|
||||
<table-column label="备注">{{getRemarkText(row)}}</table-column>
|
||||
<table-column label="申请状态">
|
||||
<span :class="getStateClass(row.stateId)">{{getStateName(row.stateId)}}</span>
|
||||
</table-column>
|
||||
<table-column label="报销项目">{{getReimburseProjectName(row.reimburseProject) || '--'}}</table-column>
|
||||
<table-column label="" label_suffix="">{{getRemarkText(row) || '--'}}</table-column>
|
||||
<table-column label="所属工会">{{row.unionName || '--'}}</table-column>
|
||||
<table-column label="所属单位">{{row.unitName || '--'}}</table-column>
|
||||
<table-column label="申请时间">{{formatCreateTime(row.createTime) || '--'}}</table-column>
|
||||
<table-column label="当前节点">{{row.taskName || '--'}}</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<van-icon name="eye-o"></van-icon>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" @click="onEdit(row)" v-if="row.stateId == 1 || row.stateId == 5">
|
||||
<i class="fa fa-edit"></i>
|
||||
<van-icon name="edit"></van-icon>
|
||||
<span>编辑</span>
|
||||
</div>
|
||||
<div class="action-btn delete" v-if="row.stateId == 2" @click="onRevoke(row)">
|
||||
<i class="fa fa-undo"></i>
|
||||
<van-icon name="revoke"></van-icon>
|
||||
<span>撤回</span>
|
||||
</div>
|
||||
<div class="action-btn delete" @click="onDelete(row)" v-if="row.stateId == 1">
|
||||
<i class="fa fa-trash"></i>
|
||||
<van-icon name="delete-o"></van-icon>
|
||||
<span>删除</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #empty>
|
||||
<div v-if="listLoading" class="union-reimburse-list-skeleton"><div v-for="item in 2" :key="item" class="union-reimburse-skeleton-card"><div class="union-reimburse-skeleton-line union-reimburse-skeleton-line--title"></div><div class="union-reimburse-skeleton-line"></div><div class="union-reimburse-skeleton-line union-reimburse-skeleton-line--short"></div></div></div>
|
||||
<div v-else class="union-reimburse-empty"><img src="/assets/mobile/img/unionReimburse/union-reimburse-empty.png" alt="暂无报销记录插画"><div class="union-reimburse-empty__title">暂无报销记录</div><div class="union-reimburse-empty__hint">当前筛选条件下暂时没有报销申请</div></div>
|
||||
</template>
|
||||
</table-list>
|
||||
</main>
|
||||
|
||||
<union-reimburse-info ref="unionReimburseInfoRef"></union-reimburse-info>
|
||||
<union-reimburse-info ref="unionReimburseInfoRef" history-layer-name="union-reimburse-mine-info"></union-reimburse-info>
|
||||
<van-dialog :value="confirmVisible" title="提示" :message="confirmMessage" show-cancel-button :confirm-button-loading="formLoading" @confirm="confirmPendingAction" @cancel="closeConfirm"></van-dialog>
|
||||
|
||||
</div>
|
||||
<script nonce="${cspNonce!}">
|
||||
@@ -66,13 +68,18 @@ layout("/layouts/platform_h5.html"){
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
dicts: ["UNION_REIMBURSE_PROJECT"],
|
||||
dicts: ["UNION_REIMBURSE_PROJECT", "PROCESS_INSTANCE_STATE"],
|
||||
components: {
|
||||
"union-reimburse-info":UNION_REIMBURSE_INFO
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
viewShow: false,
|
||||
listLoading: true,
|
||||
formLoading: false,
|
||||
confirmVisible: false,
|
||||
pendingAction: "",
|
||||
pendingRow: null,
|
||||
historyLayerUnsubscribe: null,
|
||||
yearList: [],
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
@@ -84,6 +91,9 @@ layout("/layouts/platform_h5.html"){
|
||||
infoShow: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
confirmMessage() { return this.pendingAction === "revoke" ? "您确定要撤销申请吗?" : "您确定要删除吗?" }
|
||||
},
|
||||
methods: {
|
||||
// 手机端列表的报销项目、备注、状态文案与 PC 端 mine 列表保持一致。
|
||||
getReimburseProjectName(reimburseProject) {
|
||||
@@ -125,58 +135,34 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
return stateId || ""
|
||||
},
|
||||
getStateClass(stateId) {
|
||||
if (stateId == 3) {
|
||||
return "state-success"
|
||||
}
|
||||
if (stateId == 4) {
|
||||
return "state-danger"
|
||||
}
|
||||
return "state-primary"
|
||||
getStatusClass(stateId) {
|
||||
if (stateId == 3) return "union-reimburse-card-header__status--success"
|
||||
if (stateId == 4 || stateId == 5) return "union-reimburse-card-header__status--danger"
|
||||
return "union-reimburse-card-header__status--pending"
|
||||
},
|
||||
formatCreateTime(value) {
|
||||
return value && this.$moment(value).isValid() ? this.$moment(value).format("YYYY-MM-DD HH:mm:ss") : ""
|
||||
},
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
this.$refs.unionReimburseInfoRef.onOpen(row)
|
||||
this.$refs.unionReimburseInfoRef.onOpen(row, "报销详情")
|
||||
},
|
||||
onEdit(row) {
|
||||
this.$pjaxReplace('/platform/unionReimburse/apply/h5?taskId=' + (row.startTaskId || '') + "&bizId=" + row.id)
|
||||
},
|
||||
|
||||
onRevoke(row){
|
||||
this.$dialog
|
||||
.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要撤销申请吗?"
|
||||
})
|
||||
.then(() => {
|
||||
this.$axios.post("/platform/unionReimburse/mine/revokeTask", {id: row.id}).then((resp) => {
|
||||
this.$toast.success(resp.msg)
|
||||
this.doSearch()
|
||||
})
|
||||
})
|
||||
},
|
||||
onDelete(row) {
|
||||
this.$dialog
|
||||
.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要删除吗?"
|
||||
})
|
||||
.then(() => {
|
||||
this.$axios.post("/platform/unionReimburse/mine/delete", {id: row.id}).then((resp) => {
|
||||
if (resp.code === 0) {
|
||||
this.$toast.success(resp.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
onLoadingChange(state) { this.$set(this, "listLoading", state.loading) },
|
||||
onNavBack() { const manager = window.h5HistoryLayerManager; if (manager && manager.stack.length) { manager.close(); return } historyBack() },
|
||||
openConfirm(action, row) { this.$set(this, "pendingAction", action); this.$set(this, "pendingRow", row); const manager = window.h5HistoryLayerManager; if (manager) { manager.open("union-reimburse-mine-confirm"); return } this.$set(this, "confirmVisible", true) },
|
||||
closeConfirm(afterClose) { const manager = window.h5HistoryLayerManager; if (manager) { manager.close("union-reimburse-mine-confirm", afterClose); return } this.$set(this, "confirmVisible", false); if (afterClose) afterClose() },
|
||||
confirmPendingAction() { const action = this.pendingAction; const row = this.pendingRow; this.closeConfirm(() => { if (action === "revoke") { this.revoke(row) } else { this.deleteApplication(row) } }) },
|
||||
onRevoke(row){ this.openConfirm("revoke", row) },
|
||||
revoke(row) { this.$set(this, "formLoading", true); this.$axios.post("/platform/unionReimburse/mine/revokeTask", {id: row.id}).then((resp) => { if (resp.code === 0) { this.$toast.success(resp.msg); this.doSearch() } else { this.$toast.fail(resp.msg) } }).finally(() => { this.$set(this, "formLoading", false) }) },
|
||||
onDelete(row) { this.openConfirm("delete", row) },
|
||||
deleteApplication(row) { this.$set(this, "formLoading", true); this.$axios.post("/platform/unionReimburse/mine/delete", {id: row.id}).then((resp) => { if (resp.code === 0) { this.$toast.success(resp.msg); this.doSearch() } else { this.$toast.fail(resp.msg) } }).finally(() => { this.$set(this, "formLoading", false) }) },
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$set(this.pageForm, "pageNumber", 1)
|
||||
this.$set(this.pageForm, "totalCount", 0)
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
},
|
||||
@@ -190,7 +176,13 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
created() {
|
||||
this.initData()
|
||||
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (manager) { manager.ensureRegistered("union-reimburse-mine"); this.$set(this, "historyLayerUnsubscribe", manager.subscribe((layers) => { this.$set(this, "confirmVisible", layers.includes("union-reimburse-mine-confirm")) })) }
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.historyLayerUnsubscribe) this.historyLayerUnsubscribe()
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (manager) manager.unregister("union-reimburse-mine")
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
+99
-114
@@ -2,100 +2,66 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style>
|
||||
.state-primary {
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.state-success {
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.state-danger {
|
||||
color: #f56c6c;
|
||||
}
|
||||
<style id="style-union-reimburse-h5">
|
||||
<!--#include('../common/unionReimburse.css'){}#-->
|
||||
</style>
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="报销审核" placeholder fixed></van-nav-bar>
|
||||
<div id="app" v-cloak class="union-reimburse-page">
|
||||
<van-nav-bar @click-left="onNavBack" left-arrow left-text="返回" title="报销审核" placeholder fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<van-search
|
||||
:reverse-color="false"
|
||||
:show-action="false"
|
||||
@search="doSearch"
|
||||
input-align="left"
|
||||
placeholder="请输入经办人搜索"
|
||||
v-model="pageForm.searchKeyword"
|
||||
></van-search>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
<div class="union-reimburse-sticky">
|
||||
<van-search class="union-reimburse-search" :reverse-color="false" :show-action="false" @search="doSearch" @clear="doSearch" input-align="left" placeholder="请输入姓名或工号搜索" v-model="pageForm.searchKeyword"></van-search>
|
||||
<van-dropdown-menu class="union-reimburse-filter" :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item :options="yearList" @change="doSearch" v-model="pageForm.year"></van-dropdown-item>
|
||||
<van-dropdown-item :options="reimburseProjectOptions" @change="doSearch" v-model="pageForm.reimburseProject"></van-dropdown-item>
|
||||
<van-dropdown-item :options="approvalOptions" @change="onApprovalFilterChange" v-model="pageForm.approvalText"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
|
||||
<table-list api="/platform/unionReimburse/review/pageData" :page_form.sync="pageForm" ref="tableListRef"
|
||||
@ready="doSearch">
|
||||
<main class="union-reimburse-list-content">
|
||||
<table-list api="/platform/unionReimburse/review/pageData" :page_form.sync="pageForm" ref="tableListRef" :show_loading_overlay="false"
|
||||
@ready="doSearch" @loading-change="onLoadingChange">
|
||||
<template #header="{row}"><div v-if="row" class="union-reimburse-card-header"><div class="union-reimburse-card-header__heading"><div class="union-reimburse-card-header__title">{{row.userName || '--'}}</div><div class="union-reimburse-card-header__sub">工号:{{row.loginName || '--'}}</div></div><van-tag :class="['union-reimburse-card-header__status', getStatusClass(row.stateId)]">{{getStateName(row.stateId)}}</van-tag></div></template>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="经办人工号">{{row.loginName}}</table-column>
|
||||
<table-column label="姓名">{{row.userName}}</table-column>
|
||||
<table-column label="所属工会">{{row.unionName}}</table-column>
|
||||
<table-column label="所属单位">{{row.unitName}}</table-column>
|
||||
<table-column label="申请时间">{{formatCreateTime(row.createTime)}}</table-column>
|
||||
<table-column label="报销项目">{{getReimburseProjectName(row.reimburseProject)}}</table-column>
|
||||
<table-column label="备注">{{getRemarkText(row)}}</table-column>
|
||||
<table-column label="申请状态">
|
||||
<span :class="getStateClass(row.stateId)">{{getStateName(row.stateId)}}</span>
|
||||
</table-column>
|
||||
<table-column label="报销项目">{{getReimburseProjectName(row.reimburseProject) || '--'}}</table-column>
|
||||
<table-column label="" label_suffix="">{{getRemarkText(row) || '--'}}</table-column>
|
||||
<table-column label="所属工会">{{row.unionName || '--'}}</table-column>
|
||||
<table-column label="所属单位">{{row.unitName || '--'}}</table-column>
|
||||
<table-column label="申请时间">{{formatCreateTime(row.createTime) || '--'}}</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<van-icon name="eye-o"></van-icon>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.stateId == 2" @click="onAudit(row)">
|
||||
<i class="fa fa-edit"></i>
|
||||
<div class="action-btn review" v-if="row.stateId == 2" @click="onAudit(row)">
|
||||
<van-icon name="edit"></van-icon>
|
||||
<span>审核</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #empty><div v-if="listLoading" class="union-reimburse-list-skeleton"><div v-for="item in 2" :key="item" class="union-reimburse-skeleton-card"><div class="union-reimburse-skeleton-line union-reimburse-skeleton-line--title"></div><div class="union-reimburse-skeleton-line"></div><div class="union-reimburse-skeleton-line union-reimburse-skeleton-line--short"></div></div></div><div v-else class="union-reimburse-empty"><img src="/assets/mobile/img/unionReimburse/union-reimburse-empty.png" alt="暂无报销审核记录插画"><div class="union-reimburse-empty__title">暂无报销审核记录</div><div class="union-reimburse-empty__hint">当前筛选条件下暂时没有待办申请</div></div></template>
|
||||
</table-list>
|
||||
</main>
|
||||
|
||||
<union-reimburse-info ref="unionReimburseInfoRef">
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">
|
||||
校工会审核
|
||||
</div>
|
||||
<div class="form-container">
|
||||
<union-reimburse-info ref="unionReimburseInfoRef" history-layer-name="union-reimburse-review-info">
|
||||
<div v-if="showApprovalForm" class="union-reimburse-approval">
|
||||
<section class="union-reimburse-approval-card">
|
||||
<h2 class="union-reimburse-approval-card__title">{{formData.taskName || '校工会审核'}}</h2>
|
||||
<van-form ref="formRef">
|
||||
<van-cell-group title="审批意见">
|
||||
<van-field label=""
|
||||
:rules="[{ required: true,message:'请填审批意见' }]"
|
||||
v-model="formData.reviewOpinion"
|
||||
required
|
||||
type="textarea"
|
||||
name="reviewOpinion"
|
||||
rows="4"
|
||||
autosize
|
||||
class="more-text"
|
||||
placeholder="请填审批意见"></van-field>
|
||||
</van-cell-group>
|
||||
<!-- <van-cell-group title="电子签名" class="form-section">-->
|
||||
<!-- <van-field class="more-text" name="tf_userSign" label="" required-->
|
||||
<!-- v-model="formData.reviewOpinion" :rules="[{ required: true,message:'请签名' }]">-->
|
||||
<!-- <template #input>-->
|
||||
<!-- <h5-signature v-model="formData.tf_userSign" slot="input"></h5-signature>-->
|
||||
<!-- </template>-->
|
||||
<!-- </van-field>-->
|
||||
<!-- </van-cell-group>-->
|
||||
<div class="form-actions">
|
||||
<van-button type="danger" @click="handleTaskAction(5)">退回到发起人</van-button>
|
||||
<van-button type="danger" @click="handleTaskAction(4)">拒绝申请</van-button>
|
||||
<van-button type="primary" @click="handleTaskAction(3)">同意申请</van-button>
|
||||
</div>
|
||||
<p class="union-reimburse-approval-field-label"><span class="union-reimburse-approval-required">*</span>审批意见</p>
|
||||
<van-field v-model="formData.reviewOpinion" class="union-reimburse-approval-field" name="reviewOpinion" type="textarea" rows="6" label="" placeholder="请输入审批意见" :rules="[{required: true, message: '请填写审批意见'}]" maxlength="100" show-word-limit></van-field>
|
||||
</van-form>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<template slot="footer">
|
||||
<div v-if="showApprovalForm" class="union-reimburse-approval-actions">
|
||||
<van-button :loading="formLoading" type="danger" block @click="handleTaskAction(5)">退回</van-button>
|
||||
<van-button :loading="formLoading" type="danger" block @click="handleTaskAction(4)">不同意</van-button>
|
||||
<van-button :loading="formLoading" type="primary" block @click="handleTaskAction(3)">同意</van-button>
|
||||
</div>
|
||||
</template>
|
||||
</union-reimburse-info>
|
||||
<van-dialog :value="submitConfirmVisible" title="温馨提示" message="您确定要提交审核结果吗?" show-cancel-button :confirm-button-loading="formLoading" @confirm="submitTaskAction" @cancel="closeSubmitConfirm"></van-dialog>
|
||||
|
||||
</div>
|
||||
<script nonce="${cspNonce!}">
|
||||
@@ -116,11 +82,26 @@ layout("/layouts/platform_h5.html"){
|
||||
searchKeyword: "",
|
||||
approvalText: "0",
|
||||
approval: false,
|
||||
year: new Date().getFullYear()
|
||||
year: new Date().getFullYear(),
|
||||
reimburseProject: ""
|
||||
},
|
||||
yearList: [],
|
||||
reimburseProjectOptions: [
|
||||
{text: "全部项目", value: ""},
|
||||
{text: "慰问", value: "UNION_REIMBURSE_PROJECT_1"},
|
||||
{text: "文体活动", value: "UNION_REIMBURSE_PROJECT_2"},
|
||||
{text: "日常活动", value: "UNION_REIMBURSE_PROJECT_3"},
|
||||
{text: "专项活动", value: "UNION_REIMBURSE_PROJECT_4"}
|
||||
],
|
||||
approvalOptions: [{text: "未审核", value: "0"}, {text: "已审核", value: "1"}],
|
||||
formData: {},
|
||||
showApprovalForm: false,
|
||||
infoShow: false
|
||||
infoShow: false,
|
||||
listLoading: true,
|
||||
formLoading: false,
|
||||
submitConfirmVisible: false,
|
||||
pendingSubmitType: null,
|
||||
historyLayerUnsubscribe: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -164,62 +145,66 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
return stateId || ""
|
||||
},
|
||||
getStateClass(stateId) {
|
||||
if (stateId == 3) {
|
||||
return "state-success"
|
||||
}
|
||||
if (stateId == 4) {
|
||||
return "state-danger"
|
||||
}
|
||||
return "state-primary"
|
||||
},
|
||||
getStatusClass(stateId) { if (stateId == 3) return "union-reimburse-card-header__status--success"; if (stateId == 4 || stateId == 5) return "union-reimburse-card-header__status--danger"; return "union-reimburse-card-header__status--pending" },
|
||||
formatCreateTime(value) {
|
||||
return value && this.$moment(value).isValid() ? this.$moment(value).format("YYYY-MM-DD HH:mm:ss") : ""
|
||||
},
|
||||
handleTaskAction(val) {
|
||||
const opinion = (this.formData.reviewOpinion || "").trim()
|
||||
if (!opinion) {
|
||||
this.$toast("请填写审批意见")
|
||||
this.$refs.formRef.validate("reviewOpinion").catch(() => {})
|
||||
return
|
||||
}
|
||||
this.$set(this.formData, "reviewOpinion", opinion)
|
||||
this.$refs.formRef.validate().then(() => {
|
||||
this.$dialog.confirm({
|
||||
title: "温馨提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/platform/unionReimburse/review/reviewTask", {
|
||||
data: JSON.stringify(Object.assign({}, this.formData)),
|
||||
submitType: val
|
||||
}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.success("提交成功")
|
||||
this.doSearch()
|
||||
this.$refs.unionReimburseInfoRef.onClose()
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
})
|
||||
}).catch()
|
||||
this.$set(this, "pendingSubmitType", val)
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (manager) { manager.open("union-reimburse-review-confirm"); return }
|
||||
this.$set(this, "submitConfirmVisible", true)
|
||||
}).catch(() => {})
|
||||
},
|
||||
closeSubmitConfirm(afterClose) { const manager = window.h5HistoryLayerManager; if (manager) { manager.close("union-reimburse-review-confirm", afterClose); return } this.$set(this, "submitConfirmVisible", false); if (afterClose) afterClose() },
|
||||
submitTaskAction() { const submitType = this.pendingSubmitType; this.closeSubmitConfirm(() => { this.$set(this, "formLoading", true); this.$axios.post("/platform/unionReimburse/review/reviewTask", {data: JSON.stringify(Object.assign({}, this.formData)), submitType: submitType}).then((res) => { if (res.code === 0) { this.$toast.success("提交成功"); this.doSearch(); this.$refs.unionReimburseInfoRef.onClose() } else { this.$toast.fail(res.msg) } }).finally(() => { this.$set(this, "formLoading", false) }) }) },
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
this.$refs.unionReimburseInfoRef.onOpen(row)
|
||||
this.$set(this, "showApprovalForm", false)
|
||||
this.$refs.unionReimburseInfoRef.onOpen(row, "报销详情")
|
||||
},
|
||||
onAudit(row) {
|
||||
this.showApprovalForm = true
|
||||
this.formData = {
|
||||
this.$set(this, "showApprovalForm", true)
|
||||
this.$set(this, "formData", {
|
||||
id: row.id,
|
||||
reviewOpinion: "通过"
|
||||
}
|
||||
this.$refs.unionReimburseInfoRef.onOpen(row)
|
||||
taskName: "校工会审核",
|
||||
reviewOpinion: "已付款成功"
|
||||
})
|
||||
// 先完成审批意见及插槽渲染,再打开详情,避免首次打开时表单尚未更新。
|
||||
this.$nextTick(() => {
|
||||
this.$refs.unionReimburseInfoRef.onOpen(row, "报销审核")
|
||||
})
|
||||
},
|
||||
|
||||
onLoadingChange(state) { this.$set(this, "listLoading", state.loading) },
|
||||
onNavBack() { const manager = window.h5HistoryLayerManager; if (manager && manager.stack.length) { manager.close(); return } historyBack() },
|
||||
onApprovalFilterChange(val) { this.$set(this.pageForm, "approval", val === "1"); this.doSearch() },
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$set(this.pageForm, "pageNumber", 1)
|
||||
this.$set(this.pageForm, "totalCount", 0)
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
}
|
||||
|
||||
},
|
||||
created() {
|
||||
|
||||
for (let i = new Date().getFullYear() - 10; i <= new Date().getFullYear(); i++) {
|
||||
this.yearList.unshift({value: i, text: i + "年"})
|
||||
}
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (manager) { manager.ensureRegistered("union-reimburse-review"); this.$set(this, "historyLayerUnsubscribe", manager.subscribe((layers) => { this.$set(this, "submitConfirmVisible", layers.includes("union-reimburse-review-confirm")) })) }
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.historyLayerUnsubscribe) this.historyLayerUnsubscribe()
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (manager) manager.unregister("union-reimburse-review")
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,245 +1,380 @@
|
||||
const PROPOSAL_INFO = {
|
||||
name: "ProposalInfo",
|
||||
template: /*language=HTML*/ `
|
||||
<van-action-sheet v-model="visible" title="查看详情">
|
||||
<div class="detail-container">
|
||||
<van-cell-group title="基本信息">
|
||||
<van-cell title="提案名称">
|
||||
<div style="font-weight:bold;">
|
||||
{{ viewData.name }}
|
||||
</div>
|
||||
</van-cell>
|
||||
<van-cell title="提案编号">{{ viewData.code }}</van-cell>
|
||||
<van-cell title="立案编号">{{ viewData.caseFilingCode || '暂无' }}</van-cell>
|
||||
<van-cell title="提案人">{{ viewData.createUserName }}</van-cell>
|
||||
<van-cell title="提案时间">{{ viewData.createTime }}</van-cell>
|
||||
<van-cell title="教代会届次">{{ viewData.fullName }}</van-cell>
|
||||
<van-cell title="提案人单位">{{ viewData.unitName }}</van-cell>
|
||||
<van-cell :title="viewData.mannerCode!=='W03'?'代表团名称':'委员会名称'">
|
||||
{{ viewData.mannerCode !== 'W03' ? viewData.delegationName : viewData.committeeName }}
|
||||
</van-cell>
|
||||
<van-cell title="提案类别">
|
||||
{{viewData.typeName}}
|
||||
</van-cell>
|
||||
<!--<van-cell title="建议承办单位">
|
||||
{{viewData.suggestUnits}}
|
||||
</van-cell>-->
|
||||
<van-cell title="立案结果">
|
||||
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_RESULT"
|
||||
:value="viewData.caseFilingResult"></dict-tag>
|
||||
</van-cell>
|
||||
<!--<van-cell title="调研情况" class="direction-column-cell">
|
||||
<div v-html="viewData.researchFindings"></div>
|
||||
</van-cell>-->
|
||||
<van-cell title="提案案由" class="direction-column-cell">
|
||||
<div v-html="viewData.brief"></div>
|
||||
</van-cell>
|
||||
<van-cell title="建议措施" class="direction-column-cell">
|
||||
<div v-html="viewData.measures"></div>
|
||||
</van-cell>
|
||||
<van-cell title="附件" class="direction-column-cell">
|
||||
<file-preview :files="viewData.files" complete_result></file-preview>
|
||||
</van-cell>
|
||||
<!-- <van-cell title="签字">-->
|
||||
<!-- <div slot="label">-->
|
||||
<!-- <van-image :src="viewData.signature"-->
|
||||
<!-- style="width: 100%;height: 150px;border: 1px dashed"></van-image>-->
|
||||
<!-- </div>-->
|
||||
<!-- </van-cell>-->
|
||||
</van-cell-group>
|
||||
|
||||
<!--并案信息-->
|
||||
<van-cell-group title="并案信息" v-if="viewData.merges && viewData.merges.length">
|
||||
<van-cell v-for="(merge, index) in viewData.merges" :key="merge.id"
|
||||
:title="(index + 1) + '. ' + merge.name"
|
||||
:label="'提案编号:' + merge.code + ' | 提案人:' + merge.createUserName + ' | 类别:' + merge.typeName + ' | 代表团:' + merge.delegationName"
|
||||
is-link
|
||||
@click="openView(merge)">
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
|
||||
<!--委员会成员意见-->
|
||||
<template v-if="viewData.commissionerOpinions && viewData.commissionerOpinions.length">
|
||||
<div class="process-title" style="margin-bottom: 0!important;">
|
||||
委员会成员意见
|
||||
</div>
|
||||
<div v-for="(opinion, index) in viewData.commissionerOpinions" :key="index"
|
||||
style="margin-bottom: 16px;">
|
||||
<van-cell :title="opinion.commissionerName + '(' + opinion.commissionerLoginName + ')'"
|
||||
class="direction-column-cell">
|
||||
<div class="proposal-info-content proposal-view-page">
|
||||
<main class="proposal-view-main">
|
||||
<!-- 编号和名称优先展示,便于手机端进入详情后快速确认当前提案。 -->
|
||||
<section class="proposal-view-card">
|
||||
<h2 class="proposal-view-card__title">提案内容</h2>
|
||||
<van-cell-group :border="false">
|
||||
<van-cell title="提案编号">{{ viewData.code || '--' }}</van-cell>
|
||||
<van-cell title="提案名称">{{ viewData.name || '--' }}</van-cell>
|
||||
<van-cell title="立案编号">{{ viewData.caseFilingCode || '暂无' }}</van-cell>
|
||||
<van-cell title="立案结果" v-if="viewData.caseFilingResult">
|
||||
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_RESULT"
|
||||
:value="viewData.caseFilingResult"></dict-tag>
|
||||
</van-cell>
|
||||
<van-cell title="立案结果">
|
||||
<div style="display: flex;justify-content: end;">
|
||||
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_RESULT"
|
||||
:value="opinion.caseFilingResult"></dict-tag>
|
||||
<template v-if="opinion.caseFilingType">
|
||||
(
|
||||
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_TYPE"
|
||||
:value="opinion.caseFilingType"></dict-tag>
|
||||
)
|
||||
</template>
|
||||
</div>
|
||||
<van-cell title="立案类型" v-if="viewData.caseFilingType">
|
||||
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_TYPE"
|
||||
:value="viewData.caseFilingType"></dict-tag>
|
||||
</van-cell>
|
||||
<van-cell title="意见" v-if="opinion.opinionText">
|
||||
<div>{{ opinion.opinionText }}</div>
|
||||
<van-cell title="提案类型">{{ viewData.typeName || '--' }}</van-cell>
|
||||
<van-cell title="提案方式">{{ getDictText(dict.type.PROPOSAL_SOURCE, viewData.source) }}
|
||||
</van-cell>
|
||||
<van-cell title="时间" v-if="opinion.opinionTime">
|
||||
{{ opinion.opinionTime }}
|
||||
<van-cell title="代表姓名">{{ viewData.createUserName || '--' }}</van-cell>
|
||||
<van-cell title="所属教代会">{{ viewData.sessionName || viewData.fullName || '--' }}</van-cell>
|
||||
<van-cell :title="viewData.committeeName ? '所属委员会' : '所属代表团'">
|
||||
{{ viewData.committeeName || viewData.delegationName || '--' }}
|
||||
</van-cell>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<template v-for="task in doneTasks">
|
||||
<van-cell-group :title="task.displayName" v-if="task.ext.isFirstTaskNode">
|
||||
<van-cell title="申请用户">{{ task.ext.initiatorName }}({{task.ext.initiatorAccount}})
|
||||
<van-cell title="单位">{{ viewData.unitName || '--' }}</van-cell>
|
||||
<van-cell title="联系电话">{{ viewData.mobile || '--' }}</van-cell>
|
||||
<van-cell title="提案时间">{{ viewData.createTime || '--' }}</van-cell>
|
||||
<van-cell title="案由" class="proposal-view-long-cell">
|
||||
<div class="proposal-view-rich-value" v-html="viewData.brief || '--'"></div>
|
||||
</van-cell>
|
||||
<van-cell title="申请时间">{{ task.finishTime }}</van-cell>
|
||||
<van-cell title="办理结果">
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
|
||||
:value="task.ext.submitType"></dict-tag>
|
||||
<van-cell title="建议措施" class="proposal-view-long-cell">
|
||||
<div class="proposal-view-rich-value" v-html="viewData.measures || '--'"></div>
|
||||
</van-cell>
|
||||
<van-cell title="附件" class="proposal-view-long-cell">
|
||||
<file-preview :files="viewData.files" complete_result></file-preview>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
|
||||
<!--邀请附议人-->
|
||||
<van-cell-group :title="task.displayName"
|
||||
v-else-if="task.taskName === 'invite'">
|
||||
<van-cell title="办理用户">{{ task.taskFormData.userName }}({{task.taskFormData.loginName}})
|
||||
</van-cell>
|
||||
<van-cell title="办理时间">{{ task.finishTime }}</van-cell>
|
||||
<van-cell title="附议人" v-if="task.taskName === 'invite'"
|
||||
class="direction-column-cell">
|
||||
<el-table :data="task?.taskFormData?.seconder">
|
||||
<el-table-column label="姓名" prop="userName"></el-table-column>
|
||||
<el-table-column label="工号" prop="loginName"></el-table-column>
|
||||
<el-table-column label="性别" prop="sex"></el-table-column>
|
||||
<el-table-column label="单位" prop="unitName" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="分工会" prop="unionName"
|
||||
show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="代表团" prop="delegationName"
|
||||
show-overflow-tooltip></el-table-column>
|
||||
</el-table>
|
||||
<!-- 并案信息仍支持点击切换当前公共详情组件的数据。 -->
|
||||
<section class="proposal-view-card" v-if="viewData.merges && viewData.merges.length">
|
||||
<h2 class="proposal-view-card__title">并案信息</h2>
|
||||
<van-cell-group :border="false">
|
||||
<van-cell v-for="(merge, index) in viewData.merges"
|
||||
:key="merge.id"
|
||||
class="proposal-view-merge-cell"
|
||||
:title="(index + 1) + '. ' + merge.name"
|
||||
:label="'提案编号:' + merge.code + '|提案人:' + merge.createUserName + '|类别:' + merge.typeName + '|代表团:' + merge.delegationName"
|
||||
is-link
|
||||
@click="openView(merge)">
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
|
||||
<!--提案委员会立案-->
|
||||
<van-cell-group :title="task.displayName"
|
||||
v-else-if="task.taskName === 'committee'||task.taskName === 'committeeFilingUnit'">
|
||||
<van-cell title="办理用户">{{ task.taskFormData.userName }}({{task.taskFormData.loginName}})
|
||||
</van-cell>
|
||||
<van-cell title="办理时间">{{ task.finishTime }}</van-cell>
|
||||
<van-cell title="立案结果">
|
||||
<div style="display: flex;justify-content: center">
|
||||
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_RESULT"
|
||||
:value="task.ext.tf_caseFilingResult"></dict-tag>
|
||||
|
||||
<template v-if="task.ext.tf_caseFilingType">
|
||||
(
|
||||
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_TYPE"
|
||||
:value="task.ext.tf_caseFilingType"></dict-tag>
|
||||
)
|
||||
</template>
|
||||
</div>
|
||||
</van-cell>
|
||||
<template v-if="['CONFIRM_FILING','SUGGESTION'].includes(task.ext.tf_caseFilingResult)">
|
||||
<van-cell v-if="task.ext.tf_caseFilingResult === 'SUGGESTION'" title="承办单位">{{ task?.ext?.tf_masterUnitNameStr || task?.ext?.tf_slaveUnitNameStr }}</van-cell>
|
||||
<template v-else>
|
||||
<van-cell title="主办单位">{{ task?.ext?.tf_masterUnitNameStr }}</van-cell>
|
||||
<van-cell title="协办单位">{{ task?.ext?.tf_slaveUnitNameStr }}</van-cell>
|
||||
<!-- 每位委员会成员意见独立成卡片,便于手机端逐块阅读。 -->
|
||||
<section class="proposal-view-card"
|
||||
v-for="(opinion, index) in viewData.commissionerOpinions || []"
|
||||
:key="'commissioner-' + index">
|
||||
<h2 class="proposal-view-card__title">委员会成员意见 {{ index + 1 }}</h2>
|
||||
<van-cell-group :border="false">
|
||||
<van-cell title="委员">
|
||||
{{ opinion.commissionerName || '--' }}
|
||||
<template v-if="opinion.commissionerLoginName">({{ opinion.commissionerLoginName }})
|
||||
</template>
|
||||
</van-cell>
|
||||
<van-cell title="立案结果">
|
||||
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_RESULT"
|
||||
:value="opinion.caseFilingResult"></dict-tag>
|
||||
</van-cell>
|
||||
<van-cell title="立案类型" v-if="opinion.caseFilingType">
|
||||
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_TYPE"
|
||||
:value="opinion.caseFilingType"></dict-tag>
|
||||
</van-cell>
|
||||
<van-cell title="意见" v-if="opinion.opinionText" class="proposal-view-long-cell">
|
||||
<div class="proposal-view-rich-value">{{ opinion.opinionText }}</div>
|
||||
</van-cell>
|
||||
<van-cell title="时间" v-if="opinion.opinionTime">{{ opinion.opinionTime }}</van-cell>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
|
||||
<!-- 已办 WF 任务压缩为横向时间轴,节点仅展示名称和办理人。 -->
|
||||
<section class="proposal-view-card proposal-flow-card" v-if="doneTasks && doneTasks.length">
|
||||
<div class="proposal-flow-card__header">
|
||||
<h2 class="proposal-view-card__title">审批流程</h2>
|
||||
<span class="proposal-flow-card__hint">
|
||||
左右滑动查看
|
||||
<van-icon name="exchange"></van-icon>
|
||||
</span>
|
||||
</div>
|
||||
<div class="proposal-flow-scroll" ref="workflowScroll">
|
||||
<div class="proposal-flow-track">
|
||||
<button type="button"
|
||||
ref="workflowNode"
|
||||
class="proposal-flow-node"
|
||||
:class="{'is-active': selectedTask && selectedTask.id === task.id}"
|
||||
v-for="(task, index) in doneTasks"
|
||||
:key="task.id"
|
||||
@click="selectTask(task)">
|
||||
<span class="proposal-flow-node__icon">
|
||||
<van-icon :name="getTaskNodeIcon(task, index)"></van-icon>
|
||||
</span>
|
||||
<span class="proposal-flow-node__title">{{ task.displayName || '--' }}</span>
|
||||
<span class="proposal-flow-node__handler">{{ getTaskHandlerName(task) }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 点击时间轴节点后,只在此处展示该任务原有的完整详情。 -->
|
||||
<section class="proposal-view-card proposal-flow-detail" v-if="selectedTask">
|
||||
<h2 class="proposal-view-card__title">{{ selectedTask.displayName || '--' }}</h2>
|
||||
<van-cell-group :border="false">
|
||||
<template v-if="selectedTask.ext && selectedTask.ext.isFirstTaskNode">
|
||||
<van-cell title="申请用户">
|
||||
{{ selectedTask.ext.initiatorName || '--' }}({{ selectedTask.ext.initiatorAccount ||
|
||||
'--' }})
|
||||
</van-cell>
|
||||
<van-cell title="申请时间">{{ selectedTask.finishTime || '--' }}</van-cell>
|
||||
<van-cell title="办理结果">
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
|
||||
:value="selectedTask.ext.submitType"></dict-tag>
|
||||
</van-cell>
|
||||
</template>
|
||||
|
||||
<template v-else-if="selectedTask.taskName === 'invite'">
|
||||
<van-cell title="办理用户">
|
||||
{{ selectedTask.taskFormData.userName || '--' }}({{ selectedTask.taskFormData.loginName
|
||||
|| '--' }})
|
||||
</van-cell>
|
||||
<van-cell title="办理时间">{{ selectedTask.finishTime || '--' }}</van-cell>
|
||||
<van-cell title="附议人" class="proposal-view-long-cell">
|
||||
<div class="proposal-view-table-wrap">
|
||||
<el-table :data="selectedTask?.taskFormData?.seconder">
|
||||
<el-table-column label="姓名" prop="userName" width="80px"
|
||||
header-align="center" align="center"></el-table-column>
|
||||
<el-table-column label="工号" prop="loginName" width="80px"
|
||||
header-align="center" align="center"></el-table-column>
|
||||
<el-table-column label="性别" prop="sex" width="50px" header-align="center"
|
||||
align="center"></el-table-column>
|
||||
<el-table-column label="单位" prop="unitName"
|
||||
show-overflow-tooltip header-align="center"
|
||||
align="center"></el-table-column>
|
||||
<el-table-column label="代表团" prop="delegationName"
|
||||
show-overflow-tooltip header-align="center"
|
||||
align="center"></el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</van-cell>
|
||||
</template>
|
||||
|
||||
<template
|
||||
v-else-if="selectedTask.taskName === 'committee' || selectedTask.taskName === 'committeeFilingUnit'">
|
||||
<van-cell title="办理用户">
|
||||
{{ selectedTask.taskFormData.userName || '--' }}({{ selectedTask.taskFormData.loginName
|
||||
|| '--' }})
|
||||
</van-cell>
|
||||
<van-cell title="办理时间">{{ selectedTask.finishTime || '--' }}</van-cell>
|
||||
<van-cell title="立案结果">
|
||||
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_RESULT"
|
||||
:value="selectedTask.ext.tf_caseFilingResult"></dict-tag>
|
||||
</van-cell>
|
||||
<van-cell title="立案类型" v-if="selectedTask.ext.tf_caseFilingType">
|
||||
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_TYPE"
|
||||
:value="selectedTask.ext.tf_caseFilingType"></dict-tag>
|
||||
</van-cell>
|
||||
<template
|
||||
v-if="['CONFIRM_FILING', 'SUGGESTION'].includes(selectedTask.ext.tf_caseFilingResult)">
|
||||
<van-cell v-if="selectedTask.ext.tf_caseFilingResult === 'SUGGESTION'" title="承办单位">
|
||||
{{ selectedTask?.ext?.tf_masterUnitNameStr || selectedTask?.ext?.tf_slaveUnitNameStr
|
||||
|| '--' }}
|
||||
</van-cell>
|
||||
<template v-else>
|
||||
<van-cell title="主办单位">{{ selectedTask?.ext?.tf_masterUnitNameStr || '--' }}
|
||||
</van-cell>
|
||||
<van-cell title="协办单位">{{ selectedTask?.ext?.tf_slaveUnitNameStr || '--' }}
|
||||
</van-cell>
|
||||
</template>
|
||||
</template>
|
||||
<van-cell title="办理意见"
|
||||
v-if="selectedTask.taskFormData.tf_opinion">
|
||||
<div class="proposal-view-rich-value"
|
||||
v-html="selectedTask.taskFormData.tf_opinion"></div>
|
||||
</van-cell>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<van-cell title="办理单位"
|
||||
v-if="['opinion_unit_reply', 'unit_reply', 'two_unit_reply', 'master_reply', 'slave_reply'].includes(selectedTask.taskName)">
|
||||
{{ selectedTask.ext.underTakeName || '--' }}
|
||||
</van-cell>
|
||||
<van-cell title="办理用户">
|
||||
{{ selectedTask.taskFormData.userName || '--' }}({{ selectedTask.taskFormData.loginName
|
||||
|| '--' }})
|
||||
</van-cell>
|
||||
<van-cell title="办理时间">{{ selectedTask.finishTime || '--' }}</van-cell>
|
||||
<van-cell title="办理评价" v-if="selectedTask.taskName === 'feedback'">
|
||||
<dict-tag :options="dict.type.PROPOSAL_FEEDBACK"
|
||||
:value="selectedTask.ext.tf_feedback"></dict-tag>
|
||||
</van-cell>
|
||||
<van-cell title="办理结果" v-else>
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
|
||||
:value="selectedTask.ext.submitType"></dict-tag>
|
||||
</van-cell>
|
||||
<van-cell title="办理意见"
|
||||
v-if="selectedTask.taskFormData && selectedTask.taskFormData.tf_opinion">
|
||||
<div class="proposal-view-rich-value"
|
||||
v-html="selectedTask.taskFormData.tf_opinion"></div>
|
||||
</van-cell>
|
||||
</template>
|
||||
<van-cell title="办理意见" v-if="task.taskFormData.tf_opinion" class="direction-column-cell">
|
||||
<div v-html="task.taskFormData.tf_opinion"></div>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
<div class="proposal-flow-detail__tip">点击其他节点查看详情</div>
|
||||
</section>
|
||||
|
||||
<van-cell-group :title="task.displayName" v-else>
|
||||
<van-cell title="办理单位" v-if="['opinion_unit_reply','unit_reply','two_unit_reply','master_reply','slave_reply'].includes(task.taskName)">
|
||||
{{task.ext.underTakeName}}
|
||||
</van-cell>
|
||||
|
||||
<van-cell title="办理用户">{{ task.taskFormData.userName }}({{task.taskFormData.loginName}})
|
||||
</van-cell>
|
||||
<van-cell title="办理时间">{{ task.finishTime }}</van-cell>
|
||||
|
||||
<van-cell title="办理评价" v-if="['feedback'].includes(task.taskName)">
|
||||
<dict-tag :options="dict.type.PROPOSAL_FEEDBACK"
|
||||
:value="task.ext.tf_feedback"></dict-tag>
|
||||
</van-cell>
|
||||
<van-cell title="办理结果" v-else>
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
|
||||
:value="task.ext.submitType"></dict-tag>
|
||||
</van-cell>
|
||||
<van-cell title="办理意见" v-if="!task.ext.isFirstTaskNode" class="direction-column-cell">
|
||||
<div v-html="task.taskFormData.tf_opinion"></div>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<slot></slot>
|
||||
</van-action-sheet>
|
||||
<!-- 审批、答复等业务页面继续通过原插槽追加表单。 -->
|
||||
<div class="proposal-view-slot">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
`,
|
||||
dicts: ["PROPOSAL_TYPE", "PROPOSAL_CASE_FILING_RESULT", "PROPOSAL_CASE_FILING_TYPE", "PROCESS_TASK_SUBMIT_TYPE", "PROPOSAL_FEEDBACK"],
|
||||
props: {
|
||||
// bizId 为提案主键;组件根据该参数加载提案详情和对应的已办流程记录。
|
||||
bizId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
// visible 表示承载详情的 Popup 是否打开;每次重新打开时都需要查询最新详情和流程记录。
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
dicts: ["PROPOSAL_TYPE", "PROPOSAL_SOURCE", "PROPOSAL_CASE_FILING_RESULT", "PROPOSAL_CASE_FILING_TYPE", "PROCESS_TASK_SUBMIT_TYPE", "PROPOSAL_FEEDBACK"],
|
||||
data() {
|
||||
return {
|
||||
visible:false,
|
||||
viewData: {},
|
||||
doneTasks: [],
|
||||
row: null,
|
||||
originalRow: null, // 用于保存原始数据,支持返回功能
|
||||
selectedTask: null,
|
||||
currentBizId: "",
|
||||
reloadPending: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
bizId: {
|
||||
immediate: true,
|
||||
handler(value) {
|
||||
if (!value) return
|
||||
this.$set(this, "currentBizId", value)
|
||||
if (this.visible) this.queueReload()
|
||||
}
|
||||
},
|
||||
visible(value) {
|
||||
if (!value || !this.bizId) return
|
||||
this.$set(this, "currentBizId", this.bizId)
|
||||
this.queueReload()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 打开
|
||||
onOpen(row) {
|
||||
this.row = row
|
||||
this.visible = true
|
||||
this.getInfo()
|
||||
this.getDoneTasks()
|
||||
/**
|
||||
* 合并同一轮 bizId 与 Popup 显示状态变化触发的刷新。
|
||||
* 无参数;组件可见且存在提案主键时调用详情和已办流程接口,无返回值。
|
||||
*/
|
||||
queueReload() {
|
||||
if (this.reloadPending) return
|
||||
this.$set(this, "reloadPending", true)
|
||||
this.$nextTick(() => {
|
||||
this.$set(this, "reloadPending", false)
|
||||
if (!this.visible || !this.currentBizId) return
|
||||
this.resetScrollPosition()
|
||||
this.getInfo()
|
||||
this.getDoneTasks()
|
||||
})
|
||||
},
|
||||
|
||||
// 关闭
|
||||
onClose(){
|
||||
this.visible = false
|
||||
/**
|
||||
* 重置提案详情的纵向滚动位置。
|
||||
* 无参数;查找组件所在的 proposal-full-popup__scroll 容器并滚动到顶部,无匹配容器时安全跳过。
|
||||
*/
|
||||
resetScrollPosition() {
|
||||
const componentRoot = this.$el
|
||||
const scrollContainer = componentRoot && componentRoot.closest
|
||||
? componentRoot.closest(".proposal-full-popup__scroll")
|
||||
: null
|
||||
if (scrollContainer) scrollContainer.scrollTop = 0
|
||||
},
|
||||
|
||||
// 获取申请信息
|
||||
/**
|
||||
* 获取字典字段的展示文本。
|
||||
* options 为 PROPOSAL_SOURCE 等字典数组,value 为业务保存的字典 code;返回名称字符串,无匹配项时返回原值或 --。
|
||||
*/
|
||||
getDictText(options, value) {
|
||||
const option = (options || []).find((item) => String(item.code) === String(value))
|
||||
return option ? (option.name || option.label || value) : (value || "--")
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取横向流程节点的办理人名称。
|
||||
* task 为 doneTasks 接口返回的任务对象;发起节点读取 initiatorName,其他节点读取 taskFormData.userName,返回字符串。
|
||||
*/
|
||||
getTaskHandlerName(task) {
|
||||
if (!task) return "--"
|
||||
if (task.ext && task.ext.isFirstTaskNode) {
|
||||
return task.ext.initiatorName || "--"
|
||||
}
|
||||
return task.taskFormData && task.taskFormData.userName
|
||||
? task.taskFormData.userName
|
||||
: "--"
|
||||
},
|
||||
|
||||
/**
|
||||
* 根据任务类型返回 Vant 图标名称,只用于区分发起、邀请附议和普通已办节点。
|
||||
*/
|
||||
getTaskNodeIcon(task) {
|
||||
if (task && task.ext && task.ext.isFirstTaskNode) return "manager-o"
|
||||
if (task && task.taskName === "invite") return "friends-o"
|
||||
return "passed"
|
||||
},
|
||||
|
||||
/**
|
||||
* 选中流程节点并展示详情。
|
||||
* task 为 doneTasks 中的任务对象;该方法无返回值,并把对应节点滚动到横向区域中部。
|
||||
*/
|
||||
selectTask(task) {
|
||||
if (!task) return
|
||||
this.$set(this, "selectedTask", task)
|
||||
this.scrollTaskIntoView(task.id)
|
||||
},
|
||||
|
||||
/**
|
||||
* 将指定任务节点滚动至时间轴可视区域中部。
|
||||
* taskId 为流程任务主键;节点或滚动容器不存在时直接结束,无返回值。
|
||||
*/
|
||||
scrollTaskIntoView(taskId) {
|
||||
this.$nextTick(() => {
|
||||
const nodes = this.$refs.workflowNode
|
||||
const nodeList = Array.isArray(nodes) ? nodes : [nodes]
|
||||
const taskIndex = this.doneTasks.findIndex((item) => String(item.id) === String(taskId))
|
||||
const node = nodeList[taskIndex]
|
||||
const scrollContainer = this.$refs.workflowScroll
|
||||
if (!node || !scrollContainer) return
|
||||
const targetLeft = node.offsetLeft - (scrollContainer.clientWidth - node.offsetWidth) / 2
|
||||
scrollContainer.scrollLeft = Math.max(0, targetLeft)
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 使用 currentBizId 查询提案详情。
|
||||
* 接口参数 id 为提案主键;成功响应的 data 为详情对象并写入 viewData。
|
||||
*/
|
||||
getInfo() {
|
||||
this.$axios.post("/platform/proposal/common/proposalInfo", {id: this.row.id}).then((res) => {
|
||||
this.$axios.post("/platform/proposal/common/proposalInfo", {id: this.currentBizId}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.viewData = res.data
|
||||
this.$set(this, "viewData", res.data)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 查看提案
|
||||
openView(row) {
|
||||
// 如果传入的是并案对象,则打开新的详情页面
|
||||
if (row && typeof row === 'object' && row.id) {
|
||||
// 创建一个新的提案详情组件实例来显示并案详情
|
||||
this.$nextTick(() => {
|
||||
// 可以通过事件总线或者其他方式来打开新的详情页面
|
||||
// 这里暂时使用简单的方式,直接在当前组件中显示
|
||||
const currentRow = this.row;
|
||||
this.row = row;
|
||||
this.getInfo();
|
||||
// 保存原来的数据,以便返回时恢复
|
||||
this.originalRow = currentRow;
|
||||
})
|
||||
} else {
|
||||
// 原有的逻辑,通过ID查看
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.infoDialogRef) {
|
||||
this.$refs.infoDialogRef.onOpen(row)
|
||||
}
|
||||
})
|
||||
this.$set(this, "currentBizId", row.id)
|
||||
this.queueReload()
|
||||
}
|
||||
},
|
||||
|
||||
// 获取已办任务审批记录
|
||||
/**
|
||||
* 使用 currentBizId 查询已办流程记录。
|
||||
* 接口参数 bizId 为提案主键;成功响应的 data 为流程任务数组并写入 doneTasks。
|
||||
*/
|
||||
getDoneTasks() {
|
||||
this.$axios.post("/flow/common/doneTasks", {bizId: this.row.id}).then((res) => {
|
||||
this.$set(this, "doneTasks", [])
|
||||
this.$set(this, "selectedTask", null)
|
||||
this.$axios.post("/flow/common/doneTasks", {bizId: this.currentBizId}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const tasks = res.data || []
|
||||
// 按提案业务流程展示历史记录,避免迁移或并行任务受数据库写入顺序影响。
|
||||
@@ -270,7 +405,14 @@ const PROPOSAL_INFO = {
|
||||
}
|
||||
return first.id - second.id
|
||||
})
|
||||
this.$set(this, "doneTasks", tasks)
|
||||
|
||||
const taskList = tasks
|
||||
const latestTask = taskList.length ? taskList[taskList.length - 1] : null
|
||||
this.$set(this, "doneTasks", taskList)
|
||||
this.$set(this, "selectedTask", latestTask)
|
||||
if (latestTask) {
|
||||
this.scrollTaskIntoView(latestTask.id)
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
+54
-20
@@ -1,8 +1,11 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<style>
|
||||
<!--#include("../../common/info.css"){}#-->
|
||||
</style>
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="提案查询" placeholder fixed></van-nav-bar>
|
||||
<van-nav-bar @click-left="handlePageBack" left-arrow left-text="返回" title="提案查询" placeholder fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<van-search
|
||||
v-model="pageForm.name"
|
||||
@@ -23,7 +26,7 @@ layout("/layouts/platform_h5.html"){
|
||||
<!-- <van-dropdown-item-->
|
||||
<!-- v-model="pageForm.unionId"-->
|
||||
<!-- :options="unionOptions"-->
|
||||
<!-- @change="pageForm.unitId=null;listUnit();doSearch()"-->
|
||||
<!-- @change="$set(pageForm, 'unitId', null);listUnit();doSearch()"-->
|
||||
<!-- ></van-dropdown-item>-->
|
||||
<!-- <van-dropdown-item v-model="pageForm.unitId" :options="unitOptions" @change="doSearch"></van-dropdown-item>-->
|
||||
<!-- <van-dropdown-item v-model="pageForm.undertakeUnitId" :options="underTakeOptions" @change="doSearch"></van-dropdown-item>-->
|
||||
@@ -49,7 +52,9 @@ layout("/layouts/platform_h5.html"){
|
||||
<van-cell title="代表团" :value="row.delegationName"></van-cell>
|
||||
<van-cell title="当前节点" :value="row.processInstanceNodeName"></van-cell>
|
||||
<van-cell class="table-card-footer">
|
||||
<van-button size="small" @click="openView(row)">查看</van-button>
|
||||
<van-button size="small" @click="openView(row)">
|
||||
<van-icon class="proposal-action-icon" name="eye-o"></van-icon>查看
|
||||
</van-button>
|
||||
</van-cell>
|
||||
</div>
|
||||
</div>
|
||||
@@ -57,20 +62,26 @@ layout("/layouts/platform_h5.html"){
|
||||
<van-empty v-else image="/assets/platform/plugins/vant-green/images/nodata/nodata.png" description="暂无数据"></van-empty>
|
||||
</div>
|
||||
|
||||
<van-popup :style="{ height: '100%', width: '100%' }" position="right" safe-area-inset-bottom v-model="infoShow">
|
||||
<van-sticky>
|
||||
<van-nav-bar @click-left="infoShow=false" left-arrow left-text="返回" title="提案信息"></van-nav-bar>
|
||||
</van-sticky>
|
||||
<div style="height: calc(100vh - 44px); overflow-y: auto">
|
||||
<info ref="infoRef"></info>
|
||||
<van-popup v-model="detailVisible" class="proposal-full-popup" position="right"
|
||||
:close-on-click-overlay="false" safe-area-inset-bottom>
|
||||
<div class="proposal-full-popup__page">
|
||||
<van-nav-bar title="提案信息" left-arrow left-text="返回" fixed
|
||||
@click-left="closeHistoryLayer('detail')"></van-nav-bar>
|
||||
<div class="proposal-full-popup__scroll">
|
||||
<proposal-info v-if="detailVisible && detailBizId" :biz-id="detailBizId" :visible="detailVisible"></proposal-info>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
|
||||
</div>
|
||||
<script nonce="${cspNonce!}">
|
||||
<!--#include("../../common/info.js"){}#-->
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
components: {
|
||||
"proposal-info": PROPOSAL_INFO
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageForm: {
|
||||
@@ -99,14 +110,33 @@ layout("/layouts/platform_h5.html"){
|
||||
moreOptions: {},
|
||||
id: "",
|
||||
formValidSuccess: false,
|
||||
infoShow: false
|
||||
detailVisible: false,
|
||||
detailBizId: "",
|
||||
historyLayerPageKey: "proposal-query-comprehensive-h5"
|
||||
}
|
||||
},
|
||||
components: {
|
||||
info: H5_PROPOSAL_INFO_COMPONENT
|
||||
},
|
||||
methods: {
|
||||
historyBack,
|
||||
registerHistoryLayers() {
|
||||
if (!window.h5HistoryLayerManager) return
|
||||
window.h5HistoryLayerManager.register(this.historyLayerPageKey, (stack) => {
|
||||
this.$set(this, "detailVisible", stack.includes("detail"))
|
||||
})
|
||||
},
|
||||
openHistoryLayer(layerName) {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open(layerName)) return
|
||||
if (layerName === "detail") this.$set(this, "detailVisible", true)
|
||||
},
|
||||
closeHistoryLayer(layerName) {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.close(layerName)) return
|
||||
if (layerName === "detail") this.$set(this, "detailVisible", false)
|
||||
},
|
||||
handlePageBack() {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.stack.length) {
|
||||
window.h5HistoryLayerManager.close()
|
||||
return
|
||||
}
|
||||
historyBack()
|
||||
},
|
||||
sessionChange(val) {
|
||||
this.pageForm.delegationId = null
|
||||
if (this.pageForm.sessionId) {
|
||||
@@ -161,10 +191,8 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
|
||||
openView(row) {
|
||||
this.infoShow = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.infoRef.onOpen(row.id)
|
||||
})
|
||||
this.$set(this, "detailBizId", row.id)
|
||||
this.openHistoryLayer("detail")
|
||||
},
|
||||
|
||||
pageData() {
|
||||
@@ -181,8 +209,8 @@ layout("/layouts/platform_h5.html"){
|
||||
} else {
|
||||
this.pageForm.pageNumber++
|
||||
}
|
||||
this.tableLoading = false
|
||||
})
|
||||
|
||||
}).finally(() => { this.$set(this, "tableLoading", false) })
|
||||
},
|
||||
doSearch() {
|
||||
this.pageForm.pageNumber = 1
|
||||
@@ -192,8 +220,14 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.registerHistoryLayers()
|
||||
this.pageData()
|
||||
this.listSession()
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (window.h5HistoryLayerManager) {
|
||||
window.h5HistoryLayerManager.unregister(this.historyLayerPageKey)
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
+212
-121
@@ -1,29 +1,71 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<style>
|
||||
body { background-color: #f3f7fd; }
|
||||
.proposal-commissioner-page { min-height: 100vh; padding-bottom: calc(24px + env(safe-area-inset-bottom)); box-sizing: border-box; background-color: #f3f7fd; }
|
||||
.proposal-commissioner-page .van-nav-bar { background-color: #fff; }
|
||||
.proposal-commissioner-page .van-nav-bar__title { color: #172033; font-size: 16px; font-weight: 600; }
|
||||
.proposal-commissioner-page .van-nav-bar .van-icon, .proposal-commissioner-page .van-nav-bar__text { color: #1989fa; }
|
||||
.proposal-commissioner-content { padding: 0 12px; }
|
||||
.proposal-commissioner-sticky { padding: 22px 12px 1px; box-sizing: border-box; background-color: #f3f7fd; }
|
||||
.proposal-commissioner-search { margin: 0 0 8px; padding: 0; overflow: hidden; border-radius: 12px; background-color: #fff; box-shadow: 0 5px 16px rgba(43, 73, 112, .1); }
|
||||
.proposal-commissioner-search .van-search__content { height: 42px; padding-left: 12px; align-items: center; border-radius: 12px; background-color: #fff; }
|
||||
.proposal-commissioner-search .van-field__control { color: #263548; font-size: 14px; }
|
||||
.proposal-commissioner-search .van-field__control::placeholder { color: #a7b0bf; }
|
||||
.proposal-commissioner-filter { margin: 0 0 10px; overflow: hidden; border-radius: 10px; box-shadow: 0 5px 16px rgba(43, 73, 112, .08); transition: border-radius .18s ease; }
|
||||
.proposal-commissioner-filter.is-open { border-radius: 10px 10px 0 0; }
|
||||
.proposal-commissioner-filter .van-dropdown-menu__bar, .proposal-commissioner-filter .van-dropdown-menu__item, .proposal-commissioner-filter .van-dropdown-menu__title { height: 44px; }
|
||||
.proposal-commissioner-filter .van-dropdown-menu__bar { box-shadow: none; }
|
||||
.proposal-commissioner-filter .van-dropdown-menu__item, .proposal-commissioner-filter .van-dropdown-menu__title { align-items: center; }
|
||||
.proposal-commissioner-filter .van-dropdown-menu__item { justify-content: center; }
|
||||
.proposal-commissioner-filter .van-dropdown-menu__title { display: inline-flex; color: #66758a; font-size: 14px; line-height: 20px; }
|
||||
.proposal-commissioner-filter .van-dropdown-menu__title--active, .proposal-commissioner-filter .van-dropdown-item__option--active, .proposal-commissioner-filter .van-dropdown-item__option--active .van-dropdown-item__icon { color: #1989fa; }
|
||||
.proposal-commissioner-filter .van-dropdown-menu__title--down::after { border-color: transparent transparent #1989fa #1989fa; }
|
||||
.proposal-commissioner-filter .van-dropdown-item__content { width: calc(100% - 24px); margin: 0 12px; overflow: hidden; box-sizing: border-box; border-radius: 0 0 12px 12px; box-shadow: 0 10px 24px rgba(31, 65, 108, .14); }
|
||||
.proposal-commissioner-filter .van-dropdown-item__option { display: flex; min-height: 48px; padding: 0 16px; align-items: center; color: #46566c; font-size: 14px; }
|
||||
.proposal-commissioner-filter .van-cell::after { right: 16px; left: 16px; }
|
||||
.proposal-commissioner-list .empty-state { display: none; }
|
||||
.proposal-commissioner-empty { display: flex; min-height: 280px; padding: 46px 18px 36px; align-items: center; justify-content: center; flex-direction: column; box-sizing: border-box; text-align: center; }
|
||||
.proposal-commissioner-empty img { display: block; width: 86%; max-width: 290px; height: auto; object-fit: contain; }
|
||||
.proposal-commissioner-empty__title { margin-top: 14px; color: #50627a; font-size: 15px; line-height: 22px; font-weight: 600; }
|
||||
.proposal-commissioner-empty__hint { margin-top: 5px; color: #9aa7b8; font-size: 12px; line-height: 18px; }
|
||||
@media (max-width: 350px) { .proposal-commissioner-content, .proposal-commissioner-sticky { padding-right: 10px; padding-left: 10px; } }
|
||||
</style>
|
||||
<style id="style-proposal-commissioner-h5">
|
||||
<!--#include("../../common/info.css"){}#-->
|
||||
<!--#include("../theme.css"){}#-->
|
||||
</style>
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="委员会成员意见" placeholder
|
||||
<div class="proposal-commissioner-page">
|
||||
<van-nav-bar @click-left="handlePageBack" left-arrow left-text="返回" title="委员会成员意见" placeholder
|
||||
fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<div class="proposal-commissioner-sticky">
|
||||
<van-search
|
||||
v-model="pageForm.name"
|
||||
class="proposal-commissioner-search"
|
||||
:show-action="false"
|
||||
:reverse-color="false"
|
||||
input-align="left"
|
||||
placeholder="请输入提案名称搜索"
|
||||
shape="round"
|
||||
clearable
|
||||
@search="doSearch"
|
||||
@clear="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-menu class="proposal-commissioner-filter" :class="{'is-open': filterOpened}" active-color="#1989fa" :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions" :multiple="false"
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
@change="doSearch" @open="setFilterOpened(true)" @close="setFilterOpened(false)"></van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.approvalText" :options="approvalOptions" :multiple="false"
|
||||
@change="approvalChange" @open="setFilterOpened(true)" @close="setFilterOpened(false)"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<main class="proposal-commissioner-content"><div class="proposal-commissioner-list">
|
||||
<!-- 列表无记录时展示与团长审核一致的提案专用空状态。 -->
|
||||
<div v-if="pageForm.totalCount === 0" class="proposal-commissioner-empty"><img src="/assets/mobile/img/proposal/proposal-empty.png" alt="暂无提案记录插画"><div class="proposal-commissioner-empty__title">暂无提案记录</div><div class="proposal-commissioner-empty__hint">当前筛选条件下暂时没有提案</div></div>
|
||||
<table-list api="/platform/proposal/commissioner/pageData" :page_form.sync="pageForm" @ready="onReady"
|
||||
ref="tableListRef"
|
||||
title="name">
|
||||
@@ -41,86 +83,83 @@ layout("/layouts/platform_h5.html"){
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<van-icon class="proposal-action-icon" name="eye-o"></van-icon>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="!row.pcoId" @click="onApproval(row)">
|
||||
<i class="fa fa-edit"></i>
|
||||
<van-icon class="proposal-action-icon" name="edit"></van-icon>
|
||||
<span>审核</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
</div></main>
|
||||
|
||||
<proposal-info ref="proposalInfoRef">
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">提案委员会成员意见</div>
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
v-model="formData.caseFilingResultName"
|
||||
name="caseFilingResultName"
|
||||
label="立案结果"
|
||||
placeholder="请选择立案结果"
|
||||
:rules="[{ required: true, message: '请选择立案结果' }]"
|
||||
required
|
||||
is-link
|
||||
@click="showCaseFilingResultPicker = true"
|
||||
></van-field>
|
||||
<van-popup v-model="showCaseFilingResultPicker" position="bottom">
|
||||
<van-picker
|
||||
show-toolbar
|
||||
:columns="dict.type.PROPOSAL_CASE_FILING_RESULT.map(item => ({text: item.label, value: item.code}))"
|
||||
@confirm="onCaseFilingResultConfirm"
|
||||
@cancel="showCaseFilingResultPicker = false"
|
||||
></van-picker>
|
||||
</van-popup>
|
||||
|
||||
<template v-if="['CONFIRM_FILING'].includes(formData.caseFilingResult)">
|
||||
<van-field
|
||||
v-model="formData.caseFilingTypeName"
|
||||
name="caseFilingTypeName"
|
||||
label="立案结果"
|
||||
placeholder="请选择立案类型"
|
||||
:rules="[{ required: true, message: '请选择立案类型' }]"
|
||||
required
|
||||
is-link
|
||||
@click="showCaseFilingTypePicker = true"
|
||||
></van-field>
|
||||
<van-popup v-model="showCaseFilingTypePicker" position="bottom">
|
||||
<van-picker
|
||||
show-toolbar
|
||||
:columns="dict.type.PROPOSAL_CASE_FILING_TYPE.map(item => ({text: item.label, value: item.code}))"
|
||||
@confirm="onCaseFilingTypeConfirm"
|
||||
@cancel="showCaseFilingTypePicker = false"
|
||||
></van-picker>
|
||||
</van-popup>
|
||||
</template>
|
||||
|
||||
<van-field
|
||||
v-model="formData.opinion"
|
||||
name="opinion"
|
||||
label="审批意见"
|
||||
placeholder="请输入审批意见"
|
||||
:rules="[{ required: true, message: '请填写审批意见' }]"
|
||||
required
|
||||
maxlength="100"
|
||||
show-word-limit
|
||||
></van-field>
|
||||
</van-form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button block @click="$refs.proposalInfoRef.onClose()">取消</van-button>
|
||||
<van-button type="primary" block @click="doSubmit">提交</van-button>
|
||||
<van-popup v-model="detailVisible" class="proposal-full-popup" position="right"
|
||||
:close-on-click-overlay="false" safe-area-inset-bottom>
|
||||
<div class="proposal-full-popup__page">
|
||||
<van-nav-bar :title="popupTitle" left-arrow left-text="返回" fixed
|
||||
@click-left="closeHistoryLayer('detail')"></van-nav-bar>
|
||||
<div class="proposal-full-popup__scroll">
|
||||
<proposal-info v-if="detailVisible && detailBizId" :biz-id="detailBizId" :visible="detailVisible">
|
||||
<div v-if="isApproval">
|
||||
<van-form ref="formRef">
|
||||
<van-field v-model="formData.caseFilingResultName" name="caseFilingResultName"
|
||||
label="立案结果" placeholder="请选择立案结果" readonly required is-link
|
||||
:rules="[{ required: true, message: '请选择立案结果' }]"
|
||||
@click="openHistoryLayer('result-picker')"></van-field>
|
||||
<template v-if="formData.caseFilingResult === 'CONFIRM_FILING'">
|
||||
<van-field v-model="formData.caseFilingTypeName" name="caseFilingTypeName"
|
||||
label="立案类型" placeholder="请选择立案类型" readonly required is-link
|
||||
:rules="[{ required: true, message: '请选择立案类型' }]"
|
||||
@click="openHistoryLayer('type-picker')"></van-field>
|
||||
</template>
|
||||
<section class="proposal-view-card">
|
||||
<h2 class="proposal-view-card__title">
|
||||
审批意见
|
||||
<span class="proposal-audit-card__required">*</span>
|
||||
</h2>
|
||||
<van-field v-model="formData.opinion" class="proposal-audit-field" name="opinion"
|
||||
type="textarea" rows="6" label="" placeholder="请输入审批意见"
|
||||
required maxlength="100" show-word-limit
|
||||
:rules="[{ required: true, message: '请填写审批意见' }]"></van-field>
|
||||
</section>
|
||||
</van-form>
|
||||
<div class="proposal-popup-form-actions">
|
||||
<van-button block :disabled="formLoading" @click="closeHistoryLayer('detail')">取消</van-button>
|
||||
<van-button type="primary" block :loading="formLoading" class="proposal-soft-button" @click="submitApproval">提交</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</proposal-info>
|
||||
</div>
|
||||
</div>
|
||||
</proposal-info>
|
||||
</van-popup>
|
||||
|
||||
<van-popup v-model="showCaseFilingResultPicker" position="bottom" :close-on-click-overlay="false">
|
||||
<van-picker show-toolbar
|
||||
:columns="dict.type.PROPOSAL_CASE_FILING_RESULT.map(item => ({text: item.label, value: item.code}))"
|
||||
@confirm="onCaseFilingResultConfirm"
|
||||
@cancel="closeHistoryLayer('result-picker')"></van-picker>
|
||||
</van-popup>
|
||||
<van-popup v-model="showCaseFilingTypePicker" position="bottom" :close-on-click-overlay="false">
|
||||
<van-picker show-toolbar
|
||||
:columns="dict.type.PROPOSAL_CASE_FILING_TYPE.map(item => ({text: item.label, value: item.code}))"
|
||||
@confirm="onCaseFilingTypeConfirm"
|
||||
@cancel="closeHistoryLayer('type-picker')"></van-picker>
|
||||
</van-popup>
|
||||
<van-dialog :value="submitConfirmVisible" title="提示" message="您确定要提交吗?" show-cancel-button
|
||||
@confirm="confirmApproval" @cancel="closeHistoryLayer('submit-confirm')"></van-dialog>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<script nonce="${cspNonce!}">
|
||||
<!--#include("../../common/info.js"){}#-->
|
||||
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
dicts: ["PROPOSAL_CASE_FILING_RESULT", "PROPOSAL_CASE_FILING_TYPE"],
|
||||
components: {
|
||||
"proposal-info": PROPOSAL_INFO
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageForm: {
|
||||
@@ -134,87 +173,133 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
|
||||
sessionOptions: [],
|
||||
filterOpened: false,
|
||||
approvalOptions: [
|
||||
{text: "未审核", value: "0"},
|
||||
{text: "已审核", value: "1"}
|
||||
],
|
||||
detailVisible: false,
|
||||
detailBizId: "",
|
||||
popupAction: "view",
|
||||
formData: {},
|
||||
showApprovalForm: false,
|
||||
|
||||
formLoading: false,
|
||||
showCaseFilingResultPicker: false,
|
||||
showCaseFilingTypePicker: false
|
||||
showCaseFilingTypePicker: false,
|
||||
submitConfirmVisible: false,
|
||||
historyLayerPageKey: "proposal-commissioner-h5"
|
||||
}
|
||||
},
|
||||
components: {
|
||||
"proposal-info": PROPOSAL_INFO
|
||||
computed: {
|
||||
isApproval() {
|
||||
return this.popupAction === "approval"
|
||||
},
|
||||
popupTitle() {
|
||||
return this.isApproval ? "委员会成员意见" : "提案详情"
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
registerHistoryLayers() {
|
||||
if (!window.h5HistoryLayerManager) return
|
||||
window.h5HistoryLayerManager.register(this.historyLayerPageKey, (stack) => {
|
||||
this.$set(this, "detailVisible", stack.includes("detail"))
|
||||
this.$set(this, "showCaseFilingResultPicker", stack.includes("result-picker"))
|
||||
this.$set(this, "showCaseFilingTypePicker", stack.includes("type-picker"))
|
||||
this.$set(this, "submitConfirmVisible", stack.includes("submit-confirm"))
|
||||
})
|
||||
},
|
||||
openHistoryLayer(layerName) {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open(layerName)) return
|
||||
this.setHistoryLayerVisible(layerName, true)
|
||||
},
|
||||
closeHistoryLayer(layerName, afterClose = null) {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.close(layerName, afterClose)) return
|
||||
this.setHistoryLayerVisible(layerName, false)
|
||||
if (typeof afterClose === "function") afterClose()
|
||||
},
|
||||
setHistoryLayerVisible(layerName, visible) {
|
||||
if (layerName === "detail") this.$set(this, "detailVisible", visible)
|
||||
if (layerName === "result-picker") this.$set(this, "showCaseFilingResultPicker", visible)
|
||||
if (layerName === "type-picker") this.$set(this, "showCaseFilingTypePicker", visible)
|
||||
if (layerName === "submit-confirm") this.$set(this, "submitConfirmVisible", visible)
|
||||
},
|
||||
handlePageBack() {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.stack.length) {
|
||||
window.h5HistoryLayerManager.close()
|
||||
return
|
||||
}
|
||||
this.historyBack()
|
||||
},
|
||||
setFilterOpened(value) {
|
||||
this.$set(this, "filterOpened", value)
|
||||
},
|
||||
onReady() {
|
||||
this.listSession()
|
||||
},
|
||||
// 审核状态下拉框使用字符串值展示,查询接口使用布尔值区分已审核和未审核。
|
||||
approvalChange(value) {
|
||||
this.$set(this.pageForm, "approval", value === "1")
|
||||
this.doSearch()
|
||||
},
|
||||
listSession() {
|
||||
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.sessionOptions = [
|
||||
this.$set(this, "sessionOptions", [
|
||||
{
|
||||
text: "全部届次",
|
||||
value: null
|
||||
}
|
||||
].concat(res.data.map((v) => ({text: v.fullName, value: v.id})))
|
||||
if (this.sessionOptions.length > 0) {
|
||||
this.pageForm.sessionId = this.sessionOptions[0].value
|
||||
this.doSearch()
|
||||
}
|
||||
].concat(res.data.map((v) => ({text: v.fullName, value: v.id}))))
|
||||
// 届次接口按开始时间倒序返回,首条即最新届次;无届次时继续按全部届次查询。
|
||||
this.$set(this.pageForm, "sessionId", res.data.length > 0 ? res.data[0].id : null)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
},
|
||||
|
||||
// 确定立案类型
|
||||
onCaseFilingResultConfirm(value) {
|
||||
this.$set(this.formData, "caseFilingResultName", value.text)
|
||||
this.$set(this.formData, "caseFilingResult", value.value)
|
||||
this.showCaseFilingResultPicker = false
|
||||
},
|
||||
|
||||
// 确定立案类型
|
||||
onCaseFilingTypeConfirm(value) {
|
||||
this.$set(this.formData, "caseFilingTypeName", value.text)
|
||||
this.$set(this.formData, "caseFilingType", value.value)
|
||||
this.showCaseFilingTypePicker = false
|
||||
this.$set(this, "detailBizId", row.id)
|
||||
this.$set(this, "popupAction", "view")
|
||||
this.$set(this, "formData", {})
|
||||
this.openHistoryLayer("detail")
|
||||
},
|
||||
|
||||
onApproval(row) {
|
||||
this.showApprovalForm = true
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
this.formData = {
|
||||
this.$set(this, "detailBizId", row.id)
|
||||
this.$set(this, "popupAction", "approval")
|
||||
this.$set(this, "formData", {
|
||||
proposalId: row.id,
|
||||
caseFilingResult: null,
|
||||
caseFilingType: null,
|
||||
opinion: null
|
||||
}
|
||||
})
|
||||
this.openHistoryLayer("detail")
|
||||
},
|
||||
|
||||
async doSubmit() {
|
||||
try {
|
||||
await this.$refs.formRef.validate();
|
||||
this.$dialog.confirm({
|
||||
title: '提示',
|
||||
message: "您确定要提交吗?",
|
||||
}).then(() => {
|
||||
this.$axios.post('/platform/proposal/commissioner/doApproval', this.formData).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.proposalInfoRef.onClose()
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
|
||||
onCaseFilingResultConfirm(value) {
|
||||
this.$set(this.formData, "caseFilingResultName", value.text)
|
||||
this.$set(this.formData, "caseFilingResult", value.value)
|
||||
this.closeHistoryLayer("result-picker")
|
||||
},
|
||||
onCaseFilingTypeConfirm(value) {
|
||||
this.$set(this.formData, "caseFilingTypeName", value.text)
|
||||
this.$set(this.formData, "caseFilingType", value.value)
|
||||
this.closeHistoryLayer("type-picker")
|
||||
},
|
||||
submitApproval() {
|
||||
this.$refs.formRef.validate().then(() => this.openHistoryLayer("submit-confirm")).catch(() => {})
|
||||
},
|
||||
confirmApproval() {
|
||||
this.closeHistoryLayer("submit-confirm", () => this.doSubmitApproval())
|
||||
},
|
||||
doSubmitApproval() {
|
||||
this.$set(this, "formLoading", true)
|
||||
this.$axios.post("/platform/proposal/commissioner/doApproval", this.formData)
|
||||
.then((res) => {
|
||||
if (res && res.code === 0) {
|
||||
this.$toast.success(res.msg)
|
||||
this.closeHistoryLayer("detail", () => this.doSearch())
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
.finally(() => this.$set(this, "formLoading", false))
|
||||
},
|
||||
|
||||
doSearch() {
|
||||
@@ -224,6 +309,12 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.registerHistoryLayers()
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (window.h5HistoryLayerManager) window.h5HistoryLayerManager.unregister(this.historyLayerPageKey)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
+40
-24
@@ -1,7 +1,11 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<div id="app" v-cloak>
|
||||
<style>
|
||||
<!--#include("../theme.css"){}#-->
|
||||
<!--#include("../../common/info.css"){}#-->
|
||||
</style>
|
||||
<div class="swufe-mobile-page" id="app" v-cloak>
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="提案委员会立案" placeholder fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<van-search v-model="pageForm.name" :show-action="false" :reverse-color="false" input-align="left"
|
||||
@@ -38,7 +42,9 @@ layout("/layouts/platform_h5.html"){
|
||||
</template>
|
||||
</table-list>
|
||||
|
||||
<proposal-info ref="proposalInfoRef">
|
||||
<van-popup v-model="proposalVisible" position="right" class="proposal-full-popup" :close-on-click-overlay="false">
|
||||
<div class="proposal-full-popup__page"><van-nav-bar title="提案详情" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
<div class="proposal-full-popup__scroll"><proposal-info v-if="proposalBizId" :biz-id="proposalBizId" :visible="proposalVisible" ref="proposalInfoRef">
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">{{formData.taskName}}</div>
|
||||
<van-form ref="formRef">
|
||||
@@ -94,7 +100,7 @@ layout("/layouts/platform_h5.html"){
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">提交</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</proposal-info>
|
||||
</proposal-info></div></div></van-popup>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
@@ -111,6 +117,8 @@ layout("/layouts/platform_h5.html"){
|
||||
sessionOptions: [],
|
||||
underTakeOptions: [],
|
||||
formData: {},
|
||||
proposalBizId: "",
|
||||
proposalVisible: false,
|
||||
showApprovalForm: false,
|
||||
showResultPicker: false,
|
||||
showMasterUnitPicker: false,
|
||||
@@ -121,7 +129,7 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
computed: {
|
||||
caseFilingResultOptions() {
|
||||
return (this.dict.type.PROPOSAL_CASE_FILING_RESULT || []).map(function (item) {
|
||||
return (this.dict.type.PROPOSAL_CASE_FILING_RESULT || []).map((item) => {
|
||||
return {text: item.label, value: item.code}
|
||||
})
|
||||
},
|
||||
@@ -188,7 +196,7 @@ layout("/layouts/platform_h5.html"){
|
||||
listSession() {
|
||||
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$set(this, "sessionOptions", [{text: "全部届次", value: null}].concat(res.data.map(function (item) {
|
||||
this.$set(this, "sessionOptions", [{text: "全部届次", value: null}].concat(res.data.map((item) => {
|
||||
return {text: item.fullName, value: item.id}
|
||||
})))
|
||||
this.$set(this.pageForm, "sessionId", this.sessionOptions[0].value)
|
||||
@@ -207,7 +215,8 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
onView(row) {
|
||||
this.$set(this, "showApprovalForm", false)
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
this.$set(this, "proposalBizId", row.id)
|
||||
this.$set(this, "proposalVisible", true)
|
||||
},
|
||||
onApproval(row) {
|
||||
this.$set(this, "showApprovalForm", true)
|
||||
@@ -221,7 +230,8 @@ layout("/layouts/platform_h5.html"){
|
||||
tf_slaveUnitIds: [],
|
||||
tf_opinion: ""
|
||||
})
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
this.$set(this, "proposalBizId", row.id)
|
||||
this.$set(this, "proposalVisible", true)
|
||||
},
|
||||
onResultConfirm(value) {
|
||||
this.$set(this.formData, "tf_caseFilingResult", value.value)
|
||||
@@ -247,9 +257,9 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$set(this.formData, fieldName, nextUnitIds)
|
||||
},
|
||||
getUnitNames(unitIds) {
|
||||
return this.underTakeOptions.filter(function (item) {
|
||||
return this.underTakeOptions.filter((item) => {
|
||||
return unitIds.includes(item.id)
|
||||
}).map(function (item) {
|
||||
}).map((item) => {
|
||||
return item.name
|
||||
}).join("、")
|
||||
},
|
||||
@@ -270,22 +280,28 @@ layout("/layouts/platform_h5.html"){
|
||||
})
|
||||
},
|
||||
getUnitName(unitId) {
|
||||
const unit = this.underTakeOptions.find(function (item) { return item.id === unitId })
|
||||
const unit = this.underTakeOptions.find((item) => { return item.id === unitId })
|
||||
return unit ? unit.name : ""
|
||||
},
|
||||
async handleTaskAction(submitType) {
|
||||
try {
|
||||
await this.$refs.formRef.validate()
|
||||
this.$dialog.confirm({title: "提示", message: "您确定要提交吗?"}).then(() => {
|
||||
this.$axios.post("/flow/common/executeTask", {data: JSON.stringify(this.buildSubmitData(submitType))}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.proposalInfoRef.onClose()
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(function () {})
|
||||
} catch (error) {}
|
||||
handleTaskAction(submitType) {
|
||||
return Promise.resolve().then(() => {
|
||||
return this.$refs.formRef.validate().then(() => {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify(this.buildSubmitData(submitType))
|
||||
}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$set(this, "proposalVisible", false);
|
||||
this.$toast.success(res.msg);
|
||||
this.doSearch();
|
||||
}
|
||||
});
|
||||
}).catch(() => {});
|
||||
});
|
||||
}).catch(error => {});
|
||||
},
|
||||
onRevoke(row) {
|
||||
this.$dialog.confirm({title: "提示", message: "您确定要撤回吗?"}).then(() => {
|
||||
@@ -298,7 +314,7 @@ layout("/layouts/platform_h5.html"){
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(function () {})
|
||||
}).catch(() => {})
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
|
||||
+44
-30
@@ -1,7 +1,11 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<div id="app" v-cloak>
|
||||
<style>
|
||||
<!--#include("../theme.css"){}#-->
|
||||
<!--#include("../../common/info.css"){}#-->
|
||||
</style>
|
||||
<div class="swufe-mobile-page" id="app" v-cloak>
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="委员会确认承办单位" placeholder fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<van-search v-model="pageForm.name" :show-action="false" :reverse-color="false" input-align="left"
|
||||
@@ -38,7 +42,9 @@ layout("/layouts/platform_h5.html"){
|
||||
</template>
|
||||
</table-list>
|
||||
|
||||
<proposal-info ref="proposalInfoRef">
|
||||
<van-popup v-model="proposalVisible" position="right" class="proposal-full-popup" :close-on-click-overlay="false">
|
||||
<div class="proposal-full-popup__page"><van-nav-bar title="提案详情" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
<div class="proposal-full-popup__scroll"><proposal-info v-if="proposalBizId" :biz-id="proposalBizId" :visible="proposalVisible" ref="proposalInfoRef">
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">{{formData.taskName}}</div>
|
||||
<van-form ref="formRef">
|
||||
@@ -94,7 +100,7 @@ layout("/layouts/platform_h5.html"){
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">提交</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</proposal-info>
|
||||
</proposal-info></div></div></van-popup>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
@@ -111,6 +117,8 @@ layout("/layouts/platform_h5.html"){
|
||||
sessionOptions: [],
|
||||
underTakeOptions: [],
|
||||
formData: {},
|
||||
proposalBizId: "",
|
||||
proposalVisible: false,
|
||||
showApprovalForm: false,
|
||||
showResultPicker: false,
|
||||
showMasterUnitPicker: false,
|
||||
@@ -121,7 +129,7 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
computed: {
|
||||
caseFilingResultOptions() {
|
||||
return (this.dict.type.PROPOSAL_CASE_FILING_RESULT || []).map(function (item) {
|
||||
return (this.dict.type.PROPOSAL_CASE_FILING_RESULT || []).map((item) => {
|
||||
return {text: item.label, value: item.code}
|
||||
})
|
||||
},
|
||||
@@ -188,7 +196,7 @@ layout("/layouts/platform_h5.html"){
|
||||
listSession() {
|
||||
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$set(this, "sessionOptions", [{text: "全部届次", value: null}].concat(res.data.map(function (item) {
|
||||
this.$set(this, "sessionOptions", [{text: "全部届次", value: null}].concat(res.data.map((item) => {
|
||||
return {text: item.fullName, value: item.id}
|
||||
})))
|
||||
this.$set(this.pageForm, "sessionId", this.sessionOptions[0].value)
|
||||
@@ -207,7 +215,8 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
onView(row) {
|
||||
this.$set(this, "showApprovalForm", false)
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
this.$set(this, "proposalBizId", row.id)
|
||||
this.$set(this, "proposalVisible", true)
|
||||
},
|
||||
onApproval(row) {
|
||||
this.$set(this, "showApprovalForm", true)
|
||||
@@ -222,7 +231,8 @@ layout("/layouts/platform_h5.html"){
|
||||
tf_opinion: ""
|
||||
})
|
||||
this.loadCommitteeFilingData(row.id)
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
this.$set(this, "proposalBizId", row.id)
|
||||
this.$set(this, "proposalVisible", true)
|
||||
},
|
||||
/**
|
||||
* 确认承办单位必须延续上一“提案委员会立案”的结果和单位,
|
||||
@@ -231,7 +241,7 @@ layout("/layouts/platform_h5.html"){
|
||||
loadCommitteeFilingData(proposalId) {
|
||||
this.$axios.post("/flow/common/doneTasks", {bizId: proposalId}).then((res) => {
|
||||
if (res.code !== 0) return
|
||||
const committeeTasks = res.data.filter(function (task) { return task.taskName === "committee" })
|
||||
const committeeTasks = res.data.filter((task) => { return task.taskName === "committee" })
|
||||
const committeeTask = committeeTasks.length ? committeeTasks[committeeTasks.length - 1] : null
|
||||
if (!committeeTask || !committeeTask.ext) return
|
||||
const ext = committeeTask.ext
|
||||
@@ -242,7 +252,7 @@ layout("/layouts/platform_h5.html"){
|
||||
})
|
||||
},
|
||||
getCaseFilingResultName(code) {
|
||||
const result = (this.dict.type.PROPOSAL_CASE_FILING_RESULT || []).find(function (item) { return item.code === code })
|
||||
const result = (this.dict.type.PROPOSAL_CASE_FILING_RESULT || []).find((item) => { return item.code === code })
|
||||
return result ? result.label : ""
|
||||
},
|
||||
normalizeUnitIds(unitIds) {
|
||||
@@ -253,7 +263,7 @@ layout("/layouts/platform_h5.html"){
|
||||
const parsedValue = JSON.parse(unitIds)
|
||||
if (Array.isArray(parsedValue)) return parsedValue
|
||||
} catch (error) {}
|
||||
return unitIds.split(",").filter(function (item) { return item && item.trim() }).map(function (item) { return item.trim() })
|
||||
return unitIds.split(",").filter((item) => { return item && item.trim() }).map((item) => { return item.trim() })
|
||||
}
|
||||
return []
|
||||
},
|
||||
@@ -281,14 +291,14 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$set(this.formData, fieldName, nextUnitIds)
|
||||
},
|
||||
getUnitNames(unitIds) {
|
||||
return this.underTakeOptions.filter(function (item) {
|
||||
return this.underTakeOptions.filter((item) => {
|
||||
return unitIds.includes(item.id)
|
||||
}).map(function (item) {
|
||||
}).map((item) => {
|
||||
return item.name
|
||||
}).join("、")
|
||||
},
|
||||
getUnitName(unitId) {
|
||||
const unit = this.underTakeOptions.find(function (item) { return item.id === unitId })
|
||||
const unit = this.underTakeOptions.find((item) => { return item.id === unitId })
|
||||
return unit ? unit.name : ""
|
||||
},
|
||||
buildSubmitData() {
|
||||
@@ -307,21 +317,25 @@ layout("/layouts/platform_h5.html"){
|
||||
submitType: 1
|
||||
})
|
||||
},
|
||||
async handleTaskAction() {
|
||||
try {
|
||||
await this.$refs.formRef.validate()
|
||||
this.$dialog.confirm({title: "提示", message: "您确定要提交吗?"}).then(() => {
|
||||
this.$axios.post("/platform/proposal/committeeFilingUnit/h5/executeTask", {
|
||||
data: JSON.stringify(this.buildSubmitData())
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.proposalInfoRef.onClose()
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(function () {})
|
||||
} catch (error) {}
|
||||
handleTaskAction() {
|
||||
return Promise.resolve().then(() => {
|
||||
return this.$refs.formRef.validate().then(() => {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/platform/proposal/committeeFilingUnit/h5/executeTask", {
|
||||
data: JSON.stringify(this.buildSubmitData())
|
||||
}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$set(this, "proposalVisible", false);
|
||||
this.$toast.success(res.msg);
|
||||
this.doSearch();
|
||||
}
|
||||
});
|
||||
}).catch(() => {});
|
||||
});
|
||||
}).catch(error => {});
|
||||
},
|
||||
onRevoke(row) {
|
||||
this.$dialog.confirm({title: "提示", message: "您确定要撤回吗?"}).then(() => {
|
||||
@@ -334,10 +348,10 @@ layout("/layouts/platform_h5.html"){
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(function () {})
|
||||
}).catch(() => {})
|
||||
},
|
||||
closeApproval() {
|
||||
this.$refs.proposalInfoRef.onClose()
|
||||
this.$set(this, "proposalVisible", false)
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
|
||||
+361
-129
@@ -1,86 +1,338 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<style>
|
||||
body {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.proposal-delegation-page {
|
||||
min-height: 100vh;
|
||||
padding-bottom: calc(24px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.proposal-delegation-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.proposal-delegation-page .van-nav-bar__title {
|
||||
color: #172033;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.proposal-delegation-page .van-nav-bar .van-icon,
|
||||
.proposal-delegation-page .van-nav-bar__text {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.proposal-delegation-content {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.proposal-delegation-sticky {
|
||||
padding: 22px 12px 1px;
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.proposal-delegation-search {
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.proposal-delegation-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.proposal-delegation-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.proposal-delegation-search .van-field__control::placeholder {
|
||||
color: #a7b0bf;
|
||||
}
|
||||
|
||||
.proposal-delegation-filter {
|
||||
margin: 0 0 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
transition: border-radius .18s ease;
|
||||
}
|
||||
|
||||
.proposal-delegation-filter.is-open {
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
.proposal-delegation-filter .van-dropdown-menu__bar,
|
||||
.proposal-delegation-filter .van-dropdown-menu__item,
|
||||
.proposal-delegation-filter .van-dropdown-menu__title {
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.proposal-delegation-filter .van-dropdown-menu__bar {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.proposal-delegation-filter .van-dropdown-menu__item,
|
||||
.proposal-delegation-filter .van-dropdown-menu__title {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.proposal-delegation-filter .van-dropdown-menu__item {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.proposal-delegation-filter .van-dropdown-menu__title {
|
||||
display: inline-flex;
|
||||
color: #66758a;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.proposal-delegation-filter .van-dropdown-menu__title--active,
|
||||
.proposal-delegation-filter .van-dropdown-item__option--active,
|
||||
.proposal-delegation-filter .van-dropdown-item__option--active .van-dropdown-item__icon {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.proposal-delegation-filter .van-dropdown-menu__title--down::after {
|
||||
border-color: transparent transparent #1989fa #1989fa;
|
||||
}
|
||||
|
||||
.proposal-delegation-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
margin: 0 12px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0 0 12px 12px;
|
||||
box-shadow: 0 10px 24px rgba(31, 65, 108, .14);
|
||||
}
|
||||
|
||||
.proposal-delegation-filter .van-dropdown-item__option {
|
||||
display: flex;
|
||||
min-height: 48px;
|
||||
padding: 0 16px;
|
||||
align-items: center;
|
||||
color: #46566c;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.proposal-delegation-filter .van-cell::after {
|
||||
right: 16px;
|
||||
left: 16px;
|
||||
}
|
||||
|
||||
.proposal-delegation-list .empty-state {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.proposal-delegation-empty {
|
||||
display: flex;
|
||||
min-height: 280px;
|
||||
padding: 46px 18px 36px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.proposal-delegation-empty img {
|
||||
display: block;
|
||||
width: 86%;
|
||||
max-width: 290px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.proposal-delegation-empty__title {
|
||||
margin-top: 14px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.proposal-delegation-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.proposal-delegation-card-header {
|
||||
display: flex;
|
||||
margin-bottom: 7px;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.proposal-delegation-card-heading {
|
||||
min-width: 0;
|
||||
padding-right: 10px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.proposal-delegation-card-title {
|
||||
overflow: hidden;
|
||||
color: #253247;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.proposal-delegation-card-code {
|
||||
margin-top: 1px;
|
||||
color: #9ba6b6;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.proposal-delegation-status {
|
||||
display: inline-flex;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.proposal-delegation-status .van-tag {
|
||||
display: inline-flex;
|
||||
min-height: 24px;
|
||||
padding: 3px 9px;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
border: 0;
|
||||
border-radius: 12px;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@media (max-width: 350px) {
|
||||
.proposal-delegation-content,
|
||||
.proposal-delegation-sticky {
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style id="style-proposal-task-popup-h5">
|
||||
<!--#include("../../common/info.css"){}#-->
|
||||
<!--#include("../theme.css"){}#-->
|
||||
</style>
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" :title="pageTitle" placeholder fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<van-search
|
||||
v-model="pageForm.name"
|
||||
:show-action="false"
|
||||
:reverse-color="false"
|
||||
input-align="left"
|
||||
placeholder="请输入提案名称搜索"
|
||||
@search="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions" :multiple="false"
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
</van-sticky>
|
||||
<div class="proposal-delegation-page">
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" :title="pageTitle" placeholder fixed></van-nav-bar>
|
||||
<van-sticky :offset-top="46">
|
||||
<div class="proposal-delegation-sticky">
|
||||
<van-search
|
||||
v-model="pageForm.name"
|
||||
class="proposal-delegation-search"
|
||||
placeholder="请输入提案名称搜索"
|
||||
shape="round"
|
||||
clearable
|
||||
@search="doSearch"
|
||||
@clear="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu
|
||||
class="proposal-delegation-filter"
|
||||
:class="{'is-open': filterOpened}"
|
||||
active-color="#1989fa"
|
||||
>
|
||||
<van-dropdown-item
|
||||
v-model="pageForm.sessionId"
|
||||
:options="sessionOptions"
|
||||
:multiple="false"
|
||||
@change="doSearch"
|
||||
@open="$set($data, 'filterOpened', true)"
|
||||
@close="$set($data, 'filterOpened', false)"
|
||||
></van-dropdown-item>
|
||||
<van-dropdown-item
|
||||
v-model="pageForm.approvalText"
|
||||
:options="approvalOptions"
|
||||
:multiple="false"
|
||||
@change="approvalChange"
|
||||
@open="$set($data, 'filterOpened', true)"
|
||||
@close="$set($data, 'filterOpened', false)"
|
||||
></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<table-list :api="pageDataUrl" :page_form.sync="pageForm" @ready="onReady"
|
||||
ref="tableListRef"
|
||||
title="name">
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="提案编号">{{row.code}}</table-column>
|
||||
<table-column label="提案类别">{{row.typeName}}</table-column>
|
||||
<table-column label="提案人">{{row.createUserName}}</table-column>
|
||||
<table-column label="代表团">{{row.delegationName}}</table-column>
|
||||
<table-column label="当前节点">{{row.curTaskName}}</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span>查看</span>
|
||||
<main class="proposal-delegation-content">
|
||||
<div class="proposal-delegation-list">
|
||||
<!-- 列表无记录时使用与“我的提案”一致的提案专用空状态。 -->
|
||||
<div v-if="pageForm.totalCount === 0" class="proposal-delegation-empty">
|
||||
<img src="/assets/mobile/img/proposal/proposal-empty.png" alt="暂无提案记录插画">
|
||||
<div class="proposal-delegation-empty__title">暂无提案记录</div>
|
||||
<div class="proposal-delegation-empty__hint">当前筛选条件下暂时没有提案</div>
|
||||
</div>
|
||||
<table-list :api="pageDataUrl" :page_form.sync="pageForm" @ready="onReady"
|
||||
ref="tableListRef"
|
||||
title="name">
|
||||
<template #header="{index,row}">
|
||||
<div class="proposal-delegation-card-header">
|
||||
<div class="proposal-delegation-card-heading">
|
||||
<div class="proposal-delegation-card-title">{{row.name}}</div>
|
||||
<div class="proposal-delegation-card-code">编号:{{row.code || '--'}}</div>
|
||||
</div>
|
||||
<enum-tag
|
||||
class="proposal-delegation-status"
|
||||
v-if="row.instanceState"
|
||||
:value="row.instanceState"
|
||||
name="ProcessInstanceStateEnum"
|
||||
label_key="message"
|
||||
size="small"
|
||||
></enum-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="提案类别">{{row.typeName || '--'}}</table-column>
|
||||
<table-column label="提案人">{{row.createUserName || '--'}}</table-column>
|
||||
<table-column label="代表团">{{row.delegationName || '--'}}</table-column>
|
||||
<table-column label="当前节点">{{row.curTaskName || '--'}}</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row,index)">
|
||||
<van-icon class="proposal-action-icon" name="eye-o"></van-icon>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row,index)">
|
||||
<van-icon class="proposal-action-icon" name="edit"></van-icon>
|
||||
<span>审核</span>
|
||||
</div>
|
||||
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">
|
||||
<van-icon class="proposal-action-icon" name="revoke"></van-icon>
|
||||
<span>撤回</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
|
||||
<i class="fa fa-edit"></i>
|
||||
<span>审核</span>
|
||||
</div>
|
||||
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">
|
||||
<i class="fa fa-reply"></i>
|
||||
<span>撤回</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
|
||||
<proposal-info ref="proposalInfoRef">
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">{{formData.taskName}}</div>
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
v-model="formData.tf_opinion"
|
||||
name="tf_opinion"
|
||||
label="审批意见"
|
||||
placeholder="请输入审批意见"
|
||||
:rules="[{ required: true, message: '请填写审批意见' }]"
|
||||
required
|
||||
maxlength="100"
|
||||
show-word-limit
|
||||
></van-field>
|
||||
</van-form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(2)">不同意</van-button>
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">同意</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</proposal-info>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
<proposal-task-popup ref="taskPopup" kind="delegation" page-key="proposal-delegation-task" @success="doSearch"></proposal-task-popup>
|
||||
</div>
|
||||
<script nonce="${cspNonce!}">
|
||||
<!--#include("../../common/info.js"){}#-->
|
||||
|
||||
<!--#include("../../common/task-popup.js"){}#-->
|
||||
/**
|
||||
* 同一审核页面模板按当前访问地址选择标题和手机端数据接口,
|
||||
* 使 PC、H5 的权限接口保持分离。
|
||||
*/
|
||||
function getH5AuditPageConfig() {
|
||||
const getH5AuditPageConfig = () => {
|
||||
const pathname = window.location.pathname
|
||||
if (pathname.indexOf("/secondaryUnionAudit/") !== -1) {
|
||||
return {
|
||||
@@ -102,91 +354,61 @@ layout("/layouts/platform_h5.html"){
|
||||
|
||||
const auditPageConfig = getH5AuditPageConfig()
|
||||
|
||||
const vue = new Vue({
|
||||
new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
components: {"proposal-task-popup": PROPOSAL_TASK_POPUP},
|
||||
data() {
|
||||
return {
|
||||
pageTitle: auditPageConfig.title,
|
||||
pageDataUrl: auditPageConfig.pageDataUrl,
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "",
|
||||
pageOrderBy: "",
|
||||
name: null,
|
||||
sessionId: null,
|
||||
approvalText: "0",
|
||||
approval: false
|
||||
},
|
||||
|
||||
pageTitle: auditPageConfig.title,
|
||||
pageDataUrl: auditPageConfig.pageDataUrl,
|
||||
sessionOptions: [],
|
||||
formData: {},
|
||||
showApprovalForm: false
|
||||
filterOpened: false,
|
||||
approvalOptions: [
|
||||
{text: "未审核", value: "0"},
|
||||
{text: "已审核", value: "1"}
|
||||
],
|
||||
}
|
||||
},
|
||||
components: {
|
||||
"proposal-info": PROPOSAL_INFO
|
||||
},
|
||||
methods: {
|
||||
onReady() {
|
||||
this.listSession()
|
||||
this.listSession(false)
|
||||
},
|
||||
listSession() {
|
||||
// 审核状态下拉框使用字符串值展示,查询接口使用布尔值区分已审核和未审核。
|
||||
approvalChange(value) {
|
||||
this.$set(this.pageForm, "approval", value === "1")
|
||||
this.doSearch()
|
||||
},
|
||||
listSession(skipDefaultSearch) {
|
||||
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.sessionOptions = [
|
||||
{
|
||||
text: "全部届次",
|
||||
value: null
|
||||
}
|
||||
].concat(res.data.map((v) => ({text: v.fullName, value: v.id})))
|
||||
if (this.sessionOptions.length > 0) {
|
||||
this.pageForm.sessionId = this.sessionOptions[0].value
|
||||
this.doSearch()
|
||||
}
|
||||
this.sessionOptions = [{text: "全部届次", value: null}]
|
||||
.concat(res.data.map((v) => ({text: v.fullName, value: v.id})))
|
||||
if (skipDefaultSearch) return
|
||||
this.$set(this.pageForm, "sessionId", res.data.length > 0 ? res.data[0].id : null)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
onView(row, index) {
|
||||
this.$refs.taskPopup.open(row, "view")
|
||||
},
|
||||
|
||||
onApproval(row) {
|
||||
this.showApprovalForm = true
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
this.formData = {
|
||||
processTaskId: row.taskId,
|
||||
taskName: row.curTaskName
|
||||
}
|
||||
},
|
||||
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate();
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: val
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.proposalInfoRef.onClose()
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
|
||||
})
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
onApproval(row, index) {
|
||||
this.$refs.taskPopup.open(row, "approval")
|
||||
},
|
||||
|
||||
onRevoke(row){
|
||||
@@ -205,11 +427,21 @@ layout("/layouts/platform_h5.html"){
|
||||
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$set(this.pageForm, "pageNumber", 1)
|
||||
this.$set(this.pageForm, "totalCount", 0)
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
},
|
||||
},
|
||||
created() {
|
||||
const tab = new URLSearchParams(window.location.search).get("tab")
|
||||
if (tab === "done") {
|
||||
this.$set(this.pageForm, "approval", true)
|
||||
this.$set(this.pageForm, "approvalText", "1")
|
||||
} else if (tab === "todo") {
|
||||
this.$set(this.pageForm, "approval", false)
|
||||
this.$set(this.pageForm, "approvalText", "0")
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
+362
-203
@@ -1,243 +1,392 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<style>
|
||||
body {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-page {
|
||||
min-height: 100vh;
|
||||
padding-bottom: calc(24px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-page .van-nav-bar__title {
|
||||
color: #172033;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-page .van-nav-bar .van-icon,
|
||||
.proposal-feedback-evaluation-page .van-nav-bar__text {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-content {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-sticky {
|
||||
padding: 22px 12px 1px;
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-search {
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-search .van-field__control::placeholder {
|
||||
color: #a7b0bf;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-filter {
|
||||
margin: 0 0 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
transition: border-radius .18s ease;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-filter.is-open {
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-filter .van-dropdown-menu__bar,
|
||||
.proposal-feedback-evaluation-filter .van-dropdown-menu__item,
|
||||
.proposal-feedback-evaluation-filter .van-dropdown-menu__title {
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-filter .van-dropdown-menu__bar {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-filter .van-dropdown-menu__item,
|
||||
.proposal-feedback-evaluation-filter .van-dropdown-menu__title {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-filter .van-dropdown-menu__item {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-filter .van-dropdown-menu__title {
|
||||
display: inline-flex;
|
||||
color: #66758a;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-filter .van-dropdown-menu__title--active,
|
||||
.proposal-feedback-evaluation-filter .van-dropdown-item__option--active,
|
||||
.proposal-feedback-evaluation-filter .van-dropdown-item__option--active .van-dropdown-item__icon {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-filter .van-dropdown-menu__title--down::after {
|
||||
border-color: transparent transparent #1989fa #1989fa;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
margin: 0 12px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0 0 12px 12px;
|
||||
box-shadow: 0 10px 24px rgba(31, 65, 108, .14);
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-filter .van-dropdown-item__option {
|
||||
display: flex;
|
||||
min-height: 48px;
|
||||
padding: 0 16px;
|
||||
align-items: center;
|
||||
color: #46566c;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-filter .van-cell::after {
|
||||
right: 16px;
|
||||
left: 16px;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-list .empty-state {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-empty {
|
||||
display: flex;
|
||||
min-height: 280px;
|
||||
padding: 46px 18px 36px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-empty img {
|
||||
display: block;
|
||||
width: 86%;
|
||||
max-width: 290px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-empty__title {
|
||||
margin-top: 14px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-card-header {
|
||||
display: flex;
|
||||
margin-bottom: 7px;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-card-heading {
|
||||
min-width: 0;
|
||||
padding-right: 10px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-card-title {
|
||||
overflow: hidden;
|
||||
color: #253247;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-card-code {
|
||||
margin-top: 1px;
|
||||
color: #9ba6b6;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-status {
|
||||
display: inline-flex;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.proposal-feedback-evaluation-status .van-tag {
|
||||
display: inline-flex;
|
||||
min-height: 24px;
|
||||
padding: 3px 9px;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
border: 0;
|
||||
border-radius: 12px;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@media (max-width: 350px) {
|
||||
.proposal-feedback-evaluation-content,
|
||||
.proposal-feedback-evaluation-sticky {
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style id="style-proposal-task-popup-h5">
|
||||
<!--#include("../../common/info.css"){}#-->
|
||||
<!--#include("../theme.css"){}#-->
|
||||
</style>
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="反馈评价" placeholder fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<van-search
|
||||
v-model="pageForm.name"
|
||||
:show-action="false"
|
||||
:reverse-color="false"
|
||||
input-align="left"
|
||||
placeholder="请输入提案名称搜索"
|
||||
@search="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions" :multiple="false"
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
<van-tab title="已评价" name="1"></van-tab>
|
||||
<van-tab title="未评价" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
</van-sticky>
|
||||
|
||||
<table-list api="/platform/proposal/feedbackEvaluation/pageData" :page_form.sync="pageForm" @ready="onReady"
|
||||
ref="tableListRef"
|
||||
title="name">
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="提案编号">{{row.code}}</table-column>
|
||||
<table-column label="提案类别">{{row.typeName}}</table-column>
|
||||
<table-column label="提案人">{{row.createUserName}}</table-column>
|
||||
<table-column label="代表团">{{row.delegationName}}</table-column>
|
||||
<table-column label="当前节点">{{row.curTaskName}}</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span>查看</span>
|
||||
<div class="proposal-feedback-evaluation-page">
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="反馈评价" placeholder fixed></van-nav-bar>
|
||||
<van-sticky :offset-top="46">
|
||||
<div class="proposal-feedback-evaluation-sticky">
|
||||
<van-search
|
||||
v-model="pageForm.name"
|
||||
class="proposal-feedback-evaluation-search"
|
||||
placeholder="请输入提案名称搜索"
|
||||
shape="round"
|
||||
clearable
|
||||
@search="doSearch"
|
||||
@clear="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu
|
||||
class="proposal-feedback-evaluation-filter"
|
||||
:class="{'is-open': filterOpened}"
|
||||
active-color="#1989fa"
|
||||
>
|
||||
<van-dropdown-item
|
||||
v-model="pageForm.sessionId"
|
||||
:options="sessionOptions"
|
||||
:multiple="false"
|
||||
@change="doSearch"
|
||||
@open="$set($data, 'filterOpened', true)"
|
||||
@close="$set($data, 'filterOpened', false)"
|
||||
></van-dropdown-item>
|
||||
<van-dropdown-item
|
||||
v-model="pageForm.approvalText"
|
||||
:options="approvalOptions"
|
||||
:multiple="false"
|
||||
@change="approvalChange"
|
||||
@open="$set($data, 'filterOpened', true)"
|
||||
@close="$set($data, 'filterOpened', false)"
|
||||
></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
|
||||
<i class="fa fa-edit"></i>
|
||||
<span>评价</span>
|
||||
</van-sticky>
|
||||
|
||||
<main class="proposal-feedback-evaluation-content">
|
||||
<div class="proposal-feedback-evaluation-list">
|
||||
<!-- 列表无记录时使用与团长审核一致的提案专用空状态。 -->
|
||||
<div v-if="pageForm.totalCount === 0" class="proposal-feedback-evaluation-empty">
|
||||
<img src="/assets/mobile/img/proposal/proposal-empty.png" alt="暂无提案记录插画">
|
||||
<div class="proposal-feedback-evaluation-empty__title">暂无提案记录</div>
|
||||
<div class="proposal-feedback-evaluation-empty__hint">当前筛选条件下暂时没有提案</div>
|
||||
</div>
|
||||
<table-list api="/platform/proposal/feedbackEvaluation/pageData" :page_form.sync="pageForm" @ready="onReady"
|
||||
ref="tableListRef"
|
||||
title="name">
|
||||
<template #header="{index,row}">
|
||||
<div class="proposal-feedback-evaluation-card-header">
|
||||
<div class="proposal-feedback-evaluation-card-heading">
|
||||
<div class="proposal-feedback-evaluation-card-title">{{row.name}}</div>
|
||||
<div class="proposal-feedback-evaluation-card-code">编号:{{row.code || '--'}}</div>
|
||||
</div>
|
||||
<enum-tag
|
||||
class="proposal-feedback-evaluation-status"
|
||||
v-if="row.instanceState"
|
||||
:value="row.instanceState"
|
||||
name="ProcessInstanceStateEnum"
|
||||
label_key="message"
|
||||
size="small"
|
||||
></enum-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="提案类别">{{row.typeName || '--'}}</table-column>
|
||||
<table-column label="提案人">{{row.createUserName || '--'}}</table-column>
|
||||
<table-column label="代表团">{{row.delegationName || '--'}}</table-column>
|
||||
<table-column label="当前节点">{{row.curTaskName || '--'}}</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row,index)">
|
||||
<van-icon class="proposal-action-icon" name="eye-o"></van-icon>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row,index)">
|
||||
<van-icon class="proposal-action-icon" name="edit"></van-icon>
|
||||
<span>评价</span>
|
||||
</div>
|
||||
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">
|
||||
<van-icon class="proposal-action-icon" name="revoke"></van-icon>
|
||||
<span>撤回</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
</div>
|
||||
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">
|
||||
<i class="fa fa-reply"></i>
|
||||
<span>撤回</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
|
||||
<proposal-info ref="proposalInfoRef">
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">{{formData.taskName}}</div>
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
v-model="formData.tf_feedback_name"
|
||||
name="tf_feedback_name"
|
||||
label="满意度"
|
||||
placeholder="请选择满意度"
|
||||
:rules="[{ required: true, message: '请选择满意度' }]"
|
||||
required
|
||||
is-link
|
||||
@click="showFeedBackPicker = true"
|
||||
></van-field>
|
||||
<van-popup v-model="showFeedBackPicker" position="bottom">
|
||||
<van-picker
|
||||
show-toolbar
|
||||
:columns="dict.type.PROPOSAL_FEEDBACK.map(item => ({text: item.label, value: item.code}))"
|
||||
@confirm="onFeedBackConfirm"
|
||||
@cancel="showFeedBackPicker = false"
|
||||
></van-picker>
|
||||
</van-popup>
|
||||
|
||||
<van-field
|
||||
v-model="formData.tf_opinion"
|
||||
name="tf_opinion"
|
||||
label="审批意见"
|
||||
placeholder="请输入审批意见"
|
||||
:rules="[{ required: true, message: '请填写审批意见' }]"
|
||||
required
|
||||
maxlength="100"
|
||||
show-word-limit
|
||||
></van-field>
|
||||
|
||||
<template v-if="['SATISFIED','FAIRLY_SATISFIED'].includes(formData.tf_feedback)">
|
||||
<van-field
|
||||
v-model="formData.tf_address"
|
||||
name="tf_address"
|
||||
label="通讯地址"
|
||||
placeholder="请输入通讯地址"
|
||||
:rules="[{ required: true, message: '请输入通讯地址' }]"
|
||||
required
|
||||
show-word-limit
|
||||
></van-field>
|
||||
<!--联系电话-->
|
||||
<van-field
|
||||
v-model="formData.tf_phone"
|
||||
name="tf_phone"
|
||||
label="联系电话"
|
||||
placeholder="请输入联系电话"
|
||||
:rules="[{ required: true, message: '请输入联系电话' }]"
|
||||
required
|
||||
show-word-limit
|
||||
></van-field>
|
||||
<!--邮政编码-->
|
||||
<van-field
|
||||
v-model="formData.tf_postcode"
|
||||
name="tf_postcode"
|
||||
label="邮政编码"
|
||||
placeholder="请输入邮政编码"
|
||||
:rules="[{ required: true, message: '请输入邮政编码' }]"
|
||||
required
|
||||
show-word-limit
|
||||
></van-field>
|
||||
</template>
|
||||
</van-form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button type="danger" block @click="$refs.proposalInfoRef.onClose()">取消</van-button>
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">提交</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</proposal-info>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<proposal-task-popup ref="taskPopup" kind="feedbackEvaluation" page-key="proposal-feedback-task" @success="doSearch"></proposal-task-popup>
|
||||
</div>
|
||||
<script nonce="${cspNonce!}">
|
||||
<!--#include("../../common/info.js"){}#-->
|
||||
|
||||
<!--#include("../../common/task-popup.js"){}#-->
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
dicts: ["PROPOSAL_FEEDBACK"],
|
||||
store,
|
||||
components: {"proposal-task-popup": PROPOSAL_TASK_POPUP},
|
||||
data() {
|
||||
return {
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "",
|
||||
pageOrderBy: "",
|
||||
name: null,
|
||||
sessionId: null,
|
||||
approvalText: "0",
|
||||
approval: false
|
||||
},
|
||||
|
||||
sessionOptions: [],
|
||||
formData: {},
|
||||
showApprovalForm: false,
|
||||
|
||||
showFeedBackPicker: false
|
||||
filterOpened: false,
|
||||
approvalOptions: [
|
||||
{text: "未评价", value: "0"},
|
||||
{text: "已评价", value: "1"}
|
||||
],
|
||||
}
|
||||
},
|
||||
components: {
|
||||
"proposal-info": PROPOSAL_INFO
|
||||
},
|
||||
methods: {
|
||||
onReady() {
|
||||
this.listSession()
|
||||
this.listSession(false)
|
||||
},
|
||||
listSession() {
|
||||
|
||||
// 评价状态下拉框使用字符串值展示,查询接口使用布尔值区分已评价和未评价。
|
||||
approvalChange(value) {
|
||||
this.$set(this.pageForm, "approval", value === "1")
|
||||
this.doSearch()
|
||||
},
|
||||
|
||||
// 缓存恢复时只加载届次选项,不覆盖离开列表前的筛选条件和列表快照。
|
||||
listSession(skipDefaultSearch) {
|
||||
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.sessionOptions = [
|
||||
{
|
||||
text: "全部届次",
|
||||
value: null
|
||||
}
|
||||
].concat(res.data.map((v) => ({text: v.fullName, value: v.id})))
|
||||
if (this.sessionOptions.length > 0) {
|
||||
this.pageForm.sessionId = this.sessionOptions[0].value
|
||||
this.doSearch()
|
||||
}
|
||||
this.sessionOptions = [{text: "全部届次", value: null}]
|
||||
.concat(res.data.map((item) => ({text: item.fullName, value: item.id})))
|
||||
if (skipDefaultSearch) return
|
||||
// 届次接口按开始时间倒序返回,首条即最新届次;无届次时继续按全部届次查询。
|
||||
this.$set(this.pageForm, "sessionId", res.data.length > 0 ? res.data[0].id : null)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
onView(row, index) {
|
||||
this.$refs.taskPopup.open(row, "view")
|
||||
},
|
||||
|
||||
onApproval(row) {
|
||||
this.showApprovalForm = true
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
this.formData = {
|
||||
processTaskId: row.taskId,
|
||||
taskName: row.curTaskName,
|
||||
instanceId: row.instanceId
|
||||
}
|
||||
onApproval(row, index) {
|
||||
this.$refs.taskPopup.open(row, "approval")
|
||||
},
|
||||
|
||||
onFeedBackConfirm({value, text}) {
|
||||
this.formData.tf_feedback_name = text
|
||||
this.formData.tf_feedback = value
|
||||
this.showFeedBackPicker = false
|
||||
},
|
||||
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate();
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(async () => {
|
||||
debugger
|
||||
const formData = {
|
||||
...this.formData,
|
||||
submitType: val
|
||||
}
|
||||
// 不满意
|
||||
if (this.formData.tf_feedback === 'DISSATISFIED') {
|
||||
const caseInfo = await this.getCaseInfo(this.formData.instanceId)
|
||||
formData.tf_masterUnitId = caseInfo.tf_masterUnitId
|
||||
}
|
||||
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify(formData)
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.proposalInfoRef.onClose()
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
|
||||
})
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
},
|
||||
// 获取立案信息
|
||||
async getCaseInfo(instId) {
|
||||
const {
|
||||
data,
|
||||
code
|
||||
} = await this.$axios.post('/platform/proposal/feedbackEvaluation/caseInfo', {instId})
|
||||
if (code === 0) {
|
||||
return data
|
||||
}
|
||||
},
|
||||
onRevoke(row) {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
@@ -254,11 +403,21 @@ layout("/layouts/platform_h5.html"){
|
||||
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$set(this.pageForm, "pageNumber", 1)
|
||||
this.$set(this.pageForm, "totalCount", 0)
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
const tab = new URLSearchParams(window.location.search).get("tab")
|
||||
if (tab === "done") {
|
||||
this.$set(this.pageForm, "approval", true)
|
||||
this.$set(this.pageForm, "approvalText", "1")
|
||||
} else if (tab === "todo") {
|
||||
this.$set(this.pageForm, "approval", false)
|
||||
this.$set(this.pageForm, "approvalText", "0")
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
+710
-66
@@ -1,63 +1,640 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<style>
|
||||
<!--#include("../../common/info.css"){}#-->
|
||||
<!--#include("../theme.css"){}#-->
|
||||
|
||||
body {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.proposal-mine-page {
|
||||
min-height: 100vh;
|
||||
padding-bottom: calc(24px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.proposal-mine-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.proposal-mine-page .van-nav-bar__title {
|
||||
color: #172033;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.proposal-mine-page .van-nav-bar .van-icon,
|
||||
.proposal-mine-page .van-nav-bar__text {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.proposal-mine-popup {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.proposal-mine-popup .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.proposal-mine-popup .van-nav-bar .van-icon,
|
||||
.proposal-mine-popup .van-nav-bar__text {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
/* Popup 内固定导航栏不依赖 placeholder 占位,避免遮挡邀请附议筛选框。 */
|
||||
.proposal-invite-popup {
|
||||
display: flex;
|
||||
padding-top: 46px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 邀请附议人弹框固定展示工号、姓名查询入口,清空关键词后恢复完整人员列表。 */
|
||||
.proposal-invite-search {
|
||||
padding: 12px 12px 8px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.proposal-invite-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.proposal-invite-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.proposal-invite-search .van-field__control::placeholder {
|
||||
color: #a7b0bf;
|
||||
}
|
||||
|
||||
/* 邀请状态使用双分段切换,当前状态通过白色底和蓝色短线突出展示。 */
|
||||
.proposal-invite-tabs {
|
||||
padding: 4px 12px 8px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.proposal-invite-tabs .van-tabs__wrap {
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.proposal-invite-tabs .van-tabs__nav {
|
||||
padding: 4px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 14px;
|
||||
background-color: #edf4ff;
|
||||
}
|
||||
|
||||
.proposal-invite-tabs .van-tab {
|
||||
height: 40px;
|
||||
color: #6e7d92;
|
||||
font-size: 14px;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.proposal-invite-tabs .van-tab--active {
|
||||
border-radius: 10px;
|
||||
color: #1989fa;
|
||||
font-weight: 600;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 4px 10px rgba(31, 89, 164, .08);
|
||||
}
|
||||
|
||||
.proposal-invite-tabs .van-tabs__line {
|
||||
bottom: 4px;
|
||||
width: 30px;
|
||||
height: 3px;
|
||||
border-radius: 3px;
|
||||
background-color: #1989fa;
|
||||
}
|
||||
|
||||
/* 人员卡片区域独立滚动,顶部筛选区和底部操作区始终保留在视口内。 */
|
||||
.proposal-invite-scroll {
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
flex: 1;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
/* 人员列表以独立卡片呈现,姓名、工号、单位和勾选区域层级清晰。 */
|
||||
.proposal-invite-list {
|
||||
padding: 0 12px 12px;
|
||||
}
|
||||
|
||||
.proposal-invite-list .van-cell-group {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.proposal-invite-person {
|
||||
min-height: 70px;
|
||||
margin-top: 12px;
|
||||
padding: 12px 14px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 6px 16px rgba(43, 73, 112, .08);
|
||||
}
|
||||
|
||||
.proposal-invite-person::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.proposal-invite-person__title {
|
||||
display: block;
|
||||
color: #253247;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.proposal-invite-person__login-name {
|
||||
color: #79879a;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.proposal-invite-person__unit {
|
||||
display: block;
|
||||
margin-top: 3px;
|
||||
color: #8c99aa;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.proposal-invite-person__checkbox {
|
||||
display: flex;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.proposal-invite-person__checkbox .van-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #4b8cff;
|
||||
border-radius: 50%;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.proposal-invite-person__checkbox .van-checkbox__icon--checked .van-icon {
|
||||
border-color: #1989fa;
|
||||
background-color: #1989fa;
|
||||
}
|
||||
|
||||
/* 分页和邀请按钮沿用同一圆角语言,与人员卡片形成统一的操作区域。 */
|
||||
.proposal-invite-actions {
|
||||
padding: 0 12px calc(12px + env(safe-area-inset-bottom));
|
||||
background-color: #f3f7fd;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.proposal-invite-pagination {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.proposal-invite-pagination .van-pagination__item {
|
||||
min-height: 36px;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 4px 12px rgba(43, 73, 112, .06);
|
||||
}
|
||||
|
||||
.proposal-invite-pagination .van-pagination__item--active,
|
||||
.proposal-invite-pagination .van-pagination__item:not(.van-pagination__item--disabled):active {
|
||||
color: #fff;
|
||||
background-color: #1989fa;
|
||||
}
|
||||
|
||||
.proposal-invite-submit {
|
||||
height: 42px;
|
||||
margin-top: 12px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.proposal-invite-empty {
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* 详情弹框复用项目全屏 Popup 的固定导航结构,内容区域单独滚动。 */
|
||||
.proposal-detail-popup {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.proposal-detail-popup-page {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
padding-top: 46px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.proposal-detail-popup-page .van-nav-bar {
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.proposal-detail-scroll {
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
flex: 1;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.proposal-detail-scroll .proposal-view-main {
|
||||
padding-top: 18px;
|
||||
}
|
||||
|
||||
.proposal-mine-content {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.proposal-mine-sticky {
|
||||
padding: 22px 12px 1px;
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.proposal-mine-search {
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.proposal-mine-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.proposal-mine-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.proposal-mine-search .van-field__control::placeholder {
|
||||
color: #a7b0bf;
|
||||
}
|
||||
|
||||
.proposal-mine-filter {
|
||||
margin: 0 0 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
transition: border-radius .18s ease;
|
||||
}
|
||||
|
||||
.proposal-mine-filter.is-open {
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
.proposal-mine-filter .van-dropdown-menu__bar {
|
||||
height: 44px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.proposal-mine-filter .van-dropdown-menu__item {
|
||||
height: 44px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.proposal-mine-filter .van-dropdown-menu__title {
|
||||
display: inline-flex;
|
||||
height: 44px;
|
||||
align-items: center;
|
||||
line-height: 20px;
|
||||
color: #66758a;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.proposal-mine-filter .van-dropdown-menu__title--active,
|
||||
.proposal-mine-filter .van-dropdown-item__option--active,
|
||||
.proposal-mine-filter .van-dropdown-item__option--active .van-dropdown-item__icon {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.proposal-mine-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
margin: 0 12px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0 0 12px 12px;
|
||||
box-shadow: 0 10px 24px rgba(31, 65, 108, .14);
|
||||
}
|
||||
|
||||
.proposal-mine-filter .van-dropdown-item__option {
|
||||
display: flex;
|
||||
min-height: 48px;
|
||||
padding: 0 16px;
|
||||
align-items: center;
|
||||
color: #46566c;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.proposal-mine-filter .van-dropdown-item__option .van-cell__title {
|
||||
display: flex;
|
||||
min-height: 20px;
|
||||
align-items: center;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.proposal-mine-list {
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.proposal-mine-list .empty-state {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.proposal-mine-empty {
|
||||
display: flex;
|
||||
min-height: 280px;
|
||||
padding: 46px 18px 36px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.proposal-mine-empty img {
|
||||
display: block;
|
||||
width: 86%;
|
||||
max-width: 290px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.proposal-mine-empty__title {
|
||||
margin-top: 14px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.proposal-mine-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.proposal-invite-empty {
|
||||
display: flex;
|
||||
min-height: 300px;
|
||||
padding: 40px 18px 36px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.proposal-invite-empty img {
|
||||
display: block;
|
||||
width: 82%;
|
||||
max-width: 270px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.proposal-invite-empty__title {
|
||||
margin-top: 14px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.proposal-invite-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.proposal-card-header {
|
||||
display: flex;
|
||||
margin-bottom: 7px;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.proposal-card-heading {
|
||||
min-width: 0;
|
||||
padding-right: 10px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.proposal-card-title {
|
||||
overflow: hidden;
|
||||
color: #253247;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.proposal-card-code {
|
||||
margin-top: 1px;
|
||||
color: #9ba6b6;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.proposal-card-status {
|
||||
display: inline-flex;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.proposal-card-status .van-tag,
|
||||
.proposal-card-status--plain {
|
||||
display: inline-flex;
|
||||
min-height: 24px;
|
||||
padding: 3px 9px;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
border: 0;
|
||||
border-radius: 12px;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.proposal-card-status--plain {
|
||||
color: #1989fa;
|
||||
background-color: #eaf4ff;
|
||||
}
|
||||
|
||||
.proposal-mine-page .table-list-container .table-list-item .action-btn .van-icon {
|
||||
margin-right: 6px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
@media (max-width: 350px) {
|
||||
.proposal-mine-content {
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.proposal-mine-sticky {
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="我的提案" placeholder fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<van-search
|
||||
:reverse-color="false"
|
||||
:show-action="false"
|
||||
@search="doSearch"
|
||||
input-align="left"
|
||||
placeholder="请输入提案名称搜索"
|
||||
v-model="pageForm.name"
|
||||
></van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item :multiple="false" :options="sessionOptions" @change="doSearch"
|
||||
v-model="pageForm.sessionId"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</van-sticky>
|
||||
<div class="proposal-mine-page">
|
||||
<van-nav-bar @click-left="handlePageBack" left-arrow left-text="返回" title="我的提案" placeholder fixed></van-nav-bar>
|
||||
|
||||
<table-list api="/platform/proposal/mine/h5/pageData" :page_form.sync="pageForm" @ready="onReady" ref="tableListRef"
|
||||
title="name">
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="提案编号">{{row.code}}</table-column>
|
||||
<table-column label="提案类别">{{row.typeName}}</table-column>
|
||||
<table-column label="提案人">{{row.createUserName}}</table-column>
|
||||
<table-column label="代表团">{{row.delegationName}}</table-column>
|
||||
<table-column label="当前节点">{{ (row.startTaskId) ? row.taskName : '待提交' }}</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span>查看</span>
|
||||
<van-sticky :offset-top="46">
|
||||
<div class="proposal-mine-sticky">
|
||||
<van-search
|
||||
v-model="pageForm.name"
|
||||
class="proposal-mine-search"
|
||||
placeholder="请输入提案名称搜索"
|
||||
shape="round"
|
||||
clearable
|
||||
@search="doSearch"
|
||||
@clear="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu
|
||||
class="proposal-mine-filter"
|
||||
:class="{'is-open': filterOpened}"
|
||||
active-color="#1989fa"
|
||||
:close-on-click-outside="false"
|
||||
:close-on-click-overlay="false"
|
||||
>
|
||||
<van-dropdown-item
|
||||
v-model="pageForm.sessionId"
|
||||
:multiple="false"
|
||||
:options="sessionOptions"
|
||||
@change="doSearch"
|
||||
@open="$set($data, 'filterOpened', true)"
|
||||
@close="$set($data, 'filterOpened', false)"
|
||||
></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskKey === 'startTask' || !row.instanceId"
|
||||
@click="onEdit(row)">
|
||||
<i class="fa fa-edit"></i>
|
||||
<span>编辑</span>
|
||||
</div>
|
||||
<div class="action-btn"
|
||||
v-if="row.taskKey === 'invite' || row.taskKey === 'second'"
|
||||
@click="onInvite(row)">
|
||||
<i class="fa fa-user-plus"></i>
|
||||
<span>邀请附议人</span>
|
||||
</div>
|
||||
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">
|
||||
<i class="fa fa-undo"></i>
|
||||
<span>撤回</span>
|
||||
</div>
|
||||
<div class="action-btn delete" v-if="row.taskKey === 'startTask' || !row.instanceId"
|
||||
@click="onDelete(row)">
|
||||
<i class="fa fa-trash"></i>
|
||||
<span>删除</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
</van-sticky>
|
||||
|
||||
<invite-seconder @refresh="doSearch" ref="inviteSeconderRef"></invite-seconder>
|
||||
<main class="proposal-mine-content">
|
||||
<div class="proposal-mine-list">
|
||||
<div v-if="pageForm.totalCount === 0" class="proposal-mine-empty">
|
||||
<img src="/assets/mobile/img/proposal/proposal-empty.png" alt="暂无提案记录插画">
|
||||
<div class="proposal-mine-empty__title">暂无提案记录</div>
|
||||
<div class="proposal-mine-empty__hint">当前筛选条件下暂时没有提案</div>
|
||||
</div>
|
||||
<table-list api="/platform/proposal/mine/h5/pageData" :page_form.sync="pageForm" @ready="onReady" ref="tableListRef"
|
||||
title="name">
|
||||
<template #header="{index,row}">
|
||||
<div class="proposal-card-header">
|
||||
<div class="proposal-card-heading">
|
||||
<div class="proposal-card-title">{{row.name}}</div>
|
||||
<div class="proposal-card-code">编号:{{row.code || '--'}}</div>
|
||||
</div>
|
||||
<!-- 流程已启动时显示真实实例状态,尚未启动的提案统一标记为待提交。 -->
|
||||
<enum-tag
|
||||
class="proposal-card-status"
|
||||
v-if="row.instanceState"
|
||||
:value="row.instanceState"
|
||||
name="ProcessInstanceStateEnum"
|
||||
label_key="message"
|
||||
size="small"
|
||||
></enum-tag>
|
||||
<span v-else class="proposal-card-status proposal-card-status--plain">待提交</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="提案类别">{{row.typeName || '--'}}</table-column>
|
||||
<table-column label="提案人">{{row.createUserName || '--'}}</table-column>
|
||||
<table-column label="代表团">{{row.delegationName || '--'}}</table-column>
|
||||
<table-column label="当前节点">{{ (row.startTaskId) ? row.taskName : '待提交' }}</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<van-icon name="eye-o"></van-icon>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskKey === 'startTask' || !row.instanceId"
|
||||
@click="onEdit(row)">
|
||||
<van-icon class="proposal-action-icon" name="edit"></van-icon>
|
||||
<span>编辑</span>
|
||||
</div>
|
||||
<div class="action-btn"
|
||||
v-if="row.taskKey === 'invite' || row.taskKey === 'second'"
|
||||
@click="onInvite(row)">
|
||||
<van-icon class="proposal-action-icon" name="friends-o"></van-icon>
|
||||
<span>邀请附议人</span>
|
||||
</div>
|
||||
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">
|
||||
<van-icon class="proposal-action-icon" name="revoke"></van-icon>
|
||||
<span>撤回</span>
|
||||
</div>
|
||||
<div class="action-btn delete" v-if="row.taskKey === 'startTask' || !row.instanceId"
|
||||
@click="onDelete(row)">
|
||||
<van-icon class="proposal-action-icon" name="delete-o"></van-icon>
|
||||
<span>删除</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<proposal-info ref="proposalInfoRef"></proposal-info>
|
||||
<van-popup
|
||||
v-model="detailVisible"
|
||||
class="proposal-mine-popup proposal-detail-popup"
|
||||
position="right"
|
||||
:close-on-click-overlay="false"
|
||||
safe-area-inset-bottom>
|
||||
<div class="proposal-detail-popup-page">
|
||||
<van-nav-bar
|
||||
title="提案详情"
|
||||
left-arrow
|
||||
left-text="返回"
|
||||
fixed
|
||||
@click-left="closeHistoryLayer('detail')">
|
||||
</van-nav-bar>
|
||||
<div class="proposal-detail-scroll">
|
||||
<proposal-info v-if="detailVisible && detailBizId" :biz-id="detailBizId" :visible="detailVisible"></proposal-info>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
|
||||
<invite-seconder
|
||||
:visible="inviteVisible"
|
||||
:confirm-visible="inviteConfirmVisible"
|
||||
@close="closeHistoryLayer('invite')"
|
||||
@open-confirm="openHistoryLayer('invite-confirm')"
|
||||
@close-confirm="closeHistoryLayer('invite-confirm')"
|
||||
@confirm-invite="confirmInvite"
|
||||
@refresh="doSearch"
|
||||
ref="inviteSeconderRef">
|
||||
</invite-seconder>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script nonce="${cspNonce!}">
|
||||
@@ -68,8 +645,8 @@ layout("/layouts/platform_h5.html"){
|
||||
el: "#app",
|
||||
store,
|
||||
components: {
|
||||
"invite-seconder": PROPOSAL_INVITE_SECONDER_COMPONENT,
|
||||
"proposal-info": PROPOSAL_INFO
|
||||
"proposal-info": PROPOSAL_INFO,
|
||||
"invite-seconder": PROPOSAL_INVITE_SECONDER_COMPONENT
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -78,34 +655,85 @@ layout("/layouts/platform_h5.html"){
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
searchKeyword: "",
|
||||
pageOrderName: "",
|
||||
pageOrderBy: "",
|
||||
sessionId: null
|
||||
},
|
||||
|
||||
sessionOptions: [],
|
||||
infoShow: false
|
||||
filterOpened: false,
|
||||
detailVisible: false,
|
||||
detailBizId: "",
|
||||
inviteVisible: false,
|
||||
inviteConfirmVisible: false,
|
||||
historyLayerPageKey: "proposal-mine-h5"
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 注册“我的提案”页面弹层历史。
|
||||
* pageKey 使用固定页面标识;回调参数 stack 为当前弹层名称数组,无返回值。
|
||||
*/
|
||||
registerHistoryLayers() {
|
||||
if (!window.h5HistoryLayerManager) return
|
||||
window.h5HistoryLayerManager.register(this.historyLayerPageKey, (stack) => {
|
||||
this.syncHistoryLayerStack(stack)
|
||||
})
|
||||
},
|
||||
|
||||
// 根据浏览器历史栈同步详情、邀请附议和邀请确认弹层的显示状态。
|
||||
syncHistoryLayerStack(stack) {
|
||||
this.$set(this, "detailVisible", stack.includes("detail"))
|
||||
this.$set(this, "inviteVisible", stack.includes("invite"))
|
||||
this.$set(this, "inviteConfirmVisible", stack.includes("invite-confirm"))
|
||||
},
|
||||
|
||||
// 打开弹层时同步增加当前地址的浏览器历史记录。
|
||||
openHistoryLayer(layerName) {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open(layerName)) return
|
||||
this.setHistoryLayerVisible(layerName, true)
|
||||
},
|
||||
|
||||
// 主动关闭弹层时回退对应历史记录,afterClose 在历史状态同步后执行。
|
||||
closeHistoryLayer(layerName, afterClose = null) {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.close(layerName, afterClose)) return
|
||||
this.setHistoryLayerVisible(layerName, false)
|
||||
if (typeof afterClose === "function") afterClose()
|
||||
},
|
||||
|
||||
setHistoryLayerVisible(layerName, visible) {
|
||||
if (layerName === "detail") this.$set(this, "detailVisible", visible)
|
||||
if (layerName === "invite") this.$set(this, "inviteVisible", visible)
|
||||
if (layerName === "invite-confirm") this.$set(this, "inviteConfirmVisible", visible)
|
||||
},
|
||||
|
||||
// 页面返回时优先关闭最上层弹框,没有弹框时再返回上一业务页面。
|
||||
handlePageBack() {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.stack.length) {
|
||||
window.h5HistoryLayerManager.close()
|
||||
return
|
||||
}
|
||||
this.historyBack()
|
||||
},
|
||||
|
||||
listSession() {
|
||||
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.sessionOptions = res.data
|
||||
.map((v) => ({
|
||||
this.sessionOptions = [{text: "全部届次", value: null}]
|
||||
.concat(res.data.map((v) => ({
|
||||
text: v.fullName,
|
||||
value: v.id
|
||||
}))
|
||||
.concat([{text: "全部届次", value: null}])
|
||||
if (this.sessionOptions.length > 0) {
|
||||
this.pageForm.sessionId = this.sessionOptions[0].value
|
||||
this.doSearch()
|
||||
}
|
||||
})))
|
||||
// “全部届次”固定展示在首位,但首次查询仍默认使用接口倒序返回的最新届次。
|
||||
this.$set(this.pageForm, "sessionId", res.data.length > 0 ? res.data[0].id : null)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
this.$set(this, "detailBizId", row.id)
|
||||
this.openHistoryLayer("detail")
|
||||
},
|
||||
|
||||
onEdit(row) {
|
||||
@@ -155,14 +783,30 @@ layout("/layouts/platform_h5.html"){
|
||||
onInvite(row) {
|
||||
this.$axios.post("/platform/proposal/mine/inviteCheck", {id: row.id}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.inviteSeconderRef.onOpen(row)
|
||||
this.$refs.inviteSeconderRef.prepare(row)
|
||||
this.openHistoryLayer("invite")
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 邀请确认后先关闭确认层,再提交邀请,避免浏览器历史中残留已关闭的 Dialog。
|
||||
confirmInvite() {
|
||||
this.closeHistoryLayer("invite-confirm", () => {
|
||||
this.$refs.inviteSeconderRef.submitInvite()
|
||||
})
|
||||
},
|
||||
|
||||
onReady() {
|
||||
this.listSession()
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.registerHistoryLayers()
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (window.h5HistoryLayerManager) {
|
||||
window.h5HistoryLayerManager.unregister(this.historyLayerPageKey)
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
+184
-99
@@ -1,133 +1,205 @@
|
||||
const PROPOSAL_INVITE_SECONDER_COMPONENT = {
|
||||
template: `
|
||||
<van-action-sheet v-model="visible" title="邀请附议人" class="height100">
|
||||
<van-search
|
||||
v-model="pageForm.searchKeyword"
|
||||
:show-action="false"
|
||||
placeholder="请输入工号或者姓名查询"
|
||||
@search="doSearch"
|
||||
></van-search>
|
||||
<van-tabs v-model="isInvite" @click="isInviteClick">
|
||||
<van-tab title="已邀请" name="1"></van-tab>
|
||||
<van-tab title="可邀请" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
|
||||
<van-checkbox-group v-model="tableSelection" v-if="tableData && tableData.length>0">
|
||||
<van-cell-group >
|
||||
template: /*language=HTML*/ `
|
||||
<van-popup
|
||||
:value="visible"
|
||||
class="proposal-mine-popup proposal-invite-popup"
|
||||
position="right"
|
||||
:close-on-click-overlay="false"
|
||||
safe-area-inset-bottom>
|
||||
<van-nav-bar
|
||||
title="邀请附议人"
|
||||
left-arrow
|
||||
left-text="返回"
|
||||
fixed
|
||||
@click-left="$emit('close')">
|
||||
</van-nav-bar>
|
||||
|
||||
<van-search
|
||||
v-model="pageForm.searchKeyword"
|
||||
class="proposal-invite-search"
|
||||
:show-action="false"
|
||||
shape="round"
|
||||
clearable
|
||||
placeholder="请输入工号或者姓名查询"
|
||||
@search="doSearch"
|
||||
@clear="doSearch">
|
||||
</van-search>
|
||||
<van-tabs v-model="isInvite" class="proposal-invite-tabs" @click="isInviteClick">
|
||||
<van-tab title="已邀请" name="1"></van-tab>
|
||||
<van-tab title="可邀请" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
|
||||
<div class="proposal-invite-scroll" v-if="tableData && tableData.length > 0">
|
||||
<van-checkbox-group class="proposal-invite-list" v-model="tableSelection">
|
||||
<van-cell-group>
|
||||
<van-cell
|
||||
v-for="(item, index) in tableData"
|
||||
clickable
|
||||
:key="item.loginName"
|
||||
@click="tableRowToggle(index)"
|
||||
>
|
||||
<span slot="title">
|
||||
{{item.userName}}
|
||||
({{item.loginName}})
|
||||
</span>
|
||||
<span slot="label" class="font-size0 van-color-text-assist">
|
||||
{{item.unitName}}
|
||||
</span>
|
||||
<van-checkbox
|
||||
:name="item"
|
||||
:ref="'checkboxes'+item.loginName"
|
||||
class="proposal-invite-person"
|
||||
v-for="(item, index) in tableData"
|
||||
clickable
|
||||
:key="item.loginName"
|
||||
@click="tableRowToggle(index)">
|
||||
<span slot="title" class="proposal-invite-person__title">
|
||||
{{item.userName}} <span class="proposal-invite-person__login-name">({{item.loginName}})</span>
|
||||
</span>
|
||||
<span slot="label" class="proposal-invite-person__unit">
|
||||
{{item.unitName}}
|
||||
</span>
|
||||
<van-checkbox
|
||||
:name="item"
|
||||
:ref="'checkboxes' + item.loginName"
|
||||
class="proposal-invite-person__checkbox"
|
||||
slot="right-icon"
|
||||
v-if="!pageForm.isInvite"></van-checkbox>
|
||||
</van-cell>
|
||||
@click.stop
|
||||
v-if="!pageForm.isInvite">
|
||||
</van-checkbox>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
<div class="p10">
|
||||
<van-pagination
|
||||
v-model="pageForm.pageNumber"
|
||||
:total-items="pageForm.totalCount"
|
||||
:items-per-page="pageForm.pageSize"
|
||||
@change="pageData"
|
||||
></van-pagination>
|
||||
<van-button @click="invite" type="primary" block :disabled="pageForm.isInvite" class="mt10">邀请</van-button>
|
||||
</div>
|
||||
</van-checkbox-group>
|
||||
<van-empty v-else :figure="2"></van-empty>
|
||||
</van-action-sheet>
|
||||
`,
|
||||
</div>
|
||||
|
||||
<!-- 空状态提示随“已邀请 / 可邀请”标签切换,便于用户判断当前无数据的具体范围。 -->
|
||||
<div v-else class="proposal-invite-empty">
|
||||
<img src="/assets/mobile/img/proposal/proposal-empty.png" alt="暂无附议人插画">
|
||||
<div class="proposal-invite-empty__title">暂无附议人</div>
|
||||
<div class="proposal-invite-empty__hint">
|
||||
{{ isInvite === "1" ? "当前暂无已邀请的附议人" : "当前暂无可邀请的附议人" }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="proposal-invite-actions" v-if="tableData && tableData.length > 0">
|
||||
<van-pagination
|
||||
class="proposal-soft-pagination proposal-invite-pagination"
|
||||
v-model="pageForm.pageNumber"
|
||||
:total-items="pageForm.totalCount"
|
||||
:items-per-page="pageForm.pageSize"
|
||||
@change="pageData">
|
||||
</van-pagination>
|
||||
<van-button
|
||||
@click="invite"
|
||||
type="primary"
|
||||
block
|
||||
:disabled="pageForm.isInvite"
|
||||
class="proposal-soft-button proposal-invite-submit">
|
||||
邀请
|
||||
</van-button>
|
||||
</div>
|
||||
|
||||
<van-dialog
|
||||
:value="confirmVisible"
|
||||
title="提示"
|
||||
:message="confirmMessage"
|
||||
show-cancel-button
|
||||
@confirm="$emit('confirm-invite')"
|
||||
@cancel="$emit('close-confirm')">
|
||||
</van-dialog>
|
||||
</van-popup>
|
||||
`,
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
confirmVisible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
secondedNum: 0,
|
||||
record: {},
|
||||
tableData: [],
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 5,
|
||||
pageSize: 6,
|
||||
totalCount: 0,
|
||||
pageOrderName: "",
|
||||
pageOrderBy: "",
|
||||
isInvite: false,
|
||||
searchKeyword: null
|
||||
},
|
||||
config: {},
|
||||
isInvite: "0",
|
||||
tableSelection: []
|
||||
tableSelection: [],
|
||||
confirmMessage: ""
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
visible(value) {
|
||||
if (!value || !this.record.id) return
|
||||
this.getConfig().then(() => {
|
||||
this.pageData()
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async onOpen(record) {
|
||||
this.visible = true
|
||||
this.record = record
|
||||
await this.getConfig()
|
||||
this.pageData()
|
||||
|
||||
|
||||
},
|
||||
detail(id) {
|
||||
/**
|
||||
* 准备邀请附议弹框数据。
|
||||
* record 为列表当前提案对象,至少包含 id 和 sessionId;该方法只缓存提案并重置查询条件,无返回值。
|
||||
*/
|
||||
prepare(record) {
|
||||
this.$set(this, "record", record || {})
|
||||
this.$set(this, "isInvite", "0")
|
||||
this.$set(this, "tableSelection", [])
|
||||
this.$set(this.pageForm, "pageNumber", 1)
|
||||
this.$set(this.pageForm, "isInvite", false)
|
||||
this.$set(this.pageForm, "searchKeyword", null)
|
||||
},
|
||||
|
||||
// 校验勾选结果后打开确认 Dialog,实际提交在确认并回退 Dialog 历史层后执行。
|
||||
invite() {
|
||||
if (this.tableSelection.length === 0) {
|
||||
this.$toast("请先选择附议人后在点击邀请")
|
||||
this.$toast("请先选择附议人后再点击邀请")
|
||||
return
|
||||
}
|
||||
const userNames = [...new Set(this.tableSelection.map((item) => item.userName))]
|
||||
this.$set(this, "confirmMessage", "您确定要邀请" + userNames.join("、") + "代表附议吗?")
|
||||
this.$emit("open-confirm")
|
||||
},
|
||||
|
||||
const loginNames = [...new Set(this.tableSelection.map((s) => s.loginName))]
|
||||
const userName = [...new Set(this.tableSelection.map((s) => s.userName))]
|
||||
|
||||
console.log(this.tableSelection)
|
||||
|
||||
this.$dialog.confirm({
|
||||
title: '提示',
|
||||
message: "您确定要邀请" + userName.join("、") + "代表附议吗?",
|
||||
}).then(() => {
|
||||
this.$axios.post("/platform/proposal/mine/inviteSeconder", {
|
||||
proposalId: this.record.id,
|
||||
seconders: JSON.stringify(loginNames)
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.pageData()
|
||||
this.$toast.success(res.msg)
|
||||
this.tableSelection = []
|
||||
// this.visible = false
|
||||
this.$emit("refresh", null)
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
|
||||
/**
|
||||
* 提交邀请附议人。
|
||||
* 参数 proposalId 为当前提案主键,seconders 为已勾选人员工号数组;接口返回 Result,code 为 0 表示邀请成功。
|
||||
*/
|
||||
submitInvite() {
|
||||
const loginNames = [...new Set(this.tableSelection.map((item) => item.loginName))]
|
||||
this.$axios.post("/platform/proposal/mine/inviteSeconder", {
|
||||
proposalId: this.record.id,
|
||||
seconders: JSON.stringify(loginNames)
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.pageData()
|
||||
this.$toast.success(res.msg)
|
||||
this.$set(this, "tableSelection", [])
|
||||
this.$emit("refresh")
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 查询邀请附议人列表。
|
||||
* 参数包含当前提案 ID、届次 ID、邀请状态、关键词及分页条件;返回分页对象并更新列表和总数。
|
||||
*/
|
||||
pageData() {
|
||||
this.$axios.post("/platform/proposal/mine/listSeconder", {
|
||||
...this.pageForm,
|
||||
sessionId: this.record.sessionId,
|
||||
proposalId: this.record.id
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$set(this, "tableData", res.data.list || [])
|
||||
this.$set(this.pageForm, "totalCount", res.data.totalCount || 0)
|
||||
this.echoCheckBox()
|
||||
}
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.tableData = res.data.list
|
||||
this.pageForm.totalCount = res.data.totalCount
|
||||
this.echoCheckBox()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 翻页回显勾选
|
||||
// 翻页后回显当前已勾选的附议人。
|
||||
echoCheckBox() {
|
||||
this.$nextTick(() => {
|
||||
this.tableData.forEach((item) => {
|
||||
const checkboxRef = this.$refs['checkboxes' + item.loginName]
|
||||
if (checkboxRef && this.tableSelection.map((s) => s.loginName).includes(item.loginName)) {
|
||||
const checkboxRef = this.$refs["checkboxes" + item.loginName]
|
||||
if (checkboxRef && this.tableSelection.map((selected) => selected.loginName).includes(item.loginName)) {
|
||||
checkboxRef[0].toggle()
|
||||
}
|
||||
})
|
||||
@@ -135,24 +207,37 @@ const PROPOSAL_INVITE_SECONDER_COMPONENT = {
|
||||
},
|
||||
|
||||
doSearch() {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.$set(this.pageForm, "pageNumber", 1)
|
||||
this.pageData()
|
||||
},
|
||||
|
||||
isInviteClick(index, title) {
|
||||
this.pageForm.isInvite = index === "1"
|
||||
isInviteClick(name) {
|
||||
this.$set(this.pageForm, "isInvite", name === "1")
|
||||
this.doSearch()
|
||||
},
|
||||
|
||||
/**
|
||||
* 点击人员卡片时切换对应的附议人勾选状态。
|
||||
* index 为当前页人员索引;已邀请状态或找不到对应复选框时不处理,无返回值。
|
||||
*/
|
||||
tableRowToggle(index) {
|
||||
console.log(index)
|
||||
if (this.pageForm.isInvite || index < 0) return
|
||||
const item = this.tableData[index]
|
||||
const checkboxRef = item ? this.$refs["checkboxes" + item.loginName] : null
|
||||
if (!checkboxRef || !checkboxRef[0]) return
|
||||
checkboxRef[0].toggle()
|
||||
},
|
||||
|
||||
async getConfig() {
|
||||
const {code, data} = await this.$axios.post("/platform/proposal/common/config")
|
||||
if (code === 0) {
|
||||
this.config = data
|
||||
}
|
||||
/**
|
||||
* 查询提案附议配置。
|
||||
* 接口无业务参数,返回 ProposalConfig 配置对象;Promise 用于确保配置完成后再查询人员列表。
|
||||
*/
|
||||
getConfig() {
|
||||
return this.$axios.post("/platform/proposal/common/config").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$set(this, "config", res.data || {})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+82
-179
@@ -1,195 +1,98 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<style>
|
||||
body { background-color: #f3f7fd; }
|
||||
.proposal-school-leader-page { min-height: 100vh; padding-bottom: calc(24px + env(safe-area-inset-bottom)); box-sizing: border-box; background-color: #f3f7fd; }
|
||||
.proposal-school-leader-page .van-nav-bar { background-color: #fff; }
|
||||
.proposal-school-leader-page .van-nav-bar__title { color: #172033; font-size: 16px; font-weight: 600; }
|
||||
.proposal-school-leader-page .van-nav-bar .van-icon, .proposal-school-leader-page .van-nav-bar__text { color: #1989fa; }
|
||||
.proposal-school-leader-content { padding: 0 12px; }
|
||||
.proposal-school-leader-sticky { padding: 22px 12px 1px; box-sizing: border-box; background-color: #f3f7fd; }
|
||||
.proposal-school-leader-search { margin: 0 0 8px; padding: 0; overflow: hidden; border-radius: 12px; background-color: #fff; box-shadow: 0 5px 16px rgba(43, 73, 112, .1); }
|
||||
.proposal-school-leader-search .van-search__content { height: 42px; padding-left: 12px; align-items: center; border-radius: 12px; background-color: #fff; }
|
||||
.proposal-school-leader-search .van-field__control { color: #263548; font-size: 14px; }
|
||||
.proposal-school-leader-search .van-field__control::placeholder { color: #a7b0bf; }
|
||||
.proposal-school-leader-filter { margin: 0 0 10px; overflow: hidden; border-radius: 10px; box-shadow: 0 5px 16px rgba(43, 73, 112, .08); transition: border-radius .18s ease; }
|
||||
.proposal-school-leader-filter.is-open { border-radius: 10px 10px 0 0; }
|
||||
.proposal-school-leader-filter .van-dropdown-menu__bar, .proposal-school-leader-filter .van-dropdown-menu__item, .proposal-school-leader-filter .van-dropdown-menu__title { height: 44px; }
|
||||
.proposal-school-leader-filter .van-dropdown-menu__bar { box-shadow: none; }
|
||||
.proposal-school-leader-filter .van-dropdown-menu__item, .proposal-school-leader-filter .van-dropdown-menu__title { align-items: center; }
|
||||
.proposal-school-leader-filter .van-dropdown-menu__item { justify-content: center; }
|
||||
.proposal-school-leader-filter .van-dropdown-menu__title { display: inline-flex; color: #66758a; font-size: 14px; line-height: 20px; }
|
||||
.proposal-school-leader-filter .van-dropdown-menu__title--active, .proposal-school-leader-filter .van-dropdown-item__option--active, .proposal-school-leader-filter .van-dropdown-item__option--active .van-dropdown-item__icon { color: #1989fa; }
|
||||
.proposal-school-leader-filter .van-dropdown-menu__title--down::after { border-color: transparent transparent #1989fa #1989fa; }
|
||||
.proposal-school-leader-filter .van-dropdown-item__content { width: calc(100% - 24px); margin: 0 12px; overflow: hidden; box-sizing: border-box; border-radius: 0 0 12px 12px; box-shadow: 0 10px 24px rgba(31, 65, 108, .14); }
|
||||
.proposal-school-leader-filter .van-dropdown-item__option { display: flex; min-height: 48px; padding: 0 16px; align-items: center; color: #46566c; font-size: 14px; }
|
||||
.proposal-school-leader-filter .van-cell::after { right: 16px; left: 16px; }
|
||||
.proposal-school-leader-list .empty-state { display: none; }
|
||||
.proposal-school-leader-empty { display: flex; min-height: 280px; padding: 46px 18px 36px; align-items: center; justify-content: center; flex-direction: column; box-sizing: border-box; text-align: center; }
|
||||
.proposal-school-leader-empty img { display: block; width: 86%; max-width: 290px; height: auto; object-fit: contain; }
|
||||
.proposal-school-leader-empty__title { margin-top: 14px; color: #50627a; font-size: 15px; line-height: 22px; font-weight: 600; }
|
||||
.proposal-school-leader-empty__hint { margin-top: 5px; color: #9aa7b8; font-size: 12px; line-height: 18px; }
|
||||
@media (max-width: 350px) { .proposal-school-leader-content, .proposal-school-leader-sticky { padding-right: 10px; padding-left: 10px; } }
|
||||
</style>
|
||||
<style id="style-proposal-school-leader-h5">
|
||||
<!--#include("../../common/info.css"){}#-->
|
||||
<!--#include("../theme.css"){}#-->
|
||||
</style>
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="分管校领导审批" placeholder fixed></van-nav-bar>
|
||||
<div class="proposal-school-leader-page">
|
||||
<van-nav-bar @click-left="handlePageBack" left-arrow left-text="返回" title="分管校领导审批" placeholder fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<van-search
|
||||
v-model="pageForm.name"
|
||||
:show-action="false"
|
||||
:reverse-color="false"
|
||||
input-align="left"
|
||||
placeholder="请输入提案名称搜索"
|
||||
@search="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions" :multiple="false"
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
<div class="proposal-school-leader-sticky">
|
||||
<van-search v-model="pageForm.name" class="proposal-school-leader-search" placeholder="请输入提案名称搜索" shape="round" clearable @search="doSearch" @clear="doSearch"></van-search>
|
||||
<van-dropdown-menu class="proposal-school-leader-filter" :class="{'is-open': filterOpened}" active-color="#1989fa" :close-on-click-outside="false" :close-on-click-overlay="false"><van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions" :multiple="false" @change="doSearch" @open="setFilterOpened(true)" @close="setFilterOpened(false)"></van-dropdown-item><van-dropdown-item v-model="pageForm.approvalText" :options="approvalOptions" :multiple="false" @change="approvalChange" @open="setFilterOpened(true)" @close="setFilterOpened(false)"></van-dropdown-item></van-dropdown-menu>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<table-list api="/platform/proposal/schoolLeaderApproval/pageData" :page_form.sync="pageForm" @ready="onReady"
|
||||
ref="tableListRef"
|
||||
title="name">
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="提案编号">{{row.code}}</table-column>
|
||||
<table-column label="提案类别">{{row.typeName}}</table-column>
|
||||
<table-column label="提案人">{{row.createUserName}}</table-column>
|
||||
<table-column label="代表团">{{row.delegationName}}</table-column>
|
||||
<table-column label="当前节点">{{row.curTaskName}}</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
|
||||
<i class="fa fa-edit"></i>
|
||||
<span>审核</span>
|
||||
</div>
|
||||
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">
|
||||
<i class="fa fa-reply"></i>
|
||||
<span>撤回</span>
|
||||
</div>
|
||||
<main class="proposal-school-leader-content"><div class="proposal-school-leader-list">
|
||||
<!-- 列表无记录时展示与团长审核一致的提案专用空状态。 -->
|
||||
<div v-if="pageForm.totalCount === 0" class="proposal-school-leader-empty"><img src="/assets/mobile/img/proposal/proposal-empty.png" alt="暂无提案记录插画"><div class="proposal-school-leader-empty__title">暂无提案记录</div><div class="proposal-school-leader-empty__hint">当前筛选条件下暂时没有提案</div></div>
|
||||
<table-list api="/platform/proposal/schoolLeaderApproval/pageData" :page_form.sync="pageForm" @ready="onReady" ref="tableListRef" title="name">
|
||||
<template v-slot="{row}"><table-column label="提案编号">{{row.code}}</table-column><table-column label="提案类别">{{row.typeName}}</table-column><table-column label="提案人">{{row.createUserName}}</table-column><table-column label="代表团">{{row.delegationName}}</table-column><table-column label="当前节点">{{row.curTaskName}}</table-column></template>
|
||||
<template #actions="{row}">
|
||||
<div class="action-btn" @click="onView(row)"><van-icon class="proposal-action-icon" name="eye-o"></van-icon><span>查看</span></div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)"><van-icon class="proposal-action-icon" name="edit"></van-icon><span>审核</span></div>
|
||||
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)"><van-icon class="proposal-action-icon" name="revoke"></van-icon><span>撤回</span></div>
|
||||
</template>
|
||||
</table-list>
|
||||
|
||||
<proposal-info ref="proposalInfoRef">
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">{{formData.taskName}}</div>
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
v-model="formData.tf_opinion"
|
||||
name="tf_opinion"
|
||||
label="审批意见"
|
||||
placeholder="请输入审批意见"
|
||||
:rules="[{ required: true, message: '请填写审批意见' }]"
|
||||
required
|
||||
maxlength="100"
|
||||
show-word-limit
|
||||
></van-field>
|
||||
</van-form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button type="danger" block @click="handleTaskAction('back')">退回答复</van-button>
|
||||
<van-button type="primary" block @click="handleTaskAction('agree')">同意答复</van-button>
|
||||
</div>
|
||||
</div></main>
|
||||
<van-popup v-model="detailVisible" position="right" class="proposal-full-popup" :close-on-click-overlay="false" get-container="#app">
|
||||
<div class="proposal-full-popup__page"><van-nav-bar @click-left="closeDetail" left-arrow left-text="返回" :title="popupTitle" placeholder fixed></van-nav-bar>
|
||||
<div class="proposal-full-popup__scroll"><proposal-info v-if="detailBizId" :biz-id="detailBizId" :visible="detailVisible">
|
||||
<div v-if="isApproval"><van-form ref="formRef"><section class="proposal-view-card"><h2 class="proposal-view-card__title">审批意见<span class="proposal-audit-card__required">*</span></h2><van-field v-model="formData.tf_opinion" class="proposal-audit-field" name="tf_opinion" type="textarea" rows="6" label="" placeholder="请输入审批意见" :rules="[{required:true,message:'请填写审批意见'}]" required maxlength="100" show-word-limit></van-field></section></van-form>
|
||||
<div class="proposal-popup-form-actions"><van-button type="danger" block :loading="formLoading" class="proposal-soft-button proposal-soft-button--danger" @click="handleTaskAction('back')">退回答复</van-button><van-button type="primary" block :loading="formLoading" class="proposal-soft-button" @click="handleTaskAction('agree')">同意答复</van-button></div>
|
||||
</div>
|
||||
</proposal-info></div>
|
||||
</div>
|
||||
</proposal-info>
|
||||
|
||||
</van-popup>
|
||||
<van-dialog :value="submitConfirmVisible" title="提示" message="您确定要提交吗?" show-cancel-button @confirm="confirmTaskAction" @cancel="closeSubmitConfirm"></van-dialog>
|
||||
</div>
|
||||
</div>
|
||||
<script nonce="${cspNonce!}">
|
||||
<!--#include("../../common/info.js"){}#-->
|
||||
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
data() {
|
||||
return {
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
name: null,
|
||||
sessionId: null,
|
||||
approvalText: "0",
|
||||
approval: false
|
||||
},
|
||||
|
||||
sessionOptions: [],
|
||||
formData: {},
|
||||
showApprovalForm: false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
"proposal-info": PROPOSAL_INFO
|
||||
},
|
||||
new Vue({
|
||||
el: "#app", store, components: {"proposal-info": PROPOSAL_INFO},
|
||||
data() { return {pageForm:{pageNumber:1,pageSize:10,totalCount:0,name:null,sessionId:null,approvalText:"0",approval:false},sessionOptions:[],filterOpened:false,approvalOptions:[{text:"未审核",value:"0"},{text:"已审核",value:"1"}],detailVisible:false,detailBizId:"",action:"view",formData:{},formLoading:false,submitConfirmVisible:false,pendingSubmitType:"",historyLayerPageKey:"proposal-school-leader-approval"} },
|
||||
computed: {isApproval() { return this.action === "approval" }, popupTitle() { return this.isApproval ? "分管校领导审批" : "提案详情" }},
|
||||
methods: {
|
||||
onReady() {
|
||||
this.listSession()
|
||||
},
|
||||
listSession() {
|
||||
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.sessionOptions = [
|
||||
{
|
||||
text: "全部届次",
|
||||
value: null
|
||||
}
|
||||
].concat(res.data.map((v) => ({text: v.fullName, value: v.id})))
|
||||
if (this.sessionOptions.length > 0) {
|
||||
this.pageForm.sessionId = this.sessionOptions[0].value
|
||||
this.doSearch()
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
},
|
||||
|
||||
onApproval(row) {
|
||||
this.showApprovalForm = true
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
this.formData = {
|
||||
processTaskId: row.taskId,
|
||||
taskKey: row.taskKey,
|
||||
taskName: row.taskName,
|
||||
proposalId: row.id
|
||||
}
|
||||
},
|
||||
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate();
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
|
||||
const formData = {
|
||||
...this.formData,
|
||||
tf_approval: val
|
||||
}
|
||||
delete formData.taskKey
|
||||
delete formData.taskName
|
||||
|
||||
|
||||
this.$axios.post("/platform/proposal/schoolLeaderApproval/executeTask", {
|
||||
data: JSON.stringify(formData)
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.proposalInfoRef.onClose()
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
|
||||
})
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
onRevoke(row){
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要撤回吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
},
|
||||
}
|
||||
registerHistoryLayers() { window.h5HistoryLayerManager.register(this.historyLayerPageKey, (stack) => { this.$set(this,"detailVisible",stack.includes("detail")); this.$set(this,"submitConfirmVisible",stack.includes("submit-confirm")) }) },
|
||||
openHistoryLayer(name) { window.h5HistoryLayerManager.open(name) },
|
||||
closeHistoryLayer(name,callback) { window.h5HistoryLayerManager.close(name,callback) },
|
||||
handlePageBack() { if (window.h5HistoryLayerManager.stack.length) { window.h5HistoryLayerManager.close(); return } historyBack() },
|
||||
closeDetail() { this.closeHistoryLayer("detail") }, closeSubmitConfirm() { this.closeHistoryLayer("submit-confirm") },
|
||||
setFilterOpened(value) { this.$set(this,"filterOpened",value) },
|
||||
approvalChange(value) { this.$set(this.pageForm,"approval",value === "1"); this.doSearch() }, onReady() { this.listSession() },
|
||||
listSession() { this.$axios.post("/platform/proposal/common/listSession").then((res) => { if (res.code !== 0) return; this.$set(this,"sessionOptions",[{text:"全部届次",value:null}].concat(res.data.map((v) => ({text:v.fullName,value:v.id})))); this.$set(this.pageForm,"sessionId",res.data.length > 0 ? res.data[0].id : null); this.doSearch() }) },
|
||||
onView(row) { this.$set(this,"detailBizId",row.id); this.$set(this,"action","view"); this.$set(this,"formData",{}); this.openHistoryLayer("detail") },
|
||||
onApproval(row) { this.$set(this,"detailBizId",row.id); this.$set(this,"action","approval"); this.$set(this,"formData",{processTaskId:row.taskId,taskKey:row.taskKey || "",taskName:row.taskName || "分管校领导审批",proposalId:row.id,tf_opinion:""}); this.openHistoryLayer("detail") },
|
||||
/** val 为 back 或 agree,确认后提交分管校领导审批接口。 */
|
||||
handleTaskAction(val) { this.$refs.formRef.validate().then(() => { this.$set(this,"pendingSubmitType",val); this.openHistoryLayer("submit-confirm") }).catch(() => {}) },
|
||||
confirmTaskAction() { const submitData={...this.formData,tf_approval:this.pendingSubmitType}; delete submitData.taskKey; delete submitData.taskName; this.$set(this,"formLoading",true); this.$axios.post("/platform/proposal/schoolLeaderApproval/executeTask",{data:JSON.stringify(submitData)}).then((res) => { if (res && res.code === 0) { this.$toast.success(res.msg); window.h5HistoryLayerManager.closeAll(() => this.doSearch()) } }).finally(() => { this.$set(this,"formLoading",false) }) },
|
||||
onRevoke(row) { this.$dialog.confirm({title:"提示",message:"您确定要撤回吗?"}).then(() => this.$axios.post("/flow/common/revokeTask",{taskId:row.taskId})).then((res) => { if (res && res.code === 0) { this.$toast.success(res.msg); this.doSearch() } }).catch(() => {}) },
|
||||
doSearch() { this.$nextTick(() => { this.$set(this.pageForm,"pageNumber",1); this.$set(this.pageForm,"totalCount",0); this.$refs.tableListRef.doSearch() }) }
|
||||
},
|
||||
created() { this.registerHistoryLayers() }, beforeDestroy() { window.h5HistoryLayerManager.unregister(this.historyLayerPageKey) }
|
||||
})
|
||||
</script>
|
||||
<!--#
|
||||
|
||||
+573
-141
@@ -1,98 +1,455 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<style>
|
||||
<!--#include("../../common/info.css"){}#-->
|
||||
<!--#include("../theme.css"){}#-->
|
||||
|
||||
body {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.proposal-seconded-page {
|
||||
min-height: 100vh;
|
||||
padding-bottom: calc(24px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.proposal-seconded-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.proposal-seconded-page .van-nav-bar__title {
|
||||
color: #172033;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.proposal-seconded-page .van-nav-bar .van-icon,
|
||||
.proposal-seconded-page .van-nav-bar__text {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.proposal-seconded-popup {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.proposal-seconded-popup-page {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
padding-top: 46px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.proposal-seconded-popup-page .van-nav-bar {
|
||||
z-index: 20;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.proposal-seconded-popup-scroll {
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
flex: 1;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.proposal-seconded-popup-scroll .proposal-view-main {
|
||||
padding-top: 18px;
|
||||
}
|
||||
|
||||
.proposal-seconded-form-actions {
|
||||
display: flex;
|
||||
padding: 10px;
|
||||
justify-content: space-between;
|
||||
column-gap: 10px;
|
||||
}
|
||||
|
||||
.proposal-seconded-content {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.proposal-seconded-sticky {
|
||||
padding: 22px 12px 1px;
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.proposal-seconded-search {
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.proposal-seconded-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.proposal-seconded-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.proposal-seconded-search .van-field__control::placeholder {
|
||||
color: #a7b0bf;
|
||||
}
|
||||
|
||||
.proposal-seconded-filter {
|
||||
margin: 0 0 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
transition: border-radius .18s ease;
|
||||
}
|
||||
|
||||
.proposal-seconded-filter.is-open {
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
.proposal-seconded-filter .van-dropdown-menu__bar {
|
||||
height: 44px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.proposal-seconded-filter .van-dropdown-menu__item {
|
||||
height: 44px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.proposal-seconded-filter .van-dropdown-menu__title {
|
||||
display: inline-flex;
|
||||
height: 44px;
|
||||
align-items: center;
|
||||
line-height: 20px;
|
||||
color: #66758a;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.proposal-seconded-filter .van-dropdown-menu__title--active,
|
||||
.proposal-seconded-filter .van-dropdown-item__option--active,
|
||||
.proposal-seconded-filter .van-dropdown-item__option--active .van-dropdown-item__icon {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.proposal-seconded-filter .van-dropdown-menu__title--down::after {
|
||||
border-color: transparent transparent #1989fa #1989fa;
|
||||
}
|
||||
|
||||
.proposal-seconded-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
margin: 0 12px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0 0 12px 12px;
|
||||
box-shadow: 0 10px 24px rgba(31, 65, 108, .14);
|
||||
}
|
||||
|
||||
.proposal-seconded-filter .van-dropdown-item__option {
|
||||
display: flex;
|
||||
min-height: 48px;
|
||||
padding: 0 16px;
|
||||
align-items: center;
|
||||
color: #46566c;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.proposal-seconded-filter .van-dropdown-item__option .van-cell__title {
|
||||
display: flex;
|
||||
min-height: 20px;
|
||||
align-items: center;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.proposal-seconded-filter .van-cell::after {
|
||||
right: 16px;
|
||||
left: 16px;
|
||||
}
|
||||
|
||||
.proposal-seconded-list .empty-state {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.proposal-seconded-empty {
|
||||
display: flex;
|
||||
min-height: 280px;
|
||||
padding: 46px 18px 36px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.proposal-seconded-empty img {
|
||||
display: block;
|
||||
width: 86%;
|
||||
max-width: 290px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.proposal-seconded-empty__title {
|
||||
margin-top: 14px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.proposal-seconded-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.proposal-seconded-card-header {
|
||||
display: flex;
|
||||
margin-bottom: 7px;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.proposal-seconded-card-heading {
|
||||
min-width: 0;
|
||||
padding-right: 10px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.proposal-seconded-card-title {
|
||||
overflow: hidden;
|
||||
color: #253247;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.proposal-seconded-card-code {
|
||||
margin-top: 1px;
|
||||
color: #9ba6b6;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.proposal-seconded-status {
|
||||
display: inline-flex;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.proposal-seconded-status .van-tag {
|
||||
display: inline-flex;
|
||||
min-height: 24px;
|
||||
padding: 3px 9px;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
border: 0;
|
||||
border-radius: 12px;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.proposal-seconded-page .table-list-container .table-list-item .action-btn .van-icon {
|
||||
margin-right: 6px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
@media (max-width: 350px) {
|
||||
.proposal-seconded-content {
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.proposal-seconded-sticky {
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="附议提案" placeholder fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<van-search
|
||||
v-model="pageForm.name"
|
||||
:show-action="false"
|
||||
:reverse-color="false"
|
||||
input-align="left"
|
||||
placeholder="请输入提案名称搜索"
|
||||
@search="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions" :multiple="false"
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
<van-tab title="已附议" name="1"></van-tab>
|
||||
<van-tab title="未附议" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
</van-sticky>
|
||||
<div class="proposal-seconded-page">
|
||||
<van-nav-bar @click-left="handlePageBack" left-arrow left-text="返回" title="附议提案" placeholder fixed></van-nav-bar>
|
||||
|
||||
<table-list api="/platform/proposal/seconded/h5/pageData" :page_form.sync="pageForm" @ready="onReady"
|
||||
ref="tableListRef"
|
||||
title="name">
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="提案编号">{{row.code}}</table-column>
|
||||
<table-column label="提案类别">{{row.typeName}}</table-column>
|
||||
<table-column label="提案人">{{row.createUserName}}</table-column>
|
||||
<table-column label="代表团">{{row.delegationName}}</table-column>
|
||||
<table-column label="当前节点">{{row.curTaskName}}</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span>查看</span>
|
||||
<van-sticky :offset-top="46">
|
||||
<div class="proposal-seconded-sticky">
|
||||
<van-search
|
||||
v-model="pageForm.name"
|
||||
class="proposal-seconded-search"
|
||||
placeholder="请输入提案名称搜索"
|
||||
shape="round"
|
||||
clearable
|
||||
@search="doSearch"
|
||||
@clear="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu
|
||||
class="proposal-seconded-filter"
|
||||
:class="{'is-open': filterOpened}"
|
||||
active-color="#1989fa"
|
||||
>
|
||||
<van-dropdown-item
|
||||
v-model="pageForm.sessionId"
|
||||
:options="sessionOptions"
|
||||
:multiple="false"
|
||||
@change="doSearch"
|
||||
@open="$set($data, 'filterOpened', true)"
|
||||
@close="$set($data, 'filterOpened', false)"
|
||||
></van-dropdown-item>
|
||||
<van-dropdown-item
|
||||
v-model="pageForm.approvalText"
|
||||
:options="approvalOptions"
|
||||
:multiple="false"
|
||||
@change="approvalChange"
|
||||
@open="$set($data, 'filterOpened', true)"
|
||||
@close="$set($data, 'filterOpened', false)"
|
||||
></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</div>
|
||||
<div class="action-btn" v-if="showSecondAction(row)" @click="onApproval(row)">
|
||||
<i class="fa fa-edit"></i>
|
||||
<span>附议</span>
|
||||
</div>
|
||||
<!-- <div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">-->
|
||||
<!-- <i class="fa fa-reply"></i>-->
|
||||
<!-- <span>撤回</span>-->
|
||||
<!-- </div>-->
|
||||
</template>
|
||||
</table-list>
|
||||
</van-sticky>
|
||||
|
||||
<proposal-info ref="proposalInfoRef">
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">提案附议</div>
|
||||
<!-- <div class="process-title">{{formData.taskName}}</div>-->
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
v-model="formData.tf_opinion"
|
||||
name="tf_opinion"
|
||||
label="审批意见"
|
||||
placeholder="请输入审批意见"
|
||||
:rules="[{ required: true, message: '请填写审批意见' }]"
|
||||
required
|
||||
maxlength="100"
|
||||
show-word-limit
|
||||
></van-field>
|
||||
<!-- <van-field label="签字" name="approvalSignature" v-model="formData.signature" required class="direction-column-field">-->
|
||||
<!-- <h5-signature v-model="formData.approvalSignature" slot="input"></h5-signature>-->
|
||||
<!-- </van-field>-->
|
||||
</van-form>
|
||||
<div v-if="row && row.curTaskCode === 'second'"
|
||||
style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button type="danger" block @click="handleTaskAction(20)">不同意</van-button>
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">同意</van-button>
|
||||
<main class="proposal-seconded-content">
|
||||
<div class="proposal-seconded-list">
|
||||
<!-- 列表无记录时使用与“我的提案”一致的提案专用空状态。 -->
|
||||
<div v-if="pageForm.totalCount === 0" class="proposal-seconded-empty">
|
||||
<img src="/assets/mobile/img/proposal/proposal-empty.png" alt="暂无提案记录插画">
|
||||
<div class="proposal-seconded-empty__title">暂无提案记录</div>
|
||||
<div class="proposal-seconded-empty__hint">当前筛选条件下暂时没有提案</div>
|
||||
</div>
|
||||
<table-list api="/platform/proposal/seconded/h5/pageData" :page_form.sync="pageForm" @ready="onReady"
|
||||
ref="tableListRef"
|
||||
title="name">
|
||||
<template #header="{index,row}">
|
||||
<div class="proposal-seconded-card-header">
|
||||
<div class="proposal-seconded-card-heading">
|
||||
<div class="proposal-seconded-card-title">{{row.name}}</div>
|
||||
<div class="proposal-seconded-card-code">编号:{{row.code || '--'}}</div>
|
||||
</div>
|
||||
<!-- 流程状态固定显示在卡片右上角,并使用胶囊形标签突出当前进度。 -->
|
||||
<enum-tag
|
||||
class="proposal-seconded-status"
|
||||
v-if="row.instanceState"
|
||||
:value="row.instanceState"
|
||||
name="ProcessInstanceStateEnum"
|
||||
label_key="message"
|
||||
size="small"
|
||||
></enum-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="提案类别">{{row.typeName || '--'}}</table-column>
|
||||
<table-column label="提案人">{{row.createUserName || '--'}}</table-column>
|
||||
<table-column label="代表团">{{row.delegationName || '--'}}</table-column>
|
||||
<table-column label="当前节点">{{row.curTaskName || '--'}}</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<van-icon name="eye-o"></van-icon>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="showSecondAction(row)" @click="onApproval(row)">
|
||||
<van-icon name="edit"></van-icon>
|
||||
<span>附议</span>
|
||||
</div>
|
||||
<!-- <div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">-->
|
||||
<!-- <span>撤回</span>-->
|
||||
<!-- </div>-->
|
||||
</template>
|
||||
</table-list>
|
||||
</div>
|
||||
<div v-else style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button type="danger" block @click="updateSecond(2)">不同意</van-button>
|
||||
<van-button type="primary" block @click="updateSecond(1)">同意</van-button>
|
||||
</main>
|
||||
|
||||
<van-popup
|
||||
v-model="detailVisible"
|
||||
class="proposal-seconded-popup"
|
||||
position="right"
|
||||
:close-on-click-overlay="false"
|
||||
safe-area-inset-bottom>
|
||||
<div class="proposal-seconded-popup-page">
|
||||
<van-nav-bar
|
||||
:title="popupTitle"
|
||||
left-arrow
|
||||
left-text="返回"
|
||||
fixed
|
||||
@click-left="closeHistoryLayer('detail')">
|
||||
</van-nav-bar>
|
||||
<div class="proposal-seconded-popup-scroll">
|
||||
<proposal-info v-if="detailVisible && detailBizId" :biz-id="detailBizId" :visible="detailVisible">
|
||||
<div v-if="isApproval">
|
||||
<section class="proposal-view-card proposal-seconded-opinion-card">
|
||||
<h2 class="proposal-view-card__title">
|
||||
提案附议
|
||||
<span class="proposal-audit-card__required">*</span>
|
||||
</h2>
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
v-model="formData.tf_opinion"
|
||||
class="proposal-audit-field"
|
||||
name="tf_opinion"
|
||||
type="textarea"
|
||||
rows="6"
|
||||
label=""
|
||||
placeholder="请输入附议意见"
|
||||
:rules="[{ required: true, message: '请填写附议意见' }]"
|
||||
required
|
||||
maxlength="200"
|
||||
show-word-limit>
|
||||
</van-field>
|
||||
</van-form>
|
||||
</section>
|
||||
<div class="proposal-seconded-form-actions">
|
||||
<van-button type="primary" block :loading="formLoading" class="proposal-soft-button" @click="submitSeconded(true)">同意</van-button>
|
||||
<van-button type="danger" block :loading="formLoading" class="proposal-soft-button proposal-soft-button--danger" @click="submitSeconded(false)">不同意</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</proposal-info>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</proposal-info>
|
||||
</van-popup>
|
||||
|
||||
<van-dialog
|
||||
:value="submitConfirmVisible"
|
||||
title="提示"
|
||||
message="您确定要提交吗?"
|
||||
show-cancel-button
|
||||
@confirm="confirmSubmitSeconded"
|
||||
@cancel="closeHistoryLayer('submit-confirm')">
|
||||
</van-dialog>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script nonce="${cspNonce!}">
|
||||
<!--#include("../../common/info.js"){}#-->
|
||||
|
||||
const vue = new Vue({
|
||||
new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
components: {
|
||||
"proposal-info": PROPOSAL_INFO
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
// 排序字段和方向为空时,后端使用任务创建时间倒序返回分页数据。
|
||||
pageOrderName: "",
|
||||
pageOrderBy: "",
|
||||
name: null,
|
||||
sessionId: null,
|
||||
approvalText: "0",
|
||||
@@ -100,18 +457,76 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
|
||||
sessionOptions: [],
|
||||
row: null,
|
||||
// 任一筛选项展开时,将筛选栏切换为与下拉面板衔接的上圆角样式。
|
||||
filterOpened: false,
|
||||
approvalOptions: [
|
||||
{text: "未附议", value: "0"},
|
||||
{text: "已附议", value: "1"}
|
||||
],
|
||||
detailVisible: false,
|
||||
detailBizId: "",
|
||||
popupAction: "view",
|
||||
curTaskCode: "",
|
||||
formData: {},
|
||||
showApprovalForm: false,
|
||||
rules: {
|
||||
approvalSignature: [{required: true, message: "请签字"}]
|
||||
}
|
||||
formLoading: false,
|
||||
submitConfirmVisible: false,
|
||||
pendingSubmitAgree: true,
|
||||
historyLayerPageKey: "proposal-seconded-h5"
|
||||
}
|
||||
},
|
||||
components: {
|
||||
"proposal-info": PROPOSAL_INFO
|
||||
computed: {
|
||||
isApproval() {
|
||||
return this.popupAction === "approval"
|
||||
},
|
||||
popupTitle() {
|
||||
return this.isApproval ? "提案附议" : "提案详情"
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 注册附议提案页面弹层历史。
|
||||
* pageKey 使用固定页面标识;回调参数 stack 为当前弹层名称数组,无返回值。
|
||||
*/
|
||||
registerHistoryLayers() {
|
||||
if (!window.h5HistoryLayerManager) return
|
||||
window.h5HistoryLayerManager.register(this.historyLayerPageKey, (stack) => {
|
||||
this.syncHistoryLayerStack(stack)
|
||||
})
|
||||
},
|
||||
|
||||
// 根据浏览器历史栈同步详情 Popup 和提交确认 Dialog 的显示状态。
|
||||
syncHistoryLayerStack(stack) {
|
||||
this.$set(this, "detailVisible", stack.includes("detail"))
|
||||
this.$set(this, "submitConfirmVisible", stack.includes("submit-confirm"))
|
||||
},
|
||||
|
||||
// 打开弹层时同步增加当前地址的浏览器历史记录。
|
||||
openHistoryLayer(layerName) {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open(layerName)) return
|
||||
this.setHistoryLayerVisible(layerName, true)
|
||||
},
|
||||
|
||||
// 主动关闭弹层时回退对应历史记录,afterClose 在历史状态同步后执行。
|
||||
closeHistoryLayer(layerName, afterClose = null) {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.close(layerName, afterClose)) return
|
||||
this.setHistoryLayerVisible(layerName, false)
|
||||
if (typeof afterClose === "function") afterClose()
|
||||
},
|
||||
|
||||
setHistoryLayerVisible(layerName, visible) {
|
||||
if (layerName === "detail") this.$set(this, "detailVisible", visible)
|
||||
if (layerName === "submit-confirm") this.$set(this, "submitConfirmVisible", visible)
|
||||
},
|
||||
|
||||
// 页面返回时优先关闭最上层弹框,没有弹框时再返回上一业务页面。
|
||||
handlePageBack() {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.stack.length) {
|
||||
window.h5HistoryLayerManager.close()
|
||||
return
|
||||
}
|
||||
this.historyBack()
|
||||
},
|
||||
|
||||
// 附议按钮显示规则:
|
||||
// 1. 当前任务进行中(taskState=10)时显示
|
||||
// 2. 当前任务已废弃(taskState=99)时,仅 invite、second、delegation、committee 节点显示
|
||||
@@ -119,101 +534,118 @@ layout("/layouts/platform_h5.html"){
|
||||
return row.taskState === 10 || (row.taskState === 99 && ["invite", "second", "preAudit", "delegation", "committee"].includes(row.taskKey))
|
||||
},
|
||||
onReady() {
|
||||
this.listSession()
|
||||
this.listSession(false)
|
||||
},
|
||||
listSession() {
|
||||
// 附议状态下拉框使用字符串值展示,查询接口使用布尔值区分已附议和未附议。
|
||||
approvalChange(value) {
|
||||
this.$set(this.pageForm, "approval", value === "1")
|
||||
this.doSearch()
|
||||
},
|
||||
listSession(skipDefaultSearch) {
|
||||
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.sessionOptions = [
|
||||
{
|
||||
text: "全部届次",
|
||||
value: null
|
||||
}
|
||||
].concat(res.data.map((v) => ({text: v.fullName, value: v.id})))
|
||||
if (this.sessionOptions.length > 0) {
|
||||
this.pageForm.sessionId = this.sessionOptions[0].value
|
||||
this.doSearch()
|
||||
}
|
||||
this.sessionOptions = [{text: "全部届次", value: null}]
|
||||
.concat(res.data.map((v) => ({text: v.fullName, value: v.id})))
|
||||
if (skipDefaultSearch) return
|
||||
// “全部届次”固定展示在首位,但首次查询仍默认使用接口倒序返回的最新届次。
|
||||
this.$set(this.pageForm, "sessionId", res.data.length > 0 ? res.data[0].id : null)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
this.$set(this, "detailBizId", row.id)
|
||||
this.$set(this, "popupAction", "view")
|
||||
this.$set(this, "curTaskCode", "")
|
||||
this.$set(this, "formData", {})
|
||||
this.openHistoryLayer("detail")
|
||||
},
|
||||
|
||||
/**
|
||||
* 打开提案附议 Popup。
|
||||
* row 包含提案、任务和附议人信息;这些字段用于详情查询、任务定位、附议人校验和提交链路选择。
|
||||
*/
|
||||
onApproval(row) {
|
||||
this.row = row
|
||||
this.showApprovalForm = true
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
this.formData = {
|
||||
this.$set(this, "detailBizId", row.id)
|
||||
this.$set(this, "popupAction", "approval")
|
||||
this.$set(this, "curTaskCode", row.curTaskCode || "")
|
||||
this.$set(this, "formData", {
|
||||
processTaskId: row.taskId,
|
||||
taskId: row.taskId,
|
||||
proposalId: row.id,
|
||||
taskActorUserId: row.taskActorUserId,
|
||||
taskName: row.curTaskName,
|
||||
taskName: row.curTaskName || "提案附议",
|
||||
tf_opinion: "同意该提案"
|
||||
}
|
||||
})
|
||||
this.openHistoryLayer("detail")
|
||||
},
|
||||
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate();
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/platform/proposal/seconded/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: val
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.proposalInfoRef.onClose()
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
|
||||
// 表单校验通过后打开提交确认 Dialog,并记录本次附议结果。
|
||||
submitSeconded(isAgree) {
|
||||
this.$refs.formRef.validate()
|
||||
.then(() => {
|
||||
this.$set(this, "pendingSubmitAgree", isAgree)
|
||||
this.openHistoryLayer("submit-confirm")
|
||||
})
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
.catch(() => {})
|
||||
},
|
||||
|
||||
updateSecond(submitType) {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/platform/proposal/seconded/updateInfo", {
|
||||
// 确认提交时先关闭 Dialog 历史层,再调用附议接口。
|
||||
confirmSubmitSeconded() {
|
||||
this.closeHistoryLayer("submit-confirm", () => {
|
||||
this.doSubmitSeconded()
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 提交附议结果。
|
||||
* second 节点向 executeTask 提交完整 WF 数据,其他关联节点向 updateInfo 提交提案、任务、附议人和意见;接口返回 Result。
|
||||
*/
|
||||
doSubmitSeconded() {
|
||||
const isAgree = this.pendingSubmitAgree
|
||||
this.$set(this, "formLoading", true)
|
||||
const request = this.curTaskCode === "second"
|
||||
? this.$axios.post("/platform/proposal/seconded/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: isAgree ? 1 : 20
|
||||
})
|
||||
})
|
||||
: this.$axios.post("/platform/proposal/seconded/updateInfo", {
|
||||
proposalId: this.formData.proposalId,
|
||||
taskId: this.formData.taskId,
|
||||
taskActorUserId: this.formData.taskActorUserId,
|
||||
opinion: this.formData.tf_opinion,
|
||||
submitType: submitType,
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.proposalInfoRef.onClose()
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
submitType: isAgree ? 1 : 2
|
||||
})
|
||||
}).catch(() => {
|
||||
|
||||
request.then((res) => {
|
||||
if (res && res.code === 0) {
|
||||
this.$toast.success(res.msg)
|
||||
this.closeHistoryLayer("detail", () => {
|
||||
this.doSearch()
|
||||
})
|
||||
}
|
||||
}).finally(() => {
|
||||
this.$set(this, "formLoading", false)
|
||||
})
|
||||
},
|
||||
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$set(this.pageForm, "pageNumber", 1)
|
||||
this.$set(this.pageForm, "totalCount", 0)
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.registerHistoryLayers()
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (window.h5HistoryLayerManager) {
|
||||
window.h5HistoryLayerManager.unregister(this.historyLayerPageKey)
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
+93
-99
@@ -2,35 +2,75 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
<style>
|
||||
body { background-color: #f3f7fd; }
|
||||
.proposal-suggestion-page { min-height: 100vh; padding-bottom: calc(24px + env(safe-area-inset-bottom)); box-sizing: border-box; background-color: #f3f7fd; }
|
||||
.proposal-suggestion-page .van-nav-bar { background-color: #fff; }
|
||||
.proposal-suggestion-page .van-nav-bar__title { color: #172033; font-size: 16px; font-weight: 600; }
|
||||
.proposal-suggestion-page .van-nav-bar .van-icon, .proposal-suggestion-page .van-nav-bar__text { color: #1989fa; }
|
||||
.proposal-suggestion-content { padding: 0 12px; }
|
||||
.proposal-suggestion-sticky { padding: 22px 12px 1px; box-sizing: border-box; background-color: #f3f7fd; }
|
||||
.proposal-suggestion-search { margin: 0 0 8px; padding: 0; overflow: hidden; border-radius: 12px; background-color: #fff; box-shadow: 0 5px 16px rgba(43, 73, 112, .1); }
|
||||
.proposal-suggestion-search .van-search__content { height: 42px; padding-left: 12px; align-items: center; border-radius: 12px; background-color: #fff; }
|
||||
.proposal-suggestion-search .van-field__control { color: #263548; font-size: 14px; }
|
||||
.proposal-suggestion-search .van-field__control::placeholder { color: #a7b0bf; }
|
||||
.proposal-suggestion-filter { margin: 0 0 10px; overflow: hidden; border-radius: 10px; box-shadow: 0 5px 16px rgba(43, 73, 112, .08); transition: border-radius .18s ease; }
|
||||
.proposal-suggestion-filter.is-open { border-radius: 10px 10px 0 0; }
|
||||
.proposal-suggestion-filter .van-dropdown-menu__bar, .proposal-suggestion-filter .van-dropdown-menu__item, .proposal-suggestion-filter .van-dropdown-menu__title { height: 44px; }
|
||||
.proposal-suggestion-filter .van-dropdown-menu__bar { box-shadow: none; }
|
||||
.proposal-suggestion-filter .van-dropdown-menu__item, .proposal-suggestion-filter .van-dropdown-menu__title { align-items: center; }
|
||||
.proposal-suggestion-filter .van-dropdown-menu__item { justify-content: center; }
|
||||
.proposal-suggestion-filter .van-dropdown-menu__title { display: inline-flex; color: #66758a; font-size: 14px; line-height: 20px; }
|
||||
.proposal-suggestion-filter .van-dropdown-menu__title--active, .proposal-suggestion-filter .van-dropdown-item__option--active, .proposal-suggestion-filter .van-dropdown-item__option--active .van-dropdown-item__icon { color: #1989fa; }
|
||||
.proposal-suggestion-filter .van-dropdown-menu__title--down::after { border-color: transparent transparent #1989fa #1989fa; }
|
||||
.proposal-suggestion-filter .van-dropdown-item__content { width: calc(100% - 24px); margin: 0 12px; overflow: hidden; box-sizing: border-box; border-radius: 0 0 12px 12px; box-shadow: 0 10px 24px rgba(31, 65, 108, .14); }
|
||||
.proposal-suggestion-filter .van-dropdown-item__option { display: flex; min-height: 48px; padding: 0 16px; align-items: center; color: #46566c; font-size: 14px; }
|
||||
.proposal-suggestion-filter .van-cell::after { right: 16px; left: 16px; }
|
||||
.proposal-suggestion-list .empty-state { display: none; }
|
||||
.proposal-suggestion-empty { display: flex; min-height: 280px; padding: 46px 18px 36px; align-items: center; justify-content: center; flex-direction: column; box-sizing: border-box; text-align: center; }
|
||||
.proposal-suggestion-empty img { display: block; width: 86%; max-width: 290px; height: auto; object-fit: contain; }
|
||||
.proposal-suggestion-empty__title { margin-top: 14px; color: #50627a; font-size: 15px; line-height: 22px; font-weight: 600; }
|
||||
.proposal-suggestion-empty__hint { margin-top: 5px; color: #9aa7b8; font-size: 12px; line-height: 18px; }
|
||||
.van-button--small {
|
||||
height: 26px;
|
||||
}
|
||||
@media (max-width: 350px) { .proposal-suggestion-content, .proposal-suggestion-sticky { padding-right: 10px; padding-left: 10px; } }
|
||||
</style>
|
||||
<style id="style-proposal-task-popup-h5">
|
||||
<!--#include("../../common/info.css"){}#-->
|
||||
<!--#include("../theme.css"){}#-->
|
||||
</style>
|
||||
|
||||
<div id="app">
|
||||
<van-nav-bar title="承办单位意见" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
<div class="proposal-suggestion-page">
|
||||
<van-nav-bar title="承办单位意见" left-text="返回" left-arrow @click-left="handlePageBack" fixed placeholder></van-nav-bar>
|
||||
|
||||
<van-sticky offset-top="46px">
|
||||
<div class="proposal-suggestion-sticky">
|
||||
<van-search
|
||||
v-model="pageForm.name"
|
||||
class="proposal-suggestion-search"
|
||||
:show-action="false"
|
||||
:reverse-color="false"
|
||||
input-align="left"
|
||||
placeholder="请输入提案名称搜索"
|
||||
shape="round"
|
||||
clearable
|
||||
@search="doSearch"
|
||||
@clear="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-menu class="proposal-suggestion-filter" :class="{'is-open': filterOpened}" active-color="#1989fa" :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions" :multiple="false"
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
@change="doSearch" @open="setFilterOpened(true)" @close="setFilterOpened(false)"></van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.approvalText" :options="approvalOptions" :multiple="false"
|
||||
@change="approvalChange" @open="setFilterOpened(true)" @close="setFilterOpened(false)"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
<van-tab title="已反馈" name="1"></van-tab>
|
||||
<van-tab title="未反馈" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<main class="proposal-suggestion-content"><div class="proposal-suggestion-list">
|
||||
<!-- 列表无记录时展示与团长审核一致的提案专用空状态。 -->
|
||||
<div v-if="pageForm.totalCount === 0" class="proposal-suggestion-empty"><img src="/assets/mobile/img/proposal/proposal-empty.png" alt="暂无提案记录插画"><div class="proposal-suggestion-empty__title">暂无提案记录</div><div class="proposal-suggestion-empty__hint">当前筛选条件下暂时没有提案</div></div>
|
||||
<table-list api="/platform/proposal/suggestion/pageData" :page_form.sync="pageForm" ref="tableListRef" title="name" @ready="onReady">
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="提案编号">{{row.code}}</table-column>
|
||||
@@ -43,67 +83,31 @@ layout("/layouts/platform_h5.html"){
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<van-icon class="proposal-action-icon" name="eye-o"></van-icon>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" @click="openSuggestion(row)" v-if="pageForm.approval === true">
|
||||
<i class="fa fa-eye"></i>
|
||||
<van-icon class="proposal-action-icon" name="eye-o"></van-icon>
|
||||
<span>查看意见</span>
|
||||
</div>
|
||||
<div class="action-btn" @click="onAudit(row)">
|
||||
<i class="fa fa-edit"></i>
|
||||
<van-icon class="proposal-action-icon" name="edit"></van-icon>
|
||||
<span>反馈意见</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
</div></main>
|
||||
|
||||
<proposal-info ref="proposalInfoRef">
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">承办单位意见</div>
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
v-model="formData.result"
|
||||
name="result"
|
||||
label="承办意向"
|
||||
placeholder="请选择承办意向"
|
||||
:rules="[{ required: true, message: '必填' }]"
|
||||
required
|
||||
is-link
|
||||
@click="showPicker = true"
|
||||
></van-field>
|
||||
<van-popup v-model="showPicker" position="bottom">
|
||||
<van-picker
|
||||
show-toolbar
|
||||
:columns="dict.type.UNDERTAKE_SUGGESTION.map(item => item.code)"
|
||||
@confirm="(val) => {formData.result = val; showPicker = false}"
|
||||
@cancel="showPicker = false"
|
||||
></van-picker>
|
||||
</van-popup>
|
||||
<van-field
|
||||
v-model="formData.opinion"
|
||||
name="opinion"
|
||||
label="反馈意见"
|
||||
placeholder="请输入反馈意见"
|
||||
:rules="[{ required: true, message: '必填' }]"
|
||||
required
|
||||
show-word-limit
|
||||
></van-field>
|
||||
</van-form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button block @click="">取消</van-button>
|
||||
<van-button type="primary" block @click="doSubmit">提交</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</proposal-info>
|
||||
|
||||
<van-action-sheet v-model="visible" title="意见信息">
|
||||
<div class="detail-container">
|
||||
<van-popup v-model="visible" position="right" class="proposal-full-popup" :close-on-click-overlay="false" get-container="#app">
|
||||
<div class="proposal-full-popup__page">
|
||||
<van-nav-bar @click-left="closeSuggestion" left-arrow left-text="返回" title="意见信息" placeholder fixed></van-nav-bar>
|
||||
<div class="proposal-full-popup__scroll detail-container">
|
||||
<van-cell-group :key="index" v-for="item,index in suggestionList">
|
||||
<template #title>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center">
|
||||
<div>{{ '意见' + (index + 1) }}</div>
|
||||
<div>
|
||||
<van-button type="danger" @click="onDelete(item)" size="small">删除</van-button>
|
||||
<van-button type="danger" @click="onDelete(item)" size="small"><van-icon name="delete-o"></van-icon> 删除</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -115,19 +119,20 @@ layout("/layouts/platform_h5.html"){
|
||||
<span v-html="item.opinion"></span>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
</div>
|
||||
</div>
|
||||
</van-action-sheet>
|
||||
</van-popup>
|
||||
<proposal-task-popup ref="taskPopup" kind="suggestion" page-key="proposal-suggestion-task" @success="doSearch"></proposal-task-popup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
<!--#include("../../common/info.js"){}#-->
|
||||
<!--#include("../../common/task-popup.js"){}#-->
|
||||
new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
dicts: ["UNDERTAKE_SUGGESTION"],
|
||||
components: {
|
||||
"proposal-info": PROPOSAL_INFO
|
||||
},
|
||||
components: {"proposal-task-popup": PROPOSAL_TASK_POPUP},
|
||||
data() {
|
||||
return {
|
||||
pageForm: {
|
||||
@@ -141,15 +146,21 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
|
||||
sessionOptions: [],
|
||||
formData: {},
|
||||
showApprovalForm: false,
|
||||
|
||||
showPicker: false,
|
||||
filterOpened: false,
|
||||
approvalOptions: [
|
||||
{text: "未反馈", value: "0"},
|
||||
{text: "已反馈", value: "1"}
|
||||
],
|
||||
suggestionList: [],
|
||||
visible: false,
|
||||
historyLayerPageKey: "proposal-suggestion-list"
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
registerHistoryLayers() { window.h5HistoryLayerManager.register(this.historyLayerPageKey, (stack) => this.$set(this, "visible", stack.includes("opinions"))) },
|
||||
handlePageBack() { if (window.h5HistoryLayerManager.stack.length) { window.h5HistoryLayerManager.close(); return } historyBack() },
|
||||
closeSuggestion() { window.h5HistoryLayerManager.close("opinions") },
|
||||
setFilterOpened(value) { this.$set(this, "filterOpened", value) },
|
||||
onDelete(row) {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
@@ -159,7 +170,7 @@ layout("/layouts/platform_h5.html"){
|
||||
.then(res => {
|
||||
if(res.code === 0) {
|
||||
this.$toast.success(res.msg)
|
||||
this.visible = false
|
||||
this.closeSuggestion()
|
||||
this.doSearch()
|
||||
} else {
|
||||
this.$message.fail(res.msg)
|
||||
@@ -172,12 +183,12 @@ layout("/layouts/platform_h5.html"){
|
||||
proposalId: row.id,
|
||||
}).then(res => {
|
||||
if(res.code === 0) {
|
||||
this.suggestionList = res.data
|
||||
this.$set(this, "suggestionList", res.data)
|
||||
if(this.suggestionList.length === 0) {
|
||||
this.$toast('暂无意见数')
|
||||
return
|
||||
}
|
||||
this.visible = true
|
||||
window.h5HistoryLayerManager.open("opinions")
|
||||
} else {
|
||||
this.$toast.fail(res.msg)
|
||||
}
|
||||
@@ -186,59 +197,42 @@ layout("/layouts/platform_h5.html"){
|
||||
onReady() {
|
||||
this.listSession()
|
||||
},
|
||||
// 反馈状态下拉框使用字符串值展示,查询接口使用布尔值区分已反馈和未反馈。
|
||||
approvalChange(value) {
|
||||
this.$set(this.pageForm, "approval", value === "1")
|
||||
this.doSearch()
|
||||
},
|
||||
listSession() {
|
||||
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.sessionOptions = [
|
||||
this.$set(this, "sessionOptions", [
|
||||
{
|
||||
text: "全部届次",
|
||||
value: null
|
||||
}
|
||||
].concat(res.data.map((v) => ({text: v.fullName, value: v.id})))
|
||||
if (this.sessionOptions.length > 0) {
|
||||
this.pageForm.sessionId = this.sessionOptions[0].value
|
||||
this.doSearch()
|
||||
}
|
||||
].concat(res.data.map((v) => ({text: v.fullName, value: v.id}))))
|
||||
// 届次接口按开始时间倒序返回,首条即最新届次;无届次时继续按全部届次查询。
|
||||
this.$set(this.pageForm, "sessionId", res.data.length > 0 ? res.data[0].id : null)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
},
|
||||
onAudit(row) {
|
||||
this.showApprovalForm = true
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
this.formData = {
|
||||
proposalId: row.id,
|
||||
}
|
||||
},
|
||||
async doSubmit() {
|
||||
try {
|
||||
await this.$refs.formRef.validate()
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/platform/proposal/suggestion/suggest", this.formData)
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.proposalInfoRef.onClose()
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(() => {})
|
||||
} catch (error) {}
|
||||
this.$refs.taskPopup.open(row, "approval")
|
||||
},
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
this.$refs.taskPopup.open(row, "view")
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$set(this.pageForm, "pageNumber", 1)
|
||||
this.$set(this.pageForm, "totalCount", 0)
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
}
|
||||
},
|
||||
created() { this.registerHistoryLayers() },
|
||||
beforeDestroy() { window.h5HistoryLayerManager.unregister(this.historyLayerPageKey) }
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
+538
-228
@@ -1,271 +1,561 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<style>
|
||||
body {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-page {
|
||||
min-height: 100vh;
|
||||
padding-bottom: calc(24px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-page .van-nav-bar__title {
|
||||
color: #172033;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-page .van-nav-bar .van-icon,
|
||||
.proposal-unit-reply-page .van-nav-bar__text {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-content {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-sticky {
|
||||
padding: 22px 12px 1px;
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-search {
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.proposal-unit-reply-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-search .van-field__control::placeholder {
|
||||
color: #a7b0bf;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-filter {
|
||||
margin: 0 0 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
transition: border-radius .18s ease;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-filter.is-open {
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-filter .van-dropdown-menu__bar,
|
||||
.proposal-unit-reply-filter .van-dropdown-menu__item,
|
||||
.proposal-unit-reply-filter .van-dropdown-menu__title {
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-filter .van-dropdown-menu__bar {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-filter .van-dropdown-menu__item,
|
||||
.proposal-unit-reply-filter .van-dropdown-menu__title {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-filter .van-dropdown-menu__item {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-filter .van-dropdown-menu__title {
|
||||
display: inline-flex;
|
||||
color: #66758a;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-filter .van-dropdown-menu__title--active,
|
||||
.proposal-unit-reply-filter .van-dropdown-item__option--active,
|
||||
.proposal-unit-reply-filter .van-dropdown-item__option--active .van-dropdown-item__icon {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-filter .van-dropdown-menu__title--down::after {
|
||||
border-color: transparent transparent #1989fa #1989fa;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
margin: 0 12px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0 0 12px 12px;
|
||||
box-shadow: 0 10px 24px rgba(31, 65, 108, .14);
|
||||
}
|
||||
|
||||
.proposal-unit-reply-filter .van-dropdown-item__option {
|
||||
display: flex;
|
||||
min-height: 48px;
|
||||
padding: 0 16px;
|
||||
align-items: center;
|
||||
color: #46566c;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-filter .van-cell::after {
|
||||
right: 16px;
|
||||
left: 16px;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-list .empty-state {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-empty {
|
||||
display: flex;
|
||||
min-height: 280px;
|
||||
padding: 46px 18px 36px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-empty img {
|
||||
display: block;
|
||||
width: 86%;
|
||||
max-width: 290px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-empty__title {
|
||||
margin-top: 14px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-card-header {
|
||||
display: flex;
|
||||
margin-bottom: 7px;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-card-heading {
|
||||
min-width: 0;
|
||||
padding-right: 10px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-card-title {
|
||||
overflow: hidden;
|
||||
color: #253247;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-card-code {
|
||||
margin-top: 1px;
|
||||
color: #9ba6b6;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-status {
|
||||
display: inline-flex;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.proposal-unit-reply-status .van-tag {
|
||||
display: inline-flex;
|
||||
min-height: 24px;
|
||||
padding: 3px 9px;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
border: 0;
|
||||
border-radius: 12px;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 转办弹框底部直接使用页面浅蓝底色承载操作按钮,避免出现独立白色操作栏。 */
|
||||
.proposal-full-popup__page > .button-group.proposal-transfer-button-group {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.proposal-transfer-button-group .van-button {
|
||||
border-radius: 14px;
|
||||
}
|
||||
|
||||
.proposal-transfer-button-group .proposal-transfer-cancel-button {
|
||||
border-color: transparent;
|
||||
color: #46566c;
|
||||
background-color: rgba(255, 255, 255, .78);
|
||||
box-shadow: 0 4px 12px rgba(43, 73, 112, .08), inset 0 1px 1px rgba(255, 255, 255, .82);
|
||||
}
|
||||
|
||||
/* 选择转交人弹框沿用提案列表的圆角搜索框、人员卡片和插图空状态。 */
|
||||
.proposal-transfer-user-popup .proposal-full-popup__page {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.proposal-transfer-user-search {
|
||||
padding: 12px 12px 8px;
|
||||
background-color: #f3f7fd;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.proposal-transfer-user-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.proposal-transfer-user-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.proposal-transfer-user-search .van-field__control::placeholder {
|
||||
color: #a7b0bf;
|
||||
}
|
||||
|
||||
.proposal-transfer-user-scroll {
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
flex: 1;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.proposal-transfer-user-list {
|
||||
padding: 0 12px 12px;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.proposal-transfer-user-item {
|
||||
min-height: 64px;
|
||||
margin-top: 12px;
|
||||
padding: 12px 14px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 6px 16px rgba(43, 73, 112, .08);
|
||||
}
|
||||
|
||||
.proposal-transfer-user-item::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.proposal-transfer-user-item__name {
|
||||
display: block;
|
||||
color: #253247;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.proposal-transfer-user-item__unit {
|
||||
color: #79879a;
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.proposal-transfer-user-empty {
|
||||
display: flex;
|
||||
min-height: 420px;
|
||||
padding: 40px 18px 36px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.proposal-transfer-user-empty img {
|
||||
display: block;
|
||||
width: 82%;
|
||||
max-width: 270px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.proposal-transfer-user-empty__title {
|
||||
margin-top: 14px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.proposal-transfer-user-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
@media (max-width: 350px) {
|
||||
.proposal-unit-reply-content,
|
||||
.proposal-unit-reply-sticky {
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style id="style-proposal-task-popup-h5">
|
||||
<!--#include("../../common/info.css"){}#-->
|
||||
<!--#include("../theme.css"){}#-->
|
||||
</style>
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="承办单位答复" placeholder
|
||||
fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<van-search
|
||||
v-model="pageForm.name"
|
||||
:show-action="false"
|
||||
:reverse-color="false"
|
||||
input-align="left"
|
||||
placeholder="请输入提案名称搜索"
|
||||
@search="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions" :multiple="false"
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
</van-sticky>
|
||||
|
||||
<table-list api="/platform/proposal/unitReply/pageData" :page_form.sync="pageForm" @ready="onReady"
|
||||
ref="tableListRef"
|
||||
title="name">
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="提案编号">{{row.code}}</table-column>
|
||||
<table-column label="提案类别">{{row.typeName}}</table-column>
|
||||
<table-column label="提案人">{{row.createUserName}}</table-column>
|
||||
<table-column label="代表团">{{row.delegationName}}</table-column>
|
||||
<table-column label="承办单位">{{row.underTakeName}}({{row.underTakeIsMaster ? '主办' : '协办'}})
|
||||
</table-column>
|
||||
<table-column label="当前节点">{{row.curTaskName}}</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span>查看</span>
|
||||
<div class="proposal-unit-reply-page">
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="承办单位答复" placeholder fixed></van-nav-bar>
|
||||
<van-sticky :offset-top="46">
|
||||
<div class="proposal-unit-reply-sticky">
|
||||
<van-search
|
||||
v-model="pageForm.name"
|
||||
class="proposal-unit-reply-search"
|
||||
placeholder="请输入提案名称搜索"
|
||||
shape="round"
|
||||
clearable
|
||||
@search="doSearch"
|
||||
@clear="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu
|
||||
class="proposal-unit-reply-filter"
|
||||
:class="{'is-open': filterOpened}"
|
||||
active-color="#1989fa"
|
||||
>
|
||||
<van-dropdown-item
|
||||
v-model="pageForm.sessionId"
|
||||
:options="sessionOptions"
|
||||
:multiple="false"
|
||||
@change="doSearch"
|
||||
@open="$set($data, 'filterOpened', true)"
|
||||
@close="$set($data, 'filterOpened', false)"
|
||||
></van-dropdown-item>
|
||||
<van-dropdown-item
|
||||
v-model="pageForm.approvalText"
|
||||
:options="approvalOptions"
|
||||
:multiple="false"
|
||||
@change="approvalChange"
|
||||
@open="$set($data, 'filterOpened', true)"
|
||||
@close="$set($data, 'filterOpened', false)"
|
||||
></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
|
||||
<i class="fa fa-edit"></i>
|
||||
<span>答复</span>
|
||||
</div>
|
||||
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">
|
||||
<i class="fa fa-reply"></i>
|
||||
<span>撤回</span>
|
||||
</van-sticky>
|
||||
|
||||
<main class="proposal-unit-reply-content">
|
||||
<div class="proposal-unit-reply-list">
|
||||
<!-- 列表无记录时使用与团长审核一致的提案专用空状态。 -->
|
||||
<div v-if="pageForm.totalCount === 0" class="proposal-unit-reply-empty">
|
||||
<img src="/assets/mobile/img/proposal/proposal-empty.png" alt="暂无提案记录插画">
|
||||
<div class="proposal-unit-reply-empty__title">暂无提案记录</div>
|
||||
<div class="proposal-unit-reply-empty__hint">当前筛选条件下暂时没有提案</div>
|
||||
</div>
|
||||
<table-list api="/platform/proposal/unitReply/pageData" :page_form.sync="pageForm" @ready="onReady"
|
||||
ref="tableListRef"
|
||||
title="name">
|
||||
<template #header="{index,row}">
|
||||
<div class="proposal-unit-reply-card-header">
|
||||
<div class="proposal-unit-reply-card-heading">
|
||||
<div class="proposal-unit-reply-card-title">{{row.name}}</div>
|
||||
<div class="proposal-unit-reply-card-code">编号:{{row.code || '--'}}</div>
|
||||
</div>
|
||||
<enum-tag
|
||||
class="proposal-unit-reply-status"
|
||||
v-if="row.instanceState"
|
||||
:value="row.instanceState"
|
||||
name="ProcessInstanceStateEnum"
|
||||
label_key="message"
|
||||
size="small"
|
||||
></enum-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="提案类别">{{row.typeName || '--'}}</table-column>
|
||||
<table-column label="提案人">{{row.createUserName || '--'}}</table-column>
|
||||
<table-column label="代表团">{{row.delegationName || '--'}}</table-column>
|
||||
<table-column label="承办单位">{{row.underTakeName || '--'}}({{row.underTakeIsMaster ? '主办' : '协办'}})</table-column>
|
||||
<table-column label="当前节点">{{row.curTaskName || '--'}}</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row,index)">
|
||||
<van-icon class="proposal-action-icon" name="eye-o"></van-icon>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row,index)">
|
||||
<van-icon class="proposal-action-icon" name="edit"></van-icon>
|
||||
<span>答复</span>
|
||||
</div>
|
||||
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">
|
||||
<van-icon class="proposal-action-icon" name="revoke"></van-icon>
|
||||
<span>撤回</span>
|
||||
</div>
|
||||
|
||||
<!-- 承办单位领导、超级管理员才能转办。 -->
|
||||
<div class="action-btn" v-if="!pageForm.approval && $auth.hasRoleOr('SYSADMIN,PROPOSAL_UNIT_LEADER')"
|
||||
@click="openTransfer(row)">
|
||||
<van-icon class="proposal-action-icon" name="exchange"></van-icon>
|
||||
<span>转办</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<!--承办单位领导、超级管理员才能转办-->
|
||||
<div class="action-btn" v-if="!pageForm.approval && $auth.hasRoleOr('SYSADMIN,PROPOSAL_UNIT_LEADER')"
|
||||
@click="openTransfer(row)">
|
||||
<i class="fa fa-arrow-right"></i>
|
||||
<span>转交</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
|
||||
<proposal-info ref="proposalInfoRef">
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">{{formData.taskName}}</div>
|
||||
<van-form ref="formRef">
|
||||
<van-field :value="formData.underTakeName"
|
||||
label="承办单位"
|
||||
readonly></van-field>
|
||||
|
||||
<van-field
|
||||
v-model="formData.tf_implementStateName"
|
||||
name="tf_implementStateName"
|
||||
label="落实情况"
|
||||
placeholder="请选择落实情况"
|
||||
:rules="[{ required: true, message: '请选择落实情况' }]"
|
||||
required
|
||||
is-link
|
||||
@click="showImplementPicker = true"
|
||||
></van-field>
|
||||
<van-popup v-model="showImplementPicker" position="bottom">
|
||||
<van-picker
|
||||
show-toolbar
|
||||
:columns="dict.type.PROPOSAL_REPLY_IMPLEMENT.map(item => ({text: item.label, value: item.code}))"
|
||||
@confirm="onImplementConfirm"
|
||||
@cancel="showImplementPicker = false"
|
||||
></van-picker>
|
||||
</van-popup>
|
||||
|
||||
<van-field
|
||||
v-model="formData.tf_opinion"
|
||||
name="tf_opinion"
|
||||
label="答复内容"
|
||||
placeholder="请输入答复内容"
|
||||
:rules="[{ required: true, message: '请填写答复内容' }]"
|
||||
required
|
||||
maxlength="100"
|
||||
show-word-limit
|
||||
></van-field>
|
||||
|
||||
<van-field
|
||||
v-if="supportCandidate && formData.underTakeIsMaster"
|
||||
v-model="formData.tf_nextNodeOperatorName"
|
||||
name="tf_nextNodeOperatorName"
|
||||
label="校领导"
|
||||
placeholder="校领导"
|
||||
:rules="[{ required: true, message: '请选择校领导' }]"
|
||||
required
|
||||
is-link
|
||||
@click="showCandidatesPicker = true"
|
||||
></van-field>
|
||||
<van-popup v-model="showCandidatesPicker" position="bottom">
|
||||
<van-picker
|
||||
show-toolbar
|
||||
:columns="candidates.map(item => ({text: item.userName, value: item.userId}))"
|
||||
@confirm="onCandidatesConfirm"
|
||||
@cancel="showCandidatesPicker = false"
|
||||
></van-picker>
|
||||
</van-popup>
|
||||
|
||||
</van-form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button block @click="$refs.proposalInfoRef.onClose()">取消</van-button>
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">提交</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</proposal-info>
|
||||
|
||||
<transfer ref="transferRef"></transfer>
|
||||
<transfer ref="transferRef" @success="doSearch"></transfer>
|
||||
<proposal-task-popup ref="taskPopup" kind="unitReply" page-key="proposal-unit-reply-task" @success="doSearch"></proposal-task-popup>
|
||||
<van-dialog
|
||||
:value="communicationConfirmVisible"
|
||||
title="提示"
|
||||
message="是否已与提案代表进行充分沟通?"
|
||||
confirm-button-text="是"
|
||||
cancel-button-text="否"
|
||||
show-cancel-button
|
||||
@confirm="confirmCommunication"
|
||||
@cancel="closeCommunicationConfirm">
|
||||
</van-dialog>
|
||||
</div>
|
||||
<script nonce="${cspNonce!}">
|
||||
<!--#include("../../common/info.js"){}#-->
|
||||
<!--#include("transfer.js"){}#-->
|
||||
<!--#include("../../common/info.js"){}#-->
|
||||
<!--#include("../../common/task-popup.js"){}#-->
|
||||
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
dicts: ['PROPOSAL_REPLY_IMPLEMENT'],
|
||||
data() {
|
||||
return {
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "",
|
||||
pageOrderBy: "",
|
||||
name: null,
|
||||
sessionId: null,
|
||||
approvalText: "0",
|
||||
approval: false
|
||||
},
|
||||
|
||||
sessionOptions: [],
|
||||
formData: {},
|
||||
showApprovalForm: false,
|
||||
|
||||
showImplementPicker: false,
|
||||
|
||||
supportCandidate: false,
|
||||
candidates: [],
|
||||
showCandidatesPicker: false,
|
||||
|
||||
filterOpened: false,
|
||||
approvalOptions: [
|
||||
{text: "未审核", value: "0"},
|
||||
{text: "已审核", value: "1"}
|
||||
],
|
||||
communicationConfirmVisible: false,
|
||||
pendingApprovalRow: null,
|
||||
historyLayerPageKey: "proposal-unit-reply",
|
||||
unsubscribeHistoryLayer: null
|
||||
}
|
||||
},
|
||||
components: {
|
||||
"proposal-info": PROPOSAL_INFO,
|
||||
"transfer": transfer
|
||||
"transfer": transfer,
|
||||
"proposal-task-popup": PROPOSAL_TASK_POPUP
|
||||
},
|
||||
methods: {
|
||||
onReady() {
|
||||
this.listSession()
|
||||
this.listSession(false)
|
||||
},
|
||||
listSession() {
|
||||
|
||||
// 审核状态下拉框使用字符串值展示,查询接口使用布尔值区分已审核和未审核。
|
||||
approvalChange(value) {
|
||||
this.$set(this.pageForm, "approval", value === "1")
|
||||
this.doSearch()
|
||||
},
|
||||
|
||||
// 缓存恢复时只加载届次选项,不覆盖离开列表前的筛选条件和列表快照。
|
||||
listSession(skipDefaultSearch) {
|
||||
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.sessionOptions = [
|
||||
{
|
||||
text: "全部届次",
|
||||
value: null
|
||||
}
|
||||
].concat(res.data.map((v) => ({text: v.fullName, value: v.id})))
|
||||
if (this.sessionOptions.length > 0) {
|
||||
this.pageForm.sessionId = this.sessionOptions[0].value
|
||||
this.doSearch()
|
||||
}
|
||||
this.sessionOptions = [{text: "全部届次", value: null}]
|
||||
.concat(res.data.map((item) => ({text: item.fullName, value: item.id})))
|
||||
if (skipDefaultSearch) return
|
||||
// 届次接口按开始时间倒序返回,首条即最新届次;无届次时继续按全部届次查询。
|
||||
this.$set(this.pageForm, "sessionId", res.data.length > 0 ? res.data[0].id : null)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
onView(row, index) {
|
||||
this.$refs.taskPopup.open(row, "view")
|
||||
},
|
||||
|
||||
async onApproval(row) {
|
||||
// 与 PC 端保持一致,确认已沟通后才允许进入答复表单。
|
||||
try {
|
||||
await this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "是否已与提案代表进行充分沟通?",
|
||||
confirmButtonText: "是",
|
||||
cancelButtonText: "否"
|
||||
})
|
||||
} catch (error) {
|
||||
return
|
||||
}
|
||||
this.loadCandidates(row.taskId)
|
||||
onApproval(row, index) {
|
||||
// row 为当前待答复提案;确认已充分沟通后,才进入原有答复表单。
|
||||
this.$set(this, "pendingApprovalRow", row)
|
||||
window.h5HistoryLayerManager.open("communication-confirm")
|
||||
},
|
||||
|
||||
this.$set(this, "showApprovalForm", true)
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
this.$set(this, "formData", {
|
||||
processTaskId: row.taskId,
|
||||
taskKey: row.taskKey,
|
||||
taskName: row.taskName,
|
||||
proposalId: row.id,
|
||||
underTakeName: row.underTakeName,
|
||||
underTakeIsMaster: row.underTakeIsMaster
|
||||
/** stack 为当前页面弹层名称数组;同步沟通确认框状态,无返回值。 */
|
||||
syncHistoryLayers(stack) {
|
||||
const visible = stack.includes("communication-confirm")
|
||||
this.$set(this, "communicationConfirmVisible", visible)
|
||||
if (!visible) this.$set(this, "pendingApprovalRow", null)
|
||||
},
|
||||
|
||||
// 取消确认时同步回退浏览器历史,手机返回键与弹窗按钮行为保持一致。
|
||||
closeCommunicationConfirm() {
|
||||
window.h5HistoryLayerManager.close("communication-confirm")
|
||||
},
|
||||
|
||||
// 确认后先关闭沟通弹层,再使用暂存的提案数据打开原有答复表单。
|
||||
confirmCommunication() {
|
||||
const row = this.pendingApprovalRow
|
||||
window.h5HistoryLayerManager.close("communication-confirm", () => {
|
||||
if (row) this.$refs.taskPopup.open(row, "approval")
|
||||
})
|
||||
},
|
||||
|
||||
// 加载候选人列表
|
||||
loadCandidates(taskId) {
|
||||
$.get("/flow/common/candidate", {taskId}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.candidates = res.data.candidates
|
||||
this.supportCandidate = res.data.support
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
onImplementConfirm(value) {
|
||||
this.$set(this.formData, "tf_implementStateName", value.text)
|
||||
this.$set(this.formData, "tf_implementState", value.value)
|
||||
this.showImplementPicker = false
|
||||
},
|
||||
|
||||
onCandidatesConfirm(value) {
|
||||
this.$set(this.formData, "tf_nextNodeOperatorName", value.text)
|
||||
this.$set(this.formData, "tf_nextNodeOperator", value.value)
|
||||
this.showCandidatesPicker = false
|
||||
},
|
||||
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate();
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
delete this.formData.underTakeIsMaster
|
||||
delete this.formData.underTakeName
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: val
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.proposalInfoRef.onClose()
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
|
||||
})
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
onRevoke(row) {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
@@ -280,18 +570,38 @@ layout("/layouts/platform_h5.html"){
|
||||
})
|
||||
},
|
||||
|
||||
// 打开转办
|
||||
openTransfer(row){
|
||||
// 打开转办。
|
||||
openTransfer(row) {
|
||||
this.$refs.transferRef.openTransfer(row)
|
||||
},
|
||||
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$set(this.pageForm, "pageNumber", 1)
|
||||
this.$set(this.pageForm, "totalCount", 0)
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
window.h5HistoryLayerManager.ensureRegistered(this.historyLayerPageKey)
|
||||
this.$set(this, "unsubscribeHistoryLayer", window.h5HistoryLayerManager.subscribe((stack) => {
|
||||
this.syncHistoryLayers(stack)
|
||||
}))
|
||||
const tab = new URLSearchParams(window.location.search).get("tab")
|
||||
if (tab === "done") {
|
||||
this.$set(this.pageForm, "approval", true)
|
||||
this.$set(this.pageForm, "approvalText", "1")
|
||||
} else if (tab === "todo") {
|
||||
this.$set(this.pageForm, "approval", false)
|
||||
this.$set(this.pageForm, "approvalText", "0")
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.unsubscribeHistoryLayer) this.unsubscribeHistoryLayer()
|
||||
if (window.h5HistoryLayerManager.pageKey === this.historyLayerPageKey) {
|
||||
window.h5HistoryLayerManager.unregister(this.historyLayerPageKey)
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
+79
-135
@@ -1,147 +1,91 @@
|
||||
const transfer = {
|
||||
template: /*language=HTML*/ `
|
||||
<van-action-sheet v-model="showTransferDialog" title="提案转办">
|
||||
<div class="transfer-dialog">
|
||||
<!-- 提案信息 -->
|
||||
<div class="proposal-info-card">
|
||||
<div class="info-item"><label>提案编号:</label><span>{{transferForm.code}}</span></div>
|
||||
<div class="info-item"><label>提案名称:</label><span>{{transferForm.name}}</span></div>
|
||||
<div class="info-item"><label>代表团:</label><span>{{transferForm.delegationName}}</span></div>
|
||||
<van-popup v-model="showTransferDialog" position="right" class="proposal-full-popup proposal-transfer-dialog" :close-on-click-overlay="false" get-container="#app">
|
||||
<div class="proposal-full-popup__page">
|
||||
<van-nav-bar @click-left="closeTransfer" left-arrow left-text="返回" title="提案转办" placeholder fixed></van-nav-bar>
|
||||
<div class="proposal-full-popup__scroll transfer-dialog">
|
||||
<section class="proposal-view-card proposal-transfer-info-card">
|
||||
<van-cell-group :border="false">
|
||||
<van-cell title="提案编号">{{transferForm.code || '--'}}</van-cell>
|
||||
<van-cell title="提案名称">{{transferForm.name || '--'}}</van-cell>
|
||||
<van-cell title="代表团">{{transferForm.delegationName || '--'}}</van-cell>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
<section class="proposal-view-card proposal-transfer-user-card">
|
||||
<van-cell-group :border="false">
|
||||
<van-field v-model="searchKeyword" label="转交给" placeholder="搜索用户" required readonly is-link @click="openUserList"></van-field>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- 用户选择 -->
|
||||
<van-field v-model="searchKeyword" label="转交给" placeholder="搜索用户" required readonly @click="showUserList=true"></van-field>
|
||||
<van-popup v-model="showUserList" position="bottom">
|
||||
<van-search v-model="keyword" placeholder="搜索用户" @search="selectTransferUser(keyword)" @cancel="showUserList=false"></van-search>
|
||||
<van-empty v-if="transferUserOptions.length === 0" class="empty-tip">请搜索需要转办的用户</van-empty>
|
||||
<van-cell v-for="item in transferUserOptions" :key="item.id" :title="item.username" @click="selectUser(item)"></van-cell>
|
||||
</van-popup>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<div class="button-group">
|
||||
<van-button block plain @click="showTransferDialog = false" class="cancel-btn">取消</van-button>
|
||||
<van-button block type="info" @click="handleTransfer" class="submit-btn">提交</van-button>
|
||||
<div class="button-group proposal-transfer-button-group">
|
||||
<van-button block type="info" class="proposal-soft-button" @click="handleTransfer">提交</van-button>
|
||||
<van-button block plain class="proposal-transfer-cancel-button" @click="closeTransfer">返回</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</van-action-sheet>
|
||||
<van-popup v-model="showUserList" position="right" class="proposal-full-popup proposal-transfer-user-popup" :close-on-click-overlay="false" get-container="#app">
|
||||
<div class="proposal-full-popup__page">
|
||||
<van-nav-bar @click-left="closeUserList" left-arrow left-text="返回" title="选择转交人" placeholder fixed></van-nav-bar>
|
||||
<van-search
|
||||
v-model="keyword"
|
||||
class="proposal-transfer-user-search"
|
||||
shape="round"
|
||||
clearable
|
||||
placeholder="请输入姓名或工号搜索"
|
||||
@search="selectTransferUser(keyword)"
|
||||
@clear="resetTransferUserSearch">
|
||||
</van-search>
|
||||
<div class="proposal-transfer-user-scroll">
|
||||
<van-cell-group v-if="transferUserOptions.length" class="proposal-transfer-user-list" :border="false">
|
||||
<van-cell
|
||||
v-for="item in transferUserOptions"
|
||||
:key="item.id"
|
||||
class="proposal-transfer-user-item"
|
||||
clickable
|
||||
@click="selectUser(item)">
|
||||
<span slot="title" class="proposal-transfer-user-item__name">
|
||||
{{item.username}}<span class="proposal-transfer-user-item__unit">({{item.unitName || '--'}})</span>
|
||||
</span>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
<div v-else class="proposal-transfer-user-empty">
|
||||
<img src="/assets/mobile/img/proposal/proposal-empty.png" alt="暂无转交用户插画">
|
||||
<div class="proposal-transfer-user-empty__title">
|
||||
{{hasUserSearched ? '暂无搜索记录' : '请搜索需要转办的用户'}}
|
||||
</div>
|
||||
<div v-if="hasUserSearched" class="proposal-transfer-user-empty__hint">请调整搜索条件后重试</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
<van-dialog :value="confirmVisible" title="提示" :message="confirmMessage" show-cancel-button @confirm="confirmTransfer" @cancel="closeConfirm"></van-dialog>
|
||||
</van-popup>
|
||||
`,
|
||||
data() {
|
||||
return {
|
||||
showTransferDialog: false,
|
||||
transferForm: {},
|
||||
transferUserOptions: [],
|
||||
searchKeyword: '',
|
||||
showUserList: false,
|
||||
keyword: ''
|
||||
return {showTransferDialog:false,transferForm:{},transferUserOptions:[],searchKeyword:"",showUserList:false,keyword:"",hasUserSearched:false,confirmVisible:false,historyLayerPageKey:"proposal-unit-reply-transfer",unsubscribeHistoryLayer:null}
|
||||
},
|
||||
computed: {
|
||||
confirmMessage() {
|
||||
const item=this.transferUserOptions.find((option) => option.id === this.transferForm.userId)
|
||||
return "您确定要将" + (this.transferForm.name || "") + "提案转交给" + (item ? item.username : "") + "办理吗?"
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
openTransfer(row) {
|
||||
this.showTransferDialog = true
|
||||
this.transferForm = { taskId: row.taskId, name: row.name, code: row.code, delegationName: row.delegationName }
|
||||
this.searchKeyword = ''
|
||||
},
|
||||
selectUser(item) {
|
||||
this.transferForm.userId = item.id
|
||||
this.searchKeyword = item.username
|
||||
this.showUserList = false
|
||||
},
|
||||
selectTransferUser(keyword) {
|
||||
this.$axios.post("/platform/proposal/unitReply/selectViceUser", {keyword}).then(res => {
|
||||
if (res.code === 0) this.transferUserOptions = res.data
|
||||
})
|
||||
},
|
||||
|
||||
// 转办
|
||||
handleTransfer() {
|
||||
if (!this.transferForm.userId) {
|
||||
this.$toast('请选择转交用户')
|
||||
return
|
||||
}
|
||||
|
||||
const transferUserName = this.transferUserOptions.find(item => item.id === this.transferForm.userId)?.username
|
||||
const name = this.transferForm.name
|
||||
|
||||
this.$dialog.confirm({
|
||||
title: '提示',
|
||||
message: `您确定要将` + name + `提案转交给` + transferUserName + `办理吗?`,
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消'
|
||||
}).then(() => {
|
||||
this.$axios.post('/platform/proposal/unitReply/transfer', this.transferForm).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.success(res.msg)
|
||||
this.showTransferDialog = false
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
// 取消操作
|
||||
})
|
||||
}
|
||||
syncLayers(stack) { this.$set(this,"showTransferDialog",stack.includes("transfer")); this.$set(this,"showUserList",stack.includes("user-list")); this.$set(this,"confirmVisible",stack.includes("confirm")) },
|
||||
openTransfer(row) { this.$set(this,"transferForm",{taskId:row.taskId,name:row.name,code:row.code,delegationName:row.delegationName}); this.$set(this,"searchKeyword",""); window.h5HistoryLayerManager.open("transfer") },
|
||||
closeTransfer() { window.h5HistoryLayerManager.close("transfer") },
|
||||
/** 打开用户列表前重置搜索条件和结果,确保首次进入展示搜索引导空状态。 */
|
||||
openUserList() { this.resetTransferUserSearch(); window.h5HistoryLayerManager.open("user-list") },
|
||||
closeUserList() { window.h5HistoryLayerManager.close("user-list") },
|
||||
closeConfirm() { window.h5HistoryLayerManager.close("confirm") },
|
||||
selectUser(item) { this.$set(this.transferForm,"userId",item.id); this.$set(this,"searchKeyword",item.username); this.closeUserList() },
|
||||
/** 清空姓名或工号关键词、搜索状态和人员结果,无返回值。 */
|
||||
resetTransferUserSearch() { this.$set(this,"keyword",""); this.$set(this,"hasUserSearched",false); this.$set(this,"transferUserOptions",[]) },
|
||||
/** keyword 为姓名或工号关键词;空值仅恢复搜索引导,非空值查询并返回可转交用户数组。 */
|
||||
selectTransferUser(keyword) { const searchText=(keyword || "").trim(); if (!searchText) { this.resetTransferUserSearch(); return } this.$set(this,"hasUserSearched",true); this.$axios.post("/platform/proposal/unitReply/selectViceUser",{keyword:searchText}).then((res) => { if (res.code === 0) this.$set(this,"transferUserOptions",res.data || []) }) },
|
||||
handleTransfer() { if (!this.transferForm.userId) { this.$toast("请选择转交用户"); return } window.h5HistoryLayerManager.open("confirm") },
|
||||
/** 提交 taskId 和 userId 完成转办,成功后清理弹层并通知父列表刷新。 */
|
||||
confirmTransfer() { this.$axios.post("/platform/proposal/unitReply/transfer",this.transferForm).then((res) => { if (res.code === 0) { this.$toast.success(res.msg); window.h5HistoryLayerManager.closeAll(() => this.$emit("success")) } }) }
|
||||
},
|
||||
style: /*language=CSS*/ `
|
||||
.transfer-dialog {
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
padding: 16px 16px 65px;
|
||||
}
|
||||
|
||||
.proposal-info-card {
|
||||
background: #f8f9fa;
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.proposal-info-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.info-item label {
|
||||
font-size: 12px;
|
||||
color: #969799;
|
||||
}
|
||||
|
||||
.info-item span {
|
||||
font-size: 14px;
|
||||
color: #323233;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
border-top: 1px solid #ebedf0;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
column-gap: 10px;
|
||||
padding: 10px
|
||||
}
|
||||
|
||||
.cancel-btn,
|
||||
.submit-btn {
|
||||
|
||||
}
|
||||
|
||||
.empty-tip {
|
||||
text-align: center;
|
||||
padding: 50px 16px;
|
||||
color: #969799;
|
||||
font-size: 14px;
|
||||
}
|
||||
`
|
||||
created() { window.h5HistoryLayerManager.ensureRegistered(this.historyLayerPageKey); this.$set(this,"unsubscribeHistoryLayer",window.h5HistoryLayerManager.subscribe((stack) => this.syncLayers(stack))) },
|
||||
beforeDestroy() { if (this.unsubscribeHistoryLayer) this.unsubscribeHistoryLayer(); if (window.h5HistoryLayerManager.pageKey === this.historyLayerPageKey) window.h5HistoryLayerManager.unregister(this.historyLayerPageKey) }
|
||||
}
|
||||
|
||||
+108
-17
@@ -1,28 +1,73 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<style>
|
||||
body { background-color: #f3f7fd; }
|
||||
.proposal-vice-delegation-page { min-height: 100vh; padding-bottom: calc(24px + env(safe-area-inset-bottom)); box-sizing: border-box; background-color: #f3f7fd; }
|
||||
.proposal-vice-delegation-page .van-nav-bar { background-color: #fff; }
|
||||
.proposal-vice-delegation-page .van-nav-bar__title { color: #172033; font-size: 16px; font-weight: 600; }
|
||||
.proposal-vice-delegation-page .van-nav-bar .van-icon, .proposal-vice-delegation-page .van-nav-bar__text { color: #1989fa; }
|
||||
.proposal-vice-delegation-content { padding: 0 12px; }
|
||||
.proposal-vice-delegation-sticky { padding: 22px 12px 1px; box-sizing: border-box; background-color: #f3f7fd; }
|
||||
.proposal-vice-delegation-search { margin: 0 0 8px; padding: 0; overflow: hidden; border-radius: 12px; background-color: #fff; box-shadow: 0 5px 16px rgba(43, 73, 112, .1); }
|
||||
.proposal-vice-delegation-search .van-search__content { height: 42px; padding-left: 12px; align-items: center; border-radius: 12px; background-color: #fff; }
|
||||
.proposal-vice-delegation-search .van-field__control { color: #263548; font-size: 14px; }
|
||||
.proposal-vice-delegation-search .van-field__control::placeholder { color: #a7b0bf; }
|
||||
.proposal-vice-delegation-filter { margin: 0 0 10px; overflow: hidden; border-radius: 10px; box-shadow: 0 5px 16px rgba(43, 73, 112, .08); transition: border-radius .18s ease; }
|
||||
.proposal-vice-delegation-filter.is-open { border-radius: 10px 10px 0 0; }
|
||||
.proposal-vice-delegation-filter .van-dropdown-menu__bar, .proposal-vice-delegation-filter .van-dropdown-menu__item, .proposal-vice-delegation-filter .van-dropdown-menu__title { height: 44px; }
|
||||
.proposal-vice-delegation-filter .van-dropdown-menu__bar { box-shadow: none; }
|
||||
.proposal-vice-delegation-filter .van-dropdown-menu__item, .proposal-vice-delegation-filter .van-dropdown-menu__title { align-items: center; }
|
||||
.proposal-vice-delegation-filter .van-dropdown-menu__item { justify-content: center; }
|
||||
.proposal-vice-delegation-filter .van-dropdown-menu__title { display: inline-flex; color: #66758a; font-size: 14px; line-height: 20px; }
|
||||
.proposal-vice-delegation-filter .van-dropdown-menu__title--active, .proposal-vice-delegation-filter .van-dropdown-item__option--active, .proposal-vice-delegation-filter .van-dropdown-item__option--active .van-dropdown-item__icon { color: #1989fa; }
|
||||
.proposal-vice-delegation-filter .van-dropdown-menu__title--down::after { border-color: transparent transparent #1989fa #1989fa; }
|
||||
.proposal-vice-delegation-filter .van-dropdown-item__content { width: calc(100% - 24px); margin: 0 12px; overflow: hidden; box-sizing: border-box; border-radius: 0 0 12px 12px; box-shadow: 0 10px 24px rgba(31, 65, 108, .14); }
|
||||
.proposal-vice-delegation-filter .van-dropdown-item__option { display: flex; min-height: 48px; padding: 0 16px; align-items: center; color: #46566c; font-size: 14px; }
|
||||
.proposal-vice-delegation-filter .van-cell::after { right: 16px; left: 16px; }
|
||||
.proposal-vice-delegation-list .empty-state { display: none; }
|
||||
.proposal-vice-delegation-empty { display: flex; min-height: 280px; padding: 46px 18px 36px; align-items: center; justify-content: center; flex-direction: column; box-sizing: border-box; text-align: center; }
|
||||
.proposal-vice-delegation-empty img { display: block; width: 86%; max-width: 290px; height: auto; object-fit: contain; }
|
||||
.proposal-vice-delegation-empty__title { margin-top: 14px; color: #50627a; font-size: 15px; line-height: 22px; font-weight: 600; }
|
||||
.proposal-vice-delegation-empty__hint { margin-top: 5px; color: #9aa7b8; font-size: 12px; line-height: 18px; }
|
||||
@media (max-width: 350px) { .proposal-vice-delegation-content, .proposal-vice-delegation-sticky { padding-right: 10px; padding-left: 10px; } }
|
||||
</style>
|
||||
<style id="style-proposal-vice-delegation-h5">
|
||||
<!--#include("../../common/info.css"){}#-->
|
||||
<!--#include("../theme.css"){}#-->
|
||||
</style>
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="团长审核" placeholder fixed></van-nav-bar>
|
||||
<div class="proposal-vice-delegation-page">
|
||||
<van-nav-bar @click-left="handlePageBack" left-arrow left-text="返回" title="团长审核" placeholder fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<div class="proposal-vice-delegation-sticky">
|
||||
<van-search
|
||||
v-model="pageForm.name"
|
||||
class="proposal-vice-delegation-search"
|
||||
:show-action="false"
|
||||
:reverse-color="false"
|
||||
input-align="left"
|
||||
placeholder="请输入提案名称搜索"
|
||||
shape="round"
|
||||
clearable
|
||||
@search="doSearch"
|
||||
@clear="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-menu class="proposal-vice-delegation-filter" :class="{'is-open': filterOpened}" active-color="#1989fa" :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions" :multiple="false"
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
@change="doSearch" @open="setFilterOpened(true)" @close="setFilterOpened(false)"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<!-- <van-tabs v-model="pageForm.approvalText"-->
|
||||
<!-- @change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">-->
|
||||
<!-- @change="(val)=>{$set(this.pageForm, 'approval', val==='1');this.doSearch();}">-->
|
||||
<!-- <van-tab title="已审核" name="1"></van-tab>-->
|
||||
<!-- <van-tab title="未审核" name="0"></van-tab>-->
|
||||
<!-- </van-tabs>-->
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<main class="proposal-vice-delegation-content"><div class="proposal-vice-delegation-list">
|
||||
<!-- 列表无记录时展示与团长审核一致的提案专用空状态。 -->
|
||||
<div v-if="pageForm.totalCount === 0" class="proposal-vice-delegation-empty"><img src="/assets/mobile/img/proposal/proposal-empty.png" alt="暂无提案记录插画"><div class="proposal-vice-delegation-empty__title">暂无提案记录</div><div class="proposal-vice-delegation-empty__hint">当前筛选条件下暂时没有提案</div></div>
|
||||
<table-list api="/platform/proposal/vice/delegation/pageData" :page_form.sync="pageForm" @ready="onReady"
|
||||
ref="tableListRef"
|
||||
title="name">
|
||||
@@ -35,21 +80,33 @@ layout("/layouts/platform_h5.html"){
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<van-icon class="proposal-action-icon" name="eye-o"></van-icon>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
</div></main>
|
||||
|
||||
<proposal-info ref="proposalInfoRef"></proposal-info>
|
||||
|
||||
<van-popup v-model="detailVisible" class="proposal-full-popup" position="right"
|
||||
:close-on-click-overlay="false" safe-area-inset-bottom>
|
||||
<div class="proposal-full-popup__page">
|
||||
<van-nav-bar title="提案详情" left-arrow left-text="返回" fixed
|
||||
@click-left="closeHistoryLayer('detail')"></van-nav-bar>
|
||||
<div class="proposal-full-popup__scroll">
|
||||
<proposal-info v-if="detailVisible && detailBizId" :biz-id="detailBizId" :visible="detailVisible"></proposal-info>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</div>
|
||||
</div>
|
||||
<script nonce="${cspNonce!}">
|
||||
<!--#include("../../common/info.js"){}#-->
|
||||
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
components: {
|
||||
"proposal-info": PROPOSAL_INFO
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageForm: {
|
||||
@@ -63,14 +120,39 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
|
||||
sessionOptions: [],
|
||||
filterOpened: false,
|
||||
formData: {},
|
||||
showApprovalForm: false
|
||||
showApprovalForm: false,
|
||||
detailVisible: false,
|
||||
detailBizId: "",
|
||||
historyLayerPageKey: "proposal-vice-delegation-h5"
|
||||
}
|
||||
},
|
||||
components: {
|
||||
"proposal-info": PROPOSAL_INFO
|
||||
},
|
||||
methods: {
|
||||
registerHistoryLayers() {
|
||||
if (!window.h5HistoryLayerManager) return
|
||||
window.h5HistoryLayerManager.register(this.historyLayerPageKey, (stack) => {
|
||||
this.$set(this, "detailVisible", stack.includes("detail"))
|
||||
})
|
||||
},
|
||||
openHistoryLayer(layerName) {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open(layerName)) return
|
||||
if (layerName === "detail") this.$set(this, "detailVisible", true)
|
||||
},
|
||||
closeHistoryLayer(layerName) {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.close(layerName)) return
|
||||
if (layerName === "detail") this.$set(this, "detailVisible", false)
|
||||
},
|
||||
handlePageBack() {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.stack.length) {
|
||||
window.h5HistoryLayerManager.close()
|
||||
return
|
||||
}
|
||||
this.historyBack()
|
||||
},
|
||||
setFilterOpened(value) {
|
||||
this.$set(this, "filterOpened", value)
|
||||
},
|
||||
onReady() {
|
||||
this.listSession()
|
||||
},
|
||||
@@ -83,17 +165,18 @@ layout("/layouts/platform_h5.html"){
|
||||
value: null
|
||||
}
|
||||
].concat(res.data.map((v) => ({text: v.fullName, value: v.id})))
|
||||
if (this.sessionOptions.length > 0) {
|
||||
this.pageForm.sessionId = this.sessionOptions[0].value
|
||||
this.doSearch()
|
||||
// 届次接口按开始时间倒序返回,首条即最新届次;无届次时继续按全部届次查询。
|
||||
if (res.data && res.data.length > 0) {
|
||||
this.$set(this.pageForm, "sessionId", res.data[0].id)
|
||||
}
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
this.$refs.proposalInfoRef.onOpen(row)
|
||||
this.$set(this, "detailBizId", row.id)
|
||||
this.openHistoryLayer("detail")
|
||||
},
|
||||
|
||||
doSearch() {
|
||||
@@ -103,6 +186,14 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.registerHistoryLayers()
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (window.h5HistoryLayerManager) {
|
||||
window.h5HistoryLayerManager.unregister(this.historyLayerPageKey)
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
+595
-204
File diff suppressed because it is too large
Load Diff
+4
-4
@@ -16,7 +16,7 @@ layout("/layouts/platform_h5.html"){
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item :multiple="false" :options="sessionOptions" @change="sessionChange" v-model="pageForm.sessionId"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-tabs v-model="pageForm.approvalText" @change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
<van-tabs v-model="pageForm.approvalText" @change="(val)=>{$set(this.pageForm, 'approval', val==='1');this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
@@ -59,7 +59,7 @@ layout("/layouts/platform_h5.html"){
|
||||
|
||||
<van-popup :style="{ height: '100%', width: '100%' }" position="right" safe-area-inset-bottom v-model="infoShow">
|
||||
<van-sticky>
|
||||
<van-nav-bar @click-left="infoShow=false" left-arrow left-text="返回" title="详细信息"></van-nav-bar>
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="详细信息"></van-nav-bar>
|
||||
</van-sticky>
|
||||
<div style="height: calc(100vh - 44px); overflow-y: auto">
|
||||
<info ref="infoRef"></info>
|
||||
@@ -76,9 +76,9 @@ layout("/layouts/platform_h5.html"){
|
||||
></van-field>
|
||||
</van-form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button type="danger" block @click.submit="doApproval('BACK')">退回重新填写</van-button>
|
||||
<van-button type="danger" block @click.submit="doApproval('REJECT')">建议撤销</van-button>
|
||||
<van-button type="primary" block @click.submit="doApproval('PASS')">同意</van-button>
|
||||
<van-button type="danger" block @click.submit="doApproval('REJECT')">建议撤销</van-button>
|
||||
<van-button type="danger" block @click.submit="doApproval('BACK')">退回重新填写</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+3
-3
@@ -16,7 +16,7 @@ layout("/layouts/platform_h5.html"){
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item :multiple="false" :options="sessionOptions" @change="sessionChange" v-model="pageForm.sessionId"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-tabs v-model="pageForm.approvalText" @change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
<van-tabs v-model="pageForm.approvalText" @change="(val)=>{$set(this.pageForm, 'approval', val==='1');this.doSearch();}">
|
||||
<van-tab title="已附议" name="1"></van-tab>
|
||||
<van-tab title="未附议" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
@@ -47,7 +47,7 @@ layout("/layouts/platform_h5.html"){
|
||||
|
||||
<van-popup :style="{ height: '100%', width: '100%' }" position="right" safe-area-inset-bottom v-model="infoShow">
|
||||
<van-sticky>
|
||||
<van-nav-bar @click-left="infoShow=false" left-arrow left-text="返回" title="详细信息"></van-nav-bar>
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="详细信息"></van-nav-bar>
|
||||
</van-sticky>
|
||||
<div style="height: calc(100vh - 44px); overflow-y: auto">
|
||||
<info ref="infoRef"></info>
|
||||
@@ -59,8 +59,8 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-field>
|
||||
</form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button type="danger" block @click.submit="doApproval('REJECT')">拒绝</van-button>
|
||||
<van-button type="primary" block @click.submit="doApproval('PASS')">同意</van-button>
|
||||
<van-button type="danger" block @click.submit="doApproval('REJECT')">拒绝</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+4
-4
@@ -16,7 +16,7 @@ layout("/layouts/platform_h5.html"){
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item :multiple="false" :options="sessionOptions" @change="sessionChange" v-model="pageForm.sessionId"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-tabs v-model="pageForm.approvalText" @change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
<van-tabs v-model="pageForm.approvalText" @change="(val)=>{$set(this.pageForm, 'approval', val==='1');this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
@@ -59,7 +59,7 @@ layout("/layouts/platform_h5.html"){
|
||||
|
||||
<van-popup :style="{ height: '100%', width: '100%' }" position="right" safe-area-inset-bottom v-model="infoShow">
|
||||
<van-sticky>
|
||||
<van-nav-bar @click-left="infoShow=false" left-arrow left-text="返回" title="详细信息"></van-nav-bar>
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="详细信息"></van-nav-bar>
|
||||
</van-sticky>
|
||||
<div style="height: calc(100vh - 44px); overflow-y: auto">
|
||||
<info ref="infoRef"></info>
|
||||
@@ -76,9 +76,9 @@ layout("/layouts/platform_h5.html"){
|
||||
></van-field>
|
||||
</van-form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button type="danger" block @click.submit="doApproval('BACK')">退回重新填写</van-button>
|
||||
<van-button type="danger" block @click.submit="doApproval('REJECT')">建议撤销</van-button>
|
||||
<van-button type="primary" block @click.submit="doApproval('PASS')">同意</van-button>
|
||||
<van-button type="danger" block @click.submit="doApproval('REJECT')">建议撤销</van-button>
|
||||
<van-button type="danger" block @click.submit="doApproval('BACK')">退回重新填写</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+3
-3
@@ -16,7 +16,7 @@ layout("/layouts/platform_h5.html"){
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item :multiple="false" :options="sessionOptions" @change="sessionChange" v-model="pageForm.sessionId"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-tabs v-model="pageForm.approvalText" @change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
<van-tabs v-model="pageForm.approvalText" @change="(val)=>{$set(this.pageForm, 'approval', val==='1');this.doSearch();}">
|
||||
<van-tab title="已附议" name="1"></van-tab>
|
||||
<van-tab title="未附议" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
@@ -51,7 +51,7 @@ layout("/layouts/platform_h5.html"){
|
||||
|
||||
<van-popup :style="{ height: '100%', width: '100%' }" position="right" safe-area-inset-bottom v-model="infoShow">
|
||||
<van-sticky>
|
||||
<van-nav-bar @click-left="infoShow=false" left-arrow left-text="返回" title="详细信息"></van-nav-bar>
|
||||
<van-nav-bar @click-left="historyBack" left-arrow left-text="返回" title="详细信息"></van-nav-bar>
|
||||
</van-sticky>
|
||||
<div style="height: calc(100vh - 44px); overflow-y: auto">
|
||||
<info ref="infoRef"></info>
|
||||
@@ -70,8 +70,8 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-field>
|
||||
</van-form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button type="danger" block @click.submit="doApproval('REJECT')">拒绝</van-button>
|
||||
<van-button type="primary" block @click.submit="doApproval('PASS')">同意</van-button>
|
||||
<van-button type="danger" block @click.submit="doApproval('REJECT')">拒绝</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -15,7 +15,7 @@ layout("/layouts/platform_h5.html"){
|
||||
@search="doSearch"
|
||||
></van-search>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
@change="(val)=>{$set(this.pageForm, 'approval', val==='1');this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
@@ -60,9 +60,9 @@ layout("/layouts/platform_h5.html"){
|
||||
></van-field>
|
||||
</van-form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(2)">拒绝</van-button>
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">同意</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(2)">拒绝</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</suggestion-box-info>
|
||||
@@ -124,31 +124,28 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
},
|
||||
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate();
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: val
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.suggestionBoxInfoRef.onClose()
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
|
||||
})
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
handleTaskAction(val) {
|
||||
return Promise.resolve().then(() => {
|
||||
return this.$refs.formRef.validate().then(() => {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: val
|
||||
})
|
||||
}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.suggestionBoxInfoRef.onClose();
|
||||
this.$toast.success(res.msg);
|
||||
this.doSearch();
|
||||
}
|
||||
});
|
||||
}).catch(() => {});
|
||||
});
|
||||
}).catch(error => {});
|
||||
},
|
||||
|
||||
|
||||
|
||||
+583
-53
@@ -2,63 +2,555 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak style="padding-bottom: 70px;">
|
||||
<van-nav-bar title="代表阅览" left-text="返回" left-arrow @click-left="historyBack" placeholder fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<van-search
|
||||
v-model="pageForm.searchKeyword"
|
||||
:show-action="false"
|
||||
:reverse-color="false"
|
||||
input-align="left"
|
||||
placeholder="请输入姓名/工号搜索"
|
||||
@search="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions"
|
||||
@change="sessionChange"></van-dropdown-item>
|
||||
<van-dropdown-item
|
||||
v-if="pageForm.sessionId"
|
||||
v-model="pageForm.delegationId"
|
||||
:options="delegationOptions"
|
||||
@change="doSearch"
|
||||
></van-dropdown-item>
|
||||
<style>
|
||||
body {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.delegate-read-page {
|
||||
min-height: 100vh;
|
||||
padding-bottom: calc(86px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.delegate-read-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.delegate-read-page .van-nav-bar .van-icon,
|
||||
.delegate-read-page .van-nav-bar__text {
|
||||
color: #397fbd;
|
||||
}
|
||||
|
||||
.delegate-read-content {
|
||||
padding: 12px 12px 0;
|
||||
}
|
||||
|
||||
.delegate-read-hero {
|
||||
position: relative;
|
||||
height: 134px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
color: #fff;
|
||||
background-color: #247fe8;
|
||||
box-shadow: 0 8px 20px rgba(51, 117, 219, .18);
|
||||
}
|
||||
|
||||
.delegate-read-hero__image {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
|
||||
.delegate-read-hero__copy {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
width: 68%;
|
||||
height: 100%;
|
||||
padding-left: 16px;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
background: linear-gradient(90deg, rgba(22, 112, 232, .98) 0%, rgba(22, 112, 232, .88) 52%, rgba(22, 112, 232, 0) 100%);
|
||||
}
|
||||
|
||||
.delegate-read-hero__title {
|
||||
font-size: 25px;
|
||||
line-height: 34px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 1px;
|
||||
text-shadow: 0 2px 6px rgba(17, 86, 182, .18);
|
||||
}
|
||||
|
||||
.delegate-read-hero__subtitle {
|
||||
margin-top: 4px;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
letter-spacing: .5px;
|
||||
opacity: .95;
|
||||
}
|
||||
|
||||
.delegate-read-sticky {
|
||||
padding: 10px 0 1px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.van-sticky--fixed .delegate-read-sticky {
|
||||
padding-right: 12px;
|
||||
padding-left: 12px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.delegate-read-search {
|
||||
margin: 0 0 10px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 9px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 3px 12px rgba(43, 73, 112, .06);
|
||||
}
|
||||
|
||||
.delegate-read-search .van-search__content {
|
||||
height: 40px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 9px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.delegate-read-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.delegate-read-search .van-field__control::placeholder {
|
||||
color: #a7b0bf;
|
||||
}
|
||||
|
||||
.delegate-read-filter {
|
||||
margin: 0 0 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
transition: border-radius .18s ease;
|
||||
}
|
||||
|
||||
.delegate-read-filter.is-open {
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
.delegate-read-filter .van-dropdown-menu__bar {
|
||||
height: 44px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.delegate-read-filter .van-dropdown-menu__item {
|
||||
min-width: 0;
|
||||
flex: 1 1 0;
|
||||
}
|
||||
|
||||
.delegate-read-filter .van-dropdown-menu__title {
|
||||
width: auto;
|
||||
max-width: calc(100% - 24px);
|
||||
padding: 0 12px 0 0;
|
||||
color: #66758a;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.delegate-read-filter .van-dropdown-menu__title::after {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.delegate-read-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
max-height: 80%;
|
||||
margin: 0 12px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0 0 12px 12px;
|
||||
box-shadow: 0 10px 24px rgba(31, 65, 108, .14);
|
||||
}
|
||||
|
||||
.delegate-read-list .empty-state {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.delegate-read-list .table-list.is-empty {
|
||||
height: calc(100vh - 400px - env(safe-area-inset-bottom));
|
||||
min-height: 300px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.delegate-read-list .table-list-container {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.delegate-read-page-skeleton {
|
||||
padding: 12px 12px 86px;
|
||||
}
|
||||
|
||||
.delegate-read-skeleton__block {
|
||||
background: linear-gradient(90deg, #f2f3f5 25%, #e6e7e9 37%, #f2f3f5 63%);
|
||||
background-size: 400% 100%;
|
||||
animation: delegate-read-skeleton-loading 1.4s ease infinite;
|
||||
}
|
||||
|
||||
.delegate-read-skeleton__hero {
|
||||
height: 134px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.delegate-read-skeleton__search {
|
||||
height: 40px;
|
||||
margin-top: 10px;
|
||||
border-radius: 9px;
|
||||
}
|
||||
|
||||
.delegate-read-skeleton__filter {
|
||||
height: 44px;
|
||||
margin: 10px 0;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.delegate-read-skeleton__item {
|
||||
margin-bottom: 10px;
|
||||
padding: 12px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 9px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 3px 12px rgba(43, 73, 112, .06);
|
||||
}
|
||||
|
||||
.delegate-read-skeleton__item .van-skeleton {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.delegate-read-skeleton__item .van-skeleton__avatar {
|
||||
width: 58px;
|
||||
height: 58px;
|
||||
}
|
||||
|
||||
.delegate-read-skeleton__item .van-skeleton__content {
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
.delegate-read-skeleton__item .van-skeleton__title {
|
||||
width: 34%;
|
||||
}
|
||||
|
||||
.delegate-read-skeleton__actions {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
|
||||
background-color: #fff;
|
||||
border-top: 1px solid #edf1f6;
|
||||
}
|
||||
|
||||
.delegate-read-skeleton__action {
|
||||
height: 44px;
|
||||
flex: 1;
|
||||
border-radius: 9px;
|
||||
}
|
||||
|
||||
@keyframes delegate-read-skeleton-loading {
|
||||
0% {
|
||||
background-position: 100% 50%;
|
||||
}
|
||||
100% {
|
||||
background-position: 0 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.delegate-read-list .table-list-container .table-list-item {
|
||||
margin-bottom: 10px;
|
||||
padding: 12px;
|
||||
border: 0;
|
||||
border-radius: 9px;
|
||||
box-shadow: 0 3px 12px rgba(43, 73, 112, .06);
|
||||
}
|
||||
|
||||
.delegate-read-list .table-list-container .table-list-item .table-list-content,
|
||||
.delegate-read-list .table-list-container .table-list-item .table-list-columns {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.delegate-read-list .table-list-container .table-list-item .item-header,
|
||||
.delegate-read-list .table-list-container .table-list-item .item-actions {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.delegate-card {
|
||||
display: grid;
|
||||
grid-template-columns: 58px minmax(0, 1fr);
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
min-height: 76px;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.delegate-card__avatar {
|
||||
display: flex;
|
||||
width: 58px;
|
||||
height: 58px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
border-radius: 50%;
|
||||
color: #6ca8f2;
|
||||
background-color: #eaf3ff;
|
||||
}
|
||||
|
||||
.delegate-card__avatar.is-female {
|
||||
color: #ee9cab;
|
||||
background-color: #fff0f3;
|
||||
}
|
||||
|
||||
.delegate-card__avatar .van-icon {
|
||||
font-size: 34px;
|
||||
}
|
||||
|
||||
.delegate-card__body {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.delegate-card__name {
|
||||
margin-bottom: 4px;
|
||||
overflow: hidden;
|
||||
color: #1e2c43;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.delegate-card__row {
|
||||
display: grid;
|
||||
grid-template-columns: 76px minmax(0, 1fr);
|
||||
min-height: 20px;
|
||||
align-items: center;
|
||||
color: #52637c;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.delegate-card__label {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
align-items: center;
|
||||
color: #91a0b3;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.delegate-card__label i {
|
||||
width: 15px;
|
||||
margin-right: 5px;
|
||||
color: #8da2bd;
|
||||
font-size: 11px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.delegate-card__value {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
color: #435570;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.delegate-read-empty {
|
||||
display: flex;
|
||||
min-height: 260px;
|
||||
padding: 26px 18px 32px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.delegate-read-empty img {
|
||||
display: block;
|
||||
width: 82%;
|
||||
max-width: 280px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.delegate-read-empty__title {
|
||||
margin-top: 14px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.delegate-read-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.delegate-read-actions {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background: #fff;
|
||||
border-top: 1px solid #edf1f6;
|
||||
box-shadow: 0 -5px 16px rgba(43, 73, 112, .08);
|
||||
}
|
||||
|
||||
.delegate-read-actions .van-button {
|
||||
flex: 1;
|
||||
height: 44px;
|
||||
border-radius: 9px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.delegate-read-actions .delegate-read-action.is-excel {
|
||||
color: #217346;
|
||||
border-color: #8fc6a8;
|
||||
background-color: #eef8f2;
|
||||
box-shadow: inset 0 0 0 1px rgba(33, 115, 70, .06);
|
||||
}
|
||||
|
||||
.delegate-read-actions .delegate-read-action.is-word {
|
||||
color: #2b579a;
|
||||
border-color: #91afd4;
|
||||
background-color: #eef4fb;
|
||||
box-shadow: inset 0 0 0 1px rgba(43, 87, 154, .06);
|
||||
}
|
||||
|
||||
.delegate-read-actions .is-excel i {
|
||||
color: #217346;
|
||||
}
|
||||
|
||||
.delegate-read-actions .is-word i {
|
||||
color: #2b579a;
|
||||
}
|
||||
|
||||
.delegate-read-actions i {
|
||||
margin-right: 7px;
|
||||
font-size: 17px;
|
||||
vertical-align: -1px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<div class="delegate-read-page">
|
||||
<van-nav-bar title="代表阅览" left-text="返回" left-arrow @click-left="historyBack" placeholder fixed></van-nav-bar>
|
||||
|
||||
<div v-if="pageSkeletonLoading" class="delegate-read-page-skeleton">
|
||||
<div class="delegate-read-skeleton__hero delegate-read-skeleton__block"></div>
|
||||
<div class="delegate-read-skeleton__search delegate-read-skeleton__block"></div>
|
||||
<div class="delegate-read-skeleton__filter delegate-read-skeleton__block"></div>
|
||||
<div v-for="item in 5" :key="item" class="delegate-read-skeleton__item">
|
||||
<van-skeleton title avatar avatar-shape="round" :row="3" row-width="100%" animated></van-skeleton>
|
||||
</div>
|
||||
<div class="delegate-read-skeleton__actions">
|
||||
<div class="delegate-read-skeleton__action delegate-read-skeleton__block"></div>
|
||||
<div class="delegate-read-skeleton__action delegate-read-skeleton__block"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-show="!pageSkeletonLoading" class="delegate-read-content">
|
||||
<section class="delegate-read-hero">
|
||||
<img class="delegate-read-hero__image" src="/assets/mobile/img/democratic/teachercongress/delegate-read-hero.png" alt="代表阅览插画">
|
||||
<div class="delegate-read-hero__copy">
|
||||
<div class="delegate-read-hero__title">代表阅览</div>
|
||||
<div class="delegate-read-hero__subtitle">查阅教代会代表信息</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<van-sticky :offset-top="46">
|
||||
<div class="delegate-read-sticky">
|
||||
<van-search
|
||||
v-model="pageForm.searchKeyword"
|
||||
class="delegate-read-search"
|
||||
:show-action="false"
|
||||
:reverse-color="false"
|
||||
input-align="left"
|
||||
placeholder="请输入姓名/工号搜索"
|
||||
shape="round"
|
||||
clearable
|
||||
@search="doSearch"
|
||||
@clear="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu class="delegate-read-filter" :class="{'is-open': filterOpened}" active-color="#1989fa">
|
||||
<van-dropdown-item v-model="pageForm.sessionId" :options="sessionOptions"
|
||||
@change="sessionChange" @open="setFilterOpened(true)" @close="setFilterOpened(false)"></van-dropdown-item>
|
||||
<van-dropdown-item
|
||||
v-if="pageForm.sessionId"
|
||||
v-model="pageForm.delegationId"
|
||||
:options="delegationOptions"
|
||||
@change="doSearch"
|
||||
@open="setFilterOpened(true)"
|
||||
@close="setFilterOpened(false)"
|
||||
></van-dropdown-item>
|
||||
<!-- <van-dropdown-item ref="moreDropDownItemOption" title="更多查询" multiple :options="moreOptions"-->
|
||||
<!-- @change="moreOptionChange">-->
|
||||
<!-- <van-button type="primary" class="margin-top20 width100" @click="$refs.moreDropDownItemOption.toggle()">-->
|
||||
<!-- 查询-->
|
||||
<!-- </van-button>-->
|
||||
<!-- </van-dropdown-item>-->
|
||||
</van-dropdown-menu>
|
||||
</van-sticky>
|
||||
</van-dropdown-menu>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<div class="export-buttons" style="position: fixed; bottom: 0; left: 0; right: 0; padding: 10px; display: flex; gap: 10px; background: white; border-top: 1px solid #eee; z-index: 1000; box-shadow: 0 -2px 8px rgba(0,0,0,0.1);">
|
||||
<van-button type="primary" size="medium" @click="exportXlsx" style="flex: 1;">
|
||||
<i class="fa fa-file-excel-o"></i> 导出Excel
|
||||
</van-button>
|
||||
<van-button type="info" size="medium" @click="exportDocx" style="flex: 1;">
|
||||
<i class="fa fa-file-word-o"></i> 导出Word
|
||||
</van-button>
|
||||
</div>
|
||||
|
||||
<table-list api="/platform/teacherCongress/delegate/read/pageData" :page_form.sync="pageForm" json
|
||||
@ready="onReady"
|
||||
ref="tableListRef"
|
||||
style="padding-bottom: 65px">
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="代表姓名">{{row.userName}}</table-column>
|
||||
<table-column label="代表工号">{{row.loginName}}</table-column>
|
||||
<table-column label="代表团">{{delegationOptions.find(v=>v.id===row.delegationId)?.name}}</table-column>
|
||||
<table-column label="代表身份">
|
||||
{{moreOptions.find(v=>v.title==='代表身份')?.options.find(v=>v.id===row.roleId)?.name}}
|
||||
</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span>查看</span>
|
||||
<div class="delegate-read-list">
|
||||
<table-list api="/platform/teacherCongress/delegate/read/pageData" :page_form.sync="pageForm"
|
||||
:class="{'is-empty': pageForm.totalCount === 0}" json
|
||||
:show_loading_overlay="!pageSkeletonLoading"
|
||||
@ready="onReady"
|
||||
@loading-change="onListLoadingChange"
|
||||
ref="tableListRef"
|
||||
title="userName">
|
||||
<template #empty>
|
||||
<div v-if="!listLoading" class="delegate-read-empty">
|
||||
<img src="/assets/mobile/img/democratic/teachercongress/delegate-read-empty.png" alt="暂无代表信息插画">
|
||||
<div class="delegate-read-empty__title">暂无代表信息</div>
|
||||
<div class="delegate-read-empty__hint">当前筛选条件下暂时没有可阅览的代表</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #header></template>
|
||||
<template v-slot="{index,row}">
|
||||
<div class="delegate-card">
|
||||
<div class="delegate-card__avatar" :class="{'is-female': row.sex === '女'}">
|
||||
<van-icon name="manager"></van-icon>
|
||||
</div>
|
||||
<div class="delegate-card__body">
|
||||
<div class="delegate-card__name">{{row.userName || '--'}}</div>
|
||||
<div class="delegate-card__row">
|
||||
<div class="delegate-card__label"><i class="fa fa-id-card-o"></i>代表工号</div>
|
||||
<div class="delegate-card__value">{{row.loginName || '--'}}</div>
|
||||
</div>
|
||||
<div class="delegate-card__row">
|
||||
<div class="delegate-card__label"><i class="fa fa-sitemap"></i>代表团</div>
|
||||
<div class="delegate-card__value">{{delegationOptions.find(v=>v.id===row.delegationId)?.name || '--'}}</div>
|
||||
</div>
|
||||
<div class="delegate-card__row">
|
||||
<div class="delegate-card__label"><i class="fa fa-user-o"></i>代表身份</div>
|
||||
<div class="delegate-card__value">{{moreOptions.find(v=>v.title==='代表身份')?.options.find(v=>v.id===row.roleId)?.name || '--'}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
</div>
|
||||
|
||||
<div v-show="!pageSkeletonLoading" class="delegate-read-actions">
|
||||
<van-button class="delegate-read-action is-excel" size="medium" @click="exportXlsx">
|
||||
<i class="fa fa-file-excel-o"></i> 导出Excel
|
||||
</van-button>
|
||||
<van-button class="delegate-read-action is-word" type="primary" size="medium" @click="exportDocx">
|
||||
<i class="fa fa-file-word-o"></i> 导出Word
|
||||
</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
@@ -81,11 +573,39 @@ layout("/layouts/platform_h5.html"){
|
||||
delegationOptions: [],
|
||||
roleOptions: [],
|
||||
|
||||
moreOptions: []
|
||||
moreOptions: [],
|
||||
filterOpened: false,
|
||||
pageSkeletonLoading: true,
|
||||
initialPendingCount: 0,
|
||||
initialListLoadingTracked: false,
|
||||
listLoading: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
historyBack,
|
||||
beginInitialLoad() {
|
||||
this.initialPendingCount++
|
||||
},
|
||||
endInitialLoad() {
|
||||
this.initialPendingCount = Math.max(0, this.initialPendingCount - 1)
|
||||
if (this.initialPendingCount === 0) {
|
||||
this.pageSkeletonLoading = false
|
||||
}
|
||||
},
|
||||
onListLoadingChange({loading, initial}) {
|
||||
this.listLoading = loading
|
||||
if (!initial || !this.pageSkeletonLoading) return
|
||||
if (loading && !this.initialListLoadingTracked) {
|
||||
this.initialListLoadingTracked = true
|
||||
this.beginInitialLoad()
|
||||
} else if (!loading && this.initialListLoadingTracked) {
|
||||
this.initialListLoadingTracked = false
|
||||
this.endInitialLoad()
|
||||
}
|
||||
},
|
||||
setFilterOpened(value) {
|
||||
this.$set(this, "filterOpened", value)
|
||||
},
|
||||
|
||||
moreOptionChange(options) {
|
||||
this.moreOptions = options
|
||||
@@ -116,16 +636,21 @@ layout("/layouts/platform_h5.html"){
|
||||
this.doSearch()
|
||||
},
|
||||
listSession() {
|
||||
this.$axios.post("/platform/proposal/common/listSession").then((res) => {
|
||||
this.beginInitialLoad()
|
||||
return this.$axios.post("/platform/proposal/common/listSession").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.sessionOptions = res.data.map((v) => ({text: v.fullName, value: v.id}))
|
||||
this.pageForm.sessionId = res.data[0].id
|
||||
this.sessionChange()
|
||||
}
|
||||
}).finally(() => {
|
||||
this.endInitialLoad()
|
||||
})
|
||||
},
|
||||
listDelegation() {
|
||||
this.$axios.post("/platform/proposal/common/listDelegation", {sessionId: this.pageForm.sessionId}).then((res) => {
|
||||
const isInitialLoad = this.pageSkeletonLoading
|
||||
if (isInitialLoad) this.beginInitialLoad()
|
||||
return this.$axios.post("/platform/proposal/common/listDelegation", {sessionId: this.pageForm.sessionId}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.delegationOptions = [
|
||||
{
|
||||
@@ -134,16 +659,21 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
].concat(res.data.map((v) => ({...v, text: v.name, value: v.id})))
|
||||
}
|
||||
}).finally(() => {
|
||||
if (isInitialLoad) this.endInitialLoad()
|
||||
})
|
||||
},
|
||||
listRole() {
|
||||
this.$axios.post("/platform/teacherCongress/common/listDelegateRole").then((res) => {
|
||||
this.beginInitialLoad()
|
||||
return this.$axios.post("/platform/teacherCongress/common/listDelegateRole").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.moreOptions.push({
|
||||
title: "代表身份",
|
||||
options: res.data.map((v) => ({...v, text: v.name}))
|
||||
})
|
||||
}
|
||||
}).finally(() => {
|
||||
this.endInitialLoad()
|
||||
})
|
||||
},
|
||||
doSearch() {
|
||||
|
||||
+1189
-375
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<div id="app" v-cloak>
|
||||
<div class="swufe-mobile-page" id="app" v-cloak>
|
||||
<van-nav-bar @click-left="back" left-arrow left-text="返回" placeholder title="幸福工荟详情"></van-nav-bar>
|
||||
<van-image :src="previewUrl(detail.cover)" fit="cover" height="220" v-if="detail.cover" width="100%"></van-image>
|
||||
<van-cell-group>
|
||||
@@ -21,16 +21,16 @@ layout("/layouts/platform_h5.html"){
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
data: function () { return {id: "", detail: {}} },
|
||||
computed: { hasLink: function () { return !!(this.detail.linkUrl && this.detail.linkUrl.trim()) } },
|
||||
data() { return {id: "", detail: {}} },
|
||||
computed: { hasLink() { return !!(this.detail.linkUrl && this.detail.linkUrl.trim()) } },
|
||||
methods: {
|
||||
back: function () { history.back() },
|
||||
previewUrl: function (cover) { return cover || "" },
|
||||
formatDate: function (value) { return value ? moment(value).format("YYYY-MM-DD") : "" },
|
||||
findOne: function () { var self = this; $.post("/platform/h5/inclusive/findOne", {id: this.id}).then(function (res) { if (res.code === 0 && res.data) { self.$set(self, "detail", res.data) } else { self.$toast(res.msg || "未查询到活动详情") } }) },
|
||||
openLink: function () { if (this.hasLink) { window.location.href = this.detail.linkUrl.trim() } }
|
||||
back() { history.back() },
|
||||
previewUrl(cover) { return cover || "" },
|
||||
formatDate(value) { return value ? moment(value).format("YYYY-MM-DD") : "" },
|
||||
findOne() { var self = this; $.post("/platform/h5/inclusive/findOne", {id: this.id}).then((res) => { if (res.code === 0 && res.data) { self.$set(self, "detail", res.data) } else { self.$toast(res.msg || "未查询到活动详情") } }) },
|
||||
openLink() { if (this.hasLink) { window.location.href = this.detail.linkUrl.trim() } }
|
||||
},
|
||||
created: function () { this.$set(this, "id", GetQueryString("id")); this.findOne() }
|
||||
created() { this.$set(this, "id", GetQueryString("id")); this.findOne() }
|
||||
})
|
||||
</script>
|
||||
<!--#
|
||||
|
||||
@@ -25,7 +25,7 @@ layout("/layouts/platform_h5.html"){
|
||||
.inclusive-empty { min-height: 320px; display: flex; align-items: center; justify-content: center; flex-direction: column; color: #909399; font-size: 14px; background: transparent; }
|
||||
.inclusive-empty-icon { width: 120px; height: 120px; margin-bottom: 10px; opacity: .56; }
|
||||
</style>
|
||||
<div id="app" v-cloak>
|
||||
<div class="swufe-mobile-page" id="app" v-cloak>
|
||||
<van-nav-bar @click-left="back" fixed left-arrow left-text="返回" placeholder title="幸福工荟"></van-nav-bar>
|
||||
<van-sticky :offset-top="46">
|
||||
<div class="inclusive-tab-wrap">
|
||||
@@ -59,31 +59,31 @@ layout("/layouts/platform_h5.html"){
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
data: function () { return {activeTag: "", tagOptions: [], tableData: [], loading: false, refreshing: false, finished: false, pageForm: {pageNumber: 1, pageSize: 6, totalCount: 0, tagType: ""}} },
|
||||
data() { return {activeTag: "", tagOptions: [], tableData: [], loading: false, refreshing: false, finished: false, pageForm: {pageNumber: 1, pageSize: 6, totalCount: 0, tagType: ""}} },
|
||||
methods: {
|
||||
previewUrl: function (cover) { return cover || "" },
|
||||
formatDate: function (value) { return value ? moment(value).format("YYYY-MM-DD") : "" },
|
||||
back: function () { history.back() },
|
||||
getTagOptions: function () { var self = this; $.post("/platform/h5/inclusive/tagOptions", {}).then(function (res) { if (res.code === 0) { self.$set(self, "tagOptions", res.data || []) } }) },
|
||||
pageData: function () {
|
||||
previewUrl(cover) { return cover || "" },
|
||||
formatDate(value) { return value ? moment(value).format("YYYY-MM-DD") : "" },
|
||||
back() { history.back() },
|
||||
getTagOptions() { var self = this; $.post("/platform/h5/inclusive/tagOptions", {}).then((res) => { if (res.code === 0) { self.$set(self, "tagOptions", res.data || []) } }) },
|
||||
pageData() {
|
||||
var self = this;
|
||||
this.$set(this, "loading", true);
|
||||
this.$set(this.pageForm, "tagType", this.activeTag);
|
||||
$.post("/platform/h5/inclusive/pageData", this.pageForm).then(function (res) {
|
||||
$.post("/platform/h5/inclusive/pageData", this.pageForm).then((res) => {
|
||||
if (self.refreshing) { self.$set(self, "tableData", []); self.$set(self, "refreshing", false) }
|
||||
if (res.code === 0) {
|
||||
var data = res.data || {}; var list = data.list || [];
|
||||
self.$set(self, "tableData", self.tableData.concat(list)); self.$set(self.pageForm, "totalCount", data.totalCount || 0);
|
||||
if (self.tableData.length >= self.pageForm.totalCount) { self.$set(self, "finished", true) } else { self.$set(self.pageForm, "pageNumber", self.pageForm.pageNumber + 1) }
|
||||
} else { self.$toast(res.msg || "查询失败") }
|
||||
}).always(function () { self.$set(self, "loading", false) })
|
||||
}).always(() => { self.$set(self, "loading", false) })
|
||||
},
|
||||
resetList: function () { this.$set(this, "tableData", []); this.$set(this, "finished", false); this.$set(this.pageForm, "pageNumber", 1); this.$set(this.pageForm, "totalCount", 0) },
|
||||
tagChange: function (value) { this.$set(this, "activeTag", value); this.resetList(); this.pageData() },
|
||||
onRefresh: function () { this.resetList(); this.$set(this, "refreshing", true); this.pageData() },
|
||||
openDetail: function (item) { window.location.href = "/platform/h5/inclusive/detail?id=" + item.id }
|
||||
resetList() { this.$set(this, "tableData", []); this.$set(this, "finished", false); this.$set(this.pageForm, "pageNumber", 1); this.$set(this.pageForm, "totalCount", 0) },
|
||||
tagChange(value) { this.$set(this, "activeTag", value); this.resetList(); this.pageData() },
|
||||
onRefresh() { this.resetList(); this.$set(this, "refreshing", true); this.pageData() },
|
||||
openDetail(item) { window.location.href = "/platform/h5/inclusive/detail?id=" + item.id }
|
||||
},
|
||||
created: function () { this.getTagOptions() }
|
||||
created() { this.getTagOptions() }
|
||||
})
|
||||
</script>
|
||||
<!--#
|
||||
|
||||
@@ -467,17 +467,15 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
methods: {
|
||||
historyBack,
|
||||
async loadOptions() {
|
||||
const [typeResp, recommendResp] = await Promise.all([
|
||||
this.$axios.post(this.apiBase + "/courseTypes"),
|
||||
this.$axios.post(this.apiBase + "/recommendOptions")
|
||||
])
|
||||
loadOptions() {
|
||||
return Promise.all([this.$axios.post(this.apiBase + "/courseTypes"), this.$axios.post(this.apiBase + "/recommendOptions")]).then(([typeResp, recommendResp]) => {
|
||||
if (typeResp.code === 0) {
|
||||
this.courseTypeOptions = typeResp.data || []
|
||||
this.courseTypeOptions = typeResp.data || [];
|
||||
}
|
||||
if (recommendResp.code === 0) {
|
||||
this.recommendOptions = recommendResp.data || []
|
||||
this.recommendOptions = recommendResp.data || [];
|
||||
}
|
||||
});
|
||||
},
|
||||
onRefresh() {
|
||||
this.finished = false
|
||||
@@ -600,9 +598,10 @@ layout("/layouts/platform_h5.html"){
|
||||
return colors[index % colors.length]
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
await this.loadOptions()
|
||||
this.onLoad()
|
||||
mounted() {
|
||||
return this.loadOptions().then(() => {
|
||||
this.onLoad();
|
||||
});
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
+172
-10
@@ -2,12 +2,174 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
#app {
|
||||
--color-primary: #1989fa;
|
||||
}
|
||||
|
||||
#app > .van-nav-bar .van-icon,
|
||||
#app > .van-nav-bar .van-nav-bar__text {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
#app > .van-nav-bar .van-nav-bar__title,
|
||||
#app > .van-nav-bar .van-nav-bar__text,
|
||||
#app > .van-nav-bar .van-nav-bar__arrow {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.search-dialog {
|
||||
height: 80%;
|
||||
}
|
||||
|
||||
/* 补贴申请页复用提案撰写页的 Card 层级,仅覆盖当前表单分组和底部操作栏。 */
|
||||
.condolence-apply-form.form-container {
|
||||
min-height: 100%;
|
||||
padding: 12px 15px calc(84px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background: #f3f7fc;
|
||||
}
|
||||
|
||||
.condolence-apply-form .form-section {
|
||||
margin-bottom: 11px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #e9eff7;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
box-shadow: 0 3px 11px rgba(51, 87, 126, 0.08);
|
||||
}
|
||||
|
||||
.condolence-apply-form .condolence-card__title {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
padding: 12px 14px 8px 21px;
|
||||
color: #354255;
|
||||
font-size: 15px;
|
||||
line-height: 20px;
|
||||
font-weight: 600;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.condolence-apply-form .condolence-card__title::before {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
bottom: 11px;
|
||||
left: 12px;
|
||||
width: 2px;
|
||||
border-radius: 2px;
|
||||
background: #1989fa;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.condolence-apply-form .form-section .van-cell-group {
|
||||
margin: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.condolence-card__desc {
|
||||
padding: 0 14px 8px 21px;
|
||||
color: orangered;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.condolence-apply-form .form-section .van-cell {
|
||||
min-height: 44px;
|
||||
padding: 10px 14px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.condolence-apply-form .form-section .van-cell:not(:last-child)::after {
|
||||
right: 14px;
|
||||
left: 14px;
|
||||
border-color: #eef2f7;
|
||||
}
|
||||
|
||||
.condolence-apply-form .form-section .van-field__label {
|
||||
width: 84px;
|
||||
color: #596779;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.condolence-apply-form .form-section .van-field__value,
|
||||
.condolence-apply-form .form-section .van-field__control {
|
||||
color: #4f5d70;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.condolence-apply-form .form-section .van-field__control::placeholder {
|
||||
color: #b1bac6;
|
||||
}
|
||||
|
||||
.condolence-apply-form .form-section .van-cell--required::before {
|
||||
left: 6px;
|
||||
color: #f06464;
|
||||
}
|
||||
|
||||
.condolence-apply-actions {
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
gap: 9px;
|
||||
padding: 10px 18px calc(10px + env(safe-area-inset-bottom));
|
||||
border-top: 1px solid #edf1f6;
|
||||
background: rgba(255, 255, 255, 0.98);
|
||||
box-shadow: 0 -4px 14px rgba(50, 78, 112, 0.06);
|
||||
}
|
||||
|
||||
.condolence-apply-actions .van-button {
|
||||
height: 40px;
|
||||
margin: 0;
|
||||
border-radius: 14px !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.condolence-apply-actions .van-button:first-child {
|
||||
flex: 1;
|
||||
color: #1989fa;
|
||||
border-color: #1989fa;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.condolence-apply-actions .van-button:last-child {
|
||||
flex: 1.08;
|
||||
border-color: #1989fa;
|
||||
background: #1989fa;
|
||||
}
|
||||
|
||||
#app .van-action-sheet__header,
|
||||
#app .van-picker__title,
|
||||
.van-dialog__header {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
#app .van-action-sheet__name,
|
||||
#app .van-action-sheet__cancel,
|
||||
#app .van-empty__description,
|
||||
#app .van-search__field,
|
||||
#app .van-picker__cancel,
|
||||
#app .van-picker__confirm,
|
||||
.van-dialog__message {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
#app .van-picker-column__item {
|
||||
font-size: 18px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app">
|
||||
<van-nav-bar title="填写补贴申请" left-text="返回" left-arrow @click-left="historyBack" fixed
|
||||
placeholder></van-nav-bar>
|
||||
|
||||
<van-form ref="formRef" class="form-container">
|
||||
<van-cell-group title="申请信息" class="form-section">
|
||||
<van-form ref="formRef" class="form-container condolence-apply-form">
|
||||
<section class="form-section"><h2 class="condolence-card__title">申请信息</h2><van-cell-group :border="false">
|
||||
<van-field label="申请人" v-model="formData.applyUserName" readonly name="applyUserName"></van-field>
|
||||
<van-field label="申请时间" v-model="formData.createTime" readonly name="createTime"></van-field>
|
||||
|
||||
@@ -70,7 +232,7 @@ layout("/layouts/platform_h5.html"){
|
||||
:rules="[{ required: true, message: '请选择出生年月' }]"
|
||||
@click="showBirthdayPickerClick"
|
||||
></van-field>
|
||||
<van-popup position="bottom" round v-model:show="showBirthdayPicker">
|
||||
<van-popup position="bottom" round v-model="showBirthdayPicker">
|
||||
<van-datetime-picker
|
||||
v-model="birthdayDate"
|
||||
type="date"
|
||||
@@ -94,7 +256,7 @@ layout("/layouts/platform_h5.html"){
|
||||
clickable
|
||||
is-link
|
||||
></van-field>
|
||||
<van-popup position="bottom" round v-model:show="showTypePicker">
|
||||
<van-popup position="bottom" round v-model="showTypePicker">
|
||||
<van-picker :columns="typeColumns" @cancel="closeTypePicker" @confirm="onTypeConfirm"
|
||||
show-toolbar :default-index="typeDefaultIndex"></van-picker>
|
||||
</van-popup>
|
||||
@@ -161,9 +323,9 @@ layout("/layouts/platform_h5.html"){
|
||||
:rules="[{ required: true, message: '请填写申请事由' }]"
|
||||
required
|
||||
></van-field>
|
||||
</van-cell-group>
|
||||
</van-cell-group></section>
|
||||
|
||||
<van-cell-group title="纸质申请表" class="form-section">
|
||||
<section class="form-section"><h2 class="condolence-card__title">纸质申请表</h2><van-cell-group :border="false">
|
||||
<van-field class="direction-column-field" name="applyFiles" label="">
|
||||
<template #input>
|
||||
<h5-file-upload
|
||||
@@ -175,9 +337,9 @@ layout("/layouts/platform_h5.html"){
|
||||
></h5-file-upload>
|
||||
</template>
|
||||
</van-field>
|
||||
</van-cell-group>
|
||||
</van-cell-group></section>
|
||||
|
||||
<van-cell-group title="附件" class="form-section">
|
||||
<section class="form-section"><h2 class="condolence-card__title">附件</h2><van-cell-group :border="false">
|
||||
<van-field class="direction-column-field" name="files" label="">
|
||||
<template #input>
|
||||
<h5-file-upload
|
||||
@@ -189,9 +351,9 @@ layout("/layouts/platform_h5.html"){
|
||||
></h5-file-upload>
|
||||
</template>
|
||||
</van-field>
|
||||
</van-cell-group>
|
||||
</van-cell-group></section>
|
||||
|
||||
<div v-if="bizId || !applyClosed" class="form-actions">
|
||||
<div v-if="bizId || !applyClosed" class="form-actions condolence-apply-actions">
|
||||
<van-button native-type="button" :loading="formLoading" @click="onSave" round type="info" plain>
|
||||
保存申请
|
||||
</van-button>
|
||||
|
||||
+235
-82
@@ -2,35 +2,101 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
<style>
|
||||
#app { --color-primary: #1989fa; }
|
||||
.condolence-list-page { min-height: 100vh; padding-bottom: calc(24px + env(safe-area-inset-bottom)); box-sizing: border-box; background: #f3f7fd; }
|
||||
.condolence-list-page .van-nav-bar, .condolence-list-page .van-sticky--fixed { background: #fff; }
|
||||
.condolence-list-page .van-nav-bar__title { color: #172033; font-size: 16px; font-weight: 600; }
|
||||
.condolence-list-page .van-nav-bar .van-icon, .condolence-list-page .van-nav-bar__text { color: #1989fa; }
|
||||
.condolence-list-sticky { padding: 22px 12px 1px; box-sizing: border-box; background: #f3f7fd; }
|
||||
.condolence-list-search { margin: 0 0 8px; padding: 0; overflow: hidden; border-radius: 12px; background: #fff; box-shadow: 0 5px 16px rgba(43, 73, 112, .1); }
|
||||
.condolence-list-search .van-search__content { height: 42px; padding-left: 12px; align-items: center; border-radius: 12px; background: #fff; }
|
||||
.condolence-list-search .van-field__control { color: #263548; font-size: 14px; }
|
||||
.condolence-list-search .van-field__control::placeholder { color: #a7b0bf; }
|
||||
.condolence-list-filter { margin-bottom: 8px; overflow: hidden; border-radius: 10px; box-shadow: 0 5px 16px rgba(43, 73, 112, .08); }
|
||||
.condolence-list-filter .van-dropdown-menu__bar { height: 44px; box-shadow: none; }
|
||||
.condolence-list-filter .van-dropdown-menu__item, .condolence-list-filter .van-dropdown-menu__title { height: 44px; }
|
||||
.condolence-list-filter .van-dropdown-menu__item { align-items: center; justify-content: center; }
|
||||
.condolence-list-filter .van-dropdown-menu__title { display: inline-flex; align-items: center; line-height: 20px; color: #66758a; font-size: 14px; }
|
||||
.condolence-list-filter .van-dropdown-menu__title--active, .condolence-list-filter .van-dropdown-item__option--active, .condolence-list-filter .van-dropdown-item__option--active .van-dropdown-item__icon { color: #1989fa; }
|
||||
.condolence-list-filter .van-dropdown-item__content { width: calc(100% - 24px); margin: 0 12px; overflow: hidden; box-sizing: border-box; border-radius: 0 0 12px 12px; box-shadow: 0 10px 24px rgba(31, 65, 108, .14); }
|
||||
.condolence-list-filter .van-dropdown-item__option { display: flex; min-height: 48px; padding: 0 16px; align-items: center; color: #46566c; font-size: 14px; }
|
||||
.condolence-list-filter .van-dropdown-item__option .van-cell__title { display: flex; min-height: 20px; align-items: center; line-height: 20px; }
|
||||
.condolence-list-content { padding: 0 12px; }
|
||||
.condolence-list-skeleton { padding-top: 2px; }
|
||||
.condolence-list-skeleton__card { margin-bottom: 12px; padding: 18px 14px 14px; border: 1px solid #e9eff7; border-radius: 12px; background: #fff; box-shadow: 0 5px 16px rgba(43, 73, 112, .08); }
|
||||
.condolence-list-skeleton__card .van-skeleton { padding: 0; }
|
||||
.condolence-list-skeleton__card .van-skeleton__title { width: 42%; height: 18px; margin-bottom: 18px; }
|
||||
.condolence-list-skeleton__card .van-skeleton__row { height: 14px; margin-top: 12px; }
|
||||
.condolence-list-skeleton__card .van-skeleton__row:nth-child(2n) { width: 72% !important; }
|
||||
.condolence-list-skeleton__card .van-skeleton__row:last-child { width: 34% !important; margin-top: 18px; margin-left: auto; }
|
||||
.condolence-list-page .table-list-container { margin-top: 0; padding-bottom: 2px; }
|
||||
.condolence-list-page .table-list-container .table-list-item { margin-bottom: 12px; padding: 14px; border: 1px solid #e9eff7; border-radius: 12px; box-shadow: 0 5px 16px rgba(43, 73, 112, .08); }
|
||||
.condolence-card-header { display: flex; margin-bottom: 8px; align-items: flex-start; justify-content: space-between; }
|
||||
.condolence-card-heading { min-width: 0; padding-right: 10px; flex: 1; }
|
||||
.condolence-card-title { overflow: hidden; color: #253247; font-size: 15px; font-weight: 600; line-height: 22px; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.condolence-card-code { margin-top: 1px; color: #9ba6b6; font-size: 12px; line-height: 18px; }
|
||||
.condolence-card-status { display: inline-flex; flex: none; }
|
||||
.condolence-card-status .van-tag { min-height: 24px; padding: 3px 9px; border: 0; border-radius: 12px; box-sizing: border-box; font-size: 12px; line-height: 18px; }
|
||||
.condolence-list-page .table-list-container .table-list-item .item-actions { margin-top: 10px; padding-top: 10px; border-top-color: #edf1f6; }
|
||||
.condolence-list-page .table-list-container .table-list-item .action-btn { min-height: 28px; padding: 4px 11px; border-radius: 14px; color: #1989fa; background: #eaf4ff; font-size: 12px; line-height: 18px; }
|
||||
.condolence-list-page .table-list-container .table-list-item .action-btn.delete { color: #f04444; background: #fff0f0; }
|
||||
.condolence-list-page .table-list-container .table-list-item .action-btn i { margin-right: 5px; font-size: 13px; }
|
||||
.condolence-list-page .empty-state { padding: 0; }
|
||||
.condolence-list-empty { display: flex; min-height: 280px; padding: 46px 18px 36px; align-items: center; justify-content: center; box-sizing: border-box; flex-direction: column; text-align: center; }
|
||||
.condolence-list-empty img { display: block; width: 86%; max-width: 290px; height: auto; object-fit: contain; }
|
||||
.condolence-list-empty__title { margin-top: 14px; color: #50627a; font-size: 15px; font-weight: 600; line-height: 22px; }
|
||||
.condolence-list-empty__hint { margin-top: 5px; color: #9aa7b8; font-size: 12px; line-height: 18px; }
|
||||
</style>
|
||||
|
||||
<style id="style-condolence-info-h5">
|
||||
<!--#include("../common/info.css"){}#-->
|
||||
</style>
|
||||
|
||||
<div id="app">
|
||||
<div class="condolence-list-page">
|
||||
<van-nav-bar title="分工会审核" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
|
||||
<van-sticky offset-top="46px">
|
||||
<div class="condolence-list-sticky">
|
||||
<van-search
|
||||
v-model="pageForm.searchKeyword"
|
||||
:show-action="false"
|
||||
:reverse-color="false"
|
||||
input-align="left"
|
||||
class="condolence-list-search"
|
||||
placeholder="请输入姓名或者工号搜索"
|
||||
shape="round"
|
||||
clearable
|
||||
@search="doSearch"
|
||||
@clear="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-menu class="condolence-list-filter" :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<year-van-dropdown-item :num="5" @change="doSearch" v-model="pageForm.year"></year-van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.type" :options="typeOptions" :multiple="false"
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.approvalText" :options="approvalOptions" :multiple="false"
|
||||
@change="onApprovalFilterChange"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<table-list api="/platform/condolence/branchUnionApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" @ready="onReady">
|
||||
<main class="condolence-list-content">
|
||||
<div class="condolence-list-skeleton" v-if="skeletonLoading">
|
||||
<div class="condolence-list-skeleton__card" v-for="index in 3" :key="'branch-approval-skeleton-' + index">
|
||||
<van-skeleton title :row="5" animated></van-skeleton>
|
||||
</div>
|
||||
</div>
|
||||
<table-list api="/platform/condolence/branchUnionApproval/pageData" :page_form.sync="pageForm" ref="tableListRef"
|
||||
v-show="!skeletonLoading" :show_loading_overlay="false" @ready="onReady"
|
||||
@loading-change="handleListLoadingChange">
|
||||
<template #header="{index,row}">
|
||||
<div class="condolence-card-header">
|
||||
<div class="condolence-card-heading">
|
||||
<div class="condolence-card-title">{{row.helpUserName || '--'}}</div>
|
||||
<div class="condolence-card-code">工号:{{row.helpLoginName || '--'}}</div>
|
||||
</div>
|
||||
<enum-tag class="condolence-card-status" v-if="row.instanceState" :value="row.instanceState"
|
||||
name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="补贴对象">{{row.helpUserName}}</table-column>
|
||||
<table-column label="补贴对象工号">{{row.helpLoginName}}</table-column>
|
||||
@@ -42,42 +108,65 @@ layout("/layouts/platform_h5.html"){
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<van-icon name="eye-o"></van-icon>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
|
||||
<i class="fa fa-edit"></i>
|
||||
<van-icon name="edit"></van-icon>
|
||||
<span>审核</span>
|
||||
</div>
|
||||
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">
|
||||
<i class="fa fa-reply"></i>
|
||||
<van-icon name="revoke"></van-icon>
|
||||
<span>撤回</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #empty>
|
||||
<div class="condolence-list-empty">
|
||||
<img src="/assets/mobile/img/condolence/condolence-empty.png" alt="暂无补贴审核记录插画">
|
||||
<div class="condolence-list-empty__title">暂无补贴审核记录</div>
|
||||
<div class="condolence-list-empty__hint">当前筛选条件下暂时没有补贴申请</div>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
</main>
|
||||
|
||||
<info ref="infoRef">
|
||||
<info ref="infoRef" page-key="condolence-branch-union-detail">
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">{{formData.taskName}}</div>
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
v-model="formData.tf_opinion"
|
||||
name="tf_opinion"
|
||||
label="审批意见"
|
||||
placeholder="请输入审批意见"
|
||||
:rules="[{ required: true, message: '请填写审批意见' }]"
|
||||
required
|
||||
maxlength="100"
|
||||
show-word-limit
|
||||
></van-field>
|
||||
</van-form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(20)">不同意</van-button>
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">同意</van-button>
|
||||
<section class="condolence-info-card">
|
||||
<h2 class="condolence-info-card__title">
|
||||
审批意见<span class="condolence-audit-card__required">*</span>
|
||||
</h2>
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
v-model="formData.tf_opinion"
|
||||
class="condolence-audit-field"
|
||||
name="tf_opinion"
|
||||
type="textarea"
|
||||
rows="6"
|
||||
placeholder="请输入审批意见"
|
||||
:rules="[{ required: true, message: '请填写审批意见' }]"
|
||||
maxlength="100"
|
||||
show-word-limit
|
||||
></van-field>
|
||||
</van-form>
|
||||
</section>
|
||||
<div class="condolence-popup-actions">
|
||||
<van-button class="condolence-action-danger" type="danger" block :loading="formLoading" @click="handleTaskAction(6)">退回</van-button>
|
||||
<van-button class="condolence-action-danger" type="danger" block :loading="formLoading" @click="handleTaskAction(20)">不同意</van-button>
|
||||
<van-button class="condolence-action-primary" type="primary" block :loading="formLoading" @click="handleTaskAction(1)">同意</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</info>
|
||||
<van-dialog
|
||||
:value="confirmVisible"
|
||||
title="提示"
|
||||
:message="confirmActionType === 'revoke' ? '您确定要撤回吗?' : '您确定要提交吗?'"
|
||||
show-cancel-button
|
||||
confirm-button-color="#1989fa"
|
||||
@confirm="confirmPendingAction"
|
||||
@cancel="closeActionConfirm"
|
||||
></van-dialog>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
@@ -101,78 +190,133 @@ layout("/layouts/platform_h5.html"){
|
||||
type: null,
|
||||
},
|
||||
typeOptions: [],
|
||||
approvalOptions: [
|
||||
{text: "未审核", value: "0"},
|
||||
{text: "已审核", value: "1"}
|
||||
],
|
||||
skeletonLoading: true,
|
||||
formData: {},
|
||||
showApprovalForm: false
|
||||
showApprovalForm: false,
|
||||
formLoading: false,
|
||||
confirmVisible: false,
|
||||
confirmActionType: "task",
|
||||
pendingSubmitType: null,
|
||||
pendingRevokeRow: null,
|
||||
historyLayerUnsubscribe: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async onReady() {
|
||||
const typeList = await this.queryCondolenceType()
|
||||
this.typeOptions = [
|
||||
{
|
||||
text: "全部补贴类型",
|
||||
value: null
|
||||
}
|
||||
].concat(typeList.map((v) => ({ text: v.name, value: v.id })))
|
||||
if (this.typeOptions.length > 0) {
|
||||
this.pageForm.type = this.typeOptions[0].value
|
||||
this.doSearch()
|
||||
}
|
||||
// state.initial 表示当前查询前列表为空,仅此阶段使用整组卡片骨架屏。
|
||||
handleListLoadingChange(state) {
|
||||
if (state.initial) this.$set(this, "skeletonLoading", state.loading)
|
||||
},
|
||||
// 审核状态下拉值为字符串,接口参数 approval 继续使用布尔值。
|
||||
onApprovalFilterChange(val) {
|
||||
this.$set(this.pageForm, "approval", val === "1")
|
||||
this.doSearch()
|
||||
},
|
||||
onReady() {
|
||||
this.queryCondolenceType()
|
||||
},
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
this.$set(this, "showApprovalForm", false)
|
||||
this.$refs.infoRef.onOpen(row, "补贴详情")
|
||||
},
|
||||
onApproval(row) {
|
||||
this.showApprovalForm = true
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
this.formData = {
|
||||
this.$set(this, "showApprovalForm", true)
|
||||
this.$set(this, "formData", {
|
||||
processTaskId: row.taskId,
|
||||
taskName: row.curTaskName
|
||||
}
|
||||
taskName: row.curTaskName,
|
||||
tf_opinion: ""
|
||||
})
|
||||
this.$refs.infoRef.onOpen(row, row.curTaskName || "补贴审核")
|
||||
},
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate();
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: val
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.infoRef.onClose()
|
||||
// val 为流程提交类型:1 同意、20 不同意、6 退回;校验通过后打开历史栈确认框。
|
||||
handleTaskAction(val) {
|
||||
this.$refs.formRef.validate()
|
||||
.then(() => {
|
||||
this.$set(this, "confirmActionType", "task")
|
||||
this.$set(this, "pendingSubmitType", val)
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open("condolence-action-confirm")) return
|
||||
this.$set(this, "confirmVisible", true)
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
// 确认操作时先回退确认框历史,再根据操作类型调用办理或撤回接口。
|
||||
confirmPendingAction() {
|
||||
this.closeActionConfirm(() => {
|
||||
if (this.confirmActionType === "revoke") {
|
||||
this.revokeTask()
|
||||
return
|
||||
}
|
||||
this.submitTaskAction()
|
||||
})
|
||||
},
|
||||
// 提交 processTaskId、taskName、tf_opinion 和 submitType,接口返回统一响应对象。
|
||||
submitTaskAction() {
|
||||
this.$set(this, "formLoading", true)
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: this.pendingSubmitType
|
||||
})
|
||||
})
|
||||
.then((res) => {
|
||||
if (res && res.code === 0) {
|
||||
const afterClose = () => {
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.closeAll(afterClose)) return
|
||||
this.$refs.infoRef.onClose(afterClose)
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.$set(this, "formLoading", false)
|
||||
})
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
},
|
||||
closeActionConfirm(afterClose = null) {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.close("condolence-action-confirm", afterClose)) return
|
||||
this.$set(this, "confirmVisible", false)
|
||||
if (typeof afterClose === "function") afterClose()
|
||||
},
|
||||
// row 提供待撤回任务 taskId,确认后保存当前行并由统一确认框执行撤回。
|
||||
onRevoke(row){
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要撤回吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
|
||||
this.$set(this, "confirmActionType", "revoke")
|
||||
this.$set(this, "pendingRevokeRow", row)
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open("condolence-action-confirm")) return
|
||||
this.$set(this, "confirmVisible", true)
|
||||
},
|
||||
// 使用 pendingRevokeRow.taskId 撤回任务,接口返回统一响应对象。
|
||||
revokeTask() {
|
||||
if (!this.pendingRevokeRow) return
|
||||
this.$set(this, "formLoading", true)
|
||||
this.$axios.post("/flow/common/revokeTask", {taskId: this.pendingRevokeRow.taskId})
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
this.$set(this, "formLoading", false)
|
||||
})
|
||||
},
|
||||
async queryCondolenceType() {
|
||||
const res = await this.$axios.post('/platform/condolence/type/queryCondolenceType')
|
||||
return res.data
|
||||
queryCondolenceType() {
|
||||
this.$axios.post('/platform/condolence/type/queryCondolenceType', {}, {h5SkeletonLoading: true})
|
||||
.then((res) => {
|
||||
const typeList = res.data || []
|
||||
this.$set(this, "typeOptions", [
|
||||
{
|
||||
text: "全部补贴类型",
|
||||
value: null
|
||||
}
|
||||
].concat(typeList.map((v) => ({ text: v.name, value: v.id }))))
|
||||
if (this.typeOptions.length > 0) {
|
||||
this.$set(this.pageForm, "type", this.typeOptions[0].value)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
@@ -182,6 +326,15 @@ layout("/layouts/platform_h5.html"){
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (!window.h5HistoryLayerManager) return
|
||||
this.$set(this, "historyLayerUnsubscribe", window.h5HistoryLayerManager.subscribe((stack) => {
|
||||
this.$set(this, "confirmVisible", stack.includes("condolence-action-confirm"))
|
||||
}))
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (typeof this.historyLayerUnsubscribe === "function") this.historyLayerUnsubscribe()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,10 +1,25 @@
|
||||
const condolenceInfo = {
|
||||
template:
|
||||
/*language=HTML*/
|
||||
`
|
||||
<van-action-sheet v-model="visible" title="查看详情">
|
||||
<div class="detail-container">
|
||||
<van-cell-group title="申请信息">
|
||||
template: /*language=HTML*/ `
|
||||
<van-popup
|
||||
v-model="visible"
|
||||
position="right"
|
||||
class="condolence-full-popup"
|
||||
:close-on-click-overlay="false"
|
||||
get-container="#app"
|
||||
>
|
||||
<div class="condolence-full-popup__page">
|
||||
<van-nav-bar
|
||||
:title="popupTitle"
|
||||
left-arrow
|
||||
left-text="返回"
|
||||
fixed
|
||||
@click-left="onClose()"
|
||||
></van-nav-bar>
|
||||
<div class="condolence-full-popup__scroll">
|
||||
<main class="condolence-info-main">
|
||||
<section class="condolence-info-card">
|
||||
<h2 class="condolence-info-card__title">基本信息</h2>
|
||||
<van-cell-group :border="false">
|
||||
<van-cell title="申请人">{{ viewData.applyUserName }}</van-cell>
|
||||
<van-cell title="申请时间">{{ viewData.createTime }}</van-cell>
|
||||
<van-cell title="补贴对象">{{ viewData.helpUserName }}</van-cell>
|
||||
@@ -30,69 +45,122 @@ const condolenceInfo = {
|
||||
:files="viewData.files" complete_result></file-preview>
|
||||
<span v-else>暂无附件</span>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
<template v-for="task in doneTasks">
|
||||
<van-cell-group :title="task.displayName" v-if="task.ext.isFirstTaskNode">
|
||||
<van-cell title="申请用户">{{ task.ext.initiatorName }}({{task.ext.initiatorAccount}})
|
||||
</van-cell>
|
||||
<van-cell title="申请时间">{{ task.finishTime }}</van-cell>
|
||||
<van-cell title="办理结果">
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
|
||||
:value="task.ext.submitType"></dict-tag>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
<van-cell-group :title="task.displayName" v-else>
|
||||
<van-cell title="办理用户">{{ task.taskFormData.userName }}({{task.taskFormData.loginName}})
|
||||
</van-cell>
|
||||
<van-cell title="办理时间">{{ task.finishTime }}</van-cell>
|
||||
<van-cell title="办理结果">
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
|
||||
:value="task.ext.submitType"></dict-tag>
|
||||
</van-cell>
|
||||
<van-cell title="办理意见" v-if="!task.ext.isFirstTaskNode" class="direction-column-cell">
|
||||
<div v-html="task.taskFormData.tf_opinion"></div>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
</template>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
|
||||
<section
|
||||
v-for="(task, index) in doneTasks"
|
||||
:key="task.id || index"
|
||||
class="condolence-info-card"
|
||||
>
|
||||
<h2 class="condolence-info-card__title">{{ task.displayName || '办理记录' }}</h2>
|
||||
<van-cell-group :border="false" v-if="task.ext && task.ext.isFirstTaskNode">
|
||||
<van-cell title="申请用户">
|
||||
{{ task.ext.initiatorName || '--' }}({{ task.ext.initiatorAccount || '--' }})
|
||||
</van-cell>
|
||||
<van-cell title="申请时间">{{ task.finishTime || '--' }}</van-cell>
|
||||
<van-cell title="办理结果">
|
||||
<dict-tag
|
||||
:options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
|
||||
:value="task.ext.submitType"
|
||||
></dict-tag>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
<van-cell-group :border="false" v-else>
|
||||
<van-cell title="办理用户">
|
||||
{{ task.taskFormData && task.taskFormData.userName || '--' }}({{ task.taskFormData && task.taskFormData.loginName || '--' }})
|
||||
</van-cell>
|
||||
<van-cell title="办理时间">{{ task.finishTime || '--' }}</van-cell>
|
||||
<van-cell title="办理结果">
|
||||
<dict-tag
|
||||
:options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
|
||||
:value="task.ext && task.ext.submitType"
|
||||
></dict-tag>
|
||||
</van-cell>
|
||||
<van-cell class="condolence-info-long-cell" title="办理意见">
|
||||
<div v-html="task.taskFormData && task.taskFormData.tf_opinion || '暂无'"></div>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
|
||||
<slot></slot>
|
||||
</main>
|
||||
</div>
|
||||
<slot></slot>
|
||||
</van-action-sheet>
|
||||
`,
|
||||
</div>
|
||||
</van-popup>
|
||||
`,
|
||||
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
|
||||
props: {
|
||||
pageKey: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visible:false,
|
||||
visible: false,
|
||||
popupTitle: "补贴详情",
|
||||
viewData: {},
|
||||
doneTasks: [],
|
||||
row: null,
|
||||
historyLayerUnsubscribe: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onOpen(row) {
|
||||
this.row = row
|
||||
this.visible = true
|
||||
// 浏览器历史变化时,只同步当前补贴详情弹框的显示状态。
|
||||
syncHistoryLayerStack(stack) {
|
||||
this.$set(this, "visible", stack.includes("condolence-detail"))
|
||||
},
|
||||
|
||||
/**
|
||||
* 打开补贴详情或审核弹框。
|
||||
* row 传列表当前行,title 传顶部导航标题;无返回值。
|
||||
*/
|
||||
onOpen(row, title = "补贴详情") {
|
||||
this.$set(this, "row", row)
|
||||
this.$set(this, "popupTitle", title)
|
||||
this.$set(this, "viewData", {})
|
||||
this.$set(this, "doneTasks", [])
|
||||
this.getInfo()
|
||||
this.getDoneTasks()
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open("condolence-detail")) return
|
||||
this.$set(this, "visible", true)
|
||||
},
|
||||
onClose(){
|
||||
this.visible = false
|
||||
|
||||
// 顶部返回按钮与业务主动关闭统一回退弹框对应的浏览器历史。
|
||||
onClose(afterClose = null) {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.close("condolence-detail", afterClose)) return
|
||||
this.$set(this, "visible", false)
|
||||
if (typeof afterClose === "function") afterClose()
|
||||
},
|
||||
|
||||
getInfo() {
|
||||
this.$axios.post("/platform/condolence/mine/info", { id: this.row.id }).then((res) => {
|
||||
this.$axios.post("/platform/condolence/mine/info", {id: this.row.id}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.viewData = res.data
|
||||
this.$set(this, "viewData", res.data || {})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
getDoneTasks() {
|
||||
this.$axios.post("/flow/common/doneTasks", {bizId: this.row.id}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.doneTasks = res.data
|
||||
this.$set(this, "doneTasks", res.data || [])
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
},
|
||||
style: /*language=CSS*/ `
|
||||
|
||||
`
|
||||
created() {
|
||||
if (!window.h5HistoryLayerManager) return
|
||||
window.h5HistoryLayerManager.ensureRegistered(this.pageKey)
|
||||
this.$set(this, "historyLayerUnsubscribe", window.h5HistoryLayerManager.subscribe((stack) => {
|
||||
this.syncHistoryLayerStack(stack)
|
||||
}))
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (typeof this.historyLayerUnsubscribe === "function") this.historyLayerUnsubscribe()
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.pageKey === this.pageKey) {
|
||||
window.h5HistoryLayerManager.unregister(this.pageKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,30 +2,338 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
<style>
|
||||
#app {
|
||||
--color-primary: #1989fa;
|
||||
}
|
||||
|
||||
.condolence-list-page {
|
||||
min-height: 100vh;
|
||||
padding-bottom: calc(24px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background: #f3f7fd;
|
||||
}
|
||||
|
||||
.condolence-list-page .van-nav-bar,
|
||||
.condolence-list-page .van-sticky--fixed {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.condolence-list-page .van-nav-bar__title {
|
||||
color: #172033;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.condolence-list-page .van-nav-bar .van-icon,
|
||||
.condolence-list-page .van-nav-bar__text {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.condolence-list-sticky {
|
||||
padding: 22px 12px 1px;
|
||||
box-sizing: border-box;
|
||||
background: #f3f7fd;
|
||||
}
|
||||
|
||||
.condolence-list-search {
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.condolence-list-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.condolence-list-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.condolence-list-search .van-field__control::placeholder {
|
||||
color: #a7b0bf;
|
||||
}
|
||||
|
||||
.condolence-list-filter {
|
||||
margin-bottom: 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
}
|
||||
|
||||
.condolence-list-filter .van-dropdown-menu__bar {
|
||||
height: 44px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.condolence-list-filter .van-dropdown-menu__item,
|
||||
.condolence-list-filter .van-dropdown-menu__title {
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.condolence-list-filter .van-dropdown-menu__item {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.condolence-list-filter .van-dropdown-menu__title {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
line-height: 20px;
|
||||
color: #66758a;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.condolence-list-filter .van-dropdown-menu__title--active,
|
||||
.condolence-list-filter .van-dropdown-item__option--active,
|
||||
.condolence-list-filter .van-dropdown-item__option--active .van-dropdown-item__icon {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.condolence-list-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
margin: 0 12px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0 0 12px 12px;
|
||||
box-shadow: 0 10px 24px rgba(31, 65, 108, .14);
|
||||
}
|
||||
|
||||
.condolence-list-filter .van-dropdown-item__option {
|
||||
display: flex;
|
||||
min-height: 48px;
|
||||
padding: 0 16px;
|
||||
align-items: center;
|
||||
color: #46566c;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.condolence-list-filter .van-dropdown-item__option .van-cell__title {
|
||||
display: flex;
|
||||
min-height: 20px;
|
||||
align-items: center;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.condolence-list-content {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.condolence-list-skeleton {
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
.condolence-list-skeleton__card {
|
||||
margin-bottom: 12px;
|
||||
padding: 18px 14px 14px;
|
||||
border: 1px solid #e9eff7;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
}
|
||||
|
||||
.condolence-list-skeleton__card .van-skeleton {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.condolence-list-skeleton__card .van-skeleton__title {
|
||||
width: 42%;
|
||||
height: 18px;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.condolence-list-skeleton__card .van-skeleton__row {
|
||||
height: 14px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.condolence-list-skeleton__card .van-skeleton__row:nth-child(2n) {
|
||||
width: 72% !important;
|
||||
}
|
||||
|
||||
.condolence-list-skeleton__card .van-skeleton__row:last-child {
|
||||
width: 34% !important;
|
||||
margin-top: 18px;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.condolence-list-page .table-list-container {
|
||||
margin-top: 0;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.condolence-list-page .table-list-container .table-list-item {
|
||||
margin-bottom: 12px;
|
||||
padding: 14px;
|
||||
border: 1px solid #e9eff7;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
}
|
||||
|
||||
.condolence-card-header {
|
||||
display: flex;
|
||||
margin-bottom: 8px;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.condolence-card-heading {
|
||||
min-width: 0;
|
||||
padding-right: 10px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.condolence-card-title {
|
||||
overflow: hidden;
|
||||
color: #253247;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.condolence-card-code {
|
||||
margin-top: 1px;
|
||||
color: #9ba6b6;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.condolence-card-status {
|
||||
display: inline-flex;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.condolence-card-status .van-tag {
|
||||
min-height: 24px;
|
||||
padding: 3px 9px;
|
||||
border: 0;
|
||||
border-radius: 12px;
|
||||
box-sizing: border-box;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.condolence-list-page .table-list-container .table-list-item .item-actions {
|
||||
margin-top: 10px;
|
||||
padding-top: 10px;
|
||||
border-top-color: #edf1f6;
|
||||
}
|
||||
|
||||
.condolence-list-page .table-list-container .table-list-item .action-btn {
|
||||
min-height: 28px;
|
||||
padding: 4px 11px;
|
||||
border-radius: 14px;
|
||||
color: #1989fa;
|
||||
background: #eaf4ff;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.condolence-list-page .table-list-container .table-list-item .action-btn.delete {
|
||||
color: #f04444;
|
||||
background: #fff0f0;
|
||||
}
|
||||
|
||||
.condolence-list-page .table-list-container .table-list-item .action-btn i {
|
||||
margin-right: 5px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.condolence-list-page .empty-state {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.condolence-list-empty {
|
||||
display: flex;
|
||||
min-height: 280px;
|
||||
padding: 46px 18px 36px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.condolence-list-empty img {
|
||||
display: block;
|
||||
width: 86%;
|
||||
max-width: 290px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.condolence-list-empty__title {
|
||||
margin-top: 14px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.condolence-list-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style id="style-condolence-info-h5">
|
||||
<!--#include("../common/info.css"){}#-->
|
||||
</style>
|
||||
|
||||
<div id="app">
|
||||
<div class="condolence-list-page">
|
||||
<van-nav-bar title="我的申请" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
|
||||
<van-sticky offset-top="46px">
|
||||
<div class="condolence-list-sticky">
|
||||
<van-search
|
||||
v-model="pageForm.searchKeyword"
|
||||
:show-action="false"
|
||||
:reverse-color="false"
|
||||
input-align="left"
|
||||
class="condolence-list-search"
|
||||
placeholder="请输入姓名或者工号搜索"
|
||||
shape="round"
|
||||
clearable
|
||||
@search="doSearch"
|
||||
@clear="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-menu class="condolence-list-filter" :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<year-van-dropdown-item :num="5" @change="doSearch" v-model="pageForm.year"></year-van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.type" :options="typeOptions" :multiple="false"
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<table-list api="/platform/condolence/mine/pageData" :page_form.sync="pageForm" ref="tableListRef" @ready="onReady">
|
||||
<main class="condolence-list-content">
|
||||
<div class="condolence-list-skeleton" v-if="skeletonLoading">
|
||||
<div class="condolence-list-skeleton__card" v-for="index in 3" :key="'mine-skeleton-' + index">
|
||||
<van-skeleton title :row="5" animated></van-skeleton>
|
||||
</div>
|
||||
</div>
|
||||
<table-list api="/platform/condolence/mine/pageData" :page_form.sync="pageForm" ref="tableListRef"
|
||||
v-show="!skeletonLoading" :show_loading_overlay="false" @ready="onReady"
|
||||
@loading-change="handleListLoadingChange">
|
||||
<template #header="{index,row}">
|
||||
<div class="condolence-card-header">
|
||||
<div class="condolence-card-heading">
|
||||
<div class="condolence-card-title">{{row.helpUserName || '--'}}</div>
|
||||
<div class="condolence-card-code">工号:{{row.helpLoginName || '--'}}</div>
|
||||
</div>
|
||||
<enum-tag class="condolence-card-status" v-if="row.instanceState" :value="row.instanceState"
|
||||
name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="补贴对象">{{row.helpUserName}}</table-column>
|
||||
<table-column label="补贴对象工号">{{row.helpLoginName}}</table-column>
|
||||
@@ -37,28 +345,37 @@ layout("/layouts/platform_h5.html"){
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<van-icon name="eye-o"></van-icon>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" @click="onEdit(row)"
|
||||
v-if="row.taskKey === 'startTask' || !row.instanceId">
|
||||
<i class="fa fa-edit"></i>
|
||||
<van-icon name="edit"></van-icon>
|
||||
<span>编辑</span>
|
||||
</div>
|
||||
<div class="action-btn delete" @click="onRevoke(row)"
|
||||
v-if="row.canRevoke">
|
||||
<i class="fa fa-undo"></i>
|
||||
<van-icon name="revoke"></van-icon>
|
||||
<span>撤回</span>
|
||||
</div>
|
||||
<div class="action-btn delete" @click="onDelete(row)"
|
||||
v-if="row.taskKey === 'startTask' || !row.instanceId">
|
||||
<i class="fa fa-trash"></i>
|
||||
<van-icon name="delete-o"></van-icon>
|
||||
<span>删除</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #empty>
|
||||
<div class="condolence-list-empty">
|
||||
<img src="/assets/mobile/img/condolence/condolence-empty.png" alt="暂无补贴申请记录插画">
|
||||
<div class="condolence-list-empty__title">暂无补贴申请记录</div>
|
||||
<div class="condolence-list-empty__hint">当前筛选条件下暂时没有补贴申请</div>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
</main>
|
||||
|
||||
<info ref="infoRef"></info>
|
||||
<info ref="infoRef" page-key="condolence-mine-detail"></info>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
@@ -79,21 +396,28 @@ layout("/layouts/platform_h5.html"){
|
||||
type: null
|
||||
},
|
||||
typeOptions: [],
|
||||
skeletonLoading: true,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async onReady() {
|
||||
const typeList = await this.queryCondolenceType()
|
||||
this.typeOptions = [
|
||||
{
|
||||
text: "全部补贴类型",
|
||||
value: null
|
||||
}
|
||||
].concat(typeList.map((v) => ({ text: v.name, value: v.id })))
|
||||
if (this.typeOptions.length > 0) {
|
||||
this.pageForm.type = this.typeOptions[0].value
|
||||
this.doSearch()
|
||||
}
|
||||
// state.initial 表示当前查询前列表为空,仅此阶段使用整组卡片骨架屏。
|
||||
handleListLoadingChange(state) {
|
||||
if (state.initial) this.$set(this, "skeletonLoading", state.loading)
|
||||
},
|
||||
onReady() {
|
||||
this.queryCondolenceType()
|
||||
.then((typeList) => {
|
||||
this.$set(this, "typeOptions", [
|
||||
{
|
||||
text: "全部补贴类型",
|
||||
value: null
|
||||
}
|
||||
].concat(typeList.map((v) => ({ text: v.name, value: v.id }))))
|
||||
if (this.typeOptions.length > 0) {
|
||||
this.$set(this.pageForm, "type", this.typeOptions[0].value)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
},
|
||||
onRevoke(row) {
|
||||
this.$dialog.confirm({
|
||||
@@ -109,7 +433,7 @@ layout("/layouts/platform_h5.html"){
|
||||
})
|
||||
},
|
||||
onView(row) {
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
this.$refs.infoRef.onOpen(row, "补贴详情")
|
||||
},
|
||||
onEdit(row) {
|
||||
this.$pjaxReplace("/platform/condolence/apply/h5?taskId=" + (row.startTaskId || "") + "&bizId=" + row.id)
|
||||
@@ -131,9 +455,9 @@ layout("/layouts/platform_h5.html"){
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
async queryCondolenceType() {
|
||||
const res = await this.$axios.post('/platform/condolence/type/queryCondolenceType')
|
||||
return res.data
|
||||
queryCondolenceType() {
|
||||
return this.$axios.post('/platform/condolence/type/queryCondolenceType', {}, {h5SkeletonLoading: true})
|
||||
.then((res) => res.data || [])
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
|
||||
+235
-82
@@ -2,35 +2,101 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
<style>
|
||||
#app { --color-primary: #1989fa; }
|
||||
.condolence-list-page { min-height: 100vh; padding-bottom: calc(24px + env(safe-area-inset-bottom)); box-sizing: border-box; background: #f3f7fd; }
|
||||
.condolence-list-page .van-nav-bar, .condolence-list-page .van-sticky--fixed { background: #fff; }
|
||||
.condolence-list-page .van-nav-bar__title { color: #172033; font-size: 16px; font-weight: 600; }
|
||||
.condolence-list-page .van-nav-bar .van-icon, .condolence-list-page .van-nav-bar__text { color: #1989fa; }
|
||||
.condolence-list-sticky { padding: 22px 12px 1px; box-sizing: border-box; background: #f3f7fd; }
|
||||
.condolence-list-search { margin: 0 0 8px; padding: 0; overflow: hidden; border-radius: 12px; background: #fff; box-shadow: 0 5px 16px rgba(43, 73, 112, .1); }
|
||||
.condolence-list-search .van-search__content { height: 42px; padding-left: 12px; align-items: center; border-radius: 12px; background: #fff; }
|
||||
.condolence-list-search .van-field__control { color: #263548; font-size: 14px; }
|
||||
.condolence-list-search .van-field__control::placeholder { color: #a7b0bf; }
|
||||
.condolence-list-filter { margin-bottom: 8px; overflow: hidden; border-radius: 10px; box-shadow: 0 5px 16px rgba(43, 73, 112, .08); }
|
||||
.condolence-list-filter .van-dropdown-menu__bar { height: 44px; box-shadow: none; }
|
||||
.condolence-list-filter .van-dropdown-menu__item, .condolence-list-filter .van-dropdown-menu__title { height: 44px; }
|
||||
.condolence-list-filter .van-dropdown-menu__item { align-items: center; justify-content: center; }
|
||||
.condolence-list-filter .van-dropdown-menu__title { display: inline-flex; align-items: center; line-height: 20px; color: #66758a; font-size: 14px; }
|
||||
.condolence-list-filter .van-dropdown-menu__title--active, .condolence-list-filter .van-dropdown-item__option--active, .condolence-list-filter .van-dropdown-item__option--active .van-dropdown-item__icon { color: #1989fa; }
|
||||
.condolence-list-filter .van-dropdown-item__content { width: calc(100% - 24px); margin: 0 12px; overflow: hidden; box-sizing: border-box; border-radius: 0 0 12px 12px; box-shadow: 0 10px 24px rgba(31, 65, 108, .14); }
|
||||
.condolence-list-filter .van-dropdown-item__option { display: flex; min-height: 48px; padding: 0 16px; align-items: center; color: #46566c; font-size: 14px; }
|
||||
.condolence-list-filter .van-dropdown-item__option .van-cell__title { display: flex; min-height: 20px; align-items: center; line-height: 20px; }
|
||||
.condolence-list-content { padding: 0 12px; }
|
||||
.condolence-list-skeleton { padding-top: 2px; }
|
||||
.condolence-list-skeleton__card { margin-bottom: 12px; padding: 18px 14px 14px; border: 1px solid #e9eff7; border-radius: 12px; background: #fff; box-shadow: 0 5px 16px rgba(43, 73, 112, .08); }
|
||||
.condolence-list-skeleton__card .van-skeleton { padding: 0; }
|
||||
.condolence-list-skeleton__card .van-skeleton__title { width: 42%; height: 18px; margin-bottom: 18px; }
|
||||
.condolence-list-skeleton__card .van-skeleton__row { height: 14px; margin-top: 12px; }
|
||||
.condolence-list-skeleton__card .van-skeleton__row:nth-child(2n) { width: 72% !important; }
|
||||
.condolence-list-skeleton__card .van-skeleton__row:last-child { width: 34% !important; margin-top: 18px; margin-left: auto; }
|
||||
.condolence-list-page .table-list-container { margin-top: 0; padding-bottom: 2px; }
|
||||
.condolence-list-page .table-list-container .table-list-item { margin-bottom: 12px; padding: 14px; border: 1px solid #e9eff7; border-radius: 12px; box-shadow: 0 5px 16px rgba(43, 73, 112, .08); }
|
||||
.condolence-card-header { display: flex; margin-bottom: 8px; align-items: flex-start; justify-content: space-between; }
|
||||
.condolence-card-heading { min-width: 0; padding-right: 10px; flex: 1; }
|
||||
.condolence-card-title { overflow: hidden; color: #253247; font-size: 15px; font-weight: 600; line-height: 22px; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.condolence-card-code { margin-top: 1px; color: #9ba6b6; font-size: 12px; line-height: 18px; }
|
||||
.condolence-card-status { display: inline-flex; flex: none; }
|
||||
.condolence-card-status .van-tag { min-height: 24px; padding: 3px 9px; border: 0; border-radius: 12px; box-sizing: border-box; font-size: 12px; line-height: 18px; }
|
||||
.condolence-list-page .table-list-container .table-list-item .item-actions { margin-top: 10px; padding-top: 10px; border-top-color: #edf1f6; }
|
||||
.condolence-list-page .table-list-container .table-list-item .action-btn { min-height: 28px; padding: 4px 11px; border-radius: 14px; color: #1989fa; background: #eaf4ff; font-size: 12px; line-height: 18px; }
|
||||
.condolence-list-page .table-list-container .table-list-item .action-btn.delete { color: #f04444; background: #fff0f0; }
|
||||
.condolence-list-page .table-list-container .table-list-item .action-btn i { margin-right: 5px; font-size: 13px; }
|
||||
.condolence-list-page .empty-state { padding: 0; }
|
||||
.condolence-list-empty { display: flex; min-height: 280px; padding: 46px 18px 36px; align-items: center; justify-content: center; box-sizing: border-box; flex-direction: column; text-align: center; }
|
||||
.condolence-list-empty img { display: block; width: 86%; max-width: 290px; height: auto; object-fit: contain; }
|
||||
.condolence-list-empty__title { margin-top: 14px; color: #50627a; font-size: 15px; font-weight: 600; line-height: 22px; }
|
||||
.condolence-list-empty__hint { margin-top: 5px; color: #9aa7b8; font-size: 12px; line-height: 18px; }
|
||||
</style>
|
||||
|
||||
<style id="style-condolence-info-h5">
|
||||
<!--#include("../common/info.css"){}#-->
|
||||
</style>
|
||||
|
||||
<div id="app">
|
||||
<div class="condolence-list-page">
|
||||
<van-nav-bar title="校工会预审" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
|
||||
<van-sticky offset-top="46px">
|
||||
<div class="condolence-list-sticky">
|
||||
<van-search
|
||||
v-model="pageForm.searchKeyword"
|
||||
:show-action="false"
|
||||
:reverse-color="false"
|
||||
input-align="left"
|
||||
class="condolence-list-search"
|
||||
placeholder="请输入姓名或者工号搜索"
|
||||
shape="round"
|
||||
clearable
|
||||
@search="doSearch"
|
||||
@clear="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-menu class="condolence-list-filter" :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<year-van-dropdown-item :num="5" @change="doSearch" v-model="pageForm.year"></year-van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.type" :options="typeOptions" :multiple="false"
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.approvalText" :options="approvalOptions" :multiple="false"
|
||||
@change="onApprovalFilterChange"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<table-list api="/platform/condolence/schoolPrincipalApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" @ready="onReady">
|
||||
<main class="condolence-list-content">
|
||||
<div class="condolence-list-skeleton" v-if="skeletonLoading">
|
||||
<div class="condolence-list-skeleton__card" v-for="index in 3" :key="'school-principal-approval-skeleton-' + index">
|
||||
<van-skeleton title :row="5" animated></van-skeleton>
|
||||
</div>
|
||||
</div>
|
||||
<table-list api="/platform/condolence/schoolPrincipalApproval/pageData" :page_form.sync="pageForm" ref="tableListRef"
|
||||
v-show="!skeletonLoading" :show_loading_overlay="false" @ready="onReady"
|
||||
@loading-change="handleListLoadingChange">
|
||||
<template #header="{index,row}">
|
||||
<div class="condolence-card-header">
|
||||
<div class="condolence-card-heading">
|
||||
<div class="condolence-card-title">{{row.helpUserName || '--'}}</div>
|
||||
<div class="condolence-card-code">工号:{{row.helpLoginName || '--'}}</div>
|
||||
</div>
|
||||
<enum-tag class="condolence-card-status" v-if="row.instanceState" :value="row.instanceState"
|
||||
name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="补贴对象">{{row.helpUserName}}</table-column>
|
||||
<table-column label="补贴对象工号">{{row.helpLoginName}}</table-column>
|
||||
@@ -42,42 +108,65 @@ layout("/layouts/platform_h5.html"){
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<van-icon name="eye-o"></van-icon>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
|
||||
<i class="fa fa-edit"></i>
|
||||
<van-icon name="edit"></van-icon>
|
||||
<span>审核</span>
|
||||
</div>
|
||||
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">
|
||||
<i class="fa fa-reply"></i>
|
||||
<van-icon name="revoke"></van-icon>
|
||||
<span>撤回</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #empty>
|
||||
<div class="condolence-list-empty">
|
||||
<img src="/assets/mobile/img/condolence/condolence-empty.png" alt="暂无补贴审核记录插画">
|
||||
<div class="condolence-list-empty__title">暂无补贴审核记录</div>
|
||||
<div class="condolence-list-empty__hint">当前筛选条件下暂时没有补贴申请</div>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
</main>
|
||||
|
||||
<info ref="infoRef">
|
||||
<info ref="infoRef" page-key="condolence-school-principal-detail">
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">{{formData.taskName}}</div>
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
v-model="formData.tf_opinion"
|
||||
name="tf_opinion"
|
||||
label="审批意见"
|
||||
placeholder="请输入审批意见"
|
||||
:rules="[{ required: true, message: '请填写审批意见' }]"
|
||||
required
|
||||
maxlength="100"
|
||||
show-word-limit
|
||||
></van-field>
|
||||
</van-form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(20)">不同意</van-button>
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">同意</van-button>
|
||||
<section class="condolence-info-card">
|
||||
<h2 class="condolence-info-card__title">
|
||||
审批意见<span class="condolence-audit-card__required">*</span>
|
||||
</h2>
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
v-model="formData.tf_opinion"
|
||||
class="condolence-audit-field"
|
||||
name="tf_opinion"
|
||||
type="textarea"
|
||||
rows="6"
|
||||
placeholder="请输入审批意见"
|
||||
:rules="[{ required: true, message: '请填写审批意见' }]"
|
||||
maxlength="100"
|
||||
show-word-limit
|
||||
></van-field>
|
||||
</van-form>
|
||||
</section>
|
||||
<div class="condolence-popup-actions">
|
||||
<van-button class="condolence-action-danger" type="danger" block :loading="formLoading" @click="handleTaskAction(6)">退回</van-button>
|
||||
<van-button class="condolence-action-danger" type="danger" block :loading="formLoading" @click="handleTaskAction(20)">不同意</van-button>
|
||||
<van-button class="condolence-action-primary" type="primary" block :loading="formLoading" @click="handleTaskAction(1)">同意</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</info>
|
||||
<van-dialog
|
||||
:value="confirmVisible"
|
||||
title="提示"
|
||||
:message="confirmActionType === 'revoke' ? '您确定要撤回吗?' : '您确定要提交吗?'"
|
||||
show-cancel-button
|
||||
confirm-button-color="#1989fa"
|
||||
@confirm="confirmPendingAction"
|
||||
@cancel="closeActionConfirm"
|
||||
></van-dialog>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
@@ -101,78 +190,133 @@ layout("/layouts/platform_h5.html"){
|
||||
type: null,
|
||||
},
|
||||
typeOptions: [],
|
||||
approvalOptions: [
|
||||
{text: "未审核", value: "0"},
|
||||
{text: "已审核", value: "1"}
|
||||
],
|
||||
skeletonLoading: true,
|
||||
formData: {},
|
||||
showApprovalForm: false
|
||||
showApprovalForm: false,
|
||||
formLoading: false,
|
||||
confirmVisible: false,
|
||||
confirmActionType: "task",
|
||||
pendingSubmitType: null,
|
||||
pendingRevokeRow: null,
|
||||
historyLayerUnsubscribe: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async onReady() {
|
||||
const typeList = await this.queryCondolenceType()
|
||||
this.typeOptions = [
|
||||
{
|
||||
text: "全部补贴类型",
|
||||
value: null
|
||||
}
|
||||
].concat(typeList.map((v) => ({ text: v.name, value: v.id })))
|
||||
if (this.typeOptions.length > 0) {
|
||||
this.pageForm.type = this.typeOptions[0].value
|
||||
this.doSearch()
|
||||
}
|
||||
// state.initial 表示当前查询前列表为空,仅此阶段使用整组卡片骨架屏。
|
||||
handleListLoadingChange(state) {
|
||||
if (state.initial) this.$set(this, "skeletonLoading", state.loading)
|
||||
},
|
||||
// 审核状态下拉值为字符串,接口参数 approval 继续使用布尔值。
|
||||
onApprovalFilterChange(val) {
|
||||
this.$set(this.pageForm, "approval", val === "1")
|
||||
this.doSearch()
|
||||
},
|
||||
onReady() {
|
||||
this.queryCondolenceType()
|
||||
},
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
this.$set(this, "showApprovalForm", false)
|
||||
this.$refs.infoRef.onOpen(row, "补贴详情")
|
||||
},
|
||||
onApproval(row) {
|
||||
this.showApprovalForm = true
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
this.formData = {
|
||||
this.$set(this, "showApprovalForm", true)
|
||||
this.$set(this, "formData", {
|
||||
processTaskId: row.taskId,
|
||||
taskName: row.curTaskName
|
||||
}
|
||||
taskName: row.curTaskName,
|
||||
tf_opinion: ""
|
||||
})
|
||||
this.$refs.infoRef.onOpen(row, row.curTaskName || "补贴审核")
|
||||
},
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate();
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: val
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.infoRef.onClose()
|
||||
// val 为流程提交类型:1 同意、20 不同意、6 退回;校验通过后打开历史栈确认框。
|
||||
handleTaskAction(val) {
|
||||
this.$refs.formRef.validate()
|
||||
.then(() => {
|
||||
this.$set(this, "confirmActionType", "task")
|
||||
this.$set(this, "pendingSubmitType", val)
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open("condolence-action-confirm")) return
|
||||
this.$set(this, "confirmVisible", true)
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
// 确认操作时先回退确认框历史,再根据操作类型调用办理或撤回接口。
|
||||
confirmPendingAction() {
|
||||
this.closeActionConfirm(() => {
|
||||
if (this.confirmActionType === "revoke") {
|
||||
this.revokeTask()
|
||||
return
|
||||
}
|
||||
this.submitTaskAction()
|
||||
})
|
||||
},
|
||||
// 提交 processTaskId、taskName、tf_opinion 和 submitType,接口返回统一响应对象。
|
||||
submitTaskAction() {
|
||||
this.$set(this, "formLoading", true)
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: this.pendingSubmitType
|
||||
})
|
||||
})
|
||||
.then((res) => {
|
||||
if (res && res.code === 0) {
|
||||
const afterClose = () => {
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.closeAll(afterClose)) return
|
||||
this.$refs.infoRef.onClose(afterClose)
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.$set(this, "formLoading", false)
|
||||
})
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
},
|
||||
closeActionConfirm(afterClose = null) {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.close("condolence-action-confirm", afterClose)) return
|
||||
this.$set(this, "confirmVisible", false)
|
||||
if (typeof afterClose === "function") afterClose()
|
||||
},
|
||||
// row 提供待撤回任务 taskId,确认后保存当前行并由统一确认框执行撤回。
|
||||
onRevoke(row){
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要撤回吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
|
||||
this.$set(this, "confirmActionType", "revoke")
|
||||
this.$set(this, "pendingRevokeRow", row)
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open("condolence-action-confirm")) return
|
||||
this.$set(this, "confirmVisible", true)
|
||||
},
|
||||
// 使用 pendingRevokeRow.taskId 撤回任务,接口返回统一响应对象。
|
||||
revokeTask() {
|
||||
if (!this.pendingRevokeRow) return
|
||||
this.$set(this, "formLoading", true)
|
||||
this.$axios.post("/flow/common/revokeTask", {taskId: this.pendingRevokeRow.taskId})
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
this.$set(this, "formLoading", false)
|
||||
})
|
||||
},
|
||||
async queryCondolenceType() {
|
||||
const res = await this.$axios.post('/platform/condolence/type/queryCondolenceType')
|
||||
return res.data
|
||||
queryCondolenceType() {
|
||||
this.$axios.post('/platform/condolence/type/queryCondolenceType', {}, {h5SkeletonLoading: true})
|
||||
.then((res) => {
|
||||
const typeList = res.data || []
|
||||
this.$set(this, "typeOptions", [
|
||||
{
|
||||
text: "全部补贴类型",
|
||||
value: null
|
||||
}
|
||||
].concat(typeList.map((v) => ({ text: v.name, value: v.id }))))
|
||||
if (this.typeOptions.length > 0) {
|
||||
this.$set(this.pageForm, "type", this.typeOptions[0].value)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
@@ -182,6 +326,15 @@ layout("/layouts/platform_h5.html"){
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (!window.h5HistoryLayerManager) return
|
||||
this.$set(this, "historyLayerUnsubscribe", window.h5HistoryLayerManager.subscribe((stack) => {
|
||||
this.$set(this, "confirmVisible", stack.includes("condolence-action-confirm"))
|
||||
}))
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (typeof this.historyLayerUnsubscribe === "function") this.historyLayerUnsubscribe()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
+235
-82
@@ -2,35 +2,101 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
<style>
|
||||
#app { --color-primary: #1989fa; }
|
||||
.condolence-list-page { min-height: 100vh; padding-bottom: calc(24px + env(safe-area-inset-bottom)); box-sizing: border-box; background: #f3f7fd; }
|
||||
.condolence-list-page .van-nav-bar, .condolence-list-page .van-sticky--fixed { background: #fff; }
|
||||
.condolence-list-page .van-nav-bar__title { color: #172033; font-size: 16px; font-weight: 600; }
|
||||
.condolence-list-page .van-nav-bar .van-icon, .condolence-list-page .van-nav-bar__text { color: #1989fa; }
|
||||
.condolence-list-sticky { padding: 22px 12px 1px; box-sizing: border-box; background: #f3f7fd; }
|
||||
.condolence-list-search { margin: 0 0 8px; padding: 0; overflow: hidden; border-radius: 12px; background: #fff; box-shadow: 0 5px 16px rgba(43, 73, 112, .1); }
|
||||
.condolence-list-search .van-search__content { height: 42px; padding-left: 12px; align-items: center; border-radius: 12px; background: #fff; }
|
||||
.condolence-list-search .van-field__control { color: #263548; font-size: 14px; }
|
||||
.condolence-list-search .van-field__control::placeholder { color: #a7b0bf; }
|
||||
.condolence-list-filter { margin-bottom: 8px; overflow: hidden; border-radius: 10px; box-shadow: 0 5px 16px rgba(43, 73, 112, .08); }
|
||||
.condolence-list-filter .van-dropdown-menu__bar { height: 44px; box-shadow: none; }
|
||||
.condolence-list-filter .van-dropdown-menu__item, .condolence-list-filter .van-dropdown-menu__title { height: 44px; }
|
||||
.condolence-list-filter .van-dropdown-menu__item { align-items: center; justify-content: center; }
|
||||
.condolence-list-filter .van-dropdown-menu__title { display: inline-flex; align-items: center; line-height: 20px; color: #66758a; font-size: 14px; }
|
||||
.condolence-list-filter .van-dropdown-menu__title--active, .condolence-list-filter .van-dropdown-item__option--active, .condolence-list-filter .van-dropdown-item__option--active .van-dropdown-item__icon { color: #1989fa; }
|
||||
.condolence-list-filter .van-dropdown-item__content { width: calc(100% - 24px); margin: 0 12px; overflow: hidden; box-sizing: border-box; border-radius: 0 0 12px 12px; box-shadow: 0 10px 24px rgba(31, 65, 108, .14); }
|
||||
.condolence-list-filter .van-dropdown-item__option { display: flex; min-height: 48px; padding: 0 16px; align-items: center; color: #46566c; font-size: 14px; }
|
||||
.condolence-list-filter .van-dropdown-item__option .van-cell__title { display: flex; min-height: 20px; align-items: center; line-height: 20px; }
|
||||
.condolence-list-content { padding: 0 12px; }
|
||||
.condolence-list-skeleton { padding-top: 2px; }
|
||||
.condolence-list-skeleton__card { margin-bottom: 12px; padding: 18px 14px 14px; border: 1px solid #e9eff7; border-radius: 12px; background: #fff; box-shadow: 0 5px 16px rgba(43, 73, 112, .08); }
|
||||
.condolence-list-skeleton__card .van-skeleton { padding: 0; }
|
||||
.condolence-list-skeleton__card .van-skeleton__title { width: 42%; height: 18px; margin-bottom: 18px; }
|
||||
.condolence-list-skeleton__card .van-skeleton__row { height: 14px; margin-top: 12px; }
|
||||
.condolence-list-skeleton__card .van-skeleton__row:nth-child(2n) { width: 72% !important; }
|
||||
.condolence-list-skeleton__card .van-skeleton__row:last-child { width: 34% !important; margin-top: 18px; margin-left: auto; }
|
||||
.condolence-list-page .table-list-container { margin-top: 0; padding-bottom: 2px; }
|
||||
.condolence-list-page .table-list-container .table-list-item { margin-bottom: 12px; padding: 14px; border: 1px solid #e9eff7; border-radius: 12px; box-shadow: 0 5px 16px rgba(43, 73, 112, .08); }
|
||||
.condolence-card-header { display: flex; margin-bottom: 8px; align-items: flex-start; justify-content: space-between; }
|
||||
.condolence-card-heading { min-width: 0; padding-right: 10px; flex: 1; }
|
||||
.condolence-card-title { overflow: hidden; color: #253247; font-size: 15px; font-weight: 600; line-height: 22px; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.condolence-card-code { margin-top: 1px; color: #9ba6b6; font-size: 12px; line-height: 18px; }
|
||||
.condolence-card-status { display: inline-flex; flex: none; }
|
||||
.condolence-card-status .van-tag { min-height: 24px; padding: 3px 9px; border: 0; border-radius: 12px; box-sizing: border-box; font-size: 12px; line-height: 18px; }
|
||||
.condolence-list-page .table-list-container .table-list-item .item-actions { margin-top: 10px; padding-top: 10px; border-top-color: #edf1f6; }
|
||||
.condolence-list-page .table-list-container .table-list-item .action-btn { min-height: 28px; padding: 4px 11px; border-radius: 14px; color: #1989fa; background: #eaf4ff; font-size: 12px; line-height: 18px; }
|
||||
.condolence-list-page .table-list-container .table-list-item .action-btn.delete { color: #f04444; background: #fff0f0; }
|
||||
.condolence-list-page .table-list-container .table-list-item .action-btn i { margin-right: 5px; font-size: 13px; }
|
||||
.condolence-list-page .empty-state { padding: 0; }
|
||||
.condolence-list-empty { display: flex; min-height: 280px; padding: 46px 18px 36px; align-items: center; justify-content: center; box-sizing: border-box; flex-direction: column; text-align: center; }
|
||||
.condolence-list-empty img { display: block; width: 86%; max-width: 290px; height: auto; object-fit: contain; }
|
||||
.condolence-list-empty__title { margin-top: 14px; color: #50627a; font-size: 15px; font-weight: 600; line-height: 22px; }
|
||||
.condolence-list-empty__hint { margin-top: 5px; color: #9aa7b8; font-size: 12px; line-height: 18px; }
|
||||
</style>
|
||||
|
||||
<style id="style-condolence-info-h5">
|
||||
<!--#include("../common/info.css"){}#-->
|
||||
</style>
|
||||
|
||||
<div id="app">
|
||||
<div class="condolence-list-page">
|
||||
<van-nav-bar title="校工会审核" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
|
||||
<van-sticky offset-top="46px">
|
||||
<div class="condolence-list-sticky">
|
||||
<van-search
|
||||
v-model="pageForm.searchKeyword"
|
||||
:show-action="false"
|
||||
:reverse-color="false"
|
||||
input-align="left"
|
||||
class="condolence-list-search"
|
||||
placeholder="请输入姓名或者工号搜索"
|
||||
shape="round"
|
||||
clearable
|
||||
@search="doSearch"
|
||||
@clear="doSearch"
|
||||
></van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-menu class="condolence-list-filter" :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<year-van-dropdown-item :num="5" @change="doSearch" v-model="pageForm.year"></year-van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.type" :options="typeOptions" :multiple="false"
|
||||
@change="doSearch"></van-dropdown-item>
|
||||
<van-dropdown-item v-model="pageForm.approvalText" :options="approvalOptions" :multiple="false"
|
||||
@change="onApprovalFilterChange"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.approval = val==='1';this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<table-list api="/platform/condolence/schoolUnionApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" @ready="onReady">
|
||||
<main class="condolence-list-content">
|
||||
<div class="condolence-list-skeleton" v-if="skeletonLoading">
|
||||
<div class="condolence-list-skeleton__card" v-for="index in 3" :key="'school-union-approval-skeleton-' + index">
|
||||
<van-skeleton title :row="5" animated></van-skeleton>
|
||||
</div>
|
||||
</div>
|
||||
<table-list api="/platform/condolence/schoolUnionApproval/pageData" :page_form.sync="pageForm" ref="tableListRef"
|
||||
v-show="!skeletonLoading" :show_loading_overlay="false" @ready="onReady"
|
||||
@loading-change="handleListLoadingChange">
|
||||
<template #header="{index,row}">
|
||||
<div class="condolence-card-header">
|
||||
<div class="condolence-card-heading">
|
||||
<div class="condolence-card-title">{{row.helpUserName || '--'}}</div>
|
||||
<div class="condolence-card-code">工号:{{row.helpLoginName || '--'}}</div>
|
||||
</div>
|
||||
<enum-tag class="condolence-card-status" v-if="row.instanceState" :value="row.instanceState"
|
||||
name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="补贴对象">{{row.helpUserName}}</table-column>
|
||||
<table-column label="补贴对象工号">{{row.helpLoginName}}</table-column>
|
||||
@@ -42,42 +108,65 @@ layout("/layouts/platform_h5.html"){
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<van-icon name="eye-o"></van-icon>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
|
||||
<i class="fa fa-edit"></i>
|
||||
<van-icon name="edit"></van-icon>
|
||||
<span>审核</span>
|
||||
</div>
|
||||
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">
|
||||
<i class="fa fa-reply"></i>
|
||||
<van-icon name="revoke"></van-icon>
|
||||
<span>撤回</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #empty>
|
||||
<div class="condolence-list-empty">
|
||||
<img src="/assets/mobile/img/condolence/condolence-empty.png" alt="暂无补贴审核记录插画">
|
||||
<div class="condolence-list-empty__title">暂无补贴审核记录</div>
|
||||
<div class="condolence-list-empty__hint">当前筛选条件下暂时没有补贴申请</div>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
</main>
|
||||
|
||||
<info ref="infoRef">
|
||||
<info ref="infoRef" page-key="condolence-school-union-detail">
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">{{formData.taskName}}</div>
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
v-model="formData.tf_opinion"
|
||||
name="tf_opinion"
|
||||
label="审批意见"
|
||||
placeholder="请输入审批意见"
|
||||
:rules="[{ required: true, message: '请填写审批意见' }]"
|
||||
required
|
||||
maxlength="100"
|
||||
show-word-limit
|
||||
></van-field>
|
||||
</van-form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(20)">不同意</van-button>
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">同意</van-button>
|
||||
<section class="condolence-info-card">
|
||||
<h2 class="condolence-info-card__title">
|
||||
审批意见<span class="condolence-audit-card__required">*</span>
|
||||
</h2>
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
v-model="formData.tf_opinion"
|
||||
class="condolence-audit-field"
|
||||
name="tf_opinion"
|
||||
type="textarea"
|
||||
rows="6"
|
||||
placeholder="请输入审批意见"
|
||||
:rules="[{ required: true, message: '请填写审批意见' }]"
|
||||
maxlength="100"
|
||||
show-word-limit
|
||||
></van-field>
|
||||
</van-form>
|
||||
</section>
|
||||
<div class="condolence-popup-actions">
|
||||
<van-button class="condolence-action-danger" type="danger" block :loading="formLoading" @click="handleTaskAction(6)">退回</van-button>
|
||||
<van-button class="condolence-action-danger" type="danger" block :loading="formLoading" @click="handleTaskAction(20)">不同意</van-button>
|
||||
<van-button class="condolence-action-primary" type="primary" block :loading="formLoading" @click="handleTaskAction(1)">同意</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</info>
|
||||
<van-dialog
|
||||
:value="confirmVisible"
|
||||
title="提示"
|
||||
:message="confirmActionType === 'revoke' ? '您确定要撤回吗?' : '您确定要提交吗?'"
|
||||
show-cancel-button
|
||||
confirm-button-color="#1989fa"
|
||||
@confirm="confirmPendingAction"
|
||||
@cancel="closeActionConfirm"
|
||||
></van-dialog>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
@@ -101,78 +190,133 @@ layout("/layouts/platform_h5.html"){
|
||||
type: null,
|
||||
},
|
||||
typeOptions: [],
|
||||
approvalOptions: [
|
||||
{text: "未审核", value: "0"},
|
||||
{text: "已审核", value: "1"}
|
||||
],
|
||||
skeletonLoading: true,
|
||||
formData: {},
|
||||
showApprovalForm: false
|
||||
showApprovalForm: false,
|
||||
formLoading: false,
|
||||
confirmVisible: false,
|
||||
confirmActionType: "task",
|
||||
pendingSubmitType: null,
|
||||
pendingRevokeRow: null,
|
||||
historyLayerUnsubscribe: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async onReady() {
|
||||
const typeList = await this.queryCondolenceType()
|
||||
this.typeOptions = [
|
||||
{
|
||||
text: "全部补贴类型",
|
||||
value: null
|
||||
}
|
||||
].concat(typeList.map((v) => ({ text: v.name, value: v.id })))
|
||||
if (this.typeOptions.length > 0) {
|
||||
this.pageForm.type = this.typeOptions[0].value
|
||||
this.doSearch()
|
||||
}
|
||||
// state.initial 表示当前查询前列表为空,仅此阶段使用整组卡片骨架屏。
|
||||
handleListLoadingChange(state) {
|
||||
if (state.initial) this.$set(this, "skeletonLoading", state.loading)
|
||||
},
|
||||
// 审核状态下拉值为字符串,接口参数 approval 继续使用布尔值。
|
||||
onApprovalFilterChange(val) {
|
||||
this.$set(this.pageForm, "approval", val === "1")
|
||||
this.doSearch()
|
||||
},
|
||||
onReady() {
|
||||
this.queryCondolenceType()
|
||||
},
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
this.$set(this, "showApprovalForm", false)
|
||||
this.$refs.infoRef.onOpen(row, "补贴详情")
|
||||
},
|
||||
onApproval(row) {
|
||||
this.showApprovalForm = true
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
this.formData = {
|
||||
this.$set(this, "showApprovalForm", true)
|
||||
this.$set(this, "formData", {
|
||||
processTaskId: row.taskId,
|
||||
taskName: row.curTaskName
|
||||
}
|
||||
taskName: row.curTaskName,
|
||||
tf_opinion: ""
|
||||
})
|
||||
this.$refs.infoRef.onOpen(row, row.curTaskName || "补贴审核")
|
||||
},
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate();
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: val
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.infoRef.onClose()
|
||||
// val 为流程提交类型:1 同意、20 不同意、6 退回;校验通过后打开历史栈确认框。
|
||||
handleTaskAction(val) {
|
||||
this.$refs.formRef.validate()
|
||||
.then(() => {
|
||||
this.$set(this, "confirmActionType", "task")
|
||||
this.$set(this, "pendingSubmitType", val)
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open("condolence-action-confirm")) return
|
||||
this.$set(this, "confirmVisible", true)
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
// 确认操作时先回退确认框历史,再根据操作类型调用办理或撤回接口。
|
||||
confirmPendingAction() {
|
||||
this.closeActionConfirm(() => {
|
||||
if (this.confirmActionType === "revoke") {
|
||||
this.revokeTask()
|
||||
return
|
||||
}
|
||||
this.submitTaskAction()
|
||||
})
|
||||
},
|
||||
// 提交 processTaskId、taskName、tf_opinion 和 submitType,接口返回统一响应对象。
|
||||
submitTaskAction() {
|
||||
this.$set(this, "formLoading", true)
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: this.pendingSubmitType
|
||||
})
|
||||
})
|
||||
.then((res) => {
|
||||
if (res && res.code === 0) {
|
||||
const afterClose = () => {
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.closeAll(afterClose)) return
|
||||
this.$refs.infoRef.onClose(afterClose)
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.$set(this, "formLoading", false)
|
||||
})
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
},
|
||||
closeActionConfirm(afterClose = null) {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.close("condolence-action-confirm", afterClose)) return
|
||||
this.$set(this, "confirmVisible", false)
|
||||
if (typeof afterClose === "function") afterClose()
|
||||
},
|
||||
// row 提供待撤回任务 taskId,确认后保存当前行并由统一确认框执行撤回。
|
||||
onRevoke(row){
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要撤回吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
|
||||
this.$set(this, "confirmActionType", "revoke")
|
||||
this.$set(this, "pendingRevokeRow", row)
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open("condolence-action-confirm")) return
|
||||
this.$set(this, "confirmVisible", true)
|
||||
},
|
||||
// 使用 pendingRevokeRow.taskId 撤回任务,接口返回统一响应对象。
|
||||
revokeTask() {
|
||||
if (!this.pendingRevokeRow) return
|
||||
this.$set(this, "formLoading", true)
|
||||
this.$axios.post("/flow/common/revokeTask", {taskId: this.pendingRevokeRow.taskId})
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
this.$set(this, "formLoading", false)
|
||||
})
|
||||
},
|
||||
async queryCondolenceType() {
|
||||
const res = await this.$axios.post('/platform/condolence/type/queryCondolenceType')
|
||||
return res.data
|
||||
queryCondolenceType() {
|
||||
this.$axios.post('/platform/condolence/type/queryCondolenceType', {}, {h5SkeletonLoading: true})
|
||||
.then((res) => {
|
||||
const typeList = res.data || []
|
||||
this.$set(this, "typeOptions", [
|
||||
{
|
||||
text: "全部补贴类型",
|
||||
value: null
|
||||
}
|
||||
].concat(typeList.map((v) => ({ text: v.name, value: v.id }))))
|
||||
if (this.typeOptions.length > 0) {
|
||||
this.$set(this.pageForm, "type", this.typeOptions[0].value)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
@@ -182,6 +326,15 @@ layout("/layouts/platform_h5.html"){
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (!window.h5HistoryLayerManager) return
|
||||
this.$set(this, "historyLayerUnsubscribe", window.h5HistoryLayerManager.subscribe((stack) => {
|
||||
this.$set(this, "confirmVisible", stack.includes("condolence-action-confirm"))
|
||||
}))
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (typeof this.historyLayerUnsubscribe === "function") this.historyLayerUnsubscribe()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
+616
-133
@@ -1,17 +1,305 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<style>
|
||||
#app {
|
||||
--color-primary: #1989fa;
|
||||
}
|
||||
|
||||
#app > .van-nav-bar .van-icon,
|
||||
#app > .van-nav-bar .van-nav-bar__text {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
#app > .van-nav-bar .van-nav-bar__title,
|
||||
#app > .van-nav-bar .van-nav-bar__text,
|
||||
#app > .van-nav-bar .van-nav-bar__arrow {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.difficult-help-apply-form.form-container {
|
||||
min-height: 100%;
|
||||
padding: 12px 15px calc(84px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background: #f3f7fc;
|
||||
}
|
||||
|
||||
.difficult-help-apply-form .form-section {
|
||||
margin-bottom: 11px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #e9eff7;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
box-shadow: 0 3px 11px rgba(51, 87, 126, 0.08);
|
||||
}
|
||||
|
||||
.difficult-help-apply-form .difficult-help-card__title {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
padding: 12px 14px 8px 21px;
|
||||
color: #354255;
|
||||
font-size: 15px;
|
||||
line-height: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.difficult-help-apply-form .difficult-help-card__title::before {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
bottom: 11px;
|
||||
left: 12px;
|
||||
width: 2px;
|
||||
border-radius: 2px;
|
||||
background: #1989fa;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.difficult-help-apply-form .form-section .van-cell-group {
|
||||
margin: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.difficult-help-apply-form .form-section .van-cell {
|
||||
min-height: 44px;
|
||||
padding: 10px 14px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.difficult-help-apply-form .form-section .van-cell:not(:last-child)::after {
|
||||
right: 14px;
|
||||
left: 14px;
|
||||
border-color: #eef2f7;
|
||||
}
|
||||
|
||||
.difficult-help-apply-form .form-section .van-field__label {
|
||||
width: 84px;
|
||||
color: #596779;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.difficult-help-apply-form .form-section .van-field__value,
|
||||
.difficult-help-apply-form .form-section .van-field__control {
|
||||
color: #4f5d70;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.difficult-help-apply-form .form-section .van-field__control::placeholder {
|
||||
color: #b1bac6;
|
||||
}
|
||||
|
||||
.difficult-help-apply-form .form-section .van-cell--required::before {
|
||||
left: 6px;
|
||||
color: #f06464;
|
||||
}
|
||||
|
||||
.difficult-help-apply-actions {
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
gap: 9px;
|
||||
padding: 10px 18px calc(10px + env(safe-area-inset-bottom));
|
||||
border-top: 1px solid #edf1f6;
|
||||
background: rgba(255, 255, 255, 0.98);
|
||||
box-shadow: 0 -4px 14px rgba(50, 78, 112, 0.06);
|
||||
}
|
||||
|
||||
.difficult-help-apply-actions .van-button {
|
||||
height: 40px;
|
||||
margin: 0;
|
||||
border-radius: 14px !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.difficult-help-apply-actions .van-button:first-child {
|
||||
flex: 1;
|
||||
color: #1989fa;
|
||||
border-color: #1989fa;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.difficult-help-apply-actions .van-button:last-child {
|
||||
flex: 1.08;
|
||||
border-color: #1989fa;
|
||||
background: #1989fa;
|
||||
}
|
||||
|
||||
#app .van-action-sheet__header,
|
||||
#app .van-picker__title,
|
||||
.van-dialog__header {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
#app .van-action-sheet__name,
|
||||
#app .van-action-sheet__cancel,
|
||||
#app .van-empty__description,
|
||||
#app .van-search__field,
|
||||
#app .van-picker__cancel,
|
||||
#app .van-picker__confirm,
|
||||
.van-dialog__message {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
#app .van-picker-column__item {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.difficult-help-option-popup {
|
||||
display: flex;
|
||||
height: 50%;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background: #f5f7fa;
|
||||
}
|
||||
|
||||
.difficult-help-option-popup__header {
|
||||
display: flex;
|
||||
min-height: 52px;
|
||||
padding: 0 16px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex: none;
|
||||
border-bottom: 1px solid #edf1f6;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.difficult-help-option-popup__title {
|
||||
color: #263548;
|
||||
font-size: 17px;
|
||||
line-height: 24px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.difficult-help-option-popup__action {
|
||||
min-width: 48px;
|
||||
padding: 8px 0;
|
||||
border: 0;
|
||||
color: #1989fa;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
text-align: left;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.difficult-help-option-popup__action:last-child {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.difficult-help-option-popup__action:disabled {
|
||||
color: #b7c0cc;
|
||||
}
|
||||
|
||||
.difficult-help-option-popup__list {
|
||||
min-height: 0;
|
||||
padding: 12px;
|
||||
overflow-y: auto;
|
||||
flex: 1;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.difficult-help-option-popup__search {
|
||||
padding: 10px 12px 0;
|
||||
flex: none;
|
||||
background: #f5f7fa;
|
||||
}
|
||||
|
||||
.difficult-help-option-popup__search .van-search__content {
|
||||
border: 1px solid #e3e9f1;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.difficult-help-option-popup__empty {
|
||||
padding: 44px 18px;
|
||||
color: #98a4b3;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.difficult-help-option-popup__option {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
min-height: 58px;
|
||||
margin-bottom: 10px;
|
||||
padding: 13px 14px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #e4eaf2;
|
||||
border-radius: 10px;
|
||||
color: #46566c;
|
||||
text-align: left;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.difficult-help-option-popup__option:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.difficult-help-option-popup__option.is-selected {
|
||||
border-color: #1989fa;
|
||||
color: #176fbd;
|
||||
background: #eef7ff;
|
||||
box-shadow: 0 3px 10px rgba(25, 137, 250, 0.1);
|
||||
}
|
||||
|
||||
.difficult-help-option-popup__option-text {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
font-size: 15px;
|
||||
line-height: 23px;
|
||||
white-space: normal;
|
||||
word-break: break-word;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.difficult-help-option-popup__recipient {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.difficult-help-option-popup__recipient-name {
|
||||
color: #304157;
|
||||
font-size: 16px;
|
||||
line-height: 23px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.difficult-help-option-popup__recipient-unit {
|
||||
margin-top: 5px;
|
||||
color: #8290a3;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
white-space: normal;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.difficult-help-option-popup__option.is-selected .difficult-help-option-popup__recipient-name,
|
||||
.difficult-help-option-popup__option.is-selected .difficult-help-option-popup__recipient-unit {
|
||||
color: #176fbd;
|
||||
}
|
||||
|
||||
</style>
|
||||
<div id="app">
|
||||
<div v-if="!isShow">
|
||||
<van-empty image="error" :description="'抱歉,当前时间不能申请,可申请时间为' + time + '。'"></van-empty>
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<van-nav-bar title="帮扶申请" left-text="返回" left-arrow @click-left="historyBack" placeholder fixed></van-nav-bar>
|
||||
<van-nav-bar title="帮扶申请" left-text="返回" left-arrow @click-left="handlePageBack" placeholder fixed></van-nav-bar>
|
||||
|
||||
<div class="form-container">
|
||||
<van-form ref="formRef">
|
||||
<van-cell-group title="申请人信息" class="form-section">
|
||||
<van-form ref="formRef" class="form-container difficult-help-apply-form">
|
||||
<section class="form-section">
|
||||
<h2 class="difficult-help-card__title">申请人信息</h2>
|
||||
<van-cell-group :border="false">
|
||||
<van-field label="申请次数" v-model="formData.applyCount" readonly
|
||||
required name="applyCount"></van-field>
|
||||
<van-field label="填写人姓名" :rules="[{ required: true }]" v-model="formData.proxyUserName" readonly
|
||||
@@ -29,28 +317,25 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-radio-group>
|
||||
</template>
|
||||
</van-field>
|
||||
</van-cell-group>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
|
||||
<van-cell-group title="受助人信息" class="form-section">
|
||||
<section class="form-section">
|
||||
<h2 class="difficult-help-card__title">受助人信息</h2>
|
||||
<van-cell-group :border="false">
|
||||
<template v-if="formData.mode == 2">
|
||||
<van-field label="受助人" :rules="[{ required: true }]" v-model="formData.userName"
|
||||
required name="userName" placeholder="请输入受补助人姓名后点击查询">
|
||||
<template #button>
|
||||
<van-button :disabled="formData.id" @click="queryRecipients(formData.userName)"
|
||||
size="small" type="primary">查询
|
||||
</van-button>
|
||||
</template>
|
||||
<van-field
|
||||
label="受助人"
|
||||
:rules="[{ required: true }]"
|
||||
v-model="formData.userName"
|
||||
:is-link="!formData.id"
|
||||
readonly
|
||||
required
|
||||
name="userName"
|
||||
placeholder="请选择受助人"
|
||||
@click="openRecipientPopup">
|
||||
</van-field>
|
||||
|
||||
<van-action-sheet
|
||||
:actions="subsidizedList"
|
||||
:close-on-click-overlay="false"
|
||||
@cancel="userCancel"
|
||||
@select="onUserSelect"
|
||||
cancel-text="重新输入姓名或工号查询"
|
||||
v-model="userSheetShow">
|
||||
</van-action-sheet>
|
||||
|
||||
</template>
|
||||
<template v-else>
|
||||
<van-field label="受助人" :rules="[{ required: true }]" v-model="formData.userName" readonly
|
||||
@@ -66,16 +351,8 @@ layout("/layouts/platform_h5.html"){
|
||||
readonly
|
||||
name="sex"
|
||||
:rules="[{ required: true }]"
|
||||
@click="showSexPicker = true"
|
||||
@click="openOptionPopup('sex')"
|
||||
></van-field>
|
||||
<van-popup v-model="showSexPicker" position="bottom">
|
||||
<van-picker
|
||||
show-toolbar
|
||||
:columns="['男', '女']"
|
||||
@confirm="onSexConfirm"
|
||||
@cancel="showSexPicker=false"
|
||||
></van-picker>
|
||||
</van-popup>
|
||||
|
||||
<van-field
|
||||
v-model="formData.unionName"
|
||||
@@ -171,47 +448,34 @@ layout("/layouts/platform_h5.html"){
|
||||
:rules="[{ required: true }]"
|
||||
></van-field>
|
||||
|
||||
</van-cell-group>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
|
||||
<van-cell-group title="困难类型及材料" class="form-section">
|
||||
<section class="form-section">
|
||||
<h2 class="difficult-help-card__title">困难类型及材料</h2>
|
||||
<van-cell-group :border="false">
|
||||
<van-field
|
||||
v-model="formData.subsidyName"
|
||||
label="补助类型"
|
||||
placeholder="请选择补助类型"
|
||||
is-link
|
||||
@click="showSubsidyPicker = true"
|
||||
readonly
|
||||
@click="openOptionPopup('subsidyType')"
|
||||
required
|
||||
name="subsidyName"
|
||||
:rules="[{ required: true, message: '请选择补助类型' }]"
|
||||
></van-field>
|
||||
<van-popup v-model="showSubsidyPicker" position="bottom">
|
||||
<van-picker
|
||||
show-toolbar
|
||||
:columns="subsidyTypeColumns"
|
||||
@confirm="onSubsidyTypeConfirm"
|
||||
@cancel="showSubsidyPicker=false">
|
||||
</van-picker>
|
||||
</van-popup>
|
||||
|
||||
<van-field
|
||||
v-model="formData.subsidyStandardsName"
|
||||
label="困难类型"
|
||||
placeholder="请选择困难类型"
|
||||
is-link
|
||||
@click="showSubsidyStandardPicker = true"
|
||||
readonly
|
||||
@click="openOptionPopup('subsidyStandard')"
|
||||
required
|
||||
name="subsidyStandardsName"
|
||||
:rules="[{ required: true, message: '请选择困难类型' }]"
|
||||
></van-field>
|
||||
<van-popup v-model="showSubsidyStandardPicker" position="bottom">
|
||||
<van-picker
|
||||
show-toolbar
|
||||
:columns="subsidyStandardColumns"
|
||||
@confirm="onSubsidyStandardConfirm"
|
||||
@cancel="showSubsidyStandardPicker=false">
|
||||
</van-picker>
|
||||
</van-popup>
|
||||
|
||||
<van-field
|
||||
v-model="formData.bankCardNum"
|
||||
label="收款账户"
|
||||
@@ -242,9 +506,12 @@ layout("/layouts/platform_h5.html"){
|
||||
name="reason"
|
||||
:rules="[{ required: true }]"
|
||||
></van-field>
|
||||
</van-cell-group>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
|
||||
<van-cell-group title="家庭主要成员信息" class="form-section up_down">
|
||||
<section class="form-section up_down">
|
||||
<h2 class="difficult-help-card__title">家庭主要成员信息</h2>
|
||||
<van-cell-group :border="false">
|
||||
<div class="van-cell">
|
||||
<div style="display: flex;justify-content: space-between">
|
||||
<div style="display: flex;">
|
||||
@@ -290,9 +557,12 @@ layout("/layouts/platform_h5.html"){
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</van-cell-group>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
|
||||
<van-cell-group title="附件信息" class="form-section">
|
||||
<section class="form-section">
|
||||
<h2 class="difficult-help-card__title">附件信息</h2>
|
||||
<van-cell-group :border="false">
|
||||
<van-field class="more-text" name="files" label="">
|
||||
<template #input>
|
||||
<h5-file-upload
|
||||
@@ -306,9 +576,12 @@ layout("/layouts/platform_h5.html"){
|
||||
></h5-file-upload>
|
||||
</template>
|
||||
</van-field>
|
||||
</van-cell-group>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
|
||||
<van-cell-group title="签字" class="form-section">
|
||||
<section class="form-section">
|
||||
<h2 class="difficult-help-card__title">签字确认</h2>
|
||||
<van-cell-group :border="false">
|
||||
<van-field class="more-text" name="sign" label="">
|
||||
<template #input>
|
||||
<h5-signature v-model="formData.sign" slot="input"></h5-signature>
|
||||
@@ -317,15 +590,67 @@ layout("/layouts/platform_h5.html"){
|
||||
<div style="color: red; padding: 10px;">
|
||||
本人承诺:本人及家庭成员未有购买价格超过15万元的机动车,也未有两套及以上商品房,特此承诺!
|
||||
</div>
|
||||
</van-cell-group>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
|
||||
<div class="form-actions">
|
||||
<van-button native-type="button" plain type="info" @click="onSave">保存</van-button>
|
||||
<van-button type="primary" @click="onSubmit" v-if="!taskId">提交</van-button>
|
||||
<van-button type="primary" @click="onFinishTask" v-else>提交</van-button>
|
||||
<div class="form-actions difficult-help-apply-actions">
|
||||
<van-button native-type="button" plain round type="info" @click="onSave">保存申请</van-button>
|
||||
<van-button round type="info" @click="onSubmit" v-if="!taskId">提交申请</van-button>
|
||||
<van-button round type="info" @click="onFinishTask" v-else>提交申请</van-button>
|
||||
</div>
|
||||
</van-form>
|
||||
</div>
|
||||
|
||||
<van-popup
|
||||
v-model="showOptionPicker"
|
||||
position="bottom"
|
||||
round
|
||||
:close-on-click-overlay="false"
|
||||
class="difficult-help-option-popup">
|
||||
<div class="difficult-help-option-popup__header">
|
||||
<button type="button" class="difficult-help-option-popup__action"
|
||||
@click="cancelOptionPopup">取消</button>
|
||||
<div class="difficult-help-option-popup__title">{{optionPopupTitle}}</div>
|
||||
<button type="button" class="difficult-help-option-popup__action"
|
||||
:disabled="pendingOptionValue === null || pendingOptionValue === undefined || pendingOptionValue === ''"
|
||||
@click="confirmOptionPopup">确认</button>
|
||||
</div>
|
||||
<van-search
|
||||
v-if="optionPopupType === 'recipient'"
|
||||
v-model.trim="recipientSearchKey"
|
||||
class="difficult-help-option-popup__search"
|
||||
shape="round"
|
||||
clearable
|
||||
placeholder="请输入姓名或工号搜索"
|
||||
@search="queryRecipients"
|
||||
@clear="clearRecipientSearchResults">
|
||||
</van-search>
|
||||
<div class="difficult-help-option-popup__list">
|
||||
<div
|
||||
v-if="optionPopupType === 'recipient' && !recipientHasSearched && optionPopupOptions.length === 0"
|
||||
class="difficult-help-option-popup__empty">
|
||||
输入姓名或工号后,点击键盘搜索键查询
|
||||
</div>
|
||||
<div
|
||||
v-else-if="optionPopupType === 'recipient' && recipientHasSearched && optionPopupOptions.length === 0"
|
||||
class="difficult-help-option-popup__empty">
|
||||
未查询到符合条件的受助人
|
||||
</div>
|
||||
<button
|
||||
v-for="option in optionPopupOptions"
|
||||
:key="option.value"
|
||||
type="button"
|
||||
class="difficult-help-option-popup__option"
|
||||
:class="{'is-selected': pendingOptionValue === option.value}"
|
||||
:aria-pressed="pendingOptionValue === option.value"
|
||||
@click="selectOptionPopupItem(option)">
|
||||
<span v-if="optionPopupType === 'recipient'" class="difficult-help-option-popup__recipient">
|
||||
<span class="difficult-help-option-popup__recipient-name">{{option.text}}</span>
|
||||
<span class="difficult-help-option-popup__recipient-unit">{{option.description || '暂无单位信息'}}</span>
|
||||
</span>
|
||||
<span v-else class="difficult-help-option-popup__option-text">{{option.text}}</span>
|
||||
</button>
|
||||
</div>
|
||||
</van-popup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -333,11 +658,11 @@ layout("/layouts/platform_h5.html"){
|
||||
.mt5 {
|
||||
margin-top: 5px;
|
||||
}
|
||||
.up_down > .van-cell {
|
||||
.up_down > .van-cell-group > .van-cell {
|
||||
flex-flow: column;
|
||||
}
|
||||
|
||||
.up_down > .van-cell > .van-field__label {
|
||||
.up_down > .van-cell-group > .van-cell > .van-field__label {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -350,10 +675,15 @@ layout("/layouts/platform_h5.html"){
|
||||
return {
|
||||
bizId: GetQueryString("bizId"),
|
||||
taskId: GetQueryString("taskId"),
|
||||
showSexPicker: false,
|
||||
showDatePicker: false,
|
||||
showSubsidyPicker: false,
|
||||
showSubsidyStandardPicker: false,
|
||||
showOptionPicker: false,
|
||||
optionPopupType: "",
|
||||
optionPopupTitle: "",
|
||||
optionPopupOptions: [],
|
||||
pendingOptionValue: "",
|
||||
recipientSearchKey: "",
|
||||
recipientHasSearched: false,
|
||||
historyLayerPageKey: "difficult-help-apply",
|
||||
formData: {
|
||||
id: GetQueryString("bizId"),
|
||||
mode: "1",
|
||||
@@ -365,7 +695,6 @@ layout("/layouts/platform_h5.html"){
|
||||
subsidyValue: "",
|
||||
subsidyStandardsValue: "",
|
||||
|
||||
userSheetShow: false,
|
||||
subsidizedList: [],
|
||||
maxDate: new Date(),
|
||||
|
||||
@@ -380,29 +709,170 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
methods: {
|
||||
historyBack,
|
||||
// 替他人申请时由只读字段主动打开受助人选择,已有业务数据时保持原禁止更换规则。
|
||||
openRecipientPopup() {
|
||||
if (this.formData.mode !== "2" || this.formData.id) return
|
||||
this.$set(this, "recipientSearchKey", "")
|
||||
this.$set(this, "recipientHasSearched", false)
|
||||
this.$set(this, "subsidizedList", [])
|
||||
this.openOptionPopup("recipient")
|
||||
},
|
||||
/**
|
||||
* 根据选择类型配置并打开统一弹框。
|
||||
* optionType 支持 recipient、sex、subsidyType、subsidyStandard;方法无返回值。
|
||||
*/
|
||||
openOptionPopup(optionType) {
|
||||
let title = ""
|
||||
let options = []
|
||||
let currentValue = ""
|
||||
if (optionType === "recipient") {
|
||||
title = "选择受助人"
|
||||
options = this.subsidizedList.map((item) => {
|
||||
return {value: item.id, text: item.username, description: item.unitName, source: item}
|
||||
})
|
||||
const matchedRecipient = options.find((item) => {
|
||||
return item.value === this.formData.userId
|
||||
})
|
||||
currentValue = matchedRecipient ? matchedRecipient.value : ""
|
||||
} else if (optionType === "sex") {
|
||||
title = "选择性别"
|
||||
options = [{value: "男", text: "男"}, {value: "女", text: "女"}]
|
||||
currentValue = this.formData.sex || ""
|
||||
} else if (optionType === "subsidyType") {
|
||||
title = "选择补助类型"
|
||||
options = this.subsidyTypeColumns.slice()
|
||||
const matchedSubsidy = options.find((item) => {
|
||||
return item.text === this.formData.subsidyName
|
||||
})
|
||||
currentValue = matchedSubsidy
|
||||
? matchedSubsidy.value
|
||||
: (this.formData.subsidy || this.subsidyValue || "")
|
||||
} else if (optionType === "subsidyStandard") {
|
||||
title = "选择困难类型"
|
||||
options = this.subsidyStandardColumns.slice()
|
||||
const matchedStandard = options.find((item) => {
|
||||
return item.text === this.formData.subsidyStandardsName
|
||||
})
|
||||
currentValue = matchedStandard
|
||||
? matchedStandard.value
|
||||
: (this.formData.subsidyStandards || this.subsidyStandardsValue || "")
|
||||
}
|
||||
this.$set(this, "optionPopupType", optionType)
|
||||
this.$set(this, "optionPopupTitle", title)
|
||||
this.$set(this, "optionPopupOptions", options)
|
||||
this.$set(this, "pendingOptionValue", currentValue)
|
||||
this.openPopup("showOptionPicker")
|
||||
},
|
||||
selectOptionPopupItem(option) {
|
||||
this.$set(this, "pendingOptionValue", option.value)
|
||||
},
|
||||
cancelOptionPopup() {
|
||||
if (this.optionPopupType === "recipient") {
|
||||
this.$set(this, "recipientSearchKey", "")
|
||||
this.$set(this, "recipientHasSearched", false)
|
||||
this.$set(this, "subsidizedList", [])
|
||||
}
|
||||
this.closePopup("showOptionPicker")
|
||||
},
|
||||
clearRecipientSearchResults() {
|
||||
this.$set(this, "recipientHasSearched", false)
|
||||
this.$set(this, "subsidizedList", [])
|
||||
this.$set(this, "optionPopupOptions", [])
|
||||
this.$set(this, "pendingOptionValue", "")
|
||||
},
|
||||
/**
|
||||
* 确认统一弹框选项并按类型回填表单。
|
||||
* 选项 value 为业务值、text 为展示文本,recipient 额外携带 source 用户对象;方法无返回值。
|
||||
*/
|
||||
confirmOptionPopup() {
|
||||
const selectedOption = this.optionPopupOptions.find((item) => {
|
||||
return item.value === this.pendingOptionValue
|
||||
})
|
||||
if (!selectedOption) {
|
||||
this.$toast("请选择" + this.optionPopupTitle.replace("选择", ""))
|
||||
return
|
||||
}
|
||||
if (this.optionPopupType === "recipient") {
|
||||
this.applySelectedUser(selectedOption.source)
|
||||
this.$set(this, "recipientSearchKey", "")
|
||||
this.$set(this, "recipientHasSearched", false)
|
||||
this.$set(this, "subsidizedList", [])
|
||||
} else if (this.optionPopupType === "sex") {
|
||||
this.$set(this.formData, "sex", selectedOption.value)
|
||||
} else if (this.optionPopupType === "subsidyType") {
|
||||
this.$set(this.formData, "subsidyName", selectedOption.text)
|
||||
this.$set(this, "subsidyValue", selectedOption.value)
|
||||
} else if (this.optionPopupType === "subsidyStandard") {
|
||||
this.$set(this.formData, "subsidyStandardsName", selectedOption.text)
|
||||
this.$set(this, "subsidyStandardsValue", selectedOption.value)
|
||||
}
|
||||
this.closePopup("showOptionPicker")
|
||||
},
|
||||
/**
|
||||
* 打开底部弹框并增加一层浏览器历史。
|
||||
* popupKey 传弹框对应的 data 字段名;方法无返回值。
|
||||
*/
|
||||
openPopup(popupKey) {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open(popupKey)) return
|
||||
this.syncPopupState(popupKey, true)
|
||||
},
|
||||
/**
|
||||
* 主动关闭底部弹框并回退对应的浏览器历史。
|
||||
* popupKey 传弹框对应的 data 字段名;返回键回调只同步界面状态,避免重复回退历史。
|
||||
*/
|
||||
closePopup(popupKey) {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.close(popupKey)) return
|
||||
this.syncPopupState(popupKey, false)
|
||||
},
|
||||
syncPopupState(popupKey, visible) {
|
||||
const popupKeys = ["showOptionPicker"]
|
||||
if (popupKeys.includes(popupKey)) {
|
||||
this.$set(this, popupKey, visible)
|
||||
}
|
||||
},
|
||||
// 根据统一弹层历史栈同步界面,返回操作只关闭栈顶弹框,不重新加载当前页面。
|
||||
syncHistoryLayerStack(stack) {
|
||||
const popupKeys = ["showOptionPicker"]
|
||||
popupKeys.forEach((popupKey) => {
|
||||
this.syncPopupState(popupKey, stack.includes(popupKey))
|
||||
})
|
||||
},
|
||||
// NavBar 返回与系统返回保持一致:有弹框先关闭弹框,无弹框再返回业务页面。
|
||||
handlePageBack() {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.stack.length) {
|
||||
window.h5HistoryLayerManager.close()
|
||||
return
|
||||
}
|
||||
this.historyBack()
|
||||
},
|
||||
// 业务跳转前清空当前页面的弹框历史,避免返回时重新出现已关闭弹框。
|
||||
clearPopupHistoryAndNavigate(url) {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.closeAllAndNavigate(url)) return
|
||||
this.$pjaxReplace(url)
|
||||
},
|
||||
showBirthday() {
|
||||
if (this.formData.birthday) {
|
||||
this.$set(this.formData, "currentDate", new Date(this.formData.birthday))
|
||||
}
|
||||
this.showDatePicker = true
|
||||
},
|
||||
userCancel() {
|
||||
if (!this.formData.userId) {
|
||||
this.$set(this.formData, "userName", null)
|
||||
}
|
||||
this.subsidizedList = []
|
||||
},
|
||||
|
||||
async initDictOptions() {
|
||||
const subsidyTypeData = await this.$businessTool.getDictOptions("DIFFICULT_SUBSIDY_TYPE");
|
||||
initDictOptions() {
|
||||
return this.$businessTool.getDictOptions("DIFFICULT_SUBSIDY_TYPE").then(subsidyTypeData => {
|
||||
this.subsidyTypeColumns = subsidyTypeData.map(item => {
|
||||
return { value: item.code, text: item.name };
|
||||
return {
|
||||
value: item.code,
|
||||
text: item.name
|
||||
};
|
||||
});
|
||||
|
||||
const subsidyStandardData = await this.$businessTool.getDictOptions("DIFFICULT_TYPE");
|
||||
this.subsidyStandardColumns = subsidyStandardData.map(item => {
|
||||
return { value: item.code, text: item.name };
|
||||
return this.$businessTool.getDictOptions("DIFFICULT_TYPE").then(subsidyStandardData => {
|
||||
this.subsidyStandardColumns = subsidyStandardData.map(item => {
|
||||
return {
|
||||
value: item.code,
|
||||
text: item.name
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
prepareSubmitData() {
|
||||
@@ -432,7 +902,7 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$axios.post("/platform/difficultHelp/apply/save", { data: JSON.stringify(submitData) }).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$toast("保存成功")
|
||||
this.$pjaxReplace("/platform/difficultHelp/mine/h5")
|
||||
this.clearPopupHistoryAndNavigate("/platform/difficultHelp/mine/h5")
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -465,7 +935,7 @@ layout("/layouts/platform_h5.html"){
|
||||
}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$toast("提交成功")
|
||||
this.$pjaxReplace("/platform/difficultHelp/mine/h5")
|
||||
this.clearPopupHistoryAndNavigate("/platform/difficultHelp/mine/h5")
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -500,39 +970,56 @@ layout("/layouts/platform_h5.html"){
|
||||
}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$toast("提交成功")
|
||||
this.$pjaxReplace("/platform/difficultHelp/mine/h5")
|
||||
this.clearPopupHistoryAndNavigate("/platform/difficultHelp/mine/h5")
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
// 查询受助人
|
||||
async queryRecipients(key) {
|
||||
/**
|
||||
* 按姓名或工号查询受助人。
|
||||
* recipientSearchKey 传搜索关键词;接口返回用户数组,列表仅展示姓名和单位。
|
||||
*/
|
||||
queryRecipients() {
|
||||
if (this.formData.mode !== "2") {
|
||||
return
|
||||
}
|
||||
const res = await this.$axios.post("/platform/difficultHelp/apply/queryRecipients", { key })
|
||||
if (res.code === 0) {
|
||||
res.data.forEach((v) => {
|
||||
v.name = v.username
|
||||
return v
|
||||
})
|
||||
this.subsidizedList = res.data
|
||||
this.userSheetShow = true
|
||||
const key = (this.recipientSearchKey || "").trim()
|
||||
if (!key) {
|
||||
this.$toast("请输入姓名或工号")
|
||||
return
|
||||
}
|
||||
this.$axios.post("/platform/difficultHelp/apply/queryRecipients", {key: key}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const recipients = res.data || []
|
||||
const options = recipients.map((item) => {
|
||||
return {value: item.id, text: item.username, description: item.unitName, source: item}
|
||||
})
|
||||
const currentRecipient = options.find((item) => {
|
||||
return String(item.value) === String(this.formData.userId || "")
|
||||
})
|
||||
this.$set(this, "recipientHasSearched", true)
|
||||
this.$set(this, "subsidizedList", recipients)
|
||||
this.$set(this, "optionPopupOptions", options)
|
||||
this.$set(this, "pendingOptionValue", currentRecipient ? currentRecipient.value : "")
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
onUserSelect(val) {
|
||||
const user = this.subsidizedList.find((item) => item.id === val.id)
|
||||
// 受助人确认后回填用户、单位和工会信息,参数 user 为查询接口返回的完整用户对象。
|
||||
applySelectedUser(user) {
|
||||
if (user) {
|
||||
const unitId = user.unitId !== undefined ? user.unitId : user.unitid
|
||||
const unionId = user.unionId !== undefined ? user.unionId : user.unionid
|
||||
this.$set(this.formData, "userId", user.id)
|
||||
this.$set(this.formData, "userName", user.username)
|
||||
this.$set(this.formData, "loginName", user.loginname)
|
||||
this.$set(this.formData, "sex", user.sex)
|
||||
this.$set(this.formData, "unitId", user.unitid)
|
||||
this.$set(this.formData, "birthday", user.birthday)
|
||||
this.$set(this.formData, "unitId", unitId)
|
||||
this.$set(this.formData, "unitName", user.unitName)
|
||||
this.$set(this.formData, "unionId", user.unionid)
|
||||
this.$set(this.formData, "unionId", unionId)
|
||||
this.$set(this.formData, "unionName", user.unionName)
|
||||
this.$set(this.formData, "position", user.position || "")
|
||||
this.$set(this.formData, "officialCapacity", user.officialCapacity || "")
|
||||
@@ -554,27 +1041,11 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$set(this.formData, "idCard", null)
|
||||
this.$set(this.formData, "homeAddress", null)
|
||||
}
|
||||
this.userSheetShow = false
|
||||
},
|
||||
|
||||
onSexConfirm(value) {
|
||||
this.formData.sex = value
|
||||
this.showSexPicker = false
|
||||
},
|
||||
onDateConfirm(value) {
|
||||
this.formData.birthday = moment(value).format("YYYY-MM-DD")
|
||||
this.showDatePicker = false
|
||||
},
|
||||
onSubsidyTypeConfirm(option) {
|
||||
this.$set(this.formData, "subsidyName", option.text);
|
||||
this.subsidyValue = option.value;
|
||||
this.showSubsidyPicker = false;
|
||||
},
|
||||
onSubsidyStandardConfirm(option) {
|
||||
this.$set(this.formData, "subsidyStandardsName", option.text);
|
||||
this.subsidyStandardsValue = option.value;
|
||||
this.showSubsidyStandardPicker = false;
|
||||
},
|
||||
|
||||
findOne(id) {
|
||||
this.$axios.post("/platform/difficultHelp/mine/findOne", { id }).then(res => {
|
||||
@@ -599,7 +1070,6 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
}
|
||||
|
||||
this.queryRecipients(res.data.loginName)
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -631,7 +1101,6 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$set(this.formData, 'familyList', [])
|
||||
this.$set(this.formData, 'files', [])
|
||||
this.$set(this.formData, 'applyCount', savedApplyCount )
|
||||
this.queryRecipients(user.loginname)
|
||||
} else {
|
||||
this.formData = {}
|
||||
this.$set(this.formData, 'proxyUserId', user.id)
|
||||
@@ -752,27 +1221,41 @@ layout("/layouts/platform_h5.html"){
|
||||
return overWan ? getWan(overWan) + "万" + getWan(noWan) : getWan(num)
|
||||
},
|
||||
|
||||
async getIsCanPlay() {
|
||||
const res = await this.$axios.post("/platform/difficultHelp/apply/getIsCanPlay");
|
||||
getIsCanPlay() {
|
||||
return this.$axios.post("/platform/difficultHelp/apply/getIsCanPlay").then(res => {
|
||||
if (res.code === 0) {
|
||||
this.isShow = res.data.result;
|
||||
this.time = res.data.time;
|
||||
if (res.data.applyCount !== null && res.data.applyCount !== undefined && res.data.applyCount !== 0) {
|
||||
this.$set(this.formData, 'applyCount', res.data.applyCount)
|
||||
}
|
||||
this.isShow = res.data.result;
|
||||
this.time = res.data.time;
|
||||
if (res.data.applyCount !== null && res.data.applyCount !== undefined && res.data.applyCount !== 0) {
|
||||
this.$set(this.formData, 'applyCount', res.data.applyCount);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
await this.getIsCanPlay();
|
||||
|
||||
created() {
|
||||
return this.getIsCanPlay().then(() => {
|
||||
if (this.isShow) {
|
||||
await this.initDictOptions();
|
||||
return this.initDictOptions().then(() => {
|
||||
if (this.bizId) {
|
||||
this.findOne(this.bizId)
|
||||
this.findOne(this.bizId);
|
||||
} else {
|
||||
this.modeChange("1")
|
||||
this.modeChange("1");
|
||||
}
|
||||
});
|
||||
} else {}
|
||||
});
|
||||
},
|
||||
mounted() {
|
||||
// 使用布局统一管理器注册弹层状态,处理方式与提案预审核详情弹层保持一致。
|
||||
if (!window.h5HistoryLayerManager) return
|
||||
window.h5HistoryLayerManager.register(this.historyLayerPageKey, (stack) => {
|
||||
this.syncHistoryLayerStack(stack)
|
||||
})
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.pageKey === this.historyLayerPageKey) {
|
||||
window.h5HistoryLayerManager.unregister(this.historyLayerPageKey)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
+245
-108
@@ -1,38 +1,81 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<style id="style-difficult-help-approval-list-h5">
|
||||
<!--#include("../common/approval-list.css"){}#-->
|
||||
</style>
|
||||
<style id="style-difficult-help-info-h5">
|
||||
<!--#include("../common/info.css"){}#-->
|
||||
</style>
|
||||
<div id="app">
|
||||
<van-sticky>
|
||||
<div class="difficult-help-approval-page">
|
||||
<van-nav-bar title="帮扶分工会审核" left-text="返回" left-arrow @click-left="historyBack" placeholder fixed></van-nav-bar>
|
||||
<van-sticky offset-top="46px">
|
||||
<div class="difficult-help-approval-sticky">
|
||||
<van-search
|
||||
v-model="pageForm.searchKeyword"
|
||||
class="difficult-help-approval-search"
|
||||
placeholder="请输入工号或者姓名进行查询"
|
||||
show-action
|
||||
:reverse-color="false"
|
||||
input-align="left"
|
||||
@search="doSearch">
|
||||
<template #action>
|
||||
<div @click="doSearch">搜索</div>
|
||||
</template>
|
||||
shape="round"
|
||||
clearable
|
||||
@search="doSearch"
|
||||
@clear="doSearch">
|
||||
</van-search>
|
||||
<van-dropdown-menu
|
||||
v-if="$auth.hasRoleOr('SYSADMIN,SCHOOL_UNION_ADMIN,BRANCH_UNION_CHAIRMAN')"
|
||||
class="difficult-help-approval-filter"
|
||||
:class="{'is-open': filterOpened}"
|
||||
active-color="#1989fa"
|
||||
:close-on-click-outside="false"
|
||||
:close-on-click-overlay="false"
|
||||
>
|
||||
<van-dropdown-item :options="unionList" @change="unionChange" v-model="pageForm.unionId"></van-dropdown-item>
|
||||
<van-dropdown-item :options="unitList" @change="doSearch" v-model="pageForm.unitId"></van-dropdown-item>
|
||||
<van-dropdown-item
|
||||
v-if="$auth.hasRoleOr('SYSADMIN,SCHOOL_UNION_ADMIN,BRANCH_UNION_CHAIRMAN')"
|
||||
:options="unionList"
|
||||
@change="unionChange"
|
||||
@open="onFilterOpen"
|
||||
@close="onFilterClose"
|
||||
v-model="pageForm.unionId">
|
||||
</van-dropdown-item>
|
||||
<van-dropdown-item
|
||||
v-if="$auth.hasRoleOr('SYSADMIN,SCHOOL_UNION_ADMIN,BRANCH_UNION_CHAIRMAN')"
|
||||
:options="unitList"
|
||||
@change="doSearch"
|
||||
@open="onFilterOpen"
|
||||
@close="onFilterClose"
|
||||
v-model="pageForm.unitId">
|
||||
</van-dropdown-item>
|
||||
<van-dropdown-item
|
||||
:options="approvalOptions"
|
||||
@change="onApprovalFilterChange"
|
||||
@open="onFilterOpen"
|
||||
@close="onFilterClose"
|
||||
v-model="pageForm.approvalText">
|
||||
</van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
<van-tabs v-model="pageForm.approvalText"
|
||||
@change="(val)=>{this.pageForm.audit = val==='1';this.doSearch();}">
|
||||
<van-tab title="已审核" name="1"></van-tab>
|
||||
<van-tab title="未审核" name="0"></van-tab>
|
||||
</van-tabs>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<table-list api="/platform/difficultHelp/branchUnionApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" title="userName" @ready="onReady">
|
||||
<main class="difficult-help-approval-content">
|
||||
<div class="difficult-help-list-skeleton" v-if="skeletonLoading">
|
||||
<div class="difficult-help-list-skeleton__card" v-for="index in 3" :key="'branch-approval-skeleton-' + index">
|
||||
<van-skeleton title :row="5" animated></van-skeleton>
|
||||
</div>
|
||||
</div>
|
||||
<table-list api="/platform/difficultHelp/branchUnionApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" title="userName"
|
||||
v-show="!skeletonLoading" :show_loading_overlay="false" @ready="onReady"
|
||||
@loading-change="handleListLoadingChange">
|
||||
<template #header="{index,row}">
|
||||
<div class="difficult-help-approval-card-header">
|
||||
<div class="difficult-help-approval-card-heading">
|
||||
<div class="difficult-help-approval-card-title">{{row.userName || '--'}}</div>
|
||||
<div class="difficult-help-approval-card-code">工号:{{row.loginName || '--'}}</div>
|
||||
</div>
|
||||
<enum-tag class="difficult-help-approval-card-status" v-if="row.instanceState" :value="row.instanceState"
|
||||
name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot="{index,row}">
|
||||
<table-column label="受助人">{{row.userName + '(' + row.loginName + ')'}}</table-column>
|
||||
<table-column label="申请人">{{row.proxyUserName || '--'}}</table-column>
|
||||
<table-column label="所属工会">{{row.unionName}}</table-column>
|
||||
<table-column label="工作单位">{{row.unitName}}</table-column>
|
||||
<table-column label="困难类型">{{row.subsidyStandards}}</table-column>
|
||||
@@ -41,43 +84,66 @@ layout("/layouts/platform_h5.html"){
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<van-icon name="eye-o"></van-icon>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
|
||||
<i class="fa fa-check"></i>
|
||||
<van-icon name="edit"></van-icon>
|
||||
<span>审核</span>
|
||||
</div>
|
||||
<div class="action-btn delete" v-if="row.canRevoke" @click="onRevoke(row)">
|
||||
<i class="fa fa-undo"></i>
|
||||
<van-icon name="revoke"></van-icon>
|
||||
<span>撤回</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #empty>
|
||||
<div class="difficult-help-approval-empty">
|
||||
<img src="/assets/mobile/img/difficultHelp/difficult-help-empty.png" alt="暂无帮扶审核记录插画">
|
||||
<div class="difficult-help-approval-empty__title">暂无帮扶审核记录</div>
|
||||
<div class="difficult-help-approval-empty__hint">当前筛选条件下暂时没有帮扶申请</div>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
</main>
|
||||
|
||||
|
||||
<info ref="infoRef">
|
||||
<info ref="infoRef" page-key="difficult-help-branch-union-detail" full-screen>
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">{{formData.taskName}}</div>
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
v-model="formData.tf_opinion"
|
||||
name="tf_opinion"
|
||||
label="审批意见"
|
||||
placeholder="请输入审批意见"
|
||||
:rules="[{ required: true, message: '请填写审批意见' }]"
|
||||
required
|
||||
maxlength="100"
|
||||
show-word-limit
|
||||
></van-field>
|
||||
</van-form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(2)">拒绝</van-button>
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">同意</van-button>
|
||||
<section class="difficult-help-info-card">
|
||||
<h2 class="difficult-help-info-card__title">
|
||||
审批意见<span class="difficult-help-audit-card__required">*</span>
|
||||
</h2>
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
v-model="formData.tf_opinion"
|
||||
class="difficult-help-audit-textarea"
|
||||
name="tf_opinion"
|
||||
type="textarea"
|
||||
rows="6"
|
||||
placeholder="请输入审批意见"
|
||||
:rules="[{ required: true, message: '请填写审批意见' }]"
|
||||
maxlength="100"
|
||||
show-word-limit
|
||||
></van-field>
|
||||
</van-form>
|
||||
</section>
|
||||
<div class="difficult-help-popup-actions">
|
||||
<van-button class="difficult-help-action-danger" type="danger" block :loading="formLoading" @click="handleTaskAction(6)">退回</van-button>
|
||||
<van-button class="difficult-help-action-danger" type="danger" block :loading="formLoading" @click="handleTaskAction(2)">拒绝</van-button>
|
||||
<van-button class="difficult-help-action-primary" type="primary" block :loading="formLoading" @click="handleTaskAction(1)">同意</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</info>
|
||||
<van-dialog
|
||||
:value="confirmVisible"
|
||||
title="提示"
|
||||
:message="confirmActionType === 'revoke' ? '您确定要撤回吗?' : '您确定要提交吗?'"
|
||||
show-cancel-button
|
||||
confirm-button-color="#1989fa"
|
||||
@confirm="confirmPendingAction"
|
||||
@cancel="closeActionConfirm">
|
||||
</van-dialog>
|
||||
</div>
|
||||
</div>
|
||||
<script nonce="${cspNonce!}">
|
||||
<!--#include("../common/info.js"){}#-->
|
||||
@@ -88,8 +154,9 @@ layout("/layouts/platform_h5.html"){
|
||||
data() {
|
||||
return {
|
||||
pageForm: {
|
||||
pageNo: 1,
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
searchKeyword: '',
|
||||
unionId: '',
|
||||
unitId: '',
|
||||
@@ -98,9 +165,21 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
unionList: [],
|
||||
unitList: [],
|
||||
approvalOptions: [
|
||||
{text: "未审核", value: "0"},
|
||||
{text: "已审核", value: "1"}
|
||||
],
|
||||
filterOpened: false,
|
||||
skeletonLoading: true,
|
||||
|
||||
formData: {},
|
||||
showApprovalForm: false
|
||||
showApprovalForm: false,
|
||||
formLoading: false,
|
||||
confirmVisible: false,
|
||||
confirmActionType: "task",
|
||||
pendingSubmitType: null,
|
||||
pendingRevokeRow: null,
|
||||
historyLayerUnsubscribe: null
|
||||
}
|
||||
},
|
||||
components: {
|
||||
@@ -109,6 +188,24 @@ layout("/layouts/platform_h5.html"){
|
||||
methods: {
|
||||
historyBack,
|
||||
|
||||
// state.initial 表示当前查询前列表为空,仅此阶段使用整组卡片骨架屏。
|
||||
handleListLoadingChange(state) {
|
||||
if (state.initial) this.$set(this, "skeletonLoading", state.loading)
|
||||
},
|
||||
|
||||
// 审核状态下拉值为字符串,接口参数 audit 继续使用布尔值。
|
||||
onApprovalFilterChange(val) {
|
||||
this.$set(this.pageForm, "audit", val === "1")
|
||||
this.doSearch()
|
||||
},
|
||||
// 同步筛选面板展开状态,用于调整下拉框底部圆角。
|
||||
onFilterOpen() {
|
||||
this.$set(this, "filterOpened", true)
|
||||
},
|
||||
onFilterClose() {
|
||||
this.$set(this, "filterOpened", false)
|
||||
},
|
||||
|
||||
onReady() {
|
||||
this.doSearch()
|
||||
},
|
||||
@@ -123,99 +220,139 @@ layout("/layouts/platform_h5.html"){
|
||||
|
||||
// 查看详情
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
this.$set(this, "showApprovalForm", false)
|
||||
this.$refs.infoRef.onOpen(row, "帮扶详情")
|
||||
},
|
||||
|
||||
onApproval(row) {
|
||||
this.showApprovalForm = true
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
this.formData = {
|
||||
this.$set(this, "showApprovalForm", true)
|
||||
this.$set(this, "formData", {
|
||||
processTaskId: row.taskId,
|
||||
taskName: row.curTaskName
|
||||
}
|
||||
taskName: row.curTaskName,
|
||||
tf_opinion: ""
|
||||
})
|
||||
this.$refs.infoRef.onOpen(row, row.curTaskName || "帮扶审核")
|
||||
},
|
||||
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate();
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: val
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.infoRef.onClose()
|
||||
// val 为流程提交类型:1 同意、2 拒绝、6 退回;校验通过后打开历史栈确认框。
|
||||
handleTaskAction(val) {
|
||||
this.$refs.formRef.validate()
|
||||
.then(() => {
|
||||
this.$set(this, "confirmActionType", "task")
|
||||
this.$set(this, "pendingSubmitType", val)
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open("difficult-help-action-confirm")) return
|
||||
this.$set(this, "confirmVisible", true)
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
|
||||
// 确认操作时先回退确认框历史,再根据操作类型调用办理或撤回接口。
|
||||
confirmPendingAction() {
|
||||
this.closeActionConfirm(() => {
|
||||
if (this.confirmActionType === "revoke") {
|
||||
this.revokeTask()
|
||||
return
|
||||
}
|
||||
this.submitTaskAction()
|
||||
})
|
||||
},
|
||||
|
||||
// 提交流程任务参数,接口成功后清理详情弹框历史并刷新列表。
|
||||
submitTaskAction() {
|
||||
this.$set(this, "formLoading", true)
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: this.pendingSubmitType
|
||||
})
|
||||
})
|
||||
.then((res) => {
|
||||
if (res && res.code === 0) {
|
||||
const afterClose = () => {
|
||||
this.$toast.success(res.msg)
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
|
||||
})
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
// 撤回
|
||||
onRevoke(row) {
|
||||
debugger
|
||||
this.$dialog.confirm({
|
||||
title: '提示',
|
||||
message: '您确定要撤回吗?',
|
||||
}).then(() => {
|
||||
this.$axios.post('/flow/common/revokeTask', {taskId: row.taskId}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.success('撤回成功');
|
||||
this.doSearch();
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.closeAll(afterClose)) return
|
||||
this.$refs.infoRef.onClose(afterClose)
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
});
|
||||
.finally(() => {
|
||||
this.$set(this, "formLoading", false)
|
||||
})
|
||||
},
|
||||
|
||||
closeActionConfirm(afterClose = null) {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.close("difficult-help-action-confirm", afterClose)) return
|
||||
this.$set(this, "confirmVisible", false)
|
||||
if (typeof afterClose === "function") afterClose()
|
||||
},
|
||||
|
||||
// row 提供待撤回任务 taskId,确认后由统一确认框执行撤回。
|
||||
onRevoke(row) {
|
||||
this.$set(this, "confirmActionType", "revoke")
|
||||
this.$set(this, "pendingRevokeRow", row)
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open("difficult-help-action-confirm")) return
|
||||
this.$set(this, "confirmVisible", true)
|
||||
},
|
||||
|
||||
// 使用 pendingRevokeRow.taskId 撤回任务,接口返回统一响应对象。
|
||||
revokeTask() {
|
||||
if (!this.pendingRevokeRow) return
|
||||
this.$set(this, "formLoading", true)
|
||||
this.$axios.post("/flow/common/revokeTask", {taskId: this.pendingRevokeRow.taskId})
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.success(res.msg || "撤回成功")
|
||||
this.doSearch()
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.$set(this, "formLoading", false)
|
||||
})
|
||||
},
|
||||
unionChange() {
|
||||
this.$set(this.pageForm, "unitId", null)
|
||||
this.flushUnits()
|
||||
this.doSearch()
|
||||
},
|
||||
async initUnion() {
|
||||
initUnion() {
|
||||
const hasAdmin = this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])
|
||||
const unionId = hasAdmin ? null : this.$store.state.user.union.id
|
||||
this.unionList = await this.$businessTool.listUnion(unionId)
|
||||
this.unionList.forEach((v) => {
|
||||
v.text = v.name
|
||||
v.value = v.id
|
||||
return this.$axios.post("/open/common/unionOptions", {unionId}, {h5SkeletonLoading: true}).then((res) => {
|
||||
const list = res && res.code === 0 ? res.data : []
|
||||
this.$set(this, "unionList", list || [])
|
||||
this.unionList.forEach((v) => {
|
||||
this.$set(v, "text", v.name)
|
||||
this.$set(v, "value", v.id)
|
||||
})
|
||||
if (hasAdmin) this.unionList.unshift({text: "全部工会", value: null})
|
||||
if (this.unionList.length > 0) this.$set(this.pageForm, "unionId", this.unionList[0].value)
|
||||
})
|
||||
if (hasAdmin) {
|
||||
this.unionList.unshift({ text: "全部工会", value: null })
|
||||
}
|
||||
if (this.unionList && this.unionList.length > 0) {
|
||||
this.$set(this.pageForm, "unionId", this.unionList[0].value)
|
||||
}
|
||||
},
|
||||
async flushUnits() {
|
||||
flushUnits() {
|
||||
const hasAdmin = this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])
|
||||
const unionId = hasAdmin ? this.pageForm.unionId : this.$store.state.user.union.id
|
||||
this.unitList = await this.$businessTool.listUnit(unionId)
|
||||
this.unitList.forEach((v) => {
|
||||
v.text = v.name
|
||||
v.value = v.id
|
||||
return this.$axios.post("/open/common/unitOptions", {unionId}, {h5SkeletonLoading: true}).then((res) => {
|
||||
const list = res && res.code === 0 ? res.data : []
|
||||
this.$set(this, "unitList", list || [])
|
||||
this.unitList.forEach((v) => {
|
||||
this.$set(v, "text", v.name)
|
||||
this.$set(v, "value", v.id)
|
||||
})
|
||||
this.unitList.unshift({text: "全部单位", value: null})
|
||||
if (this.unitList.length > 0) this.$set(this.pageForm, "unitId", this.unitList[0].value)
|
||||
})
|
||||
this.unitList.unshift({ text: "全部单位", value: null })
|
||||
if (this.unitList && this.unitList.length > 0) {
|
||||
this.$set(this.pageForm, "unitId", this.unitList[0].value)
|
||||
}
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
await this.initUnion()
|
||||
await this.flushUnits()
|
||||
created() {
|
||||
this.initUnion().then(() => this.flushUnits())
|
||||
if (!window.h5HistoryLayerManager) return
|
||||
this.$set(this, "historyLayerUnsubscribe", window.h5HistoryLayerManager.subscribe((stack) => {
|
||||
this.$set(this, "confirmVisible", stack.includes("difficult-help-action-confirm"))
|
||||
}))
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (typeof this.historyLayerUnsubscribe === "function") this.historyLayerUnsubscribe()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
+298
-138
@@ -1,166 +1,326 @@
|
||||
const INFO = {
|
||||
template: /*language=HTML*/ `
|
||||
<van-action-sheet v-model="visible" title="查看详情">
|
||||
<div class="detail-container">
|
||||
<van-cell-group title="基本信息">
|
||||
<van-cell title="填写人姓名">{{ viewData.proxyUserName }}</van-cell>
|
||||
<van-cell title="填写人工号">{{ viewData.proxyLoginName }}</van-cell>
|
||||
<van-cell title="性别">{{ viewData.sex }}</van-cell>
|
||||
<component
|
||||
:is="detailComponent"
|
||||
v-model="visible"
|
||||
:title="detailTitle"
|
||||
:position="detailPosition"
|
||||
:class="detailClass"
|
||||
:close-on-click-overlay="false"
|
||||
:get-container="detailContainer"
|
||||
>
|
||||
<div :class="{'difficult-help-full-popup__page': fullScreen, 'detail-container': !fullScreen}">
|
||||
<van-nav-bar
|
||||
v-if="fullScreen"
|
||||
:title="popupTitle"
|
||||
left-arrow
|
||||
left-text="返回"
|
||||
fixed
|
||||
@click-left="onClose()"
|
||||
></van-nav-bar>
|
||||
<div ref="detailScrollRef" :class="{'difficult-help-full-popup__scroll': fullScreen}">
|
||||
<main :class="{'difficult-help-info-main': fullScreen}">
|
||||
<section :class="{'difficult-help-info-card': fullScreen}">
|
||||
<h2 v-if="fullScreen" class="difficult-help-info-card__title">基本信息</h2>
|
||||
<van-cell-group :title="fullScreen ? '' : '基本信息'" :border="!fullScreen">
|
||||
<van-cell title="填写人姓名">{{ viewData.proxyUserName || '--' }}</van-cell>
|
||||
<van-cell title="填写人工号">{{ viewData.proxyLoginName || '--' }}</van-cell>
|
||||
<van-cell title="性别">{{ viewData.sex || '--' }}</van-cell>
|
||||
<van-cell title="受助人">
|
||||
{{ viewData.userName || '--' }}{{ viewData.loginName ? '(' + viewData.loginName + ')' : '' }}
|
||||
</van-cell>
|
||||
<van-cell title="所在单位">{{ viewData.unitName || '--' }}</van-cell>
|
||||
<van-cell title="所在工会">{{ viewData.unionName || '--' }}</van-cell>
|
||||
<van-cell title="职务">{{ viewData.position || '--' }}</van-cell>
|
||||
<van-cell title="职称">{{ viewData.officialCapacity || '--' }}</van-cell>
|
||||
<van-cell title="联系电话">{{ viewData.mobile || '--' }}</van-cell>
|
||||
<van-cell title="家庭年总收入(万元)">{{ viewData.homeIncome || '--' }}</van-cell>
|
||||
<van-cell title="家庭人数">{{ viewData.homeNumber || '--' }}</van-cell>
|
||||
<van-cell :class="{'difficult-help-info-long-cell': fullScreen}" title="家庭住址">
|
||||
{{ viewData.homeAddress || '--' }}
|
||||
</van-cell>
|
||||
<van-cell title="补助类型">
|
||||
<dict-tag :options="dict.type.DIFFICULT_SUBSIDY_TYPE" :value="viewData.subsidy"></dict-tag>
|
||||
</van-cell>
|
||||
<van-cell title="困难类型">
|
||||
<dict-tag :options="dict.type.DIFFICULT_TYPE" :value="viewData.subsidyStandards"></dict-tag>
|
||||
</van-cell>
|
||||
<van-cell title="申请次数">{{ viewData.applyCount || 1 }}</van-cell>
|
||||
<van-cell :class="{'difficult-help-info-long-cell': fullScreen}" title="开户行">
|
||||
{{ viewData.bankOfDeposit || '--' }}
|
||||
</van-cell>
|
||||
<van-cell title="银行卡号">{{ viewData.bankCardNum || '--' }}</van-cell>
|
||||
<van-cell :class="{'difficult-help-info-long-cell': fullScreen, 'text-cell': !fullScreen}" title="生活致困原因">
|
||||
<div class="difficult-help-info-pre-line">{{ viewData.reason || '暂无' }}</div>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
|
||||
<van-cell title="受助人">{{ viewData.userName + '(' + viewData.loginName + ')' }}</van-cell>
|
||||
<van-cell title="所在单位">{{ viewData.unitName }}</van-cell>
|
||||
<van-cell title="所在工会">{{ viewData.unionName }}</van-cell>
|
||||
|
||||
<van-cell title="职务">{{ viewData.position }}</van-cell>
|
||||
<van-cell title="职称">{{ viewData.officialCapacity }}</van-cell>
|
||||
<van-cell title="联系电话">{{ viewData.mobile }}</van-cell>
|
||||
|
||||
<van-cell title="家庭年总收入(万元)">{{ viewData.homeIncome }}</van-cell>
|
||||
<van-cell title="家庭人数">{{ viewData.homeNumber }}</van-cell>
|
||||
<van-cell title="家庭住址">{{ viewData.homeAddress }}</van-cell>
|
||||
|
||||
<van-cell title="补助类型">
|
||||
<dict-tag :options="dict.type.DIFFICULT_SUBSIDY_TYPE" :value="viewData.subsidy"></dict-tag>
|
||||
</van-cell>
|
||||
<van-cell title="困难类型">
|
||||
<dict-tag :options="dict.type.DIFFICULT_TYPE" :value="viewData.subsidyStandards"></dict-tag>
|
||||
</van-cell>
|
||||
<van-cell title="申请次数">{{ viewData.applyCount || 1 }}</van-cell>
|
||||
|
||||
<van-cell title="开户行">{{ viewData.bankOfDeposit }}</van-cell>
|
||||
<van-cell title="银行卡号">{{ viewData.bankCardNum }}</van-cell>
|
||||
|
||||
<van-cell title="生活致困原因" class="text-cell">
|
||||
<template #label>
|
||||
<div style="word-wrap: break-word; white-space: pre-line;">
|
||||
{{viewData.reason}}
|
||||
<section v-if="fullScreen" class="difficult-help-info-card">
|
||||
<h2 class="difficult-help-info-card__title">家庭成员</h2>
|
||||
<div v-if="viewData.familyList && viewData.familyList.length" class="difficult-help-family-list">
|
||||
<article
|
||||
v-for="(item, index) in viewData.familyList"
|
||||
:key="index"
|
||||
class="difficult-help-family-item"
|
||||
>
|
||||
<header class="difficult-help-family-header">
|
||||
<span class="difficult-help-family-index">{{ index + 1 }}</span>
|
||||
<strong class="difficult-help-family-name">{{ item.name || '未填写姓名' }}</strong>
|
||||
<span class="difficult-help-family-relation">{{ item.relation || '关系未填写' }}</span>
|
||||
</header>
|
||||
<div class="difficult-help-family-summary">
|
||||
<div class="difficult-help-family-summary__item">
|
||||
<span>年龄</span>
|
||||
<strong>
|
||||
{{ item.age !== null && item.age !== undefined && item.age !== '' ? item.age + ' 岁' : '--' }}
|
||||
</strong>
|
||||
</div>
|
||||
<div class="difficult-help-family-summary__item">
|
||||
<span>年收入</span>
|
||||
<strong>
|
||||
{{ item.yearIncome !== null && item.yearIncome !== undefined && item.yearIncome !== '' ? item.yearIncome + ' 元' : '--' }}
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div class="difficult-help-family-detail">
|
||||
<div class="difficult-help-family-detail__row">
|
||||
<span>工作单位</span>
|
||||
<strong>{{ item.homeUnit || '--' }}</strong>
|
||||
</div>
|
||||
<div class="difficult-help-family-detail__row">
|
||||
<span>备注</span>
|
||||
<strong>{{ item.remarks || '--' }}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</template>
|
||||
</van-cell>
|
||||
<van-empty v-else description="暂无家庭成员信息" image-size="72"></van-empty>
|
||||
</section>
|
||||
|
||||
<van-cell title="家庭成员" class="column-cell">
|
||||
<table class="family-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="table-header">序号</th>
|
||||
<th class="table-header">与本人关系</th>
|
||||
<th class="table-header">姓名</th>
|
||||
<th class="table-header">年龄</th>
|
||||
<th class="table-header">工作单位</th>
|
||||
<th class="table-header">年收入(元)</th>
|
||||
<th class="table-header">备注</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="table-row" v-for="(item, index) in viewData.familyList" :key="index">
|
||||
<td class="table-cell">{{ index + 1 }}</td>
|
||||
<td class="table-cell">{{ item.relation }}</td>
|
||||
<td class="table-cell">{{ item.name }}</td>
|
||||
<td class="table-cell">{{ item.age }}</td>
|
||||
<td class="table-cell">{{ item.homeUnit }}</td>
|
||||
<td class="table-cell">{{ item.yearIncome }}</td>
|
||||
<td class="table-cell">{{ item.remarks }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</van-cell>
|
||||
<van-cell-group v-else title="家庭成员">
|
||||
<van-cell class="column-cell">
|
||||
<table class="family-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="table-header">序号</th>
|
||||
<th class="table-header">与本人关系</th>
|
||||
<th class="table-header">姓名</th>
|
||||
<th class="table-header">年龄</th>
|
||||
<th class="table-header">工作单位</th>
|
||||
<th class="table-header">年收入(元)</th>
|
||||
<th class="table-header">备注</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="table-row" v-for="(item, index) in viewData.familyList" :key="index">
|
||||
<td class="table-cell">{{ index + 1 }}</td>
|
||||
<td class="table-cell">{{ item.relation }}</td>
|
||||
<td class="table-cell">{{ item.name }}</td>
|
||||
<td class="table-cell">{{ item.age }}</td>
|
||||
<td class="table-cell">{{ item.homeUnit }}</td>
|
||||
<td class="table-cell">{{ item.yearIncome }}</td>
|
||||
<td class="table-cell">{{ item.remarks }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
|
||||
<van-cell title="本人承诺">
|
||||
<div style="text-align: left; padding: 5px 0; font-size: 14px;">
|
||||
本人及家庭成员未有购买价格超过15万元的机动车,也未有两套及以上商品房,特此承诺!
|
||||
</div>
|
||||
<div style="text-align: right; font-size: 12px; color: #999; margin-top: 5px;">
|
||||
<span>承诺人:{{ viewData.userName }}</span>
|
||||
<br/>
|
||||
<span>{{ $moment(viewData.applyTime).format("YYYY-MM-DD") }}</span>
|
||||
</div>
|
||||
</van-cell>
|
||||
<section :class="{'difficult-help-info-card': fullScreen}">
|
||||
<h2 v-if="fullScreen" class="difficult-help-info-card__title">承诺与材料</h2>
|
||||
<van-cell-group :title="fullScreen ? '' : '承诺与材料'" :border="!fullScreen">
|
||||
<van-cell :class="{'difficult-help-info-long-cell': fullScreen}" title="本人承诺">
|
||||
<div class="difficult-help-info-promise">
|
||||
本人及家庭成员未有购买价格超过15万元的机动车,也未有两套及以上商品房,特此承诺!
|
||||
</div>
|
||||
<div class="difficult-help-info-commitment">
|
||||
<span>承诺人:{{ viewData.userName || '--' }}</span>
|
||||
<span>{{ viewData.applyTime ? $moment(viewData.applyTime).format('YYYY-MM-DD') : '--' }}</span>
|
||||
</div>
|
||||
</van-cell>
|
||||
<van-cell :class="{'difficult-help-info-long-cell': fullScreen}" title="签字">
|
||||
<van-image
|
||||
v-if="viewData.sign"
|
||||
:src="viewData.sign"
|
||||
class="difficult-help-signature-image"
|
||||
></van-image>
|
||||
<span v-else>暂无签字</span>
|
||||
</van-cell>
|
||||
<van-cell :class="{'difficult-help-info-long-cell': fullScreen}" title="附件">
|
||||
<file-preview v-if="fullScreen" :files="viewData.files" complete_result></file-preview>
|
||||
<template v-else-if="viewData.files && viewData.files.length">
|
||||
<div v-for="(file, index) in viewData.files" :key="index">
|
||||
<a :href="file.url" target="_blank">{{ file.name }}</a>
|
||||
</div>
|
||||
</template>
|
||||
<span v-else>暂无</span>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
|
||||
<van-cell title="签字" v-if="viewData.sign">
|
||||
<img :src="viewData.sign" style="max-width: 100px; max-height: 50px;" />
|
||||
</van-cell>
|
||||
|
||||
<van-cell title="附件" v-if="viewData.files && viewData.files.length > 0">
|
||||
<div v-for="(file, index) in viewData.files" :key="index" style="margin-bottom: 5px;">
|
||||
<a :href="file.url" target="_blank">{{ file.name }}</a>
|
||||
</div>
|
||||
</van-cell>
|
||||
<van-cell title="附件" v-else>
|
||||
<span>暂无</span>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
|
||||
<template v-for="task in doneTasks">
|
||||
<van-cell-group :title="task.displayName" v-if="task.ext.isFirstTaskNode">
|
||||
<van-cell title="申请用户">{{ task.ext.initiatorName }}({{task.ext.initiatorAccount}})
|
||||
</van-cell>
|
||||
<van-cell title="申请时间">{{ task.finishTime }}</van-cell>
|
||||
<van-cell title="办理结果">
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
|
||||
:value="task.ext.submitType"></dict-tag>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
|
||||
<van-cell-group :title="task.displayName" v-else>
|
||||
<van-cell title="办理用户">{{ task.taskFormData.userName }}({{task.taskFormData.loginName}})
|
||||
</van-cell>
|
||||
<van-cell title="办理时间">{{ task.finishTime }}</van-cell>
|
||||
|
||||
<van-cell title="审批级别" v-if="task.displayName == '校工会审核'">
|
||||
{{ viewData.level }}
|
||||
</van-cell>
|
||||
<van-cell title="审批金额" v-if="task.displayName == '校工会审核'">
|
||||
{{ '¥' + viewData.money }}
|
||||
</van-cell>
|
||||
|
||||
<van-cell title="办理结果">
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
|
||||
:value="task.ext.submitType"></dict-tag>
|
||||
</van-cell>
|
||||
<van-cell title="办理意见" v-if="!task.ext.isFirstTaskNode && task.taskFormData.opinion" class="direction-column-cell">
|
||||
<div style="white-space: pre-line;">{{ task.taskFormData.opinion }}</div>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
</template>
|
||||
<section
|
||||
v-for="(task, index) in doneTasks"
|
||||
:key="task.id || index"
|
||||
:class="{'difficult-help-info-card': fullScreen}"
|
||||
>
|
||||
<h2 v-if="fullScreen" class="difficult-help-info-card__title">
|
||||
{{ task.displayName || '办理记录' }}
|
||||
</h2>
|
||||
<van-cell-group
|
||||
v-if="task.ext && task.ext.isFirstTaskNode"
|
||||
:title="fullScreen ? '' : task.displayName"
|
||||
:border="!fullScreen"
|
||||
>
|
||||
<van-cell title="申请用户">
|
||||
{{ task.ext.initiatorName || '--' }}{{ task.ext.initiatorAccount ? '(' + task.ext.initiatorAccount + ')' : '' }}
|
||||
</van-cell>
|
||||
<van-cell title="申请时间">{{ task.finishTime || '--' }}</van-cell>
|
||||
<van-cell title="办理结果">
|
||||
<dict-tag
|
||||
:options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
|
||||
:value="task.ext.submitType"
|
||||
></dict-tag>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
<van-cell-group v-else :title="fullScreen ? '' : task.displayName" :border="!fullScreen">
|
||||
<van-cell title="办理用户">
|
||||
{{ task.taskFormData && task.taskFormData.userName || '--' }}{{ task.taskFormData && task.taskFormData.loginName ? '(' + task.taskFormData.loginName + ')' : '' }}
|
||||
</van-cell>
|
||||
<van-cell title="办理时间">{{ task.finishTime || '--' }}</van-cell>
|
||||
<van-cell v-if="task.displayName === '校工会审核'" title="审批级别">
|
||||
{{ viewData.level || '--' }}
|
||||
</van-cell>
|
||||
<van-cell v-if="task.displayName === '校工会审核'" title="审批金额">
|
||||
{{ viewData.money ? '¥' + viewData.money : '--' }}
|
||||
</van-cell>
|
||||
<van-cell title="办理结果">
|
||||
<dict-tag
|
||||
:options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
|
||||
:value="task.ext && task.ext.submitType"
|
||||
></dict-tag>
|
||||
</van-cell>
|
||||
<van-cell
|
||||
v-if="task.taskFormData && (task.taskFormData.opinion || task.taskFormData.tf_opinion)"
|
||||
:class="{'difficult-help-info-long-cell': fullScreen, 'direction-column-cell': !fullScreen}"
|
||||
title="办理意见"
|
||||
>
|
||||
<div class="difficult-help-info-pre-line">
|
||||
{{ task.taskFormData.opinion || task.taskFormData.tf_opinion }}
|
||||
</div>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
<slot></slot>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
<slot></slot>
|
||||
</van-action-sheet>
|
||||
</component>
|
||||
`,
|
||||
dicts: ["PROCESS_TASK_SUBMIT_TYPE", "DIFFICULT_SUBSIDY_TYPE", "DIFFICULT_TYPE"], data() {
|
||||
dicts: ["PROCESS_TASK_SUBMIT_TYPE", "DIFFICULT_SUBSIDY_TYPE", "DIFFICULT_TYPE"],
|
||||
props: {
|
||||
fullScreen: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
pageKey: {
|
||||
type: String,
|
||||
default: ""
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
popupTitle: "帮扶详情",
|
||||
row: {},
|
||||
viewData: {},
|
||||
doneTasks: [],
|
||||
historyLayerUnsubscribe: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
detailComponent() {
|
||||
return this.fullScreen ? "van-popup" : "van-action-sheet"
|
||||
},
|
||||
detailTitle() {
|
||||
return this.fullScreen ? undefined : "查看详情"
|
||||
},
|
||||
detailPosition() {
|
||||
return this.fullScreen ? "right" : undefined
|
||||
},
|
||||
detailClass() {
|
||||
return this.fullScreen ? "difficult-help-full-popup" : ""
|
||||
},
|
||||
detailContainer() {
|
||||
return this.fullScreen ? "#app" : undefined
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onOpen(row) {
|
||||
this.row = row
|
||||
this.visible = true
|
||||
this.info()
|
||||
this.getDoneTasks()
|
||||
// 浏览器历史变化时,只同步当前困难帮扶详情弹框的显示状态。
|
||||
syncHistoryLayerStack(stack) {
|
||||
this.$set(this, "visible", stack.includes("difficult-help-detail"))
|
||||
},
|
||||
|
||||
// 关闭
|
||||
onClose(){
|
||||
this.visible = false
|
||||
// 全屏详情复用同一滚动容器,每次切换记录后将内部滚动位置恢复到基本信息顶部。
|
||||
resetScrollPosition() {
|
||||
if (!this.fullScreen) return
|
||||
this.$nextTick(() => {
|
||||
const scrollContainer = this.$refs.detailScrollRef
|
||||
if (scrollContainer) scrollContainer.scrollTop = 0
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 打开困难帮扶详情。
|
||||
* row 传列表当前行,title 传顶部导航标题;方法无返回值,详情数据和流程记录由组件内部加载。
|
||||
*/
|
||||
onOpen(row, title = "帮扶详情") {
|
||||
this.$set(this, "row", row || {})
|
||||
this.$set(this, "popupTitle", title)
|
||||
this.$set(this, "viewData", {})
|
||||
this.$set(this, "doneTasks", [])
|
||||
this.info()
|
||||
this.getDoneTasks()
|
||||
this.resetScrollPosition()
|
||||
if (this.fullScreen && window.h5HistoryLayerManager && window.h5HistoryLayerManager.open("difficult-help-detail")) return
|
||||
this.$set(this, "visible", true)
|
||||
},
|
||||
|
||||
// 顶部返回按钮与业务主动关闭统一回退详情弹框对应的浏览器历史。
|
||||
onClose(afterClose = null) {
|
||||
if (this.fullScreen && window.h5HistoryLayerManager && window.h5HistoryLayerManager.close("difficult-help-detail", afterClose)) return
|
||||
this.$set(this, "visible", false)
|
||||
if (typeof afterClose === "function") afterClose()
|
||||
},
|
||||
|
||||
info() {
|
||||
this.$axios.post("/platform/difficultHelp/mine/findOne", { id: this.row.id }).then((res) => {
|
||||
this.$axios.post("/platform/difficultHelp/mine/findOne", {id: this.row.id}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.viewData = res.data
|
||||
this.$set(this, "viewData", res.data || {})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
getDoneTasks() {
|
||||
this.$axios.post("/flow/common/doneTasks", { bizId: this.row.id }).then((res) => {
|
||||
this.$axios.post("/flow/common/doneTasks", {bizId: this.row.id}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.doneTasks = res.data
|
||||
this.$set(this, "doneTasks", res.data || [])
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (!this.fullScreen || !this.pageKey || !window.h5HistoryLayerManager) return
|
||||
window.h5HistoryLayerManager.ensureRegistered(this.pageKey)
|
||||
this.$set(this, "historyLayerUnsubscribe", window.h5HistoryLayerManager.subscribe((stack) => {
|
||||
this.syncHistoryLayerStack(stack)
|
||||
}))
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (typeof this.historyLayerUnsubscribe === "function") this.historyLayerUnsubscribe()
|
||||
if (this.fullScreen && window.h5HistoryLayerManager && window.h5HistoryLayerManager.pageKey === this.pageKey) {
|
||||
window.h5HistoryLayerManager.unregister(this.pageKey)
|
||||
}
|
||||
},
|
||||
style: /*language=CSS*/ `
|
||||
.column-cell {
|
||||
@@ -169,21 +329,21 @@ const INFO = {
|
||||
.family-table {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
margin: 20px 0;
|
||||
border-collapse: collapse;
|
||||
table-layout: auto;
|
||||
font-family: Arial, sans-serif;
|
||||
text-align: center;
|
||||
font-family: 'Arial', sans-serif;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.table-header {
|
||||
background-color: gray;
|
||||
color: white;
|
||||
background-color: gray;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.table-row {
|
||||
background-color: #f9f9f9;
|
||||
transition: background-color 0.3s;
|
||||
transition: background-color .3s;
|
||||
}
|
||||
.table-row:hover {
|
||||
background-color: #f1f1f1;
|
||||
@@ -191,8 +351,8 @@ const INFO = {
|
||||
.table-cell {
|
||||
padding: 10px 5px;
|
||||
border: 1px solid #ddd;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
.text-cell {
|
||||
word-break: break-all;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user