1
jhzh
2026-01-09 f1aaecc9dc0a3d680f2f693ee963d5d060e75734
src/page/home/listcomponents/dazongjiaoyi.vue
@@ -11,38 +11,111 @@
            </div>
        </div>
        <div class="dbox">
            <div class="daz"><span class="d1">{{ $t("MingCheng") }}</span><span class="d2">{{ $t("hj81") }}</span><span class="d3"></span></div>
            <div class="daz">
                <span class="d1">{{ $t("MingCheng") }}</span>
                <span class="d2">{{ $t("hj81") }}</span>
            </div>
        </div>
        <div class="list" v-for="(item, index) in dazongList" :key="index">
            <div class="lbox">
                <div class="lb1">
                    <h6>{{ item.stockName }}</h6>
                    <p>
                        <span v-if="item.stockType == 'sz'">{{ $t("jy83") }}</span>
                        <span class="sh" v-if="item.stockType == 'sh'">{{ $t("jy84") }}</span>
                        <span class="bj" v-if="item.stockType == 'bj'">{{ $t("jy85") }}</span>
                        <a :class="item.stockType == 'sh' ? 'shbg' : item.stockType == 'bj' ? 'bjbg' : ''">{{
                                item.stockGid
                        }}</a>
                    </p>
                <div class="top-section">
                    <div class="lb1">
                        <h6>{{ item.stockName }}</h6>
                        <p>
                            <span v-if="item.stockType == 'sz'">{{ $t("jy83") }}</span>
                            <span class="sh" v-if="item.stockType == 'sh'">{{ $t("jy84") }}</span>
                            <span class="bj" v-if="item.stockType == 'bj'">{{ $t("jy85") }}</span>
                            <a :class="item.stockType == 'sh' ? 'shbg' : item.stockType == 'bj' ? 'bjbg' : ''">{{
                                    item.stockGid
                            }}</a>
                        </p>
                    </div>
                    <div class="top-right">
                        <div class="lb2">
                            <div class="price-value">{{ item.price }}{{ $t('jy51') }}</div>
                            <div class="price-label">{{ $t("hj81") }}</div>
                        </div>
                        <div class="lb3"><a @click="getdetail(item)">{{ $t("hj238") }}</a></div>
                    </div>
                </div>
                <div class="lb2"> {{ item.price }} </div>
                <div class="lb3"><a @click="getdetail(item)">{{ $t("hj238") }}</a></div>
                <div class="middle-section">
                    <div class="share-info">
                        <span class="label">{{ $t('dz_share') }}:</span>
                        <span class="value">{{ formatAmount(item.stockShare || 0) }}</span>
                    </div>
                    <div class="surplus-info">
                        <span class="label">{{ $t('dz_completed') }}:</span>
                        <span class="value">{{ formatAmount(item.stockSurplus || 0) }}</span>
                    </div>
                </div>
                <div class="progress-section">
                <div class="progress-bar">
                    <div class="progress-fill" :style="{ width: getProgressPercent(item) + '%' }">
                    <div class="progress-text-wrap">
                        <div class="progress-text">{{ getProgressPercent(item) }}%</div>
                    </div>
                    </div>
                </div>
                </div>
            </div>
        </div>
        <van-popup v-model="show" round position="bottom">
            <div class="boxd">
                <div class="boxh"> {{ $t("jy86") }} <span @click="show = false"></span></div>
                <h5>{{ $t("hj130") }}</h5>
                <h6>{{ currentItem.price ? currentItem.price : '' }}</h6>
                <div class="erty tghj"><input :placeholder="$t('jy87')" type="number" class="inpy" v-model="num"
                        @input="num = num.replace(/^(0+)|[^\d]+/g, '')"><a>{{ $t("hj117") }}</a></div>
                <p class="plm"><span>{{ $t("jy88") }}</span><a>{{ currentItem.price ? (currentItem.price * num * 100).toFixed(2) :
                        '0.00'
                }}</a></p>
                <div class="erty"><input :placeholder="$t('jy89')" type="password" class="inpy" v-model="password"></div>
                <p class="plm"><span>{{ $t("hj54") }}</span><a>{{ userinfo.enableAmt }}</a></p>
                <div class="maik" @click="getxiadan">{{ $t("hj85") }}</div>
                <!-- 顶部份额和已完成金额 -->
                <!-- <div class="popup-header">
                    <span class="header-left">{{ $t("dz_share") }}: {{ formatAmount(currentItem.stockShare || 0) }}</span>
                    <span class="header-right">{{ $t("dz_completed") }}: {{ formatAmount(currentItem.stockSurplus || 0) }}</span>
                </div> -->
                <!-- 标题和关闭按钮 -->
                <div class="boxh">
                    <span class="close-btn" @click="show = false">×</span>
                    <h5>{{ $t("hj85") }}</h5>
                </div>
                <!-- 价格输入 -->
                <div class="price-section">
                    <div class="erty price-input">
                        <input type="number" class="inpy" v-model="price" disabled :placeholder="currentItem.price || ''">
                        <a class="current-price-btn" @click="setCurrentPrice">{{ $t("hj81") }}</a>
                    </div>
                </div>
                <!-- 买入数量 -->
                <div class="quantity-section">
                    <label class="section-label">{{ $t("jy87") }}</label>
                    <div class="erty quantity-input">
                        <input :placeholder="$t('jy87')" type="number" class="inpy" v-model="num"
                            @input="num = num.replace(/^(0+)|[^\d]+/g, '')">
                        <a>{{ $t("hj117") }}</a>
                    </div>
                </div>
                <!-- 仓位选择 -->
                <div class="position-section">
                    <label class="section-label">{{ $t("hj226") }}</label>
                    <div class="position-buttons">
                        <div class="position-btn" :class="{ active: selectedPosition === '1/4' }" @click="selectPosition('1/4')">{{ $t('hj258') }}</div>
                        <div class="position-btn" :class="{ active: selectedPosition === '1/3' }" @click="selectPosition('1/3')">{{ $t('hj259') }}</div>
                        <div class="position-btn" :class="{ active: selectedPosition === '1/2' }" @click="selectPosition('1/2')">{{ $t('hj260') }}</div>
                        <div class="position-btn" :class="{ active: selectedPosition === 'full' }" @click="selectPosition('full')">{{ $t('hj261') }}</div>
                    </div>
                </div>
                <!-- 金额信息 -->
                <div class="amount-info">
                    <p class="plm">
                        <span>{{ $t("hj54") }}</span>
                        <a>¥{{ (userinfo.enableAmt || 0).toFixed(2) }}</a>
                    </p>
                    <p class="plm">
                        <span>{{ $t("jy88") }}</span>
                        <a class="red-amount">¥{{ getActualAmount() }}</a>
                    </p>
                </div>
                <!-- 密码输入 -->
                <!-- <div class="password-section">
                    <div class="erty">
                        <input :placeholder="$t('jy89')" type="password" class="inpy" v-model="password">
                    </div>
                </div> -->
                <!-- 下单按钮 -->
                <div class="maik" @click="getxiadan">{{ $t("hj85") }}{{ $t("jy150") }}</div>
            </div>
        </van-popup>
    </div>
@@ -59,9 +132,11 @@
            show: false,
            dazongList: [],
            num: '',
            currentItem: '',
            userinfo: '',
            password: ''
            currentItem: {},
            userinfo: {},
            password: '',
            price: '',
            selectedPosition: ''
        }
    },
    mounted() {
@@ -74,31 +149,85 @@
        },
        getdetail(item) {
            this.currentItem = item
            this.price = item.price || ''
            this.num = ''
            this.selectedPosition = ''
            this.password = ''
            this.show = true
        },
        setCurrentPrice() {
            if (this.currentItem.price) {
                this.price = this.currentItem.price
            }
        },
        selectPosition(position) {
            this.selectedPosition = position
            if (this.userinfo.enableAmt && this.price) {
                let availableAmount = parseFloat(this.userinfo.enableAmt) || 0
                let currentPrice = parseFloat(this.price) || 0
                let positionRatio = 0
                switch(position) {
                    case '1/4':
                        positionRatio = 0.25
                        break
                    case '1/3':
                        positionRatio = 0.333
                        break
                    case '1/2':
                        positionRatio = 0.5
                        break
                    case 'full':
                        positionRatio = 1
                        break
                }
                // 计算可买入的手数(1手=100股)
                let maxAmount = availableAmount * positionRatio
                let maxHands = Math.floor(maxAmount / (currentPrice * 100))
                this.num = maxHands.toString()
            }
        },
        getActualAmount() {
            if (this.price && this.num) {
                let price = parseFloat(this.price) || 0
                let num = parseFloat(this.num) || 0
                return (price * num * 100).toFixed(2)
            }
            return '0.00'
        },
        async getxiadan() {
            if (!this.price) {
                this.$toast('请输入价格')
                return
            }
            if (!this.num) {
                this.show = false
                this.$toast('请输入数量')
                this.$toast(this.$t('jy87'))
                return
            }
            if (!this.password) {
                this.show = false
                this.$toast('请输入秘钥')
                return
            }
            // if (!this.password) {
            //     this.$toast(this.$t('jy89'))
            //     return
            // }
            var opt = {
                stockCode: this.currentItem.stockCode,
                password: this.password,
                num: this.num * 100,
                price: this.price
            }
            let res = await api.buyStockDz(opt)
            if (res.status == 0) {
                this.$toast('买入成功')
            } else {
                this.$toast(res.msg)
            }
            // 先关闭弹窗,避免遮罩层遮挡 Toast
            this.show = false
            if (res.status == 0) {
                this.$nextTick(() => {
                    this.$toast(this.$t('dz_buySuccess'))
                })
                this.stockgetDzList()
            } else {
                this.$nextTick(() => {
                    this.$toast(res.msg)
                })
            }
        },
        async stockgetDzList() {
            let res = await api.stockgetDzList()
@@ -112,6 +241,19 @@
            if (data.status === 0) {
                this.userinfo = data.data;
            }
        },
        getProgressPercent(item) {
            if (!item.stockShare || item.stockShare === 0) {
                return 0;
            }
            const percent = (item.stockSurplus || 0) / item.stockShare * 100;
            return Math.min(100, Math.max(0, Math.round(percent * 100) / 100));
        },
        formatAmount(amount) {
            return Number(amount).toLocaleString('zh-CN', {
                minimumFractionDigits: 2,
                maximumFractionDigits: 2
            });
        },
    },
}
@@ -127,6 +269,7 @@
        margin: 0 auto;
        display: flex;
        justify-content: space-between;
        align-items: center;
        span {
            color: #666;
@@ -134,16 +277,13 @@
        }
        .d1 {
            width: 40%;
            flex: 1;
            text-align: left;
        }
        .d2 {
            width: 20%;
            text-align: center;
        }
        .d3 {
            width: 40%;
            flex: 1;
            text-align: right;
        }
    }
}
@@ -173,93 +313,191 @@
.list {
    width: 100%;
    padding: 0.4rem 0;
    border-bottom: 1px solid #e0e0e0;
    padding: 0.4rem 0.3rem;
    margin-bottom: 0.3rem;
    background: #fff;
    border-radius: 0.25rem;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
    .lbox {
        width: 9.35rem;
        margin: 0 auto;
        display: flex;
        justify-content: space-between;
        .lb1 {
            h6 {
                color: #333;
                font-size: .4rem;
                font-weight: 600;
            }
        .top-section {
            display: flex;
            justify-content: space-between;
            align-items: flex-start;
            margin-bottom: 0.4rem;
            p {
                color: #333;
                font-size: .32rem;
                margin-top: 0.13rem;
                span {
                    width: 0.4rem;
                    height: 0.4rem;
                    background: #3b4fde;
                    border-radius: 0.05rem;
                    padding: 0.04rem;
                    text-align: center;
                    line-height: .4rem;
                    color: #fff;
                    font-size: .3rem;
            .lb1 {
                flex: 1;
                h6 {
                    color: #333;
                    font-size: .4rem;
                    font-weight: 600;
                    margin-bottom: 0.13rem;
                }
                a {
                    display: inline-block;
                    height: 0.4rem;
                    line-height: .4rem;
                    padding: 0 0.11rem;
                    background: rgba(59, 79, 222, .1);
                    border-radius: 0.05rem;
                    color: #3b4fde;
                p {
                    color: #333;
                    font-size: .32rem;
                    vertical-align: middle;
                    margin: 0;
                    span {
                        width: 0.4rem;
                        height: 0.4rem;
                        background: #4caf50;
                        border-radius: 0.05rem;
                        padding: 0.04rem;
                        text-align: center;
                        line-height: .4rem;
                        color: #fff;
                        font-size: .3rem;
                        display: inline-block;
                        margin-right: 0.1rem;
                    }
                    a {
                        display: inline-block;
                        height: 0.4rem;
                        line-height: .4rem;
                        padding: 0 0.11rem;
                        background: rgba(59, 79, 222, .1);
                        border-radius: 0.05rem;
                        color: #3b4fde;
                        font-size: .32rem;
                        vertical-align: middle;
                    }
                    .bj {
                        background: #ea6248;
                    }
                    .sh {
                        background: #aa3bde;
                    }
                    .shbg {
                        color: #aa3bde;
                        background: rgba(170, 59, 222, .1);
                    }
                    .bjbg {
                        color: #ea6248;
                        background: rgba(234, 98, 72, .1);
                    }
                }
            }
            .top-right {
                display: flex;
                align-items: flex-end;
                gap: 0.2rem;
                .lb2 {
                    // text-align: right;
                    display: flex;
                    flex-direction: column;
                    align-items: center;
                    .price-value {
                        color: #d73d3d;
                        font-size: .4rem;
                        font-weight: 600;
                    }
                    .price-label {
                        color: #999;
                        font-size: .28rem;
                        margin-top: 0.15rem;
                    }
                }
                .bj {
                    background: #ea6248;
                }
                .sh {
                    background: #aa3bde;
                }
                .shbg {
                    color: #aa3bde;
                    background: rgba(170, 59, 222, .1);
                }
                .bjbg {
                    color: #ea6248;
                    background: rgba(234, 98, 72, .1);
                .lb3 {
                    a {
                        display: inline-block;
                        width: 1.6rem;
                        height: 100%;
                        background: linear-gradient(-55deg, rgb(241, 22, 20), rgb(240, 40, 37));
                        border-radius: 0.35rem;
                        text-align: center;
                        color: #fff;
                        font-size: .32rem;
                        line-height: .67rem;
                    }
                }
            }
        }
        .lb2 {
            color: #d73d3d;
            font-size: .32rem;
            margin-top: 0.32rem;
        }
        .middle-section {
            display: flex;
            justify-content: space-between;
            margin-bottom: 0.1rem;
        .lb3 {
            text-align: right;
            .share-info, .surplus-info {
                display: flex;
                align-items: center;
                gap: 0.1rem;
            a {
                display: inline-block;
                width: 1.6rem;
                height: 0.67rem;
                background: linear-gradient(-55deg,rgb(241, 22, 20),rgb(240, 40, 37));
                border-radius: 0.35rem;
                text-align: center;
                color: #fff;
                font-sizE: .32rem;
                line-height: .67rem;
                margin-top: 0.08rem;
                .label {
                    color: #666;
                    font-size: .32rem;
                }
                .value {
                    color: #333;
                    font-size: .32rem;
                    font-weight: 500;
                }
            }
        }
        .progress-section {
  width: 100%;
  height: 10px; /* 核心:降低整体容器高度,匹配图片紧凑感 */
  display: flex;
  align-items: center;
}
.progress-bar {
  position: relative;
  width: 100%;
  height: 100%; /* 跟随外层容器高度 */
  background: #f0f0f0;
  border-radius: 8px; /* 圆角适配小高度,更精致 */
  overflow: visible;
}
.progress-fill {
  position: relative;
  height: 100%;
  background: linear-gradient(-55deg, rgb(241, 22, 20), rgb(240, 40, 37));
  transition: width 0.3s ease;
  border-radius: 8px; /* 同步圆角 */
  min-width: 40px;
  display: flex;
  align-items: center;
}
.progress-text-wrap {
    position: absolute;
    right: 0;
    top: -0.15556rem;
    height: 300%;
}
.progress-text {
  font-size: 14px; /* 缩小字体适配小高度 */
  color: #fff;
  background-color: red;
  padding: 0 10px; /* 紧凑内边距,不宽不高 */
  height: 100%;
  border-radius: 18px; /* 圆角和进度条一致,适配小高度 */
  font-weight: 600;
  white-space: nowrap;
  display: flex;
  align-items: center;
  justify-content: center;
  max-width: max-content;
}
    }
}
@@ -267,6 +505,19 @@
    background: #fff;
    border-radius: 0.266rem 0.266rem 0 0;
    padding-bottom: 0.53rem;
    .popup-header {
        background: #4a4a4a;
        color: #fff;
        padding: 0.3rem 0.53rem;
        display: flex;
        justify-content: space-between;
        font-size: 0.32rem;
        .header-left, .header-right {
            color: #fff;
        }
    }
    .boxh {
        height: 1.2rem;
@@ -278,76 +529,125 @@
        width: 9.48rem;
        margin: 0 auto;
        position: relative;
        display: flex;
        align-items: center;
        justify-content: center;
        span {
        .close-btn {
            position: absolute;
            width: 0.32rem;
            height: 0.32rem;
            background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAStJREFUSEutlk1qhDAUgF+EzG5EWsYTzK6HKO0hcgB3gscR3IgH8BBTeojuegJLQWg3NqDlyUQwRn0xcWeQ7zMv7ycMAKCu61PTNOcsy77x3fUpy/IhDMNfIcQfQ3jbtvUwDFfO+UuSJF8ugqqqLlLKN8bYZxRFguV5/sg5fweAJwD4cJEouGJJKZ8Z/m1RFHEQBDcXiQ7v+/41TdNmFLhK1uDInQRHJVvwhcBWsgc3CqgSCnxVsCehwjcFaxJcxzynZtzskE0Fpqfw/RtyzewKDDvBJXJBkgRazP0K9AP1GiIdjn2q6zpm01ZWQ2SCq05r07uMgi24be9aCChwG8lMYAOnSibBEThFMgpc4HsSryNTz65xZPoe+koyDX3cou9rC14k4jj+wWvLP1ylVM57GzhpAAAAAElFTkSuQmCC) no-repeat 50%;
            background-size: 100%;
            right: 0.266rem;
            top: 0.4rem;
            left: 0.266rem;
            width: 0.8rem;
            height: 0.8rem;
            font-size: 0.6rem;
            color: #999;
            line-height: 0.8rem;
            text-align: center;
            cursor: pointer;
        }
        h5 {
            color: #333;
            font-size: 0.43rem;
            font-weight: 500;
            margin: 0;
        }
    }
    h5 {
        color: #333;
        font-size: .37rem;
        font-weight: 500;
        width: 9.48rem;
        margin: 0 auto;
        margin-top: 0.32rem;
    .price-section {
        padding: 0.4rem 0.53rem 0;
    }
    h6 {
        color: #ea3544;
        font-size: .43rem;
        width: 9.48rem;
        margin: 0 auto;
        margin-top: 0.32rem;
        font-weight: 600;
    .quantity-section, .position-section {
        padding: 0.4rem 0.53rem 0;
        .section-label {
            display: block;
            color: #333;
            font-size: 0.35rem;
            margin-bottom: 0.2rem;
        }
    }
    .erty {
        width: 9.21rem;
        width: 100%;
        height: 1.07rem;
        border: 0.0266rem solid #999;
        border-radius: 0.13rem;
        margin: 0 auto;
        display: flex;
        justify-content: space-between;
        margin-top: 0.59rem;
        align-items: center;
        &.price-input {
            margin-top: 0;
        }
        .inpy {
            height: 1.07rem;
            width: 5.34rem;
            flex: 1;
            margin-left: 0.266rem;
            background: transparent;
            font-size: .37rem;
            color: #000;
            border: none;
            outline: none;
        }
        a {
            height: 0.64rem;
            border-left: 0.0266rem solid #999;
            width: 1.15rem;
            margin-top: 0.266rem;
            width: 1.5rem;
            margin-right: 0.266rem;
            text-align: center;
            font-size: .37rem;
            color: #000;
            font-size: .32rem;
            color: #666;
            line-height: .64rem;
            &.current-price-btn {
                color: #666;
                cursor: pointer;
            }
        }
    }
    .tghj {
        border: 0.0266rem solid #3b4fde;
        margin-top: 0.45rem;
    .position-buttons {
        display: flex;
        gap: 0.2rem;
        margin-top: 0.2rem;
        .position-btn {
            flex: 1;
            height: 0.8rem;
            border: 0.0266rem solid #999;
            border-radius: 0.13rem;
            text-align: center;
            line-height: 0.8rem;
            font-size: 0.32rem;
            color: #666;
            cursor: pointer;
            transition: all 0.3s;
            &.active {
                border-color: #3b4fde;
                background: rgba(59, 79, 222, 0.1);
                color: #3b4fde;
            }
        }
    }
    .amount-info {
        padding: 0.4rem 0.53rem 0;
    }
    .password-section {
        padding: 0.4rem 0.53rem 0;
    }
    .plm {
        width: 8.94rem;
        margin: 0 auto;
        margin-top: 0.266rem;
        width: 100%;
        margin: 0.2rem 0;
        display: flex;
        justify-content: space-between;
        span {
            color: #999;
@@ -355,8 +655,12 @@
        }
        a {
            color: #f33030;
            margin-left: 0.11rem;
            color: #333;
            font-size: .32rem;
            &.red-amount {
                color: #f33030;
            }
        }
    }
@@ -365,12 +669,12 @@
        height: 1.07rem;
        background: linear-gradient(-55deg,rgb(241, 22, 20),rgb(240, 40, 37));
        border-radius: 0.26rem;
        margin: 0 auto;
        margin-top: 0.56rem;
        margin: 0.4rem auto 0;
        text-align: center;
        line-height: 1.07rem;
        color: #fff;
        font-size: .37rem;
        cursor: pointer;
    }
}
</style>