feat: 会员中心 hgcloud 主题初始化 + drone 部署步骤
All checks were successful
continuous-integration/drone/push Build is passing

- 解压官方默认主题 default_yfMBA.tar.gz 到 clientarea/hgcloud/
- .gitignore 排除压缩包和临时解压目录
- drone 新增步骤: 同步 hgcloud 到 /clientarea/template/pc/
This commit is contained in:
yiqiu
2026-03-19 17:56:44 +08:00
parent 75756e5a64
commit 3b41cffbc9
381 changed files with 386825 additions and 1 deletions

View File

@@ -20,7 +20,8 @@ steps:
# 将主题配置插件同步到运行目录 # 将主题配置插件同步到运行目录
- cp -rf /www/wwwroot/hgdemo.hgidc.cn/public/web/BlackFruit-web/plugins/addon/theme_configurator /www/wwwroot/hgdemo.hgidc.cn/public/plugins/addon/ - cp -rf /www/wwwroot/hgdemo.hgidc.cn/public/web/BlackFruit-web/plugins/addon/theme_configurator /www/wwwroot/hgdemo.hgidc.cn/public/plugins/addon/
- ls -l # 将会员中心全局主题 hgcloud 同步到运行目录
- cp -rf /www/wwwroot/hgdemo.hgidc.cn/public/web/BlackFruit-web/clientarea/hgcloud /www/wwwroot/hgdemo.hgidc.cn/public/clientarea/template/pc/
- name: Restart Nginx - name: Restart Nginx
commands: commands:

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
clientarea/default_yfMBA.tar.gz
clientarea/default/

View File

@@ -0,0 +1,31 @@
{include file="header"}
<link rel="stylesheet" href="/{$template_catalog}/template/{$themes}/css/NotFound.css" />
</head>
<body>
<div class="template">
<el-container>
<aside-menu></aside-menu>
<el-container>
<top-menu></top-menu>
<el-main>
<!-- 自己的东西 -->
<div class="main-card">
<div class="content-box">
<div class="img-box">
<img src="/{$template_catalog}/template/{$themes}/img/common/404.png" alt="">
</div>
<div class="tips-box">
{{lang.status_text1}}
<p class="tran-again" @click="goBack">{{lang.status_text2}}</p>
</div>
</div>
</div>
</el-main>
</el-container>
</el-container>
</div>
<!-- =======页面独有======= -->
<script src="/{$template_catalog}/template/{$themes}/js/NotFound.js"></script>
{include file="footer"}

View File

@@ -0,0 +1,66 @@
<!DOCTYPE html>
<html lang="en" theme-color="default">
<?php $template_catalog='clientarea';$themes=configuration('clientarea_theme');?>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
<title></title>
<script>
const url = "/<?php echo $template_catalog?>/template/<?php echo $themes?>/"
</script>
<!-- 页面独有样式 -->
<link rel="stylesheet" href="/<?php echo $template_catalog?>/template/<?php echo $themes?>/css/common/element.css">
<script src="/<?php echo $template_catalog?>/template/<?php echo $themes?>/js/common/vue.js"></script>
<script src="/<?php echo $template_catalog?>/template/<?php echo $themes?>/js/common/element.js"></script>
<!-- 模板样式 -->
<link rel="stylesheet" href="/<?php echo $template_catalog?>/template/<?php echo $themes?>/css/common/common.css">
<link rel="stylesheet" href="/upload/common/iconfont/iconfont.css">
<script src="/<?php echo $template_catalog?>/template/<?php echo $themes?>/js/common/lang.js"></script>
<script src="/<?php echo $template_catalog?>/template/<?php echo $themes?>/js/common/common.js"></script>
<link rel="stylesheet" href="/<?php echo $template_catalog?>/template/<?php echo $themes?>/css/NotFound.css">
</head>
<body>
<div class="template">
<el-container>
<aside-menu></aside-menu>
<el-container>
<top-menu></top-menu>
<el-main>
<!-- 自己的东西 -->
<div class="main-card">
<div class="content-box">
<div class="img-box">
<img src="/<?php echo $template_catalog?>/template/<?php echo $themes?>/img/common/404.png" alt="">
</div>
<div class="tips-box">
{{lang.status_text1}}
<p class="tran-again" @click="goBack">{{lang.status_text2}}</p>
</div>
</div>
</div>
</el-main>
</el-container>
</el-container>
</div>
<!-- =======页面独有======= -->
<script src="/<?php echo $template_catalog?>/template/<?php echo $themes?>/js/NotFound.js"></script>
<script src="/<?php echo $template_catalog?>/template/<?php echo $themes?>/js/common/axios.min.js"></script>
<script src="/<?php echo $template_catalog?>/template/<?php echo $themes?>/utils/request.js"></script>
<script src="/<?php echo $template_catalog?>/template/<?php echo $themes?>/utils/util.js"></script>
<script src="/<?php echo $template_catalog?>/template/<?php echo $themes?>/api/common.js"></script>
<script
src="/<?php echo $template_catalog?>/template/<?php echo $themes?>/components/asideMenu/asideMenu.js"></script>
<script src="/<?php echo $template_catalog?>/template/<?php echo $themes?>/components/topMenu/topMenu.js"></script>
</body>
</html>

View File

@@ -0,0 +1,720 @@
{include file="header"}
<!-- 页面独有样式 -->
<link rel="stylesheet" href="/{$template_catalog}/template/{$themes}/css/account.css">
<link rel="stylesheet" href="/{$template_catalog}/template/{$themes}/css/certification.css">
</head>
<body>
<!-- mounted之前显示 -->
<div id="mainLoading">
<div class="ddr ddr1"></div>
<div class="ddr ddr2"></div>
<div class="ddr ddr3"></div>
<div class="ddr ddr4"></div>
<div class="ddr ddr5"></div>
</div>
<div id="account" class="template">
<el-container>
<aside-menu :menu-active-id="2" @getruleslist="getRule"></aside-menu>
<el-container>
<top-menu ref="topMenuRef"></top-menu>
<el-main>
<!-- 自己的东西 -->
<div class="main-card">
<div class="main-card-title">{{lang.account_title1}}</div>
<div class="content-box">
<el-tabs v-model="activeIndex" @tab-click="handleClick">
<el-tab-pane :label="lang.account_menu1" name="1" v-if="showAccountController">
<div class="box-top">
<div class="right-name">
<div>
<span class="name-text">{{userName}}
<span v-if="idcsmart_client_level.id"
:style="{'color':idcsmart_client_level.background_color}">({{idcsmart_client_level.name}})
</span>
</span>
<p class="name-country">
<img v-show="imgShow" class="country-img" :src="curSrc">
</p>
</div>
<div class="attestation-status" v-plugin="'IdcsmartCertification'"
v-show="attestationStatusInfo.iocnShow && certification_open == 1" @click="handelAttestation">
<img :src="attestationStatusInfo.iconUrl" alt="">
<!-- 企业认证关闭时 -->
<template v-if="attestationStatusInfo.certification_company_open === 0">
<span class="attestation-text"
v-if="attestationStatusInfo.status === 0">{{lang.account_tips20}}<span
class="bule-text">{{lang.account_tips21}}<i class="el-icon-arrow-right"></i></span></span>
<span class="attestation-text"
v-else-if="attestationStatusInfo.status === 10">{{lang.account_tips24}}</span></span>
</template>
<template v-else>
<span class="attestation-text"
v-if="attestationStatusInfo.status === 0 || attestationStatusInfo.status === 25">{{lang.account_tips20}}<span
class="bule-text">{{lang.account_tips21}}<i class="el-icon-arrow-right"></i></span></span>
<span class="attestation-text"
v-else-if="attestationStatusInfo.status === 10 || attestationStatusInfo.status === 26">{{lang.account_tips22}}<span
class="bule-text">{{lang.account_tips23}}<i class="el-icon-arrow-right"></i></span></span>
<span class="attestation-text"
v-else-if="attestationStatusInfo.status === 20 || attestationStatusInfo.status === 30 ">{{lang.account_tips24}}</span>
</template>
</div>
</div>
</div>
<div class="box-main">
<div class="basic">
<el-row>
<el-col :span="7">
<div class="basic-title">
{{lang.account_menu3}}
</div>
</el-col>
<el-col :span="7">
</el-col>
<el-col :span="7">
</el-col>
<el-col :span="3">
</el-col>
</el-row>
<el-row>
<el-col :span="7">
<div class="box-item">
<div class="box-item-t">{{lang.account_label1}}</div>
<div class="box-item-b">
<el-input v-model="accountData.username"></el-input>
</div>
</div>
</el-col>
<el-col :span="7">
<div class="box-item">
<div class="box-item-t">{{lang.account_label2}}</div>
<div class="box-item-b">
<el-select v-model="accountData.language" :disabled="commonData.lang_home_open == 0">
<el-option v-for="(item,index) in commonData.lang_list" :key="item.display_flag + index"
:value="item.display_lang" :label="item.display_name"></el-option>
</el-select>
</div>
</div>
</el-col>
<el-col :span="7">
<div class="box-item">
<div class="box-item-t">{{lang.account_tips_text9}}
<el-switch @change="noticeChange" v-model="accountData.notice_open" :active-value="1"
:inactive-value="0">
</el-switch>
</div>
<div class="box-item-b">
<el-select v-model="accountData.notice_method" :disabled="accountData.notice_open == 0">
<el-option value="all" :label="lang.account_tips_text12"></el-option>
<el-option value="email" :label="lang.account_tips_text11"></el-option>
<el-option value="sms" :label="lang.account_tips_text10"></el-option>
</el-select>
</div>
</div>
</el-col>
</el-row>
<el-row>
<el-col :span="7">
<div class="box-item">
<div class="box-item-t">{{lang.account_label3}}</div>
<div class="box-item-b">
<el-input v-model="accountData.company"></el-input>
</div>
</div>
</el-col>
<el-col :span="7">
<div class="box-item">
<div class="box-item-t">{{lang.account_label4}}</div>
<div class="box-item-b">
<el-select v-model="accountData.country_id" filterable>
<el-option v-for="item in countryList" :key="item.id" :value="item.id"
:label="item.name_zh">
</el-option>
</el-select>
</div>
</div>
</el-col>
<el-col :span="7">
<div class="box-item">
<div class="box-item-t">{{lang.account_label5}}</div>
<div class="box-item-b">
<el-input v-model="accountData.address"></el-input>
</div>
</div>
</el-col>
<el-col :span="3">
</el-col>
</el-row>
</div>
<div class="account">
<el-row>
<el-col :span="7">
<div class="account-title">
{{lang.account_menu4}}
</div>
</el-col>
<el-col :span="7">
</el-col>
<el-col :span="7">
</el-col>
<el-col :span="3">
</el-col>
</el-row>
<el-row>
<el-col :span="7">
<div class="box-item">
<div class="box-item-t">{{lang.account_label6}}</div>
<div class="box-item-b" @click.capture="showPhone">
<el-input :readonly="true" v-model="accountData.phone">
<i class="el-icon-edit edit-icon" slot="suffix"
v-if="!prohibit_user_information_changes.includes('phone') || orginAcountData.phone == ''"></i>
</el-input>
</div>
</div>
</el-col>
<el-col :span="7">
<div class="box-item">
<div class="box-item-t">{{lang.account_label7}}</div>
<div class="box-item-b" @click="showEmail">
<el-input :readonly="true" v-model="accountData.email">
<i class="el-icon-edit edit-icon" slot="suffix"
v-if="!prohibit_user_information_changes.includes('email') || orginAcountData.email == ''"></i>
</el-input>
</div>
</div>
</el-col>
<el-col :span=" 7">
<div class="box-item">
<div class="box-item-t">{{lang.account_label8}}</div>
<div class="box-item-b" @click="showPass">
<el-input :readonly="true" type="password" value="********">
<i class="el-icon-edit edit-icon" slot="suffix"
v-if="!prohibit_user_information_changes.includes('password') "></i>
</el-input>
</div>
</div>
</el-col>
<el-col :span="3">
</el-col>
</el-row>
<el-row>
<el-col :span=" 7">
<div class="box-item">
<div class="box-item-t">{{lang.account_tips_text3}}</div>
<div class="box-item-b" @click="openPreaDia">
<el-input :readonly="true" type="password"
:value="orginAcountData.set_operate_password ? '********' : '' ">
<i class="el-icon-edit edit-icon" slot="suffix"></i>
</el-input>
</div>
</div>
</el-col>
<el-col :span="7">
</el-col>
<el-col :span="7">
</el-col>
<el-col :span="3">
</el-col>
</el-row>
<el-form :model="ruleForm" ref="ruleForm" :rules="rules" label-position="top" class="custom-form"
v-plugin="'ClientCustomField'">
<div class="oauth-box">
<div class="box-item el-col el-col-7" v-for="item in clientCustomFieldList" :key="item.id"
@click="handleCustomField(Boolean(item.value && prohibit_user_information_changes.includes(item.id)))">
<el-form-item :prop="item.id + ''" style="margin-bottom: 0;">
<div class="box-item-t">{{item.name}}</div>
<div class="box-item-b">
<el-select v-model="ruleForm[item.id]" :placeholder="item.description"
v-if="item.type === 'dropdown'"
:disabled="Boolean(item.value && prohibit_user_information_changes.includes(item.id))">
<el-option :label="items" :value="items" v-for="(items,indexs) in item.options"
:key="indexs"></el-option>
</el-select>
<el-checkbox true-label="1" false-label="0" :label="item.name"
:disabled="Boolean(item.value && prohibit_user_information_changes.includes(item.id))"
v-model="ruleForm[item.id]" v-else-if="item.type === 'tickbox'">
{{item.description}}
</el-checkbox>
<el-input type="textarea" v-model="ruleForm[item.id]"
:readonly="Boolean(item.value && prohibit_user_information_changes.includes(item.id))"
v-else-if="item.type === 'textarea'" :placeholder="item.description">
</el-input>
<el-input class="input-with-select" :placeholder="item.description"
:readonly="Boolean(item.value && prohibit_user_information_changes.includes(item.id))"
v-model="ruleForm[item.id]" v-else-if="item.type === 'dropdown_text'">
<el-select v-model="item.select_select" slot="prepend" style="width: 1.3rem;"
:disabled="Boolean(item.value && prohibit_user_information_changes.includes(item.id))">
<el-option :label="items" :value="items" v-for="(items,indexs) in item.options"
:key="indexs"></el-option>
</el-select>
</el-input>
<el-input :show-password="item.type === 'password'" v-model="ruleForm[item.id]"
autocomplete="off"
:readonly="Boolean(item.value && prohibit_user_information_changes.includes(item.id))"
:placeholder="item.description" v-else>
</el-input>
</div>
</el-form-item>
</div>
</div>
</el-form>
</div>
<div class="oauth" v-if="oauth.length > 0">
<el-row>
<el-col :span="7">
<div class="account-title">
{{lang.oauth_text5}}
</div>
</el-col>
<el-col :span="7">
</el-col>
<el-col :span="7">
</el-col>
<el-col :span="3">
</el-col>
</el-row>
<div class="oauth-box">
<div class="box-item el-col el-col-7" v-for="item in oauth">
<div class="box-item-t">{{item.title}}</div>
<div class="box-item-b">
<el-input :disabled="true" v-model="item.showStatus">
<el-popconfirm v-if="item.link" :title="lang.oauth_text10" @confirm="cancelOauth(item)"
slot="suffix">
<span slot="reference" v-if="item.link" class="a-text bule-text">{{lang.oauth_text9}}
</span>
</el-popconfirm>
<span slot="suffix" class="a-text bule-text" @click="bingOauth(item)"
v-else>{{lang.oauth_text8}}</span>
</el-input>
</div>
</div>
</div>
</div>
<div class="oauth" v-if="hasWxPlugin && conectInfo.is_subscribe === 1">
<el-row>
<el-col :span="7">
<div class="account-title">
{{lang.wx_tip2}}
</div>
</el-col>
</el-row>
<div class="wx-switch">
<div class="box-item">
<div class="box-item-t">
{{lang.wx_tip3}}
<el-switch @change="changeWxPush" v-model="conectInfo.accept_push" :active-value="1"
:inactive-value="0">
</el-switch>
</div>
</div>
</div>
</div>
<el-button class="btn-save" @click="saveAccount" type="primary"
:loading="saveLoading">{{lang.account_btn1}}</el-button>
</div>
</el-tab-pane>
<!-- 操作日志开始 -->
<el-tab-pane :label="lang.account_menu2" name="2" v-if="showLogController">
<div class="searchbar com-search">
<el-input v-model="params.keywords" style="width: 3.2rem;margin-left: .2rem;"
:placeholder="lang.cloud_tip_2" @keypress.enter.native="inputChange" clearable
@clear="getAccountList">
<i class="el-icon-search input-search" slot="suffix" @Click="inputChange"></i>
</el-input>
</div>
<div class="content_table">
<div class="tabledata">
<el-table v-loading="loading" :data="dataList" style="width: 100%;margin-bottom: .2rem;">
<el-table-column prop="id" label="ID" width="120" align="left">
</el-table-column>
<el-table-column prop="description" min-width="650" :show-overflow-tooltip="true"
:label="lang.account_label9" align="left">
</el-table-column>
<el-table-column prop="create_time" :label="lang.account_label10" min-width="200" align="left">
<template slot-scope="scope">
<span>{{scope.row.create_time | formateTime}}</span>
</template>
</el-table-column>
<el-table-column prop="ip" label="IP" width="150" align="left"></el-table-column>
</el-table>
<pagination :page-data="params" @sizechange="sizeChange" @currentchange="currentChange"
layout="sizes, jumper" :show-custom-buttons="true" :cur-page-length="dataList.length"
v-if="params.total > 0">
</pagination>
</div>
</div>
<!-- 移动端显示表格开始 -->
<div class="mobel">
<div class="mob-searchbar mob-com-search">
<el-input class="mob-search-input" v-model="params.keywords" :placeholder="lang.cloud_tip_2"
@keypress.enter.native="inputChange" clearable @clear="getAccountList">
<i class="el-icon-search input-search" slot="suffix" @Click="inputChange"></i>
</el-input>
</div>
<div class="mob-tabledata">
<div class="mob-tabledata-item" v-for="item in dataList" :key="item.id">
<div class="mob-item-row mob-item-row1">
<span>{{item.id}}</span>
<span>
{{item.ip}}
</span>
</div>
<div class="mob-item-row mob-item-row2">
<span class="mob-item-row2-name" :title="item.description">
{{item.description}}
</span>
</div>
<div class="mob-item-row mob-item-row3">
<span>{{item.create_time | formateTime}}</span>
<div>
</div>
</div>
</div>
</div>
<div class="bottom-text">
<span v-show="isEnd">{{lang.account_tips15}}</span>
<span v-loading=isShowMore></span>
</div>
<img v-show="isShowBackTop" class="back-top-img" @click="goBackTop"
src="/{$template_catalog}/template/{$themes}/img/common/toTop.png">
</div>
</el-tab-pane>
<el-tab-pane :label="lang.subaccount_text56" name="3" v-if="havePlugin('ClientCare')">
<div class="searchbar msg-search">
<div class="msgsearch-left">
<el-button @click="handelDelMsg">{{lang.subaccount_text61}}</el-button>
<el-button @click="handelReadMsg">{{lang.subaccount_text62}}</el-button>
<el-button @click="handelReadAllMsg">{{lang.subaccount_text63}}</el-button>
</div>
<div class="msgsearch-right">
<el-select v-model="msgParams.read" clearable :placeholder="lang.placeholder_pre2">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
<el-select v-model="msgParams.type" clearable :placeholder="lang.placeholder_pre2">
<el-option v-for="item in msgTypeOptions" :key="item.name" :label="item.name_lang"
:value="item.name">
</el-option>
</el-select>
<el-input v-model="msgParams.keywords" style="width: 3.2rem;" :placeholder="lang.cloud_tip_2"
@keypress.enter.native="msgInputChange" clearable @clear="clearKey">
</el-input>
<el-button class="search-btn" @click="msgInputChange">{{lang.subaccount_text64}}</el-button>
</div>
</div>
<div class="content_table">
<div class="tabledata">
<el-table v-loading="msgLoading" @selection-change="handleSelectionChange" :data="msgDataList"
style="width: 100%;margin-bottom: .2rem;">
<el-table-column type="selection" width="90"></el-table-column>
<el-table-column :label="lang.subaccount_text58">
<template slot-scope="scope">
<span @click="goMsgDetail(scope.row.id)">
<span class="msg-status"
:class="scope.row.read === 1 ? 'is-read' : 'no-read'">{{scope.row.read === 1 ?
lang.subaccount_text66 : lang.subaccount_text67}}</span>
<span class="a-text">{{ scope.row.title }}</span>
</span>
</template>
</el-table-column>
<el-table-column :label="lang.subaccount_text59" width="200" align="left">
<template slot-scope="scope">
<span>{{scope.row.create_time | formateTime}}</span>
</template>
</el-table-column>
<el-table-column :label="lang.subaccount_text60" width="200">
<template slot-scope="scope">{{ msgType[scope.row.type] }}</template>
</el-table-column>
</el-table>
<pagination :page-data="msgParams" @sizechange="msgSizeChange" @currentchange="msgCurrentChange">
</pagination>
</div>
</div>
</el-tab-pane>
</el-tabs>
</div>
</div>
<!-- 更改密码弹框 -->
<div class="edit-pass">
<el-dialog width="6.8rem" :visible.sync="isShowPass" :show-close=false :close-on-click-modal=false>
<div class="dialog-title">
{{lang.account_title2}}
</div>
<div class="mian-form">
<el-form :model="passData" label-position="top">
<el-form-item :label="lang.account_label11">
<el-input type="password" v-model="passData.old_password" :placeholder="lang.account_tips1">
</el-input>
<span class="forget-pass">{{lang.account_tips4}} <a @click="showCodePass">{{lang.account_tips5}}</a>
</span>
</el-form-item>
<el-form-item :label="lang.account_label12">
<el-input type="password" v-model="passData.new_password" :placeholder="lang.account_tips2">
</el-input>
</el-form-item>
<el-form-item :label="lang.account_label13">
<el-input type="password" v-model="passData.repassword" :placeholder="lang.account_tips3">
</el-input>
</el-form-item>
<el-form-item v-show="errorText">
<el-alert show-icon :title="errorText" type="error" :closable="false"></el-alert>
</el-form-item>
</el-form>
</div>
<div class="dialog-footer">
<el-button class="btn-ok" @click="doPassEdit">{{lang.account_btn2}}</el-button>
<el-button class="btn-no" @click="isShowPass= false">{{lang.account_btn3}}</el-button>
</div>
</el-dialog>
</div>
<!-- 更改操作密码弹窗 -->
<div class="edit-pass">
<el-dialog width="6.8rem" :visible.sync="isShowPeratedia" :show-close=false :close-on-click-modal=false>
<div class="dialog-title">
{{orginAcountData.set_operate_password ? lang.account_tips_text4 : lang.account_tips_text5}}
</div>
<div class="mian-form">
<el-form :model="operateData" label-position="top" :rules="operaRules" ref="operaForm"
hide-required-asterisk>
<el-form-item :label="lang.account_label12" prop="operate_password">
<el-input type="password" v-model="operateData.operate_password" autocomplete="off"
:placeholder="lang.account_tips2">
</el-input>
</el-form-item>
<div class="form-tips" style="color: var(--color-text-tips); font-size: 0.14rem;">
<span style="color:var(--color-danger); margin-right: 4px;">*</span>{{lang.account_tips_text8}}
</div>
<el-form-item :label="lang.account_label13" prop="re_operate_password">
<el-input type="password" autocomplete="off" v-model="operateData.re_operate_password"
:placeholder="lang.account_tips3">
</el-input>
</el-form-item>
</el-form>
</div>
<div class="dialog-footer">
<el-button class="btn-ok" @click="surePerate" :loading="subLoading">{{lang.account_btn2}}</el-button>
<el-button class="btn-no" @click="closePerate">{{lang.account_btn3}}</el-button>
</div>
</el-dialog>
</div>
<!-- 验证码更改密码弹框 -->
<div class="edit-pass">
<el-dialog width="6.8rem" :visible.sync="isShowCodePass" :show-close=false :close-on-click-modal=false>
<div class="dialog-title">
{{lang.account_title2}}
</div>
<div class="login-top">
<div class="login-email" :class="isEmailOrPhone? 'active':null" @click="isEmailOrPhone = true">
{{lang.account_label14}}
</div>
<div class="login-phone" :class="!isEmailOrPhone? 'active':null" @click="isEmailOrPhone = false">
{{lang.account_label15}}
</div>
</div>
<div class="form-main">
<div class="form-item">
<el-input v-if="isEmailOrPhone" :disabled="true" v-model="formData.email"
:placeholder="lang.account_tips6">
</el-input>
<el-input v-else class="input-with-select" :disabled="true" v-model="formData.phone"
:placeholder="lang.account_tips7">
<el-select class="code-pass-select" :disabled="true" filterable slot="prepend"
v-model="formData.countryCode">
<el-option v-for="item in countryList" :key="item.name" :value="item.phone_code"
:label="'+' + item.phone_code">
+{{item.phone_code}} {{item.name_zh}}
</el-option>
</el-select>
</el-input>
</div>
<div class="form-item code-item">
<!-- 邮箱验证码 -->
<el-input v-if="isEmailOrPhone" v-model="formData.emailCode" :placeholder="lang.account_tips8">
</el-input>
<count-down-button ref="codeEmailCodebtn" @click.native="sendEmailCode('code')" v-if="isEmailOrPhone"
my-class="code-btn"></count-down-button>
<!-- <el-button v-if="isEmailOrPhone" class="code-btn" type="primary">获取验证码</el-button> -->
<!-- 手机验证码 -->
<el-input v-if="!isEmailOrPhone" v-model="formData.phoneCode" :placeholder="lang.account_tips9">
</el-input>
<count-down-button ref="codePhoneCodebtn" @click.native="sendPhoneCode('code')" v-if="!isEmailOrPhone"
my-class="code-btn"></count-down-button>
<!-- <el-button v-if="!isEmailOrPhone" class="code-btn" type="primary">获取验证码</el-button> -->
</div>
<div class="form-item">
<el-input :placeholder="lang.tip1" v-model="formData.password" type="password">
</el-input>
</div>
<div class="form-item">
<el-input :placeholder="lang.tip2" v-model="formData.repassword" type="password">
</el-input>
</div>
<div class="read-item" v-if="errorText">
<el-alert :title="errorText" type="error" show-icon :closable="false">
</el-alert>
</div>
<div class="form-item dialog-footer">
<el-button class="btn-ok" @click="doResetPass">{{lang.account_btn2}}</el-button>
<el-button class="btn-no" @click="quiteCodePass">{{lang.account_btn3}}</el-button>
</div>
</div>
</el-dialog>
</div>
<!-- 验证手机号弹框 -->
<div class="check-phone">
<el-dialog width="6.8rem" :visible.sync="isShowPhone" :show-close=false :close-on-click-modal=false>
<div class="dialog-title">
{{lang.account_title3}}
</div>
<div class="mian-form">
<el-form :model="phoneData" label-position="top">
<el-form-item :label="lang.account_label15">
<el-input :disabled="true" v-model="phoneData.phone"
:placeholder="lang.account_tips10 +accountData.phone+ lang.account_tips11"></el-input>
</el-form-item>
<el-form-item :label="lang.account_label16">
<div class="input-btn">
<el-input v-model="phoneData.code">
</el-input>
<count-down-button ref="phoneCodebtn" @click.native="sendPhoneCode('old')" my-class="code-btn"
slot="append"></count-down-button>
</div>
</el-form-item>
<el-form-item v-show="errorText">
<el-alert show-icon :title="errorText" type="error" :closable="false"></el-alert>
</el-form-item>
</el-form>
</div>
<div class="dialog-footer">
<el-button class="btn-ok" @click="doPhoneEdit">{{lang.account_btn4}}</el-button>
<el-button class="btn-no" @click="isShowPhone= false">{{lang.account_btn3}}</el-button>
</div>
</el-dialog>
</div>
<!-- 修改手机号弹框 -->
<div class="check-phone">
<el-dialog width="6.8rem" :visible.sync="isShowRePhone" :show-close=false :close-on-click-modal=false>
<div class="dialog-title">
{{accountData.phone?lang.account_title4 : lang.account_title5}}
</div>
<div class="mian-form">
<el-form :model="rePhoneData" label-position="top">
<el-form-item :label="lang.account_label15">
<el-input v-model="rePhoneData.phone" :placeholder="lang.account_tips16">
<el-select class="select-input" filterable slot="prepend" v-model="rePhoneData.countryCode">
<el-option v-for="item in countryList" :key="item.name" :value="item.phone_code"
:label="item.name_zh + '+' + item.phone_code"></el-option>
</el-select>
</el-input>
</el-form-item>
<el-form-item :label="lang.account_label16">
<div class="input-btn">
<el-input v-model="rePhoneData.code">
</el-input>
<count-down-button ref="rePhoneCodebtn" @click.native="sendPhoneCode('new')" my-class="code-btn"
slot="append"></count-down-button>
</div>
</el-form-item>
<el-form-item v-show="errorText">
<el-alert show-icon :title="errorText" type="error" :closable="false"></el-alert>
</el-form-item>
</el-form>
</div>
<div class="dialog-footer">
<el-button class="btn-ok" @click="doRePhoneEdit">{{lang.account_btn4}}</el-button>
<el-button class="btn-no" @click="isShowRePhone= false">{{lang.account_btn3}}</el-button>
</div>
</el-dialog>
</div>
<!-- 验证邮箱弹框 -->
<div class="check-phone">
<el-dialog width="6.8rem" :visible.sync="isShowEmail" :show-close=false :close-on-click-modal=false>
<div class="dialog-title">
{{lang.account_title6}}
</div>
<div class="mian-form">
<el-form :model="emailData" label-position="top">
<el-form-item :label="lang.account_label7">
<el-input :disabled="true" v-model="emailData.email"
:placeholder="lang.account_tips17 +accountData.email+ lang.account_tips18"></el-input>
</el-form-item>
<el-form-item :label="lang.account_label16">
<div class="input-btn">
<el-input v-model="emailData.code">
</el-input>
<count-down-button ref="emailCodebtn" @click.native="sendEmailCode('old')" my-class="code-btn"
slot="append"></count-down-button>
</div>
</el-form-item>
<el-form-item v-show="errorText">
<el-alert show-icon :title="errorText" type="error" :closable="false"></el-alert>
</el-form-item>
</el-form>
</div>
<div class="dialog-footer">
<el-button class="btn-ok" @click="doEmailEdit">{{lang.account_btn4}}</el-button>
<el-button class="btn-no" @click="isShowEmail= false">{{lang.account_btn3}}</el-button>
</div>
</el-dialog>
</div>
<!-- 修改邮箱弹框 -->
<div class="check-phone">
<el-dialog width="6.8rem" :visible.sync="isShowReEmail" :show-close=false :close-on-click-modal=false>
<div class="dialog-title">
{{accountData.email? lang.account_title7 : lang.account_title8}}
</div>
<div class="mian-form">
<el-form :model="reEmailData" label-position="top">
<el-form-item :label="lang.account_label7">
<el-input v-model="reEmailData.email" :placeholder="lang.account_tips19"></el-input>
</el-form-item>
<el-form-item :label="lang.account_label16">
<div class="input-btn">
<el-input v-model="reEmailData.code">
</el-input>
<count-down-button ref="reEmailCodebtn" @click.native="sendEmailCode('new')" my-class="code-btn"
slot="append"></count-down-button>
</div>
</el-form-item>
<el-form-item v-show="errorText">
<el-alert show-icon :title="errorText" type="error" :closable="false"></el-alert>
</el-form-item>
</el-form>
</div>
<div class="dialog-footer">
<el-button class="btn-ok" @click="doReEmailEdit">{{lang.account_btn4}}</el-button>
<el-button class="btn-no" @click="isShowReEmail= false">{{lang.account_btn3}}</el-button>
</div>
</el-dialog>
</div>
<!-- 安全验证 -->
<security-verification ref="securityRef" @confirm="hadelSecurityConfirm"
:action-type="actionType"></security-verification>
<!-- 验证码 -->
<captcha-dialog :is-show-captcha="isShowCaptcha" ref="captcha" captcha-id="account-captcha"
@get-captcha-data="getData" @captcha-cancel="captchaCancel"></captcha-dialog>
</el-main>
</el-container>
</el-container>
</div>
<!-- =======页面独有======= -->
<script src="/{$template_catalog}/template/{$themes}/js/common/jquery.mini.js"></script>
<script src="/{$template_catalog}/template/{$themes}/api/account.js"></script>
<script src="/{$template_catalog}/template/{$themes}/api/certification.js"></script>
<script src="/{$template_catalog}/template/{$themes}/components/captchaDialog/captchaDialog.js"></script>
<script src="/{$template_catalog}/template/{$themes}/components/countDownButton/countDownButton.js"></script>
<script
src="/{$template_catalog}/template/{$themes}/components/securityVerification/securityVerification.js"></script>
<script src="/{$template_catalog}/template/{$themes}/components/pagination/pagination.js"></script>
<script src="/{$template_catalog}/template/{$themes}/js/account.js"></script>
{include file="footer"}

View File

@@ -0,0 +1,49 @@
{include file="header"}
<link rel="stylesheet" href="/{$template_catalog}/template/{$themes}/css/agreement.css">
</head>
<body>
<div id="mainLoading">
<div class="ddr ddr1"></div>
<div class="ddr ddr2"></div>
<div class="ddr ddr3"></div>
<div class="ddr ddr4"></div>
<div class="ddr ddr5"></div>
</div>
<div id="content" class="template">
<div class="contnet-right-out">
<div class="content-right" v-show="detailData.id" v-loading="contentLoading">
<!-- 标题 -->
<div class="right-title">
{{detailData.title}}
</div>
<!-- 更新时间 -->
<div class="right-keywords-time">
<div class="right-time">
{{lang.agreement_text1}}{{detailData.create_time | formateTime}}
</div>
<div class="right-keywords">
{{lang.agreement_text2}}{{detailData.keywords || '--'}}
</div>
</div>
<!-- 主体内容 -->
<div class="right-content" v-html="calStr(detailData.content)">
</div>
<!-- 附件 -->
<div class="right-attachment">
{{lang.agreement_text3}}
<div class="right-attachment-item" v-for="(f,i) in detailData.attachment" :key="i"
@click="downloadfile(f.url)">
<span :title="f.name">
<i class="el-icon-tickets"></i><span>{{f.name}}</span>
</span>
</div>
</div>
</div>
</div>
</div>
<script src="/{$template_catalog}/template/{$themes}/js/agreement.js"></script>
{include file="footer"}

View File

@@ -0,0 +1,88 @@
// 获取国家列表
function getCountry (params) {
return Axios.get(`/country`, params);
}
// 账户详情
function account () {
return Axios.get(`/account`);
}
// 获取国家列表
function country (params) {
return Axios.get(`/country`, { params });
}
// 编辑账户
function updateAccount (params) {
return Axios.put(`/account`, params);
}
// 修改密码
function updatePassword (params) {
return Axios.put(`/account/password`, params);
}
// 忘记密码
function forgetPass (params) {
return Axios.post("/account/password_reset", params);
}
// 发送手机验证码
function phoneCode (params) {
return Axios.post(`/phone/code`, params);
}
// 发送邮箱验证码
function emailCode (params) {
return Axios.post(`/email/code`, params);
}
// 验证原手机
function verifiedPhone (params) {
return Axios.put(`/account/phone/old`, params);
}
// 修改手机
function updatePhone (params) {
return Axios.put(`/account/phone`, params);
}
// 验证原邮箱
function verifiedEmail (params) {
return Axios.put(`/account/email/old`, params);
}
// 修改邮箱
function updateEmail (params) {
return Axios.put(`/account/email`, params);
}
// 阿里云修改邮箱
function updateAliEmail (params) {
return Axios.put(`/aliyun_agency/account/email`, params);
}
// 操作日志
function getLog (params) {
return Axios.get(`/log`, { params });
}
// 取消关联
function cancelOauth (name) {
return Axios.post(`/oauth/unbind/${name}`);
}
// 获取用户自定义字段和值
function clientCustomFieldValue () {
return Axios.get(`/client_custom_field_value`);
}
// 修改操作密码
function updateOperationPassword (params) {
return Axios.put(`/account/operate_password`, params);
}
// 获取微信公众号用户关联信息
function getWxInfo () {
return Axios.get(`/mp_weixin_notice/client`);
}
// 修改允许推送
function changePushStatus (params) {
return Axios.put(`/mp_weixin_notice/accept_push`, params);
}

View File

@@ -0,0 +1,34 @@
// 获取实名认证信息
function certificationInfo() {
return Axios.get(`/certification/info`)
}
// 获取实名认证方式
function certificationPlugin() {
return Axios.get(`/certification/plugin`)
}
//获取实名认证自定义字段
function custom_fields(params) {
return Axios.get(`/certification/custom_fields`, { params })
}
// 个人认证
function uploadPerson(params) {
return Axios.post(`/certification/person`, params)
}
// 实名认证验证页面
function certificationAuth() {
return Axios.get(`/certification/auth`)
}
// 获取系统状态
function certificationStatus() {
return Axios.get(`certification/status`)
}
//企业认证
function uploadCompany(params) {
return Axios.post(`/certification/company`, params)
}

View File

@@ -0,0 +1,530 @@
/* 通用接口API */
// 获取国家列表
function getCountry(params) {
return Axios.get(`/country`, params);
}
// 获取支付接口
function getPayList() {
return Axios.get("/gateway");
}
// 获取公共配置
function getCommon(params) {
return Axios.get("/common", { params });
}
// 获取登录信息
function getLoginInfo() {
return Axios.get("/login");
}
// 获取图形验证码
function getNewCaptcha() {
return Axios.get("/captcha");
}
// 编辑账户
function updateAccount(params) {
return Axios.put(`/account`, params);
}
// 验证图形验证码
function checkCaptcha(params) {
return Axios.post("/captcha", params);
}
// 注册
function regist(params) {
return Axios.post("/register", params);
}
// 注册页面获取用户自定义字段
function registCustomField() {
return Axios.get("/register/custom_field");
}
// 登录
function logIn(params) {
return Axios.post("/login", params);
}
// 忘记密码
function forgetPass(params) {
return Axios.post("/account/password_reset", params);
}
// 退出登录
function logout() {
return Axios.post("/logout");
}
// 获取权限
function getAuthRole() {
return Axios.get("/auth");
}
// 发送短信验证码
function phoneCode(params) {
return Axios.post("/phone/code", params);
}
// 获取邮箱验证码
function emailCode(params) {
return Axios.post("/email/code", params);
}
// 全局搜索
function globalSearch(params) {
return Axios.get("/global_search", { params });
}
// 获取前台导航
function getMenu() {
return Axios.get("/menu");
}
/* 停用相关 */
// 获取停用页面
function refundPage(params) {
return Axios.get(`/refund`, { params });
}
// 申请停用
function refund(params) {
return Axios.post(`/refund`, params);
}
// 取消停用
function cancel(params) {
return Axios.put(`/refund/${params.id}/cancel`, params);
}
// 获取产品停用信息
function refundMsg(params) {
return Axios.get(`/refund/host/${params.id}/refund`, { params });
}
// 账户详情
function account() {
return Axios.get(`/account`);
}
// 支付方式
function gatewayList() {
return Axios.get(`/gateway`);
}
// 支付
function pay(params) {
return Axios.post(`/pay`, params);
}
// 支付状态
function getPayStatus(id) {
return Axios.get(`/pay/${id}/status`);
}
// 使用/取消余额
function creditPay(params) {
return Axios.post(`/credit`, params);
}
// 订单详情
function orderDetails(id) {
return Axios.get(`/order/${id}`);
}
/* 续费相关 */
// 续费页面
function renewPage(params) {
return Axios.get(`/host/${params.id}/renew`, { params });
}
// 续费提交
function renew(params) {
return Axios.post(`/host/${params.id}/renew`, params);
}
// 商品列表
function productList(params) {
return Axios.get(`/product`, { params });
}
// 商品详情
function productInfo(id) {
return Axios.get(`/product/${id}`);
}
// 获取购物车
function cartList() {
return Axios.get(`/cart`);
}
// 会员中心首页
function indexData() {
return Axios.get(`/index`);
}
// 应用优惠码
function applyPromoCode(params) {
return Axios.post(`/promo_code/apply`, params);
}
// 获取提现设置
function withdrawConfig(params) {
return Axios.get(`/withdraw/rule/credit`, { params });
}
// 申请提现
function applyWithdraw(params) {
return Axios.post(`/withdraw`, params);
}
// 账户详情
function accountDetail() {
return Axios.get(`/account`);
}
// 账户权限
function accountPermissions(id) {
return Axios.get(`/sub_account/${id}/auth`);
}
/**
* @获取在线客服代码
*/
function queryCustomerServiceCode(id) {
return Axios.get(`/online_service`);
}
// 获取实名认证信息
function certificationInfo() {
return Axios.get(`/certification/info`);
}
// 帮助文档详情
function helpDetails(params) {
return Axios.get(`/help/${params.id}`, { params });
}
// 获取返现信息
function getCashbackInfo(params) {
return Axios.get(`/host/${params.id}/product_cashback`);
}
// 申请返现
function apllyCashback(params) {
return Axios.post(`/host/${params.id}/product_cashback`);
}
// 授信详情
function creditDetail() {
return Axios.get(`/credit_limit`);
}
// 信用额支付
function payCreditLimit(params) {
return Axios.post(`/credit_limit/pay`, params);
}
// 流量包列表
function getFlowPacket(params) {
return Axios.get(`/host/${params.id}/flow_packet`, { params });
}
// 根据模块获取流量包
function getFlowPacketByModule(module, params) {
return Axios.get(`/${module}/${params.id}/traffic_package`, { params });
}
// 订购流量包
function buyFlowPacket(params) {
return Axios.post(`/host/${params.id}/flow_packet_order`, params);
}
// 站内信
function messageInfo() {
return Axios.get(`/client_care/mail`);
}
// 站内信列表
function messageList(params) {
return Axios.get(`/client_care/mail/list`, { params });
}
// 删除站内信
function deleteMessage(params) {
return Axios.delete(`/client_care/mail`, { params });
}
// 标记已读站内信
function readMessage(params) {
return Axios.put(`/client_care/mail/read`, params);
}
// 验证oauthtoken
function oauthToken() {
return Axios.get(`/oauth/token`);
}
// 关联账户
function bindOauthAccount(params) {
return Axios.post(`/oauth/client/bind`, params);
}
//跳转到登录授权网址
function oauthUrl(name) {
return Axios.get(`/oauth/${name}`);
}
// 获取商品活动促销信息
function eventPromotion(params) {
return Axios.get(`/event_promotion/product/${params.id}/event_promotion`, {
params,
});
}
// 应用活动促销
function applyEventPromotion(params) {
return Axios.post(`/event_promotion/apply`, params);
}
// 商品订单页自定义字段
function customFieldsProduct(id) {
return Axios.get(`/product/${id}/self_defined_field/order_page`);
}
// 批量续费页面
function batchRenewList(params) {
return Axios.get(`/host/renew/batch`, { params });
}
// 批量续费
function aipBatchRenew(params) {
return Axios.post(`/host/renew/batch`, params);
}
// 产品IP详情
function getHostIpDetails(id) {
return Axios.get(`/host/${id}/ip`);
}
// 批量操作
function batchOperation(module, params) {
return Axios.post(`/${module}/batch_operate`, params);
}
// 银行转账提交申请
function submitApplication(id) {
return Axios.post(`/order/${id}/submit_application`);
}
// 上传凭证
function uploadProof(params) {
return Axios.put(`/order/${params.id}/voucher`, params);
}
// 变更支付方式
function changePayType(id) {
return Axios.put(`/order/${id}/gateway`);
}
// 产品是否正在转移
function hostIsTransfer(params) {
return Axios.get(`/host_transfer/host/${params.id}/is_transfer`);
}
// 自动续费开关
function rennewAuto(params) {
return Axios.put(`/host/${params.id}/renew/auto`, params);
}
// 产品列表获取产品详情-用于自动续费显示
function getHostSpecific(params) {
return Axios.get(`/host/${params.id}/specific_info`);
}
// 获取升级防御配置
function apiGetUpDefenceConfig(params, module) {
return Axios.get(`/${module}/${params.id}/upgrade_defence_config`, {
params,
});
}
// 计算升级防御价格
function apiCalculateUpDefencePrice(params, module) {
return Axios.get(`/${module}/${params.id}/upgrade_defence/price`, {
params,
});
}
// 生成升级防御订单
function apiGenerateUpDefenceOrder(params, module) {
return Axios.post(`/${module}/${params.id}/upgrade_defence/order`, params);
}
// 防火墙用户统计(首页产品列表)
function apiProductGetHostIp(params, module) {
switch (module) {
case "mf_cloud":
case "mf_dcim":
case "mf_dcim_cabinet":
return Axios.get(`/aodun_firewall/host_ip`, { params });
case "remf_cloud":
case "remf_dcim":
return Axios.get(`/aodun_firewall_agent/host_ip`, { params });
}
}
// 防火墙用户统计刷新状态(首页产品列表)
function apiProductRefreshHostIpStatus(params, module) {
switch (module) {
case "mf_cloud":
case "mf_dcim":
case "mf_dcim_cabinet":
return Axios.get(`/aodun_firewall/host_ip/${params.id}/refresh_status`, {
params,
});
case "remf_cloud":
case "remf_dcim":
return Axios.get(
`/aodun_firewall_agent/host_ip/${params.id}/refresh_status`,
{
params,
}
);
}
}
// 用户流量预警详情
function getTrafficWarning(params) {
return Axios.get(`/account/traffic_warning`, { params });
}
// 保存用户流量预警
function saveTrafficWarning(params) {
return Axios.put(`/account/traffic_warning`, params);
}
// 获取微信二维码
function apiGetWeixinQrCode(params) {
return Axios.get(`/mp_weixin_notice/qrcode`, { params });
}
// 获取二维码状态
function apiGetQrCodeStatus(params) {
return Axios.get(`/mp_weixin_notice/qrcode/status`, { params });
}
// 关联账户
function apiBindWxAccount(params) {
return Axios.post(`/mp_weixin_notice/qrcode/bind_client`, params);
}
// 选择用户登录
function apiSelectClientLogin(params) {
return Axios.post(`/mp_weixin_notice/qrcode/select_client_login`, params);
}
// 充值
function apiRecharge(params) {
return Axios.post(`/recharge`, params);
}
// 用户可用平台币详情
function apiCoinClientCoupon(params) {
return Axios.get(`/coin/client/coupon`, { params });
}
// 平台币充值页面详情
function apiCoinRechargeDetail(params) {
return Axios.get(`/coin/recharge`, { params });
}
// 应用平台币
function apiApplyCoin(params) {
return Axios.post(`/coin/pay`, params);
}
// 支付页面可用平台币列表
function apiCoinPayList(params) {
return Axios.get(`/coin/pay`, { params });
}
// 余额提醒
function apiCreateCreditRemind(params) {
return Axios.post(`/account/credit/remind`, params);
}
// 平台币发放规则列表
function apiCoinActiveList(params) {
return Axios.get(`/coin/rules`, { params });
}
// 续费页面
function getRenewApi(params) {
return Axios.get(`/host/${params.id}/renew`, { params });
}
// 续费提交
function apiRenew(params) {
return Axios.post(`/host/${params.id}/renew`, params);
}
// 获取产品按需转包年包月周期价格
function apiGetDemandToPrepaymentPrice(params) {
return Axios.get(`/host/${params.id}/on_demand_to_recurring_prepayment`);
}
// 产品按需转包年包月
function apiDemandToPrepayment(params) {
return Axios.post(
`/host/${params.id}/on_demand_to_recurring_prepayment`,
params
);
}
// 获取用户等级折扣金额
function apiClientLevelAmount(params) {
return Axios.get(`/client_level/product/${params.id}/amount`, { params });
}
/* 重置授权 */
// 提交授权重置申请
function apiRestAuth(params) {
return Axios.post(`/authreset/applications`, params);
}
// 获取实名信息
function apiGetRealName(params) {
return Axios.get(`/authreset/certificate`, { params });
}
// 获取实名状态
function apiGetRealNameStatus(params) {
return Axios.get(`/authreset/certificate/status`, { params });
}
// 自助重置确认
function apiAutoResetSure(params) {
return Axios.post(`/authreset/reset/sure`, params);
}
// 撤销重置
function apiCancelRest(params) {
return Axios.post(`/authreset/reset/cancel`, params);
}
// 批量续费使用优惠码
function applyBatchRenewCode(params) {
return Axios.post(`/promo_code/apply_batch`, params);
}
// 修改语言
function changeLanguage(params) {
return Axios.put(`/language`, params);
}
// 异常登录创建实名认证
function apiCreateCertification(params) {
return Axios.post(`/login/exception/certification/create`, params);
}
// 异常登录查询实名认证状态
function apiGetCertificationStatus(params) {
return Axios.get(`/login/exception/certification/status`, { params });
}
// 前台产品列表(跨模块)
function apiCrossModuleList(params) {
return Axios.get(`/home/host`, { params });
}
// 支付页面可用代金券列表
function apiVoucherPayList(params) {
return Axios.get(`/voucher/pay`, { params });
}
// 应用代金券
function apiApplyVoucher(params) {
return Axios.post(`/voucher/pay`, params);
}
// 批量修改产品备注
function apiBatchUpdateHostNotes(params) {
return Axios.put(`/host/notes/batch`, params);
}

View File

@@ -0,0 +1,202 @@
// 订单列表
function orderList(params) {
return Axios.get("/order", {params});
}
// 交易记录列表
function transactionList(params) {
return Axios.get(`/transaction`, {params});
}
// 订单详情
function orderDetails(id) {
return Axios.get(`/order/${id}`);
}
// 余额记录列表
function creditList(params) {
return Axios.get(`/credit`, {params});
}
// 公共配置
function common() {
return Axios.get(`/common`);
}
// 账户详情
function account() {
return Axios.get(`/account`);
}
// 提现申请
function withdraw(params) {
return Axios.post(`/withdraw`, params);
}
// 提现规则详情
function withdrawRule(params) {
return Axios.get(`/withdraw/rule/credit`, {params});
}
// 充值
function recharge(params) {
return Axios.post(`/recharge`, params);
}
// 支付方式
function gatewayList() {
return Axios.get(`/gateway`);
}
// 支付
function pay(params) {
return Axios.post(`/pay`, params);
}
// 支付状态
function getPayStatus(id) {
return Axios.get(`/pay/${id}/status`);
}
// 获取待审核金额
function unAmount() {
return Axios.get(`/refund/pending/amount`);
}
// 使用/取消余额
function creditPay(params) {
return Axios.post(`/credit`, params);
}
// 删除订单
function delete_order(id) {
return Axios.delete(`/order/${id}`);
}
// 批量删除订单
function batchDeleteOrder(params) {
return Axios.delete(`/order`, {params});
}
// // 使用余额支付
// function onlinePay(params) {
// return Axios.post(`/pay`, params);
// }
// 代金券
// 可领代金券列表
function voucherAvailable({params}) {
return Axios.get(`/voucher`, {params});
}
function voucherMine(params) {
return Axios.get(`/voucher/mine`, {params});
}
function voucherGet(params) {
return Axios.post(`/voucher/${params.id}/get`, params);
}
function combineOrder(params) {
return Axios.post(`/order/combine`, params);
}
/* 申请合同列表 */
function contractOrder(params) {
return Axios.get(`/e_contract/order`, {params});
}
/* 合同管理列表 */
function contractList(params) {
return Axios.get(`/e_contract`, {params});
}
/* 保存甲方信息 */
function editPartInfo(params) {
return Axios.put(`/e_contract/first_part_info`, params);
}
/* 获取甲方信息 */
function getPartInfo() {
return Axios.get(`/e_contract/first_part_info`);
}
// 下载PDF
function downloadContract(id) {
return Axios.post(`/e_contract/${id}/download`);
}
// 预览PDF
function viewContract(id) {
return Axios.get(`/e_contract/${id}/preview`);
}
//取消合同
function cancelContrat(id) {
return Axios.post(`/e_contract/${id}/cancel`);
}
//邮递纸质合同
function mailContract(params) {
return Axios.post(`/e_contract/${params.id}/mail`, params);
}
// 获取实名认证信息
function certificationInfo() {
return Axios.get(`/certification/info`);
}
// 出账列表
function creditLimtList(params) {
return Axios.get(`/credit_limit/account`, {params});
}
// 授信详情
function creditDetail() {
return Axios.get(`/credit_limit`);
}
//出账周期订单列表
function creditOrderList(params) {
return Axios.get(`/credit_limit/account/${params.id}/order`, {params});
}
// 信用额提前还款
function prePayment() {
return Axios.post(`/credit_limit/prepayment`);
}
// 冻结记录
function apiFreezeList(params) {
return Axios.get(`/account/credit/freeze`, {params});
}
// 用户可用平台币详情
function apiCoinCoupon(params) {
return Axios.get(`/coin/client/coupon`, {params});
}
// 待领取平台币列表
function apiCoinWaitList(params) {
return Axios.get(`/coin/wait_get`, {params});
}
// 领取平台币
function apiCoinGet(params) {
return Axios.post(`/coin/${params.id}/get`, params);
}
// 平台币列表
function apiCoinList(params) {
return Axios.get(`/coin/coupon`, {params});
}
// 获取平台币使用详情
function apiCoinUseDetail(params) {
return Axios.get(`/coin/coupon/${params.id}/use_detail`, {params});
}
// 订单列表导出EXCEL
function apiExportOrder(params) {
return Axios.get(`/export_excel/order`, {
params,
responseType: "blob",
timeout: 0,
});
}

View File

@@ -0,0 +1,16 @@
// 产品订购地址
function goodsUrl(params) {
return Axios.get(`/baidu_cloud/goods`, { params });
}
// 获取token
function goodsToken() {
return Axios.get(`/baidu_cloud/token`);
}
// 产品订购
function goodsSettle(params) {
return Axios.get(`/baidu_cloud/settle`, { params });
}
// 产品列表地址
function goodsList(params) {
return Axios.get(`/baidu_cloud/list`, { params });
}

View File

@@ -0,0 +1,112 @@
// 获取商品一级分组
function productGroupFirst() {
return Axios.get(`/product/group/first`);
}
//获取商品二级分组
function productGroupSecond(id) {
return Axios.get(`/product/group/second?id=${id}`, id);
}
// 商品列表
function productGoods(params) {
return Axios.get(`/product`, { params });
}
// 获取可用域名后缀
function domainSuffix(id) {
return Axios.get(`/idcsmart_domain/domain_suffix?host_id=${id}`);
}
// 域名查询
function domainSearch(params) {
return Axios.get(`/idcsmart_domain/check_domain`, { params });
}
// 获取域名价格
function domainPrice(params) {
return Axios.get(`/idcsmart_domain/get_price`, { params });
}
// 获取whois信息
function domainWhois(params) {
return Axios.get(`/idcsmart_domain/whois`, { params });
}
// 加入购物车
function addToCart(params) {
return Axios.post(`/cart`, params, { timeout: 1000 * 60 * 20 });
}
// 结算购物车
function cartCheckout(params) {
return Axios.post(`/cart/settle`, params);
}
// 获取商品活动促销信息
function eventPromotion(params) {
return Axios.get(`/event_promotion/product/${params.id}/event_promotion`, {
params
});
}
// 编辑购物车商品
function updateCart(params) {
return Axios.put(`/cart/${params.position}`, params);
}
// 删除购物车商品
function deleteCart(params) {
return Axios.delete(`/cart/${params.position}`, params);
}
// 批量删除购物车商品
function deleteCartBatch(params) {
return Axios.delete(`/cart/batch`, { params });
}
// 信息模板列表
function templateList(params) {
return Axios.get(`/idcsmart_domain/info_template`, { params });
}
// 信息模板详情
function templateDetails(id) {
return Axios.get(`/idcsmart_domain/info_template/${id}`);
}
// 新建信息模板
function templateAdd(params) {
return Axios.post(`/idcsmart_domain/info_template`, params);
}
// 删除信息模板
function templateDelete(id) {
return Axios.delete(`/idcsmart_domain/info_template/${id}`);
}
// 信息模板实名认证
function templateAuth(params) {
return Axios.post(
`/idcsmart_domain/info_template/${params.id}/certifications`,
params
);
}
// 支持的信息模板
function templateSupport(params) {
return Axios.get(`/idcsmart_domain/info_template/support`, { params });
}
// 批量查询域名
function domainBatch(params) {
return Axios.get(`/idcsmart_domain/bulk_check`, {
params,
timeout: 1000 * 60 * 20
});
}
// 获取域名设置
function domainSetting() {
return Axios.get(`/idcsmart_domain/config`);
}

View File

@@ -0,0 +1,48 @@
// 会员中心首页
function indexData() {
return Axios.get(`/index`);
}
//会员中心首页产品列表
function indexHost(params) {
return Axios.get(`/index/host`, { params });
}
// 获取实名认证信息
function certificationInfo() {
return Axios.get(`/certification/info`);
}
//工单列表
function ticket_list(params) {
return Axios.get(`/ticket`, { params });
}
//会员中心首页新闻列表
function newsList(params) {
return Axios.get(`/news/index`, { params });
}
// 推广者统计信息
function promoter_statistic() {
return Axios.get(`/referral/promoter/statistic`);
}
// 开启推介计划
function openRecommend() {
return Axios.post(`recommend/promoter`);
}
// 推广者基础信息
function promoterInfo() {
return Axios.get(`/recommend/promoter`);
}
// 获取微信公众号用户关联信息
function getWxInfo() {
return Axios.get(`/mp_weixin_notice/client`);
}
// 获取二维码
function getWxQrcode() {
return Axios.get(`/mp_weixin_notice/qrcode`);
}
// 授信详情
function creditDetail() {
return Axios.get(`/credit_limit`);
}

View File

@@ -0,0 +1,19 @@
// 订单详情
function orderDetail(id) {
return Axios.get(`/order/${id}`);
}
// 交易记录
function transactionDetail(params) {
return Axios.get(`/transaction`, { params });
}
// 余额变更记录列表
function creditList(params) {
return Axios.get(`/credit`, { params });
}
// 订单交易记录
function apiTransactionRecord(params) {
return Axios.get(`/order/${params.id}/transaction_record`, { params });
}

View File

@@ -0,0 +1,25 @@
// 获取商品列表页
function getProduct(id) {
return Axios.get(`/menu/${id}/host`);
}
// 获取详情
function getProductDetail(id) {
return Axios.get(`/host/${id}/view`);
}
// 获取订购页
function getOrederConfig(params) {
return Axios.get(`/product/${params.id}/config_option`, {params});
}
// 产品详情
function hostDetail(params) {
return Axios.get(`/host/${params.id}`, {params});
}
// 产品合同是否逾期
function timeoutStatus(id) {
return Axios.get(`/e_contract/host/${id}/timeout`);
}
// 会员中心已订购产品列表
function clientHost(params) {
return Axios.get(`/client/host`, {params});
}

View File

@@ -0,0 +1,38 @@
// api 秘钥列表
function apiList(params) {
return Axios.get(`/api`, { params })
}
// 创建api秘钥
function createApi(params) {
return Axios.post(`/api`, params)
}
// APi白名单设置
function whiteApi(params) {
return Axios.put(`/api/${params.id}/white_list`, params)
}
// 删除API秘钥
function delApi(params) {
return Axios.delete(`/api/${params.id}`, params)
}
// ssh 密钥列表
function sshList(params) {
return Axios.get(`/ssh_key`, { params })
}
// 创建SSH密钥
function createSsh(params) {
return Axios.post(`/ssh_key`, params)
}
// 编辑SSH密钥
function editSsh(params) {
return Axios.put(`/ssh_key/${params.id}`, params)
}
// 删除SSH秘钥
function delSsh(params) {
return Axios.delete(`/ssh_key/${params.id}`, params)
}
// 日志列表
function logList(params) {
return Axios.get(`/log`, { params })
}

View File

@@ -0,0 +1,64 @@
/* 安全组 */
function getGroup(params) {
return Axios.get(`/security_group`, {params});
}
function getGroupDetail(id) {
return Axios.get(`/security_group/${id}`);
}
function addAndUpdateGroup(type, params) {
if (type === "add") {
return Axios.post(`/security_group`, params);
} else if (type === "update") {
return Axios.put(`/security_group/${params.id}`, params);
}
}
function deleteGroup(id) {
return Axios.delete(`/security_group/${id}`);
}
/* 安全组规则 */
function getGroupRules(params) {
return Axios.get(`/security_group/${params.id}/rule`, {params});
}
function addAndUpdateGroupRules(type, params) {
if (type === "add") {
return Axios.post(`/security_group/${params.id}/rule`, params);
} else if (type === "update") {
return Axios.put(`/security_group/rule/${params.id}`, params);
}
}
function deleteGroupRules(id) {
return Axios.delete(`/security_group/rule/${id}`);
}
// 批量添加安全组规则
function batchRules(params) {
return Axios.post(`/security_group/${params.id}/rule/batch`, params);
}
// 安全组实例列表
function getGroupCloud(params) {
return Axios.get(`/security_group/${params.id}/host`, {params});
}
// 关联安全组
function concatCloud(params) {
return Axios.post(
`/security_group/${params.id}/host/${params.host_id}`,
params
);
}
// 取消关联实例
function cancelConcatCloud(params) {
return Axios.delete(`/security_group/${params.id}/host/${params.host_id}`);
}
// 获取所有可用实例
// function getAllCloud () {
// return Axios.get(`/idcsmart_cloud/all`);
// }
function getAllCloud(params) {
return Axios.get(`/host`, {params});
}
// 批量关联安全组
function apiLinkGroup(params) {
return Axios.post(`/security_group/${params.id}/host`, params);
}

View File

@@ -0,0 +1,48 @@
// 获取购物车
function cartList() {
return Axios.get(`/cart`);
}
//修改购物车商品数量
function editGoodsNum(index, num) {
return Axios.put(`/cart/${index}/qty`, {qty: num});
}
//批量删除购物车商品
function deleteGoods(arr) {
const params = {positions: arr};
return Axios.delete(`/cart/batch`, {data: params});
}
// 修改配置计算价格
function configOption(id, params) {
return Axios.post(`/product/${id}/config_option`, params);
}
// 结算购物车
function cart_settle(params) {
return Axios.post(`/cart/settle`, params);
}
// 获取商品折扣金额
function clientLevelAmount(params) {
return Axios.get(`/client_level/product/${params.id}/amount`, {params});
}
// 结算商品
function product_settle(params) {
return Axios.post(`/product/settle`, params);
}
//支付接口
function payLisy() {
return Axios.get(`/gateway`);
}
// 修改购物车
function updateCart(params) {
return Axios.put(`/cart/${params.position}`, params);
}
// 商品列表
function productDetail(id) {
return Axios.get(`/product/${id}`);
}

View File

View File

@@ -0,0 +1,8 @@
/**
* @获取提现列表
* @param {*} params
* @returns
*/
function queryWithdrawIistAPI(params) {
return Axios.get(`/withdraw`, { params });
}

View File

@@ -0,0 +1,38 @@
// css 样式依赖common.css
const aliAsideMenu = {
template: ` <el-aside width="220px">
<img class="ali-logo" :src="logo"></img>
<div class="menu-list-top">
<div class="menu-item" :class="item.id === menuActiveId ? 'menu-active':''" v-for="item in menu1" :key="item.id" @click="toPage(item)">
<img :src="item.icon" class="item-img">
<span class="item-text">{{item.text}}</span>
</div>
</div>
</el-aside>`,
data() {
return {
activeId: 1,
menu1: [
{ icon: `${url}/img/common/menu1.png`, text: lang.menu_1, url: "./index.htm", id: 1 },
{ icon: `${url}/img/common/menu2.png`, text: lang.menu_4, url: "./account.htm", id: 2 },
],
logo:`${url}/img/ali/logo.png`
}
},
created() {
console.log(location.href);
},
methods: {
// 页面跳转
toPage(e) {
location.href = e.url
},
},
props: {
menuActiveId: {
type: Number,
default: 1
}
},
}

View File

@@ -0,0 +1,304 @@
// css 样式依赖common.css
const asideMenu = {
template: `
<el-aside width="190px">
<a :href="commonData.clientarea_logo_url || '/home.htm'" onclick="return false" class="menu-alink">
<img class="ali-logo" :src="logo" @click="goHome" v-show="logo"></img>
</a>
<el-menu class="menu-top" :default-active="menuActiveId" @select="handleSelect" background-color="transparent"
text-color="var(--color-menu-text)" active-text-color="var(--color-menu-text-active)">
<template v-for="(item,index) in menu1">
<!-- 只有一级菜单 -->
<template v-if="!item.child || item.child?.length === 0">
<a :href="getMenuUrl(item.id || item.url)" onclick="return false" class="menu-alink">
<el-menu-item :key="item.id ? item.id : item.url" :index="item.id ? item.id + '' : item.url">
<i class="iconfont" :class="item.icon"></i>
<span class="aside-menu-text" slot="title">{{item.name}}</span>
</el-menu-item>
</a>
</template>
<!-- 有二级菜单 -->
<el-submenu v-else :key="item.id ? item.id : item.url" :index="item.id ? item.id + '' : item.url">
<template slot="title">
<i class="iconfont" :class="item.icon"></i>
<span class="aside-menu-text" slot="title">{{item.name}}</span>
</template>
<template v-for="child in item.child">
<a :href="getMenuUrl(child.id || child.url)" onclick="return false" class="menu-alink">
<el-menu-item :index="child.id + ''" :key="child.id">
{{child.name}}
</el-menu-item>
</a>
</template>
</el-submenu>
</template>
</el-menu>
<div class="line" v-if="hasSeparate"></div>
<el-menu class="menu-top" :default-active="menuActiveId" @select="handleSelect" background-color="transparent"
text-color="var(--color-menu-text)" active-text-color="#FFF">
<template v-for="(item,index) in menu2">
<!-- 只有一级菜单 -->
<template v-if="!item.child || item.child?.length === 0">
<a :href="getMenuUrl(item.id || item.url)" onclick="return false" class="menu-alink">
<el-menu-item :key="item.id ? item.id + '' : item.url" :index="item.id ? item.id + '' : item.url">
<i class="iconfont" :class="item.icon"></i>
<span class="aside-menu-text" slot="title">{{item.name}}</span>
</el-menu-item>
</a>
</template>
<!-- 有二级菜单 -->
<el-submenu v-else :key="item.id ? item.id : item.url" :index="item.id ? item.id + '' : item.url">
<template slot="title">
<i class="iconfont" :class="item.icon"></i>
<span class="aside-menu-text" slot="title">{{item.name}}</span>
</template>
<template v-for="child in item.child">
<a :href="getMenuUrl(child.id || child.url)" onclick="return false" class="menu-alink">
<el-menu-item :index="child.id + ''" :key="child.id">
{{child.name}}
</el-menu-item>
</a>
</template>
</el-submenu>
</template>
</el-menu>
</el-aside>
`,
// 云服务器 当前
// 物理服务器 dcim
// 通用产品
data() {
return {
activeId: 1,
menu1: [],
menu2: [],
logo: "",
menuActiveId: "",
iconsData: [],
commonData: {},
noRepeat: [],
hasSeparate: false,
originMenu: [],
};
},
mounted() {
this.doGetMenu();
// const mainLoading = document.getElementById("mainLoading");
// if (mainLoading) {
// mainLoading.style.display = "none";
// }
// if (document.getElementsByClassName("template")[0]) {
// document.getElementsByClassName("template")[0].style.display = "block";
// }
},
created() {
this.getCommonSetting();
},
beforeUpdate() {},
mixins: [mixin],
updated() {
// // 关闭loading
// document.getElementsByClassName('template')[0].style.display = 'block'
const mainLoading = document.getElementById("mainLoading");
if (mainLoading) {
mainLoading.style.display = "none";
}
if (document.getElementsByClassName("template")[0]) {
document.getElementsByClassName("template")[0].style.display = "block";
}
},
methods: {
// 页面跳转
// toPage(e) {
// // 获取 当前点击导航的id 存入本地
// const id = e.id
// localStorage.setItem('frontMenusActiveId', id)
// // 跳转到对应路径
// location.href = '/' + e.url
// },
// 获取通用配置
async getCommonSetting() {
try {
const res = await getCommon();
this.commonData = res.data.data;
localStorage.setItem(
"common_set_before",
JSON.stringify(res.data.data)
);
this.logo = this.commonData.system_logo;
} catch (error) {}
},
// 判断当前菜单激活
setActiveMenu() {
const originUrl = location.pathname.slice(1);
const allUrl = originUrl + location.search;
let flag = false;
this.originMenu.forEach((item) => {
// 当前url下存在和导航菜单对应的路径
if (!item.child && item.url) {
const url = String(item.url).split("?");
if (
(url.length > 1 && item.url == allUrl) ||
(url.length == 1 && item.url == originUrl)
) {
this.menuActiveId = item.id + "";
flag = true;
}
}
// 当前url下存在二级菜单
if (item.child && item.child.length > 0) {
item.child.forEach((child) => {
const url = String(child.url).split("?");
if (
(url.length > 1 && child.url == allUrl) ||
(url.length == 1 && child.url == originUrl)
) {
this.menuActiveId = child.id + "";
flag = true;
}
});
}
});
if (!flag) {
this.menuActiveId = localStorage.getItem("frontMenusActiveId") || "";
}
},
goHome() {
localStorage.frontMenusActiveId = "";
const openUrl = this.commonData.clientarea_logo_url || "/home.htm";
if (this.commonData.clientarea_logo_url_blank == 1) {
window.open(openUrl);
} else {
location.href = openUrl;
}
},
// 获取前台导航
doGetMenu() {
getMenu().then((res) => {
if (res.data.status === 200) {
res.data.data.menu.forEach((item) => {
if (item.child && item.child.length > 0) {
this.originMenu.push(...item.child);
} else {
this.originMenu.push(item);
}
});
const menu = res.data.data.menu;
localStorage.setItem("frontMenus", JSON.stringify(menu));
let index = menu.findIndex((item) => item.name == "分隔符");
if (index != -1) {
this.hasSeparate = true;
this.menu1 = menu.slice(0, index);
this.menu2 = menu.slice(index + 1);
} else {
this.hasSeparate = false;
this.menu1 = menu;
}
this.setActiveMenu();
}
});
// 获取详情
accountDetail()
.then((res) => {
if (res.data.status == 200) {
let obj = res.data.data.account;
let id = res.data.data.account.id;
localStorage.setItem(
"is_sub_account",
obj.customfield?.is_sub_account
);
if (obj.customfield?.is_sub_account == 1) {
// 子账户
accountPermissions(id).then((relust) => {
let rule = relust.data.data.rule;
this.$emit("getruleslist", rule);
});
} else {
// 主账户
this.$emit("getruleslist", "all");
}
}
})
.catch((err) => {
console.log(err, "err----->");
});
},
arrFun(n) {
for (var i = 0; i < n.length; i++) {
//用typeof判断是否是数组
if (n[i].child && typeof n[i].child == "object") {
let obj = JSON.parse(JSON.stringify(n[i]));
delete obj.child;
this.noRepeat.push(obj);
this.arrFun(n[i].child);
} else {
this.noRepeat.push(n[i]);
}
}
},
/*
* 获取菜单url
* @param {Number} id 菜单id 或者url
* @return {String} url 菜单url
*/
getMenuUrl(id) {
const temp =
this.originMenu.find((item) => item.id == id || item.url == id) || {};
const reg =
/^(((ht|f)tps?):\/\/)([^!@#$%^&*?.\s-]([^!@#$%^&*?.\s]{0,63}[^!@#$%^&*?.\s])?\.)+[a-z]{2,6}\/?/;
let url = "/" + temp.url;
if (reg.test(temp.url)) {
if (temp?.second_reminder === 1) {
url = `/transfer.htm?target=${encodeURIComponent(temp.url)}`;
} else {
url = temp.url;
}
}
return url;
},
handleSelect(id) {
localStorage.setItem("frontMenusActiveId", id);
const temp =
this.originMenu.find((item) => item.id == id || item.url == id) || {};
const reg =
/^(((ht|f)tps?):\/\/)([^!@#$%^&*?.\s-]([^!@#$%^&*?.\s]{0,63}[^!@#$%^&*?.\s])?\.)+[a-z]{2,6}\/?/;
if (reg.test(temp.url)) {
if (temp?.second_reminder === 1) {
return window.open(
`/transfer.htm?target=${encodeURIComponent(temp.url)}`
);
} else {
return window.open(temp.url);
}
}
location.href = "/" + temp.url;
},
getAllIcon() {
let url = "/upload/common/iconfont/iconfont.json";
let _this = this;
// 申明一个XMLHttpRequest
let request = new XMLHttpRequest();
// 设置请求方法与路径
request.open("get", url);
// 不发送数据到服务器
request.send(null);
//XHR对象获取到返回信息后执行
request.onload = function () {
// 解析获取到的数据
let data = JSON.parse(request.responseText);
_this.iconsData = data.glyphs;
_this.iconsData.map((item) => {
item.font_class = "icon-" + item.font_class;
});
};
},
},
};

View File

@@ -0,0 +1,148 @@
/* 自动续费 */
const autoRenew = {
template: `
<div class="com-auto-renew">
<el-switch :value="isAutoRenew" active-color="var(--color-primary)"
:active-value="1" :inactive-value="0" @change="autoRenewChange">
</el-switch>
<el-dialog :visible.sync="showRenewDialog" :show-close="false" custom-class="common-renew-dialog"
width="6.2rem">
<div class="dialog-title">
{{calcTitle}}
</div>
<div class="con" v-loading="loading">
<p class="item">
<span class="label">ID</span>
<span class="value">{{host.id}}</span>
</p>
<p class="item">
<span class="label">{{lang.auto_renew_name}}</span>
<span class="value">{{host.name}}</span>
</p>
<p class="item" v-if="host.area">
<span class="label">{{lang.auto_renew_area}}</span>
<span class="value">{{host.country}}-{{host.city}}-{{host.area}}</span>
</p>
<p class="item" v-if="host.dedicate_ip">
<span class="label">IP</span>
<span class="value">
<span>{{host.dedicate_ip}}</span>
<el-popover placement="top" trigger="hover" v-if="host.ip_num > 1">
<div class="ips">
<p v-for="(item,index) in host.allIp" :key="index">
{{item}}
<i class="el-icon-document-copy base-color" @click="copyIp(item)"></i>
</p>
</div>
<span slot="reference" class="base-color">
({{host.ip_num}})
</span>
</el-popover>
<i class="el-icon-document-copy base-color" @click="copyIp(host.allIp)" v-if="host.ip_num > 0">
</i>
</span>
</p>
<p class="item">
<span class="label">{{lang.auto_renew_cycle}}</span>
<span class="value">{{commonData.currency_prefix}}{{host.renew_amount}}/{{host.billing_cycle_name}}</span>
</p>
<p class="item">
<span class="label">{{lang.auto_renew_due}}</span>
<span class="value">{{host.due_time | formateTime}}</span>
</p>
</div>
<div class="dialog-footer">
<el-button class="btn-ok" @click="handleAutoRenew" :loading="submitLoading">{{lang.auto_renew_sure}}</el-button>
<el-button class="btn-no" @click="showRenewDialog = false">{{lang.auto_renew_cancel}}</el-button>
</div>
</el-dialog>
</div>
`,
data() {
return {
showRenewDialog: false,
submitLoading: false,
calcTitle: "",
is_auto_renew: 0,
host: {},
loading: false,
commonData: JSON.parse(localStorage.getItem("common_set_before")) || {},
};
},
props: {
isAutoRenew: {
type: Number,
required: true,
default: 0,
},
id: {
type: Number | String,
required: true,
default: null,
},
},
filters: {
formateTime(time) {
if (time && time !== 0) {
return formateDate(time * 1000);
} else {
return "--";
}
},
},
methods: {
copyIp(ip) {
if (typeof ip !== "string") {
ip = ip.join(",");
}
const textarea = document.createElement("textarea");
textarea.value = ip.replace(/,/g, "\n");
document.body.appendChild(textarea);
textarea.select();
document.execCommand("copy");
document.body.removeChild(textarea);
this.$message.success(lang.index_text32);
},
async handleAutoRenew() {
try {
const params = {
id: this.host.id,
status: this.is_auto_renew,
};
this.submitLoading = true;
const res = await rennewAuto(params);
this.$message.success(res.data.msg);
this.showRenewDialog = false;
this.submitLoading = false;
this.$emit("update");
} catch (error) {
this.submitLoading = false;
this.showRenewDialog = false;
this.$message.error(error.data.msg);
}
},
async autoRenewChange(val) {
try {
this.showRenewDialog = true;
this.is_auto_renew = val ? 1 : 0;
this.loading = true;
const res = await getHostSpecific({id: this.id});
this.host = res.data.data;
this.host.allIp = (
this.host.dedicate_ip +
"," +
this.host.assign_ip
).split(",");
this.calcTitle =
lang.auto_renew_tip1 +
(this.isAutoRenew
? lang_obj.auto_renew_tip3
: lang_obj.auto_renew_tip2);
this.loading = false;
} catch (error) {
this.loading = false;
this.$message.error(error.data.msg);
}
},
},
};

View File

@@ -0,0 +1,651 @@
const batchRenewpage = {
template: /*html */ `
<div class="batch-op-btn">
<div class="search-btn" style="margin-right: 0.1rem;" v-if="show_quick_order === 1">
<a :href="quick_order_url" style="color: #fff; text-decoration: none;" target="_blank">{{lang.new_goods}}</a>
</div>
<el-dropdown split-button type="primary" @click="handleClick" @command="handleCommand" v-show="canOp">
{{opName}}
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-for="item in opList" :key="item.value" :command="item.value">{{item.label}}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-dialog width="5.5rem" :visible.sync="confirmDialog" :title="lang.cart_tip_text15 + opName + '?'" class="branch-confirm-dialog">
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="handelOp" :loading="subLoading">{{lang.cart_tip_text9}}</el-button>
<el-button @click="confirmDialog = false;">{{lang.cart_tip_text10}}</el-button>
</div>
</el-dialog>
<el-dialog width="10rem" :visible.sync="isShow" @close="rzClose" class="branch-rennew-dialog">
<div class="dialag-content" v-loading="loading">
<h2 class="tips-title">{{title}}</h2>
<el-table :data="dataList" style="width: 100%" max-height="600">
<el-table-column prop="id" label="ID" width="120">
</el-table-column>
<el-table-column prop="product_name" :label="lang.cart_tip_text11" min-width="180"
:show-overflow-tooltip="true">
</el-table-column>
<el-table-column prop="billing_cycles" :label="lang.cart_tip_text12" min-width="180">
<template slot-scope="{row}">
<el-select v-model="row.select_cycles" @change="(val) =>changeCycles(row)">
<el-option v-for="(item,index) in row.billing_cycles" :key="index" :value="index" :label=" item.customfield?.multi_language?.billing_cycle || item.billing_cycle">
<span>{{currency_prefix + item.price}} /{{ item.customfield?.multi_language?.billing_cycle || item.billing_cycle }}</span>
</el-option>
</el-select>
</template>
</el-table-column>
<el-table-column prop="base_price" :label="lang.cart_tip_text13" width="180" align="right">
<template slot-scope="{row}">
<span>{{currency_prefix + row.cur_pirce}}</span>
</template>
</el-table-column>
</el-table>
<div class="total-price">{{lang.template_text87}}
<span class="pay-money">{{currency_prefix }} <span
class="font-26">{{ calcDiscountPrice }}</span> </span>
</div>
<div class="origin-price" v-if="hasDiscount && currentDiscount > 0">
<span class="pay-money">{{currency_prefix }} <span
class="font-26">{{ calcTotalPrice}}</span> </span>
</div>
<!-- 优惠码 -->
<div class="batch-discount-popover">
<el-popover placement="bottom" trigger="click" v-if="hasDiscount && !promo.promo_code " v-model="visibleShow"
:visible-arrow="false">
<div class="discount-content">
<div class="close-btn-img" @click="closePopver">
<img src="${url}/img/common/close_icon.png" alt="">
</div>
<div>
<el-input class="discount-input" clearable v-model="discountInputVal" :placeholder="lang.login_text10"
maxlength="9"></el-input>
<el-button class="discount-btn" :loading="isLoading"
@click="handelApplyPromoCode">{{lang.shoppingCar_tip_text9}}</el-button>
</div>
</div>
<span slot="reference" class="discount-text">{{lang.shoppingCar_tip_text12}}</span>
</el-popover>
<div v-if="promo.promo_code && currentDiscount > 0" class="used">
{{ promo.promo_code }}
<i class="el-icon-circle-close remove-discountCode" @click="removeDiscountCode"></i>
</div>
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="handelRenew" :loading="subLoading">{{lang.cart_tip_text9}}</el-button>
<el-button @click="rzClose">{{lang.cart_tip_text10}}</el-button>
</div>
</el-dialog>
<!-- 重置密码弹窗 -->
<div class="branch-repass-dialog">
<el-dialog width="6.8rem" :visible.sync="isShowRePass" :show-close=false @close="rePassDgClose">
<div class="dialog-title">
{{lang.cart_tip_text28}}
</div>
<div class="dialog-main">
<el-input class="pass-input" v-model="rePassData.password" :placeholder="lang.account_tips47">
<div class="pass-btn" slot="suffix" @click="autoPass">{{lang.common_cloud_btn1}}</div>
</el-input>
</div>
<div slot="footer" class="dialog-footer">
<div class="btn-ok" @click="rePassSub" v-loading="subLoading">{{lang.cart_tip_text9}}</div>
<div class="btn-no" @click="rePassDgClose">{{lang.cart_tip_text10}}</div>
</div>
</el-dialog>
</div>
<!-- 修改备注弹窗 -->
<div class="branch-repass-dialog">
<el-dialog width="6.8rem" :visible.sync="isShowNote" :show-close=false>
<div class="dialog-title">
{{lang.cart_tip_text30}}
</div>
<div class="dialog-main">
<el-input class="pass-input" v-model="notes" :placeholder="lang.cart_tip_text31"></el-input>
</div>
<div slot="footer" class="dialog-footer">
<div class="btn-ok" @click="handelNoteSub" v-loading="subLoading">{{lang.cart_tip_text9}}</div>
<div class="btn-no" @click="isShowNote = false">{{lang.cart_tip_text10}}</div>
</div>
</el-dialog>
</div>
<pay-dialog ref="RennwPayDialog" @payok="paySuccess" @paycancel="payCancel"></pay-dialog>
<safe-confirm ref="safeRef" :password.sync="client_operate_password" @confirm="hadelSafeConfirm"></safe-confirm>
</div>
`,
props: {
title: {
type: String,
default: lang.cart_tip_text7,
},
ids: {
type: Array,
required: true,
default: () => {
return [];
},
},
tab: {
type: String,
required: true,
default: "", // using expiring // overdue // deleted // ""
},
moduleType: {
type: String,
required: true,
},
},
components: {
payDialog,
safeConfirm,
},
data() {
return {
currency_prefix:
(JSON.parse(localStorage.getItem("common_set_before")) || {})
?.currency_prefix || "¥",
isShow: false,
loading: false,
subLoading: false,
confirmDialog: false,
dataList: [],
opType: "renew",
client_operate_password: "",
allOpList: [
{
value: "renew",
label: lang.cart_tip_text7,
},
{
value: "on",
label: lang.cart_tip_text16,
},
{
value: "off",
label: lang.cart_tip_text17,
},
{
value: "reboot",
label: lang.cart_tip_text18,
},
{
value: "hard_off",
label: lang.cart_tip_text19,
},
{
value: "hard_reboot",
label: lang.cart_tip_text20,
},
],
cloud_moudle: ["mf_cloud", "remf_cloud", "remf_finance", "rewhmcs_cloud"],
dcim_moudle: [
"mf_dcim",
"remf_dcim",
"remf_finance_dcim",
"rewhmcs_dcim",
],
ip_moudle: ["mf_cloud_ip", "mf_cloud_disk", "huawei_eip"],
common_moudle: ["idcsmart_common"],
show_quick_order: 0,
quick_order_url: "",
isShowRePass: false,
rePassData: {
password: "",
},
promo: {
promo_code: "",
},
visibleShow: false,
discountInputVal: "",
isLoading: false,
currentDiscount: 0,
batchHostDiscount: {}, // 批量使用优惠码过后的折扣
notes: "",
isShowNote: false,
};
},
mixins: [mixin],
created() {
const addons = document.querySelector("#addons_js");
const addons_js_arr = JSON.parse(addons.getAttribute("addons_js")).map((item) => {
return item.name;
});
this.hasDiscount = addons_js_arr.includes("PromoCode");
this.setQuickOrderUrl();
},
computed: {
canOp() {
return this.tab !== "deleted";
},
opList() {
const isActive =
this.tab === "using" || this.tab === "expiring" || this.tab == "";
const isCloud = this.cloud_moudle.includes(this.moduleType);
const isDcim = this.dcim_moudle.includes(this.moduleType);
const isIp = this.ip_moudle.includes(this.moduleType);
const isCommon = this.common_moudle.includes(this.moduleType);
if (!isActive) {
return [
{
value: "renew",
label: lang.cart_tip_text7,
},
];
}
if (isIp) {
return [
{
value: "renew",
label: lang.cart_tip_text7,
},
{
value: "unlink",
label: lang.cart_tip_text21,
},
{
value: "note",
label: lang.cart_tip_text30,
},
];
} else if (isCloud) {
return [...this.allOpList, {
value: "note",
label: lang.cart_tip_text30,
},];
} else if (isDcim) {
return [
{
value: "renew",
label: lang.cart_tip_text7,
},
{
value: "on",
label: lang.cart_tip_text16,
},
{
value: "off",
label: lang.cart_tip_text17,
},
{
value: "reboot",
label: lang.cart_tip_text18,
},
{
value: "note",
label: lang.cart_tip_text30,
},
];
}
if (isCommon) {
return [
...this.allOpList,
{
value: "crack_pass",
label: lang.cart_tip_text27,
},
// {
// value: "reinstall",
// label: lang.cart_tip_text28,
// },
];
} else {
return [
{
value: "renew",
label: lang.cart_tip_text7,
},
{
value: "note",
label: lang.cart_tip_text30,
},
];
}
},
idsArr() {
return this.ids.map((item) => {
return item.id;
});
},
rewIdArr() {
return this.dataList.map((item) => {
return item.id;
});
},
calcTotalPrice() {
return this.dataList
.reduce((acc, cur) => {
return acc + cur.cur_pirce * 1;
}, 0)
.toFixed(2);
},
// 折扣价钱计算方式
calcDiscountPrice() {
return (this.dataList
.reduce((acc, cur) => {
let temp = 0;
// 折扣价 + 已减去的循环优惠的价格 - 批量使用优惠码的折扣
if (this.batchHostDiscount[cur.id] * 1 > 0) {
temp = cur.cur_pirce * 1 + cur.promo_code_discount * 1 - this.batchHostDiscount[cur.id] * 1;
} else {
temp = cur.cur_pirce * 1;
}
return acc + temp;
}, 0))
.toFixed(2);
},
opName() {
return (
this.opList.filter((item) => item.value === this.opType)[0]?.label ||
lang.cart_tip_text22
);
},
},
watch: {
opList(val) {
this.opType = val[0].value || "";
},
},
methods: {
removeDiscountCode() {
this.discountInputVal = "";
this.promo.promo_code = "";
this.currentDiscount = 0;
this.batchHostDiscount = {};
},
async handelApplyPromoCode(bol = true) {
try {
if (this.discountInputVal.length === 0) {
if (bol) {
this.$message.warning(lang.shoppingCar_tip_text13);
}
return;
}
// this.isLoading = true;
let discountArr = [];
this.dataList.forEach(item => {
const params = {
host_id: item.id,
product_id: item.product_id,
amount: item.billing_cycles[item.select_cycles].base_price,
billing_cycle_time: item.billing_cycles[item.select_cycles].duration,
promo_code: this.discountInputVal,
scene: "renew"
};
discountArr.push(params);
});
const res = await applyBatchRenewCode({ promo_codes: discountArr });
this.promo.promo_code = this.discountInputVal;
this.currentDiscount = res.data.data.discount;
this.batchHostDiscount = res.data.data.host_discount;
if (this.currentDiscount * 1 > 0) {
this.$message.success(res.data.msg);
} else {
this.removeDiscountCode();
}
} catch (error) {
this.$message.error(error.data.msg);
}
},
closePopver() {
this.visibleShow = false;
this.discountInputVal = "";
},
setQuickOrderUrl() {
// 拿到当前导航完整路径 去除location.origin
this.currentNav = location.href.replace(location.origin, "");
const params = getUrlParams();
let currentMenu;
const menuList = JSON.parse(localStorage.getItem("frontMenus") || "[]");
let isFindById = false;
// 找到当前导航
// 有id直接使用id
if (params.m) {
currentMenu = menuList.find(
(item) =>
item.id == params.m || item?.child?.some((el) => el.id == params.m)
);
isFindById = true;
}
if (!currentMenu) {
currentMenu = menuList.find(
(item) =>
(item.url !== "" && this.currentNav.includes(item.url)) ||
item?.child?.some(
(el) => el.url !== "" && this.currentNav.includes(el.url)
)
);
isFindById = false;
}
if (currentMenu?.child) {
if (isFindById) {
currentMenu = currentMenu?.child?.find((el) => el.id == params.m);
} else {
currentMenu = currentMenu.child.find(
(el) => el.url !== "" && this.currentNav.includes(el.url)
);
}
}
if (currentMenu) {
this.show_quick_order = currentMenu?.show_quick_order;
this.quick_order_url = currentMenu?.quick_order_url;
}
},
// 随机生成密码
autoPass() {
let passLen = 9;
let pass =
randomCoding(1) +
randomCoding(1).toLocaleLowerCase() +
0 +
genEnCode(passLen, 1, 1, 0, 1, 0);
this.rePassData.password = pass;
},
rePassSub() {
if (!this.rePassData.password) {
this.$message.error(lang.cart_tip_text29);
return;
}
this.handelOp();
},
rePassDgClose() {
this.isShowRePass = false;
this.rePassData.password = "";
},
hadelSafeConfirm(val) {
this[val]();
},
handleCommand(command) {
this.opType = command;
this.handleClick();
},
handleClick() {
if (this.opType === "") {
this.$message.warning(lang.cart_tip_text23);
return;
}
if (this.idsArr.length === 0) {
this.$message.warning(lang.cart_tip_text24);
return;
}
if (this.opType === "renew") {
this.openDia();
return;
}
if (this.opType === "crack_pass") {
this.isShowRePass = true;
return;
}
if (this.opType === "note") {
this.openNoteDia();
return;
}
this.confirmDialog = true;
},
handelNoteSub() {
this.subLoading = true;
apiBatchUpdateHostNotes({ ids: this.idsArr, notes: this.notes })
.then((res) => {
this.$message.success(res.data.msg);
this.subLoading = false;
this.isShowNote = false;
this.$emit("success");
})
.catch((err) => {
this.$message.error(err.data.msg);
this.subLoading = false;
});
},
openNoteDia() {
this.notes = "";
this.isShowNote = true;
},
handelOp(e, remember_operate_password = 0) {
// if (!this.client_operate_password) {
// this.$refs.safeRef.openDialog("handelOp");
// return;
// }
const client_operate_password = this.client_operate_password;
this.client_operate_password = "";
this.subLoading = true;
const params = {
id: this.idsArr,
action: this.opType,
client_operate_password,
client_operate_methods: "handelOp",
remember_operate_password,
};
if (this.opType === "crack_pass") {
params.password = this.rePassData.password;
}
batchOperation(this.moduleType, params)
.then((res) => {
const arr = res.data.data;
const tips = arr
.map((item) => {
return `<p>ID${item.id}${item.msg}</p>`;
})
.join("");
this.$notify({
title: lang.cart_tip_text25,
message: tips,
duration: 0,
dangerouslyUseHTMLString: true,
});
this.$emit("success");
this.subLoading = false;
this.confirmDialog = false;
if (this.opType === "crack_pass") {
this.isShowRePass = false;
}
})
.catch((err) => {
this.subLoading = false;
this.$message.error(err.data.msg);
if (err.data.data) {
if (
!client_operate_password &&
err.data.data.operate_password === 1
) {
this.$refs.safeRef.openDialog("handelOp");
return;
} else {
return this.$message.error(err.data.msg);
}
}
});
},
openDia() {
this.promo.promo_code = "";
this.discountInputVal = "";
this.currentDiscount = 0;
this.batchHostDiscount = {};
this.isShow = true;
this.getRenewList();
},
changeCycles(item) {
this.discountInputVal = this.promo.promo_code;
this.handelApplyPromoCode(false);
item.cur_pirce = this.calcPrice(item);
item.promo_code_discount = this.calcPrice(item, true);
},
calcPrice(row, bol = false) {
let temp = 'price';
if (bol) {
temp = 'promo_code_discount';
}
return (
row.billing_cycles.filter(
(item, index) => index == row.select_cycles
)[0]?.[temp] || 0
);
},
getRenewList() {
this.loading = true;
batchRenewList({ ids: this.idsArr })
.then((res) => {
this.dataList = res.data.data.list.map((item) => {
item.select_cycles = 0;
item.cur_pirce = item.billing_cycles[0].price;
item.promo_code_discount = item.billing_cycles[0].promo_code_discount || 0;
return item;
});
this.loading = false;
})
.catch((err) => {
this.loading = false;
this.$message.error(err.data.msg);
});
},
rzClose() {
this.isShow = false;
},
paySuccess(e) {
this.isShow = false;
this.$emit("success");
},
// 取消支付回调
payCancel(e) { },
handelRenew() {
this.subLoading = true;
const billing_cycles = {};
this.dataList.forEach((item) => {
billing_cycles[item.id] = item.billing_cycles.filter(
(items, index) => index == item.select_cycles
)[0].billing_cycle;
});
aipBatchRenew({
ids: this.rewIdArr,
billing_cycles,
customfield: {
promo_code: this.promo.promo_code,
},
})
.then((res) => {
this.subLoading = false;
if (res.data.code === "Unpaid") {
this.$refs.RennwPayDialog.showPayDialog(res.data.data.id);
} else {
this.isShow = false;
this.$emit("success");
}
})
.catch((err) => {
this.subLoading = false;
this.$message.error(err.data.msg);
});
},
},
};

View File

@@ -0,0 +1,116 @@
// 验证码通过 - 找到当前显示的验证码实例
function captchaCheckSuccsss(bol, captcha, token) {
if (bol) {
// 遍历所有注册的验证码实例,找到 DOM 中存在的那个v-if 确保存在即可见)
if (window.captchaInstances) {
for (let captchaId in window.captchaInstances) {
const element = document.getElementById(captchaId);
// v-if 保证:元素存在 = 元素可见
if (element) {
const instance = window.captchaInstances[captchaId];
if (instance && instance.getData) {
instance.getData(captcha, token);
break; // 找到就退出循环
}
}
}
}
}
}
// 取消验证码验证 - 找到当前显示的验证码实例
function captchaCheckCancel() {
if (window.captchaInstances) {
for (let captchaId in window.captchaInstances) {
const element = document.getElementById(captchaId);
// v-if 保证:元素存在 = 元素可见
if (element) {
const instance = window.captchaInstances[captchaId];
if (instance && instance.captchaCancel) {
instance.captchaCancel();
break; // 找到就退出循环
}
}
}
}
}
// css 样式依赖common.css
const captchaDialog = {
template: `
<div :id="captchaId" v-if="isShowCaptcha"></div>`,
created() {
// this.doGetCaptcha()
},
data() {
return {
captchaData: {
token: "",
captcha: "",
},
captchaHtml: "",
};
},
props: {
isShowCaptcha: {
type: Boolean,
},
captchaId: {
type: String,
default() {
// 生成唯一 ID避免多实例冲突
return `captchaHtml_${Date.now()}_${Math.random()
.toString(36)
.slice(2, 11)}`;
},
},
},
methods: {
// 获取图形验证码
doGetCaptcha() {
try {
getNewCaptcha().then((res) => {
if (res.data.status === 200) {
this.captchaHtml = res.data.data.html;
$(`#${this.captchaId}`).html(this.captchaHtml);
$(`#${this.captchaId}`).show();
}
});
} catch (e) {
console.log("获取图形验证码", e);
}
},
// 取消验证码
captchaCancel() {
this.$emit("captcha-cancel");
},
// 获取验证码数据
getData(captchaCode, token) {
this.captchaData.captcha = captchaCode;
this.captchaData.token = token;
this.$emit("get-captcha-data", captchaCode, token);
},
},
mounted() {
// 创建全局实例映射对象
if (!window.captchaInstances) {
window.captchaInstances = {};
}
// 将当前实例注册到全局映射表中,使用箭头函数保持 this 指向
window.captchaInstances[this.captchaId] = {
getData: (captchaCode, token) => {
this.getData(captchaCode, token);
},
captchaCancel: () => {
this.captchaCancel();
},
};
},
// 组件销毁时清理对应的实例引用
beforeDestroy() {
if (window.captchaInstances && window.captchaInstances[this.captchaId]) {
delete window.captchaInstances[this.captchaId];
}
},
};

View File

@@ -0,0 +1,104 @@
const cashBack = {
template: `
<el-dialog :visible.sync="showCash" :show-close="false" custom-class="common-cashback-dialog">
<div class="dialog-title">
{{lang.apply_cashback}}
</div>
<div class="con">
{{lang.cashback_tip1}}<span class="price">{{currency_prefix}}{{cashbackPrice | filterMoney}}</span>
<template v-if="cashbackTime">{{lang.cashback_tip2}} {{cashbackTime | formateTime}}</template>
</div>
<div class="dialog-footer">
<div class="tip">{{lang.cashback_tip}}</div>
<div class="opt">
<el-button class="btn-ok" @click="sureCashback" :loading="cashLoading">{{lang.ticket_btn6}}</el-button>
<el-button class="btn-no" @click="cancleDialog">{{lang.finance_btn7}}</el-button>
</div>
</div>
</el-dialog>
`,
filters: {
filterMoney(money) {
if (isNaN(money)) {
return "0.00";
} else {
const temp = `${money}`.split(".");
return parseInt(temp[0]).toLocaleString() + "." + (temp[1] || "00");
}
},
formateTime(time) {
if (time && time !== 0) {
return formateDate(time * 1000);
} else {
return "--";
}
},
},
data() {
return {
hasCash: false, // 是否安装了插件
isShowBtn: false, // 是否展示申请返现按钮
cashbackPrice: null,
cashbackTime: null,
cashLoading: false,
currency_prefix: (localStorage.common_set_before && JSON.parse(localStorage.common_set_before)?.currency_prefix) || "¥",
};
},
props: {
id: {
type: Number | String,
required: true,
},
showCash: {
type: Boolean,
},
},
mixins: [mixin],
mounted() {
this.hasCash = this.addons_js_arr.includes("ProductCashback");
this.hasCash && this.getCash();
},
created() { },
methods: {
async getCash() {
try {
const {
data: {
data: { cashback_support, is_cashback, expired, price },
},
} = await getCashbackInfo({ id: this.id });
if (
cashback_support &&
!is_cashback &&
price * 1 &&
(expired > new Date().getTime() / 1000 || expired === 0)
) {
this.cashbackPrice = price;
this.cashbackTime = expired;
this.isShowBtn = true;
} else {
this.isShowBtn = false;
}
this.$emit("showbtn", this.isShowBtn);
} catch (error) {
this.$message.error(error.data.msg);
}
},
async sureCashback() {
try {
this.cashLoading = true;
const res = await apllyCashback({ id: this.id });
this.$message.success(res.data.msg);
this.getCash();
this.cashLoading = false;
this.$emit("cancledialog", false);
} catch (error) {
this.cashLoading = false;
this.$message.error(error.data.msg);
}
},
cancleDialog() {
this.$emit("cancledialog", false);
},
},
};

View File

@@ -0,0 +1,84 @@
const cashCoupon = {
template: `
<div>
<el-popover placement="bottom" trigger="click" v-model="visibleShow" class="discount-popover" @show="popSow" :visible-arrow="false">
<div class="discount-content">
<div class="close-btn-img" @click="closePopver">
<img src="${url}/img/common/close_icon.png" alt="">
</div>
<div>
<el-select class="discount-input" v-model="value" clearable :placeholder="lang.shoppingCar_tip_text8" value-key="id">
<el-option v-for="item in options" :key="item.id" :label=" item.code + '--' + currency_prefix + item.price " :value="item"></el-option>
</el-select>
<el-button class="discount-btn" @click="handelApplyPromoCode">{{lang.shoppingCar_tip_text9}}</el-button>
</div>
</div>
<span slot="reference" class="cash-code">{{lang.shoppingCar_tip_text10}}</span>
</el-popover>
</div>
`,
data() {
return {
visibleShow: false, // 是否显示代金券弹窗
isLoading: false, // 确认按钮loading
value: {}, // 选择的对象
options: [], // 代金券数组
};
},
components: {},
props: {
scene: {
type: String, // new新购,renew续费,upgrade升降级
required: true,
},
product_id: {
type: Array, // 场景中的所有商品ID
required: true,
},
price: {
type: Number | String, // 需要支付的原价格
required: true,
},
currency_prefix: {
type: String,
default:
(localStorage.common_set_before &&
JSON.parse(localStorage.common_set_before)?.currency_prefix) ||
"¥",
},
},
created() {},
mounted() {},
methods: {
closePopver() {
this.visibleShow = false;
this.value = {};
},
handelApplyPromoCode() {
if (!this.value.id) {
this.$message.warning(lang.shoppingCar_tip_text11);
return;
}
this.$emit("use-cash", this.value);
this.visibleShow = false;
},
popSow() {
const params = {
scene: this.scene,
product_id: this.product_id,
price: Number(this.price),
};
this.getEnableList(params);
},
getEnableList(params) {
enableList(params)
.then((res) => {
this.options = res.data.data.list;
})
.catch((err) => {
this.$message.error(err.data.msg);
})
.finally(() => {});
},
},
};

View File

@@ -0,0 +1,36 @@
const certificationDialog = {
template: `
<!-- 未实名认证 dialog -->
<div class="rz-dialog">
<el-dialog width="10rem" :visible.sync="isShow" @close="rzClose">
<div class="dialag-content">
<h2 class="tips-title">您尚未进行实名认证,请先完成实名认证</h2>
<p class="tips-text">据我国2016年11月7日全国人民代表大会常务委员会通过的《中华人民共和国网络安全法》规定,用户不提供真实身份信息的,网络运营者不得为其提供相关服务。 为了符合国家法律法规,以及不影响您参与优惠活动,请您先实名认证。实名认证信息保密工作是统一管理,请放心填写。</p>
<div class="button-box">
<el-button @click="goCertification">立即认证</el-button>
<el-link @click ="rzClose()">以后再说</el-link>
</div>
</div>
</el-dialog>
</div>
`,
props: {
},
data() {
return {
isShow: false
}
},
methods: {
rzClose() {
this.isShow = false
},
goCertification() {
location.href = `plugin/${getPluginId("IdcsmartCertification")}/authentication_select.htm`;
},
},
watch: {}
}

View File

@@ -0,0 +1,128 @@
.coin-active-popover {
padding: 0 !important;
}
.coin-active-btn {
position: fixed;
right: 3px;
top: 35vh;
z-index: 99;
}
.coin-active-btn .coin-active-trigger {
position: relative;
display: inline-flex;
flex-direction: column;
align-items: center;
gap: 8px;
padding: 8px 5px;
border-radius: 99px;
color: #fff;
background: var(--color-primary);
cursor: pointer;
user-select: none;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(26, 97, 214, 0.2);
}
.coin-active-btn .coin-active-trigger:hover {
transform: scale(1.05);
box-shadow: 0 4px 16px rgba(26, 97, 214, 0.4);
/* 由于@primary-color是CSS变量less的lighten函数无法直接处理改为使用filter实现亮色效果 */
background: var(--color-primary);
filter: brightness(1.08);
}
.coin-active-btn .coin-active-trigger:hover .trigger-icon {
transform: rotate(5deg);
background-color: #f8f9ff;
}
.coin-active-btn .coin-active-trigger:hover .trigger-text {
letter-spacing: 6px;
}
.coin-active-btn .coin-active-trigger .trigger-icon {
font-size: 0;
padding: 7px;
border-radius: 50%;
background-color: #fff;
transition: all 0.3s ease;
}
.coin-active-btn .coin-active-trigger .trigger-icon .icon-svg {
width: 16px;
height: 16px;
}
.coin-active-btn .coin-active-trigger .trigger-text {
writing-mode: vertical-rl;
text-orientation: mixed;
letter-spacing: 5px;
font-size: 12px;
transition: all 0.3s ease;
}
.coin-active-box .coin-title {
padding: 16px 24px;
font-size: 16px;
font-weight: 600;
color: #2B2B2B;
border-bottom: 1px solid #EAEAEA;
}
.coin-active-box .coin-active-tabs .el-tabs__nav-wrap {
padding-left: 24px;
}
.coin-active-box .coin-list {
padding: 0 24px;
max-height: 5rem;
overflow-y: auto;
width: 5rem;
}
.coin-active-box .coin-list .coin-list-item {
box-sizing: border-box;
padding: 16px 0;
border-bottom: 1px dashed #EAEAEA;
display: flex;
align-items: flex-start;
gap: 16px;
}
.coin-active-box .coin-list .coin-list-item:nth-last-of-type(1) {
border-bottom: none;
}
.coin-active-box .coin-list .coin-list-item .coin-item-icon {
border-radius: 50%;
background-color: #F3F3F3;
padding: 11px;
font-size: 0;
}
.coin-active-box .coin-list .coin-list-item .coin-item-icon .item-icon {
width: 24px;
height: 24px;
}
.coin-active-box .coin-list .coin-list-item .coin-item-content {
flex: 1;
}
.coin-active-box .coin-list .coin-list-item .coin-item-content .coin-item-content-top {
display: flex;
align-items: center;
justify-content: space-between;
column-gap: 0.3rem;
}
.coin-active-box .coin-list .coin-list-item .coin-item-content .coin-item-content-top .coin-item-content-title-text {
font-size: 14px;
font-weight: 600;
color: #2B2B2B;
}
.coin-active-box .coin-list .coin-list-item .coin-item-content .coin-item-content-top .coin-item-content-time {
font-size: 12px;
color: #A2A2A2;
}
.coin-active-box .coin-list .coin-list-item .coin-item-content .coin-item-content-desc {
text-align: right;
margin-top: 8px;
font-size: 14px;
cursor: pointer;
color: var(--color-primary);
}
.coin-active-box .coin-list .coin-list-item .coin-item-content .coin-item-detail .coin-detail-active-limit,
.coin-active-box .coin-list .coin-list-item .coin-item-content .coin-item-detail .coin-detail-use-limit {
font-size: 14px;
font-weight: 600;
color: #2B2B2B;
margin-bottom: 5px;
}
.coin-active-box .coin-list .coin-list-item .coin-item-content .coin-item-detail .coin-detail-use-limit {
margin-top: 10px;
}

View File

@@ -0,0 +1,467 @@
const coinActive = {
template: /* html*/ `
<el-popover placement="left-start" v-model="active_show" trigger="click" popper-class="coin-active-popover"
@show="visbleShow" v-if="home_show_coin_activity == 1">
<div class="coin-active-btn" slot="reference">
<div class="coin-active-trigger" role="button" :aria-label="lang.coin_text71 + coin_name">
<div class="trigger-icon" aria-hidden="true">
<svg class="icon-svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none"
version="1.1" width="16" height="16" viewBox="0 0 16 16">
<defs>
<clipPath id="master_svg0_783_42616">
<rect x="0" y="0" width="16" height="16" rx="0" />
</clipPath>
</defs>
<g clip-path="url(#master_svg0_783_42616)">
<g>
<path
d="M13.6663418125,13.347250952929688L13.6663418125,6.6666717529296875L2.3330078125,6.6666717529296875L2.3330078125,13.347250952929688C2.3330078125,14.075946852929688,2.9237326425,14.666671752929688,3.6524287125,14.666671752929688L12.3469208125,14.666671752929688C13.0756168125,14.666671752929688,13.6663418125,14.075946852929688,13.6663418125,13.347250952929688"
fill="var(--color-primary)" fill-opacity="1" style="mix-blend-mode:passthrough" />
<path
d="M2.4862143825,14.513465452929687Q2.9692757125,14.996526752929688,3.6524287125,14.996526752929688L12.3469208125,14.996526752929688Q13.0300728125,14.996526752929688,13.5131348125,14.513465452929687Q13.9961968125,14.030403652929689,13.9961968125,13.347250952929688L13.9961968125,6.6666717529296875Q13.9961968125,6.634183853929687,13.9898588125,6.602320201929688Q13.9835208125,6.570456549929688,13.9710878125,6.540441642929688Q13.9586548125,6.510426742929687,13.9406048125,6.483414042929687Q13.9225558125,6.456401352929688,13.8995838125,6.4334289129296875Q13.8766118125,6.410456512929687,13.8495988125,6.392407182929688Q13.8225858125,6.374357882929687,13.7925708125,6.361925302929688Q13.7625558125,6.349492732929687,13.7306918125,6.3431546429296874Q13.6988298125,6.336816552929688,13.6663418125,6.336816552929688L2.3330078125,6.336816552929688Q2.3005199135,6.336816552929688,2.2686562615,6.3431546429296874Q2.2367926095,6.349492732929687,2.2067777025,6.361925302929688Q2.1767628025,6.374357882929687,2.1497501025,6.392407182929688Q2.1227374125,6.410456512929687,2.0997649725,6.4334289129296875Q2.0767925725,6.456401352929688,2.0587432425,6.483414052929687Q2.0406939425,6.510426742929687,2.0282613625,6.540441642929688Q2.0158287925,6.570456549929688,2.0094907025,6.602320201929688Q2.0031526125,6.634183853929687,2.0031526125,6.6666717529296875L2.0031526125,13.347250952929688Q2.0031526125,14.030403652929689,2.4862143825,14.513465452929687ZM12.3469208125,14.336816752929687L3.6524287125,14.336816752929687Q3.2425374424999998,14.336816752929687,2.9527000825,14.046979452929687Q2.6628630125,13.757142552929688,2.6628630125,13.347250952929688L2.6628630125,6.996526952929687L13.3364868125,6.996526952929687L13.3364868125,13.347250952929688Q13.3364868125,13.757141552929689,13.0466488125,14.046979452929687Q12.7568108125,14.336816752929687,12.3469208125,14.336816752929687Z"
fill-rule="evenodd" fill="var(--color-primary)" fill-opacity="1" style="mix-blend-mode:passthrough" />
</g>
<g>
<path
d="M8.65971041,6.6666717529296875L8.660000029999999,6.6666717529296875L8.66000301,6.006668742929688L7.33999699,6.006668742929688L7.33999997,6.6666717529296875L7.34028959,6.6666717529296875L7.34028959,14.333338752929688L7.33999997,14.333338752929688L7.33999699,14.993341452929688L8.66000301,14.993341452929688L8.660000029999999,14.333338752929688L8.65971041,14.333338752929688L8.65971041,6.6666717529296875Z"
fill-rule="evenodd" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough" />
</g>
<g>
<rect x="1.3330078125" y="4" width="13.333333969116211" height="2.6666667461395264"
rx="1.3194208145141602" fill="var(--color-primary)" fill-opacity="1"
style="mix-blend-mode:passthrough" />
<path
d="M1.0031526125,5.3472459L1.0031526125,5.3194208Q1.0031526125,4.6362685,1.4862143825,4.15320657Q1.9692761325,3.6701448,2.6524286125,3.6701448L13.3469218125,3.6701448Q14.0300738125,3.6701448,14.5131358125,4.1532066499999996Q14.9961968125,4.6362685,14.9961968125,5.3194208L14.9961968125,5.3472459Q14.9961968125,6.0303984,14.5131358125,6.5134602Q14.0300738125,6.996521899999999,13.3469218125,6.996521899999999L2.6524286125,6.996521899999999Q1.9692763725,6.996521899999999,1.4862143825,6.5134602Q1.0031526125,6.0303984,1.0031526125,5.3472459ZM1.6628630125,5.3472459Q1.6628630725,5.7571373,1.9527000825,6.0469744Q2.2425371425,6.3368115,2.6524286125,6.3368115L13.3469218125,6.3368115Q13.7568118125,6.3368115,14.0466488125,6.0469744Q14.3364858125,5.7571373,14.3364858125,5.3472459L14.3364858125,5.3194208Q14.3364858125,4.90952921,14.0466488125,4.61969221Q13.7568118125,4.3298552,13.3469218125,4.3298552L2.6524286125,4.3298552Q2.2425370225,4.32985526,1.9527000825,4.61969227Q1.6628630125,4.90952933,1.6628630125,5.3194208L1.6628630125,5.3472459Z"
fill="var(--color-primary)" fill-opacity="1" style="mix-blend-mode:passthrough" />
</g>
<g>
<path
d="M4.8803459725,1.8136378270703126Q4.7811028325,1.7201073770703126,4.7270553125,1.5949034670703126Q4.6730077825,1.4696996070703126,4.6730077825,1.3333282470703125Q4.6730078425,1.2683239280703125,4.6856895725,1.2045686570703125Q4.6983712925,1.1408133670703124,4.7232474125,1.0807571970703125Q4.7481235225,1.0207010470703124,4.7842379225,0.9666519170703125Q4.8203523725,0.9126027870703125,4.8663173625,0.8666377970703125Q4.9122823525,0.8206728070703125,4.9663314825,0.7845583570703125Q5.0203806125,0.7484439570703125,5.0804367625,0.7235678470703125Q5.1404929325,0.6986917270703125,5.2042482225,0.6860100070703125Q5.2680034935,0.6733282770703125,5.3330078125,0.6733282170703125Q5.4693791725,0.6733282170703125,5.5945830325,0.7273757470703125Q5.7197869425,0.7814232670703125,5.8133173925,0.8806664070703125L7.9996745125,3.0670235470703124L10.1860304125,0.8806677470703125Q10.2795610125,0.7814239870703125,10.4047651125,0.7273761070703125Q10.5299692125,0.6733282170703125,10.6663413125,0.6733282170703125Q10.7313456125,0.6733282770703125,10.7951012125,0.6860100070703125Q10.858856212500001,0.6986917270703125,10.9189119125,0.7235678470703125Q10.978967712500001,0.7484439570703125,11.0330171125,0.7845583570703125Q11.0870657125,0.8206728070703125,11.1330309125,0.8666377970703125Q11.1789961125,0.9126027870703125,11.2151103125,0.9666519170703125Q11.2512250125,1.0207010470703124,11.276101112500001,1.0807571970703125Q11.300977212500001,1.1408133670703124,11.3136592125,1.2045686570703125Q11.3263407125,1.2683239280703125,11.3263411125,1.3333282470703125Q11.3263416125,1.4696971770703124,11.272295912499999,1.5948992370703126Q11.2182503125,1.7201012670703126,11.1190100125,1.8136314470703125L8.4661603125,4.466480747070312Q8.4202154125,4.512425447070313,8.3661899125,4.548523947070313Q8.3121643125,4.5846223470703125,8.2521345125,4.609487547070312Q8.1921048125,4.634352647070313,8.1283774125,4.6470289470703126Q8.0646500125,4.659705147070312,7.9996743125,4.659705147070312Q7.9346986125,4.659705147070312,7.8709710125,4.6470289470703126Q7.807243812499999,4.634352647070313,7.7472138125,4.609487547070312Q7.687184112500001,4.5846223470703125,7.6331589125,4.548523947070313Q7.5791335125,4.512425447070313,7.533188812500001,4.466480747070312L4.8803459725,1.8136378270703126Z"
fill-rule="evenodd" fill="var(--color-primary)" fill-opacity="1" style="mix-blend-mode:passthrough" />
</g>
</g>
</svg>
</div>
<div class="trigger-text">{{lang.coin_text71}}{{coin_name}}</div>
</div>
</div>
<div class="coin-active-box" v-loading="loading">
<div class="coin-title">
{{coin_name}}{{lang.coin_text72}}
</div>
<template v-if="product_id || host_id">
<el-tabs v-model="activeTab" @tab-click="handleTabClick" class="coin-active-tabs">
<el-tab-pane :label="lang.coin_text76" name="current">
</el-tab-pane>
<el-tab-pane :label="lang.coin_text77" name="all">
</el-tab-pane>
</el-tabs>
</template>
<div class="coin-list">
<template v-if="coinActiveList.length === 0 && !loading">
<el-empty :description="lang.order_text15"></el-empty>
</template>
<template v-else>
<div class="coin-list-item" v-for="item in coinActiveList" :key="item.id">
<div class="coin-item-icon">
<svg class="item-icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
fill="none" version="1.1" width="24" height="24" viewBox="0 0 24 24">
<defs>
<clipPath id="master_svg0_783_43860">
<rect x="0" y="0" width="24" height="24" rx="0" />
</clipPath>
</defs>
<g clip-path="url(#master_svg0_783_43860)">
<g>
<path
d="M18.708139875,3.64892128671875C16.746531875000002,-0.54723961328125,13.474185875,0.72000699871875,12.082462875,1.87477598671875C11.011678675,4.83818338671875,8.189241875,9.15282158671875,6.912997675,10.94046338671875C9.057568575000001,10.38557438671875,10.998181375,13.12552738671875,11.700040775,14.56673738671875C11.914497375,13.85588038671875,16.461587875,6.99325228671875,18.708139875,3.64892128671875ZM18.132253875,5.46505788671875C18.618157875,6.10842898671875,20.269326875,7.25570008671875,22.995780875,6.69931168671875C20.890203875,8.653420486718751,16.440591875000003,12.96355938671875,15.489781875,14.56823938671875C14.762426875,14.65822038671875,13.100760875,14.78419538671875,12.274424875,14.56823938671875C13.549170875,12.33068538671875,16.509577874999998,7.37867598671875,18.132253875,5.46505788671875ZM4.994881375,16.10993138671875C4.4579884750000005,16.31688838671875,3.546170875,17.24520338671875,4.189542275,19.31178838671875C4.432493975,20.01964738671875,5.246830675,21.54184538671875,6.565067275,21.97375638671875C5.7852234750000004,22.15371938671875,3.999080375,21.87327738671875,3.079764475,19.31178838671875C3.040772275,19.27279838671875,2.236932905,15.64802238671875,4.994881375,16.10993138671875ZM4.802920074999999,13.40747038671875L5.990683075,11.44136338671875C7.151450675,11.05444038671875,9.804419075,11.17891638671875,11.121155775,14.75869938671875C12.485883875,15.16961838671875,15.930694875,15.53854338671875,18.780124875,13.71640938671875C18.499681875,14.07633538671875,17.860808875,14.85768038671875,17.554869875,15.10513038671875C18.001779875,15.16961838671875,19.002080875,15.33608438671875,19.429494875,15.49055438671875C18.601659875,16.06943838671875,16.245629875,17.21970938671875,13.457687875,17.18821538671875C14.083063875,17.54814338671875,15.501779875,18.26050038671875,16.176644875,18.22900538671875C15.882704875,18.28149638671875,15.203340875,18.38347638671875,14.835913875,18.38347638671875C15.000878875,18.70591138671875,15.432794875,19.40927138671875,15.831713875,19.65822238671875C14.222536875,19.46326038671875,10.746232075,18.33848538671875,9.703939875,15.37507838671875C9.270526875,14.34628438671875,7.682343975,12.51365138671875,4.802920074999999,13.40747038671875ZM12.115457875,18.77339738671875C11.748030675,18.68041638671875,11.094161975,18.06703738671875,10.813717875,17.77009738671875C10.629254375,18.14052438671875,10.072865475,19.80219038671875,9.817916875,20.58653438671875C9.297520675000001,22.03674538671875,8.553669975,22.81059038671875,8.247730775,23.01605038671875L9.511978175,23.13302638671875C9.601959274999999,22.63812438671875,11.286123275,20.02115038671875,12.115457875,18.77339738671875ZM9.092061475000001,15.06763738671875C7.469387075,12.87807538671875,5.072865675,13.58893538671875,4.075565575000001,14.21880838671875L2.469386425,16.34088338671875C2.008978501,17.20471038671875,1.971486052,18.24400338671875,2.008978501,18.65492038671875C2.592361685,22.20471238671875,5.290322574999999,23.19451338671875,6.566566975,23.24550438671875C8.129253875,23.18401538671875,9.107058075000001,21.39337338671875,9.401000475,20.50705138671875C9.553969875,19.88917338671875,10.153849575,18.19301438671875,10.434293775,17.42066738671875C9.699440975,16.77279638671875,9.234533775,15.58203438671875,9.093561675,15.06763638671875L9.092061475000001,15.06763738671875ZM8.019775875,19.58173538671875C7.215936675,16.367880386718753,5.422295775,15.60003138671875,4.255528975,15.61203038671875C3.8776046749999997,15.61503038671875,3.510177975,15.76200138671875,3.232733275,16.01694938671875C2.706338465,16.50585138671875,2.527874235,17.12222838671875,2.506878435,17.42066938671875C2.401899485,19.74220438671875,3.448690075,21.19691238671875,4.496980475,21.99625238671875C5.303818975,22.61263038671875,6.490082275,23.00105238671875,7.280423675,22.36067938671875C8.070765975,21.72031038671875,8.136752575,20.38407538671875,8.019775875,19.58173538671875Z"
fill="var(--color-primary)" fill-opacity="1" style="mix-blend-mode:passthrough" />
</g>
</g>
</svg>
</div>
<div class="coin-item-content">
<div class="coin-item-content-top">
<div class="coin-item-content-title-text">
{{ item.name }}
</div>
<div class="coin-item-content-time">
<template v-if="item.begin_time == 0 ">
{{lang.coin_text73}} - {{ item.end_time | formateTime }}
</template>
<template v-else>
{{ item.begin_time | formateTime }} - {{ item.end_time | formateTime }}
</template>
</div>
</div>
<div class="coin-item-content-desc">
<span @click="item.show_desc = !item.show_desc">{{ lang.coin_text78 }}</span>
<i class="el-icon-arrow-down" v-show="!item.show_desc" @click="item.show_desc = !item.show_desc"></i>
<i class="el-icon-arrow-up" v-show="item.show_desc" @click="item.show_desc = !item.show_desc"></i>
</div>
<div class="coin-item-detail" v-if="item.show_desc">
<div class="coin-detail-active-limit">
{{lang.coin_text79}}
</div>
<div class="coin-active-detail">
<template v-if="item.type === 'default'">
<!-- 公开送 -->
<p class="coin-detail-main-desc">
{{coin_name}}{{lang.coin_text80}}
</p>
</template>
<template v-if="item.type === 'property'">
<!-- 属性送 -->
<p class="coin-detail-main-desc">
<p>{{lang.coin_text81}}{{item.property_type === 'register' ? lang.coin_text82 : lang.coin_text83}}
</p>
<p>{{lang.coin_text84}}<template v-if="item.property_strategy === 'signal'">
{{lang.coin_text85}}
</template>
<template v-else>
{{lang.coin_text86}}{{item.property_cycle_num}}{{item.property_cycle_unit === 'day' ? lang.coin_text87 : lang.coin_text88}}{{lang.coin_text89}}
</template>
</p>
<p>{{lang.coin_text90}}{{coin_name}}{{lang.coin_text91}}
<template v-if="item.property_type === 'register'">
{{item.property_amount}}{{coin_name}}
</template>
<template v-else>
<p v-for="(property_item,index) in item.property_level" :key="index">
{{property_item.level_id_arr.map(item => item.name).join('、')}}{{lang.coin_text92}}{{property_item.award}}{{coin_name}}
</p>
</template>
</p>
</p>
</template>
<template v-if="item.type === 'recharge'">
<!-- 充值送 -->
<p>{{lang.coin_text93}}{{lang.coin_text94}}</p>
<p>{{lang.coin_text90}}{{coin_name}}{{lang.coin_text91}}</p>
<template v-if="item.recharge_type === 'gradient'">
<p v-for="recharge_item in item.recharge_return" :key="recharge_item.amount">
{{lang.coin_text94}}{{recharge_item.amount}}{{lang.coin_text92}}{{recharge_item.award}}{{coin_name}}
</p>
</template>
<template v-else>
<p>{{lang.coin_text94}}{{item.recharge_min}}{{lang.coin_text95}}{{lang.coin_text96}}
{{item.recharge_proportion}}% {{lang.coin_text97}}{{coin_name}}
</p>
</template>
</template>
<template v-if="item.type === 'total_consume'">
<!-- 累计消费送 -->
<p>{{lang.coin_text81}}{{lang.coin_text98}}</p>
<p v-if="item.total_consume_type === 'total'">{{lang.coin_text99}}{{lang.coin_text100}}</p>
<p v-if="item.total_consume_type === 'stage'">{{lang.coin_text99}}{{lang.coin_text101}}</p>
<p>{{lang.coin_text102}}{{lang.coin_text103}}</p>
<p>{{lang.coin_text90}}{{coin_name}}{{lang.coin_text91}}</p>
<template v-if="item.total_consume_type === 'total'">
<p v-for="total_consume_item in item.total_consume_total_return" :key="total_consume_item.amount">
{{lang.coin_text104}}{{total_consume_item.amount}}{{lang.coin_text105}}{{total_consume_item.award}}{{coin_name}}
</p>
</template>
<template v-else>
<p v-for="total_consume_item in item.total_consume_stage_return" :key="total_consume_item.amount">
{{lang.coin_text106}}{{total_consume_item.amount}}{{lang.coin_text105}}{{total_consume_item.award}}{{coin_name}}
</p>
</template>
</template>
<template v-if="item.type === 'scene'">
<!-- 场景送 -->
<p v-for="(action,index) in calculateSceneRange(item.rules)" :key="index">{{action}}</p>
<p>{{lang.coin_text102}}
<span v-if="item.gift_strategy === 'rule_once'">{{lang.coin_text145}}</span>
<span v-if="item.gift_strategy === 'activity_once'">{{lang.coin_text146}}</span>
<span v-if="item.gift_strategy === 'multiple'">{{lang.coin_text147}}</span>
</p>
</template>
<template v-if="item.type === 'single_consume'">
<!-- 单笔消费送 -->
<p>{{lang.coin_text93}}{{lang.coin_text98}}</p>
{{lang.coin_text107}}<template v-if="item.single_consume_able_product_ids_arr?.length > 0">
<span v-for="(product_item,index) in item.single_consume_able_product_ids_arr"
:key="product_item.id">
<a :href="'/cart/goods.htm?id=' + product_item.id" target="_blank"
style="color: var(--color-primary);">{{product_item.name}}
<span v-if="index !== item.single_consume_able_product_ids_arr.length - 1">、</span>
</a>
</span>
</template>
<template v-else>
{{lang.coin_text108}}
</template>
</p>
<p>{{lang.coin_text99}}{{lang.coin_text101}}</p>
<p>{{lang.coin_text102}}{{lang.coin_text103}}</p>
<p>{{lang.coin_text90}}{{coin_name}}{{lang.coin_text91}}</p>
<p v-for="single_consume_item in item.single_consume_return" :key="single_consume_item.amount">
{{lang.coin_text109}}{{single_consume_item.amount}}{{lang.coin_text105}}{{single_consume_item.award}}{{coin_name}}
</p>
</template>
<template v-if="item.type === 'order'">
<!-- 订购送 -->
<p>{{lang.coin_text81}}{{lang.coin_text110}}</p>
<p>{{lang.coin_text99}}{{lang.coin_text111}}</p>
<p v-if="item.order_same_once === 1">{{lang.coin_text102}}{{lang.coin_text112}}</p>
<p>{{lang.coin_text90}}{{coin_name}}{{lang.coin_text91}}</p>
<p v-for="(order_item,index) in item.order_return" :key="index">
{{lang.coin_text110}}
<template v-if="order_item.product_ids_arr?.length > 0">
<span v-for="(product_item,indexs) in order_item.product_ids_arr" :key="product_item.id">
<a :href="'/cart/goods.htm?id=' + product_item.id" target="_blank"
style="color: var(--color-primary);">{{product_item.name}}</a>
<span v-if="indexs !== order_item.product_ids_arr.length - 1">、</span>
</span>
</template>
<template v-else>
{{lang.coin_text108}}
</template>
{{lang.coin_text105}}{{order_item.award}}{{coin_name}}
</p>
</template>
<template v-if="item.type === 'full_gift'">
<!-- 每满送 -->
<p>{{lang.coin_text93}}
<template v-if="item.full_gift_send_scene_order == 1">
{{lang.coin_text110}}<template
v-if="item.full_gift_send_scene_renew == 1 || item.full_gift_send_scene_upgrade == 1">、</template>
</template>
<template v-if="item.full_gift_send_scene_renew == 1">
{{lang.coin_text113}}<template v-if="item.full_gift_send_scene_upgrade == 1">、</template>
</template>
<template v-if="item.full_gift_send_scene_upgrade == 1">
{{lang.coin_text114}}
</template>
</p>
<p>{{lang.coin_text115}}
<template v-if="item.full_gift_client_limit_open == 0">
{{lang.coin_text116}}
</template>
<template v-else>
{{item.full_gift_client_limit_type === 'client' ? lang.coin_text117 : lang.coin_text118}}
</template>
</p>
<p>{{lang.coin_text107}}<template v-if="item.full_gift_product_only_defence == 1">
({{lang.coin_text119}})
</template>
<template v-if="item.full_gift_send_product_ids_arr?.length > 0">
<span v-for="(product_item,index) in item.full_gift_send_product_ids_arr" :key="product_item.id">
<a :href="'/cart/goods.htm?id=' + product_item.id" target="_blank"
style="color: var(--color-primary);">{{product_item.name}}
<span v-if="index !== item.full_gift_send_product_ids_arr.length - 1">、</span>
</a>
</span>
</template>
<template v-else>
{{lang.coin_text108}}
</template>
</p>
<p>
{{lang.coin_text102}}{{lang.coin_text120}}{{item.full_gift_payment_threshold>0?item.full_gift_payment_threshold:item.full_gift_threshold_amount}}
<template v-if="item.full_gift_same_once == 1">{{lang.coin_text121}}</template>
</p>
<p>{{lang.coin_text90}}{{coin_name}}{{lang.coin_text91}}</p>
<p>
{{lang.coin_text122}}{{item.full_gift_threshold_amount}}{{lang.coin_text105}}{{item.full_gift_gift_amount}}{{coin_name}}
</p>
</template>
</div>
<div class="coin-detail-use-limit">{{coin_name}}{{lang.coin_text123}}</div>
<p>{{lang.coin_text124}}
<template v-if="item.type == 'default'">
{{item.effective_start_time | formateTime}}
</template>
<template v-else-if="item.immediately_effective == 1 || item.effective_time == 0">
{{lang.coin_text125}}
</template>
<template v-else>
{{lang.coin_text126}}{{item.effective_time}}{{item.effective_time_unit === 'day' ? lang.coin_text87 : lang.coin_text88}}{{lang.coin_text127}}
</template>
</p>
<p>{{lang.coin_text128}}
<template v-if="item.type == 'default'">
{{item.effective_end_time | formateTime}}
</template>
<template v-else-if="item.unlimit_efficient === 0">
{{item.efficient_time }} {{item.efficient_time_unit === 'day' ? lang.coin_text87 : lang.coin_text88}}
</template>
<template v-else>
{{lang.coin_text129}}
</template>
</p>
<p v-if="item.certification_can_use === 1">{{lang.coin_text48}}</p>
<p v-if="item.with_event_promotion_use === 0">{{lang.coin_text49}}</p>
<p v-if="item.with_promo_code_use === 0">{{lang.coin_text50}}</p>
<p v-if="item.with_client_level_use === 0">{{lang.coin_text51}}</p>
<p v-if="item.with_voucher_use === 0">{{lang.coin_text52}}</p>
<template
v-if="item.order_use_limit == 'product' || item.single_consume_use_limit == 'product' || item.full_gift_use_limit == 'product' || item.type == 'default' || item.type == 'property' || item.type == 'recharge' || item.type == 'total_consume'">
<p v-if="item.product_ids_arr?.length > 0">
{{lang.coin_text47}}
<span v-for="(el,index) in item.product_ids_arr" :key="el.id">
<a :href="'/cart/goods.htm?id=' + el.id" target="_blank"
style="color: var(--color-primary);">{{el.name}}</a>
<span v-if="index !== item.product_ids_arr.length - 1">、</span>
</span>
</p>
<p v-else>
{{lang.coin_text74}}
</p>
</template>
<p
v-if="item.order_use_limit == 'host' || item.single_consume_use_limit == 'host' || item.full_gift_use_limit == 'host'">
{{lang.coin_text130}}{{coin_name}}{{lang.coin_text131}}
</p>
<p v-if="item.product_only_defence == 1">{{lang.coin_text65}}</p>
<p
v-if="item.order_available == 1 || item.upgrade_available == 1 || item.renew_available == 1 || item.demand_available == 1">
{{lang.coin_text132}}
<template v-if="item.order_available == 1">
{{lang.coin_text133}}<span
v-if="item.upgrade_available == 1 || item.renew_available == 1 || item.demand_available == 1">、</span>
</template>
<template v-if="item.renew_available == 1">
{{lang.coin_text134}}<span v-if="item.upgrade_available == 1 || item.demand_available == 1">、</span>
</template>
<template v-if="item.upgrade_available == 1">
{{lang.coin_text135}}<span v-if="item.demand_available == 1">、</span>
</template>
<template v-if="item.demand_available == 1">
{{lang.coin_text136}}
</template>
</p>
<p v-if="item.cycle_limit === 1 ">
{{lang.coin_text5}}<span v-for="(cycle_item,index) in item.cycle"
:key="cycle_item">{{lang[cycle_item]}}
<span v-if="index !== item.cycle.length - 1">、</span></span>
</p>
</div>
</div>
</div>
</template>
</div>
</div>
</el-popover>
`,
data() {
return {
commonData: {},
coin_name: "",
coinClientInfo: {},
coinActiveList: [],
loading: false,
home_show_coin_activity: 0,
activeTab: "current",
product_id: 0,
host_id: 0,
active_show: false,
init: true,
};
},
filters: {
formateTime(time) {
if (time && time !== 0) {
return formateDate(time * 1000, "YYYY-MM-DD HH:mm");
} else {
return lang.voucher_effective;
}
},
},
created() {
if (!havePlugin("Coin")) {
return;
}
// 加载css
if (
!document.querySelector(
'link[href="' + url + 'components/coinActive/coinActive.css"]'
)
) {
const link = document.createElement("link");
link.rel = "stylesheet";
link.href = `${url}components/coinActive/coinActive.css`;
document.head.appendChild(link);
}
this.commonData =
JSON.parse(localStorage.getItem("common_set_before")) || {};
this.getCoinInfo();
},
methods: {
visbleShow() {
this.coinActiveList.forEach((item) => {
item.show_desc = false;
});
this.getCoinActiveList();
},
handleTabClick() {
this.getCoinActiveList();
},
// 计算场景送的活动范围
calculateSceneRange(item) {
const allActions = [];
item.forEach(rule => {
rule.notice_actions_arr.forEach(action => {
if (action.name === 'host_renew') {
allActions.push(`${rule.trigger_products[0] ? rule.trigger_products[0].name : lang.coin_text108}${action.name_lang}${lang.coin_text105}${rule.amount}${this.coin_name}`);
} else if (action.name === 'order_pay') {
allActions.push(`${rule.trigger_products[0] ? rule.trigger_products[0].name : lang.coin_text108}${action.name_lang}${lang.coin_text105}${rule.amount}${this.coin_name}`);
} else {
if (!allActions.includes(action)) {
allActions.push(`${action.name_lang}${lang.coin_text105}${rule.amount}${this.coin_name}`);
}
}
});
});
return allActions;
},
setProductId() {
const nowUrl = location.href.split("/").pop();
const pageRouter =
nowUrl.indexOf("?") !== -1 ? nowUrl.split("?")[0] : nowUrl;
if (pageRouter == "goods.htm") {
this.product_id = getUrlParams().id;
} else if (pageRouter == "productdetail.htm") {
this.host_id = getUrlParams().id;
}
},
async getCoinInfo() {
try {
const res = await apiCoinClientCoupon();
this.coin_name = res.data.data.name;
this.coinClientInfo = res.data.data;
this.home_show_coin_activity = res.data.data.home_show_coin_activity;
if (this.home_show_coin_activity == 1) {
this.setProductId();
await this.getCoinActiveList(true);
}
} catch (error) {
console.log(error);
}
},
async getCoinActiveList(isInit = false) {
this.loading = true;
const params = {};
const isProduct = this.activeTab === "current" && this.product_id;
const isHost = this.activeTab === "current" && this.host_id;
params.product_id = isProduct ? this.product_id : undefined;
params.host_id = isHost ? this.host_id : undefined;
const isGoodPage = isProduct || isHost;
await apiCoinActiveList(params)
.then((res) => {
this.coinActiveList = res.data.data.list.map((item) => {
item.show_desc = false;
return item;
});
if (isGoodPage && isInit === true) {
this.active_show = this.coinActiveList.length > 0;
}
})
.finally(() => {
this.loading = false;
});
},
},
};

View File

@@ -0,0 +1,190 @@
// 变量定义
@primary-color: var(--color-primary);
@text-primary: #2B2B2B;
@text-secondary: #A2A2A2;
@border-color: #EAEAEA;
.coin-active-popover {
padding: 0 !important;
}
// 主容器
.coin-active-btn {
position: fixed;
right: 3px;
top: 35vh;
z-index: 99;
// 悬浮触发按钮
.coin-active-trigger {
position: relative;
display: inline-flex;
flex-direction: column;
align-items: center;
gap: 8px;
padding: 8px 5px;
border-radius: 99px;
color: #fff;
background: @primary-color;
cursor: pointer;
user-select: none;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(26, 97, 214, 0.2);
&:hover {
transform: scale(1.05);
box-shadow: 0 4px 16px rgba(26, 97, 214, 0.4);
/* 由于@primary-color是CSS变量less的lighten函数无法直接处理改为使用filter实现亮色效果 */
background: @primary-color;
filter: brightness(1.08);
.trigger-icon {
transform: rotate(5deg);
background-color: #f8f9ff;
}
.trigger-text {
letter-spacing: 6px;
}
}
.trigger-icon {
font-size: 0;
padding: 7px;
border-radius: 50%;
background-color: #fff;
transition: all 0.3s ease;
.icon-svg {
width: 16px;
height: 16px;
}
}
.trigger-text {
writing-mode: vertical-rl;
text-orientation: mixed;
letter-spacing: 5px;
font-size: 12px;
transition: all 0.3s ease;
}
}
}
.coin-active-box {
.coin-title {
padding: 16px 24px;
font-size: 16px;
font-weight: 600;
color: @text-primary;
border-bottom: 1px solid @border-color;
}
.coin-active-tabs {
.el-tabs__nav-wrap {
padding-left: 24px;
}
}
.coin-list {
padding: 0 24px;
max-height: 5rem;
overflow-y: auto;
width: 5rem;
.coin-list-item {
box-sizing: border-box;
padding: 16px 0;
border-bottom: 1px dashed @border-color;
display: flex;
align-items: flex-start;
gap: 16px;
&:nth-last-of-type(1) {
border-bottom: none;
}
.coin-item-icon {
border-radius: 50%;
background-color: #F3F3F3;
padding: 11px;
font-size: 0;
.item-icon {
width: 24px;
height: 24px;
}
}
.coin-item-content {
flex: 1;
.coin-item-content-top {
display: flex;
align-items: center;
justify-content: space-between;
column-gap: .3rem;
.coin-item-content-title-text {
font-size: 14px;
font-weight: 600;
color: @text-primary;
}
.coin-item-content-time {
font-size: 12px;
color: @text-secondary;
}
}
.coin-item-content-desc {
text-align: right;
margin-top: 8px;
font-size: 14px;
cursor: pointer;
color: @primary-color;
}
.coin-item-detail {
.coin-detail-active-limit,
.coin-detail-use-limit {
font-size: 14px;
font-weight: 600;
color: @text-primary;
margin-bottom: 5px;
}
.coin-detail-use-limit {
margin-top: 10px;
}
}
}
// &:hover {
// cursor: pointer;
// .coin-item-content-top {
// .coin-item-content-title-text {
// color: @primary-color;
// }
// }
// .coin-item-content {
// background-color: #F3F3F3;
// }
// }
}
}
}

View File

@@ -0,0 +1,46 @@
// 父组件执行该组件的countDown() 实现倒计时
const countDownButton = {
template: `
<el-button :class="myClass" v-loading="loading" type="primary" :disabled="!flag">{{ flag? name : num + lang.second_try}}</el-button>
`,
data() {
return {
num: 60,
flag: true,
timer: null,
};
},
props: {
myClass: {
type: String,
default: "count-down-btn",
},
name: {
type: String,
default: lang.send_code,
},
loading: {
type: Boolean,
default: false,
},
},
created() {},
methods: {
countDown() {
this.flag = false;
this.num = --this.num;
this.timer = setInterval(() => {
if (this.num > 1) {
this.flag = false;
this.num = --this.num;
} else {
clearInterval(this.timer);
this.timer = null;
this.flag = true;
this.num = 60;
this.$emit("countend");
}
}, 1000);
},
},
};

View File

@@ -0,0 +1,84 @@
const creditNotice = {
template: /*html*/ `
<el-dialog width="7rem" :visible.sync="isShow" @close="diaClose" custom-class="credit-notice-dialog"
:show-close="false">
<div class="credit-content">
<div class="credit-title">
<span class="title-text">{{lang.coin_text67}}</span>
<span class="close-btn" @click="diaClose">
<i class="el-icon-close"></i>
</span>
</div>
<div class="credit-box">
<div class="credit-open">
{{lang.coin_text66}}
<el-switch v-model="credit_remind" :active-value="1" :inactive-value="0">
</el-switch>
</div>
<div class="credit-input">
{{lang.coin_text68}}
<el-input-number v-model="credit_remind_amount" :min="0" :precision="2" :step="0.01" :controls="false"
:placeholder="lang.coin_text70">
</el-input-number>
{{lang.coin_text69}}
</div>
</div>
<div class="credit-footer">
<el-button class="cancel-btn" @click="diaClose">{{lang.referral_btn7}}</el-button>
<el-button type="primary" @click="submitCredit" :loading="submitLoading">{{lang.referral_btn6}}</el-button>
</div>
</div>
</el-dialog>
`,
data() {
return {
isShow: false,
credit_remind_amount: undefined,
submitLoading: false,
credit_remind: 0,
coinClientCoupon: {},
};
},
methods: {
open() {
this.isShow = true;
accountDetail().then((res) => {
const {credit_remind, credit_remind_amount} = res.data.data.account;
this.credit_remind = credit_remind;
this.credit_remind_amount = credit_remind_amount;
});
},
diaClose() {
this.amount = undefined;
this.isShow = false;
},
submitCredit() {
if (!this.credit_remind_amount) {
return this.$message.error(lang.coin_text70);
}
this.submitLoading = true;
apiCreateCreditRemind({
credit_remind: this.credit_remind,
credit_remind_amount: this.credit_remind_amount,
})
.then((res) => {
if (res.data.status === 200) {
this.$message.success(res.data.msg);
this.diaClose();
this.$emit("success", {
credit_remind: this.credit_remind,
credit_remind_amount: this.credit_remind_amount,
});
}
})
.catch((error) => {
this.$message.error(error.data.msg);
})
.finally(() => {
this.submitLoading = false;
});
},
},
};

View File

@@ -0,0 +1,165 @@
const customGoods = {
template: `
<div class="custom-goods-box">
<el-form :model="ruleForm" ref="ruleForm" :label-position="labelPosition" :label-width="labelWidth" :rules="rules" :hide-required-asterisk="hideRequiredAsterisk">
<el-form-item :prop="item.id + ''" :label="item.field_name" v-for="item in customFieldList" :key="item.id">
<el-select v-model="ruleForm[item.id]" :placeholder="item.description" v-if="item.field_type === 'dropdown'">
<el-option :label="items" :value="items" v-for="(items,indexs) in calcFieldOption(item.field_option)" :key="indexs"></el-option>
</el-select>
<el-checkbox true-label="1" false-label="0" :label="item.field_name" v-model="ruleForm[item.id]"
v-else-if="item.field_type === 'tickbox'" :disabled="item.is_required === 1">
{{item.description}}
</el-checkbox>
<el-input type="textarea" v-model="ruleForm[item.id]" v-else-if="item.field_type === 'textarea'" :placeholder="item.description"></el-input>
<span v-html="item.explain_content" v-else-if="item.field_type === 'explain'" class="custom-explain"></span>
<el-input v-model="ruleForm[item.id]" :placeholder="item.description" v-else></el-input>
</el-form-item>
</el-form>
</div>
`,
data() {
return {
ruleForm: {},
rules: {},
customFieldList: [],
};
},
components: {},
props: {
id: {
type: Number | String,
required: true,
},
self_defined_field: {
type: Object,
required: true,
},
is_show_custom: {
type: Boolean,
required: false,
default: false,
},
labelWidth: {
type: String,
required: false,
default: "auto",
},
labelPosition: {
// :value right/left/top
type: String,
required: false,
default: "left",
},
hideRequiredAsterisk: {
type: Boolean,
required: false,
default: false,
},
},
created() {
this.getCustomFields();
},
watch: {},
mounted() {},
methods: {
getSelfDefinedField() {
let isValid = false;
this.$refs.ruleForm.validate((valid) => {
if (valid) {
this.$emit("update:self_defined_field", this.ruleForm);
isValid = true;
} else {
this.$message.error(lang.custom_goods_text3);
}
});
return isValid;
},
getCustomFields() {
customFieldsProduct(this.id).then((res) => {
const obj = {};
const rules = {};
this.customFieldList = res.data.data.data.map((item) => {
if (item.field_type === "dropdown" && item.is_required === 1) {
obj[item.id + ""] = this.calcFieldOption(item.field_option)[0];
} else {
obj[item.id + ""] = item.field_type === "tickbox" ? 0 : "";
if (item.field_type === "tickbox" && item.is_required === 1) {
obj[item.id + ""] = "1";
}
}
rules[item.id + ""] = this.calcRules(item);
return item;
});
this.$set(this, "ruleForm", obj);
if (Object.keys(this.self_defined_field).length > 0) {
// 设置默认值
for (let i = 0; i < this.customFieldList.length; i++) {
const item = this.customFieldList[i];
if (this.self_defined_field[item.id + ""] !== undefined) {
this.ruleForm[item.id + ""] =
this.self_defined_field[item.id + ""];
}
}
}
this.$emit("update:is_show_custom", this.customFieldList.length > 0);
this.$set(this, "rules", rules);
});
},
calcValidator(item, value, callback, regexpr) {
if (item.is_required === 1 && value === "") {
callback(new Error(lang.custom_goods_text1));
return;
}
if (
value !== "" &&
!new RegExp(regexpr.replace(/^\/|\/$/g, "")).test(value)
) {
callback(new Error(lang.custom_goods_text2));
return;
}
callback();
},
calcRules(item) {
const rules = [];
if (item.is_required === 1) {
rules.push({
required: true,
message: lang.custom_goods_text1,
trigger: ["blur", "change"],
});
} else {
rules.push({
required: false,
trigger: ["blur", "change"],
});
}
if (item.field_type === "link") {
// 类型为链接时需要校验url格式 http://www.baidu.com
const url =
"/^(((ht|f)tps?)://)?([^!@#$%^&*?.s-]([^!@#$%^&*?.s]{0,63}[^!@#$%^&*?.s])?.)+[a-z]{2,6}/?/";
rules.push({
validator: (rule, value, callback) =>
this.calcValidator(item, value, callback, url),
trigger: ["blur", "change"],
});
}
if (
item.field_type !== "dropdown" &&
item.field_type !== "tickbox" &&
item.regexpr
) {
rules.push({
validator: (rule, value, callback) =>
this.calcValidator(item, value, callback, item.regexpr),
trigger: ["blur", "change"],
});
}
return rules;
},
calcFieldOption(item) {
return item.split(",");
},
},
};

View File

@@ -0,0 +1,170 @@
const discountCode = {
template: `
<div>
<el-popover placement="bottom" trigger="click" v-model="visibleShow" class="discount-popover" :visible-arrow="false">
<div class="discount-content">
<div class="close-btn-img" @click="closePopver">
<img src="${url}/img/common/close_icon.png" alt="">
</div>
<div>
<el-input class="discount-input" clearable v-model="discountInputVal" :placeholder="lang.login_text10" maxlength="9"></el-input>
<el-button class="discount-btn" :loading="isLoading" @click="handelApplyPromoCode">{{lang.shoppingCar_tip_text9}}</el-button>
</div>
</div>
<span slot="reference" class="discount-text">{{lang.shoppingCar_tip_text12}}</span>
</el-popover>
</div>
`,
data () {
return {
discountInputVal: "", // 输入框Value
visibleShow: false, // 是否显示优惠弹窗
isLoading: false, // 确认按钮loading
discountMoney: 0, // 抵扣金额
};
},
components: {},
props: {
scene: {
type: String, // new新购,renew续费,upgrade升降级
required: true,
},
isNeedPromo_code: {
//优惠码
type: Boolean,
required: false,
default: true,
},
host_id: {
// 产品ID
type: String | Number,
required: false,
},
product_id: {
// 商品ID
type: String | Number,
required: true,
},
qty: {
// 数量 新购时必传
type: String | Number,
required: false,
},
amount: {
//单价
type: String | Number,
required: true,
},
billing_cycle_time: {
// 周期时间
type: String | Number,
required: true,
},
shopping_index: {
// 购物车位置
type: Number,
required: false,
},
multiple_product: {
// 订购页面多商品同时使用优惠
type: Array,
default: () => [],
required: false,
}
},
created () { },
mounted () { },
methods: {
closePopver () {
this.visibleShow = false;
this.discountInputVal = "";
},
handelApplyPromoCode () {
if (this.isNeedPromo_code && this.discountInputVal.length === 0) {
this.$message.warning(lang.shoppingCar_tip_text13);
return;
}
this.isLoading = true;
if (this.multiple_product.length === 0) {
const params = {
scene: this.scene,
product_id: this.product_id,
amount: this.amount,
billing_cycle_time: this.billing_cycle_time,
promo_code: this.discountInputVal,
};
if (this.qty) {
params.qty = this.qty;
}
if (this.host_id) {
params.host_id = this.host_id;
}
this.getCountMoney(params);
} else {
// 批量使用优惠码,目前只针对订购
let discountArr = [];
this.multiple_product.forEach(item => {
const params = {
scene: this.scene,
product_id: item.product_id,
amount: item.totalPrice,
billing_cycle_time: this.billing_cycle_time,
promo_code: this.discountInputVal,
};
if (item.qty) {
params.qty = item.qty;
}
if (this.host_id) {
params.host_id = this.host_id;
}
discountArr.push(applyPromoCode(params));
});
Promise.all(discountArr).then(res => {
this.discountMoney = res.reduce((all, cur) => {
all += Number(cur.data.data.discount);
return all;
}, 0);
this.$emit(
"get-discount",
this.discountMoney,
this.discountInputVal
);
this.$message.success(lang.shoppingCar_tip_text14);
this.closePopver();
}).catch(err => {
this.$message.error(err.data.msg);
}).finally(() => {
this.isLoading = false;
});
}
},
getCountMoney (params) {
applyPromoCode(params)
.then((res) => {
this.discountMoney = Number(res.data.data.discount);
if (this.shopping_index || this.shopping_index === 0) {
this.$emit(
"get-discount",
this.discountMoney,
this.discountInputVal,
this.shopping_index
);
} else {
this.$emit(
"get-discount",
this.discountMoney,
this.discountInputVal
);
}
this.$message.success(lang.shoppingCar_tip_text14);
this.closePopver();
})
.catch((err) => {
this.$message.error(err.data.msg);
})
.finally(() => {
this.isLoading = false;
});
},
},
};

View File

@@ -0,0 +1,171 @@
const eventCode = {
template: `
<div>
<el-popover placement="bottom" trigger="click" v-model="visibleShow" :visible-arrow="false" v-if="!disabled && options.length !==0">
<div class="event-content">
<el-select class="event-select" @change="changePromotion" v-model="eventId"
:placeholder="lang.goods_text5" >
<el-option v-for="item in options" :key="item.id" :value="item.id" :label="calcLebal(item)">
</el-option>
</el-select>
</div>
<span slot="reference" class="event-text">{{showText}}<i class="el-icon-caret-bottom"></i></span>
</el-popover>
<span class="event-text" v-if="disabled && options.length > 0">{{showText}}</span>
</div>
`,
data() {
return {
eventId: "", // 活动促销ID
options: [],
discount: 0,
visibleShow: false,
nowParams: {},
};
},
computed: {
showText() {
return this.eventId
? this.calcLebal(
this.options.filter((item) => item.id === this.eventId)[0]
)
: lang.goods_text6;
},
},
watch: {
billing_cycle_time() {
this.getEventList();
},
amount() {
this.getEventList();
},
qty() {
this.getEventList();
},
},
props: {
id: {
type: String | Number,
},
// 场景中的所有商品ID
product_id: {
type: String | Number,
required: true,
},
// 需要支付的原价格
amount: {
type: Number | String,
required: true,
},
// 购买数量
qty: {
type: Number | String,
default: 1,
required: true,
},
//周期时间
billing_cycle_time: {
type: Number | String,
required: true,
},
disabled: {
type: Boolean,
default: false,
},
},
created() {
this.getEventList();
},
mounted() {},
methods: {
calcLebal(item) {
if (!item) {
return "";
}
return item.type === "percent"
? lang.goods_text1 + " " + item.value + "%"
: item.type === "reduce"
? lang.goods_text2 + item.full + lang.goods_text3 + " " + item.value
: lang.goods_text6;
},
getEventList() {
const params = {
id: this.product_id,
billing_cycle_time: this.billing_cycle_time,
qty: this.qty,
amount: this.amount,
billing_cycle_time: this.billing_cycle_time,
};
if (
JSON.stringify(this.nowParams) == JSON.stringify(params) ||
!this.billing_cycle_time
) {
// 没有变化 防止重复请求
return;
}
this.nowParams = params;
eventPromotion(params)
.then((res) => {
const event_list = res.data.list;
const isTop =
res.data.addon_event_promotion_does_not_participate === "top";
if (event_list.length > 0) {
const no_select = {
id: 0,
type: "no",
value: 0,
full: 0,
};
if (isTop) {
event_list.unshift(no_select);
} else {
event_list.push(no_select);
}
this.options = event_list;
// 默认选中处理
if (
this.id &&
this.options.map((item) => item.id).includes(this.id)
) {
this.eventId = this.id;
} else {
this.eventId = this.options[0]?.id || "";
}
}
})
.catch((err) => {
this.$message.error(err.data.msg);
})
.finally(() => {
this.changePromotion();
});
},
changePromotion() {
this.$emit("change", {
discount: this.eventId ? this.discount : 0,
id: this.eventId ? this.eventId : "",
});
// applyEventPromotion({
// event_promotion: this.eventId,
// product_id: this.product_id,
// qty: this.qty,
// amount: this.amount,
// billing_cycle_time: this.billing_cycle_time,
// })
// .then((res) => {
// this.discount = res.data.data.discount;
// })
// .catch((err) => {
// this.discount = 0;
// console.log(err.data);
// })
// .finally(() => {
// });
},
clearPromotion() {
this.discount = 0;
this.$emit("change", { discount: this.discount, id: this.eventId });
},
},
};

View File

@@ -0,0 +1,362 @@
const flowPacket = {
template:
`
<div style="flex: 1">
<el-dialog :visible.sync="showPackage && packageList.length > 0" custom-class="common-package-dialog" :loading="packageLoading">
<i class="el-icon-close" @click="cancleDialog"></i>
<div class="dialog-title">
{{lang.buy_package}}
</div>
<!-- Radio 筛选:限时/不限时 -->
<div class="filter-radio" v-if="hasLimitTime || hasUnlimitedTime">
<el-radio-group v-model="filterType" @change="onFilterTypeChange">
<el-radio :label="0" v-if="hasLimitTime">{{lang.limit_time_flow}}</el-radio>
<el-radio :label="1" v-if="hasUnlimitedTime">{{lang.unlimited_traffic}}</el-radio>
</el-radio-group>
</div>
<div class="con">
<div class="items">
<div class="p-item" v-for="item in filteredPackageList" :key="item.id"
:class="{active: item.id === curPackageId}" @click="choosePackage(item)">
<p class="price">{{currencyPrefix}}{{getDisplayPrice(item) | filterMoney}}</p>
<p class="tit">
{{item.name}}
<template v-if="item.billing_mode === 0">
{{item.capacity}}G
</template>
<template v-else>{{item.min_capacity}}-{{item.max_capacity}}G</template>
</p>
<i class="el-icon-check"></i>
</div>
</div>
<div class="slider-container" v-if="showSlider">
<el-slider v-model="sliderValueComputed" :min="sliderMin" :max="sliderMax" :marks="sliderMarks"
show-input>
</el-slider>
</div>
</div>
<div class="dialog-footer">
<el-button class="btn-ok" @click="handlerPackage"
:loading="submitLoading">{{lang.ticket_btn6}}</el-button>
<el-button class="btn-no" @click="cancleDialog">{{lang.finance_btn7}}</el-button>
</div>
</el-dialog>
<!-- 弹窗模式下的触发按钮 -->
<el-button v-if="showFlowPacketList && displayMode === 'dialog' && hasFlow && lineType === 'flow'"
@click="openFlowListDialog" type="primary" size="small">
{{lang.flow_packet_list}}
</el-button>
<!-- 流量包列表 -->
<component
:is="listWrapper"
v-bind="listWrapperProps"
v-on="listWrapperEvents"
v-if="showFlowPacketList && hasFlow && lineType === 'flow' && (displayMode === 'inline' || showFlowListDialog)">
<div class="dialog-title" v-if="displayMode === 'dialog'">{{lang.flow_packet_list}}</div>
<div class="dialog-main">
<el-table :data="flowPacketList" v-loading="flowPacketLoading" style="width: 100%">
<el-table-column prop="id" :label="lang.flow_packet_id" min-width="100"></el-table-column>
<el-table-column prop="name" :label="lang.flow_packet_name" min-width="150"></el-table-column>
<el-table-column :label="lang.flow_packet_create_time" min-width="180">
<template slot-scope="scope">
<span>{{scope.row.create_time | formateTime}}</span>
</template>
</el-table-column>
<el-table-column :label="lang.flow_packet_size" min-width="150">
<template slot-scope="scope">
{{scope.row.size}}GB
</template>
</el-table-column>
<el-table-column :label="lang.flow_packet_used" min-width="120">
<template slot-scope="scope">
{{scope.row.used || 0}}GB
</template>
</el-table-column>
<el-table-column :label="lang.flow_packet_expire_time" min-width="180">
<template slot-scope="scope">
<span v-if="scope.row.expire_time === 0">/</span>
<span v-else>{{scope.row.expire_time | formateTime}}</span>
</template>
</el-table-column>
<el-table-column :label="lang.flow_packet_status" min-width="100">
<template slot-scope="scope">
<el-tag v-if="scope.row.status === 1" type="success" size="small">{{lang.flow_packet_status_valid}}</el-tag>
<el-tag v-else type="warning" size="small">{{lang.flow_packet_status_invalid}}</el-tag>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<pagination :page-data="flowParams" v-if="flowParams.total > 0"
@sizechange="handleFlowPageSizeChange" @currentchange="handleFlowPageChange">
</pagination>
</div>
</component>
</div>
`,
mixins: [mixin],
components: {
pagination
},
filters: {
filterMoney (money) {
if (isNaN(money)) {
return '0.00';
} else {
const temp = `${money}`.split('.');
return parseInt(temp[0]).toLocaleString() + '.' + (temp[1] || '00');
}
},
formateTime (time) {
if (time && time !== 0) {
return formateDate(time * 1000);
} else {
return "--";
}
},
},
data () {
return {
hasFlow: true,
packageLoading: false,
submitLoading: false,
packageList: [],
curPackageId: '',
currencyPrefix: JSON.parse(localStorage.getItem("common_set_before")).currency_prefix,
filterType: 0, // 1: 不限时, 0: 限时
sliderValue: 10, // 滑动条的值
showSlider: false, // 是否显示滑动条
sliderMin: 0,
sliderMax: 100,
flowPacketList: [],
flowPacketLoading: false,
flowParams: {
page: 1,
limit: 20,
pageSizes: [20, 50, 100],
total: 0
},
showFlowListDialog: false, // 控制流量包列表弹窗
};
},
props: {
id: {
type: Number | String,
required: true,
},
showPackage: {
type: Boolean
},
module: {
type: String,
default: 'mf_cloud_mysql'
},
lineType: {
type: String,
default: 'bw'
},
displayMode: {
type: String,
default: 'inline' // inline | dialog (401使用dialog)
}
},
mounted () {
this.hasFlow = this.addons_js_arr.includes('FlowPacket');
if (this.hasFlow) {
this.getPackageList();
this.getFlowPacketList();
}
},
computed: {
showFlowPacketList() {
const hiddenModules = ['mf_dcim', 'remf_dcim'];
return !hiddenModules.includes(this.module);
},
// 处理滑动条空值问题
sliderValueComputed: {
get () {
return this.sliderValue === '' || this.sliderValue === null ? this.sliderMin : this.sliderValue;
},
set (val) {
this.sliderValue = val;
}
},
// 根据 filterType 筛选流量包
filteredPackageList () {
return this.packageList.filter(item => item.long_term_valid === this.filterType);
},
// 获取当前选中的流量包
currentPackage () {
return this.packageList.find(item => item.id === this.curPackageId);
},
// 滑动条标记
sliderMarks () {
return {
[this.sliderMin]: this.sliderMin + 'GB',
[this.sliderMax]: this.sliderMax + 'GB'
};
},
// 是否有限时流量包
hasLimitTime () {
return this.packageList.some(item => item.long_term_valid === 0);
},
// 是否有不限时流量包
hasUnlimitedTime () {
return this.packageList.some(item => item.long_term_valid === 1);
},
// 动态容器组件
listWrapper () {
return this.displayMode === 'dialog' ? 'el-dialog' : 'div';
},
// 动态容器属性
listWrapperProps () {
if (this.displayMode === 'dialog') {
return {
width: "1200px",
visible: this.showFlowListDialog,
'custom-class': 'flow-list-dialog'
};
}
return {
class: 'flow-packet-list'
};
},
// 动态容器事件
listWrapperEvents () {
if (this.displayMode === 'dialog') {
return {
'update:visible': (val) => { this.showFlowListDialog = val; }
};
}
return {};
},
},
watch: {
// 监听筛选类型变化,自动选中第一个
filteredPackageList (newList) {
if (newList.length > 0) {
this.curPackageId = newList[0].id;
this.choosePackage(newList[0]);
}
}
},
methods: {
async getPackageList () {
try {
this.packageLoading = true;
const res = await getFlowPacket({
id: this.id,
page: 1,
limit: 9999,
});
this.packageList = res.data.data.list;
if (this.packageList.length === 0) {
this.$emit('cancledialog', false);
return;
}
// 根据数据设置默认 filterType 和选中流量包
const limitTimeList = this.packageList.filter(item => item.long_term_valid === 0);
const unlimitedTimeList = this.packageList.filter(item => item.long_term_valid === 1);
// 优先选限时,只有不限时时才选不限时
if (limitTimeList.length > 0) {
this.filterType = 0;
this.curPackageId = limitTimeList[0].id;
this.choosePackage(limitTimeList[0]);
} else if (unlimitedTimeList.length > 0) {
this.filterType = 1;
this.curPackageId = unlimitedTimeList[0].id;
this.choosePackage(unlimitedTimeList[0]);
}
this.packageLoading = false;
} catch (error) {
this.packageLoading = false;
}
},
choosePackage (item) {
this.curPackageId = item.id;
// 如果 billing_mode = 1显示滑动条
if (item.billing_mode === 1) {
this.showSlider = true;
this.sliderMin = item.min_capacity;
this.sliderMax = item.max_capacity;
this.sliderValue = item.min_capacity;
} else {
this.showSlider = false;
}
},
async handlerPackage () {
try {
this.submitLoading = true;
const params = {
id: this.id,
flow_packet_id: this.curPackageId,
};
// 如果是范围流量包,传递滑动条的值
if (this.currentPackage && this.currentPackage.billing_mode === 1) {
params.selected_capacity = this.sliderValue;
}
const res = await buyFlowPacket(params);
this.$emit('sendpackid', res.data.data.id);
this.submitLoading = false;
} catch (error) {
this.submitLoading = false;
this.$message.error(error.data.msg);
}
},
cancleDialog () {
this.$emit('cancledialog', false);
},
// 获取流量包列表
async getFlowPacketList () {
// mf_dcim 和 remf_dcim 不请求流量包列表
if (!this.showFlowPacketList) return;
try {
this.flowPacketLoading = true;
const res = await getFlowPacketByModule(this.module, {
id: this.id,
...this.flowParams
});
this.flowPacketList = res.data.data.list || [];
this.flowParams.total = res.data.data.count || 0;
this.flowPacketLoading = false;
} catch (error) {
this.flowPacketLoading = false;
this.$message.error(error.data.msg);
}
},
// 分页变化
handleFlowPageChange (page) {
this.flowParams.page = page;
this.getFlowPacketList();
},
handleFlowPageSizeChange (e) {
this.flowParams.limit = e;
this.getFlowPacketList();
},
// 计算显示价格
getDisplayPrice (item) {
let price;
if (item.billing_mode === 0) {
price = item.price;
} else {
if (item.id === this.curPackageId) {
price = this.sliderValue * item.price;
} else {
price = item.min_capacity * item.price;
}
}
return Math.round(price * 100) / 100;
},
// 切换筛选类型时移除焦点
onFilterTypeChange () {
document.activeElement?.blur();
},
// 打开流量包列表弹窗
openFlowListDialog () {
this.showFlowListDialog = true;
this.getFlowPacketList();
}
},
};

View File

@@ -0,0 +1,47 @@
/* 处理产品转移中的状态 */
const hostStatus = {
template:
`
<div>
<div class="host-is-transfer" v-if="isTransferring">{{lang.host_transferring}}</div>
<slot v-else></slot>
</div>
`,
data () {
return {
isTransferring: false,
};
},
props: {
id: {
type: Number | String,
required: true,
default: null,
},
status: {
type: String,
required: true,
default: '',
}
},
methods: {
async getHostTransferStatus () {
try {
const res = await hostIsTransfer({ id: this.id * 1 });
const transferring = res.data.data.status;
// 状态为 Active 且 transferring === 1 的时候显示转移中
this.isTransferring = transferring && this.status === 'Active';
} catch (error) {
this.$message.error(error.data.msg);
}
}
},
mounted () {
const arr = JSON.parse(
document.querySelector("#addons_js").getAttribute("addons_js")
).map((item) => {
return item.name;
});
arr.includes("HostTransfer") && this.getHostTransferStatus();
}
};

View File

@@ -0,0 +1,827 @@
const ipDefase = {
template: /*html*/ `
<div>
<div class="ip-defase-box">
<div class="fire-list-search">
<el-select v-model="params.status" clearable :placeholder="lang.ipDefase_text1">
<el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
<el-input v-model="params.keywords" clearable @keyup.enter.native="search" :placeholder="lang.ipDefase_text2">
</el-input>
<el-button type="primary" @click="search">{{lang.ipDefase_text3}}</el-button>
</div>
<el-table v-loading="tabeLoading" :data="productList" @sort-change="sortChange"
style="width: 100%; margin:0.2rem 0;">
<el-table-column prop="id" label="ID">
</el-table-column>
<el-table-column prop="host_ip" :label="lang.ipDefase_text4" sortable>
</el-table-column>
<el-table-column prop="defense_peak" :label="lang.ipDefase_text14">
<template slot-scope="{row}">
<span>{{row.defense_peak || '--'}}</span>
</template>
</el-table-column>
<el-table-column prop="due_time" :label="lang.index_text13">
<template slot-scope="{row}">
<span>{{row.due_time | formateTime }}</span>
</template>
</el-table-column>
<el-table-column prop="status" :label="lang.ipDefase_text5" width="200">
<template slot-scope="{row}">
<template v-if="row.statusLoading">
<i class="primary-icon el-icon-loading"></i>
</template>
<template v-else>
{{getStatusLabel(row.status)}}
<i @click="getProductStatus(row)" class="primary-icon el-icon-refresh"></i>
</template>
</template>
</el-table-column>
<el-table-column prop="op" :label="lang.ipDefase_text6" width="160" fixed="right">
<template slot-scope="{row}">
<div class="operation">
<el-button type="text" @click="showRenew(row)" v-if="row.sub_host_id">{{lang.cloud_re_btn}}</el-button>
<el-button type="text" @click="openUpgradeDialog(row)">{{lang.ipDefase_text7}}</el-button>
</div>
</template>
</el-table-column>
</el-table>
<pagination :page-data="params" @sizechange="sizeChange" @currentchange="currentChange"></pagination>
</div>
<div class="upgrade-dialog" v-if="isShowUpgrade">
<el-dialog width="9.5rem" :visible.sync="isShowUpgrade" :show-close="false" @close="upgradeDgClose">
<div class="dialog-title">{{lang.ipDefase_text11}}</div>
<div class="dialog-main">
<div class="ipDefase-now-info">
<div class="now-text">{{lang.ipDefase_text15}}{{ipInfo.host_ip}}</div>
<div class="now-text">{{lang.ipDefase_text16}}{{getStatusLabel(ipInfo.status)}}</div>
<div class="now-text">{{lang.ipDefase_text17}}{{ipInfo.defense_peak || '--'}}</div>
</div>
<el-form ref="ipDefaseForm" label-position="left" label-width="100px" hide-required-asterisk>
<!-- 防御 -->
<el-form-item :label="lang.ipDefase_text12">
<el-radio-group v-model="defenseName">
<el-radio-button :label="c.desc" v-for="(c,cInd) in defenceList" :key="cInd" @click.native="chooseDefence($event,c)">
</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item :label="lang.cart_tip_text12" v-if="upDurationList.length > 0">
<el-radio-group v-model="upParams.duration_id">
<el-radio-button :label="c.id" v-for="c in upDurationList" :key="c.id" @click.native="changeDuration($event,c)">
{{c.name_show}}
</el-radio-button>
</el-radio-group>
</el-form-item>
</el-form>
</div>
<div class="dialog-footer">
<div class="footer-top">
<div class="money-text">{{lang.ipDefase_text13}}</div>
<div class="money" v-loading="upgradePriceLoading">
<span class="money-num">{{commonData.currency_prefix }} {{ upParams.totalPrice | filterMoney}}</span>
<el-popover placement="top-start" width="200" trigger="hover"
v-if="isShowLevel || (isShowPromo && upParams.isUseDiscountCode)">
<div class="show-config-list">
<p v-if="isShowLevel">
{{lang.shoppingCar_tip_text2}}{{commonData.currency_prefix}}
{{ upParams.clDiscount | filterMoney }}
</p>
<p v-if="isShowPromo && upParams.isUseDiscountCode">
{{lang.shoppingCar_tip_text4}}{{commonData.currency_prefix}}
{{ upParams.code_discount | filterMoney}}
</p>
</div>
<i class="el-icon-warning-outline total-icon" slot="reference"></i>
</el-popover>
<p class="original-price" v-if="upParams.totalPrice != upParams.original_price">
{{commonData.currency_prefix}} {{ upParams.original_price |
filterMoney}}
</p>
<div class="code-box" v-if="false">
<!-- 优惠码 -->
<discount-code v-show="isShowPromo && !upParams.customfield.promo_code "
@get-discount="getUpDiscount(arguments)" scene="upgrade" :product_id="product_id"
:amount="upParams.original_price" :billing_cycle_time="billing_cycle_time">
</discount-code>
</div>
<div class="code-number-text">
<div class="discount-codeNumber" v-show="upParams.customfield.promo_code">
{{ upParams.customfield.promo_code }}<i class="el-icon-circle-close remove-discountCode"
@click="removeUpDiscountCode()"></i>
</div>
</div>
</div>
</div>
<div class="footer-bottom">
<el-button class="btn-ok" @click="upgradeSub" :loading="loading4">
{{lang.security_btn5}}
</el-button>
<div class="btn-no" @click="upgradeDgClose">
{{lang.security_btn6}}
</div>
</div>
</div>
</el-dialog>
</div>
<!-- 续费弹窗 -->
<div class="renew-dialog">
<el-dialog width="6.9rem" :visible.sync="isShowRenew" :show-close="false" @close="renewDgClose">
<div class="dialog-title">{{lang.common_cloud_title10}}</div>
<div class="dialog-main">
<div class="renew-content">
<div class="renew-item" :class="renewActiveId==item.id?'renew-active':''" v-for="item in renewPageData"
:key="item.id" @click="renewItemChange(item)">
<div class="item-top">{{item.customfield?.multi_language?.billing_cycle || item.billing_cycle}}</div>
<div class="item-bottom" v-if="isShowPromo && renewParams.isUseDiscountCode">
{{commonData.currency_prefix + item.base_price}}
</div>
<div class="item-bottom" v-else>
{{commonData.currency_prefix + item.price}}
</div>
<div class="item-origin-price"
v-if="item.price*1 < item.base_price*1 && !renewParams.isUseDiscountCode">
{{commonData.currency_prefix + item.base_price}}
</div>
<i class="el-icon-check check" v-show="renewActiveId==item.id"></i>
</div>
</div>
<div class="pay-content">
<div class="pay-price">
<div class="money" v-loading="renewLoading">
<span class="text">{{lang.common_cloud_label11}}:</span>
<span>{{commonData.currency_prefix}}{{renewParams.totalPrice |
filterMoney}}</span>
<el-popover placement="top-start" width="200" trigger="hover"
v-if="(isShowLevel && renewParams.clDiscount*1 > 0) || (isShowPromo && renewParams.isUseDiscountCode)">
<div class="show-config-list">
<p v-if="isShowLevel && renewParams.clDiscount*1 > 0">
{{lang.shoppingCar_tip_text2}}{{commonData.currency_prefix}}
{{ renewParams.clDiscount | filterMoney}}
</p>
<p v-if="isShowPromo && renewParams.isUseDiscountCode">
{{lang.shoppingCar_tip_text4}}{{commonData.currency_prefix}}
{{ renewParams.code_discount | filterMoney }}
</p>
</div>
<i class="el-icon-warning-outline total-icon" slot="reference"></i>
</el-popover>
<p class="original-price"
v-if="renewParams.customfield.promo_code && renewParams.totalPrice != renewParams.base_price">
{{commonData.currency_prefix}} {{ renewParams.base_price |
filterMoney}}
</p>
<p class="original-price"
v-if="!renewParams.customfield.promo_code && renewParams.totalPrice != renewParams.original_price">
{{commonData.currency_prefix}} {{ renewParams.original_price
| filterMoney}}
</p>
<div class="code-box" v-if="false">
<!-- 优惠码 -->
<discount-code v-show="isShowPromo && !renewParams.customfield.promo_code"
@get-discount="getRenewDiscount(arguments)" scene="renew" :product_id="product_id"
:amount="renewParams.base_price" :billing_cycle_time="renewParams.duration">
</discount-code>
</div>
<div class="code-number-text">
<div class="discount-codeNumber" v-show="renewParams.customfield.promo_code">
{{ renewParams.customfield.promo_code }}<i class="el-icon-circle-close remove-discountCode"
@click="removeRenewDiscountCode()"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="dialog-footer">
<el-button class="btn-ok" @click="subRenew" :loading="subRenewLoading">
{{lang.common_cloud_btn30}}
</el-button>
<el-button class="btn-no" @click="renewDgClose">
{{lang.common_cloud_btn29}}
</el-button>
</div>
</el-dialog>
</div>
<pay-dialog ref="ipDefasePayDialog" @payok="paySuccess" @paycancel="payCancel"></pay-dialog>
</div>
`,
data() {
return {
commonData: {},
params: {
keywords: "",
status: "",
page: 1,
limit: 20,
pageSizes: [20, 50, 100],
total: 0,
orderby: "id",
sort: "desc",
},
tabeLoading: false,
statusOptions: [
{label: lang.ipDefase_text8, value: 0},
{label: lang.ipDefase_text9, value: 1},
{label: lang.ipDefase_text10, value: 2},
],
productList: [],
isShowUpgrade: false,
isShowLevel: false,
isShowPromo: false,
upParams: {
customfield: {
promo_code: "", // 优惠码
},
duration_id: "", // 周期
isUseDiscountCode: false, // 是否使用优惠码
clDiscount: 0, // 用户等级折扣价
code_discount: 0, // 优惠码折扣价
original_price: 0, // 原价
totalPrice: 0, // 现价
},
upgradePriceLoading: false,
loading4: false,
defenceList: [],
peak_defence: "",
defenseName: "",
ipInfo: {},
ip: "",
isInit: true,
isShowRenew: false, // 续费的总计loading
renewBtnLoading: false, // 续费按钮的loading
// 续费页面信息
renewPageData: [],
renewPriceList: [],
renewActiveId: "",
renewLoading: false, // 续费计算折扣loading
// 续费参数
renewParams: {
id: 0, //默认选中的续费id
isUseDiscountCode: false, // 是否使用优惠码
customfield: {
promo_code: "", // 优惠码
},
duration: "", // 周期
billing_cycle: "", // 周期时间
clDiscount: 0, // 用户等级折扣价
code_discount: 0, // 优惠码折扣价
original_price: 0, // 原价
base_price: 0,
totalPrice: 0, // 现价
},
sub_host_id: 0,
subRenewLoading: false,
upDurationList: [],
};
},
components: {
payDialog,
pagination,
discountCode,
cashBack,
},
props: {
id: {
// 产品id
type: String | Number,
required: true,
},
// 场景中的所有商品ID
product_id: {
type: String | Number,
required: true,
},
billing_cycle_time: {
type: String | Number,
required: true,
},
module: {
type: String,
required: true,
},
listmode: {
type: String,
required: true,
},
showip: {
type: String,
required: false,
},
},
watch: {
renewParams: {
handler() {
let n = 0;
// l:当前周期的续费价格
if (this.isShowPromo && this.renewParams.customfield.promo_code) {
// n: 算出来的价格
n =
(this.renewParams.base_price * 1000 -
this.renewParams.clDiscount * 1000 -
this.renewParams.code_discount * 1000) /
1000 >
0
? (this.renewParams.base_price * 1000 -
this.renewParams.clDiscount * 1000 -
this.renewParams.code_discount * 1000) /
1000
: 0;
} else {
// n: 算出来的价格
n =
(this.renewParams.original_price * 1000 -
this.renewParams.clDiscount * 1000 -
this.renewParams.code_discount * 1000) /
1000 >
0
? (this.renewParams.original_price * 1000 -
this.renewParams.clDiscount * 1000 -
this.renewParams.code_discount * 1000) /
1000
: 0;
}
let t = n;
// 如果当前周期和选择的周期相同,则和当前周期对比价格
// if (
// this.hostData.billing_cycle_time === this.renewParams.duration ||
// this.hostData.billing_cycle_name === this.renewParams.billing_cycle
// ) {
// // 谁大取谁
// t = n;
// }
this.renewParams.totalPrice =
t * 1000 > 0 ? ((t * 1000) / 1000).toFixed(2) : 0;
},
immediate: true,
deep: true,
},
},
created() {
this.getProductList();
this.getCommonData();
},
mounted() {
this.isShowLevel = havePlugin("IdcsmartClientLevel");
this.isShowPromo = havePlugin("PromoCode");
},
filters: {
formateTime(time) {
if (time && time !== 0) {
return formateDate(time * 1000);
} else {
return "--";
}
},
// 返回剩余到期时间
formateDueDay(time) {
return Math.floor((time * 1000 - Date.now()) / (1000 * 60 * 60 * 24));
},
filterMoney(money) {
if (isNaN(money) || money * 1 < 0) {
return "0.00";
} else {
return formatNuberFiexd(money);
}
},
},
methods: {
paySuccess(e) {
this.isShowUpgrade = false;
this.$emit("success");
setTimeout(() => {
this.getProductList();
}, 1000);
},
// 取消支付回调
payCancel(e) {},
openUpgradeDialog(row) {
this.ipInfo = row;
this.ip = row.host_ip;
this.getUpConfig();
},
getUpConfig() {
apiGetUpDefenceConfig(
{
id: this.id,
ip: this.ip,
},
this.module
)
.then((res) => {
this.defenceList = res.data.data?.defence || [];
this.peak_defence = res.data.data?.current_defence
? res.data.data?.current_defence
: res.data.data?.defence[0]?.value || "";
this.defenseName = this.defenceList.find(
(item) => item.value === this.peak_defence
)?.desc;
this.isShowUpgrade = true;
this.getCycleList();
})
.catch((err) => {
err.data.msg && this.$message.error(err.data.msg);
});
},
chooseDefence(e, c) {
this.defenseName = c.desc;
this.peak_defence = c.value;
this.getCycleList();
e.preventDefault();
},
changeDuration(e, c) {
this.upParams.duration_id = c.id;
this.getCycleList();
e.preventDefault();
},
// 关闭升降级弹窗
upgradeDgClose() {
this.isShowUpgrade = false;
this.removeUpDiscountCode(false);
},
// 升降级使用优惠码
getUpDiscount(data) {
this.upParams.customfield.promo_code = data[1];
this.upParams.isUseDiscountCode = true;
this.upParams.code_discount = Number(data[0]);
this.getCycleList();
},
// 移除升降级优惠码
removeUpDiscountCode(flag = true) {
this.upParams.isUseDiscountCode = false;
this.upParams.customfield.promo_code = "";
this.upParams.code_discount = 0;
if (flag) {
this.getCycleList();
}
},
// 获取升降级价格
getCycleList() {
this.upgradePriceLoading = true;
const params = {
id: this.id,
ip: this.ip,
peak_defence: this.peak_defence,
duration_id: this.upParams.duration_id,
};
apiCalculateUpDefencePrice(params, this.module)
.then(async (res) => {
if (res.data.status == 200) {
this.upDurationList = res.data.data.durations;
if (!this.upParams.duration_id) {
this.upParams.duration_id =
res.data.data.duration_id || this.upDurationList[0]?.id;
}
if (res.data.data.durations?.length === 0) {
this.upParams.duration_id = "";
}
let price = res.data.data.price; // 当前产品的价格
if (price < 0) {
this.upParams.original_price = 0;
this.upParams.totalPrice = 0;
this.upgradePriceLoading = false;
return;
}
this.upParams.original_price = price;
this.upParams.totalPrice = price;
// 开启了等级优惠
if (this.isShowLevel) {
await clientLevelAmount({id: this.product_id, amount: price})
.then((ress) => {
this.upParams.clDiscount = Number(ress.data.data.discount);
})
.catch(() => {
this.upParams.clDiscount = 0;
});
}
// 开启了优惠码插件
if (this.isShowPromo) {
// 更新优惠码
await applyPromoCode({
// 开启了优惠券
scene: "upgrade",
product_id: this.product_id,
amount: price,
billing_cycle_time: this.billing_cycle_time,
promo_code: this.upParams.customfield.promo_code,
host_id: this.id,
})
.then((resss) => {
this.upParams.isUseDiscountCode = true;
this.upParams.code_discount = Number(
resss.data.data.discount
);
})
.catch((err) => {
this.upParams.isUseDiscountCode = false;
this.upParams.customfield.promo_code = "";
this.upParams.code_discount = 0;
this.$message.error(err.data.msg);
});
}
this.upParams.totalPrice =
(price * 1000 -
this.upParams.clDiscount * 1000 -
this.upParams.code_discount * 1000) /
1000 >
0
? (
(price * 1000 -
this.upParams.clDiscount * 1000 -
this.upParams.code_discount * 1000) /
1000
).toFixed(2)
: 0;
this.upgradePriceLoading = false;
} else {
this.upParams.original_price = 0;
this.upParams.clDiscount = 0;
this.upParams.isUseDiscountCode = false;
this.upParams.customfield.promo_code = "";
this.upParams.code_discount = 0;
this.upParams.totalPrice = 0;
this.upgradePriceLoading = false;
}
})
.catch((error) => {
this.upDurationList = [];
this.upParams.duration_id = "";
this.upParams.original_price = 0;
this.upParams.clDiscount = 0;
this.upParams.isUseDiscountCode = false;
this.upParams.customfield.promo_code = "";
this.upParams.code_discount = 0;
this.upParams.totalPrice = 0;
this.upgradePriceLoading = false;
});
},
// 升降级提交
upgradeSub() {
const params = {
id: this.id,
ip: this.ip,
peak_defence: this.peak_defence,
duration_id: this.upParams.duration_id,
customfield: this.upParams.customfield,
};
this.loading4 = true;
apiGenerateUpDefenceOrder(params, this.module)
.then((res) => {
if (res.data.status === 200) {
this.$message.success(lang.common_cloud_text56);
const orderId = res.data.data.id;
// 调支付弹窗
this.$refs.ipDefasePayDialog.showPayDialog(orderId, 0);
} else {
this.$message.error(err.data.msg);
}
})
.catch((err) => {
this.$message.error(err.data.msg);
})
.finally(() => {
this.loading4 = false;
});
},
goProductDetail(row) {
window.open(`/productdetail.htm?id=${row.host_id}&showUp=1`);
},
getStatusLabel(status) {
return (
this.statusOptions.find((item) => item.value === status)?.label || "--"
);
},
search() {
this.params.page = 1;
this.getProductList();
},
// 每页展示数改变
sizeChange(e) {
this.params.limit = e;
this.params.page = 1;
// 获取列表
this.getProductList();
},
// 当前页改变
currentChange(e) {
this.params.page = e;
this.getProductList();
},
sortChange({prop, order}) {
this.params.orderby = order ? prop : "id";
this.params.sort = order === "ascending" ? "asc" : "desc";
this.getProductList();
},
// 获取产品状态
getProductStatus(item, isInit = false) {
!isInit && (item.statusLoading = true);
apiProductRefreshHostIpStatus({id: item.id}, this.listmode)
.then((res) => {
item.status = res.data.data.status;
if (item.statusLoading) {
this.$message.success(res.data.msg);
}
item.statusLoading = false;
})
.catch((err) => {
item.statusLoading = false;
this.$message.error(err.data.msg);
});
},
getProductList() {
this.tabeLoading = true;
apiProductGetHostIp({...this.params, host_id: this.id}, this.listmode)
.then(async (res) => {
this.tabeLoading = false;
this.productList = res.data.data.list.map((item) => {
item.statusLoading = false;
this.getProductStatus(item, true);
return item;
});
this.params.total = res.data.data.count;
if (this.showip && this.isInit) {
this.isInit = false;
const ipInfo = this.productList.find(
(item) => item.host_ip == this.showip
);
if (ipInfo) {
this.openUpgradeDialog(ipInfo);
}
}
})
.catch((err) => {
this.tabeLoading = false;
this.$message.error(err.data.msg);
});
},
getCommonData() {
this.commonData = JSON.parse(localStorage.getItem("common_set_before"));
},
// 续费使用优惠码
async getRenewDiscount(data) {
this.renewParams.customfield.promo_code = data[1];
this.renewParams.isUseDiscountCode = true;
this.renewParams.code_discount = Number(data[0]);
const price = this.renewParams.base_price;
const discountParams = {id: this.product_id, amount: price};
// 开启了等级折扣插件
if (this.isShowLevel) {
// 获取等级抵扣价格
await clientLevelAmount(discountParams)
.then((res2) => {
if (res2.data.status === 200) {
this.renewParams.clDiscount = Number(res2.data.data.discount); // 客户等级优惠金额
}
})
.catch((error) => {
this.renewParams.clDiscount = 0;
});
}
},
// 移除续费的优惠码
removeRenewDiscountCode() {
this.renewParams.isUseDiscountCode = false;
this.renewParams.customfield.promo_code = "";
this.renewParams.code_discount = 0;
this.renewParams.clDiscount = 0;
const price = this.renewParams.original_price;
},
// 显示续费弹窗
showRenew(row) {
this.sub_host_id = row.sub_host_id;
if (this.renewBtnLoading) return;
this.renewBtnLoading = true;
// 获取续费页面信息
const params = {
id: this.sub_host_id,
};
this.isShowRenew = true;
this.renewLoading = true;
renewPage(params)
.then((res) => {
if (res.data.status === 200) {
this.renewBtnLoading = false;
this.renewPageData = res.data.data.host;
this.renewActiveId = this.renewPageData[0].id;
this.renewParams.billing_cycle =
this.renewPageData[0].billing_cycle;
this.renewParams.duration = this.renewPageData[0].duration;
this.renewParams.original_price = this.renewPageData[0].price;
this.renewParams.base_price = this.renewPageData[0].base_price;
}
this.renewLoading = false;
})
.catch((err) => {
this.renewBtnLoading = false;
this.renewLoading = false;
this.$message.error(err.data.msg);
});
},
getRenewPrice() {
renewPage({id: this.id})
.then(async (res) => {
if (res.data.status === 200) {
this.renewPriceList = res.data.data.host;
}
})
.catch((err) => {
this.renewPriceList = [];
});
},
// 续费弹窗关闭
renewDgClose() {
this.isShowRenew = false;
this.removeRenewDiscountCode();
},
// 续费提交
subRenew() {
this.subRenewLoading = true;
const params = {
id: this.sub_host_id,
billing_cycle: this.renewParams.billing_cycle,
customfield: this.renewParams.customfield,
};
renew(params)
.then((res) => {
this.subRenewLoading = false;
if (res.data.status === 200) {
this.$message.success(res.data.msg);
this.isShowRenew = false;
if (res.data.code == "Paid") {
this.getProductList();
} else {
this.$refs.ipDefasePayDialog.showPayDialog(res.data.data.id);
}
}
})
.catch((err) => {
this.subRenewLoading = false;
this.$message.error(err.data.msg);
});
},
// 续费周期点击
async renewItemChange(item) {
this.renewLoading = true;
this.renewActiveId = item.id;
this.renewParams.duration = item.duration;
this.renewParams.billing_cycle = item.billing_cycle;
this.renewParams.original_price = item.price;
this.renewParams.base_price = item.base_price;
// 开启了优惠码插件
if (this.isShowPromo && this.renewParams.isUseDiscountCode) {
const discountParams = {id: this.product_id, amount: item.base_price};
// 开启了等级折扣插件
if (this.isShowLevel) {
// 获取等级抵扣价格
await clientLevelAmount(discountParams)
.then((res2) => {
if (res2.data.status === 200) {
this.renewParams.clDiscount = Number(res2.data.data.discount); // 客户等级优惠金额
}
})
.catch((error) => {
this.renewParams.clDiscount = 0;
});
}
// 更新优惠码
await applyPromoCode({
scene: "renew",
product_id: this.product_id,
amount: item.base_price,
billing_cycle_time: this.renewParams.duration,
promo_code: this.renewParams.customfield.promo_code,
})
.then((resss) => {
price = item.base_price;
this.renewParams.isUseDiscountCode = true;
this.renewParams.code_discount = Number(resss.data.data.discount);
})
.catch((err) => {
this.$message.error(err.data.msg);
this.removeRenewDiscountCode();
});
}
this.renewLoading = false;
},
},
};

View File

@@ -0,0 +1,452 @@
// 验证码通过
function captchaCheckSuccsss(bol, captcha, token) {
if (bol) {
// 验证码验证通过
getData(captcha, token)
}
};
// 取消验证码验证
function captchaCheckCancel() {
captchaCancel()
};
const loginDialog = {
template:
`
<div>
<!-- 验证码 -->
<captcha-dialog :is-show-captcha="isShowCaptcha" ref="captcha"></captcha-dialog>
<el-dialog width="16.95rem" custom-class='login-dialog' :visible.sync="visible" :show-close=true>
<div class="login-left">
<div class="login-text">
<div class="login-text-title">{{lang.login}}</div>
<div class="login-text-regist" v-if="commonData.register_email == 1 || commonData.register_phone == 1">
{{lang.login_no_account}}<a @click="toRegist">{{lang.login_regist_text}}</a>
</div>
</div>
<div class="login-form">
<div class="login-top">
<div v-show="isPassOrCode" class="login-email" :class="isEmailOrPhone? 'active':null" @click="isEmailOrPhone = true">{{lang.login_email}}
</div>
<div class="login-phone" :class="!isEmailOrPhone? 'active':null" @click="isEmailOrPhone = false">{{lang.login_phone}}
</div>
</div>
<div class="form-main">
<div class="form-item">
<el-input v-if="isEmailOrPhone" v-model="formData.email" :placeholder="lang.login_placeholder_pre + lang.login_email"></el-input>
<el-input v-else class="input-with-select select-input" v-model="formData.phone" :placeholder="lang.login_placeholder_pre + lang.login_phone">
<el-select filterable slot="prepend" v-model="formData.countryCode">
<el-option v-for="item in countryList" :key="item.name" :value="item.phone_code" :label="item.name_zh + '+' + item.phone_code"></el-option>
</el-select>
</el-input>
</div>
<div v-if="isPassOrCode" class="form-item">
<el-input :placeholder="lang.login_pass" v-model="formData.password" type="password">
</el-input>
</div>
<div v-else class="form-item code-item">
<!-- 邮箱验证码 -->
<el-input v-if="isEmailOrPhone" v-model="formData.emailCode" :placeholder="lang.email_code">
</el-input>
<count-down-button ref="emailCodebtn" @click.native="sendEmailCode" v-if="isEmailOrPhone" my-class="code-btn"></count-down-button>
<!-- <el-button v-if="isEmailOrPhone" class="code-btn" type="primary">获取验证码</el-button> -->
<!-- 手机验证码 -->
<el-input v-if="!isEmailOrPhone" v-model="formData.phoneCode" :placeholder="lang.login_phone_code">
</el-input>
<count-down-button ref="phoneCodebtn" @click.native="sendPhoneCode" v-if="!isEmailOrPhone" my-class="code-btn"></count-down-button>
<!-- <el-button v-if="!isEmailOrPhone" class="code-btn" type="primary">获取验证码</el-button> -->
</div>
<div class="form-item rember-item">
<el-checkbox v-model="formData.isRemember">{{lang.login_remember}}</el-checkbox>
<a @click="toForget">{{lang.login_forget}}</a>
</div>
<div class="read-item" v-if="errorText.length !== 0">
<el-alert :title="errorText" type="error" show-icon :closable="false">
</el-alert>
</div>
<div class="form-item">
<el-button type="primary" class="login-btn" @click="doLogin">{{lang.login}}</el-button>
</div>
<div class="form-item read-item">
<el-checkbox v-model="checked">
{{lang.login_read}}<a @click="toService">{{lang.read_service}}</a>{{lang.read_and}}<a @click="toPrivacy">{{lang.read_privacy}}</a>
</el-checkbox>
</div>
<div class="form-item line-item" v-if="commonData.login_phone_verify == 1">
<el-divider><span class="text">or</span></el-divider>
</div>
<div class="form-item" v-if="commonData.login_phone_verify == 1">
<el-button v-if="isPassOrCode" :disabled="commonData.login_phone_verify == 0" @click="isPassOrCode = false;isEmailOrPhone = false" class="type-btn">{{lang.login_code_login}}
</el-button>
<el-button v-else @click="isPassOrCode = true" class="type-btn">
{{lang.login_pass_login}}
</el-button>
</div>
</div>
</div>
</div>
<div class="login-right">
<img src="${url}/img/common/login_back.png" class="login-back-img">
</div>
</el-dialog>
</div>
`,
data() {
return {
visible: true,
// 登录是否需要验证
isCaptcha: false,
isShowCaptcha: false, //登录是否显示验证码弹窗
checked: getCookie("checked") == "1" ? true : false,
isEmailOrPhone: getCookie("isEmailOrPhone") == "1" ? true : false, // true:电子邮件 false:手机号
isPassOrCode: getCookie("isPassOrCode") == "1" ? true : false, // true:密码登录 false:验证码登录
errorText: "",
formData: {
email: getCookie("email") ? getCookie("email") : null,
phone: getCookie("phone") ? getCookie("phone") : null,
password: getCookie("password") ? getCookie("password") : null,
phoneCode: "",
emailCode: "",
isRemember: getCookie("isRemember") == "1" ? true : false,
countryCode: 86
},
token: "",
captcha: '',
countryList: [],
commonData: {}
}
},
components: {
countDownButton,
captchaDialog
},
props: {
isShowLogin: {
default: false,
type: Boolean,
}
},
created() {
this.getCommonData()
this.getCountryList()
},
mounted() {
window.captchaCancel = this.captchaCancel
window.getData = this.getData
window.showLoginDialog = this.showLoginDialog
},
methods: {
// 获取通用配置
getCommonData() {
this.commonData = JSON.parse(localStorage.getItem('common_set_before'))
if (this.commonData.login_phone_verify == 0) {
this.isPassOrCode = true
}
if (this.commonData.captcha_client_login == 1) {
this.isCaptcha = true
}
},
showLoginDialog() {
this.visible = true
},
toRegist() {
// location.href = 'regist.html'
console.log("显示注册弹窗");
},
toForget() {
// location.href = 'forget.html'
console.log("显示忘记密码弹窗");
},
// 验证码验证成功后的回调
getData(captchaCode, token) {
this.isCaptcha = false
this.token = token
this.captcha = captchaCode
this.isShowCaptcha = false
// 判断是否密码登录 是执行登录
// 否则判断发送手机验证码还是邮箱验证码
if (this.isPassOrCode) {
this.doLogin()
} else {
if (this.isEmailOrPhone) {
// 发送邮箱验证码
this.sendEmailCode()
} else {
// 发送手机验证码
this.sendPhoneCode()
}
}
},
// 登录
doLogin() {
let isPass = true;
const form = { ...this.formData };
console.log(form);
// 邮件登录验证
if (this.isEmailOrPhone) {
if (!form.email) {
isPass = false
this.errorText = "请输入邮箱"
} else if (
form.email.search(
/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/
) === -1
) {
isPass = false
this.errorText = "邮箱格式不正确"
}
// 邮件 密码登录 验证
if (this.isPassOrCode) { // 密码登录
if (!form.password) {
isPass = false
this.errorText = "请输入密码"
}
} else {
// 邮件 验证码登录 验证
if (!form.emailCode) {
isPass = false
this.errorText = "请输入邮箱验证码"
} else {
if (form.emailCode.length !== 6) {
isPass = false
this.errorText = "邮箱验证码应为6位"
}
}
}
}
// 手机号码登录 验证
if (!this.isEmailOrPhone) {
if (!form.phone) {
isPass = false
this.errorText = "请输入手机号码"
} else {
// 设置正则表达式的手机号码格式 规则 ^起点 $终点 1第一位数是必为1 [3-9]第二位数可取3-9的数字 \d{9} 匹配9位数字
const reg = /^1[3-9]\d{9}$/;
if (!reg.test(form.phone)) {
isPass = false
this.errorText = "请输入正确的手机号"
}
}
// 手机号 密码登录 验证
if (this.isPassOrCode) { // 密码登录
if (!form.password) {
isPass = false
this.errorText = "请输入密码"
}
} else {
// 手机 验证码登录 验证
if (!form.phoneCode) {
isPass = false
this.errorText = "请输入手机验证码"
} else {
if (form.phoneCode.length !== 6) {
isPass = false
this.errorText = "手机验证码应为6位"
}
}
}
}
// 勾选协议
if (!this.checked) {
isPass = false
this.errorText = "请勾选服务协议书!"
}
if (isPass && this.isCaptcha) {
this.isShowCaptcha = true
this.$refs.captcha.doGetCaptcha()
return
}
// 验证通过
if (isPass) {
this.errorText = ""
let code = "";
if (!this.isPassOrCode) {
if (this.isEmailOrPhone) {
code = form.emailCode
} else {
code = form.phoneCode
}
}
const params = {
type: this.isPassOrCode ? "password" : "code",
account: this.isEmailOrPhone ? form.email : form.phone,
phone_code: form.countryCode.toString(),
code,
password: this.isPassOrCode ? this.encrypt(form.password) : "",
remember_password: form.isRemember ? "1" : "0",
captcha: this.captcha,
token: this.token
}
//调用登录接口
logIn(params).then(res => {
if (res.data.status === 200) {
this.$message.success(res.data.msg);
// 存入 jwt
localStorage.setItem("jwt", res.data.data.jwt);
if (form.isRemember) {// 记住密码
console.log(form);
if (this.isEmailOrPhone) {
console.log("email");
setCookie("email", form.email, 30)
} else {
console.log("phone");
setCookie("phone", form.phone, 30)
}
setCookie("password", form.password, 30)
setCookie("isRemember", form.isRemember ? "1" : "0")
setCookie("checked", this.checked ? "1" : "0")
// 保存登录方式
setCookie("isEmailOrPhone", this.isEmailOrPhone ? "1" : "0")
setCookie("isPassOrCode", this.isPassOrCode ? "1" : "0")
} else {
// 未勾选记住密码
delCookie("email")
delCookie("phone")
delCookie("password")
delCookie("isRemember")
delCookie("checked")
}
location.reload();
}
}).catch(err => {
if (err.data.msg === "请输入图形验证码" || err.data.msg === "图形验证码错误") {
this.isShowCaptcha = true
this.$refs.captcha.doGetCaptcha()
} else {
this.errorText = err.data.msg
// this.$message.error(err.data.msg);
}
})
}
},
// 获取国家列表
getCountryList() {
getCountry({}).then(res => {
console.log(res);
if (res.data.status === 200) {
this.countryList = res.data.data.list
}
})
},
// 加密方法
encrypt(str) {
const key = CryptoJS.enc.Utf8.parse("idcsmart.finance");
const iv = CryptoJS.enc.Utf8.parse("9311019310287172");
var encrypted = CryptoJS.AES.encrypt(str, key, {
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
iv: iv,
}).toString();
return encrypted;
},
// 发送邮箱验证码
sendEmailCode() {
let isPass = true
const form = this.formData
if (!form.email) {
isPass = false
this.errorText = "请输入邮箱"
} else if (
form.email.search(
/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/
) === -1
) {
isPass = false
this.errorText = "邮箱格式不正确"
}
if (isPass) {
this.errorText = ""
const params = {
action: "login",
email: form.email,
token: this.token,
captcha: this.captcha
}
emailCode(params).then(res => {
if (res.data.status === 200) {
// 执行倒计时
this.$refs.emailCodebtn.countDown()
}
}).catch(err => {
if (err.data.msg === "请输入图形验证码" || err.data.msg === "图形验证码错误") {
this.isShowCaptcha = true
this.$refs.captcha.doGetCaptcha()
} else {
this.errorText = err.data.msg
// this.$message.error(err.data.msg);
}
})
}
},
// 发送手机短信
sendPhoneCode() {
let isPass = true
const form = this.formData
if (!form.phone) {
isPass = false
this.errorText = "请输入手机号码"
} else {
// 设置正则表达式的手机号码格式 规则 ^起点 $终点 1第一位数是必为1 [3-9]第二位数可取3-9的数字 \d{9} 匹配9位数字
const reg = /^1[3-9]\d{9}$/;
if (!reg.test(form.phone)) {
isPass = false
this.errorText = "请输入正确的手机号"
}
}
if (isPass) {
this.errorText = ""
const params = {
action: "login",
phone_code: form.countryCode,
phone: form.phone,
token: this.token,
captcha: this.captcha
}
phoneCode(params).then(res => {
if (res.data.status === 200) {
// 执行倒计时
this.$refs.phoneCodebtn.countDown()
}
}).catch(err => {
if (err.data.msg == "请输入图形验证码" || err.data.msg == "图形验证码错误") {
this.isShowCaptcha = true
this.$refs.captcha.doGetCaptcha()
} else {
this.errorText = err.data.msg
// this.$message.error(err.data.msg);
}
})
}
},
toService() {
const url = this.commonData.terms_service_url
window.open(url);
},
toPrivacy() {
const url = this.commonData.terms_privacy_url
window.open(url);
},
// 验证码 关闭
captchaCancel() {
this.isShowCaptcha = false
}
},
}

View File

@@ -0,0 +1,79 @@
// css 样式依赖common.css
const pagination = {
inheritAttrs: false,
template: `
<div class="myPage custom-pagination">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageData.page"
:page-sizes="pageData.pageSizes" :page-size="pageData.limit"
:layout="layoutToUse"
:total="pageData.total"
:pager-count=5
v-bind="$attrs"
:disabled="pageData.page <= 1 && isNextPageDisabled && showCustomButtons"
>
<span class="page-total">{{lang.total}} {{pageData.total}} {{lang.pieces}}</span>
</el-pagination>
<div class="manual-btn" v-if="showCustomButtons">
<el-button type="primary" size="small" :disabled="pageData.page <= 1" @click="handleChange(0)">{{lang.prev_page}}</el-button>
<el-button type="primary" size="small" :disabled="isNextPageDisabled" @click="handleChange(1)">{{lang.next_page}}</el-button>
</div>
</div>
`,
data () {
return {};
},
computed: {
layoutToUse () {
return this.$attrs.layout || "slot, sizes, prev, pager,jumper, next";
},
isNextPageDisabled () {
return this.curPageLength < this.pageData.limit;
},
},
props: {
pageData: {
default: function () {
return {
page: 1,
pageSizes: [20, 50, 100],
limit: 20,
total: 400,
};
},
},
showCustomButtons: {
type: Boolean,
default: false,
},
curPageLength: {
type: Number,
default: 0,
}
},
methods: {
handleChange (direction) {
if (direction === 0) {
if (this.pageData.page > 1) {
this.pageData.page -= 1;
this.$emit('currentchange', this.pageData.page);
}
} else if (direction === 1) {
if (!this.isNextPageDisabled) {
this.pageData.page += 1;
this.$emit('currentchange', this.pageData.page);
}
}
},
handleSizeChange (e) {
this.pageData.limit = e;
this.$emit("sizechange", e);
},
handleCurrentChange (e) {
this.pageData.page = e;
this.$emit("currentchange", e);
},
},
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,98 @@
const productFilter = {
template: /*html */ `
<div class="product-tab-list">
<el-tabs v-model="select_tab" @tab-click="handelTab" v-if="isInit">
<el-tab-pane v-for="(item,index) in tabList" :key="item.tab" :name="item.tab">
<template #label>
<span>{{item.name}}</span>
<span v-if="count[item.countName] > 0">({{count[item.countName]}})</span>
</template>
</el-tab-pane>
</el-tabs>
</div>
`,
data() {
return {
select_tab: "all",
isInit: false,
};
},
props: {
tabList: {
type: Array,
required: false,
default: () => {
return [
{
name: lang.product_list_status1,
tab: "using",
countName: "using_count",
},
{
name: lang.product_list_status2,
tab: "expiring",
countName: "expiring_count",
},
{
name: lang.product_list_status3,
tab: "overdue",
countName: "overdue_count",
},
{
name: lang.product_list_status4,
tab: "deleted",
countName: "deleted_count",
},
{
name: lang.finance_btn5,
tab: "all",
countName: "all_count",
},
];
},
},
tab: {
type: String,
required: false,
default: "",
},
count: {
type: Object,
required: false,
default: {
all_count: 0, // 全部产品数量
deleted_count: 0, // 已删除产品数量
expiring_count: 0, // 即将到期产品数量
overdue_count: 0, // 已逾期产品数量
using_count: 0, // 正常使用产品数量
},
},
},
// 监听count 数据变化了代表有数据 只执行一次 初始化不执行
watch: {
count: {
handler(newVal) {
if (newVal.list) {
this.isInit = true;
}
},
deep: true,
immediate: true,
},
},
mounted() {
if (this.tab) {
this.select_tab = this.tab;
}
if (this.tab == "") {
this.select_tab = "all";
}
},
methods: {
handelTab({name}) {
const tab = name === "all" ? "" : name;
this.$emit("update:tab", tab);
this.$emit("change");
},
},
};

View File

@@ -0,0 +1,358 @@
const proofDialog = {
template: `
<!-- 上传凭证 -->
<div>
<el-dialog custom-class='pay-dialog proof-dailog' :class='{look: isLook}' :visible.sync="proofDialog" :show-close="false"
@close="proofClose">
<div class="pc-pay">
<div class="dia-title">
<div class="title-text" v-if="isLook">{{lang.finance_custom19}}</div>
<div class="title-text" v-else>{{lang.finance_custom6}}{{zfData.orderId}}</div>
<div class="title-text" v-show="!isLook">{{lang.pay_text2}}
<span class="pay-money">{{ commonData.currency_prefix }}
<span class="font-26">{{ Number(zfData.amount).toFixed(2)}}</span>
</span>
<i class="el-icon-circle-close close" @click="proofDialog = false"></i>
</div>
</div>
<div class="dia-content">
<div class="item" v-show="!isLook">
<div class="pay-top">
<div class="pay-type" ref="payListRef">
<div class="type-item active">
<img :src="bankImg" alt="" />
</div>
</div>
</div>
<div class="qr-money">
<span>{{lang.finance_custom11}}</span>
<span class="pay-money">{{ commonData.currency_prefix}}
<span class="font-26">
{{orderInfo.amount_unpaid}}{{commonData.currency_code}}
</span>
</span>
</div>
<p class="des">
({{lang.finance_custom12}}{{commonData.currency_prefix}}{{orderInfo.credit}}{{commonData.currency_code}})
</p>
<div class="custom-text">
<div class="qr-content" v-loading="payLoading" v-html="payHtml" id="payBox"></div>
<i class="el-icon-document-copy" v-if="payHtml" @click="copyText(payHtml)"></i>
</div>
<el-steps :space="200" :active="stepNum" finish-status="success" :align-center="true"
class="custom-step">
<el-step :title="lang.finance_custom7"></el-step>
<el-step :title="lang.finance_custom4"></el-step>
<el-step>
<template slot="title">
<span class="txt" :class="{ fail: orderStatus === 'ReviewFail'}">{{orderStatus === 'ReviewFail'
? lang.finance_custom9 : lang.finance_custom8}}</span>
<el-popover placement="top-start" trigger="hover" :title="review_fail_reason">
<span class="help" slot="reference" v-if="orderStatus === 'ReviewFail'">?</span>
</el-popover>
</template>
</el-step>
<el-step :title="lang.finance_custom10"></el-step>
</el-steps>
</div>
<div class="item">
<p v-show="!isLook">{{lang.finance_custom4}}</p>
<el-upload class="upload-demo" ref="fileupload" drag
action="/console/v1/upload" :headers="{Authorization: jwt}"
:before-remove="beforeRemove" multiple :file-list="fileList" :on-success="handleSuccess"
:on-preview="clickFile"
:limit="10"
accept="image/*, .pdf, .PDF" v-if="!isLook">
<div class="el-upload__text">
<p>{{lang.finance_custom16}}<em>{{lang.finance_custom17}}</em></p>
<p>{{lang.finance_custom18}}</p>
</div>
</el-upload>
<div v-else class="view-box">
<p class="item" v-for="(item, index) in fileList" :key="index" @click="clickFile(item)">
{{item.name}}
</p>
</div>
<div class="dia-fotter" v-if="!isLook">
<el-button class="cancel-btn" @click="changeWay">{{lang.finance_custom14}}</el-button>
<el-button @click="submitProof" :disabled="formData.voucher.length === 0" class="submit-btn" :loading="submitLoading">
{{orderStatus === 'WaitUpload' ? lang.finance_custom4 : lang.finance_custom5}}
</el-button>
</div>
<div class="dia-fotter" v-else>
<el-button class="cancel-btn" @click="proofClose">{{lang.finance_text58}}</el-button>
</div>
</div>
</div>
</div>
</el-dialog>
<!-- 图片预览 -->
<div style="height: 0;">
<img id="proofViewer" :src="preImg" alt="">
</div>
<!-- 变更支付方式 -->
<div class="delete-dialog">
<el-dialog width="4.35rem" :visible.sync="showChangeWay" :show-close=false @close="showChangeWay=false">
<div class="delete-box">
<div class="delete-content">{{lang.finance_custom15}}</div>
<div class="delete-btn">
<el-button class="confirm-btn btn" @click="handelChangeWay" :loading="changeLoading">{{lang.finance_btn8}}</el-button>
<el-button class="cancel-btn btn" @click="showChangeWay=false">{{lang.finance_btn7}}</el-button>
</div>
</div>
</el-dialog>
</div>
</div>
`,
created() {},
mounted() {
// 引入 jquery
// const script = document.createElement("script");
// script.src = `${url}js/common/jquery.mini.js`;
// document.body.appendChild(script);
// this.initViewer();
},
// components: {
// payDialog
// },
computed: {
srcList() {
return this.formData.voucher;
},
},
destroyed() {},
props: {},
data() {
return {
proofDialog: false,
zfData: {
orderId: 0,
amount: 0,
},
commonData: {
currency_prefix: "¥",
},
orderInfo: {},
stepNum: 0,
orderStatus: "",
review_fail_reason: "",
payLoading: false,
payHtml: "",
fileList: [],
jwt: `Bearer ${localStorage.jwt}`,
formData: {
id: "",
voucher: [],
},
submitLoading: false,
showChangeWay: false,
changeLoading: false,
viewer: null,
preImg: "",
isLook: false,
bankImg: `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGoAAAAcCAYAAACJWipLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJ
bWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdp
bj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6
eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2
MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJo
dHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlw
dGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAv
IiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RS
ZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpD
cmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0
YW5jZUlEPSJ4bXAuaWlkOkRDQ0EyQzUzQTNFOTExRUE5OENBOTNGMERBMUM4MkM0IiB4bXBNTTpE
b2N1bWVudElEPSJ4bXAuZGlkOkRDQ0EyQzU0QTNFOTExRUE5OENBOTNGMERBMUM4MkM0Ij4gPHht
cE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6RENDQTJDNTFBM0U5MTFF
QTk4Q0E5M0YwREExQzgyQzQiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6RENDQTJDNTJBM0U5
MTFFQTk4Q0E5M0YwREExQzgyQzQiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94
OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz48YXx4AAAEzUlEQVR42uxaO2/TUBR2SiqxoKYS
MMDQAGKuO9IONQsSYmiQGBBCqvsLcOcMSQWZm1asqC4TEgNhYGGJI9GygOqOFUW4bEyEAYFQUDhH
fJee3th5tUpi4SMdXz+u7+N85+kkZSjKNy7Q8SbxGWM49Jt4xyil3/BFs9k0EjqkNEC6R8cnxKeH
vqJ84xUd7xD/TOA5pDESzBVq3ZEA6S/dIi4m0OhAGcZd4vERW9f9BJpWoM6N4LouJtC0ApVQAlRC
J5n1PSauxHHx1tycyW1te9vvd4z52VmLmoDGCHp8L0ONzYkYvVvXnvG66t2MKcsQ2g+vxfe2tuqt
QJXS+9TujxwKj7qqoxxiE8wCKqvzsL46oBA2K6lH5w4EH0WuJngW6iq/y8LV+nrIXMshANtyHgLH
ADg8f5X4Ot5XwOX4WTquroA2kaVmkXgNVlEXIHla9wJxJgQkTwCegfCjqIL3eF7mHPE3fk/MnwFP
CGs1YF0KTPW+KwA3I7xFRa0xtkCJWusBuKZAIqEUNVAKESBNswYLS7G6mNcG8IqqaHn+eXF/VZzX
tLEDzJ9Fa4WA5KGfHVugsBG2piUSsisA4M3ZQpMj3RhAWmJtpv58beqxJoxYCag/a/oO8TKsRa6B
z7N0r9MaLLBu/TmAw3M4Kl6ljXyjDI0cNUp10WeDBLOB8xXh9lytXzXEjZWhsT6uGbBOIHnCqg7g
5liwLmJPFsIP6LrYIcZFEc9RJ4CKetYXO6JN+GRVl+D+TMSYQAlJCFRpuS5wV1igilFfe1AeG3PL
uGdi/imxlpYY18ZLqOzpBa6le12JbYwisALaTAA34wlACnpMikivXcSUGlxeKiRtryKGedr9CYCV
QTKhMj8es9iF2wuj65hvGWP7wjMEcY1RlnRnJKimSCY2kYGxO7+Nc2V5ngBpEVlbr+RDqMqyTIxf
V+m4sNR/7xB4TgfF81SqrhINvhf3LxNKWAzKLs4dkVGVNXc0j1hiiBR5KaT+6UhsfWxhsLIAABmw
LgfzFMG+lgkamqv028SpBZQgsY5RLBwPlqW7PhYmB/NNpNFsNct0ryyEbYnis58vGaruMuEGq0gu
KsKysrC4Tc2aXPRjXmCFof1Y2v4qtLcDjJMbtEW9Jp5sw2+P8RnIQcoshVmHtdVDUuDjUBYgqbjE
c0wSGFlYmCPcFyc2tmaRgUg6XjIY6lOYcO1FAMpW5QzaoqaMUjq6Tsk39uh4rccxTbgW5jURMwqI
WTY2vAMLK7f7LoivDraoZ8Jcn6uCPFJwS9VfbLVQGJWo+Fxcy/qMrnMohtfgHj14B0fLDi0oxSq7
wEFa1GUC41Sb5x/6GDMDjZ6Bm5hQ8YvdG0CxUGPl9M9IEVQAT2PsnuIYWwxc6woSFiek2N5ldwgA
LdzLiPhkcglCbANQb5AWNQ4N+RjxfK+PMXMqwENbZ3SLwbOiEf7zvhPillI9zO9G1Uf4ghFW5Joi
AVHx1oHLCzg+afFq4K6P6WoboHr+gh/yc0CvWZx/zP0EfTwP2uwnsigeGwJQxkkB9T8RW9SXAc63
TnFqvYt+nxNoWi3qGfGvEVvX0wQaHahS+hO1/AfM7yOypufEDxNojlJK1DFn6XiD+PyQ1vKD+B0p
znu+SP7SfJT+CDAAdKMBqP61EkMAAAAASUVORK5CYII=
`,
};
},
methods: {
proofClose() {
this.proofDialog = false;
this.viewer && this.viewer.destroy();
},
changeWay() {
this.showChangeWay = true;
},
initViewer() {
this.viewer = new Viewer(document.getElementById("proofViewer"), {
button: true,
inline: false,
zoomable: true,
title: true,
tooltip: true,
minZoomRatio: 0.5,
maxZoomRatio: 100,
movable: true,
interval: 2000,
navbar: true,
loading: true,
});
},
// 附件下载
clickFile(item) {
const name = item.name;
const imgUrl = item.url || item.response.data.image_url;
const type = name.substring(name.lastIndexOf(".") + 1);
if (
[
"png",
"jpg",
"jepg",
"bmp",
"webp",
"PNG",
"JPG",
"JEPG",
"BMP",
"WEBP",
].includes(type)
) {
this.preImg = imgUrl;
if (!this.viewer) {
this.initViewer();
}
setTimeout(() => {
this.viewer.show();
$("#proofViewer").attr("src", imgUrl);
}, 10);
} else {
const downloadElement = document.createElement("a");
downloadElement.href = url;
downloadElement.download = item.name; // 下载后文件名
document.body.appendChild(downloadElement);
downloadElement.click(); // 点击下载
}
},
emitRefresh(isChange = false) {
this.$emit("refresh", isChange, this.orderInfo.id);
},
async handelChangeWay() {
try {
this.changeLoading = true;
const res = await changePayType(this.orderInfo.id);
this.$message.success(res.data.msg);
this.showChangeWay = false;
this.proofDialog = false;
this.changeLoading = false;
this.emitRefresh(true);
} catch (error) {
console.log("error", error);
this.changeLoading = false;
this.showChangeWay = false;
this.$message.error(error.data.msg);
}
},
onProgress(event) {
console.log(event);
},
async submitProof() {
try {
if (this.formData.voucher.length === 0) {
return this.$message.warning(lang.finance_custom13);
}
this.submitLoading = true;
const params = {
id: this.zfData.orderId,
voucher: this.formData.voucher,
};
const res = await uploadProof(params);
this.submitLoading = false;
this.$message.success(res.data.msg);
this.proofDialog = false;
this.emitRefresh();
} catch (error) {
this.submitLoading = false;
this.$message.error(error.data.msg);
}
},
beforeRemove(file, fileList) {
// 获取到删除的 save_name
let save_name = file.save_name || file.response.data.save_name;
this.formData.voucher = this.formData.voucher.filter((item) => {
return item != save_name;
});
},
// 上传文件相关
handleSuccess(response, file, fileList) {
if (response.status != 200) {
this.$message.error(response.msg);
// 清空上传框
let uploadFiles = this.$refs["fileupload"].uploadFiles;
let length = uploadFiles.length;
uploadFiles.splice(length - 1, length);
} else {
this.formData.voucher = [];
this.formData.voucher = fileList.map(
(item) => item.response?.data?.save_name || item.save_name
);
}
},
async getOrderDetails(orderId) {
try {
const res = await orderDetails(orderId);
this.orderInfo = res.data.data.order;
const {id, amount, status, review_fail_reason} = res.data.data.order;
this.zfData.orderId = Number(id);
this.zfData.amount = amount;
this.proofDialog = true;
this.orderStatus = status;
this.review_fail_reason = review_fail_reason;
this.isLook = status === "Paid" && this.orderInfo.voucher.length > 0;
if (status === "WaitUpload") {
this.stepNum = 2;
} else {
this.stepNum = 3;
}
// 获取转账信息
this.payLoading = true;
let result = "";
if (!this.isLook) {
result = await pay({
id,
gateway: "UserCustom",
});
this.payLoading = false;
this.payHtml = result.data.data.html;
$("#payBox").html(res.data.data.html);
}
this.fileList = this.orderInfo.voucher;
this.formData.voucher = this.orderInfo.voucher.map(
(item) => item.save_name
);
} catch (error) {
console.log("error", error);
this.$message.error(error.data.msg);
this.payLoading = false;
}
},
},
};

View File

@@ -0,0 +1,255 @@
const rechargeDialog = {
template: /*html*/ `
<div>
<el-dialog width="7.5rem" :visible.sync="isShowCz" @close="czClose" custom-class="recharge-dialog"
:show-close="false">
<div class="recharge-content">
<div class="recharge-title">
<span class="title-text">{{lang.finance_title4}}</span>
<span class="close-btn" @click="czClose">
<i class="el-icon-close"></i>
</span>
</div>
<div class="recharge-box">
<div class="recharge-input">
<el-input-number v-model="amount" :min="0" :precision="2" :step="0.01" :controls="false"
:placeholder="lang.finance_text130">
</el-input-number>
<el-button @click="handleSubmit" type="primary" :loading="submitLoading">{{lang.finance_btn6}}
</el-button>
</div>
<template v-if="rechargeActive.length > 0">
<div class="recharge-tip">
<template v-for="(item, index) in rechargeTip">
<span>{{item}}</span>
<template v-if="index !== rechargeTip.length - 1">
<br />
</template>
</template>
</div>
<div class="recharge-active">
<div class="active-title">{{lang.coin_text12}}<el-tooltip effect="dark" placement="top"
v-if="coinClientCoupon.coin_description_open == 1">
<div slot="content" v-html="coinClientCoupon.coin_description"></div>
<svg t="1745803081479" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="14138" width="16" height="16"
xmlns:xlink="http://www.w3.org/1999/xlink">
<path
d="M512 97.52381c228.912762 0 414.47619 185.563429 414.47619 414.47619s-185.563429 414.47619-414.47619 414.47619S97.52381 740.912762 97.52381 512 283.087238 97.52381 512 97.52381z m0 73.142857C323.486476 170.666667 170.666667 323.486476 170.666667 512s152.81981 341.333333 341.333333 341.333333 341.333333-152.81981 341.333333-341.333333S700.513524 170.666667 512 170.666667z m45.32419 487.619047v73.142857h-68.510476l-0.024381-73.142857h68.534857z m-4.047238-362.008381c44.251429 8.923429 96.889905 51.126857 96.889905 112.518096 0 61.415619-50.151619 84.650667-68.120381 96.134095-17.993143 11.50781-24.722286 24.771048-24.722286 38.863238V609.52381h-68.534857v-90.672762c0-21.504 6.89981-36.571429 26.087619-49.883429l4.315429-2.852571 38.497524-25.6c24.551619-16.530286 24.210286-49.712762 9.020952-64.365715a68.998095 68.998095 0 0 0-60.391619-15.481904c-42.715429 8.387048-47.640381 38.521905-47.932952 67.779047v16.554667H390.095238c0-56.953905 6.534095-82.773333 36.912762-115.395048 34.03581-36.449524 81.993143-42.300952 126.268952-33.328762z"
p-id="14139" fill="currentColor"></path>
</svg>
</el-tooltip></div>
<div class="active-main">
<div class="active-list">
<div class="active-item" v-for="item in rechargeActive" :key="item.id">
<div class="active-name">
<span>{{item.name}}</span>
<span class="active-time">
<template v-if="item.begin_time == 0">
{{item.begin_time | formateTime}}
</template>
<template v-else>
{{item.begin_time | formateTime}} - {{item.end_time | formateTime}}
</template>
</span>
</div>
<div class="gradient-content" v-if="item.type === 'gradient'">
<div class="gradient-item"
:class="{active: amount *1 >= items.amount * 1 && (index == item.return.length - 1 || amount * 1 < item.return[index + 1].amount * 1)}"
v-for="(items, index) in item.return" :key="items.id"
@click="amount = items.amount">
<div class="gradient-money">
<span class="s-12">{{currency_prefix}}</span>{{items.amount}}
</div>
<div class="gradient-award ">
{{lang.coin_text13}}{{items.amount}}{{lang.coin_text14}}{{items.award}}{{coinClientCoupon.name}}
<i class="el-icon-check active-icon"></i>
</div>
</div>
</div>
<div class="gradient-content" v-if="item.type === 'proportion'">
<div class="gradient-item" :class="{active:amount * 1 >= item.recharge_min * 1}"
@click="amount = item.recharge_min">
<div class="gradient-money">
<span class="s-12">{{currency_prefix}}</span>{{item.recharge_min}}
</div>
<div class="gradient-award ">
{{lang.coin_text15}}{{item.recharge_min}}<br>{{lang.coin_text16}}{{Number(item.recharge_proportion)}}%{{coinClientCoupon.name}}
<i class="el-icon-check active-icon"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<div v-if="commonData.recharge_money_notice_content" v-html="commonData.recharge_money_notice_content"
class="cz-notice">
</div>
</div>
</div>
</el-dialog>
<pay-dialog ref="payDialog" @payok="paySuccess"></pay-dialog>
</div>
`,
data() {
return {
isShowCz: false,
currency_prefix: "",
currency_suffix: "",
commonData: {},
amount: undefined,
submitLoading: false,
rechargeActive: [],
coinClientCoupon: {},
};
},
components: {
payDialog,
},
created() {
this.getCommon();
},
filters: {
formateTime(time) {
if (time && time !== 0) {
return formateDate(time * 1000);
} else if (time === 0) {
return lang.coin_text17;
} else {
return "--";
}
},
},
computed: {
rechargeTip() {
if (this.rechargeActive.length === 0 || !this.amount) {
return [];
}
const rechargeTipList = [];
const maxCoinAward = Number(
this.coinClientCoupon.per_recharge_get_coin_max
);
this.rechargeActive.forEach((item) => {
if (item.type === "proportion") {
if (this.amount * 1 >= item.recharge_min * 1) {
const award = Number(item.recharge_proportion * 0.01 * this.amount);
const tip = `${item.name}${lang.coin_text18}${Number(
award > maxCoinAward ? maxCoinAward : award
).toFixed(2)}${this.coinClientCoupon.name}`;
rechargeTipList.push(tip);
} else {
const tip = `${item.name}${lang.coin_text19}${Number(
item.recharge_min - this.amount
).toFixed(2)}${this.currency_suffix}${lang.coin_text20}${Number(
item.recharge_proportion * 0.01 * item.recharge_min
).toFixed(2)}${this.coinClientCoupon.name}`;
rechargeTipList.push(tip);
}
}
if (item.type === "gradient") {
// 找出最大的阶梯金额
const maxAmount = Math.max(
...item.return.map((items) => items.amount)
);
if (this.amount * 1 >= maxAmount * 1) {
const maxAward = item.return.find(
(items) => items.amount === maxAmount
)?.award;
const tip = `${item.name}${lang.coin_text18}${Number(
maxAward > maxCoinAward ? maxCoinAward : maxAward
).toFixed(2)}${this.coinClientCoupon.name}`;
rechargeTipList.push(tip);
} else {
// 找出当前充值金额对应的阶梯 和 下一个阶梯
const currentIndex = item.return.findIndex((items, index) => {
return (
this.amount * 1 >= items.amount * 1 &&
this.amount * 1 < item.return[index + 1]?.amount * 1
);
});
const currentAmount = item.return[currentIndex];
const nextAmount = item.return[currentIndex + 1];
if (currentAmount && nextAmount) {
const currentAward =
currentAmount.award > maxCoinAward
? maxCoinAward
: currentAmount.award;
const nextAward =
nextAmount.award > maxCoinAward
? maxCoinAward
: nextAmount.award;
const tip = `${item.name}${lang.coin_text21}${Number(
currentAward
).toFixed(2)}${this.coinClientCoupon.name}${
lang.coin_text22
}${Number(nextAmount.amount - this.amount).toFixed(2)}${
this.currency_suffix
}${lang.coin_text20}${Number(nextAward).toFixed(2)}${
this.coinClientCoupon.name
}`;
rechargeTipList.push(tip);
}
}
}
});
return rechargeTipList;
},
},
methods: {
getCoinClientCoupon() {
apiCoinClientCoupon().then((res) => {
this.coinClientCoupon = res.data.data;
});
},
getRechargeDetail() {
apiCoinRechargeDetail().then((res) => {
this.rechargeActive = res.data.data.coins;
});
},
open() {
if (havePlugin("Coin")) {
this.getRechargeDetail();
this.getCoinClientCoupon();
}
this.isShowCz = true;
},
czClose() {
this.amount = undefined;
this.isShowCz = false;
},
handleSubmit() {
if (!this.amount) {
return this.$message.error(lang.finance_text130);
}
this.submitLoading = true;
apiRecharge({amount: this.amount})
.then((res) => {
if (res.data.status === 200) {
this.isShowCz = false;
const orderId = res.data.data.id;
this.$refs.payDialog.czPay(orderId);
}
})
.catch((error) => {
this.$message.error(error.data.msg);
})
.finally(() => {
this.submitLoading = false;
});
},
paySuccess() {
this.$emit("success");
},
getCommon() {
this.commonData = JSON.parse(localStorage.getItem("common_set_before"));
this.currency_prefix = this.commonData.currency_prefix;
this.currency_suffix = this.commonData.currency_suffix;
},
},
};

View File

@@ -0,0 +1,10 @@
const refundDialog = {
template: `
<div>这是退款弹窗</div>
`,
created() {},
data() {
return {};
},
methods: {},
};

View File

@@ -0,0 +1,96 @@
.common-renew-dialog .dialog-main .renew-content {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 105%;
}
.common-renew-dialog .dialog-main .renew-content .renew-item {
width: 1.6rem;
min-height: 0.83rem;
border: 1px solid #E6E7EB;
border-radius: 3px;
display: flex;
flex-direction: column;
align-items: center;
margin-right: 0.2rem;
margin-bottom: 0.2rem;
cursor: pointer;
position: relative;
box-sizing: border-box;
}
.common-renew-dialog .dialog-main .renew-content .renew-item:nth-child(3) {
margin-right: 0;
}
.common-renew-dialog .dialog-main .renew-content .renew-item:nth-child(6) {
margin-right: 0;
}
.common-renew-dialog .dialog-main .renew-content .renew-item .item-top {
font-size: 0.15rem;
color: #1E2736;
margin-top: 0.08rem;
}
.common-renew-dialog .dialog-main .renew-content .renew-item .item-bottom {
font-size: 0.15rem;
color: var(--color-primary);
margin-top: 0.04rem;
}
.common-renew-dialog .dialog-main .renew-content .renew-item .check {
position: absolute;
right: 0;
bottom: 0;
z-index: 3;
color: #FFF;
}
.common-renew-dialog .dialog-main .renew-content .renew-item .item-origin-price {
text-decoration: line-through;
font-size: 0.15rem;
color: #8692B0;
}
.common-renew-dialog .dialog-main .renew-content .renew-active {
box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.12);
}
.common-renew-dialog .dialog-main .renew-content .renew-active::after {
content: '';
position: absolute;
bottom: 0;
right: 0;
z-index: 2;
width: 0;
height: 0;
border-bottom: 0.24rem solid var(--color-primary);
border-left: 0.24rem solid transparent;
}
.common-renew-dialog .dialog-main .pay-content {
border: 1px solid #E6E7EB;
border-radius: 3px;
padding: 0.2rem 0;
padding-right: 0.3rem;
}
.common-renew-dialog .dialog-main .pay-content .pay-price {
display: flex;
text-align: right;
flex-direction: row;
}
.common-renew-dialog .dialog-main .pay-content .pay-price .text {
font-size: 0.14rem;
margin-top: 0.1rem;
color: #1E2736;
margin-right: 1.43rem;
}
.common-renew-dialog .dialog-main .pay-content .pay-price .money {
width: 100%;
font-size: 0.28rem;
font-weight: bold;
color: var(--color-price-text);
text-align: right;
}
.common-renew-dialog .dialog-main .pay-content .pay-price .total-icon {
font-size: 0.16rem;
color: #1E2736;
}
.common-renew-dialog .dialog-main .pay-content .pay-price .original-price {
text-decoration: line-through;
font-size: 0.2rem;
font-weight: 500;
color: #999999;
}

View File

@@ -0,0 +1,325 @@
const renewDialog = {
template: /*html*/ `
<div>
<el-dialog width="6.9rem" :visible.sync="isShowRenew" :show-close="false" @close="renewDgClose" class="common-renew-dialog">
<div class="dialog-title">{{demand ? '转包年包月' : '续费'}}</div>
<div class="dialog-main">
<div class="renew-content">
<div class="renew-item" :class="selected_id==item.id?'renew-active':''" v-for="item in renewList"
:key="item.id" @click="renewItemChange(item)">
<div class="item-top">{{item.customfield?.multi_language?.billing_cycle || item.billing_cycle}}</div>
<div class="item-bottom" v-if="hasShowPromo && useDiscount">
{{commonData.currency_prefix + item.base_price}}
</div>
<div class="item-bottom" v-else>{{commonData.currency_prefix + item.price}}</div>
<div class="item-origin-price"
v-if="item.price*1 < item.base_price*1 && !useDiscount">
{{commonData.currency_prefix + item.base_price}}
</div>
<i class="el-icon-check check" v-show="selected_id==item.id"></i>
</div>
</div>
<div class="pay-content">
<div class="pay-price">
<div class="money" v-loading="renewLoading">
<span class="text">{{lang.common_cloud_label11}}:</span>
<span>{{commonData.currency_prefix}}{{totalPrice | filterMoney}}</span>
<el-popover placement="top-start" width="200" trigger="hover" v-if="level_discount_amount * 1 || code_discount_amount * 1">
<div class="show-config-list">
<p v-if="level_discount_amount*1 > 0">
{{lang.shoppingCar_tip_text2}}{{commonData.currency_prefix}}
{{ level_discount_amount | filterMoney}}
</p>
<p v-if="code_discount_amount * 1 > 0">
{{lang.shoppingCar_tip_text4}}{{commonData.currency_prefix}}
{{ code_discount_amount | filterMoney }}
</p>
</div>
<i class="el-icon-warning-outline total-icon" slot="reference"></i>
</el-popover>
<p class="original-price"
v-if="customfield.promo_code && totalPrice != base_price">
{{commonData.currency_prefix}} {{ base_price | filterMoney}}
</p>
<p class="original-price"
v-if="!customfield.promo_code && totalPrice != original_price">
{{commonData.currency_prefix}} {{ original_price | filterMoney}}
</p>
<div class="code-box">
<!-- 优惠码 -->
<discount-code v-show="hasShowPromo && !customfield.promo_code"
@get-discount="getRenewDiscount(arguments)"
:scene="demand ? 'change_billing_cycle' : 'renew'" :product_id="product_id"
:amount="base_price" :billing_cycle_time="duration"></discount-code>
</div>
<div class="code-number-text">
<div class="discount-codeNumber" v-show="customfield.promo_code">
{{ customfield.promo_code }}<i class="el-icon-circle-close remove-discountCode"
@click="removeRenewDiscountCode"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="dialog-footer">
<el-button :loading="submitLoading" type="primary" class="btn-ok" @click="subRenew">
{{demand ? lang.mf_demand_tip9 : lang.common_cloud_btn30}}
</el-button>
<div class="btn-no" @click="renewDgClose">{{lang.common_cloud_btn29}}</div>
</div>
</el-dialog>
</div>
`,
data() {
return {
isShowRenew: false,
currency_prefix: "",
currency_suffix: "",
commonData: {},
submitLoading: false,
renewList: [],
hasClientLevel: false,
hasShowPromo: false,
hasShowCash: false,
useDiscount: false,
level_discount_amount: 0, // 用户等级优惠金额
code_discount_amount: 0, // 优惠码优惠金额
duration: 0, // 续费周期
customfield: {
promo_code: "",
voucher_get_id: "",
},
billing_cycle: "",
selected_id: 0,
original_price: 0,
base_price: 0,
renewLoading: false,
};
},
props: {
demand: {
type: Boolean,
default: false,
},
id: {
type: Number,
default: 0,
required: true,
},
product_id: {
type: Number,
default: 0,
required: true,
},
renew_amount: {
type: Number,
default: 0,
},
billing_cycle_time: {
type: Number,
default: 0,
},
billing_cycle_name: {
type: String,
default: "",
},
},
created() {
// 加载css
if (
!document.querySelector(
'link[href="' + url + 'components/renewDialog/renewDialog.css"]'
)
) {
const link = document.createElement("link");
link.rel = "stylesheet";
link.href = `${url}components/renewDialog/renewDialog.css`;
document.head.appendChild(link);
}
this.hasClientLevel = havePlugin("IdcsmartClientLevel");
this.hasShowPromo = havePlugin("PromoCode");
this.hasShowCash = havePlugin("IdcsmartVoucher");
this.getCommon();
},
computed: {
totalPrice() {
const goodsPrice =
this.hasShowPromo && this.customfield.promo_code
? this.base_price
: this.original_price;
const discountPrice =
this.level_discount_amount + this.code_discount_amount;
const totalPrice = goodsPrice - discountPrice;
const nowPrice = totalPrice > 0 ? totalPrice.toFixed(2) : 0;
const showPirce = Number(nowPrice);
return showPirce > 0 ? showPirce.toFixed(2) : 0;
},
},
methods: {
// 显示续费弹窗
showRenew() {
if (this.isShowRenew) return;
// 获取续费页面信息
const params = {
id: this.id,
};
this.renewLoading = true;
this.submitLoading = true;
this.isShowRenew = true;
const getRenewApi = this.demand
? apiGetDemandToPrepaymentPrice
: renewPage;
getRenewApi(params)
.then(async (res) => {
this.submitLoading = false;
this.renewLoading = false;
if (res.data.status === 200) {
this.renewList = res.data.data.host || res.data.data.duration || [];
this.selected_id = this.renewList[0].id;
this.billing_cycle = this.renewList[0].billing_cycle;
this.duration = this.renewList[0].duration;
this.original_price = this.renewList[0].price;
this.base_price = this.renewList[0].base_price;
}
})
.catch((err) => {
this.submitLoading = false;
this.renewLoading = false;
this.isShowRenew = false;
this.$message.error(err.data.msg);
});
},
// 续费使用优惠码
async getRenewDiscount(data) {
this.customfield.promo_code = data[1];
this.useDiscount = true;
this.code_discount_amount = Number(data[0]);
this.level_discount_amount = await this.getClientLevelAmount(
this.base_price
);
},
// 移除续费的优惠码
removeRenewDiscountCode() {
this.useDiscount = false;
this.customfield.promo_code = "";
this.code_discount_amount = 0;
this.level_discount_amount = 0;
},
// 续费弹窗关闭
renewDgClose() {
this.isShowRenew = false;
this.selected_id = 0;
this.duration = 0;
this.billing_cycle = "";
this.original_price = 0;
this.base_price = 0;
this.renewList = [];
this.customfield = {
promo_code: "",
voucher_get_id: "",
};
this.code_discount_amount = 0;
this.level_discount_amount = 0;
this.removeRenewDiscountCode();
},
async getClientLevelAmount(amount) {
try {
if (!this.hasClientLevel) {
return 0;
}
const params = {id: this.product_id, amount: amount};
const res = await apiClientLevelAmount(params);
return Number(res.data.data.discount);
} catch (error) {
this.$message.error(error.data.msg);
return 0;
}
},
async getPromoDiscount(amount) {
try {
if (!this.hasShowPromo || !this.useDiscount) {
return 0;
}
const params = {
scene: this.demand ? "change_billing_cycle" : "renew",
product_id: this.product_id,
amount: amount,
billing_cycle_time: this.duration,
promo_code: this.customfield.promo_code,
};
// 更新优惠码
const res = await applyPromoCode(params);
return Number(res.data.data.discount);
} catch (error) {
this.useDiscount = false;
this.customfield.promo_code = "";
this.level_discount_amount = 0;
this.$message.error(error.data.msg);
return 0;
}
},
// 续费周期点击
async renewItemChange(item) {
this.submitLoading = true;
this.selected_id = item.id;
this.duration = item.duration;
this.billing_cycle = item.billing_cycle;
this.original_price = item.price;
this.base_price = item.base_price;
// 开启了优惠码插件
this.level_discount_amount = await this.getClientLevelAmount(
item.base_price
);
this.code_discount_amount = await this.getPromoDiscount(item.base_price);
this.submitLoading = false;
},
// 续费提交
subRenew() {
this.submitLoading = true;
const params = {
id: this.id,
billing_cycle: this.billing_cycle,
customfield: this.customfield,
duration_id: this.selected_id,
};
const subApi = this.demand ? apiDemandToPrepayment : apiRenew;
subApi(params)
.then((res) => {
this.submitLoading = false;
if (res.data.status === 200) {
if (res.data.code == "Paid") {
this.isShowRenew = false;
this.$message.success(res.data.msg);
this.$emit("success");
} else {
this.isShowRenew = false;
this.$emit("pay", res.data.data.id);
}
}
})
.catch((err) => {
this.submitLoading = false;
this.$message.error(err.data.msg);
});
},
getCommon() {
this.commonData = JSON.parse(localStorage.getItem("common_set_before"));
this.currency_prefix = this.commonData.currency_prefix;
this.currency_suffix = this.commonData.currency_suffix;
},
},
};

View File

@@ -0,0 +1,122 @@
.common-renew-dialog {
.dialog-main {
.renew-content {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 105%;
.renew-item {
width: 1.6rem;
min-height: .83rem;
border: 1px solid #E6E7EB;
border-radius: 3px;
display: flex;
flex-direction: column;
align-items: center;
margin-right: .2rem;
margin-bottom: .2rem;
cursor: pointer;
position: relative;
box-sizing: border-box;
&:nth-child(3) {
margin-right: 0;
}
&:nth-child(6) {
margin-right: 0;
}
.item-top {
font-size: .15rem;
color: #1E2736;
margin-top: .08rem;
}
.item-bottom {
font-size: .15rem;
color: var(--color-primary);
margin-top: .04rem;
}
.check {
position: absolute;
right: 0;
bottom: 0;
z-index: 3;
color: #FFF;
}
.item-origin-price {
text-decoration: line-through;
font-size: 0.15rem;
color: #8692B0;
}
}
.renew-active {
box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.12);
&::after {
content: '';
position: absolute;
bottom: 0;
right: 0;
z-index: 2;
width: 0;
height: 0;
border-bottom: 0.24rem solid var(--color-primary);
border-left: 0.24rem solid transparent;
}
}
}
.pay-content {
border: 1px solid #E6E7EB;
border-radius: 3px;
padding: 0.2rem 0;
padding-right: 0.3rem;
.pay-price {
display: flex;
text-align: right;
flex-direction: row;
.text {
font-size: 0.14rem;
margin-top: .1rem;
color: #1E2736;
margin-right: 1.43rem;
}
.money {
width: 100%;
font-size: .28rem;
font-weight: bold;
color: var(--color-price-text);
text-align: right;
}
.total-icon {
font-size: 0.16rem;
color: #1E2736;
}
.original-price {
text-decoration: line-through;
font-size: 0.2rem;
font-weight: 500;
color: #999999;
}
}
}
}
}

View File

@@ -0,0 +1,171 @@
.qrcode-status {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.qrcode-status.loading {
color: #999;
}
.qrcode-status.error {
color: #f56c6c;
}
.common-auth-info .top {
display: flex;
align-items: center;
margin-bottom: 10px;
}
.common-auth-info .top .tit {
font-size: 16px;
font-weight: 500;
margin: 0;
}
.common-auth-info .top .reset-auth {
cursor: pointer;
font-size: 14px;
}
.common-auth-info .top .reset-auth:hover {
opacity: 0.8;
}
.common-auth-info .bot-info {
display: flex;
align-items: center;
}
.common-auth-info .bot-info .label {
color: #606266;
}
.common-auth-info .bot-info .status.reject {
color: #f56c6c;
}
.common-auth-info .bot-info .status.pending {
color: #e6a23c;
}
.common-auth-info .bot-info .status.pending .cancel-auth {
margin-left: 10px;
color: var(--color-primary);
cursor: pointer;
}
.common-auth-info .bot-info .status.pending .cancel-auth:hover {
opacity: 0.8;
}
.common-auth-info .bot-info .status.approved {
color: #67c23a;
}
.common-auth-dialog .dialog-title {
font-size: 18px;
font-weight: 500;
text-align: center;
margin-bottom: 0.6rem;
}
.common-auth-dialog .tip {
color: #606266;
font-size: 14px;
margin-bottom: 15px;
}
.common-auth-dialog .tip.primary-color {
color: var(--color-primary);
}
.common-auth-dialog .auth-info-display .base-info {
display: flex;
gap: 40px;
margin-bottom: 20px;
}
.common-auth-dialog .auth-info-display .base-info .item .s-tit {
font-weight: 500;
margin-bottom: 10px;
}
.common-auth-dialog .auth-info-display .base-info .item .info-row {
margin-bottom: 8px;
}
.common-auth-dialog .auth-info-display .base-info .item .info-row .label {
color: #909399;
}
.common-auth-dialog .auth-info-display .base-info .item .info-row .value {
color: #303133;
}
.common-auth-dialog .auth-info-display .base-info .item .info-row .value.primary-color {
color: var(--color-primary);
}
.common-auth-dialog .auth-info-display .domain-tip {
color: #909399;
font-size: 12px;
margin-top: 5px;
}
.common-auth-dialog .reason-section {
margin-top: 20px;
}
.common-auth-dialog .method-selection {
display: flex;
gap: 20px;
margin-top: 20px;
}
.common-auth-dialog .method-selection .method-card {
flex: 1;
padding: 20px;
border: 1px solid #dcdfe6;
border-radius: 8px;
text-align: center;
cursor: pointer;
transition: all 0.3s;
}
.common-auth-dialog .method-selection .method-card:hover {
border-color: var(--color-primary);
box-shadow: 0 2px 12px rgba(64, 158, 255, 0.2);
}
.common-auth-dialog .method-selection .method-card h4 {
margin: 0 0 10px;
font-size: 16px;
color: #303133;
}
.common-auth-dialog .method-selection .method-card p {
color: #909399;
margin-bottom: 15px;
}
.common-auth-dialog .verify-content .user-info {
background: #f5f7fa;
padding: 15px;
border-radius: 8px;
margin: 15px 0;
}
.common-auth-dialog .verify-content .user-info .info-row {
margin-bottom: 8px;
}
.common-auth-dialog .verify-content .user-info .info-row:last-child {
margin-bottom: 0;
}
.common-auth-dialog .verify-content .user-info .info-row .label {
color: #909399;
}
.common-auth-dialog .verify-content .user-info .info-row .value {
color: #303133;
}
.common-auth-dialog .verify-content .user-info .info-row .value.primary-color {
color: var(--color-primary);
}
.common-auth-dialog .verify-content .qr-section {
text-align: center;
margin-top: 20px;
}
.common-auth-dialog .verify-content .qr-section > p {
color: #606266;
margin-bottom: 15px;
}
.common-auth-dialog .verify-content .qr-section .qr-code {
display: flex;
justify-content: center;
margin-bottom: 15px;
}
.common-auth-dialog .verify-content .qr-section .qr-code #qrcode-container {
width: 150px;
height: 150px;
display: flex;
align-items: center;
justify-content: center;
}
.common-auth-dialog .verify-content .qr-section .verify-status {
margin-top: 10px;
}
.common-auth-dialog .dialog-footer {
margin-top: 30px;
text-align: center;
}

View File

@@ -0,0 +1,567 @@
// 加载组件样式
(function () {
if (!document.querySelector('link[href*="resetAuth.css"]')) {
const link = document.createElement("link");
link.rel = "stylesheet";
link.href = `${url}components/resetAuth/resetAuth.css`;
document.head.appendChild(link);
}
})();
const resetAuth = {
template: `
<div>
<!-- 授权 -->
<div class="common-auth-info">
<div class="top">
<p class="tit">{{lang.reset_auth_detail_title}}</p>
<span class="reset-auth" @click="handleResetAuth" v-if="hasRestAuth && authDialog.status !== 'pending'">{{lang.reset_auth_reset_button}}</span>
</div>
<div class="bot-info" v-if="hasRestAuth">
<span class="label">{{lang.reset_auth_status_label}}</span>
<div class="status">
<div class="status reject" v-if="authDialog.status === 'rejected'">{{lang.reset_auth_status_failed}}{{authDialog.reject_reason}}
</div>
<div class="status pending" v-if="authDialog.status === 'pending'">{{lang.reset_auth_status_pending}}<span class="cancel-auth"
@click="handleCancelAuth">{{lang.reset_auth_cancel_reset}}</span></div>
<div class="status approved" v-if="authDialog.status === 'approved'">{{lang.reset_auth_status_normal}}</div>
</div>
</div>
</div>
<!-- 授权重置弹窗 -->
<el-dialog :visible.sync="authDialog.visible" width="800px"
:close-on-click-modal="false" custom-class="common-auth-dialog " @close="closeAuthDialog">
<div class="dialog-title">
{{authDialogTitle}}
</div>
<div v-if="authDialog.currentStep === 'confirm'">
<p class="tip">{{lang.reset_auth_modify_tip}}</p>
</div>
<el-form :model="authDialog" status-icon :rules="rules" ref="ruleForm" label-width="100px"
label-position="top" class="demo-ruleForm">
<template v-if="authDialog.currentStep !== 'autoVerify'">
<div class="auth-info-display">
<div class="base-info">
<div class="item">
<p class="s-tit">{{lang.reset_auth_current_info}}</p>
<div class="info-row">
<span class="label">{{lang.reset_auth_ip_label}}</span>
<span class="value">{{authDialog.original_ip || '--'}}</span>
</div>
<div class="info-row">
<span class="label">{{lang.reset_auth_domain_label}}</span>
<span class="value">{{authDialog.original_domain || '--'}}</span>
</div>
</div>
<div class="item"
v-if="authDialog.currentStep === 'selectMethod' || authDialog.currentStep === 'manualReview'">
<p class="s-tit">{{lang.reset_auth_new_info}}</p>
<div class="info-row">
<span class="label">{{lang.reset_auth_ip_label}}</span>
<span class="value">{{authDialog.new_ip || '--'}}</span>
</div>
<div class="info-row">
<span class="label">{{lang.reset_auth_domain_label}}</span>
<span class="value">{{authDialog.new_domain || '--'}}</span>
</div>
</div>
</div>
<template v-if="authDialog.currentStep === 'confirm'">
<el-form-item :label="lang.reset_auth_new_ip" prop="new_ip">
<el-input v-model="authDialog.new_ip" :placeholder="lang.reset_auth_ip_placeholder"></el-input>
</el-form-item>
<el-form-item :label="lang.reset_auth_new_domain" prop="new_domain">
<el-input v-model="authDialog.new_domain" :placeholder="lang.reset_auth_domain_placeholder"></el-input>
</el-form-item>
<p class="domain-tip">{{lang.reset_auth_domain_tip}}</p>
<p class="domain-tip">{{lang.reset_auth_domain_example}}</p>
</template>
</div>
</template>
<!-- 申请理由 -->
<div class="reason-section" v-if="authDialog.currentStep !== 'confirm' && authDialog.currentStep !== 'autoVerify'">
<el-form-item :label="lang.reset_auth_apply_reason" prop="reset_reason">
<el-input type="textarea" v-model="authDialog.reset_reason" :rows="4" :maxlength="300"
show-word-limit :placeholder="lang.reset_auth_reason_placeholder">
</el-input>
</el-form-item>
</div>
<!-- 方式选择 -->
<div v-if="authDialog.currentStep === 'selectMethod'">
<p class="tip">{{lang.reset_auth_select_verify_tip}}</p>
<div class="method-selection">
<div class="method-card" @click="selectVerifyMethod('manual')">
<h4>{{lang.reset_auth_manual_review}}</h4>
<p>{{lang.reset_auth_manual_review_desc}}</p>
<el-button>{{lang.reset_auth_submit_manual}}</el-button>
</div>
<div class="method-card" @click="selectVerifyMethod('auto')">
<h4>{{lang.reset_auth_auto_reset}}</h4>
<p>{{lang.reset_auth_auto_reset_desc}}</p>
<el-button>{{lang.reset_auth_start_auto}}</el-button>
</div>
</div>
</div>
<!-- 自动扫码认证 -->
<div class="verify-content" v-if="authDialog.currentStep === 'autoVerify'">
<p class="tip">{{lang.reset_auth_verify_tip}}</p>
<p class="tip primary-color">{{lang.reset_auth_current_verify_info}}</p>
<div class="user-info">
<div class="info-row">
<span class="label">{{lang.reset_auth_current_user}}</span>
<span class="value primary-color">{{authDialog.userInfo.username}}</span>
</div>
<div class="info-row">
<span class="label">{{lang.reset_auth_real_name}}</span>
<span class="value primary-color">{{authDialog.userInfo.card_name}}</span>
</div>
<div class="info-row">
<span class="label">{{lang.reset_auth_id_card}}</span>
<span class="value primary-color">{{authDialog.userInfo.card_number}}</span>
</div>
</div>
<div class="qr-section">
<p>{{lang.reset_auth_scan_tip}}</p>
<div class="qr-code">
<div id="qrcode-container">
<!-- 二维码将在这里生成 -->
</div>
</div>
<div class="verify-status">
<el-link :loading="verifying" type="primary" :underline="false" v-if="realnameStatus === 2">
<i class="el-icon-loading"></i>
{{lang.reset_auth_waiting_verify}}
</el-link>
<el-link type="success" :underline="false" v-if="realnameStatus === 1">{{lang.reset_auth_verify_success}}</el-link>
</div>
</div>
</div>
<!-- 动态底部按钮 -->
<div class="dialog-footer">
<template v-if="authDialog.currentStep === 'confirm'">
<el-button type="primary" @click="confirmAuthChange" :loading="submitLoading">{{lang.reset_auth_confirm_modify}}</el-button>
<el-button @click="closeAuthDialog">{{lang.reset_auth_cancel}}</el-button>
</template>
<template v-if="authDialog.currentStep === 'selectMethod'">
<el-button @click="goBackStep">{{lang.reset_auth_back}}</el-button>
<el-button @click="closeAuthDialog">{{lang.reset_auth_cancel}}</el-button>
</template>
<div v-show="authDialog.currentStep === 'autoVerify'">
<el-button type="primary" @click="handleSure" :disabled="realnameStatus === 2" :loading="submitLoading">{{lang.reset_auth_confirm_apply}}</el-button>
<el-button @click="closeAuthDialog">{{lang.reset_auth_cancel}}</el-button>
</div>
<!-- 人工审核提交转移到选择方式的时候直接提交
<template v-if="authDialog.currentStep === 'manualReview'">
<el-button type="primary" @click="submitReset" :loading="submitLoading">{{lang.reset_auth_submit_apply}}</el-button>
<el-button @click="closeAuthDialog">{{lang.reset_auth_cancel}}</el-button>
</template>
-->
</div>
</el-form>
</el-dialog>
</div>
`,
data() {
return {
hasRestAuth: false,
authDialog: {
visible: false,
currentStep: "confirm", // confirm -> selectMethod -> autoVerify/manualReview
host_id: "",
original_ip: "",
original_domain: "",
status: "",
application_id: "",
new_ip: "",
new_domain: "",
userInfo: {
username: "",
card_name: "",
card_number: "",
url: "",
certify_id: "",
},
reset_reason: "",
verifying: false,
},
// 实名状态
realnameStatus: 2, // 1通过 2未通过
verifying: true,
rules: {
new_ip: [
{
required: false,
pattern:
/^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
message: this.lang.reset_auth_ip_format_error,
trigger: "blur",
},
],
new_domain: [
{
required: false,
pattern:
/^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\.[a-zA-Z]{2,}$/,
message: this.lang.reset_auth_domain_format_error,
trigger: "blur",
},
],
reset_reason: [
{
required: true,
message: this.lang.reset_auth_reason_required,
trigger: "change",
},
],
},
submitLoading: false,
pollingTimer: null, // 轮询定时器
pollingTimeout: null, // 轮询超时定时器
qrCodeLibLoaded: false, // QRCode库是否已加载
};
},
components: {},
props: {
info: {
type: Object,
required: true,
default: () => {
return {
reject_reason: "", // 授权信息里面回显的拒绝理由
host_id: "",
original_ip: "",
original_domain: "",
status: "",
reset_reason: "", // 申请重置的理由
application_id: "",
};
},
},
},
created() {
if (this.info && Object.keys(this.info).length > 0) {
Object.assign(this.authDialog, this.info);
}
},
watch: {
info: {
handler(newVal) {
if (newVal && Object.keys(newVal).length > 0) {
Object.assign(this.authDialog, newVal);
}
},
deep: true,
immediate: false,
},
},
computed: {
authDialogTitle() {
const titleMap = {
confirm: this.lang.reset_auth_modify_title,
selectMethod: this.lang.reset_auth_modify_title,
autoVerify: this.lang.reset_auth_auto_reset,
manualReview: this.lang.reset_auth_manual_review,
};
return (
titleMap[this.authDialog.currentStep] ||
this.lang.reset_auth_modify_title
);
},
// 检查是否有授权信息变更
hasAuthChanges() {
const hasIPChange =
this.authDialog.new_ip.trim() !== "" &&
this.authDialog.new_ip !== this.authDialog.original_ip;
const hasDomainChange =
this.authDialog.new_domain.trim() !== "" &&
this.authDialog.new_domain !== this.authDialog.original_domain;
return hasIPChange || hasDomainChange;
},
},
mixins: [mixin],
mounted() {
this.hasRestAuth = this.addons_js_arr.includes("IdcsmartAuthreset");
},
methods: {
/* 授权相关方法 */
// 打开授权重置弹窗
handleResetAuth() {
this.authDialog.visible = true;
this.authDialog.currentStep = "confirm";
// 重置表单数据
this.authDialog.new_ip = this.authDialog.original_ip;
this.authDialog.new_domain = this.authDialog.original_domain;
this.authDialog.reset_reason = "";
this.authDialog.verifying = false;
},
/* 撤销重置 */
handleCancelAuth() {
this.$confirm(this.lang.reset_auth_cancel_confirm)
.then(async () => {
try {
const res = await apiCancelRest({
application_id: this.authDialog.application_id,
});
this.$message.success(res.data.msg);
this.$emit("cancel-auth");
} catch (error) {
this.$message.error(error.data?.msg);
}
})
.catch((_) => {});
},
// 确认授权修改
confirmAuthChange() {
if (!this.hasAuthChanges) {
this.submitReset();
} else {
this.$refs.ruleForm.validate((valid) => {
if (!valid) {
this.$message.error("请检查输入信息格式");
return;
}
this.authDialog.currentStep = "selectMethod";
});
}
},
// 选择验证方式
selectVerifyMethod(method) {
this.authDialog.reset_method = method;
this.submitReset();
},
// 开始自动验证
async startAutoVerify() {
try {
// application_id 提交申请过后返回的 application_id
const params = {
application_id: this.authDialog.application_id,
};
const res = await apiGetRealName(params);
this.authDialog.userInfo = res.data.data;
if (!this.authDialog.userInfo.url) {
this.realnameStatus = 2;
return this.$message.error("获取认证链接失败");
}
// 1. 根据 this.authDialog.userInfo.url生成二维码
this.generateQRCode(this.authDialog.userInfo.url);
// 2. 开始轮询状态
this.startPolling();
} catch (error) {
this.$message.error(error.data?.msg);
}
},
// 加载QRCode库
loadQRCodeLib() {
return new Promise((resolve) => {
if (typeof QRCode !== "undefined") {
this.qrCodeLibLoaded = true;
resolve();
return;
}
// 检查是否已有加载中的脚本
if (document.querySelector('script[src*="qrcode.min.js"]')) {
const checkLoaded = setInterval(() => {
if (typeof QRCode !== "undefined") {
clearInterval(checkLoaded);
this.qrCodeLibLoaded = true;
resolve();
}
}, 100);
return;
}
const script = document.createElement("script");
script.src = `${url}js/common/qrcode.min.js`;
script.onload = () => {
this.qrCodeLibLoaded = true;
resolve();
};
document.body.appendChild(script);
});
},
// 生成二维码
async generateQRCode(qrUrl) {
if (!qrUrl) return;
const container = document.getElementById("qrcode-container");
if (!container) return;
// 显示加载状态
container.innerHTML = '<div class="qrcode-status loading">生成中...</div>';
try {
// 确保QRCode库已加载
if (!this.qrCodeLibLoaded) {
await this.loadQRCodeLib();
}
if (typeof QRCode !== "undefined") {
container.innerHTML = "";
new QRCode(container, {
text: qrUrl,
width: 150,
height: 150,
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.M,
});
} else {
container.innerHTML = '<div class="qrcode-status error">二维码库加载失败</div>';
}
} catch (error) {
console.error("二维码生成错误:", error);
container.innerHTML = '<div class="qrcode-status error">二维码生成失败</div>';
}
},
// 开始轮询认证状态
startPolling() {
this.verifying = true;
this.realnameStatus = 2; // 重置为未通过状态
// 清除之前的轮询
if (this.pollingTimer) {
clearInterval(this.pollingTimer);
}
// 开始轮询每3秒检查一次
this.pollingTimer = setInterval(async () => {
try {
const result = await apiGetRealNameStatus({
application_id: this.authDialog.application_id,
certify_id: this.authDialog.userInfo.certify_id,
});
if (result.data && result.data.code === 1) {
// 认证成功
this.realnameStatus = 1;
this.verifying = false;
this.stopPolling();
}
} catch (error) {
this.verifying = false;
this.stopPolling();
this.$message.error("认证状态检查失败");
}
}, 3000);
// 设置最大轮询时间5分钟后自动停止
this.pollingTimeout = setTimeout(() => {
if (this.pollingTimer) {
this.stopPolling();
this.verifying = false;
this.realnameStatus = 2;
this.$message.warning("认证超时,请重试");
}
}, 300000);
},
// 停止轮询
stopPolling() {
if (this.pollingTimer) {
clearInterval(this.pollingTimer);
this.pollingTimer = null;
}
if (this.pollingTimeout) {
clearTimeout(this.pollingTimeout);
this.pollingTimeout = null;
}
},
async handleSure() {
try {
this.submitLoading = true;
const res = await apiAutoResetSure({
application_id: this.authDialog.application_id,
});
this.$message.success(res.data.msg);
this.submitLoading = false;
this.closeAuthDialog();
} catch (error) {
this.submitLoading = false;
this.$message.error(error.data?.msg);
}
},
// 提交审核申请
submitReset() {
this.$refs.ruleForm.validate(async (valid) => {
if (valid) {
try {
let params = {};
if (this.authDialog.currentStep !== "confirm") {
params = {
new_ip: this.authDialog.new_ip,
new_domain: this.authDialog.new_domain,
reset_reason: this.authDialog.reset_reason,
reset_method: this.authDialog.reset_method,
};
}
this.submitLoading = true;
params.host_id = this.authDialog.host_id;
const res = await apiRestAuth(params);
this.$message.success(res.data.msg);
const {application_id} = res.data.data;
this.authDialog.application_id = application_id;
this.submitLoading = false;
if (params.reset_method === "auto") {
this.authDialog.currentStep = "autoVerify";
this.startAutoVerify();
} else {
this.closeAuthDialog();
}
} catch (error) {
this.submitLoading = false;
this.$message.error(error.data?.msg);
}
} else {
return false;
}
});
},
// 返回上一步
goBackStep() {
const stepFlow = {
selectMethod: "confirm",
autoVerify: "selectMethod",
manualReview: "selectMethod",
};
this.authDialog.currentStep =
stepFlow[this.authDialog.currentStep] || "confirm";
},
// 关闭弹窗
closeAuthDialog() {
// 避免重复触发
if (!this.authDialog.visible) return;
// 停止轮询
this.stopPolling();
// 重置状态
this.verifying = false;
this.realnameStatus = 2;
// 清空二维码
const container = document.getElementById("qrcode-container");
if (container) {
container.innerHTML = "";
}
// 关闭弹窗
this.authDialog.visible = false;
this.authDialog.currentStep = "confirm";
// 重新拉取授权信息
this.$emit("cancel-auth");
},
/* 授权相关方法 end */
},
// 组件销毁时清理定时器
beforeDestroy() {
this.stopPolling();
},
};

View File

@@ -0,0 +1,230 @@
// 授权重置组件样式
// 二维码状态样式
.qrcode-status {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
&.loading {
color: #999;
}
&.error {
color: #f56c6c;
}
}
.common-auth-info {
.top {
display: flex;
align-items: center;
margin-bottom: 10px;
.tit {
font-size: 16px;
font-weight: 500;
margin: 0;
}
.reset-auth {
cursor: pointer;
font-size: 14px;
&:hover {
opacity: 0.8;
}
}
}
.bot-info {
display: flex;
align-items: center;
.label {
color: #606266;
}
.status {
&.reject {
color: #f56c6c;
}
&.pending {
color: #e6a23c;
.cancel-auth {
margin-left: 10px;
color: var(--color-primary);
cursor: pointer;
&:hover {
opacity: 0.8;
}
}
}
&.approved {
color: #67c23a;
}
}
}
}
// 授权重置弹窗
.common-auth-dialog {
.dialog-title {
font-size: 18px;
font-weight: 500;
text-align: center;
margin-bottom: 0.6rem;
}
.tip {
color: #606266;
font-size: 14px;
margin-bottom: 15px;
&.primary-color {
color: var(--color-primary);
}
}
.auth-info-display {
.base-info {
display: flex;
gap: 40px;
margin-bottom: 20px;
.item {
.s-tit {
font-weight: 500;
margin-bottom: 10px;
}
.info-row {
margin-bottom: 8px;
.label {
color: #909399;
}
.value {
color: #303133;
&.primary-color {
color: var(--color-primary);
}
}
}
}
}
.domain-tip {
color: #909399;
font-size: 12px;
margin-top: 5px;
}
}
.reason-section {
margin-top: 20px;
}
// 方式选择
.method-selection {
display: flex;
gap: 20px;
margin-top: 20px;
.method-card {
flex: 1;
padding: 20px;
border: 1px solid #dcdfe6;
border-radius: 8px;
text-align: center;
cursor: pointer;
transition: all 0.3s;
&:hover {
border-color: var(--color-primary);
box-shadow: 0 2px 12px rgba(64, 158, 255, 0.2);
}
h4 {
margin: 0 0 10px;
font-size: 16px;
color: #303133;
}
p {
color: #909399;
margin-bottom: 15px;
}
}
}
// 自动验证
.verify-content {
.user-info {
background: #f5f7fa;
padding: 15px;
border-radius: 8px;
margin: 15px 0;
.info-row {
margin-bottom: 8px;
&:last-child {
margin-bottom: 0;
}
.label {
color: #909399;
}
.value {
color: #303133;
&.primary-color {
color: var(--color-primary);
}
}
}
}
.qr-section {
text-align: center;
margin-top: 20px;
> p {
color: #606266;
margin-bottom: 15px;
}
.qr-code {
display: flex;
justify-content: center;
margin-bottom: 15px;
#qrcode-container {
width: 150px;
height: 150px;
display: flex;
align-items: center;
justify-content: center;
}
}
.verify-status {
margin-top: 10px;
}
}
}
.dialog-footer {
margin-top: 30px;
text-align: center;
}
}

View File

@@ -0,0 +1,100 @@
const safeConfirm = {
template: `
<div>
<el-dialog width="6.8rem" :visible.sync="visible" :show-close=false @close="closeDialog" custom-class="withdraw-dialog">
<div class="dialog-title">
{{lang.account_tips_text3}}
</div>
<div class="dialog-main">
<el-form label-width="80px" ref="ruleForm" :rules="rules" :model="dataForm" label-position="top" @submit.native.prevent>
<el-form-item :label="lang.account_tips_text3" prop="password">
<el-input class="input-select" type="password" v-model="dataForm.password" autocomplete="off" :placeholder="lang.account_tips_text2"></el-input>
<el-checkbox v-model="remember" style="margin-top: 5px;color: #999;}">{{lang.account_tips_text13}}</el-checkbox>
</el-form-item>
</el-form>
</div>
<div slot="footer" class="dialog-footer">
<el-button class="btn-ok" type="primary" @click="save" v-loading="submitLoading">{{lang.cart_tip_text9}}</el-button>
<el-button class="btn-no" @click="closeDialog">{{lang.cart_tip_text10}}</el-button>
</div>
</el-dialog>
</div>
`,
data() {
return {
visible: false,
submitLoading: false,
passData: "",
callbackFun: "",
home_enforce_safe_method: [],
dataForm: {
password: "",
},
rules: {
password: [
{required: true, message: lang.account_tips_text2, trigger: "blur"},
],
},
remember: false,
};
},
computed: {},
props: {
password: {
type: String,
default: "",
},
isLogin: {
type: Boolean,
default: false,
},
},
watch: {},
created() {
this.home_enforce_safe_method =
JSON.parse(localStorage.getItem("common_set_before"))
?.home_enforce_safe_method || [];
},
methods: {
/**
* @param {String} callbackFun 回调函数名称
*/
openDialog(callbackFun) {
this.callbackFun = callbackFun;
this.dataForm.password = "";
this.$emit("update:password", this.dataForm.password);
// if (
// !this.home_enforce_safe_method.includes("operate_password") &&
// !this.isLogin
// ) {
// this.$emit("update:password", "noNeed");
// // 执行父级方法
// this.$emit("confirm", this.callbackFun);
// } else {
// this.visible = true;
// setTimeout(() => {
// this.$refs.ruleForm.resetFields();
// }, 0);
// }
this.visible = true;
setTimeout(() => {
this.$refs.ruleForm.resetFields();
}, 0);
},
closeDialog() {
this.visible = false;
},
save() {
this.$refs.ruleForm.validate((valid) => {
if (!valid) {
return false;
}
this.$emit("update:password", this.dataForm.password);
// 执行父级方法
this.$emit("confirm", this.callbackFun, this.remember ? 1 : 0);
this.closeDialog();
});
},
},
};

View File

@@ -0,0 +1,93 @@
const scrollText = {
template: /* html*/ `
<div class="scroll-container" ref="container">
<div
class="scroll-text"
ref="text"
:class="{ 'centered': !isOverflow }"
:style="textStyle"
@mouseenter="pause"
@mouseleave="resume"
>
<slot></slot>
<!-- loop 模式下复制一份实现无缝 -->
<span v-if="mode === 'loop' && isOverflow" class="clone">
<slot></slot>
</span>
</div>
</div>
`,
data() {
return {
duration: 0,
isOverflow: false,
paused: false,
containerWidth: 0,
textWidth: 0,
};
},
props: {
speed: {type: Number, default: 50}, // 像素/秒
pauseTime: {type: Number, default: 2}, // once 模式停顿时间(秒)
mode: {
type: String,
default: "loop", // 可选: loop, once, pause
},
},
computed: {
textStyle() {
// 不超出:静止居中
if (!this.isOverflow) {
return {transform: "translateX(0)"};
}
let animation = "";
if (this.mode === "loop") {
animation = `scroll-loop ${this.duration}s linear infinite`;
} else if (this.mode === "once") {
// 每次滚动结束,停 pauseTime 秒
const totalTime = this.duration + this.pauseTime;
animation = `scroll-once ${totalTime}s linear infinite`;
} else if (this.mode === "pause") {
animation = `scroll-pause ${this.duration}s linear forwards`;
}
return {
animation,
"animation-play-state": this.paused ? "paused" : "running",
};
},
},
mounted() {
this.checkOverflow();
window.addEventListener("resize", this.checkOverflow);
},
beforeDestroy() {
window.removeEventListener("resize", this.checkOverflow);
},
methods: {
checkOverflow() {
this.$nextTick(() => {
const container = this.$refs.container;
const text = this.$refs.text;
if (!container || !text) return;
this.containerWidth = container.clientWidth;
this.textWidth = text.scrollWidth;
this.isOverflow = this.textWidth > this.containerWidth;
if (this.isOverflow) {
this.duration = this.textWidth / this.speed;
}
});
},
pause() {
this.paused = true;
},
resume() {
this.paused = false;
},
},
};

View File

@@ -0,0 +1,423 @@
const securityVerification = {
template: `
<div>
<el-dialog width="6rem" :visible.sync="securityVisible" @close="closeSecurityDialog" custom-class="security-dialog"
:show-close="false">
<div class="security-title">
<span class="title-text">安全验证</span>
<span class="close-btn" @click="closeSecurityDialog">
<i class="el-icon-close"></i>
</span>
</div>
<div class="security-content">
<el-form label-width="80px" ref="securityForm" :model="securityForm" label-position="top" :rules="currentRules">
<el-form-item :label="lang.security_verify_text2" prop="method_id">
<el-select v-model="securityForm.method_id" style="width: 100%;" @change="methodChange" :placeholder="lang.security_verify_text7">
<el-option v-for="item in availableMethods" :key="item.value" :value="item.value" :label="item.label">
</el-option>
</el-select>
</el-form-item>
<el-form-item :label="calcCurrentMethod?.label" v-if="securityForm.method_id === 'phone_code'" prop="phone_code">
<div style="display: flex; align-items: center;gap: 10px;">
<el-input v-model="securityForm.phone_code" :placeholder="calcCurrentMethod?.tip">
</el-input>
<count-down-button ref="securityPhoneCodeBtnRef" :loading="phoneCodeLoading" @click.native="sendPhoneCode" my-class="code-btn" >
</count-down-button>
</div>
</el-form-item>
<el-form-item :label="calcCurrentMethod?.label" v-if="securityForm.method_id === 'email_code'" prop="email_code">
<div style="display: flex; align-items: center;gap: 10px;">
<el-input v-model="securityForm.email_code" :placeholder="calcCurrentMethod?.tip">
</el-input>
<count-down-button ref="securityEmailCodeBtnRef" :loading="emailCodeLoading" @click.native="sendEmailCode" my-class="code-btn" >
</count-down-button>
</div>
</el-form-item>
<el-form-item :label="calcCurrentMethod?.label" v-if="securityForm.method_id === 'operate_password'" prop="operate_password">
<el-input v-model="securityForm.operate_password" :placeholder="calcCurrentMethod?.placeholder"></el-input>
</el-form-item>
<el-form-item :label="calcCurrentMethod?.label" v-if="securityForm.method_id === 'certification'" prop="certification">
<div class="realname-verify-box">
<div ref="realnameVerifyRef" id="realnameVerify" style="display: flex; align-items: center; justify-content: center;"></div>
<p style="text-align: center;margin-top: 10px;">{{calcCurrentMethod?.tip}}</p>
</div>
</el-form-item>
</el-form>
</div>
<div class="security-footer">
<el-button type="primary" @click="confirmSecurity" :loading="confirmSecurityLoading">{{lang.finance_btn8}}</el-button>
<el-button type="info" class="cancel-btn" @click="closeSecurityDialog">{{lang.finance_btn7}}</el-button>
</div>
</el-dialog>
<captcha-dialog :is-show-captcha="isShowCaptcha" ref="securityCaptchaRef" captcha-id="security-captcha"
@get-captcha-data="getData" @captcha-cancel="captchaCancel">
</captcha-dialog>
</div>
`,
components: {
captchaDialog,
countDownButton,
},
props: {
actionType: {
type: String,
default: "exception_login",
},
},
data() {
return {
commonData: {},
phoneCodeLoading: false, // 手机验证码loading
emailCodeLoading: false, // 邮箱验证码loading
securityVisible: false, // 安全验证弹窗是否显示
confirmSecurityLoading: false, // 确认按钮loading
realnameStatus: false, // true通过 false未通过
verifying: false, // 是否正在验证
pollingTimer: null, // 轮询定时器
pollingTimeout: null, // 轮询超时定时器
securityForm: {
method_id: "", // 验证方式
phone_code: "", // 手机验证码
email_code: "", // 邮箱验证码
operate_password: "", // 操作密码
certification: "", // 实名验证
},
callbackFun: "", // 回调函数名称
availableMethods: [], // 可用验证方式
certify_id: "", // 认证ID
certify_url: "", // 认证URL
isShowCaptcha: false, //登录是否显示验证码弹窗
codeAction: "",
};
},
computed: {
currentRules() {
const {method_id} = this.securityForm;
const base = {
method_id: [{required: true, message: lang.security_verify_text7}],
};
if (method_id === "phone_code") {
base.phone_code = [
{required: true, message: lang.security_verify_text8},
];
}
if (method_id === "email_code") {
base.email_code = [
{required: true, message: lang.security_verify_text9},
];
}
if (method_id === "operate_password") {
base.operate_password = [
{required: true, message: lang.security_verify_text10},
];
}
if (method_id === "certification") {
base.certification = [
{required: true, message: lang.security_verify_text11},
];
}
return base;
},
calcCurrentMethod() {
return (
this.availableMethods.find(
(item) => item.value === this.securityForm.method_id
) || {}
);
},
},
methods: {
/**
* @param {String} callbackFun 回调函数名称
*/
openDialog(callbackFun, availableMethods = []) {
this.callbackFun = callbackFun;
this.availableMethods = availableMethods;
this.account = availableMethods[0]?.account || "";
this.phone_code = availableMethods[0]?.phone_code || "";
this.confirmSecurityLoading = false;
this.securityForm = {
method_id: availableMethods[0]?.value || "",
phone_code: "",
email_code: "",
operate_password: "",
certification: "",
};
this.stopPolling();
this.realnameStatus = false; // 重置为未通过状态
this.verifying = false; // 重置为未验证状态
this.securityVisible = true; // 显示安全验证弹窗
this.$nextTick(() => {
this.methodChange(availableMethods[0]?.value || "");
});
},
closeSecurityDialog() {
this.$refs.securityForm.resetFields();
if (this.$refs.realnameVerifyRef) {
this.$refs.realnameVerifyRef.innerHTML = "";
}
this.securityVisible = false;
this.stopPolling();
},
confirmSecurity() {
this.$refs.securityForm.validate((valid) => {
if (valid) {
if (this.securityForm.method_id === "certification") {
// 判断实名状态
if (!this.realnameStatus) {
this.$message.error(lang.security_verify_text11);
return;
}
}
this.confirmSecurityLoading = true;
this.$emit("confirm", this.callbackFun, {
security_verify_method: this.securityForm.method_id,
security_verify_value:
this.securityForm[this.securityForm.method_id],
certify_id:
this.securityForm.method_id === "certification"
? this.certify_id
: "",
security_verify_token:
this.calcCurrentMethod?.security_verify_token || "",
});
this.confirmSecurityLoading = false;
this.closeSecurityDialog();
}
});
},
methodChange(value) {
this.stopPolling();
this.securityForm.phone_code = "";
this.securityForm.email_code = "";
this.securityForm.operate_password = "";
this.securityForm.certification = "";
this.account =
this.availableMethods.find((item) => item.value === value)?.account ||
"";
this.phone_code =
this.availableMethods.find((item) => item.value === value)
?.phone_code || "";
if (value === "certification") {
this.$nextTick(async () => {
try {
const res = await apiCreateCertification({
account: this.account,
phone_code: this.phone_code,
security_verify_token:
this.calcCurrentMethod?.security_verify_token || "",
});
this.certify_id = res.data.data.certify_id;
this.certify_url = res.data.data.certify_url;
this.generateQRCode(this.certify_url);
this.startPolling();
} catch (error) {
console.error("创建认证失败:", error);
this.$message.error(error?.data?.msg || "创建认证失败,请重试");
}
});
}
},
sendPhoneCode(isAuto = false) {
if (this.phoneCodeLoading) return;
if (isAuto !== true) {
this.token = "";
this.captcha = "";
}
if (
this.commonData.captcha_client_security_verify == 1 &&
!this.captcha
) {
this.codeAction = "phoneCode";
this.isShowCaptcha = true;
this.$refs.securityCaptchaRef.doGetCaptcha();
return;
}
this.phoneCodeLoading = true;
const params = {
action: this.actionType,
phone_code: this.phone_code ?? undefined,
phone: this.account ?? undefined,
token: this.token,
captcha: this.captcha,
};
phoneCode(params)
.then((res) => {
if (res.data.status === 200) {
this.phoneCodeLoading = false;
// 执行倒计时
this.$refs.securityPhoneCodeBtnRef.countDown();
this.$message.success(res.data.msg);
}
})
.catch((err) => {
this.phoneCodeLoading = false;
this.$message.error(err.data.msg);
});
},
sendEmailCode(isAuto = false) {
if (this.emailCodeLoading) return;
if (isAuto !== true) {
this.token = "";
this.captcha = "";
}
if (
this.commonData.captcha_client_security_verify == 1 &&
!this.captcha
) {
this.codeAction = "emailCode";
this.isShowCaptcha = true;
this.$refs.securityCaptchaRef.doGetCaptcha();
return;
}
this.emailCodeLoading = true;
const params = {
action: this.actionType,
email: this.account,
token: this.token,
captcha: this.captcha,
};
emailCode(params)
.then((res) => {
this.$message.success(res.data.msg);
this.emailCodeLoading = false;
this.$refs.securityEmailCodeBtnRef.countDown();
})
.catch((err) => {
this.emailCodeLoading = false;
this.$message.error(err.data.msg);
});
},
loadQRCodeLib() {
return new Promise((resolve) => {
const script = document.createElement("script");
script.src = `${url}js/common/qrcode.min.js`;
script.onload = resolve;
document.body.appendChild(script);
});
},
// 生成二维码
generateQRCode(url) {
if (!url) return;
// 清空之前的二维码
const container = this.$refs.realnameVerifyRef;
if (container) {
// 显示加载状态
container.innerHTML =
'<div style="display: flex; align-items: center; justify-content: center; height: 100%; color: #999;">生成中...</div>';
try {
// 使用QRCode.js库生成二维码需要确保已引入
if (typeof QRCode !== "undefined") {
container.innerHTML = "";
new QRCode(container, {
text: url,
width: 200,
height: 200,
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.M,
});
}
} catch (error) {
console.error("二维码生成错误:", error);
container.innerHTML =
'<div style="display: flex; align-items: center; justify-content: center; height: 100%; color: #f56c6c;">二维码生成失败</div>';
}
}
},
// 开始轮询认证状态
startPolling() {
this.verifying = true;
this.realnameStatus = false; // 重置为未通过状态
// 清除之前的轮询
if (this.pollingTimer) {
clearInterval(this.pollingTimer);
}
// 开始轮询每3秒检查一次
this.pollingTimer = setInterval(async () => {
try {
const result = await apiGetCertificationStatus({
certify_id: this.certify_id,
account: this.account,
phone_code: this.phone_code,
security_verify_token:
this.calcCurrentMethod?.security_verify_token || "",
});
if (result?.data?.data?.verify_status === 1) {
// 认证成功
this.realnameStatus = true;
this.verifying = false;
this.stopPolling();
this.securityForm.certification = this.certify_id;
this.confirmSecurity();
}
} catch (error) {
this.verifying = false;
this.stopPolling();
this.$message.error("认证状态检查失败");
}
}, 3000);
// 设置最大轮询时间5分钟后自动停止
this.pollingTimeout = setTimeout(() => {
if (this.pollingTimer) {
this.stopPolling();
this.verifying = false;
this.realnameStatus = false;
this.$message.warning("认证超时,请重试");
}
}, 300000);
},
// 停止轮询
stopPolling() {
if (this.pollingTimer) {
clearInterval(this.pollingTimer);
this.pollingTimer = null;
}
if (this.pollingTimeout) {
clearTimeout(this.pollingTimeout);
this.pollingTimeout = null;
}
},
// 获取通用配置
getCommonData() {
this.commonData = JSON.parse(
localStorage.getItem("common_set_before") || "{}"
);
},
// 验证码验证成功后的回调
getData(captchaCode, token) {
this.isShowCaptcha = false;
this.token = token;
this.captcha = captchaCode;
if (this.codeAction === "emailCode") {
this.sendEmailCode(true);
} else if (this.codeAction === "phoneCode") {
this.sendPhoneCode(true);
}
},
// 验证码 关闭
captchaCancel() {
this.isShowCaptcha = false;
},
},
async mounted() {
this.getCommonData();
await this.loadQRCodeLib();
},
// 组件销毁时清理定时器
beforeDestroy() {
this.stopPolling();
},
};

View File

@@ -0,0 +1,39 @@
const shadowContent = {
template: /* html*/ `
<div ref="shadow"></div>
`,
props: {
content: {
type: String,
default: "",
},
},
data() {
return {
shadowRoot: null,
};
},
mounted() {
this.shadowRoot = this.$refs.shadow.attachShadow({mode: "open"});
this.renderShadow();
},
// 内容变动时更新 Shadow DOM
watch: {
content() {
this.renderShadow();
},
},
methods: {
renderShadow() {
this.shadowRoot.innerHTML = `
<style>
img {
max-width: 100%;
height: auto;
}
</style>
${this.content}
`;
},
},
};

View File

@@ -0,0 +1,616 @@
// css 样式依赖common.css
ELEMENT.Dialog.props.closeOnClickModal.default = false;
const topMenu = {
template: /*html*/ `
<div>
<el-drawer :visible.sync="isShowMenu" direction="ltr" :before-close="handleClose" :with-header="false" size="3.8rem"
custom-class="drawer-menu">
<div class="drawer-menu-top">
<a :href="commonData.clientarea_logo_url || '/home.htm'" onclick="return false" class="menu-alink">
<img class="drawer-menu-logo" @click="goHome" :src="logo"></img>
</a>
</div>
<div class="drawer-menu-list-top">
<el-menu class="menu-top" :default-active="menuActiveId" @select="handleSelect" background-color="transparent"
text-color="var(--color-menu-text)" active-text-color="var(--color-menu-text-active)">
<template v-for="item in menu1">
<!-- 只有一级菜单 -->
<el-menu-item v-if="!item.child || item.child?.length === 0" :key="item.id"
:index="item.id ? item.id + '' : item.url" :id="item.url">
<a :href="getMenuUrl(item.id || item.url)" onclick="return false" class="menu-alink">
<i class="iconfont" :class="item.icon"></i>
<span class="aside-menu-text" slot="title">{{item.name}}</span>
</a>
</el-menu-item>
<!-- 有二级菜单 -->
<el-submenu v-else :key="item.id" :index="item.id ? item.id + '' : item.url" :id="item.url">
<template slot="title">
<i class="iconfont" :class="item.icon"></i>
<span class="aside-menu-text" slot="title">{{item.name}}</span>
</template>
<template v-for="child in item.child">
<el-menu-item :index="child.id ? child.id + '' : child.url" :key="child.id">
<a :href="getMenuUrl(child.id || child.url)" onclick="return false" class="menu-alink">
{{child.name}}
</a>
</el-menu-item>
</template>
</el-submenu>
</template>
</el-menu>
<div class="line" v-if="hasSeparate"></div>
<el-menu class="menu-top" :default-active="menuActiveId " @select="handleSelect" background-color="transparent"
text-color="var(--color-menu-text)" active-text-color="var(--color-menu-text-active)">
<template v-for="item in menu2">
<!-- 只有一级菜单 -->
<el-menu-item v-if="!item.child || item.child?.length === 0" :key="item.id"
:index="item.id ? item.id + '' : item.url" :id="item.url">
<a :href="getMenuUrl(item.id || item.url)" onclick="return false" class="menu-alink">
<i class="iconfont" :class="item.icon"></i>
<span class="aside-menu-text" slot="title">{{item.name}}</span>
</a>
</el-menu-item>
<!-- 有二级菜单 -->
<el-submenu v-else :key="item.id" :index="item.id ? item.id + '' : item.url" :id="item.url">
<template slot="title">
<i class="iconfont" :class="item.icon"></i>
<span class="aside-menu-text" slot="title">{{item.name}}</span>
</template>
<template v-for="child in item.child">
<el-menu-item :index="child.id ? child.id + '' : child.url" :key="child.id">
<a :href="getMenuUrl(child.id || child.url)" onclick="return false" class="menu-alink">
{{child.name}}
</a>
</el-menu-item>
</template>
</el-submenu>
</template>
</el-menu>
</div>
</el-drawer>
<el-header>
<div class="header-left">
<img src="${url}/img/common/menu.png" class="menu-img" @click="showMenu">
<img v-if="isShowMore" src="${url}/img/common/search.png" class="left-img">
<el-autocomplete v-if="isShowMore" v-model="topInput" :fetch-suggestions="querySearchAsync" placeholder="请输入内容"
@select="handleSelect">
<template slot-scope="{ item }">
<div class="search-value">{{ item.value }}</div>
<div class="search-name">{{ item.name }}</div>
</template>
</el-autocomplete>
</div>
<div class="header-right">
<div class="header-right-item car-item">
<div v-if="isShowCart" class="right-item" @click="goShoppingCar">
<el-badge :value="shoppingCarNum" class="item" :max="999" :hidden="shoppingCarNum === 0 ? true : false">
<img src="${url}/img/common/cart.svg">
</el-badge>
</div>
</div>
<div class="header-right-item car-item" v-plugin="'ClientCare'">
<el-popover placement="bottom-start" trigger="hover" :visible-arrow="false">
<div class="top-msg-box">
<div class="msg-top">
<span class="msg-top-left">{{lang.subaccount_text56}}</span>
<span class="msg-top-right" @click="goAccount">{{lang.subaccount_text57}}</span>
</div>
<div class="msg-list" v-if="msgList.length !== 0">
<div class="msg-item" v-for="item in msgList" :key="item.id" @click="goMsgDetail(item.id)">
<div class="msg-item-left" :style="{color: item.read === 1 ? '#8692b0' : 'var(--color-primary)' }">
<svg t="1750123872473" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12811" width="16" height="16">
<path d="M440.35072 623.04768 46.04416 373.1456l0 393.62048c0 64.63488 52.53632 117.39136 117.31968 117.39136l706.71872 0c64.70656 0 117.31456-52.57728 117.31456-117.39136l0-387.1232-368.99328 242.10944C568.1408 654.72 491.07968 655.19104 440.35072 623.04768L440.35072 623.04768 440.35072 623.04768z" fill="currentColor" p-id="12812"></path>
<path d="M870.08256 158.51008 163.35872 158.51008c-64.70656 0-117.31968 52.57728-117.31968 117.39136l0 0.90112 443.30496 280.96c20.83328 13.2096 58.27584 12.95872 78.93504-0.57856l419.1488-275.00032 0-6.28224C987.39712 211.3024 934.8608 158.51008 870.08256 158.51008L870.08256 158.51008 870.08256 158.51008z" fill="currentColor" p-id="12813"></path>
</svg>
</div>
<div class="msg-item-right">
<div class="msg-item-right-top">{{item.title}}</div>
<div class="msg-item-right-bottom">
<span>{{msgType[item.type]}}</span>
<span>{{item.create_time | formateTime}}</span>
</div>
</div>
</div>
</div>
<el-empty v-else :description="lang.subaccount_text55"></el-empty>
</div>
<div class="right-item" slot="reference">
<el-badge :value="msgCount" class="item" :max="999" :hidden="msgCount === 0 ? true : false">
<img src="${url}/img/common/msg.svg">
</el-badge>
</div>
</el-popover>
</div>
<div class="header-right-item hg-24">
<el-dropdown @command="changeLang" trigger="click" :disabled="commonData.lang_home_open * 1 ? false : true">
<div class="el-dropdown-country">
<img :src="curSrc" alt="">
<i class="right-icon el-icon-arrow-down el-icon--right"></i>
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-for="item in commonData.lang_list" :key="item.display_lang"
:command="item.display_lang">{{item.display_name}}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<div class="header-right-item cloum-line-item" v-if="isGetData">
<div class="cloum-line"></div>
</div>
<div class="header-right-item" v-show="unLogin && isGetData">
<div class="un-login" @click="goLogin">
<img src="${url}/img/common/login_icon.png">{{lang.topMenu_text1}}
</div>
</div>
<div class="header-right-item" v-show="!unLogin && isGetData">
<el-dropdown @command="handleCommand" trigger="click">
<div class="el-dropdown-header">
<div class="right-item head-box" ref="headBoxRef" v-show="firstName">{{firstName}}</div>
<i class="right-icon el-icon-arrow-down el-icon--right"></i>
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="account">{{lang.topMenu_text2}}</el-dropdown-item>
<el-dropdown-item command="quit">{{lang.topMenu_text3}}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<coin-active ref="coinActive" v-plugin="'Coin'"></coin-active>
</div>
</el-header>
</div>
`,
directives: {
plugin: {
inserted: function (el, binding) {
const addonsDom = document.querySelector("#addons_js");
let addonsArr = [];
let arr = [];
if (addonsDom) {
addonsArr = JSON.parse(addonsDom.getAttribute("addons_js")) || []; // 插件列表
// 判断是否安装了某插件
arr = addonsArr.filter((item) => item.name === binding.value);
if (arr.length === 0) {
// 未安装 移除该元素的dom
el.parentNode.removeChild(el);
}
} else {
el.parentNode.removeChild(el);
}
},
},
},
components: {
coinActive,
},
data () {
return {
topInput: "",
// curSrc: url+'/img/common/'+lang_obj.countryImg+'.png' ,
curSrc: `/upload/common/country/${lang_obj.countryImg}.png`,
isShowMenu: false,
logo: `/upload/logo.png`,
menu1: [],
menu2: [],
menuActiveId: "",
firstName: "",
hasSeparate: false,
originMenu: [],
produclData: [],
selectValue: "",
shoppingCarNum: 0,
headBgcList: [
"#3699FF",
"#57C3EA",
"#5CC2D7",
"#EF8BA2",
"#C1DB81",
"#F1978C",
"#F08968",
],
commonData: {
lang_list: [],
},
unLogin: true,
isGetData: false,
msgList: [],
msgCount: 0,
accountData: {},
msgType: {
official: lang.subaccount_text54,
host: lang.finance_info,
finance: lang.finance_text123,
},
predefineColors: [
"#ff4500",
"#ff8c00",
"#ffd700",
"#90ee90",
"#00ced1",
"#1e90ff",
"#c71585",
"rgba(255, 69, 0, 0.68)",
"rgb(255, 120, 0)",
"hsv(51, 100, 98)",
"hsva(120, 40, 94, 0.5)",
"hsl(181, 100%, 37%)",
"hsla(209, 100%, 56%, 0.73)",
"#c7158577",
],
};
},
props: {
isShowMore: {
type: Boolean,
default: false,
},
isShowCart: {
type: Boolean,
default: true,
},
num: {
type: Number,
default: 0,
},
},
watch: {
num (val) {
if (val) {
this.shoppingCarNum = val;
}
},
},
filters: {
formateTime (time) {
if (time && time !== 0) {
const date = new Date(time * 1000);
Y = date.getFullYear() + "-";
M =
(date.getMonth() + 1 < 10
? "0" + (date.getMonth() + 1)
: date.getMonth() + 1) + "-";
D = (date.getDate() < 10 ? "0" + date.getDate() : date.getDate()) + " ";
h =
(date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) +
":";
m =
date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
return Y + M + D + h + m;
} else {
return "--";
}
},
},
created () {
this.GetIndexData();
this.doGetMenu();
this.getCartList();
this.getCommonSetting();
},
mounted () {
// 不生效
this.color1 = getComputedStyle(document.documentElement)
.getPropertyValue("--color-primary")
.trim();
if (this.getPluginId("ClientCare")) {
this.getMessageList();
}
},
methods: {
getPluginId (pluginName) {
const addonsDom = document.querySelector("#addons_js");
if (addonsDom) {
const addonsArr = JSON.parse(addonsDom.getAttribute("addons_js")); // 插件列表
for (let index = 0; index < addonsArr.length; index++) {
const element = addonsArr[index];
if (pluginName === element.name) {
return element.id;
}
}
} else {
console.log("请检查页面是否有插件dom");
}
},
goAccount () {
location.href = "/account.htm?type=3";
},
getMessageList () {
messageInfo().then((res) => {
this.msgList = res.data.data.credit_limit.list;
this.msgCount = res.data.data.credit_limit.count;
this.msgType = res.data.data.credit_limit.type.reduce((all, cur) => {
all[cur.name] = cur.name_lang;
return all;
}, {});
});
},
goMsgDetail (id) {
location.href = `/plugin/${getPluginId(
"ClientCare"
)}/msgDetail.htm?id=${id}`;
},
// 退出登录
logOut () {
this.$confirm(lang.topMenu_text4, lang.topMenu_text5, {
confirmButtonText: lang.topMenu_text6,
cancelButtonText: lang.topMenu_text7,
type: "warning",
})
.then(() => {
//const res = await Axios.post('/logout')
Axios.post("/logout").then((res) => {
localStorage.removeItem("jwt");
setTimeout(() => {
location.href = "/login.htm";
}, 300);
});
})
.catch(() => { });
},
goLogin () {
location.href = "/login.htm";
},
goHome () {
localStorage.frontMenusActiveId = "";
const openUrl = this.commonData.clientarea_logo_url || "/home.htm";
if (this.commonData.clientarea_logo_url_blank == 1) {
window.open(openUrl);
} else {
location.href = openUrl;
}
},
// 获取购物车数量
getCartList () {
cartList()
.then((res) => {
this.shoppingCarNum = res.data.data.list.filter(
(item) => item.customfield?.is_domain !== 1
).length;
})
.catch((err) => {
this.$message.error(err.data.msg);
});
},
GetIndexData () {
accountDetail()
.then((res) => {
if (res.data.status == 200) {
this.accountData = res.data.data.account;
localStorage.lang = res.data.data.account.language || "zh-cn";
this.firstName = res.data.data.account.username
.substring(0, 1)
.toUpperCase();
this.unLogin = false;
if (sessionStorage.headBgc) {
this.$refs.headBoxRef.style.background = sessionStorage.headBgc;
} else {
const index = Math.round(
Math.random() * (this.headBgcList.length - 1)
);
this.$refs.headBoxRef.style.background = this.headBgcList[index];
sessionStorage.headBgc = this.headBgcList[index];
}
}
})
.finally(() => {
this.isGetData = true;
});
},
goShoppingCar () {
localStorage.frontMenusActiveId = "";
location.href = "/cart/shoppingCar.htm";
},
goAccountpage () {
location.href = "/account.htm";
},
// 语言切换
changeLang (e) {
if (localStorage.getItem("lang") !== e || !localStorage.getItem("lang")) {
localStorage.setItem("lang", e);
sessionStorage.setItem("brow_lang", e);
let jwt = localStorage.getItem("jwt") || "";
if (jwt) {
this.accountData.language = e;
this.saveAccount();
} else {
this.changeLangHandle(e);
}
}
},
async changeLangHandle (e) {
try {
const res = await changeLanguage({
language: e,
});
this.$message.success(res.data.msg);
window.location.reload();
} catch (error) {
this.$message.error(error.data.msg);
}
},
// 编辑基础资料
saveAccount () {
const params = {
...this.accountData,
};
updateAccount(params)
.then((res) => {
if (res.data.status === 200) {
this.$message.success(res.data.msg);
window.location.reload();
}
})
.catch((error) => {
this.$message.error(error.data.msg);
});
},
handleCommand (e) {
if (e == "account") {
this.goAccountpage();
}
if (e == "quit") {
this.logOut();
}
console.log(e);
},
// 全局搜索
querySearchAsync (queryString, cb) {
if (queryString.length == 0) {
return false;
}
const params = {
keywords: queryString,
};
globalSearch(params).then((res) => {
if (res.data.status === 200) {
const data = res.data.data.hosts;
const result = [];
data.map((item) => {
let value = item.product_name + "#/" + item.id;
result.push({
id: item.id,
value,
name: item.name,
});
});
cb(result);
}
});
},
/*
* 获取菜单url
* @param {Number} id 菜单id 或者url
* @return {String} url 菜单url
*/
getMenuUrl (id) {
const temp =
this.originMenu.find((item) => item.id == id || item.url == id) || {};
const reg =
/^(((ht|f)tps?):\/\/)([^!@#$%^&*?.\s-]([^!@#$%^&*?.\s]{0,63}[^!@#$%^&*?.\s])?\.)+[a-z]{2,6}\/?/;
let url = "/" + temp.url;
if (reg.test(temp.url)) {
if (temp?.second_reminder === 1) {
url = `/transfer.htm?target=${encodeURIComponent(temp.url)}`;
} else {
url = temp.url;
}
}
return url;
},
handleSelect (id) {
localStorage.setItem("frontMenusActiveId", id);
const temp =
this.originMenu.find((item) => item.id == id || item.url == id) || {};
const reg =
/^(((ht|f)tps?):\/\/)([^!@#$%^&*?.\s-]([^!@#$%^&*?.\s]{0,63}[^!@#$%^&*?.\s])?\.)+[a-z]{2,6}\/?/;
if (reg.test(temp.url)) {
if (temp?.second_reminder === 1) {
return window.open(
`/transfer.htm?target=${encodeURIComponent(temp.url)}`
);
} else {
return window.open(temp.url);
}
}
location.href = "/" + temp.url;
},
showMenu () {
this.isShowMenu = true;
},
handleClose () {
this.isShowMenu = false;
},
// 获取前台导航
doGetMenu () {
getMenu().then((res) => {
if (res.data.status === 200) {
res.data.data.menu.forEach((item) => {
if (item.child && item.child.length > 0) {
this.originMenu.push(...item.child);
} else {
this.originMenu.push(item);
}
});
const menu = res.data.data.menu;
localStorage.setItem("frontMenus", JSON.stringify(menu));
let index = menu.findIndex((item) => item.name == "分隔符");
if (index != -1) {
this.hasSeparate = true;
this.menu1 = menu.slice(0, index);
this.menu2 = menu.slice(index + 1);
} else {
this.hasSeparate = false;
this.menu1 = menu;
}
this.setActiveMenu();
}
});
},
// 判断当前菜单激活
setActiveMenu () {
const originUrl = location.pathname.slice(1);
const allUrl = originUrl + location.search;
let flag = false;
this.originMenu.forEach((item) => {
// 当前url下存在和导航菜单对应的路径
if (!item.child && item.url) {
const url = String(item.url).split("?");
if (
(url.length > 1 && item.url == allUrl) ||
(url.length == 1 && item.url == originUrl)
) {
this.menuActiveId = item.id + "";
flag = true;
}
}
// 当前url下存在二级菜单
if (item.child && item.child.length > 0) {
item.child.forEach((child) => {
const url = String(child.url).split("?");
if (
(url.length > 1 && child.url == allUrl) ||
(url.length == 1 && child.url == originUrl)
) {
this.menuActiveId = child.id + "";
flag = true;
}
});
}
});
if (!flag) {
this.menuActiveId = localStorage.getItem("frontMenusActiveId") || "";
}
},
// 页面跳转
toPage (e) {
location.href = "/" + e.url;
},
// 获取通用配置
async getCommonSetting () {
try {
if (!localStorage.getItem("common_set_before")) {
const res = await getCommon();
this.commonData = res.data.data;
localStorage.setItem(
"common_set_before",
JSON.stringify(res.data.data)
);
}
this.commonData = JSON.parse(localStorage.getItem("common_set_before"));
this.logo = this.commonData.system_logo;
} catch (error) { }
},
},
};

View File

@@ -0,0 +1,108 @@
/* 流量预警 */
const trafficWarning = {
template: `
<div class="traffic-warning">
<div class="search-btn" @click="handleConfig">{{lang.flow_warn_text3}}</div>
<span v-if="tempValue" class="tip">{{lang.flow_warn_text1}}{{tempValue}}%{{lang.flow_warn_text2}}</span>
<el-dialog width="6.8rem" :visible.sync="visible" :show-close="false" @close="closeDialog" custom-class="withdraw-dialog">
<div class="dialog-title">{{lang.flow_warn_text3}}</div>
<div class="dialog-main">
<el-form label-width="120px" ref="ruleForm" :rules="rules" :model="warningForm" label-position="right">
<el-form-item :label="lang.flow_warn_text4" prop="warning_switch">
<el-switch v-model="warningForm.warning_switch" active-color="var(--color-primary)"
:active-value="1" :inactive-value="0">
</el-switch>
</el-form-item>
<el-form-item :label="lang.flow_warn_text1" prop="leave_percent" v-if="warningForm.warning_switch">
<el-select v-model="warningForm.leave_percent" :placeholder="lang.placeholder_pre2">
<el-option :value="5" label="5%"></el-option>
<el-option :value="10" label="10%"></el-option>
<el-option :value="15" label="15%"></el-option>
<el-option :value="20" label="20%"></el-option>
</el-select>
<span class="warning-text">{{lang.flow_warn_text5}}</span>
</el-form-item>
</el-form>
</div>
<div slot="footer" class="dialog-footer">
<el-button class="btn-ok" type="primary" @click="submit" :loading="submitLoading">{{lang.cart_tip_text9}}</el-button>
<el-button class="btn-no" @click="closeDialog">{{lang.cart_tip_text10}}</el-button>
</div>
</el-dialog>
</div>
`,
data() {
return {
visible: false,
submitLoading: false,
rules: {
leave_percent: [
{required: true, message: lang.placeholder_pre2, trigger: "change"},
],
},
warningForm: {
module: "",
warning_switch: 1,
leave_percent: "",
},
tempValue: 0,
tempData: {},
};
},
computed: {},
props: {
module: {
type: String,
default: "mf_cloud", // 目前支持 mf_cloud mf_dcim
},
},
watch: {},
created() {
this.getWarningConfig();
},
methods: {
async getWarningConfig() {
try {
const res = await getTrafficWarning({
module: this.module,
});
const temp = res.data.data;
this.tempValue = temp.leave_percent;
temp.leave_percent = temp.leave_percent || "";
this.warningForm = temp;
this.tempData = JSON.parse(JSON.stringify(temp));
} catch (error) {
this.$message.error(error.message);
}
},
handleConfig() {
this.visible = true;
Object.assign(this.warningForm, this.tempData);
},
closeDialog() {
this.visible = false;
},
submit() {
this.$refs.ruleForm.validate(async (valid) => {
if (valid) {
const params = {
module: this.module,
warning_switch: this.warningForm.warning_switch,
leave_percent: this.warningForm.leave_percent,
};
if (params.warning_switch === 0) {
params.leave_percent = 0;
}
this.submitLoading = true;
const res = await saveTrafficWarning(params);
this.submitLoading = false;
this.visible = false;
this.$message.success(res.data.msg);
this.getWarningConfig();
} else {
return false;
}
});
},
},
};

View File

@@ -0,0 +1,238 @@
const withdrawDialog = {
template: /*html */ `
<el-dialog width="6.8rem" :visible.sync="withdrawVisible" :show-close=false @close="withdrawCancel" custom-class="withdraw-dialog">
<div class="dialog-title">
{{lang.withdraw_title}}
</div>
<div class="dialog-main">
<el-form label-width="80px" :model="withdrawForm" label-position="top">
<el-form-item :label="lang.withdraw_label1" >
<el-select class="input-select" v-model="withdrawForm.method_id" @change="methodChange" :placeholder="lang.withdraw_placeholder1">
<el-option v-for="item in ruler.method" :key="item.id" :value="item.id" :label="item.name"></el-option>
</el-select>
</el-form-item>
<template v-if="withdrawForm.method_id != 0">
<el-form-item :label="lang.withdraw_label2" v-if="isBank">
<el-input class="input-select" v-model="withdrawForm.card_number"
:placeholder="lang.withdraw_placeholder3"></el-input>
</el-form-item>
<el-form-item :label="lang.withdraw_label3" v-else>
<el-input class="input-select" v-model="withdrawForm.account"
:placeholder="lang.withdraw_placeholder2"></el-input>
</el-form-item>
<el-form-item :label="lang.withdraw_label4">
<el-input class="input-select" v-model="withdrawForm.name" :placeholder="lang.withdraw_placeholder4"></el-input>
</el-form-item>
</template>
<el-form-item :label="lang.withdraw_label5" >
<el-input @keyup.native="withdrawForm.amount=oninput(withdrawForm.amount)" class="input-select amount-input" v-model="withdrawForm.amount" :placeholder="lang.withdraw_placeholder5 + currency_prefix + ruler.withdrawable_amount">
<el-button class="all-btn" type="text" slot="suffix" @click="withdrawForm.amount=ruler.withdrawable_amount">{{lang.withdraw_btn3}}
</el-button>
</el-input>
</el-form-item>
<el-form-item v-if="errText">
<el-alert :title="errText" type="error" :closable="false" show-icon>
</el-alert>
</el-form-item>
</el-form>
</div>
<div class="withdraw-rule">
<div class="label">{{lang.withdraw_title2}}</div>
<div class="rules">
<div class="rules-item" v-if="ruler.withdraw_min || ruler.withdraw_max">
{{lang.withdraw_text1}}
<span v-if="ruler.withdraw_min">{{lang.withdraw_text2}}{{currency_prefix}}{{ruler.withdraw_min}}</span>
<span v-if="ruler.withdraw_min && ruler.withdraw_max">,</span>
<span v-if="ruler.withdraw_max">{{lang.withdraw_text3}}{{currency_prefix}}{{ruler.withdraw_max}}</span>
</div>
<div class="rules-item" v-if="ruler.withdraw_handling_fee || ruler.percent_min">
{{lang.withdraw_text4}}
<span v-if="ruler.withdraw_handling_fee">{{ruler.withdraw_handling_fee}}</span>
<!-- 最低手续费 -->
<span v-if="ruler.percent_min">{{lang.withdraw_text5}}{{currency_prefix}}{{ruler.percent_min}}</span>
<span>{{lang.withdraw_text6}}</span>
</div>
<div class="rules-item">
{{lang.withdraw_text7}}
</div>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button class="btn-ok" type="primary" @click="doApplyWithdraw()" v-loading="withdrawLoading">{{lang.withdraw_btn1}}</el-button>
<el-button class="btn-no" @click="withdrawCancel">{{lang.withdraw_btn2}}</el-button>
</span>
</el-dialog>
`,
data() {
return {
// 提现弹窗开始
// 是否显示提现弹窗
currency_prefix: "¥",
withdrawVisible: false,
withdrawForm: {
source: "",
method_id: "",
amount: "",
card_number: "",
name: "",
account: "",
notes: "",
},
isBank: false,
withdrawLoading: false,
errText: "",
ruler: {
// 提现来源
source: "",
// 提现方式
method: [],
// 第一个提现方式
method_id: "",
// 可提现金额
withdrawable_amount: "",
// 单次提现最提金额
withdraw_min: "",
// 单次提现最高金额
withdraw_max: "",
// 提现手续费 百分比的带上“%” 固定金额 保留两位数
withdraw_handling_fee: "",
// 最低提现手续费
percent_min: "",
},
};
},
created() {
this.currency_prefix = JSON.parse(
localStorage.getItem("common_set_before")
).currency_prefix;
},
methods: {
// 提现弹窗开始
// 提现方式变化
methodChange(e) {
const method = this.ruler.method;
this.isBank = false;
method.forEach((item) => {
if (item.id == e && item.name == "银行卡") {
this.isBank = true;
}
});
},
// 显示提现弹窗
shwoWithdrawal(ruler) {
this.withdrawForm = {
source: ruler.source,
method_id: ruler.method_id,
amount: "",
card_number: "",
name: "",
account: "",
notes: "",
};
// 默认选择第一个
// this.withdrawForm.method_id = ruler.method[0].id
this.methodChange(this.withdrawForm.method_id);
this.ruler = ruler;
this.withdrawVisible = true;
this.errText = "";
},
// 申请提现
doApplyWithdraw() {
let isPass = true;
this.errText = "";
const params = {
...this.withdrawForm,
};
if (this.isBank && !params.card_number) {
this.errText = lang.withdraw_placeholder3;
isPass = false;
return;
}
if (!params.method_id && params.method_id != 0) {
this.errText = lang.withdraw_placeholder1;
isPass = false;
return;
}
if (!params.amount) {
this.errText = lang.withdraw_placeholder6;
isPass = false;
return;
} else {
// 提现金额小于最小金额
if (
this.ruler.withdraw_min &&
Number(this.ruler.withdraw_min) > Number(params.amount)
) {
this.errText =
lang.withdraw_tips1 +
this.currency_prefix +
this.ruler.withdraw_min;
isPass = false;
return;
}
if (Number(params.amount) > Number(this.ruler.withdrawable_amount)) {
this.errText = lang.withdraw_tips2;
isPass = false;
return;
}
if (
this.ruler.withdraw_max &&
Number(this.ruler.withdraw_max) < Number(params.amount)
) {
this.errText =
lang.withdraw_tips3 +
this.currency_prefix +
this.ruler.withdraw_max;
isPass = false;
return;
}
}
if (isPass) {
this.withdrawLoading = true;
this.errText = "";
this.$emit("dowithdraw", params);
}
},
oninput(value) {
let str = value;
let len1 = str.substr(0, 1);
let len2 = str.substr(1, 1);
//如果第一位是0第二位不是点就用数字把点替换掉
if (str.length > 1 && len1 == 0 && len2 != ".") {
str = str.substr(1, 1);
}
//第一位不能是.
if (len1 == ".") {
str = "";
}
if (len1 == "+") {
str = "";
}
if (len1 == "-") {
str = "";
}
//限制只能输入一个小数点
if (str.indexOf(".") != -1) {
let str_ = str.substr(str.indexOf(".") + 1);
if (str_.indexOf(".") != -1) {
str = str.substr(0, str.indexOf(".") + str_.indexOf(".") + 1);
}
}
//正则替换
str = str.replace(/[^\d^\.]+/g, ""); // 保留数字和小数点
str = str.replace(/^\D*([0-9]\d*\.?\d{0,2})?.*$/, "$1"); // 小数点后只能输 2 位
return str;
},
withdrawCancel() {
this.withdrawVisible = false;
this.withdrawLoading = false;
},
},
};

View File

@@ -0,0 +1,227 @@
{include file="header"}
<!-- 页面独有样式 -->
<link rel="stylesheet" href="/{$template_catalog}/template/{$themes}/css/productList.css" />
</head>
<body>
<!-- mounted之前显示 -->
<div id="mainLoading">
<div class="ddr ddr1"></div>
<div class="ddr ddr2"></div>
<div class="ddr ddr3"></div>
<div class="ddr ddr4"></div>
<div class="ddr ddr5"></div>
</div>
<div class="product">
<el-container>
<aside-menu></aside-menu>
<el-container>
<top-menu></top-menu>
<el-main>
<div class="main-card">
<!-- 表格 -->
<div class="main-card-table">
<product-filter :tab.sync="params.tab" @change="inputChange"
:count="countData"></product-filter>
<!-- 筛选 -->
<div class="main-card-search">
<batch-renewpage :tab="params.tab" :ids="multipleSelection" module-type="all"
@success="inputChange" ref="batchRenewRef"></batch-renewpage>
<div class="right-search">
<el-select v-model="params.index" @change="centerSelectChange" :filterable="true"
:clearable="true" :placeholder="lang.data_center_filter"
v-if="hasSelectField('area') && center.length > 0">
<el-option v-for="(item,index) in center" :key="index" :value="index"
:label="item.label">
<div class="center-option-label">
<img :src="'/upload/common/country/' + item.country_code + '.png'"
class="area-img" />
<span class="option-text">{{item.label}}</span>
</div>
</el-option>
</el-select>
<!-- 产品状态 -->
<el-select v-model="params.status" @change="statusSelectChange"
:placeholder="lang.com_config.select_pro_status" clearable>
<el-option v-for="item in statusSelect" :key="item.id" :value="item.status"
:label="item.label">
</el-option>
</el-select>
<el-input v-model="params.keywords" :placeholder="lang.cloud_tip_2" clearable
@clear="clearKey" @keyup.enter.native="inputChange">
</el-input>
<div class="search-btn" @Click="inputChange">{{lang.search}}</div>
</div>
</div>
<div class="table">
<el-table v-loading="loading" :data="cloudData"
style="width: 100%; margin-bottom: 0.2rem" row-class-name="border-r-none"
header-row-class-name="border-r-hover" border class="list-table-border"
@sort-change="sortChange" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="60" :show-overflow-tooltip="true">
</el-table-column>
<el-table-column prop="id" label="ID" min-width="100" align="left">
<template slot-scope="scope">
<span class="column-id" @click="toDetail(scope.row)">{{scope.row.id}}</span>
</template>
</el-table-column>
<!-- 区域 -->
<el-table-column :label="lang.com_config.area" min-width="200"
v-if="hasSelectField('area') && center.length > 0"
:show-overflow-tooltip="true">
<template slot-scope="scope">
<div class="area" v-if="scope.row.country">
<img :src="'/upload/common/country/' + scope.row.country_code + '.png'"
class="area-img" />
<span class="area-country">{{scope.row.country}}</span>
<span>-{{scope.row.city}}-{{scope.row.area}}</span>
</div>
<div v-else>--</div>
</template>
</el-table-column>
<!-- 产品名称 -->
<el-table-column prop="product-name" :label="lang.cart_tip_text4" min-width="170"
:show-overflow-tooltip="true" v-if="hasSelectField('product_name')">
&nbsp;
<template slot-scope="scope">
<p class="cloud-name" @click="toDetail(scope.row)">
<span class="packge-name">{{ scope.row.product_name }}</span>
<span class="name">{{ scope.row.name }}</span>
</p>
</template>
</el-table-column>
<!-- 计费方式 -->
<el-table-column prop="billing_cycle" v-if="hasSelectField('billing_cycle')"
:label="lang.billing_cycle" width="130" :show-overflow-tooltip="true">
<template slot-scope="{row}">
<span
v-if="row.billing_cycle === 'on_demand' || row.billing_cycle === 'recurring_prepayment_on_demand'">
{{lang.demand_fee}}
</span>
<span v-else>{{lang.month_year}}</span>
</template>
</el-table-column>
<!-- 自动续费 -->
<el-table-column prop="renew" width="120" :label="lang.auto_renew"
v-if="hasAutoRenew && hasSelectField('is_auto_renew')">
<template slot-scope="{row}">
<auto-renew v-if="row.status === 'Active'" :id="row.id"
:is-auto-renew="row.is_auto_renew" @update="getCloudList">
</auto-renew>
<span v-else>--</span>
</template>
</el-table-column>
<!-- 基础信息 -->
<el-table-column prop="base_info" :label="lang.base_info" min-width="130"
v-if="hasSelectField('base_info')" :show-overflow-tooltip="true">
<template slot-scope="scope">
{{(scope.row.show_base_info === 1 && scope.row.base_info) || '--'}}
</template>
</el-table-column>
<!-- <el-table-column :label="item.field_name" min-width="150"
:show-overflow-tooltip="true" v-for="item in self_defined_field"
:key="item.id + 'fff'">
<template slot-scope="{row}">
<span
:class="item.field_type === 'textarea' ? 'word-pre' : ''">{{row.self_defined_field[item.id]
||'--'}}</span>
</template>
</el-table-column> -->
<!-- IP -->
<el-table-column label="IP" width="180" :show-overflow-tooltip="true"
v-if="hasSelectField('ip')" class-name="list-show-ip">
<template slot-scope="scope">
<template v-if="scope.row.dedicate_ip && scope.row.status !== 'Deleted'">
<div class="com-ip-box">
<span @click="toDetail(scope.row)">{{scope.row.dedicate_ip}}</span>
<el-popover placement="top" trigger="hover"
v-if="scope.row.ip_num > 1">
<div class="ips">
<p v-for="(item,index) in scope.row.allIp" :key="index">
{{item}}
<i class="el-icon-document-copy base-color"
@click="copyIp(item)"></i>
</p>
</div>
<span slot="reference" class="base-color">
({{scope.row.ip_num}}) </span>
</el-popover>
</div>
<i class="el-icon-document-copy base-color"
@click="copyIp(scope.row.allIp)" v-if="scope.row.ip_num > 0"></i>
</template>
<template v-else>--</template>
</template>
</el-table-column>
<!-- OS -->
<el-table-column label="OS" width="80" :show-overflow-tooltip="true"
v-if="hasSelectField('os')">
<template slot-scope="scope">
<div class="os">
<img :title="scope.row.image_name" v-if="scope.row.image_icon"
class="os-img"
:src="'/plugins/server/mf_cloud/template/clientarea/pc/default/img/mf_cloud/'+scope.row.image_icon +'.svg'" />
<span v-else>--</span>
</div>
</template>
</el-table-column>
<!-- 创建时间 -->
<el-table-column prop="active_time" :label="lang.com_config.active_time" width="160"
v-if="hasSelectField('active_time')" sortable>
<template slot-scope="scope">
<span>{{scope.row.active_time | formateTime}}</span>
</template>
</el-table-column>
<!-- 到期时间 -->
<el-table-column prop="due_time" v-if="hasSelectField('due_time')" width="160"
:label="lang.index_text13" sortable>
<template slot-scope="scope">
<span>{{scope.row.due_time | formateTime}}</span>
</template>
</el-table-column>
<!-- 产品状态 -->
<el-table-column :label="lang.finance_label4" v-if="hasSelectField('status')"
width="100">
<template slot-scope="scope">
<div class="status"
:style="'color:'+status[scope.row.status].color + ';background:' + status[scope.row.status].bgColor">
{{status[scope.row.status].text }}
</div>
</template>
</el-table-column>
<!-- 备注 -->
<el-table-column :label="lang.invoice_text139" min-width="100"
:show-overflow-tooltip="true" v-if="hasSelectField('notes')">
<template slot-scope="{row}">
<span>{{row.client_notes || '--'}}</span>
</template>
</el-table-column>
</el-table>
</div>
<div class="page">
<pagination :page-data="params" @sizechange="sizeChange" @currentchange="currentChange">
</pagination>
</div>
</div>
</div>
</el-main>
</el-container>
</el-container>
</div>
<!-- =======页面独有======= -->
<script src="/{$template_catalog}/template/{$themes}/api/product.js"></script>
<script src="/{$template_catalog}/template/{$themes}/components/autoRenew/autoRenew.js"></script>
<script src="/{$template_catalog}/template/{$themes}/components/payDialog/payDialog.js"></script>
<script src="/{$template_catalog}/template/{$themes}/components/pagination/pagination.js"></script>
<script src="/{$template_catalog}/template/{$themes}/components/safeConfirm/safeConfirm.js"></script>
<script src="/{$template_catalog}/template/{$themes}/components/batchRenewpage/batchRenewpage.js"></script>
<script src="/{$template_catalog}/template/{$themes}/components/productFilter/productFilter.js"></script>
<script src="/{$template_catalog}/template/{$themes}/js/crossModule.js"></script>
{include file="footer"}

View File

@@ -0,0 +1,28 @@
.content-box {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.content-box .img-box {
width: 2.91rem;
height: 2.08rem;
}
.content-box .img-box img {
width: 100%;
height: 100%;
}
.content-box .tips-box {
text-align: center;
color: #666B80;
font-size: 0.16rem;
margin-top: 0.5rem;
}
.content-box .tran-again {
margin-top: 0.06rem;
cursor: pointer;
color: var(--color-primary);
font-size: 0.16rem;
}

View File

@@ -0,0 +1,32 @@
.content-box {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.img-box {
width: 2.91rem;
height: 2.08rem;
img {
width: 100%;
height: 100%;
}
}
.tips-box {
text-align: center;
color: #666B80;
font-size: 0.16rem;
margin-top: 0.5rem;
}
.tran-again {
margin-top: 0.06rem;
cursor: pointer;
color: var(--color-primary);
font-size: 0.16rem;
}
}

View File

@@ -0,0 +1,478 @@
.main-card-title {
font-size: 0.28rem;
line-height: 0.28rem;
}
.content-box {
margin-top: 0.4rem;
}
.box-top {
height: 1rem;
width: 100%;
border-bottom: 1px solid #e6e7eb;
display: flex;
align-items: center;
}
.right-name {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
.name-text {
font-size: 0.32rem;
font-family: Helvetica;
font-weight: bold;
line-height: 0.32rem;
color: #1e2736;
}
.name-country {
margin-top: 0.1rem;
display: flex;
align-items: center;
}
.country-img {
height: 0.25rem;
width: 0.4rem;
}
.attestation-status {
display: inline-flex;
align-items: center;
cursor: pointer;
margin-left: 0.04rem;
}
.attestation-status > img {
width: 0.26rem;
height: 0.26rem;
}
.attestation-text {
cursor: pointer;
margin-left: 0.1rem;
font-size: 0.14rem;
color: #1e2736;
}
.bule-text {
color: var(--color-primary) !important;
}
.bule-text .el-icon-arrow-right {
margin-left: 0.08rem;
}
.box-main {
margin-top: 0.4rem;
}
.el-popconfirm .el-popconfirm__main {
margin: 14px 0;
}
.el-popconfirm .el-popconfirm__action .el-button {
display: initial !important;
}
.account-title,
.basic-title {
border-left: 3px solid var(--color-primary);
padding-left: 0.1rem;
font-size: 0.16rem;
line-height: 0.16rem;
font-weight: 400;
}
.account {
margin-top: 0.62rem !important;
}
.basic > .el-row,
.account > .el-row {
margin-top: 0.43rem;
}
.oauth {
margin-top: 0.62rem;
}
.wx-switch {
margin-top: 0.43rem;
}
.oauth-box {
margin-top: 0.43rem;
display: flex;
flex-wrap: wrap;
row-gap: 0.43rem;
}
.box-item {
display: flex;
flex-direction: column;
font-family: PingFang SC;
}
.box-item-t {
font-size: 0.13rem;
font-weight: 500;
height: 0.2rem;
color: #8692b0;
margin-bottom: 0.25rem;
}
.box-item-b > .el-input,
.box-item-b .el-select,
.box-item-b .el-textarea {
width: 3.2rem;
border: none;
border-bottom: 1px solid #e6e7eb;
}
.el-textarea .el-textarea__inner {
padding: 0;
border: none;
}
.box-item-b .el-input__inner {
border: none;
padding: 0;
}
.btn-save {
width: 0.88rem;
height: 0.32rem;
margin-top: 0.43rem;
background: var(--color-primary);
border-radius: 3px;
color: #ffffff;
display: flex;
align-items: center;
justify-content: center;
}
.el-input.is-disabled .el-input__inner {
background: #ffffff;
}
.el-input__inner {
height: 0.46rem;
}
.el-input__suffix {
display: flex;
align-items: center;
}
.input-with-select .el-input-group__prepend {
width: 60px;
border: none;
background: #ffffff;
}
.edit-icon {
cursor: pointer;
padding: 0.15rem;
}
.el-dialog__body {
padding: 0.3rem 0.8rem;
font-size: 0.16rem;
}
.mian-form {
margin-top: 0.4rem;
}
.input-btn {
display: flex;
flex-direction: row;
}
.code-btn {
margin-left: 0.12rem;
width: 1.3rem;
background: #eef4ff;
opacity: 1;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
color: var(--color-primary);
}
.select-input {
width: auto !important;
min-width: 1.14rem;
}
.com-search {
display: flex;
justify-content: flex-end;
padding: 0.2rem 0;
}
.msg-search {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.2rem 0;
}
.msgsearch-left {
display: flex;
align-items: center;
}
.msgsearch-left .el-button {
border-radius: 0.03rem;
border: 0.01rem solid var(--color-primary);
color: var(--color-primary);
font-size: 0.16rem;
margin-right: 0.1rem;
}
.msgsearch-right {
display: flex;
}
.msgsearch-right .el-select {
width: 2.4rem;
margin-right: 0.1rem;
border: none;
}
.msgsearch-right .search-btn {
margin-left: 0.1rem;
background: var(--color-primary);
font-size: 0.16rem;
color: rgba(255, 255, 255, 0.9);
}
.a-text {
color: #171725;
}
.a-text:hover {
color: var(--color-primary);
cursor: pointer;
text-decoration: underline;
}
.msg-status {
margin-right: 0.05rem;
}
.is-read {
color: #8692b0;
}
.no-read {
color: var(--color-primary);
}
tr > td {
padding-left: 20px !important;
}
th {
padding-left: 20px !important;
}
.forget-pass {
display: flex;
justify-content: flex-end;
line-height: 0.14rem;
font-size: 0.14rem;
margin-top: 0.04rem;
}
.forget-pass > a {
color: var(--color-primary);
cursor: pointer;
}
.login-top {
display: flex;
flex-direction: row;
margin-top: 0.3rem;
}
.login-email,
.login-phone {
color: #666b80;
cursor: pointer;
}
.login-phone {
margin-left: 0.4rem;
}
.active {
color: var(--color-primary);
padding-bottom: 0.14rem;
border-bottom: 2px solid var(--color-primary);
}
.form-main {
margin-top: 0.3rem;
}
.form-item {
margin-top: 0.3rem;
}
.code-item {
display: flex;
flex-direction: row;
}
.rember-item {
margin-top: 0.2rem;
display: flex;
align-items: center;
justify-content: space-between;
}
.rember-item a {
color: var(--color-primary);
cursor: pointer;
}
.login-btn {
width: 100%;
height: 0.46rem;
background: var(--color-primary);
}
.read-item {
margin-top: 0.2rem;
}
.read-item a {
color: var(--color-primary);
cursor: pointer;
}
.line-item {
margin-top: 0.4rem;
}
.line-item text {
font-size: 16px;
color: #1e2736;
}
.type-btn {
width: 100%;
height: 0.46rem;
font-size: 0.16rem;
}
.code-pass-select {
width: auto;
height: 44px;
border: 1px solid #e6e7eb;
border-right: none;
}
.el-message-box__btns {
display: flex;
flex-direction: row-reverse;
}
.el-message-box__btns > .el-button {
display: inline-block;
margin-left: 10px;
}
.mobel {
display: none;
}
@media screen and (max-width: 750px) {
.main-card-title {
font-size: 0.48rem;
}
.name-text {
font-size: 0.4rem;
}
.basic-title,
.account-title {
font-size: 0.36rem;
font-family: PingFang SC;
font-weight: 800;
line-height: 0.36rem;
color: var(--color-primary);
border-left: none;
padding-left: 0;
}
.box-item-t {
font-size: 0.28rem;
height: 0.28rem;
}
.el-row {
display: flex;
flex-direction: column;
}
.el-col {
width: 100%;
}
.box-item-b > .el-input,
.box-item-b .el-select,
.box-item-b .el-textarea {
width: 100%;
margin-bottom: 0.4rem;
}
.el-input__inner {
font-size: 0.32rem;
height: auto;
}
.btn-save {
width: calc(100% - 0.6rem);
margin: 0 auto;
margin-top: 0.43rem;
height: 0.8rem;
font-size: 0.34rem;
}
.code-btn {
width: auto;
height: 0.8rem;
font-size: 0.32rem;
}
.dialog-footer {
flex-direction: column;
}
.dialog-footer .btn-ok,
.dialog-footer .btn-no {
width: 100%;
height: 0.8rem;
font-size: 0.34rem;
}
.dialog-footer .btn-no {
margin-left: 0;
margin-top: 0.2rem;
}
.el-form-item__label {
font-size: 0.32rem;
}
.edit-icon {
font-size: 0.4rem;
}
.dialog-title {
font-size: 0.36rem;
}
.forget-pass {
font-size: 0.28rem;
line-height: 0.29rem;
}
.content_searchbar .left_tips .tips_item {
margin-right: 0.1rem;
}
.searchbar {
width: 100%;
}
.searchbar .el-input {
margin-left: 0;
width: 100% !important;
}
.mob-searchbar {
margin-top: 0.53rem;
}
.mob-search-input {
height: 0.8rem;
background: rgba(134, 146, 176, 0.1);
border-radius: 3px 3px 0px 0px;
}
.mob-search-input > input {
height: 0.8rem;
background: rgba(134, 146, 176, 0.1);
border-radius: 3px 3px 0px 0px;
}
.mob-tabledata {
display: flex;
flex-direction: column;
border: 1px solid #d7d8db;
border-radius: 0px 0px 3px 3px;
}
.mob-tabledata-item {
height: auto;
border-bottom: 1px solid #d7d8db;
display: flex;
flex-direction: column;
padding: 0 0.3rem;
}
.mob-item-row {
display: flex;
justify-content: space-between;
margin-top: 0.2rem;
}
.mob-item-row1,
.mob-item-row3,
.mob-item-row-notes {
font-size: 0.26rem;
line-height: 0.27rem;
color: #8692b0;
}
.mob-item-row2-name {
font-size: 0.32rem;
line-height: 0.33rem;
}
.mob-item-row3 {
margin-bottom: 0.4rem;
}
.back-top-img {
width: 0.88rem;
position: fixed;
right: 0.3rem;
bottom: 1.17rem;
}
.bottom-text {
font-size: 0.26rem;
line-height: 0.27rem;
color: #8692b0;
margin: 0.4rem 0;
display: flex;
justify-content: center;
}
.basic > .el-row:nth-child(3) {
margin-top: 0;
}
.select-input > .el-input--suffix {
width: 1.86rem;
}
}

View File

@@ -0,0 +1,616 @@
// Variables
@text-color: #1e2736;
@border-color: #e6e7eb;
@text-secondary: #8692b0;
@white: #ffffff;
// Mixins
.flex-center() {
display: flex;
align-items: center;
justify-content: center;
}
.flex-between() {
display: flex;
align-items: center;
justify-content: space-between;
}
// Main styles
.main-card-title {
font-size: 0.28rem;
line-height: 0.28rem;
}
.content-box {
margin-top: 0.4rem;
}
.box-top {
height: 1rem;
width: 100%;
border-bottom: 1px solid @border-color;
display: flex;
align-items: center;
}
.right-name {
.flex-between();
width: 100%;
}
.name-text {
font-size: 0.32rem;
font-family: Helvetica;
font-weight: bold;
line-height: 0.32rem;
color: @text-color;
}
.name-country {
margin-top: 0.1rem;
display: flex;
align-items: center;
}
.country-img {
height: 0.25rem;
width: 0.4rem;
}
.attestation-status {
display: inline-flex;
align-items: center;
cursor: pointer;
margin-left: 0.04rem;
>img {
width: 0.26rem;
height: 0.26rem;
}
}
.attestation-text {
cursor: pointer;
margin-left: 0.1rem;
font-size: 0.14rem;
color: @text-color;
}
.bule-text {
color: var(--color-primary) !important;
.el-icon-arrow-right {
margin-left: 0.08rem;
}
}
.box-main {
margin-top: 0.4rem;
}
// Element UI overrides
.el-popconfirm {
.el-popconfirm__main {
margin: 14px 0;
}
.el-popconfirm__action .el-button {
display: initial !important;
}
}
.account-title,
.basic-title {
border-left: 3px solid var(--color-primary);
padding-left: 0.1rem;
font-size: 0.16rem;
line-height: 0.16rem;
font-weight: 400;
}
.account {
margin-top: 0.62rem !important;
}
.basic>.el-row,
.account>.el-row {
margin-top: 0.43rem;
}
.oauth {
margin-top: 0.62rem;
}
.wx-switch {
margin-top: 0.43rem;
}
.oauth-box {
margin-top: 0.43rem;
display: flex;
flex-wrap: wrap;
row-gap: 0.43rem;
}
.box-item {
display: flex;
flex-direction: column;
font-family: PingFang SC;
}
.box-item-t {
font-size: 0.13rem;
font-weight: 500;
height: 0.2rem;
color: @text-secondary;
margin-bottom: 0.25rem;
}
.box-item-b {
>.el-input,
.el-select,
.el-textarea {
width: 3.2rem;
border: none;
border-bottom: 1px solid @border-color;
}
}
.el-textarea .el-textarea__inner {
padding: 0;
border: none;
}
.box-item-b .el-input__inner {
border: none;
padding: 0;
}
.btn-save {
width: 0.88rem;
height: 0.32rem;
margin-top: 0.43rem;
background: var(--color-primary);
border-radius: 3px;
color: @white;
.flex-center();
}
.el-input {
&.is-disabled .el-input__inner {
background: @white;
}
&__inner {
height: 0.46rem;
}
&__suffix {
display: flex;
align-items: center;
}
}
.input-with-select .el-input-group__prepend {
width: 60px;
border: none;
background: @white;
}
.edit-icon {
cursor: pointer;
padding: 0.15rem;
}
// Dialog styles
.el-dialog__body {
padding: 0.3rem 0.8rem;
font-size: 0.16rem;
}
.mian-form {
margin-top: 0.4rem;
}
.input-btn {
display: flex;
flex-direction: row;
}
.code-btn {
margin-left: 0.12rem;
width: 1.3rem;
background: #eef4ff;
opacity: 1;
border-radius: 4px;
.flex-center();
color: var(--color-primary);
}
.select-input {
width: auto !important;
min-width: 1.14rem;
}
// Table styles
// Search styles
.com-search {
display: flex;
justify-content: flex-end;
padding: 0.2rem 0;
}
.msg-search {
.flex-between();
padding: 0.2rem 0;
}
.msgsearch-left {
display: flex;
align-items: center;
.el-button {
border-radius: 0.03rem;
border: 0.01rem solid var(--color-primary);
color: var(--color-primary);
font-size: 0.16rem;
margin-right: 0.1rem;
}
}
.msgsearch-right {
display: flex;
.el-select {
width: 2.4rem;
margin-right: 0.1rem;
border: none;
}
.search-btn {
margin-left: 0.1rem;
background: var(--color-primary);
font-size: 0.16rem;
color: rgba(255, 255, 255, 0.9);
}
}
// Link styles
.a-text {
color: #171725;
&:hover {
color: var(--color-primary);
cursor: pointer;
text-decoration: underline;
}
}
.msg-status {
margin-right: 0.05rem;
}
.is-read {
color: @text-secondary;
}
.no-read {
color: var(--color-primary);
}
// Table cell styles
tr>td {
padding-left: 20px !important;
}
th {
padding-left: 20px !important;
}
// Forget password styles
.forget-pass {
display: flex;
justify-content: flex-end;
line-height: 0.14rem;
font-size: 0.14rem;
margin-top: 0.04rem;
>a {
color: var(--color-primary);
cursor: pointer;
}
}
// Login styles
.login-top {
display: flex;
flex-direction: row;
margin-top: 0.3rem;
}
.login-email,
.login-phone {
color: #666b80;
cursor: pointer;
}
.login-phone {
margin-left: 0.4rem;
}
.active {
color: var(--color-primary);
padding-bottom: 0.14rem;
border-bottom: 2px solid var(--color-primary);
}
.form-main {
margin-top: 0.3rem;
}
.form-item {
margin-top: 0.3rem;
}
.code-item {
display: flex;
flex-direction: row;
}
.rember-item {
margin-top: 0.2rem;
.flex-between();
a {
color: var(--color-primary);
cursor: pointer;
}
}
.login-btn {
width: 100%;
height: 0.46rem;
background: var(--color-primary);
}
.read-item {
margin-top: 0.2rem;
a {
color: var(--color-primary);
cursor: pointer;
}
}
.line-item {
margin-top: 0.4rem;
text {
font-size: 16px;
color: @text-color;
}
}
.type-btn {
width: 100%;
height: 0.46rem;
font-size: 0.16rem;
}
.code-pass-select {
width: auto;
height: 44px;
border: 1px solid @border-color;
border-right: none;
}
// Message box styles
.el-message-box__btns {
display: flex;
flex-direction: row-reverse;
>.el-button {
display: inline-block;
margin-left: 10px;
}
}
// Mobile styles
.mobel {
display: none;
}
@media screen and (max-width: 750px) {
.main-card-title {
font-size: 0.48rem;
}
.name-text {
font-size: 0.4rem;
}
.basic-title,
.account-title {
font-size: 0.36rem;
font-family: PingFang SC;
font-weight: 800;
line-height: 0.36rem;
color: var(--color-primary);
border-left: none;
padding-left: 0;
}
.box-item-t {
font-size: 0.28rem;
height: 0.28rem;
}
.el-row {
display: flex;
flex-direction: column;
}
.el-col {
width: 100%;
}
.box-item-b {
>.el-input,
.el-select,
.el-textarea {
width: 100%;
margin-bottom: 0.4rem;
}
}
.el-input__inner {
font-size: 0.32rem;
height: auto;
}
.btn-save {
width: calc(100% - 0.6rem);
margin: 0 auto;
margin-top: 0.43rem;
height: 0.8rem;
font-size: 0.34rem;
}
.code-btn {
width: auto;
height: 0.8rem;
font-size: 0.32rem;
}
.dialog-footer {
flex-direction: column;
.btn-ok,
.btn-no {
width: 100%;
height: 0.8rem;
font-size: 0.34rem;
}
.btn-no {
margin-left: 0;
margin-top: 0.2rem;
}
}
.el-form-item__label {
font-size: 0.32rem;
}
.edit-icon {
font-size: 0.4rem;
}
.dialog-title {
font-size: 0.36rem;
}
.forget-pass {
font-size: 0.28rem;
line-height: 0.29rem;
}
.content_searchbar {
.left_tips .tips_item {
margin-right: 0.1rem;
}
}
.searchbar {
width: 100%;
.el-input {
margin-left: 0;
width: 100% !important;
}
}
.mob-searchbar {
margin-top: 0.53rem;
}
.mob-search-input {
height: 0.8rem;
background: rgba(134, 146, 176, 0.1);
border-radius: 3px 3px 0px 0px;
>input {
height: 0.8rem;
background: rgba(134, 146, 176, 0.1);
border-radius: 3px 3px 0px 0px;
}
}
.mob-tabledata {
display: flex;
flex-direction: column;
border: 1px solid #d7d8db;
border-radius: 0px 0px 3px 3px;
}
.mob-tabledata-item {
height: auto;
border-bottom: 1px solid #d7d8db;
display: flex;
flex-direction: column;
padding: 0 0.3rem;
}
.mob-item-row {
display: flex;
justify-content: space-between;
margin-top: 0.2rem;
}
.mob-item-row1,
.mob-item-row3,
.mob-item-row-notes {
font-size: 0.26rem;
line-height: 0.27rem;
color: @text-secondary;
}
.mob-item-row2-name {
font-size: 0.32rem;
line-height: 0.33rem;
}
.mob-item-row3 {
margin-bottom: 0.4rem;
}
.back-top-img {
width: 0.88rem;
position: fixed;
right: 0.3rem;
bottom: 1.17rem;
}
.bottom-text {
font-size: 0.26rem;
line-height: 0.27rem;
color: @text-secondary;
margin: 0.4rem 0;
display: flex;
justify-content: center;
}
.basic>.el-row:nth-child(3) {
margin-top: 0;
}
.select-input>.el-input--suffix {
width: 1.86rem;
}
}

View File

@@ -0,0 +1,68 @@
.contnet-right-out {
margin: auto;
font-size: 0.14rem;
padding: 0.2rem 3rem;
}
.contnet-right-out .content-right {
border: 1px solid #e6e7eb;
border-radius: 3px;
padding: 0.36rem 0.5rem;
overflow-x: auto;
}
.contnet-right-out .content-right .right-title {
font-size: 0.28rem;
font-weight: bold;
line-height: 0.28rem;
color: #1e2736;
}
.contnet-right-out .content-right .right-keywords-time {
display: flex;
flex-direction: row;
}
.contnet-right-out .content-right .right-keywords-time .right-time,
.contnet-right-out .content-right .right-keywords-time .right-keywords {
font-size: 0.14rem;
color: #8692b0;
margin-top: 0.14rem;
}
.contnet-right-out .content-right .right-keywords-time .right-keywords {
margin-left: 0.2rem;
}
.contnet-right-out .content-right .right-content {
word-wrap: break-word;
word-break: normal;
margin-top: 0.42rem;
}
.contnet-right-out .content-right .right-content img {
max-width: 100%;
}
.contnet-right-out .content-right .right-attachment {
margin-top: 0.42rem;
display: flex;
flex-direction: row;
}
.contnet-right-out .content-right .right-attachment .right-attachment-item {
margin-right: 0.2rem;
color: var(--color-primary);
cursor: pointer;
}
.contnet-right-out .page {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 0.2rem;
margin-left: 0.4rem;
}
.contnet-right-out .page .blue {
color: var(--color-primary) !important;
}
.contnet-right-out .page .pre,
.contnet-right-out .page .next {
cursor: pointer;
color: #4e5259;
}
@media screen and (max-width: 750px) {
.contnet-right-out {
padding: 0.2rem 0.3rem;
}
}

View File

@@ -0,0 +1,82 @@
.contnet-right-out {
margin: auto;
font-size: 0.14rem;
padding: 0.2rem 3rem;
.content-right {
border: 1px solid #e6e7eb;
border-radius: 3px;
padding: 0.36rem 0.5rem;
// margin-left: .4rem;
overflow-x: auto;
.right-title {
font-size: 0.28rem;
font-weight: bold;
line-height: 0.28rem;
color: #1e2736;
}
.right-keywords-time {
display: flex;
flex-direction: row;
.right-time,
.right-keywords {
font-size: 0.14rem;
color: #8692b0;
margin-top: 0.14rem;
}
.right-keywords {
margin-left: 0.2rem;
}
}
.right-content {
word-wrap: break-word;
word-break: normal;
margin-top: 0.42rem;
img {
max-width: 100%;
}
}
.right-attachment {
margin-top: 0.42rem;
display: flex;
flex-direction: row;
.right-attachment-item {
margin-right: 0.2rem;
color: var(--color-primary);
cursor: pointer;
}
}
}
.page {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 0.2rem;
margin-left: 0.4rem;
.blue {
color: var(--color-primary) !important;
}
.pre,
.next {
cursor: pointer;
color: #4e5259;
}
}
}
@media screen and (max-width: 750px) {
.contnet-right-out {
padding: 0.2rem 0.3rem;
}
}

View File

@@ -0,0 +1,438 @@
.main-card-title {
font-size: .28rem;
display: flex;
align-items: center;
color: #171725;
}
.top-back-img {
cursor: pointer;
width: 0.24rem;
height: 0.26rem;
margin-right: 0.25rem;
}
.top-line {
width: 100%;
height: 1px;
background: #E6E7EB;
opacity: 1;
margin-top: .2rem;
margin-bottom: 0.65rem;
}
.content-title {
font-size: 0.18rem;
color: #1E2736;
font-weight: 500;
}
.check-type {
display: flex;
margin-top: .2rem;
}
.check-type>div {
position: relative;
cursor: pointer;
display: flex;
flex: 1;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
height: 3.13rem;
border: 0.01rem solid #E6E7EB;
}
.select-type {
border-radius: 0.03rem;
background: #FEFFFF;
box-shadow: 0rem 0rem 0.06rem rgba(0, 0, 0, 0.12);
}
.font-18 {
color: #1E2736;
font-weight: bold;
font-size: 0.18rem;
}
/* .person-box {} */
.presonl-status {
position: absolute;
width: 100%;
left: 0;
bottom: 0;
text-align: center;
height: 0.52rem;
line-height: 0.52rem;
z-index: 8;
}
.person-success {
color: #FFFFFF;
font-size: 0.16rem;
background: rgb(61, 213, 152);
}
.person-loading {
color: #F0142F;
font-weight: bold;
font-size: 0.16rem;
background: rgba(240, 20, 46, 0.08);
}
.check-type>div:nth-of-type(1) {
margin-right: .4rem;
}
.checked-icon {
position: absolute;
z-index: 9;
bottom: 0;
right: 0;
line-height: 0;
width: 0;
height: 0;
border-bottom: .25rem solid #0058FF;
border-left: .25rem solid transparent;
}
.checked-icon::after {
content: '√';
font-size: .16rem;
color: #fff;
position: absolute;
right: 0;
top: .15rem;
}
.check-mode {
margin-top: 0.4rem;
}
.check-select .el-select {
margin-top: .2rem;
width: 4.2rem;
height: 0.52rem;
border-radius: 0.03rem;
}
.next-box {
margin-top: 1.5rem;
display: flex;
}
.next-box .el-button {
width: 1.8rem;
height: 0.46rem;
background: #0058FF;
color: #FFFFFF;
font-size: 0.16rem;
}
.next-box .back-btn {
color: #0058FF;
background: #fff;
border: 1px solid #0058FF;
}
.go-Back-Btn {
margin-top: 1.1rem;
}
.go-Back-Btn .back-btn {
border-radius: 0;
width: 1.8rem;
height: 0.46rem;
font-size: 0.16rem;
color: #0058FF;
background: #fff;
border: 1px solid #0058FF;
}
.main-content .el-form .el-form-item .el-input {
width: 5.2rem;
}
.type-img img {
width: 0.64rem;
height: 0.64rem;
}
.type-title {
margin: 0.24rem 0 0.21rem 0;
}
.type-tips {
margin-bottom: 0.1rem;
width: 4.36rem;
color: #4E5259;
text-align: center;
}
.upload-btn {
display: flex;
}
.el-upload--picture-card {
width: 3.6rem;
height: 2.66rem;
border: none;
}
.upload-progress {
width: 3.6rem;
height: 2.66rem;
}
.upload-btn-img {
display: flex;
justify-content: center;
align-items: center;
width: 3.6rem;
height: 2.66rem;
background: #FEFFFF;
box-shadow: 0rem 0.08rem 0.12rem rgba(0, 0, 0, 0.08);
border-radius: 0.03rem;
overflow: hidden;
}
.upload-btn-img img {
width: 3.08rem;
border: 1px dashed #DCDCDC;
height: 1.83rem;
}
.certification-person {
margin-bottom: .3rem;
}
.visibleImg {
height: 65vh;
text-align: center;
}
.visibleImg img {
height: 100%;
width: 100%;
}
.hide .el-upload--picture-card {
display: none !important;
}
.el-upload-list--picture-card .el-upload-list__item {
width: 3.6rem;
height: 2.66rem;
}
.el-upload-list--picture-card .el-upload-list__item-thumbnail {
width: 3.6rem;
height: 2.66rem;
}
.status-box {
width: 100%;
height: 6.97rem;
box-sizing: border-box;
text-align: center;
padding-top: 1.08rem;
border-radius: 0.03rem;
}
.third-box {
width: 9.7rem;
height: 5.49rem;
box-sizing: border-box;
text-align: center;
padding-top: 1.08rem;
border-radius: 0.03rem;
border: 1px solid #E6E7EB;
}
.status-title {
color: #3DD598;
font-weight: 500;
font-size: 0.28rem;
margin-bottom: 0.2rem;
}
.status-tips {
font-size: 0.16rem;
font-weight: 400;
color: #1E2736;
}
.status-info {
margin-top: 0.2rem;
display: flex;
justify-content: center;
}
.status-info>div:nth-of-type(1) {
text-align: right;
}
.status-info>div:nth-of-type(2) {
text-align: left;
}
.status-info>p {
margin-bottom: .05rem;
font-size: 0.13rem;
}
.info-key {
color: #8692B0;
}
.info-value {
margin-left: .2rem;
color: #4E5259;
}
.btn-box {
margin-top: 0.82rem;
display: flex;
justify-content: center;
}
.btn-box .el-button {
width: 1.8rem;
background: #0058FF;
color: #FFFFFF;
font-size: 0.16rem;
}
.origin-color {
color: #F99600;
}
.black-color {
color: #1E2736;
}
.personl-ing {
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
}
.title-blue {
color: #0058FF;
font-size: 0.28rem;
}
.updata-btn {
margin-top: 0.24rem;
}
.updata-btn .el-button {
color: #FFFFFF;
font-size: 0.16rem;
border-radius: 0;
background: #0058FF;
width: 1.8rem;
height: 0.46rem;
}
.status-img-box img {
width: 0.68rem;
height: 0.68rem;
}
.title-green {
margin-top: 0.21rem;
color: #3DD598;
font-weight: 800;
font-size: 0.28rem;
}
.table-box {
margin-top: 0.8rem;
border-spacing: 0;
text-align: left;
width: 8.23rem;
height: 1.05rem;
border: 1px solid #E6E7EB;
}
.mar-top-42 {
margin-top: 0.42rem;
}
.table-box tr td {
color: #1E2736;
font-size: 0.14rem;
border: 1px solid #E6E7EB;
padding-left: 0.4rem !important;
}
.again-btn {
margin-top: 0.4rem;
}
.again-btn .el-button {
border-radius: 0;
width: 1.8rem;
height: 0.46rem;
color: #0058FF;
font-size: 0.16rem;
border: 1px solid #0058FF;
}
.el-link.el-link--default {
align-items: flex-end;
margin-left: 0.1rem;
color: #0058FF;
font-size: 0.14rem;
}
.green-text {
color: #3DD598;
}
.font-14 {
color: #8692B0;
font-size: 0.16rem;
font-weight: 400;
}
.bule-text {
color: #3699FF;
}
.red-text {
text-align: center;
font-size: 0.16rem;
color: red;
margin-top: 0;
}
/*去除upload组件过渡效果*/
.el-upload-list__item {
transition: none !important;
}
.mar-top-114 {
margin-top: 1.14rem;
}
.tips-text {
text-align: center;
font-size: 0.14rem;
color: #8692B0;
}
.upload-1 {
margin-right: 0.6rem;
}

View File

@@ -0,0 +1,34 @@
.dialag-content {
padding: 1.79rem 1.94rem 2rem 1.94rem;
text-align: center;
}
.tips-title {
font-size: 0.28rem;
font-weight: 400;
color: #1E2736;
}
.tips-text {
margin-top: 0.3rem;
font-size: 0.14rem;
font-weight: 400;
color: #1E2736;
}
.button-box {
margin-top: 0.8rem;
display: flex;
justify-content: center;
align-items: center;
align-items: flex-end;
}
.button-box .el-button {
width: 1.8rem;
height: 0.46rem;
background: var(--color-primary);
color: #FFFFFF;
font-size: 0.16rem;
margin-right: 0.1rem;
}
.button-box .el-link {
color: var(--color-primary);
font-size: 0.14rem;
}

View File

@@ -0,0 +1,57 @@
// Variables
@text-color: #1E2736;
@font-size-small: 0.14rem;
@font-size-medium: 0.16rem;
@font-size-large: 0.28rem;
// Mixins
.flex-center() {
display: flex;
justify-content: center;
align-items: center;
}
.flex-between() {
display: flex;
justify-content: space-between;
align-items: center;
}
// Styles
.dialag-content {
padding: 1.79rem 1.94rem 2rem 1.94rem;
text-align: center;
}
.tips-title {
font-size: @font-size-large;
font-weight: 400;
color: @text-color;
}
.tips-text {
margin-top: 0.3rem;
font-size: @font-size-small;
font-weight: 400;
color: @text-color;
}
.button-box {
margin-top: 0.8rem;
.flex-center();
align-items: flex-end;
.el-button {
width: 1.8rem;
height: 0.46rem;
background: var(--color-primary);
color: #FFFFFF;
font-size: @font-size-medium;
margin-right: 0.1rem;
}
.el-link {
color: var(--color-primary);
font-size: @font-size-small;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,84 @@
.el-pagination .el-select .el-input {
margin: 0;
}
.el-button {
display: inline-flex;
align-items: center;
justify-content: center;
}
.el-table__fixed-right::before,
.el-table__fixed::before {
height: 0;
}
.el-slider__button-wrapper {
z-index: 2;
}
.el-tabs__nav-wrap::after {
height: 1px;
}
.el-notification__content {
overflow-y: auto;
padding-right: 5px;
max-height: 80vh;
}
.el-notification__content::-webkit-scrollbar {
width: 5px;
}
.el-notification__content::-webkit-scrollbar-track {
background-color: rgba(255, 255, 255, 0.4);
}
.el-notification__content::-webkit-scrollbar-thumb {
background-color: rgba(255, 255, 255, 0.8);
border-radius: 0.5rem;
}
/* 提示弹窗 */
.el-message-box {
width: 5.2rem;
}
.el-message {
z-index: 99999999999 !important;
}
.el-tooltip__popper {
max-width: 50%;
}
/* 表格 表头和每一行 的统一高度 */
thead tr {
height: 0.56rem;
color: #2B2B2B;
}
.el-table th.el-table__cell {
background-color: #F9FAFC;
}
tbody .el-table__row {
height: 0.6rem;
}
.el-table .el-table__cell {
padding: 0;
}
.el-container:nth-child(2) {
flex-direction: column;
background: #f6f6fa;
}
.el-container:nth-child(2) > .el-main {
background: #fff;
margin: 0.24rem;
margin-top: calc(40px + 0.24rem);
border-radius: 0.08rem;
padding: 0.24rem;
}
/* el弹窗自带底部按钮 */
.el-message-box__btns > .el-button {
display: inline-block;
margin-left: 10px;
}
.el-message-box__btns {
display: flex;
flex-direction: row-reverse;
}
.list-table-border {
border: none;
}
.list-table-border::after,
.list-table-border::before {
display: none;
}

View File

@@ -0,0 +1,111 @@
.el-pagination .el-select .el-input {
margin: 0;
}
.el-button {
display: inline-flex;
align-items: center;
justify-content: center;
}
.el-table__fixed-right::before,
.el-table__fixed::before {
height: 0;
}
.el-slider__button-wrapper {
z-index: 2;
}
.el-tabs__nav-wrap::after {
height: 1px;
}
.el-notification__content {
overflow-y: auto;
padding-right: 5px;
max-height: 80vh;
&::-webkit-scrollbar {
width: 5px;
}
&::-webkit-scrollbar-track {
background-color: rgba(255, 255, 255, 0.4);
}
&::-webkit-scrollbar-thumb {
background-color: rgba(255, 255, 255, 0.8);
border-radius: 0.5rem;
}
}
/* 提示弹窗 */
.el-message-box {
width: 5.2rem;
}
.el-message {
z-index: 99999999999 !important;
}
.el-tooltip__popper {
max-width: 50%;
}
/* 表格 表头和每一行 的统一高度 */
thead tr {
height: 0.56rem;
color: #2B2B2B;
}
.el-table th.el-table__cell {
background-color: #F9FAFC;
}
tbody .el-table__row {
height: 0.6rem;
}
.el-table .el-table__cell {
padding: 0;
}
.el-container:nth-child(2) {
flex-direction: column;
background: #f6f6fa;
&>.el-main {
background: #fff;
margin: 0.24rem;
margin-top: calc(40px + 0.24rem);
border-radius: 0.08rem;
padding: 0.24rem;
}
}
/* el弹窗自带底部按钮 */
.el-message-box__btns>.el-button {
display: inline-block;
margin-left: 10px;
}
.el-message-box__btns {
display: flex;
flex-direction: row-reverse;
}
.list-table-border {
border: none;
&::after,
&::before {
display: none;
}
}

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,75 @@
@charset 'utf-8';
/*这些元素都建议重新初始化*/
body,
div,
dl,
dt,
dd,
ul,
ol,
li,
tr,
td,
th,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
br,
img,
table,
input,
form,
a,
p,
textarea {
padding: 0;
margin: 0;
}
/*去掉列表默认排列*/
ul,
ol,
li {
list-style: none;
}
/*去掉底部横线*/
/*把a元素更改设置成块级元素这个根据实际情况决定要不要*/
a {
text-decoration: none;
}
/*img标签要清除border。*/
/*display设为block设置为块级元素默认为display:inline;
存在下边线多出4px状况,所以一般设为block*/
img {
border: 0;
}
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background-color: rgba(255, 255, 255, 0);
}
::-webkit-scrollbar-thumb {
background-color: rgba(144, 147, 153, 0.3);
border-radius: 0.5rem;
}
::-webkit-scrollbar-thumb:hover {
cursor: pointer;
background-color: rgba(144, 147, 153, 0.5);
}
/*清除浮动破坏带来的塌陷问题*/
/*清除浮动的兼容IE*/
.clearfloat {
zoom: 1;
}
.clearfloat:after {
display: block;
clear: both;
content: "";
visibility: hidden;
height: 0;
}

View File

@@ -0,0 +1,89 @@
@charset 'utf-8';
/*这些元素都建议重新初始化*/
body,
div,
dl,
dt,
dd,
ul,
ol,
li,
tr,
td,
th,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
br,
img,
table,
input,
form,
a,
p,
textarea {
padding: 0;
margin: 0;
}
/*去掉列表默认排列*/
ul,
ol,
li {
list-style: none;
}
/*去掉底部横线*/
/*把a元素更改设置成块级元素这个根据实际情况决定要不要*/
a {
text-decoration: none;
}
/*img标签要清除border。*/
/*display设为block设置为块级元素默认为display:inline;
存在下边线多出4px状况,所以一般设为block*/
img {
border: 0;
}
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background-color: rgba(255, 255, 255, 0);
}
::-webkit-scrollbar-thumb {
background-color: rgba(144, 147, 153, .3);
border-radius: 0.5rem;
&:hover {
cursor: pointer;
background-color: rgba(144, 147, 153, .5);
}
}
/*清除浮动破坏带来的塌陷问题*/
/*清除浮动的兼容IE*/
.clearfloat {
zoom: 1;
}
.clearfloat:after {
display: block;
clear: both;
content: "";
visibility: hidden;
height: 0;
}

View File

@@ -0,0 +1,386 @@
/*!
* Viewer.js v0.3.1
* https://github.com/fengyuanchen/viewerjs
*
* Copyright (c) 2015-2016 Fengyuan Chen
* Released under the MIT license
*
* Date: 2016-02-02T11:35:36.273Z
*/
.viewer-container,
.viewer-navbar {
background-color: #000;
overflow: hidden
}
.viewer-canvas,
.viewer-container,
.viewer-footer,
.viewer-player {
right: 0;
bottom: 0;
left: 0
}
.viewer-button,
.viewer-canvas,
.viewer-container,
.viewer-footer,
.viewer-list,
.viewer-navbar,
.viewer-open,
.viewer-title,
.viewer-toolbar,
.viewer-toolbar>li {
overflow: hidden
}
.viewer-close:before,
.viewer-flip-horizontal:before,
.viewer-flip-vertical:before,
.viewer-fullscreen-exit:before,
.viewer-fullscreen:before,
.viewer-next:before,
.viewer-one-to-one:before,
.viewer-play:before,
.viewer-prev:before,
.viewer-reset:before,
.viewer-rotate-left:before,
.viewer-rotate-right:before,
.viewer-zoom-in:before,
.viewer-zoom-out:before {
font-size: 0;
line-height: 0;
display: block;
width: 20px;
height: 20px;
color: transparent;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARgAAAAUCAYAAABWOyJDAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAQPSURBVHic7Zs/iFxVFMa/0U2UaJGksUgnIVhYxVhpjDbZCBmLdAYECxsRFBTUamcXUiSNncgKQbSxsxH8gzAP3FU2jY0kKKJNiiiIghFlccnP4p3nPCdv3p9778vsLOcHB2bfveeb7955c3jvvNkBIMdxnD64a94GHMfZu3iBcRynN7zAOI7TG15gHCeeNUkr8zaxG2lbYDYsdgMbktBsP03jdQwljSXdtBhLOmtjowC9Mg9L+knSlcD8TNKpSA9lBpK2JF2VdDSR5n5J64m0qli399hNFMUlpshQii5jbXTbHGviB0nLNeNDSd9VO4A2UdB2fp+x0eCnaXxWXGA2X0au/3HgN9P4LFCjIANOJdrLr0zzZ+BEpNYDwKbpnQMeAw4m8HjQtM6Z9qa917zPQwFr3M5KgA6J5rTJCdFZJj9/lyvGhsDvwFNVuV2MhhjrK6b9bFiE+j1r87eBl4HDwCF7/U/k+ofAX5b/EXBv5JoLMuILzf3Ap6Z3EzgdqHMCuF7hcQf4HDgeoHnccncqdK/TvSDWffFXI/exICY/xZyqc6XLWF1UFZna4gJ7q8BsRvgd2/xXpo6P+D9dfT7PpECtA3cnWPM0GXGFZh/wgWltA+cDNC7X+AP4GzjZQe+k5dRxuYPeiuXU7e1qwLpDz7dFjXKRaSwuMLvAlG8zZlG+YmiK1HoFqT7wP2z+4Q45TfEGcMt01xLoNZEBTwRqD4BLpnMLeC1A41UmVxsXgXeBayV/Wx20rpTyrpnWRft7p6O/FdqzGrDukPNtkaMoMo3FBdBSQMOnYBCReyf05s126fU9ytfX98+mY54Kxnp7S9K3kj6U9KYdG0h6UdLbkh7poFXMfUnSOyVvL0h6VtIXHbS6nOP+s/Zm9mvyXW1uuC9ohZ72E9uDmXWLJOB1GxsH+DxPftsB8B6wlGDN02TAkxG6+4D3TWsbeC5CS8CDFce+AW500LhhOW2020TRjK3b21HEmgti9m0RonxbdMZeVzV+/4tF3cBpP7E9mKHNL5q8h5g0eYsCMQz0epq8gQrwMXAgcs0FGXGFRcB9wCemF9PkbYqM/Bas7fxLwNeJPdTdpo4itQti8lPMqTpXuozVRVXPpbHI3KkNTB1NfkL81j2mvhDp91HgV9MKuRIqrykj3WPq4rHyL+axj8/qGPmTqi6F9YDlHOvJU6oYcTsh/TYSzWmTE6JT19CtLTJt32D6CmHe0eQn1O8z5AXgT4sx4Vcu0/EQecMydB8z0hUWkTd2t4CrwNEePqMBcAR4mrBbwyXLPWJa8zrXmmLEhNBmfpkuY2102xxrih+pb+ieAb6vGhuA97UcJ5KR8gZ77K+99xxeYBzH6Q3/Z0fHcXrDC4zjOL3hBcZxnN74F+zlvXFWXF9PAAAAAElFTkSuQmCC);
background-repeat: no-repeat
}
.viewer-zoom-in:before {
content: 'Zoom In';
background-position: 0 0
}
.viewer-zoom-out:before {
content: 'Zoom Out';
background-position: -20px 0
}
.viewer-one-to-one:before {
content: 'One to One';
background-position: -40px 0
}
.viewer-reset:before {
content: 'Reset';
background-position: -60px 0
}
.viewer-prev:before {
content: 'Previous';
background-position: -80px 0
}
.viewer-play:before {
content: 'Play';
background-position: -100px 0
}
.viewer-next:before {
content: 'Next';
background-position: -120px 0
}
.viewer-rotate-left:before {
content: 'Rotate Left';
background-position: -140px 0
}
.viewer-rotate-right:before {
content: 'Rotate Right';
background-position: -160px 0
}
.viewer-flip-horizontal:before {
content: 'Flip Horizontal';
background-position: -180px 0
}
.viewer-flip-vertical:before {
content: 'Flip Vertical';
background-position: -200px 0
}
.viewer-fullscreen:before {
content: 'Enter Full Screen';
background-position: -220px 0
}
.viewer-fullscreen-exit:before {
content: 'Exit Full Screen';
background-position: -240px 0
}
.viewer-close:before {
content: 'Close';
background-position: -260px 0
}
.viewer-container {
font-size: 0;
line-height: 0;
position: absolute;
top: 0;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: rgba(0, 0, 0, .5);
direction: ltr !important;
-ms-touch-action: none;
touch-action: none;
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none
}
.viewer-container ::-moz-selection,
.viewer-container::-moz-selection {
background-color: transparent
}
.viewer-container ::selection,
.viewer-container::selection {
background-color: transparent
}
.viewer-container img {
display: block;
width: 100%;
min-width: 0 !important;
max-width: none !important;
height: auto;
min-height: 0 !important;
max-height: none !important
}
.viewer-player,
.viewer-tooltip {
display: none;
position: absolute
}
.viewer-canvas {
position: absolute;
top: 0
}
.viewer-canvas>img {
width: auto;
max-width: 90% !important;
height: auto;
margin: 15px auto
}
.viewer-footer {
position: absolute;
text-align: center
}
.viewer-navbar {
background-color: rgba(0, 0, 0, .5)
}
.viewer-list {
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
height: 50px;
margin: 0;
padding: 1px 0
}
.viewer-list>li {
font-size: 0;
line-height: 0;
float: left;
overflow: hidden;
width: 30px;
height: 50px;
cursor: pointer;
opacity: .5;
color: transparent;
filter: alpha(opacity=50)
}
.viewer-list>li+li {
margin-left: 1px
}
.viewer-list>.viewer-active {
opacity: 1;
filter: alpha(opacity=100)
}
.viewer-player {
top: 0;
cursor: none;
background-color: #000
}
.viewer-player>img {
position: absolute;
top: 0;
left: 0
}
.viewer-toolbar {
width: 280px;
margin: 0 auto 5px;
padding: 3px 0
}
.viewer-toolbar>li {
float: left;
width: 24px;
height: 24px;
cursor: pointer;
border-radius: 50%;
background-color: #000;
background-color: rgba(0, 0, 0, .5)
}
.viewer-toolbar>li:hover {
background-color: #000;
background-color: rgba(0, 0, 0, .8)
}
.viewer-toolbar>li:before {
margin: 2px
}
.viewer-toolbar>li+li {
margin-left: 1px
}
.viewer-toolbar>.viewer-play {
width: 30px;
height: 30px;
margin-top: -3px;
margin-bottom: -3px
}
.viewer-toolbar>.viewer-play:before {
margin: 5px
}
.viewer-tooltip {
font-size: 12px;
line-height: 20px;
top: 50%;
left: 50%;
width: 50px;
height: 20px;
margin-top: -10px;
margin-left: -25px;
text-align: center;
color: #fff;
border-radius: 10px;
background-color: #000;
background-color: rgba(0, 0, 0, .8)
}
.viewer-title {
font-size: 12px;
line-height: 1;
display: inline-block;
max-width: 90%;
margin: 0 5% 5px;
white-space: nowrap;
text-overflow: ellipsis;
opacity: .8;
color: #ccc;
filter: alpha(opacity=80)
}
.viewer-title:hover {
opacity: 1;
filter: alpha(opacity=100)
}
.viewer-button {
position: absolute;
top: -40px;
right: -40px;
width: 80px;
height: 80px;
cursor: pointer;
border-radius: 50%;
background-color: #000;
background-color: rgba(0, 0, 0, .5)
}
.viewer-button:before {
position: absolute;
bottom: 15px;
left: 15px
}
.viewer-fixed {
position: fixed
}
.viewer-show {
display: block
}
.viewer-hide {
display: none
}
.viewer-invisible {
visibility: hidden
}
.viewer-move {
cursor: move;
cursor: -webkit-grab;
cursor: -moz-grab;
cursor: grab
}
.viewer-fade {
opacity: 0;
filter: alpha(opacity=0)
}
.viewer-in {
opacity: 1;
filter: alpha(opacity=100)
}
.viewer-transition {
-webkit-transition: all .3s ease-out;
-o-transition: all .3s ease-out;
transition: all .3s ease-out
}
@media (max-width:767px) {
.viewer-hide-xs-down {
display: none
}
}
@media (max-width:991px) {
.viewer-hide-sm-down {
display: none
}
}
@media (max-width:1199px) {
.viewer-hide-md-down {
display: none
}
}

View File

@@ -0,0 +1,951 @@
.el-main {
padding: 0 !important;
}
.finance .finance-top .finance-title {
padding: 0.24rem;
font-size: 0.16rem;
font-weight: 600;
color: #2B2B2B;
border-bottom: 1px solid #EAEAEA;
}
.finance .finance-top .finance-money-main {
padding: 0.24rem;
border-bottom: 1px solid #EAEAEA;
}
.finance .finance-top .finance-money-main .finance-balance {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.finance .finance-top .finance-money-main .finance-balance .balance-left .balance-left-title {
font-weight: 400;
font-size: 0.14rem;
color: #646464;
}
.finance .finance-top .finance-money-main .finance-balance .balance-left .balance-left-title .balance-title-num {
font-weight: 600;
color: #2B2B2B;
}
.finance .finance-top .finance-money-main .finance-balance .balance-left .balance-left-num {
margin-top: 0.16rem;
font-weight: 600;
font-size: 0.45rem;
color: #2B2B2B;
}
.finance .finance-top .finance-money-main .finance-balance .balance-left .balance-left-num .prefix {
font-size: 0.24rem;
}
.finance .finance-top .finance-money-main .finance-balance .balance-right {
display: flex;
align-items: center;
column-gap: 0.16rem;
}
.finance .finance-top .finance-money-main .finance-balance .balance-right .el-button {
height: 0.37rem;
border-radius: 0.04rem;
}
.finance .finance-top .finance-money-main .finance-balance .balance-right .balance-tx-btn {
color: var(--color-primary);
border-color: var(--color-primary);
}
.finance .finance-top .finance-money-main .finance-balance .balance-right .tx-list {
font-size: 0.14rem;
color: #999999;
cursor: pointer;
}
.finance .finance-top .finance-money-main .finance-other-money {
margin-top: 0.24rem;
padding-top: 0.24rem;
display: flex;
align-items: center;
border-top: 1px dashed #EAEAEA;
}
.finance .finance-top .finance-money-main .finance-other-money .other-money-item {
display: flex;
align-items: center;
padding: 0 0.4rem;
border-left: 1px solid #EAEAEA;
}
.finance .finance-top .finance-money-main .finance-other-money .other-money-item:nth-of-type(1) {
padding-left: 0;
border-left: none;
}
.finance .finance-top .finance-money-main .finance-other-money .other-money-item .other-money-item-title {
display: flex;
align-items: center;
column-gap: 0.05rem;
color: #646464;
font-weight: 400;
font-size: 0.14rem;
margin-right: 0.08rem;
}
.finance .finance-top .finance-money-main .finance-other-money .other-money-item .other-money-item-value {
font-weight: 600;
font-size: 0.18rem;
color: #2B2B2B;
}
.finance .finance-top .finance-money-main .finance-other-money .other-money-item .other-money-item-value .prefix {
font-size: 0.12rem;
}
.finance .finance-top .finance-money-main .finance-other-money .other-money-item .freeze-list {
margin-left: 0.16rem;
font-weight: 400;
font-size: 0.12rem;
color: var(--color-primary);
text-decoration: underline;
cursor: pointer;
}
.finance .content_box {
padding: 0.24rem;
}
.a-text {
cursor: pointer;
}
.a-text:hover {
text-decoration: underline;
}
.content_searchbar {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 0.2rem;
margin-bottom: 0.2rem;
}
.content_searchbar .left_tips {
display: flex;
align-items: center;
column-gap: 0.2rem;
}
.content_searchbar .left_tips .all-pay {
padding: 0 10px;
height: 32px;
}
.content_searchbar .left_tips .all-del {
margin-left: 0;
padding: 0 10px;
height: 32px;
}
.content_searchbar .left_tips .tips_item {
display: flex;
align-items: center;
}
.finance .el-tabs__content {
min-height: 5rem;
}
.dot {
width: 0.08rem;
height: 0.08rem;
line-height: 0.1rem;
border-radius: 50%;
display: inline-block;
margin-right: 0.1rem;
}
.dot.new {
background: #0058FF;
}
.dot.renew,
.dot.on_demand {
background: #3DD598;
}
.dot.upgrade,
.dot.change_billing_cycle {
background: #F0142F;
}
.dot.artificial {
background: #F99600;
}
.dot.recharge {
background: #9C27B0;
}
.main_table {
margin-top: 0.7rem;
}
.main_table > thead > tr > th:nth-child(1) {
padding-left: 0.3rem;
}
.pay-html {
display: flex;
justify-content: center;
}
.pay-html > img {
width: 2.5rem;
height: 2.5rem;
}
.status-tag {
padding: 0.04rem 0.1rem;
border-radius: 3px;
font-size: 13px;
border: none;
}
.status-tag.Unpaid {
background-color: rgba(240, 20, 47, 0.08);
color: var(--color-danger);
border: none;
}
.status-tag.Paid {
background-color: rgba(61, 213, 152, 0.12);
color: var(--color-success);
border: none;
}
.status-tag.Wait {
background-color: rgba(230, 162, 60, 0.12);
color: var(--color-warning);
border: none;
}
.status-tag.Refunded {
background-color: rgba(64, 158, 255, 0.12);
color: var(--color-info);
border: none;
}
.gateway-pay {
color: #5c5ee4;
cursor: pointer;
}
.tooltip {
text-align: center;
}
.balance-tag {
padding: 0.04rem 0.1rem;
border-radius: 3px;
font-size: 13px;
}
.balance-tag.Recharge,
.balance-tag.recharge {
background: rgba(54, 153, 255, 0.12);
color: var(--color-info);
}
.Applied {
background: rgba(249, 150, 0, 0.12);
color: var(--color-warning);
}
.Refund {
background: rgba(240, 20, 47, 0.12);
color: var(--color-danger);
}
.Withdraw {
background: rgba(61, 213, 152, 0.12);
color: var(--color-success);
}
.Artificial {
background: rgba(54, 153, 255, 0.12);
color: var(--color-primary);
}
.Freeze {
background: rgba(240, 20, 47, 0.12);
color: var(--color-danger);
}
.Unfreeze {
background: rgba(54, 153, 255, 0.12);
color: var(--color-info);
}
.el-form,
.el-select {
width: 100%;
}
.el-form-item__label {
font-size: 0.16rem;
font-family: PingFang SC;
font-weight: 400;
color: #1e2736;
}
.kd-dialog .dialog-title {
font-size: 0.24rem;
font-weight: 400;
color: #171725;
}
.kd-dialog .dialog-dec {
margin-top: 0.2rem;
color: #1e2736;
}
.kd-dialog .el-dialog__body {
padding: 0.24rem;
font-size: 0.16rem;
}
.kd-dialog .dialog-box {
margin-top: 0.3rem;
padding: 0.2rem 0.16rem;
border: 0.01rem solid #e6e7eb;
}
.kd-dialog .kd-item {
margin-bottom: 0.1rem;
font-size: 0.14rem;
}
.kd-dialog .kd-item:nth-last-of-type(1) {
margin-bottom: 0;
}
.kd-dialog .kd-item .kd-label {
color: #8692b0;
}
.kd-dialog .kd-item .kd-value {
margin-left: 0.3rem;
color: #4E5259;
}
.kd-dialog .dialog-fotter {
display: flex;
justify-content: center;
margin-top: 0.4rem;
}
.kd-dialog .dialog-fotter .el-button {
width: 1.12rem;
height: 0.46rem;
color: #1e2736;
font-size: 0.16rem;
background: #E7E7E7;
border-radius: 0.03rem 0.03rem 0.03rem 0.03rem;
}
.info-dialog .dialog-title {
font-size: 0.24rem;
font-weight: 400;
color: #171725;
}
.info-dialog .certification-info {
margin-top: 0.1rem;
margin-bottom: 0.3rem;
padding: 0.2rem 0.16rem;
border: 0.01rem solid #e6e7eb;
}
.info-dialog .certification-info .kd-item {
margin-bottom: 0.1rem;
font-size: 0.14rem;
}
.info-dialog .certification-info .kd-item:nth-last-of-type(1) {
margin-bottom: 0;
}
.info-dialog .certification-info .kd-item .kd-label {
color: #8692b0;
}
.info-dialog .certification-info .kd-item .kd-value {
margin-left: 0.3rem;
color: #4E5259;
}
.info-dialog .dialog-dec {
font-size: 0.14rem;
padding: 0.12rem 0.16rem;
margin-top: 0.4rem;
color: var(--color-danger);
border-radius: 0.03rem 0.03rem 0.03rem 0.03rem;
background: #FDE6E9;
}
.info-dialog .dialog-dec p {
margin: 0;
}
.info-dialog .el-dialog__body {
padding: 0.24rem;
font-size: 0.16rem;
}
.info-dialog .dialog-fotter {
display: flex;
justify-content: end;
margin-top: 0.4rem;
}
.info-dialog .info-form .el-form-item__label {
padding: 0 !important;
}
.info-dialog .save-btn,
.info-dialog .cancel-btn {
width: 1.12rem;
height: 0.46rem;
font-size: 0.16rem;
border-radius: 0.03rem;
border: none;
}
.info-dialog .save-btn {
background: var(--color-primary);
color: rgba(255, 255, 255, 0.9);
}
.info-dialog .cancel-btn {
margin-left: 0.12rem;
background: #E7E7E7;
color: #1e2736;
}
.info-dialog .first-save-tip {
font-size: 0.14rem;
color: var(--color-danger);
}
.cancel-dialog .dialog-title {
font-size: 0.24rem;
font-weight: 400;
color: #171725;
}
.cancel-dialog .el-dialog__body {
padding: 0.24rem;
font-size: 0.16rem;
}
.cancel-dialog .dialog-dec {
margin-top: 0.3rem;
color: #1e2736;
}
.cancel-dialog .dialog-fotter {
margin-top: 0.4rem;
display: flex;
justify-content: center;
}
.cancel-dialog .dialog-fotter .save-btn,
.cancel-dialog .dialog-fotter .cancel-btn {
width: 1.12rem;
height: 0.46rem;
border-radius: 0.03rem 0.03rem 0.03rem 0.03rem;
border: none;
font-size: 0.16rem;
}
.cancel-dialog .dialog-fotter .save-btn {
background: var(--color-primary);
color: rgba(255, 255, 255, 0.9);
}
.cancel-dialog .dialog-fotter .cancel-btn {
margin-left: 0.12rem;
background: #E7E7E7;
color: #1e2736;
}
.mail-dialog .dialog-title {
font-size: 0.24rem;
font-weight: 400;
color: #171725;
}
.mail-dialog .dialog-dec {
font-size: 0.14rem;
margin-top: 0.3rem;
color: #1e2736;
}
.mail-dialog .el-dialog__body {
padding: 0.24rem;
font-size: 0.16rem;
}
.mail-dialog .dialog-fotter {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 0.4rem;
}
.mail-dialog .info-form .el-form-item__label {
padding: 0 !important;
}
.mail-dialog .fotter-left {
color: #1e2736;
font-size: 0.16rem;
}
.mail-dialog .fotter-left .price-blue {
font-weight: bold;
color: var(--color-primary);
}
.mail-dialog .save-btn,
.mail-dialog .cancel-btn {
width: 1.12rem;
height: 0.46rem;
font-size: 0.16rem;
border-radius: 0.03rem;
border: none;
}
.mail-dialog .save-btn {
background: var(--color-primary);
color: rgba(255, 255, 255, 0.9);
}
.mail-dialog .cancel-btn {
margin-left: 0.12rem;
background: #E7E7E7;
color: #1e2736;
}
.creat-dia .dialog-tips {
display: flex;
}
.creat-dia .tips_item {
margin-right: 0.2rem;
}
.credit-content {
margin-top: 0.4rem;
}
.credit-content .credit-top {
display: flex;
margin-bottom: 0.4rem;
}
.credit-content .credit-top .credit-item {
margin-left: 0.4rem;
padding: 0.31rem 0.2rem 0.4rem 0.2rem;
flex: 1;
flex-shrink: 0;
border-radius: 0.03rem 0.03rem 0.03rem 0.03rem;
border: 0.01rem solid #e6e7eb;
}
.credit-content .credit-top .credit-item:nth-of-type(1) {
margin-left: 0;
}
.credit-content .credit-top .credit-item .item-top {
display: flex;
justify-content: space-between;
align-items: center;
color: #8692b0;
}
.credit-content .credit-top .credit-item .item-top .item-l {
font-size: 0.16rem;
}
.credit-content .credit-top .credit-item .item-top .item-r {
font-size: 0.14rem;
}
.credit-content .credit-top .credit-item .item-top .label-box {
display: inline-block;
padding: 0.03rem 0.16rem;
border-radius: 0.03rem 0.03rem 0.03rem 0.03rem;
}
.credit-content .credit-top .credit-item .item-top .is-active {
background-color: rgba(54, 153, 255, 0.12);
color: var(--color-primary);
}
.credit-content .credit-top .credit-item .item-top .no-active {
background-color: rgba(240, 20, 47, 0.08);
color: var(--color-danger);
}
.credit-content .credit-top .credit-item .item-bottom {
margin-top: 0.1rem;
}
.credit-content .credit-top .credit-item .item-bottom .item-bl {
font-size: 0.28rem;
font-weight: bold;
color: #1e2736;
}
.credit-content .credit-top .credit-item .flex-bottom {
display: flex;
justify-content: space-between;
align-items: center;
}
.credit-content .credit-top .credit-item .flex-bottom .credit-btn,
.credit-content .credit-top .credit-item .flex-bottom .no-btn {
height: 0.32rem;
font-size: 0.14rem;
border-radius: 0.03rem 0.03rem 0.03rem 0.03rem;
}
.credit-content .credit-top .credit-item .flex-bottom .credit-btn {
background: var(--color-primary);
color: #FFFFFF;
}
.credit-content .credit-top .credit-item .flex-bottom .no-btn {
border: 0.01rem solid #e6e7eb;
background: #FFFFFF;
color: #757575;
}
.credit-content .credit-operation {
cursor: pointer;
font-size: 0.14rem;
color: var(--color-primary);
}
.dialog-form {
display: flex;
flex-direction: column;
}
.el-row {
display: flex;
align-items: center;
margin-top: 0.3rem;
}
.form-footer {
display: flex;
justify-content: flex-end;
}
.form-footer > .btn-ok {
background: var(--color-primary);
border-radius: 3px;
color: rgba(255, 255, 255, 0.9);
display: flex;
align-items: center;
justify-content: center;
}
.form-footer > .btn-no {
background: #e7e7e7;
border-radius: 3px;
color: #1e2736;
display: flex;
align-items: center;
justify-content: center;
}
.true-money {
color: var(--color-warning);
}
.orderid_a {
cursor: pointer;
}
.orderid_a:hover {
border-bottom: 2px solid #808080;
}
.el-input__suffix {
display: flex;
align-items: center;
}
.input-search {
padding-right: 0.1rem;
cursor: pointer;
}
.cz-input {
display: flex;
flex-direction: row;
align-items: center;
}
.cz-input > .btn-ok {
margin-left: 0.1rem;
height: 0.46rem;
background: var(--color-primary);
border-radius: 3px;
color: rgba(255, 255, 255, 0.9);
display: flex;
align-items: center;
justify-content: center;
}
.el-table__expand-icon {
position: absolute;
left: 0.1rem;
}
.el-table__indent {
padding: 0 !important;
}
.mobel {
display: none;
}
.el-icon-more {
font-size: 0.16rem;
color: var(--color-primary);
cursor: pointer;
}
.el-popover {
min-width: 0.5rem !important;
}
.operation-box {
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.operation-item {
margin-top: 0.05rem;
margin-bottom: 0.05rem;
cursor: pointer;
}
.operation-item:hover {
color: var(--color-primary);
}
.has-border {
border: 0.01rem solid #e6e7eb;
}
.contract-status {
display: inline-block;
padding: 0.04rem 0.1rem;
border-radius: 0.03rem;
}
.help-icon {
cursor: pointer;
margin-left: 0.04rem;
color: var(--color-primary);
}
.delete-order-dialog .el-dialog__header {
padding: 0;
}
.delete-order-dialog .el-dialog__body {
padding: 0;
}
.delete-order-dialog .delete-box {
height: 2.56rem;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: #ffffff;
}
.delete-order-dialog .delete-content {
font-size: 0.18rem;
color: #1e2736;
}
.delete-order-dialog .delete-btn {
margin-top: 0.4rem;
display: flex;
justify-content: center;
}
.delete-order-dialog .delete-btn .save-btn,
.delete-order-dialog .delete-btn .cancel-btn {
width: 1.12rem;
height: 0.46rem;
border-radius: 0.03rem 0.03rem 0.03rem 0.03rem;
border: none;
font-size: 0.16rem;
}
.delete-order-dialog .delete-btn .save-btn {
background: var(--color-danger);
color: rgba(255, 255, 255, 0.9);
}
.delete-order-dialog .delete-btn .cancel-btn {
margin-left: 0.12rem;
background: #E7E7E7;
color: #1e2736;
}
.pre-dialog .dialog-box {
text-align: center;
}
.pre-dialog .dialog-box .tit {
font-size: 0.18rem;
font-weight: bold;
color: #333;
margin-top: 0;
margin-bottom: 0.3rem;
}
.pre-dialog .dialog-box .con .item {
margin: 5px 0;
}
.pre-dialog .dialog-fotter {
margin-top: 0.2rem;
}
.pre-dialog .dialog-fotter .save-btn {
background: var(--color-primary);
color: #fff;
}
.pre-dialog .s-tip {
margin: 0.2rem 0 0 0;
font-size: 0.14rem;
color: #999;
}
@media screen and (max-width: 750px) {
.content_searchbar .left_tips .tips_item {
margin-right: 0.1rem;
}
.searchbar {
width: 100%;
}
.searchbar .el-input {
width: 100% !important;
margin-left: 0 !important;
}
.content_searchbar {
flex-wrap: wrap;
}
.mob-searchbar {
margin-top: 0.53rem;
}
.mob-search-input {
height: 0.8rem;
background: rgba(134, 146, 176, 0.1);
border-radius: 3px 3px 0px 0px;
}
.mob-search-input > input {
height: 0.8rem;
background: rgba(134, 146, 176, 0.1);
border-radius: 3px 3px 0px 0px;
}
.mob-tabledata {
display: flex;
flex-direction: column;
border: 1px solid #d7d8db;
border-radius: 0px 0px 3px 3px;
}
.mob-tabledata-item {
height: auto;
border-bottom: 1px solid #d7d8db;
display: flex;
flex-direction: column;
padding: 0 0.3rem;
}
.mob-item-row {
display: flex;
justify-content: space-between;
margin-top: 0.2rem;
}
.mob-item-row1,
.mob-item-row3,
.mob-item-row-notes {
font-size: 0.26rem;
line-height: 0.26rem;
color: #8692b0;
margin-left: 0.26rem;
}
.mob-item-row1 {
margin-top: 0.41rem;
align-items: center;
}
.mob-item-row2 {
font-size: 0.3rem;
line-height: 0.31rem;
color: #1e2736;
}
.mob-item-row3 {
margin-bottom: 0.33rem;
}
.mob-item-row2-name {
width: 50%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.bottom-text {
font-size: 0.26rem;
line-height: 0.26rem;
color: #8692b0;
margin: 0.4rem 0;
display: flex;
justify-content: center;
}
.back-top-img {
width: 0.88rem;
position: fixed;
right: 0.3rem;
bottom: 1.17rem;
}
.el-form-item__label {
font-size: 0.32rem;
line-height: 0.32rem;
}
.dialog-form .el-input__inner {
height: 0.8rem;
}
.cz-input > .btn-ok {
height: 0.8rem;
}
.dialog-footer {
flex-direction: column;
}
.dialog-footer .btn-ok,
.dialog-footer .btn-no {
width: 100%;
height: 0.8rem;
font-size: 0.34rem;
}
.dialog-footer .btn-no {
margin-left: 0;
margin-top: 0.2rem;
}
.top-line {
display: none;
}
.order-detail-table {
margin-top: 0.5rem;
}
.main_table {
display: none;
}
.mob-item-row-child {
background: #eef4ff;
display: flex;
flex-direction: column;
}
.child-row {
display: flex;
flex-direction: row;
justify-content: space-between;
font-size: 0.26rem;
margin-bottom: 0.16rem;
line-height: 0.4rem;
color: #8692b0;
margin-left: 0.26rem;
margin-right: 0.2rem;
}
.child-row:nth-child(1) {
margin-top: 0.16rem;
}
.child-row-name {
color: #1e2736;
width: 2.86rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.money {
font-size: 0.4rem;
}
.item-balance > .text {
font-size: 0.26rem;
}
.money-num > .text {
font-size: 0.26rem;
}
.item-unbalance > .text {
font-size: 0.26rem;
}
.btn-tx,
.btn-cz {
height: 0.42rem;
width: 0.76rem;
font-size: 0.22rem;
}
.balance-tag {
font-size: 0.24rem;
}
.left_tips {
font-size: 0.26rem;
}
.balance-searchbar {
margin-top: 0;
}
.form-footer {
display: flex;
flex-direction: column;
}
}
/* 签章上传样式 */
.seal-upload .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: all 0.3s;
}
.seal-upload .el-upload:hover {
border-color: var(--color-primary);
}
.seal-upload-content {
width: 150px;
height: 150px;
position: relative;
}
.seal-upload-content .seal-image {
width: 100%;
height: 100%;
object-fit: contain;
display: block;
}
.seal-upload-content .seal-mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #fff;
opacity: 0;
transition: opacity 0.3s;
}
.seal-upload-content:hover .seal-mask {
opacity: 1;
}
.seal-mask-actions {
display: flex;
gap: 20px;
}
.seal-mask-actions i {
font-size: 20px;
cursor: pointer;
transition: transform 0.2s;
}
.seal-upload-placeholder {
width: 150px;
height: 150px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #8c939d;
}
.seal-upload-placeholder i {
font-size: 32px;
color: #8c939d;
}
.seal-upload-text {
margin-top: 8px;
font-size: 12px;
color: #606266;
}
.seal-upload-tip {
margin-top: 4px;
font-size: 11px;
color: #909399;
text-align: center;
line-height: 1.4;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,243 @@
* {
margin: 0;
padding: 0;
}
#forget {
height: 100vh;
width: 100vw;
display: flex;
justify-content: center;
align-items: center;
}
.login-container {
width: 15.7rem;
height: 8.2rem;
display: flex;
justify-content: center;
align-items: center;
position: relative;
}
.container-back {
width: 15.7rem;
height: 6.8rem;
background: var(--color-primary);
border-radius: 20px;
overflow: hidden;
position: relative;
font-family: Source Han Sans CN;
}
.container-back .back-text {
font-size: 0.27rem;
z-index: 10;
color: #FFFFFF;
margin-top: 1.39rem;
margin-left: 0.65rem;
font-weight: 400;
}
.container-back .text-welcome {
font-size: 0.74rem;
font-family: Bahnschrift;
line-height: 0.74rem;
}
.container-back .text-title {
margin-top: 5px;
}
.container-back .text-level {
font-size: 0.12rem;
margin-top: 0.81rem;
}
.container-back .back-line1,
.container-back .back-line2,
.container-back .back-line3 {
width: 60px;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.3) 0%, rgba(255, 255, 255, 0) 100%);
z-index: 2;
position: absolute;
}
.container-back .back-line1 {
height: 5rem;
opacity: 1;
transform: rotate(45deg);
top: -1.2rem;
left: 4.15rem;
}
.container-back .back-line2 {
height: 7rem;
transform: rotate(110deg);
top: 0px;
left: 5rem;
}
.container-back .back-line3 {
height: 5rem;
transform: rotate(45deg);
top: 2.3rem;
left: 1.5rem;
}
.container-before {
width: 7.5rem;
height: 8rem;
background: #FFFFFF;
box-shadow: 0px 3px 12px rgba(0, 0, 0, 0.1);
position: absolute;
right: 0.9rem;
border: 4px;
z-index: 10;
}
.login {
padding-top: 0.8rem;
padding-left: 1.24rem;
padding-right: 1.05rem;
font-size: 14px;
font-family: PingFang SC;
font-weight: 400;
line-height: 14px;
}
.login-text {
display: flex;
flex-direction: column;
}
.login-text-title {
font-size: 0.32rem;
color: #1E2736;
line-height: 0.32rem;
}
.login-text-regist {
font-weight: Regular;
margin-top: 0.08rem;
color: #1E2736;
}
.login-text-regist a {
color: var(--color-primary);
cursor: pointer;
}
.login-form {
margin-top: 0.68rem;
}
.login-top {
display: flex;
flex-direction: row;
}
.login-email,
.login-phone {
height: 0.34rem;
color: #666B80;
cursor: pointer;
}
.login-phone {
margin-left: 0.4rem;
}
.active {
color: var(--color-primary);
border-bottom: 2px solid var(--color-primary);
}
.form-main {
margin-top: 0.3rem;
}
.form-item {
margin-top: 0.3rem;
}
.input-with-select .el-input-group__prepend {
background: #FFFFFF;
width: 60px;
}
.code-item {
display: flex;
flex-direction: row;
}
.code-btn {
margin-left: 0.1rem;
background: var(--color-primary);
color: #FFFFFF;
}
.rember-item {
margin-top: 0.2rem;
display: flex;
justify-content: space-between;
}
.rember-item a {
color: var(--color-primary);
cursor: pointer;
}
.login-btn {
width: 100%;
height: 46px;
background: var(--color-primary);
}
.read-item {
margin-top: 0.2rem;
}
.read-item a {
color: var(--color-primary);
cursor: pointer;
}
.line-item {
margin-top: 0.4rem;
}
.line-item text {
font-size: 16px;
color: #1E2736;
}
.type-btn {
width: 100%;
height: 0.46rem;
font-size: 0.16rem;
}
@media screen and (max-width: 750px) {
.login-container {
height: calc(100vh - 1.2rem);
width: 100vw;
background: #F2F2FE;
padding: 0.6rem 0;
}
.container-back {
display: none;
}
.container-before {
width: 100%;
height: 100%;
margin: 0rem 0.3rem;
position: unset;
z-index: 0;
}
.login {
padding-top: 1.17rem;
padding-left: 0.3rem;
padding-right: 0.3rem;
font-size: 0.26rem;
line-height: 0.3rem;
}
.login-text-title {
font-size: 0.4rem;
}
.login-text-regist {
margin-top: 0.1rem;
font-size: 0.28rem;
}
.login-form {
margin-top: 1.21rem;
}
.login-email,
.login-phone {
height: 0.34rem;
width: 100%;
text-align: center;
color: #666B80;
cursor: pointer;
padding-bottom: 0.13rem;
}
.el-checkbox__label {
font-size: 0.26rem;
}
.read-item {
line-height: 0.3rem;
}
.login-btn {
font-size: 0.34rem;
height: 0.8rem;
}
.type-btn {
border: none;
color: var(--color-primary);
font-size: 0.34rem;
}
}

View File

@@ -0,0 +1,306 @@
// Variables
@text-color: #1E2736;
@border-color: #E6E7EB;
@background-color: #FFFFFF;
@text-secondary: #666B80;
// Mixins
.flex-center() {
display: flex;
justify-content: center;
align-items: center;
}
* {
margin: 0;
padding: 0;
}
#forget {
height: 100vh;
width: 100vw;
.flex-center();
}
.login-container {
width: 15.7rem;
height: 8.2rem;
.flex-center();
position: relative;
}
// Background panel
.container-back {
width: 15.7rem;
height: 6.8rem;
background: var(--color-primary);
border-radius: 20px;
overflow: hidden;
position: relative;
font-family: Source Han Sans CN;
.back-text {
font-size: .27rem;
z-index: 10;
color: #FFFFFF;
margin-top: 1.39rem;
margin-left: .65rem;
font-weight: 400;
}
.text-welcome {
font-size: .74rem;
font-family: Bahnschrift;
line-height: .74rem;
}
.text-title {
margin-top: 5px;
}
.text-level {
font-size: .12rem;
margin-top: .81rem;
}
.back-line1,
.back-line2,
.back-line3 {
width: 60px;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.3000) 0%, rgba(255, 255, 255, 0) 100%);
z-index: 2;
position: absolute;
}
.back-line1 {
height: 5rem;
opacity: 1;
transform: rotate(45deg);
top: -1.2rem;
left: 4.15rem;
}
.back-line2 {
height: 7rem;
transform: rotate(110deg);
top: 0px;
left: 5rem;
}
.back-line3 {
height: 5rem;
transform: rotate(45deg);
top: 2.3rem;
left: 1.5rem;
}
}
// Login form
.container-before {
width: 7.5rem;
height: 8rem;
background: @background-color;
box-shadow: 0px 3px 12px rgba(0, 0, 0, 0.1000);
position: absolute;
right: .9rem;
border: 4px;
z-index: 10;
}
.login {
padding-top: .8rem;
padding-left: 1.24rem;
padding-right: 1.05rem;
font-size: 14px;
font-family: PingFang SC;
font-weight: 400;
line-height: 14px;
&-text {
display: flex;
flex-direction: column;
&-title {
font-size: .32rem;
color: @text-color;
line-height: .32rem;
}
&-regist {
font-weight: Regular;
margin-top: .08rem;
color: @text-color;
a {
color: var(--color-primary);
cursor: pointer;
}
}
}
&-form {
margin-top: .68rem;
}
&-top {
display: flex;
flex-direction: row;
}
&-email,
&-phone {
height: .34rem;
color: @text-secondary;
cursor: pointer;
}
&-phone {
margin-left: .4rem;
}
}
.active {
color: var(--color-primary);
border-bottom: 2px solid var(--color-primary);
}
.form-main {
margin-top: .3rem;
}
.form-item {
margin-top: .3rem;
}
.input-with-select {
.el-input-group__prepend {
background: @background-color;
width: 60px;
}
}
.code-item {
display: flex;
flex-direction: row;
}
.code-btn {
margin-left: .1rem;
background: var(--color-primary);
color: @background-color;
}
.rember-item {
margin-top: .2rem;
display: flex;
justify-content: space-between;
a {
color: var(--color-primary);
cursor: pointer;
}
}
.login-btn {
width: 100%;
height: 46px;
background: var(--color-primary);
}
.read-item {
margin-top: .2rem;
a {
color: var(--color-primary);
cursor: pointer;
}
}
.line-item {
margin-top: .4rem;
text {
font-size: 16px;
color: @text-color;
}
}
.type-btn {
width: 100%;
height: 0.46rem;
font-size: .16rem;
}
// Media queries
@media screen and (max-width: 750px) {
.login-container {
height: calc(100vh - 1.2rem);
width: 100vw;
background: #F2F2FE;
padding: .6rem 0;
}
.container-back {
display: none;
}
.container-before {
width: 100%;
height: 100%;
margin: 0rem .3rem;
position: unset;
z-index: 0;
}
.login {
padding-top: 1.17rem;
padding-left: .3rem;
padding-right: .3rem;
font-size: .26rem;
line-height: .3rem;
&-text {
&-title {
font-size: .4rem;
}
&-regist {
margin-top: .1rem;
font-size: .28rem;
}
}
&-form {
margin-top: 1.21rem;
}
&-email,
&-phone {
height: .34rem;
width: 100%;
text-align: center;
color: @text-secondary;
cursor: pointer;
padding-bottom: .13rem;
}
}
.el-checkbox__label {
font-size: .26rem;
}
.read-item {
line-height: .3rem;
}
.login-btn {
font-size: .34rem;
height: 0.8rem;
}
.type-btn {
border: none;
color: var(--color-primary);
font-size: .34rem;
}
}

View File

@@ -0,0 +1,883 @@
.el-main {
padding: 40px 0 0 0;
}
.main-card {
max-width: none;
background: #F3F5F9;
}
.main-content {
display: flex;
}
.left-box {
flex: 1;
}
.info-box {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
box-sizing: border-box;
padding: 0.84rem 0.6rem 0.4rem 1.1rem;
border-right: 1px solid #E6E7EB;
background-color: #fff;
min-height: 1.88rem;
}
.info-first {
height: 0.6rem;
display: flex;
cursor: pointer;
}
.name-first {
display: flex;
justify-content: center;
align-items: center;
font-size: 0.36rem;
background: #fff;
width: 0.6rem;
height: 0.6rem;
border-radius: 0.03rem;
color: #FFFFFF;
font-weight: bold;
}
.name-box {
display: flex;
flex-direction: column;
justify-content: flex-end;
margin-left: 0.08rem;
}
.name {
color: #8692B0;
font-size: 0.14rem;
font-weight: 400;
}
.name .id-text {
color: #1E2736;
}
.hello {
font-weight: 400;
font-size: 0.16rem;
color: #1E2736;
}
.info-second {
height: 0.6rem;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.info-three {
display: flex;
flex-direction: column;
justify-content: space-between;
row-gap: 0.04rem;
}
.info-three .compny-box,
.info-three .person-box {
display: flex;
align-items: flex-start;
column-gap: 0.32rem;
font-size: 0.14rem;
}
.info-three .compny-box .left-icon,
.info-three .person-box .left-icon {
display: flex;
align-items: center;
column-gap: 0.04rem;
font-size: 0.14rem;
color: #8692B0;
}
.info-three .compny-box .left-icon img,
.info-three .person-box .left-icon img {
vertical-align: middle;
width: 0.24rem;
height: 0.24rem;
flex-shrink: 0;
}
.info-three .compny-box .right-text .certify-id,
.info-three .person-box .right-text .certify-id {
display: flex;
align-items: center;
}
.info-three .compny-box .right-text .right-type,
.info-three .person-box .right-text .right-type {
color: #949CB0;
}
.info-three .compny-box .right-text .company-name,
.info-three .person-box .right-text .company-name {
color: #1E2736;
}
.info-three .compny-box .right-text .certify-bottom,
.info-three .person-box .right-text .certify-bottom {
display: flex;
align-items: center;
}
.info-three .compny-box .right-text .certify-bottom .cpoy-btn,
.info-three .person-box .right-text .certify-bottom .cpoy-btn {
cursor: pointer;
margin-left: 0.04rem;
width: 0.14rem;
height: 0.14rem;
}
.info-three .compny-box .right-text .bule-text,
.info-three .person-box .right-text .bule-text {
cursor: pointer;
color: #3699FF;
}
.info-three .compny-box .right-text .certify-text,
.info-three .person-box .right-text .certify-text {
color: #292E36;
display: inline-block;
max-width: 1.6rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.email-box,
.phone-box {
color: #8692B0;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 0.14rem;
}
.email-box .phone-number,
.phone-box .phone-number {
margin-left: 0.25rem;
color: #1E2736;
}
.info-second > div img {
margin-right: 0.05rem;
vertical-align: middle;
width: 0.16rem;
}
.statistics-box {
margin-top: 0.4rem;
padding: 0 0.36rem 0rem 0.8rem;
}
.title-text {
font-weight: Bold;
color: #171725;
font-size: 0.16rem;
margin-bottom: 0.1rem;
}
.statistics-content {
display: flex;
flex-wrap: wrap;
min-height: 2.57rem;
}
.money-box {
flex: 1;
background-color: #fff;
}
.order-box {
display: flex;
}
.order-box > div {
height: 100%;
width: 1.66rem;
}
.statistics-top {
padding: 0.16rem 0.16rem 0 0.16rem;
display: flex;
justify-content: space-between;
column-gap: 0.16rem;
}
.statistics-top .statistics-credit {
flex: 1;
flex-shrink: 0;
border-radius: 4px;
background: rgba(221, 225, 230, 0.24);
padding: 0.12rem 0.08rem;
}
.statistics-top .statistics-credit .credit-title {
color: #949cb0;
font-size: 0.12rem;
display: flex;
align-items: center;
column-gap: 0.08rem;
}
.statistics-top .statistics-credit .credit-title .credit-tag {
color: #444B59;
font-size: 0.12rem;
box-sizing: border-box;
padding: 0.02rem 0.04rem;
/* 线条/描边 */
border: 1px solid #dcdfe6;
border-radius: 2px;
background: #ffffff;
}
.statistics-top .statistics-credit .credit-money {
margin-top: 0.1rem;
display: flex;
align-items: center;
column-gap: 0.1rem;
}
.statistics-top .statistics-credit .credit-money .credit-num {
color: #292e36;
font-size: 0.18rem;
font-weight: bold;
flex-shrink: 0;
}
.statistics-top .statistics-credit .credit-money .recharge-btn {
cursor: pointer;
padding: 0 0.1rem;
line-height: 0.24rem;
color: #ffffff;
font-size: 0.12rem;
border-radius: 0.04rem;
background: #0058FF;
}
.statistics-top .statistics-credit .credit-money .recharge-text {
cursor: pointer;
color: #0058FF;
font-size: 0.12rem;
}
.voucher-box {
padding: 0 0.16rem;
color: #949CB0;
font-size: 0.12rem;
margin-top: 0.06rem;
}
.voucher-box .bule-text {
color: #0058FF;
margin-left: 0.03rem;
cursor: pointer;
}
.statistics-bottom {
display: flex;
padding: 0.16rem 0.24rem;
}
.statistics-bottom-right {
margin-left: 0.24rem;
display: flex;
flex: 1;
flex-direction: column;
justify-content: center;
}
.money-month,
.money-total {
display: flex;
align-items: center;
flex-wrap: wrap;
justify-content: space-between;
color: #949CB0;
font-size: 0.12rem;
}
.money-total {
margin-top: 0.1rem;
}
.type-box {
margin-right: 0.05rem;
display: inline-block;
width: 0.08rem;
height: 0.08rem;
}
.green-bg {
background-color: #04C8C9;
}
.grey-bg {
background-color: #E4E7EF;
}
.percent-box-green {
display: inline-block;
padding: 0 0.03rem;
background: rgba(80, 205, 136, 0.08);
color: #50CD89;
font-size: 0.13rem;
border-radius: 0.03rem;
}
.percent-box-red {
display: inline-block;
padding: 0 0.03rem;
background: rgba(240, 20, 46, 0.08);
font-size: 0.13rem;
color: #F0142F;
border-radius: 0.03rem;
}
.money-num {
color: #1E2736;
font-weight: bold;
font-size: 0.16rem;
}
.order-item {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
width: 1.16rem;
border-radius: 0.03rem;
}
.order-item:hover {
cursor: default;
transform: scale(1.1);
transition: all 0.3s;
}
.order-box {
margin-left: 0.29rem;
}
.order-box-1 {
margin-right: 0.11rem;
background: #7239EA;
}
.order-box-2 {
margin-right: 0.11rem;
background: #3699FF;
}
.order-box-3 {
background: #3DD598;
}
.order-title {
color: #FFFFFF;
font-size: 0.13rem;
font-weight: 500;
}
.order-nums {
margin-bottom: 0.33rem;
font-size: 0.32rem;
font-weight: bold;
color: #FFFFFF;
}
.order-type-img {
margin-top: 0.36rem;
}
.order-type-img img {
width: 0.68rem;
height: 0.68rem;
}
.product-list-box {
margin-top: 0.4rem;
padding: 0 0.36rem 0rem 0.8rem;
}
.goods-box {
background-color: #fff;
}
.goods-table {
border-spacing: 0;
width: 100%;
}
.product-item {
cursor: pointer;
}
.product-item:hover {
background-color: #F5F7FA;
transition: background-color 0.25s ease;
}
.goods-table thead tr td {
font-size: 0.14rem;
color: #8692B0;
width: 25%;
}
.goods-table tbody tr td {
padding: 0.2rem 0;
font-size: 0.14rem;
color: #171725;
}
.time-box {
width: 1.6rem;
}
.goods-table tbody tr .red-time {
color: #F0142F;
}
.right-box {
box-sizing: border-box;
padding: 0.4rem;
width: 5.9rem;
background-color: #fff;
}
.recommend-box {
width: 3.65rem;
text-align: center;
margin: 0 auto;
margin-top: 0.21rem;
}
.recommend-box h2 {
text-align: center;
color: #1E2736;
font-size: 0.24rem;
}
.recommend-box p {
margin-top: 0.26rem;
text-align: center;
color: #8692B0;
font-size: 0.14rem;
}
.recommend-box img {
width: 3.65rem;
height: 2.56rem;
}
.recommend-people {
margin-top: 0.3rem;
border-top: 1px solid #E6E7EB;
padding-top: 0.3rem;
text-align: left;
}
.recommend-people-num {
display: inline-block;
width: 1rem;
height: 0.08rem;
background: #F99600;
border-radius: 0rem 0.2rem 0.2rem 0rem;
}
.recommend-money-num {
display: inline-block;
width: 1.2rem;
height: 0.08rem;
background: #3DD598;
border-radius: 0rem 0.2rem 0.2rem 0rem;
}
.recommend-number {
margin-left: 0.16rem;
font-weight: bold;
font-size: 0.26rem;
color: #040E34;
}
.recommend-people > div {
display: flex;
align-items: center;
}
.recommend-people > div:nth-of-type(2) {
margin-top: 0.47rem;
}
.WorkOrder-box {
margin-top: 0.4rem;
}
.WorkOrder-title {
display: flex;
align-items: center;
justify-content: space-between;
}
.more {
cursor: pointer;
display: block;
padding: 0 0.03rem;
background: #EEF4FF;
height: 0.24rem;
line-height: 0.24rem;
text-align: center;
border-radius: 0.03rem;
color: #8692B0;
}
.WorkOrder-content {
padding: 0.3rem 0.3rem 0 0.3rem;
border-radius: 0.03rem;
border: 1px solid #E6E7EB;
}
.WorkOrder-item {
display: flex;
margin-bottom: 0.3rem;
}
.WorkOrder-item:hover {
cursor: pointer;
background-color: #f5f7fa;
transition: background-color 0.25s ease;
}
.replay-div {
margin-right: 0.1rem;
font-weight: 500;
font-size: 0.13rem;
padding: 0 0.1rem;
height: 0.26rem;
line-height: 0.26rem;
text-align: center;
background: rgba(54, 155, 255, 0.205);
color: #FFF;
border-radius: 0.03rem;
}
.replay-red {
color: #F0142F;
background: rgba(240, 20, 46, 0.205);
}
.replay-green {
background: rgba(61, 213, 152, 0.205);
color: #3DD598;
}
.replay-box {
width: 80%;
}
.replay-title {
font-size: 0.14rem;
color: #1E2736;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.replay-name {
font-size: 0.13rem;
font-weight: 500;
color: #8692B0;
}
.notice-box {
margin-top: 0.3rem;
}
.notice-item {
display: flex;
cursor: pointer;
justify-content: space-between;
align-items: center;
padding-left: 0.16rem;
}
.notice-item:hover {
background-color: #f5f7fa;
transition: background-color 0.25s ease;
}
.progress-box .el-progress-circle {
width: 1.1rem !important;
}
.notice-item:nth-of-type(1) {
border-left: 0.02rem solid #3DD598;
margin-bottom: 0.4rem;
}
.notice-item:nth-of-type(2) {
border-left: 0.02rem solid #3699FF;
margin-bottom: 0.4rem;
}
.notice-item:nth-of-type(3) {
border-left: 0.02rem solid #F99600;
margin-bottom: 0.3rem;
}
.notice-time {
font-size: 0.2rem;
color: #1E2736;
}
.notice-title {
font-weight: 400;
font-size: 0.14rem;
color: #1E2736;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.notice-type {
font-size: 0.13rem;
font-weight: 500;
color: #8692B0;
}
.notice-item-right {
color: #8692B0;
width: 0.24rem;
height: 0.24rem;
text-align: center;
line-height: 0.24rem;
background: #EEF4FF;
border-radius: 0.03rem;
}
.no-product {
width: 100%;
text-align: center;
margin-top: 1.06rem;
padding-bottom: 1.72rem;
}
.no-product h2 {
font-weight: 400;
color: #171725;
font-size: 0.28rem;
}
.no-product p {
margin: 0.1rem 0 0.2rem 0;
color: #8692B0;
font-size: 0.14rem;
}
.no-product .el-button {
margin: 0 auto;
width: 1.02rem;
height: 0.32rem;
background: #0058FF;
border-radius: 0.03rem;
font-size: 0.14rem;
border: none;
color: rgba(255, 255, 255, 0.9);
}
.no-recommend {
margin: 0 auto;
margin-top: 0.24rem;
color: #FFF;
font-size: 0.14rem;
background: #3699FF;
height: 0.32rem;
line-height: 0.32rem;
width: 1.52rem;
border-radius: 0.03rem;
cursor: pointer;
}
.recommend-text {
margin: 0 auto;
margin-top: 0.24rem;
color: #8692B0;
font-size: 0.14rem;
background: #EEF4FF;
height: 0.32rem;
line-height: 0.32rem;
border-radius: 0.03rem;
}
.info-box .divider-box {
height: 0.6rem;
background-color: #E6E7EB !important;
}
/* 提现弹窗 */
.tx-dialog .el-dialog__body,
.cz-dialog .el-dialog__body {
padding: 0.3rem 0.8rem;
}
.dialog-form {
display: flex;
flex-direction: column;
}
.cz-input {
display: flex;
flex-direction: row;
align-items: center;
}
.cz-input > .btn-ok {
margin-left: 0.1rem;
height: 0.46rem;
background: #0058FF;
border-radius: 3px;
color: rgba(255, 255, 255, 0.9);
display: flex;
align-items: center;
justify-content: center;
}
.pay-html {
display: flex;
justify-content: center;
}
.pay-html > img {
width: 2.5rem;
height: 2.5rem;
}
.ty-select {
width: 100%;
}
.recommend-box-open .recommend-top {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.recommend-box-open .recommend-top .left {
padding-top: 0.26rem;
display: flex;
flex-direction: column;
}
.recommend-box-open .recommend-top .left .row1 {
display: flex;
flex-direction: row;
align-items: center;
}
.recommend-box-open .recommend-top .left .row1 .title-text {
font-size: 18px;
font-weight: bold;
color: #171725;
margin-right: 0.2rem;
margin-bottom: 0;
}
.recommend-box-open .recommend-top .left .row1 .reword {
background: linear-gradient(180deg, #F74C4B 0%, #EF7575 100%);
border-radius: 3px;
color: #FFF;
position: relative;
padding: 1px 6px 1px 20px;
font-size: 13px;
cursor: pointer;
}
.recommend-box-open .recommend-top .left .row1 .reword img {
width: 36px;
height: 35px;
position: absolute;
left: -18px;
top: -4px;
}
.recommend-box-open .recommend-top .left .row2 {
font-size: 16px;
font-weight: bold;
color: #171725;
margin-top: 0.3rem;
margin-bottom: 0.13rem;
}
.recommend-box-open .recommend-top .left .row3,
.recommend-box-open .recommend-top .left .row4 {
font-size: 14px;
color: #8692B0;
}
.recommend-box-open .recommend-top .right {
width: 1.5rem;
height: 1.53rem;
}
.recommend-box-open .url {
width: 5.2rem;
height: 0.46rem;
border: 1px solid #E6E7EB;
border-radius: 3px;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
margin-top: 0.26rem;
}
.recommend-box-open .url .url-text {
width: 100%;
font-size: 15px;
color: #8692B0;
margin-left: 0.16rem;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.recommend-box-open .url .copy-btn {
width: 112px;
height: 100%;
background: #E1F0FF;
border-left: 1px solid #E6E7EB;
border-radius: 0px 3px 3px 0px;
font-size: 16px;
color: #0058FF;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
.recommend-box-open .top-statistic {
display: flex;
flex-direction: row;
justify-content: space-between;
flex-wrap: wrap;
padding-left: 3px;
padding-right: 3px;
margin-top: 0.25rem;
}
.recommend-box-open .top-statistic .top-item {
width: 2.4rem;
min-height: 1.76rem;
background: #FFFFFF;
box-shadow: 0px 1px 4px rgba(21, 34, 50, 0.08);
border-radius: 3px;
display: flex;
flex-direction: column;
justify-content: space-between;
margin-bottom: 0.4rem;
}
.recommend-box-open .top-statistic .top-item .item-top {
margin-top: 0.12rem;
margin-left: 0.21rem;
}
.recommend-box-open .top-statistic .top-item .item-top .top-money {
font-size: 0.32rem;
font-weight: bold;
color: #1E2736;
display: flex;
flex-direction: row;
align-items: center;
}
.recommend-box-open .top-statistic .top-item .item-top .top-money .icon-help {
width: 14px;
height: 14px;
border: 1px solid #0058FF;
border-radius: 50%;
margin-left: 5px;
cursor: help;
font-size: 12px;
display: flex;
align-items: center;
justify-content: center;
color: #0058FF;
}
.recommend-box-open .top-statistic .top-item .item-top .top-text {
font-size: 12px;
color: #8692B0;
}
.recommend-box-open .top-statistic .top-item .top-img {
width: 100%;
align-self: flex-end;
}
.open-dialog {
font-size: 16px;
}
.open-dialog .dialog-footer {
font-size: 0.16rem;
}
.open-dialog .dialog-footer .btn-ok {
width: 1.12rem;
height: 0.46rem;
background: #0058FF;
border-radius: 3px;
color: #FFF;
}
.open-dialog .dialog-footer .btn-no {
width: 1.12rem;
height: 0.46rem;
background: #E7E7E7;
border-radius: 3px;
color: #1E2736;
}
.wx-code {
width: 60px;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
z-index: 100;
position: fixed;
top: 50%;
right: 8px;
transform: translateY(-50%);
cursor: pointer;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.wx-code:hover .wx-img {
width: 40px;
height: 40px;
background: url('../img/home/wx_hover.png') no-repeat;
background-size: 100%;
}
.wx-code .wx-img {
width: 60px;
height: 60px;
background: url('../img/home/wx.png') no-repeat;
background-size: 100%;
}
.wx-box {
text-align: center;
}
.wx-box .img {
width: 200px;
height: 200px;
margin: 0 auto;
}
.wx-box .img img {
width: 100%;
}
@media screen and (max-width: 750px) {
.main-content {
display: block;
padding-bottom: 1.5rem;
}
.replay-div {
flex-shrink: 0;
}
.recharge-btn {
height: 30px;
line-height: 30px;
}
.progress-box .el-progress-circle {
display: flex;
}
.order-box {
width: 100%;
margin-left: 0;
margin-top: 0.2rem;
}
.order-box .order-item {
flex: 1;
}
.info-box .divider-box {
display: none;
}
.info-three {
margin-top: 10px;
width: 100%;
align-items: flex-end;
}
.right-box {
width: auto;
margin-left: 0.8rem;
margin-right: 0.36rem;
margin-top: 0.2rem;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,36 @@
*{
margin: 0;
padding: 0;
}
.el-header, .el-footer {
background-color: #B3C0D1;
color: #333;
text-align: center;
line-height: 60px;
}
.el-aside {
background-color: #1E41C9;
text-align: center;
height: 100vh;
}
.el-main {
background-color: #E9EEF3;
color: #333;
text-align: center;
line-height: 160px !important;
}
body > .el-container {
margin-bottom: 40px;
}
.el-container:nth-child(5) .el-aside,
.el-container:nth-child(6) .el-aside {
line-height: 260px;
}
.el-container:nth-child(7) .el-aside {
line-height: 320px;
}

View File

@@ -0,0 +1,391 @@
[v-cloak] {
display: none;
}
.lang-option {
display: flex;
align-items: center;
column-gap: 5px;
}
.lang-option .lang-img {
width: 30px;
height: 20px;
display: inline-block;
vertical-align: middle;
}
.read-text {
flex: 1;
font-size: 14px;
line-height: 19px;
padding: 0 10px;
color: #606266;
font-weight: 500;
}
#login {
height: 100vh;
width: 100vw;
display: flex;
justify-content: center;
align-items: center;
}
.login-container {
width: 15.7rem;
height: 8.2rem;
display: flex;
justify-content: center;
align-items: center;
position: relative;
}
.container-back {
width: 15.7rem;
height: 6.8rem;
background: var(--color-primary);
border-radius: 20px;
overflow: hidden;
position: relative;
font-family: Source Han Sans CN;
}
.container-back .back-text {
font-size: 0.27rem;
z-index: 10;
color: #ffffff;
margin-top: 1.39rem;
margin-left: 0.65rem;
font-weight: 400;
}
.container-back .text-welcome {
font-size: 0.74rem;
font-family: Bahnschrift;
line-height: 0.74rem;
}
.container-back .text-title {
margin-top: 5px;
}
.container-back .text-level {
font-size: 0.12rem;
margin-top: 0.81rem;
}
.back-line1,
.back-line2,
.back-line3 {
width: 0.6rem;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.3) 0%, rgba(255, 255, 255, 0) 100%);
z-index: 2;
position: absolute;
}
.back-line1 {
height: 5rem;
opacity: 1;
transform: rotate(45deg);
top: -1.2rem;
left: 4.15rem;
}
.back-line2 {
height: 7rem;
transform: rotate(110deg);
top: 0;
left: 5rem;
}
.back-line3 {
height: 5rem;
transform: rotate(45deg);
top: 2.3rem;
left: 1.5rem;
clip-path: polygon(0px 0.3rem, 0.64rem 0px, 100% 100%, 0 100%);
}
.container-before {
width: 7.5rem;
height: 8rem;
background: #ffffff;
box-shadow: 0px 3px 12px rgba(0, 0, 0, 0.1);
position: absolute;
right: 0.9rem;
border: 4px;
z-index: 10;
}
.login {
padding-top: 0.8rem;
padding-left: 1.24rem;
padding-right: 1.05rem;
font-size: 14px;
font-family: PingFang SC;
font-weight: 400;
line-height: 14px;
position: relative;
}
.login .lang-box {
position: absolute;
right: 0.1rem;
top: 0.1rem;
}
.login .qr-code {
position: absolute;
right: 1.05rem;
top: 0.8rem;
cursor: pointer;
width: 0.48rem;
height: 0.48rem;
}
.login .qr-code .login-icon {
fill: var(--color-primary);
width: 100%;
height: 100%;
}
.login .qr-box {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
.login .qr-box .qr-box-img {
width: 200px;
height: 200px;
position: relative;
}
.login .qr-box .qr-box-img img {
cursor: pointer;
width: 100%;
height: 100%;
}
.login .qr-box .qr-box-img .qr-expire-time {
position: absolute;
top: 0;
left: 0;
z-index: 2;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
gap: 8px;
background: rgba(0, 0, 0, 0.5);
color: #ffffff;
font-size: 14px;
font-weight: 500;
line-height: 14px;
cursor: pointer;
}
.login .qr-box .qr-box-img .qr-expire-time .el-icon-refresh-right {
font-size: 30px;
}
.login .qr-box .qr-box-tips {
margin-top: 10px;
font-size: 14px;
color: #666;
}
.login .qr-box-select-account {
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 0.2rem;
width: 100%;
height: 100%;
padding: 0.2rem;
border-radius: 10px;
border: 1px solid #e5e5e5;
}
.login .qr-box-select-account .qr-box-back {
width: 100%;
display: flex;
align-items: center;
justify-content: flex-start;
gap: 5px;
font-size: 16px;
color: var(--color-primary);
cursor: pointer;
}
.login .qr-box-select-account .qr-box-select-account-title {
font-size: 14px;
color: #666;
}
.login-text {
display: flex;
flex-direction: column;
}
.login-text-title {
font-size: 0.32rem;
color: #1e2736;
line-height: 0.32rem;
}
.login-text-regist {
font-weight: Regular;
margin-top: 0.08rem;
color: #1e2736;
}
.login-text-regist a {
color: var(--color-primary);
cursor: pointer;
}
.login-form {
margin-top: 0.68rem;
}
.login-top {
display: flex;
flex-direction: row;
}
.login-email,
.login-phone {
height: 0.34rem;
color: #666b80;
cursor: pointer;
}
.active {
color: var(--color-primary);
border-bottom: 2px solid var(--color-primary);
}
.login-email {
margin-right: 0.4rem;
}
.form-main {
margin-top: 0.3rem;
}
.form-item {
margin-top: 0.3rem;
}
.input-with-select .el-input-group__prepend {
background: #ffffff;
width: 60px;
}
.code-item {
display: flex;
flex-direction: row;
}
.code-btn {
margin-left: 0.1rem;
color: #ffffff;
}
.rember-item {
margin-top: 0.2rem;
display: flex;
align-items: center;
justify-content: space-between;
line-height: 1.5;
}
.rember-item a {
color: var(--color-primary);
cursor: pointer;
}
.login-btn {
width: 100%;
height: 46px;
}
.pass-btn {
width: 100%;
height: 46px;
margin-left: 0 !important;
margin-top: 0.15rem;
}
.read-item {
margin-top: 0.2rem;
}
.read-item a {
color: var(--color-primary);
cursor: pointer;
}
.line-item {
margin-top: 0.4rem;
}
.line-item text {
font-size: 16px;
color: #1e2736;
}
.type-btn {
width: 100%;
height: 46px;
font-size: 0.16rem;
}
.login-type {
display: flex;
align-items: center;
column-gap: 0.15rem;
flex-wrap: wrap;
}
.a-text {
color: var(--color-primary);
cursor: pointer;
margin-right: 5px;
}
.oauth-item {
display: flex;
align-items: center;
padding: 10px;
cursor: pointer;
}
.oauth-item:hover .oauth-img {
filter: brightness(0.8);
}
.oauth-img {
width: 40px;
height: 40px;
}
@media screen and (max-width: 750px) {
.login-container {
height: calc(100vh - 1.2rem);
width: 100vw;
background: #f2f2fe;
padding: 0.6rem 0;
}
.container-back {
display: none;
}
.container-before {
width: 100%;
height: 100%;
margin: 0rem 0.3rem;
position: unset;
z-index: 0;
}
.login {
padding-top: 1.17rem;
padding-left: 0.3rem;
padding-right: 0.3rem;
font-size: 0.26rem;
line-height: 0.3rem;
}
.login .qr-code {
right: 0.3rem;
top: 1.17rem;
cursor: pointer;
}
.login-text-title {
font-size: 0.4rem;
}
.login-text-regist {
margin-top: 0.16rem;
font-size: 0.28rem;
}
.login-form {
margin-top: 1.21rem;
}
.form-main {
margin-top: 0.6rem;
}
.login-email,
.login-phone {
height: 0.34rem;
width: 100%;
text-align: center;
color: #666b80;
cursor: pointer;
padding-bottom: 0.13rem;
}
.el-checkbox__label {
font-size: 0.22rem;
}
.read-item {
line-height: 0.3rem;
}
.login-btn {
font-size: 0.34rem;
height: 0.8rem;
}
.type-btn {
border: none;
color: var(--color-primary);
font-size: 0.34rem;
}
}

View File

@@ -0,0 +1,480 @@
// Variables
@text-color: #1e2736;
@text-secondary: #666b80;
@white: #ffffff;
@shadow-color: rgba(0, 0, 0, 0.1);
[v-cloak] {
display: none;
}
.lang-option {
display: flex;
align-items: center;
column-gap: 5px;
.lang-img {
width: 30px;
height: 20px;
display: inline-block;
vertical-align: middle;
}
}
.read-text {
flex: 1;
font-size: 14px;
line-height: 19px;
padding: 0 10px;
color: #606266;
font-weight: 500;
}
#login {
height: 100vh;
width: 100vw;
display: flex;
justify-content: center;
align-items: center;
}
.login-container {
width: 15.7rem;
height: 8.2rem;
display: flex;
justify-content: center;
align-items: center;
position: relative;
}
// Background panel
.container-back {
width: 15.7rem;
height: 6.8rem;
background: var(--color-primary);
border-radius: 20px;
overflow: hidden;
position: relative;
font-family: Source Han Sans CN;
.back-text {
font-size: .27rem;
z-index: 10;
color: @white;
margin-top: 1.39rem;
margin-left: .65rem;
font-weight: 400;
}
.text-welcome {
font-size: .74rem;
font-family: Bahnschrift;
line-height: .74rem;
}
.text-title {
margin-top: 5px;
}
.text-level {
font-size: .12rem;
margin-top: .81rem;
}
}
// Background lines
.back-line1,
.back-line2,
.back-line3 {
width: .6rem;
background: linear-gradient(180deg,
rgba(255, 255, 255, 0.3) 0%,
rgba(255, 255, 255, 0) 100%);
z-index: 2;
position: absolute;
}
.back-line1 {
height: 5rem;
opacity: 1;
transform: rotate(45deg);
top: -1.2rem;
left: 4.15rem;
}
.back-line2 {
height: 7rem;
transform: rotate(110deg);
top: 0;
left: 5rem;
}
.back-line3 {
height: 5rem;
transform: rotate(45deg);
top: 2.3rem;
left: 1.5rem;
clip-path: polygon(0px .3rem, .64rem 0px, 100% 100%, 0 100%);
}
// Login form container
.container-before {
width: 7.5rem;
height: 8rem;
background: @white;
box-shadow: 0px 3px 12px @shadow-color;
position: absolute;
right: .9rem;
border: 4px;
z-index: 10;
}
.login {
padding-top: .8rem;
padding-left: 1.24rem;
padding-right: 1.05rem;
font-size: 14px;
font-family: PingFang SC;
font-weight: 400;
line-height: 14px;
position: relative;
.lang-box {
position: absolute;
right: 0.1rem;
top: 0.1rem;
}
.qr-code {
position: absolute;
right: 1.05rem;
top: 0.8rem;
cursor: pointer;
width: 0.48rem;
height: 0.48rem;
.login-icon {
fill: var(--color-primary);
width: 100%;
height: 100%;
}
}
.qr-box {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
.qr-box-img {
width: 200px;
height: 200px;
position: relative;
img {
cursor: pointer;
width: 100%;
height: 100%;
}
.qr-expire-time {
position: absolute;
top: 0;
left: 0;
z-index: 2;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
gap: 8px;
background: rgba(0, 0, 0, 0.5);
color: @white;
font-size: 14px;
font-weight: 500;
line-height: 14px;
cursor: pointer;
.el-icon-refresh-right {
font-size: 30px;
}
}
}
.qr-box-tips {
margin-top: 10px;
font-size: 14px;
color: #666;
}
}
.qr-box-select-account {
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: .2rem;
width: 100%;
height: 100%;
padding: .2rem;
border-radius: 10px;
border: 1px solid #e5e5e5;
.qr-box-back {
width: 100%;
display: flex;
align-items: center;
justify-content: flex-start;
gap: 5px;
font-size: 16px;
color: var(--color-primary);
cursor: pointer;
}
.qr-box-select-account-title {
font-size: 14px;
color: #666;
}
}
}
.login-text {
display: flex;
flex-direction: column;
&-title {
font-size: .32rem;
color: @text-color;
line-height: .32rem;
}
&-regist {
font-weight: Regular;
margin-top: .08rem;
color: @text-color;
a {
color: var(--color-primary);
cursor: pointer;
}
}
}
.login-form {
margin-top: .68rem;
}
.login-top {
display: flex;
flex-direction: row;
}
.login-email,
.login-phone {
height: .34rem;
color: @text-secondary;
cursor: pointer;
}
.active {
color: var(--color-primary);
border-bottom: 2px solid var(--color-primary);
}
.login-email {
margin-right: .4rem;
}
.form-main {
margin-top: .3rem;
}
.form-item {
margin-top: .3rem;
}
.input-with-select {
.el-input-group__prepend {
background: @white;
width: 60px;
}
}
.code-item {
display: flex;
flex-direction: row;
}
.code-btn {
margin-left: .1rem;
color: @white;
}
.rember-item {
margin-top: .2rem;
display: flex;
align-items: center;
justify-content: space-between;
line-height: 1.5;
a {
color: var(--color-primary);
cursor: pointer;
}
}
.login-btn {
width: 100%;
height: 46px;
}
.pass-btn {
width: 100%;
height: 46px;
margin-left: 0 !important;
margin-top: .15rem;
}
.read-item {
margin-top: .2rem;
a {
color: var(--color-primary);
cursor: pointer;
}
}
.line-item {
margin-top: .4rem;
text {
font-size: 16px;
color: @text-color;
}
}
.type-btn {
width: 100%;
height: 46px;
font-size: .16rem;
}
.login-type {
display: flex;
align-items: center;
column-gap: 0.15rem;
flex-wrap: wrap;
}
.a-text {
color: var(--color-primary);
cursor: pointer;
margin-right: 5px;
}
.oauth-item {
display: flex;
align-items: center;
padding: 10px;
cursor: pointer;
&:hover .oauth-img {
filter: brightness(0.8);
}
}
.oauth-img {
width: 40px;
height: 40px;
}
// Media queries
@media screen and (max-width: 750px) {
.login-container {
height: calc(100vh - 1.2rem);
width: 100vw;
background: #f2f2fe;
padding: .6rem 0;
}
.container-back {
display: none;
}
.container-before {
width: 100%;
height: 100%;
margin: 0rem .3rem;
position: unset;
z-index: 0;
}
.login {
padding-top: 1.17rem;
padding-left: .3rem;
padding-right: .3rem;
font-size: .26rem;
line-height: .3rem;
.qr-code {
right: .3rem;
top: 1.17rem;
cursor: pointer;
}
}
.login-text-title {
font-size: .4rem;
}
.login-text-regist {
margin-top: .16rem;
font-size: .28rem;
}
.login-form {
margin-top: 1.21rem;
}
.form-main {
margin-top: .6rem;
}
.login-email,
.login-phone {
height: .34rem;
width: 100%;
text-align: center;
color: @text-secondary;
cursor: pointer;
padding-bottom: .13rem;
}
.el-checkbox__label {
font-size: .22rem;
}
.read-item {
line-height: .3rem;
}
.login-btn {
font-size: .34rem;
height: .8rem;
}
.type-btn {
border: none;
color: var(--color-primary);
font-size: .34rem;
}
}

View File

@@ -0,0 +1,114 @@
.login-dialog {
border-radius: 0.3rem;
margin-top: 10vh !important;
}
.login-dialog .el-dialog__body {
padding: 0.95rem 1.36rem;
display: flex;
flex-direction: row;
position: relative;
}
.login-dialog .el-dialog__body .login-left {
width: 5.21rem;
position: relative;
}
.login-dialog .el-dialog__body .login-left::after {
content: '';
width: 0px;
height: 4.6rem;
border: 1px solid #E6E7EB;
opacity: 0.4;
position: absolute;
top: 0.91rem;
right: -1.65rem;
}
.login-dialog .el-dialog__body .login-left .login-text .login-text-title {
font-size: 0.32rem;
color: #1E2736;
}
.login-dialog .el-dialog__body .login-left .login-text .login-text-regist {
color: #1E2736;
}
.login-dialog .el-dialog__body .login-left .login-text .login-text-regist a {
color: #0058FF;
cursor: pointer;
}
.login-dialog .el-dialog__body .login-left .login-form {
margin-top: 0.68rem;
}
.login-dialog .el-dialog__body .login-left .login-form .login-top {
display: flex;
flex-direction: row;
}
.login-dialog .el-dialog__body .login-left .login-form .login-top .active {
color: #0058FF;
border-bottom: 2px solid #0058FF;
}
.login-dialog .el-dialog__body .login-left .login-form .login-top .login-email {
margin-right: 0.4rem;
}
.login-dialog .el-dialog__body .login-left .login-form .login-top .login-email,
.login-dialog .el-dialog__body .login-left .login-form .login-top .login-phone {
height: 0.34rem;
color: #666B80;
cursor: pointer;
}
.login-dialog .el-dialog__body .login-left .login-form .form-main {
margin-top: 0.3rem;
}
.login-dialog .el-dialog__body .login-left .login-form .form-main .form-item {
margin-top: 0.3rem;
}
.login-dialog .el-dialog__body .login-left .login-form .form-main .form-item .input-with-select .el-input-group__prepend {
background: #FFFFFF;
width: 64px;
}
.login-dialog .el-dialog__body .login-left .login-form .form-main .form-item .login-btn {
width: 100%;
height: 46px;
background: #0058FF;
}
.login-dialog .el-dialog__body .login-left .login-form .form-main .form-item .type-btn {
width: 100%;
height: 46px;
font-size: 0.16rem;
}
.login-dialog .el-dialog__body .login-left .login-form .form-main .code-item {
display: flex;
flex-direction: row;
}
.login-dialog .el-dialog__body .login-left .login-form .form-main .code-item .code-btn {
margin-left: 0.1rem;
background: #0058FF;
color: #FFFFFF;
}
.login-dialog .el-dialog__body .login-left .login-form .form-main .rember-item {
margin-top: 0.2rem;
display: flex;
justify-content: space-between;
}
.login-dialog .el-dialog__body .login-left .login-form .form-main .rember-item a {
color: #0058FF;
cursor: pointer;
}
.login-dialog .el-dialog__body .login-left .login-form .form-main .read-item {
margin-top: 0.2rem;
}
.login-dialog .el-dialog__body .login-left .login-form .form-main .read-item a {
color: #0058FF;
cursor: pointer;
}
.login-dialog .el-dialog__body .login-left .login-form .form-main .line-item {
margin-top: 0.4rem;
}
.login-dialog .el-dialog__body .login-left .login-form .form-main .line-item text {
font-size: 16px;
color: #1E2736;
}
.login-dialog .el-dialog__body .login-right .login-back-img {
width: 5.17rem;
height: 3.975rem;
position: absolute;
top: 2.29rem;
right: 1.36rem;
}

View File

@@ -0,0 +1,151 @@
.login-dialog {
border-radius: .3rem;
margin-top: 10vh !important;
.el-dialog__body {
padding: .95rem 1.36rem;
display: flex;
flex-direction: row;
position: relative;
.login-left {
width: 5.21rem;
position: relative;
&::after {
content: '';
width: 0px;
height: 4.6rem;
border: 1px solid #E6E7EB;
opacity: 0.4;
position: absolute;
top: .91rem;
right: -1.65rem;
}
.login-text {
.login-text-title {
font-size: .32rem;
color: #1E2736;
}
.login-text-regist {
color: #1E2736;
a {
color: #0058FF;
cursor: pointer;
}
}
}
.login-form {
margin-top: .68rem;
.login-top {
display: flex;
flex-direction: row;
.active {
color: #0058FF;
border-bottom: 2px solid #0058FF;
}
.login-email {
margin-right: .4rem;
}
.login-email,
.login-phone {
height: .34rem;
color: #666B80;
cursor: pointer;
}
}
.form-main {
margin-top: .3rem;
.form-item {
margin-top: .3rem;
.input-with-select {
.el-input-group__prepend {
background: #FFFFFF;
width: 64px;
}
}
.login-btn {
width: 100%;
height: 46px;
background: #0058FF;
}
.type-btn {
width: 100%;
height: 46px;
font-size: .16rem;
}
}
.code-item {
display: flex;
flex-direction: row;
.code-btn {
margin-left: .1rem;
background: #0058FF;
color: #FFFFFF;
}
}
.rember-item {
margin-top: .2rem;
display: flex;
justify-content: space-between;
a {
color: #0058FF;
cursor: pointer;
}
}
.read-item {
margin-top: .2rem;
a {
color: #0058FF;
cursor: pointer;
}
}
.line-item {
margin-top: .4rem;
text {
font-size: 16px;
color: #1E2736;
}
}
}
}
}
.login-right {
.login-back-img {
width: 5.17rem;
height: 3.975rem;
position: absolute;
top: 2.29rem;
right: 1.36rem;
}
}
}
}

View File

@@ -0,0 +1,32 @@
.content-box {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.content-box .img-box {
position: relative;
width: 2.82rem;
height: 4.55rem;
background: url('../img/common/network_erro.png') center no-repeat;
background-size: 100% 100%;
}
.content-box .img-box .tips-box {
position: absolute;
left: 0.96rem;
bottom: 0.9rem;
text-align: center;
}
.content-box .img-box .tips-box .tips-text {
margin-top: 0.12rem;
color: #666B80;
font-size: 0.16rem;
}
.content-box .img-box .tips-box .tran-again {
margin-top: 0.06rem;
cursor: pointer;
color: var(--color-primary);
font-size: 0.16rem;
}

View File

@@ -0,0 +1,36 @@
.content-box {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.img-box {
position: relative;
width: 2.82rem;
height: 4.55rem;
background: url('../img/common/network_erro.png') center no-repeat;
background-size: 100% 100%;
.tips-box {
position: absolute;
left: 0.96rem;
bottom: 0.9rem;
text-align: center;
.tips-text {
margin-top: 0.12rem;
color: #666B80;
font-size: 0.16rem;
}
.tran-again {
margin-top: 0.06rem;
cursor: pointer;
color: var(--color-primary);
font-size: 0.16rem;
}
}
}
}

View File

@@ -0,0 +1,344 @@
.news .top-back {
width: calc(100% - 190px);
background: #F6FAFF;
height: calc(40px + 2.56rem);
position: absolute;
z-index: -1;
}
.news .main-card {
position: relative;
}
.news .main-card .main-card-title {
font-size: 0.28rem;
color: #171725;
margin-bottom: 0.24rem;
}
.news .main-card .search-input {
margin-bottom: 0.6rem;
height: 0.46rem;
width: 3.2rem;
}
.news .main-card .search-input .el-input__inner {
height: 0.46rem;
}
.news .main-card .search-input .el-input__suffix {
display: flex;
align-items: center;
right: 0.14rem;
}
.news .main-card .search-input .input-search {
cursor: pointer;
}
.news .main-card .back-img {
width: 3.7rem;
height: 2.35rem;
position: absolute;
top: -0.3rem;
right: 1.84rem;
z-index: -1;
}
.news .top-search {
display: flex;
justify-content: space-between;
align-items: flex-start;
padding: 0 0.4rem 0 0;
}
.news .top-search .input-search {
line-height: 0.4rem;
}
.news .tit {
font-size: 0.2rem;
color: #171725;
line-height: 1;
}
.news .com-search {
height: 0.4rem;
}
.news .com-search .el-input__inner {
height: 0.4rem;
line-height: 0.4rem;
}
.news .box {
margin-top: 0.4rem;
position: relative;
min-height: 70vh;
}
.news .com-l-box {
margin-right: 3.57rem;
}
.news .com-r-box {
width: 3.58rem !important;
padding: 0.3rem;
box-sizing: border-box;
box-shadow: 0px 3px 12px rgba(0, 0, 0, 0.1);
margin-right: 3px;
float: right;
}
.news .com-r-box .tit {
margin-bottom: 0.3rem;
}
.news .no-data {
text-align: center;
line-height: 0.6rem;
height: 0.6rem;
color: #999;
}
.news .myPage {
margin-top: 0.2rem;
}
.news .el-icon-download {
color: var(--color-primary);
font-size: 0.16rem;
cursor: pointer;
}
.news .tag {
line-height: 0.2rem;
height: 0.2rem;
padding: 0 0.05rem;
border-radius: 0.03rem;
font-size: 0.13rem;
background: #E6E7EB;
color: #4E5259;
}
.news .tag.suc {
background: #C9F7F5;
color: var(--color-success);
}
.news .tag.war {
background: #FFF4DE;
color: var(--color-warning);
}
.news .tag.error {
background: #FFE2E5;
color: var(--color-danger);
}
.news .tag.def {
background: #E1F0FF;
color: var(--color-info);
}
.news .total {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
line-height: 0.2rem;
font-size: 0.16rem;
color: #171725;
padding-left: 0.2rem;
margin-bottom: 0.2rem;
box-sizing: border-box;
cursor: pointer;
}
.news .total.active {
color: var(--color-primary);
}
.news .file_folder {
padding-left: 0.1rem;
}
.news .file_folder .item {
position: relative;
line-height: 0.18rem;
padding-left: 0.15rem;
margin-bottom: 0.2rem;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
}
.news .file_folder .item::before {
content: '';
width: 0.03rem;
height: 0.18rem;
background: #E6E7EB;
position: absolute;
left: 0;
top: 0;
}
.news .file_folder .item.active {
color: var(--color-primary);
}
.news .file_folder .item.active::before {
background: var(--color-primary);
}
.news .news-list {
padding: 0 0.4rem 0 0;
}
.news .news-list .item {
margin-top: 0.32rem;
cursor: pointer;
display: flex;
flex-direction: row;
}
.news .news-list .item .item-left {
margin-right: 0.2rem;
}
.news .news-list .item .item-left .item-img {
width: 1.4rem;
height: 0.84rem;
}
.news .news-list .item .item-right {
width: 100%;
height: 0.84rem;
border-bottom: 1px solid #E6E7EB;
}
.news .news-list .title {
margin-bottom: 0.1rem;
font-size: 0.16rem;
}
.news .news-list .info {
font-size: 0.13rem;
color: var(--color-text-tips);
}
.news .mobile {
display: none;
}
/* news_detail */
.news_detail .main-card-title {
padding-bottom: 0.2rem;
border-bottom: 1px solid #E6E7EB;
}
.news_detail .back {
cursor: pointer;
width: 0.24rem;
}
.news_detail .news_annex {
margin-top: 0.3rem;
line-height: 0.24rem;
}
.news_detail .news_annex a {
text-decoration: none;
color: #171725;
}
.news_detail .news_annex a:hover {
text-decoration: underline;
color: var(--color-primary);
}
.news_detail .new-box {
width: 10.33rem;
border: 1px solid #E6E7EB;
margin: 0.4rem auto;
padding: 0.3rem 0.5rem;
box-sizing: border-box;
}
.news_detail .new-box .tit {
line-height: 1.2;
font-size: 0.28rem;
color: #171725;
margin-bottom: 0.14rem;
}
.news_detail .new-box .time {
font-size: 0.14rem;
color: var(--color-text-tips);
margin-bottom: 0.4rem;
}
.news_detail .new-box img {
max-width: 100%;
width: auto !important;
height: auto !important;
margin: 0 auto;
}
.news_detail .new-box .content {
word-break: break-all;
overflow-x: auto;
}
.news_detail .page {
overflow: hidden;
margin-top: 0.3rem;
}
.news_detail .page .link {
width: 50%;
height: 0.24rem;
float: left;
}
.news_detail .page .link .txt,
.news_detail .page .link .icon {
color: var(--color-text-tips);
}
.news_detail .page .link a {
display: block;
font-size: 0.14rem;
color: #171725;
text-decoration: none;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.news_detail .page .link:last-child {
text-align: right;
}
@media screen and (max-width: 1100px) {
.news .com-search {
height: 0.5rem;
}
.news .com-search .el-input__inner {
height: 0.5rem;
line-height: 0.5rem;
}
.news .top-search .input-search {
line-height: 0.5rem;
}
.news .com-l-box {
margin-right: 3rem;
}
.news .com-r-box {
width: 3rem !important;
}
.news .box::after {
right: 3rem;
}
.news_detail .new-box {
width: 100%;
}
}
@media screen and (max-width: 750px) {
.news .com-l-box {
width: 100%;
margin-top: 10px;
margin-right: 0;
}
.news .pc {
display: flex;
flex-wrap: wrap;
}
.news .tit {
font-size: 0.3rem;
}
.news .main-card-title {
font-size: 0.48rem;
}
.news .com-r-box {
font-size: 0.16rem;
width: 100% !important;
}
.news_detail .back {
width: 0.42rem;
}
.news_detail .new-box {
border: none;
padding: 0;
}
.news_detail .new-box .tit {
font-size: 0.46rem;
font-weight: bold;
margin-bottom: 0.3rem;
}
.news_detail .new-box .time {
font-size: 0.24rem;
margin-bottom: 0.6rem;
}
.news_detail .new-box .content {
font-size: 0.28rem;
line-height: 1.5;
}
.news_detail .new-box .news_annex {
line-height: 1.5;
font-size: 0.24rem;
}
.news_detail .page .link {
height: 0.4rem;
line-height: 0.4rem;
}
.news_detail .page .link a {
font-size: 0.24rem;
}
}

View File

@@ -0,0 +1,466 @@
@text-color: #171725;
.news {
.top-back {
width: calc(100% - 190px);
background: #F6FAFF;
height: calc(40px + 2.56rem);
position: absolute;
z-index: -1;
}
.main-card {
position: relative;
.main-card-title {
font-size: .28rem;
color: @text-color;
margin-bottom: .24rem;
}
.search-input {
margin-bottom: .6rem;
height: .46rem;
width: 3.2rem;
.el-input__inner {
height: .46rem;
}
.el-input__suffix {
display: flex;
align-items: center;
right: .14rem;
}
.input-search {
cursor: pointer;
}
}
.back-img {
width: 3.7rem;
height: 2.35rem;
position: absolute;
top: -.3rem;
right: 1.84rem;
z-index: -1;
}
}
.top-search {
display: flex;
justify-content: space-between;
align-items: flex-start;
padding: 0 .4rem 0 0;
.input-search {
line-height: .4rem;
}
}
.tit {
font-size: .2rem;
color: @text-color;
line-height: 1;
}
.com-search {
height: .4rem;
.el-input__inner {
height: .4rem;
line-height: .4rem;
}
}
.box {
// width: 100%;
margin-top: .4rem;
// border: 1px solid #E6E7EB;
position: relative;
min-height: 70vh;
// &::after {
// content: '';
// width: 1px;
// height: 100%;
// background: #E6E7EB;
// position: absolute;
// top: 0;
// right: 3.57rem;
// }
}
.com-l-box {
margin-right: 3.57rem;
}
.com-r-box {
width: 3.58rem !important;
padding: .3rem;
box-sizing: border-box;
box-shadow: 0px 3px 12px rgba(0, 0, 0, 0.1);
margin-right: 3px;
float: right;
.tit {
margin-bottom: .3rem;
}
}
.no-data {
text-align: center;
line-height: .6rem;
height: .6rem;
color: #999;
}
.myPage {
margin-top: 0.2rem;
}
.el-icon-download {
color: var(--color-primary);
font-size: .16rem;
cursor: pointer;
}
.tag {
line-height: .2rem;
height: .2rem;
padding: 0 .05rem;
border-radius: .03rem;
font-size: .13rem;
background: #E6E7EB;
color: #4E5259;
&.suc {
background: #C9F7F5;
color: var(--color-success);
}
&.war {
background: #FFF4DE;
color: var(--color-warning);
}
&.error {
background: #FFE2E5;
color: var(--color-danger);
}
&.def {
background: #E1F0FF;
color: var(--color-info);
}
}
.total {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
line-height: .2rem;
font-size: .16rem;
color: @text-color;
padding-left: .2rem;
margin-bottom: .2rem;
box-sizing: border-box;
cursor: pointer;
&.active {
color: var(--color-primary);
}
}
.file_folder {
padding-left: .1rem;
.item {
position: relative;
line-height: .18rem;
padding-left: .15rem;
margin-bottom: .2rem;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
&::before {
content: '';
width: .03rem;
height: .18rem;
background: #E6E7EB;
position: absolute;
left: 0;
top: 0;
}
&.active {
color: var(--color-primary);
&::before {
background: var(--color-primary);
}
}
}
}
.news-list {
padding: 0 .4rem 0 0;
.item {
// line-height: 1;
// color: #171725;
// border-bottom: 1px solid #E6E7EB;
// padding: .2rem 0;
margin-top: .32rem;
cursor: pointer;
display: flex;
flex-direction: row;
.item-left {
margin-right: .2rem;
.item-img {
width: 1.40rem;
height: .84rem;
}
}
.item-right {
width: 100%;
height: .84rem;
border-bottom: 1px solid #E6E7EB;
}
}
.title {
margin-bottom: .1rem;
font-size: .16rem;
}
.info {
font-size: .13rem;
color: var(--color-text-tips);
}
}
.mobile {
display: none;
}
}
/* news_detail */
.news_detail {
.main-card-title {
padding-bottom: .2rem;
border-bottom: 1px solid #E6E7EB;
}
.back {
cursor: pointer;
width: .24rem;
}
.news_annex {
margin-top: .3rem;
line-height: .24rem;
a {
text-decoration: none;
color: @text-color;
&:hover {
text-decoration: underline;
color: var(--color-primary);
}
}
}
.new-box {
width: 10.33rem;
border: 1px solid #E6E7EB;
margin: .4rem auto;
padding: .3rem .5rem;
box-sizing: border-box;
.tit {
line-height: 1.2;
font-size: .28rem;
color: @text-color;
margin-bottom: .14rem;
}
.time {
font-size: .14rem;
color: var(--color-text-tips);
margin-bottom: .4rem;
}
img {
max-width: 100%;
width: auto !important;
height: auto !important;
margin: 0 auto;
}
.content {
word-break: break-all;
overflow-x: auto;
}
}
.page {
overflow: hidden;
margin-top: .3rem;
.link {
width: 50%;
height: .24rem;
float: left;
.txt,
.icon {
color: var(--color-text-tips);
}
a {
display: block;
font-size: .14rem;
color: @text-color;
text-decoration: none;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
&:last-child {
text-align: right;
}
}
}
}
@media screen and (max-width: 1100px) {
.news {
.com-search {
height: .5rem;
.el-input__inner {
height: .5rem;
line-height: .5rem;
}
}
.top-search .input-search {
line-height: .5rem;
}
.com-l-box {
margin-right: 3rem;
}
.com-r-box {
width: 3rem !important;
}
.box {
&::after {
right: 3rem;
}
}
}
.news_detail {
.new-box {
width: 100%;
}
}
}
@media screen and (max-width: 750px) {
.news {
.com-l-box {
width: 100%;
margin-top: 10px;
margin-right: 0;
}
.pc {
// display: none;
display: flex;
flex-wrap: wrap;
}
.tit {
font-size: 0.3rem;
}
.mobile {
// display: block;
}
.main-card-title {
font-size: .48rem;
}
.com-r-box {
font-size: 0.16rem;
width: 100% !important;
}
}
.news_detail {
.back {
width: .42rem;
}
.new-box {
border: none;
padding: 0;
.tit {
font-size: .46rem;
font-weight: bold;
margin-bottom: .3rem;
}
.time {
font-size: .24rem;
margin-bottom: .6rem;
}
.content {
font-size: .28rem;
line-height: 1.5;
}
.news_annex {
line-height: 1.5;
font-size: .24rem;
}
}
.page .link {
height: .4rem;
line-height: .4rem;
a {
font-size: .24rem;
}
}
}
}

View File

@@ -0,0 +1,38 @@
.content-box {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.img-box {
position: relative;
width: 2.82rem;
height: 4.55rem;
background: url('../img/common/network_erro.png') center no-repeat;
background-size: 100% 100%;
}
.tips-box {
position: absolute;
left: 0.96rem;
bottom: 0.9rem;
text-align: center;
}
.tips-text {
margin-top: 0.12rem;
color: #666B80;
font-size: 0.16rem;
}
.tran-again {
margin-top: 0.06rem;
cursor: pointer;
color: #0058FF;
font-size: 0.16rem;
}

View File

@@ -0,0 +1,24 @@
.el-main {
padding-left: 1.02rem;
}
.box {
display: flex;
flex-direction: column;
align-items: center;
}
.box img {
margin-bottom: 0.2rem;
width: 2.4rem;
margin-top: 3rem;
}
.box p {
font-size: 0.18rem;
color: #848585;
display: flex;
justify-content: center;
align-items: center;
margin: 0.1rem 0;
}
.box p .el-button {
font-size: 0.18rem;
}

View File

@@ -0,0 +1,28 @@
.el-main {
padding-left: 1.02rem;
}
.box {
display: flex;
flex-direction: column;
align-items: center;
img {
margin-bottom: 0.2rem;
width: 2.4rem;
margin-top: 3rem;
}
p {
font-size: 0.18rem;
color: rgb(132, 133, 133);
display: flex;
justify-content: center;
align-items: center;
margin: 0.1rem 0;
.el-button {
font-size: 0.18rem;
}
}
}

View File

@@ -0,0 +1,203 @@
.order-detail {
font-size: 0.14rem;
}
.page-top {
padding-bottom: 0.2rem;
display: flex;
align-items: center;
border-bottom: 1px solid #E6E7EB;
margin-bottom: 0.4rem;
}
.page-top .back-btn {
cursor: pointer;
width: 0.24rem;
height: 0.26rem;
}
.page-top .back-btn img {
width: 100%;
height: 100%;
}
.page-top .top-title {
margin-left: 0.25rem;
font-size: 0.28rem;
color: #1E2736;
}
.order-info {
display: flex;
align-items: center;
justify-content: space-between;
padding-right: 0.85rem;
}
.order-info .info-left .order-user {
font-size: 0.18rem;
color: #1E2736;
}
.order-info .info-right {
display: flex;
flex-direction: column;
align-items: center;
}
.order-info .info-right .order-status {
display: flex;
align-items: center;
font-size: 0.18rem;
}
.order-info .info-right .go-pay {
text-align: center;
}
.order-info .info-right .go-pay .pay-text {
margin-top: 0.15rem;
cursor: pointer;
font-size: 0.14rem;
color: var(--color-primary);
}
.order-info .info-right .go-pay .pay-text:hover {
text-decoration: underline;
}
.order-info .info-right .go-pay .pay-info {
margin-top: 0.1rem;
font-weight: bold;
font-size: 0.14rem;
color: #1E2736;
}
.order-info .pay-status {
border-radius: 0.03rem;
padding: 0.05rem 0.14rem;
font-size: 0.16rem;
color: #FFFFFF;
}
.order-info .Unpaid-text {
background: var(--color-danger);
}
.order-info .Wait {
background: var(--color-warning);
}
.order-info .Unpaid {
background: var(--color-danger);
}
.order-info .Paid-text {
background: var(--color-primary);
}
.order-info .Refunded-text {
background: var(--color-danger);
}
.order-info .order-num {
margin-top: 0.13rem;
color: #1E2736;
font-size: 0.14rem;
}
.order-info .order-num .num-text {
color: #666B80;
}
.order-info .order-data {
margin-top: 0.04rem;
}
.self-field {
display: flex;
flex-direction: column;
row-gap: 0.04rem;
}
.self-field .self-num {
display: flex;
color: #1E2736;
font-size: 0.14rem;
}
.self-field .self-num .field-name {
flex-shrink: 0;
}
.self-field .self-num .self-text {
white-space: pre;
color: #666B80;
}
.order-table {
margin-top: 0.33rem;
border-radius: 0.03rem;
border: 0.01rem solid #E6E7EB;
}
.order-table .table-title {
font-size: 0.14rem;
background: #FAFBFF;
height: 0.46rem;
line-height: 0.46rem;
padding-left: 0.2rem;
border-bottom: 0.01rem solid #E6E7EB;
}
.order-table .table-item {
margin: 0 0.2rem;
min-height: 0.5rem;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 0.14rem;
}
.order-table .table-item .des,
.order-table .table-item .money {
color: #1E2736;
}
.order-table .table-item .des-text {
margin-right: 0.5rem;
color: #666B80;
}
.order-table .table-item .money-text {
color: #666B80;
}
.order-table .order-item {
border-bottom: 0.01rem dashed #E6E7EB;
}
.order-table .title-item {
border-bottom: 0.01rem solid #E6E7EB;
}
.order-table .total-money {
color: #1E2736;
margin-right: 0.3rem;
}
.order-transaction {
margin-top: 0.4rem;
}
.order-transaction .table-top,
.order-transaction .table-bottom {
font-size: 0.14rem;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 0.01rem solid #E6E7EB;
}
.order-transaction .table-top {
color: #1E2736;
padding: 0.13rem 0.2rem 0.14rem;
}
.order-transaction .table-bottom {
padding: 0.13rem 0.2rem;
color: #666B80;
}
.order-transaction .w-200 {
width: 2rem;
}
.order-transaction .flex-1 {
flex: 1;
text-align: center;
}
.order-transaction .text-r {
text-align: right;
}
.order-transaction .no-list {
height: 60px;
line-height: 60px;
border-bottom: 0.01rem solid #E6E7EB;
text-align: center;
color: #909399;
font-size: 14px;
}
.down-pag {
margin-top: 0.8rem;
display: flex;
align-items: center;
justify-content: center;
}
.down-pag .el-button {
height: 0.32rem;
border-radius: 0.03rem;
border: 0.01rem solid var(--color-primary);
font-size: 0.14rem;
color: var(--color-primary);
}

Some files were not shown because too many files have changed in this diff Show More