AdwebSiteList.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. <template>
  2. <div class="p-2">
  3. <!--查询区域-->
  4. <div class="jeecg-basic-table-form-container">
  5. <a-form ref="formRef" @keyup.enter.native="searchQuery" :model="queryParam" :label-col="labelCol" :wrapper-col="wrapperCol">
  6. <a-row :gutter="24">
  7. <a-col :xxl="6" :xl="7">
  8. <a-form-item name="name" label="站点名称">
  9. <j-input placeholder="请输入站点名称" v-model:value="queryParam.name" allow-clear />
  10. </a-form-item>
  11. </a-col>
  12. <a-col :xxl="6" :xl="7">
  13. <a-form-item name="domain" label="站点域名">
  14. <j-input placeholder="请输入站点域名" v-model:value="queryParam.domain" allow-clear />
  15. </a-form-item>
  16. </a-col>
  17. <a-col :xxl="6" :xl="8">
  18. <a-form-item label="发布状态">
  19. <j-search-select placeholder="请选择发布状态" v-model:value="queryParam.status" dict="site_status" />
  20. </a-form-item>
  21. </a-col>
  22. <template v-if="toggleSearchStatus">
  23. <a-col :xxl="6" :xl="7">
  24. <a-form-item label="渠道商">
  25. <a-select placeholder="请选择渠道商" v-model:value="queryParam.channelProviderId" showSearch allowClear :filterOption="filterOption">
  26. <a-select-option v-for="data in channelProviderList" :key="data.username" :value="data.workNo">
  27. {{ data.username }}
  28. </a-select-option>
  29. </a-select>
  30. </a-form-item>
  31. </a-col>
  32. <!-- <a-col :xxl="12" :xl="10">-->
  33. <!-- <a-form-item label="创建时间">-->
  34. <!-- <j-range-date placeholder="请选择开始日期" class="query-group-cust" v-model:value="queryParam.ctime" />-->
  35. <!-- </a-form-item>-->
  36. <!-- </a-col>-->
  37. <!-- <a-col :xl="10" :lg="11" :md="12" :sm="24">-->
  38. <!-- <a-form-item label="到期时间">-->
  39. <!-- <j-range-date placeholder="请选择开始日期" class="query-group-cust" v-model:value="queryParam.etime" />-->
  40. <!-- </a-form-item>-->
  41. <!-- </a-col>-->
  42. </template>
  43. <a-col :xl="6" :lg="7" :md="8" :sm="24">
  44. <span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
  45. <a-col :lg="6">
  46. <a-button type="primary" preIcon="ant-design:search-outlined" @click="searchQuery">查询</a-button>
  47. <a-button type="primary" preIcon="ant-design:reload-outlined" @click="searchReset" style="margin-left: 8px">重置</a-button>
  48. <a @click="toggleSearchStatus = !toggleSearchStatus" style="margin-left: 8px">
  49. {{ toggleSearchStatus ? '收起' : '展开' }}
  50. <Icon :icon="toggleSearchStatus ? 'ant-design:up-outlined' : 'ant-design:down-outlined'" />
  51. </a>
  52. </a-col>
  53. </span>
  54. </a-col>
  55. </a-row>
  56. </a-form>
  57. </div>
  58. <!--引用表格-->
  59. <BasicTable @register="registerTable" :rowSelection="rowSelection">
  60. <!--插槽:table标题-->
  61. <template #tableTitle>
  62. <a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
  63. <a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
  64. <!-- <j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>-->
  65. <!-- <a-dropdown v-if="selectedRowKeys.length > 0">-->
  66. <!-- <template #overlay>-->
  67. <!-- <a-menu>-->
  68. <!-- <a-menu-item key="1" @click="batchHandleDelete">-->
  69. <!-- <Icon icon="ant-design:delete-outlined" />-->
  70. <!-- 删除-->
  71. <!-- </a-menu-item>-->
  72. <!-- </a-menu>-->
  73. <!-- </template>-->
  74. <!-- <a-button-->
  75. <!-- >批量操作-->
  76. <!-- <Icon icon="mdi:chevron-down" />-->
  77. <!-- </a-button>-->
  78. <!-- </a-dropdown>-->
  79. <!-- 高级查询 -->
  80. <super-query :config="superQueryConfig" @search="handleSuperQuery" />
  81. </template>
  82. <!--操作栏-->
  83. <template #action="{ record }">
  84. <TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" />
  85. </template>
  86. <template #bodyCell="{ column, record, index, text }">
  87. <div v-if="column.dataIndex == 'name'">
  88. <a :href="record.domain" target="_blank">{{ text }}</a>
  89. </div>
  90. <div v-if="column.dataIndex == 'domain'">
  91. <a :href="record.domain" target="_blank">{{ text }}</a>
  92. </div>
  93. <div v-if="column.dataIndex == 'subscribePlan'">
  94. <template v-if="text === null || text === ''"> 无 </template>
  95. <template v-else>
  96. <a-popover>
  97. <template #content>
  98. <a-descriptions bordered :column="{ xxl: 1, xl: 1, lg: 1, md: 1, sm: 1, xs: 1 }" title="SEO套餐详情" size="default">
  99. <a-descriptions-item label="套餐名">
  100. {{ text.planName }}
  101. </a-descriptions-item>
  102. <a-descriptions-item label="关键词"> {{ text.keywordCount }}个 </a-descriptions-item>
  103. <a-descriptions-item label="服务时间">
  104. <template v-if="text.serviceTime != 0"> {{ text.serviceTime }}个月 </template>
  105. <template v-else> 长期 </template>
  106. </a-descriptions-item>
  107. <a-descriptions-item label="价格"> {{ text.price }}元 </a-descriptions-item>
  108. </a-descriptions>
  109. </template>
  110. <a-tag color="blue">
  111. {{ text.planName }}
  112. </a-tag>
  113. </a-popover>
  114. </template>
  115. </div>
  116. <div v-if="column.dataIndex == 'status_dictText'">
  117. <template v-if="record.status == 1">
  118. <a-tag color="blue">
  119. {{ text }}
  120. </a-tag>
  121. </template>
  122. <template v-else-if="record.status == 2">
  123. <a-tag color="green">
  124. {{ text }}
  125. </a-tag>
  126. </template>
  127. <template v-else>
  128. <a-tag color="red">
  129. {{ text }}
  130. </a-tag>
  131. </template>
  132. </div>
  133. <div v-if="column.dataIndex == 'siteCurrentStep'">
  134. <span v-if="text === null || text === undefined || text === ''"> - </span>
  135. <template v-else>
  136. <a @click="handleProcess(record, 'site')"> <span class="circle" style="background-color: #7194f8"></span>{{ text }} </a>
  137. </template>
  138. </div>
  139. <div v-if="column.dataIndex == 'completeProcess'">
  140. <a-progress :stroke-color="{ '0%': '#108ee9', '100%': '#87d068' }" :percent="record.completeProcess" />
  141. </div>
  142. </template>
  143. </BasicTable>
  144. <!-- 表单区域 -->
  145. <AdwebSiteModal ref="registerModal" @success="handleSuccess" />
  146. <site-set-enquiry ref="siteSetEnquiryRef" @success="reload" />
  147. <!-- 自动化嵌入GTM 代码 -->
  148. <gtm-add ref="gtmRef" />
  149. <!--SEO流程-->
  150. <seo-process ref="seoProcessRef" :visible="seoProcessVisible" :title="processTitle" @close="closeProcess" @reload="reload" />
  151. <google-ads-modal ref="googleAdsModalRef" @success="reload" />
  152. </div>
  153. </template>
  154. <script lang="ts" name="adweb-adwebSite" setup>
  155. import { computed, onBeforeMount, reactive, ref } from 'vue';
  156. import { getAction } from '/@/api/manage/manage';
  157. import { BasicTable, TableAction } from '/src/components/Table';
  158. import { useListPage } from '/src/hooks/system/useListPage';
  159. import { columns, superQuerySchema } from './AdwebSite.data';
  160. import { batchDelete, deleteOne, getExportUrl, getImportUrl, list, gtmListUrl, saveOrUpdate } from './AdwebSite.api';
  161. import AdwebSiteModal from './components/AdwebSiteModal.vue';
  162. import { useUserStore } from '/src/store/modules/user';
  163. import SeoProcess from '@/views/adweb/site/components/SeoProcess.vue';
  164. import JInput from '@/components/Form/src/jeecg/components/JInput.vue';
  165. import JSearchSelect from '@/components/Form/src/jeecg/components/JSearchSelect.vue';
  166. import GtmAdd from '@/views/adweb/site/components/GtmAdd.vue';
  167. import { RoleEnum } from '@/enums/roleEnum';
  168. import { useMessage } from '@/hooks/web/useMessage';
  169. import SiteSetEnquiry from '@/views/adweb/site/components/SiteSetEnquiry.vue';
  170. import GoogleAdsModal from './components/GoogleAdsModal.vue';
  171. const formRef = ref();
  172. const queryParam = reactive<any>({});
  173. const toggleSearchStatus = ref<boolean>(false);
  174. const registerModal = ref();
  175. const userStore = useUserStore();
  176. const processTitle = ref('');
  177. const seoProcessVisible = ref(false);
  178. const seoProcessRef = ref();
  179. const gtmRef = ref();
  180. const siteSetEnquiryRef = ref();
  181. const googleAdsModalRef = ref();
  182. const isAdmin = computed(() => userStore.getRoleList.includes(RoleEnum.ADMIN));
  183. const { createMessage } = useMessage();
  184. let channelProviderList = reactive([{ username: '', workNo: '' }]);
  185. //注册table数据
  186. const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
  187. tableProps: {
  188. title: 'adweb站点配置表单',
  189. api: list,
  190. columns,
  191. canResize: false,
  192. useSearchForm: true,
  193. showTableSetting: true,
  194. actionColumn: {
  195. width: 120,
  196. fixed: 'right',
  197. },
  198. beforeFetch: (params) => {
  199. return Object.assign(params, queryParam);
  200. },
  201. },
  202. exportConfig: {
  203. name: 'adweb站点配置表单',
  204. url: getExportUrl,
  205. params: queryParam,
  206. },
  207. importConfig: {
  208. url: getImportUrl,
  209. success: handleSuccess,
  210. },
  211. });
  212. const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] =
  213. tableContext;
  214. const labelCol = reactive({
  215. xs: 24,
  216. sm: 4,
  217. xl: 6,
  218. xxl: 4,
  219. });
  220. const wrapperCol = reactive({
  221. xs: 24,
  222. sm: 20,
  223. });
  224. // 高级查询配置
  225. const superQueryConfig = reactive(superQuerySchema);
  226. //渠道商搜索
  227. const filterOption = (input: string, option: any) => {
  228. console.log(option, 'optionoption');
  229. return option.key.toLowerCase().indexOf(input.toLowerCase()) >= 0;
  230. };
  231. onBeforeMount(() => {
  232. getChannelProvider();
  233. });
  234. function getChannelProvider() {
  235. getAction('/adweb/system/getChannelProvider', null).then((res) => {
  236. channelProviderList = res.result;
  237. });
  238. }
  239. /**
  240. * 高级查询事件
  241. */
  242. function handleSuperQuery(params) {
  243. Object.keys(params).map((k) => {
  244. queryParam[k] = params[k];
  245. });
  246. searchQuery();
  247. }
  248. /**
  249. * 新增事件
  250. */
  251. function handleAdd() {
  252. registerModal.value.disableSubmit = false;
  253. registerModal.value.add();
  254. }
  255. /**
  256. * 编辑事件
  257. */
  258. function handleEdit(record: Recordable) {
  259. registerModal.value.disableSubmit = false;
  260. registerModal.value.edit(record);
  261. }
  262. /**
  263. * 详情
  264. */
  265. function handleDetail(record: Recordable) {
  266. registerModal.value.disableSubmit = true;
  267. registerModal.value.edit(record);
  268. }
  269. /**
  270. * 删除事件
  271. */
  272. async function handleDelete(record) {
  273. await deleteOne({ id: record.id }, handleSuccess);
  274. }
  275. async function siteDeleteStatus(record) {
  276. record.status = 0;
  277. await saveOrUpdate(record, true)
  278. .then((res) => {
  279. if (res.success) {
  280. createMessage.success(res.message);
  281. } else {
  282. createMessage.warning(res.message);
  283. }
  284. reload();
  285. })
  286. .finally(() => {});
  287. }
  288. /**
  289. * 批量删除事件
  290. */
  291. async function batchHandleDelete() {
  292. await batchDelete({ ids: selectedRowKeys.value }, handleSuccess);
  293. }
  294. /**
  295. * 成功回调
  296. */
  297. function handleSuccess() {
  298. (selectedRowKeys.value = []) && reload();
  299. }
  300. /**
  301. * 操作栏
  302. */
  303. function getTableAction(record) {
  304. return [
  305. {
  306. label: '编辑网站',
  307. onClick: handleEdit.bind(null, record),
  308. },
  309. ];
  310. }
  311. /**
  312. * 下拉操作栏
  313. */
  314. function getDropDownAction(record) {
  315. let dropDown = [
  316. {
  317. label: '详情',
  318. onClick: handleDetail.bind(null, record),
  319. },
  320. {
  321. label: '询盘设置',
  322. onClick: setEnquiry.bind(null, record),
  323. },
  324. ];
  325. // 站点不是删除状态
  326. if (record.status != 0) {
  327. dropDown.push({
  328. label: '站点删除',
  329. onClick: siteDeleteStatus.bind(null, record),
  330. });
  331. }
  332. // 站点已发布,并且是正式域名时可以添加GTM 代码
  333. if (record.isDomain === 1 && record.status === 1) {
  334. dropDown.push({
  335. label: 'GTM代码',
  336. onClick: addGtm.bind(null, record),
  337. },{
  338. label: 'Google Ads',
  339. onClick: bindGoogleAds.bind(null, record),
  340. });
  341. }
  342. if (isAdmin.value) {
  343. dropDown.push({
  344. label: '资源删除',
  345. popConfirm: {
  346. title: '该站点将从系统中删除,站点资源将会保留15天,是否确认删除',
  347. confirm: handleDelete.bind(null, record),
  348. placement: 'topLeft',
  349. },
  350. });
  351. }
  352. return dropDown;
  353. }
  354. // 添加gtm
  355. function addGtm(r) {
  356. gtmRef.value.init(r);
  357. }
  358. // 询盘设置
  359. function setEnquiry(r) {
  360. siteSetEnquiryRef.value.init(r);
  361. }
  362. /**
  363. * 查询
  364. */
  365. function searchQuery() {
  366. reload();
  367. }
  368. /**
  369. * 重置
  370. */
  371. function searchReset() {
  372. formRef.value.resetFields();
  373. selectedRowKeys.value = [];
  374. //刷新数据
  375. reload();
  376. }
  377. function handleProcess(record, type) {
  378. seoProcessVisible.value = true;
  379. processTitle.value = record.name;
  380. seoProcessRef.value.init(record, type);
  381. seoProcessRef.value.isCustomer = true;
  382. }
  383. function closeProcess() {
  384. seoProcessVisible.value = false;
  385. }
  386. function bindGoogleAds(record) {
  387. googleAdsModalRef.value.init({ record });
  388. }
  389. </script>
  390. <style lang="less" scoped>
  391. .jeecg-basic-table-form-container {
  392. padding: 0;
  393. .table-page-search-submitButtons {
  394. display: block;
  395. margin-bottom: 24px;
  396. white-space: nowrap;
  397. }
  398. .query-group-cust {
  399. min-width: 100px !important;
  400. }
  401. .query-group-split-cust {
  402. width: 30px;
  403. display: inline-block;
  404. text-align: center;
  405. }
  406. .ant-form-item:not(.ant-form-item-with-help) {
  407. margin-bottom: 16px;
  408. height: 32px;
  409. }
  410. :deep(.ant-picker),
  411. :deep(.ant-input-number) {
  412. width: 100%;
  413. }
  414. }
  415. </style>