| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- <template>
- <view class="page">
- <u-navbar title="新建套餐" :autoBack="true" :placeholder="true"></u-navbar>
- <view class="content">
- <u-collapse ref="collapse" :accordion="false" @change="onCollapse">
- <u-collapse-item
- v-for="(cat, ci) in categories"
- :key="cat.id"
- :name="cat.id"
- :open="activeNames.includes(cat.id)"
- >
- <view slot="title" class="c-title">
- {{ cat.name }}
- <text class="num" v-if="filledCount(cat)">({{ filledCount(cat) }})</text>
- </view>
- <view class="dish-item" v-for="(dish, di) in cat.items" :key="dish.id">
- <view class="dish-head">
- <u-icon name="edit-pen" color="#333" size="28"></u-icon>
- <text class="dish-title">{{ cat.name }}{{ di + 1 }}</text>
- </view>
- <view class="form-box">
- <view class="row">
- <text class="label">名称</text>
- <input class="input" v-model="dish.name" placeholder="请输入" placeholder-class="ph" />
- </view>
- <view class="row">
- <text class="label">价格</text>
- <input class="input" v-model="dish.price" type="digit" placeholder="输入金额" placeholder-class="ph" @blur="onPriceBlur(dish, $event)" />
- <text class="unit">元</text>
- </view>
- <view class="row last">
- <text class="label">描述</text>
- <input class="input" v-model="dish.description" placeholder="请描述菜品的使用素材" placeholder-class="ph" />
- </view>
- </view>
- <view class="ops">
- <view class="op-btn danger" @click.stop="removeItem(ci, di)">
- <u-icon name="trash" color="#FF4D4F" size="28"></u-icon>
- <text>删除</text>
- </view>
- <view
- v-if="di === cat.items.length - 1"
- class="op-btn primary"
- @click.stop="addItem(ci)"
- >
- <u-icon name="plus-square-fill" color="#449AFF" size="28"></u-icon>
- <text>添加</text>
- </view>
- </view>
- </view>
- </u-collapse-item>
- </u-collapse>
- </view>
- <view class="footer">
- <u-button type="primary" shape="circle" @click="onConfirm">确定</u-button>
- </view>
- </view>
- </template>
- <script>
- let itemIdSeed = 1;
- const nextItemId = () => ++itemIdSeed;
- const emptyItem = () => ({ id: nextItemId(), name: '', price: '', description: '' });
- export default {
- data() {
- return {
- categories: [
- { id: 'meat', name: '荤菜', items: [emptyItem()] },
- { id: 'veg', name: '素菜', items: [emptyItem()] },
- { id: 'staple', name: '主食', items: [emptyItem()] },
- { id: 'soup', name: '汤', items: [emptyItem()] },
- { id: 'other', name: '其他', items: [emptyItem()] }
- ],
- activeNames: ['meat']
- };
- },
- onLoad() {
- const prev = this.getPrevFormPage();
- const editing = prev && prev.form ? prev.form.comboItems : null;
- if (editing && editing.length) {
- this.categories = editing.map((cat) => ({
- ...cat,
- items: (cat.items && cat.items.length ? cat.items : [emptyItem()]).map((item) => ({
- ...item,
- id: item.id || nextItemId()
- }))
- }));
- this.categories.forEach((cat) => {
- (cat.items || []).forEach((item) => {
- if (Number(item.id) >= itemIdSeed) itemIdSeed = Number(item.id);
- });
- });
- }
- },
- methods: {
- onPriceBlur(dish, event) {
- const value = String((event.detail && event.detail.value) || '');
- dish.price = value.replace(/-/g, '');
- },
- getPrevFormPage() {
- const pages = getCurrentPages();
- const prev = pages[pages.length - 2];
- return prev && prev.$vm ? prev.$vm : null;
- },
- onCollapse(e) {
- this.activeNames = Array.isArray(e) ? e : e ? [e] : [];
- },
- filledCount(cat) {
- return (cat.items || []).filter((i) => i.name).length;
- },
- refreshCollapse() {
- this.$nextTick(() => {
- setTimeout(() => {
- if (this.$refs.collapse && this.$refs.collapse.init) {
- this.$refs.collapse.init();
- }
- }, 50);
- });
- },
- addItem(ci) {
- const items = this.categories[ci].items.slice();
- items.push(emptyItem());
- this.$set(this.categories[ci], 'items', items);
- this.refreshCollapse();
- },
- removeItem(ci, di) {
- const items = this.categories[ci].items.slice();
- if (items.length <= 1) {
- this.$set(this.categories[ci], 'items', [emptyItem()]);
- } else {
- items.splice(di, 1);
- this.$set(this.categories[ci], 'items', items);
- }
- this.refreshCollapse();
- },
- onConfirm() {
- const prev = this.getPrevFormPage();
- if (prev && typeof prev.applyComboItems === 'function') {
- prev.applyComboItems(this.categories);
- } else if (prev && prev.form) {
- prev.form.comboItems = this.categories;
- }
- uni.showToast({ title: '提交成功', icon: 'success' });
- setTimeout(() => uni.navigateBack(), 400);
- }
- }
- };
- </script>
- <style lang="scss" scoped>
- .page {
- min-height: 100vh;
- background: #f7f8fc;
- padding-bottom: 160rpx;
- }
- .content {
- padding: 20rpx 24rpx;
- }
- .c-title {
- font-size: 30rpx;
- font-weight: 500;
- color: #333;
- .num {
- color: #449aff;
- margin-left: 8rpx;
- }
- }
- .dish-item {
- margin-bottom: 24rpx;
- }
- .dish-head {
- display: flex;
- align-items: center;
- gap: 8rpx;
- margin-bottom: 12rpx;
- .dish-title {
- font-size: 28rpx;
- font-weight: 500;
- color: #333;
- }
- }
- .form-box {
- background: #edf5ff;
- border-radius: 12rpx;
- padding: 0 24rpx;
- overflow: hidden;
- }
- .row {
- display: flex;
- align-items: center;
- min-height: 88rpx;
- border-bottom: 1rpx solid rgba(0, 0, 0, 0.06);
- &.last {
- border-bottom: none;
- }
- .label {
- width: 88rpx;
- flex-shrink: 0;
- font-size: 28rpx;
- color: #333;
- }
- .input {
- flex: 1;
- font-size: 28rpx;
- color: #333;
- text-align: left;
- }
- .unit {
- margin-left: 8rpx;
- font-size: 28rpx;
- color: #333;
- flex-shrink: 0;
- }
- }
- .ph {
- color: #c0c4cc;
- }
- .ops {
- display: flex;
- justify-content: flex-end;
- align-items: center;
- gap: 16rpx;
- margin-top: 16rpx;
- }
- .op-btn {
- display: flex;
- align-items: center;
- justify-content: center;
- gap: 6rpx;
- height: 56rpx;
- padding: 0 22rpx;
- border-radius: 8rpx;
- font-size: 26rpx;
- box-sizing: border-box;
- &.danger {
- color: #ff4d4f;
- border: 1rpx solid #ff4d4f;
- background: #fff;
- }
- &.primary {
- color: #449aff;
- border: 1rpx solid #449aff;
- background: #fff;
- }
- }
- .footer {
- position: fixed;
- left: 0;
- right: 0;
- bottom: 0;
- padding: 20rpx 40rpx calc(20rpx + env(safe-area-inset-bottom));
- background: #fff;
- }
- </style>
|