shish 3 săptămâni în urmă
părinte
comite
4eeed7a055

+ 32 - 4
ghsApp/src/admin/ghsNotice/list.vue

@@ -47,7 +47,7 @@
             <button
               class="action-btn"
               :class="item.status == 1 ? 'offline' : 'publish'"
-              @click.stop="toggleStatus(item, index)"
+              @click.stop="openStatusToggle(item, index)"
             >
               {{ item.status == 1 ? '下架' : '发布' }}
             </button>
@@ -77,6 +77,16 @@
       :size="32"
       padding="30rpx 30rpx"
     />
+
+    <modal-module
+      :show="statusModal"
+      @cancel="statusModal = false"
+      @click="statusModalClick"
+      :content="statusModalContent"
+      color="#333"
+      :size="32"
+      padding="30rpx 30rpx"
+    />
   </view>
 </template>
 
@@ -111,6 +121,9 @@ export default {
       searchText: '',
       appliedKeyword: '',
       delModal: false,
+      statusModal: false,
+      statusModalContent: '',
+      pendingStatus: null,
       operateData: {},
       operateIndex: null,
       searchTimer: null,
@@ -226,9 +239,24 @@ export default {
       const pad = n => String(n).padStart(2, '0')
       return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
     },
-    toggleStatus(item, index) {
-      const status = item.status == 1 ? 0 : 1
-      updateGhsNoticeStatus({ id: item.id, status }).then(res => {
+    // 打开发布/下架确认弹框
+    openStatusToggle(item, index) {
+      this.operateData = item
+      this.operateIndex = index
+      this.pendingStatus = item.status == 1 ? 0 : 1
+      this.statusModalContent = this.pendingStatus === 1 ? '确定发布该公告吗?' : '确定下架该公告吗?'
+      this.statusModal = true
+    },
+    // 确认发布/下架
+    statusModalClick(e) {
+      if (e.index === 0) {
+        this.statusModal = false
+        return
+      }
+      const status = this.pendingStatus
+      const index = this.operateIndex
+      updateGhsNoticeStatus({ id: this.operateData.id, status }).then(res => {
+        this.statusModal = false
         if (res.code == 1) {
           this.$set(this.list.data[index], 'status', status)
           if (status === 1) {

+ 60 - 59
hdApp/src/admin/shopNotice/add.vue

@@ -59,6 +59,7 @@
                 <text class="checkbox-text">{{ item.label }}</text>
               </label>
             </checkbox-group>
+            <text class="form-tip">同个位置有多个公告,每5秒轮播一条</text>
           </view>
         </view>
 
@@ -277,24 +278,24 @@ export default {
 <style lang="scss" scoped>
 .app-content {
   min-height: 100vh;
-  padding: 24rpx 24rpx 0;
+  padding: 24upx 24upx 0;
   background: #f3f4f6;
   box-sizing: border-box;
 }
 
 .form-card {
   background: #fff;
-  border-radius: 20rpx;
-  padding: 32rpx 28rpx;
-  margin-bottom: 24rpx;
-  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
+  border-radius: 20upx;
+  padding: 32upx 28upx;
+  margin-bottom: 24upx;
+  box-shadow: 0 2upx 12upx rgba(0, 0, 0, 0.04);
 }
 
 .card-title {
-  font-size: 34rpx;
+  font-size: 34upx;
   font-weight: 600;
   color: #1a1a1a;
-  margin-bottom: 28rpx;
+  margin-bottom: 28upx;
 
   &.no-margin {
     margin-bottom: 0;
@@ -304,7 +305,7 @@ export default {
 .form-item {
   display: flex;
   align-items: center;
-  margin-bottom: 28rpx;
+  margin-bottom: 28upx;
 
 .form-item.align-top {
   align-items: flex-start;
@@ -317,19 +318,19 @@ export default {
 
 .form-label {
   flex-shrink: 0;
-  width: 168rpx;
-  font-size: 28rpx;
+  width: 168upx;
+  font-size: 28upx;
   color: #333;
   font-weight: 500;
 }
 
 .form-item:not(.align-top) .form-label {
-  line-height: 80rpx;
+  line-height: 80upx;
 }
 
 .form-item.align-top .form-label {
   line-height: 1.4;
-  padding-top: 4rpx;
+  padding-top: 4upx;
 }
 
 .form-field {
@@ -339,30 +340,30 @@ export default {
 
 .input-box {
   background: #f5f6f8;
-  border-radius: 12rpx;
-  padding: 0 24rpx;
+  border-radius: 12upx;
+  padding: 0 24upx;
   position: relative;
 
   &.textarea-box {
-    padding-top: 12rpx;
-    padding-bottom: 12rpx;
+    padding-top: 12upx;
+    padding-bottom: 12upx;
   }
 }
 
 .form-input {
   width: 100%;
-  height: 80rpx;
-  font-size: 28rpx;
+  height: 80upx;
+  font-size: 28upx;
   color: #333;
-  padding-right: 80rpx;
+  padding-right: 80upx;
   box-sizing: border-box;
 }
 
 .form-textarea {
   width: 100%;
-  min-height: 80rpx;
-  padding: 8rpx 80rpx 8rpx 0;
-  font-size: 28rpx;
+  min-height: 80upx;
+  padding: 8upx 80upx 8upx 0;
+  font-size: 28upx;
   color: #333;
   line-height: 1.5;
   box-sizing: border-box;
@@ -375,13 +376,13 @@ export default {
 .form-label.required::before {
   content: '*';
   color: #e64340;
-  margin-right: 6rpx;
+  margin-right: 6upx;
 }
 
 .char-count {
   position: absolute;
-  right: 20rpx;
-  font-size: 22rpx;
+  right: 20upx;
+  font-size: 22upx;
   color: #999;
   line-height: 1;
 }
@@ -392,21 +393,21 @@ export default {
 }
 
 .textarea-box .char-count {
-  bottom: 12rpx;
+  bottom: 12upx;
 }
 
 .form-tip {
   display: block;
-  font-size: 22rpx;
-  color: #999;
-  padding: 10rpx 16rpx;
+  font-size: 26upx;
+  color: #898dbe;
+  padding: 10upx 0upx;
   line-height: 1.4;
 }
 
 .position-grid {
   display: flex;
   flex-wrap: wrap;
-  gap: 24rpx 0;
+  gap: 24upx 0;
 }
 
 .position-item {
@@ -414,33 +415,33 @@ export default {
   display: flex;
   align-items: center;
   box-sizing: border-box;
-  padding-right: 12rpx;
+  padding-right: 12upx;
 }
 
 .checkbox-text {
-  font-size: 28rpx;
+  font-size: 28upx;
   color: #333;
-  margin-left: 8rpx;
+  margin-left: 8upx;
 }
 
 .content-card {
-  padding-bottom: 24rpx;
+  padding-bottom: 24upx;
 }
 
 .content-header {
   display: flex;
   align-items: center;
   justify-content: space-between;
-  margin-bottom: 20rpx;
+  margin-bottom: 20upx;
 }
 
 .content-tip {
-  font-size: 24rpx;
+  font-size: 24upx;
   color: #999;
 }
 
 .editor-wrap {
-  margin: 0 -28rpx;
+  margin: 0 -28upx;
 
   ::v-deep .rich-media-editor {
     border: none;
@@ -449,23 +450,23 @@ export default {
   }
 
   ::v-deep .content-area {
-    min-height: 280rpx;
-    padding: 0 28rpx 40rpx;
+    min-height: 280upx;
+    padding: 0 28upx 40upx;
     background: #fff;
   }
 
   ::v-deep .empty-placeholder {
-    min-height: 280rpx;
+    min-height: 280upx;
     margin: 0;
     background: #f5f6f8;
-    border: 2rpx dashed #d9dce3;
-    border-radius: 16rpx;
+    border: 2upx dashed #d9dce3;
+    border-radius: 16upx;
     flex-direction: column;
-    gap: 16rpx;
+    gap: 16upx;
 
     &::before {
       content: '+';
-      font-size: 56rpx;
+      font-size: 56upx;
       color: #07a94b;
       font-weight: 300;
       line-height: 1;
@@ -474,23 +475,23 @@ export default {
 
   ::v-deep .empty-text {
     color: #999;
-    font-size: 26rpx;
+    font-size: 26upx;
   }
 
   ::v-deep .bottom-toolbar {
     height: auto;
-    padding: 24rpx 28rpx 32rpx;
+    padding: 24upx 28upx 32upx;
     border-top: none;
     background: #fff;
-    gap: 20rpx;
+    gap: 20upx;
   }
 
   ::v-deep .toolbar-btn {
     flex: 1;
-    padding: 24rpx 0;
+    padding: 24upx 0;
     background: #eef8f1;
-    border-radius: 16rpx;
-    gap: 12rpx;
+    border-radius: 16upx;
+    gap: 12upx;
 
     &:active {
       background: #dff0e4;
@@ -499,13 +500,13 @@ export default {
 
   ::v-deep .toolbar-btn .btn-text {
     color: #07a94b;
-    font-size: 26rpx;
+    font-size: 26upx;
     font-weight: 500;
   }
 }
 
 .footer-placeholder {
-  height: calc(140rpx + env(safe-area-inset-bottom));
+  height: calc(140upx + env(safe-area-inset-bottom));
 }
 
 .footer-bar {
@@ -515,24 +516,24 @@ export default {
   bottom: 0;
   z-index: 999;
   display: flex;
-  padding: 20rpx 30rpx calc(20rpx + env(safe-area-inset-bottom));
+  padding: 20upx 30upx calc(20upx + env(safe-area-inset-bottom));
   background: #fff;
-  box-shadow: 0 -2rpx 16rpx rgba(0, 0, 0, 0.06);
+  box-shadow: 0 -2upx 16upx rgba(0, 0, 0, 0.06);
   box-sizing: border-box;
 }
 
 .footer-btn {
   flex: 1;
-  height: 88rpx;
-  line-height: 88rpx;
+  height: 88upx;
+  line-height: 88upx;
   margin: 0;
   padding: 0;
-  font-size: 32rpx;
-  border-radius: 44rpx;
+  font-size: 32upx;
+  border-radius: 44upx;
   border: none;
 
   &:first-child {
-    margin-right: 24rpx;
+    margin-right: 24upx;
   }
 
   &::after {

+ 90 - 62
hdApp/src/admin/shopNotice/list.vue

@@ -47,7 +47,7 @@
             <button
               class="action-btn"
               :class="item.status == 1 ? 'offline' : 'publish'"
-              @click.stop="toggleStatus(item, index)"
+              @click.stop="openStatusToggle(item, index)"
             >
               {{ item.status == 1 ? '下架' : '发布' }}
             </button>
@@ -77,6 +77,16 @@
       :size="32"
       padding="30rpx 30rpx"
     />
+
+    <modal-module
+      :show="statusModal"
+      @cancel="statusModal = false"
+      @click="statusModalClick"
+      :content="statusModalContent"
+      color="#333"
+      :size="32"
+      padding="30rpx 30rpx"
+    />
   </view>
 </template>
 
@@ -111,6 +121,9 @@ export default {
       searchText: '',
       appliedKeyword: '',
       delModal: false,
+      statusModal: false,
+      statusModalContent: '',
+      pendingStatus: null,
       operateData: {},
       operateIndex: null,
       searchTimer: null,
@@ -228,9 +241,24 @@ export default {
       const pad = n => String(n).padStart(2, '0')
       return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
     },
-    toggleStatus(item, index) {
-      const status = item.status == 1 ? 0 : 1
-      updateShopNoticeStatus({ id: item.id, status }).then(res => {
+    // 打开发布/下架确认弹框
+    openStatusToggle(item, index) {
+      this.operateData = item
+      this.operateIndex = index
+      this.pendingStatus = item.status == 1 ? 0 : 1
+      this.statusModalContent = this.pendingStatus === 1 ? '确定发布该公告吗?' : '确定下架该公告吗?'
+      this.statusModal = true
+    },
+    // 确认发布/下架
+    statusModalClick(e) {
+      if (e.index === 0) {
+        this.statusModal = false
+        return
+      }
+      const status = this.pendingStatus
+      const index = this.operateIndex
+      updateShopNoticeStatus({ id: this.operateData.id, status }).then(res => {
+        this.statusModal = false
         if (res.code == 1) {
           this.$set(this.list.data[index], 'status', status)
           if (status === 1) {
@@ -265,47 +293,47 @@ export default {
 <style lang="scss" scoped>
 .app-content {
   min-height: 100vh;
-  padding-bottom: calc(140rpx + env(safe-area-inset-bottom));
+  padding-bottom: calc(140upx + env(safe-area-inset-bottom));
   background: #f3f4f6;
 }
 
 .search-wrap {
-  padding: 24rpx 24rpx 8rpx;
+  padding: 24upx 24upx 8upx;
   background: #f3f4f6;
 
   ::v-deep .app-search-module .map-search {
-    border-radius: 20rpx;
-    box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
+    border-radius: 20upx;
+    box-shadow: 0 2upx 8upx rgba(0, 0, 0, 0.04);
   }
 }
 
 .list-wrap {
-  padding: 16rpx 24rpx 24rpx;
-  min-height: 400rpx;
+  padding: 16upx 24upx 24upx;
+  min-height: 400upx;
 }
 
 .list-loading-placeholder {
-  min-height: 400rpx;
+  min-height: 400upx;
 }
 
 .notice-card {
   background: #fff;
-  border-radius: 20rpx;
-  padding: 28rpx 28rpx 24rpx;
-  margin-bottom: 24rpx;
-  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
+  border-radius: 20upx;
+  padding: 28upx 28upx 24upx;
+  margin-bottom: 24upx;
+  box-shadow: 0 2upx 12upx rgba(0, 0, 0, 0.04);
 }
 
 .card-top {
   display: flex;
   align-items: flex-start;
   justify-content: space-between;
-  gap: 20rpx;
+  gap: 20upx;
 }
 
 .title {
   flex: 1;
-  font-size: 34rpx;
+  font-size: 34upx;
   font-weight: 600;
   color: $fontColorMain;
   line-height: 1.4;
@@ -315,10 +343,10 @@ export default {
   flex-shrink: 0;
   display: flex;
   align-items: center;
-  gap: 6rpx;
-  font-size: 24rpx;
-  padding: 8rpx 18rpx;
-  border-radius: 24rpx;
+  gap: 6upx;
+  font-size: 24upx;
+  padding: 8upx 18upx;
+  border-radius: 24upx;
   white-space: nowrap;
 
   &.active {
@@ -326,7 +354,7 @@ export default {
     background: #e8f8ee;
     .status-dot {
       color: #07a94b;
-      font-size: 18rpx;
+      font-size: 18upx;
     }
   }
 
@@ -335,7 +363,7 @@ export default {
     background: #f0f0f0;
     .status-dot {
       color: #bfbfbf;
-      font-size: 18rpx;
+      font-size: 18upx;
     }
   }
 }
@@ -343,30 +371,30 @@ export default {
 .position-row {
   display: flex;
   align-items: flex-start;
-  margin-top: 24rpx;
-  gap: 16rpx;
+  margin-top: 24upx;
+  gap: 16upx;
 }
 
 .position-label {
   flex-shrink: 0;
-  font-size: 26rpx;
+  font-size: 26upx;
   color: #8c8c8c;
-  line-height: 48rpx;
+  line-height: 48upx;
 }
 
 .position-tags {
   flex: 1;
   display: flex;
   flex-wrap: wrap;
-  gap: 12rpx;
+  gap: 12upx;
 }
 
 .tag {
-  font-size: 24rpx;
+  font-size: 24upx;
   color: #4a7fd0;
   background: #eef4fc;
-  padding: 8rpx 20rpx;
-  border-radius: 8rpx;
+  padding: 8upx 20upx;
+  border-radius: 8upx;
   line-height: 1.2;
 }
 
@@ -374,20 +402,20 @@ export default {
   display: flex;
   align-items: center;
   justify-content: space-evenly‌;
-  padding:20rpx 0;
-  border-bottom: 1rpx solid #f5f5f5;
+  padding:20upx 0;
+  border-bottom: 1upx solid #f5f5f5;
 }
 
 .meta-left {
   display: flex;
   align-items: center;
-  gap: 10rpx;
+  gap: 10upx;
 }
 
 .meta-clock {
-  width: 24rpx;
-  height: 24rpx;
-  border: 2rpx solid #bfbfbf;
+  width: 24upx;
+  height: 24upx;
+  border: 2upx solid #bfbfbf;
   border-radius: 50%;
   position: relative;
   flex-shrink: 0;
@@ -403,28 +431,28 @@ export default {
   }
 
   &::before {
-    width: 2rpx;
-    height: 7rpx;
-    margin-left: -1rpx;
-    margin-top: -7rpx;
+    width: 2upx;
+    height: 7upx;
+    margin-left: -1upx;
+    margin-top: -7upx;
   }
 
   &::after {
-    width: 2rpx;
-    height: 5rpx;
-    margin-left: -1rpx;
-    margin-top: -5rpx;
+    width: 2upx;
+    height: 5upx;
+    margin-left: -1upx;
+    margin-top: -5upx;
     transform: rotate(90deg);
   }
 }
 
 .meta-text{
-	font-size: 24rpx;
+	font-size: 24upx;
 	color: #999;
 }
 .meta-sort {
-	 margin-left:20rpx;
-  font-size: 24rpx;
+	 margin-left:20upx;
+  font-size: 24upx;
   color: #999;
 }
 
@@ -432,19 +460,19 @@ export default {
   display: flex;
   justify-content: flex-end;
   align-items: center;
-  gap: 16rpx;
-  margin-top: 24rpx;
+  gap: 16upx;
+  margin-top: 24upx;
 }
 
 .action-btn {
   margin: 0;
-  padding: 0 28rpx;
-  height: 56rpx;
-  line-height: 54rpx;
-  font-size: 26rpx;
-  border-radius: 12rpx;
+  padding: 0 28upx;
+  height: 56upx;
+  line-height: 54upx;
+  font-size: 26upx;
+  border-radius: 12upx;
   background: #fff;
-  border: 1rpx solid #e0e0e0;
+  border: 1upx solid #e0e0e0;
   color: #666;
 
   &::after {
@@ -481,21 +509,21 @@ export default {
   left: 0;
   right: 0;
   bottom: 0;
-  padding: 20rpx 30rpx calc(20rpx + env(safe-area-inset-bottom));
+  padding: 20upx 30upx calc(20upx + env(safe-area-inset-bottom));
   background: #fff;
-  box-shadow: 0 -2rpx 16rpx rgba(0, 0, 0, 0.06);
+  box-shadow: 0 -2upx 16upx rgba(0, 0, 0, 0.06);
 }
 
 .footer-btn {
   width: 100%;
-  height: 88rpx;
-  line-height: 88rpx;
+  height: 88upx;
+  line-height: 88upx;
   margin: 0;
   padding: 0;
-  font-size: 32rpx;
+  font-size: 32upx;
   color: #fff;
   background: $greenColor;
-  border-radius: 22rpx;
+  border-radius: 22upx;
   border: none;
 
   &::after {

+ 6 - 6
hdApp/src/admin/shopNotice/preview.vue

@@ -77,26 +77,26 @@ export default {
 }
 
 .page-header {
-  padding: 30rpx;
-  border-bottom: 1rpx solid #eee;
+  padding: 30upx;
+  border-bottom: 1upx solid #eee;
 }
 
 .page-title {
   display: block;
-  font-size: 36rpx;
+  font-size: 36upx;
   font-weight: bold;
   color: #333;
 }
 
 .page-summary {
   display: block;
-  margin-top: 16rpx;
-  font-size: 28rpx;
+  margin-top: 16upx;
+  font-size: 28upx;
   color: #666;
   line-height: 1.6;
 }
 
 .preview-content {
-  padding: 20rpx 0;
+  padding: 20upx 0;
 }
 </style>