1. 诊所管理
This commit is contained in:
@@ -28,26 +28,26 @@ function getOssSignatureByPrefix(prefix, headerKey) {
|
||||
});
|
||||
}
|
||||
|
||||
function registerOssFileByPrefix(prefix, headerKey, url) {
|
||||
function registerOssFileByPrefix(prefix, headerKey, url, fileSize = 0) {
|
||||
return req.request({
|
||||
url: `${prefix}register-oss-file`,
|
||||
method: 'POST',
|
||||
data: { url, source: 2 },
|
||||
data: { url, source: 2, file_size: fileSize },
|
||||
header: {
|
||||
[headerKey]: '1',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function registerBusinessOssFile(url) {
|
||||
function registerBusinessOssFile(url, fileSize = 0) {
|
||||
const mode = uni.getStorageSync('loginMode');
|
||||
if (mode === 'platform_admin') {
|
||||
return registerOssFileByPrefix(PLATFORM_PREFIX, '_platformAdmin', url);
|
||||
return registerOssFileByPrefix(PLATFORM_PREFIX, '_platformAdmin', url, fileSize);
|
||||
}
|
||||
if (mode === 'clinic_admin') {
|
||||
return registerOssFileByPrefix(CLINIC_ADMIN_PREFIX, '_clinicAdmin', url);
|
||||
return registerOssFileByPrefix(CLINIC_ADMIN_PREFIX, '_clinicAdmin', url, fileSize);
|
||||
}
|
||||
return registerOssFileByPrefix(SALESPERSON_PREFIX, '_salesperson', url);
|
||||
return registerOssFileByPrefix(SALESPERSON_PREFIX, '_salesperson', url, fileSize);
|
||||
}
|
||||
|
||||
export { registerBusinessOssFile };
|
||||
|
||||
@@ -48,7 +48,7 @@ export async function getOssSignatureFromBackend() {
|
||||
* @returns {Promise<{ url: string, objectName: string }>}
|
||||
*/
|
||||
export async function uploadToOss(options) {
|
||||
const { filePath, onProgress } = options || {};
|
||||
const { filePath, onProgress, fileSize = 0 } = options || {};
|
||||
if (!filePath) {
|
||||
throw new Error('文件路径为空');
|
||||
}
|
||||
@@ -76,7 +76,7 @@ export async function uploadToOss(options) {
|
||||
if (code >= 200 && code < 300 || code === 204) {
|
||||
const host = String(signature.host).replace(/\/$/, '');
|
||||
const url = `${host}/${objectName}`;
|
||||
registerBusinessOssFile(url).catch((err) => {
|
||||
registerBusinessOssFile(url, fileSize).catch((err) => {
|
||||
console.warn('OSS 文件登记失败:', err);
|
||||
});
|
||||
resolve({
|
||||
|
||||
22
subPackages/sub_salesperson/common/imageGalleryBridge.js
Normal file
22
subPackages/sub_salesperson/common/imageGalleryBridge.js
Normal file
@@ -0,0 +1,22 @@
|
||||
let pending = null
|
||||
|
||||
export function requestGalleryPick() {
|
||||
return new Promise((resolve, reject) => {
|
||||
pending = { resolve, reject }
|
||||
uni.$emit('salesperson:open-gallery')
|
||||
})
|
||||
}
|
||||
|
||||
export function resolveGalleryPick(url) {
|
||||
if (pending) {
|
||||
pending.resolve(url)
|
||||
pending = null
|
||||
}
|
||||
}
|
||||
|
||||
export function cancelGalleryPick() {
|
||||
if (pending) {
|
||||
pending.reject(new Error('cancel'))
|
||||
pending = null
|
||||
}
|
||||
}
|
||||
@@ -1,45 +1,26 @@
|
||||
import { prepareImagePath } from '@/common/js/image-compress.js'
|
||||
import { uploadToOss } from '@/common/js/oss-upload.js'
|
||||
import { requestGalleryPick } from '@/subPackages/sub_salesperson/common/imageGalleryBridge.js'
|
||||
|
||||
/**
|
||||
* 选择并上传图片(压缩 + OSS 直传)
|
||||
* @param {{ count?: number }} options count>1 时依次上传多张,返回 url 数组
|
||||
*/
|
||||
export function pickAndUploadImage(options = {}) {
|
||||
const count = Math.min(Math.max(options.count || 1, 1), 9)
|
||||
function chooseImageFromDevice(count = 1) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.chooseImage({
|
||||
count,
|
||||
sizeType: ['original', 'compressed'],
|
||||
sourceType: ['album', 'camera'],
|
||||
success: async (res) => {
|
||||
uni.showLoading({ title: '上传中...', mask: true })
|
||||
try {
|
||||
const files = res.tempFiles || []
|
||||
const paths = files.length
|
||||
? files.map((f) => f.path)
|
||||
: (res.tempFilePaths || [])
|
||||
const urls = []
|
||||
for (const path of paths) {
|
||||
const prepared = await prepareImagePath({
|
||||
path,
|
||||
size: files.find((f) => f.path === path)?.size,
|
||||
})
|
||||
if (!prepared) continue
|
||||
const result = await uploadToOss({ filePath: prepared.path })
|
||||
urls.push(result.url)
|
||||
}
|
||||
uni.hideLoading()
|
||||
if (!urls.length) {
|
||||
reject(new Error('上传失败'))
|
||||
return
|
||||
}
|
||||
resolve(count === 1 ? urls[0] : urls)
|
||||
} catch (e) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: e.message || '上传失败', icon: 'none' })
|
||||
reject(e)
|
||||
}
|
||||
uni.showActionSheet({
|
||||
itemList: ['拍照', '从相册选择'],
|
||||
success: (sheet) => {
|
||||
const sourceType = sheet.tapIndex === 0 ? ['camera'] : ['album']
|
||||
uni.chooseImage({
|
||||
count,
|
||||
sizeType: ['original', 'compressed'],
|
||||
sourceType,
|
||||
success: (res) => resolve(res),
|
||||
fail: (err) => {
|
||||
if (err && err.errMsg && err.errMsg.indexOf('cancel') !== -1) {
|
||||
reject(new Error('cancel'))
|
||||
return
|
||||
}
|
||||
reject(err)
|
||||
},
|
||||
})
|
||||
},
|
||||
fail: (err) => {
|
||||
if (err && err.errMsg && err.errMsg.indexOf('cancel') !== -1) {
|
||||
@@ -52,6 +33,50 @@ export function pickAndUploadImage(options = {}) {
|
||||
})
|
||||
}
|
||||
|
||||
async function uploadChosenImages(res, count = 1) {
|
||||
uni.showLoading({ title: '上传中...', mask: true })
|
||||
try {
|
||||
const files = res.tempFiles || []
|
||||
const paths = files.length ? files.map((f) => f.path) : (res.tempFilePaths || [])
|
||||
const urls = []
|
||||
for (const path of paths) {
|
||||
const prepared = await prepareImagePath({
|
||||
path,
|
||||
size: files.find((f) => f.path === path)?.size,
|
||||
})
|
||||
if (!prepared) continue
|
||||
const fileSize = files.find((f) => f.path === path)?.size || 0
|
||||
const result = await uploadToOss({ filePath: prepared.path, fileSize })
|
||||
urls.push(result.url)
|
||||
}
|
||||
uni.hideLoading()
|
||||
if (!urls.length) throw new Error('上传失败')
|
||||
return count === 1 ? urls[0] : urls
|
||||
} catch (e) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: e.message || '上传失败', icon: 'none' })
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开图库选择(由页面内 link 单独触发)
|
||||
*/
|
||||
export function openGalleryPick() {
|
||||
return requestGalleryPick()
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择并上传图片(压缩 + OSS 直传)
|
||||
* @param {{ count?: number }} options count>1 时依次上传多张,返回 url 数组
|
||||
*/
|
||||
export function pickAndUploadImage(options = {}) {
|
||||
const count = Math.min(Math.max(options.count || 1, 1), 9)
|
||||
return chooseImageFromDevice(count)
|
||||
.then((res) => uploadChosenImages(res, count))
|
||||
.catch((err) => Promise.reject(err))
|
||||
}
|
||||
|
||||
function getUserDataPath() {
|
||||
if (typeof wx !== 'undefined' && wx.env && wx.env.USER_DATA_PATH) {
|
||||
return wx.env.USER_DATA_PATH
|
||||
@@ -177,6 +202,7 @@ export function createDefaultDoctorInputForm() {
|
||||
card_up: '',
|
||||
card_down: '',
|
||||
sign_image: '',
|
||||
register_price: 0,
|
||||
store_id: 0,
|
||||
store_ids: [],
|
||||
}
|
||||
|
||||
181
subPackages/sub_salesperson/components/ImageGalleryPicker.vue
Normal file
181
subPackages/sub_salesperson/components/ImageGalleryPicker.vue
Normal file
@@ -0,0 +1,181 @@
|
||||
<template>
|
||||
<u-popup v-model="visible" mode="bottom" border-radius="24" height="70%">
|
||||
<view class="gallery-panel">
|
||||
<view class="gallery-header">
|
||||
<text class="gallery-title">从图库选择</text>
|
||||
<text class="gallery-close" @click="close">关闭</text>
|
||||
</view>
|
||||
<scroll-view scroll-y class="gallery-scroll" @scrolltolower="loadMore">
|
||||
<view v-if="loading && !items.length" class="gallery-loading">加载中...</view>
|
||||
<view v-else-if="!items.length" class="gallery-empty">图库暂无图片</view>
|
||||
<view v-else class="gallery-grid">
|
||||
<view
|
||||
v-for="item in items"
|
||||
:key="item.id"
|
||||
class="gallery-item"
|
||||
@click="selectItem(item)"
|
||||
>
|
||||
<image :src="item.url" class="gallery-thumb" mode="aspectFill" />
|
||||
<text class="gallery-size">{{ item.file_size_text || '' }}</text>
|
||||
<text v-if="item.created_at" class="gallery-time">{{ item.created_at }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="loadingMore" class="gallery-loading">加载更多...</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { req } from '@/common/js/index.js'
|
||||
import { unwrapClinicRes } from '@/api/clinicAdmin.js'
|
||||
import { cancelGalleryPick, resolveGalleryPick } from '@/subPackages/sub_salesperson/common/imageGalleryBridge.js'
|
||||
|
||||
const SALESPERSON_PREFIX = '/newApi/salesperson-file-gallery/'
|
||||
const PLATFORM_PREFIX = '/newApi/platform-admin-file-gallery/'
|
||||
|
||||
function getGalleryListApi(params) {
|
||||
const mode = uni.getStorageSync('loginMode')
|
||||
const prefix = mode === 'platform_admin' ? PLATFORM_PREFIX : SALESPERSON_PREFIX
|
||||
const headerKey = mode === 'platform_admin' ? '_platformAdmin' : '_salesperson'
|
||||
return req.request({
|
||||
url: `${prefix}list`,
|
||||
method: 'GET',
|
||||
data: params,
|
||||
header: { [headerKey]: '1' },
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'ImageGalleryPicker',
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
loading: false,
|
||||
loadingMore: false,
|
||||
items: [],
|
||||
page: 1,
|
||||
pageSize: 24,
|
||||
total: 0,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
uni.$on('salesperson:open-gallery', this.open)
|
||||
},
|
||||
beforeDestroy() {
|
||||
uni.$off('salesperson:open-gallery', this.open)
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.visible = true
|
||||
this.page = 1
|
||||
this.items = []
|
||||
this.fetchList(true)
|
||||
},
|
||||
close() {
|
||||
this.visible = false
|
||||
cancelGalleryPick()
|
||||
},
|
||||
async fetchList(reset) {
|
||||
if (reset) {
|
||||
this.loading = true
|
||||
} else {
|
||||
this.loadingMore = true
|
||||
}
|
||||
try {
|
||||
const res = await getGalleryListApi({
|
||||
page: this.page,
|
||||
page_size: this.pageSize,
|
||||
pid: 0,
|
||||
type: 0,
|
||||
})
|
||||
const data = unwrapClinicRes(res) || {}
|
||||
const list = data.items || []
|
||||
this.total = data.total || 0
|
||||
this.items = reset ? list : [...this.items, ...list]
|
||||
} catch (e) {
|
||||
uni.showToast({ title: '图库加载失败', icon: 'none' })
|
||||
} finally {
|
||||
this.loading = false
|
||||
this.loadingMore = false
|
||||
}
|
||||
},
|
||||
loadMore() {
|
||||
if (this.loadingMore || this.items.length >= this.total) return
|
||||
this.page += 1
|
||||
this.fetchList(false)
|
||||
},
|
||||
selectItem(item) {
|
||||
if (!item || !item.url) return
|
||||
this.visible = false
|
||||
resolveGalleryPick(item.url)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.gallery-panel {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #fff;
|
||||
}
|
||||
.gallery-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 28rpx 32rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
.gallery-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #1d2129;
|
||||
}
|
||||
.gallery-close {
|
||||
font-size: 28rpx;
|
||||
color: #86909c;
|
||||
}
|
||||
.gallery-scroll {
|
||||
flex: 1;
|
||||
height: 0;
|
||||
}
|
||||
.gallery-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 16rpx;
|
||||
padding: 24rpx;
|
||||
}
|
||||
.gallery-item {
|
||||
border-radius: 12rpx;
|
||||
overflow: hidden;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
.gallery-thumb {
|
||||
width: 100%;
|
||||
height: 200rpx;
|
||||
display: block;
|
||||
}
|
||||
.gallery-size {
|
||||
display: block;
|
||||
font-size: 22rpx;
|
||||
color: #86909c;
|
||||
text-align: center;
|
||||
padding: 8rpx 0 0;
|
||||
}
|
||||
.gallery-time {
|
||||
display: block;
|
||||
font-size: 20rpx;
|
||||
color: #86909c;
|
||||
text-align: center;
|
||||
padding: 4rpx 0 12rpx;
|
||||
}
|
||||
.gallery-loading,
|
||||
.gallery-empty {
|
||||
text-align: center;
|
||||
padding: 80rpx 0;
|
||||
color: #86909c;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -10,6 +10,7 @@
|
||||
<view class="clinic-body" :style="bodyStyle">
|
||||
<slot />
|
||||
</view>
|
||||
<image-gallery-picker />
|
||||
<u-tabbar
|
||||
v-if="showTabbar"
|
||||
:value="tabIndex"
|
||||
@@ -22,10 +23,12 @@
|
||||
|
||||
<script>
|
||||
import businessMixin from '@/subPackages/sub_salesperson/common/businessMixin.js';
|
||||
import ImageGalleryPicker from '@/subPackages/sub_salesperson/components/ImageGalleryPicker.vue';
|
||||
|
||||
export default {
|
||||
name: 'BusinessPageLayout',
|
||||
mixins: [businessMixin],
|
||||
components: { ImageGalleryPicker },
|
||||
props: {
|
||||
title: { type: String, default: '' },
|
||||
showBack: { type: Boolean, default: false },
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
<text class="upload-txt">上传头像</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="gallery-link" @click="pickFromGallery('avatar')">从图库选择</text>
|
||||
</u-form-item>
|
||||
<u-form-item label="职称" right-icon="arrow-right">
|
||||
<u-input :value="selectedTitleLabel" type="select" @click="showTitle = true" placeholder="请选择" />
|
||||
@@ -96,6 +97,7 @@
|
||||
<text class="upload-txt">上传签名图</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="gallery-link" @click="pickFromGallery('sign_image')">从图库选择</text>
|
||||
</view>
|
||||
</u-form-item>
|
||||
<u-form-item label="擅长" :required="true">
|
||||
@@ -104,10 +106,14 @@
|
||||
<u-form-item label="简介" :required="true">
|
||||
<u-input v-model="form.intro" type="textarea" placeholder="请输入简介" />
|
||||
</u-form-item>
|
||||
<u-form-item label="挂号费">
|
||||
<u-input v-model="form.register_price" type="digit" placeholder="默认0,自动开启挂号" />
|
||||
</u-form-item>
|
||||
</view>
|
||||
|
||||
<view v-show="currentStep === 1" class="step-content">
|
||||
<view class="section-title">证照资料</view>
|
||||
<view class="upload-grid">
|
||||
<view v-for="item in imageFields" :key="item.key" class="upload-group">
|
||||
<view class="upload-label"><text v-if="item.required" class="required">*</text>{{ item.label }}</view>
|
||||
<view class="img-row">
|
||||
@@ -117,6 +123,8 @@
|
||||
<text class="upload-txt">上传</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="gallery-link" @click="pickFromGallery(item.key)">从图库选择</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -128,6 +136,7 @@
|
||||
<view class="summary-row"><text class="k">关联门店</text><text class="v">{{ selectedStoreNames || '-' }}</text></view>
|
||||
<view class="summary-row"><text class="k">科室/职称</text><text class="v">{{ selectedDepartLabel }} / {{ selectedTitleLabel }}</text></view>
|
||||
<view class="summary-row"><text class="k">身份</text><text class="v">{{ selectedTypeLabel }}</text></view>
|
||||
<view class="summary-row"><text class="k">挂号费</text><text class="v">{{ form.register_price != null && form.register_price !== '' ? form.register_price : '0' }}</text></view>
|
||||
<view class="summary-row"><text class="k">签名</text><text class="v">{{ form.sign_image ? '已填写' : '-' }}</text></view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -164,6 +173,7 @@ import businessMixin from '@/subPackages/sub_salesperson/common/businessMixin.js
|
||||
import { getInputBusinessContext } from '@/subPackages/sub_salesperson/common/context.js'
|
||||
import {
|
||||
pickAndUploadImage,
|
||||
openGalleryPick,
|
||||
uploadSignCanvasBase64,
|
||||
uploadSignCanvasTempPath,
|
||||
createDefaultDoctorInputForm,
|
||||
@@ -347,6 +357,9 @@ export default {
|
||||
uploadField(field) {
|
||||
pickAndUploadImage().then((url) => { this.form[field] = url }).catch(() => {})
|
||||
},
|
||||
pickFromGallery(field) {
|
||||
openGalleryPick().then((url) => { this.form[field] = url }).catch(() => {})
|
||||
},
|
||||
onSignCanvasSave(payload) {
|
||||
this.showSignPad = false
|
||||
const base64 = typeof payload === 'string' ? payload : (payload && payload.base64)
|
||||
@@ -473,6 +486,7 @@ export default {
|
||||
if (!this.validate()) return
|
||||
const payload = {
|
||||
...this.form,
|
||||
register_price: Number(this.form.register_price) || 0,
|
||||
store_input_ids: this.selectedStoreInputIds,
|
||||
store_ids: this.selectedStoreIds,
|
||||
store_id: this.selectedStoreInputIds[0] || this.selectedStoreIds[0] || 0,
|
||||
@@ -544,6 +558,17 @@ export default {
|
||||
gap: 12rpx;
|
||||
}
|
||||
.sign-tip { font-size: 26rpx; color: #6acdbb; }
|
||||
.upload-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 24rpx;
|
||||
padding-bottom: 20rpx;
|
||||
}
|
||||
.upload-grid .upload-group {
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
border-bottom: none;
|
||||
}
|
||||
.img-row, .img-list { display: flex; flex-wrap: wrap; gap: 24rpx; }
|
||||
.thumb { width: 160rpx; height: 160rpx; border-radius: 12rpx; }
|
||||
.upload-group { margin-bottom: 30rpx; padding-bottom: 20rpx; border-bottom: 1rpx solid #f5f5f5; }
|
||||
@@ -561,6 +586,12 @@ export default {
|
||||
border: 2rpx dashed #dcdfe6;
|
||||
}
|
||||
.upload-txt { font-size: 24rpx; color: #999; margin-top: 12rpx; }
|
||||
.gallery-link {
|
||||
display: inline-block;
|
||||
margin-top: 12rpx;
|
||||
font-size: 24rpx;
|
||||
color: #6acdbb;
|
||||
}
|
||||
.summary-card { background: #f7f8fa; border-radius: 12rpx; padding: 24rpx; margin-bottom: 40rpx; }
|
||||
.summary-row { display: flex; padding: 12rpx 0; font-size: 28rpx; }
|
||||
.summary-row .k { width: 180rpx; color: #86909c; flex-shrink: 0; }
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
<text class="upload-txt">上传公章</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="gallery-link" @click="pickFromGallery('see_rate')">从图库选择</text>
|
||||
</view>
|
||||
|
||||
<view class="upload-group">
|
||||
@@ -113,6 +114,7 @@
|
||||
<u-icon name="plus" size="40" color="#999"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
<text class="gallery-link" @click="pickCarouselFromGallery">从图库选择</text>
|
||||
</view>
|
||||
|
||||
<view class="upload-group">
|
||||
@@ -196,7 +198,7 @@ import RegionAddressPicker from '@/subPackages/sub_salesperson/components/Region
|
||||
import PromoterPicker from '@/subPackages/sub_salesperson/components/PromoterPicker.vue'
|
||||
import businessMixin from '@/subPackages/sub_salesperson/common/businessMixin.js'
|
||||
import { getInputBusinessContext } from '@/subPackages/sub_salesperson/common/context.js'
|
||||
import { pickAndUploadImage, createDefaultStoreInputForm } from '@/subPackages/sub_salesperson/common/inputFormHelpers.js'
|
||||
import { pickAndUploadImage, openGalleryPick, createDefaultStoreInputForm } from '@/subPackages/sub_salesperson/common/inputFormHelpers.js'
|
||||
import { getDraft, saveDraft, removeDraft } from '@/subPackages/sub_salesperson/common/inputDraftStorage.js'
|
||||
import { serializeStoreDraft, applyStoreDraft } from '@/subPackages/sub_salesperson/common/inputDraftHelpers.js'
|
||||
import { goDoctorInputFromStore } from '@/subPackages/sub_salesperson/common/inputNavigation.js'
|
||||
@@ -360,6 +362,12 @@ export default {
|
||||
uploadField(field) {
|
||||
pickAndUploadImage().then(url => { this.form[field] = url }).catch(() => {})
|
||||
},
|
||||
pickFromGallery(field) {
|
||||
openGalleryPick().then(url => { this.form[field] = url }).catch(() => {})
|
||||
},
|
||||
pickCarouselFromGallery() {
|
||||
openGalleryPick().then(url => { this.form.url.push(url) }).catch(() => {})
|
||||
},
|
||||
uploadCarousel() {
|
||||
pickAndUploadImage().then(url => { this.form.url.push(url) }).catch(() => {})
|
||||
},
|
||||
@@ -516,21 +524,21 @@ export default {
|
||||
.time-box { flex: 1; text-align: center; background: #f5f7fa; padding: 12rpx 0; border-radius: 8rpx; font-size: 28rpx; color: #606266; }
|
||||
.time-sep { margin: 0 20rpx; color: #999; }
|
||||
|
||||
.clinic-type-cards { display: flex; gap: 20rpx; width: 100%; }
|
||||
.clinic-type-cards { display: flex; gap: 12rpx; width: 100%; }
|
||||
.clinic-type-card {
|
||||
flex: 1;
|
||||
padding: 24rpx 16rpx;
|
||||
padding: 12rpx 10rpx;
|
||||
text-align: center;
|
||||
background: #f5f7fa;
|
||||
border: 2rpx solid #e4e7ed;
|
||||
border-radius: 12rpx;
|
||||
border-radius: 8rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.clinic-type-card.active {
|
||||
background: rgba(106, 205, 187, 0.08);
|
||||
border-color: #6acdbb;
|
||||
}
|
||||
.clinic-type-label { font-size: 28rpx; color: #303133; }
|
||||
.clinic-type-label { font-size: 24rpx; color: #303133; }
|
||||
.clinic-type-card.active .clinic-type-label { color: #6acdbb; font-weight: 600; }
|
||||
.switch-row {
|
||||
display: flex;
|
||||
@@ -550,6 +558,12 @@ export default {
|
||||
.thumb { width: 160rpx; height: 160rpx; border-radius: 12rpx; box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.05); }
|
||||
.upload-btn { width: 160rpx; height: 160rpx; background: #f4f5f7; border-radius: 12rpx; display: flex; flex-direction: column; align-items: center; justify-content: center; border: 2rpx dashed #dcdfe6; }
|
||||
.upload-txt { font-size: 24rpx; color: #999; margin-top: 12rpx; }
|
||||
.gallery-link {
|
||||
display: inline-block;
|
||||
margin-top: 12rpx;
|
||||
font-size: 24rpx;
|
||||
color: #6acdbb;
|
||||
}
|
||||
.contract-btn { width: 100%; height: 100rpx; flex-direction: row; gap: 12rpx; background: rgba(106, 205, 187, 0.05); border-color: #6acdbb; }
|
||||
|
||||
/* 底部操作区 */
|
||||
|
||||
Reference in New Issue
Block a user