Commit fdb057fe by qinjianhui

Merge branch 'dev' into 'master'

Dev

See merge request !62
parents 4a7fd873 6c6c8b3c
......@@ -18,6 +18,9 @@ module.exports = {
'multiline-ternary': 'off',
'vue/multi-word-component-names': 'off',
'eol-last': 0,
'node/no-callback-literal': 'off',
'no-trailing-spaces': 'off',
'no-unused-vars': 'off',
'vue/no-mutating-props': 'off'
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -176,6 +176,12 @@ const routes = [
meta: { title: '异步任务' }
},
{
path: '/operation/amazonAttributeGrouping',
component: () => import('@/views/operation/amazon/amazonAttributeGrouping.vue'),
name: 'amazonAttributeGrouping',
meta: { title: '亚马逊属性分类' }
},
{
path: '/saas/production/assistant/manage',
component: () => import('@/views/production/AssistantManage.vue'),
name: 'production_assistant_manage',
......
......@@ -301,6 +301,14 @@ export default {
icon: 'el-icon-box',
index: '/saas/import-template',
children: []
},
{
id: 12,
path: '',
label: '亚马逊属性分类',
icon: 'el-icon-s-check',
index: '/operation/amazonAttributeGrouping',
children: []
}
// {
// id: 11,
......
<template>
<div class="card amazon-attribute-grouping">
<div class="left-group-status">
<div class="add-group">
<el-button size="small" type="primary" @click="addGroup">
添加分组
</el-button>
<el-button
size="small"
type="danger"
@click="batchDeleteGroups"
:disabled="selectedGroups.length === 0">
删除分组
</el-button>
</div>
<div class="group-status-box" v-if="groupsList.length > 0">
<div
class="group-status-item"
:class="{
active: currentGroupId === 0
}"
@click="currentGroupId = 0">
<span class="group-name">全部(All)</span>
</div>
<div
class="group-status-item"
v-for="item in groupsList"
:key="item.id"
:class="{ active: currentGroupId === item.id }"
@click="currentGroupId = item.id">
<div class="group-checkbox" @click.stop>
<div
class="custom-checkbox"
:class="{ active: selectedGroups.includes(item.id) }"
@click="toggleGroupSelection(item.id)"></div>
</div>
<span class="group-name">{{ item.name }} ({{ item.nameEn }})</span>
<div class="operate-group">
<i
title="编辑"
style="color: #e6a23c; font-size: 14px; margin-right: 6px"
class="el-icon-edit"
@click="editGroup(item)"></i>
</div>
</div>
</div>
</div>
<div class="right-group-content">
<div class="category-box">
<div class="category-item">
<div class="category-title">
<span>店铺</span>
</div>
<div>
<el-select
v-model="shopId"
placeholder="请选择店铺"
@change="shopChange">
<el-option
v-for="item in shopList"
:key="item.id"
:label="item.shopName"
:value="item.id"></el-option>
</el-select>
</div>
<div class="category-title">
<span>Category</span>
</div>
<div style="flex: 1">
<!-- <CustomCascader
:options="amCateCascaders"
v-model="aliCatePathIds"
:loadData="customLazyLoad"
@change="customCascaderChange"></CustomCascader> -->
<el-cascader
size="medium"
:options="amCateCascaders"
ref="amCateCascadersRef"
placeholder="请选择分类"
style="width: 100%"
v-model="aliCatePathIds"
filterable
:props="{
label: 'browseNodeName',
value: 'browseNodeId',
lazy: true,
lazyLoad: lazyLoad
}"
@change="categoryTypeChange"></el-cascader>
</div>
</div>
<div class="category-item">
<div class="category-title">
<span>Search</span>
</div>
<div>
<el-input clearable v-model="keyWord" placeholder="请输入关键词">
<el-button
slot="append"
icon="el-icon-search"
@click="searchCategory"></el-button>
</el-input>
</div>
<div style="flex: 1">
<el-select
style="width: 100%"
filterable
clearable
popper-class="custom-popper-select"
v-model="productType"
@change="productTypeChange"
placeholder="请选择分类">
<el-option
v-for="item in productTypeList"
:key="item.id"
:label="item.browsePathByName"
:value="item.browseNodeId">
<div class="custom-label">
<div>Product Type: {{ item.productType }}</div>
<div>{{ item.browsePathByName }}</div>
</div>
</el-option>
</el-select>
</div>
</div>
</div>
<div class="attribute-box">
<div class="attribute-header">
<el-button type="primary" size="small" @click="setGrouping">
设置分组
</el-button>
<el-button type="success" size="small" @click="selectAll">
全选
</el-button>
<el-button type="warning" size="small" @click="selectNone">
取消全选
</el-button>
</div>
<div class="attribute-content">
<div style="height: 100%; overflow: auto">
<div class="attribute" v-if="showJsonSchema.length > 0">
<div
class="attribute-item"
:class="{
'visible-item-properties': !visibleGroupList[item.name]
}"
v-for="item in showJsonSchema"
:key="item.name">
<div class="attribute-item-title">
<span class="attribute-item-title-text">
{{ item.title }}
</span>
<i
:title="item.description"
class="el-icon-info"
style="font-size: 12px; color: #999; cursor: pointer"></i>
</div>
<div class="attribute-item-content">
<el-select
v-model="dataGroupForm[item.name]"
placeholder="请设置分组"
clearable
class="attribute-item-select"
style="width: 100%">
<el-option
v-for="group in groupsList"
:key="group.id"
:label="`${group.name} (${group.nameEn})`"
:value="group.id"></el-option>
</el-select>
</div>
<div class="select-group-icon" @click="selectAttr(item)">
<div
class="check-icon"
:class="{ active: selectedAttrStatus(item) }"></div>
</div>
</div>
</div>
</div>
</div>
<div class="attribute-footer">
<el-button type="info" size="small" @click="resetGrouping">
重置
</el-button>
<el-button type="success" size="small" @click="saveGrouping">
保存
</el-button>
</div>
</div>
</div>
<el-dialog
title="添加分组"
:visible.sync="addDialogVisible"
:close-on-click-modal="false"
width="50%">
<el-form :model="addForm" label-width="100px" ref="addFormRef">
<el-form-item
label="中文名称"
prop="name"
:rules="[{ required: true, message: '请输入中文名称' }]">
<el-input
v-model="addForm.name"
placeholder="请输入分组名称"></el-input>
</el-form-item>
<el-form-item
label="英文名称"
prop="nameEn"
:rules="[{ required: true, message: '请输入英文名称' }]">
<el-input
v-model="addForm.nameEn"
placeholder="请输入英文名称"></el-input>
</el-form-item>
<el-form-item label="排序">
<el-input
v-model="addForm.sort"
clearable
placeholder="请输入排序"></el-input>
</el-form-item>
<el-form-item label="备注">
<el-input
v-model="addForm.remark"
placeholder="请输入备注"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="addDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="submitAdd" :loading="addLoading">
确 定
</el-button>
</div>
</el-dialog>
<el-dialog
title="设置分组"
:visible.sync="setGroupDialogVisible"
:close-on-click-modal="false"
width="500px">
<el-select
v-model="groupingId"
placeholder="请选择分组"
clearable
style="width: 100%">
<el-option
v-for="item in groupsList"
:key="item.id"
:label="`${item.name} (${item.nameEn})`"
:value="item.id"></el-option>
</el-select>
<div slot="footer" class="dialog-footer">
<el-button @click="setGroupDialogVisible = false">取 消</el-button>
<el-button
type="primary"
@click="submitSetGroup"
:loading="setGroupLoading">
确 定
</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { get, post } from '@/common/api/axios'
// import CustomCascader from '@/common/components/base/CustomCascader.vue'
export default {
name: 'amazonAttributeGrouping',
components: {
// CustomCascader
},
data() {
return {
groupsList: [],
keyWord: '',
productTypeList: [],
amCateCascaders: [],
aliCatePathIds: [],
jsonSchema: {},
productType: '',
shopList: [],
shopId: '',
addDialogVisible: false,
addForm: {
cnName: '',
enName: '',
remark: '',
sort: ''
},
addLoading: false,
groupSearchForm: {
productType: ''
},
selectedAttr: [],
dataGroupForm: {},
setGroupDialogVisible: false,
setGroupLoading: false,
groupingId: '',
currentGroupId: 0,
cloneDataGroupForm: {},
selectedGroups: []
}
},
mounted() {
this.getAmazonShopList()
this.getGroupList()
},
computed: {
showJsonSchema() {
return (
Object.keys(this.jsonSchema?.properties || {}).map((item) => {
return {
name: item,
title: this.jsonSchema.properties[item].title,
description: this.jsonSchema.properties[item].description
}
}) || []
)
},
currentGroupPropertiesMap() {
const groupedProperties = {}
const result = {}
for (const key of Object.keys(this.dataGroupForm)) {
if (!this.dataGroupForm[key]) continue
result[this.dataGroupForm[key]] = {
...result[this.dataGroupForm[key]],
[key]: true
}
groupedProperties[key] = true
}
if (this.jsonSchema?.properties) {
const notGroupedProperties = Object.keys(this.jsonSchema.properties)
.filter((key) => !groupedProperties[key])
.reduce((acc, key) => {
acc[key] = true
return acc
}, {})
result[0] = notGroupedProperties
}
return result
},
visibleGroupList() {
return this.currentGroupPropertiesMap[this.currentGroupId] ?? {}
}
},
methods: {
selectAll() {
this.selectedAttr = this.showJsonSchema
},
selectNone() {
this.selectedAttr = []
},
selectedAttrStatus(item) {
const status = this.selectedAttr.findIndex((e) => e.name === item.name)
return status > -1
},
selectAttr(item) {
const status = this.selectedAttrStatus(item)
if (status) {
const index = this.selectedAttr.findIndex((e) => e.name === item.name)
this.selectedAttr.splice(index, 1)
} else {
this.selectedAttr.push(item)
}
},
submitSetGroup() {
this.selectedAttr.forEach((item) => {
this.$set(this.dataGroupForm, item.name, this.groupingId)
})
this.setGroupDialogVisible = false
this.selectedAttr = []
},
addGroup() {
this.addForm = {
name: '',
nameEn: '',
remark: '',
sort: ''
}
this.$nextTick(() => {
this.$refs.addFormRef.clearValidate()
})
this.addDialogVisible = true
},
editGroup(item) {
this.addForm = {
name: item.name,
nameEn: item.nameEn,
remark: item.remark,
id: item.id,
sort: item.sort
}
this.$nextTick(() => {
this.$refs.addFormRef.clearValidate()
})
this.addDialogVisible = true
},
setGrouping() {
if (this.selectedAttr.length === 0) {
this.$message.warning('请选择属性')
return
}
this.groupingId = ''
this.setGroupDialogVisible = true
},
async getGroupList() {
try {
const res = await post(
'amazonProductTypeGroup/list',
this.groupSearchForm
)
if (res.code !== 200) return
this.groupsList = [...res.data]
} catch (e) {
console.error(e)
}
},
async submitAdd() {
try {
await this.$refs.addFormRef.validate()
} catch (e) {
console.error(e)
return
}
const url = this.addForm.id
? 'amazonProductTypeGroup/update'
: 'amazonProductTypeGroup/add'
try {
const res = await post(url, {
...this.addForm
})
if (res.code !== 200) return
this.addDialogVisible = false
this.getGroupList()
} catch (e) {
console.error(e)
} finally {
this.addLoading = false
}
},
async searchCategory() {
if (!this.keyWord) return
const loading = this.$loading({
lock: true
})
try {
const find = this.shopList.find((item) => item.id === this.shopId)
const res = await get('amazon/category/getChildListByKeywords', {
keywords: this.keyWord,
marketplaceId: find.marketplaceId
})
if (res.code !== 200) return
this.productTypeList = res.data.map((item) => {
item.browsePathByName = item.browsePathByName?.split(',').join(' > ')
return item
})
} catch (e) {
console.error(e)
} finally {
loading.close()
}
},
productTypeChange(val) {
if (!val) return
const item = this.productTypeList.find(
(item) => item.browseNodeId === val
)
if (!item) return
const categoryPath = item.browsePathById
?.split(',')
?.slice(1)
?.map((e) => Number(e))
this.initCate(categoryPath || [], () => {
if (item.productType && categoryPath) {
this.aliCatePathIds = categoryPath
this.categoryTypeChange(item.productType, true)
} else {
this.jsonSchema = {}
this.groupList = []
}
})
},
getCateAttrs(id, categoryFullPath, callback) {
if (!id || id.length === 0) return
if (Array.isArray(id)) id = id[id.length - 1]
const loading = this.$loading({
lock: true
})
get('amazon/category/getAttributeByProductType', {
productType: id,
shopId: this.shopId
})
.then(async (res) => {
if (res.code !== 200) return
try {
const groupRes = await post(
'amazonProductTypeGroup/groupPropsList',
{
groupId: this.groupingId,
productType: id,
categoryFullPath: categoryFullPath
}
)
if (groupRes.code !== 200) return
const groupProps = groupRes.data
this.groupsList = groupProps
// eslint-disable-next-line node/no-callback-literal
callback && callback({ list: res.data, groupProps })
} catch (e) {
console.error(e)
}
})
.finally(() => {
loading.close()
})
},
categoryTypeChange(val) {
this.$nextTick(() => {
const nodes = this.$refs.amCateCascadersRef.getCheckedNodes()
let targetNode
if (this.aliCatePathIds) {
targetNode = nodes[nodes.length - 1]
}
this.dataGroupForm = {}
if (targetNode) {
const { data } = targetNode
this.getCateAttrs(
data.productTypeDefinitions,
data.browsePathByName,
({ list, groupProps }) => {
if (list) {
this.jsonSchema = list
groupProps.forEach((item) => {
item.propertyList.forEach((e) => {
this.$set(this.dataGroupForm, e.propertyNameEn, item.id)
})
})
this.cloneDataGroupForm = JSON.parse(
JSON.stringify(this.dataGroupForm)
)
} else {
this.jsonSchema = {}
this.dataGroupForm = {}
}
}
)
} else if (val) {
this.getCateAttrs(val, '', ({ list, groupProps }) => {
if (list) {
this.jsonSchema = list
groupProps.forEach((item) => {
item.propertyList.forEach((e) => {
this.$set(this.dataGroupForm, e.propertyNameEn, item.groupId)
})
})
} else {
this.jsonSchema = {}
this.dataGroupForm = {}
}
})
} else {
this.jsonSchema = {}
this.dataGroupForm = {}
}
})
},
customCascaderChange(val) {
console.log(val)
},
async initCate(ids, callback) {
const shopId = this.shopList.find(
(item) => item.id === this.shopId
)?.marketplaceId
const loading = this.$loading({
lock: true
})
const arr = [
get('amazon/category/getChildListByBrowseNodeId', {
marketplaceId: shopId
})
]
for (let i = 0; i < ids.length - 1; i++) {
arr.push(
get('amazon/category/getChildListByBrowseNodeId', {
browseNodeId: ids[i],
marketplaceId: shopId
})
)
}
Promise.all(arr)
.then((res) => {
const catearr = res[0].data.map((e) => {
return {
...e,
leaf: !e.childId
}
})
let arr1 = catearr
for (let i = 0; i < ids.length - 1; i++) {
for (const iterator of arr1) {
if (iterator.browseNodeId === ids[i]) {
iterator.children = res[i + 1].data.map((e) => {
return {
...e,
leaf: !e.childId
}
})
arr1 = iterator.children
}
}
}
this.amCateCascaders = catearr
callback && callback(catearr)
})
.finally(() => {
loading.close()
})
},
lazyLoad(node, resolve) {
if (node.level === 0) return
const shopId = this.shopList.find(
(item) => item.id === this.shopId
)?.marketplaceId
if (node.children && node.children.length > 0) {
resolve([])
} else {
get('amazon/category/getChildListByBrowseNodeId', {
browseNodeId: node.value,
marketplaceId: shopId
})
.then((res) => {
res.data.forEach((e) => {
e.leaf = !e.childId
})
resolve(res.data)
})
.catch((err) => {
console.error(err)
resolve([])
})
}
},
async customLazyLoad(node, callback) {
try {
const res = await get('amazon/category/getChildListByBrowseNodeId', {
browseNodeId: node.browseNodeId,
marketplaceId: this.shopId
})
if (res.code !== 200) return
callback(res.data)
} catch (e) {
console.error(e)
}
},
async getAmazonShopList() {
const loading = this.$loading({
lock: true
})
try {
const res = await get('business/shop/amazonList')
if (res.code !== 200) return
this.shopList = res.data
} catch (e) {
console.error(e)
} finally {
loading.close()
}
},
shopChange(val) {
if (!val) return
this.initCate([])
},
async saveGrouping() {
const nodes = this.$refs.amCateCascadersRef.getCheckedNodes()
let targetNode
if (this.aliCatePathIds) {
targetNode = nodes[nodes.length - 1]
}
const updatePropertyList = []
const delPropertyList = []
if (Object.keys(this.dataGroupForm).length > 0) {
Object.keys(this.dataGroupForm).forEach((item) => {
if (this.dataGroupForm[item] !== this.cloneDataGroupForm[item]) {
updatePropertyList.push({
propertyNameEn: item,
groupId: this.dataGroupForm[item] || undefined,
productType: targetNode.data.productTypeDefinitions,
categoryFullPath: targetNode.data.browsePathByName
})
} else {
updatePropertyList.push({
propertyNameEn: item,
groupId: this.dataGroupForm[item] || undefined,
productType: targetNode.data.productTypeDefinitions,
categoryFullPath: targetNode.data.browsePathByName
})
}
})
}
if (Object.keys(this.cloneDataGroupForm).length > 0) {
Object.keys(this.cloneDataGroupForm)
.filter((item) => {
return !this.dataGroupForm[item]
})
.forEach((item) => {
if (!this.dataGroupForm[item]) {
delPropertyList.push({
propertyNameEn: item,
productType: targetNode.data.productTypeDefinitions,
categoryFullPath: targetNode.data.browsePathByName,
groupId: this.cloneDataGroupForm[item]
})
}
})
}
try {
const res = await post('amazonProductGroupProperty/batchUpdate', {
updatePropertyList,
delPropertyList
})
if (res.code !== 200) return
this.selectedAttr = []
this.$message.success('设置分组成功')
} catch (e) {
console.error(e)
}
},
async deleteGroup(item) {
this.$confirm(
`确定要删除分组 "${item.name}" 吗?删除后该分组下的属性将移至全部分组。`,
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
).then(async () => {
try {
// 先获取该分组下的所有属性
const propertiesRes = await post(
'amazonProductTypeGroup/getGroupProperties',
{
groupId: item.id
}
)
if (propertiesRes.code === 200 && propertiesRes.data.length > 0) {
// 将该分组下的属性移至全部分组(groupId为0或null)
const updatePropertyList = propertiesRes.data.map((prop) => ({
propertyNameEn: prop.propertyNameEn,
groupId: null, // 移至全部分组
productType: prop.productType,
categoryFullPath: prop.categoryFullPath
}))
await post('amazonProductGroupProperty/batchUpdate', {
updatePropertyList,
delPropertyList: []
})
}
// 删除分组
const res = await post('amazonProductTypeGroup/delete', {
id: item.id
})
if (res.code !== 200) return
this.$message.success('删除分组成功,该分组下的属性已移至全部分组')
this.getGroupList()
// 如果当前选中的是被删除的分组,切换到全部分组
if (this.currentGroupId === item.id) {
this.currentGroupId = 0
}
} catch (e) {
console.error(e)
this.$message.error('删除分组失败')
}
})
},
async batchDeleteGroups() {
if (this.selectedGroups.length === 0) {
this.$message.warning('请选择要删除的分组')
return
}
this.$confirm(
`确定要批量删除选中的 ${this.selectedGroups.length} 个分组吗?删除后这些分组下的属性将移至全部分组。`,
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
).then(async () => {
try {
let allProperties = []
const groups = this.groupsList.filter((item) =>
this.selectedGroups.includes(item.id)
)
if (groups.length > 0) {
allProperties = groups.map((e) => e.propertyList).flat()
}
if (allProperties.length > 0) {
allProperties.forEach((item) => {
this.$set(this.dataGroupForm, item.propertyNameEn, '')
})
}
const res = await get('amazonProductTypeGroup/delete', {
ids: this.selectedGroups.join(',')
})
if (res.code !== 200) return
this.$message.success('批量删除分组成功')
this.getGroupList()
this.selectedGroups = []
if (this.selectedGroups.includes(this.currentGroupId)) {
this.currentGroupId = 0
}
} catch (e) {
console.error(e)
this.$message.error('批量删除分组失败')
}
})
},
toggleGroupSelection(groupId) {
const index = this.selectedGroups.indexOf(groupId)
if (index > -1) {
this.selectedGroups.splice(index, 1)
} else {
this.selectedGroups.push(groupId)
}
},
selectAllGroups() {
this.selectedGroups = this.groupsList.map((group) => group.id)
},
clearAllGroups() {
this.selectedGroups = []
},
resetGrouping() {
this.dataGroupForm = {}
}
}
}
</script>
<style lang="scss" scoped>
.amazon-attribute-grouping {
height: 100%;
overflow: hidden;
display: flex;
gap: 10px;
}
.group-status-box {
overflow: auto;
}
.left-group-status {
width: 300px;
height: 100%;
border-right: 2px solid #e5e5e5;
padding-right: 10px;
display: flex;
flex-direction: column;
.add-group {
text-align: right;
margin-bottom: 10px;
.group-select-actions {
margin-top: 5px;
text-align: center;
.selection-info {
display: block;
font-size: 12px;
color: #409eff;
margin-top: 3px;
}
}
}
}
.right-group-content {
flex: 1;
overflow: hidden;
display: flex;
flex-direction: column;
gap: 10px;
.attribute-box {
flex: 1;
overflow: hidden;
border: 1px solid #eee;
display: flex;
flex-direction: column;
padding: 6px;
.attribute-content {
flex: 1;
overflow: hidden;
}
.attribute-footer {
text-align: right;
}
}
}
.group-status-item {
cursor: pointer;
font-size: 14px;
border-radius: 4px;
border: 1px solid #e5e5e5;
margin-bottom: 6px;
padding: 6px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
height: 60px;
.operate-group {
position: absolute;
right: 2px;
bottom: 0;
background-color: #fff;
border-radius: 4px;
}
&.active {
border-color: #67c23a;
color: #67c23a;
border-width: 2px;
font-weight: bold;
}
.group-checkbox {
position: absolute;
left: 8px;
top: 8px;
z-index: 1;
.custom-checkbox {
width: 14px;
height: 14px;
border: 1px solid #dcdfe6;
border-radius: 2px;
background-color: #fff;
cursor: pointer;
position: relative;
transition: all 0.3s;
&:hover {
border-color: #409eff;
}
&.active {
background-color: #409eff;
border-color: #409eff;
&::after {
content: '';
position: absolute;
top: 0px;
left: 4px;
width: 4px;
height: 8px;
border: 2px solid #fff;
border-top: none;
border-left: none;
transform: rotate(45deg);
}
}
}
}
}
.category-item {
display: flex;
align-items: center;
gap: 10px;
&:not(:last-child) {
margin-bottom: 10px;
}
}
.category-title {
width: 60px;
text-align: right;
font-size: 14px;
color: #606266;
}
.group-name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.attribute {
display: grid;
grid-template-columns: repeat(4, minmax(100px, 1fr));
gap: 10px;
/* padding: 10px; */
}
.attribute-item {
border: 1px solid #eee;
border-radius: 4px;
padding: 10px;
display: flex;
align-items: center;
gap: 5px;
position: relative;
.select-group-icon {
position: absolute;
left: 2px;
top: 2px;
width: 10px;
height: 10px;
}
.check-icon {
width: 16px;
height: 16px;
border: 1px solid #eee;
box-shadow: 0px 2px 3px 0px rgba(0, 0, 0, 0.4) inset;
border-radius: 50%;
cursor: pointer;
position: relative;
&.active {
background: #4168ff;
position: relative;
border-color: #4168ff;
}
&.active::after {
position: absolute;
content: '';
top: 0px;
left: 4px;
width: 4px;
height: 8px;
border-width: 2px;
border-style: solid;
border-color: transparent #fff #fff transparent;
transform: rotate(45deg) scale(0.8);
}
}
}
.visible-item-properties {
display: none;
}
.attribute-item-title {
flex: 1;
font-size: 14px;
color: #606266;
display: flex;
align-items: center;
overflow: hidden;
gap: 2px;
.attribute-item-title-text {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.attribute-item-content {
width: 100px;
}
.attribute-header {
text-align: right;
margin-bottom: 10px;
}
.attribute-item-description {
font-size: 12px;
color: #999;
}
</style>
<style lang="scss">
.attribute-item-select {
.el-input__inner {
color: #e6a23c;
font-weight: 500;
}
}
.custom-popper-select {
.el-select-dropdown__item {
border-bottom: 1px solid #ddd;
height: unset;
}
}
.is-selected {
color: #409eff !important;
font-weight: bold;
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment