修改首页
This commit is contained in:
@@ -148,7 +148,7 @@ price.bill.bizDateRequired=业务日期为空
|
||||
|
||||
price.set.version.effectiveTime.empty=版本生效时间不能为空
|
||||
price.set.version.notExists=套餐版本不存在
|
||||
price.set.version.activate.statusNotAllowed=仅草稿版本可启动
|
||||
price.set.version.activate.statusNotAllowed=仅草稿或待生效版本可设置生效时间
|
||||
price.set.version.delete.statusNotAllowed=仅草稿版本可删除
|
||||
price.set.version.copy.draftExists=已有草稿版本,请先启动或删除后再复制
|
||||
price.set.save.task.notExists=保存任务不存在或已过期
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ public interface IPrcPriceSetService
|
||||
public int disable(Long priceSetId, String updateBy);
|
||||
|
||||
/**
|
||||
* Activate a draft version with user-specified effectiveTime.
|
||||
* Activate a draft or reschedule a pending version with user-specified effectiveTime.
|
||||
* effectiveTime <= now -> EFFECT; future -> PENDING(3). Then refresh 0/3/1/2.
|
||||
*/
|
||||
public int activateVersion(Long psvId, Date effectiveTime, String updateBy);
|
||||
|
||||
+1
-1
@@ -288,7 +288,7 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.set.version.notExists"));
|
||||
}
|
||||
if (!VER_DRAFT.equals(version.getStatus()))
|
||||
if (!VER_DRAFT.equals(version.getStatus()) && !VER_PENDING.equals(version.getStatus()))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.set.version.activate.statusNotAllowed"));
|
||||
}
|
||||
|
||||
@@ -12,14 +12,6 @@
|
||||
<template v-if="appStore.device !== 'mobile'">
|
||||
<header-search id="header-search" class="right-menu-item" />
|
||||
|
||||
<el-tooltip content="源码地址" effect="dark" placement="bottom">
|
||||
<ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />
|
||||
</el-tooltip>
|
||||
|
||||
<el-tooltip content="文档地址" effect="dark" placement="bottom">
|
||||
<ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" />
|
||||
</el-tooltip>
|
||||
|
||||
<screenfull id="screenfull" class="right-menu-item hover-effect" />
|
||||
|
||||
<el-tooltip content="主题模式" effect="dark" placement="bottom">
|
||||
@@ -74,8 +66,6 @@ import Hamburger from '@/components/Hamburger'
|
||||
import Screenfull from '@/components/Screenfull'
|
||||
import SizeSelect from '@/components/SizeSelect'
|
||||
import HeaderSearch from '@/components/HeaderSearch'
|
||||
import RuoYiGit from '@/components/RuoYi/Git'
|
||||
import RuoYiDoc from '@/components/RuoYi/Doc'
|
||||
import useAppStore from '@/store/modules/app'
|
||||
import useUserStore from '@/store/modules/user'
|
||||
import useLockStore from '@/store/modules/lock'
|
||||
|
||||
@@ -62,6 +62,6 @@ export default {
|
||||
/**
|
||||
* 底部版权文本内容
|
||||
*/
|
||||
footerContent: 'Copyright © 2018-2026 RuoYi. All Rights Reserved.'
|
||||
footerContent: 'Copyright © 2026 BMS. All Rights Reserved.'
|
||||
}
|
||||
|
||||
|
||||
+129
-79
@@ -1,107 +1,157 @@
|
||||
<template>
|
||||
<div class="app-container home">
|
||||
<el-row :gutter="20">
|
||||
<el-col :sm="24" :lg="12" style="padding-left: 20px">
|
||||
<h2>若依后台管理框架</h2>
|
||||
<p>
|
||||
一直想做一款后台管理系统,看了很多优秀的开源项目但是发现没有合适自己的。于是利用空闲休息时间开始自己写一套后台系统。如此有了BMS,她可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA等等,当然,您也可以对她进行深度定制,以做出更强系统。所有前端后台代码封装过后十分精简易上手,出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。
|
||||
<div class="home-hero">
|
||||
<div class="hero-main">
|
||||
<h2 class="hero-title">BMS 业务管理系统</h2>
|
||||
<p class="hero-sub">跨境物流 · 询价计价 · 账单管理</p>
|
||||
<p class="hero-welcome">
|
||||
{{ greeting }},{{ user.nickName || user.name }},欢迎使用 BMS 业务管理系统。
|
||||
</p>
|
||||
<p>
|
||||
<b>当前版本:</b> <span>v{{ version }}</span>
|
||||
</p>
|
||||
<p>
|
||||
<el-tag type="danger">¥免费开源</el-tag>
|
||||
</p>
|
||||
<p>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="Cloudy"
|
||||
plain
|
||||
@click="goTarget('https://gitee.com/y_project/RuoYi-Vue')"
|
||||
>访问码云</el-button
|
||||
>
|
||||
<el-button
|
||||
icon="HomeFilled"
|
||||
plain
|
||||
@click="goTarget('http://ruoyi.vip')"
|
||||
>访问主页</el-button
|
||||
>
|
||||
</p>
|
||||
</el-col>
|
||||
<p class="hero-date">{{ nowText }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-row :gutter="20" class="home-cards">
|
||||
<el-col :xs="24" :sm="12" :lg="8">
|
||||
<el-card shadow="hover" class="home-card">
|
||||
<div class="card-icon icon-price">
|
||||
<el-icon :size="28"><PriceTag /></el-icon>
|
||||
</div>
|
||||
<div class="card-title">价格管理</div>
|
||||
<div class="card-desc">产品价卡、套餐与附加费配置维护</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :lg="8">
|
||||
<el-card shadow="hover" class="home-card">
|
||||
<div class="card-icon icon-bill">
|
||||
<el-icon :size="28"><Tickets /></el-icon>
|
||||
</div>
|
||||
<div class="card-title">账单管理</div>
|
||||
<div class="card-desc">应收应付账单查询与计费核对</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :lg="8">
|
||||
<el-card shadow="hover" class="home-card">
|
||||
<div class="card-icon icon-customer">
|
||||
<el-icon :size="28"><User /></el-icon>
|
||||
</div>
|
||||
<div class="card-title">客户管理</div>
|
||||
<div class="card-desc">客户资料、供应商与授信额度管理</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="Index">
|
||||
const version = ref('3.9.2')
|
||||
import { PriceTag, Tickets, User } from '@element-plus/icons-vue'
|
||||
import useUserStore from '@/store/modules/user'
|
||||
|
||||
function goTarget(url) {
|
||||
window.open(url, '__blank')
|
||||
const user = useUserStore()
|
||||
|
||||
const nowText = ref('')
|
||||
|
||||
const greeting = computed(() => {
|
||||
const h = new Date().getHours()
|
||||
if (h < 6) return '凌晨好'
|
||||
if (h < 12) return '上午好'
|
||||
if (h < 14) return '中午好'
|
||||
if (h < 18) return '下午好'
|
||||
return '晚上好'
|
||||
})
|
||||
|
||||
function formatNow() {
|
||||
const d = new Date()
|
||||
const week = ['日', '一', '二', '三', '四', '五', '六'][d.getDay()]
|
||||
const pad = n => String(n).padStart(2, '0')
|
||||
nowText.value = `${d.getFullYear()}年${d.getMonth() + 1}月${d.getDate()}日 星期${week} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
formatNow()
|
||||
setInterval(formatNow, 1000)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
// 清理定时器
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.home {
|
||||
blockquote {
|
||||
padding: 10px 20px;
|
||||
margin: 0 0 20px;
|
||||
font-size: 17.5px;
|
||||
border-left: 5px solid #eee;
|
||||
}
|
||||
hr {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
border: 0;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
.col-item {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 13px;
|
||||
color: #676a6c;
|
||||
overflow-x: hidden;
|
||||
color: #303133;
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
}
|
||||
.home-hero {
|
||||
padding: 40px 24px;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 8px;
|
||||
background: linear-gradient(135deg, #409eff 0%, #6c8cff 100%);
|
||||
color: #fff;
|
||||
|
||||
h4 {
|
||||
margin-top: 0px;
|
||||
}
|
||||
.hero-title {
|
||||
margin: 0 0 8px;
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 10px;
|
||||
font-size: 26px;
|
||||
font-weight: 100;
|
||||
}
|
||||
.hero-sub {
|
||||
margin: 0 0 16px;
|
||||
font-size: 14px;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 10px;
|
||||
.hero-welcome {
|
||||
margin: 0 0 6px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
b {
|
||||
font-weight: 700;
|
||||
.hero-date {
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
opacity: 0.85;
|
||||
}
|
||||
}
|
||||
|
||||
.update-log {
|
||||
ol {
|
||||
display: block;
|
||||
list-style-type: decimal;
|
||||
margin-block-start: 1em;
|
||||
margin-block-end: 1em;
|
||||
margin-inline-start: 0;
|
||||
margin-inline-end: 0;
|
||||
padding-inline-start: 40px;
|
||||
.home-cards {
|
||||
.home-card {
|
||||
margin-bottom: 20px;
|
||||
border-radius: 8px;
|
||||
|
||||
.card-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
margin-bottom: 14px;
|
||||
border-radius: 10px;
|
||||
color: #fff;
|
||||
|
||||
&.icon-price {
|
||||
background: #409eff;
|
||||
}
|
||||
&.icon-bill {
|
||||
background: #67c23a;
|
||||
}
|
||||
&.icon-customer {
|
||||
background: #e6a23c;
|
||||
}
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.card-desc {
|
||||
font-size: 13px;
|
||||
color: #909399;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -28,21 +28,14 @@
|
||||
<el-table-column :label="colRows" width="100" align="center">
|
||||
<template #default="{ row }">{{ detailCount(row) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="colAction" width="360" align="center" fixed="right">
|
||||
<el-table-column :label="colAction" width="380" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" @click="openDetails(row)">查看详情</el-button>
|
||||
<el-button
|
||||
v-if="isPriceEditableVersion(row)"
|
||||
v-if="showEditButton(row)"
|
||||
link
|
||||
type="primary"
|
||||
@click="emit('edit', row)"
|
||||
v-hasPermi="['price:set:edit']"
|
||||
>继续配置</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="warning"
|
||||
@click="emit('edit', row)"
|
||||
v-hasPermi="['price:set:forceEdit']"
|
||||
>编辑</el-button>
|
||||
<el-button
|
||||
v-if="isDraftVersion(row)"
|
||||
@@ -51,6 +44,13 @@
|
||||
@click="emit('activate', row)"
|
||||
v-hasPermi="['price:set:edit']"
|
||||
>启动</el-button>
|
||||
<el-button
|
||||
v-if="isPendingVersion(row)"
|
||||
link
|
||||
type="primary"
|
||||
@click="emit('reschedule', row)"
|
||||
v-hasPermi="['price:set:edit']"
|
||||
>修改生效时间</el-button>
|
||||
<el-button
|
||||
v-if="isDraftVersion(row)"
|
||||
link
|
||||
@@ -73,13 +73,14 @@
|
||||
|
||||
<script setup name="SetVersionTable">
|
||||
import SetSectionCard from './SetSectionCard.vue'
|
||||
import { versionStatusLabel, versionStatusTag, isDraftVersion, isPriceEditableVersion } from '../../utils/priceSet'
|
||||
import { versionStatusLabel, versionStatusTag, isDraftVersion, isPendingVersion, isPriceEditableVersion } from '../../utils/priceSet'
|
||||
import { checkPermi } from '@/utils/permission'
|
||||
|
||||
const props = defineProps({
|
||||
versions: { type: Array, default: () => [] },
|
||||
modelValue: { type: [Number, String], default: undefined }
|
||||
})
|
||||
const emit = defineEmits(['update:modelValue', 'copy-version', 'open-details', 'activate', 'edit', 'remove'])
|
||||
const emit = defineEmits(['update:modelValue', 'copy-version', 'open-details', 'activate', 'reschedule', 'edit', 'remove'])
|
||||
|
||||
const title = '套餐版本'
|
||||
const colNo = '版本号'
|
||||
@@ -124,6 +125,11 @@ function detailCount(row) {
|
||||
return (row && row.details || []).length
|
||||
}
|
||||
|
||||
function showEditButton(row) {
|
||||
if (checkPermi(['price:set:forceEdit'])) return true
|
||||
return isPriceEditableVersion(row) && checkPermi(['price:set:edit'])
|
||||
}
|
||||
|
||||
function openDetails(row) {
|
||||
if (!row || row.psvId == null) return
|
||||
emit('update:modelValue', row.psvId)
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
@copy-version="onCopyVersion"
|
||||
@open-details="onOpenVersionDetails"
|
||||
@activate="onActivateVersion"
|
||||
@reschedule="onRescheduleVersion"
|
||||
@edit="onEditVersion"
|
||||
@remove="onRemoveVersion"
|
||||
/>
|
||||
@@ -38,7 +39,7 @@
|
||||
|
||||
<el-dialog
|
||||
v-model="activateVisible"
|
||||
:title="activateTitle"
|
||||
:title="activateDialogTitle"
|
||||
width="460px"
|
||||
append-to-body
|
||||
@closed="onActivateClosed"
|
||||
@@ -56,11 +57,11 @@
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<div class="activate-hint">{{ activateHint }}</div>
|
||||
<div class="activate-hint">{{ activateDialogHint }}</div>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="activateVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="activateSubmitting" @click="submitActivate">确认启动</el-button>
|
||||
<el-button type="primary" :loading="activateSubmitting" @click="submitActivate">{{ activateConfirmText }}</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
@@ -130,27 +131,48 @@ function formatNow() {
|
||||
const activateVisible = ref(false)
|
||||
const activateSubmitting = ref(false)
|
||||
const activateFormRef = ref()
|
||||
const activateTitle = '启动版本'
|
||||
const activateMode = ref('activate')
|
||||
const activatePh = '请选择生效时间'
|
||||
const activateHint = '若生效时间晚于当前,版本将进入「待生效」;到时自动生效并使上一版本失效。'
|
||||
const activateForm = reactive({
|
||||
psvId: undefined,
|
||||
versionNo: '',
|
||||
effectiveTime: undefined
|
||||
})
|
||||
const activateDialogTitle = computed(() =>
|
||||
activateMode.value === 'reschedule' ? '修改生效时间' : '启动版本'
|
||||
)
|
||||
const activateConfirmText = computed(() =>
|
||||
activateMode.value === 'reschedule' ? '确认修改' : '确认启动'
|
||||
)
|
||||
const activateDialogHint = computed(() =>
|
||||
activateMode.value === 'reschedule'
|
||||
? '仅待生效版本可修改;若时间晚于当前仍为待生效,到时自动生效并使上一版本失效。'
|
||||
: '若生效时间晚于当前,版本将进入「待生效」;到时自动生效并使上一版本失效。'
|
||||
)
|
||||
const activateRules = {
|
||||
effectiveTime: [{ required: true, message: '请选择生效时间', trigger: 'change' }]
|
||||
}
|
||||
|
||||
function onActivateVersion(row) {
|
||||
if (!row || row.psvId == null) return
|
||||
activateMode.value = 'activate'
|
||||
activateForm.psvId = row.psvId
|
||||
activateForm.versionNo = row.versionNo || ''
|
||||
activateForm.effectiveTime = formatNow()
|
||||
activateVisible.value = true
|
||||
}
|
||||
|
||||
function onRescheduleVersion(row) {
|
||||
if (!row || row.psvId == null) return
|
||||
activateMode.value = 'reschedule'
|
||||
activateForm.psvId = row.psvId
|
||||
activateForm.versionNo = row.versionNo || ''
|
||||
activateForm.effectiveTime = row.effectiveTime || formatNow()
|
||||
activateVisible.value = true
|
||||
}
|
||||
|
||||
function onActivateClosed() {
|
||||
activateMode.value = 'activate'
|
||||
activateForm.psvId = undefined
|
||||
activateForm.versionNo = ''
|
||||
activateForm.effectiveTime = undefined
|
||||
@@ -165,7 +187,10 @@ function submitActivate() {
|
||||
.then(() => {
|
||||
const eff = activateForm.effectiveTime
|
||||
const pending = eff && new Date(eff.replace(/-/g, '/')).getTime() > Date.now()
|
||||
proxy.$modal.msgSuccess(pending ? '已设为待生效' : '版本已启动')
|
||||
const okMsg = activateMode.value === 'reschedule'
|
||||
? (pending ? '已更新为待生效' : '生效时间已更新,版本已生效')
|
||||
: (pending ? '已设为待生效' : '版本已启动')
|
||||
proxy.$modal.msgSuccess(okMsg)
|
||||
activateVisible.value = false
|
||||
load()
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user