diff --git a/src/main/java/com/budwk/app/flow/service/FlowCommonService.java b/src/main/java/com/budwk/app/flow/service/FlowCommonService.java
index 1230331c..b77824d8 100644
--- a/src/main/java/com/budwk/app/flow/service/FlowCommonService.java
+++ b/src/main/java/com/budwk/app/flow/service/FlowCommonService.java
@@ -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())) {
diff --git a/src/main/java/com/budwk/app/zhgh/activity/workscollection/controller/ActivityWorksCollectionNewController.java b/src/main/java/com/budwk/app/zhgh/activity/workscollection/controller/ActivityWorksCollectionNewController.java
index eba3d64d..2801e4e7 100644
--- a/src/main/java/com/budwk/app/zhgh/activity/workscollection/controller/ActivityWorksCollectionNewController.java
+++ b/src/main/java/com/budwk/app/zhgh/activity/workscollection/controller/ActivityWorksCollectionNewController.java
@@ -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() {
}
diff --git a/src/main/java/com/budwk/app/zhgh/activity/workscollection/controller/ActivityWorksCollectionUploadController.java b/src/main/java/com/budwk/app/zhgh/activity/workscollection/controller/ActivityWorksCollectionUploadController.java
index 3a16dc8c..afc87e84 100644
--- a/src/main/java/com/budwk/app/zhgh/activity/workscollection/controller/ActivityWorksCollectionUploadController.java
+++ b/src/main/java/com/budwk/app/zhgh/activity/workscollection/controller/ActivityWorksCollectionUploadController.java
@@ -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);
diff --git a/src/main/java/com/budwk/app/zhgh/activity/workscollection/controller/h5/H5ActivityWorksUploadCollectionController.java b/src/main/java/com/budwk/app/zhgh/activity/workscollection/controller/h5/H5ActivityWorksUploadCollectionController.java
index d87c4573..6d604a9a 100644
--- a/src/main/java/com/budwk/app/zhgh/activity/workscollection/controller/h5/H5ActivityWorksUploadCollectionController.java
+++ b/src/main/java/com/budwk/app/zhgh/activity/workscollection/controller/h5/H5ActivityWorksUploadCollectionController.java
@@ -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"));
}//查询已结束的
diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpMineController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpMineController.java
index 6d9816e4..e03fa156 100644
--- a/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpMineController.java
+++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpMineController.java
@@ -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();
diff --git a/src/main/resources/static/assets/mobile/img/democratic/teachercongress/seat-available.png b/src/main/resources/static/assets/mobile/img/democratic/teachercongress/seat-available.png
new file mode 100644
index 00000000..e7a8468a
Binary files /dev/null and b/src/main/resources/static/assets/mobile/img/democratic/teachercongress/seat-available.png differ
diff --git a/src/main/resources/static/assets/mobile/img/democratic/teachercongress/seat-disabled.png b/src/main/resources/static/assets/mobile/img/democratic/teachercongress/seat-disabled.png
new file mode 100644
index 00000000..076d6d0f
Binary files /dev/null and b/src/main/resources/static/assets/mobile/img/democratic/teachercongress/seat-disabled.png differ
diff --git a/src/main/resources/static/assets/mobile/img/democratic/teachercongress/seat-mine.png b/src/main/resources/static/assets/mobile/img/democratic/teachercongress/seat-mine.png
new file mode 100644
index 00000000..be5c56e1
Binary files /dev/null and b/src/main/resources/static/assets/mobile/img/democratic/teachercongress/seat-mine.png differ
diff --git a/src/main/resources/static/assets/mobile/img/democratic/teachercongress/seat-occupied.png b/src/main/resources/static/assets/mobile/img/democratic/teachercongress/seat-occupied.png
new file mode 100644
index 00000000..3f367597
Binary files /dev/null and b/src/main/resources/static/assets/mobile/img/democratic/teachercongress/seat-occupied.png differ
diff --git a/src/main/resources/static/assets/mobile/img/democratic/teachercongress/seat-selected.png b/src/main/resources/static/assets/mobile/img/democratic/teachercongress/seat-selected.png
new file mode 100644
index 00000000..25979f34
Binary files /dev/null and b/src/main/resources/static/assets/mobile/img/democratic/teachercongress/seat-selected.png differ
diff --git a/src/main/resources/static/assets/mobile/img/democratic/teachercongress/seat-status-icon.png b/src/main/resources/static/assets/mobile/img/democratic/teachercongress/seat-status-icon.png
new file mode 100644
index 00000000..f23cf617
Binary files /dev/null and b/src/main/resources/static/assets/mobile/img/democratic/teachercongress/seat-status-icon.png differ
diff --git a/src/main/resources/static/assets/mobile/img/democratic/teachercongress/seat-status-icon.svg b/src/main/resources/static/assets/mobile/img/democratic/teachercongress/seat-status-icon.svg
new file mode 100644
index 00000000..bc20f7de
--- /dev/null
+++ b/src/main/resources/static/assets/mobile/img/democratic/teachercongress/seat-status-icon.svg
@@ -0,0 +1,8 @@
+
diff --git a/src/main/resources/static/assets/mobile/img/difficultHelp/difficult-help-empty.png b/src/main/resources/static/assets/mobile/img/difficultHelp/difficult-help-empty.png
new file mode 100644
index 00000000..7e7eeaab
Binary files /dev/null and b/src/main/resources/static/assets/mobile/img/difficultHelp/difficult-help-empty.png differ
diff --git a/src/main/resources/static/assets/mobile/img/unionReimburse/union-reimburse-empty.png b/src/main/resources/static/assets/mobile/img/unionReimburse/union-reimburse-empty.png
new file mode 100644
index 00000000..a3231b2f
Binary files /dev/null and b/src/main/resources/static/assets/mobile/img/unionReimburse/union-reimburse-empty.png differ
diff --git a/src/main/resources/static/components/plugins/sysFilePreview/H5Index.vue b/src/main/resources/static/components/plugins/sysFilePreview/H5Index.vue
index a721e438..7cb901a1 100644
--- a/src/main/resources/static/components/plugins/sysFilePreview/H5Index.vue
+++ b/src/main/resources/static/components/plugins/sysFilePreview/H5Index.vue
@@ -3,16 +3,16 @@
![]()
@@ -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()
}
}
}
diff --git a/src/main/resources/views/platform/zhgh/activity/workscollection/manage/index.html b/src/main/resources/views/platform/zhgh/activity/workscollection/manage/index.html
index d059200b..a4174eae 100644
--- a/src/main/resources/views/platform/zhgh/activity/workscollection/manage/index.html
+++ b/src/main/resources/views/platform/zhgh/activity/workscollection/manage/index.html
@@ -118,283 +118,7 @@ layout("/layouts/platform.html"){
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 作品类型
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 开启
- 关闭
-
-
-
-
- 取消
- {{ copyTemplateMode ? "另存为" : "保存" }}
- {{ copyTemplateMode ? "新活动提交" : "确定" }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- jpg
- jpeg
- png
- mp3
- mp4
- docx
- xlsx
- pdf
- zip
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 取消
- 确定
-
-
+
+
diff --git a/src/main/resources/views/platform/zhghh5/activity/workscollection/mine/index.html b/src/main/resources/views/platform/zhghh5/activity/workscollection/mine/index.html
index e79c0385..0933ab31 100644
--- a/src/main/resources/views/platform/zhghh5/activity/workscollection/mine/index.html
+++ b/src/main/resources/views/platform/zhghh5/activity/workscollection/mine/index.html
@@ -1,47 +1,474 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
- 编辑
-
-
-
- 删除
-
-
-
+
+
+
+
+
+
+
+ {{hasCover(row) ? '图片加载失败' : '暂无图片'}}
+
+
+
{{row.name}}
+
所属活动:{{row.activityName || '暂无活动信息'}}
+
+ 提交时间:{{$moment(row.createdAt).format('YYYY-MM-DD HH:mm')}}
+
+
+
+ 主题{{row.subjectName}}
+
+
+ 类型{{row.worksName}}
+
+
+
+
+
+
+
+
+
+
+
+
+

+
暂无作品记录
+
当前筛选条件下暂时没有已提交作品
+
+
+
+
+
+
-
@@ -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)
}
})
diff --git a/src/main/resources/views/platform/zhghh5/activity/workscollection/mine/info.js b/src/main/resources/views/platform/zhghh5/activity/workscollection/mine/info.js
index 93cda6d7..530c07ed 100644
--- a/src/main/resources/views/platform/zhghh5/activity/workscollection/mine/info.js
+++ b/src/main/resources/views/platform/zhghh5/activity/workscollection/mine/info.js
@@ -2,63 +2,189 @@ const INFO = {
template: /*language=HTML*/
`
-
-
-
-
- {{ viewData.userName }}
-
-
- {{ viewData.loginName }}
-
-
- {{ viewData.unitName }}
-
-
- {{ viewData.unionName }}
-
-
- {{ viewData.name }}
-
-
- {{ viewData.activityName }}
-
-
- {{ viewData.subjectName }}
-
-
- {{ viewData.worksName }}
-
-
- {{ viewData.description }}
-
-
-
-
-
+
`,
+ 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()
}
}
diff --git a/src/main/resources/views/platform/zhghh5/activity/workscollection/read/index.html b/src/main/resources/views/platform/zhghh5/activity/workscollection/read/index.html
index 82ded3e0..30f2ed0d 100644
--- a/src/main/resources/views/platform/zhghh5/activity/workscollection/read/index.html
+++ b/src/main/resources/views/platform/zhghh5/activity/workscollection/read/index.html
@@ -1,66 +1,495 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
点赞
+
+
+
+
+
-
-
-
取消点赞
+
+

+
暂无作品记录
+
当前筛选条件下暂时没有可阅览作品
-
-
-
+
+
+
+
+
+ {{row.worksName || '--'}}
+ {{row.userName || '--'}}
+ {{row.loginName || '--'}}
+ {{$moment(row.createdAt).format('YYYY-MM-DD')}}
+
+
+ 上传附件
+
+ 共{{getAttachmentCount(row.files)}}个附件 · 左滑查看更多
+
+
+
+
+
+
+
+
+
+
+ 查看
+
+
+
+
+ 点赞
+
+
+
+ 取消点赞
+
+
+ ♥
+
+
+
+
+
+
+
+
@@ -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)
}
})
diff --git a/src/main/resources/views/platform/zhghh5/activity/workscollection/upload/applyForm.js b/src/main/resources/views/platform/zhghh5/activity/workscollection/upload/applyForm.js
index df0a511a..4251822e 100644
--- a/src/main/resources/views/platform/zhghh5/activity/workscollection/upload/applyForm.js
+++ b/src/main/resources/views/platform/zhghh5/activity/workscollection/upload/applyForm.js
@@ -3,189 +3,539 @@ const applyForm = {
/*language=HTML*/
`
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
- 提交
-
-
-
-
+
+
`,
+ 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)
}
}
diff --git a/src/main/resources/views/platform/zhghh5/activity/workscollection/upload/index.html b/src/main/resources/views/platform/zhghh5/activity/workscollection/upload/index.html
index 555f4ed1..7a10e8a8 100644
--- a/src/main/resources/views/platform/zhghh5/activity/workscollection/upload/index.html
+++ b/src/main/resources/views/platform/zhghh5/activity/workscollection/upload/index.html
@@ -1,108 +1,690 @@
-
-
-
-
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
- {{row.activityGroupName}}
-
- {{$moment(row.startDateTime).format('MM/DD HH:mm')
- + '~' + $moment(row.endDateTime).format('MM/DD HH:mm')}}
-
-
-
-
-
-
查看介绍
+
-
-
- 去报名
-
-
-
-
-
-
-
-
{{infoRow.name}}
-
+
+
+
+
+
![]()
+
+
+ {{ hasCover(row) ? '图片加载失败' : '暂无图片' }}
+
+
+
{{ row.name }}
+
+ 征集时间:{{ $moment(row.startDateTime).format('MM/DD HH:mm') }}~{{ $moment(row.endDateTime).format('MM/DD HH:mm') }}
+
+
+
+ 面向对象{{ row.activityGroupName }}
+
+
+
+
+
+
+
+
+

+
暂无作品征集活动
+
当前筛选条件下暂时没有可展示的活动
+
+
-
-
-
diff --git a/src/main/resources/views/platform/zhghh5/dayofficework/unionReimburse/apply/index.html b/src/main/resources/views/platform/zhghh5/dayofficework/unionReimburse/apply/index.html
index 86beb5ef..aa55d246 100644
--- a/src/main/resources/views/platform/zhghh5/dayofficework/unionReimburse/apply/index.html
+++ b/src/main/resources/views/platform/zhghh5/dayofficework/unionReimburse/apply/index.html
@@ -4,12 +4,12 @@ layout("/layouts/platform_h5.html"){
-
-
+
+
+
+
@@ -985,22 +997,22 @@ layout("/layouts/platform_h5.html"){
- 保存
- 提交
- 提交
+ 保存申请
+ 提交申请
+ 提交申请
-
发票识别中...
-
+
- 上传发票文件后会自动识别发票信息;开启自动校验时会同步校验发票是否重复。
+
+
+
diff --git a/src/main/resources/views/platform/zhghh5/dayofficework/unionReimburse/collect/index.html b/src/main/resources/views/platform/zhghh5/dayofficework/unionReimburse/collect/index.html
index be53964a..093cd660 100644
--- a/src/main/resources/views/platform/zhghh5/dayofficework/unionReimburse/collect/index.html
+++ b/src/main/resources/views/platform/zhghh5/dayofficework/unionReimburse/collect/index.html
@@ -2,71 +2,57 @@
layout("/layouts/platform_h5.html"){
#-->
-
-
-
+
+
-
-
-
-
+
+
+
+
+
+
+
-
-
+
+
+
- {{row.loginName}}
- {{row.userName}}
- {{row.unionName}}
- {{row.unitName}}
- {{formatCreateTime(row.createTime)}}
- {{getReimburseProjectName(row.reimburseProject)}}
- {{getRemarkText(row)}}
-
- {{getStateName(row.stateId)}}
-
+ {{getReimburseProjectName(row.reimburseProject) || '--'}}
+ {{getRemarkText(row) || '--'}}
+ {{row.unionName || '--'}}
+ {{row.unitName || '--'}}
+ {{formatCreateTime(row.createTime) || '--'}}
+ {{formatMoney(row.money)}}
-
+
查看
-
-
+
+
撤回
-
+
删除
+

暂无报销统计记录
当前筛选条件下暂时没有报销记录
+
-
+
+
diff --git a/src/main/resources/views/platform/zhghh5/dayofficework/unionReimburse/common/unionReimburse.css b/src/main/resources/views/platform/zhghh5/dayofficework/unionReimburse/common/unionReimburse.css
new file mode 100644
index 00000000..da2ab30d
--- /dev/null
+++ b/src/main/resources/views/platform/zhghh5/dayofficework/unionReimburse/common/unionReimburse.css
@@ -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%; }
+}
diff --git a/src/main/resources/views/platform/zhghh5/dayofficework/unionReimburse/info.js b/src/main/resources/views/platform/zhghh5/dayofficework/unionReimburse/info.js
index e2dc4636..e999bd54 100644
--- a/src/main/resources/views/platform/zhghh5/dayofficework/unionReimburse/info.js
+++ b/src/main/resources/views/platform/zhghh5/dayofficework/unionReimburse/info.js
@@ -2,14 +2,10 @@ const UNION_REIMBURSE_INFO = {
template:
/*language=HTML*/
`
-
-
-