| 作者 | SHA1 | 备注 | 提交日期 |
|---|---|---|---|
|
|
19cf75a36d | Merge branch 'master' of http://218.59.175.43:3000/zhangzl/rongxin.dashboard | 2 个月前 |
|
|
ca28b7150f | 组件化2 | 2 个月前 |
|
|
26d6c1a2c9 | 组件化 | 2 个月前 |
| @@ -17,3 +17,17 @@ export function addNotice(data) { | |||||
| data: data | data: data | ||||
| }) | }) | ||||
| } | } | ||||
| //上传全局方法附件 | |||||
| export function commonUpload(data) { | |||||
| return request({ | |||||
| url: '/common/upload', | |||||
| method: 'post', | |||||
| data: data, | |||||
| timeout: 60000, // 延长超时时间 | |||||
| headers: { | |||||
| // 不设置 Content-Type,让浏览器自动设置 | |||||
| } | |||||
| }) | |||||
| } | |||||
| @@ -1,160 +1,399 @@ | |||||
| <!-- 通用上传组件 zhao --> | |||||
| <template> | <template> | ||||
| <van-uploader | |||||
| v-model="fileList" | |||||
| :multiple="multiple" | |||||
| :after-read="afterRead" | |||||
| :show-upload="showUpload" | |||||
| :deletable="deletable" | |||||
| @delete="deleteFile" | |||||
| :accept="accept || null" | |||||
| /> | |||||
| <div class="component-upload-image"> | |||||
| <!-- 上传区域 --> | |||||
| <el-upload | |||||
| multiple | |||||
| :disabled="disabled" | |||||
| :action="uploadImgUrl" | |||||
| list-type="picture-card" | |||||
| :on-success="handleUploadSuccess" | |||||
| :before-upload="handleBeforeUpload" | |||||
| :data="data" | |||||
| :limit="limit" | |||||
| :on-error="handleUploadError" | |||||
| :on-exceed="handleExceed" | |||||
| ref="imageUpload" | |||||
| :on-remove="handleDelete" | |||||
| :show-file-list="true" | |||||
| :headers="headers" | |||||
| :file-list="fileList" | |||||
| :on-preview="handlePictureCardPreview" | |||||
| :class="{hide: fileList.length >= limit}" | |||||
| style="grid-template-columns: repeat(auto-fill, minmax(70px, 1fr)); gap: 12px; padding: 0;" | |||||
| > | |||||
| <!-- 上传按钮 --> | |||||
| <div class="upload-btn"> | |||||
| <i class="el-icon-plus" style="font-size: 20px;"></i> | |||||
| </div> | |||||
| </el-upload> | |||||
| <!-- 上传提示:关键调整 - 减小与上传框的间距 --> | |||||
| <div class="el-upload__tip" slot="tip" v-if="showTip && !disabled" style="font-size: 12px; margin-top: 4px; line-height: 1.4;"> | |||||
| <template v-if="fileSize"> 大小: ≤ <b style="color: #f56c6c">{{ fileSize }}MB</b> </template> | |||||
| <template v-if="fileType && fileSize">,</template> | |||||
| <template v-if="fileType"> 格式: <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template> | |||||
| </div> | |||||
| <!-- 预览弹窗 --> | |||||
| <el-dialog :visible.sync="dialogVisible" title="预览" :width="dialogWidth" append-to-body :close-on-click-modal="true"> | |||||
| <img :src="dialogImageUrl" style="display: block; max-width: 100%; max-height: 70vh; margin: 0 auto;" @load="handleImageLoad"/> | |||||
| </el-dialog> | |||||
| </div> | |||||
| </template> | </template> | ||||
| <script> | <script> | ||||
| import { getToken } from "@/utils/auth"; | |||||
| import { isExternal } from "@/utils/validate"; | |||||
| import Sortable from 'sortablejs'; | |||||
| import {Dialog} from "vant"; | |||||
| import {commonUpload} from "@/api/sunVillage_info/fixedAssets"; | |||||
| export default { | |||||
| name: "commonUpload", | |||||
| props: { | |||||
| name: String, | |||||
| value: { // 绑定值 字符串 ,分隔 可监听 | |||||
| type: String, | |||||
| default: null, | |||||
| }, | |||||
| accept: { // 上传类型限制: 默认图片, * = 任意类型 | |||||
| type: String, | |||||
| }, | |||||
| multiple: { // 多文件上传 | |||||
| type: Boolean, | |||||
| default: false, | |||||
| }, | |||||
| deletable: { // 允许删除 | |||||
| type: Boolean, | |||||
| default: true, | |||||
| }, | |||||
| showUpload: { // 显示上传按钮 | |||||
| type: Boolean, | |||||
| default: true, | |||||
| }, | |||||
| formData: { // 额外请求参数 | |||||
| type: Object, | |||||
| default: function() { | |||||
| return {}; | |||||
| export default { | |||||
| props: { | |||||
| value: [String, Object, Array], | |||||
| action: { | |||||
| type: String, | |||||
| default: "/common/upload" | |||||
| }, | }, | ||||
| data: { | |||||
| type: Object | |||||
| }, | |||||
| limit: { | |||||
| type: Number, | |||||
| default: 5 | |||||
| }, | |||||
| fileSize: { | |||||
| type: Number, | |||||
| default: 3 | |||||
| }, | |||||
| fileType: { | |||||
| type: Array, | |||||
| default: () => ["png", "jpg", "jpeg"] | |||||
| }, | |||||
| isShowTip: { | |||||
| type: Boolean, | |||||
| default: true | |||||
| }, | |||||
| disabled: { | |||||
| type: Boolean, | |||||
| default: false | |||||
| }, | |||||
| drag: { | |||||
| type: Boolean, | |||||
| default: false | |||||
| } | |||||
| }, | }, | ||||
| file: { // 上传文件字段名 | |||||
| type: String, | |||||
| default: 'file', | |||||
| }, | |||||
| host: { | |||||
| type: String, // 文件地址前缀 | |||||
| default: '/api', | |||||
| data() { | |||||
| return { | |||||
| number: 0, | |||||
| uploadList: [], | |||||
| dialogImageUrl: "", | |||||
| dialogVisible: false, | |||||
| dialogWidth: "90%", | |||||
| baseUrl: process.env.VUE_APP_BASE_API, | |||||
| uploadImgUrl: process.env.VUE_APP_BASE_API + this.action, | |||||
| headers: { | |||||
| Authorization: "Bearer " + getToken(), | |||||
| }, | |||||
| fileList: [] | |||||
| }; | |||||
| }, | }, | ||||
| }, | |||||
| watch: { | |||||
| value: function (newVal, oldVal) { | |||||
| if(newVal != this.internalValue) | |||||
| this.setInternalValue(newVal); | |||||
| mounted() { | |||||
| if (this.drag && !this.disabled) { | |||||
| this.$nextTick(() => { | |||||
| const element = this.$refs.imageUpload?.$el?.querySelector('.el-upload-list'); | |||||
| if (element) { | |||||
| Sortable.create(element, { | |||||
| onEnd: (evt) => { | |||||
| const movedItem = this.fileList.splice(evt.oldIndex, 1)[0]; | |||||
| this.fileList.splice(evt.newIndex, 0, movedItem); | |||||
| this.$emit("input", this.listToString(this.fileList)); | |||||
| }, | |||||
| handle: ".el-upload-list__item", | |||||
| animation: 150 | |||||
| }); | |||||
| } | |||||
| }); | |||||
| } | |||||
| window.addEventListener("resize", this.adjustDialogWidth); | |||||
| }, | }, | ||||
| }, | |||||
| created() { | |||||
| this.parseValue(this.value); | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| internalValue: this.value, | |||||
| fileList: [], | |||||
| pathList: [], | |||||
| }; | |||||
| }, | |||||
| methods: { | |||||
| setInternalValue(newVal) { | |||||
| this.parseValue(newVal); | |||||
| this.internalValue = newVal; | |||||
| beforeDestroy() { | |||||
| window.removeEventListener("resize", this.adjustDialogWidth); | |||||
| }, | }, | ||||
| parseValue(data) { | |||||
| if(data) | |||||
| { | |||||
| this.pathList = data.split(','); | |||||
| } | |||||
| else | |||||
| { | |||||
| this.pathList = []; | |||||
| watch: { | |||||
| value: { | |||||
| handler(val) { | |||||
| if (val) { | |||||
| const list = Array.isArray(val) ? val : val.split(','); | |||||
| this.fileList = list.map(item => { | |||||
| if (typeof item === "string") { | |||||
| const imgUrl = !isExternal(item) && item.indexOf(this.baseUrl) === -1 | |||||
| ? `${this.baseUrl}${item}` | |||||
| : item; | |||||
| return { | |||||
| name: imgUrl, | |||||
| url: imgUrl, | |||||
| response: { url: imgUrl } | |||||
| }; | |||||
| } | |||||
| return item; | |||||
| }); | |||||
| } else { | |||||
| this.fileList = []; | |||||
| } | |||||
| }, | |||||
| deep: true, | |||||
| immediate: true | |||||
| } | } | ||||
| this.fileList = this.pathList.map((x) => { | |||||
| return { | |||||
| url: this.host + x, | |||||
| }; | |||||
| }); | |||||
| }, | }, | ||||
| makeFormData() { | |||||
| let fd = new FormData(); | |||||
| if(this.formData) | |||||
| { | |||||
| for(let k of Object.keys(this.formData)) | |||||
| { | |||||
| fd.set(k, this.formData[k]); | |||||
| } | |||||
| computed: { | |||||
| showTip() { | |||||
| return this.isShowTip && (this.fileType.length || this.fileSize); | |||||
| } | } | ||||
| return fd; | |||||
| }, | }, | ||||
| upload(file) { | |||||
| let params1 = this.makeFormData(); | |||||
| params1.append(this.file, file.file); | |||||
| return commonUpload(params1).then((resp) => { | |||||
| this.pathList.push(resp.fileName); | |||||
| this.updateInternalValue(); | |||||
| this.$emit('upload', resp.fileName); | |||||
| }); | |||||
| }, | |||||
| afterRead(file) { | |||||
| this.$toast.loading({ | |||||
| message: "上传中...", | |||||
| forbidClick: true, | |||||
| duration: 0, | |||||
| }); | |||||
| // 此时可以自行将文件上传至服务器 | |||||
| if (file instanceof Array) {//判断是否为数组,单张图片为array,多张为数组,数组返回true否则为false | |||||
| if(file.length > 0) | |||||
| { | |||||
| let index = 0; | |||||
| const f = () => { | |||||
| if(index >= file.length) | |||||
| return; | |||||
| let up = file[index]; | |||||
| //console.log(up); | |||||
| console.log(`上传文件: ${index} -> ${up.file.name}`); | |||||
| this.upload(up).then(() => { | |||||
| index++; | |||||
| if(index < file.length) | |||||
| f(); | |||||
| }); | |||||
| }; | |||||
| f(); | |||||
| methods: { | |||||
| adjustDialogWidth() { | |||||
| const screenWidth = window.innerWidth; | |||||
| this.dialogWidth = screenWidth < 375 ? "95%" : "90%"; | |||||
| }, | |||||
| handleBeforeUpload(file) { | |||||
| let isImg = false; | |||||
| const fileExtension = file.name.lastIndexOf(".") > -1 | |||||
| ? file.name.slice(file.name.lastIndexOf(".") + 1).toLowerCase() | |||||
| : ""; | |||||
| if (this.fileType.length) { | |||||
| isImg = this.fileType.includes(fileExtension) || file.type.includes(fileExtension); | |||||
| } else { | |||||
| isImg = file.type.indexOf("image") > -1; | |||||
| } | |||||
| if (!isImg) { | |||||
| this.$modal.msgError(`请上传${this.fileType.join("/")}格式图片`); | |||||
| return false; | |||||
| } | |||||
| if (file.name.includes(',')) { | |||||
| this.$modal.msgError("文件名不能包含英文逗号"); | |||||
| return false; | |||||
| } | |||||
| if (this.fileSize) { | |||||
| const isLt = file.size / 1024 / 1024 < this.fileSize; | |||||
| if (!isLt) { | |||||
| this.$modal.msgError(`图片大小不能超过${this.fileSize}MB`); | |||||
| return false; | |||||
| } | |||||
| } | |||||
| this.$modal.loading({ | |||||
| message: "上传中...", | |||||
| lock: false | |||||
| }); | |||||
| this.number++; | |||||
| }, | |||||
| handleExceed() { | |||||
| this.$modal.msgError(`最多可上传${this.limit}张图片`); | |||||
| }, | |||||
| handleUploadSuccess(res, file) { | |||||
| if (res.code === 200) { | |||||
| this.uploadList.push({ | |||||
| name: res.fileName, | |||||
| url: res.fileName, | |||||
| response: { url: `${this.baseUrl}${res.fileName}` } | |||||
| }); | |||||
| this.uploadedSuccessfully(); | |||||
| } else { | |||||
| this.number--; | |||||
| this.$modal.closeLoading(); | |||||
| this.$modal.msgError(res.msg || "上传失败"); | |||||
| this.$refs.imageUpload?.handleRemove(file); | |||||
| } | |||||
| }, | |||||
| handleDelete(file, list) { | |||||
| Dialog.confirm({ | |||||
| title: '提示', | |||||
| message: '确定要移除这张图片吗?', | |||||
| }) | |||||
| .then(() => { | |||||
| const findex = this.fileList.map(f => f.name).indexOf(file.name); | |||||
| if (findex > -1) { | |||||
| this.fileList.splice(findex, 1); | |||||
| this.$emit("input", this.listToString(this.fileList)); | |||||
| } | |||||
| }) | |||||
| .catch(() => { | |||||
| // on cancel | |||||
| }); | |||||
| }, | |||||
| handleUploadError() { | |||||
| this.$modal.closeLoading(); | |||||
| this.$modal.msgError("上传失败,请重试"); | |||||
| }, | |||||
| uploadedSuccessfully() { | |||||
| if (this.number > 0 && this.uploadList.length === this.number) { | |||||
| this.fileList = this.fileList.concat(this.uploadList); | |||||
| this.uploadList = []; | |||||
| this.number = 0; | |||||
| this.$emit("input", this.listToString(this.fileList)); | |||||
| this.$modal.closeLoading(); | |||||
| this.$modal.msgSuccess("全部上传完成"); | |||||
| } | |||||
| }, | |||||
| handlePictureCardPreview(file) { | |||||
| this.dialogImageUrl = file.url || file.response?.url; | |||||
| this.adjustDialogWidth(); | |||||
| this.dialogVisible = true; | |||||
| }, | |||||
| handleImageLoad(e) { | |||||
| const img = e.target; | |||||
| const maxHeight = window.innerHeight * 0.7; | |||||
| if (img.height > maxHeight) { | |||||
| img.style.height = `${maxHeight}px`; | |||||
| img.style.width = "auto"; | |||||
| } | } | ||||
| } else { | |||||
| this.upload(file); | |||||
| }, | |||||
| listToString(list, separator) { | |||||
| separator = separator || ","; | |||||
| return list | |||||
| .filter(item => item.url) | |||||
| .map(item => item.url.replace(this.baseUrl, "")) | |||||
| .join(separator); | |||||
| } | } | ||||
| }, | |||||
| deleteFile(detail){ | |||||
| this.pathList.splice(detail.index,1); | |||||
| this.updateInternalValue(); | |||||
| this.$emit('remove', detail.index); | |||||
| }, | |||||
| updateInternalValue() { | |||||
| let files = this.pathList.join(','); | |||||
| console.log(files); | |||||
| this.internalValue = files; | |||||
| if(this.internalValue != this.value) | |||||
| this.$emit('input', this.internalValue); | |||||
| }, | |||||
| }, | |||||
| } | |||||
| } | |||||
| }; | |||||
| </script> | </script> | ||||
| <style scoped> | |||||
| <style scoped lang="scss"> | |||||
| // 上传按钮样式 | |||||
| .upload-btn { | |||||
| width: 60px; | |||||
| height: 60px; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| border: 1px dashed #dcdcdc; | |||||
| border-radius: 4px; | |||||
| background-color: #fafafa; | |||||
| margin: 0; | |||||
| transition: all 0.2s; | |||||
| &:hover { | |||||
| border-color: #409eff; | |||||
| background-color: #f5faff; | |||||
| } | |||||
| &:active { | |||||
| background-color: #f0f7ff; | |||||
| } | |||||
| } | |||||
| // 已上传图片项样式 | |||||
| ::v-deep .el-upload-list--picture-card .el-upload-list__item { | |||||
| width: 60px; | |||||
| height: 60px; | |||||
| border-radius: 4px; | |||||
| overflow: hidden; | |||||
| position: relative; | |||||
| border: 1px solid #e5e7eb; | |||||
| .el-upload-list__item-thumbnail { | |||||
| object-fit: cover; | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| } | |||||
| .el-upload-list__item-delete { | |||||
| position: absolute; | |||||
| top: -8px; | |||||
| right: -8px; | |||||
| width: 20px; | |||||
| height: 20px; | |||||
| font-size: 12px; | |||||
| background-color: #f56c6c; | |||||
| color: #fff; | |||||
| border-radius: 50%; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| box-shadow: 0 2px 4px rgba(0,0,0,0.1); | |||||
| z-index: 10; | |||||
| &:hover, &:active { | |||||
| width: 22px; | |||||
| height: 22px; | |||||
| background-color: #e4393c; | |||||
| top: -9px; | |||||
| right: -9px; | |||||
| } | |||||
| } | |||||
| &:hover { | |||||
| border-color: #409eff; | |||||
| } | |||||
| &:hover .el-upload-list__item-delete { | |||||
| opacity: 1; | |||||
| } | |||||
| } | |||||
| // 移除外层默认边框 | |||||
| ::v-deep .el-upload--picture-card { | |||||
| border: none !important; | |||||
| background: transparent !important; | |||||
| margin-bottom: 0 !important; /* 移除上传组件底部默认边距 */ | |||||
| } | |||||
| // 隐藏上传按钮(数量达限时) | |||||
| ::v-deep.hide .el-upload--picture-card { | |||||
| display: none; | |||||
| } | |||||
| // 禁用状态样式 | |||||
| ::v-deep .el-upload-list--picture-card.is-disabled + .el-upload--picture-card { | |||||
| display: none !important; | |||||
| } | |||||
| // 列表动画优化 | |||||
| ::v-deep .el-list-enter-active, | |||||
| ::v-deep .el-list-leave-active { | |||||
| transition: all 0s; | |||||
| } | |||||
| ::v-deep .el-list-enter, | |||||
| ::v-deep .el-list-leave-active { | |||||
| opacity: 0; | |||||
| transform: translateY(0); | |||||
| } | |||||
| // 小屏幕适配 | |||||
| @media screen and (max-width: 375px) { | |||||
| .upload-btn, | |||||
| ::v-deep .el-upload-list--picture-card .el-upload-list__item { | |||||
| width: 55px; | |||||
| height: 55px; | |||||
| } | |||||
| .el-upload--picture-card { | |||||
| grid-template-columns: repeat(auto-fill, minmax(55px, 1fr)); | |||||
| gap: 8px; | |||||
| } | |||||
| // 提示文字进一步缩小间距 | |||||
| .el-upload__tip { | |||||
| margin-top: 3px !important; | |||||
| font-size: 11px !important; | |||||
| } | |||||
| ::v-deep .el-upload-list__item-delete { | |||||
| width: 18px; | |||||
| height: 18px; | |||||
| top: -7px; | |||||
| right: -7px; | |||||
| &:hover, &:active { | |||||
| width: 20px; | |||||
| height: 20px; | |||||
| top: -8px; | |||||
| right: -8px; | |||||
| } | |||||
| } | |||||
| } | |||||
| </style> | </style> | ||||
| @@ -416,3 +416,265 @@ export function save(name, src) { | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * 解析日期时间 | |||||
| * @param date 日期时间字符串 字符串 | |||||
| * @param format 格式化字符串 字符串 默认 yyyy-MM-dd HH:mm:ss | |||||
| * @param initNow 缺省部分是否使用当前日期时间部分代替 bool 默认不使用当前 | |||||
| * @returns {Date} 解析日期时间出来的Date对象 | |||||
| */ | |||||
| export function strtotime(date, format, initNow) | |||||
| { | |||||
| if (!date) | |||||
| return null; | |||||
| let expect = function(target, str) { | |||||
| if(Array.isArray(target)) | |||||
| { | |||||
| let res = 0; | |||||
| if(typeof(target[0]) === 'number') | |||||
| { | |||||
| for(let t of target) | |||||
| { | |||||
| if(str.length >= t) | |||||
| { | |||||
| if(t > res && new RegExp(`^\\d{${t}}`).test(str)) | |||||
| res = t; | |||||
| } | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| for(let t of target) | |||||
| { | |||||
| if(str.length < t.length) | |||||
| continue; | |||||
| if(str.startsWith(t)) | |||||
| { | |||||
| res = t.length; | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| return res; | |||||
| } | |||||
| else | |||||
| { | |||||
| if(typeof(target) === 'number') | |||||
| { | |||||
| if(str.length < target) | |||||
| return 0; | |||||
| if(!new RegExp(`^\\d{${target}}`).test(str)) | |||||
| return null; | |||||
| return target; | |||||
| } | |||||
| else if(typeof(target) === 'object') | |||||
| { | |||||
| let res = 0; | |||||
| let min = target.min || 0; | |||||
| let max = target.max; | |||||
| for(let m = min; m <= max; m++) | |||||
| { | |||||
| let t = '' + m; | |||||
| if(str.length >= t.length) | |||||
| { | |||||
| if(str.startsWith(t)) | |||||
| res = t.length; | |||||
| } | |||||
| } | |||||
| return res; | |||||
| } | |||||
| else | |||||
| { | |||||
| if(str.length < target.length) | |||||
| return 0; | |||||
| if(!str.startsWith(target)) | |||||
| return 0; | |||||
| return target.length; | |||||
| } | |||||
| } | |||||
| }; | |||||
| format = format || 'yyyy-MM-dd HH:mm:ss'; | |||||
| let arr = parseDateTimeFormatter(format); | |||||
| let i = 0; | |||||
| let _y = undefined; | |||||
| let _m = undefined; | |||||
| let _d = undefined; | |||||
| let _h = undefined; | |||||
| let _i = undefined; | |||||
| let _s = undefined; | |||||
| let _z = undefined; | |||||
| let _h_12 = undefined; | |||||
| let _ap = undefined; | |||||
| let get_token = function(str, target) { | |||||
| let r = expect(target, date.substr(i)); | |||||
| if(r <= 0) | |||||
| return null; | |||||
| let nstr = date.substr(i, r); | |||||
| i += r; | |||||
| return nstr; | |||||
| }; | |||||
| //console.log(arr); | |||||
| for(let part of arr) | |||||
| { | |||||
| if(part.type === DATE_TIME_FORMAT_TYPE_RAW || part.type === DATE_TIME_FORMAT_TYPE_IGNORE) | |||||
| { | |||||
| let r = expect(part.str, date.substr(i)); | |||||
| if(!r) | |||||
| return null; | |||||
| i += r; | |||||
| } | |||||
| else | |||||
| { | |||||
| let p = null; | |||||
| switch(part.str) | |||||
| { | |||||
| case 'yyyy': | |||||
| case '%Y': | |||||
| p = get_token(part.str, 4); | |||||
| if(p) | |||||
| _y = parseInt(p); | |||||
| break; | |||||
| case 'yy': | |||||
| case '%y': | |||||
| p = get_token(part.str, 2); | |||||
| if(p) | |||||
| _y = Math.floor((date.getFullYear()) / 100) * 100 + parseInt(p); | |||||
| break; | |||||
| case 'MM': | |||||
| case '%m': | |||||
| p = get_token(part.str, 2); | |||||
| if(p) | |||||
| _m = parseInt(p); | |||||
| break; | |||||
| case 'M': | |||||
| case '%c': | |||||
| p = get_token(part.str, {min: 1, max: 12}); | |||||
| if(p) | |||||
| _m = parseInt(p); | |||||
| break; | |||||
| case 'MMMM': | |||||
| case '%M': | |||||
| p = get_token(part.str, MONTHS); | |||||
| if(p) | |||||
| _m = MONTHS.indexOf(p) + 1; | |||||
| break; | |||||
| case 'MMM': | |||||
| case '%b': | |||||
| p = get_token(part.str, MONTHS_SIMPLE); | |||||
| if(p) | |||||
| _m = MONTHS_SIMPLE.indexOf(p) + 1; | |||||
| break; | |||||
| case 'dd': | |||||
| case '%d': | |||||
| p = get_token(part.str, 2); | |||||
| if(p) | |||||
| _d = parseInt(p); | |||||
| break; | |||||
| case 'HH': | |||||
| case '%H': | |||||
| p = get_token(part.str, 2); | |||||
| if(p) | |||||
| _h = parseInt(p); | |||||
| break; | |||||
| case 'H': | |||||
| case '%k': | |||||
| p = get_token(part.str, {max: 23}); | |||||
| if(p) | |||||
| _h = parseInt(p); | |||||
| break; | |||||
| case 'hh': | |||||
| case '%I': | |||||
| case '%h': | |||||
| p = get_token(part.str, 2); | |||||
| if(p) | |||||
| _h_12 = parseInt(p); | |||||
| break; | |||||
| case 'h': | |||||
| case '%l': | |||||
| p = get_token(part.str, {max: 12}); | |||||
| if(p) | |||||
| _h_12 = parseInt(p); | |||||
| break; | |||||
| case 'mm': | |||||
| case 'ii': | |||||
| case '%i': | |||||
| p = get_token(part.str, 2); | |||||
| if(p) | |||||
| _i = parseInt(p); | |||||
| break; | |||||
| case 'm': | |||||
| case 'i': | |||||
| p = get_token(part.str, {max: 59}); | |||||
| if(p) | |||||
| _i = parseInt(p); | |||||
| break; | |||||
| case 'ss': | |||||
| case '%s': | |||||
| case '%S': | |||||
| p = get_token(part.str, 2); | |||||
| if(p) | |||||
| _s = parseInt(p); | |||||
| break; | |||||
| case 's': | |||||
| p = get_token(part.str, {max: 59}); | |||||
| if(p) | |||||
| _s = parseInt(p); | |||||
| break; | |||||
| case 'sss': | |||||
| p = get_token(part.str, {max: 999}); | |||||
| if(p) | |||||
| _z = parseInt(p); | |||||
| break; | |||||
| case 'A': | |||||
| case 'p': { | |||||
| const AP = ['AM', 'PM']; | |||||
| p = get_token(part.str, AP); | |||||
| if(p) | |||||
| _ap = p.toLowerCase(); | |||||
| } | |||||
| break; | |||||
| case 'a': | |||||
| case 'P': | |||||
| case '%p':{ | |||||
| const AP = ['am', 'pm']; | |||||
| p = get_token(part.str, AP); | |||||
| if(p) | |||||
| _ap = p; | |||||
| } | |||||
| break; | |||||
| case 'u': | |||||
| case '%w': | |||||
| case '%W': | |||||
| case 'dddd': | |||||
| case 'ddd': | |||||
| throw new Error('不支持星期几解析: ' + part.str); // not ignore and throw | |||||
| //break; | |||||
| case '%%': | |||||
| //TODO: ignore 最好不解析出来 | |||||
| break; | |||||
| default: | |||||
| throw new Error('不支持的格式解析: ' + part.str); | |||||
| break; | |||||
| } | |||||
| if(!p) | |||||
| return null; | |||||
| } | |||||
| } | |||||
| if(_h_12 !== undefined && _ap !== undefined) | |||||
| { | |||||
| _h = (_ap === 'pm' ? _h_12 + 12 : _h_12) % 24; | |||||
| } | |||||
| let res = new Date; | |||||
| //console.log('1111111111',_y, _m, _d, _h, _i, _s, _z); | |||||
| if(_y === undefined) _y = initNow ? res.getFullYear() : 0; | |||||
| if(_m === undefined) _m = initNow ? res.getMonth() + 1 : 1; | |||||
| if(_d === undefined) _d = initNow ? res.getDate() : 1; | |||||
| if(_h === undefined) _h = initNow ? res.getHours() : 0; | |||||
| if(_i === undefined) _i = initNow ? res.getMinutes() : 0; | |||||
| if(_s === undefined) _s = initNow ? res.getSeconds() : 0; | |||||
| if(_z === undefined) _z = initNow ? res.getMilliseconds() : 0; | |||||
| //console.log('2222222222',_y, _m, _d, _h, _i, _s, _z); | |||||
| res.setFullYear(_y, _m - 1, _d); | |||||
| res.setHours(_h, _i, _s, _z); | |||||
| return res; | |||||
| } | |||||
| @@ -3,70 +3,48 @@ | |||||
| <van-nav-bar title="经营信息维护" left-arrow placeholder safe-area-inset-top @click-left="onClickLeft"/> | <van-nav-bar title="经营信息维护" left-arrow placeholder safe-area-inset-top @click-left="onClickLeft"/> | ||||
| <van-form @submit="onSubmit"> | <van-form @submit="onSubmit"> | ||||
| <div class="main"> | |||||
| <p class="title"><i></i>经营信息</p> | |||||
| <van-field readonly v-model="form.deptName" label="区域位置名称" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-field readonly required :rules="[{ required: true }]" v-model="form.dkbm" label="地块编码" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-field readonly :rules="[{ required: true }]" v-model="form.dkmc" label="地块名称" placeholder="请输入" input-align="right" label-width="auto" required /> | |||||
| <van-field readonly v-model="form.dkdz" label="地块东至" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-field readonly v-model="form.dkxz" label="地块西至" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-field readonly v-model="form.dknz" label="地块南至" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-field readonly v-model="form.dkbz" label="地块北至" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <div class="main"> | |||||
| <p class="title"><i></i>经营信息</p> | |||||
| <van-field readonly v-model="form.deptName" label="区域位置名称" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-field readonly v-model="form.dkbm" label="地块编码" placeholder="请输入" input-align="right" label-width="auto" required :rules="[{ required: true }]"/> | |||||
| <van-field readonly v-model="form.dkmc" label="地块名称" placeholder="请输入" input-align="right" label-width="auto" required :rules="[{ required: true }]"/> | |||||
| <van-field readonly v-model="form.dkdz" label="地块东至" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-field readonly v-model="form.dkxz" label="地块西至" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-field readonly v-model="form.dknz" label="地块南至" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-field readonly v-model="form.dkbz" label="地块北至" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-field required :rules="[{ required: true }]" v-model="form.jymj" label="经营面积" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-field v-model="form.jymj" label="经营面积" placeholder="请输入" type="number" input-align="right" label-width="auto" required :rules="[{ required: true }]"/> | |||||
| <van-field required :rules="[{ required: true }]" readonly @click="showJyfsPicker = true" v-model="form.jyfsText" label="经营方式" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-popup v-model="showJyfsPicker" round position="bottom"> | |||||
| <van-picker show-toolbar :columns="dict.type.jyfs" value-key="label" @cancel="showJyfsPicker = false" @confirm="onConfirmJyfs"/> | |||||
| </van-popup> | |||||
| <field-select v-model="form.jyfs" label="经营方式" placeholder="请选择" value-key="dictLabel" data-key="dictValue" remote-url="/system/dict/data/type/jyfs" :on-remote-response="'data'" required/> | |||||
| <van-field readonly @click="showJydxlxPicker = true" v-model="form.jydxlxText" label="经营对象类型" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-popup v-model="showJydxlxPicker" round position="bottom"> | |||||
| <van-picker show-toolbar :columns="dict.type.jydxlx" value-key="label" @cancel="showJydxlxPicker = false" @confirm="onConfirmJydxlx"/> | |||||
| </van-popup> | |||||
| <field-select v-model="form.jydxlx" label="经营对象类型" placeholder="请选择" value-key="dictLabel" data-key="dictValue" remote-url="/system/dict/data/type/jydxlx" :on-remote-response="'data'" required/> | |||||
| <van-field required :rules="[{ required: true }]" v-model="form.jydxmc" label="经营对象名称" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-field v-model="form.jydxmc" label="经营对象名称" placeholder="请输入" input-align="right" label-width="auto" required :rules="[{ required: true }]"/> | |||||
| <van-field readonly @click="showJydxzjlxPicker = true" v-model="form.jydxzjlxText" label="经营对象证件类型" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-popup v-model="showJydxzjlxPicker" round position="bottom"> | |||||
| <van-picker show-toolbar :columns="dict.type.zjlx" value-key="label" @cancel="showJydxzjlxPicker = false" @confirm="onConfirmJydxzjlx"/> | |||||
| </van-popup> | |||||
| <field-select v-model="form.jydxlx" label="经营对象证件类型" placeholder="请选择" value-key="dictLabel" data-key="dictValue" remote-url="/system/dict/data/type/zjlx" :on-remote-response="'data'"/> | |||||
| <van-field v-model="form.jydxzjhm" label="经营对象证件号码" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-field v-model="form.jydxzjhm" label="经营对象证件号码" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-field readonly @click="showSfqdhtPicker = true" v-model="form.sfqdhtText" label="是否签订合同" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-popup v-model="showSfqdhtPicker" round position="bottom"> | |||||
| <van-picker show-toolbar :columns="dict.type.is_common" value-key="label" @cancel="showSfqdhtPicker = false" @confirm="onConfirmSfqdht"/> | |||||
| </van-popup> | |||||
| <field-radio v-model="form.sfqdht" label="是否签订合同" value-key="dictLabel" data-key="dictValue" remote-url="/system/dict/data/type/is_common" :on-remote-response="'data'" required/> | |||||
| <van-field required :rules="[{ required: true }]" readonly @click="showJykssjPicker = true" v-model="form.jykssj" label="经营开始时间" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-popup v-model="showJykssjPicker" round position="bottom"> | |||||
| <van-datetime-picker v-model="jykssj" type="date" title="选择年月日" :min-date="minDate" :max-date="maxDate" @cancel="showJykssjPicker = false" @confirm="onConfirmJykssj"/> | |||||
| </van-popup> | |||||
| <field-date-picker v-model="form.jykssj" label="经营开始时间" placeholder="请选择" formatter="yyyy-MM-dd" input-align="right" type="date" :required="true" size="large"/> | |||||
| <van-field required :rules="[{ required: true }]" readonly @click="showJyjssjPicker = true" v-model="form.jyjssj" label="经营结束时间" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-popup v-model="showJyjssjPicker" round position="bottom"> | |||||
| <van-datetime-picker v-model="jyjssj" type="date" title="选择年月日" :min-date="minDate" :max-date="maxDate" @cancel="showJyjssjPicker = false" @confirm="onConfirmJyjssj"/> | |||||
| </van-popup> | |||||
| <field-date-picker v-model="form.jyjssj" label="经营结束时间" placeholder="请选择" formatter="yyyy-MM-dd" input-align="right" type="date" :required="true" size="large"/> | |||||
| <van-field required :rules="[{ required: true }]" v-model="form.cbje" label="承包金额(元)" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-field v-model="form.dxje" label="兑现金额(元)" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-field v-model="form.sqje" label="尚欠金额(元)" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-field v-model="form.nsy" label="年收益(元)" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-field v-model="form.bzxx" label="备注信息" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-field v-model="form.cbje" label="承包金额(元)" placeholder="请输入" type="number" input-align="right" label-width="auto" required :rules="[{ required: true }]"/> | |||||
| <van-field v-model="form.dxje" label="兑现金额(元)" placeholder="请输入" type="number" input-align="right" label-width="auto" /> | |||||
| <van-field v-model="form.sqje" label="尚欠金额(元)" placeholder="请输入" type="number" input-align="right" label-width="auto" /> | |||||
| <van-field v-model="form.nsy" label="年收益(元)" placeholder="请输入" type="number" input-align="right" label-width="auto" /> | |||||
| <van-field v-model="form.bzxx" label="备注信息" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <!--<van-field readonly required :rules="[{ required: true }]" @click="showSurveyStatusPicker = true" v-model="form.surveyStatusText" label="调查状态" placeholder="请输入" input-align="right" label-width="auto" /> | |||||
| <van-popup v-model="showSurveyStatusPicker" round position="bottom"> | |||||
| <van-picker show-toolbar :columns="dict.type.survey_status" value-key="label" @cancel="showSurveyStatusPicker = false" @confirm="onConfirmSurveyStatus"/> | |||||
| </van-popup>--> | |||||
| <field-select v-model="form.surveyStatusText" label="调查状态" value-key="dictLabel" data-key="dictValue" placeholder="请选择" requiredx remote-url="/system/dict/data/type/survey_status" :on-remote-response="'data'"/> | |||||
| <field-radio v-model="form.surveyStatus" label="调查状态" value-key="dictLabel" data-key="dictValue" remote-url="/system/dict/data/type/survey_status" :on-remote-response="'data'" required/> | |||||
| <van-field readonly label="实物图" placeholder="" input-align="right" label-width="auto" /> | |||||
| <image-upload v-model="form.dkImg"/> | |||||
| <van-field label="实物图" placeholder="" input-align="right" label-width="auto" /> | |||||
| <CommonUpload v-model="form.dkImg" accept="image/*" multiple :deletable="true" :show-upload="true" fileField="file" /> | |||||
| </div> | |||||
| </div> | |||||
| <van-button round block type="primary" native-type="submit" class="subClass">提交</van-button> | |||||
| <van-button round block type="primary" native-type="submit" class="subClass">提交</van-button> | |||||
| </van-form> | </van-form> | ||||
| </div> | </div> | ||||
| @@ -76,23 +54,18 @@ | |||||
| import { getLandDetail } from "@/api/resource/land" | import { getLandDetail } from "@/api/resource/land" | ||||
| import { getOperationDetail, updateOperation, addOperation } from "@/api/resource/operation" | import { getOperationDetail, updateOperation, addOperation } from "@/api/resource/operation" | ||||
| import { getInfoByImportCode } from "@/api/system/dept"; | import { getInfoByImportCode } from "@/api/system/dept"; | ||||
| import FieldSelect from "@/components/form/FieldSelect.vue"; | import FieldSelect from "@/components/form/FieldSelect.vue"; | ||||
| import FieldRadio from "@/components/form/FieldRadio.vue"; | |||||
| import FieldDatePicker from "@/components/form/FieldDatePicker.vue"; | |||||
| import CommonUpload from "@/components/form/CommonUpload.vue"; | |||||
| export default { | export default { | ||||
| dicts: ['zjlx', 'survey_status', 'is_common', 'jydxlx', 'jyfs'], | dicts: ['zjlx', 'survey_status', 'is_common', 'jydxlx', 'jyfs'], | ||||
| name: "appEdit", | name: "appEdit", | ||||
| components: {FieldSelect}, | |||||
| components: {FieldSelect, FieldRadio, FieldDatePicker, CommonUpload}, | |||||
| data() { | data() { | ||||
| return { | return { | ||||
| showJyfsPicker: false, | |||||
| showSfqdhtPicker: false, | |||||
| showJydxlxPicker: false, | |||||
| showJydxzjlxPicker: false, | |||||
| showJykssjPicker: false, | |||||
| showJyjssjPicker: false, | |||||
| showSurveyStatusPicker: false, | |||||
| minDate: new Date(2020, 0, 1), | |||||
| maxDate: new Date(2025, 10, 1), | |||||
| importCode: null, | importCode: null, | ||||
| form: { | form: { | ||||
| dkbm: null, | dkbm: null, | ||||
| @@ -120,10 +93,6 @@ | |||||
| importCode: null, | importCode: null, | ||||
| deptName: null, | deptName: null, | ||||
| }, | }, | ||||
| jykssj:new Date(), | |||||
| jyjssj:new Date(), | |||||
| openPic: [], | |||||
| openPic2: [], | |||||
| }; | }; | ||||
| }, | }, | ||||
| created() { | created() { | ||||
| @@ -136,13 +105,6 @@ | |||||
| getDetail(){ | getDetail(){ | ||||
| getOperationDetail(this.$route.query.dkbm).then(response => { | getOperationDetail(this.$route.query.dkbm).then(response => { | ||||
| if (response.data){ | if (response.data){ | ||||
| response.data.jyfsText = this.selectDictLabel(this.dict.type.jyfs,response.data.jyfs); | |||||
| response.data.jydxlxText = this.selectDictLabel(this.dict.type.jydxlx,response.data.jydxlx); | |||||
| response.data.jydxzjlxText = this.selectDictLabel(this.dict.type.zjlx,response.data.jydxzjlx); | |||||
| response.data.sfqdhtText = this.selectDictLabel(this.dict.type.is_common,response.data.sfqdht); | |||||
| response.data.surveyStatusText = this.selectDictLabel(this.dict.type.survey_status,response.data.surveyStatus); | |||||
| this.jykssj = new Date(response.data.jykssj); | |||||
| this.jyjssj = new Date(response.data.jyjssj); | |||||
| this.form = response.data | this.form = response.data | ||||
| }else{ | }else{ | ||||
| getLandDetail(this.$route.query.dkbm).then(response => { | getLandDetail(this.$route.query.dkbm).then(response => { | ||||
| @@ -157,15 +119,11 @@ | |||||
| this.form.dknz = response.data.dknz; | this.form.dknz = response.data.dknz; | ||||
| this.form.dkbz = response.data.dkbz; | this.form.dkbz = response.data.dkbz; | ||||
| this.form.jymj = response.data.scmjm; | this.form.jymj = response.data.scmjm; | ||||
| this.form.jyfsText = '家庭承包'; | |||||
| this.form.jyfs = '110'; | this.form.jyfs = '110'; | ||||
| this.form.jydxlxText = '农户'; | |||||
| this.form.jydxlx = '1'; | this.form.jydxlx = '1'; | ||||
| this.form.jydxzjlxText = '居民身份证'; | |||||
| this.form.jydxzjlx = '1'; | this.form.jydxzjlx = '1'; | ||||
| this.form.sfqdhtText = '是'; | |||||
| this.form.sfqdht = '1'; | this.form.sfqdht = '1'; | ||||
| this.form.surveyStatusText = '已调查'; | |||||
| this.form.surveyStatus = '2'; | this.form.surveyStatus = '2'; | ||||
| getInfoByImportCode(response.data.importCode).then((res) => { | getInfoByImportCode(response.data.importCode).then((res) => { | ||||
| @@ -175,39 +133,6 @@ | |||||
| } | } | ||||
| }); | }); | ||||
| }, | }, | ||||
| onConfirmJydxlx(value) { | |||||
| this.form.jydxlxText = value.label; | |||||
| this.form.jydxlx = value.value; | |||||
| this.showJydxlxPicker = false; | |||||
| }, | |||||
| onConfirmJyfs(value) { | |||||
| this.form.jyfsText = value.label; | |||||
| this.form.jyfs = value.value; | |||||
| this.showJyfsPicker = false; | |||||
| }, | |||||
| onConfirmJydxzjlx(value) { | |||||
| this.form.jydxzjlxText = value.label; | |||||
| this.form.jydxzjlx = value.value; | |||||
| this.showJydxzjlxPicker = false; | |||||
| }, | |||||
| onConfirmSfqdht(value) { | |||||
| this.form.sfqdhtText = value.label; | |||||
| this.form.sfqdht = value.value; | |||||
| this.showSfqdhtPicker = false; | |||||
| }, | |||||
| onConfirmJykssj(data) { | |||||
| this.form.jykssj = this.format(data, 'yyyy-MM-dd'); | |||||
| this.showJykssjPicker = false; | |||||
| }, | |||||
| onConfirmJyjssj(data) { | |||||
| this.form.jyjssj = this.format(data, 'yyyy-MM-dd'); | |||||
| this.showJyjssjPicker = false; | |||||
| }, | |||||
| onConfirmSurveyStatus(value) { | |||||
| this.form.surveyStatusText = value.label; | |||||
| this.form.surveyStatus = value.value; | |||||
| this.showSurveyStatusPicker = false; | |||||
| }, | |||||
| /** 提交按钮 */ | /** 提交按钮 */ | ||||
| onSubmit() { | onSubmit() { | ||||
| if (!this.form.id){ | if (!this.form.id){ | ||||