弹窗样式修改,组件预定义
This commit is contained in:
parent
a7f9544bc5
commit
6aa66ce311
|
|
@ -1,10 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="form-checkbox">
|
<view class="form-checkbox">
|
||||||
<view v-for="(item, index) in options" :key="index" class="checkbox-item" @click="toggle(item)">
|
<view v-for="(item, index) in options" :key="index" class="checkbox-item" @click="onToggle(item)">
|
||||||
<view :class="['checkbox-dot', { checked: isSelected(item.value) }]">
|
<view class="checkbox-dot" :class="{ active: isChecked(item) }"></view>
|
||||||
<text v-if="isSelected(item.value)" class="check-icon">✓</text>
|
<text class="checkbox-label">{{ item }}</text>
|
||||||
</view>
|
|
||||||
<text class="checkbox-label">{{ item.label }}</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -13,44 +11,30 @@
|
||||||
export default {
|
export default {
|
||||||
name: 'FormItemCheckbox',
|
name: 'FormItemCheckbox',
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: { type: Array, default: function () { return []; } },
|
||||||
type: Array,
|
options: { type: Array, default: function () { return []; } },
|
||||||
default: function () {
|
maxCount: { type: Number, default: 0 }
|
||||||
return [];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
type: Array,
|
|
||||||
default: function () {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: function () {
|
|
||||||
return {
|
|
||||||
selectedValues: []
|
|
||||||
};
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
value: {
|
|
||||||
handler: function (val) {
|
|
||||||
this.selectedValues = Array.isArray(val) ? val.slice() : [];
|
|
||||||
},
|
|
||||||
immediate: true
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
isSelected: function (val) {
|
isChecked: function (val) {
|
||||||
return this.selectedValues.indexOf(val) > -1;
|
return this.value && this.value.indexOf(val) !== -1;
|
||||||
},
|
},
|
||||||
toggle: function (item) {
|
onToggle: function (val) {
|
||||||
var index = this.selectedValues.indexOf(item.value);
|
var newValue = (this.value || []).slice();
|
||||||
if (index > -1) {
|
var index = newValue.indexOf(val);
|
||||||
this.selectedValues.splice(index, 1);
|
if (index === -1) {
|
||||||
} else {
|
if (this.maxCount > 0 && newValue.length >= this.maxCount) {
|
||||||
this.selectedValues.push(item.value);
|
uni.showToast({
|
||||||
|
title: '最多只能选择' + this.maxCount + '项',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
this.$emit('input', this.selectedValues.slice());
|
newValue.push(val);
|
||||||
|
} else {
|
||||||
|
newValue.splice(index, 1);
|
||||||
|
}
|
||||||
|
this.$emit('input', newValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -60,34 +44,39 @@ export default {
|
||||||
.form-checkbox {
|
.form-checkbox {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 24rpx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkbox-item {
|
.checkbox-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 16rpx 0;
|
margin-right: 40rpx;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkbox-dot {
|
.checkbox-dot {
|
||||||
width: 36rpx;
|
width: 36rpx;
|
||||||
height: 36rpx;
|
height: 36rpx;
|
||||||
border-radius: 6rpx;
|
border-radius: 8rpx;
|
||||||
border: 2rpx solid #dddddd;
|
border: 2rpx solid #cccccc;
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
margin-right: 12rpx;
|
margin-right: 12rpx;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkbox-dot.checked {
|
.checkbox-dot.active {
|
||||||
border-color: #e8101e;
|
border-color: #e8101e;
|
||||||
background-color: #e8101e;
|
background-color: #e8101e;
|
||||||
}
|
}
|
||||||
|
|
||||||
.check-icon {
|
.checkbox-dot.active::after {
|
||||||
color: #ffffff;
|
content: '';
|
||||||
font-size: 24rpx;
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -60%) rotate(-45deg);
|
||||||
|
width: 20rpx;
|
||||||
|
height: 12rpx;
|
||||||
|
border-left: 4rpx solid #ffffff;
|
||||||
|
border-bottom: 4rpx solid #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkbox-label {
|
.checkbox-label {
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: "FormItemImage",
|
name: 'FormItemImage',
|
||||||
props: {
|
props: {
|
||||||
value: { type: Array, default: function () { return []; } },
|
value: { type: Array, default: function () { return []; } },
|
||||||
maxCount: { type: Number, default: 9 }
|
maxCount: { type: Number, default: 9 }
|
||||||
|
|
@ -41,17 +41,17 @@ export default {
|
||||||
var self = this;
|
var self = this;
|
||||||
uni.chooseImage({
|
uni.chooseImage({
|
||||||
count: remaining,
|
count: remaining,
|
||||||
sizeType: ["compressed"],
|
sizeType: ['compressed'],
|
||||||
sourceType: ["album", "camera"],
|
sourceType: ['album', 'camera'],
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
self.imageList = self.imageList.concat(res.tempFilePaths);
|
self.imageList = self.imageList.concat(res.tempFilePaths);
|
||||||
self.$emit("input", self.imageList);
|
self.$emit('input', self.imageList);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
deleteImage: function (index) {
|
deleteImage: function (index) {
|
||||||
this.imageList.splice(index, 1);
|
this.imageList.splice(index, 1);
|
||||||
this.$emit("input", this.imageList);
|
this.$emit('input', this.imageList);
|
||||||
},
|
},
|
||||||
previewImage: function (index) {
|
previewImage: function (index) {
|
||||||
uni.previewImage({
|
uni.previewImage({
|
||||||
|
|
@ -67,44 +67,54 @@ export default {
|
||||||
.form-image {
|
.form-image {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-list {
|
.image-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 16rpx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-item {
|
.image-item {
|
||||||
width: 200rpx;
|
width: 200rpx;
|
||||||
height: 200rpx;
|
height: 200rpx;
|
||||||
|
margin-right: 10rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
border-radius: 8rpx;
|
border-radius: 8rpx;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-image {
|
.preview-image {
|
||||||
width: 100%;
|
width: 200rpx;
|
||||||
height: 100%;
|
height: 200rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.delete-btn {
|
.delete-btn {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: -20rpx;
|
||||||
right: 0;
|
right: -20rpx;
|
||||||
width: 40rpx;
|
width: 40rpx;
|
||||||
height: 40rpx;
|
height: 40rpx;
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
border-radius: 50%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.delete-icon {
|
.delete-icon {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
font-size: 28rpx;
|
font-size: 32rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-btn {
|
.add-btn {
|
||||||
background-color: #f5f5f5;
|
background-color: #ffffff;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
border: 2rpx dashed #cccccc;
|
border: 2rpx dashed #dddddd;
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-icon {
|
.add-icon {
|
||||||
font-size: 60rpx;
|
font-size: 60rpx;
|
||||||
color: #999999;
|
color: #999999;
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,36 @@
|
||||||
<template>
|
<template>
|
||||||
<input type="number" class="form-input" :value="value" :placeholder="placeholder" placeholder-class="placeholder"
|
<view class="form-number-wrap">
|
||||||
@input="$emit('input', $event.detail.value)" />
|
<input type="digit" :value="value" :placeholder="placeholder" placeholder-class="placeholder" class="form-input" @input="onInput" />
|
||||||
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'FormItemNumber',
|
name: 'FormItemNumber',
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: { type: [String, Number], default: '' },
|
||||||
type: [String, Number],
|
placeholder: { type: String, default: '请输入' }
|
||||||
default: ''
|
|
||||||
},
|
},
|
||||||
placeholder: {
|
methods: {
|
||||||
type: String,
|
onInput: function(e) {
|
||||||
default: '请输入数字'
|
this.$emit('input', e.target.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.form-number-wrap {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
.form-input {
|
.form-input {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: 80rpx;
|
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: #333333;
|
color: #333333;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background-color: #f5f5f5;
|
|
||||||
border-radius: 8rpx;
|
|
||||||
padding: 0 24rpx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.placeholder {
|
.placeholder {
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,22 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="form-radio">
|
<view class="form-radio">
|
||||||
<view v-for="(item, index) in options" :key="index" class="radio-item" @click="onSelect(item.value)">
|
<view v-for="(item, index) in options" :key="index" class="radio-item" @click="onSelect(item)">
|
||||||
<view class="radio-dot" :class="{ active: value == item.value }"></view>
|
<view class="radio-dot" :class="{ active: value === item }"></view>
|
||||||
<text class="radio-label">{{ item.label }}</text>
|
<text class="radio-label">{{ item }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: "FormItemRadio",
|
name: 'FormItemRadio',
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: { type: [String, Number], default: '' },
|
||||||
type: [String, Number],
|
options: { type: Array, default: function () { return []; } }
|
||||||
default: ""
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
type: Array,
|
|
||||||
default: function() {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onSelect: function (val) {
|
onSelect: function (val) {
|
||||||
this.$emit("input", val);
|
this.$emit('input', val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -35,12 +27,14 @@ export default {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.radio-item {
|
.radio-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-right: 40rpx;
|
margin-right: 40rpx;
|
||||||
margin-bottom: 16rpx;
|
margin-bottom: 16rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.radio-dot {
|
.radio-dot {
|
||||||
width: 36rpx;
|
width: 36rpx;
|
||||||
height: 36rpx;
|
height: 36rpx;
|
||||||
|
|
@ -49,12 +43,14 @@ export default {
|
||||||
margin-right: 12rpx;
|
margin-right: 12rpx;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.radio-dot.active {
|
.radio-dot.active {
|
||||||
border-color: #e8101e;
|
border-color: #e8101e;
|
||||||
background-color: #e8101e;
|
background-color: #e8101e;
|
||||||
}
|
}
|
||||||
|
|
||||||
.radio-dot.active::after {
|
.radio-dot.active::after {
|
||||||
content: "";
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
|
|
@ -64,6 +60,7 @@ export default {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.radio-label {
|
.radio-label {
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: #333333;
|
color: #333333;
|
||||||
|
|
|
||||||
|
|
@ -1,83 +1,43 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="form-richtext">
|
<view class="form-richtext">
|
||||||
<view class="richtext-toolbar">
|
<view class="richtext-trigger" @click="goEdit">
|
||||||
<text class="toolbar-btn" @click="insertTag('b')">加粗</text>
|
<text class="richtext-value">{{ value ? '已设置' : '去设置' }}</text>
|
||||||
<text class="toolbar-btn" @click="insertTag('i')">斜体</text>
|
|
||||||
<text class="toolbar-btn" @click="insertImage">图片</text>
|
|
||||||
</view>
|
|
||||||
<textarea class="richtext-editor" :value="value" placeholder="请输入图文内容" placeholder-class="placeholder"
|
|
||||||
@input="$emit('input', $event.detail.value)" />
|
|
||||||
<view v-if="value" class="richtext-preview">
|
|
||||||
<rich-text :nodes="value" />
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: "FormItemRichtext",
|
name: 'FormItemRichtext',
|
||||||
props: {
|
props: {
|
||||||
value: { type: String, default: "" },
|
value: { type: String, default: '' }
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
insertTag(tag) {
|
goEdit: function () {
|
||||||
const text = `<${tag}></${tag}>`;
|
uni.navigateTo({
|
||||||
this.$emit("input", (this.value || "") + text);
|
url: '/pages/shop/add-img-text?list=' + this.value
|
||||||
},
|
|
||||||
insertImage() {
|
|
||||||
uni.chooseImage({
|
|
||||||
count: 1,
|
|
||||||
success: (res) => {
|
|
||||||
const imgTag = `<img src="${res.tempFilePaths[0]}" />`;
|
|
||||||
this.$emit("input", (this.value || "") + imgTag);
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.form-richtext {
|
.form-richtext {
|
||||||
width: 100%;
|
flex: 1;
|
||||||
}
|
|
||||||
|
|
||||||
.richtext-toolbar {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 16rpx;
|
align-items: center;
|
||||||
padding: 16rpx;
|
justify-content: flex-end;
|
||||||
background-color: #f0f0f0;
|
|
||||||
border-radius: 8rpx 8rpx 0 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar-btn {
|
.richtext-trigger {
|
||||||
padding: 8rpx 16rpx;
|
display: flex;
|
||||||
background-color: #ffffff;
|
align-items: center;
|
||||||
border-radius: 4rpx;
|
|
||||||
font-size: 24rpx;
|
|
||||||
color: #333333;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.richtext-editor {
|
.richtext-value {
|
||||||
width: 100%;
|
|
||||||
height: 300rpx;
|
|
||||||
background-color: #ffffff;
|
|
||||||
border: 2rpx solid #e0e0e0;
|
|
||||||
border-top: none;
|
|
||||||
border-radius: 0 0 8rpx 8rpx;
|
|
||||||
padding: 20rpx;
|
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: #333333;
|
color: #333333;
|
||||||
}
|
text-align: right;
|
||||||
|
|
||||||
.placeholder {
|
|
||||||
color: #999999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.richtext-preview {
|
|
||||||
margin-top: 16rpx;
|
|
||||||
padding: 16rpx;
|
|
||||||
background-color: #f9f9f9;
|
|
||||||
border-radius: 8rpx;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,53 +1,29 @@
|
||||||
<template>
|
<template>
|
||||||
<picker :range="optionLabels" @change="onChange">
|
<picker :range="options" @change="onChange">
|
||||||
<view class="form-select">
|
<view class="form-select">
|
||||||
<text :class="['select-text', selectedLabel ? '' : 'placeholder']">
|
<text :class="['select-text', value ? '' : 'placeholder']">
|
||||||
{{ selectedLabel || placeholder }}
|
{{ value || placeholder }}
|
||||||
</text>
|
</text>
|
||||||
<image src="https://mrrplus.oss-cn-beijing.aliyuncs.com/wxstaic/images/arrow_right.png" class="arrow-right" mode="aspectFit" />
|
<image src="https://mrrplus.oss-cn-beijing.aliyuncs.com/wxstaic/images/arrow_right.png" class="arrow-right"
|
||||||
|
mode="aspectFit" />
|
||||||
</view>
|
</view>
|
||||||
</picker>
|
</picker>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: "FormItemSelect",
|
name: 'FormItemSelect',
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: { type: [String, Number], default: '' },
|
||||||
type: [String, Number],
|
options: { type: Array, default: function () { return []; } },
|
||||||
default: ""
|
placeholder: { type: String, default: '请选择' }
|
||||||
},
|
|
||||||
options: {
|
|
||||||
type: Array,
|
|
||||||
default: function() {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
placeholder: {
|
|
||||||
type: String,
|
|
||||||
default: "请选择"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
optionLabels: function() {
|
|
||||||
return this.options.map(function(item) {
|
|
||||||
return item.label;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
selectedLabel: function() {
|
|
||||||
var self = this;
|
|
||||||
var found = this.options.find(function(item) {
|
|
||||||
return item.value == self.value;
|
|
||||||
});
|
|
||||||
return found ? found.label : "";
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onChange: function (e) {
|
onChange: function (e) {
|
||||||
var index = e.detail.value;
|
var index = e.detail.value;
|
||||||
var selected = this.options[index];
|
var selected = this.options[index];
|
||||||
if (selected) {
|
if (selected !== undefined) {
|
||||||
this.$emit("input", selected.value);
|
this.$emit('input', selected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -59,21 +35,22 @@ export default {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
width: 100%;
|
|
||||||
height: 80rpx;
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
border-radius: 8rpx;
|
|
||||||
padding: 0 24rpx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.select-text {
|
.select-text {
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: #333333;
|
color: #333333;
|
||||||
|
margin-right: 16rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.placeholder {
|
.placeholder {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 28rpx;
|
||||||
color: #999999;
|
color: #999999;
|
||||||
}
|
}
|
||||||
|
|
||||||
.arrow-right {
|
.arrow-right {
|
||||||
width: 24rpx;
|
width: 32rpx;
|
||||||
height: 24rpx;
|
height: 32rpx;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,36 @@
|
||||||
<template>
|
<template>
|
||||||
<input type="text" class="form-input" :value="value" :placeholder="placeholder" placeholder-class="placeholder"
|
<view class="form-text-wrap">
|
||||||
@input="$emit('input', $event.detail.value)" />
|
<input type="text" :value="value" :placeholder="placeholder" placeholder-class="placeholder" class="form-input" @input="onInput" />
|
||||||
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'FormItemText',
|
name: 'FormItemText',
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: { type: [String, Number], default: '' },
|
||||||
type: String,
|
placeholder: { type: String, default: '请输入' }
|
||||||
default: ''
|
|
||||||
},
|
},
|
||||||
placeholder: {
|
methods: {
|
||||||
type: String,
|
onInput: function(e) {
|
||||||
default: '请输入'
|
this.$emit('input', e.target.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.form-text-wrap {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
.form-input {
|
.form-input {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: 80rpx;
|
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: #333333;
|
color: #333333;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background-color: #f5f5f5;
|
|
||||||
border-radius: 8rpx;
|
|
||||||
padding: 0 24rpx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.placeholder {
|
.placeholder {
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="textarea-wrap">
|
<view class="detail-textarea-wrap">
|
||||||
<textarea class="form-textarea" :value="value" :placeholder="placeholder" placeholder-class="placeholder"
|
<textarea class="detail-textarea" :value="value" :placeholder="placeholder" placeholder-class="placeholder" maxlength="200" @input="onInput" />
|
||||||
maxlength="200" @input="$emit('input', $event.detail.value)" />
|
<text class="detail-count">{{ (value || '').length }}/200</text>
|
||||||
<text class="char-count">{{ (value || '').length }}/200</text>
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -10,47 +9,44 @@
|
||||||
export default {
|
export default {
|
||||||
name: 'FormItemTextarea',
|
name: 'FormItemTextarea',
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: { type: String, default: '' },
|
||||||
type: String,
|
placeholder: { type: String, default: '请输入' }
|
||||||
default: ''
|
|
||||||
},
|
},
|
||||||
placeholder: {
|
methods: {
|
||||||
type: String,
|
onInput: function(e) {
|
||||||
default: '请输入'
|
this.$emit('input', e.target.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.textarea-wrap {
|
.detail-textarea-wrap {
|
||||||
width: 100%;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
background: #f7f7f7;
|
||||||
|
border-radius: 16rpx;
|
||||||
.form-textarea {
|
padding: 24rpx 24rpx 52rpx;
|
||||||
width: 100%;
|
|
||||||
height: 150rpx;
|
|
||||||
font-size: 28rpx;
|
|
||||||
color: #333333;
|
|
||||||
line-height: 1.5;
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
border-radius: 8rpx;
|
|
||||||
padding: 20rpx;
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
.detail-textarea {
|
||||||
.placeholder {
|
width: 100%;
|
||||||
font-weight: 400;
|
height: 108rpx;
|
||||||
|
min-height: 108rpx;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: #999999;
|
line-height: 40rpx;
|
||||||
|
color: #333333;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
.detail-count {
|
||||||
.char-count {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 16rpx;
|
right: 24rpx;
|
||||||
bottom: 16rpx;
|
bottom: 16rpx;
|
||||||
font-size: 24rpx;
|
font-size: 22rpx;
|
||||||
color: #999999;
|
color: #999999;
|
||||||
|
line-height: 32rpx;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,33 +1,32 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="form-video">
|
<view class="form-video">
|
||||||
<view v-if="videoUrl" class="video-preview">
|
<view v-if="videoUrl" class="video-preview">
|
||||||
<video :src="videoUrl" class="video-player" controls />
|
<video :src="videoUrl" class="preview-video" controls />
|
||||||
<view class="delete-btn" @click="deleteVideo">
|
<view class="delete-btn" @click="deleteVideo">
|
||||||
<text class="delete-icon">×</text>
|
<text class="delete-icon">×</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view v-else class="video-add" @click="chooseVideo">
|
<view v-else class="upload-btn" @click="chooseVideo">
|
||||||
<text class="add-icon">+</text>
|
<text class="plus-icon">+</text>
|
||||||
<text class="add-text">选择视频</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: "FormItemVideo",
|
name: 'FormItemVideo',
|
||||||
props: {
|
props: {
|
||||||
value: { type: String, default: "" }
|
value: { type: String, default: '' }
|
||||||
},
|
},
|
||||||
data: function () {
|
data: function () {
|
||||||
return {
|
return {
|
||||||
videoUrl: ""
|
videoUrl: ''
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
value: {
|
value: {
|
||||||
handler: function (val) {
|
handler: function (val) {
|
||||||
this.videoUrl = val || "";
|
this.videoUrl = val || '';
|
||||||
},
|
},
|
||||||
immediate: true
|
immediate: true
|
||||||
}
|
}
|
||||||
|
|
@ -36,17 +35,17 @@ export default {
|
||||||
chooseVideo: function () {
|
chooseVideo: function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
uni.chooseVideo({
|
uni.chooseVideo({
|
||||||
sourceType: ["album", "camera"],
|
sourceType: ['album', 'camera'],
|
||||||
maxDuration: 60,
|
maxDuration: 60,
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
self.videoUrl = res.tempFilePath;
|
self.videoUrl = res.tempFilePath;
|
||||||
self.$emit("input", self.videoUrl);
|
self.$emit('input', self.videoUrl);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
deleteVideo: function () {
|
deleteVideo: function () {
|
||||||
this.videoUrl = "";
|
this.videoUrl = '';
|
||||||
this.$emit("input", "");
|
this.$emit('input', '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -56,49 +55,50 @@ export default {
|
||||||
.form-video {
|
.form-video {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.video-preview {
|
.video-preview {
|
||||||
width: 100%;
|
width: 200rpx;
|
||||||
|
height: 200rpx;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.video-player {
|
|
||||||
width: 100%;
|
.preview-video {
|
||||||
height: 400rpx;
|
width: 200rpx;
|
||||||
|
height: 200rpx;
|
||||||
border-radius: 8rpx;
|
border-radius: 8rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.delete-btn {
|
.delete-btn {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 16rpx;
|
top: -20rpx;
|
||||||
right: 16rpx;
|
right: -20rpx;
|
||||||
width: 48rpx;
|
width: 40rpx;
|
||||||
height: 48rpx;
|
height: 40rpx;
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.delete-icon {
|
.delete-icon {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
font-size: 32rpx;
|
font-size: 32rpx;
|
||||||
}
|
}
|
||||||
.video-add {
|
|
||||||
width: 300rpx;
|
.upload-btn {
|
||||||
height: 300rpx;
|
width: 200rpx;
|
||||||
background-color: #f5f5f5;
|
height: 200rpx;
|
||||||
border: 2rpx dashed #cccccc;
|
background-color: #ffffff;
|
||||||
|
border: 2rpx dashed #dddddd;
|
||||||
border-radius: 8rpx;
|
border-radius: 8rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
.add-icon {
|
|
||||||
|
.plus-icon {
|
||||||
font-size: 60rpx;
|
font-size: 60rpx;
|
||||||
color: #999999;
|
color: #999999;
|
||||||
}
|
}
|
||||||
.add-text {
|
|
||||||
font-size: 24rpx;
|
|
||||||
color: #999999;
|
|
||||||
margin-top: 8rpx;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,40 +1,89 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="dynamic-form">
|
<view class="dynamic-form">
|
||||||
<view v-for="(field, index) in fields" :key="field.id || index" class="form-item"
|
<view v-for="(field, index) in fields" :key="field.key" class="form-section">
|
||||||
:class="{ 'form-item-up': isUpType(field.type) }">
|
|
||||||
<view class="form-header">
|
|
||||||
<text class="form-label" :class="{ required: field.is_required == 1 }">{{ field.label }}</text>
|
|
||||||
<text v-if="field.tips" class="form-tips">{{ field.tips }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="form-control">
|
|
||||||
<!-- 单行文本 -->
|
<!-- 单行文本 -->
|
||||||
<form-item-text v-if="field.type === 'text'" :value="formData[field.key]"
|
<view v-if="field.type === 'text'" class="form-item">
|
||||||
:placeholder="field.placeholder" @input="onInput(field.key, $event)" />
|
<text :class="['form-label', field.is_required === true ? 'required' : '']">{{ field.label }}</text>
|
||||||
|
<input type="text" :value="formData[field.key]" :placeholder="field.placeholder" placeholder-class="placeholder"
|
||||||
|
class="form-input" @input="onInput(field.key, $event)" />
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 多行文本 -->
|
<!-- 多行文本 -->
|
||||||
<form-item-textarea v-else-if="field.type === 'textarea'" :value="formData[field.key]"
|
<view v-else-if="field.type === 'textarea'" class="detail-card">
|
||||||
:placeholder="field.placeholder" @input="onInput(field.key, $event)" />
|
<view class="detail-row">
|
||||||
|
<text :class="['form-label', field.is_required === true ? 'required' : '']">{{ field.label }}</text>
|
||||||
|
<view class="detail-textarea-wrap">
|
||||||
|
<textarea class="detail-textarea" :value="formData[field.key]" :placeholder="field.placeholder"
|
||||||
|
placeholder-class="placeholder" maxlength="200" @input="onInput(field.key, $event)" />
|
||||||
|
<text class="detail-count">{{ (formData[field.key] || '').length }}/200</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 数字输入 -->
|
<!-- 数字输入 -->
|
||||||
<form-item-number v-else-if="field.type === 'number'" :value="formData[field.key]"
|
<view v-else-if="field.type === 'number'" class="form-item" :style="field.tip ? 'flex-wrap: wrap;' : ''">
|
||||||
:placeholder="field.placeholder" @input="onInput(field.key, $event)" />
|
<text :class="['form-label', field.is_required === true ? 'required' : '']">{{ field.label }}</text>
|
||||||
|
<input type="digit" :value="formData[field.key]" :placeholder="field.placeholder"
|
||||||
|
placeholder-class="placeholder" class="form-input" @input="onInput(field.key, $event)" />
|
||||||
|
<text v-if="field.tips && !field.tip" class="form-tips">{{ field.tips }}</text>
|
||||||
|
<view v-if="field.tip" class="price-tip">
|
||||||
|
<text class="price-tip-card">{{ field.tip }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 多图上传 -->
|
<!-- 多图上传 -->
|
||||||
<form-item-image v-else-if="field.type === 'image_multi'" :value="formData[field.key]"
|
<view v-else-if="field.type === 'image_multi'" class="form-item-up upload-item">
|
||||||
:maxCount="field.maxCount || 9" @input="onInput(field.key, $event)" />
|
<view>
|
||||||
|
<text :class="['form-label', field.is_required === true ? 'required' : '']">{{ field.label }}</text>
|
||||||
|
<text class="upload-tip">(仅可上传{{ field.maxCount || 9 }}个图片)</text>
|
||||||
|
</view>
|
||||||
|
<view class="upload-content">
|
||||||
|
<form-item-image :value="formData[field.key]" :maxCount="field.maxCount || 9"
|
||||||
|
@input="onInput(field.key, $event)" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 视频上传 -->
|
<!-- 视频上传 -->
|
||||||
<form-item-video v-else-if="field.type === 'video'" :value="formData[field.key]"
|
<view v-else-if="field.type === 'video'" class="form-item-up upload-item">
|
||||||
@input="onInput(field.key, $event)" />
|
<view>
|
||||||
|
<text :class="['form-label', field.is_required === true ? 'required' : '']">{{ field.label }}</text>
|
||||||
|
<text class="upload-tip">(仅可上传1个视频)</text>
|
||||||
|
</view>
|
||||||
|
<view class="upload-content">
|
||||||
|
<form-item-video :value="formData[field.key]" @input="onInput(field.key, $event)" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 下拉选择 -->
|
<!-- 下拉选择 -->
|
||||||
<form-item-select v-else-if="field.type === 'select'" :value="formData[field.key]"
|
<view v-else-if="field.type === 'select'" class="form-item">
|
||||||
:options="field.options" :placeholder="field.placeholder" @input="onInput(field.key, $event)" />
|
<text :class="['form-label', field.is_required === true ? 'required' : '']">{{ field.label }}</text>
|
||||||
<!-- 单选 -->
|
<form-item-select :value="formData[field.key]" :options="field.options || []" :placeholder="field.placeholder"
|
||||||
<form-item-radio v-else-if="field.type === 'single_select'" :value="formData[field.key]"
|
|
||||||
:options="field.options" @input="onInput(field.key, $event)" />
|
|
||||||
<!-- 多选 -->
|
|
||||||
<form-item-checkbox v-else-if="field.type === 'multi_select'" :value="formData[field.key]"
|
|
||||||
:options="field.options" @input="onInput(field.key, $event)" />
|
|
||||||
<!-- 图文编辑器 -->
|
|
||||||
<form-item-richtext v-else-if="field.type === 'richtext_editor'" :value="formData[field.key]"
|
|
||||||
@input="onInput(field.key, $event)" />
|
@input="onInput(field.key, $event)" />
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- 单选 -->
|
||||||
|
<view v-else-if="field.type === 'single_select'" class="form-item" style="flex-wrap: wrap;">
|
||||||
|
<text :class="['form-label', field.is_required === true ? 'required' : '']">{{ field.label }}</text>
|
||||||
|
<view class="select-options">
|
||||||
|
<form-item-radio :value="formData[field.key]" :options="field.options || []"
|
||||||
|
@input="onInput(field.key, $event)" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 多选 -->
|
||||||
|
<view v-else-if="field.type === 'multi_select'" class="form-item" style="flex-wrap: wrap;">
|
||||||
|
<text :class="['form-label', field.is_required === true ? 'required' : '']">{{ field.label }}</text>
|
||||||
|
<view class="select-options">
|
||||||
|
<form-item-checkbox :value="formData[field.key]" :options="field.options || []"
|
||||||
|
:maxCount="field.maxCount || 0" @input="onInput(field.key, $event)" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 图文编辑器 -->
|
||||||
|
<view v-else-if="field.type === 'richtext_editor'" class="form-item">
|
||||||
|
<text :class="['form-label', field.is_required === true ? 'required' : '']">{{ field.label }}</text>
|
||||||
|
<form-item-richtext :value="formData[field.key]" @input="onInput(field.key, $event)" />
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -53,28 +102,24 @@ import FormItemRichtext from './FormItemRichtext.vue';
|
||||||
export default {
|
export default {
|
||||||
name: 'DynamicForm',
|
name: 'DynamicForm',
|
||||||
components: {
|
components: {
|
||||||
FormItemText,
|
'form-item-text': FormItemText,
|
||||||
FormItemTextarea,
|
'form-item-textarea': FormItemTextarea,
|
||||||
FormItemNumber,
|
'form-item-number': FormItemNumber,
|
||||||
FormItemImage,
|
'form-item-image': FormItemImage,
|
||||||
FormItemVideo,
|
'form-item-video': FormItemVideo,
|
||||||
FormItemSelect,
|
'form-item-select': FormItemSelect,
|
||||||
FormItemRadio,
|
'form-item-radio': FormItemRadio,
|
||||||
FormItemCheckbox,
|
'form-item-checkbox': FormItemCheckbox,
|
||||||
FormItemRichtext
|
'form-item-richtext': FormItemRichtext
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
fields: {
|
fields: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: function () {
|
default: function () { return []; }
|
||||||
return [];
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: function () {
|
default: function () { return {}; }
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data: function () {
|
data: function () {
|
||||||
|
|
@ -87,48 +132,49 @@ export default {
|
||||||
handler: function (val) {
|
handler: function (val) {
|
||||||
this.formData = Object.assign({}, val);
|
this.formData = Object.assign({}, val);
|
||||||
},
|
},
|
||||||
immediate: true,
|
immediate: true
|
||||||
deep: true
|
|
||||||
},
|
},
|
||||||
fields: {
|
fields: {
|
||||||
handler: function (val) {
|
handler: function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
if (val && val.length > 0) {
|
var data = {};
|
||||||
val.forEach(function (field) {
|
this.fields.forEach(function (field) {
|
||||||
if (self.formData[field.key] === undefined) {
|
if (self.formData[field.key] !== undefined) {
|
||||||
self.$set(self.formData, field.key, self.getDefaultValue(field.type));
|
data[field.key] = self.formData[field.key];
|
||||||
|
} else if (field.default_value !== undefined) {
|
||||||
|
data[field.key] = field.default_value;
|
||||||
|
} else if (field.type === 'multi_select' || field.type === 'image_multi') {
|
||||||
|
data[field.key] = [];
|
||||||
|
} else {
|
||||||
|
data[field.key] = '';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
this.formData = Object.assign({}, this.formData, data);
|
||||||
},
|
},
|
||||||
immediate: true
|
immediate: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
isUpType: function (type) {
|
onInput: function (key, event) {
|
||||||
return type === 'image_multi' || type === 'video';
|
var value = event;
|
||||||
},
|
if (event && event.target && event.target.value !== undefined) {
|
||||||
getDefaultValue: function (type) {
|
value = event.target.value;
|
||||||
if (type === 'multi_select') {
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
if (type === 'image_multi') {
|
this.$set(this.formData, key, value);
|
||||||
return [];
|
this.$emit('input', this.formData);
|
||||||
}
|
|
||||||
return '';
|
|
||||||
},
|
},
|
||||||
onInput: function (key, val) {
|
getData: function () {
|
||||||
this.$set(this.formData, key, val);
|
return Object.assign({}, this.formData);
|
||||||
this.$emit('input', Object.assign({}, this.formData));
|
|
||||||
},
|
},
|
||||||
validate: function () {
|
validate: function () {
|
||||||
|
var self = this;
|
||||||
for (var i = 0; i < this.fields.length; i++) {
|
for (var i = 0; i < this.fields.length; i++) {
|
||||||
var field = this.fields[i];
|
var field = this.fields[i];
|
||||||
if (field.is_required == 1) {
|
if (field.is_required === true) {
|
||||||
var val = this.formData[field.key];
|
var value = self.formData[field.key];
|
||||||
if (val === undefined || val === null || val === '' || (Array.isArray(val) && val.length === 0)) {
|
if (!value || (Array.isArray(value) && value.length === 0)) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '请填写' + field.label,
|
title: field.label + '不能为空',
|
||||||
icon: 'none'
|
icon: 'none'
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -136,9 +182,6 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
|
||||||
getData: function () {
|
|
||||||
return Object.assign({}, this.formData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -149,6 +192,10 @@ export default {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.form-section {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.form-item {
|
.form-item {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
padding: 24rpx;
|
padding: 24rpx;
|
||||||
|
|
@ -161,26 +208,14 @@ export default {
|
||||||
margin-bottom: 24rpx;
|
margin-bottom: 24rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-item-up {
|
|
||||||
flex-flow: column nowrap;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 16rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-label {
|
.form-label {
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: #333333;
|
color: #333333;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-label.required::before {
|
.required::before {
|
||||||
content: '*';
|
content: '*';
|
||||||
color: #e8101e;
|
color: #ff0000;
|
||||||
margin-right: 4rpx;
|
margin-right: 4rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -190,8 +225,100 @@ export default {
|
||||||
margin-left: 10rpx;
|
margin-left: 10rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-control {
|
.price-tip {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
flex: 1;
|
margin-top: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-tip-card {
|
||||||
|
padding: 8rpx 12rpx;
|
||||||
|
background: #FDF0F0;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #E8101E;
|
||||||
|
line-height: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item-up {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 24rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column nowrap;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-item {
|
||||||
|
padding-bottom: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-tip {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999999;
|
||||||
|
margin-left: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-content {
|
||||||
|
margin-top: 20rpx;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-options {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-card {
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
padding: 0 24rpx 8rpx;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-row {
|
||||||
|
padding: 24rpx 0 36rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-row .form-label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
line-height: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-textarea-wrap {
|
||||||
|
position: relative;
|
||||||
|
background: #f7f7f7;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 24rpx 24rpx 52rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-textarea {
|
||||||
|
width: 100%;
|
||||||
|
height: 108rpx;
|
||||||
|
min-height: 108rpx;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
font-size: 28rpx;
|
||||||
|
line-height: 40rpx;
|
||||||
|
color: #333333;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-count {
|
||||||
|
position: absolute;
|
||||||
|
right: 24rpx;
|
||||||
|
bottom: 16rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: #999999;
|
||||||
|
line-height: 32rpx;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -99,13 +99,12 @@
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
<!-- <view class="add-btn"></view> -->
|
|
||||||
|
|
||||||
<!-- 服务分类选择弹窗 -->
|
<!-- 服务分类选择弹窗 -->
|
||||||
<view class="category-popup-mask" v-if="showCategoryPopup" @click="closeCategoryPopup">
|
<view class="category-popup-mask" v-if="showCategoryPopup" @click="closeCategoryPopup">
|
||||||
<view class="category-popup" @click.stop>
|
<view class="category-popup" @click.stop>
|
||||||
<view class="category-popup-header">
|
<view class="category-popup-header">
|
||||||
<text class="category-popup-title">选择服务分类</text>
|
<text class="category-popup-title">选择服务类型</text>
|
||||||
<view class="category-popup-close" @click="closeCategoryPopup">
|
<view class="category-popup-close" @click="closeCategoryPopup">
|
||||||
<text class="category-popup-close-icon">×</text>
|
<text class="category-popup-close-icon">×</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -124,10 +123,16 @@
|
||||||
<view v-if="secondClassList.length === 0" class="category-empty">
|
<view v-if="secondClassList.length === 0" class="category-empty">
|
||||||
<text class="category-empty-text">暂无子分类</text>
|
<text class="category-empty-text">暂无子分类</text>
|
||||||
</view>
|
</view>
|
||||||
<view v-for="item in secondClassList" :key="item.id" class="category-right-item"
|
<view v-for="item in secondClassList" :key="item.id"
|
||||||
|
:class="['category-right-item', { selected: selectedSecondId === item.id }]"
|
||||||
@click="selectSecondClass(item)">
|
@click="selectSecondClass(item)">
|
||||||
<text class="category-right-text">{{ item.title }}</text>
|
<text class="category-right-text">{{ item.title }}</text>
|
||||||
<view :class="['category-dot', { selected: selectedSecondId === item.id }]"></view>
|
<image class="category-icon"
|
||||||
|
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/b6fa6b5b-b5c1-45e3-9372-74ade548f76b.png"
|
||||||
|
mode="widthFix" v-if="!selectedSecondId || selectedSecondId !== item.id"></image>
|
||||||
|
<image class="category-icon"
|
||||||
|
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/f0f97cad-03f6-4363-abb5-58d3176cfa81.png"
|
||||||
|
mode="widthFix" v-else></image>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -187,31 +192,6 @@ export default {
|
||||||
selectedSecondId: null,
|
selectedSecondId: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
// computed: {
|
|
||||||
// filteredServices() {
|
|
||||||
// return this.services.filter(service => {
|
|
||||||
// // 根据搜索文本过滤
|
|
||||||
// if (this.title && !service.title.includes(this.title)) {
|
|
||||||
// return false
|
|
||||||
// }
|
|
||||||
// // 根据当前标签过滤
|
|
||||||
// switch (this.currentTab) {
|
|
||||||
// case 0: // 草稿
|
|
||||||
// return service.state === 2
|
|
||||||
// case 1: // 审核中
|
|
||||||
// return service.state === 1
|
|
||||||
// case 2: // 已上架
|
|
||||||
// return service.state === 2
|
|
||||||
// case 3: // 下架
|
|
||||||
// return service.state === 3
|
|
||||||
// case 4: // 驳回
|
|
||||||
// return service.state === 4
|
|
||||||
// default:
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
onLoad() {
|
onLoad() {
|
||||||
this.getServicesList();
|
this.getServicesList();
|
||||||
},
|
},
|
||||||
|
|
@ -256,7 +236,7 @@ export default {
|
||||||
title: "下架成功",
|
title: "下架成功",
|
||||||
icon: "none",
|
icon: "none",
|
||||||
});
|
});
|
||||||
this.getServicesList(0); // 刷新列表
|
this.getServicesList(0);
|
||||||
} else {
|
} else {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: res.msg,
|
title: res.msg,
|
||||||
|
|
@ -280,7 +260,7 @@ export default {
|
||||||
title: "上架成功",
|
title: "上架成功",
|
||||||
icon: "none",
|
icon: "none",
|
||||||
});
|
});
|
||||||
this.getServicesList(0); // 刷新列表
|
this.getServicesList(0);
|
||||||
} else {
|
} else {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: res.msg,
|
title: res.msg,
|
||||||
|
|
@ -296,7 +276,6 @@ export default {
|
||||||
|
|
||||||
},
|
},
|
||||||
addService() {
|
addService() {
|
||||||
// 获取一级分类并显示弹窗
|
|
||||||
request.post("/sj/firstclass", {}).then((res) => {
|
request.post("/sj/firstclass", {}).then((res) => {
|
||||||
if (res.data && res.data.length > 0) {
|
if (res.data && res.data.length > 0) {
|
||||||
this.firstClassList = res.data;
|
this.firstClassList = res.data;
|
||||||
|
|
@ -304,7 +283,6 @@ export default {
|
||||||
this.selectedSecondId = null;
|
this.selectedSecondId = null;
|
||||||
this.secondClassList = [];
|
this.secondClassList = [];
|
||||||
this.showCategoryPopup = true;
|
this.showCategoryPopup = true;
|
||||||
// 自动加载第一个一级分类的二级分类
|
|
||||||
this.loadSecondClass(res.data[0].id);
|
this.loadSecondClass(res.data[0].id);
|
||||||
} else {
|
} else {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
|
|
@ -314,7 +292,6 @@ export default {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 加载二级分类
|
|
||||||
loadSecondClass(firstId) {
|
loadSecondClass(firstId) {
|
||||||
request.post("/user/secondclass", {
|
request.post("/user/secondclass", {
|
||||||
id: firstId,
|
id: firstId,
|
||||||
|
|
@ -322,18 +299,15 @@ export default {
|
||||||
this.secondClassList = res.data || [];
|
this.secondClassList = res.data || [];
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 选择一级分类
|
|
||||||
selectFirstClass(index, item) {
|
selectFirstClass(index, item) {
|
||||||
if (this.selectedFirstIndex === index) return;
|
if (this.selectedFirstIndex === index) return;
|
||||||
this.selectedFirstIndex = index;
|
this.selectedFirstIndex = index;
|
||||||
this.selectedSecondId = null;
|
this.selectedSecondId = null;
|
||||||
this.loadSecondClass(item.id);
|
this.loadSecondClass(item.id);
|
||||||
},
|
},
|
||||||
// 选择二级分类(仅记录选中状态)
|
|
||||||
selectSecondClass(item) {
|
selectSecondClass(item) {
|
||||||
this.selectedSecondId = item.id;
|
this.selectedSecondId = item.id;
|
||||||
},
|
},
|
||||||
// 确认选择分类
|
|
||||||
confirmCategory() {
|
confirmCategory() {
|
||||||
if (this.selectedFirstIndex < 0) {
|
if (this.selectedFirstIndex < 0) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
|
|
@ -342,7 +316,6 @@ export default {
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 如果有二级分类但未选择
|
|
||||||
if (this.secondClassList.length > 0 && !this.selectedSecondId) {
|
if (this.secondClassList.length > 0 && !this.selectedSecondId) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: "请选择服务子类",
|
title: "请选择服务子类",
|
||||||
|
|
@ -355,7 +328,6 @@ export default {
|
||||||
uni.navigateTo({ url });
|
uni.navigateTo({ url });
|
||||||
this.closeCategoryPopup();
|
this.closeCategoryPopup();
|
||||||
},
|
},
|
||||||
// 关闭分类弹窗
|
|
||||||
closeCategoryPopup() {
|
closeCategoryPopup() {
|
||||||
this.showCategoryPopup = false;
|
this.showCategoryPopup = false;
|
||||||
this.firstClassList = [];
|
this.firstClassList = [];
|
||||||
|
|
@ -377,7 +349,7 @@ export default {
|
||||||
title: "删除成功",
|
title: "删除成功",
|
||||||
icon: "none",
|
icon: "none",
|
||||||
});
|
});
|
||||||
this.getServicesList(0); // 刷新列表
|
this.getServicesList(0);
|
||||||
} else {
|
} else {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: res.msg,
|
title: res.msg,
|
||||||
|
|
@ -391,11 +363,8 @@ export default {
|
||||||
},
|
},
|
||||||
touchStart(e, index) {
|
touchStart(e, index) {
|
||||||
if (this.currentTab != 3) return;
|
if (this.currentTab != 3) return;
|
||||||
// 阻止默认事件和冒泡
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
// 获取触摸事件的坐标
|
|
||||||
if (e.touches && e.touches[0]) {
|
if (e.touches && e.touches[0]) {
|
||||||
this.startX = e.touches[0].clientX;
|
this.startX = e.touches[0].clientX;
|
||||||
this.currentIndex = index;
|
this.currentIndex = index;
|
||||||
|
|
@ -404,87 +373,60 @@ export default {
|
||||||
touchMove(e) {
|
touchMove(e) {
|
||||||
if (this.currentTab != 3) return;
|
if (this.currentTab != 3) return;
|
||||||
if (this.currentIndex === -1) return;
|
if (this.currentIndex === -1) return;
|
||||||
|
|
||||||
// 阻止默认事件和冒泡
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
// 获取触摸事件的坐标
|
|
||||||
if (e.touches && e.touches[0]) {
|
if (e.touches && e.touches[0]) {
|
||||||
this.moveX = e.touches[0].clientX - this.startX;
|
this.moveX = e.touches[0].clientX - this.startX;
|
||||||
|
|
||||||
// 限制只能向左滑动
|
|
||||||
if (this.moveX > 0) {
|
if (this.moveX > 0) {
|
||||||
this.moveX = 0;
|
this.moveX = 0;
|
||||||
}
|
}
|
||||||
// 限制最大滑动距离
|
|
||||||
if (this.moveX < -160) {
|
if (this.moveX < -160) {
|
||||||
this.moveX = -160;
|
this.moveX = -160;
|
||||||
}
|
}
|
||||||
// 更新当前项的滑动状态
|
|
||||||
this.$set(this.services[this.currentIndex], "slideX", this.moveX);
|
this.$set(this.services[this.currentIndex], "slideX", this.moveX);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
touchEnd(e) {
|
touchEnd(e) {
|
||||||
if (this.currentTab != 3) return;
|
if (this.currentTab != 3) return;
|
||||||
if (this.currentIndex === -1) return;
|
if (this.currentIndex === -1) return;
|
||||||
|
|
||||||
// 阻止默认事件和冒泡
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
// 如果滑动距离超过一半,则完全展开
|
|
||||||
if (this.moveX < -80) {
|
if (this.moveX < -80) {
|
||||||
this.$set(this.services[this.currentIndex], "slideX", -160);
|
this.$set(this.services[this.currentIndex], "slideX", -160);
|
||||||
} else {
|
} else {
|
||||||
// 否则恢复原位
|
|
||||||
this.$set(this.services[this.currentIndex], "slideX", 0);
|
this.$set(this.services[this.currentIndex], "slideX", 0);
|
||||||
}
|
}
|
||||||
this.currentIndex = -1;
|
this.currentIndex = -1;
|
||||||
},
|
},
|
||||||
mouseDown(e, index) {
|
mouseDown(e, index) {
|
||||||
if (this.currentTab != 3) return;
|
if (this.currentTab != 3) return;
|
||||||
// 阻止默认事件和冒泡
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
this.startX = e.clientX;
|
this.startX = e.clientX;
|
||||||
this.currentIndex = index;
|
this.currentIndex = index;
|
||||||
},
|
},
|
||||||
mouseMove(e) {
|
mouseMove(e) {
|
||||||
if (this.currentTab != 3) return;
|
if (this.currentTab != 3) return;
|
||||||
if (this.currentIndex === -1) return;
|
if (this.currentIndex === -1) return;
|
||||||
|
|
||||||
// 阻止默认事件和冒泡
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
this.moveX = e.clientX - this.startX;
|
this.moveX = e.clientX - this.startX;
|
||||||
|
|
||||||
// 限制只能向左滑动
|
|
||||||
if (this.moveX > 0) {
|
if (this.moveX > 0) {
|
||||||
this.moveX = 0;
|
this.moveX = 0;
|
||||||
}
|
}
|
||||||
// 限制最大滑动距离
|
|
||||||
if (this.moveX < -160) {
|
if (this.moveX < -160) {
|
||||||
this.moveX = -160;
|
this.moveX = -160;
|
||||||
}
|
}
|
||||||
// 更新当前项的滑动状态
|
|
||||||
this.$set(this.services[this.currentIndex], "slideX", this.moveX);
|
this.$set(this.services[this.currentIndex], "slideX", this.moveX);
|
||||||
},
|
},
|
||||||
mouseUp(e) {
|
mouseUp(e) {
|
||||||
if (this.currentTab != 3) return;
|
if (this.currentTab != 3) return;
|
||||||
if (this.currentIndex === -1) return;
|
if (this.currentIndex === -1) return;
|
||||||
|
|
||||||
// 阻止默认事件和冒泡
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
// 如果滑动距离超过一半,则完全展开
|
|
||||||
if (this.moveX < -80) {
|
if (this.moveX < -80) {
|
||||||
this.$set(this.services[this.currentIndex], "slideX", -160);
|
this.$set(this.services[this.currentIndex], "slideX", -160);
|
||||||
} else {
|
} else {
|
||||||
// 否则恢复原位
|
|
||||||
this.$set(this.services[this.currentIndex], "slideX", 0);
|
this.$set(this.services[this.currentIndex], "slideX", 0);
|
||||||
}
|
}
|
||||||
this.currentIndex = -1;
|
this.currentIndex = -1;
|
||||||
|
|
@ -578,7 +520,7 @@ export default {
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
width: 32rpx;
|
width: 32rpx;
|
||||||
height: 6rpx;
|
height: 6rpx;
|
||||||
background-color: #E8101E;
|
background-color: #FF4767;
|
||||||
border-radius: 3rpx;
|
border-radius: 3rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -623,7 +565,7 @@ export default {
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 160rpx;
|
width: 160rpx;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: #E8101E;
|
background-color: #FF4767;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
@ -669,20 +611,20 @@ export default {
|
||||||
|
|
||||||
.price-symbol {
|
.price-symbol {
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
color: #E8101E;
|
color: #FF4767;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.price-value {
|
.price-value {
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: #E8101E;
|
color: #FF4767;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
margin: 0 4rpx;
|
margin: 0 4rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.price-unit {
|
.price-unit {
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
color: #E8101E;
|
color: #FF4767;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-tag {
|
.status-tag {
|
||||||
|
|
@ -700,11 +642,11 @@ export default {
|
||||||
|
|
||||||
/* 已上架 */
|
/* 已上架 */
|
||||||
.status-tag.state2 {
|
.status-tag.state2 {
|
||||||
background-color: rgba(232, 16, 30, 0.2);
|
background-color: rgba(255, 71, 103, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-tag.state2 .status-text {
|
.status-tag.state2 .status-text {
|
||||||
color: #E8101E;
|
color: #FF4767;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 审核中 */
|
/* 审核中 */
|
||||||
|
|
@ -720,13 +662,13 @@ export default {
|
||||||
.status-tag.state0,
|
.status-tag.state0,
|
||||||
.status-tag.state3,
|
.status-tag.state3,
|
||||||
.status-tag.state4 {
|
.status-tag.state4 {
|
||||||
background-color: rgba(209, 15, 19, 0.2);
|
background-color: rgba(255, 71, 103, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-tag.state0 .status-text,
|
.status-tag.state0 .status-text,
|
||||||
.status-tag.state3 .status-text,
|
.status-tag.state3 .status-text,
|
||||||
.status-tag.state4 .status-text {
|
.status-tag.state4 .status-text {
|
||||||
color: #d10f13;
|
color: #FF4767;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btns {
|
.btns {
|
||||||
|
|
@ -816,7 +758,6 @@ export default {
|
||||||
|
|
||||||
/* #ifdef MP-WEIXIN */
|
/* #ifdef MP-WEIXIN */
|
||||||
.search-box input {
|
.search-box input {
|
||||||
/* 小程序搜索框样式调整 */
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -825,7 +766,6 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.service-item {
|
.service-item {
|
||||||
/* 小程序阴影效果 */
|
|
||||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
|
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -846,17 +786,15 @@ export default {
|
||||||
height: 88rpx;
|
height: 88rpx;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 88rpx;
|
line-height: 88rpx;
|
||||||
background-color: #E8101E;
|
background-color: #FF4767;
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
|
|
||||||
.serviceBtn-text {
|
.serviceBtn-text {
|
||||||
|
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 分类选择弹窗样式 */
|
/* 分类选择弹窗样式 */
|
||||||
|
|
@ -881,12 +819,11 @@ export default {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
|
||||||
|
|
||||||
.category-popup-header {
|
.category-popup-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: space-between;
|
||||||
padding: 32rpx;
|
padding: 32rpx;
|
||||||
position: relative;
|
position: relative;
|
||||||
border-bottom: 1rpx solid #f0f0f0;
|
border-bottom: 1rpx solid #f0f0f0;
|
||||||
|
|
@ -946,7 +883,7 @@ export default {
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
width: 6rpx;
|
width: 6rpx;
|
||||||
height: 40rpx;
|
height: 40rpx;
|
||||||
background-color: #E8101E;
|
background-color: #FF4767;
|
||||||
border-radius: 0 3rpx 3rpx 0;
|
border-radius: 0 3rpx 3rpx 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -956,7 +893,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-left-item.active .category-left-text {
|
.category-left-item.active .category-left-text {
|
||||||
color: #E8101E;
|
color: #FF4767;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -971,7 +908,12 @@ export default {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 30rpx 32rpx;
|
padding: 30rpx 32rpx;
|
||||||
border-bottom: 1rpx solid #f5f5f5;
|
/* 移除 border-bottom: 1rpx solid #f5f5f5; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-right-item.selected .category-right-text {
|
||||||
|
color: #FF4767;
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-right-text {
|
.category-right-text {
|
||||||
|
|
@ -980,30 +922,10 @@ export default {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-dot {
|
.category-icon {
|
||||||
width: 36rpx;
|
width: 36rpx;
|
||||||
height: 36rpx;
|
height: 36rpx;
|
||||||
border-radius: 50%;
|
|
||||||
border: 2rpx solid #dddddd;
|
|
||||||
margin-left: 16rpx;
|
margin-left: 16rpx;
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-dot.selected {
|
|
||||||
border-color: #E8101E;
|
|
||||||
background-color: #E8101E;
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-dot.selected::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
width: 16rpx;
|
|
||||||
height: 16rpx;
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: #ffffff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-empty {
|
.category-empty {
|
||||||
|
|
@ -1046,10 +968,11 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-popup-btn-confirm {
|
.category-popup-btn-confirm {
|
||||||
background-color: #E8101E;
|
background-color: #FF4767;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-popup-btn-confirm text {
|
.category-popup-btn-confirm text {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -151,20 +151,20 @@ export default {
|
||||||
async getTemplate() {
|
async getTemplate() {
|
||||||
// 模拟数据
|
// 模拟数据
|
||||||
const mockFields = [
|
const mockFields = [
|
||||||
{ key: 'title', type: 'text', label: '服务名称', is_required: 1, placeholder: '请输入服务名称' },
|
{ key: 'title', type: 'text', label: '服务名称', is_required: true, placeholder: '请输入服务名称' },
|
||||||
{ key: 'service_price', type: 'number', label: '服务定价', is_required: 1, placeholder: '请输入定价,最多两位小数', tips: '(元)' },
|
{ key: 'service_price', type: 'number', label: '服务定价', is_required: true, placeholder: '请输入定价,最多两位小数', tips: '(元)', tip: '服务的基础定价,未参与任何优惠的价格' },
|
||||||
{ key: 'sale_price', type: 'number', label: '服务售价', is_required: 1, placeholder: '请输入售价,最多两位小数', tips: '(元)' },
|
{ key: 'sale_price', type: 'number', label: '服务售价', is_required: true, placeholder: '请输入售价,最多两位小数', tips: '(元)', tip: '服务参与单品优惠后的价格' },
|
||||||
{ key: 'service_time', type: 'number', label: '服务时长', is_required: 1, placeholder: '请输入服务时间', tips: '(分钟)' },
|
{ key: 'service_time', type: 'number', label: '服务时长', is_required: true, placeholder: '请输入服务时间', tips: '(分钟)' },
|
||||||
{ key: 'effect', type: 'textarea', label: '服务功效', is_required: 1, placeholder: '请输入服务功效' },
|
{ key: 'effect', type: 'textarea', label: '服务功效', is_required: true, placeholder: '请输入服务功效' },
|
||||||
{ key: 'crowd', type: 'textarea', label: '适用人群', is_required: 1, placeholder: '请输入不适用人群,例如:未成年人/孕妇不适用' },
|
{ key: 'crowd', type: 'textarea', label: '适用人群', is_required: true, placeholder: '请输入不适用人群,例如:未成年人/孕妇不适用' },
|
||||||
{ key: 'product', type: 'textarea', label: '产品清单', is_required: 0, placeholder: '请输入产品清单' },
|
{ key: 'product', type: 'textarea', label: '产品清单', is_required: false, placeholder: '请输入产品清单' },
|
||||||
{ key: 'scope', type: 'textarea', label: '适用范围', is_required: 0, placeholder: '请输入使用时间/适用人数' },
|
{ key: 'scope', type: 'textarea', label: '适用范围', is_required: false, placeholder: '请输入使用时间/适用人数' },
|
||||||
{ key: 'tips_text', type: 'textarea', label: '温馨提示', is_required: 0, placeholder: '请输入其他注意事项' },
|
{ key: 'tips_text', type: 'textarea', label: '温馨提示', is_required: false, placeholder: '请输入其他注意事项' },
|
||||||
{ key: 'images', type: 'image_multi', label: '服务图片', is_required: 1, maxCount: 9 },
|
{ key: 'images', type: 'image_multi', label: '服务图片', is_required: true, maxCount: 9 },
|
||||||
{ key: 'video', type: 'video', label: '上传短视频', is_required: 0 },
|
{ key: 'video', type: 'video', label: '上传短视频', is_required: false },
|
||||||
{ key: 'category', type: 'select', label: '服务分类', is_required: 1, placeholder: '请选择服务分类', options: [{ label: '美发', value: '1' }, { label: '美甲', value: '2' }, { label: '美容', value: '3' }] },
|
{ key: 'service_type', type: 'single_select', label: '服务类型', is_required: true, options: ['到店服务', '上门服务'] },
|
||||||
{ key: 'service_type', type: 'single_select', label: '服务类型', is_required: 1, options: [{ label: '到店服务', value: '1' }, { label: '上门服务', value: '2' }] },
|
{ key: 'features', type: 'multi_select', label: '服务特色', is_required: false, options: ['一对一服务', '免费咨询', '售后保障'], maxCount: 2 },
|
||||||
{ key: 'features', type: 'multi_select', label: '服务特色', is_required: 0, options: [{ label: '一对一服务', value: '1' }, { label: '免费咨询', value: '2' }, { label: '售后保障', value: '3' }] },
|
{ key: 'graphic_details', type: 'richtext_editor', label: '图文详情', is_required: false },
|
||||||
];
|
];
|
||||||
try {
|
try {
|
||||||
const res = await request.post("/sj/servers/getTemplate", {
|
const res = await request.post("/sj/servers/getTemplate", {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue