|
144 | 144 | </div> |
145 | 145 | </div> |
146 | 146 | </div> |
| 147 | + <button |
| 148 | + @click="showGuideModal = true" |
| 149 | + class="btn btn-secondary" |
| 150 | + :title="t('admin.subscriptions.guide.showGuide')" |
| 151 | + > |
| 152 | + <Icon name="questionCircle" size="md" /> |
| 153 | + </button> |
147 | 154 | <button @click="showAssignModal = true" class="btn btn-primary"> |
148 | 155 | <Icon name="plus" size="md" class="mr-2" /> |
149 | 156 | {{ t('admin.subscriptions.assignSubscription') }} |
|
638 | 645 | @confirm="confirmResetQuota" |
639 | 646 | @cancel="showResetQuotaConfirm = false" |
640 | 647 | /> |
| 648 | + <!-- Subscription Guide Modal --> |
| 649 | + <teleport to="body"> |
| 650 | + <transition name="modal"> |
| 651 | + <div v-if="showGuideModal" class="fixed inset-0 z-50 flex items-center justify-center p-4" @mousedown.self="showGuideModal = false"> |
| 652 | + <div class="fixed inset-0 bg-black/50" @click="showGuideModal = false"></div> |
| 653 | + <div class="relative max-h-[85vh] w-full max-w-2xl overflow-y-auto rounded-xl bg-white p-6 shadow-2xl dark:bg-dark-800"> |
| 654 | + <button type="button" class="absolute right-4 top-4 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200" @click="showGuideModal = false"> |
| 655 | + <svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" /></svg> |
| 656 | + </button> |
| 657 | + |
| 658 | + <h2 class="mb-4 text-lg font-bold text-gray-900 dark:text-white">{{ t('admin.subscriptions.guide.title') }}</h2> |
| 659 | + <p class="mb-5 text-sm text-gray-500 dark:text-gray-400">{{ t('admin.subscriptions.guide.subtitle') }}</p> |
| 660 | + |
| 661 | + <!-- Step 1 --> |
| 662 | + <div class="mb-5"> |
| 663 | + <h3 class="mb-2 flex items-center gap-2 text-sm font-semibold text-gray-900 dark:text-white"> |
| 664 | + <span class="flex h-6 w-6 items-center justify-center rounded-full bg-primary-100 text-xs font-bold text-primary-700 dark:bg-primary-900/40 dark:text-primary-300">1</span> |
| 665 | + {{ t('admin.subscriptions.guide.step1.title') }} |
| 666 | + </h3> |
| 667 | + <ol class="ml-8 list-decimal space-y-1 text-sm text-gray-600 dark:text-gray-300"> |
| 668 | + <li>{{ t('admin.subscriptions.guide.step1.line1') }}</li> |
| 669 | + <li>{{ t('admin.subscriptions.guide.step1.line2') }}</li> |
| 670 | + <li>{{ t('admin.subscriptions.guide.step1.line3') }}</li> |
| 671 | + </ol> |
| 672 | + <div class="ml-8 mt-2"> |
| 673 | + <router-link |
| 674 | + to="/admin/groups" |
| 675 | + @click="showGuideModal = false" |
| 676 | + class="inline-flex items-center gap-1 text-sm font-medium text-primary-600 hover:text-primary-700 dark:text-primary-400 dark:hover:text-primary-300" |
| 677 | + > |
| 678 | + {{ t('admin.subscriptions.guide.step1.link') }} |
| 679 | + <Icon name="arrowRight" size="xs" /> |
| 680 | + </router-link> |
| 681 | + </div> |
| 682 | + </div> |
| 683 | + |
| 684 | + <!-- Step 2 --> |
| 685 | + <div class="mb-5"> |
| 686 | + <h3 class="mb-2 flex items-center gap-2 text-sm font-semibold text-gray-900 dark:text-white"> |
| 687 | + <span class="flex h-6 w-6 items-center justify-center rounded-full bg-primary-100 text-xs font-bold text-primary-700 dark:bg-primary-900/40 dark:text-primary-300">2</span> |
| 688 | + {{ t('admin.subscriptions.guide.step2.title') }} |
| 689 | + </h3> |
| 690 | + <ol class="ml-8 list-decimal space-y-1 text-sm text-gray-600 dark:text-gray-300"> |
| 691 | + <li>{{ t('admin.subscriptions.guide.step2.line1') }}</li> |
| 692 | + <li>{{ t('admin.subscriptions.guide.step2.line2') }}</li> |
| 693 | + <li>{{ t('admin.subscriptions.guide.step2.line3') }}</li> |
| 694 | + </ol> |
| 695 | + </div> |
| 696 | + |
| 697 | + <!-- Step 3 --> |
| 698 | + <div class="mb-5"> |
| 699 | + <h3 class="mb-2 flex items-center gap-2 text-sm font-semibold text-gray-900 dark:text-white"> |
| 700 | + <span class="flex h-6 w-6 items-center justify-center rounded-full bg-primary-100 text-xs font-bold text-primary-700 dark:bg-primary-900/40 dark:text-primary-300">3</span> |
| 701 | + {{ t('admin.subscriptions.guide.step3.title') }} |
| 702 | + </h3> |
| 703 | + <div class="ml-8 overflow-hidden rounded-lg border border-gray-200 dark:border-dark-600"> |
| 704 | + <table class="w-full text-sm"> |
| 705 | + <tbody> |
| 706 | + <tr v-for="(row, i) in guideActionRows" :key="i" class="border-b border-gray-100 dark:border-dark-700 last:border-0"> |
| 707 | + <td class="whitespace-nowrap bg-gray-50 px-3 py-2 font-medium text-gray-700 dark:bg-dark-700 dark:text-gray-300">{{ row.action }}</td> |
| 708 | + <td class="px-3 py-2 text-gray-600 dark:text-gray-400">{{ row.desc }}</td> |
| 709 | + </tr> |
| 710 | + </tbody> |
| 711 | + </table> |
| 712 | + </div> |
| 713 | + </div> |
| 714 | + |
| 715 | + <!-- Tip --> |
| 716 | + <div class="rounded-lg bg-blue-50 p-3 text-xs text-blue-700 dark:bg-blue-900/20 dark:text-blue-300"> |
| 717 | + {{ t('admin.subscriptions.guide.tip') }} |
| 718 | + </div> |
| 719 | + |
| 720 | + <div class="mt-4 text-right"> |
| 721 | + <button type="button" class="btn btn-primary btn-sm" @click="showGuideModal = false">{{ t('common.close') }}</button> |
| 722 | + </div> |
| 723 | + </div> |
| 724 | + </div> |
| 725 | + </transition> |
| 726 | + </teleport> |
641 | 727 | </AppLayout> |
642 | 728 | </template> |
643 | 729 |
|
@@ -674,6 +760,15 @@ interface GroupOption { |
674 | 760 | rate: number |
675 | 761 | } |
676 | 762 |
|
| 763 | +// Guide modal state |
| 764 | +const showGuideModal = ref(false) |
| 765 | +
|
| 766 | +const guideActionRows = computed(() => [ |
| 767 | + { action: t('admin.subscriptions.guide.actions.adjust'), desc: t('admin.subscriptions.guide.actions.adjustDesc') }, |
| 768 | + { action: t('admin.subscriptions.guide.actions.resetQuota'), desc: t('admin.subscriptions.guide.actions.resetQuotaDesc') }, |
| 769 | + { action: t('admin.subscriptions.guide.actions.revoke'), desc: t('admin.subscriptions.guide.actions.revokeDesc') } |
| 770 | +]) |
| 771 | +
|
677 | 772 | // User column display mode: 'email' or 'username' |
678 | 773 | const userColumnMode = ref<'email' | 'username'>('email') |
679 | 774 | const USER_COLUMN_MODE_KEY = 'subscription-user-column-mode' |
|
0 commit comments