form-step1.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. <template>
  2. <view class="page-container">
  3. <u-navbar title="新建团餐" :autoBack="true" :placeholder="true"></u-navbar>
  4. <view class="form-card">
  5. <view class="section-title">基础信息</view>
  6. <u-form :model="form" ref="uForm" :rules="rules"
  7. labelPosition="left" labelWidth="auto"
  8. :error-type="['toast', 'border-bottom']"
  9. >
  10. <u-form-item prop="category" label="商品分类" required borderBottom @click="show = true">
  11. <u-input v-model="form.categoryName" class="form-input" disabled placeholder="去设置" height="41" inputAlign="right"></u-input>
  12. <u-icon slot="right" name="arrow-right" color="#C7C6CA"></u-icon>
  13. </u-form-item>
  14. <u-form-item prop="name" label="商品名称" required borderBottom>
  15. <u-input v-model="form.name" placeholder="请输入商品名称" height="41" inputAlign="right"></u-input>
  16. </u-form-item>
  17. <u-form-item prop="specialCategoryId" label="特色分类" required borderBottom @click="showSpecial = true">
  18. <u-input v-model="form.specialCategoryName" class="form-input" disabled placeholder="去设置" height="41" inputAlign="right"></u-input>
  19. <u-icon slot="right" name="arrow-right" color="#C7C6CA"></u-icon>
  20. </u-form-item>
  21. <u-form-item prop="productImage" label="商品封面图" required labelPosition="top">
  22. <view class="upload-content">
  23. <view class="upload-tip">支持jpg、png格式,建议尺寸为750px*750px,上传1-4张</view>
  24. <Upload
  25. width="140"
  26. height="140"
  27. :maxCount="4"
  28. :multiple="true"
  29. :fileList.sync="fileList.cover"
  30. :previewFullImage="true"
  31. @complete="onUpload($event, 'cover')"
  32. />
  33. </view>
  34. </u-form-item>
  35. <u-form-item prop="detailImages" label="商品详情图" required borderBottom labelPosition="top">
  36. <view class="upload-content">
  37. <view class="upload-tip">支持jpg、png格式,最多20张</view>
  38. <Upload
  39. width="140"
  40. height="140"
  41. :maxCount="20"
  42. :multiple="true"
  43. :fileList.sync="fileList.detail"
  44. :previewFullImage="true"
  45. @complete="onUpload($event, 'detail')"
  46. />
  47. </view>
  48. </u-form-item>
  49. <u-form-item prop="price" label="团餐价" required borderBottom>
  50. <u-input type="digit" height="41" :clearable="false"
  51. inputAlign="right"
  52. placeholder="请输入团餐价"
  53. v-model.number="form.price"
  54. @input="onInput($event, 'price')"
  55. ></u-input>
  56. <text slot="right" class="input-suffix">元</text>
  57. </u-form-item>
  58. <u-form-item prop="sellingPrice" label="售价" required :borderBottom="true">
  59. <u-input type="digit" height="41" :clearable="false"
  60. inputAlign="right" placeholder="请输入商品售价"
  61. v-model.number="form.sellingPrice"
  62. @input="onInput($event, 'sellingPrice')"
  63. ></u-input>
  64. <text slot="right" class="input-suffix">元</text>
  65. </u-form-item>
  66. <u-form-item prop="dailyStock" label="库存" required :borderBottom="true">
  67. <u-input type="number" height="41" :clearable="false"
  68. inputAlign="right" placeholder="请输入每日库存"
  69. v-model="form.dailyStock"
  70. ></u-input>
  71. <text slot="right" class="input-suffix">份</text>
  72. </u-form-item>
  73. <view class="tips">每日库存最大量的设置,当天售完后关闭该团餐</view>
  74. </u-form>
  75. </view>
  76. <view class="footer-bar">
  77. <u-button type="primary" @click="goNextStep">下一步</u-button>
  78. </view>
  79. <!-- 商品分类选择 -->
  80. <u-action-sheet :list="actionSheetList" v-model="show" @click="actionSheetCallback"></u-action-sheet>
  81. <!-- 特色分类 -->
  82. <u-action-sheet :list="categoryList" v-model="showSpecial" @click="specialCategoryCallback"></u-action-sheet>
  83. </view>
  84. </template>
  85. <script>
  86. import Upload from '@/components/upload/index.vue';
  87. import configService from '@/common/service/config.service';
  88. export default {
  89. components: {
  90. Upload,
  91. },
  92. data() {
  93. return {
  94. show: false,
  95. showSpecial: false,
  96. form: {
  97. name: '',
  98. category: '',
  99. categoryName: '',
  100. specialCategoryId: '',
  101. specialCategoryName: '',
  102. productImage: 'https://test.baoxianzhanggui.com/locallive-java/product/企业微信截图_1781494923590_1781494943931.png',
  103. detailImages: 'https://test.baoxianzhanggui.com/locallive-java/product/企业微信截图_1781494923590_1781494943931.png',
  104. price: '',
  105. sellingPrice: '',
  106. dailyStock:null,
  107. saleDays:''
  108. },
  109. categoryList:[],
  110. query: {},
  111. fileList: {
  112. cover: [],
  113. detail: [],
  114. },
  115. actionSheetList: [
  116. {
  117. text: '早餐',
  118. value: '1'
  119. },
  120. {
  121. text: '午餐',
  122. value: '2'
  123. },
  124. {
  125. text: '晚餐',
  126. value: '3'
  127. }
  128. ],
  129. rules: {
  130. name: [
  131. {
  132. required: true,
  133. message: '请输入名称',
  134. trigger: ['blur', 'change']
  135. }
  136. ],
  137. category: [
  138. {
  139. required: true,
  140. message: '请选择商品分类',
  141. trigger: ['blur', 'change']
  142. }
  143. ],
  144. specialCategoryId: [
  145. {
  146. required: true,
  147. message: '请选择特色分类',
  148. trigger: ['blur', 'change']
  149. }
  150. ],
  151. price: [
  152. {
  153. required: true,
  154. type: 'number',
  155. message: '请输入团餐价格',
  156. trigger: ['blur', 'change']
  157. },
  158. {
  159. asyncValidator: (rule, value, callback) => {
  160. if (this.form.sellingPrice && value > this.form.sellingPrice) {
  161. callback(new Error('团餐价格不能大于商品售价'));
  162. } else {
  163. callback();
  164. }
  165. },
  166. trigger: ['blur', 'change']
  167. },
  168. ],
  169. sellingPrice: [
  170. {
  171. required: true,
  172. type: 'number',
  173. message: '请输入商品售价',
  174. trigger: ['blur', 'change']
  175. },
  176. {
  177. asyncValidator: (rule, value, callback) => {
  178. if (this.form.price && value < this.form.price) {
  179. callback(new Error('商品售价不能小于团餐价格'));
  180. } else {
  181. callback();
  182. }
  183. },
  184. trigger: ['blur', 'change']
  185. },
  186. ],
  187. productImage: [
  188. {
  189. required: true,
  190. message: '请上传商品封面图',
  191. trigger: ['blur', 'change']
  192. }
  193. ],
  194. detailImages: [
  195. {
  196. required: true,
  197. message: '请上传商品详情图片',
  198. trigger: ['blur', 'change']
  199. }
  200. ],
  201. dailyStock:[
  202. {
  203. required: true,
  204. type: 'number',
  205. message: '请填写库存',
  206. trigger: ['blur', 'change']
  207. }
  208. ]
  209. }
  210. };
  211. },
  212. async onLoad(query) {
  213. if (query.id) {
  214. this.query = query;
  215. await this.getCategoryList()
  216. await this.getData();
  217. }
  218. // 清除
  219. uni.removeStorageSync('gm_goods');
  220. // 获取餐品分类
  221. this.getClassData();
  222. },
  223. onShow() {
  224. },
  225. onReady() {
  226. this.$refs.uForm.setRules(this.rules);
  227. },
  228. methods: {
  229. //获取特色分类
  230. getCategoryList(){
  231. this.$http.get('/groupmeal/gmSpecialCategory/listAll').then(res => {
  232. if (res.data.code === 200 && res.data.result) {
  233. this.categoryList = res.data.result.map(item => {
  234. return {
  235. text: item.categoryName,
  236. value: item.id
  237. }
  238. })
  239. }
  240. })
  241. },
  242. // 编辑数据
  243. getData() {
  244. this.$http.get('/groupmeal/gmCustomerPackage/queryById', { params: { id: this.query.id } }).then(res => {
  245. if (res.data.code === 200) {
  246. let data = res.data.result;
  247. // 查找商品分类名称
  248. const categoryItem = this.actionSheetList.find(item => item.value == data.category);
  249. // 查找特色分类名称
  250. const specialCategoryItem = this.categoryList.find(item => item.value == data.specialCategoryId);
  251. console.log(specialCategoryItem)
  252. this.form = {
  253. ...data,
  254. categoryName: categoryItem ? categoryItem.text : '',
  255. specialCategoryId: data.specialCategoryId+'',
  256. specialCategoryName: specialCategoryItem ? specialCategoryItem.text : ''
  257. };
  258. this.fileList = {
  259. cover: data.productImage.split(',').map(item => {
  260. return {
  261. url: item
  262. }
  263. }),
  264. detail: data.detailImages.split(',').map(item => {
  265. return {
  266. url: item
  267. }
  268. }),
  269. };
  270. }
  271. });
  272. },
  273. // 餐品分类
  274. getClassData() {
  275. this.$http.get('/groupmeal/gmMerchantPackage/getGroupMealCategory', {}).then(res => {
  276. if (res.data.code === 200) {
  277. this.actionSheetList = res.data.result.map(item => {
  278. return {
  279. text: item.name,
  280. value: item.code
  281. }
  282. })
  283. }
  284. });
  285. },
  286. // 商品分类选择回调
  287. actionSheetCallback(e) {
  288. this.form.category = e.value;
  289. this.form.categoryName = e.text;
  290. },
  291. // 特色分类选择回调
  292. specialCategoryCallback(e) {
  293. console.log(e)
  294. this.form.specialCategoryId = e.value;
  295. this.form.specialCategoryName = e.text;
  296. },
  297. // 价格数值处理
  298. onInput(value, key) {
  299. // 过滤所有非数字和非小数点的字符
  300. let filtered = value.replace(/[^\d.]/g, '');
  301. // 处理多个小数点(只保留第一个)
  302. filtered = filtered.replace(/^\./g, ''); // 移除开头的小数点(避免 ".123" 情况)
  303. filtered = filtered.replace(/\.{2,}/g, '.'); // 多个小数点只保留第一个
  304. // 分割整数和小数部分,限制小数最多两位
  305. const parts = filtered.split('.');
  306. if (parts.length > 1) {
  307. // 小数部分只保留前两位
  308. filtered = parts[0] + '.' + (parts[1].slice(0, 2) || '');
  309. }
  310. // 处理特殊情况(如 "000" 转为 "0",但价格允许 "0.00")
  311. // 若需要严格限制整数部分首位不为0(非必须,根据业务决定):
  312. // if (parts.length === 1 && filtered.length > 1 && filtered[0] === '0') {
  313. // filtered = filtered.replace(/^0+/, '0');
  314. // }
  315. // 更新绑定值
  316. this.$nextTick(() => {
  317. this.form[key] = !filtered ? filtered : filtered - 0;
  318. });
  319. },
  320. // 图片处理
  321. onUpload(event, type) {
  322. this.fileList[type] = event;
  323. this.form[type == 'cover' ? 'productImage' : 'detailImages'] = this.fileList[type].map(f => f.url).join();
  324. },
  325. // 下一步
  326. goNextStep() {
  327. // 表单校验
  328. this.$refs.uForm.validate(valid => {
  329. if (valid) {
  330. const { categoryName, specialCategoryName, ...form } = this.form;
  331. uni.setStorageSync('gm_goods', form);
  332. uni.navigateTo({
  333. url: '/pages/groupMeal/goods/form-day'
  334. });
  335. } else {
  336. console.log('验证失败');
  337. }
  338. });
  339. }
  340. }
  341. };
  342. </script>
  343. <style lang="scss" scoped>
  344. $uni-text-color: #303133;
  345. $uni-color-primary: #2979ff;
  346. .page-container {
  347. min-height: 100vh;
  348. background-color: #f5f5f5;
  349. .section-title {
  350. font-weight: 500;
  351. font-size: 30rpx;
  352. color: #333333;
  353. margin-bottom: 32rpx;
  354. }
  355. }
  356. .form-card {
  357. margin: 24rpx;
  358. padding: 16rpx 16rpx;
  359. background-color: #fff;
  360. border-radius: 16rpx;
  361. ::v-deep .u-form-item {
  362. padding: 16rpx 0;
  363. line-height: 1;
  364. .u-form-item--left__content {
  365. flex: none;
  366. .u-form-item--left__content__label {
  367. font-weight: 600;
  368. }
  369. .u-form-item--left__content--required {
  370. color: #fa3534;
  371. left: auto;
  372. right: 0;
  373. }
  374. }
  375. }
  376. .form-input {
  377. pointer-events: none;
  378. }
  379. ::v-deep .uni-input-input:disabled {
  380. pointer-events: none;
  381. }
  382. .input-suffix {
  383. color: #232832;
  384. font-size: 26rpx;
  385. margin-left: 10rpx;
  386. }
  387. .upload-content {
  388. width: 100%;
  389. .upload-tip {
  390. font-weight: 400;
  391. font-size: 20rpx;
  392. color: #999999;
  393. margin-bottom: 20rpx;
  394. }
  395. ::v-deep .u-add-tips {
  396. display: none !important;
  397. }
  398. ::v-deep .u-add-wrap {
  399. background: url('/static/groupMeal/upload.png') center center / 100% 100% no-repeat !important;
  400. border: none !important;
  401. }
  402. ::v-deep .u-add-btn {
  403. display: none !important;
  404. }
  405. }
  406. }
  407. .tips{
  408. width: 100%;
  409. font-weight: 400;
  410. font-size: 20rpx;
  411. color: #999999;
  412. margin-top: 66rpx;
  413. text-align: center;
  414. }
  415. // 底部按钮
  416. .footer-bar {
  417. ::v-deep .u-btn {
  418. width: 100%;
  419. height: 76rpx;
  420. font-weight: 400;
  421. font-size: 28rpx;
  422. color: #449AFF;
  423. border-radius: 54rpx;
  424. border: 1rpx solid #449AFF;
  425. background: #FFFFFF;
  426. }
  427. }
  428. // 分类选择弹窗样式
  429. .category-popup {
  430. padding: 30rpx;
  431. .popup-title {
  432. text-align: center;
  433. font-size: 34rpx;
  434. font-weight: bold;
  435. color: $uni-text-color;
  436. margin-bottom: 30rpx;
  437. }
  438. .category-list {
  439. max-height: 600rpx; // 限制高度,可滚动
  440. }
  441. .category-item {
  442. padding: 20rpx 0;
  443. font-size: 30rpx;
  444. color: $uni-text-color;
  445. border-bottom: 1rpx solid #eee;
  446. display: flex;
  447. justify-content: space-between;
  448. align-items: center;
  449. &:last-child {
  450. border-bottom: none;
  451. }
  452. &.selected {
  453. color: $uni-color-primary;
  454. font-weight: bold;
  455. }
  456. }
  457. .popup-footer {
  458. padding-top: 30rpx;
  459. }
  460. }
  461. </style>