
主页面 父组件 index.vue
<!-- 产品信息管理 -->
<template>
<div class="app-container">
<el-row :gutter="20">
<el-col :xs="9" :sm="6" :md="5" :lg="5" :xl="5">
<enterpriseTree ref="tree" @change="handleTreeNodeChange"></enterpriseTree>
</el-col>
<el-col :xs="15" :sm="18" :md="19" :lg="19" :xl="19">
<div>
<div class="head-query">
<el-form
ref="queryForm"
class="query-form"
:model="query"
label-width="70px"
inline
>
<el-form-item prop="productName" label="产品名称">
<el-input
v-model.trim="query.productName"
type="text"
placeholder="请输入产品名称"
maxlength="50"
show-word-limit
clearable
/>
</el-form-item>
<el-form-item prop="modelName" label="型号名称">
<el-input
v-model.trim="query.modelName"
type="text"
placeholder="请输入型号名称"
maxlength="50"
show-word-limit
clearable
/>
</el-form-item>
<el-form-item prop="editionName" label="版本名称">
<el-input
v-model.trim="query.editionName"
type="text"
placeholder="请输入版本名称"
maxlength="50"
show-word-limit
clearable
/>
</el-form-item>
<el-form-item prop="description" label="备注">
<el-input
v-model.trim="query.description"
type="text"
placeholder="请输入备注"
maxlength="50"
show-word-limit
clearable
/>
</el-form-item>
</el-form>
<div class="query-btn">
<el-button size="mini" type="primary" icon="el-icon-search" @click="handleQuery">查询</el-button>
<el-button size="mini" type="info" icon="el-icon-refresh-left" @click="resetQuery">重置</el-button>
</div>
</div>
<div>
<el-button size="mini" type="primary" @click="addRowProduct">
新增产品
</el-button>
</div>
</div>
<el-table
class="productTable"
ref="table"
v-loading="loading"
:data="tableData"
:row-class-name="iconModel"
header-align="center"
>
<el-table-column label="序号" type="index" width="50" />
<el-table-column type="expand" width="30">
<template slot-scope="scope">
<div class="ml50" v-if="scope.row.modelList && scope.row.modelList.length > 0">
<el-table :ref="'tableModel'+scope.row.id" :data="scope.row.modelList" :show-header="false" :row-class-name="iconEdition">
<el-table-column type="expand" width="30">
<template slot-scope="scope">
<div class="ml30" v-if="scope.row.editionList && scope.row.editionList.length > 0">
<el-table :data="scope.row.editionList" :show-header="false" :row-class-name="iconEdition">
<el-table-column prop="editionName" label="型号名称" min-width="180">
<template slot-scope="scope">
<el-input v-model.trim="scope.row.editionName" v-if="scope.row.editEdition" maxlength="100" show-word-limit clearable></el-input>
<div v-else>
<tooltip-over :content="scope.row.editionName" :refName="'tipEdition' + scope.row.id"></tooltip-over>
</div>
</template>
</el-table-column>
<el-table-column prop="type" label="类型" width="50">
<template slot-scope="scope">
<span v-if="scope.row.type == 3">版本</span>
</template>
</el-table-column>
<el-table-column label="备注" prop="description">
<template slot-scope="scope">
<el-input v-model.trim="scope.row.description" v-if="scope.row.editEdition" maxlength="200" show-word-limit clearable></el-input>
<div v-else>
<tooltip-over :content="scope.row.description" :refName="'tipEditionDesc' + scope.row.id"></tooltip-over>
</div>
</template>
</el-table-column>
<el-table-column label="操作" width="170">
<template slot-scope="scope">
<div v-if="!scope.row.editEdition">
<el-button type="text" size="small" :disabled="scope.row.isAllow" @click="editRowEdition(scope.$index,scope.row)"> 修改 </el-button>
<el-button type="text" size="small" :disabled="scope.row.isAllow" @click="setDelEdition(scope.row)"> 删除 </el-button>
</div>
<div v-else>
<el-button size="mini" @click="saveRowEdition(scope.$index, scope.row)"> 保存 </el-button>
<el-button size="mini" @click="cancelRowEdition(scope.$index, scope.row)"> 取消 </el-button>
</div>
</template>
</el-table-column>
</el-table>
</div>
</template>
</el-table-column>
<el-table-column prop="modelName" label="型号名称" min-width="180">
<template slot-scope="scope">
<el-input v-model.trim="scope.row.modelName" v-if="scope.row.editModel" maxlength="100" show-word-limit clearable></el-input>
<div v-else>
<tooltip-over :content="scope.row.modelName" :refName="'tipModel' + scope.row.id"></tooltip-over>
</div>
</template>
</el-table-column>
<el-table-column prop="type" label="类型" width="50">
<template slot-scope="scope">
<span v-if="scope.row.type == 2">型号</span>
</template>
</el-table-column>
<el-table-column label="备注" prop="description">
<template slot-scope="scope">
<el-input v-model.trim="scope.row.description" v-if="scope.row.editModel" maxlength="200" show-word-limit clearable></el-input>
<div v-else>
<tooltip-over :content="scope.row.description" :refName="'tipModelDesc' + scope.row.id"></tooltip-over>
</div>
</template>
</el-table-column>
<el-table-column label="操作" width="170">
<template slot-scope="scope">
<div v-if="!scope.row.editModel">
<el-button type="text" size="small" :disabled="scope.row.isAllow" @click="editRowModel(scope.$index,scope.row)"> 修改 </el-button>
<el-button type="text" size="small" :disabled="scope.row.isAllow" @click="setDelModel(scope.row)"> 删除 </el-button>
<el-button type="text" size="small" :disabled="scope.row.isAllow" @click="addRowEdition(scope.$index,scope.row)"> 添加版本 </el-button>
</div>
<div v-else>
<el-button size="mini" @click="saveRowModel(scope.$index, scope.row)">保存</el-button>
<el-button size="mini" @click="cancelRowModel(scope.$index, scope.row)">取消</el-button>
</div>
</template>
</el-table-column>
</el-table>
</div>
</template>
</el-table-column>
<el-table-column prop="productName" label="产品名称/型号名称/版本名称" min-width="180">
<template slot-scope="scope">
<el-input v-model.trim="scope.row.productName" v-if="scope.row.editProduct" maxlength="100" show-word-limit clearable></el-input>
<div v-else>
<tooltip-over :content="scope.row.productName" :refName="'tipProduct' + scope.row.id"></tooltip-over>
</div>
</template>
</el-table-column>
<el-table-column prop="type" label="类型" width="50">
<template slot-scope="scope">
<span v-if="scope.row.type == 1">产品</span>
</template>
</el-table-column>
<el-table-column label="备注" prop="description">
<template slot-scope="scope">
<el-input v-model.trim="scope.row.description" v-if="scope.row.editProduct" maxlength="200" show-word-limit clearable></el-input>
<div v-else>
<tooltip-over :content="scope.row.description" :refName="'tipProductDesc' + scope.row.id"></tooltip-over>
</div>
</template>
</el-table-column>
<el-table-column label="操作" width="170">
<template slot-scope="scope">
<div v-if="!scope.row.editProduct">
<el-button type="text" size="small" :disabled="scope.row.isAllow" @click="editRowProduct(scope.$index)"> 修改 </el-button>
<el-button type="text" size="small" :disabled="scope.row.isAllow" @click="setDelProduct(scope.row)"> 删除 </el-button>
<el-button type="text" size="small" :disabled="scope.row.isAllow" @click="addRowModel(scope.$index,scope.row)"> 添加型号 </el-button>
</div>
<div v-else>
<el-button size="mini" @click="saveRowProduct(scope.$index, scope.row)">保存</el-button>
<el-button size="mini" @click="cancelRowProduct(scope.$index)">取消</el-button>
</div>
</template>
</el-table-column>
</el-table>
<el-pagination
:page-size.sync="query.size"
:total="total"
:current-page.sync="query.page"
style="margin-top: 8px;"
:popper-append-to-body="false"
layout="total, prev, pager, next, sizes,jumper"
@size-change="sizeChangeHandler"
@current-change="pageChangeHandler"
/>
</el-col>
</el-row>
<el-dialog
class="product-add-dialog"
append-to-body
title="新增产品"
:visible.sync="visible"
width="520px"
@closed="onRest"
:close-on-click-modal="false"
>
<el-form ref="form" inline :model="form" :rules="rules" size="small" label-width="80px">
<el-form-item label="企业名称" prop="manufacturerId">
<el-input
v-model="form.manufacturerName"
disabled
style="width: 380px;"
/>
</el-form-item>
<el-form-item label="产品名称" prop="productName">
<el-input
v-model="form.productName"
placeholder="请输入产品名称"
maxlength="100"
show-word-limit
clearable
style="width: 380px;"
/>
</el-form-item>
<el-form-item label="备注" prop="description">
<el-input v-model="form.description" maxlength="200" placeholder="请输入备注" style="width: 380px;" rows="4" type="textarea" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="text" @click="onRest">取消</el-button>
<el-button :loading="confirmLoading" type="primary" @click="onConfirm">确认</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import tooltipOver from './module/tooltipOver';
import enterpriseTree from './module/enterpriseTree';
import { cloneDeep } from "lodash-es";
import { getProductList,delProduct,delModel,delEdition,editProduct,editModel,editEdition,addProduct,addModel,addEdition } from '@/api/enAndProManagement/product.js';
export default {
name: "product",
components: {
enterpriseTree,
tooltipOver,
},
data() {
return {
loading: false,
total: 0,
tableData: [],
query: {
manufacturerId: '',
productName: '',
modelName: '',
editionName: '',
description: '',
page: 1,
size: 10,
sort: 'id,desc'
},
cobyObj:{},
visible:false,
confirmLoading:false,
form: {
manufacturerName: '',
manufacturerId: '',
productName: '',
description: '',
},
rules: {
manufacturerId: [{ required: true, message: '请输入企业名称', trigger: 'blur' }],
productName: [{ required: true, message: '请输入产品名称', trigger: 'blur' }]
},
};
},
created() {
this.handleQuery();
},
methods: {
editRowProduct(index){
let nowArr = this.tableData.filter(item => item.editProduct);
if (nowArr.length > 0) {
this.$message.error("请修改完成后再次操作");
return false;
}else{
this.cobyObj = cloneDeep(this.tableData[index]);
this.tableData[index].editProduct = true;
this.setForbid(index);
}
},
setForbid(index){
this.tableData.map(item => {
item.isAllow = true;
if(item.modelList && item.modelList.length > 0){
item.modelList.map(val => {
val.isAllow = true;
if(val.editionList && val.editionList.length > 0){
val.editionList.map(node => node.isAllow = true);
}
});
}
})
},
setAllow(){
this.tableData.map(item => {
item.isAllow = false;
if(item.modelList && item.modelList.length > 0){
item.modelList.map(val => {
val.isAllow = false;
if(val.editionList && val.editionList.length > 0){
val.editionList.map(node => node.isAllow = false);
}
});
}
})
},
cancelRowProduct(index) {
this.tableData[index].editProduct = false;
this.$set(this.tableData, index, this.cobyObj);
this.setAllow();
this.cobyObj = {};
},
saveRowProduct(index,row){
if(!row.productName){
this.$message.error("产品名称不能为空");
return false;
}
this.tableData[index].editProduct = false;
let params = {
manufacturerId: row.manufacturerId,
id: row.id,
productName: row.productName,
description: row.description,
}
this.loading = true;
editProduct(params).then(res => {
if(res.code == 200){
this.$message.success(res.msg);
this.getList();
}else{
this.$message.error(res.msg);
}
this.loading = false;
}).catch(() => {
this.loading = false;
this.cancelRowProduct(index);
});
},
addRowModel(index,row){
this.tableData[index].modelList.unshift({
editModel: true,
description: '',
manufacturerId: row.manufacturerId,
productId: row.id,
modelName: '',
type:2,
});
this.setForbid(index);
this.$refs.table.toggleRowExpansion(row, true);
},
editRowModel(index,row){
this.cobyObj = cloneDeep(row);
row.editModel = true;
this.setForbid(index);
},
cancelRowModel(index,row){
if(row.id){
this.tableData.forEach((item,i) => {
if(item.id == row.productId){
item.modelList.forEach((val,j) => {
if(row.id == val.id){
this.$set(item.modelList,j,this.cobyObj);
}
})
}
})
}else{
this.tableData.forEach((item,i) => {
if(item.id == row.productId){
item.modelList.splice(index, 1);
}
})
}
this.setAllow();
this.cobyObj = {};
console.log('型号添加编辑2-取消 tableData ',this.tableData);
},
saveRowModel(index,row){
if(!row.modelName){
this.$message.error("型号名称不能为空");
return false;
}
row.editModel = false;
let params = {
manufacturerId: row.manufacturerId,
productId: row.productId,
modelName: row.modelName,
description: row.description,
}
let axiosUrl = addModel;
if(row.id){
params.id = row.id;
axiosUrl = editModel;
}
this.loading = true;
axiosUrl(params).then(res => {
if(res.code == 200){
this.$message.success(res.msg);
this.getList();
}else{
this.$message.error(res.msg);
}
this.loading = false;
}).catch(() => {
this.loading = false;
this.cancelRowModel(index,row);
});
},
addRowEdition(index,row){
console.log('版本添加3',row);
row.editionList.unshift({
editEdition: true,
manufacturerId: row.manufacturerId,
productId: row.productId,
productModelId: row.id,
description: '',
editionName: '',
type:3,
});
this.setForbid(index);
let refName = 'tableModel' + row.productId;
this.$refs[refName].toggleRowExpansion(row, true);
},
editRowEdition(index,row){
this.cobyObj = cloneDeep(row);
row.editEdition = true;
this.setForbid(index);
},
cancelRowEdition(index,row){
if(row.id){
row.editEdition = false;
row.editionName = this.cobyObj.editionName;
row.description = this.cobyObj.description;
}else{
this.tableData.forEach((item,i) => {
if(item.id == row.productId && item.modelList.length > 0){
item.modelList.forEach((val,j) => {
if(val.id == row.productModelId){
val.editionList.splice(index, 1);
}
})
}
})
}
this.setAllow();
this.cobyObj = {};
},
saveRowEdition(index,row){
if(!row.editionName){
this.$message.error("版本名称不能为空");
return false;
}
row.editEdition = false;
let params = {
manufacturerId: row.manufacturerId,
productId: row.productId,
productModelId: row.productModelId,
editionName: row.editionName,
description: row.description,
}
let axiosUrl = addEdition;
if(row.id){
params.id = row.id;
axiosUrl = editEdition;
}
this.loading = true;
axiosUrl(params).then(res => {
if(res.code == 200){
this.$message.success(res.msg);
this.getList();
}else{
this.$message.error(res.msg);
}
this.loading = false;
}).catch(() => {
this.loading = false;
this.cancelRowEdition(index,row);
});
},
handleQuery() {
this.query.page = 1;
this.getList();
},
resetQuery() {
this.$refs.queryForm.resetFields();
this.handleQuery();
},
getList() {
this.loading = true;
const params = {
manufacturerId: this.query.manufacturerId,
productName: this.query.productName,
modelName: this.query.modelName,
editionName: this.query.editionName,
description: this.query.description,
page: this.query.page - 1,
size: this.query.size,
sort: this.query.sort,
}
console.log(params);
getProductList(params).then(res => {
if (res.code == 200) {
this.tableData = res.data.list.map(item => {
item.editProduct = false;
item.isAllow = false;
if(item.modelList && item.modelList.length > 0){
item.modelList.map(val => {
val.editModel = false;
val.isAllow = false;
if(val.editionList && val.editionList.length > 0){
val.editionList.map(node => {
node.editEdition = false;
node.isAllow = false;
return node;
});
}
return val;
});
}
return item;
});
this.total = res.data.total;
}else{
this.$message.error(res.msg);
}
this.loading = false;
})
.finally(() => {
this.loading = false;
});
},
pageChangeHandler(e) {
console.log('当前页改变',e);
this.query.page = e;
this.getList();
},
sizeChangeHandler(e) {
this.query.size = e;
this.query.page = 1;
this.getList();
},
handleTreeNodeChange(data) {
this.query.manufacturerId = data.id;
this.form.manufacturerName = data.name;
this.form.manufacturerId = data.id;
this.handleQuery();
},
iconModel({ row }) {
if(row.modelList== null || row.modelList.length == 0){
return "icon-no";
}
},
iconEdition({ row }) {
if(row.editionList== null || row.editionList.length == 0){
return "icon-no";
}
},
setDelProduct(row) {
this.$confirm(`是否确认删除?`, "删除", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.loading = true;
let params = {
id: row.id,
productName:row.productName,
manufacturerId:row.manufacturerId,
}
delProduct(params).then(res => {
if (res.code == 200) {
this.$message.success("删除成功");
this.getList();
} else {
this.$message.error(res.msg);
}
this.loading = false;
}).catch(() => {
this.loading = false;
});
});
},
setDelModel(row) {
this.$confirm(`是否确认删除?`, "删除", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.loading = true;
let params = {
id: row.id,
manufacturerId:row.manufacturerId,
productId:row.productId,
modelName:row.modelName,
}
delModel(params).then(res => {
if (res.code == 200) {
this.$message.success("删除成功");
this.getList();
} else {
this.$message.error(res.msg);
}
this.loading = false;
}).catch(() => {
this.loading = false;
});
});
},
setDelEdition(row) {
this.$confirm(`是否确认删除?`, "删除", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.loading = true;
let params = {
id: row.id,
manufacturerId:row.manufacturerId,
productId:row.productId,
productModelId:row.productModelId,
editionName:row.editionName,
}
delEdition(params).then(res => {
if (res.code == 200) {
this.$message.success(res.msg);
this.getList();
} else {
this.$message.error(res.msg);
}
this.loading = false;
}).catch(() => {
this.loading = false;
});
});
},
addRowProduct(){
this.visible = true;
},
onRest(){
this.visible = false;
this.confirmLoading = false;
this.$refs.form.resetFields();
},
onConfirm(){
this.$refs.form.validate((valid, obj) => {
if (valid) {
let params = {
manufacturerId: this.form.manufacturerId,
productName: this.form.productName,
description: this.form.description,
}
this.confirmLoading = true;
addProduct(params).then(res => {
if (res.code == 200) {
this.$message.success(res.msg);
this.handleQuery();
this.onRest();
} else {
this.$message.error(res.msg);
}
}).finally(() => {
this.confirmLoading = false;
})
}
})
},
},
};
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.head-query {
::v-deep {
.el-form.query-form .el-form-item .el-form-item__label {
font-size: 12px;
font-weight: normal;
color: #3e3b3b;
display: inline-block;
text-align: right;
padding-right: 5px;
}
.el-form.el-form--inline .el-form-item.el-form-item--small{
.el-input--suffix .el-input__inner{
padding-right: 65px;
}
}
}
.query-btn {
display: flex;
align-items: center;
justify-content: end;
}
}
.productTable{
::v-deep .el-table__cell.el-table__expanded-cell{
padding: 0 0 !important;
}
::v-deep .el-input--suffix .el-input__inner{
padding-right: 75px;
}
}
::v-deep .el-table.productTable,th,tr,td{
margin:0;
}
::v-deep .el-table.productTable .el-table__row td div{
text-align:left;
}
.ml50{
margin-left: 50px;
}
.ml30{
margin-left: 30px;
}
::v-deep .icon-no .el-table__cell .cell .el-table__expand-icon {
display: none;
}
.product-add-dialog{
::v-deep {
.el-form.el-form--inline .el-form-item.el-form-item--small{
.el-input--suffix .el-input__inner{
padding-right: 75px;
}
}
}
}
</style>
左侧树子组件 enterpriseTree.vue
<template>
<div v-loading="loading">
<div class="search-top">
<label class="search-label">企业名称</label>
<el-input
class="search-input"
placeholder="请输入企业名称"
v-model.trim="filterText"
maxlength="50"
clearable
show-word-limit
size="small"
@clear="handleClear"
></el-input>
</div>
<div class="tree-node" id="tree">
<div v-for="node in treeData" :key="node.id">
<div :class="['tree-node-content', node.isClick ? 'is-current' : '']" @click="handleNodeClick(node)">
<span class="tree-node-label">
<span class="span-label" v-if="node.name.length < 16">{{ node.name }}</span>
<el-tooltip
popper-class="force-orgTree-tooltip-content"
class="item"
effect="dark"
:content="node.name"
:open-delay="500"
placement="top-start"
v-else
>
<span class="span-label">{{ node.name }}</span>
</el-tooltip>
<em v-if="node.isRegister > 0">({{ node.isRegister }})</em>
</span>
</div>
</div>
</div>
</div>
</template>
<script>
import { cloneDeep } from "lodash-es";
import { getEnterpriseList } from '@/api/enAndProManagement/product.js';
export default {
data() {
return {
filterText: "",
treeData: [],
loading: false,
copyTreeData: [],
};
},
watch: {
filterText(val) {
this.treeData = this.copyTreeData.filter(item => {
if(item.name.includes(val)){
return item;
}
});
},
},
created() {
this.getList();
},
methods: {
getList(){
let params = {
name: this.filterText,
}
this.loading = true;
getEnterpriseList(params).then(res => {
if(res.code == 200){
this.treeData = res.data.map(item => {
item.isClick = false;
return item;
});
this.copyTreeData = cloneDeep(this.treeData);
if(this.treeData.length > 0){
this.treeData[0].isClick = true;
this.$emit("change", this.treeData[0]);
}
}
this.loading = false;
}).finally(()=>{
this.loading = false;
})
},
handleClear() {
this.$nextTick(() => {
if (this.defaultExpandedKeys.length) {
this.$refs.tree.setCheckedKeys(this.defaultExpandedKeys);
}
});
},
filterNode(value, data) {
if (!value) return true;
return data.label.indexOf(value) !== -1;
},
handleNodeClick(data) {
this.treeData.map(item => {
if(data.id == item.id){
item.isClick = true;
}else{
item.isClick = false;
}
})
this.$emit("change", data);
},
clearNodeStyles() {
this.treeData.map(item => item.isClick = false);
},
},
};
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.search-label{
font-size: 12px;
font-weight: normal;
color: #3e3b3b;
display: inline-block;
text-align: right;
padding-right: 5px;
}
.search-top{
margin-bottom: 10px;
}
.search-input{
width: 190px;
::v-deep .el-input__inner{
padding-right: 65px;
}
}
.tree-node{
white-space: nowrap;
outline: none;
height: calc(100vh - 180px);
overflow-y: auto;
.tree-node-content{
display: flex;
align-items: center;
height: 30px;
cursor: pointer;
padding-left: 10px;
&:hover{
background-color: #f5f7fa;
}
.tree-node-label {
display: inline-flex;
justify-content: flex-start;
align-items: center;
width: 100%;
font-size: 14px;
.span-label {
display: inline-block;
max-width: 85%;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-all;
}
em {
font-style: normal;
padding: 4px;
}
}
}
}
.is-current{
color: #1890ff;
background-color: #edf6ff;
}
.treeBox li{
font-size: 12px;
}
.force-orgTree-tooltip-content {
width: 400px;
}
::v-deep .el-tree .is-current .tree-node-label{
color: #1890ff;
}
</style>
表格内超出省略提示信息 子组件 tooltipOver.vue
<template>
<div class="text-tooltip">
<el-tooltip class="item" effect="dark" :disabled="isShowTooltip" :content="content" :placement="placement">
<p class="over-flow" :class="className" @mouseover="onMouseOver(refName)">
<span :ref="refName">{{content||'-'}}</span>
</p>
</el-tooltip>
</div>
</template>
<script>
export default {
name: 'textTooltip',
props: {
content: {
type: String,
default: () => {
return ''
}
},
placement: {
type: String,
default: () => {
return 'top'
}
},
className: {
type: String,
default: () => {
return ''
}
},
refName: {
type: String,
default: () => {
return ''
}
}
},
data() {
return {
isShowTooltip: true
}
},
methods: {
onMouseOver(str) {
let parentWidth = this.$refs[str].parentNode.offsetWidth;
let contentWidth = this.$refs[str].offsetWidth;
if (contentWidth>parentWidth) {
this.isShowTooltip = false;
} else {
this.isShowTooltip = true;
}
}
}
}
</script>
<style lang="scss" scoped>
.over-flow {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.wid190 {
width: 100%;
}
p{
margin: 0;
}
</style>