|
|
@@ -1,308 +1,447 @@
|
|
|
<template>
|
|
|
- <el-dialog v-model="dialogVisible" title="选择链接" width="65%" @close="handleClose">
|
|
|
- <div class="link-selector-container">
|
|
|
- <!-- 左侧树状结构导航 -->
|
|
|
- <div class="tree-container">
|
|
|
- <el-tree ref="treeRef" :data="treeData" node-key="id" :props="defaultProps" @node-click="handleNodeClick" default-expand-all></el-tree>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 右侧链接内容 -->
|
|
|
- <div class="links-container">
|
|
|
- <div v-if="selectedCategory" class="category-title">{{ selectedCategory.title || selectedCategory.name }}</div>
|
|
|
- <div v-else class="category-title">基础链接</div>
|
|
|
-
|
|
|
- <!-- 链接区域 -->
|
|
|
- <div class="link-list-container">
|
|
|
- <!-- 商品链接选择区域 -->
|
|
|
- <div v-if="isProductCategoryComputed" class="product-selection-container">
|
|
|
- <!-- 搜索框 -->
|
|
|
- <div class="product-search">
|
|
|
- <el-input v-model="productSearchKeyword" placeholder="请输入商品名称关键词" clearable @keyup.enter="handleProductSearch" />
|
|
|
- <el-button type="primary" @click="handleProductSearch">搜索</el-button>
|
|
|
+ <div>
|
|
|
+ <el-dialog v-model="showDialog" title="选择链接" width="1000">
|
|
|
+ <div class="dialog-bos">
|
|
|
+ <div class="menu-container">
|
|
|
+ <el-menu @select="onMenu" style="height: 100%" :default-openeds="defaultOpeneds" :default-active="defaultActive" v-if="menuData.length > 0">
|
|
|
+ <template v-for="(item1, index1) in menuData" :key="index1">
|
|
|
+ <el-sub-menu :index="index1 + ''" v-if="item1.children && item1.children.length > 0">
|
|
|
+ <template #title>{{ item1.name }}</template>
|
|
|
+ <el-menu-item v-for="(item2, index2) in item1.children" :key="index2" :index="index1 + '-' + index2">{{ item2.name }}</el-menu-item>
|
|
|
+ </el-sub-menu>
|
|
|
+ <el-menu-item v-else :index="index1 + ''">{{ item1.name }}</el-menu-item>
|
|
|
+ </template>
|
|
|
+ </el-menu>
|
|
|
+ </div>
|
|
|
+ <div class="dialog-box">
|
|
|
+ <template v-if="boxShow1">
|
|
|
+ <div v-for="(item1, index1) in boxData" :key="index1">
|
|
|
+ <h5 class="button-title">
|
|
|
+ <div class="title">{{ item1.name }}</div>
|
|
|
+ <div v-if="index1 == 0">
|
|
|
+ <span class="mr-[5px]">是否新窗口打开</span>
|
|
|
+ <el-switch v-model="switchVal" />
|
|
|
+ </div>
|
|
|
+ </h5>
|
|
|
+ <div class="button-container">
|
|
|
+ <el-button
|
|
|
+ @click="onSelected(item2)"
|
|
|
+ :type="item2.url == selected ? 'primary' : ''"
|
|
|
+ v-for="(item2, index2) in item1.children"
|
|
|
+ :key="index2"
|
|
|
+ >{{ item2.name }}</el-button
|
|
|
+ >
|
|
|
+ </div>
|
|
|
</div>
|
|
|
-
|
|
|
- <!-- 商品列表 -->
|
|
|
- <div class="product-list">
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <div v-if="boxpageKey == 'goodsClassify'">
|
|
|
+ <div>
|
|
|
+ <span class="mr-[5px]">是否新窗口打开</span>
|
|
|
+ <el-switch v-model="switchVal" />
|
|
|
+ </div>
|
|
|
<el-table
|
|
|
- :data="productList"
|
|
|
- :style="{ width: '100%' }"
|
|
|
- :row-class-name="({ row }) => (selectedProduct?.id === row.id ? 'product-row-active' : '')"
|
|
|
- @row-click="handleProductSelect"
|
|
|
- class="custom-product-table"
|
|
|
+ style="width: 100%"
|
|
|
+ height="546px"
|
|
|
+ v-loading="loading1"
|
|
|
+ :data="tableData1"
|
|
|
+ row-key="id"
|
|
|
+ border
|
|
|
+ lazy
|
|
|
+ :load="loadChildren"
|
|
|
+ :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
|
|
>
|
|
|
- <el-table-column width="80">
|
|
|
+ <el-table-column width="120" align="center">
|
|
|
<template #default="{ row }">
|
|
|
- <el-radio :model-value="selectedProduct?.id" :label="row.id" @change="() => handleProductSelect(row)" />
|
|
|
+ <el-checkbox v-model="tableId1" :true-value="row.id" @change="handleCheckboxChange(row)" />
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column label="ID" prop="id" width="180" />
|
|
|
- <el-table-column label="图片" width="120">
|
|
|
- <template #default="{ row }">
|
|
|
- <el-image
|
|
|
- :src="row.image || ''"
|
|
|
- style="width: 80px; height: 60px; object-fit: cover; display: block"
|
|
|
- :preview-src-list="row.image ? [row.image] : []"
|
|
|
- >
|
|
|
- <template #error>
|
|
|
- <div class="image-slot">
|
|
|
- <el-icon><Picture /></el-icon>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- </el-image>
|
|
|
+ <el-table-column prop="categoryName" label="分类名称" minWidth="260"></el-table-column>
|
|
|
+ <el-table-column prop="classLevel" align="center" label="分类级别" width="150">
|
|
|
+ <template #default="scope">
|
|
|
+ <span>{{ scope.row.classLevel }}级</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column prop="name" label="商品名称">
|
|
|
- <template #default="{ row }">
|
|
|
- <div class="product-name">{{ row.name }}</div>
|
|
|
+ <el-table-column prop="platform" align="center" label="平台" width="150">
|
|
|
+ <template #default="scope">
|
|
|
+ <span>{{ scope.row.platform === 0 ? '工业品' : scope.row.platform === 1 ? 'PC端' : '未知' }}</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
</div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 文章链接选择区域 -->
|
|
|
- <div v-else-if="isArticleCategoryComputed" class="article-selection-container">
|
|
|
- <!-- 搜索框 -->
|
|
|
- <div class="product-search">
|
|
|
- <el-input v-model="articleSearchKeyword" placeholder="请输入文章标题关键词" clearable @keyup.enter="handleArticleSearch" />
|
|
|
- <el-button type="primary" @click="handleArticleSearch">搜索</el-button>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 文章列表 -->
|
|
|
- <div class="article-list">
|
|
|
- <el-table
|
|
|
- :data="articleList"
|
|
|
- :style="{ width: '100%' }"
|
|
|
- :row-class-name="({ row }) => (selectedArticle?.id === row.id ? 'article-row-active' : '')"
|
|
|
- @row-click="handleArticleSelect"
|
|
|
- class="custom-article-table"
|
|
|
- >
|
|
|
- <el-table-column width="80">
|
|
|
+ <!-- 商品 -->
|
|
|
+ <div v-if="boxpageKey == 'goodsItem'">
|
|
|
+ <div class="flex justify-between">
|
|
|
+ <el-input v-model="queryParams2.itemName" placeholder="请输入商品名称" clearable style="width: 300px; margin-bottom: 10px">
|
|
|
+ <template #append>
|
|
|
+ <el-button :icon="Search" @click="handleQuery2" />
|
|
|
+ </template>
|
|
|
+ </el-input>
|
|
|
+ <div>
|
|
|
+ <span class="mr-[5px]">是否新窗口打开</span>
|
|
|
+ <el-switch v-model="switchVal" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <el-table height="480" ref="multipleTableRef" v-loading="loading2" :data="tableData2" border>
|
|
|
+ <el-table-column width="80" align="center">
|
|
|
<template #default="{ row }">
|
|
|
- <el-radio :model-value="selectedArticle?.id" :label="row.id" @change="() => handleArticleSelect(row)" />
|
|
|
+ <el-checkbox v-model="tableId2" :true-value="row.productNo" />
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column label="ID" prop="id" width="180" />
|
|
|
- <el-table-column prop="title" label="文章标题">
|
|
|
- <template #default="{ row }">
|
|
|
- <div class="article-title">{{ row.title }}</div>
|
|
|
+ <el-table-column label="商品图片" align="center" prop="productImage" width="100">
|
|
|
+ <template #default="scope">
|
|
|
+ <image-preview :src="scope.row.productImage" :width="60" :height="60" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="商品信息" align="center" minWidth="250" show-overflow-tooltip>
|
|
|
+ <template #default="scope">
|
|
|
+ <div class="text-left">
|
|
|
+ <div>{{ scope.row.itemName }}</div>
|
|
|
+ <div class="text-gray-500" style="font-size: 12px">品牌: {{ scope.row.brandName || '-' }}</div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="SKU价格" align="center" width="180">
|
|
|
+ <template #default="scope">
|
|
|
+ <div class="text-left" style="font-size: 12px">
|
|
|
+ <div>
|
|
|
+ <span class="text-gray-500">市场价:</span>
|
|
|
+ <span class="text-red-500">¥{{ scope.row.marketPrice || '0.00' }}</span>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span class="text-gray-500">会员价:</span>
|
|
|
+ <span class="text-red-500">¥{{ scope.row.memberPrice || '0.00' }}</span>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span class="text-gray-500">最低价:</span>
|
|
|
+ <span class="text-red-500">¥{{ scope.row.minSellingPrice || '0.00' }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="成本情况" align="center" width="150">
|
|
|
+ <template #default="scope">
|
|
|
+ <div class="text-left" style="font-size: 12px">
|
|
|
+ <div>
|
|
|
+ <span class="text-gray-500">采购价:</span>
|
|
|
+ <span>¥{{ scope.row.purchasingPrice || '0.00' }}</span>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span class="text-gray-500">暂估毛利率:</span>
|
|
|
+ <span>{{ scope.row.tempGrossMargin || '0.0000' }}%</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
+ <pagination
|
|
|
+ v-show="tableData2.length > 0"
|
|
|
+ v-model:page="queryParams2.pageNum"
|
|
|
+ v-model:limit="queryParams2.pageSize"
|
|
|
+ v-model:way="queryParams2.way"
|
|
|
+ :cursor-mode="true"
|
|
|
+ :has-more="hasMore2"
|
|
|
+ @pagination="getTableData2"
|
|
|
+ />
|
|
|
</div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 微页面链接选择区域 -->
|
|
|
- <div v-else-if="isMicropageCategoryComputed" class="micropage-selection-container">
|
|
|
- <!-- 搜索框 -->
|
|
|
- <div class="product-search">
|
|
|
- <el-input v-model="micropageSearchKeyword" placeholder="请输入微页面名称关键词" clearable @keyup.enter="handleMicropageSearch" />
|
|
|
- <el-button type="primary" @click="handleMicropageSearch">搜索</el-button>
|
|
|
+ <!-- 采购方案 -->
|
|
|
+ <div v-if="boxpageKey == 'plan'">
|
|
|
+ <div class="flex justify-between">
|
|
|
+ <el-input v-model="queryParams3.tweetsTitle" placeholder="请输入方案主题" clearable style="width: 300px; margin-bottom: 10px">
|
|
|
+ <template #append>
|
|
|
+ <el-button :icon="Search" @click="handleQuery3" />
|
|
|
+ </template>
|
|
|
+ </el-input>
|
|
|
+ <div>
|
|
|
+ <span class="mr-[5px]">是否新窗口打开</span>
|
|
|
+ <el-switch v-model="switchVal" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <el-table v-loading="loading3" border :data="tableData3" height="480">
|
|
|
+ <el-table-column width="80" align="center">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-checkbox v-model="tableId3" :true-value="row.id" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="方案编号" align="center" prop="programNo" width="120" />
|
|
|
+ <el-table-column label="封面图片" align="center" prop="coverImage" width="100">
|
|
|
+ <template #default="scope">
|
|
|
+ <image-preview :src="scope.row.coverImage" :width="50" :height="50" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="方案主题" align="center" prop="tweetsTitle" show-overflow-tooltip />
|
|
|
+ <el-table-column label="发布时间" align="center" prop="createTime" width="180">
|
|
|
+ <template #default="scope">
|
|
|
+ <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ <pagination
|
|
|
+ v-show="total3 > 0"
|
|
|
+ :total="total3"
|
|
|
+ v-model:page="queryParams3.pageNum"
|
|
|
+ v-model:limit="queryParams3.pageSize"
|
|
|
+ @pagination="getTableData3"
|
|
|
+ />
|
|
|
</div>
|
|
|
-
|
|
|
- <!-- 微页面列表 -->
|
|
|
- <div class="micropage-list">
|
|
|
- <el-table
|
|
|
- :data="micropageList"
|
|
|
- :style="{ width: '100%' }"
|
|
|
- :row-class-name="({ row }) => (selectedMicropage?.id === row.id ? 'micropage-row-active' : '')"
|
|
|
- @row-click="handleMicropageSelect"
|
|
|
- class="custom-micropage-table"
|
|
|
- >
|
|
|
- <el-table-column width="80">
|
|
|
+ <!-- 产品推荐 -->
|
|
|
+ <div v-if="boxpageKey == 'procure'">
|
|
|
+ <div class="flex justify-between">
|
|
|
+ <el-input v-model="queryParams4.title" placeholder="请输入推文标题" clearable style="width: 300px; margin-bottom: 10px">
|
|
|
+ <template #append>
|
|
|
+ <el-button :icon="Search" @click="handleQuery4" />
|
|
|
+ </template>
|
|
|
+ </el-input>
|
|
|
+ <div>
|
|
|
+ <span class="mr-[5px]">是否新窗口打开</span>
|
|
|
+ <el-switch v-model="switchVal" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <el-table v-loading="loading4" border :data="tableData4" height="480">
|
|
|
+ <el-table-column width="80" align="center">
|
|
|
<template #default="{ row }">
|
|
|
- <el-radio :model-value="selectedMicropage?.id" :label="row.id" @change="() => handleMicropageSelect(row)" />
|
|
|
+ <el-checkbox v-model="tableId4" :true-value="row.id" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="封面图片" align="center" prop="coverImageUrl" width="120">
|
|
|
+ <template #default="scope">
|
|
|
+ <image-preview :src="scope.row.coverImage" :width="60" :height="60" />
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column label="ID" prop="id" width="180" />
|
|
|
- <el-table-column prop="name" label="标题名称名称">
|
|
|
+ <el-table-column label="推文标题" align="center" prop="title" min-width="200" show-overflow-tooltip>
|
|
|
+ <template #default="scope">
|
|
|
+ {{ scope.row.title }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ <pagination
|
|
|
+ v-show="total4 > 0"
|
|
|
+ :total="total4"
|
|
|
+ v-model:page="queryParams4.pageNum"
|
|
|
+ v-model:limit="queryParams4.pageSize"
|
|
|
+ @pagination="getTableData4"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <!-- 采购指南 -->
|
|
|
+ <div v-if="boxpageKey == 'guide'">
|
|
|
+ <div class="flex justify-between">
|
|
|
+ <el-input v-model="queryParams5.title" placeholder="请输入标题" clearable style="width: 300px; margin-bottom: 10px">
|
|
|
+ <template #append>
|
|
|
+ <el-button :icon="Search" @click="handleQuery5" />
|
|
|
+ </template>
|
|
|
+ </el-input>
|
|
|
+ <div>
|
|
|
+ <span class="mr-[5px]">是否新窗口打开</span>
|
|
|
+ <el-switch v-model="switchVal" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <el-table v-loading="loading5" border :data="tableData5" height="480">
|
|
|
+ <el-table-column width="80" align="center">
|
|
|
<template #default="{ row }">
|
|
|
- <div class="micropage-name">{{ row.name }}</div>
|
|
|
+ <el-checkbox v-model="tableId5" :true-value="row.id" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="标题" align="center" prop="title" min-width="200" show-overflow-tooltip>
|
|
|
+ <template #default="scope">
|
|
|
+ {{ scope.row.title }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="发布时间" align="center" prop="releaseTime" width="120">
|
|
|
+ <template #default="scope">
|
|
|
+ <span>{{ parseTime(scope.row.releaseTime, '{y}-{m}-{d}') }}</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
+ <pagination
|
|
|
+ v-show="total5 > 0"
|
|
|
+ :total="total5"
|
|
|
+ v-model:page="queryParams5.pageNum"
|
|
|
+ v-model:limit="queryParams5.pageSize"
|
|
|
+ @pagination="getTableData5"
|
|
|
+ />
|
|
|
</div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 自定义链接输入区域 -->
|
|
|
- <div v-else-if="isCustomLinkCategory" class="custom-link-container">
|
|
|
- <el-form label-position="top">
|
|
|
- <el-form-item label="跳转路径">
|
|
|
- <el-input
|
|
|
- v-model="customLinkPath"
|
|
|
- placeholder="请输入跳转路径"
|
|
|
- clearable
|
|
|
- @input="() => emit('update:modelValue', customLinkPath.trim())"
|
|
|
- >
|
|
|
- <template #prefix>
|
|
|
- <el-icon><Aim /></el-icon>
|
|
|
+ <!-- 项目案例 -->
|
|
|
+ <div v-if="boxpageKey == 'project'">
|
|
|
+ <div class="flex justify-between">
|
|
|
+ <el-input v-model="queryParams6.caseTitle" placeholder="请输入标题" clearable style="width: 300px; margin-bottom: 10px">
|
|
|
+ <template #append>
|
|
|
+ <el-button :icon="Search" @click="handleQuery6" />
|
|
|
</template>
|
|
|
</el-input>
|
|
|
- <div class="custom-link-tips">
|
|
|
- <el-icon size="14"><Warning /></el-icon>
|
|
|
- <span>请确保链接格式正确,支持相对路径和绝对路径</span>
|
|
|
+ <div>
|
|
|
+ <span class="mr-[5px]">是否新窗口打开</span>
|
|
|
+ <el-switch v-model="switchVal" />
|
|
|
</div>
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 预设链接展示区域 -->
|
|
|
- <div v-else class="links-grid">
|
|
|
- <el-button
|
|
|
- v-for="link in currentLinks"
|
|
|
- :key="link.id"
|
|
|
- size="small"
|
|
|
- :class="['link-button', { active: selectedLink && selectedLink.id === link.id }]"
|
|
|
- :type="selectedLink && selectedLink.id === link.id ? 'primary' : 'default'"
|
|
|
- :title="link.url"
|
|
|
- @click="handleLinkClick(link)"
|
|
|
- >
|
|
|
- {{ link.name }}
|
|
|
- </el-button>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 链接预览 -->
|
|
|
- <div v-if="selectedLink || (isCustomLinkCategory && customLinkPath)" class="link-preview">
|
|
|
- <span class="preview-label">当前选择:</span>
|
|
|
- <span v-if="selectedLink" class="preview-name">{{ selectedLink.name }}</span>
|
|
|
- <span v-else class="preview-name">自定义链接</span>
|
|
|
- <span class="preview-path">{{ selectedLink ? selectedLink.url : customLinkPath }}</span>
|
|
|
- </div>
|
|
|
+ </div>
|
|
|
+ <el-table v-loading="loading6" border :data="tableData6" height="480">
|
|
|
+ <el-table-column width="80" align="center">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-checkbox v-model="tableId6" :true-value="row.id" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="封面图片" align="center" width="120">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-image
|
|
|
+ :src="row.caseImage"
|
|
|
+ fit="cover"
|
|
|
+ style="width: 80px; height: 60px; border-radius: 4px"
|
|
|
+ :preview-src-list="[row.caseImage]"
|
|
|
+ preview-teleported
|
|
|
+ lazy
|
|
|
+ >
|
|
|
+ <template #error>
|
|
|
+ <div class="image-placeholder">
|
|
|
+ <el-icon><Picture /></el-icon>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-image>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="标题" align="center" prop="caseTitle" min-width="200" show-overflow-tooltip>
|
|
|
+ <template #default="scope">
|
|
|
+ {{ scope.row.caseTitle }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="发布时间" align="center" prop="createTime" width="120">
|
|
|
+ <template #default="scope">
|
|
|
+ <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ <pagination
|
|
|
+ v-show="total6 > 0"
|
|
|
+ :total="total6"
|
|
|
+ v-model:page="queryParams6.pageNum"
|
|
|
+ v-model:limit="queryParams6.pageSize"
|
|
|
+ @pagination="getTableData6"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <!-- 自定义 -->
|
|
|
+ <div v-if="boxpageKey == 'zdy'">
|
|
|
+ <div class="flex justify-between">
|
|
|
+ <el-input v-model="input" placeholder="请输入自定义链接" clearable style="width: 300px; margin-bottom: 10px"></el-input>
|
|
|
+ <div>
|
|
|
+ <span class="mr-[5px]">是否新窗口打开</span>
|
|
|
+ <el-switch v-model="switchVal" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 底部按钮 -->
|
|
|
- <template #footer>
|
|
|
- <el-button @click="handleCancel">取消</el-button>
|
|
|
- <el-button type="primary" @click="handleConfirm">确定</el-button>
|
|
|
- </template>
|
|
|
- </el-dialog>
|
|
|
+ <template #footer>
|
|
|
+ <span class="dialog-footer">
|
|
|
+ <el-button @click="showDialog = false">取消</el-button>
|
|
|
+ <el-button type="primary" @click="onConfirm">确认</el-button>
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
-import { ref, computed, watch, nextTick, onMounted, onUnmounted } from 'vue';
|
|
|
-import type { TreeNode } from 'element-plus';
|
|
|
-import { ElMessage } from 'element-plus';
|
|
|
-import { Aim, Warning, Picture } from '@element-plus/icons-vue';
|
|
|
import { getCategoryTree } from '@/api/mall/pageCategory/api';
|
|
|
import { listPageLink } from '@/api/mall/pageLink/api';
|
|
|
-import { pcDiyList } from '@/api/diy/index';
|
|
|
+import { CategoryVO } from '@/api/product/category/types';
|
|
|
+import { listCategory } from '@/api/product/category';
|
|
|
+import { Search } from '@element-plus/icons-vue';
|
|
|
import { listBase } from '@/api/pmsProduct/base';
|
|
|
+import { listProgram } from '@/api/product/program/index';
|
|
|
+import { programList } from '@/api/pmsProduct/program';
|
|
|
+import { listTopics } from '@/api/product/topics';
|
|
|
import { listServiceCase } from '@/api/product/serviceCase';
|
|
|
-
|
|
|
-interface LinkItem {
|
|
|
- id: string;
|
|
|
- name: string;
|
|
|
- url: string;
|
|
|
-}
|
|
|
-
|
|
|
-// 商品数据接口
|
|
|
-interface ProductItem {
|
|
|
- id: number;
|
|
|
- name: string;
|
|
|
- image: string;
|
|
|
-}
|
|
|
-
|
|
|
-// 文章数据接口
|
|
|
-interface ArticleItem {
|
|
|
- id: number;
|
|
|
- title: string;
|
|
|
-}
|
|
|
-
|
|
|
-// 微页面数据接口
|
|
|
-interface MicropageItem {
|
|
|
- id: number;
|
|
|
- name: string;
|
|
|
-}
|
|
|
-
|
|
|
-// Props
|
|
|
-interface Props {
|
|
|
- visible: boolean;
|
|
|
- modelValue?: string;
|
|
|
-}
|
|
|
-
|
|
|
-const props = withDefaults(defineProps<Props>(), {
|
|
|
- visible: false,
|
|
|
- modelValue: ''
|
|
|
+const showDialog = ref(false);
|
|
|
+const menuData = ref<any[]>([]);
|
|
|
+const defaultOpeneds = ref<any>(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']);
|
|
|
+const defaultActive = ref('0-0');
|
|
|
+const boxData = ref<any>([]);
|
|
|
+const boxpageKey = ref<any>(null);
|
|
|
+const selected = ref<any>(null);
|
|
|
+const switchVal = ref<any>(true);
|
|
|
+//分类的列表
|
|
|
+const tableId1 = ref<any>(null);
|
|
|
+const loading1 = ref(true);
|
|
|
+const tableData1 = ref<any>([]);
|
|
|
+const selectedRowObj = ref<any>(null);
|
|
|
+// 存储懒加载的子节点加载状态和 resolve 函数
|
|
|
+const lazyTreeNodeMap = ref<Map<string | number, { tree: any; treeNode: any; resolve: (data: CategoryVO[]) => void }>>(new Map());
|
|
|
+//商品列表
|
|
|
+const tableId2 = ref<any>(null);
|
|
|
+const total2 = ref(0);
|
|
|
+const loading2 = ref(true);
|
|
|
+const tableData2 = ref<any>([]);
|
|
|
+const hasMore2 = ref(true); // 是否还有更多数据
|
|
|
+const queryParams2 = reactive({
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ way: undefined,
|
|
|
+ itemName: ''
|
|
|
});
|
|
|
-
|
|
|
-// Emits
|
|
|
-interface Emits {
|
|
|
- 'update:visible': [value: boolean];
|
|
|
- 'update:modelValue': [value: string];
|
|
|
- 'confirm': [value: string, link: LinkItem];
|
|
|
- 'cancel': [];
|
|
|
- 'close': [];
|
|
|
- 'reset': [];
|
|
|
-}
|
|
|
-
|
|
|
-const emit = defineEmits<Emits>();
|
|
|
-
|
|
|
-// 响应式数据
|
|
|
-const dialogVisible = computed({
|
|
|
- get: () => props.visible,
|
|
|
- set: (value) => emit('update:visible', value)
|
|
|
+//采购方案
|
|
|
+const tableId3 = ref<any>(null);
|
|
|
+const total3 = ref(0);
|
|
|
+const loading3 = ref(true);
|
|
|
+const tableData3 = ref<any>([]);
|
|
|
+const queryParams3 = reactive({
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ tweetsTitle: ''
|
|
|
});
|
|
|
+//产品推荐
|
|
|
+const tableId4 = ref<any>(null);
|
|
|
+const total4 = ref(0);
|
|
|
+const loading4 = ref(true);
|
|
|
+const tableData4 = ref<any>([]);
|
|
|
+const queryParams4 = reactive({
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ title: ''
|
|
|
+});
|
|
|
+//采购指南
|
|
|
+const tableId5 = ref<any>(null);
|
|
|
+const total5 = ref(0);
|
|
|
+const loading5 = ref(true);
|
|
|
+const tableData5 = ref<any>([]);
|
|
|
+const queryParams5 = reactive({
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ title: ''
|
|
|
+});
|
|
|
+//项目案例
|
|
|
+const tableId6 = ref<any>(null);
|
|
|
+const total6 = ref(0);
|
|
|
+const loading6 = ref(true);
|
|
|
+const tableData6 = ref<any>([]);
|
|
|
+const queryParams6 = reactive({
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ caseTitle: ''
|
|
|
+});
|
|
|
+//自定义
|
|
|
+const input = ref('');
|
|
|
|
|
|
-const treeRef = ref<InstanceType<(typeof import('element-plus'))['ElTree']>>();
|
|
|
-const selectedCategory = ref<any>();
|
|
|
-const selectedLink = ref<LinkItem>();
|
|
|
-const customLinkPath = ref('');
|
|
|
-const selectedProduct = ref<ProductItem>();
|
|
|
-const productList = ref<ProductItem[]>([]);
|
|
|
-const productSearchKeyword = ref('');
|
|
|
-const isProductCategory = ref(false);
|
|
|
-
|
|
|
-// 文章相关响应式数据
|
|
|
-const selectedArticle = ref<ArticleItem>();
|
|
|
-const articleList = ref<ArticleItem[]>([]);
|
|
|
-const articleSearchKeyword = ref('');
|
|
|
-const isArticleCategory = ref(false);
|
|
|
-
|
|
|
-// 微页面相关响应式数据
|
|
|
-// 获取DIY上下文
|
|
|
-const selectedMicropage = ref<MicropageItem>();
|
|
|
-const micropageList = ref<any[]>([]);
|
|
|
-const micropageSearchKeyword = ref('');
|
|
|
-const isMicropageCategory = ref(false);
|
|
|
+const emit = defineEmits(['update:modelValue']);
|
|
|
|
|
|
-// 动态树数据
|
|
|
-const treeData = ref<any[]>([]);
|
|
|
-// 分类对应的链接数据
|
|
|
-const categoryLinksMap = ref<Map<string | number, LinkItem[]>>(new Map());
|
|
|
+// 打开对话框的方法,用于外部调用
|
|
|
+const open = () => {
|
|
|
+ showDialog.value = true;
|
|
|
+ // 如果数据还没加载完成,则重新加载
|
|
|
+ if (menuData.value.length === 0) {
|
|
|
+ loadCategoryData();
|
|
|
+ } else {
|
|
|
+ boxData.value = menuData.value[0].children[0].children;
|
|
|
+ }
|
|
|
+};
|
|
|
|
|
|
// 加载分类数据
|
|
|
const loadCategoryData = async () => {
|
|
|
try {
|
|
|
const res = await getCategoryTree();
|
|
|
- if (res.data) {
|
|
|
- // 只保留非顶级的分类
|
|
|
- const filteredItems = res.data.find((item) => item.id === 0).children || [];
|
|
|
- // 剩余的节点转换为树结构
|
|
|
- const convertToTreeFormat = (items: any[]) => {
|
|
|
- return items.map((item) => ({
|
|
|
- id: item.id,
|
|
|
- title: item.name,
|
|
|
- originalData: item,
|
|
|
- children: item.children ? convertToTreeFormat(item.children) : []
|
|
|
- }));
|
|
|
- };
|
|
|
- treeData.value = convertToTreeFormat(filteredItems);
|
|
|
- // 获取所有分类的 ID 列表
|
|
|
- const allCategoryIds = getAllCategoryIds(treeData.value);
|
|
|
-
|
|
|
- // 并行请求所有分类的链接数据
|
|
|
- const linkPromises = allCategoryIds.map((id) => loadLinksForCategory(id));
|
|
|
- const allLinks = await Promise.all(linkPromises);
|
|
|
-
|
|
|
- // 将结果合并到 categoryLinksMap
|
|
|
- allLinks.forEach((links, index) => {
|
|
|
- const categoryId = allCategoryIds[index];
|
|
|
- if (links && links.length > 0) {
|
|
|
- categoryLinksMap.value.set(categoryId, links);
|
|
|
- }
|
|
|
- });
|
|
|
+ if (res.data && res.data.length > 0) {
|
|
|
+ const firstLevelChildren = res.data[0].children;
|
|
|
+ menuData.value = firstLevelChildren;
|
|
|
+ await Promise.all(firstLevelChildren.map((item: any) => processNode(item)));
|
|
|
+ boxData.value = menuData.value[0].children[0].children;
|
|
|
return true;
|
|
|
}
|
|
|
return false;
|
|
|
@@ -313,911 +452,371 @@ const loadCategoryData = async () => {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-// 递归获取所有分类 ID
|
|
|
-const getAllCategoryIds = (nodes: any[]): number[] => {
|
|
|
- const ids: number[] = [];
|
|
|
- nodes.forEach((node) => {
|
|
|
- ids.push(node.id);
|
|
|
- if (node.children && node.children.length > 0) {
|
|
|
- ids.push(...getAllCategoryIds(node.children));
|
|
|
+const processNode = async (node: any) => {
|
|
|
+ if (node.children && node.children.length > 0 && node.type == 1) {
|
|
|
+ await Promise.all(node.children.map((child: any) => processNode(child)));
|
|
|
+ } else {
|
|
|
+ if ((!node.children || node.children.length === 0) && node.type == 1) {
|
|
|
+ try {
|
|
|
+ if (node.id) {
|
|
|
+ const res = await listPageLink({
|
|
|
+ cateId: node.id,
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 100,
|
|
|
+ createTime: undefined
|
|
|
+ });
|
|
|
+ node.children = res.rows;
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ node.children = [];
|
|
|
+ console.error(`Failed to load links for node ${node.name}:`, error);
|
|
|
+ }
|
|
|
}
|
|
|
- });
|
|
|
- return ids;
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
-// 加载指定分类的链接数据
|
|
|
-const loadLinksForCategory = async (categoryId: number): Promise<LinkItem[]> => {
|
|
|
- try {
|
|
|
- const res = await listPageLink({
|
|
|
- cateId: categoryId,
|
|
|
- pageNum: 1,
|
|
|
- pageSize: 100,
|
|
|
- createTime: undefined
|
|
|
- });
|
|
|
- if (res.rows) {
|
|
|
- return res.rows.map((item: any) => ({
|
|
|
- id: item.linkKey,
|
|
|
- name: item.name,
|
|
|
- url: item.url
|
|
|
- }));
|
|
|
+const onMenu = (res: any) => {
|
|
|
+ const list = res.split('-');
|
|
|
+ defaultActive.value = res;
|
|
|
+ if (res.startsWith('0')) {
|
|
|
+ boxData.value = menuData.value[list[0]].children[list[1]].children;
|
|
|
+ } else {
|
|
|
+ if (list.length == 2) {
|
|
|
+ const datas = menuData.value[list[0]].children[list[1]];
|
|
|
+ boxpageKey.value = datas.pageKey;
|
|
|
+ if (boxpageKey.value == 'goodsClassify') {
|
|
|
+ if (tableData1.value.length == 0) {
|
|
|
+ getTableData1();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (boxpageKey.value == 'goodsItem') {
|
|
|
+ handleQuery2();
|
|
|
+ }
|
|
|
+ if (boxpageKey.value == 'plan') {
|
|
|
+ handleQuery3();
|
|
|
+ }
|
|
|
+ if (boxpageKey.value == 'procure') {
|
|
|
+ handleQuery4();
|
|
|
+ }
|
|
|
+ if (boxpageKey.value == 'guide') {
|
|
|
+ handleQuery5();
|
|
|
+ }
|
|
|
+ if (boxpageKey.value == 'project') {
|
|
|
+ handleQuery6();
|
|
|
+ }
|
|
|
+ console.log(datas, 'datas');
|
|
|
+ } else {
|
|
|
+ if (menuData.value[list[0]].type == '4') {
|
|
|
+ boxpageKey.value = 'zdy';
|
|
|
+ }
|
|
|
}
|
|
|
- return [];
|
|
|
- } catch (error) {
|
|
|
- console.error(`获取分类 ${categoryId} 链接失败:`, error);
|
|
|
- return [];
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-// 默认树配置
|
|
|
-const defaultProps = {
|
|
|
- children: 'children',
|
|
|
- label: 'title'
|
|
|
+const getTableData1 = async () => {
|
|
|
+ loading1.value = true;
|
|
|
+ // 清空懒加载缓存
|
|
|
+ lazyTreeNodeMap.value.clear();
|
|
|
+ // 只加载顶级分类(parentId = 0)
|
|
|
+ const res = await listCategory({ parentId: 0 });
|
|
|
+ const data = (res as any).rows || res.data || [];
|
|
|
+ // 根据 hasChildren 字段标记是否有子节点
|
|
|
+ tableData1.value = data.map((item: CategoryVO) => ({
|
|
|
+ ...item,
|
|
|
+ hasChildren: item.hasChildren ?? item.classLevel < 3 // 如果后端没返回 hasChildren,根据 classLevel 判断
|
|
|
+ }));
|
|
|
+ loading1.value = false;
|
|
|
};
|
|
|
|
|
|
-// 当前显示的链接列表
|
|
|
-const currentLinks = computed(() => {
|
|
|
- if (!selectedCategory.value || !selectedCategory.value.id) {
|
|
|
- return [];
|
|
|
+/** 懒加载子节点 */
|
|
|
+const loadChildren = async (row: CategoryVO, treeNode: any, resolve: (data: CategoryVO[]) => void) => {
|
|
|
+ // 存储加载状态,便于刷新时重新加载
|
|
|
+ lazyTreeNodeMap.value.set(row.id, { tree: row, treeNode, resolve });
|
|
|
+ try {
|
|
|
+ const res = await listCategory({ parentId: row.id });
|
|
|
+ const data = (res as any).rows || res.data || [];
|
|
|
+ // 标记子节点是否还有子级
|
|
|
+ const children = data.map((item: CategoryVO) => ({
|
|
|
+ ...item,
|
|
|
+ hasChildren: item.hasChildren ?? item.classLevel < 3
|
|
|
+ }));
|
|
|
+ resolve(children);
|
|
|
+ } catch (error) {
|
|
|
+ resolve([]);
|
|
|
}
|
|
|
+};
|
|
|
|
|
|
- // 从缓存中获取链接数据
|
|
|
- return categoryLinksMap.value.get(selectedCategory.value.id) || [];
|
|
|
-});
|
|
|
-
|
|
|
-// 是否为自定义链接分类
|
|
|
-const isCustomLinkCategory = computed(() => {
|
|
|
- return selectedCategory.value?.originalData?.type === '4' || selectedCategory.value?.name === '自定义链接';
|
|
|
-});
|
|
|
-
|
|
|
-// 是否为商品分类
|
|
|
-const isProductCategoryComputed = computed(() => {
|
|
|
- return selectedCategory.value?.name === '商品' || selectedCategory.value?.title === '商品';
|
|
|
-});
|
|
|
-
|
|
|
-// 是否为文章分类
|
|
|
-const isArticleCategoryComputed = computed(() => {
|
|
|
- return selectedCategory.value?.name === '文章' || selectedCategory.value?.title === '文章';
|
|
|
-});
|
|
|
-
|
|
|
-// 是否为微页面分类
|
|
|
-const isMicropageCategoryComputed = computed(() => {
|
|
|
- return selectedCategory.value?.name === '微页面' || selectedCategory.value?.title === '微页面';
|
|
|
-});
|
|
|
-
|
|
|
-// 处理节点点击
|
|
|
-async function handleNodeClick(node: TreeNode) {
|
|
|
- const treeNode = node as any;
|
|
|
- if (treeNode.id) {
|
|
|
- selectedCategory.value = treeNode;
|
|
|
- selectedLink.value = undefined;
|
|
|
- selectedProduct.value = undefined;
|
|
|
- selectedArticle.value = undefined;
|
|
|
- selectedMicropage.value = undefined;
|
|
|
+// 处理 Checkbox 点击
|
|
|
+const handleCheckboxChange = (row: any) => {
|
|
|
+ if (tableId1.value === row.id) {
|
|
|
+ selectedRowObj.value = row;
|
|
|
+ } else {
|
|
|
+ selectedRowObj.value = null;
|
|
|
+ }
|
|
|
+};
|
|
|
|
|
|
- // 设置当前分类类型
|
|
|
- isProductCategory.value = isProductCategoryComputed.value;
|
|
|
- isArticleCategory.value = isArticleCategoryComputed.value;
|
|
|
- isMicropageCategory.value = isMicropageCategoryComputed.value;
|
|
|
+//商品查询
|
|
|
+const handleQuery2 = () => {
|
|
|
+ queryParams2.pageNum = 1;
|
|
|
+ getTableData2();
|
|
|
+};
|
|
|
|
|
|
- if (isProductCategory.value) {
|
|
|
- // 如果是商品分类,清空搜索关键词并加载商品列表
|
|
|
- productSearchKeyword.value = '';
|
|
|
- await loadProductList();
|
|
|
- emit('update:modelValue', '');
|
|
|
- } else if (isArticleCategory.value) {
|
|
|
- // 如果是文章分类,清空搜索关键词并加载文章列表
|
|
|
- articleSearchKeyword.value = '';
|
|
|
- await loadArticleList();
|
|
|
- emit('update:modelValue', '');
|
|
|
- } else if (isMicropageCategory.value) {
|
|
|
- // 如果是微页面分类,清空搜索关键词并加载微页面列表
|
|
|
- micropageSearchKeyword.value = '';
|
|
|
- await loadMicropageList();
|
|
|
- emit('update:modelValue', '');
|
|
|
- } else if (isCustomLinkCategory.value) {
|
|
|
- // 如果是自定义链接分类,清空选择
|
|
|
- customLinkPath.value = '';
|
|
|
- emit('update:modelValue', '');
|
|
|
- } else {
|
|
|
- // 获取当前分类的链接
|
|
|
- const links = currentLinks.value;
|
|
|
- if (links.length > 0) {
|
|
|
- // 自动选择第一个链接
|
|
|
- selectedLink.value = links[0];
|
|
|
- emit('update:modelValue', links[0].url);
|
|
|
- } else {
|
|
|
- emit('update:modelValue', '');
|
|
|
- }
|
|
|
- }
|
|
|
+/** 获取列表商品 */
|
|
|
+const getTableData2 = async () => {
|
|
|
+ loading2.value = true;
|
|
|
+ try {
|
|
|
+ const res = await listBase(queryParams2);
|
|
|
+ tableData2.value = res.rows || [];
|
|
|
+ total2.value = res.total || 0;
|
|
|
+ } finally {
|
|
|
+ loading2.value = false;
|
|
|
}
|
|
|
-}
|
|
|
+};
|
|
|
+
|
|
|
+//采购方案查询
|
|
|
+const handleQuery3 = () => {
|
|
|
+ queryParams3.pageNum = 1;
|
|
|
+ getTableData3();
|
|
|
+};
|
|
|
|
|
|
-// 加载商品列表
|
|
|
-async function loadProductList(keyword: string = '') {
|
|
|
+/** 获取列表采购方案 */
|
|
|
+const getTableData3 = async () => {
|
|
|
+ loading3.value = true;
|
|
|
try {
|
|
|
- // 这里模拟获取商品数据,实际项目中应该调用API
|
|
|
- const queryParams: any = {
|
|
|
- pageNum: 1,
|
|
|
- pageSize: 100,
|
|
|
- itemName: keyword
|
|
|
- };
|
|
|
- const res = await listBase(queryParams);
|
|
|
- if (res.rows) {
|
|
|
- productList.value = res.rows.map((item: any) => ({
|
|
|
- id: Number(item.id),
|
|
|
- name: item.itemName,
|
|
|
- image: item.productImage
|
|
|
- }));
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.error('加载商品列表失败:', error);
|
|
|
- ElMessage.error('加载商品列表失败');
|
|
|
- productList.value = [];
|
|
|
+ const res = await listProgram(queryParams3);
|
|
|
+ tableData3.value = res.rows || [];
|
|
|
+ total3.value = res.total || 0;
|
|
|
+ } finally {
|
|
|
+ loading3.value = false;
|
|
|
}
|
|
|
-}
|
|
|
-
|
|
|
-// 搜索商品
|
|
|
-async function handleProductSearch() {
|
|
|
- await loadProductList(productSearchKeyword.value);
|
|
|
-}
|
|
|
+};
|
|
|
|
|
|
-// 选择商品
|
|
|
-function handleProductSelect(product: ProductItem) {
|
|
|
- selectedProduct.value = product;
|
|
|
- // 构建商品详情链接:pages/goods/detail/detail?id=商品Id
|
|
|
- const productUrl = `/pages/goods/detail/detail?id=${product.id}`;
|
|
|
- emit('update:modelValue', productUrl);
|
|
|
-}
|
|
|
+//产品推荐查询
|
|
|
+const handleQuery4 = () => {
|
|
|
+ queryParams4.pageNum = 1;
|
|
|
+ getTableData4();
|
|
|
+};
|
|
|
|
|
|
-// 加载文章列表
|
|
|
-async function loadArticleList(keyword: string = '') {
|
|
|
+/** 获取列表产品推荐 */
|
|
|
+const getTableData4 = async () => {
|
|
|
+ loading4.value = true;
|
|
|
try {
|
|
|
- const queryParams = {
|
|
|
- pageNum: 1,
|
|
|
- pageSize: 100,
|
|
|
- caseTitle: keyword
|
|
|
- };
|
|
|
-
|
|
|
- const res = await listServiceCase(queryParams);
|
|
|
- if (res.data) {
|
|
|
- articleList.value = res.data.map((item: any) => ({
|
|
|
- id: item.id,
|
|
|
- title: item.caseTitle
|
|
|
- }));
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.error('加载文章列表失败:', error);
|
|
|
- ElMessage.error('加载文章列表失败');
|
|
|
- articleList.value = [];
|
|
|
+ const res = await programList(queryParams4);
|
|
|
+ tableData4.value = res.rows || [];
|
|
|
+ total4.value = res.total || 0;
|
|
|
+ } finally {
|
|
|
+ loading4.value = false;
|
|
|
}
|
|
|
-}
|
|
|
-
|
|
|
-// 搜索文章
|
|
|
-async function handleArticleSearch() {
|
|
|
- await loadArticleList(articleSearchKeyword.value);
|
|
|
-}
|
|
|
+};
|
|
|
|
|
|
-// 选择文章
|
|
|
-function handleArticleSelect(article: ArticleItem) {
|
|
|
- selectedArticle.value = article;
|
|
|
- // 构建文章详情链接:pages/article/detail/detail?id=文章Id
|
|
|
- const articleUrl = `/pages/article/detail/detail?id=${article.id}`;
|
|
|
- emit('update:modelValue', articleUrl);
|
|
|
-}
|
|
|
+//采购指南查询
|
|
|
+const handleQuery5 = () => {
|
|
|
+ queryParams5.pageNum = 1;
|
|
|
+ getTableData5();
|
|
|
+};
|
|
|
|
|
|
-// 加载微页面列表
|
|
|
-async function loadMicropageList(keyword: string = '') {
|
|
|
+/** 获取列表采购指南 */
|
|
|
+const getTableData5 = async () => {
|
|
|
+ loading5.value = true;
|
|
|
try {
|
|
|
- // 这里模拟获取微页面数据,实际项目中应该调用API
|
|
|
- // 假设的查询参数结构
|
|
|
- const queryParams = {
|
|
|
- pageNum: 1,
|
|
|
- pageSize: 100,
|
|
|
- title: keyword
|
|
|
- };
|
|
|
- let res = undefined;
|
|
|
- res = await pcDiyList(queryParams);
|
|
|
- if (res.rows) {
|
|
|
- micropageList.value = res.list.map((item: any) => ({
|
|
|
- id: item.id,
|
|
|
- name: item.name
|
|
|
- }));
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.error('加载微页面列表失败:', error);
|
|
|
- ElMessage.error('加载微页面列表失败');
|
|
|
- micropageList.value = [];
|
|
|
+ const res = await listTopics(queryParams5);
|
|
|
+ tableData5.value = res.rows || [];
|
|
|
+ total5.value = res.total || 0;
|
|
|
+ } finally {
|
|
|
+ loading5.value = false;
|
|
|
}
|
|
|
-}
|
|
|
+};
|
|
|
|
|
|
-// 搜索微页面
|
|
|
-async function handleMicropageSearch() {
|
|
|
- await loadMicropageList(micropageSearchKeyword.value);
|
|
|
-}
|
|
|
+//项目案例查询
|
|
|
+const handleQuery6 = () => {
|
|
|
+ queryParams6.pageNum = 1;
|
|
|
+ getTableData6();
|
|
|
+};
|
|
|
|
|
|
-// 选择微页面
|
|
|
-function handleMicropageSelect(micropage: MicropageItem) {
|
|
|
- selectedMicropage.value = micropage;
|
|
|
- // 构建微页面链接:pages/micropage/detail/detail?id=微页面Id
|
|
|
- const micropageUrl = `/pages/diy/index?id=${micropage.id}`;
|
|
|
- emit('update:modelValue', micropageUrl);
|
|
|
-}
|
|
|
+/** 获取列表项目案例 */
|
|
|
+const getTableData6 = async () => {
|
|
|
+ loading6.value = true;
|
|
|
+ try {
|
|
|
+ const res = await listServiceCase(queryParams5);
|
|
|
+ tableData6.value = res.rows || [];
|
|
|
+ total6.value = res.total || 0;
|
|
|
+ } finally {
|
|
|
+ loading6.value = false;
|
|
|
+ }
|
|
|
+};
|
|
|
|
|
|
-// 处理链接点击
|
|
|
-function handleLinkClick(link: LinkItem) {
|
|
|
- selectedLink.value = link;
|
|
|
- // 触发临时选择事件,让父组件可以实时获取选择的链接
|
|
|
- emit('update:modelValue', link.url);
|
|
|
-}
|
|
|
+const onSelected = (item: any) => {
|
|
|
+ selected.value = item.url;
|
|
|
+};
|
|
|
|
|
|
-// 处理确定
|
|
|
-function handleConfirm() {
|
|
|
- if (isProductCategory.value) {
|
|
|
- if (!selectedProduct.value) {
|
|
|
+const onConfirm = () => {
|
|
|
+ if (boxShow1.value) {
|
|
|
+ if (selected.value) {
|
|
|
+ emit('update:modelValue', `${selected.value}?openType=${switchVal.value ? 1 : 0}`);
|
|
|
+ showDialog.value = false;
|
|
|
+ } else {
|
|
|
ElMessage({
|
|
|
- message: '请选择商品',
|
|
|
+ message: '请选择一个链接',
|
|
|
type: 'warning',
|
|
|
duration: 2000
|
|
|
});
|
|
|
- return;
|
|
|
}
|
|
|
- dialogVisible.value = false;
|
|
|
- ElMessage({
|
|
|
- message: '商品设置成功',
|
|
|
- type: 'success',
|
|
|
- duration: 2000
|
|
|
- });
|
|
|
- } else if (isArticleCategory.value) {
|
|
|
- if (!selectedArticle.value) {
|
|
|
- ElMessage({
|
|
|
- message: '请选择文章',
|
|
|
- type: 'warning',
|
|
|
- duration: 2000
|
|
|
- });
|
|
|
- return;
|
|
|
+ } else {
|
|
|
+ if (boxpageKey.value == 'goodsClassify') {
|
|
|
+ if (tableId1.value) {
|
|
|
+ let url1 = '/search?type=' + selectedRowObj.value.classLevel;
|
|
|
+ if (selectedRowObj.value.classLevel == 1) {
|
|
|
+ url1 = url1 + '&topCategoryId=' + tableId1.value;
|
|
|
+ } else if (selectedRowObj.value.classLevel == 2) {
|
|
|
+ url1 = url1 + '&middleCategoryId=' + tableId1.value;
|
|
|
+ } else if (selectedRowObj.value.classLevel == 3) {
|
|
|
+ url1 = url1 + '&bottomCategoryId=' + tableId1.value;
|
|
|
+ }
|
|
|
+ url1 = url1 + '&openType=' + (switchVal.value ? 1 : 0);
|
|
|
+ emit('update:modelValue', url1);
|
|
|
+ showDialog.value = false;
|
|
|
+ } else {
|
|
|
+ ElMessage({
|
|
|
+ message: '请选择一个分类',
|
|
|
+ type: 'warning',
|
|
|
+ duration: 2000
|
|
|
+ });
|
|
|
+ }
|
|
|
}
|
|
|
- dialogVisible.value = false;
|
|
|
- ElMessage({
|
|
|
- message: '文章设置成功',
|
|
|
- type: 'success',
|
|
|
- duration: 2000
|
|
|
- });
|
|
|
- } else if (isMicropageCategory.value) {
|
|
|
- if (!selectedMicropage.value) {
|
|
|
- ElMessage({
|
|
|
- message: '请选择微页面',
|
|
|
- type: 'warning',
|
|
|
- duration: 2000
|
|
|
- });
|
|
|
- return;
|
|
|
+ if (boxpageKey.value == 'goodsItem') {
|
|
|
+ if (tableId2.value) {
|
|
|
+ let url2 = '/item?productNo=' + tableId2.value;
|
|
|
+ url2 = url2 + '&openType=' + (switchVal.value ? 1 : 0);
|
|
|
+ emit('update:modelValue', url2);
|
|
|
+ showDialog.value = false;
|
|
|
+ } else {
|
|
|
+ ElMessage({
|
|
|
+ message: '请选择一个商品',
|
|
|
+ type: 'warning',
|
|
|
+ duration: 2000
|
|
|
+ });
|
|
|
+ }
|
|
|
}
|
|
|
- dialogVisible.value = false;
|
|
|
- ElMessage({
|
|
|
- message: '微页面设置成功',
|
|
|
- type: 'success',
|
|
|
- duration: 2000
|
|
|
- });
|
|
|
- } else if (isCustomLinkCategory.value) {
|
|
|
- // 自定义链接处理
|
|
|
- if (!customLinkPath.value.trim()) {
|
|
|
- ElMessage({
|
|
|
- message: '请输入自定义链接地址',
|
|
|
- type: 'warning',
|
|
|
- duration: 2000
|
|
|
- });
|
|
|
- return;
|
|
|
+ if (boxpageKey.value == 'plan') {
|
|
|
+ if (tableId3.value) {
|
|
|
+ let url3 = '/plan_info?id=' + tableId3.value;
|
|
|
+ url3 = url3 + '&openType=' + (switchVal.value ? 1 : 0);
|
|
|
+ emit('update:modelValue', url3);
|
|
|
+ showDialog.value = false;
|
|
|
+ } else {
|
|
|
+ ElMessage({
|
|
|
+ message: '请选择一个采购方案',
|
|
|
+ type: 'warning',
|
|
|
+ duration: 2000
|
|
|
+ });
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- // 验证链接格式
|
|
|
- const path = customLinkPath.value.trim();
|
|
|
- // 创建临时的自定义链接项
|
|
|
- const customLink: LinkItem = {
|
|
|
- id: `custom-${Date.now()}`,
|
|
|
- name: '自定义链接',
|
|
|
- url: path
|
|
|
- };
|
|
|
-
|
|
|
- emit('update:modelValue', path);
|
|
|
- emit('confirm', path, customLink);
|
|
|
- dialogVisible.value = false;
|
|
|
- ElMessage({
|
|
|
- message: '自定义链接设置成功',
|
|
|
- type: 'success',
|
|
|
- duration: 2000
|
|
|
- });
|
|
|
- } else if (selectedLink.value) {
|
|
|
- // 普通链接处理
|
|
|
- emit('update:modelValue', selectedLink.value.url);
|
|
|
- emit('confirm', selectedLink.value.url, selectedLink.value);
|
|
|
- dialogVisible.value = false;
|
|
|
- // 确认选择后,显示成功提示
|
|
|
- ElMessage({
|
|
|
- message: '链接选择成功',
|
|
|
- type: 'success',
|
|
|
- duration: 2000
|
|
|
- });
|
|
|
- } else {
|
|
|
- // 如果没有选择链接,提示用户
|
|
|
- ElMessage({
|
|
|
- message: '请选择一个链接',
|
|
|
- type: 'warning',
|
|
|
- duration: 2000
|
|
|
- });
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 处理取消
|
|
|
-function handleCancel() {
|
|
|
- emit('cancel');
|
|
|
- dialogVisible.value = false;
|
|
|
-}
|
|
|
-
|
|
|
-// 打开对话框的方法,用于外部调用
|
|
|
-const open = () => {
|
|
|
- dialogVisible.value = true;
|
|
|
- // 如果数据还没加载完成,则重新加载
|
|
|
- if (treeData.value.length === 0) {
|
|
|
- loadCategoryData();
|
|
|
- }
|
|
|
-};
|
|
|
-
|
|
|
-// 处理关闭
|
|
|
-function handleClose() {
|
|
|
- emit('close');
|
|
|
- // 对话框关闭时重置所有状态,不更新modelValue
|
|
|
- selectedCategory.value = undefined;
|
|
|
- selectedLink.value = undefined;
|
|
|
- selectedProduct.value = undefined;
|
|
|
- selectedArticle.value = undefined;
|
|
|
- selectedMicropage.value = undefined;
|
|
|
- if (treeRef.value) {
|
|
|
- treeRef.value.setCurrentKey(null);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 重置状态
|
|
|
-function resetState() {
|
|
|
- selectedCategory.value = undefined;
|
|
|
- selectedLink.value = undefined;
|
|
|
- customLinkPath.value = '';
|
|
|
- selectedProduct.value = undefined;
|
|
|
- selectedArticle.value = undefined;
|
|
|
- selectedMicropage.value = undefined;
|
|
|
- productSearchKeyword.value = '';
|
|
|
- articleSearchKeyword.value = '';
|
|
|
- micropageSearchKeyword.value = '';
|
|
|
-
|
|
|
- // 重置树的当前节点
|
|
|
- if (treeRef.value) {
|
|
|
- treeRef.value.setCurrentKey(null);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 监听dialogVisible变化,当对话框打开时初始化状态
|
|
|
-watch(
|
|
|
- () => dialogVisible.value,
|
|
|
- async (newValue) => {
|
|
|
- if (newValue) {
|
|
|
- nextTick(async () => {
|
|
|
- // 重置自定义链接输入
|
|
|
- customLinkPath.value = '';
|
|
|
- // 清空缓存
|
|
|
- categoryLinksMap.value.clear();
|
|
|
-
|
|
|
- // 加载分类数据
|
|
|
- await loadCategoryData();
|
|
|
-
|
|
|
- if (props.modelValue) {
|
|
|
- // 如果有传入的modelValue,则尝试匹配
|
|
|
- }
|
|
|
-
|
|
|
- // 如果没有匹配的链接或没有传入modelValue,则设置默认选中
|
|
|
- if (!selectedCategory.value && treeData.value.length > 0) {
|
|
|
- // 找到第一个有子分类的节点
|
|
|
- const findFirstNodeWithLinks = (nodes: any[]) => {
|
|
|
- for (const node of nodes) {
|
|
|
- if (node.children && node.children.length > 0) {
|
|
|
- return node.children[0];
|
|
|
- }
|
|
|
- }
|
|
|
- return null;
|
|
|
- };
|
|
|
-
|
|
|
- const firstNode = findFirstNodeWithLinks(treeData.value);
|
|
|
- if (firstNode) {
|
|
|
- selectedCategory.value = firstNode;
|
|
|
- if (treeRef.value && firstNode.id) {
|
|
|
- treeRef.value.setCurrentKey(firstNode.id);
|
|
|
- // 触发节点点击,加载链接数据
|
|
|
- await handleNodeClick(firstNode);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
+ if (boxpageKey.value == 'procure') {
|
|
|
+ if (tableId4.value) {
|
|
|
+ let url4 = '/plan_info/procure?id=' + tableId4.value;
|
|
|
+ url4 = url4 + '&openType=' + (switchVal.value ? 1 : 0);
|
|
|
+ emit('update:modelValue', url4);
|
|
|
+ showDialog.value = false;
|
|
|
+ } else {
|
|
|
+ ElMessage({
|
|
|
+ message: '请选择一个产品推荐',
|
|
|
+ type: 'warning',
|
|
|
+ duration: 2000
|
|
|
+ });
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
-);
|
|
|
-
|
|
|
-// 键盘导航处理
|
|
|
-function handleKeyDown(event: KeyboardEvent) {
|
|
|
- // 只有当对话框可见时才处理键盘事件
|
|
|
- if (!dialogVisible.value || !selectedLink.value) return;
|
|
|
-
|
|
|
- const links = currentLinks.value;
|
|
|
- if (links.length === 0) return;
|
|
|
-
|
|
|
- const currentIndex = links.findIndex((link) => link.id === selectedLink.value?.id);
|
|
|
-
|
|
|
- switch (event.key) {
|
|
|
- case 'ArrowRight':
|
|
|
- // 向右箭头:选择下一个链接
|
|
|
- event.preventDefault();
|
|
|
- if (currentIndex < links.length - 1) {
|
|
|
- handleLinkClick(links[currentIndex + 1]);
|
|
|
- } else if (links.length > 0) {
|
|
|
- handleLinkClick(links[0]);
|
|
|
+ if (boxpageKey.value == 'guide') {
|
|
|
+ if (tableId5.value) {
|
|
|
+ let url5 = '/plan_info/guide?id=' + tableId5.value;
|
|
|
+ url5 = url5 + '&openType=' + (switchVal.value ? 1 : 0);
|
|
|
+ emit('update:modelValue', url5);
|
|
|
+ showDialog.value = false;
|
|
|
+ } else {
|
|
|
+ ElMessage({
|
|
|
+ message: '请选择一个采购指南',
|
|
|
+ type: 'warning',
|
|
|
+ duration: 2000
|
|
|
+ });
|
|
|
}
|
|
|
- break;
|
|
|
- case 'ArrowLeft':
|
|
|
- // 向左箭头:选择上一个链接
|
|
|
- event.preventDefault();
|
|
|
- if (currentIndex > 0) {
|
|
|
- handleLinkClick(links[currentIndex - 1]);
|
|
|
- } else if (links.length > 0) {
|
|
|
- handleLinkClick(links[links.length - 1]);
|
|
|
+ }
|
|
|
+ if (boxpageKey.value == 'project') {
|
|
|
+ if (tableId6.value) {
|
|
|
+ let url6 = '/plan_info/project?id=' + tableId6.value;
|
|
|
+ url6 = url6 + '&openType=' + (switchVal.value ? 1 : 0);
|
|
|
+ emit('update:modelValue', url6);
|
|
|
+ showDialog.value = false;
|
|
|
+ } else {
|
|
|
+ ElMessage({
|
|
|
+ message: '请选择一个项目案例',
|
|
|
+ type: 'warning',
|
|
|
+ duration: 2000
|
|
|
+ });
|
|
|
}
|
|
|
- break;
|
|
|
- case 'Enter':
|
|
|
- // 回车键:确认选择
|
|
|
- event.preventDefault();
|
|
|
- handleConfirm();
|
|
|
- break;
|
|
|
- case 'Escape':
|
|
|
- // ESC键:取消
|
|
|
- event.preventDefault();
|
|
|
- handleCancel();
|
|
|
- break;
|
|
|
+ }
|
|
|
+ if (boxpageKey.value == 'zdy') {
|
|
|
+ if (input.value) {
|
|
|
+ emit('update:modelValue', `${input.value}?openType=${switchVal.value ? 1 : 0}`);
|
|
|
+ showDialog.value = false;
|
|
|
+ } else {
|
|
|
+ ElMessage({
|
|
|
+ message: '请输入自定义链接',
|
|
|
+ type: 'warning',
|
|
|
+ duration: 2000
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
-}
|
|
|
-
|
|
|
-// 重置方法
|
|
|
-defineExpose({
|
|
|
- reset: () => {
|
|
|
- resetState();
|
|
|
- emit('reset');
|
|
|
- emit('update:modelValue', '');
|
|
|
- },
|
|
|
- open,
|
|
|
- resetState
|
|
|
-});
|
|
|
+};
|
|
|
|
|
|
-// 组件挂载时添加键盘事件监听
|
|
|
-onMounted(() => {
|
|
|
- document.addEventListener('keydown', handleKeyDown);
|
|
|
+const boxShow1 = computed(() => {
|
|
|
+ return defaultActive.value.startsWith('0');
|
|
|
});
|
|
|
|
|
|
-// 组件卸载时移除键盘事件监听
|
|
|
-onUnmounted(() => {
|
|
|
- document.removeEventListener('keydown', handleKeyDown);
|
|
|
+defineExpose({
|
|
|
+ open
|
|
|
});
|
|
|
</script>
|
|
|
|
|
|
-<style scoped>
|
|
|
-/* 主容器样式 */
|
|
|
-.link-selector-container {
|
|
|
- display: flex;
|
|
|
- height: 800px;
|
|
|
- gap: 20px;
|
|
|
- animation: fadeIn 0.3s ease-in-out;
|
|
|
-}
|
|
|
-
|
|
|
-/* 商品链接选择区域样式 */
|
|
|
-.product-selection-container {
|
|
|
- height: 100%;
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
-}
|
|
|
-
|
|
|
-.product-search {
|
|
|
- margin-bottom: 16px;
|
|
|
-}
|
|
|
-
|
|
|
-.product-search .el-input {
|
|
|
- width: 30%;
|
|
|
- margin-right: 8px;
|
|
|
-}
|
|
|
-
|
|
|
-.product-list {
|
|
|
- flex: 1;
|
|
|
- overflow-y: auto;
|
|
|
-}
|
|
|
-
|
|
|
-/* Element UI表格样式调整 */
|
|
|
-.product-list .el-table {
|
|
|
- --el-table-header-bg-color: #1890ff;
|
|
|
- --el-table-header-text-color: #ffffff;
|
|
|
- --el-table-border-color: #e4e7ed;
|
|
|
-}
|
|
|
-
|
|
|
-.product-list .el-table :deep(.el-table__header th) {
|
|
|
- font-weight: 500;
|
|
|
- text-align: left;
|
|
|
- padding: 12px;
|
|
|
-}
|
|
|
-
|
|
|
-.product-list .el-table :deep(.el-table__body td) {
|
|
|
- padding: 12px;
|
|
|
-}
|
|
|
-
|
|
|
-.product-list .el-table :deep(.el-table__row:hover) {
|
|
|
- background-color: #f5f7fa;
|
|
|
-}
|
|
|
-
|
|
|
-/* 选中行样式 */
|
|
|
-.product-row-active {
|
|
|
- background-color: #ecf5ff !important;
|
|
|
-}
|
|
|
-
|
|
|
-/* 商品名称样式 */
|
|
|
-.product-name {
|
|
|
- font-size: 14px;
|
|
|
- line-height: 20px;
|
|
|
- word-break: break-word;
|
|
|
- max-width: 300px;
|
|
|
-}
|
|
|
-
|
|
|
-/* 左侧树容器 */
|
|
|
-.tree-container {
|
|
|
- width: 200px;
|
|
|
- border-right: 1px solid #e4e7ed;
|
|
|
- overflow-y: auto;
|
|
|
- background-color: #fafafa;
|
|
|
- transition: all 0.3s ease;
|
|
|
-}
|
|
|
-
|
|
|
-/* 右侧链接容器 */
|
|
|
-.links-container {
|
|
|
- flex: 1;
|
|
|
- overflow-y: auto;
|
|
|
- padding: 15px;
|
|
|
- background-color: #ffffff;
|
|
|
- border-radius: 4px;
|
|
|
+<style scoped lang="scss">
|
|
|
+.dialog-bos {
|
|
|
+ height: 580px;
|
|
|
display: flex;
|
|
|
- flex-direction: column;
|
|
|
- transition: all 0.3s ease;
|
|
|
-}
|
|
|
|
|
|
-/* 分类标题 */
|
|
|
-.category-title {
|
|
|
- font-size: 16px;
|
|
|
- font-weight: bold;
|
|
|
- margin-bottom: 20px;
|
|
|
- color: #303133;
|
|
|
- padding-bottom: 8px;
|
|
|
- border-bottom: 2px solid #409eff;
|
|
|
- animation: slideInLeft 0.3s ease-out;
|
|
|
-}
|
|
|
-
|
|
|
-/* 链接网格 */
|
|
|
-.links-grid {
|
|
|
- display: flex;
|
|
|
- flex-wrap: wrap;
|
|
|
- gap: 12px;
|
|
|
- margin-bottom: 20px;
|
|
|
-}
|
|
|
-
|
|
|
-/* 自定义链接容器 */
|
|
|
-.custom-link-container {
|
|
|
- animation: fadeInUp 0.3s ease-out;
|
|
|
-}
|
|
|
-
|
|
|
-/* 自定义链接提示 */
|
|
|
-.custom-link-tips {
|
|
|
- margin-top: 8px;
|
|
|
- font-size: 12px;
|
|
|
- color: #909399;
|
|
|
- display: flex;
|
|
|
- align-items: flex-start;
|
|
|
- gap: 4px;
|
|
|
- word-break: break-all;
|
|
|
- flex-wrap: wrap;
|
|
|
- width: 100%;
|
|
|
-}
|
|
|
-
|
|
|
-.custom-link-tips .el-icon {
|
|
|
- color: #e6a23c;
|
|
|
-}
|
|
|
-
|
|
|
-/* 链接按钮 */
|
|
|
-.link-button {
|
|
|
- margin-bottom: 8px;
|
|
|
- transition: all 0.3s ease;
|
|
|
- min-width: 120px;
|
|
|
- animation: fadeInUp 0.3s ease-out;
|
|
|
-}
|
|
|
-
|
|
|
-.link-button:hover {
|
|
|
- transform: translateY(-1px);
|
|
|
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
|
-}
|
|
|
-
|
|
|
-.link-button.active {
|
|
|
- background-color: #409eff;
|
|
|
- color: white;
|
|
|
- animation: pulse 0.5s ease-in-out;
|
|
|
-}
|
|
|
-
|
|
|
-/* 链接预览区域 */
|
|
|
-.link-preview {
|
|
|
- margin-top: auto;
|
|
|
- padding: 12px;
|
|
|
- background-color: #f5f7fa;
|
|
|
- border-radius: 4px;
|
|
|
- border-left: 4px solid #409eff;
|
|
|
- font-size: 14px;
|
|
|
- animation: slideInUp 0.4s ease-out;
|
|
|
- transition: all 0.3s ease;
|
|
|
-}
|
|
|
-
|
|
|
-.link-preview:hover {
|
|
|
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
|
-}
|
|
|
-
|
|
|
-.preview-label {
|
|
|
- color: #606266;
|
|
|
- font-weight: 500;
|
|
|
-}
|
|
|
-
|
|
|
-.preview-name {
|
|
|
- color: #409eff;
|
|
|
- font-weight: bold;
|
|
|
- margin: 0 8px;
|
|
|
-}
|
|
|
-
|
|
|
-.preview-path {
|
|
|
- color: #909399;
|
|
|
- font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
|
|
- word-break: break-all;
|
|
|
-}
|
|
|
-
|
|
|
-/* 滚动条样式 */
|
|
|
-.tree-container::-webkit-scrollbar,
|
|
|
-.links-container::-webkit-scrollbar {
|
|
|
- width: 6px;
|
|
|
- height: 6px;
|
|
|
-}
|
|
|
-
|
|
|
-.tree-container::-webkit-scrollbar-thumb,
|
|
|
-.links-container::-webkit-scrollbar-thumb {
|
|
|
- background-color: #dcdfe6;
|
|
|
- border-radius: 3px;
|
|
|
- transition: background-color 0.3s;
|
|
|
-}
|
|
|
-
|
|
|
-.tree-container::-webkit-scrollbar-thumb:hover,
|
|
|
-.links-container::-webkit-scrollbar-thumb:hover {
|
|
|
- background-color: #c0c4cc;
|
|
|
-}
|
|
|
-
|
|
|
-.tree-container::-webkit-scrollbar-track,
|
|
|
-.links-container::-webkit-scrollbar-track {
|
|
|
- background-color: #f5f7fa;
|
|
|
-}
|
|
|
-
|
|
|
-/* Element Plus 树样式覆盖 */
|
|
|
-:deep(.el-tree-node) {
|
|
|
- padding: 2px 0;
|
|
|
- transition: all 0.2s ease;
|
|
|
-}
|
|
|
-
|
|
|
-:deep(.el-tree-node__content) {
|
|
|
- transition: all 0.3s ease;
|
|
|
- padding: 8px 12px;
|
|
|
- margin: 0;
|
|
|
-}
|
|
|
-
|
|
|
-:deep(.el-tree-node__content:hover) {
|
|
|
- background-color: #ecf5ff;
|
|
|
- transform: translateX(2px);
|
|
|
-}
|
|
|
-
|
|
|
-:deep(.el-tree-node.is-current > .el-tree-node__content) {
|
|
|
- background-color: #ecf5ff;
|
|
|
- color: #409eff;
|
|
|
- font-weight: 500;
|
|
|
- border-right: 3px solid #409eff;
|
|
|
-}
|
|
|
-
|
|
|
-:deep(.el-tree-node.is-current > .el-tree-node__content .el-tree-node__label) {
|
|
|
- color: #409eff;
|
|
|
-}
|
|
|
-
|
|
|
-/* 自定义表格样式 */
|
|
|
-:deep(.custom-product-table .el-table__header th) {
|
|
|
- background-color: #188fff54 !important;
|
|
|
-}
|
|
|
-
|
|
|
-/* 移除单选框后面的点 */
|
|
|
-:deep(.el-radio__label) {
|
|
|
- display: none;
|
|
|
-}
|
|
|
-
|
|
|
-/* 确保单选框样式正确 */
|
|
|
-:deep(.el-radio) {
|
|
|
- margin-right: 0;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
-}
|
|
|
-
|
|
|
-/* 图片加载失败时的样式 */
|
|
|
-:deep(.image-slot) {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- width: 80px;
|
|
|
- height: 60px;
|
|
|
- background-color: #f5f7fa;
|
|
|
- color: #909399;
|
|
|
-}
|
|
|
-
|
|
|
-/* 动画定义 */
|
|
|
-@keyframes fadeIn {
|
|
|
- from {
|
|
|
- opacity: 0;
|
|
|
- }
|
|
|
- to {
|
|
|
- opacity: 1;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-@keyframes slideInLeft {
|
|
|
- from {
|
|
|
- opacity: 0;
|
|
|
- transform: translateX(-20px);
|
|
|
- }
|
|
|
- to {
|
|
|
- opacity: 1;
|
|
|
- transform: translateX(0);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-@keyframes slideInUp {
|
|
|
- from {
|
|
|
- opacity: 0;
|
|
|
- transform: translateY(20px);
|
|
|
- }
|
|
|
- to {
|
|
|
- opacity: 1;
|
|
|
- transform: translateY(0);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-@keyframes fadeInUp {
|
|
|
- from {
|
|
|
- opacity: 0;
|
|
|
- transform: translateY(10px);
|
|
|
- }
|
|
|
- to {
|
|
|
- opacity: 1;
|
|
|
- transform: translateY(0);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-@keyframes pulse {
|
|
|
- 0% {
|
|
|
- transform: scale(1);
|
|
|
- }
|
|
|
- 50% {
|
|
|
- transform: scale(1.05);
|
|
|
- }
|
|
|
- 100% {
|
|
|
- transform: scale(1);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/* 响应式设计 */
|
|
|
-@media (max-width: 1200px) {
|
|
|
- .link-selector-container {
|
|
|
- height: 350px;
|
|
|
- }
|
|
|
-
|
|
|
- .tree-container {
|
|
|
- width: 180px;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-@media (max-width: 768px) {
|
|
|
- .link-selector-container {
|
|
|
- height: 300px;
|
|
|
- gap: 10px;
|
|
|
- }
|
|
|
-
|
|
|
- .tree-container {
|
|
|
- width: 160px;
|
|
|
- }
|
|
|
-
|
|
|
- .links-container {
|
|
|
- padding: 10px;
|
|
|
- }
|
|
|
-
|
|
|
- .link-button {
|
|
|
- min-width: 100px;
|
|
|
- padding: 8px 12px;
|
|
|
- font-size: 13px;
|
|
|
- }
|
|
|
-
|
|
|
- .category-title {
|
|
|
- font-size: 14px;
|
|
|
- margin-bottom: 15px;
|
|
|
+ .menu-container {
|
|
|
+ height: 100%;
|
|
|
+ width: 140px;
|
|
|
+ overflow: auto;
|
|
|
}
|
|
|
|
|
|
- .link-preview {
|
|
|
- font-size: 12px;
|
|
|
- padding: 8px;
|
|
|
- }
|
|
|
-}
|
|
|
+ .dialog-box {
|
|
|
+ flex: 1;
|
|
|
+ padding: 0 20px 20px 20px;
|
|
|
|
|
|
-@media (max-width: 480px) {
|
|
|
- .link-selector-container {
|
|
|
- flex-direction: column;
|
|
|
- height: 450px;
|
|
|
- }
|
|
|
+ .button-title {
|
|
|
+ margin: 15px 0;
|
|
|
|
|
|
- .tree-container {
|
|
|
- width: 100%;
|
|
|
- height: 120px;
|
|
|
- border-right: none;
|
|
|
- border-bottom: 1px solid #e4e7ed;
|
|
|
- }
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ .title {
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 600;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- .links-container {
|
|
|
- flex: 1;
|
|
|
- }
|
|
|
+ .button-container {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 10px;
|
|
|
|
|
|
- .links-grid {
|
|
|
- gap: 8px;
|
|
|
+ :deep(.el-button + .el-button) {
|
|
|
+ margin-left: 0px;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- .link-button {
|
|
|
- min-width: calc(50% - 4px);
|
|
|
- margin-bottom: 0;
|
|
|
+ :deep(.pagination-container) {
|
|
|
+ margin-top: 0px;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-/* 加载动画 */
|
|
|
-:deep(.el-loading-spinner) {
|
|
|
- margin-top: -20px;
|
|
|
-}
|
|
|
-
|
|
|
-/* 确保对话框在小屏幕上也能良好显示 */
|
|
|
-:deep(.el-dialog__wrapper) {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
-}
|
|
|
-
|
|
|
-:deep(.el-dialog) {
|
|
|
- margin: 0 !important;
|
|
|
- max-height: 90vh;
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
-}
|
|
|
-
|
|
|
-:deep(.el-dialog__body) {
|
|
|
- flex: 1;
|
|
|
- overflow-y: auto;
|
|
|
- padding: 20px;
|
|
|
-}
|
|
|
-
|
|
|
-/* 当选择链接时的反馈 */
|
|
|
-:deep(.el-button--primary.is-active) {
|
|
|
- background-color: #337ecc;
|
|
|
- border-color: #337ecc;
|
|
|
-}
|
|
|
-
|
|
|
-/* 确保选中行样式正确 */
|
|
|
-.product-row-active {
|
|
|
- background-color: #e6f7ff !important;
|
|
|
-}
|
|
|
</style>
|