Commit 4927ce371c725f55015c7996bcb781f1d79c5a60

Authored by wuxw
1 parent 2e0fd29c

开发完成报修功能

Showing 47 changed files with 5512 additions and 77 deletions
src/api/work/myRepairDispatchManageApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 获取维修已办列表
  4 +export function listStaffFinishRepairs(params) {
  5 + return new Promise((resolve, reject) => {
  6 + request({
  7 + url: '/ownerRepair.listStaffFinishRepairs',
  8 + method: 'get',
  9 + params
  10 + }).then(response => {
  11 + const res = response.data
  12 + if (res.code === 0) {
  13 + resolve(res)
  14 + } else {
  15 + reject(new Error(res.msg || '获取维修已办列表失败'))
  16 + }
  17 + }).catch(error => {
  18 + reject(error)
  19 + })
  20 + })
  21 +}
  22 +
  23 +// 获取报修类型列表
  24 +export function listRepairSettings(params) {
  25 + return new Promise((resolve, reject) => {
  26 + request({
  27 + url: 'repair.listRepairSettings',
  28 + method: 'get',
  29 + params
  30 + }).then(response => {
  31 + const res = response.data
  32 + if (res.code === 0) {
  33 + resolve(res)
  34 + } else {
  35 + reject(new Error(res.msg || '获取报修类型失败'))
  36 + }
  37 + }).catch(error => {
  38 + reject(error)
  39 + })
  40 + })
  41 +}
  42 +
  43 +// 结单操作
  44 +export function closeRepairDispatch(data) {
  45 + return new Promise((resolve, reject) => {
  46 + request({
  47 + url: '/ownerRepair.closeRepairDispatch',
  48 + method: 'post',
  49 + data
  50 + }).then(response => {
  51 + const res = response.data
  52 + if (res.code === 0) {
  53 + resolve(res)
  54 + } else {
  55 + reject(new Error(res.msg || '结单操作失败'))
  56 + }
  57 + }).catch(error => {
  58 + reject(error)
  59 + })
  60 + })
  61 +}
0 \ No newline at end of file 62 \ No newline at end of file
src/api/work/ownerRepairManageApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 查询业主报修列表
  4 +export function listOwnerRepairs(params) {
  5 + return new Promise((resolve, reject) => {
  6 + request({
  7 + url: '/ownerRepair.listOwnerRepairs',
  8 + method: 'get',
  9 + params
  10 + }).then(response => {
  11 + const res = response.data
  12 + if (res.code == 0) {
  13 + resolve(res)
  14 + } else {
  15 + reject(new Error(res.msg || '获取业主报修列表失败'))
  16 + }
  17 + }).catch(error => {
  18 + reject(error)
  19 + })
  20 + })
  21 +}
  22 +
  23 +// 添加业主报修
  24 +export function saveOwnerRepair(data) {
  25 + return new Promise((resolve, reject) => {
  26 + request({
  27 + url: '/ownerRepair.saveOwnerRepair',
  28 + method: 'post',
  29 + data
  30 + }).then(response => {
  31 + const res = response.data
  32 + if (res.code == 0) {
  33 + resolve(res)
  34 + } else {
  35 + reject(new Error(res.msg || '添加业主报修失败'))
  36 + }
  37 + }).catch(error => {
  38 + reject(error)
  39 + })
  40 + })
  41 +}
  42 +
  43 +// 更新业主报修
  44 +export function updateOwnerRepair(data) {
  45 + return new Promise((resolve, reject) => {
  46 + request({
  47 + url: '/ownerRepair.updateOwnerRepair',
  48 + method: 'post',
  49 + data
  50 + }).then(response => {
  51 + const res = response.data
  52 + if (res.code == 0) {
  53 + resolve(res)
  54 + } else {
  55 + reject(new Error(res.msg || '更新业主报修失败'))
  56 + }
  57 + }).catch(error => {
  58 + reject(error)
  59 + })
  60 + })
  61 +}
  62 +
  63 +// 删除业主报修
  64 +export function deleteOwnerRepair(data) {
  65 + return new Promise((resolve, reject) => {
  66 + request({
  67 + url: '/ownerRepair.deleteOwnerRepair',
  68 + method: 'post',
  69 + data
  70 + }).then(response => {
  71 + const res = response.data
  72 + if (res.code == 0) {
  73 + resolve(res)
  74 + } else {
  75 + reject(new Error(res.msg || '删除业主报修失败'))
  76 + }
  77 + }).catch(error => {
  78 + reject(error)
  79 + })
  80 + })
  81 +}
  82 +
  83 +// 查询报修类型列表
  84 +export function listRepairSettings(params) {
  85 + return new Promise((resolve, reject) => {
  86 + request({
  87 + url: '/repair.listRepairSettings',
  88 + method: 'get',
  89 + params
  90 + }).then(response => {
  91 + const res = response.data
  92 + if (res.code == 0) {
  93 + resolve(res)
  94 + } else {
  95 + reject(new Error(res.msg || '获取报修类型列表失败'))
  96 + }
  97 + }).catch(error => {
  98 + reject(error)
  99 + })
  100 + })
  101 +}
  102 +
  103 +// 查询楼栋列表
  104 +export function queryFloors(params) {
  105 + return new Promise((resolve, reject) => {
  106 + request({
  107 + url: '/floor.queryFloors',
  108 + method: 'get',
  109 + params
  110 + }).then(response => {
  111 + const res = response.data
  112 + if (res.code == 0) {
  113 + resolve(res)
  114 + } else {
  115 + reject(new Error(res.msg || '获取楼栋列表失败'))
  116 + }
  117 + }).catch(error => {
  118 + reject(error)
  119 + })
  120 + })
  121 +}
  122 +
  123 +// 查询单元列表
  124 +export function queryUnits(params) {
  125 + return new Promise((resolve, reject) => {
  126 + request({
  127 + url: '/unit.queryUnits',
  128 + method: 'get',
  129 + params
  130 + }).then(response => {
  131 + const res = response.data
  132 + if (res.code == 0) {
  133 + resolve(res)
  134 + } else {
  135 + reject(new Error(res.msg || '获取单元列表失败'))
  136 + }
  137 + }).catch(error => {
  138 + reject(error)
  139 + })
  140 + })
  141 +}
  142 +
  143 +// 查询房屋列表
  144 +export function queryRooms(params) {
  145 + return new Promise((resolve, reject) => {
  146 + request({
  147 + url: '/room.queryRooms',
  148 + method: 'get',
  149 + params
  150 + }).then(response => {
  151 + const res = response.data
  152 + if (res.code == 0) {
  153 + resolve(res)
  154 + } else {
  155 + reject(new Error(res.msg || '获取房屋列表失败'))
  156 + }
  157 + }).catch(error => {
  158 + reject(error)
  159 + })
  160 + })
  161 +}
0 \ No newline at end of file 162 \ No newline at end of file
src/api/work/repairDetailApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +import { getCommunityId } from '@/api/community/communityApi'
  3 +
  4 +// 获取工单详情
  5 +export function getRepairDetail(repairId) {
  6 + return new Promise((resolve, reject) => {
  7 + const communityId = getCommunityId()
  8 + request({
  9 + url: '/ownerRepair.listOwnerRepairs',
  10 + method: 'get',
  11 + params: {
  12 + page: 1,
  13 + row: 1,
  14 + communityId,
  15 + repairId
  16 + }
  17 + }).then(response => {
  18 + const res = response.data
  19 + if (res.code === 0) {
  20 + resolve(res.data[0])
  21 + } else {
  22 + reject(new Error(res.msg || '获取工单详情失败'))
  23 + }
  24 + }).catch(error => {
  25 + reject(error)
  26 + })
  27 + })
  28 +}
  29 +
  30 +// 获取工单图片
  31 +export function getRepairPhotos(repairId) {
  32 + return new Promise((resolve, reject) => {
  33 + const communityId = getCommunityId()
  34 + request({
  35 + url: '/ownerRepair.listOwnerRepairs',
  36 + method: 'get',
  37 + params: {
  38 + page: 1,
  39 + row: 1,
  40 + communityId,
  41 + repairId
  42 + }
  43 + }).then(response => {
  44 + const res = response.data
  45 + if (res.code === 0) {
  46 + resolve({
  47 + photos: res.data[0].repairPhotos || [],
  48 + beforePhotos: res.data[0].beforePhotos || [],
  49 + afterPhotos: res.data[0].afterPhotos || []
  50 + })
  51 + } else {
  52 + reject(new Error(res.msg || '获取工单图片失败'))
  53 + }
  54 + }).catch(error => {
  55 + reject(error)
  56 + })
  57 + })
  58 +}
  59 +
  60 +// 获取维修物品
  61 +export function getRepairResources(repairId) {
  62 + return new Promise((resolve, reject) => {
  63 + const communityId = getCommunityId()
  64 + request({
  65 + url: '/resourceStore.listResourceStoreUseRecords',
  66 + method: 'get',
  67 + params: {
  68 + page: 1,
  69 + row: 100,
  70 + communityId,
  71 + repairId
  72 + }
  73 + }).then(response => {
  74 + const res = response.data
  75 + if (res.code === 0) {
  76 + const resources = res.data.map(item => {
  77 + if (item.resId === '666666') {
  78 + return { ...item, rstName: '自定义', specName: '自定义' }
  79 + }
  80 + return item
  81 + })
  82 + resolve(resources)
  83 + } else {
  84 + reject(new Error(res.msg || '获取维修物品失败'))
  85 + }
  86 + }).catch(error => {
  87 + reject(error)
  88 + })
  89 + })
  90 +}
  91 +
  92 +// 获取工单流转
  93 +export function getRepairFlow(repairId) {
  94 + return new Promise((resolve, reject) => {
  95 + const communityId = getCommunityId()
  96 + request({
  97 + url: '/ownerRepair.listRepairStaffs',
  98 + method: 'get',
  99 + params: {
  100 + page: 1,
  101 + row: 100,
  102 + communityId,
  103 + repairId
  104 + }
  105 + }).then(response => {
  106 + const res = response.data
  107 + if (res.code === 0) {
  108 + resolve(res.data)
  109 + } else {
  110 + reject(new Error(res.msg || '获取工单流转失败'))
  111 + }
  112 + }).catch(error => {
  113 + reject(error)
  114 + })
  115 + })
  116 +}
  117 +
  118 +// 获取工单事件
  119 +export function getRepairEvents(repairId) {
  120 + return new Promise((resolve, reject) => {
  121 + const communityId = getCommunityId()
  122 + request({
  123 + url: '/repair.listRepairEvent',
  124 + method: 'get',
  125 + params: {
  126 + page: 1,
  127 + row: 100,
  128 + communityId,
  129 + repairId
  130 + }
  131 + }).then(response => {
  132 + const res = response.data
  133 + if (res.code === 0) {
  134 + resolve(res.data)
  135 + } else {
  136 + reject(new Error(res.msg || '获取工单事件失败'))
  137 + }
  138 + }).catch(error => {
  139 + reject(error)
  140 + })
  141 + })
  142 +}
  143 +
  144 +// 回复评价
  145 +export function replyAppraise(data) {
  146 + return new Promise((resolve, reject) => {
  147 + const communityId = getCommunityId()
  148 + request({
  149 + url: '/repair.replyRepairAppraise',
  150 + method: 'post',
  151 + data: {
  152 + ...data,
  153 + communityId
  154 + }
  155 + }).then(response => {
  156 + const res = response.data
  157 + if (res.code === 0) {
  158 + resolve()
  159 + } else {
  160 + reject(new Error(res.msg || '回复评价失败'))
  161 + }
  162 + }).catch(error => {
  163 + reject(error)
  164 + })
  165 + })
  166 +}
0 \ No newline at end of file 167 \ No newline at end of file
src/api/work/repairDispatchManageApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +import { getCommunityId } from '@/api/community/communityApi'
  3 +
  4 +// 获取报修单列表
  5 +export function listStaffRepairs(params) {
  6 + return new Promise((resolve, reject) => {
  7 + request({
  8 + url: '/ownerRepair.listStaffRepairs',
  9 + method: 'get',
  10 + params: {
  11 + ...params,
  12 + communityId: getCommunityId()
  13 + }
  14 + }).then(response => {
  15 + const res = response.data
  16 + if (res.code === 0) {
  17 + resolve(res)
  18 + } else {
  19 + reject(new Error(res.msg || '获取报修单列表失败'))
  20 + }
  21 + }).catch(error => {
  22 + reject(error)
  23 + })
  24 + })
  25 +}
  26 +
  27 +// 获取报修类型
  28 +export function listRepairSettings(params) {
  29 + return new Promise((resolve, reject) => {
  30 + request({
  31 + url: '/repair.listRepairSettings',
  32 + method: 'get',
  33 + params: {
  34 + ...params,
  35 + communityId: getCommunityId()
  36 + }
  37 + }).then(response => {
  38 + const res = response.data
  39 + if (res.code === 0) {
  40 + resolve(res)
  41 + } else {
  42 + reject(new Error(res.msg || '获取报修类型失败'))
  43 + }
  44 + }).catch(error => {
  45 + reject(error)
  46 + })
  47 + })
  48 +}
  49 +
  50 +// 获取维修师傅列表
  51 +export function listRepairTypeUsers(params) {
  52 + return new Promise((resolve, reject) => {
  53 + request({
  54 + url: '/repair.listRepairTypeUsers',
  55 + method: 'get',
  56 + params: {
  57 + ...params,
  58 + communityId: getCommunityId()
  59 + }
  60 + }).then(response => {
  61 + const res = response.data
  62 + if (res.code === 0) {
  63 + resolve(res)
  64 + } else {
  65 + reject(new Error(res.msg || '获取维修师傅列表失败'))
  66 + }
  67 + }).catch(error => {
  68 + reject(error)
  69 + })
  70 + })
  71 +}
  72 +
  73 +// 报修派单
  74 +export function repairDispatch(data) {
  75 + return new Promise((resolve, reject) => {
  76 + request({
  77 + url: '/ownerRepair.repairDispatch',
  78 + method: 'post',
  79 + data: {
  80 + ...data,
  81 + communityId: getCommunityId()
  82 + }
  83 + }).then(response => {
  84 + const res = response.data
  85 + if (res.code === 0) {
  86 + resolve(res)
  87 + } else {
  88 + reject(new Error(res.msg || '报修派单失败'))
  89 + }
  90 + }).catch(error => {
  91 + reject(error)
  92 + })
  93 + })
  94 +}
  95 +
  96 +// 回访工单
  97 +export function appraiseRepair(data) {
  98 + return new Promise((resolve, reject) => {
  99 + request({
  100 + url: '/ownerRepair.appraiseRepair',
  101 + method: 'post',
  102 + data: {
  103 + ...data,
  104 + communityId: getCommunityId()
  105 + }
  106 + }).then(response => {
  107 + const res = response.data
  108 + if (res.code === 0) {
  109 + resolve(res)
  110 + } else {
  111 + reject(new Error(res.msg || '回访工单失败'))
  112 + }
  113 + }).catch(error => {
  114 + reject(error)
  115 + })
  116 + })
  117 +}
  118 +
  119 +// 暂停报修
  120 +export function repairStop(data) {
  121 + return new Promise((resolve, reject) => {
  122 + request({
  123 + url: '/ownerRepair.repairStop',
  124 + method: 'post',
  125 + data: {
  126 + ...data,
  127 + communityId: getCommunityId()
  128 + }
  129 + }).then(response => {
  130 + const res = response.data
  131 + if (res.code === 0) {
  132 + resolve(res)
  133 + } else {
  134 + reject(new Error(res.msg || '暂停报修失败'))
  135 + }
  136 + }).catch(error => {
  137 + reject(error)
  138 + })
  139 + })
  140 +}
  141 +
  142 +// 启动报修
  143 +export function repairStart(data) {
  144 + return new Promise((resolve, reject) => {
  145 + request({
  146 + url: '/ownerRepair.repairStart',
  147 + method: 'post',
  148 + data: {
  149 + ...data,
  150 + communityId: getCommunityId()
  151 + }
  152 + }).then(response => {
  153 + const res = response.data
  154 + if (res.code === 0) {
  155 + resolve(res)
  156 + } else {
  157 + reject(new Error(res.msg || '启动报修失败'))
  158 + }
  159 + }).catch(error => {
  160 + reject(error)
  161 + })
  162 + })
  163 +}
0 \ No newline at end of file 164 \ No newline at end of file
src/api/work/repairForceFinishManageApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +import { getCommunityId } from '@/api/community/communityApi'
  3 +
  4 +// 获取报修设置列表
  5 +export function listRepairSettings() {
  6 + return new Promise((resolve, reject) => {
  7 + request({
  8 + url: '/repair.listRepairSettings',
  9 + method: 'get',
  10 + params: {
  11 + page: 1,
  12 + row: 50,
  13 + communityId: getCommunityId()
  14 + }
  15 + }).then(response => {
  16 + const res = response.data
  17 + if (res.code == 0) {
  18 + resolve(res.data)
  19 + } else {
  20 + reject(new Error(res.msg || '获取报修设置失败'))
  21 + }
  22 + }).catch(error => {
  23 + reject(error)
  24 + })
  25 + })
  26 +}
  27 +
  28 +// 获取报修池列表
  29 +export function listOwnerRepairs(params) {
  30 + return new Promise((resolve, reject) => {
  31 + request({
  32 + url: '/ownerRepair.listOwnerRepairs',
  33 + method: 'get',
  34 + params: {
  35 + ...params,
  36 + communityId: getCommunityId()
  37 + }
  38 + }).then(response => {
  39 + const res = response.data
  40 + if (res.code == 0) {
  41 + resolve({
  42 + data: res.data,
  43 + total: res.total,
  44 + records: res.records
  45 + })
  46 + } else {
  47 + reject(new Error(res.msg || '获取报修列表失败'))
  48 + }
  49 + }).catch(error => {
  50 + reject(error)
  51 + })
  52 + })
  53 +}
  54 +
  55 +// 获取资源物品类型
  56 +export function listResourceStoreTypes(parentId = '0') {
  57 + return new Promise((resolve, reject) => {
  58 + request({
  59 + url: '/resourceStoreType.listResourceStoreTypes',
  60 + method: 'get',
  61 + params: {
  62 + page: 1,
  63 + row: 100,
  64 + communityId: getCommunityId(),
  65 + parentId,
  66 + giveType: 1
  67 + }
  68 + }).then(response => {
  69 + const res = response.data
  70 + if (res.code == 0) {
  71 + resolve(res.data)
  72 + } else {
  73 + reject(new Error(res.msg || '获取资源物品类型失败'))
  74 + }
  75 + }).catch(error => {
  76 + reject(error)
  77 + })
  78 + })
  79 +}
  80 +
  81 +// 获取用户仓库物品
  82 +export function listUserStorehouses(params) {
  83 + return new Promise((resolve, reject) => {
  84 + request({
  85 + url: '/resourceStore.listUserStorehouses',
  86 + method: 'get',
  87 + params: {
  88 + ...params,
  89 + communityId: getCommunityId(),
  90 + chooseType: "repair",
  91 + flag: 1,
  92 + sign: 1,
  93 + giveType: 1
  94 + }
  95 + }).then(response => {
  96 + const res = response.data
  97 + if (res.code == 0) {
  98 + resolve(res.data)
  99 + } else {
  100 + reject(new Error(res.msg || '获取仓库物品失败'))
  101 + }
  102 + }).catch(error => {
  103 + reject(error)
  104 + })
  105 + })
  106 +}
  107 +
  108 +// 强制回单
  109 +export function repairForceFinish(data) {
  110 + return new Promise((resolve, reject) => {
  111 + request({
  112 + url: '/ownerRepair.repairForceFinish',
  113 + method: 'post',
  114 + data: {
  115 + ...data,
  116 + communityId: getCommunityId()
  117 + }
  118 + }).then(response => {
  119 + const res = response.data
  120 + if (res.code == 0) {
  121 + resolve(res)
  122 + } else {
  123 + reject(new Error(res.msg || '强制回单失败'))
  124 + }
  125 + }).catch(error => {
  126 + reject(error)
  127 + })
  128 + })
  129 +}
  130 +
  131 +// 获取字典数据
  132 +export function getDict(dictType, statusCd) {
  133 + return new Promise((resolve, reject) => {
  134 + request({
  135 + url: '/dict.listDict',
  136 + method: 'get',
  137 + params: {
  138 + dictType,
  139 + statusCd,
  140 + page: 1,
  141 + row: 100
  142 + }
  143 + }).then(response => {
  144 + const res = response.data
  145 + if (res.code == 0) {
  146 + resolve(res.data)
  147 + } else {
  148 + reject(new Error(res.msg || '获取字典失败'))
  149 + }
  150 + }).catch(error => {
  151 + reject(error)
  152 + })
  153 + })
  154 +}
0 \ No newline at end of file 155 \ No newline at end of file
src/api/work/repairPoolManageApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +import { getCommunityId } from '@/api/community/communityApi'
  3 +
  4 +// 查询报修工单池
  5 +export function listRepairPools(params) {
  6 + return new Promise((resolve, reject) => {
  7 + const baseParams = {
  8 + communityId: getCommunityId(),
  9 + page: params.page || 1,
  10 + row: params.row || 10
  11 + }
  12 +
  13 + const queryParams = { ...baseParams, ...params }
  14 +
  15 + if (queryParams.state === 'TIMEOUT') {
  16 + queryParams.state = ''
  17 + queryParams.timeoutFlag = 'Y'
  18 + }
  19 +
  20 + request({
  21 + url: '/ownerRepair.listOwnerRepairs',
  22 + method: 'get',
  23 + params: queryParams
  24 + }).then(response => {
  25 + const res = response.data
  26 + if (res.code === 0) {
  27 + resolve(res)
  28 + } else {
  29 + reject(new Error(res.msg || 'Failed to fetch repair pools'))
  30 + }
  31 + }).catch(error => {
  32 + reject(error)
  33 + })
  34 + })
  35 +}
  36 +
  37 +// 派单
  38 +export function dispatchRepair(data) {
  39 + return new Promise((resolve, reject) => {
  40 + request({
  41 + url: '/ownerRepair.repairDispatch',
  42 + method: 'post',
  43 + data: {
  44 + ...data,
  45 + communityId: getCommunityId()
  46 + }
  47 + }).then(response => {
  48 + const res = response.data
  49 + if (res.code === 0) {
  50 + resolve(res)
  51 + } else {
  52 + reject(new Error(res.msg || 'Dispatch failed'))
  53 + }
  54 + }).catch(error => {
  55 + reject(error)
  56 + })
  57 + })
  58 +}
  59 +
  60 +// 结束工单
  61 +export function endRepair(data) {
  62 + return new Promise((resolve, reject) => {
  63 + request({
  64 + url: '/ownerRepair.repairEnd',
  65 + method: 'post',
  66 + data: {
  67 + ...data,
  68 + communityId: getCommunityId()
  69 + }
  70 + }).then(response => {
  71 + const res = response.data
  72 + if (res.code === 0) {
  73 + resolve(res)
  74 + } else {
  75 + reject(new Error(res.msg || 'End repair failed'))
  76 + }
  77 + }).catch(error => {
  78 + reject(error)
  79 + })
  80 + })
  81 +}
  82 +
  83 +// 更新业主报修
  84 +export function updateOwnerRepair(data) {
  85 + return new Promise((resolve, reject) => {
  86 + request({
  87 + url: '/ownerRepair.updateOwnerRepair',
  88 + method: 'post',
  89 + data: {
  90 + ...data,
  91 + communityId: getCommunityId()
  92 + }
  93 + }).then(response => {
  94 + const res = response.data
  95 + if (res.code === 0) {
  96 + resolve(res)
  97 + } else {
  98 + reject(new Error(res.msg || 'Update failed'))
  99 + }
  100 + }).catch(error => {
  101 + reject(error)
  102 + })
  103 + })
  104 +}
  105 +
  106 +// 删除业主报修
  107 +export function deleteOwnerRepair(data) {
  108 + return new Promise((resolve, reject) => {
  109 + request({
  110 + url: '/ownerRepair.deleteOwnerRepair',
  111 + method: 'post',
  112 + data: {
  113 + ...data,
  114 + communityId: getCommunityId()
  115 + }
  116 + }).then(response => {
  117 + const res = response.data
  118 + if (res.code === 0) {
  119 + resolve(res)
  120 + } else {
  121 + reject(new Error(res.msg || 'Delete failed'))
  122 + }
  123 + }).catch(error => {
  124 + reject(error)
  125 + })
  126 + })
  127 +}
  128 +
  129 +// 抢单
  130 +export function grabbingRepair(data) {
  131 + return new Promise((resolve, reject) => {
  132 + request({
  133 + url: '/ownerRepair.grabbingRepair',
  134 + method: 'post',
  135 + data: {
  136 + ...data,
  137 + communityId: getCommunityId()
  138 + }
  139 + }).then(response => {
  140 + const res = response.data
  141 + if (res.code === 0) {
  142 + resolve(res)
  143 + } else {
  144 + reject(new Error(res.msg || 'Grab order failed'))
  145 + }
  146 + }).catch(error => {
  147 + reject(error)
  148 + })
  149 + })
  150 +}
0 \ No newline at end of file 151 \ No newline at end of file
src/api/work/repairReturnVisitApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 查询报修回访列表
  4 +export function getRepairReturnVisitList(params) {
  5 + return new Promise((resolve, reject) => {
  6 + request({
  7 + url: '/repair/queryRepairReturnVisit',
  8 + method: 'get',
  9 + params
  10 + }).then(response => {
  11 + const res = response.data
  12 + if (res.code === 0) {
  13 + resolve({
  14 + data: res.data,
  15 + total: res.total
  16 + })
  17 + } else {
  18 + reject(new Error(res.msg || '查询报修回访列表失败'))
  19 + }
  20 + }).catch(error => {
  21 + reject(error)
  22 + })
  23 + })
  24 +}
  25 +
  26 +// 保存报修回访记录
  27 +export function saveRepairReturnVisit(data) {
  28 + return new Promise((resolve, reject) => {
  29 + request({
  30 + url: '/repair/saveRepairReturnVisit',
  31 + method: 'post',
  32 + data
  33 + }).then(response => {
  34 + const res = response.data
  35 + if (res.code === 0) {
  36 + resolve(res)
  37 + } else {
  38 + reject(new Error(res.msg || '保存回访记录失败'))
  39 + }
  40 + }).catch(error => {
  41 + reject(error)
  42 + })
  43 + })
  44 +}
  45 +
  46 +// 查询报修类型设置
  47 +export function listRepairSettings(params) {
  48 + return new Promise((resolve, reject) => {
  49 + request({
  50 + url: '/repair.listRepairSettings',
  51 + method: 'get',
  52 + params
  53 + }).then(response => {
  54 + const res = response.data
  55 + if (res.code === 0) {
  56 + resolve({
  57 + data: res.data
  58 + })
  59 + } else {
  60 + reject(new Error(res.msg || '查询报修类型设置失败'))
  61 + }
  62 + }).catch(error => {
  63 + reject(error)
  64 + })
  65 + })
  66 +}
0 \ No newline at end of file 67 \ No newline at end of file
src/api/work/repairTypeUserApi.js
@@ -38,7 +38,7 @@ export function updateRepairTypeUser(data) { @@ -38,7 +38,7 @@ export function updateRepairTypeUser(data) {
38 38
39 return new Promise((resolve, reject) => { 39 return new Promise((resolve, reject) => {
40 request({ 40 request({
41 - url: '/repair/updateRepairTypeUser', 41 + url: '/repair.updateRepairTypeUser',
42 method: 'post', 42 method: 'post',
43 data 43 data
44 }).then(response => { 44 }).then(response => {
@@ -55,7 +55,7 @@ export function deleteRepairTypeUser(data) { @@ -55,7 +55,7 @@ export function deleteRepairTypeUser(data) {
55 55
56 return new Promise((resolve, reject) => { 56 return new Promise((resolve, reject) => {
57 request({ 57 request({
58 - url: '/repair/deleteRepairTypeUser', 58 + url: '/repair.deleteRepairTypeUser',
59 method: 'post', 59 method: 'post',
60 data 60 data
61 }).then(response => { 61 }).then(response => {
@@ -71,7 +71,7 @@ export function listOrgTree(params) { @@ -71,7 +71,7 @@ export function listOrgTree(params) {
71 71
72 return new Promise((resolve, reject) => { 72 return new Promise((resolve, reject) => {
73 request({ 73 request({
74 - url: '/org/listOrgTree', 74 + url: '/org.listOrgTree',
75 method: 'get', 75 method: 'get',
76 params 76 params
77 }).then(response => { 77 }).then(response => {
src/components/work/OrgTreeShow.vue renamed to src/components/org/OrgTreeShow.vue
1 <template> 1 <template>
2 <div> 2 <div>
3 - <el-tree  
4 - ref="orgTree"  
5 - :data="orgs"  
6 - node-key="id"  
7 - :props="defaultProps"  
8 - default-expand-all  
9 - :expand-on-click-node="false"  
10 - @node-click="handleNodeClick"  
11 - ></el-tree> 3 + <el-tree ref="orgTree" :data="orgs" node-key="id" :props="defaultProps" default-expand-all
  4 + :expand-on-click-node="false" @node-click="handleNodeClick"></el-tree>
12 </div> 5 </div>
13 </template> 6 </template>
14 7
@@ -36,7 +29,7 @@ export default { @@ -36,7 +29,7 @@ export default {
36 } 29 }
37 const response = await listOrgTree(params) 30 const response = await listOrgTree(params)
38 if (response.code === 0) { 31 if (response.code === 0) {
39 - this.orgs = response.data 32 + this.orgs = [response.data]
40 } else { 33 } else {
41 this.$message.error(response.msg || this.$t('common.requestFailed')) 34 this.$message.error(response.msg || this.$t('common.requestFailed'))
42 } 35 }
src/components/work/SelectStaff.vue renamed to src/components/staff/SelectStaff.vue
1 <template> 1 <template>
2 - <el-dialog  
3 - :visible="visible"  
4 - :title="$t('selectStaff.title')"  
5 - width="80%"  
6 - @close="handleClose"  
7 - > 2 + <el-dialog :visible="visible" :title="$t('selectStaff.title')" width="80%" @close="handleClose">
8 <el-row :gutter="20"> 3 <el-row :gutter="20">
9 <el-col :span="12" class="border-right"> 4 <el-col :span="12" class="border-right">
10 <div class="text-center"> 5 <div class="text-center">
@@ -19,13 +14,8 @@ @@ -19,13 +14,8 @@
19 <h4>{{ $t('selectStaff.staffInfo') }}</h4> 14 <h4>{{ $t('selectStaff.staffInfo') }}</h4>
20 </div> 15 </div>
21 <div class="padding-left staff padding padding-top-xs"> 16 <div class="padding-left staff padding padding-top-xs">
22 - <div  
23 - v-for="(item, index) in staffs"  
24 - :key="index"  
25 - class="staff-item"  
26 - :class="{'selected': curStaffId === item.staffId}"  
27 - @click="selectStaff(item)"  
28 - > 17 + <div v-for="(item, index) in staffs" :key="index" class="staff-item"
  18 + :class="{'selected': curStaffId == item.userId }" @click="selectStaff(item)">
29 <div> 19 <div>
30 <i class="el-icon-user margin-right-xs"></i> 20 <i class="el-icon-user margin-right-xs"></i>
31 {{ item.name }} 21 {{ item.name }}
@@ -43,7 +33,7 @@ @@ -43,7 +33,7 @@
43 </template> 33 </template>
44 34
45 <script> 35 <script>
46 -import OrgTreeShow from '@/components/work/OrgTreeShow' 36 +import OrgTreeShow from '@/components/org/OrgTreeShow'
47 import { getStaffInfos } from '@/api/work/repairTypeUserApi' 37 import { getStaffInfos } from '@/api/work/repairTypeUserApi'
48 38
49 export default { 39 export default {
@@ -62,8 +52,7 @@ export default { @@ -62,8 +52,7 @@ export default {
62 } 52 }
63 }, 53 },
64 methods: { 54 methods: {
65 - open(staffConfig) {  
66 - this.staffConfig = staffConfig || {} 55 + open() {
67 this.visible = true 56 this.visible = true
68 this.$nextTick(() => { 57 this.$nextTick(() => {
69 this.$refs.orgTree.refreshTree() 58 this.$refs.orgTree.refreshTree()
@@ -83,34 +72,29 @@ export default { @@ -83,34 +72,29 @@ export default {
83 try { 72 try {
84 const params = { 73 const params = {
85 orgId: orgId, 74 orgId: orgId,
86 - row: 50 75 + row: 50,
  76 + page: 1
87 } 77 }
88 - const response = await getStaffInfos(params)  
89 - if (response.code === 0) {  
90 - this.staffs = response.data 78 + const {staffs} = await getStaffInfos(params)
  79 +
  80 + this.staffs = staffs
91 if (this.staffs.length > 0) { 81 if (this.staffs.length > 0) {
92 - this.curStaffId = this.staffs[0].staffId 82 + this.curStaffId = this.staffs[0].userId
93 } 83 }
94 - } else {  
95 - this.$message.error(response.msg || this.$t('common.requestFailed'))  
96 - }  
97 } catch (error) { 84 } catch (error) {
98 console.error('Error loading staff:', error) 85 console.error('Error loading staff:', error)
99 this.$message.error(this.$t('common.requestFailed')) 86 this.$message.error(this.$t('common.requestFailed'))
100 } 87 }
101 }, 88 },
102 selectStaff(staff) { 89 selectStaff(staff) {
103 - this.curStaffId = staff.staffId 90 + this.curStaffId = staff.userId
104 this.selectedStaff = staff 91 this.selectedStaff = staff
105 }, 92 },
106 handleSubmit() { 93 handleSubmit() {
107 if (this.selectedStaff) { 94 if (this.selectedStaff) {
108 - if (this.staffConfig.call) {  
109 - this.staffConfig.call({  
110 - staffId: this.selectedStaff.staffId,  
111 - staffName: this.selectedStaff.name  
112 - })  
113 - } 95 + this.selectedStaff.staffId = this.selectedStaff.userId
  96 + this.selectedStaff.staffName = this.selectedStaff.userName
  97 + this.$emit('selectStaff', this.selectedStaff)
114 this.handleClose() 98 this.handleClose()
115 } else { 99 } else {
116 this.$message.warning(this.$t('selectStaff.selectStaffFirst')) 100 this.$message.warning(this.$t('selectStaff.selectStaffFirst'))
@@ -124,23 +108,28 @@ export default { @@ -124,23 +108,28 @@ export default {
124 .border-right { 108 .border-right {
125 border-right: 1px solid #ebeef5; 109 border-right: 1px solid #ebeef5;
126 } 110 }
  111 +
127 .padding { 112 .padding {
128 padding: 15px; 113 padding: 15px;
129 } 114 }
  115 +
130 .staff-item { 116 .staff-item {
131 padding: 10px; 117 padding: 10px;
132 margin-bottom: 10px; 118 margin-bottom: 10px;
133 - border: 1px solid #ebeef5; 119 +
134 border-radius: 4px; 120 border-radius: 4px;
135 cursor: pointer; 121 cursor: pointer;
136 } 122 }
  123 +
137 .staff-item:hover { 124 .staff-item:hover {
138 background-color: #f5f7fa; 125 background-color: #f5f7fa;
139 } 126 }
140 -.staff-item.selected { 127 +
  128 +.selected {
141 background-color: #ecf5ff; 129 background-color: #ecf5ff;
142 - border-color: #409eff; 130 + border: 1px solid #409eff;
143 } 131 }
  132 +
144 .text-center { 133 .text-center {
145 text-align: center; 134 text-align: center;
146 margin-bottom: 15px; 135 margin-bottom: 15px;
src/components/work/AppraiseRepair.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('repairDispatchManage.returnVisit')"
  4 + :visible.sync="visible"
  5 + width="50%"
  6 + @close="resetForm"
  7 + >
  8 + <el-form :model="form" ref="form" label-width="120px">
  9 + <el-form-item
  10 + :label="$t('repairDispatchManage.returnVisitSuggestion')"
  11 + prop="context"
  12 + :rules="[{ required: true, message: $t('repairDispatchManage.requiredReturnVisitSuggestion'), trigger: 'blur' }]"
  13 + >
  14 + <el-input
  15 + type="textarea"
  16 + :rows="4"
  17 + v-model="form.context"
  18 + :placeholder="$t('repairDispatchManage.requiredReturnVisitSuggestion')"
  19 + />
  20 + </el-form-item>
  21 + </el-form>
  22 +
  23 + <div slot="footer" class="dialog-footer">
  24 + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
  25 + <el-button type="primary" @click="submitForm">{{ $t('common.submit') }}</el-button>
  26 + </div>
  27 + </el-dialog>
  28 +</template>
  29 +
  30 +<script>
  31 +import { appraiseRepair } from '@/api/work/repairDispatchManageApi'
  32 +import { getCommunityId } from '@/api/community/communityApi'
  33 +
  34 +export default {
  35 + name: 'AppraiseRepair',
  36 + data() {
  37 + return {
  38 + visible: false,
  39 + form: {
  40 + repairId: '',
  41 + repairType: '',
  42 + context: '',
  43 + publicArea: '',
  44 + repairChannel: '',
  45 + maintenanceType: ''
  46 + }
  47 + }
  48 + },
  49 + methods: {
  50 + open(row) {
  51 + this.form = {
  52 + repairId: row.repairId,
  53 + repairType: row.repairType,
  54 + publicArea: row.publicArea,
  55 + repairChannel: row.repairChannel,
  56 + maintenanceType: row.maintenanceType,
  57 + context: ''
  58 + }
  59 + this.visible = true
  60 + },
  61 + async submitForm() {
  62 + this.$refs.form.validate(async valid => {
  63 + if (!valid) return
  64 +
  65 + try {
  66 + const data = {
  67 + ...this.form,
  68 + communityId: getCommunityId()
  69 + }
  70 +
  71 + await appraiseRepair(data)
  72 + this.$emit('success')
  73 + this.visible = false
  74 + this.$message.success(this.$t('common.operationSuccess'))
  75 + } catch (error) {
  76 + console.error('回访失败:', error)
  77 + this.$message.error(this.$t('repairDispatchManage.returnVisitFailed'))
  78 + }
  79 + })
  80 + },
  81 + resetForm() {
  82 + this.$refs.form.resetFields()
  83 + this.form = {
  84 + repairId: '',
  85 + repairType: '',
  86 + context: '',
  87 + publicArea: '',
  88 + repairChannel: '',
  89 + maintenanceType: ''
  90 + }
  91 + }
  92 + }
  93 +}
  94 +</script>
0 \ No newline at end of file 95 \ No newline at end of file
src/components/work/DeleteRepairTypeUser.vue
@@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
10 </div> 10 </div>
11 <div slot="footer" class="dialog-footer"> 11 <div slot="footer" class="dialog-footer">
12 <el-button @click="handleClose">{{ $t('common.cancel') }}</el-button> 12 <el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
13 - <el-button type="danger" @click="confirmDelete">{{ $t('common.confirmDelete') }}</el-button> 13 + <el-button type="danger" @click="confirmDelete">{{ $t('common.delete') }}</el-button>
14 </div> 14 </div>
15 </el-dialog> 15 </el-dialog>
16 </template> 16 </template>
src/components/work/EditRepairTypeUser.vue
1 <template> 1 <template>
2 - <el-dialog  
3 - :visible="visible"  
4 - :title="$t('editRepairTypeUser.title')"  
5 - width="50%"  
6 - @close="handleClose"  
7 - > 2 + <el-dialog :visible="visible" :title="$t('editRepairTypeUser.title')" width="50%" @close="handleClose">
8 <el-form ref="form" :model="form" label-width="120px"> 3 <el-form ref="form" :model="form" label-width="120px">
9 <el-form-item :label="$t('editRepairTypeUser.status')" prop="state" required> 4 <el-form-item :label="$t('editRepairTypeUser.status')" prop="state" required>
10 <el-select v-model="form.state" style="width: 100%"> 5 <el-select v-model="form.state" style="width: 100%">
@@ -35,7 +30,8 @@ export default { @@ -35,7 +30,8 @@ export default {
35 form: { 30 form: {
36 typeUserId: '', 31 typeUserId: '',
37 state: '', 32 state: '',
38 - remark: '' 33 + remark: '',
  34 + repairType: ''
39 } 35 }
40 } 36 }
41 }, 37 },
@@ -43,6 +39,7 @@ export default { @@ -43,6 +39,7 @@ export default {
43 open(repairTypeUser) { 39 open(repairTypeUser) {
44 this.form = { 40 this.form = {
45 typeUserId: repairTypeUser.typeUserId, 41 typeUserId: repairTypeUser.typeUserId,
  42 + repairType: repairTypeUser.repairType,
46 state: repairTypeUser.state, 43 state: repairTypeUser.state,
47 remark: repairTypeUser.remark 44 remark: repairTypeUser.remark
48 } 45 }
@@ -53,7 +50,8 @@ export default { @@ -53,7 +50,8 @@ export default {
53 this.form = { 50 this.form = {
54 typeUserId: '', 51 typeUserId: '',
55 state: '', 52 state: '',
56 - remark: '' 53 + remark: '',
  54 + repairType: ''
57 } 55 }
58 }, 56 },
59 async saveChanges() { 57 async saveChanges() {
@@ -62,13 +60,13 @@ export default { @@ -62,13 +60,13 @@ export default {
62 this.$message.warning(this.$t('editRepairTypeUser.statusRequired')) 60 this.$message.warning(this.$t('editRepairTypeUser.statusRequired'))
63 return 61 return
64 } 62 }
65 - 63 +
66 const communityId = await getCommunityId() 64 const communityId = await getCommunityId()
67 const data = { 65 const data = {
68 ...this.form, 66 ...this.form,
69 communityId: communityId 67 communityId: communityId
70 } 68 }
71 - 69 +
72 const response = await updateRepairTypeUser(data) 70 const response = await updateRepairTypeUser(data)
73 if (response.code === 0) { 71 if (response.code === 0) {
74 this.$message.success(this.$t('common.saveSuccess')) 72 this.$message.success(this.$t('common.saveSuccess'))
src/components/work/StartRepair.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('repairDispatchManage.confirmOperation')"
  4 + :visible.sync="visible"
  5 + width="30%"
  6 + >
  7 + <div class="text-center">
  8 + <p>{{ $t('repairDispatchManage.confirmStartRepair') }}</p>
  9 + </div>
  10 +
  11 + <div slot="footer" class="dialog-footer">
  12 + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
  13 + <el-button type="primary" @click="submitForm">{{ $t('common.confirm') }}</el-button>
  14 + </div>
  15 + </el-dialog>
  16 +</template>
  17 +
  18 +<script>
  19 +import { repairStart } from '@/api/work/repairDispatchManageApi'
  20 +import { getCommunityId } from '@/api/community/communityApi'
  21 +
  22 +export default {
  23 + name: 'StartRepair',
  24 + data() {
  25 + return {
  26 + visible: false,
  27 + form: {}
  28 + }
  29 + },
  30 + methods: {
  31 + open(row) {
  32 + this.form = { ...row }
  33 + this.visible = true
  34 + },
  35 + async submitForm() {
  36 + try {
  37 + const data = {
  38 + ...this.form,
  39 + communityId: getCommunityId()
  40 + }
  41 +
  42 + await repairStart(data)
  43 + this.$emit('success')
  44 + this.visible = false
  45 + this.$message.success(this.$t('common.operationSuccess'))
  46 + } catch (error) {
  47 + console.error('启动失败:', error)
  48 + this.$message.error(this.$t('repairDispatchManage.startFailed'))
  49 + }
  50 + }
  51 + }
  52 +}
  53 +</script>
0 \ No newline at end of file 54 \ No newline at end of file
src/components/work/StopRepair.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('repairDispatchManage.pauseRepair')"
  4 + :visible.sync="visible"
  5 + width="50%"
  6 + @close="resetForm"
  7 + >
  8 + <el-form :model="form" ref="form" label-width="120px">
  9 + <el-form-item
  10 + :label="$t('repairDispatchManage.pauseReason')"
  11 + prop="remark"
  12 + :rules="[{ required: true, message: $t('repairDispatchManage.requiredPauseReason'), trigger: 'blur' }]"
  13 + >
  14 + <el-input
  15 + type="textarea"
  16 + :rows="4"
  17 + v-model="form.remark"
  18 + :placeholder="$t('repairDispatchManage.requiredPauseReason')"
  19 + />
  20 + </el-form-item>
  21 + </el-form>
  22 +
  23 + <div slot="footer" class="dialog-footer">
  24 + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
  25 + <el-button type="primary" @click="submitForm">{{ $t('common.submit') }}</el-button>
  26 + </div>
  27 + </el-dialog>
  28 +</template>
  29 +
  30 +<script>
  31 +import { repairStop } from '@/api/work/repairDispatchManageApi'
  32 +import { getCommunityId } from '@/api/community/communityApi'
  33 +
  34 +export default {
  35 + name: 'StopRepair',
  36 + data() {
  37 + return {
  38 + visible: false,
  39 + form: {
  40 + repairId: '',
  41 + repairType: '',
  42 + remark: ''
  43 + }
  44 + }
  45 + },
  46 + methods: {
  47 + open(row) {
  48 + this.form = {
  49 + repairId: row.repairId,
  50 + repairType: row.repairType,
  51 + remark: ''
  52 + }
  53 + this.visible = true
  54 + },
  55 + async submitForm() {
  56 + this.$refs.form.validate(async valid => {
  57 + if (!valid) return
  58 +
  59 + try {
  60 + const data = {
  61 + ...this.form,
  62 + communityId: getCommunityId()
  63 + }
  64 +
  65 + await repairStop(data)
  66 + this.$emit('success')
  67 + this.visible = false
  68 + this.$message.success(this.$t('common.operationSuccess'))
  69 + } catch (error) {
  70 + console.error('暂停失败:', error)
  71 + this.$message.error(this.$t('repairDispatchManage.pauseFailed'))
  72 + }
  73 + })
  74 + },
  75 + resetForm() {
  76 + this.$refs.form.resetFields()
  77 + this.form = {
  78 + repairId: '',
  79 + repairType: '',
  80 + remark: ''
  81 + }
  82 + }
  83 + }
  84 +}
  85 +</script>
0 \ No newline at end of file 86 \ No newline at end of file
src/components/work/addOwnerRepair.vue 0 → 100644
  1 +<template>
  2 + <el-dialog :title="$t('addOwnerRepair.title')" :visible.sync="visible" width="50%" @close="closeDialog">
  3 + <el-form ref="form" :model="formData" label-width="120px">
  4 + <el-form-item :label="$t('addOwnerRepair.repairScope')" prop="repairObjType" required>
  5 + <el-select v-model="formData.repairObjType" style="width:100%" @change="changeRepairObjType">
  6 + <el-option v-for="item in repairObjTypes" :key="item.value" :label="item.label" :value="item.value" />
  7 + </el-select>
  8 + </el-form-item>
  9 +
  10 + <el-form-item v-if="formData.repairObjType && formData.repairObjType !== '001'"
  11 + :label="$t('addOwnerRepair.belongBuilding')">
  12 + <el-select v-model="formData.floorId" style="width:100%" @change="handleFloorChange">
  13 + <el-option v-for="item in floors" :key="item.floorId" :label="item.floorNum" :value="item.floorId" />
  14 + </el-select>
  15 + </el-form-item>
  16 +
  17 + <el-form-item v-if="formData.repairObjType === '003' || formData.repairObjType === '004'"
  18 + :label="$t('addOwnerRepair.belongUnit')">
  19 + <el-select v-model="formData.unitId" style="width:100%" @change="handleUnitChange">
  20 + <el-option v-for="item in units" :key="item.unitId" :label="item.unitNum" :value="item.unitId" />
  21 + </el-select>
  22 + </el-form-item>
  23 +
  24 + <el-form-item v-if="formData.repairObjType === '004'" :label="$t('addOwnerRepair.belongRoom')">
  25 + <el-select v-model="formData.roomId" style="width:100%" @change="handleRoomChange">
  26 + <el-option v-for="item in rooms" :key="item.roomId" :label="item.roomName" :value="item.roomId" />
  27 + </el-select>
  28 + </el-form-item>
  29 +
  30 + <el-form-item :label="$t('addOwnerRepair.repairType')" prop="repairType" required>
  31 + <el-select v-model="formData.repairType" style="width:100%">
  32 + <el-option v-for="item in repairSettings" :key="item.repairType" :label="item.repairTypeName"
  33 + :value="item.repairType" />
  34 + </el-select>
  35 + </el-form-item>
  36 +
  37 + <el-form-item :label="$t('addOwnerRepair.repairName')" prop="repairName" required>
  38 + <el-input v-model.trim="formData.repairName" />
  39 + </el-form-item>
  40 +
  41 + <el-form-item :label="$t('addOwnerRepair.tel')" prop="tel" required>
  42 + <el-input v-model.trim="formData.tel" type="tel" />
  43 + </el-form-item>
  44 +
  45 + <el-form-item :label="$t('addOwnerRepair.appointmentTime')" prop="appointmentTime" required>
  46 + <el-date-picker v-model="formData.appointmentTime" type="datetime" style="width:100%"
  47 + :placeholder="$t('addOwnerRepair.placeholder.appointmentTime')" value-format="yyyy-MM-dd HH:mm:ss" />
  48 + </el-form-item>
  49 +
  50 + <el-form-item :label="$t('addOwnerRepair.context')" prop="context" required>
  51 + <el-input v-model.trim="formData.context" type="textarea" rows="4" />
  52 + </el-form-item>
  53 + </el-form>
  54 +
  55 + <span slot="footer" class="dialog-footer">
  56 + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
  57 + <el-button type="primary" @click="saveOwnerRepairInfo">{{ $t('common.submit') }}</el-button>
  58 + </span>
  59 + </el-dialog>
  60 +</template>
  61 +
  62 +<script>
  63 +import * as ownerRepairManageApi from '@/api/work/ownerRepairManageApi'
  64 +import { getCommunityName } from '@/api/community/communityApi'
  65 +import {getFloors, getUnits, queryRooms} from '@/api/room/roomApi'
  66 +import {getDateYYYYMMDD} from '@/utils/dateUtil'
  67 +
  68 +export default {
  69 + name: 'AddOwnerRepair',
  70 + data() {
  71 + return {
  72 + visible: false,
  73 + formData: {
  74 + repairType: '',
  75 + repairName: '',
  76 + tel: '',
  77 + appointmentTime: '',
  78 + context: '',
  79 + repairObjType: '',
  80 + repairObjId: '',
  81 + repairObjName: '',
  82 + repairChannel: 'T',
  83 + floorId: '',
  84 + unitId: '',
  85 + roomId: ''
  86 + },
  87 + repairSettings: [],
  88 + repairObjTypes: [
  89 + { value: '001', label: this.$t('addOwnerRepair.community') },
  90 + { value: '002', label: this.$t('addOwnerRepair.building') },
  91 + { value: '003', label: this.$t('addOwnerRepair.unit') },
  92 + { value: '004', label: this.$t('addOwnerRepair.room') }
  93 + ],
  94 + floors:[],
  95 + units:[],
  96 + rooms:[]
  97 + }
  98 + },
  99 + methods: {
  100 + open() {
  101 + this.visible = true
  102 + this.resetForm()
  103 + this.formData.appointmentTime =getDateYYYYMMDD()
  104 + this.listRepairSettings('T')
  105 + },
  106 + closeDialog() {
  107 + this.$refs.form.resetFields()
  108 + },
  109 + resetForm() {
  110 + this.formData = {
  111 + repairType: '',
  112 + repairName: '',
  113 + tel: '',
  114 + appointmentTime: '',
  115 + context: '',
  116 + repairObjType: '',
  117 + repairObjId: '',
  118 + repairObjName: '',
  119 + repairChannel: 'T'
  120 + }
  121 + },
  122 + handleFloorChange(floorId) {
  123 + if (this.formData.repairObjType == '002') {
  124 + this.formData.repairObjId = floorId
  125 + this.formData.repairObjName = this.floors.find(item => item.floorId == floorId).floorNum + this.$t('addOwnerRepair.buildingSuffix')
  126 + }else{
  127 + this.listUnits()
  128 + }
  129 + },
  130 + handleUnitChange(unitId) {
  131 + if (this.formData.repairObjType == '003') {
  132 + this.formData.repairObjId = unitId
  133 + this.formData.repairObjName = this.units.find(item => item.unitId == unitId).unitNum + this.$t('addOwnerRepair.unitSuffix')
  134 + }else{
  135 + this.listRooms()
  136 + }
  137 + },
  138 + handleRoomChange(roomId) {
  139 + if (this.formData.repairObjType === '004') {
  140 + this.formData.repairObjId = roomId
  141 + this.formData.repairObjName =this.rooms.find(item => item.roomId == roomId).roomNum + this.$t('addOwnerRepair.roomSuffix')
  142 + }
  143 + },
  144 + changeRepairObjType() {
  145 + this.formData.repairType = ''
  146 + const publicArea = this.formData.repairObjType === '004' ? 'F' : 'T'
  147 + this.listRepairSettings(publicArea)
  148 + this.listFloors()
  149 + },
  150 + async listFloors() {
  151 + const params = {
  152 + communityId: this.getCommunityId(),
  153 + page: 1,
  154 + row: 200
  155 + }
  156 + const { apiFloorDataVoList } = await getFloors(params);
  157 + this.floors = apiFloorDataVoList
  158 + },
  159 + async listUnits() {
  160 + const params = {
  161 + communityId: this.getCommunityId(),
  162 + floorId: this.formData.floorId,
  163 + page: 1,
  164 + row: 200
  165 + }
  166 + const data = await getUnits(params);
  167 + this.units = data
  168 + },
  169 + async listRooms() {
  170 + const params = {
  171 + communityId: this.getCommunityId(),
  172 + unitId: this.formData.unitId,
  173 + page: 1,
  174 + row: 500
  175 + }
  176 + const { rooms } = await queryRooms(params);
  177 + this.rooms = rooms
  178 + },
  179 + async listRepairSettings(publicArea) {
  180 + const params = {
  181 + page: 1,
  182 + row: 50,
  183 + publicArea: publicArea,
  184 + communityId: this.getCommunityId()
  185 + }
  186 + const { data } = await ownerRepairManageApi.listRepairSettings(params);
  187 + this.repairSettings = data
  188 + },
  189 + saveOwnerRepairInfo() {
  190 + if (this.formData.repairObjType === '001') {
  191 + this.formData.repairObjId = this.getCommunityId()
  192 + this.formData.repairObjName = getCommunityName()
  193 + }
  194 + this.formData.communityId = this.getCommunityId()
  195 +
  196 + this.$refs.form.validate(valid => {
  197 + if (valid) {
  198 + ownerRepairManageApi.saveOwnerRepair(this.formData).then(res => {
  199 + if (res.code === 0) {
  200 + this.$message.success(this.$t('common.addSuccess'))
  201 + this.visible = false
  202 + this.$emit('success')
  203 + } else {
  204 + this.$message.error(res.msg)
  205 + }
  206 + })
  207 + }
  208 + })
  209 + }
  210 + }
  211 +}
  212 +</script>
0 \ No newline at end of file 213 \ No newline at end of file
src/components/work/chooseSingleResource.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('chooseSingleResource.title')"
  4 + :visible.sync="visible"
  5 + width="60%"
  6 + @close="closeDialog"
  7 + >
  8 + <el-form label-width="120px">
  9 + <el-form-item :label="$t('chooseSingleResource.goodsType')">
  10 + <el-select
  11 + v-model="form.rsId"
  12 + placeholder="请选择"
  13 + style="width:100%"
  14 + @change="listSonResourceStoreType"
  15 + >
  16 + <el-option
  17 + v-for="item in resourceStoreTypes"
  18 + :key="item.rstId"
  19 + :label="item.name"
  20 + :value="item.rstId"
  21 + />
  22 + </el-select>
  23 + </el-form-item>
  24 +
  25 + <template v-if="form.isCustom">
  26 + <el-form-item :label="$t('chooseSingleResource.goodsName')">
  27 + <el-input
  28 + v-model="form.customGoodsName"
  29 + :placeholder="$t('chooseSingleResource.goodsNamePlaceholder')"
  30 + />
  31 + </el-form-item>
  32 + </template>
  33 +
  34 + <template v-else>
  35 + <el-form-item :label="$t('chooseSingleResource.secondaryCategory')">
  36 + <el-select
  37 + v-model="form.rstId"
  38 + placeholder="请选择"
  39 + style="width:100%"
  40 + @change="choseGoods"
  41 + >
  42 + <el-option
  43 + v-for="item in sonResourceStoreTypes"
  44 + :key="item.rstId"
  45 + :label="item.name"
  46 + :value="item.rstId"
  47 + />
  48 + </el-select>
  49 + </el-form-item>
  50 +
  51 + <el-form-item v-if="form.rstId" :label="$t('chooseSingleResource.goods')">
  52 + <el-select
  53 + v-model="form.resId"
  54 + placeholder="请选择"
  55 + style="width:100%"
  56 + @change="chosePrice"
  57 + >
  58 + <el-option
  59 + v-for="item in resourceStores"
  60 + :key="item.resId"
  61 + :label="item.resName"
  62 + :value="item.resId"
  63 + />
  64 + </el-select>
  65 + </el-form-item>
  66 + </template>
  67 +
  68 + <template v-if="form.resId || form.isCustom">
  69 + <el-form-item :label="$t('chooseSingleResource.quantity')">
  70 + <el-input-number
  71 + v-model="form.useNumber"
  72 + :min="1"
  73 + label="数量"
  74 + />
  75 + </el-form-item>
  76 + </template>
  77 + </el-form>
  78 +
  79 + <div slot="footer" class="dialog-footer">
  80 + <el-button @click="closeDialog">{{ $t('chooseSingleResource.cancel') }}</el-button>
  81 + <el-button type="primary" @click="confirmSelection">{{ $t('chooseSingleResource.confirm') }}</el-button>
  82 + </div>
  83 + </el-dialog>
  84 +</template>
  85 +
  86 +<script>
  87 +import { listResourceStoreTypes, listUserStorehouses } from '@/api/work/repairForceFinishManageApi'
  88 +
  89 +export default {
  90 + name: 'ChooseSingleResource',
  91 + props: {
  92 + visible: {
  93 + type: Boolean,
  94 + default: false
  95 + },
  96 + maintenanceType: {
  97 + type: String,
  98 + default: ''
  99 + },
  100 + repairId: {
  101 + type: String,
  102 + default: ''
  103 + }
  104 + },
  105 + data() {
  106 + return {
  107 + form: {
  108 + maintenanceType: '',
  109 + resourceStoreTypes: [],
  110 + sonResourceStoreTypes: [],
  111 + rstId: '',
  112 + rsId: '',
  113 + resId: '',
  114 + repairId: '',
  115 + selectedGoodsInfo: {},
  116 + resourceStores: [],
  117 + isCustom: false,
  118 + customGoodsName: '',
  119 + price: '',
  120 + outLowPrice: '',
  121 + outHighPrice: '',
  122 + useNumber: 1,
  123 + sign: ''
  124 + }
  125 + }
  126 + },
  127 + watch: {
  128 + maintenanceType(newVal) {
  129 + this.form.maintenanceType = newVal
  130 + },
  131 + repairId(newVal) {
  132 + this.form.repairId = newVal
  133 + }
  134 + },
  135 + mounted() {
  136 + this.listResourceStoreType()
  137 + },
  138 + methods: {
  139 + open(param) {
  140 + this.form = {
  141 + ...this.form,
  142 + maintenanceType: param.maintenanceType,
  143 + repairId: param.repairId || '',
  144 + sign: param.sign || ''
  145 + }
  146 + this.listResourceStoreType()
  147 + },
  148 + closeDialog() {
  149 + this.$emit('update:visible', false)
  150 + },
  151 + async listResourceStoreType() {
  152 + try {
  153 + const data = await listResourceStoreTypes('0')
  154 + this.form.resourceStoreTypes = [...data, { rstId: 'custom', name: '自定义' }]
  155 + } catch (error) {
  156 + console.error('获取资源类型失败:', error)
  157 + this.$message.error('获取资源类型失败')
  158 + }
  159 + },
  160 + async listSonResourceStoreType() {
  161 + if (this.form.rsId === 'custom') {
  162 + this.form.isCustom = true
  163 + return
  164 + }
  165 +
  166 + this.form.isCustom = false
  167 + try {
  168 + const data = await listResourceStoreTypes(this.form.rsId)
  169 + this.form.sonResourceStoreTypes = data
  170 + } catch (error) {
  171 + console.error('获取子资源类型失败:', error)
  172 + this.$message.error('获取子资源类型失败')
  173 + }
  174 + },
  175 + async choseGoods() {
  176 + if (!this.form.rstId) return
  177 +
  178 + try {
  179 + const params = {
  180 + repairId: this.form.repairId,
  181 + rstId: this.form.rstId,
  182 + sign: this.form.sign
  183 + }
  184 + const data = await listUserStorehouses(params)
  185 + this.form.resourceStores = data
  186 + } catch (error) {
  187 + console.error('获取商品失败:', error)
  188 + this.$message.error('获取商品失败')
  189 + }
  190 + },
  191 + chosePrice() {
  192 + const selected = this.form.resourceStores.find(item => item.resId === this.form.resId)
  193 + if (selected) {
  194 + this.form.selectedGoodsInfo = selected
  195 + if (selected.outLowPrice === selected.outHighPrice) {
  196 + this.form.price = selected.outLowPrice
  197 + } else {
  198 + this.form.price = ''
  199 + }
  200 + this.form.outLowPrice = selected.outLowPrice
  201 + this.form.outHighPrice = selected.outHighPrice
  202 + }
  203 + },
  204 + confirmSelection() {
  205 + if (this.validateForm()) {
  206 + this.$emit('confirm', {
  207 + ...this.form.selectedGoodsInfo,
  208 + price: this.form.price,
  209 + useNumber: this.form.useNumber,
  210 + isCustom: this.form.isCustom,
  211 + customGoodsName: this.form.customGoodsName
  212 + })
  213 + this.closeDialog()
  214 + }
  215 + },
  216 + validateForm() {
  217 + if (this.form.isCustom) {
  218 + if (!this.form.customGoodsName) {
  219 + this.$message.warning('请填写商品名')
  220 + return false
  221 + }
  222 + if (this.form.maintenanceType === '1001' && !this.form.price) {
  223 + this.$message.warning('请填写价格')
  224 + return false
  225 + }
  226 + } else {
  227 + if (!this.form.rsId) {
  228 + this.$message.warning('请选择商品类型')
  229 + return false
  230 + }
  231 + if (!this.form.rstId) {
  232 + this.$message.warning('请选择二级分类')
  233 + return false
  234 + }
  235 + if (!this.form.resId) {
  236 + this.$message.warning('请选择商品')
  237 + return false
  238 + }
  239 + }
  240 + return true
  241 + }
  242 + }
  243 +}
  244 +</script>
0 \ No newline at end of file 245 \ No newline at end of file
src/components/work/closeOrder.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('closeOrder.closeOrderInfo')"
  4 + :visible.sync="visible"
  5 + width="50%"
  6 + :before-close="handleClose"
  7 + >
  8 + <el-form ref="form" :model="closeOrderInfo" label-width="120px">
  9 + <el-form-item :label="$t('closeOrder.closeStatus')" prop="state" required>
  10 + <el-select
  11 + v-model="closeOrderInfo.state"
  12 + :placeholder="$t('closeOrder.selectCloseStatus')"
  13 + style="width:100%;"
  14 + >
  15 + <el-option
  16 + :label="$t('closeOrder.closeOrder')"
  17 + value="1100"
  18 + />
  19 + <el-option
  20 + :label="$t('closeOrder.returnOrder')"
  21 + value="1200"
  22 + />
  23 + </el-select>
  24 + </el-form-item>
  25 +
  26 + <el-form-item :label="$t('closeOrder.reason')" prop="remark">
  27 + <el-input
  28 + v-model="closeOrderInfo.remark"
  29 + type="textarea"
  30 + :placeholder="$t('closeOrder.reasonPlaceholder')"
  31 + :rows="4"
  32 + />
  33 + </el-form-item>
  34 + </el-form>
  35 +
  36 + <div slot="footer" class="dialog-footer">
  37 + <el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
  38 + <el-button type="primary" @click="_closeOrderSubmit">{{ $t('common.submit') }}</el-button>
  39 + </div>
  40 + </el-dialog>
  41 + </template>
  42 +
  43 + <script>
  44 + export default {
  45 + name: 'CloseOrder',
  46 + data() {
  47 + return {
  48 + visible: false,
  49 + closeOrderInfo: {
  50 + state: '',
  51 + remark: ''
  52 + }
  53 + }
  54 + },
  55 + watch: {
  56 + 'closeOrderInfo.state': {
  57 + handler(val) {
  58 + if (val === '1100') {
  59 + this.closeOrderInfo.remark = this.$t('closeOrder.processed')
  60 + } else {
  61 + this.closeOrderInfo.remark = ''
  62 + }
  63 + },
  64 + deep: true
  65 + }
  66 + },
  67 + methods: {
  68 + open() {
  69 + this.visible = true
  70 + this.resetForm()
  71 + },
  72 +
  73 + handleClose() {
  74 + this.visible = false
  75 + this.resetForm()
  76 + },
  77 +
  78 + resetForm() {
  79 + this.closeOrderInfo = {
  80 + state: '',
  81 + remark: ''
  82 + }
  83 + if (this.$refs.form) {
  84 + this.$refs.form.resetFields()
  85 + }
  86 + },
  87 +
  88 + _closeOrderSubmit() {
  89 + this.$refs.form.validate(valid => {
  90 + if (valid) {
  91 + this.$emit('success', this.closeOrderInfo)
  92 + this.handleClose()
  93 + }
  94 + })
  95 + }
  96 + }
  97 + }
  98 + </script>
  99 +
  100 + <style scoped>
  101 + .dialog-footer {
  102 + text-align: right;
  103 + }
  104 + </style>
0 \ No newline at end of file 105 \ No newline at end of file
src/components/work/deleteOwnerRepair.vue 0 → 100644
  1 +<template>
  2 + <el-dialog :title="$t('common.delete')" :visible.sync="visible" width="30%">
  3 + <p>{{ $t('common.deleteConfirm') }}</p>
  4 +
  5 + <span slot="footer" class="dialog-footer">
  6 + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
  7 + <el-button type="primary" @click="confirmDelete">{{ $t('common.confirm') }}</el-button>
  8 + </span>
  9 + </el-dialog>
  10 +</template>
  11 +
  12 +<script>
  13 +import { deleteOwnerRepair } from '@/api/work/repairPoolManageApi'
  14 +import { getCommunityId } from '@/api/community/communityApi'
  15 +
  16 +export default {
  17 + name: 'DeleteOwnerRepair',
  18 + data() {
  19 + return {
  20 + visible: false,
  21 + repairId: ''
  22 + }
  23 + },
  24 + methods: {
  25 + open(repairId) {
  26 + this.repairId = repairId
  27 + this.visible = true
  28 + },
  29 +
  30 + async confirmDelete() {
  31 + try {
  32 + await deleteOwnerRepair({
  33 + repairId: this.repairId,
  34 + communityId: getCommunityId()
  35 + })
  36 +
  37 + this.$message.success(this.$t('common.deleteSuccess'))
  38 + this.visible = false
  39 + this.$emit('success')
  40 + } catch (error) {
  41 + console.error('Delete repair failed:', error)
  42 + }
  43 + }
  44 + }
  45 +}
  46 +</script>
0 \ No newline at end of file 47 \ No newline at end of file
src/components/work/dispatchRepair.vue 0 → 100644
  1 +<template>
  2 + <el-dialog :title="$t('repairPoolManage.dispatch')" :visible.sync="visible" width="50%" @close="resetForm">
  3 + <el-form ref="form" :model="formData" label-width="120px">
  4 + <el-form-item v-if="formData.action === 'BACK'" :label="$t('repairPoolManage.repairPerson')" prop="staffName">
  5 + <el-input v-model="formData.staffName" disabled />
  6 + </el-form-item>
  7 +
  8 + <el-form-item v-else :label="$t('repairPoolManage.repairPerson')" prop="staffId"
  9 + :rules="[{ required: true, message: $t('repairPoolManage.selectRepairPerson'), trigger: 'blur' }]">
  10 + <el-select v-model="formData.staffId" style="width:100%">
  11 + <el-option v-for="item in repairTypeUsers" :key="item.staffId" :label="item.staffName" :value="item.staffId" />
  12 + </el-select>
  13 + </el-form-item>
  14 +
  15 + <el-form-item :label="$t('repairPoolManage.operationSuggestions')" prop="context"
  16 + :rules="[{ required: true, message: $t('repairPoolManage.operationSuggestions'), trigger: 'blur' }]">
  17 + <el-input v-model="formData.context" type="textarea" :rows="4"
  18 + :placeholder="$t('repairPoolManage.processingOpinionsPlaceholder')" />
  19 + </el-form-item>
  20 + </el-form>
  21 +
  22 + <span slot="footer" class="dialog-footer">
  23 + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
  24 + <el-button type="primary" @click="submitForm">{{ $t('common.submit') }}</el-button>
  25 + </span>
  26 + </el-dialog>
  27 +</template>
  28 +
  29 +<script>
  30 +import { dispatchRepair } from '@/api/work/repairPoolManageApi'
  31 +import {listRepairTypeUsers} from '@/api/work/repairTypeUserApi'
  32 +import { getCommunityId } from '@/api/community/communityApi'
  33 +
  34 +export default {
  35 + name: 'DispatchRepair',
  36 + data() {
  37 + return {
  38 + visible: false,
  39 + formData: {
  40 + repairId: '',
  41 + repairType: '',
  42 + staffId: '',
  43 + staffName: '',
  44 + context: '',
  45 + action: '',
  46 + repairTypeUsers: [],
  47 + currentUserId: ''
  48 + },
  49 + repairTypeUsers: []
  50 + }
  51 + },
  52 + methods: {
  53 + open(repair) {
  54 + this.formData = {
  55 + ...this.formData,
  56 + repairId: repair.repairId,
  57 + repairType: repair.repairType,
  58 + action: repair.action || 'DISPATCH'
  59 + }
  60 +
  61 + if (repair.action === 'BACK') {
  62 + this.formData.staffId = repair.preStaffId
  63 + this.formData.staffName = repair.preStaffName
  64 + }
  65 +
  66 + this.listRepairTypeUsers()
  67 + this.visible = true
  68 + },
  69 +
  70 + async listRepairTypeUsers() {
  71 + try {
  72 + const params = {
  73 + page: 1,
  74 + row: 50,
  75 + communityId: getCommunityId(),
  76 + repairType: this.formData.repairType,
  77 + state: '9999'
  78 + }
  79 +
  80 + const res = await listRepairTypeUsers(params)
  81 + this.repairTypeUsers = res.data || []
  82 + } catch (error) {
  83 + console.error('Failed to fetch repair type users:', error)
  84 + }
  85 + },
  86 +
  87 + async submitForm() {
  88 + this.$refs.form.validate(async valid => {
  89 + if (valid) {
  90 + try {
  91 + const staff = this.repairTypeUsers.find(item => item.staffId === this.formData.staffId)
  92 + if (staff) {
  93 + this.formData.staffName = staff.staffName
  94 + }
  95 +
  96 + if (this.formData.action === 'TRANSFER' && this.formData.currentUserId === this.formData.staffId) {
  97 + this.$message.error(this.$t('repairPoolManage.cannotTransferSelf'))
  98 + return
  99 + }
  100 +
  101 + const data = {
  102 + ...this.formData,
  103 + communityId: getCommunityId()
  104 + }
  105 +
  106 + await dispatchRepair(data)
  107 + this.$message.success(this.$t('common.operationSuccess'))
  108 + this.visible = false
  109 + this.$emit('success')
  110 + } catch (error) {
  111 + console.error('Dispatch repair failed:', error)
  112 + }
  113 + }
  114 + })
  115 + },
  116 +
  117 + resetForm() {
  118 + this.$refs.form.resetFields()
  119 + this.formData = {
  120 + repairId: '',
  121 + repairType: '',
  122 + staffId: '',
  123 + staffName: '',
  124 + context: '',
  125 + action: '',
  126 + repairTypeUsers: [],
  127 + currentUserId: this.$store.getters.userId
  128 + }
  129 + }
  130 + }
  131 +}
  132 +</script>
0 \ No newline at end of file 133 \ No newline at end of file
src/components/work/editOwnerRepair.vue 0 → 100644
  1 +<template>
  2 + <el-dialog :title="$t('repairPoolManage.modify')" :visible.sync="visible" width="50%" @close="resetForm">
  3 + <el-form ref="form" :model="formData" label-width="120px">
  4 + <el-form-item :label="$t('repairPoolManage.repairType')" prop="repairType"
  5 + :rules="[{ required: true, message: $t('repairPoolManage.repairTypeRequired'), trigger: 'change' }]">
  6 + <el-select v-model="formData.repairType" style="width:100%">
  7 + <el-option v-for="item in repairSettings" :key="item.repairType" :label="item.repairTypeName"
  8 + :value="item.repairType" />
  9 + </el-select>
  10 + </el-form-item>
  11 +
  12 + <el-form-item :label="$t('repairPoolManage.repairPerson')" prop="repairName"
  13 + :rules="[{ required: true, message: $t('repairPoolManage.repairPersonRequired'), trigger: 'blur' }]">
  14 + <el-input v-model="formData.repairName" />
  15 + </el-form-item>
  16 +
  17 + <el-form-item :label="$t('repairPoolManage.contact')" prop="tel" :rules="[
  18 + { required: true, message: $t('repairPoolManage.contactRequired'), trigger: 'blur' },
  19 + { pattern: /^1[3-9]\d{9}$/, message: $t('repairPoolManage.contactFormat'), trigger: 'blur' }
  20 + ]">
  21 + <el-input v-model="formData.tel" type="tel" />
  22 + </el-form-item>
  23 +
  24 + <el-form-item :label="$t('repairPoolManage.appointmentTime')" prop="appointmentTime"
  25 + :rules="[{ required: true, message: $t('repairPoolManage.appointmentTimeRequired'), trigger: 'blur' }]">
  26 + <el-date-picker v-model="formData.appointmentTime" type="datetime" style="width:100%"
  27 + value-format="yyyy-MM-dd HH:mm:ss" :placeholder="$t('repairPoolManage.selectAppointmentTime')" />
  28 + </el-form-item>
  29 +
  30 + <el-form-item :label="$t('repairPoolManage.repairContent')" prop="context"
  31 + :rules="[{ required: true, message: $t('repairPoolManage.repairContentRequired'), trigger: 'blur' }]">
  32 + <el-input v-model="formData.context" type="textarea" :rows="4"
  33 + :placeholder="$t('repairPoolManage.repairContentPlaceholder')" />
  34 + </el-form-item>
  35 + </el-form>
  36 +
  37 + <span slot="footer" class="dialog-footer">
  38 + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
  39 + <el-button type="primary" @click="submitForm">{{ $t('common.submit') }}</el-button>
  40 + </span>
  41 + </el-dialog>
  42 +</template>
  43 +
  44 +<script>
  45 +import { updateOwnerRepair,listRepairSettings } from '@/api/work/ownerRepairManageApi'
  46 +import { getCommunityId } from '@/api/community/communityApi'
  47 +
  48 +export default {
  49 + name: 'EditOwnerRepair',
  50 + data() {
  51 + return {
  52 + visible: false,
  53 + formData: {
  54 + repairId: '',
  55 + repairType: '',
  56 + repairName: '',
  57 + tel: '',
  58 + appointmentTime: '',
  59 + context: '',
  60 + repairObjType: '',
  61 + repairObjId: '',
  62 + repairObjName: ''
  63 + },
  64 + repairSettings: []
  65 + }
  66 + },
  67 + methods: {
  68 + open(repair) {
  69 + this.formData = { ...repair }
  70 + this.changeRepairObjType()
  71 + this.listRepairSettings()
  72 + this.visible = true
  73 + },
  74 +
  75 + async listRepairSettings() {
  76 + try {
  77 + const publicArea = this.formData.repairObjType === '004' ? 'F' : 'T'
  78 + const params = {
  79 + page: 1,
  80 + row: 50,
  81 + communityId: getCommunityId(),
  82 + publicArea
  83 + }
  84 +
  85 + const res = await listRepairSettings(params)
  86 + this.repairSettings = res.data || []
  87 + } catch (error) {
  88 + console.error('Failed to fetch repair settings:', error)
  89 + }
  90 + },
  91 +
  92 + changeRepairObjType() {
  93 + // 根据报修对象类型设置公共区域标志
  94 + this.listRepairSettings()
  95 + },
  96 +
  97 + async submitForm() {
  98 + this.$refs.form.validate(async valid => {
  99 + if (valid) {
  100 + try {
  101 + if (this.formData.repairObjType === '001') {
  102 + this.formData.repairObjId = getCommunityId()
  103 + this.formData.repairObjName = this.$store.getters.community.name
  104 + }
  105 +
  106 + const data = {
  107 + ...this.formData,
  108 + communityId: getCommunityId()
  109 + }
  110 +
  111 + await updateOwnerRepair(data)
  112 + this.$message.success(this.$t('common.updateSuccess'))
  113 + this.visible = false
  114 + this.$emit('success')
  115 + } catch (error) {
  116 + console.error('Update owner repair failed:', error)
  117 + }
  118 + }
  119 + })
  120 + },
  121 +
  122 + resetForm() {
  123 + this.$refs.form.resetFields()
  124 + this.formData = {
  125 + repairId: '',
  126 + repairType: '',
  127 + repairName: '',
  128 + tel: '',
  129 + appointmentTime: '',
  130 + context: '',
  131 + repairObjType: '',
  132 + repairObjId: '',
  133 + repairObjName: ''
  134 + }
  135 + }
  136 + }
  137 +}
  138 +</script>
0 \ No newline at end of file 139 \ No newline at end of file
src/components/work/endRepair.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('repairPoolManage.end')"
  4 + :visible.sync="visible"
  5 + width="50%"
  6 + @close="resetForm"
  7 + >
  8 + <el-form ref="form" :model="formData" label-width="120px">
  9 + <el-form-item
  10 + :label="$t('repairPoolManage.endReason')"
  11 + prop="context"
  12 + :rules="[{ required: true, message: $t('repairPoolManage.endReason'), trigger: 'blur' }]"
  13 + >
  14 + <el-input
  15 + v-model="formData.context"
  16 + type="textarea"
  17 + :rows="4"
  18 + :placeholder="$t('repairPoolManage.endReason')"
  19 + />
  20 + </el-form-item>
  21 + </el-form>
  22 +
  23 + <span slot="footer" class="dialog-footer">
  24 + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
  25 + <el-button type="primary" @click="submitForm">{{ $t('common.submit') }}</el-button>
  26 + </span>
  27 + </el-dialog>
  28 +</template>
  29 +
  30 +<script>
  31 +import { endRepair } from '@/api/work/repairPoolManageApi'
  32 +import { getCommunityId } from '@/api/community/communityApi'
  33 +
  34 +export default {
  35 + name: 'EndRepair',
  36 + data() {
  37 + return {
  38 + visible: false,
  39 + formData: {
  40 + repairId: '',
  41 + context: ''
  42 + }
  43 + }
  44 + },
  45 + methods: {
  46 + open(repair) {
  47 + this.formData.repairId = repair.repairId
  48 + this.visible = true
  49 + },
  50 +
  51 + async submitForm() {
  52 + this.$refs.form.validate(async valid => {
  53 + if (valid) {
  54 + try {
  55 + const data = {
  56 + ...this.formData,
  57 + communityId: getCommunityId()
  58 + }
  59 +
  60 + await endRepair(data)
  61 + this.$message.success(this.$t('common.operationSuccess'))
  62 + this.visible = false
  63 + this.$emit('success')
  64 + } catch (error) {
  65 + console.error('End repair failed:', error)
  66 + }
  67 + }
  68 + })
  69 + },
  70 +
  71 + resetForm() {
  72 + this.$refs.form.resetFields()
  73 + this.formData = {
  74 + repairId: '',
  75 + context: ''
  76 + }
  77 + }
  78 + }
  79 +}
  80 +</script>
0 \ No newline at end of file 81 \ No newline at end of file
src/components/work/forceFinishRepair.vue 0 → 100644
  1 +<template>
  2 + <el-dialog :title="$t('forceFinishRepair.title')" :visible.sync="visible" width="60%" @close="closeDialog">
  3 + <el-form label-width="120px">
  4 + <el-form-item v-if="form.repairObjType !== '004'" :label="$t('forceFinishRepair.useMaterial')">
  5 + <el-select v-model="form.maintenanceType" placeholder="请选择" style="width:100%">
  6 + <template v-for="item in maintenanceTypes">
  7 + <el-option :key="item.statusCd" :label="item.name" :value="item.statusCd"
  8 + v-if="item.statusCd !== '1001' && item.statusCd !== '1002'" />
  9 + </template>
  10 + </el-select>
  11 + </el-form-item>
  12 +
  13 + <el-form-item v-else :label="$t('forceFinishRepair.maintenanceType')">
  14 + <el-select v-model="form.maintenanceType" placeholder="请选择" style="width:100%">
  15 + <template v-for="item in maintenanceTypes">
  16 + <el-option :key="item.statusCd" :label="item.name" :value="item.statusCd"
  17 + v-if="item.statusCd !== '1003' && item.statusCd !== '1004'" />
  18 + </template>
  19 + </el-select>
  20 + </el-form-item>
  21 +
  22 + <template v-if="form.maintenanceType === '1001' || form.maintenanceType === '1003'">
  23 + <el-form-item :label="$t('forceFinishRepair.goodsType')">
  24 + <el-select v-model="form.rsId" placeholder="请选择" style="width:100%" @change="listSonResourceStoreType">
  25 + <el-option v-for="item in resourceStoreTypes" :key="item.rstId" :label="item.name" :value="item.rstId" />
  26 + </el-select>
  27 + </el-form-item>
  28 +
  29 + <template v-if="form.isCustom">
  30 + <el-form-item :label="$t('forceFinishRepair.goodsName')">
  31 + <el-input v-model="form.customGoodsName" :placeholder="$t('forceFinishRepair.goodsNamePlaceholder')" />
  32 + </el-form-item>
  33 +
  34 + <el-form-item v-if="form.maintenanceType === '1001'" :label="$t('forceFinishRepair.customPrice')">
  35 + <el-input v-model="form.price" placeholder="必填,请填写自定义价格" />
  36 + </el-form-item>
  37 + </template>
  38 +
  39 + <template v-else>
  40 + <el-form-item :label="$t('forceFinishRepair.secondaryCategory')">
  41 + <el-select v-model="form.rstId" placeholder="请选择" style="width:100%" @change="choseGoods">
  42 + <el-option v-for="item in sonResourceStoreTypes" :key="item.rstId" :label="item.name" :value="item.rstId" />
  43 + </el-select>
  44 + </el-form-item>
  45 +
  46 + <el-form-item v-if="form.rstId" :label="$t('forceFinishRepair.goods')">
  47 + <el-select v-model="form.resId" placeholder="请选择" style="width:100%" @change="chosePrice">
  48 + <el-option v-for="item in resourceStores" :key="item.resId" :label="item.resName" :value="item.resId" />
  49 + </el-select>
  50 + </el-form-item>
  51 + </template>
  52 +
  53 + <template v-if="form.resId || form.isCustom">
  54 + <el-form-item :label="$t('forceFinishRepair.quantity')">
  55 + <el-input-number v-model="form.useNumber" :min="1" label="数量" />
  56 + </el-form-item>
  57 +
  58 + <el-form-item v-if="form.maintenanceType === '1001'" :label="$t('forceFinishRepair.paymentMethod')">
  59 + <el-select v-model="form.payType" placeholder="请选择" style="width:100%">
  60 + <el-option v-for="item in payTypes" :key="item.statusCd" :label="item.name" :value="item.statusCd" />
  61 + </el-select>
  62 + </el-form-item>
  63 + </template>
  64 + </template>
  65 +
  66 + <el-form-item :label="$t('forceFinishRepair.explanation')">
  67 + <el-input v-model="form.context" type="textarea" :placeholder="$t('forceFinishRepair.explanationPlaceholder')"
  68 + :rows="4" />
  69 + </el-form-item>
  70 + </el-form>
  71 +
  72 + <div slot="footer" class="dialog-footer">
  73 + <el-button @click="closeDialog">{{ $t('forceFinishRepair.cancel') }}</el-button>
  74 + <el-button type="primary" @click="submitForceFinish">{{ $t('forceFinishRepair.submit') }}</el-button>
  75 + </div>
  76 + </el-dialog>
  77 +</template>
  78 +
  79 +<script>
  80 +import {
  81 + listResourceStoreTypes,
  82 + listUserStorehouses,
  83 + repairForceFinish,
  84 + getDict
  85 +} from '@/api/work/repairForceFinishManageApi'
  86 +
  87 +export default {
  88 + name: 'ForceFinishRepair',
  89 + props: {
  90 + visible: {
  91 + type: Boolean,
  92 + default: false
  93 + }
  94 + },
  95 + data() {
  96 + return {
  97 + form: {
  98 + repairId: '',
  99 + repairType: '',
  100 + repairObjType: '',
  101 + context: '',
  102 + maintenanceType: '',
  103 + resId: '',
  104 + rsId: '',
  105 + isCustom: false,
  106 + customGoodsName: '',
  107 + price: '',
  108 + useNumber: 1,
  109 + rstId: '',
  110 + payType: '',
  111 + selectedGoodsInfo: {},
  112 + payTypes: [],
  113 + resourceStores: [],
  114 + sonResourceStoreTypes: [],
  115 + resourceStoreTypes: [],
  116 + maintenanceTypes: []
  117 + },
  118 + payTypes: [],
  119 + maintenanceTypes: []
  120 + }
  121 + },
  122 + mounted() {
  123 + this.loadDictData()
  124 + },
  125 + methods: {
  126 + open(repair) {
  127 + this.form = {
  128 + ...this.form,
  129 + repairId: repair.repairId,
  130 + repairType: repair.repairType,
  131 + repairObjType: repair.repairObjType
  132 + }
  133 + this.listResourceStoreType()
  134 + },
  135 + closeDialog() {
  136 + this.$emit('update:visible', false)
  137 + },
  138 + async loadDictData() {
  139 + try {
  140 + this.maintenanceTypes = await getDict('r_repair_pool', 'maintenance_type')
  141 + this.payTypes = await getDict('r_repair_pool', 'pay_type')
  142 + } catch (error) {
  143 + console.error('获取字典数据失败:', error)
  144 + this.$message.error('获取字典数据失败')
  145 + }
  146 + },
  147 + async listResourceStoreType() {
  148 + try {
  149 + const data = await listResourceStoreTypes('0')
  150 + this.form.resourceStoreTypes = [...data, { rstId: 'custom', name: '自定义' }]
  151 + } catch (error) {
  152 + console.error('获取资源类型失败:', error)
  153 + this.$message.error('获取资源类型失败')
  154 + }
  155 + },
  156 + async listSonResourceStoreType() {
  157 + if (this.form.rsId === 'custom') {
  158 + this.form.isCustom = true
  159 + return
  160 + }
  161 +
  162 + this.form.isCustom = false
  163 + try {
  164 + const data = await listResourceStoreTypes(this.form.rsId)
  165 + this.form.sonResourceStoreTypes = data
  166 + } catch (error) {
  167 + console.error('获取子资源类型失败:', error)
  168 + this.$message.error('获取子资源类型失败')
  169 + }
  170 + },
  171 + async choseGoods() {
  172 + if (!this.form.rstId) return
  173 +
  174 + try {
  175 + const params = {
  176 + repairId: this.form.repairId,
  177 + rstId: this.form.rstId
  178 + }
  179 + const data = await listUserStorehouses(params)
  180 + this.form.resourceStores = data
  181 + } catch (error) {
  182 + console.error('获取商品失败:', error)
  183 + this.$message.error('获取商品失败')
  184 + }
  185 + },
  186 + chosePrice() {
  187 + const selected = this.form.resourceStores.find(item => item.resId === this.form.resId)
  188 + if (selected) {
  189 + this.form.selectedGoodsInfo = selected
  190 + if (selected.outLowPrice === selected.outHighPrice) {
  191 + this.form.price = selected.outLowPrice
  192 + } else {
  193 + this.form.price = ''
  194 + }
  195 + }
  196 + },
  197 + async submitForceFinish() {
  198 + if (this.validateForm()) {
  199 + try {
  200 + await repairForceFinish(this.form)
  201 + this.$message.success('强制回单成功')
  202 + this.closeDialog()
  203 + this.$emit('success')
  204 + } catch (error) {
  205 + console.error('强制回单失败:', error)
  206 + this.$message.error('强制回单失败')
  207 + }
  208 + }
  209 + },
  210 + validateForm() {
  211 + if (!this.form.maintenanceType) {
  212 + this.$message.warning('请选择维修类型')
  213 + return false
  214 + }
  215 +
  216 + if (this.form.maintenanceType === '1001' || this.form.maintenanceType === '1003') {
  217 + if (!this.form.rsId) {
  218 + this.$message.warning('请选择商品类型')
  219 + return false
  220 + }
  221 +
  222 + if (this.form.isCustom) {
  223 + if (!this.form.customGoodsName) {
  224 + this.$message.warning('请填写商品名')
  225 + return false
  226 + }
  227 + if (this.form.maintenanceType === '1001' && !this.form.price) {
  228 + this.$message.warning('请填写价格')
  229 + return false
  230 + }
  231 + } else {
  232 + if (!this.form.rstId) {
  233 + this.$message.warning('请选择二级分类')
  234 + return false
  235 + }
  236 + if (!this.form.resId) {
  237 + this.$message.warning('请选择商品')
  238 + return false
  239 + }
  240 + }
  241 +
  242 + if (this.form.maintenanceType === '1001' && !this.form.payType) {
  243 + this.$message.warning('请选择支付方式')
  244 + return false
  245 + }
  246 + }
  247 +
  248 + if (!this.form.context) {
  249 + this.$message.warning('请填写说明')
  250 + return false
  251 + }
  252 +
  253 + return true
  254 + }
  255 + }
  256 +}
  257 +</script>
0 \ No newline at end of file 258 \ No newline at end of file
src/components/work/repairDetailEvent.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-table :data="events" border style="width: 100%">
  4 + <el-table-column prop="eventTypeName" :label="$t('repairDetailEvent.eventType')" align="center" />
  5 + <el-table-column prop="staffName" :label="$t('repairDetailEvent.staff')" align="center" />
  6 + <el-table-column prop="remark" :label="$t('repairDetailEvent.description')" align="center" />
  7 + <el-table-column prop="createTime" :label="$t('repairDetailEvent.createTime')" align="center" />
  8 + </el-table>
  9 + </div>
  10 +</template>
  11 +
  12 +<script>
  13 +import { getRepairEvents } from '@/api/work/repairDetailApi'
  14 +
  15 +export default {
  16 + name: 'RepairDetailEvent',
  17 + props: {
  18 + repairId: {
  19 + type: String,
  20 + required: true
  21 + }
  22 + },
  23 + data() {
  24 + return {
  25 + events: []
  26 + }
  27 + },
  28 + methods: {
  29 + async loadData() {
  30 + try {
  31 + this.events = await getRepairEvents(this.repairId)
  32 + } catch (error) {
  33 + this.$message.error(error.message)
  34 + }
  35 + }
  36 + }
  37 +}
  38 +</script>
0 \ No newline at end of file 39 \ No newline at end of file
src/components/work/repairDetailPhotos.vue 0 → 100644
  1 +<template>
  2 + <div class="margin-top">
  3 + <div v-if="photos.length > 0" class="row padding">
  4 + <div class="text-title">{{ $t('repairDetail.orderPhotos') }}</div>
  5 + <div v-for="(item, index) in photos" :key="index" class="form-group margin-left">
  6 + <el-image style="width: 120px; height: 120px;" :src="item.url" :preview-src-list="[item.url]" fit="cover"
  7 + @click="openFile(item)"></el-image>
  8 + </div>
  9 + </div>
  10 +
  11 + <div v-if="beforePhotos.length > 0" class="row padding">
  12 + <div class="text-title">{{ $t('repairDetail.beforeRepairPhotos') }}</div>
  13 + <div v-for="(item, index) in beforePhotos" :key="index" class="form-group margin-left">
  14 + <el-image style="width: 120px; height: 120px;" :src="item.url" :preview-src-list="[item.url]" fit="cover"
  15 + @click="openFile(item)"></el-image>
  16 + </div>
  17 + </div>
  18 +
  19 + <div v-if="afterPhotos.length > 0" class="row padding">
  20 + <div class="text-title">{{ $t('repairDetail.afterRepairPhotos') }}</div>
  21 + <div v-for="(item, index) in afterPhotos" :key="index" class="form-group margin-left">
  22 + <el-image style="width: 120px; height: 120px;" :src="item.url" :preview-src-list="[item.url]" fit="cover"
  23 + @click="openFile(item)"></el-image>
  24 + </div>
  25 + </div>
  26 + </div>
  27 +</template>
  28 +
  29 +<script>
  30 +import { getRepairPhotos } from '@/api/work/repairDetailApi'
  31 +
  32 +export default {
  33 + name: 'RepairDetailPhotos',
  34 + props: {
  35 + repairId: {
  36 + type: String,
  37 + required: true
  38 + }
  39 + },
  40 + data() {
  41 + return {
  42 + photos: [],
  43 + beforePhotos: [],
  44 + afterPhotos: []
  45 + }
  46 + },
  47 + methods: {
  48 + async loadData() {
  49 + try {
  50 + console.log(this.repairId)
  51 + const data = await getRepairPhotos(this.repairId)
  52 + this.photos = data.photos
  53 + this.beforePhotos = data.beforePhotos
  54 + this.afterPhotos = data.afterPhotos
  55 + } catch (error) {
  56 + this.$message.error(error.message)
  57 + }
  58 + },
  59 + openFile(item) {
  60 + this.$emit('show-image', item)
  61 + }
  62 + }
  63 +}
  64 +</script>
  65 +
  66 +<style scoped>
  67 +.padding {
  68 + padding: 10px 0;
  69 +}
  70 +
  71 +.text-title {
  72 + font-size: 16px;
  73 + font-weight: bold;
  74 + margin-bottom: 10px;
  75 +}
  76 +
  77 +.margin-left {
  78 + margin-left: 10px;
  79 + display: inline-block;
  80 +}
  81 +</style>
0 \ No newline at end of file 82 \ No newline at end of file
src/components/work/repairDetailResource.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-table :data="resources" border style="width: 100%">
  4 + <el-table-column prop="resId" :label="$t('repairDetailResource.itemCode')" align="center" />
  5 + <el-table-column :label="$t('repairDetailResource.itemType')" align="center">
  6 + <template slot-scope="scope">
  7 + {{ scope.row.parentRstName }} > {{ scope.row.rstName }}
  8 + </template>
  9 + </el-table-column>
  10 + <el-table-column prop="resourceStoreName" :label="$t('repairDetailResource.itemName')" align="center" />
  11 + <el-table-column :label="$t('repairDetailResource.specification')" align="center">
  12 + <template slot-scope="scope">
  13 + {{ scope.row.specName || '-' }}
  14 + </template>
  15 + </el-table-column>
  16 + <el-table-column :label="$t('repairDetailResource.quantity')" align="center">
  17 + <template slot-scope="scope">
  18 + {{ scope.row.quantity }}{{ scope.row.miniUnitCodeName }}
  19 + </template>
  20 + </el-table-column>
  21 + <el-table-column :label="$t('repairDetailResource.price')" align="center">
  22 + <template slot-scope="scope">
  23 + {{ scope.row.unitPrice || '-' }}
  24 + </template>
  25 + </el-table-column>
  26 + <el-table-column prop="createUserName" :label="$t('repairDetailResource.user')" align="center" />
  27 + <el-table-column prop="createTime" :label="$t('repairDetailResource.time')" align="center" />
  28 + </el-table>
  29 + </div>
  30 +</template>
  31 +
  32 +<script>
  33 +import { getRepairResources } from '@/api/work/repairDetailApi'
  34 +
  35 +export default {
  36 + name: 'RepairDetailResource',
  37 + props: {
  38 + repairId: {
  39 + type: String,
  40 + required: true
  41 + }
  42 + },
  43 + data() {
  44 + return {
  45 + resources: []
  46 + }
  47 + },
  48 + methods: {
  49 + async loadData() {
  50 + try {
  51 + this.resources = await getRepairResources(this.repairId)
  52 + } catch (error) {
  53 + this.$message.error(error.message)
  54 + }
  55 + }
  56 + }
  57 +}
  58 +</script>
0 \ No newline at end of file 59 \ No newline at end of file
src/components/work/repairDetailUser.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-table :data="users" border style="width: 100%">
  4 + <el-table-column :label="$t('repairDetailUser.serial')" align="center" width="80">
  5 + <template slot-scope="scope">
  6 + {{ scope.$index + 1 }}
  7 + </template>
  8 + </el-table-column>
  9 + <el-table-column prop="staffName" :label="$t('repairDetailUser.handler')" align="center" />
  10 + <el-table-column :label="$t('repairDetailUser.status')" align="center">
  11 + <template slot-scope="scope">
  12 + <template v-if="(scope.row.state === '10009' || scope.row.state === '12000') && scope.row.payTypeName">
  13 + {{ scope.row.stateName }}({{ scope.row.payTypeName }})
  14 + </template>
  15 + <template v-else>
  16 + {{ scope.row.stateName }}
  17 + <span v-if="scope.row.state === '10007'">
  18 + (<a href="javascript:void(0)" @click="openRepairAppraise(scope.row)">{{ $t('repairDetailUser.reply') }}</a>)
  19 + </span>
  20 + </template>
  21 + </template>
  22 + </el-table-column>
  23 + <el-table-column prop="startTime" :label="$t('repairDetailUser.startTime')" align="center" />
  24 + <el-table-column prop="endTime" :label="$t('repairDetailUser.endTime')" align="center" />
  25 + <el-table-column prop="duration" :label="$t('repairDetailUser.duration')" align="center" />
  26 + <el-table-column prop="context" :label="$t('repairDetailUser.opinion')" align="center" />
  27 + </el-table>
  28 + </div>
  29 +</template>
  30 +
  31 +<script>
  32 +import { getRepairFlow } from '@/api/work/repairDetailApi'
  33 +
  34 +export default {
  35 + name: 'RepairDetailUser',
  36 + props: {
  37 + repairId: {
  38 + type: String,
  39 + required: true
  40 + }
  41 + },
  42 + data() {
  43 + return {
  44 + users: []
  45 + }
  46 + },
  47 + methods: {
  48 + async loadData() {
  49 + try {
  50 + this.users = await getRepairFlow(this.repairId)
  51 + } catch (error) {
  52 + this.$message.error(error.message)
  53 + }
  54 + },
  55 + openRepairAppraise(row) {
  56 + this.$emit('open-appraise', row)
  57 + }
  58 + }
  59 +}
  60 +</script>
0 \ No newline at end of file 61 \ No newline at end of file
src/components/work/visitOwnerRepair.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('repairReturnVisit.visitTitle')"
  4 + :visible.sync="visible"
  5 + width="600px"
  6 + @close="resetForm"
  7 + >
  8 + <el-form
  9 + ref="visitForm"
  10 + :model="formData"
  11 + :rules="rules"
  12 + label-width="100px"
  13 + label-position="right"
  14 + >
  15 + <el-form-item
  16 + :label="$t('repairReturnVisit.satisfaction')"
  17 + prop="visitType"
  18 + >
  19 + <el-select
  20 + v-model="formData.visitType"
  21 + :placeholder="$t('repairReturnVisit.satisfactionPlaceholder')"
  22 + style="width:100%"
  23 + >
  24 + <el-option
  25 + :label="$t('repairReturnVisit.satisfied')"
  26 + value="1001"
  27 + />
  28 + <el-option
  29 + :label="$t('repairReturnVisit.unsatisfied')"
  30 + value="2002"
  31 + />
  32 + </el-select>
  33 + </el-form-item>
  34 +
  35 + <el-form-item
  36 + :label="$t('repairReturnVisit.visitContent')"
  37 + prop="context"
  38 + >
  39 + <el-input
  40 + v-model="formData.context"
  41 + type="textarea"
  42 + :rows="4"
  43 + :placeholder="$t('repairReturnVisit.visitContentPlaceholder')"
  44 + />
  45 + </el-form-item>
  46 + </el-form>
  47 +
  48 + <div slot="footer" class="dialog-footer">
  49 + <el-button @click="visible = false">
  50 + {{ $t('common.cancel') }}
  51 + </el-button>
  52 + <el-button type="primary" @click="submitVisit">
  53 + {{ $t('common.submit') }}
  54 + </el-button>
  55 + </div>
  56 + </el-dialog>
  57 +</template>
  58 +
  59 +<script>
  60 +import { saveRepairReturnVisit } from '@/api/work/repairReturnVisitApi'
  61 +
  62 +export default {
  63 + name: 'VisitOwnerRepair',
  64 + data() {
  65 + return {
  66 + visible: false,
  67 + formData: {
  68 + repairId: '',
  69 + visitType: '',
  70 + context: ''
  71 + },
  72 + rules: {
  73 + visitType: [
  74 + { required: true, message: this.$t('repairReturnVisit.satisfactionRequired'), trigger: 'change' }
  75 + ],
  76 + context: [
  77 + { required: true, message: this.$t('repairReturnVisit.visitContentRequired'), trigger: 'blur' },
  78 + { max: 1000, message: this.$t('repairReturnVisit.visitContentMaxLength'), trigger: 'blur' }
  79 + ]
  80 + }
  81 + }
  82 + },
  83 + methods: {
  84 + open(repairPool) {
  85 + this.formData = {
  86 + repairId: repairPool.repairId,
  87 + visitType: '',
  88 + context: '',
  89 + communityId: this.$store.getters.communityId
  90 + }
  91 + this.visible = true
  92 + },
  93 + resetForm() {
  94 + this.$refs.visitForm.resetFields()
  95 + },
  96 + submitVisit() {
  97 + this.$refs.visitForm.validate(async valid => {
  98 + if (valid) {
  99 + try {
  100 + await saveRepairReturnVisit(this.formData)
  101 + this.$message.success(this.$t('common.submitSuccess'))
  102 + this.visible = false
  103 + this.$emit('success')
  104 + } catch (error) {
  105 + console.error('保存回访记录失败:', error)
  106 + }
  107 + }
  108 + })
  109 + }
  110 + }
  111 +}
  112 +</script>
0 \ No newline at end of file 113 \ No newline at end of file
src/i18n/commonLang.js
@@ -44,7 +44,8 @@ export const messages = { @@ -44,7 +44,8 @@ export const messages = {
44 hour:'hour', 44 hour:'hour',
45 more:'More', 45 more:'More',
46 tip:'Tip', 46 tip:'Tip',
47 - selectFile:'Select File' 47 + selectFile:'Select File',
  48 + change:'Change'
48 } 49 }
49 }, 50 },
50 zh: { 51 zh: {
@@ -92,7 +93,8 @@ export const messages = { @@ -92,7 +93,8 @@ export const messages = {
92 hour:'时', 93 hour:'时',
93 more:'更多', 94 more:'更多',
94 tip:'提示', 95 tip:'提示',
95 - selectFile:'选择文件' 96 + selectFile:'选择文件',
  97 + change:'变更'
96 } 98 }
97 } 99 }
98 } 100 }
99 \ No newline at end of file 101 \ No newline at end of file
src/i18n/index.js
@@ -163,6 +163,14 @@ import { messages as listCarFeeMessages } from &#39;../views/fee/listCarFeeLang&#39; @@ -163,6 +163,14 @@ import { messages as listCarFeeMessages } from &#39;../views/fee/listCarFeeLang&#39;
163 import { messages as repairSettingMessages } from '../views/work/repairSettingLang' 163 import { messages as repairSettingMessages } from '../views/work/repairSettingLang'
164 import { messages as repairTypeUserMessages } from '../views/work/repairTypeUserLang' 164 import { messages as repairTypeUserMessages } from '../views/work/repairTypeUserLang'
165 165
  166 +import { messages as ownerRepairManageMessages } from '../views/work/ownerRepairManageLang'
  167 +import { messages as repairPoolManageMessages } from '../views/work/repairPoolManageLang'
  168 +import { messages as repairDetailMessages } from '../views/work/repairDetailLang'
  169 +import { messages as repairDispatchManageMessages } from '../views/work/repairDispatchManageLang'
  170 +import { messages as myRepairDispatchManageMessages } from '../views/work/myRepairDispatchManageLang'
  171 +import { messages as repairReturnVisitMessages } from '../views/work/repairReturnVisitLang'
  172 +import { messages as repairForceFinishManageMessages } from '../views/work/repairForceFinishManageLang'
  173 +
166 Vue.use(VueI18n) 174 Vue.use(VueI18n)
167 175
168 // 合并所有语言配置 176 // 合并所有语言配置
@@ -328,6 +336,14 @@ const messages = { @@ -328,6 +336,14 @@ const messages = {
328 ...listCarFeeMessages.en, 336 ...listCarFeeMessages.en,
329 ...repairSettingMessages.en, 337 ...repairSettingMessages.en,
330 ...repairTypeUserMessages.en, 338 ...repairTypeUserMessages.en,
  339 +
  340 + ...ownerRepairManageMessages.en,
  341 + ...repairPoolManageMessages.en,
  342 + ...repairDetailMessages.en,
  343 + ...repairDispatchManageMessages.en,
  344 + ...myRepairDispatchManageMessages.en,
  345 + ...repairReturnVisitMessages.en,
  346 + ...repairForceFinishManageMessages.en,
331 }, 347 },
332 zh: { 348 zh: {
333 ...loginMessages.zh, 349 ...loginMessages.zh,
@@ -490,6 +506,14 @@ const messages = { @@ -490,6 +506,14 @@ const messages = {
490 ...listCarFeeMessages.zh, 506 ...listCarFeeMessages.zh,
491 ...repairSettingMessages.zh, 507 ...repairSettingMessages.zh,
492 ...repairTypeUserMessages.zh, 508 ...repairTypeUserMessages.zh,
  509 +
  510 + ...ownerRepairManageMessages.zh,
  511 + ...repairPoolManageMessages.zh,
  512 + ...repairDetailMessages.zh,
  513 + ...repairDispatchManageMessages.zh,
  514 + ...myRepairDispatchManageMessages.zh,
  515 + ...repairReturnVisitMessages.zh,
  516 + ...repairForceFinishManageMessages.zh,
493 } 517 }
494 } 518 }
495 519
src/router/index.js
@@ -802,10 +802,45 @@ const routes = [ @@ -802,10 +802,45 @@ const routes = [
802 component: () => import('@/views/work/repairSettingList.vue') 802 component: () => import('@/views/work/repairSettingList.vue')
803 }, 803 },
804 { 804 {
805 - path:'/views/work/repairTypeUser',  
806 - name:'/views/work/repairTypeUser', 805 + path: '/views/work/repairTypeUser',
  806 + name: '/views/work/repairTypeUser',
807 component: () => import('@/views/work/repairTypeUserList.vue') 807 component: () => import('@/views/work/repairTypeUserList.vue')
808 - }, 808 + },
  809 + {
  810 + path: '/pages/property/ownerRepairManage',
  811 + name: '/pages/property/ownerRepairManage',
  812 + component: () => import('@/views/work/ownerRepairManageList.vue')
  813 + },
  814 + {
  815 + path: '/pages/property/repairPoolManage',
  816 + name: '/pages/property/repairPoolManage',
  817 + component: () => import('@/views/work/repairPoolManageList.vue')
  818 + },
  819 + {
  820 + path: '/views/work/repairDetail',
  821 + name: '/views/work/repairDetail',
  822 + component: () => import('@/views/work/repairDetailList.vue')
  823 + },
  824 + {
  825 + path: '/pages/property/repairDispatchManage',
  826 + name: '/pages/property/repairDispatchManage',
  827 + component: () => import('@/views/work/repairDispatchManageList.vue')
  828 + },
  829 + {
  830 + path: '/pages/property/myRepairDispatchManage',
  831 + name: '/pages/property/myRepairDispatchManage',
  832 + component: () => import('@/views/work/myRepairDispatchManageList.vue')
  833 + },
  834 + {
  835 + path: '/pages/property/repairReturnVisit',
  836 + name: '/pages/property/repairReturnVisit',
  837 + component: () => import('@/views/work/repairReturnVisitList.vue')
  838 + },
  839 + {
  840 + path: '/pages/property/repairForceFinishManage',
  841 + name: '/pages/property/repairForceFinishManage',
  842 + component: () => import('@/views/work/repairForceFinishManageList.vue')
  843 + },
809 // 其他子路由可以在这里添加 844 // 其他子路由可以在这里添加
810 ] 845 ]
811 }, 846 },
src/views/work/myRepairDispatchManageLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + myRepairDispatchManage: {
  4 + queryCondition: 'Query Conditions',
  5 + selectMaintenanceType: 'Select Maintenance Type',
  6 + inputRepairName: 'Enter Reporter Name',
  7 + inputRepairTel: 'Enter Reporter Phone',
  8 + selectRepairType: 'Select Repair Type',
  9 + selectRepairState: 'Select Repair State',
  10 + inputRepairId: 'Enter Work Order ID',
  11 + repairDispatch: 'Repair Dispatch',
  12 + repairId: 'Work Order ID',
  13 + location: 'Location',
  14 + repairType: 'Repair Type',
  15 + maintenanceType: 'Maintenance Type',
  16 + repairPerson: 'Reporter',
  17 + contact: 'Contact',
  18 + appointmentTime: 'Appointment Time',
  19 + state: 'Status',
  20 + operation: 'Operation',
  21 + detail: 'Detail',
  22 + scheduledTask: 'Scheduled Task',
  23 + paidService: 'Paid Service',
  24 + freeService: 'Free Service',
  25 + needMaterial: 'Need Material',
  26 + noMaterial: 'No Material'
  27 + },
  28 + closeOrder: {
  29 + closeOrderInfo: 'Close Order Information',
  30 + closeStatus: 'Close Status',
  31 + selectCloseStatus: 'Please select',
  32 + closeOrder: 'Close Order',
  33 + returnOrder: 'Return Order',
  34 + reason: 'Reason',
  35 + reasonPlaceholder: 'Optional, please fill in the reason',
  36 + processed: 'Processed'
  37 + }
  38 + },
  39 + zh: {
  40 + myRepairDispatchManage: {
  41 + queryCondition: '查询条件',
  42 + selectMaintenanceType: '请选择维修类型',
  43 + inputRepairName: '请输入报修人',
  44 + inputRepairTel: '请输入报修电话',
  45 + selectRepairType: '请选择报修类型',
  46 + selectRepairState: '请选择报修状态',
  47 + inputRepairId: '请输入工单编号',
  48 + repairDispatch: '报修已办',
  49 + repairId: '工单编号',
  50 + location: '位置',
  51 + repairType: '报修类型',
  52 + maintenanceType: '维修类型',
  53 + repairPerson: '报修人',
  54 + contact: '联系方式',
  55 + appointmentTime: '预约时间',
  56 + state: '状态',
  57 + operation: '操作',
  58 + detail: '详情',
  59 + scheduledTask: '定时任务处理',
  60 + paidService: '有偿服务',
  61 + freeService: '无偿服务',
  62 + needMaterial: '需要用料',
  63 + noMaterial: '无需用料'
  64 + },
  65 + closeOrder: {
  66 + closeOrderInfo: '结单信息',
  67 + closeStatus: '结单状态',
  68 + selectCloseStatus: '请选择',
  69 + closeOrder: '结单',
  70 + returnOrder: '退单',
  71 + reason: '原因',
  72 + reasonPlaceholder: '选填,请填写原因',
  73 + processed: '已处理'
  74 + }
  75 + }
  76 + }
0 \ No newline at end of file 77 \ No newline at end of file
src/views/work/myRepairDispatchManageList.vue 0 → 100644
  1 +<template>
  2 + <div class="padding">
  3 + <el-row>
  4 + <el-col :span="24">
  5 + <el-card>
  6 + <div slot="header" class="flex justify-between">
  7 + <div>{{ $t('myRepairDispatchManage.queryCondition') }}</div>
  8 + <div class="ibox-tools" style="top:10px;">
  9 + <el-button type="text" style="margin-right:10px;" @click="_moreCondition()">
  10 + {{ myRepairDispatchInfo.moreCondition ? $t('common.hide') : $t('common.more') }}
  11 + </el-button>
  12 + </div>
  13 + </div>
  14 + <div class="">
  15 + <el-row :gutter="20">
  16 + <el-col :xs="24" :sm="12" :md="6" :lg="4">
  17 + <el-select v-model="myRepairDispatchInfo.conditions.maintenanceType"
  18 + :placeholder="$t('myRepairDispatchManage.selectMaintenanceType')" style="width:100%;">
  19 + <el-option v-for="(item, index) in myRepairDispatchInfo.maintenanceTypes" :key="index" :label="item.name"
  20 + :value="item.statusCd" />
  21 + </el-select>
  22 + </el-col>
  23 + <el-col :xs="24" :sm="12" :md="6" :lg="4">
  24 + <el-input v-model.trim="myRepairDispatchInfo.conditions.repairName"
  25 + :placeholder="$t('myRepairDispatchManage.inputRepairName')" clearable />
  26 + </el-col>
  27 + <el-col :xs="24" :sm="12" :md="6" :lg="4">
  28 + <el-input v-model.trim="myRepairDispatchInfo.conditions.tel"
  29 + :placeholder="$t('myRepairDispatchManage.inputRepairTel')" clearable />
  30 + </el-col>
  31 + <el-col :xs="24" :sm="12" :md="6" :lg="4">
  32 + <el-select v-model="myRepairDispatchInfo.conditions.repairType"
  33 + :placeholder="$t('myRepairDispatchManage.selectRepairType')" style="width:100%;">
  34 + <el-option v-for="(item, index) in myRepairDispatchInfo.repairTypes" :key="index"
  35 + :label="item.repairTypeName" :value="item.repairType" />
  36 + </el-select>
  37 + </el-col>
  38 + <el-col :xs="24" :sm="12" :md="6" :lg="4">
  39 + <el-select v-model="myRepairDispatchInfo.conditions.state"
  40 + :placeholder="$t('myRepairDispatchManage.selectRepairState')" style="width:100%;">
  41 + <el-option v-for="(item, index) in myRepairDispatchInfo.states" :key="index" :label="item.name"
  42 + :value="item.statusCd" />
  43 + </el-select>
  44 + </el-col>
  45 + <el-col :xs="24" :sm="12" :md="6" :lg="4">
  46 + <el-button type="primary" icon="el-icon-search" @click="_queryMyRepairDispatchMethod">
  47 + {{ $t('common.search') }}
  48 + </el-button>
  49 + <el-button icon="el-icon-refresh" @click="_resetMyRepairDispatchMethod">
  50 + {{ $t('common.reset') }}
  51 + </el-button>
  52 + </el-col>
  53 + </el-row>
  54 + <el-row v-show="myRepairDispatchInfo.moreCondition" :gutter="20" style="margin-top:15px;">
  55 + <el-col :xs="24" :sm="12" :md="6" :lg="4">
  56 + <el-input v-model.trim="myRepairDispatchInfo.conditions.repairId"
  57 + :placeholder="$t('myRepairDispatchManage.inputRepairId')" clearable />
  58 + </el-col>
  59 + </el-row>
  60 + </div>
  61 + </el-card>
  62 + </el-col>
  63 + </el-row>
  64 +
  65 + <el-row style="margin-top:20px;">
  66 + <el-col :span="24">
  67 + <el-card>
  68 + <div slot="header" class="flex justify-between">
  69 + <div>
  70 + <span>{{ myRepairDispatchInfo.conditions.roomName }}</span>
  71 + <span>{{ $t('myRepairDispatchManage.repairDispatch') }}</span>
  72 + </div>
  73 + </div>
  74 + <div class="">
  75 + <el-table :data="myRepairDispatchInfo.ownerRepairs" border style="width: 100%">
  76 + <el-table-column prop="repairId" :label="$t('myRepairDispatchManage.repairId')" align="center" />
  77 + <el-table-column prop="repairObjName" :label="$t('myRepairDispatchManage.location')" align="center" />
  78 + <el-table-column prop="repairTypeName" :label="$t('myRepairDispatchManage.repairType')" align="center" />
  79 + <el-table-column :label="$t('myRepairDispatchManage.maintenanceType')" align="center">
  80 + <template slot-scope="scope">
  81 + {{ getMaintenanceTypeName(scope.row.maintenanceType) }}
  82 + </template>
  83 + </el-table-column>
  84 + <el-table-column prop="repairName" :label="$t('myRepairDispatchManage.repairPerson')" align="center" />
  85 + <el-table-column prop="tel" :label="$t('myRepairDispatchManage.contact')" align="center" />
  86 + <el-table-column prop="appointmentTime" :label="$t('myRepairDispatchManage.appointmentTime')"
  87 + align="center" />
  88 + <el-table-column :label="$t('myRepairDispatchManage.state')" align="center">
  89 + <template slot-scope="scope">
  90 + <span
  91 + v-if="scope.row.state == '1800' && (scope.row.returnVisitFlag == '001' || scope.row.returnVisitFlag == '002')">
  92 + {{ scope.row.stateName }}({{ $t('myRepairDispatchManage.scheduledTask') }})
  93 + </span>
  94 + <span v-else>
  95 + {{ scope.row.stateName }}
  96 + </span>
  97 + </template>
  98 + </el-table-column>
  99 + <el-table-column :label="$t('common.operation')" align="center" width="120">
  100 + <template slot-scope="scope">
  101 + <el-button size="mini" type="primary" @click="_openRepairDetail(scope.row)">
  102 + {{ $t('common.detail') }}
  103 + </el-button>
  104 + </template>
  105 + </el-table-column>
  106 + </el-table>
  107 +
  108 + <el-pagination background layout="total, sizes, prev, pager, next, jumper"
  109 + :current-page.sync="pagination.current" :page-sizes="[10, 20, 30, 50]" :page-size="pagination.size"
  110 + :total="pagination.total" @size-change="handleSizeChange" @current-change="handleCurrentChange"
  111 + style="margin-top: 20px;" />
  112 + </div>
  113 + </el-card>
  114 + </el-col>
  115 + </el-row>
  116 +
  117 + <close-order ref="closeOrderModal" @success="handleCloseOrderSuccess" />
  118 + </div>
  119 +</template>
  120 +
  121 +<script>
  122 +import { listStaffFinishRepairs, listRepairSettings, closeRepairDispatch } from '@/api/work/myRepairDispatchManageApi'
  123 +import { getDict } from '@/api/community/communityApi'
  124 +import CloseOrder from '@/components/work/closeOrder'
  125 +
  126 +export default {
  127 + name: 'MyRepairDispatchManageList',
  128 + components: {
  129 + CloseOrder
  130 + },
  131 + data() {
  132 + return {
  133 + myRepairDispatchInfo: {
  134 + ownerRepairs: [],
  135 + moreCondition: false,
  136 + currentRepairId: '',
  137 + repairTypes: [],
  138 + states: [],
  139 + maintenanceTypes: [],
  140 + conditions: {
  141 + pageFlag: 'myRepairDispatch',
  142 + repairId: '',
  143 + repairName: '',
  144 + tel: '',
  145 + repairType: '',
  146 + roomId: '',
  147 + roomName: '',
  148 + ownerId: '',
  149 + state: '',
  150 + maintenanceType: '',
  151 + page: 1,
  152 + row: 10,
  153 + communityId: ''
  154 + }
  155 + },
  156 + pagination: {
  157 + current: 1,
  158 + size: 10,
  159 + total: 0
  160 + }
  161 + }
  162 + },
  163 + created() {
  164 + this.initData()
  165 + },
  166 + methods: {
  167 + async initData() {
  168 + try {
  169 + this.myRepairDispatchInfo.conditions.communityId = this.getCommunityId()
  170 + await this.getDictData()
  171 + this._listRepairTypes()
  172 + this._listOwnerRepairs(1, this.pagination.size)
  173 + } catch (error) {
  174 + console.error('初始化数据失败:', error)
  175 + }
  176 + },
  177 +
  178 + async getDictData() {
  179 + try {
  180 + const stateData = await getDict('r_repair_pool', 'state')
  181 + this.myRepairDispatchInfo.states = stateData
  182 +
  183 + const maintenanceTypeData = await getDict('r_repair_pool', 'maintenance_type')
  184 + this.myRepairDispatchInfo.maintenanceTypes = maintenanceTypeData
  185 + } catch (error) {
  186 + console.error('获取字典数据失败:', error)
  187 + }
  188 + },
  189 +
  190 + async _listOwnerRepairs(page, size) {
  191 + try {
  192 + this.myRepairDispatchInfo.conditions.page = page
  193 + this.myRepairDispatchInfo.conditions.row = size
  194 +
  195 + const params = {
  196 + ...this.myRepairDispatchInfo.conditions,
  197 + repairId: this.myRepairDispatchInfo.conditions.repairId.trim(),
  198 + repairName: this.myRepairDispatchInfo.conditions.repairName.trim(),
  199 + tel: this.myRepairDispatchInfo.conditions.tel.trim()
  200 + }
  201 +
  202 + const res = await listStaffFinishRepairs(params)
  203 + this.myRepairDispatchInfo.ownerRepairs = res.data
  204 + this.pagination.total = res.total
  205 + this.pagination.current = page
  206 + } catch (error) {
  207 + console.error('获取报修列表失败:', error)
  208 + }
  209 + },
  210 +
  211 + async _listRepairTypes() {
  212 + try {
  213 + const params = {
  214 + page: 1,
  215 + row: 100,
  216 + communityId: this.getCommunityId()
  217 + }
  218 +
  219 + const res = await listRepairSettings(params)
  220 + this.myRepairDispatchInfo.repairTypes = res.data
  221 + } catch (error) {
  222 + console.error('获取报修类型失败:', error)
  223 + }
  224 + },
  225 +
  226 + _moreCondition() {
  227 + this.myRepairDispatchInfo.moreCondition = !this.myRepairDispatchInfo.moreCondition
  228 + },
  229 +
  230 + _openRepairDetail(repairPool) {
  231 + this.$router.push({
  232 + path: '/views/work/repairDetail',
  233 + query: { repairId: repairPool.repairId }
  234 + })
  235 + },
  236 +
  237 + _openDealRepair(ownerRepair) {
  238 + this.myRepairDispatchInfo.currentRepairId = ownerRepair.repairId
  239 + this.$refs.closeOrderModal.open()
  240 + },
  241 +
  242 + async handleCloseOrderSuccess(orderInfo) {
  243 + try {
  244 + const params = {
  245 + repairId: this.myRepairDispatchInfo.currentRepairId,
  246 + context: orderInfo.remark,
  247 + communityId: this.$store.getters.communityId,
  248 + state: orderInfo.state === '1100' ? '10002' : '10003'
  249 + }
  250 +
  251 + await closeRepairDispatch(params)
  252 + this.$message.success(this.$t('common.operateSuccess'))
  253 + this._listOwnerRepairs(this.pagination.current, this.pagination.size)
  254 + } catch (error) {
  255 + console.error('结单操作失败:', error)
  256 + }
  257 + },
  258 +
  259 + _queryMyRepairDispatchMethod() {
  260 + this._listOwnerRepairs(1, this.pagination.size)
  261 + },
  262 +
  263 + _resetMyRepairDispatchMethod() {
  264 + this.myRepairDispatchInfo.conditions = {
  265 + ...this.myRepairDispatchInfo.conditions,
  266 + repairId: '',
  267 + repairName: '',
  268 + tel: '',
  269 + repairType: '',
  270 + state: '',
  271 + maintenanceType: ''
  272 + }
  273 + this._listOwnerRepairs(1, this.pagination.size)
  274 + },
  275 +
  276 + getMaintenanceTypeName(type) {
  277 + const mapping = {
  278 + '1001': this.$t('myRepairDispatchManage.paidService'),
  279 + '1002': this.$t('myRepairDispatchManage.freeService'),
  280 + '1003': this.$t('myRepairDispatchManage.needMaterial'),
  281 + '1004': this.$t('myRepairDispatchManage.noMaterial')
  282 + }
  283 + return mapping[type] || '--'
  284 + },
  285 +
  286 + handleSizeChange(size) {
  287 + this.pagination.size = size
  288 + this._listOwnerRepairs(1, size)
  289 + },
  290 +
  291 + handleCurrentChange(page) {
  292 + this._listOwnerRepairs(page, this.pagination.size)
  293 + }
  294 + }
  295 +}
  296 +</script>
  297 +
  298 +<style scoped>
  299 +.ibox-content {
  300 + padding: 15px 20px 20px 20px;
  301 +}
  302 +
  303 +.ibox-tools {
  304 + position: absolute;
  305 + right: 15px;
  306 + top: 15px;
  307 +}
  308 +</style>
0 \ No newline at end of file 309 \ No newline at end of file
src/views/work/ownerRepairManageLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + ownerRepairManage: {
  4 + queryCondition: 'Query Condition',
  5 + phoneRepair: 'Phone Repair',
  6 + register: 'Register',
  7 + placeholder: {
  8 + repairId: 'Please input repair id',
  9 + repairName: 'Please input repair name',
  10 + tel: 'Please input tel',
  11 + repairType: 'Please select repair type',
  12 + state: 'Please select state'
  13 + },
  14 + table: {
  15 + repairId: 'Repair Id',
  16 + location: 'Location',
  17 + repairType: 'Repair Type',
  18 + repairName: 'Repair Name',
  19 + tel: 'Tel',
  20 + appointmentTime: 'Appointment Time',
  21 + timeout: 'Timeout',
  22 + createTime: 'Create Time',
  23 + state: 'State',
  24 + operation: 'Operation',
  25 + scheduledTask: '(Scheduled Task)'
  26 + },
  27 + tip1: 'Note: Before using this function, please go to Repair Management;',
  28 + tip2: 'For general owner housing repairs, we must add a non-public area type to report repairs normally.',
  29 +
  30 + },
  31 + addOwnerRepair: {
  32 + title: 'Repair Registration',
  33 + repairScope: 'Repair Scope',
  34 + belongBuilding: 'Belong Building',
  35 + belongUnit: 'Belong Unit',
  36 + belongRoom: 'Belong Room',
  37 + repairType: 'Repair Type',
  38 + repairName: 'Repair Name',
  39 + tel: 'Contact',
  40 + appointmentTime: 'Appointment Time',
  41 + context: 'Repair Content',
  42 + placeholder: {
  43 + appointmentTime: 'Please select appointment time'
  44 + },
  45 + community: 'Community',
  46 + building: 'Building',
  47 + unit: 'Unit',
  48 + room: 'Room',
  49 + buildingSuffix: ' Building',
  50 + unitSuffix: ' Unit',
  51 + roomSuffix: ' Room'
  52 + },
  53 + editOwnerRepair: {
  54 + title: 'Edit Owner Repair',
  55 + repairType: 'Repair Type',
  56 + repairName: 'Repair Name',
  57 + tel: 'Contact',
  58 + appointmentTime: 'Appointment Time',
  59 + context: 'Repair Content',
  60 + placeholder: {
  61 + appointmentTime: 'Please select appointment time'
  62 + }
  63 + },
  64 + deleteOwnerRepair: {
  65 + title: 'Confirm Operation',
  66 + confirmText: 'Are you sure to delete this repair record?'
  67 + },
  68 + },
  69 + zh: {
  70 + ownerRepairManage: {
  71 + queryCondition: '查询条件',
  72 + phoneRepair: '电话报修',
  73 + register: '登记',
  74 + placeholder: {
  75 + repairId: '请输入工单编号',
  76 + repairName: '请输入报修人',
  77 + tel: '请输入报修电话',
  78 + repairType: '请选择报修类型',
  79 + state: '请选择报修状态'
  80 + },
  81 + table: {
  82 + repairId: '工单编号',
  83 + location: '位置',
  84 + repairType: '报修类型',
  85 + repairName: '报修人',
  86 + tel: '联系方式',
  87 + appointmentTime: '预约时间',
  88 + timeout: '超时时间',
  89 + createTime: '提交时间',
  90 + state: '状态',
  91 + operation: '操作',
  92 + scheduledTask: '(定时任务处理)'
  93 + },
  94 + tip1: '注意:此功能使用前 请先到 报修管理;',
  95 + tip2: '一般业主房屋报修 我们必须要添加一个非公共区域的类型才能正常报修'
  96 + },
  97 + addOwnerRepair: {
  98 + title: '报修登记',
  99 + repairScope: '报修范围',
  100 + belongBuilding: '归属楼栋',
  101 + belongUnit: '归属单元',
  102 + belongRoom: '归属房屋',
  103 + repairType: '报修类型',
  104 + repairName: '报修人',
  105 + tel: '联系方式',
  106 + appointmentTime: '预约时间',
  107 + context: '报修内容',
  108 + placeholder: {
  109 + appointmentTime: '请选择预约时间'
  110 + },
  111 + community: '小区',
  112 + building: '楼栋',
  113 + unit: '单元',
  114 + room: '房屋',
  115 + buildingSuffix: '栋',
  116 + unitSuffix: '单元',
  117 + roomSuffix: '室'
  118 + },
  119 + editOwnerRepair: {
  120 + title: '修改业主报修',
  121 + repairType: '报修类型',
  122 + repairName: '报修人',
  123 + tel: '联系方式',
  124 + appointmentTime: '预约时间',
  125 + context: '报修内容',
  126 + placeholder: {
  127 + appointmentTime: '请选择预约时间'
  128 + }
  129 + },
  130 + deleteOwnerRepair: {
  131 + title: '请确认您的操作',
  132 + confirmText: '确定删除业主报修?'
  133 + },
  134 + }
  135 +}
0 \ No newline at end of file 136 \ No newline at end of file
src/views/work/ownerRepairManageList.vue 0 → 100644
  1 +<template>
  2 + <div class="animated fadeInRight">
  3 + <el-card shadow="hover">
  4 + <div slot="header" class="flex justify-between">
  5 + <span>{{ $t('ownerRepairManage.queryCondition') }}</span>
  6 + </div>
  7 + <div class="search-content">
  8 + <el-row :gutter="20">
  9 + <el-col :span="4">
  10 + <el-input v-model.trim="ownerRepairManageInfo.conditions.repairId"
  11 + :placeholder="$t('ownerRepairManage.placeholder.repairId')" clearable />
  12 + </el-col>
  13 + <el-col :span="4">
  14 + <el-input v-model.trim="ownerRepairManageInfo.conditions.repairName"
  15 + :placeholder="$t('ownerRepairManage.placeholder.repairName')" clearable />
  16 + </el-col>
  17 + <el-col :span="4">
  18 + <el-input v-model.trim="ownerRepairManageInfo.conditions.tel"
  19 + :placeholder="$t('ownerRepairManage.placeholder.tel')" clearable />
  20 + </el-col>
  21 + <el-col :span="4">
  22 + <el-select v-model="ownerRepairManageInfo.conditions.repairType"
  23 + :placeholder="$t('ownerRepairManage.placeholder.repairType')" style="width:100%" clearable>
  24 + <el-option v-for="(item, index) in ownerRepairManageInfo.repairTypes" :key="index"
  25 + :label="item.repairTypeName" :value="item.repairType" />
  26 + </el-select>
  27 + </el-col>
  28 + <el-col :span="4">
  29 + <el-select v-model="ownerRepairManageInfo.conditions.state"
  30 + :placeholder="$t('ownerRepairManage.placeholder.state')" style="width:100%" clearable>
  31 + <el-option v-for="(item, index) in ownerRepairManageInfo.states" :key="index" :label="item.name"
  32 + :value="item.statusCd" />
  33 + </el-select>
  34 + </el-col>
  35 + <el-col :span="4">
  36 + <el-button type="primary" icon="el-icon-search" @click="_queryOwnerRepairMethod">{{ $t('common.search')
  37 + }}</el-button>
  38 + <el-button type="info" icon="el-icon-refresh" @click="_resetOwnerRepairMethod" style="margin-left: 20px">{{
  39 + $t('common.reset') }}</el-button>
  40 + </el-col>
  41 + </el-row>
  42 + </div>
  43 + </el-card>
  44 +
  45 + <el-card shadow="hover" style="margin-top: 20px">
  46 + <div slot="header" class="flex justify-between">
  47 + <span>{{ $t('ownerRepairManage.phoneRepair') }}</span>
  48 + <el-button v-if="ownerRepairManageInfo.conditions.roomId != ''" size="small" type="primary" icon="el-icon-plus"
  49 + style="float:right" @click="_openAddOwnerRepairModal">{{ $t('ownerRepairManage.register') }}</el-button>
  50 + </div>
  51 + <el-table :data="ownerRepairManageInfo.ownerRepairs" border style="width: 100%">
  52 + <el-table-column prop="repairId" :label="$t('ownerRepairManage.table.repairId')" align="center" />
  53 + <el-table-column prop="repairObjName" :label="$t('ownerRepairManage.table.location')" align="center" />
  54 + <el-table-column prop="repairTypeName" :label="$t('ownerRepairManage.table.repairType')" align="center" />
  55 + <el-table-column prop="repairName" :label="$t('ownerRepairManage.table.repairName')" align="center" />
  56 + <el-table-column prop="tel" :label="$t('ownerRepairManage.table.tel')" align="center" />
  57 + <el-table-column prop="appointmentTime" :label="$t('ownerRepairManage.table.appointmentTime')" align="center" />
  58 + <el-table-column prop="timeout" :label="$t('ownerRepairManage.table.timeout')" align="center" />
  59 + <el-table-column prop="createTime" :label="$t('ownerRepairManage.table.createTime')" align="center" />
  60 + <el-table-column :label="$t('ownerRepairManage.table.state')" align="center">
  61 + <template slot-scope="scope">
  62 + <span
  63 + v-if="scope.row.state == '1800' && (scope.row.returnVisitFlag == '001' || scope.row.returnVisitFlag == '002')">
  64 + {{ scope.row.stateName }}{{ $t('ownerRepairManage.table.scheduledTask') }}
  65 + </span>
  66 + <span v-else>{{ scope.row.stateName }}</span>
  67 + </template>
  68 + </el-table-column>
  69 + <el-table-column :label="$t('common.operation')" align="center" fixed="right" width="200">
  70 + <template slot-scope="scope">
  71 + <el-button
  72 + v-if="hasPrivilege('502021012067300023') && (scope.row.state == '1000' || scope.row.state == '1200')"
  73 + size="mini" type="primary" @click="_openEditOwnerRepairModel(scope.row)">{{ $t('common.edit') }}</el-button>
  74 + <el-button
  75 + v-if="hasPrivilege('502021012051410024') && (scope.row.state == '1000' || scope.row.state == '1200')"
  76 + size="mini" type="danger" @click="_openDeleteOwnerRepairModel(scope.row)">{{ $t('common.delete')
  77 + }}</el-button>
  78 + </template>
  79 + </el-table-column>
  80 + </el-table>
  81 + <!-- 分页 -->
  82 + <div style="margin-top: 20px">
  83 + <el-row>
  84 + <el-col :span="18" class="text-left">
  85 + <div>
  86 + {{ $t('ownerRepairManage.tip1') }}
  87 + </div>
  88 + <div>
  89 + {{ $t('ownerRepairManage.tip2') }}
  90 + </div>
  91 + </el-col>
  92 + <el-col :span="6">
  93 + <el-pagination :current-page="ownerRepairManageInfo.page" :page-sizes="[10, 20, 30, 50]"
  94 + :page-size="ownerRepairManageInfo.rows" layout="total, sizes, prev, pager, next, jumper"
  95 + :total="ownerRepairManageInfo.total" @size-change="handleSizeChange"
  96 + @current-change="handleCurrentChange" />
  97 + </el-col>
  98 + </el-row>
  99 + </div>
  100 + </el-card>
  101 +
  102 + <!-- 添加报修模态框 -->
  103 + <add-owner-repair ref="addOwnerRepair" @success="_queryOwnerRepairMethod" />
  104 + <!-- 修改报修模态框 -->
  105 + <edit-owner-repair ref="editOwnerRepair" @success="_queryOwnerRepairMethod" />
  106 + <!-- 删除报修模态框 -->
  107 + <delete-owner-repair ref="deleteOwnerRepair" @success="_queryOwnerRepairMethod" />
  108 + </div>
  109 +</template>
  110 +
  111 +<script>
  112 +import * as ownerRepairManageApi from '@/api/work/ownerRepairManageApi'
  113 +import AddOwnerRepair from '@/components/work/addOwnerRepair'
  114 +import EditOwnerRepair from '@/components/work/editOwnerRepair'
  115 +import DeleteOwnerRepair from '@/components/work/deleteOwnerRepair'
  116 +import { getDict } from '@/api/community/communityApi'
  117 +
  118 +export default {
  119 + name: 'OwnerRepairManageList',
  120 + components: {
  121 + AddOwnerRepair,
  122 + EditOwnerRepair,
  123 + DeleteOwnerRepair
  124 + },
  125 + data() {
  126 + return {
  127 + ownerRepairManageInfo: {
  128 + ownerRepairs: [],
  129 + total: 0,
  130 + page: 1,
  131 + rows: 10,
  132 + moreCondition: false,
  133 + repairTypes: [],
  134 + states: [],
  135 + conditions: {
  136 + repairId: '',
  137 + repairName: '',
  138 + tel: '',
  139 + repairType: '',
  140 + state: '',
  141 + reqSource: 'pc_mobile'
  142 + }
  143 + }
  144 + }
  145 + },
  146 + created() {
  147 + this._listOwnerRepairs(1, this.ownerRepairManageInfo.rows)
  148 + this._listRepairTypes(1, 50)
  149 + this._loadStates()
  150 + },
  151 + methods: {
  152 + _loadStates() {
  153 + getDict('r_repair_pool', 'state').then(data => {
  154 + this.ownerRepairManageInfo.states = data
  155 + })
  156 + },
  157 + async _listRepairTypes(page, rows) {
  158 + const param = {
  159 + page: page,
  160 + row: rows,
  161 + communityId: this.getCommunityId()
  162 + }
  163 + const { data } = await ownerRepairManageApi.listRepairSettings(param)
  164 + this.ownerRepairManageInfo.repairTypes = data
  165 +
  166 + },
  167 + _listOwnerRepairs(page, rows) {
  168 + this.ownerRepairManageInfo.conditions.page = page
  169 + this.ownerRepairManageInfo.conditions.row = rows
  170 + this.ownerRepairManageInfo.conditions.communityId = this.getCommunityId()
  171 + ownerRepairManageApi.listOwnerRepairs(this.ownerRepairManageInfo.conditions).then(res => {
  172 + if (res.code === 0) {
  173 + this.ownerRepairManageInfo.ownerRepairs = res.data
  174 + this.ownerRepairManageInfo.total = res.total
  175 + this.ownerRepairManageInfo.page = page
  176 + this.ownerRepairManageInfo.rows = rows
  177 + }
  178 + })
  179 + },
  180 + _resetListOwnerRepairs() {
  181 + this.ownerRepairManageInfo.conditions = {
  182 + repairId: '',
  183 + repairName: '',
  184 + tel: '',
  185 + repairType: '',
  186 + state: '',
  187 + reqSource: 'pc_mobile'
  188 + }
  189 + this._listOwnerRepairs(1, this.ownerRepairManageInfo.rows)
  190 + },
  191 + _openAddOwnerRepairModal() {
  192 + this.$refs.addOwnerRepair.open()
  193 + },
  194 + _openEditOwnerRepairModel(row) {
  195 + this.$refs.editOwnerRepair.open(row)
  196 + },
  197 + _openDeleteOwnerRepairModel(row) {
  198 + this.$refs.deleteOwnerRepair.open(row)
  199 + },
  200 + _queryOwnerRepairMethod() {
  201 + this._listOwnerRepairs(1, this.ownerRepairManageInfo.rows)
  202 + },
  203 + _resetOwnerRepairMethod() {
  204 + this._resetListOwnerRepairs()
  205 + },
  206 + handleSizeChange(val) {
  207 + this.ownerRepairManageInfo.rows = val
  208 + this._listOwnerRepairs(this.ownerRepairManageInfo.page, val)
  209 + },
  210 + handleCurrentChange(val) {
  211 + this.ownerRepairManageInfo.page = val
  212 + this._listOwnerRepairs(val, this.ownerRepairManageInfo.rows)
  213 + }
  214 + }
  215 +}
  216 +</script>
  217 +
  218 +<style lang="scss" scoped>
  219 +.animated {
  220 + padding: 20px;
  221 +}
  222 +
  223 +.search-content {
  224 + padding: 20px;
  225 +}
  226 +</style>
0 \ No newline at end of file 227 \ No newline at end of file
src/views/work/repairDetailLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + repairDetail: {
  4 + title: 'Work Order Details',
  5 + print: 'Print',
  6 + back: 'Back',
  7 + orderCode: 'Work Order Code:',
  8 + repairType: 'Repair Type:',
  9 + repairer: 'Repairer:',
  10 + contact: 'Contact:',
  11 + location: 'Location:',
  12 + appointmentStart: 'Appointment Start:',
  13 + appointmentEnd: 'Appointment End:',
  14 + submitDuration: 'Submission Duration:',
  15 + finishTime: 'Completion Time:',
  16 + status: 'Status:',
  17 + content: 'Content:',
  18 + maintenanceType: 'Maintenance Type:',
  19 + materials: 'Materials:',
  20 + costDetail: 'Cost Details:',
  21 + yuan: 'Yuan (Unit Price * Quantity)',
  22 + avgScore: 'Average Score:',
  23 + comprehensiveScore: 'Comprehensive Score:',
  24 + doorSpeedScore: 'Door Speed Score:',
  25 + serviceScore: 'Service Score:',
  26 + points: 'Points',
  27 + visitSatisfaction: 'Visit Satisfaction:',
  28 + visitContent: 'Visit Content:',
  29 + orderPhotos: 'Order Photos',
  30 + orderFlow: 'Order Flow',
  31 + orderEvents: 'Order Events',
  32 + repairItems: 'Repair Items',
  33 + paidService: 'Paid Service',
  34 + freeService: 'Free Service',
  35 + needMaterials: 'Need Materials',
  36 + noMaterials: 'No Materials'
  37 + },
  38 + repairDetailResource: {
  39 + itemCode: 'Item Code',
  40 + itemType: 'Item Type',
  41 + itemName: 'Item Name',
  42 + specification: 'Specification',
  43 + quantity: 'Quantity',
  44 + price: 'Price',
  45 + user: 'User',
  46 + time: 'Time'
  47 + },
  48 + repairDetailUser: {
  49 + serial: 'Serial',
  50 + handler: 'Handler',
  51 + status: 'Status',
  52 + startTime: 'Start Time',
  53 + endTime: 'End Time',
  54 + duration: 'Duration',
  55 + opinion: 'Opinion',
  56 + reply: 'Reply'
  57 + },
  58 + repairDetailEvent: {
  59 + eventType: 'Event Type',
  60 + staff: 'Staff',
  61 + description: 'Description',
  62 + createTime: 'Create Time'
  63 + },
  64 + replyRepairAppraise: {
  65 + title: 'Reply Evaluation',
  66 + content: 'Content',
  67 + submit: 'Submit',
  68 + cancel: 'Cancel',
  69 + placeholder: 'Required, please fill in reply content'
  70 + }
  71 + },
  72 + zh: {
  73 + repairDetail: {
  74 + title: '工单详情',
  75 + print: '打印',
  76 + back: '返回',
  77 + orderCode: '工单编码:',
  78 + repairType: '报修类型:',
  79 + repairer: '报修人:',
  80 + contact: '联系方式:',
  81 + location: '位置:',
  82 + appointmentStart: '预约开始时间:',
  83 + appointmentEnd: '预约结束时间:',
  84 + submitDuration: '提单时长:',
  85 + finishTime: '完成时间:',
  86 + status: '状态:',
  87 + content: '报修内容:',
  88 + maintenanceType: '维修类型:',
  89 + materials: '用料:',
  90 + costDetail: '费用明细:',
  91 + yuan: '元(单价*数量)',
  92 + avgScore: '平均分:',
  93 + comprehensiveScore: '综合评价得分:',
  94 + doorSpeedScore: '上门速度评分:',
  95 + serviceScore: '维修员服务评分:',
  96 + points: '分',
  97 + visitSatisfaction: '回访满意度:',
  98 + visitContent: '回访内容:',
  99 + orderPhotos: '工单图片',
  100 + orderFlow: '工单流转',
  101 + orderEvents: '工单事件',
  102 + repairItems: '维修物品',
  103 + paidService: '有偿服务',
  104 + freeService: '无偿服务',
  105 + needMaterials: '需要用料',
  106 + noMaterials: '无需用料'
  107 + },
  108 + repairDetailResource: {
  109 + itemCode: '物品资源编号',
  110 + itemType: '物品资源类型',
  111 + itemName: '物品资源名称',
  112 + specification: '物品资源规格',
  113 + quantity: '物品使用数量',
  114 + price: '物品价格',
  115 + user: '使用人',
  116 + time: '时间'
  117 + },
  118 + repairDetailUser: {
  119 + serial: '序号',
  120 + handler: '处理人',
  121 + status: '状态',
  122 + startTime: '处理开始时间',
  123 + endTime: '处理结束时间',
  124 + duration: '耗时',
  125 + opinion: '意见',
  126 + reply: '回复'
  127 + },
  128 + repairDetailEvent: {
  129 + eventType: '事件类型',
  130 + staff: '员工',
  131 + description: '事件说明',
  132 + createTime: '创建时间'
  133 + },
  134 + replyRepairAppraise: {
  135 + title: '回复评价',
  136 + content: '内容',
  137 + submit: '提交',
  138 + cancel: '取消',
  139 + placeholder: '必填,请填写回复内容'
  140 + }
  141 + }
  142 +}
0 \ No newline at end of file 143 \ No newline at end of file
src/views/work/repairDetailList.vue 0 → 100644
  1 +<template>
  2 + <el-card class="repair-detail-container">
  3 + <div class="flex justify-between">
  4 + <div class="text-title">{{ $t('repairDetail.title') }}</div>
  5 + <div>
  6 + <el-button type="primary" size="small" @click="printRepairDetail">
  7 + {{ $t('repairDetail.print') }}
  8 + </el-button>
  9 + <el-button type="primary" size="small" @click="goBack">
  10 + {{ $t('repairDetail.back') }}
  11 + </el-button>
  12 + </div>
  13 + </div>
  14 +
  15 + <div class="margin-top">
  16 + <el-form :model="repairDetailInfo" label-width="auto" class="text-left">
  17 + <el-row :gutter="20">
  18 + <el-col :sm="8" :xs="24">
  19 + <el-form-item :label="$t('repairDetail.orderCode')">
  20 + <span>{{ repairDetailInfo.repairId }}</span>
  21 + </el-form-item>
  22 + </el-col>
  23 + <el-col :sm="8" :xs="24">
  24 + <el-form-item :label="$t('repairDetail.repairType')">
  25 + <span>{{ repairDetailInfo.repairTypeName }}</span>
  26 + </el-form-item>
  27 + </el-col>
  28 + <el-col :sm="8" :xs="24">
  29 + <el-form-item :label="$t('repairDetail.repairer')">
  30 + <span>{{ repairDetailInfo.repairName }}</span>
  31 + </el-form-item>
  32 + </el-col>
  33 +
  34 + <el-col :sm="8" :xs="24">
  35 + <el-form-item :label="$t('repairDetail.contact')">
  36 + <span>{{ repairDetailInfo.tel }}</span>
  37 + </el-form-item>
  38 + </el-col>
  39 + <el-col :sm="8" :xs="24">
  40 + <el-form-item :label="$t('repairDetail.location')">
  41 + <span>{{ repairDetailInfo.repairObjName }}</span>
  42 + </el-form-item>
  43 + </el-col>
  44 + <el-col :sm="8" :xs="24">
  45 + <el-form-item :label="$t('repairDetail.appointmentStart')">
  46 + <span>{{ repairDetailInfo.appointmentTime }}</span>
  47 + </el-form-item>
  48 + </el-col>
  49 + <el-col :sm="8" :xs="24">
  50 + <el-form-item :label="$t('repairDetail.appointmentEnd')">
  51 + <span>{{ repairDetailInfo.timeout }}</span>
  52 + </el-form-item>
  53 + </el-col>
  54 + <el-col :sm="8" :xs="24">
  55 + <el-form-item :label="$t('repairDetail.submitDuration')">
  56 + <span>{{ repairDetailInfo.submitHours || '0' }}</span>
  57 + </el-form-item>
  58 + </el-col>
  59 + <el-col :sm="8" :xs="24">
  60 + <el-form-item :label="$t('repairDetail.finishTime')">
  61 + <span>{{ repairDetailInfo.finishTime || '-' }}</span>
  62 + </el-form-item>
  63 + </el-col>
  64 + <el-col :sm="8" :xs="24">
  65 + <el-form-item :label="$t('repairDetail.status')">
  66 + <span>{{ repairDetailInfo.stateName }}</span>
  67 + </el-form-item>
  68 + </el-col>
  69 + <el-col :sm="8" :xs="24">
  70 + <el-form-item :label="$t('repairDetail.content')">
  71 + <span>{{ repairDetailInfo.context }}</span>
  72 + </el-form-item>
  73 + </el-col>
  74 + <el-col v-if="repairDetailInfo.maintenanceType" :sm="8" :xs="24">
  75 + <el-form-item :label="$t('repairDetail.maintenanceType')">
  76 + <span>
  77 + <template v-if="repairDetailInfo.maintenanceType === '1001'">
  78 + {{ $t('repairDetail.paidService') }}
  79 + </template>
  80 + <template v-else-if="repairDetailInfo.maintenanceType === '1002'">
  81 + {{ $t('repairDetail.freeService') }}
  82 + </template>
  83 + <template v-else-if="repairDetailInfo.maintenanceType === '1003'">
  84 + {{ $t('repairDetail.needMaterials') }}
  85 + </template>
  86 + <template v-else-if="repairDetailInfo.maintenanceType === '1004'">
  87 + {{ $t('repairDetail.noMaterials') }}
  88 + </template>
  89 + </span>
  90 + </el-form-item>
  91 + </el-col>
  92 +
  93 + <el-col v-if="repairDetailInfo.maintenanceType === '1001' || repairDetailInfo.maintenanceType === '1003'" :sm="8"
  94 + :xs="24">
  95 + <el-form-item :label="$t('repairDetail.materials')">
  96 + <span>{{ repairDetailInfo.repairMaterials }}</span>
  97 + </el-form-item>
  98 + </el-col>
  99 + <el-col v-if="repairDetailInfo.maintenanceType === '1001'" :sm="8" :xs="24">
  100 + <el-form-item :label="$t('repairDetail.costDetail')">
  101 + <span>
  102 + {{ repairDetailInfo.repairFee }}
  103 + <span>{{ $t('repairDetail.yuan') }}</span>
  104 + </span>
  105 + </el-form-item>
  106 + </el-col>
  107 + <el-col v-if="repairDetailInfo.appraiseScore !== '0'" :sm="8" :xs="24">
  108 + <el-form-item :label="$t('repairDetail.comprehensiveScore')">
  109 + <span>
  110 + {{ repairDetailInfo.appraiseScore }}
  111 + <span>{{ $t('repairDetail.points') }}</span>
  112 + </span>
  113 + </el-form-item>
  114 + </el-col>
  115 +
  116 + <el-col v-if="repairDetailInfo.doorSpeedScore !== '0'" :sm="8" :xs="24">
  117 + <el-form-item :label="$t('repairDetail.doorSpeedScore')">
  118 + <span>
  119 + {{ repairDetailInfo.doorSpeedScore }}
  120 + <span>{{ $t('repairDetail.points') }}</span>
  121 + </span>
  122 + </el-form-item>
  123 + </el-col>
  124 + <el-col v-if="repairDetailInfo.repairmanServiceScore !== '0'" :sm="8" :xs="24">
  125 + <el-form-item :label="$t('repairDetail.serviceScore')">
  126 + <span>
  127 + {{ repairDetailInfo.repairmanServiceScore }}
  128 + <span>{{ $t('repairDetail.points') }}</span>
  129 + </span>
  130 + </el-form-item>
  131 + </el-col>
  132 + <el-col v-if="repairDetailInfo.average !== '0.0'" :sm="8" :xs="24">
  133 + <el-form-item :label="$t('repairDetail.avgScore')">
  134 + <span>
  135 + {{ repairDetailInfo.average }}
  136 + {{ $t('repairDetail.points') }}
  137 + </span>
  138 + </el-form-item>
  139 + </el-col>
  140 + </el-row>
  141 +
  142 + <el-row v-if="repairDetailInfo.visitType" :gutter="20">
  143 + <el-col :sm="8" :xs="24">
  144 + <el-form-item :label="$t('repairDetail.visitSatisfaction')">
  145 + <span>{{ repairDetailInfo.visitType === '1001' ? $t('repairDetail.satisfied') :
  146 + $t('repairDetail.notSatisfied') }}</span>
  147 + </el-form-item>
  148 + </el-col>
  149 + <el-col :sm="8" :xs="24">
  150 + <el-form-item :label="$t('repairDetail.visitContent')">
  151 + <span>{{ repairDetailInfo.visitContext }}</span>
  152 + </el-form-item>
  153 + </el-col>
  154 + </el-row>
  155 + </el-form>
  156 + </div>
  157 +
  158 + <divider></divider>
  159 +
  160 + <div class="margin-top-sm">
  161 + <el-tabs v-model="currentTab" @tab-click="changeTab(currentTab)">
  162 + <el-tab-pane :label="$t('repairDetail.orderPhotos')" name="repairDetailPhotos"></el-tab-pane>
  163 + <el-tab-pane :label="$t('repairDetail.repairItems')" name="repairDetailResource"></el-tab-pane>
  164 + <el-tab-pane :label="$t('repairDetail.orderFlow')" name="repairDetailUser"></el-tab-pane>
  165 + <el-tab-pane :label="$t('repairDetail.orderEvents')" name="repairDetailEvent"></el-tab-pane>
  166 + </el-tabs>
  167 + </div>
  168 +
  169 + <div v-if="currentTab === 'repairDetailPhotos'">
  170 + <repair-detail-photos ref="repairDetailPhotos" :repair-id="repairDetailInfo.repairId"></repair-detail-photos>
  171 + </div>
  172 + <div v-if="currentTab === 'repairDetailResource'">
  173 + <repair-detail-resource ref="repairDetailResource" :repair-id="repairDetailInfo.repairId"></repair-detail-resource>
  174 + </div>
  175 + <div v-if="currentTab === 'repairDetailUser'">
  176 + <repair-detail-user ref="repairDetailUser" :repair-id="repairDetailInfo.repairId"></repair-detail-user>
  177 + </div>
  178 + <div v-if="currentTab === 'repairDetailEvent'">
  179 + <repair-detail-event ref="repairDetailEvent" :repair-id="repairDetailInfo.repairId"></repair-detail-event>
  180 + </div>
  181 +
  182 + <view-image ref="viewImage"></view-image>
  183 + <reply-repair-appraise ref="replyAppraise"></reply-repair-appraise>
  184 + </el-card>
  185 +</template>
  186 +
  187 +<script>
  188 +import { getRepairDetail } from '@/api/work/repairDetailApi'
  189 +import RepairDetailPhotos from '@/components/work/repairDetailPhotos'
  190 +import RepairDetailResource from '@/components/work/repairDetailResource'
  191 +import RepairDetailUser from '@/components/work/repairDetailUser'
  192 +import RepairDetailEvent from '@/components/work/repairDetailEvent'
  193 +import ViewImage from '@/components/work/viewImage'
  194 +import ReplyRepairAppraise from '@/components/work/ReplyRepairAppraise'
  195 +import divider from '@/components/system/divider'
  196 +
  197 +export default {
  198 + name: 'RepairDetailList',
  199 + components: {
  200 + RepairDetailPhotos,
  201 + RepairDetailResource,
  202 + RepairDetailUser,
  203 + RepairDetailEvent,
  204 + ViewImage,
  205 + ReplyRepairAppraise,
  206 + divider
  207 + },
  208 + data() {
  209 + return {
  210 + currentTab: 'repairDetailPhotos',
  211 + repairDetailInfo: {
  212 + repairId: '',
  213 + repairType: '',
  214 + repairTypeName: '',
  215 + repairName: '',
  216 + tel: '',
  217 + roomId: '',
  218 + roomName: '',
  219 + repairObjName: '',
  220 + appointmentTime: '',
  221 + submitHours: '',
  222 + timeout: '',
  223 + finishTime: '',
  224 + context: '',
  225 + stateName: '',
  226 + userId: '',
  227 + userName: '',
  228 + photos: [],
  229 + visitType: '',
  230 + visitContext: '',
  231 + maintenanceType: '',
  232 + repairMaterials: '',
  233 + repairFee: '',
  234 + appraiseScore: 0,
  235 + doorSpeedScore: 0,
  236 + repairmanServiceScore: 0,
  237 + average: 0.0
  238 + }
  239 + }
  240 + },
  241 + created() {
  242 + const repairId = this.$route.query.repairId
  243 + this.repairDetailInfo.repairId = repairId
  244 + this.loadRepairDetail()
  245 + },
  246 + methods: {
  247 + async loadRepairDetail() {
  248 + try {
  249 + const data = await getRepairDetail(this.repairDetailInfo.repairId)
  250 + Object.assign(this.repairDetailInfo, data)
  251 + } catch (error) {
  252 + this.$message.error(error.message)
  253 + }
  254 + },
  255 + goBack() {
  256 + this.$router.go(-1)
  257 + },
  258 + printRepairDetail() {
  259 + window.open(`/print.html#/pages/property/printRepairDetail?repairId=${this.repairDetailInfo.repairId}&repairType=${this.repairDetailInfo.repairType}`)
  260 + },
  261 + changeTab(tab) {
  262 + this.currentTab = tab
  263 + setTimeout(() => {
  264 + if (this.$refs[`${tab}`]) {
  265 + this.$refs[`${tab}`].loadData()
  266 + }
  267 + },500)
  268 + }
  269 + }
  270 +}
  271 +</script>
  272 +
  273 +<style scoped>
  274 +.repair-detail-container {
  275 + padding: 20px;
  276 +}
  277 +
  278 +.text-title {
  279 + font-size: 18px;
  280 + font-weight: bold;
  281 + margin-bottom: 20px;
  282 +}
  283 +
  284 +.margin-top {
  285 + margin-top: 20px;
  286 +}
  287 +
  288 +.margin-top-sm {
  289 + margin-top: 10px;
  290 +}
  291 +
  292 +.flex {
  293 + display: flex;
  294 +}
  295 +
  296 +.justify-between {
  297 + justify-content: space-between;
  298 +}
  299 +
  300 +.el-divider {
  301 + margin: 20px 0;
  302 +}
  303 +
  304 +.el-form-item {
  305 + margin-bottom: 15px;
  306 +}
  307 +</style>
0 \ No newline at end of file 308 \ No newline at end of file
src/views/work/repairDispatchManageLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + repairDispatchManage: {
  4 + searchConditions: 'Search Conditions',
  5 + repairBacklog: 'Repair Backlog',
  6 + placeholder: {
  7 + repairId: 'Please enter work order number',
  8 + repairName: 'Please enter reporter name',
  9 + tel: 'Please enter reporter phone',
  10 + selectRepairType: 'Please select repair type',
  11 + selectStatus: 'Please select status'
  12 + },
  13 + table: {
  14 + location: 'Location',
  15 + repairType: 'Repair Type',
  16 + repairPerson: 'Reporter',
  17 + repairPhone: 'Reporter Phone',
  18 + appointmentTime: 'Appointment Time',
  19 + status: 'Status',
  20 + operation: 'Operation'
  21 + },
  22 + transferOrder: 'Transfer Order',
  23 + returnOrder: 'Return Order',
  24 + complete: 'Complete',
  25 + returnVisit: 'Return Visit',
  26 + pause: 'Pause',
  27 + start: 'Start',
  28 + detail: 'Detail',
  29 + scheduledTask: 'Scheduled Task',
  30 + dispatchRepair: 'Dispatch Repair',
  31 + previousHandler: 'Previous Handler',
  32 + requiredPreviousHandler: 'Required, please fill in the previous handler',
  33 + repairMaster: 'Repair Master',
  34 + requiredRepairMaster: 'Required, please select repair master',
  35 + handlingOpinions: 'Handling Opinions',
  36 + requiredHandlingOpinions: 'Required, please fill in handling opinions',
  37 + returnVisitSuggestion: 'Return Visit Suggestion',
  38 + requiredReturnVisitSuggestion: 'Required, please fill in return visit suggestion',
  39 + pauseReason: 'Pause Reason',
  40 + requiredPauseReason: 'Required, please fill in pause reason',
  41 + confirmOperation: 'Confirm Operation',
  42 + confirmStartRepair: 'Confirm to start the repair?',
  43 + cannotTransferToSelf: 'Cannot transfer the order to yourself',
  44 + fetchRepairListFailed: 'Failed to get repair list',
  45 + fetchRepairTypesFailed: 'Failed to get repair types',
  46 + fetchRepairMasterFailed: 'Failed to get repair masters',
  47 + dispatchFailed: 'Dispatch failed',
  48 + returnVisitFailed: 'Return visit failed',
  49 + pauseFailed: 'Pause failed',
  50 + startFailed: 'Start failed'
  51 + }
  52 + },
  53 + zh: {
  54 + repairDispatchManage: {
  55 + searchConditions: '查询条件',
  56 + repairBacklog: '报修待办',
  57 + placeholder: {
  58 + repairId: '请输入工单编号',
  59 + repairName: '请输入报修人',
  60 + tel: '请输入报修人电话',
  61 + selectRepairType: '请选择报修类型',
  62 + selectStatus: '请选择报修状态'
  63 + },
  64 + table: {
  65 + location: '位置',
  66 + repairType: '报修类型',
  67 + repairPerson: '报修人',
  68 + repairPhone: '报修人电话',
  69 + appointmentTime: '预约时间',
  70 + status: '状态',
  71 + operation: '操作'
  72 + },
  73 + transferOrder: '转单',
  74 + returnOrder: '退单',
  75 + complete: '办结',
  76 + returnVisit: '回访',
  77 + pause: '暂停',
  78 + start: '启动',
  79 + detail: '详情',
  80 + scheduledTask: '定时任务处理',
  81 + dispatchRepair: '报修派单',
  82 + previousHandler: '上级处理人',
  83 + requiredPreviousHandler: '必填,请填写上级处理人',
  84 + repairMaster: '报修师傅',
  85 + requiredRepairMaster: '必填,请选择报修师傅',
  86 + handlingOpinions: '处理意见',
  87 + requiredHandlingOpinions: '必填,请填写处理意见',
  88 + returnVisitSuggestion: '回访建议',
  89 + requiredReturnVisitSuggestion: '必填,请填写回访建议',
  90 + pauseReason: '暂停原因',
  91 + requiredPauseReason: '必填,请填写暂停原因',
  92 + confirmOperation: '确认操作',
  93 + confirmStartRepair: '确定启动报修?',
  94 + cannotTransferToSelf: '不能转单给自己',
  95 + fetchRepairListFailed: '获取报修列表失败',
  96 + fetchRepairTypesFailed: '获取报修类型失败',
  97 + fetchRepairMasterFailed: '获取维修师傅列表失败',
  98 + dispatchFailed: '派单失败',
  99 + returnVisitFailed: '回访失败',
  100 + pauseFailed: '暂停失败',
  101 + startFailed: '启动失败'
  102 + }
  103 + }
  104 +}
0 \ No newline at end of file 105 \ No newline at end of file
src/views/work/repairDispatchManageList.vue 0 → 100644
  1 +<template>
  2 + <div class="padding">
  3 + <el-row :gutter="20">
  4 + <el-col :span="24">
  5 + <el-card>
  6 + <div slot="header" class="flex justify-between">
  7 + <div>{{ $t('repairDispatchManage.searchConditions') }}</div>
  8 + </div>
  9 + <div class="">
  10 + <el-row :gutter="15">
  11 + <el-col :span="4">
  12 + <el-input :placeholder="$t('repairDispatchManage.placeholder.repairId')"
  13 + v-model.trim="repairDispatchManageInfo.conditions.repairId" clearable />
  14 + </el-col>
  15 + <el-col :span="4">
  16 + <el-input :placeholder="$t('repairDispatchManage.placeholder.repairName')"
  17 + v-model.trim="repairDispatchManageInfo.conditions.repairName" clearable />
  18 + </el-col>
  19 + <el-col :span="4">
  20 + <el-input :placeholder="$t('repairDispatchManage.placeholder.tel')"
  21 + v-model.trim="repairDispatchManageInfo.conditions.tel" clearable />
  22 + </el-col>
  23 + <el-col :span="4">
  24 + <el-select v-model="repairDispatchManageInfo.conditions.repairType" style="width:100%">
  25 + <el-option :label="$t('repairDispatchManage.placeholder.selectRepairType')" value="" />
  26 + <el-option v-for="(item, index) in repairDispatchManageInfo.repairTypes" :key="index"
  27 + :label="item.repairTypeName" :value="item.repairType" />
  28 + </el-select>
  29 + </el-col>
  30 + <el-col :span="4">
  31 + <el-select v-model="repairDispatchManageInfo.conditions.state" style="width:100%">
  32 + <el-option :label="$t('repairDispatchManage.placeholder.selectStatus')" value="" />
  33 + <el-option v-for="(item, index) in repairDispatchManageInfo.states" :key="index" :label="item.name"
  34 + :value="item.statusCd" />
  35 + </el-select>
  36 + </el-col>
  37 + <el-col :span="4">
  38 + <el-button type="primary" @click="_queryOwnerRepairMethod">
  39 + <i class="el-icon-search"></i>
  40 + {{ $t('common.search') }}
  41 + </el-button>
  42 + <el-button type="default" @click="_resetOwnerRepairMethod">
  43 + <i class="el-icon-refresh"></i>
  44 + {{ $t('common.reset') }}
  45 + </el-button>
  46 + </el-col>
  47 + </el-row>
  48 + </div>
  49 + </el-card>
  50 + </el-col>
  51 + </el-row>
  52 +
  53 + <el-row :gutter="20" class="margin-top">
  54 + <el-col :span="24">
  55 + <el-card>
  56 + <div slot="header" class="flex justify-between">
  57 + <div>
  58 + <span>{{ repairDispatchManageInfo.conditions.roomName }}</span>
  59 + <span>{{ $t('repairDispatchManage.repairBacklog') }}</span>
  60 + </div>
  61 + </div>
  62 + <div class="">
  63 + <el-table :data="repairDispatchManageInfo.ownerRepairs" border style="width:100%">
  64 + <el-table-column prop="repairObjName" :label="$t('repairDispatchManage.table.location')" align="center" />
  65 + <el-table-column prop="repairTypeName" :label="$t('repairDispatchManage.table.repairType')"
  66 + align="center" />
  67 + <el-table-column prop="repairName" :label="$t('repairDispatchManage.table.repairPerson')" align="center" />
  68 + <el-table-column prop="tel" :label="$t('repairDispatchManage.table.repairPhone')" align="center" />
  69 + <el-table-column prop="appointmentTime" :label="$t('repairDispatchManage.table.appointmentTime')"
  70 + align="center" />
  71 + <el-table-column :label="$t('repairDispatchManage.table.status')" align="center">
  72 + <template slot-scope="scope">
  73 + <span
  74 + v-if="scope.row.state == '1800' && (scope.row.returnVisitFlag == '001' || scope.row.returnVisitFlag == '002')">
  75 + {{ scope.row.stateName }}({{ $t('repairDispatchManage.scheduledTask') }})
  76 + </span>
  77 + <span v-else>
  78 + {{ scope.row.stateName }}
  79 + </span>
  80 + </template>
  81 + </el-table-column>
  82 + <el-table-column :label="$t('common.operation')" align="center" width="300">
  83 + <template slot-scope="scope">
  84 + <el-button-group>
  85 + <el-button
  86 + v-if="(scope.row.state == '1100' || scope.row.state == '1200' || scope.row.state == '1300') && scope.row.state != '2001'"
  87 + size="mini" @click="_openDispatchRepairModel(scope.row)">
  88 + {{ $t('repairDispatchManage.transferOrder') }}
  89 + </el-button>
  90 + <el-button
  91 + v-if="scope.row.preStaffId != '-1' && scope.row.ruId != scope.row.preRuId && scope.row.state != '2001'"
  92 + size="mini" @click="_openBackRepairModel(scope.row)">
  93 + {{ $t('repairDispatchManage.returnOrder') }}
  94 + </el-button>
  95 + <el-button
  96 + v-if="(scope.row.state == '1100' || scope.row.state == '1200' || scope.row.state == '1300') && scope.row.state != '2001'"
  97 + size="mini" @click="_openFinishRepair(scope.row)">
  98 + {{ $t('repairDispatchManage.complete') }}
  99 + </el-button>
  100 + <el-button
  101 + v-if="$store.getters.hasPrivilege('502021040151320003') && scope.row.state == '1800' && scope.row.returnVisitFlag == '003' && scope.row.state != '2001'"
  102 + size="mini" @click="_openAppraiseRepair(scope.row)">
  103 + {{ $t('repairDispatchManage.returnVisit') }}
  104 + </el-button>
  105 + <el-button v-if="scope.row.state == '1100' || scope.row.state == '1200' || scope.row.state == '1300'"
  106 + size="mini" @click="_openStopRepair(scope.row)">
  107 + {{ $t('repairDispatchManage.pause') }}
  108 + </el-button>
  109 + <el-button v-if="scope.row.state == '2001'" size="mini" @click="_openStartRepair(scope.row)">
  110 + {{ $t('repairDispatchManage.start') }}
  111 + </el-button>
  112 + <el-button size="mini" @click="_openDispatchRepairDetail(scope.row)">
  113 + {{ $t('common.detail') }}
  114 + </el-button>
  115 + </el-button-group>
  116 + </template>
  117 + </el-table-column>
  118 + </el-table>
  119 + <el-pagination :current-page.sync="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size"
  120 + :total="page.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
  121 + @current-change="handleCurrentChange" class="pagination" />
  122 + </div>
  123 + </el-card>
  124 + </el-col>
  125 + </el-row>
  126 +
  127 + <dispatch-repair ref="dispatchRepair" @success="handleSuccess" />
  128 + <appraise-repair ref="appraiseRepair" @success="handleSuccess" />
  129 + <stop-repair ref="stopRepair" @success="handleSuccess" />
  130 + <start-repair ref="startRepair" @success="handleSuccess" />
  131 + </div>
  132 +</template>
  133 +
  134 +<script>
  135 +import { listStaffRepairs, listRepairSettings } from '@/api/work/repairDispatchManageApi'
  136 +import { getDict } from '@/api/community/communityApi'
  137 +import { getCommunityId } from '@/api/community/communityApi'
  138 +import DispatchRepair from '@/components/work/dispatchRepair'
  139 +import AppraiseRepair from '@/components/work/AppraiseRepair'
  140 +import StopRepair from '@/components/work/StopRepair'
  141 +import StartRepair from '@/components/work/StartRepair'
  142 +
  143 +export default {
  144 + name: 'RepairDispatchManageList',
  145 + components: {
  146 + DispatchRepair,
  147 + AppraiseRepair,
  148 + StopRepair,
  149 + StartRepair
  150 + },
  151 + data() {
  152 + return {
  153 + repairDispatchManageInfo: {
  154 + ownerRepairs: [],
  155 + total: 0,
  156 + records: 1,
  157 + moreCondition: false,
  158 + repairTypes: [],
  159 + states: [],
  160 + conditions: {
  161 + repairId: '',
  162 + repairName: '',
  163 + tel: '',
  164 + repairType: '',
  165 + roomId: '',
  166 + roomName: '',
  167 + ownerId: '',
  168 + userId: '',
  169 + userName: '',
  170 + state: ''
  171 + }
  172 + },
  173 + page: {
  174 + current: 1,
  175 + size: 10,
  176 + total: 0
  177 + }
  178 + }
  179 + },
  180 + created() {
  181 + this.communityId = getCommunityId()
  182 + this._initData()
  183 + },
  184 + methods: {
  185 + async _initData() {
  186 + try {
  187 + // 获取报修类型字典
  188 + this.repairDispatchManageInfo.states = await getDict('r_repair_pool', 'state')
  189 + this._listRepairTypes()
  190 + this._listOwnerRepairs()
  191 + } catch (error) {
  192 + console.error('初始化数据失败:', error)
  193 + this.$message.error(this.$t('common.initFailed'))
  194 + }
  195 + },
  196 + async _listOwnerRepairs() {
  197 + try {
  198 + const params = {
  199 + ...this.repairDispatchManageInfo.conditions,
  200 + page: this.page.current,
  201 + row: this.page.size,
  202 + communityId: this.communityId
  203 + }
  204 +
  205 + const res = await listStaffRepairs(params)
  206 + this.repairDispatchManageInfo.ownerRepairs = res.data
  207 + this.page.total = res.total
  208 + } catch (error) {
  209 + console.error('获取报修列表失败:', error)
  210 + this.$message.error(this.$t('repairDispatchManage.fetchRepairListFailed'))
  211 + }
  212 + },
  213 + async _listRepairTypes() {
  214 + try {
  215 + const params = {
  216 + page: 1,
  217 + row: 50,
  218 + communityId: this.communityId
  219 + }
  220 +
  221 + const res = await listRepairSettings(params)
  222 + this.repairDispatchManageInfo.repairTypes = res.data
  223 + } catch (error) {
  224 + console.error('获取报修类型失败:', error)
  225 + this.$message.error(this.$t('repairDispatchManage.fetchRepairTypesFailed'))
  226 + }
  227 + },
  228 + _queryOwnerRepairMethod() {
  229 + this.page.current = 1
  230 + this._listOwnerRepairs()
  231 + },
  232 + _resetOwnerRepairMethod() {
  233 + this.repairDispatchManageInfo.conditions.repairId = ''
  234 + this.repairDispatchManageInfo.conditions.repairName = ''
  235 + this.repairDispatchManageInfo.conditions.tel = ''
  236 + this.repairDispatchManageInfo.conditions.repairType = ''
  237 + this.repairDispatchManageInfo.conditions.state = ''
  238 + this._listOwnerRepairs()
  239 + },
  240 + _openDispatchRepairModel(row) {
  241 + this.$refs.dispatchRepair.open({ ...row, action: 'TRANSFER' })
  242 + },
  243 + _openBackRepairModel(row) {
  244 + this.$refs.dispatchRepair.open({ ...row, action: 'BACK' })
  245 + },
  246 + _openFinishRepair(row) {
  247 + this.$router.push({
  248 + path: '/property/finishRepair',
  249 + query: {
  250 + repairType: row.repairType,
  251 + repairId: row.repairId,
  252 + repairObjType: row.repairObjType,
  253 + publicArea: row.publicArea,
  254 + repairChannel: row.repairChannel
  255 + }
  256 + })
  257 + },
  258 + _openDispatchRepairDetail(row) {
  259 + this.$router.push({
  260 + path: '/property/ownerRepairDetail',
  261 + query: { repairId: row.repairId }
  262 + })
  263 + },
  264 + _openAppraiseRepair(row) {
  265 + this.$refs.appraiseRepair.open(row)
  266 + },
  267 + _openStopRepair(row) {
  268 + this.$refs.stopRepair.open(row)
  269 + },
  270 + _openStartRepair(row) {
  271 + this.$refs.startRepair.open(row)
  272 + },
  273 + handleSizeChange(size) {
  274 + this.page.size = size
  275 + this._listOwnerRepairs()
  276 + },
  277 + handleCurrentChange(current) {
  278 + this.page.current = current
  279 + this._listOwnerRepairs()
  280 + },
  281 + handleSuccess() {
  282 + this._listOwnerRepairs()
  283 + }
  284 + }
  285 +}
  286 +</script>
  287 +
  288 +<style scoped>
  289 +.ibox-content {
  290 + padding: 15px 20px 20px 20px;
  291 +}
  292 +
  293 +.pagination {
  294 + margin-top: 15px;
  295 + text-align: right;
  296 +}
  297 +</style>
0 \ No newline at end of file 298 \ No newline at end of file
src/views/work/repairForceFinishManageLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + repairForceFinishManage: {
  4 + searchCondition: 'Search Conditions',
  5 + repairTypePlaceholder: 'Select Repair Type',
  6 + repairPersonPlaceholder: 'Enter Repair Person',
  7 + repairPhonePlaceholder: 'Enter Repair Phone',
  8 + search: 'Search',
  9 + reset: 'Reset',
  10 + forceFinish: 'Force Finish',
  11 + repairId: 'Work Order ID',
  12 + location: 'Location',
  13 + repairType: 'Repair Type',
  14 + repairPerson: 'Repair Person',
  15 + contact: 'Contact',
  16 + appointmentTime: 'Appointment Time',
  17 + submitTime: 'Submit Time',
  18 + status: 'Status',
  19 + operation: 'Operation',
  20 + detail: 'Detail',
  21 + description: 'Description: This function is mainly used to solve the scenario where the maintenance master is too old to use the mobile phone operation, and the customer service personnel need to confirm the maintenance completion and force the order back'
  22 + },
  23 + forceFinishRepair: {
  24 + title: 'Force Finish',
  25 + useMaterial: 'Use Material?',
  26 + maintenanceType: 'Maintenance Type',
  27 + goodsType: 'Goods Type',
  28 + goodsName: 'Goods Name',
  29 + customPrice: 'Custom Price',
  30 + secondaryCategory: 'Secondary Category',
  31 + goods: 'Goods',
  32 + goodsPrice: 'Goods Price',
  33 + priceRange: 'Price Range',
  34 + specification: 'Specification',
  35 + quantity: 'Quantity',
  36 + paymentMethod: 'Payment Method',
  37 + explanation: 'Explanation',
  38 + submit: 'Submit',
  39 + cancel: 'Cancel'
  40 + },
  41 + chooseSingleResource: {
  42 + title: 'Select Item',
  43 + goodsType: 'Goods Type',
  44 + secondaryCategory: 'Secondary Category',
  45 + goods: 'Goods',
  46 + goodsPrice: 'Goods Price',
  47 + priceRange: 'Price Range',
  48 + specification: 'Specification',
  49 + quantity: 'Quantity',
  50 + confirm: 'Confirm',
  51 + cancel: 'Cancel'
  52 + }
  53 + },
  54 + zh: {
  55 + repairForceFinishManage: {
  56 + searchCondition: '查询条件',
  57 + repairTypePlaceholder: '请选择报修类型',
  58 + repairPersonPlaceholder: '请输入报修人',
  59 + repairPhonePlaceholder: '请输入报修电话',
  60 + search: '查询',
  61 + reset: '重置',
  62 + forceFinish: '强制回单',
  63 + repairId: '工单编号',
  64 + location: '位置',
  65 + repairType: '报修类型',
  66 + repairPerson: '报修人',
  67 + contact: '联系方式',
  68 + appointmentTime: '预约时间',
  69 + submitTime: '提交时间',
  70 + status: '状态',
  71 + operation: '操作',
  72 + detail: '详情',
  73 + description: '说明:此功能主要为了解决维修师傅年龄大不会使用手机操作,需要客服人员确认维修完后强制回单场景'
  74 + },
  75 + forceFinishRepair: {
  76 + title: '强制回单',
  77 + useMaterial: '是否用料',
  78 + maintenanceType: '维修类型',
  79 + goodsType: '商品类型',
  80 + goodsName: '商品名',
  81 + customPrice: '自定义价格',
  82 + secondaryCategory: '二级分类',
  83 + goods: '商品',
  84 + goodsPrice: '商品价格',
  85 + priceRange: '价格范围',
  86 + specification: '规格',
  87 + quantity: '商品数量',
  88 + paymentMethod: '支付方式',
  89 + explanation: '说明',
  90 + submit: '提交',
  91 + cancel: '取消'
  92 + },
  93 + chooseSingleResource: {
  94 + title: '选择物品',
  95 + goodsType: '商品类型',
  96 + secondaryCategory: '二级分类',
  97 + goods: '商品',
  98 + goodsPrice: '商品价格',
  99 + priceRange: '价格范围',
  100 + specification: '规格',
  101 + quantity: '商品数量',
  102 + confirm: '确定',
  103 + cancel: '取消'
  104 + }
  105 + }
  106 +}
0 \ No newline at end of file 107 \ No newline at end of file
src/views/work/repairForceFinishManageList.vue 0 → 100644
  1 +<template>
  2 + <div class="repair-force-finish-container">
  3 + <!-- 查询条件 -->
  4 + <el-card class="search-card">
  5 + <div slot="header" class="flex justify-between">
  6 + <span>{{ $t('repairForceFinishManage.searchCondition') }}</span>
  7 + </div>
  8 +
  9 + <el-row :gutter="20">
  10 + <el-col :span="6">
  11 + <el-select v-model="searchForm.repairType" :placeholder="$t('repairForceFinishManage.repairTypePlaceholder')"
  12 + clearable style="width:100%">
  13 + <el-option v-for="item in repairSettings" :key="item.repairType" :label="item.repairTypeName"
  14 + :value="item.repairType" />
  15 + </el-select>
  16 + </el-col>
  17 +
  18 + <el-col :span="6">
  19 + <el-input v-model="searchForm.repairName" :placeholder="$t('repairForceFinishManage.repairPersonPlaceholder')"
  20 + clearable />
  21 + </el-col>
  22 +
  23 + <el-col :span="6">
  24 + <el-input v-model="searchForm.tel" :placeholder="$t('repairForceFinishManage.repairPhonePlaceholder')"
  25 + clearable />
  26 + </el-col>
  27 +
  28 + <el-col :span="6">
  29 + <el-button type="primary" @click="queryRepairPool">
  30 + <i class="el-icon-search"></i>
  31 + {{ $t('repairForceFinishManage.search') }}
  32 + </el-button>
  33 + <el-button @click="resetRepairPool" style="margin-left:10px">
  34 + <i class="el-icon-refresh"></i>
  35 + {{ $t('repairForceFinishManage.reset') }}
  36 + </el-button>
  37 + </el-col>
  38 + </el-row>
  39 + </el-card>
  40 +
  41 + <!-- 报修列表 -->
  42 + <el-card class="list-card">
  43 + <div slot="header" class="flex justify-between">
  44 + <span>{{ searchForm.roomName }} {{ $t('repairForceFinishManage.forceFinish') }}</span>
  45 + </div>
  46 +
  47 + <el-table :data="repairPools" border v-loading="loading">
  48 + <el-table-column prop="repairId" :label="$t('repairForceFinishManage.repairId')" align="center" />
  49 + <el-table-column prop="repairObjName" :label="$t('repairForceFinishManage.location')" align="center" />
  50 + <el-table-column prop="repairTypeName" :label="$t('repairForceFinishManage.repairType')" align="center" />
  51 + <el-table-column prop="repairName" :label="$t('repairForceFinishManage.repairPerson')" align="center" />
  52 + <el-table-column prop="tel" :label="$t('repairForceFinishManage.contact')" align="center" />
  53 + <el-table-column prop="appointmentTime" :label="$t('repairForceFinishManage.appointmentTime')" align="center" />
  54 + <el-table-column prop="createTime" :label="$t('repairForceFinishManage.submitTime')" align="center" />
  55 + <el-table-column prop="stateName" :label="$t('repairForceFinishManage.status')" align="center" />
  56 + <el-table-column :label="$t('repairForceFinishManage.operation')" align="center" width="200">
  57 + <template slot-scope="scope">
  58 + <el-button size="mini" type="primary" @click="openForceFinishRepair(scope.row)">
  59 + {{ $t('repairForceFinishManage.forceFinish') }}
  60 + </el-button>
  61 + <el-button size="mini" @click="openRepairDetail(scope.row)">
  62 + {{ $t('repairForceFinishManage.detail') }}
  63 + </el-button>
  64 + </template>
  65 + </el-table-column>
  66 + </el-table>
  67 +
  68 + <el-row class="footer-row">
  69 + <el-col :span="18">
  70 + <div class="description">
  71 + {{ $t('repairForceFinishManage.description') }}
  72 + </div>
  73 + </el-col>
  74 + <el-col :span="6">
  75 + <el-pagination :current-page="pagination.current" :page-sizes="[10, 20, 30, 50]" :page-size="pagination.size"
  76 + :total="pagination.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
  77 + @current-change="handleCurrentChange" />
  78 + </el-col>
  79 + </el-row>
  80 + </el-card>
  81 +
  82 + <!-- 强制回单弹窗 -->
  83 + <force-finish-repair ref="forceFinishDialog" :visible.sync="forceFinishVisible" @success="handleForceFinishSuccess" />
  84 + </div>
  85 +</template>
  86 +
  87 +<script>
  88 +import {
  89 + listRepairSettings,
  90 + listOwnerRepairs,
  91 + getDict
  92 +} from '@/api/work/repairForceFinishManageApi'
  93 +import ForceFinishRepair from '@/components/work/forceFinishRepair'
  94 +
  95 +export default {
  96 + name: 'RepairForceFinishManageList',
  97 + components: {
  98 + ForceFinishRepair
  99 + },
  100 + data() {
  101 + return {
  102 + searchForm: {
  103 + repairType: '',
  104 + repairName: '',
  105 + tel: '',
  106 + roomId: '',
  107 + roomName: '',
  108 + state: '1100'
  109 + },
  110 + repairPools: [],
  111 + repairSettings: [],
  112 + states: [],
  113 + loading: false,
  114 + forceFinishVisible: false,
  115 + pagination: {
  116 + current: 1,
  117 + size: 10,
  118 + total: 0
  119 + }
  120 + }
  121 + },
  122 + mounted() {
  123 + this.loadRepairSettings()
  124 + this.loadDictData()
  125 + this.listRepairPools()
  126 + },
  127 + methods: {
  128 + async loadRepairSettings() {
  129 + try {
  130 + this.repairSettings = await listRepairSettings()
  131 + } catch (error) {
  132 + console.error('获取报修设置失败:', error)
  133 + this.$message.error('获取报修设置失败')
  134 + }
  135 + },
  136 + async loadDictData() {
  137 + try {
  138 + this.states = await getDict('r_repair_pool', 'state')
  139 + } catch (error) {
  140 + console.error('获取状态字典失败:', error)
  141 + this.$message.error('获取状态字典失败')
  142 + }
  143 + },
  144 + async listRepairPools() {
  145 + this.loading = true
  146 + try {
  147 + const params = {
  148 + ...this.searchForm,
  149 + page: this.pagination.current,
  150 + row: this.pagination.size
  151 + }
  152 +
  153 + // 清理空值
  154 + Object.keys(params).forEach(key => {
  155 + if (params[key] === '') delete params[key]
  156 + })
  157 +
  158 + const { data, total } = await listOwnerRepairs(params)
  159 + this.repairPools = data
  160 + this.pagination.total = total
  161 + } catch (error) {
  162 + console.error('获取报修列表失败:', error)
  163 + this.$message.error('获取报修列表失败')
  164 + } finally {
  165 + this.loading = false
  166 + }
  167 + },
  168 + queryRepairPool() {
  169 + this.pagination.current = 1
  170 + this.listRepairPools()
  171 + },
  172 + resetRepairPool() {
  173 + this.searchForm = {
  174 + repairType: '',
  175 + repairName: '',
  176 + tel: '',
  177 + state: '1100'
  178 + }
  179 + this.queryRepairPool()
  180 + },
  181 + openForceFinishRepair(repair) {
  182 + this.forceFinishVisible = true
  183 + this.$nextTick(() => {
  184 + this.$refs.forceFinishDialog.open(repair)
  185 + })
  186 + },
  187 + openRepairDetail(repair) {
  188 + this.$router.push(`/work/repairDetail/${repair.repairId}`)
  189 + },
  190 + handleForceFinishSuccess() {
  191 + this.listRepairPools()
  192 + },
  193 + handleSizeChange(size) {
  194 + this.pagination.size = size
  195 + this.listRepairPools()
  196 + },
  197 + handleCurrentChange(current) {
  198 + this.pagination.current = current
  199 + this.listRepairPools()
  200 + }
  201 + }
  202 +}
  203 +</script>
  204 +
  205 +<style lang="scss" scoped>
  206 +.repair-force-finish-container {
  207 + padding: 20px;
  208 +
  209 + .search-card {
  210 + margin-bottom: 20px;
  211 + }
  212 +
  213 + .list-card {
  214 + margin-bottom: 20px;
  215 + }
  216 +
  217 + .footer-row {
  218 + margin-top: 20px;
  219 + display: flex;
  220 + align-items: center;
  221 +
  222 + .description {
  223 + font-size: 14px;
  224 + color: #999;
  225 + }
  226 + }
  227 +
  228 + .el-pagination {
  229 + display: flex;
  230 + justify-content: flex-end;
  231 + }
  232 +}
  233 +</style>
0 \ No newline at end of file 234 \ No newline at end of file
src/views/work/repairPoolManageLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + repairPoolManage: {
  4 + queryConditions: 'Query Conditions',
  5 + repairOrderPool: 'Repair Order Pool',
  6 + workOrderCode: 'Work Order Code',
  7 + location: 'Location',
  8 + repairType: 'Repair Type',
  9 + maintenanceType: 'Maintenance Type',
  10 + repairPerson: 'Repair Person',
  11 + contact: 'Contact',
  12 + appointmentTime: 'Appointment Time',
  13 + submissionTime: 'Submission Time',
  14 + submissionDuration: 'Submission Duration',
  15 + completionTime: 'Completion Time',
  16 + status: 'Status',
  17 + operation: 'Operation',
  18 + modify: 'Modify',
  19 + dispatch: 'Dispatch',
  20 + grabOrder: 'Grab Order',
  21 + end: 'End',
  22 + details: 'Details',
  23 + delete: 'Delete',
  24 + search: 'Search',
  25 + reset: 'Reset',
  26 + more: 'More',
  27 + hide: 'Hide',
  28 + all: 'All',
  29 + timeoutOrders: 'Timeout Orders',
  30 + workOrderNumber: 'Work Order Number',
  31 + repairPersonName: 'Repair Person Name',
  32 + repairPhone: 'Repair Phone',
  33 + selectRepairType: 'Select Repair Type',
  34 + selectRepairSettingType: 'Select Repair Setting Type',
  35 + repairLocation: 'Repair Location',
  36 + selectMaintenanceType: 'Select Maintenance Type',
  37 + startTime: 'Start Time',
  38 + endTime: 'End Time',
  39 + repairSettingType: 'Repair Setting Type',
  40 + repairContent: 'Repair Content',
  41 + operationSuggestions: 'Operation Suggestions',
  42 + endReason: 'End Reason',
  43 + }
  44 + },
  45 + zh: {
  46 + repairPoolManage: {
  47 + queryConditions: '查询条件',
  48 + repairOrderPool: '报修工单池',
  49 + workOrderCode: '工单编码',
  50 + location: '位置',
  51 + repairType: '报修类型',
  52 + maintenanceType: '维修类型',
  53 + repairPerson: '报修人',
  54 + contact: '联系方式',
  55 + appointmentTime: '预约时间',
  56 + submissionTime: '提交时间',
  57 + submissionDuration: '提单时长',
  58 + completionTime: '完成时间',
  59 + status: '状态',
  60 + operation: '操作',
  61 + modify: '修改',
  62 + dispatch: '派单',
  63 + grabOrder: '抢单',
  64 + end: '结束',
  65 + details: '详情',
  66 + delete: '删除',
  67 + search: '查询',
  68 + reset: '重置',
  69 + more: '更多',
  70 + hide: '隐藏',
  71 + all: '全部',
  72 + timeoutOrders: '超时工单',
  73 + workOrderNumber: '工单编号',
  74 + repairPersonName: '报修人',
  75 + repairPhone: '报修电话',
  76 + selectRepairType: '请选择报修类型',
  77 + selectRepairSettingType: '请选择报修设置类型',
  78 + repairLocation: '报修位置',
  79 + selectMaintenanceType: '请选择维修类型',
  80 + startTime: '开始时间',
  81 + endTime: '结束时间',
  82 + repairSettingType: '报修设置类型',
  83 + repairContent: '报修内容',
  84 + operationSuggestions: '说明',
  85 + endReason: '结束原因',
  86 + }
  87 + }
  88 +}
0 \ No newline at end of file 89 \ No newline at end of file
src/views/work/repairPoolManageList.vue 0 → 100644
  1 +<template>
  2 + <div class="app-container">
  3 + <el-row :gutter="20">
  4 + <!-- 左侧状态栏 -->
  5 + <el-col :span="3">
  6 + <el-card>
  7 + <div class="status-list">
  8 + <div v-for="(item, index) in states" :key="index" class="status-item"
  9 + :class="{ 'status-active': conditions.state === item.statusCd }" @click="switchRepairState(item)">
  10 + {{ item.name }}
  11 + </div>
  12 + </div>
  13 + </el-card>
  14 + </el-col>
  15 +
  16 + <!-- 右侧内容 -->
  17 + <el-col :span="21">
  18 + <!-- 查询条件 -->
  19 + <el-card class="box-card">
  20 + <div slot="header" class="flex justify-between">
  21 + <span>{{ $t('repairPoolManage.queryConditions') }}</span>
  22 + <el-button style="float: right; padding: 3px 0" type="text" @click="toggleMoreCondition">
  23 + {{ moreCondition ? $t('repairPoolManage.hide') : $t('repairPoolManage.more') }}
  24 + </el-button>
  25 + </div>
  26 +
  27 + <el-form :model="conditions" label-width="auto">
  28 + <el-row :gutter="20">
  29 + <el-col :span="4">
  30 + <el-form-item>
  31 + <el-input v-model="conditions.repairId" :placeholder="$t('repairPoolManage.workOrderNumber')" />
  32 + </el-form-item>
  33 + </el-col>
  34 +
  35 + <el-col :span="4">
  36 + <el-form-item>
  37 + <el-input v-model="conditions.repairName" :placeholder="$t('repairPoolManage.repairPersonName')" />
  38 + </el-form-item>
  39 + </el-col>
  40 +
  41 + <el-col :span="4">
  42 + <el-form-item>
  43 + <el-input v-model="conditions.tel" :placeholder="$t('repairPoolManage.repairPhone')" />
  44 + </el-form-item>
  45 + </el-col>
  46 +
  47 + <el-col :span="4">
  48 + <el-form-item>
  49 + <el-select v-model="conditions.repairType" :placeholder="$t('repairPoolManage.selectRepairType')"
  50 + style="width:100%">
  51 + <el-option v-for="(item, index) in repairSettings" :key="index" :label="item.repairTypeName"
  52 + :value="item.repairType" />
  53 + </el-select>
  54 + </el-form-item>
  55 + </el-col>
  56 + <el-col :span="4">
  57 + <el-form-item>
  58 + <el-input v-model="conditions.repairObjName" :placeholder="$t('repairPoolManage.repairLocation')" />
  59 + </el-form-item>
  60 + </el-col>
  61 +
  62 + <el-col :span="4">
  63 + <el-form-item>
  64 + <el-select v-model="conditions.maintenanceType"
  65 + :placeholder="$t('repairPoolManage.selectMaintenanceType')" style="width:100%">
  66 + <el-option v-for="(item, index) in maintenanceTypes" :key="index" :label="item.name"
  67 + :value="item.statusCd" />
  68 + </el-select>
  69 + </el-form-item>
  70 + </el-col>
  71 +
  72 + <el-col :span="4">
  73 + <el-form-item>
  74 + <el-date-picker v-model="conditions.startTime" type="datetime" style="width:100%"
  75 + :placeholder="$t('repairPoolManage.startTime')" value-format="yyyy-MM-dd HH:mm:ss" />
  76 + </el-form-item>
  77 + </el-col>
  78 +
  79 + <el-col :span="4">
  80 + <el-form-item>
  81 + <el-date-picker v-model="conditions.endTime" type="datetime" style="width:100%"
  82 + :placeholder="$t('repairPoolManage.endTime')" value-format="yyyy-MM-dd HH:mm:ss" />
  83 + </el-form-item>
  84 + </el-col>
  85 + <el-col :span="4" >
  86 + <el-button type="primary" @click="queryRepairPool">{{ $t('repairPoolManage.search') }}</el-button>
  87 + <el-button @click="resetRepairPool">{{ $t('repairPoolManage.reset') }}</el-button>
  88 + </el-col>
  89 + </el-row>
  90 + </el-form>
  91 + </el-card>
  92 +
  93 + <!-- 报修工单池 -->
  94 + <el-card class="box-card">
  95 + <div slot="header" class="clearfix flex justify-between">
  96 + <span>{{ $t('repairPoolManage.repairOrderPool') }}</span>
  97 + </div>
  98 +
  99 + <el-table v-loading="loading" :data="repairPools" border style="width: 100%">
  100 + <el-table-column prop="repairId" :label="$t('repairPoolManage.workOrderCode')" align="center" />
  101 + <el-table-column prop="repairObjName" :label="$t('repairPoolManage.location')" align="center" />
  102 + <el-table-column prop="repairTypeName" :label="$t('repairPoolManage.repairType')" align="center" />
  103 + <el-table-column :label="$t('repairPoolManage.maintenanceType')" align="center">
  104 + <template slot-scope="scope">
  105 + {{ formatMaintenanceType(scope.row.maintenanceType) }}
  106 + </template>
  107 + </el-table-column>
  108 + <el-table-column prop="repairName" :label="$t('repairPoolManage.repairPerson')" align="center" />
  109 + <el-table-column prop="tel" :label="$t('repairPoolManage.contact')" align="center" />
  110 + <el-table-column :label="$t('repairPoolManage.appointmentTime')" align="center">
  111 + <template slot-scope="scope">
  112 + <div>{{ scope.row.appointmentTime }}</div>
  113 + <div>~{{ scope.row.timeout }}</div>
  114 + </template>
  115 + </el-table-column>
  116 + <el-table-column prop="createTime" :label="$t('repairPoolManage.submissionTime')" align="center" />
  117 + <el-table-column prop="submitHours" :label="$t('repairPoolManage.submissionDuration')" align="center">
  118 + <template slot-scope="scope">
  119 + {{ scope.row.submitHours || '0' }}
  120 + </template>
  121 + </el-table-column>
  122 + <el-table-column prop="finishTime" :label="$t('repairPoolManage.completionTime')" align="center">
  123 + <template slot-scope="scope">
  124 + {{ scope.row.finishTime || '-' }}
  125 + </template>
  126 + </el-table-column>
  127 + <el-table-column :label="$t('repairPoolManage.status')" align="center">
  128 + <template slot-scope="scope">
  129 + <span v-if="scope.row.state === '1800' && ['001', '002'].includes(scope.row.returnVisitFlag)">
  130 + {{ scope.row.stateName }}({{ $t('repairPoolManage.timedTaskProcessing') }})
  131 + </span>
  132 + <span v-else>{{ scope.row.stateName }}</span>
  133 + </template>
  134 + </el-table-column>
  135 + <el-table-column :label="$t('repairPoolManage.operation')" align="center" width="300">
  136 + <template slot-scope="scope">
  137 + <el-button v-if="hasPrivilege('502021012067300023') && ['1000', '1200'].includes(scope.row.state)"
  138 + size="mini" @click="openEditModal(scope.row)">
  139 + {{ $t('repairPoolManage.modify') }}
  140 + </el-button>
  141 +
  142 + <el-button v-if="hasPrivilege('502019101946430010') && scope.row.state === '1000'" size="mini"
  143 + type="primary" @click="openDispatchModal(scope.row)">
  144 + {{ $t('repairPoolManage.dispatch') }}
  145 + </el-button>
  146 +
  147 + <el-button
  148 + v-if="hasPrivilege('502021012099350016') && scope.row.state === '1000' && scope.row.repairWay === '100'"
  149 + size="mini" type="success" @click="grabOrder(scope.row)">
  150 + {{ $t('repairPoolManage.grabOrder') }}
  151 + </el-button>
  152 +
  153 + <el-button
  154 + v-if="hasPrivilege('502019101946430010') && !['1900', '1700', '1800'].includes(scope.row.state)"
  155 + size="mini" type="warning" @click="openEndModal(scope.row)">
  156 + {{ $t('repairPoolManage.end') }}
  157 + </el-button>
  158 +
  159 + <el-button size="mini" type="info" @click="openDetail(scope.row)">
  160 + {{ $t('repairPoolManage.details') }}
  161 + </el-button>
  162 +
  163 + <el-button v-if="hasPrivilege('502021012051410024') && ['1000', '1200'].includes(scope.row.state)"
  164 + size="mini" type="danger" @click="openDeleteModal(scope.row.repairId)">
  165 + {{ $t('repairPoolManage.delete') }}
  166 + </el-button>
  167 + </template>
  168 + </el-table-column>
  169 + </el-table>
  170 +
  171 + <!-- 分页 -->
  172 + <el-pagination background layout="total, sizes, prev, pager, next, jumper" :current-page="page.current"
  173 + :page-sizes="[10, 20, 30, 50]" :page-size="page.size" :total="page.total" @size-change="handleSizeChange"
  174 + @current-change="handleCurrentChange" />
  175 + </el-card>
  176 + </el-col>
  177 + </el-row>
  178 +
  179 + <!-- 组件 -->
  180 + <dispatch-repair ref="dispatchRepair" @success="fetchData" />
  181 + <end-repair ref="endRepair" @success="fetchData" />
  182 + <edit-owner-repair ref="editOwnerRepair" @success="fetchData" />
  183 + <delete-owner-repair ref="deleteOwnerRepair" @success="fetchData" />
  184 + </div>
  185 +</template>
  186 +
  187 +<script>
  188 +import { listRepairPools, grabbingRepair } from '@/api/work/repairPoolManageApi'
  189 +import { getDict } from '@/api/community/communityApi'
  190 +import { getCommunityId } from '@/api/community/communityApi'
  191 +import DispatchRepair from '@/components/work/dispatchRepair'
  192 +import EndRepair from '@/components/work/endRepair'
  193 +import EditOwnerRepair from '@/components/work/editOwnerRepair'
  194 +import DeleteOwnerRepair from '@/components/work/deleteOwnerRepair'
  195 +import {listRepairSettings} from '@/api/work/ownerRepairManageApi'
  196 +
  197 +export default {
  198 + name: 'RepairPoolManage',
  199 + components: {
  200 + DispatchRepair,
  201 + EndRepair,
  202 + EditOwnerRepair,
  203 + DeleteOwnerRepair
  204 + },
  205 + data() {
  206 + return {
  207 + loading: false,
  208 + repairPools: [],
  209 + repairSettings: [],
  210 + states: [],
  211 + repairSettingTypes: [],
  212 + maintenanceTypes: [],
  213 + moreCondition: false,
  214 + conditions: {
  215 + repairId: '',
  216 + repairName: '',
  217 + tel: '',
  218 + repairType: '',
  219 + repairSettingType: '',
  220 + roomId: '',
  221 + roomName: '',
  222 + ownerId: '',
  223 + state: '',
  224 + maintenanceType: '',
  225 + startTime: '',
  226 + endTime: '',
  227 + repairObjName: ''
  228 + },
  229 + page: {
  230 + current: 1,
  231 + size: 10,
  232 + total: 0
  233 + }
  234 + }
  235 + },
  236 + created() {
  237 + this.fetchData()
  238 + this.fetchRepairSettings()
  239 + this.loadDictData()
  240 + },
  241 + methods: {
  242 + async fetchData() {
  243 + this.loading = true
  244 + try {
  245 + const params = {
  246 + ...this.conditions,
  247 + page: this.page.current,
  248 + row: this.page.size
  249 + }
  250 +
  251 + const res = await listRepairPools(params)
  252 + this.repairPools = res.data || []
  253 + this.page.total = res.total || 0
  254 + } catch (error) {
  255 + console.error('Failed to fetch repair pools:', error)
  256 + } finally {
  257 + this.loading = false
  258 + }
  259 + },
  260 +
  261 + async fetchRepairSettings() {
  262 + try {
  263 + const params = {
  264 + page: 1,
  265 + row: 50,
  266 + communityId: getCommunityId()
  267 + }
  268 +
  269 + const res = await listRepairSettings(params)
  270 + this.repairSettings = res.data || []
  271 + } catch (error) {
  272 + console.error('Failed to fetch repair settings:', error)
  273 + }
  274 + },
  275 +
  276 + async loadDictData() {
  277 + try {
  278 + // 获取状态字典
  279 + const stateData = await getDict('r_repair_pool', 'state')
  280 + this.states = [
  281 + { statusCd: '', name: this.$t('repairPoolManage.all') },
  282 + { statusCd: 'TIMEOUT', name: this.$t('repairPoolManage.timeoutOrders') },
  283 + ...(stateData || [])
  284 + ]
  285 +
  286 + // 获取报修设置类型字典
  287 + this.repairSettingTypes = await getDict('r_repair_setting', 'repair_setting_type')
  288 +
  289 + // 获取维修类型字典
  290 + this.maintenanceTypes = await getDict('r_repair_pool', 'maintenance_type')
  291 + } catch (error) {
  292 + console.error('Failed to load dict data:', error)
  293 + }
  294 + },
  295 +
  296 + formatMaintenanceType(type) {
  297 + const types = {
  298 + '1001': this.$t('repairPoolManage.paidService'),
  299 + '1002': this.$t('repairPoolManage.freeService'),
  300 + '1003': this.$t('repairPoolManage.needMaterials'),
  301 + '1004': this.$t('repairPoolManage.noMaterialsNeeded')
  302 + }
  303 + return types[type] || '--'
  304 + },
  305 +
  306 + switchRepairState(item) {
  307 + this.conditions.state = item.statusCd
  308 + this.fetchData()
  309 + },
  310 +
  311 + toggleMoreCondition() {
  312 + this.moreCondition = !this.moreCondition
  313 + },
  314 +
  315 + queryRepairPool() {
  316 + this.page.current = 1
  317 + this.fetchData()
  318 + },
  319 +
  320 + resetRepairPool() {
  321 + this.conditions = {
  322 + repairId: '',
  323 + repairName: '',
  324 + tel: '',
  325 + repairType: '',
  326 + repairSettingType: '',
  327 + repairObjName: '',
  328 + maintenanceType: '',
  329 + startTime: '',
  330 + endTime: '',
  331 + state: this.conditions.state // 保持当前状态
  332 + }
  333 + this.fetchData()
  334 + },
  335 +
  336 + openEditModal(repair) {
  337 + this.$refs.editOwnerRepair.open(repair)
  338 + },
  339 +
  340 + openDispatchModal(repair) {
  341 + this.$refs.dispatchRepair.open(repair)
  342 + },
  343 +
  344 + async grabOrder(repair) {
  345 + try {
  346 + const data = {
  347 + communityId: getCommunityId(),
  348 + repairId: repair.repairId
  349 + }
  350 +
  351 + await grabbingRepair(data)
  352 + this.$message.success(this.$t('common.operationSuccess'))
  353 + this.fetchData()
  354 + } catch (error) {
  355 + console.error('Grab order failed:', error)
  356 + }
  357 + },
  358 +
  359 + openEndModal(repair) {
  360 + this.$refs.endRepair.open(repair)
  361 + },
  362 +
  363 + openDetail(repair) {
  364 + this.$router.push(`/views/work/repairDetail?repairId=${repair.repairId}`)
  365 + },
  366 +
  367 + openDeleteModal(repairId) {
  368 + this.$refs.deleteOwnerRepair.open(repairId)
  369 + },
  370 +
  371 + handleSizeChange(size) {
  372 + this.page.size = size
  373 + this.fetchData()
  374 + },
  375 +
  376 + handleCurrentChange(current) {
  377 + this.page.current = current
  378 + this.fetchData()
  379 + },
  380 +
  381 + }
  382 +}
  383 +</script>
  384 +
  385 +<style scoped>
  386 +.status-list {
  387 + display: flex;
  388 + flex-direction: column;
  389 +}
  390 +
  391 +.status-item {
  392 + padding: 12px;
  393 + margin-bottom: 8px;
  394 + border-radius: 4px;
  395 + cursor: pointer;
  396 + text-align: center;
  397 + transition: all 0.3s;
  398 +}
  399 +
  400 +.status-item:hover {
  401 + background-color: #f5f7fa;
  402 +}
  403 +
  404 +.status-active {
  405 + background-color: #409eff;
  406 + color: white;
  407 +}
  408 +
  409 +.box-card {
  410 + margin-bottom: 20px;
  411 +}
  412 +</style>
0 \ No newline at end of file 413 \ No newline at end of file
src/views/work/repairReturnVisitLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + repairReturnVisit: {
  4 + queryTitle: 'Query Conditions',
  5 + listTitle: 'Repair Return Visit',
  6 + repairId: 'Work Order No.',
  7 + location: 'Location',
  8 + repairType: 'Repair Type',
  9 + repairName: 'Repair Person',
  10 + contact: 'Contact',
  11 + appointmentTime: 'Appointment Time',
  12 + operation: 'Operation',
  13 + visit: 'Visit',
  14 + detail: 'Detail',
  15 + repairIdPlaceholder: 'Please enter work order number',
  16 + repairTypePlaceholder: 'Please select repair type',
  17 + repairNamePlaceholder: 'Please enter repair person',
  18 + telPlaceholder: 'Please enter repair phone',
  19 + statePlaceholder: 'Please select visit status',
  20 + waiting: 'Pending Visit',
  21 + finish: 'Visited'
  22 + }
  23 + },
  24 + zh: {
  25 + repairReturnVisit: {
  26 + queryTitle: '查询条件',
  27 + listTitle: '报修回访',
  28 + repairId: '工单编码',
  29 + location: '位置',
  30 + repairType: '报修类型',
  31 + repairName: '报修人',
  32 + contact: '联系方式',
  33 + appointmentTime: '预约时间',
  34 + operation: '操作',
  35 + visit: '回访',
  36 + detail: '详情',
  37 + repairIdPlaceholder: '请输入工单编号',
  38 + repairTypePlaceholder: '请选择报修类型',
  39 + repairNamePlaceholder: '请输入报修人',
  40 + telPlaceholder: '请输入报修电话',
  41 + statePlaceholder: '请选择回访状态',
  42 + waiting: '待回访',
  43 + finish: '已回访'
  44 + }
  45 + }
  46 +}
0 \ No newline at end of file 47 \ No newline at end of file
src/views/work/repairReturnVisitList.vue 0 → 100644
  1 +<template>
  2 + <div class="padding">
  3 + <el-row :gutter="20">
  4 + <el-col :span="24">
  5 + <el-card>
  6 + <div slot="header" class="flex justify-between">
  7 + <span>{{ $t('repairReturnVisit.queryTitle') }}</span>
  8 + </div>
  9 + <el-form :model="searchForm" label-width="0">
  10 + <el-row :gutter="15">
  11 + <el-col :sm="6" :md="4">
  12 + <el-input v-model.trim="searchForm.repairId" :placeholder="$t('repairReturnVisit.repairIdPlaceholder')"
  13 + clearable />
  14 + </el-col>
  15 + <el-col :sm="6" :md="4">
  16 + <el-select v-model="searchForm.repairType" :placeholder="$t('repairReturnVisit.repairTypePlaceholder')"
  17 + clearable style="width:100%">
  18 + <el-option v-for="item in repairSettings" :key="item.repairType" :label="item.repairTypeName"
  19 + :value="item.repairType" />
  20 + </el-select>
  21 + </el-col>
  22 + <el-col :sm="6" :md="4">
  23 + <el-input v-model.trim="searchForm.repairName"
  24 + :placeholder="$t('repairReturnVisit.repairNamePlaceholder')" clearable />
  25 + </el-col>
  26 + <el-col :sm="6" :md="4">
  27 + <el-input v-model.trim="searchForm.tel" :placeholder="$t('repairReturnVisit.telPlaceholder')" clearable />
  28 + </el-col>
  29 + <el-col :sm="6" :md="4">
  30 + <el-select v-model="searchForm.state" :placeholder="$t('repairReturnVisit.statePlaceholder')" clearable
  31 + style="width:100%">
  32 + <el-option v-for="item in states" :key="item.value" :label="item.label" :value="item.value" />
  33 + </el-select>
  34 + </el-col>
  35 + <el-col :sm="6" :md="4">
  36 + <el-button type="primary" icon="el-icon-search" @click="queryRepairPool">
  37 + {{ $t('common.search') }}
  38 + </el-button>
  39 + <el-button icon="el-icon-refresh" @click="resetRepairPool">
  40 + {{ $t('common.reset') }}
  41 + </el-button>
  42 + </el-col>
  43 + </el-row>
  44 + </el-form>
  45 + </el-card>
  46 + </el-col>
  47 + </el-row>
  48 +
  49 + <el-row :gutter="20" class="mt-20">
  50 + <el-col :span="24">
  51 + <el-card>
  52 + <div slot="header" class="flex justify-between">
  53 + <span>{{ $t('repairReturnVisit.listTitle') }}</span>
  54 + </div>
  55 + <el-table v-loading="loading" :data="repairPools" border stripe style="width: 100%">
  56 + <el-table-column prop="repairId" :label="$t('repairReturnVisit.repairId')" align="center" />
  57 + <el-table-column prop="repairObjName" :label="$t('repairReturnVisit.location')" align="center" />
  58 + <el-table-column prop="repairTypeName" :label="$t('repairReturnVisit.repairType')" align="center" />
  59 + <el-table-column prop="repairName" :label="$t('repairReturnVisit.repairName')" align="center" />
  60 + <el-table-column prop="tel" :label="$t('repairReturnVisit.contact')" align="center" />
  61 + <el-table-column prop="appointmentTime" :label="$t('repairReturnVisit.appointmentTime')" align="center" />
  62 + <el-table-column :label="$t('common.operation')" align="center" width="180">
  63 + <template slot-scope="scope">
  64 + <el-button v-if="!scope.row.visitId" type="primary" size="mini" @click="openEditOwnerRepair(scope.row)">
  65 + {{ $t('repairReturnVisit.visit') }}
  66 + </el-button>
  67 + <el-button size="mini" @click="openRepairDetail(scope.row)">
  68 + {{ $t('repairReturnVisit.detail') }}
  69 + </el-button>
  70 + </template>
  71 + </el-table-column>
  72 + </el-table>
  73 + <el-pagination class="mt-20" :current-page.sync="pagination.current" :page-sizes="[10, 20, 30, 50]"
  74 + :page-size="pagination.size" layout="total, sizes, prev, pager, next, jumper" :total="pagination.total"
  75 + @size-change="handleSizeChange" @current-change="handleCurrentChange" />
  76 + </el-card>
  77 + </el-col>
  78 + </el-row>
  79 +
  80 + <visit-owner-repair ref="visitModal" @success="listRepairPools" />
  81 + </div>
  82 +</template>
  83 +
  84 +<script>
  85 +import { getRepairReturnVisitList, listRepairSettings } from '@/api/work/repairReturnVisitApi'
  86 +import VisitOwnerRepair from '@/components/work/visitOwnerRepair'
  87 +
  88 +export default {
  89 + name: 'RepairReturnVisitList',
  90 + components: { VisitOwnerRepair },
  91 + data() {
  92 + return {
  93 + loading: false,
  94 + searchForm: {
  95 + repairId: '',
  96 + repairType: '',
  97 + repairName: '',
  98 + tel: '',
  99 + state: 'waiting'
  100 + },
  101 + repairPools: [],
  102 + repairSettings: [],
  103 + states: [],
  104 + pagination: {
  105 + current: 1,
  106 + size: 10,
  107 + total: 0
  108 + }
  109 + }
  110 + },
  111 + async created() {
  112 + await this.loadDictData()
  113 + this.listRepairPools()
  114 + this.listRepairSettings()
  115 + },
  116 + methods: {
  117 + async loadDictData() {
  118 + try {
  119 + this.states = [{
  120 + value: 'waiting',
  121 + label: '待回访'
  122 + },{
  123 + value: 'finish',
  124 + label: '已回访'
  125 + }]
  126 + } catch (error) {
  127 + console.error('获取字典数据失败:', error)
  128 + }
  129 + },
  130 + async listRepairPools() {
  131 + try {
  132 + this.loading = true
  133 + const params = {
  134 + ...this.searchForm,
  135 + page: this.pagination.current,
  136 + row: this.pagination.size,
  137 + communityId: this.getCommunityId()
  138 + }
  139 +
  140 + // 清理空值
  141 + Object.keys(params).forEach(key => {
  142 + if (params[key] === '') delete params[key]
  143 + })
  144 +
  145 + const { data, total } = await getRepairReturnVisitList(params)
  146 + this.repairPools = data
  147 + this.pagination.total = total
  148 + } catch (error) {
  149 + console.error('查询报修回访列表失败:', error)
  150 + } finally {
  151 + this.loading = false
  152 + }
  153 + },
  154 + async listRepairSettings() {
  155 + try {
  156 + const { data } = await listRepairSettings({
  157 + page: 1,
  158 + row: 50,
  159 + communityId: this.getCommunityId()
  160 + })
  161 + this.repairSettings = data
  162 + } catch (error) {
  163 + console.error('查询报修类型设置失败:', error)
  164 + }
  165 + },
  166 + queryRepairPool() {
  167 + this.pagination.current = 1
  168 + this.listRepairPools()
  169 + },
  170 + resetRepairPool() {
  171 + this.searchForm = {
  172 + repairId: '',
  173 + repairType: '',
  174 + repairName: '',
  175 + tel: '',
  176 + state: ''
  177 + }
  178 + this.queryRepairPool()
  179 + },
  180 + openRepairDetail(repairPool) {
  181 + this.$router.push({
  182 + path: '/pages/property/ownerRepairDetail',
  183 + query: { repairId: repairPool.repairId }
  184 + })
  185 + },
  186 + openEditOwnerRepair(repairPool) {
  187 + this.$refs.visitModal.open(repairPool)
  188 + },
  189 + handleSizeChange(size) {
  190 + this.pagination.size = size
  191 + this.listRepairPools()
  192 + },
  193 + handleCurrentChange(current) {
  194 + this.pagination.current = current
  195 + this.listRepairPools()
  196 + }
  197 + }
  198 +}
  199 +</script>
  200 +
  201 +<style scoped>
  202 +.mt-20 {
  203 + margin-top: 20px;
  204 +}
  205 +</style>
0 \ No newline at end of file 206 \ No newline at end of file
src/views/work/repairSettingList.vue
@@ -102,7 +102,7 @@ @@ -102,7 +102,7 @@
102 </el-table> 102 </el-table>
103 103
104 <!-- 分页和说明 --> 104 <!-- 分页和说明 -->
105 - <el-row :gutter="20" class="margin-top-xs"> 105 + <el-row :gutter="20" class="margin-top-xs text-left">
106 <el-col :span="18"> 106 <el-col :span="18">
107 <div class="explanation-section"> 107 <div class="explanation-section">
108 <p><strong>{{ $t('repairSetting.dispatchExplanation') }}</strong></p> 108 <p><strong>{{ $t('repairSetting.dispatchExplanation') }}</strong></p>
@@ -276,14 +276,9 @@ export default { @@ -276,14 +276,9 @@ export default {
276 } 276 }
277 277
278 .explanation-section { 278 .explanation-section {
279 - background-color: #f8f9fa;  
280 - padding: 15px;  
281 - border-radius: 4px;  
282 font-size: 14px; 279 font-size: 14px;
283 - line-height: 1.6;  
284 -  
285 p { 280 p {
286 - margin-bottom: 8px; 281 + margin-bottom: 2px;
287 } 282 }
288 } 283 }
289 } 284 }
src/views/work/repairTypeUserList.vue
@@ -43,7 +43,7 @@ @@ -43,7 +43,7 @@
43 </el-col> 43 </el-col>
44 </el-row> 44 </el-row>
45 45
46 - <SelectStaff ref="selectStaff" /> 46 + <SelectStaff ref="selectStaff" @selectStaff="handleSelectStaff"/>
47 <DeleteRepairTypeUser ref="deleteRepairTypeUser" @success="handleDeleteSuccess" /> 47 <DeleteRepairTypeUser ref="deleteRepairTypeUser" @success="handleDeleteSuccess" />
48 <EditRepairTypeUser ref="editRepairTypeUser" @success="handleEditSuccess" /> 48 <EditRepairTypeUser ref="editRepairTypeUser" @success="handleEditSuccess" />
49 </div> 49 </div>
@@ -52,7 +52,7 @@ @@ -52,7 +52,7 @@
52 <script> 52 <script>
53 import { listRepairTypeUsers, saveRepairTypeUser } from '@/api/work/repairTypeUserApi' 53 import { listRepairTypeUsers, saveRepairTypeUser } from '@/api/work/repairTypeUserApi'
54 import { getCommunityId } from '@/api/community/communityApi' 54 import { getCommunityId } from '@/api/community/communityApi'
55 -import SelectStaff from '@/components/work/SelectStaff' 55 +import SelectStaff from '@/components/staff/SelectStaff'
56 import DeleteRepairTypeUser from '@/components/work/DeleteRepairTypeUser' 56 import DeleteRepairTypeUser from '@/components/work/DeleteRepairTypeUser'
57 import EditRepairTypeUser from '@/components/work/EditRepairTypeUser' 57 import EditRepairTypeUser from '@/components/work/EditRepairTypeUser'
58 58
@@ -116,11 +116,7 @@ export default { @@ -116,11 +116,7 @@ export default {
116 this._listRepairTypeUsers(val, this.pageSize) 116 this._listRepairTypeUsers(val, this.pageSize)
117 }, 117 },
118 _openAddRepairTypeUserModal() { 118 _openAddRepairTypeUserModal() {
119 - this.$refs.selectStaff.open({  
120 - call: (staff) => {  
121 - this.saveRepairTypeUserInfo(staff)  
122 - }  
123 - }) 119 + this.$refs.selectStaff.open()
124 }, 120 },
125 _openEditrepairTypeUserModel(row) { 121 _openEditrepairTypeUserModel(row) {
126 this.$refs.editRepairTypeUser.open(row) 122 this.$refs.editRepairTypeUser.open(row)
@@ -131,6 +127,9 @@ export default { @@ -131,6 +127,9 @@ export default {
131 _goBack() { 127 _goBack() {
132 this.$router.go(-1) 128 this.$router.go(-1)
133 }, 129 },
  130 + handleSelectStaff(staff) {
  131 + this.saveRepairTypeUserInfo(staff)
  132 + },
134 async saveRepairTypeUserInfo(staff) { 133 async saveRepairTypeUserInfo(staff) {
135 try { 134 try {
136 const communityId = await getCommunityId() 135 const communityId = await getCommunityId()