bugfix
This commit is contained in:
parent
9bbaf61467
commit
285c9409d5
@ -84,8 +84,35 @@ export function reqSearchByMangement(data){
|
||||
return request({
|
||||
url: '/product/publish_product_search.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
headers: { 'Content-Type': 'application/js1on' },
|
||||
data
|
||||
|
||||
})
|
||||
}
|
||||
//编辑商品
|
||||
export function reqEditProduct(data){
|
||||
return request({
|
||||
url: '/product/publish_product_update.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
data
|
||||
})
|
||||
}
|
||||
//编辑非图片字段
|
||||
export function reqEditProductNoImg(data){
|
||||
return request({
|
||||
url: '/product/publish_product_update.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/js1on' },
|
||||
data
|
||||
})
|
||||
}
|
||||
//搜索
|
||||
export function reqSearch(data){
|
||||
return request({
|
||||
url: '/product/global_search.dspy',
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/js1on' },
|
||||
data
|
||||
})
|
||||
}
|
||||
@ -65,24 +65,6 @@ export const constantRoutes = [
|
||||
component: () => import('@/views/beforeLogin/index.vue'),
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
alwaysShow: true,
|
||||
path: "/productMangement",
|
||||
component:Layout,
|
||||
name: "productMangement",
|
||||
redirect: "/productMangement/index",
|
||||
meta: { fullPath: "/productMangement", title: "商品管理", noCache: true, icon: 'el-icon-s-home' },
|
||||
children: [
|
||||
{
|
||||
path: "index",
|
||||
component: () => import("@/views/customer/productMangement/productList/index.vue"),
|
||||
name: "productList",
|
||||
meta: { title: "商品清单", fullPath: "/productMangement/index" },
|
||||
},
|
||||
|
||||
]
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
path: '/wxPage',
|
||||
@ -182,6 +164,7 @@ export const constantRoutes = [
|
||||
meta: { title: "注册" },
|
||||
},
|
||||
{
|
||||
hidden: true,
|
||||
path: "/ncmatchHome",
|
||||
component: () => import("@/views/homePage/ncmatch/index.vue"),
|
||||
name: "ncmatchHome",
|
||||
@ -202,6 +185,13 @@ export const constantRoutes = [
|
||||
hidden: true,
|
||||
meta: { title: "算力供需广场", fullPath: "/ncmatch/supplyAndDemandSquare" },
|
||||
},
|
||||
{
|
||||
path: "search",
|
||||
component: () => import("@/views/homePage/ncmatch/searchBox/index.vue"),
|
||||
name: "search",
|
||||
hidden: true,
|
||||
meta: { title: "产品查询", fullPath: "/ncmatch/searchBox" },
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -311,6 +301,85 @@ export const asyncRoutes = [
|
||||
// name: 'productHome',
|
||||
// meta: {title: "概览", fullPath: "/productHome", noCache: true}
|
||||
// },
|
||||
{
|
||||
path: "/approveMangement",
|
||||
component:Layout,
|
||||
name: "approveMangement",
|
||||
redirect: "/approveMangement/index",
|
||||
meta: { fullPath: "/approveMangement", title: "审核管理", noCache: true, icon: 'el-icon-s-home' },
|
||||
children: [
|
||||
{
|
||||
path: "pendingPro",
|
||||
component: () => import("@/views/customer/approveMangement/pendingPro.vue"),
|
||||
name: "pendingPro",
|
||||
meta: { title: "待审清单", fullPath: "/approveMangement/index" },
|
||||
},
|
||||
{
|
||||
path: "approvedPro",
|
||||
component: () => import("@/views/customer/approveMangement/approvedPro.vue"),
|
||||
name: "approvedPro",
|
||||
meta: { title: "已审清单", fullPath: "/approveMangement/approvedPro" },
|
||||
},
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
path: "/productMangement",
|
||||
component:Layout,
|
||||
name: "productMangement",
|
||||
redirect: "/productMangement/index",
|
||||
meta: { fullPath: "/productMangement", title: "商品管理", noCache: true, icon: 'el-icon-s-home' },
|
||||
children: [
|
||||
{
|
||||
path: "index",
|
||||
component: () => import("@/views/customer/productMangement/productList/index.vue"),
|
||||
name: "productList",
|
||||
meta: { title: "商品发布清单", fullPath: "/productMangement/index" },
|
||||
},
|
||||
{
|
||||
path: "rejectedPro",
|
||||
component: () => import("@/views/customer/productMangement/rejectedPro/index.vue"),
|
||||
name: "rejectedPro",
|
||||
meta: { title: "商品未通过清单", fullPath: "/productMangement/index" },
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
path: "/menuMangement",
|
||||
component:Layout,
|
||||
name: "menuMangement",
|
||||
redirect: "/menuMangement/index",
|
||||
meta: { fullPath: "/menuMangement", title: "菜单管理", noCache: true, icon: 'el-icon-s-home' },
|
||||
children: [
|
||||
{
|
||||
path: "index",
|
||||
component: () => import("@/views/operation/menuMangement/index.vue"),
|
||||
name: "menuMangement",
|
||||
meta: { title: "菜单管理", fullPath: "/menuMangement/index" },
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
path: "/demandMangement",
|
||||
component:Layout,
|
||||
name: "demandMangement",
|
||||
redirect: "/demandMangement/index",
|
||||
meta: { fullPath: "/demandMangement", title: "需求管理", noCache: true, icon: 'el-icon-s-home' },
|
||||
children: [
|
||||
{
|
||||
path: "index",
|
||||
component: () => import("@/views/customer/demand/demandList.vue"),
|
||||
name: "demandList",
|
||||
meta: { title: "需求发布清单", fullPath: "/demandMangement/index" },
|
||||
},
|
||||
{
|
||||
path: "rejectDemand",
|
||||
component: () => import("@/views/customer/demand/rejectDemand.vue"),
|
||||
name: "rejectDemand",
|
||||
meta: { title: "需求未通过清单", fullPath: "/demandMangement/rejectDemand" },
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
path: getHomePath() == '/ncmatchHome/index' ? "/ncmatchHome" : "/homePage",
|
||||
|
||||
6
f/web-kboss/src/utils/eventBus.js
Normal file
6
f/web-kboss/src/utils/eventBus.js
Normal file
@ -0,0 +1,6 @@
|
||||
import Vue from 'vue'
|
||||
|
||||
// 创建事件总线实例
|
||||
const eventBus = new Vue()
|
||||
|
||||
export default eventBus
|
||||
@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<div>
|
||||
<commonBox :role="role"></commonBox>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
//运营|用户 查找商品|需求
|
||||
import commonBox from '@/views/customer/productMangement/commonBox/index.vue';
|
||||
|
||||
export default {
|
||||
name: 'productList',
|
||||
components: { commonBox },
|
||||
data() {
|
||||
return {
|
||||
role:{
|
||||
role_type:'customer',
|
||||
audit_status:'approved'
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<div>
|
||||
<commonBox :role="role"></commonBox>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
//运营|用户 查找商品|需求
|
||||
import commonBox from '@/views/customer/productMangement/commonBox/index.vue';
|
||||
|
||||
export default {
|
||||
name: 'productList',
|
||||
components: { commonBox },
|
||||
data() {
|
||||
return {
|
||||
role:{
|
||||
role_type:'customer',
|
||||
audit_status:'pending'
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
36
f/web-kboss/src/views/customer/demand/demandList.vue
Normal file
36
f/web-kboss/src/views/customer/demand/demandList.vue
Normal file
@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<div>
|
||||
<commonBox :role="role"></commonBox>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
//运营|用户 查找商品|需求
|
||||
import commonBox from '@/views/customer/productMangement/commonBox/index.vue';
|
||||
|
||||
export default {
|
||||
name: 'productList',
|
||||
components: { commonBox },
|
||||
data() {
|
||||
return {
|
||||
role:{
|
||||
role_type:'customer',
|
||||
audit_status:'',
|
||||
publish_type:null
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if(sessionStorage.getItem('jueseNew').includes('运营')){
|
||||
console.log("运营");
|
||||
this.role.role_type='customer'
|
||||
}else if(sessionStorage.getItem('jueseNew').includes('客户')){
|
||||
console.log("客户");
|
||||
this.role.role_type='user'
|
||||
}
|
||||
console.log("role",this.role);
|
||||
this.role.audit_status='pending,approved'
|
||||
this.role.publish_type='2'
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
36
f/web-kboss/src/views/customer/demand/rejectDemand.vue
Normal file
36
f/web-kboss/src/views/customer/demand/rejectDemand.vue
Normal file
@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<div>
|
||||
<commonBox :role="role"></commonBox>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
//运营|用户 查找商品|需求
|
||||
import commonBox from '@/views/customer/productMangement/commonBox/index.vue';
|
||||
|
||||
export default {
|
||||
name: 'productList',
|
||||
components: { commonBox },
|
||||
data() {
|
||||
return {
|
||||
role:{
|
||||
role_type:'customer',
|
||||
audit_status:'',
|
||||
publish_type:null
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if(sessionStorage.getItem('jueseNew').includes('运营')){
|
||||
console.log("运营");
|
||||
this.role.role_type='customer'
|
||||
}else if(sessionStorage.getItem('jueseNew').includes('客户')){
|
||||
console.log("客户");
|
||||
this.role.role_type='user'
|
||||
}
|
||||
console.log("role",this.role);
|
||||
this.role.audit_status='rejected'
|
||||
this.role.publish_type='2'
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
@ -12,7 +12,7 @@
|
||||
</li>
|
||||
<li>
|
||||
|
||||
<el-input size="mini" v-model="searchData.keyword" placeholder="请输入商品名称或关键词" clearable></el-input>
|
||||
<el-input size="mini" v-model="searchData.keyword" placeholder="请输入关键词" clearable></el-input>
|
||||
</li>
|
||||
<li>
|
||||
<el-button size="mini" @click="resetSearch">重置</el-button>
|
||||
@ -22,17 +22,21 @@
|
||||
</div>
|
||||
<div class="table-box">
|
||||
<div style="margin-bottom: 10px;">
|
||||
<el-radio-group v-model="searchData.radioType" class="radio-group" size="mini"
|
||||
<el-radio-group v-if="role.role_type=='customer'" v-model="searchData.radioType" class="radio-group" size="mini"
|
||||
@change="handleRadioChange">
|
||||
<el-radio-button v-for="item in radioOptions" :key="item.value" :label="item.value">
|
||||
{{ item.label }}
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
<!-- <el-button style="margin-left: 10px;" size="mini" @click="openAddDialog">
|
||||
<i class="el-icon-plus"></i> 添加{{ searchData.radioType === '1' || searchData.radioType === '3' ?
|
||||
'需求' : '商品' }}
|
||||
</el-button> -->
|
||||
<el-button style="margin-left: 10px;" size="mini" @click="exportData">
|
||||
<i class="el-icon-upload2"></i> 导出
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table height="calc(100vh - 210px)" v-loading="loading" :data="tableData"
|
||||
<el-table border height="calc(100vh - 210px)" v-loading="loading" :data="tableData"
|
||||
style="width: 100%;border:1px solid #ccc;" element-loading-text="加载中..."
|
||||
element-loading-spinner="el-icon-loading" element-loading-background="rgba(255, 255, 255, 0.8)">
|
||||
<el-table-column prop="date" label="商品图片" width="180">
|
||||
@ -49,14 +53,29 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="product_category" show-overflow-tooltip label="所属类别" min-width="180">
|
||||
</el-table-column>
|
||||
<el-table-column show-overflow-tooltip label="审核状态" min-width="180">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.audit_status === 'approved'" type="success">审核通过</el-tag>
|
||||
<el-tag v-else-if="scope.row.audit_status === 'rejected'" type="danger">审核不通过</el-tag>
|
||||
<el-tag v-else type="warning">待审核</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column show-overflow-tooltip label="上架状态" min-width="180">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.listing_status === 'listing'" type="success">已上架</el-tag>
|
||||
<el-tag v-else-if="scope.row.listing_status === 'delisting'" type="danger">已下架</el-tag>
|
||||
<el-tag v-else type="warning">未上架</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="company_name" show-overflow-tooltip label="所属企业" min-width="180">
|
||||
</el-table-column>
|
||||
<el-table-column prop="company_type" show-overflow-tooltip label="公司类别" min-width="180">
|
||||
</el-table-column>
|
||||
<el-table-column prop="address" show-overflow-tooltip label="商品概述" min-width="180">
|
||||
</el-table-column>
|
||||
<el-table-column prop="address" show-overflow-tooltip label="商品详情" min-width="180">
|
||||
<!-- <el-table-column prop="requirement_summary" show-overflow-tooltip label="商品概述" min-width="180">
|
||||
</el-table-column>
|
||||
<el-table-column prop="related_parameters" show-overflow-tooltip label="相关参数" min-width="180">
|
||||
</el-table-column> -->
|
||||
<el-table-column prop="contact_person" show-overflow-tooltip label="联系人" min-width="180">
|
||||
</el-table-column>
|
||||
<el-table-column prop="phone_number" show-overflow-tooltip label="联系电话" min-width="180">
|
||||
@ -65,12 +84,19 @@
|
||||
</el-table-column>
|
||||
<el-table-column fixed="right" min-width="240" label="操作">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="small" @click="openDetail(scope.row)">查看</el-button>
|
||||
<el-button type="text" style="color: #409EFF;" size="small">修改</el-button>
|
||||
<el-button type="text" size="small" @click="openDetail(scope.row,1)">查看</el-button>
|
||||
<el-button @click="editProduct(scope.row)" type="text" style="color: #409EFF;"
|
||||
size="small">修改</el-button>
|
||||
<el-button v-if="role.role_type=='customer'" type="text" size="small" @click="openDetail(scope.row,2)">审核</el-button>
|
||||
|
||||
<!-- <el-button type="text" style="color: #E6A23C;" size="small">导出</el-button> -->
|
||||
<el-button type="text" style="color: #67C23A;" size="small">上架</el-button>
|
||||
<el-button type="text" size="small">下架</el-button>
|
||||
<el-button type="text" style="color: #F56C6C;" size="small">删除</el-button>
|
||||
<el-button :disabled="scope.row.audit_status === 'approved'&&scope.row.listing_status === 'listing'" v-if="role.role_type=='customer'" @click="grounding(scope.row, 'listing')" type="text" style="color: #67C23A;"
|
||||
size="small">上架</el-button>
|
||||
<el-button :disabled="scope.row.audit_status === 'approved'&&scope.row.listing_status === 'delisting'" v-if="role.role_type=='customer'" @click="grounding(scope.row, 'delisting')" type="text" size="small">下架</el-button>
|
||||
<el-popconfirm v-if="role.role_type=='customer'" title="确定删除该条目吗?" @confirm="deleteProduct(scope.row)">
|
||||
<el-button slot="reference" type="text" style="color: #F56C6C;margin-left: 10px;" size="small">删除</el-button>
|
||||
</el-popconfirm>
|
||||
|
||||
|
||||
</template>
|
||||
</el-table-column>
|
||||
@ -80,21 +106,35 @@
|
||||
layout="total, prev, pager, next" :total="total_count">
|
||||
</el-pagination>
|
||||
</div>
|
||||
<commonDetail
|
||||
:visible="showProductDetail"
|
||||
@close="handleDetailClose"
|
||||
@approve="handleApprove"
|
||||
<commonDetail :showType="detailType" :visible="showProductDetail" @close="handleDetailClose" @approve="handleApprove"
|
||||
@reject="handleReject">
|
||||
</commonDetail>
|
||||
|
||||
<!-- 编辑商品弹窗 -->
|
||||
<el-dialog :title="editForm.publish_type === '1' ? '编辑商品' : '编辑需求'" :visible.sync="showEditDialog" width="80%"
|
||||
top="5vh">
|
||||
<sendProduct :publish_type="editForm.publish_type" :isEdit="true" :editData="editForm"
|
||||
@success="handleEditSuccess" @close="closeEditDialog">
|
||||
</sendProduct>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 添加商品/需求弹窗 -->
|
||||
<el-dialog :title="publish_type === '2' ? '添加需求' : '添加商品'" width="80%" top="5vh"
|
||||
:visible.sync="sendProductVisible">
|
||||
<sendProduct :publish_type="publish_type" :isEdit="false" @success="sendProductSuccess"
|
||||
@close="closeAddDialog">
|
||||
</sendProduct>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { reqSearchByMangement, reqGetProductDetail } from '@/api/ncmatch';
|
||||
import { reqSearchByMangement, reqGetProductDetail, reqEditProduct, reqEditProductNoImg } from '@/api/ncmatch';
|
||||
import commonDetail from '@/views/customer/productMangement/commonDetail/index.vue';
|
||||
import { mapState } from 'vuex';
|
||||
import sendProduct from '@/views/homePage/ncmatch/mainPage/sendProduct/index.vue';
|
||||
export default {
|
||||
name: 'commonBox',
|
||||
components: { commonDetail },
|
||||
components: { commonDetail, sendProduct },
|
||||
props: {
|
||||
role: {
|
||||
type: Object,
|
||||
@ -103,13 +143,15 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
detailType: '1',//1:查看 2:审核 3:前台
|
||||
sendProductVisible: false,
|
||||
searchDate: [],
|
||||
searchData: {
|
||||
radioType: "1",
|
||||
start_date: null,
|
||||
end_date: null,
|
||||
keyword: "",
|
||||
audit_status: null,
|
||||
audit_status: null, // 移除对 this.role.audit_status 的直接引用
|
||||
listing_status: null,
|
||||
publish_type: "2",
|
||||
manager_self: "",
|
||||
@ -164,6 +206,8 @@ export default {
|
||||
tableData: [],
|
||||
total_count: 0,
|
||||
loading: false,
|
||||
showEditDialog: false,
|
||||
editForm: {},
|
||||
pickerOptions: {
|
||||
shortcuts: [{
|
||||
text: '最近一周',
|
||||
@ -194,9 +238,84 @@ export default {
|
||||
}
|
||||
},
|
||||
created() {
|
||||
console.log("父组件传来的值是",this.role);
|
||||
// 在 created 生命周期中设置 audit_status
|
||||
if (this.role && this.role.audit_status) {
|
||||
|
||||
this.searchData.audit_status = this.role.audit_status;
|
||||
}
|
||||
if (this.role && this.role.publish_type) {
|
||||
this.searchData.publish_type = this.role.publish_type;
|
||||
}
|
||||
this.getTableData();
|
||||
},
|
||||
watch: {
|
||||
// 监听 role 对象的变化
|
||||
role: {
|
||||
handler(newRole) {
|
||||
if (newRole && newRole.audit_status) {
|
||||
this.searchData.audit_status = newRole.audit_status;
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
showProductDetail: {
|
||||
get() {
|
||||
return this.$store.state.ncmatch.showProductDetail;
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('SHOWPRODUCTDETAIL', value);
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
deleteProduct(row) {
|
||||
console.log(row);
|
||||
let ploay = {
|
||||
id: row.id,
|
||||
del_flg: '1'
|
||||
}
|
||||
reqEditProductNoImg(ploay).then(res => {
|
||||
|
||||
if (res.status) {
|
||||
this.$message.success('删除成功~');
|
||||
this.getTableData();
|
||||
} else {
|
||||
this.$message.error('删除失败~');
|
||||
}
|
||||
})
|
||||
},
|
||||
grounding(row, listing_status) {
|
||||
console.log(listing_status);
|
||||
let ploay = {
|
||||
id: row.id,
|
||||
listing_status: listing_status,
|
||||
}
|
||||
reqEditProductNoImg(ploay).then(res => {
|
||||
let msg = listing_status == 'listing' ? '上架' : '下架';
|
||||
if (res.status) {
|
||||
this.$message.success(msg + '成功~');
|
||||
this.getTableData();
|
||||
} else {
|
||||
this.$message.error(msg + '失败~');
|
||||
}
|
||||
})
|
||||
},
|
||||
sendProductSuccess() {
|
||||
this.sendProductVisible = false; // 关闭弹窗
|
||||
this.getTableData(); // 刷新列表
|
||||
},
|
||||
// 关闭添加弹窗
|
||||
closeAddDialog() {
|
||||
this.sendProductVisible = false;
|
||||
},
|
||||
openSendProduct(item) {
|
||||
this.sendProductVisible = true;
|
||||
this.sendProductData = item;
|
||||
},
|
||||
handleRadioChange(value) {
|
||||
this.searchData.publish_type = this.radioMap[value].publish_type;
|
||||
this.searchData.manager_self = this.radioMap[value].manager_self;
|
||||
@ -208,6 +327,7 @@ export default {
|
||||
this.searchDate = [];
|
||||
this.searchData.keyword = "";
|
||||
this.searchData.current_page = 1;
|
||||
this.searchData.audit_status = this.role.audit_status;
|
||||
this.getTableData();
|
||||
},
|
||||
exportData() {
|
||||
@ -220,13 +340,35 @@ export default {
|
||||
handleApprove() {
|
||||
// 处理审核通过逻辑
|
||||
console.log('审核通过');
|
||||
this.getTableData();
|
||||
// 这里可以添加审核通过后的业务逻辑
|
||||
},
|
||||
handleReject() {
|
||||
// 处理审核不通过逻辑
|
||||
console.log('审核不通过');
|
||||
this.getTableData();
|
||||
// 这里可以添加审核不通过后的业务逻辑
|
||||
},
|
||||
// 编辑商品
|
||||
editProduct(item) {
|
||||
console.log('编辑商品数据:', item);
|
||||
console.log('公司类别数据:', item.company_type);
|
||||
this.editForm = { ...item };
|
||||
this.showEditDialog = true;
|
||||
},
|
||||
// 关闭编辑弹窗
|
||||
closeEditDialog() {
|
||||
this.showEditDialog = false;
|
||||
this.editForm = {};
|
||||
},
|
||||
// 编辑成功回调
|
||||
handleEditSuccess() {
|
||||
// 根据编辑的数据类型显示不同的成功消息
|
||||
const successMessage = this.editForm.publish_type === '2' ? '需求编辑成功!' : '商品编辑成功!';
|
||||
this.$message.success(successMessage);
|
||||
this.closeEditDialog();
|
||||
this.getTableData(); // 刷新列表
|
||||
},
|
||||
getTableData() {
|
||||
// 处理日期范围
|
||||
if (this.searchDate && this.searchDate.length === 2) {
|
||||
@ -257,37 +399,33 @@ export default {
|
||||
console.log(`每页 ${val} 条`);
|
||||
},
|
||||
handleCurrentChange(val) {
|
||||
this.searchData.current_page = val;
|
||||
this.getTableData();
|
||||
console.log(`当前页: ${val}`);
|
||||
},
|
||||
openDetail(item) {
|
||||
openDetail(item,type) {
|
||||
this.detailType = type;
|
||||
this.loading = true;
|
||||
reqGetProductDetail({
|
||||
|
||||
id: item.id,
|
||||
from: 'b'
|
||||
}).then(async res => {
|
||||
this.loading = false
|
||||
this.loading = false;
|
||||
if (res.status) {
|
||||
await this.$store.commit('SETPRODUCTDETAIL', res.data);
|
||||
await this.$store.commit('SHOWPRODUCTDETAIL', true);
|
||||
} else {
|
||||
this.$message.error(res.msg);
|
||||
this.$set(this.loadingStates, item.id, false);
|
||||
this.$message.error(res.msg || '获取详情失败');
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
showProductDetail: {
|
||||
get() {
|
||||
return this.$store.state.ncmatch.showProductDetail;
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('SHOWPRODUCTDETAIL', value);
|
||||
}
|
||||
}).catch(error => {
|
||||
this.loading = false;
|
||||
console.error('获取详情失败:', error);
|
||||
this.$message.error('获取详情失败,请重试');
|
||||
});
|
||||
},
|
||||
openAddDialog() {
|
||||
this.publish_type = this.searchData.radioType === '1' || this.searchData.radioType === '3' ? '2' : '1';
|
||||
this.sendProductVisible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,23 +1,34 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="dialogTitle"
|
||||
top="5vh"
|
||||
:visible.sync="visible"
|
||||
width="80%"
|
||||
@open="scrollToTop"
|
||||
@close="handleClose">
|
||||
<ProductDetail></ProductDetail>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="handleClose">关 闭</el-button>
|
||||
<el-button type="success" @click="handleApprove">审核通过</el-button>
|
||||
<el-button type="danger" @click="handleReject">审核不通过</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
<div>
|
||||
<el-dialog :title="dialogTitle" top="5vh" :visible.sync="visible" width="80%" @open="scrollToTop"
|
||||
@close="handleClose">
|
||||
<ProductDetail :isApprove="true" ></ProductDetail>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="handleClose">关 闭</el-button>
|
||||
<el-button type="success" v-if="showType===2" @click="handleApprove">审核通过</el-button>
|
||||
<el-button type="danger" v-if="showType===2" @click="handleReject">审核不通过</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
<!-- Form -->
|
||||
|
||||
<el-dialog title="审核退回" :visible.sync="dialogFormVisible">
|
||||
<el-form :model="form">
|
||||
<el-form-item label="驳回原因" :label-width="formLabelWidth">
|
||||
<el-input v-model="form.reject_reason" autocomplete="off" type="textarea" :rows="3"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogFormVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="rejectProduct">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ProductDetail from '@/views/homePage/ncmatch/proDetail/index.vue';
|
||||
import { mapState } from 'vuex';
|
||||
import { reqEditProductNoImg } from '@/api/ncmatch';
|
||||
|
||||
export default {
|
||||
name: 'commonDetail',
|
||||
@ -26,6 +37,19 @@ export default {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showType: {
|
||||
type: String,
|
||||
default: '1'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogFormVisible: false,
|
||||
form: {
|
||||
reject_reason: ''
|
||||
},
|
||||
formLabelWidth: '120px'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -56,26 +80,56 @@ export default {
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
// 这里可以调用审核通过的API
|
||||
this.$emit('approve');
|
||||
this.$message.success('审核通过成功');
|
||||
this.handleClose();
|
||||
let ploay = {
|
||||
id: this.productDetailInfo.id,
|
||||
audit_status: "approved"
|
||||
}
|
||||
reqEditProductNoImg(ploay).then(res => {
|
||||
if (res.status) {
|
||||
this.$emit('approve');
|
||||
this.$message.success('审核通过成功');
|
||||
this.handleClose();
|
||||
} else {
|
||||
this.$message.error(res.msg || '审核失败,请重试')
|
||||
}
|
||||
})
|
||||
|
||||
}).catch(() => {
|
||||
this.$message.info('已取消操作');
|
||||
});
|
||||
},
|
||||
handleReject() {
|
||||
this.$confirm('确认审核不通过吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
// 这里可以调用审核不通过的API
|
||||
this.$emit('reject');
|
||||
this.$message.success('审核不通过成功');
|
||||
this.handleClose();
|
||||
}).catch(() => {
|
||||
this.$message.info('已取消操作');
|
||||
});
|
||||
this.dialogFormVisible = true;
|
||||
// this.$confirm('确认审核不通过吗?', '提示', {
|
||||
// confirmButtonText: '确定',
|
||||
// cancelButtonText: '取消',
|
||||
// type: 'warning'
|
||||
// }).then(() => {
|
||||
// // 这里可以调用审核不通过的API
|
||||
// this.$emit('reject');
|
||||
// this.$message.success('审核不通过成功');
|
||||
// this.handleClose();
|
||||
// }).catch(() => {
|
||||
// this.$message.info('已取消操作');
|
||||
// });
|
||||
},
|
||||
rejectProduct() {
|
||||
let ploay={
|
||||
id:this.productDetailInfo.id,
|
||||
audit_status:"rejected",
|
||||
reject_reason:this.form.reject_reason
|
||||
}
|
||||
reqEditProductNoImg(ploay).then(res => {
|
||||
this.dialogFormVisible=false;
|
||||
if (res.status) {
|
||||
this.$emit('reject');
|
||||
this.handleClose();
|
||||
this.$message.success('审核成功');
|
||||
}else{
|
||||
this.$message.error('审核失败,请重试');
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,12 +14,22 @@ export default {
|
||||
return {
|
||||
role:{
|
||||
role_type:'customer',
|
||||
type:'look'
|
||||
audit_status:'',
|
||||
publish_type:null
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
if(sessionStorage.getItem('jueseNew').includes('运营')){
|
||||
console.log("运营");
|
||||
this.role.role_type='customer'
|
||||
}else if(sessionStorage.getItem('jueseNew').includes('客户')){
|
||||
console.log("客户");
|
||||
this.role.role_type='user'
|
||||
}
|
||||
console.log("role",this.role);
|
||||
this.role.audit_status='pending,approved'
|
||||
this.role.publish_type='1'
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<div>
|
||||
<commonBox :role="role"></commonBox>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
//运营|用户 查找商品|需求
|
||||
import commonBox from '@/views/customer/productMangement/commonBox/index.vue';
|
||||
|
||||
export default {
|
||||
name: 'productList',
|
||||
components: { commonBox },
|
||||
data() {
|
||||
return {
|
||||
role:{
|
||||
role_type:null,
|
||||
audit_status:null,
|
||||
publish_type:null
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
if(sessionStorage.getItem('jueseNew').includes('运营')){
|
||||
console.log("运营");
|
||||
this.role.role_type='customer'
|
||||
}else if(sessionStorage.getItem('jueseNew').includes('客户')){
|
||||
console.log("客户");
|
||||
this.role.role_type='user'
|
||||
}
|
||||
console.log("role",this.role);
|
||||
this.role.audit_status='rejected'
|
||||
this.role.publish_type='1'
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
@ -181,20 +181,12 @@ export default Vue.extend({
|
||||
<template>
|
||||
<div class="jd-homepage">
|
||||
<!-- 顶部Header -->
|
||||
<header class="header">
|
||||
<!-- <header class="header">
|
||||
<div class="header-content">
|
||||
<!-- 左侧Logo -->
|
||||
<!-- <div class="logo-section"> -->
|
||||
<!--
|
||||
<div class="logo">
|
||||
<img src="./img/logo.png" alt="">
|
||||
</div> -->
|
||||
|
||||
<!-- </div> -->
|
||||
|
||||
|
||||
</div>
|
||||
</header>
|
||||
</header> -->
|
||||
<!-- 主内容区域 -->
|
||||
<main class="main-content">
|
||||
<div class="content-wrapper">
|
||||
@ -435,7 +427,6 @@ export default Vue.extend({
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
height: 100px;
|
||||
|
||||
.header-content {
|
||||
width: 100%;
|
||||
@ -506,7 +497,7 @@ export default Vue.extend({
|
||||
margin: 20px auto;
|
||||
margin-top: 10px;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
overflow: visible;
|
||||
background-color: white;
|
||||
height: 360px;
|
||||
|
||||
|
||||
@ -1,12 +1,20 @@
|
||||
export function buildDynamicStructure(data, parentId = "None", currentLevel = 1) {
|
||||
export function buildDynamicStructure(data, parentId = null, currentLevel = 1) {
|
||||
// 1. 找出当前层级的节点
|
||||
const currentNodes = data.filter(item => item.parentid === parentId);
|
||||
if (currentNodes.length === 0) return [];
|
||||
|
||||
// 2. 处理每个节点
|
||||
return currentNodes.map(node => {
|
||||
return currentNodes.map((node, index) => {
|
||||
const resultNode = {};
|
||||
|
||||
// 为每个节点添加唯一id
|
||||
if (node.id) {
|
||||
resultNode.id = node.id;
|
||||
} else {
|
||||
// 如果没有id,生成一个唯一的id
|
||||
resultNode.id = `level${currentLevel}_${parentId || 'root'}_${index}_${Date.now()}`;
|
||||
}
|
||||
|
||||
// 设置层级名称字段
|
||||
if (currentLevel === 1) {
|
||||
resultNode.first_level_name = node.name;
|
||||
@ -15,6 +23,9 @@ export function buildDynamicStructure(data, parentId = "None", currentLevel = 1)
|
||||
resultNode.second_level_name = node.name;
|
||||
} else if (currentLevel === 3) {
|
||||
resultNode.third_level_name = node.name;
|
||||
} else if (currentLevel === 4) {
|
||||
// 第四级节点也需要保存name字段
|
||||
resultNode.name = node.name;
|
||||
}
|
||||
|
||||
// 3. 递归处理子节点
|
||||
@ -27,9 +38,12 @@ export function buildDynamicStructure(data, parentId = "None", currentLevel = 1)
|
||||
} else if (currentLevel === 2) {
|
||||
resultNode.thirdClassification = children;
|
||||
} else if (currentLevel === 3) {
|
||||
|
||||
// 第四级特殊处理为product_list
|
||||
|
||||
resultNode.product_list = children.map(child => ({
|
||||
first_level_name: child.third_level_name || child.name
|
||||
id: child.id,
|
||||
first_level_name: child.name // 修复:使用 child.name 而不是 child.third_level_name
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,14 +4,14 @@
|
||||
<ul class="category-list">
|
||||
<li class="category-item" style="color: #E02020;"><img src="../img/hot.svg" style="margin-right: 10px;"
|
||||
alt=""> 热门推荐 / 活动促销</li>
|
||||
<li v-for="category in categories" :key="category.first_level_name" class="category-item"
|
||||
<li v-for="category in categories" :key="category.id" class="category-item"
|
||||
@mouseenter="showProductList(category)" @mouseleave="hideProductList">
|
||||
<span class="category-icon"> <img style="width: 24px;height: 24px;" :src="category.icon" alt=""> </span>
|
||||
<span class="category-name">{{ category.first_level_name }}</span>
|
||||
<span style="display: flex;margin-left: 0px;padding-left: 0px;">|</span>
|
||||
<div class="menu-item">
|
||||
<span v-for="(secondary, index) in category.secondaryClassification"
|
||||
:key="secondary.second_level_name">
|
||||
:key="secondary.id">
|
||||
{{ secondary.second_level_name }}{{ index < category.secondaryClassification.length - 1 ? ' / '
|
||||
: '' }} </span>
|
||||
</div>
|
||||
@ -19,12 +19,12 @@
|
||||
</ul>
|
||||
<transition name="slide-fade">
|
||||
<!-- v-if="currentCategory" -->
|
||||
<div class="rightBox" v-if="currentCategory" @mouseenter="keepProductList" @mouseleave="hideProductList">
|
||||
<div v-loading="loading" element-loading-text="加载中..." element-loading-spinner="el-icon-loading" element-loading-background="rgba(255, 255, 255, 0.8)" class="rightBox" v-if="currentCategory" @mouseenter="keepProductList" @mouseleave="hideProductList">
|
||||
<div class="rightBox-content">
|
||||
<!-- 二级菜单标题 -->
|
||||
<div class="secondary-menu">
|
||||
<div v-for="secondary in currentCategory.secondaryClassification"
|
||||
:key="secondary.second_level_name" class="secondary-item"
|
||||
:key="secondary.id" class="secondary-item"
|
||||
:class="{ active: selectedSecondary === secondary }"
|
||||
@mouseenter="selectSecondary(secondary)">
|
||||
{{ secondary.second_level_name }}
|
||||
@ -36,7 +36,7 @@
|
||||
<!-- 如果有选中的二级菜单且有三级菜单,显示京东风格的分类区域 -->
|
||||
<div v-if="selectedSecondary && selectedSecondary.thirdClassification && selectedSecondary.thirdClassification.length > 0"
|
||||
class="jd-style-menu">
|
||||
<div v-for="third in selectedSecondary.thirdClassification" :key="third.third_level_name"
|
||||
<div v-for="third in selectedSecondary.thirdClassification" :key="third.id"
|
||||
class="category-section">
|
||||
<!-- 只有当有四级菜单时才显示三级菜单标题 -->
|
||||
<div v-if="third.product_list && third.product_list.length > 0" class="section-header">
|
||||
@ -48,7 +48,7 @@
|
||||
<div v-if="third.product_list && third.product_list.length > 0"
|
||||
class="product-grid">
|
||||
<div v-for="(product, index) in third.product_list"
|
||||
:key="product.first_level_name" class="product-tag">
|
||||
:key="product.id" class="product-tag">
|
||||
{{ product.first_level_name }}
|
||||
</div>
|
||||
</div>
|
||||
@ -82,7 +82,7 @@
|
||||
<!-- 默认:显示所有二级菜单项 -->
|
||||
<div v-else class="jd-style-menu">
|
||||
<div v-for="secondary in currentCategory.secondaryClassification"
|
||||
:key="secondary.second_level_name" class="category-section">
|
||||
:key="secondary.id" class="category-section">
|
||||
<div class="section-header">
|
||||
<span class="section-title">{{ secondary.second_level_name }}</span>
|
||||
<span class="section-arrow">></span>
|
||||
@ -112,61 +112,8 @@ export default {
|
||||
currentCategory: null,
|
||||
selectedSecondary: null,
|
||||
hideTimer: null,
|
||||
categories: [
|
||||
{
|
||||
first_level_name: '云', icon: require('../img/cloud.png'), secondaryClassification: [
|
||||
{
|
||||
second_level_name: '百度云',
|
||||
thirdClassification: [
|
||||
{
|
||||
third_level_name: '计算',
|
||||
product_list: [{ first_level_name: 'ECS1' }, { first_level_name: 'ECS2' }, { first_level_name: 'ECS3' }]
|
||||
},
|
||||
{
|
||||
third_level_name: '存储',
|
||||
product_list: [{ first_level_name: 'BOS1' }, { first_level_name: 'BOS2' }]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
second_level_name: '阿里云',
|
||||
thirdClassification: [
|
||||
{
|
||||
third_level_name: '计算',
|
||||
product_list: [{ first_level_name: 'ECS-A' }, { first_level_name: 'ECS-B' }]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
first_level_name: '国产算力', icon: require('../img/cloud.png'), secondaryClassification: [
|
||||
{
|
||||
second_level_name: '昇腾910B',
|
||||
thirdClassification: [
|
||||
{
|
||||
third_level_name: '昇腾910B1',
|
||||
},
|
||||
{
|
||||
third_level_name: '昇腾910B2',
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
second_level_name: '昆仑芯',
|
||||
thirdClassification: [
|
||||
{
|
||||
third_level_name: '昆仑芯A',
|
||||
},
|
||||
{
|
||||
third_level_name: '昆仑芯B',
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
],
|
||||
categories: [ ],
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@ -174,9 +121,13 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
getCategories() {
|
||||
this.loading = true;
|
||||
reqNcMatchMenu({ url_link: window.location.href }).then(res => {
|
||||
this.loading = false;
|
||||
if (res.status) {
|
||||
this.categories = buildDynamicStructure(res.data)
|
||||
console.log("测试",this.categories);
|
||||
|
||||
// this.categories = res.data.map(item => {
|
||||
// return {
|
||||
// name: item.name,
|
||||
@ -236,6 +187,7 @@ export default {
|
||||
|
||||
// 左侧分类导航
|
||||
.category-sidebar {
|
||||
position: relative;
|
||||
background-color: #f8fbfe;
|
||||
height: 100%;
|
||||
border-radius: 10px;
|
||||
@ -306,14 +258,17 @@ export default {
|
||||
position: absolute;
|
||||
left: 100%;
|
||||
top: 0;
|
||||
width: 900px;
|
||||
border: 1px solid red;
|
||||
width: 1000px;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
z-index: 1000;
|
||||
z-index: 9999;
|
||||
padding: 25px;
|
||||
min-height: 400px;
|
||||
// height: 500px;
|
||||
margin-left: 10px;
|
||||
overflow: visible;
|
||||
white-space: nowrap;
|
||||
|
||||
/* 添加一个透明的连接区域,防止鼠标移动时意外消失 */
|
||||
&::before {
|
||||
@ -327,7 +282,10 @@ export default {
|
||||
}
|
||||
|
||||
.rightBox-content {
|
||||
|
||||
|
||||
.secondary-menu {
|
||||
|
||||
line-height: 1.5;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@ -355,6 +313,10 @@ export default {
|
||||
|
||||
.menu-content {
|
||||
min-height: 200px;
|
||||
height: 100%;
|
||||
max-height: calc(100vh - 280px);
|
||||
overflow-y: auto;
|
||||
border: 5px solid red;
|
||||
|
||||
.jd-style-menu {
|
||||
width: 100%;
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
<template>
|
||||
<div class="form-container">
|
||||
<div v-if="form.reject_reason" class="tip">
|
||||
<i class="el-icon-error"></i>未通过原因: <span style="color: #666;font-size: 12px;">{{ form.reject_reason }}</span>
|
||||
</div>
|
||||
<el-form :model="form" :rules="rules" ref="form" label-width="120px" class="two-column-form">
|
||||
<!-- 商品图片 - 单独一行 -->
|
||||
<el-form-item v-if="publish_type === '1'" :label="publish_type === '2' ? '需求图片' : '商品图片'" prop="img"
|
||||
@ -72,7 +75,7 @@
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<el-form-item label="GPU支持" prop="cart_flag" required class="form-item-half">
|
||||
<el-form-item label="GPU支持" prop="cart_flag" required class="form-item-half">
|
||||
<el-radio-group v-model="form.cart_flag">
|
||||
<el-radio label="1">是</el-radio>
|
||||
<el-radio label="0">否</el-radio>
|
||||
@ -124,29 +127,31 @@
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<el-form-item label="折扣" class="full-width">
|
||||
<el-input-number style="width: 120px;" :controls="false" v-model="form.discount" :precision="2" :step="0.01" :max="10">
|
||||
<el-form-item label="折扣" class="full-width">
|
||||
<el-input-number style="width: 120px;" :controls="false" v-model="form.discount" :precision="2"
|
||||
:step="0.01" :max="10">
|
||||
</el-input-number>
|
||||
<span style="margin-left: 10px; font-weight: bold;"> 折</span>
|
||||
<span style="margin-left: 10px; font-weight: bold;font-size: 14px;">折后价:
|
||||
<span v-if="form.discount!==0&&form.price" style="color: red;">¥{{ (form.price * form.discount/10).toFixed(2 ) }}</span>
|
||||
<span v-else>-</span>
|
||||
</span>
|
||||
<span style="margin-left: 10px; font-weight: bold;"> 折</span>
|
||||
<span style="margin-left: 10px; font-weight: bold;font-size: 14px;">折后价:
|
||||
<span v-if="form.discount !== 0 && form.price" style="color: red;">¥{{ (form.price *
|
||||
form.discount/10).toFixed(2 ) }}</span>
|
||||
<span v-else>-</span>
|
||||
</span>
|
||||
<!-- <el-input v-model="form.discount" placeholder="请输入折扣" type="number">
|
||||
<template slot="append">折</template>
|
||||
</el-input> -->
|
||||
</el-input> -->
|
||||
</el-form-item>
|
||||
<el-form-item class="full-width">
|
||||
<template slot="label">
|
||||
<span>平台服务费用</span>
|
||||
<el-tooltip
|
||||
content="平台服务费用为商品价格的3%,如有疑问请联系客服进行处理。"
|
||||
placement="top"
|
||||
effect="light">
|
||||
<i class="el-icon-warning-outline" style="margin-left: 5px; color: #333; cursor: pointer;"></i>
|
||||
<el-tooltip content="平台服务费用为商品价格的3%,如有疑问请联系客服进行处理。" placement="top" effect="light">
|
||||
<i class="el-icon-warning-outline"
|
||||
style="margin-left: 5px; color: #333; cursor: pointer;"></i>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<span v-if="form.discount!==0&&form.price" style="color: red;font-size: 14px;font-weight: bold;">¥{{ ((form.price * form.discount/10)*0.03).toFixed(2) }}</span>
|
||||
<span v-if="form.discount !== 0 && form.price" style="color: red;font-size: 14px;font-weight: bold;">¥{{
|
||||
((form.price *
|
||||
form.discount/10)*0.03).toFixed(2) }}</span>
|
||||
|
||||
<span v-else>-</span>
|
||||
</el-form-item>
|
||||
@ -169,10 +174,11 @@
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<div class="form-actions">
|
||||
<el-button type="primary" @click="submitForm" size="large">{{ isEdit ? '编辑商品' : (publish_type === '2' ? '发布需求' : '发布商品')
|
||||
}}</el-button>
|
||||
<el-button v-if="isEdit" @click="editBtn" size="large">确定修改</el-button>
|
||||
<!-- <el-button @click="resetForm" size="large">重置</el-button> -->
|
||||
<el-button type="primary" @click="submitForm" size="large">
|
||||
{{ isEdit ? (publish_type === '2' ? '保存需求' : '保存商品') : (publish_type === '2' ? '发布需求' : '发布商品') }}
|
||||
</el-button>
|
||||
<el-button @click="resetForm" size="large">重置</el-button>
|
||||
<el-button @click="handleClose" size="large">关闭</el-button>
|
||||
<!-- <el-button type="info" @click="getBinaryData" size="large">获取二进制数据</el-button> -->
|
||||
</div>
|
||||
</el-form>
|
||||
@ -208,7 +214,7 @@
|
||||
<script>
|
||||
import { VueCropper } from 'vue-cropper'
|
||||
import { buildCaTree } from './buildCaTree'
|
||||
import { reqGetProductCategorySearch, reqPublishProductAdd, reqCompanyCategorySearch } from '@/api/ncmatch'
|
||||
import { reqGetProductCategorySearch, reqPublishProductAdd, reqCompanyCategorySearch, reqEditProduct } from '@/api/ncmatch'
|
||||
export default {
|
||||
name: 'sendProduct',
|
||||
props: {
|
||||
@ -219,6 +225,10 @@ export default {
|
||||
isEdit: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
editData: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
components: {
|
||||
@ -264,8 +274,9 @@ export default {
|
||||
application_scenario: "",//应用场景
|
||||
unit: "",//单位
|
||||
short_term: "",//是否短租
|
||||
discount:null,//折扣
|
||||
discount: null,//折扣
|
||||
cart_flag: '1',//是否支持GPU
|
||||
reject_reason: "",//未通过原因
|
||||
},
|
||||
rules: {
|
||||
product_name: [
|
||||
@ -339,10 +350,75 @@ export default {
|
||||
created() {
|
||||
this.init_product_category()
|
||||
this.init_company_category()
|
||||
|
||||
// 如果是编辑模式且有编辑数据,等待数据初始化完成后填充
|
||||
if (this.isEdit && this.editData && Object.keys(this.editData).length > 0) {
|
||||
Promise.all([
|
||||
this.init_product_category(),
|
||||
this.init_company_category()
|
||||
]).then(() => {
|
||||
this.$nextTick(() => {
|
||||
this.fillEditData(this.editData);
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
editData: {
|
||||
handler(newVal) {
|
||||
if (newVal && Object.keys(newVal).length > 0 && this.isEdit) {
|
||||
// 延迟执行,确保分类数据已加载完成
|
||||
this.$nextTick(() => {
|
||||
this.fillEditData(newVal);
|
||||
});
|
||||
}
|
||||
},
|
||||
immediate: false, // 改为 false,避免在组件初始化时就执行
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 填充编辑数据
|
||||
fillEditData(data) {
|
||||
// 处理图片数据
|
||||
if (data.img) {
|
||||
this.selectedImage = data.img;
|
||||
this.form.img = data.img;
|
||||
}
|
||||
|
||||
// 填充表单数据
|
||||
Object.keys(this.form).forEach(key => {
|
||||
if (data[key] !== undefined && data[key] !== null) {
|
||||
this.form[key] = data[key];
|
||||
}
|
||||
});
|
||||
|
||||
// 特殊处理数组类型的数据
|
||||
if (data.company_type) {
|
||||
// 处理公司类别数据,可能是字符串或数组
|
||||
if (Array.isArray(data.company_type)) {
|
||||
this.form.company_type = [...data.company_type];
|
||||
} else if (typeof data.company_type === 'string') {
|
||||
// 如果是字符串,尝试按逗号分割
|
||||
if (data.company_type.includes(',')) {
|
||||
this.form.company_type = data.company_type.split(',').map(item => item.trim());
|
||||
} else {
|
||||
this.form.company_type = [data.company_type];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (data.product_category && Array.isArray(data.product_category)) {
|
||||
this.form.product_category = [...data.product_category];
|
||||
}
|
||||
|
||||
console.log('编辑数据已填充:', this.form);
|
||||
console.log('公司类别数据:', data.company_type);
|
||||
console.log('处理后的公司类别:', this.form.company_type);
|
||||
},
|
||||
|
||||
init_company_category() {
|
||||
reqCompanyCategorySearch({ url_link: window.location.href }).then(res => {
|
||||
return reqCompanyCategorySearch({ url_link: window.location.href }).then(res => {
|
||||
if (res.status) {
|
||||
this.company_category_list = []
|
||||
for (let item of res.data) {
|
||||
@ -351,8 +427,8 @@ export default {
|
||||
value: item.company_category
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
return res;
|
||||
})
|
||||
},
|
||||
// 将base64字符串转换为Blob对象
|
||||
@ -368,11 +444,11 @@ export default {
|
||||
|
||||
init_product_category() {
|
||||
// 根据 publish_type 参数决定 to_page 的值
|
||||
|
||||
reqGetProductCategorySearch({ url_link: window.location.href, to_page: 'publish' }).then(res => {
|
||||
return reqGetProductCategorySearch({ url_link: window.location.href, to_page: 'publish' }).then(res => {
|
||||
if (res.status) {
|
||||
this.typeList = buildCaTree(res.data)
|
||||
}
|
||||
return res;
|
||||
})
|
||||
},
|
||||
// 触发文件选择
|
||||
@ -512,22 +588,49 @@ export default {
|
||||
if (valid) {
|
||||
console.log('表单数据:', this.form)
|
||||
console.log('发布类型:', this.publish_type)
|
||||
console.log('是否为编辑模式:', this.isEdit)
|
||||
|
||||
|
||||
|
||||
let formdata = new FormData();
|
||||
for (let key in this.form) {
|
||||
formdata.append(key, this.form[key]);
|
||||
}
|
||||
formdata.append('publish_type', this.publish_type)
|
||||
// 添加发布类型到表单数据
|
||||
// formdata.append('publish_type', this.publish_type);
|
||||
|
||||
reqPublishProductAdd(formdata).then(res => {
|
||||
if (res.status) {
|
||||
this.$emit('success');
|
||||
const successMessage = this.publish_type === '2' ? '添加需求成功!' : '添加产品成功!'
|
||||
this.$message.success(successMessage)
|
||||
}
|
||||
})
|
||||
// 如果是编辑模式,添加编辑标识
|
||||
if (this.isEdit) {
|
||||
formdata.append('id', this.editData.id || '');
|
||||
reqEditProduct(formdata).then(res => {
|
||||
if (res.status) {
|
||||
this.$emit('success');
|
||||
// 移除这里的成功消息,避免重复显示
|
||||
// const successMessage = this.publish_type === '2' ? '编辑需求成功!' : '编辑商品成功!'
|
||||
// this.$message.success(successMessage)
|
||||
} else {
|
||||
this.$message.error(res.msg || '编辑失败,请重试')
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('编辑请求失败:', error);
|
||||
this.$message.error('编辑失败,请检查网络连接后重试')
|
||||
})
|
||||
} else {
|
||||
reqPublishProductAdd(formdata).then(res => {
|
||||
if (res.status) {
|
||||
this.$emit('success');
|
||||
const successMessage = this.publish_type === '2' ? '添加需求成功!' : '添加产品成功!'
|
||||
this.$message.success(successMessage)
|
||||
} else {
|
||||
this.$message.error(res.msg || '添加失败,请重试')
|
||||
}
|
||||
}).catch(error => {
|
||||
loading.close();
|
||||
console.error('添加请求失败:', error);
|
||||
this.$message.error('添加失败,请检查网络连接后重试')
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
this.$message.error('请完善表单信息')
|
||||
}
|
||||
@ -540,10 +643,51 @@ export default {
|
||||
if (this.selectedImage) {
|
||||
URL.revokeObjectURL(this.selectedImage)
|
||||
}
|
||||
|
||||
// 重置表单字段
|
||||
this.$refs.form.resetFields()
|
||||
this.selectedImage = null
|
||||
this.form.img = null
|
||||
this.$refs.fileInput.value = ''
|
||||
|
||||
// 如果是编辑模式,重新填充编辑数据
|
||||
if (this.isEdit && this.editData && Object.keys(this.editData).length > 0) {
|
||||
this.$nextTick(() => {
|
||||
this.fillEditData(this.editData);
|
||||
});
|
||||
} else {
|
||||
// 添加模式,清空所有数据
|
||||
this.selectedImage = null
|
||||
this.form.img = null
|
||||
this.$refs.fileInput.value = ''
|
||||
|
||||
// 重置表单数据到初始状态
|
||||
this.form = {
|
||||
url_link: window.location.href,
|
||||
img: null,
|
||||
product_name: "",
|
||||
product_category: "",
|
||||
company_name: "",
|
||||
company_type: [],
|
||||
contact_person: "",
|
||||
job_title: "",
|
||||
phone_number: "",
|
||||
email: "",
|
||||
cpu: "",
|
||||
memory: "",
|
||||
gpu: "",
|
||||
sys_disk: "",
|
||||
data_disk: "",
|
||||
net_card: "",
|
||||
priority: "",
|
||||
price: "",
|
||||
unit: "",
|
||||
short_term: "",
|
||||
label: "",
|
||||
requirement_summary: "",
|
||||
related_parameters: "",
|
||||
application_scenario: "",
|
||||
discount: null,
|
||||
cart_flag: '1',
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 处理级联选择器变化
|
||||
@ -596,6 +740,9 @@ export default {
|
||||
console.log('没有二进制数据')
|
||||
return null
|
||||
}
|
||||
},
|
||||
handleClose() {
|
||||
this.$emit('close');
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1002,4 +1149,25 @@ export default {
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xOdTWsmQAAAGiSURBVDhPY2AYBYMRMDIyMjAyMjL8//+f4f///wz//v1j+Pv3L8OfP38Yfv/+zfDnzx+G37//MPz69Yvh58+fDD9+/GD4/v07w7dv3xi+fv3K8OXLF4bPnz8zfPr0ieHjx48MHz58YHj//j3Du3fvGN6+fcvw5s0bhtevXzO8evWK4eXLlwwvXrxgeP78OcOzZ88Ynj59yvDkyROGx48fMzx69Ijh4cOHDA8ePGC4f/8+w7179xju3r3LcOfOHYbbt28z3Lp1i+HmzZsMN27cYLh+/TrDtWvXGK5evcpw5coVhsuXLzNcunSJ4eLFiwwXLlxgOH/+PMO5c+cYzp49y3DmzBmG06dPM5w6dYrh5MmTDCdOnGA4fvw4w7FjxxiOHj3KcOTIEYbDhw8zHDp0iOHgwYMMBw4cYNi/fz/Dvn37GPbu3cuwZ88eht27dzPs2rWLYefOnQw7duxg2L59O8O2bdsYtm7dyrBlyxaGzZs3M2zatIlh48aNDBs2bGBYv349w7p16xjWrl3LsGbNGoZVq1YxrFy5kmHFihUMy5cvZ1i2bBnD0qVLGZYsWcKwePFihkWLFjEsXLiQYcGCBQzz59nmDdvHsPcuXMZ5syZwzB79myGWbNmMcycOZNhxowZDNOnT2eYNm0aw9SpUxmmTJnCMHnyZIZJkyYxTJw4kWHChAkM48ePZxg3bhzD2LFjGcaMGcMwevRohlGjRjGMHDmSYcSIEQzDhw9nGDZsGMPQoUMZhgwZwjB48GCGQYMG0Q8AABKxLhX5TqgFAAAAAElFTkSuQmCC');
|
||||
}
|
||||
}
|
||||
.tip{
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: red;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
background-color: #ecf7fe;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
margin-bottom: 20px;
|
||||
&::after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 2px;
|
||||
transform: translateX(-50%);
|
||||
width: 5px;
|
||||
height: 100%;
|
||||
background-color: rgb(189, 83, 83);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -5,7 +5,7 @@
|
||||
{{ productDetailInfo.product_name }}
|
||||
|
||||
</h1>
|
||||
<button class="consult-btn" @click="openTalk">立即咨询</button>
|
||||
<button v-if="!isApprove" class="consult-btn" @click="openTalk">立即咨询</button>
|
||||
</div>
|
||||
<!-- 标题区域 -->
|
||||
<ul class="title-section">
|
||||
@ -139,6 +139,12 @@
|
||||
import { mapState } from "vuex";
|
||||
export default {
|
||||
name: 'proDetail',
|
||||
props: {
|
||||
isApprove: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
|
||||
@ -2,40 +2,69 @@
|
||||
<div
|
||||
style="display: flex;align-items: center;justify-content: center;border:1px solid red;width: 100%;max-width: 1400px;">
|
||||
|
||||
<img style="width: 180px;height: 60px;padding-right: 20px;" src="https://www.kaiyuancloud.cn/idfile?path=logo_ncmatch.png" alt="">
|
||||
<img @click="goHome" class="logo-clickable" style="width: 180px;height: 60px;padding-right: 20px;"
|
||||
src="https://www.kaiyuancloud.cn/idfile?path=logo_ncmatch.png" alt="">
|
||||
<div
|
||||
style="min-width:800px;border-bottom: 1px solid #E5E5E5;display: flex;align-items: center;justify-content: space-between;">
|
||||
|
||||
<!-- 中间搜索区域 -->
|
||||
<div class="search-section" style="position: relative;margin: 0 20px;">
|
||||
<div class="search-bar">
|
||||
<input v-model="searchKeyword" type="text" class="search-input" placeholder="搜你想搜...">
|
||||
<div class="search-bar" :class="{ 'has-results': showSearchResults && searchResults.length > 0 }">
|
||||
<el-select class="mySelect" v-model="publish_type" placeholder="请选择" @change="handleTypeChange"
|
||||
style="width: 75px;">
|
||||
<el-option label="商品" value="1">
|
||||
</el-option>
|
||||
<el-option label="需求" value="2"></el-option>
|
||||
</el-select>
|
||||
<input v-model="keyword" type="text" class="search-input" placeholder="搜你想搜..." @input="handleInputChange"
|
||||
@focus="handleInputFocus" @blur="handleInputBlur">
|
||||
|
||||
<button class="search-btn" @click="handleSearch">搜索</button>
|
||||
</div>
|
||||
|
||||
<!-- 实时搜索结果 -->
|
||||
<div v-if="showSearchResults && searchResults.length > 0" class="search-results" @click.stop>
|
||||
<div v-for="result in searchResults" :key="result.id" class="search-result-item"
|
||||
@click.stop.prevent="handleSearch(result)"
|
||||
@mousedown.stop.prevent
|
||||
@mouseup.stop.prevent
|
||||
style="cursor: pointer; padding: 10px">
|
||||
<span class="result-title" v-html="highlightKeyword(result)"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 热搜关键词 -->
|
||||
<div class="hot-search">
|
||||
<a v-for="keyword in hotSearchKeywords" :key="keyword" href="#" class="hot-keyword">
|
||||
<span class="search-label">热门搜索:</span>
|
||||
<a v-for="keyword in hotSearchKeywords" :key="keyword" href="#" class="hot-keyword"
|
||||
@click="handleHotKeywordClick(keyword)">
|
||||
{{ keyword }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- position: absolute;right: -150px;top: 0px; -->
|
||||
<span
|
||||
style="height: 44px;line-height: 44px;border-radius: 8px;border:1px solid #275AFF; color: #275AFF;font-size: 18px;font-weight: 500;padding: 0 20px;z-index: 10;display: flex;align-items: center;gap: 10px;">
|
||||
<img style="width: 24px;height: 24px;" src="../mainPage/img/robot.svg" alt="">
|
||||
NC AI</span>
|
||||
style="height: 44px;line-height: 44px;border-radius: 8px;border:1px solid #275AFF; color: #275AFF;font-size: 18px;font-weight: 500;padding: 0 20px;z-index: 10;display: flex;align-items: center;gap: 10px;">
|
||||
<img style="width: 24px;height: 24px;" src="../mainPage/img/robot.svg" alt="">
|
||||
NC AI</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import eventBus from '@/utils/eventBus'
|
||||
import { reqSearch } from '@/api/ncmatch'
|
||||
export default {
|
||||
name: 'search',
|
||||
data() {
|
||||
return {
|
||||
keyword: '',
|
||||
publish_type: '1',
|
||||
showSearchResults: false,
|
||||
searchResults: [],
|
||||
searchTimeout: null,
|
||||
// 移除搜索历史记录
|
||||
// 移除当前搜索状态
|
||||
hotSearchKeywords: [
|
||||
'昆仑芯-P800',
|
||||
'天垓-150',
|
||||
@ -86,6 +115,444 @@ export default {
|
||||
}
|
||||
],
|
||||
}
|
||||
},
|
||||
// 移除计算属性
|
||||
// 移除watch监听器
|
||||
methods: {
|
||||
goHome(event) {
|
||||
|
||||
|
||||
if (this.$route.path != '/ncmatchHome/index') {
|
||||
console.log('准备跳转到:', '/ncmatchHome/index');
|
||||
this.$router.push('/ncmatchHome/index').then(() => {
|
||||
console.log('跳转成功');
|
||||
}).catch(err => {
|
||||
console.error('跳转失败:', err);
|
||||
});
|
||||
} else {
|
||||
console.log('已经在首页,无需跳转');
|
||||
}
|
||||
},
|
||||
goSearch() {
|
||||
// 通过路由传参控制搜索行为
|
||||
const currentRoute = this.$route;
|
||||
const currentDisplayPage = currentRoute.query.display_page;
|
||||
const targetQuery = {
|
||||
keyword: this.keyword,
|
||||
publish_type: this.publish_type,
|
||||
display_page: 'list', // 正式搜索使用 list
|
||||
current_page: 1,
|
||||
page_size: 8
|
||||
};
|
||||
|
||||
console.log('准备跳转到搜索结果页面:', { currentRoute, targetQuery });
|
||||
|
||||
// 通过 display_page 参数判断是否在搜索结果页面
|
||||
if (currentDisplayPage !== 'list') {
|
||||
// 不在搜索结果页面,需要跳转
|
||||
console.log('执行路由跳转');
|
||||
this.$router.push({
|
||||
path: '/ncmatchHome/search',
|
||||
query: targetQuery
|
||||
}).catch(err => {
|
||||
// 忽略重复导航错误
|
||||
if (err.name !== 'NavigationDuplicated') {
|
||||
console.error('路由导航错误:', err);
|
||||
} else {
|
||||
console.log('路由重复导航,忽略错误');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 如果已经在搜索结果页面,重新调用接口获取最新数据
|
||||
console.log('已在搜索结果页面,重新调用接口获取最新数据');
|
||||
this.performFormalSearch(this.keyword, this.publish_type);
|
||||
}
|
||||
},
|
||||
// 处理输入变化
|
||||
handleInputChange() {
|
||||
// 清除之前的定时器
|
||||
if (this.searchTimeout) {
|
||||
clearTimeout(this.searchTimeout)
|
||||
}
|
||||
|
||||
// 如果输入框为空,隐藏搜索结果
|
||||
if (!this.keyword.trim()) {
|
||||
this.showSearchResults = false
|
||||
this.searchResults = []
|
||||
return
|
||||
}
|
||||
|
||||
// 设置防抖,300ms后执行搜索
|
||||
this.searchTimeout = setTimeout(() => {
|
||||
this.performRandomSearch()
|
||||
}, 300)
|
||||
},
|
||||
|
||||
// 执行搜索
|
||||
performRandomSearch() {
|
||||
if (!this.keyword.trim()) {
|
||||
this.showSearchResults = false
|
||||
this.searchResults = []
|
||||
return
|
||||
}
|
||||
|
||||
console.log('执行联想搜索:', { keyword: this.keyword, type: this.publish_type });
|
||||
|
||||
// 调用统一的搜索方法
|
||||
this.performSearch(this.keyword, this.publish_type);
|
||||
},
|
||||
|
||||
// 统一的搜索方法
|
||||
performSearch(keyword, type) {
|
||||
console.log('执行联想搜索:', { keyword, type });
|
||||
|
||||
reqSearch({
|
||||
url_link: window.location.href,
|
||||
keyword: keyword,
|
||||
publish_type: type,
|
||||
display_page: 'overview', // 联想搜索使用 overview
|
||||
current_page: 1,
|
||||
page_size: 15
|
||||
}).then(res => {
|
||||
this.searchResults = res.data.result
|
||||
console.log('联想搜索结果:', res)
|
||||
this.showSearchResults = true
|
||||
|
||||
// 联想搜索不需要更新URL参数,只显示结果
|
||||
console.log('联想搜索完成,显示结果');
|
||||
|
||||
}).catch(error => {
|
||||
console.error('联想搜索失败:', error);
|
||||
this.$message.error('搜索失败,请重试');
|
||||
});
|
||||
},
|
||||
|
||||
// 正式搜索方法(用于在搜索路由下重新调用接口)
|
||||
performFormalSearch(keyword, type) {
|
||||
console.log('=== 执行正式搜索开始 ===');
|
||||
console.log('搜索参数:', { keyword, type });
|
||||
console.log('当前路由:', this.$route.path);
|
||||
console.log('事件总线实例:', eventBus);
|
||||
|
||||
reqSearch({
|
||||
url_link: window.location.href,
|
||||
keyword: keyword,
|
||||
publish_type: type,
|
||||
display_page: 'list', // 正式搜索使用 list
|
||||
current_page: 1,
|
||||
page_size: 8
|
||||
}).then(res => {
|
||||
console.log('正式搜索结果:', res);
|
||||
|
||||
// 准备发送事件数据
|
||||
const eventData = {
|
||||
type: type,
|
||||
keyword: keyword,
|
||||
data: res.data
|
||||
};
|
||||
console.log('准备发送事件数据:', eventData);
|
||||
|
||||
// 通过事件总线触发搜索事件,让兄弟组件处理结果
|
||||
try {
|
||||
eventBus.$emit('search', eventData);
|
||||
console.log('事件总线事件发送成功');
|
||||
} catch (error) {
|
||||
console.error('事件总线事件发送失败:', error);
|
||||
}
|
||||
|
||||
console.log('正式搜索完成,已触发搜索事件');
|
||||
|
||||
}).catch(error => {
|
||||
console.error('正式搜索失败:', error);
|
||||
this.$message.error('搜索失败,请重试');
|
||||
});
|
||||
},
|
||||
|
||||
// 更新URL参数
|
||||
updateURLParams(keyword, type) {
|
||||
const query = { ...this.$route.query };
|
||||
|
||||
if (keyword) {
|
||||
query.keyword = keyword;
|
||||
} else {
|
||||
delete query.keyword;
|
||||
}
|
||||
|
||||
if (type) {
|
||||
query.publish_type = type;
|
||||
} else {
|
||||
delete query.publish_type;
|
||||
}
|
||||
|
||||
console.log('更新URL参数:', {
|
||||
oldQuery: this.$route.query,
|
||||
newQuery: query
|
||||
});
|
||||
|
||||
// 直接更新URL参数,不检查是否变化
|
||||
this.$router.replace({
|
||||
path: this.$route.path,
|
||||
query: query
|
||||
}).catch(err => {
|
||||
// 忽略重复导航错误
|
||||
if (err.name !== 'NavigationDuplicated') {
|
||||
console.error('更新URL参数失败:', err);
|
||||
} else {
|
||||
console.log('URL参数更新重复,忽略错误');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 提取纯文本内容
|
||||
extractPlainText(htmlText) {
|
||||
// 创建临时DOM元素来提取纯文本
|
||||
const tempDiv = document.createElement('div');
|
||||
tempDiv.innerHTML = htmlText;
|
||||
return tempDiv.textContent || tempDiv.innerText || '';
|
||||
},
|
||||
|
||||
// 处理类型选择变化
|
||||
handleTypeChange(value) {
|
||||
console.log('选择的类型:', value === '1' ? '商品' : '需求', value)
|
||||
this.publish_type = value
|
||||
|
||||
// 如果当前有搜索结果,重新搜索
|
||||
if (this.keyword.trim() && this.showSearchResults) {
|
||||
this.performSearch(this.keyword, value);
|
||||
}
|
||||
},
|
||||
|
||||
// 处理搜索
|
||||
handleSearch(result) {
|
||||
// 立即阻止事件传播,确保方法能被正确执行
|
||||
if (event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
console.log('=== handleSearch 开始执行 ===');
|
||||
console.log('接收到的参数:', result);
|
||||
console.log('当前路由路径:', this.$route.path);
|
||||
console.log('当前查询参数:', this.$route.query);
|
||||
|
||||
// 如果传入了result参数(来自联想结果),使用其product_name作为keyword
|
||||
if (result && result.product_name) {
|
||||
console.log('使用联想结果作为搜索关键词');
|
||||
const plainText = this.extractPlainText(result.product_name);
|
||||
this.keyword = plainText;
|
||||
console.log('提取的纯文本:', plainText);
|
||||
|
||||
// 立即隐藏搜索结果,避免被全局点击事件干扰
|
||||
this.showSearchResults = false;
|
||||
this.searchResults = [];
|
||||
} else {
|
||||
console.log('使用输入框的关键词进行搜索');
|
||||
// 如果没有传入result,检查输入框是否有内容
|
||||
if (!this.keyword.trim()) {
|
||||
this.$message.warning('请输入搜索关键词');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 执行搜索逻辑
|
||||
console.log('准备执行搜索,关键词:', this.keyword, '类型:', this.publish_type);
|
||||
|
||||
// 通过路由传参控制搜索行为
|
||||
const currentRoute = this.$route;
|
||||
const currentDisplayPage = currentRoute.query.display_page;
|
||||
|
||||
if (currentDisplayPage !== 'list') {
|
||||
// 不在搜索结果页面,需要跳转
|
||||
console.log('跳转到搜索结果页面');
|
||||
this.goSearch()
|
||||
} else {
|
||||
// 已经在搜索结果页面,重新调用接口获取最新数据
|
||||
console.log('已在搜索结果页面,重新调用接口获取最新数据');
|
||||
// 更新URL参数
|
||||
this.updateURLParams(this.keyword, this.publish_type);
|
||||
|
||||
// 重新调用搜索接口,获取最新数据
|
||||
this.performFormalSearch(this.keyword, this.publish_type);
|
||||
}
|
||||
|
||||
console.log('=== handleSearch 执行完成 ===');
|
||||
},
|
||||
|
||||
// 处理热门关键词点击
|
||||
handleHotKeywordClick(keyword) {
|
||||
this.keyword = keyword
|
||||
this.handleSearch()
|
||||
},
|
||||
|
||||
// 处理输入框聚焦
|
||||
handleInputFocus() {
|
||||
// 聚焦时不立即显示联想框,只有当有搜索结果时才显示
|
||||
if (this.keyword.trim() && this.searchResults.length > 0) {
|
||||
this.showSearchResults = true;
|
||||
}
|
||||
},
|
||||
|
||||
// 处理输入框失焦
|
||||
handleInputBlur() {
|
||||
// 延迟隐藏搜索结果,给用户点击联想结果的机会
|
||||
setTimeout(() => {
|
||||
if (!this.$el.contains(document.activeElement)) {
|
||||
this.hideSearchResults()
|
||||
}
|
||||
}, 100); // 延迟100ms
|
||||
},
|
||||
|
||||
// 手动隐藏搜索结果
|
||||
hideSearchResults() {
|
||||
this.showSearchResults = false
|
||||
this.searchResults = []
|
||||
},
|
||||
|
||||
// 处理全局点击事件
|
||||
handleGlobalClick(event) {
|
||||
// 延迟处理,避免干扰其他点击事件
|
||||
setTimeout(() => {
|
||||
// 检查点击是否在搜索框内部或联想结果内部
|
||||
if (this.$el && this.$el.contains(event.target)) {
|
||||
console.log('点击在搜索组件内部,不隐藏联想结果');
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果联想结果正在显示,则隐藏
|
||||
if (this.showSearchResults) {
|
||||
console.log('点击在搜索组件外部,隐藏联想结果');
|
||||
this.hideSearchResults();
|
||||
}
|
||||
}, 100); // 增加延迟到100ms,给其他事件处理器留出更多时间
|
||||
},
|
||||
|
||||
// 高亮显示搜索关键词
|
||||
highlightKeyword(item) {
|
||||
console.log(item)
|
||||
|
||||
if (!this.keyword || !this.keyword.trim()) {
|
||||
return item.product_name || item;
|
||||
}
|
||||
|
||||
const keyword = this.keyword.trim();
|
||||
// 使用 product_name 字段作为显示文本
|
||||
const text = item.product_name || item;
|
||||
|
||||
console.log('高亮处理:', { keyword, text, item, textType: typeof text });
|
||||
|
||||
// 如果关键词为空,直接返回原文本
|
||||
if (!keyword) {
|
||||
return text;
|
||||
}
|
||||
|
||||
// 如果文本为空或不是字符串,返回原文本
|
||||
if (!text || typeof text !== 'string') {
|
||||
console.warn('文本不是字符串类型:', text);
|
||||
return text;
|
||||
}
|
||||
|
||||
// 创建正则表达式,支持多个关键词(用空格分隔)
|
||||
const keywords = keyword.split(/\s+/).filter(k => k.length > 0);
|
||||
let highlightedText = text;
|
||||
|
||||
// 对每个关键词进行高亮处理
|
||||
keywords.forEach(key => {
|
||||
if (key.length > 0) {
|
||||
const regex = new RegExp(`(${this.escapeRegExp(key)})`, 'gi');
|
||||
highlightedText = highlightedText.replace(regex, '<span class="highlighted-keyword">$1</span>');
|
||||
}
|
||||
});
|
||||
|
||||
console.log('高亮结果:', highlightedText);
|
||||
return highlightedText;
|
||||
},
|
||||
|
||||
// 转义正则表达式特殊字符
|
||||
escapeRegExp(string) {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
},
|
||||
|
||||
// 处理路由变化
|
||||
handleRouteChange(to, from) {
|
||||
console.log('处理路由变化:', { to, from, currentKeyword: this.keyword });
|
||||
|
||||
const keyword = to.query.keyword;
|
||||
const publishType = to.query.publish_type;
|
||||
|
||||
if (keyword) {
|
||||
// 直接更新搜索状态,不检查是否相同
|
||||
console.log('更新搜索状态:', { keyword, publishType });
|
||||
this.keyword = keyword;
|
||||
this.publish_type = publishType || '1'; // 如果没有指定类型,默认为商品
|
||||
|
||||
// 确保组件状态正确初始化
|
||||
this.showSearchResults = false;
|
||||
this.searchResults = [];
|
||||
|
||||
// 重新绑定事件监听器,确保点击事件正常工作
|
||||
this.$nextTick(() => {
|
||||
this.reinitializeEventListeners();
|
||||
});
|
||||
|
||||
// 不在这里执行搜索,只更新状态
|
||||
// 搜索由用户点击搜索按钮或选择联想结果时触发
|
||||
console.log('搜索状态已更新,等待用户操作');
|
||||
} else {
|
||||
// 如果没有搜索参数,清空状态
|
||||
if (this.keyword || this.publish_type !== '1') {
|
||||
console.log('清空搜索状态');
|
||||
this.keyword = '';
|
||||
this.publish_type = '1';
|
||||
this.hideSearchResults();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 重新初始化事件监听器
|
||||
reinitializeEventListeners() {
|
||||
console.log('重新初始化事件监听器');
|
||||
|
||||
// 移除旧的监听器
|
||||
document.removeEventListener('click', this.handleGlobalClick);
|
||||
|
||||
// 重新添加新的监听器
|
||||
document.addEventListener('click', this.handleGlobalClick);
|
||||
|
||||
// 确保组件状态正确
|
||||
this.showSearchResults = false;
|
||||
this.searchResults = [];
|
||||
|
||||
console.log('事件监听器重新初始化完成');
|
||||
}
|
||||
},
|
||||
|
||||
// 组件挂载后添加全局点击事件监听
|
||||
mounted() {
|
||||
console.log('=== 组件挂载开始 ===');
|
||||
console.log('当前路由:', this.$route.path);
|
||||
console.log('当前查询参数:', this.$route.query);
|
||||
|
||||
document.addEventListener('click', this.handleGlobalClick)
|
||||
console.log('全局点击事件监听器已添加');
|
||||
|
||||
// 检查URL参数,如果有搜索参数则自动执行搜索
|
||||
this.handleRouteChange(this.$route, null);
|
||||
|
||||
// 添加路由监听,确保子路由变化时能正确处理
|
||||
this.$watch('$route', (to, from) => {
|
||||
console.log('路由变化监听:', { to, from });
|
||||
this.handleRouteChange(to, from);
|
||||
}, { immediate: true, deep: true });
|
||||
|
||||
console.log('=== 组件挂载完成 ===');
|
||||
},
|
||||
|
||||
// 组件销毁时清理定时器和事件监听器
|
||||
beforeDestroy() {
|
||||
if (this.searchTimeout) {
|
||||
clearTimeout(this.searchTimeout)
|
||||
}
|
||||
document.removeEventListener('click', this.handleGlobalClick)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -95,6 +562,7 @@ export default {
|
||||
border: 1px solid red;
|
||||
flex: 1;
|
||||
min-width: 850px;
|
||||
|
||||
.search-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -102,6 +570,14 @@ export default {
|
||||
border: 2px solid #3f68d8;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
transition: border-radius 0.2s ease;
|
||||
|
||||
// 当显示搜索结果时,隐藏下边框并调整圆角
|
||||
&.has-results {
|
||||
border-bottom-color: transparent;
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
flex: 1;
|
||||
@ -109,12 +585,7 @@ export default {
|
||||
border: none;
|
||||
outline: none;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.camera-icon {
|
||||
padding: 0 10px;
|
||||
color: #666;
|
||||
cursor: pointer;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.search-btn {
|
||||
@ -131,12 +602,68 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索结果样式
|
||||
.search-results {
|
||||
position: absolute;
|
||||
top: 42px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: white;
|
||||
border: 2px solid #3f68d8;
|
||||
border-top: none;
|
||||
border-radius: 0 0 4px 4px;
|
||||
z-index: 99999;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
|
||||
.search-result-item {
|
||||
padding: 12px 15px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
&:hover {
|
||||
background-color: #f5f7fa;
|
||||
|
||||
* {
|
||||
color: #0864dd!important;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.result-title {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.result-type {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
padding: 2px 8px;
|
||||
background: #f0f2f5;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.hot-search {
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.search-label {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.hot-keyword {
|
||||
&:nth-child(-n+3) {
|
||||
color: #e1251b;
|
||||
@ -153,6 +680,26 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .mySelect {
|
||||
input {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .highlighted-keyword {
|
||||
font-weight: bold;
|
||||
color: #0864dd;
|
||||
}
|
||||
|
||||
.logo-clickable {
|
||||
cursor: pointer;
|
||||
transition: opacity 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.search-section {
|
||||
width: 100%;
|
||||
|
||||
140
f/web-kboss/src/views/homePage/ncmatch/searchBox/index.vue
Normal file
140
f/web-kboss/src/views/homePage/ncmatch/searchBox/index.vue
Normal file
@ -0,0 +1,140 @@
|
||||
<template>
|
||||
<div class="searchBox">
|
||||
|
||||
<div v-if="loadData">
|
||||
<!-- <div class="loading">
|
||||
加载数据中...
|
||||
</div> -->
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-loading="loadData">
|
||||
<productCard :productList="list"></productCard>
|
||||
<el-pagination @current-change="handleCurrentChange" :current-page="current_page" :page-size="page_size"
|
||||
layout="total, prev, pager, next" :total="total">
|
||||
</el-pagination>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { reqSearch } from '@/api/ncmatch'
|
||||
import productCard from '../mainPage/productCard/index.vue'
|
||||
import eventBus from '@/utils/eventBus'
|
||||
export default {
|
||||
name: 'searchBox',
|
||||
components: {
|
||||
productCard
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
keyword: '',
|
||||
publish_type: '',
|
||||
display_page: '',
|
||||
current_page: 1,
|
||||
page_size: 8,
|
||||
list:[],
|
||||
total:0,
|
||||
loadData:false
|
||||
}
|
||||
},
|
||||
created(){
|
||||
console.log('=== searchBox 组件创建 ===');
|
||||
this.keyword = this.$route.query.keyword
|
||||
this.publish_type = this.$route.query.publish_type
|
||||
|
||||
this.initData()
|
||||
|
||||
// 监听搜索事件
|
||||
console.log('开始监听搜索事件');
|
||||
eventBus.$on('search', this.handleSearch)
|
||||
console.log('搜索事件监听器已添加');
|
||||
},
|
||||
mounted() {
|
||||
console.log('=== searchBox 组件挂载 ===');
|
||||
console.log('当前路由:', this.$route.path);
|
||||
console.log('当前查询参数:', this.$route.query);
|
||||
},
|
||||
beforeDestroy() {
|
||||
console.log('=== searchBox 组件销毁 ===');
|
||||
// 移除事件监听器,避免内存泄漏
|
||||
eventBus.$off('search', this.handleSearch)
|
||||
console.log('搜索事件监听器已移除');
|
||||
},
|
||||
methods: {
|
||||
handleCurrentChange(val) {
|
||||
console.log('分页变化:', val);
|
||||
this.current_page = val;
|
||||
this.initData();
|
||||
},
|
||||
handleSearch(searchData) {
|
||||
console.log('=== searchBox 接收到搜索事件 ===');
|
||||
console.log('搜索数据:', searchData);
|
||||
console.log('当前组件状态:', {
|
||||
keyword: this.keyword,
|
||||
publish_type: this.publish_type,
|
||||
list_length: this.list.length,
|
||||
total: this.total
|
||||
});
|
||||
|
||||
// 重置分页到第一页
|
||||
this.current_page = 1;
|
||||
console.log('分页已重置到第1页');
|
||||
|
||||
// 更新组件数据
|
||||
if (searchData.data && searchData.data.result) {
|
||||
console.log('更新搜索结果数据');
|
||||
this.list = searchData.data.result;
|
||||
this.total = searchData.data.total_count;
|
||||
console.log('数据更新完成:', {
|
||||
new_list_length: this.list.length,
|
||||
new_total: this.total
|
||||
});
|
||||
} else {
|
||||
console.warn('搜索数据格式不正确:', searchData);
|
||||
}
|
||||
|
||||
// 更新本地状态
|
||||
this.keyword = searchData.keyword;
|
||||
this.publish_type = searchData.type;
|
||||
console.log('本地状态已更新:', {
|
||||
new_keyword: this.keyword,
|
||||
new_publish_type: this.publish_type
|
||||
});
|
||||
|
||||
console.log('=== 搜索事件处理完成 ===');
|
||||
},
|
||||
|
||||
initData(){
|
||||
this.loadData = true
|
||||
reqSearch({
|
||||
url_link: window.location.href,
|
||||
keyword: this.keyword,
|
||||
publish_type: this.publish_type,
|
||||
display_page: 'list',
|
||||
current_page: this.current_page,
|
||||
page_size: this.page_size
|
||||
}).then(res => {
|
||||
console.log("@@@@",res);
|
||||
this.loadData = false
|
||||
if(res.status){
|
||||
this.list = res.data.result
|
||||
this.total = res.data.total_count
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.searchBox {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.searchBox {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
326
f/web-kboss/src/views/operation/menuMangement/index.vue
Normal file
326
f/web-kboss/src/views/operation/menuMangement/index.vue
Normal file
@ -0,0 +1,326 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 调试信息 -->
|
||||
<div style="margin-bottom: 20px; padding: 15px; background: #f5f7fa; border-radius: 8px;">
|
||||
<el-button size="small" @click="showDebugInfo">查看调试信息</el-button>
|
||||
<el-button size="small" @click="showRawData">查看原始数据</el-button>
|
||||
<el-button size="small" type="primary" @click="testTreeStructure">测试树形结构</el-button>
|
||||
<el-button size="small" type="success" @click="getCategories">重新加载数据</el-button>
|
||||
<span style="margin-left: 20px; color: #666;">
|
||||
数据总数: {{ tableData.length }} |
|
||||
树形层级: {{ getMaxLevel() }}级
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<el-table :data="tableData" style="width: 100%;margin-bottom: 20px;" row-key="id" border v-loading="loading"
|
||||
element-loading-text="加载中..." element-loading-spinner="el-icon-loading"
|
||||
:tree-props="{ children: 'children' }" :default-expand-all="false" :expand-on-click-node="false">
|
||||
<el-table-column prop="name" label="名称" min-width="120">
|
||||
</el-table-column>
|
||||
<el-table-column prop="id" label="id" min-width="200">
|
||||
</el-table-column>
|
||||
<el-table-column prop="level" label="层级" min-width="120">
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="280" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="small" @click="addNode(scope.row, 'sibling')">新增同级</el-button>
|
||||
<el-button type="text" size="small" @click="addNode(scope.row, 'child')">新增子级</el-button>
|
||||
<el-button type="text" size="small" @click="editNode(scope.row)">编辑</el-button>
|
||||
<el-button type="text" size="small" @click="deleteNode(scope.row)"
|
||||
style="color: #F56C6C;">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
|
||||
<el-drawer title="菜单管理" :visible.sync="drawer" :direction="direction">
|
||||
|
||||
<div style="margin: 20px;"></div>
|
||||
<el-form :label-position="labelPosition" label-width="80px" :model="formLabelAlign">
|
||||
<el-form-item label="菜单名称">
|
||||
<el-input v-model="formLabelAlign.name"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
</el-form>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { reqNcMatchMenu } from '@/api/ncmatch';
|
||||
export default {
|
||||
name: 'menuMangement',
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
categories: [],
|
||||
tableData: [], // 移除硬编码的测试数据
|
||||
drawer: false,
|
||||
direction: 'rtl',
|
||||
labelPosition: 'right',
|
||||
formLabelAlign: {
|
||||
name: '',
|
||||
region: '',
|
||||
type: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getCategories();
|
||||
},
|
||||
methods: {
|
||||
addNode(row, type) {
|
||||
this.drawer = true;
|
||||
console.log('新增节点:', row, '类型:', type);
|
||||
},
|
||||
getCategories() {
|
||||
this.loading = true;
|
||||
reqNcMatchMenu({ url_link: window.location.href }).then(res => {
|
||||
this.loading = false;
|
||||
if (res.status) {
|
||||
this.categories = this.buildSimpleTree(res.data);
|
||||
this.tableData = this.categories; // 使用精简的树形结构
|
||||
console.log("构建的精简树结构:", this.categories);
|
||||
}
|
||||
}).catch(error => {
|
||||
this.loading = false;
|
||||
console.error('获取菜单数据失败:', error);
|
||||
});
|
||||
},
|
||||
editNode(row) {
|
||||
this.drawer = true;
|
||||
console.log('编辑节点:', row);
|
||||
},
|
||||
deleteNode(row) {
|
||||
this.drawer = true;
|
||||
console.log('删除节点:', row);
|
||||
},
|
||||
buildTree(data, parentId = null) {
|
||||
if (!Array.isArray(data)) {
|
||||
console.log('数据不是数组:', data);
|
||||
return [];
|
||||
}
|
||||
|
||||
console.log('构建树结构,当前parentId:', parentId, '数据长度:', data.length);
|
||||
|
||||
// 找出当前层级的节点
|
||||
const currentNodes = data.filter(item => {
|
||||
// 处理顶级节点(parentid 为 null 或空字符串)
|
||||
if (parentId === null) {
|
||||
return !item.parentid || item.parentid === '' || item.parentid === '0';
|
||||
}
|
||||
return item.parentid === parentId;
|
||||
});
|
||||
|
||||
console.log('当前层级节点数量:', currentNodes.length, '节点:', currentNodes);
|
||||
|
||||
if (currentNodes.length === 0) return [];
|
||||
|
||||
// 处理每个节点
|
||||
return currentNodes.map(node => {
|
||||
const resultNode = {
|
||||
id: node.id,
|
||||
name: node.name || '未命名',
|
||||
parentid: node.parentid
|
||||
};
|
||||
|
||||
// 递归处理子节点
|
||||
const children = this.buildSimpleTree(data, node.id);
|
||||
|
||||
// 只有当有子节点时才添加 children 字段
|
||||
if (children && children.length > 0) {
|
||||
resultNode.children = children;
|
||||
}
|
||||
|
||||
return resultNode;
|
||||
});
|
||||
},
|
||||
|
||||
// 精简的树形结构构建方法
|
||||
buildSimpleTree(data, parentId = null) {
|
||||
if (!Array.isArray(data)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// 找出当前层级的节点
|
||||
const currentNodes = data.filter(item => {
|
||||
if (parentId === null) {
|
||||
return !item.parentid || item.parentid === '' || item.parentid === '0';
|
||||
}
|
||||
return item.parentid === parentId;
|
||||
});
|
||||
|
||||
if (currentNodes.length === 0) return [];
|
||||
|
||||
// 处理每个节点,只保留必要字段
|
||||
return currentNodes.map(node => {
|
||||
const resultNode = {
|
||||
id: node.id,
|
||||
name: node.name || '未命名',
|
||||
parentid: node.parentid
|
||||
};
|
||||
|
||||
// 递归处理子节点
|
||||
const children = this.buildSimpleTree(data, node.id);
|
||||
|
||||
// 只有当有子节点时才添加 children 字段
|
||||
if (children && children.length > 0) {
|
||||
resultNode.children = children;
|
||||
}
|
||||
|
||||
return resultNode;
|
||||
});
|
||||
},
|
||||
|
||||
// 计算节点层级
|
||||
calculateLevel(data, nodeId) {
|
||||
let level = 1;
|
||||
let currentId = nodeId;
|
||||
|
||||
while (true) {
|
||||
const parent = data.find(item => item.id === currentId);
|
||||
if (!parent || !parent.parentid || parent.parentid === '' || parent.parentid === '0') {
|
||||
break;
|
||||
}
|
||||
level++;
|
||||
currentId = parent.parentid;
|
||||
}
|
||||
|
||||
return level;
|
||||
},
|
||||
showDebugInfo() {
|
||||
console.log("当前 tableData 的结构:", this.tableData);
|
||||
console.log("当前 tableData 的层级分布:", this.getLevelDistribution());
|
||||
console.log("当前 tableData 的最大层级:", this.getMaxLevel());
|
||||
|
||||
// 检查树形结构
|
||||
this.checkTreeStructure(this.tableData);
|
||||
},
|
||||
|
||||
// 检查树形结构
|
||||
checkTreeStructure(nodes, level = 0) {
|
||||
if (!Array.isArray(nodes)) return;
|
||||
|
||||
nodes.forEach(node => {
|
||||
const indent = ' '.repeat(level);
|
||||
console.log(`${indent}📁 ${node.name} (ID: ${node.id})`);
|
||||
console.log(`${indent} - hasChildren: ${node.hasChildren}`);
|
||||
console.log(`${indent} - children.length: ${node.children ? node.children.length : 'undefined'}`);
|
||||
console.log(`${indent} - level: ${node.level}`);
|
||||
|
||||
if (node.children && node.children.length > 0) {
|
||||
this.checkTreeStructure(node.children, level + 1);
|
||||
}
|
||||
});
|
||||
},
|
||||
showRawData() {
|
||||
console.log("原始数据:", this.categories);
|
||||
},
|
||||
|
||||
// 测试树形结构
|
||||
testTreeStructure() {
|
||||
const testData = [
|
||||
{
|
||||
id: 1,
|
||||
name: '一级菜单1',
|
||||
parentid: null
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '一级菜单2',
|
||||
parentid: null
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '一级菜单3',
|
||||
parentid: null,
|
||||
children: [
|
||||
{
|
||||
id: 31,
|
||||
name: '二级菜单3-1',
|
||||
parentid: 3
|
||||
},
|
||||
{
|
||||
id: 32,
|
||||
name: '二级菜单3-2',
|
||||
parentid: 3,
|
||||
children: [
|
||||
{
|
||||
id: 321,
|
||||
name: '三级菜单3-2-1',
|
||||
parentid: 32
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
console.log("精简测试数据:", testData);
|
||||
this.tableData = testData;
|
||||
},
|
||||
getLevelDistribution() {
|
||||
const levels = {};
|
||||
this.tableData.forEach(node => {
|
||||
const level = node.level;
|
||||
if (levels[level]) {
|
||||
levels[level]++;
|
||||
} else {
|
||||
levels[level] = 1;
|
||||
}
|
||||
});
|
||||
return levels;
|
||||
},
|
||||
getMaxLevel() {
|
||||
let maxLevel = 0;
|
||||
this.tableData.forEach(node => {
|
||||
if (node.level > maxLevel) {
|
||||
maxLevel = node.level;
|
||||
}
|
||||
});
|
||||
return maxLevel;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.el-table {
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.el-table th {
|
||||
background-color: #f5f7fa;
|
||||
color: #606266;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.el-table td {
|
||||
padding: 12px 0;
|
||||
}
|
||||
|
||||
.el-button--text {
|
||||
padding: 4px 8px;
|
||||
margin: 0 2px;
|
||||
}
|
||||
|
||||
.el-button--text:hover {
|
||||
background-color: #f5f7fa;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.el-tag {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* 树形表格的缩进样式 */
|
||||
.el-table__expand-icon {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
/* 加载状态样式 */
|
||||
.el-loading-mask {
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
</style>
|
||||
Loading…
x
Reference in New Issue
Block a user