App.vue 5.2 KB
Newer Older
6
UPDATE  
64104061f23fda247c679fa8 已提交
1
<template>
6
622eda98dfef6c4fdb84ccca 已提交
2
  <div class="container ivu-p">
6
622eda98dfef6c4fdb84ccca 已提交
3 4 5 6 7 8
    <Title :level="4" class="ivu-text-center">ChatGPT 中英互译</Title>
    <Paragraph class="ivu-text-center">
      Powered By <img src="./assets/inscode-logo.png" height="14">
      <br>
      <a href="https://inscode.net">https://inscode.net</a>
    </Paragraph>
6
622eda98dfef6c4fdb84ccca 已提交
9
    <Alert>QPM 是 5,如果超过访问限制,可以到 <a href="https://inscode.csdn.net/@aresn/gpt-vue">https://inscode.csdn.net/@aresn/gpt-vue</a> Fork 后免费使用自己的额度。</Alert>
6
622eda98dfef6c4fdb84ccca 已提交
10 11 12 13 14
    <div class="dialog">
      <template v-for="(item, index) in dialogs" :key="index">
        <div class="dialog-item" :class="{ 'dialog-item-me': item.role === 'me', 'dialog-item-ai': item.role === 'ai' }">
          <div class="dialog-item-main">{{ item.text }}</div>
        </div>
6
622eda98dfef6c4fdb84ccca 已提交
15 16 17 18 19 20
        <div class="dialog-action" :class="{ 'dialog-action-me': item.role === 'me', 'dialog-action-ai': item.role === 'ai' }">
          <Space class="ivu-mt-8">
            <Button size="small" icon="md-megaphone" @click="handleRead(item.text)">朗读</Button>
            <Button size="small" icon="md-copy" @click="handleCopy(item.text)">复制</Button>
          </Space>
        </div>
6
622eda98dfef6c4fdb84ccca 已提交
21 22 23
      </template>
    </div>
    <div class="question ivu-mt">
6
622eda98dfef6c4fdb84ccca 已提交
24
      <Input v-model="question" type="textarea" :autosize="{ minRows: 4, maxRows: 6 }" placeholder="当你输入中文时,会翻译为英文;当你输入英文时,则会翻译为中文..." />
6
update  
64104061f23fda247c679fa8 已提交
25 26
      <Row class="ivu-mt">
        <Col>
6
622eda98dfef6c4fdb84ccca 已提交
27
          <Button type="primary" size="large" icon="md-send" :loading="loading" @click="handleSend">翻译</Button>
6
update  
64104061f23fda247c679fa8 已提交
28 29
        </Col>
        <Col>
6
622eda98dfef6c4fdb84ccca 已提交
30
          <Button size="large" class="ivu-ml" icon="md-add" :disabled="loading" @click="handleNewChat">新对话</Button>
6
update  
64104061f23fda247c679fa8 已提交
31 32
        </Col>
      </Row>
6
622eda98dfef6c4fdb84ccca 已提交
33 34
    </div>
  </div>
6
UPDATE  
64104061f23fda247c679fa8 已提交
35
</template>
6
update  
64104061f23fda247c679fa8 已提交
36
<script>
6
UPDATE  
64104061f23fda247c679fa8 已提交
37 38
import { fetchEventSource } from '@microsoft/fetch-event-source';
import { apiKey, apiUrl } from './api';
39

40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
export default {
  data() {
    return {
      question: '',
      loading: false,
      dialogs: []
    }
  },
  methods: {
    handleSend() {
      if (this.loading || this.question === '') return;
      this.loading = true;

      const question = this.question;
      this.question = '';

      this.dialogs.push({
        id: this.dialogs.length + 1,
        role: 'me',
        text: question
      });

      const aiDialogID = this.dialogs.length + 1;
63

64 65 66
      this.dialogs.push({
        id: aiDialogID,
        role: 'ai',
6
622eda98dfef6c4fdb84ccca 已提交
67
        text: 'AI 翻译中...'
68
      });
69

6
UPDATE  
64104061f23fda247c679fa8 已提交
70
      const dialog = this.dialogs.find(item => item.id === aiDialogID);
6
update  
64104061f23fda247c679fa8 已提交
71

6
UPDATE  
64104061f23fda247c679fa8 已提交
72 73 74 75 76 77 78 79 80 81
      /**
       * 发送请求,InsCode 已经集成了 GPT 能力
       * 在 vite.config.js 中已通过环境变量写入了 apiKey(该 key 是动态写入使用者的,在 IDE 中是作者,发布到社区是运行该作品的用户)
       * 发布到社区后,将消耗运行者的额度
       * 注意:如果部署应用,任何人通过部署后的域名访问应用时,都将消耗部署者的额度
       */
      const body = {
        messages: [
          {
            role: 'user',
6
622eda98dfef6c4fdb84ccca 已提交
82
            content: '把以下内容进行翻译,只返回翻译后的内容。现在你是一个英汉互译器,当我输入中文时,你翻译成英文;当我输入英文时,请翻译成中文。以下是要翻译的内容\n\n' + question
6
update  
64104061f23fda247c679fa8 已提交
83
          }
6
UPDATE  
64104061f23fda247c679fa8 已提交
84 85 86
        ],
        apikey: apiKey
      }
87

6
UPDATE  
64104061f23fda247c679fa8 已提交
88 89 90
      const source = fetchEventSource(apiUrl, {
        method: 'POST',
        headers: {
6
622eda98dfef6c4fdb84ccca 已提交
91
          'Content-Type': 'application/json'
6
UPDATE  
64104061f23fda247c679fa8 已提交
92 93 94 95 96 97
        },
        body: JSON.stringify(body),
        onopen: (response) => {
          dialog.text = '';
        },
        onmessage: (msg) => {
6
64104061f23fda247c679fa8 已提交
98 99 100 101
          if (msg.data === '[DONE]') {
            this.loading = false;
            return;
          };
6
UPDATE  
64104061f23fda247c679fa8 已提交
102
          const data = JSON.parse(msg.data);
6
64104061f23fda247c679fa8 已提交
103 104
          const finish_reason = data.choices[0].finish_reason;
          const finish = finish_reason === 'stop' || finish_reason === 'length';
6
UPDATE  
64104061f23fda247c679fa8 已提交
105 106
          const content = data.choices[0].delta.content;

6
622eda98dfef6c4fdb84ccca 已提交
107 108
          console.log(222, content);

6
UPDATE  
64104061f23fda247c679fa8 已提交
109 110 111 112 113
          if (finish) {
            this.loading = false;
          } else if (content) {
            const text = content;
            dialog.text += text;
6
622eda98dfef6c4fdb84ccca 已提交
114
            if (content.indexOf('超过访问限制') >=0) this.loading = false;
6
UPDATE  
64104061f23fda247c679fa8 已提交
115 116 117 118
          }
        },
        onerror: (err) => {
          console.log("error", err);
119
        }
6
UPDATE  
64104061f23fda247c679fa8 已提交
120
      });
121 122 123
    },
    handleNewChat() {
      this.dialogs = [];
6
622eda98dfef6c4fdb84ccca 已提交
124 125 126 127 128 129 130 131 132 133 134
    },
    handleRead (text) {
      const speech = new SpeechSynthesisUtterance(text);
      speech.rate = 1;
      speech.pitch = 1;
      window.speechSynthesis.speak(speech);
    },
    handleCopy (text) {
      this.$Copy({
          text: text
      })
6
update  
64104061f23fda247c679fa8 已提交
135 136
    }
  }
137
}
6
622eda98dfef6c4fdb84ccca 已提交
138
</script>
6
update  
64104061f23fda247c679fa8 已提交
139
<style>
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
.container {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.dialog {
  flex: 1;
  overflow: auto;
}

.dialog-item {
  display: flex;
}

.dialog-item-main {
  max-width: 80%;
  padding: 8px;
  word-wrap: break-word;
  margin-top: 16px;
  border-radius: 4px;
}

.dialog-item-me {
  justify-content: flex-end;
}

.dialog-item-me .dialog-item-main {
  background-color: antiquewhite;
}

.dialog-item-ai .dialog-item-main {
  background-color: #eee;
}
6
622eda98dfef6c4fdb84ccca 已提交
174 175 176 177 178 179 180

.dialog-action{
  display: flex;
}
.dialog-action-me{
  justify-content: flex-end;
}
6
update  
64104061f23fda247c679fa8 已提交
181
</style>