疗休养1.0版本
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
ALTER TABLE activity_user_scope
|
||||
ADD COLUMN groupType INT(2) NULL COMMENT '分组类型 1.结果分组 2.SQL条件分组' AFTER userId;
|
||||
|
||||
ALTER TABLE activity_user_scope
|
||||
ADD COLUMN groupSql LONGTEXT NULL COMMENT 'SQL条件分组保存的查询SQL' AFTER groupType;
|
||||
|
||||
ALTER TABLE activity_user_scope
|
||||
ADD INDEX INDEX_ACTIVITY_USER_SCOPE_GROUPID_USERID (groupId, userId);
|
||||
@@ -0,0 +1,122 @@
|
||||
-- 普惠疗休养平台电脑端菜单。
|
||||
-- 使用 permission 做幂等判断,避免同一环境重复执行时插入重复菜单。
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bb1a10001',
|
||||
'',
|
||||
LPAD(IFNULL(MAX(CAST(path AS UNSIGNED)), 0) + 1, 4, '0'),
|
||||
'普惠疗休养',
|
||||
'Tour',
|
||||
'menu',
|
||||
'',
|
||||
'',
|
||||
'ti-map-alt',
|
||||
1,
|
||||
0,
|
||||
'tour',
|
||||
NULL,
|
||||
991,
|
||||
1,
|
||||
'',
|
||||
UNIX_TIMESTAMP(NOW()) * 1000,
|
||||
'',
|
||||
UNIX_TIMESTAMP(NOW()) * 1000,
|
||||
0,
|
||||
'PC',
|
||||
NULL,
|
||||
NULL,
|
||||
'p',
|
||||
0,
|
||||
0
|
||||
FROM sys_menu
|
||||
WHERE (parentId = '' OR parentId IS NULL)
|
||||
AND CHAR_LENGTH(path) = 4
|
||||
HAVING NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour') t);
|
||||
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT 'b7c63f0c73a44a9a8c4f3d3bb1a10002', p.id, CONCAT(p.path, '0001'), '疗休养设置', 'Tour Setting', 'menu', '/platform/tour/setting', 'data-pjax', '', 1, 0, 'tour.setting', NULL, 1, 0, '', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0, 'PC', NULL, NULL, 'l', 0, 0
|
||||
FROM sys_menu p
|
||||
WHERE p.permission = 'tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour.setting') t);
|
||||
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT 'b7c63f0c73a44a9a8c4f3d3bb1a10003', p.id, CONCAT(p.path, '0002'), '旅行社管理', 'Travel Agency', 'menu', '/platform/tour/travelAgency', 'data-pjax', '', 1, 0, 'tour.travelAgency', NULL, 2, 0, '', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0, 'PC', NULL, NULL, 'l', 0, 0
|
||||
FROM sys_menu p
|
||||
WHERE p.permission = 'tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour.travelAgency') t);
|
||||
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT 'b7c63f0c73a44a9a8c4f3d3bb1a10004', p.id, CONCAT(p.path, '0003'), '线路管理', 'Route Manage', 'menu', '/platform/tour/route', 'data-pjax', '', 1, 0, 'tour.route', NULL, 3, 0, '', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0, 'PC', NULL, NULL, 'x', 0, 0
|
||||
FROM sys_menu p
|
||||
WHERE p.permission = 'tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour.route') t);
|
||||
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT 'b7c63f0c73a44a9a8c4f3d3bb1a10005', p.id, CONCAT(p.path, '0004'), '疗休养事项', 'Tour Matter', 'menu', '/platform/tour/matter', 'data-pjax', '', 1, 0, 'tour.matter', NULL, 4, 0, '', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0, 'PC', NULL, NULL, 'l', 0, 0
|
||||
FROM sys_menu p
|
||||
WHERE p.permission = 'tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour.matter') t);
|
||||
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT 'b7c63f0c73a44a9a8c4f3d3bb1a10006', p.id, CONCAT(p.path, '0005'), '疗休养报名', 'Tour Signup', 'menu', '/platform/tour/signup', 'data-pjax', '', 1, 0, 'tour.signup', NULL, 5, 0, '', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0, 'PC', NULL, NULL, 'l', 0, 0
|
||||
FROM sys_menu p
|
||||
WHERE p.permission = 'tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour.signup') t);
|
||||
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT 'b7c63f0c73a44a9a8c4f3d3bb1a10008', p.id, CONCAT(p.path, '0006'), '我的报名', 'My Signup', 'menu', '/platform/tour/mysignup', 'data-pjax', '', 1, 0, 'tour.mysignup', NULL, 6, 0, '', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0, 'PC', NULL, NULL, 'w', 0, 0
|
||||
FROM sys_menu p
|
||||
WHERE p.permission = 'tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour.mysignup') t);
|
||||
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT 'b7c63f0c73a44a9a8c4f3d3bb1a10009', p.id, CONCAT(p.path, '0007'), '分工会查询', 'Union Ledger', 'menu', '/platform/tour/unionledger', 'data-pjax', '', 1, 0, 'tour.unionledger', NULL, 7, 0, '', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0, 'PC', NULL, NULL, 'f', 0, 0
|
||||
FROM sys_menu p
|
||||
WHERE p.permission = 'tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour.unionledger') t);
|
||||
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT 'b7c63f0c73a44a9a8c4f3d3bb1a10011', p.id, CONCAT(p.path, '0010'), '分工会审核', 'Union Approval', 'menu', '/platform/tour/unionApproval', 'data-pjax', '', 1, 0, 'tour.unionApproval', NULL, 8, 0, '', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0, 'PC', NULL, NULL, 'f', 0, 0
|
||||
FROM sys_menu p
|
||||
WHERE p.permission = 'tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour.unionApproval') t);
|
||||
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT 'b7c63f0c73a44a9a8c4f3d3bb1a10012', p.id, CONCAT(p.path, '0011'), '校工会审核', 'School Union Approval', 'menu', '/platform/tour/schoolUnionApproval', 'data-pjax', '', 1, 0, 'tour.schoolUnionApproval', NULL, 9, 0, '', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0, 'PC', NULL, NULL, 'x', 0, 0
|
||||
FROM sys_menu p
|
||||
WHERE p.permission = 'tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour.schoolUnionApproval') t);
|
||||
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT 'b7c63f0c73a44a9a8c4f3d3bb1a10007', p.id, CONCAT(p.path, '0008'), '疗休养台账', 'Tour Ledger', 'menu', '/platform/tour/ledger', 'data-pjax', '', 1, 0, 'tour.ledger', NULL, 10, 0, '', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0, 'PC', NULL, NULL, 'l', 0, 0
|
||||
FROM sys_menu p
|
||||
WHERE p.permission = 'tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour.ledger') t);
|
||||
|
||||
INSERT INTO sys_menu (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService)
|
||||
SELECT 'b7c63f0c73a44a9a8c4f3d3bb1a10010', p.id, CONCAT(p.path, '0009'), '线路成团', 'Tour Group', 'menu', '/platform/tour/group', 'data-pjax', '', 1, 0, 'tour.group', NULL, 11, 0, '', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0, 'PC', NULL, NULL, 'x', 0, 0
|
||||
FROM sys_menu p
|
||||
WHERE p.permission = 'tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM sys_menu WHERE permission = 'tour.group') t);
|
||||
|
||||
-- 给系统管理员默认授权,其他角色可在角色管理中按需分配。
|
||||
INSERT INTO sys_role_menu (roleId, menuId)
|
||||
SELECT r.id, m.id
|
||||
FROM sys_role r
|
||||
JOIN sys_menu m ON m.permission IN (
|
||||
'tour',
|
||||
'tour.setting',
|
||||
'tour.travelAgency',
|
||||
'tour.route',
|
||||
'tour.matter',
|
||||
'tour.signup',
|
||||
'tour.group',
|
||||
'tour.mysignup',
|
||||
'tour.unionledger',
|
||||
'tour.unionApproval',
|
||||
'tour.schoolUnionApproval',
|
||||
'tour.ledger'
|
||||
)
|
||||
LEFT JOIN sys_role_menu rm ON rm.roleId = r.id AND rm.menuId = m.id
|
||||
WHERE r.code = 'SYSADMIN'
|
||||
AND rm.roleId IS NULL;
|
||||
@@ -0,0 +1,253 @@
|
||||
-- 普惠疗休养系统字典初始化。
|
||||
-- 执行后可在 /platform/sys/dict 页面看到:疗休养(Tour) -> 组织形式/疗休养类型/线路类型/床型。
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict001', '', '9500', '疗休养', '普惠疗休养平台字典', 'Tour', 0, 9500, 1,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'Tour') t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict002', p.id, CONCAT(p.path, '0001'), '组织形式', '疗休养组织形式', 'organizationType', 0, 1, 1,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'Tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'organizationType' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict003', p.id, CONCAT(p.path, '0001'), '校工会组织', '疗休养组织形式', 'schoolUnion', 0, 1, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'organizationType'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'schoolUnion' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict004', p.id, CONCAT(p.path, '0002'), '分工会组织', '疗休养组织形式', 'branchUnion', 0, 2, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'organizationType'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'branchUnion' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict005', p.id, CONCAT(p.path, '0003'), '个人组织', '疗休养组织形式', 'personal', 0, 3, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'organizationType'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'personal' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict006', p.id, CONCAT(p.path, '0002'), '疗休养类型', '疗休养类型', 'tourType', 0, 2, 1,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'Tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'tourType' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict007', p.id, CONCAT(p.path, '0001'), '普惠性疗休养', '疗休养类型', 'inclusiveTour', 0, 1, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'tourType'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'inclusiveTour' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict008', p.id, CONCAT(p.path, '0002'), '优秀职工疗休养', '疗休养类型', 'excellentWorkerTour', 0, 2, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'tourType'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'excellentWorkerTour' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict009', p.id, CONCAT(p.path, '0003'), '线路类型', '线路类型', 'lineType', 0, 3, 1,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'Tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'lineType' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict010', p.id, CONCAT(p.path, '0001'), '省内线路', '线路类型', 'inProvinceLine', 0, 1, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'lineType'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'inProvinceLine' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict011', p.id, CONCAT(p.path, '0002'), '省外线路', '线路类型', 'outProvinceLine', 0, 2, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'lineType'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'outProvinceLine' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict020', p.id, CONCAT(p.path, '0004'), '床型', '床型', 'bedType', 0, 4, 1,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'Tour'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'bedType' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict021', p.id, CONCAT(p.path, '0001'), '双人床', '床型', 'doubleBed', 0, 1, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'bedType'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'doubleBed' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict022', p.id, CONCAT(p.path, '0002'), '单人床', '床型', 'singleBed', 0, 2, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'bedType'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'singleBed' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict023', p.id, CONCAT(p.path, '0003'), '大床', '床型', 'kingBed', 0, 3, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'bedType'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'kingBed' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict012', '', '9600', '亲属关系', '亲属关系', 'familyRelationship', 0, 9600, 1,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
WHERE NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'familyRelationship') t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict013', p.id, CONCAT(p.path, '0001'), '直系亲属', '亲属关系', 'directRelative', 0, 1, 1,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'familyRelationship'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'directRelative' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict014', p.id, CONCAT(p.path, '0001'), '父亲', '直系亲属', 'father', 0, 1, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'directRelative'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'father' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict015', p.id, CONCAT(p.path, '0002'), '母亲', '直系亲属', 'mother', 0, 2, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'directRelative'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'mother' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict016', p.id, CONCAT(p.path, '0003'), '丈夫', '直系亲属', 'husband', 0, 3, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'directRelative'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'husband' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict017', p.id, CONCAT(p.path, '0004'), '妻子', '直系亲属', 'wife', 0, 4, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'directRelative'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'wife' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict018', p.id, CONCAT(p.path, '0005'), '儿子', '直系亲属', 'son', 0, 5, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'directRelative'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'son' AND `parentId` = p.id) t);
|
||||
|
||||
INSERT INTO `sys_dict` (
|
||||
`id`, `parentId`, `path`, `name`, `remark`, `code`, `disabled`, `location`, `hasChildren`,
|
||||
`createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`
|
||||
)
|
||||
SELECT
|
||||
'b7c63f0c73a44a9a8c4f3d3bdict019', p.id, CONCAT(p.path, '0006'), '女儿', '直系亲属', 'daughter', 0, 6, 0,
|
||||
'', UNIX_TIMESTAMP(NOW()) * 1000, '', UNIX_TIMESTAMP(NOW()) * 1000, 0
|
||||
FROM `sys_dict` p
|
||||
WHERE p.`code` = 'directRelative'
|
||||
AND NOT EXISTS (SELECT 1 FROM (SELECT id FROM `sys_dict` WHERE `code` = 'daughter' AND `parentId` = p.id) t);
|
||||
|
||||
UPDATE `sys_dict` SET `hasChildren` = 1 WHERE `code` IN ('Tour', 'organizationType', 'tourType', 'lineType', 'bedType', 'familyRelationship', 'directRelative');
|
||||
@@ -0,0 +1,7 @@
|
||||
-- Add matter reference so signup records are unique per travel period/matter.
|
||||
ALTER TABLE `tour_ledger`
|
||||
ADD COLUMN `matterId` varchar(32) DEFAULT NULL COMMENT '报名事项ID' AFTER `signupTime`;
|
||||
|
||||
ALTER TABLE `tour_ledger`
|
||||
ADD KEY `idx_tour_ledger_matter` (`matterId`),
|
||||
ADD KEY `idx_tour_ledger_matter_job` (`matterId`, `jobNo`);
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE `tour_ledger`
|
||||
ADD COLUMN `overCostReimbursed` tinyint(1) DEFAULT 0 COMMENT '报销超出费用' AFTER `reimbursed`;
|
||||
@@ -0,0 +1,9 @@
|
||||
-- 疗休养台账查询加速索引。
|
||||
ALTER TABLE `tour_ledger`
|
||||
ADD KEY `idx_tour_ledger_year_signup` (`year`, `delFlag`, `signupTime`),
|
||||
ADD KEY `idx_tour_ledger_year_line` (`year`, `lineId`, `delFlag`),
|
||||
ADD KEY `idx_tour_ledger_year_union_type` (`year`, `unionId`, `lineType`, `delFlag`),
|
||||
ADD KEY `idx_tour_ledger_year_job` (`year`, `jobNo`, `delFlag`);
|
||||
|
||||
ALTER TABLE `wf_process_instance`
|
||||
ADD KEY `idx_wf_process_instance_business_state` (`businessNo`, `state`);
|
||||
@@ -0,0 +1,21 @@
|
||||
-- 直系亲属线路报名信息表,独立于普通携带亲属信息表。
|
||||
CREATE TABLE IF NOT EXISTS `tour_ledger_direct_relative` (
|
||||
`id` varchar(32) NOT NULL COMMENT 'ID',
|
||||
`ledgerId` varchar(32) DEFAULT NULL COMMENT '台账ID',
|
||||
`relativeName` varchar(100) DEFAULT NULL COMMENT '亲属姓名',
|
||||
`unitName` varchar(100) DEFAULT NULL COMMENT '所在单位',
|
||||
`relationshipCode` varchar(50) DEFAULT NULL COMMENT '亲属关系编码',
|
||||
`relationshipName` varchar(50) DEFAULT NULL COMMENT '亲属关系',
|
||||
`lineId` varchar(32) DEFAULT NULL COMMENT '线路ID',
|
||||
`lineName` varchar(100) DEFAULT NULL COMMENT '线路名称',
|
||||
`travelStartTime` varchar(20) DEFAULT NULL COMMENT '出行开始日期',
|
||||
`travelEndTime` varchar(20) DEFAULT NULL COMMENT '出行结束日期',
|
||||
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||
`createdAt` bigint DEFAULT NULL COMMENT '创建时间',
|
||||
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间',
|
||||
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_tour_ledger_direct_relative_ledger` (`ledgerId`),
|
||||
KEY `idx_tour_ledger_direct_relative_line` (`lineId`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='普惠疗休养直系亲属线路报名信息';
|
||||
@@ -0,0 +1,10 @@
|
||||
-- 线路管理增加创建人和所在单位业务字段。
|
||||
ALTER TABLE `tour_line`
|
||||
ADD COLUMN `creatorUserId` varchar(32) DEFAULT NULL COMMENT '创建人ID' AFTER `travelAgencyId`,
|
||||
ADD COLUMN `creatorName` varchar(100) DEFAULT NULL COMMENT '创建人' AFTER `creatorUserId`,
|
||||
ADD COLUMN `unitId` varchar(32) DEFAULT NULL COMMENT '所在单位ID' AFTER `creatorName`,
|
||||
ADD COLUMN `unitName` varchar(100) DEFAULT NULL COMMENT '所在单位' AFTER `unitId`;
|
||||
|
||||
ALTER TABLE `tour_line`
|
||||
ADD KEY `idx_tour_line_creator` (`creatorUserId`),
|
||||
ADD KEY `idx_tour_line_unit` (`unitId`);
|
||||
@@ -0,0 +1,3 @@
|
||||
-- 线路管理增加是否直系亲属线路字段,默认否。
|
||||
ALTER TABLE `tour_line`
|
||||
ADD COLUMN `directFamilyUnitLine` tinyint(1) DEFAULT 0 COMMENT '是否直系亲属线路' AFTER `openFlag`;
|
||||
@@ -0,0 +1,3 @@
|
||||
-- 线路管理增加是否对外开放字段,默认是。
|
||||
ALTER TABLE `tour_line`
|
||||
ADD COLUMN `openFlag` tinyint(1) DEFAULT 1 COMMENT '是否对外开放' AFTER `mobileThumb`;
|
||||
@@ -0,0 +1,7 @@
|
||||
-- 疗休养事项增加创建人字段。
|
||||
ALTER TABLE `tour_matter`
|
||||
ADD COLUMN `creatorUserId` varchar(32) DEFAULT NULL COMMENT '创建人ID' AFTER `settingId`,
|
||||
ADD COLUMN `creatorName` varchar(100) DEFAULT NULL COMMENT '创建人' AFTER `creatorUserId`;
|
||||
|
||||
ALTER TABLE `tour_matter`
|
||||
ADD KEY `idx_tour_matter_creator` (`creatorUserId`);
|
||||
@@ -0,0 +1,26 @@
|
||||
-- 疗休养事项批次表。
|
||||
CREATE TABLE IF NOT EXISTS `tour_matter_batch` (
|
||||
`id` varchar(32) NOT NULL COMMENT 'ID',
|
||||
`matterId` varchar(32) DEFAULT NULL COMMENT '事项ID',
|
||||
`lineId` varchar(32) DEFAULT NULL COMMENT '线路ID',
|
||||
`batchName` varchar(100) DEFAULT NULL COMMENT '批次名称',
|
||||
`signupStartTime` varchar(20) DEFAULT NULL COMMENT '报名开始时间',
|
||||
`signupEndTime` varchar(20) DEFAULT NULL COMMENT '报名结束时间',
|
||||
`travelStartTime` varchar(20) DEFAULT NULL COMMENT '出行开始时间',
|
||||
`travelEndTime` varchar(20) DEFAULT NULL COMMENT '出行结束时间',
|
||||
`changeDeadline` varchar(20) DEFAULT NULL COMMENT '变更截止时间',
|
||||
`contactName` varchar(30) DEFAULT NULL COMMENT '联系人',
|
||||
`contactPhone` varchar(30) DEFAULT NULL COMMENT '联系方式',
|
||||
`minGroupPeople` int DEFAULT NULL COMMENT '最少成团人数',
|
||||
`maxGroupPeople` int DEFAULT NULL COMMENT '最多成团人数',
|
||||
`estimatedCost` decimal(10,2) DEFAULT NULL COMMENT '预计费用',
|
||||
`enabled` tinyint(1) DEFAULT 1 COMMENT '状态',
|
||||
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||
`createdAt` bigint DEFAULT NULL COMMENT '创建时间',
|
||||
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间',
|
||||
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_tour_matter_batch_matter` (`matterId`),
|
||||
KEY `idx_tour_matter_batch_line` (`lineId`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='普惠疗休养事项批次';
|
||||
@@ -0,0 +1,25 @@
|
||||
-- 疗休养事项表。
|
||||
CREATE TABLE IF NOT EXISTS `tour_matter` (
|
||||
`id` varchar(32) NOT NULL COMMENT 'ID',
|
||||
`year` int DEFAULT NULL COMMENT '年度',
|
||||
`matterName` varchar(100) DEFAULT NULL COMMENT '事项名称',
|
||||
`settingId` varchar(32) DEFAULT NULL COMMENT '疗休养配置ID',
|
||||
`creatorUserId` varchar(32) DEFAULT NULL COMMENT '创建人ID',
|
||||
`creatorName` varchar(100) DEFAULT NULL COMMENT '创建人',
|
||||
`unionId` varchar(32) DEFAULT NULL COMMENT '所属工会ID',
|
||||
`organizationType` varchar(100) DEFAULT NULL COMMENT '组织形式',
|
||||
`mobileThumb` varchar(500) DEFAULT NULL COMMENT '移动端缩略图',
|
||||
`enabled` tinyint(1) DEFAULT 1 COMMENT '事项状态',
|
||||
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||
`createdAt` bigint DEFAULT NULL COMMENT '创建时间',
|
||||
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间',
|
||||
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_tour_matter_year_name` (`year`, `matterName`),
|
||||
KEY `idx_tour_matter_year` (`year`),
|
||||
KEY `idx_tour_matter_creator` (`creatorUserId`),
|
||||
KEY `idx_tour_matter_setting` (`settingId`),
|
||||
KEY `idx_tour_matter_union` (`unionId`),
|
||||
KEY `idx_tour_matter_org_type` (`organizationType`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='普惠疗休养事项';
|
||||
@@ -0,0 +1,6 @@
|
||||
-- Add activity user scope reference for tour settings.
|
||||
ALTER TABLE `tour_setting`
|
||||
ADD COLUMN `activityGroupId` varchar(32) DEFAULT NULL COMMENT '可参加人员范围ID' AFTER `tourType`;
|
||||
|
||||
ALTER TABLE `tour_setting`
|
||||
ADD KEY `idx_tour_setting_activity_group` (`activityGroupId`);
|
||||
@@ -0,0 +1,3 @@
|
||||
-- 疗休养配置增加周期允许次数字段。
|
||||
ALTER TABLE `tour_setting`
|
||||
ADD COLUMN `cycleAllowedTimes` int DEFAULT NULL COMMENT '周期允许次数' AFTER `cycleTotalCost`;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE `tour_setting`
|
||||
ADD COLUMN `cycleTotalCost` int DEFAULT NULL COMMENT '周期内总费用' AFTER `cycleEndYear`;
|
||||
@@ -0,0 +1,4 @@
|
||||
-- Add optional cycle year range for tour settings.
|
||||
ALTER TABLE `tour_setting`
|
||||
ADD COLUMN `cycleStartYear` int DEFAULT NULL COMMENT '周期开始年度' AFTER `outProvinceRatio`,
|
||||
ADD COLUMN `cycleEndYear` int DEFAULT NULL COMMENT '周期结束年度' AFTER `cycleStartYear`;
|
||||
@@ -0,0 +1,3 @@
|
||||
-- 疗休养配置增加是否填报床位信息字段,默认开启以兼容历史配置。
|
||||
ALTER TABLE `tour_setting`
|
||||
ADD COLUMN `fillBedInfo` tinyint(1) DEFAULT 1 COMMENT '是否填报床位信息' AFTER `allowFamily`;
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE `tour_setting`
|
||||
ADD COLUMN `outProvinceRatioType` varchar(50) DEFAULT '当年报名人数' COMMENT '省外人数占比类型' AFTER `outProvinceRatio`,
|
||||
ADD COLUMN `outProvinceFixedPeople` int DEFAULT 0 COMMENT '省外固定人数' AFTER `outProvinceRatioType`;
|
||||
@@ -0,0 +1,183 @@
|
||||
-- 普惠疗休养基础配置表。
|
||||
-- 若生产环境未开启 Nutz 自动建表,请先执行本脚本再使用“疗休养设置”菜单。
|
||||
CREATE TABLE IF NOT EXISTS `tour_setting` (
|
||||
`id` varchar(32) NOT NULL COMMENT 'ID',
|
||||
`year` int DEFAULT NULL COMMENT '年度',
|
||||
`configName` varchar(100) DEFAULT NULL COMMENT '疗休养配置名称',
|
||||
`tourType` varchar(50) DEFAULT NULL COMMENT '疗休养类型',
|
||||
`activityGroupId` varchar(32) DEFAULT NULL COMMENT '可参加人员范围ID',
|
||||
`sortNo` int DEFAULT NULL COMMENT '排序编号',
|
||||
`minGroupPeople` int DEFAULT NULL COMMENT '最少成团人数',
|
||||
`maxGroupPeople` int DEFAULT NULL COMMENT '最多成团人数',
|
||||
`outProvinceYears` int DEFAULT NULL COMMENT '省外几年去一次',
|
||||
`outProvinceRatio` decimal(10,2) DEFAULT NULL COMMENT '省外人数占比',
|
||||
`outProvinceRatioType` varchar(50) DEFAULT '当年报名人数' COMMENT '省外人数占比类型',
|
||||
`outProvinceFixedPeople` int DEFAULT 0 COMMENT '省外固定人数',
|
||||
`cycleStartYear` int DEFAULT NULL COMMENT '周期开始年度',
|
||||
`cycleEndYear` int DEFAULT NULL COMMENT '周期结束年度',
|
||||
`cycleTotalCost` int DEFAULT NULL COMMENT '周期内总费用',
|
||||
`cycleAllowedTimes` int DEFAULT NULL COMMENT '周期允许次数',
|
||||
`allowFamily` tinyint(1) DEFAULT 0 COMMENT '是否允许携带家属',
|
||||
`fillBedInfo` tinyint(1) DEFAULT 1 COMMENT '是否填报床位信息',
|
||||
`enabled` tinyint(1) DEFAULT 1 COMMENT '是否启用',
|
||||
`serviceNotice` text COMMENT '服务须知',
|
||||
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||
`createdAt` bigint DEFAULT NULL COMMENT '创建时间',
|
||||
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间',
|
||||
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_tour_setting_year` (`year`),
|
||||
KEY `idx_tour_setting_activity_group` (`activityGroupId`),
|
||||
KEY `idx_tour_setting_sort` (`sortNo`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='普惠疗休养配置';
|
||||
|
||||
-- 疗休养配置标段表。
|
||||
-- 标段先挂在配置上维护,后续线路、旅行社、报名等模块可继续通过 lotId 做业务关联。
|
||||
CREATE TABLE IF NOT EXISTS `tour_setting_lot` (
|
||||
`id` varchar(32) NOT NULL COMMENT 'ID',
|
||||
`settingId` varchar(32) DEFAULT NULL COMMENT '所属配置ID',
|
||||
`lotName` varchar(50) DEFAULT NULL COMMENT '标段名称',
|
||||
`lotValue` varchar(50) DEFAULT NULL COMMENT '标段值',
|
||||
`activityCost` int DEFAULT NULL COMMENT '标段费用',
|
||||
`allowOverReimbursement` tinyint(1) DEFAULT 0 COMMENT '允许超出报销',
|
||||
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||
`createdAt` bigint DEFAULT NULL COMMENT '创建时间',
|
||||
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间',
|
||||
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_tour_setting_lot_setting` (`settingId`),
|
||||
KEY `idx_tour_setting_lot_value` (`lotValue`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='普惠疗休养配置标段';
|
||||
|
||||
-- 旅行社管理表。
|
||||
CREATE TABLE IF NOT EXISTS `tour_travel_agency` (
|
||||
`id` varchar(32) NOT NULL COMMENT 'ID',
|
||||
`year` int DEFAULT NULL COMMENT '年度',
|
||||
`agencyCode` varchar(50) DEFAULT NULL COMMENT '旅行社编号',
|
||||
`agencyName` varchar(100) DEFAULT NULL COMMENT '旅行社名称',
|
||||
`contactName` varchar(30) DEFAULT NULL COMMENT '联系人',
|
||||
`contactPhone` varchar(30) DEFAULT NULL COMMENT '联系人手机',
|
||||
`email` varchar(100) DEFAULT NULL COMMENT '邮箱',
|
||||
`remark` text COMMENT '备注',
|
||||
`mobileThumb` varchar(500) DEFAULT NULL COMMENT '移动端缩略图',
|
||||
`enabled` tinyint(1) DEFAULT 1 COMMENT '激活状态',
|
||||
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||
`createdAt` bigint DEFAULT NULL COMMENT '创建时间',
|
||||
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间',
|
||||
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_tour_travel_agency_year_code` (`year`, `agencyCode`),
|
||||
KEY `idx_tour_travel_agency_name` (`agencyName`),
|
||||
KEY `idx_tour_travel_agency_contact` (`contactName`, `contactPhone`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='普惠疗休养旅行社';
|
||||
|
||||
-- 线路管理表。
|
||||
CREATE TABLE IF NOT EXISTS `tour_line` (
|
||||
`id` varchar(32) NOT NULL COMMENT 'ID',
|
||||
`year` int DEFAULT NULL COMMENT '创建年度',
|
||||
`lineCode` varchar(50) DEFAULT NULL COMMENT '线路编号',
|
||||
`lineName` varchar(100) DEFAULT NULL COMMENT '线路名称',
|
||||
`travelAgencyId` varchar(32) DEFAULT NULL COMMENT '旅行社ID',
|
||||
`creatorUserId` varchar(32) DEFAULT NULL COMMENT '创建人ID',
|
||||
`creatorName` varchar(100) DEFAULT NULL COMMENT '创建人',
|
||||
`unitId` varchar(32) DEFAULT NULL COMMENT '所在单位ID',
|
||||
`unitName` varchar(100) DEFAULT NULL COMMENT '所在单位',
|
||||
`lineType` varchar(50) DEFAULT NULL COMMENT '线路类型',
|
||||
`lotId` varchar(32) DEFAULT NULL COMMENT '时间标段ID',
|
||||
`lineContent` text COMMENT '线路内容',
|
||||
`mobileThumb` varchar(500) DEFAULT NULL COMMENT '移动端缩略图',
|
||||
`openFlag` tinyint(1) DEFAULT 1 COMMENT '是否对外开放',
|
||||
`directFamilyUnitLine` tinyint(1) DEFAULT 0 COMMENT '是否直系亲属线路',
|
||||
`enabled` tinyint(1) DEFAULT 1 COMMENT '激活状态',
|
||||
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||
`createdAt` bigint DEFAULT NULL COMMENT '创建时间',
|
||||
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间',
|
||||
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_tour_line_year_code` (`year`, `lineCode`),
|
||||
KEY `idx_tour_line_year` (`year`),
|
||||
KEY `idx_tour_line_name` (`lineName`),
|
||||
KEY `idx_tour_line_agency` (`travelAgencyId`),
|
||||
KEY `idx_tour_line_creator` (`creatorUserId`),
|
||||
KEY `idx_tour_line_unit` (`unitId`),
|
||||
KEY `idx_tour_line_lot` (`lotId`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='普惠疗休养线路';
|
||||
|
||||
-- 疗休养事项表。
|
||||
CREATE TABLE IF NOT EXISTS `tour_matter` (
|
||||
`id` varchar(32) NOT NULL COMMENT 'ID',
|
||||
`year` int DEFAULT NULL COMMENT '年度',
|
||||
`matterName` varchar(100) DEFAULT NULL COMMENT '事项名称',
|
||||
`settingId` varchar(32) DEFAULT NULL COMMENT '疗休养配置ID',
|
||||
`creatorUserId` varchar(32) DEFAULT NULL COMMENT '创建人ID',
|
||||
`creatorName` varchar(100) DEFAULT NULL COMMENT '创建人',
|
||||
`unionId` varchar(32) DEFAULT NULL COMMENT '所属工会ID',
|
||||
`organizationType` varchar(100) DEFAULT NULL COMMENT '组织形式',
|
||||
`mobileThumb` varchar(500) DEFAULT NULL COMMENT '移动端缩略图',
|
||||
`enabled` tinyint(1) DEFAULT 1 COMMENT '事项状态',
|
||||
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||
`createdAt` bigint DEFAULT NULL COMMENT '创建时间',
|
||||
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间',
|
||||
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_tour_matter_year_name` (`year`, `matterName`),
|
||||
KEY `idx_tour_matter_year` (`year`),
|
||||
KEY `idx_tour_matter_creator` (`creatorUserId`),
|
||||
KEY `idx_tour_matter_setting` (`settingId`),
|
||||
KEY `idx_tour_matter_union` (`unionId`),
|
||||
KEY `idx_tour_matter_org_type` (`organizationType`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='普惠疗休养事项';
|
||||
|
||||
-- 疗休养事项批次表。
|
||||
CREATE TABLE IF NOT EXISTS `tour_matter_batch` (
|
||||
`id` varchar(32) NOT NULL COMMENT 'ID',
|
||||
`matterId` varchar(32) DEFAULT NULL COMMENT '事项ID',
|
||||
`lineId` varchar(32) DEFAULT NULL COMMENT '线路ID',
|
||||
`batchName` varchar(100) DEFAULT NULL COMMENT '批次名称',
|
||||
`signupStartTime` varchar(20) DEFAULT NULL COMMENT '报名开始时间',
|
||||
`signupEndTime` varchar(20) DEFAULT NULL COMMENT '报名结束时间',
|
||||
`travelStartTime` varchar(20) DEFAULT NULL COMMENT '出行开始时间',
|
||||
`travelEndTime` varchar(20) DEFAULT NULL COMMENT '出行结束时间',
|
||||
`changeDeadline` varchar(20) DEFAULT NULL COMMENT '变更截止时间',
|
||||
`contactName` varchar(30) DEFAULT NULL COMMENT '联系人',
|
||||
`contactPhone` varchar(30) DEFAULT NULL COMMENT '联系方式',
|
||||
`minGroupPeople` int DEFAULT NULL COMMENT '最少成团人数',
|
||||
`maxGroupPeople` int DEFAULT NULL COMMENT '最多成团人数',
|
||||
`estimatedCost` decimal(10,2) DEFAULT NULL COMMENT '预计费用',
|
||||
`enabled` tinyint(1) DEFAULT 1 COMMENT '状态',
|
||||
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||
`createdAt` bigint DEFAULT NULL COMMENT '创建时间',
|
||||
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间',
|
||||
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_tour_matter_batch_matter` (`matterId`),
|
||||
KEY `idx_tour_matter_batch_line` (`lineId`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='普惠疗休养事项批次';
|
||||
|
||||
-- 直系亲属线路报名信息表。
|
||||
CREATE TABLE IF NOT EXISTS `tour_ledger_direct_relative` (
|
||||
`id` varchar(32) NOT NULL COMMENT 'ID',
|
||||
`ledgerId` varchar(32) DEFAULT NULL COMMENT '台账ID',
|
||||
`relativeName` varchar(100) DEFAULT NULL COMMENT '亲属姓名',
|
||||
`unitName` varchar(100) DEFAULT NULL COMMENT '所在单位',
|
||||
`relationshipCode` varchar(50) DEFAULT NULL COMMENT '亲属关系编码',
|
||||
`relationshipName` varchar(50) DEFAULT NULL COMMENT '亲属关系',
|
||||
`lineId` varchar(32) DEFAULT NULL COMMENT '线路ID',
|
||||
`lineName` varchar(100) DEFAULT NULL COMMENT '线路名称',
|
||||
`travelStartTime` varchar(20) DEFAULT NULL COMMENT '出行开始日期',
|
||||
`travelEndTime` varchar(20) DEFAULT NULL COMMENT '出行结束日期',
|
||||
`createdBy` varchar(32) DEFAULT NULL COMMENT '创建人',
|
||||
`createdAt` bigint DEFAULT NULL COMMENT '创建时间',
|
||||
`updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人',
|
||||
`updatedAt` bigint DEFAULT NULL COMMENT '修改时间',
|
||||
`delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_tour_ledger_direct_relative_ledger` (`ledgerId`),
|
||||
KEY `idx_tour_ledger_direct_relative_line` (`lineId`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='普惠疗休养直系亲属线路报名信息';
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE `tour_setting_lot`
|
||||
ADD COLUMN `allowOverReimbursement` tinyint(1) DEFAULT 0 COMMENT '允许超出报销' AFTER `activityCost`;
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 92 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 67 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.0 KiB |
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,353 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<el-card shadow="never">
|
||||
<search :is-search-button="false">
|
||||
<search-item label="年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.year"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="线路名称">
|
||||
<el-input
|
||||
v-model="pageForm.lineName"
|
||||
clearable
|
||||
placeholder="请输入线路名称"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="doSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<search-item label="线路类型">
|
||||
<el-select v-model="pageForm.lineType" clearable filterable placeholder="请选择线路类型" style="width: 100%">
|
||||
<el-option v-for="item in lineTypeOptions" :key="item.lineType" :label="item.lineType" :value="item.lineType"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="所属工会">
|
||||
<el-select v-model="pageForm.unionId" clearable filterable placeholder="请选择所属工会" style="width: 100%">
|
||||
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<div class="search-query" style="margin-left: auto;">
|
||||
<el-button size="medium" type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
|
||||
<el-button size="medium" @click="resetSearch">重置</el-button>
|
||||
</div>
|
||||
</search>
|
||||
</el-card>
|
||||
|
||||
<el-card class="mt10" shadow="never">
|
||||
<table-tool :app="this" label="线路列表"></table-tool>
|
||||
|
||||
<el-table
|
||||
v-loading="tableLoading"
|
||||
:data="tableData"
|
||||
:size="tableSize"
|
||||
border
|
||||
:default-sort="{prop: 'lineName', order: 'ascending'}"
|
||||
:row-class-name="tableRowClassName"
|
||||
@sort-change="pageOrder">
|
||||
<el-table-column label="序号" type="index" :index="indexMethod" width="80" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="线路名称" prop="lineName" min-width="220" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="出行时段" prop="travelPeriod" width="260" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="事项名称" prop="matterName" min-width="200" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="所属工会" prop="unionName" min-width="180" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="线路类型" prop="lineType" width="140" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="最少成团人数" prop="minGroupPeople" width="140" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
{{ row.minGroupPeople || 0 }}人
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="最多成团人数" prop="maxGroupPeople" width="140" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
{{ row.maxGroupPeople || 0 }}人
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="报名人数" prop="signupCount" width="120" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="Number(row.signupCount || 0) > 0 ? 'success' : 'info'">{{ row.signupCount || 0 }}人</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="成团状态" prop="groupStatusName" width="120" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="groupStatusType(row.groupStatus)">{{ row.groupStatusName || '未成团' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160" align="center" header-align="center" fixed="right">
|
||||
<template slot-scope="{row}">
|
||||
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
|
||||
<el-button size="mini" type="primary" @click="exportLine(row)">导出</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
|
||||
<el-drawer
|
||||
:title="viewTitle"
|
||||
:visible.sync="viewVisible"
|
||||
direction="rtl"
|
||||
size="72%"
|
||||
custom-class="tour-group-view-drawer"
|
||||
:close-on-click-modal="false">
|
||||
<div class="tour-group-view">
|
||||
<el-card shadow="never">
|
||||
<search :is-search-button="false">
|
||||
<search-item label="姓名/工号">
|
||||
<el-input
|
||||
v-model="viewForm.keyword"
|
||||
clearable
|
||||
placeholder="请输入姓名或工号"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="viewSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<search-item label="所属工会">
|
||||
<el-select v-model="viewForm.unionId" clearable filterable placeholder="请选择所属工会" style="width: 100%">
|
||||
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<div class="search-query" style="margin-left: auto;">
|
||||
<el-button size="medium" type="primary" icon="el-icon-search" @click="viewSearch">搜索</el-button>
|
||||
<el-button size="medium" @click="viewReset">重置</el-button>
|
||||
</div>
|
||||
</search>
|
||||
</el-card>
|
||||
|
||||
<el-card class="mt10" shadow="never">
|
||||
<div class="tour-group-view-title">报名人员列表</div>
|
||||
<el-table
|
||||
v-loading="viewLoading"
|
||||
:data="viewTableData"
|
||||
:size="tableSize"
|
||||
border
|
||||
@sort-change="viewPageOrder">
|
||||
<el-table-column label="序号" type="index" :index="viewIndexMethod" width="80" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="工号" prop="jobNo" width="130" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="姓名" prop="userName" width="120" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="手机号码" prop="mobile" width="140" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="身份证号" prop="idCard" min-width="190" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="所属工会" prop="unionName" min-width="180" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
</el-table>
|
||||
<el-row class="el-pagination-container tour-group-view-pagination">
|
||||
<el-pagination
|
||||
background
|
||||
:current-page="viewForm.pageNumber"
|
||||
:page-size="viewForm.pageSize"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:total="viewForm.totalCount"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="viewSizeChange"
|
||||
@current-change="viewCurrentChange">
|
||||
</el-pagination>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</guava>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
mixins: [initTableMixins],
|
||||
data() {
|
||||
const currentYear = moment().format("YYYY")
|
||||
return {
|
||||
unionOptions: [],
|
||||
lineTypeOptions: [],
|
||||
viewVisible: false,
|
||||
viewLoading: false,
|
||||
viewRequestSeq: 0,
|
||||
viewTitle: "",
|
||||
viewRow: {},
|
||||
viewTableData: [],
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "lineName",
|
||||
pageOrderBy: "ascending",
|
||||
year: currentYear,
|
||||
lineName: "",
|
||||
lineType: "",
|
||||
unionId: ""
|
||||
},
|
||||
viewForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "signupTime",
|
||||
pageOrderBy: "descending",
|
||||
keyword: "",
|
||||
unionId: ""
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetSearch() {
|
||||
this.pageForm.year = moment().format("YYYY")
|
||||
this.pageForm.lineName = ""
|
||||
this.pageForm.lineType = ""
|
||||
this.pageForm.unionId = ""
|
||||
this.loadLineTypeOptions()
|
||||
this.doSearch()
|
||||
},
|
||||
groupStatusType(status) {
|
||||
if (status === "formed") return "success"
|
||||
if (status === "over") return "danger"
|
||||
return "info"
|
||||
},
|
||||
tableRowClassName({ row }) {
|
||||
return this.isDirectFamilyLine(row) ? "direct-family-row" : ""
|
||||
},
|
||||
isDirectFamilyLine(row) {
|
||||
if (!row) return false
|
||||
return row.directFamilyUnitLine === true
|
||||
|| row.directFamilyUnitLine === 1
|
||||
|| row.directFamilyUnitLine === "1"
|
||||
},
|
||||
openView(row) {
|
||||
this.viewRow = row || {}
|
||||
this.viewTitle = this.viewRow.lineName || "报名人员"
|
||||
this.viewVisible = true
|
||||
this.viewForm.pageNumber = 1
|
||||
this.viewForm.pageSize = 10
|
||||
this.viewForm.totalCount = 0
|
||||
this.viewForm.pageOrderName = "signupTime"
|
||||
this.viewForm.pageOrderBy = "descending"
|
||||
this.viewForm.keyword = ""
|
||||
this.viewForm.unionId = ""
|
||||
this.viewTableData = []
|
||||
this.loadViewData()
|
||||
},
|
||||
viewSearch() {
|
||||
this.viewForm.pageNumber = 1
|
||||
this.loadViewData()
|
||||
},
|
||||
viewReset() {
|
||||
this.viewForm.keyword = ""
|
||||
this.viewForm.unionId = ""
|
||||
this.viewForm.pageNumber = 1
|
||||
this.loadViewData()
|
||||
},
|
||||
viewIndexMethod(index) {
|
||||
return (this.viewForm.pageNumber - 1) * this.viewForm.pageSize + index + 1
|
||||
},
|
||||
viewSizeChange(size) {
|
||||
this.viewForm.pageSize = size
|
||||
this.viewForm.pageNumber = 1
|
||||
this.loadViewData()
|
||||
},
|
||||
viewCurrentChange(page) {
|
||||
this.viewForm.pageNumber = page
|
||||
this.loadViewData()
|
||||
},
|
||||
viewPageOrder({ prop, order }) {
|
||||
this.viewForm.pageOrderName = prop || "signupTime"
|
||||
this.viewForm.pageOrderBy = order || "descending"
|
||||
this.viewForm.pageNumber = 1
|
||||
this.loadViewData()
|
||||
},
|
||||
loadViewData() {
|
||||
if (!this.viewRow || !this.viewRow.matterId) {
|
||||
this.viewTableData = []
|
||||
this.viewForm.totalCount = 0
|
||||
return
|
||||
}
|
||||
this.viewLoading = true
|
||||
const requestSeq = ++this.viewRequestSeq
|
||||
this.$axios.post(loc() + "/signupPageData", {
|
||||
matterId: this.viewRow.matterId,
|
||||
keyword: this.viewForm.keyword,
|
||||
unionId: this.viewForm.unionId,
|
||||
pageNumber: this.viewForm.pageNumber,
|
||||
pageSize: this.viewForm.pageSize,
|
||||
pageOrderName: this.viewForm.pageOrderName,
|
||||
pageOrderBy: this.viewForm.pageOrderBy
|
||||
}).then((res) => {
|
||||
if (requestSeq !== this.viewRequestSeq) return
|
||||
if (res.code === 0) {
|
||||
const data = res.data || {}
|
||||
this.viewTableData = data.list || []
|
||||
this.viewForm.totalCount = data.totalCount || 0
|
||||
} else {
|
||||
this.$message.warning(res.msg || "查询失败")
|
||||
}
|
||||
}).finally(() => {
|
||||
if (requestSeq === this.viewRequestSeq) {
|
||||
this.viewLoading = false
|
||||
}
|
||||
})
|
||||
},
|
||||
exportLine(row) {
|
||||
if (!row || !row.matterId) {
|
||||
this.$message.warning("线路信息不完整")
|
||||
return
|
||||
}
|
||||
window.location.href = loc() + "/exportParticipants?matterId=" + encodeURIComponent(row.matterId)
|
||||
},
|
||||
loadUnionOptions() {
|
||||
this.$axios.post(loc() + "/unionOptions").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.unionOptions = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
loadLineTypeOptions() {
|
||||
this.$axios.post(loc() + "/lineTypeOptions", {
|
||||
year: this.pageForm.year
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.lineTypeOptions = (res.data || []).filter(item => item.lineType)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadUnionOptions()
|
||||
this.loadLineTypeOptions()
|
||||
this.pageData()
|
||||
},
|
||||
watch: {
|
||||
"pageForm.year"() {
|
||||
this.pageForm.lineType = ""
|
||||
this.loadLineTypeOptions()
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.tour-group-view-drawer .el-drawer__body {
|
||||
background: #f5f7fa;
|
||||
padding: 12px;
|
||||
overflow: auto;
|
||||
}
|
||||
.tour-group-view-pagination {
|
||||
margin-top: 12px;
|
||||
text-align: right;
|
||||
}
|
||||
.tour-group-view-title {
|
||||
border-left: 4px solid #0079c2;
|
||||
color: #0079c2;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 16px;
|
||||
margin-bottom: 12px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
.el-table .direct-family-row > td,
|
||||
.el-table .direct-family-row > td .cell {
|
||||
color: #f56c6c;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,653 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<el-card shadow="never">
|
||||
<search :is-search-button="false">
|
||||
<search-item label="开始年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.startYear"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择开始年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="结束年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.endYear"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择结束年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="姓名/工号">
|
||||
<el-input
|
||||
v-model="pageForm.keyword"
|
||||
clearable
|
||||
placeholder="请输入姓名或工号"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="doSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<search-item label="所属工会">
|
||||
<el-select v-model="pageForm.unionId" clearable filterable placeholder="请选择所属工会" style="width: 100%">
|
||||
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="线路">
|
||||
<el-select v-model="pageForm.lineId" clearable filterable placeholder="请选择线路" style="width: 100%">
|
||||
<el-option v-for="item in lineOptions" :key="item.lineId" :label="item.lineName" :value="item.lineId"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="出行时段">
|
||||
<el-select v-model="pageForm.travelPeriod" clearable filterable placeholder="请选择出行时段" style="width: 100%">
|
||||
<el-option v-for="item in travelPeriodOptions" :key="item.travelPeriod" :label="item.travelPeriod" :value="item.travelPeriod"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="线路类型">
|
||||
<dict-select
|
||||
v-model="pageForm.lineType"
|
||||
code="lineType"
|
||||
option_value="name"
|
||||
placeholder="请选择线路类型">
|
||||
</dict-select>
|
||||
</search-item>
|
||||
<div class="search-query" style="margin-left: auto;">
|
||||
<el-button size="medium" type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
|
||||
<el-button size="medium" @click="resetSearch">重置</el-button>
|
||||
</div>
|
||||
</search>
|
||||
</el-card>
|
||||
|
||||
<el-card class="mt10" shadow="never">
|
||||
<div class="tour-ledger-toolbar">
|
||||
<div class="tour-ledger-toolbar-title">
|
||||
<table-tool :app="this" label="台账列表"></table-tool>
|
||||
</div>
|
||||
<div class="tour-ledger-actions">
|
||||
<el-button size="medium" type="primary" icon="el-icon-upload2" @click="showImportDialog = true">参加人员导入</el-button>
|
||||
<el-button size="medium" type="primary" icon="el-icon-check" @click="setParticipants">设置参加人员</el-button>
|
||||
<el-button size="medium" type="primary" icon="el-icon-download" @click="exportUnionSignupZip">导出分工会报名压缩包</el-button>
|
||||
</div>
|
||||
<div class="tour-ledger-scope">
|
||||
<el-button
|
||||
class="tour-scope-btn"
|
||||
size="medium"
|
||||
:class="{'is-active': pageForm.directFamilyOnly}"
|
||||
@click="setDirectFamilyOnly">
|
||||
参加直系亲属单位线路人员
|
||||
</el-button>
|
||||
<el-button
|
||||
class="tour-scope-btn"
|
||||
size="medium"
|
||||
:class="{'is-active': pageForm.overCostOnly}"
|
||||
@click="setOverCostOnly">
|
||||
申请超出费用由单位承担人员
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
v-loading="tableLoading"
|
||||
:data="tableData"
|
||||
:size="tableSize"
|
||||
border
|
||||
row-key="id"
|
||||
:row-class-name="tableRowClassName"
|
||||
@selection-change="handleSelectionChange"
|
||||
@sort-change="pageOrder">
|
||||
<el-table-column type="selection" width="55" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="序号" type="index" :index="indexMethod" width="80" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="工号" prop="jobNo" width="130" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="姓名" prop="userName" width="120" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="所在单位" prop="unitName" min-width="180" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="报名线路" prop="lineName" min-width="220" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="出行时段" prop="travelPeriod" min-width="260" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="线路类型" prop="lineType" width="130" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="报名时间" prop="signupTime" width="170" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="携带家属" prop="familyCount" width="120" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="Number(row.familyCount || 0) > 0 ? 'success' : 'info'">{{ row.familyCount || 0 }}人</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否参加" prop="joined" width="120" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="row.joined ? 'success' : 'info'">{{ row.joined ? '是' : '否' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="报销超出费用" prop="overCostReimbursed" width="140" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="row.overCostReimbursed ? 'success' : 'info'">{{ row.overCostReimbursed ? '是' : '否' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160" align="center" header-align="center" fixed="right">
|
||||
<template slot-scope="{row}">
|
||||
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
|
||||
<el-button size="mini" type="danger" @click="doDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
<div class="tour-ledger-tip">温馨提醒:走审核流程的报名,审核通过后才在台账中显示</div>
|
||||
</el-card>
|
||||
</guava>
|
||||
|
||||
<excel-import
|
||||
ref="excelImportRef"
|
||||
url="/platform/tour/ledger/importParticipants"
|
||||
template_url="/platform/tour/ledger/downloadTemplate"
|
||||
:visible.sync="showImportDialog"
|
||||
title="参加人员导入"
|
||||
width="700px"
|
||||
@import-success="afterImport"
|
||||
:extra_params="{}">
|
||||
</excel-import>
|
||||
|
||||
<el-dialog
|
||||
title="台账详情"
|
||||
:visible.sync="detailVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="72%">
|
||||
<div class="tour-ledger-section">
|
||||
<div class="tour-ledger-title">教职工信息</div>
|
||||
<el-descriptions :column="3" border size="medium">
|
||||
<el-descriptions-item label="工号">{{ detail.jobNo || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="姓名">{{ detail.userName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="性别">{{ detail.gender || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="身份证号">{{ detail.idCard || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在单位">{{ detail.unitName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在工会">{{ detail.unionName || '' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<div class="tour-ledger-section mt10">
|
||||
<div class="tour-ledger-title">
|
||||
报名信息
|
||||
<el-link v-if="detailHasWorkflow()" type="primary" @click="openChart">点击查看流程图</el-link>
|
||||
</div>
|
||||
<el-descriptions :column="3" border size="medium">
|
||||
<el-descriptions-item label="报名时间">{{ detail.signupTime || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报名线路">{{ detail.lineName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="线路类型">{{ detail.lineType || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报名酒店">{{ detail.hotelName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报名旅行社">{{ detail.travelAgencyName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="出行时间">{{ detail.travelPeriod || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item v-if="fillBedInfo" label="床型">{{ detail.bedType || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item v-if="fillBedInfo" label="床位信息">{{ detail.bedInfo || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item v-if="fillBedInfo" label="意向拼床人">{{ detail.intendedRoommate || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="是否携带家属">{{ familyText() }}</el-descriptions-item>
|
||||
<el-descriptions-item label="是否参加">{{ detail.joined ? '是' : '否' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="是否报销">{{ detail.reimbursed ? '是' : '否' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报销超出费用">{{ detail.overCostReimbursed ? '是' : '否' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<div v-if="isDirectFamilyLine()" class="tour-ledger-section mt10">
|
||||
<div class="tour-ledger-title">直系亲属线路</div>
|
||||
<el-descriptions :column="3" border size="medium">
|
||||
<el-descriptions-item label="亲属姓名">{{ directRelative.relativeName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在单位">{{ directRelative.unitName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="亲属关系">{{ directRelative.relationshipName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="线路名称">{{ directRelative.lineName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="出行开始日期">{{ directRelative.travelStartTime || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="出行结束日期">{{ directRelative.travelEndTime || '' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<div v-if="showFamilySection()" class="tour-ledger-section mt10">
|
||||
<div class="tour-ledger-title">家属信息</div>
|
||||
<el-table :data="familyData" border :size="tableSize" empty-text="暂无家属信息">
|
||||
<el-table-column label="序号" type="index" width="70" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="家属姓名" prop="familyName" min-width="120" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="性别" prop="gender" width="90" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="身份证号码" prop="idCard" min-width="180" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="年龄" prop="age" width="90" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="关系" prop="relationship" width="110" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column v-if="fillBedInfo" label="床型" prop="bedType" width="110" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column v-if="fillBedInfo" label="床位" prop="bedInfo" min-width="120" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column v-if="fillBedInfo" label="意向拼床人" prop="intendedRoommate" min-width="130" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<template v-if="detailHasWorkflow()" v-for="task in doneTasks">
|
||||
<div class="tour-ledger-section mt10" :key="task.id">
|
||||
<div class="tour-ledger-title">{{ task.displayName }}</div>
|
||||
<el-descriptions border :column="3" v-if="task.ext && task.ext.isFirstTaskNode">
|
||||
<el-descriptions-item label="申请用户">
|
||||
{{ task.ext.initiatorName }}({{ task.ext.initiatorAccount }})
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="申请时间">{{ task.finishTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="办理结果">
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE" :value="task.ext.submitType"></dict-tag>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-descriptions border :column="3" v-else>
|
||||
<el-descriptions-item label="办理用户">
|
||||
{{ (task.taskFormData && task.taskFormData.userName) || '' }}({{ (task.taskFormData && task.taskFormData.loginName) || '' }})
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="办理时间">{{ task.finishTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="办理结果">
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE" :value="task.ext && task.ext.submitType"></dict-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="办理意见" :span="3">
|
||||
{{ (task.taskFormData && (task.taskFormData.opinion || task.taskFormData.tf_opinion)) || '' }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<snaker-chart ref="snakerChartRef"></snaker-chart>
|
||||
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="detailVisible = false">确定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.tour-ledger-section {
|
||||
padding: 0 2px;
|
||||
}
|
||||
.tour-ledger-title {
|
||||
border-left: 4px solid #0079c2;
|
||||
color: #0079c2;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 16px;
|
||||
margin-bottom: 14px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
.tour-ledger-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
gap: 24px;
|
||||
margin-bottom: 12px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.tour-ledger-toolbar-title {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.tour-ledger-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 0 0 auto;
|
||||
gap: 10px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.tour-ledger-actions .el-button {
|
||||
margin: 0;
|
||||
}
|
||||
.tour-ledger-scope {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 0 0 auto;
|
||||
flex-wrap: nowrap;
|
||||
gap: 12px;
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.tour-ledger-scope .el-button {
|
||||
margin: 0;
|
||||
}
|
||||
.tour-ledger-scope .el-button + .el-button {
|
||||
margin-left: 0;
|
||||
}
|
||||
.tour-ledger-scope .tour-scope-btn {
|
||||
background: #ecf5ff;
|
||||
border-color: #b3d8ff;
|
||||
border-radius: 4px;
|
||||
color: #0079c2;
|
||||
font-weight: 600;
|
||||
height: 34px;
|
||||
line-height: 1;
|
||||
padding: 8px 18px;
|
||||
}
|
||||
.tour-ledger-scope .tour-scope-btn:hover,
|
||||
.tour-ledger-scope .tour-scope-btn:focus {
|
||||
background: #d9ecff;
|
||||
border-color: #66b1ff;
|
||||
color: #006bb0;
|
||||
}
|
||||
.tour-ledger-scope .tour-scope-btn.is-active {
|
||||
background: #0079c2;
|
||||
border-color: #0079c2;
|
||||
box-shadow: 0 2px 6px rgba(0, 121, 194, 0.24);
|
||||
color: #fff;
|
||||
}
|
||||
.tour-ledger-scope .tour-scope-btn.is-active:hover,
|
||||
.tour-ledger-scope .tour-scope-btn.is-active:focus {
|
||||
background: #006bb0;
|
||||
border-color: #006bb0;
|
||||
color: #fff;
|
||||
}
|
||||
.tour-ledger-tip {
|
||||
color: #f56c6c;
|
||||
font-family: SimSun, "宋体", serif;
|
||||
font-size: 9pt;
|
||||
line-height: 1.6;
|
||||
margin-top: -4px;
|
||||
text-align: center;
|
||||
}
|
||||
.el-table .direct-family-row > td,
|
||||
.el-table .direct-family-row > td .cell {
|
||||
color: #f56c6c;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
mixins: [initTableMixins],
|
||||
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
|
||||
data() {
|
||||
const currentYear = moment().format("YYYY")
|
||||
return {
|
||||
detailVisible: false,
|
||||
unionOptions: [],
|
||||
lineOptions: [],
|
||||
travelPeriodOptions: [],
|
||||
detail: {},
|
||||
familyData: [],
|
||||
directRelative: {},
|
||||
directFamilyUnitLine: false,
|
||||
fillBedInfo: true,
|
||||
detailRow: {},
|
||||
doneTasks: [],
|
||||
showImportDialog: false,
|
||||
multipleSelection: [],
|
||||
filterOptionsTimer: null,
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "signupTime",
|
||||
pageOrderBy: "descending",
|
||||
startYear: currentYear,
|
||||
endYear: currentYear,
|
||||
keyword: "",
|
||||
unionId: "",
|
||||
lineId: "",
|
||||
travelPeriod: "",
|
||||
lineType: "",
|
||||
directFamilyOnly: false,
|
||||
overCostOnly: false
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toBoolean(value) {
|
||||
return value === true || value === 1 || value === "1" || value === "true" || value === "TRUE"
|
||||
},
|
||||
tableRowClassName({ row }) {
|
||||
return this.isDirectFamilyRow(row) ? "direct-family-row" : ""
|
||||
},
|
||||
isDirectFamilyRow(row) {
|
||||
return this.toBoolean(row && row.directFamilyUnitLine) || !!(row && row.directRelativeId)
|
||||
},
|
||||
handleSelectionChange(val) {
|
||||
this.multipleSelection = val || []
|
||||
},
|
||||
clearTableSelection() {
|
||||
this.multipleSelection = []
|
||||
if (this.$refs.tableRef) {
|
||||
this.$refs.tableRef.clearSelection()
|
||||
}
|
||||
},
|
||||
setParticipants() {
|
||||
if (!this.multipleSelection.length) {
|
||||
this.$message.warning("请选择要设置的参加人员")
|
||||
return
|
||||
}
|
||||
this.$confirm("确定将选中的" + this.multipleSelection.length + "条台账设置为已参加吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
this.$axios.post(loc() + "/setParticipants", {
|
||||
ids: JSON.stringify(this.multipleSelection.map(item => item.id))
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success("设置成功")
|
||||
this.clearTableSelection()
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "设置失败")
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
exportUnionSignupZip() {
|
||||
const params = new URLSearchParams()
|
||||
;["startYear", "endYear", "keyword", "unionId", "lineId", "travelPeriod", "lineType"].forEach(key => {
|
||||
const value = this.pageForm[key]
|
||||
if (value !== undefined && value !== null && value !== "") {
|
||||
params.append(key, value)
|
||||
}
|
||||
})
|
||||
if (this.pageForm.directFamilyOnly) {
|
||||
params.append("directFamilyOnly", "true")
|
||||
}
|
||||
if (this.pageForm.overCostOnly) {
|
||||
params.append("overCostOnly", "true")
|
||||
}
|
||||
window.location.href = loc() + "/exportUnionSignupZip?" + params.toString()
|
||||
},
|
||||
afterImport() {
|
||||
this.showImportDialog = false
|
||||
this.clearTableSelection()
|
||||
this.pageData()
|
||||
this.loadFilterOptions()
|
||||
},
|
||||
isDirectFamilyLine() {
|
||||
return this.directFamilyUnitLine
|
||||
|| this.toBoolean(this.detail && this.detail.directFamilyUnitLine)
|
||||
|| !!(this.directRelative && this.directRelative.id)
|
||||
},
|
||||
detailHasWorkflow() {
|
||||
return !!(this.detailRow && this.detailRow.instanceId)
|
||||
},
|
||||
hasFamily() {
|
||||
return this.toBoolean(this.detail && this.detail.hasFamily) || this.familyData.length > 0
|
||||
},
|
||||
familyText() {
|
||||
if (this.isDirectFamilyLine()) {
|
||||
return "否"
|
||||
}
|
||||
if (!this.hasFamily()) {
|
||||
return "否"
|
||||
}
|
||||
const count = Number(this.familyData.length || 0)
|
||||
return count > 0 ? count + "人" : "是"
|
||||
},
|
||||
showFamilySection() {
|
||||
return this.hasFamily() && !this.isDirectFamilyLine()
|
||||
},
|
||||
loadDoneTasks() {
|
||||
this.$axios.post("/flow/common/doneTasks", { bizId: this.detailRow.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.doneTasks = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
openChart() {
|
||||
if (!this.detailRow.instanceProcessDefineId || !this.detailRow.instanceId) {
|
||||
this.$message.warning("暂无流程图信息")
|
||||
return
|
||||
}
|
||||
this.$refs.snakerChartRef.onOpenFull(this.detailRow.instanceProcessDefineId, this.detailRow.instanceId)
|
||||
},
|
||||
resetSearch() {
|
||||
this.pageForm.startYear = moment().format("YYYY")
|
||||
this.pageForm.endYear = moment().format("YYYY")
|
||||
this.pageForm.keyword = ""
|
||||
this.pageForm.unionId = ""
|
||||
this.pageForm.lineId = ""
|
||||
this.pageForm.travelPeriod = ""
|
||||
this.pageForm.lineType = ""
|
||||
this.pageForm.directFamilyOnly = false
|
||||
this.pageForm.overCostOnly = false
|
||||
this.doSearch()
|
||||
},
|
||||
openView(row) {
|
||||
this.detailRow = row || {}
|
||||
this.detail = {}
|
||||
this.familyData = []
|
||||
this.directRelative = {}
|
||||
this.directFamilyUnitLine = false
|
||||
this.fillBedInfo = true
|
||||
this.doneTasks = []
|
||||
this.$axios.post(loc() + "/detail", { id: row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const data = res.data || {}
|
||||
this.detail = data.ledger || {}
|
||||
this.detail.travelPeriod = data.travelPeriod || ""
|
||||
this.familyData = data.families || []
|
||||
this.directRelative = data.directRelative || {}
|
||||
this.directFamilyUnitLine = this.toBoolean(data.directFamilyUnitLine)
|
||||
this.fillBedInfo = data.fillBedInfo === undefined || data.fillBedInfo === null || this.toBoolean(data.fillBedInfo)
|
||||
this.detailVisible = true
|
||||
if (this.detailHasWorkflow()) {
|
||||
this.loadDoneTasks()
|
||||
}
|
||||
} else {
|
||||
this.$message.warning(res.msg || "查询失败")
|
||||
}
|
||||
})
|
||||
},
|
||||
doDelete(row) {
|
||||
this.$confirm("确定删除【" + row.userName + "】的报名台账吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
this.$axios.post(loc() + "/doDelete", { id: row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success("删除成功")
|
||||
this.pageData()
|
||||
this.loadFilterOptions()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "删除失败")
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
loadUnionOptions() {
|
||||
this.$axios.post(loc() + "/unionOptions").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.unionOptions = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
loadFilterOptions() {
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
},
|
||||
scheduleFilterOptions(delay) {
|
||||
if (this.filterOptionsTimer) {
|
||||
clearTimeout(this.filterOptionsTimer)
|
||||
}
|
||||
this.filterOptionsTimer = setTimeout(() => {
|
||||
this.loadFilterOptions()
|
||||
this.filterOptionsTimer = null
|
||||
}, delay === undefined ? 80 : delay)
|
||||
},
|
||||
loadLineOptions() {
|
||||
this.$axios.post(loc() + "/lineOptions", {
|
||||
startYear: this.pageForm.startYear,
|
||||
endYear: this.pageForm.endYear,
|
||||
travelPeriod: this.pageForm.travelPeriod,
|
||||
lineType: this.pageForm.lineType,
|
||||
unionId: this.pageForm.unionId,
|
||||
keyword: this.pageForm.keyword,
|
||||
directFamilyOnly: this.pageForm.directFamilyOnly,
|
||||
overCostOnly: this.pageForm.overCostOnly
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.lineOptions = res.data || []
|
||||
if (this.pageForm.lineId && !this.lineOptions.some(item => item.lineId === this.pageForm.lineId)) {
|
||||
this.pageForm.lineId = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadTravelPeriodOptions() {
|
||||
this.$axios.post(loc() + "/travelPeriodOptions", {
|
||||
startYear: this.pageForm.startYear,
|
||||
endYear: this.pageForm.endYear,
|
||||
lineId: this.pageForm.lineId,
|
||||
lineType: this.pageForm.lineType,
|
||||
unionId: this.pageForm.unionId,
|
||||
keyword: this.pageForm.keyword,
|
||||
directFamilyOnly: this.pageForm.directFamilyOnly,
|
||||
overCostOnly: this.pageForm.overCostOnly
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.travelPeriodOptions = res.data || []
|
||||
if (this.pageForm.travelPeriod && !this.travelPeriodOptions.some(item => item.travelPeriod === this.pageForm.travelPeriod)) {
|
||||
this.pageForm.travelPeriod = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
doSearch() {
|
||||
this.tableKey = new Date().getTime()
|
||||
this.pageForm.pageNumber = 1
|
||||
this.clearTableSelection()
|
||||
this.pageData()
|
||||
this.scheduleFilterOptions(0)
|
||||
},
|
||||
setDirectFamilyOnly() {
|
||||
this.pageForm.directFamilyOnly = !this.pageForm.directFamilyOnly
|
||||
this.pageForm.pageNumber = 1
|
||||
this.clearTableSelection()
|
||||
this.pageData()
|
||||
this.scheduleFilterOptions(0)
|
||||
},
|
||||
setOverCostOnly() {
|
||||
this.pageForm.overCostOnly = !this.pageForm.overCostOnly
|
||||
this.pageForm.pageNumber = 1
|
||||
this.clearTableSelection()
|
||||
this.pageData()
|
||||
this.scheduleFilterOptions(0)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadUnionOptions()
|
||||
this.pageData()
|
||||
this.scheduleFilterOptions(150)
|
||||
},
|
||||
watch: {
|
||||
"pageForm.startYear"() {
|
||||
this.pageForm.lineId = ""
|
||||
this.pageForm.travelPeriod = ""
|
||||
this.scheduleFilterOptions()
|
||||
},
|
||||
"pageForm.endYear"() {
|
||||
this.pageForm.lineId = ""
|
||||
this.pageForm.travelPeriod = ""
|
||||
this.scheduleFilterOptions()
|
||||
},
|
||||
"pageForm.lineId"() {
|
||||
this.scheduleFilterOptions()
|
||||
},
|
||||
"pageForm.travelPeriod"() {
|
||||
this.scheduleFilterOptions()
|
||||
},
|
||||
"pageForm.lineType"() {
|
||||
this.scheduleFilterOptions()
|
||||
},
|
||||
"pageForm.unionId"() {
|
||||
this.scheduleFilterOptions()
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,712 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<el-card shadow="never">
|
||||
<search :is-search-button="false">
|
||||
<search-item label="年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.year"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="所属工会">
|
||||
<el-select v-model="pageForm.unionId" clearable filterable placeholder="请选择所属工会" style="width: 100%">
|
||||
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="事项名称">
|
||||
<el-input
|
||||
v-model="pageForm.matterName"
|
||||
clearable
|
||||
placeholder="请输入事项名称"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="doSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<search-item label="组织形式">
|
||||
<el-select v-model="pageForm.organizationType" clearable filterable placeholder="请选择组织形式" style="width: 100%">
|
||||
<el-option v-for="item in organizationTypeOptions" :key="item.code" :label="item.name" :value="item.code"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<div class="search-query" style="margin-left: auto;">
|
||||
<el-button size="medium" type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
|
||||
<el-button size="medium" @click="resetSearch">重置</el-button>
|
||||
</div>
|
||||
</search>
|
||||
</el-card>
|
||||
|
||||
<el-card class="mt10" shadow="never">
|
||||
<table-tool :app="this" label="事项列表">
|
||||
<el-button @click="openAdd" size="medium" type="primary">
|
||||
<i class="el-icon-plus"></i>
|
||||
新增
|
||||
</el-button>
|
||||
</table-tool>
|
||||
|
||||
<el-table
|
||||
v-loading="tableLoading"
|
||||
:data="tableData"
|
||||
:size="tableSize"
|
||||
border
|
||||
:row-class-name="tableRowClassName"
|
||||
@sort-change="pageOrder">
|
||||
<el-table-column label="序号" type="index" :index="indexMethod" width="80" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="年度" prop="year" width="110" sortable="custom" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="事项名称" prop="matterName" min-width="200" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="所属工会" prop="unionName" min-width="180" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="线路名称" prop="lineName" min-width="220" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="组织形式" prop="organizationTypeName" width="150" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="联系人" prop="contactName" width="130" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="联系方式" prop="contactPhone" width="150" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="事项状态" prop="enabled" width="160" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-switch
|
||||
v-model="row.enabled"
|
||||
active-text="启用"
|
||||
inactive-text="禁用"
|
||||
@change="toggleEnabled(row)">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="260" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-button size="mini" type="primary" @click="openBatchForm(row)">选择线路</el-button>
|
||||
<el-button size="mini" type="primary" @click="openEdit(row)">编辑</el-button>
|
||||
<el-button size="mini" type="danger" :loading="row.deleteLoading" @click="doDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
</guava>
|
||||
|
||||
<el-dialog
|
||||
:title="title"
|
||||
:visible.sync="dialogVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="54%"
|
||||
@closed="destroyForm">
|
||||
<el-form :model="formData" :rules="formRules" label-width="110px" ref="form" :disabled="viewMode">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="年度" prop="year">
|
||||
<el-date-picker
|
||||
v-model="formData.year"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择年度"
|
||||
style="width: 100%"
|
||||
@change="yearChange">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="事项状态" prop="enabled">
|
||||
<el-radio-group v-model="formData.enabled">
|
||||
<el-radio :label="true">启用</el-radio>
|
||||
<el-radio :label="false">禁用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="事项名称" prop="matterName">
|
||||
<el-input v-model="formData.matterName" maxlength="30" show-word-limit placeholder="请输入事项名称"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建人">
|
||||
<el-input v-model="formData.creatorName" readonly placeholder="当前登录人"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="疗休养配置" prop="settingId">
|
||||
<el-select v-model="formData.settingId" clearable filterable placeholder="请选择配置" style="width: 100%">
|
||||
<el-option v-for="item in settingOptions" :key="item.id" :label="item.configName" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="组织形式" prop="organizationType">
|
||||
<el-select v-model="formData.organizationType" clearable filterable placeholder="请选择组织形式" style="width: 100%" @change="organizationTypeChange">
|
||||
<el-option v-for="item in organizationTypeOptions" :key="item.code" :label="item.name" :value="item.code"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属工会" prop="unionId">
|
||||
<el-select v-model="formData.unionId" clearable filterable placeholder="请选择所属工会" style="width: 100%" :disabled="isUnionDisabled()">
|
||||
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button v-if="!viewMode" type="primary" :loading="subDis" @click="doSubmit">保存</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
:title="batchTitle"
|
||||
:visible.sync="batchFormVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="74%">
|
||||
<el-form :model="batchForm" :rules="batchRules" label-width="110px" ref="batchFormRef">
|
||||
<el-form-item label="线路" prop="lineId">
|
||||
<el-select v-model="batchForm.lineId" clearable filterable placeholder="请选择线路" style="width: 100%" @change="lineChange">
|
||||
<el-option v-for="item in lineOptions" :key="item.id" :label="lineOptionLabel(item)" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="报名开始时间" prop="signupStartTime">
|
||||
<el-date-picker v-model="batchForm.signupStartTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择时间" style="width: 100%"></el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="报名结束时间" prop="signupEndTime">
|
||||
<el-date-picker v-model="batchForm.signupEndTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择时间" style="width: 100%"></el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="出行开始时间" prop="travelStartTime">
|
||||
<el-date-picker v-model="batchForm.travelStartTime" type="date" value-format="yyyy-MM-dd" placeholder="选择日期" style="width: 100%" @change="travelStartChange"></el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="出行结束时间" prop="travelEndTime">
|
||||
<el-date-picker v-model="batchForm.travelEndTime" type="date" value-format="yyyy-MM-dd" placeholder="选择日期" style="width: 100%" @change="travelEndChange"></el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="联系人" prop="contactName">
|
||||
<el-input v-model="batchForm.contactName" maxlength="10" placeholder="请输入联系人"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="联系方式" prop="contactPhone">
|
||||
<el-input v-model="batchForm.contactPhone" maxlength="11" placeholder="请输入联系方式"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="预计费用" prop="estimatedCost">
|
||||
<el-input v-model="batchForm.estimatedCost" maxlength="10" placeholder="请输入预计费用"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="最少成团人数" prop="minGroupPeople">
|
||||
<el-input-number v-model="batchForm.minGroupPeople" :min="1" :precision="0" controls-position="right" style="width: 100%" @change="peopleChange"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="最多成团人数" prop="maxGroupPeople">
|
||||
<el-input-number v-model="batchForm.maxGroupPeople" :min="1" :precision="0" controls-position="right" style="width: 100%" @change="peopleChange"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="batchFormVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="batchSubDis" @click="submitBatch">确定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.el-table .direct-family-row > td,
|
||||
.el-table .direct-family-row > td .cell {
|
||||
color: #f56c6c;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
mixins: [initTableMixins],
|
||||
data() {
|
||||
const currentYear = moment().format("YYYY")
|
||||
const validateUnion = (rule, value, callback) => {
|
||||
if (this.formData.organizationType === "schoolUnion" || value) {
|
||||
callback()
|
||||
} else {
|
||||
callback(new Error("必填"))
|
||||
}
|
||||
}
|
||||
const validateMobile = (rule, value, callback) => {
|
||||
const mobileReg = /^1[3-9]\d{9}$/
|
||||
if (!value) {
|
||||
callback(new Error("必填"))
|
||||
} else if (!mobileReg.test(value)) {
|
||||
callback(new Error("手机号格式不正确"))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const validateMoney = (rule, value, callback) => {
|
||||
const moneyReg = /^(0|[1-9]\d*)(\.\d{1,2})?$/
|
||||
if (value === "" || value === null || value === undefined) {
|
||||
callback(new Error("必填"))
|
||||
} else if (!moneyReg.test(String(value))) {
|
||||
callback(new Error("请输入非负金额,最多两位小数"))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const validatePeople = (rule, value, callback) => {
|
||||
if (!value || value <= 0) {
|
||||
callback(new Error("人数必须大于0"))
|
||||
} else if (this.batchForm.minGroupPeople && this.batchForm.maxGroupPeople
|
||||
&& this.batchForm.minGroupPeople > this.batchForm.maxGroupPeople) {
|
||||
callback(new Error("最少人数不能大于最多人数"))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const validateBatchTime = (rule, value, callback) => {
|
||||
if (!value) {
|
||||
callback(new Error("必填"))
|
||||
return
|
||||
}
|
||||
const form = this.batchForm
|
||||
if (form.signupStartTime && form.signupEndTime && form.signupStartTime >= form.signupEndTime) {
|
||||
callback(new Error("报名开始时间必须小于报名结束时间"))
|
||||
return
|
||||
}
|
||||
if (form.travelStartTime && form.travelEndTime && form.travelStartTime > form.travelEndTime) {
|
||||
callback(new Error("出行开始时间不能晚于出行结束时间"))
|
||||
return
|
||||
}
|
||||
if (form.signupEndTime && form.travelStartTime && form.signupEndTime >= form.travelStartTime) {
|
||||
callback(new Error("报名结束时间必须小于出行开始时间"))
|
||||
return
|
||||
}
|
||||
callback()
|
||||
}
|
||||
return {
|
||||
title: "",
|
||||
dialogVisible: false,
|
||||
viewMode: false,
|
||||
subDis: false,
|
||||
batchFormVisible: false,
|
||||
batchSubDis: false,
|
||||
batchTitle: "",
|
||||
currentMatter: {},
|
||||
batchForm: {},
|
||||
lineOptions: [],
|
||||
settingOptions: [],
|
||||
unionOptions: [],
|
||||
organizationTypeOptions: [],
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
year: currentYear,
|
||||
matterName: "",
|
||||
unionId: "",
|
||||
organizationType: ""
|
||||
},
|
||||
formData: {},
|
||||
formRules: {
|
||||
year: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
matterName: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
settingId: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
unionId: [{ validator: validateUnion, trigger: ["blur", "change"] }],
|
||||
organizationType: [{ required: true, message: "必填", trigger: ["blur", "change"] }]
|
||||
},
|
||||
batchRules: {
|
||||
lineId: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
signupStartTime: [{ validator: validateBatchTime, trigger: ["blur", "change"] }],
|
||||
signupEndTime: [{ validator: validateBatchTime, trigger: ["blur", "change"] }],
|
||||
travelStartTime: [{ validator: validateBatchTime, trigger: ["blur", "change"] }],
|
||||
travelEndTime: [{ validator: validateBatchTime, trigger: ["blur", "change"] }],
|
||||
contactName: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
contactPhone: [{ validator: validateMobile, trigger: ["blur", "change"] }],
|
||||
minGroupPeople: [{ validator: validatePeople, trigger: ["blur", "change"] }],
|
||||
maxGroupPeople: [{ validator: validatePeople, trigger: ["blur", "change"] }],
|
||||
estimatedCost: [{ validator: validateMoney, trigger: ["blur", "change"] }]
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
"pageForm.year"(year) {
|
||||
this.loadSettings(year)
|
||||
},
|
||||
"batchForm.lineId"() {
|
||||
if (this.batchFormVisible) {
|
||||
this.applySelectedLineDefaults(true)
|
||||
}
|
||||
},
|
||||
"batchForm.travelStartTime"() {
|
||||
if (this.batchFormVisible) {
|
||||
this.fillTravelEndByLot()
|
||||
}
|
||||
},
|
||||
"batchForm.travelEndTime"() {
|
||||
if (this.batchFormVisible) {
|
||||
this.validateTravelFields()
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetSearch() {
|
||||
this.pageForm.year = moment().format("YYYY")
|
||||
this.pageForm.matterName = ""
|
||||
this.pageForm.unionId = ""
|
||||
this.pageForm.organizationType = ""
|
||||
this.loadSettings(this.pageForm.year)
|
||||
this.doSearch()
|
||||
},
|
||||
tableRowClassName({ row }) {
|
||||
return this.isDirectFamilyLine(row) ? "direct-family-row" : ""
|
||||
},
|
||||
isDirectFamilyLine(row) {
|
||||
if (!row) return false
|
||||
return row.directFamilyUnitLine === true
|
||||
|| row.directFamilyUnitLine === 1
|
||||
|| row.directFamilyUnitLine === "1"
|
||||
},
|
||||
emptyForm() {
|
||||
const user = this.currentUser()
|
||||
return {
|
||||
year: moment().format("YYYY"),
|
||||
matterName: "",
|
||||
settingId: "",
|
||||
creatorUserId: user.id || "",
|
||||
creatorName: user.username || "",
|
||||
unionId: "",
|
||||
organizationType: "",
|
||||
enabled: true
|
||||
}
|
||||
},
|
||||
openAdd() {
|
||||
this.title = "新增事项信息"
|
||||
this.viewMode = false
|
||||
this.formData = this.emptyForm()
|
||||
this.loadSettings(this.formData.year, true)
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
|
||||
},
|
||||
openEdit(row) {
|
||||
this.title = "编辑事项信息"
|
||||
this.viewMode = false
|
||||
this.loadDetail(row.id)
|
||||
},
|
||||
openView(row) {
|
||||
this.title = "查看事项信息"
|
||||
this.viewMode = true
|
||||
this.loadDetail(row.id)
|
||||
},
|
||||
loadDetail(id) {
|
||||
this.$axios.post(loc() + "/detail", { id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.formData = Object.assign(this.emptyForm(), res.data || {})
|
||||
this.formData.year = this.formData.year ? String(this.formData.year) : ""
|
||||
this.ensureSelectedUnionOption()
|
||||
this.loadSettings(this.formData.year)
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
|
||||
} else {
|
||||
this.$message.warning(res.msg || "查询失败")
|
||||
}
|
||||
})
|
||||
},
|
||||
currentUser() {
|
||||
return (this.$store && this.$store.state && this.$store.state.user) || {}
|
||||
},
|
||||
currentUnion() {
|
||||
return this.currentUser().union || {}
|
||||
},
|
||||
organizationTypeChange() {
|
||||
this.applyOrganizationTypeRule()
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.validateField("unionId"))
|
||||
},
|
||||
applyOrganizationTypeRule() {
|
||||
if (this.formData.organizationType === "schoolUnion") {
|
||||
this.formData.unionId = ""
|
||||
return
|
||||
}
|
||||
if (this.formData.organizationType === "branchUnion" || this.formData.organizationType === "personal") {
|
||||
const union = this.currentUnion()
|
||||
this.formData.unionId = union.id || ""
|
||||
this.ensureCurrentUnionOption(union)
|
||||
}
|
||||
},
|
||||
ensureCurrentUnionOption(union) {
|
||||
if (!union || !union.id) return
|
||||
const exists = this.unionOptions.some(item => item.id === union.id)
|
||||
if (!exists) {
|
||||
this.unionOptions.push({ id: union.id, name: union.name || "" })
|
||||
}
|
||||
},
|
||||
ensureSelectedUnionOption() {
|
||||
if (!this.formData.unionId) return
|
||||
const exists = this.unionOptions.some(item => item.id === this.formData.unionId)
|
||||
if (!exists) {
|
||||
this.unionOptions.push({ id: this.formData.unionId, name: this.formData.unionName || "" })
|
||||
}
|
||||
},
|
||||
isUnionDisabled() {
|
||||
return ["schoolUnion", "branchUnion", "personal"].includes(this.formData.organizationType)
|
||||
},
|
||||
yearChange(year) {
|
||||
this.formData.settingId = ""
|
||||
this.loadSettings(year, true)
|
||||
},
|
||||
loadSettings(year, autoSelectLatest) {
|
||||
this.$axios.post(loc() + "/settingOptions", { year }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.settingOptions = res.data || []
|
||||
if (autoSelectLatest && !this.formData.settingId && this.settingOptions.length > 0) {
|
||||
this.formData.settingId = this.settingOptions[0].id
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadUnions() {
|
||||
this.$axios.post(loc() + "/unionOptions").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.unionOptions = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
loadOrganizationTypes() {
|
||||
this.$axios.post(loc() + "/organizationTypeOptions").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.organizationTypeOptions = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
emptyBatchForm() {
|
||||
return {
|
||||
id: this.currentMatter.id || "",
|
||||
lineId: "",
|
||||
signupStartTime: "",
|
||||
signupEndTime: "",
|
||||
travelStartTime: "",
|
||||
travelEndTime: "",
|
||||
contactName: "",
|
||||
contactPhone: "",
|
||||
minGroupPeople: null,
|
||||
maxGroupPeople: null,
|
||||
estimatedCost: ""
|
||||
}
|
||||
},
|
||||
openBatchForm(row) {
|
||||
this.currentMatter = row
|
||||
this.loadLines(row.year)
|
||||
this.batchTitle = "选择线路"
|
||||
this.batchForm = this.emptyBatchForm()
|
||||
this.$axios.post(loc() + "/lineConfig", { matterId: row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.batchForm = Object.assign(this.emptyBatchForm(), res.data || {})
|
||||
this.batchForm.travelStartTime = this.dateOnly(this.batchForm.travelStartTime)
|
||||
this.batchForm.travelEndTime = this.dateOnly(this.batchForm.travelEndTime)
|
||||
this.applySelectedLineDefaults(false)
|
||||
if (!this.batchForm.minGroupPeople || !this.batchForm.maxGroupPeople) {
|
||||
this.loadSettingPeople((data) => {
|
||||
this.batchForm.minGroupPeople = data.minGroupPeople || null
|
||||
this.batchForm.maxGroupPeople = data.maxGroupPeople || null
|
||||
})
|
||||
}
|
||||
this.batchFormVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.applySelectedLineDefaults(true)
|
||||
this.$refs.batchFormRef && this.$refs.batchFormRef.clearValidate()
|
||||
})
|
||||
} else {
|
||||
this.$message.warning(res.msg || "查询失败")
|
||||
}
|
||||
})
|
||||
},
|
||||
loadLines(year) {
|
||||
this.$axios.post(loc() + "/lineOptions", { year }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.lineOptions = res.data || []
|
||||
this.applySelectedLineDefaults(true)
|
||||
}
|
||||
})
|
||||
},
|
||||
lineOptionLabel(item) {
|
||||
if (!item) return ""
|
||||
const lineName = this.lineField(item, "lineName") || ""
|
||||
const lineType = this.lineField(item, "lineType") || ""
|
||||
return lineType ? lineName + "(" + lineType + ")" : lineName
|
||||
},
|
||||
lineChange() {
|
||||
this.applySelectedLineDefaults(true)
|
||||
},
|
||||
travelStartChange() {
|
||||
this.fillTravelEndByLot()
|
||||
},
|
||||
travelEndChange() {
|
||||
this.validateTravelFields()
|
||||
},
|
||||
selectedLine() {
|
||||
return (this.lineOptions || []).find((item) => this.lineField(item, "id") === this.batchForm.lineId) || null
|
||||
},
|
||||
applySelectedLineDefaults(recalculateEnd) {
|
||||
const line = this.selectedLine()
|
||||
if (!line) return
|
||||
const activityCost = this.lineField(line, "activityCost")
|
||||
if (activityCost !== null && activityCost !== undefined && activityCost !== "") {
|
||||
this.batchForm.estimatedCost = activityCost
|
||||
}
|
||||
if (recalculateEnd) {
|
||||
this.fillTravelEndByLot()
|
||||
}
|
||||
},
|
||||
fillTravelEndByLot() {
|
||||
const line = this.selectedLine()
|
||||
const days = this.lineLotDays(line)
|
||||
if (!this.batchForm.travelStartTime || !days) return
|
||||
this.$set(this.batchForm, "travelEndTime", moment(this.batchForm.travelStartTime).add(days - 1, "days").format("YYYY-MM-DD"))
|
||||
this.validateTravelFields()
|
||||
},
|
||||
lineLotDays(line) {
|
||||
if (!line) return null
|
||||
const lotDays = this.lineField(line, "lotDays") || this.lineField(line, "lotValue")
|
||||
if (!/^\d+$/.test(String(lotDays || ""))) return null
|
||||
const days = parseInt(lotDays, 10)
|
||||
return days > 0 ? days : null
|
||||
},
|
||||
lineField(line, field) {
|
||||
if (!line) return null
|
||||
if (line[field] !== undefined) return line[field]
|
||||
const lowerField = field.toLowerCase()
|
||||
const matchedKey = Object.keys(line).find((key) => key.toLowerCase() === lowerField)
|
||||
return matchedKey ? line[matchedKey] : null
|
||||
},
|
||||
validateTravelFields() {
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.batchFormRef) {
|
||||
this.$refs.batchFormRef.validateField(["travelStartTime", "travelEndTime"])
|
||||
}
|
||||
})
|
||||
},
|
||||
dateOnly(value) {
|
||||
if (!value) return ""
|
||||
return String(value).substring(0, 10)
|
||||
},
|
||||
loadSettingPeople(callback) {
|
||||
this.$axios.post(loc() + "/settingPeople", { matterId: this.currentMatter.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const data = res.data || {}
|
||||
callback && callback(data)
|
||||
}
|
||||
})
|
||||
},
|
||||
peopleChange() {
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.batchFormRef) {
|
||||
this.$refs.batchFormRef.validateField(["minGroupPeople", "maxGroupPeople"])
|
||||
}
|
||||
})
|
||||
},
|
||||
submitBatch() {
|
||||
this.$refs.batchFormRef.validate((valid) => {
|
||||
if (!valid) return
|
||||
this.batchSubDis = true
|
||||
this.$axios.post(loc() + "/lineConfigDoSubmit", this.batchForm).then((res) => {
|
||||
this.batchSubDis = false
|
||||
if (res.code === 0) {
|
||||
this.$message.success("保存成功")
|
||||
this.batchFormVisible = false
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "保存失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
this.batchSubDis = false
|
||||
})
|
||||
})
|
||||
},
|
||||
doSubmit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (!valid) return
|
||||
this.subDis = true
|
||||
this.$axios.post(loc() + "/doSubmit", this.formData).then((res) => {
|
||||
this.subDis = false
|
||||
if (res.code === 0) {
|
||||
this.$message.success("保存成功")
|
||||
this.dialogVisible = false
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "保存失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
this.subDis = false
|
||||
})
|
||||
})
|
||||
},
|
||||
toggleEnabled(row) {
|
||||
this.$axios.post(loc() + "/doSubmit", row).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success("状态已更新")
|
||||
} else {
|
||||
row.enabled = !row.enabled
|
||||
this.$message.warning(res.msg || "状态更新失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
row.enabled = !row.enabled
|
||||
})
|
||||
},
|
||||
doDelete(row) {
|
||||
this.$set(row, "deleteLoading", true)
|
||||
this.$axios.post(loc() + "/deleteInfo", { id: row.id }).then((res) => {
|
||||
this.$set(row, "deleteLoading", false)
|
||||
if (res.code !== 0) {
|
||||
this.$message.warning(res.msg || "删除检查失败")
|
||||
return
|
||||
}
|
||||
const data = res.data || {}
|
||||
const signupCount = Number(data.signupCount || 0)
|
||||
const matterName = row.matterName || ""
|
||||
if (!data.canDelete) {
|
||||
this.$alert("事项【" + matterName + "】已有 " + signupCount + " 人报名,不能删除。", "删除提醒", {
|
||||
confirmButtonText: "知道了",
|
||||
type: "warning"
|
||||
})
|
||||
return
|
||||
}
|
||||
this.$confirm("事项【" + matterName + "】暂无人员报名,确认删除吗?", "删除提醒", {
|
||||
confirmButtonText: "确认删除",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning",
|
||||
confirmButtonClass: "el-button--danger"
|
||||
}).then(() => {
|
||||
this.$set(row, "deleteLoading", true)
|
||||
this.$axios.post(loc() + "/doDelete", { id: row.id }).then((deleteRes) => {
|
||||
this.$set(row, "deleteLoading", false)
|
||||
if (deleteRes.code === 0) {
|
||||
this.$message.success("删除成功")
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(deleteRes.msg || "删除失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
this.$set(row, "deleteLoading", false)
|
||||
})
|
||||
}).catch(() => {})
|
||||
}).catch(() => {
|
||||
this.$set(row, "deleteLoading", false)
|
||||
})
|
||||
},
|
||||
destroyForm() {
|
||||
this.formData = {}
|
||||
this.viewMode = false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadSettings(this.pageForm.year)
|
||||
this.loadUnions()
|
||||
this.loadOrganizationTypes()
|
||||
this.pageData()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,23 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<el-card shadow="never">
|
||||
<el-empty description="${title!'功能建设中'}">
|
||||
<template slot="description">
|
||||
<span>${title!'功能建设中'}正在分阶段建设中</span>
|
||||
</template>
|
||||
</el-empty>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app"
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,432 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<el-card shadow="never">
|
||||
<search :is-search-button="false">
|
||||
<search-item label="创建年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.year"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择创建年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="线路名称">
|
||||
<el-input
|
||||
v-model="pageForm.lineName"
|
||||
clearable
|
||||
placeholder="请输入线路名称"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="doSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<search-item label="时间标段">
|
||||
<el-select v-model="pageForm.lotId" clearable filterable placeholder="请选择时间标段" style="width: 100%">
|
||||
<el-option v-for="item in lotOptions" :key="item.id" :label="item.lotName" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<div class="search-query" style="margin-left: auto;">
|
||||
<el-button size="medium" type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
|
||||
<el-button size="medium" @click="resetSearch">重置</el-button>
|
||||
</div>
|
||||
</search>
|
||||
</el-card>
|
||||
|
||||
<el-card class="mt10" shadow="never">
|
||||
<table-tool :app="this" label="线路列表">
|
||||
<el-button @click="openAdd" size="medium" type="primary">
|
||||
<i class="el-icon-plus"></i>
|
||||
新增
|
||||
</el-button>
|
||||
</table-tool>
|
||||
|
||||
<el-table
|
||||
v-loading="tableLoading"
|
||||
:data="tableData"
|
||||
:size="tableSize"
|
||||
border
|
||||
:default-sort="{prop: 'enabled', order: 'descending'}"
|
||||
:row-class-name="tableRowClassName"
|
||||
@sort-change="pageOrder">
|
||||
<el-table-column label="序号" type="index" :index="indexMethod" width="80" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="创建年度" prop="year" width="120" sortable="custom" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="线路编号" prop="lineCode" width="140" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="线路名称" prop="lineName" min-width="220" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="时间标段" prop="lotName" width="140" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="线路类型" prop="lineType" width="140" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="创建人" prop="creatorName" width="140" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="是否对外开放" prop="openFlag" width="160" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-switch
|
||||
v-model="row.openFlag"
|
||||
active-text="是"
|
||||
inactive-text="否"
|
||||
@change="toggleOpenFlag(row)">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="激活状态" prop="enabled" width="160" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-switch
|
||||
v-model="row.enabled"
|
||||
active-text="启用"
|
||||
inactive-text="禁用"
|
||||
@change="toggleEnabled(row)">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="260" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
|
||||
<el-button size="mini" type="primary" @click="openEdit(row)">编辑</el-button>
|
||||
<el-button size="mini" type="danger" @click="doDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
</guava>
|
||||
|
||||
<el-dialog
|
||||
:title="title"
|
||||
:visible.sync="dialogVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="72%"
|
||||
@closed="destroyEditor">
|
||||
<el-form :model="formData" :rules="formRules" label-width="110px" ref="form" :disabled="viewMode">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="创建年度" prop="year">
|
||||
<el-date-picker
|
||||
v-model="formData.year"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择创建年度"
|
||||
style="width: 100%"
|
||||
@change="yearChange">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="旅行社名称" prop="travelAgencyId">
|
||||
<el-select v-model="formData.travelAgencyId" clearable filterable placeholder="请选择旅行社" style="width: 100%">
|
||||
<el-option v-for="item in travelAgencyOptions" :key="item.id" :label="item.agencyName" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="线路名称" prop="lineName">
|
||||
<el-input v-model="formData.lineName" maxlength="30" show-word-limit placeholder="请输入线路名称"></el-input>
|
||||
</el-form-item>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="创建人">
|
||||
<el-input v-model="formData.creatorName" readonly placeholder="当前登录人"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="所在单位">
|
||||
<el-input v-model="formData.unitName" readonly placeholder="当前登录人所在单位"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="线路编号" prop="lineCode">
|
||||
<el-input v-model="formData.lineCode" maxlength="50" placeholder="建议年度加序号,如202601"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="激活状态" prop="enabled">
|
||||
<el-radio-group v-model="formData.enabled">
|
||||
<el-radio :label="true">启用</el-radio>
|
||||
<el-radio :label="false">禁用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="是否对外开放" prop="openFlag">
|
||||
<el-radio-group v-model="formData.openFlag">
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<el-radio :label="false">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="直系亲属线路" prop="directFamilyUnitLine">
|
||||
<el-radio-group v-model="formData.directFamilyUnitLine">
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<el-radio :label="false">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="线路类型" prop="lineType">
|
||||
<el-select v-model="formData.lineType" clearable placeholder="请选择线路类型" style="width: 100%">
|
||||
<el-option v-for="item in lineTypeOptions" :key="item.code" :label="item.name" :value="item.name"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="时间标段" prop="lotId">
|
||||
<el-select v-model="formData.lotId" clearable filterable placeholder="请选择时间标段" style="width: 100%">
|
||||
<el-option v-for="item in lotOptions" :key="item.id" :label="item.lotName" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="线路内容" prop="lineContent">
|
||||
<text-editor v-model="formData.lineContent"></text-editor>
|
||||
</el-form-item>
|
||||
<el-form-item label="移动端缩略图" prop="mobileThumb">
|
||||
<!-- 与旅行社管理保持一致:移动端缩略图使用单图上传并保存URL。 -->
|
||||
<file-upload
|
||||
style="--upload-width: 200px;--upload-height:108px"
|
||||
:upload_number="1"
|
||||
:upload_size="20971520"
|
||||
:value.sync="formData.mobileThumb"
|
||||
accept=".jpg,.jpeg,.png"
|
||||
complete_result
|
||||
upload_mode="image"
|
||||
upload_result_category="interval">
|
||||
</file-upload>
|
||||
<div class="el-upload__tip">支持jpg、jpeg、png格式,大小不超过20MB。</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button v-if="!viewMode" type="primary" :loading="submitLoading" @click="doSubmit">保存</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.el-table .direct-family-row > td,
|
||||
.el-table .direct-family-row > td .cell {
|
||||
color: #f56c6c;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
mixins: [initTableMixins],
|
||||
data() {
|
||||
const currentYear = moment().format("YYYY")
|
||||
return {
|
||||
title: "",
|
||||
dialogVisible: false,
|
||||
viewMode: false,
|
||||
submitLoading: false,
|
||||
travelAgencyOptions: [],
|
||||
lotOptions: [],
|
||||
lineTypeOptions: [],
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "enabled",
|
||||
pageOrderBy: "descending",
|
||||
year: currentYear,
|
||||
lineName: "",
|
||||
lotId: ""
|
||||
},
|
||||
formData: {},
|
||||
formRules: {
|
||||
year: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
travelAgencyId: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
lineName: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
lineCode: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
lineType: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
lotId: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
mobileThumb: [{ required: true, message: "请上传移动端缩略图", trigger: ["blur", "change"] }]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetSearch() {
|
||||
this.pageForm.year = moment().format("YYYY")
|
||||
this.pageForm.lineName = ""
|
||||
this.pageForm.lotId = ""
|
||||
this.loadOptions(this.pageForm.year)
|
||||
this.doSearch()
|
||||
},
|
||||
tableRowClassName({ row }) {
|
||||
return this.isDirectFamilyLine(row) ? "direct-family-row" : ""
|
||||
},
|
||||
isDirectFamilyLine(row) {
|
||||
if (!row) return false
|
||||
return row.directFamilyUnitLine === true
|
||||
|| row.directFamilyUnitLine === 1
|
||||
|| row.directFamilyUnitLine === "1"
|
||||
},
|
||||
emptyForm() {
|
||||
const user = (this.$store && this.$store.state && this.$store.state.user) || {}
|
||||
return {
|
||||
year: moment().format("YYYY"),
|
||||
travelAgencyId: "",
|
||||
creatorUserId: user.id || "",
|
||||
creatorName: user.username || "",
|
||||
unitId: user.unit?.id || "",
|
||||
unitName: user.unit?.name || "",
|
||||
lineName: "",
|
||||
lineCode: "",
|
||||
enabled: true,
|
||||
openFlag: true,
|
||||
directFamilyUnitLine: false,
|
||||
lineType: "",
|
||||
lotId: "",
|
||||
lineContent: "",
|
||||
mobileThumb: ""
|
||||
}
|
||||
},
|
||||
openAdd() {
|
||||
this.title = "新增线路信息"
|
||||
this.viewMode = false
|
||||
this.formData = this.emptyForm()
|
||||
this.loadOptions(this.formData.year)
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
|
||||
},
|
||||
openEdit(row) {
|
||||
this.title = "编辑线路信息"
|
||||
this.viewMode = false
|
||||
this.loadDetail(row.id)
|
||||
},
|
||||
openView(row) {
|
||||
this.title = "查看线路信息"
|
||||
this.viewMode = true
|
||||
this.loadDetail(row.id)
|
||||
},
|
||||
loadDetail(id) {
|
||||
this.$axios.post(loc() + "/detail", { id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.formData = Object.assign(this.emptyForm(), res.data || {})
|
||||
this.formData.year = this.formData.year ? String(this.formData.year) : ""
|
||||
this.loadOptions(this.formData.year)
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
|
||||
} else {
|
||||
this.$message.warning(res.msg || "查询失败")
|
||||
}
|
||||
})
|
||||
},
|
||||
yearChange(year) {
|
||||
this.formData.travelAgencyId = ""
|
||||
this.formData.lotId = ""
|
||||
this.loadOptions(year)
|
||||
},
|
||||
loadOptions(year) {
|
||||
this.loadTravelAgencies(year)
|
||||
this.loadLots(year)
|
||||
this.loadLineTypes()
|
||||
},
|
||||
loadTravelAgencies(year) {
|
||||
this.$axios.post(loc() + "/travelAgencyOptions", { year }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.travelAgencyOptions = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
loadLots(year) {
|
||||
this.$axios.post(loc() + "/lotOptions", { year }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.lotOptions = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
loadLineTypes() {
|
||||
this.$axios.post(loc() + "/lineTypeOptions").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.lineTypeOptions = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
doSubmit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (!valid) return
|
||||
this.submitLoading = true
|
||||
this.$axios.post(loc() + "/doSubmit", this.formData).then((res) => {
|
||||
this.submitLoading = false
|
||||
if (res.code === 0) {
|
||||
this.$message.success("保存成功")
|
||||
this.dialogVisible = false
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "保存失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
this.submitLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
toggleEnabled(row) {
|
||||
this.$axios.post(loc() + "/doSubmit", row).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success("状态已更新")
|
||||
} else {
|
||||
row.enabled = !row.enabled
|
||||
this.$message.warning(res.msg || "状态更新失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
row.enabled = !row.enabled
|
||||
})
|
||||
},
|
||||
toggleOpenFlag(row) {
|
||||
this.$axios.post(loc() + "/doSubmit", row).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success("对外开放状态已更新")
|
||||
} else {
|
||||
row.openFlag = !row.openFlag
|
||||
this.$message.warning(res.msg || "对外开放状态更新失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
row.openFlag = !row.openFlag
|
||||
})
|
||||
},
|
||||
doDelete(row) {
|
||||
this.$confirm("确定删除【" + row.lineName + "】吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
this.$axios.post(loc() + "/doDelete", { id: row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success("删除成功")
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "删除失败")
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
destroyEditor() {
|
||||
this.formData = {}
|
||||
this.viewMode = false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadOptions(this.pageForm.year)
|
||||
this.pageData()
|
||||
},
|
||||
watch: {
|
||||
"pageForm.year"(year) {
|
||||
this.pageForm.lotId = ""
|
||||
this.loadOptions(year)
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
+549
@@ -0,0 +1,549 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<el-card shadow="never">
|
||||
<search :is-search-button="false">
|
||||
<search-item label="开始年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.startYear"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择开始年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="结束年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.endYear"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择结束年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="姓名/工号">
|
||||
<el-input
|
||||
v-model="pageForm.keyword"
|
||||
clearable
|
||||
placeholder="请输入姓名或工号"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="doSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<search-item label="所属工会">
|
||||
<el-select v-model="pageForm.unionId" clearable filterable placeholder="请选择所属工会" style="width: 100%">
|
||||
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="线路">
|
||||
<el-select v-model="pageForm.lineId" clearable filterable placeholder="请选择线路" style="width: 100%">
|
||||
<el-option v-for="item in lineOptions" :key="item.lineId" :label="item.lineName" :value="item.lineId"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="出行时段">
|
||||
<el-select v-model="pageForm.travelPeriod" clearable filterable placeholder="请选择出行时段" style="width: 100%">
|
||||
<el-option v-for="item in travelPeriodOptions" :key="item.travelPeriod" :label="item.travelPeriod" :value="item.travelPeriod"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="线路类型">
|
||||
<el-select v-model="pageForm.lineType" clearable filterable placeholder="请选择线路类型" style="width: 100%">
|
||||
<el-option v-for="item in lineTypeOptions" :key="item.lineType" :label="item.lineType" :value="item.lineType"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<div class="search-query" style="margin-left: auto;">
|
||||
<el-button size="medium" type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
|
||||
<el-button size="medium" @click="resetSearch">重置</el-button>
|
||||
</div>
|
||||
</search>
|
||||
</el-card>
|
||||
|
||||
<el-card class="mt10" shadow="never">
|
||||
<table-tool :app="this" label="校工会审核">
|
||||
<el-radio-group class="mr5" size="small" v-model="pageForm.audit" @change="changeAudit">
|
||||
<el-radio-button :label="true">已审核</el-radio-button>
|
||||
<el-radio-button :label="false">未审核</el-radio-button>
|
||||
</el-radio-group>
|
||||
</table-tool>
|
||||
<el-table
|
||||
v-loading="tableLoading"
|
||||
:data="tableData"
|
||||
:size="tableSize"
|
||||
border
|
||||
@sort-change="pageOrder">
|
||||
<el-table-column label="序号" type="index" :index="indexMethod" width="80" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="工号" prop="jobNo" width="130" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="姓名" prop="userName" width="120" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="所在单位" prop="unitName" min-width="180" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="报名线路" prop="lineName" min-width="220" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="出行时段" prop="travelPeriod" min-width="220" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="线路类型" prop="lineType" width="130" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="报名时间" prop="signupTime" width="170" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="携带家属" prop="familyCount" width="120" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="Number(row.familyCount || 0) > 0 ? 'success' : 'info'">{{ row.familyCount || 0 }}人</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="报销超出费用" prop="overCostReimbursed" width="140" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="row.overCostReimbursed ? 'success' : 'info'">{{ row.overCostReimbursed ? '是' : '否' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="当前节点" prop="curTaskName" width="140" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="流程状态" prop="instanceState" width="120" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160" align="center" header-align="center" fixed="right">
|
||||
<template slot-scope="{row}">
|
||||
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
|
||||
<el-button v-if="row.taskState === 10" size="mini" type="primary" @click="openApproval(row)">审核</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
|
||||
<template #edit>
|
||||
<tour-approval-info ref="infoRef">
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">
|
||||
{{ formData.taskName }}
|
||||
</div>
|
||||
<el-form
|
||||
:model="formData"
|
||||
ref="formRef"
|
||||
label-width="0"
|
||||
label-suffix=":"
|
||||
class="flow-task-form">
|
||||
<el-form-item
|
||||
label="审批意见"
|
||||
prop="tf_opinion"
|
||||
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
|
||||
<user-opinion-textarea v-model="formData.tf_opinion"></user-opinion-textarea>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-row type="flex" justify="end">
|
||||
<el-button @click="$refs.guava.index()" size="small">取消</el-button>
|
||||
<el-button @click="handleTaskAction(6)" size="small" type="info">退回到发起人</el-button>
|
||||
<el-button @click="handleTaskAction(2)" size="small" type="danger">拒绝申请</el-button>
|
||||
<el-button @click="handleTaskAction(1)" size="small" type="primary">同意申请</el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
</tour-approval-info>
|
||||
</template>
|
||||
</guava>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
#app .search .search-item {
|
||||
width: calc((100% - 150px) / 4);
|
||||
}
|
||||
#app .search .search-query {
|
||||
margin-left: auto;
|
||||
}
|
||||
@media screen and (max-width: 1350px) {
|
||||
#app .search .search-item {
|
||||
width: calc((100% - 100px) / 3);
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 1200px) {
|
||||
#app .search .search-item {
|
||||
width: calc((100% - 50px) / 2);
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 992px) {
|
||||
#app .search .search-item {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.tour-approval-section {
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
.tour-approval-table {
|
||||
width: 100%;
|
||||
}
|
||||
.tour-approval-empty {
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
const TOUR_APPROVAL_INFO = {
|
||||
template: [
|
||||
"\n",
|
||||
" <div>\n",
|
||||
" <div class=\"process-title\">\n",
|
||||
" 报名信息\n",
|
||||
" <el-link type=\"primary\" @click=\"openChart\">点击查看流程图</el-link>\n",
|
||||
" </div>\n",
|
||||
" <el-descriptions :column=\"3\" border class=\"tour-approval-section\">\n",
|
||||
" <el-descriptions-item label=\"工号\">{{ detail.jobNo || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"姓名\">{{ detail.userName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"性别\">{{ detail.gender || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"身份证号\">{{ detail.idCard || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"所在单位\">{{ detail.unitName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"所在工会\">{{ detail.unionName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"报名时间\">{{ detail.signupTime || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"报名线路\">{{ detail.lineName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"出行时段\">{{ detail.travelPeriod || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"线路类型\">{{ detail.lineType || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"报名酒店\">{{ detail.hotelName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"旅行社\">{{ detail.travelAgencyName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"是否携带家属\">\n",
|
||||
" {{ familyText() }}\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"报销超出费用\">{{ detail.overCostReimbursed ? '是' : '否' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item v-if=\"fillBedInfo\" label=\"意向拼床人\">{{ detail.intendedRoommate || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item v-if=\"fillBedInfo\" label=\"床型\">{{ detail.bedType || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item v-if=\"fillBedInfo\" label=\"床位信息\">{{ detail.bedInfo || '' }}</el-descriptions-item>\n",
|
||||
" </el-descriptions>\n",
|
||||
"\n",
|
||||
" <div v-if=\"isDirectFamilyLine()\" class=\"tour-approval-section\">\n",
|
||||
" <div class=\"process-title\">直系亲属线路</div>\n",
|
||||
" <el-descriptions :column=\"3\" border>\n",
|
||||
" <el-descriptions-item label=\"亲属姓名\">{{ directRelative.relativeName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"所在单位\">{{ directRelative.unitName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"亲属关系\">{{ directRelative.relationshipName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"线路名称\">{{ directRelative.lineName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"出行开始日期\">{{ directRelative.travelStartTime || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"出行结束日期\">{{ directRelative.travelEndTime || '' }}</el-descriptions-item>\n",
|
||||
" </el-descriptions>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <div v-if=\"showFamilySection()\" class=\"tour-approval-section\">\n",
|
||||
" <div class=\"process-title\">亲属信息</div>\n",
|
||||
" <el-table :data=\"familyData\" border size=\"mini\" empty-text=\"暂无亲属信息\" class=\"tour-approval-table\">\n",
|
||||
" <el-table-column label=\"序号\" type=\"index\" width=\"70\" align=\"center\" header-align=\"center\"></el-table-column>\n",
|
||||
" <el-table-column label=\"家属姓名\" prop=\"familyName\" min-width=\"120\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" <el-table-column label=\"性别\" prop=\"gender\" width=\"90\" align=\"center\" header-align=\"center\"></el-table-column>\n",
|
||||
" <el-table-column label=\"身份证号码\" prop=\"idCard\" min-width=\"180\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" <el-table-column label=\"年龄\" prop=\"age\" width=\"90\" align=\"center\" header-align=\"center\"></el-table-column>\n",
|
||||
" <el-table-column label=\"关系\" prop=\"relationship\" width=\"110\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" <el-table-column v-if=\"fillBedInfo\" label=\"床型\" prop=\"bedType\" width=\"110\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" <el-table-column v-if=\"fillBedInfo\" label=\"床位\" prop=\"bedInfo\" min-width=\"120\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" <el-table-column v-if=\"fillBedInfo\" label=\"意向拼床人\" prop=\"intendedRoommate\" min-width=\"130\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" </el-table>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <template v-for=\"task in doneTasks\">\n",
|
||||
" <div class=\"mt10\">\n",
|
||||
" <div class=\"process-title\">{{ task.displayName }}</div>\n",
|
||||
" <el-descriptions border class=\"flow-task-form\" :column=\"3\" :key=\"task.id\" v-if=\"task.ext.isFirstTaskNode\">\n",
|
||||
" <el-descriptions-item label=\"申请用户\">\n",
|
||||
" {{ task.ext.initiatorName }}({{ task.ext.initiatorAccount }})\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"申请时间\">{{ task.finishTime }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"办理结果\">\n",
|
||||
" <dict-tag :options=\"dict.type.PROCESS_TASK_SUBMIT_TYPE\" :value=\"task.ext.submitType\"></dict-tag>\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" </el-descriptions>\n",
|
||||
"\n",
|
||||
" <el-descriptions border class=\"flow-task-form\" :column=\"3\" :key=\"task.id\" v-else>\n",
|
||||
" <el-descriptions-item label=\"办理用户\">\n",
|
||||
" {{ task.taskFormData.userName }}({{ task.taskFormData.loginName }})\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"办理时间\">{{ task.finishTime }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"办理结果\">\n",
|
||||
" <dict-tag :options=\"dict.type.PROCESS_TASK_SUBMIT_TYPE\" :value=\"task.ext.submitType\"></dict-tag>\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"办理意见\" :span=\"3\">\n",
|
||||
" {{ task.taskFormData.opinion || task.taskFormData.tf_opinion || '' }}\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" </el-descriptions>\n",
|
||||
" </div>\n",
|
||||
" </template>\n",
|
||||
"\n",
|
||||
" <slot></slot>\n",
|
||||
"\n",
|
||||
" <snaker-chart ref=\"snakerChartRef\"></snaker-chart>\n",
|
||||
" </div>\n",
|
||||
" \n"
|
||||
].join(""),
|
||||
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
|
||||
data() {
|
||||
return {
|
||||
row: {},
|
||||
detail: {},
|
||||
familyData: [],
|
||||
directRelative: {},
|
||||
allowFamily: false,
|
||||
fillBedInfo: true,
|
||||
directFamilyUnitLine: false,
|
||||
doneTasks: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onOpen(row) {
|
||||
this.row = row || {}
|
||||
this.detail = {}
|
||||
this.familyData = []
|
||||
this.directRelative = {}
|
||||
this.allowFamily = false
|
||||
this.fillBedInfo = true
|
||||
this.directFamilyUnitLine = false
|
||||
this.doneTasks = []
|
||||
this.info()
|
||||
this.getDoneTasks()
|
||||
},
|
||||
info() {
|
||||
this.$axios.post(loc() + "/detail", { id: this.row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const data = res.data || {}
|
||||
this.detail = data.ledger || {}
|
||||
this.detail.travelPeriod = data.travelPeriod || this.row.travelPeriod || ""
|
||||
this.familyData = data.families || []
|
||||
this.directRelative = data.directRelative || {}
|
||||
this.allowFamily = this.toBoolean(data.allowFamily)
|
||||
this.fillBedInfo = data.fillBedInfo === undefined || data.fillBedInfo === null || this.toBoolean(data.fillBedInfo)
|
||||
this.directFamilyUnitLine = this.toBoolean(data.directFamilyUnitLine)
|
||||
} else {
|
||||
this.$message.warning(res.msg || "查询失败")
|
||||
}
|
||||
})
|
||||
},
|
||||
toBoolean(value) {
|
||||
return value === true || value === 1 || value === "1"
|
||||
},
|
||||
isDirectFamilyLine() {
|
||||
return this.directFamilyUnitLine
|
||||
|| this.toBoolean(this.detail.directFamilyUnitLine)
|
||||
|| (this.directRelative && this.directRelative.id)
|
||||
},
|
||||
hasFamily() {
|
||||
return this.toBoolean(this.detail.hasFamily) || this.familyData.length > 0
|
||||
},
|
||||
showFamilySection() {
|
||||
return this.allowFamily && this.hasFamily() && !this.isDirectFamilyLine()
|
||||
},
|
||||
familyText() {
|
||||
if (this.isDirectFamilyLine()) {
|
||||
return "否"
|
||||
}
|
||||
if (!this.allowFamily) {
|
||||
return "否"
|
||||
}
|
||||
return this.hasFamily() ? "是" : "否"
|
||||
},
|
||||
getDoneTasks() {
|
||||
this.$axios.post("/flow/common/doneTasks", { bizId: this.row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.doneTasks = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
openChart() {
|
||||
if (!this.row.instanceProcessDefineId || !this.row.instanceId) {
|
||||
this.$message.warning("暂无流程图信息")
|
||||
return
|
||||
}
|
||||
this.$refs.snakerChartRef.onOpenFull(this.row.instanceProcessDefineId, this.row.instanceId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new Vue({
|
||||
el: "#app",
|
||||
mixins: [initTableMixins],
|
||||
data() {
|
||||
const currentYear = moment().format("YYYY")
|
||||
return {
|
||||
unionOptions: [],
|
||||
lineOptions: [],
|
||||
travelPeriodOptions: [],
|
||||
lineTypeOptions: [],
|
||||
showApprovalForm: false,
|
||||
formData: {
|
||||
tf_opinion: ""
|
||||
},
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "signupTime",
|
||||
pageOrderBy: "descending",
|
||||
audit: false,
|
||||
startYear: currentYear,
|
||||
endYear: currentYear,
|
||||
keyword: "",
|
||||
unionId: "",
|
||||
lineId: "",
|
||||
travelPeriod: "",
|
||||
lineType: ""
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetSearch() {
|
||||
this.pageForm.startYear = moment().format("YYYY")
|
||||
this.pageForm.endYear = moment().format("YYYY")
|
||||
this.pageForm.keyword = ""
|
||||
this.pageForm.unionId = ""
|
||||
this.pageForm.lineId = ""
|
||||
this.pageForm.travelPeriod = ""
|
||||
this.pageForm.lineType = ""
|
||||
this.loadOptions()
|
||||
this.doSearch()
|
||||
},
|
||||
changeAudit() {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.clearCascadeFilters()
|
||||
this.loadOptions()
|
||||
this.pageData()
|
||||
},
|
||||
clearCascadeFilters() {
|
||||
this.pageForm.unionId = ""
|
||||
this.pageForm.lineId = ""
|
||||
this.pageForm.travelPeriod = ""
|
||||
this.pageForm.lineType = ""
|
||||
},
|
||||
openView(row) {
|
||||
this.$refs.guava.edit(() => {
|
||||
this.showApprovalForm = false
|
||||
this.formData = {
|
||||
tf_opinion: ""
|
||||
}
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
})
|
||||
},
|
||||
openApproval(row) {
|
||||
this.$refs.guava.edit(() => {
|
||||
this.showApprovalForm = true
|
||||
this.formData = {
|
||||
processTaskId: row.taskId,
|
||||
taskName: row.curTaskName || row.taskName,
|
||||
tf_opinion: ""
|
||||
}
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
})
|
||||
},
|
||||
handleTaskAction(val) {
|
||||
this.$refs.formRef.validate((valid) => {
|
||||
if (!valid) return
|
||||
this.$confirm("您确定要提交吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
const loading = createLoading()
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: val
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.guava.index()
|
||||
this.$message.success(res.msg || "操作成功")
|
||||
this.doSearch()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "操作失败")
|
||||
}
|
||||
}).finally(() => {
|
||||
loading.close()
|
||||
})
|
||||
}).catch(() => {})
|
||||
})
|
||||
},
|
||||
loadOptions() {
|
||||
this.loadUnionOptions()
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
},
|
||||
baseOptionParams() {
|
||||
return {
|
||||
audit: this.pageForm.audit,
|
||||
startYear: this.pageForm.startYear,
|
||||
endYear: this.pageForm.endYear,
|
||||
keyword: this.pageForm.keyword,
|
||||
unionId: this.pageForm.unionId,
|
||||
lineId: this.pageForm.lineId,
|
||||
travelPeriod: this.pageForm.travelPeriod,
|
||||
lineType: this.pageForm.lineType
|
||||
}
|
||||
},
|
||||
loadUnionOptions() {
|
||||
this.$axios.post(loc() + "/unionOptions", this.baseOptionParams()).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.unionOptions = res.data || []
|
||||
if (this.pageForm.unionId && !this.unionOptions.some(item => item.id === this.pageForm.unionId)) {
|
||||
this.pageForm.unionId = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadLineOptions() {
|
||||
this.$axios.post(loc() + "/lineOptions", this.baseOptionParams()).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.lineOptions = res.data || []
|
||||
if (this.pageForm.lineId && !this.lineOptions.some(item => item.lineId === this.pageForm.lineId)) {
|
||||
this.pageForm.lineId = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadTravelPeriodOptions() {
|
||||
this.$axios.post(loc() + "/travelPeriodOptions", this.baseOptionParams()).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.travelPeriodOptions = res.data || []
|
||||
if (this.pageForm.travelPeriod && !this.travelPeriodOptions.some(item => item.travelPeriod === this.pageForm.travelPeriod)) {
|
||||
this.pageForm.travelPeriod = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadLineTypeOptions() {
|
||||
this.$axios.post(loc() + "/lineTypeOptions", this.baseOptionParams()).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.lineTypeOptions = res.data || []
|
||||
if (this.pageForm.lineType && !this.lineTypeOptions.some(item => item.lineType === this.pageForm.lineType)) {
|
||||
this.pageForm.lineType = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadOptions()
|
||||
this.pageData()
|
||||
},
|
||||
components: {
|
||||
"tour-approval-info": TOUR_APPROVAL_INFO
|
||||
},
|
||||
watch: {
|
||||
"pageForm.startYear"() {
|
||||
this.clearCascadeFilters()
|
||||
this.loadOptions()
|
||||
},
|
||||
"pageForm.endYear"() {
|
||||
this.clearCascadeFilters()
|
||||
this.loadOptions()
|
||||
},
|
||||
"pageForm.lineId"() {
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
},
|
||||
"pageForm.travelPeriod"() {
|
||||
this.loadLineOptions()
|
||||
this.loadLineTypeOptions()
|
||||
},
|
||||
"pageForm.lineType"() {
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
},
|
||||
"pageForm.unionId"() {
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,636 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<el-card shadow="never">
|
||||
<search :is-search-button="false">
|
||||
<search-item label="年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.year"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="配置名称">
|
||||
<el-input
|
||||
v-model="pageForm.configName"
|
||||
clearable
|
||||
placeholder="请输入疗休养配置名称"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="doSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<div class="search-query">
|
||||
<el-button size="medium" type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
|
||||
<el-button size="medium" @click="resetSearch">重置</el-button>
|
||||
</div>
|
||||
</search>
|
||||
</el-card>
|
||||
|
||||
<el-card class="mt10" shadow="never">
|
||||
<table-tool :app="this" label="疗休养配置">
|
||||
<el-button type="primary" size="medium" @click="openAdd">
|
||||
<i class="el-icon-plus"></i>
|
||||
新建
|
||||
</el-button>
|
||||
</table-tool>
|
||||
|
||||
<el-table
|
||||
:data="tableData"
|
||||
:size="tableSize"
|
||||
border
|
||||
class="vi-table"
|
||||
ref="table"
|
||||
row-key="id"
|
||||
v-loading="tableLoading"
|
||||
@sort-change="pageOrder"
|
||||
>
|
||||
<el-table-column label="序号" type="index" :index="indexMethod" width="70" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="年度" prop="year" width="100" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="疗休养配置名称" prop="configName" min-width="260" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="周期开始年度" prop="cycleStartYear" width="130" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="最少成团人数" prop="minGroupPeople" width="120" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="最多成团人数" prop="maxGroupPeople" width="120" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="是否携带家属" prop="allowFamily" width="120" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" type="success" v-if="row.allowFamily">允许</el-tag>
|
||||
<el-tag size="mini" type="info" v-else>不允许</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否启用" prop="enabled" width="100" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" type="success" v-if="row.enabled">启用</el-tag>
|
||||
<el-tag size="mini" type="info" v-else>停用</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="150" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-button size="mini" type="primary" @click="openEdit(row)">编辑</el-button>
|
||||
<el-button size="mini" type="danger" @click="doDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
</guava>
|
||||
|
||||
<el-dialog
|
||||
:title="title"
|
||||
:visible.sync="dialogVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="64.8%"
|
||||
@closed="destroyEditor">
|
||||
<el-form :model="formData" :rules="formRules" label-width="120px" ref="form">
|
||||
<div v-if="title === '新建疗休养配置'" class="tour-setting-inherit">
|
||||
<el-button type="primary" plain size="medium" icon="el-icon-copy-document" :loading="inheritLoading" @click="inheritPreviousYearInfo">延用上一年信息</el-button>
|
||||
</div>
|
||||
<el-tabs v-model="activeTab" type="card">
|
||||
<el-tab-pane label="基本信息" name="basic">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="年度" prop="year">
|
||||
<el-date-picker
|
||||
v-model="formData.year"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择年度"
|
||||
style="width: 100%"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="配置名称" prop="configName">
|
||||
<el-input v-model="formData.configName" maxlength="100" placeholder="请输入配置名称"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="疗休养类型" prop="tourType">
|
||||
<el-select v-model="formData.tourType" clearable allow-create filterable placeholder="请选择或输入类型" style="width: 100%">
|
||||
<el-option label="省内疗休养" value="省内疗休养"></el-option>
|
||||
<el-option label="省外疗休养" value="省外疗休养"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="可参加人员" prop="activityGroupId">
|
||||
<div class="tour-user-scope">
|
||||
<el-select
|
||||
v-model="formData.activityGroupId"
|
||||
placeholder="请选择可参加人员"
|
||||
filterable
|
||||
clearable
|
||||
style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in activityGroupList"
|
||||
:key="item.groupId"
|
||||
:label="item.groupName"
|
||||
:value="item.groupId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-button type="primary" @click="openUserScope">设置</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="最少成团人数" prop="minGroupPeople">
|
||||
<el-input-number v-model="formData.minGroupPeople" :controls="false" :min="0" :precision="0" placeholder="请输入最少成团人数" style="width: 100%"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="最多成团人数" prop="maxGroupPeople">
|
||||
<el-input-number v-model="formData.maxGroupPeople" :controls="false" :min="0" :precision="0" placeholder="请输入最多成团人数" style="width: 100%"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<div class="tour-setting-basic-divider"></div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="省外几年去一次" prop="outProvinceYears">
|
||||
<el-input-number v-model="formData.outProvinceYears" :controls="false" :min="0" :precision="0" placeholder="请输入省外间隔年限" style="width: 100%"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="省外人数占比" prop="outProvinceRatio">
|
||||
<el-input-number v-model="formData.outProvinceRatio" :controls="false" :min="0" :max="100" :precision="2" placeholder="请输入省外人数占比" style="width: 100%"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="省外占比类型" prop="outProvinceRatioType">
|
||||
<el-select v-model="formData.outProvinceRatioType" placeholder="请选择省外占比类型" style="width: 100%" @change="outProvinceRatioTypeChange">
|
||||
<el-option label="当年报名人数" value="当年报名人数"></el-option>
|
||||
<el-option label="可参加教职工人数" value="可参加教职工人数"></el-option>
|
||||
<el-option label="固定人数" value="固定人数"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-if="formData.outProvinceRatioType === '固定人数'" :span="12">
|
||||
<el-form-item label="固定人数" prop="outProvinceFixedPeople">
|
||||
<el-input-number v-model="formData.outProvinceFixedPeople" :controls="false" :min="0" :precision="0" placeholder="请输入固定人数" style="width: 100%"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<div class="tour-setting-basic-divider"></div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="周期开始年度" prop="cycleStartYear">
|
||||
<el-date-picker
|
||||
v-model="formData.cycleStartYear"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
clearable
|
||||
placeholder="请选择周期开始年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="周期结束年度" prop="cycleEndYear">
|
||||
<el-date-picker
|
||||
v-model="formData.cycleEndYear"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
clearable
|
||||
placeholder="请选择周期结束年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="周期内总费用" prop="cycleTotalCost">
|
||||
<el-input-number v-model="formData.cycleTotalCost" :controls="false" :min="0" :precision="0" placeholder="请输入周期内总费用" style="width: 100%"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="周期允许次数" prop="cycleAllowedTimes">
|
||||
<el-input-number v-model="formData.cycleAllowedTimes" :controls="false" :min="0" :precision="0" placeholder="请输入周期允许次数" style="width: 100%"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<div class="tour-setting-basic-divider"></div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="允许携带家属" prop="allowFamily">
|
||||
<el-switch v-model="formData.allowFamily" active-text="允许" inactive-text="不允许"></el-switch>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="填报床位信息" prop="fillBedInfo">
|
||||
<el-switch v-model="formData.fillBedInfo" active-text="是" inactive-text="否"></el-switch>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="是否启用" prop="enabled">
|
||||
<el-switch v-model="formData.enabled" active-text="启用" inactive-text="停用"></el-switch>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="标段管理" name="lots">
|
||||
<div style="text-align: right; margin-bottom: 10px;">
|
||||
<el-button type="primary" size="medium" icon="el-icon-plus" @click="addLot">增加一条</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
:data="formData.lots"
|
||||
border
|
||||
class="vi-table"
|
||||
empty-text="暂无标段"
|
||||
style="width: 100%">
|
||||
<el-table-column label="序号" type="index" width="70" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="标段名称" min-width="180" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-input v-model="row.lotName" maxlength="50" placeholder="请输入标段名称"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="标段值" min-width="160" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-input v-model="row.lotValue" maxlength="10" placeholder="请输入整数" @input="integerInput(row, 'lotValue', $event)"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="标段费用" min-width="150" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-input v-model="row.activityCost" maxlength="10" placeholder="请输入整数" @input="integerInput(row, 'activityCost', $event)"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="允许超出报销" width="140" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-checkbox v-model="row.allowOverReimbursement"></el-checkbox>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="90" align="center" header-align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="danger" size="mini" icon="el-icon-delete" @click="deleteLot(scope.$index, scope.row)"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="服务须知" name="notice">
|
||||
<el-form-item prop="serviceNotice" label-width="0">
|
||||
<text-editor v-model="formData.serviceNotice"></text-editor>
|
||||
</el-form-item>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="submitLoading" @click="doSubmit">确认</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
<drawer-user-scope
|
||||
ref="drawerUserScope"
|
||||
:group_id.sync="formData.activityGroupId"
|
||||
@group_change="handleActivityGroupChange">
|
||||
</drawer-user-scope>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
mixins: [initTableMixins],
|
||||
data() {
|
||||
// 前端先做成团人数区间校验,后端也会再兜底校验一次。
|
||||
const checkGroupPeople = (rule, value, callback) => {
|
||||
if (this.formData.minGroupPeople !== null && this.formData.maxGroupPeople !== null
|
||||
&& this.formData.minGroupPeople > this.formData.maxGroupPeople) {
|
||||
callback(new Error("最少成团人数不能大于最多成团人数"))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const checkCycleYear = (rule, value, callback) => {
|
||||
const startYear = parseInt(this.formData.cycleStartYear, 10)
|
||||
const endYear = parseInt(this.formData.cycleEndYear, 10)
|
||||
if (!isNaN(startYear) && !isNaN(endYear) && startYear > endYear) {
|
||||
callback(new Error("周期开始年度不能大于周期结束年度"))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const checkOutProvinceFixedPeople = (rule, value, callback) => {
|
||||
if (this.formData.outProvinceRatioType === "固定人数"
|
||||
&& (value === null || value === undefined || value === "" || value < 0)) {
|
||||
callback(new Error("固定人数必须大于等于0"))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
return {
|
||||
title: "",
|
||||
dialogVisible: false,
|
||||
activeTab: "basic",
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
year: "",
|
||||
configName: ""
|
||||
},
|
||||
activityGroupList: [],
|
||||
formData: {},
|
||||
lotDeleteList: [],
|
||||
inheritLoading: false,
|
||||
formRules: {
|
||||
year: [{required: true, message: "必填", trigger: ["blur", "change"]}],
|
||||
configName: [{required: true, message: "必填", trigger: ["blur", "change"]}],
|
||||
minGroupPeople: [{validator: checkGroupPeople, trigger: ["blur", "change"]}],
|
||||
maxGroupPeople: [{validator: checkGroupPeople, trigger: ["blur", "change"]}],
|
||||
outProvinceRatioType: [{required: true, message: "必填", trigger: ["blur", "change"]}],
|
||||
outProvinceFixedPeople: [{validator: checkOutProvinceFixedPeople, trigger: ["blur", "change"]}],
|
||||
cycleStartYear: [{validator: checkCycleYear, trigger: ["blur", "change"]}],
|
||||
cycleEndYear: [{validator: checkCycleYear, trigger: ["blur", "change"]}]
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
"drawer-user-scope": httpVueLoader("/components/module/activity/DrawerUserScope.vue")
|
||||
},
|
||||
methods: {
|
||||
getActivityGroup() {
|
||||
return this.$axios.post("/platform/activity/basic/scope/getActivityUserScopeGroup").then((res) => {
|
||||
const data = res.data
|
||||
this.activityGroupList = (data || []).map((item) => {
|
||||
return Object.assign({}, item, {
|
||||
groupId: item.groupId === null || item.groupId === undefined ? "" : String(item.groupId)
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
openUserScope() {
|
||||
if (this.$refs.drawerUserScope) {
|
||||
this.$refs.drawerUserScope.groupId = this.formData.activityGroupId || ""
|
||||
this.$refs.drawerUserScope.userScopeDialog = true
|
||||
}
|
||||
},
|
||||
async handleActivityGroupChange() {
|
||||
if (this.formData.activityGroupId !== null && this.formData.activityGroupId !== undefined) {
|
||||
this.formData.activityGroupId = String(this.formData.activityGroupId)
|
||||
}
|
||||
await this.getActivityGroup()
|
||||
},
|
||||
resetSearch() {
|
||||
this.pageForm.year = ""
|
||||
this.pageForm.configName = ""
|
||||
this.doSearch()
|
||||
},
|
||||
defaultFormData() {
|
||||
return {
|
||||
year: moment().format("YYYY"),
|
||||
configName: "",
|
||||
tourType: "",
|
||||
activityGroupId: "",
|
||||
sortNo: 0,
|
||||
minGroupPeople: 0,
|
||||
maxGroupPeople: 0,
|
||||
outProvinceYears: 0,
|
||||
outProvinceRatio: 0,
|
||||
outProvinceRatioType: "当年报名人数",
|
||||
outProvinceFixedPeople: 0,
|
||||
cycleStartYear: "",
|
||||
cycleEndYear: "",
|
||||
cycleTotalCost: null,
|
||||
cycleAllowedTimes: null,
|
||||
allowFamily: false,
|
||||
fillBedInfo: true,
|
||||
enabled: true,
|
||||
lots: [],
|
||||
serviceNotice: ""
|
||||
}
|
||||
},
|
||||
openAdd() {
|
||||
this.title = "新建疗休养配置"
|
||||
this.lotDeleteList = []
|
||||
this.activeTab = "basic"
|
||||
// 新建时给出默认年度和开关值,减少校工会管理员录入成本。
|
||||
this.formData = this.defaultFormData()
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
|
||||
},
|
||||
inheritPreviousYearInfo() {
|
||||
const currentYear = parseInt(this.formData.year, 10)
|
||||
if (isNaN(currentYear)) {
|
||||
this.$message.warning("请先选择年度")
|
||||
return
|
||||
}
|
||||
this.inheritLoading = true
|
||||
this.$axios.post(loc() + "/previousYearInfo", {year: currentYear}).then((res) => {
|
||||
this.inheritLoading = false
|
||||
if (res.code !== 0) {
|
||||
this.$message.warning(res.msg || "未找到上一年度配置")
|
||||
return
|
||||
}
|
||||
const previous = res.data || {}
|
||||
const inheritedLots = (previous.lots || []).map(item => {
|
||||
return {
|
||||
lotName: item.lotName || "",
|
||||
lotValue: item.lotValue || "",
|
||||
activityCost: item.activityCost,
|
||||
allowOverReimbursement: !!item.allowOverReimbursement
|
||||
}
|
||||
})
|
||||
this.formData = Object.assign(this.defaultFormData(), previous, {
|
||||
year: String(currentYear),
|
||||
cycleStartYear: previous.cycleStartYear ? String(previous.cycleStartYear) : "",
|
||||
cycleEndYear: previous.cycleEndYear ? String(previous.cycleEndYear) : "",
|
||||
lots: inheritedLots
|
||||
})
|
||||
delete this.formData.id
|
||||
delete this.formData.createdAt
|
||||
delete this.formData.createdBy
|
||||
delete this.formData.updatedAt
|
||||
delete this.formData.updatedBy
|
||||
delete this.formData.delFlag
|
||||
if (!this.formData.outProvinceRatioType) {
|
||||
this.$set(this.formData, "outProvinceRatioType", "当年报名人数")
|
||||
}
|
||||
if (this.formData.outProvinceFixedPeople === null || this.formData.outProvinceFixedPeople === undefined) {
|
||||
this.$set(this.formData, "outProvinceFixedPeople", 0)
|
||||
}
|
||||
if (this.formData.fillBedInfo === null || this.formData.fillBedInfo === undefined) {
|
||||
this.$set(this.formData, "fillBedInfo", true)
|
||||
}
|
||||
this.lotDeleteList = []
|
||||
this.$message.success("已延用上一年配置信息")
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
|
||||
}).catch(() => {
|
||||
this.inheritLoading = false
|
||||
})
|
||||
},
|
||||
openEdit(row) {
|
||||
this.title = "编辑疗休养配置"
|
||||
this.lotDeleteList = []
|
||||
this.activeTab = "basic"
|
||||
this.$axios.post(loc() + "/detail", {id: row.id}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.formData = Object.assign({
|
||||
activityGroupId: "",
|
||||
outProvinceRatioType: "当年报名人数",
|
||||
outProvinceFixedPeople: 0,
|
||||
cycleStartYear: "",
|
||||
cycleEndYear: "",
|
||||
cycleTotalCost: null,
|
||||
cycleAllowedTimes: null,
|
||||
allowFamily: false,
|
||||
fillBedInfo: true,
|
||||
enabled: true,
|
||||
lots: [],
|
||||
serviceNotice: ""
|
||||
}, res.data || {})
|
||||
this.formData.year = this.formData.year ? String(this.formData.year) : ""
|
||||
if (!this.formData.outProvinceRatioType) {
|
||||
this.$set(this.formData, "outProvinceRatioType", "当年报名人数")
|
||||
}
|
||||
if (this.formData.outProvinceFixedPeople === null || this.formData.outProvinceFixedPeople === undefined) {
|
||||
this.$set(this.formData, "outProvinceFixedPeople", 0)
|
||||
}
|
||||
if (this.formData.fillBedInfo === null || this.formData.fillBedInfo === undefined) {
|
||||
this.$set(this.formData, "fillBedInfo", true)
|
||||
}
|
||||
this.formData.cycleStartYear = this.formData.cycleStartYear ? String(this.formData.cycleStartYear) : ""
|
||||
this.formData.cycleEndYear = this.formData.cycleEndYear ? String(this.formData.cycleEndYear) : ""
|
||||
this.formData.lots = (this.formData.lots || []).map(item => Object.assign({}, item, {
|
||||
allowOverReimbursement: !!item.allowOverReimbursement
|
||||
}))
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
|
||||
} else {
|
||||
this.$message.warning(res.msg || "查询失败")
|
||||
}
|
||||
})
|
||||
},
|
||||
doSubmit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (!valid) return
|
||||
if (!this.validateLots()) return
|
||||
this.submitLoading = true
|
||||
// Nutz 对子表集合按字符串化 JSON 绑定更稳定,和体检项目维护的提交方式保持一致。
|
||||
const submitData = JSON.parse(JSON.stringify(this.formData))
|
||||
if (submitData.outProvinceRatioType !== "固定人数") {
|
||||
submitData.outProvinceFixedPeople = 0
|
||||
}
|
||||
submitData.lots = JSON.stringify(this.formData.lots || [])
|
||||
submitData.lotDeleteList = JSON.stringify(this.lotDeleteList)
|
||||
this.$axios.post(loc() + "/doSubmit", submitData).then((res) => {
|
||||
this.submitLoading = false
|
||||
if (res.code === 0) {
|
||||
this.$message.success("保存成功")
|
||||
this.dialogVisible = false
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "保存失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
this.submitLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
addLot() {
|
||||
if (!this.formData.lots) {
|
||||
this.$set(this.formData, "lots", [])
|
||||
}
|
||||
this.formData.lots.push({
|
||||
lotName: "",
|
||||
lotValue: "",
|
||||
activityCost: null,
|
||||
allowOverReimbursement: false
|
||||
})
|
||||
},
|
||||
integerInput(row, field, value) {
|
||||
const nextValue = String(value || "").replace(/[^\d]/g, "")
|
||||
this.$set(row, field, nextValue)
|
||||
},
|
||||
outProvinceRatioTypeChange(value) {
|
||||
if (value !== "固定人数") {
|
||||
this.$set(this.formData, "outProvinceFixedPeople", 0)
|
||||
}
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.validateField("outProvinceFixedPeople"))
|
||||
},
|
||||
validateLots() {
|
||||
const lots = this.formData.lots || []
|
||||
for (let i = 0; i < lots.length; i++) {
|
||||
const row = lots[i]
|
||||
const hasContent = row && (row.lotName || row.lotValue || row.activityCost !== null && row.activityCost !== undefined && row.activityCost !== "")
|
||||
if (!hasContent) continue
|
||||
if (!/^\d+$/.test(String(row.lotValue || ""))) {
|
||||
this.$message.warning("第" + (i + 1) + "行标段值必须为整数")
|
||||
return false
|
||||
}
|
||||
if (!/^\d+$/.test(String(row.activityCost === null || row.activityCost === undefined ? "" : row.activityCost))) {
|
||||
this.$message.warning("第" + (i + 1) + "行标段费用必须为整数")
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
deleteLot(index, row) {
|
||||
this.$confirm("确定删除该标段吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
if (row && row.id) {
|
||||
this.lotDeleteList.push(row.id)
|
||||
}
|
||||
this.formData.lots.splice(index, 1)
|
||||
})
|
||||
},
|
||||
doDelete(row) {
|
||||
this.$confirm("确定删除【" + row.configName + "】吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
this.$axios.post(loc() + "/doDelete", {id: row.id}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success("删除成功")
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "删除失败")
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
destroyEditor() {
|
||||
this.formData = {}
|
||||
this.lotDeleteList = []
|
||||
this.inheritLoading = false
|
||||
this.activeTab = "basic"
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getActivityGroup()
|
||||
this.pageData()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.tour-user-scope {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tour-user-scope .el-select {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.tour-setting-inherit {
|
||||
margin-bottom: -40px;
|
||||
padding-right: 96px;
|
||||
position: relative;
|
||||
text-align: right;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.tour-setting-basic-divider {
|
||||
border-top: 1px dashed #dcdfe6;
|
||||
margin: 2px 0 18px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,338 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<el-card shadow="never">
|
||||
<search :is-search-button="false">
|
||||
<search-item label="年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.year"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="旅行社名称">
|
||||
<el-input
|
||||
v-model="pageForm.agencyName"
|
||||
clearable
|
||||
placeholder="请输入旅行社名称"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="doSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<search-item label="联系人">
|
||||
<el-input
|
||||
v-model="pageForm.contactName"
|
||||
clearable
|
||||
placeholder="请输入联系人"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="doSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<search-item label="联系电话">
|
||||
<el-input
|
||||
v-model="pageForm.contactPhone"
|
||||
clearable
|
||||
placeholder="请输入联系电话"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="doSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<div class="search-query" style="margin-left: auto;">
|
||||
<el-button size="medium" type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
|
||||
<el-button size="medium" @click="resetSearch">重置</el-button>
|
||||
</div>
|
||||
</search>
|
||||
</el-card>
|
||||
|
||||
<el-card class="mt10" shadow="never">
|
||||
<table-tool :app="this" label="旅行社列表">
|
||||
<el-button @click="openAdd" size="medium" type="primary">
|
||||
<i class="el-icon-plus"></i>
|
||||
新增
|
||||
</el-button>
|
||||
</table-tool>
|
||||
|
||||
<el-table
|
||||
v-loading="tableLoading"
|
||||
:data="tableData"
|
||||
:size="tableSize"
|
||||
border
|
||||
@sort-change="pageOrder">
|
||||
<el-table-column label="序号" type="index" :index="indexMethod" width="80" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="年度" prop="year" width="110" sortable="custom" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="旅行社编号" prop="agencyCode" width="120" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="旅行社名称" prop="agencyName" min-width="220" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="联系人" prop="contactName" width="130" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="联系电话" prop="contactPhone" width="150" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="激活状态" prop="enabled" width="160" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-switch
|
||||
v-model="row.enabled"
|
||||
active-text="启用"
|
||||
inactive-text="禁用"
|
||||
@change="toggleEnabled(row)">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="260" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
|
||||
<el-button size="mini" type="primary" @click="openEdit(row)">编辑</el-button>
|
||||
<el-button size="mini" type="danger" @click="doDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
</guava>
|
||||
|
||||
<el-dialog
|
||||
:title="title"
|
||||
:visible.sync="dialogVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="72%"
|
||||
@closed="destroyForm">
|
||||
<el-form :model="formData" :rules="formRules" label-width="110px" ref="form" :disabled="viewMode">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="年度" prop="year">
|
||||
<el-date-picker
|
||||
v-model="formData.year"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="旅行社名称" prop="agencyName">
|
||||
<el-input v-model="formData.agencyName" maxlength="30" show-word-limit placeholder="请输入旅行社名称"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="旅行社编号" prop="agencyCode">
|
||||
<el-input v-model="formData.agencyCode" maxlength="50" placeholder="请输入旅行社编号"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="激活状态" prop="enabled">
|
||||
<el-radio-group v-model="formData.enabled">
|
||||
<el-radio :label="true">启用</el-radio>
|
||||
<el-radio :label="false">禁用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="联系人" prop="contactName">
|
||||
<el-input v-model="formData.contactName" maxlength="10" show-word-limit placeholder="请输入联系人"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="联系人手机" prop="contactPhone">
|
||||
<el-input v-model="formData.contactPhone" maxlength="30" placeholder="请输入联系人手机"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="邮箱" prop="email">
|
||||
<el-input v-model="formData.email" maxlength="100" placeholder="请输入邮箱"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="formData.remark" type="textarea" maxlength="100" :rows="3" show-word-limit placeholder="请输入备注"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="移动端缩略图" prop="mobileThumb">
|
||||
<!-- 复用课程管理的封面上传逻辑:单图上传,保存URL,供移动端列表展示使用。 -->
|
||||
<file-upload
|
||||
style="--upload-width: 200px;--upload-height:108px"
|
||||
:upload_number="1"
|
||||
:upload_size="20971520"
|
||||
:value.sync="formData.mobileThumb"
|
||||
accept=".jpg,.jpeg,.png"
|
||||
complete_result
|
||||
upload_mode="image"
|
||||
upload_result_category="interval">
|
||||
</file-upload>
|
||||
<div class="el-upload__tip">支持jpg、jpeg、png格式,大小不超过20MB。</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button v-if="!viewMode" type="primary" :loading="subDis" @click="doSubmit">保存</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
mixins: [initTableMixins],
|
||||
data() {
|
||||
const currentYear = moment().format("YYYY")
|
||||
const validateMobile = (rule, value, callback) => {
|
||||
const mobileReg = /^1[3-9]\d{9}$/
|
||||
if (!value) {
|
||||
callback(new Error("必填"))
|
||||
} else if (!mobileReg.test(value)) {
|
||||
callback(new Error("手机号格式不正确"))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const validateEmail = (rule, value, callback) => {
|
||||
const emailReg = /^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$/
|
||||
if (!value) {
|
||||
callback(new Error("必填"))
|
||||
} else if (!emailReg.test(value)) {
|
||||
callback(new Error("邮箱格式不正确"))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
return {
|
||||
title: "",
|
||||
dialogVisible: false,
|
||||
viewMode: false,
|
||||
subDis: false,
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
year: currentYear,
|
||||
agencyName: "",
|
||||
contactName: "",
|
||||
contactPhone: ""
|
||||
},
|
||||
formData: {},
|
||||
formRules: {
|
||||
year: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
agencyName: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
agencyCode: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
contactName: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
|
||||
contactPhone: [{ validator: validateMobile, trigger: ["blur", "change"] }],
|
||||
email: [{ validator: validateEmail, trigger: ["blur", "change"] }]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetSearch() {
|
||||
this.pageForm.year = moment().format("YYYY")
|
||||
this.pageForm.agencyName = ""
|
||||
this.pageForm.contactName = ""
|
||||
this.pageForm.contactPhone = ""
|
||||
this.doSearch()
|
||||
},
|
||||
emptyForm() {
|
||||
return {
|
||||
year: moment().format("YYYY"),
|
||||
agencyName: "",
|
||||
agencyCode: "",
|
||||
contactName: "",
|
||||
contactPhone: "",
|
||||
email: "",
|
||||
remark: "",
|
||||
mobileThumb: "",
|
||||
enabled: true
|
||||
}
|
||||
},
|
||||
openAdd() {
|
||||
this.title = "新增旅行社信息"
|
||||
this.viewMode = false
|
||||
this.formData = this.emptyForm()
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
|
||||
},
|
||||
openEdit(row) {
|
||||
this.title = "编辑旅行社信息"
|
||||
this.viewMode = false
|
||||
this.loadDetail(row.id)
|
||||
},
|
||||
openView(row) {
|
||||
this.title = "查看旅行社信息"
|
||||
this.viewMode = true
|
||||
this.loadDetail(row.id)
|
||||
},
|
||||
loadDetail(id) {
|
||||
this.$axios.post(loc() + "/detail", { id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.formData = Object.assign(this.emptyForm(), res.data || {})
|
||||
this.formData.year = this.formData.year ? String(this.formData.year) : ""
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
|
||||
} else {
|
||||
this.$message.warning(res.msg || "查询失败")
|
||||
}
|
||||
})
|
||||
},
|
||||
doSubmit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (!valid) return
|
||||
this.subDis = true
|
||||
this.$axios.post(loc() + "/doSubmit", this.formData).then((res) => {
|
||||
this.subDis = false
|
||||
if (res.code === 0) {
|
||||
this.$message.success("保存成功")
|
||||
this.dialogVisible = false
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "保存失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
this.subDis = false
|
||||
})
|
||||
})
|
||||
},
|
||||
toggleEnabled(row) {
|
||||
this.$axios.post(loc() + "/doSubmit", row).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success("状态已更新")
|
||||
} else {
|
||||
row.enabled = !row.enabled
|
||||
this.$message.warning(res.msg || "状态更新失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
row.enabled = !row.enabled
|
||||
})
|
||||
},
|
||||
doDelete(row) {
|
||||
this.$confirm("确定删除【" + row.agencyName + "】吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
this.$axios.post(loc() + "/doDelete", { id: row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success("删除成功")
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "删除失败")
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
destroyForm() {
|
||||
this.formData = {}
|
||||
this.viewMode = false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.pageData()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,549 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<el-card shadow="never">
|
||||
<search :is-search-button="false">
|
||||
<search-item label="开始年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.startYear"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择开始年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="结束年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.endYear"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择结束年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="姓名/工号">
|
||||
<el-input
|
||||
v-model="pageForm.keyword"
|
||||
clearable
|
||||
placeholder="请输入姓名或工号"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="doSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<search-item label="所属工会">
|
||||
<el-select v-model="pageForm.unionId" clearable filterable placeholder="请选择所属工会" style="width: 100%">
|
||||
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="线路">
|
||||
<el-select v-model="pageForm.lineId" clearable filterable placeholder="请选择线路" style="width: 100%">
|
||||
<el-option v-for="item in lineOptions" :key="item.lineId" :label="item.lineName" :value="item.lineId"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="出行时段">
|
||||
<el-select v-model="pageForm.travelPeriod" clearable filterable placeholder="请选择出行时段" style="width: 100%">
|
||||
<el-option v-for="item in travelPeriodOptions" :key="item.travelPeriod" :label="item.travelPeriod" :value="item.travelPeriod"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="线路类型">
|
||||
<el-select v-model="pageForm.lineType" clearable filterable placeholder="请选择线路类型" style="width: 100%">
|
||||
<el-option v-for="item in lineTypeOptions" :key="item.lineType" :label="item.lineType" :value="item.lineType"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<div class="search-query" style="margin-left: auto;">
|
||||
<el-button size="medium" type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
|
||||
<el-button size="medium" @click="resetSearch">重置</el-button>
|
||||
</div>
|
||||
</search>
|
||||
</el-card>
|
||||
|
||||
<el-card class="mt10" shadow="never">
|
||||
<table-tool :app="this" label="分工会审核">
|
||||
<el-radio-group class="mr5" size="small" v-model="pageForm.audit" @change="changeAudit">
|
||||
<el-radio-button :label="true">已审核</el-radio-button>
|
||||
<el-radio-button :label="false">未审核</el-radio-button>
|
||||
</el-radio-group>
|
||||
</table-tool>
|
||||
<el-table
|
||||
v-loading="tableLoading"
|
||||
:data="tableData"
|
||||
:size="tableSize"
|
||||
border
|
||||
@sort-change="pageOrder">
|
||||
<el-table-column label="序号" type="index" :index="indexMethod" width="80" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="工号" prop="jobNo" width="130" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="姓名" prop="userName" width="120" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="所在单位" prop="unitName" min-width="180" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="报名线路" prop="lineName" min-width="220" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="出行时段" prop="travelPeriod" min-width="220" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="线路类型" prop="lineType" width="130" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="报名时间" prop="signupTime" width="170" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="携带家属" prop="familyCount" width="120" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="Number(row.familyCount || 0) > 0 ? 'success' : 'info'">{{ row.familyCount || 0 }}人</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="报销超出费用" prop="overCostReimbursed" width="140" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="row.overCostReimbursed ? 'success' : 'info'">{{ row.overCostReimbursed ? '是' : '否' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="当前节点" prop="curTaskName" width="140" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="流程状态" prop="instanceState" width="120" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160" align="center" header-align="center" fixed="right">
|
||||
<template slot-scope="{row}">
|
||||
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
|
||||
<el-button v-if="row.taskState === 10" size="mini" type="primary" @click="openApproval(row)">审核</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
|
||||
<template #edit>
|
||||
<tour-approval-info ref="infoRef">
|
||||
<div v-if="showApprovalForm">
|
||||
<div class="process-title">
|
||||
{{ formData.taskName }}
|
||||
</div>
|
||||
<el-form
|
||||
:model="formData"
|
||||
ref="formRef"
|
||||
label-width="0"
|
||||
label-suffix=":"
|
||||
class="flow-task-form">
|
||||
<el-form-item
|
||||
label="审批意见"
|
||||
prop="tf_opinion"
|
||||
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
|
||||
<user-opinion-textarea v-model="formData.tf_opinion"></user-opinion-textarea>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-row type="flex" justify="end">
|
||||
<el-button @click="$refs.guava.index()" size="small">取消</el-button>
|
||||
<el-button @click="handleTaskAction(6)" size="small" type="info">退回到发起人</el-button>
|
||||
<el-button @click="handleTaskAction(2)" size="small" type="danger">拒绝申请</el-button>
|
||||
<el-button @click="handleTaskAction(1)" size="small" type="primary">同意申请</el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
</tour-approval-info>
|
||||
</template>
|
||||
</guava>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
#app .search .search-item {
|
||||
width: calc((100% - 150px) / 4);
|
||||
}
|
||||
#app .search .search-query {
|
||||
margin-left: auto;
|
||||
}
|
||||
@media screen and (max-width: 1350px) {
|
||||
#app .search .search-item {
|
||||
width: calc((100% - 100px) / 3);
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 1200px) {
|
||||
#app .search .search-item {
|
||||
width: calc((100% - 50px) / 2);
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 992px) {
|
||||
#app .search .search-item {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.tour-approval-section {
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
.tour-approval-table {
|
||||
width: 100%;
|
||||
}
|
||||
.tour-approval-empty {
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
const TOUR_APPROVAL_INFO = {
|
||||
template: [
|
||||
"\n",
|
||||
" <div>\n",
|
||||
" <div class=\"process-title\">\n",
|
||||
" 报名信息\n",
|
||||
" <el-link type=\"primary\" @click=\"openChart\">点击查看流程图</el-link>\n",
|
||||
" </div>\n",
|
||||
" <el-descriptions :column=\"3\" border class=\"tour-approval-section\">\n",
|
||||
" <el-descriptions-item label=\"工号\">{{ detail.jobNo || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"姓名\">{{ detail.userName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"性别\">{{ detail.gender || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"身份证号\">{{ detail.idCard || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"所在单位\">{{ detail.unitName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"所在工会\">{{ detail.unionName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"报名时间\">{{ detail.signupTime || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"报名线路\">{{ detail.lineName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"出行时段\">{{ detail.travelPeriod || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"线路类型\">{{ detail.lineType || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"报名酒店\">{{ detail.hotelName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"旅行社\">{{ detail.travelAgencyName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"是否携带家属\">\n",
|
||||
" {{ familyText() }}\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"报销超出费用\">{{ detail.overCostReimbursed ? '是' : '否' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item v-if=\"fillBedInfo\" label=\"意向拼床人\">{{ detail.intendedRoommate || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item v-if=\"fillBedInfo\" label=\"床型\">{{ detail.bedType || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item v-if=\"fillBedInfo\" label=\"床位信息\">{{ detail.bedInfo || '' }}</el-descriptions-item>\n",
|
||||
" </el-descriptions>\n",
|
||||
"\n",
|
||||
" <div v-if=\"isDirectFamilyLine()\" class=\"tour-approval-section\">\n",
|
||||
" <div class=\"process-title\">直系亲属线路</div>\n",
|
||||
" <el-descriptions :column=\"3\" border>\n",
|
||||
" <el-descriptions-item label=\"亲属姓名\">{{ directRelative.relativeName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"所在单位\">{{ directRelative.unitName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"亲属关系\">{{ directRelative.relationshipName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"线路名称\">{{ directRelative.lineName || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"出行开始日期\">{{ directRelative.travelStartTime || '' }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"出行结束日期\">{{ directRelative.travelEndTime || '' }}</el-descriptions-item>\n",
|
||||
" </el-descriptions>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <div v-if=\"showFamilySection()\" class=\"tour-approval-section\">\n",
|
||||
" <div class=\"process-title\">亲属信息</div>\n",
|
||||
" <el-table :data=\"familyData\" border size=\"mini\" empty-text=\"暂无亲属信息\" class=\"tour-approval-table\">\n",
|
||||
" <el-table-column label=\"序号\" type=\"index\" width=\"70\" align=\"center\" header-align=\"center\"></el-table-column>\n",
|
||||
" <el-table-column label=\"家属姓名\" prop=\"familyName\" min-width=\"120\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" <el-table-column label=\"性别\" prop=\"gender\" width=\"90\" align=\"center\" header-align=\"center\"></el-table-column>\n",
|
||||
" <el-table-column label=\"身份证号码\" prop=\"idCard\" min-width=\"180\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" <el-table-column label=\"年龄\" prop=\"age\" width=\"90\" align=\"center\" header-align=\"center\"></el-table-column>\n",
|
||||
" <el-table-column label=\"关系\" prop=\"relationship\" width=\"110\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" <el-table-column v-if=\"fillBedInfo\" label=\"床型\" prop=\"bedType\" width=\"110\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" <el-table-column v-if=\"fillBedInfo\" label=\"床位\" prop=\"bedInfo\" min-width=\"120\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" <el-table-column v-if=\"fillBedInfo\" label=\"意向拼床人\" prop=\"intendedRoommate\" min-width=\"130\" align=\"center\" header-align=\"center\" show-overflow-tooltip></el-table-column>\n",
|
||||
" </el-table>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <template v-for=\"task in doneTasks\">\n",
|
||||
" <div class=\"mt10\">\n",
|
||||
" <div class=\"process-title\">{{ task.displayName }}</div>\n",
|
||||
" <el-descriptions border class=\"flow-task-form\" :column=\"3\" :key=\"task.id\" v-if=\"task.ext.isFirstTaskNode\">\n",
|
||||
" <el-descriptions-item label=\"申请用户\">\n",
|
||||
" {{ task.ext.initiatorName }}({{ task.ext.initiatorAccount }})\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"申请时间\">{{ task.finishTime }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"办理结果\">\n",
|
||||
" <dict-tag :options=\"dict.type.PROCESS_TASK_SUBMIT_TYPE\" :value=\"task.ext.submitType\"></dict-tag>\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" </el-descriptions>\n",
|
||||
"\n",
|
||||
" <el-descriptions border class=\"flow-task-form\" :column=\"3\" :key=\"task.id\" v-else>\n",
|
||||
" <el-descriptions-item label=\"办理用户\">\n",
|
||||
" {{ task.taskFormData.userName }}({{ task.taskFormData.loginName }})\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"办理时间\">{{ task.finishTime }}</el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"办理结果\">\n",
|
||||
" <dict-tag :options=\"dict.type.PROCESS_TASK_SUBMIT_TYPE\" :value=\"task.ext.submitType\"></dict-tag>\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" <el-descriptions-item label=\"办理意见\" :span=\"3\">\n",
|
||||
" {{ task.taskFormData.opinion || task.taskFormData.tf_opinion || '' }}\n",
|
||||
" </el-descriptions-item>\n",
|
||||
" </el-descriptions>\n",
|
||||
" </div>\n",
|
||||
" </template>\n",
|
||||
"\n",
|
||||
" <slot></slot>\n",
|
||||
"\n",
|
||||
" <snaker-chart ref=\"snakerChartRef\"></snaker-chart>\n",
|
||||
" </div>\n",
|
||||
" \n"
|
||||
].join(""),
|
||||
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
|
||||
data() {
|
||||
return {
|
||||
row: {},
|
||||
detail: {},
|
||||
familyData: [],
|
||||
directRelative: {},
|
||||
allowFamily: false,
|
||||
fillBedInfo: true,
|
||||
directFamilyUnitLine: false,
|
||||
doneTasks: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onOpen(row) {
|
||||
this.row = row || {}
|
||||
this.detail = {}
|
||||
this.familyData = []
|
||||
this.directRelative = {}
|
||||
this.allowFamily = false
|
||||
this.fillBedInfo = true
|
||||
this.directFamilyUnitLine = false
|
||||
this.doneTasks = []
|
||||
this.info()
|
||||
this.getDoneTasks()
|
||||
},
|
||||
info() {
|
||||
this.$axios.post(loc() + "/detail", { id: this.row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const data = res.data || {}
|
||||
this.detail = data.ledger || {}
|
||||
this.detail.travelPeriod = data.travelPeriod || this.row.travelPeriod || ""
|
||||
this.familyData = data.families || []
|
||||
this.directRelative = data.directRelative || {}
|
||||
this.allowFamily = this.toBoolean(data.allowFamily)
|
||||
this.fillBedInfo = data.fillBedInfo === undefined || data.fillBedInfo === null || this.toBoolean(data.fillBedInfo)
|
||||
this.directFamilyUnitLine = this.toBoolean(data.directFamilyUnitLine)
|
||||
} else {
|
||||
this.$message.warning(res.msg || "查询失败")
|
||||
}
|
||||
})
|
||||
},
|
||||
toBoolean(value) {
|
||||
return value === true || value === 1 || value === "1"
|
||||
},
|
||||
isDirectFamilyLine() {
|
||||
return this.directFamilyUnitLine
|
||||
|| this.toBoolean(this.detail.directFamilyUnitLine)
|
||||
|| (this.directRelative && this.directRelative.id)
|
||||
},
|
||||
hasFamily() {
|
||||
return this.toBoolean(this.detail.hasFamily) || this.familyData.length > 0
|
||||
},
|
||||
showFamilySection() {
|
||||
return this.allowFamily && this.hasFamily() && !this.isDirectFamilyLine()
|
||||
},
|
||||
familyText() {
|
||||
if (this.isDirectFamilyLine()) {
|
||||
return "否"
|
||||
}
|
||||
if (!this.allowFamily) {
|
||||
return "否"
|
||||
}
|
||||
return this.hasFamily() ? "是" : "否"
|
||||
},
|
||||
getDoneTasks() {
|
||||
this.$axios.post("/flow/common/doneTasks", { bizId: this.row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.doneTasks = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
openChart() {
|
||||
if (!this.row.instanceProcessDefineId || !this.row.instanceId) {
|
||||
this.$message.warning("暂无流程图信息")
|
||||
return
|
||||
}
|
||||
this.$refs.snakerChartRef.onOpenFull(this.row.instanceProcessDefineId, this.row.instanceId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new Vue({
|
||||
el: "#app",
|
||||
mixins: [initTableMixins],
|
||||
data() {
|
||||
const currentYear = moment().format("YYYY")
|
||||
return {
|
||||
unionOptions: [],
|
||||
lineOptions: [],
|
||||
travelPeriodOptions: [],
|
||||
lineTypeOptions: [],
|
||||
showApprovalForm: false,
|
||||
formData: {
|
||||
tf_opinion: ""
|
||||
},
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "signupTime",
|
||||
pageOrderBy: "descending",
|
||||
audit: false,
|
||||
startYear: currentYear,
|
||||
endYear: currentYear,
|
||||
keyword: "",
|
||||
unionId: "",
|
||||
lineId: "",
|
||||
travelPeriod: "",
|
||||
lineType: ""
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetSearch() {
|
||||
this.pageForm.startYear = moment().format("YYYY")
|
||||
this.pageForm.endYear = moment().format("YYYY")
|
||||
this.pageForm.keyword = ""
|
||||
this.pageForm.unionId = ""
|
||||
this.pageForm.lineId = ""
|
||||
this.pageForm.travelPeriod = ""
|
||||
this.pageForm.lineType = ""
|
||||
this.loadOptions()
|
||||
this.doSearch()
|
||||
},
|
||||
changeAudit() {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.clearCascadeFilters()
|
||||
this.loadOptions()
|
||||
this.pageData()
|
||||
},
|
||||
clearCascadeFilters() {
|
||||
this.pageForm.unionId = ""
|
||||
this.pageForm.lineId = ""
|
||||
this.pageForm.travelPeriod = ""
|
||||
this.pageForm.lineType = ""
|
||||
},
|
||||
openView(row) {
|
||||
this.$refs.guava.edit(() => {
|
||||
this.showApprovalForm = false
|
||||
this.formData = {
|
||||
tf_opinion: ""
|
||||
}
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
})
|
||||
},
|
||||
openApproval(row) {
|
||||
this.$refs.guava.edit(() => {
|
||||
this.showApprovalForm = true
|
||||
this.formData = {
|
||||
processTaskId: row.taskId,
|
||||
taskName: row.curTaskName || row.taskName,
|
||||
tf_opinion: ""
|
||||
}
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
})
|
||||
},
|
||||
handleTaskAction(val) {
|
||||
this.$refs.formRef.validate((valid) => {
|
||||
if (!valid) return
|
||||
this.$confirm("您确定要提交吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
const loading = createLoading()
|
||||
this.$axios.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
...this.formData,
|
||||
submitType: val
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$refs.guava.index()
|
||||
this.$message.success(res.msg || "操作成功")
|
||||
this.doSearch()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "操作失败")
|
||||
}
|
||||
}).finally(() => {
|
||||
loading.close()
|
||||
})
|
||||
}).catch(() => {})
|
||||
})
|
||||
},
|
||||
loadOptions() {
|
||||
this.loadUnionOptions()
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
},
|
||||
baseOptionParams() {
|
||||
return {
|
||||
audit: this.pageForm.audit,
|
||||
startYear: this.pageForm.startYear,
|
||||
endYear: this.pageForm.endYear,
|
||||
keyword: this.pageForm.keyword,
|
||||
unionId: this.pageForm.unionId,
|
||||
lineId: this.pageForm.lineId,
|
||||
travelPeriod: this.pageForm.travelPeriod,
|
||||
lineType: this.pageForm.lineType
|
||||
}
|
||||
},
|
||||
loadUnionOptions() {
|
||||
this.$axios.post(loc() + "/unionOptions", this.baseOptionParams()).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.unionOptions = res.data || []
|
||||
if (this.pageForm.unionId && !this.unionOptions.some(item => item.id === this.pageForm.unionId)) {
|
||||
this.pageForm.unionId = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadLineOptions() {
|
||||
this.$axios.post(loc() + "/lineOptions", this.baseOptionParams()).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.lineOptions = res.data || []
|
||||
if (this.pageForm.lineId && !this.lineOptions.some(item => item.lineId === this.pageForm.lineId)) {
|
||||
this.pageForm.lineId = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadTravelPeriodOptions() {
|
||||
this.$axios.post(loc() + "/travelPeriodOptions", this.baseOptionParams()).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.travelPeriodOptions = res.data || []
|
||||
if (this.pageForm.travelPeriod && !this.travelPeriodOptions.some(item => item.travelPeriod === this.pageForm.travelPeriod)) {
|
||||
this.pageForm.travelPeriod = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadLineTypeOptions() {
|
||||
this.$axios.post(loc() + "/lineTypeOptions", this.baseOptionParams()).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.lineTypeOptions = res.data || []
|
||||
if (this.pageForm.lineType && !this.lineTypeOptions.some(item => item.lineType === this.pageForm.lineType)) {
|
||||
this.pageForm.lineType = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadOptions()
|
||||
this.pageData()
|
||||
},
|
||||
components: {
|
||||
"tour-approval-info": TOUR_APPROVAL_INFO
|
||||
},
|
||||
watch: {
|
||||
"pageForm.startYear"() {
|
||||
this.clearCascadeFilters()
|
||||
this.loadOptions()
|
||||
},
|
||||
"pageForm.endYear"() {
|
||||
this.clearCascadeFilters()
|
||||
this.loadOptions()
|
||||
},
|
||||
"pageForm.lineId"() {
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
},
|
||||
"pageForm.travelPeriod"() {
|
||||
this.loadLineOptions()
|
||||
this.loadLineTypeOptions()
|
||||
},
|
||||
"pageForm.lineType"() {
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
},
|
||||
"pageForm.unionId"() {
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,609 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<guava ref="guava">
|
||||
<el-card shadow="never">
|
||||
<search :is-search-button="false">
|
||||
<search-item label="开始年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.startYear"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择开始年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="结束年度">
|
||||
<el-date-picker
|
||||
v-model="pageForm.endYear"
|
||||
type="year"
|
||||
value-format="yyyy"
|
||||
placeholder="请选择结束年度"
|
||||
style="width: 100%">
|
||||
</el-date-picker>
|
||||
</search-item>
|
||||
<search-item label="姓名/工号">
|
||||
<el-input
|
||||
v-model="pageForm.keyword"
|
||||
clearable
|
||||
placeholder="请输入姓名或工号"
|
||||
style="width: 100%"
|
||||
@keyup.enter.native="doSearch">
|
||||
</el-input>
|
||||
</search-item>
|
||||
<search-item label="所属工会">
|
||||
<el-select v-model="pageForm.unionId" clearable filterable placeholder="请选择所属工会" style="width: 100%">
|
||||
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="线路">
|
||||
<el-select v-model="pageForm.lineId" clearable filterable placeholder="请选择线路" style="width: 100%">
|
||||
<el-option v-for="item in lineOptions" :key="item.lineId" :label="item.lineName" :value="item.lineId"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="出行时段">
|
||||
<el-select v-model="pageForm.travelPeriod" clearable filterable placeholder="请选择出行时段" style="width: 100%">
|
||||
<el-option v-for="item in travelPeriodOptions" :key="item.travelPeriod" :label="item.travelPeriod" :value="item.travelPeriod"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="线路类型">
|
||||
<el-select v-model="pageForm.lineType" clearable filterable placeholder="请选择线路类型" style="width: 100%">
|
||||
<el-option v-for="item in lineTypeOptions" :key="item.lineType" :label="item.lineType" :value="item.lineType"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<div class="search-query" style="margin-left: auto;">
|
||||
<el-button size="medium" type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
|
||||
<el-button size="medium" @click="resetSearch">重置</el-button>
|
||||
</div>
|
||||
</search>
|
||||
</el-card>
|
||||
|
||||
<el-card class="mt10" shadow="never">
|
||||
<div class="tour-ledger-toolbar">
|
||||
<div class="tour-ledger-toolbar-title">
|
||||
<table-tool :app="this" label="分工会台账"></table-tool>
|
||||
</div>
|
||||
<div class="tour-ledger-scope">
|
||||
<el-button
|
||||
class="tour-scope-btn"
|
||||
size="medium"
|
||||
:class="{'is-active': pageForm.scopeType === 'ownUnionJoined'}"
|
||||
@click="setScopeType('ownUnionJoined')">
|
||||
本工会参加疗休养教职工({{ summaryStats.ownUnionJoinedStaffCount || 0 }})
|
||||
</el-button>
|
||||
<el-button
|
||||
class="tour-scope-btn"
|
||||
size="medium"
|
||||
:class="{'is-active': pageForm.scopeType === 'organizedLineJoined'}"
|
||||
@click="setScopeType('organizedLineJoined')">
|
||||
参加本工会组织线路人员(含其他工会及家属)({{ summaryStats.organizedLineJoinedTotalCount || 0 }})
|
||||
</el-button>
|
||||
<el-button
|
||||
class="tour-scope-btn"
|
||||
size="medium"
|
||||
:class="{'is-active': pageForm.overCostOnly}"
|
||||
@click="setOverCostOnly">
|
||||
超出费用由单位承担
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="pageForm.overCostOnly"
|
||||
type="primary"
|
||||
size="medium"
|
||||
icon="el-icon-download"
|
||||
@click="downloadOverCostSummary">
|
||||
导出
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="tableLoading"
|
||||
:data="tableData"
|
||||
:size="tableSize"
|
||||
border
|
||||
@sort-change="pageOrder">
|
||||
<el-table-column label="序号" type="index" :index="indexMethod" width="80" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="工号" prop="jobNo" width="130" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="姓名" prop="userName" width="120" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="所在单位" prop="unitName" min-width="180" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="报名线路" prop="lineName" min-width="220" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="出行时段" prop="travelPeriod" min-width="260" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="线路类型" prop="lineType" width="130" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="报名时间" prop="signupTime" width="170" sortable="custom" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="携带家属" prop="familyCount" width="120" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="Number(row.familyCount || 0) > 0 ? 'success' : 'info'">{{ row.familyCount || 0 }}人</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否参加" prop="joined" width="120" sortable="custom" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="row.joined ? 'success' : 'info'">{{ row.joined ? '是' : '否' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="报销超出费用" prop="overCostReimbursed" width="140" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="mini" :type="row.overCostReimbursed ? 'success' : 'info'">{{ row.overCostReimbursed ? '是' : '否' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160" align="center" header-align="center" fixed="right">
|
||||
<template slot-scope="{row}">
|
||||
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
|
||||
<el-button size="mini" type="danger" @click="doDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
</guava>
|
||||
|
||||
<el-dialog
|
||||
title="台账详情"
|
||||
:visible.sync="detailVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="72%">
|
||||
<div class="tour-ledger-section">
|
||||
<div class="tour-ledger-title">教职工信息</div>
|
||||
<el-descriptions :column="3" border size="medium">
|
||||
<el-descriptions-item label="工号">{{ detail.jobNo || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="姓名">{{ detail.userName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="性别">{{ detail.gender || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="身份证号">{{ detail.idCard || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在单位">{{ detail.unitName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在工会">{{ detail.unionName || '' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<div class="tour-ledger-section mt10">
|
||||
<div class="tour-ledger-title">
|
||||
报名信息
|
||||
<el-link v-if="detailHasWorkflow()" type="primary" @click="openChart">点击查看流程图</el-link>
|
||||
</div>
|
||||
<el-descriptions :column="3" border size="medium">
|
||||
<el-descriptions-item label="报名时间">{{ detail.signupTime || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报名线路">{{ detail.lineName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="线路类型">{{ detail.lineType || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报名酒店">{{ detail.hotelName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报名旅行社">{{ detail.travelAgencyName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="出行时间">{{ detail.travelPeriod || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item v-if="fillBedInfo" label="床型">{{ detail.bedType || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item v-if="fillBedInfo" label="床位信息">{{ detail.bedInfo || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item v-if="fillBedInfo" label="意向拼床人">{{ detail.intendedRoommate || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="是否携带家属">{{ familyText() }}</el-descriptions-item>
|
||||
<el-descriptions-item label="是否参加">{{ detail.joined ? '是' : '否' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="是否报销">{{ detail.reimbursed ? '是' : '否' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报销超出费用">{{ detail.overCostReimbursed ? '是' : '否' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<div v-if="isDirectFamilyLine()" class="tour-ledger-section mt10">
|
||||
<div class="tour-ledger-title">直系亲属线路</div>
|
||||
<el-descriptions :column="3" border size="medium">
|
||||
<el-descriptions-item label="亲属姓名">{{ directRelative.relativeName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在单位">{{ directRelative.unitName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="亲属关系">{{ directRelative.relationshipName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="线路名称">{{ directRelative.lineName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="出行开始日期">{{ directRelative.travelStartTime || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="出行结束日期">{{ directRelative.travelEndTime || '' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<div v-if="showFamilySection()" class="tour-ledger-section mt10">
|
||||
<div class="tour-ledger-title">家属信息</div>
|
||||
<el-table :data="familyData" border :size="tableSize" empty-text="暂无家属信息">
|
||||
<el-table-column label="序号" type="index" width="70" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="家属姓名" prop="familyName" min-width="120" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="性别" prop="gender" width="90" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="身份证号码" prop="idCard" min-width="180" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="年龄" prop="age" width="90" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="关系" prop="relationship" width="110" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column v-if="fillBedInfo" label="床型" prop="bedType" width="110" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column v-if="fillBedInfo" label="床位" prop="bedInfo" min-width="120" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column v-if="fillBedInfo" label="意向拼床人" prop="intendedRoommate" min-width="130" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<template v-if="detailHasWorkflow()" v-for="task in doneTasks">
|
||||
<div class="tour-ledger-section mt10" :key="task.id">
|
||||
<div class="tour-ledger-title">{{ task.displayName }}</div>
|
||||
<el-descriptions border :column="3" v-if="task.ext && task.ext.isFirstTaskNode">
|
||||
<el-descriptions-item label="申请用户">
|
||||
{{ task.ext.initiatorName }}({{ task.ext.initiatorAccount }})
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="申请时间">{{ task.finishTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="办理结果">
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE" :value="task.ext.submitType"></dict-tag>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-descriptions border :column="3" v-else>
|
||||
<el-descriptions-item label="办理用户">
|
||||
{{ (task.taskFormData && task.taskFormData.userName) || '' }}({{ (task.taskFormData && task.taskFormData.loginName) || '' }})
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="办理时间">{{ task.finishTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="办理结果">
|
||||
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE" :value="task.ext && task.ext.submitType"></dict-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="办理意见" :span="3">
|
||||
{{ (task.taskFormData && (task.taskFormData.opinion || task.taskFormData.tf_opinion)) || '' }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<snaker-chart ref="snakerChartRef"></snaker-chart>
|
||||
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="detailVisible = false">确定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.tour-ledger-section {
|
||||
padding: 0 2px;
|
||||
}
|
||||
.tour-ledger-title {
|
||||
border-left: 4px solid #0079c2;
|
||||
color: #0079c2;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 16px;
|
||||
margin-bottom: 14px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
.tour-ledger-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
gap: 24px;
|
||||
margin-bottom: 12px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.tour-ledger-toolbar-title {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.tour-ledger-scope {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 0 0 auto;
|
||||
flex-wrap: nowrap;
|
||||
gap: 12px;
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.tour-ledger-scope .el-button {
|
||||
margin: 0;
|
||||
}
|
||||
.tour-ledger-scope .el-button + .el-button {
|
||||
margin-left: 0;
|
||||
}
|
||||
.tour-ledger-scope .tour-scope-btn {
|
||||
background: #ecf5ff;
|
||||
border-color: #b3d8ff;
|
||||
border-radius: 4px;
|
||||
color: #0079c2;
|
||||
font-weight: 600;
|
||||
height: 34px;
|
||||
line-height: 1;
|
||||
padding: 8px 18px;
|
||||
}
|
||||
.tour-ledger-scope .tour-scope-btn:hover,
|
||||
.tour-ledger-scope .tour-scope-btn:focus {
|
||||
background: #d9ecff;
|
||||
border-color: #66b1ff;
|
||||
color: #006bb0;
|
||||
}
|
||||
.tour-ledger-scope .tour-scope-btn.is-active {
|
||||
background: #0079c2;
|
||||
border-color: #0079c2;
|
||||
box-shadow: 0 2px 6px rgba(0, 121, 194, 0.24);
|
||||
color: #fff;
|
||||
}
|
||||
.tour-ledger-scope .tour-scope-btn.is-active:hover,
|
||||
.tour-ledger-scope .tour-scope-btn.is-active:focus {
|
||||
background: #006bb0;
|
||||
border-color: #006bb0;
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
mixins: [initTableMixins],
|
||||
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
|
||||
data() {
|
||||
const currentYear = moment().format("YYYY")
|
||||
return {
|
||||
detailVisible: false,
|
||||
unionOptions: [],
|
||||
lineOptions: [],
|
||||
travelPeriodOptions: [],
|
||||
lineTypeOptions: [],
|
||||
summaryStats: {},
|
||||
detail: {},
|
||||
familyData: [],
|
||||
directRelative: {},
|
||||
directFamilyUnitLine: false,
|
||||
fillBedInfo: true,
|
||||
detailRow: {},
|
||||
doneTasks: [],
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "signupTime",
|
||||
pageOrderBy: "descending",
|
||||
startYear: currentYear,
|
||||
endYear: currentYear,
|
||||
keyword: "",
|
||||
unionId: "",
|
||||
lineId: "",
|
||||
travelPeriod: "",
|
||||
lineType: "",
|
||||
scopeType: "",
|
||||
overCostOnly: false
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toBoolean(value) {
|
||||
return value === true || value === 1 || value === "1" || value === "true"
|
||||
},
|
||||
isDirectFamilyLine() {
|
||||
return this.directFamilyUnitLine
|
||||
|| this.toBoolean(this.detail && this.detail.directFamilyUnitLine)
|
||||
|| !!(this.directRelative && this.directRelative.id)
|
||||
},
|
||||
detailHasWorkflow() {
|
||||
return !!(this.detailRow && this.detailRow.instanceId)
|
||||
},
|
||||
hasFamily() {
|
||||
return this.toBoolean(this.detail && this.detail.hasFamily) || this.familyData.length > 0
|
||||
},
|
||||
familyText() {
|
||||
if (this.isDirectFamilyLine()) {
|
||||
return "否"
|
||||
}
|
||||
if (!this.hasFamily()) {
|
||||
return "否"
|
||||
}
|
||||
const count = Number(this.familyData.length || 0)
|
||||
return count > 0 ? count + "人" : "是"
|
||||
},
|
||||
showFamilySection() {
|
||||
return this.hasFamily() && !this.isDirectFamilyLine()
|
||||
},
|
||||
loadDoneTasks() {
|
||||
this.$axios.post("/flow/common/doneTasks", { bizId: this.detailRow.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.doneTasks = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
openChart() {
|
||||
if (!this.detailRow.instanceProcessDefineId || !this.detailRow.instanceId) {
|
||||
this.$message.warning("暂无流程图信息")
|
||||
return
|
||||
}
|
||||
this.$refs.snakerChartRef.onOpenFull(this.detailRow.instanceProcessDefineId, this.detailRow.instanceId)
|
||||
},
|
||||
resetSearch() {
|
||||
this.pageForm.startYear = moment().format("YYYY")
|
||||
this.pageForm.endYear = moment().format("YYYY")
|
||||
this.pageForm.keyword = ""
|
||||
this.pageForm.unionId = ""
|
||||
this.pageForm.lineId = ""
|
||||
this.pageForm.travelPeriod = ""
|
||||
this.pageForm.lineType = ""
|
||||
this.pageForm.scopeType = ""
|
||||
this.pageForm.overCostOnly = false
|
||||
this.loadUnionOptions()
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
this.loadSummaryStats()
|
||||
this.doSearch()
|
||||
},
|
||||
openView(row) {
|
||||
this.detailRow = row || {}
|
||||
this.detail = {}
|
||||
this.familyData = []
|
||||
this.directRelative = {}
|
||||
this.directFamilyUnitLine = false
|
||||
this.fillBedInfo = true
|
||||
this.doneTasks = []
|
||||
this.$axios.post(loc() + "/detail", { id: row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const data = res.data || {}
|
||||
this.detail = data.ledger || {}
|
||||
this.detail.travelPeriod = data.travelPeriod || ""
|
||||
this.familyData = data.families || []
|
||||
this.directRelative = data.directRelative || {}
|
||||
this.directFamilyUnitLine = this.toBoolean(data.directFamilyUnitLine)
|
||||
this.fillBedInfo = data.fillBedInfo === undefined || data.fillBedInfo === null || this.toBoolean(data.fillBedInfo)
|
||||
this.detailVisible = true
|
||||
if (this.detailHasWorkflow()) {
|
||||
this.loadDoneTasks()
|
||||
}
|
||||
} else {
|
||||
this.$message.warning(res.msg || "查询失败")
|
||||
}
|
||||
})
|
||||
},
|
||||
doDelete(row) {
|
||||
this.$confirm("确定删除【" + row.userName + "】的报名台账吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
this.$axios.post(loc() + "/doDelete", { id: row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success("删除成功")
|
||||
this.pageData()
|
||||
this.loadSummaryStats()
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "删除失败")
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
loadUnionOptions() {
|
||||
this.$axios.post(loc() + "/unionOptions", {
|
||||
startYear: this.pageForm.startYear,
|
||||
endYear: this.pageForm.endYear
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.unionOptions = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
loadLineOptions() {
|
||||
this.$axios.post(loc() + "/lineOptions", {
|
||||
startYear: this.pageForm.startYear,
|
||||
endYear: this.pageForm.endYear,
|
||||
travelPeriod: this.pageForm.travelPeriod,
|
||||
lineType: this.pageForm.lineType,
|
||||
unionId: this.pageForm.unionId,
|
||||
keyword: this.pageForm.keyword,
|
||||
scopeType: this.pageForm.scopeType
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.lineOptions = res.data || []
|
||||
if (this.pageForm.lineId && !this.lineOptions.some(item => item.lineId === this.pageForm.lineId)) {
|
||||
this.pageForm.lineId = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadTravelPeriodOptions() {
|
||||
this.$axios.post(loc() + "/travelPeriodOptions", {
|
||||
startYear: this.pageForm.startYear,
|
||||
endYear: this.pageForm.endYear,
|
||||
lineId: this.pageForm.lineId,
|
||||
lineType: this.pageForm.lineType,
|
||||
unionId: this.pageForm.unionId,
|
||||
keyword: this.pageForm.keyword,
|
||||
scopeType: this.pageForm.scopeType
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.travelPeriodOptions = res.data || []
|
||||
if (this.pageForm.travelPeriod && !this.travelPeriodOptions.some(item => item.travelPeriod === this.pageForm.travelPeriod)) {
|
||||
this.pageForm.travelPeriod = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadLineTypeOptions() {
|
||||
this.$axios.post(loc() + "/lineTypeOptions", {
|
||||
startYear: this.pageForm.startYear,
|
||||
endYear: this.pageForm.endYear,
|
||||
lineId: this.pageForm.lineId,
|
||||
travelPeriod: this.pageForm.travelPeriod,
|
||||
unionId: this.pageForm.unionId,
|
||||
keyword: this.pageForm.keyword,
|
||||
scopeType: this.pageForm.scopeType
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.lineTypeOptions = res.data || []
|
||||
if (this.pageForm.lineType && !this.lineTypeOptions.some(item => item.lineType === this.pageForm.lineType)) {
|
||||
this.pageForm.lineType = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadSummaryStats() {
|
||||
this.$axios.post(loc() + "/summaryStats", {
|
||||
startYear: this.pageForm.startYear,
|
||||
endYear: this.pageForm.endYear,
|
||||
unionId: this.pageForm.unionId,
|
||||
lineId: this.pageForm.lineId,
|
||||
travelPeriod: this.pageForm.travelPeriod,
|
||||
lineType: this.pageForm.lineType
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.summaryStats = res.data || {}
|
||||
}
|
||||
})
|
||||
},
|
||||
setScopeType(scopeType) {
|
||||
this.pageForm.scopeType = this.pageForm.scopeType === scopeType ? "" : scopeType
|
||||
this.pageForm.pageNumber = 1
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
this.pageData()
|
||||
},
|
||||
setOverCostOnly() {
|
||||
this.pageForm.overCostOnly = !this.pageForm.overCostOnly
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageData()
|
||||
},
|
||||
downloadOverCostSummary() {
|
||||
this.$downLoad(loc() + "/exportOverCostSummary", this.pageForm)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadUnionOptions()
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
this.loadSummaryStats()
|
||||
this.pageData()
|
||||
},
|
||||
watch: {
|
||||
"pageForm.startYear"() {
|
||||
this.pageForm.lineId = ""
|
||||
this.pageForm.travelPeriod = ""
|
||||
this.pageForm.lineType = ""
|
||||
this.pageForm.unionId = ""
|
||||
this.pageForm.scopeType = ""
|
||||
this.loadUnionOptions()
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
this.loadSummaryStats()
|
||||
},
|
||||
"pageForm.endYear"() {
|
||||
this.pageForm.lineId = ""
|
||||
this.pageForm.travelPeriod = ""
|
||||
this.pageForm.lineType = ""
|
||||
this.pageForm.unionId = ""
|
||||
this.pageForm.scopeType = ""
|
||||
this.loadUnionOptions()
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
this.loadSummaryStats()
|
||||
},
|
||||
"pageForm.lineId"() {
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
this.loadSummaryStats()
|
||||
},
|
||||
"pageForm.travelPeriod"() {
|
||||
this.loadLineOptions()
|
||||
this.loadLineTypeOptions()
|
||||
this.loadSummaryStats()
|
||||
},
|
||||
"pageForm.lineType"() {
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadSummaryStats()
|
||||
},
|
||||
"pageForm.unionId"() {
|
||||
this.loadLineOptions()
|
||||
this.loadTravelPeriodOptions()
|
||||
this.loadLineTypeOptions()
|
||||
this.loadSummaryStats()
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
File diff suppressed because it is too large
Load Diff
+480
@@ -0,0 +1,480 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
.tour-approval-page {
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #f4f6f8;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-approval-sticky {
|
||||
flex-shrink: 0;
|
||||
background: #f4f6f8;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll {
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding-bottom: 18px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-approval-search /deep/ .van-search__content,
|
||||
.tour-approval-search .van-search__content {
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.tour-card-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.tour-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 22px;
|
||||
padding: 0 8px;
|
||||
border-radius: 4px;
|
||||
background: #eef6ff;
|
||||
color: #0b75bd;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.tour-tag.gray {
|
||||
background: #f1f5f9;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.tour-tag.warn {
|
||||
background: #fff3e5;
|
||||
color: #d97706;
|
||||
}
|
||||
|
||||
.tour-approval-sheet {
|
||||
max-height: 86vh;
|
||||
overflow-y: auto;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
background: #f4f6f8;
|
||||
}
|
||||
|
||||
.tour-section {
|
||||
margin: 10px 12px;
|
||||
overflow: hidden;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.tour-section-title {
|
||||
position: relative;
|
||||
padding: 14px 16px;
|
||||
border-bottom: 1px solid #edf0f4;
|
||||
color: #0b75bd;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.tour-section-title::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 16px;
|
||||
top: 0;
|
||||
width: 30px;
|
||||
height: 4px;
|
||||
border-radius: 0 0 3px 3px;
|
||||
background: #0b75bd;
|
||||
}
|
||||
|
||||
.tour-approval-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 10px 12px 14px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.tour-process-opinion {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" class="tour-approval-page" v-cloak>
|
||||
<van-nav-bar title="校工会审核" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
|
||||
<van-sticky offset-top="46px" class="tour-approval-sticky">
|
||||
<van-search
|
||||
class="tour-approval-search"
|
||||
v-model="pageForm.keyword"
|
||||
placeholder="请输入工号/姓名/线路搜索"
|
||||
show-action
|
||||
clearable
|
||||
input-align="left"
|
||||
@search="doSearch"
|
||||
@clear="doSearch">
|
||||
<template #action>
|
||||
<div @click="doSearch">搜索</div>
|
||||
</template>
|
||||
</van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item :options="auditOptions" @change="doSearch" v-model="pageForm.audit"></van-dropdown-item>
|
||||
<van-dropdown-item :options="unionOptions" @change="doSearch" v-model="pageForm.unionId"></van-dropdown-item>
|
||||
<van-dropdown-item :options="lineTypeOptions" @change="doSearch" v-model="pageForm.lineType"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</van-sticky>
|
||||
|
||||
<div class="tour-approval-list-scroll">
|
||||
<table-list api="/platform/tour/schoolUnionApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" title="userName" @ready="onReady">
|
||||
<template v-slot="{index,row}">
|
||||
<div class="tour-card-tags">
|
||||
<span v-if="row.jobNo" class="tour-tag">{{ row.jobNo }}</span>
|
||||
<span v-if="row.lineType" class="tour-tag gray">{{ row.lineType }}</span>
|
||||
<span v-if="row.overCostReimbursed" class="tour-tag warn">报销超出费用</span>
|
||||
</div>
|
||||
<table-column label="线路名称">{{ row.lineName || '' }}</table-column>
|
||||
<table-column label="出行时段">{{ row.travelPeriod || '' }}</table-column>
|
||||
<table-column label="报销超出费用">{{ row.overCostReimbursed ? '是' : '否' }}</table-column>
|
||||
<table-column label="当前节点">{{ row.curTaskName || '' }}</table-column>
|
||||
<table-column label="流程状态">
|
||||
<enum-tag
|
||||
v-if="row.instanceState !== null && row.instanceState !== undefined && row.instanceState !== ''"
|
||||
:value="row.instanceState"
|
||||
name="ProcessInstanceStateEnum"
|
||||
label_key="message"
|
||||
size="small">
|
||||
</enum-tag>
|
||||
</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
|
||||
<i class="fa fa-check"></i>
|
||||
<span>审核</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
</div>
|
||||
|
||||
<tour-info ref="infoRef">
|
||||
<div v-if="showApprovalForm" class="tour-section">
|
||||
<div class="tour-section-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
|
||||
type="textarea"
|
||||
rows="3"
|
||||
maxlength="200"
|
||||
show-word-limit>
|
||||
</van-field>
|
||||
</van-form>
|
||||
<div class="tour-approval-actions">
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(2)">拒绝</van-button>
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">同意</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</tour-info>
|
||||
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
const TOUR_INFO = {
|
||||
template: [
|
||||
"\n",
|
||||
" <van-action-sheet v-model=\"visible\" title=\"报名详情\">\n",
|
||||
" <div class=\"tour-approval-sheet\">\n",
|
||||
" <div class=\"tour-section\">\n",
|
||||
" <div class=\"tour-section-title\">教职工信息</div>\n",
|
||||
" <van-cell title=\"工号\" :value=\"detail.jobNo || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"姓名\" :value=\"detail.userName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"性别\" :value=\"detail.gender || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"身份证号\" :value=\"detail.idCard || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"所在单位\" :value=\"detail.unitName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"所在工会\" :value=\"detail.unionName || ''\"></van-cell>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <div class=\"tour-section\">\n",
|
||||
" <div class=\"tour-section-title\">报名信息</div>\n",
|
||||
" <van-cell title=\"报名线路\" :value=\"detail.lineName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"线路类型\" :value=\"detail.lineType || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"出行时段\" :value=\"detail.travelPeriod || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"报名时间\" :value=\"detail.signupTime || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"报名酒店\" :value=\"detail.hotelName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"旅行社\" :value=\"detail.travelAgencyName || ''\"></van-cell>\n",
|
||||
" <van-cell v-if=\"fillBedInfo\" title=\"床型\" :value=\"detail.bedType || ''\"></van-cell>\n",
|
||||
" <van-cell v-if=\"fillBedInfo\" title=\"床位信息\" :value=\"detail.bedInfo || ''\"></van-cell>\n",
|
||||
" <van-cell v-if=\"fillBedInfo\" title=\"意向拼床人\" :value=\"detail.intendedRoommate || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"携带家属\" :value=\"familyText()\"></van-cell>\n",
|
||||
" <van-cell title=\"报销超出费用\" :value=\"detail.overCostReimbursed ? '是' : '否'\"></van-cell>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <div v-if=\"isDirectFamilyLine()\" class=\"tour-section\">\n",
|
||||
" <div class=\"tour-section-title\">直系亲属线路</div>\n",
|
||||
" <van-cell title=\"亲属姓名\" :value=\"directRelative.relativeName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"所在单位\" :value=\"directRelative.unitName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"亲属关系\" :value=\"directRelative.relationshipName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"线路名称\" :value=\"directRelative.lineName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"出行开始\" :value=\"directRelative.travelStartTime || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"出行结束\" :value=\"directRelative.travelEndTime || ''\"></van-cell>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <div v-if=\"showFamilySection()\" class=\"tour-section\">\n",
|
||||
" <div class=\"tour-section-title\">家属信息</div>\n",
|
||||
" <template v-for=\"(item,index) in familyData\">\n",
|
||||
" <van-cell :key=\"'title_' + index\" :title=\"'家属' + (index + 1)\"></van-cell>\n",
|
||||
" <van-cell :key=\"'name_' + index\" title=\"姓名\" :value=\"item.familyName || ''\"></van-cell>\n",
|
||||
" <van-cell :key=\"'gender_' + index\" title=\"性别\" :value=\"item.gender || ''\"></van-cell>\n",
|
||||
" <van-cell :key=\"'id_' + index\" title=\"身份证号\" :value=\"item.idCard || ''\"></van-cell>\n",
|
||||
" <van-cell :key=\"'rel_' + index\" title=\"关系\" :value=\"item.relationship || ''\"></van-cell>\n",
|
||||
" <van-cell v-if=\"fillBedInfo\" :key=\"'bed_' + index\" title=\"床型\" :value=\"item.bedType || ''\"></van-cell>\n",
|
||||
" </template>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <div v-if=\"doneTasks.length > 0\" class=\"tour-section\">\n",
|
||||
" <div class=\"tour-section-title\">流程记录</div>\n",
|
||||
" <template v-for=\"task in doneTasks\">\n",
|
||||
" <van-cell-group :key=\"task.id\" :title=\"task.displayName || task.taskName\">\n",
|
||||
" <van-cell title=\"办理时间\" :value=\"task.finishTime || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"办理结果\">\n",
|
||||
" <dict-tag :options=\"dict.type.PROCESS_TASK_SUBMIT_TYPE\" :value=\"task.ext && task.ext.submitType\"></dict-tag>\n",
|
||||
" </van-cell>\n",
|
||||
" <van-cell title=\"办理意见\" v-if=\"task.taskFormData\" class=\"direction-column-cell\">\n",
|
||||
" <div class=\"tour-process-opinion\">{{ task.taskFormData.opinion || task.taskFormData.tf_opinion || '' }}</div>\n",
|
||||
" </van-cell>\n",
|
||||
" </van-cell-group>\n",
|
||||
" </template>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <slot></slot>\n",
|
||||
" </div>\n",
|
||||
" </van-action-sheet>\n",
|
||||
" \n"
|
||||
].join(""),
|
||||
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
row: {},
|
||||
detail: {},
|
||||
familyData: [],
|
||||
directRelative: {},
|
||||
allowFamily: false,
|
||||
fillBedInfo: true,
|
||||
directFamilyUnitLine: false,
|
||||
doneTasks: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onOpen(row) {
|
||||
this.row = row || {}
|
||||
this.visible = true
|
||||
this.detail = {}
|
||||
this.familyData = []
|
||||
this.directRelative = {}
|
||||
this.allowFamily = false
|
||||
this.fillBedInfo = true
|
||||
this.directFamilyUnitLine = false
|
||||
this.doneTasks = []
|
||||
this.info()
|
||||
this.getDoneTasks()
|
||||
},
|
||||
onClose() {
|
||||
this.visible = false
|
||||
},
|
||||
info() {
|
||||
this.$axios.post("/platform/tour/schoolUnionApproval/detail", { id: this.row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const data = res.data || {}
|
||||
this.detail = data.ledger || {}
|
||||
this.detail.travelPeriod = data.travelPeriod || this.row.travelPeriod || ""
|
||||
this.familyData = data.families || []
|
||||
this.directRelative = data.directRelative || {}
|
||||
this.allowFamily = this.toBoolean(data.allowFamily)
|
||||
this.fillBedInfo = data.fillBedInfo === undefined || data.fillBedInfo === null || this.toBoolean(data.fillBedInfo)
|
||||
this.directFamilyUnitLine = this.toBoolean(data.directFamilyUnitLine)
|
||||
} else {
|
||||
vant.Toast(res.msg || "查询失败")
|
||||
}
|
||||
})
|
||||
},
|
||||
getDoneTasks() {
|
||||
this.$axios.post("/flow/common/doneTasks", { bizId: this.row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.doneTasks = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
toBoolean(value) {
|
||||
return value === true || value === 1 || value === "1" || value === "true" || value === "TRUE"
|
||||
},
|
||||
isDirectFamilyLine() {
|
||||
return this.directFamilyUnitLine || this.toBoolean(this.detail.directFamilyUnitLine) || !!(this.directRelative && this.directRelative.id)
|
||||
},
|
||||
hasFamily() {
|
||||
return this.toBoolean(this.detail.hasFamily) || this.familyData.length > 0
|
||||
},
|
||||
showFamilySection() {
|
||||
return this.allowFamily && this.hasFamily() && !this.isDirectFamilyLine()
|
||||
},
|
||||
familyText() {
|
||||
if (this.isDirectFamilyLine() || !this.allowFamily) {
|
||||
return "否"
|
||||
}
|
||||
return this.hasFamily() ? "是" : "否"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
components: {
|
||||
"tour-info": TOUR_INFO
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "signupTime",
|
||||
pageOrderBy: "descending",
|
||||
audit: false,
|
||||
keyword: "",
|
||||
unionId: "",
|
||||
lineType: ""
|
||||
},
|
||||
auditOptions: [
|
||||
{ text: "未审核", value: false },
|
||||
{ text: "已审核", value: true }
|
||||
],
|
||||
unionOptions: [
|
||||
{ text: "全部工会", value: "" }
|
||||
],
|
||||
lineTypeOptions: [
|
||||
{ text: "全部线路类型", value: "" }
|
||||
],
|
||||
formData: {},
|
||||
showApprovalForm: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
historyBack,
|
||||
onReady() {
|
||||
this.doSearch()
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(async () => {
|
||||
await Promise.all([this.loadUnionOptions(), this.loadLineTypeOptions()])
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
},
|
||||
loadUnionOptions() {
|
||||
return this.$axios.post("/platform/tour/schoolUnionApproval/unionOptions", {
|
||||
audit: this.pageForm.audit,
|
||||
keyword: this.pageForm.keyword,
|
||||
lineType: this.pageForm.lineType
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const options = (res.data || []).map(item => ({
|
||||
text: item.name,
|
||||
value: item.id
|
||||
})).filter(item => item.value)
|
||||
this.unionOptions = [{ text: "全部工会", value: "" }].concat(options)
|
||||
if (this.pageForm.unionId && !this.unionOptions.some(item => item.value === this.pageForm.unionId)) {
|
||||
this.pageForm.unionId = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadLineTypeOptions() {
|
||||
return this.$axios.post("/platform/tour/schoolUnionApproval/lineTypeOptions", {
|
||||
audit: this.pageForm.audit,
|
||||
keyword: this.pageForm.keyword,
|
||||
unionId: this.pageForm.unionId
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const options = (res.data || []).map(item => ({
|
||||
text: item.lineType,
|
||||
value: item.lineType
|
||||
})).filter(item => item.value)
|
||||
this.lineTypeOptions = [{ text: "全部线路类型", value: "" }].concat(options)
|
||||
if (this.pageForm.lineType && !this.lineTypeOptions.some(item => item.value === this.pageForm.lineType)) {
|
||||
this.pageForm.lineType = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
},
|
||||
onApproval(row) {
|
||||
this.showApprovalForm = true
|
||||
this.formData = {
|
||||
processTaskId: row.taskId,
|
||||
taskName: row.curTaskName || row.taskName,
|
||||
tf_opinion: ""
|
||||
}
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
},
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate()
|
||||
} catch (e) {
|
||||
return
|
||||
}
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
const loading = this.$toast.loading({
|
||||
message: "加载中...",
|
||||
forbidClick: true,
|
||||
overlay: true,
|
||||
duration: 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()
|
||||
} else {
|
||||
this.$toast(res.msg || "操作失败")
|
||||
}
|
||||
}).finally(() => {
|
||||
loading.close()
|
||||
})
|
||||
}).catch(() => {})
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,570 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_tour_signup_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
.tour-apply-page {
|
||||
min-height: 100vh;
|
||||
padding: 10px 14px 78px;
|
||||
background: #f4f6f8;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-apply-card {
|
||||
margin-bottom: 14px;
|
||||
overflow: hidden;
|
||||
border-radius: 6px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 2px 10px rgba(15, 23, 42, 0.05);
|
||||
}
|
||||
|
||||
.tour-apply-title {
|
||||
position: relative;
|
||||
padding: 14px 16px;
|
||||
border-bottom: 1px solid #edf0f4;
|
||||
color: #0b75bd;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.tour-apply-title::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 16px;
|
||||
top: 0;
|
||||
width: 30px;
|
||||
height: 4px;
|
||||
border-radius: 0 0 3px 3px;
|
||||
background: #0b75bd;
|
||||
}
|
||||
|
||||
.tour-card-title-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tour-card-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.tour-family-tab {
|
||||
margin: 10px 12px 0;
|
||||
height: 30px;
|
||||
border-radius: 5px;
|
||||
background: #1684d2;
|
||||
color: #ffffff;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tour-field-tip {
|
||||
padding: 0 16px 12px;
|
||||
color: #ee2f2f;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.tour-over-cost /deep/ .van-field__label,
|
||||
.tour-over-cost /deep/ .van-field__label span,
|
||||
.tour-over-cost /deep/ .van-radio__label {
|
||||
color: #ee2f2f;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.tour-submit-bar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 20;
|
||||
padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
|
||||
border-top: 1px solid #edf0f4;
|
||||
background: #ffffff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-apply-empty {
|
||||
padding: 24px 0;
|
||||
color: #94a3b8;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app">
|
||||
<van-nav-bar title="疗休养报名" left-text="返回" left-arrow @click-left="historyBack('/platform/tour/signup/h5/signup')" fixed placeholder></van-nav-bar>
|
||||
|
||||
<div class="tour-apply-page">
|
||||
<van-loading v-if="pageLoading" size="24px" vertical>加载中...</van-loading>
|
||||
|
||||
<template v-else>
|
||||
<div class="tour-apply-card">
|
||||
<div class="tour-apply-title">教职工信息</div>
|
||||
<van-field label="姓名" readonly v-model="signupForm.userName"></van-field>
|
||||
<van-field label="工号" readonly v-model="signupForm.jobNo"></van-field>
|
||||
<van-field label="身份证号码" v-model="signupForm.idCard" maxlength="30" placeholder="请填写身份证号码"></van-field>
|
||||
<van-field label="手机号" v-model="signupForm.mobile" type="tel" maxlength="30" placeholder="请填写手机号"></van-field>
|
||||
<van-field label="所属工会" readonly v-model="signupForm.unionName"></van-field>
|
||||
</div>
|
||||
|
||||
<div class="tour-apply-card">
|
||||
<div class="tour-apply-title">报名信息</div>
|
||||
<van-field label="报名线路" readonly v-model="signupForm.lineName"></van-field>
|
||||
<van-field label="线路类型" readonly v-model="signupForm.lineType"></van-field>
|
||||
<van-field v-if="signupForm.travelPeriod" label="出行时间" readonly v-model="signupForm.travelPeriod"></van-field>
|
||||
<van-field label="报名酒店" v-model="signupForm.hotelName" maxlength="100" placeholder="请输入报名酒店"></van-field>
|
||||
<van-field
|
||||
v-if="fillBedInfo"
|
||||
label="床型"
|
||||
readonly
|
||||
clickable
|
||||
is-link
|
||||
placeholder="请选择房型"
|
||||
v-model="signupForm.bedType"
|
||||
@click="openBedPicker('self')">
|
||||
</van-field>
|
||||
<van-field v-if="fillBedInfo" label="床位信息" v-model="signupForm.bedInfo" maxlength="100" placeholder="请输入床位数量"></van-field>
|
||||
<van-field v-if="fillBedInfo" label="意向拼床人" v-model="signupForm.intendedRoommate" maxlength="100" placeholder="请输入意向拼床人"></van-field>
|
||||
<van-field v-if="canApplyOverReimbursement(signupForm)" class="tour-over-cost" label="报销超出费用">
|
||||
<template #input>
|
||||
<van-radio-group v-model="signupForm.overCostReimbursed" direction="horizontal">
|
||||
<van-radio :name="true">是</van-radio>
|
||||
<van-radio :name="false">否</van-radio>
|
||||
</van-radio-group>
|
||||
</template>
|
||||
</van-field>
|
||||
<div v-if="canApplyOverReimbursement(signupForm) && signupForm.overCostReimbursed" class="tour-field-tip">
|
||||
提醒:您选择了报销超出费用,会影响到下一年度的疗休养,请认真思考。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="isDirectFamilyLine(signupForm)" class="tour-apply-card">
|
||||
<div class="tour-apply-title">直系亲属线路</div>
|
||||
<van-field label="亲属姓名" v-model="directRelativeForm.relativeName" maxlength="100" placeholder="请输入亲属姓名"></van-field>
|
||||
<van-field label="所在单位" v-model="directRelativeForm.unitName" maxlength="100" placeholder="请输入所在单位"></van-field>
|
||||
<van-field
|
||||
label="亲属关系"
|
||||
readonly
|
||||
clickable
|
||||
is-link
|
||||
placeholder="请选择亲属关系"
|
||||
v-model="directRelativeForm.relationshipName"
|
||||
@click="openDirectRelativePicker">
|
||||
</van-field>
|
||||
<van-field label="线路名称" v-model="directRelativeForm.lineName" maxlength="100" placeholder="请输入线路名称"></van-field>
|
||||
<van-field label="出行开始" v-model="directRelativeForm.travelStartTime" type="date" placeholder="请选择出行开始日期"></van-field>
|
||||
<van-field label="出行结束" v-model="directRelativeForm.travelEndTime" type="date" placeholder="请选择出行结束日期"></van-field>
|
||||
</div>
|
||||
|
||||
<div class="tour-apply-card">
|
||||
<div class="tour-apply-title">
|
||||
<div class="tour-card-title-row">
|
||||
<span>亲属信息</span>
|
||||
<div class="tour-card-actions">
|
||||
<van-button size="small" type="default" :disabled="familyData.length === 0" @click="removeFamily">删除亲属</van-button>
|
||||
<van-button size="small" type="info" :disabled="!allowFamily || isDirectFamilyLine(signupForm)" @click="addFamily">添加亲属</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!allowFamily || isDirectFamilyLine(signupForm)" class="tour-apply-empty">
|
||||
当前线路不支持填写亲属
|
||||
</div>
|
||||
<template v-else-if="familyData.length > 0">
|
||||
<div class="tour-family-tab">亲属{{ familyActive + 1 }}</div>
|
||||
<van-field label="姓名" v-model="currentFamily.familyName" maxlength="100" placeholder="请填写姓名"></van-field>
|
||||
<van-field label="年龄" v-model.number="currentFamily.age" type="digit" placeholder="请填写年龄"></van-field>
|
||||
<van-field label="性别">
|
||||
<template #input>
|
||||
<van-radio-group v-model="currentFamily.gender" direction="horizontal">
|
||||
<van-radio name="男">男</van-radio>
|
||||
<van-radio name="女">女</van-radio>
|
||||
</van-radio-group>
|
||||
</template>
|
||||
</van-field>
|
||||
<van-field label="身份证号码" v-model="currentFamily.idCard" maxlength="18" placeholder="请填写身份证号码" @blur="normalizeFamilyIdCard(currentFamily)"></van-field>
|
||||
<van-field label="手机号" v-model="currentFamily.mobile" maxlength="30" placeholder="请填写手机号"></van-field>
|
||||
<van-field
|
||||
label="与本人关系"
|
||||
readonly
|
||||
clickable
|
||||
is-link
|
||||
placeholder="请选择关系"
|
||||
v-model="currentFamily.relationship"
|
||||
@click="openRelationshipPicker">
|
||||
</van-field>
|
||||
<van-field
|
||||
v-if="fillBedInfo"
|
||||
label="床型"
|
||||
readonly
|
||||
clickable
|
||||
is-link
|
||||
placeholder="请选择房型"
|
||||
v-model="currentFamily.bedType"
|
||||
@click="openBedPicker('family')">
|
||||
</van-field>
|
||||
<van-field v-if="fillBedInfo" label="床位" v-model="currentFamily.bedInfo" maxlength="100" placeholder="请输入床位数量"></van-field>
|
||||
<van-field v-if="fillBedInfo" label="意向拼床人" v-model="currentFamily.intendedRoommate" maxlength="100" placeholder="请输入意向拼床人"></van-field>
|
||||
<div v-if="fillBedInfo" class="tour-field-tip">提醒:如果跟报名人员同一房间,无须选择!</div>
|
||||
</template>
|
||||
<div v-else class="tour-apply-empty">暂无亲属,请按需添加</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="tour-submit-bar">
|
||||
<van-button type="info" block round :loading="submitLoading" @click="submitSignup">提交报名</van-button>
|
||||
</div>
|
||||
|
||||
<van-popup v-model="bedPickerVisible" position="bottom">
|
||||
<van-picker show-toolbar :columns="bedTypeColumns" @confirm="confirmBedType" @cancel="bedPickerVisible=false"></van-picker>
|
||||
</van-popup>
|
||||
|
||||
<van-popup v-model="relationshipPickerVisible" position="bottom">
|
||||
<van-picker show-toolbar :columns="relationshipColumns" @confirm="confirmRelationship" @cancel="relationshipPickerVisible=false"></van-picker>
|
||||
</van-popup>
|
||||
|
||||
<van-popup v-model="directRelativePickerVisible" position="bottom">
|
||||
<van-picker show-toolbar :columns="directRelativeColumns" @confirm="confirmDirectRelative" @cancel="directRelativePickerVisible=false"></van-picker>
|
||||
</van-popup>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
data() {
|
||||
return {
|
||||
pageLoading: true,
|
||||
submitLoading: false,
|
||||
allowFamily: false,
|
||||
fillBedInfo: true,
|
||||
signupForm: {},
|
||||
directRelativeForm: {},
|
||||
familyData: [],
|
||||
familyActive: 0,
|
||||
bedTypeOptions: [],
|
||||
familyRelationshipOptions: [],
|
||||
directRelativeOptions: [],
|
||||
bedPickerVisible: false,
|
||||
relationshipPickerVisible: false,
|
||||
directRelativePickerVisible: false,
|
||||
bedPickerTarget: "self",
|
||||
matterId: GetQueryString("matterId") || ""
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentFamily() {
|
||||
return this.familyData[this.familyActive] || {}
|
||||
},
|
||||
bedTypeColumns() {
|
||||
return this.bedTypeOptions.map(item => item.name || item.code).filter(Boolean)
|
||||
},
|
||||
relationshipColumns() {
|
||||
return this.familyRelationshipOptions.map(item => item.name || item.code).filter(Boolean)
|
||||
},
|
||||
directRelativeColumns() {
|
||||
return this.directRelativeOptions.map(item => ({ text: item.name || item.code, item }))
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
formatDateTime(date) {
|
||||
const pad = (value) => String(value).padStart(2, "0")
|
||||
return date.getFullYear()
|
||||
+ "-"
|
||||
+ pad(date.getMonth() + 1)
|
||||
+ "-"
|
||||
+ pad(date.getDate())
|
||||
+ " "
|
||||
+ pad(date.getHours())
|
||||
+ ":"
|
||||
+ pad(date.getMinutes())
|
||||
+ ":"
|
||||
+ pad(date.getSeconds())
|
||||
},
|
||||
init() {
|
||||
if (!this.matterId) {
|
||||
vant.Dialog.alert({ title: "提示", message: "报名事项参数缺失", confirmButtonColor: "#1867b0" })
|
||||
this.pageLoading = false
|
||||
return
|
||||
}
|
||||
Promise.all([this.loadOptions(), this.loadSignupDetail()]).finally(() => {
|
||||
this.pageLoading = false
|
||||
})
|
||||
},
|
||||
loadOptions() {
|
||||
return Promise.all([
|
||||
this.$axios.post("/platform/tour/signup/bedTypeOptions").then(res => {
|
||||
if (res.code === 0) this.bedTypeOptions = res.data || []
|
||||
}),
|
||||
this.$axios.post("/platform/tour/signup/familyRelationshipOptions").then(res => {
|
||||
if (res.code === 0) this.familyRelationshipOptions = res.data || []
|
||||
}),
|
||||
this.$axios.post("/platform/tour/signup/directRelativeOptions").then(res => {
|
||||
if (res.code === 0) this.directRelativeOptions = res.data || []
|
||||
})
|
||||
])
|
||||
},
|
||||
loadSignupDetail() {
|
||||
return this.$axios.post("/platform/tour/signup/signupDetail", { matterId: this.matterId }).then((res) => {
|
||||
if (res.code !== 0) {
|
||||
vant.Dialog.alert({
|
||||
title: "提示",
|
||||
message: res.msg || "报名信息加载失败",
|
||||
confirmButtonColor: "#1867b0"
|
||||
})
|
||||
return
|
||||
}
|
||||
const data = res.data || {}
|
||||
const matter = data.matter || {}
|
||||
const staff = data.staff || {}
|
||||
const ledger = data.ledger || {}
|
||||
const directRelative = data.directRelative || {}
|
||||
this.allowFamily = matter.allowFamily === true || matter.allowFamily === 1 || matter.allowFamily === "1"
|
||||
this.fillBedInfo = matter.fillBedInfo === undefined || matter.fillBedInfo === null || matter.fillBedInfo === true || matter.fillBedInfo === 1 || matter.fillBedInfo === "1"
|
||||
this.signupForm = Object.assign({
|
||||
id: "",
|
||||
year: matter.year,
|
||||
jobNo: "",
|
||||
userName: "",
|
||||
gender: "",
|
||||
idCard: "",
|
||||
mobile: "",
|
||||
unitId: "",
|
||||
unitName: "",
|
||||
unionId: "",
|
||||
unionName: "",
|
||||
signupTime: this.formatDateTime(new Date()),
|
||||
matterId: matter.matterId || "",
|
||||
lineId: matter.lineId || "",
|
||||
lineName: matter.lineName || "",
|
||||
lineType: matter.lineType || "",
|
||||
directFamilyUnitLine: matter.directFamilyUnitLine,
|
||||
hotelName: "",
|
||||
travelAgencyId: matter.travelAgencyId || "",
|
||||
travelAgencyName: matter.travelAgencyName || "",
|
||||
travelPeriod: matter.travelPeriod || "",
|
||||
travelStartTime: matter.travelStartTime || "",
|
||||
travelEndTime: matter.travelEndTime || "",
|
||||
allowOverReimbursement: matter.allowOverReimbursement,
|
||||
overCostReimbursed: false,
|
||||
hasFamily: false,
|
||||
intendedRoommate: "",
|
||||
bedType: "",
|
||||
bedInfo: ""
|
||||
}, staff, ledger, {
|
||||
year: matter.year,
|
||||
matterId: matter.matterId || ledger.matterId || "",
|
||||
lineId: matter.lineId || ledger.lineId || "",
|
||||
lineName: matter.lineName || ledger.lineName || "",
|
||||
lineType: matter.lineType || ledger.lineType || "",
|
||||
directFamilyUnitLine: matter.directFamilyUnitLine,
|
||||
travelAgencyId: matter.travelAgencyId || ledger.travelAgencyId || "",
|
||||
travelAgencyName: matter.travelAgencyName || ledger.travelAgencyName || "",
|
||||
travelPeriod: matter.travelPeriod || "",
|
||||
travelStartTime: matter.travelStartTime || "",
|
||||
travelEndTime: matter.travelEndTime || "",
|
||||
allowOverReimbursement: matter.allowOverReimbursement,
|
||||
overCostReimbursed: ledger.overCostReimbursed === true || ledger.overCostReimbursed === 1 || ledger.overCostReimbursed === "1",
|
||||
hasFamily: ledger.hasFamily === true || ledger.hasFamily === 1 || ledger.hasFamily === "1"
|
||||
})
|
||||
this.directRelativeForm = Object.assign(this.emptyDirectRelative(), {
|
||||
lineId: matter.lineId || "",
|
||||
lineName: matter.lineName || "",
|
||||
travelStartTime: matter.travelStartTime || "",
|
||||
travelEndTime: matter.travelEndTime || ""
|
||||
}, directRelative)
|
||||
this.familyData = (data.families || []).map(item => Object.assign(this.emptyFamily(), item))
|
||||
if (this.familyData.length > 0) {
|
||||
this.signupForm.hasFamily = true
|
||||
}
|
||||
if (!this.allowFamily || this.isDirectFamilyLine(this.signupForm)) {
|
||||
this.familyData = []
|
||||
this.signupForm.hasFamily = false
|
||||
}
|
||||
})
|
||||
},
|
||||
emptyFamily() {
|
||||
return {
|
||||
familyName: "",
|
||||
gender: "",
|
||||
idCard: "",
|
||||
mobile: "",
|
||||
age: null,
|
||||
bedType: "",
|
||||
bedInfo: "",
|
||||
intendedRoommate: "",
|
||||
staffJobNo: this.signupForm.jobNo || "",
|
||||
staffName: this.signupForm.userName || "",
|
||||
relationship: ""
|
||||
}
|
||||
},
|
||||
emptyDirectRelative() {
|
||||
return {
|
||||
relativeName: "",
|
||||
unitName: "",
|
||||
relationshipCode: "",
|
||||
relationshipName: "",
|
||||
lineId: this.signupForm.lineId || "",
|
||||
lineName: this.signupForm.lineName || "",
|
||||
travelStartTime: this.signupForm.travelStartTime || "",
|
||||
travelEndTime: this.signupForm.travelEndTime || ""
|
||||
}
|
||||
},
|
||||
isDirectFamilyLine(row) {
|
||||
return row && (row.directFamilyUnitLine === true || row.directFamilyUnitLine === 1 || row.directFamilyUnitLine === "1")
|
||||
},
|
||||
canApplyOverReimbursement(row) {
|
||||
return row && (row.allowOverReimbursement === true || row.allowOverReimbursement === 1 || row.allowOverReimbursement === "1")
|
||||
},
|
||||
addFamily() {
|
||||
if (!this.allowFamily || this.isDirectFamilyLine(this.signupForm)) return
|
||||
this.familyData.push(this.emptyFamily())
|
||||
this.familyActive = this.familyData.length - 1
|
||||
this.signupForm.hasFamily = true
|
||||
},
|
||||
removeFamily() {
|
||||
if (this.familyData.length === 0) return
|
||||
this.familyData.splice(this.familyActive, 1)
|
||||
this.familyActive = Math.max(0, this.familyActive - 1)
|
||||
this.signupForm.hasFamily = this.familyData.length > 0
|
||||
},
|
||||
openBedPicker(target) {
|
||||
if (this.bedTypeColumns.length === 0) {
|
||||
vant.Toast("暂无床型选项")
|
||||
return
|
||||
}
|
||||
this.bedPickerTarget = target
|
||||
this.bedPickerVisible = true
|
||||
},
|
||||
confirmBedType(value) {
|
||||
if (this.bedPickerTarget === "family") {
|
||||
this.currentFamily.bedType = value
|
||||
} else {
|
||||
this.signupForm.bedType = value
|
||||
}
|
||||
this.bedPickerVisible = false
|
||||
},
|
||||
openRelationshipPicker() {
|
||||
if (this.relationshipColumns.length === 0) {
|
||||
vant.Toast("暂无关系选项")
|
||||
return
|
||||
}
|
||||
this.relationshipPickerVisible = true
|
||||
},
|
||||
confirmRelationship(value) {
|
||||
this.currentFamily.relationship = value
|
||||
this.relationshipPickerVisible = false
|
||||
},
|
||||
openDirectRelativePicker() {
|
||||
if (this.directRelativeColumns.length === 0) {
|
||||
vant.Toast("暂无亲属关系选项")
|
||||
return
|
||||
}
|
||||
this.directRelativePickerVisible = true
|
||||
},
|
||||
confirmDirectRelative(value) {
|
||||
const item = value && value.item ? value.item : {}
|
||||
this.directRelativeForm.relationshipCode = item.code || ""
|
||||
this.directRelativeForm.relationshipName = item.name || value.text || ""
|
||||
this.directRelativePickerVisible = false
|
||||
},
|
||||
normalizeFamilyIdCard(row) {
|
||||
if (!row || !row.idCard) return
|
||||
row.idCard = String(row.idCard).trim().toUpperCase()
|
||||
},
|
||||
isValidIdCard(value) {
|
||||
if (!value) return false
|
||||
const idCard = String(value).trim().toUpperCase()
|
||||
return /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dX]$/.test(idCard)
|
||||
},
|
||||
validateFamilies() {
|
||||
if (!this.allowFamily || !this.signupForm.hasFamily) return true
|
||||
if (this.familyData.length === 0) {
|
||||
vant.Toast("请添加亲属信息")
|
||||
return false
|
||||
}
|
||||
const invalid = this.familyData.some(item => !item.familyName || !item.gender || !item.idCard || !item.relationship)
|
||||
if (invalid) {
|
||||
vant.Toast("请完善亲属姓名、性别、身份证号码和关系")
|
||||
return false
|
||||
}
|
||||
const invalidIdCard = this.familyData.some(item => !this.isValidIdCard(item.idCard))
|
||||
if (invalidIdCard) {
|
||||
vant.Toast("请输入正确的亲属身份证号码")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
validateDirectRelative() {
|
||||
if (!this.isDirectFamilyLine(this.signupForm)) return true
|
||||
if (!this.directRelativeForm.relativeName) {
|
||||
vant.Toast("请输入亲属姓名")
|
||||
return false
|
||||
}
|
||||
if (!this.directRelativeForm.unitName) {
|
||||
vant.Toast("请输入亲属所在单位")
|
||||
return false
|
||||
}
|
||||
if (!this.directRelativeForm.relationshipCode) {
|
||||
vant.Toast("请选择亲属关系")
|
||||
return false
|
||||
}
|
||||
if (!this.directRelativeForm.lineName) {
|
||||
vant.Toast("请输入直系亲属线路名称")
|
||||
return false
|
||||
}
|
||||
if (!this.directRelativeForm.travelStartTime || !this.directRelativeForm.travelEndTime) {
|
||||
vant.Toast("请选择直系亲属出行时间")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
submitSignup() {
|
||||
if (this.pageLoading || this.submitLoading) return
|
||||
if (!this.validateFamilies()) return
|
||||
if (!this.validateDirectRelative()) return
|
||||
const families = this.allowFamily && this.signupForm.hasFamily ? this.familyData : []
|
||||
const form = Object.assign({}, this.signupForm, {
|
||||
families: JSON.stringify(families),
|
||||
directRelative: this.isDirectFamilyLine(this.signupForm) ? JSON.stringify(this.directRelativeForm) : ""
|
||||
})
|
||||
this.submitLoading = true
|
||||
this.$axios.post("/platform/tour/signup/doSignup", form).then((res) => {
|
||||
this.submitLoading = false
|
||||
if (res.code === 0) {
|
||||
vant.Dialog.alert({
|
||||
title: "提示",
|
||||
message: res.msg || "报名成功",
|
||||
confirmButtonColor: "#1867b0"
|
||||
}).then(() => {
|
||||
window.location.replace("/platform/tour/signup/h5/signup")
|
||||
})
|
||||
} else {
|
||||
vant.Dialog.alert({
|
||||
title: "提示",
|
||||
message: res.msg || "报名失败",
|
||||
confirmButtonColor: "#1867b0"
|
||||
})
|
||||
}
|
||||
}).catch(() => {
|
||||
this.submitLoading = false
|
||||
vant.Toast("报名提交失败")
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.init()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,403 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_tour_signup_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
.tour-signup-h5 {
|
||||
min-height: 100vh;
|
||||
background: #f5f7fb;
|
||||
padding-bottom: 80px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-signup-banner {
|
||||
position: relative;
|
||||
height: 193px;
|
||||
overflow: hidden;
|
||||
background: #0f74bc;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.tour-signup-swipe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.tour-signup-swipe img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 193px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.tour-signup-banner::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(90deg, rgba(5, 83, 143, 0.72) 0%, rgba(5, 83, 143, 0.32) 48%, rgba(5, 83, 143, 0.08) 100%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.tour-signup-banner__text {
|
||||
position: absolute;
|
||||
left: 16px;
|
||||
right: 16px;
|
||||
bottom: 20px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.tour-signup-title {
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.tour-signup-subtitle {
|
||||
margin-top: 8px;
|
||||
color: rgba(255, 255, 255, 0.86);
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.tour-signup-card {
|
||||
margin: 10px 12px 0;
|
||||
padding: 14px 14px 16px;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 8px 20px rgba(15, 23, 42, 0.08);
|
||||
}
|
||||
|
||||
.tour-signup-card__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 1px solid #eef2f7;
|
||||
}
|
||||
|
||||
.tour-signup-card__title {
|
||||
color: #111827;
|
||||
font-size: 17px;
|
||||
font-weight: 700;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.tour-signup-card__year {
|
||||
flex-shrink: 0;
|
||||
color: #0f74bc;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-signup-notice {
|
||||
margin-top: 14px;
|
||||
color: #334155;
|
||||
font-size: 15px;
|
||||
line-height: 1.8;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.tour-signup-notice /deep/ img,
|
||||
.tour-signup-notice /deep/ video {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.tour-pdf-preview {
|
||||
min-height: 560px;
|
||||
}
|
||||
|
||||
.tour-pdf-status {
|
||||
padding: 16px 0;
|
||||
color: #64748b;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tour-pdf-toolbar {
|
||||
margin-bottom: 8px;
|
||||
color: #64748b;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.tour-pdf-pages {
|
||||
min-height: 180px;
|
||||
}
|
||||
|
||||
.tour-pdf-page {
|
||||
margin-bottom: 10px;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
background: #f8fafc;
|
||||
box-shadow: 0 1px 4px rgba(15, 23, 42, 0.08);
|
||||
}
|
||||
|
||||
.tour-pdf-page canvas {
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tour-signup-empty {
|
||||
padding: 34px 0 26px;
|
||||
}
|
||||
|
||||
.tour-signup-footer {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
|
||||
background: rgba(255, 255, 255, 0.96);
|
||||
box-shadow: 0 -6px 18px rgba(15, 23, 42, 0.08);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" class="tour-signup-h5">
|
||||
<van-nav-bar title="疗休养报名" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
|
||||
<div class="tour-signup-banner">
|
||||
<van-swipe class="tour-signup-swipe" :autoplay="3500" indicator-color="white">
|
||||
<van-swipe-item v-for="item in bannerList" :key="item">
|
||||
<img :src="item" alt="疗休养报名">
|
||||
</van-swipe-item>
|
||||
</van-swipe>
|
||||
<div class="tour-signup-banner__text">
|
||||
<div class="tour-signup-title">疗休养报名</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tour-signup-card">
|
||||
<div class="tour-signup-card__header">
|
||||
<div class="tour-signup-card__title">服务须知</div>
|
||||
<div class="tour-signup-card__year">{{ setting.year || currentYear }}年度</div>
|
||||
</div>
|
||||
|
||||
<van-skeleton title :row="8" :loading="loading">
|
||||
<div v-if="setting.serviceNotice" class="tour-signup-notice">
|
||||
<div v-if="serviceNoticePdfHref" class="tour-pdf-preview">
|
||||
<div v-if="pdfPageCount" class="tour-pdf-toolbar">
|
||||
已加载 {{ pdfRenderedPages }} / {{ pdfPageCount }} 页
|
||||
</div>
|
||||
<div ref="pdfPreviewContainer" class="tour-pdf-pages"></div>
|
||||
<div v-if="pdfLoading && pdfRenderedPages === 0" class="tour-pdf-status">
|
||||
<van-loading size="22px" vertical>正在加载第一页...</van-loading>
|
||||
</div>
|
||||
<div v-else-if="pdfLoading" class="tour-pdf-status">
|
||||
正在继续加载后续页面...
|
||||
</div>
|
||||
<div v-if="pdfError" class="tour-pdf-status">{{ pdfError }}</div>
|
||||
</div>
|
||||
<div v-else v-html="setting.serviceNotice"></div>
|
||||
</div>
|
||||
<van-empty v-else class="tour-signup-empty" description="暂无服务须知"></van-empty>
|
||||
</van-skeleton>
|
||||
</div>
|
||||
|
||||
<div class="tour-signup-footer">
|
||||
<van-button block type="info" color="#0f74bc" round @click="confirmRead">我已阅读</van-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
currentYear: new Date().getFullYear(),
|
||||
serviceNoticePdfHref: "",
|
||||
pdfDoc: null,
|
||||
pdfLoadingTask: null,
|
||||
pdfLoading: false,
|
||||
pdfError: "",
|
||||
pdfPageCount: 0,
|
||||
pdfRenderedPages: 0,
|
||||
pdfRenderToken: 0,
|
||||
bannerList: [
|
||||
"/assets/platform/images/tour/tour-h5-banner-1.jpg",
|
||||
"/assets/platform/images/tour/tour-h5-banner-2.jpg"
|
||||
],
|
||||
setting: {
|
||||
year: "",
|
||||
configName: "",
|
||||
serviceNotice: ""
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
parseContentHref(content) {
|
||||
if (!content) {
|
||||
return ""
|
||||
}
|
||||
try {
|
||||
const parser = new DOMParser()
|
||||
const doc = parser.parseFromString(content, "text/html")
|
||||
const link = doc.querySelector("a[href]")
|
||||
return link ? link.getAttribute("href") : ""
|
||||
} catch (e) {
|
||||
return ""
|
||||
}
|
||||
},
|
||||
getPdfLib() {
|
||||
return window.pdfjsLib || window["pdfjs-dist/build/pdf"]
|
||||
},
|
||||
loadPdfLib() {
|
||||
const pdfLib = this.getPdfLib()
|
||||
if (pdfLib && pdfLib.getDocument) {
|
||||
return Promise.resolve(pdfLib)
|
||||
}
|
||||
return window.loadScriptOnce("/assets/platform/plugins/pdfJs/h5/pdf.js?v=20260524").then(() => {
|
||||
const loadedPdfLib = this.getPdfLib()
|
||||
if (!loadedPdfLib || !loadedPdfLib.getDocument) {
|
||||
throw new Error("pdf lib load failed")
|
||||
}
|
||||
return loadedPdfLib
|
||||
})
|
||||
},
|
||||
clearPdfPreview() {
|
||||
this.pdfRenderToken += 1
|
||||
this.pdfDoc = null
|
||||
this.pdfLoading = false
|
||||
this.pdfError = ""
|
||||
this.pdfPageCount = 0
|
||||
this.pdfRenderedPages = 0
|
||||
if (this.pdfLoadingTask && this.pdfLoadingTask.destroy) {
|
||||
try {
|
||||
this.pdfLoadingTask.destroy()
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
this.pdfLoadingTask = null
|
||||
if (this.$refs.pdfPreviewContainer) {
|
||||
this.$refs.pdfPreviewContainer.innerHTML = ""
|
||||
}
|
||||
},
|
||||
renderServiceNoticePdf() {
|
||||
this.clearPdfPreview()
|
||||
if (!this.serviceNoticePdfHref) {
|
||||
return
|
||||
}
|
||||
const token = this.pdfRenderToken
|
||||
this.pdfLoading = true
|
||||
this.loadPdfLib().then((pdfLib) => {
|
||||
if (token !== this.pdfRenderToken) {
|
||||
return null
|
||||
}
|
||||
if (pdfLib.GlobalWorkerOptions) {
|
||||
pdfLib.GlobalWorkerOptions.workerSrc = "/assets/platform/plugins/pdfJs/h5/pdf.worker.js?v=20260524"
|
||||
}
|
||||
this.pdfLoadingTask = pdfLib.getDocument({
|
||||
url: this.serviceNoticePdfHref,
|
||||
disableAutoFetch: false,
|
||||
disableStream: false,
|
||||
disableRange: false
|
||||
})
|
||||
return this.pdfLoadingTask.promise
|
||||
}).then((pdf) => {
|
||||
if (token !== this.pdfRenderToken || !pdf) {
|
||||
return
|
||||
}
|
||||
this.pdfDoc = pdf
|
||||
this.pdfPageCount = pdf.numPages || 0
|
||||
return this.renderPdfPage(1, token)
|
||||
}).then(() => {
|
||||
if (token !== this.pdfRenderToken) {
|
||||
return
|
||||
}
|
||||
this.renderRestPdfPages(2, token)
|
||||
}).catch(() => {
|
||||
if (token !== this.pdfRenderToken) {
|
||||
return
|
||||
}
|
||||
this.pdfLoading = false
|
||||
this.pdfError = "PDF加载失败,请稍后重试"
|
||||
})
|
||||
},
|
||||
renderPdfPage(pageNumber, token) {
|
||||
if (!this.pdfDoc || token !== this.pdfRenderToken || pageNumber > this.pdfPageCount) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
return this.pdfDoc.getPage(pageNumber).then((page) => {
|
||||
if (token !== this.pdfRenderToken || !this.$refs.pdfPreviewContainer) {
|
||||
return
|
||||
}
|
||||
const container = this.$refs.pdfPreviewContainer
|
||||
const baseViewport = page.getViewport({scale: 1})
|
||||
const containerWidth = Math.max(container.clientWidth || 0, window.innerWidth - 44)
|
||||
const cssScale = containerWidth / baseViewport.width
|
||||
const outputScale = Math.min(window.devicePixelRatio || 1, 2)
|
||||
const viewport = page.getViewport({scale: cssScale})
|
||||
const pageEl = document.createElement("div")
|
||||
pageEl.className = "tour-pdf-page"
|
||||
const canvas = document.createElement("canvas")
|
||||
const context = canvas.getContext("2d")
|
||||
canvas.width = Math.floor(viewport.width * outputScale)
|
||||
canvas.height = Math.floor(viewport.height * outputScale)
|
||||
canvas.style.width = Math.floor(viewport.width) + "px"
|
||||
canvas.style.height = Math.floor(viewport.height) + "px"
|
||||
pageEl.appendChild(canvas)
|
||||
container.appendChild(pageEl)
|
||||
return page.render({
|
||||
canvasContext: context,
|
||||
viewport: viewport,
|
||||
transform: outputScale !== 1 ? [outputScale, 0, 0, outputScale, 0, 0] : null
|
||||
}).promise.then(() => {
|
||||
if (token === this.pdfRenderToken) {
|
||||
this.pdfRenderedPages = Math.max(this.pdfRenderedPages, pageNumber)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
renderRestPdfPages(pageNumber, token) {
|
||||
if (token !== this.pdfRenderToken || !this.pdfDoc || pageNumber > this.pdfPageCount) {
|
||||
this.pdfLoading = false
|
||||
return
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.renderPdfPage(pageNumber, token).then(() => {
|
||||
this.renderRestPdfPages(pageNumber + 1, token)
|
||||
}).catch(() => {
|
||||
if (token === this.pdfRenderToken) {
|
||||
this.pdfLoading = false
|
||||
this.pdfError = "部分页面加载失败"
|
||||
}
|
||||
})
|
||||
}, 120)
|
||||
},
|
||||
loadServiceNotice() {
|
||||
this.loading = true
|
||||
this.$axios.post("/platform/tour/signup/h5/serviceNotice").then((res) => {
|
||||
this.loading = false
|
||||
if (res.code === 0) {
|
||||
this.setting = Object.assign({}, this.setting, res.data || {})
|
||||
this.serviceNoticePdfHref = this.parseContentHref(this.setting.serviceNotice)
|
||||
this.$nextTick(() => {
|
||||
this.renderServiceNoticePdf()
|
||||
})
|
||||
} else {
|
||||
vant.Toast(res.msg || "服务须知加载失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
confirmRead() {
|
||||
window.location.href = "/platform/tour/signup/h5/signup"
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadServiceNotice()
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.clearPdfPreview()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,587 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_tour_signup_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
#app {
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tour-detail-page {
|
||||
height: calc(100vh - 46px);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 10px 10px 70px;
|
||||
background: #f4f6f8;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-detail-header {
|
||||
padding: 14px 12px;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 2px 10px rgba(15, 23, 42, 0.05);
|
||||
}
|
||||
|
||||
.tour-detail-title {
|
||||
color: #0f172a;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
line-height: 1.35;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.tour-detail-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.tour-line-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
height: 20px;
|
||||
padding: 0 7px;
|
||||
border-radius: 4px;
|
||||
background: #0b75bd;
|
||||
color: #ffffff;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.tour-detail-meta {
|
||||
margin-top: 10px;
|
||||
color: #334155;
|
||||
font-size: 13px;
|
||||
line-height: 1.7;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.tour-detail-meta-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.tour-detail-meta-label {
|
||||
width: 72px;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
color: #64748b;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tour-detail-meta-value {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.tour-detail-section {
|
||||
margin-top: 10px;
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 12px;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 2px 10px rgba(15, 23, 42, 0.05);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-detail-section-title {
|
||||
flex-shrink: 0;
|
||||
margin-bottom: 8px;
|
||||
padding-left: 8px;
|
||||
border-left: 3px solid #0b75bd;
|
||||
color: #0f172a;
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.tour-detail-content /deep/ img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.tour-detail-section-scroll {
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.tour-pdf-preview {
|
||||
min-height: 220px;
|
||||
}
|
||||
|
||||
.tour-pdf-status {
|
||||
padding: 16px 0;
|
||||
color: #64748b;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tour-pdf-toolbar {
|
||||
margin-bottom: 8px;
|
||||
color: #64748b;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.tour-pdf-pages {
|
||||
min-height: 180px;
|
||||
}
|
||||
|
||||
.tour-pdf-page {
|
||||
margin-bottom: 10px;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
background: #f8fafc;
|
||||
box-shadow: 0 1px 4px rgba(15, 23, 42, 0.08);
|
||||
}
|
||||
|
||||
.tour-pdf-page canvas {
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tour-detail-empty {
|
||||
padding: 18px 0;
|
||||
color: #94a3b8;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tour-detail-footer {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 10;
|
||||
padding: 9px 12px calc(9px + env(safe-area-inset-bottom));
|
||||
border-top: 1px solid #edf0f4;
|
||||
background: #ffffff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app">
|
||||
<van-nav-bar title="线路详情" left-text="返回" left-arrow @click-left="historyBack('/platform/tour/signup/h5/signup')" fixed placeholder></van-nav-bar>
|
||||
|
||||
<div class="tour-detail-page">
|
||||
<van-loading v-if="detailLoading" size="24px" vertical>加载中...</van-loading>
|
||||
<template v-else>
|
||||
<div class="tour-detail-header">
|
||||
<div class="tour-detail-title">{{ lineDetail.lineName || signupDetail.lineName || '线路详情' }}</div>
|
||||
<div class="tour-detail-tags">
|
||||
<span v-if="lineDetail.lotName || signupDetail.lotName" class="tour-line-tag">{{ lineDetail.lotName || signupDetail.lotName }}</span>
|
||||
<span v-if="lineDetail.lineType || signupDetail.lineType" class="tour-line-tag">{{ lineDetail.lineType || signupDetail.lineType }}</span>
|
||||
<span v-if="signupDetail.unionName" class="tour-line-tag">{{ signupDetail.unionName }}</span>
|
||||
</div>
|
||||
<div class="tour-detail-meta">
|
||||
<div v-if="travelPeriod(signupDetail)" class="tour-detail-meta-row">
|
||||
<span class="tour-detail-meta-label"><span>出行时间</span><span>:</span></span>
|
||||
<span class="tour-detail-meta-value">{{ travelPeriod(signupDetail) }}</span>
|
||||
</div>
|
||||
<div class="tour-detail-meta-row">
|
||||
<span class="tour-detail-meta-label"><span>已报人数</span><span>:</span></span>
|
||||
<span class="tour-detail-meta-value">{{ signupDetail.signupCount || 0 }}(家属{{ signupDetail.familyCount || 0 }}人)</span>
|
||||
</div>
|
||||
<div class="tour-detail-meta-row">
|
||||
<span class="tour-detail-meta-label"><span>联系人</span><span>:</span></span>
|
||||
<span class="tour-detail-meta-value">{{ signupDetail.contactName || '暂无' }}</span>
|
||||
</div>
|
||||
<div class="tour-detail-meta-row">
|
||||
<span class="tour-detail-meta-label"><span>联系方式</span><span>:</span></span>
|
||||
<span class="tour-detail-meta-value">{{ lineDetail.contactPhone || signupDetail.contactPhone || '暂无' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tour-detail-section">
|
||||
<div class="tour-detail-section-title">线路介绍</div>
|
||||
<div class="tour-detail-section-scroll">
|
||||
<div v-if="lineDetail.lineContent && lineContentHref" class="tour-pdf-preview">
|
||||
<div v-if="pdfPageCount" class="tour-pdf-toolbar">
|
||||
已加载 {{ pdfRenderedPages }} / {{ pdfPageCount }} 页
|
||||
</div>
|
||||
<div ref="pdfPreviewContainer" class="tour-pdf-pages"></div>
|
||||
<div v-if="pdfLoading && pdfRenderedPages === 0" class="tour-pdf-status">
|
||||
<van-loading size="22px" vertical>正在加载第一页...</van-loading>
|
||||
</div>
|
||||
<div v-else-if="pdfLoading" class="tour-pdf-status">
|
||||
正在继续加载后续页面...
|
||||
</div>
|
||||
<div v-if="pdfError" class="tour-pdf-status">{{ pdfError }}</div>
|
||||
</div>
|
||||
<div v-else-if="lineDetail.lineContent" class="tour-detail-content" v-html="lineDetail.lineContent">
|
||||
</div>
|
||||
<div v-else class="tour-detail-empty">暂无线路介绍</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="tour-detail-footer">
|
||||
<van-button :type="detailActionType()" block round :disabled="detailActionDisabled()" @click="handleDetailAction">
|
||||
{{ detailActionText() }}
|
||||
</van-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
data() {
|
||||
return {
|
||||
detailLoading: true,
|
||||
lineDetail: {},
|
||||
signupDetail: {},
|
||||
lineContentHref: "",
|
||||
pdfDoc: null,
|
||||
pdfLoadingTask: null,
|
||||
pdfLoading: false,
|
||||
pdfError: "",
|
||||
pdfPageCount: 0,
|
||||
pdfRenderedPages: 0,
|
||||
pdfRenderToken: 0,
|
||||
matterId: GetQueryString("matterId") || "",
|
||||
lineId: GetQueryString("lineId") || ""
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
travelPeriod(row) {
|
||||
if (!row) {
|
||||
return ""
|
||||
}
|
||||
if (row.travelStartTime && row.travelEndTime) {
|
||||
return row.travelStartTime + " 至 " + row.travelEndTime
|
||||
}
|
||||
return row.travelPeriod || row.travelStartTime || row.travelEndTime || ""
|
||||
},
|
||||
toBoolean(value) {
|
||||
return value === true || value === 1 || value === "1" || value === "true" || value === "TRUE"
|
||||
},
|
||||
isSigned() {
|
||||
return !!(this.signupDetail && this.signupDetail.signed)
|
||||
},
|
||||
isApprovalSignup() {
|
||||
return this.isSigned() && !!this.signupDetail.instanceId
|
||||
},
|
||||
canRevokeSignup() {
|
||||
return this.isApprovalSignup() && this.toBoolean(this.signupDetail.canRevoke) && !!this.signupDetail.startTaskId
|
||||
},
|
||||
isFinishedSignup() {
|
||||
return this.isApprovalSignup() && Number(this.signupDetail.instanceState) === 20
|
||||
},
|
||||
isRejectedSignup() {
|
||||
return this.isApprovalSignup() && Number(this.signupDetail.instanceState) === 45
|
||||
},
|
||||
canModifySignup() {
|
||||
if (!this.isSigned()) {
|
||||
return true
|
||||
}
|
||||
if (!this.isApprovalSignup()) {
|
||||
return true
|
||||
}
|
||||
return !this.isFinishedSignup() && !this.isRejectedSignup() && this.signupDetail.taskKey === "startTask"
|
||||
},
|
||||
detailActionText() {
|
||||
if (this.isSigned()) {
|
||||
if (this.canRevokeSignup()) {
|
||||
return "撤回"
|
||||
}
|
||||
if (this.isFinishedSignup()) {
|
||||
return "已完成"
|
||||
}
|
||||
if (this.isRejectedSignup()) {
|
||||
return "已拒绝"
|
||||
}
|
||||
return this.canModifySignup() ? "修改报名" : "审核中"
|
||||
}
|
||||
return "我要报名"
|
||||
},
|
||||
detailActionType() {
|
||||
return this.canRevokeSignup() ? "danger" : "info"
|
||||
},
|
||||
detailActionDisabled() {
|
||||
return this.isSigned() && this.isApprovalSignup() && (this.isFinishedSignup() || this.isRejectedSignup() || (!this.canRevokeSignup() && !this.canModifySignup()))
|
||||
},
|
||||
handleDetailAction() {
|
||||
if (this.detailActionDisabled()) {
|
||||
return
|
||||
}
|
||||
if (this.canRevokeSignup()) {
|
||||
this.revokeSignup()
|
||||
return
|
||||
}
|
||||
this.onApply()
|
||||
},
|
||||
parseLineContentHref(content) {
|
||||
if (!content) {
|
||||
return ""
|
||||
}
|
||||
try {
|
||||
const parser = new DOMParser()
|
||||
const doc = parser.parseFromString(content, "text/html")
|
||||
const link = doc.querySelector("a[href]")
|
||||
return link ? link.getAttribute("href") : ""
|
||||
} catch (e) {
|
||||
return ""
|
||||
}
|
||||
},
|
||||
getPdfLib() {
|
||||
return window.pdfjsLib || window["pdfjs-dist/build/pdf"]
|
||||
},
|
||||
loadPdfLib() {
|
||||
const pdfLib = this.getPdfLib()
|
||||
if (pdfLib && pdfLib.getDocument) {
|
||||
return Promise.resolve(pdfLib)
|
||||
}
|
||||
return window.loadScriptOnce("/assets/platform/plugins/pdfJs/h5/pdf.js?v=20260524").then(() => {
|
||||
const loadedPdfLib = this.getPdfLib()
|
||||
if (!loadedPdfLib || !loadedPdfLib.getDocument) {
|
||||
throw new Error("pdf lib load failed")
|
||||
}
|
||||
return loadedPdfLib
|
||||
})
|
||||
},
|
||||
clearPdfPreview() {
|
||||
this.pdfRenderToken += 1
|
||||
this.pdfDoc = null
|
||||
this.pdfLoading = false
|
||||
this.pdfError = ""
|
||||
this.pdfPageCount = 0
|
||||
this.pdfRenderedPages = 0
|
||||
if (this.pdfLoadingTask && this.pdfLoadingTask.destroy) {
|
||||
try {
|
||||
this.pdfLoadingTask.destroy()
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
this.pdfLoadingTask = null
|
||||
if (this.$refs.pdfPreviewContainer) {
|
||||
this.$refs.pdfPreviewContainer.innerHTML = ""
|
||||
}
|
||||
},
|
||||
renderLinePdf() {
|
||||
this.clearPdfPreview()
|
||||
if (!this.lineContentHref) {
|
||||
return
|
||||
}
|
||||
if (!this.getPdfLib() || !this.getPdfLib().getDocument) {
|
||||
const token = this.pdfRenderToken
|
||||
this.pdfLoading = true
|
||||
this.loadPdfLib().then(() => {
|
||||
if (token === this.pdfRenderToken) {
|
||||
this.renderLinePdf()
|
||||
}
|
||||
}).catch(() => {
|
||||
if (token === this.pdfRenderToken) {
|
||||
this.pdfLoading = false
|
||||
this.pdfError = "PDF预览组件加载失败"
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
const pdfLib = this.getPdfLib()
|
||||
if (!pdfLib || !pdfLib.getDocument) {
|
||||
this.pdfError = "PDF预览组件加载失败"
|
||||
return
|
||||
}
|
||||
if (pdfLib.GlobalWorkerOptions) {
|
||||
pdfLib.GlobalWorkerOptions.workerSrc = "/assets/platform/plugins/pdfJs/h5/pdf.worker.js?v=20260524"
|
||||
}
|
||||
const token = this.pdfRenderToken
|
||||
this.pdfLoading = true
|
||||
this.pdfLoadingTask = pdfLib.getDocument({
|
||||
url: this.lineContentHref,
|
||||
disableAutoFetch: false,
|
||||
disableStream: false,
|
||||
disableRange: false
|
||||
})
|
||||
this.pdfLoadingTask.promise.then((pdf) => {
|
||||
if (token !== this.pdfRenderToken) {
|
||||
return
|
||||
}
|
||||
this.pdfDoc = pdf
|
||||
this.pdfPageCount = pdf.numPages || 0
|
||||
return this.renderPdfPage(1, token)
|
||||
}).then(() => {
|
||||
if (token !== this.pdfRenderToken) {
|
||||
return
|
||||
}
|
||||
this.renderRestPdfPages(2, token)
|
||||
}).catch(() => {
|
||||
if (token !== this.pdfRenderToken) {
|
||||
return
|
||||
}
|
||||
this.pdfLoading = false
|
||||
this.pdfError = "PDF加载失败,请稍后重试"
|
||||
})
|
||||
},
|
||||
renderPdfPage(pageNumber, token) {
|
||||
if (!this.pdfDoc || token !== this.pdfRenderToken || pageNumber > this.pdfPageCount) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
return this.pdfDoc.getPage(pageNumber).then((page) => {
|
||||
if (token !== this.pdfRenderToken || !this.$refs.pdfPreviewContainer) {
|
||||
return
|
||||
}
|
||||
const container = this.$refs.pdfPreviewContainer
|
||||
const baseViewport = page.getViewport({scale: 1})
|
||||
const containerWidth = Math.max(container.clientWidth || 0, window.innerWidth - 44)
|
||||
const cssScale = containerWidth / baseViewport.width
|
||||
const outputScale = Math.min(window.devicePixelRatio || 1, 2)
|
||||
const viewport = page.getViewport({scale: cssScale})
|
||||
const pageEl = document.createElement("div")
|
||||
pageEl.className = "tour-pdf-page"
|
||||
const canvas = document.createElement("canvas")
|
||||
const context = canvas.getContext("2d")
|
||||
canvas.width = Math.floor(viewport.width * outputScale)
|
||||
canvas.height = Math.floor(viewport.height * outputScale)
|
||||
canvas.style.width = Math.floor(viewport.width) + "px"
|
||||
canvas.style.height = Math.floor(viewport.height) + "px"
|
||||
pageEl.appendChild(canvas)
|
||||
container.appendChild(pageEl)
|
||||
const renderContext = {
|
||||
canvasContext: context,
|
||||
viewport: viewport,
|
||||
transform: outputScale !== 1 ? [outputScale, 0, 0, outputScale, 0, 0] : null
|
||||
}
|
||||
return page.render(renderContext).promise.then(() => {
|
||||
if (token === this.pdfRenderToken) {
|
||||
this.pdfRenderedPages = Math.max(this.pdfRenderedPages, pageNumber)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
renderRestPdfPages(pageNumber, token) {
|
||||
if (token !== this.pdfRenderToken || !this.pdfDoc || pageNumber > this.pdfPageCount) {
|
||||
this.pdfLoading = false
|
||||
return
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.renderPdfPage(pageNumber, token).then(() => {
|
||||
this.renderRestPdfPages(pageNumber + 1, token)
|
||||
}).catch(() => {
|
||||
if (token === this.pdfRenderToken) {
|
||||
this.pdfLoading = false
|
||||
this.pdfError = "部分页面加载失败"
|
||||
}
|
||||
})
|
||||
}, 120)
|
||||
},
|
||||
loadDetail() {
|
||||
if (!this.matterId || !this.lineId) {
|
||||
this.detailLoading = false
|
||||
vant.Dialog.alert({
|
||||
title: "提示",
|
||||
message: "线路参数不完整",
|
||||
confirmButtonColor: "#1867b0"
|
||||
})
|
||||
return
|
||||
}
|
||||
Promise.all([
|
||||
this.$axios.post("/platform/tour/signup/lineDetail", { lineId: this.lineId }),
|
||||
this.$axios.post("/platform/tour/signup/signupDetail", { matterId: this.matterId })
|
||||
]).then(([lineRes, signupRes]) => {
|
||||
this.detailLoading = false
|
||||
if (lineRes.code !== 0) {
|
||||
vant.Toast(lineRes.msg || "线路详情加载失败")
|
||||
} else {
|
||||
this.lineDetail = lineRes.data || {}
|
||||
this.lineContentHref = this.parseLineContentHref(this.lineDetail.lineContent)
|
||||
this.$nextTick(() => {
|
||||
this.renderLinePdf()
|
||||
})
|
||||
}
|
||||
if (signupRes.code !== 0) {
|
||||
vant.Toast(signupRes.msg || "报名信息加载失败")
|
||||
} else {
|
||||
const data = signupRes.data || {}
|
||||
const process = data.process || {}
|
||||
this.signupDetail = Object.assign({}, data.matter || {}, {
|
||||
signed: !!(data.ledger && data.ledger.id)
|
||||
}, process)
|
||||
}
|
||||
}).catch(() => {
|
||||
this.detailLoading = false
|
||||
vant.Toast("线路详情加载失败")
|
||||
})
|
||||
},
|
||||
onApply() {
|
||||
if (!this.matterId) {
|
||||
vant.Toast("报名事项信息不完整")
|
||||
return
|
||||
}
|
||||
const goApply = () => {
|
||||
window.location.href = "/platform/tour/signup/h5/apply?matterId=" + encodeURIComponent(this.matterId)
|
||||
}
|
||||
this.$axios.post("/platform/tour/signup/signupEligibilityNotice", { matterId: this.matterId }).then((res) => {
|
||||
if (res.code !== 0) {
|
||||
vant.Dialog.alert({
|
||||
title: "温馨提醒",
|
||||
message: res.msg || "当前不能报名",
|
||||
confirmButtonColor: "#1867b0"
|
||||
})
|
||||
return
|
||||
}
|
||||
const data = res.data || {}
|
||||
if (!data.noticeRequired) {
|
||||
goApply()
|
||||
return
|
||||
}
|
||||
if (data.canApply) {
|
||||
vant.Dialog.confirm({
|
||||
title: "温馨提醒",
|
||||
message: data.message || "当前可报名,是否继续报名?",
|
||||
confirmButtonText: "继续报名",
|
||||
cancelButtonText: "稍后报名",
|
||||
confirmButtonColor: "#1867b0"
|
||||
}).then(goApply).catch(() => {})
|
||||
} else {
|
||||
vant.Dialog.alert({
|
||||
title: "温馨提醒",
|
||||
message: data.message || "当前不能报名",
|
||||
confirmButtonColor: "#1867b0"
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
revokeSignup() {
|
||||
vant.Dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要撤回吗?",
|
||||
confirmButtonColor: "#ee2f2f"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/revokeTask", { taskId: this.signupDetail.startTaskId }).then((resp) => {
|
||||
if (resp.code === 0) {
|
||||
vant.Toast.success(resp.msg || "撤回成功")
|
||||
this.loadDetail()
|
||||
} else {
|
||||
vant.Dialog.alert({ title: "提示", message: resp.msg || "撤回失败", confirmButtonColor: "#1867b0" })
|
||||
}
|
||||
})
|
||||
}).catch(() => {})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadDetail()
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.clearPdfPreview()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,794 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_tour_signup_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
.tour-line-page {
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #f4f6f8;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-line-scroll {
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding-bottom: 18px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-line-toolbar {
|
||||
padding: 10px 0 8px 16px;
|
||||
background: #f4f6f8;
|
||||
}
|
||||
|
||||
.tour-line-toolbar /deep/ .van-search {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.tour-line-toolbar .van-search {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.tour-line-toolbar /deep/ .van-search__content {
|
||||
height: 38px;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.tour-line-toolbar .van-search__content {
|
||||
height: 38px;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.tour-line-toolbar /deep/ .van-search__action {
|
||||
padding: 0 0 0 6px;
|
||||
}
|
||||
|
||||
.tour-line-toolbar .van-search__action {
|
||||
padding: 0 0 0 6px;
|
||||
}
|
||||
|
||||
.tour-line-search-button {
|
||||
width: 42px;
|
||||
height: 38px;
|
||||
border: 0;
|
||||
border-radius: 8px;
|
||||
background: #1e88e5;
|
||||
color: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 20px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.tour-line-search-row {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-line-union-entry {
|
||||
width: 48px;
|
||||
min-height: 42px;
|
||||
flex-shrink: 0;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
color: #64748b;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 2px;
|
||||
font-size: 11px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.tour-line-union-entry .van-icon {
|
||||
color: #64748b;
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.tour-line-union-entry--active,
|
||||
.tour-line-union-entry--active .van-icon {
|
||||
color: #0b75bd;
|
||||
}
|
||||
|
||||
.tour-line-union-popup {
|
||||
max-height: 68vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tour-line-union-popup__title {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
padding: 14px 16px 10px;
|
||||
background: #ffffff;
|
||||
color: #0f172a;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-line-union-popup__list {
|
||||
overflow-y: auto;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
.tour-line-union-popup__item {
|
||||
min-height: 48px;
|
||||
transition: background-color 0.18s ease, color 0.18s ease;
|
||||
}
|
||||
|
||||
.tour-line-union-popup__item:hover,
|
||||
.tour-line-union-popup__item:active {
|
||||
background: rgba(30, 136, 229, 0.1);
|
||||
}
|
||||
|
||||
.tour-line-union-popup__item:hover /deep/ .van-cell__title,
|
||||
.tour-line-union-popup__item:active /deep/ .van-cell__title {
|
||||
color: #0b75bd;
|
||||
}
|
||||
|
||||
.tour-line-union-popup__item--active /deep/ .van-cell__title {
|
||||
color: #0b75bd;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.tour-line-shortcuts {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.tour-line-shortcut {
|
||||
min-height: 76px;
|
||||
padding: 12px 8px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 5px;
|
||||
box-shadow: 0 2px 10px rgba(15, 23, 42, 0.05);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-line-shortcut--active {
|
||||
border-color: #0b75bd;
|
||||
background: rgba(11, 117, 189, 0.08);
|
||||
}
|
||||
|
||||
.tour-line-shortcut__icon {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
flex-shrink: 0;
|
||||
display: block;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.tour-line-shortcut__text {
|
||||
min-width: 0;
|
||||
color: #0f172a;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
line-height: 1.3;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tour-line-shortcut__hint {
|
||||
margin-top: 2px;
|
||||
color: #64748b;
|
||||
font-size: 11px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.tour-line-list {
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.tour-line-card {
|
||||
position: relative;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
min-height: 112px;
|
||||
margin: 8px 0;
|
||||
padding: 10px;
|
||||
border-radius: 6px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 2px 10px rgba(15, 23, 42, 0.05);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-line-thumb {
|
||||
width: 145px;
|
||||
height: 98px;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 6px;
|
||||
background: #e5edf6;
|
||||
}
|
||||
|
||||
.tour-line-thumb img,
|
||||
.tour-line-thumb .van-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tour-line-thumb-empty {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #8a98a8;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.tour-line-main {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.tour-line-signed-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
flex-shrink: 0;
|
||||
border-radius: 50%;
|
||||
background: #a78bfa;
|
||||
color: #ffffff;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 13px;
|
||||
line-height: 1;
|
||||
box-shadow: 0 2px 5px rgba(167, 139, 250, 0.32);
|
||||
}
|
||||
|
||||
.tour-line-title-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.tour-line-title {
|
||||
min-width: 0;
|
||||
color: #0f172a;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
line-height: 1.35;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.tour-line-type-badge {
|
||||
height: 18px;
|
||||
flex-shrink: 0;
|
||||
padding: 0 5px;
|
||||
border: 1px solid #ffd6a8;
|
||||
border-radius: 4px;
|
||||
background: #fff3e5;
|
||||
color: #d97706;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
line-height: 17px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-line-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.tour-line-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
height: 20px;
|
||||
padding: 0 7px;
|
||||
border-radius: 4px;
|
||||
background: #39a9ed;
|
||||
color: #ffffff;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.tour-line-info {
|
||||
margin-top: 5px;
|
||||
color: #111827;
|
||||
font-size: 13px;
|
||||
line-height: 1.55;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.tour-line-info span {
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.tour-line-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.tour-line-action {
|
||||
min-width: 70px;
|
||||
height: 28px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #1e88e5;
|
||||
border-radius: 14px;
|
||||
background: #1e88e5;
|
||||
color: #ffffff;
|
||||
font-size: 12px;
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
.tour-line-action--danger {
|
||||
border-color: #ee2f2f;
|
||||
background: #ee2f2f;
|
||||
}
|
||||
|
||||
.tour-line-action--disabled {
|
||||
border-color: #d1d5db;
|
||||
background: #e5e7eb;
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
@media (max-width: 360px) {
|
||||
.tour-line-card {
|
||||
gap: 9px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.tour-line-thumb {
|
||||
width: 126px;
|
||||
height: 92px;
|
||||
}
|
||||
|
||||
.tour-line-title {
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" class="tour-line-page">
|
||||
<van-nav-bar title="疗休养线路" left-text="返回" left-arrow @click-left="historyBack('/platform/tour/signup/h5')" fixed placeholder></van-nav-bar>
|
||||
|
||||
<div class="tour-line-toolbar">
|
||||
<div class="tour-line-search-row">
|
||||
<van-search
|
||||
v-model="pageForm.lineName"
|
||||
show-action
|
||||
clearable
|
||||
placeholder="请输入线路名称搜索"
|
||||
@search="doSearch"
|
||||
@clear="doSearch">
|
||||
<template #action>
|
||||
<button type="button" class="tour-line-search-button" @click="doSearch">
|
||||
<van-icon name="search"></van-icon>
|
||||
</button>
|
||||
</template>
|
||||
</van-search>
|
||||
<button
|
||||
type="button"
|
||||
class="tour-line-union-entry"
|
||||
:class="{'tour-line-union-entry--active': !!pageForm.unionId}"
|
||||
@click="openUnionPopup">
|
||||
<van-icon name="friends-o"></van-icon>
|
||||
<span>分工会</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="tour-line-shortcuts">
|
||||
<div
|
||||
class="tour-line-shortcut"
|
||||
:class="{'tour-line-shortcut--active': pageForm.lineType === '省内线路' && pageForm.directFamilyUnitLine === null}"
|
||||
@click="toggleLineType('省内线路')">
|
||||
<img class="tour-line-shortcut__icon" src="/assets/platform/images/tour/tour-in-province.png" alt="省内线路">
|
||||
<div class="tour-line-shortcut__text">
|
||||
<div>省内线路</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="tour-line-shortcut"
|
||||
:class="{'tour-line-shortcut--active': pageForm.lineType === '省外线路' && pageForm.directFamilyUnitLine === null}"
|
||||
@click="toggleLineType('省外线路')">
|
||||
<img class="tour-line-shortcut__icon" src="/assets/platform/images/tour/tour-out-province.png" alt="省外线路">
|
||||
<div class="tour-line-shortcut__text">
|
||||
<div>省外线路</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="tour-line-shortcut"
|
||||
:class="{'tour-line-shortcut--active': pageForm.directFamilyUnitLine === true}"
|
||||
@click="toggleDirectFamilyLine">
|
||||
<img class="tour-line-shortcut__icon" src="/assets/platform/images/tour/tour-direct-family-icon.png?v=20260524" alt="直系亲属">
|
||||
<div class="tour-line-shortcut__text">
|
||||
<div>直系亲属</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tour-line-scroll">
|
||||
<van-list
|
||||
v-model="loading"
|
||||
:finished="finished"
|
||||
finished-text="没有更多了"
|
||||
@load="loadData">
|
||||
<div class="tour-line-list">
|
||||
<div class="tour-line-card" v-for="row in list" :key="row.matterId" @click="onLine(row)">
|
||||
<div class="tour-line-thumb">
|
||||
<van-image v-if="thumbUrl(row)" :src="thumbUrl(row)" fit="cover" lazy-load>
|
||||
<template #loading>
|
||||
<div class="tour-line-thumb-empty">图片加载中</div>
|
||||
</template>
|
||||
<template #error>
|
||||
<div class="tour-line-thumb-empty">暂无图片</div>
|
||||
</template>
|
||||
</van-image>
|
||||
<div v-else class="tour-line-thumb-empty">暂无图片</div>
|
||||
</div>
|
||||
<div class="tour-line-main">
|
||||
<div class="tour-line-title-row">
|
||||
<div class="tour-line-title">{{ row.lineName || '未命名线路' }}</div>
|
||||
<span v-if="lineTypeBadge(row.lineType)" class="tour-line-type-badge">{{ lineTypeBadge(row.lineType) }}</span>
|
||||
<span v-if="isSigned(row)" class="tour-line-signed-icon">
|
||||
<van-icon name="good-job"></van-icon>
|
||||
</span>
|
||||
</div>
|
||||
<div class="tour-line-tags">
|
||||
<span v-if="row.lotName" class="tour-line-tag">{{ row.lotName }}</span>
|
||||
<span v-if="row.unionName" class="tour-line-tag">{{ row.unionName }}</span>
|
||||
</div>
|
||||
<div class="tour-line-info">
|
||||
<div><span>出行开始时间:</span>{{ row.travelStartTime || '暂无' }}</div>
|
||||
<div><span>出行结束时间:</span>{{ row.travelEndTime || '暂无' }}</div>
|
||||
<!-- 临时屏蔽旅行社信息,保留字段和接口便于后续恢复。
|
||||
<div><span>旅行社:</span>{{ row.travelAgencyName || '暂无' }}</div>
|
||||
-->
|
||||
</div>
|
||||
<div class="tour-line-actions">
|
||||
<button
|
||||
v-if="showSignupAction(row)"
|
||||
type="button"
|
||||
class="tour-line-action"
|
||||
:class="{
|
||||
'tour-line-action--danger': canRevokeSignup(row),
|
||||
'tour-line-action--disabled': signupActionDisabled(row)
|
||||
}"
|
||||
:disabled="signupActionDisabled(row)"
|
||||
@click.stop="handleSignupAction(row)">
|
||||
{{ signupActionText(row) }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-list>
|
||||
|
||||
<van-empty v-if="!loading && list.length === 0" description="暂无线路"></van-empty>
|
||||
</div>
|
||||
|
||||
<van-popup v-model="showUnionPopup" position="bottom" round>
|
||||
<div class="tour-line-union-popup">
|
||||
<div class="tour-line-union-popup__title">选择分工会</div>
|
||||
<div class="tour-line-union-popup__list">
|
||||
<van-cell
|
||||
v-for="item in unionList"
|
||||
:key="item.id || 'all'"
|
||||
clickable
|
||||
class="tour-line-union-popup__item"
|
||||
:class="{'tour-line-union-popup__item--active': pageForm.unionId === item.id}"
|
||||
:title="item.name"
|
||||
@click="selectUnion(item)">
|
||||
<template #right-icon>
|
||||
<van-icon v-if="pageForm.unionId === item.id" name="success" color="#0b75bd"></van-icon>
|
||||
</template>
|
||||
</van-cell>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
loading: false,
|
||||
finished: false,
|
||||
lineChecking: false,
|
||||
showUnionPopup: false,
|
||||
unionList: [
|
||||
{id: "", name: "全部分工会"}
|
||||
],
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
year: new Date().getFullYear(),
|
||||
lineName: "",
|
||||
lineType: "",
|
||||
unionId: "",
|
||||
directFamilyUnitLine: null,
|
||||
pageOrderName: "lineName",
|
||||
pageOrderBy: "ascending"
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
thumbUrl(row) {
|
||||
return row.lineMobileThumb || row.agencyMobileThumb || ""
|
||||
},
|
||||
lineTypeBadge(lineType) {
|
||||
if (lineType === "省内线路" || lineType === "省内") {
|
||||
return "省内"
|
||||
}
|
||||
if (lineType === "省外线路" || lineType === "省外") {
|
||||
return "省外"
|
||||
}
|
||||
return ""
|
||||
},
|
||||
isSigned(row) {
|
||||
return !!(row && (row.signed === true || row.signed === 1 || row.signed === "1" || row.ledgerId))
|
||||
},
|
||||
isApprovalSignup(row) {
|
||||
return !!(row && this.isSigned(row) && row.instanceId)
|
||||
},
|
||||
canRevokeSignup(row) {
|
||||
return this.isApprovalSignup(row) && this.toBoolean(row.canRevoke) && !!row.startTaskId
|
||||
},
|
||||
isFinishedSignup(row) {
|
||||
return this.isApprovalSignup(row) && Number(row.instanceState) === 20
|
||||
},
|
||||
isRejectedSignup(row) {
|
||||
return this.isApprovalSignup(row) && Number(row.instanceState) === 45
|
||||
},
|
||||
canModifySignup(row) {
|
||||
if (!row || !this.isSigned(row)) {
|
||||
return true
|
||||
}
|
||||
if (!this.isApprovalSignup(row)) {
|
||||
return true
|
||||
}
|
||||
return !this.isFinishedSignup(row) && !this.isRejectedSignup(row) && row.taskKey === "startTask"
|
||||
},
|
||||
signupActionText(row) {
|
||||
if (this.isSigned(row)) {
|
||||
if (this.canRevokeSignup(row)) {
|
||||
return "撤回"
|
||||
}
|
||||
if (this.isRejectedSignup(row)) {
|
||||
return "已拒绝"
|
||||
}
|
||||
return this.canModifySignup(row) ? "修改" : "审核中"
|
||||
}
|
||||
return "报名"
|
||||
},
|
||||
showSignupAction(row) {
|
||||
return this.isSigned(row) && this.canModifySignup(row)
|
||||
},
|
||||
signupActionDisabled(row) {
|
||||
return !!(this.isSigned(row) && this.isApprovalSignup(row) && (this.isRejectedSignup(row) || (!this.canRevokeSignup(row) && !this.canModifySignup(row))))
|
||||
},
|
||||
toBoolean(value) {
|
||||
return value === true || value === 1 || value === "1" || value === "true" || value === "TRUE"
|
||||
},
|
||||
handleSignupAction(row) {
|
||||
if (this.signupActionDisabled(row)) {
|
||||
return
|
||||
}
|
||||
if (this.canRevokeSignup(row)) {
|
||||
this.revokeSignup(row)
|
||||
return
|
||||
}
|
||||
this.goApply(row)
|
||||
},
|
||||
goApply(row) {
|
||||
if (!row || !row.matterId) {
|
||||
vant.Toast("报名事项信息不完整")
|
||||
return
|
||||
}
|
||||
const go = () => {
|
||||
window.location.href = "/platform/tour/signup/h5/apply?matterId=" + encodeURIComponent(row.matterId)
|
||||
}
|
||||
this.$axios.post("/platform/tour/signup/signupEligibilityNotice", { matterId: row.matterId }).then((res) => {
|
||||
if (res.code !== 0) {
|
||||
vant.Dialog.alert({
|
||||
title: "温馨提醒",
|
||||
message: res.msg || "当前不能报名",
|
||||
confirmButtonColor: "#1867b0"
|
||||
})
|
||||
return
|
||||
}
|
||||
const data = res.data || {}
|
||||
if (!data.noticeRequired) {
|
||||
go()
|
||||
return
|
||||
}
|
||||
if (data.canApply) {
|
||||
vant.Dialog.confirm({
|
||||
title: "温馨提醒",
|
||||
message: data.message || "当前可报名,是否继续报名?",
|
||||
confirmButtonText: "继续报名",
|
||||
cancelButtonText: "稍后报名",
|
||||
confirmButtonColor: "#1867b0"
|
||||
}).then(go).catch(() => {})
|
||||
} else {
|
||||
vant.Dialog.alert({
|
||||
title: "温馨提醒",
|
||||
message: data.message || "当前不能报名",
|
||||
confirmButtonColor: "#1867b0"
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
revokeSignup(row) {
|
||||
vant.Dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要撤回吗?",
|
||||
confirmButtonColor: "#ee2f2f"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/revokeTask", { taskId: row.startTaskId }).then((resp) => {
|
||||
if (resp.code === 0) {
|
||||
vant.Toast.success(resp.msg || "撤回成功")
|
||||
this.doSearch()
|
||||
} else {
|
||||
vant.Dialog.alert({ title: "提示", message: resp.msg || "撤回失败", confirmButtonColor: "#1867b0" })
|
||||
}
|
||||
})
|
||||
}).catch(() => {})
|
||||
},
|
||||
doSearch() {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.list = []
|
||||
this.finished = false
|
||||
this.loadData()
|
||||
},
|
||||
toggleLineType(lineType) {
|
||||
const active = this.pageForm.lineType === lineType && this.pageForm.directFamilyUnitLine === null
|
||||
this.pageForm.lineType = active ? "" : lineType
|
||||
this.pageForm.directFamilyUnitLine = null
|
||||
this.doSearch()
|
||||
},
|
||||
toggleDirectFamilyLine() {
|
||||
const active = this.pageForm.directFamilyUnitLine === true
|
||||
this.pageForm.directFamilyUnitLine = active ? null : true
|
||||
this.pageForm.lineType = ""
|
||||
this.doSearch()
|
||||
},
|
||||
openUnionPopup() {
|
||||
this.showUnionPopup = true
|
||||
if (this.unionList.length <= 1) {
|
||||
this.loadUnionOptions()
|
||||
}
|
||||
},
|
||||
selectUnion(item) {
|
||||
const unionId = item && item.id ? item.id : ""
|
||||
this.showUnionPopup = false
|
||||
if (this.pageForm.unionId === unionId) {
|
||||
return
|
||||
}
|
||||
this.pageForm.unionId = unionId
|
||||
this.doSearch()
|
||||
},
|
||||
loadUnionOptions() {
|
||||
this.$axios.post("/platform/tour/signup/unionOptions").then((res) => {
|
||||
if (res.code !== 0) {
|
||||
return
|
||||
}
|
||||
const rows = res.data || []
|
||||
this.unionList = [{id: "", name: "全部分工会"}].concat(rows.map((item) => {
|
||||
return {
|
||||
id: item.id || "",
|
||||
name: item.name || "未命名分工会"
|
||||
}
|
||||
}))
|
||||
})
|
||||
},
|
||||
loadData() {
|
||||
if (this.finished) {
|
||||
this.loading = false
|
||||
return
|
||||
}
|
||||
this.loading = true
|
||||
this.$axios.post("/platform/tour/signup/h5/pageData", this.pageForm).then((res) => {
|
||||
this.loading = false
|
||||
if (res.code !== 0) {
|
||||
vant.Toast(res.msg || "线路加载失败")
|
||||
this.finished = true
|
||||
return
|
||||
}
|
||||
const data = res.data || {}
|
||||
const rows = data.list || []
|
||||
this.pageForm.totalCount = data.totalCount || 0
|
||||
this.list = this.pageForm.pageNumber === 1 ? rows : this.list.concat(rows)
|
||||
if (this.list.length >= this.pageForm.totalCount || rows.length === 0) {
|
||||
this.finished = true
|
||||
} else {
|
||||
this.pageForm.pageNumber += 1
|
||||
}
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.finished = true
|
||||
})
|
||||
},
|
||||
onLine(row) {
|
||||
if (!row || !row.lineId || !row.matterId) {
|
||||
vant.Toast("线路信息不完整")
|
||||
return
|
||||
}
|
||||
if (this.lineChecking) {
|
||||
return
|
||||
}
|
||||
this.lineChecking = true
|
||||
axios.post("/platform/tour/signup/signupDetail", $.param({ matterId: row.matterId }), {
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded;charset=utf-8",
|
||||
"x-requested-with": "XMLHttpRequest"
|
||||
}
|
||||
}).then((resp) => {
|
||||
this.lineChecking = false
|
||||
const res = resp.data || {}
|
||||
if (res.code !== 0) {
|
||||
vant.Dialog.alert({
|
||||
title: "温馨提醒",
|
||||
message: res.msg || "当前线路暂不能报名",
|
||||
confirmButtonColor: "#1867b0"
|
||||
})
|
||||
return
|
||||
}
|
||||
window.location.href = "/platform/tour/signup/h5/lineInfo?matterId="
|
||||
+ encodeURIComponent(row.matterId)
|
||||
+ "&lineId="
|
||||
+ encodeURIComponent(row.lineId)
|
||||
}).catch((err) => {
|
||||
this.lineChecking = false
|
||||
vant.Dialog.alert({
|
||||
title: "温馨提醒",
|
||||
message: err && err.msg ? err.msg : "当前线路暂不能报名",
|
||||
confirmButtonColor: "#1867b0"
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadUnionOptions()
|
||||
this.loadData()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -0,0 +1,455 @@
|
||||
<!--#
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
.tour-approval-page {
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #f4f6f8;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-approval-sticky {
|
||||
flex-shrink: 0;
|
||||
background: #f4f6f8;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll {
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding-bottom: 18px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-approval-search /deep/ .van-search__content,
|
||||
.tour-approval-search .van-search__content {
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.tour-card-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.tour-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 22px;
|
||||
padding: 0 8px;
|
||||
border-radius: 4px;
|
||||
background: #eef6ff;
|
||||
color: #0b75bd;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.tour-tag.gray {
|
||||
background: #f1f5f9;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.tour-tag.warn {
|
||||
background: #fff3e5;
|
||||
color: #d97706;
|
||||
}
|
||||
|
||||
.tour-approval-sheet {
|
||||
max-height: 86vh;
|
||||
overflow-y: auto;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
background: #f4f6f8;
|
||||
}
|
||||
|
||||
.tour-section {
|
||||
margin: 10px 12px;
|
||||
overflow: hidden;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.tour-section-title {
|
||||
position: relative;
|
||||
padding: 14px 16px;
|
||||
border-bottom: 1px solid #edf0f4;
|
||||
color: #0b75bd;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.tour-section-title::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 16px;
|
||||
top: 0;
|
||||
width: 30px;
|
||||
height: 4px;
|
||||
border-radius: 0 0 3px 3px;
|
||||
background: #0b75bd;
|
||||
}
|
||||
|
||||
.tour-approval-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 10px 12px 14px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.tour-process-opinion {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" class="tour-approval-page" v-cloak>
|
||||
<van-nav-bar title="分工会审核" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
|
||||
<van-sticky offset-top="46px" class="tour-approval-sticky">
|
||||
<van-search
|
||||
class="tour-approval-search"
|
||||
v-model="pageForm.keyword"
|
||||
placeholder="请输入工号/姓名/线路搜索"
|
||||
show-action
|
||||
clearable
|
||||
input-align="left"
|
||||
@search="doSearch"
|
||||
@clear="doSearch">
|
||||
<template #action>
|
||||
<div @click="doSearch">搜索</div>
|
||||
</template>
|
||||
</van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item :options="auditOptions" @change="doSearch" v-model="pageForm.audit"></van-dropdown-item>
|
||||
<van-dropdown-item :options="lineTypeOptions" @change="doSearch" v-model="pageForm.lineType"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</van-sticky>
|
||||
|
||||
<div class="tour-approval-list-scroll">
|
||||
<table-list api="/platform/tour/unionApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" title="userName" @ready="onReady">
|
||||
<template v-slot="{index,row}">
|
||||
<div class="tour-card-tags">
|
||||
<span v-if="row.jobNo" class="tour-tag">{{ row.jobNo }}</span>
|
||||
<span v-if="row.lineType" class="tour-tag gray">{{ row.lineType }}</span>
|
||||
<span v-if="row.overCostReimbursed" class="tour-tag warn">报销超出费用</span>
|
||||
</div>
|
||||
<table-column label="线路名称">{{ row.lineName || '' }}</table-column>
|
||||
<table-column label="出行时段">{{ row.travelPeriod || '' }}</table-column>
|
||||
<table-column label="报销超出费用">{{ row.overCostReimbursed ? '是' : '否' }}</table-column>
|
||||
<table-column label="当前节点">{{ row.curTaskName || '' }}</table-column>
|
||||
<table-column label="流程状态">
|
||||
<enum-tag
|
||||
v-if="row.instanceState !== null && row.instanceState !== undefined && row.instanceState !== ''"
|
||||
:value="row.instanceState"
|
||||
name="ProcessInstanceStateEnum"
|
||||
label_key="message"
|
||||
size="small">
|
||||
</enum-tag>
|
||||
</table-column>
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
|
||||
<i class="fa fa-check"></i>
|
||||
<span>审核</span>
|
||||
</div>
|
||||
</template>
|
||||
</table-list>
|
||||
</div>
|
||||
|
||||
<tour-info ref="infoRef">
|
||||
<div v-if="showApprovalForm" class="tour-section">
|
||||
<div class="tour-section-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
|
||||
type="textarea"
|
||||
rows="3"
|
||||
maxlength="200"
|
||||
show-word-limit>
|
||||
</van-field>
|
||||
</van-form>
|
||||
<div class="tour-approval-actions">
|
||||
<van-button type="danger" block @click="handleTaskAction(6)">退回</van-button>
|
||||
<van-button type="danger" block @click="handleTaskAction(2)">拒绝</van-button>
|
||||
<van-button type="primary" block @click="handleTaskAction(1)">同意</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</tour-info>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
const TOUR_INFO = {
|
||||
template: [
|
||||
"\n",
|
||||
" <van-action-sheet v-model=\"visible\" title=\"报名详情\">\n",
|
||||
" <div class=\"tour-approval-sheet\">\n",
|
||||
" <div class=\"tour-section\">\n",
|
||||
" <div class=\"tour-section-title\">教职工信息</div>\n",
|
||||
" <van-cell title=\"工号\" :value=\"detail.jobNo || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"姓名\" :value=\"detail.userName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"性别\" :value=\"detail.gender || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"身份证号\" :value=\"detail.idCard || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"所在单位\" :value=\"detail.unitName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"所在工会\" :value=\"detail.unionName || ''\"></van-cell>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <div class=\"tour-section\">\n",
|
||||
" <div class=\"tour-section-title\">报名信息</div>\n",
|
||||
" <van-cell title=\"报名线路\" :value=\"detail.lineName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"线路类型\" :value=\"detail.lineType || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"出行时段\" :value=\"detail.travelPeriod || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"报名时间\" :value=\"detail.signupTime || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"报名酒店\" :value=\"detail.hotelName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"旅行社\" :value=\"detail.travelAgencyName || ''\"></van-cell>\n",
|
||||
" <van-cell v-if=\"fillBedInfo\" title=\"床型\" :value=\"detail.bedType || ''\"></van-cell>\n",
|
||||
" <van-cell v-if=\"fillBedInfo\" title=\"床位信息\" :value=\"detail.bedInfo || ''\"></van-cell>\n",
|
||||
" <van-cell v-if=\"fillBedInfo\" title=\"意向拼床人\" :value=\"detail.intendedRoommate || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"携带家属\" :value=\"familyText()\"></van-cell>\n",
|
||||
" <van-cell title=\"报销超出费用\" :value=\"detail.overCostReimbursed ? '是' : '否'\"></van-cell>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <div v-if=\"isDirectFamilyLine()\" class=\"tour-section\">\n",
|
||||
" <div class=\"tour-section-title\">直系亲属线路</div>\n",
|
||||
" <van-cell title=\"亲属姓名\" :value=\"directRelative.relativeName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"所在单位\" :value=\"directRelative.unitName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"亲属关系\" :value=\"directRelative.relationshipName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"线路名称\" :value=\"directRelative.lineName || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"出行开始\" :value=\"directRelative.travelStartTime || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"出行结束\" :value=\"directRelative.travelEndTime || ''\"></van-cell>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <div v-if=\"showFamilySection()\" class=\"tour-section\">\n",
|
||||
" <div class=\"tour-section-title\">家属信息</div>\n",
|
||||
" <template v-for=\"(item,index) in familyData\">\n",
|
||||
" <van-cell :key=\"'title_' + index\" :title=\"'家属' + (index + 1)\"></van-cell>\n",
|
||||
" <van-cell :key=\"'name_' + index\" title=\"姓名\" :value=\"item.familyName || ''\"></van-cell>\n",
|
||||
" <van-cell :key=\"'gender_' + index\" title=\"性别\" :value=\"item.gender || ''\"></van-cell>\n",
|
||||
" <van-cell :key=\"'id_' + index\" title=\"身份证号\" :value=\"item.idCard || ''\"></van-cell>\n",
|
||||
" <van-cell :key=\"'rel_' + index\" title=\"关系\" :value=\"item.relationship || ''\"></van-cell>\n",
|
||||
" <van-cell v-if=\"fillBedInfo\" :key=\"'bed_' + index\" title=\"床型\" :value=\"item.bedType || ''\"></van-cell>\n",
|
||||
" </template>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <div v-if=\"doneTasks.length > 0\" class=\"tour-section\">\n",
|
||||
" <div class=\"tour-section-title\">流程记录</div>\n",
|
||||
" <template v-for=\"task in doneTasks\">\n",
|
||||
" <van-cell-group :key=\"task.id\" :title=\"task.displayName || task.taskName\">\n",
|
||||
" <van-cell title=\"办理时间\" :value=\"task.finishTime || ''\"></van-cell>\n",
|
||||
" <van-cell title=\"办理结果\">\n",
|
||||
" <dict-tag :options=\"dict.type.PROCESS_TASK_SUBMIT_TYPE\" :value=\"task.ext && task.ext.submitType\"></dict-tag>\n",
|
||||
" </van-cell>\n",
|
||||
" <van-cell title=\"办理意见\" v-if=\"task.taskFormData\" class=\"direction-column-cell\">\n",
|
||||
" <div class=\"tour-process-opinion\">{{ task.taskFormData.opinion || task.taskFormData.tf_opinion || '' }}</div>\n",
|
||||
" </van-cell>\n",
|
||||
" </van-cell-group>\n",
|
||||
" </template>\n",
|
||||
" </div>\n",
|
||||
"\n",
|
||||
" <slot></slot>\n",
|
||||
" </div>\n",
|
||||
" </van-action-sheet>\n",
|
||||
" \n"
|
||||
].join(""),
|
||||
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
row: {},
|
||||
detail: {},
|
||||
familyData: [],
|
||||
directRelative: {},
|
||||
allowFamily: false,
|
||||
fillBedInfo: true,
|
||||
directFamilyUnitLine: false,
|
||||
doneTasks: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onOpen(row) {
|
||||
this.row = row || {}
|
||||
this.visible = true
|
||||
this.detail = {}
|
||||
this.familyData = []
|
||||
this.directRelative = {}
|
||||
this.allowFamily = false
|
||||
this.fillBedInfo = true
|
||||
this.directFamilyUnitLine = false
|
||||
this.doneTasks = []
|
||||
this.info()
|
||||
this.getDoneTasks()
|
||||
},
|
||||
onClose() {
|
||||
this.visible = false
|
||||
},
|
||||
info() {
|
||||
this.$axios.post("/platform/tour/unionApproval/detail", { id: this.row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const data = res.data || {}
|
||||
this.detail = data.ledger || {}
|
||||
this.detail.travelPeriod = data.travelPeriod || this.row.travelPeriod || ""
|
||||
this.familyData = data.families || []
|
||||
this.directRelative = data.directRelative || {}
|
||||
this.allowFamily = this.toBoolean(data.allowFamily)
|
||||
this.fillBedInfo = data.fillBedInfo === undefined || data.fillBedInfo === null || this.toBoolean(data.fillBedInfo)
|
||||
this.directFamilyUnitLine = this.toBoolean(data.directFamilyUnitLine)
|
||||
} else {
|
||||
vant.Toast(res.msg || "查询失败")
|
||||
}
|
||||
})
|
||||
},
|
||||
getDoneTasks() {
|
||||
this.$axios.post("/flow/common/doneTasks", { bizId: this.row.id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.doneTasks = res.data || []
|
||||
}
|
||||
})
|
||||
},
|
||||
toBoolean(value) {
|
||||
return value === true || value === 1 || value === "1" || value === "true" || value === "TRUE"
|
||||
},
|
||||
isDirectFamilyLine() {
|
||||
return this.directFamilyUnitLine || this.toBoolean(this.detail.directFamilyUnitLine) || !!(this.directRelative && this.directRelative.id)
|
||||
},
|
||||
hasFamily() {
|
||||
return this.toBoolean(this.detail.hasFamily) || this.familyData.length > 0
|
||||
},
|
||||
showFamilySection() {
|
||||
return this.allowFamily && this.hasFamily() && !this.isDirectFamilyLine()
|
||||
},
|
||||
familyText() {
|
||||
if (this.isDirectFamilyLine() || !this.allowFamily) {
|
||||
return "否"
|
||||
}
|
||||
return this.hasFamily() ? "是" : "否"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
components: {
|
||||
"tour-info": TOUR_INFO
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
pageOrderName: "signupTime",
|
||||
pageOrderBy: "descending",
|
||||
audit: false,
|
||||
keyword: "",
|
||||
lineType: ""
|
||||
},
|
||||
auditOptions: [
|
||||
{ text: "未审核", value: false },
|
||||
{ text: "已审核", value: true }
|
||||
],
|
||||
lineTypeOptions: [
|
||||
{ text: "全部线路类型", value: "" }
|
||||
],
|
||||
formData: {},
|
||||
showApprovalForm: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
historyBack,
|
||||
onReady() {
|
||||
this.doSearch()
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(async () => {
|
||||
await this.loadLineTypeOptions()
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
},
|
||||
loadLineTypeOptions() {
|
||||
return this.$axios.post("/platform/tour/unionApproval/lineTypeOptions", {
|
||||
audit: this.pageForm.audit,
|
||||
keyword: this.pageForm.keyword
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const options = (res.data || []).map(item => ({
|
||||
text: item.lineType,
|
||||
value: item.lineType
|
||||
})).filter(item => item.value)
|
||||
this.lineTypeOptions = [{ text: "全部线路类型", value: "" }].concat(options)
|
||||
if (this.pageForm.lineType && !this.lineTypeOptions.some(item => item.value === this.pageForm.lineType)) {
|
||||
this.pageForm.lineType = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
},
|
||||
onApproval(row) {
|
||||
this.showApprovalForm = true
|
||||
this.formData = {
|
||||
processTaskId: row.taskId,
|
||||
taskName: row.curTaskName || row.taskName,
|
||||
tf_opinion: ""
|
||||
}
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
},
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate()
|
||||
} catch (e) {
|
||||
return
|
||||
}
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
const loading = this.$toast.loading({
|
||||
message: "加载中...",
|
||||
forbidClick: true,
|
||||
overlay: true,
|
||||
duration: 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()
|
||||
} else {
|
||||
this.$toast(res.msg || "操作失败")
|
||||
}
|
||||
}).finally(() => {
|
||||
loading.close()
|
||||
})
|
||||
}).catch(() => {})
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
Reference in New Issue
Block a user