api接口文档支持用户权限控制
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
import apiClient from './request/zyplayer.js'
|
||||
|
||||
export const zyplayerApi = {
|
||||
|
||||
searchUserList: data => apiClient({url: '/user/info/search', method: 'post', data: data}),
|
||||
|
||||
getSelfUserInfo: data => apiClient({url: '/user/info/selfInfo', method: 'post', data: data}),
|
||||
userLogout: data => apiClient({url: '/logout', method: 'post', data: data}),
|
||||
systemUpgradeInfo: data => apiClient({url: '/system/info/upgrade', method: 'post', data: data}),
|
||||
@@ -15,5 +18,9 @@ export const zyplayerApi = {
|
||||
requestUrl: data => apiClient({url: '/doc-api/proxy/request', method: 'post', data: data}),
|
||||
apiShareDocDetail: data => apiClient({url: '/doc-api/share/detail', method: 'post', data: data}),
|
||||
apiShareDocApisDetail: data => apiClient({url: '/doc-api/share/apis/detail', method: 'post', data: data}),
|
||||
|
||||
docAuthList: data => apiClient({url: '/doc-api/doc/auth/list', method: 'post', data: data}),
|
||||
docAuthAssign: data => apiClient({url: '/doc-api/doc/auth/assign', method: 'post', data: data}),
|
||||
docAuthDelete: data => apiClient({url: '/doc-api/doc/auth/delete', method: 'post', data: data}),
|
||||
};
|
||||
|
||||
|
||||
@@ -63,7 +63,6 @@ export function analysisOpenApiData(swagger) {
|
||||
* @param tagPathMap 分组信息{分组名: {url: {...接口信息, path: '', url: '', method: ''}}}
|
||||
* @param keywords 过滤关键字
|
||||
* @param metaInfo 接口元信息,点击时放入URL的参数
|
||||
* @returns {{children: [], title: (*|string), key: string}[]}
|
||||
*/
|
||||
export function getTreeDataForTag(swagger, tagPathMap, keywords, metaInfo) {
|
||||
let treeData = [];
|
||||
@@ -116,7 +115,7 @@ export function getTreeDataForTag(swagger, tagPathMap, keywords, metaInfo) {
|
||||
return [
|
||||
{
|
||||
key: 'main',
|
||||
title: swagger.info.title || 'Swagger接口文档',
|
||||
title: swagger.info.title || 'OpenApi接口文档',
|
||||
children: treeData
|
||||
}
|
||||
];
|
||||
|
||||
@@ -63,7 +63,6 @@ export function analysisSwaggerData(swagger) {
|
||||
* @param tagPathMap 分组信息{分组名: {url: {...接口信息, path: '', url: '', method: ''}}}
|
||||
* @param keywords 过滤关键字
|
||||
* @param metaInfo 接口元信息,点击时放入URL的参数
|
||||
* @returns {{children: [], title: (*|string), key: string}[]}
|
||||
*/
|
||||
export function getTreeDataForTag(swagger, tagPathMap, keywords, metaInfo) {
|
||||
let treeData = [];
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
<template>
|
||||
<a-directory-tree :showIcon="false" :tree-data="treeData" v-model:expandedKeys="expandedKeys" @select="docChecked">
|
||||
<template #title="{ title, isLeaf, method, children, key }">
|
||||
<template v-if="key === 'info'">
|
||||
<file-text-outlined style="margin-right: 3px;"/>
|
||||
</template>
|
||||
<template v-if="isLeaf">
|
||||
<a-tag color="pink" v-if="method === 'get'">get</a-tag>
|
||||
<a-tag color="red" v-else-if="method === 'post'">post</a-tag>
|
||||
@@ -22,10 +25,12 @@
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
import {useStore} from 'vuex';
|
||||
import { message } from 'ant-design-vue';
|
||||
import {InfoCircleOutlined, FileTextOutlined} from '@ant-design/icons-vue';
|
||||
import {zyplayerApi} from '../../../api'
|
||||
import {analysisOpenApiData, getTreeDataForTag} from '../../../assets/core/OpenApiTreeAnalysis.js'
|
||||
|
||||
export default {
|
||||
components: {InfoCircleOutlined, FileTextOutlined},
|
||||
setup() {
|
||||
const store = useStore();
|
||||
const route = useRoute();
|
||||
@@ -39,7 +44,7 @@
|
||||
let searchKeywords = ref('');
|
||||
|
||||
const docChecked = (val, node) => {
|
||||
if (node.node.key === 'main') {
|
||||
if (node.node.key === 'info') {
|
||||
router.push({path: '/openapi/info'});
|
||||
} else if (node.node.isLeaf) {
|
||||
let dataRef = node.node.dataRef;
|
||||
@@ -64,17 +69,12 @@
|
||||
tagPathMap.value = treeData.tagPathMap;
|
||||
loadTreeData();
|
||||
callback();
|
||||
setTimeout(() => {
|
||||
let isViewPage = (route.path === '/openapi/view' && route.query.id);
|
||||
if (!isViewPage) {
|
||||
router.push({path: '/openapi/info'});
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
};
|
||||
const loadTreeData = async () => {
|
||||
let metaInfo = {id: choiceDocId.value};
|
||||
treeData.value = getTreeDataForTag(openApiDoc.value, tagPathMap.value, searchKeywords.value, metaInfo);
|
||||
treeData.value.unshift({key: 'info', title: '文档说明信息', isLeaf: true});
|
||||
await nextTick();
|
||||
expandedKeys.value = ['main'];
|
||||
};
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
<template>
|
||||
<a-directory-tree :showIcon="false" :tree-data="treeData" v-model:expandedKeys="expandedKeys" @select="docChecked">
|
||||
<template #title="{ title, isLeaf, method, children, key }">
|
||||
<template v-if="key === 'info'">
|
||||
<file-text-outlined style="margin-right: 3px;"/>
|
||||
</template>
|
||||
<template v-if="isLeaf">
|
||||
<a-tag color="pink" v-if="method === 'get'">get</a-tag>
|
||||
<a-tag color="red" v-else-if="method === 'post'">post</a-tag>
|
||||
@@ -22,10 +25,12 @@
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
import {useStore} from 'vuex';
|
||||
import { message } from 'ant-design-vue';
|
||||
import {InfoCircleOutlined, FileTextOutlined} from '@ant-design/icons-vue';
|
||||
import {zyplayerApi} from '../../../api'
|
||||
import {analysisSwaggerData, getTreeDataForTag} from '../../../assets/core/SwaggerTreeAnalysis.js'
|
||||
|
||||
export default {
|
||||
components: {InfoCircleOutlined, FileTextOutlined},
|
||||
setup() {
|
||||
const store = useStore();
|
||||
const route = useRoute();
|
||||
@@ -39,7 +44,7 @@
|
||||
let searchKeywords = ref('');
|
||||
|
||||
const docChecked = (val, node) => {
|
||||
if (node.node.key === 'main') {
|
||||
if (node.node.key === 'info') {
|
||||
router.push({path: '/swagger/info'});
|
||||
} else if (node.node.isLeaf) {
|
||||
let dataRef = node.node.dataRef;
|
||||
@@ -64,17 +69,12 @@
|
||||
tagPathMap.value = treeData.tagPathMap;
|
||||
loadTreeData();
|
||||
callback(true);
|
||||
setTimeout(() => {
|
||||
let isViewPage = (route.path === '/swagger/view' && route.query.id);
|
||||
if (!isViewPage) {
|
||||
router.push({path: '/swagger/info'});
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
};
|
||||
const loadTreeData = async () => {
|
||||
let metaInfo = {id: choiceDocId.value};
|
||||
treeData.value = getTreeDataForTag(swaggerDoc.value, tagPathMap.value, searchKeywords.value, metaInfo);
|
||||
treeData.value.unshift({key: 'info', title: '文档说明信息', isLeaf: true});
|
||||
await nextTick();
|
||||
expandedKeys.value = ['main'];
|
||||
};
|
||||
|
||||
@@ -1,329 +1,33 @@
|
||||
<template>
|
||||
<a-form layout="inline" style="margin-bottom: 20px;">
|
||||
<a-form-item label="文档类型">
|
||||
<a-select placeholder="请选择文档类型" v-model:value="searchParam.docType" style="width: 150px;">
|
||||
<a-select-option value="">全部</a-select-option>
|
||||
<a-select-option :value="1">URL添加</a-select-option>
|
||||
<a-select-option :value="2">JSON内容</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="开放访问">
|
||||
<a-select placeholder="请选择开放访问" v-model:value="searchParam.openVisit" style="width: 150px;">
|
||||
<a-select-option value="">全部</a-select-option>
|
||||
<a-select-option :value="0">否</a-select-option>
|
||||
<a-select-option :value="1">是</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态">
|
||||
<a-select placeholder="请选择状态" v-model:value="searchParam.docStatus" style="width: 150px;">
|
||||
<a-select-option value="">全部</a-select-option>
|
||||
<a-select-option :value="1">启用</a-select-option>
|
||||
<a-select-option :value="2">禁用</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-button @click="searchDocList" type="primary">查询</a-button>
|
||||
<a-button @click="openNewDoc" :style="{ marginLeft: '8px' }">新建</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<a-table :dataSource="docList" :columns="docListColumns" size="middle"
|
||||
:loading="docListLoading" :pagination="pagination"
|
||||
@change="handleTableChange"
|
||||
:scroll="{ x: 1400, y: 'calc(100vh - 300px)' }">
|
||||
<template #bodyCell="{ column, text, record }">
|
||||
<template v-if="column.dataIndex === 'operation'">
|
||||
<a-button size="small" type="link" @click="editDoc(record)">编辑</a-button>
|
||||
<a-popconfirm title="确定要删除吗?" @confirm="deleteDoc(record)">
|
||||
<a-button size="small" type="link" danger>删除</a-button>
|
||||
</a-popconfirm>
|
||||
<a-dropdown :trigger="['click']">
|
||||
<template #overlay>
|
||||
<a-menu @click="handleActionMenuClick($event, record)">
|
||||
<a-menu-item key="shareView"><link-outlined /> 查看开放文档</a-menu-item>
|
||||
<a-menu-item key="shareInstruction"><edit-outlined /> 编辑开放文档说明</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button type="link" size="small">更多<DownOutlined /></a-button>
|
||||
</a-dropdown>
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'docType'">
|
||||
<a-tag color="red" v-if="text === 1">Swagger URL</a-tag>
|
||||
<a-tag color="blue" v-else-if="text === 2">Swagger JSON</a-tag>
|
||||
<a-tag color="green" v-else-if="text === 4">OpenApi JSON</a-tag>
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'openVisit'">
|
||||
<a-tag color="pink" v-if="text === 0">未开放</a-tag>
|
||||
<a-tag color="green" v-else-if="text === 1">已开放</a-tag>
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'docStatus'">
|
||||
<a-tag color="green" v-if="text === 1">启用</a-tag>
|
||||
<a-tag color="pink" v-else-if="text === 2">禁用</a-tag>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
<a-modal v-model:visible="newDocVisible" :title="docEdit.isNew?'新增文档':'编辑文档'" @ok="handleNewDocOk" :width="800">
|
||||
<a-form layout="horizontal" ref="newDocFormRef" :rules="newDocRules" :model="docEdit" :label-col="{span: 4}" :wrapper-col="{span: 20}">
|
||||
<a-form-item label="文档名称" required name="name">
|
||||
<a-input placeholder="请输入文档名称" v-model:value="docEdit.name"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="文档类型" required name="docType">
|
||||
<a-radio-group v-model:value="docEdit.docType">
|
||||
<a-radio :value="1">Swagger URL</a-radio>
|
||||
<a-radio :value="2">Swagger JSON</a-radio>
|
||||
<a-radio :value="3">OpenApi URL</a-radio>
|
||||
<a-radio :value="4">OpenApi JSON</a-radio>
|
||||
<a-radio :value="5" disabled>自建API</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="文档地址" required name="docUrl" v-if="docEdit.docType === 1">
|
||||
<a-input placeholder="请输入文档地址URL" v-model:value="docEdit.docUrl"></a-input>
|
||||
<template #extra>
|
||||
查看文档地址
|
||||
<a-popover title="文档地址支持以下任一格式">
|
||||
<template #content>
|
||||
<p>格式一:http://doc.zyplayer.com/v2/api-docs</p>
|
||||
<p>格式二:http://doc.zyplayer.com/swagger-resources</p>
|
||||
<p>格式三:http://doc.zyplayer.com/swagger-ui.html</p>
|
||||
</template>
|
||||
<a>示例</a>
|
||||
</a-popover>
|
||||
</template>
|
||||
</a-form-item>
|
||||
<a-form-item label="文档内容" required name="jsonContent" v-else-if="docEdit.docType === 2">
|
||||
<!-- textarea在内容很多的时候(>300KB)会卡顿,ace不会-->
|
||||
<ace-editor v-model:value="docEdit.jsonContent" lang="json" theme="monokai" width="100%" height="100" :options="aceEditorConfig"></ace-editor>
|
||||
<!-- <a-textarea placeholder="请输入JSON格式的Swagger文档内容" v-model:value="docEdit.jsonContent" :auto-size="{ minRows: 5, maxRows: 10 }"></a-textarea>-->
|
||||
<template #extra>
|
||||
查看文档内容
|
||||
<a-popover title="文档内容说明">
|
||||
<template #content>
|
||||
<div>支持以下格式的Swagger文档内容输入,其中 {"swagger": "2.0"} 为必要属性</div>
|
||||
<div v-highlight>
|
||||
<pre><code class="lang-json">{{swaggerDocDemo}}</code></pre>
|
||||
</div>
|
||||
</template>
|
||||
<a>说明</a>
|
||||
</a-popover>
|
||||
</template>
|
||||
</a-form-item>
|
||||
<a-form-item label="文档地址" required name="docUrl" v-if="docEdit.docType === 3">
|
||||
<a-input placeholder="请输入文档地址URL" v-model:value="docEdit.docUrl"></a-input>
|
||||
<template #extra>
|
||||
查看文档地址
|
||||
<a-popover title="文档地址支持以下任一格式">
|
||||
<template #content>
|
||||
<p>格式一:http://doc.zyplayer.com/v3/api-docs</p>
|
||||
</template>
|
||||
<a>示例</a>
|
||||
</a-popover>
|
||||
</template>
|
||||
</a-form-item>
|
||||
<a-form-item label="文档内容" required name="jsonContent" v-else-if="docEdit.docType === 4">
|
||||
<ace-editor v-model:value="docEdit.jsonContent" lang="json" theme="monokai" width="100%" height="100" :options="aceEditorConfig"></ace-editor>
|
||||
<!-- <a-textarea placeholder="请输入JSON格式的OpenApi文档内容" v-model:value="docEdit.jsonContent" :auto-size="{ minRows: 5, maxRows: 10 }"></a-textarea>-->
|
||||
<template #extra>
|
||||
查看文档内容
|
||||
<a-popover title="文档内容说明">
|
||||
<template #content>
|
||||
<div>支持以下格式的OpenApi文档内容输入,其中 {"openapi": "3.x.x"} 为必要属性</div>
|
||||
<div v-highlight>
|
||||
<pre><code class="lang-json">{{openApiDocDemo}}</code></pre>
|
||||
</div>
|
||||
</template>
|
||||
<a>说明</a>
|
||||
</a-popover>
|
||||
</template>
|
||||
</a-form-item>
|
||||
<a-form-item label="目标域名" name="rewriteDomain">
|
||||
<a-input placeholder="请输入目标域名" v-model:value="docEdit.rewriteDomain"></a-input>
|
||||
<template #extra>
|
||||
目标域名
|
||||
<a-popover title="目标域名说明">
|
||||
<template #content>
|
||||
<p>在文档的在线调试界面,访问的域名可以初始为此处录入的域名,而非文档本身的域名地址</p>
|
||||
<p>可便于不同环境间的接口测试,例:http://doc.zyplayer.com</p>
|
||||
</template>
|
||||
<a>说明</a>
|
||||
</a-popover>
|
||||
</template>
|
||||
</a-form-item>
|
||||
<a-form-item label="开放访问" required name="openVisit">
|
||||
<a-radio-group v-model:value="docEdit.openVisit">
|
||||
<a-radio :value="0">否</a-radio>
|
||||
<a-radio :value="1">开放访问</a-radio>
|
||||
</a-radio-group>
|
||||
<template #extra>
|
||||
开放访问后无需登录即可通过<a @click="openShareViewWindow(docEdit)">开放文档URL</a>访问该文档信息
|
||||
</template>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态" required name="docStatus">
|
||||
<a-radio-group v-model:value="docEdit.docStatus">
|
||||
<a-radio :value="1">启用</a-radio>
|
||||
<a-radio :value="2">禁用</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
<EditShareInstruction ref="instruction"></EditShareInstruction>
|
||||
<DocManageList v-if="showView === 'list'" @showMembers="showMembers"></DocManageList>
|
||||
<div v-else>
|
||||
<DocManageMembers v-if="showView === 'members'" @showDocList="showDocList" :doc="docInfo"></DocManageMembers>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { toRefs, ref, reactive, onMounted } from 'vue';
|
||||
import {zyplayerApi} from '../../api';
|
||||
import {useStore} from 'vuex';
|
||||
import aceEditor from "../../assets/ace-editor";
|
||||
import EditShareInstruction from "./components/EditShareInstruction.vue";
|
||||
import {getZyplayerApiBaseUrl} from "../../api/request/utils";
|
||||
import {DownOutlined, LinkOutlined, EditOutlined} from '@ant-design/icons-vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import DocManageList from "./DocManageList.vue";
|
||||
import DocManageMembers from "./DocManageMembers.vue";
|
||||
|
||||
export default {
|
||||
components: {aceEditor, EditShareInstruction, DownOutlined, LinkOutlined, EditOutlined},
|
||||
setup() {
|
||||
const store = useStore();
|
||||
let docList = ref([]);
|
||||
let docListLoading = ref(false);
|
||||
let searchParam = ref({docType: '', openVisit: '', docStatus: '', pageNum: 1, pageSize: 20});
|
||||
let pagination = ref({
|
||||
pageSize: 20,
|
||||
pageNum: 1,
|
||||
total: 0,
|
||||
showSizeChanger: true,
|
||||
pageSizeOptions: ['20', '50', '100'],
|
||||
showTotal: total => `共${total}条`
|
||||
});
|
||||
const handleTableChange = (paginationNew, filters, sorter) => {
|
||||
pagination.value.pageNum = paginationNew.current;
|
||||
pagination.value.pageSize = paginationNew.pageSize;
|
||||
searchParam.value.pageNum = paginationNew.current;
|
||||
searchParam.value.pageSize = paginationNew.pageSize;
|
||||
searchDocList();
|
||||
};
|
||||
const searchDocList = async () => {
|
||||
docListLoading.value = true;
|
||||
zyplayerApi.apiDocList(searchParam.value).then(res => {
|
||||
setTimeout(() => docListLoading.value = false, 500);
|
||||
docList.value = res.data || [];
|
||||
pagination.value.total = res.total || 0;
|
||||
});
|
||||
};
|
||||
let docEdit = ref({});
|
||||
let newDocFormRef = ref();
|
||||
let newDocVisible = ref(false);
|
||||
const handleNewDocOk = async () => {
|
||||
newDocFormRef.value.validate().then(() => {
|
||||
zyplayerApi.apiDocAdd(docEdit.value).then(res => {
|
||||
searchDocList();
|
||||
newDocVisible.value = false;
|
||||
store.commit('addDocChangedNum');
|
||||
});
|
||||
}).catch(error => {
|
||||
console.log('error', error);
|
||||
});
|
||||
};
|
||||
const openNewDoc = async () => {
|
||||
newDocVisible.value = true;
|
||||
docEdit.value = {
|
||||
docType: 1, openVisit: 0, docStatus: 1, isNew: 1
|
||||
};
|
||||
};
|
||||
const editDoc = (record) => {
|
||||
zyplayerApi.apiDocDetail({id: record.id}).then(res => {
|
||||
docEdit.value = res.data;
|
||||
newDocVisible.value = true;
|
||||
});
|
||||
};
|
||||
const updateDoc = async (id, docStatus, yn) => {
|
||||
zyplayerApi.apiDocUpdate({id, docStatus, yn}).then(res => {
|
||||
searchDocList();
|
||||
store.commit('addDocChangedNum');
|
||||
});
|
||||
};
|
||||
const deleteDoc = async (row) => updateDoc(row.id, null, 0);
|
||||
// 打开开放文档新窗口
|
||||
const openShareViewWindow = record => {
|
||||
if (!record.shareUuid) {
|
||||
message.warning('请先保存文档后再试');
|
||||
} else if (record.openVisit !== 1) {
|
||||
message.warning('该文档尚未开启开放访问功能,请在编辑页选择开放后再试');
|
||||
} else {
|
||||
window.open(getZyplayerApiBaseUrl() + '/doc-api#/share/home?uuid=' + record.shareUuid);
|
||||
}
|
||||
};
|
||||
const handleActionMenuClick = (item, record) => {
|
||||
if (item.key === 'shareView') {
|
||||
openShareViewWindow(record);
|
||||
} else if (item.key === 'shareInstruction') {
|
||||
instruction.value.editDoc(record.id);
|
||||
}
|
||||
}
|
||||
let instruction = ref();
|
||||
onMounted(() => {
|
||||
searchDocList();
|
||||
});
|
||||
components: {DocManageList, DocManageMembers},
|
||||
setup() {
|
||||
let showView = ref('list');
|
||||
let docInfo = ref({});
|
||||
const showMembers = (doc) => {
|
||||
docInfo.value = doc;
|
||||
showView.value = 'members';
|
||||
};
|
||||
const showDocList = () => {
|
||||
showView.value = 'list';
|
||||
};
|
||||
return {
|
||||
searchParam,
|
||||
docList,
|
||||
docListLoading,
|
||||
newDocVisible,
|
||||
docEdit,
|
||||
newDocFormRef,
|
||||
searchDocList,
|
||||
openNewDoc,
|
||||
handleNewDocOk,
|
||||
deleteDoc,
|
||||
editDoc,
|
||||
handleTableChange,
|
||||
openShareViewWindow,
|
||||
handleActionMenuClick,
|
||||
pagination,
|
||||
instruction,
|
||||
newDocRules: {
|
||||
name: [{required: true, message: '请输入文档名称', trigger: 'change'}],
|
||||
docUrl: [{required: true, message: '请输入文档地址', trigger: 'change'}],
|
||||
jsonContent: [{required: true, message: '请输入JSON格式的swagger文档内容', trigger: 'change'}],
|
||||
docType: [{type: 'number', required: true, message: '请选择文档类型', trigger: 'change'}],
|
||||
openVisit: [{type: 'number', required: true, message: '请选择是否开放访问', trigger: 'change'}],
|
||||
docStatus: [{type: 'number', required: true, message: '请选择文档状态', trigger: 'change'}],
|
||||
},
|
||||
docListColumns: [
|
||||
{title: 'ID', dataIndex: 'id', width: 70},
|
||||
{title: '文档名称', dataIndex: 'name', width: 250},
|
||||
{title: '文档类型', dataIndex: 'docType', width: 120},
|
||||
{title: '开放访问', dataIndex: 'openVisit', width: 90},
|
||||
{title: '状态', dataIndex: 'docStatus', width: 90},
|
||||
{title: '文档地址', dataIndex: 'docUrl'},
|
||||
{title: '目标域名', dataIndex: 'rewriteDomain', width: 250},
|
||||
{title: '操作', dataIndex: 'operation', fixed: 'right', width: 200},
|
||||
],
|
||||
aceEditorConfig: {
|
||||
wrap: true,
|
||||
autoScrollEditorIntoView: true,
|
||||
enableBasicAutocompletion: true,
|
||||
enableSnippets: true,
|
||||
enableLiveAutocompletion: true,
|
||||
minLines: 10,
|
||||
maxLines: 15,
|
||||
},
|
||||
swaggerDocDemo:
|
||||
'{\n'
|
||||
+ ' "swagger": "2.0",\n'
|
||||
+ ' "info": {},\n'
|
||||
+ ' "host": "doc.zyplayer.com",\n'
|
||||
+ ' "basePath":"/",\n'
|
||||
+ ' "tags": [],\n'
|
||||
+ ' "paths": {},\n'
|
||||
+ ' "definitions": {}\n'
|
||||
+ '}',
|
||||
openApiDocDemo:
|
||||
'{\n'
|
||||
+ ' "openapi": "3.0.3",\n'
|
||||
+ ' "components": {}\n'
|
||||
+ ' "servers": [],\n'
|
||||
+ ' "paths": {},\n'
|
||||
+ ' "info": {},\n'
|
||||
+ '}',
|
||||
};
|
||||
showView,
|
||||
docInfo,
|
||||
showMembers,
|
||||
showDocList,
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
337
zyplayer-doc-ui/api-ui/src/views/manage/DocManageList.vue
Normal file
337
zyplayer-doc-ui/api-ui/src/views/manage/DocManageList.vue
Normal file
@@ -0,0 +1,337 @@
|
||||
<template>
|
||||
<a-form layout="inline" style="margin-bottom: 20px;">
|
||||
<a-form-item label="文档类型">
|
||||
<a-select placeholder="请选择文档类型" v-model:value="searchParam.docType" style="width: 150px;">
|
||||
<a-select-option value="">全部</a-select-option>
|
||||
<a-select-option :value="1">URL添加</a-select-option>
|
||||
<a-select-option :value="2">JSON内容</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="开放访问">
|
||||
<a-select placeholder="请选择开放访问" v-model:value="searchParam.openVisit" style="width: 150px;">
|
||||
<a-select-option value="">全部</a-select-option>
|
||||
<a-select-option :value="0">否</a-select-option>
|
||||
<a-select-option :value="1">是</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态">
|
||||
<a-select placeholder="请选择状态" v-model:value="searchParam.docStatus" style="width: 150px;">
|
||||
<a-select-option value="">全部</a-select-option>
|
||||
<a-select-option :value="1">启用</a-select-option>
|
||||
<a-select-option :value="2">禁用</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-button @click="searchDocList" type="primary">查询</a-button>
|
||||
<a-button @click="openNewDoc" :style="{ marginLeft: '8px' }">新建</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<a-table :dataSource="docList" :columns="docListColumns" size="middle"
|
||||
:loading="docListLoading" :pagination="pagination"
|
||||
@change="handleTableChange"
|
||||
:scroll="{ x: 1400, y: 'calc(100vh - 300px)' }">
|
||||
<template #bodyCell="{ column, text, record }">
|
||||
<template v-if="column.dataIndex === 'operation'">
|
||||
<a-button size="small" type="link" @click="editDoc(record)">编辑</a-button>
|
||||
<template v-if="record.authType === 1">
|
||||
<a-button size="small" type="link" @click="showMembers(record)">成员管理</a-button>
|
||||
<a-popconfirm title="确定要删除吗?" @confirm="deleteDoc(record)">
|
||||
<a-button size="small" type="link" danger>删除</a-button>
|
||||
</a-popconfirm>
|
||||
</template>
|
||||
<a-dropdown :trigger="['click']">
|
||||
<template #overlay>
|
||||
<a-menu @click="handleActionMenuClick($event, record)">
|
||||
<a-menu-item key="shareView"><link-outlined /> 查看开放文档</a-menu-item>
|
||||
<a-menu-item key="shareInstruction"><edit-outlined /> 编辑开放文档说明</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button type="link" size="small">更多<DownOutlined /></a-button>
|
||||
</a-dropdown>
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'docType'">
|
||||
<a-tag color="red" v-if="text === 1">Swagger URL</a-tag>
|
||||
<a-tag color="blue" v-else-if="text === 2">Swagger JSON</a-tag>
|
||||
<a-tag color="green" v-else-if="text === 4">OpenApi JSON</a-tag>
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'openVisit'">
|
||||
<a-tag color="pink" v-if="text === 0">未开放</a-tag>
|
||||
<a-tag color="green" v-else-if="text === 1">已开放</a-tag>
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'docStatus'">
|
||||
<a-tag color="green" v-if="text === 1">启用</a-tag>
|
||||
<a-tag color="pink" v-else-if="text === 2">禁用</a-tag>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
<a-modal v-model:visible="newDocVisible" :title="docEdit.isNew?'新增文档':'编辑文档'" @ok="handleNewDocOk" :width="800">
|
||||
<a-form layout="horizontal" ref="newDocFormRef" :rules="newDocRules" :model="docEdit" :label-col="{span: 4}" :wrapper-col="{span: 20}">
|
||||
<a-form-item label="文档名称" required name="name">
|
||||
<a-input placeholder="请输入文档名称" v-model:value="docEdit.name"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="文档类型" required name="docType">
|
||||
<a-radio-group v-model:value="docEdit.docType">
|
||||
<a-radio :value="1">Swagger URL</a-radio>
|
||||
<a-radio :value="2">Swagger JSON</a-radio>
|
||||
<a-radio :value="3">OpenApi URL</a-radio>
|
||||
<a-radio :value="4">OpenApi JSON</a-radio>
|
||||
<a-radio :value="5" disabled>自建API</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="文档地址" required name="docUrl" v-if="docEdit.docType === 1">
|
||||
<a-input placeholder="请输入文档地址URL" v-model:value="docEdit.docUrl"></a-input>
|
||||
<template #extra>
|
||||
查看文档地址
|
||||
<a-popover title="文档地址支持以下任一格式">
|
||||
<template #content>
|
||||
<p>格式一:http://doc.zyplayer.com/v2/api-docs</p>
|
||||
<p>格式二:http://doc.zyplayer.com/swagger-resources</p>
|
||||
<p>格式三:http://doc.zyplayer.com/swagger-ui.html</p>
|
||||
</template>
|
||||
<a>示例</a>
|
||||
</a-popover>
|
||||
</template>
|
||||
</a-form-item>
|
||||
<a-form-item label="文档内容" required name="jsonContent" v-else-if="docEdit.docType === 2">
|
||||
<!-- textarea在内容很多的时候(>300KB)会卡顿,ace不会-->
|
||||
<ace-editor v-model:value="docEdit.jsonContent" lang="json" theme="monokai" width="100%" height="100" :options="aceEditorConfig"></ace-editor>
|
||||
<!-- <a-textarea placeholder="请输入JSON格式的Swagger文档内容" v-model:value="docEdit.jsonContent" :auto-size="{ minRows: 5, maxRows: 10 }"></a-textarea>-->
|
||||
<template #extra>
|
||||
查看文档内容
|
||||
<a-popover title="文档内容说明">
|
||||
<template #content>
|
||||
<div>支持以下格式的Swagger文档内容输入,其中 {"swagger": "2.0"} 为必要属性</div>
|
||||
<div v-highlight>
|
||||
<pre><code class="lang-json">{{swaggerDocDemo}}</code></pre>
|
||||
</div>
|
||||
</template>
|
||||
<a>说明</a>
|
||||
</a-popover>
|
||||
</template>
|
||||
</a-form-item>
|
||||
<a-form-item label="文档地址" required name="docUrl" v-if="docEdit.docType === 3">
|
||||
<a-input placeholder="请输入文档地址URL" v-model:value="docEdit.docUrl"></a-input>
|
||||
<template #extra>
|
||||
查看文档地址
|
||||
<a-popover title="文档地址支持以下任一格式">
|
||||
<template #content>
|
||||
<p>格式一:http://doc.zyplayer.com/v3/api-docs</p>
|
||||
</template>
|
||||
<a>示例</a>
|
||||
</a-popover>
|
||||
</template>
|
||||
</a-form-item>
|
||||
<a-form-item label="文档内容" required name="jsonContent" v-else-if="docEdit.docType === 4">
|
||||
<ace-editor v-model:value="docEdit.jsonContent" lang="json" theme="monokai" width="100%" height="100" :options="aceEditorConfig"></ace-editor>
|
||||
<!-- <a-textarea placeholder="请输入JSON格式的OpenApi文档内容" v-model:value="docEdit.jsonContent" :auto-size="{ minRows: 5, maxRows: 10 }"></a-textarea>-->
|
||||
<template #extra>
|
||||
查看文档内容
|
||||
<a-popover title="文档内容说明">
|
||||
<template #content>
|
||||
<div>支持以下格式的OpenApi文档内容输入,其中 {"openapi": "3.x.x"} 为必要属性</div>
|
||||
<div v-highlight>
|
||||
<pre><code class="lang-json">{{openApiDocDemo}}</code></pre>
|
||||
</div>
|
||||
</template>
|
||||
<a>说明</a>
|
||||
</a-popover>
|
||||
</template>
|
||||
</a-form-item>
|
||||
<a-form-item label="目标域名" name="rewriteDomain">
|
||||
<a-input placeholder="请输入目标域名" v-model:value="docEdit.rewriteDomain"></a-input>
|
||||
<template #extra>
|
||||
目标域名
|
||||
<a-popover title="目标域名说明">
|
||||
<template #content>
|
||||
<p>在文档的在线调试界面,访问的域名可以初始为此处录入的域名,而非文档本身的域名地址</p>
|
||||
<p>可便于不同环境间的接口测试,例:http://doc.zyplayer.com</p>
|
||||
</template>
|
||||
<a>说明</a>
|
||||
</a-popover>
|
||||
</template>
|
||||
</a-form-item>
|
||||
<a-form-item label="开放访问" required name="openVisit">
|
||||
<a-radio-group v-model:value="docEdit.openVisit">
|
||||
<a-radio :value="0">否</a-radio>
|
||||
<a-radio :value="1">开放访问</a-radio>
|
||||
</a-radio-group>
|
||||
<template #extra>
|
||||
开放访问后无需登录即可通过<a @click="openShareViewWindow(docEdit)">开放文档URL</a>访问该文档信息
|
||||
</template>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态" required name="docStatus">
|
||||
<a-radio-group v-model:value="docEdit.docStatus">
|
||||
<a-radio :value="1">启用</a-radio>
|
||||
<a-radio :value="2">禁用</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
<EditShareInstruction ref="instruction"></EditShareInstruction>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { toRefs, ref, reactive, onMounted } from 'vue';
|
||||
import {zyplayerApi} from '../../api';
|
||||
import {useStore} from 'vuex';
|
||||
import aceEditor from "../../assets/ace-editor";
|
||||
import EditShareInstruction from "./components/EditShareInstruction.vue";
|
||||
import {getZyplayerApiBaseUrl} from "../../api/request/utils";
|
||||
import {DownOutlined, LinkOutlined, EditOutlined} from '@ant-design/icons-vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
export default {
|
||||
emits: ['showMembers'],
|
||||
components: {aceEditor, EditShareInstruction, DownOutlined, LinkOutlined, EditOutlined},
|
||||
setup(props, {emit}) {
|
||||
const store = useStore();
|
||||
let docList = ref([]);
|
||||
let docListLoading = ref(false);
|
||||
let searchParam = ref({docType: '', openVisit: '', docStatus: '', pageNum: 1, pageSize: 20});
|
||||
let pagination = ref({
|
||||
pageSize: 20,
|
||||
pageNum: 1,
|
||||
total: 0,
|
||||
showSizeChanger: true,
|
||||
pageSizeOptions: ['20', '50', '100'],
|
||||
showTotal: total => `共${total}条`
|
||||
});
|
||||
const handleTableChange = (paginationNew, filters, sorter) => {
|
||||
pagination.value.pageNum = paginationNew.current;
|
||||
pagination.value.pageSize = paginationNew.pageSize;
|
||||
searchParam.value.pageNum = paginationNew.current;
|
||||
searchParam.value.pageSize = paginationNew.pageSize;
|
||||
searchDocList();
|
||||
};
|
||||
const searchDocList = async () => {
|
||||
docListLoading.value = true;
|
||||
zyplayerApi.apiDocList(searchParam.value).then(res => {
|
||||
setTimeout(() => docListLoading.value = false, 500);
|
||||
docList.value = res.data || [];
|
||||
pagination.value.total = res.total || 0;
|
||||
});
|
||||
};
|
||||
let docEdit = ref({});
|
||||
let newDocFormRef = ref();
|
||||
let newDocVisible = ref(false);
|
||||
const handleNewDocOk = async () => {
|
||||
newDocFormRef.value.validate().then(() => {
|
||||
zyplayerApi.apiDocAdd(docEdit.value).then(res => {
|
||||
searchDocList();
|
||||
newDocVisible.value = false;
|
||||
store.commit('addDocChangedNum');
|
||||
});
|
||||
}).catch(error => {
|
||||
console.log('error', error);
|
||||
});
|
||||
};
|
||||
const openNewDoc = async () => {
|
||||
newDocVisible.value = true;
|
||||
docEdit.value = {
|
||||
docType: 1, openVisit: 0, docStatus: 1, isNew: 1
|
||||
};
|
||||
};
|
||||
const showMembers = (record) => {
|
||||
emit('showMembers', record);
|
||||
};
|
||||
const editDoc = (record) => {
|
||||
zyplayerApi.apiDocDetail({id: record.id}).then(res => {
|
||||
docEdit.value = res.data;
|
||||
newDocVisible.value = true;
|
||||
});
|
||||
};
|
||||
const updateDoc = async (id, docStatus, yn) => {
|
||||
zyplayerApi.apiDocUpdate({id, docStatus, yn}).then(res => {
|
||||
searchDocList();
|
||||
store.commit('addDocChangedNum');
|
||||
});
|
||||
};
|
||||
const deleteDoc = async (row) => updateDoc(row.id, null, 0);
|
||||
// 打开开放文档新窗口
|
||||
const openShareViewWindow = record => {
|
||||
if (!record.shareUuid) {
|
||||
message.warning('请先保存文档后再试');
|
||||
} else if (record.openVisit !== 1) {
|
||||
message.warning('该文档尚未开启开放访问功能,请在编辑页选择开放后再试');
|
||||
} else {
|
||||
window.open(getZyplayerApiBaseUrl() + '/doc-api#/share/home?uuid=' + record.shareUuid);
|
||||
}
|
||||
};
|
||||
const handleActionMenuClick = (item, record) => {
|
||||
if (item.key === 'shareView') {
|
||||
openShareViewWindow(record);
|
||||
} else if (item.key === 'shareInstruction') {
|
||||
instruction.value.editDoc(record.id);
|
||||
}
|
||||
}
|
||||
let instruction = ref();
|
||||
onMounted(() => {
|
||||
searchDocList();
|
||||
});
|
||||
return {
|
||||
searchParam,
|
||||
docList,
|
||||
docListLoading,
|
||||
newDocVisible,
|
||||
docEdit,
|
||||
newDocFormRef,
|
||||
searchDocList,
|
||||
openNewDoc,
|
||||
handleNewDocOk,
|
||||
deleteDoc,
|
||||
editDoc,
|
||||
showMembers,
|
||||
handleTableChange,
|
||||
openShareViewWindow,
|
||||
handleActionMenuClick,
|
||||
pagination,
|
||||
instruction,
|
||||
newDocRules: {
|
||||
name: [{required: true, message: '请输入文档名称', trigger: 'change'}],
|
||||
docUrl: [{required: true, message: '请输入文档地址', trigger: 'change'}],
|
||||
jsonContent: [{required: true, message: '请输入JSON格式的swagger文档内容', trigger: 'change'}],
|
||||
docType: [{type: 'number', required: true, message: '请选择文档类型', trigger: 'change'}],
|
||||
openVisit: [{type: 'number', required: true, message: '请选择是否开放访问', trigger: 'change'}],
|
||||
docStatus: [{type: 'number', required: true, message: '请选择文档状态', trigger: 'change'}],
|
||||
},
|
||||
docListColumns: [
|
||||
{title: 'ID', dataIndex: 'id', width: 70},
|
||||
{title: '文档名称', dataIndex: 'name', width: 250},
|
||||
{title: '文档类型', dataIndex: 'docType', width: 120},
|
||||
{title: '开放访问', dataIndex: 'openVisit', width: 90},
|
||||
{title: '状态', dataIndex: 'docStatus', width: 90},
|
||||
{title: '文档地址', dataIndex: 'docUrl'},
|
||||
{title: '目标域名', dataIndex: 'rewriteDomain', width: 250},
|
||||
{title: '操作', dataIndex: 'operation', fixed: 'right', width: 280},
|
||||
],
|
||||
aceEditorConfig: {
|
||||
wrap: true,
|
||||
autoScrollEditorIntoView: true,
|
||||
enableBasicAutocompletion: true,
|
||||
enableSnippets: true,
|
||||
enableLiveAutocompletion: true,
|
||||
minLines: 10,
|
||||
maxLines: 15,
|
||||
},
|
||||
swaggerDocDemo:
|
||||
'{\n'
|
||||
+ ' "swagger": "2.0",\n'
|
||||
+ ' "info": {},\n'
|
||||
+ ' "host": "doc.zyplayer.com",\n'
|
||||
+ ' "basePath":"/",\n'
|
||||
+ ' "tags": [],\n'
|
||||
+ ' "paths": {},\n'
|
||||
+ ' "definitions": {}\n'
|
||||
+ '}',
|
||||
openApiDocDemo:
|
||||
'{\n'
|
||||
+ ' "openapi": "3.0.3",\n'
|
||||
+ ' "components": {}\n'
|
||||
+ ' "servers": [],\n'
|
||||
+ ' "paths": {},\n'
|
||||
+ ' "info": {},\n'
|
||||
+ '}',
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
200
zyplayer-doc-ui/api-ui/src/views/manage/DocManageMembers.vue
Normal file
200
zyplayer-doc-ui/api-ui/src/views/manage/DocManageMembers.vue
Normal file
@@ -0,0 +1,200 @@
|
||||
<template>
|
||||
<a-page-header
|
||||
title="成员管理"
|
||||
:sub-title="doc.name||''"
|
||||
@back="showDocList">
|
||||
<template #extra>
|
||||
<a-button @click="searchDocMemberList" type="primary">查询</a-button>
|
||||
<a-button @click="openAddDocMember" :style="{ marginLeft: '8px' }">添加用户</a-button>
|
||||
</template>
|
||||
</a-page-header>
|
||||
<a-table :dataSource="docMemberList" :columns="docListColumns" size="middle"
|
||||
:loading="docMemberListLoading" :pagination="false"
|
||||
@change="handleTableChange"
|
||||
:scroll="{ x: 1400, y: 'calc(100vh - 300px)' }">
|
||||
<template #bodyCell="{ column, text, record }">
|
||||
<template v-if="column.dataIndex === 'operation'">
|
||||
<a-popconfirm title="确定要删除吗?" @confirm="deleteDocMember(record)">
|
||||
<a-button size="small" type="link" danger>删除</a-button>
|
||||
</a-popconfirm>
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'sex'">
|
||||
<a-tag color="pink" v-if="record.sex === 1">男</a-tag>
|
||||
<a-tag color="red" v-else-if="record.sex === 0">女</a-tag>
|
||||
<a-tag color="orange" v-else>-</a-tag>
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'authType'">
|
||||
<a-select placeholder="请选择角色" v-model:value="record.authType" @change="userAuthTypeChange(record)" style="width: 150px;">
|
||||
<a-select-option :value="1">管理员</a-select-option>
|
||||
<a-select-option :value="2">开发人员</a-select-option>
|
||||
</a-select>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
<a-modal v-model:visible="addUserVisible" title="添加用户" @ok="handleAddUserOk" :width="600">
|
||||
<a-form layout="horizontal" ref="addUserFormRef" :model="userAdd" :rules="addUserRules" :label-col="{span: 4}" :wrapper-col="{span: 20}">
|
||||
<a-form-item label="选择用户" required name="userId">
|
||||
<a-select
|
||||
v-model:value="userAdd.userId"
|
||||
show-search
|
||||
placeholder="输入用户名、邮箱、手机号搜索"
|
||||
:default-active-first-option="false"
|
||||
:show-arrow="true"
|
||||
:filter-option="false"
|
||||
:not-found-content="undefined"
|
||||
:options="userSearchList"
|
||||
@search="handleUserSearch"
|
||||
>
|
||||
<template v-if="userSearchState.fetching" #notFoundContent>
|
||||
<a-spin size="small" />
|
||||
</template>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="用户角色" required name="authType">
|
||||
<a-radio-group v-model:value="userAdd.authType">
|
||||
<a-radio :value="1">管理员</a-radio>
|
||||
<a-radio :value="2">开发人员</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { toRefs, ref, reactive, onMounted } from 'vue';
|
||||
import {zyplayerApi} from '../../api';
|
||||
import {useStore} from 'vuex';
|
||||
import {getZyplayerApiBaseUrl} from "../../api/request/utils";
|
||||
import {DownOutlined, LinkOutlined, EditOutlined} from '@ant-design/icons-vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
export default {
|
||||
emits: ['showDocList'],
|
||||
components: {DownOutlined, LinkOutlined, EditOutlined},
|
||||
props: {
|
||||
doc: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
},
|
||||
setup(props, {emit}) {
|
||||
const store = useStore();
|
||||
let docMemberList = ref([]);
|
||||
let docMemberListLoading = ref(false);
|
||||
let searchParam = ref({docId: '', pageNum: 1, pageSize: 20});
|
||||
// 项目应该加不了很多的人,暂不分页
|
||||
let pagination = ref({
|
||||
pageSize: 20,
|
||||
pageNum: 1,
|
||||
total: 0,
|
||||
showSizeChanger: true,
|
||||
pageSizeOptions: ['20', '50', '100'],
|
||||
showTotal: total => `共${total}条`
|
||||
});
|
||||
const handleTableChange = (paginationNew, filters, sorter) => {
|
||||
pagination.value.pageNum = paginationNew.current;
|
||||
pagination.value.pageSize = paginationNew.pageSize;
|
||||
searchParam.value.pageNum = paginationNew.current;
|
||||
searchParam.value.pageSize = paginationNew.pageSize;
|
||||
searchDocMemberList();
|
||||
};
|
||||
const searchDocMemberList = async () => {
|
||||
docMemberListLoading.value = true;
|
||||
searchParam.value.docId = props.doc.id;
|
||||
zyplayerApi.docAuthList(searchParam.value).then(res => {
|
||||
setTimeout(() => docMemberListLoading.value = false, 500);
|
||||
docMemberList.value = res.data || [];
|
||||
pagination.value.total = res.total || 0;
|
||||
});
|
||||
};
|
||||
let userAdd = ref({});
|
||||
let userSearchState = ref({
|
||||
data: [],
|
||||
search: '',
|
||||
fetching: false,
|
||||
});
|
||||
let userSearchList = ref([]);
|
||||
let addUserFormRef = ref();
|
||||
let addUserVisible = ref(false);
|
||||
const handleUserSearch = (search) => {
|
||||
userSearchState.value.search = search;
|
||||
if (userSearchState.value.fetching) {
|
||||
return;
|
||||
}
|
||||
userSearchState.value.fetching = true;
|
||||
userSearchList.value = [];
|
||||
setTimeout(() => {
|
||||
zyplayerApi.searchUserList({search: userSearchState.value.search}).then(res => {
|
||||
let resArr = res.data || [];
|
||||
resArr.forEach(item => userSearchList.value.push({label: item.userName, value: item.id}));
|
||||
userSearchState.value.fetching = false;
|
||||
});
|
||||
}, 500);
|
||||
};
|
||||
const handleAddUserOk = async () => {
|
||||
addUserFormRef.value.validate().then(() => {
|
||||
zyplayerApi.docAuthAssign(userAdd.value).then(res => {
|
||||
searchDocMemberList();
|
||||
addUserVisible.value = false;
|
||||
});
|
||||
}).catch(error => {
|
||||
console.log('error', error);
|
||||
});
|
||||
};
|
||||
const userAuthTypeChange = async (record) => {
|
||||
let param = {...record, docId: props.doc.id};
|
||||
zyplayerApi.docAuthAssign(param).then(res => {
|
||||
message.success('修改成功');
|
||||
});
|
||||
};
|
||||
const openAddDocMember = async () => {
|
||||
addUserVisible.value = true;
|
||||
userAdd.value = {docId: props.doc.id, userId: undefined, authType: 1};
|
||||
};
|
||||
const deleteDocMember = async (row) => {
|
||||
zyplayerApi.docAuthDelete({docId: props.doc.id, userId: row.userId}).then(res => {
|
||||
searchDocMemberList();
|
||||
});
|
||||
};
|
||||
const showDocList = () => {
|
||||
emit('showDocList');
|
||||
}
|
||||
onMounted(() => {
|
||||
searchDocMemberList();
|
||||
});
|
||||
return {
|
||||
showDocList,
|
||||
searchParam,
|
||||
docMemberList,
|
||||
docMemberListLoading,
|
||||
addUserVisible,
|
||||
userAdd,
|
||||
userSearchList,
|
||||
addUserFormRef,
|
||||
userSearchState,
|
||||
handleUserSearch,
|
||||
searchDocMemberList,
|
||||
openAddDocMember,
|
||||
handleAddUserOk,
|
||||
userAuthTypeChange,
|
||||
deleteDocMember,
|
||||
handleTableChange,
|
||||
pagination,
|
||||
docListColumns: [
|
||||
{title: 'ID', dataIndex: 'userId', width: 70},
|
||||
{title: '用户名', dataIndex: 'userName'},
|
||||
{title: '帐号', dataIndex: 'userNo'},
|
||||
{title: '邮箱', dataIndex: 'email'},
|
||||
{title: '手机号', dataIndex: 'phone'},
|
||||
{title: '性别', dataIndex: 'sex', width: 90},
|
||||
{title: '角色', dataIndex: 'authType', width: 200},
|
||||
{title: '操作', dataIndex: 'operation', fixed: 'right', width: 100},
|
||||
],
|
||||
addUserRules: {
|
||||
userId: [{type: 'number', required: true, message: '请选择用户', trigger: 'change'}],
|
||||
authType: [{type: 'number', required: true, message: '请选择用户角色', trigger: 'change'}],
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
Reference in New Issue
Block a user