Commit 03f63ab425d41ad23f1bf8064bf3c5a84e8b17dd
1 parent
8592fee7
优化到商户信息
Showing
42 changed files
with
3832 additions
and
89 deletions
src/api/org/addScheduleClassesApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * 保存排班信息 | |
| 5 | + * @param {Object} data 排班数据 | |
| 6 | + * @returns {Promise} | |
| 7 | + */ | |
| 8 | +export function saveScheduleClasses(data) { | |
| 9 | + return new Promise((resolve, reject) => { | |
| 10 | + request({ | |
| 11 | + url: '/scheduleClasses.saveScheduleClasses', | |
| 12 | + method: 'post', | |
| 13 | + data | |
| 14 | + }).then(response => { | |
| 15 | + const res = response.data | |
| 16 | + resolve(res) | |
| 17 | + }).catch(error => { | |
| 18 | + reject(error) | |
| 19 | + }) | |
| 20 | + }) | |
| 21 | +} | |
| 22 | + | |
| 23 | +/** | |
| 24 | + * 获取班次列表 | |
| 25 | + * @param {Object} params 查询参数 | |
| 26 | + * @returns {Promise} | |
| 27 | + */ | |
| 28 | +export function listClasses(params) { | |
| 29 | + return new Promise((resolve, reject) => { | |
| 30 | + request({ | |
| 31 | + url: '/classes.listClasses', | |
| 32 | + method: 'get', | |
| 33 | + params | |
| 34 | + }).then(response => { | |
| 35 | + const res = response.data | |
| 36 | + resolve(res) | |
| 37 | + }).catch(error => { | |
| 38 | + reject(error) | |
| 39 | + }) | |
| 40 | + }) | |
| 41 | +} | |
| 42 | + | |
| 43 | +/** | |
| 44 | + * 获取排班详情 | |
| 45 | + * @param {String} scheduleId 排班ID | |
| 46 | + * @returns {Promise} | |
| 47 | + */ | |
| 48 | +export function getScheduleClassesDetail(scheduleId) { | |
| 49 | + return new Promise((resolve, reject) => { | |
| 50 | + request({ | |
| 51 | + url: '/scheduleClasses.getScheduleClasses', | |
| 52 | + method: 'get', | |
| 53 | + params: { scheduleId } | |
| 54 | + }).then(response => { | |
| 55 | + const res = response.data | |
| 56 | + resolve(res) | |
| 57 | + }).catch(error => { | |
| 58 | + reject(error) | |
| 59 | + }) | |
| 60 | + }) | |
| 61 | +} | |
| 0 | 62 | \ No newline at end of file | ... | ... |
src/api/org/editScheduleClassesApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | + | |
| 3 | +// 更新排班信息 | |
| 4 | +export function updateScheduleClasses(data) { | |
| 5 | + return new Promise((resolve, reject) => { | |
| 6 | + request({ | |
| 7 | + url: '/scheduleClasses.updateScheduleClasses', | |
| 8 | + method: 'post', | |
| 9 | + data | |
| 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 listScheduleClasses(params) { | |
| 21 | + return new Promise((resolve, reject) => { | |
| 22 | + request({ | |
| 23 | + url: '/scheduleClasses.listScheduleClasses', | |
| 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 listScheduleClassesDay(params) { | |
| 37 | + return new Promise((resolve, reject) => { | |
| 38 | + request({ | |
| 39 | + url: '/scheduleClasses.listScheduleClassesDay', | |
| 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 listClasses(params) { | |
| 53 | + return new Promise((resolve, reject) => { | |
| 54 | + request({ | |
| 55 | + url: '/classes.listClasses', | |
| 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 | +} | |
| 0 | 66 | \ No newline at end of file | ... | ... |
src/api/org/scheduleClassesApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 3 | + | |
| 4 | +// 获取排班列表 | |
| 5 | +export function listScheduleClasses(params) { | |
| 6 | + return new Promise((resolve, reject) => { | |
| 7 | + request({ | |
| 8 | + url: '/scheduleClasses.listScheduleClasses', | |
| 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 deleteScheduleClasses(data) { | |
| 25 | + return new Promise((resolve, reject) => { | |
| 26 | + request({ | |
| 27 | + url: '/scheduleClasses.deleteScheduleClasses', | |
| 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 updateScheduleClassesState(data) { | |
| 44 | + return new Promise((resolve, reject) => { | |
| 45 | + request({ | |
| 46 | + url: '/scheduleClasses.updateScheduleClassesState', | |
| 47 | + method: 'post', | |
| 48 | + data: { | |
| 49 | + ...data, | |
| 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 getDict(dictType, dictName) { | |
| 63 | + return new Promise((resolve, reject) => { | |
| 64 | + request({ | |
| 65 | + url: '/dict.getDict', | |
| 66 | + method: 'get', | |
| 67 | + params: { | |
| 68 | + dictType, | |
| 69 | + dictName, | |
| 70 | + communityId: getCommunityId() | |
| 71 | + } | |
| 72 | + }).then(response => { | |
| 73 | + const res = response.data | |
| 74 | + resolve(res) | |
| 75 | + }).catch(error => { | |
| 76 | + reject(error) | |
| 77 | + }) | |
| 78 | + }) | |
| 79 | +} | |
| 0 | 80 | \ No newline at end of file | ... | ... |
src/api/org/scheduleClassesPageApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * 获取班次列表 | |
| 5 | + * @param {Object} params 查询参数 | |
| 6 | + * @returns {Promise} Promise对象 | |
| 7 | + */ | |
| 8 | +export function listScheduleClasses(params) { | |
| 9 | + return new Promise((resolve, reject) => { | |
| 10 | + request({ | |
| 11 | + url: '/scheduleClasses.listScheduleClasses', | |
| 12 | + method: 'get', | |
| 13 | + params | |
| 14 | + }).then(response => { | |
| 15 | + const res = response.data | |
| 16 | + resolve(res) | |
| 17 | + }).catch(error => { | |
| 18 | + reject(error) | |
| 19 | + }) | |
| 20 | + }) | |
| 21 | +} | |
| 22 | + | |
| 23 | +/** | |
| 24 | + * 获取员工月度排班表 | |
| 25 | + * @param {Object} params 查询参数 | |
| 26 | + * @returns {Promise} Promise对象 | |
| 27 | + */ | |
| 28 | +export function staffMonthScheduleClasses(params) { | |
| 29 | + return new Promise((resolve, reject) => { | |
| 30 | + request({ | |
| 31 | + url: '/scheduleClasses.staffMonthScheduleClasses', | |
| 32 | + method: 'get', | |
| 33 | + params | |
| 34 | + }).then(response => { | |
| 35 | + const res = response.data | |
| 36 | + resolve(res) | |
| 37 | + }).catch(error => { | |
| 38 | + reject(error) | |
| 39 | + }) | |
| 40 | + }) | |
| 41 | +} | |
| 42 | + | |
| 43 | +/** | |
| 44 | + * 导出排班表数据 | |
| 45 | + * @param {Object} params 导出参数 | |
| 46 | + * @returns {Promise} Promise对象 | |
| 47 | + */ | |
| 48 | +export function exportData(params) { | |
| 49 | + return new Promise((resolve, reject) => { | |
| 50 | + request({ | |
| 51 | + url: '/export.exportData', | |
| 52 | + method: 'get', | |
| 53 | + params | |
| 54 | + }).then(response => { | |
| 55 | + const res = response.data | |
| 56 | + resolve(res) | |
| 57 | + }).catch(error => { | |
| 58 | + reject(error) | |
| 59 | + }) | |
| 60 | + }) | |
| 61 | +} | |
| 62 | + | |
| 63 | +/** | |
| 64 | + * 获取组织树 | |
| 65 | + * @param {Object} params 查询参数 | |
| 66 | + * @returns {Promise} Promise对象 | |
| 67 | + */ | |
| 68 | +export function listOrgTree(params) { | |
| 69 | + return new Promise((resolve, reject) => { | |
| 70 | + request({ | |
| 71 | + url: '/org.listOrgTree', | |
| 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 | 82 | \ No newline at end of file | ... | ... |
src/api/system/communitySettingManageApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * 获取小区设置项列表 | |
| 5 | + * @param {Object} params 查询参数 | |
| 6 | + * @returns {Promise} | |
| 7 | + */ | |
| 8 | +export function listCommunitySettingKey(params) { | |
| 9 | + return new Promise((resolve, reject) => { | |
| 10 | + request({ | |
| 11 | + url: '/communitySettingKey.listCommunitySettingKey', | |
| 12 | + method: 'get', | |
| 13 | + params | |
| 14 | + }).then(response => { | |
| 15 | + const res = response.data | |
| 16 | + resolve(res) | |
| 17 | + }).catch(error => { | |
| 18 | + reject(error) | |
| 19 | + }) | |
| 20 | + }) | |
| 21 | +} | |
| 22 | + | |
| 23 | +/** | |
| 24 | + * 保存小区设置 | |
| 25 | + * @param {Object} data 保存数据 | |
| 26 | + * @returns {Promise} | |
| 27 | + */ | |
| 28 | +export function saveCommunitySetting(data) { | |
| 29 | + return new Promise((resolve, reject) => { | |
| 30 | + request({ | |
| 31 | + url: '/community.saveCommunitySetting', | |
| 32 | + method: 'post', | |
| 33 | + data | |
| 34 | + }).then(response => { | |
| 35 | + const res = response.data | |
| 36 | + resolve(res) | |
| 37 | + }).catch(error => { | |
| 38 | + reject(error) | |
| 39 | + }) | |
| 40 | + }) | |
| 41 | +} | |
| 0 | 42 | \ No newline at end of file | ... | ... |
src/api/system/storeInfoManageApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | + | |
| 3 | +// 获取商户列表 | |
| 4 | +export function listStores(params) { | |
| 5 | + return new Promise((resolve, reject) => { | |
| 6 | + request({ | |
| 7 | + url: '/store.listStores', | |
| 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 updateStoreInfo(data) { | |
| 21 | + return new Promise((resolve, reject) => { | |
| 22 | + request({ | |
| 23 | + url: '/update.store.info', | |
| 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 updateStoreAttr(data) { | |
| 37 | + return new Promise((resolve, reject) => { | |
| 38 | + request({ | |
| 39 | + url: '/storeAttr.updateStoreAttr', | |
| 40 | + method: 'post', | |
| 41 | + data | |
| 42 | + }).then(response => { | |
| 43 | + const res = response.data | |
| 44 | + resolve(res) | |
| 45 | + }).catch(error => { | |
| 46 | + reject(error) | |
| 47 | + }) | |
| 48 | + }) | |
| 49 | +} | |
| 0 | 50 | \ No newline at end of file | ... | ... |
src/api/system/workflowManageApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 3 | + | |
| 4 | +// 获取流程列表 | |
| 5 | +export function listWorkflows(params) { | |
| 6 | + return new Promise((resolve, reject) => { | |
| 7 | + request({ | |
| 8 | + url: '/workflow.listWorkflows', | |
| 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 listWorkflowImage(params) { | |
| 28 | + return new Promise((resolve, reject) => { | |
| 29 | + request({ | |
| 30 | + url: '/workflow.listWorkflowImage', | |
| 31 | + method: 'get', | |
| 32 | + params: { | |
| 33 | + ...params, | |
| 34 | + communityId: getCommunityId() | |
| 35 | + } | |
| 36 | + }).then(response => { | |
| 37 | + const res = response.data | |
| 38 | + if (res.code !== '0') { | |
| 39 | + reject(new Error(res.msg)) | |
| 40 | + return | |
| 41 | + } | |
| 42 | + resolve({ | |
| 43 | + data: res.data | |
| 44 | + }) | |
| 45 | + }).catch(error => { | |
| 46 | + reject(error) | |
| 47 | + }) | |
| 48 | + }) | |
| 49 | +} | |
| 50 | + | |
| 51 | +// 获取流程类型字典 | |
| 52 | +export function getFlowTypeDict() { | |
| 53 | + return new Promise((resolve, reject) => { | |
| 54 | + request({ | |
| 55 | + url: '/dict.getDict', | |
| 56 | + method: 'get', | |
| 57 | + params: { | |
| 58 | + dictType: 'workflow', | |
| 59 | + dictCd: 'flow_type' | |
| 60 | + } | |
| 61 | + }).then(response => { | |
| 62 | + const res = response.data | |
| 63 | + resolve(res) | |
| 64 | + }).catch(error => { | |
| 65 | + reject(error) | |
| 66 | + }) | |
| 67 | + }) | |
| 68 | +} | |
| 0 | 69 | \ No newline at end of file | ... | ... |
src/api/system/workflowSettingManageApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 3 | + | |
| 4 | +// 获取工作流步骤列表 | |
| 5 | +export function getWorkflowSteps(params) { | |
| 6 | + return new Promise((resolve, reject) => { | |
| 7 | + request({ | |
| 8 | + url: '/workflow.listWorkflowSteps', | |
| 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 updateWorkflow(data) { | |
| 25 | + return new Promise((resolve, reject) => { | |
| 26 | + request({ | |
| 27 | + url: '/workflow.updateWorkflow', | |
| 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 queryStaffInfos(params) { | |
| 44 | + return new Promise((resolve, reject) => { | |
| 45 | + request({ | |
| 46 | + url: '/query.staff.infos', | |
| 47 | + method: 'get', | |
| 48 | + params: { | |
| 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 listOrgTree(params) { | |
| 63 | + return new Promise((resolve, reject) => { | |
| 64 | + request({ | |
| 65 | + url: '/org.listOrgTree', | |
| 66 | + method: 'get', | |
| 67 | + params: { | |
| 68 | + ...params, | |
| 69 | + communityId: getCommunityId() | |
| 70 | + } | |
| 71 | + }).then(response => { | |
| 72 | + const res = response.data | |
| 73 | + resolve(res) | |
| 74 | + }).catch(error => { | |
| 75 | + reject(error) | |
| 76 | + }) | |
| 77 | + }) | |
| 78 | +} | |
| 0 | 79 | \ No newline at end of file | ... | ... |
src/components/org/ChooseOrgTree.vue
| 1 | 1 | <template> |
| 2 | - <el-dialog :title="$t('addStaff.chooseOrg')" :visible.sync="visible" width="50%" @close="handleClose"> | |
| 3 | - <el-tree ref="orgTree" :data="orgs" :props="defaultProps" node-key="id" highlight-current | |
| 4 | - @node-click="handleNodeClick" class="org-tree-container" /> | |
| 2 | + <el-dialog | |
| 3 | + :title="$t('scheduleClassesPage.selectOrg')" | |
| 4 | + :visible.sync="dialogVisible" | |
| 5 | + width="60%" | |
| 6 | + > | |
| 7 | + <el-tree | |
| 8 | + ref="orgTree" | |
| 9 | + :data="chooseOrgInfo.orgs" | |
| 10 | + :props="defaultProps" | |
| 11 | + node-key="id" | |
| 12 | + highlight-current | |
| 13 | + @node-click="handleNodeClick" | |
| 14 | + /> | |
| 5 | 15 | <span slot="footer" class="dialog-footer"> |
| 6 | - <el-button @click="visible = false">{{ $t('addStaff.cancel') }}</el-button> | |
| 7 | - <el-button type="primary" @click="handleConfirm">{{ $t('addStaff.confirm') }}</el-button> | |
| 16 | + <el-button @click="dialogVisible = false">{{ $t('common.cancel') }}</el-button> | |
| 17 | + <el-button type="primary" @click="_doChooseOrg">{{ $t('common.confirm') }}</el-button> | |
| 8 | 18 | </span> |
| 9 | 19 | </el-dialog> |
| 10 | 20 | </template> |
| 11 | - | |
| 21 | + | |
| 12 | 22 | <script> |
| 13 | -import { listOrgTree } from '@/api/staff/addStaffApi' | |
| 23 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 24 | +import { listOrgTree } from '@/api/org/orgApi' | |
| 14 | 25 | |
| 15 | 26 | export default { |
| 16 | 27 | name: 'ChooseOrgTree', |
| 17 | 28 | data() { |
| 18 | 29 | return { |
| 19 | -/************* ✨ Windsurf Command ⭐ *************/ | |
| 20 | -/** | |
| 21 | - * Lifecycle hook called when the component is mounted. | |
| 22 | - * Initializes the jsTree with the current organization data. | |
| 23 | - */ | |
| 24 | - | |
| 25 | -/******* cd76f80b-513b-4475-894b-fd5714d067a7 *******/ visible: false, | |
| 26 | - orgs: [], | |
| 27 | - currentOrg: null, | |
| 30 | + dialogVisible: false, | |
| 31 | + chooseOrgInfo: { | |
| 32 | + orgs: [], | |
| 33 | + orgId: '', | |
| 34 | + curOrg: {} | |
| 35 | + }, | |
| 28 | 36 | defaultProps: { |
| 29 | 37 | children: 'children', |
| 30 | - label: 'text' | |
| 38 | + label: 'name' | |
| 31 | 39 | } |
| 32 | 40 | } |
| 33 | 41 | }, |
| 34 | 42 | methods: { |
| 35 | - openOrgModal() { | |
| 36 | - this.visible = true | |
| 37 | - this.loadOrgs() | |
| 43 | + open() { | |
| 44 | + this.dialogVisible = true | |
| 45 | + this._loadChooseOrgs() | |
| 38 | 46 | }, |
| 39 | - async loadOrgs() { | |
| 40 | - this.orgs = [] | |
| 47 | + async _loadChooseOrgs() { | |
| 41 | 48 | try { |
| 42 | - const res = await listOrgTree({ | |
| 43 | - communityId: '-1' | |
| 44 | - }) | |
| 45 | - this.orgs.push(res.data) | |
| 49 | + const params = { | |
| 50 | + communityId: getCommunityId() | |
| 51 | + } | |
| 52 | + const { data } = await listOrgTree(params) | |
| 53 | + this.chooseOrgInfo.orgs = data | |
| 46 | 54 | } catch (error) { |
| 47 | - this.$message.error(error.message || '加载组织树失败') | |
| 55 | + console.error('获取组织树失败:', error) | |
| 48 | 56 | } |
| 49 | 57 | }, |
| 50 | 58 | handleNodeClick(data) { |
| 51 | - this.currentOrg = { | |
| 52 | - orgId: data.id, | |
| 53 | - allOrgName: data.text | |
| 54 | - } | |
| 59 | + this.chooseOrgInfo.curOrg = data | |
| 60 | + this.chooseOrgInfo.curOrg.orgId = data.id | |
| 55 | 61 | }, |
| 56 | - handleConfirm() { | |
| 57 | - if (!this.currentOrg) { | |
| 58 | - this.$message.warning('请选择组织') | |
| 59 | - return | |
| 60 | - } | |
| 61 | - this.$emit('switchOrg', this.currentOrg) | |
| 62 | - this.visible = false | |
| 63 | - }, | |
| 64 | - handleClose() { | |
| 65 | - this.currentOrg = null | |
| 66 | - this.$refs.orgTree.setCurrentKey(null) | |
| 62 | + _doChooseOrg() { | |
| 63 | + this.$emit('switchOrg', this.chooseOrgInfo.curOrg) | |
| 64 | + this.dialogVisible = false | |
| 67 | 65 | } |
| 68 | 66 | } |
| 69 | 67 | } |
| 70 | 68 | </script> |
| 71 | - | |
| 69 | + | |
| 72 | 70 | <style lang="scss" scoped> |
| 73 | -.org-tree-container { | |
| 74 | - min-height: 300px; | |
| 75 | - max-height: 500px; | |
| 71 | +::v-deep .el-dialog__body { | |
| 72 | + padding: 20px; | |
| 73 | + max-height: 60vh; | |
| 76 | 74 | overflow-y: auto; |
| 77 | 75 | } |
| 78 | 76 | </style> |
| 79 | 77 | \ No newline at end of file | ... | ... |
src/components/org/deleteScheduleClasses.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <el-dialog | |
| 3 | + :title="$t('scheduleClasses.delete.title')" | |
| 4 | + :visible.sync="visible" | |
| 5 | + width="30%" | |
| 6 | + @close="handleClose" | |
| 7 | + > | |
| 8 | + <div style="text-align: center"> | |
| 9 | + <p>{{ $t('scheduleClasses.delete.confirm') }}</p> | |
| 10 | + </div> | |
| 11 | + <span slot="footer" class="dialog-footer"> | |
| 12 | + <el-button @click="handleClose">{{ $t('common.cancel') }}</el-button> | |
| 13 | + <el-button type="primary" @click="handleConfirm">{{ $t('common.confirm') }}</el-button> | |
| 14 | + </span> | |
| 15 | + </el-dialog> | |
| 16 | +</template> | |
| 17 | + | |
| 18 | +<script> | |
| 19 | +import { deleteScheduleClasses } from '@/api/org/scheduleClassesApi' | |
| 20 | + | |
| 21 | +export default { | |
| 22 | + name: 'DeleteScheduleClasses', | |
| 23 | + data() { | |
| 24 | + return { | |
| 25 | + visible: false, | |
| 26 | + currentItem: null | |
| 27 | + } | |
| 28 | + }, | |
| 29 | + methods: { | |
| 30 | + open(item) { | |
| 31 | + this.currentItem = item | |
| 32 | + this.visible = true | |
| 33 | + }, | |
| 34 | + async handleConfirm() { | |
| 35 | + try { | |
| 36 | + await deleteScheduleClasses(this.currentItem) | |
| 37 | + this.$message.success(this.$t('scheduleClasses.delete.success')) | |
| 38 | + this.$emit('success') | |
| 39 | + this.visible = false | |
| 40 | + } catch (error) { | |
| 41 | + this.$message.error(this.$t('scheduleClasses.delete.error')) | |
| 42 | + } | |
| 43 | + }, | |
| 44 | + handleClose() { | |
| 45 | + this.visible = false | |
| 46 | + } | |
| 47 | + } | |
| 48 | +} | |
| 49 | +</script> | |
| 0 | 50 | \ No newline at end of file | ... | ... |
src/components/org/editScheduleClassesDay.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <el-dialog :title="$t('editScheduleClassesDay.title')" :visible.sync="visible" width="60%" @close="handleClose"> | |
| 3 | + <el-form label-position="right" label-width="120px"> | |
| 4 | + <el-form-item :label="$t('editScheduleClassesDay.status')"> | |
| 5 | + <el-select v-model="workday" @change="changeScheduleClassesDayState" style="width:100%"> | |
| 6 | + <el-option :label="$t('editScheduleClassesDay.rest')" value="2002" /> | |
| 7 | + <el-option v-for="(item, index) in classess" :key="index" :label="`${item.name}${getClassTime(item)}`" | |
| 8 | + :value="item.classesId" /> | |
| 9 | + </el-select> | |
| 10 | + </el-form-item> | |
| 11 | + | |
| 12 | + <div v-if="workday !== '2002'"> | |
| 13 | + <el-form-item v-for="(item, index) in times" :key="index"> | |
| 14 | + <el-col :span="11"> | |
| 15 | + <el-form-item :label="$t('editScheduleClassesDay.startTime')"> | |
| 16 | + <el-input v-model="item.startTime" :placeholder="$t('editScheduleClassesDay.startTimePlaceholder')" /> | |
| 17 | + </el-form-item> | |
| 18 | + </el-col> | |
| 19 | + <el-col :span="11" :offset="2"> | |
| 20 | + <el-form-item :label="$t('editScheduleClassesDay.endTime')"> | |
| 21 | + <el-input v-model="item.endTime" :placeholder="$t('editScheduleClassesDay.endTimePlaceholder')" /> | |
| 22 | + </el-form-item> | |
| 23 | + </el-col> | |
| 24 | + </el-form-item> | |
| 25 | + </div> | |
| 26 | + </el-form> | |
| 27 | + | |
| 28 | + <span slot="footer" class="dialog-footer"> | |
| 29 | + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button> | |
| 30 | + <el-button type="primary" @click="submitEditScheduleClassesDay"> | |
| 31 | + {{ $t('common.submit') }} | |
| 32 | + </el-button> | |
| 33 | + </span> | |
| 34 | + </el-dialog> | |
| 35 | +</template> | |
| 36 | + | |
| 37 | +<script> | |
| 38 | +import { listClasses } from '@/api/org/addScheduleClassesApi' | |
| 39 | + | |
| 40 | +export default { | |
| 41 | + name: 'EditScheduleClassesDay', | |
| 42 | + data() { | |
| 43 | + return { | |
| 44 | + visible: false, | |
| 45 | + workday: '', | |
| 46 | + workdayName: '', | |
| 47 | + times: [], | |
| 48 | + classess: [], | |
| 49 | + currentItem: null | |
| 50 | + } | |
| 51 | + }, | |
| 52 | + methods: { | |
| 53 | + open(item) { | |
| 54 | + this.currentItem = item | |
| 55 | + this.workday = item.workday | |
| 56 | + this.workdayName = item.workdayName | |
| 57 | + this.times = item.times ? [...item.times] : [] | |
| 58 | + this.listClassess() | |
| 59 | + this.visible = true | |
| 60 | + }, | |
| 61 | + handleClose() { | |
| 62 | + this.workday = '' | |
| 63 | + this.workdayName = '' | |
| 64 | + this.times = [] | |
| 65 | + this.currentItem = null | |
| 66 | + }, | |
| 67 | + async listClassess() { | |
| 68 | + try { | |
| 69 | + const params = { | |
| 70 | + page: 1, | |
| 71 | + row: 100, | |
| 72 | + state: '1001' | |
| 73 | + } | |
| 74 | + const res = await listClasses(params) | |
| 75 | + this.classess = res.data || [] | |
| 76 | + } catch (error) { | |
| 77 | + console.error('获取班次列表失败:', error) | |
| 78 | + } | |
| 79 | + }, | |
| 80 | + changeScheduleClassesDayState() { | |
| 81 | + this.times = [] | |
| 82 | + if (this.workday === '2002') { | |
| 83 | + this.workdayName = this.$t('editScheduleClassesDay.rest') | |
| 84 | + return | |
| 85 | + } | |
| 86 | + | |
| 87 | + const selectedClass = this.classess.find(item => item.classesId === this.workday) | |
| 88 | + if (selectedClass) { | |
| 89 | + this.workdayName = selectedClass.name | |
| 90 | + if (selectedClass.times) { | |
| 91 | + this.times = [...selectedClass.times] | |
| 92 | + } | |
| 93 | + } | |
| 94 | + }, | |
| 95 | + getClassTime(item) { | |
| 96 | + if (!item.times || item.times.length === 0) return '' | |
| 97 | + | |
| 98 | + let timeStr = '' | |
| 99 | + item.times.forEach(timeItem => { | |
| 100 | + timeStr += `${timeItem.startTime}-${timeItem.endTime};` | |
| 101 | + }) | |
| 102 | + | |
| 103 | + return `(${timeStr})` | |
| 104 | + }, | |
| 105 | + submitEditScheduleClassesDay() { | |
| 106 | + if (this.currentItem) { | |
| 107 | + this.currentItem.workday = this.workday | |
| 108 | + this.currentItem.workdayName = this.workdayName | |
| 109 | + this.currentItem.times = [...this.times] | |
| 110 | + this.visible = false | |
| 111 | + } | |
| 112 | + } | |
| 113 | + } | |
| 114 | +} | |
| 115 | +</script> | |
| 116 | + | |
| 117 | +<style lang="scss" scoped> | |
| 118 | +.el-form-item { | |
| 119 | + margin-bottom: 20px; | |
| 120 | +} | |
| 121 | +</style> | |
| 0 | 122 | \ No newline at end of file | ... | ... |
src/components/org/scheduleClassesDay.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div> | |
| 3 | + <el-form-item :label="$t('scheduleClassesDay.scheduleCycle')"> | |
| 4 | + <el-select v-model="scheduleCycle" :placeholder="$t('scheduleClassesDay.scheduleCyclePlaceholder')" | |
| 5 | + @change="changeInspectionPeriod" style="width:100%"> | |
| 6 | + <el-option v-for="index in 31" :key="index" :label="`${index}${$t('scheduleClassesDay.day')}`" :value="index" /> | |
| 7 | + </el-select> | |
| 8 | + </el-form-item> | |
| 9 | + | |
| 10 | + <el-form-item :label="$t('scheduleClassesDay.scheduleInfo')"> | |
| 11 | + <div class="schedule-days-container"> | |
| 12 | + <div v-for="(item, index) in days" :key="index" class="schedule-day-item" @click="changeWorkdayInfo(item)"> | |
| 13 | + <div class="day-number">{{ item.day }}</div> | |
| 14 | + <div class="workday-name">{{ item.workdayName }}</div> | |
| 15 | + <div v-for="(time, timeIndex) in item.times" :key="timeIndex" class="time-range"> | |
| 16 | + {{ time.startTime }}-{{ time.endTime }} | |
| 17 | + </div> | |
| 18 | + </div> | |
| 19 | + </div> | |
| 20 | + </el-form-item> | |
| 21 | + </div> | |
| 22 | +</template> | |
| 23 | + | |
| 24 | +<script> | |
| 25 | +export default { | |
| 26 | + name: 'ScheduleClassesDay', | |
| 27 | + props: { | |
| 28 | + initialData: { | |
| 29 | + type: Object, | |
| 30 | + default: () => ({}) | |
| 31 | + } | |
| 32 | + }, | |
| 33 | + data() { | |
| 34 | + return { | |
| 35 | + scheduleCycle: 1, | |
| 36 | + days: [] | |
| 37 | + } | |
| 38 | + }, | |
| 39 | + created() { | |
| 40 | + if (this.initialData.days && this.initialData.days.length > 0) { | |
| 41 | + this.days = [...this.initialData.days] | |
| 42 | + this.scheduleCycle = this.initialData.scheduleCycle | |
| 43 | + } else { | |
| 44 | + this.changeInspectionPeriod() | |
| 45 | + } | |
| 46 | + }, | |
| 47 | + methods: { | |
| 48 | + notify(params) { | |
| 49 | + this.localDays = params.days || [] | |
| 50 | + this.$emit('update:scheduleCycle', params.scheduleCycle || 1) | |
| 51 | + if (!params.days || params.days.length === 0) { | |
| 52 | + this.changeInspectionPeriodWeek() | |
| 53 | + } | |
| 54 | + }, | |
| 55 | + initData(scheduleCycle) { | |
| 56 | + this.scheduleCycle = scheduleCycle | |
| 57 | + this.changeInspectionPeriod() | |
| 58 | + }, | |
| 59 | + changeInspectionPeriod() { | |
| 60 | + this.days = [] | |
| 61 | + for (let cycleIndex = 0; cycleIndex < this.scheduleCycle; cycleIndex++) { | |
| 62 | + this.days.push({ | |
| 63 | + day: cycleIndex + 1, | |
| 64 | + workday: '2002', | |
| 65 | + workdayName: this.$t('scheduleClassesDay.rest'), | |
| 66 | + times: [] | |
| 67 | + }) | |
| 68 | + } | |
| 69 | + this.$emit('cycle-change', this.scheduleCycle) | |
| 70 | + }, | |
| 71 | + changeWorkdayInfo(item) { | |
| 72 | + this.$emit('editDay', item) | |
| 73 | + }, | |
| 74 | + getDaysData() { | |
| 75 | + return this.days | |
| 76 | + } | |
| 77 | + } | |
| 78 | +} | |
| 79 | +</script> | |
| 80 | + | |
| 81 | +<style lang="scss" scoped> | |
| 82 | +.schedule-days-container { | |
| 83 | + display: flex; | |
| 84 | + flex-wrap: wrap; | |
| 85 | + gap: 10px; | |
| 86 | +} | |
| 87 | + | |
| 88 | +.schedule-day-item { | |
| 89 | + width: calc(16.66% - 10px); | |
| 90 | + padding: 10px; | |
| 91 | + border: 1px solid #ebeef5; | |
| 92 | + border-radius: 4px; | |
| 93 | + cursor: pointer; | |
| 94 | + text-align: center; | |
| 95 | + transition: all 0.3s; | |
| 96 | + | |
| 97 | + &:hover { | |
| 98 | + border-color: #409eff; | |
| 99 | + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); | |
| 100 | + } | |
| 101 | + | |
| 102 | + .day-number { | |
| 103 | + font-weight: bold; | |
| 104 | + margin-bottom: 5px; | |
| 105 | + } | |
| 106 | + | |
| 107 | + .workday-name { | |
| 108 | + margin-bottom: 5px; | |
| 109 | + } | |
| 110 | + | |
| 111 | + .time-range { | |
| 112 | + font-size: 12px; | |
| 113 | + color: #666; | |
| 114 | + } | |
| 115 | +} | |
| 116 | +</style> | |
| 0 | 117 | \ No newline at end of file | ... | ... |
src/components/org/scheduleClassesMonth.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div> | |
| 3 | + <el-form-item :label="$t('scheduleClassesMonth.scheduleCycle')"> | |
| 4 | + <el-select | |
| 5 | + v-model="scheduleCycle" | |
| 6 | + :placeholder="$t('scheduleClassesMonth.scheduleCyclePlaceholder')" | |
| 7 | + @change="changeInspectionPeriod" | |
| 8 | + style="width:100%" | |
| 9 | + > | |
| 10 | + <el-option | |
| 11 | + :label="`1${$t('scheduleClassesMonth.month')}`" | |
| 12 | + value="1" | |
| 13 | + /> | |
| 14 | + </el-select> | |
| 15 | + </el-form-item> | |
| 16 | + | |
| 17 | + <el-form-item :label="$t('scheduleClassesMonth.scheduleInfo')"> | |
| 18 | + <div class="schedule-days-container"> | |
| 19 | + <div | |
| 20 | + v-for="(item, index) in days" | |
| 21 | + :key="index" | |
| 22 | + class="schedule-day-item" | |
| 23 | + @click="changeWorkdayInfo(item)" | |
| 24 | + > | |
| 25 | + <div class="day-number">{{ item.day }}</div> | |
| 26 | + <div class="workday-name">{{ item.workdayName }}</div> | |
| 27 | + <div | |
| 28 | + v-for="(time, timeIndex) in item.times" | |
| 29 | + :key="timeIndex" | |
| 30 | + class="time-range" | |
| 31 | + > | |
| 32 | + {{ time.startTime }}-{{ time.endTime }} | |
| 33 | + </div> | |
| 34 | + </div> | |
| 35 | + </div> | |
| 36 | + </el-form-item> | |
| 37 | + </div> | |
| 38 | +</template> | |
| 39 | + | |
| 40 | +<script> | |
| 41 | +export default { | |
| 42 | + name: 'ScheduleClassesMonth', | |
| 43 | + props: { | |
| 44 | + initialData: { | |
| 45 | + type: Object, | |
| 46 | + default: () => ({}) | |
| 47 | + } | |
| 48 | + }, | |
| 49 | + data() { | |
| 50 | + return { | |
| 51 | + scheduleCycle: 1, | |
| 52 | + days: [] | |
| 53 | + } | |
| 54 | + }, | |
| 55 | + created() { | |
| 56 | + if (this.initialData.days && this.initialData.days.length > 0) { | |
| 57 | + this.days = [...this.initialData.days] | |
| 58 | + this.scheduleCycle = this.initialData.scheduleCycle | |
| 59 | + } else { | |
| 60 | + this.changeInspectionPeriod() | |
| 61 | + } | |
| 62 | + }, | |
| 63 | + methods: { | |
| 64 | + initData(scheduleCycle) { | |
| 65 | + this.scheduleCycle = scheduleCycle | |
| 66 | + this.changeInspectionPeriod() | |
| 67 | + }, | |
| 68 | + changeInspectionPeriod() { | |
| 69 | + this.days = [] | |
| 70 | + for (let cycleIndex = 0; cycleIndex < 31; cycleIndex++) { | |
| 71 | + this.days.push({ | |
| 72 | + day: cycleIndex + 1, | |
| 73 | + workday: '2002', | |
| 74 | + workdayName: this.$t('scheduleClassesMonth.rest'), | |
| 75 | + times: [] | |
| 76 | + }) | |
| 77 | + } | |
| 78 | + }, | |
| 79 | + changeWorkdayInfo(item) { | |
| 80 | + this.$emit('edit-day', item) | |
| 81 | + }, | |
| 82 | + getDaysData() { | |
| 83 | + return this.days | |
| 84 | + } | |
| 85 | + } | |
| 86 | +} | |
| 87 | +</script> | |
| 88 | + | |
| 89 | +<style lang="scss" scoped> | |
| 90 | +.schedule-days-container { | |
| 91 | + display: flex; | |
| 92 | + flex-wrap: wrap; | |
| 93 | + gap: 10px; | |
| 94 | +} | |
| 95 | + | |
| 96 | +.schedule-day-item { | |
| 97 | + width: calc(16.66% - 10px); | |
| 98 | + padding: 10px; | |
| 99 | + border: 1px solid #ebeef5; | |
| 100 | + border-radius: 4px; | |
| 101 | + cursor: pointer; | |
| 102 | + text-align: center; | |
| 103 | + transition: all 0.3s; | |
| 104 | + | |
| 105 | + &:hover { | |
| 106 | + border-color: #409eff; | |
| 107 | + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); | |
| 108 | + } | |
| 109 | + | |
| 110 | + .day-number { | |
| 111 | + font-weight: bold; | |
| 112 | + margin-bottom: 5px; | |
| 113 | + } | |
| 114 | + | |
| 115 | + .workday-name { | |
| 116 | + margin-bottom: 5px; | |
| 117 | + } | |
| 118 | + | |
| 119 | + .time-range { | |
| 120 | + font-size: 12px; | |
| 121 | + color: #666; | |
| 122 | + } | |
| 123 | +} | |
| 124 | +</style> | |
| 0 | 125 | \ No newline at end of file | ... | ... |
src/components/org/scheduleClassesState.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <el-dialog | |
| 3 | + :title="$t('scheduleClasses.state.title')" | |
| 4 | + :visible.sync="visible" | |
| 5 | + width="30%" | |
| 6 | + @close="handleClose" | |
| 7 | + > | |
| 8 | + <div style="text-align: center"> | |
| 9 | + <p> | |
| 10 | + {{ $t('scheduleClasses.state.confirm') }} | |
| 11 | + <strong>{{ formData.stateName }}</strong> | |
| 12 | + {{ $t('scheduleClasses.state.schedule') }} | |
| 13 | + </p> | |
| 14 | + </div> | |
| 15 | + <span slot="footer" class="dialog-footer"> | |
| 16 | + <el-button @click="handleClose">{{ $t('common.cancel') }}</el-button> | |
| 17 | + <el-button type="primary" @click="handleConfirm">{{ $t('common.confirm') }}</el-button> | |
| 18 | + </span> | |
| 19 | + </el-dialog> | |
| 20 | +</template> | |
| 21 | + | |
| 22 | +<script> | |
| 23 | +import { updateScheduleClassesState } from '@/api/org/scheduleClassesApi' | |
| 24 | + | |
| 25 | +export default { | |
| 26 | + name: 'ScheduleClassesState', | |
| 27 | + data() { | |
| 28 | + return { | |
| 29 | + visible: false, | |
| 30 | + formData: { | |
| 31 | + scheduleId: '', | |
| 32 | + stateName: '', | |
| 33 | + state: '' | |
| 34 | + } | |
| 35 | + } | |
| 36 | + }, | |
| 37 | + methods: { | |
| 38 | + open(data) { | |
| 39 | + this.formData = { ...data } | |
| 40 | + this.visible = true | |
| 41 | + }, | |
| 42 | + async handleConfirm() { | |
| 43 | + try { | |
| 44 | + await updateScheduleClassesState(this.formData) | |
| 45 | + this.$message.success(this.$t('scheduleClasses.state.success')) | |
| 46 | + this.$emit('success') | |
| 47 | + this.visible = false | |
| 48 | + } catch (error) { | |
| 49 | + this.$message.error(this.$t('scheduleClasses.state.error')) | |
| 50 | + } | |
| 51 | + }, | |
| 52 | + handleClose() { | |
| 53 | + this.visible = false | |
| 54 | + } | |
| 55 | + } | |
| 56 | +} | |
| 57 | +</script> | |
| 0 | 58 | \ No newline at end of file | ... | ... |
src/components/org/scheduleClassesWeek.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div> | |
| 3 | + <el-form-item :label="$t('scheduleClassesWeek.scheduleCycle')"> | |
| 4 | + <el-select v-model="scheduleCycle" :placeholder="$t('scheduleClassesWeek.scheduleCyclePlaceholder')" | |
| 5 | + @change="changeInspectionPeriodWeek" style="width:100%"> | |
| 6 | + <el-option v-for="index in 4" :key="index" :label="`${index}${$t('scheduleClassesWeek.week')}`" | |
| 7 | + :value="index" /> | |
| 8 | + </el-select> | |
| 9 | + </el-form-item> | |
| 10 | + | |
| 11 | + <div v-for="week in scheduleCycle" :key="week"> | |
| 12 | + <el-form-item :label="getWeek(week)"> | |
| 13 | + <div class="schedule-weeks-container"> | |
| 14 | + <template v-for="(item, index) in days"> | |
| 15 | + <div v-if="item.weekFlag === week" :key="index" class="schedule-week-item" @click="changeWorkdayWeekInfo(item)"> | |
| 16 | + <div class="day-name">{{ getWorkDay(item.day) }}</div> | |
| 17 | + <div class="workday-name">{{ item.workdayName }}</div> | |
| 18 | + <div v-for="(time, timeIndex) in item.times" :key="timeIndex" class="time-range"> | |
| 19 | + {{ time.startTime }}-{{ time.endTime }} | |
| 20 | + </div> | |
| 21 | + </div> | |
| 22 | + </template> | |
| 23 | + </div> | |
| 24 | + </el-form-item> | |
| 25 | + </div> | |
| 26 | + </div> | |
| 27 | +</template> | |
| 28 | + | |
| 29 | +<script> | |
| 30 | +export default { | |
| 31 | + name: 'ScheduleClassesWeek', | |
| 32 | + props: { | |
| 33 | + initialData: { | |
| 34 | + type: Object, | |
| 35 | + default: () => ({}) | |
| 36 | + } | |
| 37 | + }, | |
| 38 | + data() { | |
| 39 | + return { | |
| 40 | + scheduleCycle: 1, | |
| 41 | + days: [] | |
| 42 | + } | |
| 43 | + }, | |
| 44 | + created() { | |
| 45 | + if (this.initialData.days && this.initialData.days.length > 0) { | |
| 46 | + this.days = [...this.initialData.days] | |
| 47 | + this.scheduleCycle = this.initialData.scheduleCycle | |
| 48 | + } else { | |
| 49 | + this.changeInspectionPeriodWeek() | |
| 50 | + } | |
| 51 | + }, | |
| 52 | + methods: { | |
| 53 | + initData(scheduleCycle) { | |
| 54 | + this.scheduleCycle = scheduleCycle | |
| 55 | + this.changeInspectionPeriodWeek() | |
| 56 | + }, | |
| 57 | + changeInspectionPeriodWeek() { | |
| 58 | + this.days = [] | |
| 59 | + for (let weekIndex = 0; weekIndex < this.scheduleCycle; weekIndex++) { | |
| 60 | + for (let cycleIndex = 0; cycleIndex < 7; cycleIndex++) { | |
| 61 | + this.days.push({ | |
| 62 | + weekFlag: weekIndex + 1, | |
| 63 | + day: cycleIndex + 1, | |
| 64 | + workday: '2002', | |
| 65 | + workdayName: this.$t('scheduleClassesWeek.rest'), | |
| 66 | + times: [] | |
| 67 | + }) | |
| 68 | + } | |
| 69 | + } | |
| 70 | + this.$emit('cycle-change', this.scheduleCycle) | |
| 71 | + }, | |
| 72 | + changeWorkdayWeekInfo(item) { | |
| 73 | + this.$emit('edit-day', item) | |
| 74 | + }, | |
| 75 | + getWeek(week) { | |
| 76 | + return `${week}${this.$t('scheduleClassesWeek.week')}` | |
| 77 | + }, | |
| 78 | + getWorkDay(day) { | |
| 79 | + const days = [ | |
| 80 | + this.$t('common.monday'), | |
| 81 | + this.$t('common.tuesday'), | |
| 82 | + this.$t('common.wednesday'), | |
| 83 | + this.$t('common.thursday'), | |
| 84 | + this.$t('common.friday'), | |
| 85 | + this.$t('common.saturday'), | |
| 86 | + this.$t('common.sunday') | |
| 87 | + ] | |
| 88 | + return days[day - 1] | |
| 89 | + }, | |
| 90 | + getDaysData() { | |
| 91 | + return this.days | |
| 92 | + } | |
| 93 | + } | |
| 94 | +} | |
| 95 | +</script> | |
| 96 | + | |
| 97 | +<style lang="scss" scoped> | |
| 98 | +.schedule-weeks-container { | |
| 99 | + display: flex; | |
| 100 | + flex-wrap: wrap; | |
| 101 | + gap: 10px; | |
| 102 | +} | |
| 103 | + | |
| 104 | +.schedule-week-item { | |
| 105 | + width: calc(14.28% - 10px); | |
| 106 | + padding: 10px; | |
| 107 | + border: 1px solid #ebeef5; | |
| 108 | + border-radius: 4px; | |
| 109 | + cursor: pointer; | |
| 110 | + text-align: center; | |
| 111 | + transition: all 0.3s; | |
| 112 | + | |
| 113 | + &:hover { | |
| 114 | + border-color: #409eff; | |
| 115 | + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); | |
| 116 | + } | |
| 117 | + | |
| 118 | + .day-name { | |
| 119 | + font-weight: bold; | |
| 120 | + margin-bottom: 5px; | |
| 121 | + } | |
| 122 | + | |
| 123 | + .workday-name { | |
| 124 | + margin-bottom: 5px; | |
| 125 | + } | |
| 126 | + | |
| 127 | + .time-range { | |
| 128 | + font-size: 12px; | |
| 129 | + color: #666; | |
| 130 | + } | |
| 131 | +} | |
| 132 | +</style> | |
| 0 | 133 | \ No newline at end of file | ... | ... |
src/components/system/editStoreAttr.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <el-dialog :title="$t('editStoreAttr.title')" :visible.sync="visible" width="60%" @close="handleClose"> | |
| 3 | + <el-form ref="form" :model="form" :rules="rules" label-width="120px" label-position="right"> | |
| 4 | + <el-form-item :label="form.name"> | |
| 5 | + <el-input v-model="form.value" :placeholder="$t('editStoreAttr.attributePlaceholder')" /> | |
| 6 | + </el-form-item> | |
| 7 | + </el-form> | |
| 8 | + <span slot="footer" class="dialog-footer"> | |
| 9 | + <el-button @click="visible = false"> | |
| 10 | + {{ $t('common.cancel') }} | |
| 11 | + </el-button> | |
| 12 | + <el-button type="primary" @click="submitForm"> | |
| 13 | + {{ $t('common.save') }} | |
| 14 | + </el-button> | |
| 15 | + </span> | |
| 16 | + </el-dialog> | |
| 17 | +</template> | |
| 18 | + | |
| 19 | +<script> | |
| 20 | +import { updateStoreAttr } from '@/api/system/storeInfoManageApi' | |
| 21 | + | |
| 22 | +export default { | |
| 23 | + name: 'EditStoreAttr', | |
| 24 | + data() { | |
| 25 | + return { | |
| 26 | + visible: false, | |
| 27 | + form: { | |
| 28 | + attrId: '', | |
| 29 | + value: '', | |
| 30 | + name: '' | |
| 31 | + }, | |
| 32 | + rules: { | |
| 33 | + value: [ | |
| 34 | + { required: true, message: this.$t('editStoreAttr.validate.valueRequired'), trigger: 'blur' }, | |
| 35 | + { max: 50, message: this.$t('editStoreAttr.validate.valueMaxLength'), trigger: 'blur' } | |
| 36 | + ], | |
| 37 | + attrId: [ | |
| 38 | + { required: true, message: this.$t('editStoreAttr.validate.attrIdRequired'), trigger: 'blur' } | |
| 39 | + ] | |
| 40 | + } | |
| 41 | + } | |
| 42 | + }, | |
| 43 | + methods: { | |
| 44 | + open(storeAttr) { | |
| 45 | + this.resetForm() | |
| 46 | + this.form = { | |
| 47 | + ...this.form, | |
| 48 | + ...storeAttr | |
| 49 | + } | |
| 50 | + this.visible = true | |
| 51 | + }, | |
| 52 | + resetForm() { | |
| 53 | + this.form = { | |
| 54 | + attrId: '', | |
| 55 | + value: '', | |
| 56 | + name: '' | |
| 57 | + } | |
| 58 | + }, | |
| 59 | + handleClose() { | |
| 60 | + this.resetForm() | |
| 61 | + }, | |
| 62 | + submitForm() { | |
| 63 | + this.$refs.form.validate(async valid => { | |
| 64 | + if (valid) { | |
| 65 | + try { | |
| 66 | + await updateStoreAttr(this.form) | |
| 67 | + this.$message.success(this.$t('common.saveSuccess')) | |
| 68 | + this.visible = false | |
| 69 | + this.$emit('success') | |
| 70 | + } catch (error) { | |
| 71 | + this.$message.error(error.message || this.$t('common.saveFailed')) | |
| 72 | + } | |
| 73 | + } | |
| 74 | + }) | |
| 75 | + } | |
| 76 | + } | |
| 77 | +} | |
| 78 | +</script> | |
| 0 | 79 | \ No newline at end of file | ... | ... |
src/components/system/editStoreInfo.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <el-dialog :title="$t('editStoreInfo.title')" :visible.sync="visible" width="60%" @close="handleClose"> | |
| 3 | + <el-form ref="form" :model="form" :rules="rules" label-width="120px" label-position="right"> | |
| 4 | + <el-form-item :label="$t('editStoreInfo.storeName')" prop="name"> | |
| 5 | + <el-input v-model="form.name" :placeholder="$t('editStoreInfo.storeNamePlaceholder')" disabled /> | |
| 6 | + </el-form-item> | |
| 7 | + <el-form-item :label="$t('editStoreInfo.storeAddress')" prop="address"> | |
| 8 | + <el-input v-model="form.address" :placeholder="$t('editStoreInfo.storeAddressPlaceholder')" /> | |
| 9 | + </el-form-item> | |
| 10 | + <el-form-item :label="$t('editStoreInfo.contactNumber')" prop="tel"> | |
| 11 | + <el-input v-model="form.tel" :placeholder="$t('editStoreInfo.contactNumberPlaceholder')" /> | |
| 12 | + </el-form-item> | |
| 13 | + <el-form-item :label="$t('editStoreInfo.nearbyLandmark')" prop="nearByLandmarks"> | |
| 14 | + <el-input v-model="form.nearByLandmarks" :placeholder="$t('editStoreInfo.nearbyLandmarkPlaceholder')" /> | |
| 15 | + </el-form-item> | |
| 16 | + <el-form-item :label="$t('editStoreInfo.mapX')" prop="mapX"> | |
| 17 | + <el-input v-model="form.mapX" :placeholder="$t('editStoreInfo.mapXPlaceholder')" /> | |
| 18 | + </el-form-item> | |
| 19 | + <el-form-item :label="$t('editStoreInfo.mapY')" prop="mapY"> | |
| 20 | + <el-input v-model="form.mapY" :placeholder="$t('editStoreInfo.mapYPlaceholder')" /> | |
| 21 | + </el-form-item> | |
| 22 | + </el-form> | |
| 23 | + <span slot="footer" class="dialog-footer"> | |
| 24 | + <el-button @click="visible = false"> | |
| 25 | + {{ $t('common.cancel') }} | |
| 26 | + </el-button> | |
| 27 | + <el-button type="primary" @click="submitForm"> | |
| 28 | + {{ $t('common.save') }} | |
| 29 | + </el-button> | |
| 30 | + </span> | |
| 31 | + </el-dialog> | |
| 32 | +</template> | |
| 33 | + | |
| 34 | +<script> | |
| 35 | +import { updateStoreInfo } from '@/api/system/storeInfoManageApi' | |
| 36 | + | |
| 37 | +export default { | |
| 38 | + name: 'EditStoreInfo', | |
| 39 | + data() { | |
| 40 | + return { | |
| 41 | + visible: false, | |
| 42 | + form: { | |
| 43 | + storeId: '', | |
| 44 | + name: '', | |
| 45 | + address: '', | |
| 46 | + tel: '', | |
| 47 | + nearByLandmarks: '', | |
| 48 | + mapX: '', | |
| 49 | + mapY: '' | |
| 50 | + }, | |
| 51 | + rules: { | |
| 52 | + name: [ | |
| 53 | + { required: true, message: this.$t('editStoreInfo.validate.nameRequired'), trigger: 'blur' }, | |
| 54 | + { max: 100, message: this.$t('editStoreInfo.validate.nameMaxLength'), trigger: 'blur' } | |
| 55 | + ], | |
| 56 | + address: [ | |
| 57 | + { required: true, message: this.$t('editStoreInfo.validate.addressRequired'), trigger: 'blur' }, | |
| 58 | + { max: 200, message: this.$t('editStoreInfo.validate.addressMaxLength'), trigger: 'blur' } | |
| 59 | + ], | |
| 60 | + tel: [ | |
| 61 | + { required: true, message: this.$t('editStoreInfo.validate.telRequired'), trigger: 'blur' }, | |
| 62 | + { max: 11, message: this.$t('editStoreInfo.validate.telMaxLength'), trigger: 'blur' } | |
| 63 | + ], | |
| 64 | + nearByLandmarks: [ | |
| 65 | + { required: true, message: this.$t('editStoreInfo.validate.landmarkRequired'), trigger: 'blur' }, | |
| 66 | + { max: 200, message: this.$t('editStoreInfo.validate.landmarkMaxLength'), trigger: 'blur' } | |
| 67 | + ] | |
| 68 | + } | |
| 69 | + } | |
| 70 | + }, | |
| 71 | + methods: { | |
| 72 | + open(storeInfo) { | |
| 73 | + this.resetForm() | |
| 74 | + this.form = { | |
| 75 | + ...this.form, | |
| 76 | + ...storeInfo | |
| 77 | + } | |
| 78 | + this.visible = true | |
| 79 | + }, | |
| 80 | + resetForm() { | |
| 81 | + this.form = { | |
| 82 | + storeId: '', | |
| 83 | + name: '', | |
| 84 | + address: '', | |
| 85 | + tel: '', | |
| 86 | + nearByLandmarks: '', | |
| 87 | + mapX: '', | |
| 88 | + mapY: '' | |
| 89 | + } | |
| 90 | + }, | |
| 91 | + handleClose() { | |
| 92 | + this.resetForm() | |
| 93 | + }, | |
| 94 | + submitForm() { | |
| 95 | + this.$refs.form.validate(async valid => { | |
| 96 | + if (valid) { | |
| 97 | + try { | |
| 98 | + await updateStoreInfo(this.form) | |
| 99 | + this.$message.success(this.$t('common.saveSuccess')) | |
| 100 | + this.visible = false | |
| 101 | + this.$emit('success') | |
| 102 | + } catch (error) { | |
| 103 | + this.$message.error(error.message || this.$t('common.saveFailed')) | |
| 104 | + } | |
| 105 | + } | |
| 106 | + }) | |
| 107 | + } | |
| 108 | + } | |
| 109 | +} | |
| 110 | +</script> | |
| 0 | 111 | \ No newline at end of file | ... | ... |
src/components/system/orgTreeShow.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="org-tree-show"> | |
| 3 | + <el-tree | |
| 4 | + ref="orgTree" | |
| 5 | + :data="orgData" | |
| 6 | + :props="defaultProps" | |
| 7 | + node-key="id" | |
| 8 | + default-expand-all | |
| 9 | + highlight-current | |
| 10 | + @node-click="handleNodeClick" | |
| 11 | + /> | |
| 12 | + </div> | |
| 13 | +</template> | |
| 14 | + | |
| 15 | +<script> | |
| 16 | +import { listOrgTree } from '@/api/system/workflowSettingManageApi' | |
| 17 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 18 | + | |
| 19 | +export default { | |
| 20 | + name: 'OrgTreeShow', | |
| 21 | + data() { | |
| 22 | + return { | |
| 23 | + communityId: '', | |
| 24 | + orgData: [], | |
| 25 | + defaultProps: { | |
| 26 | + children: 'children', | |
| 27 | + label: 'text' | |
| 28 | + } | |
| 29 | + } | |
| 30 | + }, | |
| 31 | + methods: { | |
| 32 | + async initTree() { | |
| 33 | + this.communityId = getCommunityId() | |
| 34 | + try { | |
| 35 | + const { data } = await listOrgTree({ | |
| 36 | + communityId: this.communityId | |
| 37 | + }) | |
| 38 | + this.orgData = data || [] | |
| 39 | + } catch (error) { | |
| 40 | + this.$message.error(this.$t('orgTree.fetchError')) | |
| 41 | + } | |
| 42 | + }, | |
| 43 | + | |
| 44 | + handleNodeClick(data) { | |
| 45 | + this.$emit('switch-org', { | |
| 46 | + orgId: data.id, | |
| 47 | + orgName: data.text | |
| 48 | + }) | |
| 49 | + } | |
| 50 | + } | |
| 51 | +} | |
| 52 | +</script> | |
| 53 | + | |
| 54 | +<style lang="scss" scoped> | |
| 55 | +.org-tree-show { | |
| 56 | + /deep/ .el-tree { | |
| 57 | + .el-tree-node { | |
| 58 | + .el-tree-node__content { | |
| 59 | + height: 40px; | |
| 60 | + | |
| 61 | + &:hover { | |
| 62 | + background-color: #f5f7fa; | |
| 63 | + } | |
| 64 | + } | |
| 65 | + | |
| 66 | + &.is-current { | |
| 67 | + > .el-tree-node__content { | |
| 68 | + background-color: #ecf5ff; | |
| 69 | + color: #409eff; | |
| 70 | + } | |
| 71 | + } | |
| 72 | + } | |
| 73 | + } | |
| 74 | +} | |
| 75 | +</style> | |
| 0 | 76 | \ No newline at end of file | ... | ... |
src/components/system/selectStaff.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <el-dialog | |
| 3 | + :visible.sync="visible" | |
| 4 | + :title="$t('selectStaff.title')" | |
| 5 | + width="70%" | |
| 6 | + @close="handleClose" | |
| 7 | + > | |
| 8 | + <el-row :gutter="20"> | |
| 9 | + <el-col :span="12" class="border-right"> | |
| 10 | + <div class="text-center mb-20"> | |
| 11 | + <h4>{{ $t('selectStaff.orgInfo') }}</h4> | |
| 12 | + </div> | |
| 13 | + <div class="org-tree-container"> | |
| 14 | + <org-tree-show | |
| 15 | + ref="orgTree" | |
| 16 | + @switch-org="handleSwitchOrg" | |
| 17 | + /> | |
| 18 | + </div> | |
| 19 | + </el-col> | |
| 20 | + | |
| 21 | + <el-col :span="12"> | |
| 22 | + <div class="text-center mb-20"> | |
| 23 | + <h4>{{ $t('selectStaff.staffInfo') }}</h4> | |
| 24 | + </div> | |
| 25 | + <div class="staff-list"> | |
| 26 | + <div | |
| 27 | + v-for="(item,index) in staffList" | |
| 28 | + :key="index" | |
| 29 | + class="staff-item" | |
| 30 | + :class="{ 'active': currentStaffId === item.userId }" | |
| 31 | + @click="handleSelectStaff(item)" | |
| 32 | + > | |
| 33 | + <div> | |
| 34 | + <i class="el-icon-user margin-right-xs"></i> | |
| 35 | + {{ item.userName }} | |
| 36 | + </div> | |
| 37 | + <div>{{ item.tel }}</div> | |
| 38 | + </div> | |
| 39 | + </div> | |
| 40 | + </el-col> | |
| 41 | + </el-row> | |
| 42 | + | |
| 43 | + <div | |
| 44 | + v-if="staff.from === 'bpmn' || staff.from === 'purchase' || staff.from === 'contract'" | |
| 45 | + slot="footer" | |
| 46 | + class="dialog-footer" | |
| 47 | + > | |
| 48 | + <el-button @click="handleFirstUser">{{ $t('selectStaff.submitter') }}</el-button> | |
| 49 | + <el-button @click="handleCustomUser">{{ $t('selectStaff.dynamicAssign') }}</el-button> | |
| 50 | + </div> | |
| 51 | + </el-dialog> | |
| 52 | +</template> | |
| 53 | + | |
| 54 | +<script> | |
| 55 | +import { queryStaffInfos } from '@/api/system/workflowSettingManageApi' | |
| 56 | +import OrgTreeShow from './OrgTreeShow' | |
| 57 | + | |
| 58 | +export default { | |
| 59 | + name: 'SelectStaff', | |
| 60 | + components: { | |
| 61 | + OrgTreeShow | |
| 62 | + }, | |
| 63 | + data() { | |
| 64 | + return { | |
| 65 | + visible: false, | |
| 66 | + staff: {}, | |
| 67 | + staffList: [], | |
| 68 | + currentStaffId: '', | |
| 69 | + currentOrg: null | |
| 70 | + } | |
| 71 | + }, | |
| 72 | + methods: { | |
| 73 | + open(staff) { | |
| 74 | + this.staff = staff | |
| 75 | + this.visible = true | |
| 76 | + this.$nextTick(() => { | |
| 77 | + this.$refs.orgTree.initTree() | |
| 78 | + }) | |
| 79 | + }, | |
| 80 | + | |
| 81 | + handleClose() { | |
| 82 | + this.staffList = [] | |
| 83 | + this.currentStaffId = '' | |
| 84 | + this.currentOrg = null | |
| 85 | + }, | |
| 86 | + | |
| 87 | + async handleSwitchOrg(org) { | |
| 88 | + this.currentOrg = org | |
| 89 | + try { | |
| 90 | + const { data } = await queryStaffInfos({ | |
| 91 | + page: 1, | |
| 92 | + row: 50, | |
| 93 | + orgId: org.orgId | |
| 94 | + }) | |
| 95 | + this.staffList = data.staffs || [] | |
| 96 | + if (this.staffList.length > 0) { | |
| 97 | + this.currentStaffId = this.staffList[0].userId | |
| 98 | + } | |
| 99 | + } catch (error) { | |
| 100 | + this.$message.error(this.$t('selectStaff.fetchStaffError')) | |
| 101 | + } | |
| 102 | + }, | |
| 103 | + | |
| 104 | + handleSelectStaff(item) { | |
| 105 | + this.staff.staffId = item.userId | |
| 106 | + this.staff.staffName = item.userName | |
| 107 | + this.visible = false | |
| 108 | + if (this.staff.call && typeof this.staff.call === 'function') { | |
| 109 | + this.staff.call(this.staff) | |
| 110 | + } | |
| 111 | + }, | |
| 112 | + | |
| 113 | + handleFirstUser() { | |
| 114 | + this.staff.staffId = '${startUserId}' | |
| 115 | + this.staff.staffName = this.$t('selectStaff.submitter') | |
| 116 | + this.visible = false | |
| 117 | + if (this.staff.call && typeof this.staff.call === 'function') { | |
| 118 | + this.staff.call(this.staff) | |
| 119 | + } | |
| 120 | + }, | |
| 121 | + | |
| 122 | + handleCustomUser() { | |
| 123 | + this.staff.staffId = '${nextUserId}' | |
| 124 | + this.staff.staffName = this.$t('selectStaff.dynamicAssign') | |
| 125 | + this.visible = false | |
| 126 | + if (this.staff.call && typeof this.staff.call === 'function') { | |
| 127 | + this.staff.call(this.staff) | |
| 128 | + } | |
| 129 | + } | |
| 130 | + } | |
| 131 | +} | |
| 132 | +</script> | |
| 133 | + | |
| 134 | +<style lang="scss" scoped> | |
| 135 | +.border-right { | |
| 136 | + border-right: 1px solid #ebeef5; | |
| 137 | +} | |
| 138 | + | |
| 139 | +.org-tree-container { | |
| 140 | + height: 400px; | |
| 141 | + overflow-y: auto; | |
| 142 | +} | |
| 143 | + | |
| 144 | +.staff-list { | |
| 145 | + height: 400px; | |
| 146 | + overflow-y: auto; | |
| 147 | + | |
| 148 | + .staff-item { | |
| 149 | + padding: 10px; | |
| 150 | + margin-bottom: 10px; | |
| 151 | + cursor: pointer; | |
| 152 | + border-radius: 4px; | |
| 153 | + | |
| 154 | + &:hover { | |
| 155 | + background-color: #f5f7fa; | |
| 156 | + } | |
| 157 | + | |
| 158 | + &.active { | |
| 159 | + background-color: #ecf5ff; | |
| 160 | + color: #409eff; | |
| 161 | + } | |
| 162 | + } | |
| 163 | +} | |
| 164 | + | |
| 165 | +.margin-right-xs { | |
| 166 | + margin-right: 5px; | |
| 167 | +} | |
| 168 | + | |
| 169 | +.mb-20 { | |
| 170 | + margin-bottom: 20px; | |
| 171 | +} | |
| 172 | + | |
| 173 | +.dialog-footer { | |
| 174 | + text-align: right; | |
| 175 | +} | |
| 176 | +</style> | |
| 0 | 177 | \ No newline at end of file | ... | ... |
src/components/system/viewImage.vue
| 1 | 1 | <template> |
| 2 | - <div class="image-viewer"> | |
| 3 | - <el-dialog | |
| 4 | - :visible.sync="dialogVisible" | |
| 5 | - fullscreen | |
| 2 | + <div class="view-image-container"> | |
| 3 | + <el-dialog | |
| 4 | + :visible.sync="visible" | |
| 5 | + :fullscreen="true" | |
| 6 | 6 | :show-close="false" |
| 7 | - @close="closeDialog"> | |
| 8 | - <div class="image-container"> | |
| 9 | - <el-image | |
| 10 | - :src="imageUrl" | |
| 11 | - fit="contain" | |
| 12 | - :style="{ width: imageWidth + 'px', height: imageHeight + 'px' }"> | |
| 13 | - </el-image> | |
| 14 | - <i class="el-icon-close close-icon" @click="closeDialog"></i> | |
| 7 | + custom-class="image-viewer-dialog" | |
| 8 | + > | |
| 9 | + <div class="image-wrapper"> | |
| 10 | + <img | |
| 11 | + :src="imageInfo.url" | |
| 12 | + :style="{ | |
| 13 | + width: imageInfo.width + 'px', | |
| 14 | + height: imageInfo.height + 'px' | |
| 15 | + }" | |
| 16 | + @error="handleImageError" | |
| 17 | + /> | |
| 18 | + <i class="el-icon-close close-icon" @click="close"></i> | |
| 15 | 19 | </div> |
| 16 | 20 | </el-dialog> |
| 17 | 21 | </div> |
| ... | ... | @@ -22,50 +26,74 @@ export default { |
| 22 | 26 | name: 'ViewImage', |
| 23 | 27 | data() { |
| 24 | 28 | return { |
| 25 | - dialogVisible: false, | |
| 26 | - imageUrl: '', | |
| 27 | - imageWidth: 800, | |
| 28 | - imageHeight: 800 | |
| 29 | + visible: false, | |
| 30 | + imageInfo: { | |
| 31 | + url: '', | |
| 32 | + width: 800, | |
| 33 | + height: 800 | |
| 34 | + } | |
| 29 | 35 | } |
| 30 | 36 | }, |
| 31 | 37 | methods: { |
| 32 | - open(url) { | |
| 33 | - this.imageUrl = url | |
| 34 | - this.dialogVisible = true | |
| 38 | + open(params) { | |
| 39 | + this.imageInfo.url = params.url | |
| 40 | + this.visible = true | |
| 35 | 41 | |
| 36 | - // 计算图片宽高比例 | |
| 42 | + // 动态计算图片尺寸 | |
| 37 | 43 | const img = new Image() |
| 38 | - img.src = url | |
| 44 | + img.src = params.url | |
| 39 | 45 | img.onload = () => { |
| 40 | - const ratio = img.width / img.height | |
| 41 | - this.imageWidth = 800 | |
| 42 | - this.imageHeight = 800 / ratio | |
| 46 | + const imgScale = img.width / img.height | |
| 47 | + this.imageInfo.width = 800 | |
| 48 | + this.imageInfo.height = 800 / imgScale | |
| 49 | + } | |
| 50 | + }, | |
| 51 | + close() { | |
| 52 | + this.visible = false | |
| 53 | + this.imageInfo = { | |
| 54 | + url: '', | |
| 55 | + width: 800, | |
| 56 | + height: 800 | |
| 43 | 57 | } |
| 44 | 58 | }, |
| 45 | - closeDialog() { | |
| 46 | - this.dialogVisible = false | |
| 59 | + handleImageError(e) { | |
| 60 | + e.target.src = '/img/noPhoto.jpg' | |
| 47 | 61 | } |
| 48 | 62 | } |
| 49 | 63 | } |
| 50 | 64 | </script> |
| 51 | 65 | |
| 52 | 66 | <style lang="scss" scoped> |
| 53 | -.image-viewer { | |
| 54 | - .image-container { | |
| 55 | - position: fixed; | |
| 56 | - top: 50%; | |
| 57 | - left: 50%; | |
| 58 | - transform: translate(-50%, -50%); | |
| 59 | - background-color: #fff; | |
| 60 | - padding: 20px; | |
| 67 | +.view-image-container { | |
| 68 | + .image-viewer-dialog { | |
| 69 | + background-color: rgba(0, 0, 0, 0.8); | |
| 61 | 70 | |
| 62 | - .close-icon { | |
| 63 | - position: absolute; | |
| 64 | - right: 20px; | |
| 65 | - top: 20px; | |
| 66 | - font-size: 24px; | |
| 67 | - color: #F56C6C; | |
| 68 | - cursor: pointer; | |
| 71 | + .image-wrapper { | |
| 72 | + position: relative; | |
| 73 | + display: flex; | |
| 74 | + justify-content: center; | |
| 75 | + align-items: center; | |
| 76 | + height: 100%; | |
| 77 | + | |
| 78 | + img { | |
| 79 | + max-width: 90%; | |
| 80 | + max-height: 90%; | |
| 81 | + object-fit: contain; | |
| 82 | + } | |
| 83 | + | |
| 84 | + .close-icon { | |
| 85 | + position: absolute; | |
| 86 | + top: 20px; | |
| 87 | + right: 20px; | |
| 88 | + font-size: 24px; | |
| 89 | + color: #fff; | |
| 90 | + cursor: pointer; | |
| 91 | + z-index: 2001; | |
| 92 | + | |
| 93 | + &:hover { | |
| 94 | + color: #f56c6c; | |
| 95 | + } | |
| 96 | + } | |
| 69 | 97 | } |
| 70 | 98 | } |
| 71 | 99 | } | ... | ... |
src/i18n/index.js
| ... | ... | @@ -143,6 +143,7 @@ import { messages as resourceI18n } from './resourceI18n' |
| 143 | 143 | import { messages as carI18n } from './carI18n' |
| 144 | 144 | import { messages as scmI18n } from './scmI18n' |
| 145 | 145 | import { messages as userI18n } from './userI18n' |
| 146 | +import { messages as systemI18n } from './systemI18n' | |
| 146 | 147 | |
| 147 | 148 | Vue.use(VueI18n) |
| 148 | 149 | |
| ... | ... | @@ -284,6 +285,7 @@ const messages = { |
| 284 | 285 | ...carI18n.en, |
| 285 | 286 | ...scmI18n.en, |
| 286 | 287 | ...userI18n.en, |
| 288 | + ...systemI18n.en, | |
| 287 | 289 | }, |
| 288 | 290 | zh: { |
| 289 | 291 | ...loginMessages.zh, |
| ... | ... | @@ -419,6 +421,7 @@ const messages = { |
| 419 | 421 | ...carI18n.zh, |
| 420 | 422 | ...scmI18n.zh, |
| 421 | 423 | ...userI18n.zh, |
| 424 | + ...systemI18n.zh, | |
| 422 | 425 | } |
| 423 | 426 | } |
| 424 | 427 | ... | ... |
src/i18n/systemI18n.js
0 → 100644
| 1 | +import { messages as communitySettingManageMessages } from '../views/system/communitySettingManageLang' | |
| 2 | +import { messages as storeInfoManageMessages } from '../views/system/storeInfoManageLang' | |
| 3 | +export const messages = { | |
| 4 | + en: { | |
| 5 | + ...communitySettingManageMessages.en, | |
| 6 | + ...storeInfoManageMessages.en, | |
| 7 | + }, | |
| 8 | + zh: { | |
| 9 | + ...communitySettingManageMessages.zh, | |
| 10 | + ...storeInfoManageMessages.zh, | |
| 11 | + } | |
| 12 | +} | |
| 0 | 13 | \ No newline at end of file | ... | ... |
src/i18n/userI18n.js
| ... | ... | @@ -2,6 +2,12 @@ import { messages as staffCommunityMessages } from '../views/staff/staffCommunit |
| 2 | 2 | import { messages as staffAppAuthManageMessages } from '../views/staff/staffAppAuthManageLang' |
| 3 | 3 | import { messages as dataPrivilegeManageMessages } from '../views/org/dataPrivilegeManageLang' |
| 4 | 4 | import { messages as classesManageMessages } from '../views/org/classesManageLang' |
| 5 | +import { messages as scheduleClassesMessages } from '../views/org/scheduleClassesLang' | |
| 6 | +import { messages as addScheduleClassesMessages } from '../views/org/addScheduleClassesLang' | |
| 7 | +import { messages as editScheduleClassesMessages } from '../views/org/editScheduleClassesLang' | |
| 8 | +import { messages as scheduleClassesPageMessages } from '../views/org/scheduleClassesPageLang' | |
| 9 | +import { messages as workflowManageMessages } from '../views/system/workflowManageLang' | |
| 10 | +import { messages as workflowSettingManageMessages } from '../views/system/workflowSettingManageLang' | |
| 5 | 11 | |
| 6 | 12 | export const messages = { |
| 7 | 13 | en: { |
| ... | ... | @@ -9,11 +15,23 @@ export const messages = { |
| 9 | 15 | ...staffAppAuthManageMessages.en, |
| 10 | 16 | ...dataPrivilegeManageMessages.en, |
| 11 | 17 | ...classesManageMessages.en, |
| 18 | + ...scheduleClassesMessages.en, | |
| 19 | + ...addScheduleClassesMessages.en, | |
| 20 | + ...editScheduleClassesMessages.en, | |
| 21 | + ...scheduleClassesPageMessages.en, | |
| 22 | + ...workflowManageMessages.en, | |
| 23 | + ...workflowSettingManageMessages.en, | |
| 12 | 24 | }, |
| 13 | 25 | zh: { |
| 14 | 26 | ...staffCommunityMessages.zh, |
| 15 | 27 | ...staffAppAuthManageMessages.zh, |
| 16 | 28 | ...dataPrivilegeManageMessages.zh, |
| 17 | 29 | ...classesManageMessages.zh, |
| 30 | + ...scheduleClassesMessages.zh, | |
| 31 | + ...addScheduleClassesMessages.zh, | |
| 32 | + ...editScheduleClassesMessages.zh, | |
| 33 | + ...scheduleClassesPageMessages.zh, | |
| 34 | + ...workflowManageMessages.zh, | |
| 35 | + ...workflowSettingManageMessages.zh, | |
| 18 | 36 | } |
| 19 | 37 | } |
| 20 | 38 | \ No newline at end of file | ... | ... |
src/router/index.js
| ... | ... | @@ -13,6 +13,7 @@ import resourceRouter from './resourceRouter' |
| 13 | 13 | import carRouter from './carRouter' |
| 14 | 14 | import scmRouter from './scmRouter' |
| 15 | 15 | import userRouter from './userRouter' |
| 16 | +import systemRouter from './systemRouter' | |
| 16 | 17 | |
| 17 | 18 | Vue.use(VueRouter) |
| 18 | 19 | |
| ... | ... | @@ -634,6 +635,7 @@ const routes = [ |
| 634 | 635 | ...carRouter, |
| 635 | 636 | ...scmRouter, |
| 636 | 637 | ...userRouter, |
| 638 | + ...systemRouter, | |
| 637 | 639 | // 其他子路由可以在这里添加 |
| 638 | 640 | ] |
| 639 | 641 | }, | ... | ... |
src/router/systemRouter.js
0 → 100644
| 1 | +export default [ | |
| 2 | + { | |
| 3 | + path: '/pages/property/communitySettingManage', | |
| 4 | + name: '/pages/property/communitySettingManage', | |
| 5 | + component: () => import('@/views/system/communitySettingManageList.vue') | |
| 6 | + }, | |
| 7 | + { | |
| 8 | + path: '/pages/property/workflowManage', | |
| 9 | + name: '/pages/property/workflowManage', | |
| 10 | + component: () => import('@/views/system/workflowManageList.vue') | |
| 11 | + }, | |
| 12 | + { | |
| 13 | + path: '/pages/property/workflowSettingManage', | |
| 14 | + name: '/pages/property/workflowSettingManage', | |
| 15 | + component: () => import('@/views/system/workflowSettingManageList.vue') | |
| 16 | + }, | |
| 17 | + { | |
| 18 | + path:'/pages/common/storeInfoManage', | |
| 19 | + name:'/pages/common/storeInfoManage', | |
| 20 | + component: () => import('@/views/system/storeInfoManageList.vue') | |
| 21 | + }, | |
| 22 | +] | |
| 0 | 23 | \ No newline at end of file | ... | ... |
src/router/userRouter.js
| ... | ... | @@ -15,8 +15,28 @@ export default [ |
| 15 | 15 | component: () => import('@/views/org/dataPrivilegeManageList.vue') |
| 16 | 16 | }, |
| 17 | 17 | { |
| 18 | - path:'/pages/property/classesManage', | |
| 19 | - name:'/pages/property/classesManage', | |
| 18 | + path: '/pages/property/classesManage', | |
| 19 | + name: '/pages/property/classesManage', | |
| 20 | 20 | component: () => import('@/views/org/classesManageList.vue') |
| 21 | + }, | |
| 22 | + { | |
| 23 | + path: '/pages/property/scheduleClasses', | |
| 24 | + name: '/pages/property/scheduleClasses', | |
| 25 | + component: () => import('@/views/org/scheduleClassesList.vue') | |
| 26 | + }, | |
| 27 | + { | |
| 28 | + path: '/views/org/addScheduleClasses', | |
| 29 | + name: '/views/org/addScheduleClasses', | |
| 30 | + component: () => import('@/views/org/addScheduleClassesList.vue') | |
| 31 | + }, | |
| 32 | + { | |
| 33 | + path: '/views/org/editScheduleClasses', | |
| 34 | + name: '/views/org/editScheduleClasses', | |
| 35 | + component: () => import('@/views/org/editScheduleClassesList.vue') | |
| 36 | + }, | |
| 37 | + { | |
| 38 | + path:'/pages/property/scheduleClassesPage', | |
| 39 | + name:'/pages/property/scheduleClassesPage', | |
| 40 | + component: () => import('@/views/org/scheduleClassesPageList.vue') | |
| 21 | 41 | }, |
| 22 | 42 | ] |
| 23 | 43 | \ No newline at end of file | ... | ... |
src/views/org/addScheduleClassesLang.js
0 → 100644
| 1 | +export const messages = { | |
| 2 | + en: { | |
| 3 | + addScheduleClasses: { | |
| 4 | + title: 'Add Schedule', | |
| 5 | + name: 'Schedule Name', | |
| 6 | + namePlaceholder: 'Required, please enter schedule name', | |
| 7 | + scheduleType: 'Schedule Type', | |
| 8 | + scheduleTypePlaceholder: 'Required, please select schedule type', | |
| 9 | + daily: 'Daily Schedule', | |
| 10 | + weekly: 'Weekly Schedule', | |
| 11 | + monthly: 'Monthly Schedule' | |
| 12 | + }, | |
| 13 | + scheduleClassesDay: { | |
| 14 | + scheduleCycle: 'Schedule Cycle', | |
| 15 | + scheduleCyclePlaceholder: 'Required, please select schedule cycle', | |
| 16 | + day: 'Day', | |
| 17 | + scheduleInfo: 'Schedule Information', | |
| 18 | + rest: 'Rest' | |
| 19 | + }, | |
| 20 | + scheduleClassesWeek: { | |
| 21 | + scheduleCycle: 'Schedule Cycle', | |
| 22 | + scheduleCyclePlaceholder: 'Required, please select schedule cycle', | |
| 23 | + week: 'Week', | |
| 24 | + scheduleInfo: 'Schedule Information', | |
| 25 | + rest: 'Rest' | |
| 26 | + }, | |
| 27 | + scheduleClassesMonth: { | |
| 28 | + scheduleCycle: 'Schedule Cycle', | |
| 29 | + scheduleCyclePlaceholder: 'Required, please select schedule cycle', | |
| 30 | + month: 'Month', | |
| 31 | + scheduleInfo: 'Schedule Information', | |
| 32 | + rest: 'Rest' | |
| 33 | + }, | |
| 34 | + editScheduleClassesDay: { | |
| 35 | + title: 'Edit Schedule', | |
| 36 | + status: 'Status', | |
| 37 | + rest: 'Rest', | |
| 38 | + startTime: 'Start Time', | |
| 39 | + startTimePlaceholder: 'Required, please enter start time', | |
| 40 | + endTime: 'End Time', | |
| 41 | + endTimePlaceholder: 'Required, please enter end time' | |
| 42 | + } | |
| 43 | + }, | |
| 44 | + zh: { | |
| 45 | + addScheduleClasses: { | |
| 46 | + title: '添加排班', | |
| 47 | + name: '排班名称', | |
| 48 | + namePlaceholder: '必填,请填写计划名称', | |
| 49 | + scheduleType: '排班类型', | |
| 50 | + scheduleTypePlaceholder: '必填,请选择排班类型', | |
| 51 | + daily: '按日排班', | |
| 52 | + weekly: '按周排班', | |
| 53 | + monthly: '按月排班' | |
| 54 | + }, | |
| 55 | + scheduleClassesDay: { | |
| 56 | + scheduleCycle: '排班周期', | |
| 57 | + scheduleCyclePlaceholder: '必填,请选择排班周期', | |
| 58 | + day: '日', | |
| 59 | + scheduleInfo: '排班信息', | |
| 60 | + rest: '休息' | |
| 61 | + }, | |
| 62 | + scheduleClassesWeek: { | |
| 63 | + scheduleCycle: '排班周期', | |
| 64 | + scheduleCyclePlaceholder: '必填,请选择排班周期', | |
| 65 | + week: '周', | |
| 66 | + scheduleInfo: '排班信息', | |
| 67 | + rest: '休息' | |
| 68 | + }, | |
| 69 | + scheduleClassesMonth: { | |
| 70 | + scheduleCycle: '排班周期', | |
| 71 | + scheduleCyclePlaceholder: '必填,请选择排班周期', | |
| 72 | + month: '月', | |
| 73 | + scheduleInfo: '排班信息', | |
| 74 | + rest: '休息' | |
| 75 | + }, | |
| 76 | + editScheduleClassesDay: { | |
| 77 | + title: '修改', | |
| 78 | + status: '状态', | |
| 79 | + rest: '休息', | |
| 80 | + startTime: '上班时间', | |
| 81 | + startTimePlaceholder: '必填,请填写上班时间', | |
| 82 | + endTime: '下班时间', | |
| 83 | + endTimePlaceholder: '必填,请填写下班时间' | |
| 84 | + } | |
| 85 | + } | |
| 86 | +} | |
| 0 | 87 | \ No newline at end of file | ... | ... |
src/views/org/addScheduleClassesList.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="add-schedule-classes-container"> | |
| 3 | + <el-row> | |
| 4 | + <el-col :span="24"> | |
| 5 | + <el-card> | |
| 6 | + <div slot="header" class="clearfix"> | |
| 7 | + <span>{{ $t('addScheduleClasses.title') }}</span> | |
| 8 | + </div> | |
| 9 | + <div> | |
| 10 | + <el-form label-position="right" label-width="120px"> | |
| 11 | + <el-form-item :label="$t('addScheduleClasses.name')"> | |
| 12 | + <el-input v-model="addScheduleClassesInfo.name" | |
| 13 | + :placeholder="$t('addScheduleClasses.namePlaceholder')" /> | |
| 14 | + </el-form-item> | |
| 15 | + <el-form-item :label="$t('addScheduleClasses.scheduleType')"> | |
| 16 | + <el-select v-model="addScheduleClassesInfo.scheduleType" | |
| 17 | + :placeholder="$t('addScheduleClasses.scheduleTypePlaceholder')" @change="changeScheduleType" | |
| 18 | + style="width:100%"> | |
| 19 | + <el-option :label="$t('addScheduleClasses.daily')" value="1001" /> | |
| 20 | + <el-option :label="$t('addScheduleClasses.weekly')" value="2002" /> | |
| 21 | + <el-option :label="$t('addScheduleClasses.monthly')" value="3003" /> | |
| 22 | + </el-select> | |
| 23 | + </el-form-item> | |
| 24 | + | |
| 25 | + <div v-if="addScheduleClassesInfo.scheduleType === '1001'"> | |
| 26 | + <schedule-classes-day ref="scheduleDay" @editDay="editDay" /> | |
| 27 | + </div> | |
| 28 | + <div v-if="addScheduleClassesInfo.scheduleType === '2002'"> | |
| 29 | + <schedule-classes-week ref="scheduleWeek" @editDay="editDay" /> | |
| 30 | + </div> | |
| 31 | + <div v-if="addScheduleClassesInfo.scheduleType === '3003'"> | |
| 32 | + <schedule-classes-month ref="scheduleMonth" @editDay="editDay" /> | |
| 33 | + </div> | |
| 34 | + | |
| 35 | + <div class="action-buttons"> | |
| 36 | + <el-button type="primary" @click="saveScheduleClassesInfo"> | |
| 37 | + {{ $t('common.save') }} | |
| 38 | + </el-button> | |
| 39 | + <el-button @click="goBack"> | |
| 40 | + {{ $t('common.back') }} | |
| 41 | + </el-button> | |
| 42 | + </div> | |
| 43 | + </el-form> | |
| 44 | + </div> | |
| 45 | + </el-card> | |
| 46 | + </el-col> | |
| 47 | + </el-row> | |
| 48 | + | |
| 49 | + <edit-schedule-classes-day ref="editScheduleDay" @update="updateDay" /> | |
| 50 | + </div> | |
| 51 | +</template> | |
| 52 | + | |
| 53 | +<script> | |
| 54 | +import ScheduleClassesDay from '@/components/org/scheduleClassesDay' | |
| 55 | +import ScheduleClassesWeek from '@/components/org/scheduleClassesWeek' | |
| 56 | +import ScheduleClassesMonth from '@/components/org/scheduleClassesMonth' | |
| 57 | +import EditScheduleClassesDay from '@/components/org/editScheduleClassesDay' | |
| 58 | +import { saveScheduleClasses } from '@/api/org/addScheduleClassesApi' | |
| 59 | + | |
| 60 | +export default { | |
| 61 | + name: 'AddScheduleClassesList', | |
| 62 | + components: { | |
| 63 | + ScheduleClassesDay, | |
| 64 | + ScheduleClassesWeek, | |
| 65 | + ScheduleClassesMonth, | |
| 66 | + EditScheduleClassesDay | |
| 67 | + }, | |
| 68 | + data() { | |
| 69 | + return { | |
| 70 | + addScheduleClassesInfo: { | |
| 71 | + name: '', | |
| 72 | + scheduleType: '', | |
| 73 | + scheduleCycle: '1', | |
| 74 | + days: [] | |
| 75 | + } | |
| 76 | + } | |
| 77 | + }, | |
| 78 | + methods: { | |
| 79 | + changeScheduleType() { | |
| 80 | + this.addScheduleClassesInfo.days = [] | |
| 81 | + this.addScheduleClassesInfo.scheduleCycle = 1 | |
| 82 | + | |
| 83 | + if (this.addScheduleClassesInfo.scheduleType === '1001') { | |
| 84 | + this.$refs.scheduleDay.initData(this.addScheduleClassesInfo.scheduleCycle) | |
| 85 | + } else if (this.addScheduleClassesInfo.scheduleType === '2002') { | |
| 86 | + this.$refs.scheduleWeek.initData(this.addScheduleClassesInfo.scheduleCycle) | |
| 87 | + } else if (this.addScheduleClassesInfo.scheduleType === '3003') { | |
| 88 | + this.$refs.scheduleMonth.initData(this.addScheduleClassesInfo.scheduleCycle) | |
| 89 | + } | |
| 90 | + }, | |
| 91 | + async saveScheduleClassesInfo() { | |
| 92 | + try { | |
| 93 | + // 根据不同类型获取数据 | |
| 94 | + if (this.addScheduleClassesInfo.scheduleType === '1001') { | |
| 95 | + this.addScheduleClassesInfo.days = this.$refs.scheduleDay.getDaysData() | |
| 96 | + } else if (this.addScheduleClassesInfo.scheduleType === '2002') { | |
| 97 | + this.addScheduleClassesInfo.days = this.$refs.scheduleWeek.getDaysData() | |
| 98 | + } else if (this.addScheduleClassesInfo.scheduleType === '3003') { | |
| 99 | + this.addScheduleClassesInfo.days = this.$refs.scheduleMonth.getDaysData() | |
| 100 | + } | |
| 101 | + | |
| 102 | + const res = await saveScheduleClasses(this.addScheduleClassesInfo) | |
| 103 | + if (res.code === 0) { | |
| 104 | + this.$message.success(this.$t('common.saveSuccess')) | |
| 105 | + this.goBack() | |
| 106 | + } else { | |
| 107 | + this.$message.error(res.msg) | |
| 108 | + } | |
| 109 | + } catch (error) { | |
| 110 | + this.$message.error(this.$t('common.saveFailed')) | |
| 111 | + } | |
| 112 | + }, | |
| 113 | + goBack() { | |
| 114 | + this.$router.go(-1) | |
| 115 | + }, | |
| 116 | + editDay(item) { | |
| 117 | + this.$refs.editScheduleDay.open(item) | |
| 118 | + }, | |
| 119 | + updateDay(updatedItem) { | |
| 120 | + // 由于 editScheduleClassesDay 组件现在直接修改传入的对象 | |
| 121 | + // 这里不需要额外的处理,但保留方法以保持代码完整性 | |
| 122 | + console.log('Day updated:', updatedItem) | |
| 123 | + } | |
| 124 | + } | |
| 125 | +} | |
| 126 | +</script> | |
| 127 | + | |
| 128 | +<style lang="scss" scoped> | |
| 129 | +.add-schedule-classes-container { | |
| 130 | + padding: 20px; | |
| 131 | + | |
| 132 | + .action-buttons { | |
| 133 | + margin-top: 20px; | |
| 134 | + text-align: right; | |
| 135 | + | |
| 136 | + .el-button+.el-button { | |
| 137 | + margin-left: 10px; | |
| 138 | + } | |
| 139 | + } | |
| 140 | +} | |
| 141 | +</style> | |
| 0 | 142 | \ No newline at end of file | ... | ... |
src/views/org/editScheduleClassesLang.js
0 → 100644
| 1 | +export const messages = { | |
| 2 | + en: { | |
| 3 | + editScheduleClasses: { | |
| 4 | + title: 'Edit Schedule', | |
| 5 | + name: 'Schedule Name', | |
| 6 | + namePlaceholder: 'Required, please enter schedule name', | |
| 7 | + scheduleType: 'Schedule Type', | |
| 8 | + scheduleTypePlaceholder: 'Required, please select schedule type', | |
| 9 | + daySchedule: 'Daily Schedule', | |
| 10 | + weekSchedule: 'Weekly Schedule', | |
| 11 | + monthSchedule: 'Monthly Schedule', | |
| 12 | + rest: 'Rest' | |
| 13 | + }, | |
| 14 | + scheduleClassesDay: { | |
| 15 | + scheduleCycle: 'Schedule Cycle', | |
| 16 | + scheduleCyclePlaceholder: 'Required, please select schedule cycle', | |
| 17 | + day: 'Day', | |
| 18 | + scheduleInfo: 'Schedule Information', | |
| 19 | + rest: 'Rest' | |
| 20 | + }, | |
| 21 | + scheduleClassesWeek: { | |
| 22 | + scheduleCycle: 'Schedule Cycle', | |
| 23 | + scheduleCyclePlaceholder: 'Required, please select schedule cycle', | |
| 24 | + week: 'Week', | |
| 25 | + scheduleInfo: 'Schedule Information', | |
| 26 | + rest: 'Rest' | |
| 27 | + }, | |
| 28 | + scheduleClassesMonth: { | |
| 29 | + scheduleCycle: 'Schedule Cycle', | |
| 30 | + scheduleCyclePlaceholder: 'Required, please select schedule cycle', | |
| 31 | + month: 'Month', | |
| 32 | + scheduleInfo: 'Schedule Information', | |
| 33 | + rest: 'Rest' | |
| 34 | + }, | |
| 35 | + editScheduleClassesDay: { | |
| 36 | + editTitle: 'Edit Schedule Day', | |
| 37 | + status: 'Status', | |
| 38 | + startTime: 'Start Time', | |
| 39 | + startTimePlaceholder: 'Required, please enter start time', | |
| 40 | + endTime: 'End Time', | |
| 41 | + endTimePlaceholder: 'Required, please enter end time', | |
| 42 | + rest: 'Rest' | |
| 43 | + } | |
| 44 | + }, | |
| 45 | + zh: { | |
| 46 | + editScheduleClasses: { | |
| 47 | + title: '修改排班', | |
| 48 | + name: '排班名称', | |
| 49 | + namePlaceholder: '必填,请填写计划名称', | |
| 50 | + scheduleType: '排班类型', | |
| 51 | + scheduleTypePlaceholder: '必填,请选择排班类型', | |
| 52 | + daySchedule: '按日排班', | |
| 53 | + weekSchedule: '按周排班', | |
| 54 | + monthSchedule: '按月排班', | |
| 55 | + rest: '休息' | |
| 56 | + }, | |
| 57 | + scheduleClassesDay: { | |
| 58 | + scheduleCycle: '排班周期', | |
| 59 | + scheduleCyclePlaceholder: '必填,请选择排班周期', | |
| 60 | + day: '日', | |
| 61 | + scheduleInfo: '排班信息', | |
| 62 | + rest: '休息' | |
| 63 | + }, | |
| 64 | + scheduleClassesWeek: { | |
| 65 | + scheduleCycle: '排班周期', | |
| 66 | + scheduleCyclePlaceholder: '必填,请选择排班周期', | |
| 67 | + week: '周', | |
| 68 | + scheduleInfo: '排班信息', | |
| 69 | + rest: '休息' | |
| 70 | + }, | |
| 71 | + scheduleClassesMonth: { | |
| 72 | + scheduleCycle: '排班周期', | |
| 73 | + scheduleCyclePlaceholder: '必填,请选择排班周期', | |
| 74 | + month: '月', | |
| 75 | + scheduleInfo: '排班信息', | |
| 76 | + rest: '休息' | |
| 77 | + }, | |
| 78 | + editScheduleClassesDay: { | |
| 79 | + editTitle: '修改', | |
| 80 | + status: '状态', | |
| 81 | + startTime: '上班时间', | |
| 82 | + startTimePlaceholder: '必填,请填写上班时间', | |
| 83 | + endTime: '下班时间', | |
| 84 | + endTimePlaceholder: '必填,请填写下班时间', | |
| 85 | + rest: '休息' | |
| 86 | + } | |
| 87 | + } | |
| 88 | +} | |
| 0 | 89 | \ No newline at end of file | ... | ... |
src/views/org/editScheduleClassesList.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="edit-schedule-classes-container"> | |
| 3 | + <el-card class="box-card"> | |
| 4 | + <div slot="header" class="clearfix"> | |
| 5 | + <h5>{{ $t('editScheduleClasses.title') }}</h5> | |
| 6 | + </div> | |
| 7 | + <el-row :gutter="20"> | |
| 8 | + <el-col :span="24"> | |
| 9 | + <div class="form-content"> | |
| 10 | + <el-form ref="form" :model="editScheduleClassesInfo" label-width="120px"> | |
| 11 | + <el-form-item :label="$t('editScheduleClasses.name')"> | |
| 12 | + <el-input v-model="editScheduleClassesInfo.name" | |
| 13 | + :placeholder="$t('editScheduleClasses.namePlaceholder')" clearable /> | |
| 14 | + </el-form-item> | |
| 15 | + <el-form-item :label="$t('editScheduleClasses.scheduleType')"> | |
| 16 | + <el-select v-model="editScheduleClassesInfo.scheduleType" | |
| 17 | + :placeholder="$t('editScheduleClasses.scheduleTypePlaceholder')" style="width:100%" | |
| 18 | + @change="changeScheduleType(1)"> | |
| 19 | + <el-option disabled :value="''" :label="$t('editScheduleClasses.scheduleTypePlaceholder')" /> | |
| 20 | + <el-option value="1001" :label="$t('editScheduleClasses.daySchedule')" /> | |
| 21 | + <el-option value="2002" :label="$t('editScheduleClasses.weekSchedule')" /> | |
| 22 | + <el-option value="3003" :label="$t('editScheduleClasses.monthSchedule')" /> | |
| 23 | + </el-select> | |
| 24 | + </el-form-item> | |
| 25 | + | |
| 26 | + <div v-if="editScheduleClassesInfo.scheduleType === '1001'"> | |
| 27 | + <schedule-classes-day ref="dayComponent" :schedule-cycle="editScheduleClassesInfo.scheduleCycle" | |
| 28 | + :days="editScheduleClassesInfo.days" @editDay="editDay" /> | |
| 29 | + </div> | |
| 30 | + <div v-if="editScheduleClassesInfo.scheduleType === '2002'"> | |
| 31 | + <schedule-classes-week ref="weekComponent" :schedule-cycle="editScheduleClassesInfo.scheduleCycle" | |
| 32 | + :days="editScheduleClassesInfo.days" @editDay="editDay" /> | |
| 33 | + </div> | |
| 34 | + <div v-if="editScheduleClassesInfo.scheduleType === '3003'"> | |
| 35 | + <schedule-classes-month ref="monthComponent" :schedule-cycle="editScheduleClassesInfo.scheduleCycle" | |
| 36 | + :days="editScheduleClassesInfo.days" @editDay="editDay" /> | |
| 37 | + </div> | |
| 38 | + | |
| 39 | + <el-form-item> | |
| 40 | + <el-button type="primary" @click="editScheduleClasses"> | |
| 41 | + <i class="el-icon-check" /> {{ $t('common.save') }} | |
| 42 | + </el-button> | |
| 43 | + <el-button type="warning" style="margin-right:20px;" @click="goBack"> | |
| 44 | + <i class="el-icon-close" /> {{ $t('common.back') }} | |
| 45 | + </el-button> | |
| 46 | + </el-form-item> | |
| 47 | + </el-form> | |
| 48 | + </div> | |
| 49 | + </el-col> | |
| 50 | + </el-row> | |
| 51 | + </el-card> | |
| 52 | + | |
| 53 | + <edit-schedule-classes-day ref="editDayDialog" /> | |
| 54 | + </div> | |
| 55 | +</template> | |
| 56 | + | |
| 57 | +<script> | |
| 58 | +import ScheduleClassesDay from '@/components/org/scheduleClassesDay' | |
| 59 | +import ScheduleClassesWeek from '@/components/org/scheduleClassesWeek' | |
| 60 | +import ScheduleClassesMonth from '@/components/org/scheduleClassesMonth' | |
| 61 | +import EditScheduleClassesDay from '@/components/org/editScheduleClassesDay' | |
| 62 | +import { updateScheduleClasses, listScheduleClasses, listScheduleClassesDay } from '@/api/org/editScheduleClassesApi' | |
| 63 | + | |
| 64 | +export default { | |
| 65 | + name: 'EditScheduleClassesList', | |
| 66 | + components: { | |
| 67 | + ScheduleClassesDay, | |
| 68 | + ScheduleClassesWeek, | |
| 69 | + ScheduleClassesMonth, | |
| 70 | + EditScheduleClassesDay | |
| 71 | + }, | |
| 72 | + data() { | |
| 73 | + return { | |
| 74 | + editScheduleClassesInfo: { | |
| 75 | + scheduleId: '', | |
| 76 | + name: '', | |
| 77 | + scheduleType: '', | |
| 78 | + scheduleCycle: '1', | |
| 79 | + days: [] | |
| 80 | + } | |
| 81 | + } | |
| 82 | + }, | |
| 83 | + created() { | |
| 84 | + this.editScheduleClassesInfo.scheduleId = this.$route.query.scheduleId | |
| 85 | + this.listScheduleClassess() | |
| 86 | + this.listScheduleClassesDays() | |
| 87 | + }, | |
| 88 | + methods: { | |
| 89 | + changeScheduleType(customChange) { | |
| 90 | + if (customChange) { | |
| 91 | + this.editScheduleClassesInfo.days = [] | |
| 92 | + this.editScheduleClassesInfo.scheduleCycle = 1 | |
| 93 | + } | |
| 94 | + | |
| 95 | + if (this.editScheduleClassesInfo.scheduleType === '1001') { | |
| 96 | + setTimeout(() => { | |
| 97 | + this.$refs.dayComponent.notify({ | |
| 98 | + scheduleCycle: this.editScheduleClassesInfo.scheduleCycle, | |
| 99 | + days: this.editScheduleClassesInfo.days | |
| 100 | + }) | |
| 101 | + }, 500) | |
| 102 | + } | |
| 103 | + if (this.editScheduleClassesInfo.scheduleType === '2002') { | |
| 104 | + setTimeout(() => { | |
| 105 | + this.$refs.weekComponent.notify({ | |
| 106 | + scheduleCycle: this.editScheduleClassesInfo.scheduleCycle, | |
| 107 | + days: this.editScheduleClassesInfo.days | |
| 108 | + }) | |
| 109 | + }, 100) | |
| 110 | + } | |
| 111 | + if (this.editScheduleClassesInfo.scheduleType === '3003') { | |
| 112 | + setTimeout(() => { | |
| 113 | + this.$refs.monthComponent.notify({ | |
| 114 | + scheduleCycle: this.editScheduleClassesInfo.scheduleCycle, | |
| 115 | + days: this.editScheduleClassesInfo.days | |
| 116 | + }) | |
| 117 | + }, 100) | |
| 118 | + } | |
| 119 | + }, | |
| 120 | + async editScheduleClasses() { | |
| 121 | + try { | |
| 122 | + await updateScheduleClasses(this.editScheduleClassesInfo) | |
| 123 | + this.$message.success(this.$t('common.updateSuccess')) | |
| 124 | + this.goBack() | |
| 125 | + } catch (error) { | |
| 126 | + this.$message.error(error.message || this.$t('common.updateFailed')) | |
| 127 | + } | |
| 128 | + }, | |
| 129 | + async listScheduleClassess() { | |
| 130 | + try { | |
| 131 | + const { data } = await listScheduleClasses({ | |
| 132 | + page: 1, | |
| 133 | + row: 1, | |
| 134 | + scheduleId: this.editScheduleClassesInfo.scheduleId | |
| 135 | + }) | |
| 136 | + Object.assign(this.editScheduleClassesInfo, data[0]) | |
| 137 | + this.changeScheduleType() | |
| 138 | + } catch (error) { | |
| 139 | + console.error('请求失败:', error) | |
| 140 | + } | |
| 141 | + }, | |
| 142 | + async listScheduleClassesDays() { | |
| 143 | + try { | |
| 144 | + const { data } = await listScheduleClassesDay({ | |
| 145 | + page: 1, | |
| 146 | + row: 100, | |
| 147 | + scheduleId: this.editScheduleClassesInfo.scheduleId | |
| 148 | + }) | |
| 149 | + data.forEach(item => { | |
| 150 | + if (item.workday === '2002') { | |
| 151 | + item.workdayName = this.$t('editScheduleClasses.rest') | |
| 152 | + } | |
| 153 | + }) | |
| 154 | + this.editScheduleClassesInfo.days = data | |
| 155 | + this.changeScheduleType() | |
| 156 | + } catch (error) { | |
| 157 | + console.error('请求失败:', error) | |
| 158 | + } | |
| 159 | + }, | |
| 160 | + goBack() { | |
| 161 | + this.$router.go(-1) | |
| 162 | + }, | |
| 163 | + editDay(item) { | |
| 164 | + this.$refs.editDayDialog.open(item) | |
| 165 | + } | |
| 166 | + } | |
| 167 | +} | |
| 168 | +</script> | |
| 169 | + | |
| 170 | +<style lang="scss" scoped> | |
| 171 | +.edit-schedule-classes-container { | |
| 172 | + padding: 20px; | |
| 173 | + | |
| 174 | + .box-card { | |
| 175 | + margin-bottom: 20px; | |
| 176 | + } | |
| 177 | + | |
| 178 | + .form-content { | |
| 179 | + padding: 20px; | |
| 180 | + } | |
| 181 | + | |
| 182 | + .el-form-item { | |
| 183 | + margin-bottom: 22px; | |
| 184 | + } | |
| 185 | +} | |
| 186 | +</style> | |
| 0 | 187 | \ No newline at end of file | ... | ... |
src/views/org/scheduleClassesLang.js
0 → 100644
| 1 | +export const messages = { | |
| 2 | + en: { | |
| 3 | + scheduleClasses: { | |
| 4 | + search: { | |
| 5 | + title: 'Search Conditions', | |
| 6 | + nameLike: 'Please enter schedule name', | |
| 7 | + state: 'Please select status', | |
| 8 | + allState: 'All Status' | |
| 9 | + }, | |
| 10 | + list: { | |
| 11 | + title: 'Schedule Settings' | |
| 12 | + }, | |
| 13 | + table: { | |
| 14 | + name: 'Schedule Name', | |
| 15 | + scheduleType: 'Schedule Type', | |
| 16 | + scheduleCycle: 'Schedule Cycle', | |
| 17 | + computeTime: 'Effective Time', | |
| 18 | + staff: 'Staff', | |
| 19 | + staffLink: 'Staff', | |
| 20 | + state: 'Status', | |
| 21 | + createTime: 'Create Time' | |
| 22 | + }, | |
| 23 | + delete: { | |
| 24 | + title: 'Confirm Operation', | |
| 25 | + confirm: 'Are you sure to delete this schedule?', | |
| 26 | + success: 'Delete successfully', | |
| 27 | + error: 'Delete failed' | |
| 28 | + }, | |
| 29 | + state: { | |
| 30 | + title: 'Confirm Operation', | |
| 31 | + confirm: 'Are you sure to', | |
| 32 | + schedule: 'this schedule?', | |
| 33 | + success: 'Operation successfully', | |
| 34 | + error: 'Operation failed' | |
| 35 | + }, | |
| 36 | + fetchError: 'Failed to fetch schedule data' | |
| 37 | + } | |
| 38 | + }, | |
| 39 | + zh: { | |
| 40 | + scheduleClasses: { | |
| 41 | + search: { | |
| 42 | + title: '查询条件', | |
| 43 | + nameLike: '请输入排班名称', | |
| 44 | + state: '请选择状态', | |
| 45 | + allState: '全部状态' | |
| 46 | + }, | |
| 47 | + list: { | |
| 48 | + title: '排班设置' | |
| 49 | + }, | |
| 50 | + table: { | |
| 51 | + name: '班次名称', | |
| 52 | + scheduleType: '排班类型', | |
| 53 | + scheduleCycle: '排班周期', | |
| 54 | + computeTime: '生效时间', | |
| 55 | + staff: '人员', | |
| 56 | + staffLink: '人员', | |
| 57 | + state: '状态', | |
| 58 | + createTime: '创建时间' | |
| 59 | + }, | |
| 60 | + delete: { | |
| 61 | + title: '确认操作', | |
| 62 | + confirm: '确定删除排班吗?', | |
| 63 | + success: '删除成功', | |
| 64 | + error: '删除失败' | |
| 65 | + }, | |
| 66 | + state: { | |
| 67 | + title: '确认操作', | |
| 68 | + confirm: '确定', | |
| 69 | + schedule: '该排班吗?', | |
| 70 | + success: '操作成功', | |
| 71 | + error: '操作失败' | |
| 72 | + }, | |
| 73 | + fetchError: '获取排班数据失败' | |
| 74 | + } | |
| 75 | + } | |
| 76 | +} | |
| 0 | 77 | \ No newline at end of file | ... | ... |
src/views/org/scheduleClassesList.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="schedule-classes-container animated fadeInRight"> | |
| 3 | + <!-- 查询条件 --> | |
| 4 | + <el-card class="search-wrapper"> | |
| 5 | + <div slot="header" class="text-left"> | |
| 6 | + <span>{{ $t('scheduleClasses.search.title') }}</span> | |
| 7 | + </div> | |
| 8 | + <el-row :gutter="20"> | |
| 9 | + <el-col :span="6"> | |
| 10 | + <el-input v-model="searchForm.nameLike" :placeholder="$t('scheduleClasses.search.nameLike')" clearable | |
| 11 | + @keyup.enter.native="handleSearch" /> | |
| 12 | + </el-col> | |
| 13 | + <el-col :span="6"> | |
| 14 | + <el-select v-model="searchForm.state" :placeholder="$t('scheduleClasses.search.state')" style="width:100%"> | |
| 15 | + <el-option :label="$t('scheduleClasses.search.allState')" value="" /> | |
| 16 | + <el-option v-for="item in states" :key="item.statusCd" :label="item.name" :value="item.statusCd" /> | |
| 17 | + </el-select> | |
| 18 | + </el-col> | |
| 19 | + <el-col :span="4"> | |
| 20 | + <el-button type="primary" @click="handleSearch"> | |
| 21 | + <i class="el-icon-search"></i> | |
| 22 | + {{ $t('common.search') }} | |
| 23 | + </el-button> | |
| 24 | + </el-col> | |
| 25 | + </el-row> | |
| 26 | + </el-card> | |
| 27 | + | |
| 28 | + <!-- 排班设置 --> | |
| 29 | + <el-card class="list-wrapper"> | |
| 30 | + <div slot="header" class="flex justify-between "> | |
| 31 | + <span>{{ $t('scheduleClasses.list.title') }}</span> | |
| 32 | + <el-button type="primary" style="float: right;" @click="handleAdd"> | |
| 33 | + <i class="el-icon-plus"></i> | |
| 34 | + {{ $t('common.add') }} | |
| 35 | + </el-button> | |
| 36 | + </div> | |
| 37 | + | |
| 38 | + <el-table v-loading="loading" :data="tableData" border style="width: 100%"> | |
| 39 | + <el-table-column prop="name" :label="$t('scheduleClasses.table.name')" align="center" /> | |
| 40 | + <el-table-column prop="scheduleTypeName" :label="$t('scheduleClasses.table.scheduleType')" align="center" /> | |
| 41 | + <el-table-column prop="scheduleCycle" :label="$t('scheduleClasses.table.scheduleCycle')" align="center" /> | |
| 42 | + <el-table-column prop="computeTime" :label="$t('scheduleClasses.table.computeTime')" align="center" /> | |
| 43 | + <el-table-column :label="$t('scheduleClasses.table.staff')" align="center"> | |
| 44 | + <template slot-scope="scope"> | |
| 45 | + {{ scope.row.staffCount }} ( | |
| 46 | + <el-link type="primary" @click="handleStaff(scope.row)"> | |
| 47 | + {{ $t('scheduleClasses.table.staffLink') }} | |
| 48 | + </el-link> | |
| 49 | + ) | |
| 50 | + </template> | |
| 51 | + </el-table-column> | |
| 52 | + <el-table-column prop="stateName" :label="$t('scheduleClasses.table.state')" align="center" /> | |
| 53 | + <el-table-column prop="createTime" :label="$t('scheduleClasses.table.createTime')" align="center" /> | |
| 54 | + <el-table-column :label="$t('common.operation')" align="center" width="300"> | |
| 55 | + <template slot-scope="scope"> | |
| 56 | + <el-button size="mini" type="primary" @click="handleEdit(scope.row)"> | |
| 57 | + {{ $t('common.edit') }} | |
| 58 | + </el-button> | |
| 59 | + <el-button size="mini" type="danger" @click="handleDelete(scope.row)"> | |
| 60 | + {{ $t('common.delete') }} | |
| 61 | + </el-button> | |
| 62 | + <el-button v-if="scope.row.state === '1001'" size="mini" type="warning" @click="handleDisable(scope.row)"> | |
| 63 | + {{ $t('common.disabled') }} | |
| 64 | + </el-button> | |
| 65 | + <el-button v-else size="mini" type="success" @click="handleEnable(scope.row)"> | |
| 66 | + {{ $t('common.enabled') }} | |
| 67 | + </el-button> | |
| 68 | + </template> | |
| 69 | + </el-table-column> | |
| 70 | + </el-table> | |
| 71 | + | |
| 72 | + <el-pagination :current-page.sync="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size" | |
| 73 | + :total="page.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange" | |
| 74 | + @current-change="handleCurrentChange" /> | |
| 75 | + </el-card> | |
| 76 | + | |
| 77 | + <!-- 删除对话框 --> | |
| 78 | + <delete-schedule-classes ref="deleteDialog" @success="handleSuccess" /> | |
| 79 | + | |
| 80 | + <!-- 状态对话框 --> | |
| 81 | + <schedule-classes-state ref="stateDialog" @success="handleSuccess" /> | |
| 82 | + </div> | |
| 83 | +</template> | |
| 84 | + | |
| 85 | +<script> | |
| 86 | +import { listScheduleClasses } from '@/api/org/scheduleClassesApi' | |
| 87 | +import {getDict} from '@/api/community/communityApi' | |
| 88 | +import DeleteScheduleClasses from '@/components/org/deleteScheduleClasses' | |
| 89 | +import ScheduleClassesState from '@/components/org/scheduleClassesState' | |
| 90 | + | |
| 91 | +export default { | |
| 92 | + name: 'ScheduleClassesList', | |
| 93 | + components: { | |
| 94 | + DeleteScheduleClasses, | |
| 95 | + ScheduleClassesState | |
| 96 | + }, | |
| 97 | + data() { | |
| 98 | + return { | |
| 99 | + loading: false, | |
| 100 | + searchForm: { | |
| 101 | + nameLike: '', | |
| 102 | + state: '' | |
| 103 | + }, | |
| 104 | + states: [], | |
| 105 | + tableData: [], | |
| 106 | + page: { | |
| 107 | + current: 1, | |
| 108 | + size: 10, | |
| 109 | + total: 0 | |
| 110 | + } | |
| 111 | + } | |
| 112 | + }, | |
| 113 | + created() { | |
| 114 | + this.getList() | |
| 115 | + this.getDictData() | |
| 116 | + }, | |
| 117 | + methods: { | |
| 118 | + async getList() { | |
| 119 | + try { | |
| 120 | + this.loading = true | |
| 121 | + const params = { | |
| 122 | + page: this.page.current, | |
| 123 | + row: this.page.size, | |
| 124 | + ...this.searchForm | |
| 125 | + } | |
| 126 | + const { data, total } = await listScheduleClasses(params) | |
| 127 | + this.tableData = data | |
| 128 | + this.page.total = total | |
| 129 | + } catch (error) { | |
| 130 | + this.$message.error(this.$t('scheduleClasses.fetchError')) | |
| 131 | + } finally { | |
| 132 | + this.loading = false | |
| 133 | + } | |
| 134 | + }, | |
| 135 | + async getDictData() { | |
| 136 | + try { | |
| 137 | + const data = await getDict('schedule_classes', 'state') | |
| 138 | + this.states = data | |
| 139 | + } catch (error) { | |
| 140 | + console.error('获取字典数据失败:', error) | |
| 141 | + } | |
| 142 | + }, | |
| 143 | + handleSearch() { | |
| 144 | + this.page.current = 1 | |
| 145 | + this.getList() | |
| 146 | + }, | |
| 147 | + handleAdd() { | |
| 148 | + this.$router.push('/views/org/addScheduleClasses') | |
| 149 | + }, | |
| 150 | + handleEdit(row) { | |
| 151 | + this.$router.push(`/views/org/editScheduleClasses?scheduleId=${row.scheduleId}`) | |
| 152 | + }, | |
| 153 | + handleDelete(row) { | |
| 154 | + this.$refs.deleteDialog.open(row) | |
| 155 | + }, | |
| 156 | + handleEnable(row) { | |
| 157 | + this.$refs.stateDialog.open({ | |
| 158 | + scheduleId: row.scheduleId, | |
| 159 | + stateName: this.$t('common.enable'), | |
| 160 | + state: '1001' | |
| 161 | + }) | |
| 162 | + }, | |
| 163 | + handleDisable(row) { | |
| 164 | + this.$refs.stateDialog.open({ | |
| 165 | + scheduleId: row.scheduleId, | |
| 166 | + stateName: this.$t('common.disable'), | |
| 167 | + state: '2002' | |
| 168 | + }) | |
| 169 | + }, | |
| 170 | + handleStaff(row) { | |
| 171 | + this.$router.push(`/org/scheduleClassesStaffManage?scheduleId=${row.scheduleId}`) | |
| 172 | + }, | |
| 173 | + handleSuccess() { | |
| 174 | + this.getList() | |
| 175 | + }, | |
| 176 | + handleSizeChange(val) { | |
| 177 | + this.page.size = val | |
| 178 | + this.getList() | |
| 179 | + }, | |
| 180 | + handleCurrentChange(val) { | |
| 181 | + this.page.current = val | |
| 182 | + this.getList() | |
| 183 | + } | |
| 184 | + } | |
| 185 | +} | |
| 186 | +</script> | |
| 187 | + | |
| 188 | +<style lang="scss" scoped> | |
| 189 | +.schedule-classes-container { | |
| 190 | + padding: 20px; | |
| 191 | + | |
| 192 | + .search-wrapper { | |
| 193 | + margin-bottom: 20px; | |
| 194 | + } | |
| 195 | + | |
| 196 | + .list-wrapper { | |
| 197 | + margin-bottom: 20px; | |
| 198 | + } | |
| 199 | + | |
| 200 | + .el-pagination { | |
| 201 | + margin-top: 20px; | |
| 202 | + text-align: right; | |
| 203 | + } | |
| 204 | +} | |
| 205 | +</style> | |
| 0 | 206 | \ No newline at end of file | ... | ... |
src/views/org/scheduleClassesPageLang.js
0 → 100644
| 1 | +export const messages = { | |
| 2 | + en: { | |
| 3 | + scheduleClassesPage: { | |
| 4 | + searchConditions: 'Search Conditions', | |
| 5 | + scheduleTable: 'Schedule Table', | |
| 6 | + staffNamePlaceholder: 'Please enter staff name', | |
| 7 | + schedulePlaceholder: 'Please select schedule', | |
| 8 | + selectSchedule: 'Select Schedule', | |
| 9 | + datePlaceholder: 'Please enter date YYYY-MM', | |
| 10 | + orgPlaceholder: 'Required, please select organization', | |
| 11 | + staffName: 'Staff Name', | |
| 12 | + day: 'Day', | |
| 13 | + rest: 'Rest', | |
| 14 | + selectOrg: 'Select Organization' | |
| 15 | + } | |
| 16 | + }, | |
| 17 | + zh: { | |
| 18 | + scheduleClassesPage: { | |
| 19 | + searchConditions: '查询条件', | |
| 20 | + scheduleTable: '排班表', | |
| 21 | + staffNamePlaceholder: '请输入员工名称', | |
| 22 | + schedulePlaceholder: '请选择班次', | |
| 23 | + selectSchedule: '请选择班次', | |
| 24 | + datePlaceholder: '请输入日期 YYYY-MM', | |
| 25 | + orgPlaceholder: '必填,请选择关联组织', | |
| 26 | + staffName: '员工名称', | |
| 27 | + day: '日', | |
| 28 | + rest: '休息', | |
| 29 | + selectOrg: '选择组织' | |
| 30 | + } | |
| 31 | + } | |
| 32 | +} | |
| 0 | 33 | \ No newline at end of file | ... | ... |
src/views/org/scheduleClassesPageList.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="schedule-classes-container animated fadeInRight"> | |
| 3 | + <!-- 查询条件 --> | |
| 4 | + <el-card class="box-card"> | |
| 5 | + <div slot="header" class="flex justify-between"> | |
| 6 | + <span>{{ $t('scheduleClassesPage.searchConditions') }}</span> | |
| 7 | + <el-button style="float: right; padding: 3px 0" type="text" @click="_moreCondition()"> | |
| 8 | + {{ scheduleClassesPageInfo.moreCondition ? $t('common.hide') : $t('common.more') }} | |
| 9 | + </el-button> | |
| 10 | + </div> | |
| 11 | + <el-row :gutter="20"> | |
| 12 | + <el-col :span="6"> | |
| 13 | + <el-input v-model="scheduleClassesPageInfo.conditions.staffNameLike" | |
| 14 | + :placeholder="$t('scheduleClassesPage.staffNamePlaceholder')" clearable /> | |
| 15 | + </el-col> | |
| 16 | + <el-col :span="8"> | |
| 17 | + <el-select v-model="scheduleClassesPageInfo.conditions.scheduleId" style="width:100%" | |
| 18 | + :placeholder="$t('scheduleClassesPage.schedulePlaceholder')"> | |
| 19 | + <el-option :label="$t('scheduleClassesPage.selectSchedule')" value="" /> | |
| 20 | + <el-option v-for="(item, index) in scheduleClassesPageInfo.scheduleClassess" :key="index" :label="item.name" | |
| 21 | + :value="item.scheduleId" /> | |
| 22 | + </el-select> | |
| 23 | + </el-col> | |
| 24 | + <el-col :span="6"> | |
| 25 | + <el-date-picker v-model="scheduleClassesPageInfo.conditions.curDate" type="month" | |
| 26 | + :placeholder="$t('scheduleClassesPage.datePlaceholder')" format="yyyy-MM" value-format="yyyy-MM" | |
| 27 | + style="width:100%" @change="handleDateChange" /> | |
| 28 | + </el-col> | |
| 29 | + <el-col :span="4"> | |
| 30 | + <el-button type="primary" @click="_queryScheduleClassesMethod()"> | |
| 31 | + {{ $t('common.search') }} | |
| 32 | + </el-button> | |
| 33 | + <el-button type="primary" @click="_exportScheduleClasses()"> | |
| 34 | + <i class="el-icon-upload" /> | |
| 35 | + {{ $t('common.export') }} | |
| 36 | + </el-button> | |
| 37 | + </el-col> | |
| 38 | + </el-row> | |
| 39 | + | |
| 40 | + <el-row v-show="scheduleClassesPageInfo.moreCondition" :gutter="20" style="margin-top:15px"> | |
| 41 | + <el-col :span="6"> | |
| 42 | + <el-input v-model="scheduleClassesPageInfo.conditions.orgName" readonly | |
| 43 | + :placeholder="$t('scheduleClassesPage.orgPlaceholder')" @focus="_staffChangeOrg()" /> | |
| 44 | + </el-col> | |
| 45 | + </el-row> | |
| 46 | + </el-card> | |
| 47 | + | |
| 48 | + <!-- 排班表 --> | |
| 49 | + <el-card class="box-card" style="margin-top:20px"> | |
| 50 | + <div slot="header" class="flex justify-between"> | |
| 51 | + <span>{{ $t('scheduleClassesPage.scheduleTable') }}</span> | |
| 52 | + </div> | |
| 53 | + <div class="hc-table-div" :style="{ width: _computeTableDivWidth() }"> | |
| 54 | + <el-table :data="scheduleClassesPageInfo.staffs" border style="width: 100%"> | |
| 55 | + <el-table-column prop="staffName" :label="$t('scheduleClassesPage.staffName')" align="center" width="120" /> | |
| 56 | + <el-table-column v-for="index in scheduleClassesPageInfo.maxDay" :key="index" | |
| 57 | + :label="`${index}${$t('scheduleClassesPage.day')}`" align="center"> | |
| 58 | + <template slot-scope="scope"> | |
| 59 | + <div v-for="(day, dayIndex) in scope.row.days" :key="dayIndex" | |
| 60 | + class="text-center border padding-lg labeling-strip" style="border-radius: 5px;cursor:pointer"> | |
| 61 | + <div>{{ day.workdayName || $t('scheduleClassesPage.rest') }}</div> | |
| 62 | + <div v-for="(time, timeIndex) in day.times" :key="timeIndex"> | |
| 63 | + {{ time.startTime }}-{{ time.endTime }} | |
| 64 | + </div> | |
| 65 | + </div> | |
| 66 | + </template> | |
| 67 | + </el-table-column> | |
| 68 | + </el-table> | |
| 69 | + </div> | |
| 70 | + | |
| 71 | + <!-- 分页 --> | |
| 72 | + <el-pagination :current-page.sync="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size" | |
| 73 | + :total="page.total" layout="total, sizes, prev, pager, next, jumper" style="margin-top:20px;text-align:right" | |
| 74 | + @size-change="handleSizeChange" @current-change="handleCurrentChange" /> | |
| 75 | + </el-card> | |
| 76 | + | |
| 77 | + <!-- 选择组织弹窗 --> | |
| 78 | + <choose-org-tree ref="chooseOrgTree" @switchOrg="handleSwitchOrg" /> | |
| 79 | + </div> | |
| 80 | +</template> | |
| 81 | + | |
| 82 | +<script> | |
| 83 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 84 | +import { listScheduleClasses, staffMonthScheduleClasses, exportData } from '@/api/org/scheduleClassesPageApi' | |
| 85 | +import ChooseOrgTree from '@/components/org/ChooseOrgTree' | |
| 86 | + | |
| 87 | +export default { | |
| 88 | + name: 'ScheduleClassesPageList', | |
| 89 | + components: { | |
| 90 | + ChooseOrgTree | |
| 91 | + }, | |
| 92 | + data() { | |
| 93 | + return { | |
| 94 | + communityId: '', | |
| 95 | + scheduleClassesPageInfo: { | |
| 96 | + staffs: [], | |
| 97 | + scheduleClassess: [], | |
| 98 | + maxDay: 30, | |
| 99 | + curMonth: '', | |
| 100 | + curYear: '', | |
| 101 | + total: 0, | |
| 102 | + records: 1, | |
| 103 | + moreCondition: false, | |
| 104 | + conditions: { | |
| 105 | + staffNameLike: '', | |
| 106 | + scheduleId: '', | |
| 107 | + curDate: '', | |
| 108 | + orgId: '', | |
| 109 | + orgName: '' | |
| 110 | + } | |
| 111 | + }, | |
| 112 | + page: { | |
| 113 | + current: 1, | |
| 114 | + size: 10, | |
| 115 | + total: 0 | |
| 116 | + } | |
| 117 | + } | |
| 118 | + }, | |
| 119 | + created() { | |
| 120 | + this.communityId = getCommunityId() | |
| 121 | + this.initStaffDate() | |
| 122 | + this._listScheduleClassess() | |
| 123 | + this._listStaffScheduleClassess(this.page.current, this.page.size) | |
| 124 | + }, | |
| 125 | + methods: { | |
| 126 | + initStaffDate() { | |
| 127 | + const date = new Date() | |
| 128 | + this.scheduleClassesPageInfo.curMonth = date.getMonth() + 1 | |
| 129 | + this.scheduleClassesPageInfo.curYear = date.getFullYear() | |
| 130 | + this.scheduleClassesPageInfo.conditions.curDate = `${date.getFullYear()}-${date.getMonth() + 1}` | |
| 131 | + this.scheduleClassesPageInfo.maxDay = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate() | |
| 132 | + }, | |
| 133 | + handleDateChange(val) { | |
| 134 | + if (val) { | |
| 135 | + const values = val.split('-') | |
| 136 | + this.scheduleClassesPageInfo.curYear = values[0] | |
| 137 | + this.scheduleClassesPageInfo.curMonth = values[1] | |
| 138 | + this._listStaffScheduleClassess(this.page.current, this.page.size) | |
| 139 | + } | |
| 140 | + }, | |
| 141 | + async _listStaffScheduleClassess(page, size) { | |
| 142 | + try { | |
| 143 | + const params = { | |
| 144 | + ...this.scheduleClassesPageInfo.conditions, | |
| 145 | + page, | |
| 146 | + row: size, | |
| 147 | + communityId: this.communityId | |
| 148 | + } | |
| 149 | + const { data, total, records } = await staffMonthScheduleClasses(params) | |
| 150 | + this.scheduleClassesPageInfo.staffs = data | |
| 151 | + this.scheduleClassesPageInfo.total = total | |
| 152 | + this.scheduleClassesPageInfo.records = records | |
| 153 | + this.page.total = total | |
| 154 | + } catch (error) { | |
| 155 | + console.error('获取员工排班表失败:', error) | |
| 156 | + } | |
| 157 | + }, | |
| 158 | + async _listScheduleClassess() { | |
| 159 | + try { | |
| 160 | + const params = { | |
| 161 | + page: 1, | |
| 162 | + row: 100, | |
| 163 | + communityId: this.communityId | |
| 164 | + } | |
| 165 | + const { data } = await listScheduleClasses(params) | |
| 166 | + this.scheduleClassesPageInfo.scheduleClassess = data | |
| 167 | + } catch (error) { | |
| 168 | + console.error('获取班次列表失败:', error) | |
| 169 | + } | |
| 170 | + }, | |
| 171 | + _queryScheduleClassesMethod() { | |
| 172 | + this.page.current = 1 | |
| 173 | + this._listStaffScheduleClassess(this.page.current, this.page.size) | |
| 174 | + }, | |
| 175 | + _moreCondition() { | |
| 176 | + this.scheduleClassesPageInfo.moreCondition = !this.scheduleClassesPageInfo.moreCondition | |
| 177 | + }, | |
| 178 | + async _exportScheduleClasses() { | |
| 179 | + try { | |
| 180 | + const params = { | |
| 181 | + ...this.scheduleClassesPageInfo.conditions, | |
| 182 | + communityId: this.communityId, | |
| 183 | + pagePath: 'reportStaffMonthScheduleClasses' | |
| 184 | + } | |
| 185 | + await exportData(params) | |
| 186 | + this.$message.success(this.$t('common.exportSuccess')) | |
| 187 | + } catch (error) { | |
| 188 | + console.error('导出失败:', error) | |
| 189 | + this.$message.error(this.$t('common.exportFailed')) | |
| 190 | + } | |
| 191 | + }, | |
| 192 | + _staffChangeOrg() { | |
| 193 | + this.$refs.chooseOrgTree.open() | |
| 194 | + }, | |
| 195 | + handleSwitchOrg(org) { | |
| 196 | + this.scheduleClassesPageInfo.conditions.orgId = org.orgId | |
| 197 | + this.scheduleClassesPageInfo.conditions.orgName = org.allOrgName | |
| 198 | + }, | |
| 199 | + _computeTableDivWidth() { | |
| 200 | + const mainWidth = document.getElementsByTagName('body')[0].clientWidth - | |
| 201 | + (document.getElementById('menu-nav').offsetWidth || 0) | |
| 202 | + return `${mainWidth - 55}px` | |
| 203 | + }, | |
| 204 | + handleSizeChange(val) { | |
| 205 | + this.page.size = val | |
| 206 | + this._listStaffScheduleClassess(this.page.current, val) | |
| 207 | + }, | |
| 208 | + handleCurrentChange(val) { | |
| 209 | + this.page.current = val | |
| 210 | + this._listStaffScheduleClassess(val, this.page.size) | |
| 211 | + } | |
| 212 | + } | |
| 213 | +} | |
| 214 | +</script> | |
| 215 | + | |
| 216 | +<style lang="scss" scoped> | |
| 217 | +.schedule-classes-container { | |
| 218 | + padding: 20px; | |
| 219 | + | |
| 220 | + .box-card { | |
| 221 | + margin-bottom: 20px; | |
| 222 | + } | |
| 223 | + | |
| 224 | + .hc-table-div { | |
| 225 | + overflow-x: auto; | |
| 226 | + } | |
| 227 | + | |
| 228 | + .labeling-strip { | |
| 229 | + padding: 8px; | |
| 230 | + margin: 2px; | |
| 231 | + border: 1px solid #ebeef5; | |
| 232 | + } | |
| 233 | +} | |
| 234 | +</style> | |
| 0 | 235 | \ No newline at end of file | ... | ... |
src/views/system/communitySettingManageLang.js
0 → 100644
| 1 | +export const messages = { | |
| 2 | + en: { | |
| 3 | + communitySettingManage: { | |
| 4 | + inputPlaceholder: 'Required, please enter {name}', | |
| 5 | + settingTips: 'Reminder: No spaces before or after input', | |
| 6 | + saveSuccess: 'Save successfully' | |
| 7 | + } | |
| 8 | + }, | |
| 9 | + zh: { | |
| 10 | + communitySettingManage: { | |
| 11 | + inputPlaceholder: '必填,请输入{name}', | |
| 12 | + settingTips: '温馨提示:填写前后不要有空格', | |
| 13 | + saveSuccess: '保存成功' | |
| 14 | + } | |
| 15 | + } | |
| 16 | +} | |
| 0 | 17 | \ No newline at end of file | ... | ... |
src/views/system/communitySettingManageList.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="community-setting-manage-container"> | |
| 3 | + <el-row :gutter="20"> | |
| 4 | + <el-col :span="4"> | |
| 5 | + <el-card class="setting-type-card"> | |
| 6 | + <div class="setting-type-list"> | |
| 7 | + <div v-for="(item, index) in settingTypes" :key="index" class="setting-type-item" | |
| 8 | + :class="{ 'active': conditions.settingType === item.statusCd }" @click="handleSwitchSettingType(item)"> | |
| 9 | + {{ item.name }} | |
| 10 | + </div> | |
| 11 | + </div> | |
| 12 | + </el-card> | |
| 13 | + </el-col> | |
| 14 | + <el-col :span="20"> | |
| 15 | + <el-card> | |
| 16 | + <div slot="header" class="flex justify-between"> | |
| 17 | + <span>{{ currentSettingName }}</span> | |
| 18 | + </div> | |
| 19 | + <div class="setting-content text-left"> | |
| 20 | + <el-form label-position="right" label-width="120px"> | |
| 21 | + <el-form-item v-for="(item, index) in settingKeys" :key="index" :label="item.settingName"> | |
| 22 | + <el-input v-model="item.settingValue" | |
| 23 | + :placeholder="$t('communitySettingManage.inputPlaceholder', { name: item.settingName })" /> | |
| 24 | + <div class="setting-remark">{{ item.remark }}</div> | |
| 25 | + </el-form-item> | |
| 26 | + </el-form> | |
| 27 | + <div class="setting-tips">{{ $t('communitySettingManage.settingTips') }}</div> | |
| 28 | + <div class="text-right"> | |
| 29 | + <el-button type="primary" @click="handleSaveSettings"> | |
| 30 | + <i class="el-icon-check"></i> | |
| 31 | + {{ $t('common.submit') }} | |
| 32 | + </el-button> | |
| 33 | + </div> | |
| 34 | + </div> | |
| 35 | + </el-card> | |
| 36 | + </el-col> | |
| 37 | + </el-row> | |
| 38 | + </div> | |
| 39 | +</template> | |
| 40 | + | |
| 41 | +<script> | |
| 42 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 43 | +import { getDict } from '@/api/community/communityApi' | |
| 44 | +import { | |
| 45 | + listCommunitySettingKey, | |
| 46 | + saveCommunitySetting | |
| 47 | +} from '@/api/system/communitySettingManageApi' | |
| 48 | + | |
| 49 | +export default { | |
| 50 | + name: 'CommunitySettingManageList', | |
| 51 | + data() { | |
| 52 | + return { | |
| 53 | + communityId: '', | |
| 54 | + settingTypes: [], | |
| 55 | + settingKeys: [], | |
| 56 | + currentSettingName: '', | |
| 57 | + conditions: { | |
| 58 | + settingType: '', | |
| 59 | + communityId: '' | |
| 60 | + } | |
| 61 | + } | |
| 62 | + }, | |
| 63 | + created() { | |
| 64 | + this.communityId = getCommunityId() | |
| 65 | + this.conditions.communityId = this.communityId | |
| 66 | + this.initData() | |
| 67 | + }, | |
| 68 | + methods: { | |
| 69 | + async initData() { | |
| 70 | + try { | |
| 71 | + const data = await getDict('community_setting_key', 'setting_type') | |
| 72 | + this.settingTypes = data | |
| 73 | + if (data && data.length > 0) { | |
| 74 | + this.handleSwitchSettingType(data[0]) | |
| 75 | + } | |
| 76 | + } catch (error) { | |
| 77 | + console.error('获取字典数据失败:', error) | |
| 78 | + } | |
| 79 | + }, | |
| 80 | + async handleSwitchSettingType(item) { | |
| 81 | + this.conditions.settingType = item.statusCd | |
| 82 | + this.currentSettingName = item.name | |
| 83 | + await this.loadSettingKeys() | |
| 84 | + }, | |
| 85 | + async loadSettingKeys() { | |
| 86 | + try { | |
| 87 | + const params = { | |
| 88 | + communityId: this.communityId, | |
| 89 | + settingType: this.conditions.settingType | |
| 90 | + } | |
| 91 | + const { data } = await listCommunitySettingKey(params) | |
| 92 | + this.settingKeys = data.map(item => { | |
| 93 | + return { | |
| 94 | + ...item, | |
| 95 | + settingValue: item.settingValue || '' | |
| 96 | + } | |
| 97 | + }) | |
| 98 | + } catch (error) { | |
| 99 | + console.error('获取设置项失败:', error) | |
| 100 | + } | |
| 101 | + }, | |
| 102 | + async handleSaveSettings() { | |
| 103 | + try { | |
| 104 | + const params = { | |
| 105 | + communityId: this.communityId, | |
| 106 | + keys: this.settingKeys, | |
| 107 | + settingType: this.conditions.settingType | |
| 108 | + } | |
| 109 | + await saveCommunitySetting(params) | |
| 110 | + this.$message.success(this.$t('common.saveSuccess')) | |
| 111 | + this.loadSettingKeys() | |
| 112 | + } catch (error) { | |
| 113 | + console.error('保存设置失败:', error) | |
| 114 | + } | |
| 115 | + } | |
| 116 | + } | |
| 117 | +} | |
| 118 | +</script> | |
| 119 | + | |
| 120 | +<style lang="scss" scoped> | |
| 121 | +.community-setting-manage-container { | |
| 122 | + padding: 20px; | |
| 123 | + | |
| 124 | + .setting-type-card { | |
| 125 | + height: 100%; | |
| 126 | + | |
| 127 | + .setting-type-list { | |
| 128 | + .setting-type-item { | |
| 129 | + padding: 10px; | |
| 130 | + margin-bottom: 5px; | |
| 131 | + cursor: pointer; | |
| 132 | + border-radius: 4px; | |
| 133 | + text-align: center; | |
| 134 | + | |
| 135 | + &:hover { | |
| 136 | + background-color: #f5f7fa; | |
| 137 | + } | |
| 138 | + | |
| 139 | + &.active { | |
| 140 | + background-color: #409eff; | |
| 141 | + color: white; | |
| 142 | + } | |
| 143 | + } | |
| 144 | + } | |
| 145 | + } | |
| 146 | + | |
| 147 | + .setting-content { | |
| 148 | + padding: 20px; | |
| 149 | + | |
| 150 | + .setting-remark { | |
| 151 | + margin-top: 5px; | |
| 152 | + font-size: 12px; | |
| 153 | + color: #909399; | |
| 154 | + } | |
| 155 | + | |
| 156 | + .setting-tips { | |
| 157 | + margin: 20px 0; | |
| 158 | + font-size: 12px; | |
| 159 | + color: #f56c6c; | |
| 160 | + } | |
| 161 | + } | |
| 162 | +} | |
| 163 | +</style> | |
| 0 | 164 | \ No newline at end of file | ... | ... |
src/views/system/storeInfoManageLang.js
0 → 100644
| 1 | +export const messages = { | |
| 2 | + en: { | |
| 3 | + storeInfoManage: { | |
| 4 | + basicInfo: 'Basic Information', | |
| 5 | + storeName: 'Store Name', | |
| 6 | + storeAddress: 'Store Address', | |
| 7 | + contactNumber: 'Contact Number', | |
| 8 | + storeType: 'Store Type', | |
| 9 | + legalPerson: 'Legal Person', | |
| 10 | + nearbyLandmark: 'Nearby Landmark', | |
| 11 | + operation: 'Operation', | |
| 12 | + edit: 'Edit', | |
| 13 | + storeInfo: 'Store Information', | |
| 14 | + attributeName: 'Attribute Name', | |
| 15 | + attributeValue: 'Attribute Value', | |
| 16 | + fetchError: 'Failed to fetch store information' | |
| 17 | + }, | |
| 18 | + editStoreInfo: { | |
| 19 | + title: 'Edit Store Information', | |
| 20 | + storeName: 'Store Name', | |
| 21 | + storeNamePlaceholder: 'Store name cannot be modified', | |
| 22 | + storeAddress: 'Store Address', | |
| 23 | + storeAddressPlaceholder: 'Required, please enter store address', | |
| 24 | + contactNumber: 'Contact Number', | |
| 25 | + contactNumberPlaceholder: 'Required, please enter contact number', | |
| 26 | + nearbyLandmark: 'Nearby Landmark', | |
| 27 | + nearbyLandmarkPlaceholder: 'Required, please enter nearby landmark', | |
| 28 | + mapX: 'Map X Coordinate', | |
| 29 | + mapXPlaceholder: 'Optional, please enter X coordinate', | |
| 30 | + mapY: 'Map Y Coordinate', | |
| 31 | + mapYPlaceholder: 'Optional, please enter Y coordinate', | |
| 32 | + validate: { | |
| 33 | + nameRequired: 'Store name is required', | |
| 34 | + nameMaxLength: 'Store name cannot exceed 100 characters', | |
| 35 | + addressRequired: 'Store address is required', | |
| 36 | + addressMaxLength: 'Store address cannot exceed 200 characters', | |
| 37 | + telRequired: 'Contact number is required', | |
| 38 | + telMaxLength: 'Contact number cannot exceed 11 digits', | |
| 39 | + landmarkRequired: 'Nearby landmark is required', | |
| 40 | + landmarkMaxLength: 'Nearby landmark cannot exceed 200 characters' | |
| 41 | + } | |
| 42 | + }, | |
| 43 | + editStoreAttr: { | |
| 44 | + title: 'Edit Store Attribute', | |
| 45 | + attributePlaceholder: 'Store attribute is required', | |
| 46 | + validate: { | |
| 47 | + valueRequired: 'Attribute value is required', | |
| 48 | + valueMaxLength: 'Attribute value cannot exceed 50 characters', | |
| 49 | + attrIdRequired: 'Attribute ID cannot be empty' | |
| 50 | + } | |
| 51 | + } | |
| 52 | + }, | |
| 53 | + zh: { | |
| 54 | + storeInfoManage: { | |
| 55 | + basicInfo: '基本信息', | |
| 56 | + storeName: '商户名称', | |
| 57 | + storeAddress: '商户地址', | |
| 58 | + contactNumber: '联系电话', | |
| 59 | + storeType: '商户类型', | |
| 60 | + legalPerson: '企业法人', | |
| 61 | + nearbyLandmark: '附近地标', | |
| 62 | + operation: '操作', | |
| 63 | + edit: '修改', | |
| 64 | + storeInfo: '商户信息', | |
| 65 | + attributeName: '属性名称', | |
| 66 | + attributeValue: '属性值', | |
| 67 | + fetchError: '获取商户信息失败' | |
| 68 | + }, | |
| 69 | + editStoreInfo: { | |
| 70 | + title: '修改商户信息', | |
| 71 | + storeName: '商户名称', | |
| 72 | + storeNamePlaceholder: '商户名称不能修改', | |
| 73 | + storeAddress: '商户地址', | |
| 74 | + storeAddressPlaceholder: '必填,请填写商户地址', | |
| 75 | + contactNumber: '电话', | |
| 76 | + contactNumberPlaceholder: '必填,请填写联系电话', | |
| 77 | + nearbyLandmark: '附近地标', | |
| 78 | + nearbyLandmarkPlaceholder: '必填,请填写附近地标', | |
| 79 | + mapX: '地区X坐标', | |
| 80 | + mapXPlaceholder: '选填,请填写x坐标', | |
| 81 | + mapY: '地区Y坐标', | |
| 82 | + mapYPlaceholder: '选填,请填写y坐标', | |
| 83 | + validate: { | |
| 84 | + nameRequired: '商户名称必填', | |
| 85 | + nameMaxLength: '商户名称不能超过100位', | |
| 86 | + addressRequired: '商户地址必填', | |
| 87 | + addressMaxLength: '商户地址不能超过200位', | |
| 88 | + telRequired: '联系电话必填', | |
| 89 | + telMaxLength: '联系电话最多11位', | |
| 90 | + landmarkRequired: '附件地标必填', | |
| 91 | + landmarkMaxLength: '附件地标位置最多200位' | |
| 92 | + } | |
| 93 | + }, | |
| 94 | + editStoreAttr: { | |
| 95 | + title: '修改商户属性', | |
| 96 | + attributePlaceholder: '商户属性必填', | |
| 97 | + validate: { | |
| 98 | + valueRequired: '必填', | |
| 99 | + valueMaxLength: '属性值不能超过50位', | |
| 100 | + attrIdRequired: '属性id不能为空' | |
| 101 | + } | |
| 102 | + } | |
| 103 | + } | |
| 104 | +} | |
| 0 | 105 | \ No newline at end of file | ... | ... |
src/views/system/storeInfoManageList.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="store-info-manage-container animated fadeInRight"> | |
| 3 | + <el-row :gutter="20"> | |
| 4 | + <el-col :span="24"> | |
| 5 | + <el-card class="box-card"> | |
| 6 | + <div slot="header" class="flex justify-between"> | |
| 7 | + <span>{{ $t('storeInfoManage.basicInfo') }}</span> | |
| 8 | + </div> | |
| 9 | + <el-table :data="listStoreManageInfo.listStores" border style="width: 100%" v-loading="loading"> | |
| 10 | + <el-table-column prop="name" :label="$t('storeInfoManage.storeName')" align="center" /> | |
| 11 | + <el-table-column prop="address" :label="$t('storeInfoManage.storeAddress')" align="center" /> | |
| 12 | + <el-table-column prop="tel" :label="$t('storeInfoManage.contactNumber')" align="center" /> | |
| 13 | + <el-table-column prop="storeTypeName" :label="$t('storeInfoManage.storeType')" align="center" /> | |
| 14 | + <el-table-column prop="artificialPerson" :label="$t('storeInfoManage.legalPerson')" align="center" /> | |
| 15 | + <el-table-column prop="nearByLandmarks" :label="$t('storeInfoManage.nearbyLandmark')" align="center" /> | |
| 16 | + <el-table-column :label="$t('storeInfoManage.operation')" align="center" width="150"> | |
| 17 | + <template slot-scope="scope"> | |
| 18 | + <el-button size="mini" type="primary" @click="_openEditStoreInfoModel(scope.row)"> | |
| 19 | + {{ $t('storeInfoManage.edit') }} | |
| 20 | + </el-button> | |
| 21 | + </template> | |
| 22 | + </el-table-column> | |
| 23 | + </el-table> | |
| 24 | + <el-pagination :current-page.sync="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size" | |
| 25 | + :total="page.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange" | |
| 26 | + @current-change="handleCurrentChange" /> | |
| 27 | + </el-card> | |
| 28 | + </el-col> | |
| 29 | + </el-row> | |
| 30 | + | |
| 31 | + <el-row :gutter="20" style="margin-top: 20px"> | |
| 32 | + <el-col :span="24"> | |
| 33 | + <el-card class="box-card"> | |
| 34 | + <div slot="header" class="flex justify-between"> | |
| 35 | + <span>{{ $t('storeInfoManage.storeInfo') }}</span> | |
| 36 | + </div> | |
| 37 | + <el-table :data="listStoreManageInfo.storeAttrDtoList" border style="width: 100%"> | |
| 38 | + <el-table-column prop="name" :label="$t('storeInfoManage.attributeName')" align="center" /> | |
| 39 | + <el-table-column prop="value" :label="$t('storeInfoManage.attributeValue')" align="center" /> | |
| 40 | + <el-table-column :label="$t('storeInfoManage.operation')" align="center" width="150"> | |
| 41 | + <template slot-scope="scope"> | |
| 42 | + <el-button size="mini" type="primary" @click="_openEditStoreAttrModel(scope.row)"> | |
| 43 | + {{ $t('storeInfoManage.edit') }} | |
| 44 | + </el-button> | |
| 45 | + </template> | |
| 46 | + </el-table-column> | |
| 47 | + </el-table> | |
| 48 | + </el-card> | |
| 49 | + </el-col> | |
| 50 | + </el-row> | |
| 51 | + | |
| 52 | + <edit-store-info ref="editStoreInfo" @success="handleSuccess" /> | |
| 53 | + <edit-store-attr ref="editStoreAttr" @success="handleSuccess" /> | |
| 54 | + </div> | |
| 55 | +</template> | |
| 56 | + | |
| 57 | +<script> | |
| 58 | +import { listStores } from '@/api/system/storeInfoManageApi' | |
| 59 | +import EditStoreInfo from '@/components/system/editStoreInfo' | |
| 60 | +import EditStoreAttr from '@/components/system/editStoreAttr' | |
| 61 | + | |
| 62 | +export default { | |
| 63 | + name: 'StoreInfoManageList', | |
| 64 | + components: { | |
| 65 | + EditStoreInfo, | |
| 66 | + EditStoreAttr | |
| 67 | + }, | |
| 68 | + data() { | |
| 69 | + return { | |
| 70 | + loading: false, | |
| 71 | + listStoreManageInfo: { | |
| 72 | + listStores: [], | |
| 73 | + storeAttrDtoList: [], | |
| 74 | + conditions: { | |
| 75 | + name: '', | |
| 76 | + storeTypeCd: '', | |
| 77 | + tel: '' | |
| 78 | + } | |
| 79 | + }, | |
| 80 | + page: { | |
| 81 | + current: 1, | |
| 82 | + size: 10, | |
| 83 | + total: 0 | |
| 84 | + } | |
| 85 | + } | |
| 86 | + }, | |
| 87 | + created() { | |
| 88 | + this._listListStores() | |
| 89 | + }, | |
| 90 | + methods: { | |
| 91 | + async _listListStores() { | |
| 92 | + try { | |
| 93 | + this.loading = true | |
| 94 | + const params = { | |
| 95 | + page: this.page.current, | |
| 96 | + row: this.page.size, | |
| 97 | + ...this.listStoreManageInfo.conditions | |
| 98 | + } | |
| 99 | + const { data, total } = await listStores(params) | |
| 100 | + this.listStoreManageInfo.listStores = data | |
| 101 | + this.listStoreManageInfo.storeAttrDtoList = data[0].storeAttrDtoList || [] | |
| 102 | + this.page.total = total | |
| 103 | + } catch (error) { | |
| 104 | + this.$message.error(this.$t('storeInfoManage.fetchError')) | |
| 105 | + } finally { | |
| 106 | + this.loading = false | |
| 107 | + } | |
| 108 | + }, | |
| 109 | + _openEditStoreInfoModel(storeInfo) { | |
| 110 | + this.$refs.editStoreInfo.open(storeInfo) | |
| 111 | + }, | |
| 112 | + _openEditStoreAttrModel(storeAttr) { | |
| 113 | + this.$refs.editStoreAttr.open(storeAttr) | |
| 114 | + }, | |
| 115 | + handleSuccess() { | |
| 116 | + this._listListStores() | |
| 117 | + }, | |
| 118 | + handleSizeChange(val) { | |
| 119 | + this.page.size = val | |
| 120 | + this._listListStores() | |
| 121 | + }, | |
| 122 | + handleCurrentChange(val) { | |
| 123 | + this.page.current = val | |
| 124 | + this._listListStores() | |
| 125 | + } | |
| 126 | + } | |
| 127 | +} | |
| 128 | +</script> | |
| 129 | + | |
| 130 | +<style lang="scss" scoped> | |
| 131 | +.store-info-manage-container { | |
| 132 | + padding: 20px; | |
| 133 | + | |
| 134 | + .box-card { | |
| 135 | + margin-bottom: 20px; | |
| 136 | + } | |
| 137 | + | |
| 138 | + .el-pagination { | |
| 139 | + margin-top: 15px; | |
| 140 | + text-align: right; | |
| 141 | + } | |
| 142 | +} | |
| 143 | +</style> | |
| 0 | 144 | \ No newline at end of file | ... | ... |
src/views/system/workflowManageLang.js
0 → 100644
| 1 | +export const messages = { | |
| 2 | + en: { | |
| 3 | + workflowManage: { | |
| 4 | + search: { | |
| 5 | + title: 'Search Conditions', | |
| 6 | + flowId: 'Please enter workflow code', | |
| 7 | + flowName: 'Please enter workflow name', | |
| 8 | + flowType: 'Please select workflow type' | |
| 9 | + }, | |
| 10 | + list: { | |
| 11 | + title: 'Workflow Information' | |
| 12 | + }, | |
| 13 | + table: { | |
| 14 | + flowId: 'Workflow Code', | |
| 15 | + flowName: 'Workflow Name', | |
| 16 | + flowType: 'Workflow Type', | |
| 17 | + createTime: 'Create Time' | |
| 18 | + }, | |
| 19 | + operation: { | |
| 20 | + setting: 'Setting', | |
| 21 | + viewImage: 'Flow Chart' | |
| 22 | + }, | |
| 23 | + fetchError: 'Failed to fetch workflow data', | |
| 24 | + imageError: 'Failed to load workflow image' | |
| 25 | + } | |
| 26 | + }, | |
| 27 | + zh: { | |
| 28 | + workflowManage: { | |
| 29 | + search: { | |
| 30 | + title: '查询条件', | |
| 31 | + flowId: '请输入流程编码', | |
| 32 | + flowName: '请输入流程名称', | |
| 33 | + flowType: '请选择流程类型' | |
| 34 | + }, | |
| 35 | + list: { | |
| 36 | + title: '流程信息' | |
| 37 | + }, | |
| 38 | + table: { | |
| 39 | + flowId: '流程编码', | |
| 40 | + flowName: '流程名称', | |
| 41 | + flowType: '流程类型', | |
| 42 | + createTime: '创建时间' | |
| 43 | + }, | |
| 44 | + operation: { | |
| 45 | + setting: '设置流程', | |
| 46 | + viewImage: '流程图' | |
| 47 | + }, | |
| 48 | + fetchError: '获取流程数据失败', | |
| 49 | + imageError: '加载流程图失败' | |
| 50 | + } | |
| 51 | + } | |
| 52 | +} | |
| 0 | 53 | \ No newline at end of file | ... | ... |
src/views/system/workflowManageList.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="workflow-manage-container animated fadeInRight"> | |
| 3 | + <el-row> | |
| 4 | + <el-col :span="24"> | |
| 5 | + <el-card class="box-card"> | |
| 6 | + <div slot="header" class="flex justify-between"> | |
| 7 | + <span>{{ $t('workflowManage.search.title') }}</span> | |
| 8 | + </div> | |
| 9 | + <div class="search-wrapper"> | |
| 10 | + <el-row :gutter="20"> | |
| 11 | + <el-col :span="6"> | |
| 12 | + <el-input v-model="searchForm.flowId" :placeholder="$t('workflowManage.search.flowId')" clearable | |
| 13 | + @keyup.enter.native="handleSearch" /> | |
| 14 | + </el-col> | |
| 15 | + <el-col :span="8"> | |
| 16 | + <el-select v-model="searchForm.flowType" :placeholder="$t('workflowManage.search.flowType')" | |
| 17 | + style="width:100%" clearable> | |
| 18 | + <el-option v-for="item in flowTypes" :key="item.statusCd" :label="item.name" :value="item.statusCd" /> | |
| 19 | + </el-select> | |
| 20 | + </el-col> | |
| 21 | + <el-col :span="6"> | |
| 22 | + <el-input v-model="searchForm.flowName" :placeholder="$t('workflowManage.search.flowName')" clearable | |
| 23 | + @keyup.enter.native="handleSearch" /> | |
| 24 | + </el-col> | |
| 25 | + <el-col :span="4"> | |
| 26 | + <el-button type="primary" @click="handleSearch"> | |
| 27 | + <i class="el-icon-search"></i> | |
| 28 | + {{ $t('common.search') }} | |
| 29 | + </el-button> | |
| 30 | + <el-button @click="handleReset"> | |
| 31 | + <i class="el-icon-refresh"></i> | |
| 32 | + {{ $t('common.reset') }} | |
| 33 | + </el-button> | |
| 34 | + </el-col> | |
| 35 | + </el-row> | |
| 36 | + </div> | |
| 37 | + </el-card> | |
| 38 | + </el-col> | |
| 39 | + </el-row> | |
| 40 | + | |
| 41 | + <el-row> | |
| 42 | + <el-col :span="24"> | |
| 43 | + <el-card class="box-card"> | |
| 44 | + <div slot="header" class="flex justify-between"> | |
| 45 | + <span>{{ $t('workflowManage.list.title') }}</span> | |
| 46 | + </div> | |
| 47 | + <el-table v-loading="loading" :data="tableData" border style="width: 100%"> | |
| 48 | + <el-table-column prop="flowId" :label="$t('workflowManage.table.flowId')" align="center" /> | |
| 49 | + <el-table-column prop="flowName" :label="$t('workflowManage.table.flowName')" align="center" /> | |
| 50 | + <el-table-column prop="flowTypeName" :label="$t('workflowManage.table.flowType')" align="center" /> | |
| 51 | + <el-table-column prop="createTime" :label="$t('workflowManage.table.createTime')" align="center" /> | |
| 52 | + <el-table-column :label="$t('common.operation')" align="center" width="200"> | |
| 53 | + <template slot-scope="scope"> | |
| 54 | + <el-button size="mini" type="primary" @click="handleEdit(scope.row)"> | |
| 55 | + {{ $t('workflowManage.operation.setting') }} | |
| 56 | + </el-button> | |
| 57 | + <el-button size="mini" type="success" @click="handleViewImage(scope.row)"> | |
| 58 | + {{ $t('workflowManage.operation.viewImage') }} | |
| 59 | + </el-button> | |
| 60 | + </template> | |
| 61 | + </el-table-column> | |
| 62 | + </el-table> | |
| 63 | + | |
| 64 | + <el-pagination :current-page.sync="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size" | |
| 65 | + :total="page.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange" | |
| 66 | + @current-change="handleCurrentChange" /> | |
| 67 | + </el-card> | |
| 68 | + </el-col> | |
| 69 | + </el-row> | |
| 70 | + | |
| 71 | + <view-image ref="viewImage" /> | |
| 72 | + </div> | |
| 73 | +</template> | |
| 74 | + | |
| 75 | +<script> | |
| 76 | +import { listWorkflows, listWorkflowImage } from '@/api/system/workflowManageApi' | |
| 77 | +import { getDict } from '@/api/community/communityApi' | |
| 78 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 79 | +import ViewImage from '@/components/system/viewImage' | |
| 80 | + | |
| 81 | +export default { | |
| 82 | + name: 'WorkflowManageList', | |
| 83 | + components: { | |
| 84 | + ViewImage | |
| 85 | + }, | |
| 86 | + data() { | |
| 87 | + return { | |
| 88 | + loading: false, | |
| 89 | + searchForm: { | |
| 90 | + flowId: '', | |
| 91 | + flowName: '', | |
| 92 | + flowType: '' | |
| 93 | + }, | |
| 94 | + tableData: [], | |
| 95 | + flowTypes: [], | |
| 96 | + page: { | |
| 97 | + current: 1, | |
| 98 | + size: 10, | |
| 99 | + total: 0 | |
| 100 | + }, | |
| 101 | + communityId: '' | |
| 102 | + } | |
| 103 | + }, | |
| 104 | + created() { | |
| 105 | + this.communityId = getCommunityId() | |
| 106 | + this.getList() | |
| 107 | + this.getDictData() | |
| 108 | + }, | |
| 109 | + methods: { | |
| 110 | + async getList() { | |
| 111 | + try { | |
| 112 | + this.loading = true | |
| 113 | + const params = { | |
| 114 | + page: this.page.current, | |
| 115 | + row: this.page.size, | |
| 116 | + communityId: this.communityId, | |
| 117 | + ...this.searchForm | |
| 118 | + } | |
| 119 | + const { data, total } = await listWorkflows(params) | |
| 120 | + this.tableData = data | |
| 121 | + this.page.total = total | |
| 122 | + } catch (error) { | |
| 123 | + this.$message.error(this.$t('workflowManage.fetchError')) | |
| 124 | + } finally { | |
| 125 | + this.loading = false | |
| 126 | + } | |
| 127 | + }, | |
| 128 | + async getDictData() { | |
| 129 | + try { | |
| 130 | + const data = await getDict('workflow', 'flow_type') | |
| 131 | + this.flowTypes = data | |
| 132 | + } catch (error) { | |
| 133 | + console.error('获取字典数据失败:', error) | |
| 134 | + } | |
| 135 | + }, | |
| 136 | + handleSearch() { | |
| 137 | + this.page.current = 1 | |
| 138 | + this.getList() | |
| 139 | + }, | |
| 140 | + handleReset() { | |
| 141 | + this.searchForm = { | |
| 142 | + flowId: '', | |
| 143 | + flowName: '', | |
| 144 | + flowType: '' | |
| 145 | + } | |
| 146 | + this.getList() | |
| 147 | + }, | |
| 148 | + handleEdit(row) { | |
| 149 | + this.$router.push({ | |
| 150 | + path: '/pages/property/workflowSettingManage', | |
| 151 | + query: row | |
| 152 | + }) | |
| 153 | + }, | |
| 154 | + async handleViewImage(row) { | |
| 155 | + try { | |
| 156 | + const params = { | |
| 157 | + communityId: this.communityId, | |
| 158 | + flowId: row.flowId | |
| 159 | + } | |
| 160 | + const { data } = await listWorkflowImage(params) | |
| 161 | + this.$refs.viewImage.open({ | |
| 162 | + url: 'data:image/png;base64,' + data | |
| 163 | + }) | |
| 164 | + } catch (error) { | |
| 165 | + this.$message.error(this.$t('workflowManage.imageError')) | |
| 166 | + } | |
| 167 | + }, | |
| 168 | + handleSizeChange(val) { | |
| 169 | + this.page.size = val | |
| 170 | + this.getList() | |
| 171 | + }, | |
| 172 | + handleCurrentChange(val) { | |
| 173 | + this.page.current = val | |
| 174 | + this.getList() | |
| 175 | + } | |
| 176 | + } | |
| 177 | +} | |
| 178 | +</script> | |
| 179 | + | |
| 180 | +<style lang="scss" scoped> | |
| 181 | +.workflow-manage-container { | |
| 182 | + padding: 0; | |
| 183 | + margin: 0; | |
| 184 | + | |
| 185 | + .box-card { | |
| 186 | + margin-bottom: 20px; | |
| 187 | + } | |
| 188 | + | |
| 189 | + .search-wrapper { | |
| 190 | + .el-col { | |
| 191 | + margin-bottom: 10px; | |
| 192 | + } | |
| 193 | + } | |
| 194 | + | |
| 195 | + .el-pagination { | |
| 196 | + margin-top: 20px; | |
| 197 | + text-align: right; | |
| 198 | + } | |
| 199 | +} | |
| 200 | +</style> | |
| 0 | 201 | \ No newline at end of file | ... | ... |
src/views/system/workflowSettingManageLang.js
0 → 100644
| 1 | +export const messages = { | |
| 2 | + en: { | |
| 3 | + workflowSettingManage: { | |
| 4 | + title: 'Process Settings', | |
| 5 | + flowName: 'Process Name', | |
| 6 | + flowNamePlaceholder: 'Required, please enter the title', | |
| 7 | + description: 'Process Description', | |
| 8 | + descriptionPlaceholder: 'Optional, please enter the process description', | |
| 9 | + submitterEnd: 'Submitter End', | |
| 10 | + submitterEndPlaceholder: 'Required, please select whether the submitter needs to confirm', | |
| 11 | + yes: 'Yes', | |
| 12 | + no: 'No', | |
| 13 | + flowSteps: 'Process Steps', | |
| 14 | + addStep: 'Add Step', | |
| 15 | + step: 'Step', | |
| 16 | + selectStaff: 'Select Staff', | |
| 17 | + normalFlow: 'Normal Process', | |
| 18 | + countersign: 'Countersign', | |
| 19 | + deleteStep: 'Delete Step', | |
| 20 | + addStaff: 'Add Staff', | |
| 21 | + deleteStaff: 'Delete Staff', | |
| 22 | + instructions: 'Instructions', | |
| 23 | + instruction1: 'At least two steps are required, the last step must be a fixed warehouse manager', | |
| 24 | + instruction2: 'Warehouse managers cannot participate in the review process', | |
| 25 | + instruction3: 'Warehouse managers cannot be dynamically assigned', | |
| 26 | + instruction4: 'Must configure the corresponding process', | |
| 27 | + invalidOperation: 'Invalid operation' | |
| 28 | + }, | |
| 29 | + selectStaff: { | |
| 30 | + title: 'Select Staff', | |
| 31 | + orgInfo: 'Organization Information', | |
| 32 | + staffInfo: 'Staff Information', | |
| 33 | + submitter: 'Submitter', | |
| 34 | + dynamicAssign: 'Dynamic Assign', | |
| 35 | + fetchStaffError: 'Failed to fetch staff information' | |
| 36 | + }, | |
| 37 | + orgTree: { | |
| 38 | + fetchError: 'Failed to fetch organization tree' | |
| 39 | + } | |
| 40 | + }, | |
| 41 | + zh: { | |
| 42 | + workflowSettingManage: { | |
| 43 | + title: '流程设置', | |
| 44 | + flowName: '流程名称', | |
| 45 | + flowNamePlaceholder: '必填,请填写标题', | |
| 46 | + description: '流程说明', | |
| 47 | + descriptionPlaceholder: '选填,请填写流程说明', | |
| 48 | + submitterEnd: '提交者结束', | |
| 49 | + submitterEndPlaceholder: '必填,请选择最后环节是否提交者确认', | |
| 50 | + yes: '是', | |
| 51 | + no: '否', | |
| 52 | + flowSteps: '流程步骤', | |
| 53 | + addStep: '添加步骤', | |
| 54 | + step: '第', | |
| 55 | + selectStaff: '选择员工', | |
| 56 | + normalFlow: '普通流程', | |
| 57 | + countersign: '会签', | |
| 58 | + deleteStep: '删除步骤', | |
| 59 | + addStaff: '添加员工', | |
| 60 | + deleteStaff: '删除员工', | |
| 61 | + instructions: '说明', | |
| 62 | + instruction1: '添加步骤必须要两步以上,最后一步为固定仓库管理员', | |
| 63 | + instruction2: '仓库管理不能参与审核流程', | |
| 64 | + instruction3: '仓库管理员不能为动态指定人员', | |
| 65 | + instruction4: '必须配置对应的流程', | |
| 66 | + invalidOperation: '操作错误' | |
| 67 | + }, | |
| 68 | + selectStaff: { | |
| 69 | + title: '选择员工', | |
| 70 | + orgInfo: '组织信息', | |
| 71 | + staffInfo: '员工信息', | |
| 72 | + submitter: '提交者', | |
| 73 | + dynamicAssign: '动态指定', | |
| 74 | + fetchStaffError: '获取员工信息失败' | |
| 75 | + }, | |
| 76 | + orgTree: { | |
| 77 | + fetchError: '获取组织树失败' | |
| 78 | + } | |
| 79 | + } | |
| 80 | +} | |
| 0 | 81 | \ No newline at end of file | ... | ... |
src/views/system/workflowSettingManageList.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="workflow-setting-container"> | |
| 3 | + <el-row :gutter="20"> | |
| 4 | + <el-col :span="24"> | |
| 5 | + <el-card> | |
| 6 | + <div slot="header" class="clearfix"> | |
| 7 | + <span>{{ $t('workflowSettingManage.title') }}</span> | |
| 8 | + </div> | |
| 9 | + <el-form label-width="120px"> | |
| 10 | + <el-form-item :label="$t('workflowSettingManage.flowName')"> | |
| 11 | + <el-input v-model="workflowSettingInfo.flowName" | |
| 12 | + :placeholder="$t('workflowSettingManage.flowNamePlaceholder')" disabled /> | |
| 13 | + </el-form-item> | |
| 14 | + | |
| 15 | + <el-form-item :label="$t('workflowSettingManage.description')"> | |
| 16 | + <el-input v-model="workflowSettingInfo.describle" type="textarea" | |
| 17 | + :placeholder="$t('workflowSettingManage.descriptionPlaceholder')" :rows="3" /> | |
| 18 | + </el-form-item> | |
| 19 | + | |
| 20 | + <el-form-item :label="$t('workflowSettingManage.submitterEnd')"> | |
| 21 | + <el-select v-model="workflowSettingInfo.startNodeFinish" style="width:100%" | |
| 22 | + :placeholder="$t('workflowSettingManage.submitterEndPlaceholder')"> | |
| 23 | + <el-option :label="$t('workflowSettingManage.yes')" value="Y" /> | |
| 24 | + <el-option :label="$t('workflowSettingManage.no')" value="N" /> | |
| 25 | + </el-select> | |
| 26 | + </el-form-item> | |
| 27 | + | |
| 28 | + <el-form-item :label="$t('workflowSettingManage.flowSteps')"> | |
| 29 | + <div class="step-actions"> | |
| 30 | + <el-button type="primary" @click="addWorkflowStep"> | |
| 31 | + {{ $t('workflowSettingManage.addStep') }} | |
| 32 | + </el-button> | |
| 33 | + </div> | |
| 34 | + | |
| 35 | + <div v-for="(item, index) in workflowSettingInfo.steps" :key="index" class="step-item"> | |
| 36 | + <div class="step-header"> | |
| 37 | + <span>{{ $t('workflowSettingManage.step') }} {{ index + 1 }}</span> | |
| 38 | + | |
| 39 | + <el-button type="text" @click="chooseStaff(item)"> | |
| 40 | + {{ item.staffId ? item.staffName : $t('workflowSettingManage.selectStaff') }} | |
| 41 | + </el-button> | |
| 42 | + | |
| 43 | + <el-radio-group v-model="item.type" @change="chooseType(item)"> | |
| 44 | + <el-radio :label="2">{{ $t('workflowSettingManage.normalFlow') }}</el-radio> | |
| 45 | + <el-radio v-if="index !== 0" :label="1"> | |
| 46 | + {{ $t('workflowSettingManage.countersign') }} | |
| 47 | + </el-radio> | |
| 48 | + </el-radio-group> | |
| 49 | + | |
| 50 | + <el-button type="text" @click="deleteStep(item)"> | |
| 51 | + {{ $t('workflowSettingManage.deleteStep') }} | |
| 52 | + </el-button> | |
| 53 | + | |
| 54 | + <el-button v-if="item.type == 1" type="text" @click="addStaff(item)"> | |
| 55 | + {{ $t('workflowSettingManage.addStaff') }} | |
| 56 | + </el-button> | |
| 57 | + </div> | |
| 58 | + | |
| 59 | + <div v-for="(subItem, subIndex) in item.subStaff" :key="subIndex" class="sub-staff-item"> | |
| 60 | + <el-button type="text" @click="chooseStaff(subItem)"> | |
| 61 | + {{ subItem.staffId ? subItem.staffName : $t('workflowSettingManage.selectStaff') }} | |
| 62 | + </el-button> | |
| 63 | + | |
| 64 | + <el-button type="text" @click="deleteStaff(item, subItem)"> | |
| 65 | + {{ $t('workflowSettingManage.deleteStaff') }} | |
| 66 | + </el-button> | |
| 67 | + </div> | |
| 68 | + </div> | |
| 69 | + </el-form-item> | |
| 70 | + </el-form> | |
| 71 | + | |
| 72 | + <div class="form-actions"> | |
| 73 | + <el-button type="primary" @click="saveWorkflowSettingInfo"> | |
| 74 | + {{ $t('common.submit') }} | |
| 75 | + </el-button> | |
| 76 | + <el-button type="warning" @click="_goBack"> | |
| 77 | + {{ $t('common.back') }} | |
| 78 | + </el-button> | |
| 79 | + </div> | |
| 80 | + </el-card> | |
| 81 | + </el-col> | |
| 82 | + </el-row> | |
| 83 | + | |
| 84 | + <el-row :gutter="20" class="mt-20"> | |
| 85 | + <el-col :span="24"> | |
| 86 | + <el-card> | |
| 87 | + <div slot="header" class="clearfix"> | |
| 88 | + <span>{{ $t('workflowSettingManage.instructions') }}</span> | |
| 89 | + </div> | |
| 90 | + <div v-if="workflowSettingInfo.flowType === '70007'"> | |
| 91 | + <p>1. {{ $t('workflowSettingManage.instruction1') }}</p> | |
| 92 | + <p>2. {{ $t('workflowSettingManage.instruction2') }}</p> | |
| 93 | + <p>3. {{ $t('workflowSettingManage.instruction3') }}</p> | |
| 94 | + <p>4. {{ $t('workflowSettingManage.instruction4') }}</p> | |
| 95 | + </div> | |
| 96 | + <!-- 其他流程类型的说明类似 --> | |
| 97 | + </el-card> | |
| 98 | + </el-col> | |
| 99 | + </el-row> | |
| 100 | + | |
| 101 | + <select-staff ref="selectStaff" @selectStaffs="handleStaffSelected"/> | |
| 102 | + </div> | |
| 103 | +</template> | |
| 104 | + | |
| 105 | +<script> | |
| 106 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 107 | +import SelectStaff from '@/components/staff/SelectStaff' | |
| 108 | +import { | |
| 109 | + getWorkflowSteps, | |
| 110 | + updateWorkflow | |
| 111 | +} from '@/api/system/workflowSettingManageApi' | |
| 112 | + | |
| 113 | +export default { | |
| 114 | + name: 'WorkflowSettingManageList', | |
| 115 | + components: { | |
| 116 | + SelectStaff | |
| 117 | + }, | |
| 118 | + data() { | |
| 119 | + return { | |
| 120 | + communityId: '', | |
| 121 | + workflowSettingInfo: { | |
| 122 | + flowId: '', | |
| 123 | + flowName: '', | |
| 124 | + flowType: '', | |
| 125 | + describle: '', | |
| 126 | + startNodeFinish: 'Y', | |
| 127 | + steps: [] | |
| 128 | + } | |
| 129 | + } | |
| 130 | + }, | |
| 131 | + created() { | |
| 132 | + this.communityId = getCommunityId() | |
| 133 | + this._initWorkflowSettingInfo() | |
| 134 | + }, | |
| 135 | + methods: { | |
| 136 | + async _initWorkflowSettingInfo() { | |
| 137 | + const flowId = this.$route.query.flowId | |
| 138 | + | |
| 139 | + if (!flowId) { | |
| 140 | + this.$message.error(this.$t('workflowSettingManage.invalidOperation')) | |
| 141 | + this.$router.go(-1) | |
| 142 | + return | |
| 143 | + } | |
| 144 | + | |
| 145 | + this.workflowSettingInfo.flowId = flowId | |
| 146 | + this.workflowSettingInfo.flowName = this.$route.query.flowName | |
| 147 | + this.workflowSettingInfo.flowType = this.$route.query.flowType | |
| 148 | + this.workflowSettingInfo.startNodeFinish = this.$route.query.startNodeFinish || 'Y' | |
| 149 | + | |
| 150 | + try { | |
| 151 | + const { data } = await getWorkflowSteps({ | |
| 152 | + communityId: this.communityId, | |
| 153 | + flowId | |
| 154 | + }) | |
| 155 | + this._freshResStep(data) | |
| 156 | + } catch (error) { | |
| 157 | + this.$message.error(error.message) | |
| 158 | + } | |
| 159 | + }, | |
| 160 | + | |
| 161 | + _freshResStep(data) { | |
| 162 | + // 处理步骤数据的逻辑 | |
| 163 | + console.log(data) | |
| 164 | + }, | |
| 165 | + | |
| 166 | + addWorkflowStep() { | |
| 167 | + const step = { | |
| 168 | + seq: this.workflowSettingInfo.steps.length, | |
| 169 | + staffId: '', | |
| 170 | + staffName: '', | |
| 171 | + type: '2', | |
| 172 | + subStaff: [] | |
| 173 | + } | |
| 174 | + this.workflowSettingInfo.steps.push(step) | |
| 175 | + }, | |
| 176 | + | |
| 177 | + chooseStaff(item) { | |
| 178 | + item.from = this._getStaffFromType() | |
| 179 | + this.$refs.selectStaff.open(item) | |
| 180 | + }, | |
| 181 | + | |
| 182 | + _getStaffFromType() { | |
| 183 | + // 根据flowType返回对应的from值 | |
| 184 | + }, | |
| 185 | + | |
| 186 | + _goBack() { | |
| 187 | + this.$router.go(-1) | |
| 188 | + }, | |
| 189 | + | |
| 190 | + deleteStep(step) { | |
| 191 | + this.workflowSettingInfo.steps = this.workflowSettingInfo.steps.filter( | |
| 192 | + s => s.seq !== step.seq | |
| 193 | + ) | |
| 194 | + }, | |
| 195 | + | |
| 196 | + addStaff(step) { | |
| 197 | + step.subStaff.push({ | |
| 198 | + id: this.$uuid(), | |
| 199 | + staffId: '', | |
| 200 | + staffName: '', | |
| 201 | + staffRole: '1001' | |
| 202 | + }) | |
| 203 | + }, | |
| 204 | + | |
| 205 | + deleteStaff(step, subStaff) { | |
| 206 | + step.subStaff = step.subStaff.filter(s => s.id !== subStaff.id) | |
| 207 | + }, | |
| 208 | + | |
| 209 | + chooseType(item) { | |
| 210 | + if (item.type === '1') { | |
| 211 | + item.subStaff = [] | |
| 212 | + } | |
| 213 | + }, | |
| 214 | + | |
| 215 | + handleStaffSelected(staffs) { | |
| 216 | + console.log(staffs) | |
| 217 | + }, | |
| 218 | + | |
| 219 | + async saveWorkflowSettingInfo() { | |
| 220 | + try { | |
| 221 | + await updateWorkflow({ | |
| 222 | + ...this.workflowSettingInfo, | |
| 223 | + communityId: this.communityId | |
| 224 | + }) | |
| 225 | + this.$message.success(this.$t('common.saveSuccess')) | |
| 226 | + this._goBack() | |
| 227 | + } catch (error) { | |
| 228 | + this.$message.error(error.message) | |
| 229 | + } | |
| 230 | + } | |
| 231 | + } | |
| 232 | +} | |
| 233 | +</script> | |
| 234 | + | |
| 235 | +<style lang="scss" scoped> | |
| 236 | +.workflow-setting-container { | |
| 237 | + padding: 20px; | |
| 238 | + | |
| 239 | + .step-item { | |
| 240 | + margin-bottom: 20px; | |
| 241 | + padding: 15px; | |
| 242 | + border: 1px solid #ebeef5; | |
| 243 | + border-radius: 4px; | |
| 244 | + | |
| 245 | + .step-header { | |
| 246 | + display: flex; | |
| 247 | + align-items: center; | |
| 248 | + margin-bottom: 10px; | |
| 249 | + | |
| 250 | + >* { | |
| 251 | + margin-right: 15px; | |
| 252 | + } | |
| 253 | + } | |
| 254 | + | |
| 255 | + .sub-staff-item { | |
| 256 | + margin-left: 40px; | |
| 257 | + margin-bottom: 10px; | |
| 258 | + | |
| 259 | + >* { | |
| 260 | + margin-right: 15px; | |
| 261 | + } | |
| 262 | + } | |
| 263 | + } | |
| 264 | + | |
| 265 | + .form-actions { | |
| 266 | + text-align: right; | |
| 267 | + margin-top: 20px; | |
| 268 | + } | |
| 269 | + | |
| 270 | + .mt-20 { | |
| 271 | + margin-top: 20px; | |
| 272 | + } | |
| 273 | +} | |
| 274 | +</style> | |
| 0 | 275 | \ No newline at end of file | ... | ... |