Files
guofu-admin/src/views/system/company/index.vue
2024-05-17 06:04:56 +08:00

627 lines
20 KiB
Vue

<template>
<a-page-header :title="title" @back="() => $router.go(-1)">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<!-- 表格 -->
<ele-pro-table
ref="tableRef"
row-key="companyId"
:columns="columns"
:datasource="datasource"
:scroll="{ x: 1200 }"
cache-key="proSystemCompanyTable"
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@advanced="openAdvanced"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'shortName'">
<StarOutlined
@click="onCollection(record)"
class="tag-icon"
:class="
record.collection ? 'ele-text-warning' : 'ele-text-placeholder'
"
/>
{{ record.shortName }}
</template>
<template v-if="column.key === 'companyLogo'">
<div class="company-box">
<a-image
:height="45"
:width="45"
:preview="false"
:src="record.companyLogo"
fallback="https://file.wsdns.cn/20230218/550e610d43334dd2a7f66d5b20bd58eb.svg"
/>
</div>
</template>
<template v-if="column.key === 'phone'">
<div class="ele-text-secondary">{{ record.companyName }}</div>
<div
v-any-role="['merchant', 'superAdmin']"
class="ele-text-secondary"
>{{ record.phone }}</div
>
<div v-role="'guest'" class="ele-text-secondary">{{
record.mobile
}}</div>
</template>
<template v-if="column.key === 'comments'">
<span class="ele-text-secondary">{{ record.comments }}</span>
</template>
<template v-if="column.key === 'status'">
<template v-if="record.status == 0">
<a-tag>已下架</a-tag>
</template>
<template v-if="record.status == 1">
<a-tag color="green">已上架</a-tag>
</template>
</template>
<template v-if="column.key === 'expirationTime'">
<template v-if="record.version == 30"> - </template>
<template v-else>
<div>{{ toDateString(record.createTime, 'yyyy-MM-dd') }}</div>
<div>{{ toDateString(record.expirationTime, 'yyyy-MM-dd') }}</div>
<div
v-if="expirationTime(record.expirationTime) < 0"
class="ele-text-placeholder"
>
{{ expirationTimeText(record) }}
</div>
<div
v-if="
expirationTime(record.expirationTime) > 0 &&
expirationTime(record.expirationTime) < 30
"
class="ele-text-warning"
>
{{ expirationTimeText(record) }}
</div>
</template>
</template>
<template v-if="column.key === 'version'">
<a-tag v-if="record.version == 10"
><IdcardOutlined class="tag-icon" />免费版</a-tag
>
<a-tag color="blue" v-if="record.version == 20"
><IdcardOutlined class="tag-icon" />商业版</a-tag
>
<a-tag color="cyan" v-if="record.version == 30"
><IdcardOutlined class="tag-icon" />永久授权</a-tag
>
</template>
<!-- <template v-if="column.key === 'version'">-->
<!-- <a-button-->
<!-- :size="`small`"-->
<!-- v-if="record.version == 10"-->
<!-- style="-->
<!-- background-color: var(&#45;&#45;grey-8);-->
<!-- border: 1px solid var(&#45;&#45;grey-5);-->
<!-- color: var(&#45;&#45;grey-3);-->
<!-- "-->
<!-- ><IdcardOutlined />体验版</a-button-->
<!-- >-->
<!-- <a-button-->
<!-- :size="`small`"-->
<!-- style="-->
<!-- background-color: var(&#45;&#45;green-1);-->
<!-- border: 1px solid var(&#45;&#45;green-5);-->
<!-- color: var(&#45;&#45;green-7);-->
<!-- "-->
<!-- v-if="record.version == 20"-->
<!-- ><IdcardOutlined />商业版</a-button-->
<!-- >-->
<!-- <a-button-->
<!-- :size="`small`"-->
<!-- style="-->
<!-- background-color: var(&#45;&#45;cyan-1);-->
<!-- border: 1px solid var(&#45;&#45;cyan-5);-->
<!-- color: var(&#45;&#45;cyan-7);-->
<!-- "-->
<!-- v-if="record.version == 30"-->
<!-- ><IdcardOutlined />永久授权</a-button-->
<!-- >-->
<!-- </template>-->
<template v-if="column.key === 'appUrl'">
<template v-if="record.adminUrl">
<a-popover>
<template #content>
<div class="qrcode">
<a
@click="openNew(record.adminUrl)"
class="ele-text-heading"
>进入后台管理系统</a
>
<div class="ele-text-placeholder">
账号密码:预留手机号+短信验证码登录
</div>
<div
@click="copyText(`${record.adminUrl}`)"
class="ele-text-secondary"
>{{ record.adminUrl }}</div
>
</div>
</template>
<a-button :size="`small`" @click="openNew(record.adminUrl)"
><DesktopOutlined />管理后台</a-button
>
</a-popover>
</template>
<template v-if="record.merchantUrl">
<a-divider type="vertical" />
<a-popover>
<template #content>
<div class="qrcode">
<a
@click="openNew(record.merchantUrl)"
class="ele-text-heading"
>访问商户端</a
>
<div class="ele-text-placeholder"
>商户及登录账号在总后台创建</div
>
<div
@click="copyText(`${record.merchantUrl}`)"
class="ele-text-secondary"
>{{ record.merchantUrl }}</div
>
</div>
</template>
<a-button :size="`small`" @click="openNew(record.merchantUrl)"
><DesktopOutlined />商户端</a-button
>
</a-popover>
</template>
<template v-if="record.websiteUrl">
<a-divider type="vertical" />
<a-popover>
<template #content>
<div class="qrcode">
<a
class="ele-text-heading"
@click="openNew(record.websiteUrl)"
>访问PC端</a
>
<div
@click="copyText(`${record.websiteUrl}`)"
class="ele-text-secondary"
>{{ record.websiteUrl }}</div
>
</div>
</template>
<a-button :size="`small`" @click="openNew(record.websiteUrl)"
><LaptopOutlined class="ele-text-primary" />PC</a-button
>
</a-popover>
</template>
<template v-if="record.h5Code">
<a-divider type="vertical" />
<a-popover>
<template #content>
<div class="qrcode">
<ele-qr-code
:value="`http://${record.h5Code}`"
:size="160"
level="M"
:margin="1"
/>
<span>手机扫一扫</span>
<div
@click="copyText(`${record.h5Code}`)"
class="ele-text-secondary"
>{{ record.h5Code }}</div
>
</div>
</template>
<a-button :size="`small`" @click="openNew(record.h5Code)"
><QrcodeOutlined class="ele-text-warning" />H5</a-button
>
</a-popover>
</template>
<template v-if="record.mpWeixinCode">
<a-divider type="vertical" />
<a-popover>
<template #content>
<div class="qrcode">
<ele-qr-code
:value="`微信小程序未配置`"
:size="160"
level="M"
:margin="1"
/>
微信扫一扫
</div>
</template>
<a-button :size="`small`"
><WechatOutlined
class="ele-text-success"
/>微信小程序</a-button
>
</a-popover>
</template>
<template v-if="record.mpAlipayCode">
<a-divider type="vertical" />
<a-popover>
<template #content>
<div class="qrcode">
<ele-qr-code
:value="`支付宝小程序未配置`"
:size="160"
level="M"
:margin="1"
/>
支付宝扫一扫
</div>
</template>
<a-button :size="`small`"
><AlipayOutlined class="ele-text-primary" />支付宝</a-button
>
</a-popover>
</template>
<!-- <a-divider type="vertical" />-->
<!-- <a-dropdown>-->
<!-- <template #overlay>-->
<!-- <a-menu>-->
<!-- <a-menu-item key="1" @click="onCode(record.iosUrl)">-->
<!-- <AndroidOutlined class="tag-icon" />-->
<!-- <span>APP端</span>-->
<!-- </a-menu-item>-->
<!-- <a-menu-item key="2" @click="openNew(record.android)">-->
<!-- <AlipayOutlined class="tag-icon" />-->
<!-- <span>支付宝</span>-->
<!-- </a-menu-item>-->
<!-- </a-menu>-->
<!-- </template>-->
<!-- <a-button :size="`small`">-->
<!-- 更多-->
<!-- <DownOutlined />-->
<!-- </a-button>-->
<!-- </a-dropdown>-->
</template>
<template v-if="column.key === 'action'">
<template v-if="record.deleted == 1">
<a-popconfirm
placement="topRight"
title="确定从回收站放回原处吗?"
@confirm="recovery(record)"
>
<a class="ele-text-success" style="font-weight: bold">恢复</a>
</a-popconfirm>
</template>
<template v-if="record.deleted == 0">
<a-popconfirm
placement="topRight"
title="确定要删除此租户吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</template>
<template v-if="record.deleted == 1 && getUserId() == 3731">
<a-divider type="vertical" />
<a-popconfirm
placement="topRight"
title="确定要销毁该租户吗?此操作将永久删除且不可恢复"
@confirm="destruction(record)"
>
<a class="ele-text-danger" style="font-weight: bold">销毁</a>
</a-popconfirm>
</template>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<CompanyEdit v-model:visible="showEdit" :data="current" @done="reload" />
</a-page-header>
</template>
<script lang="ts" setup>
import { createVNode, ref, watch } from 'vue';
import { message, Modal } from 'ant-design-vue';
import {
ExclamationCircleOutlined,
IdcardOutlined
} from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import CompanyEdit from './components/company-edit.vue';
import {
destructionCompany,
removeBatchCompany,
removeCompany,
undeleteCompany
} from '@/api/oa/company';
import { Company, CompanyParam } from '@/api/system/company/model';
import { toDateString } from 'ele-admin-pro';
import { useRouter } from 'vue-router';
const { currentRoute } = useRouter();
import { pageCompanyAll } from '@/api/system/company';
import {
copyText,
getMerchantId,
getPageTitle,
getUserId,
openNew
} from '@/utils/common';
import { addUserCollection } from '@/api/system/user-collection';
defineProps<{
activeKey?: boolean;
data?: any;
}>();
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '租户ID',
fixed: 'left',
dataIndex: 'tenantId',
width: 90
},
{
title: 'Logo',
dataIndex: 'companyLogo',
key: 'companyLogo',
width: 90
},
{
title: '租户名称',
dataIndex: 'shortName',
key: 'shortName',
width: 240
},
{
title: '应用入口',
key: 'appUrl'
},
{
title: '版本',
dataIndex: 'version',
align: 'center',
width: 160,
key: 'version'
},
{
title: '客户信息',
dataIndex: 'phone',
align: 'center',
key: 'phone',
width: 160
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
width: 200
},
{
title: '到期时间',
dataIndex: 'expirationTime',
key: 'expirationTime',
align: 'center',
width: 160,
sorter: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
},
// {
// title: '状态',
// dataIndex: 'status',
// align: 'center',
// width: 120,
// key: 'status',
// customRender: ({ text }) => ['已上线', '开发中'][text]
// }
{
title: '操作',
key: 'action',
width: 180,
align: 'center'
}
]);
// 表格选中数据
const selection = ref<Company[]>([]);
// 当前编辑数据
const current = ref<Company | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示高级搜索
const showAdvancedSearch = ref(false);
// 页面标题
const title = getPageTitle();
// 表格数据源
const datasource: DatasourceFunction = ({ page, limit, where, orders }) => {
where.merchantId = getMerchantId();
// 默认显示我的收藏
if (where.version == undefined) {
where.version = 99;
}
// 回收站
if (where.version == 88) {
where.version = undefined;
where.deleted = 1;
}
// 查询全部
if (where.version == 100) {
where.version = undefined;
}
return pageCompanyAll({
...where,
...orders,
page,
limit
});
};
/* 搜索 */
const reload = (where?: CompanyParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: Company) => {
current.value = row ?? null;
showEdit.value = true;
};
const expirationTime = (dateTime) => {
const now = new Date().getTime();
const expiration = new Date(dateTime).getTime();
const mss = expiration - now;
let days = Math.floor(mss / (1000 * 60 * 60 * 24));
let hours = Math.floor((mss % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
let minutes = Math.floor((mss % (1000 * 60 * 60)) / (1000 * 60));
let seconds = Math.round((mss % (1000 * 60)) / 1000);
return days;
};
const expirationTimeText = (item: any) => {
const now = new Date().getTime();
const expiration = new Date(item.expirationTime).getTime();
const mss = expiration - now;
let days = Math.floor(mss / (1000 * 60 * 60 * 24));
let hours = Math.floor((mss % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
let minutes = Math.floor((mss % (1000 * 60 * 60)) / (1000 * 60));
let seconds = Math.round((mss % (1000 * 60)) / 1000);
if (item.version == 30) {
return `永久授权`;
}
if (days < 0) {
// item.status = 1;
// updateCompany(item);
return `(已过期${Math.abs(days)}天)`;
}
if (days < 30) {
return `(剩余${days}天)`;
}
};
/* 打开高级搜索 */
const openAdvanced = () => {
showAdvancedSearch.value = !showAdvancedSearch.value;
};
const onCode = (text: string) => {
console.log(text);
};
const onCollection = (item: Company) => {
addUserCollection({ tid: item.companyId }).then((msg) => {
reload();
});
};
/* 删除单个 */
const remove = (row: Company) => {
const hide = message.loading('请求中..', 0);
removeCompany(row.companyId)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
console.log(selection.value);
if (!selection.value.length) {
message.error('请至少选择一条数据');
return;
}
Modal.confirm({
title: '提示',
content: '确定要删除选中的记录吗?',
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchCompany(selection.value.map((d) => d.companyId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
// 从回收站放回原处
const recovery = (row: Company) => {
undeleteCompany(row.companyId)
.then((msg) => {
message.success(msg);
reload();
})
.catch((e) => {
message.error(e.message);
});
};
// 销毁租户
const destruction = (row: Company) => {
destructionCompany(row.tenantId)
.then((msg) => {
message.success(msg);
reload();
})
.catch((e) => {
message.error(e.message);
});
};
watch(
currentRoute,
() => {
reload();
},
{ immediate: true }
);
</script>
<script lang="ts">
import * as MenuIcons from '@/layout/menu-icons';
export default {
name: 'CompanyIndex',
components: MenuIcons
};
</script>
<style lang="less" scoped>
.tag-icon {
padding-right: 6px;
}
.qrcode {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
</style>