提交 9ce4221f 作者: Hao

拉取最新代码

父级 cc9b12b0
NODE_ENV=development
VITE_USER_APP_API_URL=192.168.31.135
\ No newline at end of file
NODE_ENV=production
VITE_USER_APP_API_URL=192.168.31.101
\ No newline at end of file
......@@ -4,8 +4,8 @@
"type": "module",
"license":"MIT",
"scripts": {
"build": "vue-tsc --noEmit && vite build",
"serve": "vite",
"build": "vue-tsc --noEmit && vite build --mode production",
"serve": "vite --mode development",
"preview": "vite preview"
},
"dependencies": {
......
No preview for this file type
// axios.js
import axios from "axios";
let VUE_APP_API_URL = import.meta.env.VITE_USER_APP_API_URL;
const instance = axios.create({
baseURL: "http://192.168.31.123:8080", // 设置基础 URL
baseURL: `http://${VUE_APP_API_URL}:8080`, // 设置基础 URL
// baseURL:'/api',
timeout: 1000, // 设置请求超时时间
});
console.log(import.meta.env, "import.meta.env");
instance.interceptors.request.use(
(config: any) => {
// 在发送请求之前做些什么,例如添加 token
const token = localStorage.getItem("token");
if (token) {
config.headers['X-Access-Token'] = `Bearer ${token}`;
config.headers["X-Access-Token"] = `Bearer ${token}`;
}
return config;
},
......@@ -27,6 +28,7 @@ instance.interceptors.response.use(
},
(error: any) => {
// 对响应错误做点什么
console.log(error);
return Promise.reject(error);
}
);
......
......@@ -44,7 +44,7 @@ const checkMesssages = (query: any) => {
const getUploadConfigInfo = (query: any) => {
return http({
url: "/getUploadConfigInfo",
url: "/upload/getUploadConfigInfo",
method: "get",
data: query,
});
......@@ -53,7 +53,7 @@ const getUploadConfigInfo = (query: any) => {
const upload = (query: any) => {
return http({
url: "/sys/common/upload",
method: "get",
method: "post",
data: query,
});
};
......
......@@ -37,7 +37,7 @@
ref="elAutocomplete"
placeholder="输入信息"
contenteditable="true"
style="outline: none; height: 100%;"
style="outline: none; "
@paste.prevent="handlePaste"
@focus="removeDefaultContent"
@input="handleSelect"
......@@ -59,7 +59,6 @@
/>
</div>
</template>
<script lang="ts" setup>
import emotion from './IndexComponent.vue'
import { ElLoading } from 'element-plus'
......@@ -97,6 +96,7 @@ const fileChange = () => {
const handleSelect = (value: any) => {
inputVal.value = value.target.innerHTML
console.log(inputVal.value,'打印一下')
}
const emit = defineEmits(['updateState'])
......@@ -223,7 +223,7 @@ defineExpose({
</script>
<style lang="scss" scoped>
.auto-prompt {
padding: 20px;
padding: 12px 28px;
}
.textarea {
&:after {
......@@ -236,8 +236,8 @@ defineExpose({
}
}
.icon {
width: 24px;
height: 24px;
width: 20px;
height: 20px;
margin-right: 32px;
}
.chat-bar {
......@@ -249,7 +249,7 @@ defineExpose({
.el-autocomplete {
width: 100%;
max-width: 100%;
max-height: 150px;
height: calc(100vh - 732px);
overflow: auto;
}
.el-autocomplete img {
......
......@@ -7,7 +7,7 @@ import "./assets/css/reset.css";
import * as ElementPlusIconsVue from "@element-plus/icons-vue";
import translate from "i18n-jsautotranslate";
import UUID from "vue3-uuid";
import "@/permission"; // permission control
import "@/permission";
import "element-plus/dist/index.css";
import "./mocks/mock";
const app = createApp(App);
......
import { reactive, watch, ref, defineEmits, defineExpose } from "vue";
import { ElMessage } from "element-plus";
import { upload, getUploadConfigInfo } from "../axios/model/user";
import axios from "axios";
import COS from "cos-js-sdk-v5";
interface UploadMixin {
uploadMixinPath: string;
uploadMixinType: string;
uploadMixinCredentials: any;
uploadMixinTimeStamp: number;
upLoadMixinResult: object;
}
const uploadMixin: UploadMixin = {
uploadMixinPath: "",
uploadMixinType: "",
uploadMixinCredentials: {},
uploadMixinTimeStamp: 0,
upLoadMixinResult: {},
};
interface CustomAxiosResponse {
code: number;
......@@ -89,23 +92,28 @@ export const upLoadHander = async (obj: any) => {
//noCredentials变量控制是否走对象存储
if (noCredentials) {
const query = {};
const res:any = await getUploadConfigInfo(query);
// console.log(res1,'res')
// console.log(res);
const res: any = await getUploadConfigInfo(query);
if (res.code === 200 && res.result) {
const result = res.result;
uploadMixin.uploadMixinPath = result.upLoadPath;
uploadMixin.uploadMixinType = result.uploadType;
staticDomain = result.staticDomain || "https://cdn.tikcos.cn";
if (uploadMixin.uploadMixinType === "txcos") {
const credentials = result.credentials;
console.log(result.response, " result.response");
const ress = res.result.response;
const credentials = ress.credentials;
uploadMixin.uploadMixinCredentials = {
TmpSecretId: credentials?.tmpSecretId,
TmpSecretKey: credentials?.tmpSecretKey,
SecurityToken: credentials?.sessionToken,
StartTime: result.startTime,
ExpiredTime: result.expiredTime,
StartTime: ress?.startTime,
ExpiredTime: ress?.expiredTime,
};
console.log(result, "result");
console.log(
uploadMixin.uploadMixinCredentials,
" uploadMixin.uploadMixinCredentials"
);
}
} else {
resResult = false;
......@@ -114,51 +122,84 @@ export const upLoadHander = async (obj: any) => {
//resResult判断接口是否正常
if (resResult) {
const query = {};
const res:any = await getUploadConfigInfo(query);
if (uploadMixin.uploadMixinType == "txcos") {
// const res: any = await getUploadConfigInfo(query);
console.log(
uploadMixin.uploadMixinCredentials,
" console.log(uploadMixin.uploadMixinCredentials)"
);
const result: any = uploadMixin.upLoadMixinResult;
if (uploadMixin.uploadMixinType === "txcos") {
//走对象存储
const cos = new COS({
getAuthorization: (options: any, callback: any) => {
getAuthorization: (options, callback) => {
callback(uploadMixin.uploadMixinCredentials);
},
});
const tempFolder = fileInfo.biz === "temp" ? "" : `${fileInfo.biz}/`;
const folder = `${fileInfo.fileName}_${new Date().getTime()}.${
fileInfo.fileTyle
}`;
const result = res.result || {};
cos.putObject(
{
// FilePath: fileInfo.file,
Bucket: result.bucketName || "tikcos-1257774783",
Region: result.regionid || "ap-guangzhou",
Key: uploadMixin.uploadMixinPath + tempFolder + folder,
Body: fileInfo.file,
onProgress: function (progressData: any) {
obj.onProgress && obj.onProgress(progressData);
onProgress: function (progressData) {
console.log(progressData, "ada");
obj.onProgress(progressData);
},
},
async (err: any, data: any) => {
(err, data) => {
console.log(err, data, "打印一下");
console.log({ success: true });
console.log(
`${staticDomain}/${uploadMixin.uploadMixinPath}${tempFolder}${folder}`,
"打印一下,数据"
);
if (!err && data.statusCode === 200) {
const imgurl = `${staticDomain}/${uploadMixin.uploadMixinPath}${tempFolder}${folder}`;
obj.onSuccess({
success: true,
message: imgurl,
});
obj.onSuccess({ success: true, message: imgurl });
} else {
obj.onError({
success: false,
message: data.message || "图片上传失败",
});
obj.onError({ success: false, message: err || "图片上传失败" });
}
}
);
} else {
// 其他存储类型暂不支持
obj.onError({
success: false,
message: "服务接口报错",
});
//走系统上传
let VUE_APP_API_URL = import.meta.env.VITE_USER_APP_API_URL;
let newFile = fileInfo.file;
if (/[\u4e00-\u9fa5]/.test(newFile.name)) {
const folder = newFile.name.replace(/[\u4e00-\u9fa5]{1,}/g, "_");
newFile = new File([newFile], folder, { type: newFile.type });
}
let formData = new FormData();
formData.append("biz", fileInfo.biz);
formData.append("file", newFile);
const uploadRes = await axios.post(`http://${VUE_APP_API_URL}:8080/sys/common/upload`,
formData,
{
headers: { ...obj.headers },
processData: false,
contentType: false,
async: false,
}
);
if (uploadRes.success && uploadRes.message) {
//保存绝对路径,不然小程序会有问题
let url = uploadRes.message;
url = uploadRes.message.replaceAll("//", "/");
const pre = url.startsWith("/") ? "" : "/";
url = `http://${VUE_APP_API_URL}/sys/common/static` + pre + url;
obj.onSuccess({ success: true, message: url });
} else {
obj.onError({
success: false,
message: uploadRes.message || "图片上传失败",
});
}
}
} else {
obj.onError({
......
......@@ -14,7 +14,6 @@ export const useUserStore = defineStore("user", {
password: "",
token: "",
},
// userList: [],
};
},
actions: {
......@@ -37,9 +36,8 @@ export const useUserStore = defineStore("user", {
to: res.to,
id: res.id,
form: res.from,
userImg:
"https://cdn.lirimall.com//lirigo/filetempImage/新鲜水果_1661668973048.png",
time: moment(res.createTime).format("YYYY-DD-MM HH:mm:ss"),
userImg:"https://cdn.lirimall.com//lirigo/filetempImage/新鲜水果_1661668973048.png",
time: moment(res.createTime).format("HH:mm:ss"),
};
messages.push(obj);
this.customerInfo.messages = messages;
......@@ -51,7 +49,7 @@ export const useUserStore = defineStore("user", {
chatDatas.forEach((item: any) => {
item.userImg =
"https://cdn.lirimall.com//lirigo/filetempImage/新鲜水果_1661668973048.png";
item.time = moment(res.createTime).format("YYYY-DD-MM HH:mm:ss");
item.time = moment(res.createTime).format("HH:mm:ss");
});
for (const index in chatDatas) {
const userId = chatDatas[index].from;
......
......@@ -11,13 +11,21 @@
id="srollId"
ref="srollId"
:style="{
padding: '24px',
padding: '0px 24px',
height: '60vh',
width: '100%',
}"
>
<div class="title-message">You have no history messages</div>
<div class="message-container message-container-right">
<div class="we-connecting">
We are connecting you to online customer service
</div>
<!-- 推荐商品 -->
<div
class="message-container message-container-right"
v-if="productInfo.isShow"
>
<div class="classSendLink">
<div class="classSendDiv">
<div class="classSend-img">
......@@ -35,13 +43,39 @@
</div>
</div>
</div>
<div class="sendlinkbox" @click="toSendLink(productInfo)">
<div class="box-send">send link</div>
<div class="box-close">Close</div>
<div class="sendlinkbox">
<div class="box-send" @click="toSendLink(productInfo)">
send link
</div>
<div class="box-close" @click="toCloseLink(productInfo)">
Close
</div>
</div>
</div>
</div>
<!-- -->
<div class="message-container message-container-left">
<div class="avatar">
<img
:src="require('../assets/camera.png')"
class="avatar-image"
/>
</div>
<div class="bubble official-box">
<div class="bubble-title">You may want to know</div>
<a class="bubble-h1">
How to open the product multi-picture function ?
</a>
<a class="bubble-h1">
How to release more products and get traffic ?
</a>
</div>
</div>
<div v-for="(message, index) in messages" :key="index">
<div class="message-time" v-if="message.time == 1">
{{ message.time }}
</div>
<!-- 发送的推荐商品 -->
<div
class="message-container message-container-right"
v-if="message.msgType == 3"
......@@ -70,12 +104,12 @@
</div> -->
</div>
</div>
<!-- 普通聊天 -->
<div
v-else
v-if="message?.msgType == 0"
class="message-container"
:class="getMessageClass(message?.isSent)"
>
<div class="time">{{ message.time }}</div>
<div v-if="message.isSent" class="message-container">
<div class="bubble">
<!--文字 -->
......@@ -92,18 +126,18 @@
/>
</div>
</div>
<div class="avatar">
<!-- <div class="avatar">
<img
src="../assets/shop.jpg"
alt="Avatar"
class="avatar-image"
/>
</div>
/> -->
<!-- </div> -->
</div>
<div v-if="!message.isSent" class="message-container">
<div class="avatar">
<!-- <div class="avatar">
<img :src="message?.userImg" class="avatar-image" />
</div>
</div> -->
<div class="bubble">
<div
v-if="message?.msgType == 0"
......@@ -120,10 +154,45 @@
</div>
</div>
</div>
<!-- 询价单 -->
<div
class="message-container message-container-right"
v-if="message.msgType == 4"
>
<div class="inquiry-list">
<div class="inquiry-top">
<div class="product-left">
<div class="product-category">
{{ message.content.purchaseQuantity }}
</div>
<div class="product-name">
{{ message.content.ProductName }}
</div>
</div>
<div>
<div class="product-count">
{{ message.content.price }}
</div>
<div class="from-china">
{{ message.content.EmailAddress }}
</div>
</div>
</div>
<div class="product-info">
{{ message.content.otherRequirements }}
</div>
<div class="design-requirements">
<div>{{ message.content.flieName }}</div>
<div class="img">
<img :src="require('../assets/icon_download.png')" />
</div>
</div>
</div>
</div>
</div>
</el-main>
<el-footer class="el-footer" :style="{ border: '1px solid #E9ECF1' }">
<div class="static-box">
<!-- <div class="static-box">
<div
v-for="(item, index) in staticList"
:key="index"
......@@ -131,7 +200,7 @@
>
<div>{{ item }}</div>
</div>
</div>
</div> -->
<AutomaticPrompt
@keydown.enter="handleButtonClick"
@updateState="getState"
......@@ -141,31 +210,32 @@
<div>[ Send shortcut key: Enter ]</div>
<div>
<el-button
plain
style="width: 50px; background: #f8f8fa; color: #000;"
@click.stop="handleButtonClick"
>
Finish
</el-button>
<el-button
style="width: 50px; color: #fff; background: #000;"
style="
width: 80px;
height: 32px;
color: #fff;
font-family: 'PingFang SC';
font-size: 16px;
background: #000;
"
plain
@click.stop="handleButtonClick"
>
send
Send
</el-button>
</div>
</div>
</el-footer>
</el-container>
<el-aside
v-if="num == 1"
v-if="pageType == 1"
width="292px"
:style="{
height: 'calc(100vh - 60px)',
}"
>
<div class="recentlyViewd">最近浏览</div>
<div class="recentlyViewd">Browsing history</div>
<div class="Recommended">Recommended products</div>
<div
v-for="(item, index) in productList"
:key="index"
......@@ -185,7 +255,7 @@
</el-aside>
<el-aside
width="292px"
v-if="num == 2"
v-if="pageType == 2"
:style="{
height: 'calc(100vh - 60px)',
}"
......@@ -209,7 +279,7 @@
prop="Email"
/>
</el-form-item>
<el-form-item prop="Email" label="Purchase Quantity">
<el-form-item prop="Email" label="Product Category">
<el-select
placeholder="Select"
prop="Email"
......@@ -221,14 +291,11 @@
<el-option label="Tel" value="3" />
</el-select>
</el-form-item>
<el-form-item
prop="explanation"
label="Other requirements explanation"
>
<el-form-item prop="purchaseQuantity" label="Purchase Quantity">
<el-input
style="max-width: 600px; height: 36px;"
placeholder="Please enter"
v-model="ruleForm.explanation"
v-model="ruleForm.purchaseQuantity"
class="input-with-select"
prop="Email"
>
......@@ -248,10 +315,10 @@
</el-form-item>
<el-form-item
label="Other requirements explanation"
prop="explanation"
prop="otherRequirements"
>
<el-input
v-model="ruleForm.explanation"
v-model="ruleForm.otherRequirements"
:autosize="{ minRows: 3, maxRows: 10 }"
type="textarea"
placeholder="Please enter"
......@@ -267,7 +334,7 @@
</div>
<div class="requirements-box1" v-if="isUpload">
<div class="box">
<div class="upload-name">Tech design requirements.pdf</div>
<div class="upload-name">{{ ruleForm.flieName }}</div>
<div class="upload-info">
<el-icon color="green"><CircleCheck /></el-icon>
<span>200KB</span>
......@@ -277,9 +344,15 @@
</div>
</el-form-item>
<el-form-item prop="EmailAddress" label="Email Address">
<el-input style="height: 44px;" placeholder="Please enter" v-model="ruleForm.EmailAddress" />
<el-input
style="height: 36px;"
placeholder="Please enter"
v-model="ruleForm.EmailAddress"
/>
</el-form-item>
<div class="footerSubmit">Submit</div>
<div class="footerSubmit" @click="submitForm(ruleForm)">
Submit
</div>
</el-form>
</div>
</el-aside>
......@@ -290,16 +363,9 @@
<script lang="ts" setup>
import '../assets/font/iconfont.css'
import { ElMessage } from 'element-plus'
import moment from 'moment'
import type { FormInstance } from 'element-plus'
import {
ref,
onMounted,
watch,
nextTick,
getCurrentInstance,
reactive,
} from 'vue'
import { getShortDate } from '../utils/index'
import { ref, onMounted, watch, nextTick, reactive } from 'vue'
import { useUserStore } from '../store/modules/user'
import AutomaticPrompt from '../components/AutomaticPrompt.vue'
import ImageViewer from '@luohc92/vue3-image-viewer'
......@@ -308,10 +374,22 @@ import { initWebSocket } from '../utils/websocket'
import '@luohc92/vue3-image-viewer/dist/style.css'
import { checkMesssages } from '../axios/model/user'
import { require } from '@/utils/index'
import { useRoute } from 'vue-router'
const route = useRoute()
const routeParams = route.query
const pageType = routeParams.type || 1
const ruleForm = ref({
count: 1,
ProductName: 'Product Name',
Email: '1143572217@qq.com',
purchaseQuantity: 'Product Category',
China: '',
price: 5000,
flieName: 'Tech design requirements.pdf',
otherRequirements:
'Other requirements explanation Other requirements explanation Other requirements explanation Other requirements explanation Other requirements explanation',
EmailAddress: 'from china',
})
const rules = reactive({
ProductName: [
{
......@@ -352,21 +430,23 @@ const rules = reactive({
const ruleFormRef = ref<FormInstance>()
const customerInfo = ref({})
const messages = ref([])
const num = 2
const isUpload = true
const staticList = ref([
'Login account',
'Forgot password',
'Free entry',
'Add/manage products',
'improve',
])
// const staticList = ref([
// 'Login account',
// 'Forgot password',
// 'Free entry',
// 'Add/manage products',
// 'improve',
// ])
const productInfo = ref({
productImg: require('../assets/shop.jpg'),
productName: 'The secret to looking glowup nowadays',
price: '$1.40 - 2.50',
link: 'send',
isShow: true,
})
const productList = ref([
{
productImg: require('../assets/camera.png'),
......@@ -399,11 +479,13 @@ onMounted(async () => {
})
const connectMsg = () => {
return new Promise((resolve: any, reject: any) => {
// console.log(import)
const useUser = useUserStore()
useUser.setUserInfo({
username: Date.now(),
})
const toIp = `ws://192.168.31.123:8081?type=yk&code=${useUser.userInfo.username}&kf=${store.customerInfo.username}`
let VUE_APP_API_URL = import.meta.env.VITE_USER_APP_API_URL
const toIp = `ws://${VUE_APP_API_URL}:8081?type=yk&code=${useUser.userInfo.username}&kf=${store.customerInfo.username}`
useUser.connect()
initWebSocket(toIp)
setTimeout(() => {
......@@ -450,7 +532,7 @@ const setSrollHeight = () => {
//发送按钮
const handleButtonClick = () => {
if (!msg) {
if (!msg.trim()) {
return ElMessage({
message: '请输入内容',
type: 'error',
......@@ -465,7 +547,7 @@ const handleButtonClick = () => {
fromLang: 'cn',
toLang: 'en',
group_id: '',
time: getShortDate(),
time: moment(new Date()).format('HH:mm:ss'),
to: customerInfo.value.username,
form: store.userInfo.username,
}
......@@ -473,7 +555,29 @@ const handleButtonClick = () => {
sendWebSocket(data)
automaticPromptRef.value.setState('')
}
//关闭商品弹窗
const toCloseLink = () => {
productInfo.value.isShow = false
}
//发布询价单
const submitForm = (e) => {
const data = {
content: e,
isSent: true,
cmd: '11',
msgType: 4,
chatType: '2',
fromLang: 'cn',
toLang: 'en',
group_id: '',
time: moment(new Date()).format('HH:mm:ss'),
to: customerInfo.value.username,
form: store.userInfo.username,
}
messages.value?.push(data)
sendWebSocket(data)
}
const handleMessageClick = (event: any) => {
const target = event.target
if (target.tagName === 'A') {
......@@ -517,6 +621,7 @@ const handleLinkClick = (msg: string) => {
const getMessageClass = (isSent: boolean) => {
return isSent ? 'message-container-right' : 'message-container-left'
}
//发送商品信息
const toSendLink = (e: any) => {
const data = {
content: e,
......@@ -527,7 +632,7 @@ const toSendLink = (e: any) => {
fromLang: 'cn',
toLang: 'en',
group_id: '',
time: getShortDate(),
time: moment(new Date()).format('HH:mm:ss'),
to: customerInfo.value.username,
form: store.userInfo.username,
}
......@@ -537,15 +642,129 @@ const toSendLink = (e: any) => {
}
</script>
<style lang="scss" scoped>
.inquiry-list {
display: flex;
width: 360px;
padding: 12px 12px 8px 12px;
flex-direction: column;
justify-content: center;
align-items: flex-start;
border-radius: 8px 0 8px 8px;
border: 1px solid #e9ecf1;
.inquiry-top {
margin-bottom: 8px;
width: 100%;
display: flex;
justify-content: space-between;
.product-left {
display: flex;
flex-direction: column;
justify-content: space-between;
.product-category {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
color: #0c203d;
text-overflow: ellipsis;
font-family: 'Inter';
font-size: 14px;
font-style: normal;
font-weight: 500;
margin-bottom: 6px;
}
.product-name {
font-family: 'Inter';
font-size: 14px;
font-style: normal;
font-weight: 500;
}
}
}
.design-requirements {
width: 336px;
height: 36px;
justify-content: space-between;
line-height: 36px;
margin-top: 8px;
padding: 0px 8px;
display: flex;
align-items: center;
background: #f6f9fc;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
align-self: stretch;
overflow: hidden;
border-radius: 4px;
color: #475263;
text-overflow: ellipsis;
font-family: 'Inter';
font-size: 12px;
font-style: normal;
font-weight: 400;
.img {
width: 20px;
height: 20px;
img {
width: 100%;
height: 100%;
}
}
}
}
.we-connecting {
display: flex;
padding: 8px;
font-size: 12px;
justify-content: center;
align-items: center;
border-radius: 4px;
width: max-content;
background: #f8f8fa;
margin: 0px auto;
margin-bottom: 16px;
color: #798494;
}
.title-message {
color: #798494;
height: 56px;
line-height: 56px;
text-align: center;
font-feature-settings: 'clig' off, 'liga' off;
font-family: 'Helvetica Neue';
font-size: 14px;
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: 16px;
}
.message-time {
color: #798494;
text-align: center;
font-feature-settings: 'clig' off, 'liga' off;
font-family: 'Inter';
font-size: 14px;
font-style: normal;
font-weight: 500;
line-height: 20px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
&::after,
&::before {
display: flex;
content: ' ';
height: 0.5px;
background: #e6e8ed;
flex: 1;
justify-content: space-between;
align-items: center;
}
&::after {
margin-left: 8px;
}
&::before {
margin-right: 8px;
}
}
.class-send-box {
display: flex;
......@@ -968,10 +1187,11 @@ const toSendLink = (e: any) => {
}
.avatar-image {
width: 40px;
height: 40px;
width: 32px;
height: 32px;
border-radius: 50%;
object-fit: cover;
margin-right: 12px;
}
.bubble {
......@@ -979,7 +1199,6 @@ const toSendLink = (e: any) => {
color: #000;
padding: 10px 14px;
border-radius: 5px;
max-width: 320px;
background: #f5f5f5;
border-radius: 10px;
color: #000;
......@@ -992,6 +1211,30 @@ const toSendLink = (e: any) => {
height: auto;
display: block;
}
.bubble-title {
font-family: 'Helvetica Neue';
font-size: 14px;
font-style: normal;
font-weight: 500;
line-height: 20px;
margin-bottom: 4px;
}
.bubble-h1 {
color: #1a65d6;
cursor: pointer;
font-family: 'Helvetica Neue';
font-size: 14px;
font-style: normal;
display: block;
font-weight: 500;
line-height: 20px;
letter-spacing: 0.56px;
margin-bottom: 4px;
}
}
.official-box {
width: 464px;
}
.message-container-right {
......@@ -1065,12 +1308,22 @@ const toSendLink = (e: any) => {
}
.browse-glance {
display: flex;
padding: 16px 12px 0px 12px;
position: relative;
padding: 16px 12px 16px 12px;
.browse-img {
width: 64px;
height: 64px;
margin-right: 12px;
}
&::before {
position: absolute;
content: ' ';
height: 0.5px;
background: #e6e8ed;
width: 91%;
bottom: 0px;
}
.units {
margin-top: 8px;
......@@ -1092,7 +1345,6 @@ const toSendLink = (e: any) => {
line-height: 24px;
letter-spacing: 0.72px;
}
.send {
display: flex;
width: 56px;
......@@ -1219,6 +1471,7 @@ const toSendLink = (e: any) => {
color: #073a3dff;
font-family: 'Inter';
font-size: 14px;
margin-bottom: 4px;
font-style: normal;
font-weight: 500;
line-height: 20px;
......@@ -1270,4 +1523,33 @@ const toSendLink = (e: any) => {
:deep(.el-select__wrapper) {
height: 36px !important;
}
.product-count {
color: #0c203dff;
font-feature-settings: 'clig' off, 'liga' off;
font-family: 'Helvetica Neue';
font-size: 18px;
font-style: normal;
font-weight: 700;
line-height: 24px;
letter-spacing: 0.72px;
}
.from-china {
color: #475263ff;
font-family: 'Inter';
font-size: 10px;
font-style: normal;
font-weight: 400;
line-height: 16px;
}
.product-info {
align-self: stretch;
color: #475263;
font-family: 'Inter';
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 20px;
padding-bottom: 8px;
border-bottom: 1px solid #e6e8ed;
}
</style>
......@@ -46,7 +46,7 @@ export default defineConfig({
],
server: {
host: "0.0.0.0",
port: 80,
port: 8082,
open: false,
},
});
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论