13 changed files with 1238 additions and 20 deletions
@ -1,10 +1,10 @@ |
|||||
VITE_APP_NAME=后台管理系统 |
VITE_APP_NAME=后台管理系统 |
||||
VITE_SOCKET_URL=wss://server.gxwebsoft.com |
VITE_SOCKET_URL=wss://server.gxwebsoft.com |
||||
VITE_SERVER_URL=https://server.gxwebsoft.com/api |
VITE_SERVER_URL=https://server.gxwebsoft.com/api |
||||
VITE_API_URL=https://cms-api.websoft.top/api |
|
||||
|
#VITE_API_URL=https://cms-api.websoft.top/api |
||||
|
|
||||
|
|
||||
#VITE_SOCKET_URL=ws://127.0.0.1:9191 |
#VITE_SOCKET_URL=ws://127.0.0.1:9191 |
||||
#VITE_SERVER_URL=http://127.0.0.1:8000/api |
#VITE_SERVER_URL=http://127.0.0.1:8000/api |
||||
#VITE_API_URL=http://127.0.0.1:9000/api |
|
||||
|
VITE_API_URL=http://127.0.0.1:9000/api |
||||
#/booking/bookingItem |
#/booking/bookingItem |
||||
|
@ -0,0 +1,106 @@ |
|||||
|
import request from '@/utils/request'; |
||||
|
import type {ApiResult, PageResult} from '@/api'; |
||||
|
import type {UserOauth, UserOauthParam} from './model'; |
||||
|
import {SERVER_API_URL} from '@/config/setting'; |
||||
|
|
||||
|
/** |
||||
|
* 分页查询第三方用户信息表 |
||||
|
*/ |
||||
|
export async function pageUserOauth(params: UserOauthParam) { |
||||
|
const res = await request.get<ApiResult<PageResult<UserOauth>>>( |
||||
|
SERVER_API_URL + '/system/user-oauth/page', |
||||
|
{ |
||||
|
params |
||||
|
} |
||||
|
); |
||||
|
if (res.data.code === 0) { |
||||
|
return res.data.data; |
||||
|
} |
||||
|
return Promise.reject(new Error(res.data.message)); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询第三方用户信息表列表 |
||||
|
*/ |
||||
|
export async function listUserOauth(params?: UserOauthParam) { |
||||
|
const res = await request.get<ApiResult<UserOauth[]>>( |
||||
|
SERVER_API_URL + '/system/user-oauth', |
||||
|
{ |
||||
|
params |
||||
|
} |
||||
|
); |
||||
|
if (res.data.code === 0 && res.data.data) { |
||||
|
return res.data.data; |
||||
|
} |
||||
|
return Promise.reject(new Error(res.data.message)); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 添加第三方用户信息表 |
||||
|
*/ |
||||
|
export async function addUserOauth(data: UserOauth) { |
||||
|
const res = await request.post<ApiResult<unknown>>( |
||||
|
SERVER_API_URL + '/system/user-oauth', |
||||
|
data |
||||
|
); |
||||
|
if (res.data.code === 0) { |
||||
|
return res.data.message; |
||||
|
} |
||||
|
return Promise.reject(new Error(res.data.message)); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 修改第三方用户信息表 |
||||
|
*/ |
||||
|
export async function updateUserOauth(data: UserOauth) { |
||||
|
const res = await request.put<ApiResult<unknown>>( |
||||
|
SERVER_API_URL + '/system/user-oauth', |
||||
|
data |
||||
|
); |
||||
|
if (res.data.code === 0) { |
||||
|
return res.data.message; |
||||
|
} |
||||
|
return Promise.reject(new Error(res.data.message)); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 删除第三方用户信息表 |
||||
|
*/ |
||||
|
export async function removeUserOauth(id?: number) { |
||||
|
const res = await request.delete<ApiResult<unknown>>( |
||||
|
SERVER_API_URL + '/system/user-oauth/' + id |
||||
|
); |
||||
|
if (res.data.code === 0) { |
||||
|
return res.data.message; |
||||
|
} |
||||
|
return Promise.reject(new Error(res.data.message)); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 批量删除第三方用户信息表 |
||||
|
*/ |
||||
|
export async function removeBatchUserOauth(data: (number | undefined)[]) { |
||||
|
const res = await request.delete<ApiResult<unknown>>( |
||||
|
SERVER_API_URL + '/system/user-oauth/batch', |
||||
|
{ |
||||
|
data |
||||
|
} |
||||
|
); |
||||
|
if (res.data.code === 0) { |
||||
|
return res.data.message; |
||||
|
} |
||||
|
return Promise.reject(new Error(res.data.message)); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 根据id查询第三方用户信息表 |
||||
|
*/ |
||||
|
export async function getUserOauth(id: number) { |
||||
|
const res = await request.get<ApiResult<UserOauth>>( |
||||
|
SERVER_API_URL + '/system/user-oauth/' + id |
||||
|
); |
||||
|
if (res.data.code === 0 && res.data.data) { |
||||
|
return res.data.data; |
||||
|
} |
||||
|
return Promise.reject(new Error(res.data.message)); |
||||
|
} |
@ -0,0 +1,39 @@ |
|||||
|
import type { PageParam } from '@/api'; |
||||
|
|
||||
|
/** |
||||
|
* 第三方用户信息表 |
||||
|
*/ |
||||
|
export interface UserOauth { |
||||
|
// 主键ID
|
||||
|
id?: number; |
||||
|
// 用户ID
|
||||
|
userId?: number; |
||||
|
// 第三方登陆类型(MP-WEIXIN)
|
||||
|
oauthType?: string; |
||||
|
// 第三方用户唯一标识 (uid openid)
|
||||
|
oauthId?: string; |
||||
|
// 微信unionID
|
||||
|
unionid?: string; |
||||
|
// 排序(数字越小越靠前)
|
||||
|
sortNumber?: number; |
||||
|
// 备注
|
||||
|
comments?: string; |
||||
|
// 状态, 0正常, 1冻结
|
||||
|
status?: number; |
||||
|
// 是否删除, 0否, 1是
|
||||
|
deleted?: number; |
||||
|
// 租户id
|
||||
|
tenantId?: number; |
||||
|
// 注册时间
|
||||
|
createTime?: string; |
||||
|
// 修改时间
|
||||
|
updateTime?: string; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 第三方用户信息表搜索条件 |
||||
|
*/ |
||||
|
export interface UserOauthParam extends PageParam { |
||||
|
id?: number; |
||||
|
keywords?: string; |
||||
|
} |
@ -0,0 +1,161 @@ |
|||||
|
<template> |
||||
|
<ele-modal |
||||
|
:width="750" |
||||
|
:visible="visible" |
||||
|
:maskClosable="false" |
||||
|
:title="title" |
||||
|
:footer="null" |
||||
|
:body-style="{ paddingBottom: '28px' }" |
||||
|
@update:visible="updateVisible" |
||||
|
> |
||||
|
<ele-pro-table |
||||
|
ref="tableRef" |
||||
|
row-key="merchantId" |
||||
|
:datasource="datasource" |
||||
|
:columns="columns" |
||||
|
:customRow="customRow" |
||||
|
:pagination="false" |
||||
|
> |
||||
|
<template #toolbar> |
||||
|
<a-input-search |
||||
|
allow-clear |
||||
|
v-model:value="searchText" |
||||
|
placeholder="请输入搜索关键词" |
||||
|
style="width: 200px" |
||||
|
@search="reload" |
||||
|
@pressEnter="reload" |
||||
|
/> |
||||
|
</template> |
||||
|
<template #bodyCell="{ column, record }"> |
||||
|
<template v-if="column.key === 'image'"> |
||||
|
<a-image |
||||
|
v-if="record.image" |
||||
|
:src="record.image" |
||||
|
:preview="false" |
||||
|
:width="45" |
||||
|
/> |
||||
|
</template> |
||||
|
<template v-if="column.key === 'shopType'"> |
||||
|
<a-tag v-if="record.shopType === 10">企业</a-tag> |
||||
|
<a-tag v-if="record.shopType === 20">政府单位</a-tag> |
||||
|
</template> |
||||
|
<template v-if="column.key === 'action'"> |
||||
|
<a-button type="primary" @click="onRadio(record)">选择</a-button> |
||||
|
</template> |
||||
|
</template> |
||||
|
</ele-pro-table> |
||||
|
</ele-modal> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" setup> |
||||
|
import { ref } from 'vue'; |
||||
|
import { |
||||
|
ColumnItem, |
||||
|
DatasourceFunction |
||||
|
} from 'ele-admin-pro/es/ele-pro-table/types'; |
||||
|
import { pageShopMerchant } from '@/api/shop/shopMerchant'; |
||||
|
import { EleProTable } from 'ele-admin-pro'; |
||||
|
import { ShopMerchant, ShopMerchantParam } from '@/api/shop/shopMerchant/model'; |
||||
|
|
||||
|
const props = defineProps<{ |
||||
|
// 弹窗是否打开 |
||||
|
visible: boolean; |
||||
|
// 标题 |
||||
|
title?: string; |
||||
|
// 商户类型 |
||||
|
shopType?: string; |
||||
|
type?: string; |
||||
|
// 修改回显的数据 |
||||
|
data?: ShopMerchant | null; |
||||
|
}>(); |
||||
|
|
||||
|
const emit = defineEmits<{ |
||||
|
(e: 'done', data: ShopMerchant): void; |
||||
|
(e: 'update:visible', visible: boolean): void; |
||||
|
}>(); |
||||
|
|
||||
|
/* 更新visible */ |
||||
|
const updateVisible = (value: boolean) => { |
||||
|
emit('update:visible', value); |
||||
|
}; |
||||
|
|
||||
|
// 搜索内容 |
||||
|
const searchText = ref(null); |
||||
|
|
||||
|
// 表格实例 |
||||
|
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null); |
||||
|
|
||||
|
// 表格配置 |
||||
|
const columns = ref<ColumnItem[]>([ |
||||
|
{ |
||||
|
title: 'LOGO', |
||||
|
dataIndex: 'image', |
||||
|
key: 'image', |
||||
|
align: 'center' |
||||
|
}, |
||||
|
{ |
||||
|
title: '商户名称', |
||||
|
dataIndex: 'merchantName' |
||||
|
}, |
||||
|
{ |
||||
|
title: '商户类型', |
||||
|
dataIndex: 'shopType', |
||||
|
// key: 'shopType' |
||||
|
}, |
||||
|
{ |
||||
|
title: '操作', |
||||
|
key: 'action', |
||||
|
align: 'center' |
||||
|
} |
||||
|
]); |
||||
|
|
||||
|
// 表格数据源 |
||||
|
const datasource: DatasourceFunction = ({ page, limit, where, orders }) => { |
||||
|
where = {}; |
||||
|
// 搜索条件 |
||||
|
if (searchText.value) { |
||||
|
where.keywords = searchText.value; |
||||
|
} |
||||
|
if (props.shopType == 'empty') { |
||||
|
where.emptyType = true; |
||||
|
} else { |
||||
|
where.shopType = props.shopType; |
||||
|
} |
||||
|
if (props.type) { |
||||
|
where.type = props.type; |
||||
|
} |
||||
|
return pageShopMerchant({ |
||||
|
...where, |
||||
|
...orders, |
||||
|
page, |
||||
|
limit |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
/* 搜索 */ |
||||
|
const reload = (where?: ShopMerchantParam) => { |
||||
|
tableRef?.value?.reload({ page: 1, where }); |
||||
|
}; |
||||
|
|
||||
|
const onRadio = (record: ShopMerchant) => { |
||||
|
updateVisible(false); |
||||
|
emit('done', record); |
||||
|
}; |
||||
|
|
||||
|
/* 自定义行属性 */ |
||||
|
const customRow = (record: ShopMerchant) => { |
||||
|
return { |
||||
|
// 行点击事件 |
||||
|
// onClick: () => { |
||||
|
// updateVisible(false); |
||||
|
// emit('done', record); |
||||
|
// }, |
||||
|
// 行双击事件 |
||||
|
onDblclick: () => { |
||||
|
updateVisible(false); |
||||
|
emit('done', record); |
||||
|
} |
||||
|
}; |
||||
|
}; |
||||
|
</script> |
||||
|
<style lang="less"></style> |
@ -0,0 +1,64 @@ |
|||||
|
<template> |
||||
|
<div> |
||||
|
<a-input-group compact> |
||||
|
<a-input |
||||
|
disabled |
||||
|
style="width: calc(100% - 32px)" |
||||
|
v-model:value="content" |
||||
|
:placeholder="placeholder" |
||||
|
/> |
||||
|
<a-button @click="openEdit"> |
||||
|
<template #icon><BulbOutlined class="ele-text-warning" /></template> |
||||
|
</a-button> |
||||
|
</a-input-group> |
||||
|
<!-- 选择弹窗 --> |
||||
|
<SelectData |
||||
|
v-model:visible="showEdit" |
||||
|
:data="current" |
||||
|
:title="placeholder" |
||||
|
:customer-type="customerType" |
||||
|
:shopType="shopType" |
||||
|
@done="onChange" |
||||
|
/> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" setup> |
||||
|
import { BulbOutlined } from '@ant-design/icons-vue'; |
||||
|
import { ref } from 'vue'; |
||||
|
import SelectData from './components/select-data.vue'; |
||||
|
import { ShopMerchant } from '@/api/shop/shopMerchant/model'; |
||||
|
|
||||
|
const props = withDefaults( |
||||
|
defineProps<{ |
||||
|
value?: any; |
||||
|
customerType?: string; |
||||
|
placeholder?: string; |
||||
|
shopType?: string; |
||||
|
}>(), |
||||
|
{ |
||||
|
placeholder: '请选择商户' |
||||
|
} |
||||
|
); |
||||
|
|
||||
|
const emit = defineEmits<{ |
||||
|
(e: 'done', ShopMerchant): void; |
||||
|
(e: 'clear'): void; |
||||
|
}>(); |
||||
|
|
||||
|
// 是否显示编辑弹窗 |
||||
|
const showEdit = ref(false); |
||||
|
const content = ref<string>(props.value) |
||||
|
// 当前编辑数据 |
||||
|
const current = ref<ShopMerchant | null>(null); |
||||
|
|
||||
|
/* 打开编辑弹窗 */ |
||||
|
const openEdit = (row?: ShopMerchant) => { |
||||
|
current.value = row ?? null; |
||||
|
showEdit.value = true; |
||||
|
}; |
||||
|
|
||||
|
const onChange = (row) => { |
||||
|
emit('done', row); |
||||
|
}; |
||||
|
</script> |
@ -0,0 +1,149 @@ |
|||||
|
<!-- 编辑弹窗 --> |
||||
|
<template> |
||||
|
<ele-modal |
||||
|
:width="800" |
||||
|
:visible="visible" |
||||
|
:maskClosable="false" |
||||
|
:maxable="maxable" |
||||
|
:title="isUpdate ? '编辑推送提醒接收员' : '添加推送提醒接收员'" |
||||
|
:body-style="{ paddingBottom: '28px' }" |
||||
|
@update:visible="updateVisible" |
||||
|
@ok="save" |
||||
|
> |
||||
|
<a-form |
||||
|
ref="formRef" |
||||
|
:model="form" |
||||
|
:rules="rules" |
||||
|
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }" |
||||
|
:wrapper-col=" |
||||
|
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' } |
||||
|
" |
||||
|
> |
||||
|
<a-form-item label="openid" name="officeOpenid"> |
||||
|
<a-input |
||||
|
allow-clear |
||||
|
placeholder="openid" |
||||
|
v-model:value="form.officeOpenid" |
||||
|
/> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="备注" name="comments"> |
||||
|
<a-textarea |
||||
|
:rows="4" |
||||
|
:maxlength="200" |
||||
|
placeholder="请输入描述" |
||||
|
v-model:value="form.comments" |
||||
|
/> |
||||
|
</a-form-item> |
||||
|
</a-form> |
||||
|
</ele-modal> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" setup> |
||||
|
import {ref, reactive, watch} from 'vue'; |
||||
|
import {Form, message} from 'ant-design-vue'; |
||||
|
import {assignObject} from 'ele-admin-pro'; |
||||
|
import {addUser, updateUser} from '@/api/system/user'; |
||||
|
import {User} from '@/api/system/user/model'; |
||||
|
import {useThemeStore} from '@/store/modules/theme'; |
||||
|
import {storeToRefs} from 'pinia'; |
||||
|
import {ItemType} from 'ele-admin-pro/es/ele-image-upload/types'; |
||||
|
import {FormInstance} from 'ant-design-vue/es/form'; |
||||
|
|
||||
|
// 是否是修改 |
||||
|
const isUpdate = ref(false); |
||||
|
const useForm = Form.useForm; |
||||
|
// 是否开启响应式布局 |
||||
|
const themeStore = useThemeStore(); |
||||
|
const {styleResponsive} = storeToRefs(themeStore); |
||||
|
|
||||
|
const props = defineProps<{ |
||||
|
// 弹窗是否打开 |
||||
|
visible: boolean; |
||||
|
// 修改回显的数据 |
||||
|
data?: User | null; |
||||
|
}>(); |
||||
|
|
||||
|
const emit = defineEmits<{ |
||||
|
(e: 'done'): void; |
||||
|
(e: 'update:visible', visible: boolean): void; |
||||
|
}>(); |
||||
|
|
||||
|
// 提交状态 |
||||
|
const loading = ref(false); |
||||
|
// 是否显示最大化切换按钮 |
||||
|
const maxable = ref(true); |
||||
|
// 表格选中数据 |
||||
|
const formRef = ref<FormInstance | null>(null); |
||||
|
const images = ref<ItemType[]>([]); |
||||
|
|
||||
|
// 用户信息 |
||||
|
const form = reactive<User>({ |
||||
|
userId: undefined, |
||||
|
officeOpenid: undefined, |
||||
|
}); |
||||
|
|
||||
|
/* 更新visible */ |
||||
|
const updateVisible = (value: boolean) => { |
||||
|
emit('update:visible', value); |
||||
|
}; |
||||
|
|
||||
|
// 表单验证规则 |
||||
|
const rules = reactive({ |
||||
|
officeOpenid: [ |
||||
|
{ |
||||
|
required: true, |
||||
|
message: '请输入openid', |
||||
|
trigger: 'blur' |
||||
|
} |
||||
|
] |
||||
|
}); |
||||
|
|
||||
|
const {resetFields} = useForm(form, rules); |
||||
|
|
||||
|
/* 保存编辑 */ |
||||
|
const save = () => { |
||||
|
if (!formRef.value) { |
||||
|
return; |
||||
|
} |
||||
|
formRef.value |
||||
|
.validate() |
||||
|
.then(() => { |
||||
|
loading.value = true; |
||||
|
const formData = { |
||||
|
...form |
||||
|
}; |
||||
|
const saveOrUpdate = isUpdate.value ? updateUser : addUser; |
||||
|
saveOrUpdate(formData) |
||||
|
.then((msg) => { |
||||
|
loading.value = false; |
||||
|
message.success(msg); |
||||
|
updateVisible(false); |
||||
|
emit('done'); |
||||
|
}) |
||||
|
.catch((e) => { |
||||
|
loading.value = false; |
||||
|
message.error(e.message); |
||||
|
}); |
||||
|
}) |
||||
|
.catch(() => { |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
watch( |
||||
|
() => props.visible, |
||||
|
(visible) => { |
||||
|
if (visible) { |
||||
|
images.value = []; |
||||
|
if (props.data) { |
||||
|
assignObject(form, props.data); |
||||
|
isUpdate.value = true; |
||||
|
} else { |
||||
|
isUpdate.value = false; |
||||
|
} |
||||
|
} else { |
||||
|
resetFields(); |
||||
|
} |
||||
|
}, |
||||
|
{immediate: true} |
||||
|
); |
||||
|
</script> |
@ -0,0 +1,36 @@ |
|||||
|
<!-- 搜索表单 --> |
||||
|
<template> |
||||
|
<a-space :size="10" style="flex-wrap: wrap"> |
||||
|
1、设置角色为【邮政协会/管局】即可出现以下列表,2、关注微信公众号,3、然后<a href="https://mp.weixin.qq.com/" target="_blank">获取openId</a> 并填入表格,即可接受到微信的订阅消息提醒。 |
||||
|
</a-space> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" setup> |
||||
|
import { watch } from 'vue'; |
||||
|
import {UserParam} from "@/api/system/user/model"; |
||||
|
|
||||
|
const props = withDefaults( |
||||
|
defineProps<{ |
||||
|
// 选中的角色 |
||||
|
selection?: []; |
||||
|
}>(), |
||||
|
{} |
||||
|
); |
||||
|
|
||||
|
const emit = defineEmits<{ |
||||
|
(e: 'search', where?: UserParam): void; |
||||
|
(e: 'add'): void; |
||||
|
(e: 'remove'): void; |
||||
|
(e: 'batchMove'): void; |
||||
|
}>(); |
||||
|
|
||||
|
// 新增 |
||||
|
const add = () => { |
||||
|
emit('add'); |
||||
|
}; |
||||
|
|
||||
|
watch( |
||||
|
() => props.selection, |
||||
|
() => {} |
||||
|
); |
||||
|
</script> |
@ -0,0 +1,171 @@ |
|||||
|
<template> |
||||
|
<div class="page"> |
||||
|
<div class="ele-body"> |
||||
|
<a-card :bordered="false" :body-style="{ padding: '16px' }"> |
||||
|
<ele-pro-table |
||||
|
ref="tableRef" |
||||
|
row-key="userOauthId" |
||||
|
:columns="columns" |
||||
|
:datasource="datasource" |
||||
|
:customRow="customRow" |
||||
|
tool-class="ele-toolbar-form" |
||||
|
class="sys-org-table" |
||||
|
> |
||||
|
<template #toolbar> |
||||
|
<search |
||||
|
@search="reload" |
||||
|
:selection="selection" |
||||
|
@add="openEdit" |
||||
|
@remove="removeBatch" |
||||
|
@batchMove="openMove" |
||||
|
/> |
||||
|
</template> |
||||
|
<template #bodyCell="{ column, record }"> |
||||
|
<template v-if="column.key === 'image'"> |
||||
|
<a-image :src="record.image" :width="50" /> |
||||
|
</template> |
||||
|
<template v-if="column.key === 'status'"> |
||||
|
<a-tag v-if="record.status === 0" color="green">显示</a-tag> |
||||
|
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag> |
||||
|
</template> |
||||
|
<template v-if="column.key === 'action'"> |
||||
|
<a-space> |
||||
|
<a @click="openEdit(record)">修改</a> |
||||
|
</a-space> |
||||
|
</template> |
||||
|
</template> |
||||
|
</ele-pro-table> |
||||
|
</a-card> |
||||
|
|
||||
|
<!-- 编辑弹窗 --> |
||||
|
<Edit v-model:visible="showEdit" :data="current" @done="reload" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" setup> |
||||
|
import { ref } from '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 Edit from './components/Edit.vue'; |
||||
|
import {pageUsers} from "@/api/system/user"; |
||||
|
import {User, UserParam} from "@/api/system/user/model"; |
||||
|
|
||||
|
// 表格实例 |
||||
|
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null); |
||||
|
|
||||
|
// 表格选中数据 |
||||
|
const selection = ref<User[]>([]); |
||||
|
// 当前编辑数据 |
||||
|
const current = ref<User | null>(null); |
||||
|
// 是否显示编辑弹窗 |
||||
|
const showEdit = ref(false); |
||||
|
// 是否显示批量移动弹窗 |
||||
|
const showMove = ref(false); |
||||
|
// 加载状态 |
||||
|
const loading = ref(true); |
||||
|
|
||||
|
// 表格数据源 |
||||
|
const datasource: DatasourceFunction = ({ |
||||
|
page, |
||||
|
limit, |
||||
|
where, |
||||
|
orders |
||||
|
}) => { |
||||
|
where.organizationId = 421; |
||||
|
return pageUsers({ |
||||
|
...where, |
||||
|
...orders, |
||||
|
page, |
||||
|
limit |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
// 表格列配置 |
||||
|
const columns = ref<ColumnItem[]>([ |
||||
|
{ |
||||
|
title: '用户ID', |
||||
|
dataIndex: 'userId', |
||||
|
key: 'userId', |
||||
|
align: 'center', |
||||
|
width: 120 |
||||
|
}, |
||||
|
{ |
||||
|
title: '姓名', |
||||
|
dataIndex: 'realName', |
||||
|
key: 'realName', |
||||
|
align: 'center', |
||||
|
width: 170 |
||||
|
}, |
||||
|
{ |
||||
|
title: '手机号', |
||||
|
dataIndex: 'phone', |
||||
|
key: 'phone', |
||||
|
align: 'center', |
||||
|
width: 170 |
||||
|
}, |
||||
|
{ |
||||
|
title: 'openId(微信公众号)', |
||||
|
dataIndex: 'officeOpenid', |
||||
|
key: 'officeOpenid', |
||||
|
align: 'center', |
||||
|
}, |
||||
|
{ |
||||
|
title: '操作', |
||||
|
key: 'action', |
||||
|
width: 180, |
||||
|
fixed: 'right', |
||||
|
align: 'center', |
||||
|
hideInSetting: true |
||||
|
} |
||||
|
]); |
||||
|
|
||||
|
/* 搜索 */ |
||||
|
const reload = (where?: UserParam) => { |
||||
|
selection.value = []; |
||||
|
tableRef?.value?.reload({ where: where }); |
||||
|
}; |
||||
|
|
||||
|
/* 打开编辑弹窗 */ |
||||
|
const openEdit = (row?: User) => { |
||||
|
current.value = row ?? null; |
||||
|
showEdit.value = true; |
||||
|
}; |
||||
|
|
||||
|
/* 打开批量移动弹窗 */ |
||||
|
const openMove = () => { |
||||
|
showMove.value = true; |
||||
|
}; |
||||
|
|
||||
|
/* 查询 */ |
||||
|
const query = () => { |
||||
|
loading.value = true; |
||||
|
}; |
||||
|
|
||||
|
/* 自定义行属性 */ |
||||
|
const customRow = (record: User) => { |
||||
|
return { |
||||
|
// 行点击事件 |
||||
|
onClick: () => { |
||||
|
// console.log(record); |
||||
|
}, |
||||
|
// 行双击事件 |
||||
|
onDblclick: () => { |
||||
|
openEdit(record); |
||||
|
} |
||||
|
}; |
||||
|
}; |
||||
|
query(); |
||||
|
</script> |
||||
|
|
||||
|
<script lang="ts"> |
||||
|
export default { |
||||
|
name: 'User' |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="less" scoped></style> |
@ -0,0 +1,42 @@ |
|||||
|
<!-- 搜索表单 --> |
||||
|
<template> |
||||
|
<a-space :size="10" style="flex-wrap: wrap"> |
||||
|
<a-button type="primary" class="ele-btn-icon" @click="add"> |
||||
|
<template #icon> |
||||
|
<PlusOutlined /> |
||||
|
</template> |
||||
|
<span>添加</span> |
||||
|
</a-button> |
||||
|
</a-space> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" setup> |
||||
|
import { PlusOutlined } from '@ant-design/icons-vue'; |
||||
|
import type { GradeParam } from '@/api/user/grade/model'; |
||||
|
import { watch } from 'vue'; |
||||
|
|
||||
|
const props = withDefaults( |
||||
|
defineProps<{ |
||||
|
// 选中的角色 |
||||
|
selection?: []; |
||||
|
}>(), |
||||
|
{} |
||||
|
); |
||||
|
|
||||
|
const emit = defineEmits<{ |
||||
|
(e: 'search', where?: GradeParam): void; |
||||
|
(e: 'add'): void; |
||||
|
(e: 'remove'): void; |
||||
|
(e: 'batchMove'): void; |
||||
|
}>(); |
||||
|
|
||||
|
// 新增 |
||||
|
const add = () => { |
||||
|
emit('add'); |
||||
|
}; |
||||
|
|
||||
|
watch( |
||||
|
() => props.selection, |
||||
|
() => {} |
||||
|
); |
||||
|
</script> |
@ -0,0 +1,209 @@ |
|||||
|
<!-- 编辑弹窗 --> |
||||
|
<template> |
||||
|
<ele-modal |
||||
|
:width="800" |
||||
|
:visible="visible" |
||||
|
:maskClosable="false" |
||||
|
:maxable="maxable" |
||||
|
:title="isUpdate ? '编辑第三方用户信息表' : '添加第三方用户信息表'" |
||||
|
:body-style="{ paddingBottom: '28px' }" |
||||
|
@update:visible="updateVisible" |
||||
|
@ok="save" |
||||
|
> |
||||
|
<a-form |
||||
|
ref="formRef" |
||||
|
:model="form" |
||||
|
:rules="rules" |
||||
|
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }" |
||||
|
:wrapper-col=" |
||||
|
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' } |
||||
|
" |
||||
|
> |
||||
|
<a-form-item label="用户ID" name="userId"> |
||||
|
<a-input |
||||
|
allow-clear |
||||
|
placeholder="请输入用户ID" |
||||
|
v-model:value="form.userId" |
||||
|
/> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="第三方登陆类型(MP-WEIXIN)" name="oauthType"> |
||||
|
<a-input |
||||
|
allow-clear |
||||
|
placeholder="请输入第三方登陆类型(MP-WEIXIN)" |
||||
|
v-model:value="form.oauthType" |
||||
|
/> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="第三方用户唯一标识 (uid openid)" name="oauthId"> |
||||
|
<a-input |
||||
|
allow-clear |
||||
|
placeholder="请输入第三方用户唯一标识 (uid openid)" |
||||
|
v-model:value="form.oauthId" |
||||
|
/> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="微信unionID" name="unionid"> |
||||
|
<a-input |
||||
|
allow-clear |
||||
|
placeholder="请输入微信unionID" |
||||
|
v-model:value="form.unionid" |
||||
|
/> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="排序(数字越小越靠前)" name="sortNumber"> |
||||
|
<a-input-number |
||||
|
:min="0" |
||||
|
:max="9999" |
||||
|
class="ele-fluid" |
||||
|
placeholder="请输入排序号" |
||||
|
v-model:value="form.sortNumber" |
||||
|
/> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="备注" name="comments"> |
||||
|
<a-textarea |
||||
|
:rows="4" |
||||
|
:maxlength="200" |
||||
|
placeholder="请输入描述" |
||||
|
v-model:value="form.comments" |
||||
|
/> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="状态, 0正常, 1冻结" name="status"> |
||||
|
<a-radio-group v-model:value="form.status"> |
||||
|
<a-radio :value="0">显示</a-radio> |
||||
|
<a-radio :value="1">隐藏</a-radio> |
||||
|
</a-radio-group> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="是否删除, 0否, 1是" name="deleted"> |
||||
|
<a-input |
||||
|
allow-clear |
||||
|
placeholder="请输入是否删除, 0否, 1是" |
||||
|
v-model:value="form.deleted" |
||||
|
/> |
||||
|
</a-form-item> |
||||
|
<a-form-item label="修改时间" name="updateTime"> |
||||
|
<a-input |
||||
|
allow-clear |
||||
|
placeholder="请输入修改时间" |
||||
|
v-model:value="form.updateTime" |
||||
|
/> |
||||
|
</a-form-item> |
||||
|
</a-form> |
||||
|
</ele-modal> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" setup> |
||||
|
import { ref, reactive, watch } from 'vue'; |
||||
|
import { Form, message } from 'ant-design-vue'; |
||||
|
import { assignObject, uuid } from 'ele-admin-pro'; |
||||
|
import { addUserOauth, updateUserOauth } from '@/api/system/userOauth'; |
||||
|
import { UserOauth } from '@/api/system/userOauth/model'; |
||||
|
import { useThemeStore } from '@/store/modules/theme'; |
||||
|
import { storeToRefs } from 'pinia'; |
||||
|
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types'; |
||||
|
import { FormInstance } from 'ant-design-vue/es/form'; |
||||
|
|
||||
|
// 是否是修改 |
||||
|
const isUpdate = ref(false); |
||||
|
const useForm = Form.useForm; |
||||
|
// 是否开启响应式布局 |
||||
|
const themeStore = useThemeStore(); |
||||
|
const { styleResponsive } = storeToRefs(themeStore); |
||||
|
|
||||
|
const props = defineProps<{ |
||||
|
// 弹窗是否打开 |
||||
|
visible: boolean; |
||||
|
// 修改回显的数据 |
||||
|
data?: UserOauth | null; |
||||
|
}>(); |
||||
|
|
||||
|
const emit = defineEmits<{ |
||||
|
(e: 'done'): void; |
||||
|
(e: 'update:visible', visible: boolean): void; |
||||
|
}>(); |
||||
|
|
||||
|
// 提交状态 |
||||
|
const loading = ref(false); |
||||
|
// 是否显示最大化切换按钮 |
||||
|
const maxable = ref(true); |
||||
|
// 表格选中数据 |
||||
|
const formRef = ref<FormInstance | null>(null); |
||||
|
const images = ref<ItemType[]>([]); |
||||
|
|
||||
|
// 用户信息 |
||||
|
const form = reactive<UserOauth>({ |
||||
|
id: undefined, |
||||
|
userId: undefined, |
||||
|
oauthType: undefined, |
||||
|
oauthId: undefined, |
||||
|
unionid: undefined, |
||||
|
deleted: undefined, |
||||
|
tenantId: undefined, |
||||
|
createTime: undefined, |
||||
|
updateTime: undefined, |
||||
|
status: 0, |
||||
|
comments: '', |
||||
|
sortNumber: 100 |
||||
|
}); |
||||
|
|
||||
|
/* 更新visible */ |
||||
|
const updateVisible = (value: boolean) => { |
||||
|
emit('update:visible', value); |
||||
|
}; |
||||
|
|
||||
|
// 表单验证规则 |
||||
|
const rules = reactive({ |
||||
|
userOauthName: [ |
||||
|
{ |
||||
|
required: true, |
||||
|
type: 'string', |
||||
|
message: '请填写第三方用户信息表名称', |
||||
|
trigger: 'blur' |
||||
|
} |
||||
|
] |
||||
|
}); |
||||
|
|
||||
|
const { resetFields } = useForm(form, rules); |
||||
|
|
||||
|
/* 保存编辑 */ |
||||
|
const save = () => { |
||||
|
if (!formRef.value) { |
||||
|
return; |
||||
|
} |
||||
|
formRef.value |
||||
|
.validate() |
||||
|
.then(() => { |
||||
|
loading.value = true; |
||||
|
const formData = { |
||||
|
...form |
||||
|
}; |
||||
|
const saveOrUpdate = isUpdate.value ? updateUserOauth : addUserOauth; |
||||
|
saveOrUpdate(formData) |
||||
|
.then((msg) => { |
||||
|
loading.value = false; |
||||
|
message.success(msg); |
||||
|
updateVisible(false); |
||||
|
emit('done'); |
||||
|
}) |
||||
|
.catch((e) => { |
||||
|
loading.value = false; |
||||
|
message.error(e.message); |
||||
|
}); |
||||
|
}) |
||||
|
.catch(() => {}); |
||||
|
}; |
||||
|
|
||||
|
watch( |
||||
|
() => props.visible, |
||||
|
(visible) => { |
||||
|
if (visible) { |
||||
|
images.value = []; |
||||
|
if (props.data) { |
||||
|
assignObject(form, props.data); |
||||
|
isUpdate.value = true; |
||||
|
} else { |
||||
|
isUpdate.value = false; |
||||
|
} |
||||
|
} else { |
||||
|
resetFields(); |
||||
|
} |
||||
|
}, |
||||
|
{ immediate: true } |
||||
|
); |
||||
|
</script> |
@ -0,0 +1,223 @@ |
|||||
|
<template> |
||||
|
<div class="page"> |
||||
|
<div class="ele-body"> |
||||
|
<a-card :bordered="false" :body-style="{ padding: '16px' }"> |
||||
|
<ele-pro-table |
||||
|
ref="tableRef" |
||||
|
row-key="userOauthId" |
||||
|
:columns="columns" |
||||
|
:datasource="datasource" |
||||
|
:customRow="customRow" |
||||
|
tool-class="ele-toolbar-form" |
||||
|
class="sys-org-table" |
||||
|
> |
||||
|
<template #toolbar> |
||||
|
<search |
||||
|
@search="reload" |
||||
|
:selection="selection" |
||||
|
@add="openEdit" |
||||
|
@remove="removeBatch" |
||||
|
@batchMove="openMove" |
||||
|
/> |
||||
|
</template> |
||||
|
<template #bodyCell="{ column, record }"> |
||||
|
<template v-if="column.key === 'image'"> |
||||
|
<a-image :src="record.image" :width="50" /> |
||||
|
</template> |
||||
|
<template v-if="column.key === 'status'"> |
||||
|
<a-tag v-if="record.status === 0" color="green">显示</a-tag> |
||||
|
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag> |
||||
|
</template> |
||||
|
<template v-if="column.key === 'action'"> |
||||
|
<a-space> |
||||
|
<a @click="openEdit(record)">修改</a> |
||||
|
<a-divider type="vertical" /> |
||||
|
<a-popconfirm |
||||
|
title="确定要删除此记录吗?" |
||||
|
@confirm="remove(record)" |
||||
|
> |
||||
|
<a class="ele-text-danger">删除</a> |
||||
|
</a-popconfirm> |
||||
|
</a-space> |
||||
|
</template> |
||||
|
</template> |
||||
|
</ele-pro-table> |
||||
|
</a-card> |
||||
|
|
||||
|
<!-- 编辑弹窗 --> |
||||
|
<UserOauthEdit v-model:visible="showEdit" :data="current" @done="reload" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" setup> |
||||
|
import { createVNode, ref } from 'vue'; |
||||
|
import { message, Modal } from 'ant-design-vue'; |
||||
|
import { ExclamationCircleOutlined } 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 UserOauthEdit from './components/userOauthEdit.vue'; |
||||
|
import { pageUserOauth, removeUserOauth, removeBatchUserOauth } from '@/api/system/userOauth'; |
||||
|
import type { UserOauth, UserOauthParam } from '@/api/system/userOauth/model'; |
||||
|
|
||||
|
// 表格实例 |
||||
|
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null); |
||||
|
|
||||
|
// 表格选中数据 |
||||
|
const selection = ref<UserOauth[]>([]); |
||||
|
// 当前编辑数据 |
||||
|
const current = ref<UserOauth | null>(null); |
||||
|
// 是否显示编辑弹窗 |
||||
|
const showEdit = ref(false); |
||||
|
// 是否显示批量移动弹窗 |
||||
|
const showMove = ref(false); |
||||
|
// 加载状态 |
||||
|
const loading = ref(true); |
||||
|
|
||||
|
// 表格数据源 |
||||
|
const datasource: DatasourceFunction = ({ |
||||
|
page, |
||||
|
limit, |
||||
|
where, |
||||
|
orders, |
||||
|
filters |
||||
|
}) => { |
||||
|
if (filters) { |
||||
|
where.status = filters.status; |
||||
|
} |
||||
|
where.tenantId = 10519; |
||||
|
return pageUserOauth({ |
||||
|
...where, |
||||
|
...orders, |
||||
|
page, |
||||
|
limit |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
// 表格列配置 |
||||
|
const columns = ref<ColumnItem[]>([ |
||||
|
{ |
||||
|
title: '用户ID', |
||||
|
dataIndex: 'userId', |
||||
|
key: 'userId', |
||||
|
align: 'center', |
||||
|
}, |
||||
|
{ |
||||
|
title: '渠道', |
||||
|
dataIndex: 'oauthType', |
||||
|
key: 'oauthType', |
||||
|
align: 'center', |
||||
|
}, |
||||
|
{ |
||||
|
title: 'oauthId', |
||||
|
dataIndex: 'oauthId', |
||||
|
key: 'oauthId', |
||||
|
align: 'center', |
||||
|
}, |
||||
|
{ |
||||
|
title: 'unionid', |
||||
|
dataIndex: 'unionid', |
||||
|
key: 'unionid', |
||||
|
align: 'center', |
||||
|
}, |
||||
|
{ |
||||
|
title: '操作', |
||||
|
key: 'action', |
||||
|
width: 180, |
||||
|
fixed: 'right', |
||||
|
align: 'center', |
||||
|
hideInSetting: true |
||||
|
} |
||||
|
]); |
||||
|
|
||||
|
/* 搜索 */ |
||||
|
const reload = (where?: UserOauthParam) => { |
||||
|
selection.value = []; |
||||
|
tableRef?.value?.reload({ where: where }); |
||||
|
}; |
||||
|
|
||||
|
/* 打开编辑弹窗 */ |
||||
|
const openEdit = (row?: UserOauth) => { |
||||
|
current.value = row ?? null; |
||||
|
showEdit.value = true; |
||||
|
}; |
||||
|
|
||||
|
/* 打开批量移动弹窗 */ |
||||
|
const openMove = () => { |
||||
|
showMove.value = true; |
||||
|
}; |
||||
|
|
||||
|
/* 删除单个 */ |
||||
|
const remove = (row: UserOauth) => { |
||||
|
const hide = message.loading('请求中..', 0); |
||||
|
removeUserOauth(row.userOauthId) |
||||
|
.then((msg) => { |
||||
|
hide(); |
||||
|
message.success(msg); |
||||
|
reload(); |
||||
|
}) |
||||
|
.catch((e) => { |
||||
|
hide(); |
||||
|
message.error(e.message); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
/* 批量删除 */ |
||||
|
const removeBatch = () => { |
||||
|
if (!selection.value.length) { |
||||
|
message.error('请至少选择一条数据'); |
||||
|
return; |
||||
|
} |
||||
|
Modal.confirm({ |
||||
|
title: '提示', |
||||
|
content: '确定要删除选中的记录吗?', |
||||
|
icon: createVNode(ExclamationCircleOutlined), |
||||
|
maskClosable: true, |
||||
|
onOk: () => { |
||||
|
const hide = message.loading('请求中..', 0); |
||||
|
removeBatchUserOauth(selection.value.map((d) => d.userOauthId)) |
||||
|
.then((msg) => { |
||||
|
hide(); |
||||
|
message.success(msg); |
||||
|
reload(); |
||||
|
}) |
||||
|
.catch((e) => { |
||||
|
hide(); |
||||
|
message.error(e.message); |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
/* 查询 */ |
||||
|
const query = () => { |
||||
|
loading.value = true; |
||||
|
}; |
||||
|
|
||||
|
/* 自定义行属性 */ |
||||
|
const customRow = (record: UserOauth) => { |
||||
|
return { |
||||
|
// 行点击事件 |
||||
|
onClick: () => { |
||||
|
// console.log(record); |
||||
|
}, |
||||
|
// 行双击事件 |
||||
|
onDblclick: () => { |
||||
|
openEdit(record); |
||||
|
} |
||||
|
}; |
||||
|
}; |
||||
|
query(); |
||||
|
</script> |
||||
|
|
||||
|
<script lang="ts"> |
||||
|
export default { |
||||
|
name: 'UserOauth' |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="less" scoped></style> |
Loading…
Reference in new issue