Junhui Ji commited on
Commit
77c3f55
·
1 Parent(s): 9cd66d1

update openai key management

Browse files
Files changed (3) hide show
  1. main.py +5 -3
  2. static/script.js +56 -5
  3. static/styles.css +113 -0
main.py CHANGED
@@ -85,6 +85,7 @@ class OptimizationRequest(BaseModel):
85
  image_data: str
86
  suggestions: List[str]
87
  request_model_id: str = 'gpt-image-1'
 
88
 
89
  class CaseStudyRequest(BaseModel):
90
  user_input: str
@@ -249,7 +250,8 @@ async def optimize_design(request: OptimizationRequest, client_ip: str = None):
249
  response = await call_openai_image_api(
250
  image_data=image_data,
251
  prompt=prompt,
252
- request_model_id=request.request_model_id
 
253
  )
254
 
255
  return JSONResponse(response)
@@ -392,7 +394,7 @@ async def call_openai_api(system_prompt: str, user_content: List[Dict], request_
392
  raise HTTPException(status_code=response.status, detail=f"OpenAI API调用失败, response: {resp}")
393
  return await response.json()
394
 
395
- async def call_openai_image_api(image_data: str, prompt: str, request_model_id='gpt-image-1'):
396
  try:
397
  # 从base64字符串中提取纯base64数据(如果包含前缀)
398
  if image_data and 'base64,' in image_data:
@@ -420,7 +422,7 @@ async def call_openai_image_api(image_data: str, prompt: str, request_model_id='
420
  image_file.name = "original-design.png" # 设置文件名,与JS代码一致
421
 
422
  # 创建OpenAI客户端
423
- client = OpenAI(api_key=OPENAI_API_IMAGE_EDIT_KEY)
424
 
425
  # 调用图像编辑API
426
  response = client.images.edit(
 
85
  image_data: str
86
  suggestions: List[str]
87
  request_model_id: str = 'gpt-image-1'
88
+ openai_key: str = ''
89
 
90
  class CaseStudyRequest(BaseModel):
91
  user_input: str
 
250
  response = await call_openai_image_api(
251
  image_data=image_data,
252
  prompt=prompt,
253
+ request_model_id=request.request_model_id,
254
+ openai_key=request.openai_key
255
  )
256
 
257
  return JSONResponse(response)
 
394
  raise HTTPException(status_code=response.status, detail=f"OpenAI API调用失败, response: {resp}")
395
  return await response.json()
396
 
397
+ async def call_openai_image_api(image_data: str, prompt: str, request_model_id='gpt-image-1', openai_key=''):
398
  try:
399
  # 从base64字符串中提取纯base64数据(如果包含前缀)
400
  if image_data and 'base64,' in image_data:
 
422
  image_file.name = "original-design.png" # 设置文件名,与JS代码一致
423
 
424
  # 创建OpenAI客户端
425
+ client = OpenAI(api_key=openai_key if openai_key else OPENAI_API_IMAGE_EDIT_KEY)
426
 
427
  # 调用图像编辑API
428
  response = client.images.edit(
static/script.js CHANGED
@@ -703,7 +703,8 @@ document.addEventListener('DOMContentLoaded', function() {
703
  text: uploadedText,
704
  image_data: uploadedImage,
705
  suggestions: suggestions,
706
- request_model_id: 'gpt-image-1'
 
707
  })
708
  });
709
 
@@ -774,12 +775,14 @@ document.addEventListener('DOMContentLoaded', function() {
774
  text: uploadedText,
775
  image_data: uploadedImage,
776
  suggestions: suggestions,
777
- request_model_id: 'dall-e-2'
 
778
  })
779
  });
780
-
781
- if (!response.ok) {
782
- throw new Error('优化请求失败');
 
783
  }
784
 
785
  const data = await response.json();
@@ -942,4 +945,52 @@ document.addEventListener('DOMContentLoaded', function() {
942
  return imageUrl; // 如果失败,返回原始URL
943
  }
944
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
945
  });
 
703
  text: uploadedText,
704
  image_data: uploadedImage,
705
  suggestions: suggestions,
706
+ request_model_id: 'gpt-image-1',
707
+ openai_key: sessionStorage.getItem('userOpenaiKey') || ''
708
  })
709
  });
710
 
 
775
  text: uploadedText,
776
  image_data: uploadedImage,
777
  suggestions: suggestions,
778
+ request_model_id: 'dall-e-2',
779
+ openai_key: sessionStorage.getItem('userOpenaiKey') || ''
780
  })
781
  });
782
+ if (response.status === 503) {
783
+ const errData = await response.json();
784
+ alert(errData.detail)
785
+ throw new Error('用户无生图权限')
786
  }
787
 
788
  const data = await response.json();
 
945
  return imageUrl; // 如果失败,返回原始URL
946
  }
947
  }
948
+
949
+ // API Key Dialog functionality
950
+ const apiKeyLink = document.getElementById('apiKeyLink');
951
+ const apiKeyDialog = document.getElementById('apiKeyDialog');
952
+ const apiKeyInput = document.getElementById('apiKeyInput');
953
+ const saveApiKey = document.getElementById('saveApiKey');
954
+ const cancelApiKey = document.getElementById('cancelApiKey');
955
+
956
+ if (apiKeyLink && apiKeyDialog) {
957
+ // Show dialog when clicking the link
958
+ apiKeyLink.addEventListener('click', function(e) {
959
+ e.preventDefault();
960
+ apiKeyDialog.style.display = 'flex';
961
+ // Load existing key if available
962
+ const existingKey = sessionStorage.getItem('userOpenaiKey');
963
+ if (existingKey) {
964
+ apiKeyInput.value = existingKey;
965
+ }
966
+ });
967
+
968
+ // Save API Key
969
+ saveApiKey.addEventListener('click', function() {
970
+ const key = apiKeyInput.value.trim();
971
+ if (key) {
972
+ sessionStorage.setItem('userOpenaiKey', key);
973
+ apiKeyDialog.style.display = 'none';
974
+ // Show success message
975
+ const toast = document.getElementById('toast');
976
+ toast.textContent = 'API Key已保存';
977
+ toast.style.display = 'block';
978
+ setTimeout(() => {
979
+ toast.style.display = 'none';
980
+ }, 2000);
981
+ }
982
+ });
983
+
984
+ // Cancel button
985
+ cancelApiKey.addEventListener('click', function() {
986
+ apiKeyDialog.style.display = 'none';
987
+ });
988
+
989
+ // Close dialog when clicking outside
990
+ apiKeyDialog.addEventListener('click', function(e) {
991
+ if (e.target === apiKeyDialog) {
992
+ apiKeyDialog.style.display = 'none';
993
+ }
994
+ });
995
+ }
996
  });
static/styles.css CHANGED
@@ -924,4 +924,117 @@ footer {
924
 
925
  @keyframes spin {
926
  to { transform: rotate(360deg); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
927
  }
 
924
 
925
  @keyframes spin {
926
  to { transform: rotate(360deg); }
927
+ }
928
+
929
+ /* API Key Link */
930
+ .api-key-link {
931
+ text-align: center;
932
+ margin-bottom: 20px;
933
+ }
934
+
935
+ .api-key-link a {
936
+ color: #9747FF;
937
+ font-size: 14px;
938
+ text-decoration: underline;
939
+ cursor: pointer;
940
+ }
941
+
942
+ .api-key-link a:hover {
943
+ color: #b26bff;
944
+ }
945
+
946
+ /* API Key Dialog */
947
+ .api-key-dialog {
948
+ display: none;
949
+ position: fixed;
950
+ top: 0;
951
+ left: 0;
952
+ width: 100%;
953
+ height: 100%;
954
+ background: rgba(0, 0, 0, 0.7);
955
+ z-index: 1000;
956
+ justify-content: center;
957
+ align-items: center;
958
+ }
959
+
960
+ .dialog-content {
961
+ background: #1a1a1a;
962
+ padding: 30px;
963
+ border-radius: 20px;
964
+ width: 90%;
965
+ max-width: 400px;
966
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
967
+ border: 1px solid rgba(255, 255, 255, 0.1);
968
+ }
969
+
970
+ .dialog-content h3 {
971
+ margin: 0 0 15px 0;
972
+ color: #fff;
973
+ font-size: 20px;
974
+ }
975
+
976
+ .dialog-description {
977
+ color: #ccc;
978
+ margin-bottom: 15px;
979
+ font-size: 14px;
980
+ line-height: 1.5;
981
+ }
982
+
983
+ .dialog-help {
984
+ margin-bottom: 20px;
985
+ }
986
+
987
+ .dialog-help a {
988
+ color: #9747FF;
989
+ font-size: 14px;
990
+ text-decoration: none;
991
+ }
992
+
993
+ .dialog-help a:hover {
994
+ text-decoration: underline;
995
+ }
996
+
997
+ #apiKeyInput {
998
+ width: 100%;
999
+ padding: 12px;
1000
+ border: 1px solid rgba(255, 255, 255, 0.2);
1001
+ border-radius: 8px;
1002
+ background: rgba(255, 255, 255, 0.05);
1003
+ color: #fff;
1004
+ font-size: 14px;
1005
+ margin-bottom: 20px;
1006
+ }
1007
+
1008
+ .dialog-buttons {
1009
+ display: flex;
1010
+ gap: 10px;
1011
+ justify-content: flex-end;
1012
+ }
1013
+
1014
+ .dialog-buttons button {
1015
+ padding: 8px 20px;
1016
+ border: none;
1017
+ border-radius: 8px;
1018
+ cursor: pointer;
1019
+ font-size: 14px;
1020
+ transition: all 0.3s ease;
1021
+ }
1022
+
1023
+ #saveApiKey {
1024
+ background: linear-gradient(to right, #5E33F1, #BA9EF7);
1025
+ color: white;
1026
+ }
1027
+
1028
+ #saveApiKey:hover {
1029
+ transform: translateY(-2px);
1030
+ box-shadow: 0 5px 15px rgba(94, 51, 241, 0.3);
1031
+ }
1032
+
1033
+ #cancelApiKey {
1034
+ background: rgba(255, 255, 255, 0.1);
1035
+ color: #ccc;
1036
+ }
1037
+
1038
+ #cancelApiKey:hover {
1039
+ background: rgba(255, 255, 255, 0.2);
1040
  }