bep40 commited on
Commit
e2c4a03
·
verified ·
1 Parent(s): 1a5c354

Upload static/app_v2.js with huggingface_hub

Browse files
Files changed (1) hide show
  1. static/app_v2.js +169 -0
static/app_v2.js CHANGED
@@ -769,3 +769,172 @@ async function publishPersonalPostFromModal() {
769
  btn.textContent = origText;
770
  }
771
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
769
  btn.textContent = origText;
770
  }
771
  }
772
+
773
+ // ===== PERSONAL OPINION POST: Viết bài dựa trên quan điểm cá nhân + tin HOT =====
774
+ async function openPersonalPostPreview() {
775
+ const opinion = document.getElementById('opinion-input')?.value.trim();
776
+ if (!opinion || opinion.length < 10) {
777
+ alert('Vui lòng nhập quan điểm cá nhân (ít nhất 10 ký tự)');
778
+ return;
779
+ }
780
+
781
+ const selectedTopics = [];
782
+ if (window._htTopic) {
783
+ selectedTopics.push(window._htTopic);
784
+ }
785
+
786
+ const selectedSources = [];
787
+ document.querySelectorAll('.hashtag-src-item.selected').forEach(el => {
788
+ const idx = parseInt(el.dataset.idx || '0');
789
+ });
790
+
791
+ const btn = event?.target;
792
+ const origText = btn ? btn.textContent : '';
793
+ if (btn) { btn.disabled = true; btn.textContent = '⏳ Đang tạo preview...'; }
794
+
795
+ try {
796
+ const resp = await fetch('/api/personal_post/preview', {
797
+ method: 'POST',
798
+ headers: { 'Content-Type': 'application/json' },
799
+ body: JSON.stringify({
800
+ opinion: opinion,
801
+ selected_topics: selectedTopics,
802
+ selected_sources: selectedSources
803
+ })
804
+ });
805
+ const data = await resp.json();
806
+ if (!resp.ok || data.error) throw new Error(data.error || 'Lỗi tạo preview');
807
+
808
+ showPersonalPostModal(data.preview, opinion, selectedTopics, selectedSources);
809
+ } catch (e) {
810
+ toast('❌ ' + e.message);
811
+ } finally {
812
+ if (btn) { btn.disabled = false; btn.textContent = origText; }
813
+ }
814
+ }
815
+
816
+ function showPersonalPostModal(preview, originalOpinion, selectedTopics, selectedSources) {
817
+ const existing = document.getElementById('personal-post-modal');
818
+ if (existing) existing.remove();
819
+
820
+ const modal = document.createElement('div');
821
+ modal.id = 'personal-post-modal';
822
+ modal.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,.9);z-index:99999;display:flex;align-items:center;justify-content:center;padding:16px;overflow-y:auto';
823
+
824
+ const slidesHtml = (preview.slides || []).map((s, i) => {
825
+ return '<div class="preview-slide" style="background:#1a1a1a;border:1px solid #2a2a2a;border-radius:12px;padding:16px;margin-bottom:12px;max-width:600px;margin-left:auto;margin-right:auto">'
826
+ + '<div style="display:flex;gap:8px;align-items:flex-start">'
827
+ + '<div style="flex:0 0 32px;color:#5cb87a;font-size:12px;font-weight:700;margin-top:4px">Slide ' + (i+1) + '</div>'
828
+ + '<div style="flex:1;min-width:0">'
829
+ + (s.image ? '<img src="' + s.image + '" style="width:100%;max-height:200px;object-fit:cover;border-radius:8px;margin-bottom:8px" onerror="this.style.display='none'">' : '')
830
+ + '<textarea class="preview-slide-text" data-index="' + i + '" style="width:100%;min-height:80px;background:#222;border:1px solid #333;color:#eee;border-radius:8px;padding:8px;font-size:13px;resize:vertical;font-family:inherit">' + (s.text || '').replace(/"/g, '"') + '</textarea>'
831
+ + '</div></div></div>';
832
+ }).join('');
833
+
834
+ const sourcesHtml = (preview.sources || []).map((s, i) => {
835
+ const imgSrc = (preview.images && preview.images[i+1]) ? preview.images[i+1] : '';
836
+ return '<div style="display:flex;gap:8px;padding:8px;background:#202020;border-radius:8px;margin:4px 0;cursor:pointer" onclick="toggleSourceSelection(this, ' + i + ')" data-source-idx="' + i + '" data-url="' + (s.url || '') + '">'
837
+ + '<div style="flex:0 0 60px;aspect-ratio:16/9;background:#333;border-radius:4px;overflow:hidden">'
838
+ + (imgSrc ? '<img src="' + imgSrc + '" style="width:100%;height:100%;object-fit:cover" onerror="this.style.display='none'">' : '')
839
+ + '</div>'
840
+ + '<div style="flex:1;min-width:0;font-size:11px;color:#ddd">' + (s.title || '') + '</div>'
841
+ + '<input type="checkbox" class="source-checkbox" style="margin-top:4px" ' + (i < 3 ? 'checked' : '') + '>'
842
+ + '</div>';
843
+ }).join('');
844
+
845
+ modal.innerHTML = '<div style="background:#1a1a1a;border:2px solid #2d8659;border-radius:16px;padding:20px;max-width:700px;width:100%;max-height:90vh;overflow-y:auto">'
846
+ + '<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:16px">'
847
+ + '<h3 style="color:#5cb87a;margin:0;font-size:16px">📝 Xem trước bài quan điểm cá nhân</h3>'
848
+ + '<button onclick="this.closest('#personal-post-modal').remove()" style="background:none;border:0;color:#fff;font-size:24px;cursor:pointer">✕</button>'
849
+ + '</div>'
850
+ + '<div style="margin-bottom:12px">'
851
+ + '<label style="display:block;color:#888;font-size:11px;margin-bottom:4px">Tiêu đề:</label>'
852
+ + '<input id="preview-title" value="' + (preview.title || '').replace(/"/g, '"') + '" style="width:100%;background:#222;border:1px solid #333;color:#eee;border-radius:8px;padding:8px 12px;font-size:14px;font-weight:700">'
853
+ + '</div>'
854
+ + '<div style="margin-bottom:12px">'
855
+ + '<label style="display:block;color:#888;font-size:11px;margin-bottom:4px">Quan điểm gốc:</label>'
856
+ + '<textarea id="preview-opinion" readonly style="width:100%;min-height:60px;background:#141414;border:1px solid #2a2a2a;color:#aaa;border-radius:8px;padding:8px 12px;font-size:12px;resize:vertical">' + originalOpinion.replace(/"/g, '"') + '</textarea>'
857
+ + '</div>'
858
+ + '<div style="margin-bottom:12px;max-height:300px;overflow-y:auto">'
859
+ + '<label style="display:block;color:#888;font-size:11px;margin-bottom:8px">Các slide (có thể chỉnh sửa):</label>'
860
+ + slidesHtml
861
+ + '</div>'
862
+ + '<div style="margin-bottom:12px">'
863
+ + '<label style="display:block;color:#888;font-size:11px;margin-bottom:8px">Nguồn tin tham khảo (bỏ chọn để loại):</label>'
864
+ + '<div style="max-height:200px;overflow-y:auto">'
865
+ + (sourcesHtml || '<div style="color:#777;font-size:12px;padding:8px">Không có nguồn tin</div>')
866
+ + '</div></div>'
867
+ + '<div style="display:flex;gap:8px">'
868
+ + '<button onclick="publishPersonalPostFromModal()" style="flex:1;background:#2d8659;border:0;color:#fff;padding:12px;border-radius:12px;font-size:13px;font-weight:700;cursor:pointer">✅ Đăng lên Tường AI</button>'
869
+ + '<button onclick="this.closest('#personal-post-modal').remove()" style="background:#333;border:0;color:#ccc;padding:12px 16px;border-radius:12px;font-size:12px;cursor:pointer">Hủy</button>'
870
+ + '</div></div>';
871
+
872
+ document.body.appendChild(modal);
873
+
874
+ window._personalPostPreview = preview;
875
+ window._personalPostOpinion = originalOpinion;
876
+ }
877
+
878
+ function toggleSourceSelection(el, idx) {
879
+ const checkbox = el.querySelector('.source-checkbox');
880
+ checkbox.checked = !checkbox.checked;
881
+ el.style.border = checkbox.checked ? '1px solid #2d8659' : '1px solid transparent';
882
+ el.style.background = checkbox.checked ? '#1a2a1f' : '#202020';
883
+ }
884
+
885
+ async function publishPersonalPostFromModal() {
886
+ const title = document.getElementById('preview-title')?.value.trim();
887
+ if (!title) {
888
+ alert('Vui lòng nhập tiêu đề');
889
+ return;
890
+ }
891
+
892
+ const slides = [];
893
+ document.querySelectorAll('.preview-slide-text').forEach(ta => {
894
+ const text = ta.value.trim();
895
+ if (text) slides.push({ text, image: '', index: slides.length + 1 });
896
+ });
897
+
898
+ const sources = [];
899
+ document.querySelectorAll('[data-source-idx]').forEach((el, i) => {
900
+ const checkbox = el.querySelector('.source-checkbox');
901
+ if (checkbox.checked && window._personalPostPreview?.sources?.[i]) {
902
+ sources.push(window._personalPostPreview.sources[i]);
903
+ }
904
+ });
905
+
906
+ const btn = event.target;
907
+ const origText = btn.textContent;
908
+ btn.disabled = true;
909
+ btn.textContent = '⏳ Đang đăng...';
910
+
911
+ try {
912
+ const resp = await fetch('/api/personal_post', {
913
+ method: 'POST',
914
+ headers: { 'Content-Type': 'application/json' },
915
+ body: JSON.stringify({
916
+ opinion: window._personalPostOpinion,
917
+ selected_topics: [],
918
+ selected_sources: sources,
919
+ custom_title: title,
920
+ custom_slides: slides
921
+ })
922
+ });
923
+ const data = await resp.json();
924
+ if (!resp.ok || data.error) throw new Error(data.error || 'Lỗi đăng bài');
925
+
926
+ toast('✅ Đã đăng bài quan điểm lên Tường AI!');
927
+
928
+ if (data.post && typeof prependWallPost === 'function') {
929
+ prependWallPost(data.post);
930
+ }
931
+
932
+ document.getElementById('personal-post-modal')?.remove();
933
+ document.getElementById('opinion-input').value = '';
934
+ } catch (e) {
935
+ toast('❌ ' + e.message);
936
+ } finally {
937
+ btn.disabled = false;
938
+ btn.textContent = origText;
939
+ }
940
+ }