변경 파일 목록
총 49개
Admin (30)
auto_send_config_recipient_section.phpcrm/auto_send_config/auto_send_config.phpcrm/crm_recipe_send.phpcrm/layer_preview_auto_send.phpcrm/layer_template_contents_sms.phpcrm/message_template_register.phpcrm/template_contents_sms.phpcrm/message_template_register/layer_member_sms_history_result.phpcrm/mobile_message_history/layer_sms_contents.phpcrm/mobile_message_history/layer_sms_history_result.phpcrm/mobile_message_history/layer_kakao_alimtalk_content_setting.phpcrm/mobile_send/layer_kakao_friendtalk_content_setting.phpcrm/mobile_send/layer_mobile_send_save_sms_template.phpcrm/mobile_send/layer_mobile_send_sms_template.phpcrm/mobile_send/layer_mobile_send_sms_template_result.phpcrm/mobile_send/layer_myapp_push_content_setting.phpcrm/mobile_send/layer_send_method_setting.phpcrm/mobile_send/layer_sms_content_setting.phpcrm/mobile_send/mobile_send.phpcrm/layer_preview_mobile_send_alternative.phpcrm/preview_mobile_send/layer_preview_mobile_send_sms.phpcrm/preview_mobile_send/sms_auto.phpmember/sms_log.phpmember/sms_send.phpmember/cart_remind_regist.phppromotion/comeback_coupon_regist.phppromotion/layer_cart_remind_message.phppromotion/layer_comeback_coupon_sms.phpshare/layer_standby_sms.phpshare/member_crm_sms.phpshare/Component (6)
CartRemind.phpCartRemind/CouponAdmin.phpCoupon/DBTableField.phpDatabase/SmsAdmin.phpSms/SmsAuto.phpSms/SmsSender.phpSms/Controller (13)
LayerPreviewMobileSendController.phpAdmin/Crm/LayerKakaoFriendtalkContentSettingController.phpAdmin/Crm/MobileSend/LayerMobileSendSaveSmsTemplateController.phpAdmin/Crm/MobileSend/LayerMyappPushContentSettingController.phpAdmin/Crm/MobileSend/LayerSmsContentSettingController.phpAdmin/Crm/MobileSend/SmsTemplatePsController.phpAdmin/Crm/Sms/SmsAutoController.phpAdmin/Member/SmsLogPsController.phpAdmin/Member/SmsSendController.phpAdmin/Member/CartRemindRegistController.phpAdmin/Promotion/ComebackCouponRegistController.phpAdmin/Promotion/LayerCartRemindMessageController.phpAdmin/Promotion/LayerStandbySmsController.phpAdmin/Share/변경 파일 코드
추가삭제
변경 전auto_send_config_recipient_section.php
| <div class="ncua-card__body-block-section-wrap"> | |
| <section class="ncua-card__body-block-section"> | |
| <div class="ncua-card__body-title--xs">내용 입력</div> | |
| <div id="sms-message-input-container-<?= $recipient ?>" | |
| data-initial-value="<?= htmlspecialchars($autoSendConfig['SMS']['templateContents'] ?? '', ENT_QUOTES) ?>"> | |
| </div> | |
변경 후auto_send_config_recipient_section.php
| <div class="ncua-card__body-block-section-wrap"> | |
| <section class="ncua-card__body-block-section"> | |
| <div class="ncua-card__body-title--xs tooltip-align" data-tooltip-seq="009">내용 입력</div> | |
| <?php /* 제목은 본문이 LMS(90bytes 초과)일 때만 활성 — 토글·카운트는 JS(initMessageModules)가 담당 */ ?> | |
| <div class="message-title-field"> | |
| <div class="ncua-input ncua-input--xs is-disabled"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input name="recipients[<?= $recipient ?>][SMS][templateTitle]" type="text" | |
| value="<?= htmlspecialchars($autoSendConfig['SMS']['templateTitle'] ?? '', ENT_QUOTES) ?>" | |
| placeholder="제목을 입력해 주세요." data-sms-title-input disabled /> | |
| </div> | |
| </div> | |
| </div> | |
| <span class="message-title-count"> | |
| <span data-sms-title-current>0</span>/40 | |
| </span> | |
| </div> | |
| <div id="sms-message-input-container-<?= $recipient ?>" | |
| data-initial-value="<?= htmlspecialchars($autoSendConfig['SMS']['templateContents'] ?? '', ENT_QUOTES) ?>"> | |
| </div> | |
변경 전auto_send_config.php
| if (tabInfo.channel === 'SMS') { | |
| const input = messageInputInstances[recipient]?.SMS; | |
| const smsContent = input ? normalizeNewlines(input.getValue()) : ''; | |
| this.setPreview(section, { content: smsContent || '메시지 내용을 입력하세요.' }); | |
| } else if (tabInfo.channel === 'KAKAO_ALRIM_TALK') { | |
| const tabContent = section.querySelector('[data-tab="KAKAO_ALRIM_TALK"]'); | |
| if (!tabContent) return; | |
| // SMS/LMS 포인트 힌트 업데이트 | |
| const byteLength = smsInput.calculateLength(normalized); | |
| smsInput.setHint(byteLength > 90 ? 'LMS 건당 3포인트 차감' : 'SMS 건당 1포인트 차감'); | |
| // 빈 내용일 때 안내문구 숨김 | |
| if (normalized === '') { | |
| const caution = document.querySelector(`#sms-chip-selector-container-${recipient} [data-caution-template]`); | |
| }); | |
| messageInputInstances[recipient].SMS = smsInput; | |
| // 초기 힌트 상태 설정 | |
| const hintEl = smsContainer.querySelector('[data-message-hint]'); | |
| if (hintEl) hintEl.classList.add('destructive'); | |
변경 후auto_send_config.php
| if (tabInfo.channel === 'SMS') { | |
| const input = messageInputInstances[recipient]?.SMS; | |
| const smsContent = input ? normalizeNewlines(input.getValue()) : ''; | |
| const smsTitleInput = section.querySelector('input[data-sms-title-input]'); | |
| const smsTitle = smsTitleInput && !smsTitleInput.disabled ? smsTitleInput.value.replace(/\{[^}]*\}/g, '') : ''; | |
| this.setPreview(section, { title: smsTitle, content: smsContent || '메시지 내용을 입력하세요.' }); | |
| } else if (tabInfo.channel === 'KAKAO_ALRIM_TALK') { | |
| const tabContent = section.querySelector('[data-tab="KAKAO_ALRIM_TALK"]'); | |
| if (!tabContent) return; | |
| // SMS/LMS 포인트 힌트 업데이트 | |
| const byteLength = smsInput.calculateLength(normalized); | |
| smsInput.setHint(byteLength > 90 ? 'LMS 건당 3포인트 차감' : 'SMS 건당 1포인트 차감'); | |
| // 본문 기준 SMS/LMS 판단 — LMS 일 때만 제목 입력 활성화 | |
| setSmsTitleEnabled(byteLength > 90); | |
| // 빈 내용일 때 안내문구 숨김 | |
| if (normalized === '') { | |
| const caution = document.querySelector(`#sms-chip-selector-container-${recipient} [data-caution-template]`); | |
| }); | |
| messageInputInstances[recipient].SMS = smsInput; | |
| // ===== SMS/LMS 제목 — 본문이 LMS(90bytes 초과)일 때만 활성 (모바일 발송과 동일 규칙) ===== | |
| const SMS_TITLE_MAX_BYTES = 40; | |
| const sectionEl = smsContainer.closest('[data-target-type]'); | |
| const smsTitleInput = sectionEl.querySelector('input[data-sms-title-input]'); | |
| const smsTitleCounter = sectionEl.querySelector('[data-sms-title-current]'); | |
| // 미리보기 — LMS 상태에서 값이 있을 때만 노출, 제목은 변수 미지원이라 치환자는 공란으로 표기 | |
| const updateSmsTitlePreview = () => { | |
| if (!smsTitleInput) return; | |
| const value = !smsTitleInput.disabled ? smsTitleInput.value.replace(/\{[^}]*\}/g, '') : ''; | |
| PreviewFacade.setPreview(sectionEl, { title: value }); | |
| }; | |
| // 제목 입력 — 이모지 제거, 40bytes 초과분 자동 삭제 (byte 기준은 본문 MessageInput 과 동일) | |
| const handleSmsTitleInput = () => { | |
| if (!smsTitleInput) return; | |
| let value = smsInput.removeEmoji(smsTitleInput.value).value; | |
| value = smsInput.truncateBytes(value, SMS_TITLE_MAX_BYTES); | |
| if (smsTitleInput.value !== value) { | |
| smsTitleInput.value = value; | |
| } | |
| if (smsTitleCounter) smsTitleCounter.textContent = smsInput.getByteLength(value); | |
| updateSmsTitlePreview(); | |
| }; | |
| // SMS 로 돌아오면 값은 유지한 채 비활성 | |
| const setSmsTitleEnabled = (enabled) => { | |
| if (!smsTitleInput) return; | |
| smsTitleInput.disabled = !enabled; | |
| smsTitleInput.closest('.ncua-input').classList.toggle('is-disabled', !enabled); | |
| updateSmsTitlePreview(); | |
| }; | |
| if (smsTitleInput) { | |
| smsTitleInput.addEventListener('input', handleSmsTitleInput); | |
| // 초기 상태: 저장된 본문 byte 기준 활성 여부 + 저장된 제목 카운트 반영 | |
| setSmsTitleEnabled(smsInput.calculateLength(smsInitialValue) > 90); | |
| handleSmsTitleInput(); | |
| } | |
| // 초기 힌트 상태 설정 | |
| const hintEl = smsContainer.querySelector('[data-message-hint]'); | |
| if (hintEl) hintEl.classList.add('destructive'); | |
변경 전crm_recipe_send.php
| el.querySelector('.ncua-input__destructive-icon-wrap')?.remove(); | |
| }); | |
| const fail = (message, subMessage) => { | |
| NCDSAlert({ message, subMessage, iconType: 'error' }); | |
| $button.prop('disabled', false); | |
| allKeys.includes(MobileMessageReplaceCode.normalizeReplaceKey(key)) ? `{${key}}` : match); | |
| window.alternativeMessageInput.insertText(alternativeContents); | |
| window.alternativePreview?.setContent(alternativeContents); | |
| } | |
| sendClickLog('send'); | |
변경 후crm_recipe_send.php
| el.querySelector('.ncua-input__destructive-icon-wrap')?.remove(); | |
| }); | |
| // 제목 40byte 초과(C4-2)는 미해소 에러라 재표기 | |
| if (typeof refreshOverSmsTitleState === 'function') { | |
| refreshOverSmsTitleState(); | |
| } | |
| const fail = (message, subMessage) => { | |
| NCDSAlert({ message, subMessage, iconType: 'error' }); | |
| $button.prop('disabled', false); | |
| allKeys.includes(MobileMessageReplaceCode.normalizeReplaceKey(key)) ? `{${key}}` : match); | |
| window.alternativeMessageInput.insertText(alternativeContents); | |
| window.alternativePreview?.setContent(alternativeContents); | |
| if (typeof copyMainTitleToAlternativeSmsTitle === 'function') { | |
| copyMainTitleToAlternativeSmsTitle(); | |
| } | |
| } | |
| sendClickLog('send'); | |
변경 전layer_preview_auto_send.php
| <?php if ($channelKey === 'SMS'): ?> | |
| <!-- SMS 미리보기 --> | |
| <section data-component="sms-message-preview" class="mobile-preview mobile-preview--sms"> | |
| <div class="ncua-prev"><?= nl2br(htmlspecialchars($templateContents)) ?></div> | |
| </section> | |
| <?php elseif ($channelKey === 'KAKAO_ALRIM_TALK'): | |
변경 후layer_preview_auto_send.php
| <?php if ($channelKey === 'SMS'): ?> | |
| <!-- SMS 미리보기 --> | |
| <section data-component="sms-message-preview" class="mobile-preview mobile-preview--sms"> | |
| <div class="ncua-prev"> | |
| <?php if (($channelData['templateTitle'] ?? '') !== ''): ?> | |
| <div class="sms-title-side-preview"><?= htmlspecialchars($channelData['templateTitle']) ?></div> | |
| <?php endif; ?> | |
| <?= nl2br(htmlspecialchars($templateContents)) ?> | |
| </div> | |
| </section> | |
| <?php elseif ($channelKey === 'KAKAO_ALRIM_TALK'): | |
변경 전layer_template_contents_sms.php
| <!-- SMS/LMS --> | |
| <section class="mobile-preview mobile-preview--sms layer-preview-contents--sms"> | |
| <div class="ncua-prev"><?= nl2br(htmlspecialchars($smsData?->getContents() ?? '')) ?></div> | |
| </section> | |
변경 후layer_template_contents_sms.php
| <!-- SMS/LMS --> | |
| <section class="mobile-preview mobile-preview--sms layer-preview-contents--sms"> | |
| <div class="ncua-prev"> | |
| <?php if (($smsData?->getMessageTitle() ?? '') !== ''): ?> | |
| <div class="sms-title-side-preview"><?= htmlspecialchars($smsData->getMessageTitle()) ?></div> | |
| <?php endif; ?> | |
| <?= nl2br(htmlspecialchars($smsData?->getContents() ?? '')) ?> | |
| </div> | |
| </section> | |
변경 전message_template_register.php
| element.querySelectorAll('input, textarea, select').forEach(field => { | |
| // 체크박스로 제어되는 textarea는 제외 | |
| if (field.id === 'channelAddTextarea' || field.id === 'extraInfoTextarea') return; | |
| // 수정/복제 모드에서 발송수단, 제공사는 disabled 유지 | |
| if (field.name === 'sendMethod' || field.name === 'provider') return; | |
| field.disabled = !isVisible; | |
| }); | |
| }; | |
| /** | |
| * SMS 바이트 수에 따라 SMS/LMS 포인트 차감 힌트 텍스트 변경 | |
| */ | |
| } else { | |
| smsMessageInput.setHint(''); | |
| } | |
| }; | |
| /** | |
| } | |
| }); | |
| // 수정/복제 모드: initialValue 기준으로 SMS/LMS 힌트 초기화 | |
| updateSmsMessageHint(initialData.smsContent || ''); | |
| const smsVariableSelector = GodoUIModule.render({ | |
| type: 'ChipSelector', | |
| target: '#sms-variable-selector-container', | |
| document.querySelectorAll('#sms-message-input-container .ncua-input, #kakao-message-input-container .ncua-input, #myapp-message-input-container .ncua-input') | |
| .forEach(el => el.setAttribute('data-show-hint-text', 'true')); | |
| let templatePreview = null; | |
| window.addEventListener('crmPreviewLoaded', function() { | |
| const currentSendMethod = document.querySelector('input[name="sendMethod"]:checked')?.value || 'sms'; | |
| const sendTypeMap = { 'sms': 'SMS', 'kakao': 'ALIMTALK', 'myapp': 'MYAPP' }; | |
| } | |
| templatePreview.setContent(displayValue); | |
| } | |
| }; | |
| // 변수 변환 체크박스 이벤트 리스너 (CrmPreview 체크박스 사용) | |
| formData.append('templateCategory', document.querySelector('input[name="templateCategory"]:checked')?.value || ''); | |
| formData.append('templateTitle', document.querySelector('input[name="templateTitle"]')?.value || ''); | |
| formData.append('templateMessageContent', escapeLineBreaks(document.querySelector('textarea[name="smsMessageInput"]')?.value || '')); | |
| submitForm(); | |
| } else if (sendMethod === 'kakao') { | |
변경 후message_template_register.php
| element.querySelectorAll('input, textarea, select').forEach(field => { | |
| // 체크박스로 제어되는 textarea는 제외 | |
| if (field.id === 'channelAddTextarea' || field.id === 'extraInfoTextarea') return; | |
| // SMS 제목은 본문 LMS 여부로 활성 상태를 관리하므로 제외 | |
| if (field.name === 'templateMessageTitle') return; | |
| // 수정/복제 모드에서 발송수단, 제공사는 disabled 유지 | |
| if (field.name === 'sendMethod' || field.name === 'provider') return; | |
| field.disabled = !isVisible; | |
| }); | |
| }; | |
| // crmPreviewLoaded 이후 생성 — 선언보다 먼저 실행되는 초기화 코드(제목 미리보기 등)에서 참조하므로 여기서 선언 | |
| let templatePreview = null; | |
| /** | |
| * SMS/LMS 메시지 제목 — 본문이 LMS(90bytes 초과)일 때만 활성 (모바일 발송과 동일 정책) | |
| */ | |
| const SMS_TITLE_MAX_BYTES = 40; | |
| const getSmsTitleInput = () => document.querySelector('input[name="templateMessageTitle"]'); | |
| const isSmsTitleEnabled = () => { | |
| const input = getSmsTitleInput(); | |
| return !!input && !input.disabled; | |
| }; | |
| // 미리보기 — LMS 상태에서 값이 있을 때만 노출, 제목은 변수 미지원이라 치환자는 공란으로 표기 | |
| const updateSmsTitlePreview = () => { | |
| if (!templatePreview) return; | |
| const value = isSmsTitleEnabled() ? getSmsTitleInput().value.replace(/\{[^}]*\}/g, '') : ''; | |
| templatePreview.setTitle(value); | |
| }; | |
| // SMS 로 돌아오면 값은 유지한 채 비활성 | |
| const setSmsTitleEnabled = (enabled) => { | |
| const input = getSmsTitleInput(); | |
| if (!input) return; | |
| input.disabled = !enabled; | |
| input.closest('.ncua-input').classList.toggle('is-disabled', !enabled); | |
| updateSmsTitlePreview(); | |
| }; | |
| // 제목 입력 — 이모지 제거, 40bytes 초과분 자동 삭제 (byte 기준은 본문 MessageInput 과 동일) | |
| const handleSmsTitleInput = () => { | |
| const input = getSmsTitleInput(); | |
| let value = smsMessageInput.removeEmoji(input.value).value; | |
| value = smsMessageInput.truncateBytes(value, SMS_TITLE_MAX_BYTES); | |
| if (input.value !== value) { | |
| input.value = value; | |
| } | |
| document.querySelector('[data-sms-title-current]').textContent = smsMessageInput.getByteLength(value); | |
| updateSmsTitlePreview(); | |
| }; | |
| /** | |
| * SMS 바이트 수에 따라 SMS/LMS 포인트 차감 힌트 텍스트 변경 | |
| */ | |
| } else { | |
| smsMessageInput.setHint(''); | |
| } | |
| // 본문 기준 SMS/LMS 판단 — LMS 일 때만 제목 입력 활성화 | |
| setSmsTitleEnabled(currentBytes > 90); | |
| }; | |
| /** | |
| } | |
| }); | |
| // 수정/복제 모드: initialValue 기준으로 SMS/LMS 힌트 초기화 (제목 활성 상태 포함) | |
| updateSmsMessageHint(initialData.smsContent || ''); | |
| // 제목 입력 이벤트 + 초기 카운터 반영 (수정/복제 모드: 저장된 제목) | |
| getSmsTitleInput().addEventListener('input', handleSmsTitleInput); | |
| handleSmsTitleInput(); | |
| const smsVariableSelector = GodoUIModule.render({ | |
| type: 'ChipSelector', | |
| target: '#sms-variable-selector-container', | |
| document.querySelectorAll('#sms-message-input-container .ncua-input, #kakao-message-input-container .ncua-input, #myapp-message-input-container .ncua-input') | |
| .forEach(el => el.setAttribute('data-show-hint-text', 'true')); | |
| window.addEventListener('crmPreviewLoaded', function() { | |
| const currentSendMethod = document.querySelector('input[name="sendMethod"]:checked')?.value || 'sms'; | |
| const sendTypeMap = { 'sms': 'SMS', 'kakao': 'ALIMTALK', 'myapp': 'MYAPP' }; | |
| } | |
| templatePreview.setContent(displayValue); | |
| } | |
| if (sendMethod === 'sms') { | |
| updateSmsTitlePreview(); | |
| } | |
| }; | |
| // 변수 변환 체크박스 이벤트 리스너 (CrmPreview 체크박스 사용) | |
| formData.append('templateCategory', document.querySelector('input[name="templateCategory"]:checked')?.value || ''); | |
| formData.append('templateTitle', document.querySelector('input[name="templateTitle"]')?.value || ''); | |
| formData.append('templateMessageContent', escapeLineBreaks(document.querySelector('textarea[name="smsMessageInput"]')?.value || '')); | |
| // 제목은 SMS/LMS 여부와 무관하게 입력값이 있으면 함께 저장 (모바일 발송 템플릿 저장과 동일) | |
| formData.append('templateMessageTitle', getSmsTitleInput()?.value || ''); | |
| submitForm(); | |
| } else if (sendMethod === 'kakao') { | |
변경 전template_contents_sms.php
| <!-- 본문 입력: SMS 바이트형 --> | |
| <div class="message-content sms-byte-mode" data-component="message-content"> | |
| <div class="ncua-card__body-title-wrap ncua-required"> | |
| <p class="ncua-card__body-title--xs">본문 입력</p> | |
| </div> | |
| <div id="sms-message-input-container" class="message-input-container"></div> | |
| </div> | |
| <div class="ncua-accordion__content has-dot"> | |
| <ul> | |
| <li>URL 삽입 시 [단축 URL] 앱을 이용하시면 짧고 간단하게 URL을 사용하실 수 있습니다. <a href="https://apps.godo.co.kr/apps/1519" target="_blank" class="ncua-link-underline">바로가기</a></li> | |
| </ul> | |
| </div> | |
| </details> | |
변경 후template_contents_sms.php
| <!-- 본문 입력: SMS 바이트형 --> | |
| <div class="message-content sms-byte-mode" data-component="message-content"> | |
| <div class="ncua-card__body-title-wrap ncua-required"> | |
| <p class="ncua-card__body-title--xs tooltip-align" data-tooltip-seq="008">본문 입력</p> | |
| </div> | |
| <?php /* 제목은 본문이 LMS(90bytes 초과)일 때만 활성 — 토글은 JS(setSmsTitleEnabled)가 담당 */ ?> | |
| <div class="message-title-field"> | |
| <div class="ncua-input ncua-input--xs is-disabled"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input name="templateMessageTitle" type="text" value="<?= htmlspecialchars($response->getSms()?->getMessageTitle() ?? '') ?>" placeholder="제목을 입력해 주세요." disabled /> | |
| </div> | |
| </div> | |
| </div> | |
| <span class="message-title-count"> | |
| <span data-sms-title-current>0</span>/40 | |
| </span> | |
| </div> | |
| <div id="sms-message-input-container" class="message-input-container"></div> | |
| </div> | |
| <div class="ncua-accordion__content has-dot"> | |
| <ul> | |
| <li>URL 삽입 시 [단축 URL] 앱을 이용하시면 짧고 간단하게 URL을 사용하실 수 있습니다. <a href="https://apps.godo.co.kr/apps/1519" target="_blank" class="ncua-link-underline">바로가기</a></li> | |
| <li>제목은 LMS 발송 시에만 적용되는 선택 입력 항목으로, 미입력 시에는 ‘제목 없음’으로 발송되며 SMS 발송 시에는 포함되지 않습니다.</li> | |
| </ul> | |
| </div> | |
| </details> | |
변경 전layer_member_sms_history_result.php
| </div> | |
| </td> | |
| <td> | |
| <div class="ncua-align-items-start"><button class="ncua-left-align mobile-history-list-message-content-btn js-show-message-contents" data-send-key="<?= $smsHistory->getSendKey() ?>" type="button"><?= $smsHistory->getContent() ?></button></div> | |
| </td> | |
| <td> | |
| <div class="ncua-flex-column"><?= $smsHistory->getSenderName() ?> <span><?= $smsHistory->getFrom() ?></span></div> | |
변경 후layer_member_sms_history_result.php
| </div> | |
| </td> | |
| <td> | |
| <div class="ncua-align-items-start"><button class="ncua-left-align mobile-history-list-message-content-btn js-show-message-contents" data-send-key="<?= $smsHistory->getSendKey() ?>" type="button"><?php if (($smsHistory->getTitle() ?? '') !== ''): ?><span style="display: block;"><?= gd_htmlspecialchars($smsHistory->getTitle()) ?></span><?php endif; ?><?= $smsHistory->getContent() ?></button></div> | |
| </td> | |
| <td> | |
| <div class="ncua-flex-column"><?= $smsHistory->getSenderName() ?> <span><?= $smsHistory->getFrom() ?></span></div> | |
변경 전layer_sms_contents.php
| <div class="mobile-preview-wrap"> | |
| <section class="mobile-preview mobile-preview--sms"> | |
| <div class="ncua-prev"><?= nl2br(gd_htmlspecialchars_stripslashes($content)) ?></div> | |
| </section> | |
| </div> | |
변경 후layer_sms_contents.php
| <div class="mobile-preview-wrap"> | |
| <section class="mobile-preview mobile-preview--sms"> | |
| <div class="ncua-prev"> | |
| <?php if (($title ?? '') !== ''): ?> | |
| <div class="sms-title-side-preview"><?= gd_htmlspecialchars_stripslashes($title) ?></div> | |
| <?php endif; ?> | |
| <?= nl2br(gd_htmlspecialchars_stripslashes($content)) ?> | |
| </div> | |
| </section> | |
| </div> | |
변경 전layer_sms_history_result.php
| </div> | |
| </td> | |
| <td> | |
| <div class="ncua-align-items-start"><button class="ncua-left-align mobile-history-list-message-content-btn js-show-message-contents" data-send-key="<?= $smsHistory->getSendKey() ?>" type="button"><?= $smsHistory->getContent() ?></button></div> | |
| </td> | |
| <td> | |
| <div class="ncua-flex-column"><?= $smsHistory->getSenderName() ?> <span><?= $smsHistory->getFrom() ?></span></div> | |
변경 후layer_sms_history_result.php
| </div> | |
| </td> | |
| <td> | |
| <div class="ncua-align-items-start"><button class="ncua-left-align mobile-history-list-message-content-btn js-show-message-contents" data-send-key="<?= $smsHistory->getSendKey() ?>" type="button"><?php if (($smsHistory->getTitle() ?? '') !== ''): ?><span style="display: block;"><?= gd_htmlspecialchars($smsHistory->getTitle()) ?></span><?php endif; ?><?= $smsHistory->getContent() ?></button></div> | |
| </td> | |
| <td> | |
| <div class="ncua-flex-column"><?= $smsHistory->getSenderName() ?> <span><?= $smsHistory->getFrom() ?></span></div> | |
변경 전layer_kakao_alimtalk_content_setting.php
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS 활성 상태에서 값이 있을 때만. 미입력 시 null('제목없음' 처리는 발송 시스템 담당) | |
| function getAlternativeSmsTitleForSend() { | |
| return resolveTitleForSend(getAlternativeSmsTitleInput(), isAlternativeSmsTitleEnabled()); | |
| } | |
| <div class="message-content send-method-component" data-target="ALTERNATIVE"> | |
| <div class="ncua-card__body-title-wrap"> | |
| <p class="ncua-card__body-title--xs">내용 입력</p> | |
| <button type="button" class="ncua-btn ncua-btn--xs ncua-btn--text-gray has-underline refresh-btn load-main-contents"> | |
| 메시지 최신 상태 반영 | |
| </button> | |
| </div> | |
| <div id="messageContentAlternativeContainer"></div> | |
| </div> | |
| <div id="replaceCodeAlternativeContainer" class="send-method-component" data-target="ALTERNATIVE"></div> | |
| <ul> | |
| <li>SMS 작성 시 90byte를 초과하면 LMS로 자동 전환되어 발송됩니다.</li> | |
| <li>변수에 실제 데이터가 적용된 최종 메시지가 90byte를 초과하는 경우에도 LMS로 전환될 수 있습니다.</li> | |
| </ul> | |
| </div> | |
| </details> | |
| alternativeMessageInput.setValue(''); | |
| alternativeMessageInput.insertText(convertedMessage); | |
| alternativePreview.setContent(resolveReplaceCode(convertedMessage, false)); | |
| NCDSToast({message: '메시지가 최신 내용으로 업데이트 됐습니다.', color: 'success'}); | |
| }); | |
| } else { | |
| window.alternativeMessageInput.setHint(window.alternativeMessageInput.calculateLength(input) > 90 ? 'LMS 건당 3포인트 차감' : 'SMS 건당 1포인트 차감'); | |
| } | |
| } | |
| }); | |
| setDefaultPreview(['ALIMTALK_TEXT', 'ALTERNATIVE_TEXT']); | |
| } | |
| </script> | |
변경 후layer_kakao_alimtalk_content_setting.php
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS(제목 활성)일 때만 전송, 미입력·치환자만 입력 시 '[제목없음]' 으로 발송 | |
| function getAlternativeSmsTitleForSend() { | |
| return resolveTitleForSend(getAlternativeSmsTitleInput(), isAlternativeSmsTitleEnabled()); | |
| } | |
| <div class="message-content send-method-component" data-target="ALTERNATIVE"> | |
| <div class="ncua-card__body-title-wrap"> | |
| <p class="ncua-card__body-title--xs tooltip-align" data-tooltip-seq="010">내용 입력</p> | |
| <button type="button" class="ncua-btn ncua-btn--xs ncua-btn--text-gray has-underline refresh-btn load-main-contents"> | |
| 메시지 최신 상태 반영 | |
| </button> | |
| </div> | |
| <div class="message-title-field"> | |
| <div class="ncua-input ncua-input--xs ncua-input--full-width-with-count is-disabled"> | |
| <div class="ncua-input__content-wrap"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input name="alternativeSmsTitle" type="text" value="" placeholder="제목을 입력해 주세요." disabled /> | |
| </div> | |
| </div> | |
| <div class="ncua-input__field-text-count"> | |
| <output class="ncua-input__field-text-count-current" data-alternative-sms-title-current>0</output><span>/40</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="messageContentAlternativeContainer"></div> | |
| </div> | |
| <div id="replaceCodeAlternativeContainer" class="send-method-component" data-target="ALTERNATIVE"></div> | |
| <ul> | |
| <li>SMS 작성 시 90byte를 초과하면 LMS로 자동 전환되어 발송됩니다.</li> | |
| <li>변수에 실제 데이터가 적용된 최종 메시지가 90byte를 초과하는 경우에도 LMS로 전환될 수 있습니다.</li> | |
| <li>본문 내용이 LMS인 경우에만 제목 입력이 가능하며, 제목 영역에는 직접 (광고) 문구를 입력하지 않도록 하고 광고 삽입이 필요한 경우 광고성 문구 추가 기능을 사용해야 합니다.</li> | |
| </ul> | |
| </div> | |
| </details> | |
| alternativeMessageInput.setValue(''); | |
| alternativeMessageInput.insertText(convertedMessage); | |
| alternativePreview.setContent(resolveReplaceCode(convertedMessage, false)); | |
| copyMainTitleToAlternativeSmsTitle(); | |
| NCDSToast({message: '메시지가 최신 내용으로 업데이트 됐습니다.', color: 'success'}); | |
| }); | |
| } else { | |
| window.alternativeMessageInput.setHint(window.alternativeMessageInput.calculateLength(input) > 90 ? 'LMS 건당 3포인트 차감' : 'SMS 건당 1포인트 차감'); | |
| } | |
| // 대체 본문 기준 SMS/LMS 판단 — LMS 일 때만 제목 입력 활성화 | |
| setAlternativeSmsTitleEnabled(window.alternativeMessageInput.calculateLength(input) > 90); | |
| } | |
| }); | |
| setDefaultPreview(['ALIMTALK_TEXT', 'ALTERNATIVE_TEXT']); | |
| } | |
| </script> | |
| <script type="text/javascript"> | |
| // ===== SMS/LMS 대체 메시지 제목 (규칙·디자인은 SMS/친구톡 대체와 동일) ===== | |
| function getAlternativeSmsTitleInput() { | |
| return document.querySelector('input[name="alternativeSmsTitle"]'); | |
| } | |
| // 제목 입력 — 이모지 제거 후 40bytes 규칙 적용 (applySmsTitleByteRule) | |
| function handleAlternativeSmsTitleInput() { | |
| const input = getAlternativeSmsTitleInput(); | |
| const value = applySmsTitleByteRule(input, window.alternativeMessageInput); | |
| document.querySelector('[data-alternative-sms-title-current]').textContent = window.alternativeMessageInput.getByteLength(value); | |
| updateAlternativeSmsTitlePreview(); | |
| } | |
| // 대체 본문이 LMS(90bytes 초과)일 때만 제목 활성 — SMS 로 돌아오면 값은 유지한 채 비활성 | |
| function setAlternativeSmsTitleEnabled(enabled) { | |
| const input = getAlternativeSmsTitleInput(); | |
| if (!input) return; | |
| // 대체 미지원(캐러셀·와이드아이템 등)이면 본문 길이와 무관하게 비활성 — payload 에도 실리지 않는다 | |
| if (typeof enableAlternative === 'function' && !enableAlternative(getActivatedSendMethod())) { | |
| enabled = false; | |
| } | |
| input.disabled = !enabled; | |
| input.closest('.ncua-input').classList.toggle('is-disabled', !enabled); | |
| updateAlternativeSmsTitlePreview(); | |
| } | |
| function isAlternativeSmsTitleEnabled() { | |
| const input = getAlternativeSmsTitleInput(); | |
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS 활성 상태에서 값이 있을 때만. 미입력 시 null('제목없음' 처리는 발송 시스템 담당) | |
| function getAlternativeSmsTitleForSend() { | |
| return resolveTitleForSend(getAlternativeSmsTitleInput(), isAlternativeSmsTitleEnabled()); | |
| } | |
| // 미리보기 — LMS 상태에서 값이 있을 때만 노출, 치환자는 공란으로 표기 | |
| function updateAlternativeSmsTitlePreview() { | |
| window.alternativePreview.setTitle(isAlternativeSmsTitleEnabled() ? stripTitleReplaceCodes(getAlternativeSmsTitleInput().value) : ''); | |
| } | |
| // 메인 제목 → 대체 제목 매핑 — 알림톡은 강조표기형(templateTitle)만 매핑 대상 | |
| function copyMainTitleToAlternativeSmsTitle() { | |
| const input = getAlternativeSmsTitleInput(); | |
| if (!input || getActivatedSendMethod() !== 'ALIMTALK') return; | |
| input.value = getSelectedKakaoAlimtalkTemplate()?.templateTitle ?? ''; | |
| // 본문 카피 직후엔 입력 이벤트가 없어 활성 상태가 갱신되지 않는다 — 여기서 다시 잡아야 payload 에 실린다 | |
| setAlternativeSmsTitleEnabled(window.alternativeMessageInput.calculateLength(window.alternativeMessageInput.getValue() ?? '') > 90); | |
| handleAlternativeSmsTitleInput(); | |
| } | |
| getAlternativeSmsTitleInput().addEventListener('input', handleAlternativeSmsTitleInput); | |
| </script> | |
변경 전layer_kakao_friendtalk_content_setting.php
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS 활성 상태에서 값이 있을 때만. 미입력 시 null('제목없음' 처리는 발송 시스템 담당) | |
| function getAlternativeSmsTitleForSend() { | |
| return resolveTitleForSend(getAlternativeSmsTitleInput(), isAlternativeSmsTitleEnabled()); | |
| } | |
| <div class="message-content send-method-component" data-target="ALTERNATIVE"> | |
| <div class="ncua-card__body-title-wrap"> | |
| <p class="ncua-card__body-title--xs">내용 입력</p> | |
| <button type="button" class="ncua-btn ncua-btn--xs ncua-btn--text-gray has-underline refresh-btn load-main-contents"> | |
| 메시지 최신 상태 반영 | |
| </button> | |
| </div> | |
| <div id="messageContentAlternativeContainer"></div> | |
| </div> | |
| <div id="replaceCodeAlternativeContainer" class="js-replace-code send-method-component" data-target="ALTERNATIVE"></div> | |
| <ul> | |
| <li>SMS 작성 시 90byte를 초과하면 LMS로 자동 전환되어 발송됩니다.</li> | |
| <li>변수에 실제 데이터가 적용된 최종 메시지가 90byte를 초과하는 경우에도 LMS로 전환될 수 있습니다.</li> | |
| </ul> | |
| </div> | |
| </details> | |
| updateCampaignTypeComponent(radio.value); | |
| updateDefaultPreview(radio.value); | |
| applyFriendtalkRecipeDefaults(radio.value); | |
| }); | |
| }); | |
| } | |
| }); | |
| kakaoFriendtalkTabSection.querySelector('input[name="friendtalkCampaignHeader"]').addEventListener('input', function(e) { | |
| window.preview.setTitle(resolveReplaceCode(e.target.value)); | |
| if (e.target.value === '') { | |
| const initialTextContent = <?= json_encode($initialTextContent ?? '', JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP) ?>; | |
| const initialAlternativeMessage = <?= json_encode($initialAlternativeMessage ?? '', JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP) ?>; | |
| if (isRecipeContext) { | |
| const wideItemPointHint = kakaoFriendtalkTabSection.querySelector('.js-wide-item-point-hint'); | |
| } else { | |
| window.alternativeMessageInput.setHint(window.alternativeMessageInput.calculateLength(input) > 90 ? 'LMS 건당 3포인트 차감' : 'SMS 건당 1포인트 차감'); | |
| } | |
| } | |
| }); | |
| MobileMessageReplaceCode.updateExpireCodeGuide('#replaceCodeAlternativeContainer', initialAlternativeMessage); | |
| } | |
| applyFriendtalkRecipeDefaults(getCampaignMessageType()); | |
| } | |
| updateItemListPreview(); | |
| } | |
| // 친구톡 아이템 이미지 업로드 초기화 | |
| function initItemImageFileInput(containerId, itemKey, isFirst = false) { | |
| const container = document.getElementById(containerId); | |
변경 후layer_kakao_friendtalk_content_setting.php
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS(제목 활성)일 때만 전송, 미입력·치환자만 입력 시 '[제목없음]' 으로 발송 | |
| function getAlternativeSmsTitleForSend() { | |
| return resolveTitleForSend(getAlternativeSmsTitleInput(), isAlternativeSmsTitleEnabled()); | |
| } | |
| <div class="message-content send-method-component" data-target="ALTERNATIVE"> | |
| <div class="ncua-card__body-title-wrap"> | |
| <p class="ncua-card__body-title--xs tooltip-align" data-tooltip-seq="010">내용 입력</p> | |
| <button type="button" class="ncua-btn ncua-btn--xs ncua-btn--text-gray has-underline refresh-btn load-main-contents"> | |
| 메시지 최신 상태 반영 | |
| </button> | |
| </div> | |
| <div class="message-title-field"> | |
| <div class="ncua-input ncua-input--xs ncua-input--full-width-with-count is-disabled"> | |
| <div class="ncua-input__content-wrap"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input name="alternativeSmsTitle" type="text" value="" placeholder="제목을 입력해 주세요." disabled /> | |
| </div> | |
| </div> | |
| <div class="ncua-input__field-text-count"> | |
| <output class="ncua-input__field-text-count-current" data-alternative-sms-title-current>0</output><span>/40</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="messageContentAlternativeContainer"></div> | |
| </div> | |
| <div id="replaceCodeAlternativeContainer" class="js-replace-code send-method-component" data-target="ALTERNATIVE"></div> | |
| <ul> | |
| <li>SMS 작성 시 90byte를 초과하면 LMS로 자동 전환되어 발송됩니다.</li> | |
| <li>변수에 실제 데이터가 적용된 최종 메시지가 90byte를 초과하는 경우에도 LMS로 전환될 수 있습니다.</li> | |
| <li>본문 내용이 LMS인 경우에만 제목 입력이 가능하며, 제목 영역에는 직접 (광고) 문구를 입력하지 않도록 하고 광고 삽입이 필요한 경우 광고성 문구 추가 기능을 사용해야 합니다.</li> | |
| </ul> | |
| </div> | |
| </details> | |
| updateCampaignTypeComponent(radio.value); | |
| updateDefaultPreview(radio.value); | |
| applyFriendtalkRecipeDefaults(radio.value); | |
| // 유형에 따라 대체 지원 여부가 바뀌므로 제목 활성 상태를 다시 평가 (초기 change 는 대체 입력 생성 전이라 건너뜀) | |
| if (window.alternativeMessageInput) { | |
| setAlternativeSmsTitleEnabled(window.alternativeMessageInput.calculateLength(window.alternativeMessageInput.getValue() ?? '') > 90); | |
| } | |
| }); | |
| }); | |
| } | |
| }); | |
| getAlternativeSmsTitleInput().addEventListener('input', handleAlternativeSmsTitleInput); | |
| kakaoFriendtalkTabSection.querySelector('input[name="friendtalkCampaignHeader"]').addEventListener('input', function(e) { | |
| window.preview.setTitle(resolveReplaceCode(e.target.value)); | |
| if (e.target.value === '') { | |
| const initialTextContent = <?= json_encode($initialTextContent ?? '', JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP) ?>; | |
| const initialAlternativeMessage = <?= json_encode($initialAlternativeMessage ?? '', JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP) ?>; | |
| const initialAlternativeTitle = <?= json_encode($initialAlternativeTitle ?? '', JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP) ?>; | |
| if (isRecipeContext) { | |
| const wideItemPointHint = kakaoFriendtalkTabSection.querySelector('.js-wide-item-point-hint'); | |
| } else { | |
| window.alternativeMessageInput.setHint(window.alternativeMessageInput.calculateLength(input) > 90 ? 'LMS 건당 3포인트 차감' : 'SMS 건당 1포인트 차감'); | |
| } | |
| // 대체 본문 기준 SMS/LMS 판단 — LMS 일 때만 제목 입력 활성화 | |
| setAlternativeSmsTitleEnabled(window.alternativeMessageInput.calculateLength(input) > 90); | |
| } | |
| }); | |
| MobileMessageReplaceCode.updateExpireCodeGuide('#replaceCodeAlternativeContainer', initialAlternativeMessage); | |
| } | |
| // 레시피 기본 대체 제목 prefill — 대체 본문이 LMS면 활성 노출, SMS면 값만 유지한 채 비활성 (메인 SMS 레이어와 동일) | |
| if (initialAlternativeTitle !== '') { | |
| getAlternativeSmsTitleInput().value = initialAlternativeTitle; | |
| setAlternativeSmsTitleEnabled(window.alternativeMessageInput.calculateLength(initialAlternativeMessage) > 90); | |
| handleAlternativeSmsTitleInput(); | |
| } | |
| applyFriendtalkRecipeDefaults(getCampaignMessageType()); | |
| } | |
| updateItemListPreview(); | |
| } | |
| // ===== SMS/LMS 대체 메시지 제목 (규칙은 SMS 레이어의 제목과 동일) ===== | |
| function getAlternativeSmsTitleInput() { | |
| return kakaoFriendtalkTabSection.querySelector('input[name="alternativeSmsTitle"]'); | |
| } | |
| // 제목 입력 — 이모지 제거 후 40bytes 규칙 적용 (applySmsTitleByteRule) | |
| function handleAlternativeSmsTitleInput() { | |
| const input = getAlternativeSmsTitleInput(); | |
| const value = applySmsTitleByteRule(input, window.alternativeMessageInput); | |
| kakaoFriendtalkTabSection.querySelector('[data-alternative-sms-title-current]').textContent = window.alternativeMessageInput.getByteLength(value); | |
| updateAlternativeSmsTitlePreview(); | |
| } | |
| // 대체 본문이 LMS(90bytes 초과)일 때만 제목 활성 — SMS 로 돌아오면 값은 유지한 채 비활성 | |
| function setAlternativeSmsTitleEnabled(enabled) { | |
| const input = getAlternativeSmsTitleInput(); | |
| // 대체 미지원(캐러셀·와이드아이템 등)이면 본문 길이와 무관하게 비활성 — payload 에도 실리지 않는다 | |
| if (typeof enableAlternative === 'function' && !enableAlternative(getActivatedSendMethod())) { | |
| enabled = false; | |
| } | |
| input.disabled = !enabled; | |
| input.closest('.ncua-input').classList.toggle('is-disabled', !enabled); | |
| updateAlternativeSmsTitlePreview(); | |
| } | |
| function isAlternativeSmsTitleEnabled() { | |
| const input = getAlternativeSmsTitleInput(); | |
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS 활성 상태에서 값이 있을 때만. 미입력 시 null('제목없음' 처리는 발송 시스템 담당) | |
| function getAlternativeSmsTitleForSend() { | |
| return resolveTitleForSend(getAlternativeSmsTitleInput(), isAlternativeSmsTitleEnabled()); | |
| } | |
| // 미리보기 — LMS 상태에서 값이 있을 때만 노출, 치환자는 공란으로 표기 | |
| function updateAlternativeSmsTitlePreview() { | |
| window.alternativePreview.setTitle(isAlternativeSmsTitleEnabled() ? stripTitleReplaceCodes(getAlternativeSmsTitleInput().value) : ''); | |
| } | |
| // 친구톡 아이템 이미지 업로드 초기화 | |
| function initItemImageFileInput(containerId, itemKey, isFirst = false) { | |
| const container = document.getElementById(containerId); | |
변경 전layer_mobile_send_save_sms_template.php
| <div class="modal-dialog__content layer-save-as-template"> | |
| <input type="hidden" id="templateContents" value="<?= htmlspecialchars($contents, ENT_QUOTES) ?>" /> | |
| <div class="ncua-table ncua-table--vertical"> | |
| <table> | |
| <tbody> | |
| mode: 'save', | |
| category: category.value, | |
| subject: subject.value.trim(), | |
| contents: contents.value | |
| }, function(response) { | |
| if (response.success) { | |
| NCDSToast({ message: '저장되었습니다.', color: 'success' }); | |
변경 후layer_mobile_send_save_sms_template.php
| <div class="modal-dialog__content layer-save-as-template"> | |
| <input type="hidden" id="templateContents" value="<?= htmlspecialchars($contents, ENT_QUOTES) ?>" /> | |
| <input type="hidden" id="templateMessageTitle" value="<?= htmlspecialchars($messageTitle ?? '', ENT_QUOTES) ?>" /> | |
| <div class="ncua-table ncua-table--vertical"> | |
| <table> | |
| <tbody> | |
| mode: 'save', | |
| category: category.value, | |
| subject: subject.value.trim(), | |
| contents: contents.value, | |
| messageTitle: document.querySelector('#templateMessageTitle').value | |
| }, function(response) { | |
| if (response.success) { | |
| NCDSToast({ message: '저장되었습니다.', color: 'success' }); | |
변경 전layer_mobile_send_sms_template.php
| } | |
| } | |
| function applyTemplateSmsContents(contents) { | |
| const convertedContents = contents | |
| .replace(/\\r\\n/g, '\n') | |
| .replace(/\\n/g, '\n'); | |
| setTemplate(convertedContents); | |
| } | |
| document.getElementById('btnSearch').addEventListener('click', function() { | |
| return; | |
| } | |
| applyTemplateSmsContents(selected.dataset.contents); | |
| layer_close(); | |
| }); | |
변경 후layer_mobile_send_sms_template.php
| } | |
| } | |
| function applyTemplateSmsContents(contents, messageTitle = '') { | |
| const convertedContents = contents | |
| .replace(/\\r\\n/g, '\n') | |
| .replace(/\\n/g, '\n'); | |
| setTemplate(convertedContents, messageTitle); | |
| } | |
| document.getElementById('btnSearch').addEventListener('click', function() { | |
| return; | |
| } | |
| applyTemplateSmsContents(selected.dataset.contents, selected.dataset.messageTitle ?? ''); | |
| layer_close(); | |
| }); | |
변경 전layer_mobile_send_sms_template_result.php
| <div class="ncua-align-center"> | |
| <label class="ncua-radio-field ncua-radio-field--xs"> | |
| <span class="ncua-radio-input ncua-radio-input--xs ncua-radio-field__input"> | |
| <input type="radio" name="template" value="<?= $template['sno'] ?>" data-contents="<?= htmlspecialchars($template['contents'], ENT_QUOTES) ?>"/> | |
| </span> | |
| </label> | |
| </div> | |
| </td> | |
| <td><div><?= nl2br(htmlspecialchars(str_replace(['\r\n', '\n'], "\n", $template['subject'] ?? ''))) ?></div></td> | |
| <td><div><?= nl2br(htmlspecialchars(str_replace(['\r\n', '\n'], "\n", $template['contents'] ?? ''))) ?></div></td> | |
| </tr> | |
| <?php endforeach; ?> | |
| <?php endif; ?> | |
변경 후layer_mobile_send_sms_template_result.php
| <div class="ncua-align-center"> | |
| <label class="ncua-radio-field ncua-radio-field--xs"> | |
| <span class="ncua-radio-input ncua-radio-input--xs ncua-radio-field__input"> | |
| <input type="radio" name="template" value="<?= $template['sno'] ?>" data-contents="<?= htmlspecialchars($template['contents'], ENT_QUOTES) ?>" data-message-title="<?= htmlspecialchars($template['messageTitle'] ?? '', ENT_QUOTES) ?>"/> | |
| </span> | |
| </label> | |
| </div> | |
| </td> | |
| <td><div><?= nl2br(htmlspecialchars(str_replace(['\r\n', '\n'], "\n", $template['subject'] ?? ''))) ?></div></td> | |
| <td> | |
| <?php /* td > div 가 flex 컨테이너라 제목·내용을 하나의 블록으로 감싸야 분리되지 않음 */ ?> | |
| <div> | |
| <div><?php if (($template['messageTitle'] ?? '') !== ''): ?><strong style="display: block;"><?= htmlspecialchars($template['messageTitle']) ?></strong><?php endif; ?><?= nl2br(htmlspecialchars(str_replace(['\r\n', '\n'], "\n", $template['contents'] ?? ''))) ?></div> | |
| </div> | |
| </td> | |
| </tr> | |
| <?php endforeach; ?> | |
| <?php endif; ?> | |
변경 전layer_myapp_push_content_setting.php
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS 활성 상태에서 값이 있을 때만. 미입력 시 null('제목없음' 처리는 발송 시스템 담당) | |
| function getAlternativeSmsTitleForSend() { | |
| return resolveTitleForSend(getAlternativeSmsTitleInput(), isAlternativeSmsTitleEnabled()); | |
| } | |
| <div class="message-content send-method-component" data-target="ALTERNATIVE"> | |
| <div class="ncua-card__body-title-wrap"> | |
| <p class="ncua-card__body-title--xs">내용 입력</p> | |
| <button type="button" class="ncua-btn ncua-btn--xs ncua-btn--text-gray has-underline refresh-btn load-main-contents"> | |
| 메시지 최신 상태 반영 | |
| </button> | |
| </div> | |
| <div id="messageContentAlternativeContainer"></div> | |
| </div> | |
| <div id="replaceCodeAlternativeContainer" class="send-method-component" data-target="ALTERNATIVE"></div> | |
| <ul> | |
| <li>SMS 작성 시 90byte를 초과하면 LMS로 자동 전환되어 발송됩니다.</li> | |
| <li>변수에 실제 데이터가 적용된 최종 메시지가 90byte를 초과하는 경우에도 LMS로 전환될 수 있습니다.</li> | |
| </ul> | |
| </div> | |
| </details> | |
| alternativeMessageInput.setValue(''); | |
| alternativeMessageInput.insertText(convertedMessage); | |
| alternativePreview.setContent(resolveReplaceCode(convertedMessage, false)); | |
| NCDSToast({message: '메시지가 최신 내용으로 업데이트 됐습니다.', color: 'success'}); | |
| }); | |
| } else { | |
| window.alternativeMessageInput.setHint(window.alternativeMessageInput.calculateLength(input) > 90 ? 'LMS 건당 3포인트 차감' : 'SMS 건당 1포인트 차감'); | |
| } | |
| } | |
| }); | |
| window.alternativePreview.setContent(resolveReplaceCode(initialAlternativeMessage, false)); | |
| MobileMessageReplaceCode.updateExpireCodeGuide('#replaceCodeAlternativeContainer', initialAlternativeMessage); | |
| } | |
| syncMyappTitlePreview(initialMyappTitle); | |
| syncMyappMessagePreview(initialMyappMessage); | |
| } | |
| }); | |
| }); | |
| </script> | |
변경 후layer_myapp_push_content_setting.php
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS(제목 활성)일 때만 전송, 미입력·치환자만 입력 시 '[제목없음]' 으로 발송 | |
| function getAlternativeSmsTitleForSend() { | |
| return resolveTitleForSend(getAlternativeSmsTitleInput(), isAlternativeSmsTitleEnabled()); | |
| } | |
| <div class="message-content send-method-component" data-target="ALTERNATIVE"> | |
| <div class="ncua-card__body-title-wrap"> | |
| <p class="ncua-card__body-title--xs tooltip-align" data-tooltip-seq="010">내용 입력</p> | |
| <button type="button" class="ncua-btn ncua-btn--xs ncua-btn--text-gray has-underline refresh-btn load-main-contents"> | |
| 메시지 최신 상태 반영 | |
| </button> | |
| </div> | |
| <div class="message-title-field"> | |
| <div class="ncua-input ncua-input--xs ncua-input--full-width-with-count is-disabled"> | |
| <div class="ncua-input__content-wrap"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input name="alternativeSmsTitle" type="text" value="" placeholder="제목을 입력해 주세요." disabled /> | |
| </div> | |
| </div> | |
| <div class="ncua-input__field-text-count"> | |
| <output class="ncua-input__field-text-count-current" data-alternative-sms-title-current>0</output><span>/40</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="messageContentAlternativeContainer"></div> | |
| </div> | |
| <div id="replaceCodeAlternativeContainer" class="send-method-component" data-target="ALTERNATIVE"></div> | |
| <ul> | |
| <li>SMS 작성 시 90byte를 초과하면 LMS로 자동 전환되어 발송됩니다.</li> | |
| <li>변수에 실제 데이터가 적용된 최종 메시지가 90byte를 초과하는 경우에도 LMS로 전환될 수 있습니다.</li> | |
| <li>본문 내용이 LMS인 경우에만 제목 입력이 가능하며, 제목 영역에는 직접 (광고) 문구를 입력하지 않도록 하고 광고 삽입이 필요한 경우 광고성 문구 추가 기능을 사용해야 합니다.</li> | |
| </ul> | |
| </div> | |
| </details> | |
| alternativeMessageInput.setValue(''); | |
| alternativeMessageInput.insertText(convertedMessage); | |
| alternativePreview.setContent(resolveReplaceCode(convertedMessage, false)); | |
| copyMainTitleToAlternativeSmsTitle(); | |
| NCDSToast({message: '메시지가 최신 내용으로 업데이트 됐습니다.', color: 'success'}); | |
| }); | |
| } else { | |
| window.alternativeMessageInput.setHint(window.alternativeMessageInput.calculateLength(input) > 90 ? 'LMS 건당 3포인트 차감' : 'SMS 건당 1포인트 차감'); | |
| } | |
| // 대체 본문 기준 SMS/LMS 판단 — LMS 일 때만 제목 입력 활성화 | |
| setAlternativeSmsTitleEnabled(window.alternativeMessageInput.calculateLength(input) > 90); | |
| } | |
| }); | |
| window.alternativePreview.setContent(resolveReplaceCode(initialAlternativeMessage, false)); | |
| MobileMessageReplaceCode.updateExpireCodeGuide('#replaceCodeAlternativeContainer', initialAlternativeMessage); | |
| } | |
| syncMyappTitlePreview(initialMyappTitle); | |
| syncMyappMessagePreview(initialMyappMessage); | |
| } | |
| }); | |
| }); | |
| </script> | |
| <script type="text/javascript"> | |
| // ===== SMS/LMS 대체 메시지 제목 (규칙·디자인은 SMS/친구톡 대체와 동일) ===== | |
| function getAlternativeSmsTitleInput() { | |
| return document.querySelector('input[name="alternativeSmsTitle"]'); | |
| } | |
| // 제목 입력 — 이모지 제거 후 40bytes 규칙 적용 (applySmsTitleByteRule) | |
| function handleAlternativeSmsTitleInput() { | |
| const input = getAlternativeSmsTitleInput(); | |
| const value = applySmsTitleByteRule(input, window.alternativeMessageInput); | |
| document.querySelector('[data-alternative-sms-title-current]').textContent = window.alternativeMessageInput.getByteLength(value); | |
| updateAlternativeSmsTitlePreview(); | |
| } | |
| // 대체 본문이 LMS(90bytes 초과)일 때만 제목 활성 — SMS 로 돌아오면 값은 유지한 채 비활성 | |
| function setAlternativeSmsTitleEnabled(enabled) { | |
| const input = getAlternativeSmsTitleInput(); | |
| if (!input) return; | |
| // 대체 미지원(캐러셀·와이드아이템 등)이면 본문 길이와 무관하게 비활성 — payload 에도 실리지 않는다 | |
| if (typeof enableAlternative === 'function' && !enableAlternative(getActivatedSendMethod())) { | |
| enabled = false; | |
| } | |
| input.disabled = !enabled; | |
| input.closest('.ncua-input').classList.toggle('is-disabled', !enabled); | |
| updateAlternativeSmsTitlePreview(); | |
| } | |
| function isAlternativeSmsTitleEnabled() { | |
| const input = getAlternativeSmsTitleInput(); | |
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS 활성 상태에서 값이 있을 때만. 미입력 시 null('제목없음' 처리는 발송 시스템 담당) | |
| function getAlternativeSmsTitleForSend() { | |
| return resolveTitleForSend(getAlternativeSmsTitleInput(), isAlternativeSmsTitleEnabled()); | |
| } | |
| // 미리보기 — LMS 상태에서 값이 있을 때만 노출, 치환자는 공란으로 표기 | |
| function updateAlternativeSmsTitlePreview() { | |
| window.alternativePreview.setTitle(isAlternativeSmsTitleEnabled() ? stripTitleReplaceCodes(getAlternativeSmsTitleInput().value) : ''); | |
| } | |
| function copyMainTitleToAlternativeSmsTitle() { | |
| const input = getAlternativeSmsTitleInput(); | |
| if (!input || getActivatedSendMethod() !== 'MYAPP') return; | |
| input.value = document.querySelector('input[name="myappTitle"]')?.value ?? ''; | |
| handleAlternativeSmsTitleInput(); | |
| } | |
| getAlternativeSmsTitleInput().addEventListener('input', handleAlternativeSmsTitleInput); | |
| // 레시피 기본 대체 제목 prefill — 대체 본문이 LMS면 활성 노출, SMS면 값만 유지한 채 비활성. | |
| // 제목 접근자가 이 블록에 선언돼 있어(앞 블록의 초기화 시점엔 미정의) 여기서 수행한다. | |
| (function () { | |
| const initialAlternativeTitle = <?= json_encode($initialAlternativeTitle ?? '', JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP) ?>; | |
| if (initialAlternativeTitle === '') return; | |
| getAlternativeSmsTitleInput().value = initialAlternativeTitle; | |
| setAlternativeSmsTitleEnabled(window.alternativeMessageInput.calculateLength(window.alternativeMessageInput.getValue() ?? '') > 90); | |
| handleAlternativeSmsTitleInput(); | |
| })(); | |
| </script> | |
변경 전layer_send_method_setting.php
| previewContainer.setContent(resolveReplaceCode(content)); | |
| dispatchMessageContentInput(messageContainer); | |
| // 본문 갱신으로 SMS/LMS 판정이 끝난 뒤, LMS(제목 활성)면 제목에도 (광고) 삽입 — 제목 40bytes 에 카운트됨 | |
| const titleInput = resolveAdTitleInput(messageContainer); | |
| if (titleInput && !titleInput.disabled && !titleInput.value.startsWith('(광고)')) { | |
| titleInput.value = '(광고)' + titleInput.value; | |
| titleInput.dataset.titleAdInsert = '1'; // 시스템 삽입 표시 — 절삭 대신 에러 처리 (C4-2) | |
| titleInput.dispatchEvent(new Event('input')); | |
| return /^https?:\/\//.test(string); | |
| } | |
| function addAdText(messageContainer, previewContainer) { | |
| const content = '(광고)\n' + messageContainer.getValue() + '\n' + smsRejectText; | |
| messageContainer.setValue(content); | |
| previewContainer.setContent(resolveReplaceCode(content)); | |
| } | |
| function removeAdText(messageContainer, previewContainer) { | |
| let content = messageContainer.getValue(); | |
| content = content.replace(/^\(광고\)\n?/, ''); | |
| const escapedRejectText = smsRejectText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); | |
| } | |
| messageContainer.setValue(content); | |
| previewContainer.setContent(resolveReplaceCode(content)); | |
| } | |
| /** | |
변경 후layer_send_method_setting.php
| previewContainer.setContent(resolveReplaceCode(content)); | |
| dispatchMessageContentInput(messageContainer); | |
| // 제목에도 (광고) 삽입 — 제목 영역이 비활성(SMS)이어도 삽입한다(레거시 동작과 동일). 제목 40bytes 에 카운트됨 | |
| const titleInput = resolveAdTitleInput(messageContainer); | |
| if (titleInput && !titleInput.value.startsWith('(광고)')) { | |
| titleInput.value = '(광고)' + titleInput.value; | |
| titleInput.dataset.titleAdInsert = '1'; // 시스템 삽입 표시 — 절삭 대신 에러 처리 (C4-2) | |
| titleInput.dispatchEvent(new Event('input')); | |
| return /^https?:\/\//.test(string); | |
| } | |
| // LMS 제목 최대 byte — 직접 입력 초과는 절삭(C1-1), (광고) 삽입 초과는 에러 유지(C4-2) | |
| const SMS_TITLE_MAX_BYTES = 40; | |
| // 제목 인풋과 같은 탭의 '광고성 문구 추가' 체크박스 | |
| function getAdCheckboxForTitle(titleInput) { | |
| for (let node = titleInput.parentElement; node; node = node.parentElement) { | |
| const checkbox = node.querySelector('input[name="use080Reject"]'); | |
| if (checkbox) return checkbox; | |
| } | |
| return null; | |
| } | |
| // 초과 에러 표기 — destructive 로 테두리·byte 카운터가 함께 빨간색이 된다 | |
| function setSmsTitleOverState(titleInput, isOver) { | |
| titleInput.classList.toggle('js-title-over', isOver); | |
| if (isOver) { | |
| NCDSValidator.highlight(titleInput); | |
| } else { | |
| NCDSValidator.unhighlight(titleInput); | |
| } | |
| } | |
| // 제목 byte 규칙 적용(이모지 제거 포함) 후 최종 값 반환 | |
| function applySmsTitleByteRule(titleInput, messageInputModule) { | |
| let value = messageInputModule.removeEmoji(titleInput.value).value; | |
| const isOver = messageInputModule.getByteLength(value) > SMS_TITLE_MAX_BYTES; | |
| // addAdText 가 (광고) 삽입 시에만 세우는 1회성 플래그 (사용자 타이핑과 구분) | |
| const adInserted = titleInput.dataset.titleAdInsert === '1'; | |
| const base = titleInput.dataset.titleOverBase; | |
| let caret = null; | |
| delete titleInput.dataset.titleAdInsert; | |
| if (isOver && (adInserted || base !== undefined)) { | |
| // C4-2 — 절삭하지 않는다. 초과 상태에서는 늘리는 입력만 되돌리고 삭제는 허용 | |
| if (!adInserted && base !== undefined && messageInputModule.getByteLength(value) > messageInputModule.getByteLength(base)) { | |
| // 되돌린 만큼 커서를 입력 직전 위치로 복원 | |
| caret = Math.max(0, (titleInput.selectionStart ?? value.length) - (value.length - base.length)); | |
| value = base; | |
| } | |
| titleInput.dataset.titleOverBase = value; | |
| setSmsTitleOverState(titleInput, true); | |
| } else { | |
| // C1-1 — 직접 입력 초과는 (광고) 체크 여부와 무관하게 자동 절삭 | |
| value = messageInputModule.truncateBytes(value, SMS_TITLE_MAX_BYTES); | |
| delete titleInput.dataset.titleOverBase; | |
| setSmsTitleOverState(titleInput, false); | |
| } | |
| if (titleInput.value !== value) { | |
| titleInput.value = value; | |
| if (caret !== null) { | |
| titleInput.setSelectionRange(caret, caret); | |
| } | |
| } | |
| return value; | |
| } | |
| // 발송 버튼의 .destructive 일괄 초기화(mobile_send.php) 후 미해소 에러 재표기 | |
| function refreshOverSmsTitleState() { | |
| document.querySelectorAll('input[name="smsTitle"], input[name="alternativeSmsTitle"]') | |
| .forEach(input => { | |
| if (input.classList.contains('js-title-over')) { | |
| setSmsTitleOverState(input, true); | |
| } | |
| }); | |
| } | |
| // 초과 제목이 숨은 탭에 있으면 그 탭으로 전환해 에러 표시를 보이게 한다 | |
| function revealSmsTitleInput(input) { | |
| const target = input.closest('.send-method-component')?.dataset.target; | |
| const tabButton = target | |
| ? document.querySelector(`.ncua-tab-button[data-send-tab-type="${target}"]`) | |
| : null; | |
| if (tabButton && !tabButton.classList.contains('is-active')) { | |
| tabButton.click(); | |
| } | |
| NCDSValidator.highlight(input); | |
| input.focus(); | |
| input.scrollIntoView({ block: 'center' }); | |
| } | |
| // 발송 차단 검사용 — payload 에 실리는 기준(disabled)과 동일하게 판정한다. | |
| // 가시성으로 거르면 탭을 옮겨 숨겨진 제목이 검사를 건너뛴 채 전송된다. | |
| function findOverSmsTitleInput() { | |
| const titleInputs = document.querySelectorAll('input[name="smsTitle"], input[name="alternativeSmsTitle"]'); | |
| return Array.from(titleInputs) | |
| .find(input => !input.disabled && input.classList.contains('js-title-over')) ?? null; | |
| } | |
| function addAdText(messageContainer, previewContainer) { | |
| // 본문은 SMS/LMS 공통으로 (광고) 삽입 | |
| const content = '(광고)\n' + messageContainer.getValue() + '\n' + smsRejectText; | |
| messageContainer.setValue(content); | |
| previewContainer.setContent(resolveReplaceCode(content)); | |
| dispatchMessageContentInput(messageContainer); | |
| // 본문 갱신으로 SMS/LMS 판정이 끝난 뒤, LMS(제목 활성)면 제목에도 (광고) 삽입 — 제목 40bytes 에 카운트됨 | |
| const titleInput = resolveAdTitleInput(messageContainer); | |
| if (titleInput && !titleInput.disabled && !titleInput.value.startsWith('(광고)')) { | |
| titleInput.value = '(광고)' + titleInput.value; | |
| titleInput.dataset.titleAdInsert = '1'; // 시스템 삽입 표시 — 절삭 대신 에러 처리 (C4-2) | |
| titleInput.dispatchEvent(new Event('input')); | |
| // 초과했다면 해당 영역으로 포커싱 | |
| if (titleInput.classList.contains('js-title-over')) { | |
| titleInput.focus(); | |
| } | |
| } | |
| } | |
| function removeAdText(messageContainer, previewContainer) { | |
| const titleInput = resolveAdTitleInput(messageContainer); | |
| if (titleInput && titleInput.value.startsWith('(광고)')) { | |
| titleInput.value = titleInput.value.replace(/^\(광고\)/, ''); | |
| titleInput.dispatchEvent(new Event('input')); | |
| } | |
| let content = messageContainer.getValue(); | |
| content = content.replace(/^\(광고\)\n?/, ''); | |
| const escapedRejectText = smsRejectText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); | |
| } | |
| messageContainer.setValue(content); | |
| previewContainer.setContent(resolveReplaceCode(content)); | |
| dispatchMessageContentInput(messageContainer); | |
| } | |
| // 광고 문구가 들어갈 제목 인풋 — 대체 메시지 컨테이너면 대체 제목, 아니면 메인 제목 | |
| function resolveAdTitleInput(messageContainer) { | |
| return messageContainer === window.alternativeMessageInput | |
| ? document.querySelector('input[name="alternativeSmsTitle"]') | |
| : document.querySelector('input[name="smsTitle"]'); | |
| } | |
| // setValue 는 MessageInput 의 onInput 콜백을 부르지 않으므로, 본문 변경 후 | |
| // SMS/LMS 판단(제목 활성 토글·힌트 갱신)이 다시 돌도록 input 이벤트를 수동 발행 | |
| function dispatchMessageContentInput(messageContainer) { | |
| const name = messageContainer === window.alternativeMessageInput ? 'messageAlternativeContent' : 'messageContent'; | |
| document.querySelector(`textarea[name="${name}"]`)?.dispatchEvent(new Event('input')); | |
| } | |
| /** | |
변경 전layer_sms_content_setting.php
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS 활성 상태에서 값이 있을 때만. 미입력 시 null('제목없음' 처리는 발송 시스템 담당) | |
| function getSmsTitleForSend() { | |
| return resolveTitleForSend(getSmsTitleInput(), isSmsTitleEnabled()); | |
| } | |
| <div class="tab-content-wrap"> | |
| <div class="message-content"> | |
| <div class="ncua-card__body-title-wrap"> | |
| <p class="ncua-card__body-title--xs">내용 입력</p> | |
| </div> | |
| <div id="messageContentContainer"></div> | |
| </div> | |
| <ul> | |
| <li>SMS 작성 시 90byte를 초과하면 LMS로 자동 전환되어 발송됩니다.</li> | |
| <li>변수에 실제 데이터가 적용된 최종 메시지가 90byte를 초과하는 경우에도 LMS로 전환될 수 있습니다.</li> | |
| </ul> | |
| </div> | |
| </details> | |
| $(document).ready(function () { | |
| initializeSmsContentSettingSectionEvents(); | |
| initializeSmsContentSettingSectionElement(); | |
| }); | |
| function initializeSmsContentSettingSectionEvents() { | |
| }); | |
| return; | |
| } | |
| const smsData = [{ name: "contents", value: message }]; | |
| $.post('./mobile_send/layer_mobile_send_save_sms_template.php', smsData, function (data) { | |
| ncds_layer_popup({message: data, title: '템플릿으로 저장<div class="modal-title-description">작성한 내용을 저장할 카테고리와 제목을 선택하여 주시기 바랍니다.</div>', size: 'wide-sm'}); | |
| }); | |
| removeAdText(window.messageInput, window.preview); | |
| } | |
| }); | |
| } | |
| // 칩 버튼 생성 함수 | |
| syncSmsPreviewAndHint(initialMessage); | |
| const recipientType = document.querySelector('input[name="recipientType"]:checked')?.value; | |
| if (['EXCEL_UPLOAD', 'DIRECT'].includes(recipientType)) { | |
| smsSettingSection.querySelector('.js-replace-code').classList.add('display-none'); | |
| } else { | |
| window.messageInput.setHint(window.messageInput.calculateLength(input) > 90 ? 'LMS 건당 3포인트 차감' : 'SMS 건당 1포인트 차감'); | |
| } | |
| } | |
| function setTemplate(message) { | |
| smsSettingSection.querySelector('input[name="use080Reject"]').checked = false; | |
| // 메시지 적용 | |
| window.messageInput.setValue(''); | |
| window.messageInput.insertText(message); | |
| // 템플릿 불러오기 안내문구 | |
| smsSettingSection.querySelector('#useTemplateCaution').hidden = false; | |
| } | |
| shortLinkInput.value = ''; | |
| smsSettingSection.querySelector('[data-role="chip-container"]').innerHTML = ''; | |
| window.messageInput.setValue(''); | |
| window.preview.reset(); | |
| const isImpossibleAddShortLink = document.querySelectorAll(`.chip-button[data-send-tab-type="${getActivatedSendTabType()}"]`).length > 4; | |
변경 후layer_sms_content_setting.php
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS(제목 활성)일 때만 전송, 미입력·치환자만 입력 시 '[제목없음]' 으로 발송 | |
| function getSmsTitleForSend() { | |
| return resolveTitleForSend(getSmsTitleInput(), isSmsTitleEnabled()); | |
| } | |
| <div class="tab-content-wrap"> | |
| <div class="message-content"> | |
| <div class="ncua-card__body-title-wrap"> | |
| <p class="ncua-card__body-title--xs tooltip-align" data-tooltip-seq="010">내용 입력</p> | |
| </div> | |
| <div class="message-title-field"> | |
| <div class="ncua-input ncua-input--xs ncua-input--full-width-with-count is-disabled"> | |
| <div class="ncua-input__content-wrap"> | |
| <div class="ncua-input__content"> | |
| <div class="ncua-input__field ncua-input__field--xs"> | |
| <input name="smsTitle" type="text" value="" placeholder="제목을 입력해 주세요." disabled /> | |
| </div> | |
| </div> | |
| <div class="ncua-input__field-text-count"> | |
| <output class="ncua-input__field-text-count-current" data-sms-title-current>0</output><span>/40</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="messageContentContainer"></div> | |
| </div> | |
| <ul> | |
| <li>SMS 작성 시 90byte를 초과하면 LMS로 자동 전환되어 발송됩니다.</li> | |
| <li>변수에 실제 데이터가 적용된 최종 메시지가 90byte를 초과하는 경우에도 LMS로 전환될 수 있습니다.</li> | |
| <li>본문 내용이 LMS인 경우에만 제목 입력이 가능하며, 제목 영역에는 직접 (광고) 문구를 입력하지 않도록 하고 광고 삽입이 필요한 경우 광고성 문구 추가 기능을 사용해야 합니다.</li> | |
| </ul> | |
| </div> | |
| </details> | |
| $(document).ready(function () { | |
| initializeSmsContentSettingSectionEvents(); | |
| // CrmPreview(crm-preview.js)는 loader 가 비동기 로드하므로, 준비 전에 element 를 초기화하면 | |
| // MessagePreview 렌더가 null 을 반환해 window.preview 가 null 이 되고, 이후 제목 기본값 prefill· | |
| // LMS 제목 활성화까지 중단된다(레시피 iframe 로드 레이스). → CrmPreview 준비 후 element 초기화. | |
| let isElementInitialized = false; | |
| const runElementInit = function () { | |
| if (isElementInitialized) { | |
| return; | |
| } | |
| isElementInitialized = true; | |
| initializeSmsContentSettingSectionElement(); | |
| }; | |
| // crmPreviewLoaded 가 ready 이전에 이미 발생했을 수 있으므로(캐시 히트 등) 리스너를 먼저 등록하고, | |
| // 준비 완료 상태면 즉시 실행한다(중복 실행은 isElementInitialized 가드로 방지). | |
| window.addEventListener('crmPreviewLoaded', runElementInit); | |
| if (typeof CrmPreview !== 'undefined' && typeof GodoUIModule !== 'undefined') { | |
| runElementInit(); | |
| } | |
| }); | |
| function initializeSmsContentSettingSectionEvents() { | |
| }); | |
| return; | |
| } | |
| // 제목은 SMS/LMS 여부와 무관하게 입력값이 있으면 함께 저장 | |
| const smsData = [ | |
| { name: "contents", value: message }, | |
| { name: "messageTitle", value: getSmsTitleInput().value } | |
| ]; | |
| $.post('./mobile_send/layer_mobile_send_save_sms_template.php', smsData, function (data) { | |
| ncds_layer_popup({message: data, title: '템플릿으로 저장<div class="modal-title-description">작성한 내용을 저장할 카테고리와 제목을 선택하여 주시기 바랍니다.</div>', size: 'wide-sm'}); | |
| }); | |
| removeAdText(window.messageInput, window.preview); | |
| } | |
| }); | |
| getSmsTitleInput().addEventListener('input', handleSmsTitleInput); | |
| } | |
| function getSmsTitleInput() { | |
| return smsSettingSection.querySelector('input[name="smsTitle"]'); | |
| } | |
| // 제목 입력 — 이모지 제거 후 40bytes 규칙 적용 (applySmsTitleByteRule) | |
| function handleSmsTitleInput() { | |
| const input = getSmsTitleInput(); | |
| const value = applySmsTitleByteRule(input, window.messageInput); | |
| smsSettingSection.querySelector('[data-sms-title-current]').textContent = window.messageInput.getByteLength(value); | |
| updateSmsTitlePreview(); | |
| } | |
| // 본문이 LMS(90bytes 초과)일 때만 제목 활성 — SMS 로 돌아오면 값은 유지한 채 비활성 | |
| function setSmsTitleEnabled(enabled) { | |
| const input = getSmsTitleInput(); | |
| input.disabled = !enabled; | |
| input.closest('.ncua-input').classList.toggle('is-disabled', !enabled); | |
| updateSmsTitlePreview(); | |
| } | |
| function isSmsTitleEnabled() { | |
| const input = getSmsTitleInput(); | |
| return !!input && !input.disabled; | |
| } | |
| // 발송 요청용 제목 — LMS 활성 상태에서 값이 있을 때만. 미입력 시 null('제목없음' 처리는 발송 시스템 담당) | |
| function getSmsTitleForSend() { | |
| return resolveTitleForSend(getSmsTitleInput(), isSmsTitleEnabled()); | |
| } | |
| // 미리보기 — LMS 상태에서 값이 있을 때만 노출, 치환자는 공란으로 표기 | |
| function updateSmsTitlePreview() { | |
| window.preview.setTitle(isSmsTitleEnabled() ? stripTitleReplaceCodes(getSmsTitleInput().value) : ''); | |
| } | |
| // 칩 버튼 생성 함수 | |
| syncSmsPreviewAndHint(initialMessage); | |
| // 레시피 기본 제목 prefill — 본문이 LMS면 활성 노출, SMS면 값만 유지한 채 비활성 (setTemplate 패턴) | |
| const initialTitle = <?= json_encode($initialTitle ?? '', JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP) ?>; | |
| if (initialTitle !== '') { | |
| getSmsTitleInput().value = initialTitle; | |
| handleSmsTitleInput(); | |
| } | |
| const recipientType = document.querySelector('input[name="recipientType"]:checked')?.value; | |
| if (['EXCEL_UPLOAD', 'DIRECT'].includes(recipientType)) { | |
| smsSettingSection.querySelector('.js-replace-code').classList.add('display-none'); | |
| } else { | |
| window.messageInput.setHint(window.messageInput.calculateLength(input) > 90 ? 'LMS 건당 3포인트 차감' : 'SMS 건당 1포인트 차감'); | |
| } | |
| // 본문 기준 SMS/LMS 판단 — LMS 일 때만 제목 입력 활성화 (#15092) | |
| setSmsTitleEnabled(window.messageInput.calculateLength(input) > 90); | |
| } | |
| function setTemplate(message, messageTitle = '') { | |
| smsSettingSection.querySelector('input[name="use080Reject"]').checked = false; | |
| // 메시지 적용 (insertText 가 onInput 을 호출해 SMS/LMS 판단·제목 활성 토글이 함께 갱신됨) | |
| window.messageInput.setValue(''); | |
| window.messageInput.insertText(message); | |
| // 저장된 메시지 제목 복원 — SMS 상태면 값만 유지한 채 비활성으로 노출됨 | |
| const titleInput = getSmsTitleInput(); | |
| titleInput.value = messageTitle ?? ''; | |
| handleSmsTitleInput(); | |
| // 템플릿 불러오기 안내문구 | |
| smsSettingSection.querySelector('#useTemplateCaution').hidden = false; | |
| } | |
| shortLinkInput.value = ''; | |
| smsSettingSection.querySelector('[data-role="chip-container"]').innerHTML = ''; | |
| window.messageInput.setValue(''); | |
| const titleInput = getSmsTitleInput(); | |
| titleInput.value = ''; | |
| setSmsTitleOverState(titleInput, false); // 40byte 초과 에러 표기까지 함께 해제 | |
| setSmsTitleEnabled(false); | |
| smsSettingSection.querySelector('[data-sms-title-current]').textContent = '0'; | |
| window.preview.reset(); | |
| const isImpossibleAddShortLink = document.querySelectorAll(`.chip-button[data-send-tab-type="${getActivatedSendTabType()}"]`).length > 4; | |
변경 전mobile_send.php
| el.querySelector('.ncua-input__destructive-icon-wrap')?.remove(); | |
| }); | |
| // 발신번호 검증 | |
| if (!messageConfig.hasCallNumber) { | |
| NCDSAlert({message: '발신번호가 없어 발송할 수 없습니다.', subMessage: '설정에서 발신번호 등록 후 발송 시도를 해주세요.', iconType: 'error'}); | |
| }); | |
| window.alternativeMessageInput.insertText(alternativeContents); | |
| window.alternativePreview.setContent(alternativeContents); | |
| } | |
| } | |
변경 후mobile_send.php
| el.querySelector('.ncua-input__destructive-icon-wrap')?.remove(); | |
| }); | |
| // 제목 40byte 초과(C4-2)는 미해소 에러라 재표기 | |
| if (typeof refreshOverSmsTitleState === 'function') { | |
| refreshOverSmsTitleState(); | |
| } | |
| // 발신번호 검증 | |
| if (!messageConfig.hasCallNumber) { | |
| NCDSAlert({message: '발신번호가 없어 발송할 수 없습니다.', subMessage: '설정에서 발신번호 등록 후 발송 시도를 해주세요.', iconType: 'error'}); | |
| }); | |
| window.alternativeMessageInput.insertText(alternativeContents); | |
| window.alternativePreview.setContent(alternativeContents); | |
| if (typeof copyMainTitleToAlternativeSmsTitle === 'function') { | |
| copyMainTitleToAlternativeSmsTitle(); | |
| } | |
| } | |
| } | |
변경 전layer_preview_mobile_send_alternative.php
| <section class="mobile-preview mobile-preview--sms"> | |
| <div class="ncua-prev alternative-contents-preview" style="white-space: pre-wrap;"><?= $alternativeContents ?></div> | |
| </section> | |
| <script> | |
| const alternativeSmsPreview = document.querySelector('.alternative-contents-preview'); | |
| $(document).ready(() => { | |
| alternativeSmsPreview.textContent = resolveReplaceCodeForPreview(alternativeSmsPreview.textContent); | |
| }) | |
| </script> | |
변경 후layer_preview_mobile_send_alternative.php
| <section class="mobile-preview mobile-preview--sms"> | |
| <?php /* pre-wrap 은 본문에만 — 말풍선에 걸면 템플릿 마크업의 공백·줄바꿈까지 렌더링됨 */ ?> | |
| <div class="ncua-prev"> | |
| <?php if (($alternativeTitle ?? '') !== ''): ?> | |
| <div class="sms-title-side-preview alternative-title-preview"><?= gd_htmlspecialchars($alternativeTitle) ?></div> | |
| <?php endif; ?> | |
| <div class="alternative-contents-preview" style="white-space: pre-wrap;"><?= $alternativeContents ?></div> | |
| </div> | |
| </section> | |
| <script> | |
| const alternativeSmsPreview = document.querySelector('.alternative-contents-preview'); | |
| $(document).ready(() => { | |
| alternativeSmsPreview.textContent = resolveReplaceCodeForPreview(alternativeSmsPreview.textContent); | |
| // 제목은 변수 치환 미지원 — 변수는 공란으로 표기 | |
| const alternativeTitlePreview = document.querySelector('.alternative-title-preview'); | |
| if (alternativeTitlePreview) { | |
| alternativeTitlePreview.textContent = alternativeTitlePreview.textContent.replace(/[#$]?\{[^}]*\}/g, ''); | |
| } | |
| }) | |
| </script> | |
변경 전layer_preview_mobile_send_sms.php
| <section class="mobile-preview mobile-preview--sms"> | |
| <div class="ncua-prev sms-contents-preview" style="white-space: pre-wrap;"><?= $mainContents ?></div> | |
| </section> | |
| <script> | |
| const smsPreview = document.querySelector('.sms-contents-preview'); | |
| $(document).ready(() => { | |
| smsPreview.textContent = resolveReplaceCodeForPreview(smsPreview.textContent); | |
| }) | |
| </script> | |
변경 후layer_preview_mobile_send_sms.php
| <section class="mobile-preview mobile-preview--sms"> | |
| <?php /* pre-wrap 은 본문에만 — 말풍선에 걸면 템플릿 마크업의 공백·줄바꿈까지 렌더링됨 */ ?> | |
| <div class="ncua-prev"> | |
| <?php if (($mainTitle ?? '') !== ''): ?> | |
| <div class="sms-title-side-preview sms-title-preview"><?= gd_htmlspecialchars($mainTitle) ?></div> | |
| <?php endif; ?> | |
| <div class="sms-contents-preview" style="white-space: pre-wrap;"><?= $mainContents ?></div> | |
| </div> | |
| </section> | |
| <script> | |
| const smsPreview = document.querySelector('.sms-contents-preview'); | |
| $(document).ready(() => { | |
| smsPreview.textContent = resolveReplaceCodeForPreview(smsPreview.textContent); | |
| // 제목은 변수 치환 미지원 — 변수는 공란으로 표기 | |
| const smsTitlePreview = document.querySelector('.sms-title-preview'); | |
| if (smsTitlePreview) { | |
| smsTitlePreview.textContent = smsTitlePreview.textContent.replace(/[#$]?\{[^}]*\}/g, ''); | |
| } | |
| }) | |
| </script> | |
변경 전sms_auto.php
| </label> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][recipientMode]" value="<?php echo $typeData['recipientMode']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][recipientSno]" value="<?php echo $typeData['recipientSno']; ?>"/> | |
| <textarea name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][recipientContents]" rows="4" class="form-control"><?php echo $typeData['recipientContents']; ?></textarea> | |
| </td> | |
| <?php } ?> | |
| <td class="form-inline"> | |
| </label> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][memberMode]" value="<?php echo $typeData['memberMode']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][memberSno]" value="<?php echo $typeData['memberSno']; ?>"/> | |
| <textarea name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][memberContents]" rows="4" class="form-control"><?php echo $typeData['memberContents']; ?></textarea> | |
| <?php } else { ?> | |
| <div class="text-center text-blue">운영자 전용</div> | |
| <?php } ?> | |
| </label> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][adminMode]" value="<?php echo $typeData['adminMode']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][adminSno]" value="<?php echo $typeData['adminSno']; ?>"/> | |
| <textarea name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][adminContents]" rows="4" | |
| class="form-control <?php if ($sKey == 'admin') { ?> width100p <?php } ?>"><?php echo $typeData['adminContents']; ?></textarea> | |
| <?php } else { ?> | |
| <div class="text-center text-orange-red">회원 전용</div> | |
| <?php } ?> | |
| </label> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][providerMode]" value="<?php echo $typeData['providerMode']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][providerSno]" value="<?php echo $typeData['providerSno']; ?>"/> | |
| <textarea name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][providerContents]" rows="4" class="form-control"><?php echo $typeData['providerContents']; ?></textarea> | |
| <?php } else { ?> | |
| <?php if ($sKey == 'admin') { ?> | |
| <div class="text-center text-orange-red">본사 전용</div> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][providerSno]" value="<?php echo $typeData['providerSno']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][providerMode]" value="<?php echo $typeData['providerMode']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][providerContents]" value="<?php echo $typeData['providerContents']; ?>"/> | |
| <?php } ?> | |
| </tr> | |
| <?php | |
| <script type="text/javascript"> | |
| <!-- | |
| $(document).ready(function () { | |
| $('.btn-change-password').click(function () { | |
| $.get('../share/layer_sms_password.php?mode=change', function () { | |
| BootstrapDialog.closeAll(); | |
변경 후sms_auto.php
| </label> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][recipientMode]" value="<?php echo $typeData['recipientMode']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][recipientSno]" value="<?php echo $typeData['recipientSno']; ?>"/> | |
| <div class="js-sms-auto-subject-wrap mgb5"> | |
| <input type="text" name="<?= $sKey ?>[<?= $typeData['code'] ?>][recipientMessageTitle]" class="form-control js-sms-auto-subject" placeholder="제목 입력" value="<?= gd_isset($typeData['recipientMessageTitle']) ?>"/> | |
| </div> | |
| <textarea name="<?= $sKey ?>[<?= $typeData['code'] ?>][recipientContents]" rows="4" class="form-control js-sms-auto-contents"><?= $typeData['recipientContents'] ?></textarea> | |
| </td> | |
| <?php } ?> | |
| <td class="form-inline"> | |
| </label> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][memberMode]" value="<?php echo $typeData['memberMode']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][memberSno]" value="<?php echo $typeData['memberSno']; ?>"/> | |
| <div class="js-sms-auto-subject-wrap mgb5"> | |
| <input type="text" name="<?= $sKey ?>[<?= $typeData['code'] ?>][memberMessageTitle]" class="form-control js-sms-auto-subject" placeholder="제목 입력" value="<?= gd_isset($typeData['memberMessageTitle']) ?>"/> | |
| </div> | |
| <textarea name="<?= $sKey ?>[<?= $typeData['code'] ?>][memberContents]" rows="4" class="form-control js-sms-auto-contents"><?= $typeData['memberContents'] ?></textarea> | |
| <?php } else { ?> | |
| <div class="text-center text-blue">운영자 전용</div> | |
| <?php } ?> | |
| </label> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][adminMode]" value="<?php echo $typeData['adminMode']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][adminSno]" value="<?php echo $typeData['adminSno']; ?>"/> | |
| <div class="js-sms-auto-subject-wrap mgb5"> | |
| <input type="text" name="<?= $sKey ?>[<?= $typeData['code'] ?>][adminMessageTitle]" class="form-control js-sms-auto-subject" placeholder="제목 입력" value="<?= gd_isset($typeData['adminMessageTitle']) ?>"/> | |
| </div> | |
| <textarea name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][adminContents]" rows="4" | |
| class="form-control js-sms-auto-contents <?php if ($sKey == 'admin') { ?> width100p <?php } ?>"><?= $typeData['adminContents'] ?></textarea> | |
| <?php } else { ?> | |
| <div class="text-center text-orange-red">회원 전용</div> | |
| <?php } ?> | |
| </label> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][providerMode]" value="<?php echo $typeData['providerMode']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][providerSno]" value="<?php echo $typeData['providerSno']; ?>"/> | |
| <div class="js-sms-auto-subject-wrap mgb5"> | |
| <input type="text" name="<?= $sKey ?>[<?= $typeData['code'] ?>][providerMessageTitle]" class="form-control js-sms-auto-subject" placeholder="제목 입력" value="<?= gd_isset($typeData['providerMessageTitle']) ?>"/> | |
| </div> | |
| <textarea name="<?= $sKey ?>[<?= $typeData['code'] ?>][providerContents]" rows="4" class="form-control js-sms-auto-contents"><?= $typeData['providerContents'] ?></textarea> | |
| <?php } else { ?> | |
| <?php if ($sKey == 'admin') { ?> | |
| <div class="text-center text-orange-red">본사 전용</div> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][providerSno]" value="<?php echo $typeData['providerSno']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][providerMode]" value="<?php echo $typeData['providerMode']; ?>"/> | |
| <input type="hidden" name="<?php echo $sKey; ?>[<?php echo $typeData['code']; ?>][providerContents]" value="<?php echo $typeData['providerContents']; ?>"/> | |
| <input type="hidden" name="<?= $sKey ?>[<?= $typeData['code'] ?>][providerMessageTitle]" value="<?= gd_isset($typeData['providerMessageTitle']) ?>"/> | |
| <?php } ?> | |
| </tr> | |
| <?php | |
| <script type="text/javascript"> | |
| <!-- | |
| $(document).ready(function () { | |
| // 제목 바이트 계산 (한글 등 멀티바이트 2byte, ASCII 1byte, 개행 제외) | |
| function smsAutoStringToByte(str) { | |
| var length = 0; | |
| for (var i = 0; i < str.length; i++) { | |
| if (escape(str.charAt(i)).length >= 4) length += 2; | |
| else if (escape(str.charAt(i)) != "%0D") length++; | |
| } | |
| return length; | |
| } | |
| // 이모티콘 제거 (서로게이트 페어 + 변형선택자, 기획: 제목·본문 입력 불가) | |
| function smsAutoStripEmoji(str) { | |
| if (!str) return str; | |
| return str.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '').replace(/[\uFE00-\uFE0F\u200D\u20E3]/g, ''); | |
| } | |
| // 자동발송 제목 영역은 항상 활성 노출(C3). 본문은 이모티콘만 자동 제거. | |
| $('.js-sms-auto-contents').on('keyup change', function () { | |
| var $ta = $(this); | |
| var stripped = smsAutoStripEmoji($ta.val()); | |
| if (stripped !== $ta.val()) { $ta.val(stripped); } | |
| }); | |
| $('.js-sms-auto-subject').on('keyup keydown', function () { | |
| var input = $(this); | |
| var text = smsAutoStripEmoji(input.val()); | |
| while (smsAutoStringToByte(text) > <?= $lmsSubjectLimit; ?>) { text = text.substring(0, text.length - 1); } | |
| input.val(text); | |
| }); | |
| $('.btn-change-password').click(function () { | |
| $.get('../share/layer_sms_password.php?mode=change', function () { | |
| BootstrapDialog.closeAll(); | |
변경 전sms_log.php
| $listHtml[] = '<td class="text-center number">' . ($data['receiverCnt'] * $lmsPoint) . '</td>'; | |
| } | |
| $listHtml[] = '<td style="word-break:break-all;word-wrap:break-word;overflow:hidden;" class="multirows">'; | |
| $listHtml[] = '<div class="div-contents">' . $data['contents'] . '</div>'; | |
| if ($data['sendStatus'] === 'r' && $data['smsType'] === 'user') { | |
| $listHtml[] = '<div><button type="button" class="btn btn-xs btn-gray btn-modify">수정하기</button></div>'; | |
변경 후sms_log.php
| $listHtml[] = '<td class="text-center number">' . ($data['receiverCnt'] * $lmsPoint) . '</td>'; | |
| } | |
| $listHtml[] = '<td style="word-break:break-all;word-wrap:break-word;overflow:hidden;" class="multirows">'; | |
| if ($data['sendFl'] === 'lms') { | |
| $subjectText = ($data['subject'] !== null && $data['subject'] !== '') ? $data['subject'] : '[' . __('제목없음') . ']'; | |
| $listHtml[] = '<div class="div-subject text-darkblue"><strong>' . gd_htmlspecialchars($subjectText) . '</strong></div>'; | |
| } | |
| $listHtml[] = '<div class="div-contents">' . $data['contents'] . '</div>'; | |
| if ($data['sendStatus'] === 'r' && $data['smsType'] === 'user') { | |
| $listHtml[] = '<div><button type="button" class="btn btn-xs btn-gray btn-modify">수정하기</button></div>'; | |
변경 전sms_send.php
| return length; | |
| } | |
| /** | |
| * SMS 내용 길이 체크 | |
| */ | |
| function setContentsLength(contentsNm, countId) { | |
| var textarea = $('textarea[name=' + contentsNm + ']'); | |
| var contentsText = textarea.val(); | |
| var textLength = stringToByte(contentsText); | |
| if (textLength > <?php echo $smsStringLimit;?>) { | |
| if (textLength > <?php echo $lmsStringLimit;?>) { | |
| $('.sms-type').hide(); | |
| $('.lms-type').show(); | |
| $('input[name=sendFl]').val('lms'); | |
| } else { | |
| $('#' + countId).css("color", ""); | |
| $('.sms-type').show(); | |
| $('.lms-type').hide(); | |
| $('input[name=sendFl]').val('sms'); | |
| } | |
| $('#' + countId).val(textLength); | |
| } | |
| setContentsLength('smsContents', 'smsStringCount'); | |
| } | |
| function setReceiverCount() { | |
| var checkedType = $('[name=receiverType]:checked').val(); | |
| var receiverCount = 0, agreeCount = 0, rejectCount = 0; | |
| dialog: false, | |
| debug: true, | |
| submitHandler: function (form) { | |
| console.log('submitHan', form); | |
| var divisionInt = 1; | |
| if ($('input[name=sendFl]').val() === 'lms') { | |
| divisionInt = <?php echo $lmsPoint;?>; | |
| <div class="notice-danger pull-left mgl15 display-none">회원 외 치환코드는 정상 적용되지 않으니 저장된 메시지 수정 시에만 이용바랍니다.</div> | |
| </div> | |
| </div> | |
| <div class="row pdt5"> | |
| <div class="col-xs-3 pdr0"> | |
| <label class="width100p"> | |
| <div class="col-xs-12"> | |
| <div class="notice-info">URL 삽입 시 [단축 URL] 앱을 이용하시면 짧고 간단하게 URL을 사용하실 수 있습니다. <a href="https://apps.godo.co.kr/apps/1519" class="btn-link" target="_blank">바로가기</a></div> | |
| <div class="notice-info">치환코드 사용 시 LMS로 발송될 수 있으며 일부 문자가 포인트 부족으로 발송되지 않을 수 있습니다.<br/>- 포인트 충전 후 <a href="../member/sms_log.php" class="btn-link" target="_blank">SMS 발송 내역 보기</a>에서 재발송하실 수 있습니다.</div> | |
| <div class="notice-danger sms-large-caution">발송내용에 이모지 또는 사용 불가능한 특수문자, 맞춤법이 바르지 않은 문자가 포함되어있으면 일부 내용은 삭제되고 발송되오니 주의하시기 바랍니다.<br/>대량 SMS(LMS) 발송 시 이모지를 사용하지 않는 것과 맞춤법에 어긋나는 문자가 입력 되지는 않았는지 확인하시는 것을 권장 드리며,<br/> 발송 내용에 사용가능한 특수문자는 매뉴얼을 참고하시기 바랍니다.</div> | |
| </div> | |
| </div> | |
| <%= checkbox %> <%= subject %> | |
| <button type="button" class="btn btn-sm btn-white pull-right js-btn-save" data-text="저장">수정</button> | |
| <button type="button" class="btn btn-sm btn-white pull-right js-btn-insert mgr5">삽입</button> | |
| <label class="width100p pdt5"> | |
| <textarea rows="13" class="form-control width100p" name="contents"><%= contents %></textarea> | |
| </label> | |
변경 후sms_send.php
| return length; | |
| } | |
| /** | |
| * 이모티콘 제거 (제목/본문 이모티콘 입력 불가 - 자동 삭제) | |
| */ | |
| function stripEmoji(str) { | |
| if (!str) { | |
| return str; | |
| } | |
| return str | |
| .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '') | |
| .replace(/[\uFE00-\uFE0F\u200D\u20E3]/g, ''); | |
| } | |
| /** | |
| * SMS 내용 길이 체크 | |
| */ | |
| function setContentsLength(contentsNm, countId) { | |
| var textarea = $('textarea[name=' + contentsNm + ']'); | |
| var stripped = stripEmoji(textarea.val()); | |
| if (stripped !== textarea.val()) { | |
| textarea.val(stripped); | |
| } | |
| var contentsText = stripped; | |
| var textLength = stringToByte(contentsText); | |
| if (textLength > <?php echo $smsStringLimit;?>) { | |
| if (textLength > <?php echo $lmsStringLimit;?>) { | |
| $('.sms-type').hide(); | |
| $('.lms-type').show(); | |
| $('input[name=sendFl]').val('lms'); | |
| $('#smsSubject').prop('disabled', false); // LMS: 제목 영역 활성 | |
| setSubjectLength(); | |
| } else { | |
| $('#' + countId).css("color", ""); | |
| $('.sms-type').show(); | |
| $('.lms-type').hide(); | |
| $('input[name=sendFl]').val('sms'); | |
| $('#smsSubject').prop('disabled', true); // SMS: 제목 영역 비활성(값 유지, 미발송) | |
| } | |
| $('#' + countId).val(textLength); | |
| } | |
| setContentsLength('smsContents', 'smsStringCount'); | |
| } | |
| /** | |
| * LMS 제목 Byte 체크 (공백 포함 최대 <?= $lmsSubjectLimit; ?>Byte, 초과분 자동 삭제) | |
| */ | |
| function setSubjectLength() { | |
| var input = $('#smsSubject'); | |
| if (input.length === 0) { | |
| return; | |
| } | |
| var limit = <?= $lmsSubjectLimit; ?>; | |
| var text = stripEmoji(input.val()); | |
| var adChecked = $('input[name=sms080Reject]').is(':checked'); | |
| var byte = stringToByte(text); | |
| if (adChecked && byte > limit) { | |
| // C4-2: (광고) 자동 삽입으로 40Byte 초과 -> 절삭하지 않고 에러 표기 | |
| input.val(text); | |
| setSubjectOver(true); | |
| } else { | |
| // C1-1: 직접 입력 40Byte 초과분 자동삭제 | |
| while (stringToByte(text) > limit) { | |
| text = text.substring(0, text.length - 1); | |
| } | |
| input.val(text); | |
| byte = stringToByte(text); | |
| setSubjectOver(false); | |
| } | |
| $('#smsSubjectCount').val(byte); | |
| } | |
| function setSubjectOver(isOver) { | |
| var input = $('#smsSubject'); | |
| if (isOver) { | |
| input.addClass('js-subject-over').css('border-color', '#e74c3c'); | |
| $('#smsSubjectCount').css('color', '#e74c3c'); | |
| } else { | |
| input.removeClass('js-subject-over').css('border-color', ''); | |
| $('#smsSubjectCount').css('color', ''); | |
| } | |
| } | |
| function setReceiverCount() { | |
| var checkedType = $('[name=receiverType]:checked').val(); | |
| var receiverCount = 0, agreeCount = 0, rejectCount = 0; | |
| dialog: false, | |
| debug: true, | |
| submitHandler: function (form) { | |
| // C4-2: 제목 40Byte 초과(광고 삽입 등) 시 발송 차단 | |
| if ($('input[name=sendFl]').val() === 'lms' && $('#smsSubject').length && stringToByte(stripEmoji($('#smsSubject').val())) > <?= $lmsSubjectLimit; ?>) { | |
| BootstrapDialog.show({title: '경고', message: '제목은 최대 <?= $lmsSubjectLimit; ?>bytes까지 입력 가능합니다.', closable: true}); | |
| $('#smsSubject').focus(); | |
| return false; | |
| } | |
| var divisionInt = 1; | |
| if ($('input[name=sendFl]').val() === 'lms') { | |
| divisionInt = <?php echo $lmsPoint;?>; | |
| <div class="notice-danger pull-left mgl15 display-none">회원 외 치환코드는 정상 적용되지 않으니 저장된 메시지 수정 시에만 이용바랍니다.</div> | |
| </div> | |
| </div> | |
| <div class="row pdt5 js-subject-row"> | |
| <div class="col-xs-3 pdr0"> | |
| <input type="text" name="smsSubject" id="smsSubject" class="form-control width100p" placeholder="제목을 입력해주세요." value="<?= gd_isset($smsSubject); ?>" onkeyup="setSubjectLength();" onkeydown="setSubjectLength();" disabled="disabled"/> | |
| <div class="mgt5"> | |
| <input type="text" id="smsSubjectCount" value="0" readonly="readonly" class="form-control width-3xs"> / <?= $lmsSubjectLimit; ?> Bytes | |
| </div> | |
| </div> | |
| </div> | |
| <div class="row pdt5"> | |
| <div class="col-xs-3 pdr0"> | |
| <label class="width100p"> | |
| <div class="col-xs-12"> | |
| <div class="notice-info">URL 삽입 시 [단축 URL] 앱을 이용하시면 짧고 간단하게 URL을 사용하실 수 있습니다. <a href="https://apps.godo.co.kr/apps/1519" class="btn-link" target="_blank">바로가기</a></div> | |
| <div class="notice-info">치환코드 사용 시 LMS로 발송될 수 있으며 일부 문자가 포인트 부족으로 발송되지 않을 수 있습니다.<br/>- 포인트 충전 후 <a href="../member/sms_log.php" class="btn-link" target="_blank">SMS 발송 내역 보기</a>에서 재발송하실 수 있습니다.</div> | |
| <div class="notice-info">본문 내용이 LMS인 경우에만 제목 입력이 가능하며, 제목 영역에는 직접 (광고) 문구를 입력하지 않도록 하고 광고 삽입이 필요한 경우 광고성 문구 추가 기능을 사용해야 합니다.</div> | |
| <div class="notice-danger sms-large-caution">발송내용에 이모지 또는 사용 불가능한 특수문자, 맞춤법이 바르지 않은 문자가 포함되어있으면 일부 내용은 삭제되고 발송되오니 주의하시기 바랍니다.<br/>대량 SMS(LMS) 발송 시 이모지를 사용하지 않는 것과 맞춤법에 어긋나는 문자가 입력 되지는 않았는지 확인하시는 것을 권장 드리며,<br/> 발송 내용에 사용가능한 특수문자는 매뉴얼을 참고하시기 바랍니다.</div> | |
| </div> | |
| </div> | |
| <%= checkbox %> <%= subject %> | |
| <button type="button" class="btn btn-sm btn-white pull-right js-btn-save" data-text="저장">수정</button> | |
| <button type="button" class="btn btn-sm btn-white pull-right js-btn-insert mgr5">삽입</button> | |
| <input type="text" name="messageTitle" class="form-control width100p mgt5 js-sms-contents-subject" placeholder="제목을 입력해주세요." value="<%= messageTitle %>" disabled="disabled"/> | |
| <label class="width100p pdt5"> | |
| <textarea rows="13" class="form-control width100p" name="contents"><%= contents %></textarea> | |
| </label> | |
변경 전cart_remind_regist.php
| } | |
| if (e.target.checked) { | |
| $body.val('(광고)\n' + $body.val() + '\n무료거부 ' + $('input[name="sms080Reject"]').data('reject-number')); | |
| } | |
| changeCartRemindContentsLength(); | |
| // 본문 반영으로 SMS/LMS 판정이 끝난 뒤에 제목 처리 — 제목 영역이 비활성(SMS)이면 (광고) 미표기 | |
| if (e.target.checked && $subject.length && !$subject.prop('disabled')) { | |
| $subject.val('(광고)' + $subject.val()); | |
| } | |
| changeCartRemindSubjectLength(); | |
| }); | |
| } | |
| if (e.target.checked) { | |
| $body.val('(광고)\n' + $body.val() + '\n무료거부 ' + $('input[name="sms080Reject"]').data('reject-number')); | |
| if ($subject.length) { | |
| $subject.val('(광고)' + $subject.val()); | |
| } | |
| } | |
| changeCartRemindContentsLength(); | |
| changeCartRemindSubjectLength(); | |
| }); | |
| <span class="cart-remind-sms notice-info">SMS : 발송 건당 1포인트 차감</span> | |
| </div> | |
| </div> | |
| <div class="form-inline mgt10"> | |
| <textarea name="cartRemindSendMessage" rows="8" class="smsContents form-control width-xl js-sms080-update"><?= $cartRemindData['cartRemindSendMessage']; ?></textarea> | |
| <div class="mgt5"> | |
| <a href="https://www.nhn-commerce.com/customer/board-view.gd?type=notice&idx=1237" target="_blank" class="btn-link">자세히보기></a> | |
| </p> | |
| <p class="notice-info">장바구니 링크 치환코드는 LMS인 경우에만 정상적으로 발송됩니다</p> | |
| </div> | |
| </td> | |
| </tr> | |
| // 글자수 체크 | |
| $('textarea[name=cartRemindSendMessage]').keyup(changeCartRemindContentsLength); | |
| displayCartRemindCouponLink(); | |
| changeCartRemindType(); | |
| changeCartRemindSendType(); | |
| changeCartRemindManualDirectPeriod(); | |
| changeCartRemindContentsLength(); | |
| // 광고성 문구 추가 | |
| $('input[name="sms080Reject"]').click(function (e) { | |
| $('.js-sms080-update').val($('.js-sms080-update').val().replace(/(\n무료거부\s[0-9\-]*)/g, '')); | |
| if(e.target.checked){ | |
| $('.js-sms080-update').val($('.js-sms080-update').val() + '\n무료거부 ' + $('input[name="sms080Reject"]').data('reject-number')); | |
| }; | |
| }); | |
| }); | |
| * SMS 내용 길이 체크 | |
| */ | |
| function changeCartRemindContentsLength() { | |
| var contentsText = $('textarea[name=cartRemindSendMessage]').val(); | |
| var textLength = stringToByte(contentsText); | |
| if ($('input:hidden[name="cartRemindSendType"]').val() == 'sms' && textLength > <?= $smsStringLimit; ?>) { | |
| } | |
| $('#cartRemindSendMessageCount').val(textLength); | |
| } | |
| // 발송유형 따른 폼 변경 | |
| function changeCartRemindType() { | |
| if ($('input:radio[name="cartRemindType"]:checked').val() == 'manual') { | |
| $('.cart-remind-sms').hide(); | |
| $('.cart-remind-sms select').attr('disabled', 'disabled'); | |
| $('.cart-remind-sms input').attr('disabled', 'disabled'); | |
| // sms발송 | |
| } else if ($('input:hidden[name="cartRemindSendType"]').val() == 'sms') { | |
| $('.cart-remind-lms').hide(); | |
| $('.cart-remind-sms').show(); | |
| $('.cart-remind-sms select').removeAttr('disabled'); | |
| $('.cart-remind-sms input').removeAttr('disabled'); | |
| } | |
| } | |
| // 발급방식에 따른 폼 변경 | |
| } | |
| return length; | |
| } | |
| </script> | |
변경 후cart_remind_regist.php
| } | |
| if (e.target.checked) { | |
| $body.val('(광고)\n' + $body.val() + '\n무료거부 ' + $('input[name="sms080Reject"]').data('reject-number')); | |
| if ($subject.length) { | |
| $subject.val('(광고)' + $subject.val()); | |
| } | |
| } | |
| changeCartRemindContentsLength(); | |
| changeCartRemindSubjectLength(); | |
| }); | |
| } | |
| if (e.target.checked) { | |
| $body.val('(광고)\n' + $body.val() + '\n무료거부 ' + $('input[name="sms080Reject"]').data('reject-number')); | |
| } | |
| changeCartRemindContentsLength(); | |
| // 본문 반영으로 SMS/LMS 판정이 끝난 뒤에 제목 처리 — 제목 영역이 비활성(SMS)이면 (광고) 미표기 | |
| if (e.target.checked && $subject.length && !$subject.prop('disabled')) { | |
| $subject.val('(광고)' + $subject.val()); | |
| } | |
| changeCartRemindSubjectLength(); | |
| }); | |
| <span class="cart-remind-sms notice-info">SMS : 발송 건당 1포인트 차감</span> | |
| </div> | |
| </div> | |
| <div class="form-inline mgt10 js-cart-subject-row"> | |
| <input type="text" name="cartRemindSendSubject" id="cartRemindSendSubject" class="form-control width-xl" placeholder="제목을 입력해주세요." value="<?= gd_isset($cartRemindData['cartRemindSendSubject']); ?>" disabled="disabled"/> | |
| <input type="text" id="cartRemindSubjectCount" value="0" readonly="readonly" class="form-control width-3xs"> / <?= $lmsSubjectLimit; ?> Bytes | |
| </div> | |
| <div class="form-inline mgt10"> | |
| <textarea name="cartRemindSendMessage" rows="8" class="smsContents form-control width-xl js-sms080-update"><?= $cartRemindData['cartRemindSendMessage']; ?></textarea> | |
| <div class="mgt5"> | |
| <a href="https://www.nhn-commerce.com/customer/board-view.gd?type=notice&idx=1237" target="_blank" class="btn-link">자세히보기></a> | |
| </p> | |
| <p class="notice-info">장바구니 링크 치환코드는 LMS인 경우에만 정상적으로 발송됩니다</p> | |
| <p class="notice-info">본문 내용이 LMS인 경우에만 제목 입력이 가능하며, 제목 영역에는 직접 (광고) 문구를 입력하지 않도록 하고 광고 삽입이 필요한 경우 광고성 문구 추가 기능을 사용해야 합니다.</p> | |
| </div> | |
| </td> | |
| </tr> | |
| // 글자수 체크 | |
| $('textarea[name=cartRemindSendMessage]').keyup(changeCartRemindContentsLength); | |
| $('#cartRemindSendSubject').on('keyup keydown', changeCartRemindSubjectLength); | |
| displayCartRemindCouponLink(); | |
| changeCartRemindType(); | |
| changeCartRemindSendType(); | |
| changeCartRemindManualDirectPeriod(); | |
| changeCartRemindContentsLength(); | |
| changeCartRemindSubjectLength(); | |
| // 광고성 문구 추가 (본문: (광고) 접두 + 무료거부 접미 / LMS 제목: (광고) 접두) | |
| $('input[name="sms080Reject"]').click(function (e) { | |
| var $body = $('.js-sms080-update'); | |
| $body.val($body.val().replace(/(\(광고\)\n)|(\n무료거부\s[0-9\-]*)/g, '')); | |
| var $subject = $('#cartRemindSendSubject'); | |
| if ($subject.length) { | |
| $subject.val($subject.val().replace(/^\(광고\)/, '')); | |
| } | |
| if (e.target.checked) { | |
| $body.val('(광고)\n' + $body.val() + '\n무료거부 ' + $('input[name="sms080Reject"]').data('reject-number')); | |
| if ($subject.length) { | |
| $subject.val('(광고)' + $subject.val()); | |
| } | |
| } | |
| changeCartRemindContentsLength(); | |
| changeCartRemindSubjectLength(); | |
| }); | |
| }); | |
| * SMS 내용 길이 체크 | |
| */ | |
| function changeCartRemindContentsLength() { | |
| var $cartTa = $('textarea[name=cartRemindSendMessage]'); | |
| var strippedBody = stripEmoji($cartTa.val()); | |
| if (strippedBody !== $cartTa.val()) { | |
| $cartTa.val(strippedBody); | |
| } | |
| var contentsText = strippedBody; | |
| var textLength = stringToByte(contentsText); | |
| if ($('input:hidden[name="cartRemindSendType"]').val() == 'sms' && textLength > <?= $smsStringLimit; ?>) { | |
| } | |
| $('#cartRemindSendMessageCount').val(textLength); | |
| } | |
| /** | |
| * LMS 제목 Byte 체크 (공백 포함 최대 <?= $lmsSubjectLimit; ?>Byte, 초과분 자동 삭제) | |
| */ | |
| function changeCartRemindSubjectLength() { | |
| var input = $('#cartRemindSendSubject'); | |
| if (input.length === 0) { | |
| return; | |
| } | |
| var limit = <?= $lmsSubjectLimit; ?>; | |
| var text = stripEmoji(input.val()); | |
| while (stringToByte(text) > limit) { | |
| text = text.substring(0, text.length - 1); | |
| } | |
| input.val(text); | |
| $('#cartRemindSubjectCount').val(stringToByte(text)); | |
| } | |
| // 발송유형 따른 폼 변경 | |
| function changeCartRemindType() { | |
| if ($('input:radio[name="cartRemindType"]:checked').val() == 'manual') { | |
| $('.cart-remind-sms').hide(); | |
| $('.cart-remind-sms select').attr('disabled', 'disabled'); | |
| $('.cart-remind-sms input').attr('disabled', 'disabled'); | |
| $('#cartRemindSendSubject').prop('disabled', false); // LMS: 제목 영역 활성 | |
| // sms발송 | |
| } else if ($('input:hidden[name="cartRemindSendType"]').val() == 'sms') { | |
| $('.cart-remind-lms').hide(); | |
| $('.cart-remind-sms').show(); | |
| $('.cart-remind-sms select').removeAttr('disabled'); | |
| $('.cart-remind-sms input').removeAttr('disabled'); | |
| $('#cartRemindSendSubject').prop('disabled', true); // SMS: 제목 영역 비활성(값 유지, 미저장/미발송) | |
| } | |
| } | |
| // 발급방식에 따른 폼 변경 | |
| } | |
| return length; | |
| } | |
| /** | |
| * 이모티콘 제거 (제목/본문 이모티콘 입력 불가 - 자동 삭제) | |
| */ | |
| function stripEmoji(str) { | |
| if (!str) { | |
| return str; | |
| } | |
| return str | |
| .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '') | |
| .replace(/[\uFE00-\uFE0F\u200D\u20E3]/g, ''); | |
| } | |
| </script> | |
변경 전comeback_coupon_regist.php
| } | |
| if (e.target.checked) { | |
| $send_contents.val('(광고)\n' + $send_contents.val() + '\n무료거부 ' + $(selector).data('reject-number')); | |
| } | |
| refresh_send_contents(); | |
| // 본문 반영으로 SMS/LMS 판정이 끝난 뒤에 제목 처리 — 제목 영역이 비활성(SMS)이면 (광고) 미표기 | |
| if (e.target.checked && $smsSubject.length && !$smsSubject.prop('disabled')) { | |
| $smsSubject.val('(광고)' + $smsSubject.val()); | |
| setSubjectLength(); | |
| } | |
| }); | |
| } | |
| </script> | |
| } | |
| if (e.target.checked) { | |
| $send_contents.val('(광고)\n' + $send_contents.val() + '\n무료거부 ' + $(selector).data('reject-number')); | |
| if ($smsSubject.length) { | |
| $smsSubject.val('(광고)' + $smsSubject.val()); | |
| setSubjectLength(); | |
| } | |
| } | |
| refresh_send_contents(); | |
| }); | |
| } | |
| </script> | |
| <button type="button" class="btn btn-white btn-sm pull-right js-toggle-replace-code" data-target=".replace_code_area" data-text="치환코드 닫기">치환코드 보기</button> | |
| </div> | |
| </div> | |
| <div class="row pdt5"> | |
| <div class="col-xs-3 pdr0"> | |
| <label class="width100p"> | |
| 링크는 단축 URL로 자동 변환하였습니다.<br/> | |
| [단축 URL] 앱을 이용하여 단축 URL을 생성하면, 조회수 및 통계 자료를 확인하실 수 있습니다. <a href="https://apps.godo.co.kr/apps/1519" class="btn-link" target="_blank">바로가기</a> | |
| </div> | |
| </div> | |
| </div> | |
| </td> | |
| return length; | |
| } | |
| /** | |
| * SMS 내용 길이 체크 | |
| */ | |
| function setContentsLength(contentsNm, countId) { | |
| var textarea = $('textarea[name=' + contentsNm + ']'); | |
| var contentsText = textarea.val(); | |
| var textLength = stringToByte(contentsText); | |
| if (textLength > <?php echo $smsStringLimit;?>) { | |
| if (textLength > <?php echo $lmsStringLimit;?>) { | |
| $('.sms-type').hide(); | |
| $('.lms-type').show(); | |
| $('input[name=sendFl]').val('lms'); | |
| } else { | |
| $('#' + countId).css("color", ""); | |
| $('.sms-type').show(); | |
| $('.lms-type').hide(); | |
| $('input[name=sendFl]').val('sms'); | |
| } | |
| $('#' + countId).val(textLength); | |
| } | |
| // 글자수 체크 | |
| $('textarea[name=smsContents]').keyup(setSendLength).change(setSendLength); | |
| $("#frmCoupon").validate({ | |
| submitHandler: function (form) { | |
| changeTargetType(); | |
| checkSms(); | |
| setSendLength(); | |
| set_click_replace_code_insert('.replace-code-area .js-btn-insert'); | |
| set_change_focus_contents('textarea[name="smsContents"]'); | |
| set_click_sms080_contents(':checkbox[name="sms080Reject"]'); | |
| function set_click_sms080_contents (selector) { | |
| $(selector).click(function (e) { | |
| $send_contents.val($send_contents.val().replace(/(\(광고\)\n)|(\n무료거부\s[0-9\-]*)/g, '')); | |
| if (e.target.checked) { | |
| $send_contents.val('(광고)\n' + $send_contents.val() + '\n무료거부 ' + $(selector).data('reject-number')); | |
| } | |
| refresh_send_contents(); | |
| }); | |
변경 후comeback_coupon_regist.php
| } | |
| if (e.target.checked) { | |
| $send_contents.val('(광고)\n' + $send_contents.val() + '\n무료거부 ' + $(selector).data('reject-number')); | |
| if ($smsSubject.length) { | |
| $smsSubject.val('(광고)' + $smsSubject.val()); | |
| setSubjectLength(); | |
| } | |
| } | |
| refresh_send_contents(); | |
| }); | |
| } | |
| </script> | |
| } | |
| if (e.target.checked) { | |
| $send_contents.val('(광고)\n' + $send_contents.val() + '\n무료거부 ' + $(selector).data('reject-number')); | |
| } | |
| refresh_send_contents(); | |
| // 본문 반영으로 SMS/LMS 판정이 끝난 뒤에 제목 처리 — 제목 영역이 비활성(SMS)이면 (광고) 미표기 | |
| if (e.target.checked && $smsSubject.length && !$smsSubject.prop('disabled')) { | |
| $smsSubject.val('(광고)' + $smsSubject.val()); | |
| setSubjectLength(); | |
| } | |
| }); | |
| } | |
| </script> | |
| <button type="button" class="btn btn-white btn-sm pull-right js-toggle-replace-code" data-target=".replace_code_area" data-text="치환코드 닫기">치환코드 보기</button> | |
| </div> | |
| </div> | |
| <div class="row pdt5 js-subject-row"> | |
| <div class="col-xs-3 pdr0"> | |
| <input type="text" name="smsSubject" id="smsSubject" class="form-control width100p" placeholder="제목을 입력해주세요." value="<?= gd_isset($couponData['smsSubject']) ?>" disabled="disabled"/> | |
| <div class="mgt5"> | |
| <input type="text" id="smsSubjectCount" value="0" readonly="readonly" class="form-control width-3xs"> / <?= $lmsSubjectLimit; ?> Bytes | |
| </div> | |
| </div> | |
| </div> | |
| <div class="row pdt5"> | |
| <div class="col-xs-3 pdr0"> | |
| <label class="width100p"> | |
| 링크는 단축 URL로 자동 변환하였습니다.<br/> | |
| [단축 URL] 앱을 이용하여 단축 URL을 생성하면, 조회수 및 통계 자료를 확인하실 수 있습니다. <a href="https://apps.godo.co.kr/apps/1519" class="btn-link" target="_blank">바로가기</a> | |
| </div> | |
| <div class="notice-info">본문 내용이 LMS인 경우에만 제목 입력이 가능하며, 제목 영역에는 직접 (광고) 문구를 입력하지 않도록 하고 광고 삽입이 필요한 경우 광고성 문구 추가 기능을 사용해야 합니다.</div> | |
| </div> | |
| </div> | |
| </td> | |
| return length; | |
| } | |
| /** | |
| * 이모티콘 제거 (제목/본문 이모티콘 입력 불가 - 자동 삭제) | |
| */ | |
| function stripEmoji(str) { | |
| if (!str) { | |
| return str; | |
| } | |
| return str | |
| .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '') | |
| .replace(/[\uFE00-\uFE0F\u200D\u20E3]/g, ''); | |
| } | |
| /** | |
| * LMS 제목 Byte 체크 (공백 포함 최대 <?= $lmsSubjectLimit; ?>Byte, 초과분 자동 삭제) | |
| */ | |
| function setSubjectLength() { | |
| var input = $('#smsSubject'); | |
| if (input.length === 0) { | |
| return; | |
| } | |
| var limit = <?= $lmsSubjectLimit; ?>; | |
| var text = stripEmoji(input.val()); | |
| while (stringToByte(text) > limit) { | |
| text = text.substring(0, text.length - 1); | |
| } | |
| input.val(text); | |
| $('#smsSubjectCount').val(stringToByte(text)); | |
| } | |
| /** | |
| * SMS 내용 길이 체크 | |
| */ | |
| function setContentsLength(contentsNm, countId) { | |
| var textarea = $('textarea[name=' + contentsNm + ']'); | |
| var stripped = stripEmoji(textarea.val()); | |
| if (stripped !== textarea.val()) { | |
| textarea.val(stripped); | |
| } | |
| var contentsText = stripped; | |
| var textLength = stringToByte(contentsText); | |
| if (textLength > <?php echo $smsStringLimit;?>) { | |
| if (textLength > <?php echo $lmsStringLimit;?>) { | |
| $('.sms-type').hide(); | |
| $('.lms-type').show(); | |
| $('input[name=sendFl]').val('lms'); | |
| <?php if ($checkMode == 'canModify') { ?> | |
| $('#smsSubject').prop('disabled', false); // LMS: 제목 영역 활성 | |
| <?php } ?> | |
| setSubjectLength(); | |
| } else { | |
| $('#' + countId).css("color", ""); | |
| $('.sms-type').show(); | |
| $('.lms-type').hide(); | |
| $('input[name=sendFl]').val('sms'); | |
| $('#smsSubject').prop('disabled', true); // SMS: 제목 영역 비활성(값 유지) | |
| } | |
| $('#' + countId).val(textLength); | |
| } | |
| // 글자수 체크 | |
| $('textarea[name=smsContents]').keyup(setSendLength).change(setSendLength); | |
| $('#smsSubject').on('keyup keydown', setSubjectLength); | |
| $("#frmCoupon").validate({ | |
| submitHandler: function (form) { | |
| changeTargetType(); | |
| checkSms(); | |
| setSendLength(); | |
| setSubjectLength(); | |
| set_click_replace_code_insert('.replace-code-area .js-btn-insert'); | |
| set_change_focus_contents('textarea[name="smsContents"]'); | |
| set_click_sms080_contents(':checkbox[name="sms080Reject"]'); | |
| function set_click_sms080_contents (selector) { | |
| $(selector).click(function (e) { | |
| $send_contents.val($send_contents.val().replace(/(\(광고\)\n)|(\n무료거부\s[0-9\-]*)/g, '')); | |
| var $smsSubject = $('#smsSubject'); | |
| if ($smsSubject.length) { | |
| $smsSubject.val($smsSubject.val().replace(/^\(광고\)/, '')); | |
| } | |
| if (e.target.checked) { | |
| $send_contents.val('(광고)\n' + $send_contents.val() + '\n무료거부 ' + $(selector).data('reject-number')); | |
| if ($smsSubject.length) { | |
| $smsSubject.val('(광고)' + $smsSubject.val()); | |
| setSubjectLength(); | |
| } | |
| } | |
| refresh_send_contents(); | |
| }); | |
변경 전layer_cart_remind_message.php
| <span class="cart-remind-sms notice-info">SMS : 발송 건당 1포인트 차감</span> | |
| </div> | |
| </div> | |
| <div class="form-inline mgt10"> | |
| <textarea name="cartRemindSendMessage" rows="8" class="smsContents form-control width-xl"><?= $cartRemindData['cartRemindSendMessage']; ?></textarea> | |
| <div class="mgt5"> | |
| <a href="https://www.nhn-commerce.com/customer/board-view.gd?type=notice&idx=1237" target="_blank" class="btn-link">자세히보기></a> | |
| </p> | |
| <p class="notice-info">장바구니 링크 치환코드는 LMS인 경우에만 정상적으로 발송됩니다</p> | |
| </div> | |
| </td> | |
| </tr> | |
| // 글자수 체크 | |
| $('textarea[name=cartRemindSendMessage]').keyup(changeCartRemindContentsLength); | |
| changeCartRemindSendType(); | |
| changeCartRemindContentsLength(); | |
| }); | |
| /** | |
| * SMS 내용 길이 체크 | |
| */ | |
| function changeCartRemindContentsLength() { | |
| var contentsText = $('textarea[name=cartRemindSendMessage]').val(); | |
| var textLength = stringToByte(contentsText); | |
| if ($('input:hidden[name="cartRemindSendType"]').val() == 'sms' && textLength > <?= $smsStringLimit; ?>) { | |
| $('.cart-remind-sms').hide(); | |
| $('.cart-remind-sms select').attr('disabled', 'disabled'); | |
| $('.cart-remind-sms input').attr('disabled', 'disabled'); | |
| // sms발송 | |
| } else if ($('input:hidden[name="cartRemindSendType"]').val() == 'sms') { | |
| $('.cart-remind-lms').hide(); | |
| $('.cart-remind-sms').show(); | |
| $('.cart-remind-sms select').removeAttr('disabled'); | |
| $('.cart-remind-sms input').removeAttr('disabled'); | |
| } | |
| } | |
| /** | |
| } | |
| return length; | |
| } | |
| </script> | |
변경 후layer_cart_remind_message.php
| <span class="cart-remind-sms notice-info">SMS : 발송 건당 1포인트 차감</span> | |
| </div> | |
| </div> | |
| <div class="form-inline mgt10 js-cart-subject-row"> | |
| <input type="text" name="cartRemindSendSubject" id="cartRemindSendSubject" class="form-control width-xl" placeholder="제목을 입력해주세요." value="<?= gd_isset($cartRemindData['cartRemindSendSubject']); ?>" disabled="disabled"/> | |
| <input type="text" id="cartRemindSubjectCount" value="0" readonly="readonly" class="form-control width-3xs"> / <?= $lmsSubjectLimit; ?> Bytes | |
| </div> | |
| <div class="form-inline mgt10"> | |
| <textarea name="cartRemindSendMessage" rows="8" class="smsContents form-control width-xl"><?= $cartRemindData['cartRemindSendMessage']; ?></textarea> | |
| <div class="mgt5"> | |
| <a href="https://www.nhn-commerce.com/customer/board-view.gd?type=notice&idx=1237" target="_blank" class="btn-link">자세히보기></a> | |
| </p> | |
| <p class="notice-info">장바구니 링크 치환코드는 LMS인 경우에만 정상적으로 발송됩니다</p> | |
| <p class="notice-info">본문 내용이 LMS인 경우에만 제목 입력이 가능하며, 제목 영역에는 직접 (광고) 문구를 입력하지 않도록 하고 광고 삽입이 필요한 경우 광고성 문구 추가 기능을 사용해야 합니다.</p> | |
| </div> | |
| </td> | |
| </tr> | |
| // 글자수 체크 | |
| $('textarea[name=cartRemindSendMessage]').keyup(changeCartRemindContentsLength); | |
| $('#cartRemindSendSubject').on('keyup keydown', changeCartRemindSubjectLength); | |
| changeCartRemindSendType(); | |
| changeCartRemindContentsLength(); | |
| changeCartRemindSubjectLength(); | |
| }); | |
| /** | |
| * LMS 제목 Byte 체크 (공백 포함 최대 <?= $lmsSubjectLimit; ?>Byte, 초과분 자동 삭제) | |
| */ | |
| function changeCartRemindSubjectLength() { | |
| var input = $('#cartRemindSendSubject'); | |
| if (input.length === 0) { | |
| return; | |
| } | |
| var limit = <?= $lmsSubjectLimit; ?>; | |
| var text = stripEmoji(input.val()); | |
| while (stringToByte(text) > limit) { | |
| text = text.substring(0, text.length - 1); | |
| } | |
| input.val(text); | |
| $('#cartRemindSubjectCount').val(stringToByte(text)); | |
| } | |
| /** | |
| * SMS 내용 길이 체크 | |
| */ | |
| function changeCartRemindContentsLength() { | |
| var $cartTa = $('textarea[name=cartRemindSendMessage]'); | |
| var strippedBody = stripEmoji($cartTa.val()); | |
| if (strippedBody !== $cartTa.val()) { | |
| $cartTa.val(strippedBody); | |
| } | |
| var contentsText = strippedBody; | |
| var textLength = stringToByte(contentsText); | |
| if ($('input:hidden[name="cartRemindSendType"]').val() == 'sms' && textLength > <?= $smsStringLimit; ?>) { | |
| $('.cart-remind-sms').hide(); | |
| $('.cart-remind-sms select').attr('disabled', 'disabled'); | |
| $('.cart-remind-sms input').attr('disabled', 'disabled'); | |
| $('#cartRemindSendSubject').prop('disabled', false); // LMS: 제목 영역 활성 | |
| // sms발송 | |
| } else if ($('input:hidden[name="cartRemindSendType"]').val() == 'sms') { | |
| $('.cart-remind-lms').hide(); | |
| $('.cart-remind-sms').show(); | |
| $('.cart-remind-sms select').removeAttr('disabled'); | |
| $('.cart-remind-sms input').removeAttr('disabled'); | |
| $('#cartRemindSendSubject').prop('disabled', true); // SMS: 제목 영역 비활성(값 유지, 미저장/미발송) | |
| } | |
| } | |
| /** | |
| } | |
| return length; | |
| } | |
| /** | |
| * 이모티콘 제거 (제목/본문 이모티콘 입력 불가 - 자동 삭제) | |
| */ | |
| function stripEmoji(str) { | |
| if (!str) { | |
| return str; | |
| } | |
| return str | |
| .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '') | |
| .replace(/[\uFE00-\uFE0F\u200D\u20E3]/g, ''); | |
| } | |
| </script> | |
변경 전layer_comeback_coupon_sms.php
| <col style="width:80%" /> | |
| </colgroup> | |
| <tbody> | |
| <tr> | |
| <th>발송 내용</th> | |
| <td> | |
변경 후layer_comeback_coupon_sms.php
| <col style="width:80%" /> | |
| </colgroup> | |
| <tbody> | |
| <tr> | |
| <th>제목</th> | |
| <td> | |
| <input type="text" class="form-control width100p" readonly="readonly" value="<?= gd_isset($data['smsSubject']) !== '' ? gd_isset($data['smsSubject']) : '[제목없음]' ?>"/> | |
| </td> | |
| </tr> | |
| <tr> | |
| <th>발송 내용</th> | |
| <td> | |
변경 전layer_standby_sms.php
| */ | |
| ?> | |
| <form action="" method="post"> | |
| <div class="row"> | |
| <div class="col-xs-12"> | |
| <div class="pull-left"> | |
| <span class="sms-type text-darkblue">SMS : 발송 건당 1포인트 차감</span> | |
| <span class="lms-type text-orange-red display-none">LMS : 발송 건당 <?php echo $lmsPoint; ?>포인트 차감</span> | |
| </div> | |
| <div class="pull-right"> | |
| <input type="text" id="smsStringCount" value="0" readonly="readonly" class="form-control width-3xs"> / | |
| <span class="sms-type"><?php echo $smsStringLimit; ?></span><span class="lms-type display-none"><?php echo number_format($lmsStringLimit); ?></span> Bytes | |
| </div> | |
| </div> | |
| </div> | |
| <div class="row"> | |
| <div class="col-xs-12"> | |
| <textarea name="contents" id="contents" rows="8" class="form-control"><?= $data['contents']; ?></textarea> | |
| </div> | |
| </div> | |
| <div class="row"> | |
| <div class="center modal-footer"> | |
| <button type="submit" id="modify" class="btn btn-red">수정</button> | |
| $(document).ready(function () { | |
| var $textarea = $('textarea[name=contents]'); | |
| $textarea.on('keyup change', setSendLength).trigger('change'); | |
| }); | |
| function setSendLength() { | |
| setContentsLength('contents', 'smsStringCount'); | |
| $('.sms-type').hide(); | |
| $('.lms-type').show(); | |
| $('input[name=sendFl]').val('lms'); | |
| } else { | |
| $('#' + countId).css("color", ""); | |
| $('.sms-type').show(); | |
| $('.lms-type').hide(); | |
| $('input[name=sendFl]').val('sms'); | |
| } | |
| $('#' + countId).val(textLength); | |
| } | |
| } | |
| return length; | |
| } | |
| </script> | |
변경 후layer_standby_sms.php
| */ | |
| ?> | |
| <form action="" method="post"> | |
| <div class="row"> | |
| <div class="col-xs-12"> | |
| <div class="pull-right form-inline"> | |
| <input type="text" id="subjectStringCount" value="0" readonly="readonly" class="form-control width-3xs"> / <?= $lmsSubjectLimit; ?> Bytes | |
| </div> | |
| <div style="overflow:hidden; padding-right:10px;"> | |
| <input type="text" name="subject" id="subject" class="form-control" placeholder="제목을 입력해주세요." value="<?= gd_isset($data['subject']); ?>" disabled="disabled"/> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="row mgt10"> | |
| <div class="col-xs-12"> | |
| <textarea name="contents" id="contents" rows="8" class="form-control"><?= $data['contents']; ?></textarea> | |
| </div> | |
| </div> | |
| <div class="row"> | |
| <div class="col-xs-12"> | |
| <div class="pull-left"> | |
| <span class="sms-type text-darkblue">SMS : 발송 건당 1포인트 차감</span> | |
| <span class="lms-type text-orange-red display-none">LMS : 발송 건당 <?php echo $lmsPoint; ?>포인트 차감</span> | |
| </div> | |
| <div class="pull-right"> | |
| <input type="text" id="smsStringCount" value="0" readonly="readonly" class="form-control width-3xs"> / | |
| <span class="sms-type"><?php echo $smsStringLimit; ?></span><span class="lms-type display-none"><?php echo number_format($lmsStringLimit); ?></span> Bytes | |
| </div> | |
| </div> | |
| </div> | |
| <div class="row"> | |
| <div class="center modal-footer"> | |
| <button type="submit" id="modify" class="btn btn-red">수정</button> | |
| $(document).ready(function () { | |
| var $textarea = $('textarea[name=contents]'); | |
| $textarea.on('keyup change', setSendLength).trigger('change'); | |
| $('#subject').on('keyup keydown', setSubjectLength); | |
| setSubjectLength(); | |
| }); | |
| function setSendLength() { | |
| setContentsLength('contents', 'smsStringCount'); | |
| $('.sms-type').hide(); | |
| $('.lms-type').show(); | |
| $('input[name=sendFl]').val('lms'); | |
| $('#subject').prop('disabled', false); // LMS: 제목 영역 활성 | |
| setSubjectLength(); | |
| } else { | |
| $('#' + countId).css("color", ""); | |
| $('.sms-type').show(); | |
| $('.lms-type').hide(); | |
| $('input[name=sendFl]').val('sms'); | |
| $('#subject').prop('disabled', true); // SMS: 제목 영역 비활성(값 유지, 미발송) | |
| } | |
| $('#' + countId).val(textLength); | |
| } | |
| } | |
| return length; | |
| } | |
| /** | |
| * 이모티콘 제거 (제목/본문 이모티콘 입력 불가 - 자동 삭제) | |
| */ | |
| function stripEmoji(str) { | |
| if (!str) { | |
| return str; | |
| } | |
| return str | |
| .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '') | |
| .replace(/[\uFE00-\uFE0F\u200D\u20E3]/g, ''); | |
| } | |
| /** | |
| * LMS 제목 Byte 체크 (공백 포함 최대 <?= $lmsSubjectLimit; ?>Byte, 초과분 자동 삭제) | |
| */ | |
| function setSubjectLength() { | |
| var input = $('#subject'); | |
| if (input.length === 0) { | |
| return; | |
| } | |
| var limit = <?= $lmsSubjectLimit; ?>; | |
| var text = stripEmoji(input.val()); | |
| while (stringToByte(text) > limit) { | |
| text = text.substring(0, text.length - 1); | |
| } | |
| input.val(text); | |
| $('#subjectStringCount').val(stringToByte(text)); | |
| } | |
| </script> | |
변경 전member_crm_sms.php
| $listHtml[] = '<td class="text-center">' . $sSendFl . '</td>'; | |
| $listHtml[] = '<td style="word-break:break-all;word-wrap:break-word;overflow:hidden;" class="multirows">'; | |
| if ($data['sendFl'] != 'kakao') { | |
| $listHtml[] = '<div>' . $data['contents'] . '</div>'; | |
| } else { | |
| $listHtml[] = '<div>' . nl2br($data['templateContent']) . '</div>'; | |
변경 후member_crm_sms.php
| $listHtml[] = '<td class="text-center">' . $sSendFl . '</td>'; | |
| $listHtml[] = '<td style="word-break:break-all;word-wrap:break-word;overflow:hidden;" class="multirows">'; | |
| if ($data['sendFl'] != 'kakao') { | |
| // LMS 제목 — 있으면 그대로, 없으면 '[제목없음]' 표시(표시 시점 변환). 제목은 LMS 한정. | |
| if ($data['sendFl'] == 'lms') { | |
| $smsSubject = trim($data['subject'] ?? ''); | |
| if ($smsSubject === '') { | |
| $smsSubject = '[제목없음]'; | |
| } | |
| $listHtml[] = '<div><strong>' . gd_htmlspecialchars($smsSubject) . '</strong></div>'; | |
| } | |
| $listHtml[] = '<div>' . $data['contents'] . '</div>'; | |
| } else { | |
| $listHtml[] = '<div>' . nl2br($data['templateContent']) . '</div>'; | |
변경 전CartRemind.php
| $getCartRemindSend['autoSendTime'] = $cartRemindData['cartRemindAutoSendTime']; | |
| $getCartRemindSend['smsType'] = $cartRemindData['cartRemindSendType']; | |
| $getCartRemindSend['message'] = $cartRemindData['cartRemindSendMessage']; | |
| $getCartRemindSend['cartUrl'] = $cartRemindData['cartRemindSendUrl']; | |
| if ($cartRemindData['cartRemindCoupon'] > 0) { | |
| $getCartRemindSend['coupon'] = $cartRemindData['cartRemindCoupon']; | |
| $validator->add('cartRemindCoupon', null, null); // 발송쿠폰 | |
| $validator->add('cartRemindSendType', null, true); // 발송타입 (sms,lms) | |
| $validator->add('cartRemindSendMessage', null, true); // 발송메세지 | |
| if ($validator->act($arrData, true) === false) { | |
| throw new \Exception(gd_implode("<br/>", $validator->errors)); | |
| // 선택에 따른 값의 초기화를 위한 빈값 제거 - 주석처리 함 - 상태에 따른 빈값 저장(초기화)이 필요한 경우가 존재함. | |
| // $arrData = ArrayUtils::removeEmpty($arrData); | |
| switch (substr($arrData['mode'], 0, 6)) { | |
| case 'insert' : { | |
| // 저장 | |
| $validator->add('cartRemindNo', 'number', true); // 장바구니 알림 고유번호 | |
| $validator->add('cartRemindSendType', null, true); // 발송타입 (sms,lms) | |
| $validator->add('cartRemindSendMessage', null, true); // 발송메세지 | |
| if ($validator->act($arrData, true) === false) { | |
| throw new \Exception(gd_implode("<br/>", $validator->errors)); | |
| // 선택에 따른 값의 초기화를 위한 빈값 제거 - 주석처리 함 - 상태에 따른 빈값 저장(초기화)이 필요한 경우가 존재함. | |
| // $arrData = ArrayUtils::removeEmpty($arrData); | |
| // 수정 | |
| $arrBind = $this->db->get_binding(DBTableField::tableCartRemind(), $arrData, 'update', gd_array_keys($arrData), ['cartRemindNo']); | |
| $this->db->bind_param_push($arrBind['bind'], 'i', $arrData['cartRemindNo']); | |
| } | |
| // sms, lms | |
| $smsSendData['sendFl'] = $cartRemindSendData['smsType']; | |
| // ?? | |
| $smsSendData['agreeCnt'] = ''; | |
변경 후CartRemind.php
| $getCartRemindSend['autoSendTime'] = $cartRemindData['cartRemindAutoSendTime']; | |
| $getCartRemindSend['smsType'] = $cartRemindData['cartRemindSendType']; | |
| $getCartRemindSend['message'] = $cartRemindData['cartRemindSendMessage']; | |
| $getCartRemindSend['subject'] = $cartRemindData['cartRemindSendSubject'] ?? ''; | |
| $getCartRemindSend['cartUrl'] = $cartRemindData['cartRemindSendUrl']; | |
| if ($cartRemindData['cartRemindCoupon'] > 0) { | |
| $getCartRemindSend['coupon'] = $cartRemindData['cartRemindCoupon']; | |
| $validator->add('cartRemindCoupon', null, null); // 발송쿠폰 | |
| $validator->add('cartRemindSendType', null, true); // 발송타입 (sms,lms) | |
| $validator->add('cartRemindSendMessage', null, true); // 발송메세지 | |
| $validator->add('cartRemindSendSubject', null, null); // LMS 제목 (선택, lms 시) | |
| if ($validator->act($arrData, true) === false) { | |
| throw new \Exception(gd_implode("<br/>", $validator->errors)); | |
| // 선택에 따른 값의 초기화를 위한 빈값 제거 - 주석처리 함 - 상태에 따른 빈값 저장(초기화)이 필요한 경우가 존재함. | |
| // $arrData = ArrayUtils::removeEmpty($arrData); | |
| // LMS 제목은 LMS 상태에서만 저장(C5). 본문이 SMS면 제목 영역은 저장하지 않음(빈값). | |
| if (gd_isset($arrData['cartRemindSendType']) === 'sms') { | |
| $arrData['cartRemindSendSubject'] = ''; | |
| } | |
| switch (substr($arrData['mode'], 0, 6)) { | |
| case 'insert' : { | |
| // 저장 | |
| $validator->add('cartRemindNo', 'number', true); // 장바구니 알림 고유번호 | |
| $validator->add('cartRemindSendType', null, true); // 발송타입 (sms,lms) | |
| $validator->add('cartRemindSendMessage', null, true); // 발송메세지 | |
| $validator->add('cartRemindSendSubject', null, null); // LMS 제목 (선택, lms 시) | |
| if ($validator->act($arrData, true) === false) { | |
| throw new \Exception(gd_implode("<br/>", $validator->errors)); | |
| // 선택에 따른 값의 초기화를 위한 빈값 제거 - 주석처리 함 - 상태에 따른 빈값 저장(초기화)이 필요한 경우가 존재함. | |
| // $arrData = ArrayUtils::removeEmpty($arrData); | |
| // LMS 제목은 LMS 상태에서만 저장(C5). 본문이 SMS면 제목 영역은 저장하지 않음(빈값). | |
| if (gd_isset($arrData['cartRemindSendType']) === 'sms') { | |
| $arrData['cartRemindSendSubject'] = ''; | |
| } | |
| // 수정 | |
| $arrBind = $this->db->get_binding(DBTableField::tableCartRemind(), $arrData, 'update', gd_array_keys($arrData), ['cartRemindNo']); | |
| $this->db->bind_param_push($arrBind['bind'], 'i', $arrData['cartRemindNo']); | |
| } | |
| // sms, lms | |
| $smsSendData['sendFl'] = $cartRemindSendData['smsType']; | |
| // LMS 제목 (LMS 발송 시에만 SmsAdmin 에서 사용) | |
| $smsSendData['smsSubject'] = $cartRemindSendData['subject'] ?? ''; | |
| // ?? | |
| $smsSendData['agreeCnt'] = ''; | |
변경 전CouponAdmin.php
| 지금 바로 확인하세요!"; | |
| } | |
| $validator->add('smsContents', 'required', true); // SMS 발송 내용 | |
| // 전송일 null처리 | |
| $arrData['sendDt'] = null; | |
| $smsSendData['smsPoint'] = Sms::getPoint(); | |
| // 전송 내용 | |
| $smsSendData['smsContents'] = str_replace('rc_memNm', 'memNm', $getData['smsContents']); | |
| // 치환 코드 그룹 | |
| $smsSendData['replaceCodeGroup'] = 'promotion'; | |
| // 전송요청 수 | |
변경 후CouponAdmin.php
| 지금 바로 확인하세요!"; | |
| } | |
| $validator->add('smsContents', 'required', true); // SMS 발송 내용 | |
| $validator->add('smsSubject', null, null); // LMS 제목 (검증 없음, garbageDelete 방지용 등록) | |
| // 전송일 null처리 | |
| $arrData['sendDt'] = null; | |
| $smsSendData['smsPoint'] = Sms::getPoint(); | |
| // 전송 내용 | |
| $smsSendData['smsContents'] = str_replace('rc_memNm', 'memNm', $getData['smsContents']); | |
| // LMS 제목 (LMS 발송 시에만 SmsAdmin 에서 사용) | |
| $smsSendData['smsSubject'] = isset($getData['smsSubject']) ? $getData['smsSubject'] : ''; | |
| // 치환 코드 그룹 | |
| $smsSendData['replaceCodeGroup'] = 'promotion'; | |
| // 전송요청 수 | |
변경 전DBTableField.php
| ['val' => 'cartRemindAutoSendTime', 'typ' => 'i', 'def' => '10'], // 장바구니 알림 자동발송 시 발송 시간 | |
| ['val' => 'cartRemindSendType', 'typ' => 's', 'def' => 'lms'], // 장바구니 알림 전송 형식 - sms, lms | |
| ['val' => 'cartRemindSendMessage', 'typ' => 's', 'def' => '(광고)[{rc_mallNm}] {rc_memNm}님의 장바구니에 상품이 담겨 있습니다. 아래 장바구니 바로가기를 통해 바로 확인하실 수 있습니다. ▶ 장바구니 바로가기: {rc_cartRemindLink}'], // 장바구니 알림 전송 내용 | |
| ['val' => 'cartRemindSendUrl', 'typ' => 's', 'def' => ''], // 장바구니 알림 바로가기 링크 | |
| ['val' => 'cartRemindInsertAdminId', 'typ' => 's', 'def' => null], // 장바구니 알림 등록자 아이디 | |
| ['val' => 'managerNo', 'typ' => 'i', 'def' => 0], // 장바구니 알림 등록자 키 | |
| ['val' => 'smsAutoType', 'typ' => 's', 'def' => null], // SMS 자동발송 수신 종류 (member, admin, provider) | |
| ['val' => 'subject', 'typ' => 's', 'def' => null], // SMS 템플릿 제목 | |
| ['val' => 'contents', 'typ' => 's', 'def' => null], // SMS 템플릿 내용 | |
| ['val' => 'description', 'typ' => 's', 'def' => null], // 설명 | |
| ['val' => 'isUserBasic', 'typ' => 's', 'def' => 'n'], // 전송타입(user)기본제공여부 | |
| ['val' => 'modDt', 'typ' => 's', 'def' => null], // 수정일 | |
| ['val' => 'smsFl', 'typ' => 's', 'def' => 'n'], // sms동시 발송여부 - y:발송 / n:미발송 | |
| ['val' => 'smsSpamFl', 'typ' => 's', 'def' => 'n'], // 광고성 문구 추가 - y:추가 / n:미추가 | |
| ['val' => 'smsContents', 'typ' => 's', 'def' => ''], // SMS 발송 내용 | |
| ['val' => 'managerNo', 'typ' => 'i', 'def' => ''], // 등록 관리자 고유번호 | |
| ['val' => 'deleteFl', 'typ' => 's', 'def' => 'n'], // 삭제 flag - y:삭제 / n:미삭제 | |
| ['val' => 'sendDt', 'typ' => 's', 'def' => null], // 전송일 | |
변경 후DBTableField.php
| ['val' => 'cartRemindAutoSendTime', 'typ' => 'i', 'def' => '10'], // 장바구니 알림 자동발송 시 발송 시간 | |
| ['val' => 'cartRemindSendType', 'typ' => 's', 'def' => 'lms'], // 장바구니 알림 전송 형식 - sms, lms | |
| ['val' => 'cartRemindSendMessage', 'typ' => 's', 'def' => '(광고)[{rc_mallNm}] {rc_memNm}님의 장바구니에 상품이 담겨 있습니다. 아래 장바구니 바로가기를 통해 바로 확인하실 수 있습니다. ▶ 장바구니 바로가기: {rc_cartRemindLink}'], // 장바구니 알림 전송 내용 | |
| ['val' => 'cartRemindSendSubject', 'typ' => 's', 'def' => ''], // 장바구니 알림 LMS 제목 | |
| ['val' => 'cartRemindSendUrl', 'typ' => 's', 'def' => ''], // 장바구니 알림 바로가기 링크 | |
| ['val' => 'cartRemindInsertAdminId', 'typ' => 's', 'def' => null], // 장바구니 알림 등록자 아이디 | |
| ['val' => 'managerNo', 'typ' => 'i', 'def' => 0], // 장바구니 알림 등록자 키 | |
| ['val' => 'smsAutoType', 'typ' => 's', 'def' => null], // SMS 자동발송 수신 종류 (member, admin, provider) | |
| ['val' => 'subject', 'typ' => 's', 'def' => null], // SMS 템플릿 제목 | |
| ['val' => 'contents', 'typ' => 's', 'def' => null], // SMS 템플릿 내용 | |
| ['val' => 'messageTitle', 'typ' => 's', 'def' => null], // LMS 메시지 제목 | |
| ['val' => 'description', 'typ' => 's', 'def' => null], // 설명 | |
| ['val' => 'isUserBasic', 'typ' => 's', 'def' => 'n'], // 전송타입(user)기본제공여부 | |
| ['val' => 'modDt', 'typ' => 's', 'def' => null], // 수정일 | |
| ['val' => 'smsFl', 'typ' => 's', 'def' => 'n'], // sms동시 발송여부 - y:발송 / n:미발송 | |
| ['val' => 'smsSpamFl', 'typ' => 's', 'def' => 'n'], // 광고성 문구 추가 - y:추가 / n:미추가 | |
| ['val' => 'smsContents', 'typ' => 's', 'def' => ''], // SMS 발송 내용 | |
| ['val' => 'smsSubject', 'typ' => 's', 'def' => ''], // LMS 제목 | |
| ['val' => 'managerNo', 'typ' => 'i', 'def' => ''], // 등록 관리자 고유번호 | |
| ['val' => 'deleteFl', 'typ' => 's', 'def' => 'n'], // 삭제 flag - y:삭제 / n:미삭제 | |
| ['val' => 'sendDt', 'typ' => 's', 'def' => null], // 전송일 | |
변경 전SmsAdmin.php
| $dbData[$autoData[$autoType . 'Mode']][$smsType][$autoCode][$autoType]['sno'] = $autoData[$autoType . 'Sno']; | |
| $dbData[$autoData[$autoType . 'Mode']][$smsType][$autoCode][$autoType]['subject'] = $autoData['subject']; | |
| $dbData[$autoData[$autoType . 'Mode']][$smsType][$autoCode][$autoType]['contents'] = $autoData[$autoType . 'Contents']; | |
| // $dbData[$autoData[$autoType . 'Mode']][$smsType][$autoCode][$autoType]['smsType'] = $smsType; | |
| unset($request[$smsType][$autoCode][$autoType . 'Mode']); | |
| unset($request[$smsType][$autoCode][$autoType . 'Sno']); | |
| unset($request[$smsType][$autoCode]['subject']); | |
| unset($request[$smsType][$autoCode][$autoType . 'Contents']); | |
| } | |
| } | |
| } | |
| $getData = gd_htmlspecialchars_stripslashes($this->db->query_fetch($strSQL, null, false)); | |
| foreach ($getData as $data) { | |
| $setData[$data['smsType']][$data['smsAutoCode']][$data['smsAutoType']]['contents'] = $data['contents']; | |
| $setData[$data['smsType']][$data['smsAutoCode']][$data['smsAutoType']]['sno'] = $data['sno']; | |
| } | |
| unset($getData); | |
| foreach ($arrType as $sendType) { | |
| if (isset($setData[$keyType][$val['code']][$sendType]['contents']) === true) { | |
| $smsAutoType[$keyType][$key][$sendType . 'Contents'] = $setData[$keyType][$val['code']][$sendType]['contents']; | |
| $smsAutoType[$keyType][$key][$sendType . 'Mode'] = 'update'; | |
| $smsAutoType[$keyType][$key][$sendType . 'Sno'] = $setData[$keyType][$val['code']][$sendType]['sno']; | |
| } else { | |
| $smsAutoType[$keyType][$key][$sendType . 'Contents'] = $val[$sendType . 'Contents']; | |
| $smsAutoType[$keyType][$key][$sendType . 'Mode'] = 'insert'; | |
| $smsAutoType[$keyType][$key][$sendType . 'Sno'] = ''; | |
| } | |
| } | |
| if ($receiverData['sendFl'] === 'lms') { | |
| $message = new \Component\Sms\LmsMessage($receiverData['smsContents'], $receiverData['replaceCodeGroup']); | |
| } else { | |
| $message = new \Component\Sms\SmsMessage($receiverData['smsContents'], $receiverData['replaceCodeGroup']); | |
| } | |
변경 후SmsAdmin.php
| $dbData[$autoData[$autoType . 'Mode']][$smsType][$autoCode][$autoType]['sno'] = $autoData[$autoType . 'Sno']; | |
| $dbData[$autoData[$autoType . 'Mode']][$smsType][$autoCode][$autoType]['subject'] = $autoData['subject']; | |
| $dbData[$autoData[$autoType . 'Mode']][$smsType][$autoCode][$autoType]['contents'] = $autoData[$autoType . 'Contents']; | |
| $dbData[$autoData[$autoType . 'Mode']][$smsType][$autoCode][$autoType]['messageTitle'] = gd_isset($autoData[$autoType . 'MessageTitle'], ''); | |
| // $dbData[$autoData[$autoType . 'Mode']][$smsType][$autoCode][$autoType]['smsType'] = $smsType; | |
| unset($request[$smsType][$autoCode][$autoType . 'Mode']); | |
| unset($request[$smsType][$autoCode][$autoType . 'Sno']); | |
| unset($request[$smsType][$autoCode]['subject']); | |
| unset($request[$smsType][$autoCode][$autoType . 'Contents']); | |
| unset($request[$smsType][$autoCode][$autoType . 'MessageTitle']); | |
| } | |
| } | |
| } | |
| $getData = gd_htmlspecialchars_stripslashes($this->db->query_fetch($strSQL, null, false)); | |
| foreach ($getData as $data) { | |
| $setData[$data['smsType']][$data['smsAutoCode']][$data['smsAutoType']]['contents'] = $data['contents']; | |
| $setData[$data['smsType']][$data['smsAutoCode']][$data['smsAutoType']]['messageTitle'] = $data['messageTitle']; | |
| $setData[$data['smsType']][$data['smsAutoCode']][$data['smsAutoType']]['sno'] = $data['sno']; | |
| } | |
| unset($getData); | |
| foreach ($arrType as $sendType) { | |
| if (isset($setData[$keyType][$val['code']][$sendType]['contents']) === true) { | |
| $smsAutoType[$keyType][$key][$sendType . 'Contents'] = $setData[$keyType][$val['code']][$sendType]['contents']; | |
| $messageTitle = gd_isset($setData[$keyType][$val['code']][$sendType]['messageTitle'], ''); | |
| $smsAutoType[$keyType][$key][$sendType . 'MessageTitle'] = $messageTitle; | |
| $smsAutoType[$keyType][$key][$sendType . 'Title'] = $messageTitle; // CRM 뷰 호환(messageTitle 일원화) | |
| $smsAutoType[$keyType][$key][$sendType . 'Mode'] = 'update'; | |
| $smsAutoType[$keyType][$key][$sendType . 'Sno'] = $setData[$keyType][$val['code']][$sendType]['sno']; | |
| } else { | |
| $smsAutoType[$keyType][$key][$sendType . 'Contents'] = $val[$sendType . 'Contents']; | |
| $smsAutoType[$keyType][$key][$sendType . 'MessageTitle'] = ''; | |
| $smsAutoType[$keyType][$key][$sendType . 'Title'] = ''; // CRM 뷰 호환 | |
| $smsAutoType[$keyType][$key][$sendType . 'Mode'] = 'insert'; | |
| $smsAutoType[$keyType][$key][$sendType . 'Sno'] = ''; | |
| } | |
| } | |
| if ($receiverData['sendFl'] === 'lms') { | |
| $message = new \Component\Sms\LmsMessage($receiverData['smsContents'], $receiverData['replaceCodeGroup']); | |
| // LMS 제목 (미입력 시 빈 값) | |
| // 튜닝 상점 대비: 구버전 SmsSender(setSubject 미보유)에서 발송 중단 방지 | |
| if (method_exists($transport, 'setSubject')) { | |
| $transport->setSubject($receiverData['smsSubject'] ?? ''); | |
| } | |
| } else { | |
| $message = new \Component\Sms\SmsMessage($receiverData['smsContents'], $receiverData['replaceCodeGroup']); | |
| } | |
변경 전SmsAuto.php
| { | |
| $logger = $this->logger; | |
| $binds = []; | |
| $this->db->strField = 'smsType, smsAutoType, contents, subject'; | |
| $this->db->strJoin = DB_SMS_CONTENTS; | |
| $this->db->strWhere = 'smsType= ? AND smsAutoCode = ? AND smsAutoType IN (\'' . gd_implode('\', \'', $wheres) . '\') AND contents != \'\' AND contents IS NOT NULL'; | |
| $this->db->bind_param_push($binds, 's', $this->smsType); | |
| } | |
| $transport->setSmsPoint(Sms::getPoint()); | |
| $transport->setMessage($message); | |
| $transport->setSmsType($item['smsType']); | |
| $transport->setReceiver($receiverData); | |
| $transport->setSendDate($this->smsAutoSendDate); | |
변경 후SmsAuto.php
| { | |
| $logger = $this->logger; | |
| $binds = []; | |
| $this->db->strField = 'smsType, smsAutoType, contents, subject, messageTitle'; | |
| $this->db->strJoin = DB_SMS_CONTENTS; | |
| $this->db->strWhere = 'smsType= ? AND smsAutoCode = ? AND smsAutoType IN (\'' . gd_implode('\', \'', $wheres) . '\') AND contents != \'\' AND contents IS NOT NULL'; | |
| $this->db->bind_param_push($binds, 's', $this->smsType); | |
| } | |
| $transport->setSmsPoint(Sms::getPoint()); | |
| $transport->setMessage($message); | |
| // LMS 제목 (설정된 자동발송 문구 제목 - LMS 발송 시에만 SmsSender 에서 사용, 미입력 시 [제목없음]) | |
| // 튜닝 상점 대비: 구버전 SmsSender(setSubject 미보유)에서 발송 중단 방지 | |
| if (method_exists($transport, 'setSubject')) { | |
| $transport->setSubject($item['messageTitle'] ?? ''); | |
| } | |
| $transport->setSmsType($item['smsType']); | |
| $transport->setReceiver($receiverData); | |
| $transport->setSendDate($this->smsAutoSendDate); | |
변경 전SmsSender.php
| protected $isThrowPasswordException = false; | |
| /** @var string|null SMS 발송 트리거 타입 (예: FALLBACK) */ | |
| protected $sendTriggerType; | |
| /** @var string SMS 대량발송 파일 경로 */ | |
| private $_smsLargeFilePath; | |
| /** @var object SMS 대량발송 TXT 파일 생성 로거 */ | |
| ]; | |
| //@formatter:on | |
| if ($this->_isLms()) { | |
| $this->sendSms['subject'] = ''; | |
| } | |
| if ($this->sendTriggerType !== null) { | |
| $this->sendSms['sendTriggerType'] = $this->sendTriggerType; | |
| ]; | |
| if ($this->_isLms()) { | |
| $this->smsLog['sendFl'] = 'lms'; | |
| } | |
| } | |
| $this->sendTriggerType = $sendTriggerType; | |
| } | |
| /** | |
| * @param bool $isThrowPasswordException | |
| */ | |
변경 후SmsSender.php
| protected $isThrowPasswordException = false; | |
| /** @var string|null SMS 발송 트리거 타입 (예: FALLBACK) */ | |
| protected $sendTriggerType; | |
| /** @var string|null LMS 제목 */ | |
| protected $subject; | |
| /** @var string SMS 대량발송 파일 경로 */ | |
| private $_smsLargeFilePath; | |
| /** @var object SMS 대량발송 TXT 파일 생성 로거 */ | |
| ]; | |
| //@formatter:on | |
| if ($this->_isLms()) { | |
| $this->sendSms['subject'] = $this->resolveSubject(); | |
| } | |
| if ($this->sendTriggerType !== null) { | |
| $this->sendSms['sendTriggerType'] = $this->sendTriggerType; | |
| ]; | |
| if ($this->_isLms()) { | |
| $this->smsLog['sendFl'] = 'lms'; | |
| $this->smsLog['subject'] = trim(preg_replace('/#?\{[^}]*\}/u', '', (string) $this->subject)); // 저장은 치환자 제거한 원문(빈값 유지), [제목없음] 변환은 발송/표시 시점만 | |
| } | |
| } | |
| $this->sendTriggerType = $sendTriggerType; | |
| } | |
| /** | |
| * LMS 제목 설정 (LMS 발송 시에만 사용) | |
| * | |
| * @param string|null $subject | |
| */ | |
| public function setSubject(?string $subject): void | |
| { | |
| $this->subject = $subject; | |
| } | |
| /** | |
| * 실발송용 LMS 제목 계산 | |
| * - 제목 치환자({..}/#{..})는 미지원이므로 공란 처리 | |
| * - LMS 인데 제목이 없으면(또는 치환자만 있어 공란) '[제목없음]' 으로 발송 | |
| * | |
| * @return string | |
| */ | |
| protected function resolveSubject(): string | |
| { | |
| // 치환자 제거 (제목 영역은 치환자 미지원 → 실발송 시 공란 처리) | |
| $subject = trim(preg_replace('/#?\{[^}]*\}/u', '', (string) $this->subject)); | |
| if ($subject === '') { | |
| return '[제목없음]'; | |
| } | |
| return $subject; | |
| } | |
| /** | |
| * @param bool $isThrowPasswordException | |
| */ | |
변경 전LayerPreviewMobileSendController.php
| switch ($sendMethod) { | |
| case 'SMS': | |
| $smsData = $payload['smsLmsRequest'] ?? []; | |
| $this->setData('mainContents', $smsData['content'] ?? ''); | |
| $this->setData('showAdWarningText', 'n'); | |
| $previewContents = 'crm/preview_mobile_send/layer_preview_mobile_send_sms.php'; | |
| $this->setData('friendtalk', $friendTalkData); | |
| $this->setData('alternativeContents', $friendTalkData['alternativeInfo']['content'] ?? ''); | |
| $this->setData('showAdWarningText', $showAdWarningText); | |
| $previewContents = 'crm/preview_mobile_send/layer_preview_mobile_send_kakao_friendtalk.php'; | |
| break; | |
| $this->setData('template', $previewMeta); | |
| $this->setData('hasAddChannelButton', $hasAddChannelButton); | |
| $this->setData('alternativeContents', $alimTalkData['alternativeInfo']['content'] ?? ''); | |
| $this->setData('showAdWarningText', 'n'); | |
| $previewContents = 'crm/preview_mobile_send/layer_preview_mobile_send_kakao_alimtalk.php'; | |
| break; | |
| $this->setData('myappPayload', $myappPushData); | |
| $this->setData('showAdWarningText', $showAdWarningText); | |
| $this->setData('alternativeContents', $payload['myappRequest']['alternativeInfo']['content'] ?? ''); | |
| $previewContents = 'crm/preview_mobile_send/layer_preview_mobile_send_myapp_push.php'; | |
| break; | |
| } | |
변경 후LayerPreviewMobileSendController.php
| switch ($sendMethod) { | |
| case 'SMS': | |
| $smsData = $payload['smsLmsRequest'] ?? []; | |
| $this->setData('mainTitle', $smsData['title'] ?? ''); | |
| $this->setData('mainContents', $smsData['content'] ?? ''); | |
| $this->setData('showAdWarningText', 'n'); | |
| $previewContents = 'crm/preview_mobile_send/layer_preview_mobile_send_sms.php'; | |
| $this->setData('friendtalk', $friendTalkData); | |
| $this->setData('alternativeContents', $friendTalkData['alternativeInfo']['content'] ?? ''); | |
| // 대체 제목 미입력 시 메인 메시지 타이틀(친구톡 헤더)이 있으면 카피하여 표기 (미리보기 전용) | |
| $alternativeTitle = $friendTalkData['alternativeInfo']['title'] ?? ''; | |
| if ($alternativeTitle === '' || $alternativeTitle === null) { | |
| $alternativeTitle = $friendTalkData['header'] ?? ''; | |
| } | |
| $this->setData('alternativeTitle', $alternativeTitle); | |
| $this->setData('showAdWarningText', $showAdWarningText); | |
| $previewContents = 'crm/preview_mobile_send/layer_preview_mobile_send_kakao_friendtalk.php'; | |
| break; | |
| $this->setData('template', $previewMeta); | |
| $this->setData('hasAddChannelButton', $hasAddChannelButton); | |
| $this->setData('alternativeContents', $alimTalkData['alternativeInfo']['content'] ?? ''); | |
| $this->setData('alternativeTitle', $alimTalkData['alternativeInfo']['title'] ?? ''); | |
| $this->setData('showAdWarningText', 'n'); | |
| $previewContents = 'crm/preview_mobile_send/layer_preview_mobile_send_kakao_alimtalk.php'; | |
| break; | |
| $this->setData('myappPayload', $myappPushData); | |
| $this->setData('showAdWarningText', $showAdWarningText); | |
| $this->setData('alternativeContents', $payload['myappRequest']['alternativeInfo']['content'] ?? ''); | |
| // 대체 제목 미입력 시 메인 메시지 타이틀(푸시 제목)이 있으면 카피하여 표기 (미리보기 전용) | |
| $alternativeTitle = $payload['myappRequest']['alternativeInfo']['title'] ?? ''; | |
| if ($alternativeTitle === '' || $alternativeTitle === null) { | |
| $alternativeTitle = $myappPushData['pushSubject'] ?? ''; | |
| } | |
| $this->setData('alternativeTitle', $alternativeTitle); | |
| $previewContents = 'crm/preview_mobile_send/layer_preview_mobile_send_myapp_push.php'; | |
| break; | |
| } | |
변경 전LayerKakaoFriendtalkContentSettingController.php
| $friendtalkRequest = $defaultCampaignRequest['kakaoFriendtalkRequest'] ?? []; | |
| $initialTextContent = $friendtalkRequest['text']['content'] ?? ''; | |
| $initialAlternativeMessage = $defaultCampaignRequest['smsLmsRequest']['content'] ?? ''; | |
| $this->setData('is080RejectAvailable', $is080RejectAvailable); | |
| $this->setData('campaignMessageTypes', CampaignMessageType::cases()); | |
| $this->setData('friendtalkRequest', $friendtalkRequest); | |
| $this->setData('initialTextContent', $initialTextContent); | |
| $this->setData('initialAlternativeMessage', $initialAlternativeMessage); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| } | |
| } | |
변경 후LayerKakaoFriendtalkContentSettingController.php
| $friendtalkRequest = $defaultCampaignRequest['kakaoFriendtalkRequest'] ?? []; | |
| $initialTextContent = $friendtalkRequest['text']['content'] ?? ''; | |
| $initialAlternativeMessage = $defaultCampaignRequest['smsLmsRequest']['content'] ?? ''; | |
| $initialAlternativeTitle = $defaultCampaignRequest['smsLmsRequest']['title'] ?? ''; | |
| $this->setData('is080RejectAvailable', $is080RejectAvailable); | |
| $this->setData('campaignMessageTypes', CampaignMessageType::cases()); | |
| $this->setData('friendtalkRequest', $friendtalkRequest); | |
| $this->setData('initialTextContent', $initialTextContent); | |
| $this->setData('initialAlternativeMessage', $initialAlternativeMessage); | |
| $this->setData('initialAlternativeTitle', $initialAlternativeTitle); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| } | |
| } | |
변경 전LayerMobileSendSaveSmsTemplateController.php
| { | |
| $request = Request::post()->toArray(); | |
| $contents = $request['contents'] ?? ''; | |
| $categories = SmsTemplateCategory::getFindOptions(); | |
| $this->setData('categories', $categories); | |
| $this->setData('contents', $contents); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| } | |
변경 후LayerMobileSendSaveSmsTemplateController.php
| { | |
| $request = Request::post()->toArray(); | |
| $contents = $request['contents'] ?? ''; | |
| $messageTitle = $request['messageTitle'] ?? ''; | |
| $categories = SmsTemplateCategory::getFindOptions(); | |
| $this->setData('categories', $categories); | |
| $this->setData('contents', $contents); | |
| $this->setData('messageTitle', $messageTitle); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| } | |
변경 전LayerMyappPushContentSettingController.php
| $initialTitle = $myappRequest['title'] ?? ''; | |
| $initialMessage = $myappRequest['content'] ?? ''; | |
| $initialAlternativeMessage = $recipeContext['defaultCampaignRequest']['smsLmsRequest']['content'] ?? ''; | |
| $this->setData('is080RejectAvailable', $is080RejectAvailable); | |
| $this->setData('myappPushSendConditions', MyappPushSendCondition::cases()); | |
| $this->setData('initialTitle', $initialTitle); | |
| $this->setData('initialMessage', $initialMessage); | |
| $this->setData('initialAlternativeMessage', $initialAlternativeMessage); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| } | |
| } | |
변경 후LayerMyappPushContentSettingController.php
| $initialTitle = $myappRequest['title'] ?? ''; | |
| $initialMessage = $myappRequest['content'] ?? ''; | |
| $initialAlternativeMessage = $recipeContext['defaultCampaignRequest']['smsLmsRequest']['content'] ?? ''; | |
| $initialAlternativeTitle = $recipeContext['defaultCampaignRequest']['smsLmsRequest']['title'] ?? ''; | |
| $this->setData('is080RejectAvailable', $is080RejectAvailable); | |
| $this->setData('myappPushSendConditions', MyappPushSendCondition::cases()); | |
| $this->setData('initialTitle', $initialTitle); | |
| $this->setData('initialMessage', $initialMessage); | |
| $this->setData('initialAlternativeMessage', $initialAlternativeMessage); | |
| $this->setData('initialAlternativeTitle', $initialAlternativeTitle); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| } | |
| } | |
변경 전LayerSmsContentSettingController.php
| $recipeContext = $this->resolveRecipeContext(); | |
| $isRecipeContext = $this->hasRecipeContext(); | |
| $initialMessage = $recipeContext['defaultCampaignRequest']['smsLmsRequest']['content'] ?? ''; | |
| $this->setData('is080RejectAvailable', $is080RejectAvailable); | |
| $this->setData('isRecipeContext', $isRecipeContext); | |
| $this->setData('initialMessage', $initialMessage); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| } | |
| } | |
변경 후LayerSmsContentSettingController.php
| $recipeContext = $this->resolveRecipeContext(); | |
| $isRecipeContext = $this->hasRecipeContext(); | |
| $initialMessage = $recipeContext['defaultCampaignRequest']['smsLmsRequest']['content'] ?? ''; | |
| $initialTitle = $recipeContext['defaultCampaignRequest']['smsLmsRequest']['title'] ?? ''; | |
| $this->setData('is080RejectAvailable', $is080RejectAvailable); | |
| $this->setData('isRecipeContext', $isRecipeContext); | |
| $this->setData('initialMessage', $initialMessage); | |
| $this->setData('initialTitle', $initialTitle); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| } | |
| } | |
변경 전SmsTemplatePsController.php
| 'templateCategory' => $category->value, | |
| 'templateTitle' => $subject, | |
| 'templateMessageContent' => $contents, | |
| ]); | |
| $sno = $service->setSmsContents($templateDto); | |
변경 후SmsTemplatePsController.php
| 'templateCategory' => $category->value, | |
| 'templateTitle' => $subject, | |
| 'templateMessageContent' => $contents, | |
| 'templateMessageTitle' => trim($request['messageTitle'] ?? ''), | |
| ]); | |
| $sno = $service->setSmsContents($templateDto); | |
변경 전SmsAutoController.php
| // SMS 포인트 Sync | |
| Sms::saveSmsPoint(); | |
| $memberJoin = ComponentUtils::getPolicy('member.join'); | |
| $this->setData('smsAutoList', Sms::SMS_AUTO_RECEIVE_LIST); | |
| $this->setData('smsAutoOrderPeriod', Sms::SMS_AUTO_ORDER_PERIOD); | |
| $this->setData('smsAutoOrderAfterPeriod', Sms::SMS_ORDER_AFTER_PERIOD); | |
변경 후SmsAutoController.php
| // SMS 포인트 Sync | |
| Sms::saveSmsPoint(); | |
| $memberJoin = ComponentUtils::getPolicy('member.join'); | |
| $this->setData('lmsSubjectLimit', defined(Sms::class . '::LMS_SUBJECT_LIMIT') ? Sms::LMS_SUBJECT_LIMIT : 40); | |
| $this->setData('smsAutoList', Sms::SMS_AUTO_RECEIVE_LIST); | |
| $this->setData('smsAutoOrderPeriod', Sms::SMS_AUTO_ORDER_PERIOD); | |
| $this->setData('smsAutoOrderAfterPeriod', Sms::SMS_ORDER_AFTER_PERIOD); | |
변경 전SmsLogPsController.php
| try { | |
| $requestParams = $request->post()->all(); | |
| $godoSms = new GodoSmsServerApi(); | |
| $smsLog = $componentSmsLog->getSmsLog('*', $requestParams['smsLogSno']); | |
| if ($smsLog['replaceCodeType'] == 'none') { | |
| // SMS 결과 수신 처리 | |
| if ($godoSms->smsReserveChange($requestParams['sno'], 'modify', $requestParams['contents']) !== true) { | |
| throw new LayerException(__('수정이 실패되었습니다.')); | |
| } else { | |
| $componentSmsLog->editContents($requestParams); | |
| $this->json(__('수정되었습니다.')); | |
| } | |
| } else { | |
| // SMS 결과 수신 처리 | |
| if ($godoSms->smsSendListReserveChange($requestParams['sno'], 'modify', $requestParams['contents']) !== true) { | |
| throw new LayerException(__('수정이 실패되었습니다.')); | |
| } else { | |
| $componentSmsLog->editContents($requestParams); | |
| $this->json(__('수정되었습니다.')); | |
| } | |
| } | |
| } catch (LayerException $e) { | |
| $this->json($e->getMessage()); | |
| } | |
변경 후SmsLogPsController.php
| try { | |
| $requestParams = $request->post()->all(); | |
| $godoSms = new GodoSmsServerApi(); | |
| // 발송내역 고유번호 (수정 레이어는 sno 로 전달) | |
| $smsLogSno = gd_isset($requestParams['smsLogSno'], gd_isset($requestParams['sno'])); | |
| $smsLog = $componentSmsLog->getSmsLog('*', $smsLogSno); | |
| if (empty($smsLog)) { | |
| throw new LayerException(__('발송내역을 찾을 수 없습니다.')); | |
| } | |
| // 예약변경 API 는 DB 의 contents/subject 를 읽어 외부(고도 SMS 서버)로 전송하므로 | |
| // 외부 예약 메시지에 수정 내용이 반영되도록 DB 를 먼저 갱신한다. | |
| $requestParams['sno'] = $smsLogSno; | |
| $componentSmsLog->editContents($requestParams); | |
| if ($smsLog['replaceCodeType'] == 'none') { | |
| $result = $godoSms->smsReserveChange($smsLogSno, 'modify'); | |
| } else { | |
| // 치환코드 발송건은 수신자별로 재구성되므로 해당 발송내역의 발송리스트 sno 목록을 전달한다. | |
| $smsSendList = $componentSmsLog->getSmsSendList(['smsLogSno' => $smsLogSno]); | |
| $sendListSno = []; | |
| foreach ((array) gd_isset($smsSendList['data'], []) as $sendListRow) { | |
| $sendListSno[] = $sendListRow['sno']; | |
| } | |
| $result = $godoSms->smsSendListReserveChange($smsLogSno, 'modify', $sendListSno); | |
| } | |
| if ($result !== true) { | |
| throw new LayerException(__('수정이 실패되었습니다.')); | |
| } | |
| $this->json(__('수정되었습니다.')); | |
| } catch (LayerException $e) { | |
| $this->json($e->getMessage()); | |
| } | |
변경 전SmsSendController.php
| 'board' => '게시판', | |
| ]; | |
| $smsContents = ''; | |
| $receiveTotal = $rejectCount = 0; | |
| $receiverData = $reSenderData = []; | |
| $popupMode = false; | |
| $componentSmsLog = \App::load('Component\\Sms\\SmsLog'); | |
| $smsLog = $componentSmsLog->getSmsLog('*', $request->post()->get('smsLogSno')); // 재전송 문자내역 조회 | |
| $smsContents = StringUtils::htmlSpecialCharsStripSlashes($smsLog['contents']); // 재전송 메시지 설정 | |
| $smsSendList = $componentSmsLog->getSmsSendList($request->post()->all())['data']; // 재전송 문자내역 발송내역 조회 | |
| $hasGuest = $componentSmsLog->hasGuestBySendList($smsSendList); // 발송내역 중 비회원 발송내역 확인 | |
| $isReSendAll = $request->post()->get('mode', '') == 'resend_all_member'; | |
| $this->setData('sms080Policy', ComponentUtils::getPolicy('sms.sms080')); | |
| $this->setData('smsStringLimit', Sms::SMS_STRING_LIMIT); | |
| $this->setData('lmsStringLimit', Sms::LMS_STRING_LIMIT); | |
| $this->setData('smsForbidTime', Sms::SMS_FORBID_TIME); | |
| $this->setData('lmsPoint', Sms::LMS_POINT); | |
| $this->setData('smsCallNum', $smsCallNum); | |
| $this->setData('receiverMode', $receiverMode); | |
| $this->setData('popupMode', $popupMode); | |
| $this->setData('smsContents', $smsContents); | |
| $this->setData('reSenderData', $reSenderData); | |
| $this->setData('receiveTotal', $receiveTotal); | |
| $this->setData('rejectCount', $rejectCount); | |
변경 후SmsSendController.php
| 'board' => '게시판', | |
| ]; | |
| $smsContents = ''; | |
| $smsSubject = ''; | |
| $receiveTotal = $rejectCount = 0; | |
| $receiverData = $reSenderData = []; | |
| $popupMode = false; | |
| $componentSmsLog = \App::load('Component\\Sms\\SmsLog'); | |
| $smsLog = $componentSmsLog->getSmsLog('*', $request->post()->get('smsLogSno')); // 재전송 문자내역 조회 | |
| $smsContents = StringUtils::htmlSpecialCharsStripSlashes($smsLog['contents']); // 재전송 메시지 설정 | |
| $smsSubject = StringUtils::htmlSpecialCharsStripSlashes($smsLog['subject'] ?? ''); // 재전송 LMS 제목 복원 | |
| $smsSendList = $componentSmsLog->getSmsSendList($request->post()->all())['data']; // 재전송 문자내역 발송내역 조회 | |
| $hasGuest = $componentSmsLog->hasGuestBySendList($smsSendList); // 발송내역 중 비회원 발송내역 확인 | |
| $isReSendAll = $request->post()->get('mode', '') == 'resend_all_member'; | |
| $this->setData('sms080Policy', ComponentUtils::getPolicy('sms.sms080')); | |
| $this->setData('smsStringLimit', Sms::SMS_STRING_LIMIT); | |
| $this->setData('lmsStringLimit', Sms::LMS_STRING_LIMIT); | |
| $this->setData('lmsSubjectLimit', defined(Sms::class . '::LMS_SUBJECT_LIMIT') ? Sms::LMS_SUBJECT_LIMIT : 40); | |
| $this->setData('smsForbidTime', Sms::SMS_FORBID_TIME); | |
| $this->setData('lmsPoint', Sms::LMS_POINT); | |
| $this->setData('smsCallNum', $smsCallNum); | |
| $this->setData('receiverMode', $receiverMode); | |
| $this->setData('popupMode', $popupMode); | |
| $this->setData('smsContents', $smsContents); | |
| $this->setData('smsSubject', $smsSubject); | |
| $this->setData('reSenderData', $reSenderData); | |
| $this->setData('receiveTotal', $receiveTotal); | |
| $this->setData('rejectCount', $rejectCount); | |
변경 전CartRemindRegistController.php
| $this->setData('selected', $selected); | |
| $this->setData('smsStringLimit', Sms::SMS_STRING_LIMIT); | |
| $this->setData('lmsStringLimit', Sms::LMS_STRING_LIMIT); | |
| $this->setData('lmsPoint', Sms::LMS_POINT); | |
| $this->setData('sms080Policy', ComponentUtils::getPolicy('sms.sms080')); | |
| $this->setData('commerceSmsRefusalIntroUrl', ConfigUrlUtils::getNhnCommerceEchostUrl('sms-refusal-intro')); | |
변경 후CartRemindRegistController.php
| $this->setData('selected', $selected); | |
| $this->setData('smsStringLimit', Sms::SMS_STRING_LIMIT); | |
| $this->setData('lmsStringLimit', Sms::LMS_STRING_LIMIT); | |
| $this->setData('lmsSubjectLimit', defined(Sms::class . '::LMS_SUBJECT_LIMIT') ? Sms::LMS_SUBJECT_LIMIT : 40); | |
| $this->setData('lmsPoint', Sms::LMS_POINT); | |
| $this->setData('sms080Policy', ComponentUtils::getPolicy('sms.sms080')); | |
| $this->setData('commerceSmsRefusalIntroUrl', ConfigUrlUtils::getNhnCommerceEchostUrl('sms-refusal-intro')); | |
변경 전ComebackCouponRegistController.php
| ]); | |
| $this->setData('smsStringLimit', Sms::SMS_STRING_LIMIT); | |
| $this->setData('lmsStringLimit', Sms::LMS_STRING_LIMIT); | |
| $this->setData('smsForbidTime', Sms::SMS_FORBID_TIME); | |
| $this->setData('lmsPoint', Sms::LMS_POINT); | |
| $this->setData('checkMode', gd_isset($checkMode)); | |
변경 후ComebackCouponRegistController.php
| ]); | |
| $this->setData('smsStringLimit', Sms::SMS_STRING_LIMIT); | |
| $this->setData('lmsStringLimit', Sms::LMS_STRING_LIMIT); | |
| $this->setData('lmsSubjectLimit', defined(Sms::class . '::LMS_SUBJECT_LIMIT') ? Sms::LMS_SUBJECT_LIMIT : 40); | |
| $this->setData('smsForbidTime', Sms::SMS_FORBID_TIME); | |
| $this->setData('lmsPoint', Sms::LMS_POINT); | |
| $this->setData('checkMode', gd_isset($checkMode)); | |
변경 전LayerCartRemindMessageController.php
| { | |
| $cartRemindNo = Request::get()->get('cartRemindNo'); | |
| $cartRemind = new CartRemind(); | |
| $cartRemindData = $cartRemind->getCartRemindInfo($cartRemindNo,'cartRemindNo, cartRemindSendType, cartRemindSendMessage'); | |
| $this->setData('cartRemindData', $cartRemindData); | |
| $this->setData('smsStringLimit', Sms::SMS_STRING_LIMIT); | |
| $this->setData('lmsStringLimit', Sms::LMS_STRING_LIMIT); | |
| $this->setData('lmsPoint', Sms::LMS_POINT); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| } | |
변경 후LayerCartRemindMessageController.php
| { | |
| $cartRemindNo = Request::get()->get('cartRemindNo'); | |
| $cartRemind = new CartRemind(); | |
| $cartRemindData = $cartRemind->getCartRemindInfo($cartRemindNo,'cartRemindNo, cartRemindSendType, cartRemindSendMessage, cartRemindSendSubject'); | |
| $this->setData('cartRemindData', $cartRemindData); | |
| $this->setData('smsStringLimit', Sms::SMS_STRING_LIMIT); | |
| $this->setData('lmsStringLimit', Sms::LMS_STRING_LIMIT); | |
| $this->setData('lmsSubjectLimit', defined(Sms::class . '::LMS_SUBJECT_LIMIT') ? Sms::LMS_SUBJECT_LIMIT : 40); | |
| $this->setData('lmsPoint', Sms::LMS_POINT); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| } | |
변경 전LayerStandbySmsController.php
| { | |
| /** @var \Bundle\Component\Sms\SmsLog $smsLog */ | |
| $smsLog = App::load('\\Component\\Sms\\SmsLog'); | |
| $data = $smsLog->getSmsLog('sno, sendFl, contents, contentsMask', Request::get()->get('sno')); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| $this->setData('data', gd_htmlspecialchars_stripslashes($data)); | |
| $this->setData('smsStringLimit', Sms::SMS_STRING_LIMIT); | |
| $this->setData('lmsStringLimit', Sms::LMS_STRING_LIMIT); | |
| $this->setData('smsForbidTime', Sms::SMS_FORBID_TIME); | |
| $this->setData('lmsPoint', Sms::LMS_POINT); | |
| } | |
변경 후LayerStandbySmsController.php
| { | |
| /** @var \Bundle\Component\Sms\SmsLog $smsLog */ | |
| $smsLog = App::load('\\Component\\Sms\\SmsLog'); | |
| $data = $smsLog->getSmsLog('sno, sendFl, subject, contents, contentsMask', Request::get()->get('sno')); | |
| $this->getView()->setDefine('layout', 'layout_layer.php'); | |
| $this->setData('data', gd_htmlspecialchars_stripslashes($data)); | |
| $this->setData('smsStringLimit', Sms::SMS_STRING_LIMIT); | |
| $this->setData('lmsStringLimit', Sms::LMS_STRING_LIMIT); | |
| $this->setData('lmsSubjectLimit', defined(Sms::class . '::LMS_SUBJECT_LIMIT') ? Sms::LMS_SUBJECT_LIMIT : 40); | |
| $this->setData('smsForbidTime', Sms::SMS_FORBID_TIME); | |
| $this->setData('lmsPoint', Sms::LMS_POINT); | |
| } | |