1.0.2
parent
1c2e2975bb
commit
d2f23a8381
BIN
goodnews.db
BIN
goodnews.db
Binary file not shown.
16
main.go
16
main.go
|
@ -54,7 +54,7 @@ func main() {
|
||||||
// 获取喜报列表
|
// 获取喜报列表
|
||||||
func getGoodNewsList(c *gin.Context) {
|
func getGoodNewsList(c *gin.Context) {
|
||||||
var goodNewsList []models.GoodNews
|
var goodNewsList []models.GoodNews
|
||||||
result := db.Find(&goodNewsList)
|
result := db.Order("created_at desc").Find(&goodNewsList)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()})
|
||||||
return
|
return
|
||||||
|
@ -139,9 +139,14 @@ func handleUploadAndCreate(c *gin.Context) {
|
||||||
|
|
||||||
fmt.Println("OCR识别信息:", projectName, points, representative)
|
fmt.Println("OCR识别信息:", projectName, points, representative)
|
||||||
// 创建喜报记录
|
// 创建喜报记录
|
||||||
|
var pointValue int
|
||||||
|
if len(points) > 0 {
|
||||||
|
pointValue = points[0]
|
||||||
|
}
|
||||||
|
|
||||||
goodNews := models.GoodNews{
|
goodNews := models.GoodNews{
|
||||||
ProjectName: projectName,
|
ProjectName: projectName,
|
||||||
Points: points,
|
Points: pointValue,
|
||||||
Representative: representative,
|
Representative: representative,
|
||||||
ImagePath: filePath,
|
ImagePath: filePath,
|
||||||
}
|
}
|
||||||
|
@ -238,9 +243,14 @@ func handleFileUpload(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建喜报记录
|
// 创建喜报记录
|
||||||
|
var pointValue int
|
||||||
|
if len(points) > 0 {
|
||||||
|
pointValue = points[0]
|
||||||
|
}
|
||||||
|
|
||||||
goodNews := models.GoodNews{
|
goodNews := models.GoodNews{
|
||||||
ProjectName: projectName,
|
ProjectName: projectName,
|
||||||
Points: points,
|
Points: pointValue,
|
||||||
Representative: representative,
|
Representative: representative,
|
||||||
ImagePath: filePath,
|
ImagePath: filePath,
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,5 +11,4 @@
|
||||||
+ 本项目后端采用golang+gin
|
+ 本项目后端采用golang+gin
|
||||||
+ 前端采用element-ui
|
+ 前端采用element-ui
|
||||||
+ 数据库采用sqlite
|
+ 数据库采用sqlite
|
||||||
+ 图片存储采用七牛云
|
|
||||||
+ 部署采用docker
|
+ 部署采用docker
|
|
@ -24,23 +24,51 @@ func (s *OCRService) Close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExtractInfo 从图片中提取喜报信息
|
// ExtractInfo 从图片中提取喜报信息
|
||||||
func (s *OCRService) ExtractInfo(imagePath string) (string, int, string, error) {
|
func (s *OCRService) ExtractInfo(imagePath string) (string, []int, string, error) {
|
||||||
// 设置中文语言包
|
// 设置中文语言包和OCR配置
|
||||||
err := s.client.SetLanguage("chi_sim")
|
err := s.client.SetLanguage("chi_sim")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", 0, "", err
|
return "", nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置Page Segmentation Mode为自动
|
||||||
|
err = s.client.SetPageSegMode(gosseract.PSM_AUTO)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置OCR引擎参数
|
||||||
|
configs := []struct {
|
||||||
|
key string
|
||||||
|
value string
|
||||||
|
}{
|
||||||
|
{"tessedit_ocr_engine_mode", "2"}, // LSTM only
|
||||||
|
{"tessedit_enable_dict_correction", "1"}, // 启用字典校正
|
||||||
|
{"tessedit_pageseg_mode", "3"}, // 完全自动页面分割,但没有OSD
|
||||||
|
{"tessedit_do_invert", "0"}, // 不反转图像
|
||||||
|
{"textord_heavy_nr", "1"}, // 处理粗体文本
|
||||||
|
{"language_model_penalty_non_dict_word", "0.2"}, // 降低非字典词的惩罚
|
||||||
|
{"language_model_penalty_non_freq_dict_word", "0.2"}, // 降低非常用词的惩罚
|
||||||
|
{"tessedit_write_images", "1"}, // 输出调试图像
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, cfg := range configs {
|
||||||
|
err = s.client.SetVariable(gosseract.SettableVariable(cfg.key), cfg.value)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, "", err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置图片
|
// 设置图片
|
||||||
err = s.client.SetImage(imagePath)
|
err = s.client.SetImage(imagePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", 0, "", err
|
return "", nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取文本
|
// 获取文本
|
||||||
text, err := s.client.Text()
|
text, err := s.client.Text()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", 0, "", err
|
return "", nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 提取项目名称
|
// 提取项目名称
|
||||||
|
@ -57,32 +85,165 @@ func (s *OCRService) ExtractInfo(imagePath string) (string, int, string, error)
|
||||||
|
|
||||||
// 提取项目名称
|
// 提取项目名称
|
||||||
func extractProjectName(text string) string {
|
func extractProjectName(text string) string {
|
||||||
|
// 按行分割文本
|
||||||
lines := strings.Split(text, "\n")
|
lines := strings.Split(text, "\n")
|
||||||
|
|
||||||
|
// 定义项目相关的正则表达式模式
|
||||||
|
projectPatterns := []*regexp.Regexp{
|
||||||
|
regexp.MustCompile(`([\p{Han}]+)项目`),
|
||||||
|
regexp.MustCompile(`项目[::]*\s*([\p{Han}]+)`),
|
||||||
|
regexp.MustCompile(`([\p{Han}]+(?:工程|系统))`),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 遍历每一行文本
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
if strings.Contains(line, "项目") {
|
line = strings.TrimSpace(line)
|
||||||
return strings.TrimSpace(line)
|
if line == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用正则表达式匹配项目名称
|
||||||
|
for _, pattern := range projectPatterns {
|
||||||
|
matches := pattern.FindStringSubmatch(line)
|
||||||
|
if len(matches) > 1 {
|
||||||
|
name := strings.TrimSpace(matches[1])
|
||||||
|
if name != "" && len(name) >= 2 { // 确保项目名称至少包含两个汉字
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// 提取点数
|
// 提取点数
|
||||||
func extractPoints(text string) int {
|
func extractPoints(text string) []int {
|
||||||
re := regexp.MustCompile(`(\d+)\s*点|points?`)
|
var points []int
|
||||||
matches := re.FindStringSubmatch(text)
|
|
||||||
if len(matches) > 1 {
|
// 将文本按行分割
|
||||||
points, _ := strconv.Atoi(matches[1])
|
lines := strings.Split(text, "\n")
|
||||||
return points
|
|
||||||
}
|
// 存储可能的点数
|
||||||
return 0
|
var possiblePoints []int
|
||||||
|
|
||||||
|
// 遍历所有行,找出包含"点"字的行,并在其之前的行中查找数字
|
||||||
|
for i, line := range lines {
|
||||||
|
line = strings.TrimSpace(line)
|
||||||
|
if line == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果当前行包含"点"字
|
||||||
|
if strings.Contains(line, "点") {
|
||||||
|
// 向上查找最多3行
|
||||||
|
startIdx := maxInt(0, i-3)
|
||||||
|
|
||||||
|
// 检查当前行之前的行
|
||||||
|
for j := startIdx; j <= i; j++ {
|
||||||
|
prevLine := strings.TrimSpace(lines[j])
|
||||||
|
if prevLine == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取行中的数字
|
||||||
|
numPattern := regexp.MustCompile(`(\d+)`)
|
||||||
|
matches := numPattern.FindAllStringSubmatch(prevLine, -1)
|
||||||
|
for _, match := range matches {
|
||||||
|
if len(match) >= 2 {
|
||||||
|
if num, err := strconv.Atoi(match[1]); err == nil {
|
||||||
|
if num > 0 && num <= 1000 {
|
||||||
|
possiblePoints = append(possiblePoints, num)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 去重并返回结果
|
||||||
|
pointsMap := make(map[int]bool)
|
||||||
|
for _, num := range possiblePoints {
|
||||||
|
if !pointsMap[num] {
|
||||||
|
points = append(points, num)
|
||||||
|
pointsMap[num] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return points
|
||||||
}
|
}
|
||||||
|
|
||||||
// 提取代表处
|
// 提取代表处
|
||||||
|
// maxInt 返回两个整数中的较大值
|
||||||
|
func maxInt(a, b int) int {
|
||||||
|
if a > b {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// minInt 返回两个整数中的较小值
|
||||||
|
func minInt(a, b int) int {
|
||||||
|
if a < b {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
func extractRepresentative(text string) string {
|
func extractRepresentative(text string) string {
|
||||||
re := regexp.MustCompile(`([^\s]+代表处)`)
|
// 将文本按行分割
|
||||||
matches := re.FindStringSubmatch(text)
|
lines := strings.Split(text, "\n")
|
||||||
if len(matches) > 1 {
|
|
||||||
return matches[1]
|
// 定义代表处相关的关键词和对应的正则表达式模式
|
||||||
|
patterns := map[string]string{
|
||||||
|
"代表处": `([\p{Han}]{2,}代表处)`,
|
||||||
|
"事业部": `([\p{Han}]{2,}事业部)`,
|
||||||
|
"项目组": `([\p{Han}]{2,}项目组)`,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 遍历每一行文本
|
||||||
|
for _, line := range lines {
|
||||||
|
// 移除多余空格
|
||||||
|
line = strings.TrimSpace(line)
|
||||||
|
|
||||||
|
// 跳过空行
|
||||||
|
if line == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 遍历所有模式进行匹配
|
||||||
|
for keyword, pattern := range patterns {
|
||||||
|
if strings.Contains(line, keyword) {
|
||||||
|
re := regexp.MustCompile(pattern)
|
||||||
|
matches := re.FindStringSubmatch(line)
|
||||||
|
if len(matches) > 1 {
|
||||||
|
// 返回匹配到的完整名称
|
||||||
|
return matches[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有找到完整匹配,尝试提取可能的组织名称
|
||||||
|
orgPatterns := []string{
|
||||||
|
`([\p{Han}]{2,}(?:组|部|处|司|中心))`,
|
||||||
|
`([\p{Han}]{2,}(?:公司|单位))`,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, line := range lines {
|
||||||
|
line = strings.TrimSpace(line)
|
||||||
|
if line == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pattern := range orgPatterns {
|
||||||
|
re := regexp.MustCompile(pattern)
|
||||||
|
matches := re.FindStringSubmatch(line)
|
||||||
|
if len(matches) > 1 {
|
||||||
|
return matches[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
|
@ -14,41 +14,49 @@ func TestOCRService_ExtractInfo(t *testing.T) {
|
||||||
|
|
||||||
// 测试用例
|
// 测试用例
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
imagePath string
|
imagePath string
|
||||||
wantProject string
|
wantErr bool
|
||||||
wantPoints int
|
|
||||||
wantRep string
|
|
||||||
wantErr bool
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "test_image",
|
name: "test_image_360",
|
||||||
imagePath: "../uploads/test_image.jpg",
|
imagePath: "/home/devbox/project/uploads/test_image.png",
|
||||||
// 预期结果将根据实际测试图片调整
|
wantErr: false,
|
||||||
wantProject: "乌省旗信创云桌面项目",
|
},
|
||||||
wantPoints: 360,
|
{
|
||||||
wantRep: "内蒙代表处",
|
name: "test_image_100",
|
||||||
wantErr: false,
|
imagePath: "/home/devbox/project/uploads/test_image_100.png",
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "test_image_50",
|
||||||
|
imagePath: "/home/devbox/project/uploads/test_image_50.png",
|
||||||
|
wantErr: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// 运行测试用例
|
// 运行测试用例
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
// 设置图片并获取OCR识别结果
|
||||||
|
err = ocr.client.SetImage(tt.imagePath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to set image: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
text, err := ocr.client.Text()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to get OCR text: %v", err)
|
||||||
|
}
|
||||||
|
t.Logf("OCR recognized text:\n%s", text)
|
||||||
|
|
||||||
project, points, rep, err := ocr.ExtractInfo(tt.imagePath)
|
project, points, rep, err := ocr.ExtractInfo(tt.imagePath)
|
||||||
if (err != nil) != tt.wantErr {
|
if err != nil {
|
||||||
t.Errorf("ExtractInfo() error = %v, wantErr %v", err, tt.wantErr)
|
t.Fatalf("Failed to extract info: %v", err)
|
||||||
return
|
|
||||||
}
|
|
||||||
if project != tt.wantProject {
|
|
||||||
t.Errorf("ExtractInfo() project = %v, want %v", project, tt.wantProject)
|
|
||||||
}
|
|
||||||
if points != tt.wantPoints {
|
|
||||||
t.Errorf("ExtractInfo() points = %v, want %v", points, tt.wantPoints)
|
|
||||||
}
|
|
||||||
if rep != tt.wantRep {
|
|
||||||
t.Errorf("ExtractInfo() representative = %v, want %v", rep, tt.wantRep)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 输出识别结果
|
||||||
|
t.Logf("识别结果 - 项目名称: %s, 点数: %d, 代表处: %s", project, points, rep)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -87,7 +87,7 @@
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8" style="text-align: right;">
|
<el-col :span="8" style="text-align: right;">
|
||||||
<el-button @click="resetFilters">重置筛选</el-button>
|
<div>共 <span style="color: red;">{{ filteredNews.length }}</span> 条,总计 <span style="color: red;">{{ totalPoints }}</span> 点</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
|
@ -113,34 +113,6 @@
|
||||||
<img :src="currentImage.image_url" style="width: 100%;">
|
<img :src="currentImage.image_url" style="width: 100%;">
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="imageDialogVisible = false">关闭</el-button>
|
<el-button @click="imageDialogVisible = false">关闭</el-button>
|
||||||
<el-button type="primary" @click="editNews(currentImage)">编辑</el-button>
|
|
||||||
<el-button type="danger" @click="deleteNews(currentImage)">删除</el-button>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<!-- 编辑对话框 -->
|
|
||||||
<el-dialog v-model="editDialogVisible" title="编辑喜报信息" width="500px">
|
|
||||||
<el-form :model="editForm" label-width="100px">
|
|
||||||
<el-form-item label="项目名称">
|
|
||||||
<el-input v-model="editForm.project_name"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="签单点数">
|
|
||||||
<el-input-number v-model="editForm.points"></el-input-number>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="代表处">
|
|
||||||
<el-select v-model="editForm.office">
|
|
||||||
<el-option
|
|
||||||
v-for="office in offices"
|
|
||||||
:key="office"
|
|
||||||
:label="office"
|
|
||||||
:value="office">
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<template #footer>
|
|
||||||
<el-button @click="editDialogVisible = false">取消</el-button>
|
|
||||||
<el-button type="primary" @click="submitEdit">确定</el-button>
|
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
|
@ -152,15 +124,17 @@
|
||||||
const { createApp, ref, computed } = Vue
|
const { createApp, ref, computed } = Vue
|
||||||
|
|
||||||
const app = createApp({
|
const app = createApp({
|
||||||
|
components: {
|
||||||
|
// 注册所需的Element Plus组件
|
||||||
|
ElMessage: ElementPlus.ElMessage,
|
||||||
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const news = ref([])
|
const news = ref([])
|
||||||
const filterMonth = ref('')
|
const filterMonth = ref('')
|
||||||
const filterOffice = ref('')
|
const filterOffice = ref('')
|
||||||
const offices = ref([])
|
const offices = ref([])
|
||||||
const imageDialogVisible = ref(false)
|
const imageDialogVisible = ref(false)
|
||||||
const editDialogVisible = ref(false)
|
|
||||||
const currentImage = ref({})
|
const currentImage = ref({})
|
||||||
const editForm = ref({})
|
|
||||||
|
|
||||||
const filteredNews = computed(() => {
|
const filteredNews = computed(() => {
|
||||||
return news.value.filter(item => {
|
return news.value.filter(item => {
|
||||||
|
@ -190,61 +164,16 @@
|
||||||
// 筛选会自动通过computed属性完成
|
// 筛选会自动通过computed属性完成
|
||||||
}
|
}
|
||||||
|
|
||||||
const resetFilters = () => {
|
const totalPoints = computed(() => {
|
||||||
filterMonth.value = ''
|
return filteredNews.value.reduce((sum, item) => sum + item.points, 0)
|
||||||
filterOffice.value = ''
|
})
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const showImageDetail = (item) => {
|
const showImageDetail = (item) => {
|
||||||
currentImage.value = item
|
currentImage.value = item
|
||||||
imageDialogVisible.value = true
|
imageDialogVisible.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const editNews = (item) => {
|
|
||||||
editForm.value = { ...item }
|
|
||||||
imageDialogVisible.value = false
|
|
||||||
editDialogVisible.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
const submitEdit = async () => {
|
|
||||||
try {
|
|
||||||
const response = await fetch(`/api/news/${editForm.value.id}`, {
|
|
||||||
method: 'PUT',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify(editForm.value)
|
|
||||||
})
|
|
||||||
if (response.ok) {
|
|
||||||
ElMessage.success('更新成功')
|
|
||||||
editDialogVisible.value = false
|
|
||||||
fetchNews()
|
|
||||||
} else {
|
|
||||||
throw new Error('更新失败')
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
ElMessage.error('更新失败')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const deleteNews = async (item) => {
|
|
||||||
try {
|
|
||||||
const response = await fetch(`/api/news/${item.id}`, {
|
|
||||||
method: 'DELETE'
|
|
||||||
})
|
|
||||||
if (response.ok) {
|
|
||||||
ElMessage.success('删除成功')
|
|
||||||
imageDialogVisible.value = false
|
|
||||||
fetchNews()
|
|
||||||
} else {
|
|
||||||
throw new Error('删除失败')
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
ElMessage.error('删除失败')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const formatDate = (dateString) => {
|
const formatDate = (dateString) => {
|
||||||
if (!dateString) return ''
|
if (!dateString) return ''
|
||||||
|
@ -261,17 +190,12 @@
|
||||||
filterOffice,
|
filterOffice,
|
||||||
offices,
|
offices,
|
||||||
imageDialogVisible,
|
imageDialogVisible,
|
||||||
editDialogVisible,
|
|
||||||
currentImage,
|
currentImage,
|
||||||
editForm,
|
|
||||||
filteredNews,
|
filteredNews,
|
||||||
handleManageClick,
|
handleManageClick,
|
||||||
handleFilterChange,
|
handleFilterChange,
|
||||||
resetFilters,
|
totalPoints,
|
||||||
showImageDetail,
|
showImageDetail,
|
||||||
editNews,
|
|
||||||
submitEdit,
|
|
||||||
deleteNews,
|
|
||||||
formatDate
|
formatDate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,8 +50,8 @@
|
||||||
<h1>喜报管理系统 - 管理页面</h1>
|
<h1>喜报管理系统 - 管理页面</h1>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8" style="text-align: right;">
|
<el-col :span="8" style="text-align: right;">
|
||||||
<el-button @click="goToIndex" style="margin-right: 10px">返回首页</el-button>
|
<el-button @click="goToIndex" style="margin-right: 10px" :icon="ArrowLeft" circle></el-button>
|
||||||
<el-button type="primary" @click="showUploadDialog">上传喜报</el-button>
|
<el-button type="primary" @click="showUploadDialog" :icon="Upload" circle></el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
|
@ -140,10 +140,12 @@
|
||||||
const app = createApp({
|
const app = createApp({
|
||||||
setup() {
|
setup() {
|
||||||
// 导入所需的图标组件
|
// 导入所需的图标组件
|
||||||
const { UploadFilled } = ElementPlusIconsVue
|
const { UploadFilled, ArrowLeft, Upload } = ElementPlusIconsVue
|
||||||
// 确保返回UploadFilled组件以供模板使用
|
// 确保返回所有需要的组件
|
||||||
const newsList = ref([])
|
const newsList = ref([])
|
||||||
const offices = ref([])
|
const offices = ref([])
|
||||||
|
// 注册Element Plus组件
|
||||||
|
const ElMessage = ElementPlus.ElMessage
|
||||||
const uploadDialogVisible = ref(false)
|
const uploadDialogVisible = ref(false)
|
||||||
const editDialogVisible = ref(false)
|
const editDialogVisible = ref(false)
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
@ -328,7 +330,9 @@
|
||||||
handleSizeChange,
|
handleSizeChange,
|
||||||
handleCurrentChange,
|
handleCurrentChange,
|
||||||
goToIndex,
|
goToIndex,
|
||||||
UploadFilled
|
UploadFilled,
|
||||||
|
ArrowLeft,
|
||||||
|
Upload
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 164 KiB |
Binary file not shown.
After Width: | Height: | Size: 551 KiB |
Binary file not shown.
After Width: | Height: | Size: 548 KiB |
Loading…
Reference in New Issue