mirror of
				https://github.com/yangjian102621/geekai.git
				synced 2025-11-04 08:13:43 +08:00 
			
		
		
		
	Merge branch 'main' of 172.28.1.6:yangjian/chatgpt-plus into ui
This commit is contained in:
		@@ -124,10 +124,9 @@ func (h *ChatHandler) Clear(c *gin.Context) {
 | 
			
		||||
// History 获取聊天历史记录
 | 
			
		||||
func (h *ChatHandler) History(c *gin.Context) {
 | 
			
		||||
	chatId := c.Query("chat_id") // 会话 ID
 | 
			
		||||
	userId := h.GetLoginUserId(c)
 | 
			
		||||
	var items []model.ChatMessage
 | 
			
		||||
	var messages = make([]vo.HistoryMessage, 0)
 | 
			
		||||
	res := h.db.Where("user_id = ? AND chat_id = ?", userId, chatId).Find(&items)
 | 
			
		||||
	res := h.db.Debug().Where("chat_id = ?", chatId).Find(&items)
 | 
			
		||||
	if res.Error != nil {
 | 
			
		||||
		resp.ERROR(c, "No history message")
 | 
			
		||||
		return
 | 
			
		||||
 
 | 
			
		||||
@@ -276,6 +276,7 @@ func (h *ChatHandler) sendOpenAiMessage(
 | 
			
		||||
		var res types.ApiError
 | 
			
		||||
		err = json.Unmarshal(body, &res)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			logger.Debug(string(body))
 | 
			
		||||
			return fmt.Errorf("error with decode response: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -51,6 +51,10 @@
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  right: 20px;
 | 
			
		||||
}
 | 
			
		||||
.mobile-mj .content .text-line .align-right {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: right;
 | 
			
		||||
}
 | 
			
		||||
.mobile-mj .content .running-job-list .van-grid .van-grid-item .van-grid-item__content {
 | 
			
		||||
  padding: 0;
 | 
			
		||||
  position: relative;
 | 
			
		||||
 
 | 
			
		||||
@@ -67,6 +67,11 @@
 | 
			
		||||
          right 20px
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .align-right {
 | 
			
		||||
        display flex
 | 
			
		||||
        justify-content right
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .running-job-list {
 | 
			
		||||
 
 | 
			
		||||
@@ -18,9 +18,6 @@
 | 
			
		||||
.task-list-box .task-list-inner .title-tabs .el-tabs__active-bar {
 | 
			
		||||
  background-color: #47fff1;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .task-list-inner .title-tabs .el-tabs__content {
 | 
			
		||||
  padding: 10px 0;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .task-list-inner .el-textarea {
 | 
			
		||||
  --el-input-focus-border-color: #47fff1;
 | 
			
		||||
}
 | 
			
		||||
@@ -51,26 +48,49 @@
 | 
			
		||||
.task-list-box .task-list-inner .el-form-item__label {
 | 
			
		||||
  color: #fff;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .task-list-inner .img-uploader .el-upload {
 | 
			
		||||
.task-list-box .task-list-inner .img-inline {
 | 
			
		||||
  display: flex;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .task-list-inner .img-inline .img-uploader .el-upload {
 | 
			
		||||
  border: 1px dashed var(--el-border-color);
 | 
			
		||||
  border-radius: 6px;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  width: 300px;
 | 
			
		||||
  width: 120px;
 | 
			
		||||
  transition: var(--el-transition-duration-fast);
 | 
			
		||||
  margin-bottom: 20px;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .task-list-inner .img-uploader .el-upload:hover {
 | 
			
		||||
.task-list-box .task-list-inner .img-inline .img-uploader .el-upload:hover {
 | 
			
		||||
  border-color: var(--el-color-primary);
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .task-list-inner .img-uploader .el-upload .el-icon.uploader-icon {
 | 
			
		||||
.task-list-box .task-list-inner .img-inline .img-uploader .el-upload .el-icon.uploader-icon {
 | 
			
		||||
  font-size: 28px;
 | 
			
		||||
  color: #8c939d;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 120px;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .task-list-inner .img-inline .img-list-box {
 | 
			
		||||
  display: flex;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .task-list-inner .img-inline .img-list-box .img-item {
 | 
			
		||||
  width: 120px;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  margin-right: 10px;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .task-list-inner .img-inline .img-list-box .img-item .el-image {
 | 
			
		||||
  width: 120px;
 | 
			
		||||
  height: 120px;
 | 
			
		||||
  border-radius: 5px;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .task-list-inner .img-inline .img-list-box .img-item .el-button {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  right: 5px;
 | 
			
		||||
  top: 5px;
 | 
			
		||||
  width: 20px;
 | 
			
		||||
  height: 20px;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .task-list-inner .submit-btn {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  margin: 20px 0;
 | 
			
		||||
@@ -84,17 +104,17 @@
 | 
			
		||||
  justify-content: right;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .running-job-list .job-item {
 | 
			
		||||
.task-list-box .task-list-inner .job-list-box .running-job-list .job-item {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  padding: 2px;
 | 
			
		||||
  background-color: #555;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .running-job-list .job-item .job-item-inner {
 | 
			
		||||
.task-list-box .task-list-inner .job-list-box .running-job-list .job-item .job-item-inner {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .running-job-list .job-item .job-item-inner .progress {
 | 
			
		||||
.task-list-box .task-list-inner .job-list-box .running-job-list .job-item .job-item-inner .progress {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
@@ -104,11 +124,11 @@
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .running-job-list .job-item .job-item-inner .progress span {
 | 
			
		||||
.task-list-box .task-list-inner .job-list-box .running-job-list .job-item .job-item-inner .progress span {
 | 
			
		||||
  font-size: 20px;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .finish-job-list .job-item {
 | 
			
		||||
.task-list-box .task-list-inner .job-list-box .finish-job-list .job-item {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  border: 1px solid #666;
 | 
			
		||||
@@ -116,18 +136,19 @@
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  border-radius: 6px;
 | 
			
		||||
  transition: all 0.3s ease; /* 添加过渡效果 */
 | 
			
		||||
  position: relative;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .finish-job-list .job-item .opt .opt-line {
 | 
			
		||||
.task-list-box .task-list-inner .job-list-box .finish-job-list .job-item .opt .opt-line {
 | 
			
		||||
  margin: 6px 0;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .finish-job-list .job-item .opt .opt-line ul {
 | 
			
		||||
.task-list-box .task-list-inner .job-list-box .finish-job-list .job-item .opt .opt-line ul {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-flow: row;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .finish-job-list .job-item .opt .opt-line ul li {
 | 
			
		||||
.task-list-box .task-list-inner .job-list-box .finish-job-list .job-item .opt .opt-line ul li {
 | 
			
		||||
  margin-right: 6px;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .finish-job-list .job-item .opt .opt-line ul li a {
 | 
			
		||||
.task-list-box .task-list-inner .job-list-box .finish-job-list .job-item .opt .opt-line ul li a {
 | 
			
		||||
  padding: 3px 0;
 | 
			
		||||
  width: 40px;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
@@ -137,50 +158,58 @@
 | 
			
		||||
  background-color: #4e5058;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .finish-job-list .job-item .opt .opt-line ul li a:hover {
 | 
			
		||||
.task-list-box .task-list-inner .job-list-box .finish-job-list .job-item .opt .opt-line ul li a:hover {
 | 
			
		||||
  background-color: #6d6f78;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .finish-job-list .job-item .opt .opt-line ul .show-prompt {
 | 
			
		||||
.task-list-box .task-list-inner .job-list-box .finish-job-list .job-item .opt .opt-line ul .show-prompt {
 | 
			
		||||
  font-size: 20px;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .finish-job-list .animate:hover {
 | 
			
		||||
.task-list-box .task-list-inner .job-list-box .finish-job-list .job-item .remove {
 | 
			
		||||
  display: none;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  right: 10px;
 | 
			
		||||
  top: 10px;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .task-list-inner .job-list-box .finish-job-list .job-item:hover .remove {
 | 
			
		||||
  display: block;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .task-list-inner .job-list-box .finish-job-list .animate:hover {
 | 
			
		||||
  box-shadow: 0 0 10px rgba(71,255,241,0.6); /* 添加阴影效果 */
 | 
			
		||||
  transform: translateY(-10px); /* 向上移动10像素 */
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .el-image {
 | 
			
		||||
.task-list-box .task-list-inner .job-list-box .el-image {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  overflow: visible;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .el-image img {
 | 
			
		||||
.task-list-box .task-list-inner .job-list-box .el-image img {
 | 
			
		||||
  height: 240px;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .el-image .el-image-viewer__wrapper img {
 | 
			
		||||
.task-list-box .task-list-inner .job-list-box .el-image .el-image-viewer__wrapper img {
 | 
			
		||||
  width: auto;
 | 
			
		||||
  height: auto;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .el-image .image-slot {
 | 
			
		||||
.task-list-box .task-list-inner .job-list-box .el-image .image-slot {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-flow: column;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  min-height: 200px;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  height: 240px;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .el-image .image-slot .iconfont {
 | 
			
		||||
.task-list-box .task-list-inner .job-list-box .el-image .image-slot .iconfont {
 | 
			
		||||
  font-size: 50px;
 | 
			
		||||
  margin-bottom: 10px;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .el-image.upscale {
 | 
			
		||||
.task-list-box .task-list-inner .job-list-box .el-image.upscale {
 | 
			
		||||
  max-height: 310px;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .el-image.upscale img {
 | 
			
		||||
.task-list-box .task-list-inner .job-list-box .el-image.upscale img {
 | 
			
		||||
  height: 310px;
 | 
			
		||||
}
 | 
			
		||||
.task-list-box .el-image.upscale .el-image-viewer__wrapper img {
 | 
			
		||||
.task-list-box .task-list-inner .job-list-box .el-image.upscale .el-image-viewer__wrapper img {
 | 
			
		||||
  width: auto;
 | 
			
		||||
  height: auto;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -87,8 +87,8 @@ const handleKeyup = (e) => {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const login = function () {
 | 
			
		||||
  if (!validateMobile(username.value) && !validateEmail(username.value)) {
 | 
			
		||||
    return ElMessage.error("请输入合法的手机号/邮箱地址")
 | 
			
		||||
  if (username.value.trim() === '') {
 | 
			
		||||
    return ElMessage.error("请输入用户民")
 | 
			
		||||
  }
 | 
			
		||||
  if (password.value.trim() === '') {
 | 
			
		||||
    return ElMessage.error('请输入密码');
 | 
			
		||||
 
 | 
			
		||||
@@ -62,14 +62,18 @@
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div class="text-line">
 | 
			
		||||
          <van-field
 | 
			
		||||
              v-model="params.prompt"
 | 
			
		||||
          <van-field v-model="params.prompt"
 | 
			
		||||
                     rows="3"
 | 
			
		||||
              autosize
 | 
			
		||||
                     label="提示词"
 | 
			
		||||
                     autosize
 | 
			
		||||
                     type="textarea"
 | 
			
		||||
              placeholder="如:一个美丽的中国女孩站在电影院门口,手上拿着爆米花,微笑,写实风格,电影灯光效果,半身像"
 | 
			
		||||
          />
 | 
			
		||||
                     placeholder="如:一个美丽的中国女孩站在电影院门口,手上拿着爆米花,微笑,写实风格,电影灯光效果,半身像">
 | 
			
		||||
            <template #button>
 | 
			
		||||
              <van-button v-if="translating" disabled loading type="primary"/>
 | 
			
		||||
              <van-button v-else size="small" type="primary" @click="translatePrompt">翻译</van-button>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
          </van-field>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <van-collapse v-model="activeColspan">
 | 
			
		||||
@@ -192,7 +196,15 @@
 | 
			
		||||
 | 
			
		||||
<script setup>
 | 
			
		||||
import {onMounted, ref} from "vue";
 | 
			
		||||
import {showConfirmDialog, showFailToast, showNotify, showToast, showDialog, showImagePreview} from "vant";
 | 
			
		||||
import {
 | 
			
		||||
  showConfirmDialog,
 | 
			
		||||
  showFailToast,
 | 
			
		||||
  showNotify,
 | 
			
		||||
  showToast,
 | 
			
		||||
  showDialog,
 | 
			
		||||
  showImagePreview,
 | 
			
		||||
  showSuccessToast
 | 
			
		||||
} from "vant";
 | 
			
		||||
import {httpGet, httpPost} from "@/utils/http";
 | 
			
		||||
import Compressor from "compressorjs";
 | 
			
		||||
import {ElMessage} from "element-plus";
 | 
			
		||||
@@ -449,10 +461,10 @@ const publishImage = (item, action) => {
 | 
			
		||||
    text = "取消发布"
 | 
			
		||||
  }
 | 
			
		||||
  httpPost("/api/mj/publish", {id: item.id, action: action}).then(() => {
 | 
			
		||||
    ElMessage.success(text + "成功")
 | 
			
		||||
    showSuccessToast(text + "成功")
 | 
			
		||||
    item.publish = action
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error(text + "失败:" + e.message)
 | 
			
		||||
    showFailToast(text + "失败:" + e.message)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -469,6 +481,23 @@ const imageView = (item) => {
 | 
			
		||||
  showImagePreview([item['img_url']]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const translating = ref(false)
 | 
			
		||||
const translatePrompt = () => {
 | 
			
		||||
  if (params.value.prompt === '') {
 | 
			
		||||
    return showToast("请输入中文提示词!")
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  translating.value = true
 | 
			
		||||
  const prompt = params.value.prompt
 | 
			
		||||
  httpPost("/api/prompt/translate", {"prompt": prompt}).then(res => {
 | 
			
		||||
    params.value.prompt = res.data
 | 
			
		||||
    translating.value = false
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    translating.value = false
 | 
			
		||||
    showFailToast("翻译失败:" + e.message)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="stylus">
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user