This commit is contained in:
parent
bd27f18e4c
commit
9004b72ba2
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"type": "module"
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -4,71 +4,70 @@
|
||||||
/* add fonts here */
|
/* add fonts here */
|
||||||
/* @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap'); */
|
/* @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap'); */
|
||||||
|
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
--background: 0 0% 100%;
|
--background: 0 0% 100%;
|
||||||
--foreground: 222.2 84% 4.9%;
|
--foreground: 0 0% 5%;
|
||||||
|
|
||||||
--card: 0 0% 100%;
|
--card: 0 0% 100%;
|
||||||
--card-foreground: 222.2 84% 4.9%;
|
--card-foreground: 0 0% 5%;
|
||||||
|
|
||||||
--popover: 0 0% 100%;
|
--popover: 0 0% 100%;
|
||||||
--popover-foreground: 222.2 84% 4.9%;
|
--popover-foreground: 0 0% 5%;
|
||||||
|
|
||||||
--primary: 221.2 83.2% 53.3%;
|
--primary: 190 56% 55%;
|
||||||
--primary-foreground: 210 40% 98%;
|
--primary-foreground: 0 0% 2%;
|
||||||
|
|
||||||
--secondary: 210 40% 96.1%;
|
--secondary: 0 0% 96%;
|
||||||
--secondary-foreground: 222.2 47.4% 11.2%;
|
--secondary-foreground: 0 0% 5%;
|
||||||
|
|
||||||
--muted: 210 40% 96.1%;
|
--muted: 0 0% 96%;
|
||||||
--muted-foreground: 215.4 16.3% 46.9%;
|
--muted-foreground: 0 0% 45%;
|
||||||
|
|
||||||
--accent: 210 40% 96.1%;
|
--accent: 0 0% 96%;
|
||||||
--accent-foreground: 222.2 47.4% 11.2%;
|
--accent-foreground: 0 0% 5%;
|
||||||
|
|
||||||
--destructive: 0 84.2% 60.2%;
|
--destructive: 0 84% 60%;
|
||||||
--destructive-foreground: 210 40% 98%;
|
--destructive-foreground: 0 0% 98%;
|
||||||
|
|
||||||
|
--border: 0 0% 92%;
|
||||||
|
--input: 0 0% 85%;
|
||||||
|
--ring: 0 0% 76%;
|
||||||
|
|
||||||
--border:214.3 31.8% 91.4%;
|
|
||||||
--input:214.3 31.8% 91.4%;
|
|
||||||
--ring:221.2 83.2% 53.3%;
|
|
||||||
--radius: 0.5rem;
|
--radius: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
--background:222.2 84% 4.9%;
|
--background: 0 0% 0%;
|
||||||
--foreground:210 40% 98%;
|
--foreground: 0 0% 98%;
|
||||||
|
|
||||||
--card:222.2 84% 4.9%;
|
--card: 0 0% 3%;
|
||||||
--card-foreground:210 40% 98%;
|
--card-foreground: 0 0% 98%;
|
||||||
|
|
||||||
--popover:222.2 84% 4.9%;
|
--popover: 0 0% 3%;
|
||||||
--popover-foreground:210 40% 98%;
|
--popover-foreground: 0 0% 98%;
|
||||||
|
|
||||||
--primary:217.2 91.2% 59.8%;
|
--primary: 187 71% 53%;
|
||||||
--primary-foreground:222.2 47.4% 11.2%;
|
--primary-foreground: 0 0% 2%;
|
||||||
|
|
||||||
--secondary:217.2 32.6% 17.5%;
|
--secondary: 0 0% 6%;
|
||||||
--secondary-foreground:210 40% 98%;
|
--secondary-foreground: 0 0% 98%;
|
||||||
|
|
||||||
--muted:217.2 32.6% 17.5%;
|
--muted: 0 0% 9%;
|
||||||
--muted-foreground:215 20.2% 65.1%;
|
--muted-foreground: 0 0% 49%;
|
||||||
|
|
||||||
--accent:217.2 32.6% 17.5%;
|
--accent: 0 0% 6%;
|
||||||
--accent-foreground:210 40% 98%;
|
--accent-foreground: 0 0% 98%;
|
||||||
|
|
||||||
--destructive:0 62.8% 30.6%;
|
--destructive: 0 84% 60%;
|
||||||
--destructive-foreground:210 40% 98%;
|
--destructive-foreground: 0 0% 98%;
|
||||||
|
|
||||||
--border:217.2 32.6% 17.5%;
|
--border: 0 0% 11%;
|
||||||
--input:217.2 32.6% 17.5%;
|
--input: 0 0% 16%;
|
||||||
--ring:224.3 76.3% 48%;
|
--ring: 187 71% 40%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
* {
|
* {
|
||||||
@apply border-border;
|
@apply border-border;
|
||||||
|
|
|
@ -33,6 +33,11 @@ effect(() => {
|
||||||
onDeactivated(() => {
|
onDeactivated(() => {
|
||||||
window.removeEventListener('resize', listener)
|
window.removeEventListener('resize', listener)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
chart,
|
||||||
|
chartEle,
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -22,7 +22,7 @@ defineProps<{
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Iconify :icon="icon" class="absolute top-1/2 right-9 -translate-y-1/2 w-[45px] h-[45px]" />
|
<Iconify :icon="icon" class="absolute top-1/2 right-12 -translate-y-1/2 w-[45px] h-[45px]" />
|
||||||
<svg
|
<svg
|
||||||
viewBox="0 0 420 92" fill="none" class="absolute top-0 left-0 -z-[1]" xmlns="http://www.w3.org/2000/svg"
|
viewBox="0 0 420 92" fill="none" class="absolute top-0 left-0 -z-[1]" xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns:anim="http://www.w3.org/2000/anim" anim="" anim:transform-origin="50% 50%" anim:duration="1"
|
xmlns:anim="http://www.w3.org/2000/anim" anim="" anim:transform-origin="50% 50%" anim:duration="1"
|
||||||
|
|
|
@ -7,16 +7,16 @@ defineProps<{
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="w-[96px] h-[66px] relative">
|
<div class="w-[110px] h-[66px] relative">
|
||||||
<div class="space-y-3 ">
|
<div class="space-y-3 ">
|
||||||
<div class="flex items-end gap-3">
|
<div class="flex items-end gap-3">
|
||||||
<Iconify :icon="icon" class="w-[38px] h-[38px] " />
|
<Iconify :icon="icon" class="w-[38px] h-[38px] shrink-0 " />
|
||||||
<div class="text-[24px] text-shadow">
|
<div class="text-[24px] text-shadow">
|
||||||
{{ value }}
|
{{ value }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div class="text-[14px]">
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,7 +6,7 @@ defineProps<{
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="w-[460px] h-fit relative my-2">
|
<div class="w-[460px] h-fit relative my-2">
|
||||||
<div class="absolute z-10 text-2xl tracking-wide -top-1 left-14 text-cyan-200">
|
<div class="absolute z-10 text-3xl tracking-wide -top-[1px] left-14 text-cyan-200">
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</div>
|
</div>
|
||||||
<FrameV1HeaderSvg class="absolute " />
|
<FrameV1HeaderSvg class="absolute " />
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
<Background class="z-10" />
|
<Background class="z-10" />
|
||||||
<div class="absolute top-0 left-0 z-10 flex items-end h-full pl-[150px] gap-[100px] pb-[32px]">
|
<div class="absolute top-0 left-0 z-10 flex items-end h-full pl-[150px] gap-[100px] pb-[32px]">
|
||||||
<div class="pb-[12px]">
|
<div class="pb-[12px]">
|
||||||
<h1 class="text-3xl font-bold">
|
<h1 class="text-4xl font-bold">
|
||||||
农村废弃物特征数据库
|
农村废弃物特征数据库
|
||||||
</h1>
|
</h1>
|
||||||
<p class="opacity-60">
|
<p class="text-lg opacity-60">
|
||||||
Rural waste characteristics database
|
Rural waste characteristics database
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts" generic="Task extends { [key: string]: any;}">
|
||||||
import type {
|
import type {
|
||||||
ColumnDef,
|
ColumnDef,
|
||||||
ColumnFiltersState,
|
ColumnFiltersState,
|
||||||
|
@ -17,18 +17,8 @@ import {
|
||||||
} from '@tanstack/vue-table'
|
} from '@tanstack/vue-table'
|
||||||
|
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import type { Task } from '../data/schema'
|
|
||||||
import DataTablePagination from './DataTablePagination.vue'
|
import DataTablePagination from './DataTablePagination.vue'
|
||||||
import DataTableToolbar from './DataTableToolbar.vue'
|
import DataTableToolbar from './DataTableToolbar.vue'
|
||||||
import { valueUpdater } from '@/lib/utils'
|
|
||||||
import {
|
|
||||||
Table,
|
|
||||||
TableBody,
|
|
||||||
TableCell,
|
|
||||||
TableHead,
|
|
||||||
TableHeader,
|
|
||||||
TableRow,
|
|
||||||
} from '@/lib/registry/new-york/ui/table'
|
|
||||||
|
|
||||||
interface DataTableProps {
|
interface DataTableProps {
|
||||||
columns: ColumnDef<Task, any>[]
|
columns: ColumnDef<Task, any>[]
|
||||||
|
@ -51,10 +41,10 @@ const table = useVueTable({
|
||||||
get rowSelection() { return rowSelection.value },
|
get rowSelection() { return rowSelection.value },
|
||||||
},
|
},
|
||||||
enableRowSelection: true,
|
enableRowSelection: true,
|
||||||
onSortingChange: updaterOrValue => valueUpdater(updaterOrValue, sorting),
|
onSortingChange: (updaterOrValue: any) => valueUpdater(updaterOrValue, sorting),
|
||||||
onColumnFiltersChange: updaterOrValue => valueUpdater(updaterOrValue, columnFilters),
|
onColumnFiltersChange: (updaterOrValue: any) => valueUpdater(updaterOrValue, columnFilters),
|
||||||
onColumnVisibilityChange: updaterOrValue => valueUpdater(updaterOrValue, columnVisibility),
|
onColumnVisibilityChange: (updaterOrValue: any) => valueUpdater(updaterOrValue, columnVisibility),
|
||||||
onRowSelectionChange: updaterOrValue => valueUpdater(updaterOrValue, rowSelection),
|
onRowSelectionChange: (updaterOrValue: any) => valueUpdater(updaterOrValue, rowSelection),
|
||||||
getCoreRowModel: getCoreRowModel(),
|
getCoreRowModel: getCoreRowModel(),
|
||||||
getFilteredRowModel: getFilteredRowModel(),
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
getPaginationRowModel: getPaginationRowModel(),
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
@ -66,8 +56,10 @@ const table = useVueTable({
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<DataTableToolbar :table="table" />
|
<DataTableToolbar :table="table">
|
||||||
<div class="rounded-md border">
|
<slot name="toolbar" />
|
||||||
|
</DataTableToolbar>
|
||||||
|
<div class="">
|
||||||
<Table>
|
<Table>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow v-for="headerGroup in table.getHeaderGroups()" :key="headerGroup.id">
|
<TableRow v-for="headerGroup in table.getHeaderGroups()" :key="headerGroup.id">
|
||||||
|
@ -83,7 +75,7 @@ const table = useVueTable({
|
||||||
:key="row.id"
|
:key="row.id"
|
||||||
:data-state="row.getIsSelected() && 'selected'"
|
:data-state="row.getIsSelected() && 'selected'"
|
||||||
>
|
>
|
||||||
<TableCell v-for="cell in row.getVisibleCells()" :key="cell.id">
|
<TableCell v-for="cell in row.getVisibleCells()" :key="cell.id" class=" text-[16px]">
|
||||||
<FlexRender :render="cell.column.columnDef.cell" :props="cell.getContext()" />
|
<FlexRender :render="cell.column.columnDef.cell" :props="cell.getContext()" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
@ -103,4 +95,4 @@ const table = useVueTable({
|
||||||
|
|
||||||
<DataTablePagination :table="table" />
|
<DataTablePagination :table="table" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>(: any)(: any)
|
||||||
|
|
|
@ -1,20 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts" generic="Task extends { [key: string]: any;}">
|
||||||
import type { Column } from '@tanstack/vue-table'
|
import type { Column } from '@tanstack/vue-table'
|
||||||
import type { Task } from '../data/schema'
|
|
||||||
import ArrowDownIcon from '~icons/radix-icons/arrow-down'
|
|
||||||
import ArrowUpIcon from '~icons/radix-icons/arrow-up'
|
|
||||||
import CaretSortIcon from '~icons/radix-icons/caret-sort'
|
|
||||||
import EyeNoneIcon from '~icons/radix-icons/eye-none'
|
|
||||||
|
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
|
||||||
import {
|
|
||||||
DropdownMenu,
|
|
||||||
DropdownMenuContent,
|
|
||||||
DropdownMenuItem,
|
|
||||||
DropdownMenuSeparator,
|
|
||||||
DropdownMenuTrigger,
|
|
||||||
} from '@/lib/registry/new-york/ui/dropdown-menu'
|
|
||||||
|
|
||||||
interface DataTableColumnHeaderProps {
|
interface DataTableColumnHeaderProps {
|
||||||
column: Column<Task, any>
|
column: Column<Task, any>
|
||||||
|
@ -40,23 +25,23 @@ export default {
|
||||||
class="-ml-3 h-8 data-[state=open]:bg-accent"
|
class="-ml-3 h-8 data-[state=open]:bg-accent"
|
||||||
>
|
>
|
||||||
<span>{{ title }}</span>
|
<span>{{ title }}</span>
|
||||||
<ArrowDownIcon v-if="column.getIsSorted() === 'desc'" class="ml-2 h-4 w-4" />
|
<Iconify v-if="column.getIsSorted() === 'desc'" icon="solar:arrow-down-line-duotone" class="w-4 h-4 ml-2" />
|
||||||
<ArrowUpIcon v-else-if=" column.getIsSorted() === 'asc'" class="ml-2 h-4 w-4" />
|
<Iconify v-if="column.getIsSorted() === 'asc'" icon="solar:arrow-down-line-duotone" class="w-4 h-4 ml-2 rotate-180 " />
|
||||||
<CaretSortIcon v-else class="ml-2 h-4 w-4" />
|
<Iconify v-else icon="solar:transfer-vertical-line-duotone" class="w-4 h-4 ml-2" />
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="start">
|
<DropdownMenuContent align="start">
|
||||||
<DropdownMenuItem @click="column.toggleSorting(false)">
|
<DropdownMenuItem @click="column.toggleSorting(false)">
|
||||||
<ArrowUpIcon class="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
|
<Iconify icon="solar:arrow-down-line-duotone" class=" rotate-180 mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
|
||||||
Asc
|
Asc
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem @click="column.toggleSorting(true)">
|
<DropdownMenuItem @click="column.toggleSorting(true)">
|
||||||
<ArrowDownIcon class="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
|
<Iconify icon="solar:arrow-down-line-duotone" class="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
|
||||||
Desc
|
Desc
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItem @click="column.toggleVisibility(false)">
|
<DropdownMenuItem @click="column.toggleVisibility(false)">
|
||||||
<EyeNoneIcon class="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
|
<Iconify icon="solar:eye-closed-bold-duotone" class="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
|
||||||
Hide
|
Hide
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
|
|
|
@ -1,22 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts" generic="Task extends { [key: string]: any;}">
|
||||||
import type { Column } from '@tanstack/vue-table'
|
import type { Column } from '@tanstack/vue-table'
|
||||||
import type { Component } from 'vue'
|
import type { Component } from 'vue'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import type { Task } from '../data/schema'
|
|
||||||
import PlusCircledIcon from '~icons/radix-icons/plus-circled'
|
|
||||||
import CheckIcon from '~icons/radix-icons/check'
|
|
||||||
|
|
||||||
import { Badge } from '@/lib/registry/new-york/ui/badge'
|
|
||||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
|
||||||
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator } from '@/lib/registry/new-york/ui/command'
|
|
||||||
|
|
||||||
import {
|
|
||||||
Popover,
|
|
||||||
PopoverContent,
|
|
||||||
PopoverTrigger,
|
|
||||||
} from '@/lib/registry/new-york/ui/popover'
|
|
||||||
import { Separator } from '@/lib/registry/new-york/ui/separator'
|
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
|
|
||||||
interface DataTableFacetedFilter {
|
interface DataTableFacetedFilter {
|
||||||
column?: Column<Task, any>
|
column?: Column<Task, any>
|
||||||
|
@ -38,13 +23,13 @@ const selectedValues = computed(() => new Set(props.column?.getFilterValue() as
|
||||||
<Popover>
|
<Popover>
|
||||||
<PopoverTrigger as-child>
|
<PopoverTrigger as-child>
|
||||||
<Button variant="outline" size="sm" class="h-8 border-dashed">
|
<Button variant="outline" size="sm" class="h-8 border-dashed">
|
||||||
<PlusCircledIcon class="mr-2 h-4 w-4" />
|
<Iconify icon="solar:traffic-economy-line-duotone" class="w-4 h-4 mr-2" />
|
||||||
{{ title }}
|
{{ title }}
|
||||||
<template v-if="selectedValues.size > 0">
|
<template v-if="selectedValues.size > 0">
|
||||||
<Separator orientation="vertical" class="mx-2 h-4" />
|
<Separator orientation="vertical" class="h-4 mx-2" />
|
||||||
<Badge
|
<Badge
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
class="rounded-sm px-1 font-normal lg:hidden"
|
class="px-1 font-normal rounded-sm lg:hidden"
|
||||||
>
|
>
|
||||||
{{ selectedValues.size }}
|
{{ selectedValues.size }}
|
||||||
</Badge>
|
</Badge>
|
||||||
|
@ -52,7 +37,7 @@ const selectedValues = computed(() => new Set(props.column?.getFilterValue() as
|
||||||
<Badge
|
<Badge
|
||||||
v-if="selectedValues.size > 2"
|
v-if="selectedValues.size > 2"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
class="rounded-sm px-1 font-normal"
|
class="px-1 font-normal rounded-sm"
|
||||||
>
|
>
|
||||||
{{ selectedValues.size }} selected
|
{{ selectedValues.size }} selected
|
||||||
</Badge>
|
</Badge>
|
||||||
|
@ -63,7 +48,7 @@ const selectedValues = computed(() => new Set(props.column?.getFilterValue() as
|
||||||
.filter((option) => selectedValues.has(option.value))"
|
.filter((option) => selectedValues.has(option.value))"
|
||||||
:key="option.value"
|
:key="option.value"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
class="rounded-sm px-1 font-normal"
|
class="px-1 font-normal rounded-sm"
|
||||||
>
|
>
|
||||||
{{ option.label }}
|
{{ option.label }}
|
||||||
</Badge>
|
</Badge>
|
||||||
|
@ -107,11 +92,11 @@ const selectedValues = computed(() => new Set(props.column?.getFilterValue() as
|
||||||
: 'opacity-50 [&_svg]:invisible',
|
: 'opacity-50 [&_svg]:invisible',
|
||||||
)"
|
)"
|
||||||
>
|
>
|
||||||
<CheckIcon :class="cn('h-4 w-4')" />
|
<Iconify icon="solar:unread-linear" :class="cn('h-4 w-4')" />
|
||||||
</div>
|
</div>
|
||||||
<component :is="option.icon" v-if="option.icon" class="mr-2 h-4 w-4 text-muted-foreground" />
|
<component :is="option.icon" v-if="option.icon" class="w-4 h-4 mr-2 text-muted-foreground" />
|
||||||
<span>{{ option.label }}</span>
|
<span>{{ option.label }}</span>
|
||||||
<span v-if="facets?.get(option.value)" class="ml-auto flex h-4 w-4 items-center justify-center font-mono text-xs">
|
<span v-if="facets?.get(option.value)" class="flex items-center justify-center w-4 h-4 ml-auto font-mono text-xs">
|
||||||
{{ facets.get(option.value) }}
|
{{ facets.get(option.value) }}
|
||||||
</span>
|
</span>
|
||||||
</CommandItem>
|
</CommandItem>
|
||||||
|
|
|
@ -1,19 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts" generic="Task extends { [key: string]: any;}">
|
||||||
import type { Table } from '@tanstack/vue-table'
|
import type { Table } from '@tanstack/vue-table'
|
||||||
import type { Task } from '../data/schema'
|
|
||||||
import ChevronLeftIcon from '~icons/radix-icons/chevron-left'
|
|
||||||
import ChevronRightIcon from '~icons/radix-icons/chevron-right'
|
|
||||||
import DoubleArrowLeftIcon from '~icons/radix-icons/double-arrow-left'
|
|
||||||
import DoubleArrowRightIcon from '~icons/radix-icons/double-arrow-right'
|
|
||||||
|
|
||||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
|
||||||
import {
|
|
||||||
Select,
|
|
||||||
SelectContent,
|
|
||||||
SelectItem,
|
|
||||||
SelectTrigger,
|
|
||||||
SelectValue,
|
|
||||||
} from '@/lib/registry/new-york/ui/select'
|
|
||||||
|
|
||||||
interface DataTablePaginationProps {
|
interface DataTablePaginationProps {
|
||||||
table: Table<Task>
|
table: Table<Task>
|
||||||
|
@ -53,39 +39,39 @@ defineProps<DataTablePaginationProps>()
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
class="hidden h-8 w-8 p-0 lg:flex"
|
class="hidden w-8 h-8 p-0 lg:flex"
|
||||||
:disabled="!table.getCanPreviousPage()"
|
:disabled="!table.getCanPreviousPage()"
|
||||||
@click="table.setPageIndex(0)"
|
@click="table.setPageIndex(0)"
|
||||||
>
|
>
|
||||||
<span class="sr-only">Go to first page</span>
|
<span class="sr-only">Go to first page</span>
|
||||||
<DoubleArrowLeftIcon class="h-4 w-4" />
|
<Iconify icon="ph:caret-double-left-light" class="w-4 h-4" />
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
class="h-8 w-8 p-0"
|
class="w-8 h-8 p-0"
|
||||||
:disabled="!table.getCanPreviousPage()"
|
:disabled="!table.getCanPreviousPage()"
|
||||||
@click="table.previousPage()"
|
@click="table.previousPage()"
|
||||||
>
|
>
|
||||||
<span class="sr-only">Go to previous page</span>
|
<span class="sr-only">Go to previous page</span>
|
||||||
<ChevronLeftIcon class="h-4 w-4" />
|
<Iconify icon="ph:caret-left" class="w-4 h-4" />
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
class="h-8 w-8 p-0"
|
class="w-8 h-8 p-0"
|
||||||
:disabled="!table.getCanNextPage()"
|
:disabled="!table.getCanNextPage()"
|
||||||
@click="table.nextPage()"
|
@click="table.nextPage()"
|
||||||
>
|
>
|
||||||
<span class="sr-only">Go to next page</span>
|
<span class="sr-only">Go to next page</span>
|
||||||
<ChevronRightIcon class="h-4 w-4" />
|
<Iconify icon="ph:caret-right" class="w-4 h-4" />
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
class="hidden h-8 w-8 p-0 lg:flex"
|
class="hidden w-8 h-8 p-0 lg:flex"
|
||||||
:disabled="!table.getCanNextPage()"
|
:disabled="!table.getCanNextPage()"
|
||||||
@click="table.setPageIndex(table.getPageCount() - 1)"
|
@click="table.setPageIndex(table.getPageCount() - 1)"
|
||||||
>
|
>
|
||||||
<span class="sr-only">Go to last page</span>
|
<span class="sr-only">Go to last page</span>
|
||||||
<DoubleArrowRightIcon class="h-4 w-4" />
|
<Iconify icon="ph:caret-double-right-light" class="w-4 h-4" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,32 +1,21 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts" generic="Task extends { [key: string]: any;}">
|
||||||
import type { Row } from '@tanstack/vue-table'
|
import type { Row } from '@tanstack/vue-table'
|
||||||
import { computed } from 'vue'
|
|
||||||
import { labels } from '../data/data'
|
|
||||||
import { taskSchema } from '../data/schema'
|
|
||||||
import type { Task } from '../data/schema'
|
|
||||||
import DotsHorizontalIcon from '~icons/radix-icons/dots-horizontal'
|
|
||||||
|
|
||||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
|
||||||
import {
|
|
||||||
DropdownMenu,
|
|
||||||
DropdownMenuContent,
|
|
||||||
DropdownMenuItem,
|
|
||||||
DropdownMenuRadioGroup,
|
|
||||||
DropdownMenuRadioItem,
|
|
||||||
DropdownMenuSeparator,
|
|
||||||
DropdownMenuShortcut,
|
|
||||||
DropdownMenuSub,
|
|
||||||
DropdownMenuSubContent,
|
|
||||||
DropdownMenuSubTrigger,
|
|
||||||
DropdownMenuTrigger,
|
|
||||||
} from '@/lib/registry/new-york/ui/dropdown-menu'
|
|
||||||
|
|
||||||
interface DataTableRowActionsProps {
|
interface DataTableRowActionsProps {
|
||||||
row: Row<Task>
|
row: Row<Task>
|
||||||
|
menus: {
|
||||||
|
label: string
|
||||||
|
divider?: boolean
|
||||||
|
icon?: string
|
||||||
|
click: (row: Row<Task>) => void
|
||||||
|
child?: {
|
||||||
|
label: string
|
||||||
|
icon?: string
|
||||||
|
click: (row: Row<Task>) => void
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
}
|
}
|
||||||
const props = defineProps<DataTableRowActionsProps>()
|
defineProps<DataTableRowActionsProps>()
|
||||||
|
|
||||||
const task = computed(() => taskSchema.parse(props.row.original))
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -36,30 +25,31 @@ const task = computed(() => taskSchema.parse(props.row.original))
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
class="flex h-8 w-8 p-0 data-[state=open]:bg-muted"
|
class="flex h-8 w-8 p-0 data-[state=open]:bg-muted"
|
||||||
>
|
>
|
||||||
<DotsHorizontalIcon class="h-4 w-4" />
|
<Iconify icon="ph:dots-three-outline-fill" class="w-4 h-4" />
|
||||||
<span class="sr-only">Open menu</span>
|
<span class="sr-only">Open menu</span>
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="end" class="w-[160px]">
|
<DropdownMenuContent align="end" class="w-[160px]">
|
||||||
<DropdownMenuItem>Edit</DropdownMenuItem>
|
<template v-for="menu in menus" :key="menu.label">
|
||||||
<DropdownMenuItem>Make a copy</DropdownMenuItem>
|
<DropdownMenuSeparator v-if="menu.divider" />
|
||||||
<DropdownMenuItem>Favorite</DropdownMenuItem>
|
<DropdownMenuSub v-else-if="(menu?.child?.length ?? 0) > 0" :label="menu.label">
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSubTrigger>{{ menu.label }}</DropdownMenuSubTrigger>
|
||||||
<DropdownMenuSub>
|
|
||||||
<DropdownMenuSubTrigger>Labels</DropdownMenuSubTrigger>
|
|
||||||
<DropdownMenuSubContent>
|
<DropdownMenuSubContent>
|
||||||
<DropdownMenuRadioGroup :value="task.label">
|
<DropdownMenuItem v-for="child in menu.child" :key="child.label" @click="child.click(row)">
|
||||||
<DropdownMenuRadioItem v-for="label in labels" :key="label.value" :value="label.value">
|
{{ child.label }}
|
||||||
{{ label.label }}
|
<DropdownMenuShortcut>
|
||||||
</DropdownMenuRadioItem>
|
<Iconify :icon="child.icon" class="size-4" />
|
||||||
</DropdownMenuRadioGroup>
|
</DropdownMenuShortcut>
|
||||||
|
</DropdownMenuItem>
|
||||||
</DropdownMenuSubContent>
|
</DropdownMenuSubContent>
|
||||||
</DropdownMenuSub>
|
</DropdownMenuSub>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuItem v-else @click="menu.click(row)">
|
||||||
<DropdownMenuItem>
|
{{ menu.label }}
|
||||||
Delete
|
<DropdownMenuShortcut>
|
||||||
<DropdownMenuShortcut>⌘⌫</DropdownMenuShortcut>
|
<Iconify :icon="menu.icon" class="size-4" />
|
||||||
|
</DropdownMenuShortcut>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
</template>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts" generic="Task extends { [key: string]: any;}">
|
||||||
import type { Table } from '@tanstack/vue-table'
|
import type { Table } from '@tanstack/vue-table'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import type { Task } from '../data/schema'
|
import Iconify from '../iconify.vue'
|
||||||
|
|
||||||
import { priorities, statuses } from '../data/data'
|
|
||||||
import DataTableFacetedFilter from './DataTableFacetedFilter.vue'
|
import DataTableFacetedFilter from './DataTableFacetedFilter.vue'
|
||||||
import DataTableViewOptions from './DataTableViewOptions.vue'
|
import DataTableViewOptions from './DataTableViewOptions.vue'
|
||||||
import Cross2Icon from '~icons/radix-icons/cross-2'
|
|
||||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
|
||||||
import { Input } from '@/lib/registry/new-york/ui/input'
|
|
||||||
|
|
||||||
interface DataTableToolbarProps {
|
interface DataTableToolbarProps {
|
||||||
table: Table<Task>
|
table: Table<Task>
|
||||||
|
filter?: {
|
||||||
|
label: string
|
||||||
|
key: keyof Task
|
||||||
|
options: {
|
||||||
|
label: string
|
||||||
|
value: string
|
||||||
|
icon?: string
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<DataTableToolbarProps>()
|
const props = defineProps<DataTableToolbarProps>()
|
||||||
|
@ -20,27 +24,29 @@ const isFiltered = computed(() => props.table.getState().columnFilters.length >
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex items-center justify-between">
|
<div>
|
||||||
<div class="flex flex-1 items-center space-x-2">
|
<div class="flex justify-center items-center w-full py-10">
|
||||||
<Input
|
<Input
|
||||||
placeholder="Filter tasks..."
|
placeholder="搜索..."
|
||||||
:model-value="(table.getColumn('title')?.getFilterValue() as string) ?? ''"
|
:model-value="table.getColumn('title')?.getFilterValue() as string"
|
||||||
class="h-8 w-[150px] lg:w-[250px]"
|
class="h-12 w-[550px]" @input="table.getColumn('title')?.setFilterValue($event.target.value)"
|
||||||
@input="table.getColumn('title')?.setFilterValue($event.target.value)"
|
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div class="flex items-center flex-1 space-x-2">
|
||||||
<DataTableFacetedFilter
|
<DataTableFacetedFilter
|
||||||
v-if="table.getColumn('status')"
|
v-for="(item, i) in filter"
|
||||||
:column="table.getColumn('status')"
|
:key="i"
|
||||||
title="Status"
|
:column="table.getColumn(item.key.toString())"
|
||||||
:options="statuses"
|
:title="item.label"
|
||||||
/>
|
:options="item.options.map(i => ({
|
||||||
<DataTableFacetedFilter
|
label: i.label,
|
||||||
v-if="table.getColumn('priority')"
|
value: i.value,
|
||||||
:column="table.getColumn('priority')"
|
icon: h(Iconify, { icon: i.icon }),
|
||||||
title="Priority"
|
}))"
|
||||||
:options="priorities"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<div>
|
||||||
<Button
|
<Button
|
||||||
v-if="isFiltered"
|
v-if="isFiltered"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
|
@ -48,9 +54,14 @@ const isFiltered = computed(() => props.table.getState().columnFilters.length >
|
||||||
@click="table.resetColumnFilters()"
|
@click="table.resetColumnFilters()"
|
||||||
>
|
>
|
||||||
Reset
|
Reset
|
||||||
<Cross2Icon class="ml-2 h-4 w-4" />
|
<Iconify icon="ph:x" class="w-4 h-4 ml-2" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-2 justify-center items-center">
|
||||||
|
<slot />
|
||||||
<DataTableViewOptions :table="table" />
|
<DataTableViewOptions :table="table" />
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,18 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts" generic="Task extends { [key: string]: any;}">
|
||||||
import type { Table } from '@tanstack/vue-table'
|
import type { Table } from '@tanstack/vue-table'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import type { Task } from '../data/schema'
|
|
||||||
import MixerHorizontalIcon from '~icons/radix-icons/mixer-horizontal'
|
|
||||||
|
|
||||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
|
||||||
import {
|
|
||||||
DropdownMenu,
|
|
||||||
DropdownMenuCheckboxItem,
|
|
||||||
DropdownMenuContent,
|
|
||||||
DropdownMenuLabel,
|
|
||||||
DropdownMenuSeparator,
|
|
||||||
DropdownMenuTrigger,
|
|
||||||
} from '@/lib/registry/new-york/ui/dropdown-menu'
|
|
||||||
|
|
||||||
interface DataTableViewOptionsProps {
|
interface DataTableViewOptionsProps {
|
||||||
table: Table<Task>
|
table: Table<Task>
|
||||||
|
@ -33,9 +21,9 @@ const columns = computed(() => props.table.getAllColumns()
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
class="ml-auto hidden h-8 lg:flex"
|
class="hidden h-8 ml-auto lg:flex"
|
||||||
>
|
>
|
||||||
<MixerHorizontalIcon class="mr-2 h-4 w-4" />
|
<Iconify icon="ph:faders-horizontal-duotone" class="w-4 h-4 mr-2" />
|
||||||
View
|
View
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
|
|
|
@ -1,26 +1,10 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {
|
|
||||||
Avatar,
|
|
||||||
AvatarFallback,
|
|
||||||
AvatarImage,
|
|
||||||
} from '@/lib/registry/new-york/ui/avatar'
|
|
||||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
|
||||||
import {
|
|
||||||
DropdownMenu,
|
|
||||||
DropdownMenuContent,
|
|
||||||
DropdownMenuGroup,
|
|
||||||
DropdownMenuItem,
|
|
||||||
DropdownMenuLabel,
|
|
||||||
DropdownMenuSeparator,
|
|
||||||
DropdownMenuShortcut,
|
|
||||||
DropdownMenuTrigger,
|
|
||||||
} from '@/lib/registry/new-york/ui/dropdown-menu'
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger as-child>
|
<DropdownMenuTrigger as-child>
|
||||||
<Button variant="ghost" class="relative h-8 w-8 rounded-full">
|
<Button variant="ghost" class="relative w-8 h-8 rounded-full">
|
||||||
<Avatar class="h-9 w-9">
|
<Avatar class="h-9 w-9">
|
||||||
<AvatarImage src="/avatars/03.png" alt="@shadcn" />
|
<AvatarImage src="/avatars/03.png" alt="@shadcn" />
|
||||||
<AvatarFallback>SC</AvatarFallback>
|
<AvatarFallback>SC</AvatarFallback>
|
||||||
|
@ -28,7 +12,7 @@ import {
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent class="w-56" align="end">
|
<DropdownMenuContent class="w-56" align="end">
|
||||||
<DropdownMenuLabel class="font-normal flex">
|
<DropdownMenuLabel class="flex font-normal">
|
||||||
<div class="flex flex-col space-y-1">
|
<div class="flex flex-col space-y-1">
|
||||||
<p class="text-sm font-medium leading-none">
|
<p class="text-sm font-medium leading-none">
|
||||||
shadcn
|
shadcn
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
const props = defineProps<{
|
||||||
|
onSubmit: (data: ZodInfer<typeof schema>) => Promise<void>
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const schema = z.object({
|
||||||
|
endPoint: z.string({
|
||||||
|
required_error: 'endpoint字段不能为空',
|
||||||
|
}),
|
||||||
|
accessKey: z.string({
|
||||||
|
required_error: 'accesskey字段不能为空',
|
||||||
|
}),
|
||||||
|
secretKey: z.string({
|
||||||
|
required_error: 'secretkey字段不能为空',
|
||||||
|
}),
|
||||||
|
port: z.number({
|
||||||
|
required_error: 'port字段不能为空',
|
||||||
|
}).optional(),
|
||||||
|
region: z.string().optional(),
|
||||||
|
useSSL: z.boolean(),
|
||||||
|
})
|
||||||
|
|
||||||
|
const formValues = {
|
||||||
|
endPoint: 'fgws3.jwanfs.ocloud.ihep.ac.cn',
|
||||||
|
accessKey: 'NsccczIb9DsAQ7RNMIkv',
|
||||||
|
secretKey: 'gBGR9UdhESQntF7wbMqB',
|
||||||
|
region: 'us-east-1',
|
||||||
|
useSSL: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
const open = ref(false)
|
||||||
|
|
||||||
|
async function onSubmit(values: ZodInfer<typeof schema>) {
|
||||||
|
open.value = false
|
||||||
|
await props.onSubmit(values)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Dialog v-model:open="open">
|
||||||
|
<DialogTrigger as-child>
|
||||||
|
<Button class="font-bold tracking-wide" size="xs">
|
||||||
|
添加资源化技术
|
||||||
|
</Button>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogScrollContent class="sm:max-w-[425px]">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>资源化技术信息</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
请填写所需要的资源化技术信息等。
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<Form class="space-y-4" :schema="schema" :initial-values="formValues" @submit="onSubmit">
|
||||||
|
<FormFieldItem v-slot="{ componentField }" label="EndPoint" name="endPoint" required>
|
||||||
|
<Input type="text" v-bind="componentField" placeholder="" />
|
||||||
|
</FormFieldItem>
|
||||||
|
<FormFieldItem v-slot="{ componentField }" label="AccessKey" name="accessKey" required>
|
||||||
|
<Input type="text" v-bind="componentField" />
|
||||||
|
</FormFieldItem>
|
||||||
|
<FormFieldItem v-slot="{ componentField }" label="SecretKey" name="secretKey" required>
|
||||||
|
<Input type="text" v-bind="componentField" />
|
||||||
|
</FormFieldItem>
|
||||||
|
<FormFieldItem v-slot="{ componentField }" label="端口" name="port">
|
||||||
|
<Input type="number" v-bind="componentField" />
|
||||||
|
</FormFieldItem>
|
||||||
|
<FormFieldItem name="useSSL">
|
||||||
|
<template #content="{ value, handleChange }">
|
||||||
|
<div class="col-span-1" />
|
||||||
|
<div class="flex col-span-3 gap-x-3">
|
||||||
|
<FormControl>
|
||||||
|
<Checkbox :checked="value" @update:checked="handleChange" />
|
||||||
|
</FormControl>
|
||||||
|
<div class="space-y-1 leading-none">
|
||||||
|
<FormLabel>useSSL</FormLabel>
|
||||||
|
<FormDescription>
|
||||||
|
是否启用安全(HTTPS)认证
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</FormFieldItem>
|
||||||
|
|
||||||
|
<DialogFooter class="mt-4">
|
||||||
|
<Button type="submit" class="font-bold tracking-wide">
|
||||||
|
保存
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</Form>
|
||||||
|
</DialogScrollContent>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
|
@ -0,0 +1,77 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
const props = defineProps<{
|
||||||
|
env: ResourceTechnologyInfo['env']
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const schema = z.object({
|
||||||
|
yieldDistance: z.number(),
|
||||||
|
area: z.number(),
|
||||||
|
terrain: z.string().min(1),
|
||||||
|
supplyWater: z.string().min(1),
|
||||||
|
supplyElectricity: z.string().min(1),
|
||||||
|
dischargeWater: z.string().min(1),
|
||||||
|
temperature: z.number(),
|
||||||
|
airPressure: z.number(),
|
||||||
|
})
|
||||||
|
|
||||||
|
const edit = ref(false)
|
||||||
|
|
||||||
|
const open = ref(false)
|
||||||
|
|
||||||
|
async function onSubmit(values: ZodInfer<typeof schema>) {
|
||||||
|
open.value = false
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Dialog v-model:open="open">
|
||||||
|
<DialogTrigger as-child>
|
||||||
|
<Button class="font-bold tracking-wide">
|
||||||
|
查看所需场地条件
|
||||||
|
</Button>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogScrollContent class="sm:max-w-[425px]">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>所需场地条件</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
通过点击编辑按钮可以编辑所需场地条件
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<Form class="space-y-4" :schema="schema" :initial-values="env" @submit="onSubmit">
|
||||||
|
<FormFieldItem v-slot="{ componentField }" label="退让距离" name="yieldDistance" required>
|
||||||
|
<Input type="text" v-bind="componentField" placeholder="" :disabled="!edit" />
|
||||||
|
</FormFieldItem>
|
||||||
|
<FormFieldItem v-slot="{ componentField }" label="占地面积" name="area" required>
|
||||||
|
<Input type="text" v-bind="componentField" :disabled="!edit" />
|
||||||
|
</FormFieldItem>
|
||||||
|
<FormFieldItem v-slot="{ componentField }" label="地形" name="terrain" required>
|
||||||
|
<Input type="text" v-bind="componentField" :disabled="!edit" />
|
||||||
|
</FormFieldItem>
|
||||||
|
<FormFieldItem v-slot="{ componentField }" label="供水要求" name="supplyWater">
|
||||||
|
<Input type="text" v-bind="componentField" :disabled="!edit" />
|
||||||
|
</FormFieldItem>
|
||||||
|
<FormFieldItem v-slot="{ componentField }" label="排水要求" name="dischargeWater" required>
|
||||||
|
<Input type="text" v-bind="componentField" :disabled="!edit" />
|
||||||
|
</FormFieldItem>
|
||||||
|
<FormFieldItem v-slot="{ componentField }" label="供电要求" name="supplyElectricity" required>
|
||||||
|
<Input type="text" v-bind="componentField" :disabled="!edit" />
|
||||||
|
</FormFieldItem>
|
||||||
|
<FormFieldItem v-slot="{ componentField }" label="温度" name="temperature" required>
|
||||||
|
<Input type="text" v-bind="componentField" :disabled="!edit" />
|
||||||
|
</FormFieldItem>
|
||||||
|
<FormFieldItem v-slot="{ componentField }" label="气压" name="airPressure" required>
|
||||||
|
<Input type="text" v-bind="componentField" :disabled="!edit" />
|
||||||
|
</FormFieldItem>
|
||||||
|
|
||||||
|
<DialogFooter class="mt-4">
|
||||||
|
<Button type="button" class="font-bold tracking-wide" @click="edit = !edit">
|
||||||
|
{{ edit ? '取消编辑' : '编辑' }}
|
||||||
|
</Button>
|
||||||
|
<Button v-if="edit" type="submit" class="font-bold tracking-wide">
|
||||||
|
保存
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</Form>
|
||||||
|
</DialogScrollContent>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
|
@ -0,0 +1,27 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
defineProps<{
|
||||||
|
resource: ResourceTechnologyInfo
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const open = ref(false)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Dialog v-model:open="open">
|
||||||
|
<DialogTrigger as-child>
|
||||||
|
<img :src="resource.craftImage" class="size-[100px]">
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogScrollContent class="sm:max-w-[600px]">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>工艺流程</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
工艺流程设计图
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
|
||||||
|
<div class="flex justify-center items-center w-full">
|
||||||
|
<img :src="resource.craftImage" class="size-[600px]">
|
||||||
|
</div>
|
||||||
|
</DialogScrollContent>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<template>
|
||||||
|
test
|
||||||
|
</template>
|
|
@ -1,12 +1,9 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const props = defineProps<{
|
import type { EChartsType } from 'echarts'
|
||||||
data: {
|
|
||||||
value: number
|
|
||||||
name: string
|
|
||||||
}[]
|
|
||||||
}>()
|
|
||||||
const mapName = 'china'
|
const mapName = 'china'
|
||||||
const colorMode = useColorMode()
|
|
||||||
|
const info = useInfoStore()
|
||||||
const option = shallowRef({
|
const option = shallowRef({
|
||||||
tooltip: {
|
tooltip: {
|
||||||
// show: false,
|
// show: false,
|
||||||
|
@ -23,50 +20,7 @@ const option = shallowRef({
|
||||||
left: '10%',
|
left: '10%',
|
||||||
},
|
},
|
||||||
geo: [
|
geo: [
|
||||||
{
|
|
||||||
map: mapName,
|
|
||||||
zlevel: -1,
|
|
||||||
zoom: 1.0,
|
|
||||||
silent: true,
|
|
||||||
layoutCenter: ['50%', '50%'],
|
|
||||||
layoutSize: '100%',
|
|
||||||
roam: false,
|
|
||||||
itemStyle: {
|
|
||||||
borderColor: 'rgba(192,245,249,.8)',
|
|
||||||
borderWidth: 3,
|
|
||||||
shadowColor: '#6FFDFF',
|
|
||||||
shadowOffsetY: 0,
|
|
||||||
shadowBlur: 10,
|
|
||||||
// areaColor: 'rgba(29,85,139,.6)',
|
|
||||||
},
|
|
||||||
regions: [
|
|
||||||
{
|
|
||||||
name: '南海诸岛',
|
|
||||||
itemStyle: {
|
|
||||||
// 隐藏地图
|
|
||||||
opacity: 0, // 为 0 时不绘制该图形
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
show: false, // 隐藏文字
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
emphasis: {
|
|
||||||
// 动态展示的样式
|
|
||||||
label: {
|
|
||||||
show: false,
|
|
||||||
color: '#fff',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
// 静态的时候展示样式
|
|
||||||
show: false, // 是否显示地图省份得名称
|
|
||||||
color: '#fff',
|
|
||||||
fontSize: 12,
|
|
||||||
fontFamily: 'Arial',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
show: true,
|
show: true,
|
||||||
map: mapName,
|
map: mapName,
|
||||||
|
@ -103,7 +57,7 @@ const option = shallowRef({
|
||||||
colorStops: [
|
colorStops: [
|
||||||
{
|
{
|
||||||
offset: 0.5,
|
offset: 0.5,
|
||||||
color: '#0D59C1', // 0% 处的颜色
|
color: '#0D59C100', // 0% 处的颜色
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
offset: 1,
|
offset: 1,
|
||||||
|
@ -130,139 +84,55 @@ const option = shallowRef({
|
||||||
areaColor: linearColor('#1cfbfe', '#3348e7'),
|
areaColor: linearColor('#1cfbfe', '#3348e7'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
type: 'map',
|
|
||||||
map: mapName,
|
|
||||||
zlevel: -2,
|
|
||||||
zoom: 1.0,
|
|
||||||
regions: [
|
|
||||||
{
|
|
||||||
name: '南海诸岛',
|
|
||||||
itemStyle: {
|
|
||||||
// 隐藏地图
|
|
||||||
opacity: 0, // 为 0 时不绘制该图形
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
show: false, // 隐藏文字
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
layoutCenter: ['50%', '51.4%'],
|
|
||||||
layoutSize: '100%',
|
|
||||||
roam: false,
|
|
||||||
silent: true,
|
|
||||||
itemStyle: {
|
|
||||||
// borderColor: "rgba(35, 161, 184,0.5)",
|
|
||||||
// shadowColor: "#193f6bcc",
|
|
||||||
// shadowOffsetY: 5,
|
|
||||||
// shadowBlur: 1,
|
|
||||||
areaColor: '#257AB2',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'map',
|
|
||||||
map: mapName,
|
|
||||||
zlevel: -3,
|
|
||||||
zoom: 1.0,
|
|
||||||
regions: [
|
|
||||||
{
|
|
||||||
name: '南海诸岛',
|
|
||||||
itemStyle: {
|
|
||||||
// 隐藏地图
|
|
||||||
opacity: 0, // 为 0 时不绘制该图形
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
show: false, // 隐藏文字
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
layoutCenter: ['50%', '52.4%'],
|
|
||||||
layoutSize: '100%',
|
|
||||||
roam: false,
|
|
||||||
silent: true,
|
|
||||||
itemStyle: {
|
|
||||||
borderColor: 'rgba(7, 65, 117,0.5)',
|
|
||||||
shadowColor: 'rgba(7, 65, 117,0.8)',
|
|
||||||
shadowOffsetY: 10,
|
|
||||||
shadowBlur: 0,
|
|
||||||
areaColor: '#0A2763',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
series: [
|
series: [
|
||||||
// {
|
{
|
||||||
// type: 'effectScatter',
|
type: 'effectScatter',
|
||||||
// coordinateSystem: 'geo',
|
coordinateSystem: 'geo',
|
||||||
// symbolSize: 4,
|
symbolSize: 4,
|
||||||
// itemStyle: {
|
itemStyle: {
|
||||||
// color: '#ffffff', // 圆点的颜色
|
color: '#ffffff', // 圆点的颜色
|
||||||
// shadowBlur: 1,
|
shadowBlur: 1,
|
||||||
// shadowColor: '#333',
|
shadowColor: '#333',
|
||||||
// },
|
},
|
||||||
// tooltip: {
|
tooltip: {
|
||||||
// trigger: 'item',
|
trigger: 'item',
|
||||||
// backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
// borderColor: 'transparent',
|
borderColor: 'transparent',
|
||||||
// extraCssText: 'z-index:100;color:#fff;',
|
extraCssText: 'z-index:100;color:#fff;',
|
||||||
// confine: true, // 是否将 tooltip 框限制在图表的区域内
|
confine: true, // 是否将 tooltip 框限制在图表的区域内
|
||||||
// formatter(params: any) {
|
|
||||||
// // 根据业务自己拓展要显示的内容
|
|
||||||
// return `<div style="box-shadow: 0 0 10px #00000083; padding: 10px; position: absolute; top: 0; left:0; border-radius: 4px; border: 1px solid #0479ff; background: linear-gradient(to bottom, #0739a7 0%,#174ba0ef 100%);z-index:1000">
|
|
||||||
// <div style='color:#ee9803; font-size: 18px;'><b>${
|
|
||||||
// params.data.Province
|
|
||||||
// }-${params.data.City}</b></div>
|
|
||||||
|
|
||||||
// ${
|
formatter(params: any) {
|
||||||
// params.data.DataCenterList.length
|
console.log(params)
|
||||||
// ? '<div style=\'color:#eeae40; font-size: 14px;\'><b>数据中心</b></div>'
|
// 根据业务自己拓展要显示的内容
|
||||||
// : ''
|
return `<div style="box-shadow: 0 0 10px #00000083; padding: 10px; position: absolute; top: 0; left:0; border-radius: 4px; border: 1px solid #0479ff; background: linear-gradient(to bottom, #0739a7 0%,#174ba0ef 100%);z-index:1000">
|
||||||
// }
|
<div style='color:#ee9803; font-size: 18px;'><b>TEST</b></div>
|
||||||
|
</div>`
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
// ${params.data.DataCenterList.map((i: any) => {
|
label: {
|
||||||
// return `
|
show: true,
|
||||||
// <div style="display: flex; align-items: center;padding-top: 6px;">
|
color: '#fff',
|
||||||
// <div style="height: 6px; width: 6px; border-radius: 50%; background:#F4BD59; margin-right: 10px;"></div> <span style='color:#fff;font-size: 13px;margin-right: 20px;'>${i.DataCenterName}</span>
|
position: [10, 10],
|
||||||
// </div>
|
textShadowColor: 'black',
|
||||||
// `
|
textShadowBlur: 4,
|
||||||
// }).join('')}
|
formatter(obj: any) {
|
||||||
|
return obj.name
|
||||||
// ${
|
},
|
||||||
// params.data.CdnList.length
|
},
|
||||||
// ? '<div style=\'color:#eeae40; font-size: 14px;\'><b>CDN</b></div>'
|
zlevel: 12,
|
||||||
// : ''
|
data: info.data.map(i => ({
|
||||||
// }
|
name: i.name,
|
||||||
|
value: i.value,
|
||||||
// ${params.data.CdnList.map((i: any) => {
|
})),
|
||||||
// return `
|
},
|
||||||
// <div style="display: flex; align-items: center;padding-top: 6px;">
|
{
|
||||||
// <div style="height: 6px; width: 6px; border-radius: 50%; background:#F4BD59; margin-right: 10px;"></div> <span style='color:#fff;font-size: 13px;margin-right: 20px;'>${i.CdnName}</span>
|
type: 'effectScatter',
|
||||||
// </div>
|
coordinateSystem: 'geo',
|
||||||
// `
|
rippleEffect: {
|
||||||
// }).join('')}
|
brushType: 'fill',
|
||||||
|
},
|
||||||
// </div>`
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
|
|
||||||
// label: {
|
|
||||||
// show: true,
|
|
||||||
// color: '#fff',
|
|
||||||
// position: [10, 10],
|
|
||||||
// textShadowColor: 'black',
|
|
||||||
// textShadowBlur: 4,
|
|
||||||
// formatter(obj: any) {
|
|
||||||
// return obj.name
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// zlevel: 12,
|
|
||||||
// data: [...map.values()],
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// type: 'effectScatter',
|
|
||||||
// coordinateSystem: 'geo',
|
|
||||||
// rippleEffect: {
|
|
||||||
// brushType: 'fill',
|
|
||||||
// },
|
|
||||||
// symbolSize(val: any) {
|
// symbolSize(val: any) {
|
||||||
// const value = val[2]
|
// const value = val[2]
|
||||||
// if (value < max)
|
// if (value < max)
|
||||||
|
@ -270,15 +140,18 @@ const option = shallowRef({
|
||||||
|
|
||||||
// return 20
|
// return 20
|
||||||
// },
|
// },
|
||||||
// showEffectOn: 'render', // 加载完毕显示特效
|
showEffectOn: 'render', // 加载完毕显示特效
|
||||||
// itemStyle: {
|
itemStyle: {
|
||||||
// color: '#FEBE13', // 圆点的颜色
|
color: '#FEBE13', // 圆点的颜色
|
||||||
// shadowBlur: 10,
|
shadowBlur: 10,
|
||||||
// shadowColor: '#333',
|
shadowColor: '#333',
|
||||||
// },
|
},
|
||||||
// zlevel: 6,
|
zlevel: 6,
|
||||||
// data: [...map.values()].filter(i => !!i.CdnList.length),
|
data: info.data.map(i => ({
|
||||||
// },
|
name: i.name,
|
||||||
|
value: i.value,
|
||||||
|
})),
|
||||||
|
},
|
||||||
// {
|
// {
|
||||||
// type: 'custom',
|
// type: 'custom',
|
||||||
// geoIndex: 0,
|
// geoIndex: 0,
|
||||||
|
@ -310,12 +183,55 @@ const option = shallowRef({
|
||||||
// },
|
// },
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const china = ref<{
|
||||||
|
chart: EChartsType
|
||||||
|
chartEle: HTMLDivElement
|
||||||
|
}>()
|
||||||
|
|
||||||
|
let timer: any
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
console.log(info.data[1].name)
|
||||||
|
const datalen = info.data.length
|
||||||
|
let count = 0
|
||||||
|
timer && clearInterval(timer)
|
||||||
|
timer = setInterval(() => {
|
||||||
|
console.log(china.value?.chart)
|
||||||
|
|
||||||
|
china.value?.chart.dispatchAction({
|
||||||
|
type: 'downplay',
|
||||||
|
})
|
||||||
|
|
||||||
|
china.value?.chart.dispatchAction({
|
||||||
|
type: 'highlight',
|
||||||
|
dataIndex: count,
|
||||||
|
})
|
||||||
|
|
||||||
|
china.value?.chart.dispatchAction({
|
||||||
|
type: 'showTip',
|
||||||
|
dataIndex: count,
|
||||||
|
})
|
||||||
|
|
||||||
|
count++
|
||||||
|
count = count % datalen
|
||||||
|
info.setShow(count)
|
||||||
|
}, 3000)
|
||||||
|
})
|
||||||
|
|
||||||
|
onDeactivated(() => {
|
||||||
|
clearInterval(timer)
|
||||||
|
})
|
||||||
|
|
||||||
|
effect(() => {
|
||||||
|
console.log(china.value?.chart)
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ClientOnly fallback-tag="div" fallback="Loading comments...">
|
<ClientOnly fallback-tag="div" fallback="Loading comments...">
|
||||||
<Chart
|
<Chart
|
||||||
class="chart" :options="option"
|
ref="china" class="chart" :options="option"
|
||||||
/>
|
/>
|
||||||
</ClientOnly>
|
</ClientOnly>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,96 +1,14 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const invoices = [
|
const info = useInfoStore()
|
||||||
{
|
const data = computed(() => {
|
||||||
invoice: 'INV001',
|
return info.data[info.showIndex]
|
||||||
paymentStatus: 'Paid',
|
})
|
||||||
totalAmount: '$250.00',
|
|
||||||
paymentMethod: 'Credit Card',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
invoice: 'INV002',
|
|
||||||
paymentStatus: 'Pending',
|
|
||||||
totalAmount: '$150.00',
|
|
||||||
paymentMethod: 'PayPal',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
invoice: 'INV003',
|
|
||||||
paymentStatus: 'Unpaid',
|
|
||||||
totalAmount: '$350.00',
|
|
||||||
paymentMethod: 'Bank Transfer',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
invoice: 'INV004',
|
|
||||||
paymentStatus: 'Paid',
|
|
||||||
totalAmount: '$450.00',
|
|
||||||
paymentMethod: 'Credit Card',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
invoice: 'INV005',
|
|
||||||
paymentStatus: 'Paid',
|
|
||||||
totalAmount: '$550.00',
|
|
||||||
paymentMethod: 'PayPal',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
invoice: 'INV006',
|
|
||||||
paymentStatus: 'Pending',
|
|
||||||
totalAmount: '$200.00',
|
|
||||||
paymentMethod: 'Bank Transfer',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
invoice: 'INV007',
|
|
||||||
paymentStatus: 'Unpaid',
|
|
||||||
totalAmount: '$300.00',
|
|
||||||
paymentMethod: 'Credit Card',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FrameV1 title="重点区域监控">
|
<FrameV1 title="重点区域监控">
|
||||||
<div class="flex justify-around">
|
<div class="flex justify-around gap-4 pt-5">
|
||||||
<FrameImg src="/social-card.png" title="测试测试士大夫" icon="solar:adhesive-plaster-line-duotone" class="h-[90px]" />
|
<FrameImg v-for="item in data.info.monitor" :key="item.name" src="/social-card.png" :title="item.name" icon="solar:adhesive-plaster-line-duotone" class="h-[120px]" />
|
||||||
<FrameImg src="/social-card.png" title="测试测试士大夫" icon="solar:adhesive-plaster-line-duotone" class="h-[90px]" />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Table class="mt-6">
|
|
||||||
<TableHeader class=" bg-white/5">
|
|
||||||
<TableRow>
|
|
||||||
<TableHead class="w-[100px] h-8">
|
|
||||||
Invoice
|
|
||||||
</TableHead>
|
|
||||||
<TableHead class="h-8 ">
|
|
||||||
Status
|
|
||||||
</TableHead>
|
|
||||||
<TableHead class="h-8 ">
|
|
||||||
Method
|
|
||||||
</TableHead>
|
|
||||||
<TableHead class="h-8 text-right">
|
|
||||||
Amount
|
|
||||||
</TableHead>
|
|
||||||
</TableRow>
|
|
||||||
</TableHeader>
|
|
||||||
<TableBody>
|
|
||||||
<TableRow>
|
|
||||||
<TableCell class="font-medium">
|
|
||||||
INV001
|
|
||||||
</TableCell>
|
|
||||||
<TableCell>Paid</TableCell>
|
|
||||||
<TableCell>Credit Card</TableCell>
|
|
||||||
<TableCell class="text-right">
|
|
||||||
$250.00
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
<TableRow class="bg-red-500/20 hover:bg-red-500/25">
|
|
||||||
<TableCell class="font-medium">
|
|
||||||
INV001
|
|
||||||
</TableCell>
|
|
||||||
<TableCell>Paid</TableCell>
|
|
||||||
<TableCell>Credit Card</TableCell>
|
|
||||||
<TableCell class="text-right">
|
|
||||||
$250.00
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
</FrameV1>
|
</FrameV1>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,52 +1,71 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const list = [{
|
const info = useInfoStore()
|
||||||
name: '园区名称',
|
|
||||||
value: 'xx科技园',
|
|
||||||
}, {
|
|
||||||
name: '简称年份',
|
|
||||||
value: '2021年',
|
|
||||||
}, {
|
|
||||||
name: '物业公司',
|
|
||||||
value: 'xx物业公司',
|
|
||||||
}, {
|
|
||||||
name: '建筑面积',
|
|
||||||
value: '10000平方米',
|
|
||||||
}, {
|
|
||||||
name: '占地面积',
|
|
||||||
value: '10000平方米',
|
|
||||||
}, {
|
|
||||||
name: '容积率',
|
|
||||||
value: '10000',
|
|
||||||
}]
|
|
||||||
|
|
||||||
const digitals = [
|
const data = computed(() => {
|
||||||
|
return info.data[info.showIndex]
|
||||||
|
})
|
||||||
|
|
||||||
|
const list = computed(() => {
|
||||||
|
return [{
|
||||||
|
name: '地区名称',
|
||||||
|
value: data.value.name,
|
||||||
|
}, {
|
||||||
|
name: '经纬度',
|
||||||
|
value: data.value.value.join(','),
|
||||||
|
}, {
|
||||||
|
name: '收集年份',
|
||||||
|
value: `${data.value.info.collect_year}年`,
|
||||||
|
}, {
|
||||||
|
name: '经济面积',
|
||||||
|
value: `${data.value.info.economic.area}平方米`,
|
||||||
|
}, {
|
||||||
|
name: '人口总数',
|
||||||
|
value: data.value.info.economic.population,
|
||||||
|
}, {
|
||||||
|
name: '人均收入',
|
||||||
|
value: `${data.value.info.economic.revenue}元/年`,
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
|
||||||
|
const digitals = computed(() => {
|
||||||
|
return [
|
||||||
{
|
{
|
||||||
title: '总面积(m2)',
|
title: '气温(℃)',
|
||||||
value: 87512,
|
value: data.value.info.climate.temperature,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '楼栋数量',
|
title: '降水量(cc)',
|
||||||
value: 1000,
|
value: data.value.info.climate.precipitation,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '办公人数',
|
title: '日照时长(小时)',
|
||||||
value: 1000,
|
value: data.value.info.climate.sunshine,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '总入住企业',
|
title: '土壤种类',
|
||||||
value: 1000,
|
value: data.value.info.soil.length,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '入住率',
|
title: '产业',
|
||||||
value: 1000,
|
value: data.value.info.industry.length,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '总人数',
|
title: '资源化技术',
|
||||||
value: 1000,
|
value: data.value.info.garbage_feature.data.length,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
})
|
||||||
|
|
||||||
const digitalsV2 = [
|
const digitalsV2 = computed(() => {
|
||||||
|
return data.value.info.garbage_feature.data.map(i => ({
|
||||||
|
title: i.type,
|
||||||
|
value: i.details.length,
|
||||||
|
unit: '项',
|
||||||
|
icon: i.icon,
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
|
||||||
|
const i = [
|
||||||
{
|
{
|
||||||
title: '公寓',
|
title: '公寓',
|
||||||
value: 123,
|
value: 123,
|
||||||
|
@ -71,23 +90,11 @@ const digitalsV2 = [
|
||||||
unit: '加',
|
unit: '加',
|
||||||
icon: 'solar:airbuds-remove-line-duotone',
|
icon: 'solar:airbuds-remove-line-duotone',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: '餐厅',
|
|
||||||
value: 123,
|
|
||||||
unit: '加',
|
|
||||||
icon: 'solar:airbuds-remove-line-duotone',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '休想学',
|
|
||||||
value: 123,
|
|
||||||
unit: '加',
|
|
||||||
icon: 'solar:airbuds-remove-line-duotone',
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FrameV1 title="园区简介">
|
<FrameV1 title="地区简介">
|
||||||
<div class="">
|
<div class="">
|
||||||
<div class="grid grid-cols-2 gap-1 px-6">
|
<div class="grid grid-cols-2 gap-1 px-6">
|
||||||
<div v-for="(item, index) in list" :key="index" class="grid grid-cols-5 ">
|
<div v-for="(item, index) in list" :key="index" class="grid grid-cols-5 ">
|
||||||
|
@ -104,7 +111,7 @@ const digitalsV2 = [
|
||||||
<DigitalV1 v-for="(item, index) in digitals" :key="index" v-bind="item" />
|
<DigitalV1 v-for="(item, index) in digitals" :key="index" v-bind="item" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center justify-center mt-6 mb-4">
|
<div class="flex items-center justify-center mt-6 mb-4">
|
||||||
<TitleV1 title="园区环境" />
|
<TitleV1 title="地区废弃物特征库" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const items = [{
|
const items = [{
|
||||||
title: '人员统计',
|
title: '土壤统计',
|
||||||
value: 'people',
|
value: 'soil',
|
||||||
}, {
|
}, {
|
||||||
title: '设备统计',
|
title: '产业统计',
|
||||||
value: 'equipment',
|
value: 'industry',
|
||||||
}, {
|
|
||||||
title: '能耗统计',
|
|
||||||
value: 'energy',
|
|
||||||
}]
|
}]
|
||||||
|
const info = useInfoStore()
|
||||||
|
const data = computed(() => {
|
||||||
|
return info.data[info.showIndex]
|
||||||
|
})
|
||||||
|
|
||||||
const selected = ref(0)
|
const selected = ref(0)
|
||||||
|
|
||||||
|
@ -16,33 +17,110 @@ function change(value: number) {
|
||||||
selected.value = value
|
selected.value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
const digital = [
|
const count = computed(() => {
|
||||||
{
|
return selected ? data.value.info.industry.length : data.value.info.soil.length
|
||||||
title: '员工',
|
})
|
||||||
value: 245,
|
|
||||||
|
const value = computed(() => {
|
||||||
|
if (selected.value === 0) {
|
||||||
|
return {
|
||||||
|
count: data.value.info.soil.length,
|
||||||
|
unit: '种',
|
||||||
icon: 'solar:adhesive-plaster-line-duotone',
|
icon: 'solar:adhesive-plaster-line-duotone',
|
||||||
|
title: '区域内现土壤总计',
|
||||||
|
details: [{
|
||||||
|
title: '养分特征数量',
|
||||||
|
value: data.value.info.soil.reduce((a, b) => { return a + b.nutrient.length }, 0),
|
||||||
|
icon: 'solar:atom-bold-duotone',
|
||||||
|
}, {
|
||||||
|
title: '土壤环境数量',
|
||||||
|
value: data.value.info.soil.reduce((a, b) => { return a + b.env.length }, 0),
|
||||||
|
icon: 'solar:bacteria-bold-duotone',
|
||||||
|
}, {
|
||||||
|
title: '微生物数量共计',
|
||||||
|
value: data.value.info.soil.reduce((a, b) => { return a + b.microorganism_count }, 0),
|
||||||
|
icon: 'solar:bug-bold-duotone',
|
||||||
|
}],
|
||||||
|
table: {
|
||||||
|
columns: [{
|
||||||
|
title: '类型',
|
||||||
|
key: 'type',
|
||||||
|
}, {
|
||||||
|
title: '土壤养分特征',
|
||||||
|
key: 'nutrient',
|
||||||
|
}, {
|
||||||
|
title: '土壤环境',
|
||||||
|
key: 'env',
|
||||||
|
}, {
|
||||||
|
title: '微生物数量',
|
||||||
|
key: 'microorganism_count',
|
||||||
|
}],
|
||||||
|
list: data.value.info.soil,
|
||||||
},
|
},
|
||||||
{
|
}
|
||||||
title: '安保',
|
}
|
||||||
value: 245,
|
else {
|
||||||
icon: 'solar:adhesive-plaster-line-duotone',
|
return {
|
||||||
|
count: data.value.info.industry.length,
|
||||||
|
unit: '个',
|
||||||
|
icon: 'solar:buildings-broken',
|
||||||
|
title: '区域内现产业总计',
|
||||||
|
details: [{
|
||||||
|
title: '农作物共计',
|
||||||
|
value: data.value.info.industry.reduce((a, b) => { return a + b.crop.length }, 0),
|
||||||
|
icon: 'solar:floor-lamp-bold-duotone',
|
||||||
|
}, {
|
||||||
|
title: '畜产品共计',
|
||||||
|
value: data.value.info.industry.reduce((a, b) => { return a + b.livestock.length }, 0),
|
||||||
|
icon: 'solar:dumbbells-bold-duotone',
|
||||||
|
}, {
|
||||||
|
title: '产业结构共计',
|
||||||
|
value: new Set(data.value.info.industry.map(i => i.construction)).size,
|
||||||
|
icon: 'solar:buildings-bold-duotone',
|
||||||
|
}],
|
||||||
|
table: {
|
||||||
|
columns: [{
|
||||||
|
title: '名称',
|
||||||
|
key: 'name',
|
||||||
|
}, {
|
||||||
|
title: '产业结构',
|
||||||
|
key: 'construction',
|
||||||
|
}, {
|
||||||
|
title: '高值化需求',
|
||||||
|
key: 'premium_requirement',
|
||||||
|
}],
|
||||||
|
list: data.value.info.industry,
|
||||||
},
|
},
|
||||||
{
|
}
|
||||||
title: '访客',
|
}
|
||||||
value: 245,
|
})
|
||||||
icon: 'solar:adhesive-plaster-line-duotone',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FrameV1 title="人测统计">
|
<FrameV1 title="概况统计">
|
||||||
<div class="space-y-4 ">
|
<div class="space-y-6 ">
|
||||||
<TabsV2 v-model:model-value="selected" :items="items" :selected="selected" :change="change" />
|
<TabsV2 v-model:model-value="selected" :items="items" :selected="selected" :change="change" />
|
||||||
<DigitalV4 title="园区现有总人数" :value="4555" unit="人" icon="solar:adhesive-plaster-line-duotone" />
|
<DigitalV4 :title="value.title" :value="value.count" :unit="value.unit" :icon="value.icon" />
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<DigitalV5 v-for="item in digital" :key="item.title" v-bind="item" />
|
<DigitalV5 v-for="item in value.details" :key="item.title" v-bind="item" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<Table class="mt-6">
|
||||||
|
<TableHeader class=" bg-white/5">
|
||||||
|
<TableRow>
|
||||||
|
<TableHead v-for="(item, i) in value.table?.columns" :key="item.key" class="h-8" :class="{ 'text-right': i === value.table.columns.length - 1 }">
|
||||||
|
{{ item.title }}
|
||||||
|
</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
<TableRow v-for="item in value.table?.list" :key="item.type">
|
||||||
|
<TableCell v-for="(col, i) in value.table?.columns" :key="col.key" class="text-lg font-medium" :class="{ 'text-right': i === value.table.columns.length - 1 }">
|
||||||
|
{{ Array.isArray(item[col.key]) ? item[col.key].join(', ') : item[col.key] }}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
</FrameV1>
|
</FrameV1>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const useFileStore = defineStore('files', {
|
|
||||||
state: (): {
|
|
||||||
pendings: {
|
|
||||||
path: string
|
|
||||||
file: File
|
|
||||||
}[],
|
|
||||||
success: {
|
|
||||||
path: string
|
|
||||||
file: File
|
|
||||||
}[],
|
|
||||||
error: {
|
|
||||||
path: string
|
|
||||||
file: File
|
|
||||||
}[],
|
|
||||||
uploading: {
|
|
||||||
path: string
|
|
||||||
file: File
|
|
||||||
}[]
|
|
||||||
isFilesSiderOpen: Ref<boolean>
|
|
||||||
} => ({
|
|
||||||
pendings: [],
|
|
||||||
success: [],
|
|
||||||
error: [],
|
|
||||||
uploading: [],
|
|
||||||
isFilesSiderOpen: ref(false)
|
|
||||||
}),
|
|
||||||
actions: {
|
|
||||||
pendingFiles(files: File[], path: string) {
|
|
||||||
files.forEach(f => {
|
|
||||||
this.pendings.push({ file: f, path })
|
|
||||||
})
|
|
||||||
},
|
|
||||||
removePendingFile(file: File) {
|
|
||||||
const index = this.pendings.findIndex(f => f.file.name === file.name)
|
|
||||||
if (index !== -1) {
|
|
||||||
this.pendings.splice(index, 1)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
removeUploadingFile(file: File) {
|
|
||||||
const index = this.uploading.findIndex(f => f.file.name === file.name)
|
|
||||||
if (index !== -1) {
|
|
||||||
this.uploading.splice(index, 1)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
uploadFileSuccess(file: File, path: string) {
|
|
||||||
this.removeUploadingFile(file)
|
|
||||||
this.success.push({ file, path })
|
|
||||||
},
|
|
||||||
uploadFileError(file: File, path: string) {
|
|
||||||
this.removeUploadingFile(file)
|
|
||||||
this.error.push({ file, path })
|
|
||||||
},
|
|
||||||
uploadFile(): { file: File, path: string } | undefined {
|
|
||||||
const f = this.pendings.shift()
|
|
||||||
f && this.uploading.push(f)
|
|
||||||
return f
|
|
||||||
},
|
|
||||||
recoverErrorFile(file: File, path: string) {
|
|
||||||
const index = this.error.findIndex(f => f.file.name === file.name)
|
|
||||||
if (index !== -1) {
|
|
||||||
this.error.splice(index, 1)
|
|
||||||
}
|
|
||||||
this.pendings.push({ file, path })
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// persist: {
|
|
||||||
// storage: persistedState.sessionStorage
|
|
||||||
// }
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
if (import.meta.hot)
|
|
||||||
// @ts-ignore
|
|
||||||
import.meta.hot.accept(acceptHMRUpdate(useUserStore, import.meta.hot))
|
|
|
@ -0,0 +1,338 @@
|
||||||
|
export const useInfoStore = defineStore('info', {
|
||||||
|
state: (): {
|
||||||
|
data: {
|
||||||
|
name: string
|
||||||
|
value: number[]
|
||||||
|
info: {
|
||||||
|
city: string
|
||||||
|
collect_year: number
|
||||||
|
economic: {
|
||||||
|
area: number
|
||||||
|
population: number
|
||||||
|
revenue: number
|
||||||
|
}
|
||||||
|
climate: {
|
||||||
|
temperature: number
|
||||||
|
precipitation: number
|
||||||
|
sunshine: number
|
||||||
|
}
|
||||||
|
monitor: {
|
||||||
|
name: string
|
||||||
|
value: number[]
|
||||||
|
link: string
|
||||||
|
}[]
|
||||||
|
soil: {
|
||||||
|
type: string
|
||||||
|
nutrient: string[]
|
||||||
|
env: string[]
|
||||||
|
organic_carbon: boolean
|
||||||
|
microorganism_count: number
|
||||||
|
gene: string
|
||||||
|
}[]
|
||||||
|
industry: {
|
||||||
|
name: string
|
||||||
|
value: number[]
|
||||||
|
construction: string
|
||||||
|
premium_requirement: string
|
||||||
|
crop: {
|
||||||
|
name: string
|
||||||
|
type: string
|
||||||
|
area: number
|
||||||
|
yield: number
|
||||||
|
}[]
|
||||||
|
livestock: {
|
||||||
|
type: string
|
||||||
|
name: string
|
||||||
|
count: number
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
|
garbage_feature: {
|
||||||
|
collect_year: number
|
||||||
|
data: {
|
||||||
|
type: string
|
||||||
|
icon: string
|
||||||
|
details: {
|
||||||
|
type: string
|
||||||
|
count: number
|
||||||
|
quotient: {
|
||||||
|
water: number
|
||||||
|
organic_material: number
|
||||||
|
carbon: number
|
||||||
|
nitrogen: number
|
||||||
|
kalium: number
|
||||||
|
heavy_metal: number
|
||||||
|
}
|
||||||
|
physical: {
|
||||||
|
unit_weight: number
|
||||||
|
porosity: number
|
||||||
|
pHvalue: number
|
||||||
|
}
|
||||||
|
biochemical: string
|
||||||
|
energy: string
|
||||||
|
dispose_way: string
|
||||||
|
}[]
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}[]
|
||||||
|
showIndex: number
|
||||||
|
} => ({
|
||||||
|
showIndex: 0,
|
||||||
|
data: [{
|
||||||
|
name: '北京',
|
||||||
|
value: [...geoCoordMap['北京']],
|
||||||
|
info: {
|
||||||
|
city: '北京',
|
||||||
|
collect_year: 2024,
|
||||||
|
monitor: [{
|
||||||
|
name: 'xx检测站',
|
||||||
|
value: [222, 222],
|
||||||
|
link: 'http://www.baidu.com',
|
||||||
|
}, {
|
||||||
|
name: 'yy检测站',
|
||||||
|
value: [222, 222],
|
||||||
|
link: 'http://www.baidu.com',
|
||||||
|
}],
|
||||||
|
economic: {
|
||||||
|
area: 1000,
|
||||||
|
population: 1000,
|
||||||
|
revenue: 2000,
|
||||||
|
},
|
||||||
|
climate: {
|
||||||
|
temperature: 26,
|
||||||
|
precipitation: 400,
|
||||||
|
sunshine: 4050,
|
||||||
|
},
|
||||||
|
soil: [{
|
||||||
|
type: 'xx土壤',
|
||||||
|
nutrient: ['xx', 'yy', 'zz'],
|
||||||
|
env: ['丘陵'],
|
||||||
|
organic_carbon: false,
|
||||||
|
microorganism_count: 10000,
|
||||||
|
gene: '未知',
|
||||||
|
}, {
|
||||||
|
type: 'yy土壤',
|
||||||
|
nutrient: ['xx', 'yy', 'zz'],
|
||||||
|
env: ['盆地'],
|
||||||
|
organic_carbon: true,
|
||||||
|
microorganism_count: 2000,
|
||||||
|
gene: '未知',
|
||||||
|
}],
|
||||||
|
industry: [{
|
||||||
|
name: 'xx企业',
|
||||||
|
value: [222, 222],
|
||||||
|
construction: '产业结构',
|
||||||
|
premium_requirement: '什么什么什么什么什么什么什么什么什么',
|
||||||
|
crop: [{
|
||||||
|
name: 'test',
|
||||||
|
type: 'test',
|
||||||
|
area: 1000,
|
||||||
|
yield: 120000990,
|
||||||
|
}],
|
||||||
|
livestock: [{
|
||||||
|
type: 'test2',
|
||||||
|
name: 'test2',
|
||||||
|
count: 123123451,
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
garbage_feature: {
|
||||||
|
collect_year: 2012,
|
||||||
|
data: [{
|
||||||
|
type: '厨余垃圾',
|
||||||
|
icon: 'solar:airbuds-remove-line-duotone',
|
||||||
|
details: [{
|
||||||
|
type: '香蕉皮',
|
||||||
|
count: 12312312,
|
||||||
|
quotient: {
|
||||||
|
water: 12,
|
||||||
|
organic_material: 23,
|
||||||
|
carbon: 35,
|
||||||
|
nitrogen: 21,
|
||||||
|
kalium: 1,
|
||||||
|
heavy_metal: 23,
|
||||||
|
},
|
||||||
|
physical: {
|
||||||
|
unit_weight: 12,
|
||||||
|
porosity: 23,
|
||||||
|
pHvalue: 213,
|
||||||
|
},
|
||||||
|
biochemical: '什么什么升华特性',
|
||||||
|
energy: '什么什么能量特征',
|
||||||
|
dispose_way: '怎么怎么怎么怎么怎么去处理',
|
||||||
|
}, {
|
||||||
|
type: '西瓜皮',
|
||||||
|
count: 12312,
|
||||||
|
quotient: {
|
||||||
|
water: 2,
|
||||||
|
organic_material: 3,
|
||||||
|
carbon: 32,
|
||||||
|
nitrogen: 41,
|
||||||
|
kalium: 12,
|
||||||
|
heavy_metal: 3,
|
||||||
|
},
|
||||||
|
physical: {
|
||||||
|
unit_weight: 1,
|
||||||
|
porosity: 3,
|
||||||
|
pHvalue: 23,
|
||||||
|
},
|
||||||
|
biochemical: '什么什么升华特性',
|
||||||
|
energy: '什么什么能量特征',
|
||||||
|
dispose_way: '怎么怎么怎么怎么怎么去处理',
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
type: '非集约化禽畜粪便',
|
||||||
|
icon: 'solar:airbuds-right-line-duotone',
|
||||||
|
details: [],
|
||||||
|
}, {
|
||||||
|
type: '田园尾菜桔秆',
|
||||||
|
icon: 'solar:airbuds-case-open-line-duotone',
|
||||||
|
details: [],
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
name: '成都',
|
||||||
|
value: [...geoCoordMap['成都']],
|
||||||
|
info: {
|
||||||
|
city: '成都',
|
||||||
|
collect_year: 2024,
|
||||||
|
economic: {
|
||||||
|
area: 200,
|
||||||
|
population: 400,
|
||||||
|
revenue: 2450,
|
||||||
|
},
|
||||||
|
climate: {
|
||||||
|
temperature: 24,
|
||||||
|
precipitation: 700,
|
||||||
|
sunshine: 3050,
|
||||||
|
},
|
||||||
|
monitor: [{
|
||||||
|
name: '成都xx检测站',
|
||||||
|
value: [222, 222],
|
||||||
|
link: 'http://www.baidu.com',
|
||||||
|
}, {
|
||||||
|
name: '吃的yy检测站',
|
||||||
|
value: [222, 222],
|
||||||
|
link: 'http://www.baidu.com',
|
||||||
|
}],
|
||||||
|
soil: [{
|
||||||
|
type: 'aa土壤',
|
||||||
|
nutrient: ['aa', 'yy', 'zz', 'sdf'],
|
||||||
|
env: ['丘陵'],
|
||||||
|
organic_carbon: false,
|
||||||
|
microorganism_count: 1000,
|
||||||
|
gene: '未知',
|
||||||
|
}, {
|
||||||
|
type: 'bb土壤',
|
||||||
|
nutrient: ['xa', 'dy', 'gz'],
|
||||||
|
env: ['盆地', '平原'],
|
||||||
|
organic_carbon: true,
|
||||||
|
microorganism_count: 2000,
|
||||||
|
gene: '未知',
|
||||||
|
}],
|
||||||
|
industry: [{
|
||||||
|
name: 'yy企业',
|
||||||
|
value: [100, 100],
|
||||||
|
construction: '产业结构',
|
||||||
|
premium_requirement: '什么什么什么什么什么什么什么什么什么',
|
||||||
|
crop: [{
|
||||||
|
name: 'test',
|
||||||
|
type: 'test',
|
||||||
|
area: 1000,
|
||||||
|
yield: 120000990,
|
||||||
|
}],
|
||||||
|
livestock: [{
|
||||||
|
type: 'test2',
|
||||||
|
name: 'test2',
|
||||||
|
count: 123123451,
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
garbage_feature: {
|
||||||
|
collect_year: 2012,
|
||||||
|
data: [{
|
||||||
|
type: '厨余垃圾',
|
||||||
|
icon: 'solar:airbuds-remove-line-duotone',
|
||||||
|
details: [{
|
||||||
|
type: '香蕉皮',
|
||||||
|
count: 12312312,
|
||||||
|
quotient: {
|
||||||
|
water: 12,
|
||||||
|
organic_material: 23,
|
||||||
|
carbon: 35,
|
||||||
|
nitrogen: 21,
|
||||||
|
kalium: 1,
|
||||||
|
heavy_metal: 23,
|
||||||
|
},
|
||||||
|
physical: {
|
||||||
|
unit_weight: 12,
|
||||||
|
porosity: 23,
|
||||||
|
pHvalue: 213,
|
||||||
|
},
|
||||||
|
biochemical: '什么什么升华特性',
|
||||||
|
energy: '什么什么能量特征',
|
||||||
|
dispose_way: '怎么怎么怎么怎么怎么去处理',
|
||||||
|
}, {
|
||||||
|
type: '西瓜皮',
|
||||||
|
count: 12312,
|
||||||
|
quotient: {
|
||||||
|
water: 2,
|
||||||
|
organic_material: 3,
|
||||||
|
carbon: 32,
|
||||||
|
nitrogen: 41,
|
||||||
|
kalium: 12,
|
||||||
|
heavy_metal: 3,
|
||||||
|
},
|
||||||
|
physical: {
|
||||||
|
unit_weight: 1,
|
||||||
|
porosity: 3,
|
||||||
|
pHvalue: 23,
|
||||||
|
},
|
||||||
|
biochemical: '什么什么升华特性',
|
||||||
|
energy: '什么什么能量特征',
|
||||||
|
dispose_way: '怎么怎么怎么怎么怎么去处理',
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
type: '非集约化禽畜粪便',
|
||||||
|
icon: 'solar:airbuds-right-line-duotone',
|
||||||
|
details: [{
|
||||||
|
type: '猪粪',
|
||||||
|
count: 12312,
|
||||||
|
quotient: {
|
||||||
|
water: 2,
|
||||||
|
organic_material: 3,
|
||||||
|
carbon: 3,
|
||||||
|
nitrogen: 21,
|
||||||
|
kalium: 12,
|
||||||
|
heavy_metal: 3,
|
||||||
|
},
|
||||||
|
physical: {
|
||||||
|
unit_weight: 122,
|
||||||
|
porosity: 2,
|
||||||
|
pHvalue: 2123,
|
||||||
|
},
|
||||||
|
biochemical: '什么什么升华特性',
|
||||||
|
energy: '什么什么能量特征',
|
||||||
|
dispose_way: '怎么怎么怎么怎么怎么去处理',
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
type: '田园尾菜桔秆',
|
||||||
|
icon: 'solar:airbuds-case-open-line-duotone',
|
||||||
|
details: [],
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
}),
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
setShow(index: number) {
|
||||||
|
this.showIndex = index
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// persist: {
|
||||||
|
// storage: persistedState.sessionStorage,
|
||||||
|
// },
|
||||||
|
})
|
||||||
|
|
||||||
|
if (import.meta.hot)
|
||||||
|
import.meta.hot.accept(acceptHMRUpdate(useInfoStore, import.meta.hot))
|
|
@ -1,54 +0,0 @@
|
||||||
export interface Notice {
|
|
||||||
state: "loading" | "pending" | "error" | "success"
|
|
||||||
title: string
|
|
||||||
desc: string
|
|
||||||
time: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export const useNoticeStore = defineStore('notice', {
|
|
||||||
state: (): {
|
|
||||||
notices: Notice[]
|
|
||||||
} => ({
|
|
||||||
notices: [],
|
|
||||||
}),
|
|
||||||
actions: {
|
|
||||||
update(title: string, desc: string, state: "loading" | "pending" | "error" | "success") {
|
|
||||||
const index = this.notices.findIndex((i) => i.title === title)
|
|
||||||
if (index !== -1) {
|
|
||||||
this.notices.splice(index, 1, { state: "loading", title, desc, time: new Date() })
|
|
||||||
}
|
|
||||||
},
|
|
||||||
noticePending(title: string, desc: string) {
|
|
||||||
this.notices.push({ state: "pending", title, desc, time: new Date() })
|
|
||||||
},
|
|
||||||
async filesPending(path: string, files: File[]) {
|
|
||||||
files.map((file) => {
|
|
||||||
this.noticePending(file.name, `${merticKB(file.size)},${file.type}`)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
// async filesUpload() {
|
|
||||||
// const res = await bucketApi.detail.uploadUrl({ Path: path })
|
|
||||||
// for (const file of Array.from(files)) {
|
|
||||||
// try {
|
|
||||||
// this.update(file.name, `${merticKB(file.size)},${file.type},文件上传中...`, 'loading')
|
|
||||||
// await bucketApi.detail.upload(file, res.url, res.token)
|
|
||||||
// } catch (e: any) {
|
|
||||||
// // 单个文件上传失败报错信息
|
|
||||||
// this.update(file.name, `${merticKB(file.size)},${file.type},文件上传失败!`, 'error')
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
},
|
|
||||||
persist: {
|
|
||||||
storage: persistedState.sessionStorage
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
if (import.meta.hot)
|
|
||||||
// @ts-ignore
|
|
||||||
import.meta.hot.accept(acceptHMRUpdate(useUserStore, import.meta.hot))
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
export const usePolicyStore = defineStore('policy', {
|
||||||
|
state: (): {
|
||||||
|
policy: {
|
||||||
|
name: string
|
||||||
|
description: string
|
||||||
|
url: string
|
||||||
|
type: '国家' | '地方' | '企业'
|
||||||
|
}[]
|
||||||
|
} => ({
|
||||||
|
|
||||||
|
policy: [
|
||||||
|
{
|
||||||
|
name: '政策1',
|
||||||
|
url: 'https://www.baidu.com/policy1',
|
||||||
|
description: '这是政策1的描述',
|
||||||
|
type: '国家',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '政策2',
|
||||||
|
url: 'https://www.baidu.com/policy1',
|
||||||
|
description: '这是政策1的描述',
|
||||||
|
type: '国家',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '政策3',
|
||||||
|
url: 'https://www.baidu.com/policy1',
|
||||||
|
description: '这是政策1的描述',
|
||||||
|
type: '国家',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '政策2',
|
||||||
|
url: 'https://www.example.com/policy2',
|
||||||
|
description: '这是政策2的描述',
|
||||||
|
type: '企业',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '政策3',
|
||||||
|
url: 'https://www.example.com/policy3',
|
||||||
|
description: '这是政策3的描述',
|
||||||
|
type: '地方',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
persist: {
|
||||||
|
storage: persistedState.sessionStorage,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if (import.meta.hot)
|
||||||
|
import.meta.hot.accept(acceptHMRUpdate(usePolicyStore, import.meta.hot))
|
|
@ -1,24 +1,232 @@
|
||||||
import type { UserInfo } from '~/api/user'
|
export interface ResourceTechnologyInfo {
|
||||||
|
properThing: string[]
|
||||||
export const useResourceStore = defineStore('user', {
|
craftImage: string
|
||||||
state: (): {
|
device: string
|
||||||
search:string
|
env: {
|
||||||
searchThrottled:Ref<string>
|
yieldDistance: number
|
||||||
} => ({
|
area: number
|
||||||
search:'',
|
terrain: string
|
||||||
searchThrottled:refThrottled(ref(''),300)
|
supplyWater: string
|
||||||
}),
|
supplyElectricity: string
|
||||||
actions: {
|
dischargeWater: string
|
||||||
},
|
temperature: number
|
||||||
persist: {
|
airPressure: number
|
||||||
storage: persistedState.sessionStorage
|
// ...
|
||||||
}
|
}
|
||||||
|
production: string[]
|
||||||
|
discharge: {
|
||||||
|
effluent: string[]
|
||||||
|
sludge: string[]
|
||||||
|
gas: string[]
|
||||||
|
}
|
||||||
|
work: string
|
||||||
|
cost: number
|
||||||
|
efficiency: string
|
||||||
|
utilization: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useResourceStore = defineStore('resource', {
|
||||||
|
state: (): {
|
||||||
|
resources: ResourceTechnologyInfo[]
|
||||||
|
policy: {
|
||||||
|
name: string
|
||||||
|
description: string
|
||||||
|
url: string
|
||||||
|
type: '国家' | '地方' | '企业'
|
||||||
|
}[]
|
||||||
|
} => ({
|
||||||
|
resources: [{
|
||||||
|
properThing: ['易拉罐', '垃圾箱'],
|
||||||
|
craftImage: 'https://pic1.zhimg.com/v2-f24231dafa70ba95a2f84262471dadfc_r.jpg',
|
||||||
|
device: '垃圾箱',
|
||||||
|
env: {
|
||||||
|
yieldDistance: 110,
|
||||||
|
area: 4042,
|
||||||
|
terrain: '丘陵',
|
||||||
|
supplyWater: '什么什么供水要求',
|
||||||
|
supplyElectricity: '什么什么供电要求',
|
||||||
|
dischargeWater: '什么什么排水要求',
|
||||||
|
temperature: 29,
|
||||||
|
airPressure: 1000,
|
||||||
|
// ...
|
||||||
|
},
|
||||||
|
production: ['塑料', '金属'],
|
||||||
|
discharge: {
|
||||||
|
effluent: ['水', '污水'],
|
||||||
|
sludge: ['污泥', 'xx污泥'],
|
||||||
|
gas: ['氢', '甲烷', '乙烷'],
|
||||||
|
},
|
||||||
|
work: '6名工人',
|
||||||
|
cost: 222450,
|
||||||
|
efficiency: '100%',
|
||||||
|
utilization: '高效',
|
||||||
|
},
|
||||||
|
// 帮我再编写5条类似数据
|
||||||
|
{
|
||||||
|
properThing: ['玩具', '塑料袋'],
|
||||||
|
craftImage: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.BsxwuPonB9eNr4ti6SnbnAHaGV?pid=ImgDet&w=474&h=405&rs=1',
|
||||||
|
device: '垃圾管理系统',
|
||||||
|
env: {
|
||||||
|
yieldDistance: 140,
|
||||||
|
area: 2800,
|
||||||
|
terrain: '湿地',
|
||||||
|
supplyWater: '湖水',
|
||||||
|
supplyElectricity: '水力发电',
|
||||||
|
dischargeWater: '湖泊',
|
||||||
|
temperature: 27,
|
||||||
|
airPressure: 1002,
|
||||||
|
},
|
||||||
|
production: ['塑料', '再生材料'],
|
||||||
|
discharge: {
|
||||||
|
effluent: ['废水'],
|
||||||
|
sludge: ['废渣'],
|
||||||
|
gas: ['氧气', '氮气'],
|
||||||
|
},
|
||||||
|
work: '4名工人',
|
||||||
|
cost: 160000,
|
||||||
|
efficiency: '92%',
|
||||||
|
utilization: '高效',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
properThing: ['纸杯', '食品包装'],
|
||||||
|
craftImage: 'https://img.zcool.cn/community/019559594098fca8012193a303c702.png@2o.png',
|
||||||
|
device: '垃圾处理装置',
|
||||||
|
env: {
|
||||||
|
yieldDistance: 130,
|
||||||
|
area: 3200,
|
||||||
|
terrain: '山区',
|
||||||
|
supplyWater: '地下水',
|
||||||
|
supplyElectricity: '生物质能',
|
||||||
|
dischargeWater: '河流',
|
||||||
|
temperature: 26,
|
||||||
|
airPressure: 1008,
|
||||||
|
},
|
||||||
|
production: ['纸张', '有机肥料'],
|
||||||
|
discharge: {
|
||||||
|
effluent: ['废水'],
|
||||||
|
sludge: ['有机废物'],
|
||||||
|
gas: ['氧气', '甲烷'],
|
||||||
|
},
|
||||||
|
work: '5名工人',
|
||||||
|
cost: 170000,
|
||||||
|
efficiency: '88%',
|
||||||
|
utilization: '中等',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
properThing: ['食品包装', '塑料袋'],
|
||||||
|
craftImage: 'https://www.yuaoq.com/template/draw/uncategorized/10378/10378_template.png',
|
||||||
|
device: '垃圾处理机',
|
||||||
|
env: {
|
||||||
|
yieldDistance: 150,
|
||||||
|
area: 3500,
|
||||||
|
terrain: '沿海',
|
||||||
|
supplyWater: '海水',
|
||||||
|
supplyElectricity: '风力发电',
|
||||||
|
dischargeWater: '海洋',
|
||||||
|
temperature: 28,
|
||||||
|
airPressure: 1003,
|
||||||
|
},
|
||||||
|
production: ['塑料', '有机肥料'],
|
||||||
|
discharge: {
|
||||||
|
effluent: ['废水'],
|
||||||
|
sludge: ['有机废物'],
|
||||||
|
gas: ['二氧化碳', '氢气'],
|
||||||
|
},
|
||||||
|
work: '6名工人',
|
||||||
|
cost: 200000,
|
||||||
|
efficiency: '95%',
|
||||||
|
utilization: '高效',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
properThing: ['玻璃瓶', '金属罐'],
|
||||||
|
craftImage: 'https://ts1.cn.mm.bing.net/th/id/R-C.ea57da618322715a29309637a45aa83b?rik=rvuZvWzTb2t%2bFA&riu=http%3a%2f%2fdocs-aliyun.cn-hangzhou.oss.aliyun-inc.com%2fassets%2fpic%2f117771%2fcn_zh%2f1557311249692%2f%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7+2019-05-08+%E4%B8%8B%E5%8D%886.26.51.png&ehk=AEDi9kQLAwki5lezNmCNfa0H4cHaLsSAyiNrcKmTr9k%3d&risl=&pid=ImgRaw&r=0',
|
||||||
|
device: '垃圾回收机',
|
||||||
|
env: {
|
||||||
|
yieldDistance: 100,
|
||||||
|
area: 2500,
|
||||||
|
terrain: '城市',
|
||||||
|
supplyWater: '循环水',
|
||||||
|
supplyElectricity: '太阳能',
|
||||||
|
dischargeWater: '雨水管道',
|
||||||
|
temperature: 30,
|
||||||
|
airPressure: 1005,
|
||||||
|
},
|
||||||
|
production: ['玻璃', '金属'],
|
||||||
|
discharge: {
|
||||||
|
effluent: ['废水'],
|
||||||
|
sludge: ['废渣'],
|
||||||
|
gas: ['氧气', '氮气'],
|
||||||
|
},
|
||||||
|
work: '5名工人',
|
||||||
|
cost: 180000,
|
||||||
|
efficiency: '85%',
|
||||||
|
utilization: '高效',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
properThing: ['纸箱', '塑料瓶'],
|
||||||
|
craftImage: 'https://www.yuaoq.com/template/draw/uncategorized/11562/11562_template.png',
|
||||||
|
device: '垃圾桶',
|
||||||
|
env: {
|
||||||
|
yieldDistance: 120,
|
||||||
|
area: 3000,
|
||||||
|
terrain: '平原',
|
||||||
|
supplyWater: '自来水',
|
||||||
|
supplyElectricity: '市电',
|
||||||
|
dischargeWater: '污水处理厂',
|
||||||
|
temperature: 25,
|
||||||
|
airPressure: 1010,
|
||||||
|
},
|
||||||
|
production: ['塑料', '纸张'],
|
||||||
|
discharge: {
|
||||||
|
effluent: ['废水'],
|
||||||
|
sludge: ['污泥'],
|
||||||
|
gas: ['二氧化碳', '氧气'],
|
||||||
|
},
|
||||||
|
work: '4名工人',
|
||||||
|
cost: 150000,
|
||||||
|
efficiency: '90%',
|
||||||
|
utilization: '中等',
|
||||||
|
},
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
policy: [
|
||||||
|
{
|
||||||
|
name: '政策1',
|
||||||
|
url: 'https://www.baidu.com/policy1',
|
||||||
|
description: '这是政策1的描述',
|
||||||
|
type: '国家',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '政策2',
|
||||||
|
url: 'https://www.baidu.com/policy1',
|
||||||
|
description: '这是政策1的描述',
|
||||||
|
type: '国家',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '政策3',
|
||||||
|
url: 'https://www.baidu.com/policy1',
|
||||||
|
description: '这是政策1的描述',
|
||||||
|
type: '国家',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '政策2',
|
||||||
|
url: 'https://www.example.com/policy2',
|
||||||
|
description: '这是政策2的描述',
|
||||||
|
type: '企业',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '政策3',
|
||||||
|
url: 'https://www.example.com/policy3',
|
||||||
|
description: '这是政策3的描述',
|
||||||
|
type: '地方',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
persist: {
|
||||||
|
storage: persistedState.sessionStorage,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
if (import.meta.hot)
|
if (import.meta.hot)
|
||||||
// @ts-ignore
|
|
||||||
import.meta.hot.accept(acceptHMRUpdate(useResourceStore, import.meta.hot))
|
import.meta.hot.accept(acceptHMRUpdate(useResourceStore, import.meta.hot))
|
||||||
|
|
|
@ -11,8 +11,6 @@
|
||||||
<slot />
|
<slot />
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<BackgroundLeft class="absolute left-0 h-full select-none " />
|
|
||||||
<BackgroundLeft class="absolute right-0 rotate-180 scale-x-150 h-full select-none " />
|
|
||||||
<!-- <BackgroundRight class="absolute right-0 h-full select-none" /> -->
|
<!-- <BackgroundRight class="absolute right-0 h-full select-none" /> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,24 +1,28 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const digitalsV2 = [
|
const digitalsV2 = [
|
||||||
{
|
{
|
||||||
title: 'string',
|
title: '资源化技术',
|
||||||
value: 123,
|
value: 1231,
|
||||||
icon: 'solar:airbuds-remove-line-duotone',
|
icon: 'solar:bonfire-linear',
|
||||||
|
to: '/resource_technology',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'string',
|
title: '政策',
|
||||||
value: 123,
|
value: 123,
|
||||||
icon: 'solar:airbuds-remove-line-duotone',
|
icon: 'solar:buildings-2-broken',
|
||||||
|
to: '/policy',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'string',
|
title: '新闻',
|
||||||
value: 123,
|
value: 123,
|
||||||
icon: 'solar:airbuds-remove-line-duotone',
|
icon: 'solar:cart-3-broken',
|
||||||
|
to: '/news',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'string',
|
title: '标准',
|
||||||
value: 123,
|
value: 123,
|
||||||
icon: 'solar:airbuds-remove-line-duotone',
|
icon: 'solar:calculator-line-duotone',
|
||||||
|
to: '/standard',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -32,16 +36,19 @@ function change(value: number) {
|
||||||
<template>
|
<template>
|
||||||
<div class="fixed bottom-0 left-0 flex flex-col justify-between h-full pt-[170px] z-10 p-14 ">
|
<div class="fixed bottom-0 left-0 flex flex-col justify-between h-full pt-[170px] z-10 p-14 ">
|
||||||
<div class="space-y-6 ">
|
<div class="space-y-6 ">
|
||||||
<DigitalV3 v-for="(item, index) in digitalsV2" :key="index" v-bind="item" />
|
<NuxtLink v-for="(item, index) in digitalsV2" :key="index" class="block" :to="item.to">
|
||||||
|
<DigitalV3 v-bind="item" />
|
||||||
|
</NuxtLink>
|
||||||
</div>
|
</div>
|
||||||
<Warning :count="35" />
|
<Warning :count="35" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="fixed bottom-0 right-0 flex h-full gap-6 pt-[150px] z-10 p-6">
|
<div class="fixed bottom-0 right-0 flex h-full gap-6 pt-[150px] z-10 p-6 pr-14 pb-14">
|
||||||
<div class="flex flex-col justify-between">
|
<div class="flex flex-col justify-between">
|
||||||
<SectionOne />
|
<SectionOne />
|
||||||
<SectionTwo />
|
<SectionTwo />
|
||||||
<SectionFour />
|
<SectionFive />
|
||||||
|
<!-- <SectionFour /> -->
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="flex flex-col justify-between">
|
<!-- <div class="flex flex-col justify-between">
|
||||||
<SectionTwo />
|
<SectionTwo />
|
||||||
|
@ -49,7 +56,9 @@ function change(value: number) {
|
||||||
<SectionFive />
|
<SectionFive />
|
||||||
</div> -->
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
<div class="fixed top-0 left-0 w-full h-full bg-black/50">
|
<div class="fixed top-0 left-0 w-full h-full ">
|
||||||
<SectionChinaMap />
|
<SectionChinaMap />
|
||||||
</div>
|
</div>
|
||||||
|
<BackgroundLeft class="absolute top-0 left-0 h-full select-none -z-[1]" />
|
||||||
|
<BackgroundLeft class="absolute top-0 right-0 h-full scale-x-150 rotate-180 select-none -z-[1]" />
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
<script setup lang="tsx">
|
||||||
|
const data = [
|
||||||
|
{
|
||||||
|
title: '农村有机物',
|
||||||
|
description: '有关于农村有机物的新闻',
|
||||||
|
image: 'https://picsum.photos/id/10/640/360',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '农村有机肥',
|
||||||
|
description: '有关于农村有机肥的新闻',
|
||||||
|
image: 'https://picsum.photos/id/13/640/360',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '农村化肥',
|
||||||
|
description: '有关于农村化肥的新闻',
|
||||||
|
image: 'https://picsum.photos/id/12/640/360',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '农村农药',
|
||||||
|
description: '有关于农村农药的新闻',
|
||||||
|
image: 'https://picsum.photos/id/11/640/360',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '农村种子',
|
||||||
|
description: '有关于农村种子的新闻',
|
||||||
|
image: 'https://picsum.photos/id/14/640/360',
|
||||||
|
},
|
||||||
|
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<section class="">
|
||||||
|
<div class="max-w-screen-xl px-4 py-8 mx-auto lg:py-16 lg:px-6">
|
||||||
|
<div class="max-w-screen-lg text-gray-500 sm:text-lg dark:text-gray-400">
|
||||||
|
<h2 class="mb-4 text-4xl font-bold tracking-tight text-gray-900 dark:text-white">
|
||||||
|
有关于农村废弃物特征的诸多诸多新闻
|
||||||
|
</h2>
|
||||||
|
<p class="mb-4 font-light">
|
||||||
|
远程办理、智慧农业、直播带货……如今的乡村变得越来越“硬核”!手机成为了新农具,网络成为了新农资,直播成为了新农活。数字技术在为经济增长提供强大动力的同时,也正以多种形式助力乡村振兴。
|
||||||
|
</p>
|
||||||
|
<p class="mb-4 font-medium">
|
||||||
|
2018年,中共中央、国务院印发的《乡村振兴战略规划(2018-2022)》指出,大力发展数字农业,实施智慧农业工程和“互联网+”现代农业行动,建设具有广泛性的农村电子商务发展基础设施,加快建立健全适应农产品电商发展的标准体系等。
|
||||||
|
|
||||||
|
<br>在政策的指引下,近年来,浙江、江苏、山东、福建等地,一批批的专业“淘宝村”纷纷涌现。在浙江丽水,通过一系列政策保障,以农村青年、大学毕业生为主要服务群体,以优质农特产品网上销售为工作重点的农村电子商务,这几年如雨后春笋般冒了出来。
|
||||||
|
</p>
|
||||||
|
<a href="#" class="inline-flex items-center font-medium text-primary-600 hover:text-primary-800 dark:text-primary-500 dark:hover:text-primary-700">
|
||||||
|
查看更多
|
||||||
|
<svg class="w-6 h-6 ml-1" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd" /></svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-2 gap-4 pt-10 mx-auto px-[500px] md:grid-cols-3 lg:grid-cols-4">
|
||||||
|
<Card v-for="item in data" :key="item.title" class="overflow-hidden">
|
||||||
|
<CardContent class="p-0">
|
||||||
|
<img :src="item.image" alt="news" class="w-full">
|
||||||
|
</CardContent>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>{{ item.title }}</CardTitle>
|
||||||
|
<CardDescription>{{ item.description }}</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<template>
|
||||||
|
<NuxtPage />
|
||||||
|
</template>
|
|
@ -0,0 +1,80 @@
|
||||||
|
<script setup lang="tsx">
|
||||||
|
import type { ColumnDef } from '@tanstack/vue-table'
|
||||||
|
import DataTable from '~/components/common/table/DataTable.vue'
|
||||||
|
import DataTableColumnHeader from '~/components/common/table/DataTableColumnHeader.vue'
|
||||||
|
import DataTableRowActions from '~/components/common/table/DataTableRowActions.vue'
|
||||||
|
|
||||||
|
const router = useRoute()
|
||||||
|
const resource = usePolicyStore()
|
||||||
|
type Task = typeof resource.policy[0]
|
||||||
|
|
||||||
|
console.log(router.params.name)
|
||||||
|
|
||||||
|
const columns: ColumnDef<Task, any>[] = [
|
||||||
|
{
|
||||||
|
accessorKey: 'name',
|
||||||
|
header: ({ column }) =>
|
||||||
|
<DataTableColumnHeader column={column} title="政策名称" />,
|
||||||
|
cell: ({ row }) => <div class='w-26'>{row.original.name}</div>,
|
||||||
|
enableSorting: false,
|
||||||
|
enableHiding: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'description',
|
||||||
|
header: ({ column }) =>
|
||||||
|
<DataTableColumnHeader column={column} title="描述" />,
|
||||||
|
|
||||||
|
cell: ({ row }) => <div class='w-26'>{row.original.description}</div>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'url',
|
||||||
|
header: ({ column }) =>
|
||||||
|
<DataTableColumnHeader column={column} title="地址" />,
|
||||||
|
|
||||||
|
cell: ({ row }) => <a href={row.original.url} target='_blank' class='w-26 text-primary '>{row.original.url}</a>,
|
||||||
|
filterFn: (row, id, value) => {
|
||||||
|
return value.includes(row.getValue(id))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'actions',
|
||||||
|
cell: ({ row }) => (
|
||||||
|
<DataTableRowActions row={row} menus={[{
|
||||||
|
label: '修改',
|
||||||
|
icon: 'tabler:edit',
|
||||||
|
click: () => {
|
||||||
|
console.log('edit', row.original)
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
label: '删除',
|
||||||
|
icon: 'tabler:trash',
|
||||||
|
click: () => {
|
||||||
|
console.log('delete', row.original)
|
||||||
|
},
|
||||||
|
}]}/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
console.log(resource.policy)
|
||||||
|
console.log(resource.policy.filter(i => i.type === router.params.name))
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="p-4 mt-10 mx-autoto ">
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<h1 class="text-3xl font-bold mb-4 text-center">
|
||||||
|
{{ router.params.name }}政策
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<DataTable :data="resource.policy.filter(i => i.type === router.params.name)" :columns="columns" class="px-10">
|
||||||
|
<template #toolbar>
|
||||||
|
<Button size="xs">
|
||||||
|
添加
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
</DataTable>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -0,0 +1,43 @@
|
||||||
|
<script setup lang="tsx">
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="w-full flex justify-center gap-10 my-[300px]">
|
||||||
|
<NuxtLink to="/policy/国家">
|
||||||
|
<Card class="overflow-hidden w-[300px] h-[500px] flex flex-col ">
|
||||||
|
<CardContent class="p-0 flex-1">
|
||||||
|
<img src="https://r1.visitbeijing.com.cn/vbj-s/2012/1207/20121207034517194.jpg" alt="news" class="w-full h-full object-cover">
|
||||||
|
</CardContent>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle class="text-center">
|
||||||
|
国家政策
|
||||||
|
</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
</Card>
|
||||||
|
</NuxtLink>
|
||||||
|
<NuxtLink to="/policy/地方">
|
||||||
|
<Card class="overflow-hidden w-[300px] h-[500px] flex flex-col ">
|
||||||
|
<CardContent class="p-0 flex-1">
|
||||||
|
<img src="https://ts1.cn.mm.bing.net/th/id/R-C.9d9900102aea31b95588cd15dcf7e2ac?rik=EjFSTbg5c5V6ng&riu=http%3a%2f%2fp0.ifengimg.com%2fa%2f2016_51%2fccf711fb8a241d2_size259_w880_h580.jpeg&ehk=9lqQs4Bh0pNVyZP40FLRTrH%2bjh47aLKB6K5mTHQGRso%3d&risl=&pid=ImgRaw&r=0" alt="news" class="w-full h-full object-cover">
|
||||||
|
</CardContent>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle class="text-center">
|
||||||
|
地方政策
|
||||||
|
</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
</Card>
|
||||||
|
</NuxtLink>
|
||||||
|
<NuxtLink to="/policy/企业">
|
||||||
|
<Card class="overflow-hidden w-[300px] h-[500px] flex flex-col ">
|
||||||
|
<CardContent class="p-0 flex-1">
|
||||||
|
<img src="https://ts1.cn.mm.bing.net/th/id/R-C.5307c6c84d509b6d734429944227cf2d?rik=PkoltCVAAkQD4A&riu=http%3a%2f%2fwww.tech-sonic.net%2fImgUpload%2fimages%2f0905-1.jpg&ehk=C944SM%2bikWpqeVXPv1QgKwOioMud6LwZUu4lKwoOiwQ%3d&risl=&pid=ImgRaw&r=0" alt="news" class="w-full h-full object-cover">
|
||||||
|
</CardContent>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle class="text-center">
|
||||||
|
企业政策
|
||||||
|
</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
</Card>
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -0,0 +1,131 @@
|
||||||
|
<script setup lang="tsx">
|
||||||
|
import type { ColumnDef } from '@tanstack/vue-table'
|
||||||
|
import Badge from '../../../packages/ui/components/ui/badge/Badge.vue'
|
||||||
|
import DataTable from '~/components/common/table/DataTable.vue'
|
||||||
|
import DataTableColumnHeader from '~/components/common/table/DataTableColumnHeader.vue'
|
||||||
|
import DataTableRowActions from '~/components/common/table/DataTableRowActions.vue'
|
||||||
|
import EditEnv from '~/components/form/resource/edit-env.vue'
|
||||||
|
import ShowCraft from '~/components/form/resource/show-craft.vue'
|
||||||
|
|
||||||
|
const resource = useResourceStore()
|
||||||
|
|
||||||
|
const columns: ColumnDef<ResourceTechnologyInfo, any>[] = [
|
||||||
|
{
|
||||||
|
accessorKey: 'properThing',
|
||||||
|
header: ({ column }) => <DataTableColumnHeader column={column} title="适用废弃物" />,
|
||||||
|
cell: ({ row }) => <div class='w-26'>{row.original.properThing.join(',')}</div>,
|
||||||
|
enableSorting: false,
|
||||||
|
enableHiding: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'craftImage',
|
||||||
|
header: ({ column }) => <DataTableColumnHeader column={column} title="工艺流程" />,
|
||||||
|
cell: ({ row }) => (<ShowCraft resource={row.original}/>),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'device',
|
||||||
|
header: ({ column }) => <DataTableColumnHeader column={column} title="所需设备" />,
|
||||||
|
cell: ({ row }) => <div class='w-26'>{row.original.device}</div>,
|
||||||
|
filterFn: (row, id, value) => {
|
||||||
|
return value.includes(row.getValue(id))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'env',
|
||||||
|
header: ({ column }) => <DataTableColumnHeader column={column} title="场地条件" />,
|
||||||
|
cell: ({ row }) => <EditEnv env={row.original.env} />,
|
||||||
|
filterFn: (row, id, value) => {
|
||||||
|
return value.includes(row.getValue(id))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'production',
|
||||||
|
header: ({ column }) => <DataTableColumnHeader column={column} title="产出产品" />,
|
||||||
|
cell: ({ row }) => <div class='w-26'>{row.original.production}</div>,
|
||||||
|
filterFn: (row, id, value) => {
|
||||||
|
return value.includes(row.getValue(id))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'work',
|
||||||
|
header: ({ column }) => <DataTableColumnHeader column={column} title="用工" />,
|
||||||
|
cell: ({ row }) => <div class='w-26'>{row.original.work}</div>,
|
||||||
|
filterFn: (row, id, value) => {
|
||||||
|
return value.includes(row.getValue(id))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'discharge',
|
||||||
|
header: ({ column }) => <DataTableColumnHeader column={column} title="排放物" />,
|
||||||
|
cell: ({ row }) => (
|
||||||
|
<>
|
||||||
|
|
||||||
|
<div class=''>{ row.original.discharge.effluent.map(i => (<Badge class="bg-blue-500">{i}</Badge>))} </div>
|
||||||
|
|
||||||
|
<div class=''>{ row.original.discharge.sludge.map(i => (<Badge class="bg-orange-500">{i}</Badge>))} </div>
|
||||||
|
<div class=''>{ row.original.discharge.gas.map(i => (<Badge class="bg-gray-500">{i}</Badge>))} </div>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
filterFn: (row, id, value) => {
|
||||||
|
return value.includes(row.getValue(id))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'cost',
|
||||||
|
header: ({ column }) => <DataTableColumnHeader column={column} title="成本" />,
|
||||||
|
cell: ({ row }) => <div class='w-26'>{row.original.cost}元</div>,
|
||||||
|
filterFn: (row, id, value) => {
|
||||||
|
return value.includes(row.getValue(id))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'efficiency',
|
||||||
|
header: ({ column }) => <DataTableColumnHeader column={column} title="效益" />,
|
||||||
|
cell: ({ row }) => <div class='w-26'>{row.original.efficiency}</div>,
|
||||||
|
filterFn: (row, id, value) => {
|
||||||
|
return value.includes(row.getValue(id))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'utilization',
|
||||||
|
header: ({ column }) => <DataTableColumnHeader column={column} title="资源利用效率" />,
|
||||||
|
cell: ({ row }) => <div class='w-26'>{row.original.utilization}</div>,
|
||||||
|
filterFn: (row, id, value) => {
|
||||||
|
return value.includes(row.getValue(id))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'actions',
|
||||||
|
cell: ({ row }) => (
|
||||||
|
<DataTableRowActions row={row} menus={[{
|
||||||
|
label: '编辑',
|
||||||
|
icon: 'tabler:edit',
|
||||||
|
click: () => {
|
||||||
|
console.log('edit', row.original)
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
label: '删除',
|
||||||
|
icon: 'tabler:trash',
|
||||||
|
click: () => {
|
||||||
|
console.log('delete', row.original)
|
||||||
|
},
|
||||||
|
}]}/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="p-4 mt-10 mx-autoto ">
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<h1 class="text-3xl font-bold mb-4 text-center">
|
||||||
|
资源化技术信息
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<DataTable :data="resource.resources" :columns="columns" class="px-10">
|
||||||
|
<template #toolbar>
|
||||||
|
<FormResourceCreateForm />
|
||||||
|
</template>
|
||||||
|
</DataTable>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -0,0 +1,151 @@
|
||||||
|
<script setup lang="tsx">
|
||||||
|
const data = [
|
||||||
|
{
|
||||||
|
title: '电动汽车远程服务于管理系统技术规范',
|
||||||
|
description: '',
|
||||||
|
image: '1.png',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '住宅装饰装修工程施工规范',
|
||||||
|
description: '',
|
||||||
|
image: '/2.jpg',
|
||||||
|
},
|
||||||
|
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex flex-col pt-20">
|
||||||
|
<main class="grid flex-1 gap-4 p-4 overflow-auto md:grid-cols-2 lg:grid-cols-6">
|
||||||
|
<div class="relative flex-col items-start hidden gap-8 md:flex">
|
||||||
|
<form class="grid items-start w-full gap-6">
|
||||||
|
<fieldset class="grid gap-6 p-4 border rounded-lg">
|
||||||
|
<legend class="px-1 -ml-1 text-sm font-medium">
|
||||||
|
搜索条件
|
||||||
|
</legend>
|
||||||
|
<div class="grid gap-3">
|
||||||
|
<Label for="model">标准来源</Label>
|
||||||
|
<Select>
|
||||||
|
<SelectTrigger
|
||||||
|
id="model"
|
||||||
|
class="items-start [&_[data-description]]:hidden"
|
||||||
|
>
|
||||||
|
<SelectValue placeholder="Select a model" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="genesis">
|
||||||
|
<div class="flex items-start gap-3 text-muted-foreground">
|
||||||
|
<Rabbit class="size-5" />
|
||||||
|
<div class="grid gap-0.5">
|
||||||
|
<p>
|
||||||
|
Neural
|
||||||
|
<span class="font-medium text-foreground">
|
||||||
|
Genesis
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<p class="text-xs" data-description>
|
||||||
|
Our fastest model for general use cases.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="explorer">
|
||||||
|
<div class="flex items-start gap-3 text-muted-foreground">
|
||||||
|
<Bird class="size-5" />
|
||||||
|
<div class="grid gap-0.5">
|
||||||
|
<p>
|
||||||
|
Neural
|
||||||
|
<span class="font-medium text-foreground">
|
||||||
|
Explorer
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<p class="text-xs" data-description>
|
||||||
|
Performance and speed for efficiency.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="quantum">
|
||||||
|
<div class="flex items-start gap-3 text-muted-foreground">
|
||||||
|
<Turtle class="size-5" />
|
||||||
|
<div class="grid gap-0.5">
|
||||||
|
<p>
|
||||||
|
Neural
|
||||||
|
<span class="font-medium text-foreground">
|
||||||
|
Quantum
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<p class="text-xs" data-description>
|
||||||
|
The most powerful model for complex computations.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div class="grid gap-3">
|
||||||
|
<Label for="temperature">Temperature</Label>
|
||||||
|
<Input id="temperature" type="number" placeholder="0.4" />
|
||||||
|
</div>
|
||||||
|
<div class="grid grid-cols-2 gap-4">
|
||||||
|
<div class="grid gap-3">
|
||||||
|
<Label for="top-p">Top P</Label>
|
||||||
|
<Input id="top-p" type="number" placeholder="0.7" />
|
||||||
|
</div>
|
||||||
|
<div class="grid gap-3">
|
||||||
|
<Label for="top-k">Top K</Label>
|
||||||
|
<Input id="top-k" type="number" placeholder="0.0" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset class="grid gap-6 p-4 border rounded-lg">
|
||||||
|
<legend class="px-1 -ml-1 text-sm font-medium">
|
||||||
|
Messages
|
||||||
|
</legend>
|
||||||
|
<div class="grid gap-3">
|
||||||
|
<Label for="role">Role</Label>
|
||||||
|
<Select default-value="system">
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select a role" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="system">
|
||||||
|
System
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="user">
|
||||||
|
User
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="assistant">
|
||||||
|
Assistant
|
||||||
|
</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div class="grid gap-3">
|
||||||
|
<Label for="content">Content</Label>
|
||||||
|
<Textarea
|
||||||
|
id="content"
|
||||||
|
placeholder="You are a..."
|
||||||
|
class="min-h-[9.5rem]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="relative flex h-full col-span-5 p-4">
|
||||||
|
<div class="grid w-full grid-cols-2 gap-4 mx-auto md:grid-cols-3 lg:grid-cols-5">
|
||||||
|
<Card v-for="item in data" :key="item.title" class="overflow-hidden">
|
||||||
|
<CardContent class="p-0">
|
||||||
|
<img :src="item.image" alt="news" class="w-full">
|
||||||
|
</CardContent>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>{{ item.title }}</CardTitle>
|
||||||
|
<CardDescription>{{ item.description }}</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</template>
|
Binary file not shown.
After Width: | Height: | Size: 217 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.2 MiB |
|
@ -190,7 +190,7 @@ const data = [
|
||||||
{ name: '武汉', value: 273 },
|
{ name: '武汉', value: 273 },
|
||||||
{ name: '大庆', value: 279 },
|
{ name: '大庆', value: 279 },
|
||||||
]
|
]
|
||||||
const geoCoordMap = {
|
export const geoCoordMap = {
|
||||||
海门: [121.15, 31.89],
|
海门: [121.15, 31.89],
|
||||||
鄂尔多斯: [109.781327, 39.608266],
|
鄂尔多斯: [109.781327, 39.608266],
|
||||||
招远: [120.38, 37.35],
|
招远: [120.38, 37.35],
|
||||||
|
@ -383,6 +383,10 @@ const geoCoordMap = {
|
||||||
大庆: [125.03, 46.58],
|
大庆: [125.03, 46.58],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function dataMap(value: keyof typeof geoCoordMap) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function convertData(data: {
|
function convertData(data: {
|
||||||
name: string
|
name: string
|
||||||
value: number
|
value: number
|
||||||
|
@ -399,96 +403,3 @@ function convertData(data: {
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function getData() {
|
|
||||||
return {
|
|
||||||
textStyle: {
|
|
||||||
fontFamily: 'Inter, "Helvetica Neue", Arial, sans-serif',
|
|
||||||
fontWeight: 300,
|
|
||||||
},
|
|
||||||
backgroundColor: '#404a59',
|
|
||||||
title: {
|
|
||||||
text: 'Air quality of major cities in China',
|
|
||||||
subtext: 'data from PM25.in',
|
|
||||||
sublink: 'http://www.pm25.in',
|
|
||||||
left: 'center',
|
|
||||||
textStyle: {
|
|
||||||
color: '#fff',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'item',
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
orient: 'vertical',
|
|
||||||
y: 'bottom',
|
|
||||||
x: 'right',
|
|
||||||
data: ['pm2.5'],
|
|
||||||
textStyle: {
|
|
||||||
color: '#fff',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
geo: {
|
|
||||||
map: 'china',
|
|
||||||
emphasis: {
|
|
||||||
label: {
|
|
||||||
show: false,
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
areaColor: '#2a333d',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
areaColor: '#323c48',
|
|
||||||
borderColor: '#111',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: 'pm2.5',
|
|
||||||
type: 'scatter',
|
|
||||||
coordinateSystem: 'geo',
|
|
||||||
data: convertData(data),
|
|
||||||
symbolSize: val => val[2] / 10,
|
|
||||||
tooltip: {
|
|
||||||
formatter(val) {
|
|
||||||
return `${val.name}: ${val.value[2]}`
|
|
||||||
},
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
color: '#ddb926',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Top 5',
|
|
||||||
type: 'effectScatter',
|
|
||||||
coordinateSystem: 'geo',
|
|
||||||
data: convertData(data.sort((a, b) => b.value - a.value).slice(0, 6)),
|
|
||||||
symbolSize: val => val[2] / 10,
|
|
||||||
showEffectOn: 'render',
|
|
||||||
rippleEffect: {
|
|
||||||
brushType: 'stroke',
|
|
||||||
},
|
|
||||||
emphasis: {
|
|
||||||
scale: true,
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
formatter(val) {
|
|
||||||
return `${val.name}: ${val.value[2]}`
|
|
||||||
},
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
formatter: '{b}',
|
|
||||||
position: 'right',
|
|
||||||
show: true,
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
color: '#f4e925',
|
|
||||||
shadowBlur: 10,
|
|
||||||
shadowColor: '#333',
|
|
||||||
},
|
|
||||||
zlevel: 1,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { type ClassValue, clsx } from 'clsx'
|
||||||
|
import { twMerge } from 'tailwind-merge'
|
||||||
|
import type { Updater } from '@tanstack/vue-table'
|
||||||
|
import type { Ref } from 'vue'
|
||||||
|
|
||||||
|
export function cn(...inputs: ClassValue[]) {
|
||||||
|
return twMerge(clsx(inputs))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function valueUpdater<T extends Updater<any>>(updaterOrValue: T, ref: Ref) {
|
||||||
|
ref.value
|
||||||
|
= typeof updaterOrValue === 'function'
|
||||||
|
? updaterOrValue(ref.value)
|
||||||
|
: updaterOrValue
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
<script setup lang="ts" generic="T extends ZodObject<ZodRawShape>">
|
||||||
|
import { toTypedSchema } from '@vee-validate/zod'
|
||||||
|
import type { InvalidSubmissionHandler, SubmissionHandler } from 'vee-validate'
|
||||||
|
import { Form } from 'vee-validate'
|
||||||
|
import type { infer as ZodInfer, ZodObject, ZodRawShape } from 'zod'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
as?: string
|
||||||
|
schema: T
|
||||||
|
initialValues: ZodInfer<T>
|
||||||
|
onSubmit: SubmissionHandler< ZodInfer<T>> // (values: ZodInfer<T>) => Promise<void> | void
|
||||||
|
onInvalidSubmit?: InvalidSubmissionHandler
|
||||||
|
keepValues?: boolean
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const formSchema = toTypedSchema(props.schema)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Form v-bind="props" :validation-schema="formSchema">
|
||||||
|
<slot />
|
||||||
|
</Form>
|
||||||
|
</template>
|
|
@ -0,0 +1,32 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { Form, Field as FormField } from 'vee-validate'
|
||||||
|
import FormControl from './FormControl.vue'
|
||||||
|
import FormItem from './FormItem.vue'
|
||||||
|
import FormLabel from './FormLabel.vue'
|
||||||
|
import FormMessage from './FormMessage.vue'
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
name: string
|
||||||
|
label?: string
|
||||||
|
required?: boolean
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<FormField v-slot="{ componentField, value, handleChange }" :name="name">
|
||||||
|
<FormItem class="grid items-center grid-cols-4 gap-4">
|
||||||
|
<slot name="content" :component-field="componentField" :value="value" :handle-change="handleChange">
|
||||||
|
<FormLabel class="flex items-start justify-start font-medium gap-1">
|
||||||
|
{{ label }}
|
||||||
|
<span v-if="required" class="text-destructive"> *</span>
|
||||||
|
</FormLabel>
|
||||||
|
<div class="col-span-3">
|
||||||
|
<FormControl>
|
||||||
|
<slot :component-field="componentField" :value="value" :handle-change="handleChange" />
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</div>
|
||||||
|
</slot>
|
||||||
|
</FormItem>
|
||||||
|
</FormField>
|
||||||
|
</template>
|
|
@ -1,12 +1,8 @@
|
||||||
<script lang="ts">
|
|
||||||
import type { HTMLAttributes } from 'vue'
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { provide } from 'vue'
|
import { type HTMLAttributes, provide } from 'vue'
|
||||||
import { useId } from 'radix-vue'
|
import { useId } from 'radix-vue'
|
||||||
import { cn } from '../../../lib/utils'
|
import { cn } from '../../../lib/utils'
|
||||||
import { FORM_ITEM_INJECTION_KEY } from './useFormItemKey'
|
import { FORM_ITEM_INJECTION_KEY } from './injectionKeys'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
class?: HTMLAttributes['class']
|
class?: HTMLAttributes['class']
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { HTMLAttributes } from 'vue'
|
import type { HTMLAttributes } from 'vue'
|
||||||
import type { LabelProps } from 'radix-vue'
|
import type { LabelProps } from 'radix-vue'
|
||||||
import { useFormField } from './useFormField'
|
|
||||||
import { cn } from '../../../lib/utils'
|
import { cn } from '../../../lib/utils'
|
||||||
import { Label } from '../../../components/ui/label'
|
import { Label } from '../label'
|
||||||
|
import { useFormField } from './useFormField'
|
||||||
|
|
||||||
const props = defineProps<LabelProps & { class?: HTMLAttributes['class'] }>()
|
const props = defineProps<LabelProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
export { Form, Field as FormField } from 'vee-validate'
|
// export { Form, Field as FormField } from 'vee-validate'
|
||||||
export { default as FormItem } from './FormItem.vue'
|
export { default as FormItem } from './FormItem.vue'
|
||||||
export { default as FormLabel } from './FormLabel.vue'
|
export { default as FormLabel } from './FormLabel.vue'
|
||||||
export { default as FormControl } from './FormControl.vue'
|
export { default as FormControl } from './FormControl.vue'
|
||||||
export { default as FormMessage } from './FormMessage.vue'
|
export { default as FormMessage } from './FormMessage.vue'
|
||||||
export { default as FormDescription } from './FormDescription.vue'
|
export { default as FormDescription } from './FormDescription.vue'
|
||||||
|
export { default as FormFieldItem } from './FormFieldItem.vue'
|
||||||
|
export { default as Form } from './Form.vue'
|
||||||
|
export { FORM_ITEM_INJECTION_KEY } from './injectionKeys'
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
import type { InjectionKey } from 'vue'
|
||||||
|
|
||||||
|
export const FORM_ITEM_INJECTION_KEY
|
||||||
|
= Symbol() as InjectionKey<string>
|
|
@ -1,6 +1,6 @@
|
||||||
import { FieldContextKey, useFieldError, useIsFieldDirty, useIsFieldTouched, useIsFieldValid } from 'vee-validate'
|
import { FieldContextKey, useFieldError, useIsFieldDirty, useIsFieldTouched, useIsFieldValid } from 'vee-validate'
|
||||||
import { inject } from 'vue'
|
import { inject } from 'vue'
|
||||||
import { FORM_ITEM_INJECTION_KEY } from './useFormItemKey'
|
import { FORM_ITEM_INJECTION_KEY } from './injectionKeys'
|
||||||
|
|
||||||
export function useFormField() {
|
export function useFormField() {
|
||||||
const fieldContext = inject(FieldContextKey)
|
const fieldContext = inject(FieldContextKey)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
export {
|
// export {
|
||||||
PaginationRoot as Pagination,
|
// PaginationRoot as Pagination,
|
||||||
PaginationList,
|
// PaginationList,
|
||||||
PaginationListItem,
|
// PaginationListItem,
|
||||||
} from 'radix-vue'
|
// } from 'radix-vue'
|
||||||
export { default as PaginationEllipsis } from './PaginationEllipsis.vue'
|
export { default as PaginationEllipsis } from './PaginationEllipsis.vue'
|
||||||
export { default as PaginationFirst } from './PaginationFirst.vue'
|
export { default as PaginationFirst } from './PaginationFirst.vue'
|
||||||
export { default as PaginationLast } from './PaginationLast.vue'
|
export { default as PaginationLast } from './PaginationLast.vue'
|
||||||
|
|
|
@ -1,6 +1,15 @@
|
||||||
import { type ClassValue, clsx } from 'clsx'
|
import { type ClassValue, clsx } from 'clsx'
|
||||||
import { twMerge } from 'tailwind-merge'
|
import { twMerge } from 'tailwind-merge'
|
||||||
|
import type { Updater } from '@tanstack/vue-table'
|
||||||
|
import type { Ref } from 'vue'
|
||||||
|
|
||||||
export function cn(...inputs: ClassValue[]) {
|
export function cn(...inputs: ClassValue[]) {
|
||||||
return twMerge(clsx(inputs))
|
return twMerge(clsx(inputs))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function valueUpdater<T extends Updater<any>>(updaterOrValue: T, ref: Ref) {
|
||||||
|
ref.value
|
||||||
|
= typeof updaterOrValue === 'function'
|
||||||
|
? updaterOrValue(ref.value)
|
||||||
|
: updaterOrValue
|
||||||
|
}
|
||||||
|
|
|
@ -11,6 +11,10 @@ export default defineNuxtModule({
|
||||||
path: join(__dirname, 'components/ui'),
|
path: join(__dirname, 'components/ui'),
|
||||||
// prefix: 'Shadcn',
|
// prefix: 'Shadcn',
|
||||||
})
|
})
|
||||||
|
dirs.push({
|
||||||
|
path: join(__dirname, 'lib'),
|
||||||
|
// prefix: 'Shadcn',
|
||||||
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
"@tailwindcss/container-queries": "^0.1.1",
|
"@tailwindcss/container-queries": "^0.1.1",
|
||||||
"@tailwindcss/forms": "^0.5.7",
|
"@tailwindcss/forms": "^0.5.7",
|
||||||
"@tailwindcss/typography": "^0.5.13",
|
"@tailwindcss/typography": "^0.5.13",
|
||||||
|
"@tanstack/vue-table": "8.19.2",
|
||||||
"@unovis/ts": "^1.4.0",
|
"@unovis/ts": "^1.4.0",
|
||||||
"@unovis/vue": "^1.4.0",
|
"@unovis/vue": "^1.4.0",
|
||||||
"@vee-validate/zod": "^4.12.7",
|
"@vee-validate/zod": "^4.12.7",
|
||||||
|
|
17513
pnpm-lock.yaml
17513
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue