|
|
@@ -0,0 +1,354 @@
|
|
|
+<template>
|
|
|
+ <view class="page-container">
|
|
|
+ <view class="store-info-card">
|
|
|
+ <view class="card-header">
|
|
|
+ <uni-icons type="shop-filled" size="20" color="#3c82f8"></uni-icons>
|
|
|
+ <text class="store-name">{{ storeInfo.name }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="info-row">
|
|
|
+ <text class="info-label">店主名称:</text>
|
|
|
+ <text class="info-value">{{ storeInfo.owner }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="info-row">
|
|
|
+ <text class="info-label">联系方式:</text>
|
|
|
+ <text class="info-value">{{ storeInfo.contact }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="info-row">
|
|
|
+ <text class="info-label">门店地址:</text>
|
|
|
+ <text class="info-value">{{ storeInfo.address }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="patrol-content-card">
|
|
|
+ <view class="form-item">
|
|
|
+ <view class="form-label required">门头照片</view>
|
|
|
+ <uni-file-picker
|
|
|
+ :value="formData.storefrontPhoto"
|
|
|
+ file-mediatype="image"
|
|
|
+ mode="grid"
|
|
|
+ ref="mentou"
|
|
|
+ :limit="1"
|
|
|
+ />
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="form-item">
|
|
|
+ <view class="form-label required">陈列照片</view>
|
|
|
+ <uni-file-picker
|
|
|
+ :value="formData.displayPhoto"
|
|
|
+ file-mediatype="image"
|
|
|
+ mode="grid"
|
|
|
+ ref="chenlie"
|
|
|
+ :limit="9"
|
|
|
+ />
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="form-item">
|
|
|
+ <view class="form-label required">获取位置</view>
|
|
|
+ <view class="location-wrapper" @click="getLocation">
|
|
|
+ <text class="location-text" :class="{'placeholder': !locationInfo.address}">
|
|
|
+ {{ locationInfo.address || '获取当前位置' }}
|
|
|
+ </text>
|
|
|
+ <uni-icons v-if="!isLocating" type="location-filled" size="20" color="#3c82f8"></uni-icons>
|
|
|
+ <view v-if="isLocating" class="loading-spinner"></view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="form-item">
|
|
|
+ <view class="form-label">备注</view>
|
|
|
+ <textarea
|
|
|
+ class="remark-textarea"
|
|
|
+ v-model="formData.remarks"
|
|
|
+ placeholder="请输入备注信息"
|
|
|
+ placeholder-class="placeholder"
|
|
|
+ auto-height
|
|
|
+ />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="footer-save-button">
|
|
|
+ <button class="save-btn" @click="submitForm">提 交</button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { getRetailDetail, uploadImage,addPatrolRecord,parseLocation} from "@/api/hexiao";
|
|
|
+
|
|
|
+ export default {
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ // 假设的门店信息,从上个页面传来
|
|
|
+ storeInfo: {
|
|
|
+ id: 1,
|
|
|
+ name: '',
|
|
|
+ owner: '',
|
|
|
+ contact: '',
|
|
|
+ address: ''
|
|
|
+ },
|
|
|
+ // 表单数据
|
|
|
+ formData: {
|
|
|
+ storefrontPhoto: [], // 用于 file-picker 显示
|
|
|
+ storefrontPhotoUrl: '', // 门头照上传后的URL
|
|
|
+ displayPhoto: [], // 用于 file-picker 显示
|
|
|
+ displayPhotoUrl: '', // 陈列照上传后的URL
|
|
|
+ remarks: ''
|
|
|
+ },
|
|
|
+ // 位置信息
|
|
|
+ locationInfo: {
|
|
|
+ latitude: null,
|
|
|
+ longitude: null,
|
|
|
+ address: ''
|
|
|
+ },
|
|
|
+ isLocating: false, // 是否正在定位中
|
|
|
+ };
|
|
|
+ },
|
|
|
+ onLoad(opt){
|
|
|
+ this.storeInfo.id = opt.id;
|
|
|
+ getRetailDetail(opt.id).then(res=>{
|
|
|
+ let data = res.data;
|
|
|
+ this.storeInfo = {
|
|
|
+ id: data.id,
|
|
|
+ name: data.store_name,
|
|
|
+ owner: data.contact_name,
|
|
|
+ contact: data.contact_phone,
|
|
|
+ address: data.address,
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ // 文件选择后自动上传
|
|
|
+ async handleFileSelect(type, e) {
|
|
|
+ const tempFile = e.tempFiles[0];
|
|
|
+ try {
|
|
|
+ const imageUrl = await this.uploadImageToServer(tempFile.path);
|
|
|
+ if (type === 'storefrontPhoto') {
|
|
|
+ this.formData.storefrontPhotoUrl = imageUrl;
|
|
|
+ this.formData.storefrontPhoto = [tempFile];
|
|
|
+ } else if (type === 'displayPhoto') {
|
|
|
+ this.formData.displayPhotoUrl = imageUrl;
|
|
|
+ this.formData.displayPhoto = [tempFile];
|
|
|
+ }
|
|
|
+ uni.showToast({ title: '上传成功', icon: 'success' });
|
|
|
+ } catch (error) {
|
|
|
+ uni.showToast({ title: '上传失败', icon: 'none' });
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 删除图片
|
|
|
+ handleFileDelete(type) {
|
|
|
+ if (type === 'storefrontPhoto') {
|
|
|
+ this.formData.storefrontPhoto = [];
|
|
|
+ this.formData.storefrontPhotoUrl = '';
|
|
|
+ } else if (type === 'displayPhoto') {
|
|
|
+ this.formData.displayPhoto = [];
|
|
|
+ this.formData.displayPhotoUrl = '';
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 获取地理位置
|
|
|
+ getLocation() {
|
|
|
+ this.isLocating = true;
|
|
|
+ let self = this;
|
|
|
+ uni.getLocation({
|
|
|
+ type: 'gcj02', // 'wgs84' GPS坐标, 'gcj02' 国测局坐标
|
|
|
+ isHighAccuracy: true,
|
|
|
+ geocode: true, // 获取带有地址信息(仅App和H5支持)
|
|
|
+ success: (res) => {
|
|
|
+ console.log('当前位置信息:', res);
|
|
|
+ this.locationInfo.latitude = res.latitude;
|
|
|
+ this.locationInfo.longitude = res.longitude;
|
|
|
+
|
|
|
+ parseLocation(res.latitude, res.longitude).then(res=>{
|
|
|
+ if("Success" === res.data.message){
|
|
|
+ let address = res.data.result.address
|
|
|
+ self.locationInfo.address = address
|
|
|
+ }else{
|
|
|
+ uni.showToast({ title: '解析地址失败', icon: 'none' });
|
|
|
+ }
|
|
|
+
|
|
|
+ })
|
|
|
+ },
|
|
|
+ fail: (err) => {
|
|
|
+ uni.showToast({ title: '获取位置失败', icon: 'none' });
|
|
|
+ console.error(err);
|
|
|
+ },
|
|
|
+ complete: () => {
|
|
|
+ this.isLocating = false;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // 提交表单
|
|
|
+ async submitForm() {
|
|
|
+ if(this.$refs.chenlie.files.length === 0){
|
|
|
+ return uni.showToast({ title: '请上传门头照片', icon: 'none' });
|
|
|
+ }
|
|
|
+ if(this.$refs.mentou.files.length === 0){
|
|
|
+ return uni.showToast({ title: '请上传陈列照片', icon: 'none' });
|
|
|
+ }
|
|
|
+ const chenlieArr = await uploadImage(this.$refs.chenlie.files);
|
|
|
+ const mentouArr = await uploadImage(this.$refs.mentou.files);
|
|
|
+ // 数据校验
|
|
|
+ if(mentouArr.length === 0){
|
|
|
+ uni.showToast({ title: '门店照片上传失败,请重试', icon: 'none' });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if(chenlieArr.length === 0){
|
|
|
+ uni.showToast({ title: '陈列照片上传失败,请重试', icon: 'none' });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!this.locationInfo.address) {
|
|
|
+ return uni.showToast({ title: '请获取当前位置', icon: 'none' });
|
|
|
+ }
|
|
|
+
|
|
|
+ uni.showLoading({ title: '正在提交...' });
|
|
|
+
|
|
|
+ const finalData = {
|
|
|
+ storeId: this.storeInfo.id,
|
|
|
+ storeImg: mentouArr[0],
|
|
|
+ displayImg: chenlieArr,
|
|
|
+ latitude: this.locationInfo.latitude,
|
|
|
+ longitude: this.locationInfo.longitude,
|
|
|
+ address: this.locationInfo.address,
|
|
|
+ remark: this.formData.remarks
|
|
|
+ };
|
|
|
+
|
|
|
+ let res = await addPatrolRecord(finalData)
|
|
|
+ if(res.code == 0){
|
|
|
+ uni.showToast({ title: '提交成功', icon: 'success' });
|
|
|
+ }else{
|
|
|
+ uni.showToast({ title: '提交失败', icon: 'error' });
|
|
|
+ }
|
|
|
+ uni.hideLoading();
|
|
|
+ setTimeout(() => uni.navigateBack(), 1000);
|
|
|
+ },
|
|
|
+
|
|
|
+ // 上传图片到您的后端服务器(此方法保持不变)
|
|
|
+ uploadImageToServer(tempFilePath) {
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ uni.uploadFile({
|
|
|
+ url: 'https://您的服务器地址/api/upload', // 【重要】请替换
|
|
|
+ filePath: tempFilePath,
|
|
|
+ name: 'file',
|
|
|
+ success: (res) => {
|
|
|
+ const data = JSON.parse(res.data);
|
|
|
+ if (data.code === 0) {
|
|
|
+ resolve(data.data.url);
|
|
|
+ } else {
|
|
|
+ reject(new Error(data.msg || '上传失败'));
|
|
|
+ }
|
|
|
+ },
|
|
|
+ fail: (err) => { reject(err); }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+ .page-container {
|
|
|
+ min-height: 100vh;
|
|
|
+ background: linear-gradient(to bottom, #e4efff, #f5f6fa 40%);
|
|
|
+ padding: 30rpx;
|
|
|
+ box-sizing: border-box;
|
|
|
+ padding-bottom: 160rpx; // 为底部按钮留出空间
|
|
|
+ }
|
|
|
+
|
|
|
+ .store-info-card, .patrol-content-card {
|
|
|
+ background-color: #ffffff;
|
|
|
+ border-radius: 20rpx;
|
|
|
+ padding: 30rpx;
|
|
|
+ box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
|
|
|
+ margin-bottom: 30rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .store-info-card {
|
|
|
+ .card-header {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ .store-name { font-size: 32rpx; font-weight: bold; margin-left: 15rpx; }
|
|
|
+ }
|
|
|
+ .info-row {
|
|
|
+ margin-top: 20rpx;
|
|
|
+ font-size: 28rpx;
|
|
|
+ .info-label { color: #999; }
|
|
|
+ .info-value { color: #333; margin-left: 20rpx; }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .patrol-content-card {
|
|
|
+ padding: 10rpx 30rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .form-item {
|
|
|
+ padding: 30rpx 0;
|
|
|
+ border-bottom: 1rpx solid #f0f0f0;
|
|
|
+ &:last-child { border-bottom: none; }
|
|
|
+ }
|
|
|
+
|
|
|
+ .form-label {
|
|
|
+ display: block;
|
|
|
+ font-size: 30rpx;
|
|
|
+ color: #333;
|
|
|
+ font-weight: 500;
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+ &.required::before {
|
|
|
+ content: '*';
|
|
|
+ color: #e54d42;
|
|
|
+ margin-right: 8rpx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .location-wrapper {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ .location-text {
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #333;
|
|
|
+ flex: 1;
|
|
|
+ &.placeholder { color: #c0c4cc; }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .remark-textarea {
|
|
|
+ width: 100%;
|
|
|
+ font-size: 28rpx;
|
|
|
+ min-height: 150rpx;
|
|
|
+ }
|
|
|
+ .placeholder { color: #c0c4cc; }
|
|
|
+
|
|
|
+ .footer-save-button {
|
|
|
+ position: fixed;
|
|
|
+ left: 0;
|
|
|
+ bottom: 0;
|
|
|
+ width: 100%;
|
|
|
+ padding: 20rpx 30rpx;
|
|
|
+ background-color: #f5f6fa;
|
|
|
+ box-sizing: border-box;
|
|
|
+ padding-bottom: calc(20rpx + constant(safe-area-inset-bottom));
|
|
|
+ padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
|
|
+ }
|
|
|
+
|
|
|
+ .save-btn {
|
|
|
+ background-color: #409eff;
|
|
|
+ color: #ffffff;
|
|
|
+ border-radius: 50rpx;
|
|
|
+ font-size: 32rpx;
|
|
|
+ height: 90rpx;
|
|
|
+ line-height: 90rpx;
|
|
|
+ &::after { border: none; }
|
|
|
+ }
|
|
|
+
|
|
|
+ .loading-spinner {
|
|
|
+ width: 40rpx;
|
|
|
+ height: 40rpx;
|
|
|
+ border-radius: 50%;
|
|
|
+ border: 4rpx solid #f3f3f3;
|
|
|
+ border-top-color: #3498db;
|
|
|
+ animation: spin 1s linear infinite;
|
|
|
+ }
|
|
|
+ @keyframes spin {
|
|
|
+ to { transform: rotate(360deg); }
|
|
|
+ }
|
|
|
+</style>
|