| 
									
										
										
										
											2025-09-09 16:22:19 +00:00
										 |  |  |  | <!DOCTYPE html> | 
					
						
							|  |  |  |  | <html lang="zh-CN"> | 
					
						
							|  |  |  |  | <head> | 
					
						
							|  |  |  |  |     <meta charset="UTF-8"> | 
					
						
							|  |  |  |  |     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | 
					
						
							|  |  |  |  |     <title>添加商品 - 大妈集市商户端</title> | 
					
						
							|  |  |  |  |     <style> | 
					
						
							|  |  |  |  |         * { | 
					
						
							|  |  |  |  |             margin: 0; | 
					
						
							|  |  |  |  |             padding: 0; | 
					
						
							|  |  |  |  |             box-sizing: border-box; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         body { | 
					
						
							|  |  |  |  |             font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif; | 
					
						
							|  |  |  |  |             background-color: #f5f5f5; | 
					
						
							|  |  |  |  |             color: #333; | 
					
						
							|  |  |  |  |             padding: 20px; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .container { | 
					
						
							|  |  |  |  |             max-width: 800px; | 
					
						
							|  |  |  |  |             margin: 0 auto; | 
					
						
							|  |  |  |  |             background: white; | 
					
						
							|  |  |  |  |             border-radius: 8px; | 
					
						
							|  |  |  |  |             box-shadow: 0 2px 8px rgba(0,0,0,0.1); | 
					
						
							|  |  |  |  |             overflow: hidden; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .modal-header { | 
					
						
							|  |  |  |  |             padding: 20px 24px; | 
					
						
							|  |  |  |  |             border-bottom: 1px solid #f0f0f0; | 
					
						
							|  |  |  |  |             display: flex; | 
					
						
							|  |  |  |  |             justify-content: space-between; | 
					
						
							|  |  |  |  |             align-items: center; | 
					
						
							|  |  |  |  |             background: #fafafa; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .modal-title { | 
					
						
							|  |  |  |  |             font-size: 18px; | 
					
						
							|  |  |  |  |             font-weight: 600; | 
					
						
							|  |  |  |  |             color: #1a1a1a; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .close-btn { | 
					
						
							|  |  |  |  |             background: none; | 
					
						
							|  |  |  |  |             border: none; | 
					
						
							|  |  |  |  |             font-size: 20px; | 
					
						
							|  |  |  |  |             cursor: pointer; | 
					
						
							|  |  |  |  |             color: #999; | 
					
						
							|  |  |  |  |             padding: 4px; | 
					
						
							|  |  |  |  |             border-radius: 4px; | 
					
						
							|  |  |  |  |             transition: background-color 0.3s; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .close-btn:hover { | 
					
						
							|  |  |  |  |             background-color: #f0f0f0; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .modal-body { | 
					
						
							|  |  |  |  |             padding: 0; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .tabs-container { | 
					
						
							|  |  |  |  |             border-bottom: 1px solid #f0f0f0; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .tabs { | 
					
						
							|  |  |  |  |             display: flex; | 
					
						
							|  |  |  |  |             padding: 0 24px; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .tab { | 
					
						
							|  |  |  |  |             padding: 16px 20px; | 
					
						
							|  |  |  |  |             cursor: pointer; | 
					
						
							|  |  |  |  |             border-bottom: 2px solid transparent; | 
					
						
							|  |  |  |  |             font-weight: 500; | 
					
						
							|  |  |  |  |             color: #666; | 
					
						
							|  |  |  |  |             transition: all 0.3s; | 
					
						
							|  |  |  |  |             position: relative; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .tab.active { | 
					
						
							|  |  |  |  |             color: #1890ff; | 
					
						
							|  |  |  |  |             border-bottom-color: #1890ff; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .tab:hover:not(.active) { | 
					
						
							|  |  |  |  |             color: #1890ff; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .tab-content { | 
					
						
							|  |  |  |  |             padding: 24px; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .form-group { | 
					
						
							|  |  |  |  |             margin-bottom: 24px; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .form-label { | 
					
						
							|  |  |  |  |             display: block; | 
					
						
							|  |  |  |  |             margin-bottom: 8px; | 
					
						
							|  |  |  |  |             font-size: 14px; | 
					
						
							|  |  |  |  |             font-weight: 500; | 
					
						
							|  |  |  |  |             color: #333; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .required { | 
					
						
							|  |  |  |  |             color: #ff4d4f; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .form-input, .form-select, .form-textarea { | 
					
						
							|  |  |  |  |             width: 100%; | 
					
						
							|  |  |  |  |             padding: 10px 12px; | 
					
						
							|  |  |  |  |             border: 1px solid #d9d9d9; | 
					
						
							|  |  |  |  |             border-radius: 6px; | 
					
						
							|  |  |  |  |             font-size: 14px; | 
					
						
							|  |  |  |  |             transition: border-color 0.3s, box-shadow 0.3s; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .form-input:focus, .form-select:focus, .form-textarea:focus { | 
					
						
							|  |  |  |  |             outline: none; | 
					
						
							|  |  |  |  |             border-color: #1890ff; | 
					
						
							|  |  |  |  |             box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .form-textarea { | 
					
						
							|  |  |  |  |             resize: vertical; | 
					
						
							|  |  |  |  |             min-height: 80px; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .upload-area { | 
					
						
							|  |  |  |  |             border: 2px dashed #d9d9d9; | 
					
						
							|  |  |  |  |             border-radius: 6px; | 
					
						
							|  |  |  |  |             padding: 32px; | 
					
						
							|  |  |  |  |             text-align: center; | 
					
						
							|  |  |  |  |             background: #fafafa; | 
					
						
							|  |  |  |  |             transition: border-color 0.3s; | 
					
						
							|  |  |  |  |             cursor: pointer; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .upload-area:hover { | 
					
						
							|  |  |  |  |             border-color: #1890ff; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .upload-area.dragover { | 
					
						
							|  |  |  |  |             border-color: #1890ff; | 
					
						
							|  |  |  |  |             background: #f0f8ff; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .upload-icon { | 
					
						
							|  |  |  |  |             font-size: 32px; | 
					
						
							|  |  |  |  |             color: #d9d9d9; | 
					
						
							|  |  |  |  |             margin-bottom: 12px; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .upload-text { | 
					
						
							|  |  |  |  |             color: #666; | 
					
						
							|  |  |  |  |             font-size: 14px; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .upload-highlight { | 
					
						
							|  |  |  |  |             color: #1890ff; | 
					
						
							|  |  |  |  |             text-decoration: none; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .upload-hint { | 
					
						
							|  |  |  |  |             color: #999; | 
					
						
							|  |  |  |  |             font-size: 12px; | 
					
						
							|  |  |  |  |             margin-top: 8px; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .error-message { | 
					
						
							|  |  |  |  |             color: #ff4d4f; | 
					
						
							|  |  |  |  |             font-size: 12px; | 
					
						
							|  |  |  |  |             margin-top: 4px; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .image-preview { | 
					
						
							|  |  |  |  |             display: flex; | 
					
						
							|  |  |  |  |             gap: 12px; | 
					
						
							|  |  |  |  |             margin-top: 12px; | 
					
						
							|  |  |  |  |             flex-wrap: wrap; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .preview-item { | 
					
						
							|  |  |  |  |             position: relative; | 
					
						
							|  |  |  |  |             width: 80px; | 
					
						
							|  |  |  |  |             height: 80px; | 
					
						
							|  |  |  |  |             border-radius: 6px; | 
					
						
							|  |  |  |  |             overflow: hidden; | 
					
						
							|  |  |  |  |             border: 1px solid #d9d9d9; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .preview-image { | 
					
						
							|  |  |  |  |             width: 100%; | 
					
						
							|  |  |  |  |             height: 100%; | 
					
						
							|  |  |  |  |             object-fit: cover; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .preview-remove { | 
					
						
							|  |  |  |  |             position: absolute; | 
					
						
							|  |  |  |  |             top: 4px; | 
					
						
							|  |  |  |  |             right: 4px; | 
					
						
							|  |  |  |  |             background: rgba(0,0,0,0.5); | 
					
						
							|  |  |  |  |             color: white; | 
					
						
							|  |  |  |  |             border: none; | 
					
						
							|  |  |  |  |             border-radius: 50%; | 
					
						
							|  |  |  |  |             width: 20px; | 
					
						
							|  |  |  |  |             height: 20px; | 
					
						
							|  |  |  |  |             cursor: pointer; | 
					
						
							|  |  |  |  |             font-size: 12px; | 
					
						
							|  |  |  |  |             display: flex; | 
					
						
							|  |  |  |  |             align-items: center; | 
					
						
							|  |  |  |  |             justify-content: center; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .modal-footer { | 
					
						
							|  |  |  |  |             padding: 16px 24px; | 
					
						
							|  |  |  |  |             border-top: 1px solid #f0f0f0; | 
					
						
							|  |  |  |  |             background: #fafafa; | 
					
						
							|  |  |  |  |             display: flex; | 
					
						
							|  |  |  |  |             gap: 12px; | 
					
						
							|  |  |  |  |             justify-content: flex-end; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .btn { | 
					
						
							|  |  |  |  |             padding: 10px 20px; | 
					
						
							|  |  |  |  |             border: none; | 
					
						
							|  |  |  |  |             border-radius: 6px; | 
					
						
							|  |  |  |  |             font-size: 14px; | 
					
						
							|  |  |  |  |             cursor: pointer; | 
					
						
							|  |  |  |  |             transition: all 0.3s; | 
					
						
							|  |  |  |  |             font-weight: 500; | 
					
						
							|  |  |  |  |             min-width: 80px; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .btn-primary { | 
					
						
							|  |  |  |  |             background-color: #1890ff; | 
					
						
							|  |  |  |  |             color: white; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .btn-primary:hover:not(:disabled) { | 
					
						
							|  |  |  |  |             background-color: #40a9ff; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .btn-secondary { | 
					
						
							|  |  |  |  |             background-color: #f5f5f5; | 
					
						
							|  |  |  |  |             color: #666; | 
					
						
							|  |  |  |  |             border: 1px solid #d9d9d9; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .btn-secondary:hover:not(:disabled) { | 
					
						
							|  |  |  |  |             border-color: #40a9ff; | 
					
						
							|  |  |  |  |             color: #1890ff; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .btn:disabled { | 
					
						
							|  |  |  |  |             background-color: #f5f5f5; | 
					
						
							|  |  |  |  |             color: #d9d9d9; | 
					
						
							|  |  |  |  |             cursor: not-allowed; | 
					
						
							|  |  |  |  |             border-color: #f5f5f5; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .tab-pane { | 
					
						
							|  |  |  |  |             display: none; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .tab-pane.active { | 
					
						
							|  |  |  |  |             display: block; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .form-row { | 
					
						
							|  |  |  |  |             display: grid; | 
					
						
							|  |  |  |  |             grid-template-columns: 1fr 1fr; | 
					
						
							|  |  |  |  |             gap: 16px; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .checkbox-group { | 
					
						
							|  |  |  |  |             display: flex; | 
					
						
							|  |  |  |  |             align-items: center; | 
					
						
							|  |  |  |  |             gap: 8px; | 
					
						
							|  |  |  |  |             margin-top: 8px; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .checkbox { | 
					
						
							|  |  |  |  |             width: 16px; | 
					
						
							|  |  |  |  |             height: 16px; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .number-input-group { | 
					
						
							|  |  |  |  |             display: flex; | 
					
						
							|  |  |  |  |             align-items: center; | 
					
						
							|  |  |  |  |             gap: 8px; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .unit-text { | 
					
						
							|  |  |  |  |             color: #666; | 
					
						
							|  |  |  |  |             font-size: 14px; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .select-wrapper { | 
					
						
							|  |  |  |  |             position: relative; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .select-wrapper::after { | 
					
						
							|  |  |  |  |             content: ''; | 
					
						
							|  |  |  |  |             position: absolute; | 
					
						
							|  |  |  |  |             right: 12px; | 
					
						
							|  |  |  |  |             top: 50%; | 
					
						
							|  |  |  |  |             transform: translateY(-50%); | 
					
						
							|  |  |  |  |             width: 0; | 
					
						
							|  |  |  |  |             height: 0; | 
					
						
							|  |  |  |  |             border-left: 4px solid transparent; | 
					
						
							|  |  |  |  |             border-right: 4px solid transparent; | 
					
						
							|  |  |  |  |             border-top: 4px solid #999; | 
					
						
							|  |  |  |  |             pointer-events: none; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         /* 规格配置弹窗样式 */ | 
					
						
							|  |  |  |  |         .spec-modal { | 
					
						
							|  |  |  |  |             position: fixed; | 
					
						
							|  |  |  |  |             top: 0; | 
					
						
							|  |  |  |  |             left: 0; | 
					
						
							|  |  |  |  |             width: 100%; | 
					
						
							|  |  |  |  |             height: 100%; | 
					
						
							|  |  |  |  |             z-index: 1000; | 
					
						
							|  |  |  |  |             display: flex; | 
					
						
							|  |  |  |  |             align-items: center; | 
					
						
							|  |  |  |  |             justify-content: center; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-modal-overlay { | 
					
						
							|  |  |  |  |             position: absolute; | 
					
						
							|  |  |  |  |             top: 0; | 
					
						
							|  |  |  |  |             left: 0; | 
					
						
							|  |  |  |  |             width: 100%; | 
					
						
							|  |  |  |  |             height: 100%; | 
					
						
							|  |  |  |  |             background: rgba(0, 0, 0, 0.5); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-modal-content { | 
					
						
							|  |  |  |  |             position: relative; | 
					
						
							|  |  |  |  |             width: 90%; | 
					
						
							|  |  |  |  |             max-width: 1200px; | 
					
						
							|  |  |  |  |             max-height: 90vh; | 
					
						
							|  |  |  |  |             background: white; | 
					
						
							|  |  |  |  |             border-radius: 8px; | 
					
						
							|  |  |  |  |             box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); | 
					
						
							|  |  |  |  |             overflow: hidden; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-modal-header { | 
					
						
							|  |  |  |  |             padding: 20px 24px; | 
					
						
							|  |  |  |  |             border-bottom: 1px solid #f0f0f0; | 
					
						
							|  |  |  |  |             display: flex; | 
					
						
							|  |  |  |  |             justify-content: space-between; | 
					
						
							|  |  |  |  |             align-items: center; | 
					
						
							|  |  |  |  |             background: #fafafa; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-modal-title { | 
					
						
							|  |  |  |  |             font-size: 18px; | 
					
						
							|  |  |  |  |             font-weight: 600; | 
					
						
							|  |  |  |  |             color: #1a1a1a; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-modal-body { | 
					
						
							|  |  |  |  |             padding: 24px; | 
					
						
							|  |  |  |  |             max-height: calc(90vh - 120px); | 
					
						
							|  |  |  |  |             overflow-y: auto; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-combinations { | 
					
						
							|  |  |  |  |             margin-top: 24px; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-config-table { | 
					
						
							|  |  |  |  |             width: 100%; | 
					
						
							|  |  |  |  |             border-collapse: collapse; | 
					
						
							|  |  |  |  |             margin-bottom: 20px; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-config-table th, | 
					
						
							|  |  |  |  |         .spec-config-table td { | 
					
						
							|  |  |  |  |             padding: 12px 8px; | 
					
						
							|  |  |  |  |             text-align: left; | 
					
						
							|  |  |  |  |             border: 1px solid #f0f0f0; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-config-table th { | 
					
						
							|  |  |  |  |             background-color: #fafafa; | 
					
						
							|  |  |  |  |             font-weight: 600; | 
					
						
							|  |  |  |  |             color: #333; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-config-table td { | 
					
						
							|  |  |  |  |             color: #666; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-attr-input { | 
					
						
							|  |  |  |  |             width: 120px; | 
					
						
							|  |  |  |  |             padding: 6px 8px; | 
					
						
							|  |  |  |  |             border: 1px solid #d9d9d9; | 
					
						
							|  |  |  |  |             border-radius: 4px; | 
					
						
							|  |  |  |  |             font-size: 14px; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-attr-input:focus { | 
					
						
							|  |  |  |  |             outline: none; | 
					
						
							|  |  |  |  |             border-color: #1890ff; | 
					
						
							|  |  |  |  |             box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-values-container { | 
					
						
							|  |  |  |  |             display: flex; | 
					
						
							|  |  |  |  |             flex-wrap: wrap; | 
					
						
							|  |  |  |  |             gap: 8px; | 
					
						
							|  |  |  |  |             align-items: center; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-value-tag { | 
					
						
							|  |  |  |  |             display: inline-block; | 
					
						
							|  |  |  |  |             padding: 4px 8px; | 
					
						
							|  |  |  |  |             background-color: #f0f0f0; | 
					
						
							|  |  |  |  |             border-radius: 4px; | 
					
						
							|  |  |  |  |             font-size: 12px; | 
					
						
							|  |  |  |  |             position: relative; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-value-remove { | 
					
						
							|  |  |  |  |             background: none; | 
					
						
							|  |  |  |  |             border: none; | 
					
						
							|  |  |  |  |             color: #ff4d4f; | 
					
						
							|  |  |  |  |             cursor: pointer; | 
					
						
							|  |  |  |  |             font-size: 14px; | 
					
						
							|  |  |  |  |             padding: 0 4px; | 
					
						
							|  |  |  |  |             margin-left: 4px; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-value-input { | 
					
						
							|  |  |  |  |             width: 150px; | 
					
						
							|  |  |  |  |             padding: 4px 8px; | 
					
						
							|  |  |  |  |             border: 1px solid #d9d9d9; | 
					
						
							|  |  |  |  |             border-radius: 4px; | 
					
						
							|  |  |  |  |             font-size: 12px; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-value-input:focus { | 
					
						
							|  |  |  |  |             outline: none; | 
					
						
							|  |  |  |  |             border-color: #1890ff; | 
					
						
							|  |  |  |  |             box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .btn-sm { | 
					
						
							|  |  |  |  |             padding: 4px 8px; | 
					
						
							|  |  |  |  |             font-size: 12px; | 
					
						
							|  |  |  |  |             min-width: auto; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-table { | 
					
						
							|  |  |  |  |             width: 100%; | 
					
						
							|  |  |  |  |             border-collapse: collapse; | 
					
						
							|  |  |  |  |             border: 1px solid #f0f0f0; | 
					
						
							|  |  |  |  |             font-size: 14px; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-table th, | 
					
						
							|  |  |  |  |         .spec-table td { | 
					
						
							|  |  |  |  |             padding: 12px 8px; | 
					
						
							|  |  |  |  |             text-align: center; | 
					
						
							|  |  |  |  |             border: 1px solid #f0f0f0; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-table th { | 
					
						
							|  |  |  |  |             background-color: #fafafa; | 
					
						
							|  |  |  |  |             font-weight: 600; | 
					
						
							|  |  |  |  |             color: #333; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-table td { | 
					
						
							|  |  |  |  |             color: #666; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-input { | 
					
						
							|  |  |  |  |             width: 80px; | 
					
						
							|  |  |  |  |             padding: 4px 8px; | 
					
						
							|  |  |  |  |             border: 1px solid #d9d9d9; | 
					
						
							|  |  |  |  |             border-radius: 4px; | 
					
						
							|  |  |  |  |             font-size: 12px; | 
					
						
							|  |  |  |  |             text-align: center; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-input:focus { | 
					
						
							|  |  |  |  |             outline: none; | 
					
						
							|  |  |  |  |             border-color: #1890ff; | 
					
						
							|  |  |  |  |             box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .btn-danger { | 
					
						
							|  |  |  |  |             background-color: #ff4d4f; | 
					
						
							|  |  |  |  |             color: white; | 
					
						
							|  |  |  |  |             border: none; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .btn-danger:hover { | 
					
						
							|  |  |  |  |             background-color: #ff7875; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .btn-small { | 
					
						
							|  |  |  |  |             padding: 4px 8px; | 
					
						
							|  |  |  |  |             font-size: 12px; | 
					
						
							|  |  |  |  |             min-width: auto; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-modal-footer { | 
					
						
							|  |  |  |  |             padding: 16px 24px; | 
					
						
							|  |  |  |  |             border-top: 1px solid #f0f0f0; | 
					
						
							|  |  |  |  |             background: #fafafa; | 
					
						
							|  |  |  |  |             display: flex; | 
					
						
							|  |  |  |  |             gap: 12px; | 
					
						
							|  |  |  |  |             justify-content: flex-end; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         /* 只读规格表格样式 */ | 
					
						
							|  |  |  |  |         .spec-readonly-container { | 
					
						
							|  |  |  |  |             border: 1px solid #f0f0f0; | 
					
						
							|  |  |  |  |             border-radius: 6px; | 
					
						
							|  |  |  |  |             overflow: hidden; | 
					
						
							|  |  |  |  |             background: #fafafa; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-readonly-table { | 
					
						
							|  |  |  |  |             width: 100%; | 
					
						
							|  |  |  |  |             border-collapse: collapse; | 
					
						
							|  |  |  |  |             font-size: 14px; | 
					
						
							|  |  |  |  |             background: white; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-readonly-table th, | 
					
						
							|  |  |  |  |         .spec-readonly-table td { | 
					
						
							|  |  |  |  |             padding: 10px 8px; | 
					
						
							|  |  |  |  |             text-align: center; | 
					
						
							|  |  |  |  |             border: 1px solid #f0f0f0; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-readonly-table th { | 
					
						
							|  |  |  |  |             background-color: #fafafa; | 
					
						
							|  |  |  |  |             font-weight: 600; | 
					
						
							|  |  |  |  |             color: #333; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-readonly-table td { | 
					
						
							|  |  |  |  |             color: #666; | 
					
						
							|  |  |  |  |             background: white; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         .spec-readonly-actions { | 
					
						
							|  |  |  |  |             padding: 12px 16px; | 
					
						
							|  |  |  |  |             background: #fafafa; | 
					
						
							|  |  |  |  |             text-align: right; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |     </style> | 
					
						
							|  |  |  |  | </head> | 
					
						
							|  |  |  |  | <body> | 
					
						
							|  |  |  |  |     <div class="container"> | 
					
						
							|  |  |  |  |         <!-- 模态框头部 --> | 
					
						
							|  |  |  |  |         <div class="modal-header"> | 
					
						
							|  |  |  |  |             <h2 class="modal-title">添加商品</h2> | 
					
						
							|  |  |  |  |             <button class="close-btn" onclick="closeModal()">×</button> | 
					
						
							|  |  |  |  |         </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         <!-- 模态框内容 --> | 
					
						
							|  |  |  |  |         <div class="modal-body"> | 
					
						
							|  |  |  |  |             <!-- 标签页导航 --> | 
					
						
							|  |  |  |  |             <div class="tabs-container"> | 
					
						
							|  |  |  |  |                 <div class="tabs"> | 
					
						
							| 
									
										
										
										
											2025-10-20 21:00:15 +00:00
										 |  |  |  |                     <div class="tab active" data-tab="store">发布店铺</div> | 
					
						
							|  |  |  |  |                     <div class="tab" data-tab="basic">基础信息</div> | 
					
						
							| 
									
										
										
										
											2025-09-09 16:22:19 +00:00
										 |  |  |  |                     <div class="tab" data-tab="sales">销售信息</div> | 
					
						
							|  |  |  |  |                     <div class="tab" data-tab="other">其他信息</div> | 
					
						
							|  |  |  |  |                 </div> | 
					
						
							|  |  |  |  |             </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             <!-- 表单内容 --> | 
					
						
							|  |  |  |  |             <form id="addProductForm"> | 
					
						
							| 
									
										
										
										
											2025-10-20 21:00:15 +00:00
										 |  |  |  |                 <!-- 发布店铺标签页 --> | 
					
						
							|  |  |  |  |                 <div id="store" class="tab-pane active"> | 
					
						
							|  |  |  |  |                     <div class="tab-content"> | 
					
						
							|  |  |  |  |                         <div class="form-group"> | 
					
						
							|  |  |  |  |                             <label class="form-label"> | 
					
						
							|  |  |  |  |                                 <span class="required">*</span>选择店铺 | 
					
						
							|  |  |  |  |                             </label> | 
					
						
							|  |  |  |  |                             <div class="select-wrapper"> | 
					
						
							|  |  |  |  |                                 <select class="form-select" id="storeSelect" required> | 
					
						
							|  |  |  |  |                                     <option value="">请选择需要发布的店铺</option> | 
					
						
							|  |  |  |  |                                     <option value="store1">旗舰店</option> | 
					
						
							|  |  |  |  |                                     <option value="store2">生鲜直营店</option> | 
					
						
							|  |  |  |  |                                     <option value="store3">水果专营店</option> | 
					
						
							|  |  |  |  |                                     <option value="store4">蔬菜专卖店</option> | 
					
						
							|  |  |  |  |                                     <option value="store5">海鲜市场店</option> | 
					
						
							|  |  |  |  |                                 </select> | 
					
						
							|  |  |  |  |                             </div> | 
					
						
							|  |  |  |  |                             <div class="error-message" id="storeSelectError" style="display: none;">不能为空。</div> | 
					
						
							|  |  |  |  |                         </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                         <div class="form-group"> | 
					
						
							|  |  |  |  |                             <label class="form-label">店铺说明</label> | 
					
						
							|  |  |  |  |                             <div style="padding: 16px; background: #f5f5f5; border-radius: 6px; color: #666; font-size: 14px; line-height: 1.6;"> | 
					
						
							|  |  |  |  |                                 <p style="margin: 0 0 8px 0;"><strong>提示:</strong></p> | 
					
						
							|  |  |  |  |                                 <p style="margin: 0;">• 请先选择要发布商品的店铺</p> | 
					
						
							|  |  |  |  |                                 <p style="margin: 4px 0 0 0;">• 商品发布后将在所选店铺中展示</p> | 
					
						
							|  |  |  |  |                                 <p style="margin: 4px 0 0 0;">• 同一商品可以发布到多个店铺</p> | 
					
						
							|  |  |  |  |                             </div> | 
					
						
							|  |  |  |  |                         </div> | 
					
						
							|  |  |  |  |                     </div> | 
					
						
							|  |  |  |  |                 </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-09 16:22:19 +00:00
										 |  |  |  |                 <!-- 基础信息标签页 --> | 
					
						
							| 
									
										
										
										
											2025-10-20 21:00:15 +00:00
										 |  |  |  |                 <div id="basic" class="tab-pane"> | 
					
						
							| 
									
										
										
										
											2025-09-09 16:22:19 +00:00
										 |  |  |  |                     <div class="tab-content"> | 
					
						
							|  |  |  |  |                         <div class="form-group"> | 
					
						
							|  |  |  |  |                             <label class="form-label"> | 
					
						
							|  |  |  |  |                                 <span class="required">*</span>商品图片 | 
					
						
							|  |  |  |  |                             </label> | 
					
						
							|  |  |  |  |                             <div class="upload-area" id="uploadArea"> | 
					
						
							|  |  |  |  |                                 <div class="upload-icon">📷</div> | 
					
						
							|  |  |  |  |                                 <div class="upload-text"> | 
					
						
							|  |  |  |  |                                     将文件拖到此处,或<a href="#" class="upload-highlight">点击上传</a> | 
					
						
							|  |  |  |  |                                 </div> | 
					
						
							|  |  |  |  |                                 <div class="upload-hint">只能上传jpg/png文件,且不超过500kb</div> | 
					
						
							|  |  |  |  |                             </div> | 
					
						
							|  |  |  |  |                             <div class="image-preview" id="imagePreview"></div> | 
					
						
							|  |  |  |  |                             <div class="error-message" id="imageError" style="display: none;">不能为空。</div> | 
					
						
							|  |  |  |  |                             <input type="file" id="fileInput" accept="image/jpeg,image/png" multiple style="display: none;"> | 
					
						
							|  |  |  |  |                         </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                         <div class="form-group"> | 
					
						
							|  |  |  |  |                             <label class="form-label"> | 
					
						
							|  |  |  |  |                                 <span class="required">*</span>商品类目 | 
					
						
							|  |  |  |  |                             </label> | 
					
						
							|  |  |  |  |                             <div class="select-wrapper"> | 
					
						
							|  |  |  |  |                                 <select class="form-select" id="category" required> | 
					
						
							|  |  |  |  |                                     <option value="">请选择商品类目</option> | 
					
						
							|  |  |  |  |                                     <option value="vegetables">蔬菜类</option> | 
					
						
							|  |  |  |  |                                     <option value="fruits">水果类</option> | 
					
						
							|  |  |  |  |                                     <option value="meat">肉类</option> | 
					
						
							|  |  |  |  |                                     <option value="seafood">海鲜类</option> | 
					
						
							|  |  |  |  |                                     <option value="grains">粮油类</option> | 
					
						
							|  |  |  |  |                                     <option value="dairy">乳制品</option> | 
					
						
							|  |  |  |  |                                     <option value="beverages">饮料类</option> | 
					
						
							|  |  |  |  |                                     <option value="snacks">零食类</option> | 
					
						
							|  |  |  |  |                                 </select> | 
					
						
							|  |  |  |  |                             </div> | 
					
						
							|  |  |  |  |                             <div class="error-message" id="categoryError" style="display: none;">不能为空。</div> | 
					
						
							|  |  |  |  |                         </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                         <div class="form-group"> | 
					
						
							|  |  |  |  |                             <label class="form-label"> | 
					
						
							|  |  |  |  |                                 <span class="required">*</span>商品名称 | 
					
						
							|  |  |  |  |                             </label> | 
					
						
							|  |  |  |  |                             <input type="text" class="form-input" id="productName" placeholder="请输入商品名称" required> | 
					
						
							|  |  |  |  |                             <div class="error-message" id="nameError" style="display: none;">不能为空。</div> | 
					
						
							|  |  |  |  |                         </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                         <div class="form-group"> | 
					
						
							|  |  |  |  |                             <label class="form-label"> | 
					
						
							|  |  |  |  |                                 <span class="required">*</span>商品描述 | 
					
						
							|  |  |  |  |                             </label> | 
					
						
							|  |  |  |  |                             <textarea class="form-textarea" id="description" placeholder="请简单描述,如别称、口感、用途等" required></textarea> | 
					
						
							|  |  |  |  |                             <div class="error-message" id="descriptionError" style="display: none;">不能为空。</div> | 
					
						
							|  |  |  |  |                         </div> | 
					
						
							|  |  |  |  |                     </div> | 
					
						
							|  |  |  |  |                 </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                 <!-- 销售信息标签页 --> | 
					
						
							|  |  |  |  |                 <div id="sales" class="tab-pane"> | 
					
						
							|  |  |  |  |                     <div class="tab-content"> | 
					
						
							|  |  |  |  |                         <div class="form-group"> | 
					
						
							|  |  |  |  |                             <label class="form-label"> | 
					
						
							|  |  |  |  |                                 <span class="required">*</span>销售单位 | 
					
						
							|  |  |  |  |                             </label> | 
					
						
							|  |  |  |  |                             <div class="select-wrapper"> | 
					
						
							|  |  |  |  |                                 <select class="form-select" id="salesUnit" required> | 
					
						
							|  |  |  |  |                                     <option value="">请选择销售单位</option> | 
					
						
							|  |  |  |  |                                     <option value="piece">个</option> | 
					
						
							|  |  |  |  |                                     <option value="kg">公斤</option> | 
					
						
							|  |  |  |  |                                     <option value="bag">袋</option> | 
					
						
							|  |  |  |  |                                     <option value="box">盒</option> | 
					
						
							|  |  |  |  |                                     <option value="bottle">瓶</option> | 
					
						
							|  |  |  |  |                                     <option value="pack">包</option> | 
					
						
							|  |  |  |  |                                 </select> | 
					
						
							|  |  |  |  |                             </div> | 
					
						
							|  |  |  |  |                             <div class="error-message" id="salesUnitError" style="display: none;">不能为空。</div> | 
					
						
							|  |  |  |  |                         </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                         <div class="form-row"> | 
					
						
							|  |  |  |  |                             <div class="form-group"> | 
					
						
							|  |  |  |  |                                 <label class="form-label"> | 
					
						
							|  |  |  |  |                                     <span class="required">*</span>成本 | 
					
						
							|  |  |  |  |                                 </label> | 
					
						
							|  |  |  |  |                                 <div class="number-input-group"> | 
					
						
							|  |  |  |  |                                     <input type="number" class="form-input" id="costPrice" placeholder="请输入价格" min="0" step="0.01" required> | 
					
						
							|  |  |  |  |                                     <span class="unit-text">单位(元)</span> | 
					
						
							|  |  |  |  |                                 </div> | 
					
						
							|  |  |  |  |                                 <div class="error-message" id="costPriceError" style="display: none;">不能为空。</div> | 
					
						
							|  |  |  |  |                             </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                             <div class="form-group"> | 
					
						
							|  |  |  |  |                                 <label class="form-label"> | 
					
						
							|  |  |  |  |                                     <span class="required">*</span>市场价 | 
					
						
							|  |  |  |  |                                 </label> | 
					
						
							|  |  |  |  |                                 <div class="number-input-group"> | 
					
						
							|  |  |  |  |                                     <input type="number" class="form-input" id="marketPrice" placeholder="请输入市场价" min="0" step="0.01" required> | 
					
						
							|  |  |  |  |                                     <span class="unit-text">单位(元)</span> | 
					
						
							|  |  |  |  |                                 </div> | 
					
						
							|  |  |  |  |                                 <div class="error-message" id="marketPriceError" style="display: none;">不能为空。</div> | 
					
						
							|  |  |  |  |                             </div> | 
					
						
							|  |  |  |  |                         </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                         <div class="form-row"> | 
					
						
							|  |  |  |  |                             <div class="form-group"> | 
					
						
							|  |  |  |  |                                 <label class="form-label"> | 
					
						
							|  |  |  |  |                                     <span class="required">*</span>库存 | 
					
						
							|  |  |  |  |                                 </label> | 
					
						
							|  |  |  |  |                                 <input type="number" class="form-input" id="stock" placeholder="请输入库存" min="0" required> | 
					
						
							|  |  |  |  |                                 <div class="error-message" id="stockError" style="display: none;">不能为空。</div> | 
					
						
							|  |  |  |  |                             </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                             <div class="form-group"> | 
					
						
							|  |  |  |  |                                 <label class="form-label"> | 
					
						
							|  |  |  |  |                                     <span class="required">*</span>重量 | 
					
						
							|  |  |  |  |                                 </label> | 
					
						
							|  |  |  |  |                                 <div class="number-input-group"> | 
					
						
							|  |  |  |  |                                     <input type="number" class="form-input" id="weight" placeholder="请输入重量" min="0" step="0.01" required> | 
					
						
							|  |  |  |  |                                     <span class="unit-text">KG</span> | 
					
						
							|  |  |  |  |                                 </div> | 
					
						
							|  |  |  |  |                                 <div class="error-message" id="weightError" style="display: none;">不能为空。</div> | 
					
						
							|  |  |  |  |                             </div> | 
					
						
							|  |  |  |  |                         </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                         <div class="form-group"> | 
					
						
							|  |  |  |  |                             <label class="form-label"> | 
					
						
							|  |  |  |  |                                 <span class="required">*</span>体积 | 
					
						
							|  |  |  |  |                             </label> | 
					
						
							|  |  |  |  |                             <div class="number-input-group"> | 
					
						
							|  |  |  |  |                                 <input type="number" class="form-input" id="volume" placeholder="请输入体积" min="0" step="0.01" required> | 
					
						
							|  |  |  |  |                                 <span class="unit-text">立方米</span> | 
					
						
							|  |  |  |  |                             </div> | 
					
						
							|  |  |  |  |                             <div class="error-message" id="volumeError" style="display: none;">不能为空。</div> | 
					
						
							|  |  |  |  |                         </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                         <!-- 规格配置显示区域 --> | 
					
						
							|  |  |  |  |                         <div class="form-group"> | 
					
						
							|  |  |  |  |                             <label class="form-label">规格配置</label> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                             <!-- 无规格配置时显示 --> | 
					
						
							|  |  |  |  |                             <div id="noSpecGroup"> | 
					
						
							|  |  |  |  |                                 <button type="button" class="btn btn-secondary" onclick="configureSpecs()">添加多规格配置</button> | 
					
						
							|  |  |  |  |                                 <div style="margin-top: 8px; color: #999; font-size: 12px;">单规格商品无需配置</div> | 
					
						
							|  |  |  |  |                             </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                             <!-- 有规格配置时显示 --> | 
					
						
							|  |  |  |  |                             <div id="specDisplayGroup" style="display: none;"> | 
					
						
							|  |  |  |  |                                 <div class="spec-readonly-container"> | 
					
						
							|  |  |  |  |                                     <table class="spec-readonly-table" id="specReadonlyTable"> | 
					
						
							|  |  |  |  |                                         <thead> | 
					
						
							|  |  |  |  |                                             <tr> | 
					
						
							|  |  |  |  |                                                 <th>序号</th> | 
					
						
							|  |  |  |  |                                                 <th>属性</th> | 
					
						
							|  |  |  |  |                                                 <th>成本(元)</th> | 
					
						
							|  |  |  |  |                                                 <th>市场价(元)</th> | 
					
						
							|  |  |  |  |                                                 <th>库存</th> | 
					
						
							|  |  |  |  |                                                 <th>重量(千克)</th> | 
					
						
							|  |  |  |  |                                                 <th>体积(立方米)</th> | 
					
						
							|  |  |  |  |                                             </tr> | 
					
						
							|  |  |  |  |                                         </thead> | 
					
						
							|  |  |  |  |                                         <tbody id="specReadonlyTableBody"> | 
					
						
							|  |  |  |  |                                         </tbody> | 
					
						
							|  |  |  |  |                                     </table> | 
					
						
							|  |  |  |  |                                     <div class="spec-readonly-actions"> | 
					
						
							|  |  |  |  |                                         <button type="button" class="btn btn-secondary" onclick="configureSpecs()">修改规格配置</button> | 
					
						
							|  |  |  |  |                                     </div> | 
					
						
							|  |  |  |  |                                 </div> | 
					
						
							|  |  |  |  |                             </div> | 
					
						
							|  |  |  |  |                         </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                                             </div> | 
					
						
							|  |  |  |  |                 </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                 <!-- 其他信息标签页 --> | 
					
						
							|  |  |  |  |                 <div id="other" class="tab-pane"> | 
					
						
							|  |  |  |  |                     <div class="tab-content"> | 
					
						
							|  |  |  |  |                         <div class="form-group"> | 
					
						
							|  |  |  |  |                             <label class="form-label">产地</label> | 
					
						
							|  |  |  |  |                             <input type="text" class="form-input" id="origin" placeholder="请选择"> | 
					
						
							|  |  |  |  |                         </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                         <div class="form-group"> | 
					
						
							|  |  |  |  |                             <label class="form-label">保质期</label> | 
					
						
							|  |  |  |  |                             <div class="select-wrapper"> | 
					
						
							|  |  |  |  |                                 <select class="form-select" id="shelfLife"> | 
					
						
							|  |  |  |  |                                     <option value="">请填写保质期</option> | 
					
						
							|  |  |  |  |                                     <option value="1day">1天</option> | 
					
						
							|  |  |  |  |                                     <option value="3days">3天</option> | 
					
						
							|  |  |  |  |                                     <option value="1week">1周</option> | 
					
						
							|  |  |  |  |                                     <option value="2weeks">2周</option> | 
					
						
							|  |  |  |  |                                     <option value="1month">1个月</option> | 
					
						
							|  |  |  |  |                                     <option value="3months">3个月</option> | 
					
						
							|  |  |  |  |                                     <option value="6months">6个月</option> | 
					
						
							|  |  |  |  |                                     <option value="1year">1年</option> | 
					
						
							|  |  |  |  |                                     <option value="2years">2年</option> | 
					
						
							|  |  |  |  |                                     <option value="custom">自定义</option> | 
					
						
							|  |  |  |  |                                 </select> | 
					
						
							|  |  |  |  |                             </div> | 
					
						
							|  |  |  |  |                         </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                         <div class="form-group" id="customShelfLifeGroup" style="display: none;"> | 
					
						
							|  |  |  |  |                             <label class="form-label">自定义保质期</label> | 
					
						
							|  |  |  |  |                             <input type="text" class="form-input" id="customShelfLife" placeholder="请输入保质期"> | 
					
						
							|  |  |  |  |                         </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                         <div class="form-group"> | 
					
						
							|  |  |  |  |                             <label class="form-label">商品介绍图</label> | 
					
						
							|  |  |  |  |                             <div class="upload-area" id="productIntroUploadArea"> | 
					
						
							|  |  |  |  |                                 <div class="upload-icon">📷</div> | 
					
						
							|  |  |  |  |                                 <div class="upload-text"> | 
					
						
							|  |  |  |  |                                     将文件拖到此处,或<a href="#" class="upload-highlight">点击上传</a> | 
					
						
							|  |  |  |  |                                 </div> | 
					
						
							|  |  |  |  |                                 <div class="upload-hint">支持mp4、avi、mov等视频格式,建议不超过50MB</div> | 
					
						
							|  |  |  |  |                             </div> | 
					
						
							|  |  |  |  |                             <div class="image-preview" id="productIntroPreview"></div> | 
					
						
							|  |  |  |  |                             <input type="file" id="productIntroFileInput" accept="video/*,image/*" multiple style="display: none;"> | 
					
						
							|  |  |  |  |                         </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                         <div class="form-group"> | 
					
						
							|  |  |  |  |                             <label class="form-label">商品标签</label> | 
					
						
							|  |  |  |  |                             <input type="text" class="form-input" id="tags" placeholder="多个标签用逗号分隔,如:新鲜,有机,精选"> | 
					
						
							|  |  |  |  |                         </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                         <div class="form-group"> | 
					
						
							|  |  |  |  |                             <label class="form-label">备注信息</label> | 
					
						
							|  |  |  |  |                             <textarea class="form-textarea" id="remarks" placeholder="商品备注信息"></textarea> | 
					
						
							|  |  |  |  |                         </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                         <div class="form-group"> | 
					
						
							|  |  |  |  |                             <label class="form-label">排序权重</label> | 
					
						
							|  |  |  |  |                             <div class="number-input-group"> | 
					
						
							|  |  |  |  |                                 <input type="number" class="form-input" id="sortOrder" placeholder="0" value="0"> | 
					
						
							|  |  |  |  |                                 <span class="unit-text">数值越大排序越靠前</span> | 
					
						
							|  |  |  |  |                             </div> | 
					
						
							|  |  |  |  |                         </div> | 
					
						
							|  |  |  |  |                     </div> | 
					
						
							|  |  |  |  |                 </div> | 
					
						
							|  |  |  |  |             </form> | 
					
						
							|  |  |  |  |         </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         <!-- 模态框底部 --> | 
					
						
							|  |  |  |  |         <div class="modal-footer"> | 
					
						
							|  |  |  |  |             <button type="button" class="btn btn-secondary" onclick="resetForm()">重置</button> | 
					
						
							|  |  |  |  |             <button type="button" class="btn btn-primary" id="nextBtn" onclick="nextStep()">下一步</button> | 
					
						
							|  |  |  |  |             <button type="button" class="btn btn-primary" id="saveBtn" onclick="saveProduct()" style="display: none;">保存并放入仓库</button> | 
					
						
							|  |  |  |  |             <button type="button" class="btn btn-primary" id="publishBtn" onclick="publishProduct()" style="display: none;">保存并上架</button> | 
					
						
							|  |  |  |  |         </div> | 
					
						
							|  |  |  |  |     </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     <!-- 规格配置弹窗 --> | 
					
						
							|  |  |  |  |     <div id="specModal" class="spec-modal" style="display: none;"> | 
					
						
							|  |  |  |  |         <div class="spec-modal-overlay" onclick="closeSpecModal()"></div> | 
					
						
							|  |  |  |  |         <div class="spec-modal-content"> | 
					
						
							|  |  |  |  |             <div class="spec-modal-header"> | 
					
						
							|  |  |  |  |                 <h3 class="spec-modal-title">添加属性</h3> | 
					
						
							|  |  |  |  |                 <button class="close-btn" onclick="closeSpecModal()">×</button> | 
					
						
							|  |  |  |  |             </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             <div class="spec-modal-body"> | 
					
						
							|  |  |  |  |                 <div class="form-group"> | 
					
						
							|  |  |  |  |                     <label class="form-label">属性配置</label> | 
					
						
							|  |  |  |  |                     <table class="spec-config-table" id="specConfigTable"> | 
					
						
							|  |  |  |  |                         <thead> | 
					
						
							|  |  |  |  |                             <tr> | 
					
						
							|  |  |  |  |                                 <th>属性名</th> | 
					
						
							|  |  |  |  |                                 <th>属性值</th> | 
					
						
							|  |  |  |  |                                 <th>操作</th> | 
					
						
							|  |  |  |  |                             </tr> | 
					
						
							|  |  |  |  |                         </thead> | 
					
						
							|  |  |  |  |                         <tbody> | 
					
						
							|  |  |  |  |                             <tr> | 
					
						
							|  |  |  |  |                                 <td><input type="text" class="spec-attr-input" value="温度" data-attr="temperature"></td> | 
					
						
							|  |  |  |  |                                 <td> | 
					
						
							|  |  |  |  |                                     <div class="spec-values-container" data-attr="temperature"> | 
					
						
							|  |  |  |  |                                         <span class="spec-value-tag">热 <button type="button" class="spec-value-remove" onclick="removeSpecValue('temperature', '热')">×</button></span> | 
					
						
							|  |  |  |  |                                         <span class="spec-value-tag">冷 <button type="button" class="spec-value-remove" onclick="removeSpecValue('temperature', '冷')">×</button></span> | 
					
						
							|  |  |  |  |                                         <button type="button" class="btn btn-secondary btn-sm" onclick="addSpecValue('temperature')">+增加属性值</button> | 
					
						
							|  |  |  |  |                                         <input type="text" class="spec-value-input" placeholder="输入属性值按回车确认" style="display: none;" onkeypress="handleSpecValueInput(event, 'temperature')"> | 
					
						
							|  |  |  |  |                                     </div> | 
					
						
							|  |  |  |  |                                 </td> | 
					
						
							|  |  |  |  |                                 <td><button type="button" class="btn btn-danger btn-sm" onclick="removeSpecAttribute('temperature')">删除</button></td> | 
					
						
							|  |  |  |  |                             </tr> | 
					
						
							|  |  |  |  |                             <tr> | 
					
						
							|  |  |  |  |                                 <td><input type="text" class="spec-attr-input" value="体积" data-attr="volume"></td> | 
					
						
							|  |  |  |  |                                 <td> | 
					
						
							|  |  |  |  |                                     <div class="spec-values-container" data-attr="volume"> | 
					
						
							|  |  |  |  |                                         <span class="spec-value-tag">大 <button type="button" class="spec-value-remove" onclick="removeSpecValue('volume', '大')">×</button></span> | 
					
						
							|  |  |  |  |                                         <span class="spec-value-tag">小 <button type="button" class="spec-value-remove" onclick="removeSpecValue('volume', '小')">×</button></span> | 
					
						
							|  |  |  |  |                                         <button type="button" class="btn btn-secondary btn-sm" onclick="addSpecValue('volume')">+增加属性值</button> | 
					
						
							|  |  |  |  |                                         <input type="text" class="spec-value-input" placeholder="输入属性值按回车确认" style="display: none;" onkeypress="handleSpecValueInput(event, 'volume')"> | 
					
						
							|  |  |  |  |                                     </div> | 
					
						
							|  |  |  |  |                                 </td> | 
					
						
							|  |  |  |  |                                 <td><button type="button" class="btn btn-danger btn-sm" onclick="removeSpecAttribute('volume')">删除</button></td> | 
					
						
							|  |  |  |  |                             </tr> | 
					
						
							|  |  |  |  |                         </tbody> | 
					
						
							|  |  |  |  |                     </table> | 
					
						
							|  |  |  |  |                     <div style="margin-top: 10px;"> | 
					
						
							|  |  |  |  |                         <button type="button" class="btn btn-secondary" onclick="addSpecAttribute()">+添加属性</button> | 
					
						
							|  |  |  |  |                     </div> | 
					
						
							|  |  |  |  |                 </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                 <!-- 规格组合表格 --> | 
					
						
							|  |  |  |  |                 <div class="spec-combinations"> | 
					
						
							|  |  |  |  |                     <table class="spec-table"> | 
					
						
							|  |  |  |  |                         <thead> | 
					
						
							|  |  |  |  |                             <tr> | 
					
						
							|  |  |  |  |                                 <th>序号</th> | 
					
						
							|  |  |  |  |                                 <th>属性</th> | 
					
						
							|  |  |  |  |                                 <th>成本(元)</th> | 
					
						
							|  |  |  |  |                                 <th>市场价(元)</th> | 
					
						
							|  |  |  |  |                                 <th>库存</th> | 
					
						
							|  |  |  |  |                                 <th>重量(千克)</th> | 
					
						
							|  |  |  |  |                                 <th>体积(立方米)</th> | 
					
						
							|  |  |  |  |                                 <th>操作</th> | 
					
						
							|  |  |  |  |                             </tr> | 
					
						
							|  |  |  |  |                         </thead> | 
					
						
							|  |  |  |  |                         <tbody id="specCombinationsTable"> | 
					
						
							|  |  |  |  |                         </tbody> | 
					
						
							|  |  |  |  |                     </table> | 
					
						
							|  |  |  |  |                 </div> | 
					
						
							|  |  |  |  |             </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             <div class="spec-modal-footer"> | 
					
						
							|  |  |  |  |                 <button type="button" class="btn btn-secondary" onclick="closeSpecModal()">取消</button> | 
					
						
							|  |  |  |  |                 <button type="button" class="btn btn-primary" onclick="saveSpecConfig()">确定</button> | 
					
						
							|  |  |  |  |             </div> | 
					
						
							|  |  |  |  |         </div> | 
					
						
							|  |  |  |  |     </div> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     <script> | 
					
						
							|  |  |  |  |         // 标签页切换 | 
					
						
							|  |  |  |  |         const tabs = document.querySelectorAll('.tab'); | 
					
						
							|  |  |  |  |         const tabPanes = document.querySelectorAll('.tab-pane'); | 
					
						
							|  |  |  |  |         let currentTabIndex = 0; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         tabs.forEach((tab, index) => { | 
					
						
							|  |  |  |  |             tab.addEventListener('click', () => { | 
					
						
							|  |  |  |  |                 switchTab(index); | 
					
						
							|  |  |  |  |             }); | 
					
						
							|  |  |  |  |         }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         function switchTab(index) { | 
					
						
							|  |  |  |  |             // 移除所有活动状态 | 
					
						
							|  |  |  |  |             tabs.forEach(tab => tab.classList.remove('active')); | 
					
						
							|  |  |  |  |             tabPanes.forEach(pane => pane.classList.remove('active')); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             // 激活当前标签页 | 
					
						
							|  |  |  |  |             tabs[index].classList.add('active'); | 
					
						
							|  |  |  |  |             tabPanes[index].classList.add('active'); | 
					
						
							|  |  |  |  |             currentTabIndex = index; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             // 更新按钮显示 | 
					
						
							|  |  |  |  |             updateButtons(); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         function updateButtons() { | 
					
						
							|  |  |  |  |             const nextBtn = document.getElementById('nextBtn'); | 
					
						
							|  |  |  |  |             const saveBtn = document.getElementById('saveBtn'); | 
					
						
							|  |  |  |  |             const publishBtn = document.getElementById('publishBtn'); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-10-20 21:00:15 +00:00
										 |  |  |  |             if (currentTabIndex < 3) { | 
					
						
							| 
									
										
										
										
											2025-09-09 16:22:19 +00:00
										 |  |  |  |                 nextBtn.style.display = 'block'; | 
					
						
							|  |  |  |  |                 saveBtn.style.display = 'none'; | 
					
						
							|  |  |  |  |                 publishBtn.style.display = 'none'; | 
					
						
							|  |  |  |  |             } else { | 
					
						
							|  |  |  |  |                 nextBtn.style.display = 'none'; | 
					
						
							|  |  |  |  |                 saveBtn.style.display = 'block'; | 
					
						
							|  |  |  |  |                 publishBtn.style.display = 'block'; | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         function nextStep() { | 
					
						
							|  |  |  |  |             if (validateCurrentTab()) { | 
					
						
							| 
									
										
										
										
											2025-10-20 21:00:15 +00:00
										 |  |  |  |                 if (currentTabIndex < 3) { | 
					
						
							| 
									
										
										
										
											2025-09-09 16:22:19 +00:00
										 |  |  |  |                     switchTab(currentTabIndex + 1); | 
					
						
							|  |  |  |  |                 } | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         function validateCurrentTab() { | 
					
						
							|  |  |  |  |             let isValid = true; | 
					
						
							|  |  |  |  |             const currentPane = tabPanes[currentTabIndex]; | 
					
						
							|  |  |  |  |             const requiredFields = currentPane.querySelectorAll('[required]'); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             requiredFields.forEach(field => { | 
					
						
							|  |  |  |  |                 const errorElement = document.getElementById(field.id + 'Error'); | 
					
						
							|  |  |  |  |                 if (!field.value.trim()) { | 
					
						
							|  |  |  |  |                     if (errorElement) { | 
					
						
							|  |  |  |  |                         errorElement.style.display = 'block'; | 
					
						
							|  |  |  |  |                     } | 
					
						
							|  |  |  |  |                     isValid = false; | 
					
						
							|  |  |  |  |                 } else { | 
					
						
							|  |  |  |  |                     if (errorElement) { | 
					
						
							|  |  |  |  |                         errorElement.style.display = 'none'; | 
					
						
							|  |  |  |  |                     } | 
					
						
							|  |  |  |  |                 } | 
					
						
							|  |  |  |  |             }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-10-20 21:00:15 +00:00
										 |  |  |  |             // 特殊验证:图片上传(基础信息页) | 
					
						
							|  |  |  |  |             if (currentTabIndex === 1) { | 
					
						
							| 
									
										
										
										
											2025-09-09 16:22:19 +00:00
										 |  |  |  |                 const imagePreview = document.getElementById('imagePreview'); | 
					
						
							|  |  |  |  |                 const imageError = document.getElementById('imageError'); | 
					
						
							|  |  |  |  |                 if (imagePreview.children.length === 0) { | 
					
						
							|  |  |  |  |                     imageError.style.display = 'block'; | 
					
						
							|  |  |  |  |                     isValid = false; | 
					
						
							|  |  |  |  |                 } else { | 
					
						
							|  |  |  |  |                     imageError.style.display = 'none'; | 
					
						
							|  |  |  |  |                 } | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             return isValid; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 文件上传功能 | 
					
						
							|  |  |  |  |         const uploadArea = document.getElementById('uploadArea'); | 
					
						
							|  |  |  |  |         const fileInput = document.getElementById('fileInput'); | 
					
						
							|  |  |  |  |         const imagePreview = document.getElementById('imagePreview'); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         uploadArea.addEventListener('click', () => { | 
					
						
							|  |  |  |  |             fileInput.click(); | 
					
						
							|  |  |  |  |         }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         uploadArea.addEventListener('dragover', (e) => { | 
					
						
							|  |  |  |  |             e.preventDefault(); | 
					
						
							|  |  |  |  |             uploadArea.classList.add('dragover'); | 
					
						
							|  |  |  |  |         }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         uploadArea.addEventListener('dragleave', () => { | 
					
						
							|  |  |  |  |             uploadArea.classList.remove('dragover'); | 
					
						
							|  |  |  |  |         }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         uploadArea.addEventListener('drop', (e) => { | 
					
						
							|  |  |  |  |             e.preventDefault(); | 
					
						
							|  |  |  |  |             uploadArea.classList.remove('dragover'); | 
					
						
							|  |  |  |  |             const files = e.dataTransfer.files; | 
					
						
							|  |  |  |  |             handleFiles(files); | 
					
						
							|  |  |  |  |         }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         fileInput.addEventListener('change', (e) => { | 
					
						
							|  |  |  |  |             handleFiles(e.target.files); | 
					
						
							|  |  |  |  |         }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         function handleFiles(files) { | 
					
						
							|  |  |  |  |             Array.from(files).forEach(file => { | 
					
						
							|  |  |  |  |                 if (file.type.startsWith('image/') && file.size <= 500 * 1024) { | 
					
						
							|  |  |  |  |                     const reader = new FileReader(); | 
					
						
							|  |  |  |  |                     reader.onload = (e) => { | 
					
						
							|  |  |  |  |                         addImagePreview(e.target.result, file.name); | 
					
						
							|  |  |  |  |                     }; | 
					
						
							|  |  |  |  |                     reader.readAsDataURL(file); | 
					
						
							|  |  |  |  |                 } else { | 
					
						
							|  |  |  |  |                     alert('请选择小于500KB的图片文件'); | 
					
						
							|  |  |  |  |                 } | 
					
						
							|  |  |  |  |             }); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         function addImagePreview(src, name) { | 
					
						
							|  |  |  |  |             const previewItem = document.createElement('div'); | 
					
						
							|  |  |  |  |             previewItem.className = 'preview-item'; | 
					
						
							|  |  |  |  |             previewItem.innerHTML = ` | 
					
						
							|  |  |  |  |                 <img src="${src}" alt="${name}" class="preview-image"> | 
					
						
							|  |  |  |  |                 <button type="button" class="preview-remove" onclick="removeImage(this)">×</button> | 
					
						
							|  |  |  |  |             `; | 
					
						
							|  |  |  |  |             imagePreview.appendChild(previewItem); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         function removeImage(button) { | 
					
						
							|  |  |  |  |             button.parentElement.remove(); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 保质期自定义选项 | 
					
						
							|  |  |  |  |         const shelfLifeSelect = document.getElementById('shelfLife'); | 
					
						
							|  |  |  |  |         const customShelfLifeGroup = document.getElementById('customShelfLifeGroup'); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         shelfLifeSelect.addEventListener('change', () => { | 
					
						
							|  |  |  |  |             customShelfLifeGroup.style.display = shelfLifeSelect.value === 'custom' ? 'block' : 'none'; | 
					
						
							|  |  |  |  |         }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 商品介绍图上传功能 | 
					
						
							|  |  |  |  |         const productIntroUploadArea = document.getElementById('productIntroUploadArea'); | 
					
						
							|  |  |  |  |         const productIntroFileInput = document.getElementById('productIntroFileInput'); | 
					
						
							|  |  |  |  |         const productIntroPreview = document.getElementById('productIntroPreview'); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         productIntroUploadArea.addEventListener('click', () => { | 
					
						
							|  |  |  |  |             productIntroFileInput.click(); | 
					
						
							|  |  |  |  |         }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         productIntroUploadArea.addEventListener('dragover', (e) => { | 
					
						
							|  |  |  |  |             e.preventDefault(); | 
					
						
							|  |  |  |  |             productIntroUploadArea.classList.add('dragover'); | 
					
						
							|  |  |  |  |         }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         productIntroUploadArea.addEventListener('dragleave', () => { | 
					
						
							|  |  |  |  |             productIntroUploadArea.classList.remove('dragover'); | 
					
						
							|  |  |  |  |         }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         productIntroUploadArea.addEventListener('drop', (e) => { | 
					
						
							|  |  |  |  |             e.preventDefault(); | 
					
						
							|  |  |  |  |             productIntroUploadArea.classList.remove('dragover'); | 
					
						
							|  |  |  |  |             const files = e.dataTransfer.files; | 
					
						
							|  |  |  |  |             handleProductIntroFiles(files); | 
					
						
							|  |  |  |  |         }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         productIntroFileInput.addEventListener('change', (e) => { | 
					
						
							|  |  |  |  |             handleProductIntroFiles(e.target.files); | 
					
						
							|  |  |  |  |         }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         function handleProductIntroFiles(files) { | 
					
						
							|  |  |  |  |             Array.from(files).forEach(file => { | 
					
						
							|  |  |  |  |                 if ((file.type.startsWith('image/') || file.type.startsWith('video/')) && file.size <= 50 * 1024 * 1024) { | 
					
						
							|  |  |  |  |                     const reader = new FileReader(); | 
					
						
							|  |  |  |  |                     reader.onload = (e) => { | 
					
						
							|  |  |  |  |                         addProductIntroPreview(e.target.result, file.name, file.type); | 
					
						
							|  |  |  |  |                     }; | 
					
						
							|  |  |  |  |                     reader.readAsDataURL(file); | 
					
						
							|  |  |  |  |                 } else { | 
					
						
							|  |  |  |  |                     alert('请选择小于50MB的图片或视频文件'); | 
					
						
							|  |  |  |  |                 } | 
					
						
							|  |  |  |  |             }); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         function addProductIntroPreview(src, name, type) { | 
					
						
							|  |  |  |  |             const previewItem = document.createElement('div'); | 
					
						
							|  |  |  |  |             previewItem.className = 'preview-item'; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             if (type.startsWith('video/')) { | 
					
						
							|  |  |  |  |                 previewItem.innerHTML = ` | 
					
						
							|  |  |  |  |                     <video src="${src}" class="preview-image" controls></video> | 
					
						
							|  |  |  |  |                     <button type="button" class="preview-remove" onclick="removeProductIntroMedia(this)">×</button> | 
					
						
							|  |  |  |  |                 `; | 
					
						
							|  |  |  |  |             } else { | 
					
						
							|  |  |  |  |                 previewItem.innerHTML = ` | 
					
						
							|  |  |  |  |                     <img src="${src}" alt="${name}" class="preview-image"> | 
					
						
							|  |  |  |  |                     <button type="button" class="preview-remove" onclick="removeProductIntroMedia(this)">×</button> | 
					
						
							|  |  |  |  |                 `; | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |             productIntroPreview.appendChild(previewItem); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         function removeProductIntroMedia(button) { | 
					
						
							|  |  |  |  |             button.parentElement.remove(); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 规格配置功能 | 
					
						
							|  |  |  |  |         function configureSpecs() { | 
					
						
							|  |  |  |  |             document.getElementById('specModal').style.display = 'flex'; | 
					
						
							|  |  |  |  |             // 初始化现有属性值的显示 | 
					
						
							|  |  |  |  |             updateSpecValuesDisplay('temperature'); | 
					
						
							|  |  |  |  |             updateSpecValuesDisplay('volume'); | 
					
						
							|  |  |  |  |             // 初始化规格表格 | 
					
						
							|  |  |  |  |             regenerateSpecTable(); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         function closeSpecModal() { | 
					
						
							|  |  |  |  |             document.getElementById('specModal').style.display = 'none'; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 规格配置数据管理 | 
					
						
							|  |  |  |  |         let specData = { | 
					
						
							|  |  |  |  |             temperature: ['热', '冷'], | 
					
						
							|  |  |  |  |             volume: ['大', '小'] | 
					
						
							|  |  |  |  |         }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 删除属性 | 
					
						
							|  |  |  |  |         function deleteAttribute(attributeName) { | 
					
						
							|  |  |  |  |             if (confirm(`确定要删除${attributeName === 'temperature' ? '温度' : '体积'}属性吗?`)) { | 
					
						
							|  |  |  |  |                 delete specData[attributeName]; | 
					
						
							|  |  |  |  |                 updateSpecModal(); | 
					
						
							|  |  |  |  |                 regenerateSpecTable(); | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 删除规格选项 | 
					
						
							|  |  |  |  |         function removeOption(attributeName, index) { | 
					
						
							|  |  |  |  |             specData[attributeName].splice(index, 1); | 
					
						
							|  |  |  |  |             if (specData[attributeName].length === 0) { | 
					
						
							|  |  |  |  |                 delete specData[attributeName]; | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |             updateSpecModal(); | 
					
						
							|  |  |  |  |             regenerateSpecTable(); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 添加规格选项 | 
					
						
							|  |  |  |  |         function addOption(attributeName) { | 
					
						
							|  |  |  |  |             const optionName = prompt(`请输入新的${attributeName === 'temperature' ? '温度' : '体积'}规格:`); | 
					
						
							|  |  |  |  |             if (optionName && optionName.trim()) { | 
					
						
							|  |  |  |  |                 specData[attributeName].push(optionName.trim()); | 
					
						
							|  |  |  |  |                 updateSpecModal(); | 
					
						
							|  |  |  |  |                 regenerateSpecTable(); | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 添加新属性 | 
					
						
							|  |  |  |  |         function addSpecAttribute() { | 
					
						
							|  |  |  |  |             const tableBody = document.querySelector('#specConfigTable tbody'); | 
					
						
							|  |  |  |  |             const attributeKey = 'attribute' + Date.now(); // 使用时间戳作为唯一标识 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             const newRow = document.createElement('tr'); | 
					
						
							|  |  |  |  |             newRow.innerHTML = ` | 
					
						
							|  |  |  |  |                 <td><input type="text" class="spec-attr-input" value="新属性" data-attr="${attributeKey}"></td> | 
					
						
							|  |  |  |  |                 <td> | 
					
						
							|  |  |  |  |                     <div class="spec-values-container" data-attr="${attributeKey}"> | 
					
						
							|  |  |  |  |                         <button type="button" class="btn btn-secondary btn-sm" onclick="addSpecValue('${attributeKey}')">+增加属性值</button> | 
					
						
							|  |  |  |  |                         <input type="text" class="spec-value-input" placeholder="输入属性值按回车确认" style="display: none;" onkeypress="handleSpecValueInput(event, '${attributeKey}')"> | 
					
						
							|  |  |  |  |                     </div> | 
					
						
							|  |  |  |  |                 </td> | 
					
						
							|  |  |  |  |                 <td><button type="button" class="btn btn-danger btn-sm" onclick="removeSpecAttribute('${attributeKey}')">删除</button></td> | 
					
						
							|  |  |  |  |             `; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             tableBody.appendChild(newRow); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             // 初始化新属性的数据 | 
					
						
							|  |  |  |  |             specData[attributeKey] = []; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 增加属性值 | 
					
						
							|  |  |  |  |         function addSpecValue(attributeKey) { | 
					
						
							|  |  |  |  |             const container = document.querySelector(`.spec-values-container[data-attr="${attributeKey}"]`); | 
					
						
							|  |  |  |  |             const input = container.querySelector('.spec-value-input'); | 
					
						
							|  |  |  |  |             const addButton = container.querySelector('.btn-sm'); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             // 隐藏按钮,显示输入框 | 
					
						
							|  |  |  |  |             addButton.style.display = 'none'; | 
					
						
							|  |  |  |  |             input.style.display = 'inline-block'; | 
					
						
							|  |  |  |  |             input.focus(); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 处理属性值输入 | 
					
						
							|  |  |  |  |         function handleSpecValueInput(event, attributeKey) { | 
					
						
							|  |  |  |  |             if (event.key === 'Enter') { | 
					
						
							|  |  |  |  |                 const inputValue = event.target.value.trim(); | 
					
						
							|  |  |  |  |                 if (inputValue) { | 
					
						
							|  |  |  |  |                     // 添加属性值到数据 | 
					
						
							|  |  |  |  |                     if (!specData[attributeKey]) { | 
					
						
							|  |  |  |  |                         specData[attributeKey] = []; | 
					
						
							|  |  |  |  |                     } | 
					
						
							|  |  |  |  |                     specData[attributeKey].push(inputValue); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                     // 更新显示 | 
					
						
							|  |  |  |  |                     updateSpecValuesDisplay(attributeKey); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                     // 清空输入框并重新显示按钮 | 
					
						
							|  |  |  |  |                     event.target.value = ''; | 
					
						
							|  |  |  |  |                     event.target.style.display = 'none'; | 
					
						
							|  |  |  |  |                     const addButton = event.target.parentNode.querySelector('.btn-sm'); | 
					
						
							|  |  |  |  |                     addButton.style.display = 'inline-block'; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                     // 重新生成规格组合表格 | 
					
						
							|  |  |  |  |                     regenerateSpecTable(); | 
					
						
							|  |  |  |  |                 } | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 更新属性值显示 | 
					
						
							|  |  |  |  |         function updateSpecValuesDisplay(attributeKey) { | 
					
						
							|  |  |  |  |             const container = document.querySelector(`.spec-values-container[data-attr="${attributeKey}"]`); | 
					
						
							|  |  |  |  |             if (!container) return; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             // 清空容器(保留输入框和按钮) | 
					
						
							|  |  |  |  |             const input = container.querySelector('.spec-value-input'); | 
					
						
							|  |  |  |  |             const addButton = container.querySelector('.btn-sm'); | 
					
						
							|  |  |  |  |             container.innerHTML = ''; | 
					
						
							|  |  |  |  |             container.appendChild(addButton); | 
					
						
							|  |  |  |  |             container.appendChild(input); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             // 添加所有属性值标签 | 
					
						
							|  |  |  |  |             if (specData[attributeKey]) { | 
					
						
							|  |  |  |  |                 specData[attributeKey].forEach(value => { | 
					
						
							|  |  |  |  |                     const tag = document.createElement('span'); | 
					
						
							|  |  |  |  |                     tag.className = 'spec-value-tag'; | 
					
						
							|  |  |  |  |                     tag.innerHTML = `${value} <button type="button" class="spec-value-remove" onclick="removeSpecValue('${attributeKey}', '${value}')">×</button>`; | 
					
						
							|  |  |  |  |                     container.insertBefore(tag, addButton); | 
					
						
							|  |  |  |  |                 }); | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 删除属性值 | 
					
						
							|  |  |  |  |         function removeSpecValue(attributeKey, value) { | 
					
						
							|  |  |  |  |             if (specData[attributeKey]) { | 
					
						
							|  |  |  |  |                 const index = specData[attributeKey].indexOf(value); | 
					
						
							|  |  |  |  |                 if (index > -1) { | 
					
						
							|  |  |  |  |                     specData[attributeKey].splice(index, 1); | 
					
						
							|  |  |  |  |                     updateSpecValuesDisplay(attributeKey); | 
					
						
							|  |  |  |  |                     regenerateSpecTable(); | 
					
						
							|  |  |  |  |                 } | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 删除整个属性 | 
					
						
							|  |  |  |  |         function removeSpecAttribute(attributeKey) { | 
					
						
							|  |  |  |  |             // 删除数据 | 
					
						
							|  |  |  |  |             delete specData[attributeKey]; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             // 删除表格行 | 
					
						
							|  |  |  |  |             const row = document.querySelector(`input[data-attr="${attributeKey}"]`).closest('tr'); | 
					
						
							|  |  |  |  |             row.remove(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             // 重新生成规格表格 | 
					
						
							|  |  |  |  |             regenerateSpecTable(); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 监听属性名称变化 | 
					
						
							|  |  |  |  |         function setupAttributeNameListener() { | 
					
						
							|  |  |  |  |             document.addEventListener('input', function(event) { | 
					
						
							|  |  |  |  |                 if (event.target.classList.contains('spec-attr-input')) { | 
					
						
							|  |  |  |  |                     // 属性名称变化时重新生成规格表格 | 
					
						
							|  |  |  |  |                     regenerateSpecTable(); | 
					
						
							|  |  |  |  |                 } | 
					
						
							|  |  |  |  |             }); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 生成所有规格组合 | 
					
						
							|  |  |  |  |         function generateCombinations(attributes) { | 
					
						
							|  |  |  |  |             const keys = Object.keys(attributes); | 
					
						
							|  |  |  |  |             if (keys.length === 0) return []; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             function combine(arrays) { | 
					
						
							|  |  |  |  |                 if (arrays.length === 1) return arrays[0].map(item => [item]); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                 const result = []; | 
					
						
							|  |  |  |  |                 const firstArray = arrays[0]; | 
					
						
							|  |  |  |  |                 const remainingCombinations = combine(arrays.slice(1)); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                 for (const item of firstArray) { | 
					
						
							|  |  |  |  |                     for (const combination of remainingCombinations) { | 
					
						
							|  |  |  |  |                         result.push([item, ...combination]); | 
					
						
							|  |  |  |  |                     } | 
					
						
							|  |  |  |  |                 } | 
					
						
							|  |  |  |  |                 return result; | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             const attributeArrays = keys.map(key => attributes[key]); | 
					
						
							|  |  |  |  |             return combine(attributeArrays); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 重新生成规格表格 | 
					
						
							|  |  |  |  |         function regenerateSpecTable() { | 
					
						
							|  |  |  |  |             // 获取实际的属性数据 | 
					
						
							|  |  |  |  |             const actualSpecData = {}; | 
					
						
							|  |  |  |  |             const rows = document.querySelectorAll('#specConfigTable tbody tr'); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             rows.forEach(row => { | 
					
						
							|  |  |  |  |                 const attrInput = row.querySelector('.spec-attr-input'); | 
					
						
							|  |  |  |  |                 const attrKey = attrInput.getAttribute('data-attr'); | 
					
						
							|  |  |  |  |                 const attrName = attrInput.value.trim(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                 if (attrName && specData[attrKey] && specData[attrKey].length > 0) { | 
					
						
							|  |  |  |  |                     actualSpecData[attrName] = [...specData[attrKey]]; | 
					
						
							|  |  |  |  |                 } | 
					
						
							|  |  |  |  |             }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             const combinations = generateCombinations(actualSpecData); | 
					
						
							|  |  |  |  |             const tableBody = document.getElementById('specCombinationsTable'); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             if (!tableBody) return; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             tableBody.innerHTML = combinations.map((combination, index) => ` | 
					
						
							|  |  |  |  |                 <tr> | 
					
						
							|  |  |  |  |                     <td>${index + 1}</td> | 
					
						
							|  |  |  |  |                     <td>${combination.join('')}</td> | 
					
						
							|  |  |  |  |                     <td><input type="number" class="spec-input" value="0" min="0" step="0.01"></td> | 
					
						
							|  |  |  |  |                     <td><input type="number" class="spec-input" value="0" min="0" step="0.01"></td> | 
					
						
							|  |  |  |  |                     <td><input type="number" class="spec-input" value="0" min="0"></td> | 
					
						
							|  |  |  |  |                     <td><input type="number" class="spec-input" value="0" min="0" step="0.01"></td> | 
					
						
							|  |  |  |  |                     <td><input type="number" class="spec-input" value="0" min="0" step="0.01"></td> | 
					
						
							|  |  |  |  |                     <td><button type="button" class="btn btn-danger btn-small" onclick="deleteSpecRow(this)">删除</button></td> | 
					
						
							|  |  |  |  |                 </tr> | 
					
						
							|  |  |  |  |             `).join(''); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 删除规格行 | 
					
						
							|  |  |  |  |         function deleteSpecRow(button) { | 
					
						
							|  |  |  |  |             button.closest('tr').remove(); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 保存规格配置 | 
					
						
							|  |  |  |  |         function saveSpecConfig() { | 
					
						
							|  |  |  |  |             const tableRows = document.querySelectorAll('#specCombinationsTable tr'); | 
					
						
							|  |  |  |  |             const specConfigs = []; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             tableRows.forEach(row => { | 
					
						
							|  |  |  |  |                 const inputs = row.querySelectorAll('.spec-input'); | 
					
						
							|  |  |  |  |                 const spec = row.cells[1].textContent; | 
					
						
							|  |  |  |  |                 specConfigs.push({ | 
					
						
							|  |  |  |  |                     spec: spec, | 
					
						
							|  |  |  |  |                     cost: parseFloat(inputs[0].value) || 0, | 
					
						
							|  |  |  |  |                     marketPrice: parseFloat(inputs[1].value) || 0, | 
					
						
							|  |  |  |  |                     stock: parseInt(inputs[2].value) || 0, | 
					
						
							|  |  |  |  |                     weight: parseFloat(inputs[3].value) || 0, | 
					
						
							|  |  |  |  |                     volume: parseFloat(inputs[4].value) || 0 | 
					
						
							|  |  |  |  |                 }); | 
					
						
							|  |  |  |  |             }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             // 更新销售信息中的只读表格 | 
					
						
							|  |  |  |  |             updateReadonlySpecTable(specConfigs); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             console.log('规格配置已保存:', specConfigs); | 
					
						
							|  |  |  |  |             alert('规格配置已保存'); | 
					
						
							|  |  |  |  |             closeSpecModal(); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 更新销售信息中的只读规格表格 | 
					
						
							|  |  |  |  |         function updateReadonlySpecTable(specConfigs) { | 
					
						
							|  |  |  |  |             const noSpecGroup = document.getElementById('noSpecGroup'); | 
					
						
							|  |  |  |  |             const specDisplayGroup = document.getElementById('specDisplayGroup'); | 
					
						
							|  |  |  |  |             const tableBody = document.getElementById('specReadonlyTableBody'); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             if (specConfigs && specConfigs.length > 0) { | 
					
						
							|  |  |  |  |                 // 隐藏无规格区域,显示规格配置区域 | 
					
						
							|  |  |  |  |                 noSpecGroup.style.display = 'none'; | 
					
						
							|  |  |  |  |                 specDisplayGroup.style.display = 'block'; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                 // 更新表格内容 | 
					
						
							|  |  |  |  |                 tableBody.innerHTML = specConfigs.map((config, index) => ` | 
					
						
							|  |  |  |  |                     <tr> | 
					
						
							|  |  |  |  |                         <td>${index + 1}</td> | 
					
						
							|  |  |  |  |                         <td>${config.spec}</td> | 
					
						
							|  |  |  |  |                         <td>${config.cost.toFixed(2)}</td> | 
					
						
							|  |  |  |  |                         <td>${config.marketPrice.toFixed(2)}</td> | 
					
						
							|  |  |  |  |                         <td>${config.stock}</td> | 
					
						
							|  |  |  |  |                         <td>${config.weight.toFixed(2)}</td> | 
					
						
							|  |  |  |  |                         <td>${config.volume.toFixed(2)}</td> | 
					
						
							|  |  |  |  |                     </tr> | 
					
						
							|  |  |  |  |                 `).join(''); | 
					
						
							|  |  |  |  |             } else { | 
					
						
							|  |  |  |  |                 // 显示无规格区域,隐藏规格配置区域 | 
					
						
							|  |  |  |  |                 noSpecGroup.style.display = 'block'; | 
					
						
							|  |  |  |  |                 specDisplayGroup.style.display = 'none'; | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 检查是否有规格配置并更新显示 | 
					
						
							|  |  |  |  |         function checkAndUpdateSpecDisplay() { | 
					
						
							|  |  |  |  |             // 获取实际的属性数据 | 
					
						
							|  |  |  |  |             const actualSpecData = {}; | 
					
						
							|  |  |  |  |             const rows = document.querySelectorAll('#specConfigTable tbody tr'); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             rows.forEach(row => { | 
					
						
							|  |  |  |  |                 const attrInput = row.querySelector('.spec-attr-input'); | 
					
						
							|  |  |  |  |                 const attrKey = attrInput.getAttribute('data-attr'); | 
					
						
							|  |  |  |  |                 const attrName = attrInput.value.trim(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                 if (attrName && specData[attrKey] && specData[attrKey].length > 0) { | 
					
						
							|  |  |  |  |                     actualSpecData[attrName] = [...specData[attrKey]]; | 
					
						
							|  |  |  |  |                 } | 
					
						
							|  |  |  |  |             }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             const combinations = generateCombinations(actualSpecData); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             if (combinations.length > 0) { | 
					
						
							|  |  |  |  |                 const defaultConfigs = combinations.map((combination, index) => ({ | 
					
						
							|  |  |  |  |                     spec: combination.join(''), | 
					
						
							|  |  |  |  |                     cost: 0, | 
					
						
							|  |  |  |  |                     marketPrice: 0, | 
					
						
							|  |  |  |  |                     stock: 0, | 
					
						
							|  |  |  |  |                     weight: 0, | 
					
						
							|  |  |  |  |                     volume: 0 | 
					
						
							|  |  |  |  |                 })); | 
					
						
							|  |  |  |  |                 updateReadonlySpecTable(defaultConfigs); | 
					
						
							|  |  |  |  |             } else { | 
					
						
							|  |  |  |  |                 updateReadonlySpecTable([]); | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |          | 
					
						
							|  |  |  |  |         // 表单操作 | 
					
						
							|  |  |  |  |         function resetForm() { | 
					
						
							|  |  |  |  |             document.getElementById('addProductForm').reset(); | 
					
						
							|  |  |  |  |             imagePreview.innerHTML = ''; | 
					
						
							|  |  |  |  |             switchTab(0); | 
					
						
							|  |  |  |  |             hideAllErrors(); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         function hideAllErrors() { | 
					
						
							|  |  |  |  |             document.querySelectorAll('.error-message').forEach(error => { | 
					
						
							|  |  |  |  |                 error.style.display = 'none'; | 
					
						
							|  |  |  |  |             }); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         function saveProduct() { | 
					
						
							|  |  |  |  |             if (validateAllTabs()) { | 
					
						
							|  |  |  |  |                 alert('商品已保存到仓库'); | 
					
						
							|  |  |  |  |                 // 这里添加保存逻辑 | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         function publishProduct() { | 
					
						
							|  |  |  |  |             if (validateAllTabs()) { | 
					
						
							|  |  |  |  |                 alert('商品已保存并上架'); | 
					
						
							|  |  |  |  |                 // 这里添加发布逻辑 | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         function validateAllTabs() { | 
					
						
							|  |  |  |  |             let allValid = true; | 
					
						
							| 
									
										
										
										
											2025-10-20 21:00:15 +00:00
										 |  |  |  |             for (let i = 0; i < 4; i++) { | 
					
						
							| 
									
										
										
										
											2025-09-09 16:22:19 +00:00
										 |  |  |  |                 const originalIndex = currentTabIndex; | 
					
						
							|  |  |  |  |                 currentTabIndex = i; | 
					
						
							|  |  |  |  |                 if (!validateCurrentTab()) { | 
					
						
							|  |  |  |  |                     allValid = false; | 
					
						
							|  |  |  |  |                     if (originalIndex !== i) { | 
					
						
							|  |  |  |  |                         switchTab(i); | 
					
						
							|  |  |  |  |                     } | 
					
						
							|  |  |  |  |                     break; | 
					
						
							|  |  |  |  |                 } | 
					
						
							|  |  |  |  |                 currentTabIndex = originalIndex; | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |             return allValid; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         function closeModal() { | 
					
						
							|  |  |  |  |             if (confirm('确定要关闭吗?未保存的数据将丢失。')) { | 
					
						
							|  |  |  |  |                 // 关闭模态框逻辑 | 
					
						
							|  |  |  |  |                 window.history.back(); | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 初始化 | 
					
						
							|  |  |  |  |         updateButtons(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // 初始化规格表格 | 
					
						
							|  |  |  |  |         document.addEventListener('DOMContentLoaded', function() { | 
					
						
							|  |  |  |  |             regenerateSpecTable(); | 
					
						
							|  |  |  |  |             setupAttributeNameListener(); | 
					
						
							|  |  |  |  |             checkAndUpdateSpecDisplay(); | 
					
						
							|  |  |  |  |         }); | 
					
						
							|  |  |  |  |     </script> | 
					
						
							|  |  |  |  | </body> | 
					
						
							|  |  |  |  | </html> |