mirror of
https://gitee.com/niucloud-team/niucloud-admin.git
synced 2026-02-22 08:30:26 +00:00
up
This commit is contained in:
parent
5457b86e0a
commit
319aa2a6db
@ -189,4 +189,4 @@ export function changeTemplate(params: Record<string, any>) {
|
||||
*/
|
||||
export function getApps(params: Record<string, any>) {
|
||||
return request.get(`diy/apps`)
|
||||
}
|
||||
}
|
||||
|
||||
174
admin/src/app/api/web.ts
Normal file
174
admin/src/app/api/web.ts
Normal file
@ -0,0 +1,174 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 获取PC导航管理列表
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export function getNavList(params: Record<string, any>) {
|
||||
return request.get(`web/nav`, {params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取PC导航管理详情
|
||||
* @param id PC导航管理id
|
||||
* @returns
|
||||
*/
|
||||
export function getNavInfo(id: number) {
|
||||
return request.get(`web/nav/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加PC导航管理
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export function addNav(params: Record<string, any>) {
|
||||
return request.post('web/nav', params, { showErrorMessage: true, showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑PC导航管理
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export function editNav(params: Record<string, any>) {
|
||||
return request.put(`web/nav/${params.id}`, params, { showErrorMessage: true, showSuccessMessage: true })
|
||||
}
|
||||
/**
|
||||
* 编辑友情链接排序
|
||||
* @param params
|
||||
*/
|
||||
export function editNavSort(params: Record<string, any>) {
|
||||
return request.put(`web/nav/sort`, params, { showErrorMessage: true, showSuccessMessage: true })
|
||||
}
|
||||
/**
|
||||
* 删除PC导航管理
|
||||
* @param id
|
||||
* @returns
|
||||
*/
|
||||
export function deleteNav(id: number) {
|
||||
return request.delete(`web/nav/${id}`, { showErrorMessage: true, showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取PC端自定义链接列表
|
||||
* @param params
|
||||
*/
|
||||
export function getLink(params: Record<string, any>) {
|
||||
return request.get(`web/link`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取友情链接列表
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export function getFriendlyLinkList(params: Record<string, any>) {
|
||||
return request.get(`web/friendly_link`, {params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取友情链接详情
|
||||
* @param id 友情链接id
|
||||
* @returns
|
||||
*/
|
||||
export function getFriendlyLinkInfo(id: number) {
|
||||
return request.get(`web/friendly_link/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加友情链接
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export function addFriendlyLink(params: Record<string, any>) {
|
||||
return request.post('web/friendly_link', params, { showErrorMessage: true, showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑友情链接
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export function editFriendlyLink(params: Record<string, any>) {
|
||||
return request.put(`web/friendly_link/${params.id}`, params, { showErrorMessage: true, showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除友情链接
|
||||
* @param id
|
||||
* @returns
|
||||
*/
|
||||
export function deleteFriendlyLink(id: number) {
|
||||
return request.delete(`web/friendly_link/${id}`, { showErrorMessage: true, showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑友情链接排序
|
||||
* @param params
|
||||
*/
|
||||
export function editFriendlyLinkSort(params: Record<string, any>) {
|
||||
return request.put(`web/friendly_link/sort`, params, { showErrorMessage: true, showSuccessMessage: true })
|
||||
}
|
||||
/**
|
||||
* 获取广告位列表
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export function getAvdPositionList(params: Record<string, any>) {
|
||||
return request.get(`web/adv_position`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取广告列表
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export function getAdvList(params: Record<string, any>) {
|
||||
return request.get(`web/adv`, { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除广告
|
||||
* @param id
|
||||
* @returns
|
||||
*/
|
||||
export function deleteAdv(id: number) {
|
||||
return request.delete(`web/adv/${ id }`, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加广告
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export function addAdv(params: Record<string, any>) {
|
||||
return request.post('web/adv', params, { showErrorMessage: true, showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑广告
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export function editAdv(params: Record<string, any>) {
|
||||
return request.put(`web/adv/${ params.adv_id }`, params, { showErrorMessage: true, showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑友情链接排序
|
||||
* @param params
|
||||
*/
|
||||
export function editAdvSort(params: Record<string, any>) {
|
||||
return request.put(`web/adv/sort`, params, { showErrorMessage: true, showSuccessMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取广告详情
|
||||
* @param id id
|
||||
* @returns
|
||||
*/
|
||||
export function getAdvInfo(id: number) {
|
||||
return request.get(`web/adv/${ id }`);
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 113 KiB |
BIN
admin/src/app/assets/images/login/login_index_bg.jpg
Normal file
BIN
admin/src/app/assets/images/login/login_index_bg.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 117 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.7 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 32 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 87 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.5 KiB |
@ -62,6 +62,8 @@
|
||||
"imageUpload": "图片上传",
|
||||
"imageSet": "图片设置",
|
||||
"imageAdsTips": "建议上传尺寸相同的图片,推荐尺寸750*350",
|
||||
"imageAdsSameScreenTips": "开启沉浸式样式,请确保该图片广告组件在页面中位于最顶端;为保证体验,请不要开导航栏;沉浸式样式仅在微信小程序中生效。",
|
||||
"sameScreen": "沉浸式",
|
||||
"addImageAd": "添加图片",
|
||||
"imageUrlTip": "请上传图片",
|
||||
"imageHeight": "图片高度",
|
||||
|
||||
@ -29,8 +29,8 @@
|
||||
"detaBirth": "出生日期",
|
||||
"sex": "性别",
|
||||
"wxUnionid": "微信unionid",
|
||||
"weappOpenid": "微信用户openid",
|
||||
"wxOpenid": "微信小程序openid",
|
||||
"weappOpenid": "微信小程序openid",
|
||||
"wxOpenid": "微信用户openid",
|
||||
"head": "会员头像",
|
||||
"username": "用户名",
|
||||
"usernamePlaceholder": "请输入用户名",
|
||||
|
||||
@ -13,9 +13,9 @@
|
||||
"mchId": "商户号",
|
||||
"mchIdPlaceholder": "请输入商户号",
|
||||
"mchIdTips": "微信支付商户号(MCHID)",
|
||||
"mchSecretKey": "API密钥",
|
||||
"mchSecretKeyPlaceholder": "请输入API密钥",
|
||||
"mchSecretKeyTips": "微信支付商户API密钥(paySignKey)",
|
||||
"mchSecretKey": "APIv3密钥",
|
||||
"mchSecretKeyPlaceholder": "请输入APIv3密钥",
|
||||
"mchSecretKeyTips": "微信支付商户APIv3密钥(paySignKey)",
|
||||
"mchSecretCert": "商户私钥",
|
||||
"mchSecretCertPlaceholder": "请上传商户私钥",
|
||||
"mchSecretCertTips": "微信支付API证书(apiclient_key.pem)",
|
||||
|
||||
@ -4,9 +4,9 @@
|
||||
"mchId": "商户号",
|
||||
"mchIdPlaceholder": "请输入商户号",
|
||||
"mchIdTips": "微信支付商户号(MCHID)",
|
||||
"mchSecretKey": "API密钥",
|
||||
"mchSecretKeyPlaceholder": "请输入API密钥",
|
||||
"mchSecretKeyTips": "微信支付商户API密钥(paySignKey)",
|
||||
"mchSecretKey": "APIv3密钥",
|
||||
"mchSecretKeyPlaceholder": "请输入APIv3密钥",
|
||||
"mchSecretKeyTips": "微信支付商户APIv3密钥(paySignKey)",
|
||||
"mchSecretCert": "商户私钥",
|
||||
"mchSecretCertPlaceholder": "请上传商户私钥",
|
||||
"mchSecretCertTips": "微信支付API证书(apiclient_key.pem)",
|
||||
@ -28,4 +28,4 @@
|
||||
"alipayPublicCertPathTips": "上传alipayCertPublicKey文件",
|
||||
"alipayRootCertPathTips": "上传alipayRootCert文件",
|
||||
"operationTip": "温馨提示:打款设置用于会员提现转账,发放红包等场景"
|
||||
}
|
||||
}
|
||||
|
||||
16
admin/src/app/lang/zh-cn/web.adv.json
Normal file
16
admin/src/app/lang/zh-cn/web.adv.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"addAdv": "添加广告",
|
||||
"updateAdv": "编辑广告",
|
||||
"advName": "广告名称",
|
||||
"advNamePlaceholder": "请输入广告位名称",
|
||||
"advPosition": "所属广告位",
|
||||
"advUrl": "广告链接",
|
||||
"advUrlPlaceholder": "请选择链接地址",
|
||||
"advImg": "广告图片",
|
||||
"advImagePlaceholder": "请上传广告图片",
|
||||
"background": "背景色",
|
||||
"sort": "排序号",
|
||||
"sortPlaceholder": "请输入排序号",
|
||||
"sortTips": "排序号格式输入错误",
|
||||
"advDeleteTips": "确定要删除该数据吗?"
|
||||
}
|
||||
6
admin/src/app/lang/zh-cn/web.adv_position.json
Normal file
6
admin/src/app/lang/zh-cn/web.adv_position.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"apName": "广告位名称",
|
||||
"keywords": "广告关键字",
|
||||
"operation": "操作",
|
||||
"manageAdv": "管理广告"
|
||||
}
|
||||
19
admin/src/app/lang/zh-cn/web.friendly_link.json
Normal file
19
admin/src/app/lang/zh-cn/web.friendly_link.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"linkPic": "图片",
|
||||
"linkPicPlaceholder": "请输入图片",
|
||||
"linkTitle": "标题",
|
||||
"linkTitlePlaceholder": "请输入标题",
|
||||
"linkUrl": "链接",
|
||||
"linkUrlPlaceholder": "请输入链接",
|
||||
"sort": "排序号",
|
||||
"sortPlaceholder": "请输入排序号",
|
||||
"sortTips": "排序号格式输入错误",
|
||||
"isShow": "是否显示",
|
||||
"isShowPlaceholder": "请输入是否显示",
|
||||
"addFriendlyLink": "添加友情链接",
|
||||
"updateFriendlyLink": "编辑友情链接",
|
||||
"friendlyLinkDeleteTips": "确定要删除该数据吗?",
|
||||
"startDate": "请选择开始时间",
|
||||
"endDate": "请选择结束时间",
|
||||
"addressTips": "链接格式错误"
|
||||
}
|
||||
15
admin/src/app/lang/zh-cn/web.nav.json
Normal file
15
admin/src/app/lang/zh-cn/web.nav.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"navTitle": "导航名称",
|
||||
"navTitlePlaceholder": "请输入导航名称",
|
||||
"navUrl": "链接地址",
|
||||
"navUrlPlaceholder": "请选择链接地址",
|
||||
"sort": "排序号",
|
||||
"sortPlaceholder": "请输入排序号",
|
||||
"sortTips": "排序号格式输入错误",
|
||||
"isBlank": "新窗口打开",
|
||||
"createTime": "创建时间",
|
||||
"isShow": "是否显示",
|
||||
"addNav": "添加导航",
|
||||
"updateNav": "编辑导航",
|
||||
"navDeleteTips": "确定要删除该数据吗?"
|
||||
}
|
||||
@ -77,7 +77,7 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('sort')">
|
||||
<el-input-number v-model="formData.sort" :min="0" max="99999999" />
|
||||
<el-input-number v-model="formData.sort" :min="0" max="8" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<div class="main-container">
|
||||
|
||||
<el-card class="card !border-none" shadow="never">
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="$router.back()" />
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back()" />
|
||||
</el-card>
|
||||
|
||||
<el-form class="page-form mt-[15px]" :model="formData" label-width="150px" ref="formRef" v-loading="loading">
|
||||
@ -98,6 +98,9 @@ import { useRoute, useRouter } from 'vue-router'
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
const back = () => {
|
||||
router.push('/channel/aliapp')
|
||||
}
|
||||
|
||||
const loading = ref(true)
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<div class="main-container">
|
||||
|
||||
<el-card class="card !border-none" shadow="never">
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="$router.back()" />
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back()" />
|
||||
</el-card>
|
||||
|
||||
<el-card class="box-card mt-[15px] !border-none" shadow="never">
|
||||
@ -99,6 +99,9 @@ import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const back = () => {
|
||||
router.push('/channel/aliapp')
|
||||
}
|
||||
const pageName = route.meta.title
|
||||
const loading = ref(true)
|
||||
const formData = reactive<Record<string, string>>({
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
<div class="cursor-pointer" @click="copyEvent(formData.request_url)">{{ t('copy') }}</div>
|
||||
</template>
|
||||
</el-input>
|
||||
<span class="ml-2 cursor-pointer visit-btn">{{t('clickVisit')}}</span>
|
||||
<span class="ml-2 cursor-pointer visit-btn" @click="visitFn">{{t('clickVisit')}}</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<div class="main-container">
|
||||
|
||||
<el-card class="card !border-none" shadow="never">
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="$router.back()" />
|
||||
<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">
|
||||
@ -139,7 +139,9 @@ import { useRoute, useRouter } from 'vue-router'
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
|
||||
const back = () => {
|
||||
router.push('/channel/weapp')
|
||||
}
|
||||
const loading = ref(true)
|
||||
|
||||
const formData = reactive<Record<string, any>>({
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<div class="main-container">
|
||||
|
||||
<el-card class="card !border-none" shadow="never">
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="$router.back()" />
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back()" />
|
||||
</el-card>
|
||||
|
||||
<el-card class="box-card mt-[15px] !border-none" shadow="never">
|
||||
@ -63,7 +63,9 @@ import { useRoute, useRouter } from 'vue-router'
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
|
||||
const back = () => {
|
||||
router.push('/channel/weapp')
|
||||
}
|
||||
const linkEvent = () => {
|
||||
window.open('https://mp.weixin.qq.com/', '_blank')
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<div class="main-container">
|
||||
|
||||
<el-card class="card !border-none" shadow="never">
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="$router.back()" />
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back()" />
|
||||
</el-card>
|
||||
|
||||
<el-form class="page-form mt-[15px]" :model="formData" label-width="150px" ref="formRef" :rules="formRules" v-loading="loading">
|
||||
@ -129,7 +129,9 @@ import { useRoute, useRouter } from 'vue-router'
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
|
||||
const back = () => {
|
||||
router.push('/channel/wechat')
|
||||
}
|
||||
const loading = ref(true)
|
||||
|
||||
const formData = reactive<Record<string, any>>({
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<div class="main-container">
|
||||
|
||||
<el-card class="card !border-none" shadow="never">
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="$router.back()" />
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back()" />
|
||||
</el-card>
|
||||
|
||||
<el-card class="box-card mt-[15px] pt-[20px] !border-none" shadow="never">
|
||||
@ -60,6 +60,9 @@ import { useRouter, useRoute } from 'vue-router'
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title
|
||||
const router = useRouter()
|
||||
const back = () => {
|
||||
router.push('/channel/wechat')
|
||||
}
|
||||
const loading = ref(true)
|
||||
const formData = reactive<Record<string, string>>({
|
||||
wechat_name: '',
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<div class="main-container">
|
||||
|
||||
<el-card class="card !border-none" shadow="never">
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="$router.back()" />
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back()" />
|
||||
</el-card>
|
||||
|
||||
<el-form class="page-form mt-[15px]" :model="formData" label-width="150px" ref="formRef" :rules="formRules" v-loading="loading">
|
||||
@ -92,6 +92,10 @@ import NewsCard from '@/app/views/channel/wechat/components/news-card.vue'
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
const back = () => {
|
||||
router.push('/channel/wechat/reply')
|
||||
}
|
||||
|
||||
const showDialog = ref(false)
|
||||
|
||||
const formData: any = reactive({
|
||||
|
||||
@ -185,6 +185,12 @@
|
||||
<el-radio :label="'italics'">{{t('btnTextItalics')}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('topRounded')">
|
||||
<el-slider v-model="diyStore.editComponent.topElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('bottomRounded')">
|
||||
<el-slider v-model="diyStore.editComponent.bottomElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
|
||||
@ -94,7 +94,7 @@ import { img } from '@/utils/common'
|
||||
import { range } from 'lodash-es'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = ['pageBgColor','marginTop','marginBottom','marginBoth'] // 忽略公共属性
|
||||
diyStore.editComponent.ignore = ['pageBgColor','marginTop','marginBottom','marginBoth','componentBgUrl'] // 忽略公共属性
|
||||
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
@ -222,5 +222,5 @@ defineExpose({})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
|
||||
</style>
|
||||
|
||||
@ -38,7 +38,7 @@ import useDiyStore from '@/stores/modules/diy'
|
||||
import { img } from '@/utils/common'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = [] // 忽略公共属性
|
||||
diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
|
||||
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
|
||||
@ -4,6 +4,11 @@
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('imageSet') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
|
||||
<el-form-item :label="t('sameScreen')" v-if="diyStore.currentIndex == 0">
|
||||
<el-switch v-model="diyStore.editComponent.isSameScreen" />
|
||||
<div class="text-sm text-gray-400 leading-[1.4]">{{ t('imageAdsSameScreenTips') }}</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('imageHeight')" class="display-block">
|
||||
<el-input v-model.trim="diyStore.editComponent.imageHeight" :placeholder="t('imageHeightPlaceholder')" clearable maxlength="10" @blur="blurImageHeight">
|
||||
@ -52,7 +57,7 @@ import { range } from 'lodash-es'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = [] // 忽略公共属性
|
||||
diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
|
||||
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
|
||||
@ -102,9 +102,31 @@ const changeStyle = (item:any) => {
|
||||
const confirmStyle = () => {
|
||||
diyStore.editComponent.styleName = selectStyle.title;
|
||||
diyStore.editComponent.style = selectStyle.value;
|
||||
initStyle(diyStore.editComponent.style);
|
||||
showDialog.value = false
|
||||
}
|
||||
|
||||
|
||||
const initStyle = (style: any) => {
|
||||
if (style == 'style-1') {
|
||||
diyStore.editComponent.bottomRounded = 0;
|
||||
diyStore.editComponent.topRounded = 12;
|
||||
} else if (style == 'style-2') {
|
||||
diyStore.editComponent.bottomRounded = 0;
|
||||
diyStore.editComponent.topRounded = 12;
|
||||
} else if (style == 'style-3') {
|
||||
diyStore.editComponent.bottomRounded = 12;
|
||||
diyStore.editComponent.topRounded = 12;
|
||||
} else if (style == 'style-4') {
|
||||
diyStore.editComponent.bottomRounded = 12;
|
||||
diyStore.editComponent.topRounded = 12;
|
||||
} else if (style == 'style-5') {
|
||||
diyStore.editComponent.bottomRounded = 12;
|
||||
diyStore.editComponent.topRounded = 12;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
defineExpose({})
|
||||
|
||||
</script>
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
<el-form-item :label="t('image')">
|
||||
<upload-image v-model="diyStore.editComponent.moduleOne.head.textImg" :limit="1"/>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
<el-form-item :label="t('subTitle')">
|
||||
<el-input v-model.trim="diyStore.editComponent.moduleOne.head.subText" :placeholder="t('subTitlePlaceholder')" clearable maxlength="8" show-word-limit />
|
||||
</el-form-item>
|
||||
@ -125,7 +125,7 @@ import { img } from '@/utils/common'
|
||||
import { ref, reactive } from 'vue'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = [] // 忽略公共属性
|
||||
diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
|
||||
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
|
||||
@ -129,6 +129,7 @@ import { t } from '@/lang'
|
||||
import { getApps,getDiyPageList, deleteDiyPage, getDiyTemplate, editDiyPageShare, setUseDiyPage } from '@/app/api/diy'
|
||||
import { ElMessageBox, FormInstance } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { setTablePageStorage,getTablePageStorage } from "@/utils/common";
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@ -234,12 +235,13 @@ const loadDiyPageList = (page: number = 1) => {
|
||||
diyPageTableData.loading = false
|
||||
diyPageTableData.data = res.data.data
|
||||
diyPageTableData.total = res.data.total
|
||||
setTablePageStorage(diyPageTableData.page, diyPageTableData.limit, diyPageTableData.searchParam);
|
||||
}).catch(() => {
|
||||
diyPageTableData.loading = false
|
||||
})
|
||||
}
|
||||
|
||||
loadDiyPageList()
|
||||
loadDiyPageList(getTablePageStorage(diyPageTableData.searchParam).page);
|
||||
|
||||
// 编辑自定义页面
|
||||
const editEvent = (data: any) => {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="main-container">
|
||||
<el-card class="card !border-none" shadow="never">
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="$router.back()" />
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back()" />
|
||||
</el-card>
|
||||
|
||||
<el-card class="box-card mt-[15px] !border-none" shadow="never" v-loading="loading">
|
||||
|
||||
@ -89,6 +89,7 @@ const setFormData = async (row: any = null) => {
|
||||
const getRefundListInfo = async (no) => {
|
||||
loading.value = true
|
||||
formData.value = null
|
||||
refundList.value = [];
|
||||
await getPayRefundInfo(no).then(({ data }) => {
|
||||
formData.value = data
|
||||
refundList.value.push(data)
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<div class="main-container">
|
||||
|
||||
<el-card class="card !border-none" shadow="never">
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="$router.back()" />
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back()" />
|
||||
</el-card>
|
||||
|
||||
<el-card class="box-card mt-[15px] !border-none relative" shadow="never" v-if="formData">
|
||||
@ -66,6 +66,9 @@ import { ArrowLeft } from '@element-plus/icons-vue'
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
const back = () => {
|
||||
router.push('/finance/refund')
|
||||
}
|
||||
|
||||
const refundNo: any = route.query.refund_no
|
||||
const loading = ref(true)
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
</el-card>
|
||||
<div class="fixed-footer-wrap">
|
||||
<div class="fixed-footer">
|
||||
<el-button type="primary" :loading="loading" @click="save(formRef)">{{ t('save') }}</el-button>
|
||||
<el-button type="primary" :loading="loading" @click="submitForm(formRef)">{{ t('save') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<el-container :class="['w-full h-screen bg-page flex flex-col']">
|
||||
<el-container :class="['w-full h-screen bg-page flex flex-col','login-wrap']">
|
||||
<template v-if="!imgLoading">
|
||||
<!-- 平台端登录 -->
|
||||
<el-main class="login-main items-center justify-center">
|
||||
<div class="flex rounded-2xl overflow-hidden">
|
||||
<el-main class="login-main items-center justify-center flex-1 h-0">
|
||||
<div class="flex rounded-2xl shadow overflow-hidden">
|
||||
<div class="login-main-left w-[450px] flex flex-wrap justify-center">
|
||||
<el-image v-if="loginConfig.bg" class="w-[450px] h-[400px]" :src="img(loginConfig.bg)" fit="cover" />
|
||||
<img v-else src="@/app/assets/images/login/niushop_login_index_left.jpg" alt="">
|
||||
@ -11,29 +11,17 @@
|
||||
<div class="login flex flex-col w-[400px] h-[400px] p-[40px]">
|
||||
<h3 class="text-center text-lg font-bold mb-[10px]">{{ webSite.site_name || t('siteTitle') }}</h3>
|
||||
<h3 class="text-center text-2xl font-bold mb-[26px]">{{ t('platform') }}</h3>
|
||||
|
||||
<el-form :model="form" ref="formRef" :rules="formRules">
|
||||
<el-form :model="form" ref="formRef" :rules="formRules" class="mt-[30px]">
|
||||
<el-form-item prop="username">
|
||||
<el-input v-model="form.username" :placeholder="t('userPlaceholder')"
|
||||
@keyup.enter="handleLogin(formRef)" class="h-[40px] input-with-select">
|
||||
<template #prepend>
|
||||
<icon name="element User" />
|
||||
</template>
|
||||
</el-input>
|
||||
<el-input v-model.trim="form.username" :placeholder="t('userPlaceholder')" autocomplete="off" @keyup.enter="handleLogin(formRef)" class="h-[40px]"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="password">
|
||||
<el-input v-model="form.password" :placeholder="t('passwordPlaceholder')" type="password"
|
||||
@keyup.enter="handleLogin(formRef)" :show-password="true"
|
||||
class="h-[40px] input-with-select">
|
||||
<template #prepend>
|
||||
<icon name="element Lock" />
|
||||
</template>
|
||||
</el-input>
|
||||
<el-input v-model.trim="form.password" :placeholder="t('passwordPlaceholder')" type="password" autocomplete="new-password" @keyup.enter="handleLogin(formRef)" :show-password="true" class="h-[40px]"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" class="mt-[30px] h-[40px] w-full" @click="handleLogin(formRef)" :loading="loading">{{ loading ? t('logging') : t('login') }}</el-button>
|
||||
<el-button type="primary" class="mt-[30px] !h-[40px] w-full" @click="handleLogin(formRef)" :loading="loading">{{ loading ? t('logging') : t('login') }}</el-button>
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
@ -41,24 +29,22 @@
|
||||
</div>
|
||||
</el-main>
|
||||
|
||||
<div class="flex items-center justify-center mt-[20px] text-[#999] text-sm pb-8" v-if="copyright">
|
||||
<a :href="copyright.gov_url" v-if="copyright.gov_record" class="flex" target="_blank">
|
||||
<img src="@/app/assets/images/gov_icon.png" alt="" class="h-[20px] mr-1">
|
||||
<span class="mr-3">公安备案号:{{ copyright.gov_record }}</span>
|
||||
</a>
|
||||
<a href="https://beian.miit.gov.cn/" target="_blank" v-if="copyright.icp">
|
||||
<span class="mr-3">备案号:{{ copyright.icp }}</span>
|
||||
</a>
|
||||
<div class="flex items-center justify-center mt-[20px] pb-[20px] text-sm text-[#999]" v-if="copyright">
|
||||
<a :href="copyright.copyright_link" target="_blank">
|
||||
<span class="mr-3" v-if="copyright.copyright_desc">{{ copyright.copyright_desc }}</span>
|
||||
<span class="mr-3" v-if="copyright.company_name">{{ copyright.company_name }}</span>
|
||||
<span class="mr-3" v-if="copyright.copyright_desc">©{{ copyright.copyright_desc }}</span>
|
||||
</a>
|
||||
<a href="https://beian.miit.gov.cn/" v-if="copyright.icp" target="_blank">
|
||||
<span class="mr-3">{{ copyright.icp }}</span>
|
||||
</a>
|
||||
<a :href="copyright.gov_url" v-if="copyright.gov_record" target="_blank">
|
||||
<span class="mr-3">{{ copyright.gov_record }}</span>
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 验证组件 -->
|
||||
<verify @success="success" :mode="pop" captchaType="blockPuzzle" :imgSize="{ width: '330px', height: '155px' }"
|
||||
ref="verifyRef"></verify>
|
||||
<verify @success="success" :mode="pop" captchaType="blockPuzzle" :imgSize="{ width: '330px', height: '155px' }" ref="verifyRef"></verify>
|
||||
</el-container>
|
||||
</template>
|
||||
|
||||
@ -67,7 +53,6 @@ import { inject, reactive, ref } from 'vue'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { t } from '@/lang'
|
||||
import storage from '@/utils/storage'
|
||||
import { getLoginConfig } from '@/app/api/auth'
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
import { setWindowTitle, img } from '@/utils/common'
|
||||
@ -154,33 +139,21 @@ const loginFn = (data = {}) => {
|
||||
|
||||
<style lang="scss">
|
||||
.login-wrap {
|
||||
background-image: url("@/app/assets/images/login/login_index_bg.png");
|
||||
background-image: url("@/app/assets/images/login/login_index_bg.jpg");
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.login-site-main {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.input-with-select .el-input-group__prepend {
|
||||
background-color: var(--el-fill-color-blank);
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.login-main {
|
||||
display: flex !important;
|
||||
}
|
||||
|
||||
.login {
|
||||
background: var(--el-bg-color);
|
||||
}
|
||||
.login {
|
||||
background: var(--el-bg-color);
|
||||
}
|
||||
|
||||
.admin_name {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
-o-text-overflow: ellipsis;
|
||||
.el-form-item__error {
|
||||
top : 45px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 750px) {
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<div class="main-container" v-loading="loading">
|
||||
|
||||
<el-card class="card !border-none" shadow="never">
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="$router.back()" />
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back()" />
|
||||
</el-card>
|
||||
|
||||
<el-card class="box-card mt-[15px] !border-none" shadow="never">
|
||||
@ -101,6 +101,9 @@ import useAppStore from '@/stores/modules/app'
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
const back = () => {
|
||||
router.push('/marketing/verify')
|
||||
}
|
||||
|
||||
const appStore = useAppStore()
|
||||
const loading = ref(true)
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
<el-input v-model.trim="formData.memo" type="textarea" rows="4" clearable :placeholder="t('memoPlaceholder')" class="input-width" maxlength="200" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('sort')" prop="sort">
|
||||
<el-input v-model.trim="formData.sort" clearable maxlength="6" show-word-limit :placeholder="t('sortPlaceholder')" class="input-width" @keyup="filterNumber($event)" />
|
||||
<el-input v-model.trim="formData.sort" clearable maxlength="8" show-word-limit :placeholder="t('sortPlaceholder')" class="input-width" @keyup="filterNumber($event)" />
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
|
||||
@ -73,6 +73,7 @@ import { t } from '@/lang'
|
||||
import { getMemberLevelPageList, deleteMemberLevel } from '@/app/api/member'
|
||||
import { ElMessageBox, FormInstance } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { setTablePageStorage,getTablePageStorage } from "@/utils/common";
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@ -112,11 +113,12 @@ const loadMemberLevelList = (page: number = 1) => {
|
||||
memberLevelTableData.loading = false
|
||||
memberLevelTableData.data = res.data.data
|
||||
memberLevelTableData.total = res.data.total
|
||||
setTablePageStorage(memberLevelTableData.page, memberLevelTableData.limit, memberLevelTableData.searchParam);
|
||||
}).catch(() => {
|
||||
memberLevelTableData.loading = false
|
||||
})
|
||||
}
|
||||
loadMemberLevelList()
|
||||
loadMemberLevelList(getTablePageStorage(memberLevelTableData.searchParam).page);
|
||||
|
||||
/**
|
||||
* 添加会员标签
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<div class="main-container">
|
||||
|
||||
<el-card class="card !border-none" shadow="never">
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="$router.back()" />
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back()" />
|
||||
</el-card>
|
||||
|
||||
<el-card class="box-card mt-[15px] !border-none" shadow="never" v-loading="loading">
|
||||
@ -28,12 +28,12 @@
|
||||
|
||||
<h3 class="panel-title !text-sm">{{ t('levelBenefits') }}</h3>
|
||||
<div class="pl-[100px]">
|
||||
<member-benefits ref="benefitsRef" v-model="formData.level_benefits"/>
|
||||
<member-benefits v-if="!loading" ref="benefitsRef" v-model="formData.level_benefits"/>
|
||||
</div>
|
||||
|
||||
<h3 class="panel-title !text-sm">{{ t('levelGift') }}</h3>
|
||||
<div class="pl-[100px]">
|
||||
<member-gift ref="giftRef" v-model="formData.level_gifts"/>
|
||||
<member-gift v-if="!loading" ref="giftRef" v-model="formData.level_gifts"/>
|
||||
</div>
|
||||
|
||||
</el-card>
|
||||
@ -61,6 +61,10 @@ const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
|
||||
const back = () => {
|
||||
router.push('/member/level')
|
||||
}
|
||||
|
||||
const benefitsRef = ref(null)
|
||||
const giftRef = ref(null)
|
||||
const loading = ref(true)
|
||||
|
||||
@ -104,7 +104,7 @@ import { t } from '@/lang'
|
||||
import { ElMessageBox, FormInstance } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { getPosterPageList,getPosterType,modifyPosterStatus,modifyPosterDefault,deletePoster,getPreviewPoster } from '@/app/api/poster'
|
||||
import { img } from '@/utils/common'
|
||||
import { img,setTablePageStorage,getTablePageStorage } from '@/utils/common'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
@ -192,12 +192,13 @@ const loadPosterPageList = (page: number = 1) => {
|
||||
posterTableData.loading = false
|
||||
posterTableData.data = res.data.data
|
||||
posterTableData.total = res.data.total
|
||||
setTablePageStorage(posterTableData.page, posterTableData.limit, posterTableData.searchParam);
|
||||
}).catch(() => {
|
||||
posterTableData.loading = false
|
||||
})
|
||||
}
|
||||
|
||||
loadPosterPageList()
|
||||
loadPosterPageList(getTablePageStorage(posterTableData.searchParam).page);
|
||||
|
||||
// 编辑自定义海报
|
||||
const editEvent = (data: any) => {
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
|
||||
<el-card class="card !border-none" shadow="never">
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="$router.back()" />
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back()" />
|
||||
</el-card>
|
||||
|
||||
<el-card class="box-card mt-[15px] !border-none" shadow="never" v-loading="loading">
|
||||
|
||||
@ -71,7 +71,7 @@ const formData = reactive({
|
||||
is_auto_transfer: '0',
|
||||
is_auto_verify: '0',
|
||||
is_open: '0',
|
||||
min: '0.01',
|
||||
min: '0',
|
||||
rate: '0',
|
||||
transfer_type: []
|
||||
})
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container" v-loading="loading">
|
||||
|
||||
<el-card class="card !border-none" shadow="never">
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="$router.back()" />
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back()" />
|
||||
</el-card>
|
||||
|
||||
<el-card class="box-card mt-[15px] !border-none" shadow="never">
|
||||
@ -97,6 +97,10 @@ import { useRouter, useRoute } from 'vue-router'
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
|
||||
const back = () => {
|
||||
router.push('/tools/addon')
|
||||
}
|
||||
const form = ref({
|
||||
title: '',
|
||||
icon: '',
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container" v-loading="loading">
|
||||
|
||||
<el-card class="card !border-none" shadow="never">
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="$router.back()" />
|
||||
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back()" />
|
||||
</el-card>
|
||||
|
||||
<el-card class="box-card mt-[15px] !border-none" shadow="never">
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
|
||||
<el-card class="card !border-none" shadow="never">
|
||||
<el-page-header :icon="ArrowLeft" @back="$router.back()">
|
||||
<el-page-header :icon="ArrowLeft" @back="back()">
|
||||
<template #content>
|
||||
<span class="text-large font-600 mr-3">{{ pageName }}</span>
|
||||
</template>
|
||||
@ -122,7 +122,11 @@ import { ElMessageBox, ElMessage, FormInstance } from 'element-plus'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
const back = () => {
|
||||
router.push('/tools/schedule')
|
||||
}
|
||||
|
||||
const cronTableData = reactive({
|
||||
page: 1,
|
||||
|
||||
170
admin/src/app/views/web/adv.vue
Normal file
170
admin/src/app/views/web/adv.vue
Normal file
@ -0,0 +1,170 @@
|
||||
<template>
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center mb-[15px] ml-[15px]">
|
||||
<div class="flex items-center">
|
||||
<div class="text-[#666] cursor-pointer text-[14px]" @click="router.push(`/web/adv_position`)">
|
||||
<span class="iconfont iconxiangzuojiantou !text-xs"></span>
|
||||
<span class="ml-[1px]">{{ t('returnToPreviousPage') }}</span>
|
||||
</div>
|
||||
<span class="text-[#999] mx-[12px]">|</span>
|
||||
<span class="right">{{ pageName }}</span>
|
||||
</div>
|
||||
<el-button type="primary" @click="addEvent">{{ t('addAdv') }}</el-button>
|
||||
</div>
|
||||
<div class="mt-[10px]">
|
||||
<el-table :data="advTable.data" size="large" v-loading="advTable.loading">
|
||||
<template #empty>
|
||||
<span>{{ !advTable.loading ? t('emptyData') : '' }}</span>
|
||||
</template>
|
||||
<el-table-column prop="adv_title" :label="t('advName')" min-width="120" />
|
||||
<el-table-column :label="t('advUrl')" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<div>{{ row.adv_url ? row.adv_url.url : '' }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="ap_name" :label="t('advPosition')" min-width="120" />
|
||||
<el-table-column :label="t('advImg')" min-width="180">
|
||||
<template #default="{ row }">
|
||||
<div class="w-[40px] h-[40px] flex items-center">
|
||||
<el-image :src="img(row.adv_image)" :zoom-rate="1.2" :max-scale="7" :min-scale="0.2" :preview-src-list="[img(row.adv_image)]" :initial-index="4" fit="cover" />
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('sort')" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model.trim="row.sort" class="!w-[70px]" maxlength="8" @blur="sortInputListener(row.sort, row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('operation')" fixed="right" min-width="120" align="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>
|
||||
<el-button type="primary" link @click="deleteEvent(row.adv_id)">{{ t('delete') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
<div class="mt-[16px] flex justify-end">
|
||||
<el-pagination v-model:current-page="advTable.page" v-model:page-size="advTable.limit"
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="advTable.total"
|
||||
@size-change="loadAdvList()" @current-change="loadAdvList" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<edit ref="editAdvDialog" @complete="loadAdvList" />
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getAdvList, deleteAdv, editAdvSort } from '@/app/api/web'
|
||||
import { img, debounce } from '@/utils/common'
|
||||
import { ElMessageBox, ElMessage } from 'element-plus'
|
||||
import Edit from '@/app/views/web/components/adv-edit.vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
const advKey = route.query.adv_key
|
||||
const apName = route.query.ap_name
|
||||
const advTable = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: []
|
||||
})
|
||||
|
||||
/**
|
||||
* 获取广告列表
|
||||
*/
|
||||
const loadAdvList = (page: number = 1) => {
|
||||
advTable.loading = true
|
||||
advTable.page = page
|
||||
|
||||
getAdvList({
|
||||
page: advTable.page,
|
||||
limit: advTable.limit,
|
||||
adv_key: advKey
|
||||
}).then(res => {
|
||||
advTable.loading = false
|
||||
advTable.data = res.data.data
|
||||
advTable.total = res.data.total
|
||||
}).catch(() => {
|
||||
advTable.loading = false
|
||||
})
|
||||
}
|
||||
loadAdvList()
|
||||
|
||||
const editAdvDialog: Record<string, any> | null = ref(null)
|
||||
|
||||
/**
|
||||
* 添加广告
|
||||
*/
|
||||
const addEvent = () => {
|
||||
editAdvDialog.value.setFormData({adv_key: advKey, ap_name: apName})
|
||||
editAdvDialog.value.showDialog = true
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑广告
|
||||
* @param data
|
||||
*/
|
||||
const editEvent = (data: any) => {
|
||||
editAdvDialog.value.setFormData(data)
|
||||
editAdvDialog.value.showDialog = true
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除广告
|
||||
*/
|
||||
const deleteEvent = (id: number) => {
|
||||
ElMessageBox.confirm(t('advDeleteTips'), t('warning'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
cancelButtonText: t('cancel'),
|
||||
type: 'warning'
|
||||
}
|
||||
).then(() => {
|
||||
deleteAdv(id).then(() => {
|
||||
loadAdvList()
|
||||
}).catch(() => {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 正则表达式
|
||||
const regExp = {
|
||||
number: /^\d{0,10}$/,
|
||||
digit: /^\d{0,10}(.?\d{0,2})$/
|
||||
}
|
||||
|
||||
// 修改排序号
|
||||
const sortInputListener = debounce((sort, row) => {
|
||||
if (isNaN(sort) || !regExp.number.test(sort)) {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: `${t('sortTips')}`
|
||||
})
|
||||
return
|
||||
}
|
||||
if (sort > 99999999) {
|
||||
row.sort = 99999999
|
||||
}
|
||||
editAdvSort({
|
||||
id: row.adv_id,
|
||||
sort
|
||||
}).then((res: any) => {
|
||||
loadAdvList()
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.input-width-sort {
|
||||
width: 70px;
|
||||
}
|
||||
</style>
|
||||
55
admin/src/app/views/web/adv_position.vue
Normal file
55
admin/src/app/views/web/adv_position.vue
Normal file
@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center mb-[20px]">
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
</div>
|
||||
|
||||
<el-table :data="avdPositionTableData.data" size="large" v-loading="avdPositionTableData.loading">
|
||||
<template #empty>
|
||||
<span>{{ !avdPositionTableData.loading ? t('emptyData') : '' }}</span>
|
||||
</template>
|
||||
<el-table-column prop="ap_name" :label="t('apName')" min-width="120" />
|
||||
<el-table-column prop="keywords" :label="t('keywords')" min-width="120" />
|
||||
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="160">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="toLink(row)">{{ t('manageAdv') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getAvdPositionList } from '@/app/api/web'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
const avdPositionTableData: any = reactive({
|
||||
loading: true,
|
||||
data: []
|
||||
})
|
||||
|
||||
// 获取广告位列表
|
||||
const loadAvdPositionList = () => {
|
||||
getAvdPositionList({}).then(res => {
|
||||
avdPositionTableData.loading = false
|
||||
avdPositionTableData.data = res.data
|
||||
}).catch(() => {
|
||||
avdPositionTableData.loading = false
|
||||
})
|
||||
}
|
||||
loadAvdPositionList()
|
||||
const toLink = (data: any) => {
|
||||
router.push(`/web/adv?adv_key=${data.keywords}&ap_name=${data.ap_name}`)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
146
admin/src/app/views/web/components/adv-edit.vue
Normal file
146
admin/src/app/views/web/components/adv-edit.vue
Normal file
@ -0,0 +1,146 @@
|
||||
<template>
|
||||
<el-dialog v-model="showDialog" :title="formData.adv_id ? t('updateAdv') : t('addAdv')" width="30%" 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="t('advName')" prop="adv_title">
|
||||
<el-input v-model.trim="formData.adv_title" clearable :placeholder="t('advNamePlaceholder')" class="input-width" maxlength="20" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('advPosition')" prop="ap_name">
|
||||
<el-input v-model.trim="formData.ap_name" disabled class="input-width" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('advUrl')">
|
||||
<web-link v-model="formData.adv_url" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('advImg')" prop="adv_image">
|
||||
<upload-image v-model="formData.adv_image" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('background')">
|
||||
<el-color-picker v-model="formData.background" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('sort')" prop="sort">
|
||||
<el-input v-model.trim="formData.sort" clearable :placeholder="t('sortPlaceholder')" class="input-width" show-word-limit maxlength="8" @keyup="filterNumber($event)" @blur="formData.sort = $event.target.value" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<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>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { addAdv, editAdv, getAdvInfo } from '@/app/api/web'
|
||||
|
||||
const showDialog = ref(false)
|
||||
const loading = ref(false)
|
||||
|
||||
/**
|
||||
* 表单数据
|
||||
*/
|
||||
const initialFormData = {
|
||||
adv_key: '',
|
||||
ap_name: '',
|
||||
adv_id: '',
|
||||
adv_title: '',
|
||||
adv_url: {
|
||||
name : ''
|
||||
},
|
||||
adv_image: '',
|
||||
sort: '',
|
||||
background: ''
|
||||
|
||||
}
|
||||
const formData: Record<string, any> = reactive({ ...initialFormData })
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
// 正则表达式
|
||||
const regExp: any = {
|
||||
number: /^\d{0,10}$/
|
||||
}
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = computed(() => {
|
||||
return {
|
||||
adv_title: [
|
||||
{ required: true, message: t('advNamePlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
adv_image: [
|
||||
{ required: true, message: t('advImagePlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
sort: [
|
||||
{
|
||||
trigger: 'blur',
|
||||
validator: (rule: any, value: any, callback: any) => {
|
||||
if (isNaN(value) || !regExp.number.test(value)) {
|
||||
callback(new Error(t('sortTips')))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['complete'])
|
||||
|
||||
/**
|
||||
* 确认
|
||||
* @param formEl
|
||||
*/
|
||||
const confirm = async (formEl: FormInstance | undefined) => {
|
||||
if (loading.value || !formEl) return
|
||||
const save = formData.adv_id ? editAdv : addAdv
|
||||
|
||||
await formEl.validate(async (valid) => {
|
||||
if (valid) {
|
||||
loading.value = true
|
||||
const data = formData
|
||||
save(data).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.adv_id) {
|
||||
const data = await (await getAdvInfo(row.adv_id)).data
|
||||
if (data) {
|
||||
Object.keys(formData).forEach((key: string) => {
|
||||
if (data[key] != undefined) formData[key] = data[key]
|
||||
})
|
||||
}
|
||||
} else {
|
||||
formData.adv_key = row.adv_key
|
||||
formData.ap_name = row.ap_name
|
||||
}
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
// 展示链接
|
||||
const link: any = ref([])
|
||||
|
||||
defineExpose({
|
||||
showDialog,
|
||||
setFormData
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss">
|
||||
.diy-dialog-wrap .el-form-item__label {
|
||||
height: auto !important;
|
||||
}
|
||||
</style>
|
||||
146
admin/src/app/views/web/components/friendly-link-edit.vue
Normal file
146
admin/src/app/views/web/components/friendly-link-edit.vue
Normal file
@ -0,0 +1,146 @@
|
||||
<template>
|
||||
<el-dialog v-model="showDialog" :title="formData.id ? t('updateFriendlyLink') : t('addFriendlyLink')" width="500px" 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="t('linkPic')">
|
||||
<upload-image v-model="formData.link_pic" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('linkTitle')" prop="link_title">
|
||||
<el-input v-model="formData.link_title" clearable :placeholder="t('linkTitlePlaceholder')" class="input-width" maxlength="20" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('linkUrl')" prop="link_url">
|
||||
<el-input v-model="formData.link_url" clearable :placeholder="t('linkUrlPlaceholder')" class="input-width" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('sort')" prop="sort">
|
||||
<el-input v-model.trim="formData.sort" clearable :placeholder="t('sortPlaceholder')" class="input-width" show-word-limit maxlength="8" @keyup="filterNumber($event)" @blur="formData.sort = $event.target.value" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('isShow')">
|
||||
<el-switch v-model="formData.is_show" :active-value="1" :inactive-value="0" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<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>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { addFriendlyLink, editFriendlyLink, getFriendlyLinkInfo } from '@/app/api/web'
|
||||
|
||||
const showDialog = ref(false)
|
||||
const loading = ref(false)
|
||||
|
||||
/**
|
||||
* 表单数据
|
||||
*/
|
||||
const initialFormData = {
|
||||
id: '',
|
||||
link_pic: '',
|
||||
link_title: '',
|
||||
link_url: '',
|
||||
sort: '',
|
||||
is_show: 1
|
||||
}
|
||||
const formData: Record<string, any> = reactive({ ...initialFormData })
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
// 正则表达式
|
||||
const regExp: any = {
|
||||
number: /^\d{0,10}$/,
|
||||
}
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = computed(() => {
|
||||
return {
|
||||
link_pic: [
|
||||
{ required: true, message: t('linkPicPlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
link_title: [
|
||||
{ required: true, message: t('linkTitlePlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
link_url: [
|
||||
{ required: true, message: t('linkUrlPlaceholder'), trigger: 'blur' },
|
||||
{
|
||||
validator: (rule: any, value: string, callback: any) => {
|
||||
const pattern = /^(http|https):\/\/.+/
|
||||
if (value && !pattern.test(value)) {
|
||||
callback(new Error(t('addressTips')))
|
||||
} else { callback() }
|
||||
}
|
||||
}
|
||||
],
|
||||
sort: [
|
||||
{
|
||||
trigger: 'blur',
|
||||
validator: (rule: any, value: any, callback: any) => {
|
||||
if (isNaN(value) || !regExp.number.test(value)) {
|
||||
callback(new Error(t('sortTips')))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['complete'])
|
||||
|
||||
/**
|
||||
* 确认
|
||||
* @param formEl
|
||||
*/
|
||||
const confirm = async (formEl: FormInstance | undefined) => {
|
||||
if (loading.value || !formEl) return
|
||||
const save = formData.id ? editFriendlyLink : addFriendlyLink
|
||||
|
||||
await formEl.validate(async (valid) => {
|
||||
if (valid) {
|
||||
loading.value = true
|
||||
|
||||
const data = formData
|
||||
|
||||
save(data).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 getFriendlyLinkInfo(row.id)).data
|
||||
if (data) {
|
||||
Object.keys(formData).forEach((key: string) => {
|
||||
if (data[key] != undefined) formData[key] = data[key]
|
||||
})
|
||||
}
|
||||
}
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
showDialog,
|
||||
setFormData
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss">
|
||||
.diy-dialog-wrap .el-form-item__label {
|
||||
height: auto !important;
|
||||
}
|
||||
</style>
|
||||
151
admin/src/app/views/web/components/nav-edit.vue
Normal file
151
admin/src/app/views/web/components/nav-edit.vue
Normal file
@ -0,0 +1,151 @@
|
||||
<template>
|
||||
<el-dialog v-model="showDialog" :title="formData.id ? t('updateNav') : t('addNav')" width="500px" 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="t('navTitle')" prop="nav_title">
|
||||
<el-input v-model.trim="formData.nav_title" clearable :placeholder="t('navTitlePlaceholder')" class="input-width" maxlength="20" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('navUrl')" prop="nav_url">
|
||||
<web-link v-model="formData.nav_url" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('sort')" prop="sort">
|
||||
<el-input v-model.trim="formData.sort" clearable :placeholder="t('sortPlaceholder')" class="input-width" show-word-limit maxlength="8" @keyup="filterNumber($event)" @blur="formData.sort = $event.target.value" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('isBlank')">
|
||||
<el-switch v-model="formData.is_blank" :active-value="1" :inactive-value="0" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('isShow')">
|
||||
<el-switch v-model="formData.is_show" :active-value="1" :inactive-value="0" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<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>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { filterNumber } from '@/utils/common'
|
||||
import { addNav, editNav, getNavInfo } from '@/app/api/web'
|
||||
|
||||
const showDialog = ref(false)
|
||||
const loading = ref(false)
|
||||
|
||||
/**
|
||||
* 表单数据
|
||||
*/
|
||||
const initialFormData = {
|
||||
id: '',
|
||||
nav_title: '',
|
||||
nav_url: {
|
||||
name : ''
|
||||
},
|
||||
sort: '',
|
||||
is_blank: 1,
|
||||
is_show: 1
|
||||
}
|
||||
const formData: Record<string, any> = reactive({ ...initialFormData })
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
// 正则表达式
|
||||
const regExp: any = {
|
||||
number: /^\d{0,10}$/,
|
||||
}
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = computed(() => {
|
||||
return {
|
||||
nav_title: [
|
||||
{ required: true, message: t('navTitlePlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
nav_url: [
|
||||
{
|
||||
required: true,
|
||||
trigger: 'blur',
|
||||
validator: (rule: any, value: any, callback: any) => {
|
||||
if (!value.url) {
|
||||
callback(new Error(t('navUrlPlaceholder')))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
is_blank: [
|
||||
{ required: true, message: t('isBlankPlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
sort: [
|
||||
{
|
||||
trigger: 'blur',
|
||||
validator: (rule: any, value: any, callback: any) => {
|
||||
if (isNaN(value) || !regExp.number.test(value)) {
|
||||
callback(new Error(t('sortTips')))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['complete'])
|
||||
|
||||
/**
|
||||
* 确认
|
||||
* @param formEl
|
||||
*/
|
||||
const confirm = async (formEl: FormInstance | undefined) => {
|
||||
if (loading.value || !formEl) return
|
||||
const save = formData.id ? editNav : addNav
|
||||
|
||||
await formEl.validate(async (valid) => {
|
||||
if (valid) {
|
||||
loading.value = true
|
||||
const data = formData
|
||||
|
||||
save(data).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 getNavInfo(row.id)).data
|
||||
if (data) {
|
||||
Object.keys(formData).forEach((key: string) => {
|
||||
if (data[key] != undefined) formData[key] = data[key]
|
||||
})
|
||||
}
|
||||
}
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
showDialog,
|
||||
setFormData
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss">
|
||||
.diy-dialog-wrap .el-form-item__label {
|
||||
height: auto !important;
|
||||
}
|
||||
</style>
|
||||
177
admin/src/app/views/web/friendly_link.vue
Normal file
177
admin/src/app/views/web/friendly_link.vue
Normal file
@ -0,0 +1,177 @@
|
||||
<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>
|
||||
<el-button type="primary" @click="addEvent">{{ t('addFriendlyLink') }}</el-button>
|
||||
</div>
|
||||
|
||||
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
|
||||
<el-form :inline="true" :model="friendlyLinkTable.searchParam" ref="searchFormRef">
|
||||
<el-form-item :label="t('linkTitle')" prop="link_title">
|
||||
<el-input v-model="friendlyLinkTable.searchParam.link_title" :placeholder="t('linkTitlePlaceholder')" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="loadFriendlyLinkList()">{{ t('search') }}</el-button>
|
||||
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<div class="mt-[10px]">
|
||||
<el-table :data="friendlyLinkTable.data" size="large" v-loading="friendlyLinkTable.loading">
|
||||
<template #empty>
|
||||
<span>{{ !friendlyLinkTable.loading ? t('emptyData') : '' }}</span>
|
||||
</template>
|
||||
<el-table-column prop="link_title" :label="t('linkTitle')" min-width="120" />
|
||||
<el-table-column prop="link_url" :label="t('linkUrl')" min-width="200" />
|
||||
<el-table-column prop="sort" :label="t('sort')" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model.trim="row.sort" class="!w-[70px]" maxlength="8" @blur="sortInputListener(row.sort, row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('isShow')" min-width="180" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.is_show == 1 ? t('show') : t('hidden') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column :label="t('operation')" fixed="right" min-width="120" align="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>
|
||||
<el-button type="primary" link @click="deleteEvent(row.id)">{{ t('delete') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
<div class="mt-[16px] flex justify-end">
|
||||
<el-pagination v-model:current-page="friendlyLinkTable.page" v-model:page-size="friendlyLinkTable.limit"
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="friendlyLinkTable.total"
|
||||
@size-change="loadFriendlyLinkList()" @current-change="loadFriendlyLinkList" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<edit ref="editFriendlyLinkDialog" @complete="loadFriendlyLinkList" />
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getFriendlyLinkList, deleteFriendlyLink, editFriendlyLinkSort } from '@/app/api/web'
|
||||
import { debounce } from '@/utils/common'
|
||||
import { ElMessageBox, ElMessage, FormInstance } from 'element-plus'
|
||||
import Edit from '@/app/views/web/components/friendly-link-edit.vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title
|
||||
|
||||
const friendlyLinkTable = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam: {
|
||||
link_title: ''
|
||||
}
|
||||
})
|
||||
|
||||
const searchFormRef = ref<FormInstance>()
|
||||
|
||||
/**
|
||||
* 获取友情链接列表
|
||||
*/
|
||||
const loadFriendlyLinkList = (page: number = 1) => {
|
||||
friendlyLinkTable.loading = true
|
||||
friendlyLinkTable.page = page
|
||||
|
||||
getFriendlyLinkList({
|
||||
page: friendlyLinkTable.page,
|
||||
limit: friendlyLinkTable.limit,
|
||||
...friendlyLinkTable.searchParam
|
||||
}).then(res => {
|
||||
friendlyLinkTable.loading = false
|
||||
friendlyLinkTable.data = res.data.data
|
||||
friendlyLinkTable.total = res.data.total
|
||||
}).catch(() => {
|
||||
friendlyLinkTable.loading = false
|
||||
})
|
||||
}
|
||||
loadFriendlyLinkList()
|
||||
|
||||
const editFriendlyLinkDialog: Record<string, any> | null = ref(null)
|
||||
|
||||
/**
|
||||
* 添加友情链接
|
||||
*/
|
||||
const addEvent = () => {
|
||||
editFriendlyLinkDialog.value.setFormData()
|
||||
editFriendlyLinkDialog.value.showDialog = true
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑友情链接
|
||||
* @param data
|
||||
*/
|
||||
const editEvent = (data: any) => {
|
||||
editFriendlyLinkDialog.value.setFormData(data)
|
||||
editFriendlyLinkDialog.value.showDialog = true
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除友情链接
|
||||
*/
|
||||
const deleteEvent = (id: number) => {
|
||||
ElMessageBox.confirm(t('friendlyLinkDeleteTips'), t('warning'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
cancelButtonText: t('cancel'),
|
||||
type: 'warning'
|
||||
}
|
||||
).then(() => {
|
||||
deleteFriendlyLink(id).then(() => {
|
||||
loadFriendlyLinkList()
|
||||
}).catch(() => {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 正则表达式
|
||||
const regExp = {
|
||||
number: /^\d{0,10}$/,
|
||||
digit: /^\d{0,10}(.?\d{0,2})$/
|
||||
}
|
||||
|
||||
// 修改排序号
|
||||
const sortInputListener = debounce((sort, row) => {
|
||||
if (isNaN(sort) || !regExp.number.test(sort)) {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: `${t('sortTips')}`
|
||||
})
|
||||
return
|
||||
}
|
||||
if (sort > 99999999) {
|
||||
row.sort = 99999999
|
||||
}
|
||||
editFriendlyLinkSort({
|
||||
id: row.id,
|
||||
sort
|
||||
}).then((res: any) => {
|
||||
loadFriendlyLinkList()
|
||||
})
|
||||
})
|
||||
const resetForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
formEl.resetFields()
|
||||
loadFriendlyLinkList()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
190
admin/src/app/views/web/nav.vue
Normal file
190
admin/src/app/views/web/nav.vue
Normal file
@ -0,0 +1,190 @@
|
||||
<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>
|
||||
<el-button type="primary" @click="addEvent">{{ t('addNav') }}</el-button>
|
||||
</div>
|
||||
|
||||
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
|
||||
<el-form :inline="true" :model="navTable.searchParam" ref="searchFormRef">
|
||||
<el-form-item :label="t('navTitle')" prop="nav_title">
|
||||
<el-input v-model="navTable.searchParam.nav_title" :placeholder="t('navTitlePlaceholder')" maxlength="20" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="loadNavList()">{{ t('search') }}</el-button>
|
||||
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<div class="mt-[10px]">
|
||||
<el-table :data="navTable.data" size="large" v-loading="navTable.loading">
|
||||
<template #empty>
|
||||
<span>{{ !navTable.loading ? t('emptyData') : '' }}</span>
|
||||
</template>
|
||||
<el-table-column prop="nav_title" :label="t('navTitle')" min-width="120" />
|
||||
<el-table-column prop="nav_url" :label="t('navUrl')" min-width="120" >
|
||||
<template #default="{ row }">
|
||||
<div>{{ row.nav_url ? row.nav_url.url : '' }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sort" :label="t('sort')" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model.trim="row.sort" class="!w-[70px]" maxlength="8" @blur="sortInputListener(row.sort, row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('isBlank')" min-width="180" align="center" >
|
||||
<template #default="{ row }">
|
||||
{{ row.is_blank == 1 ? t('yes') : t('no') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('createTime')" min-width="180" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.create_time || '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('isShow')" min-width="180" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.is_show == 1 ? t('show') : t('hidden') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('operation')" fixed="right" min-width="120" align="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>
|
||||
<el-button type="primary" link @click="deleteEvent(row.id)">{{ t('delete') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
<div class="mt-[16px] flex justify-end">
|
||||
<el-pagination v-model:current-page="navTable.page" v-model:page-size="navTable.limit"
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="navTable.total"
|
||||
@size-change="loadNavList()" @current-change="loadNavList" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<edit ref="editNavDialog" @complete="loadNavList" />
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { debounce } from '@/utils/common'
|
||||
import { getNavList, deleteNav, editNavSort } from '@/app/api/web'
|
||||
import { ElMessageBox, FormInstance, ElMessage } from 'element-plus'
|
||||
import Edit from '@/app/views/web/components/nav-edit.vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title
|
||||
|
||||
const navTable = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam: {
|
||||
nav_title: ''
|
||||
}
|
||||
})
|
||||
|
||||
const searchFormRef = ref<FormInstance>(null)
|
||||
|
||||
/**
|
||||
* 获取PC导航管理列表
|
||||
*/
|
||||
const loadNavList = (page: number = 1) => {
|
||||
navTable.loading = true
|
||||
navTable.page = page
|
||||
|
||||
getNavList({
|
||||
page: navTable.page,
|
||||
limit: navTable.limit,
|
||||
...navTable.searchParam
|
||||
}).then(res => {
|
||||
navTable.loading = false
|
||||
navTable.data = res.data.data
|
||||
navTable.total = res.data.total
|
||||
}).catch(() => {
|
||||
navTable.loading = false
|
||||
})
|
||||
}
|
||||
loadNavList()
|
||||
|
||||
const editNavDialog: Record<string, any> | null = ref(null)
|
||||
|
||||
/**
|
||||
* 添加PC导航管理
|
||||
*/
|
||||
const addEvent = () => {
|
||||
editNavDialog.value.setFormData()
|
||||
editNavDialog.value.showDialog = true
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑PC导航管理
|
||||
* @param data
|
||||
*/
|
||||
const editEvent = (data: any) => {
|
||||
editNavDialog.value.setFormData(data)
|
||||
editNavDialog.value.showDialog = true
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除PC导航管理
|
||||
*/
|
||||
const deleteEvent = (id: number) => {
|
||||
ElMessageBox.confirm(t('navDeleteTips'), t('warning'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
cancelButtonText: t('cancel'),
|
||||
type: 'warning'
|
||||
}
|
||||
).then(() => {
|
||||
deleteNav(id).then(() => {
|
||||
loadNavList()
|
||||
}).catch(() => {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 正则表达式
|
||||
const regExp = {
|
||||
number: /^\d{0,10}$/,
|
||||
digit: /^\d{0,10}(.?\d{0,2})$/
|
||||
}
|
||||
|
||||
// 修改排序号
|
||||
const sortInputListener = debounce((sort, row) => {
|
||||
if (isNaN(sort) || !regExp.number.test(sort)) {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: `${t('sortTips')}`
|
||||
})
|
||||
return
|
||||
}
|
||||
if (sort > 99999999) {
|
||||
row.sort = 99999999
|
||||
}
|
||||
editNavSort({
|
||||
id: row.id,
|
||||
sort
|
||||
}).then((res: any) => {
|
||||
loadNavList()
|
||||
})
|
||||
})
|
||||
const resetForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
formEl.resetFields()
|
||||
loadNavList()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
214
admin/src/components/web-link/web-link.vue
Normal file
214
admin/src/components/web-link/web-link.vue
Normal file
@ -0,0 +1,214 @@
|
||||
<template>
|
||||
<div>
|
||||
<div @click="show">
|
||||
<slot>
|
||||
<el-input v-model="value.title" :placeholder="t('linkPlaceholder')" readonly class="link-input">
|
||||
<template #suffix>
|
||||
<div @click.stop="clear">
|
||||
<el-icon v-if="value.name">
|
||||
<Close />
|
||||
</el-icon>
|
||||
<el-icon v-else>
|
||||
<ArrowRight />
|
||||
</el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</el-input>
|
||||
</slot>
|
||||
</div>
|
||||
<el-dialog v-model="showDialog" :title="t('selectLinkTips')" width="40%" :close-on-press-escape="false" :destroy-on-close="true" :close-on-click-modal="false">
|
||||
|
||||
<div class="flex items-start">
|
||||
<el-scrollbar class="w-[140px] border-r h-[350px]">
|
||||
<div v-for="(item, index) in link" :key="index"
|
||||
class="h-[40px] leading-[40px] cursor-pointer hover:bg-primary-light-9 px-[10px] hover:text-primary"
|
||||
:class="[item.name == parentLinkName ? 'bg-primary-light-9 text-primary' : '']"
|
||||
@click="changeParentLink(item)">
|
||||
{{ item.title }}
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
<el-scrollbar class="pl-4 h-[350px] flex-1">
|
||||
<template v-if="parentLinkName == 'DIY_LINK'">
|
||||
<div class="mb-[16px]">
|
||||
<el-form-item :label="t('diyLinkName')">
|
||||
<el-input v-model="selectLink.title" :placeholder="t('diyLinkNamePlaceholder')" class="w-6/12" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="mb-[16px]">
|
||||
<el-form-item :label="t('diyLinkUrl')">
|
||||
<el-input v-model="selectLink.url" :placeholder="t('diyLinkUrlPlaceholder')" class="w-6/12" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-form-item label=" ">
|
||||
<div class="text-sm text-gray-400 select-text">路径必须以“/”开头,例:/index/index</div>
|
||||
</el-form-item>
|
||||
<el-form-item label=" ">
|
||||
<div class="text-sm text-gray-400 select-text">跳转外部链接“http”或“https”开头,例:https://baidu.com</div>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<div v-else class="flex flex-wrap">
|
||||
<div v-for="(item, index) in childList" :key="index"
|
||||
class="border border-br rounded-[3px] mr-[10px] mb-[10px] px-4 h-[32px] leading-[32px] cursor-pointer hover:bg-primary-light-9 px-[10px] hover:text-primary"
|
||||
:class="[item.name == selectLink.name ? 'border-primary text-primary' : '']"
|
||||
@click="changeChildLink(item)">{{ item.title }}
|
||||
</div>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</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, computed } from 'vue'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { getLink } from '@/app/api/web'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
const prop = defineProps({
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
|
||||
const value: any = computed({
|
||||
get () {
|
||||
return prop.modelValue
|
||||
},
|
||||
set (value) {
|
||||
emit('update:modelValue', value)
|
||||
}
|
||||
})
|
||||
|
||||
const showDialog = ref(false)
|
||||
|
||||
// 父级链接
|
||||
const link: any = ref([])
|
||||
|
||||
const parentLinkName = ref('')
|
||||
// 子级链接
|
||||
const childList: any = ref([])
|
||||
// 选中的链接
|
||||
const selectLink: any = ref({})
|
||||
|
||||
const show = () => {
|
||||
getLinkFn(() => {
|
||||
// 每次打开时赋值
|
||||
if (value.value.name != '') {
|
||||
selectLink.value = cloneDeep(value.value)
|
||||
parentLinkName.value = selectLink.value.parent
|
||||
for (let key in link.value) {
|
||||
if (link.value[key].name == parentLinkName.value) {
|
||||
changeParentLink(link.value[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
showDialog.value = true
|
||||
})
|
||||
}
|
||||
|
||||
const getLinkFn = (callback:any=null)=> {
|
||||
getLink({}).then((res: any) => {
|
||||
link.value = res.data
|
||||
if (prop.ignore && prop.ignore.length) {
|
||||
for (let key in link.value) {
|
||||
for (let i = 0; i < prop.ignore.length; i++) {
|
||||
if (key == prop.ignore[i]) {
|
||||
delete link.value[key];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
childList.value = Object.values(link.value)[0].child_list
|
||||
if (value.value.name != '') {
|
||||
selectLink.value = cloneDeep(value.value)
|
||||
} else {
|
||||
selectLink.value = {
|
||||
parent: Object.values(link.value)[0].name
|
||||
}
|
||||
}
|
||||
parentLinkName.value = selectLink.value.parent
|
||||
|
||||
if (callback) callback()
|
||||
})
|
||||
}
|
||||
|
||||
// 选择父级链接
|
||||
const changeParentLink = (item: any) => {
|
||||
childList.value = item.child_list
|
||||
parentLinkName.value = item.name
|
||||
}
|
||||
|
||||
// 选择子链接
|
||||
const changeChildLink = (item: any) => {
|
||||
delete item.is_share
|
||||
selectLink.value = cloneDeep(item)
|
||||
}
|
||||
|
||||
const clear = () => {
|
||||
value.value = {
|
||||
name: '',
|
||||
parent: '',
|
||||
title: '',
|
||||
url: ''
|
||||
}
|
||||
}
|
||||
|
||||
const save = () => {
|
||||
if (parentLinkName.value === 'DIY_LINK') {
|
||||
// 自定义链接
|
||||
|
||||
if (!selectLink.value.title) {
|
||||
ElMessage({
|
||||
message: t('diyLinkNameNotEmpty'),
|
||||
type: 'warning'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (!selectLink.value.url) {
|
||||
ElMessage({
|
||||
message: t('diyLinkUrlNotEmpty'),
|
||||
type: 'warning'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
selectLink.value.parent = parentLinkName.value
|
||||
selectLink.value.name = parentLinkName.value
|
||||
selectLink.value.action = ''
|
||||
} else if (parentLinkName.value == 'DIY_PAGE') {
|
||||
// 自定义页面
|
||||
selectLink.value.parent = parentLinkName.value
|
||||
selectLink.value.action = 'decorate'
|
||||
}
|
||||
|
||||
value.value = cloneDeep(selectLink.value)
|
||||
showDialog.value = false
|
||||
|
||||
emit('success')
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
showDialog
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.link-input .el-input__inner {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
0
admin/src/styles/icon/addon/.gitignore
vendored
Normal file
0
admin/src/styles/icon/addon/.gitignore
vendored
Normal file
@ -1,8 +1,8 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 3883393 */
|
||||
src: url('//at.alicdn.com/t/c/font_3883393_t4cbwq5qdz.woff2?t=1729077942624') format('woff2'),
|
||||
url('//at.alicdn.com/t/c/font_3883393_t4cbwq5qdz.woff?t=1729077942624') format('woff'),
|
||||
url('//at.alicdn.com/t/c/font_3883393_t4cbwq5qdz.ttf?t=1729077942624') format('truetype');
|
||||
src: url('//at.alicdn.com/t/c/font_3883393_xso0134odj.woff2?t=1732777083024') format('woff2'),
|
||||
url('//at.alicdn.com/t/c/font_3883393_xso0134odj.woff?t=1732777083024') format('woff'),
|
||||
url('//at.alicdn.com/t/c/font_3883393_xso0134odj.ttf?t=1732777083024') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
@ -13,6 +13,18 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.iconshujutongji:before {
|
||||
content: "\e835";
|
||||
}
|
||||
|
||||
.iconshangpinguanli1:before {
|
||||
content: "\e837";
|
||||
}
|
||||
|
||||
.icondingdanguanli:before {
|
||||
content: "\e838";
|
||||
}
|
||||
|
||||
.icona-tupianzhanbopc302:before {
|
||||
content: "\e83c";
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -40,7 +40,7 @@ export function setThemeColor(color: string, mode: string = 'light'): void {
|
||||
}
|
||||
|
||||
Object.keys(colors[mode]).forEach((key) => {
|
||||
useCssVar('--el-color-primary' + '-' + key, null).value = colorFunction.convert(`color(${color} ${colors[mode][key]})`)
|
||||
useCssVar('--el-color-primary' + '-' + key, null).value = colorFunction.convert(`color(${ color } ${ colors[mode][key] })`)
|
||||
})
|
||||
}
|
||||
|
||||
@ -48,7 +48,9 @@ export function setThemeColor(color: string, mode: string = 'light'): void {
|
||||
* 获取当前访问应用类型
|
||||
*/
|
||||
export function getAppType() {
|
||||
const path = location.pathname.split('/').filter((val) => { return val })
|
||||
const path = location.pathname.split('/').filter((val) => {
|
||||
return val
|
||||
})
|
||||
|
||||
if (!path.length) {
|
||||
return 'admin'
|
||||
@ -125,7 +127,7 @@ export function isUrl(str: string): boolean {
|
||||
* @returns
|
||||
*/
|
||||
export function img(path: string): string {
|
||||
return isUrl(path) ? path : `${import.meta.env.VITE_IMG_DOMAIN || location.origin}/${path}`
|
||||
return isUrl(path) ? path : `${ import.meta.env.VITE_IMG_DOMAIN || location.origin }/${ path }`
|
||||
}
|
||||
|
||||
/**
|
||||
@ -133,7 +135,7 @@ export function img(path: string): string {
|
||||
* @param path
|
||||
* @returns
|
||||
*/
|
||||
export function assetImg (path: string) {
|
||||
export function assetImg(path: string) {
|
||||
return new URL('@/', import.meta.url) + path
|
||||
}
|
||||
|
||||
@ -228,16 +230,16 @@ export function guid(len = 10, firstU = true, radix: any = null) {
|
||||
// 移除第一个字符,并用u替代,因为第一个字符为数值时,该guuid不能用作id或者class
|
||||
if (firstU) {
|
||||
uuid.shift()
|
||||
return `u${uuid.join('')}`
|
||||
return `u${ uuid.join('') }`
|
||||
}
|
||||
return uuid.join('')
|
||||
}
|
||||
|
||||
/**
|
||||
* 金额格式化
|
||||
*/
|
||||
export function moneyFormat(money : string) : string {
|
||||
return isNaN(parseFloat(money)) ? money : parseFloat(money).toFixed(2)
|
||||
* 金额格式化
|
||||
*/
|
||||
export function moneyFormat(money: string): string {
|
||||
return isNaN(parseFloat(money)) ? money : parseFloat(money).toFixed(2)
|
||||
}
|
||||
|
||||
|
||||
@ -245,63 +247,151 @@ export function moneyFormat(money : string) : string {
|
||||
* 时间戳转日期格式
|
||||
*/
|
||||
export function timeStampTurnTime(timeStamp: any, type = "") {
|
||||
if (timeStamp != undefined && timeStamp != "" && timeStamp > 0) {
|
||||
var date = new Date();
|
||||
date.setTime(timeStamp * 1000);
|
||||
var y: any = date.getFullYear();
|
||||
var m: any = date.getMonth() + 1;
|
||||
m = m < 10 ? ('0' + m) : m;
|
||||
var d: any = date.getDate();
|
||||
d = d < 10 ? ('0' + d) : d;
|
||||
var h: any = date.getHours();
|
||||
h = h < 10 ? ('0' + h) : h;
|
||||
var minute: any = date.getMinutes();
|
||||
var second: any = date.getSeconds();
|
||||
minute = minute < 10 ? ('0' + minute) : minute;
|
||||
second = second < 10 ? ('0' + second) : second;
|
||||
if (type) {
|
||||
if (type == 'yearMonthDay') {
|
||||
return y + '年' + m + '月' + d + '日';
|
||||
}
|
||||
return y + '-' + m + '-' + d;
|
||||
} else {
|
||||
return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second;
|
||||
}
|
||||
if (timeStamp != undefined && timeStamp != "" && timeStamp > 0) {
|
||||
var date = new Date();
|
||||
date.setTime(timeStamp * 1000);
|
||||
var y: any = date.getFullYear();
|
||||
var m: any = date.getMonth() + 1;
|
||||
m = m < 10 ? ('0' + m) : m;
|
||||
var d: any = date.getDate();
|
||||
d = d < 10 ? ('0' + d) : d;
|
||||
var h: any = date.getHours();
|
||||
h = h < 10 ? ('0' + h) : h;
|
||||
var minute: any = date.getMinutes();
|
||||
var second: any = date.getSeconds();
|
||||
minute = minute < 10 ? ('0' + minute) : minute;
|
||||
second = second < 10 ? ('0' + second) : second;
|
||||
if (type) {
|
||||
if (type == 'yearMonthDay') {
|
||||
return y + '年' + m + '月' + d + '日';
|
||||
}
|
||||
return y + '-' + m + '-' + d;
|
||||
} else {
|
||||
return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second;
|
||||
}
|
||||
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤小数点(保留两位)
|
||||
* @param event
|
||||
*/
|
||||
export function filterDigit(event:any){
|
||||
event.target.value = event.target.value.replace(/[^\d\.]/g,'');
|
||||
event.target.value = event.target.value.replace(/^\./g,'');
|
||||
event.target.value = event.target.value.replace(/\.{2,}/g,'.');
|
||||
export function filterDigit(event: any) {
|
||||
event.target.value = event.target.value.replace(/[^\d\.]/g, '');
|
||||
event.target.value = event.target.value.replace(/^\./g, '');
|
||||
event.target.value = event.target.value.replace(/\.{2,}/g, '.');
|
||||
// 限制最多两位小数
|
||||
const decimalParts = event.target.value.split('.');
|
||||
if (decimalParts.length > 1 && decimalParts[1].length > 2) {
|
||||
// 如果有小数部分且超过两位,则截取前两位
|
||||
event.target.value = `${decimalParts[0]}.${decimalParts[1].slice(0, 2)}`;
|
||||
event.target.value = `${ decimalParts[0] }.${ decimalParts[1].slice(0, 2) }`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤整数
|
||||
* @param event
|
||||
* @param event
|
||||
*/
|
||||
export function filterNumber(event:any){
|
||||
event.target.value = event.target.value.replace(/[^\d]/g,'');
|
||||
export function filterNumber(event: any) {
|
||||
event.target.value = event.target.value.replace(/[^\d]/g, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤特殊字符
|
||||
* @param event
|
||||
* @param event
|
||||
*/
|
||||
export function filterSpecial(event:any){
|
||||
export function filterSpecial(event: any) {
|
||||
event.target.value = event.target.value.replace(/[^\u4e00-\u9fa5a-zA-Z0-9]/g, '')
|
||||
event.target.value = event.target.value.replace(/[`~!@#$%^&*()_\-+=<>?:"{}|,.\/;'\\[\]·~!@#¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、]/g,'')
|
||||
}
|
||||
event.target.value = event.target.value.replace(/[`~!@#$%^&*()_\-+=<>?:"{}|,.\/;'\\[\]·~!@#¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、]/g, '')
|
||||
}
|
||||
|
||||
export function importIconFontCss() {
|
||||
// const modulesFiles = {}; // import.meta.glob('@/styles/icon/official-iconfont.css', { eager: true })
|
||||
// const modulesFiles = import.meta.glob('@/addon/**/assets/icon/*.css', { eager: true })
|
||||
// // console.log('modulesFiles',modulesFiles)
|
||||
//
|
||||
// const modules:any = {}
|
||||
// for (const [key, value] of Object.entries(modulesFiles)) {
|
||||
// const moduleName:any = key.split('/').pop()
|
||||
// const name = moduleName.split('.')[0]
|
||||
// modules[name] = value.default
|
||||
// }
|
||||
//
|
||||
// // console.log('modules',modules)
|
||||
//
|
||||
// for(let key in modules) {
|
||||
// // console.log('modules[key]',modules[key])
|
||||
// import(modules[key]).then((module) => {
|
||||
// // console.log('module', module.default);
|
||||
// }).catch((e) => {
|
||||
// // console.log('caca', e)
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
export function getIcon() {
|
||||
// const modulesFiles = import.meta.glob('@/styles/icon/*.json', { eager: true })
|
||||
// const addonModulesFiles = import.meta.glob('@/addon/**/assets/icon/*.json', { eager: true })
|
||||
// addonModulesFiles && Object.assign(modulesFiles, addonModulesFiles)
|
||||
//
|
||||
// // const modulesFiles = {}; // import.meta.glob('@/styles/icon/official-iconfont.css', { eager: true })
|
||||
// // const modulesFiles = import.meta.glob('@/styles/icon/*.json', { eager: true })
|
||||
// console.log('modulesFiles', modulesFiles)
|
||||
//
|
||||
// const modules = {}
|
||||
// for (const [key, value] of Object.entries(modulesFiles)) {
|
||||
// const moduleName = key.split('/').pop()
|
||||
// console.log('moduleName',moduleName)
|
||||
// const name = moduleName.split('.')[0]
|
||||
// modules[name] = value.default
|
||||
// }
|
||||
// console.log('modules', modules)
|
||||
// // const addonModulesFiles = import.meta.glob('@/addon/**/assets/icon/*.json', { eager: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置表格分页数据的本地存储
|
||||
* @param page
|
||||
* @param limit
|
||||
* @param where
|
||||
*/
|
||||
export function setTablePageStorage(page: any = 1, limit: any = 10, where: any = {}) {
|
||||
var data = storage.get('tablePageStorage');
|
||||
if (!data) {
|
||||
data = {};
|
||||
}
|
||||
|
||||
var key = location.pathname + JSON.stringify(where);
|
||||
data[key] = {
|
||||
page,
|
||||
limit
|
||||
};
|
||||
|
||||
var MAX_COUNT = 5; // 最多存储 5 个页面的分页缓存,超出则删除最开始的第一个页面
|
||||
if (Object.keys(data).length > MAX_COUNT) {
|
||||
delete data[Object.keys(data)[0]];
|
||||
}
|
||||
|
||||
storage.set({ key: 'tablePageStorage', data });
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表格分页数据的本地存储
|
||||
* @param where
|
||||
*/
|
||||
export function getTablePageStorage(where: any = {}) {
|
||||
var data = storage.get('tablePageStorage');
|
||||
var key = location.pathname + JSON.stringify(where);
|
||||
if (!data || !data[key]) {
|
||||
data = {
|
||||
page: 1,
|
||||
limit: 10
|
||||
};
|
||||
} else {
|
||||
data = data[key];
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user