123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837 |
- <template>
- <view class="app-diy-form" :style="{
- paddingTop: `${marginTop}rpx`,
- paddingBottom: `${marginBottom}rpx`,
- backgroundColor: `${marginColor}`
- }">
- <view class="title" v-if="title !== '' && title !== null">{{title}}</view>
- <!--<view style="border: 1rpx solid #ff3455">
- <view v-for="(item, index) in myList" :key="index">{{item.name}}:{{item.value}}</view>
- </view>-->
- <view :style="{
- backgroundColor: backgroundColor,
- backgroundImage: backgroundImage ? `url(${backgroundImage})` : `none`,
- backgroundPosition: backgroundPosition,
- backgroundSize: `${backgroundWidth}% ${backgroundHeight}%`,
- backgroundRepeat: backgroundRepeat,
- paddingTop: `${paddingTop}rpx`,
- paddingBottom: `${paddingBottom}rpx`,
- }">
- <view class="list"
- :class="[showItemBorder?'item-border':'', showAllItems?'show-all':'show-first',labelFs28?'label-fs-28':'']">
- <template v-for="(item, index) in myList">
- <view :key="index" v-if="item.key=='text'"
- class="item"
- :class="[itemClass, index===0 ? `is-first-item` : ``,]"
- :style="{
- 'padding': `0 ${itemPaddingX}rpx`,
- 'margin-bottom': `${itemMarginY}rpx`,
- }">
- <view v-if="labelPosition !== 'inset'" class="box-grow-0 cross-top label">
- <image v-if="showRequiredIcon && (item.is_required == 1 || item.is_required == '1')"
- class="required-icon"
- src="/static/image/icon/required.png"></image>
- <view class="name-key"
- :class="[`text-align-${labelTextAlign}`]"
- :style="{
- 'color': labelColor
- }">{{item.name}}
- </view>
- </view>
- <view class="box-grow-1">
- <app-input v-model="item.value"
- :default-value="item.default"
- :background-color="inputBackground"
- @input="textInput"
- :color="inputTextColor"
- :placeholder="labelPosition === 'inset' ? item.name:item.hint"
- :height="`${itemHeight}`"
- :border="showInputBorder"
- :radius="inputRadius"
- :placeholder-style="[`color:${inputPlaceholderColor}`]"
- :padding-left="getInputPaddingLeft"
- :border-color="inputBorderColor"></app-input>
- </view>
- </view>
- <view :key="index" v-if="item.key=='textarea'"
- class="item"
- :class="[itemClass, index===0 ? `is-first-item` : ``,]"
- :style="{
- 'padding': `0 ${itemPaddingX}rpx`,
- 'margin-bottom': `${itemMarginY}rpx`,
- }">
- <view v-if="labelPosition !== 'inset'" class="box-grow-0 cross-top label">
- <image v-if="showRequiredIcon && (item.is_required == 1 || item.is_required == '1')"
- class="required-icon"
- src="/static/image/icon/required.png"></image>
- <view class="name-key"
- :class="[`text-align-${labelTextAlign}`]"
- :style="{
- 'color': labelColor
- }">{{item.name}}
- </view>
- </view>
- <view class="box-grow-1">
- <app-textarea v-model="item.value"
- :default-value="item.value"
- :background="inputBackground"
- @input="textInput"
- :color="inputTextColor"
- :placeholder="labelPosition === 'inset' ? item.name:item.hint"
- :show-border="showInputBorder"
- :border-radius="inputRadius"
- :padding-x="getInputPaddingLeft"
- :placeholder-style="[`color:${inputPlaceholderColor}`]"
- :border-color="inputBorderColor"></app-textarea>
- </view>
- </view>
- <view :key="index" v-if="item.key=='date'"
- class="item"
- :class="[itemClass, index===0 ? `is-first-item` : ``,]"
- :style="{
- 'padding': `0 ${itemPaddingX}rpx`,
- 'margin-bottom': `${itemMarginY}rpx`,
- }">
- <view class="box-grow-0 cross-top label">
- <image v-if="showRequiredIcon && (item.is_required == 1 || item.is_required == '1')"
- class="required-icon"
- src="/static/image/icon/required.png"></image>
- <view class="name-key"
- :class="[`text-align-${labelTextAlign}`]"
- :style="{
- 'color': labelColor
- }">{{item.name}}
- </view>
- </view>
- <view class="box-grow-1">
- <app-datetime-picker v-model="item.value"
- @change="datetimeChange"
- :text="item.value||''"
- :sign="index"
- :show-border="showInputBorder"
- :background="inputBackground"
- :height="itemHeight"
- :radius="inputRadius"
- :default-value="item.default"
- :text-color="inputTextColor"
- :text-position="getDateTimeTextPosition"
- :border-color="inputBorderColor"
- :start="item.min ? item.min : ''"
- :padding="datePadding"
- :end="item.max ? item.max : ''">
- <!-- #ifdef MP-TOUTIAO -->
- {{item.value||''}}
- <!-- #endif -->
- </app-datetime-picker>
- </view>
- </view>
- <view :key="index" v-if="item.key=='time'"
- class="item"
- :class="[itemClass, index===0 ? `is-first-item` : ``,]"
- :style="{
- 'padding': `0 ${itemPaddingX}rpx`,
- 'margin-bottom': `${itemMarginY}rpx`,
- }">
- <view class="box-grow-0 cross-top label">
- <image v-if="showRequiredIcon && (item.is_required == 1 || item.is_required == '1')"
- class="required-icon"
- src="/static/image/icon/required.png"></image>
- <view class="name-key"
- :class="[`text-align-${labelTextAlign}`]"
- :style="{
- 'color': labelColor
- }">{{item.name}}
- </view>
- </view>
- <view class="box-grow-1">
- <app-datetime-picker v-model="item.value"
- @change="datetimeChange"
- mode="time"
- :text="item.value||''"
- :sign="index"
- :default-value="item.default"
- :show-border="showInputBorder"
- :background="inputBackground"
- :height="itemHeight"
- :radius="inputRadius"
- :text-color="inputTextColor"
- :text-position="getDateTimeTextPosition"
- :border-color="inputBorderColor"
- :start="item.min ? item.min : ''"
- :end="item.max ? item.max : ''">
- <!-- #ifdef MP-TOUTIAO -->
- {{item.value||''}}
- <!-- #endif -->
- </app-datetime-picker>
- </view>
- </view>
- <view :key="index" v-if="item.key=='radio'"
- class="item"
- :class="[itemClass, index===0 ? `is-first-item` : ``,]"
- :style="{
- 'padding': `0 ${itemPaddingX}rpx`,
- 'margin-bottom': `${itemMarginY}rpx`,
- }">
- <view class="box-grow-0 cross-top label">
- <image v-if="showRequiredIcon && (item.is_required == 1 || item.is_required == '1')"
- class="required-icon"
- src="/static/image/icon/required.png"></image>
- <view class="name-key"
- :class="[`text-align-${labelTextAlign}`]"
- :style="{
- 'color': labelColor
- }">{{item.name}}
- </view>
- </view>
- <view class="box-grow-1" :style="{
- padding: labelPosition === 'top' ? `0 0` : `0 12rpx`,
- }">
- <app-radio-group :list="item.list" v-model="item.value"
- :color="selectBoxColor"
- type="round"
- :height="74"
- @change="checkChange"></app-radio-group>
- </view>
- </view>
- <view :key="index" v-if="item.key=='checkbox'"
- class="item"
- :class="[itemClass, index===0 ? `is-first-item` : ``,]"
- :style="{
- 'padding': `0 ${itemPaddingX}rpx`,
- 'margin-bottom': `${itemMarginY}rpx`,
- }">
- <view class="box-grow-0 cross-top label">
- <image v-if="showRequiredIcon && (item.is_required == 1 || item.is_required == '1')"
- class="required-icon"
- src="/static/image/icon/required.png"></image>
- <view class="name-key"
- :class="[`text-align-${labelTextAlign}`]"
- :style="{
- 'color': labelColor
- }">{{item.name}}
- </view>
- </view>
- <view class="box-grow-1 dir-left-wrap" :style="{
- padding: labelPosition === 'top' ? `0 0` : `0 12rpx`,
- }">
- <app-diy-form-checkbox-group :list="item.list"
- v-model="item.value"
- :color="selectBoxColor"
- @change="checkChange"></app-diy-form-checkbox-group>
- </view>
- </view>
- <view :key="index" v-if="item.key=='img_upload'"
- class="item"
- :class="[itemClass, index===0 ? `is-first-item` : ``,]"
- :style="{
- 'padding': `0 ${itemPaddingX}rpx`,
- 'margin-bottom': `${itemMarginY}rpx`,
- }">
- <view class="box-grow-0 cross-top label">
- <image v-if="showRequiredIcon && (item.is_required == 1 || item.is_required == '1')"
- class="required-icon"
- src="/static/image/icon/required.png"></image>
- <view class="name-key"
- :class="[`text-align-${labelTextAlign}`]"
- :style="{
- 'color': labelColor
- }">{{item.name}}
- </view>
- </view>
- <view class="box-grow-1 dir-left-wrap" :style="{
- padding: labelPosition === 'top' ? `12rpx 0` : `12rpx 12rpx`,
- }">
- <!-- 普通图片 -->
- <template v-if="item.img_type == 1">
- <app-upload-image
- :value="uploadShowImage(item)"
- :max-num="item.num ? item.num:1"
- @image-event="handleImageUpload"
- :sign="`${index}`"
- :show-number="false"
- ></app-upload-image>
- </template>
- <!-- 身份证,正反面 -->
- <template v-if="item.img_type == 2">
- <app-upload-image
- :value="(item.value && item.value[0])?[item.value[0]]:null"
- style="margin-right: 12rpx"
- :max-num="1"
- @image-event="handleUserIdFrontUpload"
- :sign="`${index}`"
- text="身份证正面"
- :show-number="false"
- default-img="/static/image/user-id-card-front.png"></app-upload-image>
- <app-upload-image
- :value="(item.value && item.value[1])?[item.value[1]]:null"
- :max-num="1"
- @image-event="handleUserIdBackUpload"
- :sign="`${index}`"
- text="身份证反面"
- :show-number="false"
- default-img="/static/image/user-id-card-back.png"></app-upload-image>
- </template>
- <!-- 营业执照 -->
- <template v-if="item.img_type == 3">
- <app-upload-image
- :value="item.value?[item.value]:null"
- :max-num="1"
- @image-event="handleImageUpload"
- :sign="`${index}`"
- text="营业执照"
- :show-number="false"
- default-img="/static/image/company-license.png"></app-upload-image>
- </template>
- </view>
- </view>
- </template>
- </view>
- <view class="main-center cross-center scroll-bar" v-if="showScrollBtn"
- @click="showAllItems = !showAllItems">
- <view class="cross-center">点击{{showAllItems?'收起':'展开'}}</view>
- <view class="cross-center">
- <image v-if="showAllItems" src="/static/image/icon/icon-up.png"
- style="width: 18rpx;height: 10rpx;"></image>
- <image v-else src="/static/image/icon/icon-down.png"
- style="width: 18rpx;height: 10rpx;"></image>
- </view>
- </view>
- <view v-if="showSubmit" class="submit" :style="{
- 'padding': `${submitBtnMargin}rpx ${submitBtnPadding}rpx 24rpx`,
- }">
- <app-form-id @click="submit">
- <view class="submit-button" :style="{
- 'background-color': submitBtnBackground,
- 'border-color': submitBtnBorderColor,
- 'color': submitBtnTextColor,
- 'border-radius': `${submitBtnRadius}rpx`,
- 'height': `${submitBtnHeight}rpx`,
- 'line-height': `${submitBtnHeight-2}rpx`,
- }">{{submitBtnText}}
- </view>
- </app-form-id>
- </view>
- </view>
- </view>
- </template>
- <script>
- import AppDatetimePicker from '../../basic-component/app-datetime-picker/app-datetime-picker.vue';
- import AppRadio from "../../basic-component/app-radio/app-radio";
- import AppRadioGroup from "../../basic-component/app-radio/app-radio-group";
- import AppDiyFormCheckboxGroup from "./app-diy-form-checkbox-group";
- import AppUploadImage from "../../basic-component/app-upload-image/app-upload-image";
- import AppTextarea from "../../basic-component/app-textarea/app-textarea";
- export default {
- name: 'app-diy-form',
- components: {AppTextarea, AppUploadImage, AppDiyFormCheckboxGroup, AppRadioGroup, AppRadio, AppDatetimePicker},
- props: {
- sign: {
- default: null,
- },
- datePadding: {
- type: String,
- default: '0 24rpx',
- },
- title: {
- type: String,
- default: null,
- },
- backgroundColor: {
- default: '#ffffff',
- },
- backgroundImage: {
- default: null,
- },
- backgroundPosition: {
- default: 'center',
- },
- backgroundWidth: {
- default: 100,
- },
- backgroundHeight: {
- default: 100,
- },
- backgroundRepeat: {
- default: 'no-repeat',
- },
- marginTop: {
- default: 0,
- },
- marginBottom: {
- default: 0,
- },
- paddingTop: {
- default: 0,
- },
- paddingBottom: {
- default: 0,
- },
- list: {
- type: Array,
- default: [],
- },
- showRequiredIcon: {
- type: Boolean,
- default: false,
- },
- itemPaddingX: {
- default: 24,
- },
- itemMarginY: {
- default: 0,
- },
- itemHeight: {
- type: Number,
- default: 88,
- },
- showItemBorder: {
- default: true,
- },
- labelPosition: {
- default: 'left',
- },
- labelColor: {
- default: '#666666',
- },
- labelTextAlign: {
- default: 'right',
- },
- showInputBorder: {
- type: Boolean,
- default: false,
- },
- inputBackground: {
- default: '#ffffff',
- },
- inputBorderColor: {
- default: '#c0c4cc',
- },
- inputTextColor: {
- default: '#666666',
- },
- inputPlaceholderColor: {
- default: '#bbbbbb',
- },
- inputRadius: {
- default: 0,
- },
- showSubmit: {
- type: Boolean,
- default: false,
- },
- submitUrl: {
- type: String,
- default: null,
- },
- submitBtnText: {
- default: '提交',
- },
- submitBtnHeight: {
- default: 80,
- },
- submitBtnPadding: {
- default: 24,
- },
- submitBtnMargin: {
- default: 40,
- },
- submitBtnRadius: {
- default: 40,
- },
- submitBtnBackground: {
- default: '#ff4544',
- },
- submitBtnBorderColor: {
- default: '#ff4544',
- },
- submitBtnTextColor: {
- default: '#ffffff',
- },
- showScrollBtn: {
- default: false,
- },
- labelFs28: {
- default: false,
- },
- marginColor: {
- default: '#ffffff',
- },
- selectBoxColor: {
- default: '#ff4544',
- },
- },
- data() {
- const newList = [];
- for (let i in this.list) {
- const item = this.list[i];
- if (typeof item.default === 'undefined') {
- item.default = null;
- }
- if (typeof item.value === 'undefined' || item.value === null || item.value === '') {
- item.value = item.default;
- }
- item.hint = item.hint || '';
- if (item.key === 'radio' || item.key === 'checkbox') {
- if (!item.list) item.list = [];
- for (let j in item.list) {
- if (!item.list[j].value || item.list[j].value === false || item.list[j].value === 'false') {
- item.list[j].value = false;
- } else {
- item.list[j].value = true;
- }
- }
- }
- if (item.key === 'img_upload' && (item.img_type === 2 || item.img_type === '2') && !item.value) {
- item.value = ['', ''];
- }
- if(item.key == 'text') {
- }
- newList[i] = item;
- }
- return {
- myList: newList,
- randomString: '',
- validateResult: {
- hasError: false,
- errors: [],
- },
- showAllItems: this.showScrollBtn ? false : true,
- };
- },
- computed: {
- uploadShowImage() {
- return function (item) {
- if (Array.isArray(item.value)) {
- return item.value;
- }
- if (item.value) {
- return [item.value];
- }
- return null;
- }
- },
- itemClass() {
- if (this.labelPosition === 'left') {
- return 'label-left dir-left-nowrap cross-top';
- }
- if (this.labelPosition === 'inset') {
- return 'label-inset dir-left-nowrap cross-top';
- }
- if (this.labelPosition === 'top') {
- return 'label-top';
- }
- },
- getDateTimeTextPosition() {
- if (this.labelPosition === 'top') {
- return 'left';
- }
- return 'right';
- },
- getInputPaddingLeft() {
- if (this.labelPosition === 'top') {
- if (this.showInputBorder) {
- return 24;
- } else {
- return 0;
- }
- }
- return 24;
- },
- },
- created() {
- this.validate();
- this.outputData();
- },
- methods: {
- textInput() {
- this.outputData();
- },
- datetimeChange() {
- this.outputData();
- },
- checkChange() {
- setTimeout(() => {
- this.outputData();
- }, 10);
- },
- handleImageUpload(e) {
- const index = parseInt(e.sign);
- if (e.imageList.length === 1) {
- this.myList[index].value = e.imageList[0];
- } else if (e.imageList.length > 0) {
- this.myList[index].value = e.imageList;
- } else {
- this.myList[index].value = '';
- }
- this.outputData();
- },
- handleUserIdFrontUpload(e) {
- const index = parseInt(e.sign);
- if (e.imageList.length > 0) {
- this.myList[index].value[0] = e.imageList[0];
- } else {
- this.myList[index].value[0] = '';
- }
- this.outputData();
- },
- handleUserIdBackUpload(e) {
- const index = parseInt(e.sign);
- if (e.imageList.length > 0) {
- this.myList[index].value[1] = e.imageList[0];
- } else {
- this.myList[index].value[1] = '';
- }
- this.outputData();
- },
- validate() {
- this.validateResult = {
- hasError: false,
- errors: [],
- };
- for (let i in this.myList) {
- const item = this.myList[i];
- if (item.is_required === 1 || item.is_required === '1') {
- if (typeof item.value === 'undefined' || item.value === null || item.value === '') {
- this.validateResult.hasError = true;
- this.validateResult.errors.push({
- index: i,
- msg: `"${item.name}"不能为空。`,
- });
- continue;
- }
- if (item.img_type && parseInt(item.img_type) === 2) {
- if (!item.value || !item.value.length) {
- this.validateResult.hasError = true;
- this.validateResult.errors.push({
- index: i,
- msg: `"${item.name}"不能为空。`,
- });
- continue;
- }
- let imgErr = false;
- for (let j in item.value) {
- if (item.value[j] === null || item.value[j] === '') {
- imgErr = true;
- break;
- }
- }
- if (imgErr) {
- this.validateResult.hasError = true;
- this.validateResult.errors.push({
- index: i,
- msg: `"${item.name}"不能为空。`,
- });
- continue;
- }
- }
- }
- }
- this.$emit('validate', this.validateResult, this.sign);
- },
- outputData() {
- this.validate();
- for (let i in this.myList) {
- this.myList[i].label = this.myList[i].name;
- this.myList[i].required = this.myList[i].is_required;
- }
- this.$emit('input', this.myList, this.sign);
- // #ifdef MP-TOUTIAO
- setTimeout(() => {
- this.randomString = this.$utils.randomString(32);
- }, 1);
- // #endif
- },
- submit() {
- this.outputData();
- if (this.validateResult.hasError && this.validateResult.errors) {
- uni.showModal({
- title: '提示',
- content: this.validateResult.errors[0].msg,
- showCancel: false,
- });
- return;
- }
- uni.showLoading({
- mask: true,
- title: '正在提交...',
- });
- this.$request({
- url: this.submitUrl ? this.submitUrl : this.$api.diy.page_store,
- method: 'post',
- data: {
- form_data: JSON.stringify(this.myList),
- },
- }).then(response => {
- uni.hideLoading();
- if (response.code === 0) {
- setTimeout(() => {
- let copyList = this.myList;
- for (let i in copyList) {
- copyList[i].value = copyList[i].default;
- }
- this.myList = [];
- setTimeout(() => {
- this.myList = copyList;
- }, 0);
- }, 300);
- uni.showModal({
- title: '提示',
- content: response.msg || '提交成功',
- showCancel: false,
- });
- } else {
- uni.showModal({
- title: '提示',
- content: response.msg || '提交失败',
- showCancel: false,
- });
- }
- }).catch(() => {
- uni.hideLoading();
- });
- },
- },
- }
- </script>
- <style scoped lang="scss">
- .name-key {
- width: 100%;
- text-align: right;
- font-size: #{32rpx};
- color: #353535
- }
- .name-key.text-align-left {
- text-align: left;
- }
- .name-key.text-align-right {
- text-align: right;
- }
- .title {
- padding: #{24rpx};
- color: #999;
- font-size: #{26rpx};
- }
- .arrow {
- width: #{12rpx};
- height: #{22rpx};
- }
- .scroll-bar {
- border-top: #{1rpx} solid $uni-weak-color-one;
- height: #{72rpx};
- color: $uni-general-color-two;
- image {
- margin-left: #{16rpx};
- }
- }
- .list {
- .item {
- height: 0 !important;
- overflow: hidden;
- .label {
- min-width: #{125rpx};
- padding: #{12rpx} #{12rpx} #{12rpx} 0;
- height: 100%;
- position: relative;
- }
- .required-icon {
- width: #{15rpx};
- height: #{15rpx};
- display: inline-block;
- position: absolute;
- left: #{-14rpx};
- top: #{23rpx};
- }
- }
- .item.is-first-item {
- height: auto !important;
- overflow: auto;
- }
- .item.label-left {
- .name-key {
- max-width: #{200rpx};
- }
- }
- .item.label-top {
- .name-key {
- text-align: left;
- }
- .label {
- padding: #{20rpx} #{12rpx} #{8rpx} 0;
- }
- }
- .item:last-child {
- margin-bottom: 0 !important;
- }
- }
- .show-all {
- .item {
- height: auto !important;
- overflow: auto;
- }
- }
- .show-first {
- .item {
- margin-bottom: 0 !important;
- border: none !important;
- }
- }
- .item-border {
- .item {
- border-bottom: #{2rpx} solid $uni-weak-color-one;
- }
- .item:last-child {
- border-bottom: none;
- }
- }
- .submit-button {
- text-align: center;
- border: #{1rpx} solid;
- }
- .submit-button:active {
- box-shadow: inset 0 0 #{1000rpx} rgba(0, 0, 0, .15);
- }
- .label-fs-28 {
- .name-key {
- font-size: #{28rpx};
- }
- }
- </style>
|