1
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
-- Home work template menu. Prefer a sibling of sys.homeActivity, then sys.manager, then sys.
|
||||
INSERT INTO sys_menu (
|
||||
id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled,
|
||||
permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt,
|
||||
delFlag, platform, moduleId, picIcon, initialPinyinName, isRecommendApp, isRecommendService
|
||||
)
|
||||
SELECT
|
||||
'e6ed122326a8492fa7f415f97eaf4f01',
|
||||
parent.id,
|
||||
CONCAT(parent.path, LPAD(IFNULL(child.maxNo, 0) + 1, 4, '0')),
|
||||
'Work Template',
|
||||
'Work Template',
|
||||
'menu',
|
||||
'/platform/sys/worktemplate',
|
||||
'data-pjax',
|
||||
'',
|
||||
1,
|
||||
0,
|
||||
'sys.worktemplate',
|
||||
NULL,
|
||||
IFNULL(child.maxLocation, 0) + 1,
|
||||
0,
|
||||
'',
|
||||
UNIX_TIMESTAMP(NOW()) * 1000,
|
||||
'',
|
||||
UNIX_TIMESTAMP(NOW()) * 1000,
|
||||
0,
|
||||
'PC',
|
||||
NULL,
|
||||
NULL,
|
||||
'g',
|
||||
0,
|
||||
0
|
||||
FROM (
|
||||
SELECT p.*
|
||||
FROM sys_menu p
|
||||
WHERE p.id = (SELECT h.parentId FROM sys_menu h WHERE h.permission = 'sys.homeActivity' LIMIT 1)
|
||||
OR p.permission IN ('sys.manager', 'sys')
|
||||
ORDER BY
|
||||
CASE
|
||||
WHEN p.id = (SELECT h.parentId FROM sys_menu h WHERE h.permission = 'sys.homeActivity' LIMIT 1) THEN 0
|
||||
WHEN p.permission = 'sys.manager' THEN 1
|
||||
ELSE 2
|
||||
END
|
||||
LIMIT 1
|
||||
) parent
|
||||
LEFT JOIN (
|
||||
SELECT parentId,
|
||||
MAX(CAST(RIGHT(path, 4) AS UNSIGNED)) AS maxNo,
|
||||
MAX(location) AS maxLocation
|
||||
FROM sys_menu
|
||||
GROUP BY parentId
|
||||
) child ON child.parentId = parent.id
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_menu WHERE permission = 'sys.worktemplate'
|
||||
);
|
||||
|
||||
INSERT INTO sys_role_menu (roleId, menuId)
|
||||
SELECT r.id, m.id
|
||||
FROM sys_role r
|
||||
JOIN sys_menu m ON m.permission = 'sys.worktemplate'
|
||||
LEFT JOIN sys_role_menu rm ON rm.roleId = r.id AND rm.menuId = m.id
|
||||
WHERE r.code = 'SYSADMIN'
|
||||
AND rm.roleId IS NULL;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE `sys_home_template`
|
||||
ADD COLUMN `templateFile` varchar(1000) DEFAULT NULL COMMENT 'template file' AFTER `templateIcon`;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE `sys_home_template`
|
||||
ADD COLUMN `templateIcon` varchar(255) DEFAULT NULL COMMENT 'template icon' AFTER `templateName`;
|
||||
@@ -0,0 +1,6 @@
|
||||
ALTER TABLE `sys_home_template`
|
||||
ADD COLUMN `templateName` varchar(50) DEFAULT NULL COMMENT 'display template name' AFTER `name`;
|
||||
|
||||
UPDATE `sys_home_template`
|
||||
SET `templateName` = `name`
|
||||
WHERE (`templateName` IS NULL OR `templateName` = '');
|
||||
@@ -0,0 +1,26 @@
|
||||
CREATE TABLE IF NOT EXISTS `sys_home_template` (
|
||||
`id` varchar(32) NOT NULL COMMENT 'business id',
|
||||
`name` varchar(50) DEFAULT NULL COMMENT 'template name',
|
||||
`templateName` varchar(50) DEFAULT NULL COMMENT 'display template name',
|
||||
`templateIcon` varchar(255) DEFAULT NULL COMMENT 'template icon',
|
||||
`templateFile` varchar(1000) DEFAULT NULL COMMENT 'template file',
|
||||
`cover` varchar(255) DEFAULT NULL COMMENT 'template cover',
|
||||
`content` text COMMENT 'template content',
|
||||
`url` varchar(1000) DEFAULT NULL COMMENT 'pc url',
|
||||
`h5Url` varchar(1000) DEFAULT NULL COMMENT 'h5 url',
|
||||
`allowUserGroupId` int DEFAULT NULL COMMENT 'allowed user group id',
|
||||
`allowUserSql` varchar(1000) DEFAULT NULL COMMENT 'allowed user sql',
|
||||
`enable` tinyint(1) DEFAULT 0 COMMENT 'enabled',
|
||||
`classPath` varchar(500) DEFAULT NULL COMMENT 'source class path',
|
||||
`top` tinyint(1) DEFAULT 0 COMMENT 'top flag',
|
||||
`push` tinyint(1) DEFAULT 0 COMMENT 'push flag',
|
||||
`sortNo` int DEFAULT 0 COMMENT 'sort number',
|
||||
`startDate` datetime DEFAULT NULL COMMENT 'start date',
|
||||
`endDate` datetime DEFAULT NULL COMMENT 'end date',
|
||||
`createdBy` varchar(32) DEFAULT NULL,
|
||||
`createdAt` bigint DEFAULT NULL,
|
||||
`updatedBy` varchar(32) DEFAULT NULL,
|
||||
`updatedAt` bigint DEFAULT NULL,
|
||||
`delFlag` tinyint(1) DEFAULT 0,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='home work template';
|
||||
@@ -0,0 +1,214 @@
|
||||
const workTemplate = {
|
||||
template: /*language=HTML*/ `
|
||||
<div class="section-wrapper work-template-wrapper">
|
||||
<div class="work-template-header">
|
||||
<div class="work-template-title">
|
||||
<i class="fa fa-clipboard"></i>
|
||||
<span>工作模板</span>
|
||||
<em>/Templates</em>
|
||||
</div>
|
||||
</div>
|
||||
<div class="work-template-card">
|
||||
<div v-if="templateList && templateList.length > 0" class="work-template-grid">
|
||||
<div class="work-template-item"
|
||||
v-for="template in templateList"
|
||||
:key="template.id"
|
||||
@click="go(template)">
|
||||
<div class="work-template-icon">
|
||||
<img :src="template.templateIcon || template.cover || 'https://www.ncu.edu.cn/__local/8/52/2C/644986B4C9A030F7B65300178A6_8679CB08_18467.jpg'"
|
||||
alt="">
|
||||
</div>
|
||||
<div class="work-template-name">{{ template.templateName || template.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="no-activity-placeholder">
|
||||
<div class="icon"><i class="fa fa-clipboard"></i></div>
|
||||
<p>暂无工作模板</p>
|
||||
<p class="subtext">敬请关注后续更新</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
data() {
|
||||
return {
|
||||
templateList: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
listTemplate() {
|
||||
this.$axios.post("/platform/home/listHomeTemplate").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.templateList = res.data
|
||||
}
|
||||
})
|
||||
},
|
||||
go(template) {
|
||||
if (!template.url) {
|
||||
this.$message.warning("管理员未配置模板链接")
|
||||
return
|
||||
}
|
||||
const url = new URL(template.url, window.location.origin)
|
||||
if (!url.searchParams.get("mode")) {
|
||||
url.searchParams.set("mode", "edit")
|
||||
}
|
||||
if (!url.searchParams.get("id") && template.id) {
|
||||
url.searchParams.set("id", template.id)
|
||||
}
|
||||
window.localStorage.setItem("zhgh_home_template_edit", JSON.stringify({
|
||||
path: url.pathname,
|
||||
id: url.searchParams.get("id"),
|
||||
expiresAt: Date.now() + 60000
|
||||
}))
|
||||
window.open(url.href)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.listTemplate()
|
||||
},
|
||||
style: /*language=CSS*/ `
|
||||
.work-template-wrapper {
|
||||
width: 80%;
|
||||
margin: 20px auto 28px;
|
||||
}
|
||||
|
||||
.work-template-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.work-template-title {
|
||||
display: inline-flex;
|
||||
align-items: baseline;
|
||||
gap: 6px;
|
||||
color: #19324d;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.work-template-title i {
|
||||
color: #409eff;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.work-template-title em {
|
||||
color: #b5c0d6;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.work-template-card {
|
||||
background: #ffffff;
|
||||
border: 1px solid #edf1f7;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.06);
|
||||
min-height: 116px;
|
||||
padding: 18px 20px;
|
||||
}
|
||||
|
||||
.work-template-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
|
||||
justify-items: center;
|
||||
justify-content: start;
|
||||
gap: 12px 18px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.work-template-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
padding: 6px;
|
||||
cursor: pointer;
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.work-template-item:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.work-template-icon {
|
||||
width: 55px;
|
||||
height: 55px;
|
||||
margin-bottom: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.work-template-icon img {
|
||||
width: 55px !important;
|
||||
height: 55px !important;
|
||||
max-width: none;
|
||||
max-height: none;
|
||||
object-fit: cover;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.work-template-name {
|
||||
min-height: 34px;
|
||||
font-size: 12px !important;
|
||||
font-weight: 400;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
word-break: break-word;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.work-template-wrapper .no-activity-placeholder {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 40px 20px;
|
||||
color: #94a3b8;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.work-template-wrapper .no-activity-placeholder .icon {
|
||||
font-size: 44px;
|
||||
margin-bottom: 12px;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.work-template-wrapper .no-activity-placeholder p {
|
||||
margin: 4px 0 0;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.work-template-wrapper .no-activity-placeholder .subtext {
|
||||
font-size: 13px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.work-template-grid {
|
||||
grid-template-columns: repeat(3, minmax(72px, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.work-template-item {
|
||||
padding: 8px 4px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.work-template-grid {
|
||||
grid-template-columns: repeat(2, minmax(72px, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
}
|
||||
`
|
||||
};
|
||||
@@ -0,0 +1,224 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<el-card shadow="never">
|
||||
<search @search="doSearch">
|
||||
<search-item label="名称" prop="name">
|
||||
<el-input v-model="pageForm.name" clearable placeholder="请输入名称"></el-input>
|
||||
</search-item>
|
||||
</search>
|
||||
</el-card>
|
||||
<el-card shadow="never">
|
||||
<el-table :data="tableData" header-align="center" border style="width: 100%">
|
||||
<el-table-column label="序号" type="index" width="50px" :index="indexMethod"></el-table-column>
|
||||
<el-table-column label="模板名称" prop="templateName" width="260px">
|
||||
<template slot-scope="scope">
|
||||
<el-input
|
||||
v-model="scope.row.templateName"
|
||||
size="mini"
|
||||
clearable
|
||||
placeholder="请输入模板名称"
|
||||
@change="updateTemplateName(scope.row)">
|
||||
</el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="排序" prop="sortNo" width="120px" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input-number
|
||||
v-model="scope.row.sortNo"
|
||||
size="mini"
|
||||
:min="0"
|
||||
:controls="false"
|
||||
style="width: 80px"
|
||||
@change="updateSortNo(scope.row)">
|
||||
</el-input-number>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="名称" prop="name"></el-table-column>
|
||||
<el-table-column label="PC端链接" prop="url" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="模板图标" prop="templateIcon" width="120px" align="center">
|
||||
<template slot-scope="scope">
|
||||
<file-upload
|
||||
class="template-icon-upload"
|
||||
:upload_number="1"
|
||||
:value="scope.row.templateIcon"
|
||||
accept=".jpg,.jpeg,.png"
|
||||
upload_result_type="url"
|
||||
upload_result_category="interval"
|
||||
upload_mode="image"
|
||||
@update:value="onTemplateIconChange(scope.row, $event)">
|
||||
</file-upload>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="模板文件" prop="templateFile" width="170px" align="center">
|
||||
<template slot-scope="scope">
|
||||
<file-upload
|
||||
class="template-file-upload"
|
||||
:upload_number="1"
|
||||
:value="scope.row.templateFile"
|
||||
accept=".doc,.docx,.xls,.xlsx,.pdf,.ppt,.pptx,.jpg,.jpeg,.png"
|
||||
upload_result_type="url"
|
||||
upload_result_category="interval"
|
||||
upload_mode="file"
|
||||
@update:value="onTemplateFileChange(scope.row, $event)">
|
||||
</file-upload>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" prop="enable" width="80px">
|
||||
<template slot-scope="scope">
|
||||
<i v-if="!scope.row.enable" class="fa fa-circle text-danger ml5"></i>
|
||||
<i v-else class="fa fa-circle text-success ml5"></i>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="180px">
|
||||
<template slot-scope="scope">
|
||||
<el-link type="danger" size="mini" @click="disable(scope.row.id)" v-if="scope.row.enable">关闭</el-link>
|
||||
<el-link type="primary" size="mini" @click="enable(scope.row.id)" v-if="!scope.row.enable">开启</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
mixins: [initTableMixins],
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
methods: {
|
||||
disable(id) {
|
||||
this.$confirm("您确定要关闭吗?", "提示", {
|
||||
type: "warning",
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消"
|
||||
}).then(() => {
|
||||
this.$axios.post(loc() + "/disable", {id}).then((resp) => {
|
||||
if (resp.code === 0) {
|
||||
this.$message.success(resp.msg)
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.error(resp.msg)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
enable(id) {
|
||||
this.$confirm("您确定要开启吗?", "提示", {
|
||||
type: "warning",
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消"
|
||||
}).then(() => {
|
||||
this.$axios.post(loc() + "/enable", {id}).then((resp) => {
|
||||
if (resp.code === 0) {
|
||||
this.$message.success(resp.msg)
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.error(resp.msg)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
updateTemplateName(row) {
|
||||
this.$axios.post(loc() + "/updateTemplateName", {
|
||||
id: row.id,
|
||||
templateName: row.templateName
|
||||
}).then((resp) => {
|
||||
if (resp.code === 0) {
|
||||
this.$message.success(resp.msg)
|
||||
} else {
|
||||
this.$message.error(resp.msg)
|
||||
}
|
||||
})
|
||||
},
|
||||
updateSortNo(row) {
|
||||
this.$axios.post(loc() + "/updateSortNo", {
|
||||
id: row.id,
|
||||
sortNo: row.sortNo
|
||||
}).then((resp) => {
|
||||
if (resp.code === 0) {
|
||||
this.$message.success(resp.msg)
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.error(resp.msg)
|
||||
}
|
||||
})
|
||||
},
|
||||
onTemplateIconChange(row, templateIcon) {
|
||||
if (templateIcon === undefined && !row.templateIcon) {
|
||||
return
|
||||
}
|
||||
row.templateIcon = templateIcon
|
||||
this.updateTemplateIcon(row)
|
||||
},
|
||||
updateTemplateIcon(row) {
|
||||
this.$nextTick(() => {
|
||||
this.$axios.post(loc() + "/updateTemplateIcon", {
|
||||
id: row.id,
|
||||
templateIcon: row.templateIcon
|
||||
}).then((resp) => {
|
||||
if (resp.code === 0) {
|
||||
this.$message.success(resp.msg)
|
||||
} else {
|
||||
this.$message.error(resp.msg)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
onTemplateFileChange(row, templateFile) {
|
||||
if (templateFile === undefined && !row.templateFile) {
|
||||
return
|
||||
}
|
||||
row.templateFile = templateFile
|
||||
this.updateTemplateFile(row)
|
||||
},
|
||||
updateTemplateFile(row) {
|
||||
this.$nextTick(() => {
|
||||
this.$axios.post(loc() + "/updateTemplateFile", {
|
||||
id: row.id,
|
||||
templateFile: row.templateFile
|
||||
}).then((resp) => {
|
||||
if (resp.code === 0) {
|
||||
this.$message.success(resp.msg)
|
||||
} else {
|
||||
this.$message.error(resp.msg)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.pageData()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style>
|
||||
.template-icon-upload,
|
||||
.template-file-upload {
|
||||
--upload-width: 48px;
|
||||
--upload-height: 48px;
|
||||
}
|
||||
|
||||
.template-icon-upload .el-upload-list--picture-card .el-upload-list__item,
|
||||
.template-icon-upload .el-upload--picture-card,
|
||||
.template-file-upload .el-upload-list--picture-card .el-upload-list__item,
|
||||
.template-file-upload .el-upload--picture-card {
|
||||
width: 48px !important;
|
||||
height: 48px !important;
|
||||
line-height: 48px !important;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.template-icon-upload .el-upload--picture-card i,
|
||||
.template-file-upload .el-upload--picture-card i {
|
||||
font-size: 18px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
Reference in New Issue
Block a user