mirror of
https://gitee.com/niucloud-team/niucloud.git
synced 2025-12-12 09:57:20 +00:00
up
This commit is contained in:
parent
804537dc10
commit
5b0dfeee91
68
admin/src/app/api/app.ts
Normal file
68
admin/src/app/api/app.ts
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取app配置
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getAppConfig() {
|
||||||
|
return request.get('channel/app/config')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑app配置
|
||||||
|
* @param params
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function setAppConfig(params: Record<string, any>) {
|
||||||
|
return request.put('channel/app/config', params, { showSuccessMessage: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function getVersionList(params: Record<string, any>) {
|
||||||
|
return request.get('channel/app/version', { params })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getVersionInfo(id: number) {
|
||||||
|
return request.get(`channel/app/version/${id}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getAppPlatform() {
|
||||||
|
return request.get(`channel/app/platfrom`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加版本
|
||||||
|
* @param params
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function addVersion(params: Record<string, any>) {
|
||||||
|
return request.post('channel/app/version', params, { showSuccessMessage: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新版本
|
||||||
|
* @param params
|
||||||
|
*/
|
||||||
|
export function editVersion(params: Record<string, any>) {
|
||||||
|
return request.put(`channel/app/version/${ params.id }`, params, { showSuccessMessage: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除版本
|
||||||
|
* @param siteId
|
||||||
|
*/
|
||||||
|
export function deleteVersion(params: Record<string, any>) {
|
||||||
|
return request.delete(`channel/app/version/${ params.id }`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBuildLog(key: string) {
|
||||||
|
return request.get(`channel/app/build/log/${ key }`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function releaseVersion(id: number) {
|
||||||
|
return request.put(`channel/app/version/${ id }/release`, {}, { showSuccessMessage: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateSingCert(params: Record<string, any>) {
|
||||||
|
return request.post(`channel/app/generate_sing_cert`, params, { showSuccessMessage: true });
|
||||||
|
}
|
||||||
13
admin/src/app/lang/zh-cn/channel.app.access.json
Normal file
13
admin/src/app/lang/zh-cn/channel.app.access.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"accessFlow": "接入流程",
|
||||||
|
"versionManage": "版本管理",
|
||||||
|
"title": "APP端管理",
|
||||||
|
"appInlet": "App接入流程",
|
||||||
|
"uniappApp": "uni-app应用开通",
|
||||||
|
"appAttestation1": "点击进入Dcloud官网开发者后台,创建或选择应用并维护好应用平台信息",
|
||||||
|
"clickAccess": "点击接入",
|
||||||
|
"appSetting": "App端配置",
|
||||||
|
"settingInfo": "点击配置",
|
||||||
|
"releaseVersion": "发布版本",
|
||||||
|
"toCreate": "去创建"
|
||||||
|
}
|
||||||
17
admin/src/app/lang/zh-cn/channel.app.config.json
Normal file
17
admin/src/app/lang/zh-cn/channel.app.config.json
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"wechatAppInfo": "微信应用信息",
|
||||||
|
"wechatAppid": "微信移动应用AppID",
|
||||||
|
"wechatAppidTips": "用于app端 微信登录 微信支付 微信分享",
|
||||||
|
"wechatAppsecret": "微信移动应用AppSecret",
|
||||||
|
"appidPlaceholder": "请输入AppID",
|
||||||
|
"appSecretPlaceholder": "请输入AppSecret",
|
||||||
|
"appInfo": "应用信息",
|
||||||
|
"uniAppId": "uniapp应用id",
|
||||||
|
"uniAppIdTips": "uniapp应用id需在Dcloud开发者中心创建",
|
||||||
|
"toCreate": "前往Dcloud官网",
|
||||||
|
"appName": "应用名称",
|
||||||
|
"applicationId": "安卓应用包名",
|
||||||
|
"applicationIdTips": "安卓应用的包名是Android系统中用于唯一标识应用的字符串,采用反向域名格式(如com.example.myapp)。每个应用在系统中拥有唯一的包名,用于区分不同应用",
|
||||||
|
"androidAppKey": "安卓离线打包Key",
|
||||||
|
"androidAppKeyTips": "安卓离线打包Key在Dcloud开发者中心 - 应用管理 - 点击应用 - 各平台信息 创建以及查看离线AppKey"
|
||||||
|
}
|
||||||
49
admin/src/app/lang/zh-cn/channel.app.version.json
Normal file
49
admin/src/app/lang/zh-cn/channel.app.version.json
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
{
|
||||||
|
"accessFlow": "接入流程",
|
||||||
|
"versionManage": "版本管理",
|
||||||
|
"versionCode":"版本号",
|
||||||
|
"versionCodePlaceholder":"请输入版本号",
|
||||||
|
"versionCodeTips": "应用版本号,必须是整数,取值范围1~2147483647;必须高于上一版本设置的值",
|
||||||
|
"versionName":"版本名称",
|
||||||
|
"versionNamePlaceholder":"请输入版本名称",
|
||||||
|
"versionDesc":"",
|
||||||
|
"versionDescPlaceholder":"请输入",
|
||||||
|
"icon":"应用图标",
|
||||||
|
"iconPlaceholder":"请输入应用图标",
|
||||||
|
"push":"消息推送图标",
|
||||||
|
"pushPlaceholder":"请输入消息推送图标",
|
||||||
|
"splash":"应用启动页图标",
|
||||||
|
"splashPlaceholder":"请输入应用启动页的图标",
|
||||||
|
"platform":"客户端",
|
||||||
|
"packagePath":"安装包路径",
|
||||||
|
"packagePathPlaceholder":"请输入安装包路径",
|
||||||
|
"status":"状态",
|
||||||
|
"statusPlaceholder":"请输入状态",
|
||||||
|
"addAppVersion":"添加版本",
|
||||||
|
"updateAppVersion":"编辑版本",
|
||||||
|
"startDate":"请选择开始时间",
|
||||||
|
"endDate":"请选择结束时间",
|
||||||
|
"isForcedUpgrade": "强制升级",
|
||||||
|
"versionDesc": "更新内容",
|
||||||
|
"isForcedUpgradeTitle": "是否强制升级",
|
||||||
|
"releaseTime": "发布时间",
|
||||||
|
"release": "发布",
|
||||||
|
"resourceFile": "上传资源文件",
|
||||||
|
"androidResourceFileTips": "只能上传apk文件",
|
||||||
|
"iosResourceFileTips": "只能上传wgt文件",
|
||||||
|
"index": "序号",
|
||||||
|
"next": "下一步",
|
||||||
|
"prev": "上一步",
|
||||||
|
"certType": "证书类型",
|
||||||
|
"certFile": "证书文件",
|
||||||
|
"certAlias": "证书别名",
|
||||||
|
"certKeyPassword": "证书密码",
|
||||||
|
"certStorePassword": "证书库密码",
|
||||||
|
"publicCertTips": "niucloud提供的公共测试证书,证书的描述信息都是测试数据,任何人都可以使用,仅适合应用开发期间体验测试使用",
|
||||||
|
"privateCertTips": "Android平台打包发布apk应用,需要使用数字证书(.keystore文件)进行签名,用于表明开发者身份。",
|
||||||
|
"download": "下载",
|
||||||
|
"failReason": "失败原因",
|
||||||
|
"appVersionReleaseTips": "发布后无法再对该版本进行修改,确定要发布该版本吗?",
|
||||||
|
"appVersionDeleteTips": "确定要删除该版本吗?",
|
||||||
|
"upgradeType": "升级方式"
|
||||||
|
}
|
||||||
@ -7,5 +7,6 @@
|
|||||||
"validTimeTips": "过期后将重新获取定位信息",
|
"validTimeTips": "过期后将重新获取定位信息",
|
||||||
"validTimePlaceholder": "请输入定位有效期",
|
"validTimePlaceholder": "请输入定位有效期",
|
||||||
"validTimeFormatTips": "格式输入错误",
|
"validTimeFormatTips": "格式输入错误",
|
||||||
"validTimeNotZeroTips": "定位有效期不能小于5分钟"
|
"validTimeNotZeroTips": "定位有效期不能小于5分钟",
|
||||||
|
"aMapKey": "高德地图KEY"
|
||||||
}
|
}
|
||||||
@ -6,7 +6,7 @@
|
|||||||
<template v-if="Object.keys(marketingList).length">
|
<template v-if="Object.keys(marketingList).length">
|
||||||
|
|
||||||
<template v-for="(item, index) in marketingList" :key="index + 'b'">
|
<template v-for="(item, index) in marketingList" :key="index + 'b'">
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center" v-if="item.list.length > 0">
|
||||||
<span class="text-page-title">{{ item.title }}</span>
|
<span class="text-page-title">{{ item.title }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -3,9 +3,9 @@
|
|||||||
<div class="main-container">
|
<div class="main-container">
|
||||||
<el-card class="box-card !border-none" shadow="never">
|
<el-card class="box-card !border-none" shadow="never">
|
||||||
|
|
||||||
<!-- <div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<span class="text-page-title">{{ pageName }}</span>
|
<span class="text-page-title">{{ pageName }}</span>
|
||||||
</div> -->
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-between items-center mt-[20px]">
|
<div class="flex justify-between items-center mt-[20px]">
|
||||||
<el-form :inline="true" :model="roleTableData.searchParam" ref="searchFormRef">
|
<el-form :inline="true" :model="roleTableData.searchParam" ref="searchFormRef">
|
||||||
|
|||||||
@ -6,9 +6,7 @@
|
|||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<span class="text-page-title">{{ pageName }}</span>
|
<span class="text-page-title">{{ pageName }}</span>
|
||||||
</div>
|
</div>
|
||||||
<el-tabs v-model="activeName" class="mt-[20px]">
|
<div class="flex justify-between items-center mt-[20px]">
|
||||||
<el-tab-pane :label="t('管理员')" name="userList">
|
|
||||||
<div class="flex justify-between items-center mt-[20px]">
|
|
||||||
<el-form :inline="true" :model="userTableData.searchParam" ref="searchFormRef">
|
<el-form :inline="true" :model="userTableData.searchParam" ref="searchFormRef">
|
||||||
<el-form-item :label="t('accountNumber')" prop="search">
|
<el-form-item :label="t('accountNumber')" prop="search">
|
||||||
<el-input v-model.trim="userTableData.searchParam.search" class="input-width" :placeholder="t('accountNumberPlaceholder')" />
|
<el-input v-model.trim="userTableData.searchParam.search" class="input-width" :placeholder="t('accountNumberPlaceholder')" />
|
||||||
@ -84,11 +82,14 @@
|
|||||||
@size-change="loadUserList()" @current-change="loadUserList" />
|
@size-change="loadUserList()" @current-change="loadUserList" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- <el-tabs v-model="activeName" class="mt-[20px]">
|
||||||
|
<el-tab-pane :label="t('管理员')" name="userList">
|
||||||
|
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane :label="t('管理员角色')" name="userRole">
|
<el-tab-pane :label="t('管理员角色')" name="userRole">
|
||||||
<userRole></userRole>
|
<userRole></userRole>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs> -->
|
||||||
<edit-user ref="editUserDialog" @complete="loadUserList()" />
|
<edit-user ref="editUserDialog" @complete="loadUserList()" />
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
130
admin/src/app/views/channel/app/access.vue
Normal file
130
admin/src/app/views/channel/app/access.vue
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
<template>
|
||||||
|
<!--微信公众号-->
|
||||||
|
<div class="main-container">
|
||||||
|
<el-card class="card !border-none" shadow="never">
|
||||||
|
|
||||||
|
<div class="flex justify-between items-center">
|
||||||
|
<span class="text-page-title">{{ pageName }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-tabs v-model="activeName" class="my-[20px]" @tab-change="handleClick">
|
||||||
|
<el-tab-pane :label="t('accessFlow')" name="/channel/app" />
|
||||||
|
<el-tab-pane :label="t('versionManage')" name="/channel/app/version" />
|
||||||
|
</el-tabs>
|
||||||
|
|
||||||
|
<div class="p-[20px]">
|
||||||
|
<h3 class="panel-title !text-sm">{{ t("appInlet") }}</h3>
|
||||||
|
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="20">
|
||||||
|
<el-steps class="!mt-[10px]" :active="3" direction="vertical">
|
||||||
|
<el-step>
|
||||||
|
<template #title>
|
||||||
|
<p class="text-[14px] font-[700]">
|
||||||
|
{{ t("uniappApp") }}
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
|
<template #description>
|
||||||
|
<span class="text-[#999]">{{ t("appAttestation1") }}</span>
|
||||||
|
<div class="mt-[20px] mb-[40px] h-[32px]">
|
||||||
|
<el-button type="primary" @click="linkEvent('https://dcloud.io/')">{{ t("toCreate") }}</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-step>
|
||||||
|
|
||||||
|
<el-step>
|
||||||
|
<template #title>
|
||||||
|
<p class="text-[14px] font-[700]">
|
||||||
|
{{ t("appSetting") }}
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
|
<template #description>
|
||||||
|
<!-- <span class="text-[#999]">{{ t("wechatSetting1") }}</span>-->
|
||||||
|
<div class="mt-[20px] mb-[40px] h-[32px]">
|
||||||
|
<el-button type="primary" @click="router.push('/channel/app/config')">{{ t("settingInfo") }}</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-step>
|
||||||
|
|
||||||
|
<el-step>
|
||||||
|
<template #title>
|
||||||
|
<p class="text-[14px] font-[700]">
|
||||||
|
{{ t("versionManage") }}
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
|
<template #description>
|
||||||
|
<!-- <span class="text-[#999]">{{ t("wechatAccess") }}</span>-->
|
||||||
|
<div class="mt-[20px] mb-[40px] h-[32px]">
|
||||||
|
<el-button type="primary" plain @click="router.push('/channel/app/version')">{{ t("releaseVersion") }}</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-step>
|
||||||
|
</el-steps>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, onMounted, onUnmounted } from 'vue'
|
||||||
|
import { t } from '@/lang'
|
||||||
|
import { img } from '@/utils/common'
|
||||||
|
import { getWechatConfig } from '@/app/api/wechat'
|
||||||
|
import { getAuthorizationUrl } from '@/app/api/wxoplatform'
|
||||||
|
import { getWxoplatform } from '@/app/api/sys'
|
||||||
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const router = useRouter()
|
||||||
|
const pageName = route.meta.title
|
||||||
|
|
||||||
|
const activeName = ref('/channel/app')
|
||||||
|
const qrcode = ref('')
|
||||||
|
const wechatConfig = ref({})
|
||||||
|
const oplatformConfig = ref({})
|
||||||
|
|
||||||
|
const onShowGetWechatConfig = async () => {
|
||||||
|
await getWechatConfig().then(({ data }) => {
|
||||||
|
wechatConfig.value = data
|
||||||
|
qrcode.value = data.qr_code
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await onShowGetWechatConfig()
|
||||||
|
|
||||||
|
await getWxoplatform().then(({ data }) => {
|
||||||
|
oplatformConfig.value = data
|
||||||
|
})
|
||||||
|
|
||||||
|
document.addEventListener('visibilitychange', () => {
|
||||||
|
if (document.visibilityState === 'visible') {
|
||||||
|
onShowGetWechatConfig()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
document.removeEventListener('visibilitychange', () => {
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const linkEvent = (url: string) => {
|
||||||
|
window.open(url, '_blank')
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleClick = (val: any) => {
|
||||||
|
router.push({ path: activeName.value })
|
||||||
|
}
|
||||||
|
|
||||||
|
const authBindWechat = () => {
|
||||||
|
getAuthorizationUrl().then(({ data }) => {
|
||||||
|
window.open(data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
285
admin/src/app/views/channel/app/components/app-version-edit.vue
Normal file
285
admin/src/app/views/channel/app/components/app-version-edit.vue
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog v-model="showDialog" :title="formData.id ? t('updateAppVersion') : t('addAppVersion')" width="60%" class="diy-dialog-wrap" :destroy-on-close="true">
|
||||||
|
|
||||||
|
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
|
||||||
|
|
||||||
|
<div v-show="step == 1" class="h-[400px]">
|
||||||
|
<el-form-item :label="t('versionName')" prop="version_name">
|
||||||
|
<el-input v-model="formData.version_name" clearable :placeholder="t('versionNamePlaceholder')" class="input-width" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="t('versionCode')" prop="version_code">
|
||||||
|
<el-input v-model="formData.version_code" clearable :placeholder="t('versionCodePlaceholder')" class="input-width" />
|
||||||
|
<div class="form-tip">{{ t('versionCodeTips') }}</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="t('versionDesc')" prop="version_desc">
|
||||||
|
<el-input v-model="formData.version_desc" type="textarea" rows="6" clearable :placeholder="t('versionDescPlaceholder')" class="input-width" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="t('platform')" prop="platform">
|
||||||
|
<el-radio-group v-model="formData.platform">
|
||||||
|
<el-radio :label="key" size="large" v-for="(item, key) in appPlatform">{{ item }}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="t('isForcedUpgrade')" prop="is_forced_upgrade">
|
||||||
|
<el-switch v-model="formData.is_forced_upgrade" :active-value="1" :inactive-value="0"></el-switch>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-show="step == 2" class="h-[400px]">
|
||||||
|
<el-scrollbar>
|
||||||
|
<el-form-item :label="t('upgradeType')">
|
||||||
|
<el-radio-group v-model="formData.upgrade_type">
|
||||||
|
<el-radio label="app" size="large">APP整包升级</el-radio>
|
||||||
|
<el-radio label="hot" size="large">wgt资源包升级</el-radio>
|
||||||
|
<el-radio label="market" size="large">应用市场升级</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="t('resourceFile')" v-show="formData.upgrade_type == 'app'">
|
||||||
|
<el-radio-group v-model="formData.package_type">
|
||||||
|
<el-radio label="file" size="large">上传资源包</el-radio>
|
||||||
|
<el-radio label="cloud" size="large">云打包</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<div v-show="formData.package_type == 'file' && formData.upgrade_type != 'market'">
|
||||||
|
<el-form-item label="" prop="package_path">
|
||||||
|
<div class="input-width" >
|
||||||
|
<upload-file v-model="formData.package_path" :accept="accept" api="sys/document/app_package"></upload-file>
|
||||||
|
</div>
|
||||||
|
<div class="form-tip" v-if="formData.upgrade_type == 'app'">{{ t('androidResourceFileTips') }}</div>
|
||||||
|
<div class="form-tip" v-if="formData.upgrade_type == 'hot'">{{ t('iosResourceFileTips') }}</div>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-show="formData.upgrade_type == 'market'">
|
||||||
|
<el-form-item label="应用市场链接" prop="package_path">
|
||||||
|
<el-input v-model="formData.package_path" clearable class="input-width" />
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-show="formData.package_type == 'cloud'">
|
||||||
|
<el-form-item :label="t('icon')">
|
||||||
|
<div class="input-width" >
|
||||||
|
<upload-file v-model="formData.build.icon" accept=".zip" api="sys/document/applet"></upload-file>
|
||||||
|
</div>
|
||||||
|
<div class="form-tip !leading-[1.5]">应用图标和启动界面图片 icon.png为应用的图标 push.png为推送消息的图标 splash.png为应用启动页的图标 将icon.png、push.png、splash.png放置到drawable,drawable-ldpi,drawable-mdpi,drawable-hdpi,drawable-xhdpi,drawable-xxhdpi文件夹下压缩成压缩包上传,
|
||||||
|
具体详情可查看 <span class="text-primary cursor-pointer" @click="windowOpen('https://nativesupport.dcloud.net.cn/AppDocs/usesdk/android.html')">uniapp App离线打包</span>中“配置应用图标和启动界面”片段</div>
|
||||||
|
<div class="form-tip !leading-[1.5]">只支持上传.zip 在drawable的根目录进行压缩</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('certType')">
|
||||||
|
<el-radio-group v-model="formData.cert.type">
|
||||||
|
<el-radio label="public" size="large">公共证书</el-radio>
|
||||||
|
<el-radio label="private" size="large">自有证书</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
<div class="form-tip">{{ t('publicCertTips') }}</div>
|
||||||
|
<div class="form-tip !leading-[1.5]">{{ t('privateCertTips') }}<span class="text-primary cursor-pointer" @click="windowOpen('https://ask.dcloud.net.cn/article/35777')">《Android平台签名证书说明》</span></div>
|
||||||
|
<div class="form-tip flex items-center">证书可以自己生成也可通过niucloud提供的<span class="text-primary cursor-pointer" @click="generateSingCertRef.open()">证书生成工具生成</span></div>
|
||||||
|
</el-form-item>
|
||||||
|
<div v-show="formData.cert.type == 'private'">
|
||||||
|
<el-form-item :label="t('certFile')" prop="cert.cert_file">
|
||||||
|
<div class="input-width" >
|
||||||
|
<upload-file v-model="formData.cert.file" accept="" api="sys/document/android_cert"></upload-file>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('certAlias')" prop="cert.key_alias">
|
||||||
|
<el-input v-model="formData.cert.key_alias" clearable :placeholder="t('versionDescPlaceholder')" class="input-width" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('certKeyPassword')" prop="cert.key_password">
|
||||||
|
<el-input v-model="formData.cert.key_password" clearable :placeholder="t('versionDescPlaceholder')" class="input-width" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('certStorePassword')" prop="cert.store_password">
|
||||||
|
<el-input v-model="formData.cert.store_password" clearable :placeholder="t('versionDescPlaceholder')" class="input-width" />
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
|
||||||
|
<view v-show="step == 1">
|
||||||
|
<el-button type="primary" class="ml-3" @click="step = 2">{{
|
||||||
|
t('next')
|
||||||
|
}}</el-button>
|
||||||
|
</view>
|
||||||
|
<view v-show="step == 2">
|
||||||
|
<el-button type="primary" class="ml-3" @click="step = 1">{{
|
||||||
|
t('prev')
|
||||||
|
}}</el-button>
|
||||||
|
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{ t('confirm') }}</el-button>
|
||||||
|
</view>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<generate-sing-cert ref="generateSingCertRef"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, reactive, computed, watch } from 'vue'
|
||||||
|
import { t } from '@/lang'
|
||||||
|
import type { FormInstance } from 'element-plus'
|
||||||
|
import { addVersion, editVersion, getVersionInfo, getAppPlatform } from '@/app/api/app'
|
||||||
|
import GenerateSingCert from '@/app/views/channel/app/components/generate-sing-cert.vue'
|
||||||
|
|
||||||
|
const showDialog = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
const appPlatform = ref({})
|
||||||
|
const step = ref(1)
|
||||||
|
const generateSingCertRef = ref(null)
|
||||||
|
|
||||||
|
const getAppPlatformFn = async () => {
|
||||||
|
await getAppPlatform().then(({ data }) => {
|
||||||
|
appPlatform.value = data
|
||||||
|
initialFormData.platform = Object.keys(data)[0]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
getAppPlatformFn()
|
||||||
|
|
||||||
|
const accept = computed(() => {
|
||||||
|
if (formData.upgrade_type == 'app') return '.apk'
|
||||||
|
if (formData.upgrade_type == 'hot') return '.wgt'
|
||||||
|
return ''
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单数据
|
||||||
|
*/
|
||||||
|
const initialFormData = {
|
||||||
|
id: '',
|
||||||
|
version_code: '',
|
||||||
|
version_name: '',
|
||||||
|
version_desc: '',
|
||||||
|
platform: '',
|
||||||
|
is_forced_upgrade: 0,
|
||||||
|
package_path: '',
|
||||||
|
package_type: 'file',
|
||||||
|
upgrade_type: 'app',
|
||||||
|
build: {
|
||||||
|
icon: '',
|
||||||
|
},
|
||||||
|
cert: {
|
||||||
|
type: 'public',
|
||||||
|
key_alias: '',
|
||||||
|
key_password: '',
|
||||||
|
store_password: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const formData: Record<string, any> = reactive({ ...initialFormData })
|
||||||
|
|
||||||
|
const formRef = ref<FormInstance>()
|
||||||
|
|
||||||
|
watch(() => formData.upgrade_type, () => {
|
||||||
|
if (formData.upgrade_type == 'app' || formData.upgrade_type == 'hot') {
|
||||||
|
formData.package_type = 'file'
|
||||||
|
}
|
||||||
|
formData.package_path = ''
|
||||||
|
formData.cert.type = 'public'
|
||||||
|
})
|
||||||
|
|
||||||
|
// 表单验证规则
|
||||||
|
const formRules = computed(() => {
|
||||||
|
return {
|
||||||
|
version_code: [
|
||||||
|
{ required: true, message: t('versionCodePlaceholder'), trigger: 'blur' },
|
||||||
|
{
|
||||||
|
trigger: 'blur',
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
if (isNaN(value) || !/^\d{0,10}$/.test(value)) {
|
||||||
|
callback(new Error(t('versionCodeTips')))
|
||||||
|
} else if (value < 0) {
|
||||||
|
callback(new Error(t('versionCodeTips')))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
version_name: [
|
||||||
|
{ required: true, message: t('versionNamePlaceholder'), trigger: 'blur' }
|
||||||
|
],
|
||||||
|
package_path: [
|
||||||
|
{ required: formData.upgrade_type != 'market' && formData.package_type == 'file', message: '请上传资源文件', trigger: 'blur' },
|
||||||
|
{ required: formData.upgrade_type == 'market', message: '请输入应用市场链接', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
'build.icon': [
|
||||||
|
{ required: formData.package_type == 'cloud', message: '请上传图标文件', trigger: 'blur' },
|
||||||
|
],
|
||||||
|
'cert.cert_file': [
|
||||||
|
{ required: formData.package_type == 'cloud' && formData.cert.type == 'private', message: '请上传证书文件', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
'cert.key_alias': [
|
||||||
|
{ required: formData.package_type == 'cloud' && formData.cert.type == 'private', message: '请输入证书别名', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
'cert.key_password': [
|
||||||
|
{ required: formData.package_type == 'cloud' && formData.cert.type == 'private', message: '请上传证书密码', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
'cert.store_password': [
|
||||||
|
{ required: formData.package_type == 'cloud' && formData.cert.type == 'private', message: '请上传证书库密码', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['complete'])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认
|
||||||
|
* @param formEl
|
||||||
|
*/
|
||||||
|
const confirm = async (formEl: FormInstance | undefined) => {
|
||||||
|
if (loading.value || !formEl) return
|
||||||
|
const save = formData.id ? editVersion : addVersion
|
||||||
|
|
||||||
|
await formEl.validate(async (valid) => {
|
||||||
|
if (valid) {
|
||||||
|
loading.value = true
|
||||||
|
|
||||||
|
save(formData).then(res => {
|
||||||
|
loading.value = false
|
||||||
|
showDialog.value = false
|
||||||
|
emit('complete')
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const setFormData = async (row: any = null) => {
|
||||||
|
Object.assign(formData, initialFormData)
|
||||||
|
loading.value = true
|
||||||
|
if (row) {
|
||||||
|
const data = await (await getVersionInfo(row.id)).data
|
||||||
|
if (data) Object.keys(formData).forEach((key: string) => {
|
||||||
|
if (data[key] != undefined) formData[key] = data[key]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => showDialog.value, () => {
|
||||||
|
step.value = 1
|
||||||
|
})
|
||||||
|
|
||||||
|
const windowOpen = (url: string) => {
|
||||||
|
window.open(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
showDialog,
|
||||||
|
setFormData
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
|
<style lang="scss">
|
||||||
|
.diy-dialog-wrap .el-form-item__label{
|
||||||
|
height: auto !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,156 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog v-model="showDialog" title="生成Android证书" width="50%" class="diy-dialog-wrap" :destroy-on-close="true">
|
||||||
|
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
|
||||||
|
|
||||||
|
<el-form-item label="证书别名" prop="key_alias">
|
||||||
|
<el-input v-model="formData.key_alias" clearable placeholder="" class="input-width" />
|
||||||
|
<div class="form-tip">只支持字母,从证书文件中读取证书时需要别名</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="证书密码" prop="key_password">
|
||||||
|
<el-input v-model="formData.key_password" clearable placeholder="" class="input-width" />
|
||||||
|
<div class="form-tip">只支持字母或数字,密码至少 6 位,设置好后请牢记密码</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="证书库密码" prop="store_password">
|
||||||
|
<el-input v-model="formData.store_password" clearable placeholder="" class="input-width" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="有效期" prop="limit">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<el-input v-model="formData.limit" clearable placeholder="" class="w-[100px]" />
|
||||||
|
<div class="form-tip ml-2">年</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-tip">限 1 - 100 年之间</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<div class="text-primary cursor-pointer pl-[120px] my-[10px]" @click="moreInfo = !moreInfo">
|
||||||
|
{{ moreInfo ? '点击收起' : '点击展开填写更多信息 '}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<view v-show="moreInfo">
|
||||||
|
<el-form-item label="域名">
|
||||||
|
<el-input v-model="formData.cn" clearable placeholder="" class="input-width" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="组织名称">
|
||||||
|
<el-input v-model="formData.o" clearable placeholder="" class="input-width" />
|
||||||
|
<div class="form-tip">如公司名称或者其他名称</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="部门">
|
||||||
|
<el-input v-model="formData.ou" clearable placeholder="" class="input-width" />
|
||||||
|
<div class="form-tip">部门名称,如 IT 部、研发部等。</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="国家地区">
|
||||||
|
<el-input v-model="formData.c" clearable placeholder="" class="input-width" />
|
||||||
|
<div class="form-tip">输入国家/地区代号(两个字母),中国为CN</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="省份">
|
||||||
|
<el-input v-model="formData.st" clearable placeholder="" class="input-width" />
|
||||||
|
<div class="form-tip">所在省份名称,如Beijing</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="城市">
|
||||||
|
<el-input v-model="formData.l" clearable placeholder="" class="input-width" />
|
||||||
|
<div class="form-tip">所在城市名称,如Beijing</div>
|
||||||
|
</el-form-item>
|
||||||
|
</view>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="showDialog = false">取消</el-button>
|
||||||
|
<el-button type="primary" :loading="loading" @click="confirm(formRef)">生成</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive, computed } from 'vue'
|
||||||
|
import type { FormInstance } from 'element-plus'
|
||||||
|
import { generateSingCert } from '@/app/api/app'
|
||||||
|
import { img } from '@/utils/common'
|
||||||
|
|
||||||
|
const showDialog = ref(false)
|
||||||
|
const moreInfo = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const initialFormData = {
|
||||||
|
key_alias: '',
|
||||||
|
key_password: '',
|
||||||
|
store_password: '',
|
||||||
|
limit: 30,
|
||||||
|
cn: '',
|
||||||
|
o: '',
|
||||||
|
ou: '',
|
||||||
|
c: '',
|
||||||
|
st: '',
|
||||||
|
l: ''
|
||||||
|
}
|
||||||
|
const formData: Record<string, any> = reactive({ ...initialFormData })
|
||||||
|
|
||||||
|
const formRef = ref<FormInstance>()
|
||||||
|
|
||||||
|
// 表单验证规则
|
||||||
|
const formRules = computed(() => {
|
||||||
|
return {
|
||||||
|
key_alias: [
|
||||||
|
{ required: true, message: '请输入证书别名', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
key_password: [
|
||||||
|
{ required: true, message: '请输入证书密码', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
store_password: [
|
||||||
|
{ required: true, message: '请输入证书库密码', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
limit: [
|
||||||
|
{ required: true, message: '请输入有效期', trigger: 'blur' },
|
||||||
|
{
|
||||||
|
trigger: 'blur',
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
if (isNaN(value) || !/^\d{0,10}$/.test(value)) {
|
||||||
|
callback(new Error('有效期必须是数字'))
|
||||||
|
} else if (value < 0) {
|
||||||
|
callback(new Error('有效期必须为 1 - 100 之间的数字'))
|
||||||
|
} else if (value > 100) {
|
||||||
|
callback(new Error('有效期必须为 1 - 100 之间的数字'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
organization_name: [
|
||||||
|
{ required: true, message: '请输入所有者', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const confirm = async (formEl: FormInstance | undefined) => {
|
||||||
|
if (formEl) {
|
||||||
|
await formEl.validate()
|
||||||
|
loading.value = true
|
||||||
|
|
||||||
|
generateSingCert(formData).then(res => {
|
||||||
|
loading.value = false
|
||||||
|
showDialog.value = false
|
||||||
|
window.open(img(res.data), '_blank')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const open = async (row: any = null) => {
|
||||||
|
Object.assign(formData, initialFormData)
|
||||||
|
showDialog.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
open
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
129
admin/src/app/views/channel/app/config.vue
Normal file
129
admin/src/app/views/channel/app/config.vue
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
<template>
|
||||||
|
<!--小程序配置-->
|
||||||
|
<div class="main-container">
|
||||||
|
|
||||||
|
<el-card class="card !border-none" shadow="never">
|
||||||
|
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back()" />
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-form class="page-form mt-[15px]" :model="formData" label-width="170px" ref="formRef" :rules="formRules" v-loading="loading">
|
||||||
|
<el-card class="box-card !border-none mt-[15px]" shadow="never">
|
||||||
|
<h3 class="panel-title !text-sm">{{ t('appInfo') }}</h3>
|
||||||
|
|
||||||
|
<el-form-item :label="t('uniAppId')" prop="uni_app_id">
|
||||||
|
<el-input v-model.trim="formData.uni_app_id" placeholder="" class="input-width" clearable/>
|
||||||
|
<div class="form-tip flex items-center">
|
||||||
|
{{ t('uniAppIdTips') }}
|
||||||
|
<el-button link type="primary" @click="windowOpen('https://www.dcloud.io/')">{{ t('toCreate') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="t('appName')" prop="app_name">
|
||||||
|
<el-input v-model.trim="formData.app_name" placeholder="" class="input-width" clearable/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="t('androidAppKey')" prop="android_app_key">
|
||||||
|
<el-input v-model.trim="formData.android_app_key" placeholder="" class="input-width" clearable/>
|
||||||
|
<div class="form-tip">
|
||||||
|
{{ t('androidAppKeyTips') }}
|
||||||
|
<span class="text-primary cursor-pointer" @click="windowOpen('https://nativesupport.dcloud.net.cn/AppDocs/usesdk/appkey.html')">查看详情</span>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="t('applicationId')" prop="application_id">
|
||||||
|
<el-input v-model.trim="formData.application_id" placeholder="" class="input-width" clearable/>
|
||||||
|
<div class="form-tip">
|
||||||
|
{{ t('applicationIdTips') }}
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="box-card !border-none mt-[15px]" shadow="never">
|
||||||
|
<h3 class="panel-title !text-sm">{{ t('wechatAppInfo') }}</h3>
|
||||||
|
|
||||||
|
<el-form-item :label="t('wechatAppid')" prop="app_id">
|
||||||
|
<el-input v-model.trim="formData.wechat_app_id" :placeholder="t('appidPlaceholder')" class="input-width" clearable/>
|
||||||
|
<div class="form-tip">
|
||||||
|
{{ t('wechatAppidTips') }}
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="t('wechatAppsecret')" prop="app_secret">
|
||||||
|
<el-input v-model.trim="formData.wechat_app_secret" :placeholder="t('appSecretPlaceholder')" class="input-width" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
</el-card>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<div class="fixed-footer-wrap">
|
||||||
|
<div class="fixed-footer">
|
||||||
|
<el-button type="primary" :loading="loading" @click="save(formRef)">{{ t('save') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { reactive, ref, watch, computed } from 'vue'
|
||||||
|
import { t } from '@/lang'
|
||||||
|
import { getAppConfig, setAppConfig } from '@/app/api/app'
|
||||||
|
import { FormInstance } from "element-plus"
|
||||||
|
import { useRoute, useRouter } from "vue-router"
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const router = useRouter()
|
||||||
|
const pageName = route.meta.title
|
||||||
|
const loading = ref(true)
|
||||||
|
|
||||||
|
const formData = reactive<Record<string, any>>({
|
||||||
|
uni_app_id: '',
|
||||||
|
app_name: '',
|
||||||
|
android_app_key: '',
|
||||||
|
application_id: '',
|
||||||
|
wechat_app_id: '',
|
||||||
|
wechat_app_secret: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const formRef = ref<FormInstance>()
|
||||||
|
|
||||||
|
// 表单验证规则
|
||||||
|
const formRules = computed(() => {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取app配置
|
||||||
|
*/
|
||||||
|
getAppConfig().then(res => {
|
||||||
|
Object.assign(formData, res.data)
|
||||||
|
loading.value = false
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存
|
||||||
|
*/
|
||||||
|
const save = async (formEl: FormInstance | undefined) => {
|
||||||
|
if (loading.value || !formEl) return
|
||||||
|
|
||||||
|
await formEl.validate(async (valid) => {
|
||||||
|
if (valid) {
|
||||||
|
loading.value = true
|
||||||
|
setAppConfig(formData).then(() => {
|
||||||
|
loading.value = false
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const windowOpen = (url: string) => {
|
||||||
|
window.open(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
const back = () => {
|
||||||
|
router.push('/channel/app')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
237
admin/src/app/views/channel/app/version.vue
Normal file
237
admin/src/app/views/channel/app/version.vue
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
<template>
|
||||||
|
<div class="main-container">
|
||||||
|
<el-card class="box-card !border-none" shadow="never">
|
||||||
|
|
||||||
|
<div class="flex justify-between items-center">
|
||||||
|
<span class="text-lg">{{pageName}}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-tabs v-model="activeName" class="my-[20px]" @tab-change="handleClick">
|
||||||
|
<el-tab-pane :label="t('accessFlow')" name="/channel/app" />
|
||||||
|
<el-tab-pane :label="t('versionManage')" name="/channel/app/version" />
|
||||||
|
</el-tabs>
|
||||||
|
|
||||||
|
<el-alert type="info">
|
||||||
|
<template #default>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div>
|
||||||
|
<p>使用云打包提交成功后请先不要离开该页面稍待几分钟等待打包结果的返回</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-alert>
|
||||||
|
|
||||||
|
<div class="mt-[20px]">
|
||||||
|
<el-button type="primary" @click="addEvent">{{ t('addAppVersion') }}</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-[10px]">
|
||||||
|
<el-table :data="appVersionTable.data" size="large" v-loading="appVersionTable.loading">
|
||||||
|
<template #empty>
|
||||||
|
<span>{{ !appVersionTable.loading ? t('emptyData') : '' }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<el-table-column type="index" width="90" :label="t('index')" />
|
||||||
|
|
||||||
|
<el-table-column prop="version_code" :label="t('versionCode')" min-width="120" :show-overflow-tooltip="true"/>
|
||||||
|
|
||||||
|
<el-table-column prop="version_name" :label="t('versionName')" min-width="120" :show-overflow-tooltip="true"/>
|
||||||
|
|
||||||
|
<el-table-column prop="version_desc" :label="t('versionDesc')" min-width="120" :show-overflow-tooltip="true"/>
|
||||||
|
|
||||||
|
<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" :label="t('isForcedUpgradeTitle')" min-width="120" align="center" :show-overflow-tooltip="true">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.is_forced_upgrade ? '是' : '否' }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column prop="package_path" :label="t('packagePath')" min-width="120" :show-overflow-tooltip="true"/>
|
||||||
|
|
||||||
|
<el-table-column :label="t('releaseTime')" min-width="120" :show-overflow-tooltip="true">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<text v-if="row.release_time != 0">
|
||||||
|
{{ row.release_time }}
|
||||||
|
</text>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="200px">
|
||||||
|
<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.package_path && row.upgrade_type != 'market'" @click="downloadEvent(row)">{{ t('download') }}</el-button>
|
||||||
|
<el-button type="primary" link @click="deleteEvent(row)">{{ t('delete') }}</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
</el-table>
|
||||||
|
<div class="mt-[16px] flex justify-end">
|
||||||
|
<el-pagination v-model:current-page="appVersionTable.page" v-model:page-size="appVersionTable.limit"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper" :total="appVersionTable.total"
|
||||||
|
@size-change="loadAppVersionList()" @current-change="loadAppVersionList" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<edit ref="editAppVersionDialog" @complete="loadAppVersionList" />
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-dialog v-model="failReasonDialogVisible" :title="t('failReason')" width="60%">
|
||||||
|
<el-scrollbar class="h-[60vh] w-full whitespace-pre-wrap p-[20px]">
|
||||||
|
<div v-html="failReason"></div>
|
||||||
|
</el-scrollbar>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { reactive, ref } from 'vue'
|
||||||
|
import { t } from '@/lang'
|
||||||
|
import { img } 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'
|
||||||
|
const route = useRoute()
|
||||||
|
const router = useRouter()
|
||||||
|
const pageName = route.meta.title
|
||||||
|
const activeName = ref('/channel/app/version')
|
||||||
|
|
||||||
|
const appVersionTable = reactive({
|
||||||
|
page: 1,
|
||||||
|
limit: 10,
|
||||||
|
total: 0,
|
||||||
|
loading: true,
|
||||||
|
data: [],
|
||||||
|
searchParam: {
|
||||||
|
platfrom: ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleClick = (val: any) => {
|
||||||
|
router.push({ path: activeName.value })
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchFormRef = ref<FormInstance>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取app版本管理列表
|
||||||
|
*/
|
||||||
|
const loadAppVersionList = (page: number = 1) => {
|
||||||
|
appVersionTable.loading = true
|
||||||
|
appVersionTable.page = page
|
||||||
|
|
||||||
|
getVersionList({
|
||||||
|
page: appVersionTable.page,
|
||||||
|
limit: appVersionTable.limit,
|
||||||
|
...appVersionTable.searchParam
|
||||||
|
}).then(res => {
|
||||||
|
appVersionTable.loading = false
|
||||||
|
appVersionTable.data = res.data.data
|
||||||
|
appVersionTable.total = res.data.total
|
||||||
|
if (page == 1 && appVersionTable.data.length && appVersionTable.data[0].status == 'creating') getAppBuildLogFn(appVersionTable.data[0].task_key)
|
||||||
|
}).catch(() => {
|
||||||
|
appVersionTable.loading = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
loadAppVersionList()
|
||||||
|
|
||||||
|
const editAppVersionDialog: Record<string, any> | null = ref(null)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加app版本管理
|
||||||
|
*/
|
||||||
|
const addEvent = () => {
|
||||||
|
editAppVersionDialog.value.setFormData()
|
||||||
|
editAppVersionDialog.value.showDialog = true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑app版本管理
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
const editEvent = (data: any) => {
|
||||||
|
editAppVersionDialog.value.setFormData(data)
|
||||||
|
editAppVersionDialog.value.showDialog = true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除app版本管理
|
||||||
|
*/
|
||||||
|
const deleteEvent = (id: number) => {
|
||||||
|
ElMessageBox.confirm(t('appVersionDeleteTips'), t('warning'),
|
||||||
|
{
|
||||||
|
confirmButtonText: t('confirm'),
|
||||||
|
cancelButtonText: t('cancel'),
|
||||||
|
type: 'warning'
|
||||||
|
}
|
||||||
|
).then(() => {
|
||||||
|
deleteVersion({ id }).then(() => {
|
||||||
|
loadAppVersionList()
|
||||||
|
}).catch(() => {
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const releaseEvent = (data: any) => {
|
||||||
|
ElMessageBox.confirm(t('appVersionReleaseTips'), t('warning'),
|
||||||
|
{
|
||||||
|
confirmButtonText: t('confirm'),
|
||||||
|
cancelButtonText: t('cancel'),
|
||||||
|
type: 'warning'
|
||||||
|
}
|
||||||
|
).then(() => {
|
||||||
|
releaseVersion(data.id).then(() => {
|
||||||
|
loadAppVersionList()
|
||||||
|
}).catch(() => {
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getAppBuildLogFn = (key: string) => {
|
||||||
|
getBuildLog(key).then(res => {
|
||||||
|
if (res.data) {
|
||||||
|
if (res.data.status == '') {
|
||||||
|
setTimeout(() => {
|
||||||
|
getAppBuildLogFn(key)
|
||||||
|
}, 2000)
|
||||||
|
} else {
|
||||||
|
loadAppVersionList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const failReason = ref('')
|
||||||
|
const failReasonDialogVisible = ref(false)
|
||||||
|
const handleFailReason = (data: any) => {
|
||||||
|
failReason.value = data.fail_reason
|
||||||
|
failReasonDialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const downloadEvent = (data: any) => {
|
||||||
|
window.open(img(data.package_path), '_blank')
|
||||||
|
}
|
||||||
|
|
||||||
|
const resetForm = (formEl: FormInstance | undefined) => {
|
||||||
|
if (!formEl) return
|
||||||
|
formEl.resetFields()
|
||||||
|
loadAppVersionList()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
/* 多行超出隐藏 */
|
||||||
|
.multi-hidden {
|
||||||
|
word-break: break-all;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -250,10 +250,6 @@ getWeappConfig().then(res => {
|
|||||||
loading.value = false
|
loading.value = false
|
||||||
})
|
})
|
||||||
|
|
||||||
getWeappConfig().then(res => {
|
|
||||||
Object.assign(res.data)
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 复制
|
* 复制
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -185,7 +185,7 @@
|
|||||||
<el-slider v-model="diyStore.editComponent.margin.top" show-input size="small" :min="-100" class="ml-[10px] diy-nav-slider" />
|
<el-slider v-model="diyStore.editComponent.margin.top" show-input size="small" :min="-100" class="ml-[10px] diy-nav-slider" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('marginBottom')" v-if="diyStore.editComponent.ignore.indexOf('marginBottom') == -1">
|
<el-form-item :label="t('marginBottom')" v-if="diyStore.editComponent.ignore.indexOf('marginBottom') == -1">
|
||||||
<el-slider v-model="diyStore.editComponent.margin.bottom" show-input size="small" class="ml-[10px] diy-nav-slider" />
|
<el-slider v-model="diyStore.editComponent.margin.bottom" show-input size="small" class="ml-[10px] diy-nav-slider" :min="-100" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('marginBoth')" v-if="diyStore.editComponent.ignore.indexOf('marginBoth') == -1">
|
<el-form-item :label="t('marginBoth')" v-if="diyStore.editComponent.ignore.indexOf('marginBoth') == -1">
|
||||||
<el-slider v-model="diyStore.editComponent.margin.both" show-input size="small" class="ml-[10px] diy-nav-slider" />
|
<el-slider v-model="diyStore.editComponent.margin.both" show-input size="small" class="ml-[10px] diy-nav-slider" />
|
||||||
|
|||||||
@ -256,7 +256,7 @@ const editEvent = (data: any) => {
|
|||||||
// 设为使用
|
// 设为使用
|
||||||
const setUse = (id: any) => {
|
const setUse = (id: any) => {
|
||||||
setUseDiyPage({ id }).then(() => {
|
setUseDiyPage({ id }).then(() => {
|
||||||
loadDiyPageList()
|
loadDiyPageList(getTablePageStorage(diyPageTableData.searchParam).page)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const repeat = ref(false)
|
const repeat = ref(false)
|
||||||
@ -275,7 +275,7 @@ const copyEvent = (id: any) => {
|
|||||||
|
|
||||||
copyDiy({ id }).then((res: any) => {
|
copyDiy({ id }).then((res: any) => {
|
||||||
if (res.code == 1) {
|
if (res.code == 1) {
|
||||||
loadDiyPageList()
|
loadDiyPageList(getTablePageStorage(diyPageTableData.searchParam).page)
|
||||||
}
|
}
|
||||||
repeat.value = false
|
repeat.value = false
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
@ -294,7 +294,7 @@ const deleteEvent = (id: number) => {
|
|||||||
}
|
}
|
||||||
).then(() => {
|
).then(() => {
|
||||||
deleteDiyPage(id).then(() => {
|
deleteDiyPage(id).then(() => {
|
||||||
loadDiyPageList()
|
loadDiyPageList(getTablePageStorage(diyPageTableData.searchParam).page)
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -358,7 +358,7 @@ const shareEvent = async (formEl: FormInstance | undefined) => {
|
|||||||
id: shareFormId.value,
|
id: shareFormId.value,
|
||||||
share: JSON.stringify(shareFormData)
|
share: JSON.stringify(shareFormData)
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
loadDiyPageList()
|
loadDiyPageList(getTablePageStorage(diyPageTableData.searchParam).page)
|
||||||
shareDialogVisible.value = false
|
shareDialogVisible.value = false
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
})
|
})
|
||||||
|
|||||||
@ -159,10 +159,10 @@
|
|||||||
<spread-popup ref="spreadPopupRef" />
|
<spread-popup ref="spreadPopupRef" />
|
||||||
|
|
||||||
<!-- 表单提交成功页弹出框 -->
|
<!-- 表单提交成功页弹出框 -->
|
||||||
<form-submit-popup ref="formSubmitPopupRef" @complete="loadDiyFormList" />
|
<form-submit-popup ref="formSubmitPopupRef" @complete="loadDiyFormList(getTablePageStorage(diyFormTableData.searchParam).page)" />
|
||||||
|
|
||||||
<!-- 表单填写设置弹出框 -->
|
<!-- 表单填写设置弹出框 -->
|
||||||
<form-write-popup ref="formWritePopupRef" @complete="loadDiyFormList" />
|
<form-write-popup ref="formWritePopupRef" @complete="loadDiyFormList(getTablePageStorage(diyFormTableData.searchParam).page)" />
|
||||||
|
|
||||||
<records-detail ref="recordsDetailDialog"/>
|
<records-detail ref="recordsDetailDialog"/>
|
||||||
|
|
||||||
@ -352,7 +352,7 @@ const copyEvent = (id: any) => {
|
|||||||
|
|
||||||
copyForm({ form_id: id }).then((res: any) => {
|
copyForm({ form_id: id }).then((res: any) => {
|
||||||
if (res.code == 1) {
|
if (res.code == 1) {
|
||||||
loadDiyFormList()
|
loadDiyFormList(getTablePageStorage(diyFormTableData.searchParam).page)
|
||||||
}
|
}
|
||||||
repeat.value = false
|
repeat.value = false
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
@ -371,7 +371,7 @@ const deleteEvent = (form_id: number) => {
|
|||||||
}
|
}
|
||||||
).then(() => {
|
).then(() => {
|
||||||
deleteDiyForm({ form_ids: [form_id] }).then(() => {
|
deleteDiyForm({ form_ids: [form_id] }).then(() => {
|
||||||
loadDiyFormList()
|
loadDiyFormList(getTablePageStorage(diyFormTableData.searchParam).page)
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -438,7 +438,7 @@ const batchDeleteForms = () => {
|
|||||||
deleteDiyForm({
|
deleteDiyForm({
|
||||||
form_ids
|
form_ids
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
loadDiyFormList()
|
loadDiyFormList(getTablePageStorage(diyFormTableData.searchParam).page)
|
||||||
repeat.value = false
|
repeat.value = false
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
repeat.value = false
|
repeat.value = false
|
||||||
@ -497,7 +497,7 @@ const shareEvent = async (formEl: FormInstance | undefined) => {
|
|||||||
form_id: shareFormId.value,
|
form_id: shareFormId.value,
|
||||||
share: JSON.stringify(shareFormData)
|
share: JSON.stringify(shareFormData)
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
loadDiyFormList()
|
loadDiyFormList(getTablePageStorage(diyFormTableData.searchParam).page)
|
||||||
shareDialogVisible.value = false
|
shareDialogVisible.value = false
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
})
|
})
|
||||||
|
|||||||
@ -307,22 +307,18 @@ const newVersion = ref<NewVersion>({
|
|||||||
// 插件
|
// 插件
|
||||||
const appList = ref<any>([])
|
const appList = ref<any>([])
|
||||||
const getAppIndexFn = () => {
|
const getAppIndexFn = () => {
|
||||||
loading.value = true
|
|
||||||
getAppIndex().then((res) => {
|
getAppIndex().then((res) => {
|
||||||
console.log(res)
|
|
||||||
appList.value = res.data
|
appList.value = res.data
|
||||||
loading.value = false
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
getAppIndexFn()
|
|
||||||
const bannerlistr = ref<any>([])
|
const bannerlistr = ref<any>([])
|
||||||
const getAdvListFn = () => {
|
const getAdvListFn = () => {
|
||||||
getAdvList().then((res) => {
|
getAdvList().then((res) => {
|
||||||
console.log(res.data)
|
|
||||||
bannerlistr.value = res.data
|
bannerlistr.value = res.data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
getAdvListFn()
|
|
||||||
const getInfoFn = () => {
|
const getInfoFn = () => {
|
||||||
if (copyright.value.copyright_desc) {
|
if (copyright.value.copyright_desc) {
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
@ -349,9 +345,8 @@ const getStatInfoFn = async() => {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
drawChart()
|
drawChart()
|
||||||
}, 20)
|
}, 20)
|
||||||
loading.value = false
|
|
||||||
}
|
}
|
||||||
getStatInfoFn()
|
|
||||||
|
|
||||||
// 绘制折线图
|
// 绘制折线图
|
||||||
const drawChart = () => {
|
const drawChart = () => {
|
||||||
@ -494,6 +489,25 @@ onMounted(() => {
|
|||||||
showQuickStart.value = localStorage.getItem('showQuickStart') !== 'false'
|
showQuickStart.value = localStorage.getItem('showQuickStart') !== 'false'
|
||||||
showNiuCloud.value = localStorage.getItem('showNiuCloud') !== 'false'
|
showNiuCloud.value = localStorage.getItem('showNiuCloud') !== 'false'
|
||||||
showBanner.value = localStorage.getItem('showBanner') !== 'false'
|
showBanner.value = localStorage.getItem('showBanner') !== 'false'
|
||||||
|
|
||||||
|
// 定义异步初始化函数
|
||||||
|
const initData = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
await Promise.all([
|
||||||
|
getStatInfoFn(),
|
||||||
|
getAdvListFn(),
|
||||||
|
getAppIndexFn()
|
||||||
|
]);
|
||||||
|
|
||||||
|
loading.value = false;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('初始化失败', error);
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 执行初始化函数
|
||||||
|
initData();
|
||||||
})
|
})
|
||||||
|
|
||||||
const closeModule = (module:any) => {
|
const closeModule = (module:any) => {
|
||||||
|
|||||||
@ -121,7 +121,7 @@ const formRules = computed(() => {
|
|||||||
if (!value) return callback()
|
if (!value) return callback()
|
||||||
|
|
||||||
// 非空值时,验证身份证号格式
|
// 非空值时,验证身份证号格式
|
||||||
const reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
|
const reg = /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/
|
||||||
if (!reg.test(value)) {
|
if (!reg.test(value)) {
|
||||||
callback(new Error('请输入正确的身份证号'))
|
callback(new Error('请输入正确的身份证号'))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -147,7 +147,7 @@ const deleteEvent = (id: number) => {
|
|||||||
}
|
}
|
||||||
).then(() => {
|
).then(() => {
|
||||||
deleteMemberLevel(id).then(() => {
|
deleteMemberLevel(id).then(() => {
|
||||||
loadMemberLevelList()
|
loadMemberLevelList(getTablePageStorage(memberLevelTableData.searchParam).page);
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -225,7 +225,7 @@ const modifyPosterStatusFn = (id:any, status:any) => {
|
|||||||
modifyPosterStatus({
|
modifyPosterStatus({
|
||||||
id, status
|
id, status
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
loadPosterPageList()
|
loadPosterPageList(getTablePageStorage(posterTableData.searchParam).page)
|
||||||
isRepeat.value = false
|
isRepeat.value = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -237,7 +237,7 @@ const modifyPosterDefaultFn = (id:any) => {
|
|||||||
modifyPosterDefault({
|
modifyPosterDefault({
|
||||||
id
|
id
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
loadPosterPageList()
|
loadPosterPageList(getTablePageStorage(posterTableData.searchParam).page)
|
||||||
isRepeat.value = false
|
isRepeat.value = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -254,7 +254,7 @@ const deleteEvent = (id: number) => {
|
|||||||
if (isRepeat.value) return
|
if (isRepeat.value) return
|
||||||
isRepeat.value = true
|
isRepeat.value = true
|
||||||
deletePoster(id).then(() => {
|
deletePoster(id).then(() => {
|
||||||
loadPosterPageList()
|
loadPosterPageList(getTablePageStorage(posterTableData.searchParam).page)
|
||||||
isRepeat.value = false
|
isRepeat.value = false
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
isRepeat.value = false
|
isRepeat.value = false
|
||||||
|
|||||||
@ -129,7 +129,7 @@ const modifyPrinterStatusEvent = (printer_id: any, status: any) => {
|
|||||||
printer_id,
|
printer_id,
|
||||||
status
|
status
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
loadPrinterList()
|
loadPrinterList(getTablePageStorage(printerTable.searchParam).page)
|
||||||
isRepeat.value = false
|
isRepeat.value = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -163,7 +163,7 @@ const deleteEvent = (id: number) => {
|
|||||||
if (repeat.value) return
|
if (repeat.value) return
|
||||||
repeat.value = true
|
repeat.value = true
|
||||||
deletePrinter(id).then(() => {
|
deletePrinter(id).then(() => {
|
||||||
loadPrinterList()
|
loadPrinterList(getTablePageStorage(printerTable.searchParam).page)
|
||||||
repeat.value = false
|
repeat.value = false
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
repeat.value = false
|
repeat.value = false
|
||||||
@ -214,7 +214,7 @@ const refreshTokenEvent = (printer_id: any) => {
|
|||||||
if (repeat.value) return
|
if (repeat.value) return
|
||||||
repeat.value = true
|
repeat.value = true
|
||||||
refreshPrinterToken(printer_id).then((res: any) => {
|
refreshPrinterToken(printer_id).then((res: any) => {
|
||||||
loadPrinterList()
|
loadPrinterList(getTablePageStorage(printerTable.searchParam).page)
|
||||||
repeat.value = false
|
repeat.value = false
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
repeat.value = false
|
repeat.value = false
|
||||||
|
|||||||
@ -148,7 +148,7 @@ const deleteEvent = (id: number) => {
|
|||||||
}
|
}
|
||||||
).then(() => {
|
).then(() => {
|
||||||
deletePrinterTemplate(id).then(() => {
|
deletePrinterTemplate(id).then(() => {
|
||||||
loadPrinterTemplateList()
|
loadPrinterTemplateList(getTablePageStorage(printerTemplateTable.searchParam).page)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,15 +22,19 @@
|
|||||||
<h3 class="panel-title !text-[14px] bg-[#F4F5F7] p-3 border-[#E6E6E6] border-solid border-b-[1px]">{{ t('putOnRecordEdit') }}</h3>
|
<h3 class="panel-title !text-[14px] bg-[#F4F5F7] p-3 border-[#E6E6E6] border-solid border-b-[1px]">{{ t('putOnRecordEdit') }}</h3>
|
||||||
<el-form-item :label="t('icp')" prop="icp">
|
<el-form-item :label="t('icp')" prop="icp">
|
||||||
<el-input v-model.trim="formData.icp" :placeholder="t('icpPlaceholder')" class="input-width" clearable maxlength="20"/>
|
<el-input v-model.trim="formData.icp" :placeholder="t('icpPlaceholder')" class="input-width" clearable maxlength="20"/>
|
||||||
|
<div class="form-tip">{{ t('网站的ICP备案号,显示在H5和PC端底部') }}</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('govRecord')" >
|
<el-form-item :label="t('govRecord')" >
|
||||||
<el-input v-model.trim="formData.gov_record" :placeholder="t('govRecordPlaceholder')" class="input-width" clearable maxlength="50"/>
|
<el-input v-model.trim="formData.gov_record" :placeholder="t('govRecordPlaceholder')" class="input-width" clearable maxlength="50"/>
|
||||||
|
<div class="form-tip">{{ t('公安部门登记的备案信息,显示在pc底部') }}</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('govUrl')" >
|
<el-form-item :label="t('govUrl')" >
|
||||||
<el-input v-model.trim="formData.gov_url" :placeholder="t('govUrlPlaceholder')" class="input-width" clearable />
|
<el-input v-model.trim="formData.gov_url" :placeholder="t('govUrlPlaceholder')" class="input-width" clearable />
|
||||||
|
<div class="form-tip">{{ t('H5和PC底部显示的网站公安点击跳转的链接') }}</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('marketSupervisionUrl')" >
|
<el-form-item :label="t('marketSupervisionUrl')" >
|
||||||
<el-input v-model.trim="formData.market_supervision_url" rows="4" clearable :placeholder="t('marketSupervisionUrlPlaceholder')" class="input-width" />
|
<el-input v-model.trim="formData.market_supervision_url" rows="4" clearable :placeholder="t('marketSupervisionUrlPlaceholder')" class="input-width" />
|
||||||
|
<div class="form-tip">{{ t('H5和PC底部显示的市场监督管理局点击跳转的链接') }}</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|||||||
@ -10,7 +10,11 @@
|
|||||||
<el-form-item :label="t('mapKey')" prop="key">
|
<el-form-item :label="t('mapKey')" prop="key">
|
||||||
<el-input v-model.trim="formData.key" class="input-width" clearable />
|
<el-input v-model.trim="formData.key" class="input-width" clearable />
|
||||||
<span class="ml-2 cursor-pointer tutorial-btn" @click="tutorialFn">{{ t('clickTutorial') }}</span>
|
<span class="ml-2 cursor-pointer tutorial-btn" @click="tutorialFn">{{ t('clickTutorial') }}</span>
|
||||||
<span class="ml-2 cursor-pointer secret-btn" @click="secretFn">{{ t('clickSecretKey') }}</span>
|
<span class="ml-2 cursor-pointer secret-btn" @click="secretFn('https://lbs.qq.com/dev/console/key/manage')">{{ t('clickSecretKey') }}</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('aMapKey')" prop="key">
|
||||||
|
<el-input v-model.trim="formData.amap_key" class="input-width" clearable />
|
||||||
|
<span class="ml-2 cursor-pointer secret-btn" @click="secretFn('https://lbs.amap.com/')">{{ t('clickSecretKey') }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('isOpen')" prop="is_open">
|
<el-form-item :label="t('isOpen')" prop="is_open">
|
||||||
<el-switch v-model="formData.is_open" :active-value="1" :inactive-value="0" />
|
<el-switch v-model="formData.is_open" :active-value="1" :inactive-value="0" />
|
||||||
@ -42,6 +46,7 @@ const loading = ref(true)
|
|||||||
const formRef = ref<FormInstance>()
|
const formRef = ref<FormInstance>()
|
||||||
const formData = reactive({
|
const formData = reactive({
|
||||||
key: '',
|
key: '',
|
||||||
|
amap_key: '',
|
||||||
is_open: 0,
|
is_open: 0,
|
||||||
valid_time: 0
|
valid_time: 0
|
||||||
})
|
})
|
||||||
@ -107,8 +112,8 @@ const tutorialFn = () => {
|
|||||||
/**
|
/**
|
||||||
* 点击访问腾讯地图
|
* 点击访问腾讯地图
|
||||||
*/
|
*/
|
||||||
const secretFn = () => {
|
const secretFn = (url: string) => {
|
||||||
window.open('https://lbs.qq.com/dev/console/key/manage')
|
window.open(url)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -328,7 +328,7 @@ const deleteEvent = (id: number) => {
|
|||||||
}
|
}
|
||||||
).then(() => {
|
).then(() => {
|
||||||
deleteGenerateTable(id).then(() => {
|
deleteGenerateTable(id).then(() => {
|
||||||
loadGenerateTableList()
|
loadGenerateTableList(getTablePageStorage(codeTableData.searchParam).page)
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -378,7 +378,7 @@ const generateCreateFn = (id: any, generate_type: any) => {
|
|||||||
codeTableData.loading = false
|
codeTableData.loading = false
|
||||||
window.open(img(res.data.file), '_blank')
|
window.open(img(res.data.file), '_blank')
|
||||||
} else {
|
} else {
|
||||||
loadGenerateTableList()
|
loadGenerateTableList(getTablePageStorage(codeTableData.searchParam).page)
|
||||||
}
|
}
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
codeTableData.loading = false
|
codeTableData.loading = false
|
||||||
|
|||||||
@ -365,7 +365,10 @@ const getAttachmentList = debounce((page: number = 1) => {
|
|||||||
attachment.data[i].image_list.push(img(res.data.data[i].thumb))
|
attachment.data[i].image_list.push(img(res.data.data[i].thumb))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).catch(() => {
|
}).catch((err) => {
|
||||||
|
if (prop.type == 'image' && err.response.status == 500) {
|
||||||
|
showElMessage({ message: 'php脚本内存不足请加大php配置中memory_limit的数值, <a style="text-decoration: underline;" href="https://www.kancloud.cn/niucloud/niucloud-admin-develop/3249216" target="blank">点击查看相关手册</a>', type: 'error', dangerouslyUseHTMLString: true })
|
||||||
|
}
|
||||||
attachment.loading = false
|
attachment.loading = false
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -23,6 +23,10 @@ const prop = defineProps({
|
|||||||
api: {
|
api: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'sys/document/document'
|
default: 'sys/document/document'
|
||||||
|
},
|
||||||
|
accept: {
|
||||||
|
type: String,
|
||||||
|
default: '.doc,.docx,.xml,.txt,.pem,.zip,.rar,.7z,.crt,.key,.xls,.xlsx'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -37,23 +41,27 @@ const value = computed({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const upload: Record<string, any> = {
|
const upload = computed(() => {
|
||||||
action: `${import.meta.env.VITE_APP_BASE_URL}/${prop.api}`,
|
const headers: Record<string, any> = {}
|
||||||
showFileList: false,
|
headers[import.meta.env.VITE_REQUEST_HEADER_TOKEN_KEY] = getToken()
|
||||||
headers: {},
|
headers[import.meta.env.VITE_REQUEST_HEADER_SITEID_KEY] = storage.get('siteId') || 0
|
||||||
accept: '.doc,.docx,.xml,.txt,.pem,.zip,.rar,.7z,.crt,.key,.xls,.xlsx',
|
const baseURL = import.meta.env.VITE_APP_BASE_URL.substr(-1) == '/' ? import.meta.env.VITE_APP_BASE_URL : `${import.meta.env.VITE_APP_BASE_URL}/`
|
||||||
onSuccess: (response: any, uploadFile: UploadFile) => {
|
|
||||||
if (response.code != undefined && response.code != 1) {
|
|
||||||
ElMessage({ message: response.msg, type: 'error' })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
value.value = response.data.url
|
|
||||||
ElMessage({ message: t('upload.success'), type: 'success' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
upload.headers[import.meta.env.VITE_REQUEST_HEADER_TOKEN_KEY] = getToken()
|
|
||||||
upload.headers[import.meta.env.VITE_REQUEST_HEADER_SITEID_KEY] = storage.get('siteId') || 0
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
action: `${baseURL}${prop.api}`,
|
||||||
|
showFileList: false,
|
||||||
|
accept: prop.accept,
|
||||||
|
headers,
|
||||||
|
onSuccess: (response: any, uploadFile: UploadFile) => {
|
||||||
|
if (response.code != undefined && response.code != 1) {
|
||||||
|
ElMessage({ message: response.msg, type: 'error' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
value.value = response.data.url
|
||||||
|
ElMessage({ message: t('upload.success'), type: 'success' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
@ -32,7 +32,7 @@
|
|||||||
<!-- 面包屑导航 -->
|
<!-- 面包屑导航 -->
|
||||||
<div class="flex items-center h-full pl-[10px] hidden-xs-only">
|
<div class="flex items-center h-full pl-[10px] hidden-xs-only">
|
||||||
<el-breadcrumb separator="/">
|
<el-breadcrumb separator="/">
|
||||||
<el-breadcrumb-item v-for="(route, index) in breadcrumb" :key="index">{{route.meta.title }}</el-breadcrumb-item>
|
<el-breadcrumb-item v-for="(route, index) in breadcrumb" :key="index" :to="route.path" class="inter">{{route.meta.title }}</el-breadcrumb-item>
|
||||||
</el-breadcrumb>
|
</el-breadcrumb>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -23,7 +23,7 @@
|
|||||||
<!-- 面包屑导航 -->
|
<!-- 面包屑导航 -->
|
||||||
<div class="flex items-center h-full pl-[10px] hidden-xs-only">
|
<div class="flex items-center h-full pl-[10px] hidden-xs-only">
|
||||||
<el-breadcrumb separator="/">
|
<el-breadcrumb separator="/">
|
||||||
<el-breadcrumb-item v-for="(route, index) in breadcrumb" :key="index">{{route.meta.title }}</el-breadcrumb-item>
|
<el-breadcrumb-item v-for="(route, index) in breadcrumb" :key="index" :to="route.path" class="inter">{{route.meta.title }}</el-breadcrumb-item>
|
||||||
</el-breadcrumb>
|
</el-breadcrumb>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
<!-- 面包屑导航 -->
|
<!-- 面包屑导航 -->
|
||||||
<div class="flex items-center h-full pl-[10px] hidden-xs-only">
|
<div class="flex items-center h-full pl-[10px] hidden-xs-only">
|
||||||
<el-breadcrumb separator="/">
|
<el-breadcrumb separator="/">
|
||||||
<el-breadcrumb-item v-for="(route, index) in breadcrumb" :key="index">{{route.meta.title }}</el-breadcrumb-item>
|
<el-breadcrumb-item v-for="(route, index) in breadcrumb" :key="index" :to="route.path" class="inter">{{route.meta.title }}</el-breadcrumb-item>
|
||||||
</el-breadcrumb>
|
</el-breadcrumb>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
<!-- 面包屑导航 -->
|
<!-- 面包屑导航 -->
|
||||||
<div class="flex items-center h-full pl-[10px]">
|
<div class="flex items-center h-full pl-[10px]">
|
||||||
<el-breadcrumb separator="/">
|
<el-breadcrumb separator="/">
|
||||||
<el-breadcrumb-item v-for="(route, index) in breadcrumb" :key="index">{{route.meta.title }}</el-breadcrumb-item>
|
<el-breadcrumb-item v-for="(route, index) in breadcrumb" :key="index" :to="route.path" class="inter">{{route.meta.title }}</el-breadcrumb-item>
|
||||||
</el-breadcrumb>
|
</el-breadcrumb>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
<div class="flex items-center h-full pl-[10px]">
|
<div class="flex items-center h-full pl-[10px]">
|
||||||
<el-breadcrumb separator="/">
|
<el-breadcrumb separator="/">
|
||||||
<!-- :to="route.path" class="inter" 这种修改方式导致部分跳转不对,需要重新调整菜单才可以 -->
|
<!-- :to="route.path" class="inter" 这种修改方式导致部分跳转不对,需要重新调整菜单才可以 -->
|
||||||
<el-breadcrumb-item v-for="(route, index) in breadcrumb" :key="index">{{route.meta.title }}</el-breadcrumb-item>
|
<el-breadcrumb-item v-for="(route, index) in breadcrumb" :to="route.path" class="inter" :key="index">{{route.meta.title }}</el-breadcrumb-item>
|
||||||
</el-breadcrumb>
|
</el-breadcrumb>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
<div class="flex items-center h-full pl-[10px] hidden-xs-only">
|
<div class="flex items-center h-full pl-[10px] hidden-xs-only">
|
||||||
<el-breadcrumb separator="/">
|
<el-breadcrumb separator="/">
|
||||||
<!-- :to="route.path" class="inter" 这种修改方式导致部分跳转不对,需要重新调整菜单才可以 -->
|
<!-- :to="route.path" class="inter" 这种修改方式导致部分跳转不对,需要重新调整菜单才可以 -->
|
||||||
<el-breadcrumb-item v-for="(route, index) in breadcrumb" :key="index">{{route.meta.title }}</el-breadcrumb-item>
|
<el-breadcrumb-item v-for="(route, index) in breadcrumb" :key="index" :to="route.path" class="inter">{{route.meta.title }}</el-breadcrumb-item>
|
||||||
</el-breadcrumb>
|
</el-breadcrumb>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user