页面UI更新
This commit is contained in:
539
components/c-upload/c-upload.vue
Normal file
539
components/c-upload/c-upload.vue
Normal file
@@ -0,0 +1,539 @@
|
||||
<template>
|
||||
<view class="u-upload" v-if="!disabled">
|
||||
<view
|
||||
v-if="showUploadList"
|
||||
class="u-list-item u-preview-wrap"
|
||||
v-for="(item, index) in lists"
|
||||
:key="index"
|
||||
:style="{
|
||||
width: $u.addUnit(width),
|
||||
height: $u.addUnit(height)
|
||||
}"
|
||||
>
|
||||
<view
|
||||
v-if="deletable"
|
||||
class="u-delete-icon"
|
||||
@tap.stop="deleteItem(index)"
|
||||
:style="{
|
||||
background: delBgColor
|
||||
}"
|
||||
>
|
||||
<u-icon class="u-icon" :name="delIcon" size="20" :color="delColor"></u-icon>
|
||||
</view>
|
||||
<u-line-progress
|
||||
v-if="showProgress && item.progress > 0 && item.progress != 100 && !item.error"
|
||||
:show-percent="false"
|
||||
height="16"
|
||||
class="u-progress"
|
||||
:percent="item.progress"
|
||||
></u-line-progress>
|
||||
<view @tap.stop="retry(index)" v-if="item.error" class="u-error-btn">点击重试</view>
|
||||
<image @tap.stop="doPreviewImage(item.url || item.path, index)" class="u-preview-image" v-if="!item.isImage" :src="item.url || item.path" :mode="imageMode"></image>
|
||||
</view>
|
||||
<slot name="file" :file="lists"></slot>
|
||||
<view style="display: inline-block;" @tap="selectFile" v-if="maxCount > lists.length">
|
||||
<slot name="addBtn"></slot>
|
||||
<view
|
||||
v-if="!customBtn"
|
||||
class="u-list-item u-add-wrap"
|
||||
hover-class="u-add-wrap__hover"
|
||||
hover-stay-time="150"
|
||||
:style="{
|
||||
width: $u.addUnit(width),
|
||||
height: $u.addUnit(height)
|
||||
}"
|
||||
>
|
||||
<u-icon name="plus" class="u-add-btn" size="40"></u-icon>
|
||||
<view class="u-add-tips">{{ uploadText }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { prepareImagePath } from '@/utils/image-compress.js';
|
||||
|
||||
export default {
|
||||
name: 'c-upload',
|
||||
props: {
|
||||
showUploadList: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
action: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
maxCount: {
|
||||
type: [String, Number],
|
||||
default: 52
|
||||
},
|
||||
showProgress: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
imageMode: {
|
||||
type: String,
|
||||
default: 'aspectFill'
|
||||
},
|
||||
header: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
formData: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
default: 'file'
|
||||
},
|
||||
sizeType: {
|
||||
type: Array,
|
||||
default() {
|
||||
return ['original', 'compressed'];
|
||||
}
|
||||
},
|
||||
sourceType: {
|
||||
type: Array,
|
||||
default() {
|
||||
return ['album', 'camera'];
|
||||
}
|
||||
},
|
||||
previewFullImage: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
deletable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
maxSize: {
|
||||
type: [String, Number],
|
||||
default: Number.MAX_VALUE
|
||||
},
|
||||
fileList: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
uploadText: {
|
||||
type: String,
|
||||
default: '选择图片'
|
||||
},
|
||||
autoUpload: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showTips: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
customBtn: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
width: {
|
||||
type: [String, Number],
|
||||
default: 200
|
||||
},
|
||||
height: {
|
||||
type: [String, Number],
|
||||
default: 200
|
||||
},
|
||||
delBgColor: {
|
||||
type: String,
|
||||
default: '#fa3534'
|
||||
},
|
||||
delColor: {
|
||||
type: String,
|
||||
default: '#ffffff'
|
||||
},
|
||||
delIcon: {
|
||||
type: String,
|
||||
default: 'close'
|
||||
},
|
||||
toJson: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
beforeUpload: {
|
||||
type: Function,
|
||||
default: null
|
||||
},
|
||||
beforeRemove: {
|
||||
type: Function,
|
||||
default: null
|
||||
},
|
||||
limitType: {
|
||||
type: Array,
|
||||
default() {
|
||||
return ['png', 'jpg', 'jpeg', 'webp', 'gif', 'image'];
|
||||
}
|
||||
},
|
||||
index: {
|
||||
type: [Number, String],
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
lists: [],
|
||||
isInCount: true,
|
||||
uploading: false
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
fileList: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
val.map(value => {
|
||||
let tmp = this.lists.some(val => {
|
||||
return val.url == value.url;
|
||||
})
|
||||
!tmp && this.lists.push({ url: value.url, error: false, progress: 100 });
|
||||
});
|
||||
}
|
||||
},
|
||||
lists(n) {
|
||||
this.$emit('on-list-change', n, this.index);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clear() {
|
||||
this.lists = [];
|
||||
},
|
||||
reUpload() {
|
||||
this.uploadFile();
|
||||
},
|
||||
selectFile() {
|
||||
if (this.disabled) return;
|
||||
const { maxCount, multiple, maxSize, sizeType, lists, sourceType } = this;
|
||||
const newMaxCount = maxCount - lists.length;
|
||||
uni.chooseImage({
|
||||
count: multiple ? (newMaxCount > 9 ? 9 : newMaxCount) : 1,
|
||||
sourceType: sourceType,
|
||||
sizeType,
|
||||
success: async (res) => {
|
||||
const listOldLength = this.lists.length;
|
||||
for (let index = 0; index < res.tempFiles.length; index++) {
|
||||
const val = res.tempFiles[index];
|
||||
if (!this.checkFileExt(val)) continue;
|
||||
if (!multiple && index >= 1) continue;
|
||||
if (val.size > maxSize) {
|
||||
this.$emit('on-oversize', val, this.lists, this.index);
|
||||
this.showToast('超出允许的文件大小');
|
||||
continue;
|
||||
}
|
||||
if (maxCount <= lists.length) {
|
||||
this.$emit('on-exceed', val, this.lists, this.index);
|
||||
this.showToast('超出最大允许的文件个数');
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
const prepared = await prepareImagePath({
|
||||
path: val.path,
|
||||
size: val.size,
|
||||
});
|
||||
if (!prepared) continue;
|
||||
|
||||
lists.push({
|
||||
url: prepared.path,
|
||||
progress: 0,
|
||||
error: false,
|
||||
file: {
|
||||
...val,
|
||||
path: prepared.path,
|
||||
size: prepared.size,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
this.$emit('on-choose-fail', error);
|
||||
this.showToast('图片处理失败');
|
||||
}
|
||||
}
|
||||
this.$emit('on-choose-complete', this.lists, this.index);
|
||||
if (this.autoUpload) this.uploadFile(listOldLength);
|
||||
},
|
||||
fail: (error) => {
|
||||
this.$emit('on-choose-fail', error);
|
||||
}
|
||||
});
|
||||
},
|
||||
showToast(message, force = false) {
|
||||
if (this.showTips || force) {
|
||||
uni.showToast({
|
||||
title: message,
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
},
|
||||
upload() {
|
||||
this.uploadFile();
|
||||
},
|
||||
retry(index) {
|
||||
this.lists[index].progress = 0;
|
||||
this.lists[index].error = false;
|
||||
this.lists[index].response = null;
|
||||
uni.showLoading({
|
||||
title: '重新上传'
|
||||
});
|
||||
this.uploadFile(index);
|
||||
},
|
||||
async uploadFile(index = 0) {
|
||||
if (this.disabled) return;
|
||||
if (this.uploading) return;
|
||||
if (index >= this.lists.length) {
|
||||
this.$emit('on-uploaded', this.lists, this.index);
|
||||
return;
|
||||
}
|
||||
if (this.lists[index].progress == 100) {
|
||||
if (this.autoUpload == false) this.uploadFile(index + 1);
|
||||
return;
|
||||
}
|
||||
if (this.beforeUpload && typeof(this.beforeUpload) === 'function') {
|
||||
let beforeResponse = this.beforeUpload.bind(this.$u.$parent.call(this))(index, this.lists);
|
||||
if (!!beforeResponse && typeof beforeResponse.then === 'function') {
|
||||
await beforeResponse.then(res => {
|
||||
}).catch(err => {
|
||||
return this.uploadFile(index + 1);
|
||||
})
|
||||
} else if (beforeResponse === false) {
|
||||
return this.uploadFile(index + 1);
|
||||
}
|
||||
}
|
||||
if (!this.action) {
|
||||
this.showToast('请配置上传地址', true);
|
||||
return;
|
||||
}
|
||||
this.lists[index].error = false;
|
||||
this.uploading = true;
|
||||
const task = uni.uploadFile({
|
||||
url: this.action,
|
||||
filePath: this.lists[index].url,
|
||||
name: this.name,
|
||||
formData: this.formData,
|
||||
header: this.header,
|
||||
// #ifdef MP-ALIPAY
|
||||
fileType:'image',
|
||||
// #endif
|
||||
success: res => {
|
||||
let data = this.toJson && this.$u.test.jsonString(res.data) ? JSON.parse(res.data) : res.data;
|
||||
if (![200, 201, 204].includes(res.statusCode)) {
|
||||
this.uploadError(index, data);
|
||||
} else {
|
||||
this.lists[index].response = data;
|
||||
this.lists[index].progress = 100;
|
||||
this.lists[index].error = false;
|
||||
this.$emit('on-success', data, index, this.lists, this.index);
|
||||
}
|
||||
},
|
||||
fail: e => {
|
||||
this.uploadError(index, e);
|
||||
},
|
||||
complete: res => {
|
||||
uni.hideLoading();
|
||||
this.uploading = false;
|
||||
this.uploadFile(index + 1);
|
||||
this.$emit('on-change', res, index, this.lists, this.index);
|
||||
}
|
||||
});
|
||||
task.onProgressUpdate(res => {
|
||||
if (res.progress > 0) {
|
||||
this.lists[index].progress = res.progress;
|
||||
this.$emit('on-progress', res, index, this.lists, this.index);
|
||||
}
|
||||
});
|
||||
},
|
||||
uploadError(index, err) {
|
||||
this.lists[index].progress = 0;
|
||||
this.lists[index].error = true;
|
||||
this.lists[index].response = null;
|
||||
this.$emit('on-error', err, index, this.lists, this.index);
|
||||
this.showToast('上传失败,请重试');
|
||||
},
|
||||
deleteItem(index) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '您确定要删除此项吗?',
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
if (this.beforeRemove && typeof(this.beforeRemove) === 'function') {
|
||||
let beforeResponse = this.beforeRemove.bind(this.$u.$parent.call(this))(index, this.lists);
|
||||
if (!!beforeResponse && typeof beforeResponse.then === 'function') {
|
||||
await beforeResponse.then(res => {
|
||||
this.handlerDeleteItem(index);
|
||||
}).catch(err => {
|
||||
this.showToast('已终止移除');
|
||||
})
|
||||
} else if (beforeResponse === false) {
|
||||
this.showToast('已终止移除');
|
||||
} else {
|
||||
this.handlerDeleteItem(index);
|
||||
}
|
||||
} else {
|
||||
this.handlerDeleteItem(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
handlerDeleteItem(index) {
|
||||
if (this.lists[index].progress < 100 && this.lists[index].progress > 0) {
|
||||
typeof this.lists[index].uploadTask != 'undefined' && this.lists[index].uploadTask.abort();
|
||||
}
|
||||
this.lists.splice(index, 1);
|
||||
this.$forceUpdate();
|
||||
this.$emit('on-remove', index, this.lists, this.index);
|
||||
this.showToast('移除成功');
|
||||
},
|
||||
remove(index) {
|
||||
if (index >= 0 && index < this.lists.length) {
|
||||
this.lists.splice(index, 1);
|
||||
this.$emit('on-list-change', this.lists, this.index);
|
||||
}
|
||||
},
|
||||
doPreviewImage(url, index) {
|
||||
if (!this.previewFullImage) return;
|
||||
const images = this.lists.map(item => item.url || item.path);
|
||||
uni.previewImage({
|
||||
urls: images,
|
||||
current: url,
|
||||
success: () => {
|
||||
this.$emit('on-preview', url, this.lists, this.index);
|
||||
},
|
||||
fail: () => {
|
||||
uni.showToast({
|
||||
title: '预览图片失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
checkFileExt(file) {
|
||||
let noArrowExt = false;
|
||||
let fileExt = '';
|
||||
const reg = /.+\./;
|
||||
// #ifdef H5
|
||||
fileExt = file.name.replace(reg, "").toLowerCase();
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
fileExt = file.path.replace(reg, "").toLowerCase();
|
||||
// #endif
|
||||
noArrowExt = this.limitType.some(ext => {
|
||||
return ext.toLowerCase() === fileExt;
|
||||
})
|
||||
if (!noArrowExt) this.showToast(`不允许选择${fileExt}格式的文件`);
|
||||
return noArrowExt;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import 'uview-ui/libs/css/style.components.scss';
|
||||
|
||||
.u-upload {
|
||||
@include vue-flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.u-list-item {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
overflow: hidden;
|
||||
margin: 10rpx;
|
||||
background: rgb(244, 245, 246);
|
||||
position: relative;
|
||||
border-radius: 10rpx;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.u-preview-wrap {
|
||||
border: 1px solid rgb(235, 236, 238);
|
||||
}
|
||||
|
||||
.u-add-wrap {
|
||||
flex-direction: column;
|
||||
color: $u-content-color;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.u-add-tips {
|
||||
margin-top: 20rpx;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
|
||||
.u-add-wrap__hover {
|
||||
background-color: rgb(235, 236, 238);
|
||||
}
|
||||
|
||||
.u-preview-image {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.u-delete-icon {
|
||||
position: absolute;
|
||||
top: 10rpx;
|
||||
right: 10rpx;
|
||||
z-index: 10;
|
||||
background-color: $u-type-error;
|
||||
border-radius: 100rpx;
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
@include vue-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.u-icon {
|
||||
@include vue-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.u-progress {
|
||||
position: absolute;
|
||||
bottom: 10rpx;
|
||||
left: 8rpx;
|
||||
right: 8rpx;
|
||||
z-index: 9;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.u-error-btn {
|
||||
color: #ffffff;
|
||||
background-color: $u-type-error;
|
||||
font-size: 20rpx;
|
||||
padding: 4px 0;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 9;
|
||||
line-height: 1;
|
||||
}
|
||||
</style>
|
||||
676
components/image-compress-popup/image-compress-popup.vue
Normal file
676
components/image-compress-popup/image-compress-popup.vue
Normal file
@@ -0,0 +1,676 @@
|
||||
<template>
|
||||
|
||||
<u-popup v-model="visible" mode="center" width="85%" border-radius="16" :mask-close-able="false">
|
||||
|
||||
<view class="popup-wrap">
|
||||
|
||||
<view class="popup-title">图片较大</view>
|
||||
|
||||
<view v-if="sizeText" class="size-text">{{ sizeText }}</view>
|
||||
|
||||
|
||||
|
||||
<view v-if="status === 'compressing'" class="compressing-panel">
|
||||
|
||||
<image
|
||||
|
||||
v-if="originalPath"
|
||||
|
||||
:src="originalPath"
|
||||
|
||||
mode="aspectFit"
|
||||
|
||||
class="preview-image single"
|
||||
|
||||
@click="previewImage(originalPath)"
|
||||
|
||||
/>
|
||||
|
||||
<text v-if="originalPath" class="preview-hint">点击预览</text>
|
||||
|
||||
<view class="compressing-status">
|
||||
|
||||
<u-loading mode="circle" />
|
||||
|
||||
<text class="progress-text">{{ progressText }}</text>
|
||||
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
<view v-else-if="status === 'ready'" class="compare-panel">
|
||||
|
||||
<view class="preview-column">
|
||||
|
||||
<text class="preview-label">原图</text>
|
||||
|
||||
<image
|
||||
|
||||
:src="originalPath"
|
||||
|
||||
mode="aspectFit"
|
||||
|
||||
class="preview-image"
|
||||
|
||||
@click="previewImage(originalPath)"
|
||||
|
||||
/>
|
||||
|
||||
<text class="preview-size">{{ formatFileSize(originalSize) }}</text>
|
||||
|
||||
<text class="preview-hint">点击预览</text>
|
||||
|
||||
</view>
|
||||
|
||||
<view class="preview-column">
|
||||
|
||||
<text class="preview-label">压缩后</text>
|
||||
|
||||
<image
|
||||
|
||||
:src="compressedPath"
|
||||
|
||||
mode="aspectFit"
|
||||
|
||||
class="preview-image"
|
||||
|
||||
@click="previewImage(compressedPath)"
|
||||
|
||||
/>
|
||||
|
||||
<text class="preview-size">{{ formatFileSize(compressedSize) }}</text>
|
||||
|
||||
<text class="preview-hint">点击预览</text>
|
||||
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
<view v-else-if="status === 'gifSkipped'" class="gif-panel">
|
||||
|
||||
<image
|
||||
|
||||
v-if="originalPath"
|
||||
|
||||
:src="originalPath"
|
||||
|
||||
mode="aspectFit"
|
||||
|
||||
class="preview-image single"
|
||||
|
||||
@click="previewImage(originalPath)"
|
||||
|
||||
/>
|
||||
|
||||
<text v-if="originalPath" class="preview-hint">点击预览</text>
|
||||
|
||||
<text class="hint-text">GIF 不支持压缩,将上传原图。</text>
|
||||
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
<view v-else class="error-panel">
|
||||
|
||||
<image
|
||||
|
||||
v-if="originalPath"
|
||||
|
||||
:src="originalPath"
|
||||
|
||||
mode="aspectFit"
|
||||
|
||||
class="preview-image single"
|
||||
|
||||
@click="previewImage(originalPath)"
|
||||
|
||||
/>
|
||||
|
||||
<text v-if="originalPath" class="preview-hint">点击预览</text>
|
||||
|
||||
<text class="error-text">{{ errorMessage }}</text>
|
||||
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
<view class="footer-actions">
|
||||
|
||||
<view class="btn btn-default" @click="finish('cancel')">取消</view>
|
||||
|
||||
<view
|
||||
|
||||
v-if="status === 'ready' || status === 'error'"
|
||||
|
||||
class="btn btn-default"
|
||||
|
||||
@click="finish('original')"
|
||||
|
||||
>
|
||||
|
||||
{{ originalButtonLabel }}
|
||||
|
||||
</view>
|
||||
|
||||
<view
|
||||
|
||||
v-if="status === 'ready'"
|
||||
|
||||
class="btn btn-primary"
|
||||
|
||||
@click="finish('compressed')"
|
||||
|
||||
>
|
||||
|
||||
{{ compressedButtonLabel }}
|
||||
|
||||
</view>
|
||||
|
||||
<view
|
||||
|
||||
v-if="status === 'gifSkipped'"
|
||||
|
||||
class="btn btn-primary"
|
||||
|
||||
@click="finish('original')"
|
||||
|
||||
>
|
||||
|
||||
{{ originalButtonLabel }}
|
||||
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
</u-popup>
|
||||
|
||||
</template>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
import {
|
||||
|
||||
formatFileSize,
|
||||
|
||||
formatSavingsPercent,
|
||||
|
||||
isGifPath,
|
||||
|
||||
tryCompressImage,
|
||||
|
||||
} from '@/utils/image-compress.js';
|
||||
|
||||
|
||||
|
||||
export default {
|
||||
|
||||
name: 'ImageCompressPopup',
|
||||
|
||||
data() {
|
||||
|
||||
return {
|
||||
|
||||
visible: false,
|
||||
|
||||
status: 'compressing',
|
||||
|
||||
progressText: '正在压缩,请稍候…',
|
||||
|
||||
errorMessage: '',
|
||||
|
||||
originalPath: '',
|
||||
|
||||
compressedPath: '',
|
||||
|
||||
originalSize: 0,
|
||||
|
||||
compressedSize: 0,
|
||||
|
||||
skipped: false,
|
||||
|
||||
resolver: null,
|
||||
|
||||
};
|
||||
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
||||
sizeText() {
|
||||
|
||||
if (!this.originalSize) return '';
|
||||
|
||||
const originalText = formatFileSize(this.originalSize);
|
||||
|
||||
if (this.status === 'gifSkipped') {
|
||||
|
||||
return `原图 ${originalText}`;
|
||||
|
||||
}
|
||||
|
||||
if (this.compressedSize && this.status === 'ready') {
|
||||
|
||||
const savings = formatSavingsPercent(this.originalSize, this.compressedSize);
|
||||
|
||||
return `原图 ${originalText} → 压缩后 ${formatFileSize(this.compressedSize)}${savings}`;
|
||||
|
||||
}
|
||||
|
||||
if (this.compressedSize) {
|
||||
|
||||
return `原图 ${originalText} → 压缩后 ${formatFileSize(this.compressedSize)}`;
|
||||
|
||||
}
|
||||
|
||||
return `原图 ${originalText}`;
|
||||
|
||||
},
|
||||
|
||||
originalButtonLabel() {
|
||||
|
||||
if (!this.originalSize) return '使用原图';
|
||||
|
||||
return `使用原图 (${formatFileSize(this.originalSize)})`;
|
||||
|
||||
},
|
||||
|
||||
compressedButtonLabel() {
|
||||
|
||||
if (!this.compressedSize) return '使用压缩图';
|
||||
|
||||
return `使用压缩图 (${formatFileSize(this.compressedSize)})`;
|
||||
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
formatFileSize,
|
||||
|
||||
previewImage(current) {
|
||||
|
||||
if (!this.originalPath) return;
|
||||
|
||||
const urls =
|
||||
|
||||
this.status === 'ready' && this.compressedPath
|
||||
|
||||
? [this.originalPath, this.compressedPath]
|
||||
|
||||
: [this.originalPath];
|
||||
|
||||
uni.previewImage({
|
||||
|
||||
urls,
|
||||
|
||||
current,
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
open({ path, size }) {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
|
||||
this.resolver = resolve;
|
||||
|
||||
this.originalPath = path;
|
||||
|
||||
this.originalSize = size;
|
||||
|
||||
this.compressedPath = '';
|
||||
|
||||
this.compressedSize = 0;
|
||||
|
||||
this.skipped = false;
|
||||
|
||||
this.errorMessage = '';
|
||||
|
||||
this.progressText = '正在压缩,请稍候…';
|
||||
|
||||
this.visible = true;
|
||||
|
||||
this.startCompress(path, size);
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
async startCompress(path, size) {
|
||||
|
||||
if (isGifPath(path)) {
|
||||
|
||||
this.skipped = true;
|
||||
|
||||
this.status = 'gifSkipped';
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
this.status = 'compressing';
|
||||
|
||||
this.progressText = '正在压缩(质量 80%)…';
|
||||
|
||||
|
||||
|
||||
try {
|
||||
|
||||
const compressed = await tryCompressImage(path, [80, 60, 40], (quality) => {
|
||||
|
||||
this.progressText = `正在压缩(质量 ${quality}%)…`;
|
||||
|
||||
});
|
||||
|
||||
this.compressedPath = compressed.path;
|
||||
|
||||
this.compressedSize = compressed.size;
|
||||
|
||||
this.status = 'ready';
|
||||
|
||||
this.progressText = '';
|
||||
|
||||
} catch (error) {
|
||||
|
||||
this.status = 'error';
|
||||
|
||||
this.errorMessage = '图片压缩失败,请使用原图或取消';
|
||||
|
||||
this.progressText = '';
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
finish(choice) {
|
||||
|
||||
const result = { choice, path: null, size: 0, usedCompress: false };
|
||||
|
||||
|
||||
|
||||
if (choice === 'cancel') {
|
||||
|
||||
this.visible = false;
|
||||
|
||||
this.resolver && this.resolver(null);
|
||||
|
||||
this.resolver = null;
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (choice === 'compressed' && this.status === 'ready') {
|
||||
|
||||
result.path = this.compressedPath;
|
||||
|
||||
result.size = this.compressedSize;
|
||||
|
||||
result.usedCompress = true;
|
||||
|
||||
} else {
|
||||
|
||||
result.path = this.originalPath;
|
||||
|
||||
result.size = this.originalSize;
|
||||
|
||||
result.usedCompress = false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
this.visible = false;
|
||||
|
||||
this.resolver && this.resolver(result);
|
||||
|
||||
this.resolver = null;
|
||||
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.popup-wrap {
|
||||
|
||||
padding: 32rpx;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.popup-title {
|
||||
|
||||
font-size: 32rpx;
|
||||
|
||||
font-weight: 600;
|
||||
|
||||
text-align: center;
|
||||
|
||||
margin-bottom: 16rpx;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.size-text {
|
||||
|
||||
font-size: 26rpx;
|
||||
|
||||
color: #666;
|
||||
|
||||
text-align: center;
|
||||
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.preview-image {
|
||||
|
||||
width: 100%;
|
||||
|
||||
height: 280rpx;
|
||||
|
||||
background: #fafafa;
|
||||
|
||||
border-radius: 12rpx;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.preview-image.single {
|
||||
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.compare-panel {
|
||||
|
||||
display: flex;
|
||||
|
||||
gap: 16rpx;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.preview-column {
|
||||
|
||||
flex: 1;
|
||||
|
||||
display: flex;
|
||||
|
||||
flex-direction: column;
|
||||
|
||||
align-items: center;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.preview-label {
|
||||
|
||||
font-size: 26rpx;
|
||||
|
||||
font-weight: 500;
|
||||
|
||||
margin-bottom: 12rpx;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.preview-size {
|
||||
|
||||
margin-top: 8rpx;
|
||||
|
||||
font-size: 22rpx;
|
||||
|
||||
color: #999;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.preview-hint {
|
||||
|
||||
margin-top: 4rpx;
|
||||
|
||||
font-size: 22rpx;
|
||||
|
||||
color: #bbb;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.compressing-panel,
|
||||
|
||||
.gif-panel,
|
||||
|
||||
.error-panel {
|
||||
|
||||
display: flex;
|
||||
|
||||
flex-direction: column;
|
||||
|
||||
align-items: center;
|
||||
|
||||
gap: 24rpx;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.compressing-status {
|
||||
|
||||
display: flex;
|
||||
|
||||
align-items: center;
|
||||
|
||||
gap: 16rpx;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.progress-text,
|
||||
|
||||
.hint-text {
|
||||
|
||||
font-size: 26rpx;
|
||||
|
||||
color: #666;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.error-text {
|
||||
|
||||
font-size: 26rpx;
|
||||
|
||||
color: #fa3534;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.footer-actions {
|
||||
|
||||
display: flex;
|
||||
|
||||
justify-content: flex-end;
|
||||
|
||||
flex-wrap: wrap;
|
||||
|
||||
gap: 16rpx;
|
||||
|
||||
margin-top: 32rpx;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.btn {
|
||||
|
||||
min-width: 160rpx;
|
||||
|
||||
padding: 16rpx 24rpx;
|
||||
|
||||
border-radius: 8rpx;
|
||||
|
||||
font-size: 26rpx;
|
||||
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.btn-default {
|
||||
|
||||
background: #f5f5f5;
|
||||
|
||||
color: #333;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.btn-primary {
|
||||
|
||||
background: #2979ff;
|
||||
|
||||
color: #fff;
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// 下载安装方式
|
||||
// "^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue"
|
||||
// npm安装方式
|
||||
// "^u-upload$": "@/components/c-upload/c-upload.vue",
|
||||
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue",
|
||||
// 消息通知组件
|
||||
"^MessageNotification": "@/components/MessageNotification/MessageNotification.vue",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<view class="content safe-area-inset-bottom">
|
||||
<!-- 全局消息通知组件 -->
|
||||
<MessageNotification />
|
||||
<image-compress-popup ref="imageCompressPopup" />
|
||||
|
||||
<!-- 1. 自定义吸顶导航栏 -->
|
||||
<view class="custom-nav"
|
||||
@@ -118,7 +119,7 @@
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view class="consult-btn">咨询</view>-->
|
||||
<view class="consult-btn">查看</view>
|
||||
<!-- <view class="consult-btn">查看</view>-->
|
||||
</view>
|
||||
<view class="doc-stats-bar">
|
||||
<view class="stat-item">
|
||||
@@ -214,12 +215,15 @@ import { getPlatformQualificationsApi } from '../../request/api/platform'
|
||||
import { getStoreDrugListBySalespersonApi, getHomeTopProductsApi, getHomeZonesApi, checkOnlineConsultationConfigApi } from "@/request/api/product";
|
||||
import request from "@/request/api/request";
|
||||
import MessageNotification from "@/components/MessageNotification/MessageNotification.vue";
|
||||
import ImageCompressPopup from '@/components/image-compress-popup/image-compress-popup.vue';
|
||||
import { registerImageCompressPopup } from '@/utils/image-compress-modal.js';
|
||||
import { setGuestMode, isGuestMode, isLoggedIn } from '@/common/utils/auth.js';
|
||||
import {silentLogin} from "@/utils/login";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MessageNotification
|
||||
MessageNotification,
|
||||
ImageCompressPopup,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -275,6 +279,9 @@ export default {
|
||||
}
|
||||
},
|
||||
onReady() {
|
||||
if (this.$refs.imageCompressPopup) {
|
||||
registerImageCompressPopup(this.$refs.imageCompressPopup);
|
||||
}
|
||||
|
||||
// console.log('调试静默登陆', isLoggedIn());
|
||||
// 判断是否已登录
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import http from './request'
|
||||
import { get } from './http'
|
||||
|
||||
// 登录 授权 其他手机号授权
|
||||
export async function getsLogin(params) {
|
||||
@@ -106,7 +107,19 @@ export async function userInfo(params) {
|
||||
|
||||
// 就诊人保存
|
||||
export async function userAdd(params) {
|
||||
let data = await http('/oldApi/v1/patient/save', params)
|
||||
let data = await http('/xkApi/patient/save', params)
|
||||
return data
|
||||
}
|
||||
|
||||
// 就诊人监护人信息(编辑回显)
|
||||
export async function userGuardianInfo(params) {
|
||||
const query = params.data || params
|
||||
return await get('/patient/guardian-info', query, 3)
|
||||
}
|
||||
|
||||
// 删除就诊人
|
||||
export async function userPatientDel(params) {
|
||||
let data = await http('/xkApi/patient/delete', params)
|
||||
return data
|
||||
}
|
||||
|
||||
|
||||
@@ -14,12 +14,66 @@ const arr = [
|
||||
'password'
|
||||
]
|
||||
|
||||
// 敏感数据
|
||||
// 敏感数据:响应解密后保留明文原字段,脱敏值写入 {field}_tm
|
||||
const sensitiveData = [
|
||||
'id_card',
|
||||
'idcard'
|
||||
'idcard',
|
||||
'guardian_id_card'
|
||||
]
|
||||
|
||||
// 仅展示脱敏、编辑需明文的字段
|
||||
const displayMaskFields = [
|
||||
'mobile',
|
||||
'express_mobile',
|
||||
'patient_mobile',
|
||||
]
|
||||
|
||||
/**
|
||||
* 脱敏展示值(写入 field_tm)
|
||||
*/
|
||||
function maskFieldValue(key, plainText) {
|
||||
if (plainText == null || plainText === '') {
|
||||
return plainText
|
||||
}
|
||||
const str = String(plainText)
|
||||
switch (key) {
|
||||
case 'express_name':
|
||||
case 'express_region':
|
||||
case 'accept_name':
|
||||
case 'patient':
|
||||
return str.slice(0, 1).padEnd(str.length, '*')
|
||||
case 'mobile':
|
||||
case 'express_mobile':
|
||||
case 'patient_mobile':
|
||||
case 'guardian_mobile':
|
||||
if (str.length <= 7) {
|
||||
return str
|
||||
}
|
||||
return str.slice(0, 3).padEnd(str.length - 4, '*') + str.slice(-4)
|
||||
case 'id_card':
|
||||
case 'idcard':
|
||||
case 'guardian_id_card':
|
||||
if (str.length <= 10) {
|
||||
return str
|
||||
}
|
||||
return str.slice(0, 6).padEnd(str.length - 4, '*') + str.slice(-4)
|
||||
default:
|
||||
return str
|
||||
}
|
||||
}
|
||||
|
||||
/** 只读展示:优先 field_tm */
|
||||
export function displayTm(obj, field) {
|
||||
if (obj == null) {
|
||||
return ''
|
||||
}
|
||||
const tm = obj[field + '_tm']
|
||||
if (tm != null && tm !== '') {
|
||||
return tm
|
||||
}
|
||||
return obj[field] ?? ''
|
||||
}
|
||||
|
||||
const isDev = checkDev('dev');
|
||||
|
||||
// 环境URL配置
|
||||
@@ -254,56 +308,39 @@ function request(url, params, method = 0) {
|
||||
|
||||
function getRes(obj, isDecode = true) {
|
||||
try {
|
||||
if (obj == null || typeof obj !== 'object') {
|
||||
return obj
|
||||
}
|
||||
for (const key in obj) {
|
||||
if (key.endsWith('_tm')) {
|
||||
continue
|
||||
}
|
||||
if (Array.isArray(obj[key])) {
|
||||
obj[key] = getRes(obj[key])
|
||||
} else if (typeof obj[key] === 'object') {
|
||||
obj[key] = getRes(obj[key])
|
||||
} else {
|
||||
// 判断obj[key]是否在arr中
|
||||
if (arr.indexOf(key) !== -1) {
|
||||
let aseFile = ''
|
||||
if (isDecode === true) {
|
||||
aseFile = customBase64Decode(obj[key])
|
||||
} else {
|
||||
aseFile = customBase64Encode(obj[key])
|
||||
obj[key] = getRes(obj[key], isDecode)
|
||||
} else if (obj[key] !== null && typeof obj[key] === 'object') {
|
||||
obj[key] = getRes(obj[key], isDecode)
|
||||
} else if (arr.indexOf(key) !== -1) {
|
||||
let plainValue = ''
|
||||
if (isDecode === true) {
|
||||
plainValue = customBase64Decode(obj[key])
|
||||
} else {
|
||||
plainValue = customBase64Encode(obj[key])
|
||||
}
|
||||
const isGarbled = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\xFF]|[\u{E000}-\u{F8FF}]/u.test(
|
||||
typeof plainValue === 'string' ? plainValue : ''
|
||||
)
|
||||
if (isGarbled) {
|
||||
plainValue = obj[key]
|
||||
}
|
||||
if (isDecode === true) {
|
||||
const needTm = sensitiveData.indexOf(key) !== -1
|
||||
|| displayMaskFields.indexOf(key) !== -1
|
||||
obj[key] = plainValue
|
||||
if (needTm) {
|
||||
obj[key + '_tm'] = maskFieldValue(key, plainValue)
|
||||
}
|
||||
const isGarbled = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\xFF]|[\u{E000}-\u{F8FF}]/u.test(
|
||||
typeof aseFile === 'string' ? aseFile : ''
|
||||
)
|
||||
if (isGarbled) {
|
||||
aseFile = obj[key]
|
||||
}
|
||||
// 为了修改,暂时不脱敏
|
||||
if (isDecode === true) {
|
||||
|
||||
if (sensitiveData.indexOf(key) !== -1) {
|
||||
// 数据脱敏,自动匹配姓名、手机号、身份证
|
||||
switch (key) {
|
||||
case 'express_name':
|
||||
case 'express_region':
|
||||
case 'accept_name':
|
||||
case 'patient':
|
||||
// 保留前两个字符,其余用星号代替
|
||||
aseFile = aseFile.slice(0, 1).padEnd(aseFile.length, '*');
|
||||
break;
|
||||
case 'mobile':
|
||||
case 'express_mobile':
|
||||
// 保留前三位和后四位,中间用星号代替
|
||||
aseFile = aseFile.slice(0, 3).padEnd(aseFile.length - 4, '*') + aseFile.slice(-4);
|
||||
break;
|
||||
case 'id_card':
|
||||
case 'idcard':
|
||||
// 保留前六位和后四位,中间用星号代替
|
||||
aseFile = aseFile.slice(0, 6).padEnd(aseFile.length - 4, '*') + aseFile.slice(-4);
|
||||
break;
|
||||
default:
|
||||
// 默认情况下,全部用星号代替
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
obj[key] = aseFile
|
||||
} else {
|
||||
obj[key] = plainValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,6 +199,7 @@ import { ChatManager } from '@/store/chat/chat.js';
|
||||
import {getChatRegisterInfoApi, sendToUserApi, upLoadChatFileApi, getDoctorInfoApi, getRoomStatusApi} from "@/request/api/im";
|
||||
import {getTransferAssistantConfigApi, getTransferConsultationAgreementInfoApi, getAgreementDetailApi} from "@/request/api/transferPrescription";
|
||||
import { checkDev } from '@/utils/utils';
|
||||
import { prepareImagePath } from '@/utils/image-compress.js';
|
||||
|
||||
// 根据环境获取上传URL
|
||||
const isDev = checkDev('dev');
|
||||
@@ -941,6 +942,23 @@ export default {
|
||||
success: res => { res.tempFilePaths.forEach(file => { this.uploadAndSendFile(file, 'image'); }); }
|
||||
});
|
||||
}
|
||||
// if (type === 'image') {
|
||||
// uni.chooseImage({
|
||||
// count: 9,
|
||||
// sourceType: ['album', 'camera'],
|
||||
// success: async (res) => {
|
||||
// for (let index = 0; index < res.tempFiles.length; index++) {
|
||||
// const tempFile = res.tempFiles[index];
|
||||
// const prepared = await prepareImagePath({
|
||||
// path: tempFile.path,
|
||||
// size: tempFile.size,
|
||||
// });
|
||||
// if (!prepared) continue;
|
||||
// this.uploadAndSendFile(prepared.path, 'image');
|
||||
// }
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
},
|
||||
|
||||
uploadAndSendFile(filePath, type) {
|
||||
|
||||
@@ -521,12 +521,18 @@ export default {
|
||||
// const storeId = ((this.registerType === '3' || this.registerType == '2') && this.delegateStoreId)
|
||||
// ? this.delegateStoreId
|
||||
// : (uni.getStorageSync('store_id') || '11001');
|
||||
const originStoreId = uni.getStorageSync('store_id') || '';
|
||||
const shouldSendOriginStoreId =
|
||||
this.registerType === '2' ||
|
||||
this.registerType === '3' ||
|
||||
(this.registerType !== '0' && !!this.delegateStoreId);
|
||||
registe({
|
||||
method: "post",
|
||||
data: {
|
||||
user_id: uni.getStorageSync('user_id'),
|
||||
user_patient_id: this.actived,
|
||||
store_id: storeId,
|
||||
origin_store_id: shouldSendOriginStoreId ? originStoreId : 0,
|
||||
service_user_id: this.Did,
|
||||
register_type: this.registerType // 新增:挂号类型参数
|
||||
}
|
||||
|
||||
@@ -75,9 +75,15 @@
|
||||
<image :src="item.drug_image || 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/empty/gwc.png'" mode=""></image>
|
||||
</view>
|
||||
<view class="it">
|
||||
<view class="it_name">{{item.drug_name}}{{item.drug.function}}</view>
|
||||
<view class="it_info" v-if="orderInfo.ProductOrder.prescription_type==2">
|
||||
{{item.drug.usage}}
|
||||
<view class="it_name">
|
||||
<text>{{ item.drug_name }}</text>
|
||||
<text
|
||||
v-if="item.drug && item.drug.specification"
|
||||
class="drug-spec">{{ item.drug.specification }}</text>
|
||||
<text v-if="item.drug && item.drug.function">{{ item.drug.function }}</text>
|
||||
</view>
|
||||
<view class="it_info" v-if="orderInfo.ProductOrder.prescription_type==2 && item.drug">
|
||||
{{ item.drug.usage }}
|
||||
</view>
|
||||
<!-- 添加查看说明书按钮 -->
|
||||
<view class="instruction-btn" v-if="prescriptionStatus && item.drug && item.drug.instruction" @click="previewInstruction(item.drug.instruction)">
|
||||
@@ -624,8 +630,8 @@ export default {
|
||||
}).then((res) => {
|
||||
if (res.data && (res.data.code == 0 || res.data.errcode == 0)) {
|
||||
const data = res.data.data || res.data.result || {};
|
||||
// 假设 status = 2 表示审核通过
|
||||
this.prescriptionStatus = data.status === true || data.status === 2 || data.status == 2;
|
||||
const ps = data.prescription_status ?? data.status;
|
||||
this.prescriptionStatus = data.status === true || ps === 1 || ps === '1' || ps === 3 || ps === '3' || ps === 4 || ps === '4';
|
||||
} else {
|
||||
this.prescriptionStatus = false;
|
||||
}
|
||||
@@ -658,8 +664,6 @@ export default {
|
||||
onShow() {
|
||||
this.getInfo()
|
||||
this.getList()
|
||||
// 查询处方状态
|
||||
this.getPrescriptionStatus()
|
||||
},
|
||||
onUnload() {
|
||||
uni.removeStorageSync('userWay_order_id')
|
||||
@@ -902,6 +906,13 @@ export default {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.drug-spec {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-left: 10rpx;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.it_info {
|
||||
|
||||
@@ -64,6 +64,53 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 监护人信息(6岁及以下) -->
|
||||
<view class="card" v-if="showGuardianSection">
|
||||
<view class="card_title">监护人信息</view>
|
||||
<view class="cards_names" style="padding: 20rpx 0;">
|
||||
<text>填写方式</text>
|
||||
<u-radio-group v-model="guardianType" @change="onGuardianTypeChange">
|
||||
<u-radio name="1" style="margin-right: 40rpx;">选择已有就诊人</u-radio>
|
||||
<u-radio name="2">填写监护人信息</u-radio>
|
||||
</u-radio-group>
|
||||
</view>
|
||||
<view class="card_relation" v-if="guardianType == '1'">
|
||||
<text>监护人</text>
|
||||
<u-input v-model="guardianPatientName" type="select" input-align="right" placeholder="请选择"
|
||||
placeholder-style="text-align:right;color: #94A3B8;" @click="showGuardianPatient = true" />
|
||||
<u-icon name="arrow-right" color="#A7ABB0" size="26" @click="showGuardianPatient = true"></u-icon>
|
||||
<u-action-sheet :list="guardianPickerList" :safe-area-inset-bottom="true" v-model="showGuardianPatient"
|
||||
@click="guardianPatientCallback">
|
||||
</u-action-sheet>
|
||||
</view>
|
||||
<template v-if="guardianType == '2'">
|
||||
<view class="card_name">
|
||||
<text>姓名</text>
|
||||
<u-input v-model="guardianForm.name" input-align="right" placeholder="请输入监护人姓名"
|
||||
placeholder-style="text-align:right;color: #94A3B8;" :type="type" />
|
||||
</view>
|
||||
<view class="card_name">
|
||||
<text>身份证号</text>
|
||||
<u-input v-model="guardianForm.idCard" maxlength="18" input-align="right" placeholder="请输入身份证号"
|
||||
placeholder-style="text-align:right;color: #94A3B8;" :type="type" />
|
||||
</view>
|
||||
<view class="card_telephone">
|
||||
<text>手机号</text>
|
||||
<u-input v-model="guardianForm.mobile" input-align="right" placeholder="请输入手机号"
|
||||
placeholder-style="text-align:right; color: #94A3B8;" :type="type" />
|
||||
</view>
|
||||
<view class="card_relation">
|
||||
<text>与患儿关系</text>
|
||||
<u-input v-model="guardianRelations" type="select" input-align="right" placeholder="请选择"
|
||||
placeholder-style="text-align:right;color: #94A3B8;" @click="showGuardianRelat = true" />
|
||||
<u-icon name="arrow-right" color="#A7ABB0" size="26" @click="showGuardianRelat = true"></u-icon>
|
||||
<u-action-sheet :list="actionSheetList" :safe-area-inset-bottom="true" v-model="showGuardianRelat"
|
||||
@click="guardianRelationCallback">
|
||||
</u-action-sheet>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
|
||||
<!-- 健康信息 -->
|
||||
<view class="cards">
|
||||
<view class="cards_title">
|
||||
@@ -218,6 +265,7 @@
|
||||
<script>
|
||||
import {
|
||||
userAdd,
|
||||
userList,
|
||||
userRelation
|
||||
} from '../../request/api/api';
|
||||
export default {
|
||||
@@ -369,8 +417,36 @@
|
||||
person_history: [],
|
||||
family_history: [],
|
||||
is_default: 0,
|
||||
guardianType: '1',
|
||||
guardianPatientName: '',
|
||||
guardianUserPatientId: 0,
|
||||
guardianRelations: '',
|
||||
guardianRelation: '',
|
||||
showGuardianPatient: false,
|
||||
showGuardianRelat: false,
|
||||
patientList: [],
|
||||
guardianForm: {
|
||||
name: '',
|
||||
idCard: '',
|
||||
mobile: '',
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
showGuardianSection() {
|
||||
const age = Number(this.form.age);
|
||||
return this.form.age !== '' && !isNaN(age) && age <= 6;
|
||||
},
|
||||
guardianPickerList() {
|
||||
const currentId = Number(this.addid) || 0;
|
||||
return this.patientList
|
||||
.filter((item) => Number(item.id) !== currentId)
|
||||
.map((item) => ({
|
||||
text: `${item.name}(${item.age}岁)`,
|
||||
key: item.id,
|
||||
}));
|
||||
},
|
||||
},
|
||||
onLoad(e) {
|
||||
// console.log(e);
|
||||
this.addid = e.id
|
||||
@@ -439,34 +515,198 @@
|
||||
})
|
||||
},
|
||||
|
||||
loadPatientList() {
|
||||
userList({
|
||||
method: 'post',
|
||||
data: {
|
||||
store_id: uni.getStorageSync('store_id') || '11001',
|
||||
},
|
||||
}).then((res) => {
|
||||
if (res.data.errcode == 0) {
|
||||
this.patientList = res.data.data || [];
|
||||
}
|
||||
});
|
||||
},
|
||||
resetGuardian() {
|
||||
this.guardianType = '1';
|
||||
this.guardianPatientName = '';
|
||||
this.guardianUserPatientId = 0;
|
||||
this.guardianRelations = '';
|
||||
this.guardianRelation = '';
|
||||
this.guardianForm = {
|
||||
name: '',
|
||||
idCard: '',
|
||||
mobile: '',
|
||||
};
|
||||
},
|
||||
onGuardianTypeChange() {
|
||||
this.guardianPatientName = '';
|
||||
this.guardianUserPatientId = 0;
|
||||
this.guardianRelations = '';
|
||||
this.guardianRelation = '';
|
||||
this.guardianForm = {
|
||||
name: '',
|
||||
idCard: '',
|
||||
mobile: '',
|
||||
};
|
||||
},
|
||||
guardianPatientCallback(index) {
|
||||
const item = this.guardianPickerList[index];
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
this.guardianPatientName = item.text;
|
||||
this.guardianUserPatientId = item.key;
|
||||
},
|
||||
guardianRelationCallback(index) {
|
||||
this.guardianRelations = this.actionSheetList[index].text;
|
||||
this.guardianRelation = this.actionSheetList[index].key;
|
||||
},
|
||||
isAgeInRange(age) {
|
||||
const n = Number(age);
|
||||
return age !== '' && !isNaN(n) && n >= 1 && n <= 200;
|
||||
},
|
||||
calcAgeFromIdCard(idCard) {
|
||||
const reg =
|
||||
/^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
|
||||
if (!reg.test(idCard)) {
|
||||
return false;
|
||||
}
|
||||
const orgBirthday = idCard.substring(6, 14);
|
||||
const birthday =
|
||||
orgBirthday.substring(0, 4) +
|
||||
'-' +
|
||||
orgBirthday.substring(4, 6) +
|
||||
'-' +
|
||||
orgBirthday.substring(6, 8);
|
||||
const birthdays = new Date(birthday.replace(/-/g, '/'));
|
||||
const d = new Date();
|
||||
return (
|
||||
d.getFullYear() -
|
||||
birthdays.getFullYear() -
|
||||
(d.getMonth() < birthdays.getMonth() ||
|
||||
(d.getMonth() === birthdays.getMonth() && d.getDate() < birthdays.getDate()) ?
|
||||
1 :
|
||||
0)
|
||||
);
|
||||
},
|
||||
validatePatientAge() {
|
||||
if (!this.isAgeInRange(this.form.age)) {
|
||||
uni.showToast({
|
||||
title: '就诊人年龄需在1-200岁之间',
|
||||
icon: 'none',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
validateGuardian() {
|
||||
if (!this.showGuardianSection) {
|
||||
return true;
|
||||
}
|
||||
if (this.guardianType == '1') {
|
||||
if (!this.guardianUserPatientId) {
|
||||
uni.showToast({
|
||||
title: '请选择监护人就诊人',
|
||||
icon: 'none',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
const guardianPatient = this.patientList.find(
|
||||
(item) => Number(item.id) === Number(this.guardianUserPatientId)
|
||||
);
|
||||
if (guardianPatient && !this.isAgeInRange(guardianPatient.age)) {
|
||||
uni.showToast({
|
||||
title: '监护人年龄需在1-200岁之间',
|
||||
icon: 'none',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!this.guardianForm.name || !this.guardianForm.idCard || !this.guardianForm.mobile) {
|
||||
uni.showToast({
|
||||
title: '请填写完整监护人信息',
|
||||
icon: 'none',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (!/^\d{11}$/.test(this.guardianForm.mobile)) {
|
||||
uni.showToast({
|
||||
title: '监护人手机号格式不正确',
|
||||
icon: 'none',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
const guardianAge = this.calcAgeFromIdCard(this.guardianForm.idCard);
|
||||
if (guardianAge === false) {
|
||||
uni.showToast({
|
||||
title: '监护人身份证无效',
|
||||
icon: 'none',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (!this.isAgeInRange(guardianAge)) {
|
||||
uni.showToast({
|
||||
title: '监护人年龄需在1-200岁之间',
|
||||
icon: 'none',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
buildGuardianPayload(data) {
|
||||
if (!this.showGuardianSection) {
|
||||
return data;
|
||||
}
|
||||
data.guardian_type = Number(this.guardianType);
|
||||
if (this.guardianType == '1') {
|
||||
data.guardian_user_patient_id = this.guardianUserPatientId;
|
||||
} else {
|
||||
data.guardian_name = this.guardianForm.name;
|
||||
data.guardian_id_card = this.guardianForm.idCard;
|
||||
data.guardian_mobile = this.guardianForm.mobile;
|
||||
data.guardian_relation = this.guardianRelation;
|
||||
}
|
||||
return data;
|
||||
},
|
||||
isSaveSuccess(res) {
|
||||
return res.data.code === 0 || res.data.errcode == 0;
|
||||
},
|
||||
getSaveErrorMsg(res) {
|
||||
return res.data.message || res.data.msg || '保存失败';
|
||||
},
|
||||
// 添加就诊人
|
||||
getAdduser() {
|
||||
if (!this.validatePatientAge() || !this.validateGuardian()) {
|
||||
return;
|
||||
}
|
||||
const payload = this.buildGuardianPayload({
|
||||
store_id: uni.getStorageSync('store_id') || '11001',
|
||||
is_default: this.checked ? '1' : '0',
|
||||
id: this.addid,
|
||||
name: this.names,
|
||||
id_card: this.form.identityCardNo,
|
||||
sex: (this.form.sex) == '女' ? '2' : (this.form.sex == '男' ? '1' : this.form.sex),
|
||||
age: this.form.age,
|
||||
mobile: this.phone,
|
||||
relation: this.relation,
|
||||
is_visit: this.isVisit == '是' ? '1' : '0',
|
||||
liver_function: this.liver == '正常' ? '0' : '1',
|
||||
renal_function: this.renal == '正常' ? '0' : '1',
|
||||
allergic_status: this.allergic == '无' ? '0' : '1',
|
||||
person_status: this.person == '无' ? '0' : '1',
|
||||
family_status: this.family == '无' ? '0' : '1',
|
||||
allergic_history: this.allergic_history,
|
||||
person_history: this.person_history,
|
||||
family_history: this.family_history,
|
||||
});
|
||||
userAdd({
|
||||
method: "post",
|
||||
data: {
|
||||
store_id: uni.getStorageSync('store_id') || '11001',
|
||||
is_default: this.checked ? '1' : '0',
|
||||
id: this.addid,
|
||||
name: this.names,
|
||||
id_card: this.form.identityCardNo,
|
||||
sex: (this.form.sex) ,
|
||||
age: this.form.age,
|
||||
mobile: this.phone,
|
||||
relation: this.relation,
|
||||
is_visit: this.isVisit == '是' ? '1' : '0',
|
||||
liver_function: this.liver == '正常' ? '0' : '1',
|
||||
renal_function: this.renal == '正常' ? '0' : '1',
|
||||
allergic_status: this.allergic == '无' ? '0' : '1',
|
||||
person_status: this.person == '无' ? '0' : '1',
|
||||
family_status: this.family == '无' ? '0' : '1',
|
||||
allergic_history: this.allergic_history,
|
||||
person_history: this.person_history,
|
||||
family_history: this.family_history,
|
||||
}
|
||||
data: payload,
|
||||
})
|
||||
.then((res) => {
|
||||
// console.log(res, 'res');
|
||||
if (res.data.errcode == 0) {
|
||||
if (this.isSaveSuccess(res)) {
|
||||
|
||||
uni.showToast({
|
||||
title: "添加成功",
|
||||
@@ -481,9 +721,9 @@
|
||||
});
|
||||
}, 400)
|
||||
|
||||
} else if (res.data.errcode != 0) {
|
||||
} else {
|
||||
this.$refs.uToast.show({
|
||||
title: res.data.msg,
|
||||
title: this.getSaveErrorMsg(res),
|
||||
type: 'default',
|
||||
icon: false
|
||||
})
|
||||
@@ -595,6 +835,9 @@
|
||||
this.form.sex = sex;
|
||||
this.form.age = age;
|
||||
this.sex = org_gender% 2 == 1 ? 1 : 2;
|
||||
if (age > 6) {
|
||||
this.resetGuardian();
|
||||
}
|
||||
} else {
|
||||
this.form.sex = "";
|
||||
return false;
|
||||
@@ -602,7 +845,8 @@
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getAction()
|
||||
this.getAction();
|
||||
this.loadPatientList();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
<!-- 姓名 -->
|
||||
<view class="card_name">
|
||||
<text>姓名</text>
|
||||
<u-input disabled v-model="names" input-align="right" placeholder="请输入真实姓名"
|
||||
<u-input v-model="names" input-align="right" placeholder="请输入真实姓名"
|
||||
placeholder-style="text-align:right;color: #94A3B8;" :type="type" />
|
||||
</view>
|
||||
<!-- 身份证号 -->
|
||||
<view class="card_name">
|
||||
<text>身份证号</text>
|
||||
<u-input disabled v-model="form.identityCardNo" maxlength="18" input-align="right" placeholder="已经填写无法修改,请慎重填写"
|
||||
<u-input v-model="form.identityCardNo" maxlength="18" input-align="right" placeholder="请输入身份证号"
|
||||
placeholder-style="text-align:right;color: #94A3B8;padding-right:5px;" @input="inputChange"
|
||||
:type="type" />
|
||||
</view>
|
||||
@@ -53,6 +53,53 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 监护人信息(6岁及以下) -->
|
||||
<view class="card" v-if="showGuardianSection">
|
||||
<view class="card_title">监护人信息</view>
|
||||
<view class="cards_names" style="padding: 20rpx 0;">
|
||||
<text>填写方式</text>
|
||||
<u-radio-group v-model="guardianType" @change="onGuardianTypeChange">
|
||||
<u-radio name="1" style="margin-right: 40rpx;">选择已有就诊人</u-radio>
|
||||
<u-radio name="2">填写监护人信息</u-radio>
|
||||
</u-radio-group>
|
||||
</view>
|
||||
<view class="card_relation" v-if="guardianType == '1'">
|
||||
<text>监护人</text>
|
||||
<u-input v-model="guardianPatientName" type="select" input-align="right" placeholder="请选择"
|
||||
placeholder-style="text-align:right;color: #94A3B8;" @click="showGuardianPatient = true" />
|
||||
<u-icon name="arrow-right" color="#A7ABB0" size="26" @click="showGuardianPatient = true"></u-icon>
|
||||
<u-action-sheet :list="guardianPickerList" :safe-area-inset-bottom="true" v-model="showGuardianPatient"
|
||||
@click="guardianPatientCallback">
|
||||
</u-action-sheet>
|
||||
</view>
|
||||
<template v-if="guardianType == '2'">
|
||||
<view class="card_name">
|
||||
<text>姓名</text>
|
||||
<u-input v-model="guardianForm.name" input-align="right" placeholder="请输入监护人姓名"
|
||||
placeholder-style="text-align:right;color: #94A3B8;" :type="type" />
|
||||
</view>
|
||||
<view class="card_name">
|
||||
<text>身份证号</text>
|
||||
<u-input v-model="guardianForm.idCard" maxlength="18" input-align="right" placeholder="请输入身份证号"
|
||||
placeholder-style="text-align:right;color: #94A3B8;" :type="type" />
|
||||
</view>
|
||||
<view class="card_telephone">
|
||||
<text>手机号</text>
|
||||
<u-input v-model="guardianForm.mobile" input-align="right" placeholder="请输入手机号"
|
||||
placeholder-style="text-align:right; color: #94A3B8;" :type="type" />
|
||||
</view>
|
||||
<view class="card_relation">
|
||||
<text>与患儿关系</text>
|
||||
<u-input v-model="guardianRelations" type="select" input-align="right" placeholder="请选择"
|
||||
placeholder-style="text-align:right;color: #94A3B8;" @click="showGuardianRelat = true" />
|
||||
<u-icon name="arrow-right" color="#A7ABB0" size="26" @click="showGuardianRelat = true"></u-icon>
|
||||
<u-action-sheet :list="actionSheetList" :safe-area-inset-bottom="true" v-model="showGuardianRelat"
|
||||
@click="guardianRelationCallback">
|
||||
</u-action-sheet>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
|
||||
<!-- 健康信息 -->
|
||||
<view class="cards">
|
||||
<view class="cards_title">
|
||||
@@ -194,6 +241,7 @@
|
||||
import {
|
||||
userAdd,
|
||||
userEidtPatient,
|
||||
userGuardianInfo,
|
||||
userList,
|
||||
userRelation
|
||||
} from '../../request/api/api';
|
||||
@@ -347,12 +395,39 @@
|
||||
person_history: [],
|
||||
family_history: [],
|
||||
heathList: [], // 健康信息
|
||||
guardianType: '1',
|
||||
guardianPatientName: '',
|
||||
guardianUserPatientId: 0,
|
||||
guardianRelations: '',
|
||||
guardianRelation: '',
|
||||
showGuardianPatient: false,
|
||||
showGuardianRelat: false,
|
||||
allPatientList: [],
|
||||
guardianForm: {
|
||||
name: '',
|
||||
idCard: '',
|
||||
mobile: '',
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
showGuardianSection() {
|
||||
const age = Number(this.form.age);
|
||||
return this.form.age !== '' && !isNaN(age) && age <= 6;
|
||||
},
|
||||
guardianPickerList() {
|
||||
const currentId = Number(this.addid) || 0;
|
||||
return this.allPatientList
|
||||
.filter((item) => Number(item.id) !== currentId)
|
||||
.map((item) => ({
|
||||
text: `${item.name}(${item.age}岁)`,
|
||||
key: item.id,
|
||||
}));
|
||||
},
|
||||
},
|
||||
onLoad(e) {
|
||||
// console.log(e);
|
||||
this.id = e.id
|
||||
this.getAction()
|
||||
this.getAction()
|
||||
},
|
||||
watch: {
|
||||
// 默认就诊人
|
||||
@@ -507,7 +582,10 @@
|
||||
1 : 0);
|
||||
this.form.sex = sex;
|
||||
this.form.age = age;
|
||||
this.sex = org_gender;
|
||||
this.sex = org_gender % 2 == 1 ? 1 : 2;
|
||||
if (age > 6) {
|
||||
this.resetGuardian();
|
||||
}
|
||||
} else {
|
||||
this.form.sex = "";
|
||||
return false;
|
||||
@@ -522,10 +600,10 @@
|
||||
store_id: uni.getStorageSync('store_id') || '11001',
|
||||
}
|
||||
}).then((res) => {
|
||||
// console.log(res, 'relation');
|
||||
if (res.data.errcode == 0) {
|
||||
this.actionSheetList = res.data.data
|
||||
}
|
||||
this.getInfolist()
|
||||
})
|
||||
},
|
||||
|
||||
@@ -538,14 +616,12 @@
|
||||
store_id: uni.getStorageSync('store_id') || '11001',
|
||||
}
|
||||
}).then((res) => {
|
||||
// console.log(res, 'info');
|
||||
|
||||
if (res.data.errcode == 0) {
|
||||
that.infoList = res.data.data.filter((item) => item.id == that.id)
|
||||
that.allPatientList = res.data.data || [];
|
||||
that.infoList = that.allPatientList.filter((item) => item.id == that.id)
|
||||
|
||||
that.actived = that.infoList[0].id;
|
||||
that.names = that.infoList[0].name
|
||||
// that.relations = that.infoList[0].relations
|
||||
that.phone = that.infoList[0].mobile
|
||||
that.form.sex = (that.infoList[0].sex) % 2 == 0 ? '女' : '男'
|
||||
that.form.age = that.infoList[0].age
|
||||
@@ -554,40 +630,225 @@
|
||||
|
||||
that.actionSheetCallback(that.infoList[0].relation)
|
||||
that.getHeath()
|
||||
that.loadGuardianInfo()
|
||||
}
|
||||
})
|
||||
},
|
||||
loadGuardianInfo() {
|
||||
if (!this.showGuardianSection) {
|
||||
return;
|
||||
}
|
||||
userGuardianInfo({
|
||||
user_patient_id: this.addid,
|
||||
}).then((res) => {
|
||||
if (!(res.data.code === 0 || res.data.errcode == 0)) {
|
||||
return;
|
||||
}
|
||||
const info = res.data.result || res.data.data || {};
|
||||
if (!info.guardian_type) {
|
||||
return;
|
||||
}
|
||||
this.guardianType = String(info.guardian_type);
|
||||
if (this.guardianType == '1') {
|
||||
this.guardianUserPatientId = info.guardian_user_patient_id;
|
||||
if (info.guardian_patient_preview) {
|
||||
this.guardianPatientName = `${info.guardian_patient_preview.name}(${info.guardian_patient_preview.age}岁)`;
|
||||
}
|
||||
} else {
|
||||
this.guardianForm.name = info.guardian_name || '';
|
||||
this.guardianForm.idCard = info.guardian_id_card || '';
|
||||
this.guardianForm.mobile = info.guardian_mobile || '';
|
||||
this.guardianRelation = info.guardian_relation;
|
||||
const relationItem = this.actionSheetList.find((item) => item.key == info.guardian_relation);
|
||||
if (relationItem) {
|
||||
this.guardianRelations = relationItem.text;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
resetGuardian() {
|
||||
this.guardianType = '1';
|
||||
this.guardianPatientName = '';
|
||||
this.guardianUserPatientId = 0;
|
||||
this.guardianRelations = '';
|
||||
this.guardianRelation = '';
|
||||
this.guardianForm = {
|
||||
name: '',
|
||||
idCard: '',
|
||||
mobile: '',
|
||||
};
|
||||
},
|
||||
onGuardianTypeChange() {
|
||||
this.guardianPatientName = '';
|
||||
this.guardianUserPatientId = 0;
|
||||
this.guardianRelations = '';
|
||||
this.guardianRelation = '';
|
||||
this.guardianForm = {
|
||||
name: '',
|
||||
idCard: '',
|
||||
mobile: '',
|
||||
};
|
||||
},
|
||||
guardianPatientCallback(index) {
|
||||
const item = this.guardianPickerList[index];
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
this.guardianPatientName = item.text;
|
||||
this.guardianUserPatientId = item.key;
|
||||
},
|
||||
guardianRelationCallback(index) {
|
||||
this.guardianRelations = this.actionSheetList[index].text;
|
||||
this.guardianRelation = this.actionSheetList[index].key;
|
||||
},
|
||||
isAgeInRange(age) {
|
||||
const n = Number(age);
|
||||
return age !== '' && !isNaN(n) && n >= 1 && n <= 200;
|
||||
},
|
||||
calcAgeFromIdCard(idCard) {
|
||||
const reg =
|
||||
/^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
|
||||
if (!reg.test(idCard)) {
|
||||
return false;
|
||||
}
|
||||
const orgBirthday = idCard.substring(6, 14);
|
||||
const birthday =
|
||||
orgBirthday.substring(0, 4) +
|
||||
'-' +
|
||||
orgBirthday.substring(4, 6) +
|
||||
'-' +
|
||||
orgBirthday.substring(6, 8);
|
||||
const birthdays = new Date(birthday.replace(/-/g, '/'));
|
||||
const d = new Date();
|
||||
return (
|
||||
d.getFullYear() -
|
||||
birthdays.getFullYear() -
|
||||
(d.getMonth() < birthdays.getMonth() ||
|
||||
(d.getMonth() === birthdays.getMonth() && d.getDate() < birthdays.getDate()) ?
|
||||
1 :
|
||||
0)
|
||||
);
|
||||
},
|
||||
validatePatientAge() {
|
||||
if (!this.isAgeInRange(this.form.age)) {
|
||||
uni.showToast({
|
||||
title: '就诊人年龄需在1-200岁之间',
|
||||
icon: 'none',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
validateGuardian() {
|
||||
if (!this.showGuardianSection) {
|
||||
return true;
|
||||
}
|
||||
if (this.guardianType == '1') {
|
||||
if (!this.guardianUserPatientId) {
|
||||
uni.showToast({
|
||||
title: '请选择监护人就诊人',
|
||||
icon: 'none',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
const guardianPatient = this.allPatientList.find(
|
||||
(item) => Number(item.id) === Number(this.guardianUserPatientId)
|
||||
);
|
||||
if (guardianPatient && !this.isAgeInRange(guardianPatient.age)) {
|
||||
uni.showToast({
|
||||
title: '监护人年龄需在1-200岁之间',
|
||||
icon: 'none',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!this.guardianForm.name || !this.guardianForm.idCard || !this.guardianForm.mobile) {
|
||||
uni.showToast({
|
||||
title: '请填写完整监护人信息',
|
||||
icon: 'none',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (!/^\d{11}$/.test(this.guardianForm.mobile)) {
|
||||
uni.showToast({
|
||||
title: '监护人手机号格式不正确',
|
||||
icon: 'none',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
const guardianAge = this.calcAgeFromIdCard(this.guardianForm.idCard);
|
||||
if (guardianAge === false) {
|
||||
uni.showToast({
|
||||
title: '监护人身份证无效',
|
||||
icon: 'none',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (!this.isAgeInRange(guardianAge)) {
|
||||
uni.showToast({
|
||||
title: '监护人年龄需在1-200岁之间',
|
||||
icon: 'none',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
buildGuardianPayload(data) {
|
||||
if (!this.showGuardianSection) {
|
||||
return data;
|
||||
}
|
||||
data.guardian_type = Number(this.guardianType);
|
||||
if (this.guardianType == '1') {
|
||||
data.guardian_user_patient_id = this.guardianUserPatientId;
|
||||
} else {
|
||||
data.guardian_name = this.guardianForm.name;
|
||||
data.guardian_id_card = this.guardianForm.idCard;
|
||||
data.guardian_mobile = this.guardianForm.mobile;
|
||||
data.guardian_relation = this.guardianRelation;
|
||||
}
|
||||
return data;
|
||||
},
|
||||
isSaveSuccess(res) {
|
||||
return res.data.code === 0 || res.data.errcode == 0;
|
||||
},
|
||||
getSaveErrorMsg(res) {
|
||||
return res.data.message || res.data.msg || '保存失败';
|
||||
},
|
||||
|
||||
// 添加就诊人
|
||||
getAdduser() {
|
||||
if (!this.validatePatientAge() || !this.validateGuardian()) {
|
||||
return;
|
||||
}
|
||||
const payload = this.buildGuardianPayload({
|
||||
store_id: uni.getStorageSync('store_id') || '11001',
|
||||
id: this.addid,
|
||||
name: this.names,
|
||||
id_card: this.form.identityCardNo,
|
||||
sex: (this.form.sex) == '女' ? '2' : '1',
|
||||
age: this.form.age,
|
||||
mobile: this.phone,
|
||||
relation: this.relation,
|
||||
is_visit: this.isVisit == '是' ? '1' : '0',
|
||||
liver_function: this.liver == '正常' ? '0' : '1',
|
||||
renal_function: this.renal == '正常' ? '0' : '1',
|
||||
allergic_status: this.allergic == '无' ? '0' : '1',
|
||||
person_status: this.person == '无' ? '0' : '1',
|
||||
family_status: this.family == '无' ? '0' : '1',
|
||||
allergic_history: this.allergic_history,
|
||||
person_history: this.person_history,
|
||||
family_history: this.family_history,
|
||||
});
|
||||
userAdd({
|
||||
method: "post",
|
||||
data: {
|
||||
store_id: uni.getStorageSync('store_id') || '11001',
|
||||
id: this.addid,
|
||||
name: this.names,
|
||||
id_card: this.form.identityCardNo,
|
||||
sex: (this.form.sex) == '女' ? '2' : '1',
|
||||
age: this.form.age,
|
||||
mobile: this.phone,
|
||||
relation: this.relation,
|
||||
is_visit: this.isVisit == '是' ? '1' : '0',
|
||||
liver_function: this.liver == '正常' ? '0' : '1',
|
||||
renal_function: this.renal == '正常' ? '0' : '1',
|
||||
allergic_status: this.allergic == '无' ? '0' : '1',
|
||||
person_status: this.person == '无' ? '0' : '1',
|
||||
family_status: this.family == '无' ? '0' : '1',
|
||||
allergic_history: this.allergic_history,
|
||||
person_history: this.person_history,
|
||||
family_history: this.family_history,
|
||||
}
|
||||
data: payload,
|
||||
})
|
||||
.then((res) => {
|
||||
console.log(res, 'res');
|
||||
if (res.data.errcode == 0) {
|
||||
if (this.isSaveSuccess(res)) {
|
||||
|
||||
uni.showToast({
|
||||
title: "添加成功",
|
||||
title: "保存成功",
|
||||
duration: 1500,
|
||||
icon: "success",
|
||||
mask: false
|
||||
@@ -599,15 +860,9 @@
|
||||
});
|
||||
}, 400)
|
||||
|
||||
} else if (res.data.errcode != 0) {
|
||||
// uni.showToast({
|
||||
// title: res.data.msg,
|
||||
// icon: "error",
|
||||
// duration: 1500,
|
||||
// mask: false
|
||||
// })
|
||||
} else {
|
||||
this.$refs.uToast.show({
|
||||
title: res.data.msg,
|
||||
title: this.getSaveErrorMsg(res),
|
||||
type: 'default',
|
||||
icon: false
|
||||
})
|
||||
@@ -675,9 +930,6 @@
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getInfolist()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -24,13 +24,14 @@
|
||||
<text class="sign">[{{item.text}}]</text>
|
||||
<text class="default" v-if="item.is_default==1">默认</text>
|
||||
</view>
|
||||
<view class="info_sex" @tap.stop="toEidt(item.id)">
|
||||
编辑
|
||||
<view class="info_actions">
|
||||
<text class="info_action_edit" @tap.stop="toEidt(item.id)">编辑</text>
|
||||
<text class="info_action_del" @tap.stop="confirmDelete(item.id, item.name)">删除</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info_list_bottom">
|
||||
<text class="id">{{item.id_card.replace(/(\w{6})\w*(\w{4})/,'$1********$2')}}</text>
|
||||
<text class="telephone">{{item.mobile.replace(/(\d{3})\d*(\d{4})/, '$1****$2')}}</text>
|
||||
<text class="id">{{item.id_card_tm || item.id_card}}</text>
|
||||
<text class="telephone">{{item.mobile_tm || item.mobile}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -66,6 +67,7 @@
|
||||
import {
|
||||
userList,
|
||||
userPatientChoose,
|
||||
userPatientDel,
|
||||
userRelation
|
||||
} from '../../request/api/api'
|
||||
export default {
|
||||
@@ -142,6 +144,45 @@
|
||||
})
|
||||
},
|
||||
|
||||
confirmDelete(id, name) {
|
||||
uni.showModal({
|
||||
title: '确认删除',
|
||||
content: `删除后「${name}」的就诊人信息将无法恢复,是否继续?`,
|
||||
confirmText: '确认删除',
|
||||
cancelText: '取消',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
this.deletePatient(id);
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
deletePatient(id) {
|
||||
userPatientDel({
|
||||
method: 'post',
|
||||
data: {
|
||||
id,
|
||||
store_id: uni.getStorageSync('store_id') || '11001',
|
||||
},
|
||||
}).then((res) => {
|
||||
if (res.data.code === 0 || res.data.errcode == 0) {
|
||||
uni.showToast({
|
||||
title: '删除成功',
|
||||
icon: 'success',
|
||||
duration: 1500,
|
||||
});
|
||||
this.getInfolist();
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.data.message || res.data.msg || '删除失败',
|
||||
icon: 'none',
|
||||
duration: 1500,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 默认就诊人
|
||||
choose(e) {
|
||||
userPatientChoose({
|
||||
@@ -307,11 +348,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
.info_sex {
|
||||
.info_actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.info_action_edit {
|
||||
color: #1777FF;
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.info_action_del {
|
||||
color: #EF4444;
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
.info_list_bottom {
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
<view class="info_item">
|
||||
<view class="name">
|
||||
电话:
|
||||
<text>{{infoList.patient.mobile}}</text>
|
||||
<text>{{infoList.patient.mobile_tm || infoList.patient.mobile}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -82,6 +82,26 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="data.online_tcm_print && data.online_tcm_print.show" class="info">
|
||||
<view v-if="data.online_tcm_print.tcm_syndrome" class="info_item">
|
||||
<view class="names">
|
||||
中医证候:
|
||||
<text>{{ data.online_tcm_print.tcm_syndrome }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="data.online_tcm_print.tcm_method" class="info_item">
|
||||
<view class="names">
|
||||
中医治法:
|
||||
<text>{{ data.online_tcm_print.tcm_method }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="data.online_tcm_print.tcm_disease" class="info_item">
|
||||
<view class="names">
|
||||
中医疾病:
|
||||
<text>{{ data.online_tcm_print.tcm_disease }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bg">
|
||||
@@ -115,13 +135,14 @@
|
||||
</block>
|
||||
|
||||
<block v-if="data.prescription_type==2||data.prescription_type == 5||data.prescription_type == 7">
|
||||
<view class="item" v-for="(it,index) in infoList.repice" :key="item.id">
|
||||
<view class="item" v-for="(it,index) in infoList.repice" :key="it.id || index">
|
||||
<!-- v-for="(it,index) in item.content" :key="it.id" -->
|
||||
<view class="name" style="justify-content: space-between;">
|
||||
<view class="yp_name">
|
||||
<text>{{ it.content.drug_name}} </text>
|
||||
<text>{{ (it.content && it.content.drug_name) || '' }} </text>
|
||||
<text
|
||||
style="font-size: 24rpx;margin-left: 10rpx;">{{ it.content.specification }}</text>
|
||||
v-if="it.content && it.content.specification"
|
||||
class="drug-spec">{{ it.content.specification }}</text>
|
||||
</view>
|
||||
<text>x{{ it.number}}</text>
|
||||
</view>
|
||||
@@ -246,7 +267,7 @@
|
||||
</view>
|
||||
<view class="name">
|
||||
<text>电话:</text>
|
||||
{{infoList.patient.mobile}}
|
||||
{{infoList.patient.mobile_tm || infoList.patient.mobile}}
|
||||
</view>
|
||||
<view class="name">
|
||||
<text>开具日期:</text>
|
||||
@@ -258,6 +279,50 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bg" v-if="infoList.repice && infoList.repice.length">
|
||||
<view class="my_medical">
|
||||
<view class="title">Rp</view>
|
||||
|
||||
<block v-if="data.prescription_type==1 || data.prescription_type==3">
|
||||
<view class="items" v-for="(item,index) in infoList.repice" :key="item.id">
|
||||
<view class="name">
|
||||
<view class="_name" v-for="(it,index) in item.content" :key="it.id">
|
||||
<view class="text">
|
||||
<text>{{ it.name}}</text>
|
||||
<text class="_abbr" v-if="it.order!=0">[{{useWay[it.order]}}]</text>
|
||||
</view>
|
||||
<text class="name_num">{{ it.number }}{{it.unit?it.unit.name:'g'}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="details">
|
||||
<view class="text">
|
||||
<text>用法:煎服,每天 {{item.consumption}} 次 ,</text>
|
||||
<text v-if="item.deployment==2">{{' 每次 '+item.volume+' ml '}} , </text>
|
||||
<text> 共 {{item.dosage}} 剂</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<block v-if="data.prescription_type==2||data.prescription_type == 5||data.prescription_type == 7">
|
||||
<view class="item" v-for="(it,index) in infoList.repice" :key="it.id || index">
|
||||
<view class="name" style="justify-content: space-between;">
|
||||
<view class="yp_name">
|
||||
<text>{{ (it.content && it.content.drug_name) || '' }} </text>
|
||||
<text
|
||||
v-if="it.content && it.content.specification"
|
||||
class="drug-spec">{{ it.content.specification }}</text>
|
||||
</view>
|
||||
<text>x{{ it.number}}</text>
|
||||
</view>
|
||||
<view class="details" v-if="data.prescription_type==2">
|
||||
<text>用法:{{ it.instruction }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 医嘱 -->
|
||||
<view class="order_status" v-if="status==0" style="color: #E88F16;">
|
||||
您的处方正在审核中
|
||||
@@ -378,6 +443,25 @@
|
||||
url: "/subPackages/my/record-pay?id=" + this.data.id
|
||||
})
|
||||
},
|
||||
normalizeRepice(list) {
|
||||
return (list || []).map((it) => {
|
||||
let content = it.content
|
||||
if (typeof content === 'string') {
|
||||
try {
|
||||
content = JSON.parse(content || '{}')
|
||||
} catch (e) {
|
||||
content = {}
|
||||
}
|
||||
}
|
||||
if (!content || typeof content !== 'object' || Array.isArray(content)) {
|
||||
content = Array.isArray(content) ? content : {}
|
||||
}
|
||||
return {
|
||||
...it,
|
||||
content,
|
||||
}
|
||||
})
|
||||
},
|
||||
getInfo() {
|
||||
getPrescriptInfo({
|
||||
method: "post",
|
||||
@@ -389,7 +473,9 @@
|
||||
// console.log(res, 'deta');
|
||||
|
||||
if (res.data.errcode === 0) {
|
||||
this.infoList = res.data.data.content
|
||||
const content = res.data.data.content
|
||||
content.repice = this.normalizeRepice(content.repice)
|
||||
this.infoList = content
|
||||
this.rpList = res.data.data.pharmacistInfo
|
||||
this.status = res.data.data.status
|
||||
this.data = res.data.data
|
||||
@@ -657,6 +743,12 @@
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.drug-spec {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.details {
|
||||
|
||||
@@ -100,6 +100,13 @@
|
||||
<view class="it_info">
|
||||
{{item.content.usage}}
|
||||
</view>
|
||||
<view
|
||||
class="instruction-btn"
|
||||
v-if="prescriptionStatus && item.content && item.content.instruction"
|
||||
@click="previewInstruction(item.content.instruction)"
|
||||
>
|
||||
<text>查看说明书</text>
|
||||
</view>
|
||||
<view class="it_price">
|
||||
<text>¥{{item.total_price}}</text>
|
||||
<view class="it_num">
|
||||
@@ -198,6 +205,7 @@
|
||||
} from '../../request/api/api'
|
||||
// 导入 getOrderTextApi 接口方法
|
||||
import { getOrderTextApi } from '../../request/api/product'
|
||||
import { getPrescriptionStatusApi } from '../../request/api/order'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@@ -266,7 +274,8 @@
|
||||
color: '#111000',
|
||||
fontWeight: '540',
|
||||
fontSize: '33rpx'
|
||||
}
|
||||
},
|
||||
prescriptionStatus: false,
|
||||
}
|
||||
},
|
||||
onLoad(e) {
|
||||
@@ -496,9 +505,36 @@
|
||||
this.isshow = true
|
||||
}
|
||||
}
|
||||
this.getPrescriptionStatus()
|
||||
}
|
||||
})
|
||||
},
|
||||
getPrescriptionStatus() {
|
||||
if (!this.order_id) {
|
||||
return
|
||||
}
|
||||
getPrescriptionStatusApi({
|
||||
order_id: this.order_id
|
||||
}).then((res) => {
|
||||
if (res.data && (res.data.code == 0 || res.data.errcode == 0)) {
|
||||
const data = res.data.data || res.data.result || {}
|
||||
const ps = data.prescription_status ?? data.status
|
||||
this.prescriptionStatus = data.status === true || ps === 1 || ps === '1' || ps === 3 || ps === '3' || ps === 4 || ps === '4'
|
||||
} else {
|
||||
this.prescriptionStatus = false
|
||||
}
|
||||
}).catch(() => {
|
||||
this.prescriptionStatus = false
|
||||
})
|
||||
},
|
||||
previewInstruction(instructionImage) {
|
||||
if (instructionImage) {
|
||||
uni.previewImage({
|
||||
urls: [instructionImage],
|
||||
current: instructionImage
|
||||
})
|
||||
}
|
||||
},
|
||||
// 代煎费
|
||||
getServe() {
|
||||
getUseWayPay({
|
||||
@@ -915,6 +951,26 @@
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.instruction-btn {
|
||||
margin-top: 16rpx;
|
||||
margin-bottom: 16rpx;
|
||||
padding: 12rpx 24rpx;
|
||||
background: #ECF5FF;
|
||||
border-radius: 8rpx;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
text {
|
||||
font-size: 26rpx;
|
||||
color: #2B85E4;
|
||||
}
|
||||
|
||||
&:active {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
.it_price {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -61,6 +61,10 @@
|
||||
<text class="label">批准文号</text>
|
||||
<text class="val">{{ productDetail.guozi_no }}</text>
|
||||
</view>
|
||||
<view class="spec-item" v-if="manufacturerName">
|
||||
<text class="label">厂家</text>
|
||||
<text class="val">{{ manufacturerName }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 平台资质入口 -->
|
||||
@@ -78,7 +82,7 @@
|
||||
|
||||
|
||||
<!-- 4. 功效与用法 (卡片式布局 + 优化标题) -->
|
||||
<view class="info-card" v-if="productDetail.category_type !== 'health_food'">
|
||||
<view class="info-card" v-if="showFunctionSection">
|
||||
<!-- 优化点:医疗风格标题 -->
|
||||
<view class="section-title-modern">
|
||||
<view class="indicator"></view>
|
||||
@@ -262,7 +266,8 @@ export default {
|
||||
bar_code: '',
|
||||
indications: '',
|
||||
indications_array: [],
|
||||
compliance_tip: '' // 合规提示文案,由后端返回
|
||||
compliance_tip: '', // 合规提示文案,由后端返回
|
||||
supplier: null
|
||||
},
|
||||
formData: {
|
||||
id: '',
|
||||
@@ -298,6 +303,14 @@ export default {
|
||||
// 合规提示文案 - 从后端返回的 compliance_tip 字段获取
|
||||
complianceTip() {
|
||||
return this.productDetail.compliance_tip || '';
|
||||
},
|
||||
manufacturerName() {
|
||||
return (this.productDetail.supplier && this.productDetail.supplier.name) || '';
|
||||
},
|
||||
showFunctionSection() {
|
||||
if (this.productDetail.category_type === 'health_food') return false;
|
||||
if (this.productDetail.type == 2 && this.productDetail.is_otc === 0) return false;
|
||||
return true;
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
身份证号
|
||||
</view>
|
||||
<view class="word_num" v-if="registList.idcard">
|
||||
{{registList.idcard.replace(/(\w{6})\w*(\w{4})/,'$1********$2')}}
|
||||
{{registList.idcard_tm || registList.idcard}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="name_edit">
|
||||
@@ -133,7 +133,7 @@
|
||||
手机号
|
||||
</view>
|
||||
<view class="word_num" v-if="registList.mobile">
|
||||
{{registList.mobile.replace(/(\d{3})\d*(\d{4})/, '$1****$2')}}
|
||||
{{registList.mobile_tm || registList.mobile}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
身份证号
|
||||
</view>
|
||||
<view class="word_num" v-if="registList.idcard">
|
||||
{{registList.idcard.replace(/(\w{6})\w*(\w{4})/,'$1********$2')}}
|
||||
{{registList.idcard_tm || registList.idcard}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="name_edit">
|
||||
@@ -94,7 +94,7 @@
|
||||
手机号
|
||||
</view>
|
||||
<view class="word_num" v-if="registList.mobile">
|
||||
{{registList.mobile.replace(/(\d{3})\d*(\d{4})/, '$1****$2')}}
|
||||
{{registList.mobile_tm || registList.mobile}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<view class="info">收货信息</view>
|
||||
<text class="iconfont icon-guanbi" @click.stop="deleList(item.id)"></text>
|
||||
</view>
|
||||
<view class="name">{{ item.name }} {{ item.mobile }}</view>
|
||||
<view class="name">{{ item.name }} {{ item.mobile_tm || item.mobile }}</view>
|
||||
<view class="name">{{ item.region }}{{ item.detail_address }}</view>
|
||||
|
||||
<!-- 默认发货信息 -->
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<view class="head" v-if="logisticsList.express_name!=''">
|
||||
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/mine/mr_tx.png" mode=""></image>
|
||||
<view class="head_info">
|
||||
<view class="name">{{logisticsList.express_name}} {{logisticsList.express_mobile}}</view>
|
||||
<view class="name">{{logisticsList.express_name}} {{logisticsList.express_mobile_tm || logisticsList.express_mobile}}</view>
|
||||
<view class="choose_area">{{logisticsList.express_region}}{{logisticsList.express_address}}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<view class="state">
|
||||
<text>收货地址</text>
|
||||
</view>
|
||||
<view class="name">{{orderDetailList.express_name}} {{orderDetailList.express_mobile}}</view>
|
||||
<view class="name">{{orderDetailList.express_name}} {{orderDetailList.express_mobile_tm || orderDetailList.express_mobile}}</view>
|
||||
<view class="choose_area">{{orderDetailList.express_region}}{{orderDetailList.express_address}}</view>
|
||||
</view>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<!-- 收货地址 已添加地址 -->
|
||||
<view class="head" v-else @click="toArea">
|
||||
<view class="state"><text>收货地址</text></view>
|
||||
<view class="name">{{addList[0].name}} {{addList[0].mobile}}</view>
|
||||
<view class="name">{{addList[0].name}} {{addList[0].mobile_tm || addList[0].mobile}}</view>
|
||||
<view class="choose_area">{{addList[0].region}}{{addList[0].detail_address}}</view>
|
||||
</view>
|
||||
|
||||
|
||||
23
utils/image-compress-modal.js
Normal file
23
utils/image-compress-modal.js
Normal file
@@ -0,0 +1,23 @@
|
||||
let popupInstance = null;
|
||||
|
||||
export function registerImageCompressPopup(instance) {
|
||||
popupInstance = instance;
|
||||
}
|
||||
|
||||
export function openImageCompressModal({ path, size }) {
|
||||
if (!popupInstance || typeof popupInstance.open !== 'function') {
|
||||
console.warn('image-compress-popup 未注册,将直接使用原图');
|
||||
return Promise.resolve({
|
||||
path,
|
||||
size,
|
||||
usedCompress: false,
|
||||
});
|
||||
}
|
||||
|
||||
return popupInstance.open({ path, size }).then((result) => {
|
||||
if (!result) {
|
||||
return null;
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
95
utils/image-compress.js
Normal file
95
utils/image-compress.js
Normal file
@@ -0,0 +1,95 @@
|
||||
import { openImageCompressModal } from '@/utils/image-compress-modal.js';
|
||||
|
||||
export const IMAGE_COMPRESS_THRESHOLD = 1 * 1024 * 1024;
|
||||
|
||||
export function formatFileSize(bytes) {
|
||||
if (bytes === 0) return '0 B';
|
||||
const k = 1024;
|
||||
const sizes = ['B', 'KB', 'MB', 'GB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
const value = bytes / k ** i;
|
||||
return `${Number.parseFloat(value.toFixed(2))} ${sizes[i]}`;
|
||||
}
|
||||
|
||||
/** 压缩节省比例文案,如「(约节省 42%)」 */
|
||||
export function formatSavingsPercent(originalBytes, compressedBytes) {
|
||||
if (originalBytes <= 0 || compressedBytes >= originalBytes) {
|
||||
return '';
|
||||
}
|
||||
const percent = Math.round(
|
||||
((originalBytes - compressedBytes) / originalBytes) * 100,
|
||||
);
|
||||
return percent > 0 ? `(约节省 ${percent}%)` : '';
|
||||
}
|
||||
|
||||
function getFileInfo(filePath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.getFileInfo({
|
||||
filePath,
|
||||
success: resolve,
|
||||
fail: reject,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function compressImagePath(src, quality) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.compressImage({
|
||||
src,
|
||||
quality,
|
||||
success: async (res) => {
|
||||
try {
|
||||
const info = await getFileInfo(res.tempFilePath);
|
||||
resolve({
|
||||
path: res.tempFilePath,
|
||||
size: info.size,
|
||||
});
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
},
|
||||
fail: reject,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export async function tryCompressImage(
|
||||
src,
|
||||
qualities = [80, 60, 40],
|
||||
onProgress,
|
||||
) {
|
||||
let result = null;
|
||||
for (const quality of qualities) {
|
||||
onProgress && onProgress(quality);
|
||||
result = await compressImagePath(src, quality);
|
||||
if (result.size <= IMAGE_COMPRESS_THRESHOLD) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function isGifPath(path) {
|
||||
return /\.gif$/i.test(path || '');
|
||||
}
|
||||
|
||||
export async function prepareImagePath({ path, size }) {
|
||||
if (size <= IMAGE_COMPRESS_THRESHOLD) {
|
||||
return {
|
||||
path,
|
||||
size,
|
||||
usedCompress: false,
|
||||
};
|
||||
}
|
||||
|
||||
const result = await openImageCompressModal({ path, size });
|
||||
if (!result) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
path: result.path,
|
||||
size: result.size,
|
||||
usedCompress: !!result.usedCompress,
|
||||
};
|
||||
}
|
||||
@@ -6,8 +6,8 @@ export function checkDev(key = '') {
|
||||
// 判断某些模块是否开启
|
||||
switch (key) {
|
||||
case 'dev':
|
||||
return false;
|
||||
// return true;
|
||||
// return false;
|
||||
return true;
|
||||
case 'open-im':
|
||||
// return false;
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user