增加天气组件,增加商品管理页面、增加财务管理页面

增加天气组件,增加商品管理页面、增加财务管理页面
pull/400/head
wesker1121 2024-12-04 14:10:26 +08:00
parent 6a7019ec1a
commit 1717bcbfd0
8 changed files with 345 additions and 1 deletions

1
components.d.ts vendored
View File

@ -77,5 +77,6 @@ declare module '@vue/runtime-core' {
TableEdit: typeof import('./src/components/table-edit.vue')['default']
TableSearch: typeof import('./src/components/table-search.vue')['default']
Tabs: typeof import('./src/components/tabs.vue')['default']
WeatherWidget: typeof import('./src/components/WeatherWidget.vue')['default']
}
}

View File

@ -0,0 +1,79 @@
<!-- src/components/WeatherWidget.vue -->
<template>
<el-card shadow="hover" class="weather-widget">
<div class="weather-header">
<el-icon class="weather-icon">
<Sunny />
</el-icon>
<div class="weather-info">
<div class="weather-temp">{{ weather.temp }}°C</div>
<div class="weather-desc">{{ weather.description }}</div>
<div class="weather-city">{{weather.city}}</div>
</div>
</div>
</el-card>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { ElMessage } from 'element-plus';
import { Sunny } from '@element-plus/icons-vue';
const weather = ref({
temp: 0,
description: 'Loading...',
});
const fetchWeather = async () => {
try {
const response = await fetch('https://restapi.amap.com/v3/weather/weatherInfo?key= &city=230103&extensions=base');
const data = await response.json();
if (data.status === '1' && data.lives && data.lives.length > 0) {
weather.value.temp = data.lives[0].temperature;
weather.value.description = data.lives[0].weather;
weather.value.city = data.lives[0].city;
} else {
throw new Error('Invalid weather data');
}
} catch (error) {
ElMessage.error('Failed to fetch weather data');
}
};
onMounted(() => {
fetchWeather();
});
</script>
<style scoped>
.weather-widget {
display: flex;
align-items: center;
padding: 20px;
}
.weather-header {
display: flex;
align-items: center;
}
.weather-icon {
font-size: 50px;
margin-right: 20px;
}
.weather-info {
text-align: left;
}
.weather-temp {
font-size: 30px;
font-weight: bold;
}
.weather-desc {
font-size: 14px;
color: #999;
}
</style>

View File

@ -31,6 +31,18 @@ export const menuData: Menus[] = [
index: '/system-menu',
title: '菜单管理',
},
{
id: '14',
pid: '1',
index: '/product-management',
title: '商品管理',
},
{
id: '15',
pid: '1',
index: '/finance-management',
title: '财务管理',
},
],
},
{

View File

@ -50,6 +50,24 @@ const routes: RouteRecordRaw[] = [
},
component: () => import(/* webpackChunkName: "system-menu" */ '../views/system/menu.vue'),
},
{
path: '/product-management',
name: 'product-management',
meta: {
title: '商品管理',
permiss: '14',
},
component: () => import(/* webpackChunkName: "product-management" */ '../views/product-management.vue'),
},
{
path: '/finance-management',
name: 'finance-management',
meta: {
title: '财务管理',
permiss: '15',
},
component: () => import(/* webpackChunkName: "finance-management" */ '../views/finance-management.vue'),
},
{
path: '/table',
name: 'basetable',

View File

@ -13,6 +13,8 @@ export const usePermissStore = defineStore('permiss', {
'11',
'12',
'13',
'14',
'15',
'2',
'21',
'22',
@ -43,7 +45,7 @@ export const usePermissStore = defineStore('permiss', {
'65',
'66',
],
user: ['0', '1', '11', '12', '13'],
user: ['0', '1', '11', '12', '13', '14', '15'],
};
const username = localStorage.getItem('vuems_name');
console.log(username);

View File

@ -1,5 +1,10 @@
<template>
<div>
<el-row :gutter="20" class="mgb20">
<el-col :span="6">
<WeatherWidget />
</el-col>
</el-row>
<el-row :gutter="20" class="mgb20">
<el-col :span="6">
<el-card shadow="hover" body-class="card-body">
@ -127,6 +132,7 @@
</template>
<script setup lang="ts" name="dashboard">
import WeatherWidget from '@/components/WeatherWidget.vue';
import countup from '@/components/countup.vue';
import { use, registerMap } from 'echarts/core';
import { BarChart, LineChart, PieChart, MapChart } from 'echarts/charts';

View File

@ -0,0 +1,113 @@
<template>
<div>
<h1>财务管理</h1>
<el-button type="primary" @click="openDialog"></el-button>
<el-table :data="records" style="width: 100%">
<el-table-column prop="date" label="日期" width="180"></el-table-column>
<el-table-column prop="amount" label="金额" width="180"></el-table-column>
<el-table-column prop="description" label="描述" width="180"></el-table-column>
<el-table-column label="操作" width="180">
<template #default="scope">
<el-button @click="editRecord(scope.row)" type="primary" size="small">编辑</el-button>
<el-button @click="deleteRecord(scope.row)" type="danger" size="small">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog :title="isEdit ? '编辑记录' : '新增记录'" v-model="dialogVisible">
<el-form :model="form">
<el-form-item label="日期">
<el-date-picker v-model="form.date" type="date" placeholder="选择日期"></el-date-picker>
</el-form-item>
<el-form-item label="金额">
<el-input v-model="form.amount"></el-input>
</el-form-item>
<el-form-item label="描述">
<el-input v-model="form.description"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="saveRecord"></el-button>
</div>
</el-dialog>
</div>
</template>
<script setup lang="ts" name="finance-management">
import { ref, onMounted } from 'vue';
import { ElMessage } from 'element-plus';
const records = ref([]);
const dialogVisible = ref(false);
const isEdit = ref(false);
const form = ref({
date: '',
amount: '',
description: '',
});
const fetchRecords = async () => {
try {
const response = await fetch('/api/finance-records');
const data = await response.json();
records.value = data;
} catch (error) {
ElMessage.error('Failed to fetch financial records');
}
};
const openDialog = () => {
isEdit.value = false;
form.value = { date: '', amount: '', description: '' };
dialogVisible.value = true;
};
const editRecord = (record) => {
isEdit.value = true;
form.value = { ...record };
dialogVisible.value = true;
};
const saveRecord = async () => {
try {
if (isEdit.value) {
// Update record
await fetch(`/api/finance-records/${form.value.id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(form.value),
});
} else {
// Add new record
await fetch('/api/finance-records', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(form.value),
});
}
fetchRecords();
dialogVisible.value = false;
ElMessage.success('Record saved successfully');
} catch (error) {
ElMessage.error('Failed to save record');
}
};
const deleteRecord = async (record) => {
try {
await fetch(`/api/finance-records/${record.id}`, { method: 'DELETE' });
fetchRecords();
ElMessage.success('Record deleted successfully');
} catch (error) {
ElMessage.error('Failed to delete record');
}
};
onMounted(() => {
fetchRecords();
});
</script>
<style scoped>
</style>

View File

@ -0,0 +1,113 @@
<template>
<div>
<h1>商品管理</h1>
<el-button type="primary" @click="openDialog"></el-button>
<el-table :data="products" style="width: 100%">
<el-table-column prop="name" label="商品名称" width="180"></el-table-column>
<el-table-column prop="price" label="价格" width="180"></el-table-column>
<el-table-column prop="category" label="分类" width="180"></el-table-column>
<el-table-column label="操作" width="180">
<template #default="scope">
<el-button @click="editProduct(scope.row)" type="primary" size="small">编辑</el-button>
<el-button @click="deleteProduct(scope.row)" type="danger" size="small">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog :title="isEdit ? '编辑商品' : '新增商品'" v-model="dialogVisible">
<el-form :model="form">
<el-form-item label="商品名称">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="价格">
<el-input v-model="form.price"></el-input>
</el-form-item>
<el-form-item label="分类">
<el-input v-model="form.category"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="saveProduct"></el-button>
</div>
</el-dialog>
</div>
</template>
<script setup lang="ts" name="product-management">
import { ref, onMounted } from 'vue';
import { ElMessage } from 'element-plus';
const products = ref([]);
const dialogVisible = ref(false);
const isEdit = ref(false);
const form = ref({
name: '',
price: '',
category: '',
});
const fetchProducts = async () => {
try {
const response = await fetch('/api/products');
const data = await response.json();
products.value = data;
} catch (error) {
ElMessage.error('Failed to fetch product data');
}
};
const openDialog = () => {
isEdit.value = false;
form.value = { name: '', price: '', category: '' };
dialogVisible.value = true;
};
const editProduct = (product) => {
isEdit.value = true;
form.value = { ...product };
dialogVisible.value = true;
};
const saveProduct = async () => {
try {
if (isEdit.value) {
// Update product
await fetch(`/api/products/${form.value.id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(form.value),
});
} else {
// Add new product
await fetch('/api/products', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(form.value),
});
}
fetchProducts();
dialogVisible.value = false;
ElMessage.success('Product saved successfully');
} catch (error) {
ElMessage.error('Failed to save product');
}
};
const deleteProduct = async (product) => {
try {
await fetch(`/api/products/${product.id}`, { method: 'DELETE' });
fetchProducts();
ElMessage.success('Product deleted successfully');
} catch (error) {
ElMessage.error('Failed to delete product');
}
};
onMounted(() => {
fetchProducts();
});
</script>
<style scoped>
</style>