Commit 9d4e862af9f1d82d1f0a5a7605cd7502a0a7c546

Authored by wuxw
1 parent 6ed9faf1

开发完成预约功能

Showing 50 changed files with 6359 additions and 168 deletions
src/api/scm/addReserveDiningApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +import { getCommunityId } from '@/api/community/communityApi'
  3 +
  4 +// 保存就餐商品信息
  5 +export function saveReserveGoods(data) {
  6 + return new Promise((resolve, reject) => {
  7 + request({
  8 + url: '/reserve.saveReserveGoods',
  9 + method: 'post',
  10 + data: {
  11 + ...data,
  12 + communityId: getCommunityId()
  13 + }
  14 + }).then(response => {
  15 + const res = response.data
  16 + resolve(res)
  17 + }).catch(error => {
  18 + reject(error)
  19 + })
  20 + })
  21 +}
  22 +
  23 +// 获取就餐参数列表
  24 +export function listReserveParams(params) {
  25 + return new Promise((resolve, reject) => {
  26 + request({
  27 + url: '/reserve.listReserveParams',
  28 + method: 'get',
  29 + params: {
  30 + ...params,
  31 + communityId: getCommunityId()
  32 + }
  33 + }).then(response => {
  34 + const res = response.data
  35 + resolve(res)
  36 + }).catch(error => {
  37 + reject(error)
  38 + })
  39 + })
  40 +}
  41 +
  42 +// 上传文件
  43 +export function uploadFile(data) {
  44 + return new Promise((resolve, reject) => {
  45 + request({
  46 + url: '/uploadFile',
  47 + method: 'post',
  48 + data,
  49 + headers: {
  50 + 'Content-Type': 'multipart/form-data'
  51 + }
  52 + }).then(response => {
  53 + const res = response.data
  54 + resolve(res)
  55 + }).catch(error => {
  56 + reject(error)
  57 + })
  58 + })
  59 +}
  60 +
  61 +// 获取文件下载URL
  62 +export function getFileUrl(fileId) {
  63 + return new Promise((resolve, reject) => {
  64 + request({
  65 + url: '/callComponent/download/getFile/file',
  66 + method: 'get',
  67 + params: {
  68 + fileId,
  69 + communityId: getCommunityId()
  70 + }
  71 + }).then(response => {
  72 + const res = response.data
  73 + resolve(res)
  74 + }).catch(error => {
  75 + reject(error)
  76 + })
  77 + })
  78 +}
0 79 \ No newline at end of file
... ...
src/api/scm/addReserveServiceApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +import { getCommunityId } from '@/api/community/communityApi'
  3 +
  4 +/**
  5 + * 保存预约服务信息
  6 + * @param {Object} data 服务信息
  7 + * @returns {Promise}
  8 + */
  9 +export function saveReserveGoods(data) {
  10 + return new Promise((resolve, reject) => {
  11 + request({
  12 + url: '/reserve.saveReserveGoods',
  13 + method: 'post',
  14 + data: {
  15 + ...data,
  16 + communityId: getCommunityId()
  17 + }
  18 + }).then(response => {
  19 + const res = response.data
  20 + resolve(res)
  21 + }).catch(error => {
  22 + reject(error)
  23 + })
  24 + })
  25 +}
  26 +
  27 +/**
  28 + * 获取预约参数列表
  29 + * @param {Object} params 查询参数
  30 + * @returns {Promise}
  31 + */
  32 +export function listReserveParams(params = {}) {
  33 + return new Promise((resolve, reject) => {
  34 + request({
  35 + url: '/reserve.listReserveParams',
  36 + method: 'get',
  37 + params: {
  38 + page: 1,
  39 + row: 100,
  40 + communityId: getCommunityId(),
  41 + ...params
  42 + }
  43 + }).then(response => {
  44 + const res = response.data
  45 + resolve(res)
  46 + }).catch(error => {
  47 + reject(error)
  48 + })
  49 + })
  50 +}
  51 +
  52 +/**
  53 + * 上传文件
  54 + * @param {FormData} formData 文件表单数据
  55 + * @returns {Promise}
  56 + */
  57 +export function uploadFile(formData) {
  58 + return new Promise((resolve, reject) => {
  59 + request({
  60 + url: '/uploadFile',
  61 + method: 'post',
  62 + data: formData,
  63 + headers: {
  64 + 'Content-Type': 'multipart/form-data'
  65 + }
  66 + }).then(response => {
  67 + const res = response.data
  68 + resolve(res)
  69 + }).catch(error => {
  70 + reject(error)
  71 + })
  72 + })
  73 +}
  74 +
  75 +/**
  76 + * 获取文件下载URL
  77 + * @param {String} fileId 文件ID
  78 + * @returns {String} 文件下载URL
  79 + */
  80 +export function getFileUrl(fileId) {
  81 + return `/callComponent/download/getFile/file?fileId=${fileId}&communityId=${getCommunityId()}&time=${new Date().getTime()}`
  82 +}
0 83 \ No newline at end of file
... ...
src/api/scm/doDiningApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +import { getCommunityId } from '@/api/community/communityApi'
  3 +
  4 +// 获取预约商品列表
  5 +export function listReserveGoods(params) {
  6 + return new Promise((resolve, reject) => {
  7 + request({
  8 + url: '/reserve.listReserveGoods',
  9 + method: 'get',
  10 + params: {
  11 + ...params,
  12 + communityId: getCommunityId()
  13 + }
  14 + }).then(response => {
  15 + const res = response.data
  16 + resolve(res)
  17 + }).catch(error => {
  18 + reject(error)
  19 + })
  20 + })
  21 +}
  22 +
  23 +// 查询业主就餐记录
  24 +export function queryOwnerDining(params) {
  25 + return new Promise((resolve, reject) => {
  26 + request({
  27 + url: '/owner.queryOwnerDining',
  28 + method: 'get',
  29 + params: {
  30 + ...params,
  31 + communityId: getCommunityId()
  32 + }
  33 + }).then(response => {
  34 + const res = response.data
  35 + resolve(res)
  36 + }).catch(error => {
  37 + reject(error)
  38 + })
  39 + })
  40 +}
  41 +
  42 +// 导出数据
  43 +export function exportData(params) {
  44 + return new Promise((resolve, reject) => {
  45 + request({
  46 + url: '/export.exportData',
  47 + method: 'get',
  48 + params: {
  49 + ...params,
  50 + communityId: getCommunityId()
  51 + }
  52 + }).then(response => {
  53 + const res = response.data
  54 + resolve(res)
  55 + }).catch(error => {
  56 + reject(error)
  57 + })
  58 + })
  59 +}
  60 +
  61 +// 执行就餐
  62 +export function doDining(data) {
  63 + return new Promise((resolve, reject) => {
  64 + request({
  65 + url: '/reserveOrder.doDining',
  66 + method: 'post',
  67 + data: {
  68 + ...data,
  69 + communityId: getCommunityId()
  70 + }
  71 + }).then(response => {
  72 + const res = response.data
  73 + resolve(res)
  74 + }).catch(error => {
  75 + reject(error)
  76 + })
  77 + })
  78 +}
  79 +
  80 +// 保存预约商品订单
  81 +export function saveReserveGoodsOrder(data) {
  82 + return new Promise((resolve, reject) => {
  83 + request({
  84 + url: '/reserveOrder.saveReserveGoodsOrder',
  85 + method: 'post',
  86 + data: {
  87 + ...data,
  88 + communityId: getCommunityId()
  89 + }
  90 + }).then(response => {
  91 + const res = response.data
  92 + resolve(res)
  93 + }).catch(error => {
  94 + reject(error)
  95 + })
  96 + })
  97 +}
  98 +
  99 +// 删除预约商品
  100 +export function deleteReserveGoods(data) {
  101 + return new Promise((resolve, reject) => {
  102 + request({
  103 + url: '/reserve.deleteReserveGoods',
  104 + method: 'post',
  105 + data: {
  106 + ...data,
  107 + communityId: getCommunityId()
  108 + }
  109 + }).then(response => {
  110 + const res = response.data
  111 + resolve(res)
  112 + }).catch(error => {
  113 + reject(error)
  114 + })
  115 + })
  116 +}
  117 +
  118 +// 获取预约参数
  119 +export function listReserveParams(params) {
  120 + return new Promise((resolve, reject) => {
  121 + request({
  122 + url: '/reserve.listReserveParams',
  123 + method: 'get',
  124 + params: {
  125 + ...params,
  126 + communityId: getCommunityId()
  127 + }
  128 + }).then(response => {
  129 + const res = response.data
  130 + resolve(res)
  131 + }).catch(error => {
  132 + reject(error)
  133 + })
  134 + })
  135 +}
0 136 \ No newline at end of file
... ...
src/api/scm/editReserveDiningApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +import { getCommunityId } from '@/api/community/communityApi'
  3 +
  4 +// 更新预订餐饮商品
  5 +export function updateReserveGoods(data) {
  6 + return new Promise((resolve, reject) => {
  7 + data.communityId = getCommunityId()
  8 + request({
  9 + url: '/reserve.updateReserveGoods',
  10 + method: 'post',
  11 + data
  12 + }).then(response => {
  13 + const res = response.data
  14 + resolve(res)
  15 + }).catch(error => {
  16 + reject(error)
  17 + })
  18 + })
  19 +}
  20 +
  21 +// 获取预订参数列表
  22 +export function listReserveParams(params) {
  23 + return new Promise((resolve, reject) => {
  24 + const defaultParams = {
  25 + page: 1,
  26 + row: 100,
  27 + communityId: getCommunityId()
  28 + }
  29 + request({
  30 + url: '/reserve.listReserveParams',
  31 + method: 'get',
  32 + params: Object.assign(defaultParams, params)
  33 + }).then(response => {
  34 + const res = response.data
  35 + resolve(res)
  36 + }).catch(error => {
  37 + reject(error)
  38 + })
  39 + })
  40 +}
  41 +
  42 +// 获取预订餐饮商品列表
  43 +export function listReserveGoods(params) {
  44 + return new Promise((resolve, reject) => {
  45 + const defaultParams = {
  46 + page: 1,
  47 + row: 1,
  48 + communityId: getCommunityId()
  49 + }
  50 + request({
  51 + url: '/reserve.listReserveGoods',
  52 + method: 'get',
  53 + params: Object.assign(defaultParams, params)
  54 + }).then(response => {
  55 + const res = response.data
  56 + resolve(res)
  57 + }).catch(error => {
  58 + reject(error)
  59 + })
  60 + })
  61 +}
  62 +
  63 +// 上传图片
  64 +export function uploadImage(data) {
  65 + return new Promise((resolve, reject) => {
  66 + const formData = new FormData()
  67 + formData.append('uploadFile', data.file)
  68 + formData.append('communityId', getCommunityId())
  69 +
  70 + request({
  71 + url: 'uploadFile',
  72 + method: 'post',
  73 + data: formData,
  74 + headers: {
  75 + 'Content-Type': 'multipart/form-data'
  76 + }
  77 + }).then(response => {
  78 + const res = response.data
  79 + resolve(res)
  80 + }).catch(error => {
  81 + reject(error)
  82 + })
  83 + })
  84 +}
0 85 \ No newline at end of file
... ...
src/api/scm/editReserveServiceApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +/**
  4 + * 更新预约服务信息
  5 + * @param {Object} data 服务信息
  6 + * @returns {Promise}
  7 + */
  8 +export function updateReserveGoods(data) {
  9 + return new Promise((resolve, reject) => {
  10 + request({
  11 + url: '/reserve.updateReserveGoods',
  12 + method: 'post',
  13 + data
  14 + }).then(response => {
  15 + const res = response.data
  16 + resolve(res)
  17 + }).catch(error => {
  18 + reject(error)
  19 + })
  20 + })
  21 +}
  22 +
  23 +/**
  24 + * 获取预约参数列表
  25 + * @param {Object} params 查询参数
  26 + * @returns {Promise}
  27 + */
  28 +export function listReserveParams(params) {
  29 + return new Promise((resolve, reject) => {
  30 + request({
  31 + url: '/reserve.listReserveParams',
  32 + method: 'get',
  33 + params
  34 + }).then(response => {
  35 + const res = response.data
  36 + resolve(res)
  37 + }).catch(error => {
  38 + reject(error)
  39 + })
  40 + })
  41 +}
  42 +
  43 +/**
  44 + * 获取预约服务列表
  45 + * @param {Object} params 查询参数
  46 + * @returns {Promise}
  47 + */
  48 +export function listReserveGoods(params) {
  49 + return new Promise((resolve, reject) => {
  50 + request({
  51 + url: '/reserve.listReserveGoods',
  52 + method: 'get',
  53 + params
  54 + }).then(response => {
  55 + const res = response.data
  56 + resolve(res)
  57 + }).catch(error => {
  58 + reject(error)
  59 + })
  60 + })
  61 +}
  62 +
  63 +/**
  64 + * 上传文件
  65 + * @param {FormData} formData 文件表单数据
  66 + * @returns {Promise}
  67 + */
  68 +export function uploadFile(formData) {
  69 + return new Promise((resolve, reject) => {
  70 + request({
  71 + url: '/uploadFile',
  72 + method: 'post',
  73 + data: formData,
  74 + headers: {
  75 + 'Content-Type': 'multipart/form-data'
  76 + }
  77 + }).then(response => {
  78 + const res = response.data
  79 + resolve(res)
  80 + }).catch(error => {
  81 + reject(error)
  82 + })
  83 + })
  84 +}
  85 +
  86 +/**
  87 + * 获取文件下载URL
  88 + * @param {String} fileId 文件ID
  89 + * @returns {Promise}
  90 + */
  91 +export function getFileUrl(fileId) {
  92 + return new Promise((resolve, reject) => {
  93 + request({
  94 + url: '/callComponent/download/getFile/file',
  95 + method: 'get',
  96 + params: {
  97 + fileId,
  98 + communityId: -1
  99 + }
  100 + }).then(response => {
  101 + const res = response.data
  102 + resolve(res)
  103 + }).catch(error => {
  104 + reject(error)
  105 + })
  106 + })
  107 +}
0 108 \ No newline at end of file
... ...
src/api/scm/ownerDiningApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 查询业主就餐记录
  4 +export function queryOwnerReserveGoods(params) {
  5 + return new Promise((resolve, reject) => {
  6 + request({
  7 + url: '/owner.queryOwnerReserveGoods',
  8 + method: 'get',
  9 + params
  10 + }).then(response => {
  11 + const res = response.data
  12 + resolve(res)
  13 + }).catch(error => {
  14 + reject(error)
  15 + })
  16 + })
  17 +}
  18 +
  19 +// 导出数据
  20 +export function exportData(params) {
  21 + return new Promise((resolve, reject) => {
  22 + request({
  23 + url: '/export.exportData',
  24 + method: 'get',
  25 + params
  26 + }).then(response => {
  27 + const res = response.data
  28 + resolve(res)
  29 + }).catch(error => {
  30 + reject(error)
  31 + })
  32 + })
  33 +}
0 34 \ No newline at end of file
... ...
src/api/scm/reserveCatalogManageApi.js
... ... @@ -4,12 +4,13 @@ import { getCommunityId } from '@/api/community/communityApi'
4 4 // 获取预约目录列表
5 5 export function listReserveCatalog(params) {
6 6 return new Promise((resolve, reject) => {
  7 + const communityId = getCommunityId()
7 8 request({
8 9 url: '/reserve.listReserveCatalog',
9 10 method: 'get',
10 11 params: {
11 12 ...params,
12   - communityId: getCommunityId()
  13 + communityId
13 14 }
14 15 }).then(response => {
15 16 const res = response.data
... ... @@ -23,12 +24,13 @@ export function listReserveCatalog(params) {
23 24 // 添加预约目录
24 25 export function saveReserveCatalog(data) {
25 26 return new Promise((resolve, reject) => {
  27 + const communityId = getCommunityId()
26 28 request({
27 29 url: '/reserve.saveReserveCatalog',
28 30 method: 'post',
29 31 data: {
30 32 ...data,
31   - communityId: getCommunityId()
  33 + communityId
32 34 }
33 35 }).then(response => {
34 36 const res = response.data
... ... @@ -42,12 +44,13 @@ export function saveReserveCatalog(data) {
42 44 // 更新预约目录
43 45 export function updateReserveCatalog(data) {
44 46 return new Promise((resolve, reject) => {
  47 + const communityId = getCommunityId()
45 48 request({
46 49 url: '/reserve.updateReserveCatalog',
47 50 method: 'post',
48 51 data: {
49 52 ...data,
50   - communityId: getCommunityId()
  53 + communityId
51 54 }
52 55 }).then(response => {
53 56 const res = response.data
... ... @@ -61,12 +64,13 @@ export function updateReserveCatalog(data) {
61 64 // 删除预约目录
62 65 export function deleteReserveCatalog(data) {
63 66 return new Promise((resolve, reject) => {
  67 + const communityId = getCommunityId()
64 68 request({
65 69 url: '/reserve.deleteReserveCatalog',
66 70 method: 'post',
67 71 data: {
68 72 ...data,
69   - communityId: getCommunityId()
  73 + communityId
70 74 }
71 75 }).then(response => {
72 76 const res = response.data
... ...
src/api/scm/reserveConfirmApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 获取核销订单列表
  4 +export function listReserveGoodsConfirmOrder(params) {
  5 + return new Promise((resolve, reject) => {
  6 + request({
  7 + url: '/reserveOrder.listReserveGoodsConfirmOrder',
  8 + method: 'get',
  9 + params
  10 + }).then(response => {
  11 + const res = response.data
  12 + resolve(res)
  13 + }).catch(error => {
  14 + reject(error)
  15 + })
  16 + })
  17 +}
  18 +
  19 +// 核销预约订单
  20 +export function saveReserveGoodsConfirmOrder(data) {
  21 + return new Promise((resolve, reject) => {
  22 + request({
  23 + url: '/reserveOrder.saveReserveGoodsConfirmOrder',
  24 + method: 'post',
  25 + data
  26 + }).then(response => {
  27 + const res = response.data
  28 + resolve(res)
  29 + }).catch(error => {
  30 + reject(error)
  31 + })
  32 + })
  33 +}
0 34 \ No newline at end of file
... ...
src/api/scm/reserveDiningManageApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +import { getCommunityId } from '@/api/community/communityApi'
  3 +
  4 +// 获取预约就餐列表
  5 +export function listReserveGoods(params) {
  6 + return new Promise((resolve, reject) => {
  7 + request({
  8 + url: '/reserve.listReserveGoods',
  9 + method: 'get',
  10 + params: {
  11 + ...params,
  12 + communityId: getCommunityId()
  13 + }
  14 + }).then(response => {
  15 + const res = response.data
  16 + resolve(res)
  17 + }).catch(error => {
  18 + reject(error)
  19 + })
  20 + })
  21 +}
  22 +
  23 +// 获取预约目录列表
  24 +export function listReserveCatalog(params) {
  25 + return new Promise((resolve, reject) => {
  26 + request({
  27 + url: '/reserve.listReserveCatalog',
  28 + method: 'get',
  29 + params: {
  30 + ...params,
  31 + communityId: getCommunityId()
  32 + }
  33 + }).then(response => {
  34 + const res = response.data
  35 + resolve(res)
  36 + }).catch(error => {
  37 + reject(error)
  38 + })
  39 + })
  40 +}
  41 +
  42 +// 获取预约参数
  43 +export function listReserveParams(params) {
  44 + return new Promise((resolve, reject) => {
  45 + request({
  46 + url: '/reserve.listReserveParams',
  47 + method: 'get',
  48 + params: {
  49 + ...params,
  50 + communityId: getCommunityId()
  51 + }
  52 + }).then(response => {
  53 + const res = response.data
  54 + resolve(res)
  55 + }).catch(error => {
  56 + reject(error)
  57 + })
  58 + })
  59 +}
  60 +
  61 +// 保存预约订单
  62 +export function saveReserveGoodsOrder(data) {
  63 + return new Promise((resolve, reject) => {
  64 + request({
  65 + url: '/reserveOrder.saveReserveGoodsOrder',
  66 + method: 'post',
  67 + data: {
  68 + ...data,
  69 + communityId: getCommunityId()
  70 + }
  71 + }).then(response => {
  72 + const res = response.data
  73 + resolve(res)
  74 + }).catch(error => {
  75 + reject(error)
  76 + })
  77 + })
  78 +}
  79 +
  80 +// 删除预约商品
  81 +export function deleteReserveGoods(data) {
  82 + return new Promise((resolve, reject) => {
  83 + request({
  84 + url: '/reserve.deleteReserveGoods',
  85 + method: 'post',
  86 + data: {
  87 + ...data,
  88 + communityId: getCommunityId()
  89 + }
  90 + }).then(response => {
  91 + const res = response.data
  92 + resolve(res)
  93 + }).catch(error => {
  94 + reject(error)
  95 + })
  96 + })
  97 +}
0 98 \ No newline at end of file
... ...
src/api/scm/reserveOrderApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +import { getCommunityId } from '@/api/community/communityApi'
  3 +
  4 +// 获取预约订单列表
  5 +export function listReserveGoodsOrder(params) {
  6 + return new Promise((resolve, reject) => {
  7 + const defaultParams = {
  8 + communityId: getCommunityId(),
  9 + ...params
  10 + }
  11 + request({
  12 + url: '/reserveOrder.listReserveGoodsOrder',
  13 + method: 'get',
  14 + params: defaultParams
  15 + }).then(response => {
  16 + const res = response.data
  17 + resolve(res)
  18 + }).catch(error => {
  19 + reject(error)
  20 + })
  21 + })
  22 +}
  23 +
  24 +// 取消预约订单
  25 +export function cancelReserveOrder(data) {
  26 + return new Promise((resolve, reject) => {
  27 + request({
  28 + url: '/reserveOrder.cancelReserveOrder',
  29 + method: 'post',
  30 + data
  31 + }).then(response => {
  32 + const res = response.data
  33 + resolve(res)
  34 + }).catch(error => {
  35 + reject(error)
  36 + })
  37 + })
  38 +}
0 39 \ No newline at end of file
... ...
src/api/scm/reserveParamsManageApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 获取预约参数列表
  4 +export function listReserveParams(params) {
  5 + return new Promise((resolve, reject) => {
  6 + request({
  7 + url: '/reserve.listReserveParams',
  8 + method: 'get',
  9 + params
  10 + }).then(response => {
  11 + const res = response.data
  12 + resolve(res)
  13 + }).catch(error => {
  14 + reject(error)
  15 + })
  16 + })
  17 +}
  18 +
  19 +// 添加预约参数
  20 +export function saveReserveParams(data) {
  21 + return new Promise((resolve, reject) => {
  22 + request({
  23 + url: '/reserve.saveReserveParams',
  24 + method: 'post',
  25 + data
  26 + }).then(response => {
  27 + const res = response.data
  28 + resolve(res)
  29 + }).catch(error => {
  30 + reject(error)
  31 + })
  32 + })
  33 +}
  34 +
  35 +// 更新预约参数
  36 +export function updateReserveParams(data) {
  37 + return new Promise((resolve, reject) => {
  38 + request({
  39 + url: '/reserve.updateReserveParams',
  40 + method: 'post',
  41 + data
  42 + }).then(response => {
  43 + const res = response.data
  44 + resolve(res)
  45 + }).catch(error => {
  46 + reject(error)
  47 + })
  48 + })
  49 +}
  50 +
  51 +// 删除预约参数
  52 +export function deleteReserveParams(data) {
  53 + return new Promise((resolve, reject) => {
  54 + request({
  55 + url: '/reserve.deleteReserveParams',
  56 + method: 'post',
  57 + data
  58 + }).then(response => {
  59 + const res = response.data
  60 + resolve(res)
  61 + }).catch(error => {
  62 + reject(error)
  63 + })
  64 + })
  65 +}
  66 +
  67 +// 更新预约开放时间
  68 +export function updateReserveParamsOpenTime(data) {
  69 + return new Promise((resolve, reject) => {
  70 + request({
  71 + url: '/reserve.updateReserveParamsOpenTime',
  72 + method: 'post',
  73 + data
  74 + }).then(response => {
  75 + const res = response.data
  76 + resolve(res)
  77 + }).catch(error => {
  78 + reject(error)
  79 + })
  80 + })
  81 +}
0 82 \ No newline at end of file
... ...
src/api/scm/reserveServiceManageApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +import { getCommunityId } from '@/api/community/communityApi'
  3 +
  4 +// 获取预约服务列表
  5 +export function listReserveGoods(params) {
  6 + return new Promise((resolve, reject) => {
  7 + params.communityId = getCommunityId()
  8 + request({
  9 + url: '/reserve.listReserveGoods',
  10 + method: 'get',
  11 + params
  12 + }).then(response => {
  13 + const res = response.data
  14 + resolve(res)
  15 + }).catch(error => {
  16 + reject(error)
  17 + })
  18 + })
  19 +}
  20 +
  21 +// 获取预约目录列表
  22 +export function listReserveCatalog(params) {
  23 + return new Promise((resolve, reject) => {
  24 + params.communityId = getCommunityId()
  25 + request({
  26 + url: '/reserve.listReserveCatalog',
  27 + method: 'get',
  28 + params
  29 + }).then(response => {
  30 + const res = response.data
  31 + resolve(res)
  32 + }).catch(error => {
  33 + reject(error)
  34 + })
  35 + })
  36 +}
  37 +
  38 +// 获取预约参数
  39 +export function listReserveParams(params) {
  40 + return new Promise((resolve, reject) => {
  41 + params.communityId = getCommunityId()
  42 + request({
  43 + url: '/reserve.listReserveParams',
  44 + method: 'get',
  45 + params
  46 + }).then(response => {
  47 + const res = response.data
  48 + resolve(res)
  49 + }).catch(error => {
  50 + reject(error)
  51 + })
  52 + })
  53 +}
  54 +
  55 +// 保存预约订单
  56 +export function saveReserveGoodsOrder(data) {
  57 + return new Promise((resolve, reject) => {
  58 + data.communityId = getCommunityId()
  59 + request({
  60 + url: '/reserveOrder.saveReserveGoodsOrder',
  61 + method: 'post',
  62 + data
  63 + }).then(response => {
  64 + const res = response.data
  65 + resolve(res)
  66 + }).catch(error => {
  67 + reject(error)
  68 + })
  69 + })
  70 +}
  71 +
  72 +// 删除预约服务
  73 +export function deleteReserveGoods(data) {
  74 + return new Promise((resolve, reject) => {
  75 + data.communityId = getCommunityId()
  76 + request({
  77 + url: '/reserve.deleteReserveGoods',
  78 + method: 'post',
  79 + data
  80 + }).then(response => {
  81 + const res = response.data
  82 + resolve(res)
  83 + }).catch(error => {
  84 + reject(error)
  85 + })
  86 + })
  87 +}
0 88 \ No newline at end of file
... ...
src/components/scm/addReserveCatalog.vue
... ... @@ -12,57 +12,57 @@
12 12 label-width="120px"
13 13 >
14 14 <el-form-item
15   - :label="$t('reserveCatalogManage.add.name')"
  15 + :label="$t('reserveCatalogManage.form.name')"
16 16 prop="name"
17 17 >
18 18 <el-input
19 19 v-model="formData.name"
20   - :placeholder="$t('reserveCatalogManage.add.namePlaceholder')"
  20 + :placeholder="$t('reserveCatalogManage.form.namePlaceholder')"
21 21 />
22 22 </el-form-item>
23 23 <el-form-item
24   - :label="$t('reserveCatalogManage.add.sort')"
  24 + :label="$t('reserveCatalogManage.form.sort')"
25 25 prop="sort"
26 26 >
27 27 <el-input
28 28 v-model="formData.sort"
29   - :placeholder="$t('reserveCatalogManage.add.sortPlaceholder')"
  29 + :placeholder="$t('reserveCatalogManage.form.sortPlaceholder')"
30 30 />
31 31 </el-form-item>
32 32 <el-form-item
33   - :label="$t('reserveCatalogManage.add.type')"
  33 + :label="$t('reserveCatalogManage.form.type')"
34 34 prop="type"
35 35 >
36 36 <el-select
37 37 v-model="formData.type"
38   - :placeholder="$t('reserveCatalogManage.add.typePlaceholder')"
  38 + :placeholder="$t('reserveCatalogManage.form.typePlaceholder')"
39 39 style="width:100%"
40 40 >
41 41 <el-option
42   - :label="$t('reserveCatalogManage.add.typeOption1')"
  42 + :label="$t('reserveCatalogManage.form.typeOptions.dining')"
43 43 value="1001"
44 44 />
45 45 <el-option
46   - :label="$t('reserveCatalogManage.add.typeOption2')"
  46 + :label="$t('reserveCatalogManage.form.typeOptions.service')"
47 47 value="2002"
48 48 />
49 49 </el-select>
50 50 </el-form-item>
51 51 <el-form-item
52   - :label="$t('reserveCatalogManage.add.state')"
  52 + :label="$t('reserveCatalogManage.form.state')"
53 53 prop="state"
54 54 >
55 55 <el-select
56 56 v-model="formData.state"
57   - :placeholder="$t('reserveCatalogManage.add.statePlaceholder')"
  57 + :placeholder="$t('reserveCatalogManage.form.statePlaceholder')"
58 58 style="width:100%"
59 59 >
60 60 <el-option
61   - :label="$t('reserveCatalogManage.add.stateOption1')"
  61 + :label="$t('reserveCatalogManage.form.stateOptions.show')"
62 62 value="1001"
63 63 />
64 64 <el-option
65   - :label="$t('reserveCatalogManage.add.stateOption2')"
  65 + :label="$t('reserveCatalogManage.form.stateOptions.hide')"
66 66 value="2002"
67 67 />
68 68 </el-select>
... ... @@ -115,10 +115,10 @@ export default {
115 115 },
116 116 methods: {
117 117 open() {
118   - this.formData.communityId = getCommunityId()
119 118 this.visible = true
  119 + this.formData.communityId = getCommunityId()
120 120 this.$nextTick(() => {
121   - this.$refs.form.resetFields()
  121 + this.$refs.form && this.$refs.form.resetFields()
122 122 })
123 123 },
124 124 handleClose() {
... ... @@ -133,7 +133,7 @@ export default {
133 133 this.visible = false
134 134 this.$emit('success')
135 135 } catch (error) {
136   - this.$message.error(this.$t('reserveCatalogManage.add.error'))
  136 + this.$message.error(error.message || this.$t('reserveCatalogManage.add.error'))
137 137 }
138 138 }
139 139 })
... ...
src/components/scm/addReserveDiningPerson.vue 0 → 100644
  1 +<template>
  2 + <el-dialog :title="$t('addReserveDiningPerson.reserveDining')" :visible.sync="visible" width="70%"
  3 + @close="closeDialog">
  4 + <el-form :model="form" label-width="120px" ref="form">
  5 + <el-row :gutter="20">
  6 + <el-col :span="12">
  7 + <el-form-item :label="$t('addReserveDiningPerson.personName')" prop="personName" required>
  8 + <el-input v-model="form.personName"
  9 + :placeholder="$t('addReserveDiningPerson.personNamePlaceholder')"></el-input>
  10 + </el-form-item>
  11 + </el-col>
  12 + <el-col :span="12">
  13 + <el-form-item :label="$t('addReserveDiningPerson.personTel')" prop="personTel" required>
  14 + <el-input v-model="form.personTel"
  15 + :placeholder="$t('addReserveDiningPerson.personTelPlaceholder')"></el-input>
  16 + </el-form-item>
  17 + </el-col>
  18 + </el-row>
  19 +
  20 + <el-row :gutter="20">
  21 + <el-col :span="12">
  22 + <el-form-item :label="$t('addReserveDiningPerson.payWay')" prop="payWay" required>
  23 + <el-select v-model="form.payWay" :placeholder="$t('addReserveDiningPerson.payWayPlaceholder')"
  24 + style="width:100%">
  25 + <el-option :label="$t('addReserveDiningPerson.cash')" value="1"></el-option>
  26 + <el-option :label="$t('addReserveDiningPerson.wechat')" value="2"></el-option>
  27 + <el-option :label="$t('addReserveDiningPerson.alipay')" value="3"></el-option>
  28 + </el-select>
  29 + </el-form-item>
  30 + </el-col>
  31 + <el-col :span="12">
  32 + <el-form-item :label="$t('addReserveDiningPerson.quantity')" prop="quantity" required>
  33 + <el-select v-model="form.quantity" :placeholder="$t('addReserveDiningPerson.quantityPlaceholder')"
  34 + @change="_computeMoney" style="width:100%">
  35 + <el-option v-for="item in form.hoursMaxQuantity" :key="item"
  36 + :label="`${item}${$t('addReserveDiningPerson.unit')}`" :value="item"></el-option>
  37 + </el-select>
  38 + </el-form-item>
  39 + </el-col>
  40 + </el-row>
  41 +
  42 + <el-row :gutter="20">
  43 + <el-col :span="12">
  44 + <el-form-item :label="$t('addReserveDiningPerson.receivableAmount')" prop="receivableAmount" required>
  45 + <el-input v-model="form.receivableAmount"
  46 + :placeholder="$t('addReserveDiningPerson.receivableAmountPlaceholder')" disabled></el-input>
  47 + </el-form-item>
  48 + </el-col>
  49 + <el-col :span="12">
  50 + <el-form-item :label="$t('addReserveDiningPerson.receivedAmount')" prop="receivedAmount" required>
  51 + <el-input v-model="form.receivedAmount"
  52 + :placeholder="$t('addReserveDiningPerson.receivedAmountPlaceholder')"></el-input>
  53 + </el-form-item>
  54 + </el-col>
  55 + </el-row>
  56 +
  57 + <el-row :gutter="20">
  58 + <el-col :span="12">
  59 + <el-form-item :label="$t('addReserveDiningPerson.appointmentTime')" prop="appointmentTime" required>
  60 + <el-date-picker v-model="form.appointmentTime" type="datetime"
  61 + :placeholder="$t('addReserveDiningPerson.appointmentTimePlaceholder')"
  62 + style="width:100%"></el-date-picker>
  63 + </el-form-item>
  64 + </el-col>
  65 + <el-col :span="12">
  66 + <el-form-item :label="$t('addReserveDiningPerson.openTime')" prop="openTime" required>
  67 + <el-select v-model="form.openTime" :placeholder="$t('addReserveDiningPerson.openTimePlaceholder')"
  68 + style="width:100%">
  69 + <template v-for="item in form.openTimes">
  70 + <el-option v-if="item.isOpen === 'Y'" :key="item.hours"
  71 + :label="`${item.hours}${$t('addReserveDiningPerson.hour')}`" :value="item.hours"></el-option>
  72 + </template>
  73 + </el-select>
  74 + </el-form-item>
  75 + </el-col>
  76 + </el-row>
  77 +
  78 + <el-form-item :label="$t('addReserveDiningPerson.remark')" prop="remark" required>
  79 + <el-input type="textarea" v-model="form.remark"
  80 + :placeholder="$t('addReserveDiningPerson.remarkPlaceholder')"></el-input>
  81 + </el-form-item>
  82 + </el-form>
  83 +
  84 + <div slot="footer" class="dialog-footer">
  85 + <el-button @click="closeDialog">{{ $t('common.cancel') }}</el-button>
  86 + <el-button type="primary" @click="save">{{ $t('common.save') }}</el-button>
  87 + </div>
  88 + </el-dialog>
  89 +</template>
  90 +
  91 +<script>
  92 +import { getCommunityId } from '@/api/community/communityApi'
  93 +import { saveReserveGoodsOrder, listReserveParams } from '@/api/scm/doDiningApi'
  94 +
  95 +export default {
  96 + name: 'AddReserveDiningPerson',
  97 + data() {
  98 + return {
  99 + visible: false,
  100 + form: {
  101 + goodsId: '',
  102 + paramsId: '',
  103 + personName: '',
  104 + personTel: '',
  105 + appointmentTime: '',
  106 + receivableAmount: '',
  107 + receivedAmount: '',
  108 + payWay: '',
  109 + state: 'S',
  110 + remark: '',
  111 + openTime: '',
  112 + price: 0.0,
  113 + hoursMaxQuantity: 1,
  114 + quantity: 1,
  115 + type: '1001',
  116 + openTimes: [],
  117 + times: [],
  118 + communityId: ''
  119 + }
  120 + }
  121 + },
  122 + methods: {
  123 + open(params) {
  124 + this.resetForm()
  125 + Object.assign(this.form, params)
  126 + this.form.hoursMaxQuantity = parseInt(params.hoursMaxQuantity)
  127 + this._computeMoney()
  128 + this._listReserveParams()
  129 + this.visible = true
  130 + },
  131 + closeDialog() {
  132 + this.visible = false
  133 + this.$refs.form.resetFields()
  134 + },
  135 + resetForm() {
  136 + this.form = {
  137 + goodsId: '',
  138 + paramsId: '',
  139 + personName: '',
  140 + personTel: '',
  141 + appointmentTime: '',
  142 + receivableAmount: '',
  143 + receivedAmount: '',
  144 + payWay: '',
  145 + state: 'S',
  146 + remark: '',
  147 + openTime: '',
  148 + price: 0.0,
  149 + hoursMaxQuantity: 1,
  150 + quantity: 1,
  151 + type: '1001',
  152 + openTimes: [],
  153 + times: [],
  154 + communityId: ''
  155 + }
  156 + },
  157 + save() {
  158 + this.$refs.form.validate(valid => {
  159 + if (!valid) return
  160 +
  161 + this.form.communityId = getCommunityId()
  162 + this.form.times = [{
  163 + hours: this.form.openTime,
  164 + quantity: this.form.quantity
  165 + }]
  166 +
  167 + saveReserveGoodsOrder(this.form)
  168 + .then(response => {
  169 + if (response.code === 0) {
  170 + this.$message.success(this.$t('common.saveSuccess'))
  171 + this.closeDialog()
  172 + this.$emit('success')
  173 + } else {
  174 + this.$message.error(response.msg)
  175 + }
  176 + })
  177 + .catch(error => {
  178 + console.error('请求失败:', error)
  179 + })
  180 + })
  181 + },
  182 + _listReserveParams() {
  183 + const params = {
  184 + page: 1,
  185 + row: 1,
  186 + communityId: getCommunityId(),
  187 + paramsId: this.form.paramsId
  188 + }
  189 +
  190 + listReserveParams(params)
  191 + .then(response => {
  192 + this.form.openTimes = response.data[0].openTimes
  193 + })
  194 + .catch(error => {
  195 + console.error('请求失败:', error)
  196 + })
  197 + },
  198 + _computeMoney() {
  199 + const money = parseFloat(this.form.price) * parseFloat(this.form.quantity)
  200 + this.form.receivableAmount = money.toFixed(2)
  201 + this.form.receivedAmount = money.toFixed(2)
  202 + }
  203 + }
  204 +}
  205 +</script>
0 206 \ No newline at end of file
... ...
src/components/scm/addReserveParams.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('reserveParamsManage.addTitle')"
  4 + :visible.sync="visible"
  5 + width="70%"
  6 + @close="handleClose"
  7 + >
  8 + <el-form
  9 + ref="form"
  10 + :model="formData"
  11 + :rules="rules"
  12 + label-width="120px"
  13 + label-position="right"
  14 + >
  15 + <el-form-item
  16 + :label="$t('reserveParamsManage.name')"
  17 + prop="name"
  18 + >
  19 + <el-input
  20 + v-model="formData.name"
  21 + :placeholder="$t('reserveParamsManage.namePlaceholder')"
  22 + />
  23 + </el-form-item>
  24 +
  25 + <el-form-item
  26 + :label="$t('reserveParamsManage.paramWay')"
  27 + prop="paramWay"
  28 + >
  29 + <el-select
  30 + v-model="formData.paramWay"
  31 + :placeholder="$t('reserveParamsManage.paramWayPlaceholder')"
  32 + style="width: 100%"
  33 + @change="handleParamWayChange"
  34 + >
  35 + <el-option
  36 + :label="$t('reserveParamsManage.day')"
  37 + value="1"
  38 + />
  39 + <el-option
  40 + :label="$t('reserveParamsManage.week')"
  41 + value="2"
  42 + />
  43 + </el-select>
  44 + </el-form-item>
  45 +
  46 + <el-form-item
  47 + v-if="formData.paramWay === '1'"
  48 + :label="$t('reserveParamsManage.days')"
  49 + prop="days"
  50 + >
  51 + <el-checkbox-group v-model="formData.days">
  52 + <el-checkbox
  53 + v-for="day in 31"
  54 + :key="day"
  55 + :label="day"
  56 + >
  57 + {{ day }}{{ $t('reserveParamsManage.dayUnit') }}
  58 + </el-checkbox>
  59 + </el-checkbox-group>
  60 + </el-form-item>
  61 +
  62 + <el-form-item
  63 + v-if="formData.paramWay === '2'"
  64 + :label="$t('reserveParamsManage.weekdays')"
  65 + prop="workdays"
  66 + >
  67 + <el-checkbox-group v-model="formData.workdays">
  68 + <el-checkbox
  69 + v-for="(weekday, index) in weekdays"
  70 + :key="index"
  71 + :label="index + 1"
  72 + >
  73 + {{ weekday }}
  74 + </el-checkbox>
  75 + </el-checkbox-group>
  76 + </el-form-item>
  77 +
  78 + <el-form-item
  79 + :label="$t('reserveParamsManage.startTime')"
  80 + prop="startTime"
  81 + >
  82 + <el-time-picker
  83 + v-model="formData.startTime"
  84 + :placeholder="$t('reserveParamsManage.startTimePlaceholder')"
  85 + value-format="HH:mm:ss"
  86 + style="width: 100%"
  87 + />
  88 + </el-form-item>
  89 +
  90 + <el-form-item
  91 + :label="$t('reserveParamsManage.maxQuantity')"
  92 + prop="maxQuantity"
  93 + >
  94 + <el-input-number
  95 + v-model="formData.maxQuantity"
  96 + :min="1"
  97 + :placeholder="$t('reserveParamsManage.maxQuantityPlaceholder')"
  98 + style="width: 100%"
  99 + />
  100 + </el-form-item>
  101 +
  102 + <el-form-item
  103 + :label="$t('reserveParamsManage.hoursMaxQuantity')"
  104 + prop="hoursMaxQuantity"
  105 + >
  106 + <el-input-number
  107 + v-model="formData.hoursMaxQuantity"
  108 + :min="1"
  109 + :placeholder="$t('reserveParamsManage.hoursMaxQuantityPlaceholder')"
  110 + style="width: 100%"
  111 + />
  112 + </el-form-item>
  113 + </el-form>
  114 +
  115 + <div slot="footer" class="dialog-footer">
  116 + <el-button @click="visible = false">
  117 + {{ $t('common.cancel') }}
  118 + </el-button>
  119 + <el-button type="primary" @click="handleSubmit">
  120 + {{ $t('common.confirm') }}
  121 + </el-button>
  122 + </div>
  123 + </el-dialog>
  124 +</template>
  125 +
  126 +<script>
  127 +import { saveReserveParams } from '@/api/scm/reserveParamsManageApi'
  128 +import { getCommunityId } from '@/api/community/communityApi'
  129 +
  130 +export default {
  131 + name: 'AddReserveParams',
  132 + data() {
  133 + return {
  134 + visible: false,
  135 + formData: {
  136 + name: '',
  137 + paramWay: '',
  138 + days: [],
  139 + workdays: [],
  140 + startTime: '',
  141 + maxQuantity: '',
  142 + hoursMaxQuantity: '',
  143 + communityId: ''
  144 + },
  145 + weekdays: [
  146 + this.$t('common.monday'),
  147 + this.$t('common.tuesday'),
  148 + this.$t('common.wednesday'),
  149 + this.$t('common.thursday'),
  150 + this.$t('common.friday'),
  151 + this.$t('common.saturday'),
  152 + this.$t('common.sunday')
  153 + ],
  154 + rules: {
  155 + name: [
  156 + { required: true, message: this.$t('reserveParamsManage.nameRequired'), trigger: 'blur' }
  157 + ],
  158 + paramWay: [
  159 + { required: true, message: this.$t('reserveParamsManage.paramWayRequired'), trigger: 'change' }
  160 + ],
  161 + startTime: [
  162 + { required: true, message: this.$t('reserveParamsManage.startTimeRequired'), trigger: 'change' }
  163 + ],
  164 + maxQuantity: [
  165 + { required: true, message: this.$t('reserveParamsManage.maxQuantityRequired'), trigger: 'blur' }
  166 + ],
  167 + hoursMaxQuantity: [
  168 + { required: true, message: this.$t('reserveParamsManage.hoursMaxQuantityRequired'), trigger: 'blur' }
  169 + ]
  170 + }
  171 + }
  172 + },
  173 + methods: {
  174 + open() {
  175 + this.visible = true
  176 + this.formData.communityId = getCommunityId()
  177 + if (this.$refs.form) {
  178 + this.$refs.form.resetFields()
  179 + }
  180 + },
  181 + handleParamWayChange(val) {
  182 + if (val === '1') {
  183 + this.formData.days = Array.from({ length: 31 }, (_, i) => i + 1)
  184 + this.formData.workdays = []
  185 + } else {
  186 + this.formData.workdays = Array.from({ length: 7 }, (_, i) => i + 1)
  187 + this.formData.days = []
  188 + }
  189 + },
  190 + handleSubmit() {
  191 + this.$refs.form.validate(async valid => {
  192 + if (valid) {
  193 + try {
  194 + const params = {
  195 + ...this.formData,
  196 + paramWayText: this.formData.paramWay === '1'
  197 + ? this.formData.days.join(',')
  198 + : this.formData.workdays.join(',')
  199 + }
  200 + await saveReserveParams(params)
  201 + this.$message.success(this.$t('common.addSuccess'))
  202 + this.visible = false
  203 + this.$emit('success')
  204 + } catch (error) {
  205 + this.$message.error(error.message || this.$t('common.addFailed'))
  206 + }
  207 + }
  208 + })
  209 + },
  210 + handleClose() {
  211 + this.$refs.form.resetFields()
  212 + }
  213 + }
  214 +}
  215 +</script>
0 216 \ No newline at end of file
... ...
src/components/scm/addReserveServicePerson.vue 0 → 100644
  1 +<template>
  2 + <el-dialog :title="$t('addReserveServicePerson.reserveService')" :visible.sync="dialogVisible" width="70%"
  3 + @close="handleClose">
  4 + <el-form :model="form" :rules="rules" ref="form" label-width="120px">
  5 + <el-row :gutter="20">
  6 + <el-col :span="12">
  7 + <el-form-item :label="$t('addReserveServicePerson.personName')" prop="personName">
  8 + <el-input v-model="form.personName" :placeholder="$t('addReserveServicePerson.personNamePlaceholder')">
  9 + </el-input>
  10 + </el-form-item>
  11 + </el-col>
  12 + <el-col :span="12">
  13 + <el-form-item :label="$t('addReserveServicePerson.personTel')" prop="personTel">
  14 + <el-input v-model="form.personTel" :placeholder="$t('addReserveServicePerson.personTelPlaceholder')">
  15 + </el-input>
  16 + </el-form-item>
  17 + </el-col>
  18 + </el-row>
  19 +
  20 + <el-row :gutter="20">
  21 + <el-col :span="12">
  22 + <el-form-item :label="$t('addReserveServicePerson.payWay')" prop="payWay">
  23 + <el-select v-model="form.payWay" :placeholder="$t('addReserveServicePerson.payWayPlaceholder')"
  24 + style="width:100%">
  25 + <el-option :label="$t('addReserveServicePerson.cash')" value="1">
  26 + </el-option>
  27 + <el-option :label="$t('addReserveServicePerson.wechat')" value="2">
  28 + </el-option>
  29 + <el-option :label="$t('addReserveServicePerson.alipay')" value="3">
  30 + </el-option>
  31 + </el-select>
  32 + </el-form-item>
  33 + </el-col>
  34 + </el-row>
  35 +
  36 + <el-row :gutter="20">
  37 + <el-col :span="12">
  38 + <el-form-item :label="$t('addReserveServicePerson.receivableAmount')">
  39 + <el-input v-model="form.receivableAmount" disabled
  40 + :placeholder="$t('addReserveServicePerson.receivableAmountPlaceholder')">
  41 + </el-input>
  42 + </el-form-item>
  43 + </el-col>
  44 + <el-col :span="12">
  45 + <el-form-item :label="$t('addReserveServicePerson.receivedAmount')" prop="receivedAmount">
  46 + <el-input v-model="form.receivedAmount"
  47 + :placeholder="$t('addReserveServicePerson.receivedAmountPlaceholder')">
  48 + </el-input>
  49 + </el-form-item>
  50 + </el-col>
  51 + </el-row>
  52 +
  53 + <el-row :gutter="20">
  54 + <el-col :span="12">
  55 + <el-form-item :label="$t('addReserveServicePerson.appointmentTime')" prop="appointmentTime">
  56 + <el-date-picker v-model="form.appointmentTime" type="date"
  57 + :placeholder="$t('addReserveServicePerson.appointmentTimePlaceholder')" style="width:100%">
  58 + </el-date-picker>
  59 + </el-form-item>
  60 + </el-col>
  61 + <el-col :span="12">
  62 + <el-form-item :label="$t('addReserveServicePerson.openTime')" prop="openTime">
  63 + <el-select v-model="form.openTime" :placeholder="$t('addReserveServicePerson.openTimePlaceholder')"
  64 + style="width:100%">
  65 + <template v-for="(item, index) in form.openTimes">
  66 + <el-option v-if="item.isOpen == 'Y'" :key="index" :label="item.hours + $t('addReserveServicePerson.hour')"
  67 + :value="item.hours">
  68 + </el-option>
  69 + </template>
  70 + </el-select>
  71 + </el-form-item>
  72 + </el-col>
  73 + </el-row>
  74 +
  75 + <el-form-item :label="$t('addReserveServicePerson.remark')" prop="remark">
  76 + <el-input type="textarea" :rows="3" v-model="form.remark"
  77 + :placeholder="$t('addReserveServicePerson.remarkPlaceholder')">
  78 + </el-input>
  79 + </el-form-item>
  80 + </el-form>
  81 +
  82 + <span slot="footer" class="dialog-footer">
  83 + <el-button @click="dialogVisible = false">{{ $t('common.cancel') }}</el-button>
  84 + <el-button type="primary" @click="handleSubmit">{{ $t('common.save') }}</el-button>
  85 + </span>
  86 + </el-dialog>
  87 +</template>
  88 +
  89 +<script>
  90 +import { saveReserveGoodsOrder, listReserveParams } from '@/api/scm/reserveServiceManageApi'
  91 +import { getCommunityId } from '@/api/community/communityApi'
  92 +
  93 +export default {
  94 + name: 'AddReserveServicePerson',
  95 + data() {
  96 + return {
  97 + dialogVisible: false,
  98 + form: {
  99 + goodsId: '',
  100 + paramsId: '',
  101 + personName: '',
  102 + personTel: '',
  103 + appointmentTime: '',
  104 + receivableAmount: '',
  105 + receivedAmount: '',
  106 + payWay: '',
  107 + state: 'S',
  108 + remark: '',
  109 + openTime: '',
  110 + price: 0.0,
  111 + hoursMaxQuantity: 1,
  112 + quantity: 1,
  113 + type: '2002',
  114 + openTimes: [],
  115 + communityId: '',
  116 + times: []
  117 + },
  118 + rules: {
  119 + personName: [
  120 + { required: true, message: this.$t('addReserveServicePerson.personNameRequired'), trigger: 'blur' },
  121 + { max: 64, message: this.$t('addReserveServicePerson.personNameMaxLength'), trigger: 'blur' }
  122 + ],
  123 + personTel: [
  124 + { required: true, message: this.$t('addReserveServicePerson.personTelRequired'), trigger: 'blur' },
  125 + { max: 11, message: this.$t('addReserveServicePerson.personTelMaxLength'), trigger: 'blur' }
  126 + ],
  127 + appointmentTime: [
  128 + { required: true, message: this.$t('addReserveServicePerson.appointmentTimeRequired'), trigger: 'blur' }
  129 + ],
  130 + receivableAmount: [
  131 + { required: true, message: this.$t('addReserveServicePerson.receivableAmountRequired'), trigger: 'blur' }
  132 + ],
  133 + receivedAmount: [
  134 + { required: true, message: this.$t('addReserveServicePerson.receivedAmountRequired'), trigger: 'blur' }
  135 + ],
  136 + payWay: [
  137 + { required: true, message: this.$t('addReserveServicePerson.payWayRequired'), trigger: 'change' }
  138 + ],
  139 + remark: [
  140 + { required: true, message: this.$t('addReserveServicePerson.remarkRequired'), trigger: 'blur' }
  141 + ],
  142 + openTime: [
  143 + { required: true, message: this.$t('addReserveServicePerson.openTimeRequired'), trigger: 'change' }
  144 + ]
  145 + }
  146 + }
  147 + },
  148 + methods: {
  149 + open(data) {
  150 + this.resetForm()
  151 + Object.assign(this.form, data)
  152 + this.form.communityId = getCommunityId()
  153 + this._computeMoney()
  154 + this._listReserveParams()
  155 + this.dialogVisible = true
  156 + },
  157 + handleClose() {
  158 + this.$refs.form.resetFields()
  159 + },
  160 + resetForm() {
  161 + this.form = {
  162 + goodsId: '',
  163 + paramsId: '',
  164 + personName: '',
  165 + personTel: '',
  166 + appointmentTime: '',
  167 + receivableAmount: '',
  168 + receivedAmount: '',
  169 + payWay: '',
  170 + state: 'S',
  171 + remark: '',
  172 + openTime: '',
  173 + price: 0.0,
  174 + hoursMaxQuantity: 1,
  175 + quantity: 1,
  176 + type: '2002',
  177 + openTimes: [],
  178 + communityId: '',
  179 + times: []
  180 + }
  181 + },
  182 + async _listReserveParams() {
  183 + try {
  184 + const params = {
  185 + page: 1,
  186 + row: 1,
  187 + communityId: this.form.communityId,
  188 + paramsId: this.form.paramsId
  189 + }
  190 + const { data } = await listReserveParams(params)
  191 + if (data && data.length > 0) {
  192 + this.form.openTimes = data[0].openTimes
  193 + }
  194 + } catch (error) {
  195 + console.error('获取预约参数失败:', error)
  196 + }
  197 + },
  198 + _computeMoney() {
  199 + const money = parseFloat(this.form.price) * parseFloat(this.form.quantity)
  200 + this.form.receivableAmount = money.toFixed(2)
  201 + this.form.receivedAmount = money.toFixed(2)
  202 + },
  203 + handleSubmit() {
  204 + this.$refs.form.validate(async valid => {
  205 + if (valid) {
  206 + try {
  207 + this.form.times = [{
  208 + hours: this.form.openTime,
  209 + quantity: this.form.quantity
  210 + }]
  211 +
  212 + await saveReserveGoodsOrder(this.form)
  213 + this.$message.success(this.$t('common.saveSuccess'))
  214 + this.dialogVisible = false
  215 + this.$emit('success')
  216 + } catch (error) {
  217 + console.error('保存预约服务失败:', error)
  218 + this.$message.error(this.$t('common.saveFailed'))
  219 + }
  220 + }
  221 + })
  222 + }
  223 + }
  224 +}
  225 +</script>
0 226 \ No newline at end of file
... ...
src/components/scm/deleteReserveCatalog.vue
... ... @@ -6,15 +6,14 @@
6 6 @close="handleClose"
7 7 >
8 8 <div class="delete-content">
9   - <p>{{ $t('reserveCatalogManage.delete.confirmText1') }}</p>
  9 + <p>{{ $t('reserveCatalogManage.delete.confirmText') }}</p>
10 10 <p class="delete-name">{{ formData.name }}</p>
11   - <p>{{ $t('reserveCatalogManage.delete.confirmText2') }}</p>
12 11 </div>
13 12 <span slot="footer" class="dialog-footer">
14 13 <el-button @click="visible = false">
15 14 {{ $t('common.cancel') }}
16 15 </el-button>
17   - <el-button type="primary" @click="handleSubmit">
  16 + <el-button type="primary" @click="handleConfirm" :loading="loading">
18 17 {{ $t('common.confirm') }}
19 18 </el-button>
20 19 </span>
... ... @@ -30,6 +29,7 @@ export default {
30 29 data() {
31 30 return {
32 31 visible: false,
  32 + loading: false,
33 33 formData: {
34 34 catalogId: '',
35 35 name: '',
... ... @@ -38,13 +38,13 @@ export default {
38 38 }
39 39 },
40 40 methods: {
41   - open(row) {
  41 + open(data) {
  42 + this.visible = true
42 43 this.formData = {
43   - catalogId: row.catalogId,
44   - name: row.name,
  44 + catalogId: data.catalogId,
  45 + name: data.name,
45 46 communityId: getCommunityId()
46 47 }
47   - this.visible = true
48 48 },
49 49 handleClose() {
50 50 this.formData = {
... ... @@ -52,15 +52,22 @@ export default {
52 52 name: '',
53 53 communityId: ''
54 54 }
  55 + this.loading = false
55 56 },
56   - async handleSubmit() {
  57 + async handleConfirm() {
57 58 try {
58   - await deleteReserveCatalog(this.formData)
  59 + this.loading = true
  60 + await deleteReserveCatalog({
  61 + catalogId: this.formData.catalogId,
  62 + communityId: this.formData.communityId
  63 + })
59 64 this.$message.success(this.$t('reserveCatalogManage.delete.success'))
60 65 this.visible = false
61 66 this.$emit('success')
62 67 } catch (error) {
63   - this.$message.error(this.$t('reserveCatalogManage.delete.error'))
  68 + this.$message.error(error.message || this.$t('reserveCatalogManage.delete.error'))
  69 + } finally {
  70 + this.loading = false
64 71 }
65 72 }
66 73 }
... ... @@ -75,6 +82,6 @@ export default {
75 82 .delete-name {
76 83 font-weight: bold;
77 84 color: #f56c6c;
78   - margin: 10px 0;
  85 + margin-top: 10px;
79 86 }
80 87 </style>
81 88 \ No newline at end of file
... ...
src/components/scm/deleteReserveDining.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('common.confirmOperation')"
  4 + :visible.sync="visible"
  5 + width="30%"
  6 + @close="closeDialog"
  7 + >
  8 + <div class="text-center">
  9 + <p>{{ $t('deleteReserveDining.confirmDelete') }}</p>
  10 + </div>
  11 + <div slot="footer" class="dialog-footer">
  12 + <el-button @click="closeDialog">{{ $t('common.cancel') }}</el-button>
  13 + <el-button type="primary" @click="confirmDelete">{{ $t('common.confirmDelete') }}</el-button>
  14 + </div>
  15 + </el-dialog>
  16 +</template>
  17 +
  18 +<script>
  19 +import { getCommunityId } from '@/api/community/communityApi'
  20 +import { deleteReserveGoods } from '@/api/scm/doDiningApi'
  21 +
  22 +export default {
  23 + name: 'DeleteReserveDining',
  24 + data() {
  25 + return {
  26 + visible: false,
  27 + form: {
  28 + goodsId: '',
  29 + communityId: ''
  30 + }
  31 + }
  32 + },
  33 + methods: {
  34 + open(params) {
  35 + this.form = Object.assign({}, params)
  36 + this.form.communityId = getCommunityId()
  37 + this.visible = true
  38 + },
  39 + closeDialog() {
  40 + this.visible = false
  41 + this.form = {
  42 + goodsId: '',
  43 + communityId: ''
  44 + }
  45 + },
  46 + confirmDelete() {
  47 + deleteReserveGoods(this.form)
  48 + .then(response => {
  49 + if (response.code === 0) {
  50 + this.$message.success(this.$t('common.deleteSuccess'))
  51 + this.closeDialog()
  52 + this.$emit('success')
  53 + } else {
  54 + this.$message.error(response.msg)
  55 + }
  56 + })
  57 + .catch(error => {
  58 + console.error('请求失败:', error)
  59 + })
  60 + }
  61 + }
  62 +}
  63 +</script>
  64 +
  65 +<style scoped>
  66 +.text-center {
  67 + text-align: center;
  68 +}
  69 +</style>
0 70 \ No newline at end of file
... ...
src/components/scm/deleteReserveOrderPerson.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('reserveOrder.cancelAppointment')"
  4 + :visible.sync="visible"
  5 + width="30%"
  6 + @close="handleClose"
  7 + >
  8 + <el-form>
  9 + <el-form-item :label="$t('reserveOrder.confirmCancel')">
  10 + <span>{{ currentRow.orderId }}</span>
  11 + </el-form-item>
  12 + </el-form>
  13 + <span slot="footer" class="dialog-footer">
  14 + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
  15 + <el-button type="primary" @click="handleConfirm" :loading="loading">
  16 + {{ $t('common.confirm') }}
  17 + </el-button>
  18 + </span>
  19 + </el-dialog>
  20 +</template>
  21 +
  22 +<script>
  23 +import { cancelReserveOrder } from '@/api/scm/reserveOrderApi'
  24 +
  25 +export default {
  26 + name: 'DeleteReserveOrderPerson',
  27 + data() {
  28 + return {
  29 + visible: false,
  30 + loading: false,
  31 + currentRow: {}
  32 + }
  33 + },
  34 + methods: {
  35 + open(row) {
  36 + this.currentRow = { ...row }
  37 + this.visible = true
  38 + },
  39 + handleClose() {
  40 + this.currentRow = {}
  41 + },
  42 + async handleConfirm() {
  43 + try {
  44 + this.loading = true
  45 + await cancelReserveOrder({ orderId: this.currentRow.orderId })
  46 + this.$message.success(this.$t('reserveOrder.cancelSuccess'))
  47 + this.$emit('success')
  48 + this.visible = false
  49 + } catch (error) {
  50 + this.$message.error(this.$t('reserveOrder.cancelError'))
  51 + } finally {
  52 + this.loading = false
  53 + }
  54 + }
  55 + }
  56 +}
  57 +</script>
0 58 \ No newline at end of file
... ...
src/components/scm/deleteReserveParams.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('reserveParamsManage.deleteTitle')"
  4 + :visible.sync="visible"
  5 + width="500px"
  6 + @close="handleClose"
  7 + >
  8 + <div class="delete-content">
  9 + <el-alert
  10 + type="warning"
  11 + :title="$t('reserveParamsManage.deleteConfirm')"
  12 + :description="$t('reserveParamsManage.deleteTip')"
  13 + show-icon
  14 + :closable="false"
  15 + />
  16 + </div>
  17 +
  18 + <div slot="footer" class="dialog-footer">
  19 + <el-button @click="visible = false">
  20 + {{ $t('common.cancel') }}
  21 + </el-button>
  22 + <el-button type="danger" @click="handleConfirm" :loading="loading">
  23 + {{ $t('common.confirmDelete') }}
  24 + </el-button>
  25 + </div>
  26 + </el-dialog>
  27 +</template>
  28 +
  29 +<script>
  30 +import { deleteReserveParams } from '@/api/scm/reserveParamsManageApi'
  31 +import { getCommunityId } from '@/api/community/communityApi'
  32 +
  33 +export default {
  34 + name: 'DeleteReserveParams',
  35 + data() {
  36 + return {
  37 + visible: false,
  38 + loading: false,
  39 + currentRow: {
  40 + paramsId: '',
  41 + communityId: ''
  42 + }
  43 + }
  44 + },
  45 + methods: {
  46 + open(row) {
  47 + this.visible = true
  48 + this.currentRow = {
  49 + paramsId: row.paramsId,
  50 + communityId: getCommunityId()
  51 + }
  52 + },
  53 + async handleConfirm() {
  54 + try {
  55 + this.loading = true
  56 + await deleteReserveParams(this.currentRow)
  57 + this.$message.success(this.$t('common.deleteSuccess'))
  58 + this.visible = false
  59 + this.$emit('success')
  60 + } catch (error) {
  61 + this.$message.error(error.message || this.$t('common.deleteFailed'))
  62 + } finally {
  63 + this.loading = false
  64 + }
  65 + },
  66 + handleClose() {
  67 + this.currentRow = {
  68 + paramsId: '',
  69 + communityId: ''
  70 + }
  71 + }
  72 + }
  73 +}
  74 +</script>
  75 +
  76 +<style scoped>
  77 +.delete-content {
  78 + margin-bottom: 20px;
  79 +}
  80 +</style>
0 81 \ No newline at end of file
... ...
src/components/scm/editReserveCatalog.vue
... ... @@ -12,57 +12,57 @@
12 12 label-width="120px"
13 13 >
14 14 <el-form-item
15   - :label="$t('reserveCatalogManage.edit.name')"
  15 + :label="$t('reserveCatalogManage.form.name')"
16 16 prop="name"
17 17 >
18 18 <el-input
19 19 v-model="formData.name"
20   - :placeholder="$t('reserveCatalogManage.edit.namePlaceholder')"
  20 + :placeholder="$t('reserveCatalogManage.form.namePlaceholder')"
21 21 />
22 22 </el-form-item>
23 23 <el-form-item
24   - :label="$t('reserveCatalogManage.edit.sort')"
  24 + :label="$t('reserveCatalogManage.form.sort')"
25 25 prop="sort"
26 26 >
27 27 <el-input
28 28 v-model="formData.sort"
29   - :placeholder="$t('reserveCatalogManage.edit.sortPlaceholder')"
  29 + :placeholder="$t('reserveCatalogManage.form.sortPlaceholder')"
30 30 />
31 31 </el-form-item>
32 32 <el-form-item
33   - :label="$t('reserveCatalogManage.edit.type')"
  33 + :label="$t('reserveCatalogManage.form.type')"
34 34 prop="type"
35 35 >
36 36 <el-select
37 37 v-model="formData.type"
38   - :placeholder="$t('reserveCatalogManage.edit.typePlaceholder')"
  38 + :placeholder="$t('reserveCatalogManage.form.typePlaceholder')"
39 39 style="width:100%"
40 40 >
41 41 <el-option
42   - :label="$t('reserveCatalogManage.edit.typeOption1')"
  42 + :label="$t('reserveCatalogManage.form.typeOptions.dining')"
43 43 value="1001"
44 44 />
45 45 <el-option
46   - :label="$t('reserveCatalogManage.edit.typeOption2')"
  46 + :label="$t('reserveCatalogManage.form.typeOptions.service')"
47 47 value="2002"
48 48 />
49 49 </el-select>
50 50 </el-form-item>
51 51 <el-form-item
52   - :label="$t('reserveCatalogManage.edit.state')"
  52 + :label="$t('reserveCatalogManage.form.state')"
53 53 prop="state"
54 54 >
55 55 <el-select
56 56 v-model="formData.state"
57   - :placeholder="$t('reserveCatalogManage.edit.statePlaceholder')"
  57 + :placeholder="$t('reserveCatalogManage.form.statePlaceholder')"
58 58 style="width:100%"
59 59 >
60 60 <el-option
61   - :label="$t('reserveCatalogManage.edit.stateOption1')"
  61 + :label="$t('reserveCatalogManage.form.stateOptions.show')"
62 62 value="1001"
63 63 />
64 64 <el-option
65   - :label="$t('reserveCatalogManage.edit.stateOption2')"
  65 + :label="$t('reserveCatalogManage.form.stateOptions.hide')"
66 66 value="2002"
67 67 />
68 68 </el-select>
... ... @@ -118,15 +118,12 @@ export default {
118 118 }
119 119 },
120 120 methods: {
121   - open(row) {
  121 + open(data) {
  122 + this.visible = true
122 123 this.formData = {
123   - ...row,
  124 + ...data,
124 125 communityId: getCommunityId()
125 126 }
126   - this.visible = true
127   - this.$nextTick(() => {
128   - this.$refs.form.clearValidate()
129   - })
130 127 },
131 128 handleClose() {
132 129 this.$refs.form.resetFields()
... ... @@ -140,7 +137,7 @@ export default {
140 137 this.visible = false
141 138 this.$emit('success')
142 139 } catch (error) {
143   - this.$message.error(this.$t('reserveCatalogManage.edit.error'))
  140 + this.$message.error(error.message || this.$t('reserveCatalogManage.edit.error'))
144 141 }
145 142 }
146 143 })
... ...
src/components/scm/editReserveParams.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('reserveParamsManage.editTitle')"
  4 + :visible.sync="visible"
  5 + width="70%"
  6 + @close="handleClose"
  7 + >
  8 + <el-form
  9 + ref="form"
  10 + :model="formData"
  11 + :rules="rules"
  12 + label-width="120px"
  13 + label-position="right"
  14 + >
  15 + <el-form-item
  16 + :label="$t('reserveParamsManage.name')"
  17 + prop="name"
  18 + >
  19 + <el-input
  20 + v-model="formData.name"
  21 + :placeholder="$t('reserveParamsManage.namePlaceholder')"
  22 + />
  23 + </el-form-item>
  24 +
  25 + <el-form-item
  26 + :label="$t('reserveParamsManage.paramWay')"
  27 + prop="paramWay"
  28 + >
  29 + <el-select
  30 + v-model="formData.paramWay"
  31 + :placeholder="$t('reserveParamsManage.paramWayPlaceholder')"
  32 + style="width: 100%"
  33 + @change="handleParamWayChange"
  34 + >
  35 + <el-option
  36 + :label="$t('reserveParamsManage.day')"
  37 + value="1"
  38 + />
  39 + <el-option
  40 + :label="$t('reserveParamsManage.week')"
  41 + value="2"
  42 + />
  43 + </el-select>
  44 + </el-form-item>
  45 +
  46 + <el-form-item
  47 + v-if="formData.paramWay === '1'"
  48 + :label="$t('reserveParamsManage.days')"
  49 + prop="days"
  50 + >
  51 + <el-checkbox-group v-model="formData.days">
  52 + <el-checkbox
  53 + v-for="day in 31"
  54 + :key="day"
  55 + :label="day"
  56 + >
  57 + {{ day }}{{ $t('reserveParamsManage.dayUnit') }}
  58 + </el-checkbox>
  59 + </el-checkbox-group>
  60 + </el-form-item>
  61 +
  62 + <el-form-item
  63 + v-if="formData.paramWay === '2'"
  64 + :label="$t('reserveParamsManage.weekdays')"
  65 + prop="workdays"
  66 + >
  67 + <el-checkbox-group v-model="formData.workdays">
  68 + <el-checkbox
  69 + v-for="(weekday, index) in weekdays"
  70 + :key="index"
  71 + :label="index + 1"
  72 + >
  73 + {{ weekday }}
  74 + </el-checkbox>
  75 + </el-checkbox-group>
  76 + </el-form-item>
  77 +
  78 + <el-form-item
  79 + :label="$t('reserveParamsManage.startTime')"
  80 + prop="startTime"
  81 + >
  82 + <el-time-picker
  83 + v-model="formData.startTime"
  84 + :placeholder="$t('reserveParamsManage.startTimePlaceholder')"
  85 + value-format="HH:mm:ss"
  86 + style="width: 100%"
  87 + />
  88 + </el-form-item>
  89 +
  90 + <el-form-item
  91 + :label="$t('reserveParamsManage.maxQuantity')"
  92 + prop="maxQuantity"
  93 + >
  94 + <el-input-number
  95 + v-model="formData.maxQuantity"
  96 + :min="1"
  97 + :placeholder="$t('reserveParamsManage.maxQuantityPlaceholder')"
  98 + style="width: 100%"
  99 + />
  100 + </el-form-item>
  101 +
  102 + <el-form-item
  103 + :label="$t('reserveParamsManage.hoursMaxQuantity')"
  104 + prop="hoursMaxQuantity"
  105 + >
  106 + <el-input-number
  107 + v-model="formData.hoursMaxQuantity"
  108 + :min="1"
  109 + :placeholder="$t('reserveParamsManage.hoursMaxQuantityPlaceholder')"
  110 + style="width: 100%"
  111 + />
  112 + </el-form-item>
  113 + </el-form>
  114 +
  115 + <div slot="footer" class="dialog-footer">
  116 + <el-button @click="visible = false">
  117 + {{ $t('common.cancel') }}
  118 + </el-button>
  119 + <el-button type="primary" @click="handleSubmit">
  120 + {{ $t('common.confirm') }}
  121 + </el-button>
  122 + </div>
  123 + </el-dialog>
  124 +</template>
  125 +
  126 +<script>
  127 +import { updateReserveParams } from '@/api/scm/reserveParamsManageApi'
  128 +import { getCommunityId } from '@/api/community/communityApi'
  129 +
  130 +export default {
  131 + name: 'EditReserveParams',
  132 + data() {
  133 + return {
  134 + visible: false,
  135 + formData: {
  136 + paramsId: '',
  137 + name: '',
  138 + paramWay: '',
  139 + days: [],
  140 + workdays: [],
  141 + startTime: '',
  142 + maxQuantity: '',
  143 + hoursMaxQuantity: '',
  144 + communityId: ''
  145 + },
  146 + weekdays: [
  147 + this.$t('common.monday'),
  148 + this.$t('common.tuesday'),
  149 + this.$t('common.wednesday'),
  150 + this.$t('common.thursday'),
  151 + this.$t('common.friday'),
  152 + this.$t('common.saturday'),
  153 + this.$t('common.sunday')
  154 + ],
  155 + rules: {
  156 + name: [
  157 + { required: true, message: this.$t('reserveParamsManage.nameRequired'), trigger: 'blur' }
  158 + ],
  159 + paramWay: [
  160 + { required: true, message: this.$t('reserveParamsManage.paramWayRequired'), trigger: 'change' }
  161 + ],
  162 + startTime: [
  163 + { required: true, message: this.$t('reserveParamsManage.startTimeRequired'), trigger: 'change' }
  164 + ],
  165 + maxQuantity: [
  166 + { required: true, message: this.$t('reserveParamsManage.maxQuantityRequired'), trigger: 'blur' }
  167 + ],
  168 + hoursMaxQuantity: [
  169 + { required: true, message: this.$t('reserveParamsManage.hoursMaxQuantityRequired'), trigger: 'blur' }
  170 + ]
  171 + }
  172 + }
  173 + },
  174 + methods: {
  175 + open(row) {
  176 + this.visible = true
  177 + this.formData = {
  178 + ...row,
  179 + days: row.paramWay === '1' ? row.paramWayText.split(',').map(Number) : [],
  180 + workdays: row.paramWay === '2' ? row.paramWayText.split(',').map(Number) : [],
  181 + communityId: getCommunityId()
  182 + }
  183 + },
  184 + handleParamWayChange(val) {
  185 + if (val === '1') {
  186 + this.formData.days = this.formData.days.length
  187 + ? this.formData.days
  188 + : Array.from({ length: 31 }, (_, i) => i + 1)
  189 + this.formData.workdays = []
  190 + } else {
  191 + this.formData.workdays = this.formData.workdays.length
  192 + ? this.formData.workdays
  193 + : Array.from({ length: 7 }, (_, i) => i + 1)
  194 + this.formData.days = []
  195 + }
  196 + },
  197 + handleSubmit() {
  198 + this.$refs.form.validate(async valid => {
  199 + if (valid) {
  200 + try {
  201 + const params = {
  202 + ...this.formData,
  203 + paramWayText: this.formData.paramWay === '1'
  204 + ? this.formData.days.join(',')
  205 + : this.formData.workdays.join(',')
  206 + }
  207 + await updateReserveParams(params)
  208 + this.$message.success(this.$t('common.editSuccess'))
  209 + this.visible = false
  210 + this.$emit('success')
  211 + } catch (error) {
  212 + this.$message.error(error.message || this.$t('common.editFailed'))
  213 + }
  214 + }
  215 + })
  216 + },
  217 + handleClose() {
  218 + this.$refs.form.resetFields()
  219 + }
  220 + }
  221 +}
  222 +</script>
0 223 \ No newline at end of file
... ...
src/components/scm/editReserveParamsOpenTime.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('reserveParamsManage.setTimeTitle')"
  4 + :visible.sync="visible"
  5 + width="80%"
  6 + @close="handleClose"
  7 + >
  8 + <el-row :gutter="20">
  9 + <el-col
  10 + v-for="(item, index) in formData.openTimes"
  11 + :key="index"
  12 + :span="6"
  13 + class="time-item"
  14 + >
  15 + <div class="time-wrapper">
  16 + <span class="time-label">{{ item.hours }}{{ $t('reserveParamsManage.hour') }}</span>
  17 + <el-select
  18 + v-model="item.isOpen"
  19 + :placeholder="$t('reserveParamsManage.selectStatus')"
  20 + @change="handleStatusChange(item)"
  21 + >
  22 + <el-option
  23 + :label="$t('reserveParamsManage.canReserve')"
  24 + value="Y"
  25 + />
  26 + <el-option
  27 + :label="$t('reserveParamsManage.cannotReserve')"
  28 + value="N"
  29 + />
  30 + </el-select>
  31 + </div>
  32 + </el-col>
  33 + </el-row>
  34 +
  35 + <div slot="footer" class="dialog-footer">
  36 + <el-button @click="visible = false">
  37 + {{ $t('common.close') }}
  38 + </el-button>
  39 + </div>
  40 + </el-dialog>
  41 +</template>
  42 +
  43 +<script>
  44 +import { updateReserveParamsOpenTime } from '@/api/scm/reserveParamsManageApi'
  45 +import { getCommunityId } from '@/api/community/communityApi'
  46 +
  47 +export default {
  48 + name: 'EditReserveParamsOpenTime',
  49 + data() {
  50 + return {
  51 + visible: false,
  52 + formData: {
  53 + openTimes: []
  54 + }
  55 + }
  56 + },
  57 + methods: {
  58 + open(row) {
  59 + this.visible = true
  60 + this.formData.openTimes = row.openTimes.map(item => ({
  61 + ...item,
  62 + paramsId: row.paramsId,
  63 + communityId: getCommunityId()
  64 + }))
  65 + },
  66 + async handleStatusChange(item) {
  67 + try {
  68 + await updateReserveParamsOpenTime(item)
  69 + this.$message.success(this.$t('common.updateSuccess'))
  70 + this.$emit('success')
  71 + } catch (error) {
  72 + this.$message.error(error.message || this.$t('common.updateFailed'))
  73 + }
  74 + },
  75 + handleClose() {
  76 + this.formData.openTimes = []
  77 + }
  78 + }
  79 +}
  80 +</script>
  81 +
  82 +<style scoped>
  83 +.time-item {
  84 + margin-bottom: 20px;
  85 +}
  86 +
  87 +.time-wrapper {
  88 + display: flex;
  89 + align-items: center;
  90 +}
  91 +
  92 +.time-label {
  93 + width: 60px;
  94 + margin-right: 10px;
  95 + text-align: right;
  96 +}
  97 +</style>
0 98 \ No newline at end of file
... ...
src/components/scm/uploadImageUrl.vue 0 → 100644
  1 +<template>
  2 + <div class="upload-image-container">
  3 + <div v-for="(image, index) in photos" :key="index" class="image-item">
  4 + <el-image
  5 + :src="image"
  6 + fit="cover"
  7 + style="width: 100px; height: 100px"
  8 + :preview-src-list="photos"
  9 + >
  10 + <div slot="error" class="image-slot">
  11 + <i class="el-icon-picture-outline"></i>
  12 + </div>
  13 + </el-image>
  14 + <i
  15 + class="el-icon-delete remove-icon"
  16 + @click="removeImage(image)"
  17 + ></i>
  18 + </div>
  19 +
  20 + <div
  21 + v-if="photos.length < imageCount"
  22 + class="upload-button"
  23 + @click="triggerUpload"
  24 + >
  25 + <i class="el-icon-plus"></i>
  26 + </div>
  27 +
  28 + <input
  29 + type="file"
  30 + ref="fileInput"
  31 + accept="image/*"
  32 + hidden
  33 + @change="handleFileChange"
  34 + />
  35 + </div>
  36 +</template>
  37 +
  38 +<script>
  39 +import { uploadFile } from '@/api/scm/editReserveServiceApi'
  40 +import { getCommunityId } from '@/api/community/communityApi'
  41 +
  42 +export default {
  43 + name: 'UploadImageUrl',
  44 + props: {
  45 + imageCount: {
  46 + type: Number,
  47 + default: 1
  48 + }
  49 + },
  50 + data() {
  51 + return {
  52 + photos: [], // 用于显示的图片数组(base64)
  53 + photosUrl: [], // 用于传递给父组件的图片数组({fileId, url})
  54 + communityId: ''
  55 + }
  56 + },
  57 + created() {
  58 + this.communityId = getCommunityId()
  59 + },
  60 + methods: {
  61 + notifyPhotos(photos) {
  62 + this.photos = []
  63 + this.photosUrl = []
  64 +
  65 + photos.forEach(photo => {
  66 + if (photo.indexOf('base64,') > -1) {
  67 + this.photos.push(photo)
  68 + return
  69 + }
  70 +
  71 + if (photo.indexOf('http') > -1) {
  72 + this.photos.push(photo)
  73 + this.photosUrl.push({ url: photo })
  74 + return
  75 + }
  76 +
  77 + const url = `/callComponent/download/getFile/file?fileId=${photo}&communityId=-1`
  78 + this.photos.push(url)
  79 + this.photosUrl.push({ fileId: photo, url })
  80 + })
  81 + },
  82 + triggerUpload() {
  83 + this.$refs.fileInput.click()
  84 + },
  85 + async handleFileChange(event) {
  86 + const files = event.target.files
  87 + if (!files || files.length === 0) return
  88 +
  89 + const file = files[0]
  90 + if (file.size > 2 * 1024 * 1024) {
  91 + this.$message.error(this.$t('uploadImage.sizeLimit'))
  92 + return
  93 + }
  94 +
  95 + // 预览图片
  96 + const reader = new FileReader()
  97 + reader.onload = (e) => {
  98 + this.photos.push(e.target.result)
  99 + this.$emit('notify-upload-cover-image', this.photosUrl)
  100 + }
  101 + reader.readAsDataURL(file)
  102 +
  103 + // 上传图片
  104 + try {
  105 + const formData = new FormData()
  106 + formData.append('uploadFile', file)
  107 + formData.append('communityId', this.communityId)
  108 +
  109 + const { data } = await uploadFile(formData)
  110 + this.photosUrl.push(data)
  111 + this.$emit('notify-upload-cover-image', this.photosUrl)
  112 + } catch (error) {
  113 + console.error('上传失败:', error)
  114 + this.$message.error(this.$t('uploadImage.uploadError'))
  115 + } finally {
  116 + event.target.value = null
  117 + }
  118 + },
  119 + removeImage(image) {
  120 + const index = this.photos.indexOf(image)
  121 + if (index > -1) {
  122 + this.photos.splice(index, 1)
  123 + this.photosUrl.splice(index, 1)
  124 + this.$emit('notify-upload-cover-image', this.photosUrl)
  125 + }
  126 + },
  127 + clearImages() {
  128 + this.photos = []
  129 + this.photosUrl = []
  130 + this.$emit('notify-upload-cover-image', this.photosUrl)
  131 + }
  132 + }
  133 +}
  134 +</script>
  135 +
  136 +<style lang="scss" scoped>
  137 +.upload-image-container {
  138 + display: flex;
  139 + flex-wrap: wrap;
  140 + gap: 10px;
  141 +
  142 + .image-item {
  143 + position: relative;
  144 + width: 100px;
  145 + height: 100px;
  146 +
  147 + .remove-icon {
  148 + position: absolute;
  149 + top: -10px;
  150 + right: -10px;
  151 + color: #f56c6c;
  152 + font-size: 18px;
  153 + cursor: pointer;
  154 + background: white;
  155 + border-radius: 50%;
  156 + z-index: 1;
  157 +
  158 + &:hover {
  159 + color: #f78989;
  160 + }
  161 + }
  162 + }
  163 +
  164 + .upload-button {
  165 + width: 100px;
  166 + height: 100px;
  167 + border: 1px dashed #dcdfe6;
  168 + border-radius: 4px;
  169 + display: flex;
  170 + align-items: center;
  171 + justify-content: center;
  172 + cursor: pointer;
  173 + color: #909399;
  174 + font-size: 24px;
  175 +
  176 + &:hover {
  177 + border-color: #409eff;
  178 + color: #409eff;
  179 + }
  180 + }
  181 +
  182 + .image-slot {
  183 + display: flex;
  184 + justify-content: center;
  185 + align-items: center;
  186 + width: 100%;
  187 + height: 100%;
  188 + background: #f5f7fa;
  189 + color: #909399;
  190 + }
  191 +}
  192 +</style>
0 193 \ No newline at end of file
... ...
src/i18n/scmI18n.js
... ... @@ -10,6 +10,17 @@ import { messages as integralGiftDetailManageMessages } from &#39;../views/scm/integ
10 10 import { messages as communityIntegralMessages } from '../views/scm/communityIntegralLang'
11 11 import { messages as goldMessages } from '../views/scm/goldLang'
12 12 import { messages as reserveCatalogManageMessages } from '../views/scm/reserveCatalogManageLang'
  13 +import { messages as reserveParamsManageMessages } from '../views/scm/reserveParamsManageLang'
  14 +import { messages as reserveDiningManageMessages } from '../views/scm/reserveDiningManageLang'
  15 +import { messages as reserveServiceManageMessages } from '../views/scm/reserveServiceManageLang'
  16 +import { messages as addReserveDiningMessages } from '../views/scm/addReserveDiningLang'
  17 +import { messages as editReserveDiningMessages } from '../views/scm/editReserveDiningLang'
  18 +import { messages as doDiningMessages } from '../views/scm/doDiningLang'
  19 +import { messages as addReserveServiceMessages } from '../views/scm/addReserveServiceLang'
  20 +import { messages as ownerDiningMessages } from '../views/scm/ownerDiningLang'
  21 +import { messages as editReserveServiceMessages } from '../views/scm/editReserveServiceLang'
  22 +import { messages as reserveOrderMessages } from '../views/scm/reserveOrderLang'
  23 +import { messages as reserveConfirmMessages } from '../views/scm/reserveConfirmLang'
13 24  
14 25 export const messages = {
15 26 en: {
... ... @@ -26,6 +37,17 @@ export const messages = {
26 37 ...communityIntegralMessages.en,
27 38 ...goldMessages.en,
28 39 ...reserveCatalogManageMessages.en,
  40 + ...reserveParamsManageMessages.en,
  41 + ...reserveDiningManageMessages.en,
  42 + ...reserveServiceManageMessages.en,
  43 + ...addReserveDiningMessages.en,
  44 + ...editReserveDiningMessages.en,
  45 + ...doDiningMessages.en,
  46 + ...addReserveServiceMessages.en,
  47 + ...ownerDiningMessages.en,
  48 + ...editReserveServiceMessages.en,
  49 + ...reserveOrderMessages.en,
  50 + ...reserveConfirmMessages.en,
29 51 },
30 52 zh: {
31 53 ...couponMarketMessages.zh,
... ... @@ -40,5 +62,16 @@ export const messages = {
40 62 ...communityIntegralMessages.zh,
41 63 ...goldMessages.zh,
42 64 ...reserveCatalogManageMessages.zh,
  65 + ...reserveParamsManageMessages.zh,
  66 + ...reserveDiningManageMessages.zh,
  67 + ...reserveServiceManageMessages.zh,
  68 + ...addReserveDiningMessages.zh,
  69 + ...editReserveDiningMessages.zh,
  70 + ...doDiningMessages.zh,
  71 + ...addReserveServiceMessages.zh,
  72 + ...ownerDiningMessages.zh,
  73 + ...editReserveServiceMessages.zh,
  74 + ...reserveOrderMessages.zh,
  75 + ...reserveConfirmMessages.zh,
43 76 }
44 77 }
45 78 \ No newline at end of file
... ...
src/router/scmRouter.js
... ... @@ -59,4 +59,64 @@ export default [
59 59 name: '/pages/reserve/reserveCatalogManage',
60 60 component: () => import('@/views/scm/reserveCatalogManageList.vue')
61 61 },
  62 + {
  63 + path: '/pages/reserve/reserveParamsManage',
  64 + name: '/pages/reserve/reserveParamsManage',
  65 + component: () => import('@/views/scm/reserveParamsManageList.vue')
  66 + },
  67 + {
  68 + path: '/pages/reserve/reserveDiningManage',
  69 + name: '/pages/reserve/reserveDiningManage',
  70 + component: () => import('@/views/scm/reserveDiningManageList.vue')
  71 + },
  72 + {
  73 + path: '/pages/reserve/reserveServiceManage',
  74 + name: '/pages/reserve/reserveServiceManage',
  75 + component: () => import('@/views/scm/reserveServiceManageList.vue')
  76 + },
  77 + {
  78 + path: '/views/scm/addReserveDining',
  79 + name: '/views/scm/addReserveDining',
  80 + component: () => import('@/views/scm/addReserveDiningList.vue')
  81 + },
  82 + {
  83 + path: '/views/scm/editReserveDining',
  84 + name: '/views/scm/editReserveDining',
  85 + component: () => import('@/views/scm/editReserveDiningList.vue')
  86 + },
  87 + {
  88 + path: '/views/scm/doDining',
  89 + name: '/views/scm/doDining',
  90 + component: () => import('@/views/scm/doDiningList.vue')
  91 + },
  92 + {
  93 + path: '/views/scm/addReserveService',
  94 + name: '/views/scm/addReserveService',
  95 + component: () => import('@/views/scm/addReserveServiceList.vue')
  96 + },
  97 + {
  98 + path: '/views/scm/ownerDining',
  99 + name: '/views/scm/ownerDining',
  100 + component: () => import('@/views/scm/ownerDiningList.vue')
  101 + },
  102 + {
  103 + path: '/views/scm/reserveCatalogManage',
  104 + name: '/views/scm/reserveCatalogManage',
  105 + component: () => import('@/views/scm/reserveCatalogManageList.vue')
  106 + },
  107 + {
  108 + path: '/views/scm/editReserveService',
  109 + name: '/views/scm/editReserveService',
  110 + component: () => import('@/views/scm/editReserveServiceList.vue')
  111 + },
  112 + {
  113 + path: '/pages/reserve/reserveOrder',
  114 + name: '/pages/reserve/reserveOrder',
  115 + component: () => import('@/views/scm/reserveOrderList.vue')
  116 + },
  117 + {
  118 + path:'/pages/reserve/reserveConfirm',
  119 + name:'/pages/reserve/reserveConfirm',
  120 + component: () => import('@/views/scm/reserveConfirmList.vue')
  121 + },
62 122 ]
63 123 \ No newline at end of file
... ...
src/views/scm/addReserveDiningLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + addReserveDining: {
  4 + title: 'Add Dining Product',
  5 + goodsName: 'Name',
  6 + goodsNamePlaceholder: 'Required, please enter name',
  7 + paramsId: 'Parameter',
  8 + paramsIdPlaceholder: 'Required, please select parameter',
  9 + price: 'Price',
  10 + pricePlaceholder: 'Required, please enter price',
  11 + sort: 'Sort',
  12 + sortPlaceholder: 'Required, please enter sort',
  13 + startDate: 'Start Date',
  14 + startDatePlaceholder: 'Required, please select start date',
  15 + endDate: 'End Date',
  16 + endDatePlaceholder: 'Required, please select end date',
  17 + imgUrl: 'Product Cover',
  18 + state: 'Status',
  19 + statePlaceholder: 'Required, please select status',
  20 + stateOff: 'Off Shelf',
  21 + stateOn: 'On Shelf',
  22 + goodsDesc: 'Product Description',
  23 + goodsDescPlaceholder: 'Required, please enter product description',
  24 + content: 'Product Details',
  25 + contentPlaceholder: 'Required, please enter product details'
  26 + },
  27 + uploadImage: {
  28 + fileSizeLimit: 'Image size cannot exceed 2MB',
  29 + uploadFailed: 'Image upload failed'
  30 + }
  31 + },
  32 + zh: {
  33 + addReserveDining: {
  34 + title: '添加就餐商品',
  35 + goodsName: '名称',
  36 + goodsNamePlaceholder: '必填,请填写名称',
  37 + paramsId: '参数',
  38 + paramsIdPlaceholder: '必填,请选择参数',
  39 + price: '单价',
  40 + pricePlaceholder: '必填,请填写单价',
  41 + sort: '排序',
  42 + sortPlaceholder: '必填,请填写排序',
  43 + startDate: '开始时间',
  44 + startDatePlaceholder: '必填,请填写开始时间',
  45 + endDate: '结束时间',
  46 + endDatePlaceholder: '必填,请填写结束时间',
  47 + imgUrl: '产品封面',
  48 + state: '状态',
  49 + statePlaceholder: '必填,请选择状态',
  50 + stateOff: '未上架',
  51 + stateOn: '上架',
  52 + goodsDesc: '商品简介',
  53 + goodsDescPlaceholder: '必填,请填写商品简介',
  54 + content: '商品详情',
  55 + contentPlaceholder: '必填,请输入商品描述'
  56 + },
  57 + uploadImage: {
  58 + fileSizeLimit: '图片大小不能超过2MB',
  59 + uploadFailed: '图片上传失败'
  60 + }
  61 + }
  62 +}
0 63 \ No newline at end of file
... ...
src/views/scm/addReserveDiningList.vue 0 → 100644
  1 +<template>
  2 + <div class="add-reserve-dining-container">
  3 + <el-card class="box-card">
  4 + <div slot="header" class="clearfix">
  5 + <span>{{ $t('addReserveDining.title') }}</span>
  6 + </div>
  7 + <el-form ref="form" :model="addReserveDiningInfo" label-width="120px" label-position="right">
  8 + <el-row :gutter="20">
  9 + <el-col :span="12">
  10 + <el-form-item :label="$t('addReserveDining.goodsName')" prop="goodsName">
  11 + <el-input v-model="addReserveDiningInfo.goodsName"
  12 + :placeholder="$t('addReserveDining.goodsNamePlaceholder')" />
  13 + </el-form-item>
  14 + </el-col>
  15 + <el-col :span="12">
  16 + <el-form-item :label="$t('addReserveDining.paramsId')" prop="paramsId">
  17 + <el-select v-model="addReserveDiningInfo.paramsId"
  18 + :placeholder="$t('addReserveDining.paramsIdPlaceholder')" style="width:100%">
  19 + <el-option v-for="(item, index) in addReserveDiningInfo.reserveParamss" :key="index" :label="item.name"
  20 + :value="item.paramsId" />
  21 + </el-select>
  22 + </el-form-item>
  23 + </el-col>
  24 + </el-row>
  25 +
  26 + <el-row :gutter="20">
  27 + <el-col :span="12">
  28 + <el-form-item :label="$t('addReserveDining.price')" prop="price">
  29 + <el-input v-model="addReserveDiningInfo.price" :placeholder="$t('addReserveDining.pricePlaceholder')" />
  30 + </el-form-item>
  31 + </el-col>
  32 + <el-col :span="12">
  33 + <el-form-item :label="$t('addReserveDining.sort')" prop="sort">
  34 + <el-input v-model="addReserveDiningInfo.sort" :placeholder="$t('addReserveDining.sortPlaceholder')" />
  35 + </el-form-item>
  36 + </el-col>
  37 + </el-row>
  38 +
  39 + <el-row :gutter="20">
  40 + <el-col :span="12">
  41 + <el-form-item :label="$t('addReserveDining.startDate')" prop="startDate">
  42 + <el-date-picker v-model="addReserveDiningInfo.startDate" type="date" value-format="yyyy-MM-dd"
  43 + :placeholder="$t('addReserveDining.startDatePlaceholder')" style="width:100%" />
  44 + </el-form-item>
  45 + </el-col>
  46 + <el-col :span="12">
  47 + <el-form-item :label="$t('addReserveDining.endDate')" prop="endDate">
  48 + <el-date-picker v-model="addReserveDiningInfo.endDate" type="date" value-format="yyyy-MM-dd"
  49 + :placeholder="$t('addReserveDining.endDatePlaceholder')" style="width:100%" />
  50 + </el-form-item>
  51 + </el-col>
  52 + </el-row>
  53 +
  54 + <el-row :gutter="20">
  55 + <el-col :span="12">
  56 + <el-form-item :label="$t('addReserveDining.imgUrl')" prop="imgUrl">
  57 +
  58 + <upload-image-url ref="uploadImage" :limit="1" @notifyUploadCoverImage="handleImageChange" />
  59 +
  60 + </el-form-item>
  61 + </el-col>
  62 + <el-col :span="12">
  63 + <el-form-item :label="$t('addReserveDining.state')" prop="state">
  64 + <el-select v-model="addReserveDiningInfo.state" :placeholder="$t('addReserveDining.statePlaceholder')"
  65 + style="width:100%">
  66 + <el-option :label="$t('addReserveDining.stateOff')" value="1001" />
  67 + <el-option :label="$t('addReserveDining.stateOn')" value="2002" />
  68 + </el-select>
  69 + </el-form-item>
  70 + </el-col>
  71 + </el-row>
  72 +
  73 + <el-row>
  74 + <el-col :span="24">
  75 + <el-form-item :label="$t('addReserveDining.goodsDesc')" prop="goodsDesc">
  76 + <el-input v-model="addReserveDiningInfo.goodsDesc" type="textarea" :rows="3"
  77 + :placeholder="$t('addReserveDining.goodsDescPlaceholder')" />
  78 + </el-form-item>
  79 + </el-col>
  80 + </el-row>
  81 +
  82 + <el-row>
  83 + <el-col :span="24">
  84 + <el-form-item :label="$t('addReserveDining.content')">
  85 + <div class="editor-wrapper">
  86 + <rich-text-editor ref="richTextEditor" v-model="addReserveDiningInfo.content" />
  87 + </div>
  88 + </el-form-item>
  89 + </el-col>
  90 + </el-row>
  91 +
  92 + <el-row>
  93 + <el-col :span="24" class="text-right">
  94 + <el-button type="warning" @click="goBack">
  95 + {{ $t('common.cancel') }}
  96 + </el-button>
  97 + <el-button type="primary" @click="saveReserveDiningInfo">
  98 + {{ $t('common.save') }}
  99 + </el-button>
  100 + </el-col>
  101 + </el-row>
  102 + </el-form>
  103 + </el-card>
  104 + </div>
  105 +</template>
  106 +
  107 +<script>
  108 +import UploadImageUrl from '@/components/upload/UploadImageUrl'
  109 +import { saveReserveGoods, listReserveParams } from '@/api/scm/addReserveDiningApi'
  110 +import { getCommunityId } from '@/api/community/communityApi'
  111 +import RichTextEditor from "@/components/editor/RichTextEditor";
  112 +
  113 +export default {
  114 + name: 'AddReserveDining',
  115 + components: {
  116 + UploadImageUrl,
  117 + RichTextEditor
  118 + },
  119 + data() {
  120 + return {
  121 + addReserveDiningInfo: {
  122 + goodsId: '',
  123 + goodsName: '',
  124 + goodsDesc: '',
  125 + type: '1001',
  126 + paramsId: '',
  127 + price: '',
  128 + sort: '',
  129 + state: '',
  130 + startDate: '',
  131 + endDate: '',
  132 + imgUrl: '',
  133 + catalogId: '',
  134 + content: '',
  135 + reserveParamss: []
  136 + }
  137 + }
  138 + },
  139 + created() {
  140 + this.addReserveDiningInfo.catalogId = this.$route.query.catalogId
  141 + this.listReserveParamss()
  142 + this.initGoodsContent()
  143 + },
  144 + methods: {
  145 + goBack() {
  146 + this.$router.go(-1)
  147 + },
  148 + handleImageChange(images) {
  149 + this.addReserveDiningInfo.imgUrl = images.length > 0 ? images[0] : ''
  150 + },
  151 + async saveReserveDiningInfo() {
  152 + try {
  153 + if (!this.validateForm()) {
  154 + return
  155 + }
  156 +
  157 + this.addReserveDiningInfo.communityId = getCommunityId()
  158 + const response = await saveReserveGoods(this.addReserveDiningInfo)
  159 +
  160 + if (response.code === 0) {
  161 + this.$message.success(this.$t('common.saveSuccess'))
  162 + this.goBack()
  163 + } else {
  164 + this.$message.error(response.msg)
  165 + }
  166 + } catch (error) {
  167 + console.error('保存失败:', error)
  168 + this.$message.error(this.$t('common.saveFailed'))
  169 + }
  170 + },
  171 + validateForm() {
  172 + // 这里应该添加表单验证逻辑
  173 + return true
  174 + },
  175 + async listReserveParamss() {
  176 + try {
  177 + const params = {
  178 + page: 1,
  179 + row: 100,
  180 + communityId: getCommunityId()
  181 + }
  182 + const response = await listReserveParams(params)
  183 + this.addReserveDiningInfo.reserveParamss = response.data
  184 + } catch (error) {
  185 + console.error('获取参数列表失败:', error)
  186 + }
  187 + },
  188 + }
  189 +}
  190 +</script>
  191 +
  192 +<style lang="scss" scoped>
  193 +.add-reserve-dining-container {
  194 + padding: 20px;
  195 +
  196 + .editor-wrapper {
  197 + border: 1px solid #dcdfe6;
  198 + border-radius: 4px;
  199 + }
  200 +
  201 + .text-right {
  202 + text-align: right;
  203 + }
  204 +}
  205 +</style>
0 206 \ No newline at end of file
... ...
src/views/scm/addReserveServiceLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + addReserveService: {
  4 + title: 'Add Service',
  5 + name: 'Name',
  6 + namePlaceholder: 'Required, please enter name',
  7 + params: 'Parameters',
  8 + paramsPlaceholder: 'Required, please select parameters',
  9 + price: 'Service Fee',
  10 + pricePlaceholder: 'Required, please enter service fee',
  11 + sort: 'Sort',
  12 + sortPlaceholder: 'Required, please enter sort order',
  13 + startDate: 'Start Date',
  14 + startDatePlaceholder: 'Required, please select start date',
  15 + endDate: 'End Date',
  16 + endDatePlaceholder: 'Required, please select end date',
  17 + coverImage: 'Service Cover',
  18 + state: 'Status',
  19 + statePlaceholder: 'Required, please select status',
  20 + stateOff: 'Off Shelf',
  21 + stateOn: 'On Shelf',
  22 + goodsDesc: 'Service Description',
  23 + goodsDescPlaceholder: 'Required, please enter service description',
  24 + content: 'Service Details',
  25 + saveSuccess: 'Service saved successfully',
  26 + saveFailed: 'Failed to save service',
  27 + nameRequired: 'Name is required',
  28 + paramsRequired: 'Parameters is required',
  29 + priceRequired: 'Service fee is required',
  30 + sortRequired: 'Sort order is required',
  31 + startDateRequired: 'Start date is required',
  32 + endDateRequired: 'End date is required',
  33 + coverImageRequired: 'Service cover is required',
  34 + stateRequired: 'Status is required',
  35 + goodsDescRequired: 'Service description is required'
  36 + },
  37 + uploadImage: {
  38 + fileSizeLimit: 'Image size cannot exceed 2MB',
  39 + uploadFailed: 'Image upload failed'
  40 + }
  41 + },
  42 + zh: {
  43 + addReserveService: {
  44 + title: '添加服务',
  45 + name: '名称',
  46 + namePlaceholder: '必填,请填写名称',
  47 + params: '参数',
  48 + paramsPlaceholder: '必填,请选择参数',
  49 + price: '上门费',
  50 + pricePlaceholder: '必填,请填写上门费',
  51 + sort: '排序',
  52 + sortPlaceholder: '必填,请填写排序',
  53 + startDate: '开始时间',
  54 + startDatePlaceholder: '必填,请填写开始时间',
  55 + endDate: '结束时间',
  56 + endDatePlaceholder: '必填,请填写结束时间',
  57 + coverImage: '服务封面',
  58 + state: '状态',
  59 + statePlaceholder: '必填,请选择状态',
  60 + stateOff: '未上架',
  61 + stateOn: '上架',
  62 + goodsDesc: '商品简介',
  63 + goodsDescPlaceholder: '必填,请填写商品简介',
  64 + content: '商品详情',
  65 + saveSuccess: '服务保存成功',
  66 + saveFailed: '服务保存失败',
  67 + nameRequired: '名称不能为空',
  68 + paramsRequired: '参数不能为空',
  69 + priceRequired: '上门费不能为空',
  70 + sortRequired: '排序不能为空',
  71 + startDateRequired: '开始时间不能为空',
  72 + endDateRequired: '结束时间不能为空',
  73 + coverImageRequired: '服务封面不能为空',
  74 + stateRequired: '状态不能为空',
  75 + goodsDescRequired: '商品简介不能为空'
  76 + },
  77 + uploadImage: {
  78 + fileSizeLimit: '图片大小不能超过2MB',
  79 + uploadFailed: '图片上传失败'
  80 + }
  81 + }
  82 +}
0 83 \ No newline at end of file
... ...
src/views/scm/addReserveServiceList.vue 0 → 100644
  1 +<template>
  2 + <div class="add-reserve-service-container">
  3 + <el-card class="box-card">
  4 + <div slot="header" class="clearfix">
  5 + <span>{{ $t('addReserveService.title') }}</span>
  6 + </div>
  7 + <el-form ref="form" :model="addReserveServiceInfo" label-width="120px" label-position="right">
  8 + <el-row :gutter="20">
  9 + <el-col :span="12">
  10 + <el-form-item :label="$t('addReserveService.name')" prop="goodsName">
  11 + <el-input v-model="addReserveServiceInfo.goodsName" :placeholder="$t('addReserveService.namePlaceholder')"
  12 + clearable />
  13 + </el-form-item>
  14 + </el-col>
  15 + <el-col :span="12">
  16 + <el-form-item :label="$t('addReserveService.params')" prop="paramsId">
  17 + <el-select v-model="addReserveServiceInfo.paramsId"
  18 + :placeholder="$t('addReserveService.paramsPlaceholder')" style="width:100%">
  19 + <el-option v-for="(item, index) in addReserveServiceInfo.reserveParamss" :key="index" :label="item.name"
  20 + :value="item.paramsId" />
  21 + </el-select>
  22 + </el-form-item>
  23 + </el-col>
  24 + </el-row>
  25 +
  26 + <el-row :gutter="20">
  27 + <el-col :span="12">
  28 + <el-form-item :label="$t('addReserveService.price')" prop="price">
  29 + <el-input v-model="addReserveServiceInfo.price" :placeholder="$t('addReserveService.pricePlaceholder')"
  30 + clearable />
  31 + </el-form-item>
  32 + </el-col>
  33 + <el-col :span="12">
  34 + <el-form-item :label="$t('addReserveService.sort')" prop="sort">
  35 + <el-input v-model="addReserveServiceInfo.sort" :placeholder="$t('addReserveService.sortPlaceholder')"
  36 + clearable />
  37 + </el-form-item>
  38 + </el-col>
  39 + </el-row>
  40 +
  41 + <el-row :gutter="20">
  42 + <el-col :span="12">
  43 + <el-form-item :label="$t('addReserveService.startDate')" prop="startDate">
  44 + <el-date-picker v-model="addReserveServiceInfo.startDate" type="date" value-format="yyyy-MM-dd"
  45 + :placeholder="$t('addReserveService.startDatePlaceholder')" style="width:100%" />
  46 + </el-form-item>
  47 + </el-col>
  48 + <el-col :span="12">
  49 + <el-form-item :label="$t('addReserveService.endDate')" prop="endDate">
  50 + <el-date-picker v-model="addReserveServiceInfo.endDate" type="date" value-format="yyyy-MM-dd"
  51 + :placeholder="$t('addReserveService.endDatePlaceholder')" style="width:100%" />
  52 + </el-form-item>
  53 + </el-col>
  54 + </el-row>
  55 +
  56 + <el-row :gutter="20">
  57 + <el-col :span="12">
  58 + <el-form-item :label="$t('addReserveService.coverImage')" prop="imgUrl">
  59 + <upload-image-url ref="uploadImage" :limit="1" @notifyUploadCoverImage="handleImageChange" />
  60 + </el-form-item>
  61 + </el-col>
  62 + <el-col :span="12">
  63 + <el-form-item :label="$t('addReserveService.state')" prop="state">
  64 + <el-select v-model="addReserveServiceInfo.state" :placeholder="$t('addReserveService.statePlaceholder')"
  65 + style="width:100%">
  66 + <el-option :label="$t('addReserveService.stateOff')" value="1001" />
  67 + <el-option :label="$t('addReserveService.stateOn')" value="2002" />
  68 + </el-select>
  69 + </el-form-item>
  70 + </el-col>
  71 + </el-row>
  72 +
  73 + <el-row>
  74 + <el-col :span="24">
  75 + <el-form-item :label="$t('addReserveService.goodsDesc')" prop="goodsDesc">
  76 + <el-input v-model="addReserveServiceInfo.goodsDesc" type="textarea" :rows="3"
  77 + :placeholder="$t('addReserveService.goodsDescPlaceholder')" />
  78 + </el-form-item>
  79 + </el-col>
  80 + </el-row>
  81 +
  82 + <el-row>
  83 + <el-col :span="24">
  84 + <el-form-item :label="$t('addReserveService.content')">
  85 + <div class="editor-wrapper">
  86 + <rich-text-editor ref="richTextEditor" v-model="addReserveServiceInfo.content" />
  87 + </div>
  88 + </el-form-item>
  89 + </el-col>
  90 + </el-row>
  91 +
  92 + <el-row>
  93 + <el-col :span="24" class="text-right">
  94 + <el-button type="warning" @click="handleCancel">
  95 + {{ $t('common.cancel') }}
  96 + </el-button>
  97 + <el-button type="primary" @click="handleSubmit">
  98 + {{ $t('common.save') }}
  99 + </el-button>
  100 + </el-col>
  101 + </el-row>
  102 + </el-form>
  103 + </el-card>
  104 + </div>
  105 +</template>
  106 +
  107 +<script>
  108 +import { saveReserveGoods, listReserveParams } from '@/api/scm/addReserveServiceApi'
  109 +import UploadImageUrl from '@/components/upload/UploadImageUrl'
  110 +import RichTextEditor from "@/components/editor/RichTextEditor";
  111 +import { getCommunityId } from '@/api/community/communityApi'
  112 +
  113 +export default {
  114 + name: 'AddReserveService',
  115 + components: {
  116 + UploadImageUrl,
  117 + RichTextEditor
  118 + },
  119 + data() {
  120 + return {
  121 + addReserveServiceInfo: {
  122 + goodsId: '',
  123 + goodsName: '',
  124 + goodsDesc: '',
  125 + type: '2002',
  126 + paramsId: '',
  127 + price: '',
  128 + sort: '',
  129 + state: '',
  130 + startDate: '',
  131 + endDate: '',
  132 + imgUrl: '',
  133 + catalogId: '',
  134 + content: '',
  135 + reserveParamss: [],
  136 + communityId: getCommunityId()
  137 + }
  138 + }
  139 + },
  140 + created() {
  141 + this.addReserveServiceInfo.catalogId = this.$route.query.catalogId
  142 + this.loadReserveParams()
  143 + },
  144 + methods: {
  145 + async loadReserveParams() {
  146 + try {
  147 + const params = {
  148 + page: 1,
  149 + row: 100,
  150 + communityId: this.addReserveServiceInfo.communityId
  151 + }
  152 + const { data } = await listReserveParams(params)
  153 + this.addReserveServiceInfo.reserveParamss = data
  154 + } catch (error) {
  155 + console.error('Failed to load reserve params:', error)
  156 + this.$message.error(this.$t('addReserveService.loadParamsFailed'))
  157 + }
  158 + },
  159 + handleImageChange(images) {
  160 + this.addReserveServiceInfo.imgUrl = images.length > 0 ? images[0] : ''
  161 + },
  162 + validateForm() {
  163 + const requiredFields = [
  164 + 'goodsName',
  165 + 'paramsId',
  166 + 'price',
  167 + 'sort',
  168 + 'startDate',
  169 + 'endDate',
  170 + 'imgUrl',
  171 + 'state',
  172 + 'goodsDesc',
  173 + 'content'
  174 + ]
  175 +
  176 + for (const field of requiredFields) {
  177 + if (!this.addReserveServiceInfo[field]) {
  178 + this.$message.error(this.$t(`addReserveService.${field}Required`))
  179 + return false
  180 + }
  181 + }
  182 +
  183 + return true
  184 + },
  185 + async handleSubmit() {
  186 + if (!this.validateForm()) return
  187 +
  188 + try {
  189 + const response = await saveReserveGoods(this.addReserveServiceInfo)
  190 + if (response.code === 0) {
  191 + this.$message.success(this.$t('addReserveService.saveSuccess'))
  192 + this.$router.go(-1)
  193 + } else {
  194 + this.$message.error(response.msg)
  195 + }
  196 + } catch (error) {
  197 + console.error('Failed to save reserve service:', error)
  198 + this.$message.error(this.$t('addReserveService.saveFailed'))
  199 + }
  200 + },
  201 + handleCancel() {
  202 + this.$router.go(-1)
  203 + }
  204 + }
  205 +}
  206 +</script>
  207 +
  208 +<style lang="scss" scoped>
  209 +.add-reserve-service-container {
  210 + padding: 20px;
  211 +
  212 + .box-card {
  213 + margin-bottom: 20px;
  214 + }
  215 +
  216 + .editor-wrapper {
  217 + border: 1px solid #dcdfe6;
  218 + border-radius: 4px;
  219 + }
  220 +
  221 + .text-right {
  222 + text-align: right;
  223 + }
  224 +}
  225 +</style>
0 226 \ No newline at end of file
... ...
src/views/scm/doDiningLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + doDining: {
  4 + selectGoods: 'Select Goods',
  5 + scanQrCode: 'Please scan QR code',
  6 + dining: 'Dining',
  7 + diningRecords: 'Dining Records',
  8 + selectStartTime: 'Select start time',
  9 + selectEndTime: 'Select end time',
  10 + enterOwnerName: 'Enter owner name',
  11 + enterDinerName: 'Enter diner name',
  12 + diningTime: 'Dining Time',
  13 + goods: 'Goods',
  14 + owner: 'Owner',
  15 + diner: 'Diner',
  16 + dinerPhone: 'Diner Phone',
  17 + orderNo: 'Order No',
  18 + remark: 'Remark'
  19 + },
  20 + addReserveDiningPerson: {
  21 + reserveDining: 'Reserve Dining',
  22 + personName: 'Person Name',
  23 + personNamePlaceholder: 'Required, please enter person name',
  24 + personTel: 'Person Tel',
  25 + personTelPlaceholder: 'Required, please enter person tel',
  26 + payWay: 'Pay Way',
  27 + payWayPlaceholder: 'Please select pay way',
  28 + cash: 'Cash',
  29 + wechat: 'WeChat',
  30 + alipay: 'Alipay',
  31 + quantity: 'Quantity',
  32 + quantityPlaceholder: 'Please select quantity',
  33 + unit: 'unit',
  34 + receivableAmount: 'Receivable Amount',
  35 + receivableAmountPlaceholder: 'Required, please enter receivable amount',
  36 + receivedAmount: 'Received Amount',
  37 + receivedAmountPlaceholder: 'Required, please enter received amount',
  38 + appointmentTime: 'Appointment Time',
  39 + appointmentTimePlaceholder: 'Required, please select appointment time',
  40 + openTime: 'Open Time',
  41 + openTimePlaceholder: 'Please select open time',
  42 + hour: 'hour',
  43 + remark: 'Remark',
  44 + remarkPlaceholder: 'Required, please enter remark'
  45 + },
  46 + deleteReserveDining: {
  47 + confirmDelete: 'Confirm to delete reserve dining?'
  48 + }
  49 + },
  50 + zh: {
  51 + doDining: {
  52 + selectGoods: '选择商品',
  53 + scanQrCode: '请用扫码枪扫二维码',
  54 + dining: '就餐',
  55 + diningRecords: '就餐记录',
  56 + selectStartTime: '请选择开始时间',
  57 + selectEndTime: '请选择结束时间',
  58 + enterOwnerName: '请输入业主名称',
  59 + enterDinerName: '请输入就餐人',
  60 + diningTime: '就餐时间',
  61 + goods: '商品',
  62 + owner: '业主',
  63 + diner: '就餐人',
  64 + dinerPhone: '就餐电话',
  65 + orderNo: '订单编号',
  66 + remark: '备注'
  67 + },
  68 + addReserveDiningPerson: {
  69 + reserveDining: '预约就餐',
  70 + personName: '预约人',
  71 + personNamePlaceholder: '必填,请填写预约人',
  72 + personTel: '预约电话',
  73 + personTelPlaceholder: '必填,请填写预约电话',
  74 + payWay: '支付方式',
  75 + payWayPlaceholder: '请选择支付方式',
  76 + cash: '现金',
  77 + wechat: '微信',
  78 + alipay: '支付宝',
  79 + quantity: '预约数量',
  80 + quantityPlaceholder: '请选择预约数量',
  81 + unit: '个',
  82 + receivableAmount: '应收金额',
  83 + receivableAmountPlaceholder: '必填,请填写应收金额',
  84 + receivedAmount: '实收金额',
  85 + receivedAmountPlaceholder: '必填,请填写实收金额',
  86 + appointmentTime: '预约日期',
  87 + appointmentTimePlaceholder: '必填,请选择预约日期',
  88 + openTime: '预约时间',
  89 + openTimePlaceholder: '请选择预约时间',
  90 + hour: '时',
  91 + remark: '备注',
  92 + remarkPlaceholder: '必填,请填写备注'
  93 + },
  94 + deleteReserveDining: {
  95 + confirmDelete: '确定删除预约就餐?'
  96 + }
  97 + }
  98 +}
0 99 \ No newline at end of file
... ...
src/views/scm/doDiningList.vue 0 → 100644
  1 +<template>
  2 + <div class="do-dining-container">
  3 + <el-row :gutter="20">
  4 + <el-col :span="4" class="bg-white">
  5 + <div class="margin-sm">{{ $t('doDining.selectGoods') }}</div>
  6 + <div class="flex justify-start flex-wrap">
  7 + <div v-for="reserveDining in doDiningInfo.reserveDinings" :key="reserveDining.goodsId" class="margin-right-xs margin-bottom-xs">
  8 + <div
  9 + class="vc-border border-radius padding-xs cursor-pointer"
  10 + :class="{'vc-reserve-active': doDiningInfo.goodsId == reserveDining.goodsId}"
  11 + @click="_chooseDining(reserveDining)"
  12 + >
  13 + <div>
  14 + <el-image
  15 + style="width: 60px; height: 60px; border-radius: 5px;"
  16 + :src="reserveDining.imgUrl || '/img/noPhoto.jpg'"
  17 + fit="cover"
  18 + ></el-image>
  19 + </div>
  20 + <div class="text-center margin-top-xs">
  21 + {{ reserveDining.goodsName }}
  22 + </div>
  23 + </div>
  24 + </div>
  25 + </div>
  26 + </el-col>
  27 + <el-col :span="20">
  28 + <el-row :gutter="20">
  29 + <el-col :span="6"></el-col>
  30 + <el-col :span="12">
  31 + <el-input
  32 + v-model="doDiningInfo.qrCode"
  33 + :placeholder="$t('doDining.scanQrCode')"
  34 + @keyup.enter.native="_doDining()"
  35 + id="qrCode"
  36 + ></el-input>
  37 + </el-col>
  38 + <el-col :span="6">
  39 + <el-button type="primary" @click="_doDining()" style="width:100%">
  40 + {{ $t('doDining.dining') }}
  41 + </el-button>
  42 + </el-col>
  43 + </el-row>
  44 +
  45 + <el-row class="margin-top">
  46 + <el-col :span="24">
  47 + <el-card>
  48 + <div slot="header" class="clearfix">
  49 + <span>{{ $t('doDining.diningRecords') }}</span>
  50 + </div>
  51 + <el-row :gutter="20">
  52 + <el-col :span="4">
  53 + <el-date-picker
  54 + v-model="doDiningInfo.conditions.startDate"
  55 + type="datetime"
  56 + :placeholder="$t('doDining.selectStartTime')"
  57 + style="width:100%"
  58 + ></el-date-picker>
  59 + </el-col>
  60 + <el-col :span="4">
  61 + <el-date-picker
  62 + v-model="doDiningInfo.conditions.endDate"
  63 + type="datetime"
  64 + :placeholder="$t('doDining.selectEndTime')"
  65 + style="width:100%"
  66 + ></el-date-picker>
  67 + </el-col>
  68 + <el-col :span="4">
  69 + <el-input
  70 + v-model="doDiningInfo.conditions.nameLike"
  71 + :placeholder="$t('doDining.enterOwnerName')"
  72 + ></el-input>
  73 + </el-col>
  74 + <el-col :span="4">
  75 + <el-input
  76 + v-model="doDiningInfo.conditions.dinerName"
  77 + :placeholder="$t('doDining.enterDinerName')"
  78 + ></el-input>
  79 + </el-col>
  80 + <el-col :span="4">
  81 + <el-button type="primary" @click="_queryData()">
  82 + <i class="el-icon-search"></i>
  83 + {{ $t('common.search') }}
  84 + </el-button>
  85 + <el-button @click="_exportExcel()">
  86 + <i class="el-icon-download"></i>
  87 + {{ $t('common.export') }}
  88 + </el-button>
  89 + </el-col>
  90 + </el-row>
  91 +
  92 + <el-table
  93 + :data="doDiningInfo.orders"
  94 + style="width: 100%"
  95 + border
  96 + class="margin-top"
  97 + >
  98 + <el-table-column
  99 + prop="createTime"
  100 + :label="$t('doDining.diningTime')"
  101 + align="center"
  102 + ></el-table-column>
  103 + <el-table-column
  104 + prop="goodsName"
  105 + :label="$t('doDining.goods')"
  106 + align="center"
  107 + ></el-table-column>
  108 + <el-table-column
  109 + prop="ownerName"
  110 + :label="$t('doDining.owner')"
  111 + align="center"
  112 + ></el-table-column>
  113 + <el-table-column
  114 + prop="personName"
  115 + :label="$t('doDining.diner')"
  116 + align="center"
  117 + ></el-table-column>
  118 + <el-table-column
  119 + prop="personTel"
  120 + :label="$t('doDining.dinerPhone')"
  121 + align="center"
  122 + ></el-table-column>
  123 + <el-table-column
  124 + prop="orderId"
  125 + :label="$t('doDining.orderNo')"
  126 + align="center"
  127 + ></el-table-column>
  128 + <el-table-column
  129 + prop="remark"
  130 + :label="$t('doDining.remark')"
  131 + align="center"
  132 + ></el-table-column>
  133 + </el-table>
  134 +
  135 + <el-pagination
  136 + :current-page.sync="page.current"
  137 + :page-sizes="[10, 20, 30, 50]"
  138 + :page-size="page.size"
  139 + :total="page.total"
  140 + layout="total, sizes, prev, pager, next, jumper"
  141 + @size-change="handleSizeChange"
  142 + @current-change="handleCurrentChange"
  143 + class="margin-top"
  144 + ></el-pagination>
  145 + </el-card>
  146 + </el-col>
  147 + </el-row>
  148 + </el-col>
  149 + </el-row>
  150 +
  151 + <add-reserve-dining-person ref="addReserveDiningPerson"></add-reserve-dining-person>
  152 + <delete-reserve-dining ref="deleteReserveDining"></delete-reserve-dining>
  153 + </div>
  154 +</template>
  155 +
  156 +<script>
  157 +import { getCommunityId } from '@/api/community/communityApi'
  158 +import {
  159 + listReserveGoods,
  160 + queryOwnerDining,
  161 + exportData,
  162 + doDining
  163 +} from '@/api/scm/doDiningApi'
  164 +import AddReserveDiningPerson from '@/components/scm/addReserveDiningPerson'
  165 +import DeleteReserveDining from '@/components/scm/deleteReserveDining'
  166 +
  167 +export default {
  168 + name: 'DoDiningList',
  169 + components: {
  170 + AddReserveDiningPerson,
  171 + DeleteReserveDining
  172 + },
  173 + data() {
  174 + return {
  175 + communityId: '',
  176 + doDiningInfo: {
  177 + reserveDinings: [],
  178 + orders: [],
  179 + total: 0,
  180 + records: 1,
  181 + goodsId: '',
  182 + moreCondition: false,
  183 + qrCode: '',
  184 + conditions: {
  185 + goodsName: '',
  186 + startDate: '',
  187 + endDate: '',
  188 + ownerName: '',
  189 + dinerName: '',
  190 + communityId: ''
  191 + }
  192 + },
  193 + page: {
  194 + current: 1,
  195 + size: 10,
  196 + total: 0
  197 + },
  198 + focusInterval: null
  199 + }
  200 + },
  201 + created() {
  202 + this.communityId = getCommunityId()
  203 + this.doDiningInfo.conditions.communityId = this.communityId
  204 + this._listReserveDinings(1, 200)
  205 + this._listReserveConfirms(this.page.current, this.page.size)
  206 + },
  207 + mounted() {
  208 + document.getElementById("qrCode").focus()
  209 + this.focusInterval = setInterval(() => {
  210 + document.getElementById("qrCode").focus()
  211 + }, 5000)
  212 + },
  213 + beforeDestroy() {
  214 + if (this.focusInterval) {
  215 + clearInterval(this.focusInterval)
  216 + }
  217 + },
  218 + methods: {
  219 + _listReserveDinings(_page, _rows) {
  220 + const params = {
  221 + page: _page,
  222 + row: _rows,
  223 + communityId: this.communityId
  224 + }
  225 + listReserveGoods(params)
  226 + .then(response => {
  227 + this.doDiningInfo.reserveDinings = response.data
  228 + })
  229 + .catch(error => {
  230 + console.error('请求失败:', error)
  231 + })
  232 + },
  233 + _chooseDining(_dining) {
  234 + this.doDiningInfo.goodsId = _dining.goodsId
  235 + document.getElementById("qrCode").focus()
  236 + },
  237 + _doDining() {
  238 + const data = {
  239 + communityId: this.communityId,
  240 + goodsId: this.doDiningInfo.goodsId,
  241 + qrCode: this.doDiningInfo.qrCode
  242 + }
  243 +
  244 + doDining(data)
  245 + .then(response => {
  246 + this.doDiningInfo.qrCode = ''
  247 + if (response.code !== 0) {
  248 + this.$message.error(response.msg)
  249 + return
  250 + }
  251 + this._listReserveConfirms(this.page.current, this.page.size)
  252 + })
  253 + .catch(error => {
  254 + console.error('请求失败:', error)
  255 + this.doDiningInfo.qrCode = ''
  256 + })
  257 + },
  258 + _listReserveConfirms(_page, _rows) {
  259 + const params = {
  260 + page: _page,
  261 + row: _rows,
  262 + ...this.doDiningInfo.conditions
  263 + }
  264 + queryOwnerDining(params)
  265 + .then(response => {
  266 + this.doDiningInfo.total = response.total
  267 + this.doDiningInfo.records = response.records
  268 + this.doDiningInfo.orders = response.data
  269 + this.page.total = response.records
  270 + })
  271 + .catch(error => {
  272 + console.error('请求失败:', error)
  273 + })
  274 + },
  275 + _queryData() {
  276 + this.page.current = 1
  277 + this._listReserveConfirms(this.page.current, this.page.size)
  278 + },
  279 + _exportExcel() {
  280 + const params = {
  281 + ...this.doDiningInfo.conditions,
  282 + pagePath: 'doDining'
  283 + }
  284 + exportData(params)
  285 + .then(response => {
  286 + if (response.code === 0) {
  287 + this.$router.push('/pages/property/downloadTempFile?tab=下载中心')
  288 + }
  289 + })
  290 + .catch(error => {
  291 + console.error('请求失败:', error)
  292 + })
  293 + },
  294 + handleSizeChange(val) {
  295 + this.page.size = val
  296 + this._listReserveConfirms(this.page.current, val)
  297 + },
  298 + handleCurrentChange(val) {
  299 + this.page.current = val
  300 + this._listReserveConfirms(val, this.page.size)
  301 + }
  302 + }
  303 +}
  304 +</script>
  305 +
  306 +<style lang="scss" scoped>
  307 +.do-dining-container {
  308 + padding: 20px;
  309 + .vc-reserve-active {
  310 + border: 1px solid #409EFF;
  311 + background-color: #f5f7fa;
  312 + }
  313 + .margin-sm {
  314 + margin: 10px 0;
  315 + }
  316 + .margin-top {
  317 + margin-top: 20px;
  318 + }
  319 + .margin-right-xs {
  320 + margin-right: 5px;
  321 + }
  322 + .margin-bottom-xs {
  323 + margin-bottom: 5px;
  324 + }
  325 + .padding-xs {
  326 + padding: 5px;
  327 + }
  328 + .border-radius {
  329 + border-radius: 4px;
  330 + }
  331 + .vc-border {
  332 + border: 1px solid #ebeef5;
  333 + }
  334 + .text-center {
  335 + text-align: center;
  336 + }
  337 + .flex {
  338 + display: flex;
  339 + }
  340 + .justify-start {
  341 + justify-content: flex-start;
  342 + }
  343 + .flex-wrap {
  344 + flex-wrap: wrap;
  345 + }
  346 + .bg-white {
  347 + background-color: #fff;
  348 + padding: 10px;
  349 + border-radius: 4px;
  350 + }
  351 + .cursor-pointer {
  352 + cursor: pointer;
  353 + }
  354 +}
  355 +</style>
0 356 \ No newline at end of file
... ...
src/views/scm/editReserveDiningLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + editReserveDining: {
  4 + title: 'Edit Dining Product',
  5 + goodsName: 'Name',
  6 + requiredGoodsName: 'Required, please enter name',
  7 + params: 'Parameters',
  8 + requiredParams: 'Required, please select parameters',
  9 + price: 'Price',
  10 + requiredPrice: 'Required, please enter price',
  11 + sort: 'Sort',
  12 + requiredSort: 'Required, please enter sort',
  13 + startDate: 'Start Date',
  14 + requiredStartDate: 'Required, please select start date',
  15 + endDate: 'End Date',
  16 + requiredEndDate: 'Required, please select end date',
  17 + coverImage: 'Product Cover',
  18 + state: 'Status',
  19 + requiredState: 'Required, please select status',
  20 + stateNotOnShelf: 'Not On Shelf',
  21 + stateOnShelf: 'On Shelf',
  22 + goodsDesc: 'Product Description',
  23 + requiredGoodsDesc: 'Required, please enter product description',
  24 + content: 'Product Details',
  25 + requiredContent: 'Required, please enter product details',
  26 + validate: {
  27 + goodsName: 'Name cannot be empty',
  28 + paramsId: 'Please select parameters',
  29 + price: 'Price cannot be empty',
  30 + sort: 'Sort cannot be empty',
  31 + startDate: 'Please select start date',
  32 + endDate: 'Please select end date',
  33 + imgUrl: 'Please upload product cover',
  34 + state: 'Please select status',
  35 + goodsDesc: 'Product description cannot be empty',
  36 + content: 'Product details cannot be empty'
  37 + },
  38 + fetchParamsError: 'Failed to get parameters',
  39 + fetchGoodsError: 'Failed to get product information'
  40 + },
  41 + uploadImage: {
  42 + validate: {
  43 + size: 'Image size cannot exceed 2MB'
  44 + },
  45 + uploadError: 'Image upload failed'
  46 + }
  47 + },
  48 + zh: {
  49 + editReserveDining: {
  50 + title: '编辑就餐商品',
  51 + goodsName: '名称',
  52 + requiredGoodsName: '必填,请填写名称',
  53 + params: '参数',
  54 + requiredParams: '必填,请选择参数',
  55 + price: '单价',
  56 + requiredPrice: '必填,请填写单价',
  57 + sort: '排序',
  58 + requiredSort: '必填,请填写排序',
  59 + startDate: '开始时间',
  60 + requiredStartDate: '必填,请填写开始时间',
  61 + endDate: '结束时间',
  62 + requiredEndDate: '必填,请填写结束时间',
  63 + coverImage: '产品封面',
  64 + state: '状态',
  65 + requiredState: '必填,请选择状态',
  66 + stateNotOnShelf: '未上架',
  67 + stateOnShelf: '上架',
  68 + goodsDesc: '商品简介',
  69 + requiredGoodsDesc: '必填,请填写商品简介',
  70 + content: '商品详情',
  71 + requiredContent: '必填,请输入商品详情',
  72 + validate: {
  73 + goodsName: '名称不能为空',
  74 + paramsId: '请选择参数',
  75 + price: '单价不能为空',
  76 + sort: '排序不能为空',
  77 + startDate: '请选择开始时间',
  78 + endDate: '请选择结束时间',
  79 + imgUrl: '请上传产品封面',
  80 + state: '请选择状态',
  81 + goodsDesc: '商品简介不能为空',
  82 + content: '商品详情不能为空'
  83 + },
  84 + fetchParamsError: '获取参数失败',
  85 + fetchGoodsError: '获取商品信息失败'
  86 + },
  87 + uploadImage: {
  88 + validate: {
  89 + size: '图片大小不能超过2MB'
  90 + },
  91 + uploadError: '图片上传失败'
  92 + }
  93 + }
  94 +}
0 95 \ No newline at end of file
... ...
src/views/scm/editReserveDiningList.vue 0 → 100644
  1 +<template>
  2 + <div class="edit-reserve-dining-container">
  3 + <el-card>
  4 + <div slot="header" class="clearfix">
  5 + <span>{{ $t('editReserveDining.title') }}</span>
  6 + </div>
  7 +
  8 + <el-row :gutter="20">
  9 + <el-col :span="24">
  10 + <el-form label-width="120px" label-position="right">
  11 + <el-row :gutter="20">
  12 + <el-col :span="12">
  13 + <el-form-item :label="$t('editReserveDining.goodsName')">
  14 + <el-input v-model="editReserveDiningInfo.goodsName"
  15 + :placeholder="$t('editReserveDining.requiredGoodsName')" />
  16 + </el-form-item>
  17 + </el-col>
  18 + <el-col :span="12">
  19 + <el-form-item :label="$t('editReserveDining.params')">
  20 + <el-select v-model="editReserveDiningInfo.paramsId" style="width:100%"
  21 + :placeholder="$t('editReserveDining.requiredParams')">
  22 + <el-option v-for="(item, index) in editReserveDiningInfo.reserveParamss" :key="index"
  23 + :label="item.name" :value="item.paramsId" />
  24 + </el-select>
  25 + </el-form-item>
  26 + </el-col>
  27 + </el-row>
  28 +
  29 + <el-row :gutter="20">
  30 + <el-col :span="12">
  31 + <el-form-item :label="$t('editReserveDining.price')">
  32 + <el-input v-model="editReserveDiningInfo.price"
  33 + :placeholder="$t('editReserveDining.requiredPrice')" />
  34 + </el-form-item>
  35 + </el-col>
  36 + <el-col :span="12">
  37 + <el-form-item :label="$t('editReserveDining.sort')">
  38 + <el-input v-model="editReserveDiningInfo.sort" :placeholder="$t('editReserveDining.requiredSort')" />
  39 + </el-form-item>
  40 + </el-col>
  41 + </el-row>
  42 +
  43 + <el-row :gutter="20">
  44 + <el-col :span="12">
  45 + <el-form-item :label="$t('editReserveDining.startDate')">
  46 + <el-date-picker v-model="editReserveDiningInfo.startDate" type="datetime" style="width:100%"
  47 + :placeholder="$t('editReserveDining.requiredStartDate')" />
  48 + </el-form-item>
  49 + </el-col>
  50 + <el-col :span="12">
  51 + <el-form-item :label="$t('editReserveDining.endDate')">
  52 + <el-date-picker v-model="editReserveDiningInfo.endDate" type="datetime" style="width:100%"
  53 + :placeholder="$t('editReserveDining.requiredEndDate')" />
  54 + </el-form-item>
  55 + </el-col>
  56 + </el-row>
  57 +
  58 + <el-row :gutter="20">
  59 + <el-col :span="12">
  60 + <el-form-item :label="$t('editReserveDining.coverImage')">
  61 + <upload-image-url ref="uploadImage" :limit="1"
  62 + :default-images="[editReserveDiningInfo.imgUrl]"
  63 + @notifyUploadCoverImage="handleImageChange" />
  64 + </el-form-item>
  65 + </el-col>
  66 + <el-col :span="12">
  67 + <el-form-item :label="$t('editReserveDining.state')">
  68 + <el-select v-model="editReserveDiningInfo.state" style="width:100%"
  69 + :placeholder="$t('editReserveDining.requiredState')">
  70 + <el-option :label="$t('editReserveDining.stateNotOnShelf')" value="1001" />
  71 + <el-option :label="$t('editReserveDining.stateOnShelf')" value="2002" />
  72 + </el-select>
  73 + </el-form-item>
  74 + </el-col>
  75 + </el-row>
  76 +
  77 + <el-row :gutter="20">
  78 + <el-col :span="24">
  79 + <el-form-item :label="$t('editReserveDining.goodsDesc')">
  80 + <el-input v-model="editReserveDiningInfo.goodsDesc" type="textarea" :rows="3"
  81 + :placeholder="$t('editReserveDining.requiredGoodsDesc')" />
  82 + </el-form-item>
  83 + </el-col>
  84 + </el-row>
  85 +
  86 + <el-row :gutter="20">
  87 + <el-col :span="24">
  88 + <el-form-item :label="$t('editReserveDining.content')">
  89 + <div class="editor-wrapper">
  90 + <rich-text-editor ref="richTextEditor" v-model="editReserveDiningInfo.content" />
  91 + </div>
  92 + </el-form-item>
  93 + </el-col>
  94 + </el-row>
  95 +
  96 + <el-row :gutter="20">
  97 + <el-col :span="24" class="text-right">
  98 + <el-button type="warning" @click="handleCancel">
  99 + {{ $t('common.cancel') }}
  100 + </el-button>
  101 + <el-button type="primary" @click="saveReserveDiningInfo">
  102 + {{ $t('common.save') }}
  103 + </el-button>
  104 + </el-col>
  105 + </el-row>
  106 + </el-form>
  107 + </el-col>
  108 + </el-row>
  109 + </el-card>
  110 + </div>
  111 +</template>
  112 +
  113 +<script>
  114 +import UploadImageUrl from '@/components/upload/UploadImageUrl'
  115 +import RichTextEditor from "@/components/editor/RichTextEditor";
  116 +import { updateReserveGoods, listReserveParams, listReserveGoods } from '@/api/scm/editReserveDiningApi'
  117 +import { getCommunityId } from '@/api/community/communityApi'
  118 +
  119 +export default {
  120 + name: 'EditReserveDining',
  121 + components: {
  122 + UploadImageUrl,
  123 + RichTextEditor
  124 + },
  125 + data() {
  126 + return {
  127 + editReserveDiningInfo: {
  128 + goodsId: '',
  129 + goodsName: '',
  130 + goodsDesc: '',
  131 + type: '1001',
  132 + paramsId: '',
  133 + price: '',
  134 + sort: '',
  135 + state: '',
  136 + startDate: '',
  137 + endDate: '',
  138 + imgUrl: '',
  139 + catalogId: '',
  140 + content: '',
  141 + reserveParamss: [],
  142 + communityId: getCommunityId()
  143 + }
  144 + }
  145 + },
  146 + created() {
  147 + this.editReserveDiningInfo.goodsId = this.$route.query.goodsId
  148 + this.listReserveParamss()
  149 + this.listReserveDinings()
  150 + },
  151 + methods: {
  152 + handleImageChange(images) {
  153 + this.editReserveDiningInfo.imgUrl = images.length > 0 ? images[0] : ''
  154 + },
  155 + validateForm() {
  156 + if (!this.editReserveDiningInfo.goodsName) {
  157 + this.$message.error(this.$t('editReserveDining.validate.goodsName'))
  158 + return false
  159 + }
  160 + if (!this.editReserveDiningInfo.paramsId) {
  161 + this.$message.error(this.$t('editReserveDining.validate.paramsId'))
  162 + return false
  163 + }
  164 + if (!this.editReserveDiningInfo.price) {
  165 + this.$message.error(this.$t('editReserveDining.validate.price'))
  166 + return false
  167 + }
  168 + if (!this.editReserveDiningInfo.sort) {
  169 + this.$message.error(this.$t('editReserveDining.validate.sort'))
  170 + return false
  171 + }
  172 + if (!this.editReserveDiningInfo.startDate) {
  173 + this.$message.error(this.$t('editReserveDining.validate.startDate'))
  174 + return false
  175 + }
  176 + if (!this.editReserveDiningInfo.endDate) {
  177 + this.$message.error(this.$t('editReserveDining.validate.endDate'))
  178 + return false
  179 + }
  180 + if (!this.editReserveDiningInfo.imgUrl) {
  181 + this.$message.error(this.$t('editReserveDining.validate.imgUrl'))
  182 + return false
  183 + }
  184 + if (!this.editReserveDiningInfo.state) {
  185 + this.$message.error(this.$t('editReserveDining.validate.state'))
  186 + return false
  187 + }
  188 + if (!this.editReserveDiningInfo.goodsDesc) {
  189 + this.$message.error(this.$t('editReserveDining.validate.goodsDesc'))
  190 + return false
  191 + }
  192 + if (!this.editReserveDiningInfo.content) {
  193 + this.$message.error(this.$t('editReserveDining.validate.content'))
  194 + return false
  195 + }
  196 + return true
  197 + },
  198 + async saveReserveDiningInfo() {
  199 + if (!this.validateForm()) {
  200 + return
  201 + }
  202 +
  203 + try {
  204 + const res = await updateReserveGoods(this.editReserveDiningInfo)
  205 + if (res.code === 0) {
  206 + this.$message.success(this.$t('common.saveSuccess'))
  207 + this.$router.go(-1)
  208 + } else {
  209 + this.$message.error(res.msg)
  210 + }
  211 + } catch (error) {
  212 + this.$message.error(this.$t('common.saveError'))
  213 + }
  214 + },
  215 + async listReserveParamss() {
  216 + try {
  217 + const params = {
  218 + page: 1,
  219 + row: 100,
  220 + communityId: this.editReserveDiningInfo.communityId
  221 + }
  222 + const res = await listReserveParams(params)
  223 + this.editReserveDiningInfo.reserveParamss = res.data
  224 + } catch (error) {
  225 + this.$message.error(this.$t('editReserveDining.fetchParamsError'))
  226 + }
  227 + },
  228 + async listReserveDinings() {
  229 + try {
  230 + const params = {
  231 + page: 1,
  232 + row: 1,
  233 + goodsId: this.editReserveDiningInfo.goodsId,
  234 + communityId: this.editReserveDiningInfo.communityId
  235 + }
  236 + const res = await listReserveGoods(params)
  237 + if (res.data && res.data.length > 0) {
  238 + Object.assign(this.editReserveDiningInfo, res.data[0])
  239 + this.$refs.richTextEditor.setContent(this.editReserveDiningInfo.content)
  240 + this.$refs.uploadImage.setImages([this.editReserveDiningInfo.imgUrl])
  241 + }
  242 + } catch (error) {
  243 + this.$message.error(this.$t('editReserveDining.fetchGoodsError'))
  244 + }
  245 + },
  246 + handleCancel() {
  247 + this.$router.go(-1)
  248 + }
  249 + }
  250 +}
  251 +</script>
  252 +
  253 +<style lang="scss" scoped>
  254 +.edit-reserve-dining-container {
  255 + padding: 20px;
  256 +
  257 + .el-card {
  258 + margin-bottom: 20px;
  259 + }
  260 +
  261 + .text-right {
  262 + text-align: right;
  263 + }
  264 +
  265 + .editor-wrapper {
  266 + border: 1px solid #dcdfe6;
  267 + border-radius: 4px;
  268 + }
  269 +}
  270 +</style>
0 271 \ No newline at end of file
... ...
src/views/scm/editReserveServiceLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + editReserveService: {
  4 + title: 'Edit Service',
  5 + goodsName: 'Name',
  6 + goodsNamePlaceholder: 'Required, please enter name',
  7 + params: 'Parameters',
  8 + paramsPlaceholder: 'Required, please select parameters',
  9 + price: 'Service Fee',
  10 + pricePlaceholder: 'Required, please enter service fee',
  11 + sort: 'Sort',
  12 + sortPlaceholder: 'Required, please enter sort',
  13 + state: 'Status',
  14 + statePlaceholder: 'Required, please select status',
  15 + stateOff: 'Off Shelf',
  16 + stateOn: 'On Shelf',
  17 + startDate: 'Start Date',
  18 + startDatePlaceholder: 'Required, please select start date',
  19 + endDate: 'End Date',
  20 + endDatePlaceholder: 'Required, please select end date',
  21 + imgUrl: 'Cover Image',
  22 + goodsDesc: 'Description',
  23 + goodsDescPlaceholder: 'Required, please enter description',
  24 + content: 'Content',
  25 + contentPlaceholder: 'Required, please enter content'
  26 + },
  27 + uploadImage: {
  28 + sizeLimit: 'Image size cannot exceed 2MB',
  29 + uploadError: 'Upload failed'
  30 + }
  31 + },
  32 + zh: {
  33 + editReserveService: {
  34 + title: '编辑服务',
  35 + goodsName: '名称',
  36 + goodsNamePlaceholder: '必填,请填写名称',
  37 + params: '参数',
  38 + paramsPlaceholder: '必填,请选择参数',
  39 + price: '上门费',
  40 + pricePlaceholder: '必填,请填写上门费',
  41 + sort: '排序',
  42 + sortPlaceholder: '必填,请填写排序',
  43 + state: '状态',
  44 + statePlaceholder: '必填,请选择状态',
  45 + stateOff: '未上架',
  46 + stateOn: '上架',
  47 + startDate: '开始时间',
  48 + startDatePlaceholder: '必填,请填写开始时间',
  49 + endDate: '结束时间',
  50 + endDatePlaceholder: '必填,请填写结束时间',
  51 + imgUrl: '产品封面',
  52 + goodsDesc: '商品简介',
  53 + goodsDescPlaceholder: '必填,请填写商品简介',
  54 + content: '商品详情',
  55 + contentPlaceholder: '必填,请输入商品描述'
  56 + },
  57 + uploadImage: {
  58 + sizeLimit: '图片大小不能超过2MB',
  59 + uploadError: '上传失败'
  60 + }
  61 + }
  62 +}
0 63 \ No newline at end of file
... ...
src/views/scm/editReserveServiceList.vue 0 → 100644
  1 +<template>
  2 + <div class="edit-reserve-service-container">
  3 + <el-card class="box-card">
  4 + <div slot="header" class="clearfix">
  5 + <span>{{ $t('editReserveService.title') }}</span>
  6 + </div>
  7 +
  8 + <el-form ref="form" :model="editReserveServiceInfo" label-width="120px" label-position="right">
  9 + <el-row :gutter="20">
  10 + <el-col :span="24">
  11 + <el-form-item :label="$t('editReserveService.goodsName')" prop="goodsName">
  12 + <el-input
  13 + v-model="editReserveServiceInfo.goodsName"
  14 + :placeholder="$t('editReserveService.goodsNamePlaceholder')"
  15 + clearable
  16 + />
  17 + </el-form-item>
  18 + </el-col>
  19 + </el-row>
  20 +
  21 + <el-row :gutter="20">
  22 + <el-col :span="12">
  23 + <el-form-item :label="$t('editReserveService.params')" prop="paramsId">
  24 + <el-select
  25 + v-model="editReserveServiceInfo.paramsId"
  26 + :placeholder="$t('editReserveService.paramsPlaceholder')"
  27 + style="width:100%"
  28 + >
  29 + <el-option
  30 + v-for="(item,index) in editReserveServiceInfo.reserveParamss"
  31 + :key="index"
  32 + :label="item.name"
  33 + :value="item.paramsId"
  34 + />
  35 + </el-select>
  36 + </el-form-item>
  37 + </el-col>
  38 + <el-col :span="12">
  39 + <el-form-item :label="$t('editReserveService.price')" prop="price">
  40 + <el-input
  41 + v-model="editReserveServiceInfo.price"
  42 + :placeholder="$t('editReserveService.pricePlaceholder')"
  43 + clearable
  44 + />
  45 + </el-form-item>
  46 + </el-col>
  47 + </el-row>
  48 +
  49 + <el-row :gutter="20">
  50 + <el-col :span="12">
  51 + <el-form-item :label="$t('editReserveService.sort')" prop="sort">
  52 + <el-input
  53 + v-model="editReserveServiceInfo.sort"
  54 + :placeholder="$t('editReserveService.sortPlaceholder')"
  55 + clearable
  56 + />
  57 + </el-form-item>
  58 + </el-col>
  59 + <el-col :span="12">
  60 + <el-form-item :label="$t('editReserveService.state')" prop="state">
  61 + <el-select
  62 + v-model="editReserveServiceInfo.state"
  63 + :placeholder="$t('editReserveService.statePlaceholder')"
  64 + style="width:100%"
  65 + >
  66 + <el-option
  67 + :label="$t('editReserveService.stateOff')"
  68 + value="1001"
  69 + />
  70 + <el-option
  71 + :label="$t('editReserveService.stateOn')"
  72 + value="2002"
  73 + />
  74 + </el-select>
  75 + </el-form-item>
  76 + </el-col>
  77 + </el-row>
  78 +
  79 + <el-row :gutter="20">
  80 + <el-col :span="12">
  81 + <el-form-item :label="$t('editReserveService.startDate')" prop="startDate">
  82 + <el-date-picker
  83 + v-model="editReserveServiceInfo.startDate"
  84 + type="datetime"
  85 + :placeholder="$t('editReserveService.startDatePlaceholder')"
  86 + style="width:100%"
  87 + />
  88 + </el-form-item>
  89 + </el-col>
  90 + <el-col :span="12">
  91 + <el-form-item :label="$t('editReserveService.endDate')" prop="endDate">
  92 + <el-date-picker
  93 + v-model="editReserveServiceInfo.endDate"
  94 + type="datetime"
  95 + :placeholder="$t('editReserveService.endDatePlaceholder')"
  96 + style="width:100%"
  97 + />
  98 + </el-form-item>
  99 + </el-col>
  100 + </el-row>
  101 +
  102 + <el-row :gutter="20">
  103 + <el-col :span="12">
  104 + <el-form-item :label="$t('editReserveService.imgUrl')" prop="imgUrl">
  105 + <upload-image-url
  106 + ref="uploadImage"
  107 + :limit="1"
  108 + :default-images="[editReserveServiceInfo.imgUrl]"
  109 + @notifyUploadCoverImage="handleImageChange"
  110 + />
  111 + </el-form-item>
  112 + </el-col>
  113 + </el-row>
  114 +
  115 + <el-row :gutter="20">
  116 + <el-col :span="24">
  117 + <el-form-item :label="$t('editReserveService.goodsDesc')" prop="goodsDesc">
  118 + <el-input
  119 + v-model="editReserveServiceInfo.goodsDesc"
  120 + type="textarea"
  121 + :placeholder="$t('editReserveService.goodsDescPlaceholder')"
  122 + :rows="3"
  123 + />
  124 + </el-form-item>
  125 + </el-col>
  126 + </el-row>
  127 +
  128 + <el-row :gutter="20">
  129 + <el-col :span="24">
  130 + <el-form-item :label="$t('editReserveService.content')">
  131 + <div class="editor-wrapper">
  132 + <rich-text-editor ref="richTextEditor" v-model="editReserveServiceInfo.content" />
  133 + </div>
  134 + </el-form-item>
  135 + </el-col>
  136 + </el-row>
  137 +
  138 + <el-row :gutter="20">
  139 + <el-col :span="24" class="text-right">
  140 + <el-button type="warning" @click="handleCancel">
  141 + {{ $t('common.cancel') }}
  142 + </el-button>
  143 + <el-button type="primary" @click="handleSave">
  144 + {{ $t('common.save') }}
  145 + </el-button>
  146 + </el-col>
  147 + </el-row>
  148 + </el-form>
  149 + </el-card>
  150 + </div>
  151 +</template>
  152 +
  153 +<script>
  154 +import UploadImageUrl from '@/components/upload/UploadImageUrl'
  155 +import RichTextEditor from "@/components/editor/RichTextEditor";
  156 +import { updateReserveGoods, listReserveParams, listReserveGoods } from '@/api/scm/editReserveServiceApi'
  157 +import { getCommunityId } from '@/api/community/communityApi'
  158 +
  159 +export default {
  160 + name: 'EditReserveServiceList',
  161 + components: {
  162 + UploadImageUrl,
  163 + RichTextEditor
  164 + },
  165 + data() {
  166 + return {
  167 + editReserveServiceInfo: {
  168 + goodsId: '',
  169 + goodsName: '',
  170 + goodsDesc: '',
  171 + type: '1001',
  172 + paramsId: '',
  173 + price: '',
  174 + sort: '',
  175 + state: '',
  176 + startDate: '',
  177 + endDate: '',
  178 + imgUrl: '',
  179 + catalogId: '',
  180 + content: '',
  181 + reserveParamss: []
  182 + },
  183 + communityId: ''
  184 + }
  185 + },
  186 + created() {
  187 + this.communityId = getCommunityId()
  188 + this.editReserveServiceInfo.goodsId = this.$route.query.goodsId
  189 + this.listReserveParamss()
  190 + this.listReserveServices()
  191 + },
  192 + methods: {
  193 + handleImageChange(images) {
  194 + this.editReserveServiceInfo.imgUrl = images.length > 0 ? images[0] : ''
  195 + },
  196 + async listReserveParamss() {
  197 + try {
  198 + const params = {
  199 + page: 1,
  200 + row: 100,
  201 + communityId: this.communityId
  202 + }
  203 + const { data } = await listReserveParams(params)
  204 + this.editReserveServiceInfo.reserveParamss = data
  205 + } catch (error) {
  206 + console.error('获取参数列表失败:', error)
  207 + this.$message.error(this.$t('editReserveService.loadParamsFailed'))
  208 + }
  209 + },
  210 + async listReserveServices() {
  211 + try {
  212 + const params = {
  213 + page: 1,
  214 + row: 1,
  215 + goodsId: this.editReserveServiceInfo.goodsId,
  216 + communityId: this.communityId
  217 + }
  218 + const { data } = await listReserveGoods(params)
  219 + if (data && data.length > 0) {
  220 + Object.assign(this.editReserveServiceInfo, data[0])
  221 + this.$refs.richTextEditor.setContent(this.editReserveServiceInfo.content)
  222 + this.$refs.uploadImage.setImages([this.editReserveServiceInfo.imgUrl])
  223 +
  224 + }
  225 + } catch (error) {
  226 + console.error('获取服务详情失败:', error)
  227 + this.$message.error(this.$t('editReserveService.loadServiceFailed'))
  228 + }
  229 + },
  230 + validateForm() {
  231 + const requiredFields = [
  232 + 'goodsName',
  233 + 'paramsId',
  234 + 'price',
  235 + 'sort',
  236 + 'startDate',
  237 + 'endDate',
  238 + 'imgUrl',
  239 + 'state',
  240 + 'goodsDesc',
  241 + 'content'
  242 + ]
  243 +
  244 + for (const field of requiredFields) {
  245 + if (!this.editReserveServiceInfo[field]) {
  246 + this.$message.error(this.$t(`editReserveService.${field}Required`))
  247 + return false
  248 + }
  249 + }
  250 + return true
  251 + },
  252 + async handleSave() {
  253 + try {
  254 + if (!this.validateForm()) return
  255 +
  256 + this.editReserveServiceInfo.communityId = this.communityId
  257 + const { code, msg } = await updateReserveGoods(this.editReserveServiceInfo)
  258 +
  259 + if (code === 0) {
  260 + this.$message.success(this.$t('common.saveSuccess'))
  261 + this.$router.go(-1)
  262 + } else {
  263 + this.$message.error(msg)
  264 + }
  265 + } catch (error) {
  266 + console.error('保存失败:', error)
  267 + this.$message.error(this.$t('common.saveError'))
  268 + }
  269 + },
  270 + handleCancel() {
  271 + this.$router.go(-1)
  272 + }
  273 + }
  274 +}
  275 +</script>
  276 +
  277 +<style lang="scss" scoped>
  278 +.edit-reserve-service-container {
  279 + padding: 20px;
  280 +
  281 + .box-card {
  282 + margin-bottom: 20px;
  283 + }
  284 +
  285 + .text-right {
  286 + text-align: right;
  287 + }
  288 +
  289 + .editor-wrapper {
  290 + border: 1px solid #dcdfe6;
  291 + border-radius: 4px;
  292 + }
  293 +}
  294 +</style>
0 295 \ No newline at end of file
... ...
src/views/scm/ownerDiningLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + ownerDining: {
  4 + search: {
  5 + title: 'Search Conditions',
  6 + startDate: 'Select start date',
  7 + endDate: 'Select end date',
  8 + nameLike: 'Enter owner name',
  9 + link: 'Enter owner phone'
  10 + },
  11 + list: {
  12 + title: 'Owner Dining Records'
  13 + },
  14 + table: {
  15 + startDate: 'Start Date',
  16 + endDate: 'End Date',
  17 + name: 'Owner Name',
  18 + link: 'Phone',
  19 + goodsName: 'Goods',
  20 + frequency: 'Frequency'
  21 + },
  22 + fetchError: 'Failed to fetch data',
  23 + exportSuccess: 'Export successful',
  24 + exportError: 'Export failed'
  25 + }
  26 + },
  27 + zh: {
  28 + ownerDining: {
  29 + search: {
  30 + title: '查询条件',
  31 + startDate: '请选择开始时间',
  32 + endDate: '请选择结束时间',
  33 + nameLike: '请输入业主名称',
  34 + link: '请选择业主手机号'
  35 + },
  36 + list: {
  37 + title: '业主就餐'
  38 + },
  39 + table: {
  40 + startDate: '开始时间',
  41 + endDate: '结束时间',
  42 + name: '业主名称',
  43 + link: '手机号',
  44 + goodsName: '商品',
  45 + frequency: '就餐次数'
  46 + },
  47 + fetchError: '获取数据失败',
  48 + exportSuccess: '导出成功',
  49 + exportError: '导出失败'
  50 + }
  51 + }
  52 +}
0 53 \ No newline at end of file
... ...
src/views/scm/ownerDiningList.vue 0 → 100644
  1 +<template>
  2 + <div class="owner-dining-container">
  3 + <!-- 查询条件 -->
  4 + <el-card class="search-wrapper">
  5 + <div slot="header" class="text-left">
  6 + <span>{{ $t('ownerDining.search.title') }}</span>
  7 + </div>
  8 + <el-row :gutter="20">
  9 + <el-col :span="6">
  10 + <el-date-picker
  11 + v-model="searchForm.startDate"
  12 + type="date"
  13 + :placeholder="$t('ownerDining.search.startDate')"
  14 + style="width: 100%"
  15 + value-format="yyyy-MM-dd"
  16 + />
  17 + </el-col>
  18 + <el-col :span="6">
  19 + <el-date-picker
  20 + v-model="searchForm.endDate"
  21 + type="date"
  22 + :placeholder="$t('ownerDining.search.endDate')"
  23 + style="width: 100%"
  24 + value-format="yyyy-MM-dd"
  25 + />
  26 + </el-col>
  27 + <el-col :span="6">
  28 + <el-input
  29 + v-model="searchForm.nameLike"
  30 + :placeholder="$t('ownerDining.search.nameLike')"
  31 + clearable
  32 + style="width: 100%"
  33 + />
  34 + </el-col>
  35 + <el-col :span="6">
  36 + <el-button type="primary" @click="handleSearch">
  37 + {{ $t('common.search') }}
  38 + </el-button>
  39 + </el-col>
  40 + </el-row>
  41 + <el-row :gutter="20" style="margin-top: 15px">
  42 + <el-col :span="6">
  43 + <el-input
  44 + v-model="searchForm.link"
  45 + :placeholder="$t('ownerDining.search.link')"
  46 + clearable
  47 + style="width: 100%"
  48 + />
  49 + </el-col>
  50 + </el-row>
  51 + </el-card>
  52 +
  53 + <!-- 列表 -->
  54 + <el-card class="list-wrapper">
  55 + <div slot="header" class="flex justify-between">
  56 + <span>{{ $t('ownerDining.list.title') }}</span>
  57 + <div style="float: right">
  58 + <el-button type="primary" size="small" @click="handleExport">
  59 + {{ $t('common.export') }}
  60 + </el-button>
  61 + <el-button type="default" size="small" @click="goBack">
  62 + {{ $t('common.back') }}
  63 + </el-button>
  64 + </div>
  65 + </div>
  66 +
  67 + <el-table
  68 + v-loading="loading"
  69 + :data="tableData"
  70 + border
  71 + style="width: 100%"
  72 + >
  73 + <el-table-column
  74 + prop="startDate"
  75 + :label="$t('ownerDining.table.startDate')"
  76 + align="center"
  77 + />
  78 + <el-table-column
  79 + prop="endDate"
  80 + :label="$t('ownerDining.table.endDate')"
  81 + align="center"
  82 + />
  83 + <el-table-column
  84 + prop="name"
  85 + :label="$t('ownerDining.table.name')"
  86 + align="center"
  87 + />
  88 + <el-table-column
  89 + prop="link"
  90 + :label="$t('ownerDining.table.link')"
  91 + align="center"
  92 + />
  93 + <el-table-column
  94 + prop="goodsName"
  95 + :label="$t('ownerDining.table.goodsName')"
  96 + align="center"
  97 + />
  98 + <el-table-column
  99 + prop="frequency"
  100 + :label="$t('ownerDining.table.frequency')"
  101 + align="center"
  102 + />
  103 + </el-table>
  104 +
  105 + <el-pagination
  106 + :current-page.sync="page.current"
  107 + :page-sizes="[10, 20, 30, 50]"
  108 + :page-size="page.size"
  109 + :total="page.total"
  110 + layout="total, sizes, prev, pager, next, jumper"
  111 + @size-change="handleSizeChange"
  112 + @current-change="handleCurrentChange"
  113 + />
  114 + </el-card>
  115 + </div>
  116 +</template>
  117 +
  118 +<script>
  119 +import { queryOwnerReserveGoods, exportData } from '@/api/scm/ownerDiningApi'
  120 +import { getCommunityId } from '@/api/community/communityApi'
  121 +
  122 +export default {
  123 + name: 'OwnerDiningList',
  124 + data() {
  125 + return {
  126 + loading: false,
  127 + searchForm: {
  128 + startDate: '',
  129 + endDate: '',
  130 + nameLike: '',
  131 + link: '',
  132 + communityId: ''
  133 + },
  134 + tableData: [],
  135 + page: {
  136 + current: 1,
  137 + size: 10,
  138 + total: 0
  139 + }
  140 + }
  141 + },
  142 + created() {
  143 + this.initDate()
  144 + this.searchForm.communityId = getCommunityId()
  145 + this.getList()
  146 + },
  147 + methods: {
  148 + initDate() {
  149 + const date = new Date()
  150 + const month = date.getMonth() + 1
  151 + const newMonth = month < 10 ? `0${month}` : month
  152 +
  153 + this.searchForm.startDate = `${date.getFullYear()}-${newMonth}-01`
  154 +
  155 + date.setMonth(date.getMonth() + 1)
  156 + const nextMonth = date.getMonth() + 1
  157 + const newNextMonth = nextMonth < 10 ? `0${nextMonth}` : nextMonth
  158 + this.searchForm.endDate = `${date.getFullYear()}-${newNextMonth}-01`
  159 + },
  160 + async getList() {
  161 + try {
  162 + this.loading = true
  163 + const params = {
  164 + ...this.searchForm,
  165 + page: this.page.current,
  166 + row: this.page.size
  167 + }
  168 + const { data, total } = await queryOwnerReserveGoods(params)
  169 + this.tableData = data
  170 + this.page.total = total
  171 + } catch (error) {
  172 + this.$message.error(this.$t('ownerDining.fetchError'))
  173 + } finally {
  174 + this.loading = false
  175 + }
  176 + },
  177 + handleSearch() {
  178 + this.page.current = 1
  179 + this.getList()
  180 + },
  181 + async handleExport() {
  182 + try {
  183 + this.loading = true
  184 + const params = {
  185 + ...this.searchForm,
  186 + pagePath: 'ownerDining'
  187 + }
  188 + await exportData(params)
  189 + this.$message.success(this.$t('ownerDining.exportSuccess'))
  190 + } catch (error) {
  191 + this.$message.error(this.$t('ownerDining.exportError'))
  192 + } finally {
  193 + this.loading = false
  194 + }
  195 + },
  196 + goBack() {
  197 + this.$router.go(-1)
  198 + },
  199 + handleSizeChange(val) {
  200 + this.page.size = val
  201 + this.getList()
  202 + },
  203 + handleCurrentChange(val) {
  204 + this.page.current = val
  205 + this.getList()
  206 + }
  207 + }
  208 +}
  209 +</script>
  210 +
  211 +<style lang="scss" scoped>
  212 +.owner-dining-container {
  213 + padding: 20px;
  214 +
  215 + .search-wrapper {
  216 + margin-bottom: 20px;
  217 + }
  218 +
  219 + .list-wrapper {
  220 + margin-top: 20px;
  221 + }
  222 +
  223 + .el-pagination {
  224 + margin-top: 20px;
  225 + text-align: right;
  226 + }
  227 +}
  228 +</style>
0 229 \ No newline at end of file
... ...
src/views/scm/reserveCatalogManageLang.js
... ... @@ -5,72 +5,73 @@ export const messages = {
5 5 title: 'Search Conditions',
6 6 namePlaceholder: 'Please enter name',
7 7 typePlaceholder: 'Please select type',
8   - typeOption1: 'Reservation Dining',
9   - typeOption2: 'Reservation Service'
  8 + typeOptions: {
  9 + all: 'All',
  10 + dining: 'Reservation Dining',
  11 + service: 'Reservation Service'
  12 + }
10 13 },
11 14 list: {
12 15 title: 'Reservation Catalog List'
13 16 },
14 17 table: {
15 18 type: 'Type',
16   - type1: 'Reservation Dining',
17   - type2: 'Reservation Service',
18 19 name: 'Name',
19 20 sort: 'Sort',
20 21 state: 'Status',
21   - state1: 'Show',
22   - state2: 'Hide',
23   - createTime: 'Create Time'
  22 + createTime: 'Create Time',
  23 + typeOptions: {
  24 + dining: 'Reservation Dining',
  25 + service: 'Reservation Service'
  26 + },
  27 + stateOptions: {
  28 + show: 'Show',
  29 + hide: 'Hide'
  30 + }
24 31 },
25   - add: {
26   - title: 'Add Reservation Catalog',
27   - name: 'Name',
28   - namePlaceholder: 'Required, please enter name',
  32 + form: {
  33 + name: 'Catalog Name',
29 34 sort: 'Sort',
30   - sortPlaceholder: 'Required, please enter sort',
31 35 type: 'Type',
32   - typePlaceholder: 'Required, please select type',
33   - typeOption1: 'Reservation Dining',
34   - typeOption2: 'Reservation Service',
35 36 state: 'Status',
  37 + namePlaceholder: 'Required, please enter catalog name',
  38 + sortPlaceholder: 'Required, please enter sort number',
  39 + typePlaceholder: 'Required, please select type',
36 40 statePlaceholder: 'Required, please select status',
37   - stateOption1: 'Show',
38   - stateOption2: 'Hide',
  41 + typeOptions: {
  42 + dining: 'Reservation Dining',
  43 + service: 'Reservation Service'
  44 + },
  45 + stateOptions: {
  46 + show: 'Show',
  47 + hide: 'Hide'
  48 + }
  49 + },
  50 + validate: {
  51 + nameRequired: 'Catalog name is required',
  52 + nameMaxLength: 'Catalog name cannot exceed 128 characters',
  53 + sortRequired: 'Sort is required',
  54 + sortMaxLength: 'Sort cannot exceed 12 characters',
  55 + typeRequired: 'Type is required',
  56 + stateRequired: 'Status is required',
  57 + catalogIdRequired: 'Catalog ID is required'
  58 + },
  59 + add: {
  60 + title: 'Add Reservation Catalog',
39 61 success: 'Add successfully',
40   - error: 'Add failed'
  62 + error: 'Failed to add'
41 63 },
42 64 edit: {
43 65 title: 'Edit Reservation Catalog',
44   - name: 'Name',
45   - namePlaceholder: 'Required, please enter name',
46   - sort: 'Sort',
47   - sortPlaceholder: 'Required, please enter sort',
48   - type: 'Type',
49   - typePlaceholder: 'Required, please select type',
50   - typeOption1: 'Reservation Dining',
51   - typeOption2: 'Reservation Service',
52   - state: 'Status',
53   - statePlaceholder: 'Required, please select status',
54   - stateOption1: 'Show',
55   - stateOption2: 'Hide',
56 66 success: 'Edit successfully',
57   - error: 'Edit failed'
  67 + error: 'Failed to edit'
58 68 },
59 69 delete: {
60 70 title: 'Delete Confirmation',
61   - confirmText1: 'Are you sure to delete the reservation catalog',
62   - confirmText2: '? This operation cannot be undone.',
  71 + confirmText: 'Are you sure to delete this reservation catalog?',
  72 + name: 'Catalog Name',
63 73 success: 'Delete successfully',
64   - error: 'Delete failed'
65   - },
66   - validate: {
67   - nameRequired: 'Name is required',
68   - nameMaxLength: 'Name cannot exceed 128 characters',
69   - sortRequired: 'Sort is required',
70   - sortMaxLength: 'Sort cannot exceed 12 characters',
71   - typeRequired: 'Type is required',
72   - stateRequired: 'Status is required',
73   - catalogIdRequired: 'Catalog ID is required'
  74 + error: 'Failed to delete'
74 75 },
75 76 fetchError: 'Failed to fetch data'
76 77 }
... ... @@ -81,73 +82,74 @@ export const messages = {
81 82 title: '查询条件',
82 83 namePlaceholder: '请输入名称',
83 84 typePlaceholder: '请选择类型',
84   - typeOption1: '预约就餐',
85   - typeOption2: '预约服务'
  85 + typeOptions: {
  86 + all: '全部',
  87 + dining: '预约就餐',
  88 + service: '预约服务'
  89 + }
86 90 },
87 91 list: {
88 92 title: '预约目录列表'
89 93 },
90 94 table: {
91 95 type: '类型',
92   - type1: '预约就餐',
93   - type2: '预约服务',
94 96 name: '名称',
95 97 sort: '排序',
96 98 state: '状态',
97   - state1: '展示',
98   - state2: '不展示',
99   - createTime: '创建时间'
  99 + createTime: '创建时间',
  100 + typeOptions: {
  101 + dining: '预约就餐',
  102 + service: '预约服务'
  103 + },
  104 + stateOptions: {
  105 + show: '展示',
  106 + hide: '不展示'
  107 + }
100 108 },
101   - add: {
102   - title: '添加预约目录',
103   - name: '名称',
104   - namePlaceholder: '必填,请输入名称',
  109 + form: {
  110 + name: '目录名称',
105 111 sort: '排序',
106   - sortPlaceholder: '必填,请输入排序',
107 112 type: '类型',
108   - typePlaceholder: '必填,请选择类型',
109   - typeOption1: '预约就餐',
110   - typeOption2: '预约服务',
111 113 state: '状态',
  114 + namePlaceholder: '必填,请填写预约目录',
  115 + sortPlaceholder: '必填,请填写排序',
  116 + typePlaceholder: '必填,请选择类型',
112 117 statePlaceholder: '必填,请选择状态',
113   - stateOption1: '展示',
114   - stateOption2: '不展示',
  118 + typeOptions: {
  119 + dining: '预约就餐',
  120 + service: '预约服务'
  121 + },
  122 + stateOptions: {
  123 + show: '展示',
  124 + hide: '不展示'
  125 + }
  126 + },
  127 + validate: {
  128 + nameRequired: '预约名称不能为空',
  129 + nameMaxLength: '预约名称不能超过128个字符',
  130 + sortRequired: '排序不能为空',
  131 + sortMaxLength: '排序不能超过12个字符',
  132 + typeRequired: '类型不能为空',
  133 + stateRequired: '状态不能为空',
  134 + catalogIdRequired: '编号不能为空'
  135 + },
  136 + add: {
  137 + title: '添加预约目录',
115 138 success: '添加成功',
116 139 error: '添加失败'
117 140 },
118 141 edit: {
119 142 title: '修改预约目录',
120   - name: '名称',
121   - namePlaceholder: '必填,请输入名称',
122   - sort: '排序',
123   - sortPlaceholder: '必填,请输入排序',
124   - type: '类型',
125   - typePlaceholder: '必填,请选择类型',
126   - typeOption1: '预约就餐',
127   - typeOption2: '预约服务',
128   - state: '状态',
129   - statePlaceholder: '必填,请选择状态',
130   - stateOption1: '展示',
131   - stateOption2: '不展示',
132 143 success: '修改成功',
133 144 error: '修改失败'
134 145 },
135 146 delete: {
136 147 title: '删除确认',
137   - confirmText1: '确定要删除预约目录',
138   - confirmText2: '?此操作不可撤销。',
  148 + confirmText: '确定删除该预约目录吗?',
  149 + name: '目录名称',
139 150 success: '删除成功',
140 151 error: '删除失败'
141 152 },
142   - validate: {
143   - nameRequired: '名称不能为空',
144   - nameMaxLength: '名称不能超过128个字符',
145   - sortRequired: '排序不能为空',
146   - sortMaxLength: '排序不能超过12个字符',
147   - typeRequired: '类型不能为空',
148   - stateRequired: '状态不能为空',
149   - catalogIdRequired: '目录ID不能为空'
150   - },
151 153 fetchError: '获取数据失败'
152 154 }
153 155 }
... ...
src/views/scm/reserveCatalogManageList.vue
... ... @@ -7,14 +7,30 @@
7 7 </div>
8 8 <el-row :gutter="20">
9 9 <el-col :span="6">
10   - <el-input v-model="searchForm.name" :placeholder="$t('reserveCatalogManage.search.namePlaceholder')"
11   - clearable />
  10 + <el-input
  11 + v-model="searchForm.name"
  12 + :placeholder="$t('reserveCatalogManage.search.namePlaceholder')"
  13 + clearable
  14 + />
12 15 </el-col>
13 16 <el-col :span="6">
14   - <el-select v-model="searchForm.type" :placeholder="$t('reserveCatalogManage.search.typePlaceholder')"
15   - style="width:100%">
16   - <el-option :label="$t('reserveCatalogManage.search.typeOption1')" value="1001" />
17   - <el-option :label="$t('reserveCatalogManage.search.typeOption2')" value="2002" />
  17 + <el-select
  18 + v-model="searchForm.type"
  19 + :placeholder="$t('reserveCatalogManage.search.typePlaceholder')"
  20 + style="width:100%"
  21 + >
  22 + <el-option
  23 + :label="$t('reserveCatalogManage.search.typeOptions.all')"
  24 + value=""
  25 + />
  26 + <el-option
  27 + :label="$t('reserveCatalogManage.search.typeOptions.dining')"
  28 + value="1001"
  29 + />
  30 + <el-option
  31 + :label="$t('reserveCatalogManage.search.typeOptions.service')"
  32 + value="2002"
  33 + />
18 34 </el-select>
19 35 </el-col>
20 36 <el-col :span="4">
... ... @@ -29,57 +45,102 @@
29 45 <el-card class="list-wrapper">
30 46 <div slot="header" class="flex justify-between">
31 47 <span>{{ $t('reserveCatalogManage.list.title') }}</span>
32   - <el-button type="primary" size="mini" @click="handleAdd">
  48 + <el-button
  49 + type="primary"
  50 + style="float: right;"
  51 + @click="handleAdd"
  52 + >
33 53 {{ $t('common.add') }}
34 54 </el-button>
35 55 </div>
36 56  
37   - <el-table v-loading="loading" :data="tableData" border style="width: 100%">
38   - <el-table-column prop="type" :label="$t('reserveCatalogManage.table.type')" align="center">
  57 + <el-table
  58 + v-loading="loading"
  59 + :data="tableData"
  60 + border
  61 + style="width: 100%"
  62 + >
  63 + <el-table-column
  64 + prop="type"
  65 + :label="$t('reserveCatalogManage.table.type')"
  66 + align="center"
  67 + >
39 68 <template slot-scope="scope">
40   - {{ scope.row.type === '1001' ? $t('reserveCatalogManage.table.type1') :
41   - $t('reserveCatalogManage.table.type2') }}
  69 + {{ scope.row.type === '1001' ? $t('reserveCatalogManage.table.typeOptions.dining') : $t('reserveCatalogManage.table.typeOptions.service') }}
42 70 </template>
43 71 </el-table-column>
44   - <el-table-column prop="name" :label="$t('reserveCatalogManage.table.name')" align="center" />
45   - <el-table-column prop="sort" :label="$t('reserveCatalogManage.table.sort')" align="center" />
46   - <el-table-column prop="state" :label="$t('reserveCatalogManage.table.state')" align="center">
  72 + <el-table-column
  73 + prop="name"
  74 + :label="$t('reserveCatalogManage.table.name')"
  75 + align="center"
  76 + />
  77 + <el-table-column
  78 + prop="sort"
  79 + :label="$t('reserveCatalogManage.table.sort')"
  80 + align="center"
  81 + />
  82 + <el-table-column
  83 + prop="state"
  84 + :label="$t('reserveCatalogManage.table.state')"
  85 + align="center"
  86 + >
47 87 <template slot-scope="scope">
48   - {{ scope.row.state === '1001' ? $t('reserveCatalogManage.table.state1') :
49   - $t('reserveCatalogManage.table.state2') }}
  88 + {{ scope.row.state === '1001' ? $t('reserveCatalogManage.table.stateOptions.show') : $t('reserveCatalogManage.table.stateOptions.hide') }}
50 89 </template>
51 90 </el-table-column>
52   - <el-table-column prop="createTime" :label="$t('reserveCatalogManage.table.createTime')" align="center" />
53   - <el-table-column :label="$t('common.operation')" align="center" width="200">
  91 + <el-table-column
  92 + prop="createTime"
  93 + :label="$t('reserveCatalogManage.table.createTime')"
  94 + align="center"
  95 + />
  96 + <el-table-column
  97 + :label="$t('common.operation')"
  98 + align="center"
  99 + width="200"
  100 + >
54 101 <template slot-scope="scope">
55   - <el-button size="mini" type="primary" @click="handleEdit(scope.row)">
  102 + <el-button
  103 + size="mini"
  104 + type="primary"
  105 + @click="handleEdit(scope.row)"
  106 + >
56 107 {{ $t('common.edit') }}
57 108 </el-button>
58   - <el-button size="mini" type="danger" @click="handleDelete(scope.row)">
  109 + <el-button
  110 + size="mini"
  111 + type="danger"
  112 + @click="handleDelete(scope.row)"
  113 + >
59 114 {{ $t('common.delete') }}
60 115 </el-button>
61 116 </template>
62 117 </el-table-column>
63 118 </el-table>
64 119  
65   - <el-pagination :current-page.sync="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size"
66   - :total="page.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
67   - @current-change="handleCurrentChange" />
  120 + <el-pagination
  121 + :current-page="page.current"
  122 + :page-sizes="[10, 20, 30, 50]"
  123 + :page-size="page.size"
  124 + :total="page.total"
  125 + layout="total, sizes, prev, pager, next, jumper"
  126 + @size-change="handleSizeChange"
  127 + @current-change="handleCurrentChange"
  128 + />
68 129 </el-card>
69 130  
70 131 <!-- 子组件 -->
71   - <add-reserve-catalog ref="addDialog" @success="handleSuccess" />
72   - <edit-reserve-catalog ref="editDialog" @success="handleSuccess" />
73   - <delete-reserve-catalog ref="deleteDialog" @success="handleSuccess" />
  132 + <add-reserve-catalog ref="addReserveCatalog" @success="handleSuccess" />
  133 + <edit-reserve-catalog ref="editReserveCatalog" @success="handleSuccess" />
  134 + <delete-reserve-catalog ref="deleteReserveCatalog" @success="handleSuccess" />
74 135 </div>
75 136 </template>
76 137  
77 138 <script>
78 139 import { listReserveCatalog } from '@/api/scm/reserveCatalogManageApi'
79   -import { getCommunityId } from '@/api/community/communityApi'
80 140 import AddReserveCatalog from '@/components/scm/addReserveCatalog'
81 141 import EditReserveCatalog from '@/components/scm/editReserveCatalog'
82 142 import DeleteReserveCatalog from '@/components/scm/deleteReserveCatalog'
  143 +import { getCommunityId } from '@/api/community/communityApi'
83 144  
84 145 export default {
85 146 name: 'ReserveCatalogManageList',
... ... @@ -131,13 +192,13 @@ export default {
131 192 this.getList()
132 193 },
133 194 handleAdd() {
134   - this.$refs.addDialog.open()
  195 + this.$refs.addReserveCatalog.open()
135 196 },
136 197 handleEdit(row) {
137   - this.$refs.editDialog.open(row)
  198 + this.$refs.editReserveCatalog.open(row)
138 199 },
139 200 handleDelete(row) {
140   - this.$refs.deleteDialog.open(row)
  201 + this.$refs.deleteReserveCatalog.open(row)
141 202 },
142 203 handleSuccess() {
143 204 this.getList()
... ... @@ -160,15 +221,21 @@ export default {
160 221  
161 222 .search-wrapper {
162 223 margin-bottom: 20px;
163   - }
164 224  
165   - .list-wrapper {
166   - margin-bottom: 20px;
  225 + .el-row {
  226 + margin-bottom: -20px;
  227 + }
  228 +
  229 + .el-col {
  230 + margin-bottom: 20px;
  231 + }
167 232 }
168 233  
169   - .el-pagination {
170   - margin-top: 20px;
171   - text-align: right;
  234 + .list-wrapper {
  235 + .el-pagination {
  236 + margin-top: 20px;
  237 + text-align: right;
  238 + }
172 239 }
173 240 }
174 241 </style>
175 242 \ No newline at end of file
... ...
src/views/scm/reserveConfirmLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + reserveConfirm: {
  4 + scanPlaceholder: 'Please scan the QR code',
  5 + confirm: 'Confirm',
  6 + result: 'Result',
  7 + confirmTime: 'Confirm Time',
  8 + goodsService: 'Goods/Service',
  9 + quantity: 'Quantity',
  10 + appointmentDate: 'Appointment Date',
  11 + appointmentHour: 'Appointment Hour',
  12 + appointmentPerson: 'Appointment Person',
  13 + appointmentPhone: 'Appointment Phone',
  14 + remark: 'Remark',
  15 + searchCondition: 'Search Condition',
  16 + personNamePlaceholder: 'Please enter person name',
  17 + personTelPlaceholder: 'Please enter phone number',
  18 + appointmentTimePlaceholder: 'Please select appointment time',
  19 + search: 'Search',
  20 + orderId: 'Order ID',
  21 + scanWarning: 'Please scan the QR code',
  22 + confirmSuccess: 'Confirm success',
  23 + fetchError: 'Failed to fetch data'
  24 + }
  25 + },
  26 + zh: {
  27 + reserveConfirm: {
  28 + scanPlaceholder: '请扫码枪扫码核销',
  29 + confirm: '核销',
  30 + result: '核销结果',
  31 + confirmTime: '核销时间',
  32 + goodsService: '商品/服务',
  33 + quantity: '核销数量',
  34 + appointmentDate: '预约日期',
  35 + appointmentHour: '预约小时',
  36 + appointmentPerson: '预约人',
  37 + appointmentPhone: '预约电话',
  38 + remark: '备注',
  39 + searchCondition: '查询条件',
  40 + personNamePlaceholder: '请输入预约人',
  41 + personTelPlaceholder: '请输入预约电话',
  42 + appointmentTimePlaceholder: '请选择预约时间',
  43 + search: '查询',
  44 + orderId: '核销订单',
  45 + scanWarning: '请扫码',
  46 + confirmSuccess: '核销成功',
  47 + fetchError: '获取数据失败'
  48 + }
  49 + }
  50 +}
0 51 \ No newline at end of file
... ...
src/views/scm/reserveConfirmList.vue 0 → 100644
  1 +<template>
  2 + <div class="reserve-confirm-container">
  3 + <el-row :gutter="20">
  4 + <el-col :span="6">
  5 + <el-card class="box-card">
  6 + <div class="card-header">
  7 + <el-input
  8 + v-model="reserveConfirmInfo.timeId"
  9 + :placeholder="$t('reserveConfirm.scanPlaceholder')"
  10 + @keyup.enter.native="confirmReserve"
  11 + clearable
  12 + ></el-input>
  13 + <el-button
  14 + type="primary"
  15 + size="small"
  16 + @click="confirmReserve"
  17 + class="confirm-btn"
  18 + >
  19 + {{ $t('reserveConfirm.confirm') }}
  20 + </el-button>
  21 + </div>
  22 +
  23 + <div class="result-wrapper">
  24 + <div class="result-item">
  25 + <span class="label">{{ $t('reserveConfirm.result') }}</span>
  26 + <span class="value">{{ reserveConfirmInfo.order.remark }}</span>
  27 + </div>
  28 + <div class="result-item">
  29 + <span class="label">{{ $t('reserveConfirm.confirmTime') }}</span>
  30 + <span class="value">{{ reserveConfirmInfo.order.createTime }}</span>
  31 + </div>
  32 + <div class="result-item">
  33 + <span class="label">{{ $t('reserveConfirm.goodsService') }}</span>
  34 + <span class="value">{{ reserveConfirmInfo.order.goodsName }}</span>
  35 + </div>
  36 + <div class="result-item">
  37 + <span class="label">{{ $t('reserveConfirm.quantity') }}</span>
  38 + <span class="value">{{ reserveConfirmInfo.order.quantity }}</span>
  39 + </div>
  40 + <div class="result-item">
  41 + <span class="label">{{ $t('reserveConfirm.appointmentDate') }}</span>
  42 + <span class="value">{{ reserveConfirmInfo.order.appointmentTime }}</span>
  43 + </div>
  44 + <div class="result-item">
  45 + <span class="label">{{ $t('reserveConfirm.appointmentHour') }}</span>
  46 + <span class="value">{{ reserveConfirmInfo.order.hours }}</span>
  47 + </div>
  48 + <div class="result-item">
  49 + <span class="label">{{ $t('reserveConfirm.appointmentPerson') }}</span>
  50 + <span class="value">{{ reserveConfirmInfo.order.personName }}</span>
  51 + </div>
  52 + <div class="result-item">
  53 + <span class="label">{{ $t('reserveConfirm.appointmentPhone') }}</span>
  54 + <span class="value">{{ reserveConfirmInfo.order.personTel }}</span>
  55 + </div>
  56 + </div>
  57 + </el-card>
  58 + </el-col>
  59 +
  60 + <el-col :span="18">
  61 + <el-card class="box-card">
  62 + <div slot="header" class="text-left">
  63 + <span>{{ $t('reserveConfirm.searchCondition') }}</span>
  64 + </div>
  65 + <el-row :gutter="20">
  66 + <el-col :span="6">
  67 + <el-input
  68 + v-model="reserveConfirmInfo.conditions.personName"
  69 + :placeholder="$t('reserveConfirm.personNamePlaceholder')"
  70 + clearable
  71 + ></el-input>
  72 + </el-col>
  73 + <el-col :span="6">
  74 + <el-input
  75 + v-model="reserveConfirmInfo.conditions.personTel"
  76 + :placeholder="$t('reserveConfirm.personTelPlaceholder')"
  77 + clearable
  78 + ></el-input>
  79 + </el-col>
  80 + <el-col :span="6">
  81 + <el-input
  82 + v-model="reserveConfirmInfo.conditions.appointmentTime"
  83 + :placeholder="$t('reserveConfirm.appointmentTimePlaceholder')"
  84 + clearable
  85 + ></el-input>
  86 + </el-col>
  87 + <el-col :span="6">
  88 + <el-button
  89 + type="primary"
  90 + @click="queryReserveConfirm"
  91 + icon="el-icon-search"
  92 + >
  93 + {{ $t('reserveConfirm.search') }}
  94 + </el-button>
  95 + </el-col>
  96 + </el-row>
  97 + </el-card>
  98 +
  99 + <el-card class="box-card table-wrapper">
  100 + <el-table
  101 + :data="reserveConfirmInfo.orders"
  102 + border
  103 + style="width: 100%"
  104 + v-loading="loading"
  105 + >
  106 + <el-table-column
  107 + prop="orderId"
  108 + :label="$t('reserveConfirm.orderId')"
  109 + align="center"
  110 + ></el-table-column>
  111 + <el-table-column
  112 + prop="goodsName"
  113 + :label="$t('reserveConfirm.goodsService')"
  114 + align="center"
  115 + ></el-table-column>
  116 + <el-table-column
  117 + prop="quantity"
  118 + :label="$t('reserveConfirm.quantity')"
  119 + align="center"
  120 + ></el-table-column>
  121 + <el-table-column
  122 + prop="appointmentTime"
  123 + :label="$t('reserveConfirm.appointmentDate')"
  124 + align="center"
  125 + ></el-table-column>
  126 + <el-table-column
  127 + prop="hours"
  128 + :label="$t('reserveConfirm.appointmentHour')"
  129 + align="center"
  130 + ></el-table-column>
  131 + <el-table-column
  132 + prop="personName"
  133 + :label="$t('reserveConfirm.appointmentPerson')"
  134 + align="center"
  135 + ></el-table-column>
  136 + <el-table-column
  137 + prop="personTel"
  138 + :label="$t('reserveConfirm.appointmentPhone')"
  139 + align="center"
  140 + ></el-table-column>
  141 + <el-table-column
  142 + prop="createTime"
  143 + :label="$t('reserveConfirm.confirmTime')"
  144 + align="center"
  145 + ></el-table-column>
  146 + <el-table-column
  147 + prop="remark"
  148 + :label="$t('reserveConfirm.remark')"
  149 + align="center"
  150 + ></el-table-column>
  151 + </el-table>
  152 +
  153 + <el-pagination
  154 + @size-change="handleSizeChange"
  155 + @current-change="handleCurrentChange"
  156 + :current-page="page.current"
  157 + :page-sizes="[10, 20, 30, 50]"
  158 + :page-size="page.size"
  159 + layout="total, sizes, prev, pager, next, jumper"
  160 + :total="page.total"
  161 + class="pagination-wrapper"
  162 + ></el-pagination>
  163 + </el-card>
  164 + </el-col>
  165 + </el-row>
  166 + </div>
  167 +</template>
  168 +
  169 +<script>
  170 +import { listReserveGoodsConfirmOrder, saveReserveGoodsConfirmOrder } from '@/api/scm/reserveConfirmApi'
  171 +import { getCommunityId } from '@/api/community/communityApi'
  172 +
  173 +export default {
  174 + name: 'ReserveConfirmList',
  175 + data() {
  176 + return {
  177 + loading: false,
  178 + reserveConfirmInfo: {
  179 + orders: [],
  180 + order: {
  181 + remark: '',
  182 + appointmentTime: '',
  183 + createTime: '',
  184 + hours: '',
  185 + spaceName: '',
  186 + personName: '',
  187 + personTel: '',
  188 + quantity: '',
  189 + goodsName: ''
  190 + },
  191 + timeId: '',
  192 + conditions: {
  193 + spaceId: '',
  194 + personName: '',
  195 + personTel: '',
  196 + appointmentTime: '',
  197 + communityId: ''
  198 + }
  199 + },
  200 + page: {
  201 + current: 1,
  202 + size: 10,
  203 + total: 0
  204 + }
  205 + }
  206 + },
  207 + created() {
  208 + this.reserveConfirmInfo.conditions.communityId = getCommunityId()
  209 + this.listReserveConfirms()
  210 + },
  211 + methods: {
  212 + async listReserveConfirms() {
  213 + try {
  214 + this.loading = true
  215 + const params = {
  216 + ...this.reserveConfirmInfo.conditions,
  217 + page: this.page.current,
  218 + row: this.page.size
  219 + }
  220 + const { data, total } = await listReserveGoodsConfirmOrder(params)
  221 + this.reserveConfirmInfo.orders = data
  222 + this.page.total = total
  223 + } catch (error) {
  224 + this.$message.error(this.$t('reserveConfirm.fetchError'))
  225 + } finally {
  226 + this.loading = false
  227 + }
  228 + },
  229 + async confirmReserve() {
  230 + if (!this.reserveConfirmInfo.timeId) {
  231 + this.$message.warning(this.$t('reserveConfirm.scanWarning'))
  232 + return
  233 + }
  234 +
  235 + try {
  236 + const data = {
  237 + timeId: this.reserveConfirmInfo.timeId,
  238 + communityId: this.reserveConfirmInfo.conditions.communityId
  239 + }
  240 + const res = await saveReserveGoodsConfirmOrder(data)
  241 +
  242 + if (res.code !== 0) {
  243 + this.$message.error(res.msg)
  244 + return
  245 + }
  246 +
  247 + this.$message.success(this.$t('reserveConfirm.confirmSuccess'))
  248 + this.reserveConfirmInfo.timeId = ''
  249 + this.listReserveConfirms()
  250 +
  251 + if (res.data && res.data.length > 0) {
  252 + this.reserveConfirmInfo.order = { ...res.data[0] }
  253 + if (!this.reserveConfirmInfo.order.remark) {
  254 + this.reserveConfirmInfo.order.remark = this.$t('reserveConfirm.confirmSuccess')
  255 + }
  256 + }
  257 + } catch (error) {
  258 + this.$message.error(error.message)
  259 + this.reserveConfirmInfo.timeId = ''
  260 + }
  261 + },
  262 + queryReserveConfirm() {
  263 + this.page.current = 1
  264 + this.listReserveConfirms()
  265 + },
  266 + handleSizeChange(val) {
  267 + this.page.size = val
  268 + this.listReserveConfirms()
  269 + },
  270 + handleCurrentChange(val) {
  271 + this.page.current = val
  272 + this.listReserveConfirms()
  273 + }
  274 + }
  275 +}
  276 +</script>
  277 +
  278 +<style lang="scss" scoped>
  279 +.reserve-confirm-container {
  280 + padding: 20px;
  281 +
  282 + .box-card {
  283 + margin-bottom: 20px;
  284 +
  285 + .card-header {
  286 + display: flex;
  287 + margin-bottom: 20px;
  288 +
  289 + .confirm-btn {
  290 + margin-left: 10px;
  291 + }
  292 + }
  293 +
  294 + .result-wrapper {
  295 + .result-item {
  296 + display: flex;
  297 + justify-content: space-between;
  298 + margin-bottom: 10px;
  299 + padding: 5px 0;
  300 + border-bottom: 1px solid #eee;
  301 +
  302 + .label {
  303 + font-weight: bold;
  304 + }
  305 + }
  306 + }
  307 + }
  308 +
  309 + .table-wrapper {
  310 + margin-top: 20px;
  311 +
  312 + .pagination-wrapper {
  313 + margin-top: 20px;
  314 + text-align: right;
  315 + }
  316 + }
  317 +}
  318 +</style>
0 319 \ No newline at end of file
... ...
src/views/scm/reserveDiningManageLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + reserveDiningManage: {
  4 + searchTitle: 'Search Conditions',
  5 + listTitle: 'Reservation Dining',
  6 + addCatalog: 'Add Catalog',
  7 + addCatalogFirst: 'Please add catalog first',
  8 + addFirst: 'Please add first',
  9 + goodsIdPlaceholder: 'Please enter goods ID',
  10 + goodsNamePlaceholder: 'Please enter goods name',
  11 + statePlaceholder: 'Please select status',
  12 + stateNotOnline: 'Not Online',
  13 + stateOnline: 'Online',
  14 + goodsCover: 'Goods Cover',
  15 + goodsName: 'Name(ID)',
  16 + params: 'Parameters',
  17 + reserveWay: 'Reservation Way',
  18 + day: 'Day',
  19 + week: 'Week',
  20 + reserveCount: 'Reservation Count',
  21 + reserveQuantity: 'Reservation Quantity',
  22 + price: 'Price',
  23 + validDate: 'Valid Date',
  24 + reserveStartTime: 'Reservation Start Time',
  25 + sort: 'Sort',
  26 + state: 'Status',
  27 + reserveDining: 'Reservation Dining',
  28 + diningStatistics: 'Dining Statistics',
  29 + dining: 'Dining',
  30 + fetchError: 'Failed to fetch data'
  31 + },
  32 + reserveDining: {
  33 + reservePerson: 'Reservation Person',
  34 + reservePersonPlaceholder: 'Required, please enter reservation person',
  35 + reservePersonRequired: 'Reservation person is required',
  36 + reservePersonMaxLength: 'Reservation person cannot exceed 64 characters',
  37 + reserveTel: 'Reservation Tel',
  38 + reserveTelPlaceholder: 'Required, please enter reservation tel',
  39 + reserveTelRequired: 'Reservation tel is required',
  40 + reserveTelMaxLength: 'Reservation tel cannot exceed 11 characters',
  41 + payWay: 'Payment Way',
  42 + payWayPlaceholder: 'Please select payment way',
  43 + payWayRequired: 'Payment way is required',
  44 + cash: 'Cash',
  45 + wechat: 'WeChat',
  46 + alipay: 'Alipay',
  47 + reserveQuantity: 'Reservation Quantity',
  48 + reserveQuantityPlaceholder: 'Please select reservation quantity',
  49 + unit: 'unit',
  50 + receivableAmount: 'Receivable Amount',
  51 + receivableAmountPlaceholder: 'Required, please enter receivable amount',
  52 + receivableAmountRequired: 'Receivable amount is required',
  53 + receivedAmount: 'Received Amount',
  54 + receivedAmountPlaceholder: 'Required, please enter received amount',
  55 + receivedAmountRequired: 'Received amount is required',
  56 + reserveDate: 'Reservation Date',
  57 + reserveDatePlaceholder: 'Required, please select reservation date',
  58 + reserveDateRequired: 'Reservation date is required',
  59 + reserveTime: 'Reservation Time',
  60 + reserveTimePlaceholder: 'Required, please select reservation time',
  61 + hour: 'hour',
  62 + remark: 'Remark',
  63 + remarkPlaceholder: 'Required, please enter remark',
  64 + remarkRequired: 'Remark is required',
  65 + confirmDelete: 'Confirm to delete reservation dining?'
  66 + }
  67 + },
  68 + zh: {
  69 + reserveDiningManage: {
  70 + searchTitle: '查询条件',
  71 + listTitle: '预约就餐',
  72 + addCatalog: '添加目录',
  73 + addCatalogFirst: '请先添加目录',
  74 + addFirst: '请先添加',
  75 + goodsIdPlaceholder: '请输入商品ID',
  76 + goodsNamePlaceholder: '请输入商品名称',
  77 + statePlaceholder: '请选择状态',
  78 + stateNotOnline: '未上线',
  79 + stateOnline: '上线',
  80 + goodsCover: '商品封面',
  81 + goodsName: '名称(编号)',
  82 + params: '参数',
  83 + reserveWay: '预约方式',
  84 + day: '日',
  85 + week: '周',
  86 + reserveCount: '预约次数',
  87 + reserveQuantity: '预约数量',
  88 + price: '单价',
  89 + validDate: '有效期',
  90 + reserveStartTime: '开始预约时间',
  91 + sort: '排序',
  92 + state: '状态',
  93 + reserveDining: '预约就餐',
  94 + diningStatistics: '就餐统计',
  95 + dining: '就餐',
  96 + fetchError: '获取数据失败'
  97 + },
  98 + reserveDining: {
  99 + reservePerson: '预约人',
  100 + reservePersonPlaceholder: '必填,请填写预约人',
  101 + reservePersonRequired: '预约人不能为空',
  102 + reservePersonMaxLength: '预约人不能超过64个字符',
  103 + reserveTel: '预约电话',
  104 + reserveTelPlaceholder: '必填,请填写预约电话',
  105 + reserveTelRequired: '预约电话不能为空',
  106 + reserveTelMaxLength: '预约电话不能超过11个字符',
  107 + payWay: '支付方式',
  108 + payWayPlaceholder: '请选择支付方式',
  109 + payWayRequired: '支付方式不能为空',
  110 + cash: '现金',
  111 + wechat: '微信',
  112 + alipay: '支付宝',
  113 + reserveQuantity: '预约数量',
  114 + reserveQuantityPlaceholder: '请选择预约数量',
  115 + unit: '个',
  116 + receivableAmount: '应收金额',
  117 + receivableAmountPlaceholder: '必填,请填写应收金额',
  118 + receivableAmountRequired: '应收金额不能为空',
  119 + receivedAmount: '实收金额',
  120 + receivedAmountPlaceholder: '必填,请填写实收金额',
  121 + receivedAmountRequired: '实收金额不能为空',
  122 + reserveDate: '预约日期',
  123 + reserveDatePlaceholder: '必填,请选择预约日期',
  124 + reserveDateRequired: '预约日期不能为空',
  125 + reserveTime: '预约时间',
  126 + reserveTimePlaceholder: '必填,请选择预约时间',
  127 + hour: '时',
  128 + remark: '备注',
  129 + remarkPlaceholder: '必填,请填写备注',
  130 + remarkRequired: '备注不能为空',
  131 + confirmDelete: '确定删除预约就餐?'
  132 + }
  133 + }
  134 +}
0 135 \ No newline at end of file
... ...
src/views/scm/reserveDiningManageList.vue 0 → 100644
  1 +<template>
  2 + <div class="reserve-dining-manage-container">
  3 + <el-row :gutter="20">
  4 + <el-col :span="4">
  5 + <el-card class="border-radius">
  6 + <div class="treeview attendance-staff">
  7 + <ul class="list-group text-center border-radius"
  8 + v-if="reserveDiningManageInfo.catalogs && reserveDiningManageInfo.catalogs.length > 0">
  9 + <li class="list-group-item node-orgTree" v-for="(item, index) in reserveDiningManageInfo.catalogs"
  10 + :key="index" @click="swatchReserveCatalog(item)"
  11 + :class="{ 'vc-node-selected': reserveDiningManageInfo.conditions.catalogId == item.catalogId }">
  12 + {{ item.name }}
  13 + </li>
  14 + </ul>
  15 + <ul class="list-group text-center border-radius" v-else>
  16 + <li class="list-group-item node-orgTree" @click="_addCatalog()">
  17 + {{ $t('reserveDiningManage.addCatalog') }}
  18 + </li>
  19 + </ul>
  20 + </div>
  21 + </el-card>
  22 + </el-col>
  23 + <el-col :span="20">
  24 + <el-card>
  25 + <div slot="header" class="text-left">
  26 + <span>{{ $t('reserveDiningManage.searchTitle') }}</span>
  27 + </div>
  28 + <el-row :gutter="20">
  29 + <el-col :span="6">
  30 + <el-input v-model="reserveDiningManageInfo.conditions.goodsId"
  31 + :placeholder="$t('reserveDiningManage.goodsIdPlaceholder')" clearable />
  32 + </el-col>
  33 + <el-col :span="6">
  34 + <el-input v-model="reserveDiningManageInfo.conditions.goodsName"
  35 + :placeholder="$t('reserveDiningManage.goodsNamePlaceholder')" clearable />
  36 + </el-col>
  37 + <el-col :span="6">
  38 + <el-select v-model="reserveDiningManageInfo.conditions.state"
  39 + :placeholder="$t('reserveDiningManage.statePlaceholder')" style="width:100%" clearable>
  40 + <el-option :label="$t('reserveDiningManage.stateNotOnline')" value="1001" />
  41 + <el-option :label="$t('reserveDiningManage.stateOnline')" value="2002" />
  42 + </el-select>
  43 + </el-col>
  44 + <el-col :span="6">
  45 + <el-button type="primary" @click="_queryReserveDiningMethod()" icon="el-icon-search">
  46 + {{ $t('common.search') }}
  47 + </el-button>
  48 + </el-col>
  49 + </el-row>
  50 + </el-card>
  51 +
  52 + <el-card class="margin-top">
  53 + <div slot="header" class="flex justify-between">
  54 + <span>{{ $t('reserveDiningManage.listTitle') }}</span>
  55 + <div style="float: right;">
  56 + <el-button type="primary" size="small" @click="_doOwnerDining()">
  57 + {{ $t('reserveDiningManage.diningStatistics') }}
  58 + </el-button>
  59 + <el-button type="primary" size="small" @click="_doDining()">
  60 + {{ $t('reserveDiningManage.dining') }}
  61 + </el-button>
  62 + <el-button type="primary" size="small" @click="_openAddReserveDiningModal()">
  63 + {{ $t('common.add') }}
  64 + </el-button>
  65 + </div>
  66 + </div>
  67 +
  68 + <el-table :data="reserveDiningManageInfo.reserveDinings" border style="width: 100%" v-loading="loading">
  69 + <el-table-column :label="$t('reserveDiningManage.goodsCover')" align="center">
  70 + <template slot-scope="scope">
  71 + <el-image style="width: 60px; height: 60px; border-radius: 5px;"
  72 + :src="scope.row.imgUrl || '/img/noPhoto.jpg'" fit="cover" />
  73 + </template>
  74 + </el-table-column>
  75 + <el-table-column :label="$t('reserveDiningManage.goodsName')" align="center">
  76 + <template slot-scope="scope">
  77 + {{ scope.row.goodsName }}({{ scope.row.goodsId }})
  78 + </template>
  79 + </el-table-column>
  80 + <el-table-column prop="paramsName" :label="$t('reserveDiningManage.params')" align="center" />
  81 + <el-table-column :label="$t('reserveDiningManage.reserveWay')" align="center">
  82 + <template slot-scope="scope">
  83 + {{ scope.row.paramWay == '1' ? $t('reserveDiningManage.day') : $t('reserveDiningManage.week') }}
  84 + </template>
  85 + </el-table-column>
  86 + <el-table-column prop="maxQuantity" :label="$t('reserveDiningManage.reserveCount')" align="center" />
  87 + <el-table-column prop="hoursMaxQuantity" :label="$t('reserveDiningManage.reserveQuantity')"
  88 + align="center" />
  89 + <el-table-column prop="price" :label="$t('reserveDiningManage.price')" align="center" />
  90 + <el-table-column :label="$t('reserveDiningManage.validDate')" align="center">
  91 + <template slot-scope="scope">
  92 + {{ scope.row.startDate }}~{{ scope.row.endDate }}
  93 + </template>
  94 + </el-table-column>
  95 + <el-table-column prop="startTime" :label="$t('reserveDiningManage.reserveStartTime')" align="center" />
  96 + <el-table-column prop="sort" :label="$t('reserveDiningManage.sort')" align="center" />
  97 + <el-table-column :label="$t('reserveDiningManage.state')" align="center">
  98 + <template slot-scope="scope">
  99 + {{ scope.row.state == '1001' ? $t('reserveDiningManage.stateNotOnline') :
  100 + $t('reserveDiningManage.stateOnline')}}
  101 + </template>
  102 + </el-table-column>
  103 + <el-table-column :label="$t('common.operation')" align="center" width="250">
  104 + <template slot-scope="scope">
  105 + <el-button size="mini" @click="_openReserveDiningPersonModel(scope.row)">
  106 + {{ $t('reserveDiningManage.reserveDining') }}
  107 + </el-button>
  108 + <el-button size="mini" type="primary" @click="_openEditReserveDiningModel(scope.row)">
  109 + {{ $t('common.edit') }}
  110 + </el-button>
  111 + <el-button size="mini" type="danger" @click="_openDeleteReserveDiningModel(scope.row)">
  112 + {{ $t('common.delete') }}
  113 + </el-button>
  114 + </template>
  115 + </el-table-column>
  116 + </el-table>
  117 +
  118 + <el-pagination class="pagination" @size-change="handleSizeChange" @current-change="handleCurrentChange"
  119 + :current-page="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size"
  120 + layout="total, sizes, prev, pager, next, jumper" :total="page.total" />
  121 + </el-card>
  122 + </el-col>
  123 + </el-row>
  124 +
  125 + <add-reserve-dining-person ref="addReserveDiningPerson" @success="handleSuccess" />
  126 + <delete-reserve-dining ref="deleteReserveDining" @success="handleSuccess" />
  127 + </div>
  128 +</template>
  129 +
  130 +<script>
  131 +import { getCommunityId } from '@/api/community/communityApi'
  132 +import { listReserveGoods, listReserveCatalog } from '@/api/scm/reserveDiningManageApi'
  133 +import AddReserveDiningPerson from '@/components/scm/addReserveDiningPerson'
  134 +import DeleteReserveDining from '@/components/scm/deleteReserveDining'
  135 +
  136 +export default {
  137 + name: 'ReserveDiningManageList',
  138 + components: {
  139 + AddReserveDiningPerson,
  140 + DeleteReserveDining
  141 + },
  142 + data() {
  143 + return {
  144 + loading: false,
  145 + reserveDiningManageInfo: {
  146 + reserveDinings: [],
  147 + catalogs: [],
  148 + conditions: {
  149 + goodsId: '',
  150 + goodsName: '',
  151 + type: '1001',
  152 + state: '',
  153 + catalogId: '',
  154 + communityId: getCommunityId(),
  155 + page: 1,
  156 + row: 10
  157 + }
  158 + },
  159 + page: {
  160 + current: 1,
  161 + size: 10,
  162 + total: 0
  163 + }
  164 + }
  165 + },
  166 + created() {
  167 + this._listReserveCatalogs()
  168 + },
  169 + methods: {
  170 + async _listReserveDinings(page, rows) {
  171 + try {
  172 + this.loading = true
  173 + this.reserveDiningManageInfo.conditions.page = page || this.page.current
  174 + this.reserveDiningManageInfo.conditions.row = rows || this.page.size
  175 +
  176 + const { data, total } = await listReserveGoods(this.reserveDiningManageInfo.conditions)
  177 + this.reserveDiningManageInfo.reserveDinings = data
  178 + this.page.total = total
  179 + } catch (error) {
  180 + console.error(error)
  181 + this.$message.error(this.$t('reserveDiningManage.fetchError'))
  182 + } finally {
  183 + this.loading = false
  184 + }
  185 + },
  186 + async _listReserveCatalogs() {
  187 + try {
  188 + const params = {
  189 + page: 1,
  190 + row: 100,
  191 + communityId: getCommunityId(),
  192 + type: '1001'
  193 + }
  194 +
  195 + const { data } = await listReserveCatalog(params)
  196 + this.reserveDiningManageInfo.catalogs = data
  197 + if (data && data.length > 0) {
  198 + this.swatchReserveCatalog(data[0])
  199 + }
  200 + } catch (error) {
  201 + console.error(error)
  202 + }
  203 + },
  204 + swatchReserveCatalog(item) {
  205 + this.reserveDiningManageInfo.conditions.catalogId = item.catalogId
  206 + this._listReserveDinings()
  207 + },
  208 + _queryReserveDiningMethod() {
  209 + this.page.current = 1
  210 + this._listReserveDinings()
  211 + },
  212 + _openAddReserveDiningModal() {
  213 + if (!this.reserveDiningManageInfo.conditions.catalogId) {
  214 + this.$message.warning(this.$t('reserveDiningManage.addCatalogFirst'))
  215 + return
  216 + }
  217 + this.$router.push(`/views/scm/addReserveDining?catalogId=${this.reserveDiningManageInfo.conditions.catalogId}`)
  218 + },
  219 + _openEditReserveDiningModel(reserveDining) {
  220 + this.$router.push(`/views/scm/editReserveDining?goodsId=${reserveDining.goodsId}`)
  221 + },
  222 + _openDeleteReserveDiningModel(reserveDining) {
  223 + this.$refs.deleteReserveDining.open(reserveDining)
  224 + },
  225 + _openReserveDiningPersonModel(reserveDining) {
  226 + this.$refs.addReserveDiningPerson.open(reserveDining)
  227 + },
  228 + _addCatalog() {
  229 + this.$router.push('/scm/reserveCatalogManage?tab=reserveCatalog')
  230 + },
  231 + _doDining() {
  232 + if (!this.reserveDiningManageInfo.reserveDinings || this.reserveDiningManageInfo.reserveDinings.length < 1) {
  233 + this.$message.warning(this.$t('reserveDiningManage.addFirst'))
  234 + return
  235 + }
  236 + this.$router.push('/views/scm/doDining')
  237 + },
  238 + _doOwnerDining() {
  239 + this.$router.push('/views/scm/ownerDining')
  240 + },
  241 + handleSuccess() {
  242 + this._listReserveDinings()
  243 + },
  244 + handleSizeChange(val) {
  245 + this.page.size = val
  246 + this._listReserveDinings()
  247 + },
  248 + handleCurrentChange(val) {
  249 + this.page.current = val
  250 + this._listReserveDinings()
  251 + }
  252 + }
  253 +}
  254 +</script>
  255 +
  256 +<style lang="scss" scoped>
  257 +.reserve-dining-manage-container {
  258 + padding: 20px;
  259 +
  260 + .border-radius {
  261 + border-radius: 4px;
  262 + }
  263 +
  264 + .margin-top {
  265 + margin-top: 20px;
  266 + }
  267 +
  268 + .pagination {
  269 + margin-top: 20px;
  270 + text-align: right;
  271 + }
  272 +
  273 + .list-group {
  274 + list-style: none;
  275 + padding: 0;
  276 + margin: 0;
  277 +
  278 + .list-group-item {
  279 + padding: 10px 15px;
  280 + border: 1px solid #ddd;
  281 + margin-bottom: -1px;
  282 + cursor: pointer;
  283 +
  284 + &:hover {
  285 + background-color: #f5f5f5;
  286 + }
  287 + }
  288 +
  289 + .vc-node-selected {
  290 + background-color: #409EFF;
  291 + color: white;
  292 + }
  293 + }
  294 +}
  295 +</style>
0 296 \ No newline at end of file
... ...
src/views/scm/reserveOrderLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + reserveOrder: {
  4 + diningOrder: 'Dining Order',
  5 + serviceOrder: 'Service Order',
  6 + searchCondition: 'Search Condition',
  7 + selectAppointmentTime: 'Select Appointment Time',
  8 + selectAppointmentPerson: 'Select Appointment Person',
  9 + selectAppointmentPhone: 'Select Appointment Phone',
  10 + selectStatus: 'Select Status',
  11 + allStatus: 'All Status',
  12 + successStatus: 'Success',
  13 + failStatus: 'Failed',
  14 + waitAuditStatus: 'Wait Audit',
  15 + waitPayStatus: 'Wait Pay',
  16 + inputName: 'Input Name',
  17 + orderId: 'Order ID',
  18 + goodsName: 'Goods Name',
  19 + appointmentPerson: 'Appointment Person',
  20 + appointmentPhone: 'Appointment Phone',
  21 + appointmentDate: 'Appointment Date',
  22 + appointmentTime: 'Appointment Time',
  23 + hour: 'hour',
  24 + unit: 'unit',
  25 + receivableAmount: 'Receivable Amount',
  26 + receivedAmount: 'Received Amount',
  27 + payWay: 'Pay Way',
  28 + status: 'Status',
  29 + createTime: 'Create Time',
  30 + remark: 'Remark',
  31 + cancelAppointment: 'Cancel Appointment',
  32 + confirmCancel: 'Confirm to cancel this appointment?',
  33 + cancelSuccess: 'Cancel success',
  34 + cancelError: 'Cancel failed',
  35 + fetchError: 'Fetch data failed'
  36 + }
  37 + },
  38 + zh: {
  39 + reserveOrder: {
  40 + diningOrder: '就餐订单',
  41 + serviceOrder: '服务订单',
  42 + searchCondition: '查询条件',
  43 + selectAppointmentTime: '请选择预约时间',
  44 + selectAppointmentPerson: '请选择预约人',
  45 + selectAppointmentPhone: '请选择预约电话',
  46 + selectStatus: '请选择状态',
  47 + allStatus: '全部状态',
  48 + successStatus: '预约成功',
  49 + failStatus: '预约失败',
  50 + waitAuditStatus: '待审核',
  51 + waitPayStatus: '待支付',
  52 + inputName: '请输入名称',
  53 + orderId: '订单编号',
  54 + goodsName: '名称',
  55 + appointmentPerson: '预约人',
  56 + appointmentPhone: '预约电话',
  57 + appointmentDate: '预约日期',
  58 + appointmentTime: '预约时间',
  59 + hour: '时',
  60 + unit: '个',
  61 + receivableAmount: '应收金额',
  62 + receivedAmount: '实收金额',
  63 + payWay: '支付方式',
  64 + status: '状态',
  65 + createTime: '预约时间',
  66 + remark: '备注',
  67 + cancelAppointment: '取消预约',
  68 + confirmCancel: '确定要取消此预约吗?',
  69 + cancelSuccess: '取消成功',
  70 + cancelError: '取消失败',
  71 + fetchError: '获取数据失败'
  72 + }
  73 + }
  74 +}
0 75 \ No newline at end of file
... ...
src/views/scm/reserveOrderList.vue 0 → 100644
  1 +<template>
  2 + <div class="reserve-order-container">
  3 + <el-row :gutter="20">
  4 + <el-col :span="4">
  5 + <el-card class="tree-card">
  6 + <ul class="tree-list">
  7 + <li class="tree-item" :class="{ 'active': reserveOrderInfo.conditions.type === '1001' }"
  8 + @click="_changeType('1001')">
  9 + {{ $t('reserveOrder.diningOrder') }}
  10 + </li>
  11 + <li class="tree-item" :class="{ 'active': reserveOrderInfo.conditions.type === '2002' }"
  12 + @click="_changeType('2002')">
  13 + {{ $t('reserveOrder.serviceOrder') }}
  14 + </li>
  15 + </ul>
  16 + </el-card>
  17 + </el-col>
  18 + <el-col :span="20">
  19 + <el-card>
  20 + <div slot="header" class="text-left">
  21 + <span>{{ $t('reserveOrder.searchCondition') }}</span>
  22 + </div>
  23 + <el-row :gutter="20">
  24 + <el-col :span="6">
  25 + <el-input v-model="reserveOrderInfo.conditions.appointmentTime"
  26 + :placeholder="$t('reserveOrder.selectAppointmentTime')" />
  27 + </el-col>
  28 + <el-col :span="6">
  29 + <el-input v-model="reserveOrderInfo.conditions.personName"
  30 + :placeholder="$t('reserveOrder.selectAppointmentPerson')" />
  31 + </el-col>
  32 + <el-col :span="6">
  33 + <el-input v-model="reserveOrderInfo.conditions.personTel"
  34 + :placeholder="$t('reserveOrder.selectAppointmentPhone')" />
  35 + </el-col>
  36 + <el-col :span="6">
  37 + <el-button type="primary" @click="_queryReserveOrderPersonMethod">
  38 + <i class="el-icon-search"></i>
  39 + {{ $t('common.search') }}
  40 + </el-button>
  41 + </el-col>
  42 + </el-row>
  43 + <el-row :gutter="20" style="margin-top: 20px;">
  44 + <el-col :span="6">
  45 + <el-select v-model="reserveOrderInfo.conditions.state" :placeholder="$t('reserveOrder.selectStatus')"
  46 + style="width:100%">
  47 + <el-option :label="$t('reserveOrder.allStatus')" value="" />
  48 + <el-option :label="$t('reserveOrder.successStatus')" value="S" />
  49 + <el-option :label="$t('reserveOrder.failStatus')" value="F" />
  50 + <el-option :label="$t('reserveOrder.waitAuditStatus')" value="W" />
  51 + <el-option :label="$t('reserveOrder.waitPayStatus')" value="F" />
  52 + </el-select>
  53 + </el-col>
  54 + <el-col :span="6">
  55 + <el-input v-model="reserveOrderInfo.conditions.goodsNameLike"
  56 + :placeholder="$t('reserveOrder.inputName')" />
  57 + </el-col>
  58 + </el-row>
  59 + </el-card>
  60 +
  61 + <el-card style="margin-top: 20px;">
  62 + <div slot="header" class="flex justify-between">
  63 + <span v-if="reserveOrderInfo.conditions.type === '1001'">
  64 + {{ $t('reserveOrder.diningOrder') }}
  65 + </span>
  66 + <span v-else>
  67 + {{ $t('reserveOrder.serviceOrder') }}
  68 + </span>
  69 + </div>
  70 + <el-table :data="reserveOrderInfo.orders" border style="width: 100%" v-loading="loading">
  71 + <el-table-column prop="orderId" :label="$t('reserveOrder.orderId')" align="center" />
  72 + <el-table-column prop="goodsName" :label="$t('reserveOrder.goodsName')" align="center" />
  73 + <el-table-column prop="personName" :label="$t('reserveOrder.appointmentPerson')" align="center" />
  74 + <el-table-column prop="personTel" :label="$t('reserveOrder.appointmentPhone')" align="center" />
  75 + <el-table-column prop="appointmentTime" :label="$t('reserveOrder.appointmentDate')" align="center" />
  76 + <el-table-column :label="$t('reserveOrder.appointmentTime')" align="center">
  77 + <template slot-scope="scope">
  78 + <span v-for="(time, index) in scope.row.times" :key="index">
  79 + {{ time.hours }}{{ $t('reserveOrder.hour') }}
  80 + <span v-if="scope.row.type === '1001'">({{ time.quantity }}{{ $t('reserveOrder.unit') }})</span>
  81 + <span v-if="index < scope.row.times.length - 1">,</span>
  82 + </span>
  83 + </template>
  84 + </el-table-column>
  85 + <el-table-column prop="receivableAmount" :label="$t('reserveOrder.receivableAmount')" align="center" />
  86 + <el-table-column prop="receivedAmount" :label="$t('reserveOrder.receivedAmount')" align="center" />
  87 + <el-table-column prop="payWayName" :label="$t('reserveOrder.payWay')" align="center" />
  88 + <el-table-column prop="stateName" :label="$t('reserveOrder.status')" align="center" />
  89 + <el-table-column prop="createTime" :label="$t('reserveOrder.createTime')" align="center" />
  90 + <el-table-column prop="remark" :label="$t('reserveOrder.remark')" align="center" />
  91 + <el-table-column :label="$t('common.operation')" align="center" width="150">
  92 + <template slot-scope="scope">
  93 + <el-button v-if="scope.row.state === 'S'" type="text" size="small"
  94 + @click="_openDeleteReserveOrderPersonModel(scope.row)">
  95 + {{ $t('reserveOrder.cancelAppointment') }}
  96 + </el-button>
  97 + </template>
  98 + </el-table-column>
  99 + </el-table>
  100 + <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
  101 + :current-page="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size"
  102 + layout="total, sizes, prev, pager, next, jumper" :total="page.total" style="margin-top: 20px;" />
  103 + </el-card>
  104 + </el-col>
  105 + </el-row>
  106 +
  107 + <delete-reserve-order-person ref="deleteReserveOrderPerson" @success="handleSuccess" />
  108 + </div>
  109 +</template>
  110 +
  111 +<script>
  112 +import { listReserveGoodsOrder } from '@/api/scm/reserveOrderApi'
  113 +import DeleteReserveOrderPerson from '@/components/scm/deleteReserveOrderPerson'
  114 +import { getCommunityId } from '@/api/community/communityApi'
  115 +
  116 +export default {
  117 + name: 'ReserveOrderList',
  118 + components: {
  119 + DeleteReserveOrderPerson
  120 + },
  121 + data() {
  122 + return {
  123 + loading: false,
  124 + reserveOrderInfo: {
  125 + orders: [],
  126 + conditions: {
  127 + type: '1001',
  128 + goodsNameLike: '',
  129 + personName: '',
  130 + personTel: '',
  131 + appointmentTime: '',
  132 + state: '',
  133 + communityId: ''
  134 + }
  135 + },
  136 + page: {
  137 + current: 1,
  138 + size: 10,
  139 + total: 0
  140 + }
  141 + }
  142 + },
  143 + created() {
  144 + this.reserveOrderInfo.conditions.communityId = getCommunityId()
  145 + this._listReserveOrderPersons(this.page.current, this.page.size)
  146 + },
  147 + methods: {
  148 + async _listReserveOrderPersons(page, size) {
  149 + try {
  150 + this.loading = true
  151 + const params = {
  152 + ...this.reserveOrderInfo.conditions,
  153 + page,
  154 + row: size
  155 + }
  156 + const { data, total } = await listReserveGoodsOrder(params)
  157 + this.reserveOrderInfo.orders = data
  158 + this.page.total = total
  159 + } catch (error) {
  160 + this.$message.error(this.$t('reserveOrder.fetchError'))
  161 + } finally {
  162 + this.loading = false
  163 + }
  164 + },
  165 + _openDeleteReserveOrderPersonModel(row) {
  166 + this.$refs.deleteReserveOrderPerson.open(row)
  167 + },
  168 + _queryReserveOrderPersonMethod() {
  169 + this.page.current = 1
  170 + this._listReserveOrderPersons(this.page.current, this.page.size)
  171 + },
  172 + _changeType(type) {
  173 + this.reserveOrderInfo.conditions.type = type
  174 + this._listReserveOrderPersons(this.page.current, this.page.size)
  175 + },
  176 + handleSuccess() {
  177 + this._listReserveOrderPersons(this.page.current, this.page.size)
  178 + },
  179 + handleSizeChange(val) {
  180 + this.page.size = val
  181 + this._listReserveOrderPersons(this.page.current, this.page.size)
  182 + },
  183 + handleCurrentChange(val) {
  184 + this.page.current = val
  185 + this._listReserveOrderPersons(this.page.current, this.page.size)
  186 + }
  187 + }
  188 +}
  189 +</script>
  190 +
  191 +<style lang="scss" scoped>
  192 +.reserve-order-container {
  193 + padding: 20px;
  194 +
  195 + .tree-card {
  196 + height: 100%;
  197 +
  198 + .tree-list {
  199 + list-style: none;
  200 + padding: 0;
  201 + margin: 0;
  202 +
  203 + .tree-item {
  204 + padding: 10px;
  205 + cursor: pointer;
  206 + border-radius: 4px;
  207 + margin-bottom: 5px;
  208 +
  209 + &:hover {
  210 + background-color: #f5f7fa;
  211 + }
  212 +
  213 + &.active {
  214 + background-color: #409eff;
  215 + color: white;
  216 + }
  217 + }
  218 + }
  219 + }
  220 +}
  221 +</style>
0 222 \ No newline at end of file
... ...
src/views/scm/reserveParamsManageLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + reserveParamsManage: {
  4 + search: {
  5 + title: 'Search Conditions',
  6 + namePlaceholder: 'Please enter parameter name'
  7 + },
  8 + list: {
  9 + title: 'Reservation Parameters'
  10 + },
  11 + table: {
  12 + name: 'Parameter Name',
  13 + paramWay: 'Reservation Method',
  14 + startTime: 'Start Time',
  15 + maxQuantity: 'Max Quantity',
  16 + hoursMaxQuantity: 'Quantity Per Time',
  17 + operation: 'Operation'
  18 + },
  19 + day: 'Day',
  20 + week: 'Week',
  21 + dayUnit: 'th',
  22 + hour: 'o\'clock',
  23 + setTime: 'Set Time',
  24 + deleteTitle: 'Delete Confirmation',
  25 + deleteConfirm: 'Warning',
  26 + deleteTip: 'Are you sure to delete this reservation parameter? This operation cannot be undone!',
  27 + setTimeTitle: 'Set Open Time',
  28 + selectStatus: 'Select Status',
  29 + canReserve: 'Available',
  30 + cannotReserve: 'Unavailable',
  31 + addTitle: 'Add Reservation Parameter',
  32 + editTitle: 'Edit Reservation Parameter',
  33 + name: 'Parameter Name',
  34 + namePlaceholder: 'Please enter parameter name',
  35 + nameRequired: 'Parameter name is required',
  36 + paramWay: 'Reservation Method',
  37 + paramWayPlaceholder: 'Please select reservation method',
  38 + paramWayRequired: 'Reservation method is required',
  39 + days: 'Days',
  40 + weekdays: 'Weekdays',
  41 + startTime: 'Start Time',
  42 + startTimePlaceholder: 'Please select start time',
  43 + startTimeRequired: 'Start time is required',
  44 + maxQuantity: 'Max Quantity',
  45 + maxQuantityPlaceholder: 'Please enter max quantity',
  46 + maxQuantityRequired: 'Max quantity is required',
  47 + hoursMaxQuantity: 'Quantity Per Time',
  48 + hoursMaxQuantityPlaceholder: 'Please enter quantity per time',
  49 + hoursMaxQuantityRequired: 'Quantity per time is required',
  50 + fetchError: 'Failed to fetch reservation parameters'
  51 + }
  52 + },
  53 + zh: {
  54 + reserveParamsManage: {
  55 + search: {
  56 + title: '查询条件',
  57 + namePlaceholder: '请输入参数名称'
  58 + },
  59 + list: {
  60 + title: '预约参数'
  61 + },
  62 + table: {
  63 + name: '参数名称',
  64 + paramWay: '预约方式',
  65 + startTime: '开始时间',
  66 + maxQuantity: '预约次数',
  67 + hoursMaxQuantity: '预约数量',
  68 + operation: '操作'
  69 + },
  70 + day: '日',
  71 + week: '周',
  72 + dayUnit: '日',
  73 + hour: '点',
  74 + setTime: '设置时间',
  75 + deleteTitle: '删除确认',
  76 + deleteConfirm: '警告',
  77 + deleteTip: '确定删除该预约参数吗?此操作不可撤销!',
  78 + setTimeTitle: '设置开放时间',
  79 + selectStatus: '选择状态',
  80 + canReserve: '可预约',
  81 + cannotReserve: '不可预约',
  82 + addTitle: '添加预约参数',
  83 + editTitle: '编辑预约参数',
  84 + name: '参数名称',
  85 + namePlaceholder: '请输入参数名称',
  86 + nameRequired: '参数名称不能为空',
  87 + paramWay: '预约方式',
  88 + paramWayPlaceholder: '请选择预约方式',
  89 + paramWayRequired: '预约方式不能为空',
  90 + days: '日',
  91 + weekdays: '工作日',
  92 + startTime: '开始时间',
  93 + startTimePlaceholder: '请选择开始时间',
  94 + startTimeRequired: '开始时间不能为空',
  95 + maxQuantity: '预约次数',
  96 + maxQuantityPlaceholder: '请输入预约次数',
  97 + maxQuantityRequired: '预约次数不能为空',
  98 + hoursMaxQuantity: '预约数量',
  99 + hoursMaxQuantityPlaceholder: '请输入预约数量',
  100 + hoursMaxQuantityRequired: '预约数量不能为空',
  101 + fetchError: '获取预约参数失败'
  102 + }
  103 + }
  104 +}
0 105 \ No newline at end of file
... ...
src/views/scm/reserveParamsManageList.vue 0 → 100644
  1 +<template>
  2 + <div class="reserve-params-manage-container">
  3 + <!-- 查询条件 -->
  4 + <el-card class="search-wrapper">
  5 + <div slot="header" class="text-left">
  6 + <span>{{ $t('reserveParamsManage.search.title') }}</span>
  7 + </div>
  8 + <el-row :gutter="20">
  9 + <el-col :span="6">
  10 + <el-input v-model="searchForm.name" :placeholder="$t('reserveParamsManage.search.namePlaceholder')"
  11 + clearable />
  12 + </el-col>
  13 + <el-col :span="2">
  14 + <el-button type="primary" @click="handleSearch">
  15 + <i class="el-icon-search"></i>
  16 + {{ $t('common.search') }}
  17 + </el-button>
  18 + </el-col>
  19 + </el-row>
  20 + </el-card>
  21 +
  22 + <!-- 数据列表 -->
  23 + <el-card class="list-wrapper">
  24 + <div slot="header" class="flex justify-between">
  25 + <span>{{ $t('reserveParamsManage.list.title') }}</span>
  26 + <el-button type="primary" size="mini" @click="handleAdd">
  27 + <i class="el-icon-plus"></i>
  28 + {{ $t('common.add') }}
  29 + </el-button>
  30 + </div>
  31 +
  32 + <el-table v-loading="loading" :data="tableData" border style="width: 100%">
  33 + <el-table-column prop="name" :label="$t('reserveParamsManage.table.name')" align="center" />
  34 + <el-table-column prop="paramWay" :label="$t('reserveParamsManage.table.paramWay')" align="center">
  35 + <template slot-scope="scope">
  36 + {{ scope.row.paramWay === '1' ? $t('reserveParamsManage.day') : $t('reserveParamsManage.week') }}
  37 + </template>
  38 + </el-table-column>
  39 + <el-table-column prop="startTime" :label="$t('reserveParamsManage.table.startTime')" align="center" />
  40 + <el-table-column prop="maxQuantity" :label="$t('reserveParamsManage.table.maxQuantity')" align="center" />
  41 + <el-table-column prop="hoursMaxQuantity" :label="$t('reserveParamsManage.table.hoursMaxQuantity')"
  42 + align="center" />
  43 + <el-table-column :label="$t('common.operation')" align="center" width="300" fixed="right">
  44 + <template slot-scope="scope">
  45 + <el-button size="mini" type="primary" @click="handleSetTime(scope.row)">
  46 + {{ $t('reserveParamsManage.setTime') }}
  47 + </el-button>
  48 + <el-button size="mini" type="warning" @click="handleEdit(scope.row)">
  49 + {{ $t('common.edit') }}
  50 + </el-button>
  51 + <el-button size="mini" type="danger" @click="handleDelete(scope.row)">
  52 + {{ $t('common.delete') }}
  53 + </el-button>
  54 + </template>
  55 + </el-table-column>
  56 + </el-table>
  57 +
  58 + <el-pagination :current-page.sync="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size"
  59 + :total="page.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
  60 + @current-change="handleCurrentChange" />
  61 + </el-card>
  62 +
  63 + <!-- 子组件 -->
  64 + <add-reserve-params ref="addReserveParams" @success="handleSuccess" />
  65 + <edit-reserve-params ref="editReserveParams" @success="handleSuccess" />
  66 + <delete-reserve-params ref="deleteReserveParams" @success="handleSuccess" />
  67 + <edit-reserve-params-open-time ref="editReserveParamsOpenTime" @success="handleSuccess" />
  68 + </div>
  69 +</template>
  70 +
  71 +<script>
  72 +import { listReserveParams } from '@/api/scm/reserveParamsManageApi'
  73 +import { getCommunityId } from '@/api/community/communityApi'
  74 +import AddReserveParams from '@/components/scm/addReserveParams'
  75 +import EditReserveParams from '@/components/scm/editReserveParams'
  76 +import DeleteReserveParams from '@/components/scm/deleteReserveParams'
  77 +import EditReserveParamsOpenTime from '@/components/scm/editReserveParamsOpenTime'
  78 +
  79 +export default {
  80 + name: 'ReserveParamsManageList',
  81 + components: {
  82 + AddReserveParams,
  83 + EditReserveParams,
  84 + DeleteReserveParams,
  85 + EditReserveParamsOpenTime
  86 + },
  87 + data() {
  88 + return {
  89 + loading: false,
  90 + searchForm: {
  91 + name: ''
  92 + },
  93 + tableData: [],
  94 + page: {
  95 + current: 1,
  96 + size: 10,
  97 + total: 0
  98 + },
  99 + communityId: ''
  100 + }
  101 + },
  102 + created() {
  103 + this.communityId = getCommunityId()
  104 + this.getList()
  105 + },
  106 + methods: {
  107 + async getList() {
  108 + try {
  109 + this.loading = true
  110 + const params = {
  111 + page: this.page.current,
  112 + row: this.page.size,
  113 + name: this.searchForm.name,
  114 + communityId: this.communityId
  115 + }
  116 + const { data, total } = await listReserveParams(params)
  117 + this.tableData = data
  118 + this.page.total = total
  119 + } catch (error) {
  120 + this.$message.error(this.$t('reserveParamsManage.fetchError'))
  121 + } finally {
  122 + this.loading = false
  123 + }
  124 + },
  125 + handleSearch() {
  126 + this.page.current = 1
  127 + this.getList()
  128 + },
  129 + handleAdd() {
  130 + this.$refs.addReserveParams.open()
  131 + },
  132 + handleEdit(row) {
  133 + this.$refs.editReserveParams.open(row)
  134 + },
  135 + handleSetTime(row) {
  136 + this.$refs.editReserveParamsOpenTime.open(row)
  137 + },
  138 + handleDelete(row) {
  139 + this.$refs.deleteReserveParams.open(row)
  140 + },
  141 + handleSuccess() {
  142 + this.getList()
  143 + },
  144 + handleSizeChange(val) {
  145 + this.page.size = val
  146 + this.getList()
  147 + },
  148 + handleCurrentChange(val) {
  149 + this.page.current = val
  150 + this.getList()
  151 + }
  152 + }
  153 +}
  154 +</script>
  155 +
  156 +<style lang="scss" scoped>
  157 +.reserve-params-manage-container {
  158 + padding: 20px;
  159 +
  160 + .search-wrapper {
  161 + margin-bottom: 20px;
  162 + }
  163 +
  164 + .list-wrapper {
  165 + margin-bottom: 20px;
  166 + }
  167 +
  168 + .el-pagination {
  169 + margin-top: 20px;
  170 + text-align: right;
  171 + }
  172 +}
  173 +</style>
0 174 \ No newline at end of file
... ...
src/views/scm/reserveServiceManageLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + reserveServiceManage: {
  4 + searchCondition: 'Search Condition',
  5 + goodsIdPlaceholder: 'Please enter service ID',
  6 + goodsNamePlaceholder: 'Please enter service name',
  7 + statePlaceholder: 'Please select status',
  8 + stateOffShelf: 'Off Shelf',
  9 + stateOnShelf: 'On Shelf',
  10 + reserveService: 'Reserve Service',
  11 + addService: 'Add Service',
  12 + serviceCover: 'Service Cover',
  13 + nameAndId: 'Name(ID)',
  14 + params: 'Parameters',
  15 + reserveWay: 'Reserve Way',
  16 + day: 'Day',
  17 + week: 'Week',
  18 + reserveCount: 'Reserve Count',
  19 + reserveQuantity: 'Reserve Quantity',
  20 + doorFee: 'Door Fee',
  21 + validity: 'Validity',
  22 + reserveStartTime: 'Reserve Start Time',
  23 + sort: 'Sort',
  24 + state: 'Status',
  25 + offShelf: 'Off Shelf',
  26 + onShelf: 'On Shelf',
  27 + addCatalog: 'Add Catalog',
  28 + addCatalogFirst: 'Please add catalog first'
  29 + },
  30 + addReserveServicePerson: {
  31 + reserveService: 'Reserve Service',
  32 + personName: 'Reserve Person',
  33 + personNamePlaceholder: 'Required, please enter reserve person',
  34 + personTel: 'Reserve Tel',
  35 + personTelPlaceholder: 'Required, please enter reserve tel',
  36 + payWay: 'Payment Way',
  37 + payWayPlaceholder: 'Please select payment way',
  38 + cash: 'Cash',
  39 + wechat: 'WeChat',
  40 + alipay: 'Alipay',
  41 + receivableAmount: 'Receivable Amount',
  42 + receivableAmountPlaceholder: 'Required, please enter receivable amount',
  43 + receivedAmount: 'Received Amount',
  44 + receivedAmountPlaceholder: 'Required, please enter received amount',
  45 + appointmentTime: 'Appointment Time',
  46 + appointmentTimePlaceholder: 'Required, please select appointment time',
  47 + openTime: 'Open Time',
  48 + openTimePlaceholder: 'Required, please select open time',
  49 + hour: ' o\'clock',
  50 + remark: 'Remark',
  51 + remarkPlaceholder: 'Required, please enter remark',
  52 + personNameRequired: 'Reserve person is required',
  53 + personNameMaxLength: 'Reserve person cannot exceed 64 characters',
  54 + personTelRequired: 'Reserve tel is required',
  55 + personTelMaxLength: 'Reserve tel cannot exceed 11 characters',
  56 + appointmentTimeRequired: 'Appointment time is required',
  57 + receivableAmountRequired: 'Receivable amount is required',
  58 + receivedAmountRequired: 'Received amount is required',
  59 + payWayRequired: 'Payment way is required',
  60 + remarkRequired: 'Remark is required',
  61 + openTimeRequired: 'Open time is required'
  62 + },
  63 + deleteReserveDining: {
  64 + confirmTitle: 'Please confirm your operation!',
  65 + confirmContent: 'Confirm to delete reserve service'
  66 + }
  67 + },
  68 + zh: {
  69 + reserveServiceManage: {
  70 + searchCondition: '查询条件',
  71 + goodsIdPlaceholder: '请输入服务ID',
  72 + goodsNamePlaceholder: '请输入服务名称',
  73 + statePlaceholder: '请选择状态',
  74 + stateOffShelf: '未上架',
  75 + stateOnShelf: '上架',
  76 + reserveService: '预约服务',
  77 + addService: '添加服务',
  78 + serviceCover: '服务封面',
  79 + nameAndId: '名称(编号)',
  80 + params: '参数',
  81 + reserveWay: '预约方式',
  82 + day: '日',
  83 + week: '周',
  84 + reserveCount: '预约次数',
  85 + reserveQuantity: '预约数量',
  86 + doorFee: '上门费',
  87 + validity: '有效期',
  88 + reserveStartTime: '开始预约时间',
  89 + sort: '排序',
  90 + state: '状态',
  91 + offShelf: '未上架',
  92 + onShelf: '上架',
  93 + addCatalog: '添加目录',
  94 + addCatalogFirst: '请先添加目录'
  95 + },
  96 + addReserveServicePerson: {
  97 + reserveService: '预约服务',
  98 + personName: '预约人',
  99 + personNamePlaceholder: '必填,请填写预约人',
  100 + personTel: '预约电话',
  101 + personTelPlaceholder: '必填,请填写预约电话',
  102 + payWay: '支付方式',
  103 + payWayPlaceholder: '请选择支付方式',
  104 + cash: '现金',
  105 + wechat: '微信',
  106 + alipay: '支付宝',
  107 + receivableAmount: '应收金额',
  108 + receivableAmountPlaceholder: '必填,请填写应收金额',
  109 + receivedAmount: '实收金额',
  110 + receivedAmountPlaceholder: '必填,请填写实收金额',
  111 + appointmentTime: '预约日期',
  112 + appointmentTimePlaceholder: '必填,请选择预约日期',
  113 + openTime: '预约时间',
  114 + openTimePlaceholder: '必填,请选择预约时间',
  115 + hour: '时',
  116 + remark: '备注',
  117 + remarkPlaceholder: '必填,请填写备注',
  118 + personNameRequired: '预约人不能为空',
  119 + personNameMaxLength: '预约人不能超过64个字符',
  120 + personTelRequired: '预约电话不能为空',
  121 + personTelMaxLength: '预约电话不能超过11个字符',
  122 + appointmentTimeRequired: '预约时间不能为空',
  123 + receivableAmountRequired: '应收金额不能为空',
  124 + receivedAmountRequired: '实收金额不能为空',
  125 + payWayRequired: '支付方式不能为空',
  126 + remarkRequired: '备注不能为空',
  127 + openTimeRequired: '预约时间不能为空'
  128 + },
  129 + deleteReserveDining: {
  130 + confirmTitle: '请确认您的操作!',
  131 + confirmContent: '确定删除预约服务'
  132 + }
  133 + }
  134 +}
0 135 \ No newline at end of file
... ...
src/views/scm/reserveServiceManageList.vue 0 → 100644
  1 +<template>
  2 + <div class="reserve-service-manage-container">
  3 + <el-row :gutter="20">
  4 + <el-col :span="4">
  5 + <el-card class="tree-card">
  6 + <div class="treeview attendance-staff">
  7 + <ul class="list-group text-center border-radius"
  8 + v-if="reserveServiceManageInfo.catalogs && reserveServiceManageInfo.catalogs.length > 0">
  9 + <template v-for="(item, index) in reserveServiceManageInfo.catalogs">
  10 + <li class="list-group-item node-orgTree" :key="index" @click="swatchReserveCatalog(item)"
  11 + :class="{ 'vc-node-selected': reserveServiceManageInfo.conditions.catalogId == item.catalogId }">
  12 + {{ item.name }}
  13 + </li>
  14 + </template>
  15 + </ul>
  16 + <ul class="list-group text-center border-radius" v-else>
  17 + <li class="list-group-item node-orgTree" @click="_addCatalog()">
  18 + {{ $t('reserveServiceManage.addCatalog') }}
  19 + </li>
  20 + </ul>
  21 + </div>
  22 + </el-card>
  23 + </el-col>
  24 + <el-col :span="20">
  25 + <el-card>
  26 + <div slot="header" class="text-left">
  27 + <span>{{ $t('reserveServiceManage.searchCondition') }}</span>
  28 + </div>
  29 + <el-row :gutter="20">
  30 + <el-col :span="6">
  31 + <el-input :placeholder="$t('reserveServiceManage.goodsIdPlaceholder')"
  32 + v-model="reserveServiceManageInfo.conditions.goodsId">
  33 + </el-input>
  34 + </el-col>
  35 + <el-col :span="6">
  36 + <el-input :placeholder="$t('reserveServiceManage.goodsNamePlaceholder')"
  37 + v-model="reserveServiceManageInfo.conditions.goodsName">
  38 + </el-input>
  39 + </el-col>
  40 + <el-col :span="6">
  41 + <el-select v-model="reserveServiceManageInfo.conditions.state"
  42 + :placeholder="$t('reserveServiceManage.statePlaceholder')" style="width:100%">
  43 + <el-option :label="$t('reserveServiceManage.stateOffShelf')" value="1001">
  44 + </el-option>
  45 + <el-option :label="$t('reserveServiceManage.stateOnShelf')" value="2002">
  46 + </el-option>
  47 + </el-select>
  48 + </el-col>
  49 + <el-col :span="6">
  50 + <el-button type="primary" @click="_queryReserveServiceMethod()">
  51 + {{ $t('common.search') }}
  52 + </el-button>
  53 + </el-col>
  54 + </el-row>
  55 + </el-card>
  56 +
  57 + <el-card style="margin-top:20px">
  58 + <div slot="header" class="flex justify-between">
  59 + <span>{{ $t('reserveServiceManage.reserveService') }}</span>
  60 + <el-button type="primary" size="mini" @click="_openAddReserveServiceModal()">
  61 + <i class="el-icon-plus"></i>
  62 + {{ $t('reserveServiceManage.addService') }}
  63 + </el-button>
  64 + </div>
  65 +
  66 + <el-table :data="reserveServiceManageInfo.reserveServices" border style="width:100%">
  67 + <el-table-column :label="$t('reserveServiceManage.serviceCover')" align="center">
  68 + <template slot-scope="scope">
  69 + <el-image v-if="scope.row.imgUrl" style="width:60px;height:60px;border-radius:5px"
  70 + :src="scope.row.imgUrl" fit="cover">
  71 + </el-image>
  72 + <el-image v-else style="width:60px;height:60px;border-radius:5px" src="/img/noPhoto.jpg" fit="cover">
  73 + </el-image>
  74 + </template>
  75 + </el-table-column>
  76 + <el-table-column :label="$t('reserveServiceManage.nameAndId')" align="center">
  77 + <template slot-scope="scope">
  78 + {{ scope.row.goodsName }}({{ scope.row.goodsId }})
  79 + </template>
  80 + </el-table-column>
  81 + <el-table-column prop="paramsName" :label="$t('reserveServiceManage.params')" align="center">
  82 + </el-table-column>
  83 + <el-table-column prop="paramWay" :label="$t('reserveServiceManage.reserveWay')" align="center">
  84 + <template slot-scope="scope">
  85 + {{ scope.row.paramWay == '1' ? $t('reserveServiceManage.day') : $t('reserveServiceManage.week') }}
  86 + </template>
  87 + </el-table-column>
  88 + <el-table-column prop="maxQuantity" :label="$t('reserveServiceManage.reserveCount')" align="center">
  89 + </el-table-column>
  90 + <el-table-column prop="hoursMaxQuantity" :label="$t('reserveServiceManage.reserveQuantity')" align="center">
  91 + </el-table-column>
  92 + <el-table-column prop="price" :label="$t('reserveServiceManage.doorFee')" align="center">
  93 + </el-table-column>
  94 + <el-table-column :label="$t('reserveServiceManage.validity')" align="center">
  95 + <template slot-scope="scope">
  96 + {{ scope.row.startDate }}~{{ scope.row.endDate }}
  97 + </template>
  98 + </el-table-column>
  99 + <el-table-column prop="startTime" :label="$t('reserveServiceManage.reserveStartTime')" align="center">
  100 + </el-table-column>
  101 + <el-table-column prop="sort" :label="$t('reserveServiceManage.sort')" align="center">
  102 + </el-table-column>
  103 + <el-table-column :label="$t('reserveServiceManage.state')" align="center">
  104 + <template slot-scope="scope">
  105 + {{ scope.row.state == '1001' ? $t('reserveServiceManage.offShelf') : $t('reserveServiceManage.onShelf')
  106 + }}
  107 + </template>
  108 + </el-table-column>
  109 + <el-table-column :label="$t('common.operation')" align="center" width="200">
  110 + <template slot-scope="scope">
  111 + <el-button size="mini" @click="_openReserveServicePersonModel(scope.row)">
  112 + {{ $t('reserveServiceManage.reserveService') }}
  113 + </el-button>
  114 + <el-button size="mini" type="primary" @click="_openEditReserveServiceModel(scope.row)">
  115 + {{ $t('common.edit') }}
  116 + </el-button>
  117 + <el-button size="mini" type="danger" @click="_openDeleteReserveServiceModel(scope.row)">
  118 + {{ $t('common.delete') }}
  119 + </el-button>
  120 + </template>
  121 + </el-table-column>
  122 + </el-table>
  123 +
  124 + <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
  125 + :current-page="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size"
  126 + layout="total, sizes, prev, pager, next, jumper" :total="page.total">
  127 + </el-pagination>
  128 + </el-card>
  129 + </el-col>
  130 + </el-row>
  131 +
  132 + <add-reserve-service-person ref="addReserveServicePerson"></add-reserve-service-person>
  133 + <delete-reserve-dining ref="deleteReserveDining" @success="handleDeleteSuccess"></delete-reserve-dining>
  134 + </div>
  135 +</template>
  136 +
  137 +<script>
  138 +import { listReserveGoods, listReserveCatalog } from '@/api/scm/reserveServiceManageApi'
  139 +import { getCommunityId } from '@/api/community/communityApi'
  140 +import AddReserveServicePerson from '@/components/scm/addReserveServicePerson'
  141 +import DeleteReserveDining from '@/components/scm/deleteReserveDining'
  142 +
  143 +export default {
  144 + name: 'ReserveServiceManageList',
  145 + components: {
  146 + AddReserveServicePerson,
  147 + DeleteReserveDining
  148 + },
  149 + data() {
  150 + return {
  151 + reserveServiceManageInfo: {
  152 + reserveServices: [],
  153 + catalogs: [],
  154 + conditions: {
  155 + goodsId: '',
  156 + goodsName: '',
  157 + type: '2002',
  158 + state: '',
  159 + catalogId: '',
  160 + communityId: ''
  161 + }
  162 + },
  163 + page: {
  164 + current: 1,
  165 + size: 10,
  166 + total: 0
  167 + }
  168 + }
  169 + },
  170 + created() {
  171 + this.reserveServiceManageInfo.conditions.communityId = getCommunityId()
  172 + this._listReserveCatalogs()
  173 + },
  174 + methods: {
  175 + async _listReserveServices(page, rows) {
  176 + try {
  177 + this.reserveServiceManageInfo.conditions.page = page
  178 + this.reserveServiceManageInfo.conditions.row = rows
  179 + const { data, total } = await listReserveGoods(this.reserveServiceManageInfo.conditions)
  180 + this.reserveServiceManageInfo.reserveServices = data
  181 + this.page.total = total
  182 + } catch (error) {
  183 + console.error('获取预约服务列表失败:', error)
  184 + }
  185 + },
  186 + async _listReserveCatalogs() {
  187 + try {
  188 + const params = {
  189 + page: 1,
  190 + row: 100,
  191 + communityId: this.reserveServiceManageInfo.conditions.communityId,
  192 + type: '2002'
  193 + }
  194 + const { data } = await listReserveCatalog(params)
  195 + this.reserveServiceManageInfo.catalogs = data
  196 + if (data && data.length > 0) {
  197 + this.swatchReserveCatalog(data[0])
  198 + }
  199 + } catch (error) {
  200 + console.error('获取预约目录失败:', error)
  201 + }
  202 + },
  203 + _openAddReserveServiceModal() {
  204 + if (!this.reserveServiceManageInfo.conditions.catalogId) {
  205 + this.$message.warning(this.$t('reserveServiceManage.addCatalogFirst'))
  206 + return
  207 + }
  208 + this.$router.push(`/views/scm/addReserveService?catalogId=${this.reserveServiceManageInfo.conditions.catalogId}`)
  209 + },
  210 + _openEditReserveServiceModel(reserveService) {
  211 + this.$router.push(`/views/scm/editReserveService?goodsId=${reserveService.goodsId}`)
  212 + },
  213 + _openDeleteReserveServiceModel(reserveService) {
  214 + this.$refs.deleteReserveDining.open(reserveService)
  215 + },
  216 + _queryReserveServiceMethod() {
  217 + this._listReserveServices(1, this.page.size)
  218 + },
  219 + _openReserveServicePersonModel(reserveService) {
  220 + this.$refs.addReserveServicePerson.open(reserveService)
  221 + },
  222 + swatchReserveCatalog(item) {
  223 + this.reserveServiceManageInfo.conditions.catalogId = item.catalogId
  224 + this._listReserveServices(1, this.page.size)
  225 + },
  226 + _addCatalog() {
  227 + this.$router.push('/pages/reserve/reserveCatalogManage?tab=reserveCatalog')
  228 + },
  229 + handleSizeChange(val) {
  230 + this.page.size = val
  231 + this._listReserveServices(this.page.current, val)
  232 + },
  233 + handleCurrentChange(val) {
  234 + this.page.current = val
  235 + this._listReserveServices(val, this.page.size)
  236 + },
  237 + handleDeleteSuccess() {
  238 + this._listReserveServices(1, this.page.size)
  239 + }
  240 + }
  241 +}
  242 +</script>
  243 +
  244 +<style scoped>
  245 +.reserve-service-manage-container {
  246 + padding: 20px;
  247 +}
  248 +
  249 +.tree-card {
  250 + height: 100%;
  251 +}
  252 +
  253 +.list-group-item {
  254 + padding: 10px;
  255 + cursor: pointer;
  256 + border: 1px solid #ebeef5;
  257 + margin-bottom: 5px;
  258 +}
  259 +
  260 +.list-group-item:hover {
  261 + background-color: #f5f7fa;
  262 +}
  263 +
  264 +.vc-node-selected {
  265 + background-color: #ecf5ff;
  266 + color: #409eff;
  267 + border-color: #d9ecff;
  268 +}
  269 +
  270 +.el-pagination {
  271 + margin-top: 20px;
  272 + text-align: right;
  273 +}
  274 +</style>
0 275 \ No newline at end of file
... ...