Last modified by Super Admin on 2026/04/05 18:59

From version Icon 110.1 Icon
edited by Super Admin
on 2026/03/24 19:13
Change comment: There is no comment for this version
To version Icon 107.1 Icon
edited by Super Admin
on 2026/03/24 15:28
Change comment: There is no comment for this version

Summary

Details

Icon Page properties
Content
... ... @@ -7,19 +7,6 @@
7 7   #stop
8 8  #end
9 9  {{html clean="false"}}
10 -## --- OGP メタタグ(SNSシェア対応) ---
11 -#set($ogTitle = "$!{schoolName} — 生徒会Wiki")
12 -#set($ogDesc = "$!{schoolName}の生徒会活動情報。全国の高校の生徒会活動事例を集積・共有するプラットフォーム。")
13 -#set($ogUrl = "https://${request.serverName}${doc.getURL('view')}")
14 -<meta property="og:type" content="article" />
15 -<meta property="og:title" content="$escapetool.xml($ogTitle)" />
16 -<meta property="og:description" content="$escapetool.xml($ogDesc)" />
17 -<meta property="og:url" content="$escapetool.xml($ogUrl)" />
18 -<meta property="og:site_name" content="生徒会Wiki" />
19 -<meta property="og:locale" content="ja_JP" />
20 -<meta name="twitter:card" content="summary" />
21 -<meta name="twitter:title" content="$escapetool.xml($ogTitle)" />
22 -<meta name="twitter:description" content="$escapetool.xml($ogDesc)" />
23 23  ## メンテナンスバナー({{include}}ではなくインラインで記述し、<p>タグ挿入を回避)
24 24  #set($bannerDoc = $xwiki.getDocument('SeitokaiAdmin.MaintenanceBanner'))
25 25  #set($bannerObj = $bannerDoc.getObject('SeitokaiCode.MaintenanceBannerClass'))
... ... @@ -409,102 +409,23 @@
409 409  </div>
410 410  #end
411 411  
412 -## --- 入力進捗ガイド(自校ユーザー向け) ---
399 +## --- 入力ガイド(自校ユーザー向け) ---
413 413  #if(!$isGuest && $canEdit)
414 - #set($stepItems = [])
415 - #set($completedCount = 0)
416 - #set($totalSteps = 8)
417 - ## 1. 基本情報(生徒数)
418 - #if($studentCount && $studentCount != '' && $studentCount != '0')
419 - #set($discard = $stepItems.add({'name': '基本情報(生徒数・学級数)', 'done': true}))
420 - #set($completedCount = $completedCount + 1)
421 - #else
422 - #set($discard = $stepItems.add({'name': '基本情報(生徒数・学級数)', 'done': false}))
423 - #end
424 - ## 2. 生徒会組織
425 - #if($orgChart && $orgChart != '')
426 - #set($discard = $stepItems.add({'name': '生徒会組織', 'done': true}))
427 - #set($completedCount = $completedCount + 1)
428 - #else
429 - #set($discard = $stepItems.add({'name': '生徒会組織', 'done': false}))
430 - #end
431 - ## 3. 日常の活動
432 - #if($dailyActivities && $dailyActivities != '')
433 - #set($discard = $stepItems.add({'name': '日常の活動', 'done': true}))
434 - #set($completedCount = $completedCount + 1)
435 - #else
436 - #set($discard = $stepItems.add({'name': '日常の活動', 'done': false}))
437 - #end
438 - ## 4. 選挙
439 - #if($electionExists && $electionExists != '')
440 - #set($discard = $stepItems.add({'name': '選挙', 'done': true}))
441 - #set($completedCount = $completedCount + 1)
442 - #else
443 - #set($discard = $stepItems.add({'name': '選挙', 'done': false}))
444 - #end
445 - ## 5. 予算
446 - #set($budgetFilled = false)
447 - #if(($budgetScale && $budgetScale != '') || ($studentFee && $studentFee != '')) #set($budgetFilled = true) #end
448 - #if($budgetFilled)
449 - #set($discard = $stepItems.add({'name': '予算', 'done': true}))
450 - #set($completedCount = $completedCount + 1)
451 - #else
452 - #set($discard = $stepItems.add({'name': '予算', 'done': false}))
453 - #end
454 - ## 6. 校則の見直し
455 - #if($ruleReviewStatus && $ruleReviewStatus != '')
456 - #set($discard = $stepItems.add({'name': '校則・生徒会会則の見直し', 'done': true}))
457 - #set($completedCount = $completedCount + 1)
458 - #else
459 - #set($discard = $stepItems.add({'name': '校則・生徒会会則の見直し', 'done': false}))
460 - #end
461 - ## 7. 生徒総会
462 - #if($assemblyFormat && $assemblyFormat != '')
463 - #set($discard = $stepItems.add({'name': '生徒総会', 'done': true}))
464 - #set($completedCount = $completedCount + 1)
465 - #else
466 - #set($discard = $stepItems.add({'name': '生徒総会', 'done': false}))
467 - #end
468 - ## 8. 活動報告
401 + #set($missingItems = [])
402 + #if(!$studentCount || $studentCount == '' || $studentCount == '0') #set($discard = $missingItems.add('生徒数')) #end
403 + #if(!$orgChart || $orgChart == '') #set($discard = $missingItems.add('生徒会組織')) #end
404 + #if(!$dailyActivities || $dailyActivities == '') #set($discard = $missingItems.add('日常の活動')) #end
405 + #if(!$ruleReviewStatus || $ruleReviewStatus == '') #set($discard = $missingItems.add('校則・生徒会会則の見直し')) #end
469 469   #set($activityCount = $doc.getObjects('SeitokaiCode.ActivityClass').size())
470 - #if($activityCount > 0)
471 - #set($discard = $stepItems.add({'name': '活動報告', 'done': true}))
472 - #set($completedCount = $completedCount + 1)
473 - #else
474 - #set($discard = $stepItems.add({'name': '活動報告(まだ投稿がありません)', 'done': false}))
475 - #end
476 - ## 全完了なら非表示
477 - #if($completedCount < $totalSteps)
478 - #set($progressPct = $mathtool.mul($mathtool.div($completedCount, $totalSteps), 100))
479 - #set($progressPctInt = $mathtool.toInteger($progressPct))
480 - #set($firstMissing = false)
481 -<div class="progress-guide" style="margin-bottom:var(--sp-4);">
482 - <div class="progress-guide-header">
483 - <span class="progress-guide-title"><svg class="ico" viewBox="0 0 24 24" style="width:1.1em;height:1.1em;vertical-align:-2px;"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg> 学校情報の入力状況</span>
484 - <span class="progress-guide-count">${completedCount} / ${totalSteps} 完了</span>
485 - </div>
486 - <div class="progress-bar-track">
487 - <div class="progress-bar-fill" style="width:${progressPctInt}%"></div>
488 - </div>
489 - <ul class="progress-step-list">
490 - #foreach($step in $stepItems)
491 - #if($step.done)
492 - <li class="progress-step done"><svg class="ico" viewBox="0 0 24 24" style="width:0.9em;height:0.9em;"><path d="M20 6L9 17l-5-5"/></svg> $step.name</li>
493 - #else
494 - #if(!$firstMissing)
495 - <li class="progress-step next"><svg class="ico" viewBox="0 0 24 24" style="width:0.9em;height:0.9em;"><circle cx="12" cy="12" r="10"/></svg> $step.name <span class="progress-next-label">← 次はここ!</span></li>
496 - #set($firstMissing = true)
497 - #else
498 - <li class="progress-step pending"><svg class="ico" viewBox="0 0 24 24" style="width:0.9em;height:0.9em;"><rect x="3" y="3" width="18" height="18" rx="2"/></svg> $step.name</li>
499 - #end
500 - #end
407 + #if($activityCount == 0) #set($discard = $missingItems.add('活動報告(まだ投稿がありません)')) #end
408 + #if($missingItems.size() > 0)
409 +<div class="form-message-info" style="margin-bottom:var(--sp-4);">
410 + <strong>入力のお願い</strong> — 以下の項目がまだ入力されていません。<a href="$doc.getURL('view', 'sheet=SeitokaiCode.SchoolEditForm')">編集画面</a>から入力すると、他校の生徒会の参考になります。
411 + <ul style="margin:var(--sp-2) 0 0; padding-left:var(--sp-5);">
412 + #foreach($item in $missingItems)
413 + <li>$item</li>
501 501   #end
502 502   </ul>
503 - <div style="margin-top:var(--sp-3);">
504 - <a href="$doc.getURL('view', 'sheet=SeitokaiCode.SchoolEditForm')" class="btn-primary-sm">
505 - <svg class="ico" viewBox="0 0 24 24" style="width:0.9em;height:0.9em;"><path d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z"/></svg> 編集画面を開く
506 - </a>
507 - </div>
508 508  </div>
509 509   #end
510 510  #end
... ... @@ -1429,25 +1429,6 @@
1429 1429   #if($postVis != 'public')
1430 1430   <div class="visibility-badge visibility-${postVis} post-action-mt">#if($postVis == 'school_trusted')<svg class="ico" viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg> 校内承認・紹介限定#else<svg class="ico" viewBox="0 0 24 24"><path d="M2 20h20"/><path d="M5 20V10l7-5 7 5v10"/><path d="M9 20v-5h6v5"/></svg> 校内限定#end</div>
1431 1431   #end
1432 - ## いいねボタン
1433 - #set($postLikeCount = $!post.getValue('likeCount'))
1434 - #if(!$postLikeCount || $postLikeCount == '') #set($postLikeCount = 0) #end
1435 - #set($postLikedBy = $!post.getValue('likedBy'))
1436 - #set($isLikedByMe = false)
1437 - #if($postLikedBy && $postLikedBy.contains($xcontext.user)) #set($isLikedByMe = true) #end
1438 - <div class="post-like-row post-action-mt">
1439 - #if($xcontext.user != 'XWiki.XWikiGuest')
1440 - <button type="button" class="btn-like #if($isLikedByMe)liked#end" data-page="$escapetool.xml($doc.fullName)" data-obj="$post.number" data-csrf="$services.csrf.getToken()" onclick="toggleLike(this)">
1441 - <svg class="ico ico-fixed-14" viewBox="0 0 24 24" #if($isLikedByMe)fill="currentColor" stroke="none"#end><path d="M20.84 4.61a5.5 5.5 0 00-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 00-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 000-7.78z"/></svg>
1442 - <span class="like-count">$postLikeCount</span>
1443 - </button>
1444 - #else
1445 - <span class="btn-like disabled">
1446 - <svg class="ico ico-fixed-14" viewBox="0 0 24 24"><path d="M20.84 4.61a5.5 5.5 0 00-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 00-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 000-7.78z"/></svg>
1447 - <span class="like-count">$postLikeCount</span>
1448 - </span>
1449 - #end
1450 - </div>
1451 1451   ## 固定/編集/削除/通報/非表示ボタン(横並び)
1452 1452   #set($postAuthorRef = $!post.getValue('authorRef'))
1453 1453   #set($postObjNumED = $post.number)
... ... @@ -1568,68 +1568,10 @@
1568 1568  {{/html}}
1569 1569  #end
1570 1570  
1571 -## --- OGP / SNSシェア対応 ---
1572 -#set($ogpTitle = "${schoolName} — 生徒会Wiki")
1573 -#set($ogpDesc = "${schoolName}の生徒会活動情報。")
1574 -#if($prefecture && $prefecture != '') #set($ogpDesc = "${ogpDesc}${prefecture}") #end
1575 -#if($city && $city != '') #set($ogpDesc = "${ogpDesc}${city}。") #end
1576 -#if($dailyActivities && $dailyActivities != '') #set($ogpDesc = "${ogpDesc} 主な活動: ${dailyActivities}") #end
1577 -#set($ogpUrl = "https://${request.serverName}${doc.getURL()}")
1578 -
1579 1579  ## --- 年度タブ切り替え JavaScript ---
1580 1580  {{html clean="false"}}
1581 1581  <script>
1582 -// OGPメタタグ挿入
1583 -(function() {
1584 - var ogp = {
1585 - 'og:title': '$escapetool.javascript($ogpTitle)',
1586 - 'og:description': '$escapetool.javascript($ogpDesc)',
1587 - 'og:type': 'article',
1588 - 'og:url': '$escapetool.javascript($ogpUrl)',
1589 - 'og:site_name': '生徒会Wiki',
1590 - 'twitter:card': 'summary'
1591 - };
1592 - for (var p in ogp) {
1593 - var meta = document.createElement('meta');
1594 - meta.setAttribute('property', p);
1595 - meta.setAttribute('content', ogp[p]);
1596 - document.head.appendChild(meta);
1597 - }
1598 - // twitter用
1599 - var tw = document.createElement('meta');
1600 - tw.setAttribute('name', 'twitter:card');
1601 - tw.setAttribute('content', 'summary');
1602 - document.head.appendChild(tw);
1603 -})();
1604 1604  // コンパクト表示(タイトルのみ)トグル
1605 -// いいねトグル
1606 -function toggleLike(btn) {
1607 - var page = btn.getAttribute('data-page');
1608 - var obj = btn.getAttribute('data-obj');
1609 - var csrf = btn.getAttribute('data-csrf');
1610 - btn.disabled = true;
1611 - var fd = new FormData();
1612 - fd.append('page', page);
1613 - fd.append('obj', obj);
1614 - fd.append('form_token', csrf);
1615 - fetch('/bin/SeitokaiCode/LikePost', { method: 'POST', body: fd })
1616 - .then(function(r) { return r.json(); })
1617 - .then(function(data) {
1618 - btn.querySelector('.like-count').textContent = data.count;
1619 - if (data.action === 'liked') {
1620 - btn.classList.add('liked');
1621 - btn.querySelector('svg').setAttribute('fill', 'currentColor');
1622 - btn.querySelector('svg').setAttribute('stroke', 'none');
1623 - } else {
1624 - btn.classList.remove('liked');
1625 - btn.querySelector('svg').removeAttribute('fill');
1626 - btn.querySelector('svg').setAttribute('stroke', 'currentColor');
1627 - }
1628 - })
1629 - .catch(function() { alert('エラーが発生しました'); })
1630 - .finally(function() { btn.disabled = false; });
1631 -}
1632 -
1633 1633  function toggleCompactView() {
1634 1634   var container = document.querySelector('.xwiki-content') || document.body;
1635 1635   var isCompact = container.classList.toggle('activity-compact-view');