settings.vue 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. <template>
  2. <view class="page-container">
  3. <u-navbar title="团餐设置" :autoBack="true" :placeholder="true" :border-bottom="false"></u-navbar>
  4. <u-form :model="form" :rules="rules" ref="formRef" labelPosition="left" labelWidth="auto">
  5. <template v-for="(meal, index) in form.mealTimes">
  6. <view class="meal-section" :key="index" v-if="isGroup(meal)">
  7. <view class="section-title">{{ meal.name }}</view>
  8. <u-form-item :label="`拼团最低起送量`" :prop="`mealTimes.${index}.minGroupSize`" borderBottom :required="isEdited(index)">
  9. <u-input v-model="meal.minGroupSize" type="number" placeholder="输入数量" height="41" inputAlign="right"></u-input>
  10. </u-form-item>
  11. <u-form-item :label="`开团时间`" :prop="`mealTimes.${index}.startTime`" borderBottom :required="isEdited(index)">
  12. <u-input v-model="meal.startTime" :clearable="false" placeholder="去设置" height="41" inputAlign="right" @click="openTimePicker(index, 'startTime')"></u-input>
  13. <u-icon slot="right" name="arrow-right"></u-icon>
  14. </u-form-item>
  15. <u-form-item :label="`闭团时间`" :prop="`mealTimes.${index}.endTime`" @click="openTimePicker(index, 'endTime')" :required="isEdited(index)">
  16. <u-input v-model="meal.endTime" :clearable="false" placeholder="去设置" height="41" inputAlign="right" @click="openTimePicker(index, 'endTime')"></u-input>
  17. <u-icon slot="right" name="arrow-right"></u-icon>
  18. </u-form-item>
  19. </view>
  20. </template>
  21. </u-form>
  22. <view class="footer-bar">
  23. <u-button type="primary"
  24. :disabled="isSubmitDisabled"
  25. @click="submit"
  26. >提交</u-button>
  27. </view>
  28. <u-picker
  29. mode="time"
  30. :params="{
  31. hour: true,
  32. minute: true,
  33. timestamp: true
  34. }"
  35. v-model="showPicker"
  36. @confirm="onTimeConfirm"
  37. @cancel="showPicker = false"
  38. ></u-picker>
  39. </view>
  40. </template>
  41. <script>
  42. export default {
  43. data() {
  44. return {
  45. form: {
  46. mealTimes: [
  47. { id: 1, name: '早餐', minGroupSize: '', startTime: '', endTime: '' },
  48. { id: 2, name: '午餐', minGroupSize: '', startTime: '', endTime: '' },
  49. { id: 3, name: '晚餐', minGroupSize: '', startTime: '', endTime: '' },
  50. ],
  51. },
  52. rules: {}, // 规则将动态生成
  53. query: {},
  54. showPicker: false,
  55. pickerValue: '',
  56. currentEditing: { // 记录当前正在编辑的时间
  57. index: null,
  58. field: ''
  59. },
  60. };
  61. },
  62. computed: {
  63. // 判断提交按钮是否应该被禁用
  64. isSubmitDisabled() {
  65. // 如果所有餐次的所有字段都为空,则禁用
  66. return this.form.mealTimes.every(meal =>
  67. !meal.minGroupSize && !meal.startTime && !meal.endTime
  68. );
  69. }
  70. },
  71. watch: {
  72. // 深度监听表单数据变化,动态设置校验规则
  73. 'form.mealTimes': {
  74. handler() {
  75. // 使用 nextTick 确保在 DOM 更新后再设置规则,增加稳定性
  76. this.$nextTick(() => {
  77. this.updateValidationRules();
  78. });
  79. },
  80. deep: true
  81. }
  82. },
  83. onLoad(query) {
  84. this.query = query;
  85. if (query.isEnterprise) this.getData();
  86. },
  87. mounted() {
  88. // 页面加载完成后,为 u-form 实例设置初始规则
  89. this.$nextTick(() => {
  90. this.$refs.formRef.setRules(this.rules);
  91. });
  92. },
  93. methods: {
  94. getData() {
  95. let params = {
  96. isEnterprise: this.query.isEnterprise
  97. };
  98. this.$http.get('/groupmeal/gmMerchantSettings/getByIsEnterprise', {params}).then(res => {
  99. if (res.data.code === 200 && res.data.result.length > 0) {
  100. res.data.result.map(item => {
  101. let i = this.form.mealTimes.findIndex(mitem => mitem.id === item.category);
  102. if (i !== -1) {
  103. this.$set(this.form.mealTimes, i, {
  104. ...this.form.mealTimes[i],
  105. id: item.category,
  106. startTime: item.strStartTime,
  107. endTime: item.strEndTime,
  108. minGroupSize: item.minGroupSize + '',
  109. });
  110. }
  111. });
  112. }
  113. });
  114. },
  115. isGroup(e) {
  116. let flag = true;
  117. if (this.query.isEnterprise == 2 && e.id != 2) flag = false;
  118. return flag;
  119. },
  120. // 判断一个餐次区块是否被编辑过
  121. isEdited(index) {
  122. const meal = this.form.mealTimes[index];
  123. return !!(meal.minGroupSize || meal.startTime || meal.endTime);
  124. },
  125. updateValidationRules() {
  126. // 确保 u-form 实例存在
  127. if (!this.$refs.formRef) {
  128. return;
  129. }
  130. const newRules = {};
  131. this.form.mealTimes.forEach((meal, index) => {
  132. if (this.isEdited(index)) {
  133. // 如果有任何一个字段被填写,则该餐次的所有字段都变为必填
  134. newRules[`mealTimes.${index}.minGroupSize`] = [{ required: true, message: '请输入起送量', trigger: ['blur', 'change'] }];
  135. newRules[`mealTimes.${index}.startTime`] = [
  136. { required: true, message: '请设置开团时间', trigger: ['blur', 'change'] },
  137. {
  138. validator: (rule, value, callback) => {
  139. const endTime = this.form.mealTimes[index].endTime;
  140. let flag = endTime && value && value >= endTime;
  141. return !flag;
  142. },
  143. message: '开团时间必须早于闭团时间',
  144. trigger: ['change', 'blur'],
  145. }
  146. ];
  147. newRules[`mealTimes.${index}.endTime`] = [
  148. { required: true, message: '请设置闭团时间', trigger: ['blur', 'change'] },
  149. {
  150. asyncValidator: (rule, value, callback) => {
  151. const startTime = this.form.mealTimes[index].startTime;
  152. if (startTime && value && value <= startTime) {
  153. callback(new Error('闭团时间必须晚于开团时间'));
  154. } else {
  155. callback();
  156. }
  157. },
  158. trigger: ['change', 'blur'],
  159. }
  160. ];
  161. }
  162. });
  163. this.rules = newRules;
  164. this.$refs.formRef.setRules(this.rules);
  165. },
  166. openTimePicker(index, field) {
  167. this.currentEditing = { index, field };
  168. this.pickerValue = this.form.mealTimes[index][field] || '08:00'; // 默认值
  169. this.showPicker = true;
  170. },
  171. onTimeConfirm(e) {
  172. const { value } = e;
  173. const { index, field } = this.currentEditing;
  174. this.form.mealTimes[index][field] = value;
  175. this.showPicker = false;
  176. },
  177. submit() {
  178. this.$refs.formRef.validate().then(res => {
  179. let params = {
  180. gmMerchantSettingsList: this.form.mealTimes.filter((item, index) => this.isEdited(index)).map(item => {
  181. return {
  182. category: item.id,
  183. merchantId: uni.getStorageSync('login_user_info').merchantId,
  184. minGroupSize: item.minGroupSize - 0,
  185. isEnterprise: this.query.isEnterprise - 0,
  186. strEndTime: item.endTime,
  187. strStartTime: item.startTime
  188. }
  189. })
  190. };
  191. console.log('表单校验成功', this.form, params);
  192. this.$http.post('/groupmeal/gmMerchantSettings/add', params).then(res => {
  193. if (res.data.code === 200) {
  194. this.$tip.success('设置成功');
  195. } else {
  196. this.$tip.error(res.data.message);
  197. }
  198. });
  199. }).catch(errors => {
  200. console.log('表单校验失败', errors);
  201. });
  202. }
  203. }
  204. };
  205. </script>
  206. <style lang="scss" scoped>
  207. .page-container {
  208. background-color: #f5f5f5;
  209. min-height: 100vh;
  210. padding-bottom: 140rpx;
  211. }
  212. .meal-section {
  213. margin: 24rpx;
  214. padding: 20rpx 30rpx;
  215. border: 1rpx solid #F0F3F5;
  216. border-radius: 16rpx;
  217. box-shadow: 0 2rpx 8rpx 0 rgba(214,225,237,0.1);
  218. background-color: #fff;
  219. .section-title {
  220. font-size: 32rpx;
  221. font-weight: 500;
  222. padding: 0 0 16rpx;
  223. }
  224. ::v-deep .u-form-item {
  225. padding: 16rpx 0;
  226. line-height: 1;
  227. .u-form-item--left__content {
  228. flex: none;
  229. .u-form-item--left__content--required {
  230. color: #fa3534;
  231. left: auto;
  232. right: 0;
  233. }
  234. }
  235. }
  236. }
  237. .footer-bar {
  238. ::v-deep .u-btn {
  239. width: 100%;
  240. height: 76rpx;
  241. font-weight: 400;
  242. font-size: 28rpx;
  243. color: #FFFFFF;
  244. border-radius: 54rpx;
  245. background: linear-gradient(90deg, #77B6FF 0%, #449AFF 100%);
  246. &.u-btn--primary--disabled {
  247. background: #a0cfff;
  248. }
  249. }
  250. }
  251. </style>