Files
FT546MWS/ruoyi-ui/src/views/bas/BasProductCode/index.vue
张怡蓉 d427ebf6d0 初始化
2025-12-23 13:36:18 +08:00

1028 lines
29 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="app-container">
<el-row :gutter="20">
<!-- 左侧区域 -->
<el-col :span="8">
<!-- 表单区域 -->
<div class="form-container">
<div class="section-header">
<h3>生成条码</h3>
</div>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-row :gutter="20">
<el-col
v-for="field in formFields"
:key="field.prop"
:span="24"
>
<el-form-item :label="field.label" :prop="field.prop">
<el-input
v-model="form[field.prop]"
:placeholder="field.placeholder"
:disabled="loading"
:readonly="field.readonly"
@click.native="field.prop === 'spare4' && openProductSelect()"
/>
</el-form-item>
</el-col>
</el-row>
<el-form-item class="form-actions">
<el-button
type="warning"
@click="handlePreview"
:loading="previewLoading"
icon="el-icon-view"
>
预览
</el-button>
<el-button
@click="resetForm"
icon="el-icon-refresh"
>
重置
</el-button>
</el-form-item>
</el-form>
</div>
</el-col>
<!-- 右侧预览区域 -->
<el-col :span="16">
<!-- 预览弹框 -->
<el-dialog
title="标签预览"
:visible.sync="showPreview"
width="700px"
:close-on-click-modal="false"
append-to-body
>
<div class="preview-container">
<div class="label-content">
<div class="preview-box">
<div class="preview-content">
<div class="preview-row">
<span class="preview-label">MODEL:</span>
<span class="preview-value">{{ previewData.model }}</span>
</div>
<div class="preview-row">
<span class="preview-label">SERIAL:</span>
<span class="preview-value">{{ previewData.serial }}</span>
</div>
<div class="preview-row">
<span class="preview-label">COLOR:</span>
<span class="preview-value">{{ previewData.color }}</span>
</div>
<div class="preview-row">
<div class="preview-col">
<span class="preview-label">V:</span>
<span class="preview-value">{{ previewData.v }}</span>
</div>
<div class="preview-col">
<span class="preview-label">Hz:</span>
<span class="preview-value">{{ previewData.hz }}</span>
</div>
<div class="preview-col">
<span class="preview-label">PH:</span>
<span class="preview-value">{{ previewData.ph }}</span>
</div>
</div>
<div class="preview-row">
<div class="preview-col">
<span class="preview-label">N.W.:</span>
<span class="preview-value">{{ previewData.nW }}</span>
</div>
<div class="preview-col">
<span class="preview-label">G.W.:</span>
<span class="preview-value">{{ previewData.gW }}</span>
</div>
</div>
</div>
<!-- 二维码区域 -->
<div class="qrcode-container">
<vue-qr
:text="qrCodeValue"
:size="200"
:margin="0"
:correctLevel="2"
error-correction-level="M"
/>
<div class="qrcode-label">{{ previewData.spare4 }}</div>
</div>
</div>
</div>
</div>
<!-- 打印专用区域(隐藏) -->
<vue-easy-print style="display: none;" ref="easyPrint2">
<div style="page-break-after:always">
<div class="preview-row" >
<span class="preview-label">MODEL:</span>
<span class="preview-value">{{ previewData.model }}</span>
</div>
<div class="preview-row" >
<span class="preview-label">SERIAL:</span>
<span class="preview-value">{{ previewData.serial }}</span>
</div>
<div class="preview-row" >
<span class="preview-label">COLOR:</span>
<span class="preview-value">{{ previewData.color }}</span>
</div>
<div class="preview-row" >
<div class="preview-col">
<span class="preview-label">V:</span>
<span class="preview-value">{{ previewData.v }}</span>
</div>
<div class="preview-col">
<span class="preview-label">Hz:</span>
<span class="preview-value">{{ previewData.hz }}</span>
</div>
<div class="preview-col">
<span class="preview-label">PH:</span>
<span class="preview-value">{{ previewData.ph }}</span>
</div>
</div>
<div class="preview-row" >
<div class="preview-col">
<span class="preview-label">N.W.:</span>
<span class="preview-value">{{ previewData.nW }}</span>
</div>
<div class="preview-col">
<span class="preview-label">G.W.:</span>
<span class="preview-value">{{ previewData.gW }}</span>
</div>
</div>
<div class="qrcode-container">
<vue-qr
:text="qrCodeValue"
:size="100"
:margin="0"
:correctLevel="2"
error-correction-level="M"
/>
<div class="qrcode-label">{{ previewData.spare4 }}</div>
</div>
<!-- <div class="label-content">
</div>-->
</div>
</vue-easy-print>
<div slot="footer" class="dialog-footer">
<el-button @click="showPreview = false">关 闭</el-button>
<el-button type="primary" @click="submitForm" :loading="submitLoading">保存并打印</el-button>
</div>
</el-dialog>
<!-- 历史数据区域 -->
<div class="list-container" style="padding-bottom: 60px;">
<div class="section-header" style="margin-bottom: 20px;">
<h3>历史数据</h3>
<div class="header-actions">
<el-button
type="danger"
size="small"
@click="handleBatchDelete"
:disabled="!hasSelection"
icon="el-icon-delete"
>
批量删除
</el-button>
</div>
</div>
<!-- 搜索框区域 -->
<div class="search-box" style="margin-bottom: 20px; border: 1px solid #ebeef5; padding: 15px; background-color: #fff; border-radius: 4px;">
<div style="display: flex; align-items: center;">
<div style="font-weight: bold; margin-right: 10px; min-width: 60px;">订单号</div>
<el-input
v-model="queryParams.spare1"
placeholder="请输入订单号"
clearable
style="width: 240px; margin-right: 10px;"
@keyup.enter.native="handleQuery"
/>
<el-button type="primary" icon="el-icon-search" @click="handleQuery" style="margin-right: 10px;">搜索</el-button>
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
</div>
</div>
<el-table
ref="table"
v-loading="loading"
:data="tableData"
@selection-change="handleSelectionChange"
stripe
border
style="width: 100%;margin-bottom: 40px;height: 575px;"
>
<el-table-column type="selection" width="55" align="center"/>
<el-table-column
v-for="column in tableColumns"
:key="column.prop"
:label="column.label"
:prop="column.prop"
:width="column.width"
:formatter="column.formatter"
show-overflow-tooltip
/>
<el-table-column label="操作" width="180" align="center" fixed="right">
<template slot-scope="scope">
<el-button size="mini" type="text" @click="handleEdit(scope.row)" icon="el-icon-edit">编辑</el-button>
<el-button size="mini" type="text" @click="handlePrint(scope.row)" icon="el-icon-printer">打印</el-button>
<el-button size="mini" type="text" @click="handleDelete(scope.row)" icon="el-icon-delete" class="danger-text">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</div>
</el-col>
</el-row>
<!-- 物资选择弹框 -->
<el-dialog
title="选择物资"
:visible.sync="productSelectVisible"
width="800px"
append-to-body
>
<div class="search-container">
<el-form :model="productQueryParams" ref="queryForm" :inline="true">
<el-form-item label="品号" prop="productId">
<el-input
v-model="productQueryParams.productId"
placeholder="请输入品号"
clearable
size="small"
@keyup.enter.native="handleProductQuery"
/>
</el-form-item>
<el-form-item label="品名" prop="productName">
<el-input
v-model="productQueryParams.productName"
placeholder="请输入品名"
clearable
size="small"
@keyup.enter.native="handleProductQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleProductQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetProductQuery">重置</el-button>
</el-form-item>
</el-form>
</div>
<el-table
v-loading="productTableLoading"
:data="productTableData"
@row-click="handleProductSelect"
highlight-current-row
style="width: 100%"
>
<el-table-column type="index" width="50" align="center" />
<el-table-column label="品号" align="center" prop="productId" />
<el-table-column label="NC号" align="center" prop="spare9" />
<el-table-column label="品名" align="center" prop="productName" />
<el-table-column label="规格" align="center" prop="spec" />
<el-table-column label="品号描述" align="center" prop="price" />
<el-table-column label="英文描述" align="center" prop="cargoNo" />
<el-table-column label="图号" align="center" prop="unit" />
<el-table-column label="电压" align="center" prop="spare5" />
<el-table-column label="电源线" align="center" prop="spare10" />
<el-table-column label="插头" align="center" prop="spare11" />
<el-table-column label="接嘴" align="center" prop="spare12" />
<el-table-column label="快捷码" align="center" prop="spare13" />
<el-table-column label="库存单位编号" align="center" prop="spare14" />
<el-table-column label="库存单位名称" align="center" prop="spare15" />
<el-table-column label="品号群组" align="center" prop="spare16" />
<el-table-column label="归类品" align="center" prop="spare17" />
<el-table-column label="计量体系" align="center" prop="spare18" />
<el-table-column label="群组名称" align="center" prop="spare19" />
<el-table-column label="批号管理" align="center" prop="spare20" />
<el-table-column label="状态" align="center" prop="spare21" />
<el-table-column label="产品大类" align="center" prop="spare22" />
<el-table-column label="产品二类" align="center" prop="spare23" />
<el-table-column label="产品线/产品系列" align="center" prop="spare24" />
<el-table-column label="BOM状态" align="center" prop="spare25" />
<el-table-column label="产品定位" align="center" prop="spare26" />
<el-table-column label="电脑板型号" align="center" prop="spare27" />
<el-table-column label="非标要求" align="center" prop="spare28" />
<el-table-column label="品牌" align="center" prop="spare29" />
<el-table-column label="非标颜色" align="center" prop="spare30" />
<el-table-column label="主颜色" align="center" prop="spare31" />
<el-table-column label="辅助颜色" align="center" prop="spare32" />
<el-table-column label="是否标准款" align="center" prop="spare33" />
<el-table-column label="包装方式" align="center" prop="spare34" />
<el-table-column label="主要包装方式" align="center" prop="spare35" />
<el-table-column label="描述" align="center" prop="remark" />
<el-table-column label="长" align="center" prop="spare36" />
<el-table-column label="宽" align="center" prop="spare37" />
<el-table-column label="高" align="center" prop="spare38" />
<el-table-column label="包装材积" align="center" prop="spare39" />
</el-table>
<pagination
v-show="productTotal > 0"
:total="productTotal"
:page.sync="productQueryParams.pageNum"
:limit.sync="productQueryParams.pageSize"
@pagination="getProductList"
/>
</el-dialog>
</div>
</template>
<script>
import VueQr from 'vue-qr'
import VueEasyPrint from 'vue-easy-print'
import {addBasProductCode, delBasProductCode, listBasProductCode, updateBasProductCode} from "@/api/bas/BasProductCode"
import {listBasProduct} from "@/api/bas/BasProduct"
// 常量配置
const FORM_FIELDS = [
{ prop: 'spare4', label: '品号', placeholder: '点击选择品号', required: true, readonly: true },
{ prop: 'model', label: '型号', placeholder: '请输入型号', required: true },
{ prop: 'serial', label: '序列号', placeholder: '请输入序列号', required: true },
{ prop: 'color', label: '颜色', placeholder: '请输入颜色', required: true },
{ prop: 'v', label: '电压', placeholder: '请输入电压', required: true },
{ prop: 'hz', label: '功率', placeholder: '请输入功率' , required: true},
{ prop: 'ph', label: '相位', placeholder: '请输入相位' , required: true},
{ prop: 'nW', label: '净重', placeholder: '请输入净重', required: true },
{ prop: 'gW', label: '毛重', placeholder: '请输入毛重', required: true },
{ prop: 'spare1', label: '订单号', placeholder: '请输入订单号', required: true },
{ prop: 'spare2', label: '机型', placeholder: '请输入机型', required: true },
{ prop: 'spare3', label: '分销', placeholder: '请输入分销', required: true }
]
const TABLE_COLUMNS = [
{ prop: 'spare4', label: '品号', width: 140 },
{ prop: 'model', label: '型号', width: 120 },
{ prop: 'color', label: '颜色', width: 100 },
{ prop: 'serial', label: '序列号', width: 150 },
{ prop: 'v', label: '电压', width: 100 },
{ prop: 'hz', label: '功率', width: 100 },
{ prop: 'ph', label: '相位', width: 100 },
{ prop: 'nW', label: '净重', width: 100 },
{ prop: 'gW', label: '毛重', width: 100 },
{
prop: 'type',
label: '状态',
width: 100,
formatter: (row) => row.type === '1' ? '未打印' : '已打印'
},
{ prop: 'spare1', label: '订单号', width: 150 },
{ prop: 'spare2', label: '机型', width: 120 },
{ prop: 'spare3', label: '分箱', width: 100 }
]
const DEFAULT_FORM = {
model: '',
color: '',
serial: '',
v: '',
hz: '',
ph: '',
nW: '',
gW: '',
type: '1',
spare1: '',
spare2: '',
spare3: '',
spare4: ''
}
const DEFAULT_PREVIEW_DATA = {
model: '',
color: '',
serial: '',
v: '',
hz: '',
ph: '',
nW: '',
gW: ''
}
export default {
name: 'BasProductCode',
components: {
VueQr,
VueEasyPrint
},
data() {
return {
// 表单对象
form: { ...DEFAULT_FORM },
// 表单校验规则
rules: this.generateRules(),
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
searchText: ''
},
// 表格数据
tableData: [],
// 加载状态
loading: false,
previewLoading: false,
submitLoading: false,
// 总条数
total: 0,
// 预览数据
previewData: { ...DEFAULT_PREVIEW_DATA },
// 选中数据
selectedRows: [],
// 是否显示预览
showPreview: false,
// 表单字段配置
formFields: FORM_FIELDS,
// 表格列配置
tableColumns: TABLE_COLUMNS,
// 物资选择弹框显示状态
productSelectVisible: false,
// 物资查询参数
productQueryParams: {
pageNum: 1,
pageSize: 10,
productId: undefined,
productName: undefined
},
// 物资表格数据
productTableData: [],
// 物资表格加载状态
productTableLoading: false,
// 物资总条数
productTotal: 0
}
},
computed: {
// 二维码内容
qrCodeValue() {
console.log(this.previewData)
const text = `${this.previewData.spare1}@${this.previewData.model}@${this.previewData.spare2}@${this.previewData.spare3}@${this.previewData.serial}`
var bm = this.procode(text)
return "MODEL:" + this.previewData.model + " COLOR:" + this.previewData.color
+ " SERIAL:" + this.previewData.serial + " V:" + this.previewData.v
+ " Hz:" + this.previewData.hz + " PH:" + this.previewData.ph
+ " N.W.:" + this.previewData.nW + " G.W.:" + this.previewData.gW+" ITEM_CODE:"+this.previewData.spare4+ " @:" + bm + "@"
},
// 是否有选中项
hasSelection() {
return this.selectedRows.length > 0
}
},
created() {
this.init()
},
methods: {
// 初始化
async init() {
try {
await this.getList()
} catch (error) {
this.$message.error('初始化失败:' + error.message)
}
},
// 生成表单验证规则
generateRules() {
const rules = {}
FORM_FIELDS.forEach(field => {
if (field.required) {
rules[field.prop] = [
{ required: true, message: `请输入${field.label}`, trigger: 'blur' }
]
}
})
return rules
},
// 获取列表数据
async getList() {
this.loading = true
try {
const response = await listBasProductCode(this.queryParams)
this.tableData = response.rows || []
this.total = response.total || 0
} catch (error) {
this.$message.error('获取数据失败:' + error.message)
this.tableData = []
this.total = 0
} finally {
this.loading = false
}
},
// 查询按钮操作
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
// 重置表单
resetForm() {
this.$refs.form.resetFields()
this.form = { ...DEFAULT_FORM }
this.previewData = { ...DEFAULT_PREVIEW_DATA }
this.showPreview = false
},
resetQuery(){
this.queryParams = {
pageNum: 1,
pageSize: 10,
searchText: ''
}
this.handleQuery()
},
// 预览按钮操作
async handlePreview() {
try {
await this.$refs.form.validate()
this.previewLoading = true
// 模拟预览加载
setTimeout(() => {
this.previewData = { ...this.form }
this.showPreview = true
this.previewLoading = false
this.$message.success('预览生成成功')
}, 300)
} catch (error) {
this.$message.warning('请完善必填信息')
}
},
// 表单提交
async submitForm() {
try {
await this.$refs.form.validate()
this.submitLoading = true
const apiCall = this.form.id != null
? updateBasProductCode(this.form)
: addBasProductCode(this.form)
await apiCall
const message = this.form.id != null ? '修改成功' : '新增成功'
this.$message.success(message)
await this.getList()
await this.autoPrint()
} catch (error) {
this.$message.error('保存失败:' + error.message)
} finally {
this.submitLoading = false
}
},
// 新增按钮操作
handleAdd() {
this.resetForm()
},
// 编辑按钮操作
handleEdit(row) {
this.form = { ...row }
this.previewData = { ...row }
// this.showPreview = true
},
// 删除按钮操作
async handleDelete(row) {
try {
await this.$confirm(
`是否确认删除条码打印编号为"${row.id}"的数据项?`,
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
)
await delBasProductCode(row.id)
this.$message.success('删除成功')
await this.getList()
} catch (error) {
if (error !== 'cancel') {
this.$message.error('删除失败:' + error.message)
}
}
},
// 批量删除
async handleBatchDelete() {
if (!this.hasSelection) {
this.$message.warning('请选择要删除的数据')
return
}
try {
await this.$confirm(
`是否确认删除选中的${this.selectedRows.length}条数据?`,
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
)
const ids = this.selectedRows.map(row => row.id)
await delBasProductCode(ids.join(','))
this.$message.success('批量删除成功')
await this.getList()
} catch (error) {
if (error !== 'cancel') {
this.$message.error('批量删除失败:' + error.message)
}
}
},
// 打印按钮操作
async handlePrint(row) {
try {
this.previewData = { ...row }
this.showPreview = true
await this.$nextTick()
setTimeout(() => {
this.$refs.easyPrint2.print()
}, 100)
} catch (error) {
this.$message.error('打印失败:' + error.message)
}
},
// 自动打印功能
async autoPrint() {
try {
this.previewData = { ...this.form }
this.showPreview = true
await this.$nextTick()
setTimeout(() => {
this.$refs.easyPrint2.print()
}, 500)
} catch (error) {
this.$message.error('自动打印失败:' + error.message)
}
},
// 多选框选中数据
handleSelectionChange(selection) {
this.selectedRows = selection
},
// 打开物资选择弹框
openProductSelect() {
this.productSelectVisible = true;
this.getProductList();
},
// 获取物资列表
async getProductList() {
this.productTableLoading = true;
try {
const response = await listBasProduct(this.productQueryParams);
this.productTableData = response.rows || [];
this.productTotal = response.total || 0;
} catch (error) {
this.$message.error('获取物资数据失败:' + error.message);
} finally {
this.productTableLoading = false;
}
},
// 物资查询按钮操作
handleProductQuery() {
this.productQueryParams.pageNum = 1;
this.getProductList();
},
// 重置物资查询表单
resetProductQuery() {
this.$refs.queryForm.resetFields();
this.productQueryParams = {
pageNum: 1,
pageSize: 10,
productId: undefined,
productName: undefined
};
this.getProductList();
},
// 选择物资
handleProductSelect(row) {
this.form.spare4 = row.productId;
this.productSelectVisible = false;
},
// 二维码编码方法
procode(text) {
const key = "0"
const mystr = text.split("@")
const text1 = `@${mystr[1]}@${mystr[2]}@${mystr[3]}@`
let str = key + text1
let str1 = ""
for (let i = 0; i < str.length; i++) {
// 获取字符的Unicode编码并转换为16进制
let str2 = str.charCodeAt(i).toString(16).toUpperCase()
// 补齐到4位
while (str2.length < 4) {
str2 = "0" + str2
}
str1 += str2
}
// 反转字符串
str1 = str1.split('').reverse().join('')
// 替换操作
str1 = str1.replace(/100/g, "Q")
str1 = str1.replace(/200/g, "R")
str1 = str1.replace(/300/g, "S")
str1 = str1.replace(/400/g, "T")
str1 = str1.replace(/500/g, "U")
str1 = str1.replace(/600/g, "V")
str1 = str1.replace(/700/g, "W")
str1 = str1.replace(/800/g, "X")
str1 = str1.replace(/900/g, "Y")
str1 = str1.replace(/00/g, "Z")
// 最终结果反转
const result = `${mystr[0]}$${str1}$${mystr[4]}`
return result.split('').reverse().join('')
}
}
}
</script>
<style scoped>
/* 基础布局 */
.app-container {
padding: 20px;
background-color: #f5f5f5;
}
.list-container {
background: #fff;
padding: 20px;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.section-header h3 {
margin: 0;
font-size: 16px;
font-weight: 500;
}
.header-actions {
display: flex;
gap: 10px;
}
.el-table {
margin-bottom: 20px;
}
.el-table .danger-text {
color: #F56C6C;
}
.el-table .danger-text:hover {
color: #f78989;
}
/* 容器样式 */
.form-container,
.list-container,
.preview-container {
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.form-container {
margin-bottom: 0;
}
.list-container .el-table {
height: 100%;
}
.preview-display {
height: 100%;
overflow: hidden;
}
/* 区域标题 */
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px 20px 0;
margin-bottom: 20px;
}
.section-header h3 {
margin: 0;
font-size: 16px;
font-weight: 600;
color: #303133;
}
.header-actions {
display: flex;
gap: 10px;
}
/* 表单样式 */
.form-container .el-form {
padding: 0 20px 10px;
}
.form-actions {
text-align: center;
}
.form-actions .el-button {
margin: 0 10px;
}
/* 表格样式 */
.list-container .el-table {
margin: 0 20px;
}
.list-container .pagination {
margin: 20px;
text-align: center;
}
.danger-text {
color: #f56c6c !important;
}
.danger-text:hover {
color: #f78989 !important;
}
.empty-preview i {
font-size: 48px;
margin-bottom: 16px;
color: #000000;
}
.empty-preview p {
margin: 0;
}
.label-content {
border: 1px solid #e4e7ed;
border-radius: 0px;
overflow: hidden;
text-align: left;
}
.preview-box {
padding: 20px;
font-family: 'Arial', sans-serif;
position: relative;
background-color: #fff;
height: 350px;
width: 100%;
box-sizing: border-box;
}
.preview-row {
display: flex;
align-items: center;
margin-bottom: 30px;
min-height: 0;
padding-left: 15px;
}
.preview-col {
flex: 1;
display: flex;
align-items: center;
}
.preview-label {
margin-right: 15px;
min-width: 10px;
font-size: 15px;
font-weight: bold;
color: #000000;
}
.preview-value {
flex: 1;
font-size: 15px;
font-weight: bold;
color: #000000;
word-break: break-all;
}
.qrcode-label {
margin-top: 1px;
font-size: 10px;
font-weight: 600;
color: #000000;
text-align: center;
}
/* 动画效果 */
.preview-display {
animation: fadeIn 0.3s ease-in-out;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 加载状态 */
.el-button.is-loading {
pointer-events: none;
}
/* 打印样式 */
@media print {
@page {
size: auto
}
body {
margin: 0;
}
.preview-box {
border: none;
box-shadow: none;
position: relative;
}
.qrcode-container {
border: none;
position: absolute !important;
top: 10px !important;
right: 30px !important;
padding: 0;
background-color: transparent;
}
}
</style>