Merge branch 'release_20260831' into feature_周何峰
@@ -70,7 +70,7 @@ public class FlowCommonService {
|
||||
args.put(FlowConst.TASK_FORM_DATA_PREFIX + "userName", SecurityUtil.getUserUsername());
|
||||
args.put(FlowConst.TASK_FORM_DATA_PREFIX + "loginName", SecurityUtil.getUserLoginname());
|
||||
args.put(FlowConst.TASK_FORM_DATA_PREFIX + "unitId", SecurityUtil.getUnitId());
|
||||
args.put(FlowConst.TASK_FORM_DATA_PREFIX + "unitName", Optional.of(sysUnit).map(Sys_unit::getName).orElse(""));
|
||||
args.put(FlowConst.TASK_FORM_DATA_PREFIX + "unitName", Optional.ofNullable(sysUnit).map(Sys_unit::getName).orElse(""));
|
||||
args.put(FlowConst.TASK_FORM_DATA_PREFIX + "unionId", SecurityUtil.getUnionId());
|
||||
|
||||
if (ObjectUtil.equals(submitType, ProcessSubmitTypeEnum.ROLLBACK.getCode())) {
|
||||
|
||||
@@ -11,7 +11,7 @@ import org.nutz.mvc.annotation.Ok;
|
||||
public class ActivityWorksCollectionNewController {
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/activity/workscollection/manage/index.html")
|
||||
@Ok("beetl:/platform/zhgh/activity/workscollection/new/index.html")
|
||||
@SaCheckPermission(value = {"activity.workscollection.manage", "activity.workscollection.new"}, mode = SaMode.OR)
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.budwk.app.zhgh.activity.workscollection.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.result.Result;
|
||||
@@ -19,6 +20,7 @@ import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.dao.util.Daos;
|
||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||
import org.nutz.dao.util.cri.Static;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
@@ -56,16 +58,21 @@ public class ActivityWorksCollectionUploadController {
|
||||
/**
|
||||
* @param pageForm 分页
|
||||
* @param activityId 活动id
|
||||
* @param subjectId 作品类型
|
||||
* @return
|
||||
* @param subjectId 主题类型主键
|
||||
* @param worksId 作品类型主键
|
||||
* @param year 活动开始时间所在年度
|
||||
* @param activityType 活动状态:1 全部、2 征集中、3 已结束
|
||||
* @return Result,data 为当前登录人的作品分页数据
|
||||
*/
|
||||
@At
|
||||
@SaCheckPermission("activity.workscollection.upload")
|
||||
public Result pageData(@Valid PageForm pageForm, String activityId, String subjectId, String worksId, Long year) {
|
||||
public Result pageData(@Valid PageForm pageForm, String activityId, String subjectId, String worksId,
|
||||
Long year, Integer activityType) {
|
||||
Sql sql = Sqls.create("""
|
||||
select
|
||||
up.*,
|
||||
co.NAME AS activityName,
|
||||
co.cover AS cover,
|
||||
co.startDateTime AS activityStartDateTime,
|
||||
co.endDateTime AS activityEndDateTime,
|
||||
su.typeName AS subjectName,
|
||||
@@ -83,6 +90,19 @@ public class ActivityWorksCollectionUploadController {
|
||||
cnd.andEX("up.activityId", "=", activityId);
|
||||
cnd.andEX("up.subjectId", "=", subjectId);
|
||||
cnd.andEX("up.worksId", "=", worksId);
|
||||
// searchKeyword 支持按作品名称或所属活动名称搜索,空值不参与筛选。
|
||||
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||
String keyword = "%" + pageForm.getSearchKeyword().trim() + "%";
|
||||
SqlExpressionGroup keywordGroup = Cnd.exps("up.name", "like", keyword)
|
||||
.or("co.name", "like", keyword);
|
||||
cnd.and(keywordGroup);
|
||||
}
|
||||
// activityType:1 或空值查询全部,2 查询征集中,3 查询已结束。
|
||||
if (activityType != null && activityType == 2) {
|
||||
cnd.and(new Static("now() >= co.startDateTime and now() < co.endDateTime"));
|
||||
} else if (activityType != null && activityType == 3) {
|
||||
cnd.and(new Static("now() >= co.endDateTime"));
|
||||
}
|
||||
cnd.desc("up.createdAt");
|
||||
sql.setCondition(cnd);
|
||||
Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.budwk.app.zhgh.activity.workscollection.controller.h5;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.dev33.satoken.annotation.SaMode;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.result.Result;
|
||||
@@ -64,7 +65,11 @@ public class H5ActivityWorksUploadCollectionController {
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("YEAR(awc.startDateTime)", "=", year);
|
||||
//查询报名中
|
||||
// searchKeyword 为活动名称关键字,空值不参与筛选;接口仍返回分页对象。
|
||||
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||
cnd.and("awc.name", "like", "%" + pageForm.getSearchKeyword().trim() + "%");
|
||||
}
|
||||
// activityType:1 全部、2 征集中、3 已结束、4 即将开始。
|
||||
if (activityType == 2) {
|
||||
cnd.and(new Static("now() > awc.startDateTime and now() < awc.endDateTime"));
|
||||
}//查询已结束的
|
||||
|
||||
@@ -99,7 +99,6 @@ public class DifficultHelpMineController {
|
||||
difficult_help_info info
|
||||
LEFT JOIN `wf_process_instance` ins ON ins.businessNo = info.id
|
||||
LEFT JOIN wf_process_task t ON t.processInstanceId = ins.id AND t.taskState = 10
|
||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
|
||||
|
After Width: | Height: | Size: 469 B |
|
After Width: | Height: | Size: 414 B |
|
After Width: | Height: | Size: 448 B |
|
After Width: | Height: | Size: 447 B |
|
After Width: | Height: | Size: 722 B |
|
After Width: | Height: | Size: 1021 KiB |
@@ -0,0 +1,8 @@
|
||||
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="24" cy="24" r="22" fill="#EAF3FF"/>
|
||||
<rect x="15" y="11" width="18" height="17" rx="4" fill="#2F7CF6"/>
|
||||
<path d="M12 24C10.8954 24 10 24.8954 10 26V32C10 33.1046 10.8954 34 12 34H36C37.1046 34 38 33.1046 38 32V26C38 24.8954 37.1046 24 36 24C34.8954 24 34 24.8954 34 26V29H14V26C14 24.8954 13.1046 24 12 24Z" fill="#1769E8"/>
|
||||
<rect x="14" y="28" width="20" height="7" rx="2.5" fill="#2F7CF6"/>
|
||||
<path d="M16 34H20L19 38H15L16 34Z" fill="#1769E8"/>
|
||||
<path d="M28 34H32L33 38H29L28 34Z" fill="#1769E8"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 637 B |
|
After Width: | Height: | Size: 986 KiB |
|
After Width: | Height: | Size: 257 KiB |
@@ -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: {
|
||||
@@ -103,9 +108,94 @@ module.exports = {
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,283 +118,7 @@ layout("/layouts/platform.html"){
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #edit>
|
||||
<div v-if="formVisible">
|
||||
<el-form :model="formData" ref="formRef" label-width="130px" :rules="formRules">
|
||||
<el-form-item label="活动主题" prop="name">
|
||||
<el-input placeholder="请输入活动主题" v-model="formData.name" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="活动时间" prop="activityTime">
|
||||
<el-date-picker
|
||||
:default-time="['00:00:00']"
|
||||
end-placeholder="结束时间"
|
||||
start-placeholder="开始时间"
|
||||
style="width: 100%"
|
||||
type="datetimerange"
|
||||
v-model="formData.activityTime"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="点赞时间" prop="nbTime">
|
||||
<el-date-picker
|
||||
:default-time="['00:00:00']"
|
||||
end-placeholder="结束时间"
|
||||
start-placeholder="开始时间"
|
||||
style="width: 100%"
|
||||
type="datetimerange"
|
||||
v-model="formData.nbTime"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="每人每日点赞次数" prop="nbCount">
|
||||
<el-input-number
|
||||
:min="0"
|
||||
placeholder="请输入每人每日点赞次数"
|
||||
style="width: 100%"
|
||||
v-model="formData.nbCount"
|
||||
></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="主题类型" prop="subjectTypes">
|
||||
<el-row class="pb5" v-for="(type,index) in formData.subjectTypes" :key="type.id">
|
||||
<el-col :span="20">
|
||||
<el-input placeholder="请输入名称" v-model="type.typeName"></el-input>
|
||||
</el-col>
|
||||
<el-col :span="2" style="text-align: center">
|
||||
<el-button @click="addType(index)" icon="el-icon-plus" type="primary"></el-button>
|
||||
</el-col>
|
||||
<el-col :span="2" style="text-align: center">
|
||||
<el-button
|
||||
:disabled="index == 0"
|
||||
@click="formData.subjectTypes.splice(index,1)"
|
||||
icon="el-icon-delete"
|
||||
type="danger"
|
||||
></el-button>
|
||||
</el-col>
|
||||
<el-col class="pt5 pb5">
|
||||
<el-row class="pb5" v-for="(worksType,worksIndex) in type.worksTypes" :key="worksType.id">
|
||||
<el-col :span="18">
|
||||
<el-col :span="2">
|
||||
<span class="el-form-item__label" v-if="worksIndex === 0">作品类型</span>
|
||||
<span v-else> </span>
|
||||
</el-col>
|
||||
<el-col :span="22">
|
||||
<el-input placeholder="请输入名称" v-model="worksType.worksTypeName"></el-input>
|
||||
</el-col>
|
||||
</el-col>
|
||||
<el-col :span="2" style="text-align: center">
|
||||
<el-button @click="openSetting(worksType)" icon="el-icon-s-tools"
|
||||
type="primary"></el-button>
|
||||
</el-col>
|
||||
<el-col :span="2" style="text-align: center">
|
||||
<el-button @click="addWorksType(type, worksIndex)" icon="el-icon-plus"
|
||||
type="primary"></el-button>
|
||||
</el-col>
|
||||
<el-col :span="2" style="text-align: center">
|
||||
<el-button @click="type.worksTypes.splice(worksIndex, 1)" icon="el-icon-delete"
|
||||
type="danger"></el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item label="面向对象" prop="joinCnd">
|
||||
<div style="display: flex; justify-content: space-between">
|
||||
<div style="width: 99%">
|
||||
<el-select clearable filterable placeholder="请选择参加人员范围" style="width: 99%"
|
||||
v-model="formData.activityGroupId">
|
||||
<el-option
|
||||
:label="item.groupName"
|
||||
:value="item.groupId"
|
||||
v-for="item in activityGroupList"
|
||||
:key="item.groupId"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<div>
|
||||
<el-button @click="$refs.drawerUserScope.userScopeDialog = true" type="primary">设置
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="hostUnitIds" label="主办单位">
|
||||
<el-select v-model="formData.hostUnitIds" clearable filterable multiple
|
||||
placeholder="请选择主办单位"
|
||||
style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in unitOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="undertakeUnitIds" label="承办单位">
|
||||
<el-select v-model="formData.undertakeUnitIds" clearable filterable multiple
|
||||
placeholder="请选择承办单位"
|
||||
style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in unitOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="活动内容" prop="content">
|
||||
<text-editor v-model="formData.content"></text-editor>
|
||||
</el-form-item>
|
||||
<!--<el-form-item label="活动介绍" prop="introduce">
|
||||
<text-editor v-model="formData.introduce"></text-editor>
|
||||
</el-form-item>
|
||||
<el-form-item label="奖励方式" prop="rewardMethod">
|
||||
<text-editor v-model="formData.rewardMethod"></text-editor>
|
||||
</el-form-item>-->
|
||||
<el-form-item label="活动封面">
|
||||
<file-upload
|
||||
:upload_number="1"
|
||||
:value.sync="formData.cover"
|
||||
accept=".jpg,.jpeg,.png"
|
||||
complete_result
|
||||
upload_mode="image"
|
||||
upload_result_category="interval"
|
||||
></file-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label="配色" prop="activityColor">
|
||||
<el-color-picker v-model="formData.activityColor" show-alpha></el-color-picker>
|
||||
</el-form-item>
|
||||
<el-form-item prop="enable" label="状态">
|
||||
<el-radio-group v-model="formData.enable" size="small">
|
||||
<el-radio :label="true" border>开启</el-radio>
|
||||
<el-radio :label="false" border>关闭</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-row class="mt20" justify="end" type="flex">
|
||||
<el-button @click="close">取消</el-button>
|
||||
<el-button type="primary" v-if="copyTemplateMode || formData.isSubmit!=true" plain @click="doSave">{{ copyTemplateMode ? "另存为" : "保存" }}</el-button>
|
||||
<el-button type="primary" @click="doSubmit">{{ copyTemplateMode ? "新活动提交" : "确定" }}</el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
</guava>
|
||||
|
||||
<drawer-user-scope v-if="formVisible" :group_id.sync="formData.activityGroupId" @group_change="getActivityGroup"
|
||||
ref="drawerUserScope"></drawer-user-scope>
|
||||
|
||||
<el-dialog v-if="formVisible" :close-on-click-modal="false" :visible.sync="settingDialogVisible" title="更多设置" top="4%" width="40%">
|
||||
<el-form :model="currentWorksType" label-width="160px" size="small">
|
||||
<el-form-item label="作品介绍最多字数">
|
||||
<el-input-number :max="10000" :min="1" style="width: 100%"
|
||||
v-model="currentWorksType.maxWordCount"></el-input-number>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="允许上传的文件类型" prop="allowFileTypes">
|
||||
<el-checkbox-group v-model="currentWorksType.allowFileTypes">
|
||||
<el-checkbox key="jpg" label="jpg">jpg</el-checkbox>
|
||||
<el-checkbox key="jpeg" label="jpeg">jpeg</el-checkbox>
|
||||
<el-checkbox key="png" label="png">png</el-checkbox>
|
||||
<el-checkbox key="mp3" label="mp3">mp3</el-checkbox>
|
||||
<el-checkbox key="mp4" label="mp4">mp4</el-checkbox>
|
||||
<el-checkbox key="docx" label="docx">docx</el-checkbox>
|
||||
<el-checkbox key="xlsx" label="xlsx">xlsx</el-checkbox>
|
||||
<el-checkbox key="pdf" label="pdf">pdf</el-checkbox>
|
||||
<el-checkbox key="zip" label="zip">zip</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="允许上传的文件数量" prop="allowFileNum">
|
||||
<el-input-number :max="10000" :min="1" style="width: 100%"
|
||||
v-model="currentWorksType.allowFileNum"></el-input-number>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="单个文件大小(kb)" prop="allowSingleFileSize">
|
||||
<el-input-number :min="1" style="width: 100%"
|
||||
v-model="currentWorksType.allowSingleFileSize"></el-input-number>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="总文件大小(kb)" prop="allowTotalFileSize">
|
||||
<el-input-number :min="1" style="width: 100%"
|
||||
v-model="currentWorksType.allowTotalFileSize"></el-input-number>
|
||||
</el-form-item>
|
||||
|
||||
<!-- <div class="left-span-label">上传图片设置</div>-->
|
||||
|
||||
<!-- <el-form-item label="是否上传图片">-->
|
||||
<!-- <el-radio :label="true" border v-model="currentWorksType.isUploadPhoto">上传</el-radio>-->
|
||||
<!-- <el-radio :label="false" border v-model="currentWorksType.isUploadPhoto">不上传</el-radio>-->
|
||||
<!-- </el-form-item>-->
|
||||
|
||||
<!-- <template v-if="currentWorksType.isUploadPhoto === true">-->
|
||||
<!-- <el-form-item label="上传图片数量">-->
|
||||
<!-- <el-input-number :max="5" :min="1" style="width: 100%" v-model="currentWorksType.photoNum"></el-input-number>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="上传图片格式">-->
|
||||
<!-- <el-checkbox-group v-model="currentWorksType.photoType">-->
|
||||
<!-- <el-checkbox border key="jpg" label="jpg">jpg</el-checkbox>-->
|
||||
<!-- <el-checkbox border key="png" label="png">png</el-checkbox>-->
|
||||
<!-- <el-checkbox border key="jpeg" label="jpeg">jpeg</el-checkbox>-->
|
||||
<!-- </el-checkbox-group>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="每张图片大小">-->
|
||||
<!-- <el-input placeholder="请填写每张图片大小" type="number" v-model="currentWorksType.photoSize">-->
|
||||
<!-- <template slot="append">Mb</template>-->
|
||||
<!-- </el-input>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- </template>-->
|
||||
|
||||
<!-- <div class="left-span-label">上传音/视频、文档设置</div>-->
|
||||
|
||||
<!-- <el-form-item label="是否上传音/视频、文档">-->
|
||||
<!-- <el-radio :label="true" border v-model="currentWorksType.isUploadOther">上传</el-radio>-->
|
||||
<!-- <el-radio :label="false" border v-model="currentWorksType.isUploadOther">不上传</el-radio>-->
|
||||
<!-- </el-form-item>-->
|
||||
|
||||
<!-- <template v-if="currentWorksType.isUploadOther === true">-->
|
||||
<!-- <el-form-item label="文件上传数量">-->
|
||||
<!-- <el-input-number :max="5" :min="1" style="width: 100%" v-model="currentWorksType.otherFileNum"></el-input-number>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="上传文件格式">-->
|
||||
<!-- <el-checkbox-group v-model="currentWorksType.otherType">-->
|
||||
<!-- <el-checkbox key="mp3" label="mp3">mp3</el-checkbox>-->
|
||||
<!-- <el-checkbox key="mp4" label="mp4">mp4</el-checkbox>-->
|
||||
<!-- <el-checkbox key="docx" label="docx">docx</el-checkbox>-->
|
||||
<!-- <el-checkbox key="xlsx" label="xlsx">xlsx</el-checkbox>-->
|
||||
<!-- <el-checkbox key="pdf" label="pdf">pdf</el-checkbox>-->
|
||||
<!-- </el-checkbox-group>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="每个文件大小">-->
|
||||
<!-- <el-input placeholder="请填写每个文件大小" type="number" v-model="currentWorksType.otherSize">-->
|
||||
<!-- <template slot="append">Mb</template>-->
|
||||
<!-- </el-input>-->
|
||||
<!-- </el-form-item>-->
|
||||
</template>
|
||||
</el-form>
|
||||
|
||||
<el-row class="mt20" justify="end" type="flex">
|
||||
<el-button @click="settingDialogVisible=false">取消</el-button>
|
||||
<el-button @click="settingDialogVisible = false" type="primary">确定</el-button>
|
||||
</el-row>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
@@ -406,31 +130,9 @@ layout("/layouts/platform.html"){
|
||||
activeTab: "activity",
|
||||
tableHeight: 300,
|
||||
tableResizeObserver: null,
|
||||
activityGroupList: [],
|
||||
dialogFormVisible: false,
|
||||
formRules: {
|
||||
name: [{required: true, message: "必填", trigger: ["change", "blur"]}],
|
||||
activityTime: [{required: true, message: "必填", trigger: ["change", "blur"]}],
|
||||
content: [{required: true, message: "必填", trigger: ["change", "blur"]}],
|
||||
subjectTypes: [{required: true, message: "必填", trigger: ["change", "blur"]}],
|
||||
enable: [{required: true, message: "必填", trigger: ["change", "blur"]}]
|
||||
},
|
||||
currentWorksType: {
|
||||
allowFileTypes: [],
|
||||
},
|
||||
settingDialogVisible: false,
|
||||
colorList: ["#081776", "#31cab1", "#e54242", "#ff8939", "#ffb712", "#1dc47b", "#4495f7", "#ff5e8b", "#5d6e7f"],
|
||||
pageForm: {
|
||||
activityTime: []
|
||||
},
|
||||
|
||||
formVisible: false,
|
||||
copyTemplateMode: false,
|
||||
copyTemplateName: "",
|
||||
formOptionsLoaded: false,
|
||||
formOptionsPromise: null,
|
||||
unitOptions: [],
|
||||
clubOptions: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -439,53 +141,13 @@ layout("/layouts/platform.html"){
|
||||
return this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])
|
||||
}
|
||||
},
|
||||
components: {
|
||||
"drawer-user-scope": httpVueLoader("/components/module/activity/DrawerUserScope.vue")
|
||||
},
|
||||
watch: {
|
||||
"formData.activityGroupId": {
|
||||
async handler(newVal, oldVal) {
|
||||
this.activityGroupList = await this.getActivityGroup()
|
||||
this.userScopeDialog = false
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isNewPage() {
|
||||
return window.location.pathname.toLowerCase() === "/platform/activity/workscollection/new"
|
||||
},
|
||||
backToManage() {
|
||||
commonUtil.pjaxPush("/platform/activity/worksCollection/manage")
|
||||
},
|
||||
afterSaveSuccess() {
|
||||
this.formVisible = false
|
||||
if (this.isNewPage()) {
|
||||
this.backToManage()
|
||||
} else {
|
||||
this.doSearch()
|
||||
this.$refs.guava.index()
|
||||
}
|
||||
},
|
||||
initNewPage() {
|
||||
const params = new URLSearchParams(window.location.search)
|
||||
const mode = params.get("mode")
|
||||
const id = params.get("id")
|
||||
if (mode === "edit" && id) {
|
||||
this.openEdit(id, true)
|
||||
} else {
|
||||
this.openAdd()
|
||||
}
|
||||
},
|
||||
getActivityGroup() {
|
||||
return this.$axios.post("/platform/activity/basic/scope/getActivityUserScopeGroup").then((res) => res.data)
|
||||
},
|
||||
dropdownCommand(command) {
|
||||
const {type, row} = command
|
||||
if (type === "sendNotice") {
|
||||
this.sendNotice(row.id)
|
||||
} else if (type === "edit") {
|
||||
this.openEdit(row.id)
|
||||
commonUtil.pjaxPush("/platform/activity/worksCollection/new?mode=update&id=" + row.id)
|
||||
} else if (type === "setTemplate") {
|
||||
this.setTemplate(row)
|
||||
} else if (type === "cancelTemplate") {
|
||||
@@ -537,212 +199,8 @@ layout("/layouts/platform.html"){
|
||||
})
|
||||
})
|
||||
},
|
||||
async loadFormOptions() {
|
||||
if (this.formOptionsLoaded) {
|
||||
return
|
||||
}
|
||||
if (this.formOptionsPromise) {
|
||||
return this.formOptionsPromise
|
||||
}
|
||||
this.formOptionsPromise = Promise.all([
|
||||
this.getActivityGroup(),
|
||||
this.getClubsByRole(),
|
||||
this.$businessTool.listUnit()
|
||||
]).then(([activityGroupList, clubOptions, units]) => {
|
||||
this.activityGroupList = activityGroupList
|
||||
this.clubOptions = clubOptions
|
||||
this.clubOptions.map((v) => {
|
||||
v.name = v.clubName
|
||||
})
|
||||
this.unitOptions = this.clubOptions.concat(units)
|
||||
this.formOptionsLoaded = true
|
||||
}).finally(() => {
|
||||
this.formOptionsPromise = null
|
||||
})
|
||||
return this.formOptionsPromise
|
||||
},
|
||||
addType(index) {
|
||||
let item = {}
|
||||
this.initData(item)
|
||||
this.formData.subjectTypes.splice(index + 1, 0, {worksTypes: [item]})
|
||||
},
|
||||
openSetting(worksType) {
|
||||
this.currentWorksType = worksType
|
||||
this.settingDialogVisible = true
|
||||
},
|
||||
addWorksType(type, worksIndex) {
|
||||
let item = {}
|
||||
this.initData(item)
|
||||
type.worksTypes.splice(worksIndex + 1, 0, item)
|
||||
},
|
||||
initData(worksType) {
|
||||
this.$set(worksType, "maxWordCount", worksType.maxWordCount ? worksType.maxWordCount : 100)
|
||||
this.$set(worksType, "isUploadPhoto", worksType.isUploadPhoto ? worksType.isUploadPhoto : false)
|
||||
this.$set(worksType, "photoType", worksType.photoType ? worksType.photoType : ["jpg"])
|
||||
this.$set(worksType, "photoNum", worksType.photoNum ? worksType.photoNum : 1)
|
||||
this.$set(worksType, "photoSize", worksType.photoSize ? worksType.photoSize : 2)
|
||||
|
||||
this.$set(worksType, "isUploadOther", worksType.isUploadOther ? worksType.isUploadOther : false)
|
||||
this.$set(worksType, "otherType", worksType.otherType ? worksType.otherType : ["mp4", "docx"])
|
||||
this.$set(worksType, "otherFileNum", worksType.otherFileNum ? worksType.otherFileNum : 1)
|
||||
this.$set(worksType, "otherSize", worksType.otherSize ? worksType.otherSize : 2)
|
||||
|
||||
this.$set(worksType, "allowFileTypes", worksType.allowFileTypes ? worksType.allowFileTypes : [])
|
||||
},
|
||||
async openAdd() {
|
||||
this.copyTemplateMode = false
|
||||
this.copyTemplateName = ""
|
||||
await this.loadFormOptions()
|
||||
this.formVisible = true
|
||||
this.$refs.guava.edit()
|
||||
this.$nextTick(() => {
|
||||
this.formData = {
|
||||
nbCount: 0,
|
||||
activityColor: this.colorList[0],
|
||||
subjectTypes: [{worksTypes: [{}]}],
|
||||
enable: true
|
||||
}
|
||||
this.initData(this.formData.subjectTypes[0].worksTypes[0])
|
||||
})
|
||||
},
|
||||
cleanCopyTemplateData(data) {
|
||||
if (!data) {
|
||||
return
|
||||
}
|
||||
data.id = null
|
||||
data.isTemplate = false
|
||||
data.templateStatus = 0
|
||||
data.createdBy = null
|
||||
data.createdAt = null
|
||||
data.updatedBy = null
|
||||
data.updatedAt = null
|
||||
data.delFlag = null
|
||||
if (Array.isArray(data.subjectTypes)) {
|
||||
data.subjectTypes = data.subjectTypes.map((subjectType) => {
|
||||
subjectType.id = null
|
||||
subjectType.activityId = null
|
||||
subjectType.createdBy = null
|
||||
subjectType.createdAt = null
|
||||
subjectType.updatedBy = null
|
||||
subjectType.updatedAt = null
|
||||
subjectType.delFlag = null
|
||||
if (Array.isArray(subjectType.worksTypes)) {
|
||||
subjectType.worksTypes = subjectType.worksTypes.map((worksType) => {
|
||||
worksType.id = null
|
||||
worksType.subjectId = null
|
||||
worksType.createdBy = null
|
||||
worksType.createdAt = null
|
||||
worksType.updatedBy = null
|
||||
worksType.updatedAt = null
|
||||
worksType.delFlag = null
|
||||
return worksType
|
||||
})
|
||||
}
|
||||
return subjectType
|
||||
})
|
||||
}
|
||||
},
|
||||
validateCopyTemplateName() {
|
||||
if (!this.copyTemplateMode) {
|
||||
return true
|
||||
}
|
||||
const currentName = (this.formData.name || "").trim()
|
||||
const templateName = (this.copyTemplateName || "").trim()
|
||||
if (currentName && templateName && currentName === templateName) {
|
||||
this.$message.warning("请修改活动名称,不能与模板名称一致")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
buildSubmitData() {
|
||||
const data = clone(this.formData)
|
||||
data.startDateTime = data.activityTime[0]
|
||||
data.endDateTime = data.activityTime[1]
|
||||
data.nbStartDateTime = data.nbTime ? data.nbTime[0] : null
|
||||
data.nbEndDateTime = data.nbTime ? data.nbTime[1] : null
|
||||
data.type = "1"
|
||||
if (this.copyTemplateMode) {
|
||||
this.cleanCopyTemplateData(data)
|
||||
}
|
||||
return data
|
||||
},
|
||||
async openEdit(id, copyTemplateMode = false) {
|
||||
this.copyTemplateMode = !!copyTemplateMode
|
||||
const [resp] = await Promise.all([
|
||||
this.$axios.post("/platform/activity/worksCollection/manage/findOne", {id}),
|
||||
this.loadFormOptions()
|
||||
])
|
||||
this.formVisible = true
|
||||
this.formData = resp.data
|
||||
if (this.copyTemplateMode) {
|
||||
this.copyTemplateName = this.formData.name
|
||||
this.cleanCopyTemplateData(this.formData)
|
||||
} else {
|
||||
this.copyTemplateName = ""
|
||||
}
|
||||
this.$set(this.formData, "activityTime", [this.formData.startDateTime, this.formData.endDateTime])
|
||||
// this.formData.activityTime = [this.formData.startDateTime, this.formData.endDateTime]
|
||||
if (this.formData.nbStartDateTime && this.formData.nbEndDateTime) {
|
||||
// this.formData.nbTime = [this.formData.nbStartDateTime, this.formData.nbEndDateTime]
|
||||
this.$set(this.formData, "nbTime", [this.formData.nbStartDateTime, this.formData.nbEndDateTime])
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.$refs.guava.edit()
|
||||
})
|
||||
},
|
||||
close() {
|
||||
this.formVisible = false
|
||||
if (this.isNewPage()) {
|
||||
this.backToManage()
|
||||
} else {
|
||||
this.$refs.guava.index()
|
||||
}
|
||||
},
|
||||
doSubmit() {
|
||||
this.$refs.formRef.validate((valid) => {
|
||||
if (valid) {
|
||||
if (!this.validateCopyTemplateName()) {
|
||||
return
|
||||
}
|
||||
const submitData = this.buildSubmitData()
|
||||
let loading = this.$loading({
|
||||
lock: true,
|
||||
text: "数据正在提交中,请稍后...",
|
||||
spinner: "el-icon-loading",
|
||||
background: "rgba(0, 0, 0, 0.7)"
|
||||
})
|
||||
this.$axios.post("/platform/activity/worksCollection/manage" + (this.copyTemplateMode || !this.formData.id ? "/insert" : "/update"), {data: JSON.stringify(submitData)}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success(res.msg)
|
||||
this.afterSaveSuccess()
|
||||
} else {
|
||||
this.$message.warning(res.msg)
|
||||
}
|
||||
loading.close()
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
doSave() {
|
||||
if (!this.validateCopyTemplateName()) {
|
||||
return
|
||||
}
|
||||
const submitData = this.buildSubmitData()
|
||||
let loading = this.$loading({
|
||||
lock: true,
|
||||
text: "数据正在保存中,请稍后...",
|
||||
spinner: "el-icon-loading",
|
||||
background: "rgba(0, 0, 0, 0.7)"
|
||||
})
|
||||
this.$axios.post("/platform/activity/worksCollection/manage" + (this.copyTemplateMode || !this.formData.id ? "/save" : "/update"), {data: JSON.stringify(submitData)}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success(res.msg)
|
||||
this.afterSaveSuccess()
|
||||
} else {
|
||||
this.$message.warning(res.msg)
|
||||
}
|
||||
loading.close()
|
||||
})
|
||||
openAdd() {
|
||||
commonUtil.pjaxPush("/platform/activity/worksCollection/new")
|
||||
},
|
||||
doDelete(id) {
|
||||
const row = this.tableData.find((item) => item.id === id)
|
||||
@@ -819,29 +277,15 @@ layout("/layouts/platform.html"){
|
||||
})
|
||||
})
|
||||
},
|
||||
getClubsByRole() {
|
||||
return this.$axios.post("/platform/club/examine/apply/getClubsByRole").then((resp) => resp.data)
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
if (!this.isNewPage() && this.canManageTemplate) {
|
||||
created() {
|
||||
if (this.canManageTemplate) {
|
||||
// 有模板管理角色时默认进入活动列表,只展示未设置模板的活动。
|
||||
this.$set(this.pageForm, "templateStatus", 0)
|
||||
}
|
||||
if (this.isNewPage()) {
|
||||
await this.loadFormOptions()
|
||||
this.$nextTick(() => {
|
||||
this.initNewPage()
|
||||
})
|
||||
} else {
|
||||
this.pageData()
|
||||
this.loadFormOptions()
|
||||
}
|
||||
this.pageData()
|
||||
},
|
||||
mounted() {
|
||||
if (this.isNewPage()) {
|
||||
return
|
||||
}
|
||||
const listCardBody = this.$el.querySelector(".works-collection-list-card > .el-card__body")
|
||||
if (listCardBody && window.ResizeObserver) {
|
||||
// 查询区换行、页签权限或窗口变化时同步调整表格内部滚动区域。
|
||||
|
||||
@@ -0,0 +1,467 @@
|
||||
const worksCollectionBasicForm = {
|
||||
template: /*language=HTML*/ `
|
||||
<div>
|
||||
<custom-card shadow="never">
|
||||
<div slot="header">{{pageTitle}}</div>
|
||||
|
||||
<el-form :model="formData" ref="formRef" label-width="130px" :rules="formRules">
|
||||
<el-form-item label="活动主题" prop="name">
|
||||
<el-input placeholder="请输入活动主题" v-model="formData.name" clearable></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="活动时间" prop="activityTime">
|
||||
<el-date-picker
|
||||
:default-time="['00:00:00']"
|
||||
end-placeholder="结束时间"
|
||||
start-placeholder="开始时间"
|
||||
style="width: 100%"
|
||||
type="datetimerange"
|
||||
v-model="formData.activityTime"
|
||||
value-format="yyyy-MM-dd HH:mm:ss">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="点赞时间" prop="nbTime">
|
||||
<el-date-picker
|
||||
:default-time="['00:00:00']"
|
||||
end-placeholder="结束时间"
|
||||
start-placeholder="开始时间"
|
||||
style="width: 100%"
|
||||
type="datetimerange"
|
||||
v-model="formData.nbTime"
|
||||
value-format="yyyy-MM-dd HH:mm:ss">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="每人每日点赞次数" prop="nbCount">
|
||||
<el-input-number
|
||||
:min="0"
|
||||
placeholder="请输入每人每日点赞次数"
|
||||
style="width: 100%"
|
||||
v-model="formData.nbCount">
|
||||
</el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="主题类型" prop="subjectTypes">
|
||||
<el-row class="pb5" v-for="(type,index) in formData.subjectTypes" :key="type.id || index">
|
||||
<el-col :span="20">
|
||||
<el-input placeholder="请输入名称" v-model="type.typeName"></el-input>
|
||||
</el-col>
|
||||
<el-col :span="2" style="text-align: center">
|
||||
<el-button @click="addType(index)" icon="el-icon-plus" type="primary"></el-button>
|
||||
</el-col>
|
||||
<el-col :span="2" style="text-align: center">
|
||||
<el-button
|
||||
:disabled="index === 0"
|
||||
@click="removeType(index)"
|
||||
icon="el-icon-delete"
|
||||
type="danger">
|
||||
</el-button>
|
||||
</el-col>
|
||||
<el-col class="pt5 pb5">
|
||||
<el-row class="pb5" v-for="(worksType,worksIndex) in type.worksTypes"
|
||||
:key="worksType.id || worksIndex">
|
||||
<el-col :span="18">
|
||||
<el-col :span="2">
|
||||
<span class="el-form-item__label" v-if="worksIndex === 0">作品类型</span>
|
||||
<span v-else> </span>
|
||||
</el-col>
|
||||
<el-col :span="22">
|
||||
<el-input placeholder="请输入名称" v-model="worksType.worksTypeName"></el-input>
|
||||
</el-col>
|
||||
</el-col>
|
||||
<el-col :span="2" style="text-align: center">
|
||||
<el-button @click="openSetting(worksType)" icon="el-icon-s-tools"
|
||||
type="primary"></el-button>
|
||||
</el-col>
|
||||
<el-col :span="2" style="text-align: center">
|
||||
<el-button @click="addWorksType(type, worksIndex)" icon="el-icon-plus"
|
||||
type="primary"></el-button>
|
||||
</el-col>
|
||||
<el-col :span="2" style="text-align: center">
|
||||
<el-button :disabled="type.worksTypes.length === 1"
|
||||
@click="removeWorksType(type, worksIndex)" icon="el-icon-delete"
|
||||
type="danger"></el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="面向对象" prop="joinCnd">
|
||||
<div style="display: flex; justify-content: space-between">
|
||||
<div style="width: 99%">
|
||||
<el-select clearable filterable placeholder="请选择参加人员范围" style="width: 99%"
|
||||
v-model="formData.activityGroupId">
|
||||
<el-option
|
||||
:label="item.groupName"
|
||||
:value="item.groupId"
|
||||
v-for="item in activityGroupList"
|
||||
:key="item.groupId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<div>
|
||||
<el-button @click="$refs.drawerUserScope.userScopeDialog = true" type="primary">设置</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="hostUnitIds" label="主办单位">
|
||||
<el-select v-model="formData.hostUnitIds" clearable filterable multiple
|
||||
placeholder="请选择主办单位" style="width: 100%">
|
||||
<el-option v-for="item in unitOptions" :key="item.id"
|
||||
:label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="undertakeUnitIds" label="承办单位">
|
||||
<el-select v-model="formData.undertakeUnitIds" clearable filterable multiple
|
||||
placeholder="请选择承办单位" style="width: 100%">
|
||||
<el-option v-for="item in unitOptions" :key="item.id"
|
||||
:label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="活动内容" prop="content">
|
||||
<text-editor v-model="formData.content"></text-editor>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动封面">
|
||||
<file-upload
|
||||
:upload_number="1"
|
||||
:value.sync="formData.cover"
|
||||
accept=".jpg,.jpeg,.png"
|
||||
complete_result
|
||||
upload_mode="image"
|
||||
upload_result_category="interval">
|
||||
</file-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label="配色" prop="activityColor">
|
||||
<el-color-picker v-model="formData.activityColor" show-alpha></el-color-picker>
|
||||
</el-form-item>
|
||||
<el-form-item prop="enable" label="状态">
|
||||
<el-radio-group v-model="formData.enable" size="small">
|
||||
<el-radio :label="true" border>开启</el-radio>
|
||||
<el-radio :label="false" border>关闭</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template slot="footer">
|
||||
<el-button :disabled="formLoading" @click="backToManage">取消</el-button>
|
||||
<el-button :loading="formLoading" type="primary"
|
||||
v-if="copyTemplateMode || formData.isSubmit !== true"
|
||||
plain @click="doSave">{{copyTemplateMode ? "另存为" : "保存"}}</el-button>
|
||||
<el-button :loading="formLoading" type="primary" @click="doSubmit">
|
||||
{{copyTemplateMode ? "新活动提交" : "确定"}}
|
||||
</el-button>
|
||||
</template>
|
||||
</custom-card>
|
||||
|
||||
<drawer-user-scope :group_id.sync="formData.activityGroupId" @group_change="refreshActivityGroup"
|
||||
ref="drawerUserScope"></drawer-user-scope>
|
||||
|
||||
<el-dialog :close-on-click-modal="false" :visible.sync="settingDialogVisible"
|
||||
title="更多设置" top="4%" width="40%">
|
||||
<el-form :model="currentWorksType" label-width="160px" size="small">
|
||||
<el-form-item label="作品介绍最多字数">
|
||||
<el-input-number :max="10000" :min="1" style="width: 100%"
|
||||
v-model="currentWorksType.maxWordCount"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="允许上传的文件类型" prop="allowFileTypes">
|
||||
<el-checkbox-group v-model="currentWorksType.allowFileTypes">
|
||||
<el-checkbox key="jpg" label="jpg">jpg</el-checkbox>
|
||||
<el-checkbox key="jpeg" label="jpeg">jpeg</el-checkbox>
|
||||
<el-checkbox key="png" label="png">png</el-checkbox>
|
||||
<el-checkbox key="mp3" label="mp3">mp3</el-checkbox>
|
||||
<el-checkbox key="mp4" label="mp4">mp4</el-checkbox>
|
||||
<el-checkbox key="docx" label="docx">docx</el-checkbox>
|
||||
<el-checkbox key="xlsx" label="xlsx">xlsx</el-checkbox>
|
||||
<el-checkbox key="pdf" label="pdf">pdf</el-checkbox>
|
||||
<el-checkbox key="zip" label="zip">zip</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="允许上传的文件数量" prop="allowFileNum">
|
||||
<el-input-number :max="10000" :min="1" style="width: 100%"
|
||||
v-model="currentWorksType.allowFileNum"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="单个文件大小(kb)" prop="allowSingleFileSize">
|
||||
<el-input-number :min="1" style="width: 100%"
|
||||
v-model="currentWorksType.allowSingleFileSize"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="总文件大小(kb)" prop="allowTotalFileSize">
|
||||
<el-input-number :min="1" style="width: 100%"
|
||||
v-model="currentWorksType.allowTotalFileSize"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="settingDialogVisible = false">取消</el-button>
|
||||
<el-button @click="settingDialogVisible = false" type="primary">确定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
`,
|
||||
components: {
|
||||
"drawer-user-scope": httpVueLoader("/components/module/activity/DrawerUserScope.vue")
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
formData: {
|
||||
nbCount: 0,
|
||||
activityColor: "#081776",
|
||||
subjectTypes: [],
|
||||
hostUnitIds: [],
|
||||
undertakeUnitIds: [],
|
||||
enable: true
|
||||
},
|
||||
formLoading: false,
|
||||
copyTemplateMode: false,
|
||||
copyTemplateName: "",
|
||||
activityGroupList: [],
|
||||
unitOptions: [],
|
||||
currentWorksType: {allowFileTypes: []},
|
||||
settingDialogVisible: false,
|
||||
colorList: ["#081776", "#31cab1", "#e54242", "#ff8939", "#ffb712", "#1dc47b", "#4495f7", "#ff5e8b", "#5d6e7f"],
|
||||
formRules: {
|
||||
name: [{required: true, message: "必填", trigger: ["change", "blur"]}],
|
||||
activityTime: [{required: true, message: "必填", trigger: ["change", "blur"]}],
|
||||
content: [{required: true, message: "必填", trigger: ["change", "blur"]}],
|
||||
subjectTypes: [{required: true, message: "必填", trigger: ["change", "blur"]}],
|
||||
enable: [{required: true, message: "必填", trigger: ["change", "blur"]}]
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
pageTitle() {
|
||||
if (this.copyTemplateMode) {
|
||||
return "从模板创建作品征集活动"
|
||||
}
|
||||
return this.formData.id ? "编辑作品征集活动" : "新建作品征集活动"
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 初始化独立活动表单。
|
||||
* URL 参数:无 id 时创建空白活动;mode=update&id=活动ID 时编辑原活动;
|
||||
* mode=edit&id=模板活动ID 时复制模板。完成后无返回值,通过组件事件通知页面返回。
|
||||
*/
|
||||
initData() {
|
||||
Promise.all([this.loadFormOptions(), this.initForm()]).catch(() => {
|
||||
this.$message.error("活动表单初始化失败,请稍后重试")
|
||||
})
|
||||
},
|
||||
// 创建新增页面的默认表单数据,并初始化第一组主题和作品类型。
|
||||
createEmptyFormData() {
|
||||
const worksType = {}
|
||||
this.initWorksType(worksType)
|
||||
return {
|
||||
nbCount: 0,
|
||||
activityColor: "#081776",
|
||||
subjectTypes: [{worksTypes: [worksType]}],
|
||||
hostUnitIds: [],
|
||||
undertakeUnitIds: [],
|
||||
enable: true
|
||||
}
|
||||
},
|
||||
initWorksType(worksType) {
|
||||
this.$set(worksType, "maxWordCount", worksType.maxWordCount || 100)
|
||||
this.$set(worksType, "isUploadPhoto", worksType.isUploadPhoto || false)
|
||||
this.$set(worksType, "photoType", worksType.photoType || ["jpg"])
|
||||
this.$set(worksType, "photoNum", worksType.photoNum || 1)
|
||||
this.$set(worksType, "photoSize", worksType.photoSize || 2)
|
||||
this.$set(worksType, "isUploadOther", worksType.isUploadOther || false)
|
||||
this.$set(worksType, "otherType", worksType.otherType || ["mp4", "docx"])
|
||||
this.$set(worksType, "otherFileNum", worksType.otherFileNum || 1)
|
||||
this.$set(worksType, "otherSize", worksType.otherSize || 2)
|
||||
this.$set(worksType, "allowFileTypes", worksType.allowFileTypes || [])
|
||||
},
|
||||
addType(index) {
|
||||
const worksType = {}
|
||||
this.initWorksType(worksType)
|
||||
this.formData.subjectTypes.splice(index + 1, 0, {worksTypes: [worksType]})
|
||||
},
|
||||
removeType(index) {
|
||||
this.formData.subjectTypes.splice(index, 1)
|
||||
},
|
||||
addWorksType(type, worksIndex) {
|
||||
const worksType = {}
|
||||
this.initWorksType(worksType)
|
||||
type.worksTypes.splice(worksIndex + 1, 0, worksType)
|
||||
},
|
||||
removeWorksType(type, worksIndex) {
|
||||
type.worksTypes.splice(worksIndex, 1)
|
||||
},
|
||||
openSetting(worksType) {
|
||||
this.initWorksType(worksType)
|
||||
this.currentWorksType = worksType
|
||||
this.settingDialogVisible = true
|
||||
},
|
||||
getActivityGroup() {
|
||||
return this.$axios.post("/platform/activity/basic/scope/getActivityUserScopeGroup")
|
||||
.then((res) => res.data || [])
|
||||
},
|
||||
getClubsByRole() {
|
||||
return this.$axios.post("/platform/club/examine/apply/getClubsByRole")
|
||||
.then((res) => res.data || [])
|
||||
},
|
||||
loadFormOptions() {
|
||||
return Promise.all([
|
||||
this.getActivityGroup(),
|
||||
this.getClubsByRole(),
|
||||
this.$businessTool.listUnit()
|
||||
]).then(([activityGroupList, clubOptions, units]) => {
|
||||
this.activityGroupList = activityGroupList
|
||||
clubOptions.forEach((item) => {
|
||||
this.$set(item, "name", item.clubName)
|
||||
})
|
||||
this.unitOptions = clubOptions.concat(units || [])
|
||||
})
|
||||
},
|
||||
refreshActivityGroup() {
|
||||
this.getActivityGroup().then((activityGroupList) => {
|
||||
this.activityGroupList = activityGroupList
|
||||
})
|
||||
},
|
||||
// 模板仅作为新活动的数据来源,清理主表和子表标识以防止更新模板原记录。
|
||||
cleanCopyTemplateData(data) {
|
||||
data.id = null
|
||||
data.isTemplate = false
|
||||
data.templateStatus = 0
|
||||
data.createdBy = null
|
||||
data.createdAt = null
|
||||
data.updatedBy = null
|
||||
data.updatedAt = null
|
||||
data.delFlag = null
|
||||
;(data.subjectTypes || []).forEach((subjectType) => {
|
||||
subjectType.id = null
|
||||
subjectType.activityId = null
|
||||
subjectType.createdBy = null
|
||||
subjectType.createdAt = null
|
||||
subjectType.updatedBy = null
|
||||
subjectType.updatedAt = null
|
||||
subjectType.delFlag = null
|
||||
;(subjectType.worksTypes || []).forEach((worksType) => {
|
||||
worksType.id = null
|
||||
worksType.subjectId = null
|
||||
worksType.createdBy = null
|
||||
worksType.createdAt = null
|
||||
worksType.updatedBy = null
|
||||
worksType.updatedAt = null
|
||||
worksType.delFlag = null
|
||||
})
|
||||
})
|
||||
},
|
||||
initForm() {
|
||||
const mode = GetQueryString("mode")
|
||||
const id = GetQueryString("id")
|
||||
this.copyTemplateMode = mode === "edit" && !!id
|
||||
if (!id) {
|
||||
this.formData = this.createEmptyFormData()
|
||||
return Promise.resolve()
|
||||
}
|
||||
return this.$axios.post("/platform/activity/worksCollection/manage/findOne", {id})
|
||||
.then((res) => {
|
||||
if (res.code !== 0 || !res.data) {
|
||||
return
|
||||
}
|
||||
const data = res.data
|
||||
if (this.copyTemplateMode) {
|
||||
this.copyTemplateName = data.name
|
||||
this.cleanCopyTemplateData(data)
|
||||
}
|
||||
this.$set(data, "activityTime", [data.startDateTime, data.endDateTime])
|
||||
this.$set(data, "nbTime", data.nbStartDateTime && data.nbEndDateTime
|
||||
? [data.nbStartDateTime, data.nbEndDateTime] : [])
|
||||
this.$set(data, "hostUnitIds", data.hostUnitIds || [])
|
||||
this.$set(data, "undertakeUnitIds", data.undertakeUnitIds || [])
|
||||
if (!data.subjectTypes || !data.subjectTypes.length) {
|
||||
const worksType = {}
|
||||
this.initWorksType(worksType)
|
||||
this.$set(data, "subjectTypes", [{worksTypes: [worksType]}])
|
||||
}
|
||||
;(data.subjectTypes || []).forEach((subjectType) => {
|
||||
this.$set(subjectType, "worksTypes", subjectType.worksTypes || [])
|
||||
if (!subjectType.worksTypes.length) {
|
||||
const worksType = {}
|
||||
this.initWorksType(worksType)
|
||||
subjectType.worksTypes.push(worksType)
|
||||
}
|
||||
subjectType.worksTypes.forEach((worksType) => this.initWorksType(worksType))
|
||||
})
|
||||
this.formData = data
|
||||
})
|
||||
},
|
||||
validateCopyTemplateName() {
|
||||
if (!this.copyTemplateMode) {
|
||||
return true
|
||||
}
|
||||
const currentName = (this.formData.name || "").trim()
|
||||
const templateName = (this.copyTemplateName || "").trim()
|
||||
if (currentName && templateName && currentName === templateName) {
|
||||
this.$message.warning("请修改活动名称,不能与模板名称一致")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
buildSubmitData() {
|
||||
const data = clone(this.formData)
|
||||
data.startDateTime = data.activityTime && data.activityTime.length ? data.activityTime[0] : null
|
||||
data.endDateTime = data.activityTime && data.activityTime.length ? data.activityTime[1] : null
|
||||
data.nbStartDateTime = data.nbTime && data.nbTime.length ? data.nbTime[0] : null
|
||||
data.nbEndDateTime = data.nbTime && data.nbTime.length ? data.nbTime[1] : null
|
||||
data.type = "1"
|
||||
if (this.copyTemplateMode) {
|
||||
this.cleanCopyTemplateData(data)
|
||||
}
|
||||
return data
|
||||
},
|
||||
submitRequest(path) {
|
||||
if (!this.validateCopyTemplateName()) {
|
||||
return
|
||||
}
|
||||
this.formLoading = true
|
||||
this.$axios.post("/platform/activity/worksCollection/manage" + path, {
|
||||
data: JSON.stringify(this.buildSubmitData())
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success(res.msg)
|
||||
this.backToManage()
|
||||
} else {
|
||||
this.$message.warning(res.msg)
|
||||
}
|
||||
}).finally(() => {
|
||||
this.formLoading = false
|
||||
})
|
||||
},
|
||||
doSave() {
|
||||
const path = this.copyTemplateMode || !this.formData.id ? "/save" : "/update"
|
||||
this.submitRequest(path)
|
||||
},
|
||||
doSubmit() {
|
||||
this.$refs.formRef.validate((valid) => {
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
const path = this.copyTemplateMode || !this.formData.id ? "/insert" : "/update"
|
||||
this.submitRequest(path)
|
||||
})
|
||||
},
|
||||
backToManage() {
|
||||
this.$emit("back")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<works-collection-basic-form ref="formRef" @back="back"></works-collection-basic-form>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
<!--#include("basicForm.js"){}#-->
|
||||
new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
components: {
|
||||
"works-collection-basic-form": worksCollectionBasicForm
|
||||
},
|
||||
methods: {
|
||||
back() {
|
||||
commonUtil.pjaxPush("/platform/activity/worksCollection/manage")
|
||||
},
|
||||
initForm() {
|
||||
this.$refs.formRef.initData()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
this.initForm()
|
||||
})
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -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>
|
||||
.works-mine-page {
|
||||
min-height: 100vh;
|
||||
padding-bottom: calc(24px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.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>
|
||||
<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>
|
||||
<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 is-primary" @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"></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)
|
||||
},
|
||||
@@ -78,30 +542,89 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$refs.applyFormRef.onOpenEdit(row)
|
||||
},
|
||||
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>
|
||||
|
||||
@@ -2,63 +2,189 @@ const INFO = {
|
||||
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 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>
|
||||
</van-popup>
|
||||
</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.$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
|
||||
},
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,66 +1,495 @@
|
||||
<!--#
|
||||
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-tag {
|
||||
display: inline-flex;
|
||||
min-height: 24px;
|
||||
padding: 3px 9px;
|
||||
align-items: center;
|
||||
flex: none;
|
||||
border: 0;
|
||||
border-radius: 12px;
|
||||
color: #397de0;
|
||||
background-color: #edf5ff;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.works-read-like-tag .van-icon {
|
||||
margin-right: 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.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-tag">
|
||||
<van-icon name="good-job-o"></van-icon>{{row.num || 0}}
|
||||
</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 +498,9 @@ layout("/layouts/platform_h5.html"){
|
||||
new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
components: {
|
||||
'info': INFO,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageForm: {
|
||||
@@ -77,79 +509,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>
|
||||
|
||||
@@ -3,189 +3,539 @@ const applyForm = {
|
||||
/*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 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: {},
|
||||
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, "row", row)
|
||||
this.$set(this.formData, "activityId", row.id)
|
||||
this.activityChange(row.id).then(() => {
|
||||
window.h5HistoryLayerManager.open("works-collection-apply")
|
||||
})
|
||||
},
|
||||
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, "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")
|
||||
})
|
||||
},
|
||||
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(",")
|
||||
// 附件可能由列表 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("提交成功")
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
|
||||
@@ -4,12 +4,12 @@ layout("/layouts/platform_h5.html"){
|
||||
|
||||
<style>
|
||||
body {
|
||||
background: #f5f6fa;
|
||||
background: #f3f7fd;
|
||||
}
|
||||
|
||||
#app {
|
||||
min-height: 100vh;
|
||||
background: #f5f6fa;
|
||||
background: #f3f7fd;
|
||||
}
|
||||
|
||||
.custom-nav {
|
||||
@@ -394,17 +394,22 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
|
||||
</style>
|
||||
<div id="app" v-cloak>
|
||||
<van-nav-bar title="报销申请" left-text="返回" left-arrow @click-left="historyBack" placeholder fixed z-index="999"
|
||||
<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="onNavBack" placeholder fixed z-index="999"
|
||||
class="custom-nav"></van-nav-bar>
|
||||
|
||||
<div class="form-container">
|
||||
<van-form ref="formRef">
|
||||
<van-cell-group title="信息填报" class="form-section">
|
||||
<section class="form-section">
|
||||
<h2 class="form-section__title">基本信息</h2>
|
||||
<van-cell-group :border="false">
|
||||
<van-field label="工号" v-model="formData.loginName" placeholder="从信息中心获取" readonly></van-field>
|
||||
<van-field label="经办人" v-model="formData.userName" placeholder="从信息中心获取" readonly></van-field>
|
||||
<!-- 联系方式 -->
|
||||
<van-field label="联系方式" v-model="formData.mobile" required placeholder="请输入联系方式"
|
||||
<!-- 经办人联系方式,使用当前登录用户的 mobile 初始化。 -->
|
||||
<van-field label="联系方式" name="mobile" v-model="formData.mobile" required placeholder="请输入联系方式"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入联系方式' },
|
||||
{ pattern: /^(1[3-9]\d{9}|0\d{2,3}-?\d{7,8})$/, message: '请输入正确的联系方式' }
|
||||
@@ -422,7 +427,7 @@ layout("/layouts/platform_h5.html"){
|
||||
required
|
||||
is-link
|
||||
></van-field>
|
||||
<van-popup position="bottom" round v-model:show="showReimburseFundSourcePicker">
|
||||
<van-popup position="bottom" round :close-on-click-overlay="true" v-model:show="showReimburseFundSourcePicker">
|
||||
<van-picker :columns="reimburseFundSourceColumns" @cancel="closePopup('showReimburseFundSourcePicker')"
|
||||
@confirm="onReimburseFundSourceConfirm" show-toolbar></van-picker>
|
||||
</van-popup>
|
||||
@@ -444,7 +449,7 @@ layout("/layouts/platform_h5.html"){
|
||||
<span style="color: #ee0a24; text-align: left;">报销提示:{{getProjectTipByProject(formData.reimburseProject)}}</span>
|
||||
</template>
|
||||
</van-cell>
|
||||
<van-popup position="bottom" round v-model:show="showReimburseProjectPicker">
|
||||
<van-popup position="bottom" round :close-on-click-overlay="true" v-model:show="showReimburseProjectPicker">
|
||||
<van-picker :columns="reimburseProjectColumns" @cancel="closePopup('showReimburseProjectPicker')"
|
||||
@confirm="onReimburseProjectConfirm" show-toolbar></van-picker>
|
||||
</van-popup>
|
||||
@@ -461,7 +466,7 @@ layout("/layouts/platform_h5.html"){
|
||||
required
|
||||
is-link
|
||||
></van-field>
|
||||
<van-popup position="bottom" round v-model:show="showClubPicker">
|
||||
<van-popup position="bottom" round :close-on-click-overlay="true" v-model:show="showClubPicker">
|
||||
<van-picker :columns="clubColumns" @cancel="closePopup('showClubPicker')"
|
||||
@confirm="onClubConfirm" show-toolbar></van-picker>
|
||||
</van-popup>
|
||||
@@ -532,8 +537,11 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-action-sheet>
|
||||
-->
|
||||
|
||||
</van-cell-group>
|
||||
<van-cell-group :title="formData.reimburseProject === 'UNION_REIMBURSE_PROJECT_1' ? '慰问信息' : '活动信息'" class="form-section">
|
||||
</van-cell-group>
|
||||
</section>
|
||||
<section class="form-section">
|
||||
<h2 class="form-section__title">{{!formData.reimburseProject ? '报销信息' : (formData.reimburseProject === 'UNION_REIMBURSE_PROJECT_1' ? '慰问信息' : '活动信息')}}</h2>
|
||||
<van-cell-group :border="false">
|
||||
|
||||
<template v-if="formData.reimburseProject === 'UNION_REIMBURSE_PROJECT_1'">
|
||||
<van-field
|
||||
@@ -548,7 +556,7 @@ layout("/layouts/platform_h5.html"){
|
||||
required
|
||||
is-link
|
||||
></van-field>
|
||||
<van-action-sheet v-model="showCondolenceSearch" title="慰问对象" class="height100">
|
||||
<van-action-sheet v-model="showCondolenceSearch" :close-on-click-overlay="true" title="慰问对象" class="height100">
|
||||
<van-search
|
||||
v-model="condolenceSearchKeyword"
|
||||
:show-action="false"
|
||||
@@ -587,7 +595,7 @@ layout("/layouts/platform_h5.html"){
|
||||
required
|
||||
is-link
|
||||
></van-field>
|
||||
<van-popup position="bottom" round v-model:show="showCondolenceTypePicker">
|
||||
<van-popup position="bottom" round :close-on-click-overlay="true" v-model:show="showCondolenceTypePicker">
|
||||
<van-picker :columns="condolenceTypeColumns" @cancel="closePopup('showCondolenceTypePicker')"
|
||||
@confirm="onCondolenceTypeConfirm" show-toolbar></van-picker>
|
||||
</van-popup>
|
||||
@@ -604,7 +612,7 @@ layout("/layouts/platform_h5.html"){
|
||||
required
|
||||
is-link
|
||||
></van-field>
|
||||
<van-popup position="bottom" round v-model:show="showCondolenceWayPicker">
|
||||
<van-popup position="bottom" round :close-on-click-overlay="true" v-model:show="showCondolenceWayPicker">
|
||||
<van-picker :columns="condolenceWayColumns" @cancel="closePopup('showCondolenceWayPicker')"
|
||||
@confirm="onCondolenceWayConfirm" show-toolbar></van-picker>
|
||||
</van-popup>
|
||||
@@ -627,7 +635,7 @@ layout("/layouts/platform_h5.html"){
|
||||
required
|
||||
is-link
|
||||
></van-field>
|
||||
<van-popup position="bottom" round v-model:show="showCondolenceTimePicker">
|
||||
<van-popup position="bottom" round :close-on-click-overlay="true" v-model:show="showCondolenceTimePicker">
|
||||
<van-datetime-picker type="date" title="选择慰问时间" :min-date="minDate" :max-date="maxDate"
|
||||
@cancel="closePopup('showCondolenceTimePicker')"
|
||||
@confirm="onCondolenceTimeConfirm"></van-datetime-picker>
|
||||
@@ -644,7 +652,7 @@ layout("/layouts/platform_h5.html"){
|
||||
clickable
|
||||
is-link
|
||||
></van-field>
|
||||
<van-popup position="bottom" round v-model:show="showMarryTimePicker">
|
||||
<van-popup position="bottom" round :close-on-click-overlay="true" v-model:show="showMarryTimePicker">
|
||||
<van-datetime-picker type="date" title="选择结婚时间" :min-date="minDate" :max-date="maxDate"
|
||||
@cancel="closePopup('showMarryTimePicker')"
|
||||
@confirm="onDateConfirm('marryTime', 'showMarryTimePicker', $event)"></van-datetime-picker>
|
||||
@@ -661,7 +669,7 @@ layout("/layouts/platform_h5.html"){
|
||||
clickable
|
||||
is-link
|
||||
></van-field>
|
||||
<van-popup position="bottom" round v-model:show="showFertilityTimePicker">
|
||||
<van-popup position="bottom" round :close-on-click-overlay="true" v-model:show="showFertilityTimePicker">
|
||||
<van-datetime-picker type="date" title="选择生育时间" :min-date="minDate" :max-date="maxDate"
|
||||
@cancel="closePopup('showFertilityTimePicker')"
|
||||
@confirm="onDateConfirm('fertilityTime', 'showFertilityTimePicker', $event)"></van-datetime-picker>
|
||||
@@ -681,7 +689,7 @@ layout("/layouts/platform_h5.html"){
|
||||
clickable
|
||||
is-link
|
||||
></van-field>
|
||||
<van-popup position="bottom" round v-model:show="showHospitalizationStartTimePicker">
|
||||
<van-popup position="bottom" round :close-on-click-overlay="true" v-model:show="showHospitalizationStartTimePicker">
|
||||
<van-datetime-picker type="date" title="选择住院开始时间" :min-date="minDate" :max-date="maxDate"
|
||||
@cancel="closePopup('showHospitalizationStartTimePicker')"
|
||||
@confirm="onDateConfirm('hospitalizationStartTime', 'showHospitalizationStartTimePicker', $event)"></van-datetime-picker>
|
||||
@@ -696,7 +704,7 @@ layout("/layouts/platform_h5.html"){
|
||||
clickable
|
||||
is-link
|
||||
></van-field>
|
||||
<van-popup position="bottom" round v-model:show="showHospitalizationEndTimePicker">
|
||||
<van-popup position="bottom" round :close-on-click-overlay="true" v-model:show="showHospitalizationEndTimePicker">
|
||||
<van-datetime-picker type="date" title="选择住院结束时间" :min-date="minDate" :max-date="maxDate"
|
||||
@cancel="closePopup('showHospitalizationEndTimePicker')"
|
||||
@confirm="onDateConfirm('hospitalizationEndTime', 'showHospitalizationEndTimePicker', $event)"></van-datetime-picker>
|
||||
@@ -716,7 +724,7 @@ layout("/layouts/platform_h5.html"){
|
||||
clickable
|
||||
is-link
|
||||
></van-field>
|
||||
<van-popup position="bottom" round v-model:show="showDeathTimePicker">
|
||||
<van-popup position="bottom" round :close-on-click-overlay="true" v-model:show="showDeathTimePicker">
|
||||
<van-datetime-picker type="date" title="选择去世时间" :min-date="minDate" :max-date="maxDate"
|
||||
@cancel="closePopup('showDeathTimePicker')"
|
||||
@confirm="onDateConfirm('deathTime', 'showDeathTimePicker', $event)"></van-datetime-picker>
|
||||
@@ -731,13 +739,13 @@ layout("/layouts/platform_h5.html"){
|
||||
clickable
|
||||
is-link
|
||||
></van-field>
|
||||
<van-popup position="bottom" round v-model:show="showRelationshipPicker">
|
||||
<van-popup position="bottom" round :close-on-click-overlay="true" v-model:show="showRelationshipPicker">
|
||||
<van-picker :columns="relationshipColumns" @cancel="closePopup('showRelationshipPicker')"
|
||||
@confirm="onRelationshipConfirm" show-toolbar></van-picker>
|
||||
</van-popup>
|
||||
</template>
|
||||
|
||||
<van-field label="参加随行人员"
|
||||
<van-field class="more-text" label="参加随行人员"
|
||||
v-model="formData.participants"
|
||||
placeholder="请填写参加随行人员"
|
||||
type="textarea"
|
||||
@@ -745,13 +753,13 @@ layout("/layouts/platform_h5.html"){
|
||||
autosize
|
||||
:rules="[{ required: true, message: '请填写参加随行人员' }]"
|
||||
required></van-field>
|
||||
<van-field label="报销事由"
|
||||
<van-field class="more-text" label="报销事由"
|
||||
v-model="formData.paymentNotes"
|
||||
placeholder="请填写报销事由"
|
||||
type="textarea"
|
||||
rows="2"
|
||||
autosize></van-field>
|
||||
<van-field label="备注"
|
||||
<van-field class="more-text" label="备注"
|
||||
v-model="formData.notes"
|
||||
placeholder="需要填写:发票编号、开具方、金额"
|
||||
type="textarea"
|
||||
@@ -790,7 +798,7 @@ layout("/layouts/platform_h5.html"){
|
||||
required
|
||||
is-link
|
||||
></van-field>
|
||||
<van-popup position="bottom" round v-model:show="showActivityTimePicker">
|
||||
<van-popup position="bottom" round :close-on-click-overlay="true" v-model:show="showActivityTimePicker">
|
||||
<van-datetime-picker type="date" title="选择活动时间" :min-date="minDate" :max-date="maxDate"
|
||||
@cancel="closePopup('showActivityTimePicker')"
|
||||
@confirm="onActivityTimeConfirm"></van-datetime-picker>
|
||||
@@ -811,7 +819,8 @@ layout("/layouts/platform_h5.html"){
|
||||
></h5-file-upload>
|
||||
</template>
|
||||
</van-field>
|
||||
</van-cell-group>
|
||||
</van-cell-group>
|
||||
</section>
|
||||
<van-cell-group class="form-section">
|
||||
<div class="payment-section">
|
||||
<div class="payment-toolbar">
|
||||
@@ -900,11 +909,11 @@ layout("/layouts/platform_h5.html"){
|
||||
<span class="payment-dot" :class="{active: index === currentPaymentIndex}" v-for="(item, index) in paymentInfoRows"></span>
|
||||
</div>
|
||||
</div>
|
||||
<van-popup position="bottom" round v-model:show="showPaymentWayPicker">
|
||||
<van-popup position="bottom" round :close-on-click-overlay="true" v-model:show="showPaymentWayPicker">
|
||||
<van-picker :columns="paymentWayColumns" @cancel="closePopup('showPaymentWayPicker')"
|
||||
@confirm="onPaymentWayConfirm" show-toolbar></van-picker>
|
||||
</van-popup>
|
||||
<van-action-sheet v-model="payerSelectShow" title="付款人" class="height100">
|
||||
<van-action-sheet v-model="payerSelectShow" :close-on-click-overlay="true" title="付款人" class="height100">
|
||||
<van-search
|
||||
v-model="payerSearchKeyword"
|
||||
:show-action="false"
|
||||
@@ -926,7 +935,8 @@ layout("/layouts/platform_h5.html"){
|
||||
<van-empty description="暂无数据" v-else></van-empty>
|
||||
</van-action-sheet>
|
||||
</van-cell-group>
|
||||
<van-cell-group title="电子发票" class="form-section" v-if="formData.reimburseProject">
|
||||
<van-cell-group class="form-section" v-if="formData.reimburseProject">
|
||||
<div class="form-section__title">电子发票</div>
|
||||
<van-field label="报销金额"
|
||||
v-model="formData.money"
|
||||
placeholder="自动汇总发票金额"
|
||||
@@ -936,7 +946,7 @@ layout("/layouts/platform_h5.html"){
|
||||
placeholder="自动统计发票数量"
|
||||
readonly></van-field>
|
||||
<!-- 支付内容 -->
|
||||
<van-field label="支付内容"
|
||||
<van-field class="more-text" label="支付内容"
|
||||
v-model="formData.paymentNotes"
|
||||
placeholder="请填写支付内容"
|
||||
type="textarea"
|
||||
@@ -952,6 +962,8 @@ layout("/layouts/platform_h5.html"){
|
||||
<template #right-icon>
|
||||
<van-switch v-model="formData.invoiceVerifyEnabled"
|
||||
size="22px"
|
||||
active-color="#1989fa"
|
||||
inactive-color="#d8e0ea"
|
||||
@change="handleVerifySwitchChange"></van-switch>
|
||||
</template>
|
||||
</van-cell>
|
||||
@@ -966,9 +978,9 @@ layout("/layouts/platform_h5.html"){
|
||||
<div class="invoice-detail-line">项目名称:{{item.itemName || '未填写'}}</div>
|
||||
<div class="invoice-detail-line" v-if="getInvoiceFile(item)">文件:{{getInvoiceFile(item).name || getInvoiceFile(item).filename || '已上传'}}</div>
|
||||
<div class="invoice-detail-actions">
|
||||
<van-button native-type="button" size="mini" plain type="info" @click="previewInvoiceFile(item)">预览</van-button>
|
||||
<van-button native-type="button" size="mini" plain type="primary" @click="openInvoiceDialog('edit', item, index)">编辑</van-button>
|
||||
<van-button native-type="button" size="mini" plain type="danger" @click="removeInvoiceDetail(index)">删除</van-button>
|
||||
<van-button native-type="button" size="mini" plain type="info" icon="eye-o" @click="previewInvoiceFile(item)">预览</van-button>
|
||||
<van-button native-type="button" size="mini" plain type="primary" icon="edit" @click="openInvoiceDialog('edit', item, index)">编辑</van-button>
|
||||
<van-button native-type="button" size="mini" plain type="danger" icon="delete-o" @click="removeInvoiceDetail(index)">删除</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -985,22 +997,22 @@ layout("/layouts/platform_h5.html"){
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<div class="form-actions">
|
||||
<van-button plain @click="onSave" type="info">保存</van-button>
|
||||
<van-button @click="onSubmit" type="primary" v-if="!taskId">提交</van-button>
|
||||
<van-button @click="onSubmitAgain" type="primary" v-else>提交</van-button>
|
||||
<van-button plain @click="onSave" type="info">保存申请</van-button>
|
||||
<van-button @click="onSubmit" type="primary" v-if="!taskId">提交申请</van-button>
|
||||
<van-button @click="onSubmitAgain" type="primary" v-else>提交申请</van-button>
|
||||
</div>
|
||||
</van-form>
|
||||
</div>
|
||||
<van-popup v-model:show="invoiceDialogVisible" position="bottom" round class="invoice-popup">
|
||||
<van-popup v-model:show="invoiceDialogVisible" position="bottom" round :close-on-click-overlay="true" class="invoice-popup">
|
||||
<van-nav-bar :title="invoiceDialogMode === 'edit' ? '编辑发票明细' : '新增发票明细'"
|
||||
left-text="取消"
|
||||
left-arrow
|
||||
@click-left="invoiceDialogVisible = false"></van-nav-bar>
|
||||
@click-left="closePopup('invoiceDialogVisible')"></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>
|
||||
</div>
|
||||
<van-cell-group>
|
||||
<van-cell-group class="invoice-popup-card">
|
||||
<van-field class="more-text" label="发票文件" required>
|
||||
<template #input>
|
||||
<h5-file-upload
|
||||
@@ -1040,13 +1052,15 @@ layout("/layouts/platform_h5.html"){
|
||||
rows="2"
|
||||
autosize></van-field>
|
||||
</van-cell-group>
|
||||
<div class="invoice-tip" style="padding: 8px 16px;">上传发票文件后会自动识别发票信息;开启自动校验时会同步校验发票是否重复。</div>
|
||||
<div class="invoice-tip invoice-popup-tip">上传发票文件后会自动识别发票信息;开启自动校验时会同步校验发票是否重复。</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 type="info" @click="closePopup('invoiceDialogVisible')">取消</van-button>
|
||||
<van-button native-type="button" block type="primary" @click="saveInvoiceDetail">保存</van-button>
|
||||
</div>
|
||||
</van-popup>
|
||||
<van-dialog :value="submitConfirmVisible" title="温馨提示" message="您确定要提交吗?审核通过后可前往 PC 端我的报销打印。" show-cancel-button :confirm-button-loading="formLoading" @confirm="submitConfirmed" @cancel="closeSubmitConfirm"></van-dialog>
|
||||
<van-dialog :value="removeInvoiceConfirmVisible" title="提示" message="确定删除这条发票明细吗?" show-cancel-button @confirm="confirmRemoveInvoiceDetail" @cancel="closeRemoveInvoiceConfirm"></van-dialog>
|
||||
</div>
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
@@ -1127,6 +1141,20 @@ layout("/layouts/platform_h5.html"){
|
||||
files: []
|
||||
},
|
||||
invoiceDialogVisible: false,
|
||||
submitConfirmVisible: false,
|
||||
removeInvoiceConfirmVisible: false,
|
||||
formLoading: false,
|
||||
pendingSubmitAction: "",
|
||||
pendingPaymentDetails: [],
|
||||
pendingInvoiceRemoveIndex: -1,
|
||||
historyLayerUnsubscribe: null,
|
||||
popupKeys: [
|
||||
"showReimburseFundSourcePicker", "showReimburseProjectPicker", "showClubPicker", "showCondolenceSearch",
|
||||
"showCondolenceTypePicker", "showCondolenceWayPicker", "showCondolenceTimePicker", "showMarryTimePicker",
|
||||
"showFertilityTimePicker", "showHospitalizationStartTimePicker", "showHospitalizationEndTimePicker",
|
||||
"showDeathTimePicker", "showRelationshipPicker", "showActivityTimePicker", "showPaymentWayPicker",
|
||||
"payerSelectShow", "invoiceDialogVisible"
|
||||
],
|
||||
invoiceDialogMode: "add",
|
||||
detailFormIndex: -1,
|
||||
lastRecognizedFileId: "",
|
||||
@@ -1239,7 +1267,7 @@ layout("/layouts/platform_h5.html"){
|
||||
const file = newVal && newVal.length ? newVal[0] : null
|
||||
const currentFileId = this.getInvoiceFileId(file)
|
||||
if (!currentFileId) {
|
||||
this.lastRecognizedFileId = ""
|
||||
this.$set(this, "lastRecognizedFileId", "")
|
||||
return
|
||||
}
|
||||
if (currentFileId === this.lastRecognizedFileId) {
|
||||
@@ -1298,6 +1326,49 @@ layout("/layouts/platform_h5.html"){
|
||||
closePopup(key) {
|
||||
this.$set(this, key, false)
|
||||
},
|
||||
// 所有选择器与发票弹窗共用全局历史栈,遮罩关闭和浏览器返回键都只关闭当前弹层。
|
||||
syncPopupHistory(key, visible) {
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (!manager) return
|
||||
const layerName = "union-reimburse-apply-" + key
|
||||
if (visible) { manager.open(layerName); return }
|
||||
manager.close(layerName)
|
||||
},
|
||||
onNavBack() {
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (manager && manager.stack.length) { manager.close(); return }
|
||||
historyBack()
|
||||
},
|
||||
openSubmitConfirm(action, paymentDetails) {
|
||||
this.$set(this, "pendingSubmitAction", action)
|
||||
this.$set(this, "pendingPaymentDetails", paymentDetails)
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (manager) { manager.open("union-reimburse-apply-submit-confirm"); return }
|
||||
this.$set(this, "submitConfirmVisible", true)
|
||||
},
|
||||
closeSubmitConfirm(afterClose) {
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (manager) { manager.close("union-reimburse-apply-submit-confirm", afterClose); return }
|
||||
this.$set(this, "submitConfirmVisible", false)
|
||||
if (afterClose) afterClose()
|
||||
},
|
||||
openRemoveInvoiceConfirm(index) {
|
||||
this.$set(this, "pendingInvoiceRemoveIndex", index)
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (manager) { manager.open("union-reimburse-apply-remove-invoice-confirm"); return }
|
||||
this.$set(this, "removeInvoiceConfirmVisible", true)
|
||||
},
|
||||
closeRemoveInvoiceConfirm(afterClose) {
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (manager) { manager.close("union-reimburse-apply-remove-invoice-confirm", afterClose); return }
|
||||
this.$set(this, "removeInvoiceConfirmVisible", false)
|
||||
if (afterClose) afterClose()
|
||||
},
|
||||
navigateToMine() {
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (manager && manager.closeAllAndNavigate("/platform/unionReimburse/mine/h5")) return
|
||||
this.$pjaxReplace("/platform/unionReimburse/mine/h5")
|
||||
},
|
||||
openDatePicker(key) {
|
||||
this.openPopup(key)
|
||||
},
|
||||
@@ -1740,10 +1811,11 @@ layout("/layouts/platform_h5.html"){
|
||||
})
|
||||
},
|
||||
removeInvoiceDetail(index) {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "确定删除这条发票明细吗?"
|
||||
}).then(() => {
|
||||
this.openRemoveInvoiceConfirm(index)
|
||||
},
|
||||
confirmRemoveInvoiceDetail() {
|
||||
const index = this.pendingInvoiceRemoveIndex
|
||||
this.closeRemoveInvoiceConfirm(() => {
|
||||
this.formData.invoiceDetails.splice(index, 1)
|
||||
this.rebuildInvoiceSummary()
|
||||
})
|
||||
@@ -1815,11 +1887,12 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$set(this, "searchKeyword", "")
|
||||
this.$set(this, "userOptions", [])
|
||||
},
|
||||
async userRemoteMethod(event) {
|
||||
userRemoteMethod(event) {
|
||||
if (event) {
|
||||
const userOptions = await this.selectQueryUser(event)
|
||||
this.$set(this, "userOptions", userOptions)
|
||||
this.$set(this, "certifierUserSelectShow", true)
|
||||
this.selectQueryUser(event).then((userOptions) => {
|
||||
this.$set(this, "userOptions", userOptions)
|
||||
this.$set(this, "certifierUserSelectShow", true)
|
||||
})
|
||||
}
|
||||
},
|
||||
selectQueryUser(keyword) {
|
||||
@@ -1991,29 +2064,29 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
})
|
||||
},
|
||||
async onSave() {
|
||||
onSave() {
|
||||
this.normalizeContactFields()
|
||||
this.normalizeCondolenceDateFields()
|
||||
this.rebuildInvoiceSummary()
|
||||
const paymentDetails = this.preparePaymentDetailsForSubmit()
|
||||
this.$set(this, "formLoading", true)
|
||||
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")
|
||||
this.navigateToMine()
|
||||
} 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, "保存失败"))
|
||||
}).finally(() => {
|
||||
this.$set(this, "formLoading", false)
|
||||
})
|
||||
},
|
||||
// 提交
|
||||
async onSubmit() {
|
||||
|
||||
onSubmit() {
|
||||
this.normalizeContactFields()
|
||||
this.normalizeCondolenceDateFields()
|
||||
this.rebuildInvoiceSummary()
|
||||
@@ -2029,30 +2102,11 @@ layout("/layouts/platform_h5.html"){
|
||||
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, "提交失败"))
|
||||
})
|
||||
})
|
||||
this.openSubmitConfirm("submit", paymentDetails)
|
||||
})
|
||||
},
|
||||
// 再次提交
|
||||
async onSubmitAgain() {
|
||||
|
||||
onSubmitAgain() {
|
||||
this.normalizeContactFields()
|
||||
this.normalizeCondolenceDateFields()
|
||||
this.rebuildInvoiceSummary()
|
||||
@@ -2068,27 +2122,24 @@ layout("/layouts/platform_h5.html"){
|
||||
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, "提交失败"))
|
||||
})
|
||||
this.openSubmitConfirm("submitAgain", paymentDetails)
|
||||
})
|
||||
},
|
||||
submitConfirmed() {
|
||||
const action = this.pendingSubmitAction
|
||||
const paymentDetails = this.pendingPaymentDetails
|
||||
this.closeSubmitConfirm(() => {
|
||||
this.$set(this, "formLoading", true)
|
||||
const api = action === "submitAgain" ? "/platform/unionReimburse/apply/submitAgain" : "/platform/unionReimburse/apply/submit"
|
||||
const params = {data: JSON.stringify(this.buildSubmitFormData(paymentDetails))}
|
||||
if (action === "submitAgain") params.taskId = GetQueryString("taskId")
|
||||
this.$axios.post(api, params).then((res) => {
|
||||
this.$toast.clear()
|
||||
if (res.code === 0) { this.$toast.success("提交成功"); this.navigateToMine() } else { this.$toast.fail(res.msg || "提交失败") }
|
||||
}).catch((err) => {
|
||||
this.$toast.clear(); this.$toast.fail(this.getRequestErrorMessage(err, "提交失败"))
|
||||
}).finally(() => {
|
||||
this.$set(this, "formLoading", false)
|
||||
})
|
||||
})
|
||||
},
|
||||
@@ -2218,46 +2269,34 @@ 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")
|
||||
this.reimburseTypeColumns = reimburseTypeData.map(item => {
|
||||
return { value: item.code, text: item.name }
|
||||
initDictOptions() {
|
||||
return this.$businessTool.getDictOptions("UNION_REIMBURSE_TYPE").then((reimburseTypeData) => {
|
||||
this.$set(this, "reimburseTypeColumns", reimburseTypeData.map(item => ({value: item.code, text: item.name})))
|
||||
return this.$businessTool.getDictOptions("UNION_REIMBURSE_PAYMENT_WAY")
|
||||
}).then((paymentWayData) => {
|
||||
this.$set(this, "paymentWayColumns", paymentWayData.map(item => ({value: item.code, text: item.name})))
|
||||
return this.$businessTool.getDictOptions("UNION_REIMBURSE_PROJECT")
|
||||
}).then((reimburseProjectData) => {
|
||||
this.$set(this, "reimburseProjectColumns", reimburseProjectData.map(item => ({value: item.code, text: item.name})))
|
||||
this.$set(this, "reimburseProjectList", reimburseProjectData)
|
||||
return this.$businessTool.getDictOptions("UNION_REIMBURSE_FUND_SOURCE")
|
||||
}).then((reimburseFundSourceData) => {
|
||||
this.$set(this, "reimburseFundSourceColumns", reimburseFundSourceData.map(item => ({value: item.code, text: item.name})))
|
||||
this.filterReimburseFundSources()
|
||||
})
|
||||
|
||||
// 支付方式
|
||||
const paymentWayData = await this.$businessTool.getDictOptions("UNION_REIMBURSE_PAYMENT_WAY")
|
||||
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 // 保存原始数据
|
||||
|
||||
// 报销经费来源
|
||||
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()
|
||||
},
|
||||
|
||||
// 查询慰问对象
|
||||
queryCondolence(keyword) {
|
||||
this.$axios.post("/platform/UnionReimburse/apply/listUser", { keyword: keyword }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.condolenceOptions = res.data
|
||||
this.condolenceColumns = res.data.map(item => {
|
||||
this.$set(this, "condolenceOptions", res.data)
|
||||
this.$set(this, "condolenceColumns", res.data.map(item => {
|
||||
return {
|
||||
text: item.userName + "(" + item.loginName + ")" + "(" + item.unitName + ")" + "(" + item.sex + ")",
|
||||
value: item.id
|
||||
}
|
||||
})
|
||||
}))
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -2305,10 +2344,10 @@ layout("/layouts/platform_h5.html"){
|
||||
queryCondolenceType() {
|
||||
return this.$axios.post("/platform/unionReimburse/apply/queryCondolenceType")
|
||||
.then((resp) => {
|
||||
this.typeOptions = resp.data
|
||||
this.condolenceTypeColumns = resp.data.map(item => {
|
||||
this.$set(this, "typeOptions", resp.data)
|
||||
this.$set(this, "condolenceTypeColumns", resp.data.map(item => {
|
||||
return { text: item.name, value: item.id }
|
||||
})
|
||||
}))
|
||||
})
|
||||
},
|
||||
// 慰问时间确认事件
|
||||
@@ -2328,10 +2367,10 @@ layout("/layouts/platform_h5.html"){
|
||||
// 查询社团
|
||||
queryClubs() {
|
||||
return this.$businessTool.listClubByRole().then((res) => {
|
||||
this.clubOptions = res
|
||||
this.clubColumns = res.map(item => {
|
||||
this.$set(this, "clubOptions", res)
|
||||
this.$set(this, "clubColumns", res.map(item => {
|
||||
return { text: item.clubName, value: item.id }
|
||||
})
|
||||
}))
|
||||
if (res && res.length === 1 && this.formData.reimburseFundSource === "UNION_REIMBURSE_FUND_SOURCE_3" && !this.formData.clubId) {
|
||||
this.$set(this.formData, "clubId", res[0].id)
|
||||
this.$set(this.formData, "clubName", res[0].clubName)
|
||||
@@ -2404,7 +2443,7 @@ layout("/layouts/platform_h5.html"){
|
||||
})
|
||||
},
|
||||
// 添加经费来源区分
|
||||
async filterReimburseFundSources() {
|
||||
filterReimburseFundSources() {
|
||||
const filteredSources = []
|
||||
|
||||
// 原角色过滤逻辑保留如下,手机端现统一改为按权限控制,与 PC 端保持一致
|
||||
@@ -2459,16 +2498,16 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
|
||||
// 更新经费来源选项
|
||||
this.reimburseFundSourceColumns = filteredSources
|
||||
this.$set(this, "reimburseFundSourceColumns", filteredSources)
|
||||
},
|
||||
init() {
|
||||
this.bizId = GetQueryString("bizId")
|
||||
this.$set(this, "bizId", GetQueryString("bizId"))
|
||||
if (this.bizId) {
|
||||
this.$axios.post("/platform/unionReimburse/apply/info", { id: this.bizId }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
// 先保存原始数据
|
||||
const originalData = { ...res.data }
|
||||
this.formData = this.ensureFormData(res.data)
|
||||
this.$set(this, "formData", this.ensureFormData(res.data))
|
||||
this.normalizeLoadedFormData(originalData)
|
||||
|
||||
// 处理报销类别显示
|
||||
@@ -2560,7 +2599,7 @@ layout("/layouts/platform_h5.html"){
|
||||
const user = this.$store.state.user
|
||||
this.$set(this.formData, "userName", user.username)
|
||||
this.$set(this.formData, "loginName", user.loginname)
|
||||
this.$set(this.formData, "mobile", user.mobile)
|
||||
this.$set(this.formData, "mobile", user.mobile || "")
|
||||
this.$set(this.formData, "userId", user.id)
|
||||
this.$set(this.formData, "unitId", user.unitId)
|
||||
this.$set(this.formData, "unitName", user.unit.name)
|
||||
@@ -2579,12 +2618,27 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
},
|
||||
|
||||
async created() {
|
||||
await this.initDictOptions()
|
||||
await this.queryProjectDesc()
|
||||
await this.queryCondolenceType()
|
||||
await this.queryClubs()
|
||||
await this.init()
|
||||
created() {
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (manager) {
|
||||
manager.ensureRegistered("union-reimburse-apply")
|
||||
this.$set(this, "historyLayerUnsubscribe", manager.subscribe((layers) => {
|
||||
this.popupKeys.forEach((key) => {
|
||||
this.$set(this, key, layers.includes("union-reimburse-apply-" + key))
|
||||
})
|
||||
this.$set(this, "submitConfirmVisible", layers.includes("union-reimburse-apply-submit-confirm"))
|
||||
this.$set(this, "removeInvoiceConfirmVisible", layers.includes("union-reimburse-apply-remove-invoice-confirm"))
|
||||
}))
|
||||
}
|
||||
this.popupKeys.forEach((key) => {
|
||||
this.$watch(key, (visible) => { this.syncPopupHistory(key, visible) })
|
||||
})
|
||||
this.initDictOptions().then(() => this.queryProjectDesc()).then(() => this.queryCondolenceType()).then(() => this.queryClubs()).then(() => this.init())
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.historyLayerUnsubscribe) this.historyLayerUnsubscribe()
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (manager) manager.unregister("union-reimburse-apply")
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -0,0 +1,472 @@
|
||||
.union-reimburse-page {
|
||||
min-height: 100vh;
|
||||
padding-bottom: calc(24px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background: #f3f7fd;
|
||||
color: #40526a;
|
||||
}
|
||||
|
||||
.union-reimburse-page .van-nav-bar,
|
||||
.union-reimburse-page .van-sticky--fixed { background: #fff; }
|
||||
|
||||
.union-reimburse-page .van-nav-bar__title {
|
||||
color: #172033;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.union-reimburse-page .van-nav-bar .van-icon,
|
||||
.union-reimburse-page .van-nav-bar .van-nav-bar__text { color: #1989fa; }
|
||||
|
||||
.union-reimburse-sticky {
|
||||
padding: 22px 12px 1px;
|
||||
box-sizing: border-box;
|
||||
background: #f3f7fd;
|
||||
}
|
||||
|
||||
.union-reimburse-search {
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.union-reimburse-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.union-reimburse-search .van-field__control { color: #263548; font-size: 14px; }
|
||||
.union-reimburse-search .van-field__control::placeholder { color: #a7b0bf; }
|
||||
|
||||
.union-reimburse-filter {
|
||||
margin-bottom: 8px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
}
|
||||
|
||||
.union-reimburse-filter .van-dropdown-menu__bar { height: 44px; box-shadow: none; }
|
||||
.union-reimburse-filter .van-dropdown-menu__item,
|
||||
.union-reimburse-filter .van-dropdown-menu__title { height: 44px; }
|
||||
.union-reimburse-filter .van-dropdown-menu__item { align-items: center; justify-content: center; }
|
||||
.union-reimburse-filter .van-dropdown-menu__title {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: #66758a;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.union-reimburse-filter .van-dropdown-menu__title--active,
|
||||
.union-reimburse-filter .van-dropdown-item__option--active,
|
||||
.union-reimburse-filter .van-dropdown-item__option--active .van-dropdown-item__icon { color: #1989fa; }
|
||||
|
||||
.union-reimburse-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);
|
||||
}
|
||||
|
||||
.union-reimburse-filter .van-dropdown-item__option {
|
||||
display: flex;
|
||||
min-height: 48px;
|
||||
padding: 0 16px;
|
||||
align-items: center;
|
||||
color: #46566c;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.union-reimburse-list-content { padding: 0 12px; }
|
||||
.union-reimburse-page .table-list-container { margin-top: 0; padding-bottom: 2px; }
|
||||
.union-reimburse-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);
|
||||
}
|
||||
|
||||
.union-reimburse-card-header { display: flex; margin-bottom: 8px; align-items: flex-start; justify-content: space-between; }
|
||||
.union-reimburse-card-header__heading { min-width: 0; padding-right: 10px; flex: 1; }
|
||||
.union-reimburse-card-header__title {
|
||||
overflow: hidden;
|
||||
color: #253247;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.union-reimburse-card-header__sub { margin-top: 1px; color: #9ba6b6; font-size: 12px; line-height: 18px; }
|
||||
.union-reimburse-card-header__status { display: inline-flex; flex: none; }
|
||||
.union-reimburse-card-header__status.van-tag,
|
||||
.union-reimburse-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;
|
||||
}
|
||||
.union-reimburse-card-header__status--pending { color: #1989fa; background: #eaf4ff; }
|
||||
/* 报销成功与社团审核页 ProcessInstanceStateEnum 的“已完成”保持一致。 */
|
||||
.union-reimburse-card-header__status--success { color: #67c23a; background: #f0f9eb; }
|
||||
.union-reimburse-card-header__status--danger { color: #e35d5d; background: #fff0f0; }
|
||||
|
||||
.union-reimburse-page .table-list-container .table-list-item .item-actions {
|
||||
margin-top: 10px;
|
||||
padding-top: 10px;
|
||||
border-top-color: #edf1f6;
|
||||
}
|
||||
.union-reimburse-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;
|
||||
}
|
||||
.union-reimburse-page .table-list-container .table-list-item .action-btn.delete { color: #f04444; background: #fff0f0; }
|
||||
.union-reimburse-page .table-list-container .table-list-item .action-btn.review { color: #1989fa; background: #eaf4ff; }
|
||||
.union-reimburse-page .table-list-container .table-list-item .action-btn .van-icon { margin-right: 5px; font-size: 13px; }
|
||||
.union-reimburse-page .empty-state { padding: 0; }
|
||||
|
||||
.union-reimburse-list-skeleton { padding: 0; }
|
||||
.union-reimburse-skeleton-card {
|
||||
margin-bottom: 12px;
|
||||
padding: 14px;
|
||||
border: 1px solid #e9eff7;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
}
|
||||
.union-reimburse-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: union-reimburse-skeleton-loading 1.4s ease infinite;
|
||||
}
|
||||
.union-reimburse-skeleton-line--title { width: 46%; height: 16px; }
|
||||
.union-reimburse-skeleton-line--short { width: 60%; }
|
||||
|
||||
.union-reimburse-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;
|
||||
}
|
||||
.union-reimburse-empty img { display: block; width: 86%; max-width: 290px; height: auto; object-fit: contain; }
|
||||
.union-reimburse-empty__title { margin-top: 14px; color: #50627a; font-size: 15px; font-weight: 600; line-height: 22px; }
|
||||
.union-reimburse-empty__hint { margin-top: 5px; color: #9aa7b8; font-size: 12px; line-height: 18px; }
|
||||
|
||||
/* 申请页沿用社团申请的卡片层级,保留报销业务原有字段与交互。 */
|
||||
.union-reimburse-form { padding-bottom: 0; }
|
||||
.union-reimburse-form .custom-nav { box-shadow: none; }
|
||||
.union-reimburse-form .form-container { padding: 12px 15px calc(86px + env(safe-area-inset-bottom)); }
|
||||
.union-reimburse-form .form-section {
|
||||
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);
|
||||
}
|
||||
|
||||
.union-reimburse-form .form-section .van-cell-group__title,
|
||||
.union-reimburse-form .payment-toolbar,
|
||||
.union-reimburse-form .invoice-toolbar {
|
||||
position: relative;
|
||||
min-height: 42px;
|
||||
margin: 0;
|
||||
padding: 12px 14px 8px 21px;
|
||||
box-sizing: border-box;
|
||||
color: #354255;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.union-reimburse-form .form-section__title {
|
||||
position: relative;
|
||||
min-height: 41px;
|
||||
margin: 0;
|
||||
padding: 13px 15px 8px 24px;
|
||||
box-sizing: border-box;
|
||||
color: #1f2d3d;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 20px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.union-reimburse-form .form-section__title::before {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 15px;
|
||||
width: 3px;
|
||||
height: 14px;
|
||||
border-radius: 2px;
|
||||
background: #1989fa;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.union-reimburse-form .form-section .van-cell-group__title::before,
|
||||
.union-reimburse-form .payment-toolbar::before,
|
||||
.union-reimburse-form .invoice-toolbar::before {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
bottom: 11px;
|
||||
left: 12px;
|
||||
width: 2px;
|
||||
border-radius: 2px;
|
||||
background: #1989fa;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.union-reimburse-form .form-section .van-cell { min-height: 46px; padding: 11px 15px; background: transparent; }
|
||||
.union-reimburse-form .form-section .van-cell::after { right: 15px; left: 15px; border-color: #eef2f7; }
|
||||
.union-reimburse-form .form-section .van-field__label { width: 105px; color: #596779; font-size: 13px; line-height: 24px; }
|
||||
.union-reimburse-form .payment-detail-item .van-cell--required::before { left: 6px; color: #f06464; }
|
||||
.union-reimburse-form .form-section .van-field__control { color: #40526a; font-size: 14px; line-height: 24px; }
|
||||
.union-reimburse-form .form-section .van-field__control::placeholder { color: #a7b0bf; }
|
||||
.union-reimburse-form .more-text { display: block; }
|
||||
.union-reimburse-form .more-text .van-field__label { width: auto; margin-bottom: 7px; }
|
||||
.union-reimburse-form .more-text .van-field__control {
|
||||
min-height: 88px;
|
||||
padding: 10px 12px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #c9d5e5;
|
||||
border-radius: 10px;
|
||||
background: #f7f9fd;
|
||||
}
|
||||
|
||||
.union-reimburse-form .payment-section,
|
||||
.union-reimburse-form .invoice-section { padding: 0 0 14px; }
|
||||
.union-reimburse-form .payment-toolbar,
|
||||
.union-reimburse-form .invoice-toolbar { display: flex; align-items: center; justify-content: space-between; }
|
||||
.union-reimburse-form .payment-toolbar .van-button,
|
||||
.union-reimburse-form .invoice-toolbar .van-button {
|
||||
height: 28px;
|
||||
padding: 0 12px;
|
||||
border: 0;
|
||||
border-radius: 14px;
|
||||
color: #1989fa;
|
||||
background: #eaf4ff;
|
||||
}
|
||||
.union-reimburse-form .payment-detail-item,
|
||||
.union-reimburse-form .invoice-detail-item {
|
||||
margin: 8px 14px 0;
|
||||
overflow: hidden;
|
||||
border: 1px solid #e6ebf2;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
box-shadow: none;
|
||||
}
|
||||
.union-reimburse-form .invoice-detail-item { padding: 0; }
|
||||
.union-reimburse-form .invoice-detail-title {
|
||||
min-height: 38px;
|
||||
padding: 0 12px;
|
||||
box-sizing: border-box;
|
||||
color: #40526a;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
background: #f7f9fd;
|
||||
border-bottom: 1px solid #eef2f7;
|
||||
}
|
||||
.union-reimburse-form .invoice-detail-line {
|
||||
margin: 0;
|
||||
padding: 8px 12px 0;
|
||||
color: #718096;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
word-break: break-all;
|
||||
}
|
||||
.union-reimburse-form .invoice-detail-line:last-of-type { padding-bottom: 8px; }
|
||||
.union-reimburse-form .invoice-detail-actions,
|
||||
.union-reimburse-form .payment-detail-actions {
|
||||
min-height: 28px;
|
||||
margin-top: 8px;
|
||||
padding: 9px 12px;
|
||||
box-sizing: border-box;
|
||||
border-top: 1px solid #eef2f7;
|
||||
background: #fff;
|
||||
}
|
||||
.union-reimburse-form .invoice-detail-actions { justify-content: flex-end; gap: 6px; }
|
||||
.union-reimburse-form .invoice-detail-actions .van-button,
|
||||
.union-reimburse-form .payment-detail-actions .payment-delete-btn {
|
||||
height: 28px;
|
||||
min-width: 52px;
|
||||
padding: 0 10px;
|
||||
border: 0;
|
||||
border-radius: 14px;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
.union-reimburse-form .invoice-detail-actions .van-button--info,
|
||||
.union-reimburse-form .invoice-detail-actions .van-button--primary {
|
||||
color: #1989fa;
|
||||
background: #eaf4ff;
|
||||
}
|
||||
.union-reimburse-form .invoice-detail-actions .van-button--danger,
|
||||
.union-reimburse-form .payment-detail-actions .payment-delete-btn {
|
||||
color: #f04444;
|
||||
background: #fff0f0;
|
||||
}
|
||||
.union-reimburse-form .invoice-detail-actions .van-icon,
|
||||
.union-reimburse-form .payment-detail-actions .payment-delete-btn .van-icon {
|
||||
margin-right: 4px;
|
||||
font-size: 13px;
|
||||
}
|
||||
.union-reimburse-form .payment-detail-item .van-cell { padding-right: 12px; padding-left: 12px; }
|
||||
.union-reimburse-form .payment-detail-title {
|
||||
min-height: 38px;
|
||||
padding: 0 12px;
|
||||
color: #40526a;
|
||||
background: #f7f9fd;
|
||||
border-bottom-color: #eef2f7;
|
||||
}
|
||||
.union-reimburse-form .invoice-tip { margin: 8px 14px 10px; border-color: #dce9f8; color: #718096; background: #f5f9ff; }
|
||||
.union-reimburse-form .form-actions {
|
||||
gap: 10px;
|
||||
padding: 10px 15px calc(10px + env(safe-area-inset-bottom));
|
||||
box-shadow: 0 -2px 12px rgba(43, 73, 112, .09);
|
||||
}
|
||||
.union-reimburse-form .form-actions .van-button { height: 40px; border-radius: 8px; font-size: 14px; font-weight: 500; }
|
||||
.union-reimburse-form .form-actions .van-button--primary { border-color: #1989fa; background: #1989fa; box-shadow: none; }
|
||||
.union-reimburse-form .form-actions .van-button--info.van-button--plain { color: #1989fa; border-color: #1989fa; }
|
||||
|
||||
/* 新增、编辑发票弹框与申请页共用卡片、字段和操作按钮视觉规范。 */
|
||||
.union-reimburse-form .invoice-popup {
|
||||
overflow: hidden;
|
||||
background: #f3f7fd;
|
||||
}
|
||||
.union-reimburse-form .invoice-popup .van-nav-bar { flex: none; box-shadow: 0 1px 6px rgba(43, 73, 112, .08); }
|
||||
.union-reimburse-form .invoice-popup .van-nav-bar__title { color: #1f2d3d; font-size: 16px; font-weight: 600; }
|
||||
.union-reimburse-form .invoice-popup-body {
|
||||
padding: 12px 15px;
|
||||
box-sizing: border-box;
|
||||
background: #f3f7fd;
|
||||
}
|
||||
.union-reimburse-form .invoice-popup-card {
|
||||
overflow: hidden;
|
||||
border: 1px solid #e9eff7;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
box-shadow: 0 3px 11px rgba(51, 87, 126, .08);
|
||||
}
|
||||
.union-reimburse-form .invoice-popup-card .van-cell { min-height: 46px; padding: 11px 15px; background: transparent; }
|
||||
.union-reimburse-form .invoice-popup-card .van-cell::after { right: 15px; left: 15px; border-color: #eef2f7; }
|
||||
.union-reimburse-form .invoice-popup-card .van-field__label { width: 105px; color: #596779; font-size: 13px; line-height: 24px; }
|
||||
.union-reimburse-form .invoice-popup-card .van-field__control { color: #40526a; font-size: 14px; line-height: 24px; }
|
||||
.union-reimburse-form .invoice-popup-card .van-field__control::placeholder { color: #a7b0bf; }
|
||||
.union-reimburse-form .invoice-popup-card .more-text { display: block; }
|
||||
.union-reimburse-form .invoice-popup-card .more-text .van-field__label { width: auto; margin-bottom: 7px; }
|
||||
.union-reimburse-form .invoice-popup-card .more-text .van-field__control {
|
||||
min-height: 88px;
|
||||
padding: 10px 12px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #c9d5e5;
|
||||
border-radius: 10px;
|
||||
background: #f7f9fd;
|
||||
}
|
||||
.union-reimburse-form .invoice-popup-tip {
|
||||
margin: 10px 0 0;
|
||||
padding: 9px 11px;
|
||||
border-color: #dce9f8;
|
||||
color: #718096;
|
||||
background: #f5f9ff;
|
||||
}
|
||||
.union-reimburse-form .invoice-popup-actions {
|
||||
flex: none;
|
||||
gap: 10px;
|
||||
padding: 10px 15px calc(10px + env(safe-area-inset-bottom));
|
||||
box-shadow: 0 -2px 12px rgba(43, 73, 112, .09);
|
||||
}
|
||||
.union-reimburse-form .invoice-popup-actions .van-button { height: 40px; border-radius: 8px; font-size: 14px; font-weight: 500; }
|
||||
.union-reimburse-form .invoice-popup-actions .van-button--primary { border-color: #1989fa; background: #1989fa; box-shadow: none; }
|
||||
.union-reimburse-form .invoice-popup-actions .van-button--info.van-button--plain { color: #1989fa; border-color: #1989fa; background: #fff; }
|
||||
|
||||
/* 审核卡片与社团审核保持相同的标题、必填标记和按钮规格。 */
|
||||
.union-reimburse-approval { padding: 0; background: #f3f7fd; }
|
||||
.union-reimburse-approval-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);
|
||||
}
|
||||
.union-reimburse-approval-card__title {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
padding: 12px 14px 8px 21px;
|
||||
color: #354255;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
}
|
||||
.union-reimburse-approval-card__title::before {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
bottom: 11px;
|
||||
left: 12px;
|
||||
width: 2px;
|
||||
border-radius: 2px;
|
||||
background: #1989fa;
|
||||
content: '';
|
||||
}
|
||||
.union-reimburse-approval-field-label {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
padding: 10px 14px 6px;
|
||||
color: #596779;
|
||||
font-size: 12px;
|
||||
line-height: 24px;
|
||||
}
|
||||
.union-reimburse-approval-required { position: absolute; left: 6px; color: #ee0a24; font-size: 12px; }
|
||||
.union-reimburse-approval-card .van-field.union-reimburse-approval-field {
|
||||
width: calc(100% - 28px);
|
||||
margin: 0 14px 14px;
|
||||
padding: 12px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #c9d5e5;
|
||||
border-radius: 10px;
|
||||
background: #f7f9fd;
|
||||
}
|
||||
.union-reimburse-approval-card .van-field.union-reimburse-approval-field .van-field__control {
|
||||
min-height: 150px;
|
||||
color: #253247;
|
||||
font-size: 12px;
|
||||
line-height: 22px;
|
||||
}
|
||||
.union-reimburse-approval-card .van-field.union-reimburse-approval-field::after { display: none; }
|
||||
.union-reimburse-approval-actions {
|
||||
display: flex;
|
||||
column-gap: 10px;
|
||||
padding: 10px 12px calc(12px + env(safe-area-inset-bottom));
|
||||
}
|
||||
.union-reimburse-approval-actions .van-button { height: 40px; border-radius: 14px; font-size: 14px; }
|
||||
|
||||
@keyframes union-reimburse-skeleton-loading {
|
||||
0% { background-position: 100% 50%; }
|
||||
100% { background-position: 0 50%; }
|
||||
}
|
||||
@@ -2,14 +2,10 @@ 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">
|
||||
<van-popup v-model="visible" position="right" :style="{width: '100%', height: '100%'}" get-container="#app" :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>
|
||||
@@ -59,6 +55,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 +83,7 @@ const UNION_REIMBURSE_INFO = {
|
||||
<div class="union-info-value">{{ item.bankCardNumber }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</van-swipe-item>
|
||||
</van-swipe>
|
||||
</template>
|
||||
@@ -272,12 +271,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 +285,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,36 +301,44 @@ 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>
|
||||
</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: {
|
||||
@@ -339,8 +346,29 @@ const UNION_REIMBURSE_INFO = {
|
||||
return this.viewData.paymentDetails || []
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
visible(value) {
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (!manager) return
|
||||
if (value) {
|
||||
manager.open(this.historyLayerName)
|
||||
return
|
||||
}
|
||||
manager.close(this.historyLayerName)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.injectInfoStyle()
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (manager) {
|
||||
manager.ensureRegistered("union-reimburse-info")
|
||||
this.$set(this, "historyLayerUnsubscribe", manager.subscribe((layers) => {
|
||||
this.$set(this, "visible", layers.includes(this.historyLayerName))
|
||||
}))
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.historyLayerUnsubscribe) this.historyLayerUnsubscribe()
|
||||
},
|
||||
methods: {
|
||||
injectInfoStyle() {
|
||||
@@ -355,16 +383,19 @@ 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, "visible", true)
|
||||
this.$set(this, "currentPaymentIndex", 0)
|
||||
this.getInfo()
|
||||
this.getDoneTasks()
|
||||
},
|
||||
// 关闭
|
||||
// 由全局历史栈关闭详情,保证遮罩、关闭按钮和浏览器返回键遵循同一顺序。
|
||||
onClose() {
|
||||
this.visible = false
|
||||
const manager = window.h5HistoryLayerManager
|
||||
if (manager && manager.close(this.historyLayerName)) return
|
||||
this.$set(this, "visible", false)
|
||||
},
|
||||
formatCreateTime(value) {
|
||||
return value && this.$moment(value).isValid() ? this.$moment(value).format("YYYY-MM-DD HH:mm:ss") : ""
|
||||
@@ -386,6 +417,16 @@ const UNION_REIMBURSE_INFO = {
|
||||
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,131 @@ 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 {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
background: #f2f4f7;
|
||||
background: #f3f7fd;
|
||||
}
|
||||
|
||||
.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 +649,7 @@ const UNION_REIMBURSE_INFO = {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
padding: 12px 20px 4px;
|
||||
padding: 10px 14px 3px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
@@ -617,21 +669,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 +715,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 +738,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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -2,100 +2,64 @@
|
||||
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">
|
||||
<template v-if="showApprovalForm">
|
||||
<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="primary" @click="handleTaskAction(3)">同意申请</van-button>
|
||||
<van-button type="danger" @click="handleTaskAction(4)">拒绝申请</van-button>
|
||||
<van-button type="danger" @click="handleTaskAction(5)">退回到发起人</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>
|
||||
</section>
|
||||
<div 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>
|
||||
</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 +80,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 +143,63 @@ 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.$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>
|
||||
|
||||
@@ -253,11 +253,24 @@ const PROPOSAL_INFO = {
|
||||
this.$nextTick(() => {
|
||||
this.$set(this, "reloadPending", false)
|
||||
if (!this.visible || !this.currentBizId) return
|
||||
this.resetScrollPosition()
|
||||
this.getInfo()
|
||||
this.getDoneTasks()
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 重置提案详情的纵向滚动位置。
|
||||
* 无参数;查找组件所在的 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;返回名称字符串,无匹配项时返回原值或 --。
|
||||
|
||||
@@ -46,7 +46,7 @@ layout("/layouts/platform_h5.html"){
|
||||
.proposal-hero__title {
|
||||
margin: 0;
|
||||
color: var(--proposal-primary);
|
||||
font-size: 23px;
|
||||
font-size: 25px;
|
||||
line-height: 30px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 1px;
|
||||
@@ -55,7 +55,7 @@ layout("/layouts/platform_h5.html"){
|
||||
.proposal-hero__subtitle {
|
||||
margin-top: 2px;
|
||||
color: #718096;
|
||||
font-size: 11px;
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ layout("/layouts/platform_h5.html"){
|
||||
|
||||
.proposal-notice__title {
|
||||
color: #1989fa;
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
@@ -101,7 +101,7 @@ layout("/layouts/platform_h5.html"){
|
||||
.proposal-notice__text {
|
||||
margin-top: 2px;
|
||||
color: #8a97a8;
|
||||
font-size: 10px;
|
||||
font-size: 12px;
|
||||
line-height: 17px;
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ layout("/layouts/platform_h5.html"){
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: var(--proposal-primary);
|
||||
font-size: 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.proposal-card {
|
||||
@@ -132,7 +132,7 @@ layout("/layouts/platform_h5.html"){
|
||||
margin: 0;
|
||||
padding: 12px 14px 8px 21px;
|
||||
color: #354255;
|
||||
font-size: 13px;
|
||||
font-size: 15px;
|
||||
line-height: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
@@ -168,14 +168,14 @@ layout("/layouts/platform_h5.html"){
|
||||
.proposal-card .van-field__label {
|
||||
width: 84px;
|
||||
color: #596779;
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.proposal-card .van-field__value,
|
||||
.proposal-card .van-field__control {
|
||||
color: #4f5d70;
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ layout("/layouts/platform_h5.html"){
|
||||
.proposal-card .van-field__word-limit {
|
||||
margin-top: 2px;
|
||||
color: #b5bdc8;
|
||||
font-size: 9px;
|
||||
font-size: 11px;
|
||||
line-height: 14px;
|
||||
}
|
||||
|
||||
@@ -225,8 +225,8 @@ layout("/layouts/platform_h5.html"){
|
||||
.proposal-actions .van-button {
|
||||
height: 40px;
|
||||
margin: 0;
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
border-radius: 14px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.proposal-actions .van-button:first-child {
|
||||
@@ -239,14 +239,13 @@ layout("/layouts/platform_h5.html"){
|
||||
.proposal-actions .van-button:last-child {
|
||||
flex: 1.08;
|
||||
border-color: var(--proposal-primary);
|
||||
border-radius: 14px;
|
||||
background: var(--proposal-primary);
|
||||
}
|
||||
|
||||
.proposal-actions .van-icon {
|
||||
margin-right: 5px;
|
||||
font-size: 15px;
|
||||
vertical-align: -2px;
|
||||
#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;
|
||||
}
|
||||
|
||||
.suggestion-unit-picker {
|
||||
@@ -267,7 +266,7 @@ layout("/layouts/platform_h5.html"){
|
||||
.picker-cancel, .picker-confirm {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 16px;
|
||||
font-size: 18px;
|
||||
color: #1989fa;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -277,11 +276,21 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
|
||||
.picker-title {
|
||||
font-size: 16px;
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
color: #323233;
|
||||
}
|
||||
|
||||
.proposal-write-page .van-picker-column__item {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.proposal-write-page .van-picker__cancel,
|
||||
.proposal-write-page .van-picker__confirm,
|
||||
.proposal-write-page .van-search__field {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
padding: 12px 16px;
|
||||
background-color: #fff;
|
||||
@@ -303,7 +312,7 @@ layout("/layouts/platform_h5.html"){
|
||||
.option-text {
|
||||
margin-left: 12px;
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
font-size: 16px;
|
||||
color: #323233;
|
||||
}
|
||||
|
||||
@@ -324,6 +333,7 @@ layout("/layouts/platform_h5.html"){
|
||||
width: 100%;
|
||||
padding: 0 16px; /* 左右留白 */
|
||||
box-sizing: border-box;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.notice-dialog-content p {
|
||||
@@ -332,6 +342,16 @@ layout("/layouts/platform_h5.html"){
|
||||
text-indent: 2em; /* 中文首行缩进更规范 */
|
||||
}
|
||||
|
||||
#app .van-action-sheet__header,
|
||||
.van-dialog__header {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
#app .van-action-sheet__cancel,
|
||||
.van-dialog__message {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
@media (min-width: 600px) {
|
||||
.proposal-hero__content,
|
||||
.proposal-main {
|
||||
@@ -385,7 +405,7 @@ layout("/layouts/platform_h5.html"){
|
||||
<van-form ref="formRef">
|
||||
<!-- 基本信息:保留当前教代会、代表身份及联系方式等业务字段。 -->
|
||||
<section class="proposal-card">
|
||||
<h2 class="proposal-card__title">一、基本信息</h2>
|
||||
<h2 class="proposal-card__title">基本信息</h2>
|
||||
<van-cell-group :border="false">
|
||||
<van-field
|
||||
v-model="formData.createUserName"
|
||||
@@ -467,7 +487,7 @@ layout("/layouts/platform_h5.html"){
|
||||
|
||||
<!-- 提案内容:字段和校验继续以现有接口及实体定义为准。 -->
|
||||
<section class="proposal-card">
|
||||
<h2 class="proposal-card__title">二、提案内容</h2>
|
||||
<h2 class="proposal-card__title">提案内容</h2>
|
||||
<van-cell-group :border="false">
|
||||
<van-field
|
||||
v-model="formData.name"
|
||||
@@ -540,7 +560,7 @@ layout("/layouts/platform_h5.html"){
|
||||
|
||||
<!-- 附件材料仅使用卡片分组,上传控件保持项目原有样式和结果结构。 -->
|
||||
<section class="proposal-card">
|
||||
<h2 class="proposal-card__title">三、附件材料</h2>
|
||||
<h2 class="proposal-card__title">附件材料</h2>
|
||||
<van-cell-group :border="false">
|
||||
<van-field label="附件" name="files" class="direction-column-field">
|
||||
<h5-file-upload
|
||||
@@ -613,13 +633,13 @@ layout("/layouts/platform_h5.html"){
|
||||
<!-- 保存、首次提交和重新提交继续共用原业务入口。 -->
|
||||
<div class="proposal-actions" v-if="isWriteTime">
|
||||
<van-button plain type="info" :loading="formLoading && loadingAction === 'save'" :disabled="formLoading" @click="onSave">
|
||||
<van-icon name="records"></van-icon>保存草稿
|
||||
保存草稿
|
||||
</van-button>
|
||||
<van-button type="primary" :loading="formLoading && loadingAction === 'submit'" :disabled="formLoading" @click="onSubmit" v-if="!taskId">
|
||||
<van-icon name="guide-o"></van-icon>提交提案
|
||||
提交提案
|
||||
</van-button>
|
||||
<van-button type="primary" :loading="formLoading && loadingAction === 'submitAgain'" :disabled="formLoading" @click="onSubmitAgain" v-else>
|
||||
<van-icon name="guide-o"></van-icon>重新提交
|
||||
重新提交
|
||||
</van-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1005,7 +1005,7 @@ layout("/layouts/platform_h5.html"){
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
transform: scale(1.45);
|
||||
transform: scale(1.6);
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
@@ -1126,32 +1126,79 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
|
||||
.mobile-bottom-panel {
|
||||
padding: 11px 14px calc(11px + env(safe-area-inset-bottom));
|
||||
border-top: 1px solid #edf0f5;
|
||||
padding: 0 0 env(safe-area-inset-bottom);
|
||||
border-top: 0;
|
||||
background: #fff;
|
||||
box-shadow: 0 -5px 18px rgba(36, 55, 80, .08);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.mobile-bottom-panel.is-empty {
|
||||
padding-top: 12px;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.mobile-bottom-selected {
|
||||
display: grid;
|
||||
grid-template-columns: 105px minmax(0, 1fr);
|
||||
gap: 12px;
|
||||
grid-template-columns: 42px max-content 1px minmax(0, 1fr);
|
||||
gap: 9px;
|
||||
align-items: center;
|
||||
padding: 15px 9px;
|
||||
background: #fff;
|
||||
border: 1px solid #e8eef7;
|
||||
border-radius: 0;
|
||||
box-shadow: 0 5px 15px rgba(49, 93, 157, .12);
|
||||
}
|
||||
|
||||
.mobile-bottom-summary {
|
||||
display: block;
|
||||
min-height: auto;
|
||||
display: flex;
|
||||
height: 50px;
|
||||
margin: 0;
|
||||
padding: 5px 8px;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
color: #202b3c;
|
||||
font-size: 15px;
|
||||
background: #fff;
|
||||
border: 1px solid #e8eef7;
|
||||
border-radius: 23px;
|
||||
box-shadow: 0 4px 12px rgba(51, 103, 178, .1);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mobile-seat-status-icon {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.mobile-seat-status-copy {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.mobile-seat-status-value {
|
||||
color: #1677ff;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.mobile-seat-status-tag {
|
||||
margin-bottom: 1px;
|
||||
color: #7d899a;
|
||||
font-size: 10px;
|
||||
line-height: 14px;
|
||||
}
|
||||
|
||||
.mobile-seat-status-divider {
|
||||
width: 1px;
|
||||
height: 28px;
|
||||
background: #dfe5ed;
|
||||
}
|
||||
|
||||
.mobile-bottom-summary strong {
|
||||
margin: 0 4px;
|
||||
color: #1677ff;
|
||||
@@ -1160,12 +1207,13 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
|
||||
.mobile-confirm-button {
|
||||
height: 46px;
|
||||
height: 38px;
|
||||
border: 0;
|
||||
border-radius: 8px;
|
||||
background: #1677ff;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
border-radius: 9px;
|
||||
background: linear-gradient(90deg, #458df8 0%, #0869f5 100%);
|
||||
box-shadow: none;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.mobile-confirm-button.van-button--disabled {
|
||||
@@ -1174,12 +1222,13 @@ layout("/layouts/platform_h5.html"){
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.seat-confirm-sheet {
|
||||
border-radius: 18px 18px 0 0;
|
||||
.seat-confirm-dialog {
|
||||
width: calc(100% - 48px);
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.seat-confirm-content {
|
||||
padding: 21px 18px calc(18px + env(safe-area-inset-bottom));
|
||||
.seat-confirm-dialog .seat-confirm-content {
|
||||
padding: 21px 18px 18px;
|
||||
}
|
||||
|
||||
.seat-confirm-header {
|
||||
@@ -1216,17 +1265,28 @@ layout("/layouts/platform_h5.html"){
|
||||
|
||||
.seat-confirm-submit {
|
||||
height: 46px;
|
||||
margin-top: 18px;
|
||||
border: 0;
|
||||
border-radius: 8px;
|
||||
background: #ff3344;
|
||||
background: #69aefc;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
@media (max-width: 375px) {
|
||||
.mobile-bottom-selected {
|
||||
grid-template-columns: 95px minmax(0, 1fr);
|
||||
gap: 9px;
|
||||
grid-template-columns: 38px max-content 1px minmax(0, 1fr);
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.mobile-bottom-summary {
|
||||
padding: 5px 6px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.mobile-seat-status-icon {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
}
|
||||
|
||||
.mobile-seat {
|
||||
@@ -1248,7 +1308,8 @@ layout("/layouts/platform_h5.html"){
|
||||
<!-- 头部信息 -->
|
||||
<div class="mobile-header" v-if="meeting">
|
||||
<div class="meeting-title">{{ meeting.name }}</div>
|
||||
<div class="meeting-time"><van-icon name="clock-o"></van-icon>{{ formatMeetingRange(meeting) }}</div>
|
||||
<div class="meeting-time"><van-icon name="clock-o"></van-icon>开始时间:{{ formatMeetingTime(meeting.startTime) }}</div>
|
||||
<div class="meeting-time"><van-icon name="calendar-o"></van-icon>结束时间:{{ formatMeetingTime(meeting.endTime) }}</div>
|
||||
<div class="meeting-address"><van-icon name="location-o"></van-icon>{{ meeting.address || '会议地点待定' }}</div>
|
||||
<div class="mobile-header-visual">
|
||||
<img src="/assets/mobile/img/democratic/teachercongress/meeting-dais.png" alt="会议主席台">
|
||||
@@ -1337,68 +1398,23 @@ layout("/layouts/platform_h5.html"){
|
||||
<!-- 图例 -->
|
||||
<div class="mobile-legend">
|
||||
<div class="mobile-legend-item">
|
||||
<svg class="mobile-legend-seat" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#f8f9fa" stroke="#dee2e6"
|
||||
stroke-width="1"/>
|
||||
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#ffffff" stroke="#dee2e6"
|
||||
stroke-width="1"/>
|
||||
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#e9ecef" stroke="#dee2e6"
|
||||
stroke-width="1"/>
|
||||
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#e9ecef" stroke="#dee2e6"
|
||||
stroke-width="1"/>
|
||||
</svg>
|
||||
<img class="mobile-legend-seat" src="/assets/mobile/img/democratic/teachercongress/seat-available.png" alt="">
|
||||
<span>可选</span>
|
||||
</div>
|
||||
<div class="mobile-legend-item">
|
||||
<svg class="mobile-legend-seat" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#adb5bd" stroke="#6c757d"
|
||||
stroke-width="1"/>
|
||||
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#d0d0d0" stroke="#6c757d"
|
||||
stroke-width="1"/>
|
||||
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#adb5bd" stroke="#6c757d"
|
||||
stroke-width="1"/>
|
||||
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#adb5bd" stroke="#6c757d"
|
||||
stroke-width="1"/>
|
||||
</svg>
|
||||
<img class="mobile-legend-seat" src="/assets/mobile/img/democratic/teachercongress/seat-occupied.png" alt="">
|
||||
<span>占用</span>
|
||||
</div>
|
||||
<div class="mobile-legend-item">
|
||||
<svg class="mobile-legend-seat" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#0d47a1" stroke="#1867b0"
|
||||
stroke-width="2"/>
|
||||
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#1867b0" stroke="#0d47a1"
|
||||
stroke-width="2"/>
|
||||
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#0d47a1" stroke="#1867b0"
|
||||
stroke-width="2"/>
|
||||
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#0d47a1" stroke="#1867b0"
|
||||
stroke-width="2"/>
|
||||
</svg>
|
||||
<img class="mobile-legend-seat" src="/assets/mobile/img/democratic/teachercongress/seat-selected.png" alt="">
|
||||
<span>选中</span>
|
||||
</div>
|
||||
<div class="mobile-legend-item">
|
||||
<svg class="mobile-legend-seat" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#c62828" stroke="#ff3742"
|
||||
stroke-width="2"/>
|
||||
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#ff4757" stroke="#c62828"
|
||||
stroke-width="2"/>
|
||||
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#c62828" stroke="#ff3742"
|
||||
stroke-width="2"/>
|
||||
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#c62828" stroke="#ff3742"
|
||||
stroke-width="2"/>
|
||||
</svg>
|
||||
<span>我的</span>
|
||||
<img class="mobile-legend-seat" src="/assets/mobile/img/democratic/teachercongress/seat-mine.png" alt="">
|
||||
<span>已选</span>
|
||||
</div>
|
||||
<div class="mobile-legend-item">
|
||||
<svg class="mobile-legend-seat" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#f5f5f5" stroke="#cccccc"
|
||||
stroke-width="1"/>
|
||||
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#f0f0f0" stroke="#cccccc"
|
||||
stroke-width="1"/>
|
||||
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#f5f5f5" stroke="#cccccc"
|
||||
stroke-width="1"/>
|
||||
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#f5f5f5" stroke="#cccccc"
|
||||
stroke-width="1"/>
|
||||
</svg>
|
||||
<img class="mobile-legend-seat" src="/assets/mobile/img/democratic/teachercongress/seat-disabled.png" alt="">
|
||||
<span>禁用</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1426,13 +1442,7 @@ layout("/layouts/platform_h5.html"){
|
||||
class="mobile-seat"
|
||||
:class="[seat ? getSeatClass(seat) : 'seat-placeholder', {'has-aisle': seatIndex + 1 === aisleStartColumn}]"
|
||||
@click="seat && selectSeat(seat)">
|
||||
<svg class="mobile-seat-icon" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" class="seat-back"/>
|
||||
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" class="seat-cushion"/>
|
||||
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" class="seat-armrest"/>
|
||||
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" class="seat-armrest"/>
|
||||
</svg>
|
||||
<van-icon v-if="seat === selectedSeat" class="mobile-seat-check" name="success"></van-icon>
|
||||
<img v-if="seat" class="mobile-seat-icon" :src="getSeatIcon(seat)" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1444,32 +1454,33 @@ layout("/layouts/platform_h5.html"){
|
||||
<!-- 底部操作面板 -->
|
||||
<div class="mobile-bottom-panel" :class="{'is-empty': !selectedSeat}">
|
||||
<div class="mobile-bottom-selected">
|
||||
<div class="mobile-bottom-summary">
|
||||
<template v-if="myCurrentSeat">{{ myCurrentSeat.rowNumber }}排{{ myCurrentSeat.colNumber }}列(已选)</template>
|
||||
<template v-else>未选择</template>
|
||||
</div>
|
||||
<img class="mobile-seat-status-icon"
|
||||
src="/assets/mobile/img/democratic/teachercongress/seat-status-icon.svg" alt="座位">
|
||||
<span class="mobile-seat-status-copy">
|
||||
<span class="mobile-seat-status-tag">{{ myCurrentSeat ? '已选座位' : '座位状态' }}</span>
|
||||
<span class="mobile-seat-status-value">
|
||||
<template v-if="myCurrentSeat">{{ myCurrentSeat.rowNumber }}排{{ myCurrentSeat.colNumber }}列</template>
|
||||
<template v-else>未选择</template>
|
||||
</span>
|
||||
</span>
|
||||
<span class="mobile-seat-status-divider"></span>
|
||||
<van-button class="mobile-confirm-button" type="info" block :disabled="!selectedSeat"
|
||||
@click="openSeatConfirm">
|
||||
<template v-if="selectedSeat">确认换座 {{ selectedSeat.rowNumber }}排{{ selectedSeat.colNumber }}列</template>
|
||||
<template v-if="selectedSeat">{{ myCurrentSeat ? '确认换座' : '确认选座' }} {{ selectedSeat.rowNumber }}排{{ selectedSeat.colNumber }}列</template>
|
||||
<template v-else>{{ myCurrentSeat ? '点击座位更新' : '请先选择座位' }}</template>
|
||||
</van-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<van-action-sheet v-model="showSeatConfirm" class="seat-confirm-sheet" safe-area-inset-bottom>
|
||||
<van-dialog v-model="showSeatConfirm" class="seat-confirm-dialog"
|
||||
show-cancel-button confirm-button-text="确认" cancel-button-text="取消"
|
||||
@confirm="confirmSelection">
|
||||
<div class="seat-confirm-content">
|
||||
<div class="seat-confirm-header">
|
||||
<span>已选座位</span>
|
||||
<button type="button" class="seat-confirm-clear" @click="clearSelectedSeat">清空</button>
|
||||
<span v-if="selectedSeat">确认{{ myCurrentSeat ? '换座' : '选座' }} {{ selectedSeat.rowNumber }}排{{ selectedSeat.colNumber }}列吗?</span>
|
||||
</div>
|
||||
<div class="seat-confirm-value" v-if="selectedSeat">
|
||||
{{ selectedSeat.rowNumber }}排{{ selectedSeat.colNumber }}座
|
||||
</div>
|
||||
<div class="seat-confirm-tip">请确认座位信息</div>
|
||||
<van-button class="seat-confirm-submit" type="danger" block :loading="submitting"
|
||||
@click="confirmSelection">确认选座</van-button>
|
||||
</div>
|
||||
</van-action-sheet>
|
||||
</van-dialog>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
@@ -1557,11 +1568,8 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
})
|
||||
},
|
||||
formatMeetingRange(item) {
|
||||
if (!item) return ''
|
||||
const start = item.startTime ? this.$moment(item.startTime).format('YYYY-MM-DD HH:mm') : '--'
|
||||
const end = item.endTime ? this.$moment(item.endTime).format('YYYY-MM-DD HH:mm') : '--'
|
||||
return start + ' 至 ' + end
|
||||
formatMeetingTime(time) {
|
||||
return time ? this.$moment(time).format('YYYY-MM-DD HH:mm') : '--'
|
||||
},
|
||||
// 查询选座情况
|
||||
async loadSeats(loading = createListLoading()) {
|
||||
@@ -1670,6 +1678,15 @@ layout("/layouts/platform_h5.html"){
|
||||
return 'available';
|
||||
},
|
||||
|
||||
getSeatIcon(seat) {
|
||||
const iconPath = '/assets/mobile/img/democratic/teachercongress/'
|
||||
if (!seat.enable) return iconPath + 'seat-disabled.png'
|
||||
if (seat.isMine) return iconPath + 'seat-mine.png'
|
||||
if (seat === this.selectedSeat) return iconPath + 'seat-selected.png'
|
||||
if (seat.isOccupied) return iconPath + 'seat-occupied.png'
|
||||
return iconPath + 'seat-available.png'
|
||||
},
|
||||
|
||||
getSeatTitle(seat) {
|
||||
if (seat.isMine) return '我的座位';
|
||||
if (seat === this.selectedSeat) return '当前选择';
|
||||
|
||||
@@ -12,6 +12,12 @@ layout("/layouts/platform_h5.html"){
|
||||
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%;
|
||||
}
|
||||
@@ -38,7 +44,7 @@ layout("/layouts/platform_h5.html"){
|
||||
margin: 0;
|
||||
padding: 12px 14px 8px 21px;
|
||||
color: #354255;
|
||||
font-size: 13px;
|
||||
font-size: 15px;
|
||||
line-height: 20px;
|
||||
font-weight: 600;
|
||||
background: transparent;
|
||||
@@ -63,7 +69,7 @@ layout("/layouts/platform_h5.html"){
|
||||
.condolence-card__desc {
|
||||
padding: 0 14px 8px 21px;
|
||||
color: orangered;
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
font-weight: normal;
|
||||
}
|
||||
@@ -83,14 +89,14 @@ layout("/layouts/platform_h5.html"){
|
||||
.condolence-apply-form .form-section .van-field__label {
|
||||
width: 84px;
|
||||
color: #596779;
|
||||
font-size: 12px;
|
||||
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: 12px;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
@@ -120,8 +126,8 @@ layout("/layouts/platform_h5.html"){
|
||||
.condolence-apply-actions .van-button {
|
||||
height: 40px;
|
||||
margin: 0;
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
border-radius: 14px !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.condolence-apply-actions .van-button:first-child {
|
||||
@@ -134,9 +140,28 @@ layout("/layouts/platform_h5.html"){
|
||||
.condolence-apply-actions .van-button:last-child {
|
||||
flex: 1.08;
|
||||
border-color: #1989fa;
|
||||
border-radius: 14px;
|
||||
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">
|
||||
|
||||
@@ -23,6 +23,13 @@ layout("/layouts/platform_h5.html"){
|
||||
.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; }
|
||||
@@ -72,7 +79,14 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-sticky>
|
||||
|
||||
<main class="condolence-list-content">
|
||||
<table-list api="/platform/condolence/branchUnionApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" @ready="onReady">
|
||||
<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">
|
||||
@@ -180,6 +194,7 @@ layout("/layouts/platform_h5.html"){
|
||||
{text: "未审核", value: "0"},
|
||||
{text: "已审核", value: "1"}
|
||||
],
|
||||
skeletonLoading: true,
|
||||
formData: {},
|
||||
showApprovalForm: false,
|
||||
formLoading: false,
|
||||
@@ -191,6 +206,10 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// state.initial 表示当前查询前列表为空,仅此阶段使用整组卡片骨架屏。
|
||||
handleListLoadingChange(state) {
|
||||
if (state.initial) this.$set(this, "skeletonLoading", state.loading)
|
||||
},
|
||||
// 审核状态下拉值为字符串,接口参数 approval 继续使用布尔值。
|
||||
onApprovalFilterChange(val) {
|
||||
this.$set(this.pageForm, "approval", val === "1")
|
||||
@@ -284,7 +303,7 @@ layout("/layouts/platform_h5.html"){
|
||||
})
|
||||
},
|
||||
queryCondolenceType() {
|
||||
this.$axios.post('/platform/condolence/type/queryCondolenceType')
|
||||
this.$axios.post('/platform/condolence/type/queryCondolenceType', {}, {h5SkeletonLoading: true})
|
||||
.then((res) => {
|
||||
const typeList = res.data || []
|
||||
this.$set(this, "typeOptions", [
|
||||
|
||||
@@ -127,6 +127,44 @@ layout("/layouts/platform_h5.html"){
|
||||
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;
|
||||
@@ -278,7 +316,14 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-sticky>
|
||||
|
||||
<main class="condolence-list-content">
|
||||
<table-list api="/platform/condolence/mine/pageData" :page_form.sync="pageForm" ref="tableListRef" @ready="onReady">
|
||||
<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">
|
||||
@@ -351,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({
|
||||
@@ -403,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(() => {
|
||||
|
||||
@@ -23,6 +23,13 @@ layout("/layouts/platform_h5.html"){
|
||||
.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; }
|
||||
@@ -72,7 +79,14 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-sticky>
|
||||
|
||||
<main class="condolence-list-content">
|
||||
<table-list api="/platform/condolence/schoolPrincipalApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" @ready="onReady">
|
||||
<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">
|
||||
@@ -180,6 +194,7 @@ layout("/layouts/platform_h5.html"){
|
||||
{text: "未审核", value: "0"},
|
||||
{text: "已审核", value: "1"}
|
||||
],
|
||||
skeletonLoading: true,
|
||||
formData: {},
|
||||
showApprovalForm: false,
|
||||
formLoading: false,
|
||||
@@ -191,6 +206,10 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// state.initial 表示当前查询前列表为空,仅此阶段使用整组卡片骨架屏。
|
||||
handleListLoadingChange(state) {
|
||||
if (state.initial) this.$set(this, "skeletonLoading", state.loading)
|
||||
},
|
||||
// 审核状态下拉值为字符串,接口参数 approval 继续使用布尔值。
|
||||
onApprovalFilterChange(val) {
|
||||
this.$set(this.pageForm, "approval", val === "1")
|
||||
@@ -284,7 +303,7 @@ layout("/layouts/platform_h5.html"){
|
||||
})
|
||||
},
|
||||
queryCondolenceType() {
|
||||
this.$axios.post('/platform/condolence/type/queryCondolenceType')
|
||||
this.$axios.post('/platform/condolence/type/queryCondolenceType', {}, {h5SkeletonLoading: true})
|
||||
.then((res) => {
|
||||
const typeList = res.data || []
|
||||
this.$set(this, "typeOptions", [
|
||||
|
||||
@@ -23,6 +23,13 @@ layout("/layouts/platform_h5.html"){
|
||||
.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; }
|
||||
@@ -72,7 +79,14 @@ layout("/layouts/platform_h5.html"){
|
||||
</van-sticky>
|
||||
|
||||
<main class="condolence-list-content">
|
||||
<table-list api="/platform/condolence/schoolUnionApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" @ready="onReady">
|
||||
<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">
|
||||
@@ -180,6 +194,7 @@ layout("/layouts/platform_h5.html"){
|
||||
{text: "未审核", value: "0"},
|
||||
{text: "已审核", value: "1"}
|
||||
],
|
||||
skeletonLoading: true,
|
||||
formData: {},
|
||||
showApprovalForm: false,
|
||||
formLoading: false,
|
||||
@@ -191,6 +206,10 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// state.initial 表示当前查询前列表为空,仅此阶段使用整组卡片骨架屏。
|
||||
handleListLoadingChange(state) {
|
||||
if (state.initial) this.$set(this, "skeletonLoading", state.loading)
|
||||
},
|
||||
// 审核状态下拉值为字符串,接口参数 approval 继续使用布尔值。
|
||||
onApprovalFilterChange(val) {
|
||||
this.$set(this.pageForm, "approval", val === "1")
|
||||
@@ -284,7 +303,7 @@ layout("/layouts/platform_h5.html"){
|
||||
})
|
||||
},
|
||||
queryCondolenceType() {
|
||||
this.$axios.post('/platform/condolence/type/queryCondolenceType')
|
||||
this.$axios.post('/platform/condolence/type/queryCondolenceType', {}, {h5SkeletonLoading: true})
|
||||
.then((res) => {
|
||||
const typeList = res.data || []
|
||||
this.$set(this, "typeOptions", [
|
||||
|
||||
@@ -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,19 +709,153 @@ 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");
|
||||
this.subsidyTypeColumns = subsidyTypeData.map(item => {
|
||||
@@ -432,7 +895,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 +928,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 +963,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 +1034,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 +1063,6 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
}
|
||||
|
||||
this.queryRecipients(res.data.loginName)
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -631,7 +1094,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)
|
||||
@@ -774,6 +1236,18 @@ layout("/layouts/platform_h5.html"){
|
||||
this.modeChange("1")
|
||||
}
|
||||
}
|
||||
},
|
||||
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)
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -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="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>
|
||||
<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>
|
||||
|
||||
@@ -0,0 +1,307 @@
|
||||
#app {
|
||||
--color-primary: #1989fa;
|
||||
}
|
||||
|
||||
.difficult-help-approval-page {
|
||||
min-height: 100vh;
|
||||
padding-bottom: calc(24px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background: #f3f7fd;
|
||||
}
|
||||
|
||||
.difficult-help-approval-page .van-nav-bar,
|
||||
.difficult-help-approval-page .van-sticky--fixed {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.difficult-help-approval-page .van-nav-bar__title {
|
||||
color: #172033;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.difficult-help-approval-page .van-nav-bar .van-icon,
|
||||
.difficult-help-approval-page .van-nav-bar__text {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.difficult-help-approval-sticky {
|
||||
padding: 22px 12px 1px;
|
||||
box-sizing: border-box;
|
||||
background: #f3f7fd;
|
||||
}
|
||||
|
||||
.difficult-help-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);
|
||||
}
|
||||
|
||||
.difficult-help-approval-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.difficult-help-approval-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.difficult-help-approval-search .van-field__control::placeholder {
|
||||
color: #a7b0bf;
|
||||
}
|
||||
|
||||
.difficult-help-approval-filter {
|
||||
margin-bottom: 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
transition: border-radius .18s ease;
|
||||
}
|
||||
|
||||
.difficult-help-approval-filter.is-open {
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
.difficult-help-approval-filter .van-dropdown-menu__bar,
|
||||
.difficult-help-approval-filter .van-dropdown-menu__item,
|
||||
.difficult-help-approval-filter .van-dropdown-menu__title {
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.difficult-help-approval-filter .van-dropdown-menu__bar {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.difficult-help-approval-filter .van-dropdown-menu__item {
|
||||
min-width: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.difficult-help-approval-filter .van-dropdown-menu__title {
|
||||
display: inline-flex;
|
||||
max-width: calc(100% - 12px);
|
||||
align-items: center;
|
||||
color: #66758a;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.difficult-help-approval-filter .van-dropdown-menu__title--active,
|
||||
.difficult-help-approval-filter .van-dropdown-item__option--active,
|
||||
.difficult-help-approval-filter .van-dropdown-item__option--active .van-cell__title,
|
||||
.difficult-help-approval-filter .van-dropdown-item__option--active .van-dropdown-item__icon {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.difficult-help-approval-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
max-height: 50%;
|
||||
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);
|
||||
}
|
||||
|
||||
.difficult-help-approval-filter .van-dropdown-item__option {
|
||||
display: flex;
|
||||
min-height: 48px;
|
||||
padding: 0 16px;
|
||||
align-items: center;
|
||||
color: #46566c;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.difficult-help-approval-filter .van-dropdown-item__option .van-cell__title {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
min-height: 20px;
|
||||
align-items: center;
|
||||
flex: 1 1 auto;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.difficult-help-approval-filter .van-dropdown-item__option .van-cell__value {
|
||||
display: flex;
|
||||
width: 20px;
|
||||
min-width: 0;
|
||||
overflow: visible;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
flex: 0 0 20px;
|
||||
}
|
||||
|
||||
.difficult-help-approval-content {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.difficult-help-list-skeleton {
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.difficult-help-list-skeleton__card {
|
||||
margin-bottom: 12px;
|
||||
padding: 14px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #e9eff7;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
}
|
||||
|
||||
.difficult-help-list-skeleton__card .van-skeleton {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.difficult-help-list-skeleton__card .van-skeleton__title {
|
||||
width: 34%;
|
||||
height: 17px;
|
||||
margin-bottom: 13px;
|
||||
}
|
||||
|
||||
.difficult-help-list-skeleton__card .van-skeleton__row {
|
||||
height: 12px;
|
||||
margin-top: 11px;
|
||||
}
|
||||
|
||||
.difficult-help-list-skeleton__card .van-skeleton__row:nth-child(2n) {
|
||||
width: 88%;
|
||||
}
|
||||
|
||||
.difficult-help-list-skeleton__card .van-skeleton__row:last-child {
|
||||
width: 48%;
|
||||
margin-top: 18px;
|
||||
}
|
||||
|
||||
.difficult-help-approval-page .table-list-container {
|
||||
margin-top: 0;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.difficult-help-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);
|
||||
}
|
||||
|
||||
.difficult-help-approval-card-header {
|
||||
display: flex;
|
||||
margin-bottom: 8px;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.difficult-help-approval-card-heading {
|
||||
min-width: 0;
|
||||
padding-right: 10px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.difficult-help-approval-card-title {
|
||||
overflow: hidden;
|
||||
color: #253247;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.difficult-help-approval-card-code {
|
||||
margin-top: 1px;
|
||||
color: #9ba6b6;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.difficult-help-approval-card-status {
|
||||
display: inline-flex;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.difficult-help-approval-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;
|
||||
}
|
||||
|
||||
.difficult-help-approval-page .table-list-container .table-list-item .item-actions {
|
||||
margin-top: 10px;
|
||||
padding-top: 10px;
|
||||
border-top-color: #edf1f6;
|
||||
}
|
||||
|
||||
.difficult-help-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;
|
||||
}
|
||||
|
||||
.difficult-help-approval-page .table-list-container .table-list-item .action-btn.delete {
|
||||
color: #f04444;
|
||||
background: #fff0f0;
|
||||
}
|
||||
|
||||
.difficult-help-approval-page .table-list-container .table-list-item .action-btn .van-icon {
|
||||
margin-right: 5px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.difficult-help-approval-page .empty-state {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.difficult-help-approval-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;
|
||||
}
|
||||
|
||||
.difficult-help-approval-empty img {
|
||||
display: block;
|
||||
width: 86%;
|
||||
max-width: 290px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.difficult-help-approval-empty__title {
|
||||
margin-top: 14px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.difficult-help-approval-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
@@ -0,0 +1,353 @@
|
||||
.difficult-help-full-popup {
|
||||
--color-primary: #1989fa;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background: #f3f7fc;
|
||||
}
|
||||
|
||||
.difficult-help-full-popup__page {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
padding-top: 46px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.difficult-help-full-popup__page > .van-nav-bar {
|
||||
z-index: 20;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.difficult-help-full-popup__page > .van-nav-bar .van-icon,
|
||||
.difficult-help-full-popup__page > .van-nav-bar .van-nav-bar__text {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.difficult-help-full-popup__scroll {
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
flex: 1;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.difficult-help-info-main {
|
||||
padding: 12px 15px calc(18px + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.difficult-help-info-card {
|
||||
margin-bottom: 11px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #e9eff7;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
box-shadow: 0 3px 11px rgba(51, 87, 126, .08);
|
||||
}
|
||||
|
||||
.difficult-help-info-card__title {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
padding: 12px 14px 8px 21px;
|
||||
color: #354255;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.difficult-help-info-card__title::before {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
bottom: 11px;
|
||||
left: 12px;
|
||||
width: 2px;
|
||||
border-radius: 2px;
|
||||
background: #1989fa;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.difficult-help-audit-card__required {
|
||||
margin-left: 4px;
|
||||
color: #ee0a24;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.difficult-help-audit-form {
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
.difficult-help-info-card .van-field.difficult-help-audit-select,
|
||||
.difficult-help-info-card .van-field.difficult-help-audit-money {
|
||||
min-height: 48px;
|
||||
padding: 11px 14px;
|
||||
}
|
||||
|
||||
.difficult-help-info-card .van-field.difficult-help-audit-select .van-field__label,
|
||||
.difficult-help-info-card .van-field.difficult-help-audit-money .van-field__label {
|
||||
width: 88px;
|
||||
color: #596779;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.difficult-help-info-card .van-field.difficult-help-audit-select .van-field__control,
|
||||
.difficult-help-info-card .van-field.difficult-help-audit-money .van-field__control {
|
||||
color: #253247;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.difficult-help-info-card .van-field.difficult-help-audit-textarea {
|
||||
width: calc(100% - 28px);
|
||||
margin: 0 14px 14px;
|
||||
padding: 12px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #c9d5e5;
|
||||
border-radius: 10px;
|
||||
background: #f7f9fd;
|
||||
}
|
||||
|
||||
.difficult-help-info-card .van-field.difficult-help-audit-textarea .van-field__control {
|
||||
min-height: 132px;
|
||||
color: #253247;
|
||||
font-size: 13px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.difficult-help-info-card .van-field.difficult-help-audit-textarea .van-field__control::placeholder,
|
||||
.difficult-help-info-card .van-field.difficult-help-audit-select .van-field__control::placeholder,
|
||||
.difficult-help-info-card .van-field.difficult-help-audit-money .van-field__control::placeholder {
|
||||
color: #9aa7b8;
|
||||
}
|
||||
|
||||
.difficult-help-info-card .van-field.difficult-help-audit-textarea .van-field__word-limit {
|
||||
color: #718096;
|
||||
}
|
||||
|
||||
.difficult-help-info-card .van-field.difficult-help-audit-textarea::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.difficult-help-popup-actions {
|
||||
display: flex;
|
||||
padding: 10px 0 calc(12px + env(safe-area-inset-bottom));
|
||||
justify-content: space-between;
|
||||
column-gap: 10px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.difficult-help-popup-actions .van-button {
|
||||
min-width: 0;
|
||||
border-radius: 14px;
|
||||
}
|
||||
|
||||
.difficult-help-popup-actions .difficult-help-action-primary {
|
||||
border-color: #1989fa;
|
||||
background: #1989fa;
|
||||
}
|
||||
|
||||
.difficult-help-popup-actions .difficult-help-action-danger {
|
||||
border-color: #ff4d4f;
|
||||
background: #ff4d4f;
|
||||
}
|
||||
|
||||
.difficult-help-info-card .van-cell-group {
|
||||
margin: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.difficult-help-info-card .van-cell {
|
||||
min-height: 44px;
|
||||
padding: 10px 14px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.difficult-help-info-card .van-cell:not(:last-child)::after {
|
||||
right: 14px;
|
||||
left: 14px;
|
||||
border-color: #eef2f7;
|
||||
}
|
||||
|
||||
.difficult-help-info-card .van-cell__title {
|
||||
width: 112px;
|
||||
color: #596779;
|
||||
font-size: 12px;
|
||||
line-height: 24px;
|
||||
flex: 0 0 112px;
|
||||
}
|
||||
|
||||
.difficult-help-info-card .van-cell__value {
|
||||
min-width: 0;
|
||||
color: #4f5d70;
|
||||
font-size: 12px;
|
||||
line-height: 24px;
|
||||
text-align: left;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.difficult-help-info-long-cell {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.difficult-help-info-long-cell .van-cell__title {
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.difficult-help-info-long-cell .van-cell__value {
|
||||
margin-top: 7px;
|
||||
}
|
||||
|
||||
.difficult-help-info-pre-line {
|
||||
white-space: pre-line;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.difficult-help-family-list {
|
||||
padding: 0 14px 14px;
|
||||
}
|
||||
|
||||
.difficult-help-family-item {
|
||||
overflow: hidden;
|
||||
border: 1px solid #e5edf7;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
box-shadow: 0 2px 8px rgba(51, 87, 126, .06);
|
||||
}
|
||||
|
||||
.difficult-help-family-item + .difficult-help-family-item {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.difficult-help-family-header {
|
||||
display: flex;
|
||||
min-height: 44px;
|
||||
padding: 9px 11px;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
background: linear-gradient(90deg, #f0f6ff 0%, #f8fbff 100%);
|
||||
}
|
||||
|
||||
.difficult-help-family-index {
|
||||
display: inline-flex;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 8px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 0 0 24px;
|
||||
border-radius: 50%;
|
||||
color: #fff;
|
||||
background: #1989fa;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.difficult-help-family-name {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
color: #2f3d51;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.difficult-help-family-relation {
|
||||
max-width: 92px;
|
||||
margin-left: 8px;
|
||||
padding: 2px 8px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
color: #1989fa;
|
||||
background: #e7f2ff;
|
||||
font-size: 11px;
|
||||
line-height: 18px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.difficult-help-family-summary {
|
||||
display: grid;
|
||||
margin: 0 11px;
|
||||
padding: 11px 0;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
border-bottom: 1px solid #eef2f7;
|
||||
}
|
||||
|
||||
.difficult-help-family-summary__item {
|
||||
min-width: 0;
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.difficult-help-family-summary__item:first-child {
|
||||
padding-left: 0;
|
||||
border-right: 1px solid #eef2f7;
|
||||
}
|
||||
|
||||
.difficult-help-family-summary__item span,
|
||||
.difficult-help-family-summary__item strong,
|
||||
.difficult-help-family-detail__row span,
|
||||
.difficult-help-family-detail__row strong {
|
||||
display: block;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.difficult-help-family-summary__item span,
|
||||
.difficult-help-family-detail__row span {
|
||||
color: #909bac;
|
||||
font-size: 11px;
|
||||
line-height: 17px;
|
||||
}
|
||||
|
||||
.difficult-help-family-summary__item strong {
|
||||
margin-top: 3px;
|
||||
color: #435167;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.difficult-help-family-detail {
|
||||
padding: 4px 11px 7px;
|
||||
}
|
||||
|
||||
.difficult-help-family-detail__row {
|
||||
display: grid;
|
||||
padding: 7px 0;
|
||||
grid-template-columns: 68px minmax(0, 1fr);
|
||||
column-gap: 8px;
|
||||
}
|
||||
|
||||
.difficult-help-family-detail__row strong {
|
||||
color: #536176;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.difficult-help-info-card .van-empty {
|
||||
padding: 12px 0 20px;
|
||||
}
|
||||
|
||||
.difficult-help-info-promise {
|
||||
color: #4f5d70;
|
||||
font-size: 12px;
|
||||
line-height: 21px;
|
||||
}
|
||||
|
||||
.difficult-help-info-commitment {
|
||||
display: flex;
|
||||
margin-top: 8px;
|
||||
align-items: flex-end;
|
||||
color: #8995a6;
|
||||
font-size: 11px;
|
||||
line-height: 18px;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.difficult-help-signature-image {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -1,33 +1,382 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
<style>
|
||||
#app {
|
||||
--color-primary: #1989fa;
|
||||
}
|
||||
|
||||
.difficult-help-list-page {
|
||||
min-height: 100vh;
|
||||
padding-bottom: calc(24px + env(safe-area-inset-bottom));
|
||||
box-sizing: border-box;
|
||||
background: #f3f7fd;
|
||||
}
|
||||
|
||||
.difficult-help-list-page .van-nav-bar,
|
||||
.difficult-help-list-page .van-sticky--fixed {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.difficult-help-list-page .van-nav-bar__title {
|
||||
color: #172033;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.difficult-help-list-page .van-nav-bar .van-icon,
|
||||
.difficult-help-list-page .van-nav-bar__text {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.difficult-help-list-sticky {
|
||||
padding: 22px 12px 1px;
|
||||
box-sizing: border-box;
|
||||
background: #f3f7fd;
|
||||
}
|
||||
|
||||
.difficult-help-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);
|
||||
}
|
||||
|
||||
.difficult-help-list-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.difficult-help-list-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.difficult-help-list-search .van-field__control::placeholder {
|
||||
color: #a7b0bf;
|
||||
}
|
||||
|
||||
.difficult-help-list-filter {
|
||||
margin-bottom: 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
transition: border-radius .18s ease;
|
||||
}
|
||||
|
||||
.difficult-help-list-filter.is-open {
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
.difficult-help-list-filter .van-dropdown-menu__bar {
|
||||
height: 44px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.difficult-help-list-filter .van-dropdown-menu__item,
|
||||
.difficult-help-list-filter .van-dropdown-menu__title {
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.difficult-help-list-filter .van-dropdown-menu__item {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.difficult-help-list-filter .van-dropdown-menu__title {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
line-height: 20px;
|
||||
color: #66758a;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.difficult-help-list-filter .van-dropdown-menu__title--active,
|
||||
.difficult-help-list-filter .van-dropdown-item__option--active,
|
||||
.difficult-help-list-filter .van-dropdown-item__option--active .van-cell__title,
|
||||
.difficult-help-list-filter .van-dropdown-item__option--active .van-dropdown-item__icon {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.difficult-help-list-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
max-height: 50%;
|
||||
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);
|
||||
}
|
||||
|
||||
.difficult-help-list-filter .van-dropdown-item__option {
|
||||
display: flex;
|
||||
min-height: 48px;
|
||||
padding: 0 16px;
|
||||
align-items: center;
|
||||
color: #46566c;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.difficult-help-list-filter .van-dropdown-item__option .van-cell__title {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
min-height: 20px;
|
||||
align-items: center;
|
||||
flex: 1 1 auto;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.difficult-help-list-filter .van-dropdown-item__option .van-cell__value {
|
||||
display: flex;
|
||||
width: 20px;
|
||||
min-width: 0;
|
||||
overflow: visible;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
flex: 0 0 20px;
|
||||
}
|
||||
|
||||
.difficult-help-list-filter .van-dropdown-item__option .van-dropdown-item__icon {
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.difficult-help-list-content {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.difficult-help-list-skeleton {
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.difficult-help-list-skeleton__card {
|
||||
margin-bottom: 12px;
|
||||
padding: 14px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #e9eff7;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
}
|
||||
|
||||
.difficult-help-list-skeleton__card .van-skeleton {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.difficult-help-list-skeleton__card .van-skeleton__title {
|
||||
width: 34%;
|
||||
height: 17px;
|
||||
margin-bottom: 13px;
|
||||
}
|
||||
|
||||
.difficult-help-list-skeleton__card .van-skeleton__row {
|
||||
height: 12px;
|
||||
margin-top: 11px;
|
||||
}
|
||||
|
||||
.difficult-help-list-skeleton__card .van-skeleton__row:nth-child(2n) {
|
||||
width: 88%;
|
||||
}
|
||||
|
||||
.difficult-help-list-skeleton__card .van-skeleton__row:last-child {
|
||||
width: 48%;
|
||||
margin-top: 18px;
|
||||
}
|
||||
|
||||
.difficult-help-list-page .table-list-container {
|
||||
margin-top: 0;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.difficult-help-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);
|
||||
}
|
||||
|
||||
.difficult-help-card-header {
|
||||
display: flex;
|
||||
margin-bottom: 8px;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.difficult-help-card-heading {
|
||||
min-width: 0;
|
||||
padding-right: 10px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.difficult-help-card-title {
|
||||
overflow: hidden;
|
||||
color: #253247;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.difficult-help-card-code {
|
||||
margin-top: 1px;
|
||||
color: #9ba6b6;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.difficult-help-card-status {
|
||||
display: inline-flex;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.difficult-help-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;
|
||||
}
|
||||
|
||||
.difficult-help-list-page .table-list-container .table-list-item .item-actions {
|
||||
margin-top: 10px;
|
||||
padding-top: 10px;
|
||||
border-top-color: #edf1f6;
|
||||
}
|
||||
|
||||
.difficult-help-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;
|
||||
}
|
||||
|
||||
.difficult-help-list-page .table-list-container .table-list-item .action-btn.delete {
|
||||
color: #f04444;
|
||||
background: #fff0f0;
|
||||
}
|
||||
|
||||
.difficult-help-list-page .table-list-container .table-list-item .action-btn i,
|
||||
.difficult-help-list-page .table-list-container .table-list-item .action-btn .van-icon {
|
||||
margin-right: 5px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.difficult-help-list-page .empty-state {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.difficult-help-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;
|
||||
}
|
||||
|
||||
.difficult-help-list-empty img {
|
||||
display: block;
|
||||
width: 86%;
|
||||
max-width: 290px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.difficult-help-list-empty__title {
|
||||
margin-top: 14px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.difficult-help-list-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
</style>
|
||||
<style id="style-difficult-help-info-h5">
|
||||
<!--#include("../common/info.css"){}#-->
|
||||
</style>
|
||||
<div id="app">
|
||||
<van-sticky>
|
||||
<div class="difficult-help-list-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-list-sticky">
|
||||
<van-search
|
||||
v-model="pageForm.searchKeyword"
|
||||
class="difficult-help-list-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
|
||||
class="difficult-help-list-filter"
|
||||
:class="{'is-open': filterOpened}"
|
||||
v-if="$auth.hasRoleOr('SYSADMIN,SCHOOL_UNION_ADMIN,BRANCH_UNION_CHAIRMAN')"
|
||||
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
|
||||
:options="unionList"
|
||||
@change="unionChange"
|
||||
@open="filterOpened = true"
|
||||
@close="filterOpened = false"
|
||||
v-model="pageForm.unionId">
|
||||
</van-dropdown-item>
|
||||
<van-dropdown-item
|
||||
:options="unitList"
|
||||
@change="doSearch"
|
||||
@open="filterOpened = true"
|
||||
@close="filterOpened = false"
|
||||
v-model="pageForm.unitId">
|
||||
</van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</div>
|
||||
</van-sticky>
|
||||
|
||||
<table-list api="/platform/difficultHelp/mine/pageData" :page_form.sync="pageForm" ref="tableListRef" title="userName" @ready="doSearch">
|
||||
<main class="difficult-help-list-content">
|
||||
<div class="difficult-help-list-skeleton" v-if="skeletonLoading">
|
||||
<div class="difficult-help-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/difficultHelp/mine/pageData" :page_form.sync="pageForm" ref="tableListRef" title="userName"
|
||||
v-show="!skeletonLoading" :show_loading_overlay="false" @ready="doSearch"
|
||||
@loading-change="handleListLoadingChange">
|
||||
<template #header="{index,row}">
|
||||
<div class="difficult-help-card-header">
|
||||
<div class="difficult-help-card-heading">
|
||||
<div class="difficult-help-card-title">{{row.userName || '--'}}</div>
|
||||
<div class="difficult-help-card-code">工号:{{row.loginName || '--'}}</div>
|
||||
</div>
|
||||
<enum-tag class="difficult-help-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>
|
||||
@@ -36,27 +385,36 @@ 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.taskKey === 'startTask' || !row.instanceId"
|
||||
@click="onEdit(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-undo"></i>
|
||||
<van-icon name="revoke"></van-icon>
|
||||
<span>撤回</span>
|
||||
</div>
|
||||
<div class="action-btn delete" v-if="row.taskKey === 'startTask' || !row.instanceId"
|
||||
@click="onDelete(row.id)">
|
||||
<i class="fa fa-trash"></i>
|
||||
<van-icon name="delete-o"></van-icon>
|
||||
<span>删除</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #empty>
|
||||
<div class="difficult-help-list-empty">
|
||||
<img src="/assets/mobile/img/difficultHelp/difficult-help-empty.png" alt="暂无帮扶申请记录插画">
|
||||
<div class="difficult-help-list-empty__title">暂无帮扶申请记录</div>
|
||||
<div class="difficult-help-list-empty__hint">当前筛选条件下暂时没有帮扶申请</div>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
</main>
|
||||
|
||||
<info ref="infoRef"></info>
|
||||
<info ref="infoRef" page-key="difficult-help-mine-detail" full-screen></info>
|
||||
</div>
|
||||
</div>
|
||||
<script nonce="${cspNonce!}">
|
||||
<!--#include("../common/info.js"){}#-->
|
||||
@@ -75,6 +433,8 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
unionList: [],
|
||||
unitList: [],
|
||||
filterOpened: false,
|
||||
skeletonLoading: true,
|
||||
}
|
||||
},
|
||||
components: {
|
||||
@@ -83,6 +443,11 @@ layout("/layouts/platform_h5.html"){
|
||||
methods: {
|
||||
historyBack,
|
||||
|
||||
// state.initial 表示当前查询前列表为空,仅此阶段使用整组卡片骨架屏。
|
||||
handleListLoadingChange(state) {
|
||||
if (state.initial) this.$set(this, "skeletonLoading", state.loading)
|
||||
},
|
||||
|
||||
onView(row) {
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
},
|
||||
@@ -124,49 +489,51 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
|
||||
doSearch() {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
// 等待下拉框的 v-model 与 table-list 内部分页参数同步后再查询,避免旧参数回写覆盖新选中值。
|
||||
this.$nextTick(() => {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
},
|
||||
unionChange() {
|
||||
this.$set(this.pageForm, "unitId", null)
|
||||
this.flushUnits()
|
||||
this.doSearch()
|
||||
},
|
||||
async initUnion() {
|
||||
// unionId 为当前用户可查询的工会范围;返回 Promise,结果写入 Vant 工会选项。
|
||||
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
|
||||
})
|
||||
if (hasAdmin) {
|
||||
this.unionList.unshift({ text: "全部工会", value: null })
|
||||
}
|
||||
if (this.unionList && this.unionList.length > 0) {
|
||||
this.$set(this.pageForm, "unionId", this.unionList[0].value)
|
||||
}
|
||||
return this.$axios.post("/open/common/unionOptions", {unionId}, {h5SkeletonLoading: true})
|
||||
.then((res) => {
|
||||
this.$set(this, "unionList", res && res.code === 0 ? (res.data || []) : [])
|
||||
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)
|
||||
})
|
||||
},
|
||||
async flushUnits() {
|
||||
// unionId 为已选工会;返回 Promise,结果写入 Vant 单位选项。
|
||||
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
|
||||
})
|
||||
if (hasAdmin && !this.pageForm.unionId) {
|
||||
this.unitList.unshift({ text: "全部单位", value: null })
|
||||
}
|
||||
if (this.unitList && this.unitList.length > 0) {
|
||||
this.$set(this.pageForm, "unitId", this.unitList[0].value)
|
||||
}
|
||||
return this.$axios.post("/open/common/unitOptions", {unionId}, {h5SkeletonLoading: true})
|
||||
.then((res) => {
|
||||
this.$set(this, "unitList", res && res.code === 0 ? (res.data || []) : [])
|
||||
this.unitList.forEach((v) => {
|
||||
this.$set(v, "text", v.name)
|
||||
this.$set(v, "value", v.id)
|
||||
})
|
||||
if (hasAdmin && !this.pageForm.unionId) this.unitList.unshift({text: "全部单位", value: null})
|
||||
if (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())
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -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/schoolUnionApproval/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="'school-approval-skeleton-' + index">
|
||||
<van-skeleton title :row="5" animated></van-skeleton>
|
||||
</div>
|
||||
</div>
|
||||
<table-list api="/platform/difficultHelp/schoolUnionApproval/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,72 +84,101 @@ 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-school-union-detail" full-screen>
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">{{formData.taskName}}</div>
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
v-model="formData.level"
|
||||
name="level"
|
||||
label="级别"
|
||||
placeholder="请选择级别"
|
||||
is-link
|
||||
@click="showLevelPicker = true"
|
||||
:rules="[{ required: true, message: '请选择级别' }]"
|
||||
required
|
||||
></van-field>
|
||||
<van-popup v-model="showLevelPicker" position="bottom">
|
||||
<van-picker
|
||||
show-toolbar
|
||||
:columns="levelColumns"
|
||||
@confirm="onLevelConfirm"
|
||||
@cancel="showLevelPicker=false">
|
||||
</van-picker>
|
||||
</van-popup>
|
||||
|
||||
<van-field
|
||||
v-model="formData.money"
|
||||
name="money"
|
||||
label="审核金额"
|
||||
placeholder="请输入审核金额"
|
||||
type="number"
|
||||
:rules="[{ required: true, message: '请输入审核金额' }]"
|
||||
required
|
||||
></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>
|
||||
<section class="difficult-help-info-card">
|
||||
<h2 class="difficult-help-info-card__title">审核信息</h2>
|
||||
<div class="difficult-help-audit-form">
|
||||
<van-field
|
||||
v-model="formData.level"
|
||||
class="difficult-help-audit-select"
|
||||
name="level"
|
||||
label="级别"
|
||||
placeholder="请选择级别"
|
||||
readonly
|
||||
is-link
|
||||
required
|
||||
@click="openLevelPicker"
|
||||
:rules="[{ required: true, message: '请选择级别' }]"
|
||||
></van-field>
|
||||
<van-field
|
||||
v-model="formData.money"
|
||||
class="difficult-help-audit-money"
|
||||
name="money"
|
||||
label="审核金额"
|
||||
placeholder="请输入审核金额"
|
||||
type="number"
|
||||
required
|
||||
:rules="[{ required: true, message: '请输入审核金额' }]"
|
||||
></van-field>
|
||||
</div>
|
||||
</section>
|
||||
<section class="difficult-help-info-card">
|
||||
<h2 class="difficult-help-info-card__title">
|
||||
审批意见<span class="difficult-help-audit-card__required">*</span>
|
||||
</h2>
|
||||
<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>
|
||||
</section>
|
||||
</van-form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<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 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-popup :value="showLevelPicker" position="bottom" :close-on-click-overlay="false">
|
||||
<van-picker
|
||||
show-toolbar
|
||||
:columns="levelColumns"
|
||||
@confirm="onLevelConfirm"
|
||||
@cancel="closeLevelPicker">
|
||||
</van-picker>
|
||||
</van-popup>
|
||||
<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"){}#-->
|
||||
@@ -117,8 +189,9 @@ layout("/layouts/platform_h5.html"){
|
||||
data() {
|
||||
return {
|
||||
pageForm: {
|
||||
pageNo: 1,
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
searchKeyword: '',
|
||||
unionId: '',
|
||||
unitId: '',
|
||||
@@ -127,12 +200,23 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
unionList: [],
|
||||
unitList: [],
|
||||
approvalOptions: [
|
||||
{text: "未审核", value: "0"},
|
||||
{text: "已审核", value: "1"}
|
||||
],
|
||||
filterOpened: false,
|
||||
skeletonLoading: true,
|
||||
|
||||
formData: {},
|
||||
showApprovalForm: false,
|
||||
|
||||
formLoading: false,
|
||||
showLevelPicker: false,
|
||||
levelColumns: []
|
||||
levelColumns: [],
|
||||
confirmVisible: false,
|
||||
confirmActionType: "task",
|
||||
pendingSubmitType: null,
|
||||
pendingRevokeRow: null,
|
||||
historyLayerUnsubscribe: null
|
||||
}
|
||||
},
|
||||
components: {
|
||||
@@ -141,6 +225,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()
|
||||
},
|
||||
@@ -154,123 +256,179 @@ 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,
|
||||
money: 0,
|
||||
id: row.id,
|
||||
level: "",
|
||||
tf_opinion: ""
|
||||
}
|
||||
})
|
||||
this.$refs.infoRef.onOpen(row, row.curTaskName || "帮扶审核")
|
||||
},
|
||||
|
||||
async initLevelDict() {
|
||||
const levelData = await this.$businessTool.getDictOptions("DIFFICULT_LEVEL");
|
||||
this.levelColumns = levelData.map(item => {
|
||||
return { text: item.name, value: item.code };
|
||||
});
|
||||
// 加载困难级别字典并转换为 Vant Picker 所需的 text/value 结构。
|
||||
initLevelDict() {
|
||||
return this.$axios.post("/open/common/dictOptions", {code: "DIFFICULT_LEVEL"}, {h5SkeletonLoading: true}).then((res) => {
|
||||
const levelData = res && res.code === 0 ? res.data : []
|
||||
this.$set(this, "levelColumns", (levelData || []).map((item) => ({
|
||||
text: item.name,
|
||||
value: item.code
|
||||
})))
|
||||
})
|
||||
},
|
||||
|
||||
// 级别选择器作为详情上层弹框,打开时同步增加浏览器历史。
|
||||
openLevelPicker() {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open("difficult-help-level-picker")) return
|
||||
this.$set(this, "showLevelPicker", true)
|
||||
},
|
||||
|
||||
closeLevelPicker(afterClose = null) {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.close("difficult-help-level-picker", afterClose)) return
|
||||
this.$set(this, "showLevelPicker", false)
|
||||
if (typeof afterClose === "function") afterClose()
|
||||
},
|
||||
|
||||
onLevelConfirm(option) {
|
||||
this.formData.level = option.value;
|
||||
this.showLevelPicker = false;
|
||||
this.closeLevelPicker(() => {
|
||||
this.$set(this.formData, "level", option.value)
|
||||
})
|
||||
},
|
||||
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate();
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
this.$axios.post("/platform/difficultHelp/schoolUnionApproval/save", {
|
||||
// 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()
|
||||
})
|
||||
},
|
||||
|
||||
// 先保存级别和金额,再提交 processTaskId、审批意见及流程提交类型。
|
||||
submitTaskAction() {
|
||||
this.$set(this, "formLoading", true)
|
||||
this.$axios.post("/platform/difficultHelp/schoolUnionApproval/save", {
|
||||
data: JSON.stringify({...this.formData})
|
||||
})
|
||||
.then((saveRes) => {
|
||||
if (!saveRes || saveRes.code !== 0) return null
|
||||
return this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: this.pendingSubmitType
|
||||
})
|
||||
}).then((saveRes) => {
|
||||
if (saveRes.code === 0) {
|
||||
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) {
|
||||
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();
|
||||
.then((res) => {
|
||||
if (res && res.code === 0) {
|
||||
const afterClose = () => {
|
||||
this.$toast.success(res.msg)
|
||||
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()
|
||||
await this.initLevelDict()
|
||||
created() {
|
||||
this.initUnion().then(() => this.flushUnits())
|
||||
this.initLevelDict()
|
||||
if (!window.h5HistoryLayerManager) return
|
||||
this.$set(this, "historyLayerUnsubscribe", window.h5HistoryLayerManager.subscribe((stack) => {
|
||||
this.$set(this, "confirmVisible", stack.includes("difficult-help-action-confirm"))
|
||||
this.$set(this, "showLevelPicker", stack.includes("difficult-help-level-picker"))
|
||||
}))
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (typeof this.historyLayerUnsubscribe === "function") this.historyLayerUnsubscribe()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -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/unionLeaderApproval/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="'leader-approval-skeleton-' + index">
|
||||
<van-skeleton title :row="5" animated></van-skeleton>
|
||||
</div>
|
||||
</div>
|
||||
<table-list api="/platform/difficultHelp/unionLeaderApproval/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,54 +84,101 @@ 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-union-leader-detail" full-screen>
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">{{formData.taskName}}</div>
|
||||
<van-form ref="formRef">
|
||||
|
||||
<el-form-item label="级别" prop="level" :rules="[{required:true,message:'必填',trigger:['change','blur']}]">
|
||||
<search-item>
|
||||
<dict-select v-model="formData.level" code="DIFFICULT_LEVEL" style="width: 100%" placeholder="请选择级别"></dict-select>
|
||||
</search-item>
|
||||
</el-form-item>
|
||||
<el-form-item label="审核金额" prop="money" :rules="[{required:true,message:'必填',trigger:['change','blur']}]">
|
||||
<el-input-number placeholder="请输入金额" v-model="formData.money" style="width: 100%" :precision="2"
|
||||
:min="0" ></el-input-number>
|
||||
</el-form-item>
|
||||
|
||||
<van-field
|
||||
v-model="formData.tf_opinion"
|
||||
name="tf_opinion"
|
||||
label="审批意见"
|
||||
placeholder="请输入审批意见"
|
||||
:rules="[{ required: true, message: '请填写审批意见' }]"
|
||||
required
|
||||
maxlength="100"
|
||||
show-word-limit
|
||||
></van-field>
|
||||
<section class="difficult-help-info-card">
|
||||
<h2 class="difficult-help-info-card__title">审核信息</h2>
|
||||
<div class="difficult-help-audit-form">
|
||||
<van-field
|
||||
v-model="formData.level"
|
||||
class="difficult-help-audit-select"
|
||||
name="level"
|
||||
label="级别"
|
||||
placeholder="请选择级别"
|
||||
readonly
|
||||
is-link
|
||||
required
|
||||
@click="openLevelPicker"
|
||||
:rules="[{ required: true, message: '请选择级别' }]"
|
||||
></van-field>
|
||||
<van-field
|
||||
v-model="formData.money"
|
||||
class="difficult-help-audit-money"
|
||||
name="money"
|
||||
label="审核金额"
|
||||
placeholder="请输入审核金额"
|
||||
type="number"
|
||||
required
|
||||
:rules="[{ required: true, message: '请输入审核金额' }]"
|
||||
></van-field>
|
||||
</div>
|
||||
</section>
|
||||
<section class="difficult-help-info-card">
|
||||
<h2 class="difficult-help-info-card__title">
|
||||
审批意见<span class="difficult-help-audit-card__required">*</span>
|
||||
</h2>
|
||||
<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>
|
||||
</section>
|
||||
</van-form>
|
||||
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
|
||||
<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 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-popup :value="showLevelPicker" position="bottom" :close-on-click-overlay="false">
|
||||
<van-picker
|
||||
show-toolbar
|
||||
:columns="levelColumns"
|
||||
@confirm="onLevelConfirm"
|
||||
@cancel="closeLevelPicker">
|
||||
</van-picker>
|
||||
</van-popup>
|
||||
<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"){}#-->
|
||||
@@ -99,8 +189,9 @@ layout("/layouts/platform_h5.html"){
|
||||
data() {
|
||||
return {
|
||||
pageForm: {
|
||||
pageNo: 1,
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
searchKeyword: '',
|
||||
unionId: '',
|
||||
unitId: '',
|
||||
@@ -109,9 +200,23 @@ 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,
|
||||
showLevelPicker: false,
|
||||
levelColumns: [],
|
||||
confirmVisible: false,
|
||||
confirmActionType: "task",
|
||||
pendingSubmitType: null,
|
||||
pendingRevokeRow: null,
|
||||
historyLayerUnsubscribe: null
|
||||
}
|
||||
},
|
||||
components: {
|
||||
@@ -120,6 +225,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()
|
||||
},
|
||||
@@ -134,99 +257,172 @@ 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,
|
||||
level: "",
|
||||
money: 0,
|
||||
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()
|
||||
// 加载困难级别字典并转换为 Vant Picker 所需的 text/value 结构。
|
||||
initLevelDict() {
|
||||
return this.$axios.post("/open/common/dictOptions", {code: "DIFFICULT_LEVEL"}, {h5SkeletonLoading: true}).then((res) => {
|
||||
const levelData = res && res.code === 0 ? res.data : []
|
||||
this.$set(this, "levelColumns", (levelData || []).map((item) => ({
|
||||
text: item.name,
|
||||
value: item.code
|
||||
})))
|
||||
})
|
||||
},
|
||||
|
||||
// 级别选择器作为详情上层弹框,打开时同步增加浏览器历史。
|
||||
openLevelPicker() {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open("difficult-help-level-picker")) return
|
||||
this.$set(this, "showLevelPicker", true)
|
||||
},
|
||||
|
||||
closeLevelPicker(afterClose = null) {
|
||||
if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.close("difficult-help-level-picker", afterClose)) return
|
||||
this.$set(this, "showLevelPicker", false)
|
||||
if (typeof afterClose === "function") afterClose()
|
||||
},
|
||||
|
||||
onLevelConfirm(option) {
|
||||
this.closeLevelPicker(() => {
|
||||
this.$set(this.formData, "level", option.value)
|
||||
})
|
||||
},
|
||||
|
||||
// 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())
|
||||
this.initLevelDict()
|
||||
if (!window.h5HistoryLayerManager) return
|
||||
this.$set(this, "historyLayerUnsubscribe", window.h5HistoryLayerManager.subscribe((stack) => {
|
||||
this.$set(this, "confirmVisible", stack.includes("difficult-help-action-confirm"))
|
||||
this.$set(this, "showLevelPicker", stack.includes("difficult-help-level-picker"))
|
||||
}))
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (typeof this.historyLayerUnsubscribe === "function") this.historyLayerUnsubscribe()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||