Commit 0bf7e6a57b454586fc1c8153599d30ea63c7f30b
1 parent
2ca25ccd
加入问卷功能代码
Showing
42 changed files
with
5405 additions
and
6 deletions
src/api/community/communityApi.js
| @@ -57,6 +57,18 @@ export function getCommunityId() { | @@ -57,6 +57,18 @@ export function getCommunityId() { | ||
| 57 | return getCurrentCommunity().communityId | 57 | return getCurrentCommunity().communityId |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | +/************* ✨ Windsurf Command ⭐ *************/ | ||
| 61 | +/** | ||
| 62 | + * Get the current community | ||
| 63 | + * @returns {Object} The current community object | ||
| 64 | + */ | ||
| 65 | +/******* 8c78c7d7-a438-4630-a8c7-b05b9f491159 *******/ | ||
| 66 | + | ||
| 67 | + | ||
| 68 | +export function getCommunity() { | ||
| 69 | + return getCurrentCommunity() | ||
| 70 | +} | ||
| 71 | + | ||
| 60 | 72 | ||
| 61 | 73 | ||
| 62 | export function getCommunityName() { | 74 | export function getCommunityName() { |
src/api/oa/addQuestionAnswerApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | ||
| 2 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 3 | + | ||
| 4 | +// 查询楼栋和单元信息 | ||
| 5 | +export function queryFloorAndUnits(params) { | ||
| 6 | + return new Promise((resolve, reject) => { | ||
| 7 | + request({ | ||
| 8 | + url: '/floor.queryFloorAndUnits', | ||
| 9 | + method: 'get', | ||
| 10 | + params: { | ||
| 11 | + ...params, | ||
| 12 | + communityId: params.communityId || getCommunityId() | ||
| 13 | + } | ||
| 14 | + }).then(response => { | ||
| 15 | + resolve(response.data) | ||
| 16 | + }).catch(error => { | ||
| 17 | + reject(error) | ||
| 18 | + }) | ||
| 19 | + }) | ||
| 20 | +} | ||
| 21 | + | ||
| 22 | +// 查询房屋信息 | ||
| 23 | +export function queryRooms(params) { | ||
| 24 | + return new Promise((resolve, reject) => { | ||
| 25 | + request({ | ||
| 26 | + url: '/room.queryRooms', | ||
| 27 | + method: 'get', | ||
| 28 | + params: { | ||
| 29 | + ...params, | ||
| 30 | + communityId: params.communityId || getCommunityId() | ||
| 31 | + } | ||
| 32 | + }).then(response => { | ||
| 33 | + resolve(response.data) | ||
| 34 | + }).catch(error => { | ||
| 35 | + reject(error) | ||
| 36 | + }) | ||
| 37 | + }) | ||
| 38 | +} | ||
| 39 | + | ||
| 40 | +// 查询题目列表 | ||
| 41 | +export function listQuestionTitle(params) { | ||
| 42 | + return new Promise((resolve, reject) => { | ||
| 43 | + request({ | ||
| 44 | + url: '/question.listQuestionTitle', | ||
| 45 | + method: 'get', | ||
| 46 | + params: { | ||
| 47 | + ...params, | ||
| 48 | + communityId: params.communityId || getCommunityId() | ||
| 49 | + } | ||
| 50 | + }).then(response => { | ||
| 51 | + resolve(response.data) | ||
| 52 | + }).catch(error => { | ||
| 53 | + reject(error) | ||
| 54 | + }) | ||
| 55 | + }) | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +// 保存问卷 | ||
| 59 | +export function saveQuestionAnswer(data) { | ||
| 60 | + return new Promise((resolve, reject) => { | ||
| 61 | + request({ | ||
| 62 | + url: '/question.saveQuestionAnswer', | ||
| 63 | + method: 'post', | ||
| 64 | + data: { | ||
| 65 | + ...data, | ||
| 66 | + communityId: data.communityId || getCommunityId() | ||
| 67 | + } | ||
| 68 | + }).then(response => { | ||
| 69 | + resolve(response.data) | ||
| 70 | + }).catch(error => { | ||
| 71 | + reject(error) | ||
| 72 | + }) | ||
| 73 | + }) | ||
| 74 | +} | ||
| 0 | \ No newline at end of file | 75 | \ No newline at end of file |
src/api/oa/editQuestionAnswerApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | ||
| 2 | + | ||
| 3 | +// 查询问卷信息 | ||
| 4 | +export function listQuestionAnswer(params) { | ||
| 5 | + return new Promise((resolve, reject) => { | ||
| 6 | + request({ | ||
| 7 | + url: '/question.listQuestionAnswer', | ||
| 8 | + method: 'get', | ||
| 9 | + params | ||
| 10 | + }).then(response => { | ||
| 11 | + const res = response.data | ||
| 12 | + resolve(res) | ||
| 13 | + }).catch(error => { | ||
| 14 | + reject(error) | ||
| 15 | + }) | ||
| 16 | + }) | ||
| 17 | +} | ||
| 18 | + | ||
| 19 | +// 更新问卷信息 | ||
| 20 | +export function updateQuestionAnswer(data) { | ||
| 21 | + return new Promise((resolve, reject) => { | ||
| 22 | + request({ | ||
| 23 | + url: '/question.updateQuestionAnswer', | ||
| 24 | + method: 'post', | ||
| 25 | + data | ||
| 26 | + }).then(response => { | ||
| 27 | + const res = response.data | ||
| 28 | + resolve(res) | ||
| 29 | + }).catch(error => { | ||
| 30 | + reject(error) | ||
| 31 | + }) | ||
| 32 | + }) | ||
| 33 | +} | ||
| 34 | + | ||
| 35 | +// 查询题目列表 | ||
| 36 | +export function listQuestionTitle(params) { | ||
| 37 | + return new Promise((resolve, reject) => { | ||
| 38 | + request({ | ||
| 39 | + url: '/question.listQuestionTitle', | ||
| 40 | + method: 'get', | ||
| 41 | + params | ||
| 42 | + }).then(response => { | ||
| 43 | + const res = response.data | ||
| 44 | + resolve(res) | ||
| 45 | + }).catch(error => { | ||
| 46 | + reject(error) | ||
| 47 | + }) | ||
| 48 | + }) | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +// 查询楼栋和单元信息 | ||
| 52 | +export function queryFloorAndUnits(params) { | ||
| 53 | + return new Promise((resolve, reject) => { | ||
| 54 | + request({ | ||
| 55 | + url: '/floor.queryFloorAndUnits', | ||
| 56 | + method: 'get', | ||
| 57 | + params | ||
| 58 | + }).then(response => { | ||
| 59 | + const res = response.data | ||
| 60 | + resolve(res) | ||
| 61 | + }).catch(error => { | ||
| 62 | + reject(error) | ||
| 63 | + }) | ||
| 64 | + }) | ||
| 65 | +} | ||
| 66 | + | ||
| 67 | +// 查询房屋信息 | ||
| 68 | +export function queryRooms(params) { | ||
| 69 | + return new Promise((resolve, reject) => { | ||
| 70 | + request({ | ||
| 71 | + url: '/room.queryRooms', | ||
| 72 | + method: 'get', | ||
| 73 | + params | ||
| 74 | + }).then(response => { | ||
| 75 | + const res = response.data | ||
| 76 | + resolve(res) | ||
| 77 | + }).catch(error => { | ||
| 78 | + reject(error) | ||
| 79 | + }) | ||
| 80 | + }) | ||
| 81 | +} | ||
| 0 | \ No newline at end of file | 82 | \ No newline at end of file |
src/api/oa/notepadManageApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | ||
| 2 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 3 | + | ||
| 4 | +// 获取记事本列表 | ||
| 5 | +export function listNotepad(params) { | ||
| 6 | + return new Promise((resolve, reject) => { | ||
| 7 | + request({ | ||
| 8 | + url: '/notepad.listNotepad', | ||
| 9 | + method: 'get', | ||
| 10 | + params: { | ||
| 11 | + ...params, | ||
| 12 | + communityId: getCommunityId() | ||
| 13 | + } | ||
| 14 | + }).then(response => { | ||
| 15 | + const res = response.data | ||
| 16 | + resolve({ | ||
| 17 | + data: res.data, | ||
| 18 | + total: res.total | ||
| 19 | + }) | ||
| 20 | + }).catch(error => { | ||
| 21 | + reject(error) | ||
| 22 | + }) | ||
| 23 | + }) | ||
| 24 | +} | ||
| 25 | + | ||
| 26 | +// 更新记事本 | ||
| 27 | +export function updateNotepad(data) { | ||
| 28 | + return new Promise((resolve, reject) => { | ||
| 29 | + request({ | ||
| 30 | + url: '/notepad.updateNotepad', | ||
| 31 | + method: 'post', | ||
| 32 | + data: { | ||
| 33 | + ...data, | ||
| 34 | + communityId: getCommunityId() | ||
| 35 | + } | ||
| 36 | + }).then(response => { | ||
| 37 | + const res = response.data | ||
| 38 | + resolve(res) | ||
| 39 | + }).catch(error => { | ||
| 40 | + reject(error) | ||
| 41 | + }) | ||
| 42 | + }) | ||
| 43 | +} | ||
| 44 | + | ||
| 45 | +// 删除记事本 | ||
| 46 | +export function deleteNotepad(data) { | ||
| 47 | + return new Promise((resolve, reject) => { | ||
| 48 | + request({ | ||
| 49 | + url: '/notepad.deleteNotepad', | ||
| 50 | + method: 'post', | ||
| 51 | + data: { | ||
| 52 | + ...data, | ||
| 53 | + communityId: getCommunityId() | ||
| 54 | + } | ||
| 55 | + }).then(response => { | ||
| 56 | + const res = response.data | ||
| 57 | + resolve(res) | ||
| 58 | + }).catch(error => { | ||
| 59 | + reject(error) | ||
| 60 | + }) | ||
| 61 | + }) | ||
| 62 | +} | ||
| 63 | + | ||
| 64 | +// 保存记事本详情 | ||
| 65 | +export function saveNotepadDetail(data) { | ||
| 66 | + return new Promise((resolve, reject) => { | ||
| 67 | + request({ | ||
| 68 | + url: '/notepad.saveNotepadDetail', | ||
| 69 | + method: 'post', | ||
| 70 | + data: { | ||
| 71 | + ...data, | ||
| 72 | + communityId: getCommunityId() | ||
| 73 | + } | ||
| 74 | + }).then(response => { | ||
| 75 | + const res = response.data | ||
| 76 | + resolve(res) | ||
| 77 | + }).catch(error => { | ||
| 78 | + reject(error) | ||
| 79 | + }) | ||
| 80 | + }) | ||
| 81 | +} | ||
| 82 | + | ||
| 83 | +// 获取记事本详情列表 | ||
| 84 | +export function listNotepadDetail(params) { | ||
| 85 | + return new Promise((resolve, reject) => { | ||
| 86 | + request({ | ||
| 87 | + url: '/notepad.listNotepadDetail', | ||
| 88 | + method: 'get', | ||
| 89 | + params: { | ||
| 90 | + ...params, | ||
| 91 | + communityId: getCommunityId() | ||
| 92 | + } | ||
| 93 | + }).then(response => { | ||
| 94 | + const res = response.data | ||
| 95 | + resolve({ | ||
| 96 | + data: res.data, | ||
| 97 | + total: res.total | ||
| 98 | + }) | ||
| 99 | + }).catch(error => { | ||
| 100 | + reject(error) | ||
| 101 | + }) | ||
| 102 | + }) | ||
| 103 | +} | ||
| 104 | + | ||
| 105 | +// 删除记事本详情 | ||
| 106 | +export function deleteNotepadDetail(data) { | ||
| 107 | + return new Promise((resolve, reject) => { | ||
| 108 | + request({ | ||
| 109 | + url: '/notepad.deleteNotepadDetail', | ||
| 110 | + method: 'post', | ||
| 111 | + data: { | ||
| 112 | + ...data, | ||
| 113 | + communityId: getCommunityId() | ||
| 114 | + } | ||
| 115 | + }).then(response => { | ||
| 116 | + const res = response.data | ||
| 117 | + resolve(res) | ||
| 118 | + }).catch(error => { | ||
| 119 | + reject(error) | ||
| 120 | + }) | ||
| 121 | + }) | ||
| 122 | +} | ||
| 123 | + | ||
| 124 | +// 保存业主报修信息 | ||
| 125 | +export function saveOwnerRepair(data) { | ||
| 126 | + return new Promise((resolve, reject) => { | ||
| 127 | + request({ | ||
| 128 | + url: '/ownerRepair.saveOwnerRepair', | ||
| 129 | + method: 'post', | ||
| 130 | + data: { | ||
| 131 | + ...data, | ||
| 132 | + communityId: getCommunityId() | ||
| 133 | + } | ||
| 134 | + }).then(response => { | ||
| 135 | + const res = response.data | ||
| 136 | + resolve(res) | ||
| 137 | + }).catch(error => { | ||
| 138 | + reject(error) | ||
| 139 | + }) | ||
| 140 | + }) | ||
| 141 | +} | ||
| 142 | + | ||
| 143 | +// 获取报修设置列表 | ||
| 144 | +export function listRepairSettings(params) { | ||
| 145 | + return new Promise((resolve, reject) => { | ||
| 146 | + request({ | ||
| 147 | + url: '/repair.listRepairSettings', | ||
| 148 | + method: 'get', | ||
| 149 | + params: { | ||
| 150 | + ...params, | ||
| 151 | + communityId: getCommunityId() | ||
| 152 | + } | ||
| 153 | + }).then(response => { | ||
| 154 | + const res = response.data | ||
| 155 | + resolve({ | ||
| 156 | + data: res.data, | ||
| 157 | + total: res.total | ||
| 158 | + }) | ||
| 159 | + }).catch(error => { | ||
| 160 | + reject(error) | ||
| 161 | + }) | ||
| 162 | + }) | ||
| 163 | +} | ||
| 0 | \ No newline at end of file | 164 | \ No newline at end of file |
src/api/oa/printQuestionAnswerApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | ||
| 2 | + | ||
| 3 | +// 获取问题答案列表 | ||
| 4 | +export function listQuestionAnswer(params) { | ||
| 5 | + return new Promise((resolve, reject) => { | ||
| 6 | + request({ | ||
| 7 | + url: '/question.listQuestionAnswer', | ||
| 8 | + method: 'get', | ||
| 9 | + params | ||
| 10 | + }).then(response => { | ||
| 11 | + const res = response.data | ||
| 12 | + resolve(res) | ||
| 13 | + }).catch(error => { | ||
| 14 | + reject(error) | ||
| 15 | + }) | ||
| 16 | + }) | ||
| 17 | +} | ||
| 18 | + | ||
| 19 | +// 获取问题标题列表 | ||
| 20 | +export function listQuestionTitle(params) { | ||
| 21 | + return new Promise((resolve, reject) => { | ||
| 22 | + request({ | ||
| 23 | + url: '/question.listQuestionTitle', | ||
| 24 | + method: 'get', | ||
| 25 | + params | ||
| 26 | + }).then(response => { | ||
| 27 | + const res = response.data | ||
| 28 | + resolve(res) | ||
| 29 | + }).catch(error => { | ||
| 30 | + reject(error) | ||
| 31 | + }) | ||
| 32 | + }) | ||
| 33 | +} | ||
| 0 | \ No newline at end of file | 34 | \ No newline at end of file |
src/api/oa/printQuestionAnswerDetailApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | ||
| 2 | + | ||
| 3 | +// 获取问题回答列表 | ||
| 4 | +export function listQuestionAnswer(params) { | ||
| 5 | + return new Promise((resolve, reject) => { | ||
| 6 | + request({ | ||
| 7 | + url: '/question.listQuestionAnswer', | ||
| 8 | + method: 'get', | ||
| 9 | + params | ||
| 10 | + }).then(response => { | ||
| 11 | + const res = response.data | ||
| 12 | + resolve(res) | ||
| 13 | + }).catch(error => { | ||
| 14 | + reject(error) | ||
| 15 | + }) | ||
| 16 | + }) | ||
| 17 | +} | ||
| 18 | + | ||
| 19 | +// 获取问题标题列表 | ||
| 20 | +export function listQuestionTitle(params) { | ||
| 21 | + return new Promise((resolve, reject) => { | ||
| 22 | + request({ | ||
| 23 | + url: '/question.listQuestionTitle', | ||
| 24 | + method: 'get', | ||
| 25 | + params | ||
| 26 | + }).then(response => { | ||
| 27 | + const res = response.data | ||
| 28 | + resolve(res) | ||
| 29 | + }).catch(error => { | ||
| 30 | + reject(error) | ||
| 31 | + }) | ||
| 32 | + }) | ||
| 33 | +} | ||
| 34 | + | ||
| 35 | +// 获取用户问题回答列表 | ||
| 36 | +export function listUserQuestionAnswer(params) { | ||
| 37 | + return new Promise((resolve, reject) => { | ||
| 38 | + request({ | ||
| 39 | + url: '/question.listUserQuestionAnswer', | ||
| 40 | + method: 'get', | ||
| 41 | + params | ||
| 42 | + }).then(response => { | ||
| 43 | + const res = response.data | ||
| 44 | + resolve(res) | ||
| 45 | + }).catch(error => { | ||
| 46 | + reject(error) | ||
| 47 | + }) | ||
| 48 | + }) | ||
| 49 | +} | ||
| 0 | \ No newline at end of file | 50 | \ No newline at end of file |
src/api/oa/questionAnswerManageApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | ||
| 2 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 3 | + | ||
| 4 | +// 获取问卷列表 | ||
| 5 | +export function listQuestionAnswer(params) { | ||
| 6 | + return new Promise((resolve, reject) => { | ||
| 7 | + request({ | ||
| 8 | + url: '/question.listQuestionAnswer', | ||
| 9 | + method: 'get', | ||
| 10 | + params: { | ||
| 11 | + ...params, | ||
| 12 | + communityId: getCommunityId() | ||
| 13 | + } | ||
| 14 | + }).then(response => { | ||
| 15 | + const res = response.data | ||
| 16 | + resolve(res) | ||
| 17 | + }).catch(error => { | ||
| 18 | + reject(error) | ||
| 19 | + }) | ||
| 20 | + }) | ||
| 21 | +} | ||
| 22 | + | ||
| 23 | +// 更新问卷信息 | ||
| 24 | +export function updateQuestionAnswer(data) { | ||
| 25 | + return new Promise((resolve, reject) => { | ||
| 26 | + request({ | ||
| 27 | + url: '/questionAnswer.updateQuestionAnswer', | ||
| 28 | + method: 'post', | ||
| 29 | + data: { | ||
| 30 | + ...data, | ||
| 31 | + communityId: getCommunityId() | ||
| 32 | + } | ||
| 33 | + }).then(response => { | ||
| 34 | + const res = response.data | ||
| 35 | + resolve(res) | ||
| 36 | + }).catch(error => { | ||
| 37 | + reject(error) | ||
| 38 | + }) | ||
| 39 | + }) | ||
| 40 | +} | ||
| 41 | + | ||
| 42 | +// 删除问卷 | ||
| 43 | +export function deleteQuestionAnswer(params) { | ||
| 44 | + return new Promise((resolve, reject) => { | ||
| 45 | + request({ | ||
| 46 | + url: '/question.deleteQuestionAnswer', | ||
| 47 | + method: 'post', | ||
| 48 | + data: { | ||
| 49 | + ...params, | ||
| 50 | + communityId: getCommunityId() | ||
| 51 | + } | ||
| 52 | + }).then(response => { | ||
| 53 | + const res = response.data | ||
| 54 | + resolve(res) | ||
| 55 | + }).catch(error => { | ||
| 56 | + reject(error) | ||
| 57 | + }) | ||
| 58 | + }) | ||
| 59 | +} | ||
| 60 | + | ||
| 61 | +// 发布问卷 | ||
| 62 | +export function publishQuestionAnswer(data) { | ||
| 63 | + return new Promise((resolve, reject) => { | ||
| 64 | + request({ | ||
| 65 | + url: '/question.publishQuestion', | ||
| 66 | + method: 'post', | ||
| 67 | + data: { | ||
| 68 | + ...data, | ||
| 69 | + communityId: getCommunityId() | ||
| 70 | + } | ||
| 71 | + }).then(response => { | ||
| 72 | + const res = response.data | ||
| 73 | + resolve(res) | ||
| 74 | + }).catch(error => { | ||
| 75 | + reject(error) | ||
| 76 | + }) | ||
| 77 | + }) | ||
| 78 | +} | ||
| 79 | + | ||
| 80 | +// 上传图片 | ||
| 81 | +export function uploadImage(data) { | ||
| 82 | + return new Promise((resolve, reject) => { | ||
| 83 | + request({ | ||
| 84 | + url: '/uploadImage', | ||
| 85 | + method: 'post', | ||
| 86 | + headers: { | ||
| 87 | + 'Content-Type': 'multipart/form-data' | ||
| 88 | + }, | ||
| 89 | + data | ||
| 90 | + }).then(response => { | ||
| 91 | + const res = response.data | ||
| 92 | + resolve(res) | ||
| 93 | + }).catch(error => { | ||
| 94 | + reject(error) | ||
| 95 | + }) | ||
| 96 | + }) | ||
| 97 | +} | ||
| 0 | \ No newline at end of file | 98 | \ No newline at end of file |
src/api/oa/questionTitleApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | ||
| 2 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 3 | + | ||
| 4 | +// 获取题目列表 | ||
| 5 | +export function listQuestionTitle(params) { | ||
| 6 | + return new Promise((resolve, reject) => { | ||
| 7 | + const communityId = getCommunityId() | ||
| 8 | + request({ | ||
| 9 | + url: '/question.listQuestionTitle', | ||
| 10 | + method: 'get', | ||
| 11 | + params: { | ||
| 12 | + ...params, | ||
| 13 | + communityId | ||
| 14 | + } | ||
| 15 | + }).then(response => { | ||
| 16 | + const res = response.data | ||
| 17 | + resolve(res) | ||
| 18 | + }).catch(error => { | ||
| 19 | + reject(error) | ||
| 20 | + }) | ||
| 21 | + }) | ||
| 22 | +} | ||
| 23 | + | ||
| 24 | +// 添加题目 | ||
| 25 | +export function saveQuestionTitle(data) { | ||
| 26 | + return new Promise((resolve, reject) => { | ||
| 27 | + const communityId = getCommunityId() | ||
| 28 | + request({ | ||
| 29 | + url: '/question.saveQuestionTitle', | ||
| 30 | + method: 'post', | ||
| 31 | + data: { | ||
| 32 | + ...data, | ||
| 33 | + communityId | ||
| 34 | + } | ||
| 35 | + }).then(response => { | ||
| 36 | + const res = response.data | ||
| 37 | + resolve(res) | ||
| 38 | + }).catch(error => { | ||
| 39 | + reject(error) | ||
| 40 | + }) | ||
| 41 | + }) | ||
| 42 | +} | ||
| 43 | + | ||
| 44 | +// 更新题目 | ||
| 45 | +export function updateQuestionTitle(data) { | ||
| 46 | + return new Promise((resolve, reject) => { | ||
| 47 | + const communityId = getCommunityId() | ||
| 48 | + request({ | ||
| 49 | + url: '/question.updateQuestionTitle', | ||
| 50 | + method: 'post', | ||
| 51 | + data: { | ||
| 52 | + ...data, | ||
| 53 | + communityId | ||
| 54 | + } | ||
| 55 | + }).then(response => { | ||
| 56 | + const res = response.data | ||
| 57 | + resolve(res) | ||
| 58 | + }).catch(error => { | ||
| 59 | + reject(error) | ||
| 60 | + }) | ||
| 61 | + }) | ||
| 62 | +} | ||
| 63 | + | ||
| 64 | +// 删除题目 | ||
| 65 | +export function deleteQuestionTitle(data) { | ||
| 66 | + return new Promise((resolve, reject) => { | ||
| 67 | + const communityId = getCommunityId() | ||
| 68 | + request({ | ||
| 69 | + url: '/question.deleteQuestionTitle', | ||
| 70 | + method: 'post', | ||
| 71 | + data: { | ||
| 72 | + ...data, | ||
| 73 | + communityId | ||
| 74 | + } | ||
| 75 | + }).then(response => { | ||
| 76 | + const res = response.data | ||
| 77 | + resolve(res) | ||
| 78 | + }).catch(error => { | ||
| 79 | + reject(error) | ||
| 80 | + }) | ||
| 81 | + }) | ||
| 82 | +} | ||
| 0 | \ No newline at end of file | 83 | \ No newline at end of file |
src/api/oa/visitManageApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | ||
| 2 | + | ||
| 3 | +// 获取访客列表 | ||
| 4 | +export function listVisits(params) { | ||
| 5 | + return new Promise((resolve, reject) => { | ||
| 6 | + request({ | ||
| 7 | + url: '/iot.getOpenApi', | ||
| 8 | + method: 'get', | ||
| 9 | + params: { | ||
| 10 | + ...params, | ||
| 11 | + iotApiCode: 'listVisitBmoImpl' | ||
| 12 | + } | ||
| 13 | + }).then(response => { | ||
| 14 | + const res = response.data | ||
| 15 | + resolve({ | ||
| 16 | + data: res.data, | ||
| 17 | + total: res.total | ||
| 18 | + }) | ||
| 19 | + }).catch(error => { | ||
| 20 | + reject(error) | ||
| 21 | + }) | ||
| 22 | + }) | ||
| 23 | +} | ||
| 24 | + | ||
| 25 | +// 获取访客类型列表 | ||
| 26 | +export function listVisitTypes(params) { | ||
| 27 | + return new Promise((resolve, reject) => { | ||
| 28 | + request({ | ||
| 29 | + url: '/iot.getOpenApi', | ||
| 30 | + method: 'get', | ||
| 31 | + params: { | ||
| 32 | + ...params, | ||
| 33 | + iotApiCode: 'listVisitTypeBmoImpl' | ||
| 34 | + } | ||
| 35 | + }).then(response => { | ||
| 36 | + const res = response.data | ||
| 37 | + resolve({ | ||
| 38 | + data: res.data, | ||
| 39 | + total: res.total | ||
| 40 | + }) | ||
| 41 | + }).catch(error => { | ||
| 42 | + reject(error) | ||
| 43 | + }) | ||
| 44 | + }) | ||
| 45 | +} | ||
| 0 | \ No newline at end of file | 46 | \ No newline at end of file |
src/components/oa/addNotepadDetail.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog | ||
| 3 | + :title="$t('notepadManage.addDetail.title')" | ||
| 4 | + :visible.sync="visible" | ||
| 5 | + width="50%" | ||
| 6 | + @close="handleClose" | ||
| 7 | + > | ||
| 8 | + <el-form | ||
| 9 | + ref="form" | ||
| 10 | + :model="formData" | ||
| 11 | + :rules="rules" | ||
| 12 | + label-width="120px" | ||
| 13 | + > | ||
| 14 | + <el-form-item | ||
| 15 | + :label="$t('notepadManage.addDetail.state')" | ||
| 16 | + prop="state" | ||
| 17 | + > | ||
| 18 | + <el-select | ||
| 19 | + v-model="formData.state" | ||
| 20 | + style="width:100%" | ||
| 21 | + > | ||
| 22 | + <el-option | ||
| 23 | + :label="$t('notepadManage.addDetail.selectState')" | ||
| 24 | + disabled | ||
| 25 | + value="" | ||
| 26 | + /> | ||
| 27 | + <el-option | ||
| 28 | + :label="$t('notepadManage.state.following')" | ||
| 29 | + value="W" | ||
| 30 | + /> | ||
| 31 | + <el-option | ||
| 32 | + :label="$t('notepadManage.state.completed')" | ||
| 33 | + value="F" | ||
| 34 | + /> | ||
| 35 | + </el-select> | ||
| 36 | + </el-form-item> | ||
| 37 | + <el-form-item | ||
| 38 | + :label="$t('notepadManage.addDetail.content')" | ||
| 39 | + prop="content" | ||
| 40 | + > | ||
| 41 | + <el-input | ||
| 42 | + v-model="formData.content" | ||
| 43 | + type="textarea" | ||
| 44 | + rows="5" | ||
| 45 | + :placeholder="$t('notepadManage.addDetail.contentPlaceholder')" | ||
| 46 | + /> | ||
| 47 | + </el-form-item> | ||
| 48 | + </el-form> | ||
| 49 | + <span slot="footer" class="dialog-footer"> | ||
| 50 | + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button> | ||
| 51 | + <el-button type="primary" @click="handleSubmit">{{ $t('common.save') }}</el-button> | ||
| 52 | + </span> | ||
| 53 | + </el-dialog> | ||
| 54 | +</template> | ||
| 55 | + | ||
| 56 | +<script> | ||
| 57 | +import { saveNotepadDetail } from '@/api/oa/notepadManageApi' | ||
| 58 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 59 | + | ||
| 60 | +export default { | ||
| 61 | + name: 'AddNotepadDetail', | ||
| 62 | + props: { | ||
| 63 | + callBackListener: { | ||
| 64 | + type: String, | ||
| 65 | + default: '' | ||
| 66 | + }, | ||
| 67 | + callBackFunction: { | ||
| 68 | + type: String, | ||
| 69 | + default: '' | ||
| 70 | + } | ||
| 71 | + }, | ||
| 72 | + data() { | ||
| 73 | + return { | ||
| 74 | + visible: false, | ||
| 75 | + formData: { | ||
| 76 | + noteId: '', | ||
| 77 | + content: '', | ||
| 78 | + state: 'W', | ||
| 79 | + communityId: '' | ||
| 80 | + }, | ||
| 81 | + rules: { | ||
| 82 | + state: [ | ||
| 83 | + { required: true, message: this.$t('notepadManage.validate.state'), trigger: 'blur' } | ||
| 84 | + ], | ||
| 85 | + content: [ | ||
| 86 | + { required: true, message: this.$t('notepadManage.validate.content'), trigger: 'blur' } | ||
| 87 | + ] | ||
| 88 | + } | ||
| 89 | + } | ||
| 90 | + }, | ||
| 91 | + methods: { | ||
| 92 | + open(data) { | ||
| 93 | + this.visible = true | ||
| 94 | + this.formData.noteId = data.noteId | ||
| 95 | + this.formData.communityId = getCommunityId() | ||
| 96 | + }, | ||
| 97 | + async handleSubmit() { | ||
| 98 | + this.$refs.form.validate(async valid => { | ||
| 99 | + if (valid) { | ||
| 100 | + try { | ||
| 101 | + await saveNotepadDetail(this.formData) | ||
| 102 | + this.$message.success(this.$t('common.saveSuccess')) | ||
| 103 | + this.visible = false | ||
| 104 | + this.$emit('success') | ||
| 105 | + } catch (error) { | ||
| 106 | + console.error('保存记事本详情失败:', error) | ||
| 107 | + } | ||
| 108 | + } | ||
| 109 | + }) | ||
| 110 | + }, | ||
| 111 | + handleClose() { | ||
| 112 | + this.$refs.form.resetFields() | ||
| 113 | + this.formData = { | ||
| 114 | + noteId: '', | ||
| 115 | + content: '', | ||
| 116 | + state: 'W', | ||
| 117 | + communityId: '' | ||
| 118 | + } | ||
| 119 | + } | ||
| 120 | + } | ||
| 121 | +} | ||
| 122 | +</script> | ||
| 0 | \ No newline at end of file | 123 | \ No newline at end of file |
src/components/oa/addQuestionTitle.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog :title="$t('questionTitle.add.title')" :visible.sync="visible" width="70%" @close="handleClose"> | ||
| 3 | + <el-form ref="form" :model="formData" label-width="120px"> | ||
| 4 | + <el-form-item :label="$t('questionTitle.add.name')" prop="qaTitle" :rules="[ | ||
| 5 | + { required: true, message: $t('questionTitle.add.nameRequired'), trigger: 'blur' }, | ||
| 6 | + { max: 256, message: $t('questionTitle.add.nameTooLong'), trigger: 'blur' } | ||
| 7 | + ]"> | ||
| 8 | + <el-input v-model="formData.qaTitle" :placeholder="$t('questionTitle.add.namePlaceholder')" /> | ||
| 9 | + </el-form-item> | ||
| 10 | + | ||
| 11 | + <el-form-item :label="$t('questionTitle.add.type')" prop="titleType" :rules="[ | ||
| 12 | + { required: true, message: $t('questionTitle.add.typeRequired'), trigger: 'change' } | ||
| 13 | + ]"> | ||
| 14 | + <el-select v-model="formData.titleType" :placeholder="$t('questionTitle.add.typePlaceholder')" style="width:100%" | ||
| 15 | + @change="handleTypeChange"> | ||
| 16 | + <el-option :label="$t('questionTitle.add.pleaseSelect')" value="" disabled /> | ||
| 17 | + <el-option :label="$t('questionTitle.types.singleChoice')" value="1001" /> | ||
| 18 | + <el-option :label="$t('questionTitle.types.multipleChoice')" value="2002" /> | ||
| 19 | + <el-option :label="$t('questionTitle.types.shortAnswer')" value="3003" /> | ||
| 20 | + </el-select> | ||
| 21 | + </el-form-item> | ||
| 22 | + | ||
| 23 | + <template v-if="formData.titleType && formData.titleType !== '3003'"> | ||
| 24 | + <el-form-item v-for="(item, index) in formData.titleValues" :key="index" | ||
| 25 | + :label="`${$t('questionTitle.add.option')}${item.seq}`" :prop="`titleValues.${index}.itemValue`" :rules="[ | ||
| 26 | + { required: true, message: $t('questionTitle.add.optionRequired'), trigger: 'blur' } | ||
| 27 | + ]"> | ||
| 28 | + <el-row :gutter="20"> | ||
| 29 | + <el-col :span="18"> | ||
| 30 | + <el-input v-model="item.itemValue" :placeholder="$t('questionTitle.add.optionPlaceholder')" /> | ||
| 31 | + </el-col> | ||
| 32 | + <el-col :span="5"> | ||
| 33 | + <el-button v-if="index === formData.titleValues.length - 1" type="text" @click="addOption"> | ||
| 34 | + {{ $t('questionTitle.add.addOption') }} | ||
| 35 | + </el-button> | ||
| 36 | + <el-button v-else type="text" @click="removeOption(index)"> | ||
| 37 | + {{ $t('questionTitle.add.removeOption') }} | ||
| 38 | + </el-button> | ||
| 39 | + </el-col> | ||
| 40 | + </el-row> | ||
| 41 | + </el-form-item> | ||
| 42 | + </template> | ||
| 43 | + </el-form> | ||
| 44 | + | ||
| 45 | + <div slot="footer" class="dialog-footer"> | ||
| 46 | + <el-button @click="visible = false"> | ||
| 47 | + {{ $t('common.cancel') }} | ||
| 48 | + </el-button> | ||
| 49 | + <el-button type="primary" @click="handleSubmit"> | ||
| 50 | + {{ $t('common.confirm') }} | ||
| 51 | + </el-button> | ||
| 52 | + </div> | ||
| 53 | + </el-dialog> | ||
| 54 | +</template> | ||
| 55 | + | ||
| 56 | +<script> | ||
| 57 | +import { saveQuestionTitle } from '@/api/oa/questionTitleApi' | ||
| 58 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 59 | + | ||
| 60 | +export default { | ||
| 61 | + name: 'AddQuestionTitle', | ||
| 62 | + data() { | ||
| 63 | + return { | ||
| 64 | + visible: false, | ||
| 65 | + formData: { | ||
| 66 | + titleType: '', | ||
| 67 | + qaTitle: '', | ||
| 68 | + titleValues: [], | ||
| 69 | + communityId: '' | ||
| 70 | + } | ||
| 71 | + } | ||
| 72 | + }, | ||
| 73 | + methods: { | ||
| 74 | + open() { | ||
| 75 | + this.resetForm() | ||
| 76 | + this.visible = true | ||
| 77 | + this.$nextTick(() => { | ||
| 78 | + this.$refs.form.clearValidate() | ||
| 79 | + }) | ||
| 80 | + }, | ||
| 81 | + handleClose() { | ||
| 82 | + this.$refs.form.resetFields() | ||
| 83 | + }, | ||
| 84 | + resetForm() { | ||
| 85 | + this.formData = { | ||
| 86 | + titleType: '', | ||
| 87 | + qaTitle: '', | ||
| 88 | + titleValues: [], | ||
| 89 | + communityId: getCommunityId() | ||
| 90 | + } | ||
| 91 | + }, | ||
| 92 | + handleTypeChange(value) { | ||
| 93 | + this.formData.titleValues = [] | ||
| 94 | + if (value === '1001') { | ||
| 95 | + this.formData.titleValues = [{ itemValue: '', seq: 1 }] | ||
| 96 | + } else if (value === '2002') { | ||
| 97 | + this.formData.titleValues = [ | ||
| 98 | + { itemValue: '', seq: 1 }, | ||
| 99 | + { itemValue: '', seq: 2 } | ||
| 100 | + ] | ||
| 101 | + } | ||
| 102 | + }, | ||
| 103 | + addOption() { | ||
| 104 | + const newSeq = this.formData.titleValues.length + 1 | ||
| 105 | + this.formData.titleValues.push({ itemValue: '', seq: newSeq }) | ||
| 106 | + }, | ||
| 107 | + removeOption(index) { | ||
| 108 | + this.formData.titleValues.splice(index, 1) | ||
| 109 | + // 重新排序 | ||
| 110 | + this.formData.titleValues.forEach((item, i) => { | ||
| 111 | + item.seq = i + 1 | ||
| 112 | + }) | ||
| 113 | + }, | ||
| 114 | + async handleSubmit() { | ||
| 115 | + try { | ||
| 116 | + const valid = await this.$refs.form.validate() | ||
| 117 | + if (!valid) return | ||
| 118 | + | ||
| 119 | + // 如果是简答题,清空选项 | ||
| 120 | + if (this.formData.titleType === '3003') { | ||
| 121 | + this.formData.titleValues = [] | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + await saveQuestionTitle(this.formData) | ||
| 125 | + this.$message.success(this.$t('questionTitle.add.success')) | ||
| 126 | + this.$emit('success') | ||
| 127 | + this.visible = false | ||
| 128 | + } catch (error) { | ||
| 129 | + console.error(error) | ||
| 130 | + } | ||
| 131 | + } | ||
| 132 | + } | ||
| 133 | +} | ||
| 134 | +</script> | ||
| 0 | \ No newline at end of file | 135 | \ No newline at end of file |
src/components/oa/chooseQuestionTitle.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog :title="$t('chooseQuestionTitle.title')" :visible.sync="visible" width="70%" @close="handleClose"> | ||
| 3 | + <el-row :gutter="20"> | ||
| 4 | + <el-col :span="24"> | ||
| 5 | + <el-row :gutter="10"> | ||
| 6 | + <el-col :span="18"></el-col> | ||
| 7 | + <el-col :span="6"> | ||
| 8 | + <el-input v-model="currentQuestionTitleName" :placeholder="$t('chooseQuestionTitle.searchPlaceholder')" | ||
| 9 | + clearable @keyup.enter.native="queryQuestionTitles"> | ||
| 10 | + <el-button slot="append" icon="el-icon-search" @click="queryQuestionTitles" /> | ||
| 11 | + </el-input> | ||
| 12 | + </el-col> | ||
| 13 | + </el-row> | ||
| 14 | + | ||
| 15 | + <el-table :data="questionTitles" border style="width: 100%" class="margin-top"> | ||
| 16 | + <el-table-column prop="qaTitle" :label="$t('chooseQuestionTitle.table.title')" align="center" /> | ||
| 17 | + <el-table-column prop="createTime" :label="$t('chooseQuestionTitle.table.createTime')" align="center" /> | ||
| 18 | + <el-table-column :label="$t('chooseQuestionTitle.table.actions')" align="center"> | ||
| 19 | + <template slot-scope="scope"> | ||
| 20 | + <el-button type="primary" size="mini" @click="handleChoose(scope.row)"> | ||
| 21 | + {{ $t('chooseQuestionTitle.table.choose') }} | ||
| 22 | + </el-button> | ||
| 23 | + </template> | ||
| 24 | + </el-table-column> | ||
| 25 | + </el-table> | ||
| 26 | + | ||
| 27 | + <el-pagination :current-page="pagination.current" :page-sizes="[10, 20, 30, 50]" :page-size="pagination.size" | ||
| 28 | + :total="pagination.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange" | ||
| 29 | + @current-change="handleCurrentChange" class="margin-top" /> | ||
| 30 | + </el-col> | ||
| 31 | + </el-row> | ||
| 32 | + </el-dialog> | ||
| 33 | +</template> | ||
| 34 | + | ||
| 35 | +<script> | ||
| 36 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 37 | +import { listQuestionTitle } from '@/api/oa/editQuestionAnswerApi' | ||
| 38 | + | ||
| 39 | +export default { | ||
| 40 | + name: 'ChooseQuestionTitle', | ||
| 41 | + | ||
| 42 | + data() { | ||
| 43 | + return { | ||
| 44 | + visible: false, | ||
| 45 | + questionTitles: [], | ||
| 46 | + currentQuestionTitleName: '', | ||
| 47 | + pagination: { | ||
| 48 | + current: 1, | ||
| 49 | + size: 10, | ||
| 50 | + total: 0 | ||
| 51 | + } | ||
| 52 | + } | ||
| 53 | + }, | ||
| 54 | + methods: { | ||
| 55 | + open() { | ||
| 56 | + this.visible = true | ||
| 57 | + this.resetQuestionTitles() | ||
| 58 | + this.loadAllQuestionTitleInfo() | ||
| 59 | + }, | ||
| 60 | + async loadAllQuestionTitleInfo() { | ||
| 61 | + try { | ||
| 62 | + const params = { | ||
| 63 | + page: this.pagination.current, | ||
| 64 | + row: this.pagination.size, | ||
| 65 | + communityId: getCommunityId(), | ||
| 66 | + qaTitle: this.currentQuestionTitleName | ||
| 67 | + } | ||
| 68 | + const { data, total } = await listQuestionTitle(params) | ||
| 69 | + this.questionTitles = data | ||
| 70 | + this.pagination.total = total | ||
| 71 | + } catch (error) { | ||
| 72 | + console.error('Failed to load question titles:', error) | ||
| 73 | + } | ||
| 74 | + }, | ||
| 75 | + handleChoose(questionTitle) { | ||
| 76 | + this.$emit('chooseQuestionTitle', questionTitle) | ||
| 77 | + this.visible = false | ||
| 78 | + }, | ||
| 79 | + queryQuestionTitles() { | ||
| 80 | + this.pagination.current = 1 | ||
| 81 | + this.loadAllQuestionTitleInfo() | ||
| 82 | + }, | ||
| 83 | + resetQuestionTitles() { | ||
| 84 | + this.currentQuestionTitleName = '' | ||
| 85 | + this.pagination.current = 1 | ||
| 86 | + }, | ||
| 87 | + handleSizeChange(size) { | ||
| 88 | + this.pagination.size = size | ||
| 89 | + this.loadAllQuestionTitleInfo() | ||
| 90 | + }, | ||
| 91 | + handleCurrentChange(current) { | ||
| 92 | + this.pagination.current = current | ||
| 93 | + this.loadAllQuestionTitleInfo() | ||
| 94 | + }, | ||
| 95 | + handleClose() { | ||
| 96 | + this.resetQuestionTitles() | ||
| 97 | + } | ||
| 98 | + } | ||
| 99 | +} | ||
| 100 | +</script> | ||
| 101 | + | ||
| 102 | +<style lang="scss" scoped> | ||
| 103 | +.margin-top { | ||
| 104 | + margin-top: 15px; | ||
| 105 | +} | ||
| 106 | +</style> | ||
| 0 | \ No newline at end of file | 107 | \ No newline at end of file |
src/components/oa/deleteNotepad.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog | ||
| 3 | + :title="$t('notepadManage.delete.title')" | ||
| 4 | + :visible.sync="visible" | ||
| 5 | + width="30%" | ||
| 6 | + > | ||
| 7 | + <div class="text-center"> | ||
| 8 | + <p>{{ $t('notepadManage.delete.confirm') }}</p> | ||
| 9 | + </div> | ||
| 10 | + <span slot="footer" class="dialog-footer"> | ||
| 11 | + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button> | ||
| 12 | + <el-button type="primary" @click="handleConfirm">{{ $t('common.confirm') }}</el-button> | ||
| 13 | + </span> | ||
| 14 | + </el-dialog> | ||
| 15 | +</template> | ||
| 16 | + | ||
| 17 | +<script> | ||
| 18 | +import { deleteNotepad } from '@/api/oa/notepadManageApi' | ||
| 19 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 20 | + | ||
| 21 | +export default { | ||
| 22 | + name: 'DeleteNotepad', | ||
| 23 | + data() { | ||
| 24 | + return { | ||
| 25 | + visible: false, | ||
| 26 | + formData: { | ||
| 27 | + noteId: '', | ||
| 28 | + communityId: '' | ||
| 29 | + } | ||
| 30 | + } | ||
| 31 | + }, | ||
| 32 | + methods: { | ||
| 33 | + open(data) { | ||
| 34 | + this.visible = true | ||
| 35 | + this.formData.noteId = data.noteId | ||
| 36 | + this.formData.communityId = getCommunityId() | ||
| 37 | + }, | ||
| 38 | + async handleConfirm() { | ||
| 39 | + try { | ||
| 40 | + await deleteNotepad(this.formData) | ||
| 41 | + this.$message.success(this.$t('common.deleteSuccess')) | ||
| 42 | + this.visible = false | ||
| 43 | + this.$emit('success') | ||
| 44 | + } catch (error) { | ||
| 45 | + console.error('删除记事本失败:', error) | ||
| 46 | + } | ||
| 47 | + } | ||
| 48 | + } | ||
| 49 | +} | ||
| 50 | +</script> | ||
| 51 | + | ||
| 52 | +<style scoped> | ||
| 53 | +.text-center { | ||
| 54 | + text-align: center; | ||
| 55 | +} | ||
| 56 | +</style> | ||
| 0 | \ No newline at end of file | 57 | \ No newline at end of file |
src/components/oa/deleteQuestionAnswer.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog | ||
| 3 | + :title="$t('questionAnswerManage.delete.title')" | ||
| 4 | + :visible.sync="visible" | ||
| 5 | + width="30%" | ||
| 6 | + @close="handleClose" | ||
| 7 | + > | ||
| 8 | + <div class="delete-content"> | ||
| 9 | + <i class="el-icon-warning" style="color: #e6a23c; font-size: 24px;"></i> | ||
| 10 | + <span style="margin-left: 10px;">{{ $t('questionAnswerManage.delete.confirmText') }}</span> | ||
| 11 | + </div> | ||
| 12 | + | ||
| 13 | + <div slot="footer" class="dialog-footer"> | ||
| 14 | + <el-button @click="visible = false"> | ||
| 15 | + {{ $t('common.cancel') }} | ||
| 16 | + </el-button> | ||
| 17 | + <el-button type="primary" @click="handleConfirm" :loading="loading"> | ||
| 18 | + {{ $t('common.confirm') }} | ||
| 19 | + </el-button> | ||
| 20 | + </div> | ||
| 21 | + </el-dialog> | ||
| 22 | +</template> | ||
| 23 | + | ||
| 24 | +<script> | ||
| 25 | +import { deleteQuestionAnswer } from '@/api/oa/questionAnswerManageApi' | ||
| 26 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 27 | + | ||
| 28 | +export default { | ||
| 29 | + name: 'DeleteQuestionAnswer', | ||
| 30 | + data() { | ||
| 31 | + return { | ||
| 32 | + visible: false, | ||
| 33 | + loading: false, | ||
| 34 | + currentData: null | ||
| 35 | + } | ||
| 36 | + }, | ||
| 37 | + methods: { | ||
| 38 | + open(data) { | ||
| 39 | + this.currentData = data | ||
| 40 | + this.visible = true | ||
| 41 | + }, | ||
| 42 | + handleClose() { | ||
| 43 | + this.currentData = null | ||
| 44 | + this.loading = false | ||
| 45 | + }, | ||
| 46 | + async handleConfirm() { | ||
| 47 | + if (!this.currentData) return | ||
| 48 | + | ||
| 49 | + try { | ||
| 50 | + this.loading = true | ||
| 51 | + const params = { | ||
| 52 | + qaId: this.currentData.qaId, | ||
| 53 | + communityId: getCommunityId() | ||
| 54 | + } | ||
| 55 | + await deleteQuestionAnswer(params) | ||
| 56 | + this.$message.success(this.$t('questionAnswerManage.message.deleteSuccess')) | ||
| 57 | + this.visible = false | ||
| 58 | + this.$emit('success') | ||
| 59 | + } catch (error) { | ||
| 60 | + this.$message.error(error.message || this.$t('questionAnswerManage.message.deleteError')) | ||
| 61 | + } finally { | ||
| 62 | + this.loading = false | ||
| 63 | + } | ||
| 64 | + } | ||
| 65 | + } | ||
| 66 | +} | ||
| 67 | +</script> | ||
| 68 | + | ||
| 69 | +<style lang="scss" scoped> | ||
| 70 | +.delete-content { | ||
| 71 | + display: flex; | ||
| 72 | + align-items: center; | ||
| 73 | + justify-content: center; | ||
| 74 | + padding: 20px 0; | ||
| 75 | + font-size: 16px; | ||
| 76 | +} | ||
| 77 | +</style> | ||
| 0 | \ No newline at end of file | 78 | \ No newline at end of file |
src/components/oa/deleteQuestionTitle.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog | ||
| 3 | + :title="$t('questionTitle.delete.title')" | ||
| 4 | + :visible.sync="visible" | ||
| 5 | + width="500px" | ||
| 6 | + @close="handleClose" | ||
| 7 | + > | ||
| 8 | + <div class="delete-content"> | ||
| 9 | + <el-alert | ||
| 10 | + :title="$t('questionTitle.delete.confirmMessage')" | ||
| 11 | + type="warning" | ||
| 12 | + :closable="false" | ||
| 13 | + show-icon | ||
| 14 | + /> | ||
| 15 | + </div> | ||
| 16 | + | ||
| 17 | + <div slot="footer" class="dialog-footer"> | ||
| 18 | + <el-button @click="visible = false"> | ||
| 19 | + {{ $t('common.cancel') }} | ||
| 20 | + </el-button> | ||
| 21 | + <el-button type="primary" @click="handleConfirm" :loading="loading"> | ||
| 22 | + {{ $t('common.confirm') }} | ||
| 23 | + </el-button> | ||
| 24 | + </div> | ||
| 25 | + </el-dialog> | ||
| 26 | +</template> | ||
| 27 | + | ||
| 28 | +<script> | ||
| 29 | +import { deleteQuestionTitle } from '@/api/oa/questionTitleApi' | ||
| 30 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 31 | + | ||
| 32 | +export default { | ||
| 33 | + name: 'DeleteQuestionTitle', | ||
| 34 | + data() { | ||
| 35 | + return { | ||
| 36 | + visible: false, | ||
| 37 | + loading: false, | ||
| 38 | + formData: { | ||
| 39 | + titleId: '', | ||
| 40 | + communityId: '' | ||
| 41 | + } | ||
| 42 | + } | ||
| 43 | + }, | ||
| 44 | + methods: { | ||
| 45 | + open(data) { | ||
| 46 | + this.formData = { | ||
| 47 | + titleId: data.titleId, | ||
| 48 | + communityId: getCommunityId() | ||
| 49 | + } | ||
| 50 | + this.visible = true | ||
| 51 | + }, | ||
| 52 | + handleClose() { | ||
| 53 | + this.formData = { | ||
| 54 | + titleId: '', | ||
| 55 | + communityId: '' | ||
| 56 | + } | ||
| 57 | + this.loading = false | ||
| 58 | + }, | ||
| 59 | + async handleConfirm() { | ||
| 60 | + try { | ||
| 61 | + this.loading = true | ||
| 62 | + await deleteQuestionTitle(this.formData) | ||
| 63 | + this.$message.success(this.$t('questionTitle.delete.success')) | ||
| 64 | + this.$emit('success') | ||
| 65 | + this.visible = false | ||
| 66 | + } catch (error) { | ||
| 67 | + console.error(error) | ||
| 68 | + } finally { | ||
| 69 | + this.loading = false | ||
| 70 | + } | ||
| 71 | + } | ||
| 72 | + } | ||
| 73 | +} | ||
| 74 | +</script> | ||
| 75 | + | ||
| 76 | +<style scoped> | ||
| 77 | +.delete-content { | ||
| 78 | + padding: 20px 0; | ||
| 79 | + text-align: center; | ||
| 80 | +} | ||
| 81 | +</style> | ||
| 0 | \ No newline at end of file | 82 | \ No newline at end of file |
src/components/oa/editNotepad.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog | ||
| 3 | + :title="$t('notepadManage.edit.title')" | ||
| 4 | + :visible.sync="visible" | ||
| 5 | + width="50%" | ||
| 6 | + @close="handleClose" | ||
| 7 | + > | ||
| 8 | + <el-form | ||
| 9 | + ref="form" | ||
| 10 | + :model="formData" | ||
| 11 | + :rules="rules" | ||
| 12 | + label-width="120px" | ||
| 13 | + > | ||
| 14 | + <el-form-item | ||
| 15 | + :label="$t('notepadManage.edit.roomName')" | ||
| 16 | + prop="roomName" | ||
| 17 | + > | ||
| 18 | + <el-input | ||
| 19 | + v-model="formData.roomName" | ||
| 20 | + disabled | ||
| 21 | + /> | ||
| 22 | + </el-form-item> | ||
| 23 | + <el-form-item | ||
| 24 | + :label="$t('notepadManage.edit.objName')" | ||
| 25 | + prop="objName" | ||
| 26 | + > | ||
| 27 | + <el-input | ||
| 28 | + v-model="formData.objName" | ||
| 29 | + disabled | ||
| 30 | + /> | ||
| 31 | + </el-form-item> | ||
| 32 | + <el-form-item | ||
| 33 | + :label="$t('notepadManage.edit.link')" | ||
| 34 | + prop="link" | ||
| 35 | + > | ||
| 36 | + <el-input | ||
| 37 | + v-model="formData.link" | ||
| 38 | + disabled | ||
| 39 | + /> | ||
| 40 | + </el-form-item> | ||
| 41 | + <el-form-item | ||
| 42 | + :label="$t('notepadManage.edit.noteType')" | ||
| 43 | + prop="noteType" | ||
| 44 | + > | ||
| 45 | + <el-select | ||
| 46 | + v-model="formData.noteType" | ||
| 47 | + style="width:100%" | ||
| 48 | + > | ||
| 49 | + <el-option | ||
| 50 | + :label="$t('notepadManage.edit.selectNoteType')" | ||
| 51 | + disabled | ||
| 52 | + value="" | ||
| 53 | + /> | ||
| 54 | + <el-option | ||
| 55 | + v-for="(item,index) in noteTypes" | ||
| 56 | + :key="index" | ||
| 57 | + :label="item.name" | ||
| 58 | + :value="item.statusCd" | ||
| 59 | + /> | ||
| 60 | + </el-select> | ||
| 61 | + </el-form-item> | ||
| 62 | + <el-form-item | ||
| 63 | + :label="$t('notepadManage.edit.title')" | ||
| 64 | + prop="title" | ||
| 65 | + > | ||
| 66 | + <el-input | ||
| 67 | + v-model="formData.title" | ||
| 68 | + type="textarea" | ||
| 69 | + rows="5" | ||
| 70 | + /> | ||
| 71 | + </el-form-item> | ||
| 72 | + </el-form> | ||
| 73 | + <span slot="footer" class="dialog-footer"> | ||
| 74 | + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button> | ||
| 75 | + <el-button type="primary" @click="handleSubmit">{{ $t('common.save') }}</el-button> | ||
| 76 | + </span> | ||
| 77 | + </el-dialog> | ||
| 78 | +</template> | ||
| 79 | + | ||
| 80 | +<script> | ||
| 81 | +import { updateNotepad } from '@/api/oa/notepadManageApi' | ||
| 82 | +import { getDict } from '@/api/community/communityApi' | ||
| 83 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 84 | + | ||
| 85 | +export default { | ||
| 86 | + name: 'EditNotepad', | ||
| 87 | + props: { | ||
| 88 | + callBackListener: { | ||
| 89 | + type: String, | ||
| 90 | + default: '' | ||
| 91 | + }, | ||
| 92 | + callBackFunction: { | ||
| 93 | + type: String, | ||
| 94 | + default: '' | ||
| 95 | + } | ||
| 96 | + }, | ||
| 97 | + data() { | ||
| 98 | + return { | ||
| 99 | + visible: false, | ||
| 100 | + formData: { | ||
| 101 | + noteId: '', | ||
| 102 | + noteType: '', | ||
| 103 | + title: '', | ||
| 104 | + roomName: '', | ||
| 105 | + roomId: '', | ||
| 106 | + objId: '', | ||
| 107 | + objName: '', | ||
| 108 | + objType: '', | ||
| 109 | + link: '', | ||
| 110 | + communityId: '' | ||
| 111 | + }, | ||
| 112 | + noteTypes: [], | ||
| 113 | + rules: { | ||
| 114 | + noteType: [ | ||
| 115 | + { required: true, message: this.$t('notepadManage.validate.noteType'), trigger: 'blur' } | ||
| 116 | + ], | ||
| 117 | + title: [ | ||
| 118 | + { required: true, message: this.$t('notepadManage.validate.title'), trigger: 'blur' }, | ||
| 119 | + { max: 256, message: this.$t('notepadManage.validate.titleMaxLength'), trigger: 'blur' } | ||
| 120 | + ] | ||
| 121 | + } | ||
| 122 | + } | ||
| 123 | + }, | ||
| 124 | + methods: { | ||
| 125 | + open(data) { | ||
| 126 | + this.visible = true | ||
| 127 | + this.formData = { ...data } | ||
| 128 | + this.formData.communityId = getCommunityId() | ||
| 129 | + this.getNoteTypes() | ||
| 130 | + }, | ||
| 131 | + async getNoteTypes() { | ||
| 132 | + try { | ||
| 133 | + const data = await getDict('notepad', 'note_type') | ||
| 134 | + this.noteTypes = data | ||
| 135 | + } catch (error) { | ||
| 136 | + console.error('获取字典数据失败:', error) | ||
| 137 | + } | ||
| 138 | + }, | ||
| 139 | + handleSubmit() { | ||
| 140 | + this.$refs.form.validate(async valid => { | ||
| 141 | + if (valid) { | ||
| 142 | + try { | ||
| 143 | + await updateNotepad(this.formData) | ||
| 144 | + this.$message.success(this.$t('common.updateSuccess')) | ||
| 145 | + this.visible = false | ||
| 146 | + this.$emit('success') | ||
| 147 | + } catch (error) { | ||
| 148 | + console.error('更新记事本失败:', error) | ||
| 149 | + } | ||
| 150 | + } | ||
| 151 | + }) | ||
| 152 | + }, | ||
| 153 | + handleClose() { | ||
| 154 | + this.$refs.form.resetFields() | ||
| 155 | + } | ||
| 156 | + } | ||
| 157 | +} | ||
| 158 | +</script> | ||
| 0 | \ No newline at end of file | 159 | \ No newline at end of file |
src/components/oa/editQuestionAnswer.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog | ||
| 3 | + :title="$t('questionAnswerManage.edit.title')" | ||
| 4 | + :visible.sync="visible" | ||
| 5 | + width="50%" | ||
| 6 | + @close="handleClose" | ||
| 7 | + > | ||
| 8 | + <el-form | ||
| 9 | + ref="form" | ||
| 10 | + :model="formData" | ||
| 11 | + :rules="rules" | ||
| 12 | + label-width="120px" | ||
| 13 | + label-position="right" | ||
| 14 | + > | ||
| 15 | + <el-form-item | ||
| 16 | + :label="$t('questionAnswerManage.edit.qaType')" | ||
| 17 | + prop="qaType" | ||
| 18 | + > | ||
| 19 | + <el-select | ||
| 20 | + v-model="formData.qaType" | ||
| 21 | + :placeholder="$t('questionAnswerManage.edit.qaTypePlaceholder')" | ||
| 22 | + style="width: 100%" | ||
| 23 | + > | ||
| 24 | + <el-option | ||
| 25 | + value="1001" | ||
| 26 | + :label="$t('questionAnswerManage.edit.qaType1')" | ||
| 27 | + /> | ||
| 28 | + <el-option | ||
| 29 | + value="3003" | ||
| 30 | + :label="$t('questionAnswerManage.edit.qaType3')" | ||
| 31 | + /> | ||
| 32 | + <el-option | ||
| 33 | + value="4004" | ||
| 34 | + :label="$t('questionAnswerManage.edit.qaType4')" | ||
| 35 | + /> | ||
| 36 | + </el-select> | ||
| 37 | + </el-form-item> | ||
| 38 | + | ||
| 39 | + <el-form-item | ||
| 40 | + :label="$t('questionAnswerManage.edit.qaName')" | ||
| 41 | + prop="qaName" | ||
| 42 | + > | ||
| 43 | + <el-input | ||
| 44 | + v-model="formData.qaName" | ||
| 45 | + :placeholder="$t('questionAnswerManage.edit.qaNamePlaceholder')" | ||
| 46 | + /> | ||
| 47 | + </el-form-item> | ||
| 48 | + | ||
| 49 | + <el-form-item | ||
| 50 | + :label="$t('questionAnswerManage.edit.startTime')" | ||
| 51 | + prop="startTime" | ||
| 52 | + > | ||
| 53 | + <el-date-picker | ||
| 54 | + v-model="formData.startTime" | ||
| 55 | + type="datetime" | ||
| 56 | + :placeholder="$t('questionAnswerManage.edit.startTimePlaceholder')" | ||
| 57 | + style="width: 100%" | ||
| 58 | + value-format="yyyy-MM-dd HH:mm:ss" | ||
| 59 | + /> | ||
| 60 | + </el-form-item> | ||
| 61 | + | ||
| 62 | + <el-form-item | ||
| 63 | + :label="$t('questionAnswerManage.edit.endTime')" | ||
| 64 | + prop="endTime" | ||
| 65 | + > | ||
| 66 | + <el-date-picker | ||
| 67 | + v-model="formData.endTime" | ||
| 68 | + type="datetime" | ||
| 69 | + :placeholder="$t('questionAnswerManage.edit.endTimePlaceholder')" | ||
| 70 | + style="width: 100%" | ||
| 71 | + value-format="yyyy-MM-dd HH:mm:ss" | ||
| 72 | + /> | ||
| 73 | + </el-form-item> | ||
| 74 | + | ||
| 75 | + <el-form-item :label="$t('questionAnswerManage.edit.content')"> | ||
| 76 | + <el-input | ||
| 77 | + v-model="formData.content" | ||
| 78 | + type="textarea" | ||
| 79 | + :placeholder="$t('questionAnswerManage.edit.contentPlaceholder')" | ||
| 80 | + :rows="3" | ||
| 81 | + /> | ||
| 82 | + </el-form-item> | ||
| 83 | + | ||
| 84 | + <el-form-item :label="$t('questionAnswerManage.edit.remark')"> | ||
| 85 | + <el-input | ||
| 86 | + v-model="formData.remark" | ||
| 87 | + type="textarea" | ||
| 88 | + :placeholder="$t('questionAnswerManage.edit.remarkPlaceholder')" | ||
| 89 | + :rows="3" | ||
| 90 | + /> | ||
| 91 | + </el-form-item> | ||
| 92 | + | ||
| 93 | + <el-form-item :label="$t('questionAnswerManage.edit.photos')"> | ||
| 94 | + <upload-image-url | ||
| 95 | + ref="uploadImage" | ||
| 96 | + :image-count="99" | ||
| 97 | + @change="handleImageChange" | ||
| 98 | + /> | ||
| 99 | + </el-form-item> | ||
| 100 | + </el-form> | ||
| 101 | + | ||
| 102 | + <div slot="footer" class="dialog-footer"> | ||
| 103 | + <el-button @click="visible = false"> | ||
| 104 | + {{ $t('common.cancel') }} | ||
| 105 | + </el-button> | ||
| 106 | + <el-button type="primary" @click="handleSubmit"> | ||
| 107 | + {{ $t('common.confirm') }} | ||
| 108 | + </el-button> | ||
| 109 | + </div> | ||
| 110 | + </el-dialog> | ||
| 111 | +</template> | ||
| 112 | + | ||
| 113 | +<script> | ||
| 114 | +import { updateQuestionAnswer } from '@/api/oa/questionAnswerManageApi' | ||
| 115 | +import UploadImageUrl from '@/components/oa/UploadImageUrl' | ||
| 116 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 117 | + | ||
| 118 | +export default { | ||
| 119 | + name: 'EditQuestionAnswer', | ||
| 120 | + components: { | ||
| 121 | + UploadImageUrl | ||
| 122 | + }, | ||
| 123 | + data() { | ||
| 124 | + return { | ||
| 125 | + visible: false, | ||
| 126 | + formData: { | ||
| 127 | + qaId: '', | ||
| 128 | + qaType: '', | ||
| 129 | + qaName: '', | ||
| 130 | + startTime: '', | ||
| 131 | + endTime: '', | ||
| 132 | + content: '', | ||
| 133 | + remark: '', | ||
| 134 | + photos: [] | ||
| 135 | + }, | ||
| 136 | + rules: { | ||
| 137 | + qaType: [ | ||
| 138 | + { required: true, message: this.$t('questionAnswerManage.validate.qaType'), trigger: 'blur' } | ||
| 139 | + ], | ||
| 140 | + qaName: [ | ||
| 141 | + { required: true, message: this.$t('questionAnswerManage.validate.qaName'), trigger: 'blur' }, | ||
| 142 | + { max: 256, message: this.$t('questionAnswerManage.validate.qaNameMax'), trigger: 'blur' } | ||
| 143 | + ], | ||
| 144 | + startTime: [ | ||
| 145 | + { required: true, message: this.$t('questionAnswerManage.validate.startTime'), trigger: 'blur' } | ||
| 146 | + ], | ||
| 147 | + endTime: [ | ||
| 148 | + { required: true, message: this.$t('questionAnswerManage.validate.endTime'), trigger: 'blur' } | ||
| 149 | + ] | ||
| 150 | + } | ||
| 151 | + } | ||
| 152 | + }, | ||
| 153 | + methods: { | ||
| 154 | + open(data) { | ||
| 155 | + this.visible = true | ||
| 156 | + this.$nextTick(() => { | ||
| 157 | + this.resetForm() | ||
| 158 | + if (data) { | ||
| 159 | + Object.assign(this.formData, data) | ||
| 160 | + if (data.fileUrls) { | ||
| 161 | + this.$refs.uploadImage.setPhotos(data.fileUrls) | ||
| 162 | + } | ||
| 163 | + } | ||
| 164 | + }) | ||
| 165 | + }, | ||
| 166 | + resetForm() { | ||
| 167 | + this.$refs.form && this.$refs.form.resetFields() | ||
| 168 | + this.$refs.uploadImage && this.$refs.uploadImage.clear() | ||
| 169 | + this.formData = { | ||
| 170 | + qaId: '', | ||
| 171 | + qaType: '', | ||
| 172 | + qaName: '', | ||
| 173 | + startTime: '', | ||
| 174 | + endTime: '', | ||
| 175 | + content: '', | ||
| 176 | + remark: '', | ||
| 177 | + photos: [] | ||
| 178 | + } | ||
| 179 | + }, | ||
| 180 | + handleClose() { | ||
| 181 | + this.resetForm() | ||
| 182 | + }, | ||
| 183 | + handleImageChange(photos) { | ||
| 184 | + this.formData.photos = photos.map(item => item.fileId) | ||
| 185 | + }, | ||
| 186 | + async handleSubmit() { | ||
| 187 | + this.$refs.form.validate(async valid => { | ||
| 188 | + if (!valid) return | ||
| 189 | + | ||
| 190 | + try { | ||
| 191 | + this.formData.communityId = getCommunityId() | ||
| 192 | + await updateQuestionAnswer(this.formData) | ||
| 193 | + this.$message.success(this.$t('questionAnswerManage.message.updateSuccess')) | ||
| 194 | + this.visible = false | ||
| 195 | + this.$emit('success') | ||
| 196 | + } catch (error) { | ||
| 197 | + this.$message.error(error.message || this.$t('questionAnswerManage.message.updateError')) | ||
| 198 | + } | ||
| 199 | + }) | ||
| 200 | + } | ||
| 201 | + } | ||
| 202 | +} | ||
| 203 | +</script> | ||
| 0 | \ No newline at end of file | 204 | \ No newline at end of file |
src/components/oa/editQuestionTitle.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog :title="$t('questionTitle.edit.title')" :visible.sync="visible" width="70%" @close="handleClose"> | ||
| 3 | + <el-form ref="form" :model="formData" label-width="120px"> | ||
| 4 | + <el-form-item :label="$t('questionTitle.edit.type')" prop="titleType" :rules="[ | ||
| 5 | + { required: true, message: $t('questionTitle.edit.typeRequired'), trigger: 'change' } | ||
| 6 | + ]"> | ||
| 7 | + <el-select v-model="formData.titleType" :placeholder="$t('questionTitle.edit.typePlaceholder')" style="width:100%" | ||
| 8 | + @change="handleTypeChange"> | ||
| 9 | + <el-option :label="$t('questionTitle.edit.pleaseSelect')" value="" disabled /> | ||
| 10 | + <el-option :label="$t('questionTitle.types.singleChoice')" value="1001" /> | ||
| 11 | + <el-option :label="$t('questionTitle.types.multipleChoice')" value="2002" /> | ||
| 12 | + <el-option :label="$t('questionTitle.types.shortAnswer')" value="3003" /> | ||
| 13 | + </el-select> | ||
| 14 | + </el-form-item> | ||
| 15 | + | ||
| 16 | + <el-form-item :label="$t('questionTitle.edit.name')" prop="qaTitle" :rules="[ | ||
| 17 | + { required: true, message: $t('questionTitle.edit.nameRequired'), trigger: 'blur' }, | ||
| 18 | + { max: 256, message: $t('questionTitle.edit.nameTooLong'), trigger: 'blur' } | ||
| 19 | + ]"> | ||
| 20 | + <el-input v-model="formData.qaTitle" :placeholder="$t('questionTitle.edit.namePlaceholder')" /> | ||
| 21 | + </el-form-item> | ||
| 22 | + | ||
| 23 | + <template v-if="formData.titleType && formData.titleType !== '3003'"> | ||
| 24 | + <el-form-item v-for="(item, index) in formData.titleValues" :key="index" | ||
| 25 | + :label="`${$t('questionTitle.edit.option')}${item.seq}`" :prop="`titleValues.${index}.qaValue`" :rules="[ | ||
| 26 | + { required: true, message: $t('questionTitle.edit.optionRequired'), trigger: 'blur' } | ||
| 27 | + ]"> | ||
| 28 | + <el-row :gutter="20"> | ||
| 29 | + <el-col :span="18"> | ||
| 30 | + <el-input v-model="item.qaValue" :placeholder="$t('questionTitle.edit.optionPlaceholder')" /> | ||
| 31 | + </el-col> | ||
| 32 | + <el-col :span="5"> | ||
| 33 | + <el-button v-if="index === formData.titleValues.length - 1" type="text" @click="addOption"> | ||
| 34 | + {{ $t('questionTitle.edit.addOption') }} | ||
| 35 | + </el-button> | ||
| 36 | + <el-button v-else type="text" @click="removeOption(index)"> | ||
| 37 | + {{ $t('questionTitle.edit.removeOption') }} | ||
| 38 | + </el-button> | ||
| 39 | + </el-col> | ||
| 40 | + </el-row> | ||
| 41 | + </el-form-item> | ||
| 42 | + </template> | ||
| 43 | + </el-form> | ||
| 44 | + | ||
| 45 | + <div slot="footer" class="dialog-footer"> | ||
| 46 | + <el-button @click="visible = false"> | ||
| 47 | + {{ $t('common.cancel') }} | ||
| 48 | + </el-button> | ||
| 49 | + <el-button type="primary" @click="handleSubmit"> | ||
| 50 | + {{ $t('common.confirm') }} | ||
| 51 | + </el-button> | ||
| 52 | + </div> | ||
| 53 | + </el-dialog> | ||
| 54 | +</template> | ||
| 55 | + | ||
| 56 | +<script> | ||
| 57 | +import { updateQuestionTitle } from '@/api/oa/questionTitleApi' | ||
| 58 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 59 | + | ||
| 60 | +export default { | ||
| 61 | + name: 'EditQuestionTitle', | ||
| 62 | + data() { | ||
| 63 | + return { | ||
| 64 | + visible: false, | ||
| 65 | + formData: { | ||
| 66 | + titleId: '', | ||
| 67 | + titleType: '', | ||
| 68 | + qaTitle: '', | ||
| 69 | + titleValues: [], | ||
| 70 | + communityId: '' | ||
| 71 | + } | ||
| 72 | + } | ||
| 73 | + }, | ||
| 74 | + methods: { | ||
| 75 | + open(data) { | ||
| 76 | + this.resetForm() | ||
| 77 | + this.formData = { | ||
| 78 | + ...data, | ||
| 79 | + communityId: getCommunityId() | ||
| 80 | + } | ||
| 81 | + this.visible = true | ||
| 82 | + this.$nextTick(() => { | ||
| 83 | + this.$refs.form.clearValidate() | ||
| 84 | + }) | ||
| 85 | + }, | ||
| 86 | + handleClose() { | ||
| 87 | + this.$refs.form.resetFields() | ||
| 88 | + }, | ||
| 89 | + resetForm() { | ||
| 90 | + this.formData = { | ||
| 91 | + titleId: '', | ||
| 92 | + titleType: '', | ||
| 93 | + qaTitle: '', | ||
| 94 | + titleValues: [], | ||
| 95 | + communityId: getCommunityId() | ||
| 96 | + } | ||
| 97 | + }, | ||
| 98 | + handleTypeChange(value) { | ||
| 99 | + if (value === '3003') { | ||
| 100 | + this.formData.titleValues = [] | ||
| 101 | + } else if (value === '1001' && this.formData.titleValues.length === 0) { | ||
| 102 | + this.formData.titleValues = [{ qaValue: '', seq: 1 }] | ||
| 103 | + } else if (value === '2002' && this.formData.titleValues.length < 2) { | ||
| 104 | + this.formData.titleValues = [ | ||
| 105 | + { qaValue: '', seq: 1 }, | ||
| 106 | + { qaValue: '', seq: 2 } | ||
| 107 | + ] | ||
| 108 | + } | ||
| 109 | + }, | ||
| 110 | + addOption() { | ||
| 111 | + const newSeq = this.formData.titleValues.length + 1 | ||
| 112 | + this.formData.titleValues.push({ qaValue: '', seq: newSeq }) | ||
| 113 | + }, | ||
| 114 | + removeOption(index) { | ||
| 115 | + this.formData.titleValues.splice(index, 1) | ||
| 116 | + // 重新排序 | ||
| 117 | + this.formData.titleValues.forEach((item, i) => { | ||
| 118 | + item.seq = i + 1 | ||
| 119 | + }) | ||
| 120 | + }, | ||
| 121 | + async handleSubmit() { | ||
| 122 | + try { | ||
| 123 | + const valid = await this.$refs.form.validate() | ||
| 124 | + if (!valid) return | ||
| 125 | + | ||
| 126 | + // 如果是简答题,清空选项 | ||
| 127 | + if (this.formData.titleType === '3003') { | ||
| 128 | + this.formData.titleValues = [] | ||
| 129 | + } | ||
| 130 | + | ||
| 131 | + await updateQuestionTitle(this.formData) | ||
| 132 | + this.$message.success(this.$t('questionTitle.edit.success')) | ||
| 133 | + this.$emit('success') | ||
| 134 | + this.visible = false | ||
| 135 | + } catch (error) { | ||
| 136 | + console.error(error) | ||
| 137 | + } | ||
| 138 | + } | ||
| 139 | + } | ||
| 140 | +} | ||
| 141 | +</script> | ||
| 0 | \ No newline at end of file | 142 | \ No newline at end of file |
src/components/oa/notepadDetail.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog | ||
| 3 | + :title="$t('notepadManage.detail.title')" | ||
| 4 | + :visible.sync="visible" | ||
| 5 | + width="70%" | ||
| 6 | + > | ||
| 7 | + <el-table | ||
| 8 | + :data="tableData" | ||
| 9 | + border | ||
| 10 | + style="width: 100%" | ||
| 11 | + > | ||
| 12 | + <el-table-column | ||
| 13 | + type="index" | ||
| 14 | + :label="$t('notepadManage.detail.index')" | ||
| 15 | + width="80" | ||
| 16 | + align="center" | ||
| 17 | + /> | ||
| 18 | + <el-table-column | ||
| 19 | + prop="createUserName" | ||
| 20 | + :label="$t('notepadManage.detail.createUser')" | ||
| 21 | + align="center" | ||
| 22 | + /> | ||
| 23 | + <el-table-column | ||
| 24 | + prop="createTime" | ||
| 25 | + :label="$t('notepadManage.detail.createTime')" | ||
| 26 | + align="center" | ||
| 27 | + /> | ||
| 28 | + <el-table-column | ||
| 29 | + prop="content" | ||
| 30 | + :label="$t('notepadManage.detail.content')" | ||
| 31 | + align="center" | ||
| 32 | + /> | ||
| 33 | + <el-table-column | ||
| 34 | + :label="$t('common.operation')" | ||
| 35 | + align="center" | ||
| 36 | + width="120" | ||
| 37 | + > | ||
| 38 | + <template slot-scope="scope"> | ||
| 39 | + <el-button | ||
| 40 | + size="mini" | ||
| 41 | + type="danger" | ||
| 42 | + @click="handleDelete(scope.row)" | ||
| 43 | + > | ||
| 44 | + {{ $t('common.delete') }} | ||
| 45 | + </el-button> | ||
| 46 | + </template> | ||
| 47 | + </el-table-column> | ||
| 48 | + </el-table> | ||
| 49 | + </el-dialog> | ||
| 50 | +</template> | ||
| 51 | + | ||
| 52 | +<script> | ||
| 53 | +import { listNotepadDetail, deleteNotepadDetail } from '@/api/oa/notepadManageApi' | ||
| 54 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 55 | + | ||
| 56 | +export default { | ||
| 57 | + name: 'NotepadDetail', | ||
| 58 | + data() { | ||
| 59 | + return { | ||
| 60 | + visible: false, | ||
| 61 | + tableData: [], | ||
| 62 | + formData: { | ||
| 63 | + noteId: '', | ||
| 64 | + communityId: '' | ||
| 65 | + } | ||
| 66 | + } | ||
| 67 | + }, | ||
| 68 | + methods: { | ||
| 69 | + open(data) { | ||
| 70 | + this.visible = true | ||
| 71 | + this.formData.noteId = data.noteId | ||
| 72 | + this.formData.communityId = getCommunityId() | ||
| 73 | + this.loadDetails() | ||
| 74 | + }, | ||
| 75 | + async loadDetails() { | ||
| 76 | + try { | ||
| 77 | + const params = { | ||
| 78 | + noteId: this.formData.noteId, | ||
| 79 | + communityId: this.formData.communityId, | ||
| 80 | + page: 1, | ||
| 81 | + row: 50 | ||
| 82 | + } | ||
| 83 | + const { data } = await listNotepadDetail(params) | ||
| 84 | + this.tableData = data | ||
| 85 | + } catch (error) { | ||
| 86 | + console.error('获取记事本详情失败:', error) | ||
| 87 | + } | ||
| 88 | + }, | ||
| 89 | + async handleDelete(row) { | ||
| 90 | + try { | ||
| 91 | + await deleteNotepadDetail({ | ||
| 92 | + detailId: row.detailId, | ||
| 93 | + communityId: this.formData.communityId | ||
| 94 | + }) | ||
| 95 | + this.$message.success(this.$t('common.deleteSuccess')) | ||
| 96 | + this.loadDetails() | ||
| 97 | + } catch (error) { | ||
| 98 | + console.error('删除记事本详情失败:', error) | ||
| 99 | + } | ||
| 100 | + } | ||
| 101 | + } | ||
| 102 | +} | ||
| 103 | +</script> | ||
| 0 | \ No newline at end of file | 104 | \ No newline at end of file |
src/components/oa/notepadOwnerRepair.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog | ||
| 3 | + :title="$t('notepadManage.ownerRepair.title')" | ||
| 4 | + :visible.sync="visible" | ||
| 5 | + width="50%" | ||
| 6 | + @close="handleClose" | ||
| 7 | + > | ||
| 8 | + <el-form | ||
| 9 | + ref="form" | ||
| 10 | + :model="formData" | ||
| 11 | + :rules="rules" | ||
| 12 | + label-width="120px" | ||
| 13 | + > | ||
| 14 | + <el-form-item | ||
| 15 | + :label="$t('notepadManage.ownerRepair.repairType')" | ||
| 16 | + prop="repairType" | ||
| 17 | + > | ||
| 18 | + <el-select | ||
| 19 | + v-model="formData.repairType" | ||
| 20 | + style="width:100%" | ||
| 21 | + > | ||
| 22 | + <el-option | ||
| 23 | + :label="$t('notepadManage.ownerRepair.selectRepairType')" | ||
| 24 | + disabled | ||
| 25 | + value="" | ||
| 26 | + /> | ||
| 27 | + <el-option | ||
| 28 | + v-for="(item,index) in repairSettings" | ||
| 29 | + :key="index" | ||
| 30 | + :label="item.repairTypeName" | ||
| 31 | + :value="item.repairType" | ||
| 32 | + /> | ||
| 33 | + </el-select> | ||
| 34 | + </el-form-item> | ||
| 35 | + <el-form-item | ||
| 36 | + :label="$t('notepadManage.ownerRepair.repairObjName')" | ||
| 37 | + prop="repairObjName" | ||
| 38 | + > | ||
| 39 | + <el-input | ||
| 40 | + v-model="formData.repairObjName" | ||
| 41 | + :placeholder="$t('notepadManage.ownerRepair.repairObjNamePlaceholder')" | ||
| 42 | + /> | ||
| 43 | + </el-form-item> | ||
| 44 | + <el-form-item | ||
| 45 | + :label="$t('notepadManage.ownerRepair.repairName')" | ||
| 46 | + prop="repairName" | ||
| 47 | + > | ||
| 48 | + <el-input | ||
| 49 | + v-model="formData.repairName" | ||
| 50 | + :placeholder="$t('notepadManage.ownerRepair.repairNamePlaceholder')" | ||
| 51 | + /> | ||
| 52 | + </el-form-item> | ||
| 53 | + <el-form-item | ||
| 54 | + :label="$t('notepadManage.ownerRepair.tel')" | ||
| 55 | + prop="tel" | ||
| 56 | + > | ||
| 57 | + <el-input | ||
| 58 | + v-model="formData.tel" | ||
| 59 | + :placeholder="$t('notepadManage.ownerRepair.telPlaceholder')" | ||
| 60 | + /> | ||
| 61 | + </el-form-item> | ||
| 62 | + <el-form-item | ||
| 63 | + :label="$t('notepadManage.ownerRepair.appointmentTime')" | ||
| 64 | + prop="appointmentTime" | ||
| 65 | + > | ||
| 66 | + <el-date-picker | ||
| 67 | + v-model="formData.appointmentTime" | ||
| 68 | + type="datetime" | ||
| 69 | + style="width:100%" | ||
| 70 | + :placeholder="$t('notepadManage.ownerRepair.selectTime')" | ||
| 71 | + value-format="yyyy-MM-dd HH:mm:ss" | ||
| 72 | + /> | ||
| 73 | + </el-form-item> | ||
| 74 | + <el-form-item | ||
| 75 | + :label="$t('notepadManage.ownerRepair.context')" | ||
| 76 | + prop="context" | ||
| 77 | + > | ||
| 78 | + <el-input | ||
| 79 | + v-model="formData.context" | ||
| 80 | + type="textarea" | ||
| 81 | + rows="5" | ||
| 82 | + :placeholder="$t('notepadManage.ownerRepair.contextPlaceholder')" | ||
| 83 | + /> | ||
| 84 | + </el-form-item> | ||
| 85 | + </el-form> | ||
| 86 | + <span slot="footer" class="dialog-footer"> | ||
| 87 | + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button> | ||
| 88 | + <el-button type="primary" @click="handleSubmit">{{ $t('common.submit') }}</el-button> | ||
| 89 | + </span> | ||
| 90 | + </el-dialog> | ||
| 91 | +</template> | ||
| 92 | + | ||
| 93 | +<script> | ||
| 94 | +import { saveOwnerRepair, listRepairSettings } from '@/api/oa/notepadManageApi' | ||
| 95 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 96 | + | ||
| 97 | +export default { | ||
| 98 | + name: 'NotepadOwnerRepair', | ||
| 99 | + data() { | ||
| 100 | + return { | ||
| 101 | + visible: false, | ||
| 102 | + formData: { | ||
| 103 | + repairType: '', | ||
| 104 | + repairName: '', | ||
| 105 | + tel: '', | ||
| 106 | + appointmentTime: '', | ||
| 107 | + context: '', | ||
| 108 | + repairObjType: '004', | ||
| 109 | + repairObjId: '', | ||
| 110 | + repairObjName: '', | ||
| 111 | + repairChannel: 'T', | ||
| 112 | + noteId: '', | ||
| 113 | + communityId: '' | ||
| 114 | + }, | ||
| 115 | + repairSettings: [], | ||
| 116 | + rules: { | ||
| 117 | + repairType: [ | ||
| 118 | + { required: true, message: this.$t('notepadManage.validate.repairType'), trigger: 'blur' } | ||
| 119 | + ], | ||
| 120 | + repairObjName: [ | ||
| 121 | + { required: true, message: this.$t('notepadManage.validate.repairObjName'), trigger: 'blur' } | ||
| 122 | + ], | ||
| 123 | + repairName: [ | ||
| 124 | + { required: true, message: this.$t('notepadManage.validate.repairName'), trigger: 'blur' }, | ||
| 125 | + { min: 2, max: 10, message: this.$t('notepadManage.validate.repairNameLength'), trigger: 'blur' } | ||
| 126 | + ], | ||
| 127 | + tel: [ | ||
| 128 | + { required: true, message: this.$t('notepadManage.validate.tel'), trigger: 'blur' }, | ||
| 129 | + { pattern: /^1[3-9]\d{9}$/, message: this.$t('notepadManage.validate.telFormat'), trigger: 'blur' } | ||
| 130 | + ], | ||
| 131 | + appointmentTime: [ | ||
| 132 | + { required: true, message: this.$t('notepadManage.validate.appointmentTime'), trigger: 'blur' } | ||
| 133 | + ], | ||
| 134 | + context: [ | ||
| 135 | + { required: true, message: this.$t('notepadManage.validate.context'), trigger: 'blur' }, | ||
| 136 | + { max: 2000, message: this.$t('notepadManage.validate.contextMaxLength'), trigger: 'blur' } | ||
| 137 | + ] | ||
| 138 | + } | ||
| 139 | + } | ||
| 140 | + }, | ||
| 141 | + methods: { | ||
| 142 | + open(data) { | ||
| 143 | + this.visible = true | ||
| 144 | + this.formData = { | ||
| 145 | + ...this.formData, | ||
| 146 | + repairObjName: data.roomName, | ||
| 147 | + repairObjId: data.roomId, | ||
| 148 | + tel: data.link, | ||
| 149 | + repairName: data.objName, | ||
| 150 | + context: data.title, | ||
| 151 | + noteId: data.noteId, | ||
| 152 | + communityId: getCommunityId() | ||
| 153 | + } | ||
| 154 | + this.loadRepairSettings() | ||
| 155 | + }, | ||
| 156 | + async loadRepairSettings() { | ||
| 157 | + try { | ||
| 158 | + const params = { | ||
| 159 | + page: 1, | ||
| 160 | + row: 50, | ||
| 161 | + communityId: this.formData.communityId, | ||
| 162 | + publicArea: 'F' | ||
| 163 | + } | ||
| 164 | + const { data } = await listRepairSettings(params) | ||
| 165 | + this.repairSettings = data | ||
| 166 | + } catch (error) { | ||
| 167 | + console.error('获取报修设置失败:', error) | ||
| 168 | + } | ||
| 169 | + }, | ||
| 170 | + async handleSubmit() { | ||
| 171 | + this.$refs.form.validate(async valid => { | ||
| 172 | + if (valid) { | ||
| 173 | + try { | ||
| 174 | + await saveOwnerRepair(this.formData) | ||
| 175 | + this.$message.success(this.$t('common.submitSuccess')) | ||
| 176 | + this.visible = false | ||
| 177 | + this.$emit('success') | ||
| 178 | + } catch (error) { | ||
| 179 | + console.error('提交报修单失败:', error) | ||
| 180 | + } | ||
| 181 | + } | ||
| 182 | + }) | ||
| 183 | + }, | ||
| 184 | + handleClose() { | ||
| 185 | + this.$refs.form.resetFields() | ||
| 186 | + this.formData = { | ||
| 187 | + repairType: '', | ||
| 188 | + repairName: '', | ||
| 189 | + tel: '', | ||
| 190 | + appointmentTime: '', | ||
| 191 | + context: '', | ||
| 192 | + repairObjType: '004', | ||
| 193 | + repairObjId: '', | ||
| 194 | + repairObjName: '', | ||
| 195 | + repairChannel: 'T', | ||
| 196 | + noteId: '', | ||
| 197 | + communityId: '' | ||
| 198 | + } | ||
| 199 | + } | ||
| 200 | + } | ||
| 201 | +} | ||
| 202 | +</script> | ||
| 0 | \ No newline at end of file | 203 | \ No newline at end of file |
src/components/oa/publishQuestionAnswer.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog | ||
| 3 | + :title="$t('questionAnswerManage.publish.title')" | ||
| 4 | + :visible.sync="visible" | ||
| 5 | + width="40%" | ||
| 6 | + @close="handleClose" | ||
| 7 | + > | ||
| 8 | + <el-form ref="form" :model="formData" :rules="rules" label-width="120px"> | ||
| 9 | + <el-form-item :label="$t('questionAnswerManage.publish.qaName')"> | ||
| 10 | + <el-input v-model="formData.qaName" disabled /> | ||
| 11 | + </el-form-item> | ||
| 12 | + | ||
| 13 | + <el-form-item :label="$t('questionAnswerManage.publish.tip')"> | ||
| 14 | + <el-input | ||
| 15 | + :value="$t('questionAnswerManage.publish.tipText')" | ||
| 16 | + disabled | ||
| 17 | + /> | ||
| 18 | + </el-form-item> | ||
| 19 | + | ||
| 20 | + <el-form-item | ||
| 21 | + :label="$t('questionAnswerManage.publish.notifyWay')" | ||
| 22 | + prop="notifyWay" | ||
| 23 | + > | ||
| 24 | + <el-select | ||
| 25 | + v-model="formData.notifyWay" | ||
| 26 | + :placeholder="$t('questionAnswerManage.publish.notifyWayPlaceholder')" | ||
| 27 | + style="width: 100%" | ||
| 28 | + > | ||
| 29 | + <el-option | ||
| 30 | + value="1001" | ||
| 31 | + :label="$t('questionAnswerManage.publish.notifyWay1')" | ||
| 32 | + /> | ||
| 33 | + <el-option | ||
| 34 | + value="2002" | ||
| 35 | + :label="$t('questionAnswerManage.publish.notifyWay2')" | ||
| 36 | + /> | ||
| 37 | + <el-option | ||
| 38 | + value="3003" | ||
| 39 | + :label="$t('questionAnswerManage.publish.notifyWay3')" | ||
| 40 | + /> | ||
| 41 | + </el-select> | ||
| 42 | + </el-form-item> | ||
| 43 | + </el-form> | ||
| 44 | + | ||
| 45 | + <div slot="footer" class="dialog-footer"> | ||
| 46 | + <el-button @click="visible = false"> | ||
| 47 | + {{ $t('common.cancel') }} | ||
| 48 | + </el-button> | ||
| 49 | + <el-button type="primary" @click="handlePublish" :loading="loading"> | ||
| 50 | + {{ $t('questionAnswerManage.publish.button') }} | ||
| 51 | + </el-button> | ||
| 52 | + </div> | ||
| 53 | + </el-dialog> | ||
| 54 | +</template> | ||
| 55 | + | ||
| 56 | +<script> | ||
| 57 | +import { publishQuestionAnswer } from '@/api/oa/questionAnswerManageApi' | ||
| 58 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 59 | + | ||
| 60 | +export default { | ||
| 61 | + name: 'PublishQuestionAnswer', | ||
| 62 | + data() { | ||
| 63 | + return { | ||
| 64 | + visible: false, | ||
| 65 | + loading: false, | ||
| 66 | + formData: { | ||
| 67 | + qaId: '', | ||
| 68 | + qaName: '', | ||
| 69 | + notifyWay: '' | ||
| 70 | + }, | ||
| 71 | + rules: { | ||
| 72 | + notifyWay: [ | ||
| 73 | + { required: true, message: this.$t('questionAnswerManage.validate.notifyWay'), trigger: 'blur' } | ||
| 74 | + ] | ||
| 75 | + } | ||
| 76 | + } | ||
| 77 | + }, | ||
| 78 | + methods: { | ||
| 79 | + open(data) { | ||
| 80 | + this.formData = { | ||
| 81 | + qaId: data.qaId, | ||
| 82 | + qaName: data.qaName, | ||
| 83 | + notifyWay: '' | ||
| 84 | + } | ||
| 85 | + this.visible = true | ||
| 86 | + this.$nextTick(() => { | ||
| 87 | + this.$refs.form && this.$refs.form.clearValidate() | ||
| 88 | + }) | ||
| 89 | + }, | ||
| 90 | + handleClose() { | ||
| 91 | + this.formData = { | ||
| 92 | + qaId: '', | ||
| 93 | + qaName: '', | ||
| 94 | + notifyWay: '' | ||
| 95 | + } | ||
| 96 | + this.loading = false | ||
| 97 | + }, | ||
| 98 | + async handlePublish() { | ||
| 99 | + this.$refs.form.validate(async valid => { | ||
| 100 | + if (!valid) return | ||
| 101 | + | ||
| 102 | + try { | ||
| 103 | + this.loading = true | ||
| 104 | + const params = { | ||
| 105 | + ...this.formData, | ||
| 106 | + communityId: getCommunityId() | ||
| 107 | + } | ||
| 108 | + await publishQuestionAnswer(params) | ||
| 109 | + this.$message.success(this.$t('questionAnswerManage.message.publishSuccess')) | ||
| 110 | + this.visible = false | ||
| 111 | + this.$emit('success') | ||
| 112 | + } catch (error) { | ||
| 113 | + this.$message.error(error.message || this.$t('questionAnswerManage.message.publishError')) | ||
| 114 | + } finally { | ||
| 115 | + this.loading = false | ||
| 116 | + } | ||
| 117 | + }) | ||
| 118 | + } | ||
| 119 | + } | ||
| 120 | +} | ||
| 121 | +</script> | ||
| 0 | \ No newline at end of file | 122 | \ No newline at end of file |
src/components/oa/uploadImageUrl.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="upload-image-container"> | ||
| 3 | + <div v-for="(image, index) in photos" :key="index" class="image-item"> | ||
| 4 | + <el-image | ||
| 5 | + :src="getImageUrl(image)" | ||
| 6 | + fit="cover" | ||
| 7 | + :preview-src-list="[getImageUrl(image)]" | ||
| 8 | + class="image-preview" | ||
| 9 | + > | ||
| 10 | + <div slot="error" class="image-slot"> | ||
| 11 | + <i class="el-icon-picture-outline"></i> | ||
| 12 | + </div> | ||
| 13 | + </el-image> | ||
| 14 | + <i class="el-icon-close remove-icon" @click="removeImage(index)"></i> | ||
| 15 | + </div> | ||
| 16 | + | ||
| 17 | + <el-upload | ||
| 18 | + v-if="photos.length < imageCount" | ||
| 19 | + action="" | ||
| 20 | + :show-file-list="false" | ||
| 21 | + :before-upload="beforeUpload" | ||
| 22 | + :http-request="handleUpload" | ||
| 23 | + class="upload-button" | ||
| 24 | + > | ||
| 25 | + <i class="el-icon-plus"></i> | ||
| 26 | + </el-upload> | ||
| 27 | + </div> | ||
| 28 | +</template> | ||
| 29 | + | ||
| 30 | +<script> | ||
| 31 | +import { uploadImage } from '@/api/oa/questionAnswerManageApi' | ||
| 32 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 33 | + | ||
| 34 | +export default { | ||
| 35 | + name: 'UploadImageUrl', | ||
| 36 | + props: { | ||
| 37 | + imageCount: { | ||
| 38 | + type: Number, | ||
| 39 | + default: 99 | ||
| 40 | + } | ||
| 41 | + }, | ||
| 42 | + data() { | ||
| 43 | + return { | ||
| 44 | + photos: [], | ||
| 45 | + photoUrls: [] | ||
| 46 | + } | ||
| 47 | + }, | ||
| 48 | + methods: { | ||
| 49 | + getImageUrl(image) { | ||
| 50 | + if (typeof image === 'string') { | ||
| 51 | + if (image.startsWith('http') || image.startsWith('https') || image.startsWith('data:')) { | ||
| 52 | + return image | ||
| 53 | + } | ||
| 54 | + return `/callComponent/download/getFile/file?fileId=${image}&communityId=-1&time=${new Date().getTime()}` | ||
| 55 | + } | ||
| 56 | + return image.url || '' | ||
| 57 | + }, | ||
| 58 | + setPhotos(photos) { | ||
| 59 | + this.photos = photos || [] | ||
| 60 | + this.photoUrls = photos.map(photo => { | ||
| 61 | + return typeof photo === 'string' ? { fileId: photo } : photo | ||
| 62 | + }) | ||
| 63 | + this.$emit('change', this.photoUrls) | ||
| 64 | + }, | ||
| 65 | + clear() { | ||
| 66 | + this.photos = [] | ||
| 67 | + this.photoUrls = [] | ||
| 68 | + this.$emit('change', []) | ||
| 69 | + }, | ||
| 70 | + beforeUpload(file) { | ||
| 71 | + const isImage = file.type.includes('image/') | ||
| 72 | + const isLt2M = file.size / 1024 / 1024 < 2 | ||
| 73 | + | ||
| 74 | + if (!isImage) { | ||
| 75 | + this.$message.error(this.$t('uploadImage.validate.imageType')) | ||
| 76 | + } | ||
| 77 | + if (!isLt2M) { | ||
| 78 | + this.$message.error(this.$t('uploadImage.validate.imageSize')) | ||
| 79 | + } | ||
| 80 | + return isImage && isLt2M | ||
| 81 | + }, | ||
| 82 | + async handleUpload({ file }) { | ||
| 83 | + try { | ||
| 84 | + const formData = new FormData() | ||
| 85 | + formData.append('uploadFile', file) | ||
| 86 | + formData.append('communityId', getCommunityId()) | ||
| 87 | + | ||
| 88 | + const response = await uploadImage(formData) | ||
| 89 | + this.photos.push(response.data) | ||
| 90 | + this.photoUrls.push(response.data) | ||
| 91 | + this.$emit('change', this.photoUrls) | ||
| 92 | + } catch (error) { | ||
| 93 | + this.$message.error(error.message || this.$t('uploadImage.message.uploadError')) | ||
| 94 | + } | ||
| 95 | + }, | ||
| 96 | + removeImage(index) { | ||
| 97 | + this.photos.splice(index, 1) | ||
| 98 | + this.photoUrls.splice(index, 1) | ||
| 99 | + this.$emit('change', this.photoUrls) | ||
| 100 | + } | ||
| 101 | + } | ||
| 102 | +} | ||
| 103 | +</script> | ||
| 104 | + | ||
| 105 | +<style lang="scss" scoped> | ||
| 106 | +.upload-image-container { | ||
| 107 | + display: flex; | ||
| 108 | + flex-wrap: wrap; | ||
| 109 | + gap: 10px; | ||
| 110 | + | ||
| 111 | + .image-item { | ||
| 112 | + position: relative; | ||
| 113 | + width: 100px; | ||
| 114 | + height: 100px; | ||
| 115 | + border: 1px dashed #d9d9d9; | ||
| 116 | + border-radius: 6px; | ||
| 117 | + overflow: hidden; | ||
| 118 | + | ||
| 119 | + .image-preview { | ||
| 120 | + width: 100%; | ||
| 121 | + height: 100%; | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + .remove-icon { | ||
| 125 | + position: absolute; | ||
| 126 | + top: 0; | ||
| 127 | + right: 0; | ||
| 128 | + padding: 5px; | ||
| 129 | + color: #fff; | ||
| 130 | + background-color: rgba(0, 0, 0, 0.5); | ||
| 131 | + cursor: pointer; | ||
| 132 | + z-index: 10; | ||
| 133 | + } | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + .upload-button { | ||
| 137 | + display: flex; | ||
| 138 | + justify-content: center; | ||
| 139 | + align-items: center; | ||
| 140 | + width: 100px; | ||
| 141 | + height: 100px; | ||
| 142 | + border: 1px dashed #d9d9d9; | ||
| 143 | + border-radius: 6px; | ||
| 144 | + cursor: pointer; | ||
| 145 | + font-size: 28px; | ||
| 146 | + color: #8c939d; | ||
| 147 | + | ||
| 148 | + &:hover { | ||
| 149 | + border-color: #409eff; | ||
| 150 | + } | ||
| 151 | + } | ||
| 152 | +} | ||
| 153 | +</style> | ||
| 0 | \ No newline at end of file | 154 | \ No newline at end of file |
src/components/room/selectRooms.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-row :gutter="20"> | ||
| 3 | + <el-col :span="6" class="border-right"> | ||
| 4 | + <div class="text-center margin-bottom"> | ||
| 5 | + <span>{{ $t('selectRoom.buildingUnit') }}</span> | ||
| 6 | + </div> | ||
| 7 | + <div class="tree-container"> | ||
| 8 | + <el-tree ref="floorUnitTree" :data="units" :props="treeProps" node-key="id" show-checkbox @check="handleNodeCheck" | ||
| 9 | + :default-expanded-keys="expandedKeys" /> | ||
| 10 | + </div> | ||
| 11 | + </el-col> | ||
| 12 | + <el-col :span="16"> | ||
| 13 | + <div class="text-center margin-bottom"> | ||
| 14 | + <span>{{ $t('selectRoom.roomInfo') }}</span> | ||
| 15 | + </div> | ||
| 16 | + <div class="room-container"> | ||
| 17 | + <el-row :gutter="10"> | ||
| 18 | + <el-col v-for="(item, index) in rooms" :key="index" :span="6" class="margin-bottom"> | ||
| 19 | + <el-checkbox v-model="roomIds" :label="item" @change="handleRoomSelect(item)"> | ||
| 20 | + {{ item.floorNum }}-{{ item.unitNum }}-{{ item.roomNum }}({{ item.stateName }}) | ||
| 21 | + </el-checkbox> | ||
| 22 | + </el-col> | ||
| 23 | + </el-row> | ||
| 24 | + </div> | ||
| 25 | + </el-col> | ||
| 26 | + </el-row> | ||
| 27 | +</template> | ||
| 28 | + | ||
| 29 | +<script> | ||
| 30 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 31 | +import { queryFloorAndUnits, queryRooms } from '@/api/oa/addQuestionAnswerApi' | ||
| 32 | + | ||
| 33 | +export default { | ||
| 34 | + name: 'SelectRooms', | ||
| 35 | + props: { | ||
| 36 | + emitSelectRooms: { | ||
| 37 | + type: String, | ||
| 38 | + default: '' | ||
| 39 | + } | ||
| 40 | + }, | ||
| 41 | + data() { | ||
| 42 | + return { | ||
| 43 | + units: [], | ||
| 44 | + rooms: [], | ||
| 45 | + roomIds: [], | ||
| 46 | + conditions: { | ||
| 47 | + floorId: '', | ||
| 48 | + unitId: '', | ||
| 49 | + communityId: getCommunityId() | ||
| 50 | + }, | ||
| 51 | + treeProps: { | ||
| 52 | + label: 'text', | ||
| 53 | + children: 'children' | ||
| 54 | + }, | ||
| 55 | + expandedKeys: [] | ||
| 56 | + } | ||
| 57 | + }, | ||
| 58 | + created() { | ||
| 59 | + this.loadFloorAndUnits() | ||
| 60 | + }, | ||
| 61 | + methods: { | ||
| 62 | + open() { | ||
| 63 | + this.loadFloorAndUnits() | ||
| 64 | + }, | ||
| 65 | + async loadFloorAndUnits() { | ||
| 66 | + try { | ||
| 67 | + const res = await queryFloorAndUnits({ | ||
| 68 | + communityId: this.conditions.communityId | ||
| 69 | + }) | ||
| 70 | + this.units = this.formatTreeData(res) | ||
| 71 | + } catch (error) { | ||
| 72 | + console.log(error) | ||
| 73 | + this.$message.error(this.$t('selectRoom.loadError')) | ||
| 74 | + } | ||
| 75 | + }, | ||
| 76 | + formatTreeData(units) { | ||
| 77 | + const floorMap = {} | ||
| 78 | + | ||
| 79 | + units.forEach(unit => { | ||
| 80 | + if (!floorMap[unit.floorId]) { | ||
| 81 | + floorMap[unit.floorId] = { | ||
| 82 | + id: `f_${unit.floorId}`, | ||
| 83 | + floorId: unit.floorId, | ||
| 84 | + floorNum: unit.floorNum, | ||
| 85 | + icon: "/img/floor.png", | ||
| 86 | + text: `${unit.floorNum}${this.$t('room.floorUnitTree.building')}`, | ||
| 87 | + children: [] | ||
| 88 | + } | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + const unitNode = { | ||
| 92 | + id: `u_${unit.unitId}`, | ||
| 93 | + unitId: unit.unitId, | ||
| 94 | + text: `${unit.unitNum}${this.$t('room.floorUnitTree.unit')}`, | ||
| 95 | + icon: "/img/unit.png", | ||
| 96 | + children: [] | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + floorMap[unit.floorId].children.push(unitNode) | ||
| 100 | + }) | ||
| 101 | + | ||
| 102 | + return Object.values(floorMap) | ||
| 103 | + }, | ||
| 104 | + async listRooms() { | ||
| 105 | + try { | ||
| 106 | + const params = { | ||
| 107 | + ...this.conditions, | ||
| 108 | + page: 1, | ||
| 109 | + row: 500 | ||
| 110 | + } | ||
| 111 | + const res = await queryRooms(params) | ||
| 112 | + this.rooms = res.rooms | ||
| 113 | + } catch (error) { | ||
| 114 | + this.$message.error(this.$t('selectRoom.loadRoomError')) | ||
| 115 | + } | ||
| 116 | + }, | ||
| 117 | + handleNodeCheck(data, { checkedNodes }) { | ||
| 118 | + if (data.id.startsWith('f_')) { | ||
| 119 | + this.conditions.floorId = checkedNodes.some(node => node.id === data.id) ? data.floorId : '' | ||
| 120 | + } else if (data.id.startsWith('u_')) { | ||
| 121 | + this.conditions.unitId = checkedNodes.some(node => node.id === data.id) ? data.unitId : '' | ||
| 122 | + } | ||
| 123 | + this.listRooms() | ||
| 124 | + }, | ||
| 125 | + handleRoomSelect(room) { | ||
| 126 | + console.log('选择房间', room) | ||
| 127 | + this.$emit('notifySelectRooms', this.roomIds) | ||
| 128 | + }, | ||
| 129 | + refreshTree(params) { | ||
| 130 | + if (params) { | ||
| 131 | + this.conditions.floorId = params.floorId || '' | ||
| 132 | + } | ||
| 133 | + this.loadFloorAndUnits() | ||
| 134 | + } | ||
| 135 | + } | ||
| 136 | +} | ||
| 137 | +</script> | ||
| 138 | + | ||
| 139 | +<style scoped> | ||
| 140 | +.border-right { | ||
| 141 | + border-right: 1px solid #ebeef5; | ||
| 142 | +} | ||
| 143 | + | ||
| 144 | +.tree-container { | ||
| 145 | + height: 300px; | ||
| 146 | + overflow-y: auto; | ||
| 147 | +} | ||
| 148 | + | ||
| 149 | +.room-container { | ||
| 150 | + height: 300px; | ||
| 151 | + overflow-y: auto; | ||
| 152 | +} | ||
| 153 | + | ||
| 154 | +.margin-bottom { | ||
| 155 | + margin-bottom: 10px; | ||
| 156 | +} | ||
| 157 | + | ||
| 158 | +.text-center { | ||
| 159 | + text-align: center; | ||
| 160 | + padding: 10px 0; | ||
| 161 | +} | ||
| 162 | +</style> | ||
| 0 | \ No newline at end of file | 163 | \ No newline at end of file |
src/i18n/oaI18n.js
| @@ -9,7 +9,14 @@ import { messages as addComplaintTypeMessages } from '../views/oa/addComplaintTy | @@ -9,7 +9,14 @@ import { messages as addComplaintTypeMessages } from '../views/oa/addComplaintTy | ||
| 9 | import { messages as editComplaintTypeMessages } from '../views/oa/editComplaintTypeLang' | 9 | import { messages as editComplaintTypeMessages } from '../views/oa/editComplaintTypeLang' |
| 10 | import { messages as addComplaintMessages } from '../views/oa/addComplaintLang' | 10 | import { messages as addComplaintMessages } from '../views/oa/addComplaintLang' |
| 11 | import { messages as complaintMessages } from '../views/oa/complaintLang' | 11 | import { messages as complaintMessages } from '../views/oa/complaintLang' |
| 12 | - | 12 | +import { messages as notepadManageMessages } from '../views/oa/notepadManageLang' |
| 13 | +import { messages as visitManageMessages } from '../views/oa/visitManageLang' | ||
| 14 | +import { messages as questionTitleMessages } from '../views/oa/questionTitleLang' | ||
| 15 | +import { messages as questionAnswerManageMessages } from '../views/oa/questionAnswerManageLang' | ||
| 16 | +import { messages as printQuestionAnswerMessages } from '../views/oa/printQuestionAnswerLang' | ||
| 17 | +import { messages as addQuestionAnswerMessages } from '../views/oa/addQuestionAnswerLang' | ||
| 18 | +import { messages as editQuestionAnswerMessages } from '../views/oa/editQuestionAnswerLang' | ||
| 19 | +import { messages as printQuestionAnswerDetailMessages } from '../views/oa/printQuestionAnswerDetailLang' | ||
| 13 | export const messages ={ | 20 | export const messages ={ |
| 14 | en:{ | 21 | en:{ |
| 15 | ...activitiesTypeManageMessages.en, | 22 | ...activitiesTypeManageMessages.en, |
| @@ -23,6 +30,14 @@ export const messages ={ | @@ -23,6 +30,14 @@ export const messages ={ | ||
| 23 | ...editComplaintTypeMessages.en, | 30 | ...editComplaintTypeMessages.en, |
| 24 | ...addComplaintMessages.en, | 31 | ...addComplaintMessages.en, |
| 25 | ...complaintMessages.en, | 32 | ...complaintMessages.en, |
| 33 | + ...notepadManageMessages.en, | ||
| 34 | + ...visitManageMessages.en, | ||
| 35 | + ...questionTitleMessages.en, | ||
| 36 | + ...questionAnswerManageMessages.en, | ||
| 37 | + ...printQuestionAnswerMessages.en, | ||
| 38 | + ...addQuestionAnswerMessages.en, | ||
| 39 | + ...editQuestionAnswerMessages.en, | ||
| 40 | + ...printQuestionAnswerDetailMessages.en, | ||
| 26 | }, | 41 | }, |
| 27 | zh:{ | 42 | zh:{ |
| 28 | ...activitiesTypeManageMessages.zh, | 43 | ...activitiesTypeManageMessages.zh, |
| @@ -36,5 +51,13 @@ export const messages ={ | @@ -36,5 +51,13 @@ export const messages ={ | ||
| 36 | ...editComplaintTypeMessages.zh, | 51 | ...editComplaintTypeMessages.zh, |
| 37 | ...addComplaintMessages.zh, | 52 | ...addComplaintMessages.zh, |
| 38 | ...complaintMessages.zh, | 53 | ...complaintMessages.zh, |
| 54 | + ...notepadManageMessages.zh, | ||
| 55 | + ...visitManageMessages.zh, | ||
| 56 | + ...questionTitleMessages.zh, | ||
| 57 | + ...questionAnswerManageMessages.zh, | ||
| 58 | + ...printQuestionAnswerMessages.zh, | ||
| 59 | + ...addQuestionAnswerMessages.zh, | ||
| 60 | + ...editQuestionAnswerMessages.zh, | ||
| 61 | + ...printQuestionAnswerDetailMessages.zh, | ||
| 39 | } | 62 | } |
| 40 | } | 63 | } |
| 41 | \ No newline at end of file | 64 | \ No newline at end of file |
src/router/index.js
| @@ -330,7 +330,7 @@ const routes = [ | @@ -330,7 +330,7 @@ const routes = [ | ||
| 330 | name: '/views/work/adminRepairDetail', | 330 | name: '/views/work/adminRepairDetail', |
| 331 | component: () => import('@/views/work/adminRepairDetailList.vue') | 331 | component: () => import('@/views/work/adminRepairDetailList.vue') |
| 332 | }, | 332 | }, |
| 333 | - | 333 | + |
| 334 | { | 334 | { |
| 335 | path: '/pages/complaint/adminComplaint', | 335 | path: '/pages/complaint/adminComplaint', |
| 336 | name: '/pages/complaint/adminComplaint', | 336 | name: '/pages/complaint/adminComplaint', |
| @@ -361,7 +361,7 @@ const routes = [ | @@ -361,7 +361,7 @@ const routes = [ | ||
| 361 | name: '/pages/iot/adminBarrier', | 361 | name: '/pages/iot/adminBarrier', |
| 362 | component: () => import('@/views/iot/adminBarrierList.vue') | 362 | component: () => import('@/views/iot/adminBarrierList.vue') |
| 363 | }, | 363 | }, |
| 364 | - | 364 | + |
| 365 | { | 365 | { |
| 366 | path: '/pages/iot/adminMeter', | 366 | path: '/pages/iot/adminMeter', |
| 367 | name: '/pages/iot/adminMeter', | 367 | name: '/pages/iot/adminMeter', |
| @@ -822,7 +822,7 @@ const routes = [ | @@ -822,7 +822,7 @@ const routes = [ | ||
| 822 | name: '/pages/property/repairForceFinishManage', | 822 | name: '/pages/property/repairForceFinishManage', |
| 823 | component: () => import('@/views/work/repairForceFinishManageList.vue') | 823 | component: () => import('@/views/work/repairForceFinishManageList.vue') |
| 824 | }, | 824 | }, |
| 825 | - | 825 | + |
| 826 | { | 826 | { |
| 827 | path: '/pages/resource/resourceAuditFlow', | 827 | path: '/pages/resource/resourceAuditFlow', |
| 828 | name: '/pages/resource/resourceAuditFlow', | 828 | name: '/pages/resource/resourceAuditFlow', |
| @@ -843,7 +843,7 @@ const routes = [ | @@ -843,7 +843,7 @@ const routes = [ | ||
| 843 | name: '/pages/common/resourceStoreManage', | 843 | name: '/pages/common/resourceStoreManage', |
| 844 | component: () => import('@/views/resource/resourceStoreManageList.vue') | 844 | component: () => import('@/views/resource/resourceStoreManageList.vue') |
| 845 | }, | 845 | }, |
| 846 | - | 846 | + |
| 847 | { | 847 | { |
| 848 | path: '/pages/property/resourceSupplierManage', | 848 | path: '/pages/property/resourceSupplierManage', |
| 849 | name: '/pages/property/resourceSupplierManage', | 849 | name: '/pages/property/resourceSupplierManage', |
| @@ -924,7 +924,7 @@ const routes = [ | @@ -924,7 +924,7 @@ const routes = [ | ||
| 924 | name: '/pages/property/locationManage', | 924 | name: '/pages/property/locationManage', |
| 925 | component: () => import('@/views/community/locationManageList.vue') | 925 | component: () => import('@/views/community/locationManageList.vue') |
| 926 | }, | 926 | }, |
| 927 | - | 927 | + |
| 928 | ...inspectionRouter, | 928 | ...inspectionRouter, |
| 929 | ...machineRouter, | 929 | ...machineRouter, |
| 930 | ...oaRouter, | 930 | ...oaRouter, |
| @@ -945,6 +945,16 @@ const routes = [ | @@ -945,6 +945,16 @@ const routes = [ | ||
| 945 | name: '/views/resource/printEquipmentAccountLabel', | 945 | name: '/views/resource/printEquipmentAccountLabel', |
| 946 | component: printEquipmentAccountLabel | 946 | component: printEquipmentAccountLabel |
| 947 | }, | 947 | }, |
| 948 | + { | ||
| 949 | + path: '/pages/question/printQuestionAnswer', | ||
| 950 | + name: '/pages/question/printQuestionAnswer', | ||
| 951 | + component: () => import('@/views/oa/printQuestionAnswerList.vue') | ||
| 952 | + }, | ||
| 953 | + { | ||
| 954 | + path: '/pages/question/printQuestionAnswerDetail', | ||
| 955 | + name: '/pages/question/printQuestionAnswerDetail', | ||
| 956 | + component: () => import('@/views/oa/printQuestionAnswerDetailList.vue') | ||
| 957 | + }, | ||
| 948 | ] | 958 | ] |
| 949 | 959 | ||
| 950 | const router = new VueRouter({ | 960 | const router = new VueRouter({ |
src/router/oaRouter.js
| @@ -54,4 +54,35 @@ export default [ | @@ -54,4 +54,35 @@ export default [ | ||
| 54 | name: '/pages/complaint/complaint', | 54 | name: '/pages/complaint/complaint', |
| 55 | component: () => import('@/views/oa/complaintList.vue') | 55 | component: () => import('@/views/oa/complaintList.vue') |
| 56 | }, | 56 | }, |
| 57 | + { | ||
| 58 | + path: '/pages/property/notepadManage', | ||
| 59 | + name: '/pages/property/notepadManage', | ||
| 60 | + component: () => import('@/views/oa/notepadManageList.vue') | ||
| 61 | + }, | ||
| 62 | + { | ||
| 63 | + path: '/pages/property/visitManage', | ||
| 64 | + name: '/pages/property/visitManage', | ||
| 65 | + component: () => import('@/views/oa/visitManageList.vue') | ||
| 66 | + }, | ||
| 67 | + { | ||
| 68 | + path: '/pages/question/questionTitle', | ||
| 69 | + name: '/pages/question/questionTitle', | ||
| 70 | + component: () => import('@/views/oa/questionTitleList.vue') | ||
| 71 | + }, | ||
| 72 | + { | ||
| 73 | + path: '/pages/property/questionAnswerManage', | ||
| 74 | + name: '/pages/property/questionAnswerManage', | ||
| 75 | + component: () => import('@/views/oa/questionAnswerManageList.vue') | ||
| 76 | + }, | ||
| 77 | + { | ||
| 78 | + path: '/views/oa/addQuestionAnswer', | ||
| 79 | + name: '/views/oa/addQuestionAnswer', | ||
| 80 | + component: () => import('@/views/oa/addQuestionAnswerList.vue') | ||
| 81 | + }, | ||
| 82 | + { | ||
| 83 | + path:'/views/oa/editQuestionAnswer', | ||
| 84 | + name:'/views/oa/editQuestionAnswer', | ||
| 85 | + component: () => import('@/views/oa/editQuestionAnswerList.vue') | ||
| 86 | + }, | ||
| 87 | + | ||
| 57 | ] | 88 | ] |
| 58 | \ No newline at end of file | 89 | \ No newline at end of file |
src/views/oa/addQuestionAnswerLang.js
0 → 100644
| 1 | +export const messages = { | ||
| 2 | + en: { | ||
| 3 | + addQuestionAnswer: { | ||
| 4 | + title: 'Add Questionnaire', | ||
| 5 | + qaName: 'Questionnaire Name', | ||
| 6 | + qaNamePlaceholder: 'Required, please fill in the questionnaire name', | ||
| 7 | + startTime: 'Start Time', | ||
| 8 | + startTimePlaceholder: 'Required, please select start time', | ||
| 9 | + endTime: 'End Time', | ||
| 10 | + endTimePlaceholder: 'Required, please select end time', | ||
| 11 | + content: 'Questionnaire Description', | ||
| 12 | + contentPlaceholder: 'Required, please enter questionnaire description', | ||
| 13 | + questionTitle: 'Questionnaire Questions', | ||
| 14 | + chooseTitle: 'Select Questions', | ||
| 15 | + questionRoom: 'Questionnaire Rooms', | ||
| 16 | + qaNameRequired: 'Questionnaire name is required', | ||
| 17 | + startTimeRequired: 'Start time is required', | ||
| 18 | + endTimeRequired: 'End time is required', | ||
| 19 | + timeInvalid: 'End time must be later than start time', | ||
| 20 | + contentRequired: 'Questionnaire description is required', | ||
| 21 | + titleRequired: 'Please select at least one question', | ||
| 22 | + roomRequired: 'Please select at least one room', | ||
| 23 | + titleExist: 'This question has already been selected', | ||
| 24 | + confirmDeleteTitle: 'Are you sure to delete this question?', | ||
| 25 | + saveSuccess: 'Questionnaire saved successfully', | ||
| 26 | + saveError: 'Failed to save questionnaire' | ||
| 27 | + }, | ||
| 28 | + questionTitle: { | ||
| 29 | + name: 'Name', | ||
| 30 | + type: 'Type', | ||
| 31 | + options: 'Options', | ||
| 32 | + operation: 'Operation', | ||
| 33 | + delete: 'Delete', | ||
| 34 | + createTime: 'Create Time', | ||
| 35 | + singleChoice: 'Single Choice', | ||
| 36 | + multipleChoice: 'Multiple Choice', | ||
| 37 | + shortAnswer: 'Short Answer' | ||
| 38 | + }, | ||
| 39 | + selectRoom: { | ||
| 40 | + buildingUnit: 'Building Unit', | ||
| 41 | + roomInfo: 'Room Information', | ||
| 42 | + unit: 'Unit', | ||
| 43 | + loadError: 'Failed to load building units', | ||
| 44 | + loadRoomError: 'Failed to load rooms' | ||
| 45 | + }, | ||
| 46 | + chooseQuestionTitle: { | ||
| 47 | + title: 'Select Questions', | ||
| 48 | + searchPlaceholder: 'Enter question name', | ||
| 49 | + question: 'Question', | ||
| 50 | + operation: 'Operation', | ||
| 51 | + choose: 'Choose', | ||
| 52 | + queryError: 'Failed to query questions' | ||
| 53 | + } | ||
| 54 | + }, | ||
| 55 | + zh: { | ||
| 56 | + addQuestionAnswer: { | ||
| 57 | + title: '添加问卷', | ||
| 58 | + qaName: '问卷名称', | ||
| 59 | + qaNamePlaceholder: '必填,请填写问卷名称', | ||
| 60 | + startTime: '开始时间', | ||
| 61 | + startTimePlaceholder: '必填,请选择开始时间', | ||
| 62 | + endTime: '结束时间', | ||
| 63 | + endTimePlaceholder: '必填,请选择结束时间', | ||
| 64 | + content: '问卷说明', | ||
| 65 | + contentPlaceholder: '必填,请输入问卷说明', | ||
| 66 | + questionTitle: '问卷题目', | ||
| 67 | + chooseTitle: '选择题目', | ||
| 68 | + questionRoom: '问卷房屋', | ||
| 69 | + qaNameRequired: '问卷名称不能为空', | ||
| 70 | + startTimeRequired: '开始时间不能为空', | ||
| 71 | + endTimeRequired: '结束时间不能为空', | ||
| 72 | + timeInvalid: '结束时间必须晚于开始时间', | ||
| 73 | + contentRequired: '问卷说明不能为空', | ||
| 74 | + titleRequired: '请至少选择一个题目', | ||
| 75 | + roomRequired: '请至少选择一间房屋', | ||
| 76 | + titleExist: '该题目已被选择', | ||
| 77 | + confirmDeleteTitle: '确定删除该题目吗?', | ||
| 78 | + saveSuccess: '问卷保存成功', | ||
| 79 | + saveError: '问卷保存失败' | ||
| 80 | + }, | ||
| 81 | + questionTitle: { | ||
| 82 | + name: '名称', | ||
| 83 | + type: '类型', | ||
| 84 | + options: '选项', | ||
| 85 | + operation: '操作', | ||
| 86 | + delete: '删除', | ||
| 87 | + createTime: '创建时间', | ||
| 88 | + singleChoice: '单选', | ||
| 89 | + multipleChoice: '多选', | ||
| 90 | + shortAnswer: '简答' | ||
| 91 | + }, | ||
| 92 | + selectRoom: { | ||
| 93 | + buildingUnit: '楼栋单元', | ||
| 94 | + roomInfo: '房屋信息', | ||
| 95 | + unit: '单元', | ||
| 96 | + loadError: '加载楼栋单元失败', | ||
| 97 | + loadRoomError: '加载房屋信息失败' | ||
| 98 | + }, | ||
| 99 | + chooseQuestionTitle: { | ||
| 100 | + title: '选择题目', | ||
| 101 | + searchPlaceholder: '输入题目名称', | ||
| 102 | + question: '题目', | ||
| 103 | + operation: '操作', | ||
| 104 | + choose: '选择', | ||
| 105 | + queryError: '查询题目失败' | ||
| 106 | + } | ||
| 107 | + } | ||
| 108 | +} | ||
| 0 | \ No newline at end of file | 109 | \ No newline at end of file |
src/views/oa/addQuestionAnswerList.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="add-question-answer-container"> | ||
| 3 | + <el-card class="box-card"> | ||
| 4 | + <div slot="header" class="flex justify-between"> | ||
| 5 | + <span>{{ $t('addQuestionAnswer.title') }}</span> | ||
| 6 | + </div> | ||
| 7 | + <el-row :gutter="20"> | ||
| 8 | + <el-col :span="24"> | ||
| 9 | + <el-form ref="form" :model="addQuestionAnswerInfo" label-width="120px"> | ||
| 10 | + <el-row> | ||
| 11 | + <el-col :span="12"> | ||
| 12 | + <el-form-item :label="$t('addQuestionAnswer.qaName')" prop="qaName"> | ||
| 13 | + <el-input v-model="addQuestionAnswerInfo.qaName" | ||
| 14 | + :placeholder="$t('addQuestionAnswer.qaNamePlaceholder')" /> | ||
| 15 | + </el-form-item> | ||
| 16 | + </el-col> | ||
| 17 | + <el-col :span="12"> | ||
| 18 | + <el-form-item :label="$t('addQuestionAnswer.startTime')" prop="startTime"> | ||
| 19 | + <el-date-picker v-model="addQuestionAnswerInfo.startTime" type="datetime" | ||
| 20 | + :placeholder="$t('addQuestionAnswer.startTimePlaceholder')" value-format="yyyy-MM-dd HH:mm:ss" | ||
| 21 | + style="width: 100%" /> | ||
| 22 | + </el-form-item> | ||
| 23 | + </el-col> | ||
| 24 | + </el-row> | ||
| 25 | + <el-row> | ||
| 26 | + <el-col :span="12"> | ||
| 27 | + <el-form-item :label="$t('addQuestionAnswer.endTime')" prop="endTime"> | ||
| 28 | + <el-date-picker v-model="addQuestionAnswerInfo.endTime" type="datetime" | ||
| 29 | + :placeholder="$t('addQuestionAnswer.endTimePlaceholder')" value-format="yyyy-MM-dd HH:mm:ss" | ||
| 30 | + style="width: 100%" /> | ||
| 31 | + </el-form-item> | ||
| 32 | + </el-col> | ||
| 33 | + </el-row> | ||
| 34 | + <el-row> | ||
| 35 | + <el-col :span="24"> | ||
| 36 | + <el-form-item :label="$t('addQuestionAnswer.content')"> | ||
| 37 | + <el-input v-model="addQuestionAnswerInfo.content" type="textarea" :rows="5" | ||
| 38 | + :placeholder="$t('addQuestionAnswer.contentPlaceholder')" /> | ||
| 39 | + </el-form-item> | ||
| 40 | + </el-col> | ||
| 41 | + </el-row> | ||
| 42 | + </el-form> | ||
| 43 | + </el-col> | ||
| 44 | + </el-row> | ||
| 45 | + </el-card> | ||
| 46 | + | ||
| 47 | + <el-card class="box-card margin-top"> | ||
| 48 | + <div slot="header" class="flex justify-between"> | ||
| 49 | + <span>{{ $t('addQuestionAnswer.questionTitle') }}</span> | ||
| 50 | + <el-button type="primary" class="float-right" @click="chooseTitle"> | ||
| 51 | + <i class="el-icon-search"></i>{{ $t('addQuestionAnswer.chooseTitle') }} | ||
| 52 | + </el-button> | ||
| 53 | + </div> | ||
| 54 | + <el-table :data="addQuestionAnswerInfo.questionTitles" border style="width: 100%"> | ||
| 55 | + <el-table-column prop="qaTitle" :label="$t('questionTitle.name')" align="center" /> | ||
| 56 | + <el-table-column prop="titleType" :label="$t('questionTitle.type')" align="center"> | ||
| 57 | + <template slot-scope="scope"> | ||
| 58 | + {{ getTitleTypeName(scope.row.titleType) }} | ||
| 59 | + </template> | ||
| 60 | + </el-table-column> | ||
| 61 | + <el-table-column :label="$t('questionTitle.options')" align="center"> | ||
| 62 | + <template slot-scope="scope"> | ||
| 63 | + <div v-for="(item, index) in scope.row.titleValues" :key="index"> | ||
| 64 | + {{ item.seq }}、{{ item.qaValue }} | ||
| 65 | + </div> | ||
| 66 | + </template> | ||
| 67 | + </el-table-column> | ||
| 68 | + <el-table-column :label="$t('questionTitle.operation')" align="center" width="150"> | ||
| 69 | + <template slot-scope="scope"> | ||
| 70 | + <el-button type="danger" size="mini" @click="openDeleteQuestionTitle(scope.row)"> | ||
| 71 | + {{ $t('questionTitle.delete') }} | ||
| 72 | + </el-button> | ||
| 73 | + </template> | ||
| 74 | + </el-table-column> | ||
| 75 | + </el-table> | ||
| 76 | + </el-card> | ||
| 77 | + | ||
| 78 | + <el-card class="box-card margin-top"> | ||
| 79 | + <div slot="header" class="flex justify-between"> | ||
| 80 | + <span>{{ $t('addQuestionAnswer.questionRoom') }}</span> | ||
| 81 | + </div> | ||
| 82 | + <el-row> | ||
| 83 | + <el-col :span="24"> | ||
| 84 | + <el-form> | ||
| 85 | + <el-form-item :label="$t('addQuestionAnswer.questionRoom')"> | ||
| 86 | + <select-rooms ref="selectRooms" @notifySelectRooms="handleSelectRooms" /> | ||
| 87 | + </el-form-item> | ||
| 88 | + </el-form> | ||
| 89 | + </el-col> | ||
| 90 | + </el-row> | ||
| 91 | + </el-card> | ||
| 92 | + | ||
| 93 | + <div class="action-buttons margin-top"> | ||
| 94 | + <el-button type="primary" @click="saveQuestionAnswer"> | ||
| 95 | + <i class="el-icon-check"></i>{{ $t('common.save') }} | ||
| 96 | + </el-button> | ||
| 97 | + <el-button type="warning" @click="goBack"> | ||
| 98 | + {{ $t('common.cancel') }} | ||
| 99 | + </el-button> | ||
| 100 | + </div> | ||
| 101 | + | ||
| 102 | + <choose-question-title ref="chooseQuestionTitle" @chooseQuestionTitle="handleChooseQuestionTitle" /> | ||
| 103 | + </div> | ||
| 104 | +</template> | ||
| 105 | + | ||
| 106 | +<script> | ||
| 107 | +import SelectRooms from '@/components/room/selectRooms' | ||
| 108 | +import ChooseQuestionTitle from '@/components/oa/chooseQuestionTitle' | ||
| 109 | +import { saveQuestionAnswer } from '@/api/oa/addQuestionAnswerApi' | ||
| 110 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 111 | + | ||
| 112 | +export default { | ||
| 113 | + name: 'AddQuestionAnswer', | ||
| 114 | + components: { | ||
| 115 | + SelectRooms, | ||
| 116 | + ChooseQuestionTitle | ||
| 117 | + }, | ||
| 118 | + data() { | ||
| 119 | + return { | ||
| 120 | + addQuestionAnswerInfo: { | ||
| 121 | + qaName: '', | ||
| 122 | + startTime: '', | ||
| 123 | + endTime: '', | ||
| 124 | + communityId: '', | ||
| 125 | + content: '', | ||
| 126 | + questionTitles: [], | ||
| 127 | + roomIds: [] | ||
| 128 | + } | ||
| 129 | + } | ||
| 130 | + }, | ||
| 131 | + created() { | ||
| 132 | + this.addQuestionAnswerInfo.communityId = getCommunityId() | ||
| 133 | + }, | ||
| 134 | + methods: { | ||
| 135 | + getTitleTypeName(titleType) { | ||
| 136 | + if (titleType === '1001') { | ||
| 137 | + return this.$t('questionTitle.singleChoice') | ||
| 138 | + } else if (titleType === '2002') { | ||
| 139 | + return this.$t('questionTitle.multipleChoice') | ||
| 140 | + } else { | ||
| 141 | + return this.$t('questionTitle.shortAnswer') | ||
| 142 | + } | ||
| 143 | + }, | ||
| 144 | + chooseTitle() { | ||
| 145 | + this.$refs.chooseQuestionTitle.open() | ||
| 146 | + }, | ||
| 147 | + handleChooseQuestionTitle(questionTitle) { | ||
| 148 | + const hasTitle = this.addQuestionAnswerInfo.questionTitles.some( | ||
| 149 | + item => item.titleId === questionTitle.titleId | ||
| 150 | + ) | ||
| 151 | + if (hasTitle) { | ||
| 152 | + this.$message.warning(this.$t('addQuestionAnswer.titleExist')) | ||
| 153 | + return | ||
| 154 | + } | ||
| 155 | + this.addQuestionAnswerInfo.questionTitles.push(questionTitle) | ||
| 156 | + }, | ||
| 157 | + openDeleteQuestionTitle(title) { | ||
| 158 | + this.$confirm( | ||
| 159 | + this.$t('addQuestionAnswer.confirmDeleteTitle'), | ||
| 160 | + this.$t('common.tip'), | ||
| 161 | + { | ||
| 162 | + confirmButtonText: this.$t('common.confirm'), | ||
| 163 | + cancelButtonText: this.$t('common.cancel'), | ||
| 164 | + type: 'warning' | ||
| 165 | + } | ||
| 166 | + ).then(() => { | ||
| 167 | + this.addQuestionAnswerInfo.questionTitles = this.addQuestionAnswerInfo.questionTitles.filter( | ||
| 168 | + item => item.titleId !== title.titleId | ||
| 169 | + ) | ||
| 170 | + }) | ||
| 171 | + }, | ||
| 172 | + handleSelectRooms(rooms) { | ||
| 173 | + this.addQuestionAnswerInfo.roomIds = rooms.map(item => item.roomId) | ||
| 174 | + }, | ||
| 175 | + validateForm() { | ||
| 176 | + if (!this.addQuestionAnswerInfo.qaName) { | ||
| 177 | + this.$message.warning(this.$t('addQuestionAnswer.qaNameRequired')) | ||
| 178 | + return false | ||
| 179 | + } | ||
| 180 | + if (!this.addQuestionAnswerInfo.startTime) { | ||
| 181 | + this.$message.warning(this.$t('addQuestionAnswer.startTimeRequired')) | ||
| 182 | + return false | ||
| 183 | + } | ||
| 184 | + if (!this.addQuestionAnswerInfo.endTime) { | ||
| 185 | + this.$message.warning(this.$t('addQuestionAnswer.endTimeRequired')) | ||
| 186 | + return false | ||
| 187 | + } | ||
| 188 | + if (this.addQuestionAnswerInfo.startTime >= this.addQuestionAnswerInfo.endTime) { | ||
| 189 | + this.$message.warning(this.$t('addQuestionAnswer.timeInvalid')) | ||
| 190 | + return false | ||
| 191 | + } | ||
| 192 | + if (!this.addQuestionAnswerInfo.content) { | ||
| 193 | + this.$message.warning(this.$t('addQuestionAnswer.contentRequired')) | ||
| 194 | + return false | ||
| 195 | + } | ||
| 196 | + if (this.addQuestionAnswerInfo.questionTitles.length === 0) { | ||
| 197 | + this.$message.warning(this.$t('addQuestionAnswer.titleRequired')) | ||
| 198 | + return false | ||
| 199 | + } | ||
| 200 | + if (this.addQuestionAnswerInfo.roomIds.length === 0) { | ||
| 201 | + this.$message.warning(this.$t('addQuestionAnswer.roomRequired')) | ||
| 202 | + return false | ||
| 203 | + } | ||
| 204 | + return true | ||
| 205 | + }, | ||
| 206 | + async saveQuestionAnswer() { | ||
| 207 | + if (!this.validateForm()) return | ||
| 208 | + | ||
| 209 | + try { | ||
| 210 | + const res = await saveQuestionAnswer(this.addQuestionAnswerInfo) | ||
| 211 | + if (res.code === 0) { | ||
| 212 | + this.$message.success(this.$t('addQuestionAnswer.saveSuccess')) | ||
| 213 | + this.goBack() | ||
| 214 | + } else { | ||
| 215 | + this.$message.error(res.msg) | ||
| 216 | + } | ||
| 217 | + } catch (error) { | ||
| 218 | + this.$message.error(this.$t('addQuestionAnswer.saveError')) | ||
| 219 | + } | ||
| 220 | + }, | ||
| 221 | + goBack() { | ||
| 222 | + this.$router.go(-1) | ||
| 223 | + } | ||
| 224 | + } | ||
| 225 | +} | ||
| 226 | +</script> | ||
| 227 | + | ||
| 228 | +<style lang="scss" scoped> | ||
| 229 | +.add-question-answer-container { | ||
| 230 | + padding: 20px; | ||
| 231 | + | ||
| 232 | + .box-card { | ||
| 233 | + margin-bottom: 20px; | ||
| 234 | + } | ||
| 235 | + | ||
| 236 | + .margin-top { | ||
| 237 | + margin-top: 20px; | ||
| 238 | + } | ||
| 239 | + | ||
| 240 | + .float-right { | ||
| 241 | + float: right; | ||
| 242 | + } | ||
| 243 | + | ||
| 244 | + .action-buttons { | ||
| 245 | + text-align: right; | ||
| 246 | + margin-top: 20px; | ||
| 247 | + padding: 20px; | ||
| 248 | + background: #fff; | ||
| 249 | + border-radius: 4px; | ||
| 250 | + } | ||
| 251 | +} | ||
| 252 | +</style> | ||
| 0 | \ No newline at end of file | 253 | \ No newline at end of file |
src/views/oa/editQuestionAnswerLang.js
0 → 100644
| 1 | +export const messages = { | ||
| 2 | + en: { | ||
| 3 | + editQuestionAnswer: { | ||
| 4 | + title: 'Edit Questionnaire', | ||
| 5 | + qaName: 'Questionnaire Name', | ||
| 6 | + qaNamePlaceholder: 'Required, please enter questionnaire name', | ||
| 7 | + startTime: 'Start Time', | ||
| 8 | + startTimePlaceholder: 'Required, please select start time', | ||
| 9 | + endTime: 'End Time', | ||
| 10 | + endTimePlaceholder: 'Required, please select end time', | ||
| 11 | + content: 'Questionnaire Description', | ||
| 12 | + contentPlaceholder: 'Required, please enter questionnaire description', | ||
| 13 | + questionTitle: 'Questionnaire Questions', | ||
| 14 | + chooseTitle: 'Select Questions', | ||
| 15 | + questionRooms: 'Questionnaire Rooms', | ||
| 16 | + household: 'households', | ||
| 17 | + reselect: 'Reselect', | ||
| 18 | + save: 'Save', | ||
| 19 | + cancel: 'Cancel', | ||
| 20 | + table: { | ||
| 21 | + name: 'Name', | ||
| 22 | + type: 'Type', | ||
| 23 | + options: 'Options', | ||
| 24 | + actions: 'Actions', | ||
| 25 | + delete: 'Delete' | ||
| 26 | + }, | ||
| 27 | + singleChoice: 'Single Choice', | ||
| 28 | + multipleChoice: 'Multiple Choice', | ||
| 29 | + shortAnswer: 'Short Answer', | ||
| 30 | + duplicateTitle: 'Please do not select duplicate questions', | ||
| 31 | + validate: { | ||
| 32 | + qaName: 'Questionnaire name cannot be empty', | ||
| 33 | + startTime: 'Start time cannot be empty', | ||
| 34 | + endTime: 'End time cannot be empty', | ||
| 35 | + timeError: 'Start time must be earlier than end time' | ||
| 36 | + }, | ||
| 37 | + updateSuccess: 'Update successful', | ||
| 38 | + updateFailed: 'Update failed' | ||
| 39 | + }, | ||
| 40 | + selectRoom: { | ||
| 41 | + buildingUnit: 'Building Unit', | ||
| 42 | + roomInfo: 'Room Information' | ||
| 43 | + }, | ||
| 44 | + chooseQuestionTitle: { | ||
| 45 | + title: 'Select Questions', | ||
| 46 | + searchPlaceholder: 'Enter question name', | ||
| 47 | + table: { | ||
| 48 | + title: 'Question', | ||
| 49 | + createTime: 'Create Time', | ||
| 50 | + actions: 'Actions', | ||
| 51 | + choose: 'Select' | ||
| 52 | + } | ||
| 53 | + } | ||
| 54 | + }, | ||
| 55 | + zh: { | ||
| 56 | + editQuestionAnswer: { | ||
| 57 | + title: '修改问卷', | ||
| 58 | + qaName: '问卷名称', | ||
| 59 | + qaNamePlaceholder: '必填,请填写问卷名称', | ||
| 60 | + startTime: '开始时间', | ||
| 61 | + startTimePlaceholder: '必填,请选择开始时间', | ||
| 62 | + endTime: '结束时间', | ||
| 63 | + endTimePlaceholder: '必填,请选择结束时间', | ||
| 64 | + content: '问卷说明', | ||
| 65 | + contentPlaceholder: '必填,请输入问卷说明', | ||
| 66 | + questionTitle: '问卷题目', | ||
| 67 | + chooseTitle: '选择题目', | ||
| 68 | + questionRooms: '问卷房屋', | ||
| 69 | + household: '户', | ||
| 70 | + reselect: '重新选择', | ||
| 71 | + save: '保存', | ||
| 72 | + cancel: '取消', | ||
| 73 | + table: { | ||
| 74 | + name: '名称', | ||
| 75 | + type: '类型', | ||
| 76 | + options: '选项', | ||
| 77 | + actions: '操作', | ||
| 78 | + delete: '删除' | ||
| 79 | + }, | ||
| 80 | + singleChoice: '单选', | ||
| 81 | + multipleChoice: '多选', | ||
| 82 | + shortAnswer: '简答', | ||
| 83 | + duplicateTitle: '请勿重复选择题目', | ||
| 84 | + validate: { | ||
| 85 | + qaName: '问卷名称不能为空', | ||
| 86 | + startTime: '开始时间不能为空', | ||
| 87 | + endTime: '结束时间不能为空', | ||
| 88 | + timeError: '开始时间必须小于结束时间' | ||
| 89 | + }, | ||
| 90 | + updateSuccess: '修改成功', | ||
| 91 | + updateFailed: '修改失败' | ||
| 92 | + }, | ||
| 93 | + selectRoom: { | ||
| 94 | + buildingUnit: '楼栋单元', | ||
| 95 | + roomInfo: '房屋信息' | ||
| 96 | + }, | ||
| 97 | + chooseQuestionTitle: { | ||
| 98 | + title: '选择题目', | ||
| 99 | + searchPlaceholder: '输入题目名称', | ||
| 100 | + table: { | ||
| 101 | + title: '题目', | ||
| 102 | + createTime: '创建时间', | ||
| 103 | + actions: '操作', | ||
| 104 | + choose: '选择' | ||
| 105 | + } | ||
| 106 | + } | ||
| 107 | + } | ||
| 108 | +} | ||
| 0 | \ No newline at end of file | 109 | \ No newline at end of file |
src/views/oa/editQuestionAnswerList.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="edit-question-answer-container"> | ||
| 3 | + <el-card class="box-card"> | ||
| 4 | + <div slot="header" class="flex justify-between"> | ||
| 5 | + <span>{{ $t('editQuestionAnswer.title') }}</span> | ||
| 6 | + </div> | ||
| 7 | + <el-row :gutter="20"> | ||
| 8 | + <el-col :span="24"> | ||
| 9 | + <el-form ref="form" :model="editQuestionAnswerInfo" label-width="120px"> | ||
| 10 | + <el-row> | ||
| 11 | + <el-col :span="12"> | ||
| 12 | + <el-form-item :label="$t('editQuestionAnswer.qaName')" prop="qaName"> | ||
| 13 | + <el-input v-model="editQuestionAnswerInfo.qaName" | ||
| 14 | + :placeholder="$t('editQuestionAnswer.qaNamePlaceholder')" /> | ||
| 15 | + </el-form-item> | ||
| 16 | + </el-col> | ||
| 17 | + <el-col :span="12"> | ||
| 18 | + <el-form-item :label="$t('editQuestionAnswer.startTime')" prop="startTime"> | ||
| 19 | + <el-date-picker v-model="editQuestionAnswerInfo.startTime" type="datetime" | ||
| 20 | + :placeholder="$t('editQuestionAnswer.startTimePlaceholder')" style="width: 100%" /> | ||
| 21 | + </el-form-item> | ||
| 22 | + </el-col> | ||
| 23 | + </el-row> | ||
| 24 | + <el-row> | ||
| 25 | + <el-col :span="12"> | ||
| 26 | + <el-form-item :label="$t('editQuestionAnswer.endTime')" prop="endTime"> | ||
| 27 | + <el-date-picker v-model="editQuestionAnswerInfo.endTime" type="datetime" | ||
| 28 | + :placeholder="$t('editQuestionAnswer.endTimePlaceholder')" style="width: 100%" /> | ||
| 29 | + </el-form-item> | ||
| 30 | + </el-col> | ||
| 31 | + </el-row> | ||
| 32 | + <el-row> | ||
| 33 | + <el-col :span="24"> | ||
| 34 | + <el-form-item :label="$t('editQuestionAnswer.content')"> | ||
| 35 | + <el-input v-model="editQuestionAnswerInfo.content" type="textarea" :rows="5" | ||
| 36 | + :placeholder="$t('editQuestionAnswer.contentPlaceholder')" /> | ||
| 37 | + </el-form-item> | ||
| 38 | + </el-col> | ||
| 39 | + </el-row> | ||
| 40 | + </el-form> | ||
| 41 | + </el-col> | ||
| 42 | + </el-row> | ||
| 43 | + </el-card> | ||
| 44 | + | ||
| 45 | + <el-card class="box-card margin-top"> | ||
| 46 | + <div slot="header" class="flex justify-between"> | ||
| 47 | + <span>{{ $t('editQuestionAnswer.questionTitle') }}</span> | ||
| 48 | + <div class="float-right"> | ||
| 49 | + <el-button type="primary" @click="chooseTitle"> | ||
| 50 | + <i class="el-icon-search"></i>{{ $t('editQuestionAnswer.chooseTitle') }} | ||
| 51 | + </el-button> | ||
| 52 | + </div> | ||
| 53 | + </div> | ||
| 54 | + <el-table :data="editQuestionAnswerInfo.questionTitles" border style="width: 100%"> | ||
| 55 | + <el-table-column prop="qaTitle" :label="$t('editQuestionAnswer.table.name')" align="center" /> | ||
| 56 | + <el-table-column prop="titleType" :label="$t('editQuestionAnswer.table.type')" align="center"> | ||
| 57 | + <template slot-scope="scope"> | ||
| 58 | + {{ getTitleTypeName(scope.row.titleType) }} | ||
| 59 | + </template> | ||
| 60 | + </el-table-column> | ||
| 61 | + <el-table-column :label="$t('editQuestionAnswer.table.options')" align="center"> | ||
| 62 | + <template slot-scope="scope"> | ||
| 63 | + <div v-for="(item, index) in scope.row.titleValues" :key="index"> | ||
| 64 | + {{ item.seq }}、{{ item.qaValue }} | ||
| 65 | + </div> | ||
| 66 | + </template> | ||
| 67 | + </el-table-column> | ||
| 68 | + <el-table-column :label="$t('editQuestionAnswer.table.actions')" align="center"> | ||
| 69 | + <template slot-scope="scope"> | ||
| 70 | + <el-button type="danger" size="mini" @click="openDeleteQuestionTitle(scope.row)"> | ||
| 71 | + {{ $t('editQuestionAnswer.table.delete') }} | ||
| 72 | + </el-button> | ||
| 73 | + </template> | ||
| 74 | + </el-table-column> | ||
| 75 | + </el-table> | ||
| 76 | + </el-card> | ||
| 77 | + | ||
| 78 | + <el-card class="box-card margin-top"> | ||
| 79 | + <div slot="header" class="flex justify-between"> | ||
| 80 | + <span>{{ $t('editQuestionAnswer.questionRooms') }}</span> | ||
| 81 | + </div> | ||
| 82 | + <el-row> | ||
| 83 | + <el-col :span="24"> | ||
| 84 | + <el-form> | ||
| 85 | + <el-form-item :label="$t('editQuestionAnswer.questionRooms')"> | ||
| 86 | + <div v-if="editQuestionAnswerInfo.updateRoomIds"> | ||
| 87 | + <select-rooms ref="selectRooms" @notifySelectRooms="handleSelectRooms" /> | ||
| 88 | + </div> | ||
| 89 | + <div v-else> | ||
| 90 | + <span>{{ editQuestionAnswerInfo.voteCount }}{{ $t('editQuestionAnswer.household') }}</span> | ||
| 91 | + <el-button type="text" @click="updateRoomIdsMethod"> | ||
| 92 | + {{ $t('editQuestionAnswer.reselect') }} | ||
| 93 | + </el-button> | ||
| 94 | + </div> | ||
| 95 | + </el-form-item> | ||
| 96 | + </el-form> | ||
| 97 | + </el-col> | ||
| 98 | + </el-row> | ||
| 99 | + </el-card> | ||
| 100 | + | ||
| 101 | + <div class="action-buttons margin-top"> | ||
| 102 | + <el-button type="primary" @click="updateQuestionAnswer"> | ||
| 103 | + <i class="el-icon-check"></i>{{ $t('editQuestionAnswer.save') }} | ||
| 104 | + </el-button> | ||
| 105 | + <el-button type="warning" @click="goBack"> | ||
| 106 | + {{ $t('editQuestionAnswer.cancel') }} | ||
| 107 | + </el-button> | ||
| 108 | + </div> | ||
| 109 | + | ||
| 110 | + <choose-question-title ref="chooseQuestionTitle" @chooseQuestionTitle="handleChooseQuestionTitle" /> | ||
| 111 | + </div> | ||
| 112 | +</template> | ||
| 113 | + | ||
| 114 | +<script> | ||
| 115 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 116 | +import SelectRooms from '@/components/room/selectRooms' | ||
| 117 | +import ChooseQuestionTitle from '@/components/oa/chooseQuestionTitle' | ||
| 118 | +import { updateQuestionAnswer, listQuestionAnswer, listQuestionTitle } from '@/api/oa/editQuestionAnswerApi' | ||
| 119 | + | ||
| 120 | +export default { | ||
| 121 | + name: 'EditQuestionAnswerList', | ||
| 122 | + components: { | ||
| 123 | + SelectRooms, | ||
| 124 | + ChooseQuestionTitle | ||
| 125 | + }, | ||
| 126 | + data() { | ||
| 127 | + return { | ||
| 128 | + editQuestionAnswerInfo: { | ||
| 129 | + qaName: '', | ||
| 130 | + startTime: '', | ||
| 131 | + endTime: '', | ||
| 132 | + communityId: '', | ||
| 133 | + content: '', | ||
| 134 | + titleType: '', | ||
| 135 | + questionTitles: [], | ||
| 136 | + roomIds: [], | ||
| 137 | + updateRoomIds: false, | ||
| 138 | + voteCount: 0, | ||
| 139 | + qaId: '' | ||
| 140 | + } | ||
| 141 | + } | ||
| 142 | + }, | ||
| 143 | + created() { | ||
| 144 | + this.editQuestionAnswerInfo.communityId = getCommunityId() | ||
| 145 | + this.editQuestionAnswerInfo.qaId = this.$route.query.qaId | ||
| 146 | + this.loadQuestionAnswerInfo() | ||
| 147 | + this.loadQuestionTitles() | ||
| 148 | + }, | ||
| 149 | + methods: { | ||
| 150 | + async loadQuestionAnswerInfo() { | ||
| 151 | + try { | ||
| 152 | + const params = { | ||
| 153 | + page: 1, | ||
| 154 | + row: 1, | ||
| 155 | + communityId: this.editQuestionAnswerInfo.communityId, | ||
| 156 | + qaId: this.editQuestionAnswerInfo.qaId | ||
| 157 | + } | ||
| 158 | + const { data } = await listQuestionAnswer(params) | ||
| 159 | + this.editQuestionAnswerInfo = { ...this.editQuestionAnswerInfo, ...data[0] } | ||
| 160 | + } catch (error) { | ||
| 161 | + console.error('Failed to load question answer info:', error) | ||
| 162 | + } | ||
| 163 | + }, | ||
| 164 | + async loadQuestionTitles() { | ||
| 165 | + try { | ||
| 166 | + const params = { | ||
| 167 | + page: 1, | ||
| 168 | + row: 100, | ||
| 169 | + communityId: this.editQuestionAnswerInfo.communityId, | ||
| 170 | + qaId: this.editQuestionAnswerInfo.qaId | ||
| 171 | + } | ||
| 172 | + const { data } = await listQuestionTitle(params) | ||
| 173 | + this.editQuestionAnswerInfo.questionTitles = data | ||
| 174 | + } catch (error) { | ||
| 175 | + console.error('Failed to load question titles:', error) | ||
| 176 | + } | ||
| 177 | + }, | ||
| 178 | + getTitleTypeName(titleType) { | ||
| 179 | + if (titleType === '1001') { | ||
| 180 | + return this.$t('editQuestionAnswer.singleChoice') | ||
| 181 | + } else if (titleType === '2002') { | ||
| 182 | + return this.$t('editQuestionAnswer.multipleChoice') | ||
| 183 | + } else { | ||
| 184 | + return this.$t('editQuestionAnswer.shortAnswer') | ||
| 185 | + } | ||
| 186 | + }, | ||
| 187 | + chooseTitle() { | ||
| 188 | + this.$refs.chooseQuestionTitle.open() | ||
| 189 | + }, | ||
| 190 | + handleChooseQuestionTitle(questionTitle) { | ||
| 191 | + const exists = this.editQuestionAnswerInfo.questionTitles.some( | ||
| 192 | + item => item.titleId === questionTitle.titleId | ||
| 193 | + ) | ||
| 194 | + if (exists) { | ||
| 195 | + this.$message.warning(this.$t('editQuestionAnswer.duplicateTitle')) | ||
| 196 | + return | ||
| 197 | + } | ||
| 198 | + this.editQuestionAnswerInfo.questionTitles.push(questionTitle) | ||
| 199 | + }, | ||
| 200 | + openDeleteQuestionTitle(title) { | ||
| 201 | + this.editQuestionAnswerInfo.questionTitles = this.editQuestionAnswerInfo.questionTitles.filter( | ||
| 202 | + item => item.titleId !== title.titleId | ||
| 203 | + ) | ||
| 204 | + }, | ||
| 205 | + updateRoomIdsMethod() { | ||
| 206 | + this.editQuestionAnswerInfo.updateRoomIds = true | ||
| 207 | + }, | ||
| 208 | + handleSelectRooms(selectRooms) { | ||
| 209 | + this.editQuestionAnswerInfo.roomIds = selectRooms.map(item => item.roomId) | ||
| 210 | + }, | ||
| 211 | + validateForm() { | ||
| 212 | + if (!this.editQuestionAnswerInfo.qaName) { | ||
| 213 | + this.$message.error(this.$t('editQuestionAnswer.validate.qaName')) | ||
| 214 | + return false | ||
| 215 | + } | ||
| 216 | + if (!this.editQuestionAnswerInfo.startTime) { | ||
| 217 | + this.$message.error(this.$t('editQuestionAnswer.validate.startTime')) | ||
| 218 | + return false | ||
| 219 | + } | ||
| 220 | + if (!this.editQuestionAnswerInfo.endTime) { | ||
| 221 | + this.$message.error(this.$t('editQuestionAnswer.validate.endTime')) | ||
| 222 | + return false | ||
| 223 | + } | ||
| 224 | + if (new Date(this.editQuestionAnswerInfo.startTime) >= new Date(this.editQuestionAnswerInfo.endTime)) { | ||
| 225 | + this.$message.error(this.$t('editQuestionAnswer.validate.timeError')) | ||
| 226 | + return false | ||
| 227 | + } | ||
| 228 | + return true | ||
| 229 | + }, | ||
| 230 | + async updateQuestionAnswer() { | ||
| 231 | + if (!this.validateForm()) return | ||
| 232 | + | ||
| 233 | + try { | ||
| 234 | + await updateQuestionAnswer(this.editQuestionAnswerInfo) | ||
| 235 | + this.$message.success(this.$t('editQuestionAnswer.updateSuccess')) | ||
| 236 | + this.goBack() | ||
| 237 | + } catch (error) { | ||
| 238 | + console.error('Failed to update question answer:', error) | ||
| 239 | + this.$message.error(error.message || this.$t('editQuestionAnswer.updateFailed')) | ||
| 240 | + } | ||
| 241 | + }, | ||
| 242 | + goBack() { | ||
| 243 | + this.$router.go(-1) | ||
| 244 | + } | ||
| 245 | + } | ||
| 246 | +} | ||
| 247 | +</script> | ||
| 248 | + | ||
| 249 | +<style lang="scss" scoped> | ||
| 250 | +.edit-question-answer-container { | ||
| 251 | + padding: 20px; | ||
| 252 | + | ||
| 253 | + .box-card { | ||
| 254 | + margin-bottom: 20px; | ||
| 255 | + } | ||
| 256 | + | ||
| 257 | + .margin-top { | ||
| 258 | + margin-top: 20px; | ||
| 259 | + } | ||
| 260 | + | ||
| 261 | + .float-right { | ||
| 262 | + float: right; | ||
| 263 | + } | ||
| 264 | + | ||
| 265 | + .action-buttons { | ||
| 266 | + text-align: right; | ||
| 267 | + margin-top: 20px; | ||
| 268 | + } | ||
| 269 | +} | ||
| 270 | +</style> | ||
| 0 | \ No newline at end of file | 271 | \ No newline at end of file |
src/views/oa/notepadManageLang.js
0 → 100644
| 1 | +export const messages = { | ||
| 2 | + en: { | ||
| 3 | + notepadManage: { | ||
| 4 | + search: { | ||
| 5 | + title: 'Search Conditions', | ||
| 6 | + noteType: 'Please select feedback type', | ||
| 7 | + roomName: 'Please select room', | ||
| 8 | + state: 'Please select status', | ||
| 9 | + createUserName: 'Please select registrant', | ||
| 10 | + objName: 'Please select owner name' | ||
| 11 | + }, | ||
| 12 | + list: { | ||
| 13 | + title: 'Owner Feedback' | ||
| 14 | + }, | ||
| 15 | + table: { | ||
| 16 | + noteType: 'Type', | ||
| 17 | + roomName: 'Room', | ||
| 18 | + objName: 'Contact', | ||
| 19 | + link: 'Contact Phone', | ||
| 20 | + state: 'Status', | ||
| 21 | + createTime: 'Record Time', | ||
| 22 | + createUserName: 'Registrant', | ||
| 23 | + title: 'Content' | ||
| 24 | + }, | ||
| 25 | + state: { | ||
| 26 | + following: 'Following', | ||
| 27 | + completed: 'Completed', | ||
| 28 | + transferred: 'Transferred' | ||
| 29 | + }, | ||
| 30 | + operation: { | ||
| 31 | + follow: 'Follow', | ||
| 32 | + progress: 'Progress', | ||
| 33 | + transfer: 'Transfer to Repair', | ||
| 34 | + repairDetail: 'Repair Detail' | ||
| 35 | + }, | ||
| 36 | + tip: 'Tip: Please register at the business acceptance page', | ||
| 37 | + edit: { | ||
| 38 | + title: 'Edit', | ||
| 39 | + roomName: 'Room', | ||
| 40 | + objName: 'Contact', | ||
| 41 | + link: 'Contact Phone', | ||
| 42 | + noteType: 'Type', | ||
| 43 | + Content: 'Content', | ||
| 44 | + selectNoteType: 'Please select feedback type' | ||
| 45 | + }, | ||
| 46 | + delete: { | ||
| 47 | + title: 'Confirm Operation', | ||
| 48 | + confirm: 'Confirm to delete notepad?' | ||
| 49 | + }, | ||
| 50 | + addDetail: { | ||
| 51 | + title: 'Follow Up', | ||
| 52 | + state: 'Status', | ||
| 53 | + content: 'Follow Content', | ||
| 54 | + selectState: 'Please select status', | ||
| 55 | + contentPlaceholder: 'Please enter follow content' | ||
| 56 | + }, | ||
| 57 | + detail: { | ||
| 58 | + title: 'Follow Progress', | ||
| 59 | + index: 'No.', | ||
| 60 | + createUser: 'Handler', | ||
| 61 | + createTime: 'Handle Time', | ||
| 62 | + content: 'Handle Content' | ||
| 63 | + }, | ||
| 64 | + ownerRepair: { | ||
| 65 | + title: 'Transfer to Repair', | ||
| 66 | + repairType: 'Repair Type', | ||
| 67 | + repairObjName: 'Room', | ||
| 68 | + repairName: 'Repairer', | ||
| 69 | + tel: 'Contact', | ||
| 70 | + appointmentTime: 'Appointment Time', | ||
| 71 | + context: 'Repair Content', | ||
| 72 | + selectRepairType: 'Please select repair type', | ||
| 73 | + repairObjNamePlaceholder: 'Please enter room', | ||
| 74 | + repairNamePlaceholder: 'Please enter repairer', | ||
| 75 | + telPlaceholder: 'Please enter contact', | ||
| 76 | + selectTime: 'Select appointment time', | ||
| 77 | + contextPlaceholder: 'Please enter repair content' | ||
| 78 | + }, | ||
| 79 | + validate: { | ||
| 80 | + noteType: 'Type cannot be empty', | ||
| 81 | + title: 'Content cannot be empty', | ||
| 82 | + titleMaxLength: 'Content cannot exceed 256 characters', | ||
| 83 | + state: 'Status cannot be empty', | ||
| 84 | + content: 'Content cannot be empty', | ||
| 85 | + repairType: 'Repair type cannot be empty', | ||
| 86 | + repairObjName: 'Room cannot be empty', | ||
| 87 | + repairName: 'Repairer cannot be empty', | ||
| 88 | + repairNameLength: 'Repairer name must be between 2-10 characters', | ||
| 89 | + tel: 'Contact cannot be empty', | ||
| 90 | + telFormat: 'Invalid contact format', | ||
| 91 | + appointmentTime: 'Appointment time cannot be empty', | ||
| 92 | + context: 'Repair content cannot be empty', | ||
| 93 | + contextMaxLength: 'Repair content cannot exceed 2000 characters' | ||
| 94 | + } | ||
| 95 | + } | ||
| 96 | + }, | ||
| 97 | + zh: { | ||
| 98 | + notepadManage: { | ||
| 99 | + search: { | ||
| 100 | + title: '查询条件', | ||
| 101 | + noteType: '请选择反馈类型', | ||
| 102 | + roomName: '请选择房屋', | ||
| 103 | + state: '请选择状态', | ||
| 104 | + createUserName: '请选择登记人', | ||
| 105 | + objName: '请选择业主名称' | ||
| 106 | + }, | ||
| 107 | + list: { | ||
| 108 | + title: '业主反馈' | ||
| 109 | + }, | ||
| 110 | + table: { | ||
| 111 | + noteType: '类型', | ||
| 112 | + roomName: '房屋', | ||
| 113 | + objName: '联系人', | ||
| 114 | + link: '联系电话', | ||
| 115 | + state: '状态', | ||
| 116 | + createTime: '记录时间', | ||
| 117 | + createUserName: '登记人', | ||
| 118 | + title: '内容' | ||
| 119 | + }, | ||
| 120 | + state: { | ||
| 121 | + following: '跟进中', | ||
| 122 | + completed: '完成', | ||
| 123 | + transferred: '已转报修单' | ||
| 124 | + }, | ||
| 125 | + operation: { | ||
| 126 | + follow: '跟进', | ||
| 127 | + progress: '进度', | ||
| 128 | + transfer: '转报修单', | ||
| 129 | + repairDetail: '报修详情' | ||
| 130 | + }, | ||
| 131 | + tip: '温馨提示:请到业务受理页面登记', | ||
| 132 | + edit: { | ||
| 133 | + title: '修改', | ||
| 134 | + roomName: '房屋', | ||
| 135 | + objName: '联系人', | ||
| 136 | + link: '联系电话', | ||
| 137 | + noteType: '类型', | ||
| 138 | + content: '内容', | ||
| 139 | + selectNoteType: '请选择反馈类型' | ||
| 140 | + }, | ||
| 141 | + delete: { | ||
| 142 | + title: '请确认您的操作', | ||
| 143 | + confirm: '确定删除记事薄?' | ||
| 144 | + }, | ||
| 145 | + addDetail: { | ||
| 146 | + title: '跟进', | ||
| 147 | + state: '状态', | ||
| 148 | + content: '跟进内容', | ||
| 149 | + selectState: '请选择状态', | ||
| 150 | + contentPlaceholder: '请填写跟进内容' | ||
| 151 | + }, | ||
| 152 | + detail: { | ||
| 153 | + title: '跟进进度', | ||
| 154 | + index: '序号', | ||
| 155 | + createUser: '处理人', | ||
| 156 | + createTime: '处理时间', | ||
| 157 | + content: '处理内容' | ||
| 158 | + }, | ||
| 159 | + ownerRepair: { | ||
| 160 | + title: '转报修单', | ||
| 161 | + repairType: '报修类型', | ||
| 162 | + repairObjName: '房屋', | ||
| 163 | + repairName: '报修人', | ||
| 164 | + tel: '联系方式', | ||
| 165 | + appointmentTime: '预约时间', | ||
| 166 | + context: '报修内容', | ||
| 167 | + selectRepairType: '请选择报修类型', | ||
| 168 | + repairObjNamePlaceholder: '请填写房屋', | ||
| 169 | + repairNamePlaceholder: '请填写报修人', | ||
| 170 | + telPlaceholder: '请填写联系方式', | ||
| 171 | + selectTime: '选择预约时间', | ||
| 172 | + contextPlaceholder: '请填写报修内容' | ||
| 173 | + }, | ||
| 174 | + validate: { | ||
| 175 | + noteType: '类型不能为空', | ||
| 176 | + title: '内容不能为空', | ||
| 177 | + titleMaxLength: '内容不能超过256个字符', | ||
| 178 | + state: '状态不能为空', | ||
| 179 | + content: '内容不能为空', | ||
| 180 | + repairType: '报修类型不能为空', | ||
| 181 | + repairObjName: '房屋不能为空', | ||
| 182 | + repairName: '报修人不能为空', | ||
| 183 | + repairNameLength: '报修人名称必须在2至10字符之间', | ||
| 184 | + tel: '联系方式不能为空', | ||
| 185 | + telFormat: '联系方式格式不正确', | ||
| 186 | + appointmentTime: '预约时间不能为空', | ||
| 187 | + context: '报修内容不能为空', | ||
| 188 | + contextMaxLength: '报修内容不能超过2000个字符' | ||
| 189 | + } | ||
| 190 | + } | ||
| 191 | + } | ||
| 192 | +} | ||
| 0 | \ No newline at end of file | 193 | \ No newline at end of file |
src/views/oa/notepadManageList.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="notepad-manage-container"> | ||
| 3 | + <!-- 查询条件 --> | ||
| 4 | + <el-card class="search-wrapper"> | ||
| 5 | + <div slot="header" class="flex justify-between"> | ||
| 6 | + <span>{{ $t('notepadManage.search.title') }}</span> | ||
| 7 | + <el-button type="text" style="float: right; padding: 3px 0" @click="_moreCondition"> | ||
| 8 | + {{ notepadManageInfo.moreCondition ? $t('common.hide') : $t('common.more') }} | ||
| 9 | + </el-button> | ||
| 10 | + </div> | ||
| 11 | + <el-row :gutter="20"> | ||
| 12 | + <el-col :span="6"> | ||
| 13 | + <el-select v-model="notepadManageInfo.conditions.noteType" :placeholder="$t('notepadManage.search.noteType')" | ||
| 14 | + style="width:100%"> | ||
| 15 | + <el-option :label="$t('common.select')" value="" /> | ||
| 16 | + <el-option v-for="(item, index) in notepadManageInfo.noteTypes" :key="index" :label="item.name" | ||
| 17 | + :value="item.statusCd" /> | ||
| 18 | + </el-select> | ||
| 19 | + </el-col> | ||
| 20 | + <el-col :span="6"> | ||
| 21 | + <el-input v-model="notepadManageInfo.conditions.roomName" :placeholder="$t('notepadManage.search.roomName')" /> | ||
| 22 | + </el-col> | ||
| 23 | + <el-col :span="6"> | ||
| 24 | + <el-select v-model="notepadManageInfo.conditions.state" :placeholder="$t('notepadManage.search.state')" | ||
| 25 | + style="width:100%"> | ||
| 26 | + <el-option :label="$t('common.select')" value="" /> | ||
| 27 | + <el-option :label="$t('notepadManage.state.following')" value="W" /> | ||
| 28 | + <el-option :label="$t('notepadManage.state.completed')" value="F" /> | ||
| 29 | + </el-select> | ||
| 30 | + </el-col> | ||
| 31 | + <el-col :span="6"> | ||
| 32 | + <el-button type="primary" @click="_queryNotepadMethod"> | ||
| 33 | + <i class="el-icon-search"></i> | ||
| 34 | + {{ $t('common.search') }} | ||
| 35 | + </el-button> | ||
| 36 | + <el-button @click="_resetNotepadMethod"> | ||
| 37 | + <i class="el-icon-refresh"></i> | ||
| 38 | + {{ $t('common.reset') }} | ||
| 39 | + </el-button> | ||
| 40 | + </el-col> | ||
| 41 | + </el-row> | ||
| 42 | + | ||
| 43 | + <el-row v-show="notepadManageInfo.moreCondition" :gutter="20" style="margin-top:20px"> | ||
| 44 | + <el-col :span="6"> | ||
| 45 | + <el-input v-model="notepadManageInfo.conditions.createUserName" | ||
| 46 | + :placeholder="$t('notepadManage.search.createUserName')" /> | ||
| 47 | + </el-col> | ||
| 48 | + <el-col :span="6"> | ||
| 49 | + <el-input v-model="notepadManageInfo.conditions.objName" :placeholder="$t('notepadManage.search.objName')" /> | ||
| 50 | + </el-col> | ||
| 51 | + </el-row> | ||
| 52 | + </el-card> | ||
| 53 | + | ||
| 54 | + <!-- 列表 --> | ||
| 55 | + <el-card class="list-wrapper"> | ||
| 56 | + <div slot="header" class="flex justify-between"> | ||
| 57 | + <span>{{ $t('notepadManage.list.title') }}</span> | ||
| 58 | + </div> | ||
| 59 | + | ||
| 60 | + <el-table v-loading="loading" :data="notepadManageInfo.notepads" border style="width: 100%"> | ||
| 61 | + <el-table-column prop="noteTypeName" :label="$t('notepadManage.table.noteType')" align="center" /> | ||
| 62 | + <el-table-column prop="roomName" :label="$t('notepadManage.table.roomName')" align="center" /> | ||
| 63 | + <el-table-column prop="objName" :label="$t('notepadManage.table.objName')" align="center" /> | ||
| 64 | + <el-table-column prop="link" :label="$t('notepadManage.table.link')" align="center" /> | ||
| 65 | + <el-table-column :label="$t('notepadManage.table.state')" align="center"> | ||
| 66 | + <template slot-scope="scope"> | ||
| 67 | + {{ scope.row.state === 'F' ? $t('notepadManage.state.completed') : $t('notepadManage.state.following') }} | ||
| 68 | + <span v-if="scope.row.thridId">({{ $t('notepadManage.state.transferred') }})</span> | ||
| 69 | + </template> | ||
| 70 | + </el-table-column> | ||
| 71 | + <el-table-column prop="createTime" :label="$t('notepadManage.table.createTime')" align="center" /> | ||
| 72 | + <el-table-column prop="createUserName" :label="$t('notepadManage.table.createUserName')" align="center" /> | ||
| 73 | + <el-table-column prop="title" :label="$t('notepadManage.table.title')" align="center" /> | ||
| 74 | + <el-table-column :label="$t('common.operation')" align="center" width="300"> | ||
| 75 | + <template slot-scope="scope"> | ||
| 76 | + <el-button v-if="scope.row.state === 'W'" size="mini" @click="_openAddNotepadDetailModal(scope.row)"> | ||
| 77 | + {{ $t('notepadManage.operation.follow') }} | ||
| 78 | + </el-button> | ||
| 79 | + <el-button size="mini" @click="_openListNotepadDetailModal(scope.row)"> | ||
| 80 | + {{ $t('notepadManage.operation.progress') }} | ||
| 81 | + </el-button> | ||
| 82 | + <el-button v-if="!scope.row.thridId" size="mini" @click="_openAddRepairModal(scope.row)"> | ||
| 83 | + {{ $t('notepadManage.operation.transfer') }} | ||
| 84 | + </el-button> | ||
| 85 | + <el-button v-if="scope.row.thridId" size="mini" @click="_toRepairDetail(scope.row)"> | ||
| 86 | + {{ $t('notepadManage.operation.repairDetail') }} | ||
| 87 | + </el-button> | ||
| 88 | + <el-button size="mini" @click="_openEditNotepadModel(scope.row)"> | ||
| 89 | + {{ $t('common.edit') }} | ||
| 90 | + </el-button> | ||
| 91 | + <el-button size="mini" type="danger" @click="_openDeleteNotepadModel(scope.row)"> | ||
| 92 | + {{ $t('common.delete') }} | ||
| 93 | + </el-button> | ||
| 94 | + </template> | ||
| 95 | + </el-table-column> | ||
| 96 | + </el-table> | ||
| 97 | + | ||
| 98 | + <div class="margin-top-xs"> | ||
| 99 | + <div class="tip">{{ $t('notepadManage.tip') }}</div> | ||
| 100 | + <el-pagination :current-page.sync="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size" | ||
| 101 | + :total="page.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange" | ||
| 102 | + @current-change="handleCurrentChange" /> | ||
| 103 | + </div> | ||
| 104 | + </el-card> | ||
| 105 | + | ||
| 106 | + <!-- 组件 --> | ||
| 107 | + <edit-notepad ref="editNotepad" @success="handleSuccess" /> | ||
| 108 | + <delete-notepad ref="deleteNotepad" @success="handleSuccess" /> | ||
| 109 | + <add-notepad-detail ref="addNotepadDetail" @success="handleSuccess" /> | ||
| 110 | + <notepad-detail ref="notepadDetail" /> | ||
| 111 | + <notepad-owner-repair ref="notepadOwnerRepair" @success="handleSuccess" /> | ||
| 112 | + </div> | ||
| 113 | +</template> | ||
| 114 | + | ||
| 115 | +<script> | ||
| 116 | +import { listNotepad } from '@/api/oa/notepadManageApi' | ||
| 117 | +import { getDict } from '@/api/community/communityApi' | ||
| 118 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 119 | +import EditNotepad from '@/components/oa/editNotepad' | ||
| 120 | +import DeleteNotepad from '@/components/oa/deleteNotepad' | ||
| 121 | +import AddNotepadDetail from '@/components/oa/addNotepadDetail' | ||
| 122 | +import NotepadDetail from '@/components/oa/notepadDetail' | ||
| 123 | +import NotepadOwnerRepair from '@/components/oa/notepadOwnerRepair' | ||
| 124 | + | ||
| 125 | +export default { | ||
| 126 | + name: 'NotepadManageList', | ||
| 127 | + components: { | ||
| 128 | + EditNotepad, | ||
| 129 | + DeleteNotepad, | ||
| 130 | + AddNotepadDetail, | ||
| 131 | + NotepadDetail, | ||
| 132 | + NotepadOwnerRepair | ||
| 133 | + }, | ||
| 134 | + data() { | ||
| 135 | + return { | ||
| 136 | + loading: false, | ||
| 137 | + notepadManageInfo: { | ||
| 138 | + notepads: [], | ||
| 139 | + total: 0, | ||
| 140 | + records: 1, | ||
| 141 | + moreCondition: false, | ||
| 142 | + noteTypes: [], | ||
| 143 | + conditions: { | ||
| 144 | + noteType: '', | ||
| 145 | + roomName: '', | ||
| 146 | + objName: '', | ||
| 147 | + createUserName: '', | ||
| 148 | + state: '', | ||
| 149 | + communityId: '' | ||
| 150 | + } | ||
| 151 | + }, | ||
| 152 | + page: { | ||
| 153 | + current: 1, | ||
| 154 | + size: 10, | ||
| 155 | + total: 0 | ||
| 156 | + } | ||
| 157 | + } | ||
| 158 | + }, | ||
| 159 | + created() { | ||
| 160 | + this.notepadManageInfo.conditions.communityId = getCommunityId() | ||
| 161 | + this._initMethod() | ||
| 162 | + }, | ||
| 163 | + methods: { | ||
| 164 | + async _initMethod() { | ||
| 165 | + try { | ||
| 166 | + const data = await getDict('notepad', 'note_type') | ||
| 167 | + this.notepadManageInfo.noteTypes = data | ||
| 168 | + this._listNotepads(this.page.current, this.page.size) | ||
| 169 | + } catch (error) { | ||
| 170 | + console.error('获取字典数据失败:', error) | ||
| 171 | + } | ||
| 172 | + }, | ||
| 173 | + async _listNotepads(page, size) { | ||
| 174 | + this.loading = true | ||
| 175 | + try { | ||
| 176 | + const params = { | ||
| 177 | + page: page, | ||
| 178 | + row: size, | ||
| 179 | + ...this.notepadManageInfo.conditions | ||
| 180 | + } | ||
| 181 | + const { data, total } = await listNotepad(params) | ||
| 182 | + this.notepadManageInfo.notepads = data | ||
| 183 | + this.page.total = total | ||
| 184 | + } catch (error) { | ||
| 185 | + console.error('获取记事本列表失败:', error) | ||
| 186 | + } finally { | ||
| 187 | + this.loading = false | ||
| 188 | + } | ||
| 189 | + }, | ||
| 190 | + _openAddNotepadDetailModal(notepad) { | ||
| 191 | + this.$refs.addNotepadDetail.open(notepad) | ||
| 192 | + }, | ||
| 193 | + _openListNotepadDetailModal(notepad) { | ||
| 194 | + this.$refs.notepadDetail.open(notepad) | ||
| 195 | + }, | ||
| 196 | + _openEditNotepadModel(notepad) { | ||
| 197 | + this.$refs.editNotepad.open(notepad) | ||
| 198 | + }, | ||
| 199 | + _openDeleteNotepadModel(notepad) { | ||
| 200 | + this.$refs.deleteNotepad.open(notepad) | ||
| 201 | + }, | ||
| 202 | + _queryNotepadMethod() { | ||
| 203 | + this.page.current = 1 | ||
| 204 | + this._listNotepads(this.page.current, this.page.size) | ||
| 205 | + }, | ||
| 206 | + _resetNotepadMethod() { | ||
| 207 | + this.notepadManageInfo.conditions = { | ||
| 208 | + noteType: '', | ||
| 209 | + roomName: '', | ||
| 210 | + state: '', | ||
| 211 | + createUserName: '', | ||
| 212 | + objName: '', | ||
| 213 | + communityId: this.notepadManageInfo.conditions.communityId | ||
| 214 | + } | ||
| 215 | + this._listNotepads(this.page.current, this.page.size) | ||
| 216 | + }, | ||
| 217 | + _openAddRepairModal(notepad) { | ||
| 218 | + this.$refs.notepadOwnerRepair.open(notepad) | ||
| 219 | + }, | ||
| 220 | + _toRepairDetail(notepad) { | ||
| 221 | + this.$router.push(`/views/work/repairDetail?repairId=${notepad.thridId}`) | ||
| 222 | + }, | ||
| 223 | + _moreCondition() { | ||
| 224 | + this.notepadManageInfo.moreCondition = !this.notepadManageInfo.moreCondition | ||
| 225 | + }, | ||
| 226 | + handleSizeChange(val) { | ||
| 227 | + this.page.size = val | ||
| 228 | + this._listNotepads(this.page.current, this.page.size) | ||
| 229 | + }, | ||
| 230 | + handleCurrentChange(val) { | ||
| 231 | + this.page.current = val | ||
| 232 | + this._listNotepads(this.page.current, this.page.size) | ||
| 233 | + }, | ||
| 234 | + handleSuccess() { | ||
| 235 | + this._listNotepads(this.page.current, this.page.size) | ||
| 236 | + } | ||
| 237 | + } | ||
| 238 | +} | ||
| 239 | +</script> | ||
| 240 | + | ||
| 241 | +<style lang="scss" scoped> | ||
| 242 | +.notepad-manage-container { | ||
| 243 | + padding: 20px; | ||
| 244 | + | ||
| 245 | + .search-wrapper { | ||
| 246 | + margin-bottom: 20px; | ||
| 247 | + } | ||
| 248 | + | ||
| 249 | + .list-wrapper { | ||
| 250 | + margin-bottom: 20px; | ||
| 251 | + } | ||
| 252 | + | ||
| 253 | + .margin-top-xs { | ||
| 254 | + margin-top: 20px; | ||
| 255 | + display: flex; | ||
| 256 | + justify-content: space-between; | ||
| 257 | + align-items: center; | ||
| 258 | + | ||
| 259 | + .tip { | ||
| 260 | + color: #999; | ||
| 261 | + font-size: 14px; | ||
| 262 | + } | ||
| 263 | + } | ||
| 264 | +} | ||
| 265 | +</style> | ||
| 0 | \ No newline at end of file | 266 | \ No newline at end of file |
src/views/oa/printQuestionAnswerDetailLang.js
0 → 100644
| 1 | +export const messages = { | ||
| 2 | + en: { | ||
| 3 | + printQuestionAnswerDetail: { | ||
| 4 | + table: { | ||
| 5 | + title: 'Title', | ||
| 6 | + type: 'Type', | ||
| 7 | + options: 'Options', | ||
| 8 | + choices: 'Choices' | ||
| 9 | + }, | ||
| 10 | + singleChoice: 'Single Choice', | ||
| 11 | + multipleChoice: 'Multiple Choice', | ||
| 12 | + shortAnswer: 'Short Answer', | ||
| 13 | + total: 'Total', | ||
| 14 | + submitted: 'Submitted', | ||
| 15 | + people: 'people', | ||
| 16 | + print: 'Print', | ||
| 17 | + cancel: 'Cancel' | ||
| 18 | + } | ||
| 19 | + }, | ||
| 20 | + zh: { | ||
| 21 | + printQuestionAnswerDetail: { | ||
| 22 | + table: { | ||
| 23 | + title: '名称', | ||
| 24 | + type: '类型', | ||
| 25 | + options: '选项', | ||
| 26 | + choices: '选择' | ||
| 27 | + }, | ||
| 28 | + singleChoice: '单选', | ||
| 29 | + multipleChoice: '多选', | ||
| 30 | + shortAnswer: '简答', | ||
| 31 | + total: '总数', | ||
| 32 | + submitted: '已提交', | ||
| 33 | + people: '人', | ||
| 34 | + print: '打印', | ||
| 35 | + cancel: '取消' | ||
| 36 | + } | ||
| 37 | + } | ||
| 38 | +} | ||
| 0 | \ No newline at end of file | 39 | \ No newline at end of file |
src/views/oa/printQuestionAnswerDetailList.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="print-question-answer-detail-container"> | ||
| 3 | + <el-row :gutter="20"> | ||
| 4 | + <el-col :span="4" id="print-room"> | ||
| 5 | + <el-card class="tree-card"> | ||
| 6 | + <ul class="room-list"> | ||
| 7 | + <li v-for="(item, index) in printQuestionAnswerDetailInfo.userQuestions" :key="index" | ||
| 8 | + @click="swatchRoom(item)" :class="{ 'selected-room': printQuestionAnswerDetailInfo.roomId == item.roomId }"> | ||
| 9 | + {{ item.roomName }} | ||
| 10 | + </li> | ||
| 11 | + </ul> | ||
| 12 | + </el-card> | ||
| 13 | + </el-col> | ||
| 14 | + <el-col :span="20"> | ||
| 15 | + <div class="text-center"> | ||
| 16 | + <h1>{{ printQuestionAnswerDetailInfo.qaName }}</h1> | ||
| 17 | + </div> | ||
| 18 | + <div v-html="printQuestionAnswerDetailInfo.content"></div> | ||
| 19 | + | ||
| 20 | + <el-table :data="printQuestionAnswerDetailInfo.questionTitles" border style="width: 100%" class="margin-top"> | ||
| 21 | + <el-table-column prop="qaTitle" :label="$t('printQuestionAnswerDetail.table.title')" width="300" align="center"> | ||
| 22 | + <template slot-scope="scope"> | ||
| 23 | + <div style="max-width: 300px;"> | ||
| 24 | + {{ scope.row.qaTitle }} | ||
| 25 | + </div> | ||
| 26 | + </template> | ||
| 27 | + </el-table-column> | ||
| 28 | + <el-table-column prop="titleType" :label="$t('printQuestionAnswerDetail.table.type')" width="300" | ||
| 29 | + align="center"> | ||
| 30 | + <template slot-scope="scope"> | ||
| 31 | + {{ _getTitleTypeName(scope.row.titleType) }} | ||
| 32 | + </template> | ||
| 33 | + </el-table-column> | ||
| 34 | + <el-table-column :label="$t('printQuestionAnswerDetail.table.options')" align="center"> | ||
| 35 | + <template slot-scope="scope"> | ||
| 36 | + <div v-for="(item, index) in scope.row.titleValues" :key="index"> | ||
| 37 | + {{ item.seq }}、{{ item.qaValue }} | ||
| 38 | + </div> | ||
| 39 | + </template> | ||
| 40 | + </el-table-column> | ||
| 41 | + <el-table-column :label="$t('printQuestionAnswerDetail.table.choices')" align="center"> | ||
| 42 | + <template slot-scope="scope"> | ||
| 43 | + <div v-for="(item, index) in scope.row.titleValues" :key="index"> | ||
| 44 | + {{ _getChooseValue(item) }} | ||
| 45 | + </div> | ||
| 46 | + </template> | ||
| 47 | + </el-table-column> | ||
| 48 | + </el-table> | ||
| 49 | + | ||
| 50 | + <div class="margin-top"> | ||
| 51 | + <span>{{ $t('printQuestionAnswerDetail.total') }}:{{ printQuestionAnswerDetailInfo.voteCount }}</span>; | ||
| 52 | + <span>{{ $t('printQuestionAnswerDetail.submitted') }}:{{ printQuestionAnswerDetailInfo.votedCount }}</span>; | ||
| 53 | + <span v-for="(item, tIndex) in printQuestionAnswerDetailInfo.titleValues" :key="tIndex"> | ||
| 54 | + {{ item.qaValue }}: {{ item.personCount }}{{ $t('printQuestionAnswerDetail.people') }}; | ||
| 55 | + </span> | ||
| 56 | + </div> | ||
| 57 | + | ||
| 58 | + <div class="text-right margin-top"> | ||
| 59 | + {{ currentCommunity.name }} | ||
| 60 | + </div> | ||
| 61 | + <div class="text-right margin-top-sm"> | ||
| 62 | + {{ currentDate }} | ||
| 63 | + </div> | ||
| 64 | + </el-col> | ||
| 65 | + </el-row> | ||
| 66 | + | ||
| 67 | + <div id="print-btn" class="margin-top"> | ||
| 68 | + <el-button type="primary" class="float-right" @click="_printPurchaseApplyDiv"> | ||
| 69 | + <i class="el-icon-printer"></i> {{ $t('printQuestionAnswerDetail.print') }} | ||
| 70 | + </el-button> | ||
| 71 | + <el-button type="warning" class="float-right margin-right" @click="_closePage"> | ||
| 72 | + <i class="el-icon-close"></i> | ||
| 73 | + {{ $t('printQuestionAnswerDetail.cancel') }} | ||
| 74 | + </el-button> | ||
| 75 | + </div> | ||
| 76 | + </div> | ||
| 77 | +</template> | ||
| 78 | + | ||
| 79 | +<script> | ||
| 80 | +import { getCommunityId ,getCommunity} from '@/api/community/communityApi' | ||
| 81 | +import { | ||
| 82 | + listQuestionAnswer, | ||
| 83 | + listQuestionTitle, | ||
| 84 | + listUserQuestionAnswer | ||
| 85 | +} from '@/api/oa/printQuestionAnswerDetailApi' | ||
| 86 | + | ||
| 87 | +export default { | ||
| 88 | + name: 'PrintQuestionAnswerDetailList', | ||
| 89 | + data() { | ||
| 90 | + return { | ||
| 91 | + printQuestionAnswerDetailInfo: { | ||
| 92 | + qaName: '', | ||
| 93 | + startTime: '', | ||
| 94 | + endTime: '', | ||
| 95 | + communityId: '', | ||
| 96 | + content: '', | ||
| 97 | + titleType: '', | ||
| 98 | + questionTitles: [], | ||
| 99 | + updateRoomIds: false, | ||
| 100 | + voteCount: 0, | ||
| 101 | + qaId: '', | ||
| 102 | + votedCount: 0, | ||
| 103 | + userQuestions: [], | ||
| 104 | + roomId: '', | ||
| 105 | + userQuestion: {} | ||
| 106 | + }, | ||
| 107 | + currentCommunity: {}, | ||
| 108 | + currentDate: new Date().toLocaleDateString() | ||
| 109 | + } | ||
| 110 | + }, | ||
| 111 | + created() { | ||
| 112 | + this.printQuestionAnswerDetailInfo.communityId = getCommunityId() | ||
| 113 | + this.currentCommunity = getCommunity() | ||
| 114 | + this.printQuestionAnswerDetailInfo.qaId = this.$route.query.qaId | ||
| 115 | + this._listValues() | ||
| 116 | + }, | ||
| 117 | + methods: { | ||
| 118 | + async _listQuestionAnswers() { | ||
| 119 | + try { | ||
| 120 | + const params = { | ||
| 121 | + page: 1, | ||
| 122 | + row: 1, | ||
| 123 | + communityId: this.printQuestionAnswerDetailInfo.communityId, | ||
| 124 | + qaId: this.printQuestionAnswerDetailInfo.qaId | ||
| 125 | + } | ||
| 126 | + const { data } = await listQuestionAnswer(params) | ||
| 127 | + Object.assign(this.printQuestionAnswerDetailInfo, data[0]) | ||
| 128 | + } catch (error) { | ||
| 129 | + console.error('Failed to load question answers:', error) | ||
| 130 | + } | ||
| 131 | + }, | ||
| 132 | + async _loadQuestionTitles() { | ||
| 133 | + try { | ||
| 134 | + const params = { | ||
| 135 | + page: 1, | ||
| 136 | + row: 100, | ||
| 137 | + communityId: this.printQuestionAnswerDetailInfo.communityId, | ||
| 138 | + qaId: this.printQuestionAnswerDetailInfo.qaId | ||
| 139 | + } | ||
| 140 | + const { data } = await listQuestionTitle(params) | ||
| 141 | + this.printQuestionAnswerDetailInfo.questionTitles = data | ||
| 142 | + } catch (error) { | ||
| 143 | + console.error('Failed to load question titles:', error) | ||
| 144 | + } | ||
| 145 | + }, | ||
| 146 | + _printPurchaseApplyDiv() { | ||
| 147 | + this.printFlag = '1' | ||
| 148 | + document.getElementById("print-btn").style.display = "none" | ||
| 149 | + document.getElementById("print-room").style.display = "none" | ||
| 150 | + window.print() | ||
| 151 | + window.opener = null | ||
| 152 | + window.close() | ||
| 153 | + }, | ||
| 154 | + _closePage() { | ||
| 155 | + window.opener = null | ||
| 156 | + window.close() | ||
| 157 | + }, | ||
| 158 | + _getTitleTypeName(_titleType) { | ||
| 159 | + if (_titleType === '1001') { | ||
| 160 | + return this.$t('printQuestionAnswerDetail.singleChoice') | ||
| 161 | + } else if (_titleType === '2002') { | ||
| 162 | + return this.$t('printQuestionAnswerDetail.multipleChoice') | ||
| 163 | + } else { | ||
| 164 | + return this.$t('printQuestionAnswerDetail.shortAnswer') | ||
| 165 | + } | ||
| 166 | + }, | ||
| 167 | + swatchRoom(_room) { | ||
| 168 | + this.printQuestionAnswerDetailInfo.roomId = _room.roomId | ||
| 169 | + this.printQuestionAnswerDetailInfo.userQuestion = _room | ||
| 170 | + }, | ||
| 171 | + async _listValues() { | ||
| 172 | + try { | ||
| 173 | + const params = { | ||
| 174 | + page: 1, | ||
| 175 | + row: 500, | ||
| 176 | + communityId: this.printQuestionAnswerDetailInfo.communityId, | ||
| 177 | + qaId: this.printQuestionAnswerDetailInfo.qaId | ||
| 178 | + } | ||
| 179 | + const { data } = await listUserQuestionAnswer(params) | ||
| 180 | + this.printQuestionAnswerDetailInfo.userQuestions = data | ||
| 181 | + await this._listQuestionAnswers() | ||
| 182 | + await this._loadQuestionTitles() | ||
| 183 | + if (data && data.length > 0) { | ||
| 184 | + this.swatchRoom(data[0]) | ||
| 185 | + } | ||
| 186 | + } catch (error) { | ||
| 187 | + console.error('Failed to load user question answers:', error) | ||
| 188 | + } | ||
| 189 | + }, | ||
| 190 | + _getChooseValue(_title) { | ||
| 191 | + const _userQuestion = this.printQuestionAnswerDetailInfo.userQuestion | ||
| 192 | + let _chooseValue = 'X' | ||
| 193 | + if (_userQuestion['values']) { | ||
| 194 | + _userQuestion.values.forEach(tmpValue => { | ||
| 195 | + if (tmpValue.qaValue === _title.qaValue) { | ||
| 196 | + _chooseValue = 'V' | ||
| 197 | + } | ||
| 198 | + }) | ||
| 199 | + } | ||
| 200 | + return _chooseValue | ||
| 201 | + } | ||
| 202 | + } | ||
| 203 | +} | ||
| 204 | +</script> | ||
| 205 | + | ||
| 206 | +<style lang="scss" scoped> | ||
| 207 | +.print-question-answer-detail-container { | ||
| 208 | + padding: 20px; | ||
| 209 | + | ||
| 210 | + .tree-card { | ||
| 211 | + height: 100%; | ||
| 212 | + | ||
| 213 | + .room-list { | ||
| 214 | + list-style: none; | ||
| 215 | + padding: 0; | ||
| 216 | + margin: 0; | ||
| 217 | + | ||
| 218 | + li { | ||
| 219 | + padding: 10px; | ||
| 220 | + margin-bottom: 5px; | ||
| 221 | + cursor: pointer; | ||
| 222 | + border-radius: 4px; | ||
| 223 | + text-align: center; | ||
| 224 | + transition: all 0.3s; | ||
| 225 | + | ||
| 226 | + &:hover { | ||
| 227 | + background-color: #f5f7fa; | ||
| 228 | + } | ||
| 229 | + | ||
| 230 | + &.selected-room { | ||
| 231 | + background-color: #409eff; | ||
| 232 | + color: white; | ||
| 233 | + } | ||
| 234 | + } | ||
| 235 | + } | ||
| 236 | + } | ||
| 237 | + | ||
| 238 | + .margin-top { | ||
| 239 | + margin-top: 20px; | ||
| 240 | + } | ||
| 241 | + | ||
| 242 | + .margin-top-sm { | ||
| 243 | + margin-top: 10px; | ||
| 244 | + } | ||
| 245 | + | ||
| 246 | + .margin-right { | ||
| 247 | + margin-right: 20px; | ||
| 248 | + } | ||
| 249 | + | ||
| 250 | + .float-right { | ||
| 251 | + float: right; | ||
| 252 | + } | ||
| 253 | + | ||
| 254 | + .text-center { | ||
| 255 | + text-align: center; | ||
| 256 | + } | ||
| 257 | + | ||
| 258 | + .text-right { | ||
| 259 | + text-align: right; | ||
| 260 | + } | ||
| 261 | +} | ||
| 262 | + | ||
| 263 | +#print-btn, | ||
| 264 | +#print-room { | ||
| 265 | + @media print { | ||
| 266 | + display: none !important; | ||
| 267 | + } | ||
| 268 | +} | ||
| 269 | +</style> | ||
| 0 | \ No newline at end of file | 270 | \ No newline at end of file |
src/views/oa/printQuestionAnswerLang.js
0 → 100644
| 1 | +export const messages = { | ||
| 2 | + en: { | ||
| 3 | + printQuestionAnswer: { | ||
| 4 | + table: { | ||
| 5 | + name: 'Name', | ||
| 6 | + type: 'Type', | ||
| 7 | + options: 'Options', | ||
| 8 | + selectCount: 'Select Count' | ||
| 9 | + }, | ||
| 10 | + type: { | ||
| 11 | + single: 'Single Choice', | ||
| 12 | + multiple: 'Multiple Choice', | ||
| 13 | + shortAnswer: 'Short Answer' | ||
| 14 | + }, | ||
| 15 | + label: { | ||
| 16 | + total: 'Total', | ||
| 17 | + submitted: 'Submitted' | ||
| 18 | + }, | ||
| 19 | + unit: { | ||
| 20 | + person: 'person(s)' | ||
| 21 | + } | ||
| 22 | + } | ||
| 23 | + }, | ||
| 24 | + zh: { | ||
| 25 | + printQuestionAnswer: { | ||
| 26 | + table: { | ||
| 27 | + name: '名称', | ||
| 28 | + type: '类型', | ||
| 29 | + options: '选项', | ||
| 30 | + selectCount: '选择人数' | ||
| 31 | + }, | ||
| 32 | + type: { | ||
| 33 | + single: '单选', | ||
| 34 | + multiple: '多选', | ||
| 35 | + shortAnswer: '简答' | ||
| 36 | + }, | ||
| 37 | + label: { | ||
| 38 | + total: '总数', | ||
| 39 | + submitted: '已提交' | ||
| 40 | + }, | ||
| 41 | + unit: { | ||
| 42 | + person: '人' | ||
| 43 | + } | ||
| 44 | + } | ||
| 45 | + } | ||
| 46 | +} | ||
| 0 | \ No newline at end of file | 47 | \ No newline at end of file |
src/views/oa/printQuestionAnswerList.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="print-question-answer-container"> | ||
| 3 | + <el-card> | ||
| 4 | + <div class="text-center"> | ||
| 5 | + <h1>{{ printQuestionAnswerInfo.qaName }}</h1> | ||
| 6 | + </div> | ||
| 7 | + <div v-html="printQuestionAnswerInfo.content"></div> | ||
| 8 | + | ||
| 9 | + <el-table :data="printQuestionAnswerInfo.questionTitles" border style="width: 100%" class="margin-top"> | ||
| 10 | + <el-table-column prop="qaTitle" :label="$t('printQuestionAnswer.table.name')" width="300" align="center"> | ||
| 11 | + <template slot-scope="{row}"> | ||
| 12 | + <div style="max-width: 300px;"> | ||
| 13 | + {{ row.qaTitle }} | ||
| 14 | + </div> | ||
| 15 | + </template> | ||
| 16 | + </el-table-column> | ||
| 17 | + <el-table-column prop="titleType" :label="$t('printQuestionAnswer.table.type')" width="300" align="center"> | ||
| 18 | + <template slot-scope="{row}"> | ||
| 19 | + {{ _getTitleTypeName(row.titleType) }} | ||
| 20 | + </template> | ||
| 21 | + </el-table-column> | ||
| 22 | + <el-table-column :label="$t('printQuestionAnswer.table.options')" align="center"> | ||
| 23 | + <template slot-scope="{row}"> | ||
| 24 | + <div v-for="(item, index) in row.titleValues" :key="index"> | ||
| 25 | + {{ item.seq }}、{{ item.qaValue }} | ||
| 26 | + </div> | ||
| 27 | + </template> | ||
| 28 | + </el-table-column> | ||
| 29 | + <el-table-column :label="$t('printQuestionAnswer.table.selectCount')" align="center"> | ||
| 30 | + <template slot-scope="{row}"> | ||
| 31 | + <div v-for="(item, index) in row.titleValues" :key="index"> | ||
| 32 | + {{ item.personCount }} {{ $t('printQuestionAnswer.unit.person') }} | ||
| 33 | + </div> | ||
| 34 | + </template> | ||
| 35 | + </el-table-column> | ||
| 36 | + </el-table> | ||
| 37 | + | ||
| 38 | + <div class="margin-top"> | ||
| 39 | + <span>{{ $t('printQuestionAnswer.label.total') }}:{{ printQuestionAnswerInfo.voteCount }}</span>; | ||
| 40 | + <span>{{ $t('printQuestionAnswer.label.submitted') }}:{{ printQuestionAnswerInfo.votedCount }}</span>; | ||
| 41 | + <span v-for="(item, tIndex) in printQuestionAnswerInfo.titleValues" :key="tIndex"> | ||
| 42 | + {{ item.qaValue }}: {{ item.personCount }}{{ $t('printQuestionAnswer.unit.person') }}; | ||
| 43 | + </span> | ||
| 44 | + </div> | ||
| 45 | + | ||
| 46 | + <div class="text-right margin-top margin-right"> | ||
| 47 | + {{ currentCommunity.name }} | ||
| 48 | + </div> | ||
| 49 | + <div class="text-right margin-top-sm margin-right"> | ||
| 50 | + {{ dateFormat(new Date()) }} | ||
| 51 | + </div> | ||
| 52 | + | ||
| 53 | + <div id="print-btn" class="text-right margin-top"> | ||
| 54 | + <el-button type="primary" @click="_printPurchaseApplyDiv"> | ||
| 55 | + <i class="el-icon-printer"></i> {{ $t('common.print') }} | ||
| 56 | + </el-button> | ||
| 57 | + <el-button type="warning" style="margin-left: 20px;" @click="_closePage"> | ||
| 58 | + <i class="el-icon-close"></i> | ||
| 59 | + {{ $t('common.cancel') }} | ||
| 60 | + </el-button> | ||
| 61 | + </div> | ||
| 62 | + </el-card> | ||
| 63 | + </div> | ||
| 64 | +</template> | ||
| 65 | + | ||
| 66 | +<script> | ||
| 67 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 68 | +import { | ||
| 69 | + listQuestionAnswer, | ||
| 70 | + listQuestionTitle | ||
| 71 | +} from '@/api/oa/printQuestionAnswerApi' | ||
| 72 | +import { dateFormat } from '@/utils/dateUtil' | ||
| 73 | + | ||
| 74 | +export default { | ||
| 75 | + name: 'PrintQuestionAnswerList', | ||
| 76 | + data() { | ||
| 77 | + return { | ||
| 78 | + printQuestionAnswerInfo: { | ||
| 79 | + qaName: '', | ||
| 80 | + startTime: '', | ||
| 81 | + endTime: '', | ||
| 82 | + communityId: '', | ||
| 83 | + content: '', | ||
| 84 | + titleType: '', | ||
| 85 | + questionTitles: [], | ||
| 86 | + updateRoomIds: false, | ||
| 87 | + voteCount: 0, | ||
| 88 | + qaId: '', | ||
| 89 | + votedCount: 0 | ||
| 90 | + }, | ||
| 91 | + currentCommunity: { | ||
| 92 | + name: '', | ||
| 93 | + communityId: '' | ||
| 94 | + } | ||
| 95 | + } | ||
| 96 | + }, | ||
| 97 | + created() { | ||
| 98 | + this.printQuestionAnswerInfo.qaId = this.$route.query.qaId | ||
| 99 | + this.currentCommunity.communityId = getCommunityId() | ||
| 100 | + this._listQuestionAnswers() | ||
| 101 | + this._loadQuestionTitles() | ||
| 102 | + }, | ||
| 103 | + methods: { | ||
| 104 | + async _listQuestionAnswers() { | ||
| 105 | + try { | ||
| 106 | + const params = { | ||
| 107 | + page: 1, | ||
| 108 | + row: 1, | ||
| 109 | + communityId: this.currentCommunity.communityId, | ||
| 110 | + qaId: this.printQuestionAnswerInfo.qaId | ||
| 111 | + } | ||
| 112 | + const { data } = await listQuestionAnswer(params) | ||
| 113 | + this.printQuestionAnswerInfo = Object.assign( | ||
| 114 | + this.printQuestionAnswerInfo, | ||
| 115 | + data[0] | ||
| 116 | + ) | ||
| 117 | + } catch (error) { | ||
| 118 | + console.error('Failed to load question answers:', error) | ||
| 119 | + } | ||
| 120 | + }, | ||
| 121 | + async _loadQuestionTitles() { | ||
| 122 | + try { | ||
| 123 | + const params = { | ||
| 124 | + page: 1, | ||
| 125 | + row: 100, | ||
| 126 | + communityId: this.currentCommunity.communityId, | ||
| 127 | + qaId: this.printQuestionAnswerInfo.qaId | ||
| 128 | + } | ||
| 129 | + const { data } = await listQuestionTitle(params) | ||
| 130 | + this.printQuestionAnswerInfo.questionTitles = data | ||
| 131 | + } catch (error) { | ||
| 132 | + console.error('Failed to load question titles:', error) | ||
| 133 | + } | ||
| 134 | + }, | ||
| 135 | + _printPurchaseApplyDiv() { | ||
| 136 | + this.printFlag = '1' | ||
| 137 | + document.getElementById("print-btn").style.display = "none" | ||
| 138 | + window.print() | ||
| 139 | + window.opener = null | ||
| 140 | + window.close() | ||
| 141 | + }, | ||
| 142 | + _closePage() { | ||
| 143 | + window.opener = null | ||
| 144 | + window.close() | ||
| 145 | + }, | ||
| 146 | + _getTitleTypeName(_titleType) { | ||
| 147 | + if (_titleType == '1001') { | ||
| 148 | + return this.$t('printQuestionAnswer.type.single') | ||
| 149 | + } else if (_titleType == '2002') { | ||
| 150 | + return this.$t('printQuestionAnswer.type.multiple') | ||
| 151 | + } else { | ||
| 152 | + return this.$t('printQuestionAnswer.type.shortAnswer') | ||
| 153 | + } | ||
| 154 | + }, | ||
| 155 | + dateFormat | ||
| 156 | + } | ||
| 157 | +} | ||
| 158 | +</script> | ||
| 159 | + | ||
| 160 | +<style lang="scss" scoped> | ||
| 161 | +.print-question-answer-container { | ||
| 162 | + padding: 20px; | ||
| 163 | + | ||
| 164 | + .margin-top { | ||
| 165 | + margin-top: 20px; | ||
| 166 | + } | ||
| 167 | + | ||
| 168 | + .margin-top-sm { | ||
| 169 | + margin-top: 10px; | ||
| 170 | + } | ||
| 171 | + | ||
| 172 | + .margin-right { | ||
| 173 | + margin-right: 20px; | ||
| 174 | + } | ||
| 175 | + | ||
| 176 | + .text-center { | ||
| 177 | + text-align: center; | ||
| 178 | + } | ||
| 179 | + | ||
| 180 | + .text-right { | ||
| 181 | + text-align: right; | ||
| 182 | + } | ||
| 183 | +} | ||
| 184 | +</style> | ||
| 0 | \ No newline at end of file | 185 | \ No newline at end of file |
src/views/oa/questionAnswerManageLang.js
0 → 100644
| 1 | +export const messages = { | ||
| 2 | + en: { | ||
| 3 | + questionAnswerManage: { | ||
| 4 | + search: { | ||
| 5 | + title: 'Search Conditions', | ||
| 6 | + qaName: 'Please enter questionnaire name' | ||
| 7 | + }, | ||
| 8 | + list: { | ||
| 9 | + title: 'Questionnaire Survey' | ||
| 10 | + }, | ||
| 11 | + table: { | ||
| 12 | + qaName: 'Questionnaire Name', | ||
| 13 | + validity: 'Validity Period', | ||
| 14 | + voteCount: 'Total/Completed', | ||
| 15 | + score: 'Score', | ||
| 16 | + state: 'Status', | ||
| 17 | + createTime: 'Create Time' | ||
| 18 | + }, | ||
| 19 | + state: { | ||
| 20 | + published: 'Published', | ||
| 21 | + unpublished: 'Unpublished' | ||
| 22 | + }, | ||
| 23 | + button: { | ||
| 24 | + result: 'Result', | ||
| 25 | + detail: 'Detail', | ||
| 26 | + publish: 'Publish' | ||
| 27 | + }, | ||
| 28 | + edit: { | ||
| 29 | + title: 'Edit Questionnaire', | ||
| 30 | + qaType: 'Questionnaire Type', | ||
| 31 | + qaTypePlaceholder: 'Required, please select questionnaire type', | ||
| 32 | + qaType1: 'Owner Questionnaire', | ||
| 33 | + qaType3: 'Owner Voting', | ||
| 34 | + qaType4: 'Staff Voting', | ||
| 35 | + qaName: 'Name', | ||
| 36 | + qaNamePlaceholder: 'Required, please enter name', | ||
| 37 | + startTime: 'Start Time', | ||
| 38 | + startTimePlaceholder: 'Required, please enter start time', | ||
| 39 | + endTime: 'End Time', | ||
| 40 | + endTimePlaceholder: 'Required, please enter end time', | ||
| 41 | + content: 'Content', | ||
| 42 | + contentPlaceholder: 'Optional, please enter content', | ||
| 43 | + remark: 'Remark', | ||
| 44 | + remarkPlaceholder: 'Optional, please enter remark', | ||
| 45 | + photos: 'Photos' | ||
| 46 | + }, | ||
| 47 | + delete: { | ||
| 48 | + title: 'Confirm Operation', | ||
| 49 | + confirmText: 'Are you sure to delete this questionnaire?' | ||
| 50 | + }, | ||
| 51 | + publish: { | ||
| 52 | + title: 'Publish Questionnaire', | ||
| 53 | + qaName: 'Name', | ||
| 54 | + tip: 'Reminder', | ||
| 55 | + tipText: 'After publishing, it cannot be modified again. Please confirm before publishing!', | ||
| 56 | + notifyWay: 'Notification Method', | ||
| 57 | + notifyWayPlaceholder: 'Required, please select notification method', | ||
| 58 | + notifyWay1: 'SMS', | ||
| 59 | + notifyWay2: 'WeChat Message', | ||
| 60 | + notifyWay3: 'No Notification', | ||
| 61 | + button: 'Publish' | ||
| 62 | + }, | ||
| 63 | + validate: { | ||
| 64 | + qaType: 'Questionnaire type is required', | ||
| 65 | + qaName: 'Questionnaire name is required', | ||
| 66 | + qaNameMax: 'Questionnaire name is too long', | ||
| 67 | + startTime: 'Start time is required', | ||
| 68 | + endTime: 'End time is required', | ||
| 69 | + notifyWay: 'Notification method is required' | ||
| 70 | + }, | ||
| 71 | + message: { | ||
| 72 | + updateSuccess: 'Update successfully', | ||
| 73 | + updateError: 'Update failed', | ||
| 74 | + deleteSuccess: 'Delete successfully', | ||
| 75 | + deleteError: 'Delete failed', | ||
| 76 | + publishSuccess: 'Publish successfully', | ||
| 77 | + publishError: 'Publish failed', | ||
| 78 | + fetchError: 'Failed to fetch data' | ||
| 79 | + } | ||
| 80 | + }, | ||
| 81 | + uploadImage: { | ||
| 82 | + validate: { | ||
| 83 | + imageType: 'Only image files are allowed', | ||
| 84 | + imageSize: 'Image size cannot exceed 2MB' | ||
| 85 | + }, | ||
| 86 | + message: { | ||
| 87 | + uploadError: 'Image upload failed' | ||
| 88 | + } | ||
| 89 | + } | ||
| 90 | + }, | ||
| 91 | + zh: { | ||
| 92 | + questionAnswerManage: { | ||
| 93 | + search: { | ||
| 94 | + title: '查询条件', | ||
| 95 | + qaName: '请输入问卷名称' | ||
| 96 | + }, | ||
| 97 | + list: { | ||
| 98 | + title: '问卷调研' | ||
| 99 | + }, | ||
| 100 | + table: { | ||
| 101 | + qaName: '问卷名称', | ||
| 102 | + validity: '有效期', | ||
| 103 | + voteCount: '总问卷/已问卷', | ||
| 104 | + score: '得分', | ||
| 105 | + state: '状态', | ||
| 106 | + createTime: '创建时间' | ||
| 107 | + }, | ||
| 108 | + state: { | ||
| 109 | + published: '已发布', | ||
| 110 | + unpublished: '待发布' | ||
| 111 | + }, | ||
| 112 | + button: { | ||
| 113 | + result: '结果', | ||
| 114 | + detail: '明细', | ||
| 115 | + publish: '发布' | ||
| 116 | + }, | ||
| 117 | + edit: { | ||
| 118 | + title: '修改问卷信息', | ||
| 119 | + qaType: '问卷类型', | ||
| 120 | + qaTypePlaceholder: '必填,请选择问卷类型', | ||
| 121 | + qaType1: '业主问卷', | ||
| 122 | + qaType3: '业主投票', | ||
| 123 | + qaType4: '员工投票', | ||
| 124 | + qaName: '名称', | ||
| 125 | + qaNamePlaceholder: '必填,请填写名称', | ||
| 126 | + startTime: '开始时间', | ||
| 127 | + startTimePlaceholder: '必填,请填写开始时间', | ||
| 128 | + endTime: '结束时间', | ||
| 129 | + endTimePlaceholder: '必填,请填写结束时间', | ||
| 130 | + content: '内容', | ||
| 131 | + contentPlaceholder: '选填,请填写内容', | ||
| 132 | + remark: '备注', | ||
| 133 | + remarkPlaceholder: '选填,请填写备注', | ||
| 134 | + photos: '图片' | ||
| 135 | + }, | ||
| 136 | + delete: { | ||
| 137 | + title: '请确认您的操作', | ||
| 138 | + confirmText: '确定删除问卷信息' | ||
| 139 | + }, | ||
| 140 | + publish: { | ||
| 141 | + title: '发布', | ||
| 142 | + qaName: '名称', | ||
| 143 | + tip: '温馨提示', | ||
| 144 | + tipText: '发布后将无法再次修改,请确认无误后再发布!', | ||
| 145 | + notifyWay: '通知方式', | ||
| 146 | + notifyWayPlaceholder: '必填,请选择通知方式', | ||
| 147 | + notifyWay1: '短信', | ||
| 148 | + notifyWay2: '微信消息', | ||
| 149 | + notifyWay3: '不通知', | ||
| 150 | + button: '发布' | ||
| 151 | + }, | ||
| 152 | + validate: { | ||
| 153 | + qaType: '问卷类型不能为空', | ||
| 154 | + qaName: '问卷名称不能为空', | ||
| 155 | + qaNameMax: '问卷名称太长', | ||
| 156 | + startTime: '开始时间不能为空', | ||
| 157 | + endTime: '结束时间不能为空', | ||
| 158 | + notifyWay: '通知方式不能为空' | ||
| 159 | + }, | ||
| 160 | + message: { | ||
| 161 | + updateSuccess: '修改成功', | ||
| 162 | + updateError: '修改失败', | ||
| 163 | + deleteSuccess: '删除成功', | ||
| 164 | + deleteError: '删除失败', | ||
| 165 | + publishSuccess: '发布成功', | ||
| 166 | + publishError: '发布失败', | ||
| 167 | + fetchError: '获取数据失败' | ||
| 168 | + } | ||
| 169 | + }, | ||
| 170 | + uploadImage: { | ||
| 171 | + validate: { | ||
| 172 | + imageType: '只能上传图片文件', | ||
| 173 | + imageSize: '图片大小不能超过2MB' | ||
| 174 | + }, | ||
| 175 | + message: { | ||
| 176 | + uploadError: '图片上传失败' | ||
| 177 | + } | ||
| 178 | + } | ||
| 179 | + } | ||
| 180 | +} | ||
| 0 | \ No newline at end of file | 181 | \ No newline at end of file |
src/views/oa/questionAnswerManageList.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="question-answer-manage-container"> | ||
| 3 | + <!-- 查询条件 --> | ||
| 4 | + <el-card class="search-wrapper"> | ||
| 5 | + <div slot="header" class="flex justify-between"> | ||
| 6 | + <span>{{ $t('questionAnswerManage.search.title') }}</span> | ||
| 7 | + </div> | ||
| 8 | + <el-row :gutter="20"> | ||
| 9 | + <el-col :span="8"> | ||
| 10 | + <el-input v-model="searchForm.qaName" :placeholder="$t('questionAnswerManage.search.qaName')" clearable | ||
| 11 | + @keyup.enter.native="handleSearch" /> | ||
| 12 | + </el-col> | ||
| 13 | + <el-col :span="8"> | ||
| 14 | + <el-button type="primary" @click="handleSearch"> | ||
| 15 | + <i class="el-icon-search"></i> | ||
| 16 | + {{ $t('common.search') }} | ||
| 17 | + </el-button> | ||
| 18 | + <el-button @click="handleReset"> | ||
| 19 | + <i class="el-icon-refresh"></i> | ||
| 20 | + {{ $t('common.reset') }} | ||
| 21 | + </el-button> | ||
| 22 | + </el-col> | ||
| 23 | + </el-row> | ||
| 24 | + </el-card> | ||
| 25 | + | ||
| 26 | + <!-- 问卷列表 --> | ||
| 27 | + <el-card class="list-wrapper"> | ||
| 28 | + <div slot="header" class="flex justify-between"> | ||
| 29 | + <span>{{ $t('questionAnswerManage.list.title') }}</span> | ||
| 30 | + <el-button type="primary" size="small" style="float: right;" @click="handleAdd"> | ||
| 31 | + <i class="el-icon-plus"></i> | ||
| 32 | + {{ $t('common.add') }} | ||
| 33 | + </el-button> | ||
| 34 | + </div> | ||
| 35 | + | ||
| 36 | + <el-table v-loading="loading" :data="tableData" border style="width: 100%"> | ||
| 37 | + <el-table-column prop="qaName" :label="$t('questionAnswerManage.table.qaName')" align="center" /> | ||
| 38 | + <el-table-column :label="$t('questionAnswerManage.table.validity')" align="center"> | ||
| 39 | + <template slot-scope="scope"> | ||
| 40 | + <div>{{ scope.row.startTime }}</div> | ||
| 41 | + <div>{{ scope.row.endTime }}</div> | ||
| 42 | + </template> | ||
| 43 | + </el-table-column> | ||
| 44 | + <el-table-column :label="$t('questionAnswerManage.table.voteCount')" align="center"> | ||
| 45 | + <template slot-scope="scope"> | ||
| 46 | + {{ scope.row.voteCount }}/{{ scope.row.votedCount }} | ||
| 47 | + </template> | ||
| 48 | + </el-table-column> | ||
| 49 | + <el-table-column prop="score" :label="$t('questionAnswerManage.table.score')" align="center" /> | ||
| 50 | + <el-table-column :label="$t('questionAnswerManage.table.state')" align="center"> | ||
| 51 | + <template slot-scope="scope"> | ||
| 52 | + {{ scope.row.state === 'C' ? $t('questionAnswerManage.state.published') : | ||
| 53 | + $t('questionAnswerManage.state.unpublished') }} | ||
| 54 | + </template> | ||
| 55 | + </el-table-column> | ||
| 56 | + <el-table-column prop="createTime" :label="$t('questionAnswerManage.table.createTime')" align="center" /> | ||
| 57 | + <el-table-column :label="$t('common.operation')" align="center" width="300"> | ||
| 58 | + <template slot-scope="scope"> | ||
| 59 | + <el-button size="mini" @click="handleResult(scope.row)"> | ||
| 60 | + {{ $t('questionAnswerManage.button.result') }} | ||
| 61 | + </el-button> | ||
| 62 | + <el-button size="mini" @click="handleDetail(scope.row)"> | ||
| 63 | + {{ $t('questionAnswerManage.button.detail') }} | ||
| 64 | + </el-button> | ||
| 65 | + <el-button v-if="scope.row.state === 'W'" size="mini" type="success" @click="handlePublish(scope.row)"> | ||
| 66 | + {{ $t('questionAnswerManage.button.publish') }} | ||
| 67 | + </el-button> | ||
| 68 | + <el-button size="mini" type="primary" @click="handleEdit(scope.row)"> | ||
| 69 | + {{ $t('common.edit') }} | ||
| 70 | + </el-button> | ||
| 71 | + <el-button size="mini" type="danger" @click="handleDelete(scope.row)"> | ||
| 72 | + {{ $t('common.delete') }} | ||
| 73 | + </el-button> | ||
| 74 | + </template> | ||
| 75 | + </el-table-column> | ||
| 76 | + </el-table> | ||
| 77 | + | ||
| 78 | + <el-pagination :current-page.sync="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size" | ||
| 79 | + :total="page.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange" | ||
| 80 | + @current-change="handleCurrentChange" /> | ||
| 81 | + </el-card> | ||
| 82 | + | ||
| 83 | + <!-- 组件 --> | ||
| 84 | + <delete-question-answer ref="deleteDialog" @success="fetchData" /> | ||
| 85 | + <publish-question-answer ref="publishDialog" @success="fetchData" /> | ||
| 86 | + </div> | ||
| 87 | +</template> | ||
| 88 | + | ||
| 89 | +<script> | ||
| 90 | +import { listQuestionAnswer } from '@/api/oa/questionAnswerManageApi' | ||
| 91 | +import DeleteQuestionAnswer from '@/components/oa/deleteQuestionAnswer' | ||
| 92 | +import PublishQuestionAnswer from '@/components/oa/publishQuestionAnswer' | ||
| 93 | + | ||
| 94 | +export default { | ||
| 95 | + name: 'QuestionAnswerManageList', | ||
| 96 | + components: { | ||
| 97 | + DeleteQuestionAnswer, | ||
| 98 | + PublishQuestionAnswer | ||
| 99 | + }, | ||
| 100 | + data() { | ||
| 101 | + return { | ||
| 102 | + loading: false, | ||
| 103 | + searchForm: { | ||
| 104 | + qaName: '', | ||
| 105 | + qaType: '' | ||
| 106 | + }, | ||
| 107 | + tableData: [], | ||
| 108 | + page: { | ||
| 109 | + current: 1, | ||
| 110 | + size: 10, | ||
| 111 | + total: 0 | ||
| 112 | + } | ||
| 113 | + } | ||
| 114 | + }, | ||
| 115 | + created() { | ||
| 116 | + this.fetchData() | ||
| 117 | + }, | ||
| 118 | + methods: { | ||
| 119 | + async fetchData() { | ||
| 120 | + try { | ||
| 121 | + this.loading = true | ||
| 122 | + const params = { | ||
| 123 | + page: this.page.current, | ||
| 124 | + row: this.page.size, | ||
| 125 | + qaName: this.searchForm.qaName, | ||
| 126 | + qaType: this.searchForm.qaType | ||
| 127 | + } | ||
| 128 | + const { data, total } = await listQuestionAnswer(params) | ||
| 129 | + this.tableData = data | ||
| 130 | + this.page.total = total | ||
| 131 | + } catch (error) { | ||
| 132 | + this.$message.error(this.$t('questionAnswerManage.fetchError')) | ||
| 133 | + } finally { | ||
| 134 | + this.loading = false | ||
| 135 | + } | ||
| 136 | + }, | ||
| 137 | + handleSearch() { | ||
| 138 | + this.page.current = 1 | ||
| 139 | + this.fetchData() | ||
| 140 | + }, | ||
| 141 | + handleReset() { | ||
| 142 | + this.searchForm = { | ||
| 143 | + qaName: '', | ||
| 144 | + qaType: '' | ||
| 145 | + } | ||
| 146 | + this.handleSearch() | ||
| 147 | + }, | ||
| 148 | + handleAdd() { | ||
| 149 | + this.$router.push('/views/oa/addQuestionAnswer') | ||
| 150 | + }, | ||
| 151 | + handleEdit(row) { | ||
| 152 | + this.$router.push(`/views/oa/editQuestionAnswer?qaId=${row.qaId}`) | ||
| 153 | + }, | ||
| 154 | + handleDelete(row) { | ||
| 155 | + this.$refs.deleteDialog.open(row) | ||
| 156 | + }, | ||
| 157 | + handlePublish(row) { | ||
| 158 | + this.$refs.publishDialog.open(row) | ||
| 159 | + }, | ||
| 160 | + handleResult(row) { | ||
| 161 | + window.open(`/#/pages/question/printQuestionAnswer?qaId=${row.qaId}`) | ||
| 162 | + }, | ||
| 163 | + handleDetail(row) { | ||
| 164 | + window.open(`/#/pages/question/printQuestionAnswerDetail?qaId=${row.qaId}`) | ||
| 165 | + }, | ||
| 166 | + handleSizeChange(val) { | ||
| 167 | + this.page.size = val | ||
| 168 | + this.fetchData() | ||
| 169 | + }, | ||
| 170 | + handleCurrentChange(val) { | ||
| 171 | + this.page.current = val | ||
| 172 | + this.fetchData() | ||
| 173 | + } | ||
| 174 | + } | ||
| 175 | +} | ||
| 176 | +</script> | ||
| 177 | + | ||
| 178 | +<style lang="scss" scoped> | ||
| 179 | +.question-answer-manage-container { | ||
| 180 | + padding: 20px; | ||
| 181 | + | ||
| 182 | + .search-wrapper { | ||
| 183 | + margin-bottom: 20px; | ||
| 184 | + | ||
| 185 | + .el-row { | ||
| 186 | + margin-bottom: 20px; | ||
| 187 | + } | ||
| 188 | + } | ||
| 189 | + | ||
| 190 | + .list-wrapper { | ||
| 191 | + margin-bottom: 20px; | ||
| 192 | + } | ||
| 193 | + | ||
| 194 | + .el-pagination { | ||
| 195 | + margin-top: 20px; | ||
| 196 | + text-align: right; | ||
| 197 | + } | ||
| 198 | +} | ||
| 199 | +</style> | ||
| 0 | \ No newline at end of file | 200 | \ No newline at end of file |
src/views/oa/questionTitleLang.js
0 → 100644
| 1 | +export const messages = { | ||
| 2 | + en: { | ||
| 3 | + questionTitle: { | ||
| 4 | + search: { | ||
| 5 | + title: 'Search Conditions', | ||
| 6 | + itemTitlePlaceholder: 'Please enter question name', | ||
| 7 | + titleTypePlaceholder: 'Please select question type', | ||
| 8 | + pleaseSelect: 'Please select', | ||
| 9 | + singleChoice: 'Single Choice', | ||
| 10 | + multipleChoice: 'Multiple Choice', | ||
| 11 | + shortAnswer: 'Short Answer' | ||
| 12 | + }, | ||
| 13 | + list: { | ||
| 14 | + title: 'Questionnaire Questions' | ||
| 15 | + }, | ||
| 16 | + table: { | ||
| 17 | + name: 'Name', | ||
| 18 | + type: 'Type', | ||
| 19 | + options: 'Options', | ||
| 20 | + createTime: 'Create Time' | ||
| 21 | + }, | ||
| 22 | + types: { | ||
| 23 | + singleChoice: 'Single Choice', | ||
| 24 | + multipleChoice: 'Multiple Choice', | ||
| 25 | + shortAnswer: 'Short Answer' | ||
| 26 | + }, | ||
| 27 | + add: { | ||
| 28 | + title: 'Add Question', | ||
| 29 | + name: 'Name', | ||
| 30 | + namePlaceholder: 'Required, please fill in the name', | ||
| 31 | + nameRequired: 'Name cannot be empty', | ||
| 32 | + nameTooLong: 'Name is too long', | ||
| 33 | + type: 'Type', | ||
| 34 | + typePlaceholder: 'Required, please select type', | ||
| 35 | + typeRequired: 'Type cannot be empty', | ||
| 36 | + option: 'Option', | ||
| 37 | + optionPlaceholder: 'Required, please fill in the option content', | ||
| 38 | + optionRequired: 'Option content cannot be empty', | ||
| 39 | + addOption: 'Add Option', | ||
| 40 | + removeOption: 'Remove Option', | ||
| 41 | + pleaseSelect: 'Please select', | ||
| 42 | + success: 'Added successfully' | ||
| 43 | + }, | ||
| 44 | + edit: { | ||
| 45 | + title: 'Edit Question', | ||
| 46 | + name: 'Name', | ||
| 47 | + namePlaceholder: 'Required, please fill in the name', | ||
| 48 | + nameRequired: 'Name cannot be empty', | ||
| 49 | + nameTooLong: 'Name is too long', | ||
| 50 | + type: 'Type', | ||
| 51 | + typePlaceholder: 'Required, please select type', | ||
| 52 | + typeRequired: 'Type cannot be empty', | ||
| 53 | + option: 'Option', | ||
| 54 | + optionPlaceholder: 'Required, please fill in the option content', | ||
| 55 | + optionRequired: 'Option content cannot be empty', | ||
| 56 | + addOption: 'Add Option', | ||
| 57 | + removeOption: 'Remove Option', | ||
| 58 | + pleaseSelect: 'Please select', | ||
| 59 | + success: 'Updated successfully' | ||
| 60 | + }, | ||
| 61 | + delete: { | ||
| 62 | + title: 'Confirm Operation', | ||
| 63 | + confirmMessage: 'Are you sure to delete this question?', | ||
| 64 | + success: 'Deleted successfully' | ||
| 65 | + }, | ||
| 66 | + fetchError: 'Failed to fetch question data' | ||
| 67 | + } | ||
| 68 | + }, | ||
| 69 | + zh: { | ||
| 70 | + questionTitle: { | ||
| 71 | + search: { | ||
| 72 | + title: '查询条件', | ||
| 73 | + itemTitlePlaceholder: '请输入问题名称', | ||
| 74 | + titleTypePlaceholder: '请选择题目类型', | ||
| 75 | + pleaseSelect: '请选择', | ||
| 76 | + singleChoice: '单选', | ||
| 77 | + multipleChoice: '多选', | ||
| 78 | + shortAnswer: '简答' | ||
| 79 | + }, | ||
| 80 | + list: { | ||
| 81 | + title: '问卷题目' | ||
| 82 | + }, | ||
| 83 | + table: { | ||
| 84 | + name: '名称', | ||
| 85 | + type: '类型', | ||
| 86 | + options: '选项', | ||
| 87 | + createTime: '创建时间' | ||
| 88 | + }, | ||
| 89 | + types: { | ||
| 90 | + singleChoice: '单选', | ||
| 91 | + multipleChoice: '多选', | ||
| 92 | + shortAnswer: '简答' | ||
| 93 | + }, | ||
| 94 | + add: { | ||
| 95 | + title: '添加题目', | ||
| 96 | + name: '名称', | ||
| 97 | + namePlaceholder: '必填,请填写名称', | ||
| 98 | + nameRequired: '名称不能为空', | ||
| 99 | + nameTooLong: '名称太长', | ||
| 100 | + type: '类型', | ||
| 101 | + typePlaceholder: '必填,请选择类型', | ||
| 102 | + typeRequired: '类型不能为空', | ||
| 103 | + option: '选项', | ||
| 104 | + optionPlaceholder: '必填,请填写选项内容', | ||
| 105 | + optionRequired: '选项内容不能为空', | ||
| 106 | + addOption: '增加选项', | ||
| 107 | + removeOption: '删除选项', | ||
| 108 | + pleaseSelect: '请选择', | ||
| 109 | + success: '添加成功' | ||
| 110 | + }, | ||
| 111 | + edit: { | ||
| 112 | + title: '修改题目', | ||
| 113 | + name: '名称', | ||
| 114 | + namePlaceholder: '必填,请填写名称', | ||
| 115 | + nameRequired: '名称不能为空', | ||
| 116 | + nameTooLong: '名称太长', | ||
| 117 | + type: '类型', | ||
| 118 | + typePlaceholder: '必填,请选择类型', | ||
| 119 | + typeRequired: '类型不能为空', | ||
| 120 | + option: '选项', | ||
| 121 | + optionPlaceholder: '必填,请填写选项内容', | ||
| 122 | + optionRequired: '选项内容不能为空', | ||
| 123 | + addOption: '增加选项', | ||
| 124 | + removeOption: '删除选项', | ||
| 125 | + pleaseSelect: '请选择', | ||
| 126 | + success: '修改成功' | ||
| 127 | + }, | ||
| 128 | + delete: { | ||
| 129 | + title: '确认操作', | ||
| 130 | + confirmMessage: '确定删除该题目吗?', | ||
| 131 | + success: '删除成功' | ||
| 132 | + }, | ||
| 133 | + fetchError: '获取题目数据失败' | ||
| 134 | + } | ||
| 135 | + } | ||
| 136 | +} | ||
| 0 | \ No newline at end of file | 137 | \ No newline at end of file |
src/views/oa/questionTitleList.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="question-title-container"> | ||
| 3 | + <!-- 查询条件 --> | ||
| 4 | + <el-card class="search-wrapper"> | ||
| 5 | + <div slot="header" class="flex justify-between"> | ||
| 6 | + <span>{{ $t('questionTitle.search.title') }}</span> | ||
| 7 | + </div> | ||
| 8 | + <el-row :gutter="20"> | ||
| 9 | + <el-col :span="6"> | ||
| 10 | + <el-input v-model="searchForm.itemTitle" :placeholder="$t('questionTitle.search.itemTitlePlaceholder')" | ||
| 11 | + clearable /> | ||
| 12 | + </el-col> | ||
| 13 | + <el-col :span="6"> | ||
| 14 | + <el-select v-model="searchForm.titleType" :placeholder="$t('questionTitle.search.titleTypePlaceholder')" | ||
| 15 | + style="width:100%"> | ||
| 16 | + <el-option :label="$t('questionTitle.search.pleaseSelect')" value="" /> | ||
| 17 | + <el-option :label="$t('questionTitle.search.singleChoice')" value="1001" /> | ||
| 18 | + <el-option :label="$t('questionTitle.search.multipleChoice')" value="2002" /> | ||
| 19 | + <el-option :label="$t('questionTitle.search.shortAnswer')" value="3003" /> | ||
| 20 | + </el-select> | ||
| 21 | + </el-col> | ||
| 22 | + <el-col :span="12"> | ||
| 23 | + <el-button type="primary" @click="handleSearch"> | ||
| 24 | + <i class="el-icon-search"></i> | ||
| 25 | + {{ $t('common.search') }} | ||
| 26 | + </el-button> | ||
| 27 | + <el-button @click="handleReset"> | ||
| 28 | + <i class="el-icon-refresh"></i> | ||
| 29 | + {{ $t('common.reset') }} | ||
| 30 | + </el-button> | ||
| 31 | + </el-col> | ||
| 32 | + </el-row> | ||
| 33 | + </el-card> | ||
| 34 | + | ||
| 35 | + <!-- 问卷题目列表 --> | ||
| 36 | + <el-card class="list-wrapper"> | ||
| 37 | + <div slot="header" class="flex justify-between"> | ||
| 38 | + <span>{{ $t('questionTitle.list.title') }}</span> | ||
| 39 | + <el-button type="primary" size="small" style="float:right" @click="handleAdd"> | ||
| 40 | + <i class="el-icon-plus"></i> | ||
| 41 | + {{ $t('common.add') }} | ||
| 42 | + </el-button> | ||
| 43 | + </div> | ||
| 44 | + | ||
| 45 | + <el-table v-loading="loading" :data="tableData" border style="width:100%"> | ||
| 46 | + <el-table-column prop="qaTitle" :label="$t('questionTitle.table.name')" align="center" /> | ||
| 47 | + <el-table-column prop="titleType" :label="$t('questionTitle.table.type')" align="center"> | ||
| 48 | + <template slot-scope="scope"> | ||
| 49 | + {{ getTitleTypeName(scope.row.titleType) }} | ||
| 50 | + </template> | ||
| 51 | + </el-table-column> | ||
| 52 | + <el-table-column :label="$t('questionTitle.table.options')" align="center"> | ||
| 53 | + <template slot-scope="scope"> | ||
| 54 | + <div v-for="(item, index) in scope.row.titleValues" :key="index"> | ||
| 55 | + {{ item.seq }}、{{ item.qaValue }} | ||
| 56 | + </div> | ||
| 57 | + </template> | ||
| 58 | + </el-table-column> | ||
| 59 | + <el-table-column prop="createTime" :label="$t('questionTitle.table.createTime')" align="center" /> | ||
| 60 | + <el-table-column :label="$t('common.operation')" align="center" width="200"> | ||
| 61 | + <template slot-scope="scope"> | ||
| 62 | + <el-button size="mini" type="primary" @click="handleEdit(scope.row)"> | ||
| 63 | + {{ $t('common.edit') }} | ||
| 64 | + </el-button> | ||
| 65 | + <el-button size="mini" type="danger" @click="handleDelete(scope.row)"> | ||
| 66 | + {{ $t('common.delete') }} | ||
| 67 | + </el-button> | ||
| 68 | + </template> | ||
| 69 | + </el-table-column> | ||
| 70 | + </el-table> | ||
| 71 | + | ||
| 72 | + <el-pagination :current-page="pagination.current" :page-sizes="[10, 20, 30, 50]" :page-size="pagination.size" | ||
| 73 | + :total="pagination.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange" | ||
| 74 | + @current-change="handleCurrentChange" /> | ||
| 75 | + </el-card> | ||
| 76 | + | ||
| 77 | + <!-- 添加题目对话框 --> | ||
| 78 | + <add-question-title ref="addDialog" @success="handleSuccess" /> | ||
| 79 | + | ||
| 80 | + <!-- 编辑题目对话框 --> | ||
| 81 | + <edit-question-title ref="editDialog" @success="handleSuccess" /> | ||
| 82 | + | ||
| 83 | + <!-- 删除题目对话框 --> | ||
| 84 | + <delete-question-title ref="deleteDialog" @success="handleSuccess" /> | ||
| 85 | + </div> | ||
| 86 | +</template> | ||
| 87 | + | ||
| 88 | +<script> | ||
| 89 | +import { listQuestionTitle } from '@/api/oa/questionTitleApi' | ||
| 90 | +import AddQuestionTitle from '@/components/oa/addQuestionTitle' | ||
| 91 | +import EditQuestionTitle from '@/components/oa/editQuestionTitle' | ||
| 92 | +import DeleteQuestionTitle from '@/components/oa/deleteQuestionTitle' | ||
| 93 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 94 | + | ||
| 95 | +export default { | ||
| 96 | + name: 'QuestionTitleList', | ||
| 97 | + components: { | ||
| 98 | + AddQuestionTitle, | ||
| 99 | + EditQuestionTitle, | ||
| 100 | + DeleteQuestionTitle | ||
| 101 | + }, | ||
| 102 | + data() { | ||
| 103 | + return { | ||
| 104 | + loading: false, | ||
| 105 | + searchForm: { | ||
| 106 | + itemTitle: '', | ||
| 107 | + titleType: '', | ||
| 108 | + communityId: '' | ||
| 109 | + }, | ||
| 110 | + tableData: [], | ||
| 111 | + pagination: { | ||
| 112 | + current: 1, | ||
| 113 | + size: 10, | ||
| 114 | + total: 0 | ||
| 115 | + } | ||
| 116 | + } | ||
| 117 | + }, | ||
| 118 | + created() { | ||
| 119 | + this.searchForm.communityId = getCommunityId() | ||
| 120 | + this.getList() | ||
| 121 | + }, | ||
| 122 | + methods: { | ||
| 123 | + async getList() { | ||
| 124 | + try { | ||
| 125 | + this.loading = true | ||
| 126 | + const params = { | ||
| 127 | + page: this.pagination.current, | ||
| 128 | + row: this.pagination.size, | ||
| 129 | + ...this.searchForm | ||
| 130 | + } | ||
| 131 | + const { data, total } = await listQuestionTitle(params) | ||
| 132 | + this.tableData = data | ||
| 133 | + this.pagination.total = total | ||
| 134 | + } catch (error) { | ||
| 135 | + this.$message.error(this.$t('questionTitle.fetchError')) | ||
| 136 | + } finally { | ||
| 137 | + this.loading = false | ||
| 138 | + } | ||
| 139 | + }, | ||
| 140 | + handleSearch() { | ||
| 141 | + this.pagination.current = 1 | ||
| 142 | + this.getList() | ||
| 143 | + }, | ||
| 144 | + handleReset() { | ||
| 145 | + this.searchForm = { | ||
| 146 | + itemTitle: '', | ||
| 147 | + titleType: '', | ||
| 148 | + communityId: getCommunityId() | ||
| 149 | + } | ||
| 150 | + this.pagination.current = 1 | ||
| 151 | + this.getList() | ||
| 152 | + }, | ||
| 153 | + handleAdd() { | ||
| 154 | + this.$refs.addDialog.open() | ||
| 155 | + }, | ||
| 156 | + handleEdit(row) { | ||
| 157 | + this.$refs.editDialog.open(row) | ||
| 158 | + }, | ||
| 159 | + handleDelete(row) { | ||
| 160 | + this.$refs.deleteDialog.open(row) | ||
| 161 | + }, | ||
| 162 | + handleSuccess() { | ||
| 163 | + this.getList() | ||
| 164 | + }, | ||
| 165 | + handleSizeChange(val) { | ||
| 166 | + this.pagination.size = val | ||
| 167 | + this.getList() | ||
| 168 | + }, | ||
| 169 | + handleCurrentChange(val) { | ||
| 170 | + this.pagination.current = val | ||
| 171 | + this.getList() | ||
| 172 | + }, | ||
| 173 | + getTitleTypeName(type) { | ||
| 174 | + switch (type) { | ||
| 175 | + case '1001': | ||
| 176 | + return this.$t('questionTitle.types.singleChoice') | ||
| 177 | + case '2002': | ||
| 178 | + return this.$t('questionTitle.types.multipleChoice') | ||
| 179 | + case '3003': | ||
| 180 | + return this.$t('questionTitle.types.shortAnswer') | ||
| 181 | + default: | ||
| 182 | + return '' | ||
| 183 | + } | ||
| 184 | + } | ||
| 185 | + } | ||
| 186 | +} | ||
| 187 | +</script> | ||
| 188 | + | ||
| 189 | +<style lang="scss" scoped> | ||
| 190 | +.question-title-container { | ||
| 191 | + padding: 20px; | ||
| 192 | + | ||
| 193 | + .search-wrapper { | ||
| 194 | + margin-bottom: 20px; | ||
| 195 | + | ||
| 196 | + .el-row { | ||
| 197 | + margin-bottom: 10px; | ||
| 198 | + } | ||
| 199 | + } | ||
| 200 | + | ||
| 201 | + .list-wrapper { | ||
| 202 | + margin-bottom: 20px; | ||
| 203 | + } | ||
| 204 | + | ||
| 205 | + .el-pagination { | ||
| 206 | + margin-top: 20px; | ||
| 207 | + text-align: right; | ||
| 208 | + } | ||
| 209 | +} | ||
| 210 | +</style> | ||
| 0 | \ No newline at end of file | 211 | \ No newline at end of file |
src/views/oa/visitManageLang.js
0 → 100644
| 1 | +export const messages = { | ||
| 2 | + en: { | ||
| 3 | + visitManage: { | ||
| 4 | + search: { | ||
| 5 | + title: 'Search Conditions', | ||
| 6 | + state: 'Select Audit Status', | ||
| 7 | + nameLike: 'Please enter visitor name', | ||
| 8 | + gender: 'Select Gender', | ||
| 9 | + phoneNumber: 'Please enter phone number', | ||
| 10 | + roomName: 'Please enter building-unit-room', | ||
| 11 | + ownerName: 'Please enter owner name', | ||
| 12 | + startTime: 'Please enter start time', | ||
| 13 | + endTime: 'Please enter end time' | ||
| 14 | + }, | ||
| 15 | + list: { | ||
| 16 | + title: 'Visitor List' | ||
| 17 | + }, | ||
| 18 | + table: { | ||
| 19 | + visitId: 'Visit ID', | ||
| 20 | + name: 'Name', | ||
| 21 | + gender: 'Gender', | ||
| 22 | + phoneNumber: 'Phone Number', | ||
| 23 | + roomName: 'Visit Room', | ||
| 24 | + ownerName: 'Visit Owner', | ||
| 25 | + carNum: 'Visitor Car', | ||
| 26 | + visitType: 'Visit Type', | ||
| 27 | + visitCase: 'Visit Reason', | ||
| 28 | + visitTime: 'Visit Time', | ||
| 29 | + departureTime: 'Departure Time', | ||
| 30 | + state: 'Audit Status', | ||
| 31 | + msg: 'Audit Remark', | ||
| 32 | + createTime: 'Create Time' | ||
| 33 | + }, | ||
| 34 | + gender: { | ||
| 35 | + male: 'Male', | ||
| 36 | + female: 'Female' | ||
| 37 | + }, | ||
| 38 | + visitType: 'Visit Type', | ||
| 39 | + manage: 'Manage' | ||
| 40 | + }, | ||
| 41 | + }, | ||
| 42 | + zh: { | ||
| 43 | + visitManage: { | ||
| 44 | + search: { | ||
| 45 | + title: '查询条件', | ||
| 46 | + state: '请选择审核状态', | ||
| 47 | + nameLike: '请输入访客姓名', | ||
| 48 | + gender: '请选择性别', | ||
| 49 | + phoneNumber: '请输入电话号码', | ||
| 50 | + roomName: '请输入拜访房屋 楼栋-单元-房屋', | ||
| 51 | + ownerName: '请输入拜访业主', | ||
| 52 | + startTime: '请输入开始时间', | ||
| 53 | + endTime: '请输入结束时间' | ||
| 54 | + }, | ||
| 55 | + list: { | ||
| 56 | + title: '访客人员' | ||
| 57 | + }, | ||
| 58 | + table: { | ||
| 59 | + visitId: '拜访ID', | ||
| 60 | + name: '姓名', | ||
| 61 | + gender: '性别', | ||
| 62 | + phoneNumber: '电话号码', | ||
| 63 | + roomName: '拜访房屋', | ||
| 64 | + ownerName: '拜访业主', | ||
| 65 | + carNum: '访客车辆', | ||
| 66 | + visitType: '访客类型', | ||
| 67 | + visitCase: '拜访事由', | ||
| 68 | + visitTime: '拜访时间', | ||
| 69 | + departureTime: '离开时间', | ||
| 70 | + state: '审核状态', | ||
| 71 | + msg: '审核备注', | ||
| 72 | + createTime: '创建时间' | ||
| 73 | + }, | ||
| 74 | + gender: { | ||
| 75 | + male: '男', | ||
| 76 | + female: '女' | ||
| 77 | + }, | ||
| 78 | + visitType: '访客类型', | ||
| 79 | + manage: '管理' | ||
| 80 | + }, | ||
| 81 | + } | ||
| 82 | +} | ||
| 0 | \ No newline at end of file | 83 | \ No newline at end of file |
src/views/oa/visitManageList.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="visit-manage-container"> | ||
| 3 | + <el-row :gutter="20"> | ||
| 4 | + <el-col :span="4"> | ||
| 5 | + <el-card class="tree-card"> | ||
| 6 | + <ul class="visit-type-list"> | ||
| 7 | + <li | ||
| 8 | + v-for="(item, index) in visitTypeList" | ||
| 9 | + :key="index" | ||
| 10 | + @click="switchVisitType(item)" | ||
| 11 | + :class="{'selected': visitManageInfo.conditions.typeId === item.typeId}" | ||
| 12 | + > | ||
| 13 | + {{ item.name }} | ||
| 14 | + </li> | ||
| 15 | + </ul> | ||
| 16 | + </el-card> | ||
| 17 | + </el-col> | ||
| 18 | + <el-col :span="20"> | ||
| 19 | + <el-card> | ||
| 20 | + <div slot="header" class="flex justify-between"> | ||
| 21 | + <span>{{ $t('visitManage.search.title') }}</span> | ||
| 22 | + </div> | ||
| 23 | + <el-form :inline="true" :model="visitManageInfo.conditions" class="search-form text-left"> | ||
| 24 | + <el-form-item> | ||
| 25 | + <el-select | ||
| 26 | + v-model="visitManageInfo.conditions.state" | ||
| 27 | + :placeholder="$t('visitManage.search.state')" | ||
| 28 | + style="width:100%" | ||
| 29 | + > | ||
| 30 | + <el-option | ||
| 31 | + v-for="(item, index) in stateList" | ||
| 32 | + :key="index" | ||
| 33 | + :label="item.name" | ||
| 34 | + :value="item.statusCd" | ||
| 35 | + ></el-option> | ||
| 36 | + </el-select> | ||
| 37 | + </el-form-item> | ||
| 38 | + <el-form-item> | ||
| 39 | + <el-input | ||
| 40 | + v-model="visitManageInfo.conditions.nameLike" | ||
| 41 | + :placeholder="$t('visitManage.search.nameLike')" | ||
| 42 | + ></el-input> | ||
| 43 | + </el-form-item> | ||
| 44 | + <el-form-item> | ||
| 45 | + <el-select | ||
| 46 | + v-model="visitManageInfo.conditions.visitGender" | ||
| 47 | + :placeholder="$t('visitManage.search.gender')" | ||
| 48 | + style="width:100%" | ||
| 49 | + > | ||
| 50 | + <el-option :label="$t('visitManage.gender.male')" value="0"></el-option> | ||
| 51 | + <el-option :label="$t('visitManage.gender.female')" value="1"></el-option> | ||
| 52 | + </el-select> | ||
| 53 | + </el-form-item> | ||
| 54 | + <el-form-item> | ||
| 55 | + <el-input | ||
| 56 | + v-model="visitManageInfo.conditions.phoneNumberLike" | ||
| 57 | + :placeholder="$t('visitManage.search.phoneNumber')" | ||
| 58 | + ></el-input> | ||
| 59 | + </el-form-item> | ||
| 60 | + <el-form-item> | ||
| 61 | + <el-input | ||
| 62 | + v-model="visitManageInfo.conditions.roomNameLike" | ||
| 63 | + :placeholder="$t('visitManage.search.roomName')" | ||
| 64 | + ></el-input> | ||
| 65 | + </el-form-item> | ||
| 66 | + <el-form-item> | ||
| 67 | + <el-button type="primary" @click="_queryVisitMethod">{{ $t('common.search') }}</el-button> | ||
| 68 | + <el-button @click="_resetVisitMethod">{{ $t('common.reset') }}</el-button> | ||
| 69 | + </el-form-item> | ||
| 70 | + </el-form> | ||
| 71 | + <el-form :inline="true" :model="visitManageInfo.conditions" class="search-form text-left"> | ||
| 72 | + <el-form-item> | ||
| 73 | + <el-input | ||
| 74 | + v-model="visitManageInfo.conditions.ownerNameLike" | ||
| 75 | + :placeholder="$t('visitManage.search.ownerName')" | ||
| 76 | + ></el-input> | ||
| 77 | + </el-form-item> | ||
| 78 | + <el-form-item> | ||
| 79 | + <el-date-picker | ||
| 80 | + v-model="visitManageInfo.conditions.queryStartTime" | ||
| 81 | + type="datetime" | ||
| 82 | + :placeholder="$t('visitManage.search.startTime')" | ||
| 83 | + ></el-date-picker> | ||
| 84 | + </el-form-item> | ||
| 85 | + <el-form-item> | ||
| 86 | + <el-date-picker | ||
| 87 | + v-model="visitManageInfo.conditions.queryEndTime" | ||
| 88 | + type="datetime" | ||
| 89 | + :placeholder="$t('visitManage.search.endTime')" | ||
| 90 | + ></el-date-picker> | ||
| 91 | + </el-form-item> | ||
| 92 | + </el-form> | ||
| 93 | + </el-card> | ||
| 94 | + | ||
| 95 | + <el-card class="mt-20"> | ||
| 96 | + <div slot="header" class="flex justify-between"> | ||
| 97 | + <span>{{ $t('visitManage.list.title') }}</span> | ||
| 98 | + <el-button type="primary" size="small" style="float: right" @click="_toIotVisit"> | ||
| 99 | + {{ $t('visitManage.manage') }} | ||
| 100 | + </el-button> | ||
| 101 | + </div> | ||
| 102 | + <el-table :data="visitManageInfo.visits" border style="width: 100%"> | ||
| 103 | + <el-table-column prop="visitId" :label="$t('visitManage.table.visitId')" align="center"></el-table-column> | ||
| 104 | + <el-table-column prop="name" :label="$t('visitManage.table.name')" align="center"></el-table-column> | ||
| 105 | + <el-table-column :label="$t('visitManage.table.gender')" align="center"> | ||
| 106 | + <template slot-scope="scope"> | ||
| 107 | + {{ scope.row.visitGender === '0' ? $t('visitManage.gender.male') : $t('visitManage.gender.female') }} | ||
| 108 | + </template> | ||
| 109 | + </el-table-column> | ||
| 110 | + <el-table-column prop="phoneNumber" :label="$t('visitManage.table.phoneNumber')" align="center"></el-table-column> | ||
| 111 | + <el-table-column prop="roomName" :label="$t('visitManage.table.roomName')" align="center"></el-table-column> | ||
| 112 | + <el-table-column prop="ownerName" :label="$t('visitManage.table.ownerName')" align="center"> | ||
| 113 | + <template slot-scope="scope"> | ||
| 114 | + {{ scope.row.ownerName || '-' }} | ||
| 115 | + </template> | ||
| 116 | + </el-table-column> | ||
| 117 | + <el-table-column prop="carNum" :label="$t('visitManage.table.carNum')" align="center"> | ||
| 118 | + <template slot-scope="scope"> | ||
| 119 | + {{ scope.row.carNum || '-' }} | ||
| 120 | + </template> | ||
| 121 | + </el-table-column> | ||
| 122 | + <el-table-column prop="visitTypeName" :label="$t('visitManage.table.visitType')" align="center"></el-table-column> | ||
| 123 | + <el-table-column prop="visitCase" :label="$t('visitManage.table.visitCase')" align="center"> | ||
| 124 | + <template slot-scope="scope"> | ||
| 125 | + {{ scope.row.visitCase || '-' }} | ||
| 126 | + </template> | ||
| 127 | + </el-table-column> | ||
| 128 | + <el-table-column prop="visitTime" :label="$t('visitManage.table.visitTime')" align="center"> | ||
| 129 | + <template slot-scope="scope"> | ||
| 130 | + {{ scope.row.visitTime || '-' }} | ||
| 131 | + </template> | ||
| 132 | + </el-table-column> | ||
| 133 | + <el-table-column prop="departureTime" :label="$t('visitManage.table.departureTime')" align="center"> | ||
| 134 | + <template slot-scope="scope"> | ||
| 135 | + {{ scope.row.departureTime || '-' }} | ||
| 136 | + </template> | ||
| 137 | + </el-table-column> | ||
| 138 | + <el-table-column prop="stateName" :label="$t('visitManage.table.state')" align="center"></el-table-column> | ||
| 139 | + <el-table-column prop="msg" :label="$t('visitManage.table.msg')" align="center"> | ||
| 140 | + <template slot-scope="scope"> | ||
| 141 | + {{ scope.row.msg || '-' }} | ||
| 142 | + </template> | ||
| 143 | + </el-table-column> | ||
| 144 | + <el-table-column prop="createTime" :label="$t('visitManage.table.createTime')" align="center"></el-table-column> | ||
| 145 | + <el-table-column :label="$t('common.operation')" align="center" width="120"> | ||
| 146 | + <template slot-scope="scope"> | ||
| 147 | + <el-button size="mini" @click="_toVisitDetail(scope.row)">{{ $t('common.detail') }}</el-button> | ||
| 148 | + </template> | ||
| 149 | + </el-table-column> | ||
| 150 | + </el-table> | ||
| 151 | + <el-pagination | ||
| 152 | + @size-change="handleSizeChange" | ||
| 153 | + @current-change="handleCurrentChange" | ||
| 154 | + :current-page="page.current" | ||
| 155 | + :page-sizes="[10, 20, 30, 50]" | ||
| 156 | + :page-size="page.size" | ||
| 157 | + layout="total, sizes, prev, pager, next, jumper" | ||
| 158 | + :total="visitManageInfo.total" | ||
| 159 | + class="pagination" | ||
| 160 | + ></el-pagination> | ||
| 161 | + </el-card> | ||
| 162 | + </el-col> | ||
| 163 | + </el-row> | ||
| 164 | + </div> | ||
| 165 | +</template> | ||
| 166 | + | ||
| 167 | +<script> | ||
| 168 | +import { listVisits, listVisitTypes } from '@/api/oa/visitManageApi' | ||
| 169 | +import { getDict } from '@/api/community/communityApi' | ||
| 170 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 171 | + | ||
| 172 | +export default { | ||
| 173 | + name: 'VisitManageList', | ||
| 174 | + data() { | ||
| 175 | + return { | ||
| 176 | + visitManageInfo: { | ||
| 177 | + visits: [], | ||
| 178 | + total: 0, | ||
| 179 | + conditions: { | ||
| 180 | + visitId: '', | ||
| 181 | + nameLike: '', | ||
| 182 | + visitGender: '', | ||
| 183 | + phoneNumberLike: '', | ||
| 184 | + roomNameLike: '', | ||
| 185 | + ownerNameLike: '', | ||
| 186 | + communityId: '', | ||
| 187 | + typeId: '', | ||
| 188 | + state: '', | ||
| 189 | + queryStartTime: '', | ||
| 190 | + queryEndTime: '', | ||
| 191 | + page: 1, | ||
| 192 | + row: 10 | ||
| 193 | + } | ||
| 194 | + }, | ||
| 195 | + visitTypeList: [], | ||
| 196 | + stateList: [], | ||
| 197 | + page: { | ||
| 198 | + current: 1, | ||
| 199 | + size: 10 | ||
| 200 | + } | ||
| 201 | + } | ||
| 202 | + }, | ||
| 203 | + created() { | ||
| 204 | + this.communityId = getCommunityId() | ||
| 205 | + this.initData() | ||
| 206 | + }, | ||
| 207 | + methods: { | ||
| 208 | + async initData() { | ||
| 209 | + try { | ||
| 210 | + await this.listVisitTypes() | ||
| 211 | + await this.getDictData() | ||
| 212 | + this._listVisits(1, 10) | ||
| 213 | + } catch (error) { | ||
| 214 | + console.error('初始化数据失败:', error) | ||
| 215 | + } | ||
| 216 | + }, | ||
| 217 | + async getDictData() { | ||
| 218 | + try { | ||
| 219 | + const data = await getDict('visit', 'state') | ||
| 220 | + this.stateList = data | ||
| 221 | + } catch (error) { | ||
| 222 | + console.error('获取字典数据失败:', error) | ||
| 223 | + } | ||
| 224 | + }, | ||
| 225 | + async _listVisits(page, rows) { | ||
| 226 | + try { | ||
| 227 | + this.visitManageInfo.conditions.page = page | ||
| 228 | + this.visitManageInfo.conditions.row = rows | ||
| 229 | + this.visitManageInfo.conditions.communityId = this.communityId | ||
| 230 | + const { data, total } = await listVisits(this.visitManageInfo.conditions) | ||
| 231 | + this.visitManageInfo.visits = data | ||
| 232 | + this.visitManageInfo.total = total | ||
| 233 | + this.page.current = page | ||
| 234 | + this.page.size = rows | ||
| 235 | + } catch (error) { | ||
| 236 | + console.error('获取访客列表失败:', error) | ||
| 237 | + } | ||
| 238 | + }, | ||
| 239 | + async listVisitTypes() { | ||
| 240 | + try { | ||
| 241 | + const { data } = await listVisitTypes({ | ||
| 242 | + page: -1, | ||
| 243 | + row: 100, | ||
| 244 | + communityId: this.communityId | ||
| 245 | + }) | ||
| 246 | + this.visitTypeList = [{ name: this.$t('visitManage.visitType'), typeId: '' }, ...data] | ||
| 247 | + } catch (error) { | ||
| 248 | + console.error('获取访客类型失败:', error) | ||
| 249 | + } | ||
| 250 | + }, | ||
| 251 | + _queryVisitMethod() { | ||
| 252 | + this._listVisits(1, this.page.size) | ||
| 253 | + }, | ||
| 254 | + _resetVisitMethod() { | ||
| 255 | + this.visitManageInfo.conditions = { | ||
| 256 | + visitId: '', | ||
| 257 | + nameLike: '', | ||
| 258 | + visitGender: '', | ||
| 259 | + phoneNumberLike: '', | ||
| 260 | + roomNameLike: '', | ||
| 261 | + ownerNameLike: '', | ||
| 262 | + communityId: this.communityId, | ||
| 263 | + typeId: '', | ||
| 264 | + state: '', | ||
| 265 | + queryStartTime: '', | ||
| 266 | + queryEndTime: '', | ||
| 267 | + page: 1, | ||
| 268 | + row: this.page.size | ||
| 269 | + } | ||
| 270 | + this._listVisits(1, this.page.size) | ||
| 271 | + }, | ||
| 272 | + switchVisitType(item) { | ||
| 273 | + this.visitManageInfo.conditions.typeId = item.typeId | ||
| 274 | + this._listVisits(1, this.page.size) | ||
| 275 | + }, | ||
| 276 | + _toIotVisit() { | ||
| 277 | + this.$router.push('/pages/accessControl/visitManage') | ||
| 278 | + }, | ||
| 279 | + _toVisitDetail(visit) { | ||
| 280 | + this.$router.push(`/pages/accessControl/visitDetail?visitId=${visit.visitId}&phoneNumber=${visit.phoneNumber}`) | ||
| 281 | + }, | ||
| 282 | + handleSizeChange(val) { | ||
| 283 | + this._listVisits(1, val) | ||
| 284 | + }, | ||
| 285 | + handleCurrentChange(val) { | ||
| 286 | + this._listVisits(val, this.page.size) | ||
| 287 | + } | ||
| 288 | + } | ||
| 289 | +} | ||
| 290 | +</script> | ||
| 291 | + | ||
| 292 | +<style lang="scss" scoped> | ||
| 293 | +.visit-manage-container { | ||
| 294 | + padding: 20px; | ||
| 295 | + | ||
| 296 | + .tree-card { | ||
| 297 | + height: 100%; | ||
| 298 | + | ||
| 299 | + .visit-type-list { | ||
| 300 | + list-style: none; | ||
| 301 | + padding: 0; | ||
| 302 | + margin: 0; | ||
| 303 | + | ||
| 304 | + li { | ||
| 305 | + padding: 10px; | ||
| 306 | + cursor: pointer; | ||
| 307 | + text-align: center; | ||
| 308 | + border-bottom: 1px solid #eee; | ||
| 309 | + transition: all 0.3s; | ||
| 310 | + | ||
| 311 | + &:hover { | ||
| 312 | + background-color: #f5f7fa; | ||
| 313 | + } | ||
| 314 | + | ||
| 315 | + &.selected { | ||
| 316 | + background-color: #409eff; | ||
| 317 | + color: white; | ||
| 318 | + } | ||
| 319 | + } | ||
| 320 | + } | ||
| 321 | + } | ||
| 322 | + | ||
| 323 | + .search-form { | ||
| 324 | + margin-bottom: 0; | ||
| 325 | + | ||
| 326 | + .el-form-item { | ||
| 327 | + margin-bottom: 10px; | ||
| 328 | + margin-right: 10px; | ||
| 329 | + } | ||
| 330 | + } | ||
| 331 | + | ||
| 332 | + .mt-20 { | ||
| 333 | + margin-top: 20px; | ||
| 334 | + } | ||
| 335 | + | ||
| 336 | + .pagination { | ||
| 337 | + margin-top: 20px; | ||
| 338 | + text-align: right; | ||
| 339 | + } | ||
| 340 | +} | ||
| 341 | +</style> | ||
| 0 | \ No newline at end of file | 342 | \ No newline at end of file |