日曆元件總覽(QA)

對稿 Figma p2:桌機(≥992px,Tailwind lg)=日曆面板;平板與手機(<992px)=rolldate 滾輪。 縮放視窗即可切換。桌機面板已無標題列、無 X、無確認鈕;點日期直接帶入並關閉,Esc 可關閉。 每個範例都附「簡化 HTML」—— 日曆鈕、面板、隱藏的 store 欄位都由元件生成, 頁面端只要一個 <input>(dp003 的民國/西元 tab 可以只貼一個空的 <div datepicker003TabWrap class="tw-h-42 tw-w-[128px] tw-shrink-0"> 佔位, 兩顆按鈕與滑塊由元件生;貼完整 tab 標記的舊頁面也照舊沿用)。 實頁既有的標記則原樣沿用不重建,所以舊頁不必重貼也會自動升級。

汽車任意險自訂生效日

data-date-mode="comprehensiveAuto" 可選 今天 ~ 後兩個月月底;現在時間過 12:00 就改從明天起算。(計算與 effectiveDate 完全相同)

12:00 前為今日、之後為明日起算
JS 塞值:
簡化 HTML
<div class="tw-form-group">
    <label formLabel for="caDate" class="tw-form-label">標籤文字</label>
    <div datepicker001 data-date-mode="comprehensiveAuto" data-date-format="us"
         data-plugin="comp/datepicker001,datepicker" data-type="comp" data-comp-name="datepicker001"
         class="tw-form-wrap tw-relative tw-bg-white">
      <input type="tel" datepicker001Input name="caDate" id="caDate" autocomplete="off" class="tw-form-input" placeholder="0000 / 00 / 00">
    </div>
  </div>
監聽範例(addEventListener)
document.getElementById('caDate')
  .addEventListener('datepicker:change', (e) => {
    // e.detail.value    '2026/08/08'      ← 西元 yyyy/mm/dd,判斷與送後端用這個
    // e.detail.display  '2026 / 08 / 08'  ← 畫面文字
    if (!e.detail.value) return;          // 空字串=被清掉了
    doCheckDate(e.detail.id);
  });

火險預定生效日

data-date-mode="houseEffectiveDate" 可選 今天 ~ 未來 90 天,12:00 後改從明天起算。

最遠可選到未來 90 天
JS 塞值:
簡化 HTML
<div class="tw-form-group">
    <label formLabel for="efDate" class="tw-form-label">標籤文字</label>
    <div datepicker001 data-date-mode="houseEffectiveDate" data-date-format="us"
         data-plugin="comp/datepicker001,datepicker" data-type="comp" data-comp-name="datepicker001"
         class="tw-form-wrap tw-relative tw-bg-white">
      <input type="tel" datepicker001Input name="efDate" id="efDate" autocomplete="off" class="tw-form-input" placeholder="0000 / 00 / 00">
    </div>
  </div>
監聽範例(addEventListener)
document.getElementById('efDate')
  .addEventListener('datepicker:change', (e) => {
    // e.detail.value    '2026/08/08'
    // e.detail.display  '2026 / 08 / 08'
    if (!e.detail.value) return;
    doCheckDate(e.detail.id);
  });

留學出發日(年份 tab 版)

data-date-mode="overseaDepartureDate" 最早 = 4 個工作天後,最晚 = 今天 +59 天(含今天共 60 天)。工作天只跳週末、不扣國定假日;偏移量依星期幾查表:日 +4、一 +4、二~五 +6、六 +5。範圍依實頁 ECH30300 的 dateCheck。面板 header 是年份 tab,不是年份下拉。

出發日期
  • ‧
    因保單處理及電訪需作業時間,請提早4個工作天投保
  • ‧
    出發日期最晚不可超過60天
請輸入或選擇西元日期,例:出發日期為2024/10/4,保單生效日為2024/10/3 24時
JS 塞值:
簡化 HTML
<div class="tw-form-group">
    <label formLabel for="departureDate" class="tw-form-label">標籤文字</label>
    <div datepicker001 data-date-mode="overseaDepartureDate" data-date-format="us"
         data-plugin="comp/datepicker001,datepicker" data-type="comp" data-comp-name="datepicker001"
         class="tw-form-wrap tw-relative tw-bg-white">
      <!-- 注意:departureDate.html 這支 partial 把 name/id 寫死,也不吃 placeholder -->
      <input type="tel" datepicker001Input name="departureDate" id="departureDate" autocomplete="off" class="tw-form-input">
    </div>
  </div>
監聽範例(addEventListener)
document.getElementById('departureDate')
  .addEventListener('datepicker:change', (e) => {
    // e.detail.value    '2026/08/07'      ← 4 個工作天後起算
    // e.detail.mode     'overseaDepartureDate'
    if (!e.detail.value) return;
    checkDepartureDate();
  });

跨年模擬(把「今天」凍在指定時間)

日期規則都是從「今天」現算的,跨年那一刻會整份位移。最需要看的是 出發日(overseaDepartureDate): 可選範圍是「4 個工作天後 ~ 今天 +59 天」,年底時這個視窗會跨到隔年, 面板 header 的年份 tab 必須出現兩個年份(例如 2026 / 2027), 日期格也要能翻到隔年 1 月。 按鈕會把 Date 凍在該時間並重新初始化這兩個實例;按「還原」或重新整理即可回到真實時間。

凍結時間:

原發照日期(車/機車 form004)

data-date-mode="originIssueDate" 可選 今天 −50 年 ~ 今天;面板預設停在 今年 −3 / 當月 / 同日。範圍依實頁 ECV3_2200 的 doCheckOriginIssueDate(近 50 年)。注意與 dp002 出廠年月的 −59 不同。

實頁設定:mode=originIssueDate+民國
JS 塞值:
簡化 HTML
<div class="tw-form-group">
    <label formLabel for="originIssueDate" class="tw-form-label">標籤文字</label>
    <div datepicker001 data-date-mode="originIssueDate" data-date-format="tw"
         data-plugin="comp/datepicker001,datepicker" data-type="comp" data-comp-name="datepicker001"
         class="tw-form-wrap tw-relative tw-bg-white">
      <input type="tel" datepicker001Input name="originIssueDate" id="originIssueDate" autocomplete="off" class="tw-form-input" placeholder="000/00/00">
    </div>
  </div>
監聽範例(addEventListener)
document.getElementById('originIssueDate')
  .addEventListener('datepicker:change', (e) => {
    // e.detail.value    '2006/07/12'      ← 一律西元,不受民國顯示影響
    // e.detail.display  '095 / 07 / 12'   ← 畫面上的民國文字
    if (!e.detail.value) return;
    doCheckOriginIssueDate('N');
  });

出廠年月(空值)

面板寬 276、只有年/月兩個 tab、清單高 324;選年自動切到月、選月直接帶入並關閉。選中項應有淺綠底+勾。

datepicker002 沒有 mode 屬性,規則固定:年份清單 = 今年 −59 ~ 今年(車齡 59 年以內),月份 01~12 全開(選今年時只到當月);欄位空白時面板預設停在 今年 −3 / 當月(欄位仍維持空白,不會自動帶值)。

請選擇西元年、月
JS 塞值:
簡化 HTML
<div class="tw-form-group">
    <label formLabel for="ymEmpty" class="tw-form-label">標籤文字</label>
    <div datepicker002 data-plugin="comp/datepicker002,datepicker" data-type="comp" data-comp-name="datepicker002"
         class="tw-form-wrap tw-relative tw-bg-white">
      <input type="tel" datepicker002Input name="ymEmpty" id="ymEmpty" autocomplete="off" class="tw-form-input" placeholder="0000 / 00">
    </div>
  </div>
監聽範例(addEventListener)
document.getElementById('ymEmpty')
  .addEventListener('datepicker:change', (e) => {
    // e.detail.value    '2023/06/01'      ← 年月欄位,日固定補 01
    // e.detail.display  '2023 / 06'
    initMadeDate();
    doChgCarModelData('modelBrand', 'N');
  });

出廠年月(帶值)

JS 塞值:
簡化 HTML
<div class="tw-form-group">
    <label formLabel for="ymVal" class="tw-form-label">標籤文字</label>
    <div datepicker002 data-plugin="comp/datepicker002,datepicker" data-type="comp" data-comp-name="datepicker002"
         class="tw-form-wrap tw-relative tw-bg-white">
      <input type="tel" datepicker002Input name="ymVal" id="ymVal" autocomplete="off" class="tw-form-input" value="2011 / 05" placeholder="0000 / 00">
    </div>
  </div>
監聽範例(addEventListener)
document.getElementById('ymVal')
  .addEventListener('datepicker:change', (e) => {
    // e.detail.value    '2011/05/01'
    // e.detail.display  '2011 / 05'
    // 帶初值的欄位:載入時不會發,使用者改了才發
    doCheckMadeDate('N');
  });

出廠年月(disabled)

JS 塞值:
簡化 HTML
<div class="tw-form-group tw-has-disabled">
    <label formLabel for="ymDis" class="tw-form-label">標籤文字</label>
    <div datepicker002 data-plugin="comp/datepicker002,datepicker" data-type="comp" data-comp-name="datepicker002"
         class="tw-form-wrap disabled tw-relative tw-bg-white">
      <input type="tel" datepicker002Input name="ymDis" id="ymDis" autocomplete="off" class="tw-form-input" disabled value="2022 / 04" placeholder="0000 / 00">
    </div>
  </div>
監聽範例(addEventListener)
document.getElementById('ymDis')
  .addEventListener('datepicker:change', (e) => {
    // 停用中的欄位不會有使用者操作,但程式呼叫 setValue() 仍會發
    // e.detail.value    '2011/05/01'
    console.log('停用欄位被程式改值', e.detail.value);
  });

民國生日

沒有 mode 屬性,規則固定在元件裡(dateMode = "dob" 寫死)—— 頁面上寫 data-date-mode 不會有任何作用,別照著 dp001 的寫法貼。 可選 今天 −100 年 ~ 今天;面板與手機滾輪預設停在 今天 −35 年 (dp001 的 dob 停在 −18 年,這是兩支元件在日期規則上唯一的差別)。欄位空白時送出用的 名稱Store 也維持空白,預設只決定面板停在哪、不會自動帶值。 data-date-format="tw" / "us" 只決定初始 tab 落在民國或西元,使用者按 tab 可以切;送出的值跟著當下 tab 的格式走。

滾輪年份應顯示民國(閏年已修正)
JS 塞值:
簡化 HTML
<!-- 頁面端只要 input + 一個 tab 佔位;日曆鈕、面板、tab 內容全部由元件生 -->
  <div datepicker003 data-date-format="tw"
       data-plugin="comp/datepicker003,datepicker" data-type="comp" data-comp-name="datepicker003">
    <div class="tw-flex tw-flex-col lg:tw-flex-row tw-items-start tw-gap-8">
      <!-- tab 只貼佔位;兩顆按鈕與滑塊由元件生,尺寸留在頁面上避免 CLS -->
      <div datepicker003TabWrap class="tw-h-42 tw-w-[128px] tw-shrink-0"></div>
      <div class="tw-w-full lg:tw-w-auto tw-grow">
        <div datepicker003InputWrap class="tw-form-wrap tw-relative tw-bg-white">
          <input type="tel" datepicker003Input name="d3Tw" id="d3Tw" autocomplete="off" class="tw-form-input">
        </div>
          </div>
    </div>
  </div>
監聽範例(addEventListener)
document.getElementById('d3Tw')
  .addEventListener('datepicker:change', (e) => {
    // e.detail.value    '1980/03/04'      ← 一律西元,不受民國/西元 tab 影響
    // e.detail.display  '069 / 03 / 04'   ← 畫面文字,切 tab 會變
    // e.detail.format   'tw' | 'us'       ← 使用者現在看的是哪一種
    // 切換曆制不會發事件(值沒變,只換顯示格式)
    doCheckBirthday();
  });

西元生日

JS 塞值:
簡化 HTML
<!-- 頁面端只要 input + 一個 tab 佔位;日曆鈕、面板、tab 內容全部由元件生 -->
  <div datepicker003 data-date-format="us"
       data-plugin="comp/datepicker003,datepicker" data-type="comp" data-comp-name="datepicker003">
    <div class="tw-flex tw-flex-col lg:tw-flex-row tw-items-start tw-gap-8">
      <!-- tab 只貼佔位;兩顆按鈕與滑塊由元件生,尺寸留在頁面上避免 CLS -->
      <div datepicker003TabWrap class="tw-h-42 tw-w-[128px] tw-shrink-0"></div>
      <div class="tw-w-full lg:tw-w-auto tw-grow">
        <div datepicker003InputWrap class="tw-form-wrap tw-relative tw-bg-white">
          <input type="tel" datepicker003Input name="d3Us" id="d3Us" autocomplete="off" class="tw-form-input">
        </div>
          </div>
    </div>
  </div>
監聽範例(addEventListener)
document.getElementById('d3Us')
  .addEventListener('datepicker:change', (e) => {
    // e.detail.value    '1980/03/04'
    // e.detail.display  '1980 / 03 / 04'
    // e.detail.format   'us'
    doCheckBirthday();
  });

民國生日(帶值)

JS 塞值:
簡化 HTML
<!-- 頁面端只要 input + 一個 tab 佔位;日曆鈕、面板、tab 內容全部由元件生 -->
  <div datepicker003 data-date-format="tw"
       data-plugin="comp/datepicker003,datepicker" data-type="comp" data-comp-name="datepicker003">
    <div class="tw-flex tw-flex-col lg:tw-flex-row tw-items-start tw-gap-8">
      <!-- tab 只貼佔位;兩顆按鈕與滑塊由元件生,尺寸留在頁面上避免 CLS -->
      <div datepicker003TabWrap class="tw-h-42 tw-w-[128px] tw-shrink-0"></div>
      <div class="tw-w-full lg:tw-w-auto tw-grow">
        <div datepicker003InputWrap class="tw-form-wrap tw-relative tw-bg-white">
          <input type="tel" datepicker003Input name="d3TwVal" id="d3TwVal" autocomplete="off" class="tw-form-input" value="075 / 01 / 01">
        </div>
          </div>
    </div>
  </div>
監聽範例(addEventListener)
document.getElementById('d3TwVal')
  .addEventListener('datepicker:change', (e) => {
    // e.detail.value    '1986/01/01'
    // e.detail.display  '075 / 01 / 01'
    // 按上面的「西元/民國」切換:value 不變,所以不會發事件
    doCheckBirthday();
  });

民國生日(disabled)

停用時:民國/西元 tab 與日曆鈕都應該變灰、點不動、Tab 跳過;綠色滑塊改灰但位置不動(仍看得出目前是哪一種曆制)。下面的狀態切換列按「停用/預設」可測動態切換。

簡化 HTML
<!-- 停用只要照一般欄位的寫法標三個地方,tab 與日曆鈕由元件自己同步 -->
  <div class="tw-form-group tw-has-disabled">          <!-- ① 群組 -->
    <div datepicker003 data-date-format="tw" ...>
      <div datepicker003TabWrap class="tw-h-42 tw-w-[128px] tw-shrink-0"></div>   <!-- tab 佔位 -->
      <div datepicker003InputWrap class="tw-form-wrap disabled ...">   <!-- ② 外框 -->
        <input type="tel" datepicker003Input name="d3TwDis" id="d3TwDis" autocomplete="off" class="tw-form-input" disabled value="068 / 03 / 15">  <!-- ③ 欄位 -->
      </div>
    </div>
  </div>
  <!-- 動態切換走既有的 global-inseb.js API,元件會自己跟上 -->
  setInputStatus(document.querySelector('#d3TwDis'), 'disabled');
  setInputStatus(document.querySelector('#d3TwDis'), 'default');
監聽範例(addEventListener)
document.getElementById('d3TwDis')
  .addEventListener('datepicker:change', (e) => {
    // 停用中的欄位:tab 與日曆鈕都點不動,但 setValue() 仍會發
    // e.detail.value    '1986/01/01'
    console.log('停用欄位被程式改值', e.detail.value);
  });

民國生日(tab 由元件生成)

頁面只貼一個帶尺寸的佔位 <div datepicker003TabWrap>,滑塊與兩顆按鈕由元件生。行為、無障礙屬性、停用態都與上面貼完整標記的版本相同;既有頁面不受影響(偵測到已有 tab 就不會再生)。

JS 塞值:
簡化 HTML
<div datepicker003 data-date-format="tw"
       data-plugin="comp/datepicker003,datepicker" data-type="comp" data-comp-name="datepicker003">
    <div class="tw-flex tw-flex-col lg:tw-flex-row tw-items-start tw-gap-8">
      <!-- 只要這一行:尺寸與版面留在頁面(避免 CLS),內容物由元件生 -->
      <div datepicker003TabWrap class="tw-h-42 tw-w-[128px] tw-shrink-0"></div>
      <div class="tw-w-full lg:tw-w-auto tw-grow">
        <div datepicker003InputWrap class="tw-form-wrap tw-relative tw-bg-white">
          <input type="tel" datepicker003Input name="d3Gen" id="d3Gen" autocomplete="off" class="tw-form-input">
        </div>
      </div>
    </div>
  </div>
監聽範例(addEventListener)
document.getElementById('d3Gen')
  .addEventListener('datepicker:change', (e) => {
    // tab 由元件生成的版本,事件與貼完整標記的版本完全相同
    // e.detail.value    '1980/03/04'
    // e.detail.format   'tw' | 'us'
    doCheckBirthday();
  });

旅遊期間(起訖區間)

HTML 只有 <label> 和送出用的 <input name="duration">;外框、兩個顯示框、「~」、 日曆鈕都是 datepicker005 用 JS 生的。送出的值仍是 YYYY/MM/DD ~ YYYY/MM/DD 一串掛在 duration 上,後端契約沒變。 面板為桌機(≥992px)限定。

data-mode="oversea" 起始日可選 今天 ~ 今天 +90 天;點完起始日後,結束日只開到 起始日 +180 天,超出的日期會變成不可選。

JS 塞值:
簡化 HTML
<div data-type="comp" data-plugin="comp/datepicker005,easepick" data-comp-name="datepicker005"
     data-mode="oversea" data-css="/css/easepick.css" class="tw-form-group">
  <label formLabel for="qaRangeOversea" class="tw-form-label">國外旅遊期間</label>
  <input type="tel" datepicker005Input name="duration" id="qaRangeOversea" autocomplete="off" readonly>
</div>
監聽範例(addEventListener)
document.getElementById('qaRangeOversea')
  .addEventListener('datepicker:change', (e) => {
    // e.detail.value  '2026/08/01 ~ 2026/09/20'
    // e.detail.start  '2026/08/01'   ← 已拆好,不用自己 split(' ~ ')
    // e.detail.end    '2026/09/20'
    if (!e.detail.start || !e.detail.end) return;  // 只選一半或被清空
    getAmountFromServer();
  });

data-mode="domestic" 起始日可選 今天 ~ 今天 +90 天;點完起始日後,結束日只開到 起始日 +14 天,超出的日期會變成不可選。

JS 塞值:
簡化 HTML
<div data-type="comp" data-plugin="comp/datepicker005,easepick" data-comp-name="datepicker005"
     data-mode="domestic" data-css="/css/easepick.css" class="tw-form-group">
  <label formLabel for="qaRangeDomestic" class="tw-form-label">國內旅遊期間</label>
  <input type="tel" datepicker005Input name="duration" id="qaRangeDomestic" autocomplete="off" readonly>
</div>
監聽範例(addEventListener)
document.getElementById('qaRangeDomestic')
  .addEventListener('datepicker:change', (e) => {
    // e.detail.value  '2026/08/01 ~ 2026/08/14'   ← 國內上限 14 天
    // e.detail.start  '2026/08/01'
    // e.detail.end    '2026/08/14'
    if (!e.detail.start || !e.detail.end) return;
    getAmountFromServer();
  });

起始日/結束日:淺綠圈 #76DB9B + 深綠字 #00522D + 2px 邊框 #59BE81; 中間日:淺綠色帶 #D2F6DC + 深色字 #191C1A、圓圈無底。 實頁(calc003)版本另見 /travel/calc003.html。

選擇旅遊期間
一
二
三
四
五
六
日