u
This commit is contained in:
1 parent
1217f7df5f
commit
6e59e8be45
42 files changed
+1256
-430
No files matched your search
@@ -5,43 +5,20 @@ import { computed, useAttrs } from 'vue'
|
||||
interface Props {
|
||||
/** 图标名称 */
|
||||
icon?: string
|
||||
/** 图标颜色 */
|
||||
color?: string
|
||||
/** 图标大小(px) */
|
||||
fontSize?: number | string
|
||||
/** 图标大小 */
|
||||
size?: string | number
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const attrs = useAttrs()
|
||||
|
||||
const bindAttrs = computed(() => {
|
||||
const style: Record<string, string> = {}
|
||||
|
||||
if (props.color) {
|
||||
style.color = props.color
|
||||
}
|
||||
|
||||
if (props.fontSize) {
|
||||
style.fontSize
|
||||
= typeof props.fontSize === 'number'
|
||||
? `${props.fontSize}px`
|
||||
: props.fontSize
|
||||
}
|
||||
|
||||
return {
|
||||
...attrs,
|
||||
style: {
|
||||
...(attrs.style as Record<string, string>),
|
||||
...style,
|
||||
},
|
||||
}
|
||||
})
|
||||
const bindAttrs = computed<{ class: string, style: string }>(() => ({
|
||||
class: (attrs.class as string) || '',
|
||||
style: (attrs.style as string) || '',
|
||||
}))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Icon
|
||||
v-if="icon"
|
||||
:icon="icon"
|
||||
v-bind="bindAttrs"
|
||||
/>
|
||||
<Icon v-if="props.icon" :icon="props.icon" :width="props.size" :height="props.size" v-bind="bindAttrs" />
|
||||
</template>
|
||||
@@ -0,0 +1,28 @@
|
||||
<script lang="ts" setup>
|
||||
import type { AnchorMenuItem } from './type'
|
||||
|
||||
defineOptions({
|
||||
name: 'AnchorMenu',
|
||||
})
|
||||
|
||||
defineProps<{
|
||||
menu: AnchorMenuItem[]
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<template v-for="item in menu" :key="item.href">
|
||||
<el-anchor-link :href="`#${item.href}`">
|
||||
{{ item.label }}
|
||||
|
||||
<!-- 如果有子菜单,递归渲染 -->
|
||||
<template v-if="item.children && item.children.length > 0" #sub-link>
|
||||
<AnchorMenu :menu="item.children" />
|
||||
</template>
|
||||
</el-anchor-link>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 样式部分可以根据需要修改 */
|
||||
</style>
|
||||
@@ -0,0 +1,6 @@
|
||||
export interface AnchorMenuItem {
|
||||
label: string
|
||||
href: string
|
||||
level?: number
|
||||
children: AnchorMenuItem[]
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import type { PropType } from 'vue'
|
||||
import type { AnchorMenuItem } from '@/components/anchor-menu/type'
|
||||
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { computed, nextTick, onBeforeUnmount, onMounted, ref, shallowRef, watch } from 'vue'
|
||||
import { uploadImage, uploadToAliyun, uploadVideo } from '@/utils/file'
|
||||
import { registerPreviewMenu, toolbarConfig } from './config'
|
||||
import Directory from './modules/directory.vue'
|
||||
import '@wangeditor/editor/dist/css/style.css'
|
||||
|
||||
const props = defineProps({
|
||||
@@ -23,11 +23,29 @@ const props = defineProps({
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const emit = defineEmits(['update:modelValue', 'update:directory'])
|
||||
|
||||
// 内容 HTML
|
||||
const valueHtml = ref('')
|
||||
|
||||
// Directory
|
||||
const activeCollapseNames = ref(['1'])
|
||||
const directory = ref<AnchorMenuItem[]>([])
|
||||
|
||||
const updateDirectory = throttle(doGenerateDirectory)
|
||||
|
||||
watch(
|
||||
() => valueHtml.value,
|
||||
(newContent) => {
|
||||
if (newContent) {
|
||||
nextTick(() => {
|
||||
updateDirectory()
|
||||
})
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
// 只读副本
|
||||
const previewHtml = ref('')
|
||||
|
||||
@@ -121,6 +139,74 @@ function handleCreated(editor: any) {
|
||||
|
||||
nextTick(() => {})
|
||||
}
|
||||
|
||||
function throttle(fn: any) {
|
||||
let isRunning = false
|
||||
return function (...args: any) {
|
||||
if (!isRunning) {
|
||||
isRunning = true
|
||||
requestAnimationFrame(() => {
|
||||
fn(...args)
|
||||
isRunning = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function doGenerateDirectory() {
|
||||
const root = document.querySelector('.editor')
|
||||
|
||||
if (!root)
|
||||
return
|
||||
|
||||
// 获取所有 h1, h2, h3 标签
|
||||
const headings = Array.from(root.querySelectorAll('h1, h2, h3'))
|
||||
|
||||
// 用栈来管理当前的父子关系
|
||||
const toc: AnchorMenuItem[] = []
|
||||
const stack: AnchorMenuItem[] = []
|
||||
|
||||
headings.forEach((heading, idx) => {
|
||||
if (!heading.id)
|
||||
heading.id = `section-${idx + 1}`
|
||||
|
||||
const level = +heading.tagName[1] // 获取 h1 = 1, h2 = 2, h3 = 3
|
||||
const item: AnchorMenuItem = {
|
||||
href: heading.id,
|
||||
label: heading.textContent || '',
|
||||
level,
|
||||
children: [],
|
||||
}
|
||||
|
||||
// 处理层级关系
|
||||
while (stack.length > 0) {
|
||||
const top = stack[stack.length - 1] // 获取栈顶元素
|
||||
if (top.level && top.level >= level) {
|
||||
stack.pop() // 弹出更高层级的项
|
||||
}
|
||||
else {
|
||||
break // 如果栈顶元素的级别小于当前的级别,停止弹栈
|
||||
}
|
||||
}
|
||||
|
||||
if (stack.length > 0) {
|
||||
// 如果栈非空,当前节点为栈顶节点的子节点
|
||||
stack[stack.length - 1].children.push(item)
|
||||
}
|
||||
else {
|
||||
// 否则,当前节点是顶层节点
|
||||
toc.push(item)
|
||||
}
|
||||
|
||||
// 将当前节点推入栈中,成为下一个节点的父节点
|
||||
stack.push(item)
|
||||
})
|
||||
|
||||
// 保存目录结构
|
||||
directory.value = toc
|
||||
|
||||
emit('update:directory', directory.value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -129,7 +215,16 @@ function handleCreated(editor: any) {
|
||||
<Toolbar v-if="props.mode === 'edit'" :class="toolbarClass" class="toolbar" :editor="editorRef" :default-config="toolbarConfig" />
|
||||
<Editor key="main" v-model="valueHtml" :class="editorClass" class="editor" :default-config="editorConfig" @on-change="handleChange" @on-created="handleCreated" />
|
||||
</div>
|
||||
<Directory v-if="showDirecotry" v-model:content="valueHtml" class="directory" />
|
||||
|
||||
<div v-if="showDirecotry" class="directory">
|
||||
<el-collapse v-model="activeCollapseNames">
|
||||
<el-collapse-item title="目录" name="1">
|
||||
<el-anchor :offset="70">
|
||||
<AnchorMenu :menu="directory" />
|
||||
</el-anchor>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <Preview v-model:visible="showPreview" :content="previewHtml" /> -->
|
||||
</template>
|
||||
@@ -168,9 +263,11 @@ function handleCreated(editor: any) {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.directory {
|
||||
width: 200px;
|
||||
height: 450px;
|
||||
height: 100%;
|
||||
margin-left: 16px;
|
||||
}
|
||||
.main {
|
||||
min-width: 0;
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { nextTick, ref, watch } from 'vue'
|
||||
|
||||
defineOptions({
|
||||
name: 'WangEditorDirecotry',
|
||||
})
|
||||
|
||||
const props = defineProps({
|
||||
content: {
|
||||
type: String,
|
||||
},
|
||||
top: {
|
||||
type: Number,
|
||||
},
|
||||
})
|
||||
|
||||
const directory = ref<any[]>([])
|
||||
const collapsed = ref(false)
|
||||
|
||||
function toggleCollapse() {
|
||||
collapsed.value = !collapsed.value
|
||||
}
|
||||
|
||||
function scrollTo(id: any) {
|
||||
const el = document.getElementById(id)
|
||||
if (el) {
|
||||
if (props.top) {
|
||||
const rect = el.getBoundingClientRect()
|
||||
const scrollTop = window.pageYOffset || document.documentElement.scrollTop
|
||||
const top = rect.top + scrollTop - props.top
|
||||
|
||||
window.scrollTo({
|
||||
top,
|
||||
behavior: 'smooth',
|
||||
})
|
||||
}
|
||||
else {
|
||||
el.scrollIntoView({
|
||||
behavior: 'smooth', // 平滑滚动
|
||||
block: 'start', // 元素滚动到视口顶部
|
||||
inline: 'nearest', // 元素在水平方向上的滚动对齐方式
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function throttle(fn: any) {
|
||||
let isRunning = false
|
||||
return function (...args: any) {
|
||||
if (!isRunning) {
|
||||
isRunning = true
|
||||
requestAnimationFrame(() => {
|
||||
fn(...args)
|
||||
isRunning = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
function doGenerateDirectory() {
|
||||
const root = document.querySelector('.editor')
|
||||
|
||||
if (!root)
|
||||
return
|
||||
const headings = Array.from(root.querySelectorAll('h1, h2, h3'))
|
||||
const toc = headings.map((heading, idx) => {
|
||||
if (!heading.id)
|
||||
heading.id = `section-${idx + 1}`
|
||||
return {
|
||||
id: heading.id,
|
||||
text: heading.textContent || '',
|
||||
level: +heading.tagName[1], // 1 => h1, 2 => h2, 3 => h3
|
||||
index: idx,
|
||||
}
|
||||
})
|
||||
|
||||
directory.value = toc
|
||||
}
|
||||
|
||||
const updateDirectory = throttle(doGenerateDirectory)
|
||||
|
||||
watch(
|
||||
() => props.content,
|
||||
(newContent) => {
|
||||
if (newContent) {
|
||||
nextTick(() => {
|
||||
updateDirectory()
|
||||
})
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="directory-card" :class="{ collapsed }">
|
||||
<div class="directory-header" @click="toggleCollapse">
|
||||
<div class="directory-header-left">
|
||||
<i-material-symbols:folder-copy-outline />
|
||||
<span>目录</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="!collapsed" class="directory-content">
|
||||
<div v-for="item in directory" :key="item.id" class="directory-item" :class="`level-${item.level}`" @click="scrollTo(item.id)">
|
||||
{{ item.text }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.directory-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
overflow: hidden;
|
||||
|
||||
&.collapsed {
|
||||
height: 44px !important;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.directory-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 1rem;
|
||||
height: 44px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
|
||||
.directory-header-left {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.directory-content {
|
||||
flex: 1;
|
||||
padding: 1rem;
|
||||
overflow-y: auto;
|
||||
word-break: break-all;
|
||||
.directory-item {
|
||||
padding: 8px 12px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
|
||||
&.level-1 {
|
||||
font-weight: 600;
|
||||
padding-left: 0;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
&.level-2 {
|
||||
padding-left: 20px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
&.level-3 {
|
||||
padding-left: 40px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: #007aff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -24,6 +24,8 @@ function navigateTo(path: string) {
|
||||
|
||||
function exitLogin() {
|
||||
userStore.clearUserInfo()
|
||||
|
||||
router.push('/auth/login')
|
||||
}
|
||||
|
||||
function isActive(path: string) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import ElementPlus from 'element-plus'
|
||||
import zhCn from 'element-plus/es/locale/lang/zh-cn'
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import { setupRouter } from './router/index'
|
||||
@@ -11,7 +12,9 @@ async function setupApp() {
|
||||
setupPinia(app)
|
||||
setupRouter(app)
|
||||
|
||||
app.use(ElementPlus)
|
||||
app.use(ElementPlus, {
|
||||
locale: zhCn,
|
||||
})
|
||||
app.mount('#app')
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { CompanyDetail, CompanyListItem, QueryCompanyParams, RecommendCompany, RecommendHotCompany } from '@/types/company'
|
||||
import type { Company, CompanyDetail, QueryCompanyParams, RecommendCompany, RecommendHotCompany, UpdateCompanyParams } from '@/types/company'
|
||||
import { httpGet, httpPostJson } from '@/request/utils'
|
||||
|
||||
export function getRecommendCompanyApi() {
|
||||
@@ -10,9 +10,13 @@ export function getRecommendHotCompanyApi() {
|
||||
}
|
||||
|
||||
export function queryCompanyApi(params: QueryCompanyParams) {
|
||||
return httpPostJson<BasePageResult<CompanyListItem>>('/company/query', params)
|
||||
return httpPostJson<BasePageResult<Company>>('/company/query', params)
|
||||
}
|
||||
|
||||
export function getCompanyDetailApi(id: number) {
|
||||
return httpGet<CompanyDetail>(`/company/detail/${id}`)
|
||||
}
|
||||
|
||||
export function updateCompanyApi(params: UpdateCompanyParams) {
|
||||
return httpPostJson<void>(`/company/update`, params)
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import type { CompanyUser, QueryCompanyUserParams } from '@/types/company/user'
|
||||
import { httpGet, httpPostJson } from '@/request/utils'
|
||||
|
||||
export function queryCompanyUserApi(params: QueryCompanyUserParams) {
|
||||
return httpPostJson<BasePageResult<CompanyUser>>('/company/user/query', params)
|
||||
}
|
||||
@@ -30,6 +30,10 @@ const router = createRouter({
|
||||
path: '/settings/info/company',
|
||||
component: () => import('@/views/settings/info/company.vue'),
|
||||
},
|
||||
{
|
||||
path: '/settings/info/user',
|
||||
component: () => import('@/views/settings/info/user.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -23,8 +23,8 @@ export interface LoginApiResult {
|
||||
|
||||
export interface RegisterCompanyForm {
|
||||
name: string
|
||||
industry: string[]
|
||||
address: string[]
|
||||
industries: string[]
|
||||
areas: string[]
|
||||
phone: string
|
||||
email: string
|
||||
profile: string
|
||||
@@ -45,8 +45,8 @@ export interface RegisterAdminForm {
|
||||
export interface RegisterApiParams {
|
||||
company: {
|
||||
name: string
|
||||
industry: string
|
||||
address: string
|
||||
industries: string[]
|
||||
areas: string[]
|
||||
phone: string
|
||||
email: string
|
||||
profile: string
|
||||
|
||||
@@ -11,6 +11,7 @@ export {}
|
||||
/* prettier-ignore */
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
AnchorMenu: typeof import('./../components/anchor-menu/index.vue')['default']
|
||||
AreaSelect: typeof import('./../components/AreaSelect.vue')['default']
|
||||
Directory: typeof import('./../components/wang-editor/modules/directory.vue')['default']
|
||||
HelloWorld: typeof import('./../components/HelloWorld.vue')['default']
|
||||
@@ -22,6 +23,7 @@ declare module 'vue' {
|
||||
'IHugeicons:home03': typeof import('~icons/hugeicons/home03')['default']
|
||||
'IHugeicons:materialAndTexture': typeof import('~icons/hugeicons/material-and-texture')['default']
|
||||
'IHugeicons:setting07': typeof import('~icons/hugeicons/setting07')['default']
|
||||
'IHugeicons:upload01': typeof import('~icons/hugeicons/upload01')['default']
|
||||
'IHugeicons:userSettings01': typeof import('~icons/hugeicons/user-settings01')['default']
|
||||
'IIc:outlineSettings': typeof import('~icons/ic/outline-settings')['default']
|
||||
'IIc:twotoneHeadphones': typeof import('~icons/ic/twotone-headphones')['default']
|
||||
|
||||
@@ -22,7 +22,7 @@ export interface QueryCompanyParams {
|
||||
name: string
|
||||
}
|
||||
|
||||
export interface CompanyListItem {
|
||||
export interface Company {
|
||||
id: number
|
||||
name: string
|
||||
areas: string[]
|
||||
@@ -43,6 +43,7 @@ export interface CompanyDetail {
|
||||
phone: string
|
||||
email: string
|
||||
description: string
|
||||
establishmentDate: string
|
||||
users: {
|
||||
id: number
|
||||
companyId: number
|
||||
@@ -53,3 +54,16 @@ export interface CompanyDetail {
|
||||
name: string
|
||||
}[]
|
||||
}
|
||||
|
||||
export interface UpdateCompanyParams {
|
||||
id: number
|
||||
name: string
|
||||
areas: string[]
|
||||
industries: string[]
|
||||
establishmentDate: string
|
||||
profile: string
|
||||
phone: string
|
||||
email: string
|
||||
description: string
|
||||
logo: string
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
export interface QueryCompanyUserParams {
|
||||
currentPage: number
|
||||
pageSize: number
|
||||
|
||||
companyId: number
|
||||
name: string
|
||||
position: string
|
||||
email: string
|
||||
phone: string
|
||||
canuse: string
|
||||
}
|
||||
|
||||
export interface CompanyUser {
|
||||
id: number
|
||||
role: number
|
||||
name: string
|
||||
position: string
|
||||
email: string
|
||||
phone: string
|
||||
canuse: string
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import type { RegisterCompanyForm } from '@/types/auth'
|
||||
import { reactive, ref, watch } from 'vue'
|
||||
import { reactive, ref } from 'vue'
|
||||
import AreaSelect from '@/components/AreaSelect.vue'
|
||||
import IndustrySelect from '@/components/IndustrySelect.vue'
|
||||
import { validateEmail, validatePhone } from '@/utils/validate'
|
||||
@@ -15,10 +15,10 @@ const formRules = {
|
||||
name: [
|
||||
{ required: true, message: '公司名称不能为空', trigger: 'blur' },
|
||||
],
|
||||
industry: [
|
||||
industries: [
|
||||
{ required: true, message: '所属行业不能为空', trigger: 'blur' },
|
||||
],
|
||||
address: [
|
||||
areas: [
|
||||
{ required: true, message: '公司地址不能为空', trigger: 'blur' },
|
||||
],
|
||||
email: [{ validator: emailValidator, trigger: 'blur' }],
|
||||
@@ -55,19 +55,13 @@ function phoneValidator(rule: any, value: any, callback: any) {
|
||||
}
|
||||
const form = reactive<RegisterCompanyForm>({
|
||||
name: '',
|
||||
industry: [],
|
||||
address: [],
|
||||
industries: [],
|
||||
areas: [],
|
||||
phone: '',
|
||||
email: '',
|
||||
profile: '',
|
||||
})
|
||||
|
||||
watch(() => form.industry, (newVal) => {
|
||||
console.log(newVal)
|
||||
})
|
||||
watch(() => form.address, (newVal) => {
|
||||
console.log(newVal)
|
||||
})
|
||||
async function handleSubmit(formEl: FormInstance | undefined) {
|
||||
if (!formEl)
|
||||
return
|
||||
@@ -102,13 +96,13 @@ async function handleSubmit(formEl: FormInstance | undefined) {
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="所属行业" prop="industry">
|
||||
<IndustrySelect v-model="form.industry" placeholder="请输入所属行业" />
|
||||
<IndustrySelect v-model="form.industries" placeholder="请输入所属行业" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="公司地址" prop="address">
|
||||
<AreaSelect
|
||||
v-model="form.address"
|
||||
v-model="form.areas"
|
||||
placeholder="请输入公司地址"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
@@ -35,8 +35,8 @@ function handleSubmit() {
|
||||
registerApi({
|
||||
company: {
|
||||
name: props.company.name,
|
||||
industry: props.company.industry.join(','),
|
||||
address: props.company.address.join(','),
|
||||
industries: props.company.industries,
|
||||
areas: props.company.areas,
|
||||
phone: props.company.phone,
|
||||
email: props.company.email,
|
||||
profile: props.company.profile,
|
||||
@@ -84,7 +84,7 @@ function handleSubmit() {
|
||||
<div class="info-item">
|
||||
<span class="info-label">所属行业</span>
|
||||
<span class="info-value">
|
||||
{{ company.industry?.join(',') || '-' }}
|
||||
{{ company.industries?.join(',') || '-' }}
|
||||
</span>
|
||||
</div>
|
||||
</el-col>
|
||||
@@ -93,7 +93,7 @@ function handleSubmit() {
|
||||
<div class="info-item">
|
||||
<span class="info-label">公司地址</span>
|
||||
<span class="info-value">
|
||||
{{ company.address?.join('/') || '-' }}
|
||||
{{ company.areas?.join('/') || '-' }}
|
||||
</span>
|
||||
</div>
|
||||
</el-col>
|
||||
|
||||
@@ -51,8 +51,8 @@ const adminForm = ref<RegisterAdminForm>({
|
||||
})
|
||||
const companyForm = ref<RegisterCompanyForm>({
|
||||
name: '',
|
||||
industry: [],
|
||||
address: [],
|
||||
industries: [],
|
||||
areas: [],
|
||||
phone: '',
|
||||
email: '',
|
||||
profile: '',
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
<script lang="ts" setup>
|
||||
import type { AnchorMenuItem } from '@/components/anchor-menu/type'
|
||||
import type { CompanyDetail } from '@/types/company'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import AnchorMenu from '@/components/anchor-menu/index.vue'
|
||||
|
||||
import WangEditor from '@/components/wang-editor/index.vue'
|
||||
import { getCompanyDetailApi } from '@/request/api/company'
|
||||
|
||||
@@ -21,9 +24,34 @@ const companyDetail = ref<CompanyDetail>({
|
||||
phone: '',
|
||||
email: '',
|
||||
description: '',
|
||||
establishmentDate: '',
|
||||
users: [],
|
||||
})
|
||||
|
||||
const anchorMenu = ref<AnchorMenuItem[]>([
|
||||
{
|
||||
label: '基础信息',
|
||||
href: 'basic',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
label: '公司简介',
|
||||
href: 'profile',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
label: '公司成员',
|
||||
href: 'users',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
label: '公司详细介绍',
|
||||
href: 'description',
|
||||
children: [],
|
||||
},
|
||||
])
|
||||
const activeCollapseNames = ref(['1'])
|
||||
|
||||
onMounted(() => {
|
||||
companyId.value = Number(route.query.id) || 0
|
||||
|
||||
@@ -45,6 +73,10 @@ onMounted(() => {
|
||||
ElMessage.error('加载公司信息失败,请稍后再试')
|
||||
})
|
||||
})
|
||||
|
||||
function handleUpdateEditorDirectory(menus: AnchorMenuItem[]) {
|
||||
anchorMenu.value[3].children.push(...menus)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -121,7 +153,7 @@ onMounted(() => {
|
||||
<div class="info-header">
|
||||
<span class="info-title">公司详细介绍</span>
|
||||
</div>
|
||||
<WangEditor v-model="companyDetail.description" mode="view" />
|
||||
<WangEditor v-model="companyDetail.description" mode="view" @update:directory="handleUpdateEditorDirectory" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -131,18 +163,7 @@ onMounted(() => {
|
||||
导航
|
||||
</div>
|
||||
<el-anchor :offset="70">
|
||||
<el-anchor-link href="#basic">
|
||||
基础信息
|
||||
</el-anchor-link>
|
||||
<el-anchor-link href="#profile">
|
||||
公司简介
|
||||
</el-anchor-link>
|
||||
<el-anchor-link href="#users">
|
||||
公司成员
|
||||
</el-anchor-link>
|
||||
<el-anchor-link href="#description">
|
||||
公司详细介绍
|
||||
</el-anchor-link>
|
||||
<AnchorMenu :menu="anchorMenu" />
|
||||
</el-anchor>
|
||||
</el-affix>
|
||||
</div>
|
||||
@@ -202,6 +223,18 @@ onMounted(() => {
|
||||
.info-title {
|
||||
font-weight: 600;
|
||||
font-size: 18px;
|
||||
position: relative;
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
.info-title::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 2px;
|
||||
width: 4px;
|
||||
height: 25px;
|
||||
background-color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import type { CompanyListItem } from '@/types/company'
|
||||
import type { Company } from '@/types/company'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
@@ -18,7 +18,7 @@ const page = reactive<Pagination>({
|
||||
|
||||
const loading = ref<boolean>(true)
|
||||
|
||||
const companyList = ref<CompanyListItem[]>([])
|
||||
const companyList = ref<Company[]>([])
|
||||
|
||||
onMounted(() => {
|
||||
getCompanyList()
|
||||
@@ -50,7 +50,7 @@ function getCompanyList() {
|
||||
})
|
||||
}
|
||||
|
||||
function toDetail(data: CompanyListItem) {
|
||||
function toDetail(data: Company) {
|
||||
router.push({
|
||||
path: '/company/detail',
|
||||
query: {
|
||||
@@ -137,6 +137,7 @@ function toDetail(data: CompanyListItem) {
|
||||
layout="prev, pager, next"
|
||||
background
|
||||
size="large"
|
||||
@change="getCompanyList()"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -23,7 +23,7 @@ const menuList: NavMenuItem [] = [
|
||||
},
|
||||
{
|
||||
label: '成员设置',
|
||||
index: '/settings/info/company-user',
|
||||
index: '/settings/info/user',
|
||||
icon: 'hugeicons:user-settings-01',
|
||||
},
|
||||
],
|
||||
|
||||
@@ -1,124 +1,236 @@
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from 'vue'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import type { CompanyDetail } from '@/types/company'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import AreaSelect from '@/components/AreaSelect.vue'
|
||||
import IndustrySelect from '@/components/IndustrySelect.vue'
|
||||
import SvgIcon from '@/components/SvgIcon.vue'
|
||||
import WangEditor from '@/components/wang-editor/index.vue'
|
||||
import { getCompanyDetailApi, updateCompanyApi } from '@/request/api/company'
|
||||
import { useUserStore } from '@/store/user'
|
||||
import { uploadImage, uploadToAliyun } from '@/utils/file'
|
||||
import { validateEmail, validatePhone } from '@/utils/validate'
|
||||
|
||||
const form = reactive({
|
||||
name: '',
|
||||
region: '',
|
||||
date1: '',
|
||||
date2: '',
|
||||
delivery: false,
|
||||
type: [],
|
||||
resource: '',
|
||||
desc: '',
|
||||
const router = useRouter()
|
||||
const userStore = useUserStore()
|
||||
|
||||
const loading = reactive({
|
||||
save: false,
|
||||
})
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
const formRules = {
|
||||
name: [
|
||||
{ required: true, message: '公司名称不能为空', trigger: 'blur' },
|
||||
],
|
||||
industries: [
|
||||
{ required: true, message: '所属行业不能为空', trigger: 'blur' },
|
||||
],
|
||||
areas: [
|
||||
{ required: true, message: '公司地址不能为空', trigger: 'blur' },
|
||||
],
|
||||
email: [{ validator: emailValidator, trigger: 'blur' }],
|
||||
phone: [{ validator: phoneValidator, trigger: 'blur' }],
|
||||
}
|
||||
|
||||
function emailValidator(rule: any, value: any, callback: any) {
|
||||
// 未填写:直接通过
|
||||
if (!value) {
|
||||
callback()
|
||||
return
|
||||
}
|
||||
|
||||
if (!validateEmail(value)) {
|
||||
callback(new Error('邮箱格式不正确'))
|
||||
}
|
||||
else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
function phoneValidator(rule: any, value: any, callback: any) {
|
||||
// 未填写:直接通过
|
||||
if (!value) {
|
||||
callback()
|
||||
return
|
||||
}
|
||||
|
||||
if (!validatePhone(value)) {
|
||||
callback(new Error('手机号格式不正确'))
|
||||
}
|
||||
else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
const companyDetail = ref<CompanyDetail>({
|
||||
id: 0,
|
||||
name: '',
|
||||
areas: [],
|
||||
industries: [],
|
||||
logo: '',
|
||||
profile: '',
|
||||
phone: '',
|
||||
email: '',
|
||||
description: '',
|
||||
establishmentDate: '',
|
||||
users: [],
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
getCompanyDetail()
|
||||
})
|
||||
|
||||
function getCompanyDetail() {
|
||||
getCompanyDetailApi(userStore.userInfo.company.id).then((res) => {
|
||||
if (res.isSuccess) {
|
||||
companyDetail.value = res.data
|
||||
}
|
||||
else {
|
||||
ElMessage.error(res.message || '加载公司信息失败,请稍后再试')
|
||||
router.push('/')
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
ElMessage.error('加载公司信息失败,请稍后再试')
|
||||
})
|
||||
}
|
||||
|
||||
function handleUploadLogo() {
|
||||
uploadImage().then((data) => {
|
||||
uploadToAliyun(data.blob, data.name, data.size).then((res) => {
|
||||
companyDetail.value.logo = res.url
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
async function handleSubmit(formEl: FormInstance | undefined) {
|
||||
if (!formEl)
|
||||
return
|
||||
await formEl.validate((valid) => {
|
||||
if (valid) {
|
||||
loading.save = true
|
||||
updateCompanyApi({
|
||||
id: companyDetail.value.id,
|
||||
name: companyDetail.value.name,
|
||||
areas: companyDetail.value.areas,
|
||||
industries: companyDetail.value.industries,
|
||||
establishmentDate: companyDetail.value.establishmentDate,
|
||||
profile: companyDetail.value.profile,
|
||||
phone: companyDetail.value.phone,
|
||||
email: companyDetail.value.email,
|
||||
description: companyDetail.value.description,
|
||||
logo: companyDetail.value.logo,
|
||||
}).then((res) => {
|
||||
if (res.isSuccess) {
|
||||
userStore.userInfo.company.name = companyDetail.value.name
|
||||
userStore.userInfo.company.logo = companyDetail.value.logo
|
||||
|
||||
ElMessage.success('更新成功')
|
||||
}
|
||||
else {
|
||||
ElMessage.error(res.message || '更新失败,请稍后再试')
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
ElMessage.error('更新失败,请稍后再试')
|
||||
}).finally(() => {
|
||||
loading.save = false
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
const activeCollapseNames = ref(['1', '2', '3'])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="company-wrapper">
|
||||
<div class="form-item">
|
||||
<div class="form-header">
|
||||
<span class="form-title">
|
||||
基础信息
|
||||
</span>
|
||||
</div>
|
||||
<el-collapse v-model="activeCollapseNames" expand-icon-position="right">
|
||||
<el-collapse-item title="基础信息" name="1">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="companyDetail"
|
||||
:rules="formRules"
|
||||
label-width="auto"
|
||||
label-position="top"
|
||||
>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="24">
|
||||
<el-form-item>
|
||||
<el-avatar :size="86" :src="companyDetail.logo || '/no-avatar.png'" shape="square" />
|
||||
<div class="logo-upload">
|
||||
<el-button type="primary" @click="handleUploadLogo()">
|
||||
<SvgIcon icon="majesticons:cloud-upload-line" :size="18" style="margin-right: 4px;" />
|
||||
上传LOGO
|
||||
</el-button>
|
||||
<span>支持 JPG、PNG 格式,文件大小不超过 2MB</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="公司名称" prop="name">
|
||||
<el-input v-model="companyDetail.name" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="所属行业" prop="industries">
|
||||
<IndustrySelect v-model="companyDetail.industries" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="成立时间" prop="establishmentDate">
|
||||
<el-date-picker
|
||||
v-model="companyDetail.establishmentDate"
|
||||
type="date"
|
||||
placeholder="请选择公司成立时间"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="公司地址" prop="areas">
|
||||
<AreaSelect v-model="companyDetail.areas" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-form
|
||||
:model="form"
|
||||
label-width="auto"
|
||||
label-position="top"
|
||||
>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="24">
|
||||
<el-form-item>
|
||||
<el-avatar :size="86" shape="square" />
|
||||
<div class="logo-upload">
|
||||
<el-button type="primary" plain>
|
||||
上传LOGO
|
||||
</el-button>
|
||||
<span>支持 JPG、PNG 格式,文件大小不超过 2MB</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="公司名称">
|
||||
<el-input v-model="form.name" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="所属行业">
|
||||
<el-select v-model="form.region" placeholder="please select your zone">
|
||||
<el-option label="Zone one" value="shanghai" />
|
||||
<el-option label="Zone two" value="beijing" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="成立时间">
|
||||
<el-date-picker
|
||||
v-model="form.date1"
|
||||
type="date"
|
||||
placeholder="Pick a date"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="员工规模">
|
||||
<el-input v-model="form.desc" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="公司地址">
|
||||
<el-input v-model="form.name" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="公司详细地址">
|
||||
<el-input v-model="form.desc" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="联系电话">
|
||||
<el-input v-model="form.name" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="联系邮箱">
|
||||
<el-input v-model="form.desc" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-header">
|
||||
<span class="form-title">
|
||||
公司简介
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<el-form :model="form" label-width="auto">
|
||||
<el-form-item>
|
||||
<el-input v-model="form.name" type="textarea" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="form-item">
|
||||
<div class="form-header">
|
||||
<span class="form-title">
|
||||
公司介绍
|
||||
</span>
|
||||
</div>
|
||||
<WangEditor />
|
||||
</div>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="联系电话" prop="phone">
|
||||
<el-input v-model="companyDetail.phone" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="联系邮箱" prop="email">
|
||||
<el-input v-model="companyDetail.email" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="公司简介" name="2">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="companyDetail"
|
||||
:rules="formRules"
|
||||
label-width="auto"
|
||||
>
|
||||
<el-form-item prop="profile">
|
||||
<el-input v-model="companyDetail.profile" type="textarea" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="公司介绍" name="3">
|
||||
<WangEditor v-model="companyDetail.description" show-direcotry />
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
|
||||
<div class="form-footer">
|
||||
<el-button>重置</el-button>
|
||||
<el-button type="primary">
|
||||
<el-button @click="getCompanyDetail()">
|
||||
<SvgIcon icon="ic:baseline-refresh" :size="18" style="margin-right: 4px;" />
|
||||
重置
|
||||
</el-button>
|
||||
<el-button type="primary" :loading="loading.save" @click="handleSubmit(formRef)">
|
||||
<SvgIcon icon="majesticons:save-line" :size="18" style="margin-right: 4px;" />
|
||||
保存
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -129,33 +241,37 @@ const form = reactive({
|
||||
.company-wrapper {
|
||||
padding: 24px 32px;
|
||||
|
||||
.form-item {
|
||||
margin-bottom: 16px;
|
||||
.form-header {
|
||||
margin-bottom: 16px;
|
||||
.form-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.logo-upload {
|
||||
margin-left: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
span {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
:deep(.el-collapse) {
|
||||
border: none;
|
||||
}
|
||||
:deep(.el-collapse-item__wrap) {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
:deep(.el-collapse-item__header){
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
:deep(.el-collapse-item__content){
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.logo-upload {
|
||||
margin-left: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
span {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
.form-footer {
|
||||
margin-top: 16px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
:deep(.el-button){
|
||||
:deep(.el-button) {
|
||||
width: 120px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
<script lang="ts" setup>
|
||||
import type { CompanyUser, QueryCompanyUserParams } from '@/types/company/user'
|
||||
import { Delete, Plus, Refresh, Search } from '@element-plus/icons-vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
import { queryCompanyUserApi } from '@/request/api/company/user'
|
||||
import { useUserStore } from '@/store/user'
|
||||
|
||||
const userStore = useUserStore()
|
||||
const activeCollapseNames = ref(['1'])
|
||||
|
||||
const page = reactive<Pagination>({
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
})
|
||||
|
||||
const queryForm = reactive<QueryCompanyUserParams>({
|
||||
currentPage: page.current,
|
||||
pageSize: page.pageSize,
|
||||
|
||||
companyId: userStore.userInfo.company.id,
|
||||
name: '',
|
||||
phone: '',
|
||||
position: '',
|
||||
email: '',
|
||||
canuse: '',
|
||||
})
|
||||
|
||||
const canuseOptions = [
|
||||
{
|
||||
value: '',
|
||||
label: '全部',
|
||||
},
|
||||
{
|
||||
value: '1',
|
||||
label: '启用',
|
||||
},
|
||||
{
|
||||
value: '0',
|
||||
label: '禁用',
|
||||
},
|
||||
]
|
||||
const tableData = ref<CompanyUser[]>([])
|
||||
|
||||
onMounted(() => {
|
||||
getCompanyUser()
|
||||
})
|
||||
|
||||
function getCompanyUser() {
|
||||
queryCompanyUserApi({
|
||||
...queryForm,
|
||||
currentPage: page.current,
|
||||
pageSize: page.pageSize,
|
||||
}).then((res) => {
|
||||
if (res.isSuccess) {
|
||||
tableData.value = res.data.records
|
||||
page.total = res.data.total
|
||||
}
|
||||
else {
|
||||
ElMessage.error(res.message || '查询失败,请稍后再试')
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
ElMessage.error('查询失败,请稍后再试')
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="users-wrapper">
|
||||
<el-collapse v-model="activeCollapseNames">
|
||||
<el-collapse-item title="搜索条件" name="1">
|
||||
<el-form :model="queryForm">
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="名称">
|
||||
<el-input v-model="queryForm.name" placeholder="名称" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="职位">
|
||||
<el-input v-model="queryForm.position" placeholder="职位" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="邮箱">
|
||||
<el-input v-model="queryForm.email" placeholder="邮箱" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="手机">
|
||||
<el-input v-model="queryForm.phone" placeholder="手机" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="queryForm.canuse">
|
||||
<el-option
|
||||
v-for="item in canuseOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<el-form-item>
|
||||
<el-button :icon="Refresh">
|
||||
重置
|
||||
</el-button>
|
||||
<el-button type="primary" :icon="Search">
|
||||
查询
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
<div class="table-container">
|
||||
<div class="table-header">
|
||||
<div class="table-title">
|
||||
成员列表
|
||||
</div>
|
||||
|
||||
<div class="table-actions">
|
||||
<el-button type="primary" plain :icon="Plus">
|
||||
新增
|
||||
</el-button>
|
||||
<el-button type="danger" plain :icon="Delete">
|
||||
批量删除
|
||||
</el-button>
|
||||
<el-button :icon="Refresh">
|
||||
刷新
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-body-wrapper">
|
||||
<el-table :data="tableData" border stripe>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column prop="name" label="名称" align="center" />
|
||||
<el-table-column prop="position" label="职位" align="center" />
|
||||
<el-table-column prop="email" label="邮箱" align="center" />
|
||||
<el-table-column prop="phone" label="电话" align="center" />
|
||||
<el-table-column prop="canuse" label="启用" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.canuse === '1' ? 'primary' : 'warning'">
|
||||
启用
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button size="small">
|
||||
修改
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="scope.row.role !== 0"
|
||||
size="small"
|
||||
type="danger"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<div class="table-pagination">
|
||||
<el-pagination
|
||||
v-model:current-page="page.current"
|
||||
:page-size="page.pageSize"
|
||||
:total="page.total"
|
||||
layout="prev, pager, next"
|
||||
background
|
||||
size="large"
|
||||
@change="getCompanyUser()"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.users-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
padding: 16px 32px 0px 32px;
|
||||
|
||||
:deep(.el-collapse) {
|
||||
border: none;
|
||||
}
|
||||
:deep(.el-collapse-item__wrap) {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
:deep(.el-collapse-item__header) {
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
}
|
||||
:deep(.el-collapse-item__content) {
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.table-container {
|
||||
flex: 1;
|
||||
margin-top: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
|
||||
.table-body-wrapper {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
min-height: 0;
|
||||
|
||||
:deep(.el-table) {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.table-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 56px;
|
||||
.table-title {
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
:deep(.el-table__header) {
|
||||
.el-table__cell {
|
||||
background-color: #f5f7fa;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
.table-pagination {
|
||||
height: 56px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user