|
@@ -0,0 +1,449 @@
|
|
|
+<template>
|
|
|
+ <div>
|
|
|
+ <!-- 使用封装的导航栏组件 -->
|
|
|
+ <NavBar title="收货地址" @back="handleBack" />
|
|
|
+
|
|
|
+ <!-- 主容器 -->
|
|
|
+ <div class="address-container">
|
|
|
+ <!-- 顶部插画卡片 -->
|
|
|
+ <div class="header-card">
|
|
|
+ <div class="card-content">
|
|
|
+ <div class="text-section">
|
|
|
+ <h3>收货地址</h3>
|
|
|
+ </div>
|
|
|
+ <div class="illustration">
|
|
|
+ <img src="@/assets/shouhuo.png" alt="收货地址">
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 地址信息表单 -->
|
|
|
+ <div class="form-card">
|
|
|
+ <h4 class="form-title">填写收货信息</h4>
|
|
|
+
|
|
|
+ <div class="form-group">
|
|
|
+ <label class="form-label">收货姓名:</label>
|
|
|
+ <input
|
|
|
+ type="text"
|
|
|
+ v-model="addressForm.name"
|
|
|
+ class="form-input"
|
|
|
+ placeholder="请输入收货人姓名"
|
|
|
+ maxlength="20"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="form-group">
|
|
|
+ <label class="form-label">收货电话:</label>
|
|
|
+ <input
|
|
|
+ type="tel"
|
|
|
+ v-model="addressForm.phone"
|
|
|
+ class="form-input"
|
|
|
+ placeholder="请输入收货人电话"
|
|
|
+ maxlength="11"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="form-group">
|
|
|
+ <label class="form-label">收货地址:</label>
|
|
|
+ <textarea
|
|
|
+ v-model="addressForm.address"
|
|
|
+ class="form-textarea"
|
|
|
+ placeholder="请输入收货人地址"
|
|
|
+ rows="3"
|
|
|
+ maxlength="200"
|
|
|
+ ></textarea>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 保存按钮 -->
|
|
|
+ <div class="button-wrapper">
|
|
|
+ <button
|
|
|
+ class="save-btn"
|
|
|
+ @click="saveAddress"
|
|
|
+ :disabled="!isFormValid"
|
|
|
+ >
|
|
|
+ 保存地址
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- Toast 提示 -->
|
|
|
+ <Toast ref="toast" />
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import Toast from '@/components/Toast.vue';
|
|
|
+import NavBar from '@/components/NavBar.vue';
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'ShdizhiPage',
|
|
|
+ components: {
|
|
|
+ Toast,
|
|
|
+ NavBar
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ addressForm: {
|
|
|
+ name: '',
|
|
|
+ phone: '',
|
|
|
+ address: ''
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ // 表单验证
|
|
|
+ isFormValid() {
|
|
|
+ return this.addressForm.name.trim() &&
|
|
|
+ this.addressForm.phone.trim() &&
|
|
|
+ this.addressForm.address.trim() &&
|
|
|
+ this.isValidPhone(this.addressForm.phone);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ this.loadSavedAddress();
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ // 自定义返回处理
|
|
|
+ handleBack() {
|
|
|
+ // 可以在这里添加自定义逻辑,比如询问是否保存草稿
|
|
|
+ if (this.hasUnsavedChanges()) {
|
|
|
+ this.$refs.toast.show('检测到未保存的更改', 'warning');
|
|
|
+ // 可以显示确认对话框
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.$router.back();
|
|
|
+ },
|
|
|
+
|
|
|
+ // 检查是否有未保存的更改
|
|
|
+ hasUnsavedChanges() {
|
|
|
+ const current = this.addressForm;
|
|
|
+ const saved = localStorage.getItem('userAddress');
|
|
|
+
|
|
|
+ if (!saved && (current.name || current.phone || current.address)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (saved) {
|
|
|
+ const savedData = JSON.parse(saved);
|
|
|
+ return current.name !== savedData.name ||
|
|
|
+ current.phone !== savedData.phone ||
|
|
|
+ current.address !== savedData.address;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ },
|
|
|
+
|
|
|
+ // 加载已保存的地址
|
|
|
+ async loadSavedAddress() {
|
|
|
+ try {
|
|
|
+ const savedAddress = localStorage.getItem('userAddress');
|
|
|
+ if (savedAddress) {
|
|
|
+ this.addressForm = JSON.parse(savedAddress);
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('加载地址失败:', error);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 验证手机号
|
|
|
+ isValidPhone(phone) {
|
|
|
+ const phoneRegex = /^1[3-9]\d{9}$/;
|
|
|
+ return phoneRegex.test(phone);
|
|
|
+ },
|
|
|
+
|
|
|
+ // 保存地址
|
|
|
+ async saveAddress() {
|
|
|
+ if (!this.isFormValid) {
|
|
|
+ this.$refs.toast.show('请填写完整的收货信息', 'error');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!this.isValidPhone(this.addressForm.phone)) {
|
|
|
+ this.$refs.toast.show('请输入正确的手机号码', 'error');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ localStorage.setItem('userAddress', JSON.stringify(this.addressForm));
|
|
|
+ this.$refs.toast.show('地址保存成功!', 'success');
|
|
|
+
|
|
|
+ setTimeout(() => {
|
|
|
+ this.$router.back();
|
|
|
+ }, 1500);
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ console.error('保存地址失败:', error);
|
|
|
+ this.$refs.toast.show('保存失败,请重试', 'error');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+/* 主容器 */
|
|
|
+.address-container {
|
|
|
+ min-height: calc(100vh - 44px);
|
|
|
+ background: linear-gradient(135deg, #c94545 0%, #b43a39 100%);
|
|
|
+ padding: 20px;
|
|
|
+ padding-bottom: 100px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 其他样式保持不变... */
|
|
|
+.header-card {
|
|
|
+ background: #ffc5b9;
|
|
|
+ border-radius: 16px;
|
|
|
+ padding: 15px 10px;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
|
|
+ position: relative;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.card-content {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+
|
|
|
+.text-section h3 {
|
|
|
+ font-size: 20px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #d91d42;
|
|
|
+ margin: 0;
|
|
|
+}
|
|
|
+
|
|
|
+/* 插画样式 */
|
|
|
+.illustration {
|
|
|
+ position: relative;
|
|
|
+ width: 100px;
|
|
|
+ height: 100px;
|
|
|
+ img{
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.person {
|
|
|
+ position: relative;
|
|
|
+ z-index: 2;
|
|
|
+}
|
|
|
+
|
|
|
+.head {
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+ background: #ffd700;
|
|
|
+ border-radius: 50%;
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 50%;
|
|
|
+ transform: translateX(-50%);
|
|
|
+}
|
|
|
+
|
|
|
+.body {
|
|
|
+ width: 30px;
|
|
|
+ height: 40px;
|
|
|
+ background: #8b5cf6;
|
|
|
+ border-radius: 15px 15px 8px 8px;
|
|
|
+ position: absolute;
|
|
|
+ top: 20px;
|
|
|
+ left: 50%;
|
|
|
+ transform: translateX(-50%);
|
|
|
+}
|
|
|
+
|
|
|
+.gift-box {
|
|
|
+ position: absolute;
|
|
|
+ top: 15px;
|
|
|
+ right: -10px;
|
|
|
+}
|
|
|
+
|
|
|
+.box-body {
|
|
|
+ width: 20px;
|
|
|
+ height: 15px;
|
|
|
+ background: #ffd700;
|
|
|
+ border-radius: 2px;
|
|
|
+}
|
|
|
+
|
|
|
+.ribbon {
|
|
|
+ width: 20px;
|
|
|
+ height: 3px;
|
|
|
+ background: #ff6b6b;
|
|
|
+ position: absolute;
|
|
|
+ top: 6px;
|
|
|
+ left: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.bow {
|
|
|
+ width: 8px;
|
|
|
+ height: 6px;
|
|
|
+ background: #ff6b6b;
|
|
|
+ border-radius: 4px 4px 0 0;
|
|
|
+ position: absolute;
|
|
|
+ top: 3px;
|
|
|
+ left: 6px;
|
|
|
+}
|
|
|
+
|
|
|
+.bow::before,
|
|
|
+.bow::after {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ width: 4px;
|
|
|
+ height: 4px;
|
|
|
+ background: #ff6b6b;
|
|
|
+ border-radius: 50%;
|
|
|
+ top: -2px;
|
|
|
+}
|
|
|
+
|
|
|
+.bow::before {
|
|
|
+ left: -2px;
|
|
|
+}
|
|
|
+
|
|
|
+.bow::after {
|
|
|
+ right: -2px;
|
|
|
+}
|
|
|
+
|
|
|
+.shadow {
|
|
|
+ position: absolute;
|
|
|
+ bottom: 0;
|
|
|
+ left: 50%;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ width: 40px;
|
|
|
+ height: 8px;
|
|
|
+ background: rgba(0,0,0,0.1);
|
|
|
+ border-radius: 50%;
|
|
|
+ z-index: 1;
|
|
|
+}
|
|
|
+
|
|
|
+/* 表单卡片 */
|
|
|
+.form-card {
|
|
|
+ background: white;
|
|
|
+ border-radius: 16px;
|
|
|
+ padding: 25px 20px;
|
|
|
+ box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
|
|
+}
|
|
|
+
|
|
|
+.form-title {
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #333;
|
|
|
+ margin: 0 0 25px 0;
|
|
|
+}
|
|
|
+
|
|
|
+.form-group {
|
|
|
+ margin-bottom: 20px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+
|
|
|
+.form-label {
|
|
|
+ display: block;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #333;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ width: 100px;
|
|
|
+ white-space: nowrap;
|
|
|
+}
|
|
|
+
|
|
|
+.form-input,
|
|
|
+.form-textarea {
|
|
|
+ width: 100%;
|
|
|
+ padding: 12px 15px;
|
|
|
+ font-size: 15px;
|
|
|
+ color: #333;
|
|
|
+ box-sizing: border-box;
|
|
|
+ border:none;
|
|
|
+}
|
|
|
+
|
|
|
+.form-input:focus,
|
|
|
+.form-textarea:focus {
|
|
|
+ outline: none;
|
|
|
+ border-bottom: 1px solid #c94545;
|
|
|
+}
|
|
|
+
|
|
|
+.form-textarea {
|
|
|
+ resize: vertical;
|
|
|
+ min-height: 80px;
|
|
|
+ line-height: 1.5;
|
|
|
+}
|
|
|
+
|
|
|
+.form-input::placeholder,
|
|
|
+.form-textarea::placeholder {
|
|
|
+ color: #bbb;
|
|
|
+}
|
|
|
+
|
|
|
+/* 按钮样式 */
|
|
|
+.button-wrapper {
|
|
|
+ margin-top: 30px;
|
|
|
+}
|
|
|
+
|
|
|
+.save-btn {
|
|
|
+ width: 100%;
|
|
|
+ background: #c94545;
|
|
|
+ color: white;
|
|
|
+ border: none;
|
|
|
+ border-radius: 25px;
|
|
|
+ padding: 15px 0;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 600;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+ box-shadow: 0 4px 12px rgba(201, 69, 69, 0.3);
|
|
|
+}
|
|
|
+
|
|
|
+.save-btn:hover {
|
|
|
+ background: #b43a39;
|
|
|
+ transform: translateY(-1px);
|
|
|
+ box-shadow: 0 6px 16px rgba(201, 69, 69, 0.4);
|
|
|
+}
|
|
|
+
|
|
|
+.save-btn:active {
|
|
|
+ transform: translateY(0);
|
|
|
+}
|
|
|
+
|
|
|
+.save-btn:disabled {
|
|
|
+ background: #ccc;
|
|
|
+ cursor: not-allowed;
|
|
|
+ transform: none;
|
|
|
+ box-shadow: none;
|
|
|
+}
|
|
|
+
|
|
|
+/* 响应式优化 */
|
|
|
+@media screen and (max-width: 375px) {
|
|
|
+ .address-container {
|
|
|
+ padding: 15px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .header-card {
|
|
|
+ padding: 20px 15px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .form-card {
|
|
|
+ padding: 20px 15px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .text-section h3 {
|
|
|
+ font-size: 18px;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+@media screen and (max-width: 320px) {
|
|
|
+ .form-input,
|
|
|
+ .form-textarea {
|
|
|
+ padding: 10px 12px;
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .form-label {
|
|
|
+ font-size: 15px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .save-btn {
|
|
|
+ padding: 12px 0;
|
|
|
+ font-size: 15px;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|