14 files modified
1 files added
| | |
| | | "申购总额": "Gesamter Zeichnungsbetrag", |
| | | "现价总额": "Gesamter aktueller Preis", |
| | | "利润百分比": "Gewinnprozentsatz", |
| | | "ICO申购": "ICO-Zeichnung", |
| | | "发掘最热、最新币种,及时捕捉市场机会": "Entdecken Sie die heißesten und neuesten Kryptowährungen und nutzen Sie Marktchancen rechtzeitig", |
| | | "募集价格": "Zeichnungspreis", |
| | | "实际支付": "Tatsächliche Zahlung", |
| | | "限售时间": "Verkaufsbeschränkungszeit", |
| | | "持仓市值": "Marktwert der Bestände", |
| | | "购买总额": "Gesamtkaufbetrag", |
| | | "持仓信息": "Bestandsinformationen", |
| | | "此币还没有发行时间": "Diese Münze hat noch keine Ausgabezeit", |
| | | "请输入申购数量": "Bitte geben Sie die Zeichnungsmenge ein", |
| | | } |
| | |
| | | "申购总额": "Importo totale di sottoscrizione", |
| | | "现价总额": "Prezzo corrente totale", |
| | | "利润百分比": "Percentuale di profitto", |
| | | "ICO申购": "Sottoscrizione ICO", |
| | | "发掘最热、最新币种,及时捕捉市场机会": "Scopri le criptovalute più calde e recenti, cogli le opportunità di mercato in tempo", |
| | | "募集价格": "Prezzo di sottoscrizione", |
| | | "实际支付": "Pagamento effettivo", |
| | | "限售时间": "Tempo di restrizione di vendita", |
| | | "持仓市值": "Valore di mercato delle partecipazioni", |
| | | "购买总额": "Importo totale di acquisto", |
| | | "持仓信息": "Informazioni sulle partecipazioni", |
| | | "此币还没有发行时间": "Questa moneta non ha ancora un tempo di emissione", |
| | | "请输入申购数量": "Inserisci la quantità di sottoscrizione", |
| | | } |
| | |
| | | "申购总额": "申込総額", |
| | | "现价总额": "現在価格総額", |
| | | "利润百分比": "利益率", |
| | | "ICO申购": "ICO申込", |
| | | "发掘最热、最新币种,及时捕捉市场机会": "最も人気のある最新の暗号通貨を発見し、市場の機会をタイムリーに捉える", |
| | | "募集价格": "募集価格", |
| | | "实际支付": "実際の支払い", |
| | | "限售时间": "制限時間", |
| | | "持仓市值": "保有時価総額", |
| | | "购买总额": "購入総額", |
| | | "持仓信息": "保有情報", |
| | | "此币还没有发行时间": "このコインにはまだ発行時間がありません", |
| | | "请输入申购数量": "申込数量を入力してください", |
| | | } |
| | |
| | | "申购总额": "Valor total da subscrição", |
| | | "现价总额": "Preço atual total", |
| | | "利润百分比": "Percentagem de lucro", |
| | | "ICO申购": "Subscrição ICO", |
| | | "发掘最热、最新币种,及时捕捉市场机会": "Descubra as criptomoedas mais quentes e recentes, aproveite as oportunidades de mercado em tempo hábil", |
| | | "募集价格": "Preço de subscrição", |
| | | "实际支付": "Pagamento real", |
| | | "限售时间": "Tempo de restrição de venda", |
| | | "持仓市值": "Valor de mercado das participações", |
| | | "购买总额": "Valor total da compra", |
| | | "持仓信息": "Informações das participações", |
| | | "此币还没有发行时间": "Esta moeda ainda não tem tempo de emissão", |
| | | "请输入申购数量": "Por favor, insira a quantidade de subscrição", |
| | | } |
| | |
| | | "申购总额": "Importe total de suscripción", |
| | | "现价总额": "Precio actual total", |
| | | "利润百分比": "Porcentaje de beneficio", |
| | | "ICO申购": "Suscripción ICO", |
| | | "发掘最热、最新币种,及时捕捉市场机会": "Descubra las criptomonedas más populares y recientes, aproveche las oportunidades del mercado a tiempo", |
| | | "募集价格": "Precio de suscripción", |
| | | "实际支付": "Pago real", |
| | | "限售时间": "Tiempo de restricción de venta", |
| | | "持仓市值": "Valor de mercado de las participaciones", |
| | | "购买总额": "Importe total de compra", |
| | | "持仓信息": "Información de participaciones", |
| | | "此币还没有发行时间": "Esta moneda aún no tiene tiempo de emisión", |
| | | "请输入申购数量": "Por favor, ingrese la cantidad de suscripción", |
| | | } |
| | |
| | | "申购总额": "申購總額", |
| | | "现价总额": "現價總額", |
| | | "利润百分比": "利潤百分比", |
| | | "ICO申购": "ICO申購", |
| | | "发掘最热、最新币种,及时捕捉市场机会": "發掘最熱、最新幣種,及時捕捉市場機會", |
| | | "募集价格": "募集價格", |
| | | "实际支付": "實際支付", |
| | | "限售时间": "限售時間", |
| | | "持仓市值": "持倉市值", |
| | | "购买总额": "購買總額", |
| | | "持仓信息": "持倉信息", |
| | | "此币还没有发行时间": "此幣還沒有發行時間", |
| | | "请输入申购数量": "請輸入申購數量", |
| | | } |
| | |
| | | "申购总额": "Total Subscription Amount", |
| | | "现价总额": "Total Current Price", |
| | | "利润百分比": "Profit Percentage", |
| | | "ICO申购": "ICO Subscription", |
| | | "发掘最热、最新币种,及时捕捉市场机会": "Discover the hottest and latest cryptocurrencies, seize market opportunities in time", |
| | | "募集价格": "Subscription Price", |
| | | "实际支付": "Actual Payment", |
| | | "限售时间": "Restriction Time", |
| | | "持仓市值": "Market Value of Holdings", |
| | | "购买总额": "Total Purchase Amount", |
| | | "持仓信息": "Holding Information", |
| | | "此币还没有发行时间": "This coin has no issue time yet", |
| | | "请输入申购数量": "Please enter subscription quantity", |
| | | } |
| | |
| | | "申购总额": "Montant total de souscription", |
| | | "现价总额": "Prix actuel total", |
| | | "利润百分比": "Pourcentage de profit", |
| | | "ICO申购": "Souscription ICO", |
| | | "发掘最热、最新币种,及时捕捉市场机会": "Découvrez les cryptomonnaies les plus chaudes et les plus récentes, saisissez les opportunités du marché en temps opportun", |
| | | "募集价格": "Prix de souscription", |
| | | "实际支付": "Paiement réel", |
| | | "限售时间": "Temps de restriction de vente", |
| | | "持仓市值": "Valeur marchande des avoirs", |
| | | "购买总额": "Montant total d'achat", |
| | | "持仓信息": "Informations sur les avoirs", |
| | | "此币还没有发行时间": "Cette pièce n'a pas encore de temps d'émission", |
| | | "请输入申购数量": "Veuillez saisir la quantité de souscription", |
| | | } |
| | |
| | | "申购总额": "청약 총액", |
| | | "现价总额": "현재가 총액", |
| | | "利润百分比": "이익률", |
| | | "ICO申购": "ICO 청약", |
| | | "发掘最热、最新币种,及时捕捉市场机会": "가장 인기 있고 최신 암호화폐를 발견하고 시장 기회를 적시에 포착하세요", |
| | | "募集价格": "모집 가격", |
| | | "实际支付": "실제 지불", |
| | | "限售时间": "제한 판매 시간", |
| | | "持仓市值": "보유 시가총액", |
| | | "购买总额": "구매 총액", |
| | | "持仓信息": "보유 정보", |
| | | "此币还没有发行时间": "이 코인은 아직 발행 시간이 없습니다", |
| | | "请输入申购数量": "청약 수량을 입력하세요", |
| | | } |
| | |
| | | "申购总额": "จำนวนเงินสมัครซื้อทั้งหมด", |
| | | "现价总额": "ราคาปัจจุบันรวม", |
| | | "利润百分比": "เปอร์เซ็นต์กำไร", |
| | | "ICO申购": "การสมัครซื้อ ICO", |
| | | "发掘最热、最新币种,及时捕捉市场机会": "ค้นพบสกุลเงินดิจิทัลที่ร้อนแรงและใหม่ล่าสุด จับโอกาสในตลาดอย่างทันท่วงที", |
| | | "募集价格": "ราคาการสมัครซื้อ", |
| | | "实际支付": "การชำระเงินจริง", |
| | | "限售时间": "เวลาจำกัดการขาย", |
| | | "持仓市值": "มูลค่าตลาดของสินทรัพย์", |
| | | "购买总额": "จำนวนเงินซื้อทั้งหมด", |
| | | "持仓信息": "ข้อมูลสินทรัพย์", |
| | | "此币还没有发行时间": "เหรียญนี้ยังไม่มีเวลาออกจำหน่าย", |
| | | "请输入申购数量": "กรุณากรอกจำนวนการสมัครซื้อ", |
| | | } |
| | |
| | | "申购总额": "Tổng số tiền đăng ký mua", |
| | | "现价总额": "Tổng giá hiện tại", |
| | | "利润百分比": "Tỷ lệ lợi nhuận", |
| | | "ICO申购": "Đăng ký mua ICO", |
| | | "发掘最热、最新币种,及时捕捉市场机会": "Khám phá các loại tiền điện tử nóng nhất và mới nhất, nắm bắt cơ hội thị trường kịp thời", |
| | | "募集价格": "Giá đăng ký mua", |
| | | "实际支付": "Thanh toán thực tế", |
| | | "限售时间": "Thời gian hạn chế bán", |
| | | "持仓市值": "Giá trị thị trường nắm giữ", |
| | | "购买总额": "Tổng số tiền mua", |
| | | "持仓信息": "Thông tin nắm giữ", |
| | | "此币还没有发行时间": "Đồng xu này chưa có thời gian phát hành", |
| | | "请输入申购数量": "Vui lòng nhập số lượng đăng ký mua", |
| | | } |
| | |
| | | "申购总额": "申购总额", |
| | | "现价总额": "现价总额", |
| | | "利润百分比": "利润百分比", |
| | | "ICO申购": "ICO申购", |
| | | "发掘最热、最新币种,及时捕捉市场机会": "发掘最热、最新币种,及时捕捉市场机会", |
| | | "募集价格": "募集价格", |
| | | "实际支付": "实际支付", |
| | | "限售时间": "限售时间", |
| | | "持仓市值": "持仓市值", |
| | | "购买总额": "购买总额", |
| | | "持仓信息": "持仓信息", |
| | | "此币还没有发行时间": "此币还没有发行时间", |
| | | "请输入申购数量": "请输入申购数量", |
| | | } |
| | |
| | | data: params |
| | | }) |
| | | }; |
| | | //ico查询持仓 |
| | | export const _get_ico_position = (params) => { |
| | | return request({ |
| | | url: `${API_PREFIX}/exchangeapplyorder!get_ico_position.action`, |
| | | method: METHODS.GET, |
| | | data: params |
| | | }) |
| | | }; |
| | | //ico申购new |
| | | export const _ico_buy = (params) => { |
| | | return request({ |
| | | url: `${API_PREFIX}/exchangeapplyorder!ico_buy.action`, |
| | | method: METHODS.GET, |
| | | data: params |
| | | }) |
| | | }; |
| New file |
| | |
| | | <template> |
| | | <div class="ico"> |
| | | <fx-header :showLeft="false"> |
| | | <template v-slot:title> |
| | | <div>ICO</div> |
| | | </template> |
| | | <template v-slot:right> |
| | | <van-icon name="todo-list-o" @click="$router.push('/ICO/icoRecord')" /> |
| | | </template> |
| | | </fx-header> |
| | | |
| | | <div class="ico_list"> |
| | | <div class="ico_item mb-5" v-for="i in icoList" :key="i.id"> |
| | | <div class="item_1"> |
| | | {{ i.name }} |
| | | </div> |
| | | <div class="item_2 flex justify-between"> |
| | | <div class="mr-5">{{ $t('申购时间') }}</div> |
| | | <div>{{ i.startDate }} ~ {{ i.endDate }}</div> |
| | | </div> |
| | | <div class="item_2 flex justify-between"> |
| | | <div>{{ $t('最低认购') }}</div> |
| | | <div>{{ i.minContribution }}</div> |
| | | </div> |
| | | <div class="item_2 flex justify-between"> |
| | | <div>{{ $t('币种数量') }}</div> |
| | | <div>{{ i.maxContribution }}</div> |
| | | </div> |
| | | <div class="item_2 flex justify-between"> |
| | | <div>{{ $t('IssuePrice') }}</div> |
| | | <div>{{ i.unitAmount }}</div> |
| | | </div> |
| | | |
| | | <div class="item_2 flex justify-between"> |
| | | <div>{{ $t('listingDate') }}</div> |
| | | <div>{{ i.marketDate }}</div> |
| | | </div> |
| | | <div class="item_2 flex justify-between align-center"> |
| | | <div>{{ $t('进度') }}</div> |
| | | <div style="width: 70%;padding-top: 1rem;"> |
| | | <van-progress :percentage="i.progressRate || 0" track-color="#ccc" /> |
| | | </div> |
| | | </div> |
| | | <div class="item_3 flex justify-center"> |
| | | <van-button type="default" round size="large" @click="openBuy(i)">{{$t('申购')}}</van-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | |
| | | <!-- 购买弹窗 --> |
| | | <van-popup v-model:show="show" round> |
| | | <div class="buy_popup"> |
| | | <div class="buy_title flex justify-center">{{ itemObj.symbol }}</div> |
| | | |
| | | <van-field v-model="sgNum" type="digit" :label="$t('申购数量')" /> |
| | | |
| | | <div class="flex justify-center mt-5"> |
| | | <van-button type="default" size="large" round @click="buy">{{ $t('confirm') }}</van-button> |
| | | </div> |
| | | </div> |
| | | </van-popup> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref } from "vue"; |
| | | import { showToast } from 'vant' |
| | | import { _icoList, _icoSubscribe } from "@/service/ico.api.js"; |
| | | import { useI18n } from "vue-i18n"; |
| | | const { t } = useI18n() |
| | | |
| | | // 获取列表 |
| | | const icoList = ref([]) |
| | | _icoList().then(res => { |
| | | icoList.value = res.records |
| | | }).catch(err => { |
| | | // showToast(err.msg) |
| | | }) |
| | | |
| | | // 打开申购弹窗 |
| | | const show = ref(false) // 控制弹窗显示 |
| | | const itemObj = ref({}) // ico列表项 |
| | | const sgNum = ref(0) // 申购数量 |
| | | const openBuy = (i) => { |
| | | show.value = true |
| | | itemObj.value = i |
| | | } |
| | | |
| | | // 申购 |
| | | const buy = () => { |
| | | let opt = { |
| | | icoProjectId: itemObj.value.id, |
| | | subscribeNums: sgNum.value, |
| | | subscriptionType: 1, |
| | | } |
| | | _icoSubscribe(opt).then(res => { |
| | | showToast(t('submitSuccess')) |
| | | show.value = false |
| | | }).catch(err => { |
| | | showToast(err) |
| | | }) |
| | | } |
| | | |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .ico { |
| | | padding: 0rem 1.2rem 5rem 1.2rem; |
| | | font-size: 1.5rem; |
| | | |
| | | .buy_popup { |
| | | width: 40rem; |
| | | padding: 1rem; |
| | | |
| | | .buy_title { |
| | | font-size: 2.5rem; |
| | | font-weight: 700; |
| | | border-bottom: #aaa solid 1px; |
| | | padding: 1rem; |
| | | } |
| | | } |
| | | |
| | | .ico_list { |
| | | padding: 1rem 0rem; |
| | | |
| | | .ico_item { |
| | | background-color: #333; |
| | | padding: .5rem 1rem; |
| | | border: #aaa solid 1px; |
| | | border-radius: 1rem; |
| | | |
| | | .item_1 { |
| | | padding: 1rem .5rem; |
| | | border-bottom: #ccc solid 1px; |
| | | font-size: 2rem; |
| | | font-weight: 700; |
| | | } |
| | | |
| | | .item_2 { |
| | | padding: 1rem .5rem; |
| | | border-bottom: #ccc solid 1px; |
| | | font-size: 1.6rem; |
| | | font-weight: 500; |
| | | |
| | | &>div:last-child { |
| | | color: #999; |
| | | } |
| | | } |
| | | |
| | | .item_3 { |
| | | padding: .5rem; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <div class="ico"> |
| | | <fx-header :showLeft="false"> |
| | | <template v-slot:title> |
| | | <div>ICO</div> |
| | | <div>{{ $t('ICO申购') }}</div> |
| | | </template> |
| | | <template v-slot:right> |
| | | <!-- <template v-slot:right> |
| | | <van-icon name="todo-list-o" @click="$router.push('/ICO/icoRecord')" /> |
| | | </template> |
| | | </template> --> |
| | | </fx-header> |
| | | |
| | | <div class="ico_list"> |
| | | <div class="ico_item mb-5" v-for="i in icoList" :key="i.id"> |
| | | <div class="item_1"> |
| | | {{ i.name }} |
| | | </div> |
| | | <div class="item_2 flex justify-between"> |
| | | <div class="mr-5">{{ $t('申购时间') }}</div> |
| | | <div>{{ i.startDate }} ~ {{ i.endDate }}</div> |
| | | </div> |
| | | <div class="item_2 flex justify-between"> |
| | | <div>{{ $t('最低认购') }}</div> |
| | | <div>{{ i.minContribution }}</div> |
| | | </div> |
| | | <div class="item_2 flex justify-between"> |
| | | <div>{{ $t('币种数量') }}</div> |
| | | <div>{{ i.maxContribution }}</div> |
| | | </div> |
| | | <div class="item_2 flex justify-between"> |
| | | <div>{{ $t('IssuePrice') }}</div> |
| | | <div>{{ i.unitAmount }}</div> |
| | | </div> |
| | | <div class="ico-intro"> |
| | | {{ $t('发掘最热、最新币种,及时捕捉市场机会') }} |
| | | </div> |
| | | |
| | | <div class="item_2 flex justify-between"> |
| | | <div>{{ $t('listingDate') }}</div> |
| | | <div>{{ i.marketDate }}</div> |
| | | <!-- ICO申购卡片 --> |
| | | <div class="ico-card"> |
| | | <div class="card-header"> |
| | | <div class="token-info"> |
| | | <div class="token-symbol">CLK</div> |
| | | </div> |
| | | <div class="item_2 flex justify-between align-center"> |
| | | <div>{{ $t('进度') }}</div> |
| | | <div style="width: 70%;padding-top: 1rem;"> |
| | | <van-progress :percentage="i.progressRate || 0" track-color="#ccc" /> |
| | | </div> |
| | | |
| | | <div class="card-content"> |
| | | <div class="price-row"> |
| | | <div class="price-item"> |
| | | <div class="price-label">{{ $t('募集价格') }}</div> |
| | | <div class="price-value green">{{ closePrice || '0' }} USDT</div> |
| | | </div> |
| | | <div class="price-item"> |
| | | <div class="price-label">{{ $t('实际支付') }}</div> |
| | | <div class="price-value">{{ actualPayment }} USDT</div> |
| | | </div> |
| | | </div> |
| | | <div class="item_3 flex justify-center"> |
| | | <van-button type="default" round size="large" @click="openBuy(i)">{{$t('申购')}}</van-button> |
| | | |
| | | <div class="input-row"> |
| | | <div class="input-label">{{ $t('申购数量') }}</div> |
| | | <div class="input-wrapper"> |
| | | <van-field v-model="sgNum" type="digit" :placeholder="$t('请输入申购数量')" class="subscribe-input" /> |
| | | <van-button size="small" type="default" @click="setAll" class="all-btn">{{ $t('全部') |
| | | }}</van-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="balance-row"> |
| | | <div class="balance-label">{{ $t('可用余额') }}</div> |
| | | <div class="balance-value">{{ initOpen.volume || '0' }} USDT</div> |
| | | </div> |
| | | |
| | | <van-button type="primary" block round class="buy-btn" @click="buy"> |
| | | {{ $t('买入') }} |
| | | </van-button> |
| | | </div> |
| | | </div> |
| | | |
| | | |
| | | <!-- 购买弹窗 --> |
| | | <van-popup v-model:show="show" round> |
| | | <div class="buy_popup"> |
| | | <div class="buy_title flex justify-center">{{ itemObj.symbol }}</div> |
| | | |
| | | <van-field v-model="sgNum" type="digit" :label="$t('申购数量')" /> |
| | | |
| | | <div class="flex justify-center mt-5"> |
| | | <van-button type="default" size="large" round @click="buy">{{ $t('confirm') }}</van-button> |
| | | <!-- 持仓信息卡片 --> |
| | | <div class="holding-card" v-if="recordData"> |
| | | <div class="card-title">{{ $t('持仓信息') }}</div> |
| | | <div class="card-header"> |
| | | <div class="token-info"> |
| | | <div class="token-symbol">CLK</div> |
| | | </div> |
| | | </div> |
| | | </van-popup> |
| | | |
| | | <div class="card-content"> |
| | | <div class="info-row"> |
| | | <div class="info-label">{{ $t('限售时间') }}</div> |
| | | <div class="info-value">{{ recordData.lockingTime }}</div> |
| | | </div> |
| | | <div class="info-row"> |
| | | <div class="info-label">{{ $t('申购数量') }}</div> |
| | | <div class="info-value">{{ recordData.purchaseQuantity || '0' }}</div> |
| | | </div> |
| | | <div class="info-row"> |
| | | <div class="info-label">{{ $t('现价') }}</div> |
| | | <div class="info-value">{{ recordData.currentPrice || '--' }}</div> |
| | | </div> |
| | | <div class="info-row"> |
| | | <div class="info-label">{{ $t('购买价') }}</div> |
| | | <div class="info-value">{{ recordData.purchasePrice || '--' }}</div> |
| | | </div> |
| | | <div class="info-row"> |
| | | <div class="info-label">{{ $t('持仓市值') }}</div> |
| | | <div class="info-value">{{ recordData.positionvalue || '0.00' }}</div> |
| | | </div> |
| | | <div class="info-row"> |
| | | <div class="info-label">{{ $t('购买总额') }}</div> |
| | | <div class="info-value">{{ (recordData.purchaseQuantity * recordData.purchasePrice).toFixed(4) || |
| | | '--' }} |
| | | </div> |
| | | </div> |
| | | <div class="info-row"> |
| | | <div class="info-label">{{ $t('盈亏') }}</div> |
| | | <div class="info-value red"> |
| | | {{ recordData.profitPercent ? (recordData.profitPercent + '%') : '--%' }} |
| | | ({{ recordData.profit || '0.00' }}USDT) |
| | | </div> |
| | | </div> |
| | | <div class="sell-btn-wrapper" v-if="canSell"> |
| | | <van-button type="primary" block round class="sell-btn" @click="goToSell(recordData)"> |
| | | {{ $t('卖出') }} |
| | | </van-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref } from "vue"; |
| | | import { ref, computed, onMounted, onBeforeUnmount } from "vue"; |
| | | import { showToast } from 'vant' |
| | | import { _icoList, _icoSubscribe } from "@/service/ico.api.js"; |
| | | import { _icoList, _ico_buy, _get_ico_position } from "@/service/ico.api.js"; |
| | | import { _getBalance } from "@/service/user.api.js"; |
| | | import { useI18n } from "vue-i18n"; |
| | | import { useUserStore } from '@/store/user'; |
| | | import { useRouter } from "vue-router"; |
| | | import { setStorage } from "@/utils/index.js"; |
| | | import trading from '@/service/trading' |
| | | import { WS_URL } from '@/config' |
| | | const { t } = useI18n() |
| | | const userStore = useUserStore() |
| | | const router = useRouter() |
| | | |
| | | // 获取列表 |
| | | const icoList = ref([]) |
| | | _icoList().then(res => { |
| | | icoList.value = res.records |
| | | }).catch(err => { |
| | | // showToast(err.msg) |
| | | // 记录数据 |
| | | const recordData = ref(null) |
| | | // 申购数量 |
| | | const sgNum = ref('') |
| | | // 开仓数据 |
| | | const initOpen = ref({}) |
| | | // ws |
| | | const socket = ref(null) |
| | | // 价格 |
| | | const closePrice = ref(0) |
| | | |
| | | // 计算实际支付 |
| | | const actualPayment = computed(() => { |
| | | if (!sgNum.value || !closePrice.value) return '0' |
| | | return (parseFloat(sgNum.value) * parseFloat(closePrice.value)).toFixed(4) |
| | | }) |
| | | |
| | | // 打开申购弹窗 |
| | | const show = ref(false) // 控制弹窗显示 |
| | | const itemObj = ref({}) // ico列表项 |
| | | const sgNum = ref(0) // 申购数量 |
| | | const openBuy = (i) => { |
| | | show.value = true |
| | | itemObj.value = i |
| | | // 判断是否可以卖出(限售时间是否已过) |
| | | const canSell = computed(() => { |
| | | if (!recordData.value || !recordData.value.lockingTime) return false |
| | | try { |
| | | // 将 lockingTime 格式 "2026-02-09" 转换为 Date 对象(设置为当天的 00:00:00) |
| | | const lockingDate = new Date(recordData.value.lockingTime + ' 00:00:00') |
| | | const now = new Date() |
| | | // 如果限售时间早于当前时间,则可以卖出 |
| | | return lockingDate < now |
| | | } catch (error) { |
| | | console.error('时间解析错误', error) |
| | | return false |
| | | } |
| | | }) |
| | | |
| | | // 获取持仓 |
| | | const getRecordList = () => { |
| | | _get_ico_position({ |
| | | session_token: initOpen.value.session_token, |
| | | }).then(res => { |
| | | recordData.value = res |
| | | }).catch(err => { |
| | | console.error('获取持仓失败', err) |
| | | }) |
| | | } |
| | | |
| | | // 获取开仓数据 |
| | | const getInitOpen = () => { |
| | | if (userStore.userInfo && userStore.userInfo.token) { |
| | | trading.tradeBuyToken().then(res => { |
| | | initOpen.value = res || {} |
| | | getRecordList() |
| | | }).catch(err => { |
| | | console.error('获取开仓数据失败', err) |
| | | }) |
| | | } |
| | | } |
| | | |
| | | // 设置全部 |
| | | const setAll = () => { |
| | | if (!closePrice.value || !initOpen.value.volume) { |
| | | showToast(t('余额不足')) |
| | | return |
| | | } |
| | | // 计算最大可申购数量(基于可用余额) |
| | | const maxNum = Math.floor((parseFloat(initOpen.value.volume) / parseFloat(closePrice.value)) * 10000) / 10000 |
| | | sgNum.value = maxNum.toString() |
| | | } |
| | | |
| | | // 最新价格获取 |
| | | const handleQoutes = (data) => { |
| | | if (data && data.length) { |
| | | const cur = data[0] |
| | | closePrice.value = cur.close |
| | | // this.range = cur.change_ratio + '' |
| | | // this.quote = cur |
| | | } |
| | | } |
| | | |
| | | // 行情socket |
| | | const startQuoteSocket = () => { |
| | | socket.value = new WebSocket(`${WS_URL}/1/pendleusdt`) |
| | | socket.value.onmessage = (evt) => { |
| | | const { data } = evt |
| | | const { code, data: _data } = JSON.parse(data) |
| | | if (code / 1 === 0) { |
| | | handleQoutes(_data) |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 关闭清空ws |
| | | const closeSocket = () => { |
| | | socket.value && socket.value.close() |
| | | socket.value = null |
| | | } |
| | | |
| | | // 申购 |
| | | const buy = () => { |
| | | let opt = { |
| | | icoProjectId: itemObj.value.id, |
| | | subscribeNums: sgNum.value, |
| | | subscriptionType: 1, |
| | | if (!sgNum.value || parseFloat(sgNum.value) <= 0) { |
| | | showToast(t('请输入申购数量')) |
| | | return |
| | | } |
| | | _icoSubscribe(opt).then(res => { |
| | | |
| | | let opt = { |
| | | volume: actualPayment.value, |
| | | session_token: initOpen.value.session_token, |
| | | symbol: "pendleusdt", // 币种 |
| | | price: closePrice.value, |
| | | total: sgNum.value, |
| | | order_price_type: "opponent", // 市价or限价 |
| | | } |
| | | _ico_buy(opt).then(res => { |
| | | showToast(t('submitSuccess')) |
| | | show.value = false |
| | | sgNum.value = '' |
| | | getInitOpen() |
| | | }).catch(err => { |
| | | showToast(err) |
| | | showToast(err.msg || err || t('申购失败')) |
| | | }) |
| | | } |
| | | |
| | | // 卖出 |
| | | const goToSell = (item) => { |
| | | if (!item) { |
| | | showToast(t('数据加载中,请稍候')) |
| | | return |
| | | } |
| | | // 将卖出参数存储到 localStorage,供交易页面读取 |
| | | setStorage('tradeSellParams', { |
| | | volume: item.purchaseQuantity || '0', |
| | | mode: 'close' // 卖出模式 |
| | | }) |
| | | router.push(`/cryptos/trade/pendleusdt`) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getInitOpen() |
| | | startQuoteSocket() |
| | | }) |
| | | |
| | | onBeforeUnmount(() => { |
| | | closeSocket() |
| | | |
| | | }) |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .ico { |
| | | padding: 0rem 1.2rem 5rem 1.2rem; |
| | | font-size: 1.5rem; |
| | | min-height: 100vh; |
| | | background: #1a1a1a; |
| | | |
| | | .buy_popup { |
| | | width: 40rem; |
| | | padding: 1rem; |
| | | |
| | | .buy_title { |
| | | font-size: 2.5rem; |
| | | font-weight: 700; |
| | | border-bottom: #aaa solid 1px; |
| | | padding: 1rem; |
| | | } |
| | | .ico-intro { |
| | | padding: 1.5rem 0; |
| | | font-size: 1.4rem; |
| | | color: #999; |
| | | text-align: center; |
| | | } |
| | | |
| | | .ico_list { |
| | | padding: 1rem 0rem; |
| | | .ico-card, |
| | | .holding-card { |
| | | background-color: #333; |
| | | border-radius: 1rem; |
| | | padding: 1.5rem; |
| | | margin-bottom: 2rem; |
| | | border: 1px solid #444; |
| | | |
| | | .ico_item { |
| | | background-color: #333; |
| | | padding: .5rem 1rem; |
| | | border: #aaa solid 1px; |
| | | border-radius: 1rem; |
| | | .card-title { |
| | | font-size: 1.8rem; |
| | | font-weight: 700; |
| | | margin-bottom: 1.5rem; |
| | | color: #fff; |
| | | } |
| | | |
| | | .item_1 { |
| | | padding: 1rem .5rem; |
| | | border-bottom: #ccc solid 1px; |
| | | font-size: 2rem; |
| | | font-weight: 700; |
| | | .card-header { |
| | | margin-bottom: 1.5rem; |
| | | padding-bottom: 1rem; |
| | | border-bottom: 1px solid #555; |
| | | |
| | | .token-info { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 1rem; |
| | | |
| | | .token-logo { |
| | | width: 4rem; |
| | | height: 4rem; |
| | | border-radius: 50%; |
| | | background: #444; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | overflow: hidden; |
| | | |
| | | img { |
| | | width: 100%; |
| | | height: 100%; |
| | | object-fit: cover; |
| | | } |
| | | |
| | | .token-placeholder { |
| | | font-size: 2rem; |
| | | font-weight: 700; |
| | | color: #fff; |
| | | } |
| | | } |
| | | |
| | | .token-symbol { |
| | | font-size: 2rem; |
| | | font-weight: 700; |
| | | color: #fff; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .item_2 { |
| | | padding: 1rem .5rem; |
| | | border-bottom: #ccc solid 1px; |
| | | font-size: 1.6rem; |
| | | font-weight: 500; |
| | | .card-content { |
| | | .price-row { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 1.5rem; |
| | | |
| | | &>div:last-child { |
| | | color: #999; |
| | | .price-item { |
| | | flex: 1; |
| | | |
| | | .price-label { |
| | | font-size: 1.4rem; |
| | | color: #999; |
| | | margin-bottom: 0.5rem; |
| | | } |
| | | |
| | | .price-value { |
| | | font-size: 1.8rem; |
| | | font-weight: 600; |
| | | color: #fff; |
| | | |
| | | &.green { |
| | | color: #06CDA5; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .item_3 { |
| | | padding: .5rem; |
| | | .input-row { |
| | | margin-bottom: 1.5rem; |
| | | |
| | | .input-label { |
| | | font-size: 1.4rem; |
| | | color: #999; |
| | | margin-bottom: 0.5rem; |
| | | } |
| | | |
| | | .input-wrapper { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 1rem; |
| | | |
| | | .subscribe-input { |
| | | flex: 1; |
| | | background: #222; |
| | | border-radius: 0.5rem; |
| | | padding: 0; |
| | | |
| | | :deep(.van-field__control) { |
| | | color: #fff; |
| | | font-size: 1.6rem; |
| | | padding: 0 1rem; |
| | | } |
| | | |
| | | :deep(.van-field__label) { |
| | | display: none; |
| | | } |
| | | } |
| | | |
| | | .all-btn { |
| | | min-width: 6rem; |
| | | height: 3.5rem; |
| | | border-radius: 0.5rem; |
| | | background: #444; |
| | | color: #fff; |
| | | border: 1px solid #555; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .balance-row { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 1.5rem; |
| | | padding: 1rem; |
| | | background: #222; |
| | | border-radius: 0.5rem; |
| | | |
| | | .balance-label { |
| | | font-size: 1.4rem; |
| | | color: #999; |
| | | } |
| | | |
| | | .balance-value { |
| | | font-size: 1.6rem; |
| | | color: #fff; |
| | | } |
| | | } |
| | | |
| | | .buy-btn { |
| | | height: 4.5rem; |
| | | font-size: 1.8rem; |
| | | font-weight: 600; |
| | | background: #555; |
| | | border: none; |
| | | color: #fff; |
| | | } |
| | | |
| | | .info-row { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 1rem 0; |
| | | border-bottom: 1px solid #444; |
| | | |
| | | &:last-child { |
| | | border-bottom: none; |
| | | } |
| | | |
| | | .info-label { |
| | | font-size: 1.4rem; |
| | | color: #999; |
| | | } |
| | | |
| | | .info-value { |
| | | font-size: 1.6rem; |
| | | color: #fff; |
| | | font-weight: 500; |
| | | |
| | | &.red { |
| | | color: #f43368; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .sell-btn-wrapper { |
| | | margin-top: 1.5rem; |
| | | padding-top: 1.5rem; |
| | | border-top: 1px solid #444; |
| | | } |
| | | |
| | | .sell-btn { |
| | | height: 4.5rem; |
| | | font-size: 1.8rem; |
| | | font-weight: 600; |
| | | background: #555; |
| | | border: none; |
| | | color: #fff; |
| | | } |
| | | } |
| | | } |