daoyou_manage_web/src/views/manage/scenic/index.vue
2024-12-27 11:39:34 +08:00

1060 lines
43 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- 景点列表 -->
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter"
:leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]" id="search_div">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="70px">
<el-form-item :label="`${queryParams.type == '0' ? '景点' : '商家'}名称`" prop="name">
<el-input class="inputWidth" v-model="queryParams.name" placeholder="请输入景点名称" clearable
@keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="推荐语" prop="recommend">
<el-input class="inputWidth" v-model="queryParams.recommend" placeholder="请输入推荐语" clearable
@keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="发布状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择发布状态" clearable class="inputWidth">
<el-option label="未发布" value="0"></el-option>
<el-option label="审核中" value="1"></el-option>
<el-option label="已发布" value="2"></el-option>
<el-option label="草稿" value="3"></el-option>
</el-select>
</el-form-item>
<el-form-item label="景点等级" prop="level" v-if="queryParams.type == '0'">
<el-select v-model="queryParams.level" placeholder="请选择等级" clearable class="inputWidth">
<el-option v-for="item in levelList" :key="item.value" :label="item.label"
:value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="是否开放" prop="isOpen">
<el-select v-model="queryParams.isOpen" placeholder="请选择开放状态" clearable class="inputWidth">
<el-option label="已开放" value="1"></el-option>
<el-option label="未开放" value="0"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="`${queryParams.type == '0' ? '景点' : '商家'}属性`" prop="attribute">
<el-select v-model="queryParams.attribute" placeholder="请选择属性" clearable class="inputWidth">
<el-option :label="queryParams.type == '0' ? '标志性景点' : '标志性商家'" value="1"></el-option>
<el-option :label="queryParams.type == '0' ? '非标志性景点' : '非标志性商家'" value="0"></el-option>
</el-select>
</el-form-item>
<!-- <el-form-item label="标签" prop="tagId">
<el-select class="inputWidth" filterable v-model="queryParams.tagId" placeholder="请选择标签" clearable>
<el-option v-for="dict in sys_user_tagOptions" :key="dict.id" :label="dict.title" :value="dict.id" />
</el-select>
</el-form-item> -->
<el-form-item>
<el-button type="primary" icon="Search" v-hasPermi="['manage:content:query']"
@click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
<el-button type="primary" plain icon="Plus" @click="handleAdd"
v-hasPermi="['manage:content:add']">新增</el-button>
<!-- <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()"
v-hasPermi="['manage:content:edit']">修改</el-button>
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()"
v-hasPermi="['manage:content:remove']">删除</el-button> -->
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-table :height="autoTableHeight" v-loading="loading" :data="articleList"
@selection-change="handleSelectionChange" border>
<el-table-column fixed label="序号" align="center" width="80">
<template #default="scope">
<span>{{ (queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column label="ID" align="center" prop="id" fixed v-if="false" width="50px" />
<el-table-column label="景点名称" align="center" prop="name" fixed v-if="queryParams.type == '0'" width="180px" />
<el-table-column label="商家名称" align="center" prop="name" fixed v-if="queryParams.type != '0'" width="180px" />
<el-table-column label="排序" align="center" prop="orderNum" width="60px" />
<el-table-column label="等级" align="center" prop="level" v-if="queryParams.type == '0'">
<template #default="scope">
{{ formatLevel(scope.row.level) }}
</template>
</el-table-column>
<el-table-column :label="queryParams.type == '0' ? '景点icon' : '商家icon'" align="center" prop="icon" />
<el-table-column label="是否营业" align="center" prop="isOpen">
<template #default="scope">
<span>{{ scope.row.isOpen == 0 ? '否' : '是' }}</span>
</template>
</el-table-column>
<el-table-column :label="queryParams.type == '0' ? '景点属性' : '商家属性'" align="center" prop="attribute" width="120px">
<template #default="scope">
{{
scope.row.attribute == '1'
? `${queryParams.type == '0' ? '标志性景点' : '标志性商家'}`
: `${queryParams.type == '0' ? '非标志性景点' : '非标志性商家'}`
}}
</template>
</el-table-column>
<el-table-column label="地理坐标" align="center" prop="" width="200px">
<template #default="scope">
{{ scope.row.longitude + ',' + scope.row.latitude }}
</template>
</el-table-column>
<el-table-column label="地址信息" align="center" prop="address" width="180px" />
<el-table-column label="联系电话" align="center" prop="number" width="120px" />
<el-table-column label="标签" align="center" prop="tagId" show-overflow-tooltip width="150px">
<template #default="scope">
<span>{{ formatTag(scope.row.tagId) }}</span>
</template>
</el-table-column>
<el-table-column label="推荐语" align="center" prop="recommend" width="180px" show-overflow-tooltip />
<el-table-column :label="queryParams.type == '0' ? '景点详情' : '详情'" align="center" prop="remark">
<template #default="scope">
<el-button link type="primary" @click="handleDetail(scope.row)">查看</el-button>
</template>
</el-table-column>
<el-table-column label="相关笔记" align="center" prop="recommendNotebookCount">
<template #default="scope">
<el-button link type="primary" v-if="scope.row.status!==3" @click="handleNote(scope.row)">1{{
scope.row.pubNotebookCount }}</el-button>
</template>
</el-table-column>
<el-table-column :label="queryParams.type == '0' ?'景点评论数':queryParams.type == '1' ?'租车评论数':'游艇评论数'" align="center"
prop="commentCount" width="90px">
<template #default="scope">
<el-button link type="primary" v-if="scope.row.status!==3" @click="handleNote(scope.row)">1{{
scope.row.notebookCommentCount }}</el-button>
</template>
</el-table-column>
<el-table-column :label="queryParams.type == '0' ?'景点喜欢数':queryParams.type == '1' ?'租车喜欢数':'游艇喜欢数'" align="center"
prop="agreeCount" width="90" />
<el-table-column :label="queryParams.type == '0' ?'景点收藏数':queryParams.type == '1' ?'租车收藏数':'游艇收藏数'" align="center"
prop="collectionCount" width="90" />
<!-- <el-table-column label="点赞数" align="center" prop="notebookAgreeCount" width="90px">
<template #default="scope">
<el-button link type="primary" v-if="scope.row.status!==3" @click="handleNote(scope.row)">1{{
scope.row.notebookAgreeCount }}</el-button>
</template>
</el-table-column> -->
<!-- 0-未发布 1-审核中 2-发布 -->
<el-table-column label="发布状态" align="center" prop="status" width="100">
<template #default="scope">
<!-- <span>{{ scope.row.status == 0 ? '未发布' : scope.row.status == 1 ? '审核中' : scope.row.status == 2 ? '已发布' : '草稿' }}</span> -->
<el-tag v-if="scope.row.status == 0" type="info">未发布</el-tag>
<el-tag v-if="scope.row.status == 1" type="success">审核中</el-tag>
<el-tag v-if="scope.row.status == 2" type="primary">已发布</el-tag>
<el-tag v-if="scope.row.status == 3" type="warning">草稿</el-tag>
</template>
</el-table-column>
<el-table-column label="操作人" align="center" prop="updateByName" width="120px" />
<el-table-column label="操作时间" align="center" prop="updateTime" width="160px" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="170px">
<template #default="scope">
<el-button link type="primary" v-if="scope.row.status == 0" @click="updateRow(scope.row, '1')"
v-hasPermi="['manage:content:edit']">发布</el-button>
<el-button link type="primary" v-if="scope.row.status == 2" @click="updateRow(scope.row, '0')"
v-hasPermi="['manage:content:edit']">撤销发布</el-button>
<el-tooltip content="编辑" placement="top" v-if="scope.row.status == 0||scope.row.status == 3">
<el-button link type="primary" @click="handleUpdate(scope.row)"
v-hasPermi="['manage:content:edit']">编辑</el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top" v-if="scope.row.status == 0||scope.row.status == 3">
<el-button link type="primary" @click="handleDelete(scope.row)"
v-hasPermi="['manage:content:remove']">删除</el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" id="table_page" :total="total" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" @pagination="getList" />
<!-- 添加或修改景点、租赁管理对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="900px" append-to-body>
<el-form ref="articleFormRef" :model="form" :rules="rules" label-width="80px">
<el-row :gutter="10">
<el-col :span="12">
<el-form-item :label="queryParams.type == '0' ? '景点名称' : '商家名称'" prop="name">
<el-input placeholder="请输入名称" v-model="form.name" />
</el-form-item>
</el-col>
<el-col :span="12" v-if="queryParams.type == '0'">
<el-form-item label="景区等级" prop="level">
<!-- <el-input-number v-model="form.level" :min="1" :max="5" /> -->
<el-select v-model="form.level" placeholder="请选择等级" clearable class="inputWidth">
<el-option v-for="item in levelList" :key="item.value" :label="item.label"
:value="item.value"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="推荐语" prop="recommend">
<el-input v-model="form.recommend" placeholder="请输入推荐语" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="排序" prop="orderNum">
<el-input-number v-model="form.orderNum" :min="1" :max="1000" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item label="是否开放" prop="isOpen">
<el-radio-group v-model="form.isOpen">
<el-radio :value="1" size="large">开放中</el-radio>
<el-radio :value="0" size="large">未开放</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item :label="queryParams.type == '0' ? '景点icon' : '商家icon'" prop="icon">
<el-upload class="upload-demo el-upload" drag :limit="1" :headers="upload.headers" :action="uploadImgUrl"
v-model:file-list="fileList_icon"
:on-success="(res, file) => returnContractSuccess('oss_icon', res, file)"
:on-preview="handlePictureCardPreview" :on-remove="
(res, file) => {
handleRemove(res, file, 'oss_icon');
}
" list-type="picture-card">
<el-icon class="el-icon--upload" :class="{}">
<Plus />
</el-icon>
</el-upload>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item :label="queryParams.type == '0' ? '景点属性' : '商家属性'" prop="attribute">
<!-- <el-checkbox v-model="form.attribute" :label="queryParams.type == '0' ? '标志性景点' : '标志性商家'" :value="1" /> -->
<el-radio-group v-model="form.attribute">
<el-radio :value="1" size="large">{{ queryParams.type == '0' ? '标志性景点' : '标志性商家' }}</el-radio>
<el-radio :value="0" size="large">{{ queryParams.type == '0' ? '非标志性景点' : '非标志性商家' }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="标签" prop="tagId_copy">
<el-select class="inputWidth" v-model="form.tagId_copy" multiple filterable placeholder="请选择标签" clearable
@visible-change="getTagList">
<el-option v-for="dict in sys_user_tagOptions" :key="dict.id" :label="dict.title"
:value="String(dict.id)" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item label="联系电话" prop="number">
<el-input v-model="form.number" placeholder="请输入电话" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="地理位置" prop="introduce">
<!-- <el-input v-model="searchLocation" type="text" placeholder="请输入地址信息" clearable /> -->
<!-- <el-input v-model="searchLocation" placeholder="请输入地址信息" class="input-with-select"
@keyup.enter="debouncedSearch(searchLocation)">
<template #append>
<el-button @click="debouncedSearch(searchLocation)" :icon="Search" />
</template>
</el-input> -->
<el-select v-model="searchLocation" filterable remote reserve-keyword clearable placeholder="请输入地址信息"
@change="selectChnange" :remote-method="remoteMethod">
<el-option v-for="item in locationOptions" :key="item.id"
:label="item.title + '&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp' + item.province+' - '+item.city"
:value="item.province+item.city+item.title" />
<!-- :value="item.ad_info.province+item.ad_info.city+item.title" /> -->
</el-select>
</el-form-item>
<tlbs-map style="margin-left: 80px" ref="map" api-key="
6XFBZ-SAVLT-JGIX2-VOLMK-6S2H3-XUBGO" :center="center" :zoom="zoom" :control="control" @click="onClick">
<tlbs-multi-marker :geometries="geometries" :styles="styles" :options="options" />
</tlbs-map>
</el-col>
</el-row>
<el-form-item label="详细地址" prop="address" style="margin-top: 15px">
<el-input v-model="form.address" placeholder="输入地理位置或点击度图上的地点" disabled />
</el-form-item>
<el-form-item label="经度" prop="longitude">
<el-input v-model="form.longitude" placeholder="输入地理位置或点击度图上的地点" disabled />
</el-form-item>
<el-form-item label="纬度" prop="latitude">
<el-input v-model="form.latitude" placeholder="输入地理位置或点击度图上的地点" disabled />
</el-form-item>
<el-row :gutter="10">
<el-col :span="24">
<el-form-item :label="`${queryParams.type == '0' ? '景点' : '商家'}照片/视频`" prop="">
<el-upload class="upload-demo el-upload" drag :headers="upload.headers" :action="uploadImgUrl"
v-model:file-list="fileList_1" multiple
:on-success="(res, file) => returnContractSuccess('oss_1', res, file)"
:on-preview="handlePictureCardPreview" :on-remove="
(res, file) => {
handleRemove(res, file, 'oss_1');
}
" list-type="picture-card">
<el-icon class="el-icon--upload" :class="{}">
<Plus />
</el-icon>
</el-upload>
</el-form-item>
</el-col>
</el-row>
<el-form-item :label="`${queryParams.type == '0' ? '景点' : '商家'}简介`" prop="intro">
<editor v-model="form.intro" :min-height="150" :height="200" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" @click="submitForm('preview')" style="float: left">预 览</el-button>
<el-button :loading="buttonLoading" @click="submitForm('draft')" style="float: left"
v-if="form.status != '0' && form.status != '1' && form.status != '2'">存草稿</el-button>
<el-button @click="cancel('submit')">取 消</el-button>
<el-button :loading="buttonLoading" type="primary" @click="submitForm('submit')">确 定</el-button>
</div>
</template>
</el-dialog>
<!-- 图片预览 -->
<el-dialog v-model="dialogVisible">
<img w-full :src="dialogImageUrl" alt="Preview Image" />
</el-dialog>
<!-- 预览弹层 -->
<el-dialog title="预览" v-model="previewVisible" width="900px" append-to-body>
<el-form ref="previewRef" :model="form" label-width="110px">
<el-row :gutter="10">
<el-col :span="12">
<el-form-item :label="queryParams.type == '0' ? '景点名称:' : '商家名称:'" prop="name">
<span>{{ form.name }}</span>
</el-form-item>
</el-col>
<el-col :span="12" v-if="queryParams.type == '0'">
<el-form-item label="景区等级:" prop="level">
<span>{{ form.level!=null?levelList[form.level-1].label:'暂无'}}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="推荐语:" prop="recommend">
<span>{{ form.recommend?form.recommend:'暂无' }}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="排序:" prop="orderNum">
<span>{{ form.orderNum }}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item label="是否开放:" prop="isOpen">
<span>{{ form.isOpen == 1 ? '开放中' : '未开放' }}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item :label="queryParams.type == '0' ? '景点icon' : '商家icon'" prop="icon">
<el-image :src="form.icon" class="avatar" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item :label="queryParams.type == '0' ? '景点属性:' : '商家属性:'" prop="attribute">
<span>{{ form.attribute == 1 ? '标志性' : '非标志性' }}</span>
<span>{{ queryParams.type == '0' ? '景点' : '商家' }}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="标签:" prop="tagId">
<!-- <el-select class="inputWidth" v-model="form.tagId_copy" placeholder="请选择标签" clearable disabled>
<el-option v-for="item in sys_user_tagOptions" :key="item.id" :label="item.title" :value="item.id" />
</el-select> -->
<span>{{ formatTag(form.tagId) }}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12">
<el-form-item label="联系电话:" prop="number">
<span>{{ form.number?form.number:'暂无' }}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="详细地址:" prop="address" style="margin-top: 15px">
<span>{{ form.address }}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="经度:" prop="longitude">
<span>{{ form.longitude }}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="纬度:" prop="latitude">
<span>{{ form.latitude }}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="24">
<el-form-item :label="`${queryParams.type == '0' ? '景点' : '商家'}照片/视频:`" prop="" label-width="110px">
<!-- <el-image v-for="item in fileList_1" :key="item" :src="item" class="avatar" /> -->
</el-form-item>
</el-col>
</el-row>
<el-form-item :label="`${queryParams.type == '0' ? '景点' : '商家'}简介:`" prop="intro">
<div v-if="form.intro" v-html="form.intro"></div>
<div v-else>暂无</div>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="cancel('preview')">关 闭</el-button>
</div>
</template>
</el-dialog>
<!-- 相关笔记 -->
<el-dialog title="相关笔记" v-model="noteListDialog.visible" width="1200px" append-to-body>
<noteList :autoTableHeight="300" :sys_user_tagOptions="sys_user_tagOptions" parentName="scenic"
:articleList="noteListDialog.articleList" :type="queryParams.type" :id="form.id"></noteList>
<pagination v-show="noteListDialog.total > 0" :total="noteListDialog.total"
v-model:page="noteListDialog.params.pageNum" v-model:limit="noteListDialog.params.pageSize"
@pagination="handleNote" />
<template #footer>
<div class="dialog-footer">
<el-button @click="cancel('noteBookVisible')">关 闭</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="Article" lang="ts">
import { listTag,tagAll } from '@/api/manage/tag';
import { listArticle, getArticle, delArticle, addArticle, updateArticle, listByTagIdNotebook,recommend } from '@/api/manage/scenic';
import { ArticleVO, ArticleQuery, ArticleForm } from '@/api/manage/scenic/types';
import { useRouter } from 'vue-router';
import { getToken } from '@/utils/auth';
import { debounce } from '@/utils/debounce.js';
import { jsonp } from 'vue-jsonp';
import { Search } from '@element-plus/icons-vue';
import type { UploadProps, UploadUserFile } from 'element-plus';
const baseUrl = import.meta.env.VITE_APP_BASE_API;
const uploadImgUrl = ref(baseUrl + '/resource/oss/upload'); // 上传的图片服务器地址
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const autoTableHeight = ref<number>(750);
const articleList = ref<ArticleVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const sys_user_tagOptions = ref([]); //标签库
const fileList_1 = ref<UploadUserFile[]>([]);
const fileList_icon = ref<UploadUserFile[]>([]);
const queryFormRef = ref<ElFormInstance>();
const articleFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: '',
type:''
});
const locationOptions = ref([]); //腾讯地图返回的搜索地址列表
const noteLists = ref([]); // 相关笔记列表
const previewRef = ref(null);
const previewVisible = ref(false); //预览弹层
const dialogImageUrl = ref('');
const dialogVisible = ref(false);
const upload = reactive({
// 是否显示弹出层(用户导入)
returnContractShow: false,
// 是否禁用上传
isUploading: false,
// 是否更新已经存在的用户数据
updateSupport: 0,
// 设置上传的请求头部
headers: {
Clientid: import.meta.env.VITE_APP_CLIENT_ID,
Authorization: 'Bearer ' + getToken()
}
});
const levelList = ref([
{ label: 'A级', value: 1 },
{ label: 'AA级', value: 2 },
{ label: 'AAA级', value: 3 },
{ label: 'AAAA级', value: 4 },
{ label: 'AAAAA级', value: 5 }
]);
const initFormData: ArticleForm = {
name: undefined,
id: undefined,
type: undefined,
secondType: undefined,
isOpen: undefined,
attribute: null,
status: undefined,
province: '',
city: '460108',
region: '460108',
regionCode: '460108',
remark: undefined,
memberLevel: undefined,
tagId: undefined,
tagId_copy: [],
recommend: undefined,
intro: undefined,
address: '海南省海口市美兰区大英山西二街',
longitude: '110.348801',
latitude: '20.018883',
orderNum: 1,
level: null,
mediaBoList: undefined,
icon: undefined
};
const checkIcon = (rule: any, value: any, callback: any) => {
value = form.value.icon;
console.log(value, form.value);
if (!value) {
callback();
// return callback(new Error('请上传商家或景点icon'));
} else {
callback();
}
};
const data = reactive<PageData<ArticleForm, ArticleQuery>>({
queryParams: {
pageNum: 1,
pageSize: 10,
name: undefined,
type: undefined,
secondType: undefined,
isOpen: undefined,
attribute: undefined,
status: undefined,
province: undefined,
city: undefined,
memberLevel: undefined,
tagId: undefined,
tagId_copy: [],
recommend: undefined,
intro: undefined,
address: undefined,
longitude: undefined,
latitude: undefined,
orderNum: undefined,
level: undefined,
params: {}
},
form: { ...initFormData },
rules: {
id: [{ required: true, message: '景点ID/租赁ID/游艇ID不能为空', trigger: 'blur' }],
name: [{ required: true, message: '名称不能为空', trigger: 'blur' }],
number: [{ required: true, message: '电话不能为空', trigger: 'blur' }],
icon: [{ required: false, validator: checkIcon, trigger: 'change' }],
isOpen: [{ required: true, message: '请选择开放状态', trigger: 'change' }],
attribute: [{ required: true, message: '景点属性/商家属性不能为空', trigger: 'blur' }],
// remark: [{ required: true, message: '个人简介不能为空', trigger: 'blur' }],
// memberLevel: [{ required: true, message: '会员等级不能为空', trigger: 'blur' }],
tagId_copy: [{ required: true, message: '标签不能为空', trigger: 'blur' }],
recommend: [{ required: true, message: '推荐语不能为空', trigger: 'blur' }],
address: [{ required: true, message: '详细地址不能为空', trigger: 'blur' }],
longitude: [{ required: true, message: '经度不能为空', trigger: 'blur' }],
latitude: [{ required: true, message: '纬度不能为空', trigger: 'blur' }],
orderNum: [{ required: true, message: '排序不能为空', trigger: 'blur' }],
level: [{ required: true, message: '景区等级不能为空', trigger: 'blur' }],
intro: [{ required: true, message: '简介不能为空', trigger: 'blur' }]
}
});
const { queryParams, form, rules } = toRefs(data);
const map = ref(null);
const center = ref({ lat: form.value.latitude || 20.018883, lng: form.value.longitude || 110.348801 });
const zoom = ref(17);
const control = reactive({
scale: {},
zoom: {
position: 'topLeft'
}
});
const searchLocation = ref(''); // 搜索地点
const geometries = ref([{ styleId: 'marker', position: { lat: form.value.latitude || 20.018883, lng: form.value.longitude || 110.348801 } }]);
const styles = reactive({
marker: {
width: 20,
height: 30,
anchor: { x: 10, y: 30 }
}
});
const options = reactive({
minZoom: 5,
maxZoom: 20
});
// 监听输入框内容变化,调用防抖后的搜索函数
watch(searchLocation, (newValue) => {
// debouncedSearch(newValue);
});
// 路由监听================================================
let router = useRouter();
watch(
() => router.currentRoute.value,
() => {
let query = router.currentRoute.value.query;
if (query) {
queryParams.value.type = query.type as string;
}
console.log('路由信息:', router.currentRoute.value);
},
{ immediate: true }
);
onMounted(() => {
getTag(); //标签库
getList();
nextTick(() => {
autoTableHeight.value = proxy?.autoTableHeight();
});
window.onresize = () => {
autoTableHeight.value = proxy?.autoTableHeight();
};
});
const getTag = async () => {
const res = await tagAll();
sys_user_tagOptions.value = res; //标签库
};
const getTagList = async (visible: boolean) => {
if (visible) {
getTag(); //标签库
}
}
// 地理位置 输入实时搜索
const remoteMethod = (query: string) => {
if (query !== '') {
// 调用腾讯地图API进行搜索并展示在地图上
// geocoder(query).then((result) => {
// console.log(result);
// });
console.log(query);
// jsonp(`https://apis.map.qq.com/ws/place/v1/search?key=${'6XFBZ-SAVLT-JGIX2-VOLMK-6S2H3-XUBGO'}&keyword=${encodeURI(query)}&boundary=nearby(20.018883,110.348801,1000)&output=jsonp`, {}).then((res) => {
jsonp(`https://apis.map.qq.com/ws/place/v1/suggestion?key=${'6XFBZ-SAVLT-JGIX2-VOLMK-6S2H3-XUBGO'}&keyword=${encodeURI(query)}&region=三亚市&region_fix=0&output=jsonp`, {}).then((res) => {
// if (res.region.title!=='海南省') {
// proxy?.$modal.msgError('仅支持海南省地理位置');
// return
// }
if (res.status == 0) {
locationOptions.value = res.data;
}
});
}
}
// 选择地理位置 下拉框值变化
const selectChnange = (val:string) => {
if (val) {
debouncedSearch(searchLocation.value)
}
}
//输入位置,搜索位置
const performSearch = async (text) => {
// 这里简单模拟延迟,模拟真实的异步请求耗时
// await new Promise((resolve) => setTimeout(resolve, 500));
// 假设这里根据输入的文本去查找匹配的数据,实际中替换成真实逻辑
if (text === '') {
console.log('搜索内容为空');
} else {
// console.log('搜索内容为:', text);
// 调用腾讯地图API进行搜索并展示在地图上
// geocoder(text).then((result) => {
// console.log(result);
// });
jsonp(`https://apis.map.qq.com/ws/geocoder/v1/?address=${text}&key=${'6XFBZ-SAVLT-JGIX2-VOLMK-6S2H3-XUBGO'}&output=jsonp`, {}).then((data) => {
// console.log(data);
if (data.status == 0) {
form.value.address =
data.result.address_components.province +
data.result.address_components.city +
data.result.address_components.district +
data.result.address_components.street +
data.result.address_components.street_number;
form.value.latitude = data.result.location.lat;
form.value.longitude = data.result.location.lng;
form.value.region = data.result.ad_info.adcode; //行政区划编码
form.value.regionCode = data.result.ad_info.adcode; //行政区划编码
// form.value.province = data.result.address_components.province;
// form.value.city = data.result.address_components.city;
center.value = { lat: data.result.location.lat, lng: data.result.location.lng };
geometries.value = [{ styleId: 'marker', position: { lat: data.result.location.lat, lng: data.result.location.lng } }];
} else if (data.status == 348) {
//地址信息不明确,需弹出提示
proxy?.$modal.msgError('未查询到地点,请补充详细地址信息');
return;
}
});
}
};
// 点击地点,获取经纬度及地址信息
const onClick = (e: any) => {
jsonp(
`https://apis.map.qq.com/ws/geocoder/v1/?key=${'6XFBZ-SAVLT-JGIX2-VOLMK-6S2H3-XUBGO'}&location=${e.latLng.lat},${e.latLng.lng}&output=jsonp`,
{}
).then((data) => {
if (data.status == 0) {
if (form.value) {
form.value.address =
data.result.address_component.province +
data.result.address_component.city +
data.result.address_component.district +
data.result.address_component.street +
data.result.address_component.street_number;
form.value.latitude = data.result.location.lat;
form.value.longitude = data.result.location.lng;
// form.value.province = data.result.address_component.province;
// form.value.city = data.result.address_component.city;
form.value.region = data.result.ad_info.adcode; //行政区划编码
form.value.regionCode = data.result.ad_info.adcode; //行政区划编码
center.value = { lat: data.result.location.lat, lng: data.result.location.lng };
searchLocation.value = data.result.formatted_addresses?.recommend;
geometries.value = [{ styleId: 'marker', position: { lat: data.result.location.lat, lng: data.result.location.lng } }];
}
}
});
};
const debouncedSearch = debounce(performSearch, 300); // 创建防抖后的搜索函数延迟设为300毫秒
/** 查询景点、租赁管理列表 */
const getList = async () => {
loading.value = true;
if (queryParams.value.tagId && queryParams.value.tagId.length > 0) {
queryParams.value.tagId = queryParams.value.tagId.toString();
}
const res = await listArticle(queryParams.value).finally(() => (loading.value = false));
articleList.value=[];
res.rows.forEach((element: any) => {
if (element.region == null) {
element.region = element.city;
element.regionCode = element.city;
} else {
element.regionCode = element.region;
}
});
articleList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = (type: string) => {
if (type == 'preview') {
previewVisible.value = false;
return;
}
reset(type);
dialog.visible = false;
noteBookVisible.value = false;
noteBookTagIds.value = ''; // 清空标签
noteListDialog.visible = false;
noteListDialog.params.pageNum=1;
};
/** 表单重置 */
const reset = (type: string = '') => {
if (type == 'preview') {
previewRef.value?.resetFields();
return;
}
searchLocation.value = '';
form.value = { ...initFormData };
articleFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: ArticleVO[]) => {
for (let i = 0; i < selection.length; i++) {
const element = selection[i];
if (element.status=='2') {
proxy.$modal.msgError('已发布的数据不能修改或删除');
return
}
}
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/**
* 等级格式化
*/
const formatLevel = (level: number | string) => {
switch (level) {
case 1:
return 'A';
break;
case 2:
return 'AA';
break;
case 3:
return 'AAA';
break;
case 4:
return 'AAAA';
break;
case 5:
return 'AAAAA';
break;
default:
break;
}
};
/**
* 标签格式化
*/
const formatTag = (tagId: string | null) => {
let tagString = '';
for (let i = 0; i < sys_user_tagOptions.value.length; i++) {
const element = sys_user_tagOptions.value[i];
if (tagId!=null) {
let filteredArray = tagId.split(',').filter((item) => item==element.id);
if (filteredArray.length>0) {
tagString += '' + element.title;
}
}
}
return tagString.substring(1);
};
/** 新增按钮操作 */
const handleAdd = () => {
reset();
dialog.visible = true;
if (queryParams.value.type == '0') {
dialog.title = '添加景点';
} else {
dialog.title = '添加商家';
}
};
/** 修改按钮操作 */
const handleUpdate = async (row?: any) => {
reset();
const _id = row?.id || ids.value[0];
const res = await getArticle(_id);
if (res.data.status=='2') {
proxy?.$modal.msgError('已发布的文章,无法修改');
return
}
res.data.tagId_copy = (res.data.tagId==''||res.data.tagId==null)?[]:res.data.tagId?.split(',');
if (res.data.region == null) {
res.data.region = res.data.city;
res.data.regionCode = res.data.city;
} else {
res.data.regionCode = res.data.region;
}
searchLocation.value = res.data.address;
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = queryParams.value.type == '0' ? '修改景点' : '修改商家';
center.value = { lat: row.latitude, lng: row.longitude };
geometries.value = [{ styleId: 'marker', position: { lat: row.latitude, lng: row.longitude } }];
};
/**
*
* @param row 预览详情
*/
const handleDetail = async (row?: ArticleVO) => {
reset();
const _id = row?.id || ids.value[0];
const res = await getArticle(_id);
res.data.tagId_copy = res.data.tagId?.split(',');
Object.assign(form.value, res.data);
previewVisible.value = true;
};
/**
*
* @param row 相关笔记
*/
const noteBookVisible = ref(false);
const noteBookTagIds = ref(''); //相关笔记的标签id
const noteListDialog = reactive({
visible: false,
total: 0,
articleList:[],
params:{
articleId: null,
pageNum: 1,
pageSize: 10,
}
});
// 相关笔记 请求列表
const handleNote = async (row?: ArticleVO) => {
// noteBookTagIds.value = '';
// noteBookTagIds.value = row?.tagId as string;
if (row.id) {
noteListDialog.params.articleId = row?.id;
}
let res = await recommend(noteListDialog.params);
noteListDialog.articleList=res.rows;
noteListDialog.visible = true;
};
/** 新增景点,商家提交按钮 */
const submitForm = async (type: string) => {
form.value.type = queryParams.value.type;
form.value.tagId = form.value.tagId_copy?.join(',');
if (type == 'draft') {
// 存草稿,不验证必填项
form.value.status = '3'; //草稿状态为3
if (!form.value.name) {
proxy?.$modal.msgError('请输入名称');
return
}
buttonLoading.value = true;
if (form.value.id) {
await updateArticle(form.value).finally(() => (buttonLoading.value = false));
} else {
let res = await addArticle(form.value).finally(() => (buttonLoading.value = false));
form.value.id = res.msg;
}
proxy?.$modal.msgSuccess('操作成功');
// dialog.visible = false;
await getList();
return;
}
articleFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
if (type == 'preview') {
//预览
previewVisible.value = true;
return;
}
buttonLoading.value = true;
// if (!form.value.attribute) {
// form.value.attribute = 0;
// } else if (form.value.attribute == true) {
// form.value.attribute = 0;
// }
if (form.value.id) {
form.value.status = '0'; //未发布状态为0
await updateArticle(form.value).finally(() => (buttonLoading.value = false));
} else {
await addArticle(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/**
*
* @param row 发布,撤销发布
* @param type
*/
const updateRow = async (row: any, type: string) => {
await proxy?.$modal.confirm('是否确认' + (type == '0' ? '撤销发布' : '发布') + '名称为"' + row.name + '"的数据项?');
// row.status = type;
Object.assign(form.value, row);
form.value.status = type;
buttonLoading.value = true;
await updateArticle(form.value).finally(() => (buttonLoading.value = false));
proxy?.$modal.msgSuccess('操作成功');
getList();
};
/** 删除按钮操作 */
const handleDelete = async (row?: ArticleVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除名称为"' + row.name + '"的数据项?').finally(() => (loading.value = false));
await delArticle(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'system/article/export',
{
...queryParams.value
},
`article_${new Date().getTime()}.xlsx`
);
};
// 图像上传成功回调
const returnContractSuccess = (type: string, response: any, uploadFile: UploadFile) => {
// console.log(type, response, uploadFile);
if (response.code == 200) {
proxy?.$modal.msgSuccess('上传成功');
if (type == 'oss_1') {
let typeFlag = false;
let obj = {
mediaType: type,
mediaOssId: response.data.ossId
};
form.value.mediaBoList.push(obj);
} else if (type == 'oss_icon') {
form.value.icon = response.data.ossId;
}
}
};
/**
*
* @param uploadFile 预览文件
*/
const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
dialogImageUrl.value = uploadFile.url!;
dialogVisible.value = true;
};
/**
*
* @param uploadFile 删除文件
* @param uploadFiles
* @param type
*/
const handleRemove = (uploadFile, uploadFiles, type) => {
console.log(uploadFile, uploadFiles, type);
if (type == 'oss_1') {
form.value.mediaBoList.forEach((item, index) => {
if (type == item.mediaType) {
form.value.mediaBoList.splice(index, 1);
}
});
} else if (type == 'oss_icon') {
form.value.icon = '';
}
};
</script>
<style lang="scss" scoped>
.el-card :deep(.el-card__body) {
padding-bottom: 0px !important;
}
#table_page {
height: 50px !important;
margin-top: 10px !important;
padding-bottom: 10px !important;
}
.el-upload {
:deep(.el-upload-dragger) {
padding: 0;
height: 100%;
i {
top: 30%;
left: 50%;
position: absolute;
transform: translateX(-50%);
font-size: 45px;
}
}
}
</style>