|
|
@@ -0,0 +1,437 @@
|
|
|
+<template>
|
|
|
+ <view>
|
|
|
+ <block v-for="(item, index) in list " :key="item.key">
|
|
|
+ <!-- 文本输入 -->
|
|
|
+ <view class="input-box" v-if="item.type == 'text'" :style="{ marginTop: tovw(item.marginTop || 0) }"
|
|
|
+ @click="focusLabel = item.label">
|
|
|
+ <view class="box">
|
|
|
+ <view class="label">
|
|
|
+ <text class="must" v-if="item.isMust">*</text>
|
|
|
+ {{ item.label }}:
|
|
|
+ </view>
|
|
|
+ <view class="content-box">
|
|
|
+ <textarea auto-height type="text" :focus="focusLabel == item.label"
|
|
|
+ :placeholder="item.placeholder || '请填写' + item.label" :value="item.value"
|
|
|
+ :style="{ width: item.value ? '220px' : '240px' }" @input="onInput($event, index)"
|
|
|
+ :maxlength="item.maxlength || '499'" confirm-type="done" />
|
|
|
+ <icon v-if="item.value" class="icon" type="clear" size="3.733vw" @click="onClearInput(index)" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <!-- 自定义选项分类 -->
|
|
|
+ <view class="custom-class-box" v-else-if="item.type == 'customClass'"
|
|
|
+ :style="{ marginTop: tovw(item.marginTop || 0) }">
|
|
|
+ <view class="head">
|
|
|
+ <view class="label">
|
|
|
+ <text class="must" v-if="item.isMust">*</text>
|
|
|
+ {{ item.label }}
|
|
|
+ </view>
|
|
|
+ <view class="state">
|
|
|
+ {{ item.isMultipleChoice ? '可多选' : '仅单选' }}
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="options">
|
|
|
+ <view class="option"
|
|
|
+ :class="item.isMultipleChoice ? (item.value.includes(option.value) ? 'active' : '') : (item.value == option.value ? 'active' : '')"
|
|
|
+ v-for=" option in item.list " :key="option.value" hover-class="navigator-hover"
|
|
|
+ @click="changOptions(option.value, index)">
|
|
|
+ {{ option.remarks }}
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <!-- 上传附件 -->
|
|
|
+ <view class="custom-class-box" v-else-if="item.type == 'upload'"
|
|
|
+ :style="{ marginTop: tovw(item.marginTop || 0) }">
|
|
|
+ <view class="head">
|
|
|
+ <view class="label">
|
|
|
+ <text class="must" v-if="item.isMust">*</text>
|
|
|
+ {{ item.label }}
|
|
|
+ </view>
|
|
|
+ <view class="state">
|
|
|
+ {{ item.placeholder }}
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="content">
|
|
|
+ <view class="file-box" v-for="file in item.value" :key="file.attachmentid">
|
|
|
+ <image class="image" v-if="file.fileType == 'image'" :src="file.url" mode="aspectFill"
|
|
|
+ lazy-load="true" @click="previewImg(file)" />
|
|
|
+ <video v-else-if="file.fileType == 'video'" class="video" :poster="file.subfiles[0].url"
|
|
|
+ :src="file.url" />
|
|
|
+ <image class="delete" @click.stop="deleteFile(file, index)"
|
|
|
+ src="https://yossys06593.obs.cn-east-3.myhuaweicloud.com:443/202404241713944430197B47af9b2f.png"
|
|
|
+ mode="widthFix" />
|
|
|
+ </view>
|
|
|
+ <my-upload v-if="item.allowUpload" :showLoading="false" :accept="item.accept"
|
|
|
+ @uploadCallback="uploadCallback($event, index)" @onLoading="onUploadLoading($event, index)">
|
|
|
+ <view class="upload-box" hover-class="navigator-hover">
|
|
|
+ <u-loading-icon v-if="item.loading" />
|
|
|
+ <text v-else class="iconfont icon-xiazai" />
|
|
|
+ <text style="margin-left: 5px;">上传</text>
|
|
|
+ </view>
|
|
|
+ </my-upload>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </block>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import myUpload from "./my-upload.vue";
|
|
|
+import { formattedFiles, viewImage } from "../utils/settleFiles.js"
|
|
|
+export default {
|
|
|
+ name: "my_form",
|
|
|
+ components: { myUpload },
|
|
|
+ props: {
|
|
|
+ form: {
|
|
|
+ type: Array,
|
|
|
+ default: []
|
|
|
+ },
|
|
|
+ isUncomplete: {
|
|
|
+ type: Function
|
|
|
+ },
|
|
|
+ onUploading: {
|
|
|
+ type: Function
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ list: [],
|
|
|
+ focusLabel: ""
|
|
|
+ }
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ form: function (newVal) {
|
|
|
+ if (newVal) {
|
|
|
+ this.list = JSON.parse(JSON.stringify(newVal));
|
|
|
+ this.verify()
|
|
|
+ } else {
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async created() {
|
|
|
+ /* let list = [{
|
|
|
+ key: "name",
|
|
|
+ type: "text",
|
|
|
+ label: "标题",
|
|
|
+ isMust: true,//是否必填
|
|
|
+ value: "",
|
|
|
+ marginTop: 10
|
|
|
+ }, {
|
|
|
+ key: "Class",
|
|
|
+ type: "customClass",
|
|
|
+ label: "标题",
|
|
|
+ isMust: false,//是否必填
|
|
|
+ isMultipleChoice: true,//是否多选
|
|
|
+ value: [],// 多选[] 单选 ""
|
|
|
+ isMust: true,//是否必填
|
|
|
+ list: await this.getCustomClass('picturespace'),
|
|
|
+ marginTop: 10
|
|
|
+ },{
|
|
|
+ key: "attachmentids",
|
|
|
+ type: "upload",
|
|
|
+ label: "图片/视频",
|
|
|
+ accept:"all",
|
|
|
+ placeholder: "可上传多个视频或图片",
|
|
|
+ ownertable: "temporary",
|
|
|
+ ownerid: 999,
|
|
|
+ usetype: 'default',
|
|
|
+ allowUpload: true,
|
|
|
+ allowDelete: true,
|
|
|
+ value:[],
|
|
|
+ marginTop: 10
|
|
|
+ }] */
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ onInput(e, index) {
|
|
|
+ this.$set(this.list[index], 'value', e.detail.value)
|
|
|
+ if (this.list[index].isMust) this.verify()
|
|
|
+ },
|
|
|
+ onClearInput(index) {
|
|
|
+ this.$set(this.list[index], 'value', '')
|
|
|
+ if (this.list[index].isMust) this.verify()
|
|
|
+ },
|
|
|
+ changOptions(value, index) {
|
|
|
+ let item = this.list[index];
|
|
|
+ if (item.isMultipleChoice) {
|
|
|
+ let i = -1;
|
|
|
+ try {
|
|
|
+ i = item.value.findIndex(v => v == value)
|
|
|
+ } catch (error) {
|
|
|
+ }
|
|
|
+ if (i == -1) {
|
|
|
+ item.value.push(value)
|
|
|
+ } else {
|
|
|
+ item.value.splice(i, 1)
|
|
|
+ }
|
|
|
+ this.$set(this.list[index], 'value', item.value)
|
|
|
+ } else {
|
|
|
+ this.$set(this.list[index], 'value', value)
|
|
|
+ }
|
|
|
+ if (this.list[index].isMust) this.verify()
|
|
|
+ },
|
|
|
+ verify() {
|
|
|
+ let list = this.list.filter(v => v.isMust);
|
|
|
+ let Uncomplete = false;
|
|
|
+ if (list.length) Uncomplete = list.some(v => {
|
|
|
+ let res = false;
|
|
|
+ if (v.type == 'customClass') {
|
|
|
+ if (v.isMultipleChoice) {
|
|
|
+ res = v.value.length == 0;
|
|
|
+ } else {
|
|
|
+ res = v.value == "";
|
|
|
+ }
|
|
|
+ } else if (v.type == 'upload') {
|
|
|
+ res = v.value.length == 0;
|
|
|
+ } else {
|
|
|
+ res = v.value == "";
|
|
|
+ }
|
|
|
+ return res
|
|
|
+ })
|
|
|
+ this.$emit("isUncomplete", Uncomplete)
|
|
|
+ },
|
|
|
+ previewImg(item) {
|
|
|
+ viewImage(item.url)
|
|
|
+ },
|
|
|
+ uploadCallback(attachmentids, index) {
|
|
|
+ let item = this.list[index];
|
|
|
+ this.$Http.basic({
|
|
|
+ "classname": "system.attachment.Attachment",
|
|
|
+ "method": "createFileLink",
|
|
|
+ "content": {
|
|
|
+ ownertable: item.ownertable,
|
|
|
+ ownerid: item.ownerid,
|
|
|
+ usetype: item.usetype,
|
|
|
+ attachmentids
|
|
|
+ }
|
|
|
+ }).then(res => {
|
|
|
+ console.log('绑定附件', res)
|
|
|
+ if (this.cutoff(res.msg)) return;
|
|
|
+ res.data = formattedFiles(res.data)
|
|
|
+ item.value.push(res.data[0]);
|
|
|
+
|
|
|
+ //临时文件
|
|
|
+ if (res.data[0].ownertable == "temporary") try {
|
|
|
+ item.temporarys.push(attachmentids[0])
|
|
|
+ } catch (error) {
|
|
|
+ item.temporarys = [attachmentids[0]]
|
|
|
+ }
|
|
|
+
|
|
|
+ this.$set(this.list[index], 'value', item.value)
|
|
|
+ if (this.list[index].isMust) this.verify()
|
|
|
+ })
|
|
|
+ },
|
|
|
+ deleteFiles() {
|
|
|
+ this.list.forEach(v => {
|
|
|
+ if (v.type == 'upload') {
|
|
|
+ let linksids = v.value.filter(v => v.ownertable == "temporary").map(v => v.linksid)
|
|
|
+ if (linksids.length) this.$Http.basic({
|
|
|
+ "classname": "system.attachment.Attachment",
|
|
|
+ "method": "deleteFileLink",
|
|
|
+ "content": {
|
|
|
+ linksids
|
|
|
+ }
|
|
|
+ }).then(res => {
|
|
|
+ console.log("处理删除附件", res)
|
|
|
+ if (this.cutoff(res.msg)) return;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ onUploadLoading(e, index) {
|
|
|
+ this.$set(this.list[index], 'loading', e)
|
|
|
+ this.$emit("onUploading", e)
|
|
|
+ },
|
|
|
+ deleteFile(flie, index) {
|
|
|
+ let item = this.list[index];
|
|
|
+ item.value = item.value.filter(v => v.attachmentid != flie.attachmentid)
|
|
|
+ //临时文件
|
|
|
+ if (flie.ownertable == "temporary") {
|
|
|
+ item.temporarys = item.temporarys.filter(v => v != flie.attachmentid)
|
|
|
+ this.$Http.basic({
|
|
|
+ "classname": "system.attachment.Attachment",
|
|
|
+ "method": "deleteFileLink",
|
|
|
+ "content": {
|
|
|
+ linksids: [flie.linksid]
|
|
|
+ }
|
|
|
+ }).then(res => {
|
|
|
+ console.log("处理删除附件", res)
|
|
|
+ if (this.cutoff(res.msg)) return;
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ try {
|
|
|
+ item.linksids.push(flie.linksid)
|
|
|
+ } catch (error) {
|
|
|
+ item.linksids = [flie.linksid]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.$set(this.list[index], 'value', item.value)
|
|
|
+ if (this.list[index].isMust) this.verify()
|
|
|
+ },
|
|
|
+ submit() {
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ let res = {};
|
|
|
+ this.list.forEach(v => {
|
|
|
+ if (v.type == 'upload') {
|
|
|
+ res.files = {
|
|
|
+ temporarys: [],
|
|
|
+ linksids: [],
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ res.files.temporarys = v.temporarys || []
|
|
|
+ } catch (error) {
|
|
|
+
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ res.files.linksids = v.linksids || []
|
|
|
+ } catch (error) {
|
|
|
+
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ res[v.key] = v.value;
|
|
|
+ }
|
|
|
+ })
|
|
|
+ resolve(res)
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss">
|
|
|
+.custom-class-box {
|
|
|
+ width: 100%;
|
|
|
+ background: #fff;
|
|
|
+ padding: 15px 0 15px 10px;
|
|
|
+ box-sizing: border-box;
|
|
|
+
|
|
|
+ .head {
|
|
|
+ width: 355px;
|
|
|
+ height: 20px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: flex-end;
|
|
|
+
|
|
|
+ .label {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #333333;
|
|
|
+ line-height: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .state {
|
|
|
+ font-family: Source Han Sans SC, Source Han Sans SC;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #999999;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .options {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+
|
|
|
+ .option {
|
|
|
+ padding: 6px 10px;
|
|
|
+ text-align: center;
|
|
|
+ min-width: 81px;
|
|
|
+ font-family: PingFang SC, PingFang SC;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #333333;
|
|
|
+ border-radius: 5px;
|
|
|
+ background: #F2F2F2;
|
|
|
+ margin-top: 10px;
|
|
|
+ margin-right: 10px;
|
|
|
+ box-sizing: border-box;
|
|
|
+ }
|
|
|
+
|
|
|
+ .active {
|
|
|
+ background: #C30D23;
|
|
|
+ color: #fff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .content {
|
|
|
+ .file-box {
|
|
|
+ position: relative;
|
|
|
+ width: 355px;
|
|
|
+ height: 240px;
|
|
|
+ margin-top: 10px;
|
|
|
+
|
|
|
+ .video,
|
|
|
+ .image {
|
|
|
+ width: 355px;
|
|
|
+ height: 240px;
|
|
|
+ border-radius: 5px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .delete {
|
|
|
+ position: absolute;
|
|
|
+ width: 30px;
|
|
|
+ top: 0;
|
|
|
+ right: 0;
|
|
|
+ z-index: 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .upload-box {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ width: 355px;
|
|
|
+ height: 45px;
|
|
|
+ background: #FFFFFF;
|
|
|
+ border-radius: 5px;
|
|
|
+ border: 1px dashed #C30D23;
|
|
|
+ font-family: Source Han Sans SC, Source Han Sans SC;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #C30D23;
|
|
|
+ margin-top: 10px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.input-box {
|
|
|
+ width: 100vw;
|
|
|
+ background: #fff;
|
|
|
+ box-sizing: border-box;
|
|
|
+ padding-left: 10px;
|
|
|
+
|
|
|
+ .box {
|
|
|
+ display: flex;
|
|
|
+ width: 100%;
|
|
|
+ min-height: 54.4px;
|
|
|
+ padding: 15px 0;
|
|
|
+ box-sizing: border-box;
|
|
|
+ border-bottom: 1px #DDDDDD solid;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .label {
|
|
|
+ width: 100px;
|
|
|
+ margin-right: 10px;
|
|
|
+ line-height: 20px;
|
|
|
+ font-family: Source Han Sans SC, Source Han Sans SC;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #666666;
|
|
|
+ flex-shrink: 0;
|
|
|
+
|
|
|
+ .must {
|
|
|
+ color: #E3041F;
|
|
|
+ margin-right: 5px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .content-box {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding-right: 10px;
|
|
|
+ box-sizing: border-box;
|
|
|
+
|
|
|
+ .icon {
|
|
|
+ padding: 5px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+</style>
|