mirror of
https://gitee.com/niucloud-team/niucloud.git
synced 2025-12-11 01:22:49 +00:00
fix admin
This commit is contained in:
parent
08d14372e1
commit
8cb683f8fe
2
admin/components.d.ts
vendored
2
admin/components.d.ts
vendored
@ -62,6 +62,8 @@ declare module '@vue/runtime-core' {
|
||||
ElRow: typeof import('element-plus/es')['ElRow']
|
||||
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
|
||||
ElSelect: typeof import('element-plus/es')['ElSelect']
|
||||
ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
|
||||
ElSkeletonItem: typeof import('element-plus/es')['ElSkeletonItem']
|
||||
ElSlider: typeof import('element-plus/es')['ElSlider']
|
||||
ElStatistic: typeof import('element-plus/es')['ElStatistic']
|
||||
ElStep: typeof import('element-plus/es')['ElStep']
|
||||
|
||||
@ -95,3 +95,10 @@ export function syncSiteWeapp(params: Record<string, any>) {
|
||||
export function getAuthRecord(params: Record<string, any>) {
|
||||
return request.get('wxoplatform/authorization/record', { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消授权
|
||||
*/
|
||||
export function cancelAuthorization(params: Record<string, any>) {
|
||||
return request.post('wxoplatform/authorization/cancel', params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
@ -45,5 +45,11 @@
|
||||
"failReason": "失败原因",
|
||||
"appVersionReleaseTips": "发布后无法再对该版本进行修改,确定要发布该版本吗?",
|
||||
"appVersionDeleteTips": "确定要删除该版本吗?",
|
||||
"upgradeType": "升级方式"
|
||||
"upgradeType": "升级方式",
|
||||
"seeBuildLog": "查看打包日志",
|
||||
"buildLog": "打包日志",
|
||||
"authTips": "上传代码需先绑定授权码,如果已有授权请先进行绑定,没有授权可到niucloud官网购买云服务之后再进行操作",
|
||||
"toBind": "绑定授权",
|
||||
"toNiucloud": "去niucloud官网",
|
||||
"siteAuthTips": "上传代码需先绑定授权码,请联系平台管理员进行绑定"
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
<el-button type="primary" class="w-[100px]" @click="addEvent">
|
||||
{{ t('addMenu') }}
|
||||
</el-button>
|
||||
<el-button class="w-[100px]" @click="refreshMenu">
|
||||
<el-button class="w-[100px]" :loading="refreshLoading" @click="refreshMenu">
|
||||
{{ t('initializeMenu') }}
|
||||
</el-button>
|
||||
</div>
|
||||
@ -82,6 +82,7 @@ const getMenuList = () => {
|
||||
}
|
||||
getMenuList()
|
||||
// 重置菜单
|
||||
const refreshLoading = ref(false)
|
||||
const refreshMenu = () => {
|
||||
ElMessageBox.confirm(h('div', null, [
|
||||
h('p', null, t('initializeMenuTipsOne')),
|
||||
@ -93,9 +94,11 @@ const refreshMenu = () => {
|
||||
// type: 'warning'
|
||||
}
|
||||
).then(() => {
|
||||
refreshLoading.value = true
|
||||
menuRefresh({}).then(res => {
|
||||
location.reload()
|
||||
refreshLoading.value = false
|
||||
}).catch(() => {
|
||||
refreshLoading.value = false
|
||||
})
|
||||
}).catch(() => {
|
||||
})
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
</el-alert>
|
||||
|
||||
<div class="mt-[20px]">
|
||||
<el-button type="primary" @click="addEvent">{{ t('addAppVersion') }}</el-button>
|
||||
<el-button type="primary" @click="addEvent" :disabled="loading">{{ t('addAppVersion') }}</el-button>
|
||||
</div>
|
||||
|
||||
<div class="mt-[10px]">
|
||||
@ -41,7 +41,11 @@
|
||||
|
||||
<el-table-column prop="platform_name" :label="t('platform')" min-width="120" :show-overflow-tooltip="true"/>
|
||||
|
||||
<el-table-column prop="status_name" :label="t('status')" min-width="120" :show-overflow-tooltip="true"/>
|
||||
<el-table-column prop="status_name" :label="t('status')" min-width="120" align="center" :show-overflow-tooltip="true">
|
||||
<template #default="{ row }">
|
||||
<el-button link :loading="row.status == 'creating'">{{ row.status_name }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="status" :label="t('isForcedUpgradeTitle')" min-width="120" align="center" :show-overflow-tooltip="true">
|
||||
<template #default="{ row }">
|
||||
@ -63,7 +67,7 @@
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link v-if="row.release_time == 0" @click="editEvent(row)">{{ t('edit') }}</el-button>
|
||||
<el-button type="primary" link v-if="row.status == 'upload_success'" @click="releaseEvent(row)">{{ t('release') }}</el-button>
|
||||
<el-button type="primary" link v-if="row.status == 'create_fail'" @click="handleFailReason(row)">{{ t('failReason') }}</el-button>
|
||||
<el-button type="primary" link v-if="row.status == 'creating'" @click="seeBuildLog(row)">{{ t('seeBuildLog') }}</el-button>
|
||||
<el-button type="primary" link v-if="row.package_path && row.upgrade_type != 'market'" @click="downloadEvent(row)">{{ t('download') }}</el-button>
|
||||
<el-button type="primary" link @click="deleteEvent(row.id)">{{ t('delete') }}</el-button>
|
||||
</template>
|
||||
@ -86,21 +90,31 @@
|
||||
</el-scrollbar>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<el-dialog v-model="showDialog" :title="t('buildLog')" width="850px" :close-on-click-modal="false" :close-on-press-escape="false" :before-close="dialogClose">
|
||||
<div class="h-[370px]">
|
||||
<terminal ref="terminalRef" :name="`upgrade-${terminalId}`" context="" :init-log="null" :show-header="false" :show-log-time="true" @exec-cmd="onExecCmd" />
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { img } from '@/utils/common'
|
||||
import { img, getAppType } from '@/utils/common'
|
||||
import { ElMessageBox, FormInstance } from 'element-plus'
|
||||
import { getVersionList, getBuildLog, deleteVersion, releaseVersion } from '@/app/api/app'
|
||||
import Edit from '@/app/views/channel/app/components/app-version-edit.vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { Terminal, TerminalFlash } from 'vue-web-terminal'
|
||||
import 'vue-web-terminal/lib/theme/dark.css'
|
||||
import { getAuthInfo } from '@/app/api/module'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
const activeName = ref('/channel/app/version')
|
||||
|
||||
const terminalRef: any = ref(null)
|
||||
const appVersionTable = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
@ -111,6 +125,18 @@ const appVersionTable = reactive({
|
||||
platfrom: ''
|
||||
}
|
||||
})
|
||||
const showDialog = ref(false)
|
||||
const loading = ref(true)
|
||||
const authCode = ref('')
|
||||
|
||||
getAuthInfo().then(res => {
|
||||
if (res.data.data && res.data.data.auth_code) {
|
||||
authCode.value = res.data.data.auth_code
|
||||
}
|
||||
loading.value = false
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
|
||||
const handleClick = (val: any) => {
|
||||
router.push({ path: activeName.value })
|
||||
@ -146,6 +172,10 @@ const editAppVersionDialog: Record<string, any> | null = ref(null)
|
||||
* 添加app版本管理
|
||||
*/
|
||||
const addEvent = () => {
|
||||
if (!authCode.value) {
|
||||
authElMessageBox()
|
||||
return
|
||||
}
|
||||
editAppVersionDialog.value.setFormData()
|
||||
editAppVersionDialog.value.showDialog = true
|
||||
}
|
||||
@ -192,20 +222,70 @@ const releaseEvent = (data: any) => {
|
||||
})
|
||||
}
|
||||
|
||||
let buildLog = []
|
||||
const getAppBuildLogFn = (key: string) => {
|
||||
getBuildLog(key).then(res => {
|
||||
if (res.data) {
|
||||
if (res.data.status == '') {
|
||||
if (showDialog.value) {
|
||||
if (!buildLog.length) {
|
||||
terminalRef.value.execute('clear')
|
||||
terminalRef.value.execute('开始打包')
|
||||
}
|
||||
res.data.build_log.data[0].forEach((item) => {
|
||||
if (!buildLog.includes(item.action)) {
|
||||
terminalRef.value.pushMessage({ content: `${item.action}` })
|
||||
buildLog.push(item.action)
|
||||
}
|
||||
})
|
||||
}
|
||||
setTimeout(() => {
|
||||
getAppBuildLogFn(key)
|
||||
}, 2000)
|
||||
} else {
|
||||
if (res.data.status == 'fail' && showDialog.value) {
|
||||
terminalRef.value.pushMessage({ content: res.data.fail_reason, class: 'error' })
|
||||
} else {
|
||||
showDialog.value = false
|
||||
}
|
||||
loadAppVersionList()
|
||||
buildLog = []
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const seeBuildLog = () => {
|
||||
showDialog.value = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 升级进度动画
|
||||
*/
|
||||
let flashInterval: any = null
|
||||
const terminalFlash = new TerminalFlash()
|
||||
const onExecCmd = (key, command, success, failed, name) => {
|
||||
if (command == '开始打包') {
|
||||
success(terminalFlash)
|
||||
const frames = makeIterator(['/', '——', '\\', '|'])
|
||||
flashInterval = setInterval(() => {
|
||||
terminalFlash.flush('> ' + frames.next().value)
|
||||
}, 150)
|
||||
}
|
||||
}
|
||||
|
||||
const makeIterator = (array: string[]) => {
|
||||
let nextIndex = 0
|
||||
return {
|
||||
next () {
|
||||
if (nextIndex + 1 == array.length) {
|
||||
nextIndex = 0
|
||||
}
|
||||
return { value: array[nextIndex++] }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const failReason = ref('')
|
||||
const failReasonDialogVisible = ref(false)
|
||||
const handleFailReason = (data: any) => {
|
||||
@ -222,6 +302,28 @@ const resetForm = (formEl: FormInstance | undefined) => {
|
||||
formEl.resetFields()
|
||||
loadAppVersionList()
|
||||
}
|
||||
|
||||
const authElMessageBox = () => {
|
||||
if (getAppType() == 'admin') {
|
||||
ElMessageBox.confirm(
|
||||
t('authTips'),
|
||||
t('warning'),
|
||||
{
|
||||
distinguishCancelAndClose: true,
|
||||
confirmButtonText: t('toBind'),
|
||||
cancelButtonText: t('toNiucloud')
|
||||
}
|
||||
).then(() => {
|
||||
router.push({ path: '/app/authorize' })
|
||||
}).catch((action: string) => {
|
||||
if (action === 'cancel') {
|
||||
window.open('https://www.niucloud.com/app')
|
||||
}
|
||||
})
|
||||
} else {
|
||||
ElMessageBox.alert(t('siteAuthTips'), t('warning'))
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -45,6 +45,24 @@
|
||||
<template v-if="oplatformConfig.app_id && oplatformConfig.app_secret">
|
||||
<el-button type="primary" @click="router.push('/channel/weapp/config')">{{ weappConfig.app_id ? t("seeConfig") : t("weappSettingBtn") }}</el-button>
|
||||
<el-button type="primary" plain @click="authBindWeapp">{{ weappConfig.is_authorization ? t("refreshAuth") : t("authWeapp") }}</el-button>
|
||||
<template v-if="weappConfig.is_authorization">
|
||||
<el-button type="primary" plain @click="cencelAuth" >{{ t("取消授权") }}</el-button>
|
||||
<el-tooltip class="box-item" effect="light" placement="top">
|
||||
<el-icon color="#666" size="15px" class="ml-[5px]">
|
||||
<QuestionFilled />
|
||||
</el-icon>
|
||||
<template #content>
|
||||
<div>
|
||||
<div>
|
||||
非通过API创建的开放平台账号需要登录微信公众品平台进行取消授权操作
|
||||
</div>
|
||||
<div>
|
||||
微信公众平台: <a class="ml-[3px] text-[var(--el-color-primary)]" target="_blank" href="https://mp.weixin.qq.com/cgi-bin/loginpage">https://mp.weixin.qq.com/cgi-bin/loginpage</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-button type="primary" @click="router.push('/channel/weapp/config')">{{ t("weappSettingBtn") }}</el-button>
|
||||
@ -107,9 +125,10 @@ import { onMounted, onUnmounted, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { img } from '@/utils/common'
|
||||
import { getWeappConfig } from '@/app/api/weapp'
|
||||
import { getAuthorizationUrl } from '@/app/api/wxoplatform'
|
||||
import { getAuthorizationUrl ,cancelAuthorization} from '@/app/api/wxoplatform'
|
||||
import { getWxoplatform } from '@/app/api/sys'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@ -158,6 +177,24 @@ const authBindWeapp = () => {
|
||||
window.open(data)
|
||||
})
|
||||
}
|
||||
const repeat = ref(false)
|
||||
const cencelAuth = () => {
|
||||
ElMessageBox.confirm(t('确认取消授权吗?'), t('warning'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
cancelButtonText: t('cancel'),
|
||||
type: 'warning'
|
||||
}
|
||||
).then(() => {
|
||||
if (repeat.value) return
|
||||
repeat.value = true
|
||||
cancelAuthorization({}).then(() => {
|
||||
repeat.value = false
|
||||
}).catch(() => {
|
||||
repeat.value = false
|
||||
})
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@ -14,13 +14,32 @@
|
||||
</el-tabs>
|
||||
|
||||
<div class="mt-[20px]" v-if="!weappConfig.is_authorization">
|
||||
<el-button type="primary" @click="insert" :loading="uploading" :disabled="loading">{{ t('cloudRelease') }}</el-button>
|
||||
<el-button type="primary" @click="openDialog" :loading="uploading" :disabled="loading">{{ t('cloudRelease') }}</el-button>
|
||||
<el-button @click="localInsert" :disabled="loading">{{ t('localRelease') }}</el-button>
|
||||
</div>
|
||||
<div class="mt-[20px]" v-else>
|
||||
<el-button type="primary" @click="againUpload" :loading="uploading" :disabled="loading">{{ t('uploadWeapp') }}</el-button>
|
||||
</div>
|
||||
|
||||
<div class="text-[14px] mt-[15px]">
|
||||
<div class="flex items-center">
|
||||
<div v-if="weappTableData.version_info.release_version">
|
||||
线上版本: <span class="mr-10 text-primary">{{ weappTableData.version_info.release_version }}</span>
|
||||
</div>
|
||||
<div v-if="weappTableData.version_info.release_time">
|
||||
发布时间: <span >{{ weappTableData.version_info.release_time }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div v-if="weappTableData.version_info.exp_version" class="mt-2">
|
||||
体验版本: <span class="mr-10 text-primary">{{ weappTableData.version_info.exp_version }}</span>
|
||||
</div>
|
||||
<div v-if="weappTableData.version_info.exp_time" class="mt-2">
|
||||
过期时间: <span >{{ weappTableData.version_info.exp_time }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-table class="mt-[15px]" :data="weappTableData.data" v-loading="weappTableData.loading" size="default">
|
||||
<template #empty>
|
||||
<span>{{ t('emptyData') }}</span>
|
||||
@ -71,6 +90,42 @@
|
||||
<el-button @click="dialogVisible = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="insert">
|
||||
{{ t('confirm') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-dialog v-model="cloudVersionDialogVisible" :title="t('codeDownTwoDesc')" width="600px" :before-close="handleCloseCloudVersion">
|
||||
<el-form ref="cloudRuleFormRef" :model="form" :rules="formRules" label-width="120px">
|
||||
<el-form-item prop="type" :label="t('版本号类型')">
|
||||
<div>
|
||||
<el-radio-group v-model="form.type">
|
||||
<el-radio :label="1">{{ t('默认') }}</el-radio>
|
||||
<el-radio :label="2">{{ t('自定义') }}</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="mt-[10px] text-[12px] text-[#999] leading-[20px]">默认为列表版本号递增,自定义则为手动输入版本号进行上传,首位必须大于1</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item prop="version" :label="t('code')" v-if="form.type == 2">
|
||||
<div class="flex items-end">
|
||||
<el-form-item prop="code1">
|
||||
<el-input v-model.number="form.code1" class="!w-[70px]" :placeholder="t('codePlaceholder')" />
|
||||
</el-form-item>
|
||||
<span class="mx-[10px]">.</span>
|
||||
<el-form-item prop="code2">
|
||||
<el-input v-model.number="form.code2" class="!w-[70px]" :placeholder="t('codePlaceholder')" />
|
||||
</el-form-item>
|
||||
<span class="mx-[10px]">.</span>
|
||||
<el-form-item prop="code3">
|
||||
<el-input v-model.number="form.code3" class="!w-[70px]" :placeholder="t('codePlaceholder')" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="handleCloseCloudVersion">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="save">
|
||||
{{ t('confirm') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
@ -116,19 +171,22 @@ const weappTableData:{
|
||||
limit: number,
|
||||
total: number,
|
||||
loading: boolean,
|
||||
data: AnyObject
|
||||
data: AnyObject,
|
||||
version_info: AnyObject
|
||||
} = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: false,
|
||||
data: []
|
||||
data: [],
|
||||
version_info: {}
|
||||
})
|
||||
const form = ref({
|
||||
desc: '',
|
||||
code: '',
|
||||
path: '',
|
||||
content: ''
|
||||
type:1,
|
||||
version: '',
|
||||
code1: '1',
|
||||
code2: '0',
|
||||
code3: '0'
|
||||
})
|
||||
const uploadSuccessShowDialog = ref(false)
|
||||
const authCode = ref('')
|
||||
@ -161,7 +219,62 @@ const handleClick = (val: any) => {
|
||||
router.push({ path: activeName.value })
|
||||
}
|
||||
const ruleFormRef = ref<any>(null)
|
||||
|
||||
const cloudRuleFormRef = ref<any>(null)
|
||||
// 表单校验规则
|
||||
const formRules = reactive({
|
||||
code1: [
|
||||
{
|
||||
validator: (rule: any, value: number, callback: any) => {
|
||||
if (value < 1) {
|
||||
callback(new Error(t('必须大于1')));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
code2: [
|
||||
{
|
||||
validator: (rule: any, value: number, callback: any) => {
|
||||
if (value < 0) {
|
||||
callback(new Error(t('必须大于0')));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
code3: [
|
||||
{
|
||||
validator: (rule: any, value: number, callback: any) => {
|
||||
if (value < 0) {
|
||||
callback(new Error(t('必须大于0')));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
version:[
|
||||
{
|
||||
required: true,
|
||||
validator: (rule: any, value: string, callback: any) => {
|
||||
if(form.value.type == 2){
|
||||
if(!form.value.code1 || !form.value.code2 || !form.value.code3){
|
||||
callback(new Error(t('请填写版本号')));
|
||||
}else{
|
||||
callback();
|
||||
}
|
||||
}else{
|
||||
callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
/**
|
||||
* 获取版本列表
|
||||
*/
|
||||
@ -177,6 +290,7 @@ const getWeappVersionListFn = (page: number = 1) => {
|
||||
weappTableData.data = res.data.data
|
||||
weappTableData.total = res.data.total
|
||||
if (page == 1 && weappTableData.data.length && weappTableData.data[0].status == 0) getWeappUploadLogFn(weappTableData.data[0].task_key)
|
||||
weappTableData.version_info = res.data.version_info
|
||||
}).catch(() => {
|
||||
weappTableData.loading = false
|
||||
})
|
||||
@ -184,10 +298,56 @@ const getWeappVersionListFn = (page: number = 1) => {
|
||||
|
||||
getWeappVersionListFn()
|
||||
|
||||
const openDialog = () => {
|
||||
if (!authCode.value) {
|
||||
authElMessageBox()
|
||||
return
|
||||
}
|
||||
if (!weappConfig.value.app_id) {
|
||||
configElMessageBox()
|
||||
return
|
||||
}
|
||||
form.value = {
|
||||
type:1,
|
||||
version: '',
|
||||
code1: '1',
|
||||
code2: '0',
|
||||
code3: '0'
|
||||
}
|
||||
cloudVersionDialogVisible.value = true
|
||||
}
|
||||
const handleClose = () => {
|
||||
ruleFormRef.value.clearValidate()
|
||||
}
|
||||
|
||||
const cloudVersionDialogVisible = ref(false)
|
||||
const handleCloseCloudVersion = () => {
|
||||
cloudVersionDialogVisible.value = false
|
||||
form.value = {
|
||||
type:1,
|
||||
version: '',
|
||||
code1: '1',
|
||||
code2: '0',
|
||||
code3: '0'
|
||||
}
|
||||
}
|
||||
|
||||
const save = () => {
|
||||
cloudRuleFormRef.value.validate((valid: boolean) => {
|
||||
if (valid) {
|
||||
if (form.value.type == 2) {
|
||||
form.value.version = `${form.value.code1}.${form.value.code2}.${form.value.code3}`
|
||||
}
|
||||
delete form.value.code1
|
||||
delete form.value.code2
|
||||
delete form.value.code3
|
||||
delete form.value.type
|
||||
cloudVersionDialogVisible.value = false
|
||||
insert()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const uploading = ref(false)
|
||||
const insert = () => {
|
||||
if (!authCode.value) {
|
||||
@ -206,7 +366,7 @@ const insert = () => {
|
||||
|
||||
setWeappVersion(form.value).then(res => {
|
||||
getWeappVersionListFn()
|
||||
getWeappPreviewImage()
|
||||
getWeappPreviewImage()
|
||||
uploading.value = false
|
||||
}).catch(() => {
|
||||
uploading.value = false
|
||||
|
||||
@ -63,6 +63,20 @@
|
||||
<el-switch v-model="diyStore.global.bottomTabBar.isShow" />
|
||||
<div class="text-sm text-gray-400">{{ t('tabbarSwitchTips') }}</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('选择导航')">
|
||||
<tabbar-select-popup v-model="diyStore.global.bottomTabBar.designNav" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap" v-if="diyStore.global.copyright.control">
|
||||
<h3 class="mb-[10px]">{{ t('版权信息内容') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('版权信息')" class="display-block">
|
||||
<el-switch v-model="diyStore.global.copyright.isShow" />
|
||||
<div class="text-sm text-gray-400">{{ t('此处控制当前页面版权信息是否显示') }}</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="edit-attr-item-wrap">
|
||||
@ -178,6 +192,7 @@ import { t } from '@/lang'
|
||||
import { watch, ref } from 'vue'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import { img } from '@/utils/common'
|
||||
import tabbarSelectPopup from './tabbar-select-popup.vue'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
|
||||
|
||||
211
admin/src/app/views/diy/components/tabbar-select-popup.vue
Normal file
211
admin/src/app/views/diy/components/tabbar-select-popup.vue
Normal file
@ -0,0 +1,211 @@
|
||||
<template>
|
||||
<div>
|
||||
<div @click="show">
|
||||
<slot>
|
||||
<el-input v-model="selectData.title" :placeholder="t('请选择底部导航')" readonly class="link-input">
|
||||
<template #suffix>
|
||||
<div @click.stop="clear">
|
||||
<el-icon v-if="selectData.key">
|
||||
<Close />
|
||||
</el-icon>
|
||||
<el-icon v-else>
|
||||
<ArrowRight />
|
||||
</el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</el-input>
|
||||
</slot>
|
||||
</div>
|
||||
<el-dialog v-model="showDialog" :title="t('底部导航选择')" width="850px" :destroy-on-close="true" :close-on-click-modal="false">
|
||||
<el-table class="" :data="tableData.data" size="large" v-loading="tableData.loading" height="400px">
|
||||
<template #empty>
|
||||
<span>{{ !tableData.loading ? t('emptyData') : '' }}</span>
|
||||
</template>
|
||||
<el-table-column min-width="7%">
|
||||
<template #default="{ row }">
|
||||
<el-checkbox v-model="row.checked" @change="handleCheckChange($event,row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="title" :label="t('title')" min-width="30%" >
|
||||
<template #default="{ row }">
|
||||
<span>{{ row.info.title }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="key" :label="t('key')" min-width="30%"/>
|
||||
|
||||
<el-table-column :label="t('type')" min-width="30%">
|
||||
<template #default="{ row }">
|
||||
<span>{{ row.info.type === 'app' ? t('app') : t('addon') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="mt-[16px] flex justify-end">
|
||||
<el-pagination v-model:current-page="tableData.page" v-model:page-size="tableData.limit"
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="tableData.total"
|
||||
@size-change="loadBottomNavList()" @current-change="loadBottomNavList" />
|
||||
</div>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="save">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { t } from '@/lang'
|
||||
import { ref, reactive, nextTick,computed } from 'vue'
|
||||
import { FormInstance, ElMessage } from "element-plus";
|
||||
import { getDiyBottomList } from '@/app/api/diy'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
|
||||
const prop = defineProps({
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {
|
||||
key: '',
|
||||
title: '',
|
||||
}
|
||||
}
|
||||
},
|
||||
ignore: {
|
||||
type: Array,
|
||||
default: []
|
||||
}
|
||||
})
|
||||
|
||||
const clear = () => {
|
||||
selectData.value = {
|
||||
key: '',
|
||||
title: ''
|
||||
}
|
||||
setTimesSelected()
|
||||
}
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'confirm', 'success'])
|
||||
|
||||
const selectData: any = computed({
|
||||
get() {
|
||||
return prop.modelValue
|
||||
},
|
||||
set(value) {
|
||||
emit('update:modelValue', value)
|
||||
}
|
||||
})
|
||||
const searchFormRef = ref<FormInstance>()
|
||||
|
||||
const timeListTableRef = ref()
|
||||
const showDialog = ref(false)
|
||||
const show = () => {
|
||||
showDialog.value = true
|
||||
loadBottomNavList()
|
||||
}
|
||||
|
||||
const tableData: any = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
})
|
||||
|
||||
// 获取自定义页面列表
|
||||
const loadBottomNavList = (page: number = 1) => {
|
||||
tableData.loading = true
|
||||
tableData.page = page
|
||||
|
||||
getDiyBottomList({}).then(res => {
|
||||
tableData.loading = false
|
||||
|
||||
const len = Math.ceil(res.data.length / tableData.limit)
|
||||
const data = cloneDeep(res.data)
|
||||
const dataGather = []
|
||||
for (let i = 0; i < len; i++) {
|
||||
dataGather[i] = data.splice(0, tableData.limit)
|
||||
}
|
||||
tableData.data = dataGather[tableData.page - 1]
|
||||
tableData.data.forEach((item: any) => {
|
||||
item.checked = item.key == selectData.value.key
|
||||
})
|
||||
tableData.total = res.data.length
|
||||
setTimesSelected();
|
||||
}).catch(() => {
|
||||
tableData.loading = false
|
||||
})
|
||||
}
|
||||
|
||||
loadBottomNavList()
|
||||
const handleCheckChange = (isSelect: any, row: any) => {
|
||||
if (isSelect) {
|
||||
selectData.value = {
|
||||
key: row.key,
|
||||
title: row.info.title
|
||||
};
|
||||
} else {
|
||||
selectData.value = {
|
||||
key: '',
|
||||
title: ''
|
||||
};
|
||||
}
|
||||
setTimesSelected()
|
||||
}
|
||||
|
||||
// // 表格设置选中状态
|
||||
const setTimesSelected = () => {
|
||||
nextTick(() => {
|
||||
for (let i = 0; i < tableData.data.length; i++) {
|
||||
tableData.data[i].checked = false
|
||||
if (selectData.value.key == tableData.data[i].key) {
|
||||
tableData.data[i].checked = true
|
||||
selectData.value.key = tableData.data[i].key
|
||||
selectData.value.title = tableData.data[i].info.title
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const resetForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
formEl.resetFields()
|
||||
|
||||
loadBottomNavList()
|
||||
}
|
||||
|
||||
const save = () => {
|
||||
if (selectData.value.key == '') {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: `${ t('请选择底部导航') }`
|
||||
})
|
||||
return;
|
||||
}
|
||||
selectData.value = {
|
||||
key: selectData.value.key,
|
||||
title: selectData.value.title
|
||||
}
|
||||
showDialog.value = false;
|
||||
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
show,
|
||||
showDialog,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.form-item-wrap {
|
||||
margin-right: 10px !important;
|
||||
margin-bottom: 10px !important;
|
||||
|
||||
&.last-child {
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="flex items-center justify-center">
|
||||
<el-card class="box-card !border-none profile-data w-[1280px] mt-[20px] loading-box" shadow="never" v-loading="loading" >
|
||||
<el-card class="box-card !border-none profile-data w-[1280px] mt-[20px] loading-box" shadow="never">
|
||||
<!-- <div> -->
|
||||
<div class="box-border">
|
||||
<div class="bg-[#fff] mb-[20px] rounded-[6px] relative banner-box" v-if="showBanner" @mouseenter="hovering = 'banner'" @mouseleave="hovering = ''">
|
||||
@ -11,7 +11,21 @@
|
||||
</span>
|
||||
<div class="flex h-[156px]">
|
||||
<div class="w-full h-full ">
|
||||
<el-carousel :interval="3000" height="156px" class="rounded-[6px]">
|
||||
<!-- 轮播图加载中 -->
|
||||
<div v-if="loading" class="skeleton-loading h-full flex items-center justify-center">
|
||||
<el-skeleton
|
||||
style="width: 100%"
|
||||
:loading="loading"
|
||||
animated
|
||||
:throttle="{ leading: 500, initVal: true }"
|
||||
>
|
||||
<template #template>
|
||||
<el-skeleton-item variant="image" style="width: 100%; height: 156px;" />
|
||||
</template>
|
||||
|
||||
</el-skeleton>
|
||||
</div>
|
||||
<el-carousel v-else :interval="3000" height="156px" class="rounded-[6px]">
|
||||
<!-- <el-carousel-item >
|
||||
<div class="h-full index-carousel" @click="toApplication">
|
||||
<img :src="img('static/resource/images/banner_1.png')" alt="" class="w-full h-full cursor-pointer">
|
||||
@ -99,86 +113,121 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="showNiuCloud && appList.length > 0" class="mt-[50px] relative" @mouseenter="hovering = 'niuCloud'" @mouseleave="hovering = ''">
|
||||
<span class="absolute right-0 top-[-5px] text-[#999] hover:text-red-500 cursor-pointer z-10" v-if="hovering === 'niuCloud'">
|
||||
<el-icon class="icon" :size="20" color="#7b7b7b" @click="closeModule('niuCloud')">
|
||||
<CircleCloseFilled />
|
||||
</el-icon>
|
||||
</span>
|
||||
<p class="text-[18px] text-[#1D1F3A]">NIUCLOUD生态精选应用推荐</p>
|
||||
<!-- <div class="flex justify-between mt-[20px]">
|
||||
<div class="flex">
|
||||
<div :class="['flex items-center text-[14px] h-[32px] rounded-full px-[20px] mr-[24px] text-[#fff] bg-[#AFB1C8] hover:bg-[#7B7E9A] cursor-pointer', { '!text-[#fff] !bg-[#7B7E9A]': activeName === 'installed' }]" @click="activeNameTabFn('installed')">{{ t("全部") }}</div>
|
||||
<div :class="['flex items-center text-[14px] h-[32px] rounded-full px-[20px] mr-[24px] text-[#fff] bg-[#AFB1C8] hover:bg-[#7B7E9A] cursor-pointer', { '!text-[#fff] !bg-[#7B7E9A]': activeName === 'uninstalled' }]" @click="activeNameTabFn('uninstalled')">{{ t("商城") }}</div>
|
||||
<div :class="['flex items-center text-[14px] h-[32px] rounded-full px-[20px] mr-[24px] text-[#fff] bg-[#AFB1C8] hover:bg-[#7B7E9A] cursor-pointer', { '!text-[#fff] !bg-[#7B7E9A]': activeName === 'all' }]" @click="activeNameTabFn('all')">{{ t("数字人") }}</div>
|
||||
<div :class="['flex items-center text-[14px] h-[32px] rounded-full px-[20px] mr-[24px] text-[#fff] bg-[#AFB1C8] hover:bg-[#7B7E9A] cursor-pointer', { '!text-[#fff] !bg-[#7B7E9A]': activeName === 'all1' }]" @click="activeNameTabFn('all1')">{{ t("拼团") }}</div>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="mt-[20px]">
|
||||
<div class="grid grid-cols-5 gap-4">
|
||||
<div v-for="(item,index) in appList.slice(0,5)" :key="index" @click="toApplicationDetail(item)" class="bg-[#EDEEF4] rounded-[8px] overflow-hidden text-[#666] cursor-pointer hover:shadow-xl transition-shadow duration-300 border-[1px] border-[#EDEEF4]">
|
||||
<img :src="img(item.app_logo)" alt="" class="w-full rounded-t-[6px]" >
|
||||
<div class="bg-[#fff] p-[10px]">
|
||||
<div class="text-[16px] text-[#1D1F3A] mb-[10px]">
|
||||
<span class="using-hidden">{{ item.app_name }}</span>
|
||||
</div>
|
||||
<div class="text-[12px] text-[#4F516D]">
|
||||
<span class="using-hidden">{{ item.app_desc }}</span>
|
||||
</div>
|
||||
<div class="text-[12px] mt-[20px] flex justify-between">
|
||||
<div class="flex items-center">
|
||||
<img :src="img(item.developer.headimg)" alt="" class="w-[18px] h-[18px] rounded-full mr-[6px]" v-if="item.developer.headimg">
|
||||
<img src="@/app/assets/images/member_head.png" alt="" class="w-[18px] h-[18px] rounded-full mr-[6px]" v-else>
|
||||
<span class="text-[#4F516D] text-[12px] using-hidden">{{ item.developer.nickname }}</span>
|
||||
<template v-if="loading">
|
||||
<div v-if="showNiuCloud" class="mt-[50px] relative" @mouseenter="hovering = 'niuCloud'" @mouseleave="hovering = ''">
|
||||
<span class="absolute right-0 top-[-5px] text-[#999] hover:text-red-500 cursor-pointer z-10" v-if="hovering === 'niuCloud'">
|
||||
<el-icon class="icon" :size="20" color="#7b7b7b" @click="closeModule('niuCloud')">
|
||||
<CircleCloseFilled />
|
||||
</el-icon>
|
||||
</span>
|
||||
<p class="text-[18px] text-[#1D1F3A]">NIUCLOUD生态精选应用推荐</p>
|
||||
<!-- 应用列表加载中 -->
|
||||
<div v-if="loading" class="mt-[20px] grid grid-cols-5 gap-4">
|
||||
<div v-for="i in 5" :key="i" class="bg-[#EDEEF4] rounded-[8px] overflow-hidden">
|
||||
<el-skeleton
|
||||
style="width: 240px"
|
||||
:loading="loading"
|
||||
animated
|
||||
:throttle="{ leading: 500, initVal: true }"
|
||||
>
|
||||
<template #template>
|
||||
<el-skeleton-item variant="image" style="width: 240px; height: 265px" />
|
||||
<div style="padding: 14px">
|
||||
<el-skeleton-item variant="h3" style="width: 50%" />
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-items: space-between;
|
||||
margin-top: 16px;
|
||||
height: 16px;
|
||||
"
|
||||
>
|
||||
<el-skeleton-item variant="text" style="margin-right: 16px" />
|
||||
<el-skeleton-item variant="text" style="width: 30%" />
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="mr-[10px]">
|
||||
<span class="iconfont iconchakan !text-[12px] mr-[8px] !text-[#4F516D]"></span>
|
||||
<span class="text-[#4F516D] text-[12px]">{{ item.visit_num}}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</el-skeleton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div v-if="showNiuCloud && appList.length >0" class="mt-[50px] relative" @mouseenter="hovering = 'niuCloud'" @mouseleave="hovering = ''">
|
||||
<span class="absolute right-0 top-[-5px] text-[#999] hover:text-red-500 cursor-pointer z-10" v-if="hovering === 'niuCloud'">
|
||||
<el-icon class="icon" :size="20" color="#7b7b7b" @click="closeModule('niuCloud')">
|
||||
<CircleCloseFilled />
|
||||
</el-icon>
|
||||
</span>
|
||||
<p class="text-[18px] text-[#1D1F3A]">NIUCLOUD生态精选应用推荐</p>
|
||||
<div class="mt-[20px]">
|
||||
<div class="grid grid-cols-5 gap-4">
|
||||
<div v-for="(item,index) in appList.slice(0,5)" :key="index" @click="toApplicationDetail(item)" class="bg-[#EDEEF4] rounded-[8px] overflow-hidden text-[#666] cursor-pointer hover:shadow-xl transition-shadow duration-300 border-[1px] border-[#EDEEF4]">
|
||||
<img :src="img(item.app_logo)" alt="" class="w-full rounded-t-[6px]" >
|
||||
<div class="bg-[#fff] p-[10px]">
|
||||
<div class="text-[16px] text-[#1D1F3A] mb-[10px]">
|
||||
<span class="using-hidden">{{ item.app_name }}</span>
|
||||
</div>
|
||||
<div class="text-[12px] text-[#4F516D]">
|
||||
<span class="using-hidden">{{ item.app_desc }}</span>
|
||||
</div>
|
||||
<div class="text-[12px] mt-[20px] flex justify-between">
|
||||
<div class="flex items-center">
|
||||
<img :src="img(item.developer.headimg)" alt="" class="w-[18px] h-[18px] rounded-full mr-[6px]" v-if="item.developer.headimg">
|
||||
<img src="@/app/assets/images/member_head.png" alt="" class="w-[18px] h-[18px] rounded-full mr-[6px]" v-else>
|
||||
<span class="text-[#4F516D] text-[12px] using-hidden">{{ item.developer.nickname }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="iconfont iconxiaoliang !text-[12px] mr-[8px] !text-[#4F516D]"></span>
|
||||
<span class="text-[#4F516D] text-[12px]">{{ item.sale_num }}</span>
|
||||
<div class="flex items-center">
|
||||
<div class="mr-[10px]">
|
||||
<span class="iconfont iconchakan !text-[12px] mr-[8px] !text-[#4F516D]"></span>
|
||||
<span class="text-[#4F516D] text-[12px]">{{ item.visit_num}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="iconfont iconxiaoliang !text-[12px] mr-[8px] !text-[#4F516D]"></span>
|
||||
<span class="text-[#4F516D] text-[12px]">{{ item.sale_num }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<div class="text-[18px] mt-[50px] mb-[15px]">{{ t("dataSummarize") }}</div>
|
||||
<el-card class="box-card !border-none profile-data" shadow="never">
|
||||
<el-row :gutter="20" class="top">
|
||||
<el-col>
|
||||
<el-card shadow="never" @click="toHref('site/manage','1')" class="cursor-pointer min-w-[180px] first-con">
|
||||
<div class="text-[20px] font-bold">{{ statInfo.today_data.norma_site_count }}</div>
|
||||
<div class="text-[20px] font-bold">{{ statInfo.today_data.norma_site_count || 0 }}</div>
|
||||
<div class="text-[14px] mb-[9px] text-[#4F516D]">{{ t("normalSiteSum") }}</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<el-card shadow="never" @click="toHref('site/manage','1')" class="cursor-pointer min-w-[180px] first-con">
|
||||
<div class="text-[20px] font-bold">{{ statInfo.today_data.week_expire_site_count }}</div>
|
||||
<div class="text-[20px] font-bold">{{ statInfo.today_data.week_expire_site_count|| 0 }}</div>
|
||||
<div class="text-[14px] mb-[9px] text-[#4F516D]">{{ t("weekExpireSiteCount") }}</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<el-card shadow="never" @click="toHref('site/manage','2')" class="cursor-pointer min-w-[180px] first-con">
|
||||
<div class="text-[20px] font-bold">{{ statInfo.today_data.expire_site_count }}</div>
|
||||
<div class="text-[20px] font-bold">{{ statInfo.today_data.expire_site_count|| 0 }}</div>
|
||||
<div class="text-[14px] mb-[9px] text-[#4F516D]">{{ t("expireSiteSum") }}</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<el-card shadow="never" @click="toHref('/app_manage/app_store','uninstalled')" class="cursor-pointer min-w-[180px] first-con">
|
||||
<div class="text-[20px] font-bold">{{ statInfo.app.app_no_installed_count }}</div>
|
||||
<div class="text-[20px] font-bold">{{ statInfo.app.app_no_installed_count|| 0 }}</div>
|
||||
<div class="text-[14px] mb-[9px] text-[#4F516D]">{{ t("noInstallAppSun") }}</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<el-card shadow="never" @click="toHref('/app_manage/app_store','installed')" class="cursor-pointer min-w-[180px] first-con">
|
||||
<div class="text-[20px] font-bold">{{ statInfo.app.app_installed_count }}</div>
|
||||
<div class="text-[20px] font-bold">{{ statInfo.app.app_installed_count|| 0 }}</div>
|
||||
<div class="text-[14px] mb-[9px] text-[#4F516D]">{{ t("installAppSun") }}</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
@ -76,9 +76,7 @@ const formRules = computed(() => {
|
||||
const setFormData = async () => {
|
||||
loading.value = true
|
||||
const service_data = await (await getMap()).data
|
||||
formData.key = service_data.key
|
||||
formData.is_open = service_data.is_open
|
||||
formData.valid_time = service_data.valid_time
|
||||
Object.assign(formData, service_data)
|
||||
loading.value = false
|
||||
}
|
||||
setFormData()
|
||||
|
||||
@ -1,86 +1,86 @@
|
||||
<template>
|
||||
<el-dialog v-model="showDialog" :title="formData.uid ? t('updateUser') : t('addUser')" width="750px" :destroy-on-close="true">
|
||||
<el-scrollbar>
|
||||
<div class="max-h-[60vh]">
|
||||
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form" autocomplete="off" v-loading="loading">
|
||||
<el-form-item :label="t('username')" prop="username">
|
||||
<el-input v-model.trim="formData.username" clearable :placeholder="t('usernamePlaceholder')" class="input-width" :readonly="formData.uid" :disabled="formData.uid" @click="realnameInput = false" @blur="realnameInput = true" />
|
||||
</el-form-item>
|
||||
<el-dialog v-model="showDialog" :title="formData.uid ? t('updateUser') : t('addUser')" width="750px" :destroy-on-close="true">
|
||||
<el-scrollbar>
|
||||
<div class="max-h-[60vh]">
|
||||
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form" autocomplete="off" v-loading="loading">
|
||||
<el-form-item :label="t('username')" prop="username">
|
||||
<el-input v-model.trim="formData.username" clearable :placeholder="t('usernamePlaceholder')" class="input-width" :readonly="formData.uid" :disabled="formData.uid" @click="realnameInput = false" @blur="realnameInput = true" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('headImg')">
|
||||
<upload-image v-model="formData.head_img" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('headImg')">
|
||||
<upload-image v-model="formData.head_img" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('手机号')" prop="mobile">
|
||||
<el-input v-model.trim="formData.mobile" :placeholder="t('请输入手机号')" clearable class="input-width" maxlength="11" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('手机号')" prop="mobile">
|
||||
<el-input v-model.trim="formData.mobile" :placeholder="t('请输入手机号')" clearable class="input-width" maxlength="11" show-word-limit />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('userRealName')" prop="real_name">
|
||||
<el-input v-model.trim="formData.real_name" :placeholder="t('userRealNamePlaceholder')" :readonly="realnameInput" @click="realnameInput = false" @blur="realnameInput = true" clearable class="input-width" maxlength="10" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('userRealName')" prop="real_name">
|
||||
<el-input v-model.trim="formData.real_name" :placeholder="t('userRealNamePlaceholder')" :readonly="realnameInput" @click="realnameInput = false" @blur="realnameInput = true" clearable class="input-width" maxlength="10" show-word-limit />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('password')" prop="password">
|
||||
<el-input v-model.trim="formData.password" :class="passwordType == 'text' ? '' :'displayPass'" clearable :placeholder="t('passwordPlaceholder')" class="input-width" :readonly="passwordInput" @click="passwordInput = false" @blur="passwordInput = true" >
|
||||
<template #suffix>
|
||||
<el-icon @click="togglePasswordVisibility" class="cursor-pointer">
|
||||
<component :is=" passwordType === 'password' ? 'Hide' : 'View'" />
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('password')" prop="password">
|
||||
<el-input v-model.trim="formData.password" :class="passwordType == 'text' ? '' :'displayPass'" clearable :placeholder="t('passwordPlaceholder')" class="input-width" :readonly="passwordInput" @click="passwordInput = false" @blur="passwordInput = true" >
|
||||
<template #suffix>
|
||||
<el-icon @click="togglePasswordVisibility" class="cursor-pointer">
|
||||
<component :is=" passwordType === 'password' ? 'Hide' : 'View'" />
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('confirmPassword')" prop="confirm_password">
|
||||
<el-input v-model.trim="formData.confirm_password" :class="confirmPasswordType == 'text' ? '' :'displayPass'" :placeholder="t('confirmPasswordPlaceholder')" clearable class="input-width" :readonly="confirmPasswordInput" @click="confirmPasswordInput = false" @blur="confirmPasswordInput = true" >
|
||||
<template #suffix>
|
||||
<el-icon @click="toggleConfirmPasswordVisibility" class="cursor-pointer">
|
||||
<component :is=" confirmPasswordType === 'password' ? 'Hide' : 'View'" />
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('confirmPassword')" prop="confirm_password">
|
||||
<el-input v-model.trim="formData.confirm_password" :class="confirmPasswordType == 'text' ? '' :'displayPass'" :placeholder="t('confirmPasswordPlaceholder')" clearable class="input-width" :readonly="confirmPasswordInput" @click="confirmPasswordInput = false" @blur="confirmPasswordInput = true" >
|
||||
<template #suffix>
|
||||
<el-icon @click="toggleConfirmPasswordVisibility" class="cursor-pointer">
|
||||
<component :is=" confirmPasswordType === 'password' ? 'Hide' : 'View'" />
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('userCreateSiteLimit')" v-if="!formData.uid && Object.keys(siteGroup).length" prop="create_site_limit">
|
||||
<div>
|
||||
<div>{{ t('siteGroup') }}</div>
|
||||
<el-checkbox-group v-model="formData.group_ids" @change="groupSelect">
|
||||
<el-checkbox v-for="item in siteGroup" :label="item.group_id">{{ item.group_name }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<el-form-item :label="t('userCreateSiteLimit')" v-if="!formData.uid && Object.keys(siteGroup).length" prop="create_site_limit">
|
||||
<div>
|
||||
<div>{{ t('siteGroup') }}</div>
|
||||
<el-checkbox-group v-model="formData.group_ids" @change="groupSelect">
|
||||
<el-checkbox v-for="item in siteGroup" :label="item.group_id">{{ item.group_name }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
<div class="w-full">
|
||||
<div>{{ t('userCreateSiteLimit') }}</div>
|
||||
<el-table :data="formData.create_site_limit" size="large" class="w-full">
|
||||
<el-table-column :label="t('siteGroup')" :show-overflow-tooltip="true">
|
||||
<template #default="{ row }">
|
||||
{{ siteGroup[row.group_id] ? siteGroup[row.group_id].group_name : '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('createSiteNum')">
|
||||
<template #default="{ $index }">
|
||||
<el-input v-model.number.trim="formData.create_site_limit[$index].num">
|
||||
</el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('siteMonth')">
|
||||
<template #default="{ $index }">
|
||||
<el-input v-model.number.trim="formData.create_site_limit[$index].month">
|
||||
<template #append>{{ t('month') }}</template>
|
||||
</el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="w-full">
|
||||
<div>{{ t('userCreateSiteLimit') }}</div>
|
||||
<el-table :data="formData.create_site_limit" size="large" class="w-full">
|
||||
<el-table-column :label="t('siteGroup')" :show-overflow-tooltip="true">
|
||||
<template #default="{ row }">
|
||||
{{ siteGroup[row.group_id] ? siteGroup[row.group_id].group_name : '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('createSiteNum')">
|
||||
<template #default="{ $index }">
|
||||
<el-input v-model.number.trim="formData.create_site_limit[$index].num">
|
||||
</el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('siteMonth')">
|
||||
<template #default="{ $index }">
|
||||
<el-input v-model.number.trim="formData.create_site_limit[$index].month">
|
||||
<template #append>{{ t('month') }}</template>
|
||||
</el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</el-scrollbar>
|
||||
|
||||
<template #footer>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -97,135 +97,135 @@ const userStore = useUserStore()
|
||||
const showDialog = ref(false)
|
||||
const loading = ref(true)
|
||||
const formData = ref({
|
||||
uid: 0,
|
||||
username: '',
|
||||
password: '',
|
||||
head_img: '',
|
||||
mobile: '',
|
||||
real_name: '',
|
||||
confirm_password: '',
|
||||
create_site_limit: [],
|
||||
group_ids: []
|
||||
uid: 0,
|
||||
username: '',
|
||||
password: '',
|
||||
head_img: '',
|
||||
mobile: '',
|
||||
real_name: '',
|
||||
confirm_password: '',
|
||||
create_site_limit: [],
|
||||
group_ids: []
|
||||
})
|
||||
const siteGroup = ref({})
|
||||
const formRef = ref<FormInstance>()
|
||||
const formRules = computed(() => {
|
||||
return {
|
||||
username: [
|
||||
{ required: true, message: t('usernamePlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
password: [
|
||||
{ required: userStore.userInfo && userStore.userInfo.is_super_admin == true, message: t('passwordPlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
mobile: [
|
||||
{ required: true, message: t('请输入手机号'), trigger: 'blur' },
|
||||
{
|
||||
validator: (rule: any, value: string, callback: any) => {
|
||||
if (!Test.mobile(value)) {
|
||||
callback(new Error(t('手机号格式错误')))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
real_name: [
|
||||
{ required: true, message: t('userRealNamePlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
confirm_password: [
|
||||
{ required: userStore.userInfo && userStore.userInfo.is_super_admin == true, message: t('confirmPasswordPlaceholder'), trigger: 'blur' },
|
||||
{
|
||||
validator: (rule: any, value: string, callback: any) => {
|
||||
if (value != formData.value.password) callback(new Error(t('confirmPasswordError')))
|
||||
else callback()
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
create_site_limit: [
|
||||
{
|
||||
validator: (rule: any, value: string, callback: any) => {
|
||||
if (formData.value.uid) callback()
|
||||
let verify = true
|
||||
for (let i = 0; i < formData.value.create_site_limit.length; i++) {
|
||||
const item = formData.value.create_site_limit[i]
|
||||
if (Test.empty(item.num)) {
|
||||
callback(t('siteNumPlaceholder'))
|
||||
verify = false
|
||||
break
|
||||
return {
|
||||
username: [
|
||||
{ required: true, message: t('usernamePlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
password: [
|
||||
{ required: userStore.userInfo && userStore.userInfo.is_super_admin == true, message: t('passwordPlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
mobile: [
|
||||
{ required: true, message: t('请输入手机号'), trigger: 'blur' },
|
||||
{
|
||||
validator: (rule: any, value: string, callback: any) => {
|
||||
if (!Test.mobile(value)) {
|
||||
callback(new Error(t('手机号格式错误')))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
if (item.num < 1) {
|
||||
callback(t('siteNumCannotLtOne'))
|
||||
verify = false
|
||||
break
|
||||
],
|
||||
real_name: [
|
||||
{ required: true, message: t('userRealNamePlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
confirm_password: [
|
||||
{ required: userStore.userInfo && userStore.userInfo.is_super_admin == true, message: t('confirmPasswordPlaceholder'), trigger: 'blur' },
|
||||
{
|
||||
validator: (rule: any, value: string, callback: any) => {
|
||||
if (value != formData.value.password) callback(new Error(t('confirmPasswordError')))
|
||||
else callback()
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
if (Test.empty(item.month)) {
|
||||
callback(t('siteMonthPlaceholder'))
|
||||
verify = false
|
||||
break
|
||||
],
|
||||
create_site_limit: [
|
||||
{
|
||||
validator: (rule: any, value: string, callback: any) => {
|
||||
if (formData.value.uid) callback()
|
||||
let verify = true
|
||||
for (let i = 0; i < formData.value.create_site_limit.length; i++) {
|
||||
const item = formData.value.create_site_limit[i]
|
||||
if (Test.empty(item.num)) {
|
||||
callback(t('siteNumPlaceholder'))
|
||||
verify = false
|
||||
break
|
||||
}
|
||||
if (item.num < 1) {
|
||||
callback(t('siteNumCannotLtOne'))
|
||||
verify = false
|
||||
break
|
||||
}
|
||||
if (Test.empty(item.month)) {
|
||||
callback(t('siteMonthPlaceholder'))
|
||||
verify = false
|
||||
break
|
||||
}
|
||||
if (item.month < 0) {
|
||||
callback(t('siteMonthCannotLtOne'))
|
||||
verify = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if (verify) callback()
|
||||
}
|
||||
}
|
||||
if (item.month < 0) {
|
||||
callback(t('siteMonthCannotLtOne'))
|
||||
verify = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if (verify) callback()
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
getSiteGroupAll().then(({ data }) => {
|
||||
const list: any = {}
|
||||
data.forEach((item: any) => {
|
||||
list[item.group_id] = item
|
||||
})
|
||||
siteGroup.value = list
|
||||
const list: any = {}
|
||||
data.forEach((item: any) => {
|
||||
list[item.group_id] = item
|
||||
})
|
||||
siteGroup.value = list
|
||||
})
|
||||
|
||||
const setFormData = (uid: number = 0) => {
|
||||
if (uid) {
|
||||
getUserInfo(uid).then(({ data }) => {
|
||||
formData.value.uid = data.uid
|
||||
formData.value.username = data.username
|
||||
formData.value.mobile = data.mobile
|
||||
formData.value.real_name = data.real_name
|
||||
formData.value.head_img = data.head_img
|
||||
loading.value = false
|
||||
showDialog.value = true
|
||||
})
|
||||
} else {
|
||||
formData.value = {
|
||||
uid: 0,
|
||||
username: '',
|
||||
password: '',
|
||||
head_img: '',
|
||||
mobile: '',
|
||||
real_name: '',
|
||||
confirm_password: '',
|
||||
create_site_limit: [],
|
||||
group_ids: []
|
||||
if (uid) {
|
||||
getUserInfo(uid).then(({ data }) => {
|
||||
formData.value.uid = data.uid
|
||||
formData.value.username = data.username
|
||||
formData.value.mobile = data.mobile
|
||||
formData.value.real_name = data.real_name
|
||||
formData.value.head_img = data.head_img
|
||||
loading.value = false
|
||||
showDialog.value = true
|
||||
})
|
||||
} else {
|
||||
formData.value = {
|
||||
uid: 0,
|
||||
username: '',
|
||||
password: '',
|
||||
head_img: '',
|
||||
mobile: '',
|
||||
real_name: '',
|
||||
confirm_password: '',
|
||||
create_site_limit: [],
|
||||
group_ids: []
|
||||
}
|
||||
loading.value = false
|
||||
showDialog.value = true
|
||||
}
|
||||
loading.value = false
|
||||
showDialog.value = true
|
||||
}
|
||||
}
|
||||
|
||||
const emits = defineEmits(['complete'])
|
||||
|
||||
const groupSelect = (groupIds: number[]) => {
|
||||
const list:any = []
|
||||
groupIds.forEach(item => {
|
||||
list.push({
|
||||
group_id: item,
|
||||
num: 1,
|
||||
month: 1
|
||||
const list:any = []
|
||||
groupIds.forEach(item => {
|
||||
list.push({
|
||||
group_id: item,
|
||||
num: 1,
|
||||
month: 1
|
||||
})
|
||||
})
|
||||
})
|
||||
formData.value.create_site_limit = list
|
||||
formData.value.create_site_limit = list
|
||||
}
|
||||
|
||||
/**
|
||||
@ -233,22 +233,22 @@ const groupSelect = (groupIds: number[]) => {
|
||||
* @param formEl
|
||||
*/
|
||||
const confirm = async (formEl: FormInstance | undefined) => {
|
||||
if (loading.value || !formEl) return
|
||||
if (loading.value || !formEl) return
|
||||
|
||||
await formEl.validate(async (valid) => {
|
||||
if (valid) {
|
||||
loading.value = true
|
||||
const save = formData.value.uid ? editUser : addUser
|
||||
await formEl.validate(async (valid) => {
|
||||
if (valid) {
|
||||
loading.value = true
|
||||
const save = formData.value.uid ? editUser : addUser
|
||||
|
||||
save(formData.value).then(() => {
|
||||
loading.value = false
|
||||
showDialog.value = false
|
||||
emits('complete')
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
})
|
||||
save(formData.value).then(() => {
|
||||
loading.value = false
|
||||
showDialog.value = false
|
||||
emits('complete')
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const realnameInput = ref(true)
|
||||
@ -258,23 +258,23 @@ const confirmPasswordInput = ref(true)
|
||||
const passwordType = ref('password')
|
||||
|
||||
const togglePasswordVisibility = () => {
|
||||
passwordType.value = passwordType.value === 'password' ? 'text' : 'password'
|
||||
passwordType.value = passwordType.value === 'password' ? 'text' : 'password'
|
||||
}
|
||||
const confirmPasswordType = ref('password')
|
||||
|
||||
const toggleConfirmPasswordVisibility = () => {
|
||||
confirmPasswordType.value = confirmPasswordType.value === 'password' ? 'text' : 'password'
|
||||
confirmPasswordType.value = confirmPasswordType.value === 'password' ? 'text' : 'password'
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
showDialog,
|
||||
setFormData
|
||||
showDialog,
|
||||
setFormData
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.displayPass {
|
||||
:deep(.el-input__inner){
|
||||
:deep(.el-input__inner){
|
||||
-webkit-text-security: disc !important;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,99 +1,99 @@
|
||||
<template>
|
||||
<!--站点用户-->
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<!--站点用户-->
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
<div>
|
||||
<el-button type="primary" class="w-[100px]" @click="userEditRef.setFormData()">{{ t('addUser') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
<div>
|
||||
<el-button type="primary" class="w-[100px]" @click="userEditRef.setFormData()">{{ t('addUser') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
|
||||
<el-form :inline="true" :model="userTableData.searchParam" ref="searchFormRef" class="search-form">
|
||||
<el-form-item prop="username">
|
||||
<el-input v-model.trim="userTableData.searchParam.username" :placeholder="t('userNamePlaceholder')" />
|
||||
</el-form-item>
|
||||
<!-- <el-form-item :label="t('createTime')" prop="create_time">
|
||||
<el-date-picker v-model="userTableData.searchParam.create_time" type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')"
|
||||
:end-placeholder="t('endDate')" />
|
||||
</el-form-item> -->
|
||||
<el-form-item prop="last_time">
|
||||
<el-date-picker v-model="userTableData.searchParam.last_time" type="datetimerange"
|
||||
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
|
||||
<el-form :inline="true" :model="userTableData.searchParam" ref="searchFormRef" class="search-form">
|
||||
<el-form-item prop="username">
|
||||
<el-input v-model.trim="userTableData.searchParam.username" :placeholder="t('userNamePlaceholder')" />
|
||||
</el-form-item>
|
||||
<!-- <el-form-item :label="t('createTime')" prop="create_time">
|
||||
<el-date-picker v-model="userTableData.searchParam.create_time" type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')"
|
||||
:end-placeholder="t('endDate')" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="loadUserList()">{{ t('search') }}</el-button>
|
||||
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</el-form-item> -->
|
||||
<el-form-item prop="last_time">
|
||||
<el-date-picker v-model="userTableData.searchParam.last_time" type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')"
|
||||
:end-placeholder="t('endDate')" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="loadUserList()">{{ t('search') }}</el-button>
|
||||
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<div>
|
||||
<el-table :data="userTableData.data" size="large" v-loading="userTableData.loading">
|
||||
<template #empty>
|
||||
<span>{{ !userTableData.loading ? t('emptyData') : '' }}</span>
|
||||
</template>
|
||||
<el-table-column :label="t('headImg')" width="100" align="left">
|
||||
<template #default="{ row }">
|
||||
<div class="w-[54px] h-[54px] flex items-center justify-center">
|
||||
<img v-if="row.head_img" :src="img(row.head_img)" class="w-[54px] rounded-full" />
|
||||
<img v-else src="@/app/assets/images/member_head.png" class="w-[54px] rounded-full" />
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="username" :label="t('accountNumber')" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="mobile" :label="t('手机号')" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="real_name" :label="t('userRealName')" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="site_num" :label="t('siteNum')" min-width="120" show-overflow-tooltip align="center" />
|
||||
<!-- <el-table-column prop="create_time" :label="t('createTime')" min-width="180" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.create_time || '' }}
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<el-table-column prop="last_time" :label="t('lastLoginTime')" min-width="180" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.last_time || '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('lastLoginIP')" min-width="180" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.last_ip || '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('operation')" align="right" fixed="right" width="180">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="detailEvent(row.uid)">{{ t('detail') }}</el-button>
|
||||
<template v-if="!row.is_super_admin">
|
||||
<el-button type="primary" link @click="editEvent(row.uid)" >{{ t('edit') }}</el-button>
|
||||
<el-button type="primary" link @click="detailEvent(row.uid, 'userCreateSiteLimit')" >{{ t('userCreateSiteLimit') }}</el-button>
|
||||
<el-button type="primary" link @click="deleteEvent(row.uid)" >{{ t('delete') }}</el-button>
|
||||
</template>
|
||||
<!-- <div class="manage-option text-right ">
|
||||
<template v-if="!row.is_super_admin">
|
||||
<el-button type="primary" link @click="editEvent(row.uid)" >{{ t('edit') }}</el-button>
|
||||
<el-button type="primary" link @click="detailEvent(row.uid, 'userCreateSiteLimit')" >{{ t('userCreateSiteLimit') }}</el-button>
|
||||
<el-button type="primary" link @click="deleteEvent(row.uid)" >{{ t('delete') }}</el-button>
|
||||
</template>
|
||||
</div> -->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div>
|
||||
<el-table :data="userTableData.data" size="large" v-loading="userTableData.loading">
|
||||
<template #empty>
|
||||
<span>{{ !userTableData.loading ? t('emptyData') : '' }}</span>
|
||||
</template>
|
||||
<el-table-column :label="t('headImg')" width="100" align="left">
|
||||
<template #default="{ row }">
|
||||
<div class="w-[54px] h-[54px] flex items-center justify-center">
|
||||
<img v-if="row.head_img" :src="img(row.head_img)" class="w-[54px] rounded-full" />
|
||||
<img v-else src="@/app/assets/images/member_head.png" class="w-[54px] rounded-full" />
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="username" :label="t('accountNumber')" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="mobile" :label="t('手机号')" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="real_name" :label="t('userRealName')" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="site_num" :label="t('siteNum')" min-width="120" show-overflow-tooltip align="center" />
|
||||
<!-- <el-table-column prop="create_time" :label="t('createTime')" min-width="180" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.create_time || '' }}
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<el-table-column prop="last_time" :label="t('lastLoginTime')" min-width="180" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.last_time || '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('lastLoginIP')" min-width="180" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.last_ip || '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('operation')" align="right" fixed="right" width="180">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="detailEvent(row.uid)">{{ t('detail') }}</el-button>
|
||||
<template v-if="!row.is_super_admin">
|
||||
<el-button type="primary" link @click="editEvent(row.uid)" >{{ t('edit') }}</el-button>
|
||||
<el-button type="primary" link @click="detailEvent(row.uid, 'userCreateSiteLimit')" >{{ t('userCreateSiteLimit') }}</el-button>
|
||||
<el-button type="primary" link @click="deleteEvent(row.uid)" >{{ t('delete') }}</el-button>
|
||||
</template>
|
||||
<!-- <div class="manage-option text-right ">
|
||||
<template v-if="!row.is_super_admin">
|
||||
<el-button type="primary" link @click="editEvent(row.uid)" >{{ t('edit') }}</el-button>
|
||||
<el-button type="primary" link @click="detailEvent(row.uid, 'userCreateSiteLimit')" >{{ t('userCreateSiteLimit') }}</el-button>
|
||||
<el-button type="primary" link @click="deleteEvent(row.uid)" >{{ t('delete') }}</el-button>
|
||||
</template>
|
||||
</div> -->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="mt-[16px] flex justify-end">
|
||||
<el-pagination v-model:current-page="userTableData.page" v-model:page-size="userTableData.limit"
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="userTableData.total"
|
||||
@size-change="loadUserList()" @current-change="loadUserList" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-[16px] flex justify-end">
|
||||
<el-pagination v-model:current-page="userTableData.page" v-model:page-size="userTableData.limit"
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="userTableData.total"
|
||||
@size-change="loadUserList()" @current-change="loadUserList" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</el-card>
|
||||
</el-card>
|
||||
|
||||
<user-edit ref="userEditRef" @complete="loadUserList()"/>
|
||||
</div>
|
||||
<user-edit ref="userEditRef" @complete="loadUserList()"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -112,47 +112,47 @@ const pageName = route.meta.title
|
||||
const userEditRef = ref(null)
|
||||
|
||||
const userTableData = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam: {
|
||||
username: '',
|
||||
site_name: '',
|
||||
// create_time: [],
|
||||
last_time: []
|
||||
}
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam: {
|
||||
username: '',
|
||||
site_name: '',
|
||||
// create_time: [],
|
||||
last_time: []
|
||||
}
|
||||
})
|
||||
|
||||
const searchFormRef = ref<FormInstance>()
|
||||
|
||||
const resetForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
if (!formEl) return
|
||||
|
||||
formEl.resetFields()
|
||||
loadUserList()
|
||||
formEl.resetFields()
|
||||
loadUserList()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户列表
|
||||
*/
|
||||
const loadUserList = (page: number = 1) => {
|
||||
userTableData.loading = true
|
||||
userTableData.page = page
|
||||
userTableData.loading = true
|
||||
userTableData.page = page
|
||||
|
||||
getUserList({
|
||||
page: userTableData.page,
|
||||
limit: userTableData.limit,
|
||||
...userTableData.searchParam
|
||||
getUserList({
|
||||
page: userTableData.page,
|
||||
limit: userTableData.limit,
|
||||
...userTableData.searchParam
|
||||
|
||||
}).then(res => {
|
||||
userTableData.loading = false
|
||||
userTableData.data = res.data.data
|
||||
userTableData.total = res.data.total
|
||||
}).catch(() => {
|
||||
userTableData.loading = false
|
||||
})
|
||||
}).then(res => {
|
||||
userTableData.loading = false
|
||||
userTableData.data = res.data.data
|
||||
userTableData.total = res.data.total
|
||||
}).catch(() => {
|
||||
userTableData.loading = false
|
||||
})
|
||||
}
|
||||
loadUserList()
|
||||
|
||||
@ -160,7 +160,7 @@ loadUserList()
|
||||
* 查看详情
|
||||
*/
|
||||
const detailEvent = (uid: number, tab: string = '') => {
|
||||
router.push({ path: '/admin/site/user_info', query: { uid, tab } })
|
||||
router.push({ path: '/admin/site/user_info', query: { uid, tab } })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -168,69 +168,69 @@ const detailEvent = (uid: number, tab: string = '') => {
|
||||
* @param uid
|
||||
*/
|
||||
const editEvent = (uid: number) => {
|
||||
userEditRef.value.setFormData(uid)
|
||||
userEditRef.value.setFormData(uid)
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户
|
||||
*/
|
||||
const deleteEvent = (uid: number) => {
|
||||
ElMessageBox.confirm(t('userDeleteTips'), t('warning'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
cancelButtonText: t('cancel'),
|
||||
type: 'warning'
|
||||
}
|
||||
).then(() => {
|
||||
deleteUser(uid).then(res => {
|
||||
loadUserList()
|
||||
}).catch(() => {
|
||||
ElMessageBox.confirm(t('userDeleteTips'), t('warning'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
cancelButtonText: t('cancel'),
|
||||
type: 'warning'
|
||||
}
|
||||
).then(() => {
|
||||
deleteUser(uid).then(res => {
|
||||
loadUserList()
|
||||
}).catch(() => {
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-table tr td) {
|
||||
height: 100px !important;
|
||||
height: 100px !important;
|
||||
}
|
||||
:deep(.el-input__wrapper){
|
||||
box-shadow: none !important;
|
||||
border-radius: 4px !important;
|
||||
border: 1px solid #D1D5DB !important;
|
||||
height: 32px !important;
|
||||
box-shadow: none !important;
|
||||
border-radius: 4px !important;
|
||||
border: 1px solid #D1D5DB !important;
|
||||
height: 32px !important;
|
||||
}
|
||||
:deep(.el-select__wrapper){
|
||||
box-shadow: none !important;
|
||||
border-radius: 4px !important;
|
||||
border: 1px solid #D1D5DB !important;
|
||||
height: 32px !important;
|
||||
box-shadow: none !important;
|
||||
border-radius: 4px !important;
|
||||
border: 1px solid #D1D5DB !important;
|
||||
height: 32px !important;
|
||||
}
|
||||
:deep(.el-button){
|
||||
border-radius: 4px !important;
|
||||
border-radius: 4px !important;
|
||||
}
|
||||
/* 设置 el-select 的 placeholder 颜色 */
|
||||
:deep(.search-form .el-select__placeholder.is-transparent) {
|
||||
color: #C4C7DA;
|
||||
font-size: 12px;
|
||||
color: #C4C7DA;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* 设置 el-select 选中后的颜色 */
|
||||
:deep(.search-form .el-select__placeholder) {
|
||||
color: #4F516D;
|
||||
font-size: 12px;
|
||||
color: #4F516D;
|
||||
font-size: 12px;
|
||||
|
||||
}
|
||||
/* 设置 el-input 的 placeholder 颜色 */
|
||||
:deep(.search-form .el-input__inner::placeholder) {
|
||||
color: #C4C7DA;
|
||||
font-size: 12px;
|
||||
color: #C4C7DA;
|
||||
font-size: 12px;
|
||||
|
||||
}
|
||||
/* 设置 el-input 输入内容后的颜色 */
|
||||
:deep(.search-form .el-input__inner) {
|
||||
color: #4F516D;
|
||||
font-size: 12px;
|
||||
color: #4F516D;
|
||||
font-size: 12px;
|
||||
|
||||
}
|
||||
/* 设置 el-date-picker 的 placeholder 颜色 */
|
||||
@ -246,43 +246,43 @@ const deleteEvent = (uid: number) => {
|
||||
}
|
||||
|
||||
.manage-option {
|
||||
line-height: 50px;
|
||||
padding: 0 30px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: 100vw;
|
||||
bottom: 0;
|
||||
background-color: #f4f6f9;
|
||||
transition: all .3s;
|
||||
box-shadow: 0 4px 4px rgba(220, 220, 220, .3);
|
||||
opacity: 0;
|
||||
z-index: 999;
|
||||
white-space: nowrap;
|
||||
line-height: 50px;
|
||||
padding: 0 30px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: 100vw;
|
||||
bottom: 0;
|
||||
background-color: #f4f6f9;
|
||||
transition: all .3s;
|
||||
box-shadow: 0 4px 4px rgba(220, 220, 220, .3);
|
||||
opacity: 0;
|
||||
z-index: 999;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 当行被 hover 时 */
|
||||
:deep(.el-table__row:hover) {
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/* 当行被 hover 时,其下的单元格允许溢出 */
|
||||
:deep(.el-table__row:hover .el-table__cell) {
|
||||
overflow: visible;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/* 当行被 hover 时,显示 manage-option 并调整其位置 */
|
||||
:deep(.el-table__row:hover .manage-option) {
|
||||
opacity: 1;
|
||||
bottom: -51px;
|
||||
opacity: 1;
|
||||
bottom: -51px;
|
||||
}
|
||||
|
||||
:deep(.el-table__fixed-body-wrapper:hover),
|
||||
:deep(.el-table__fixed-body-wrapper .el-table__row:hover) {
|
||||
z-index: 10;
|
||||
:deep(.el-table__fixed-body-wrapper:hover),
|
||||
:deep(.el-table__fixed-body-wrapper .el-table__row:hover) {
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
:deep(.el-table__fixed-body-wrapper .el-table__row:hover .el-table__cell) {
|
||||
overflow: visible;
|
||||
overflow: visible;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,135 +1,135 @@
|
||||
<template>
|
||||
<!--用户详情-->
|
||||
<div class="main-container" v-loading="loading">
|
||||
<!--用户详情-->
|
||||
<div class="main-container" v-loading="loading">
|
||||
|
||||
<el-card class="card !border-none" shadow="never">
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back()" />
|
||||
</el-card>
|
||||
<el-card class="card !border-none" shadow="never">
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back()" />
|
||||
</el-card>
|
||||
|
||||
<el-card class="box-card mt-[15px] !border-none" shadow="never">
|
||||
<h3 class="panel-title !text-sm">{{ t('userInfo') }}</h3>
|
||||
<el-card class="box-card mt-[15px] !border-none" shadow="never">
|
||||
<h3 class="panel-title !text-sm">{{ t('userInfo') }}</h3>
|
||||
|
||||
<el-row :gutter="20" class="mt-[20px] mb-[20px]">
|
||||
<el-col :span="6">
|
||||
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ t('uid') }}</span>
|
||||
<span class="text-[14px] text-[#666666]">
|
||||
<el-row :gutter="20" class="mt-[20px] mb-[20px]">
|
||||
<el-col :span="6">
|
||||
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ t('uid') }}</span>
|
||||
<span class="text-[14px] text-[#666666]">
|
||||
{{ detail.uid }}
|
||||
</span>
|
||||
</el-col>
|
||||
<el-col :span="6" :offset="6">
|
||||
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ t('username') }}</span>
|
||||
<span class="text-[14px] text-[#666666]">
|
||||
</el-col>
|
||||
<el-col :span="6" :offset="6">
|
||||
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ t('username') }}</span>
|
||||
<span class="text-[14px] text-[#666666]">
|
||||
{{ detail.username }}
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20" class="mb-[20px]">
|
||||
<el-col :span="6" >
|
||||
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ t('realname') }}</span>
|
||||
<span class="text-[14px] text-[#666666]">
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20" class="mb-[20px]">
|
||||
<el-col :span="6" >
|
||||
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ t('realname') }}</span>
|
||||
<span class="text-[14px] text-[#666666]">
|
||||
{{ detail.real_name || '--' }}
|
||||
</span>
|
||||
</el-col>
|
||||
<el-col :span="6" :offset="6">
|
||||
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ t('手机号') }}</span>
|
||||
<span class="text-[14px] text-[#666666]">
|
||||
</el-col>
|
||||
<el-col :span="6" :offset="6">
|
||||
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ t('手机号') }}</span>
|
||||
<span class="text-[14px] text-[#666666]">
|
||||
{{ detail.mobile || '--' }}
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20" class="mb-[20px]">
|
||||
<el-col :span="6">
|
||||
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ t('addTime') }}</span>
|
||||
<span class="text-[14px] text-[#666666]">
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20" class="mb-[20px]">
|
||||
<el-col :span="6">
|
||||
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ t('addTime') }}</span>
|
||||
<span class="text-[14px] text-[#666666]">
|
||||
{{ detail.create_time }}
|
||||
</span>
|
||||
</el-col>
|
||||
<el-col :span="6" :offset="6">
|
||||
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ t('lastLoginTime') }}</span>
|
||||
<span class="text-[14px] text-[#666666]">
|
||||
</el-col>
|
||||
<el-col :span="6" :offset="6">
|
||||
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ t('lastLoginTime') }}</span>
|
||||
<span class="text-[14px] text-[#666666]">
|
||||
{{ detail.last_time || '' }}
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20" class="mb-[20px]">
|
||||
<el-col :span="6">
|
||||
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ t('lastLoginIP') }}</span>
|
||||
<span class="text-[14px] text-[#666666]">
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20" class="mb-[20px]">
|
||||
<el-col :span="6">
|
||||
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ t('lastLoginIP') }}</span>
|
||||
<span class="text-[14px] text-[#666666]">
|
||||
{{ detail.last_ip || '' }}
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<el-card class="box-card mt-[15px] !border-none" shadow="never">
|
||||
<el-tabs v-model="currTab">
|
||||
<el-tab-pane :label="t('siteInfo')" name="siteInfo">
|
||||
<el-table :data="detail.roles" size="large">
|
||||
<el-table-column prop="site_id" :label="t('siteId')" width="100px" />
|
||||
<el-table-column prop="site_name" :label="t('siteName')" />
|
||||
<el-table-column prop="is_admin" :label="t('isAdmin')" min-width="180" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.is_admin ? t('yes') : t('no') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('status')" min-width="80" align="center">
|
||||
<template #default="{ row }">
|
||||
<template v-if="row.site_status_name">
|
||||
<el-tag class="ml-2" type="success" v-if="row.site_status == 1">{{ row.site_status_name }}</el-tag>
|
||||
<el-tag class="ml-2" type="error" v-else-if="row.site_status == 3">
|
||||
{{ row.site_status_name }}
|
||||
</el-tag>
|
||||
<el-tag class="ml-2" type="error" v-else>
|
||||
{{ row.site_status_name }}
|
||||
</el-tag>
|
||||
</template>
|
||||
<el-tag class="ml-2" type="error" v-else>
|
||||
{{ t('siteEmpty') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="expire_time" :label="t('expireTime')" />
|
||||
<el-table-column :label="t('operation')" align="right" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="siteInfo(row)" v-if="row.site_status_name">{{ t('info') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="t('userCreateSiteLimit')" name="userCreateSiteLimit" v-if="!detail.is_super_admin">
|
||||
<div class="flex justify-end mb-[16px]">
|
||||
<el-button type="primary" @click="createSiteLimitRef.setFormData()">{{ t('addSserCreateSiteLimit') }}</el-button>
|
||||
</div>
|
||||
<el-table :data="userCreateSiteLimit" size="large">
|
||||
<el-table-column :label="t('siteGroup')">
|
||||
<template #default="{ row }">
|
||||
{{ siteGroup[row.group_id] ? siteGroup[row.group_id].group_name : '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('createdSiteNum')">
|
||||
<template #default="{ row }">
|
||||
{{ siteGroup[row.group_id] ? siteGroup[row.group_id].site_num : 0 }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="num" :label="t('createSiteNum')" align="center"/>
|
||||
<el-table-column prop="month" :label="t('createSiteTimeLimit')" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.month }}个{{ t('month') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('operation')" align="right" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="createSiteLimitRef.setFormData(row.id)">{{ t('edit') }}</el-button>
|
||||
<el-button type="primary" link @click="deleteCreateSiteTimeLimit(row.id)">{{ t('delete') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-card>
|
||||
<el-card class="box-card mt-[15px] !border-none" shadow="never">
|
||||
<el-tabs v-model="currTab">
|
||||
<el-tab-pane :label="t('siteInfo')" name="siteInfo">
|
||||
<el-table :data="detail.roles" size="large">
|
||||
<el-table-column prop="site_id" :label="t('siteId')" width="100px" />
|
||||
<el-table-column prop="site_name" :label="t('siteName')" />
|
||||
<el-table-column prop="is_admin" :label="t('isAdmin')" min-width="180" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.is_admin ? t('yes') : t('no') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('status')" min-width="80" align="center">
|
||||
<template #default="{ row }">
|
||||
<template v-if="row.site_status_name">
|
||||
<el-tag class="ml-2" type="success" v-if="row.site_status == 1">{{ row.site_status_name }}</el-tag>
|
||||
<el-tag class="ml-2" type="error" v-else-if="row.site_status == 3">
|
||||
{{ row.site_status_name }}
|
||||
</el-tag>
|
||||
<el-tag class="ml-2" type="error" v-else>
|
||||
{{ row.site_status_name }}
|
||||
</el-tag>
|
||||
</template>
|
||||
<el-tag class="ml-2" type="error" v-else>
|
||||
{{ t('siteEmpty') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="expire_time" :label="t('expireTime')" />
|
||||
<el-table-column :label="t('operation')" align="right" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="siteInfo(row)" v-if="row.site_status_name">{{ t('info') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="t('userCreateSiteLimit')" name="userCreateSiteLimit" v-if="!detail.is_super_admin">
|
||||
<div class="flex justify-end mb-[16px]">
|
||||
<el-button type="primary" @click="createSiteLimitRef.setFormData()">{{ t('addSserCreateSiteLimit') }}</el-button>
|
||||
</div>
|
||||
<el-table :data="userCreateSiteLimit" size="large">
|
||||
<el-table-column :label="t('siteGroup')">
|
||||
<template #default="{ row }">
|
||||
{{ siteGroup[row.group_id] ? siteGroup[row.group_id].group_name : '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('createdSiteNum')">
|
||||
<template #default="{ row }">
|
||||
{{ siteGroup[row.group_id] ? siteGroup[row.group_id].site_num : 0 }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="num" :label="t('createSiteNum')" align="center"/>
|
||||
<el-table-column prop="month" :label="t('createSiteTimeLimit')" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.month }}个{{ t('month') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('operation')" align="right" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="createSiteLimitRef.setFormData(row.id)">{{ t('edit') }}</el-button>
|
||||
<el-button type="primary" link @click="deleteCreateSiteTimeLimit(row.id)">{{ t('delete') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-card>
|
||||
|
||||
<create-site-limit ref="createSiteLimitRef" :site-group="siteGroup" :uid="uid" @complete="getUserCreateSiteLimitFn"/>
|
||||
</div>
|
||||
<create-site-limit ref="createSiteLimitRef" :site-group="siteGroup" :uid="uid" @complete="getUserCreateSiteLimitFn"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -147,7 +147,7 @@ const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
|
||||
const back = () => {
|
||||
router.push('/admin/site/user')
|
||||
router.push('/admin/site/user')
|
||||
}
|
||||
const uid: number = parseInt(route.query.uid || 0)
|
||||
const loading = ref(true)
|
||||
@ -158,22 +158,22 @@ const userCreateSiteLimit = ref([])
|
||||
const createSiteLimitRef = ref(null)
|
||||
|
||||
getUserInfo(uid).then(({ data }) => {
|
||||
detail.value = data
|
||||
loading.value = false
|
||||
detail.value = data
|
||||
loading.value = false
|
||||
}).catch()
|
||||
|
||||
getUserSiteGroupAll({ uid }).then(({ data }) => {
|
||||
const list: any = {}
|
||||
data.forEach((item: any) => {
|
||||
list[item.group_id] = item
|
||||
})
|
||||
siteGroup.value = list
|
||||
const list: any = {}
|
||||
data.forEach((item: any) => {
|
||||
list[item.group_id] = item
|
||||
})
|
||||
siteGroup.value = list
|
||||
})
|
||||
|
||||
const getUserCreateSiteLimitFn = () => {
|
||||
getUserCreateSiteLimit(uid).then(({ data }) => {
|
||||
userCreateSiteLimit.value = data
|
||||
})
|
||||
getUserCreateSiteLimit(uid).then(({ data }) => {
|
||||
userCreateSiteLimit.value = data
|
||||
})
|
||||
}
|
||||
getUserCreateSiteLimitFn()
|
||||
|
||||
@ -182,22 +182,22 @@ getUserCreateSiteLimitFn()
|
||||
* @param data
|
||||
*/
|
||||
const siteInfo = (data: any) => {
|
||||
router.push({ path: '/admin/site/info', query: { id: data.site_id } })
|
||||
router.push({ path: '/admin/site/info', query: { id: data.site_id } })
|
||||
}
|
||||
|
||||
const deleteCreateSiteTimeLimit = (id: number) => {
|
||||
ElMessageBox.confirm(t('createSiteTimeLimitDeleteTips'), t('warning'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
cancelButtonText: t('cancel'),
|
||||
type: 'warning'
|
||||
}
|
||||
).then(() => {
|
||||
delUserCreateSiteLimit(id).then(() => {
|
||||
getUserCreateSiteLimitFn()
|
||||
}).catch(() => {
|
||||
ElMessageBox.confirm(t('createSiteTimeLimitDeleteTips'), t('warning'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
cancelButtonText: t('cancel'),
|
||||
type: 'warning'
|
||||
}
|
||||
).then(() => {
|
||||
delUserCreateSiteLimit(id).then(() => {
|
||||
getUserCreateSiteLimitFn()
|
||||
}).catch(() => {
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useRouter , useRoute} from 'vue-router'
|
||||
import { computed } from 'vue'
|
||||
import { img } from '@/utils/common'
|
||||
import menuItem from './menu-item.vue'
|
||||
@ -32,6 +32,8 @@ import useUserStore from '@/stores/modules/user'
|
||||
import storage from '@/utils/storage'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const props = defineProps({
|
||||
routes: {
|
||||
type: Object,
|
||||
@ -70,8 +72,13 @@ const handleJump = (routeName: string) => {
|
||||
if (specialMenuNamesLevel1.includes(routeName)) {
|
||||
routeName = 'addon_list'
|
||||
}
|
||||
// 跳转时添加随机查询参数(用于触发页面感知)
|
||||
const query = route.name === routeName
|
||||
? { refresh: Date.now() } // 相同路由时添加随机参数
|
||||
: {};
|
||||
|
||||
// 执行跳转
|
||||
router.push({ name: routeName })
|
||||
router.push({ name: routeName, query });
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@ -190,9 +190,13 @@ const handleJump = (routeName: string) => {
|
||||
if (specialMenuNamesLevel1.value.includes(routeName)) {
|
||||
routeName = 'addon_list'
|
||||
}
|
||||
// 跳转时添加随机查询参数(用于触发页面感知)
|
||||
const query = route.name === routeName
|
||||
? { refresh: Date.now() } // 相同路由时添加随机参数
|
||||
: {};
|
||||
|
||||
// 执行跳转
|
||||
router.push({ name: routeName })
|
||||
router.push({ name: routeName, query });
|
||||
}
|
||||
|
||||
watch(route, () => {
|
||||
|
||||
@ -43,7 +43,7 @@ const addonIndexRoute = userStore.addonIndexRoute
|
||||
const menuData = ref<Record<string, any>[]>([])
|
||||
const addonRouters: Record<string, any> = {}
|
||||
const logoUrl = computed(() => {
|
||||
return userStore.siteInfo.icon ? userStore.siteInfo.icon : systemStore.website.icon
|
||||
return userStore.siteInfo.logo ? userStore.siteInfo.logo : systemStore.website.logo
|
||||
})
|
||||
|
||||
const appList = ref<Record<string, any>[]>([])
|
||||
|
||||
@ -183,9 +183,13 @@ const handleJump = (routeName: string) => {
|
||||
if (specialMenuNamesLevel1.value.includes(routeName)) {
|
||||
routeName = 'addon_list'
|
||||
}
|
||||
// 跳转时添加随机查询参数(用于触发页面感知)
|
||||
const query = route.name === routeName
|
||||
? { refresh: Date.now() } // 相同路由时添加随机参数
|
||||
: {};
|
||||
|
||||
// 执行跳转
|
||||
router.push({ name: routeName })
|
||||
router.push({ name: routeName, query });
|
||||
}
|
||||
|
||||
watch(route, () => {
|
||||
|
||||
@ -44,7 +44,7 @@ const addonIndexRoute = userStore.addonIndexRoute
|
||||
const menuData = ref<Record<string, any>[]>([])
|
||||
const addonRouters: Record<string, any> = {}
|
||||
const logoUrl = computed(() => {
|
||||
return userStore.siteInfo.icon ? userStore.siteInfo.icon : systemStore.website.icon
|
||||
return userStore.siteInfo.logo ? userStore.siteInfo.logo : systemStore.website.logo
|
||||
})
|
||||
|
||||
const appList = ref<Record<string, any>[]>([])
|
||||
|
||||
@ -24,13 +24,14 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useRouter ,useRoute } from 'vue-router'
|
||||
import { computed } from 'vue'
|
||||
import menuItem from './menu-item.vue'
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
import storage from '@/utils/storage'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const props = defineProps({
|
||||
routes: {
|
||||
type: Object,
|
||||
@ -69,8 +70,13 @@ const handleJump = (routeName: string) => {
|
||||
if (specialMenuNamesLevel1.includes(routeName)) {
|
||||
routeName = 'addon_list'
|
||||
}
|
||||
// 跳转时添加随机查询参数(用于触发页面感知)
|
||||
const query = route.name === routeName
|
||||
? { refresh: Date.now() } // 相同路由时添加随机参数
|
||||
: {};
|
||||
|
||||
// 执行跳转
|
||||
router.push({ name: routeName })
|
||||
router.push({ name: routeName, query });
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@ -77,8 +77,17 @@ const useDiyStore = defineStore('diy', {
|
||||
bottomTabBar: {
|
||||
control: true, // 是否允许展示编辑
|
||||
isShow: true, // 是否显示
|
||||
designNav:{ //类型
|
||||
title: "", // 标题
|
||||
key: "", // 组件标识
|
||||
}
|
||||
},
|
||||
|
||||
// 版权信息
|
||||
copyright: {
|
||||
control: true, // 是否允许展示编辑
|
||||
isShow: false, // 是否显示
|
||||
},
|
||||
// 弹框 count:不弹出 -1,首次弹出 1,每次弹出 0
|
||||
popWindow: {
|
||||
imgUrl: "",
|
||||
@ -171,6 +180,16 @@ const useDiyStore = defineStore('diy', {
|
||||
bottomTabBar: {
|
||||
control: true, // 是否允许展示编辑
|
||||
isShow: true, // 是否显示
|
||||
designNav:{ //类型
|
||||
title: "", // 标题
|
||||
key: "", // 组件标识
|
||||
}
|
||||
},
|
||||
|
||||
// 版权信息
|
||||
copyright: {
|
||||
control: true, // 是否允许展示编辑
|
||||
isShow: true, // 是否显示
|
||||
},
|
||||
|
||||
// 弹框 count:不弹出 -1,首次弹出 1,每次弹出 0
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user