popup.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /**
  2. * Popup 页面逻辑
  3. * 管理多页面配置
  4. */
  5. // 默认字段映射配置
  6. const DEFAULT_FIELD_MAPPING = {
  7. patientName: ['patientName', 'name', 'patient_name', 'xingming', '姓名', '患者姓名'],
  8. patientAge: ['patientAge', 'age', 'patient_age', 'nianling', '年龄', '患者年龄'],
  9. patientGender: ['patientGender', 'gender', 'patient_gender', 'xingbie', '性别'],
  10. patientPhone: ['patientPhone', 'phone', 'patient_phone', 'dianhua', '电话', '联系电话', '手机'],
  11. chiefComplaint: ['chiefComplaint', 'cc', 'chief_complaint', 'zhushu', '主诉'],
  12. presentIllness: ['presentIllness', 'hpi', 'present_illness', 'xianbingshi', '现病史'],
  13. pastHistory: ['pastHistory', 'ph', 'past_history', 'jiwangshi', '既往史'],
  14. allergyHistory: ['allergyHistory', 'ah', 'allergy_history', 'guominshi', '过敏史'],
  15. visitType: ['visitType', 'vt', 'visit_type', 'jiuzhenleixing', '就诊类型']
  16. };
  17. // DOM 元素
  18. const configList = document.getElementById('configList');
  19. const configModal = document.getElementById('configModal');
  20. const configForm = document.getElementById('configForm');
  21. const addConfigBtn = document.getElementById('addConfigBtn');
  22. const closeModalBtn = document.getElementById('closeModal');
  23. const cancelBtn = document.getElementById('cancelBtn');
  24. // 初始化
  25. document.addEventListener('DOMContentLoaded', async () => {
  26. await loadCurrentUrl();
  27. await loadConfigs();
  28. setupEventListeners();
  29. });
  30. /**
  31. * 加载当前页面 URL
  32. */
  33. async function loadCurrentUrl() {
  34. try {
  35. const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
  36. if (tab && tab.url) {
  37. const url = new URL(tab.url);
  38. document.getElementById('urlText').textContent = url.host + url.pathname;
  39. } else {
  40. document.getElementById('urlText').textContent = '无法获取当前页面 URL';
  41. }
  42. } catch (error) {
  43. console.error('获取当前 URL 失败:', error);
  44. document.getElementById('urlText').textContent = '获取失败';
  45. }
  46. }
  47. /**
  48. * 加载所有配置
  49. */
  50. async function loadConfigs() {
  51. const result = await chrome.storage.local.get('pageConfigs');
  52. const configs = result.pageConfigs || [];
  53. if (configs.length === 0) {
  54. configList.innerHTML = `
  55. <div class="empty-state">
  56. <div style="font-size: 40px; margin-bottom: 10px;">📝</div>
  57. <div>暂无配置</div>
  58. <div style="font-size: 12px; margin-top: 5px;">点击下方按钮添加新配置</div>
  59. </div>
  60. `;
  61. return;
  62. }
  63. configList.innerHTML = configs.map((config, index) => `
  64. <div class="config-item">
  65. <div class="config-item-title">
  66. <div class="config-url">${config.urlPattern}</div>
  67. <div class="config-actions">
  68. <button class="btn-edit" onclick="editConfig(${index})">编辑</button>
  69. <button class="btn-delete" onclick="deleteConfig(${index})">删除</button>
  70. </div>
  71. </div>
  72. <div class="config-details">
  73. <div><strong>模板:</strong>${getTemplateName(config.promptTemplate)}</div>
  74. <div><strong>说明:</strong>${config.description || '无'}</div>
  75. <div style="margin-top: 5px; color: #999;">
  76. 字段映射: ${Object.keys(JSON.parse(config.fieldMapping || '{}')).length} 个字段
  77. </div>
  78. </div>
  79. </div>
  80. `).join('');
  81. }
  82. /**
  83. * 获取模板名称
  84. */
  85. function getTemplateName(templateId) {
  86. const templates = {
  87. 'medical-basic': '基础医疗信息提取',
  88. 'medical-detail': '详细医疗信息提取',
  89. 'medical-emergency': '急诊快速录入'
  90. };
  91. return templates[templateId] || templateId;
  92. }
  93. /**
  94. * 设置事件监听
  95. */
  96. function setupEventListeners() {
  97. // 打开添加配置模态框
  98. addConfigBtn.addEventListener('click', () => {
  99. openModal();
  100. });
  101. // 关闭模态框
  102. closeModalBtn.addEventListener('click', closeModal);
  103. cancelBtn.addEventListener('click', closeModal);
  104. // 点击遮罩层关闭
  105. configModal.addEventListener('click', (e) => {
  106. if (e.target === configModal) {
  107. closeModal();
  108. }
  109. });
  110. // 提交表单
  111. configForm.addEventListener('submit', async (e) => {
  112. e.preventDefault();
  113. await saveConfig();
  114. });
  115. }
  116. /**
  117. * 打开模态框
  118. */
  119. function openModal(config = null) {
  120. const modalTitle = document.getElementById('modalTitle');
  121. const configId = document.getElementById('configId');
  122. const urlPattern = document.getElementById('urlPattern');
  123. const promptTemplate = document.getElementById('promptTemplate');
  124. const fieldMapping = document.getElementById('fieldMapping');
  125. const description = document.getElementById('configDescription');
  126. if (config) {
  127. // 编辑模式
  128. modalTitle.textContent = '编辑页面配置';
  129. configId.value = config.index;
  130. urlPattern.value = config.urlPattern;
  131. promptTemplate.value = config.promptTemplate;
  132. fieldMapping.value = config.fieldMapping || JSON.stringify(DEFAULT_FIELD_MAPPING, null, 2);
  133. description.value = config.description || '';
  134. } else {
  135. // 添加模式
  136. modalTitle.textContent = '添加页面配置';
  137. configId.value = '';
  138. urlPattern.value = '';
  139. promptTemplate.value = 'medical-basic';
  140. fieldMapping.value = JSON.stringify(DEFAULT_FIELD_MAPPING, null, 2);
  141. description.value = '';
  142. }
  143. configModal.style.display = 'block';
  144. }
  145. /**
  146. * 关闭模态框
  147. */
  148. function closeModal() {
  149. configModal.style.display = 'none';
  150. configForm.reset();
  151. }
  152. /**
  153. * 保存配置
  154. */
  155. async function saveConfig() {
  156. const configId = document.getElementById('configId').value;
  157. const urlPattern = document.getElementById('urlPattern').value.trim();
  158. const promptTemplate = document.getElementById('promptTemplate').value;
  159. const fieldMapping = document.getElementById('fieldMapping').value.trim();
  160. const description = document.getElementById('configDescription').value.trim();
  161. // 验证 JSON 格式
  162. try {
  163. if (fieldMapping) {
  164. JSON.parse(fieldMapping);
  165. }
  166. } catch (error) {
  167. alert('字段映射配置格式错误,请输入有效的 JSON 格式');
  168. return;
  169. }
  170. // 获取现有配置
  171. const result = await chrome.storage.local.get('pageConfigs');
  172. let configs = result.pageConfigs || [];
  173. if (configId !== '') {
  174. // 编辑现有配置
  175. configs[parseInt(configId)] = {
  176. urlPattern,
  177. promptTemplate,
  178. fieldMapping,
  179. description,
  180. updatedAt: Date.now()
  181. };
  182. } else {
  183. // 添加新配置
  184. configs.push({
  185. urlPattern,
  186. promptTemplate,
  187. fieldMapping,
  188. description,
  189. createdAt: Date.now(),
  190. updatedAt: Date.now()
  191. });
  192. }
  193. // 保存到存储
  194. await chrome.storage.local.set({ pageConfigs: configs });
  195. // 关闭模态框并刷新列表
  196. closeModal();
  197. await loadConfigs();
  198. alert('配置保存成功!');
  199. }
  200. /**
  201. * 编辑配置(全局函数)
  202. */
  203. window.editConfig = async function(index) {
  204. const result = await chrome.storage.local.get('pageConfigs');
  205. const configs = result.pageConfigs || [];
  206. const config = configs[index];
  207. if (config) {
  208. config.index = index;
  209. openModal(config);
  210. }
  211. };
  212. /**
  213. * 删除配置(全局函数)
  214. */
  215. window.deleteConfig = async function(index) {
  216. if (!confirm('确定要删除这个配置吗?')) {
  217. return;
  218. }
  219. const result = await chrome.storage.local.get('pageConfigs');
  220. let configs = result.pageConfigs || [];
  221. configs.splice(index, 1);
  222. await chrome.storage.local.set({ pageConfigs: configs });
  223. await loadConfigs();
  224. alert('配置已删除');
  225. };
  226. // 暴露到全局
  227. window.openModal = openModal;
  228. window.closeModal = closeModal;